diff --git a/CHANGELOG.md b/CHANGELOG.md index 0333e2f84..b5f33a6ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ All notable changes to this project will be documented in this file. - zookeeper: Add 3.9.6 ([#1662]). - airflow, superset, druid, nifi: Add SBOMs for the frontend (npm) dependencies ([#1600]). - nifi: Backport [NIFI-15958](https://issues.apache.org/jira/browse/NIFI-15958) to log progress during the content archive scan and provenance re-index ([#1611] and [#1727]). +- nifi: Backport [NIFI-16294](https://issues.apache.org/jira/browse/NIFI-16294) to guard against a null controller status in `SiteToSiteStatusReportingTask` during startup, for `2.6.0` and `2.9.0` ([#1629]). - hbase: Add an SBOM for the web UI (npm) dependencies, which are unpacked from webjars and therefore not covered by the CycloneDX Maven plugin ([#1620]). - trino: Add SBOMs for the web UI, both for the two npm projects behind it and for the pre-built JavaScript vendored into the source tree ([#1620]). - hive: Restore the `get_table` and `get_table_objects_by_name` Thrift methods that HIVE-26537 removed in Hive 4.0.1, for `4.2.0` ([#1636]). @@ -140,6 +141,7 @@ All notable changes to this project will be documented in this file. [#1620]: https://github.com/stackabletech/docker-images/pull/1620 [#1621]: https://github.com/stackabletech/docker-images/pull/1621 [#1623]: https://github.com/stackabletech/docker-images/pull/1623 +[#1629]: https://github.com/stackabletech/docker-images/pull/1629 [#1630]: https://github.com/stackabletech/docker-images/pull/1630 [#1635]: https://github.com/stackabletech/docker-images/pull/1635 [#1636]: https://github.com/stackabletech/docker-images/pull/1636 diff --git a/nifi/stackable/patches/2.6.0/0012-NIFI-16294-Guard-against-null-controller-status-in-S.patch b/nifi/stackable/patches/2.6.0/0012-NIFI-16294-Guard-against-null-controller-status-in-S.patch new file mode 100644 index 000000000..5ab492c37 --- /dev/null +++ b/nifi/stackable/patches/2.6.0/0012-NIFI-16294-Guard-against-null-controller-status-in-S.patch @@ -0,0 +1,59 @@ +From 0de2247795728b7dc5b4b3390df48527f15d1caf Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?S=C3=B6nke=20Liebau?= +Date: Fri, 4 Sep 2026 11:04:21 +0000 +Subject: NIFI-16294 Guard against null controller status in + SiteToSiteStatusReportingTask + +Return early when getControllerStatus() is null (flow not yet +initialized) instead of passing it unguarded into serialization. + +Log at debug level, this is a transient error that'll correct itself when the cluster is stable again and should arguably not clutter the logs. + +This differs from the null guard in SiteToSiteMetricsReportingTask.java:227 which chose to log at the error level, but I'd argue that debug is more appropriate here. +--- + .../reporting/SiteToSiteStatusReportingTask.java | 6 +++++- + .../TestSiteToSiteStatusReportingTask.java | 14 ++++++++++++++ + 2 files changed, 19 insertions(+), 1 deletion(-) + +diff --git a/nifi-extension-bundles/nifi-site-to-site-reporting-bundle/nifi-site-to-site-reporting-task/src/main/java/org/apache/nifi/reporting/SiteToSiteStatusReportingTask.java b/nifi-extension-bundles/nifi-site-to-site-reporting-bundle/nifi-site-to-site-reporting-task/src/main/java/org/apache/nifi/reporting/SiteToSiteStatusReportingTask.java +index 732a1a96170a7a80c9390ea226fac36447c01650..58891ee0dbcd71f8b3e65f47950b67612f318f94 100644 +--- a/nifi-extension-bundles/nifi-site-to-site-reporting-bundle/nifi-site-to-site-reporting-task/src/main/java/org/apache/nifi/reporting/SiteToSiteStatusReportingTask.java ++++ b/nifi-extension-bundles/nifi-site-to-site-reporting-bundle/nifi-site-to-site-reporting-task/src/main/java/org/apache/nifi/reporting/SiteToSiteStatusReportingTask.java +@@ -125,7 +125,11 @@ public class SiteToSiteStatusReportingTask extends AbstractSiteToSiteReportingTa + processGroupIDToPath = new HashMap<>(); + + final ProcessGroupStatus procGroupStatus = context.getEventAccess().getControllerStatus(); +- final String rootGroupName = procGroupStatus == null ? null : procGroupStatus.getName(); ++ if (procGroupStatus == null) { ++ getLogger().debug("Controller status is not yet available; will report status on a subsequent trigger."); ++ return; ++ } ++ final String rootGroupName = procGroupStatus.getName(); + + final String nifiUrl = context.getProperty(SiteToSiteUtils.INSTANCE_URL).evaluateAttributeExpressions().getValue(); + URL url; +diff --git a/nifi-extension-bundles/nifi-site-to-site-reporting-bundle/nifi-site-to-site-reporting-task/src/test/java/org/apache/nifi/reporting/TestSiteToSiteStatusReportingTask.java b/nifi-extension-bundles/nifi-site-to-site-reporting-bundle/nifi-site-to-site-reporting-task/src/test/java/org/apache/nifi/reporting/TestSiteToSiteStatusReportingTask.java +index b3bc0c819e7ccbff3adfa4483a09d3e7b554d8e0..b049247959028426e57d513a1115c227139816f6 100644 +--- a/nifi-extension-bundles/nifi-site-to-site-reporting-bundle/nifi-site-to-site-reporting-task/src/test/java/org/apache/nifi/reporting/TestSiteToSiteStatusReportingTask.java ++++ b/nifi-extension-bundles/nifi-site-to-site-reporting-bundle/nifi-site-to-site-reporting-task/src/test/java/org/apache/nifi/reporting/TestSiteToSiteStatusReportingTask.java +@@ -123,6 +123,20 @@ public class TestSiteToSiteStatusReportingTask { + assertEquals("UP_TO_DATE", versionedFlowState.getString()); + } + ++ @Test ++ public void testNullControllerStatus() throws IOException, InitializationException { ++ final Map properties = new HashMap<>(); ++ properties.put(SiteToSiteUtils.BATCH_SIZE, "4"); ++ properties.put(SiteToSiteStatusReportingTask.COMPONENT_NAME_FILTER_REGEX, "Awesome.*"); ++ properties.put(SiteToSiteStatusReportingTask.COMPONENT_TYPE_FILTER_REGEX, ".*"); ++ ++ // The controller status is not yet available (e.g. during startup before the flow is initialized) ++ MockSiteToSiteStatusReportingTask task = initTask(properties, null); ++ assertDoesNotThrow(() -> task.onTrigger(context)); ++ ++ assertTrue(task.dataSent.isEmpty()); ++ } ++ + @Test + public void testComponentTypeFilter() throws IOException, InitializationException { + final ProcessGroupStatus pgStatus = generateProcessGroupStatus("root", "Awesome", 1, 0); diff --git a/nifi/stackable/patches/2.9.0/0013-NIFI-16294-Guard-against-null-controller-status-in-S.patch b/nifi/stackable/patches/2.9.0/0013-NIFI-16294-Guard-against-null-controller-status-in-S.patch new file mode 100644 index 000000000..7d5416d7b --- /dev/null +++ b/nifi/stackable/patches/2.9.0/0013-NIFI-16294-Guard-against-null-controller-status-in-S.patch @@ -0,0 +1,59 @@ +From 15642c5414b24e16395fb81412d317c166a3c3f8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?S=C3=B6nke=20Liebau?= +Date: Fri, 4 Sep 2026 11:04:21 +0000 +Subject: NIFI-16294 Guard against null controller status in + SiteToSiteStatusReportingTask + +Return early when getControllerStatus() is null (flow not yet +initialized) instead of passing it unguarded into serialization. + +Log at debug level, this is a transient error that'll correct itself when the cluster is stable again and should arguably not clutter the logs. + +This differs from the null guard in SiteToSiteMetricsReportingTask.java:227 which chose to log at the error level, but I'd argue that debug is more appropriate here. +--- + .../reporting/SiteToSiteStatusReportingTask.java | 6 +++++- + .../TestSiteToSiteStatusReportingTask.java | 14 ++++++++++++++ + 2 files changed, 19 insertions(+), 1 deletion(-) + +diff --git a/nifi-extension-bundles/nifi-site-to-site-reporting-bundle/nifi-site-to-site-reporting-task/src/main/java/org/apache/nifi/reporting/SiteToSiteStatusReportingTask.java b/nifi-extension-bundles/nifi-site-to-site-reporting-bundle/nifi-site-to-site-reporting-task/src/main/java/org/apache/nifi/reporting/SiteToSiteStatusReportingTask.java +index 1bc04951305e10abddabe325140e39ffb53b7a60..c9d4c4f42c84b0c9cb1d8efe8df358461ae73bf3 100644 +--- a/nifi-extension-bundles/nifi-site-to-site-reporting-bundle/nifi-site-to-site-reporting-task/src/main/java/org/apache/nifi/reporting/SiteToSiteStatusReportingTask.java ++++ b/nifi-extension-bundles/nifi-site-to-site-reporting-bundle/nifi-site-to-site-reporting-task/src/main/java/org/apache/nifi/reporting/SiteToSiteStatusReportingTask.java +@@ -124,7 +124,11 @@ public class SiteToSiteStatusReportingTask extends AbstractSiteToSiteReportingTa + processGroupIDToPath = new HashMap<>(); + + final ProcessGroupStatus procGroupStatus = context.getEventAccess().getControllerStatus(); +- final String rootGroupName = procGroupStatus == null ? null : procGroupStatus.getName(); ++ if (procGroupStatus == null) { ++ getLogger().debug("Controller status is not yet available; will report status on a subsequent trigger."); ++ return; ++ } ++ final String rootGroupName = procGroupStatus.getName(); + + final String nifiUrl = context.getProperty(SiteToSiteUtils.INSTANCE_URL).evaluateAttributeExpressions().getValue(); + URL url; +diff --git a/nifi-extension-bundles/nifi-site-to-site-reporting-bundle/nifi-site-to-site-reporting-task/src/test/java/org/apache/nifi/reporting/TestSiteToSiteStatusReportingTask.java b/nifi-extension-bundles/nifi-site-to-site-reporting-bundle/nifi-site-to-site-reporting-task/src/test/java/org/apache/nifi/reporting/TestSiteToSiteStatusReportingTask.java +index fdabe2aee7d9d388fa5ef6e467bde83949516e7a..dea32d110444526be7ee2c6ccff96e8f9d4108ef 100644 +--- a/nifi-extension-bundles/nifi-site-to-site-reporting-bundle/nifi-site-to-site-reporting-task/src/test/java/org/apache/nifi/reporting/TestSiteToSiteStatusReportingTask.java ++++ b/nifi-extension-bundles/nifi-site-to-site-reporting-bundle/nifi-site-to-site-reporting-task/src/test/java/org/apache/nifi/reporting/TestSiteToSiteStatusReportingTask.java +@@ -123,6 +123,20 @@ public class TestSiteToSiteStatusReportingTask { + assertEquals("UP_TO_DATE", versionedFlowState.getString()); + } + ++ @Test ++ public void testNullControllerStatus() throws IOException, InitializationException { ++ final Map properties = new HashMap<>(); ++ properties.put(SiteToSiteUtils.BATCH_SIZE, "4"); ++ properties.put(SiteToSiteStatusReportingTask.COMPONENT_NAME_FILTER_REGEX, "Awesome.*"); ++ properties.put(SiteToSiteStatusReportingTask.COMPONENT_TYPE_FILTER_REGEX, ".*"); ++ ++ // The controller status is not yet available (e.g. during startup before the flow is initialized) ++ MockSiteToSiteStatusReportingTask task = initTask(properties, null); ++ assertDoesNotThrow(() -> task.onTrigger(context)); ++ ++ assertTrue(task.dataSent.isEmpty()); ++ } ++ + @Test + public void testComponentTypeFilter() throws IOException, InitializationException { + final ProcessGroupStatus pgStatus = generateProcessGroupStatus("root", "Awesome", 1, 0);