use of org.apache.nifi.connectable.Connectable in project nifi by apache.
the class StandardNiFiServiceFacade method mapToConnectableId.
private void mapToConnectableId(final Collection<? extends Connectable> connectables, final Map<String, List<Connectable>> destination) {
for (final Connectable connectable : connectables) {
final Optional<String> versionedIdOption = connectable.getVersionedComponentId();
// Determine the Versioned ID by using the ID that is assigned, if one is. Otherwise,
// we will calculate the Versioned ID. This allows us to map connectables that currently are not under
// version control. We have to do this so that if we are changing flow versions and have a component that is running and it does not exist
// in the Versioned Flow, we still need to be able to create an AffectedComponentDTO for it.
final String versionedId;
if (versionedIdOption.isPresent()) {
versionedId = versionedIdOption.get();
} else {
versionedId = UUID.nameUUIDFromBytes(connectable.getIdentifier().getBytes(StandardCharsets.UTF_8)).toString();
}
final List<Connectable> byVersionedId = destination.computeIfAbsent(versionedId, key -> new ArrayList<>());
byVersionedId.add(connectable);
}
}
use of org.apache.nifi.connectable.Connectable in project nifi by apache.
the class ConnectionResource method updateConnection.
/**
* Updates the specified connection.
*
* @param httpServletRequest request
* @param id The id of the connection.
* @param requestConnectionEntity A connectionEntity.
* @return A connectionEntity.
* @throws InterruptedException if interrupted
*/
@PUT
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("/{id}")
@ApiOperation(value = "Updates a connection", response = ConnectionEntity.class, authorizations = { @Authorization(value = "Write Source - /{component-type}/{uuid}"), @Authorization(value = "Write Destination - /{component-type}/{uuid}"), @Authorization(value = "Write New Destination - /{component-type}/{uuid} - if updating Destination"), @Authorization(value = "Write Process Group - /process-groups/{uuid} - if updating Destination") })
@ApiResponses(value = { @ApiResponse(code = 400, message = "NiFi was unable to complete the request because it was invalid. The request should not be retried without modification."), @ApiResponse(code = 401, message = "Client could not be authenticated."), @ApiResponse(code = 403, message = "Client is not authorized to make this request."), @ApiResponse(code = 404, message = "The specified resource could not be found."), @ApiResponse(code = 409, message = "The request was valid but NiFi was not in the appropriate state to process it. Retrying the same request later may be successful.") })
public Response updateConnection(@Context HttpServletRequest httpServletRequest, @ApiParam(value = "The connection id.", required = true) @PathParam("id") final String id, @ApiParam(value = "The connection configuration details.", required = true) final ConnectionEntity requestConnectionEntity) throws InterruptedException {
if (requestConnectionEntity == null || requestConnectionEntity.getComponent() == null) {
throw new IllegalArgumentException("Connection details must be specified.");
}
if (requestConnectionEntity.getRevision() == null) {
throw new IllegalArgumentException("Revision must be specified.");
}
// ensure the ids are the same
final ConnectionDTO requestConnection = requestConnectionEntity.getComponent();
if (!id.equals(requestConnection.getId())) {
throw new IllegalArgumentException(String.format("The connection id " + "(%s) in the request body does not equal the connection id of the " + "requested resource (%s).", requestConnection.getId(), id));
}
if (requestConnection.getDestination() != null) {
if (requestConnection.getDestination().getId() == null) {
throw new IllegalArgumentException("When specifying a destination component, the destination id is required.");
}
if (requestConnection.getDestination().getType() == null) {
throw new IllegalArgumentException("When specifying a destination component, the type of the destination is required.");
}
}
final List<PositionDTO> proposedBends = requestConnection.getBends();
if (proposedBends != null) {
for (final PositionDTO proposedBend : proposedBends) {
if (proposedBend.getX() == null || proposedBend.getY() == null) {
throw new IllegalArgumentException("The x and y coordinate of the each bend must be specified.");
}
}
}
if (isReplicateRequest()) {
return replicate(HttpMethod.PUT, requestConnectionEntity);
}
final Revision requestRevision = getRevision(requestConnectionEntity, id);
return withWriteLock(serviceFacade, requestConnectionEntity, requestRevision, lookup -> {
// verifies write access to this connection (this checks the current source and destination)
ConnectionAuthorizable connAuth = lookup.getConnection(id);
connAuth.getAuthorizable().authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
// if a destination has been specified and is different
final Connectable currentDestination = connAuth.getDestination();
if (requestConnection.getDestination() != null && !currentDestination.getIdentifier().equals(requestConnection.getDestination().getId())) {
try {
final ConnectableType destinationConnectableType = ConnectableType.valueOf(requestConnection.getDestination().getType());
// explicitly handle RPGs differently as the connectable id can be ambiguous if self referencing
final Authorizable newDestinationAuthorizable;
if (ConnectableType.REMOTE_INPUT_PORT.equals(destinationConnectableType)) {
newDestinationAuthorizable = lookup.getRemoteProcessGroup(requestConnection.getDestination().getGroupId());
} else {
newDestinationAuthorizable = lookup.getLocalConnectable(requestConnection.getDestination().getId());
}
// verify access of the new destination (current destination was already authorized as part of the connection check)
newDestinationAuthorizable.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
} catch (final IllegalArgumentException e) {
throw new IllegalArgumentException(String.format("Unrecognized destination type %s. Excepted values are [%s]", requestConnection.getDestination().getType(), StringUtils.join(ConnectableType.values(), ", ")));
}
// verify access of the parent group (this is the same check that is performed when creating the connection)
connAuth.getParentGroup().authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
}
}, () -> serviceFacade.verifyUpdateConnection(requestConnection), (revision, connectionEntity) -> {
final ConnectionDTO connection = connectionEntity.getComponent();
final ConnectionEntity entity = serviceFacade.updateConnection(revision, connection);
populateRemainingConnectionEntityContent(entity);
// generate the response
return generateOkResponse(entity).build();
});
}
use of org.apache.nifi.connectable.Connectable in project nifi by apache.
the class ControllerSearchService method search.
private ComponentSearchResultDTO search(final String searchStr, final Connection connection) {
final List<String> matches = new ArrayList<>();
// search id and name
addIfAppropriate(searchStr, connection.getIdentifier(), "Id", matches);
addIfAppropriate(searchStr, connection.getVersionedComponentId().orElse(null), "Version Control ID", matches);
addIfAppropriate(searchStr, connection.getName(), "Name", matches);
// search relationships
for (final Relationship relationship : connection.getRelationships()) {
addIfAppropriate(searchStr, relationship.getName(), "Relationship", matches);
}
// search prioritizers
final FlowFileQueue queue = connection.getFlowFileQueue();
for (final FlowFilePrioritizer comparator : queue.getPriorities()) {
addIfAppropriate(searchStr, comparator.getClass().getName(), "Prioritizer", matches);
}
// search expiration
if (StringUtils.containsIgnoreCase("expires", searchStr) || StringUtils.containsIgnoreCase("expiration", searchStr)) {
final int expirationMillis = connection.getFlowFileQueue().getFlowFileExpiration(TimeUnit.MILLISECONDS);
if (expirationMillis > 0) {
matches.add("FlowFile expiration: " + connection.getFlowFileQueue().getFlowFileExpiration());
}
}
// search back pressure
if (StringUtils.containsIgnoreCase("back pressure", searchStr) || StringUtils.containsIgnoreCase("pressure", searchStr)) {
final String backPressureDataSize = connection.getFlowFileQueue().getBackPressureDataSizeThreshold();
final Double backPressureBytes = DataUnit.parseDataSize(backPressureDataSize, DataUnit.B);
if (backPressureBytes > 0) {
matches.add("Back pressure data size: " + backPressureDataSize);
}
final long backPressureCount = connection.getFlowFileQueue().getBackPressureObjectThreshold();
if (backPressureCount > 0) {
matches.add("Back pressure count: " + backPressureCount);
}
}
// search the source
final Connectable source = connection.getSource();
addIfAppropriate(searchStr, source.getIdentifier(), "Source id", matches);
addIfAppropriate(searchStr, source.getName(), "Source name", matches);
addIfAppropriate(searchStr, source.getComments(), "Source comments", matches);
// search the destination
final Connectable destination = connection.getDestination();
addIfAppropriate(searchStr, destination.getIdentifier(), "Destination id", matches);
addIfAppropriate(searchStr, destination.getName(), "Destination name", matches);
addIfAppropriate(searchStr, destination.getComments(), "Destination comments", matches);
if (matches.isEmpty()) {
return null;
}
final ComponentSearchResultDTO result = new ComponentSearchResultDTO();
result.setId(connection.getIdentifier());
// determine the name of the search match
if (StringUtils.isNotBlank(connection.getName())) {
result.setName(connection.getName());
} else if (!connection.getRelationships().isEmpty()) {
final List<String> relationships = new ArrayList<>(connection.getRelationships().size());
for (final Relationship relationship : connection.getRelationships()) {
if (StringUtils.isNotBlank(relationship.getName())) {
relationships.add(relationship.getName());
}
}
if (!relationships.isEmpty()) {
result.setName(StringUtils.join(relationships, ", "));
}
}
// ensure a name is added
if (result.getName() == null) {
result.setName("From source " + connection.getSource().getName());
}
result.setMatches(matches);
return result;
}
use of org.apache.nifi.connectable.Connectable in project nifi by apache.
the class StandardConnectionDAO method updateConnection.
@Override
public Connection updateConnection(final ConnectionDTO connectionDTO) {
final Connection connection = locateConnection(connectionDTO.getId());
final ProcessGroup group = connection.getProcessGroup();
// ensure we can update
verifyUpdate(connection, connectionDTO);
final Collection<Relationship> newProcessorRelationships = new ArrayList<>();
Connectable newDestination = null;
// ensure that the source ID is correct, if specified.
final Connectable existingSource = connection.getSource();
if (isNotNull(connectionDTO.getSource()) && !existingSource.getIdentifier().equals(connectionDTO.getSource().getId())) {
throw new IllegalStateException("Connection with ID " + connectionDTO.getId() + " has conflicting Source ID");
}
// determine any new relationships
final Set<String> relationships = connectionDTO.getSelectedRelationships();
if (isNotNull(relationships)) {
if (relationships.isEmpty()) {
throw new IllegalArgumentException("Cannot remove all relationships from Connection with ID " + connection.getIdentifier() + " -- remove the Connection instead");
}
if (existingSource == null) {
throw new IllegalArgumentException("Cannot specify new relationships without including the source.");
}
for (final String relationship : relationships) {
final Relationship processorRelationship = existingSource.getRelationship(relationship);
if (processorRelationship == null) {
throw new IllegalArgumentException("Unable to locate " + relationship + " relationship.");
}
newProcessorRelationships.add(processorRelationship);
}
}
// determine if the destination changed
final ConnectableDTO proposedDestination = connectionDTO.getDestination();
if (proposedDestination != null) {
final Connectable currentDestination = connection.getDestination();
// handle remote input port differently
if (ConnectableType.REMOTE_INPUT_PORT.name().equals(proposedDestination.getType())) {
// the group id must be specified
if (proposedDestination.getGroupId() == null) {
throw new IllegalArgumentException("When the destination is a remote input port its group id is required.");
}
// if the current destination is a remote input port
boolean isDifferentRemoteProcessGroup = false;
if (currentDestination.getConnectableType() == ConnectableType.REMOTE_INPUT_PORT) {
RemoteGroupPort remotePort = (RemoteGroupPort) currentDestination;
if (!proposedDestination.getGroupId().equals(remotePort.getRemoteProcessGroup().getIdentifier())) {
isDifferentRemoteProcessGroup = true;
}
}
// if the destination is changing or the previous destination was a different remote process group
if (!proposedDestination.getId().equals(currentDestination.getIdentifier()) || isDifferentRemoteProcessGroup) {
final ProcessGroup destinationParentGroup = locateProcessGroup(flowController, group.getIdentifier());
final RemoteProcessGroup remoteProcessGroup = destinationParentGroup.getRemoteProcessGroup(proposedDestination.getGroupId());
// ensure the remote process group was found
if (remoteProcessGroup == null) {
throw new IllegalArgumentException("Unable to find the specified remote process group.");
}
final RemoteGroupPort remoteInputPort = remoteProcessGroup.getInputPort(proposedDestination.getId());
// ensure the new destination was found
if (remoteInputPort == null) {
throw new IllegalArgumentException("Unable to find the specified destination.");
}
// ensure the remote port actually exists
if (!remoteInputPort.getTargetExists()) {
throw new IllegalArgumentException("The specified remote input port does not exist.");
} else {
newDestination = remoteInputPort;
}
}
} else {
// if there is a different destination id
if (!proposedDestination.getId().equals(currentDestination.getIdentifier())) {
// if the destination connectable's group id has not been set, its inferred to be the current group
if (proposedDestination.getGroupId() == null) {
proposedDestination.setGroupId(group.getIdentifier());
}
final ProcessGroup destinationGroup = locateProcessGroup(flowController, proposedDestination.getGroupId());
newDestination = destinationGroup.getConnectable(proposedDestination.getId());
// ensure the new destination was found
if (newDestination == null) {
throw new IllegalArgumentException("Unable to find the specified destination.");
}
}
}
}
// configure the connection
configureConnection(connection, connectionDTO);
// update the relationships if necessary
if (!newProcessorRelationships.isEmpty()) {
connection.setRelationships(newProcessorRelationships);
}
// update the destination if necessary
if (isNotNull(newDestination)) {
connection.setDestination(newDestination);
}
return connection;
}
use of org.apache.nifi.connectable.Connectable in project nifi by apache.
the class StandardProcessGroupDAO method scheduleComponents.
@Override
public Future<Void> scheduleComponents(final String groupId, final ScheduledState state, final Set<String> componentIds) {
final ProcessGroup group = locateProcessGroup(flowController, groupId);
CompletableFuture<Void> future = CompletableFuture.completedFuture(null);
for (final String componentId : componentIds) {
final Connectable connectable = group.findLocalConnectable(componentId);
if (ScheduledState.RUNNING.equals(state)) {
switch(connectable.getConnectableType()) {
case PROCESSOR:
final CompletableFuture<?> processorFuture = connectable.getProcessGroup().startProcessor((ProcessorNode) connectable, true);
future = CompletableFuture.allOf(future, processorFuture);
break;
case INPUT_PORT:
connectable.getProcessGroup().startInputPort((Port) connectable);
break;
case OUTPUT_PORT:
connectable.getProcessGroup().startOutputPort((Port) connectable);
break;
case REMOTE_INPUT_PORT:
case REMOTE_OUTPUT_PORT:
final RemoteGroupPort remotePort = group.findRemoteGroupPort(componentId);
remotePort.getRemoteProcessGroup().startTransmitting(remotePort);
break;
}
} else {
switch(connectable.getConnectableType()) {
case PROCESSOR:
final CompletableFuture<?> processorFuture = connectable.getProcessGroup().stopProcessor((ProcessorNode) connectable);
future = CompletableFuture.allOf(future, processorFuture);
break;
case INPUT_PORT:
connectable.getProcessGroup().stopInputPort((Port) connectable);
break;
case OUTPUT_PORT:
connectable.getProcessGroup().stopOutputPort((Port) connectable);
break;
case REMOTE_INPUT_PORT:
case REMOTE_OUTPUT_PORT:
final RemoteGroupPort remotePort = group.findRemoteGroupPort(componentId);
remotePort.getRemoteProcessGroup().stopTransmitting(remotePort);
break;
}
}
}
return future;
}
Aggregations