mirror of https://github.com/apache/nifi.git
NIFI-11122 Corrected provided parameter context inheritance after creation
This closes #6913 Signed-off-by: David Handermann <exceptionfactory@apache.org>
This commit is contained in:
parent
027e2b9bc1
commit
2609fd5f55
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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()));
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue