mirror of https://github.com/apache/nifi.git
NIFI-8491: Adding support for configuring parameter context inheritance (#5371)
* NIFI-8491: - Adding support for configuring parameter context inheritance. * NIFI-8491: - Allowing changes to the parameter context inheritance to drive Apply disabled state. * NIFI-8491: Updating StandardParameterContext#isAuthorized check * NIFI-8491: - Showing selected inherited parameter contexts in ready only form when appropriate. - Allowing available parameter contexts to be inherited by double clicking. - Removing support for rendering unauthorized inherited parameter contexts as they can no longer be opened. * NIFI-8491: Adding inherited param context verification earlier * NIFI-8491: - Addressing CI failures by rolling back to some order JS language spec to allow yui-compress to minify and compress. * NIFI-8491: - Ensuring selected context sort order is honored. - Ensuring the Apply button is correctly enabled. - Showing Pending Apply message when selected Parameter Context changes. - Ensuring the Parameter's tab is selected now that there is a third tab. * Updates to inherited param context verification * Improving validation between parameters/inherited parameters * NIFI-8491: - Ensuring the available parameter contexts are loaded whether the edit dialog is opened from the listing or outside of the listing. * NIFI-8491: - Fixing conditions we check if the parameter context listing is currently open. * NIFI-8491: - Waiting for the parameter contexts to load prior to rendering the parameter context inheritance tab and showing the dialog. * NIFI-8491: - Fixing pending apply message clipping. - Hiding pending apply message after clicking Apply. Co-authored-by: Joe Gresock <jgresock@gmail.com> This closes #5371
This commit is contained in:
parent
46a5e3f096
commit
be57a210ff
|
@ -32,6 +32,7 @@ public class ParameterDTO {
|
|||
private Boolean valueRemoved;
|
||||
private Set<AffectedComponentEntity> referencingComponents;
|
||||
private ParameterContextReferenceEntity parameterContext;
|
||||
private Boolean inherited;
|
||||
|
||||
@ApiModelProperty("The name of the Parameter")
|
||||
public String getName() {
|
||||
|
@ -42,6 +43,15 @@ public class ParameterDTO {
|
|||
this.name = name;
|
||||
}
|
||||
|
||||
@ApiModelProperty(value = "Whether or not the Parameter is inherited from another context", accessMode = ApiModelProperty.AccessMode.READ_ONLY)
|
||||
public Boolean getInherited() {
|
||||
return inherited;
|
||||
}
|
||||
|
||||
public void setInherited(final Boolean inherited) {
|
||||
this.inherited = inherited;
|
||||
}
|
||||
|
||||
@ApiModelProperty("The description of the Parameter")
|
||||
public String getDescription() {
|
||||
return description;
|
||||
|
|
|
@ -35,6 +35,7 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
|
@ -123,7 +124,7 @@ public class StandardParameterContext implements ParameterContext {
|
|||
|
||||
final Map<String, Parameter> effectiveParameterUpdates = getEffectiveParameterUpdates(currentEffectiveParameters, effectiveProposedParameters);
|
||||
|
||||
verifyCanSetParameters(effectiveParameterUpdates);
|
||||
verifyCanSetParameters(effectiveParameterUpdates, true);
|
||||
|
||||
// Update the actual parameters
|
||||
updateParameters(parameters, updatedParameters, true);
|
||||
|
@ -339,6 +340,17 @@ public class StandardParameterContext implements ParameterContext {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Parameter> getEffectiveParameterUpdates(final Map<String, Parameter> parameterUpdates, final List<ParameterContext> inheritedParameterContexts) {
|
||||
Objects.requireNonNull(parameterUpdates, "Parameter Updates must be specified");
|
||||
Objects.requireNonNull(inheritedParameterContexts, "Inherited parameter contexts must be specified");
|
||||
|
||||
final Map<ParameterDescriptor, Parameter> currentEffectiveParameters = getEffectiveParameters();
|
||||
final Map<ParameterDescriptor, Parameter> effectiveProposedParameters = getEffectiveParameters(inheritedParameterContexts, getProposedParameters(parameterUpdates), new HashMap<>());
|
||||
|
||||
return getEffectiveParameterUpdates(currentEffectiveParameters, effectiveProposedParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an effective view of the parameters, including nested parameters, assuming the given map of parameters.
|
||||
* This allows an inspection of what parameters would be available if the given parameters were set in this ParameterContext.
|
||||
|
@ -373,15 +385,23 @@ public class StandardParameterContext implements ParameterContext {
|
|||
// Loop backwards so that the first ParameterContext in the list will override any parameters later in the list
|
||||
for(int i = parameterContexts.size() - 1; i >= 0; i--) {
|
||||
ParameterContext parameterContext = parameterContexts.get(i);
|
||||
allOverrides.putAll(overrideParameters(effectiveParameters, parameterContext.getEffectiveParameters(), parameterContext));
|
||||
combineOverrides(allOverrides, overrideParameters(effectiveParameters, parameterContext.getEffectiveParameters(), parameterContext));
|
||||
}
|
||||
|
||||
// Finally, override all child parameters with our own
|
||||
allOverrides.putAll(overrideParameters(effectiveParameters, proposedParameters, this));
|
||||
combineOverrides(allOverrides, overrideParameters(effectiveParameters, proposedParameters, this));
|
||||
|
||||
return effectiveParameters;
|
||||
}
|
||||
|
||||
private void combineOverrides(final Map<ParameterDescriptor, List<Parameter>> existingOverrides, final Map<ParameterDescriptor, List<Parameter>> newOverrides) {
|
||||
for (final Map.Entry<ParameterDescriptor, List<Parameter>> entry : newOverrides.entrySet()) {
|
||||
final ParameterDescriptor key = entry.getKey();
|
||||
final List<Parameter> existingOverrideList = existingOverrides.computeIfAbsent(key, k -> new ArrayList<>());
|
||||
existingOverrideList.addAll(entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private Map<ParameterDescriptor, List<Parameter>> overrideParameters(final Map<ParameterDescriptor, Parameter> existingParameters,
|
||||
final Map<ParameterDescriptor, Parameter> overridingParameters,
|
||||
final ParameterContext overridingContext) {
|
||||
|
@ -456,32 +476,49 @@ public class StandardParameterContext implements ParameterContext {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void verifyCanUpdateParameterContext(final Map<String, Parameter> parameterUpdates, final List<ParameterContext> inheritedParameterContexts) {
|
||||
verifyCanUpdateParameterContext(parameterUpdates, inheritedParameterContexts, false);
|
||||
}
|
||||
|
||||
private void verifyCanUpdateParameterContext(final Map<String, Parameter> parameterUpdates, final List<ParameterContext> inheritedParameterContexts, final boolean duringUpdate) {
|
||||
if (inheritedParameterContexts == null) {
|
||||
return;
|
||||
}
|
||||
verifyNoCycles(inheritedParameterContexts);
|
||||
|
||||
final Map<ParameterDescriptor, Parameter> currentEffectiveParameters = getEffectiveParameters();
|
||||
final Map<ParameterDescriptor, Parameter> effectiveProposedParameters = getEffectiveParameters(inheritedParameterContexts, getProposedParameters(parameterUpdates), new HashMap<>());
|
||||
final Map<String, Parameter> effectiveParameterUpdates = getEffectiveParameterUpdates(currentEffectiveParameters, effectiveProposedParameters);
|
||||
|
||||
try {
|
||||
verifyCanSetParameters(currentEffectiveParameters, effectiveParameterUpdates, duringUpdate);
|
||||
} catch (final IllegalStateException e) {
|
||||
// Wrap with a more accurate message
|
||||
throw new IllegalStateException(String.format("Could not update inherited Parameter Contexts for Parameter Context [%s] because: %s",
|
||||
name, e.getMessage()), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInheritedParameterContexts(final List<ParameterContext> inheritedParameterContexts) {
|
||||
if (inheritedParameterContexts.equals(this.inheritedParameterContexts)) {
|
||||
if (inheritedParameterContexts == null || inheritedParameterContexts.equals(this.inheritedParameterContexts)) {
|
||||
// No changes
|
||||
return;
|
||||
}
|
||||
|
||||
verifyCanUpdateParameterContext(Collections.emptyMap(), inheritedParameterContexts, true);
|
||||
|
||||
final Map<String, ParameterUpdate> parameterUpdates = new HashMap<>();
|
||||
|
||||
writeLock.lock();
|
||||
try {
|
||||
this.version++;
|
||||
verifyNoCycles(inheritedParameterContexts);
|
||||
|
||||
final Map<ParameterDescriptor, Parameter> currentEffectiveParameters = getEffectiveParameters();
|
||||
final Map<ParameterDescriptor, Parameter> effectiveProposedParameters = getEffectiveParameters(inheritedParameterContexts);
|
||||
final Map<String, Parameter> effectiveParameterUpdates = getEffectiveParameterUpdates(currentEffectiveParameters, effectiveProposedParameters);
|
||||
|
||||
try {
|
||||
verifyCanSetParameters(currentEffectiveParameters, effectiveParameterUpdates);
|
||||
} catch (final IllegalStateException e) {
|
||||
// Wrap with a more accurate message
|
||||
throw new IllegalStateException(String.format("Could not update inherited Parameter Contexts for Parameter Context [%s] because: %s",
|
||||
name, e.getMessage()), e);
|
||||
}
|
||||
|
||||
this.inheritedParameterContexts.clear();
|
||||
|
||||
this.inheritedParameterContexts.addAll(inheritedParameterContexts);
|
||||
|
@ -570,17 +607,30 @@ public class StandardParameterContext implements ParameterContext {
|
|||
|
||||
@Override
|
||||
public void verifyCanSetParameters(final Map<String, Parameter> updatedParameters) {
|
||||
verifyCanSetParameters(parameters, updatedParameters);
|
||||
verifyCanSetParameters(updatedParameters, false);
|
||||
}
|
||||
|
||||
public void verifyCanSetParameters(final Map<ParameterDescriptor, Parameter> currentParameters, final Map<String, Parameter> updatedParameters) {
|
||||
/**
|
||||
* Ensures that it is legal to update the Parameters for this Parameter Context to match the given set of Parameters
|
||||
* @param updatedParameters the updated set of parameters, keyed by Parameter name
|
||||
* @param duringUpdate If true, this check will be treated as if a ParameterContext update is imminent, meaning
|
||||
* referencing components may not be active even for updated values. If false, a parameter
|
||||
* value update will be valid even if referencing components are active because it will be
|
||||
* assumed that these will be stopped prior to the actual update.
|
||||
* @throws IllegalStateException if setting the given set of Parameters is not legal
|
||||
*/
|
||||
public void verifyCanSetParameters(final Map<String, Parameter> updatedParameters, final boolean duringUpdate) {
|
||||
verifyCanSetParameters(parameters, updatedParameters, duringUpdate);
|
||||
}
|
||||
|
||||
public void verifyCanSetParameters(final Map<ParameterDescriptor, Parameter> currentParameters, final Map<String, Parameter> updatedParameters, final boolean duringUpdate) {
|
||||
// Ensure that the updated parameters will not result in changing the sensitivity flag of any parameter.
|
||||
for (final Map.Entry<String, Parameter> entry : updatedParameters.entrySet()) {
|
||||
final String parameterName = entry.getKey();
|
||||
final Parameter parameter = entry.getValue();
|
||||
if (parameter == null) {
|
||||
// parameter is being deleted.
|
||||
validateReferencingComponents(parameterName, null,"remove");
|
||||
validateReferencingComponents(parameterName, null, duringUpdate);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -589,7 +639,7 @@ public class StandardParameterContext implements ParameterContext {
|
|||
}
|
||||
|
||||
validateSensitiveFlag(currentParameters, parameter);
|
||||
validateReferencingComponents(parameterName, parameter, "update");
|
||||
validateReferencingComponents(parameterName, parameter, duringUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -611,11 +661,12 @@ public class StandardParameterContext implements ParameterContext {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private void validateReferencingComponents(final String parameterName, final Parameter parameter, final String parameterAction) {
|
||||
private void validateReferencingComponents(final String parameterName, final Parameter parameter, final boolean duringUpdate) {
|
||||
final boolean isDeletion = (parameter == null);
|
||||
final String action = isDeletion ? "remove" : "update";
|
||||
for (final ProcessorNode procNode : parameterReferenceManager.getProcessorsReferencing(this, parameterName)) {
|
||||
if (procNode.isRunning()) {
|
||||
throw new IllegalStateException("Cannot " + parameterAction + " parameter '" + parameterName + "' because it is referenced by " + procNode + ", which is currently running");
|
||||
if (procNode.isRunning() && (isDeletion || duringUpdate)) {
|
||||
throw new IllegalStateException("Cannot " + action + " parameter '" + parameterName + "' because it is referenced by " + procNode + ", which is currently running");
|
||||
}
|
||||
|
||||
if (parameter != null) {
|
||||
|
@ -625,9 +676,9 @@ public class StandardParameterContext implements ParameterContext {
|
|||
|
||||
for (final ControllerServiceNode serviceNode : parameterReferenceManager.getControllerServicesReferencing(this, parameterName)) {
|
||||
final ControllerServiceState serviceState = serviceNode.getState();
|
||||
if (serviceState != ControllerServiceState.DISABLED) {
|
||||
throw new IllegalStateException("Cannot " + parameterAction + " parameter '" + parameterName + "' because it is referenced by "
|
||||
+ serviceNode + ", which currently has a state of " + serviceState);
|
||||
if (serviceState != ControllerServiceState.DISABLED && (isDeletion || duringUpdate)) {
|
||||
throw new IllegalStateException("Cannot " + action + " parameter '" + parameterName + "' because it is referenced by "
|
||||
+ serviceNode + ", which currently has a state of " + serviceState);
|
||||
}
|
||||
|
||||
if (parameter != null) {
|
||||
|
@ -678,6 +729,22 @@ public class StandardParameterContext implements ParameterContext {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAuthorized(final Authorizer authorizer, final RequestAction action, final NiFiUser user) {
|
||||
boolean isAuthorized = ParameterContext.super.isAuthorized(authorizer, action, user);
|
||||
|
||||
if (RequestAction.READ == action) {
|
||||
for (final ParameterContext parameterContext : inheritedParameterContexts) {
|
||||
isAuthorized &= parameterContext.isAuthorized(authorizer, action, user);
|
||||
if (!isAuthorized) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return isAuthorized;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Authorizable getParentAuthorizable() {
|
||||
return new Authorizable() {
|
||||
|
|
|
@ -109,12 +109,29 @@ public interface ParameterContext extends ParameterLookup, ComponentAuthorizable
|
|||
*/
|
||||
Map<ParameterDescriptor, Parameter> getEffectiveParameters();
|
||||
|
||||
/**
|
||||
* Returns the resulting map of effective parameter updates if the given parameter updates and inherited parameter contexts were to be applied.
|
||||
* This allows potential changes to be detected before actually applying the parameter updates.
|
||||
* @param parameterUpdates A map from parameter name to updated parameter (null if removal is desired)
|
||||
* @param inheritedParameterContexts An ordered list of parameter contexts to inherit from
|
||||
* @return The effective map of parameter updates that would result if these changes were applied. This includes only parameters that would
|
||||
* be effectively updated or removed, and is mapped by parameter name
|
||||
*/
|
||||
Map<String, Parameter> getEffectiveParameterUpdates(Map<String, Parameter> parameterUpdates, List<ParameterContext> inheritedParameterContexts);
|
||||
|
||||
/**
|
||||
* Returns the ParameterReferenceManager that is associated with this ParameterContext
|
||||
* @return the ParameterReferenceManager that is associated with this ParameterContext
|
||||
*/
|
||||
ParameterReferenceManager getParameterReferenceManager();
|
||||
|
||||
/**
|
||||
* Verifies whether the parameter context can be updated with the provided parameters and inherited parameter contexts.
|
||||
* @param parameterUpdates A map from parameter name to updated parameter (null if removal is desired)
|
||||
* @param inheritedParameterContexts the list of ParameterContexts from which to inherit parameters
|
||||
*/
|
||||
void verifyCanUpdateParameterContext(Map<String, Parameter> parameterUpdates, List<ParameterContext> inheritedParameterContexts);
|
||||
|
||||
/**
|
||||
* Updates the ParameterContexts within this context to match the given list of ParameterContexts. All parameter in these
|
||||
* ParameterContexts are inherited by this ParameterContext, and can be referenced as if they were actually in this ParameterContext.
|
||||
|
@ -125,7 +142,7 @@ public interface ParameterContext extends ParameterLookup, ComponentAuthorizable
|
|||
*
|
||||
* @param inheritedParameterContexts the list of ParameterContexts from which to inherit parameters, in priority order first to last
|
||||
* @throws IllegalStateException if the list of ParameterContexts is invalid (in case of a circular reference or
|
||||
* in case {@link #verifyCanSetParameters(Map)} verifyCanSetParameters} would throw an exception)
|
||||
* in case {@link #verifyCanSetParameters(Map) verifyCanSetParameters} would throw an exception)
|
||||
*/
|
||||
void setInheritedParameterContexts(List<ParameterContext> inheritedParameterContexts);
|
||||
|
||||
|
|
|
@ -91,6 +91,14 @@ import org.apache.nifi.controller.status.ProcessGroupStatus;
|
|||
import org.apache.nifi.controller.status.ProcessorStatus;
|
||||
import org.apache.nifi.diagnostics.SystemDiagnostics;
|
||||
import org.apache.nifi.events.BulletinFactory;
|
||||
import org.apache.nifi.flow.VersionedComponent;
|
||||
import org.apache.nifi.flow.VersionedConfigurableComponent;
|
||||
import org.apache.nifi.flow.VersionedConnection;
|
||||
import org.apache.nifi.flow.VersionedControllerService;
|
||||
import org.apache.nifi.flow.VersionedFlowCoordinates;
|
||||
import org.apache.nifi.flow.VersionedProcessGroup;
|
||||
import org.apache.nifi.flow.VersionedProcessor;
|
||||
import org.apache.nifi.flow.VersionedPropertyDescriptor;
|
||||
import org.apache.nifi.groups.ProcessGroup;
|
||||
import org.apache.nifi.groups.ProcessGroupCounts;
|
||||
import org.apache.nifi.groups.RemoteProcessGroup;
|
||||
|
@ -119,19 +127,11 @@ import org.apache.nifi.registry.flow.FlowRegistry;
|
|||
import org.apache.nifi.registry.flow.FlowRegistryClient;
|
||||
import org.apache.nifi.registry.flow.RestBasedFlowRegistry;
|
||||
import org.apache.nifi.registry.flow.VersionControlInformation;
|
||||
import org.apache.nifi.flow.VersionedComponent;
|
||||
import org.apache.nifi.flow.VersionedConfigurableComponent;
|
||||
import org.apache.nifi.flow.VersionedConnection;
|
||||
import org.apache.nifi.flow.VersionedControllerService;
|
||||
import org.apache.nifi.registry.flow.VersionedFlow;
|
||||
import org.apache.nifi.flow.VersionedFlowCoordinates;
|
||||
import org.apache.nifi.registry.flow.VersionedFlowSnapshot;
|
||||
import org.apache.nifi.registry.flow.VersionedFlowSnapshotMetadata;
|
||||
import org.apache.nifi.registry.flow.VersionedFlowState;
|
||||
import org.apache.nifi.registry.flow.VersionedParameterContext;
|
||||
import org.apache.nifi.flow.VersionedProcessGroup;
|
||||
import org.apache.nifi.flow.VersionedProcessor;
|
||||
import org.apache.nifi.flow.VersionedPropertyDescriptor;
|
||||
import org.apache.nifi.registry.flow.diff.ComparableDataFlow;
|
||||
import org.apache.nifi.registry.flow.diff.ConciseEvolvingDifferenceDescriptor;
|
||||
import org.apache.nifi.registry.flow.diff.DifferenceType;
|
||||
|
@ -1315,6 +1315,8 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
|||
group -> group.getParameterContext() != null && (group.getParameterContext().getIdentifier().equals(parameterContextDto.getId())
|
||||
|| group.getParameterContext().inheritsFrom(parameterContext.getIdentifier())));
|
||||
|
||||
setEffectiveParameterUpdates(parameterContextDto);
|
||||
|
||||
final Set<String> updatedParameterNames = getUpdatedParameterNames(parameterContextDto);
|
||||
|
||||
// Clear set of Affected Components for each Parameter. This parameter is read-only and it will be populated below.
|
||||
|
@ -1371,6 +1373,39 @@ public class StandardNiFiServiceFacade implements NiFiServiceFacade {
|
|||
return dtoFactory.createAffectedComponentEntities(affectedComponents, revisionManager);
|
||||
}
|
||||
|
||||
private void setEffectiveParameterUpdates(final ParameterContextDTO parameterContextDto) {
|
||||
final ParameterContext parameterContext = parameterContextDAO.getParameterContext(parameterContextDto.getId());
|
||||
|
||||
final Map<String, Parameter> parameterUpdates = parameterContextDAO.getParameters(parameterContextDto, parameterContext);
|
||||
final List<ParameterContext> inheritedParameterContexts = parameterContextDAO.getInheritedParameterContexts(parameterContextDto);
|
||||
final Map<String, Parameter> proposedParameterUpdates = parameterContext.getEffectiveParameterUpdates(parameterUpdates, inheritedParameterContexts);
|
||||
final Map<String, ParameterEntity> parameterEntities = parameterContextDto.getParameters().stream()
|
||||
.collect(Collectors.toMap(entity -> entity.getParameter().getName(), Function.identity()));
|
||||
parameterContextDto.getParameters().clear();
|
||||
|
||||
for (final Map.Entry<String, Parameter> entry : proposedParameterUpdates.entrySet()) {
|
||||
final String parameterName = entry.getKey();
|
||||
final Parameter parameter = entry.getValue();
|
||||
final ParameterEntity parameterEntity;
|
||||
if (parameterEntities.containsKey(parameterName)) {
|
||||
parameterEntity = parameterEntities.get(parameterName);
|
||||
} else if (parameter == null) {
|
||||
parameterEntity = new ParameterEntity();
|
||||
final ParameterDTO parameterDTO = new ParameterDTO();
|
||||
parameterDTO.setName(parameterName);
|
||||
parameterEntity.setParameter(parameterDTO);
|
||||
} else {
|
||||
parameterEntity = dtoFactory.createParameterEntity(parameterContext, parameter, revisionManager, parameterContextDAO);
|
||||
}
|
||||
|
||||
// Parameter is inherited if either this is the removal of a parameter not directly in this context, or it's parameter not specified directly in the DTO
|
||||
final boolean isInherited = (parameter == null && !parameterContext.getParameters().containsKey(new ParameterDescriptor.Builder().name(parameterName).build()))
|
||||
|| (parameter != null && !parameterEntities.containsKey(parameterName));
|
||||
parameterEntity.getParameter().setInherited(isInherited);
|
||||
parameterContextDto.getParameters().add(parameterEntity);
|
||||
}
|
||||
}
|
||||
|
||||
private void addReferencingComponents(final ControllerServiceNode service, final Set<ComponentNode> affectedComponents, final List<ParameterDTO> affectedParameterDtos,
|
||||
final boolean includeInactive) {
|
||||
|
||||
|
|
|
@ -575,7 +575,7 @@ public final class EntityFactory {
|
|||
final ParameterContextEntity entity = new ParameterContextEntity();
|
||||
entity.setRevision(revision);
|
||||
if (dto != null) {
|
||||
entity.setPermissions(permissions);;
|
||||
entity.setPermissions(permissions);
|
||||
entity.setId(dto.getId());
|
||||
|
||||
if (permissions != null && permissions.getCanRead()) {
|
||||
|
|
|
@ -16,10 +16,13 @@
|
|||
*/
|
||||
package org.apache.nifi.web.dao;
|
||||
|
||||
import org.apache.nifi.parameter.Parameter;
|
||||
import org.apache.nifi.parameter.ParameterContext;
|
||||
import org.apache.nifi.parameter.ParameterContextLookup;
|
||||
import org.apache.nifi.web.api.dto.ParameterContextDTO;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public interface ParameterContextDAO extends ParameterContextLookup {
|
||||
|
@ -39,6 +42,14 @@ public interface ParameterContextDAO extends ParameterContextLookup {
|
|||
*/
|
||||
ParameterContext createParameterContext(ParameterContextDTO parameterContextDto);
|
||||
|
||||
/**
|
||||
* Returns a map from parameter name to intended parameter, given the DTO.
|
||||
* @param parameterContextDto A parameter context DTO containing parameter updates
|
||||
* @param context The existing parameter context
|
||||
* @return The resulting parameter map containing updated parameters (or removals)
|
||||
*/
|
||||
Map<String, Parameter> getParameters(ParameterContextDTO parameterContextDto, ParameterContext context);
|
||||
|
||||
/**
|
||||
* Gets all of the parameter contexts.
|
||||
*
|
||||
|
@ -54,6 +65,13 @@ public interface ParameterContextDAO extends ParameterContextLookup {
|
|||
*/
|
||||
ParameterContext updateParameterContext(ParameterContextDTO parameterContextDto);
|
||||
|
||||
/**
|
||||
* Returns a list of the inherited parameter contexts proposed by the DTO.
|
||||
* @param parameterContextDto The parameter context DTO
|
||||
* @return a list of the inherited parameter contexts proposed by the DTO
|
||||
*/
|
||||
List<ParameterContext> getInheritedParameterContexts(ParameterContextDTO parameterContextDto);
|
||||
|
||||
/**
|
||||
* Determines whether this parameter context can be updated.
|
||||
*
|
||||
|
|
|
@ -20,11 +20,8 @@ import org.apache.nifi.authorization.Authorizer;
|
|||
import org.apache.nifi.authorization.RequestAction;
|
||||
import org.apache.nifi.authorization.user.NiFiUser;
|
||||
import org.apache.nifi.authorization.user.NiFiUserUtils;
|
||||
import org.apache.nifi.components.PropertyDescriptor;
|
||||
import org.apache.nifi.controller.ComponentNode;
|
||||
import org.apache.nifi.controller.FlowController;
|
||||
import org.apache.nifi.controller.ProcessorNode;
|
||||
import org.apache.nifi.controller.PropertyConfiguration;
|
||||
import org.apache.nifi.controller.flow.FlowManager;
|
||||
import org.apache.nifi.controller.service.ControllerServiceNode;
|
||||
import org.apache.nifi.controller.service.ControllerServiceState;
|
||||
|
@ -32,8 +29,6 @@ import org.apache.nifi.groups.ProcessGroup;
|
|||
import org.apache.nifi.parameter.Parameter;
|
||||
import org.apache.nifi.parameter.ParameterContext;
|
||||
import org.apache.nifi.parameter.ParameterDescriptor;
|
||||
import org.apache.nifi.parameter.ParameterReference;
|
||||
import org.apache.nifi.parameter.ParameterReferenceManager;
|
||||
import org.apache.nifi.web.ResourceNotFoundException;
|
||||
import org.apache.nifi.web.api.dto.ParameterContextDTO;
|
||||
import org.apache.nifi.web.api.dto.ParameterContextReferenceDTO;
|
||||
|
@ -73,7 +68,7 @@ public class StandardParameterContextDAO implements ParameterContextDAO {
|
|||
if (inheritedParameterContexts != null) {
|
||||
resolveInheritedParameterContexts(parameterContextDto);
|
||||
// This will throw an exception if one is not found
|
||||
inheritedParameterContexts.stream().forEach(entity -> flowManager.getParameterContextManager()
|
||||
inheritedParameterContexts.forEach(entity -> flowManager.getParameterContextManager()
|
||||
.getParameterContext(entity.getComponent().getId()));
|
||||
}
|
||||
authorizeReferences(parameterContextDto);
|
||||
|
@ -136,7 +131,8 @@ public class StandardParameterContextDAO implements ParameterContextDAO {
|
|||
}
|
||||
}
|
||||
|
||||
private Map<String, Parameter> getParameters(final ParameterContextDTO parameterContextDto, final ParameterContext context) {
|
||||
@Override
|
||||
public Map<String, Parameter> getParameters(final ParameterContextDTO parameterContextDto, final ParameterContext context) {
|
||||
final Set<ParameterEntity> parameterEntities = parameterContextDto.getParameters();
|
||||
if (parameterEntities == null) {
|
||||
return Collections.emptyMap();
|
||||
|
@ -146,6 +142,11 @@ public class StandardParameterContextDAO implements ParameterContextDAO {
|
|||
for (final ParameterEntity parameterEntity : parameterEntities) {
|
||||
final ParameterDTO parameterDto = parameterEntity.getParameter();
|
||||
|
||||
// Inherited parameters are only included for referencing components, but we should not save them as direct parameters
|
||||
if (parameterDto.getInherited() != null && parameterDto.getInherited()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (parameterDto.getName() == null) {
|
||||
throw new IllegalArgumentException("Cannot specify a Parameter without a name");
|
||||
}
|
||||
|
@ -226,7 +227,8 @@ public class StandardParameterContextDAO implements ParameterContextDAO {
|
|||
return context;
|
||||
}
|
||||
|
||||
private List<ParameterContext> getInheritedParameterContexts(final ParameterContextDTO parameterContextDto) {
|
||||
@Override
|
||||
public List<ParameterContext> getInheritedParameterContexts(final ParameterContextDTO parameterContextDto) {
|
||||
resolveInheritedParameterContexts(parameterContextDto);
|
||||
|
||||
final List<ParameterContext> inheritedParameterContexts = new ArrayList<>();
|
||||
|
@ -243,76 +245,10 @@ public class StandardParameterContextDAO implements ParameterContextDAO {
|
|||
verifyInheritedParameterContextRefs(parameterContextDto);
|
||||
|
||||
final ParameterContext currentContext = getParameterContext(parameterContextDto.getId());
|
||||
for (final ParameterEntity parameterEntity : parameterContextDto.getParameters()) {
|
||||
final ParameterDTO parameterDto = parameterEntity.getParameter();
|
||||
final String parameterName = parameterDto.getName();
|
||||
final ParameterReferenceManager referenceManager = currentContext.getParameterReferenceManager();
|
||||
|
||||
for (final ProcessorNode processor : referenceManager.getProcessorsReferencing(currentContext, parameterName)) {
|
||||
verifyParameterUpdate(parameterDto, processor, currentContext.getName(), verifyComponentStates, processor.isRunning(), "Processor that is running");
|
||||
}
|
||||
|
||||
final Set<ControllerServiceNode> referencingServices = referenceManager.getControllerServicesReferencing(currentContext, parameterName);
|
||||
for (final ControllerServiceNode serviceNode : referencingServices) {
|
||||
final ControllerServiceState serviceState = serviceNode.getState();
|
||||
final boolean serviceActive = serviceState != ControllerServiceState.DISABLED;
|
||||
|
||||
verifyParameterUpdate(parameterDto, serviceNode, currentContext.getName(), verifyComponentStates, serviceActive,
|
||||
"Controller Service [id=" + serviceNode.getIdentifier() + "] with a state of " + serviceState + " (state expected to be DISABLED)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void verifyParameterUpdate(final ParameterDTO parameterDto, final ComponentNode component, final String contextName,
|
||||
final boolean verifyComponentStates, final boolean active, final String activeExplanation) {
|
||||
|
||||
final String parameterName = parameterDto.getName();
|
||||
final Boolean parameterSensitive = parameterDto.getSensitive();
|
||||
final boolean parameterDeletion = parameterDto.getDescription() == null && parameterDto.getSensitive() == null && parameterDto.getValue() == null;
|
||||
|
||||
// For any parameter that is added or modified, we need to ensure that the new configuration will not result in a Sensitive Parameter being referenced by a non-Sensitive Property
|
||||
// or a Non-Sensitive Parameter being referenced by a Sensitive Property.
|
||||
// Additionally, if 'verifyComponentStates' or parameter is being deleted, we must ensure that any component that references a value that is to be updated
|
||||
// is stopped (if a processor) or disabled (if a controller service).
|
||||
for (final Map.Entry<PropertyDescriptor, PropertyConfiguration> entry : component.getProperties().entrySet()) {
|
||||
final PropertyConfiguration configuration = entry.getValue();
|
||||
if (configuration == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (final ParameterReference reference : configuration.getParameterReferences()) {
|
||||
final String referencedParameterName = reference.getParameterName();
|
||||
if (referencedParameterName.equals(parameterName)) {
|
||||
if (entry.getKey().isSensitive() && !parameterDeletion && !Boolean.TRUE.equals(parameterSensitive)) {
|
||||
throw new IllegalStateException("Cannot update Parameter Context " + contextName + " because the update would add a Non-Sensitive Parameter " +
|
||||
"named '" + parameterName + "' but this Parameter already is referenced by a Sensitive Property.");
|
||||
}
|
||||
|
||||
if (!entry.getKey().isSensitive() && !parameterDeletion && Boolean.TRUE.equals(parameterSensitive)) {
|
||||
throw new IllegalStateException("Cannot update Parameter Context " + contextName + " because the update would add a Sensitive Parameter named " +
|
||||
"'" + parameterName + "' but this Parameter already is referenced by a Non-Sensitive Property.");
|
||||
}
|
||||
|
||||
if (active && (verifyComponentStates || parameterDeletion)) {
|
||||
if (parameterDeletion) {
|
||||
// First check if the actual parameter context is now missing the parameter: it may not be,
|
||||
// if the parameter is inherited from another context
|
||||
final ProcessGroup processGroup = flowManager.getGroup(component.getProcessGroupIdentifier());
|
||||
final ParameterContext parameterContext = processGroup.getParameterContext();
|
||||
final ParameterDescriptor parameterDescriptor = new ParameterDescriptor.Builder()
|
||||
.name(parameterName).build();
|
||||
if (!parameterContext.hasEffectiveValueIfRemoved(parameterDescriptor)) {
|
||||
throw new IllegalStateException("Cannot update Parameter Context " + contextName + " because the " + parameterName + " Parameter is being referenced by a " +
|
||||
activeExplanation + ".");
|
||||
}
|
||||
} else {
|
||||
throw new IllegalStateException("Cannot update Parameter Context " + contextName + " because it has Parameters that are being referenced by a " +
|
||||
activeExplanation + ".");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
final List<ParameterContext> inheritedParameterContexts = getInheritedParameterContexts(parameterContextDto);
|
||||
final Map<String, Parameter> parameters = parameterContextDto.getParameters() == null ? Collections.emptyMap() : getParameters(parameterContextDto, currentContext);
|
||||
currentContext.verifyCanUpdateParameterContext(parameters, inheritedParameterContexts);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
<div class="parameter-context-tab-container dialog-content">
|
||||
<div id="parameter-context-tabs" class="tab-container"></div>
|
||||
<div id="parameter-context-tabs-content">
|
||||
<div id="parameter-context-standard-settings-tab-content" class="configuration-tab">
|
||||
<div id="parameter-context-standard-settings-tab-content" class="split-65-35 configuration-tab">
|
||||
<div class="settings-left">
|
||||
<div id="parameter-context-id-setting" class="setting hidden">
|
||||
<div class="setting-name">Id</div>
|
||||
|
@ -57,7 +57,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="parameter-context-parameters-tab-content" class="configuration-tab">
|
||||
<div id="parameter-context-parameters-tab-content" class="split-65-35 configuration-tab">
|
||||
<div class="settings-left">
|
||||
<div class="edit-mode">
|
||||
<div id="add-parameter"><button class="button fa fa-plus"></button></div>
|
||||
|
@ -96,8 +96,51 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="parameter-context-inheritance-tab-content" class="configuration-tab">
|
||||
<div id="parameter-context-inheritance-container">
|
||||
<div class="settings-left">
|
||||
<div class="setting">
|
||||
<div class="setting-name">
|
||||
Available Parameter Contexts
|
||||
<div class="fa fa-question-circle" alt="Info" title="Available Parameter Contexts that could be inherited from."></div>
|
||||
</div>
|
||||
<div class="setting-field">
|
||||
<ol id="parameter-context-available"></ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="spacer"> </div>
|
||||
<div class="settings-right">
|
||||
<div class="setting">
|
||||
<div class="setting-name">
|
||||
Selected Parameter Context
|
||||
<div class="fa fa-question-circle" alt="Info" title="Parameter Contexts selected for inheritance."></div>
|
||||
</div>
|
||||
<div class="setting-field">
|
||||
<ol id="parameter-context-selected"></ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="parameter-context-inheritance-container-read-only" style="display: none;">
|
||||
<div class="settings-left">
|
||||
<div class="setting">
|
||||
<div class="setting-name">
|
||||
Selected Parameter Context
|
||||
<div class="fa fa-question-circle" alt="Info" title="Parameter Contexts selected for inheritance."></div>
|
||||
</div>
|
||||
<div class="setting-field">
|
||||
<ol id="parameter-context-selected-read-only"></ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="inherited-parameter-contexts-message" class="ellipsis hidden">
|
||||
Inherited Parameter Contexts have been modified. Updated listing of Parameters is pending apply.
|
||||
</div>
|
||||
</div>
|
||||
<div id="parameter-dialog" class="dialog cancellable hidden">
|
||||
<div class="dialog-content">
|
||||
|
|
|
@ -333,6 +333,7 @@ div.slick-cell div.overridden {
|
|||
top: 550px;
|
||||
left: 20px;
|
||||
font-size: 13px;
|
||||
color: #775351;
|
||||
max-width: calc(100% - 230px);
|
||||
z-index: 999;
|
||||
}
|
||||
|
|
|
@ -32,12 +32,12 @@
|
|||
display: none;
|
||||
}
|
||||
|
||||
#parameter-context-dialog div.settings-left {
|
||||
.parameter-context-tabs-content.split-65-35 div.settings-left {
|
||||
float: left;
|
||||
width: 65%;
|
||||
}
|
||||
|
||||
#parameter-context-dialog div.settings-right {
|
||||
.parameter-context-tabs-content.split-65-35 div.settings-right {
|
||||
float: left;
|
||||
width: 33%;
|
||||
height: 100%;
|
||||
|
@ -134,3 +134,79 @@ span.parameter-context-referencing-component-name {
|
|||
white-space: nowrap;
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
/* inheritance */
|
||||
|
||||
#parameter-context-available, #parameter-context-selected {
|
||||
list-style-type: none;
|
||||
margin: 0px;
|
||||
background: #eaeef0;
|
||||
min-height: 32px;
|
||||
margin-bottom: 5px;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
#parameter-context-available li, #parameter-context-selected li {
|
||||
margin: 2px;
|
||||
padding: 5px;
|
||||
cursor: pointer;
|
||||
font-size: 1em;
|
||||
height: 12px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#parameter-context-available li.unauthorized, #parameter-context-selected li.unauthorized {
|
||||
color: #a8a8a8;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
#parameter-context-available li {
|
||||
background: #fff;
|
||||
border-top: 1px solid #CCDADB;
|
||||
border-right: 1px solid #CCDADB;
|
||||
border-bottom: 1px solid #CCDADB;
|
||||
border-left: 1px solid #CCDADB;
|
||||
color: #004849;
|
||||
font-weight: 500;
|
||||
cursor: grab;
|
||||
line-height: 32px;
|
||||
height: 32px;
|
||||
padding: 0px 10px;
|
||||
box-shadow:0 1px 1px rgba(0,0,0,0.4);
|
||||
}
|
||||
|
||||
#parameter-context-selected li {
|
||||
background: #355B6A;
|
||||
border-top: 1px solid #AAC1CE;
|
||||
border-right: 1px solid #85A6B8;
|
||||
border-bottom: 1px solid #618BA3;
|
||||
border-left: 1px solid #85A6B8;
|
||||
color: #fff;
|
||||
font-weight: bold;
|
||||
line-height: 32px;
|
||||
height: 32px;
|
||||
padding: 0px 10px;
|
||||
}
|
||||
|
||||
#parameter-context-selected .draggable-control {
|
||||
float: right;
|
||||
}
|
||||
|
||||
#parameter-context-selected .fa-remove, #parameter-context-selected .fa-question-circle {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#parameter-context-selected-read-only {
|
||||
list-style: inside none decimal;
|
||||
}
|
||||
|
||||
#inherited-parameter-contexts-message {
|
||||
position: absolute;
|
||||
top: 550px;
|
||||
left: 20px;
|
||||
font-size: 13px;
|
||||
line-height: normal;
|
||||
color: #775351;
|
||||
max-width: calc(100% - 230px);
|
||||
z-index: 999;
|
||||
}
|
||||
|
|
|
@ -219,6 +219,7 @@
|
|||
parameterData.setItems([]);
|
||||
|
||||
resetUsage();
|
||||
resetInheritance();
|
||||
|
||||
// reset the last selected parameter
|
||||
lastSelectedId = null;
|
||||
|
@ -300,6 +301,24 @@
|
|||
return parameters;
|
||||
};
|
||||
|
||||
/**
|
||||
* Marshals the inherited parameter contexts.
|
||||
*/
|
||||
var marshalInheritedParameterContexts = function () {
|
||||
var inheritedParameterContextIds = $('#parameter-context-selected').sortable('toArray');
|
||||
|
||||
return inheritedParameterContextIds.map(function (id) {
|
||||
var name = $('#parameter-context-selected').find('li#' + id + ' span').text();
|
||||
return {
|
||||
id: id,
|
||||
component: {
|
||||
id: id,
|
||||
name: name
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles outstanding changes.
|
||||
*
|
||||
|
@ -1062,10 +1081,19 @@
|
|||
var parameters = marshalParameters();
|
||||
var proposedParamContextName = $('#parameter-context-name').val();
|
||||
var proposedParamContextDesc = $('#parameter-context-description-field').val();
|
||||
var inheritedParameterContexts = marshalInheritedParameterContexts();
|
||||
|
||||
var inheritedParameterContextEquals = isInheritedParameterContextEquals(parameterContextEntity, inheritedParameterContexts);
|
||||
if (inheritedParameterContextEquals) {
|
||||
$('#inherited-parameter-contexts-message').addClass('hidden');
|
||||
} else {
|
||||
$('#inherited-parameter-contexts-message').removeClass('hidden');
|
||||
}
|
||||
|
||||
if (_.isEmpty(parameters) &&
|
||||
proposedParamContextName === _.get(parameterContextEntity, 'component.name') &&
|
||||
proposedParamContextDesc === _.get(parameterContextEntity, 'component.description')) {
|
||||
proposedParamContextDesc === _.get(parameterContextEntity, 'component.description') &&
|
||||
inheritedParameterContextEquals) {
|
||||
|
||||
return false;
|
||||
} else {
|
||||
|
@ -1073,6 +1101,24 @@
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines if the proposed inherited parameter contexts are equal to the current configuration.
|
||||
*
|
||||
* @param parameterContextEntity
|
||||
* @param proposedInheritedParameterContexts
|
||||
* @returns {*}
|
||||
*/
|
||||
var isInheritedParameterContextEquals = function (parameterContextEntity, proposedInheritedParameterContexts) {
|
||||
var configuredInheritedParameterContexts = parameterContextEntity.component.inheritedParameterContexts.map(function (inheritedParameterContext) {
|
||||
return inheritedParameterContext.id;
|
||||
});
|
||||
var mappedProposedInheritedParameterContexts = proposedInheritedParameterContexts.map(function (proposedInheritedParameterContext) {
|
||||
return proposedInheritedParameterContext.id;
|
||||
});
|
||||
|
||||
return _.isEqual(configuredInheritedParameterContexts, mappedProposedInheritedParameterContexts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates parameter contexts by issuing an update request and polling until it's completion.
|
||||
*
|
||||
|
@ -1081,12 +1127,15 @@
|
|||
*/
|
||||
var updateParameterContext = function (parameterContextEntity) {
|
||||
var parameters = marshalParameters();
|
||||
var inheritedParameterContexts = marshalInheritedParameterContexts();
|
||||
|
||||
if (parameters.length === 0) {
|
||||
// nothing to update
|
||||
parameterContextEntity.component.parameters = [];
|
||||
if ($('#parameter-context-name').val() === parameterContextEntity.component.name &&
|
||||
$('#parameter-context-description-field').val() === parameterContextEntity.component.description) {
|
||||
|
||||
if ($('#parameter-context-name').val() === _.get(parameterContextEntity, 'component.name') &&
|
||||
$('#parameter-context-description-field').val() === _.get(parameterContextEntity, 'component.description') &&
|
||||
isInheritedParameterContextEquals(parameterContextEntity, inheritedParameterContexts)) {
|
||||
close();
|
||||
|
||||
return;
|
||||
|
@ -1095,6 +1144,9 @@
|
|||
parameterContextEntity.component.parameters = parameters;
|
||||
}
|
||||
|
||||
// include the inherited parameter contexts
|
||||
parameterContextEntity.component.inheritedParameterContexts = inheritedParameterContexts;
|
||||
|
||||
parameterContextEntity.component.name = $('#parameter-context-name').val();
|
||||
parameterContextEntity.component.description = $('#parameter-context-description-field').val();
|
||||
|
||||
|
@ -1249,8 +1301,8 @@
|
|||
});
|
||||
|
||||
// update the parameter context table if displayed
|
||||
var parameterContextGrid = $('#parameter-contexts-table').data('gridInstance');
|
||||
if (nfCommon.isDefinedAndNotNull(parameterContextGrid)) {
|
||||
if ($('#parameter-contexts-table').is(':visible')) {
|
||||
var parameterContextGrid = $('#parameter-contexts-table').data('gridInstance');
|
||||
var parameterContextData = parameterContextGrid.getData();
|
||||
|
||||
$.extend(parameterContextEntity, {
|
||||
|
@ -1289,6 +1341,9 @@
|
|||
$('#parameter-context-tabs').hide();
|
||||
$('#parameter-context-update-status').show();
|
||||
|
||||
// hide the pending apply message for parameter context
|
||||
$('#inherited-parameter-contexts-message').addClass('hidden')
|
||||
|
||||
pollUpdateRequest(response);
|
||||
}).fail(handleAjaxFailure);
|
||||
}).promise();
|
||||
|
@ -1530,6 +1585,57 @@
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Load the parameter context inheritance tab for the current parameterContextEntity. The current parameterContextEntity could be
|
||||
* null if this is a new parameter context.
|
||||
*
|
||||
* @param parameterContextEntity the parameter context being edited or null if new
|
||||
* @param readOnly whether the controls should be read only
|
||||
* @param parameterContexts all parameter contexts
|
||||
*/
|
||||
var loadParameterContextInheritance = function (parameterContextEntity, readOnly, parameterContexts) {
|
||||
// consider each parameter context and add to the listing of available or selected contexts based on the supplied parameterContextEntity
|
||||
$.each(parameterContexts, function (i, availableParameterContext) {
|
||||
// don't support inheriting from the current context
|
||||
var isCurrent = nfCommon.isNull(parameterContextEntity) ? false : availableParameterContext.id === parameterContextEntity.id;
|
||||
|
||||
// determine if this available parameter context is already selected
|
||||
var isSelected = nfCommon.isNull(parameterContextEntity) ? false : parameterContextEntity.component.inheritedParameterContexts.some(function (selectedParameterContext) {
|
||||
return availableParameterContext.id === selectedParameterContext.id;
|
||||
});
|
||||
|
||||
if (readOnly) {
|
||||
if (isSelected) {
|
||||
$('#parameter-context-selected-read-only').append($('<li></li>').text(availableParameterContext.component.name));
|
||||
}
|
||||
} else {
|
||||
if (isSelected) {
|
||||
addParameterContextInheritanceControl(availableParameterContext, true);
|
||||
} else if (!isCurrent) {
|
||||
addParameterContextInheritanceControl(availableParameterContext, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!nfCommon.isNull(parameterContextEntity)) {
|
||||
sortSelectedParameterContexts(parameterContextEntity);
|
||||
}
|
||||
|
||||
sortAvailableParameterContexts();
|
||||
|
||||
if (readOnly) {
|
||||
if ($('#parameter-context-selected-read-only').is(':empty')) {
|
||||
$('#parameter-context-selected-read-only').append($('<span class="unset">No value set</span>'));
|
||||
}
|
||||
|
||||
$('#parameter-context-inheritance-container-read-only').show();
|
||||
$('#parameter-context-inheritance-container').hide();
|
||||
} else {
|
||||
$('#parameter-context-inheritance-container-read-only').hide();
|
||||
$('#parameter-context-inheritance-container').show();
|
||||
}
|
||||
};
|
||||
|
||||
var resetUsage = function () {
|
||||
// empty the containers
|
||||
var processorContainer = $('.parameter-context-referencing-processors');
|
||||
|
@ -1561,6 +1667,125 @@
|
|||
updateReferencingComponentsBorder($('#parameter-referencing-components-container'));
|
||||
};
|
||||
|
||||
/**
|
||||
* Reset the inheritance tab.
|
||||
*/
|
||||
var resetInheritance = function () {
|
||||
$('#parameter-context-available').empty();
|
||||
$('#parameter-context-selected').empty();
|
||||
$('#parameter-context-selected-read-only').empty();
|
||||
$('#inherited-parameter-contexts-message').addClass('hidden');
|
||||
};
|
||||
|
||||
/**
|
||||
* Sorts the available parameter contexts.
|
||||
*/
|
||||
var sortAvailableParameterContexts = function () {
|
||||
var availableParameterContextList = $('#parameter-context-available');
|
||||
availableParameterContextList.children('li')
|
||||
.detach()
|
||||
.sort(function (aElement, bElement) {
|
||||
var a = $(aElement);
|
||||
var b = $(bElement);
|
||||
|
||||
// put unauthorized last
|
||||
if (a.hasClass('unauthorized') && b.hasClass('unauthorized')) {
|
||||
return 0;
|
||||
} else if (a.hasClass('unauthorized')) {
|
||||
return 1;
|
||||
} else if (b.hasClass('unauthorized')) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
var nameA = a.text();
|
||||
var nameB = b.text();
|
||||
return nameA.localeCompare(nameB);
|
||||
})
|
||||
.appendTo(availableParameterContextList);
|
||||
};
|
||||
|
||||
/**
|
||||
* Sorts the selected parameter context array based on the current parameter context entity.
|
||||
*
|
||||
* @param {object} selectedParameterContexts
|
||||
*/
|
||||
var sortSelectedParameterContexts = function (parameterContextEntity) {
|
||||
var selectedInheritedParameterContexts = parameterContextEntity.component.inheritedParameterContexts;
|
||||
|
||||
var selectedParameterContextList = $('#parameter-context-selected');
|
||||
selectedParameterContextList.children('li')
|
||||
.detach()
|
||||
.sort(function (aElement, bElement) {
|
||||
var a = $(aElement);
|
||||
var b = $(bElement);
|
||||
|
||||
var findA = function (selectedInheritedParameterContext) {
|
||||
return a.attr('id') === selectedInheritedParameterContext.id;
|
||||
};
|
||||
var findB = function (selectedInheritedParameterContext) {
|
||||
return b.attr('id') === selectedInheritedParameterContext.id;
|
||||
};
|
||||
|
||||
return selectedInheritedParameterContexts.findIndex(findA) - selectedInheritedParameterContexts.findIndex(findB);
|
||||
})
|
||||
.appendTo(selectedParameterContextList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified parameter context to the list of available parameter contexts.
|
||||
*
|
||||
* @argument {jQuery} container The container for the parameter context
|
||||
* @argument {object} parameterContext An available parameter context
|
||||
* @argument {boolean} isSelected Whether the parameter context is selected (which is used to decide whether to provide a remove control)
|
||||
*/
|
||||
var addParameterContextInheritanceControl = function (parameterContext, isSelected) {
|
||||
var label = parameterContext.id;
|
||||
if (parameterContext.permissions.canRead) {
|
||||
label = parameterContext.component.name;
|
||||
}
|
||||
|
||||
// add the parameter context to the specified list
|
||||
var parameterContextElement = $('<li></li>').append($('<span style="float: left;"></span>').text(label)).attr('id', parameterContext.id).addClass('ui-state-default');
|
||||
if (!parameterContext.permissions.canRead) {
|
||||
parameterContextElement.addClass('unauthorized');
|
||||
} else {
|
||||
// add the description if applicable
|
||||
if (!nfCommon.isBlank(parameterContext.component.description)) {
|
||||
$('<div class="fa fa-question-circle"></div>').appendTo(parameterContextElement).qtip($.extend({
|
||||
content: nfCommon.escapeHtml(parameterContext.component.description)
|
||||
}, nfCommon.config.tooltipConfig));
|
||||
}
|
||||
|
||||
if (isSelected) {
|
||||
addControlsForSelectedParameterContext(parameterContextElement);
|
||||
}
|
||||
}
|
||||
parameterContextElement.appendTo(isSelected ? '#parameter-context-selected' : '#parameter-context-available');
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds the controls to the specified selected draggable element.
|
||||
*
|
||||
* @argument {jQuery} draggableElement
|
||||
*/
|
||||
var addControlsForSelectedParameterContext = function (draggableElement) {
|
||||
var removeIcon = $('<div class="draggable-control"><div class="fa fa-remove"></div></div>')
|
||||
.on('click', function () {
|
||||
// remove the remove ice
|
||||
removeIcon.remove();
|
||||
|
||||
// restore to the available parameter contexts
|
||||
$('#parameter-context-available').append(draggableElement);
|
||||
|
||||
// resort the available parameter contexts
|
||||
sortAvailableParameterContexts();
|
||||
|
||||
// update the buttons to possibly trigger the disabled state
|
||||
$('#parameter-context-dialog').modal('refreshButtons');
|
||||
})
|
||||
.appendTo(draggableElement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the filtering.
|
||||
*
|
||||
|
@ -1914,6 +2139,9 @@
|
|||
}, {
|
||||
name: 'Parameters',
|
||||
tabContentId: 'parameter-context-parameters-tab-content'
|
||||
}, {
|
||||
name: 'Inheritance',
|
||||
tabContentId: 'parameter-context-inheritance-tab-content'
|
||||
}],
|
||||
select: function () {
|
||||
// update the parameters table size in case this is the first time its rendered
|
||||
|
@ -2124,23 +2352,24 @@
|
|||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Fetches the available Parameter Contexts.
|
||||
*/
|
||||
var fetchParameterContexts = function () {
|
||||
return $.ajax({
|
||||
type: 'GET',
|
||||
url: '../nifi-api/flow/parameter-contexts',
|
||||
dataType: 'json'
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Loads the parameter contexts.
|
||||
*
|
||||
* @param parameterContextToSelect id of the parameter context to select in the grid
|
||||
*/
|
||||
var loadParameterContexts = function (parameterContextToSelect) {
|
||||
var parameterContexts = $.Deferred(function (deferred) {
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: '../nifi-api/flow/parameter-contexts',
|
||||
dataType: 'json'
|
||||
}).done(function (response) {
|
||||
deferred.resolve(response);
|
||||
}).fail(function (xhr, status, error) {
|
||||
deferred.reject(xhr, status, error);
|
||||
});
|
||||
}).promise();
|
||||
var parameterContexts = fetchParameterContexts();
|
||||
|
||||
// return a deferred for all parts of the parameter contexts
|
||||
return $.when(parameterContexts).done(function (response) {
|
||||
|
@ -2382,6 +2611,7 @@
|
|||
// create a new parameter context
|
||||
$('#new-parameter-context').on('click', function () {
|
||||
resetUsage();
|
||||
resetInheritance();
|
||||
|
||||
// new parameter contexts do not have an ID to show
|
||||
if (!$('#parameter-context-id-setting').hasClass('hidden')) {
|
||||
|
@ -2424,10 +2654,64 @@
|
|||
}
|
||||
}]).modal('show');
|
||||
|
||||
var parameterContextsGrid = $('#parameter-contexts-table').data('gridInstance');
|
||||
var parameterContextsData = parameterContextsGrid.getData();
|
||||
var parameterContexts = parameterContextsData.getItems();
|
||||
|
||||
loadParameterContextInheritance(null, false, parameterContexts);
|
||||
|
||||
// set the initial focus
|
||||
$('#parameter-context-name').focus();
|
||||
});
|
||||
|
||||
// work around for https://bugs.jqueryui.com/ticket/6054
|
||||
var shouldAllowDrop = true;
|
||||
|
||||
// make the parameter context containers sortable
|
||||
$('#parameter-context-available').sortable({
|
||||
containment: $('#parameter-context-inheritance-tab-content'),
|
||||
cancel: '.unauthorized',
|
||||
connectWith: '#parameter-context-selected',
|
||||
placeholder: 'available',
|
||||
scroll: true,
|
||||
opacity: 0.6,
|
||||
beforeStop: function (event, ui) {
|
||||
if ($('#parameter-context-available').find('.ui-sortable-placeholder').length) {
|
||||
shouldAllowDrop = false;
|
||||
}
|
||||
},
|
||||
stop: function (event, ui) {
|
||||
const allowDrop = shouldAllowDrop;
|
||||
shouldAllowDrop = true;
|
||||
return allowDrop;
|
||||
}
|
||||
});
|
||||
$('#parameter-context-selected').sortable({
|
||||
containment: $('#parameter-context-inheritance-tab-content'),
|
||||
cancel: '.unauthorized',
|
||||
placeholder: 'selected',
|
||||
scroll: true,
|
||||
opacity: 0.6,
|
||||
receive: function (event, ui) {
|
||||
addControlsForSelectedParameterContext(ui.item);
|
||||
},
|
||||
update: function (event, ui) {
|
||||
// update the buttons to possibly trigger the disabled state
|
||||
$('#parameter-context-dialog').modal('refreshButtons');
|
||||
}
|
||||
});
|
||||
$('#parameter-context-available, #parameter-context-selected').disableSelection();
|
||||
|
||||
// add a listener that will handle dblclick for all available authorized parameter context children
|
||||
$(document).on('dblclick', '#parameter-context-available li:not(".unauthorized")', function() {
|
||||
var availableParameterContextElement = $(this).detach().appendTo($('#parameter-context-selected'));
|
||||
|
||||
addControlsForSelectedParameterContext(availableParameterContextElement);
|
||||
|
||||
// update the buttons to possibly trigger the disabled state
|
||||
$('#parameter-context-dialog').modal('refreshButtons');
|
||||
});
|
||||
|
||||
// initialize the new parameter context dialog
|
||||
initNewParameterContextDialog();
|
||||
|
||||
|
@ -2437,7 +2721,7 @@
|
|||
if ($('#parameter-referencing-components-container').is(':visible')) {
|
||||
updateReferencingComponentsBorder($('#parameter-referencing-components-container'));
|
||||
}
|
||||
})
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -2460,6 +2744,9 @@
|
|||
})
|
||||
};
|
||||
|
||||
// include the inherited parameter contexts
|
||||
parameterContextEntity.component.inheritedParameterContexts = marshalInheritedParameterContexts();
|
||||
|
||||
var addContext = $.ajax({
|
||||
type: 'POST',
|
||||
url: config.urls.parameterContexts,
|
||||
|
@ -2467,10 +2754,9 @@
|
|||
dataType: 'json',
|
||||
contentType: 'application/json'
|
||||
}).done(function (parameterContextEntity) {
|
||||
// add the item
|
||||
var parameterContextGrid = $('#parameter-contexts-table').data('gridInstance');
|
||||
|
||||
if (nfCommon.isDefinedAndNotNull(parameterContextGrid)) {
|
||||
// update the table if displayed
|
||||
if ($('#parameter-contexts-table').is(':visible')) {
|
||||
var parameterContextGrid = $('#parameter-contexts-table').data('gridInstance');
|
||||
var parameterContextData = parameterContextGrid.getData();
|
||||
parameterContextData.addItem(parameterContextEntity);
|
||||
|
||||
|
@ -2539,6 +2825,19 @@
|
|||
dataType: 'json'
|
||||
});
|
||||
|
||||
var parameterContextsDeferred;
|
||||
if ($('#parameter-contexts-table').is(':visible')) {
|
||||
parameterContextsDeferred = $.Deferred(function (deferred) {
|
||||
var parameterContextsGrid = $('#parameter-contexts-table').data('gridInstance');
|
||||
var parameterContextsData = parameterContextsGrid.getData();
|
||||
deferred.resolve({
|
||||
parameterContexts: parameterContextsData.getItems()
|
||||
});
|
||||
}).promise();
|
||||
} else {
|
||||
parameterContextsDeferred = fetchParameterContexts();
|
||||
}
|
||||
|
||||
// once everything is loaded, show the dialog
|
||||
reloadContext.done(function (parameterContextEntity) {
|
||||
var canWrite = _.get(parameterContextEntity, 'permissions.canWrite', false);
|
||||
|
@ -2579,71 +2878,74 @@
|
|||
|
||||
loadParameters(parameterContextEntity, parameterToSelect, readOnly || !canWrite);
|
||||
|
||||
var editModeButtonModel = [{
|
||||
buttonText: 'Apply',
|
||||
color: {
|
||||
base: '#728E9B',
|
||||
hover: '#004849',
|
||||
text: '#ffffff'
|
||||
},
|
||||
disabled: function () {
|
||||
if ($('#parameter-context-name').val() !== '' && hasParameterContextChanged(currentParameterContextEntity)) {
|
||||
// load the parameter contexts in order to render all available parameter contexts
|
||||
parameterContextsDeferred.done(function (response) {
|
||||
loadParameterContextInheritance(parameterContextEntity, readOnly || !canWrite, response.parameterContexts);
|
||||
|
||||
var editModeButtonModel = [{
|
||||
buttonText: 'Apply',
|
||||
color: {
|
||||
base: '#728E9B',
|
||||
hover: '#004849',
|
||||
text: '#ffffff'
|
||||
},
|
||||
disabled: function () {
|
||||
if ($('#parameter-context-name').val() !== '' && hasParameterContextChanged(currentParameterContextEntity)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
handler: {
|
||||
click: function () {
|
||||
updateParameterContext(currentParameterContextEntity);
|
||||
}
|
||||
}
|
||||
}, {
|
||||
buttonText: 'Cancel',
|
||||
color: {
|
||||
base: '#E3E8EB',
|
||||
hover: '#C7D2D7',
|
||||
text: '#004849'
|
||||
},
|
||||
handler: {
|
||||
click: function () {
|
||||
$(this).modal('hide');
|
||||
}
|
||||
}
|
||||
}];
|
||||
|
||||
var readOnlyButtonModel = [{
|
||||
buttonText: 'Ok',
|
||||
color: {
|
||||
base: '#728E9B',
|
||||
hover: '#004849',
|
||||
text: '#ffffff'
|
||||
},
|
||||
disabled: function () {
|
||||
return false;
|
||||
},
|
||||
handler: {
|
||||
click: function () {
|
||||
$(this).modal('hide');
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
handler: {
|
||||
click: function () {
|
||||
updateParameterContext(currentParameterContextEntity);
|
||||
}
|
||||
}
|
||||
}, {
|
||||
buttonText: 'Cancel',
|
||||
color: {
|
||||
base: '#E3E8EB',
|
||||
hover: '#C7D2D7',
|
||||
text: '#004849'
|
||||
},
|
||||
handler: {
|
||||
click: function () {
|
||||
$(this).modal('hide');
|
||||
}
|
||||
}
|
||||
}];
|
||||
}];
|
||||
|
||||
var readOnlyButtonModel = [{
|
||||
buttonText: 'Ok',
|
||||
color: {
|
||||
base: '#728E9B',
|
||||
hover: '#004849',
|
||||
text: '#ffffff'
|
||||
},
|
||||
disabled: function () {
|
||||
return false;
|
||||
},
|
||||
handler: {
|
||||
click: function () {
|
||||
$(this).modal('hide');
|
||||
}
|
||||
}
|
||||
}];
|
||||
// show the context
|
||||
$('#parameter-context-dialog')
|
||||
.modal('setHeaderText', canWrite ? 'Update Parameter Context' : 'View Parameter Context')
|
||||
.modal('setButtonModel', canWrite ? editModeButtonModel : readOnlyButtonModel)
|
||||
.modal('show');
|
||||
|
||||
// select the parameters tab
|
||||
$('#parameter-context-tabs').find('li:eq(1)').click();
|
||||
|
||||
// show the context
|
||||
$('#parameter-context-dialog')
|
||||
.modal('setHeaderText', canWrite ? 'Update Parameter Context' : 'View Parameter Context')
|
||||
.modal('setButtonModel', canWrite ? editModeButtonModel : readOnlyButtonModel)
|
||||
.modal('show');
|
||||
|
||||
// select the parameters tab
|
||||
$('#parameter-context-tabs').find('li:last').click();
|
||||
|
||||
// check if border is necessary
|
||||
updateReferencingComponentsBorder($('#parameter-referencing-components-container'));
|
||||
|
||||
// show the border if necessary
|
||||
updateReferencingComponentsBorder(referencingComponentsContainer);
|
||||
// check if border is necessary
|
||||
updateReferencingComponentsBorder($('#parameter-referencing-components-container'));
|
||||
|
||||
// show the border if necessary
|
||||
updateReferencingComponentsBorder(referencingComponentsContainer);
|
||||
}).fail(nfErrorHandler.handleAjaxError);
|
||||
}).fail(nfErrorHandler.handleAjaxError);
|
||||
},
|
||||
|
||||
|
|
Loading…
Reference in New Issue