This is an automated email from the ASF dual-hosted git repository.
mcgilman pushed a commit to branch NIFI-15258
in repository https://gitbox.apache.org/repos/asf/nifi.git
The following commit(s) were added to refs/heads/NIFI-15258 by this push:
new 9d448caa1f NIFI-15439: Ensure that Process Groups are accessible from
the approp… (#10742)
9d448caa1f is described below
commit 9d448caa1fffe7157005c46c27f8835dcca0fa10
Author: Mark Payne <[email protected]>
AuthorDate: Mon Jan 12 14:30:06 2026 -0500
NIFI-15439: Ensure that Process Groups are accessible from the approp…
(#10742)
* NIFI-15439: Ensure that Process Groups are accessible from the
appropriate endpoint but not accessible elsewhere
* NIFI-15439: FlowAnalyzingRegistryClient should use an explicit Connector
ID of null when retrieving Process Group from FlowManager
---
.../nifi/controller/flow/AbstractFlowManager.java | 16 +++++
.../apache/nifi/groups/StandardProcessGroup.java | 2 +-
.../flow/FlowAnalyzingRegistryClientNode.java | 5 +-
.../flow/FlowAnalyzingRegistryClientNodeTest.java | 2 +-
.../apache/nifi/controller/flow/FlowManager.java | 9 +++
.../org/apache/nifi/controller/FlowController.java | 10 +--
.../nifi/controller/flow/StandardFlowManager.java | 7 +-
.../org/apache/nifi/web/dao/impl/ComponentDAO.java | 4 +-
.../nifi/web/dao/impl/StandardProcessGroupDAO.java | 7 +-
.../org/apache/nifi/audit/TestLabelAuditor.java | 4 +-
.../apache/nifi/audit/TestProcessGroupAuditor.java | 6 +-
.../apache/nifi/audit/TestProcessorAuditor.java | 2 +-
.../web/dao/impl/StandardProcessorDAOTest.java | 4 +-
.../web/dao/impl/TestStandardProcessGroupDAO.java | 25 ++------
.../tests/system/NestedProcessGroupConnector.java | 75 ++++++++++++++++++++++
.../org.apache.nifi.components.connector.Connector | 1 +
.../tests/system/connectors/ConnectorCrudIT.java | 49 ++++++++++++++
.../nifi/toolkit/client/ConnectorClient.java | 6 +-
.../toolkit/client/impl/JerseyConnectorClient.java | 18 +++---
19 files changed, 194 insertions(+), 58 deletions(-)
diff --git
a/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/flow/AbstractFlowManager.java
b/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/flow/AbstractFlowManager.java
index a694c5be35..076f2efa99 100644
---
a/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/flow/AbstractFlowManager.java
+++
b/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/flow/AbstractFlowManager.java
@@ -63,6 +63,7 @@ import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
@@ -122,6 +123,21 @@ public abstract class AbstractFlowManager implements
FlowManager {
return allProcessGroups.get(requireNonNull(id));
}
+ @Override
+ public ProcessGroup getGroup(final String groupId, final String
connectorId) {
+ final ProcessGroup group =
allProcessGroups.get(requireNonNull(groupId));
+ if (group == null) {
+ return null;
+ }
+
+ // If we found the group, return it only if it has the correct
connector ID
+ if (Objects.equals(group.getConnectorIdentifier().orElse(null),
connectorId)) {
+ return group;
+ }
+
+ return null;
+ }
+
@Override
public void onProcessGroupAdded(final ProcessGroup group) {
allProcessGroups.put(group.getIdentifier(), group);
diff --git
a/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java
b/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java
index 9918eda3a1..3987ea19f9 100644
---
a/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java
+++
b/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/groups/StandardProcessGroup.java
@@ -2112,7 +2112,7 @@ public final class StandardProcessGroup implements
ProcessGroup {
return this;
}
- final ProcessGroup group = flowManager.getGroup(id);
+ final ProcessGroup group = flowManager.getGroup(id,
getConnectorIdentifier().orElse(null));
if (group == null) {
return null;
}
diff --git
a/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/registry/flow/FlowAnalyzingRegistryClientNode.java
b/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/registry/flow/FlowAnalyzingRegistryClientNode.java
index 19e4563c8a..faeb336efe 100644
---
a/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/registry/flow/FlowAnalyzingRegistryClientNode.java
+++
b/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/registry/flow/FlowAnalyzingRegistryClientNode.java
@@ -29,7 +29,6 @@ import org.apache.nifi.components.validation.ValidationStatus;
import org.apache.nifi.controller.LoggableComponent;
import org.apache.nifi.controller.PropertyConfiguration;
import org.apache.nifi.controller.TerminationAwareLogger;
-import org.apache.nifi.logging.ComponentLog;
import org.apache.nifi.controller.flow.FlowManager;
import org.apache.nifi.controller.flowanalysis.FlowAnalyzer;
import org.apache.nifi.controller.service.ControllerServiceProvider;
@@ -39,6 +38,7 @@ import org.apache.nifi.flow.VersionedParameterContext;
import org.apache.nifi.flow.VersionedProcessGroup;
import org.apache.nifi.flowanalysis.EnforcementPolicy;
import org.apache.nifi.groups.ProcessGroup;
+import org.apache.nifi.logging.ComponentLog;
import org.apache.nifi.nar.ExtensionManager;
import org.apache.nifi.parameter.ParameterContext;
import org.apache.nifi.parameter.ParameterLookup;
@@ -111,7 +111,8 @@ public final class FlowAnalyzingRegistryClientNode
implements FlowRegistryClient
}
private boolean analyzeProcessGroupToRegister(final VersionedProcessGroup
snapshot) {
- final InstantiatedVersionedProcessGroup nonVersionedProcessGroup =
flowMapper.mapNonVersionedProcessGroup(flowManager.getGroup(snapshot.getInstanceIdentifier()),
serviceProvider);
+ final ProcessGroup group =
flowManager.getGroup(snapshot.getInstanceIdentifier(), null);
+ final InstantiatedVersionedProcessGroup nonVersionedProcessGroup =
flowMapper.mapNonVersionedProcessGroup(group, serviceProvider);
flowAnalyzer.analyzeProcessGroup(nonVersionedProcessGroup);
final List<RuleViolation> ruleViolations =
ruleViolationsManager.getRuleViolationsForGroup(snapshot.getInstanceIdentifier()).stream()
diff --git
a/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/test/java/org/apache/nifi/registry/flow/FlowAnalyzingRegistryClientNodeTest.java
b/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/test/java/org/apache/nifi/registry/flow/FlowAnalyzingRegistryClientNodeTest.java
index cdf73f0d11..066bd20ef6 100644
---
a/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/test/java/org/apache/nifi/registry/flow/FlowAnalyzingRegistryClientNodeTest.java
+++
b/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/test/java/org/apache/nifi/registry/flow/FlowAnalyzingRegistryClientNodeTest.java
@@ -91,7 +91,7 @@ class FlowAnalyzingRegistryClientNodeTest {
@BeforeEach
public void setUp() {
Mockito.when(versionedProcessGroup.getInstanceIdentifier()).thenReturn(INSTANCE_IDENTIFIER);
-
Mockito.when(flowManager.getGroup(Mockito.anyString())).thenReturn(processGroup);
+ Mockito.when(flowManager.getGroup(Mockito.anyString(),
Mockito.eq(null))).thenReturn(processGroup);
Mockito.when(flowMapper.mapNonVersionedProcessGroup(Mockito.same(processGroup),
Mockito.same(serviceProvider))).thenReturn(nonVersionedProcessGroup);
Mockito.when(ruleViolation1.getEnforcementPolicy()).thenReturn(EnforcementPolicy.ENFORCE);
Mockito.when(ruleViolation2.getEnforcementPolicy()).thenReturn(EnforcementPolicy.ENFORCE);
diff --git
a/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/flow/FlowManager.java
b/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/flow/FlowManager.java
index d756e8531e..c1a363a5ab 100644
---
a/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/flow/FlowManager.java
+++
b/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/flow/FlowManager.java
@@ -165,6 +165,15 @@ public interface FlowManager extends
ParameterProviderLookup {
*/
ProcessGroup getGroup(String id);
+ /**
+ * Returns the ProcessGroup with the given ID that is managed by the
Connector with the given ID,
+ * or null if no such ProcessGroup exists.
+ * @param groupId id of the group
+ * @param connectorId id of the connector
+ * @return the ProcessGroup with the given ID or null if none can be found
+ */
+ ProcessGroup getGroup(String groupId, String connectorId);
+
void onProcessGroupAdded(ProcessGroup group);
void onProcessGroupRemoved(ProcessGroup group);
diff --git
a/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/FlowController.java
b/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/FlowController.java
index 8f845b853d..3529e5199d 100644
---
a/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/FlowController.java
+++
b/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/FlowController.java
@@ -52,14 +52,14 @@ import
org.apache.nifi.components.ClassLoaderAwarePythonBridge;
import org.apache.nifi.components.connector.ConnectorRepository;
import
org.apache.nifi.components.connector.ConnectorRepositoryInitializationContext;
import org.apache.nifi.components.connector.ConnectorRequestReplicator;
+import org.apache.nifi.components.connector.ConnectorValidationTrigger;
import
org.apache.nifi.components.connector.StandardConnectorRepoInitializationContext;
import org.apache.nifi.components.connector.StandardConnectorRepository;
+import org.apache.nifi.components.connector.StandardConnectorValidationTrigger;
import
org.apache.nifi.components.connector.secrets.ParameterProviderSecretsManager;
import org.apache.nifi.components.connector.secrets.SecretsManager;
import
org.apache.nifi.components.connector.secrets.SecretsManagerInitializationContext;
import
org.apache.nifi.components.connector.secrets.StandardSecretsManagerInitializationContext;
-import org.apache.nifi.components.connector.ConnectorValidationTrigger;
-import org.apache.nifi.components.connector.StandardConnectorValidationTrigger;
import org.apache.nifi.components.monitor.LongRunningTaskMonitor;
import org.apache.nifi.components.state.StateManagerProvider;
import org.apache.nifi.components.state.StateProvider;
@@ -229,8 +229,6 @@ import org.apache.nifi.web.revision.RevisionManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.management.NotificationEmitter;
-import javax.net.ssl.SSLContext;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
@@ -263,6 +261,8 @@ import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Supplier;
import java.util.stream.Collectors;
+import javax.management.NotificationEmitter;
+import javax.net.ssl.SSLContext;
import static java.util.Objects.requireNonNull;
@@ -2180,7 +2180,7 @@ public class FlowController implements
ReportingTaskProvider, FlowAnalysisRulePr
* @return the process group or null if not group is found
*/
private ProcessGroup lookupGroup(final String id) {
- final ProcessGroup group = flowManager.getGroup(id);
+ final ProcessGroup group = flowManager.getGroup(id, null);
if (group == null) {
throw new IllegalStateException("No Group with ID " + id + "
exists");
}
diff --git
a/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/flow/StandardFlowManager.java
b/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/flow/StandardFlowManager.java
index 96bbd8f4f7..d3874eb5cb 100644
---
a/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/flow/StandardFlowManager.java
+++
b/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/flow/StandardFlowManager.java
@@ -306,10 +306,7 @@ public class StandardFlowManager extends
AbstractFlowManager implements FlowMana
flowController.getReloadComponent(), flowController,
nifiProperties, statelessGroupNodeFactory,
flowController.getAssetManager(), connectorId);
- // We don't want to register the group if it's being created as part
of a Connector
- if (connectorId == null) {
- onProcessGroupAdded(group);
- }
+ onProcessGroupAdded(group);
return group;
}
@@ -750,7 +747,7 @@ public class StandardFlowManager extends
AbstractFlowManager implements FlowMana
final ExtensionManager extensionManager =
flowController.getExtensionManager();
final String managedGroupId = UUID.nameUUIDFromBytes((id +
"-root").getBytes(StandardCharsets.UTF_8)).toString();
- final ProcessGroup managedRootGroup =
createProcessGroup(managedGroupId);
+ final ProcessGroup managedRootGroup =
createProcessGroup(managedGroupId, id);
final String paramContextId = UUID.nameUUIDFromBytes((id +
"-parameter-context").getBytes(StandardCharsets.UTF_8)).toString();
final String paramContextName = "Connector " + id + " Parameter
Context";
diff --git
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/ComponentDAO.java
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/ComponentDAO.java
index 078644a24a..90760cbcd3 100644
---
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/ComponentDAO.java
+++
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/ComponentDAO.java
@@ -63,8 +63,8 @@ public abstract class ComponentDAO {
* @param groupId id
* @return group
*/
- protected ProcessGroup locateProcessGroup(FlowController flowController,
String groupId) {
- ProcessGroup group = flowController.getFlowManager().getGroup(groupId);
+ protected ProcessGroup locateProcessGroup(final FlowController
flowController, final String groupId) {
+ ProcessGroup group = flowController.getFlowManager().getGroup(groupId,
null);
if (group == null) {
throw new ResourceNotFoundException(String.format("Unable to
locate group with id '%s'.", groupId));
diff --git
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardProcessGroupDAO.java
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardProcessGroupDAO.java
index 9df568e942..aa7c5bf736 100644
---
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardProcessGroupDAO.java
+++
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardProcessGroupDAO.java
@@ -16,6 +16,7 @@
*/
package org.apache.nifi.web.dao.impl;
+import jakarta.ws.rs.WebApplicationException;
import org.apache.nifi.authorization.user.NiFiUser;
import org.apache.nifi.authorization.user.NiFiUserUtils;
import org.apache.nifi.connectable.Connectable;
@@ -53,8 +54,6 @@ import org.apache.nifi.web.api.entity.ProcessGroupRecursivity;
import org.apache.nifi.web.dao.ProcessGroupDAO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-
-import jakarta.ws.rs.WebApplicationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
@@ -121,7 +120,7 @@ public class StandardProcessGroupDAO extends ComponentDAO
implements ProcessGrou
@Override
public boolean hasProcessGroup(String groupId) {
- return flowController.getFlowManager().getGroup(groupId) != null;
+ return flowController.getFlowManager().getGroup(groupId, null) != null;
}
@Override
@@ -412,7 +411,7 @@ public class StandardProcessGroupDAO extends ComponentDAO
implements ProcessGrou
.map(flowManager::getControllerServiceNode)
.collect(Collectors.toList());
- final ProcessGroup group = flowManager.getGroup(groupId);
+ final ProcessGroup group = flowManager.getGroup(groupId, null);
if (group == null) {
throw new IllegalArgumentException("Cannot activate Controller
Services with IDs " + serviceIds + " because the associated Process Group (id="
+ groupId + ") could not be found");
}
diff --git
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/audit/TestLabelAuditor.java
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/audit/TestLabelAuditor.java
index 024a5640b5..48605cd64f 100644
---
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/audit/TestLabelAuditor.java
+++
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/audit/TestLabelAuditor.java
@@ -24,12 +24,12 @@ import
org.apache.nifi.action.details.FlowChangeConfigureDetails;
import org.apache.nifi.admin.service.AuditService;
import org.apache.nifi.controller.FlowController;
import org.apache.nifi.controller.flow.FlowManager;
+import org.apache.nifi.controller.label.Label;
import org.apache.nifi.controller.label.StandardLabel;
import org.apache.nifi.groups.ProcessGroup;
import org.apache.nifi.web.api.dto.LabelDTO;
import org.apache.nifi.web.dao.ProcessGroupDAO;
import org.apache.nifi.web.dao.impl.StandardLabelDAO;
-import org.apache.nifi.controller.label.Label;
import org.apache.nifi.web.dao.impl.StandardProcessGroupDAO;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -119,7 +119,7 @@ public class TestLabelAuditor {
@Test
void testCreateLabelAdvice() {
final LabelDTO labelDto = getLabelDto();
- when(flowManager.getGroup(eq(GROUP_ID))).thenReturn(processGroup);
+ when(flowManager.getGroup(eq(GROUP_ID),
eq(null))).thenReturn(processGroup);
when(flowManager.createLabel(eq(LABEL_ID), eq(LABEL))).thenReturn(new
StandardLabel(LABEL_ID, LABEL));
final Label label = labelDao.createLabel(GROUP_ID, labelDto);
diff --git
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/audit/TestProcessGroupAuditor.java
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/audit/TestProcessGroupAuditor.java
index 0e8d78b1a3..689be7c09a 100644
---
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/audit/TestProcessGroupAuditor.java
+++
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/audit/TestProcessGroupAuditor.java
@@ -122,7 +122,7 @@ public class TestProcessGroupAuditor {
when(processor1.getConnectableType()).thenReturn(ConnectableType.PROCESSOR);
when(processor2.getConnectableType()).thenReturn(ConnectableType.PROCESSOR);
- when(flowManager.getGroup(eq(PG_1))).thenReturn(processGroup);
+ when(flowManager.getGroup(eq(PG_1),
eq(null))).thenReturn(processGroup);
when(flowManager.findConnectable(eq(PROC_1))).thenReturn(processor1);
when(flowManager.findConnectable(eq(PROC_2))).thenReturn(processor2);
when(flowController.getFlowManager()).thenReturn(flowManager);
@@ -169,7 +169,7 @@ public class TestProcessGroupAuditor {
when(processGroup.findInputPort(OUTPUT_PORT)).thenReturn(null);
when(processGroup.findOutputPort(OUTPUT_PORT)).thenReturn(outputPort);
- when(flowManager.getGroup(eq(PG_1))).thenReturn(processGroup);
+ when(flowManager.getGroup(eq(PG_1),
eq(null))).thenReturn(processGroup);
when(flowManager.findConnectable(eq(PROC_1))).thenReturn(processor1);
when(flowManager.findConnectable(eq(PROC_2))).thenReturn(processor2);
when(flowManager.findConnectable(eq(INPUT_PORT))).thenReturn(inputPort);
@@ -237,7 +237,7 @@ public class TestProcessGroupAuditor {
when(cs.getName()).thenReturn(CS_1);
when(processGroup.findControllerService(eq(CS_1), eq(true),
eq(true))).thenReturn(cs);
- when(flowManager.getGroup(eq(PG_1))).thenReturn(processGroup);
+ when(flowManager.getGroup(eq(PG_1),
eq(null))).thenReturn(processGroup);
when(flowManager.getControllerServiceNode(eq(CS_1))).thenReturn(cs);
when(flowController.getFlowManager()).thenReturn(flowManager);
when(flowController.getControllerServiceProvider()).thenReturn(csProvider);
diff --git
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/audit/TestProcessorAuditor.java
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/audit/TestProcessorAuditor.java
index ce253a5c6c..5ecded1074 100644
---
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/audit/TestProcessorAuditor.java
+++
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/audit/TestProcessorAuditor.java
@@ -148,7 +148,7 @@ class TestProcessorAuditor {
when(flowController.getControllerServiceProvider()).thenReturn(mock(ControllerServiceProvider.class));
when(flowController.getStateManagerProvider()).thenReturn(mockStateManagerProvider);
- when(flowManager.getGroup(GROUP_ID)).thenReturn(processGroup);
+ when(flowManager.getGroup(GROUP_ID, null)).thenReturn(processGroup);
when(flowManager.createProcessor(anyString(), anyString(),
any())).thenReturn(mockProcessorNode);
final Bundle bundle = getBundle();
diff --git
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/dao/impl/StandardProcessorDAOTest.java
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/dao/impl/StandardProcessorDAOTest.java
index 274d6d6ae9..1ae61d3dce 100644
---
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/dao/impl/StandardProcessorDAOTest.java
+++
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/dao/impl/StandardProcessorDAOTest.java
@@ -24,13 +24,13 @@ import
org.apache.nifi.components.state.StateManagerProvider;
import org.apache.nifi.controller.FlowController;
import org.apache.nifi.controller.ProcessorNode;
import org.apache.nifi.controller.ScheduledState;
+import org.apache.nifi.controller.flow.FlowManager;
import org.apache.nifi.groups.ProcessGroup;
import org.apache.nifi.nar.ExtensionManager;
import org.apache.nifi.processor.Processor;
import org.apache.nifi.web.ResourceNotFoundException;
import org.apache.nifi.web.api.dto.ProcessorDTO;
import org.apache.nifi.web.dao.ComponentStateDAO;
-import org.apache.nifi.controller.flow.FlowManager;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
@@ -210,7 +210,7 @@ class StandardProcessorDAOTest {
final Bundle bundle = new Bundle(bundleDetails,
getClass().getClassLoader());
final List<Bundle> bundles = List.of(bundle);
- when(flowManager.getGroup(eq(groupId))).thenReturn(processGroup);
+ when(flowManager.getGroup(eq(groupId),
eq(null))).thenReturn(processGroup);
when(flowController.getExtensionManager()).thenReturn(extensionManager);
when(flowManager.createProcessor(eq(processorType), eq(id),
eq(bundleCoordinate))).thenReturn(processorNode);
when(extensionManager.getBundles(eq(processorType))).thenReturn(bundles);
diff --git
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/dao/impl/TestStandardProcessGroupDAO.java
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/dao/impl/TestStandardProcessGroupDAO.java
index 6bf86e3411..5b92b12388 100644
---
a/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/dao/impl/TestStandardProcessGroupDAO.java
+++
b/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/dao/impl/TestStandardProcessGroupDAO.java
@@ -17,11 +17,6 @@
package org.apache.nifi.web.dao.impl;
-import static org.mockito.Answers.RETURNS_DEEP_STUBS;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
import org.apache.nifi.connectable.Position;
import org.apache.nifi.controller.FlowController;
import org.apache.nifi.groups.ProcessGroup;
@@ -35,6 +30,11 @@ import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
+import static org.mockito.Answers.RETURNS_DEEP_STUBS;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
@ExtendWith(MockitoExtension.class)
public class TestStandardProcessGroupDAO {
private static final String PARENT_PROCESS_GROUP_ID = "parentId";
@@ -59,21 +59,12 @@ public class TestStandardProcessGroupDAO {
testSubject = new StandardProcessGroupDAO();
testSubject.setFlowController(flowController);
- when(flowController
- .getFlowManager()
- .getGroup(PARENT_PROCESS_GROUP_ID)
- ).thenReturn(parentProcessGroup);
-
- when(flowController
- .getFlowManager()
- .getParameterContextManager()
- .getParameterContext(PARAMETER_CONTEXT_ID)
- ).thenReturn(parameterContext);
+ when(flowController.getFlowManager().getGroup(PARENT_PROCESS_GROUP_ID,
null)).thenReturn(parentProcessGroup);
+
when(flowController.getFlowManager().getParameterContextManager().getParameterContext(PARAMETER_CONTEXT_ID)).thenReturn(parameterContext);
}
@Test
public void testCreateProcessGroup() {
- //GIVEN
ParameterContextReferenceEntity parameterContextReferenceEntity = new
ParameterContextReferenceEntity();
parameterContextReferenceEntity.setId(PARAMETER_CONTEXT_ID);
@@ -84,10 +75,8 @@ public class TestStandardProcessGroupDAO {
processGroupDTO.setPosition(new PositionDTO(10.0, 20.0));
processGroupDTO.setParameterContext(parameterContextReferenceEntity);
- //WHEN
ProcessGroup createdProcessGroup =
testSubject.createProcessGroup(PARENT_PROCESS_GROUP_ID, processGroupDTO);
- //THEN
verify(createdProcessGroup).setParent(parentProcessGroup);
verify(createdProcessGroup).setParameterContext(parameterContext);
verify(createdProcessGroup).setName(PROCESS_GROUP_NAME);
diff --git
a/nifi-system-tests/nifi-system-test-extensions-bundle/nifi-system-test-extensions/src/main/java/org/apache/nifi/connectors/tests/system/NestedProcessGroupConnector.java
b/nifi-system-tests/nifi-system-test-extensions-bundle/nifi-system-test-extensions/src/main/java/org/apache/nifi/connectors/tests/system/NestedProcessGroupConnector.java
new file mode 100644
index 0000000000..e3903a38f1
--- /dev/null
+++
b/nifi-system-tests/nifi-system-test-extensions-bundle/nifi-system-test-extensions/src/main/java/org/apache/nifi/connectors/tests/system/NestedProcessGroupConnector.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.nifi.connectors.tests.system;
+
+import org.apache.nifi.components.ConfigVerificationResult;
+import org.apache.nifi.components.connector.AbstractConnector;
+import org.apache.nifi.components.connector.ConfigurationStep;
+import org.apache.nifi.components.connector.components.FlowContext;
+import org.apache.nifi.flow.VersionedExternalFlow;
+import org.apache.nifi.flow.VersionedProcessGroup;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Test Connector that creates a flow with a nested (child) process group.
+ * Used to verify that child process groups within a connector's managed flow
+ * can be properly accessed via the connector API.
+ */
+public class NestedProcessGroupConnector extends AbstractConnector {
+
+ public static final String CHILD_PROCESS_GROUP_ID =
"child-process-group-id";
+
+ private final List<ConfigurationStep> configurationSteps = List.of();
+
+ @Override
+ protected void onStepConfigured(final String stepName, final FlowContext
workingContext) {
+ }
+
+ @Override
+ public VersionedExternalFlow getInitialFlow() {
+ final VersionedProcessGroup childGroup = new VersionedProcessGroup();
+ childGroup.setIdentifier(CHILD_PROCESS_GROUP_ID);
+ childGroup.setName("Child Process Group");
+
+ final VersionedProcessGroup rootGroup = new VersionedProcessGroup();
+ rootGroup.setName("Nested Flow");
+ rootGroup.setProcessGroups(Set.of(childGroup));
+
+ final VersionedExternalFlow flow = new VersionedExternalFlow();
+ flow.setFlowContents(rootGroup);
+ return flow;
+ }
+
+ @Override
+ public List<ConfigVerificationResult> verifyConfigurationStep(final String
stepName, final Map<String, String> propertyValueOverrides, final FlowContext
flowContext) {
+ return List.of();
+ }
+
+ @Override
+ public List<ConfigurationStep> getConfigurationSteps() {
+ return configurationSteps;
+ }
+
+ @Override
+ public void applyUpdate(final FlowContext workingFlowContext, final
FlowContext activeFlowContext) {
+ }
+}
+
diff --git
a/nifi-system-tests/nifi-system-test-extensions-bundle/nifi-system-test-extensions/src/main/resources/META-INF/services/org.apache.nifi.components.connector.Connector
b/nifi-system-tests/nifi-system-test-extensions-bundle/nifi-system-test-extensions/src/main/resources/META-INF/services/org.apache.nifi.components.connector.Connector
index c8e0d0ed64..a54f75d132 100644
---
a/nifi-system-tests/nifi-system-test-extensions-bundle/nifi-system-test-extensions/src/main/resources/META-INF/services/org.apache.nifi.components.connector.Connector
+++
b/nifi-system-tests/nifi-system-test-extensions-bundle/nifi-system-test-extensions/src/main/resources/META-INF/services/org.apache.nifi.components.connector.Connector
@@ -16,3 +16,4 @@
org.apache.nifi.connectors.tests.system.NopConnector
org.apache.nifi.connectors.tests.system.AssetConnector
org.apache.nifi.connectors.tests.system.DataQueuingConnector
+org.apache.nifi.connectors.tests.system.NestedProcessGroupConnector
diff --git
a/nifi-system-tests/nifi-system-test-suite/src/test/java/org/apache/nifi/tests/system/connectors/ConnectorCrudIT.java
b/nifi-system-tests/nifi-system-test-suite/src/test/java/org/apache/nifi/tests/system/connectors/ConnectorCrudIT.java
index fb616c6d4b..c1098c4d19 100644
---
a/nifi-system-tests/nifi-system-test-suite/src/test/java/org/apache/nifi/tests/system/connectors/ConnectorCrudIT.java
+++
b/nifi-system-tests/nifi-system-test-suite/src/test/java/org/apache/nifi/tests/system/connectors/ConnectorCrudIT.java
@@ -17,6 +17,7 @@
package org.apache.nifi.tests.system.connectors;
+import jakarta.ws.rs.NotFoundException;
import org.apache.nifi.components.ConfigVerificationResult.Outcome;
import org.apache.nifi.components.connector.ConnectorState;
import org.apache.nifi.tests.system.NiFiSystemIT;
@@ -24,18 +25,24 @@ import org.apache.nifi.toolkit.client.NiFiClientException;
import org.apache.nifi.web.api.dto.ConfigVerificationResultDTO;
import org.apache.nifi.web.api.dto.ConnectorConfigurationDTO;
import org.apache.nifi.web.api.dto.ConnectorValueReferenceDTO;
+import org.apache.nifi.web.api.dto.flow.ProcessGroupFlowDTO;
import org.apache.nifi.web.api.entity.ConnectorEntity;
import org.apache.nifi.web.api.entity.ParameterContextsEntity;
import org.apache.nifi.web.api.entity.ParameterProviderEntity;
+import org.apache.nifi.web.api.entity.ProcessGroupEntity;
+import org.apache.nifi.web.api.entity.ProcessGroupFlowEntity;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
public class ConnectorCrudIT extends NiFiSystemIT {
@@ -162,4 +169,46 @@ public class ConnectorCrudIT extends NiFiSystemIT {
// Delete
getNifiClient().getConnectorClient().deleteConnector(connector);
}
+
+ @Test
+ public void testProcessGroupAccessibility() throws NiFiClientException,
IOException {
+ final ConnectorEntity connector =
getClientUtil().createConnector("NestedProcessGroupConnector");
+ assertNotNull(connector);
+
+ final ConnectorEntity updatedConnector =
getNifiClient().getConnectorClient().getConnector(connector.getId());
+ final String managedProcessGroupId =
updatedConnector.getComponent().getManagedProcessGroupId();
+ assertNotNull(managedProcessGroupId);
+
+ final ProcessGroupFlowEntity connectorFlowEntity =
getNifiClient().getConnectorClient().getFlow(connector.getId(),
managedProcessGroupId);
+ assertNotNull(connectorFlowEntity);
+
+ final ProcessGroupFlowDTO connectorFlow =
connectorFlowEntity.getProcessGroupFlow();
+ assertNotNull(connectorFlow);
+ assertEquals(managedProcessGroupId, connectorFlow.getId());
+
+ try {
+
getNifiClient().getFlowClient().getProcessGroup(managedProcessGroupId);
+ fail("Was able to retrieve connector-managed process group via
FlowClient");
+ } catch (final NiFiClientException e) {
+ assertInstanceOf(NotFoundException.class, e.getCause());
+ }
+
+ final Set<ProcessGroupEntity> childGroups =
connectorFlow.getFlow().getProcessGroups();
+ assertEquals(1, childGroups.size(), "Expected exactly one child
process group");
+
+ final ProcessGroupEntity childGroup = childGroups.iterator().next();
+ final String childGroupId = childGroup.getId();
+ assertNotNull(childGroupId);
+
+ final ProcessGroupFlowEntity childFlowEntity =
getNifiClient().getConnectorClient().getFlow(connector.getId(), childGroupId);
+ assertNotNull(childFlowEntity);
+ assertEquals(childGroupId,
childFlowEntity.getProcessGroupFlow().getId());
+
+ try {
+ getNifiClient().getFlowClient().getProcessGroup(childGroupId);
+ fail("Was able to retrieve child process group of
connector-managed flow via FlowClient");
+ } catch (final NiFiClientException e) {
+ assertInstanceOf(NotFoundException.class, e.getCause());
+ }
+ }
}
diff --git
a/nifi-toolkit/nifi-toolkit-client/src/main/java/org/apache/nifi/toolkit/client/ConnectorClient.java
b/nifi-toolkit/nifi-toolkit-client/src/main/java/org/apache/nifi/toolkit/client/ConnectorClient.java
index 923604ba5f..1e95222225 100644
---
a/nifi-toolkit/nifi-toolkit-client/src/main/java/org/apache/nifi/toolkit/client/ConnectorClient.java
+++
b/nifi-toolkit/nifi-toolkit-client/src/main/java/org/apache/nifi/toolkit/client/ConnectorClient.java
@@ -234,15 +234,15 @@ public interface ConnectorClient {
ProcessGroupFlowEntity getFlow(String connectorId) throws
NiFiClientException, IOException;
/**
- * Gets the flow for the process group managed by a connector.
+ * Gets the flow for a specific process group within a connector's managed
flow.
*
* @param connectorId the connector ID
- * @param uiOnly whether to return only UI-specific fields
+ * @param processGroupId the process group ID within the connector's
managed flow
* @return the process group flow entity
* @throws NiFiClientException if an error occurs during the request
* @throws IOException if an I/O error occurs
*/
- ProcessGroupFlowEntity getFlow(String connectorId, boolean uiOnly) throws
NiFiClientException, IOException;
+ ProcessGroupFlowEntity getFlow(String connectorId, String processGroupId)
throws NiFiClientException, IOException;
/**
* Gets the status for the process group managed by a connector.
diff --git
a/nifi-toolkit/nifi-toolkit-client/src/main/java/org/apache/nifi/toolkit/client/impl/JerseyConnectorClient.java
b/nifi-toolkit/nifi-toolkit-client/src/main/java/org/apache/nifi/toolkit/client/impl/JerseyConnectorClient.java
index 8df19b09d5..b5ad5878d5 100644
---
a/nifi-toolkit/nifi-toolkit-client/src/main/java/org/apache/nifi/toolkit/client/impl/JerseyConnectorClient.java
+++
b/nifi-toolkit/nifi-toolkit-client/src/main/java/org/apache/nifi/toolkit/client/impl/JerseyConnectorClient.java
@@ -40,11 +40,11 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
-import java.util.Objects;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
+import java.util.Objects;
/**
* Jersey implementation of ConnectorClient.
@@ -361,21 +361,21 @@ public class JerseyConnectorClient extends
AbstractJerseyClient implements Conne
@Override
public ProcessGroupFlowEntity getFlow(final String connectorId) throws
NiFiClientException, IOException {
- return getFlow(connectorId, false);
+ final ConnectorEntity connector = getConnector(connectorId);
+ final String managedProcessGroupId =
connector.getComponent().getManagedProcessGroupId();
+ return getFlow(connectorId, managedProcessGroupId);
}
@Override
- public ProcessGroupFlowEntity getFlow(final String connectorId, final
boolean uiOnly) throws NiFiClientException, IOException {
+ public ProcessGroupFlowEntity getFlow(final String connectorId, final
String processGroupId) throws NiFiClientException, IOException {
Objects.requireNonNull(connectorId, "Connector ID required");
+ Objects.requireNonNull(processGroupId, "Process Group ID required");
return executeAction("Error retrieving connector flow", () -> {
WebTarget target = connectorTarget
- .path("/flow")
- .resolveTemplate("id", connectorId);
-
- if (uiOnly) {
- target = target.queryParam("uiOnly", "true");
- }
+ .path("/flow/process-groups/{processGroupId}")
+ .resolveTemplate("id", connectorId)
+ .resolveTemplate("processGroupId", processGroupId);
return getRequestBuilder(target).get(ProcessGroupFlowEntity.class);
});