This is an automated email from the ASF dual-hosted git repository.
exceptionfactory pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/nifi.git
The following commit(s) were added to refs/heads/main by this push:
new 2609fd5f55 NIFI-11122 Corrected provided parameter context inheritance
after creation
2609fd5f55 is described below
commit 2609fd5f558e3b39a77c70d10e7a81c07022cad3
Author: Joe Gresock <[email protected]>
AuthorDate: Wed Feb 1 10:30:23 2023 -0500
NIFI-11122 Corrected provided parameter context inheritance after creation
This closes #6913
Signed-off-by: David Handermann <[email protected]>
---
.../parameter/StandardParameterProviderNode.java | 17 ++-
.../nifi/parameter/StandardParameterContext.java | 6 +-
.../apache/nifi/parameter/ParameterContext.java | 6 +
.../web/dao/impl/StandardParameterContextDAO.java | 3 +-
.../dao/impl/TestStandardParameterContextDAO.java | 157 +++++++++++++++++++++
5 files changed, 185 insertions(+), 4 deletions(-)
diff --git
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/parameter/StandardParameterProviderNode.java
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/parameter/StandardParameterProviderNode.java
index aca97a9599..c391e30ade 100644
---
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/parameter/StandardParameterProviderNode.java
+++
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/controller/parameter/StandardParameterProviderNode.java
@@ -348,7 +348,22 @@ public class StandardParameterProviderNode extends
AbstractComponentNode impleme
if (groupConfiguration == null) {
continue;
}
-
reference.verifyCanSetParameters(getFetchedParameterUpdateMap(reference,
groupConfiguration));
+ final Map<String, Parameter> parameterUpdates =
getFetchedParameterUpdateMap(reference, groupConfiguration);
+ final Collection<String> removedParametersWithReferences = new
HashSet<>();
+ for (final Map.Entry<String, Parameter> entry :
parameterUpdates.entrySet()) {
+ final String parameterName = entry.getKey();
+ if (entry.getValue() == null) {
+
reference.getParameter(parameterName).ifPresent(currentParameter -> {
+ if
(reference.hasReferencingComponents(currentParameter)) {
+
removedParametersWithReferences.add(parameterName);
+ }
+ });
+ }
+ }
+ // Any deletions of parameters with referencing components
should be removed from consideration,
+ // since we do not remove provided parameters that are deleted
until they are no longer referenced
+
removedParametersWithReferences.forEach(parameterUpdates::remove);
+ reference.verifyCanSetParameters(parameterUpdates);
}
} finally {
readLock.unlock();
diff --git
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/parameter/StandardParameterContext.java
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/parameter/StandardParameterContext.java
index 339317fdd9..da3350f099 100644
---
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/parameter/StandardParameterContext.java
+++
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-components/src/main/java/org/apache/nifi/parameter/StandardParameterContext.java
@@ -640,7 +640,8 @@ public class StandardParameterContext implements
ParameterContext {
// If a current parameter is not in the proposed parameters, it
was effectively removed
if
(!effectiveProposedParameters.containsKey(currentParameterDescriptor)) {
final Parameter parameter = entry.getValue();
- if (parameter.isProvided() &&
hasReferencingComponents(parameter)) {
+ final boolean isParameterInherited =
!parameter.getParameterContextId().equals(id);
+ if (!isParameterInherited && parameter.isProvided() &&
hasReferencingComponents(parameter)) {
logger.info("Provided parameter [{}] was removed from the
source, but it is referenced by a component, so the parameter will be
preserved",
currentParameterDescriptor.getName());
} else {
@@ -651,7 +652,8 @@ public class StandardParameterContext implements
ParameterContext {
return effectiveParameterUpdates;
}
- private boolean hasReferencingComponents(final Parameter parameter) {
+ @Override
+ public boolean hasReferencingComponents(final Parameter parameter) {
if (parameter == null) {
return false;
}
diff --git
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/parameter/ParameterContext.java
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/parameter/ParameterContext.java
index aa13288d98..7177bbbed6 100644
---
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/parameter/ParameterContext.java
+++
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core-api/src/main/java/org/apache/nifi/parameter/ParameterContext.java
@@ -174,6 +174,12 @@ public interface ParameterContext extends ParameterLookup,
ComponentAuthorizable
*/
List<String> getInheritedParameterContextNames();
+ /**
+ * @param parameter A parameter
+ * @return True if the parameter has referencing components
+ */
+ boolean hasReferencingComponents(Parameter parameter);
+
/**
* Returns true if this ParameterContext inherits from the given parameter
context, either
* directly or indirectly.
diff --git
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardParameterContextDAO.java
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardParameterContextDAO.java
index 125dff0d86..6504fd943d 100644
---
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardParameterContextDAO.java
+++
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardParameterContextDAO.java
@@ -337,7 +337,8 @@ public class StandardParameterContextDAO implements
ParameterContextDAO {
}
} else {
final boolean hasProvidedParameters = parameters.stream()
- .anyMatch(parameter ->
parameter.getParameter().getProvided() != null &&
parameter.getParameter().getProvided());
+ .anyMatch(parameter ->
parameter.getParameter().getProvided() != null &&
parameter.getParameter().getProvided()
+ && !parameter.getParameter().getInherited());
if (hasProvidedParameters) {
throw new IllegalArgumentException(String.format("Provided
Parameters may not be set on Context [%s] because its " +
"parameters can only be user-entered",
parameterContextDTO.getName()));
diff --git
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/dao/impl/TestStandardParameterContextDAO.java
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/dao/impl/TestStandardParameterContextDAO.java
new file mode 100644
index 0000000000..361a68e535
--- /dev/null
+++
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/test/java/org/apache/nifi/web/dao/impl/TestStandardParameterContextDAO.java
@@ -0,0 +1,157 @@
+/*
+ * 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.web.dao.impl;
+
+import org.apache.nifi.authorization.AuthorizationRequest;
+import org.apache.nifi.authorization.AuthorizationResult;
+import org.apache.nifi.authorization.Authorizer;
+import org.apache.nifi.authorization.user.NiFiUser;
+import org.apache.nifi.authorization.user.NiFiUserDetails;
+import org.apache.nifi.authorization.user.StandardNiFiUser;
+import org.apache.nifi.controller.FlowController;
+import org.apache.nifi.controller.flow.FlowManager;
+import org.apache.nifi.parameter.Parameter;
+import org.apache.nifi.parameter.ParameterContext;
+import org.apache.nifi.parameter.ParameterDescriptor;
+import org.apache.nifi.parameter.ParameterReferenceManager;
+import org.apache.nifi.parameter.StandardParameterContext;
+import org.apache.nifi.parameter.StandardParameterContextManager;
+import org.apache.nifi.parameter.StandardParameterReferenceManager;
+import org.apache.nifi.web.api.dto.ParameterContextDTO;
+import org.apache.nifi.web.api.dto.ParameterContextReferenceDTO;
+import org.apache.nifi.web.api.dto.ParameterDTO;
+import org.apache.nifi.web.api.entity.ParameterContextReferenceEntity;
+import org.apache.nifi.web.api.entity.ParameterEntity;
+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 org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Answers.RETURNS_DEEP_STUBS;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(MockitoExtension.class)
+public class TestStandardParameterContextDAO {
+
+ private StandardParameterContextDAO dao;
+
+ @Mock(answer = RETURNS_DEEP_STUBS)
+ private FlowController flowController;
+
+ @Mock
+ private Authentication authentication;
+
+ @Mock
+ private Authorizer authorizer;
+
+ @BeforeEach
+ void setUp() {
+ dao = new StandardParameterContextDAO();
+ dao.setFlowController(flowController);
+ dao.setAuthorizer(authorizer);
+
when(authorizer.authorize(any(AuthorizationRequest.class))).thenReturn(AuthorizationResult.approved());
+
+ final SecurityContext securityContext =
SecurityContextHolder.getContext();
+ securityContext.setAuthentication(authentication);
+ final NiFiUser user = new
StandardNiFiUser.Builder().identity("user").build();
+ final NiFiUserDetails userDetail = new NiFiUserDetails(user);
+ when(authentication.getPrincipal()).thenReturn(userDetail);
+
+ final ParameterReferenceManager parameterReferenceManager = new
StandardParameterReferenceManager(flowController.getFlowManager());
+
+ final FlowManager flowManager = flowController.getFlowManager();
+ final StandardParameterContextManager parameterContextLookup = new
StandardParameterContextManager();
+
when(flowManager.getParameterContextManager()).thenReturn(parameterContextLookup);
+ parameterContextLookup.addParameterContext(new
StandardParameterContext.Builder().id("id")
+ .name("Context")
+ .parameterReferenceManager(parameterReferenceManager)
+ .build());
+ final ParameterContext inheritedContext = new
StandardParameterContext.Builder().id("inherited-id")
+ .parameterReferenceManager(parameterReferenceManager)
+ .name("Inherited")
+ .build();
+ final Map<String, Parameter> parameters = new HashMap<>();
+ parameters.put("inherited-param", new Parameter(new
ParameterDescriptor.Builder().name("inherited-param").build(),
+ "value", null, true));
+ inheritedContext.setParameters(parameters);
+ parameterContextLookup.addParameterContext(inheritedContext);
+ }
+
+ @Test
+ public void testVerifyUpdateInheritedProvidedParameter() {
+ final ParameterContextDTO dto = new ParameterContextDTO();
+ dto.setId("id");
+ dto.setName("Context");
+
+ final List<ParameterContextReferenceEntity> refs = new ArrayList<>();
+ final ParameterContextReferenceEntity ref = new
ParameterContextReferenceEntity();
+ ref.setId("inherited-id");
+ ref.setComponent(new ParameterContextReferenceDTO());
+ ref.getComponent().setId("inherited-id");
+ ref.getComponent().setName("Inherited");
+ refs.add(ref);
+ dto.setInheritedParameterContexts(refs);
+
+ // Updating a provided parameter that is inherited is allowed
+ dao.verifyUpdate(dto, true);
+ }
+
+ @Test
+ public void testVerifyUpdateNonInheritedProvidedParameter() {
+ final ParameterContextDTO dto = new ParameterContextDTO();
+ dto.setId("id");
+ dto.setName("Context");
+ final Set<ParameterEntity> parameters = new HashSet<>();
+ final ParameterEntity parameter = new ParameterEntity();
+ parameter.setCanWrite(true);
+ final ParameterDTO parameterDto = new ParameterDTO();
+ parameterDto.setProvided(true);
+ parameterDto.setName("param");
+ parameterDto.setValue("value");
+ parameterDto.setInherited(false);
+ parameter.setParameter(parameterDto);
+ parameters.add(parameter);
+ dto.setParameters(parameters);
+
+ final List<ParameterContextReferenceEntity> refs = new ArrayList<>();
+ final ParameterContextReferenceEntity ref = new
ParameterContextReferenceEntity();
+ ref.setId("inherited-id");
+ ref.setComponent(new ParameterContextReferenceDTO());
+ ref.getComponent().setId("inherited-id");
+ ref.getComponent().setName("Inherited");
+ refs.add(ref);
+ dto.setInheritedParameterContexts(refs);
+
+
+ // Updating a provided parameter that is not inherited should fail
+ assertThrows(IllegalArgumentException.class, () ->
dao.verifyUpdate(dto, true));
+ }
+}
\ No newline at end of file