use of org.apache.nifi.web.api.entity.UpdateControllerServiceReferenceRequestEntity in project kylo by Teradata.
the class AbstractNiFiControllerServicesRestClient method updateServiceAndReferencingComponents.
/**
* Updates a controller service
* This will first disable the service, stop all referencing components, enable the service, reset the state of the components back to their prior state
*
* @param controllerService the service to update with the updated properties
* @return the updates service
*/
@Override
public ControllerServiceDTO updateServiceAndReferencingComponents(ControllerServiceDTO controllerService) {
String id = controllerService.getId();
// Get all references to this controller service. this will include processors, other controller services, and reporting tasks
Optional<ControllerServiceReferencingComponentsEntity> references = getReferences(id);
// state of the processors prior to update
Map<String, String> previousProcessorState = null;
// revisions for the processor references
Map<String, RevisionDTO> processorRevisions = null;
// revisions for the controller service references
Map<String, RevisionDTO> controllerServiceRevisions = null;
// a map of component id to reference entity. this will include all referencing processors, controller services, and reporting tasks
Map<String, ControllerServiceReferencingComponentEntity> referencingComponentEntityMap = null;
// Stop all processor references and also disable any other controller service references
if (references.isPresent()) {
// build the reference state and revision maps prior to making this update
referencingComponentEntityMap = getReferencingComponents(references.get().getControllerServiceReferencingComponents());
previousProcessorState = referencingComponentEntityMap.values().stream().filter(e -> e.getComponent().getReferenceType().equalsIgnoreCase("PROCESSOR")).map(c -> c.getComponent()).collect(Collectors.toMap(ControllerServiceReferencingComponentDTO::getId, ControllerServiceReferencingComponentDTO::getState));
processorRevisions = referencingComponentEntityMap.values().stream().filter(e -> e.getComponent().getReferenceType().equalsIgnoreCase("PROCESSOR")).collect(Collectors.toMap(ControllerServiceReferencingComponentEntity::getId, ControllerServiceReferencingComponentEntity::getRevision));
controllerServiceRevisions = referencingComponentEntityMap.values().stream().filter(e -> e.getComponent().getReferenceType().equalsIgnoreCase("ControllerService")).collect(Collectors.toMap(ControllerServiceReferencingComponentEntity::getId, ControllerServiceReferencingComponentEntity::getRevision));
// Stop the referencing processors and ensure they are in the stopped state
if (!processorRevisions.isEmpty()) {
String state = NifiProcessUtil.PROCESS_STATE.STOPPED.name();
log.info("Stopping all component references to controller service {} ", controllerService.getName());
UpdateControllerServiceReferenceRequestEntity stopComponentsRequest = new UpdateControllerServiceReferenceRequestEntity();
stopComponentsRequest.setState(state);
stopComponentsRequest.setId(controllerService.getId());
stopComponentsRequest.setReferencingComponentRevisions(processorRevisions);
updateReferences(id, stopComponentsRequest);
boolean updatedReferences = ensureComponentsAreOfState(id, "Processor", state, 5, 500, TimeUnit.MILLISECONDS);
if (!updatedReferences) {
// error unable to change the state of the references. ... error
throw new NifiClientRuntimeException("Unable to stop processor references to this controller service " + controllerService.getName() + " before making the update");
}
}
// disable any controller service references
if (!controllerServiceRevisions.isEmpty()) {
UpdateControllerServiceReferenceRequestEntity stopComponentsRequest = new UpdateControllerServiceReferenceRequestEntity();
stopComponentsRequest.setState("DISABLED");
stopComponentsRequest.setId(controllerService.getId());
stopComponentsRequest.setReferencingComponentRevisions(controllerServiceRevisions);
updateReferences(id, stopComponentsRequest);
boolean updatedReferences = ensureComponentsAreOfState(id, "ControllerService", "DISABLED", 5, 500, TimeUnit.MILLISECONDS);
if (!updatedReferences) {
// error unable to change the state of the references. ... error
throw new NifiClientRuntimeException("Unable to disable other controller service references to this controller service " + controllerService.getName() + " before making the update");
}
}
}
// mark this controller service as disabled
log.info("Disabling the controller service {} ", controllerService.getName());
// update the service and mark it disabled. this will throw a RuntimeException if it is not successful
ControllerServiceDTO updatedService = updateStateByIdWithRetries(controllerService.getId(), "DISABLED", 5, 500, TimeUnit.MILLISECONDS);
// Perform the update to this controller service
log.info("Updating the controller service {} ", controllerService.getName());
updatedService = update(controllerService);
// Enable the service
updateStateById(controllerService.getId(), NiFiControllerServicesRestClient.State.ENABLED);
// Enable any controller service references
if (!controllerServiceRevisions.isEmpty()) {
log.info("Enabling other controller services referencing this controller service {} ", controllerService.getName());
UpdateControllerServiceReferenceRequestEntity enableReferenceServicesRequest = new UpdateControllerServiceReferenceRequestEntity();
enableReferenceServicesRequest.setId(controllerService.getId());
enableReferenceServicesRequest.setState(NiFiControllerServicesRestClient.State.ENABLED.name());
enableReferenceServicesRequest.setReferencingComponentRevisions(controllerServiceRevisions);
updateReferences(id, enableReferenceServicesRequest);
boolean updatedReferences = ensureComponentsAreOfState(id, "ControllerService", NiFiControllerServicesRestClient.State.ENABLED.name(), 5, 500, TimeUnit.MILLISECONDS);
if (!updatedReferences) {
// error unable to change the state of the references. ... error
throw new NifiClientRuntimeException("The controller service " + controllerService.getName() + " was updated, but it was unable to enable other controller service references to this controller service. Please visit NiFi to reconcile and fix any controller service issues. " + controllerService.getName());
}
}
if (references.isPresent() && previousProcessorState != null) {
// reset the processor state
Map<String, RevisionDTO> finalComponentRevisions = processorRevisions;
// if all referencing processors of of the same state we can call the quick rest endpoint to update all of them
Set<String> distinctStates = previousProcessorState.values().stream().collect(Collectors.toSet());
if (distinctStates.size() > 0) {
if (distinctStates.size() == 1) {
String state = new ArrayList<>(distinctStates).get(0);
if (!NifiProcessUtil.PROCESS_STATE.STOPPED.name().equals(state)) {
UpdateControllerServiceReferenceRequestEntity startComponentsRequest = new UpdateControllerServiceReferenceRequestEntity();
startComponentsRequest.setState(state);
startComponentsRequest.setReferencingComponentRevisions(finalComponentRevisions);
startComponentsRequest.setId(controllerService.getId());
updateReferences(id, startComponentsRequest);
log.info("Updating all component references to be {} for controller service {} ", state, controllerService.getName());
boolean updatedReferences = ensureComponentsAreOfState(id, "Processor", state, 5, 500, TimeUnit.MILLISECONDS);
if (!updatedReferences) {
// error unable to change the state of the references. ... error
throw new NifiClientRuntimeException("The controller service {} was updated, but it was unable to update the state of the processors as " + state + ". Please visit NiFi to reconcile and fix any controller service issues. " + controllerService.getName());
}
log.info("Successfully updated controller service {}", controllerService.getName());
}
} else {
log.info("The controller service component references ({} total) had mixed states prior to updating {}. Going through each processor/component and setting its state back to what it was prior to the update.", previousProcessorState.size(), distinctStates);
// update references back to previous states
List<ProcessorEntity> updatedProcessors = references.get().getControllerServiceReferencingComponents().stream().filter(c -> c.getComponent().getReferenceType().equalsIgnoreCase("PROCESSOR")).filter(c -> !c.getComponent().getState().equals(NifiProcessUtil.PROCESS_STATE.STOPPED.name())).map(referencingComponentEntity -> referencingComponentEntity.getComponent()).map(c -> {
ProcessorEntity entity = new ProcessorEntity();
entity.setRevision(finalComponentRevisions.get(c.getId()));
entity.setId(c.getId());
ProcessorDTO processorDTO = new ProcessorDTO();
processorDTO.setId(c.getId());
processorDTO.setState(c.getState());
entity.setComponent(processorDTO);
return entity;
}).collect(Collectors.toList());
updatedProcessors.stream().forEach(p -> getClient().processors().update(p));
log.info("Successfully updated controller service {} and updated {} components back to their prior state ", controllerService.getName(), previousProcessorState.size());
}
}
}
return updatedService;
}
use of org.apache.nifi.web.api.entity.UpdateControllerServiceReferenceRequestEntity in project nifi by apache.
the class ControllerServiceResource method updateControllerServiceReferences.
/**
* Updates the references of the specified controller service.
*
* @param httpServletRequest request
* @param requestUpdateReferenceRequest The update request
* @return A controllerServiceReferencingComponentsEntity.
*/
@PUT
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("{id}/references")
@ApiOperation(value = "Updates a controller services references", response = ControllerServiceReferencingComponentsEntity.class, authorizations = { @Authorization(value = "Write - /{component-type}/{uuid} - For each referencing component specified") })
@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 updateControllerServiceReferences(@Context final HttpServletRequest httpServletRequest, @ApiParam(value = "The controller service id.", required = true) @PathParam("id") final String id, @ApiParam(value = "The controller service request update request.", required = true) final UpdateControllerServiceReferenceRequestEntity requestUpdateReferenceRequest) {
if (requestUpdateReferenceRequest.getId() == null) {
throw new IllegalArgumentException("The controller service identifier must be specified.");
}
if (requestUpdateReferenceRequest.getReferencingComponentRevisions() == null) {
throw new IllegalArgumentException("The controller service referencing components revisions must be specified.");
}
// parse the state to determine the desired action
// need to consider controller service state first as it shares a state with
// scheduled state (disabled) which is applicable for referencing services
// but not referencing schedulable components
ControllerServiceState requestControllerServiceState = null;
try {
requestControllerServiceState = ControllerServiceState.valueOf(requestUpdateReferenceRequest.getState());
} catch (final IllegalArgumentException iae) {
// ignore
}
ScheduledState requestScheduledState = null;
try {
requestScheduledState = ScheduledState.valueOf(requestUpdateReferenceRequest.getState());
} catch (final IllegalArgumentException iae) {
// ignore
}
// ensure an action has been specified
if (requestScheduledState == null && requestControllerServiceState == null) {
throw new IllegalArgumentException("Must specify the updated state. To update referencing Processors " + "and Reporting Tasks the state should be RUNNING or STOPPED. To update the referencing Controller Services the " + "state should be ENABLED or DISABLED.");
}
// ensure the controller service state is not ENABLING or DISABLING
if (requestControllerServiceState != null && (ControllerServiceState.ENABLING.equals(requestControllerServiceState) || ControllerServiceState.DISABLING.equals(requestControllerServiceState))) {
throw new IllegalArgumentException("Cannot set the referencing services to ENABLING or DISABLING");
}
if (isReplicateRequest()) {
return replicate(HttpMethod.PUT, requestUpdateReferenceRequest);
}
// convert the referencing revisions
final Map<String, Revision> requestReferencingRevisions = requestUpdateReferenceRequest.getReferencingComponentRevisions().entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> {
final RevisionDTO rev = e.getValue();
return new Revision(rev.getVersion(), rev.getClientId(), e.getKey());
}));
final Set<Revision> requestRevisions = new HashSet<>(requestReferencingRevisions.values());
final ScheduledState verifyScheduledState = requestScheduledState;
final ControllerServiceState verifyControllerServiceState = requestControllerServiceState;
return withWriteLock(serviceFacade, requestUpdateReferenceRequest, requestRevisions, lookup -> {
requestReferencingRevisions.entrySet().stream().forEach(e -> {
final Authorizable controllerService = lookup.getControllerServiceReferencingComponent(id, e.getKey());
controllerService.authorize(authorizer, RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
});
}, () -> serviceFacade.verifyUpdateControllerServiceReferencingComponents(requestUpdateReferenceRequest.getId(), verifyScheduledState, verifyControllerServiceState), (revisions, updateReferenceRequest) -> {
ScheduledState scheduledState = null;
try {
scheduledState = ScheduledState.valueOf(updateReferenceRequest.getState());
} catch (final IllegalArgumentException e) {
// ignore
}
ControllerServiceState controllerServiceState = null;
try {
controllerServiceState = ControllerServiceState.valueOf(updateReferenceRequest.getState());
} catch (final IllegalArgumentException iae) {
// ignore
}
final Map<String, Revision> referencingRevisions = updateReferenceRequest.getReferencingComponentRevisions().entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> {
final RevisionDTO rev = e.getValue();
return new Revision(rev.getVersion(), rev.getClientId(), e.getKey());
}));
// update the controller service references
final ControllerServiceReferencingComponentsEntity entity = serviceFacade.updateControllerServiceReferencingComponents(referencingRevisions, updateReferenceRequest.getId(), scheduledState, controllerServiceState);
return generateOkResponse(entity).build();
});
}
Aggregations