Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions docs/history.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@
History
=======

1.8.1 (2026-10-24)
-------------------

| Bug fixes for stateless process groups in parameter provider fetch/apply and for ``verify_config`` port results

**Bug Fixes**

- **AffectedComponentEntity**: Added ``STATELESS_GROUP`` to the ``reference_type`` allowed values (`#419 <https://github.com/Chaffelson/nipyapi/issues/419>`_). NiFi returns it for components in stateless process groups, but the NiFi 2.12.0 OpenAPI spec omits it from the entity (`NIFI-16464 <https://issues.apache.org/jira/browse/NIFI-16464>`_), so fetching or applying a parameter provider on a flow with stateless groups raised ``ValueError`` during deserialization. A spec augmentation mirrors the ``AffectedComponentDTO`` enum into the entity until the client is regenerated from a NiFi release that includes the upstream fix.
- **verify_config()**: Port failures in ``port_results`` now use the same ``{"step", "explanation"}`` shape as controller and processor failures (`#418 <https://github.com/Chaffelson/nipyapi/issues/418>`_). Previously each port failure was a plain string. Callers that read the port strings directly should read ``explanation`` instead.

1.8.0 (2026-10-22)
-------------------

Expand Down
3 changes: 2 additions & 1 deletion nipyapi/ci/verify_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ def _verify_ports(process_group_id: str) -> List[Dict[str, Any]]:
}
errors = port.component.validation_errors
if errors:
results.append({**base_result, "success": False, "failures": errors})
failures = [{"step": "Port validation", "explanation": e} for e in errors]
results.append({**base_result, "success": False, "failures": failures})
else:
results.append({**base_result, "success": True, "failures": []})
return results
Expand Down
2 changes: 1 addition & 1 deletion nipyapi/nifi/models/affected_component_entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ def reference_type(self, reference_type):
:type: str
"""
if Configuration().client_side_validation:
allowed_values = ["PROCESSOR", "CONTROLLER_SERVICE", "INPUT_PORT", "OUTPUT_PORT", "REMOTE_INPUT_PORT", "REMOTE_OUTPUT_PORT", ]
allowed_values = ["PROCESSOR", "CONTROLLER_SERVICE", "INPUT_PORT", "OUTPUT_PORT", "REMOTE_INPUT_PORT", "REMOTE_OUTPUT_PORT", "STATELESS_GROUP", ]
if reference_type not in allowed_values:
raise ValueError(
"Invalid value for `reference_type` ({0}), must be one of {1}"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#!/usr/bin/env python3
"""
Augmentation to fix AffectedComponentEntity.referenceType enum.

Upstream NiFi inconsistency: AffectedComponentDTO.referenceType allows
"STATELESS_GROUP", but AffectedComponentEntity.referenceType omits it, even
though NiFi returns it in the referencingComponents of parameter context
update requests and parameter provider apply requests.

This augmentation updates the entity enum to match the DTO enum.

Fixed upstream in NIFI-16464 (apache/nifi#11811). Remove this augmentation when
generating from a NiFi release that includes that fix; it is a no-op there.
"""
import json
import sys


def fix_affected_component_entity_reference_type(spec):
"""Update AffectedComponentEntity.referenceType enum to match the DTO."""
schemas = spec.get("components", {}).get("schemas", {})
dto_props = schemas.get("AffectedComponentDTO", {}).get("properties", {})
complete_enum = dto_props.get("referenceType", {}).get("enum", [])

if not complete_enum:
# Fallback if the DTO enum is missing
complete_enum = [
"PROCESSOR",
"CONTROLLER_SERVICE",
"INPUT_PORT",
"OUTPUT_PORT",
"REMOTE_INPUT_PORT",
"REMOTE_OUTPUT_PORT",
"STATELESS_GROUP",
]

entity_props = schemas.get("AffectedComponentEntity", {}).get("properties", {})
ref_type = entity_props.get("referenceType", {})
if ref_type and "enum" in ref_type:
old_enum = ref_type["enum"]
ref_type["enum"] = old_enum + [v for v in complete_enum if v not in old_enum]
print(f" AffectedComponentEntity.referenceType enum: {old_enum} -> {ref_type['enum']}")

return spec


def main():
if len(sys.argv) != 3:
print("Usage: nifi_affected_component_reference_type.py <input.json> <output.json>")
sys.exit(1)

with open(sys.argv[1], "r") as f:
spec = json.load(f)

spec = fix_affected_component_entity_reference_type(spec)

with open(sys.argv[2], "w") as f:
json.dump(spec, f, indent=2)


if __name__ == "__main__":
main()
4 changes: 4 additions & 0 deletions tests/test_ci.py
Original file line number Diff line number Diff line change
Expand Up @@ -1998,6 +1998,10 @@ def test_verify_config_with_invalid_port(fix_pg, fix_port):
assert len(failed_ports) == 1
assert failed_ports[0]["id"] == f_port.id
assert len(failed_ports[0]["failures"]) > 0
# Same failure shape as controller and processor results
for failure in failed_ports[0]["failures"]:
assert set(failure) == {"step", "explanation"}
assert failure["explanation"]


def test_get_status_port_counts(fix_pg, fix_port):
Expand Down
7 changes: 7 additions & 0 deletions tests/test_generated_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,13 @@ def test_deserialize_parameter_provider_fetch_response(payload):
assert set(groups[0].parameter_sensitivities) >= {"API_KEY"}


def test_affected_component_accepts_stateless_group():
# NiFi returns STATELESS_GROUP for components in stateless process groups;
# the 2.12.0 entity enum omits it (NIFI-16464), restored by augmentation
entity = AffectedComponentEntity(reference_type="STATELESS_GROUP")
assert entity.reference_type == "STATELESS_GROUP"


def test_client_side_validation_can_be_disabled(monkeypatch):
monkeypatch.setattr(
nipyapi.config.nifi_config, "client_side_validation", False
Expand Down
Loading