Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1838,7 +1838,16 @@ private ParameterContext getContainingParameterContext(final ParameterContext pa
return parameterContext;
}

return parameterContextDAO.getParameterContext(sourceContextId);
if (parameterContextDAO.hasParameterContext(sourceContextId)) {
try {
return parameterContextDAO.getParameterContext(sourceContextId);
} catch (final ResourceNotFoundException ignored) {
}
}

logger.warn("Parameter [{}] in Parameter Context [{}] references missing source Parameter Context [{}] and is not locally owned; reporting as locally defined",
parameter.getDescriptor().getName(), parameterContext.getIdentifier(), sourceContextId);
return parameterContext;
}

private void addReferencingComponents(final ControllerServiceNode service, final Set<ComponentNode> affectedComponents, final List<ParameterDTO> affectedParameterDtos,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@
import org.apache.nifi.util.FormatUtils;
import org.apache.nifi.util.security.MessageDigestUtils;
import org.apache.nifi.web.FlowModification;
import org.apache.nifi.web.ResourceNotFoundException;
import org.apache.nifi.web.Revision;
import org.apache.nifi.web.api.dto.SystemDiagnosticsSnapshotDTO.ResourceClaimDetailsDTO;
import org.apache.nifi.web.api.dto.action.ActionDTO;
Expand Down Expand Up @@ -1654,8 +1655,19 @@ private ParameterContext resolveContainingParameterContext(final ParameterContex
return fromGraph;
}

final ParameterContext fromLookup = parameterContextLookup.getParameterContext(sourceId);
return fromLookup != null ? fromLookup : parameterContext;
if (parameterContextLookup.hasParameterContext(sourceId)) {
try {
final ParameterContext fromLookup = parameterContextLookup.getParameterContext(sourceId);
if (fromLookup != null) {
return fromLookup;
}
} catch (final ResourceNotFoundException ignored) {
}
}

logger.warn("Parameter [{}] in Parameter Context [{}] references missing source Parameter Context [{}]; reporting as locally defined",
parameter.getDescriptor().getName(), parameterContext.getIdentifier(), sourceId);
return parameterContext;
}

private ParameterContext findInheritedParameterContext(final ParameterContext parameterContext, final String sourceId, final Set<String> visited) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -222,8 +222,6 @@ private Parameter createParameter(final ParameterDTO dto, final ParameterContext
final String dtoValue = dto.getValue();
final List<AssetReferenceDTO> referencedAssets = dto.getReferencedAssets();
final boolean referencesAsset = referencedAssets != null && !referencedAssets.isEmpty();
final String parameterContextId = dto.getParameterContext() == null ? null : dto.getParameterContext().getId();

final String value;
List<Asset> assets = null;
if (dtoValue == null && !referencesAsset && Boolean.TRUE.equals(dto.getValueRemoved())) {
Expand All @@ -245,7 +243,7 @@ private Parameter createParameter(final ParameterDTO dto, final ParameterContext
.name(dto.getName())
.description(dto.getDescription())
.sensitive(Boolean.TRUE.equals(dto.getSensitive()))
.parameterContextId(parameterContextId)
.parameterContextId(null)
.value(value)
.referencedAssets(assets)
.provided(dto.getProvided())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2531,6 +2531,7 @@ public void testGetComponentsAffectedByParameterContextUpdateTwicePreservesParam
final ParameterContextDAO parameterContextDAO = mock(ParameterContextDAO.class);
when(parameterContextDAO.getParameterContext(targetContextId)).thenReturn(targetContext);
when(parameterContextDAO.getParameterContext(inheritedContextId)).thenReturn(inheritedContext);
when(parameterContextDAO.hasParameterContext(inheritedContextId)).thenReturn(true);
when(parameterContextDAO.getParameters(any(ParameterContextDTO.class), same(targetContext))).thenReturn(Map.of());
when(parameterContextDAO.getInheritedParameterContexts(any(ParameterContextDTO.class))).thenReturn(List.of(inheritedContext));
when(targetContext.getEffectiveParameterUpdates(anyMap(), eq(List.of(inheritedContext))))
Expand Down Expand Up @@ -2623,6 +2624,134 @@ public void testGetComponentsAffectedByParameterContextUpdateTwicePreservesParam
assertFalse(secondPassParameters.containsKey(aliasParameterName));
}

@Test
public void testGetComponentsAffectedByParameterContextUpdateTwiceFallsBackWhenSourceContextDisappears() {
final String targetContextId = "target-context";
final String inheritedContextId = "inherited-context";
final String inheritedParameterName = "inherited-provider-param";
final String inheritedParameterValue = "provider-secret-value";
final String processorId = "processor-id";

final ParameterDescriptor inheritedDescriptor = new ParameterDescriptor.Builder().name(inheritedParameterName).build();
final Parameter inheritedParameter = new Parameter.Builder()
.descriptor(inheritedDescriptor)
.value(inheritedParameterValue)
.provided(true)
.parameterContextId(inheritedContextId)
.build();
final Parameter maskedInheritedParameter = new Parameter.Builder()
.descriptor(new ParameterDescriptor.Builder().name(inheritedParameterName).sensitive(true).build())
.value(inheritedParameterValue)
.provided(true)
.parameterContextId(inheritedContextId)
.build();

final ParameterContext inheritedContext = mock(ParameterContext.class);
when(inheritedContext.getIdentifier()).thenReturn(inheritedContextId);
when(inheritedContext.getName()).thenReturn("Inherited Context");
when(inheritedContext.getInheritedParameterContexts()).thenReturn(List.of());

final ParameterContext targetContext = mock(ParameterContext.class);
when(targetContext.getIdentifier()).thenReturn(targetContextId);
when(targetContext.getName()).thenReturn("Target Context");
when(targetContext.getParameters()).thenReturn(Map.of());
when(targetContext.getParameterReferenceManager()).thenReturn(ParameterReferenceManager.EMPTY);
when(targetContext.getInheritedParameterContexts()).thenReturn(List.of(inheritedContext));

final ParameterContextDAO parameterContextDAO = mock(ParameterContextDAO.class);
when(parameterContextDAO.getParameterContext(targetContextId)).thenReturn(targetContext);
when(parameterContextDAO.getParameters(any(ParameterContextDTO.class), same(targetContext))).thenReturn(Map.of());
when(parameterContextDAO.getInheritedParameterContexts(any(ParameterContextDTO.class))).thenReturn(List.of(inheritedContext));
when(targetContext.getEffectiveParameterUpdates(anyMap(), eq(List.of(inheritedContext))))
.thenReturn(Map.of(inheritedParameterName, inheritedParameter))
.thenReturn(Map.of(inheritedParameterName, maskedInheritedParameter));
when(parameterContextDAO.hasParameterContext(inheritedContextId)).thenReturn(true, true);
when(parameterContextDAO.getParameterContext(inheritedContextId))
.thenReturn(inheritedContext)
.thenThrow(new ResourceNotFoundException("Source context was removed"));

final ProcessorNode processorNode = mock(ProcessorNode.class);
when(processorNode.isRunning()).thenReturn(true);
when(processorNode.getReferencedParameterNames()).thenReturn(Set.of(inheritedParameterName));
when(processorNode.getIdentifier()).thenReturn(processorId);
when(processorNode.getName()).thenReturn("Processor");
when(processorNode.getProcessGroupIdentifier()).thenReturn("group-id");
when(processorNode.getDesiredState()).thenReturn(ScheduledState.STOPPED);
when(processorNode.getActiveThreadCount()).thenReturn(0);
when(processorNode.getValidationErrors()).thenReturn(List.of());

final ProcessGroup referencingGroup = mock(ProcessGroup.class);
when(referencingGroup.getParameterContext()).thenReturn(targetContext);
when(referencingGroup.getProcessors()).thenReturn(List.of(processorNode));
when(referencingGroup.getControllerServices(false)).thenReturn(Set.of());
when(referencingGroup.getExecutionEngine()).thenReturn(null);
when(referencingGroup.getParent()).thenReturn(null);
when(referencingGroup.getIdentifier()).thenReturn("group-id");
when(referencingGroup.getName()).thenReturn("Group");
when(referencingGroup.isAuthorized(any(), any(), any())).thenReturn(false);
when(processorNode.getProcessGroup()).thenReturn(referencingGroup);

final ProcessGroup rootGroup = mock(ProcessGroup.class);
when(processGroupDAO.getProcessGroup("root")).thenReturn(rootGroup);
when(rootGroup.findAllProcessGroups(any())).thenAnswer(invocation -> {
final java.util.function.Predicate<ProcessGroup> predicate = invocation.getArgument(0);
return predicate.test(referencingGroup) ? List.of(referencingGroup) : List.of();
});

final ParameterContextReferenceDTO inheritedReference = new ParameterContextReferenceDTO();
inheritedReference.setId(inheritedContextId);
inheritedReference.setName("Inherited Context");
final ParameterContextReferenceEntity inheritedReferenceEntity = new ParameterContextReferenceEntity();
inheritedReferenceEntity.setId(inheritedContextId);
inheritedReferenceEntity.setComponent(inheritedReference);

final ParameterContextDTO parameterContextDto = new ParameterContextDTO();
parameterContextDto.setId(targetContextId);
parameterContextDto.setName("Target Context");
parameterContextDto.setParameters(new HashSet<>());
parameterContextDto.setInheritedParameterContexts(List.of(inheritedReferenceEntity));

serviceFacade.setParameterContextDAO(parameterContextDAO);
serviceFacade.setRevisionManager(new NaiveRevisionManager());
final DtoFactory dtoFactory = new DtoFactory();
dtoFactory.setEntityFactory(new EntityFactory());
final BulletinRepository dtoBulletinRepository = mock(BulletinRepository.class);
when(dtoBulletinRepository.findBulletinsForSource(anyString(), anyString())).thenReturn(List.of());
dtoFactory.setBulletinRepository(dtoBulletinRepository);
serviceFacade.setDtoFactory(dtoFactory);

final Set<AffectedComponentEntity> firstAffected = serviceFacade.getComponentsAffectedByParameterContextUpdate(List.of(parameterContextDto));
assertEquals(1, firstAffected.size());
assertEquals(processorId, firstAffected.iterator().next().getId());

final Map<String, ParameterDTO> firstPassParameters = parameterContextDto.getParameters().stream()
.map(ParameterEntity::getParameter)
.collect(Collectors.toMap(ParameterDTO::getName, Function.identity()));
final ParameterDTO firstPassParameter = firstPassParameters.get(inheritedParameterName);
assertTrue(firstPassParameter.getInherited());
assertTrue(firstPassParameter.getProvided());
assertEquals(inheritedContextId, firstPassParameter.getParameterContext().getId());
assertEquals(inheritedParameterValue, firstPassParameter.getValue());

final Set<AffectedComponentEntity> secondAffected = serviceFacade.getComponentsAffectedByParameterContextUpdate(List.of(parameterContextDto));
assertEquals(1, secondAffected.size());
assertEquals(processorId, secondAffected.iterator().next().getId());

final Map<String, ParameterDTO> secondPassParameters = parameterContextDto.getParameters().stream()
.map(ParameterEntity::getParameter)
.collect(Collectors.toMap(ParameterDTO::getName, Function.identity()));
final ParameterDTO secondPassParameter = secondPassParameters.get(inheritedParameterName);
assertFalse(secondPassParameter.getInherited());
assertTrue(secondPassParameter.getProvided());
assertEquals(targetContextId, secondPassParameter.getParameterContext().getId());
assertEquals(inheritedParameterValue, secondPassParameter.getValue());
assertEquals(1, secondPassParameter.getReferencingComponents().size());
assertEquals(processorId, secondPassParameter.getReferencingComponents().iterator().next().getId());

verify(parameterContextDAO, times(2)).hasParameterContext(inheritedContextId);
verify(parameterContextDAO, times(2)).getParameterContext(inheritedContextId);
}

@Test
public void testGetComponentsAffectedByParameterContextUpdateDoesNotAddSensitiveLocalAliasToUpdate() {
final String targetContextId = "target-context";
Expand Down Expand Up @@ -3154,4 +3283,5 @@ private AssetManager configureAssets(final Asset asset, final ParameterContext p
serviceFacade.setParameterContextDAO(parameterContextDAO);
return assetManager;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import org.apache.nifi.registry.flow.FlowRegistryClientNode;
import org.apache.nifi.registry.flow.diff.DifferenceType;
import org.apache.nifi.registry.flow.diff.FlowDifference;
import org.apache.nifi.web.ResourceNotFoundException;
import org.apache.nifi.web.api.entity.AllowableValueEntity;
import org.apache.nifi.web.api.entity.ParameterContextReferenceEntity;
import org.apache.nifi.web.revision.RevisionManager;
Expand Down Expand Up @@ -878,6 +879,7 @@ void testCreateParameterDtoFallsBackToLookupWhenSourceNotReachableInGraph() {
.build();

final ParameterContextLookup lookup = mock(ParameterContextLookup.class);
when(lookup.hasParameterContext(externalId)).thenReturn(true);
when(lookup.getParameterContext(externalId)).thenReturn(externalContext);

final DtoFactory dtoFactory = newDtoFactoryForParameters();
Expand All @@ -886,6 +888,7 @@ void testCreateParameterDtoFallsBackToLookupWhenSourceNotReachableInGraph() {
assertTrue(dto.getInherited());
assertEquals(externalId, dto.getParameterContext().getId());

verify(lookup).hasParameterContext(externalId);
verify(lookup).getParameterContext(externalId);
}

Expand All @@ -909,6 +912,60 @@ void testCreateParameterDtoFallsBackToCurrentContextWhenSourceNotReachableInGrap
assertEquals(contextId, dto.getParameterContext().getId());
}

@Test
void testCreateParameterDtoFallsBackToCurrentContextWhenLookupReportsMissingSourceWithoutCallingGetter() {
final String contextId = "context-1";
final String missingSourceId = "context-missing";
final String parameterName = "param-name";

final ParameterContext parameterContext = createMockParameterContext(contextId, "context-1-name", Collections.emptyList());
final Parameter parameter = new Parameter.Builder()
.name(parameterName)
.value("param-value")
.parameterContextId(missingSourceId)
.build();

final ParameterContextLookup lookup = mock(ParameterContextLookup.class);
when(lookup.hasParameterContext(missingSourceId)).thenReturn(false);
when(lookup.getParameterContext(missingSourceId)).thenThrow(new AssertionError("Lookup getter should not be called for a missing source context"));

final DtoFactory dtoFactory = newDtoFactoryForParameters();
final ParameterDTO dto = dtoFactory.createParameterDto(parameterContext, parameter, mock(RevisionManager.class), lookup);

assertFalse(dto.getInherited());
assertEquals(contextId, dto.getParameterContext().getId());

verify(lookup).hasParameterContext(missingSourceId);
verify(lookup, never()).getParameterContext(missingSourceId);
}

@Test
void testCreateParameterDtoFallsBackToCurrentContextWhenSourceDisappearsDuringLookup() {
final String contextId = "context-1";
final String missingSourceId = "context-missing";
final String parameterName = "param-name";

final ParameterContext parameterContext = createMockParameterContext(contextId, "context-1-name", Collections.emptyList());
final Parameter parameter = new Parameter.Builder()
.name(parameterName)
.value("param-value")
.parameterContextId(missingSourceId)
.build();

final ParameterContextLookup lookup = mock(ParameterContextLookup.class);
when(lookup.hasParameterContext(missingSourceId)).thenReturn(true);
when(lookup.getParameterContext(missingSourceId)).thenThrow(new ResourceNotFoundException("Source context was removed"));

final DtoFactory dtoFactory = newDtoFactoryForParameters();
final ParameterDTO dto = dtoFactory.createParameterDto(parameterContext, parameter, mock(RevisionManager.class), lookup);

assertFalse(dto.getInherited());
assertEquals(contextId, dto.getParameterContext().getId());

verify(lookup).hasParameterContext(missingSourceId);
verify(lookup).getParameterContext(missingSourceId);
}

@Test
void testCreateParameterDtoResolvesSourceContextFromDiamondInheritanceGraph() {
final String contextAId = "context-a";
Expand Down Expand Up @@ -955,6 +1012,7 @@ void testCreateParameterDtoInheritanceGraphHandlesCycles() {

final ParameterContext fallbackContext = createMockParameterContext(missingId, "missing", Collections.emptyList());
final ParameterContextLookup lookup = mock(ParameterContextLookup.class);
when(lookup.hasParameterContext(missingId)).thenReturn(true);
when(lookup.getParameterContext(missingId)).thenReturn(fallbackContext);

final DtoFactory dtoFactory = newDtoFactoryForParameters();
Expand All @@ -963,6 +1021,7 @@ void testCreateParameterDtoInheritanceGraphHandlesCycles() {
assertTrue(dto.getInherited());
assertEquals(missingId, dto.getParameterContext().getId());

verify(lookup).hasParameterContext(missingId);
verify(lookup).getParameterContext(missingId);
}

Expand Down Expand Up @@ -1002,4 +1061,5 @@ private static void configureBaseParameterContext(final ParameterContext context
when(context.getName()).thenReturn(name);
when(context.getParameterReferenceManager()).thenReturn(ParameterReferenceManager.EMPTY);
}

}
Loading
Loading