NIFI-12222 Protect against missing parameter context when syncing a PG in component synchronizer (#7877)

This commit is contained in:
Bryan Bende 2023-10-13 13:51:47 -04:00 committed by GitHub
parent 22ad7d542d
commit 96eb1d825a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 71 additions and 23 deletions

View File

@ -17,7 +17,6 @@
package org.apache.nifi.flow.synchronization;
import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.bundle.BundleCoordinate;
import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.connectable.Connectable;
@ -1888,31 +1887,27 @@ public class StandardVersionedComponentSynchronizer implements VersionedComponen
group.setParameterContext(null);
} else if (proposedParameterContextName != null) {
final VersionedParameterContext versionedParameterContext = versionedParameterContexts.get(proposedParameterContextName);
createMissingParameterProvider(versionedParameterContext, versionedParameterContext.getParameterProvider(), parameterProviderReferences, componentIdGenerator);
if (currentParamContext == null) {
// Create a new Parameter Context based on the parameters provided
if (versionedParameterContext != null) {
createMissingParameterProvider(versionedParameterContext, versionedParameterContext.getParameterProvider(), parameterProviderReferences, componentIdGenerator);
if (currentParamContext == null) {
// Create a new Parameter Context based on the parameters provided
final ParameterContext contextByName = getParameterContextByName(versionedParameterContext.getName());
final ParameterContext selectedParameterContext;
if (contextByName == null) {
final String parameterContextId = componentIdGenerator.generateUuid(versionedParameterContext.getName(),
versionedParameterContext.getName(), versionedParameterContext.getName());
selectedParameterContext = createParameterContext(versionedParameterContext, parameterContextId, versionedParameterContexts,
parameterProviderReferences, componentIdGenerator);
} else {
selectedParameterContext = contextByName;
addMissingConfiguration(versionedParameterContext, selectedParameterContext, versionedParameterContexts, parameterProviderReferences, componentIdGenerator);
}
// Protect against NPE in the event somehow the proposed name is not in the set of contexts
if (versionedParameterContext == null) {
final String paramContextNames = StringUtils.join(versionedParameterContexts.keySet());
throw new IllegalStateException("Proposed parameter context name '" + proposedParameterContextName
+ "' does not exist in set of available parameter contexts [" + paramContextNames + "]");
}
final ParameterContext contextByName = getParameterContextByName(versionedParameterContext.getName());
final ParameterContext selectedParameterContext;
if (contextByName == null) {
final String parameterContextId = componentIdGenerator.generateUuid(versionedParameterContext.getName(), versionedParameterContext.getName(), versionedParameterContext.getName());
selectedParameterContext = createParameterContext(versionedParameterContext, parameterContextId, versionedParameterContexts, parameterProviderReferences, componentIdGenerator);
group.setParameterContext(selectedParameterContext);
} else {
selectedParameterContext = contextByName;
addMissingConfiguration(versionedParameterContext, selectedParameterContext, versionedParameterContexts, parameterProviderReferences, componentIdGenerator);
// Update the current Parameter Context so that it has any Parameters included in the proposed context
addMissingConfiguration(versionedParameterContext, currentParamContext, versionedParameterContexts, parameterProviderReferences, componentIdGenerator);
}
group.setParameterContext(selectedParameterContext);
} else {
// Update the current Parameter Context so that it has any Parameters included in the proposed context
addMissingConfiguration(versionedParameterContext, currentParamContext, versionedParameterContexts, parameterProviderReferences, componentIdGenerator);
}
}
}

View File

@ -40,18 +40,23 @@ import org.apache.nifi.flow.Bundle;
import org.apache.nifi.flow.ComponentType;
import org.apache.nifi.flow.ConnectableComponent;
import org.apache.nifi.flow.ConnectableComponentType;
import org.apache.nifi.flow.ExecutionEngine;
import org.apache.nifi.flow.Position;
import org.apache.nifi.flow.ScheduledState;
import org.apache.nifi.flow.VersionedComponent;
import org.apache.nifi.flow.VersionedConnection;
import org.apache.nifi.flow.VersionedControllerService;
import org.apache.nifi.flow.VersionedExternalFlow;
import org.apache.nifi.flow.VersionedParameter;
import org.apache.nifi.flow.VersionedParameterContext;
import org.apache.nifi.flow.VersionedPort;
import org.apache.nifi.flow.VersionedProcessGroup;
import org.apache.nifi.flow.VersionedProcessor;
import org.apache.nifi.flow.VersionedPropertyDescriptor;
import org.apache.nifi.groups.ComponentIdGenerator;
import org.apache.nifi.groups.ComponentScheduler;
import org.apache.nifi.groups.FlowFileConcurrency;
import org.apache.nifi.groups.FlowFileOutboundPolicy;
import org.apache.nifi.groups.FlowSynchronizationOptions;
import org.apache.nifi.groups.ProcessGroup;
import org.apache.nifi.groups.ScheduledStateChangeListener;
@ -1090,6 +1095,54 @@ public class StandardVersionedComponentSynchronizerTest {
assertEquals(new HashSet<>(Arrays.asList("abc", "secret", "Added", "Added 2")), synchronizer.getUpdatedParameterNames(existing, proposed));
}
@Test
public void testUpdateParameterContextWhenContextDoesNotExist() {
final ProcessGroup processGroup = mock(ProcessGroup.class);
when(processGroup.getIdentifier()).thenReturn("pg1");
when(processGroup.getPosition()).thenReturn(new org.apache.nifi.connectable.Position(0, 0));
when(processGroup.getFlowFileConcurrency()).thenReturn(FlowFileConcurrency.UNBOUNDED);
when(processGroup.getFlowFileOutboundPolicy()).thenReturn(FlowFileOutboundPolicy.BATCH_OUTPUT);
when(processGroup.getExecutionEngine()).thenReturn(ExecutionEngine.STANDARD);
final VersionedProcessGroup rootGroup = new VersionedProcessGroup();
rootGroup.setIdentifier("pg1");
rootGroup.setParameterContextName("does-not-exist");
final VersionedExternalFlow externalFlow = new VersionedExternalFlow();
externalFlow.setFlowContents(rootGroup);
externalFlow.setParameterContexts(Collections.emptyMap());
synchronizer.synchronize(processGroup, externalFlow, synchronizationOptions);
verify(processGroup, times(0)).setParameterContext(any(ParameterContext.class));
}
@Test
public void testUpdateParameterContextWhenContextDoesExist() {
final ProcessGroup processGroup = mock(ProcessGroup.class);
when(processGroup.getIdentifier()).thenReturn("pg1");
when(processGroup.getPosition()).thenReturn(new org.apache.nifi.connectable.Position(0, 0));
when(processGroup.getFlowFileConcurrency()).thenReturn(FlowFileConcurrency.UNBOUNDED);
when(processGroup.getFlowFileOutboundPolicy()).thenReturn(FlowFileOutboundPolicy.BATCH_OUTPUT);
when(processGroup.getExecutionEngine()).thenReturn(ExecutionEngine.STANDARD);
final VersionedParameterContext parameterContext = new VersionedParameterContext();
parameterContext.setName("My Params");
parameterContext.setParameters(Collections.emptySet());
final Map<String, VersionedParameterContext> parameterContextMap = new HashMap<>();
parameterContextMap.put(parameterContext.getName(), parameterContext);
final VersionedProcessGroup rootGroup = new VersionedProcessGroup();
rootGroup.setIdentifier("pg1");
rootGroup.setParameterContextName(parameterContext.getName());
final VersionedExternalFlow externalFlow = new VersionedExternalFlow();
externalFlow.setFlowContents(rootGroup);
externalFlow.setParameterContexts(parameterContextMap);
synchronizer.synchronize(processGroup, externalFlow, synchronizationOptions);
verify(processGroup, times(1)).setParameterContext(any(ParameterContext.class));
}
private VersionedParameterContext createVersionedParameterContext(final String name, final Map<String, String> parameters, final Set<String> sensitiveParamNames) {
final Set<VersionedParameter> versionedParameters = new HashSet<>();