diff --git a/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/parameter/StandardParameterProviderNode.java b/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/parameter/StandardParameterProviderNode.java index a9e3f4782549..479e782cb925 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/parameter/StandardParameterProviderNode.java +++ b/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/parameter/StandardParameterProviderNode.java @@ -339,6 +339,20 @@ public void fetchParameters() { } } + @Override + public Optional findFetchedParameterGroup(final String parameterGroupName) { + Objects.requireNonNull(parameterGroupName, "Parameter Group Name required"); + + readLock.lock(); + try { + return fetchedParameterGroups.stream() + .filter(parameterGroup -> parameterGroup.getGroupName().equals(parameterGroupName)) + .findFirst(); + } finally { + readLock.unlock(); + } + } + @Override public void verifyCanApplyParameters(final Collection parameterGroupConfigurations) { if (fetchedParameterGroups.isEmpty()) { diff --git a/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/parameter/FilterSensitiveParameterValueMapper.java b/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/parameter/FilterSensitiveParameterValueMapper.java new file mode 100644 index 000000000000..f7bd4b4f4546 --- /dev/null +++ b/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/parameter/FilterSensitiveParameterValueMapper.java @@ -0,0 +1,47 @@ +/* + * 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.parameter; + +import java.util.Objects; + +/** + * Filter values and return null for Parameter values with sensitive descriptors + */ +public class FilterSensitiveParameterValueMapper implements ParameterValueMapper { + /** + * Get mapped Parameter value based on properties + * + * @param parameter Parameter with descriptor of attributes for mapping + * @param value Parameter value to be mapped + * @return Mapped Parameter value + */ + @Override + public String getMapped(final Parameter parameter, final String value) { + Objects.requireNonNull(parameter, "Parameter required"); + + final ParameterDescriptor descriptor = parameter.getDescriptor(); + final String mapped; + + if (descriptor.isSensitive()) { + mapped = null; + } else { + mapped = value; + } + + return mapped; + } +} diff --git a/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/parameter/ParameterValueMapper.java b/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/parameter/ParameterValueMapper.java new file mode 100644 index 000000000000..c44ca21b6e74 --- /dev/null +++ b/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/parameter/ParameterValueMapper.java @@ -0,0 +1,31 @@ +/* + * 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.parameter; + +/** + * Abstraction for mapping Parameter values from runtime representation to versioned representation + */ +public interface ParameterValueMapper { + /** + * Get mapped Parameter value based on properties + * + * @param parameter Parameter with descriptor of attributes for mapping + * @param value Parameter value to be mapped + * @return Mapped Parameter value + */ + String getMapped(Parameter parameter, String value); +} diff --git a/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/parameter/StandardParameterValueMapper.java b/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/parameter/StandardParameterValueMapper.java new file mode 100644 index 000000000000..c47b699cfece --- /dev/null +++ b/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/parameter/StandardParameterValueMapper.java @@ -0,0 +1,66 @@ +/* + * 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.parameter; + +import org.apache.nifi.registry.flow.mapping.SensitiveValueEncryptor; + +import java.util.Objects; + +/** + * Standard implementation with encryptor for sensitive values + */ +public class StandardParameterValueMapper implements ParameterValueMapper { + static final String PROVIDED_MAPPING = "provided:parameter"; + + private static final String ENCRYPTED_FORMAT = "enc{%s}"; + + private final SensitiveValueEncryptor sensitiveValueEncryptor; + + public StandardParameterValueMapper(final SensitiveValueEncryptor sensitiveValueEncryptor) { + this.sensitiveValueEncryptor = sensitiveValueEncryptor; + } + + /** + * Get mapped Parameter value based on properties + * + * @param parameter Parameter with descriptor of attributes for mapping + * @param value Parameter value to be mapped + * @return Mapped Parameter value + */ + @Override + public String getMapped(final Parameter parameter, final String value) { + Objects.requireNonNull(parameter, "Parameter required"); + + final ParameterDescriptor descriptor = parameter.getDescriptor(); + final String mapped; + + if (parameter.isProvided()) { + mapped = PROVIDED_MAPPING; + } else if (descriptor.isSensitive()) { + if (sensitiveValueEncryptor == null) { + mapped = value; + } else { + final String encrypted = sensitiveValueEncryptor.encrypt(value); + mapped = ENCRYPTED_FORMAT.formatted(encrypted); + } + } else { + mapped = value; + } + + return mapped; + } +} diff --git a/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/registry/flow/mapping/NiFiRegistryFlowMapper.java b/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/registry/flow/mapping/NiFiRegistryFlowMapper.java index 181514cdc741..766518a8c57e 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/registry/flow/mapping/NiFiRegistryFlowMapper.java +++ b/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/registry/flow/mapping/NiFiRegistryFlowMapper.java @@ -73,12 +73,15 @@ import org.apache.nifi.groups.ProcessGroup; import org.apache.nifi.groups.RemoteProcessGroup; import org.apache.nifi.nar.ExtensionManager; +import org.apache.nifi.parameter.FilterSensitiveParameterValueMapper; import org.apache.nifi.parameter.Parameter; import org.apache.nifi.parameter.ParameterContext; import org.apache.nifi.parameter.ParameterDescriptor; import org.apache.nifi.parameter.ParameterProvider; import org.apache.nifi.parameter.ParameterProviderConfiguration; import org.apache.nifi.parameter.ParameterReferencedControllerServiceData; +import org.apache.nifi.parameter.ParameterValueMapper; +import org.apache.nifi.parameter.StandardParameterValueMapper; import org.apache.nifi.processor.Relationship; import org.apache.nifi.registry.flow.FlowRegistryClientNode; import org.apache.nifi.registry.flow.VersionControlInformation; @@ -107,6 +110,7 @@ public class NiFiRegistryFlowMapper { private final ExtensionManager extensionManager; private final FlowMappingOptions flowMappingOptions; + private final ParameterValueMapper parameterValueMapper; // We need to keep a mapping of component id to versionedComponentId as we transform these objects. This way, when // we call #mapConnectable, instead of generating a new UUID for the ConnectableComponent, we can lookup the 'versioned' @@ -121,6 +125,12 @@ public NiFiRegistryFlowMapper(final ExtensionManager extensionManager) { public NiFiRegistryFlowMapper(final ExtensionManager extensionManager, final FlowMappingOptions flowMappingOptions) { this.extensionManager = extensionManager; this.flowMappingOptions = flowMappingOptions; + + if (flowMappingOptions.isMapSensitiveConfiguration()) { + this.parameterValueMapper = new StandardParameterValueMapper(flowMappingOptions.getSensitiveValueEncryptor()); + } else { + this.parameterValueMapper = new FilterSensitiveParameterValueMapper(); + } } /** @@ -911,10 +921,10 @@ private VersionedParameter mapParameter(ParameterContext parameterContext, Param if (referencedControllerServiceData.isEmpty()) { versionedParameter = mapParameter(parameter); } else { - versionedParameter = mapParameter( - parameter, - getId(Optional.ofNullable(referencedControllerServiceData.get(0).getVersionedServiceId()), parameter.getValue()) - ); + final String referencedVersionServiceId = referencedControllerServiceData.getFirst().getVersionedServiceId(); + final String parameterValue = parameter.getValue(); + final String serviceId = getId(Optional.ofNullable(referencedVersionServiceId), parameterValue); + versionedParameter = mapParameter(parameter, serviceId); } } else { versionedParameter = mapParameter(parameter); @@ -954,19 +964,8 @@ private VersionedParameter mapParameter(final Parameter parameter, final String versionedParameter.setSensitive(descriptor.isSensitive()); versionedParameter.setProvided(parameter.isProvided()); - final boolean mapParameterValue = flowMappingOptions.isMapSensitiveConfiguration() || !descriptor.isSensitive(); - final String parameterValue; - if (mapParameterValue) { - if (descriptor.isSensitive()) { - parameterValue = encrypt(value); - } else { - parameterValue = value; - } - } else { - parameterValue = null; - } - - versionedParameter.setValue(parameterValue); + final String mapped = parameterValueMapper.getMapped(parameter, value); + versionedParameter.setValue(mapped); return versionedParameter; } diff --git a/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/test/java/org/apache/nifi/parameter/TestStandardParameterValueMapper.java b/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/test/java/org/apache/nifi/parameter/TestStandardParameterValueMapper.java new file mode 100644 index 000000000000..5181e0a8bd10 --- /dev/null +++ b/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/test/java/org/apache/nifi/parameter/TestStandardParameterValueMapper.java @@ -0,0 +1,86 @@ +/* + * 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.parameter; + +import org.apache.nifi.registry.flow.mapping.SensitiveValueEncryptor; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + +@ExtendWith(MockitoExtension.class) +class TestStandardParameterValueMapper { + private static final String NAME = "NamedParameter"; + + private static final String VALUE = "ParameterValue"; + + @Mock + private SensitiveValueEncryptor sensitiveValueEncryptor; + + private StandardParameterValueMapper mapper; + + @BeforeEach + void setMapper() { + mapper = new StandardParameterValueMapper(sensitiveValueEncryptor); + } + + @Test + void testGetMappedNotSensitiveNotProvided() { + final Parameter parameter = getParameter(false, false); + + final String mapped = mapper.getMapped(parameter, VALUE); + + assertEquals(VALUE, mapped); + } + + @Test + void testGetMappedNotSensitiveProvided() { + final Parameter parameter = getParameter(false, true); + + final String mapped = mapper.getMapped(parameter, VALUE); + + assertEquals(StandardParameterValueMapper.PROVIDED_MAPPING, mapped); + } + + @Test + void testGetMappedSensitiveProvided() { + final Parameter parameter = getParameter(true, true); + + final String mapped = mapper.getMapped(parameter, VALUE); + + assertEquals(StandardParameterValueMapper.PROVIDED_MAPPING, mapped); + } + + @Test + void testGetMappedSensitiveNotProvided() { + final Parameter parameter = getParameter(true, false); + + final String mapped = mapper.getMapped(parameter, VALUE); + + assertNotEquals(VALUE, mapped); + assertNotEquals(StandardParameterValueMapper.PROVIDED_MAPPING, mapped); + } + + private Parameter getParameter(final boolean sensitive, final boolean provided) { + final ParameterDescriptor descriptor = new ParameterDescriptor.Builder().name(NAME).sensitive(sensitive).build(); + return new Parameter(descriptor, VALUE, null, provided); + } +} diff --git a/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/ParameterProviderNode.java b/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/ParameterProviderNode.java index 11ed16db55bb..873c6c29dbac 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/ParameterProviderNode.java +++ b/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/controller/ParameterProviderNode.java @@ -20,11 +20,13 @@ import org.apache.nifi.logging.ComponentLog; import org.apache.nifi.nar.ExtensionManager; import org.apache.nifi.parameter.ParameterContext; +import org.apache.nifi.parameter.ParameterGroup; import org.apache.nifi.parameter.ParameterProvider; import org.apache.nifi.parameter.ParameterGroupConfiguration; import java.util.Collection; import java.util.List; +import java.util.Optional; import java.util.Set; public interface ParameterProviderNode extends ComponentNode { @@ -41,12 +43,30 @@ public interface ParameterProviderNode extends ComponentNode { void verifyCanFetchParameters(); + /** + * Retrieve Parameter Groups from configured Parameter Provider and store for subsequent retrieval in others methods + * + */ void fetchParameters(); + /** + * Find a named Parameter Group cached from previous request to fetch Parameters from the configured Parameter Provider + * + * @param parameterGroupName Parameter Group Name to find + * @return Parameter Group with Parameter Names and Values or empty when not found + */ + Optional findFetchedParameterGroup(String parameterGroupName); + void verifyCanApplyParameters(Collection parameterNames); Collection getParameterGroupConfigurations(); + /** + * Get Parameter Groups with Parameter Names and Values to be applied to associated Parameter Contexts + * + * @param parameterGroupConfigurations Parameter Group Configurations to be retrieved + * @return List of Parameter Groups and Parameter Contexts to be applied based on Parameters retrieved in previous fetch requests + */ List getFetchedParametersToApply(Collection parameterGroupConfigurations); void verifyCanClearState(); @@ -76,7 +96,7 @@ public interface ParameterProviderNode extends ComponentNode { * @param context the configuration to verify * @param logger a logger that can be used when performing verification * @param extensionManager extension manager that is used for obtaining appropriate NAR ClassLoaders - * @return a list of results indicating whether or not the given configuration is valid + * @return a list of results indicating whether the given configuration is valid */ List verifyConfiguration(ConfigurationContext context, ComponentLog logger, ExtensionManager extensionManager); } diff --git a/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/serialization/VersionedFlowSynchronizer.java b/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/serialization/VersionedFlowSynchronizer.java index 7ff21e7fc100..fee9285ab6ba 100644 --- a/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/serialization/VersionedFlowSynchronizer.java +++ b/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/main/java/org/apache/nifi/controller/serialization/VersionedFlowSynchronizer.java @@ -46,7 +46,6 @@ import org.apache.nifi.controller.inheritance.FlowInheritability; import org.apache.nifi.controller.inheritance.FlowInheritabilityCheck; import org.apache.nifi.controller.inheritance.MissingComponentsCheck; -import org.apache.nifi.controller.reporting.ReportingTaskInstantiationException; import org.apache.nifi.controller.service.ControllerServiceNode; import org.apache.nifi.encrypt.PropertyEncryptor; import org.apache.nifi.flow.Bundle; @@ -77,6 +76,7 @@ import org.apache.nifi.parameter.ParameterContext; import org.apache.nifi.parameter.ParameterContextManager; import org.apache.nifi.parameter.ParameterDescriptor; +import org.apache.nifi.parameter.ParameterGroup; import org.apache.nifi.parameter.ParameterProviderConfiguration; import org.apache.nifi.parameter.StandardParameterProviderConfiguration; import org.apache.nifi.persistence.FlowConfigurationArchiveManager; @@ -115,10 +115,10 @@ import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.Objects; import java.util.Optional; import java.util.Set; +import java.util.function.Function; import java.util.stream.Collectors; import java.util.zip.GZIPInputStream; @@ -381,24 +381,6 @@ private Bundle getCompatibleBundle(final Bundle bundle, final ExtensionManager e return null; } - private BundleCoordinate getCompatibleBundle(final BundleCoordinate coordinate, final ExtensionManager extensionManager, final String type) { - final org.apache.nifi.bundle.Bundle exactBundle = extensionManager.getBundle(coordinate); - if (exactBundle != null) { - return coordinate; - } - - final BundleDTO bundleDto = new BundleDTO(coordinate.getGroup(), coordinate.getId(), coordinate.getVersion()); - final Optional optionalCoordinate = BundleUtils.getOptionalCompatibleBundle(extensionManager, type, bundleDto); - if (optionalCoordinate.isPresent()) { - final BundleCoordinate selectedCoordinate = optionalCoordinate.get(); - logger.debug("Found compatible bundle {} for {} and type {}", selectedCoordinate.getCoordinate(), coordinate, type); - return selectedCoordinate; - } - - logger.debug("Could not find a compatible bundle for {} and type {}", coordinate, type); - return null; - } - private void synchronizeFlow(final FlowController controller, final DataFlow existingFlow, final DataFlow proposedFlow, final AffectedComponentSet affectedComponentSet) { // attempt to sync controller with proposed flow try { @@ -594,7 +576,7 @@ private void updateRegistry(final FlowRegistryClientNode flowRegistryClient, fin flowRegistryClient.setProperties(decryptedProperties, false, sensitiveDynamicPropertyNames); } - private void inheritReportingTasks(final FlowController controller, final VersionedDataflow dataflow, final AffectedComponentSet affectedComponentSet) throws ReportingTaskInstantiationException { + private void inheritReportingTasks(final FlowController controller, final VersionedDataflow dataflow, final AffectedComponentSet affectedComponentSet) { final Set versionedTaskIds = new HashSet<>(); for (final VersionedReportingTask versionedReportingTask : dataflow.getReportingTasks()) { versionedTaskIds.add(versionedReportingTask.getInstanceIdentifier()); @@ -613,7 +595,7 @@ private void inheritReportingTasks(final FlowController controller, final Versio } } - private void addReportingTask(final FlowController controller, final VersionedReportingTask reportingTask) throws ReportingTaskInstantiationException { + private void addReportingTask(final FlowController controller, final VersionedReportingTask reportingTask) { final BundleCoordinate coordinate = createBundleCoordinate(extensionManager, reportingTask.getBundle(), reportingTask.getType()); final ReportingTaskNode taskNode = controller.createReportingTask(reportingTask.getType(), reportingTask.getInstanceIdentifier(), coordinate, false); @@ -823,7 +805,7 @@ private void addParameterContext( final Map namedParameterContexts, final PropertyEncryptor encryptor ) { - final Map parameters = createParameterMap(versionedParameterContext, encryptor); + final Map parameters = createParameterMap(flowManager, versionedParameterContext, encryptor); final ParameterContextManager contextManager = flowManager.getParameterContextManager(); final List referenceIds = findReferencedParameterContextIds(versionedParameterContext, contextManager, namedParameterContexts); @@ -868,8 +850,13 @@ private List findReferencedParameterContextIds( return referenceIds; } - private Map createParameterMap(final VersionedParameterContext versionedParameterContext, - final PropertyEncryptor encryptor) { + private Map createParameterMap( + final FlowManager flowManager, + final VersionedParameterContext versionedParameterContext, + final PropertyEncryptor encryptor + ) { + final Map providedParameters = getProvidedParameters(flowManager, versionedParameterContext); + final Map parameters = new HashMap<>(); for (final VersionedParameter versioned : versionedParameterContext.getParameters()) { final ParameterDescriptor descriptor = new ParameterDescriptor.Builder() @@ -882,6 +869,15 @@ private Map createParameterMap(final VersionedParameterContex final String rawValue = versioned.getValue(); if (rawValue == null) { parameterValue = null; + } else if (versioned.isProvided()) { + final String name = versioned.getName(); + final Parameter providedParameter = providedParameters.get(name); + if (providedParameter == null) { + logger.warn("Parameter Context [{}] Provided Parameter [{}] not found", versionedParameterContext.getIdentifier(), name); + parameterValue = null; + } else { + parameterValue = providedParameter.getValue(); + } } else if (versioned.isSensitive()) { parameterValue = decrypt(rawValue, encryptor); } else { @@ -902,17 +898,11 @@ private void updateParameterContext( final Map namedParameterContexts, final PropertyEncryptor encryptor ) { - final Map parameters = createParameterMap(versionedParameterContext, encryptor); + final Map parameters = createParameterMap(flowManager, versionedParameterContext, encryptor); final Map currentValues = new HashMap<>(); parameterContext.getParameters().values().forEach(param -> currentValues.put(param.getDescriptor().getName(), param.getValue())); - if (logger.isDebugEnabled()) { - final Map proposedValues = parameters.entrySet().stream() - .collect(Collectors.toMap(Entry::getKey, entry -> entry.getValue().getValue())); - logger.debug("For Parameter Context {}, current parameters = {}, proposed = {}", parameterContext.getName(), currentValues, proposedValues); - } - final Map updatedParameters = new HashMap<>(); final Set proposedParameterNames = new HashSet<>(); for (final VersionedParameter parameter : versionedParameterContext.getParameters()) { @@ -1010,6 +1000,38 @@ private void inheritControllerServices(final FlowController controller, final Ve removeMissingServices(controller, dataflow); } + private Map getProvidedParameters(final FlowManager flowManager, final VersionedParameterContext versionedParameterContext) { + final Map providedProviders; + final String parameterProviderId = versionedParameterContext.getParameterProvider(); + if (parameterProviderId == null) { + providedProviders = Collections.emptyMap(); + } else { + final ParameterProviderNode parameterProviderNode = flowManager.getParameterProvider(parameterProviderId); + providedProviders = getProvidedParameters(parameterProviderNode, versionedParameterContext.getParameterGroupName()); + } + return providedProviders; + } + + private Map getProvidedParameters(final ParameterProviderNode parameterProviderNode, final String parameterGroupName) { + logger.debug("Fetching Parameters for Group [{}] from Provider [{}]", parameterGroupName, parameterProviderNode.getIdentifier()); + parameterProviderNode.fetchParameters(); + + final Map parameters; + final Optional foundParameterGroup = parameterProviderNode.findFetchedParameterGroup(parameterGroupName); + if (foundParameterGroup.isPresent()) { + final ParameterGroup parameterGroup = foundParameterGroup.get(); + parameters = parameterGroup.getParameters().stream() + .collect( + Collectors.toMap(parameter -> parameter.getDescriptor().getName(), Function.identity()) + ); + } else { + parameters = Collections.emptyMap(); + } + + logger.info("Fetched Parameters [{}] for Group [{}] from Provider [{}]", parameters.size(), parameterGroupName, parameterProviderNode.getIdentifier()); + return parameters; + } + private void removeMissingServices(final FlowController controller, final VersionedDataflow dataflow) { if (dataflow == null) { return;