NIFI-12122 Fixed persistence of Parameter Context descriptions

Fixed bug where parameter context descriptions were not loaded on NiFi startup and overwritten as empty

This closes: #7787

Signed-off-by: David Handermann <exceptionfactory@apache.org>
This commit is contained in:
Zackeus Bengtsson 2023-09-25 14:24:10 +02:00 committed by exceptionfactory
parent 3ae0eedee6
commit 0a47157640
No known key found for this signature in database
GPG Key ID: 29B6A52D2AAE8DBA
8 changed files with 107 additions and 15 deletions

View File

@ -594,8 +594,8 @@ public abstract class AbstractFlowManager implements FlowManager {
}
@Override
public ParameterContext createParameterContext(final String id, final String name, final Map<String, Parameter> parameters,
final List<String> inheritedContextIds,
public ParameterContext createParameterContext(final String id, final String name, final String description,
final Map<String, Parameter> parameters, final List<String> inheritedContextIds,
final ParameterProviderConfiguration parameterProviderConfiguration) {
final boolean namingConflict = parameterContextManager.getParameterContexts().stream()
.anyMatch(paramContext -> paramContext.getName().equals(name));
@ -614,6 +614,7 @@ public abstract class AbstractFlowManager implements FlowManager {
.parameterProviderConfiguration(parameterProviderConfiguration)
.build();
parameterContext.setParameters(parameters);
parameterContext.setDescription(description);
if (inheritedContextIds != null && !inheritedContextIds.isEmpty()) {
if (!withParameterContextResolution.get()) {

View File

@ -1990,7 +1990,8 @@ public class StandardVersionedComponentSynchronizer implements VersionedComponen
parameters.put(versionedParameter.getName(), parameter);
}
return context.getFlowManager().createParameterContext(parameterContextId, versionedParameterContext.getName(), parameters, Collections.emptyList(), null);
return context.getFlowManager().createParameterContext(parameterContextId, versionedParameterContext.getName(), versionedParameterContext.getDescription(),
parameters, Collections.emptyList(), null);
}
private ParameterProviderConfiguration getParameterProviderConfiguration(final VersionedParameterContext context) {
@ -2013,7 +2014,8 @@ public class StandardVersionedComponentSynchronizer implements VersionedComponen
final AtomicReference<ParameterContext> contextReference = new AtomicReference<>();
context.getFlowManager().withParameterContextResolution(() -> {
final ParameterContext created = context.getFlowManager().createParameterContext(parameterContextId, versionedParameterContext.getName(), parameters, parameterContextRefs,
final ParameterContext created = context.getFlowManager().createParameterContext(parameterContextId, versionedParameterContext.getName(),
versionedParameterContext.getDescription(), parameters, parameterContextRefs,
getParameterProviderConfiguration(versionedParameterContext));
contextReference.set(created);
});

View File

@ -181,10 +181,14 @@ public class StandardVersionedComponentSynchronizerTest {
.parameterReferenceManager(parameterReferenceManager)
.build();
final Map<String, Parameter> parameterMap = invocation.getArgument(2, Map.class);
final String description = invocation.getArgument(2, String.class);
parameterContext.setDescription(description);
final Map<String, Parameter> parameterMap = invocation.getArgument(3, Map.class);
parameterContext.setParameters(parameterMap);
final List<String> inheritedContextIds = invocation.getArgument(3, List.class);
final List<String> inheritedContextIds = invocation.getArgument(4, List.class);
final List<ParameterContext> inheritedContexts = inheritedContextIds.stream()
.map(parameterContextManager::getParameterContext)
.collect(Collectors.toList());
@ -193,7 +197,7 @@ public class StandardVersionedComponentSynchronizerTest {
parameterContextManager.addParameterContext(parameterContext);
return parameterContext;
}).when(flowManager).createParameterContext(anyString(), anyString(), anyMap(), anyList(), or(any(ParameterProviderConfiguration.class), isNull()));
}).when(flowManager).createParameterContext(anyString(), anyString(), anyString(), anyMap(), anyList(), or(any(ParameterProviderConfiguration.class), isNull()));
final VersionedFlowSynchronizationContext context = new VersionedFlowSynchronizationContext.Builder()
.componentIdGenerator(componentIdGenerator)

View File

@ -360,6 +360,7 @@ public interface FlowManager extends ParameterProviderLookup {
*
* @param id The unique id
* @param name The ParameterContext name
* @param description The ParameterContext description
* @param parameters The Parameters
* @param inheritedContextIds The identifiers of any Parameter Contexts that the newly created Parameter Context should inherit from. The order of the identifiers in the List determines the
* order in which parameters with conflicting names are resolved. I.e., the Parameter Context whose ID comes first in the List is preferred.
@ -368,8 +369,8 @@ public interface FlowManager extends ParameterProviderLookup {
* @throws IllegalStateException If <code>parameterContexts</code> is not empty and this method is called without being wrapped
* by {@link FlowManager#withParameterContextResolution(Runnable)}
*/
ParameterContext createParameterContext(String id, String name, Map<String, Parameter> parameters, List<String> inheritedContextIds,
ParameterProviderConfiguration parameterProviderConfiguration);
ParameterContext createParameterContext(String id, String name, String description, Map<String, Parameter> parameters,
List<String> inheritedContextIds, ParameterProviderConfiguration parameterProviderConfiguration);
/**
* Performs the given ParameterContext-related action, and then resolves all inherited ParameterContext references.

View File

@ -815,8 +815,8 @@ public class VersionedFlowSynchronizer implements FlowSynchronizer {
parameterProviderConfiguration = new StandardParameterProviderConfiguration(versionedParameterContext.getParameterProvider(),
versionedParameterContext.getParameterGroupName(), versionedParameterContext.isSynchronized());
}
flowManager.createParameterContext(versionedParameterContext.getInstanceIdentifier(), versionedParameterContext.getName(), parameters, referenceIds,
parameterProviderConfiguration);
flowManager.createParameterContext(versionedParameterContext.getInstanceIdentifier(), versionedParameterContext.getName(), versionedParameterContext.getDescription(),
parameters, referenceIds, parameterProviderConfiguration);
logger.info("Added Parameter Context {}", versionedParameterContext.getName());
}

View File

@ -118,6 +118,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
@ -478,7 +479,7 @@ public class TestFlowController {
parameters.put("param", new Parameter(new ParameterDescriptor.Builder().name("param").build(), "value"));
// No problem since there are no inherited parameter contexts
controller.getFlowManager().createParameterContext("id", "name", parameters, Collections.emptyList(), null);
controller.getFlowManager().createParameterContext("id", "name", "description", parameters, Collections.emptyList(), null);
final ParameterContext existingParameterContext = controller.getFlowManager().getParameterContextManager().getParameterContext("context");
final ParameterContextReferenceDTO dto = new ParameterContextReferenceDTO();
@ -487,17 +488,40 @@ public class TestFlowController {
// This is not wrapped in FlowManager#withParameterContextResolution(Runnable), so it will throw an exception
assertThrows(IllegalStateException.class, () ->
controller.getFlowManager().createParameterContext("id", "name", parameters, Collections.singletonList(existingParameterContext.getIdentifier()), null));
controller.getFlowManager().createParameterContext("id", "name", "description", parameters, Collections.singletonList(existingParameterContext.getIdentifier()), null));
// Instead, this is how it should be called
controller.getFlowManager().withParameterContextResolution(() -> controller
.getFlowManager().createParameterContext("id2", "name2", parameters, Collections.singletonList(existingParameterContext.getIdentifier()), null));
.getFlowManager().createParameterContext("id2", "name2", "description2", parameters, Collections.singletonList(existingParameterContext.getIdentifier()), null));
} finally {
purgeFlow();
}
}
@Test
public void testCreateParameterContextLoadsDescription() throws IOException {
final String authFingerprint = authorizer.getFingerprint();
final File flowFile = new File("src/test/resources/conf/parameter-context-flow-description.json");
final String flow = IOUtils.toString(new FileInputStream(flowFile), StandardCharsets.UTF_8);
final DataFlow proposedDataFlow = new StandardDataFlow(flow.getBytes(StandardCharsets.UTF_8), null, authFingerprint.getBytes(StandardCharsets.UTF_8), Collections.emptySet());
try {
controller.synchronize(flowSynchronizer, proposedDataFlow, mock(FlowService.class), BundleUpdateStrategy.IGNORE_BUNDLE);
controller.initializeFlow();
ParameterContext parameterContext = controller.getFlowManager().getParameterContextManager().getParameterContext("context");
assertNotNull(parameterContext);
assertNull(parameterContext.getDescription());
ParameterContext parameterContext2 = controller.getFlowManager().getParameterContextManager().getParameterContext("context2");
assertNotNull(parameterContext2);
assertEquals("description", parameterContext2.getDescription());
} finally {
purgeFlow();
}
}
private void purgeFlow() {
final ProcessGroup processGroup = controller.getFlowManager().getRootGroup();
for (final ProcessorNode procNode : processGroup.getProcessors()) {

View File

@ -0,0 +1,60 @@
{
"encodingVersion": {
"majorVersion": 2,
"minorVersion": 0
},
"maxTimerDrivenThreadCount": 10,
"registries": [],
"parameterContexts": [
{
"identifier": "e5033705-0219-3aa5-88d4-542cd7f1c13d",
"instanceIdentifier": "context",
"name": "context",
"parameters": [],
"inheritedParameterContexts": [],
"componentType": "PARAMETER_CONTEXT"
},
{
"identifier": "8304c86e-2662-3f0b-9b54-153015055f25",
"instanceIdentifier": "context2",
"name": "context2",
"parameters": [],
"inheritedParameterContexts": [],
"description": "description",
"componentType": "PARAMETER_CONTEXT"
}
],
"parameterProviders": [],
"controllerServices": [],
"reportingTasks": [],
"flowAnalysisRules": [],
"rootGroup": {
"identifier": "55cf3437-cecb-3f77-806a-b742995a79b9",
"instanceIdentifier": "e6bf1066-018a-1000-97f3-ca4c6fe9e05c",
"name": "NiFi Flow",
"comments": "",
"position": {
"x": 0.0,
"y": 0.0
},
"processGroups": [],
"remoteProcessGroups": [],
"processors": [],
"inputPorts": [],
"outputPorts": [],
"connections": [],
"labels": [],
"funnels": [],
"controllerServices": [],
"defaultFlowFileExpiration": "0 sec",
"defaultBackPressureObjectThreshold": 10000,
"defaultBackPressureDataSizeThreshold": "1 GB",
"scheduledState": "ENABLED",
"executionEngine": "INHERITED",
"maxConcurrentTasks": 1,
"statelessFlowTimeout": "1 min",
"componentType": "PROCESS_GROUP",
"flowFileOutboundPolicy": "STREAM_WHEN_AVAILABLE",
"flowFileConcurrency": "UNBOUNDED"
}
}

View File

@ -99,7 +99,7 @@ public class StandardParameterContextDAO implements ParameterContextDAO {
final ParameterProviderConfiguration parameterProviderConfiguration = createParameterProviderConfiguration(parameterProviderConfigurationEntity);
final ParameterContext parameterContext = flowManager.createParameterContext(parameterContextDto.getId(), parameterContextDto.getName(),
parameters, referencedIds, parameterProviderConfiguration);
parameterContextDto.getDescription(), parameters, referencedIds, parameterProviderConfiguration);
if (parameterContextDto.getDescription() != null) {
parameterContext.setDescription(parameterContextDto.getDescription());
}