bbende commented on a change in pull request #3553: NIFI-5856: When exporting a 
flow that references a Controller Service…
URL: https://github.com/apache/nifi/pull/3553#discussion_r303105617
 
 

 ##########
 File path: 
nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java
 ##########
 @@ -3071,6 +3078,122 @@ public void 
discoverCompatibleBundles(VersionedProcessGroup versionedGroup) {
         
BundleUtils.discoverCompatibleBundles(controllerFacade.getExtensionManager(), 
versionedGroup);
     }
 
+    @Override
+    public void resolveInheritedControllerServices(final VersionedFlowSnapshot 
versionedFlowSnapshot, final String processGroupId) {
+        final VersionedProcessGroup versionedGroup = 
versionedFlowSnapshot.getFlowContents();
+        resolveInheritedControllerServices(versionedGroup, processGroupId, 
versionedFlowSnapshot.getExternalControllerServices());
+    }
+
+    private void resolveInheritedControllerServices(final 
VersionedProcessGroup versionedGroup, final String processGroupId,
+                                                    final Map<String, 
ExternalControllerServiceReference> externalControllerServiceReferences) {
+        final Set<String> availableControllerServiceIds = 
findAllControllerServiceIds(versionedGroup);
+        final ProcessGroup parentGroup = 
processGroupDAO.getProcessGroup(processGroupId);
+        final Set<ControllerServiceNode> serviceNodes = 
parentGroup.getControllerServices(true);
+
+        final ExtensionManager extensionManager = 
controllerFacade.getExtensionManager();
+        for (final VersionedProcessor processor : 
versionedGroup.getProcessors()) {
+            final BundleCoordinate compatibleBundle = 
BundleUtils.discoverCompatibleBundle(extensionManager, processor.getType(), 
processor.getBundle());
+            final ConfigurableComponent tempComponent = 
extensionManager.getTempComponent(processor.getType(), compatibleBundle);
+
+            resolveInheritedControllerServices(processor, 
availableControllerServiceIds, serviceNodes, 
externalControllerServiceReferences, tempComponent::getPropertyDescriptor);
+        }
+
+        for (final VersionedControllerService service : 
versionedGroup.getControllerServices()) {
+            final BundleCoordinate compatibleBundle = 
BundleUtils.discoverCompatibleBundle(extensionManager, service.getType(), 
service.getBundle());
+            final ConfigurableComponent tempComponent = 
extensionManager.getTempComponent(service.getType(), compatibleBundle);
+
+            resolveInheritedControllerServices(service, 
availableControllerServiceIds, serviceNodes, 
externalControllerServiceReferences, tempComponent::getPropertyDescriptor);
+        }
+
+        for (final VersionedProcessGroup child : 
versionedGroup.getProcessGroups()) {
+            resolveInheritedControllerServices(child, processGroupId, 
externalControllerServiceReferences);
+        }
+    }
+
+
+    private void resolveInheritedControllerServices(final 
VersionedConfigurableComponent component, final Set<String> 
availableControllerServiceIds,
+                                                    final 
Set<ControllerServiceNode> availableControllerServices,
+                                                    final Map<String, 
ExternalControllerServiceReference> externalControllerServiceReferences,
+                                                    final Function<String, 
PropertyDescriptor> descriptorLookup) {
+        final Map<String, VersionedPropertyDescriptor> descriptors = 
component.getPropertyDescriptors();
+        final Map<String, String> properties = component.getProperties();
+
+        resolveInheritedControllerServices(descriptors, properties, 
availableControllerServiceIds, availableControllerServices, 
externalControllerServiceReferences, descriptorLookup);
+    }
+
+
+    private void resolveInheritedControllerServices(final Map<String, 
VersionedPropertyDescriptor> propertyDescriptors, final Map<String, String> 
componentProperties,
+                                                    final Set<String> 
availableControllerServiceIds, final Set<ControllerServiceNode> 
availableControllerServices,
+                                                    final Map<String, 
ExternalControllerServiceReference> externalControllerServiceReferences,
+                                                    final Function<String, 
PropertyDescriptor> descriptorLookup) {
+
+        for (final Map.Entry<String, String> entry : new 
HashMap<>(componentProperties).entrySet()) {
+            final String propertyName = entry.getKey();
+            final String propertyValue = entry.getValue();
+
+            final VersionedPropertyDescriptor propertyDescriptor = 
propertyDescriptors.get(propertyName);
+            if (propertyDescriptor == null) {
+                continue;
+            }
+
+            if (!propertyDescriptor.getIdentifiesControllerService()) {
+                continue;
+            }
+
+            // If the referenced Controller Service is available in this flow, 
there is nothing to resolve.
+            if (availableControllerServiceIds.contains(propertyValue)) {
+                continue;
+            }
+
+            final ExternalControllerServiceReference externalServiceReference 
= externalControllerServiceReferences == null ? null : 
externalControllerServiceReferences.get(propertyValue);
+            if (externalServiceReference == null) {
+                continue;
+            }
+
+            final PropertyDescriptor descriptor = 
descriptorLookup.apply(propertyName);
+            if (descriptor == null) {
+                continue;
+            }
+
+            final Class<? extends ControllerService> referencedServiceClass = 
descriptor.getControllerServiceDefinition();
+            if (referencedServiceClass == null) {
+                continue;
+            }
+
+            final String externalControllerServiceName = 
externalServiceReference.getName();
+            final List<ControllerServiceNode> matchingControllerServices = 
availableControllerServices.stream()
+                .filter(service -> 
service.getName().equals(externalControllerServiceName))
+                .filter(service -> 
referencedServiceClass.isAssignableFrom(service.getProxiedControllerService().getClass()))
 
 Review comment:
   I think we also need to consider whether the current user has READ access to 
the service. Right now it will resolve a service even if the current user 
doesn't have READ.
   
   This might then pose another question... if there are two services with the 
same name, and the user is only authorized for one of them, do we auto select 
the other, or do we consider it a case where we can't decide the right one?

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
[email protected]


With regards,
Apache Git Services

Reply via email to