use of org.apache.nifi.web.Revision in project nifi by apache.
the class VersionsResource method updateFlowVersion.
@PUT
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("process-groups/{id}")
@ApiOperation(value = "Update the version of a Process Group with the given ID", response = VersionControlInformationEntity.class, notes = "For a Process Group that is already under Version Control, this will update the version of the flow to a different version. This endpoint expects " + "that the given snapshot will not modify any Processor that is currently running or any Controller Service that is enabled. " + NON_GUARANTEED_ENDPOINT, authorizations = { @Authorization(value = "Read - /process-groups/{uuid}"), @Authorization(value = "Write - /process-groups/{uuid}") })
@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 updateFlowVersion(@ApiParam("The process group id.") @PathParam("id") final String groupId, @ApiParam(value = "The controller service configuration details.", required = true) final VersionedFlowSnapshotEntity requestEntity) {
// Verify the request
final RevisionDTO revisionDto = requestEntity.getProcessGroupRevision();
if (revisionDto == null) {
throw new IllegalArgumentException("Process Group Revision must be specified.");
}
final VersionedFlowSnapshot requestFlowSnapshot = requestEntity.getVersionedFlowSnapshot();
if (requestFlowSnapshot == null) {
throw new IllegalArgumentException("Versioned Flow Snapshot must be supplied.");
}
final VersionedFlowSnapshotMetadata requestSnapshotMetadata = requestFlowSnapshot.getSnapshotMetadata();
if (requestSnapshotMetadata == null) {
throw new IllegalArgumentException("Snapshot Metadata must be supplied.");
}
if (requestSnapshotMetadata.getBucketIdentifier() == null) {
throw new IllegalArgumentException("The Bucket ID must be supplied.");
}
if (requestSnapshotMetadata.getFlowIdentifier() == null) {
throw new IllegalArgumentException("The Flow ID must be supplied.");
}
// Perform the request
if (isReplicateRequest()) {
return replicate(HttpMethod.PUT, requestEntity);
}
final Revision requestRevision = getRevision(requestEntity.getProcessGroupRevision(), groupId);
return withWriteLock(serviceFacade, requestEntity, requestRevision, lookup -> {
final ProcessGroupAuthorizable groupAuthorizable = lookup.getProcessGroup(groupId);
final Authorizable processGroup = groupAuthorizable.getAuthorizable();
processGroup.authorize(authorizer, RequestAction.READ, NiFiUserUtils.getNiFiUser());
processGroup.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
}, () -> {
// We do not enforce that the Process Group is 'not dirty' because at this point,
// the client has explicitly indicated the dataflow that the Process Group should
// provide and provided the Revision to ensure that they have the most up-to-date
// view of the Process Group.
serviceFacade.verifyCanUpdate(groupId, requestFlowSnapshot, true, false);
}, (rev, entity) -> {
final VersionedFlowSnapshot flowSnapshot = entity.getVersionedFlowSnapshot();
final VersionedFlowSnapshotMetadata snapshotMetadata = flowSnapshot.getSnapshotMetadata();
final Bucket bucket = flowSnapshot.getBucket();
final VersionedFlow flow = flowSnapshot.getFlow();
// Update the Process Group to match the proposed flow snapshot
final VersionControlInformationDTO versionControlInfoDto = new VersionControlInformationDTO();
versionControlInfoDto.setBucketId(snapshotMetadata.getBucketIdentifier());
versionControlInfoDto.setBucketName(bucket.getName());
versionControlInfoDto.setFlowId(snapshotMetadata.getFlowIdentifier());
versionControlInfoDto.setFlowName(flow.getName());
versionControlInfoDto.setFlowDescription(flow.getDescription());
versionControlInfoDto.setGroupId(groupId);
versionControlInfoDto.setVersion(snapshotMetadata.getVersion());
versionControlInfoDto.setRegistryId(entity.getRegistryId());
versionControlInfoDto.setRegistryName(serviceFacade.getFlowRegistryName(entity.getRegistryId()));
final VersionedFlowState flowState = snapshotMetadata.getVersion() == flow.getVersionCount() ? VersionedFlowState.UP_TO_DATE : VersionedFlowState.STALE;
versionControlInfoDto.setState(flowState.name());
final NiFiUser user = NiFiUserUtils.getNiFiUser();
final ProcessGroupEntity updatedGroup = serviceFacade.updateProcessGroupContents(user, rev, groupId, versionControlInfoDto, flowSnapshot, getIdGenerationSeed().orElse(null), false, true, entity.getUpdateDescendantVersionedFlows());
final VersionControlInformationDTO updatedVci = updatedGroup.getComponent().getVersionControlInformation();
final VersionControlInformationEntity responseEntity = new VersionControlInformationEntity();
responseEntity.setProcessGroupRevision(updatedGroup.getRevision());
responseEntity.setVersionControlInformation(updatedVci);
return generateOkResponse(responseEntity).build();
});
}
use of org.apache.nifi.web.Revision in project nifi by apache.
the class DtoFactory method mapRevisionToDto.
private Map<String, RevisionDTO> mapRevisionToDto(final Map<String, Revision> revisionMap) {
final Map<String, RevisionDTO> dtos = new HashMap<>(revisionMap.size());
for (final Map.Entry<String, Revision> entry : revisionMap.entrySet()) {
final Revision revision = entry.getValue();
final RevisionDTO revisionDto = new RevisionDTO();
revisionDto.setClientId(revision.getClientId());
revisionDto.setVersion(revision.getVersion());
dtos.put(entry.getKey(), revisionDto);
}
return dtos;
}
use of org.apache.nifi.web.Revision in project nifi by apache.
the class FlowResource method scheduleComponents.
/**
* Updates the specified process group.
*
* @param httpServletRequest request
* @param id The id of the process group.
* @param requestScheduleComponentsEntity A scheduleComponentsEntity.
* @return A processGroupEntity.
*/
@PUT
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("process-groups/{id}")
@ApiOperation(value = "Schedule or unschedule components in the specified Process Group.", response = ScheduleComponentsEntity.class, authorizations = { @Authorization(value = "Read - /flow"), @Authorization(value = "Write - /{component-type}/{uuid} - For every component being scheduled/unscheduled") })
@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 scheduleComponents(@Context HttpServletRequest httpServletRequest, @ApiParam(value = "The process group id.", required = true) @PathParam("id") String id, @ApiParam(value = "The request to schedule or unschedule. If the comopnents in the request are not specified, all authorized components will be considered.", required = true) final ScheduleComponentsEntity requestScheduleComponentsEntity) {
// ensure the same id is being used
if (!id.equals(requestScheduleComponentsEntity.getId())) {
throw new IllegalArgumentException(String.format("The process group id (%s) in the request body does " + "not equal the process group id of the requested resource (%s).", requestScheduleComponentsEntity.getId(), id));
}
final ScheduledState state;
if (requestScheduleComponentsEntity.getState() == null) {
throw new IllegalArgumentException("The scheduled state must be specified.");
} else {
try {
state = ScheduledState.valueOf(requestScheduleComponentsEntity.getState());
} catch (final IllegalArgumentException iae) {
throw new IllegalArgumentException(String.format("The scheduled must be one of [%s].", StringUtils.join(EnumSet.of(ScheduledState.RUNNING, ScheduledState.STOPPED), ", ")));
}
}
// ensure its a supported scheduled state
if (ScheduledState.DISABLED.equals(state) || ScheduledState.STARTING.equals(state) || ScheduledState.STOPPING.equals(state)) {
throw new IllegalArgumentException(String.format("The scheduled must be one of [%s].", StringUtils.join(EnumSet.of(ScheduledState.RUNNING, ScheduledState.STOPPED), ", ")));
}
// if the components are not specified, gather all components and their current revision
if (requestScheduleComponentsEntity.getComponents() == null) {
// get the current revisions for the components being updated
final Set<Revision> revisions = serviceFacade.getRevisionsFromGroup(id, group -> {
final Set<String> componentIds = new HashSet<>();
// ensure authorized for each processor we will attempt to schedule
group.findAllProcessors().stream().filter(ScheduledState.RUNNING.equals(state) ? ProcessGroup.SCHEDULABLE_PROCESSORS : ProcessGroup.UNSCHEDULABLE_PROCESSORS).filter(processor -> processor.isAuthorized(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser())).forEach(processor -> {
componentIds.add(processor.getIdentifier());
});
// ensure authorized for each input port we will attempt to schedule
group.findAllInputPorts().stream().filter(ScheduledState.RUNNING.equals(state) ? ProcessGroup.SCHEDULABLE_PORTS : ProcessGroup.UNSCHEDULABLE_PORTS).filter(inputPort -> inputPort.isAuthorized(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser())).forEach(inputPort -> {
componentIds.add(inputPort.getIdentifier());
});
// ensure authorized for each output port we will attempt to schedule
group.findAllOutputPorts().stream().filter(ScheduledState.RUNNING.equals(state) ? ProcessGroup.SCHEDULABLE_PORTS : ProcessGroup.UNSCHEDULABLE_PORTS).filter(outputPort -> outputPort.isAuthorized(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser())).forEach(outputPort -> {
componentIds.add(outputPort.getIdentifier());
});
return componentIds;
});
// build the component mapping
final Map<String, RevisionDTO> componentsToSchedule = new HashMap<>();
revisions.forEach(revision -> {
final RevisionDTO dto = new RevisionDTO();
dto.setClientId(revision.getClientId());
dto.setVersion(revision.getVersion());
componentsToSchedule.put(revision.getComponentId(), dto);
});
// set the components and their current revision
requestScheduleComponentsEntity.setComponents(componentsToSchedule);
}
if (isReplicateRequest()) {
return replicate(HttpMethod.PUT, requestScheduleComponentsEntity);
}
final Map<String, RevisionDTO> requestComponentsToSchedule = requestScheduleComponentsEntity.getComponents();
final Map<String, Revision> requestComponentRevisions = requestComponentsToSchedule.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> getRevision(e.getValue(), e.getKey())));
final Set<Revision> requestRevisions = new HashSet<>(requestComponentRevisions.values());
return withWriteLock(serviceFacade, requestScheduleComponentsEntity, requestRevisions, lookup -> {
// ensure access to the flow
authorizeFlow();
// ensure access to every component being scheduled
requestComponentsToSchedule.keySet().forEach(componentId -> {
final Authorizable connectable = lookup.getLocalConnectable(componentId);
connectable.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
});
}, () -> serviceFacade.verifyScheduleComponents(id, state, requestComponentRevisions.keySet()), (revisions, scheduleComponentsEntity) -> {
final ScheduledState scheduledState = ScheduledState.valueOf(scheduleComponentsEntity.getState());
final Map<String, RevisionDTO> componentsToSchedule = scheduleComponentsEntity.getComponents();
final Map<String, Revision> componentRevisions = componentsToSchedule.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> getRevision(e.getValue(), e.getKey())));
// update the process group
final ScheduleComponentsEntity entity = serviceFacade.scheduleComponents(id, scheduledState, componentRevisions);
return generateOkResponse(entity).build();
});
}
use of org.apache.nifi.web.Revision in project nifi by apache.
the class FunnelResource method updateFunnel.
/**
* Creates a new Funnel.
*
* @param httpServletRequest request
* @param id The id of the funnel to update.
* @param requestFunnelEntity A funnelEntity.
* @return A funnelEntity.
*/
@PUT
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("{id}")
@ApiOperation(value = "Updates a funnel", response = FunnelEntity.class, authorizations = { @Authorization(value = "Write - /funnels/{uuid}") })
@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 updateFunnel(@Context final HttpServletRequest httpServletRequest, @ApiParam(value = "The funnel id.", required = true) @PathParam("id") final String id, @ApiParam(value = "The funnel configuration details.", required = true) final FunnelEntity requestFunnelEntity) {
if (requestFunnelEntity == null || requestFunnelEntity.getComponent() == null) {
throw new IllegalArgumentException("Funnel details must be specified.");
}
if (requestFunnelEntity.getRevision() == null) {
throw new IllegalArgumentException("Revision must be specified.");
}
// ensure the ids are the same
final FunnelDTO requestFunnelDTO = requestFunnelEntity.getComponent();
if (!id.equals(requestFunnelDTO.getId())) {
throw new IllegalArgumentException(String.format("The funnel id (%s) in the request body does not equal the " + "funnel id of the requested resource (%s).", requestFunnelDTO.getId(), id));
}
final PositionDTO proposedPosition = requestFunnelDTO.getPosition();
if (proposedPosition != null) {
if (proposedPosition.getX() == null || proposedPosition.getY() == null) {
throw new IllegalArgumentException("The x and y coordinate of the proposed position must be specified.");
}
}
if (isReplicateRequest()) {
return replicate(HttpMethod.PUT, requestFunnelEntity);
}
// Extract the revision
final Revision requestRevision = getRevision(requestFunnelEntity, id);
return withWriteLock(serviceFacade, requestFunnelEntity, requestRevision, lookup -> {
Authorizable authorizable = lookup.getFunnel(id);
authorizable.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
}, null, (revision, funnelEntity) -> {
// update the funnel
final FunnelEntity entity = serviceFacade.updateFunnel(revision, funnelEntity.getComponent());
populateRemainingFunnelEntityContent(entity);
return generateOkResponse(entity).build();
});
}
use of org.apache.nifi.web.Revision in project nifi by apache.
the class FunnelResource method removeFunnel.
/**
* Removes the specified funnel.
*
* @param httpServletRequest request
* @param version The revision is used to verify the client is working with
* the latest version of the flow.
* @param clientId Optional client id. If the client id is not specified, a
* new one will be generated. This value (whether specified or generated) is
* included in the response.
* @param id The id of the funnel to remove.
* @return A entity containing the client id and an updated revision.
*/
@DELETE
@Consumes(MediaType.WILDCARD)
@Produces(MediaType.APPLICATION_JSON)
@Path("{id}")
@ApiOperation(value = "Deletes a funnel", response = FunnelEntity.class, authorizations = { @Authorization(value = "Write - /funnels/{uuid}"), @Authorization(value = "Write - Parent Process Group - /process-groups/{uuid}") })
@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 removeFunnel(@Context final HttpServletRequest httpServletRequest, @ApiParam(value = "The revision is used to verify the client is working with the latest version of the flow.", required = false) @QueryParam(VERSION) final LongParameter version, @ApiParam(value = "If the client id is not specified, new one will be generated. This value (whether specified or generated) is included in the response.", required = false) @QueryParam(CLIENT_ID) @DefaultValue(StringUtils.EMPTY) final ClientIdParameter clientId, @ApiParam(value = "The funnel id.", required = true) @PathParam("id") final String id) {
if (isReplicateRequest()) {
return replicate(HttpMethod.DELETE);
}
final FunnelEntity requestFunnelEntity = new FunnelEntity();
requestFunnelEntity.setId(id);
// handle expects request (usually from the cluster manager)
final Revision requestRevision = new Revision(version == null ? null : version.getLong(), clientId.getClientId(), id);
return withWriteLock(serviceFacade, requestFunnelEntity, requestRevision, lookup -> {
final Authorizable funnel = lookup.getFunnel(id);
// ensure write permission to the funnel
funnel.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
// ensure write permission to the parent process group
funnel.getParentAuthorizable().authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
}, () -> serviceFacade.verifyDeleteFunnel(id), (revision, funnelEntity) -> {
// delete the specified funnel
final FunnelEntity entity = serviceFacade.deleteFunnel(revision, funnelEntity.getId());
return generateOkResponse(entity).build();
});
}
Aggregations