You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by jp...@apache.org on 2016/07/28 13:59:21 UTC
nifi git commit: NIFI-2347: - Ensuring component specific policies
are retained when using copy/paste. - This includes the policies for the
component, data of the component, data transfers of the component,
and policies of the component.
Repository: nifi
Updated Branches:
refs/heads/master 25cadf5db -> 09b124714
NIFI-2347: - Ensuring component specific policies are retained when using copy/paste. - This includes the policies for the component, data of the component, data transfers of the component, and policies of the component.
This closes #730
Signed-off-by: jpercivall <jo...@yahoo.com>
Project: http://git-wip-us.apache.org/repos/asf/nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/nifi/commit/09b12471
Tree: http://git-wip-us.apache.org/repos/asf/nifi/tree/09b12471
Diff: http://git-wip-us.apache.org/repos/asf/nifi/diff/09b12471
Branch: refs/heads/master
Commit: 09b124714eb0f97b68a77e6c2b3243a5e9ec8e06
Parents: 25cadf5
Author: Matt Gilman <ma...@gmail.com>
Authored: Wed Jul 27 21:24:46 2016 -0400
Committer: jpercivall <jo...@yahoo.com>
Committed: Thu Jul 28 09:43:40 2016 -0400
----------------------------------------------------------------------
.../nifi/web/dao/impl/StandardSnippetDAO.java | 17 +-
.../org/apache/nifi/web/util/SnippetUtils.java | 574 +++++++++++++------
.../src/main/resources/nifi-web-api-context.xml | 1 +
3 files changed, 400 insertions(+), 192 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/nifi/blob/09b12471/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardSnippetDAO.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardSnippetDAO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardSnippetDAO.java
index caa36d7..7893ddc 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardSnippetDAO.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/dao/impl/StandardSnippetDAO.java
@@ -92,10 +92,19 @@ public class StandardSnippetDAO implements SnippetDAO {
org.apache.nifi.util.SnippetUtils.moveSnippet(snippetContents, originX, originY);
}
- // instantiate the snippet
- flowController.instantiateSnippet(processGroup, snippetContents);
-
- return snippetContents;
+ try {
+ // instantiate the snippet and return the contents
+ flowController.instantiateSnippet(processGroup, snippetContents);
+ return snippetContents;
+ } catch (IllegalStateException ise) {
+ // illegal state will be thrown from instantiateSnippet when there is an issue with the snippet _before_ any of the
+ // components are actually created. if we've received this exception we want to attempt to roll back any of the
+ // policies that we've already cloned for this request
+ snippetUtils.rollbackClonedPolicies(snippetContents);
+
+ // rethrow the same exception
+ throw ise;
+ }
} catch (ProcessorInstantiationException pie) {
throw new NiFiCoreException(String.format("Unable to copy snippet because processor type '%s' is unknown to this NiFi.",
StringUtils.substringAfterLast(pie.getMessage(), ".")));
http://git-wip-us.apache.org/repos/asf/nifi/blob/09b12471/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/util/SnippetUtils.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/util/SnippetUtils.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/util/SnippetUtils.java
index c5c1d70..e7b69c1 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/util/SnippetUtils.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/util/SnippetUtils.java
@@ -16,19 +16,12 @@
*/
package org.apache.nifi.web.util;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Random;
-import java.util.Set;
-import java.util.UUID;
-import java.util.stream.Collectors;
-
import org.apache.commons.lang3.StringUtils;
+import org.apache.nifi.authorization.AccessPolicy;
+import org.apache.nifi.authorization.RequestAction;
+import org.apache.nifi.authorization.Resource;
+import org.apache.nifi.authorization.resource.ResourceFactory;
+import org.apache.nifi.authorization.resource.ResourceType;
import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.connectable.ConnectableType;
import org.apache.nifi.connectable.Connection;
@@ -44,6 +37,7 @@ import org.apache.nifi.controller.service.ControllerServiceState;
import org.apache.nifi.groups.ProcessGroup;
import org.apache.nifi.groups.RemoteProcessGroup;
import org.apache.nifi.util.TypeOneUUIDGenerator;
+import org.apache.nifi.web.api.dto.AccessPolicyDTO;
import org.apache.nifi.web.api.dto.ConnectableDTO;
import org.apache.nifi.web.api.dto.ConnectionDTO;
import org.apache.nifi.web.api.dto.ControllerServiceDTO;
@@ -59,15 +53,34 @@ import org.apache.nifi.web.api.dto.PropertyDescriptorDTO;
import org.apache.nifi.web.api.dto.RemoteProcessGroupContentsDTO;
import org.apache.nifi.web.api.dto.RemoteProcessGroupDTO;
import org.apache.nifi.web.api.dto.RemoteProcessGroupPortDTO;
+import org.apache.nifi.web.api.entity.TenantEntity;
+import org.apache.nifi.web.dao.AccessPolicyDAO;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Random;
+import java.util.Set;
+import java.util.UUID;
+import java.util.stream.Collectors;
/**
* Template utilities.
*/
public final class SnippetUtils {
+ private static final Logger logger = LoggerFactory.getLogger(SnippetUtils.class);
+
private FlowController flowController;
private DtoFactory dtoFactory;
-
+ private AccessPolicyDAO accessPolicyDAO;
/**
@@ -262,8 +275,7 @@ public final class SnippetUtils {
}
- public FlowSnippetDTO copy(final FlowSnippetDTO snippetContents, final ProcessGroup group,
- final String idGenerationSeed, boolean isCopy) {
+ public FlowSnippetDTO copy(final FlowSnippetDTO snippetContents, final ProcessGroup group, final String idGenerationSeed, boolean isCopy) {
final FlowSnippetDTO snippetCopy = copyContentsForGroup(snippetContents, group.getIdentifier(), null, null, idGenerationSeed, isCopy);
resolveNameConflicts(snippetCopy, group);
return snippetCopy;
@@ -319,210 +331,392 @@ public final class SnippetUtils {
}
}
- private FlowSnippetDTO copyContentsForGroup(final FlowSnippetDTO snippetContents, final String groupId, final Map<String, ConnectableDTO> parentConnectableMap, Map<String, String> serviceIdMap,
- final String idGenerationSeed, boolean isCopy) {
- final FlowSnippetDTO snippetContentsCopy = new FlowSnippetDTO();
-
- //
- // Copy the Controller Services
- //
- if (serviceIdMap == null) {
- serviceIdMap = new HashMap<>();
- }
+ private FlowSnippetDTO copyContentsForGroup(final FlowSnippetDTO snippetContents, final String groupId, final Map<String, ConnectableDTO> parentConnectableMap,
+ Map<String, String> serviceIdMap, final String idGenerationSeed, boolean isCopy) {
- final Set<ControllerServiceDTO> services = new HashSet<>();
- if (snippetContents.getControllerServices() != null) {
- for (final ControllerServiceDTO serviceDTO : snippetContents.getControllerServices()) {
- final ControllerServiceDTO service = dtoFactory.copy(serviceDTO);
- service.setId(generateId(serviceDTO.getId(), idGenerationSeed, isCopy));
- service.setState(ControllerServiceState.DISABLED.name());
- services.add(service);
+ final FlowSnippetDTO snippetContentsCopy = new FlowSnippetDTO();
+ try {
+ //
+ // Copy the Controller Services
+ //
+ if (serviceIdMap == null) {
+ serviceIdMap = new HashMap<>();
+ }
- // Map old service ID to new service ID so that we can make sure that we reference the new ones.
- serviceIdMap.put(serviceDTO.getId(), service.getId());
+ final Set<ControllerServiceDTO> services = new HashSet<>();
+ if (snippetContents.getControllerServices() != null) {
+ for (final ControllerServiceDTO serviceDTO : snippetContents.getControllerServices()) {
+ final ControllerServiceDTO service = dtoFactory.copy(serviceDTO);
+ service.setId(generateId(serviceDTO.getId(), idGenerationSeed, isCopy));
+ service.setState(ControllerServiceState.DISABLED.name());
+ services.add(service);
+
+ // Map old service ID to new service ID so that we can make sure that we reference the new ones.
+ serviceIdMap.put(serviceDTO.getId(), service.getId());
+
+ // clone policies as appropriate
+ if (isCopy) {
+ cloneComponentSpecificPolicies(
+ ResourceFactory.getComponentResource(ResourceType.ControllerService, serviceDTO.getId(), serviceDTO.getName()),
+ ResourceFactory.getComponentResource(ResourceType.ControllerService, service.getId(), service.getName()), idGenerationSeed);
+ }
+ }
}
- }
- // if there is any controller service that maps to another controller service, update the id's
- for (final ControllerServiceDTO serviceDTO : services) {
- final Map<String, String> properties = serviceDTO.getProperties();
- final Map<String, PropertyDescriptorDTO> descriptors = serviceDTO.getDescriptors();
- if (properties != null && descriptors != null) {
- for (final PropertyDescriptorDTO descriptor : descriptors.values()) {
- if (descriptor.getIdentifiesControllerService() != null) {
- final String currentServiceId = properties.get(descriptor.getName());
- if (currentServiceId == null) {
- continue;
+ // if there is any controller service that maps to another controller service, update the id's
+ for (final ControllerServiceDTO serviceDTO : services) {
+ final Map<String, String> properties = serviceDTO.getProperties();
+ final Map<String, PropertyDescriptorDTO> descriptors = serviceDTO.getDescriptors();
+ if (properties != null && descriptors != null) {
+ for (final PropertyDescriptorDTO descriptor : descriptors.values()) {
+ if (descriptor.getIdentifiesControllerService() != null) {
+ final String currentServiceId = properties.get(descriptor.getName());
+ if (currentServiceId == null) {
+ continue;
+ }
+
+ final String newServiceId = serviceIdMap.get(currentServiceId);
+ properties.put(descriptor.getName(), newServiceId);
}
-
- final String newServiceId = serviceIdMap.get(currentServiceId);
- properties.put(descriptor.getName(), newServiceId);
}
}
}
- }
- snippetContentsCopy.setControllerServices(services);
-
- //
- // Copy the labels
- //
- final Set<LabelDTO> labels = new HashSet<>();
- if (snippetContents.getLabels() != null) {
- for (final LabelDTO labelDTO : snippetContents.getLabels()) {
- final LabelDTO label = dtoFactory.copy(labelDTO);
- label.setId(generateId(labelDTO.getId(), idGenerationSeed, isCopy));
- label.setParentGroupId(groupId);
- labels.add(label);
+ snippetContentsCopy.setControllerServices(services);
+
+ //
+ // Copy the labels
+ //
+ final Set<LabelDTO> labels = new HashSet<>();
+ if (snippetContents.getLabels() != null) {
+ for (final LabelDTO labelDTO : snippetContents.getLabels()) {
+ final LabelDTO label = dtoFactory.copy(labelDTO);
+ label.setId(generateId(labelDTO.getId(), idGenerationSeed, isCopy));
+ label.setParentGroupId(groupId);
+ labels.add(label);
+
+ // clone policies as appropriate
+ if (isCopy) {
+ cloneComponentSpecificPolicies(
+ ResourceFactory.getComponentResource(ResourceType.Label, labelDTO.getId(), labelDTO.getLabel()),
+ ResourceFactory.getComponentResource(ResourceType.Label, label.getId(), label.getLabel()), idGenerationSeed);
+ }
+ }
}
- }
- snippetContentsCopy.setLabels(labels);
-
- //
- // Copy connectable components
- //
- // maps a group ID-ID of a Connectable in the template to the new instance
- final Map<String, ConnectableDTO> connectableMap = new HashMap<>();
-
- //
- // Copy the funnels
- //
- final Set<FunnelDTO> funnels = new HashSet<>();
- if (snippetContents.getFunnels() != null) {
- for (final FunnelDTO funnelDTO : snippetContents.getFunnels()) {
- final FunnelDTO cp = dtoFactory.copy(funnelDTO);
- cp.setId(generateId(funnelDTO.getId(), idGenerationSeed, isCopy));
- cp.setParentGroupId(groupId);
- funnels.add(cp);
-
- connectableMap.put(funnelDTO.getParentGroupId() + "-" + funnelDTO.getId(), dtoFactory.createConnectableDto(cp));
+ snippetContentsCopy.setLabels(labels);
+
+ //
+ // Copy connectable components
+ //
+ // maps a group ID-ID of a Connectable in the template to the new instance
+ final Map<String, ConnectableDTO> connectableMap = new HashMap<>();
+
+ //
+ // Copy the funnels
+ //
+ final Set<FunnelDTO> funnels = new HashSet<>();
+ if (snippetContents.getFunnels() != null) {
+ for (final FunnelDTO funnelDTO : snippetContents.getFunnels()) {
+ final FunnelDTO cp = dtoFactory.copy(funnelDTO);
+ cp.setId(generateId(funnelDTO.getId(), idGenerationSeed, isCopy));
+ cp.setParentGroupId(groupId);
+ funnels.add(cp);
+
+ connectableMap.put(funnelDTO.getParentGroupId() + "-" + funnelDTO.getId(), dtoFactory.createConnectableDto(cp));
+
+ // clone policies as appropriate
+ if (isCopy) {
+ cloneComponentSpecificPolicies(
+ ResourceFactory.getComponentResource(ResourceType.Funnel, funnelDTO.getId(), funnelDTO.getId()),
+ ResourceFactory.getComponentResource(ResourceType.Funnel, cp.getId(), cp.getId()), idGenerationSeed);
+ }
+ }
}
- }
- snippetContentsCopy.setFunnels(funnels);
+ snippetContentsCopy.setFunnels(funnels);
+
+ final Set<PortDTO> inputPorts = new HashSet<>();
+ if (snippetContents.getInputPorts() != null) {
+ for (final PortDTO portDTO : snippetContents.getInputPorts()) {
+ final PortDTO cp = dtoFactory.copy(portDTO);
+ cp.setId(generateId(portDTO.getId(), idGenerationSeed, isCopy));
+ cp.setParentGroupId(groupId);
+ cp.setState(ScheduledState.STOPPED.toString());
+ inputPorts.add(cp);
+
+ final ConnectableDTO portConnectable = dtoFactory.createConnectableDto(cp, ConnectableType.INPUT_PORT);
+ connectableMap.put(portDTO.getParentGroupId() + "-" + portDTO.getId(), portConnectable);
+ if (parentConnectableMap != null) {
+ parentConnectableMap.put(portDTO.getParentGroupId() + "-" + portDTO.getId(), portConnectable);
+ }
- final Set<PortDTO> inputPorts = new HashSet<>();
- if (snippetContents.getInputPorts() != null) {
- for (final PortDTO portDTO : snippetContents.getInputPorts()) {
- final PortDTO cp = dtoFactory.copy(portDTO);
- cp.setId(generateId(portDTO.getId(), idGenerationSeed, isCopy));
- cp.setParentGroupId(groupId);
- cp.setState(ScheduledState.STOPPED.toString());
- inputPorts.add(cp);
-
- final ConnectableDTO portConnectable = dtoFactory.createConnectableDto(cp, ConnectableType.INPUT_PORT);
- connectableMap.put(portDTO.getParentGroupId() + "-" + portDTO.getId(), portConnectable);
- if (parentConnectableMap != null) {
- parentConnectableMap.put(portDTO.getParentGroupId() + "-" + portDTO.getId(), portConnectable);
+ // clone policies as appropriate
+ if (isCopy) {
+ cloneComponentSpecificPolicies(
+ ResourceFactory.getComponentResource(ResourceType.InputPort, portDTO.getId(), portDTO.getName()),
+ ResourceFactory.getComponentResource(ResourceType.InputPort, cp.getId(), cp.getName()), idGenerationSeed);
+ }
}
}
- }
- snippetContentsCopy.setInputPorts(inputPorts);
+ snippetContentsCopy.setInputPorts(inputPorts);
+
+ final Set<PortDTO> outputPorts = new HashSet<>();
+ if (snippetContents.getOutputPorts() != null) {
+ for (final PortDTO portDTO : snippetContents.getOutputPorts()) {
+ final PortDTO cp = dtoFactory.copy(portDTO);
+ cp.setId(generateId(portDTO.getId(), idGenerationSeed, isCopy));
+ cp.setParentGroupId(groupId);
+ cp.setState(ScheduledState.STOPPED.toString());
+ outputPorts.add(cp);
+
+ final ConnectableDTO portConnectable = dtoFactory.createConnectableDto(cp, ConnectableType.OUTPUT_PORT);
+ connectableMap.put(portDTO.getParentGroupId() + "-" + portDTO.getId(), portConnectable);
+ if (parentConnectableMap != null) {
+ parentConnectableMap.put(portDTO.getParentGroupId() + "-" + portDTO.getId(), portConnectable);
+ }
- final Set<PortDTO> outputPorts = new HashSet<>();
- if (snippetContents.getOutputPorts() != null) {
- for (final PortDTO portDTO : snippetContents.getOutputPorts()) {
- final PortDTO cp = dtoFactory.copy(portDTO);
- cp.setId(generateId(portDTO.getId(), idGenerationSeed, isCopy));
- cp.setParentGroupId(groupId);
- cp.setState(ScheduledState.STOPPED.toString());
- outputPorts.add(cp);
-
- final ConnectableDTO portConnectable = dtoFactory.createConnectableDto(cp, ConnectableType.OUTPUT_PORT);
- connectableMap.put(portDTO.getParentGroupId() + "-" + portDTO.getId(), portConnectable);
- if (parentConnectableMap != null) {
- parentConnectableMap.put(portDTO.getParentGroupId() + "-" + portDTO.getId(), portConnectable);
+ // clone policies as appropriate
+ if (isCopy) {
+ cloneComponentSpecificPolicies(
+ ResourceFactory.getComponentResource(ResourceType.OutputPort, portDTO.getId(), portDTO.getName()),
+ ResourceFactory.getComponentResource(ResourceType.OutputPort, cp.getId(), cp.getName()), idGenerationSeed);
+ }
}
}
- }
- snippetContentsCopy.setOutputPorts(outputPorts);
-
- //
- // Copy the processors
- //
- final Set<ProcessorDTO> processors = new HashSet<>();
- if (snippetContents.getProcessors() != null) {
- for (final ProcessorDTO processorDTO : snippetContents.getProcessors()) {
- final ProcessorDTO cp = dtoFactory.copy(processorDTO);
- cp.setId(generateId(processorDTO.getId(), idGenerationSeed, isCopy));
- cp.setParentGroupId(groupId);
- cp.setState(ScheduledState.STOPPED.toString());
- processors.add(cp);
-
- connectableMap.put(processorDTO.getParentGroupId() + "-" + processorDTO.getId(), dtoFactory.createConnectableDto(cp));
+ snippetContentsCopy.setOutputPorts(outputPorts);
+
+ //
+ // Copy the processors
+ //
+ final Set<ProcessorDTO> processors = new HashSet<>();
+ if (snippetContents.getProcessors() != null) {
+ for (final ProcessorDTO processorDTO : snippetContents.getProcessors()) {
+ final ProcessorDTO cp = dtoFactory.copy(processorDTO);
+ cp.setId(generateId(processorDTO.getId(), idGenerationSeed, isCopy));
+ cp.setParentGroupId(groupId);
+ cp.setState(ScheduledState.STOPPED.toString());
+ processors.add(cp);
+
+ connectableMap.put(processorDTO.getParentGroupId() + "-" + processorDTO.getId(), dtoFactory.createConnectableDto(cp));
+
+ // clone policies as appropriate
+ if (isCopy) {
+ cloneComponentSpecificPolicies(
+ ResourceFactory.getComponentResource(ResourceType.Processor, processorDTO.getId(), processorDTO.getName()),
+ ResourceFactory.getComponentResource(ResourceType.Processor, cp.getId(), cp.getName()), idGenerationSeed);
+ }
+ }
}
- }
- snippetContentsCopy.setProcessors(processors);
+ snippetContentsCopy.setProcessors(processors);
+
+ // if there is any controller service that maps to another controller service, update the id's
+ updateControllerServiceIdentifiers(snippetContentsCopy, serviceIdMap);
+
+ //
+ // Copy ProcessGroups
+ //
+ // instantiate the process groups, renaming as necessary
+ final Set<ProcessGroupDTO> groups = new HashSet<>();
+ if (snippetContents.getProcessGroups() != null) {
+ for (final ProcessGroupDTO groupDTO : snippetContents.getProcessGroups()) {
+ final ProcessGroupDTO cp = dtoFactory.copy(groupDTO, false);
+ cp.setId(generateId(groupDTO.getId(), idGenerationSeed, isCopy));
+ cp.setParentGroupId(groupId);
+
+ // copy the contents of this group - we do not copy via the dto factory since we want to specify new ids
+ final FlowSnippetDTO contentsCopy = copyContentsForGroup(groupDTO.getContents(), cp.getId(), connectableMap, serviceIdMap, idGenerationSeed, isCopy);
+ cp.setContents(contentsCopy);
+ groups.add(cp);
+
+ // clone policies as appropriate
+ if (isCopy) {
+ cloneComponentSpecificPolicies(
+ ResourceFactory.getComponentResource(ResourceType.ProcessGroup, groupDTO.getId(), groupDTO.getName()),
+ ResourceFactory.getComponentResource(ResourceType.ProcessGroup, cp.getId(), cp.getName()), idGenerationSeed);
+ }
+ }
+ }
+ snippetContentsCopy.setProcessGroups(groups);
+
+ final Set<RemoteProcessGroupDTO> remoteGroups = new HashSet<>();
+ if (snippetContents.getRemoteProcessGroups() != null) {
+ for (final RemoteProcessGroupDTO remoteGroupDTO : snippetContents.getRemoteProcessGroups()) {
+ final RemoteProcessGroupDTO cp = dtoFactory.copy(remoteGroupDTO);
+ cp.setId(generateId(remoteGroupDTO.getId(), idGenerationSeed, isCopy));
+ cp.setParentGroupId(groupId);
+
+ final RemoteProcessGroupContentsDTO contents = cp.getContents();
+ if (contents != null && contents.getInputPorts() != null) {
+ for (final RemoteProcessGroupPortDTO remotePort : contents.getInputPorts()) {
+ remotePort.setGroupId(cp.getId());
+ connectableMap.put(remoteGroupDTO.getId() + "-" + remotePort.getId(), dtoFactory.createConnectableDto(remotePort, ConnectableType.REMOTE_INPUT_PORT));
+ }
+ }
+ if (contents != null && contents.getOutputPorts() != null) {
+ for (final RemoteProcessGroupPortDTO remotePort : contents.getOutputPorts()) {
+ remotePort.setGroupId(cp.getId());
+ connectableMap.put(remoteGroupDTO.getId() + "-" + remotePort.getId(), dtoFactory.createConnectableDto(remotePort, ConnectableType.REMOTE_OUTPUT_PORT));
+ }
+ }
- // if there is any controller service that maps to another controller service, update the id's
- updateControllerServiceIdentifiers(snippetContentsCopy, serviceIdMap);
+ remoteGroups.add(cp);
- //
- // Copy ProcessGroups
- //
- // instantiate the process groups, renaming as necessary
- final Set<ProcessGroupDTO> groups = new HashSet<>();
- if (snippetContents.getProcessGroups() != null) {
- for (final ProcessGroupDTO groupDTO : snippetContents.getProcessGroups()) {
- final ProcessGroupDTO cp = dtoFactory.copy(groupDTO, false);
- cp.setId(generateId(groupDTO.getId(), idGenerationSeed, isCopy));
- cp.setParentGroupId(groupId);
-
- // copy the contents of this group - we do not copy via the dto factory since we want to specify new ids
- final FlowSnippetDTO contentsCopy = copyContentsForGroup(groupDTO.getContents(), cp.getId(), connectableMap, serviceIdMap, idGenerationSeed, isCopy);
- cp.setContents(contentsCopy);
- groups.add(cp);
- }
- }
- snippetContentsCopy.setProcessGroups(groups);
-
- final Set<RemoteProcessGroupDTO> remoteGroups = new HashSet<>();
- if (snippetContents.getRemoteProcessGroups() != null) {
- for (final RemoteProcessGroupDTO remoteGroupDTO : snippetContents.getRemoteProcessGroups()) {
- final RemoteProcessGroupDTO cp = dtoFactory.copy(remoteGroupDTO);
- cp.setId(generateId(remoteGroupDTO.getId(), idGenerationSeed, isCopy));
- cp.setParentGroupId(groupId);
-
- final RemoteProcessGroupContentsDTO contents = cp.getContents();
- if (contents != null && contents.getInputPorts() != null) {
- for (final RemoteProcessGroupPortDTO remotePort : contents.getInputPorts()) {
- remotePort.setGroupId(cp.getId());
- connectableMap.put(remoteGroupDTO.getId() + "-" + remotePort.getId(), dtoFactory.createConnectableDto(remotePort, ConnectableType.REMOTE_INPUT_PORT));
+ // clone policies as appropriate
+ if (isCopy) {
+ cloneComponentSpecificPolicies(
+ ResourceFactory.getComponentResource(ResourceType.RemoteProcessGroup, remoteGroupDTO.getId(), remoteGroupDTO.getName()),
+ ResourceFactory.getComponentResource(ResourceType.RemoteProcessGroup, cp.getId(), cp.getName()), idGenerationSeed);
}
}
- if (contents != null && contents.getOutputPorts() != null) {
- for (final RemoteProcessGroupPortDTO remotePort : contents.getOutputPorts()) {
- remotePort.setGroupId(cp.getId());
- connectableMap.put(remoteGroupDTO.getId() + "-" + remotePort.getId(), dtoFactory.createConnectableDto(remotePort, ConnectableType.REMOTE_OUTPUT_PORT));
+ }
+ snippetContentsCopy.setRemoteProcessGroups(remoteGroups);
+
+ final Set<ConnectionDTO> connections = new HashSet<>();
+ if (snippetContents.getConnections() != null) {
+ for (final ConnectionDTO connectionDTO : snippetContents.getConnections()) {
+ final ConnectionDTO cp = dtoFactory.copy(connectionDTO);
+
+ final ConnectableDTO source = connectableMap.get(cp.getSource().getGroupId() + "-" + cp.getSource().getId());
+ final ConnectableDTO destination = connectableMap.get(cp.getDestination().getGroupId() + "-" + cp.getDestination().getId());
+
+ // ensure all referenced components are present
+ if (source == null || destination == null) {
+ throw new IllegalArgumentException("The flow snippet contains a Connection that references a component that is not included.");
}
- }
- remoteGroups.add(cp);
+ cp.setId(generateId(connectionDTO.getId(), idGenerationSeed, isCopy));
+ cp.setSource(source);
+ cp.setDestination(destination);
+ cp.setParentGroupId(groupId);
+ connections.add(cp);
+
+ // note - no need to copy policies of a connection as their permissions are inferred through the source and destination
+ }
}
- }
- snippetContentsCopy.setRemoteProcessGroups(remoteGroups);
+ snippetContentsCopy.setConnections(connections);
- final Set<ConnectionDTO> connections = new HashSet<>();
- if (snippetContents.getConnections() != null) {
- for (final ConnectionDTO connectionDTO : snippetContents.getConnections()) {
- final ConnectionDTO cp = dtoFactory.copy(connectionDTO);
+ return snippetContentsCopy;
+ } catch (Exception e) {
+ // attempt to role back any policies of the copies that were created in preparation for the clone
+ rollbackClonedPolicies(snippetContentsCopy);
- final ConnectableDTO source = connectableMap.get(cp.getSource().getGroupId() + "-" + cp.getSource().getId());
- final ConnectableDTO destination = connectableMap.get(cp.getDestination().getGroupId() + "-" + cp.getDestination().getId());
+ // rethrow the original exception
+ throw e;
+ }
+ }
- // ensure all referenced components are present
- if (source == null || destination == null) {
- throw new IllegalArgumentException("The flow snippet contains a Connection that references a component that is not included.");
+ /**
+ * Clones all the component specified policies for the specified original component. This will include the component resource, data resource
+ * for the component, data transfer resource for the component, and policy resource for the component.
+ *
+ * @param originalComponentResource original component resource
+ * @param clonedComponentResource cloned component resource
+ * @param idGenerationSeed id generation seed
+ */
+ private void cloneComponentSpecificPolicies(final Resource originalComponentResource, final Resource clonedComponentResource, final String idGenerationSeed) {
+ final Map<Resource, Resource> resources = new HashMap<>();
+ resources.put(originalComponentResource, clonedComponentResource);
+ resources.put(ResourceFactory.getDataResource(originalComponentResource), ResourceFactory.getDataResource(clonedComponentResource));
+ resources.put(ResourceFactory.getDataTransferResource(originalComponentResource), ResourceFactory.getDataTransferResource(clonedComponentResource));
+ resources.put(ResourceFactory.getPolicyResource(originalComponentResource), ResourceFactory.getPolicyResource(clonedComponentResource));
+
+ for (final Entry<Resource, Resource> entry : resources.entrySet()) {
+ final Resource originalResource = entry.getKey();
+ final Resource cloneResource = entry.getValue();
+
+ for (final RequestAction action : RequestAction.values()) {
+ final AccessPolicy accessPolicy = accessPolicyDAO.getAccessPolicy(action, originalResource.getIdentifier());
+
+ // if there is a component specific policy we want to clone it for the new component
+ if (accessPolicy != null) {
+ final AccessPolicyDTO cloneAccessPolicy = new AccessPolicyDTO();
+ cloneAccessPolicy.setId(generateId(accessPolicy.getIdentifier(), idGenerationSeed, true));
+ cloneAccessPolicy.setAction(accessPolicy.getAction().toString());
+ cloneAccessPolicy.setResource(cloneResource.getIdentifier());
+
+ final Set<TenantEntity> users = new HashSet<>();
+ accessPolicy.getUsers().forEach(userId -> {
+ final TenantEntity entity = new TenantEntity();
+ entity.setId(userId);
+ users.add(entity);
+ });
+ cloneAccessPolicy.setUsers(users);
+
+ final Set<TenantEntity> groups = new HashSet<>();
+ accessPolicy.getGroups().forEach(groupId -> {
+ final TenantEntity entity = new TenantEntity();
+ entity.setId(groupId);
+ groups.add(entity);
+ });
+ cloneAccessPolicy.setUserGroups(groups);
+
+ // create the access policy for the cloned policy
+ accessPolicyDAO.createAccessPolicy(cloneAccessPolicy);
}
-
- cp.setId(generateId(connectionDTO.getId(), idGenerationSeed, isCopy));
- cp.setSource(source);
- cp.setDestination(destination);
- cp.setParentGroupId(groupId);
- connections.add(cp);
}
}
- snippetContentsCopy.setConnections(connections);
+ }
+
+ /**
+ * Attempts to roll back and in the specified snippet.
+ *
+ * @param snippet snippet
+ */
+ public void rollbackClonedPolicies(final FlowSnippetDTO snippet) {
+ snippet.getControllerServices().forEach(controllerServiceDTO -> {
+ rollbackClonedPolicy(ResourceFactory.getComponentResource(ResourceType.ControllerService, controllerServiceDTO.getId(), controllerServiceDTO.getName()));
+ });
+ snippet.getFunnels().forEach(funnelDTO -> {
+ rollbackClonedPolicy(ResourceFactory.getComponentResource(ResourceType.Funnel, funnelDTO.getId(), funnelDTO.getId()));
+ });
+ snippet.getInputPorts().forEach(inputPortDTO -> {
+ rollbackClonedPolicy(ResourceFactory.getComponentResource(ResourceType.InputPort, inputPortDTO.getId(), inputPortDTO.getName()));
+ });
+ snippet.getLabels().forEach(labelDTO -> {
+ rollbackClonedPolicy(ResourceFactory.getComponentResource(ResourceType.Label, labelDTO.getId(), labelDTO.getLabel()));
+ });
+ snippet.getOutputPorts().forEach(outputPortDTO -> {
+ rollbackClonedPolicy(ResourceFactory.getComponentResource(ResourceType.OutputPort, outputPortDTO.getId(), outputPortDTO.getName()));
+ });
+ snippet.getProcessors().forEach(processorDTO -> {
+ rollbackClonedPolicy(ResourceFactory.getComponentResource(ResourceType.Processor, processorDTO.getId(), processorDTO.getName()));
+ });
+ snippet.getRemoteProcessGroups().forEach(remoteProcessGroupDTO -> {
+ rollbackClonedPolicy(ResourceFactory.getComponentResource(ResourceType.RemoteProcessGroup, remoteProcessGroupDTO.getId(), remoteProcessGroupDTO.getName()));
+ });
+ snippet.getProcessGroups().forEach(processGroupDTO -> {
+ rollbackClonedPolicy(ResourceFactory.getComponentResource(ResourceType.ProcessGroup, processGroupDTO.getId(), processGroupDTO.getName()));
+
+ // consider all descendant components
+ if (processGroupDTO.getContents() != null) {
+ rollbackClonedPolicies(processGroupDTO.getContents());
+ }
+ });
+ }
- return snippetContentsCopy;
+ /**
+ * Attempts to roll back all policies for the specified component. This includes the component resource, data resource
+ * for the component, data transfer resource for the component, and policy resource for the component.
+ *
+ * @param componentResource component resource
+ */
+ private void rollbackClonedPolicy(final Resource componentResource) {
+ final List<Resource> resources = new ArrayList<>();
+ resources.add(componentResource);
+ resources.add(ResourceFactory.getDataResource(componentResource));
+ resources.add(ResourceFactory.getDataTransferResource(componentResource));
+ resources.add(ResourceFactory.getPolicyResource(componentResource));
+
+ for (final Resource resource : resources) {
+ for (final RequestAction action : RequestAction.values()) {
+ final AccessPolicy accessPolicy = accessPolicyDAO.getAccessPolicy(action, resource.getIdentifier());
+ if (accessPolicy != null) {
+ try {
+ accessPolicyDAO.deleteAccessPolicy(accessPolicy.getIdentifier());
+ } catch (final Exception e) {
+ logger.warn(String.format("Unable to clean up cloned access policy for %s %s after failed copy/paste action.", action, componentResource.getIdentifier()), e);
+ }
+ }
+ }
+ }
}
private void updateControllerServiceIdentifiers(final FlowSnippetDTO snippet, final Map<String, String> serviceIdMap) {
@@ -585,6 +779,10 @@ public final class SnippetUtils {
this.flowController = flowController;
}
+ public void setAccessPolicyDAO(AccessPolicyDAO accessPolicyDAO) {
+ this.accessPolicyDAO = accessPolicyDAO;
+ }
+
/**
* Will normalize the coordinates of the processors to ensure their
* consistency across exports. It will do so by fist calculating the
http://git-wip-us.apache.org/repos/asf/nifi/blob/09b12471/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml
index 1f65084..bc3cc08 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/resources/nifi-web-api-context.xml
@@ -58,6 +58,7 @@
<bean id="snippetUtils" class="org.apache.nifi.web.util.SnippetUtils">
<property name="dtoFactory" ref="dtoFactory"/>
<property name="flowController" ref="flowController"/>
+ <property name="accessPolicyDAO" ref="policyBasedAuthorizerDAO"/>
</bean>
<!-- nifi component dao initialization -->