markap14 commented on code in PR #7734:
URL: https://github.com/apache/nifi/pull/7734#discussion_r1506333554
##########
nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java:
##########
@@ -2939,6 +2939,115 @@ public ControllerServiceEntity
updateControllerService(final Revision revision,
return
entityFactory.createControllerServiceEntity(snapshot.getComponent(),
dtoFactory.createRevisionDTO(snapshot.getLastModification()), permissions,
operatePermissions, bulletinEntities);
}
+ @Override
+ public ControllerServiceEntity moveControllerService(final Revision
revision, final ControllerServiceDTO controllerServiceDTO, final String
newProcessGroupID) {
+ // get the component, ensure we have access to it, and perform the
move request
+ final ControllerServiceNode controllerService =
controllerServiceDAO.getControllerService(controllerServiceDTO.getId());
+ final RevisionUpdate<ControllerServiceDTO> snapshot =
updateComponent(revision,
+ controllerService,
+ () -> moveControllerServiceWork(controllerService,
newProcessGroupID),
+ cs -> {
+ awaitValidationCompletion(cs);
+ final ControllerServiceDTO dto =
dtoFactory.createControllerServiceDto(cs);
+ final ControllerServiceReference ref =
controllerService.getReferences();
+ final ControllerServiceReferencingComponentsEntity
referencingComponentsEntity =
createControllerServiceReferencingComponentsEntity(ref);
+
dto.setReferencingComponents(referencingComponentsEntity.getControllerServiceReferencingComponents());
+ return dto;
+ });
+
+ final PermissionsDTO permissions =
dtoFactory.createPermissionsDto(controllerService);
+ final PermissionsDTO operatePermissions =
dtoFactory.createPermissionsDto(new OperationAuthorizable(controllerService));
+ final List<BulletinDTO> bulletins =
dtoFactory.createBulletinDtos(bulletinRepository.findBulletinsForSource(controllerServiceDTO.getId()));
+ final List<BulletinEntity> bulletinEntities =
bulletins.stream().map(bulletin -> entityFactory.createBulletinEntity(bulletin,
permissions.getCanRead())).collect(Collectors.toList());
+ return
entityFactory.createControllerServiceEntity(snapshot.getComponent(),
dtoFactory.createRevisionDTO(snapshot.getLastModification()), permissions,
operatePermissions, bulletinEntities);
+ }
+
+ private ControllerServiceNode moveControllerServiceWork(final
ControllerServiceNode controllerService, final String newProcessGroupID) {
Review Comment:
We should avoid names like doXYZ(), xyzWork(), xyz0(), etc. and instead name
according to what the method does. It is fine to simply name it
`moveControllerService`
##########
nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java:
##########
@@ -2939,6 +2939,115 @@ public ControllerServiceEntity
updateControllerService(final Revision revision,
return
entityFactory.createControllerServiceEntity(snapshot.getComponent(),
dtoFactory.createRevisionDTO(snapshot.getLastModification()), permissions,
operatePermissions, bulletinEntities);
}
+ @Override
+ public ControllerServiceEntity moveControllerService(final Revision
revision, final ControllerServiceDTO controllerServiceDTO, final String
newProcessGroupID) {
+ // get the component, ensure we have access to it, and perform the
move request
+ final ControllerServiceNode controllerService =
controllerServiceDAO.getControllerService(controllerServiceDTO.getId());
+ final RevisionUpdate<ControllerServiceDTO> snapshot =
updateComponent(revision,
+ controllerService,
+ () -> moveControllerServiceWork(controllerService,
newProcessGroupID),
+ cs -> {
+ awaitValidationCompletion(cs);
Review Comment:
We cannot wait for validation to complete here. This is called from a web
thread, and must return ASAP. There should be no need to wait for validation
here, though.
##########
nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java:
##########
@@ -2939,6 +2939,115 @@ public ControllerServiceEntity
updateControllerService(final Revision revision,
return
entityFactory.createControllerServiceEntity(snapshot.getComponent(),
dtoFactory.createRevisionDTO(snapshot.getLastModification()), permissions,
operatePermissions, bulletinEntities);
}
+ @Override
+ public ControllerServiceEntity moveControllerService(final Revision
revision, final ControllerServiceDTO controllerServiceDTO, final String
newProcessGroupID) {
+ // get the component, ensure we have access to it, and perform the
move request
+ final ControllerServiceNode controllerService =
controllerServiceDAO.getControllerService(controllerServiceDTO.getId());
+ final RevisionUpdate<ControllerServiceDTO> snapshot =
updateComponent(revision,
+ controllerService,
+ () -> moveControllerServiceWork(controllerService,
newProcessGroupID),
+ cs -> {
+ awaitValidationCompletion(cs);
+ final ControllerServiceDTO dto =
dtoFactory.createControllerServiceDto(cs);
+ final ControllerServiceReference ref =
controllerService.getReferences();
+ final ControllerServiceReferencingComponentsEntity
referencingComponentsEntity =
createControllerServiceReferencingComponentsEntity(ref);
+
dto.setReferencingComponents(referencingComponentsEntity.getControllerServiceReferencingComponents());
+ return dto;
+ });
+
+ final PermissionsDTO permissions =
dtoFactory.createPermissionsDto(controllerService);
+ final PermissionsDTO operatePermissions =
dtoFactory.createPermissionsDto(new OperationAuthorizable(controllerService));
+ final List<BulletinDTO> bulletins =
dtoFactory.createBulletinDtos(bulletinRepository.findBulletinsForSource(controllerServiceDTO.getId()));
+ final List<BulletinEntity> bulletinEntities =
bulletins.stream().map(bulletin -> entityFactory.createBulletinEntity(bulletin,
permissions.getCanRead())).collect(Collectors.toList());
+ return
entityFactory.createControllerServiceEntity(snapshot.getComponent(),
dtoFactory.createRevisionDTO(snapshot.getLastModification()), permissions,
operatePermissions, bulletinEntities);
+ }
+
+ private ControllerServiceNode moveControllerServiceWork(final
ControllerServiceNode controllerService, final String newProcessGroupID) {
+ final ProcessGroup oldParentGroup =
controllerService.getProcessGroup();
+ Set<ComponentNode> referencedComponents =
controllerService.getReferences().getReferencingComponents();
+ isReferencesDisabled(referencedComponents);
+ oldParentGroup.removeControllerService(controllerService);
+ ProcessGroup newParent;
+ if (!oldParentGroup.isRootGroup() &&
oldParentGroup.getParent().getIdentifier().equals(newProcessGroupID)) {
+ // move to parent process group
+ newParent = oldParentGroup.getParent();
+ newParent.addControllerService(controllerService);
+
+ // unset any references the controller services has to other
controller services that are now out of scope
+ Map<String, String> updatedProps = new HashMap<>();
+ Set<Map.Entry<PropertyDescriptor, PropertyConfiguration>>
properties = controllerService.getProperties().entrySet();
+ for (var prop : properties) {
+ var value = prop.getValue();
+ if (value !=null) {
+ ControllerServiceNode controller;
+ try {
+ controller =
controllerServiceDAO.getControllerService((value.getRawValue()));
+ } catch (Exception e){
+ continue;
+ }
+ if (controller != null) {
+ if (!hasProcessGroup(controller.getProcessGroup(),
newParent.getIdentifier())) {
+ controller.removeReference(controllerService,
prop.getKey());
+ updatedProps.put(prop.getKey().getName(), null);
+ }
+ }
+ }
+ }
+ if (!updatedProps.isEmpty())
+ controllerService.setProperties(updatedProps, true,
Collections.emptySet());
+
+ } else {
+ // move to child process group
+ newParent = oldParentGroup.getProcessGroup(newProcessGroupID);
+ newParent.addControllerService(controllerService);
+
+ // unset any references for processors that are outside the new
scope
+ for (ComponentNode node : referencedComponents) {
+ if (!hasProcessGroup(newParent,
node.getProcessGroupIdentifier())) {
+ Set<Map.Entry<PropertyDescriptor, PropertyConfiguration>>
properties = node.getProperties().entrySet();
+ Map<String, String> updatedProps = new HashMap<>();
+ for (Map.Entry<PropertyDescriptor, PropertyConfiguration>
prop : properties) {
+ final PropertyConfiguration value = prop.getValue();
+ if (value != null &&
value.getRawValue().equals(controllerService.getIdentifier())) {
+ controllerService.removeReference(node,
prop.getKey());
+
node.getComponent().onPropertyModified(prop.getKey(),
controllerService.getIdentifier(), null);
+ updatedProps.put(prop.getKey().getName(), null);
+ }
+ }
+ node.setProperties(updatedProps, true,
Collections.emptySet());
+ }
+ }
+ }
+
+ return controllerService;
+ }
+ private boolean hasProcessGroup(ProcessGroup root, String id){
+ if (root.getProcessGroup(id) != null ||
root.getIdentifier().equals(id)) {
+ return true;
+ }
+
+ for (ProcessGroup child : root.getProcessGroups()) {
+ if (hasProcessGroup(child, id)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private void isReferencesDisabled(Set<ComponentNode> nodes) {
Review Comment:
We should not have an `isXYZ` method that throws an Exception or that
doesn't return a `boolean`. The typical naming convention here is
`verifyReferencesDisabled`
##########
nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java:
##########
@@ -2939,6 +2939,115 @@ public ControllerServiceEntity
updateControllerService(final Revision revision,
return
entityFactory.createControllerServiceEntity(snapshot.getComponent(),
dtoFactory.createRevisionDTO(snapshot.getLastModification()), permissions,
operatePermissions, bulletinEntities);
}
+ @Override
+ public ControllerServiceEntity moveControllerService(final Revision
revision, final ControllerServiceDTO controllerServiceDTO, final String
newProcessGroupID) {
+ // get the component, ensure we have access to it, and perform the
move request
+ final ControllerServiceNode controllerService =
controllerServiceDAO.getControllerService(controllerServiceDTO.getId());
+ final RevisionUpdate<ControllerServiceDTO> snapshot =
updateComponent(revision,
+ controllerService,
+ () -> moveControllerServiceWork(controllerService,
newProcessGroupID),
+ cs -> {
+ awaitValidationCompletion(cs);
+ final ControllerServiceDTO dto =
dtoFactory.createControllerServiceDto(cs);
+ final ControllerServiceReference ref =
controllerService.getReferences();
+ final ControllerServiceReferencingComponentsEntity
referencingComponentsEntity =
createControllerServiceReferencingComponentsEntity(ref);
+
dto.setReferencingComponents(referencingComponentsEntity.getControllerServiceReferencingComponents());
+ return dto;
+ });
+
+ final PermissionsDTO permissions =
dtoFactory.createPermissionsDto(controllerService);
+ final PermissionsDTO operatePermissions =
dtoFactory.createPermissionsDto(new OperationAuthorizable(controllerService));
+ final List<BulletinDTO> bulletins =
dtoFactory.createBulletinDtos(bulletinRepository.findBulletinsForSource(controllerServiceDTO.getId()));
+ final List<BulletinEntity> bulletinEntities =
bulletins.stream().map(bulletin -> entityFactory.createBulletinEntity(bulletin,
permissions.getCanRead())).collect(Collectors.toList());
+ return
entityFactory.createControllerServiceEntity(snapshot.getComponent(),
dtoFactory.createRevisionDTO(snapshot.getLastModification()), permissions,
operatePermissions, bulletinEntities);
+ }
+
+ private ControllerServiceNode moveControllerServiceWork(final
ControllerServiceNode controllerService, final String newProcessGroupID) {
+ final ProcessGroup oldParentGroup =
controllerService.getProcessGroup();
+ Set<ComponentNode> referencedComponents =
controllerService.getReferences().getReferencingComponents();
+ isReferencesDisabled(referencedComponents);
+ oldParentGroup.removeControllerService(controllerService);
+ ProcessGroup newParent;
+ if (!oldParentGroup.isRootGroup() &&
oldParentGroup.getParent().getIdentifier().equals(newProcessGroupID)) {
+ // move to parent process group
+ newParent = oldParentGroup.getParent();
+ newParent.addControllerService(controllerService);
+
+ // unset any references the controller services has to other
controller services that are now out of scope
+ Map<String, String> updatedProps = new HashMap<>();
+ Set<Map.Entry<PropertyDescriptor, PropertyConfiguration>>
properties = controllerService.getProperties().entrySet();
+ for (var prop : properties) {
Review Comment:
The `var` keyword should not be used.
##########
nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java:
##########
@@ -2939,6 +2939,115 @@ public ControllerServiceEntity
updateControllerService(final Revision revision,
return
entityFactory.createControllerServiceEntity(snapshot.getComponent(),
dtoFactory.createRevisionDTO(snapshot.getLastModification()), permissions,
operatePermissions, bulletinEntities);
}
+ @Override
+ public ControllerServiceEntity moveControllerService(final Revision
revision, final ControllerServiceDTO controllerServiceDTO, final String
newProcessGroupID) {
+ // get the component, ensure we have access to it, and perform the
move request
+ final ControllerServiceNode controllerService =
controllerServiceDAO.getControllerService(controllerServiceDTO.getId());
+ final RevisionUpdate<ControllerServiceDTO> snapshot =
updateComponent(revision,
+ controllerService,
+ () -> moveControllerServiceWork(controllerService,
newProcessGroupID),
+ cs -> {
+ awaitValidationCompletion(cs);
+ final ControllerServiceDTO dto =
dtoFactory.createControllerServiceDto(cs);
+ final ControllerServiceReference ref =
controllerService.getReferences();
+ final ControllerServiceReferencingComponentsEntity
referencingComponentsEntity =
createControllerServiceReferencingComponentsEntity(ref);
+
dto.setReferencingComponents(referencingComponentsEntity.getControllerServiceReferencingComponents());
+ return dto;
+ });
+
+ final PermissionsDTO permissions =
dtoFactory.createPermissionsDto(controllerService);
+ final PermissionsDTO operatePermissions =
dtoFactory.createPermissionsDto(new OperationAuthorizable(controllerService));
+ final List<BulletinDTO> bulletins =
dtoFactory.createBulletinDtos(bulletinRepository.findBulletinsForSource(controllerServiceDTO.getId()));
+ final List<BulletinEntity> bulletinEntities =
bulletins.stream().map(bulletin -> entityFactory.createBulletinEntity(bulletin,
permissions.getCanRead())).collect(Collectors.toList());
+ return
entityFactory.createControllerServiceEntity(snapshot.getComponent(),
dtoFactory.createRevisionDTO(snapshot.getLastModification()), permissions,
operatePermissions, bulletinEntities);
+ }
+
+ private ControllerServiceNode moveControllerServiceWork(final
ControllerServiceNode controllerService, final String newProcessGroupID) {
+ final ProcessGroup oldParentGroup =
controllerService.getProcessGroup();
+ Set<ComponentNode> referencedComponents =
controllerService.getReferences().getReferencingComponents();
+ isReferencesDisabled(referencedComponents);
+ oldParentGroup.removeControllerService(controllerService);
+ ProcessGroup newParent;
+ if (!oldParentGroup.isRootGroup() &&
oldParentGroup.getParent().getIdentifier().equals(newProcessGroupID)) {
+ // move to parent process group
+ newParent = oldParentGroup.getParent();
+ newParent.addControllerService(controllerService);
+
+ // unset any references the controller services has to other
controller services that are now out of scope
+ Map<String, String> updatedProps = new HashMap<>();
+ Set<Map.Entry<PropertyDescriptor, PropertyConfiguration>>
properties = controllerService.getProperties().entrySet();
+ for (var prop : properties) {
+ var value = prop.getValue();
+ if (value !=null) {
+ ControllerServiceNode controller;
+ try {
+ controller =
controllerServiceDAO.getControllerService((value.getRawValue()));
+ } catch (Exception e){
+ continue;
+ }
+ if (controller != null) {
+ if (!hasProcessGroup(controller.getProcessGroup(),
newParent.getIdentifier())) {
+ controller.removeReference(controllerService,
prop.getKey());
+ updatedProps.put(prop.getKey().getName(), null);
+ }
+ }
+ }
+ }
+ if (!updatedProps.isEmpty())
+ controllerService.setProperties(updatedProps, true,
Collections.emptySet());
+
+ } else {
+ // move to child process group
+ newParent = oldParentGroup.getProcessGroup(newProcessGroupID);
+ newParent.addControllerService(controllerService);
+
+ // unset any references for processors that are outside the new
scope
+ for (ComponentNode node : referencedComponents) {
+ if (!hasProcessGroup(newParent,
node.getProcessGroupIdentifier())) {
+ Set<Map.Entry<PropertyDescriptor, PropertyConfiguration>>
properties = node.getProperties().entrySet();
+ Map<String, String> updatedProps = new HashMap<>();
+ for (Map.Entry<PropertyDescriptor, PropertyConfiguration>
prop : properties) {
+ final PropertyConfiguration value = prop.getValue();
+ if (value != null &&
value.getRawValue().equals(controllerService.getIdentifier())) {
+ controllerService.removeReference(node,
prop.getKey());
+
node.getComponent().onPropertyModified(prop.getKey(),
controllerService.getIdentifier(), null);
+ updatedProps.put(prop.getKey().getName(), null);
+ }
+ }
+ node.setProperties(updatedProps, true,
Collections.emptySet());
+ }
+ }
+ }
+
+ return controllerService;
+ }
+ private boolean hasProcessGroup(ProcessGroup root, String id){
Review Comment:
This method is unnecessary. There already exists a method on `ProcessGroup`
named `findProcessGroup`. So you can simply use `root.findProcessGroup(id) !=
null`
##########
nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/nf-controller-service.js:
##########
@@ -2624,6 +2788,26 @@
});
},
+ /**
+ * Prompts the user before attempting to move the specified controller
service.
+ *
+ * @param {jQuery} serviceTable
+ * @param {object} controllerServiceEntity
+ */
+ promptToMoveController: function (serviceTable,
controllerServiceEntity) {
+ // prompt for move
+ nfDialog.showYesNoDialog({
+ headerText: 'Move Controller Service',
+ dialogContent: 'Move controller service \'' +
nfCommon.escapeHtml(controllerServiceEntity.component.name) + '\' '
+ + 'to \'' +
nfCommon.escapeHtml($('#move-controller-service-scope').combo('getSelectedOption').text)
+ '\'?'
+ + '<br /><br /><i class="invalid"></i>  '
+ + 'Any reference to this controller service by
processors outside the new scope will be removed.',
+ yesHandler: function () {
+ moveToProcessGroup(serviceTable, controllerServiceEntity,
$('#move-controller-service-scope').combo('getSelectedOption').value);
+ }
+ });
+ },
Review Comment:
I don't think we need a prompt, either, after ensuring that references
cannot become invalid. And because the service doesn't require being disabled,
I think the option should always be shown.
##########
nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerServiceResource.java:
##########
@@ -680,6 +681,116 @@ public Response updateControllerService(
);
}
+ /**
+ * Moves the specified Controller Service to parent/child process groups.
+ *
+ * @param id The id of the controller service to update.
+ * @param requestControllerServiceEntity A controllerServiceEntity.
+ * @return A controllerServiceEntity.
+ */
+ @PUT
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("{id}/move")
+ @Operation(
+ summary = "Move Controller Service to the specified Process
Group.",
+ responses = @ApiResponse(content = @Content(schema =
@Schema(implementation = ControllerServiceEntity.class))),
+ security = {
+ @SecurityRequirement(name = "Write -
/controller-services/{uuid}"),
+ @SecurityRequirement(name = "Write - Parent Process Group
if scoped by Process Group - /process-groups/{uuid}"),
+ @SecurityRequirement(name = "Write - Controller if scoped
by Controller - /controller"),
+ @SecurityRequirement(name = "Read - any referenced
Controller Services - /controller-services/{uuid}")
+ })
+ @ApiResponses(
+ value = {
+ @ApiResponse(responseCode = "400", description = "NiFi was
unable to complete the request because it was invalid. The request should not
be retried without modification."),
+ @ApiResponse(responseCode = "401", description = "Client
could not be authenticated."),
+ @ApiResponse(responseCode = "403", description = "Client
is not authorized to make this request."),
+ @ApiResponse(responseCode = "404", description = "The
specified resource could not be found."),
+ @ApiResponse(responseCode = "409", description = "The
request was valid but NiFi was not in the appropriate state to process it.")
+ }
+ )
+ public Response moveControllerServices(
+ @Parameter(
+ description = "The controller service id.",
+ required = true
+ )
+ @PathParam("id") final String id,
+ @Parameter(
+ description = "The controller service entity",
+ required = true
+ )
+ final ControllerServiceEntity requestControllerServiceEntity) {
+
+ if (requestControllerServiceEntity == null) {
+ throw new IllegalArgumentException("Controller service must be
specified.");
+ }
+
+ if (requestControllerServiceEntity.getRevision() == null) {
+ throw new IllegalArgumentException("Revision must be specified.");
+ }
+
+ if (requestControllerServiceEntity.getParentGroupId() == null) {
+ throw new IllegalArgumentException("ParentGroupId must be
specified.");
+ }
+
+ final ControllerServiceDTO requestControllerServiceDTO =
serviceFacade.getControllerService(id, true).getComponent();
+ ControllerServiceState requestControllerServiceState = null;
+ try {
+ requestControllerServiceState =
ControllerServiceState.valueOf(requestControllerServiceDTO.getState());
+ } catch (final IllegalArgumentException iae) {
+ // ignore
+ }
+
+ // ensure an action has been specified
+ if (requestControllerServiceState == null) {
+ throw new IllegalArgumentException("Must specify the updated
state. To update the referencing Controller Services the "
+ + "state should be DISABLED.");
+ }
+
+ // ensure the controller service state is not DISABLING
+ if
(!ControllerServiceState.DISABLED.equals(requestControllerServiceState) ) {
+ throw new IllegalArgumentException("Cannot set the referencing
services to ENABLING or DISABLING");
+ }
Review Comment:
We should not have to care that the state is DISABLED. Given that all
references must still be valid, moving the service to a new scope should not
have any effect, and so it should be valid while the service is ENABLED.
##########
nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java:
##########
@@ -2939,6 +2939,115 @@ public ControllerServiceEntity
updateControllerService(final Revision revision,
return
entityFactory.createControllerServiceEntity(snapshot.getComponent(),
dtoFactory.createRevisionDTO(snapshot.getLastModification()), permissions,
operatePermissions, bulletinEntities);
}
+ @Override
+ public ControllerServiceEntity moveControllerService(final Revision
revision, final ControllerServiceDTO controllerServiceDTO, final String
newProcessGroupID) {
+ // get the component, ensure we have access to it, and perform the
move request
+ final ControllerServiceNode controllerService =
controllerServiceDAO.getControllerService(controllerServiceDTO.getId());
+ final RevisionUpdate<ControllerServiceDTO> snapshot =
updateComponent(revision,
+ controllerService,
+ () -> moveControllerServiceWork(controllerService,
newProcessGroupID),
+ cs -> {
+ awaitValidationCompletion(cs);
+ final ControllerServiceDTO dto =
dtoFactory.createControllerServiceDto(cs);
+ final ControllerServiceReference ref =
controllerService.getReferences();
+ final ControllerServiceReferencingComponentsEntity
referencingComponentsEntity =
createControllerServiceReferencingComponentsEntity(ref);
+
dto.setReferencingComponents(referencingComponentsEntity.getControllerServiceReferencingComponents());
+ return dto;
+ });
+
+ final PermissionsDTO permissions =
dtoFactory.createPermissionsDto(controllerService);
+ final PermissionsDTO operatePermissions =
dtoFactory.createPermissionsDto(new OperationAuthorizable(controllerService));
+ final List<BulletinDTO> bulletins =
dtoFactory.createBulletinDtos(bulletinRepository.findBulletinsForSource(controllerServiceDTO.getId()));
+ final List<BulletinEntity> bulletinEntities =
bulletins.stream().map(bulletin -> entityFactory.createBulletinEntity(bulletin,
permissions.getCanRead())).collect(Collectors.toList());
+ return
entityFactory.createControllerServiceEntity(snapshot.getComponent(),
dtoFactory.createRevisionDTO(snapshot.getLastModification()), permissions,
operatePermissions, bulletinEntities);
+ }
+
+ private ControllerServiceNode moveControllerServiceWork(final
ControllerServiceNode controllerService, final String newProcessGroupID) {
+ final ProcessGroup oldParentGroup =
controllerService.getProcessGroup();
+ Set<ComponentNode> referencedComponents =
controllerService.getReferences().getReferencingComponents();
+ isReferencesDisabled(referencedComponents);
+ oldParentGroup.removeControllerService(controllerService);
+ ProcessGroup newParent;
+ if (!oldParentGroup.isRootGroup() &&
oldParentGroup.getParent().getIdentifier().equals(newProcessGroupID)) {
+ // move to parent process group
+ newParent = oldParentGroup.getParent();
+ newParent.addControllerService(controllerService);
+
+ // unset any references the controller services has to other
controller services that are now out of scope
+ Map<String, String> updatedProps = new HashMap<>();
+ Set<Map.Entry<PropertyDescriptor, PropertyConfiguration>>
properties = controllerService.getProperties().entrySet();
+ for (var prop : properties) {
+ var value = prop.getValue();
+ if (value !=null) {
+ ControllerServiceNode controller;
+ try {
+ controller =
controllerServiceDAO.getControllerService((value.getRawValue()));
+ } catch (Exception e){
+ continue;
+ }
+ if (controller != null) {
Review Comment:
No need for a null-check here, `controller` is guaranteed non-null by using
`hasControllerService()` along with `continue`
##########
nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java:
##########
@@ -2939,6 +2939,115 @@ public ControllerServiceEntity
updateControllerService(final Revision revision,
return
entityFactory.createControllerServiceEntity(snapshot.getComponent(),
dtoFactory.createRevisionDTO(snapshot.getLastModification()), permissions,
operatePermissions, bulletinEntities);
}
+ @Override
+ public ControllerServiceEntity moveControllerService(final Revision
revision, final ControllerServiceDTO controllerServiceDTO, final String
newProcessGroupID) {
+ // get the component, ensure we have access to it, and perform the
move request
+ final ControllerServiceNode controllerService =
controllerServiceDAO.getControllerService(controllerServiceDTO.getId());
+ final RevisionUpdate<ControllerServiceDTO> snapshot =
updateComponent(revision,
+ controllerService,
+ () -> moveControllerServiceWork(controllerService,
newProcessGroupID),
+ cs -> {
+ awaitValidationCompletion(cs);
+ final ControllerServiceDTO dto =
dtoFactory.createControllerServiceDto(cs);
+ final ControllerServiceReference ref =
controllerService.getReferences();
+ final ControllerServiceReferencingComponentsEntity
referencingComponentsEntity =
createControllerServiceReferencingComponentsEntity(ref);
+
dto.setReferencingComponents(referencingComponentsEntity.getControllerServiceReferencingComponents());
+ return dto;
+ });
+
+ final PermissionsDTO permissions =
dtoFactory.createPermissionsDto(controllerService);
+ final PermissionsDTO operatePermissions =
dtoFactory.createPermissionsDto(new OperationAuthorizable(controllerService));
+ final List<BulletinDTO> bulletins =
dtoFactory.createBulletinDtos(bulletinRepository.findBulletinsForSource(controllerServiceDTO.getId()));
+ final List<BulletinEntity> bulletinEntities =
bulletins.stream().map(bulletin -> entityFactory.createBulletinEntity(bulletin,
permissions.getCanRead())).collect(Collectors.toList());
+ return
entityFactory.createControllerServiceEntity(snapshot.getComponent(),
dtoFactory.createRevisionDTO(snapshot.getLastModification()), permissions,
operatePermissions, bulletinEntities);
+ }
+
+ private ControllerServiceNode moveControllerServiceWork(final
ControllerServiceNode controllerService, final String newProcessGroupID) {
+ final ProcessGroup oldParentGroup =
controllerService.getProcessGroup();
+ Set<ComponentNode> referencedComponents =
controllerService.getReferences().getReferencingComponents();
+ isReferencesDisabled(referencedComponents);
+ oldParentGroup.removeControllerService(controllerService);
+ ProcessGroup newParent;
+ if (!oldParentGroup.isRootGroup() &&
oldParentGroup.getParent().getIdentifier().equals(newProcessGroupID)) {
+ // move to parent process group
+ newParent = oldParentGroup.getParent();
+ newParent.addControllerService(controllerService);
+
+ // unset any references the controller services has to other
controller services that are now out of scope
+ Map<String, String> updatedProps = new HashMap<>();
+ Set<Map.Entry<PropertyDescriptor, PropertyConfiguration>>
properties = controllerService.getProperties().entrySet();
+ for (var prop : properties) {
+ var value = prop.getValue();
+ if (value !=null) {
+ ControllerServiceNode controller;
+ try {
+ controller =
controllerServiceDAO.getControllerService((value.getRawValue()));
+ } catch (Exception e){
+ continue;
+ }
+ if (controller != null) {
+ if (!hasProcessGroup(controller.getProcessGroup(),
newParent.getIdentifier())) {
+ controller.removeReference(controllerService,
prop.getKey());
Review Comment:
We should never remove a reference to the Controller Service. Rather, we
must ensure that the move is valid, and that all references will remain intact
/ valid after the move. If not, the Controller Service cannot be moved.
##########
nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java:
##########
@@ -2939,6 +2939,115 @@ public ControllerServiceEntity
updateControllerService(final Revision revision,
return
entityFactory.createControllerServiceEntity(snapshot.getComponent(),
dtoFactory.createRevisionDTO(snapshot.getLastModification()), permissions,
operatePermissions, bulletinEntities);
}
+ @Override
+ public ControllerServiceEntity moveControllerService(final Revision
revision, final ControllerServiceDTO controllerServiceDTO, final String
newProcessGroupID) {
+ // get the component, ensure we have access to it, and perform the
move request
+ final ControllerServiceNode controllerService =
controllerServiceDAO.getControllerService(controllerServiceDTO.getId());
+ final RevisionUpdate<ControllerServiceDTO> snapshot =
updateComponent(revision,
+ controllerService,
+ () -> moveControllerServiceWork(controllerService,
newProcessGroupID),
+ cs -> {
+ awaitValidationCompletion(cs);
+ final ControllerServiceDTO dto =
dtoFactory.createControllerServiceDto(cs);
+ final ControllerServiceReference ref =
controllerService.getReferences();
+ final ControllerServiceReferencingComponentsEntity
referencingComponentsEntity =
createControllerServiceReferencingComponentsEntity(ref);
+
dto.setReferencingComponents(referencingComponentsEntity.getControllerServiceReferencingComponents());
+ return dto;
+ });
+
+ final PermissionsDTO permissions =
dtoFactory.createPermissionsDto(controllerService);
+ final PermissionsDTO operatePermissions =
dtoFactory.createPermissionsDto(new OperationAuthorizable(controllerService));
+ final List<BulletinDTO> bulletins =
dtoFactory.createBulletinDtos(bulletinRepository.findBulletinsForSource(controllerServiceDTO.getId()));
+ final List<BulletinEntity> bulletinEntities =
bulletins.stream().map(bulletin -> entityFactory.createBulletinEntity(bulletin,
permissions.getCanRead())).collect(Collectors.toList());
+ return
entityFactory.createControllerServiceEntity(snapshot.getComponent(),
dtoFactory.createRevisionDTO(snapshot.getLastModification()), permissions,
operatePermissions, bulletinEntities);
+ }
+
+ private ControllerServiceNode moveControllerServiceWork(final
ControllerServiceNode controllerService, final String newProcessGroupID) {
+ final ProcessGroup oldParentGroup =
controllerService.getProcessGroup();
+ Set<ComponentNode> referencedComponents =
controllerService.getReferences().getReferencingComponents();
+ isReferencesDisabled(referencedComponents);
+ oldParentGroup.removeControllerService(controllerService);
+ ProcessGroup newParent;
+ if (!oldParentGroup.isRootGroup() &&
oldParentGroup.getParent().getIdentifier().equals(newProcessGroupID)) {
+ // move to parent process group
+ newParent = oldParentGroup.getParent();
+ newParent.addControllerService(controllerService);
+
+ // unset any references the controller services has to other
controller services that are now out of scope
+ Map<String, String> updatedProps = new HashMap<>();
+ Set<Map.Entry<PropertyDescriptor, PropertyConfiguration>>
properties = controllerService.getProperties().entrySet();
+ for (var prop : properties) {
+ var value = prop.getValue();
+ if (value !=null) {
+ ControllerServiceNode controller;
+ try {
+ controller =
controllerServiceDAO.getControllerService((value.getRawValue()));
+ } catch (Exception e){
+ continue;
+ }
+ if (controller != null) {
+ if (!hasProcessGroup(controller.getProcessGroup(),
newParent.getIdentifier())) {
+ controller.removeReference(controllerService,
prop.getKey());
+ updatedProps.put(prop.getKey().getName(), null);
+ }
+ }
+ }
+ }
+ if (!updatedProps.isEmpty())
+ controllerService.setProperties(updatedProps, true,
Collections.emptySet());
Review Comment:
Should have `{}`:
```
if (!updatedProps.isEmpty()) {
controllerService.setProperties(updatedProps, true,
Collections.emptySet());
}
```
It is odd that the checkstyle didn't flag that.
##########
nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java:
##########
@@ -2939,6 +2939,115 @@ public ControllerServiceEntity
updateControllerService(final Revision revision,
return
entityFactory.createControllerServiceEntity(snapshot.getComponent(),
dtoFactory.createRevisionDTO(snapshot.getLastModification()), permissions,
operatePermissions, bulletinEntities);
}
+ @Override
+ public ControllerServiceEntity moveControllerService(final Revision
revision, final ControllerServiceDTO controllerServiceDTO, final String
newProcessGroupID) {
+ // get the component, ensure we have access to it, and perform the
move request
+ final ControllerServiceNode controllerService =
controllerServiceDAO.getControllerService(controllerServiceDTO.getId());
+ final RevisionUpdate<ControllerServiceDTO> snapshot =
updateComponent(revision,
+ controllerService,
+ () -> moveControllerServiceWork(controllerService,
newProcessGroupID),
+ cs -> {
+ awaitValidationCompletion(cs);
+ final ControllerServiceDTO dto =
dtoFactory.createControllerServiceDto(cs);
+ final ControllerServiceReference ref =
controllerService.getReferences();
+ final ControllerServiceReferencingComponentsEntity
referencingComponentsEntity =
createControllerServiceReferencingComponentsEntity(ref);
+
dto.setReferencingComponents(referencingComponentsEntity.getControllerServiceReferencingComponents());
+ return dto;
+ });
+
+ final PermissionsDTO permissions =
dtoFactory.createPermissionsDto(controllerService);
+ final PermissionsDTO operatePermissions =
dtoFactory.createPermissionsDto(new OperationAuthorizable(controllerService));
+ final List<BulletinDTO> bulletins =
dtoFactory.createBulletinDtos(bulletinRepository.findBulletinsForSource(controllerServiceDTO.getId()));
+ final List<BulletinEntity> bulletinEntities =
bulletins.stream().map(bulletin -> entityFactory.createBulletinEntity(bulletin,
permissions.getCanRead())).collect(Collectors.toList());
+ return
entityFactory.createControllerServiceEntity(snapshot.getComponent(),
dtoFactory.createRevisionDTO(snapshot.getLastModification()), permissions,
operatePermissions, bulletinEntities);
+ }
+
+ private ControllerServiceNode moveControllerServiceWork(final
ControllerServiceNode controllerService, final String newProcessGroupID) {
+ final ProcessGroup oldParentGroup =
controllerService.getProcessGroup();
+ Set<ComponentNode> referencedComponents =
controllerService.getReferences().getReferencingComponents();
+ isReferencesDisabled(referencedComponents);
+ oldParentGroup.removeControllerService(controllerService);
+ ProcessGroup newParent;
+ if (!oldParentGroup.isRootGroup() &&
oldParentGroup.getParent().getIdentifier().equals(newProcessGroupID)) {
+ // move to parent process group
+ newParent = oldParentGroup.getParent();
+ newParent.addControllerService(controllerService);
+
+ // unset any references the controller services has to other
controller services that are now out of scope
+ Map<String, String> updatedProps = new HashMap<>();
+ Set<Map.Entry<PropertyDescriptor, PropertyConfiguration>>
properties = controllerService.getProperties().entrySet();
+ for (var prop : properties) {
+ var value = prop.getValue();
+ if (value !=null) {
+ ControllerServiceNode controller;
+ try {
+ controller =
controllerServiceDAO.getControllerService((value.getRawValue()));
+ } catch (Exception e){
+ continue;
+ }
Review Comment:
We should not rely on Exceptions for flow control. Instead, use
```
if (!controllerServiceDAO.hasControllerService(value.getRawValue()) {
continue;
}
```
##########
nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/StandardNiFiServiceFacade.java:
##########
@@ -2939,6 +2939,115 @@ public ControllerServiceEntity
updateControllerService(final Revision revision,
return
entityFactory.createControllerServiceEntity(snapshot.getComponent(),
dtoFactory.createRevisionDTO(snapshot.getLastModification()), permissions,
operatePermissions, bulletinEntities);
}
+ @Override
+ public ControllerServiceEntity moveControllerService(final Revision
revision, final ControllerServiceDTO controllerServiceDTO, final String
newProcessGroupID) {
+ // get the component, ensure we have access to it, and perform the
move request
+ final ControllerServiceNode controllerService =
controllerServiceDAO.getControllerService(controllerServiceDTO.getId());
+ final RevisionUpdate<ControllerServiceDTO> snapshot =
updateComponent(revision,
+ controllerService,
+ () -> moveControllerServiceWork(controllerService,
newProcessGroupID),
+ cs -> {
+ awaitValidationCompletion(cs);
+ final ControllerServiceDTO dto =
dtoFactory.createControllerServiceDto(cs);
+ final ControllerServiceReference ref =
controllerService.getReferences();
+ final ControllerServiceReferencingComponentsEntity
referencingComponentsEntity =
createControllerServiceReferencingComponentsEntity(ref);
+
dto.setReferencingComponents(referencingComponentsEntity.getControllerServiceReferencingComponents());
+ return dto;
+ });
+
+ final PermissionsDTO permissions =
dtoFactory.createPermissionsDto(controllerService);
+ final PermissionsDTO operatePermissions =
dtoFactory.createPermissionsDto(new OperationAuthorizable(controllerService));
+ final List<BulletinDTO> bulletins =
dtoFactory.createBulletinDtos(bulletinRepository.findBulletinsForSource(controllerServiceDTO.getId()));
+ final List<BulletinEntity> bulletinEntities =
bulletins.stream().map(bulletin -> entityFactory.createBulletinEntity(bulletin,
permissions.getCanRead())).collect(Collectors.toList());
+ return
entityFactory.createControllerServiceEntity(snapshot.getComponent(),
dtoFactory.createRevisionDTO(snapshot.getLastModification()), permissions,
operatePermissions, bulletinEntities);
+ }
+
+ private ControllerServiceNode moveControllerServiceWork(final
ControllerServiceNode controllerService, final String newProcessGroupID) {
+ final ProcessGroup oldParentGroup =
controllerService.getProcessGroup();
+ Set<ComponentNode> referencedComponents =
controllerService.getReferences().getReferencingComponents();
+ isReferencesDisabled(referencedComponents);
+ oldParentGroup.removeControllerService(controllerService);
+ ProcessGroup newParent;
+ if (!oldParentGroup.isRootGroup() &&
oldParentGroup.getParent().getIdentifier().equals(newProcessGroupID)) {
+ // move to parent process group
+ newParent = oldParentGroup.getParent();
+ newParent.addControllerService(controllerService);
+
+ // unset any references the controller services has to other
controller services that are now out of scope
+ Map<String, String> updatedProps = new HashMap<>();
+ Set<Map.Entry<PropertyDescriptor, PropertyConfiguration>>
properties = controllerService.getProperties().entrySet();
+ for (var prop : properties) {
+ var value = prop.getValue();
+ if (value !=null) {
+ ControllerServiceNode controller;
+ try {
+ controller =
controllerServiceDAO.getControllerService((value.getRawValue()));
+ } catch (Exception e){
+ continue;
+ }
+ if (controller != null) {
+ if (!hasProcessGroup(controller.getProcessGroup(),
newParent.getIdentifier())) {
+ controller.removeReference(controllerService,
prop.getKey());
+ updatedProps.put(prop.getKey().getName(), null);
+ }
+ }
+ }
+ }
+ if (!updatedProps.isEmpty())
+ controllerService.setProperties(updatedProps, true,
Collections.emptySet());
+
+ } else {
+ // move to child process group
+ newParent = oldParentGroup.getProcessGroup(newProcessGroupID);
+ newParent.addControllerService(controllerService);
+
+ // unset any references for processors that are outside the new
scope
+ for (ComponentNode node : referencedComponents) {
+ if (!hasProcessGroup(newParent,
node.getProcessGroupIdentifier())) {
+ Set<Map.Entry<PropertyDescriptor, PropertyConfiguration>>
properties = node.getProperties().entrySet();
+ Map<String, String> updatedProps = new HashMap<>();
+ for (Map.Entry<PropertyDescriptor, PropertyConfiguration>
prop : properties) {
+ final PropertyConfiguration value = prop.getValue();
+ if (value != null &&
value.getRawValue().equals(controllerService.getIdentifier())) {
+ controllerService.removeReference(node,
prop.getKey());
+
node.getComponent().onPropertyModified(prop.getKey(),
controllerService.getIdentifier(), null);
+ updatedProps.put(prop.getKey().getName(), null);
+ }
+ }
+ node.setProperties(updatedProps, true,
Collections.emptySet());
+ }
+ }
Review Comment:
See above. We cannot remove references.
##########
nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerServiceResource.java:
##########
@@ -680,6 +681,116 @@ public Response updateControllerService(
);
}
+ /**
+ * Moves the specified Controller Service to parent/child process groups.
+ *
+ * @param id The id of the controller service to update.
+ * @param requestControllerServiceEntity A controllerServiceEntity.
+ * @return A controllerServiceEntity.
+ */
+ @PUT
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("{id}/move")
+ @Operation(
+ summary = "Move Controller Service to the specified Process
Group.",
+ responses = @ApiResponse(content = @Content(schema =
@Schema(implementation = ControllerServiceEntity.class))),
+ security = {
+ @SecurityRequirement(name = "Write -
/controller-services/{uuid}"),
+ @SecurityRequirement(name = "Write - Parent Process Group
if scoped by Process Group - /process-groups/{uuid}"),
+ @SecurityRequirement(name = "Write - Controller if scoped
by Controller - /controller"),
+ @SecurityRequirement(name = "Read - any referenced
Controller Services - /controller-services/{uuid}")
+ })
+ @ApiResponses(
+ value = {
+ @ApiResponse(responseCode = "400", description = "NiFi was
unable to complete the request because it was invalid. The request should not
be retried without modification."),
+ @ApiResponse(responseCode = "401", description = "Client
could not be authenticated."),
+ @ApiResponse(responseCode = "403", description = "Client
is not authorized to make this request."),
+ @ApiResponse(responseCode = "404", description = "The
specified resource could not be found."),
+ @ApiResponse(responseCode = "409", description = "The
request was valid but NiFi was not in the appropriate state to process it.")
+ }
+ )
+ public Response moveControllerServices(
+ @Parameter(
+ description = "The controller service id.",
+ required = true
+ )
+ @PathParam("id") final String id,
+ @Parameter(
+ description = "The controller service entity",
+ required = true
+ )
+ final ControllerServiceEntity requestControllerServiceEntity) {
+
+ if (requestControllerServiceEntity == null) {
+ throw new IllegalArgumentException("Controller service must be
specified.");
+ }
+
+ if (requestControllerServiceEntity.getRevision() == null) {
+ throw new IllegalArgumentException("Revision must be specified.");
+ }
+
+ if (requestControllerServiceEntity.getParentGroupId() == null) {
+ throw new IllegalArgumentException("ParentGroupId must be
specified.");
+ }
+
+ final ControllerServiceDTO requestControllerServiceDTO =
serviceFacade.getControllerService(id, true).getComponent();
+ ControllerServiceState requestControllerServiceState = null;
+ try {
+ requestControllerServiceState =
ControllerServiceState.valueOf(requestControllerServiceDTO.getState());
+ } catch (final IllegalArgumentException iae) {
+ // ignore
+ }
+
+ // ensure an action has been specified
+ if (requestControllerServiceState == null) {
+ throw new IllegalArgumentException("Must specify the updated
state. To update the referencing Controller Services the "
+ + "state should be DISABLED.");
+ }
Review Comment:
This error message may be confusing. If the request has a state of `foo`,
this is going to indicate that the requestor must specify the updated state.
Rather, it should indicate that the given state is invalid.
##########
nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/ControllerServiceResource.java:
##########
@@ -680,6 +681,116 @@ public Response updateControllerService(
);
}
+ /**
+ * Moves the specified Controller Service to parent/child process groups.
+ *
+ * @param id The id of the controller service to update.
+ * @param requestControllerServiceEntity A controllerServiceEntity.
+ * @return A controllerServiceEntity.
+ */
+ @PUT
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ @Path("{id}/move")
+ @Operation(
+ summary = "Move Controller Service to the specified Process
Group.",
+ responses = @ApiResponse(content = @Content(schema =
@Schema(implementation = ControllerServiceEntity.class))),
+ security = {
+ @SecurityRequirement(name = "Write -
/controller-services/{uuid}"),
+ @SecurityRequirement(name = "Write - Parent Process Group
if scoped by Process Group - /process-groups/{uuid}"),
+ @SecurityRequirement(name = "Write - Controller if scoped
by Controller - /controller"),
+ @SecurityRequirement(name = "Read - any referenced
Controller Services - /controller-services/{uuid}")
+ })
+ @ApiResponses(
+ value = {
+ @ApiResponse(responseCode = "400", description = "NiFi was
unable to complete the request because it was invalid. The request should not
be retried without modification."),
+ @ApiResponse(responseCode = "401", description = "Client
could not be authenticated."),
+ @ApiResponse(responseCode = "403", description = "Client
is not authorized to make this request."),
+ @ApiResponse(responseCode = "404", description = "The
specified resource could not be found."),
+ @ApiResponse(responseCode = "409", description = "The
request was valid but NiFi was not in the appropriate state to process it.")
+ }
+ )
+ public Response moveControllerServices(
+ @Parameter(
+ description = "The controller service id.",
+ required = true
+ )
+ @PathParam("id") final String id,
+ @Parameter(
+ description = "The controller service entity",
+ required = true
+ )
+ final ControllerServiceEntity requestControllerServiceEntity) {
+
+ if (requestControllerServiceEntity == null) {
+ throw new IllegalArgumentException("Controller service must be
specified.");
+ }
+
+ if (requestControllerServiceEntity.getRevision() == null) {
+ throw new IllegalArgumentException("Revision must be specified.");
+ }
+
+ if (requestControllerServiceEntity.getParentGroupId() == null) {
+ throw new IllegalArgumentException("ParentGroupId must be
specified.");
+ }
+
+ final ControllerServiceDTO requestControllerServiceDTO =
serviceFacade.getControllerService(id, true).getComponent();
+ ControllerServiceState requestControllerServiceState = null;
+ try {
+ requestControllerServiceState =
ControllerServiceState.valueOf(requestControllerServiceDTO.getState());
+ } catch (final IllegalArgumentException iae) {
+ // ignore
+ }
+
+ // ensure an action has been specified
+ if (requestControllerServiceState == null) {
+ throw new IllegalArgumentException("Must specify the updated
state. To update the referencing Controller Services the "
+ + "state should be DISABLED.");
+ }
+
+ // ensure the controller service state is not DISABLING
+ if
(!ControllerServiceState.DISABLED.equals(requestControllerServiceState) ) {
+ throw new IllegalArgumentException("Cannot set the referencing
services to ENABLING or DISABLING");
+ }
+
+ final Revision requestRevision =
getRevision(requestControllerServiceEntity, id);
+ return withWriteLock(
+ serviceFacade,
+ serviceFacade.getControllerService(id, true),
+ requestRevision,
+ lookup -> {
+ // authorize the service
+ final ComponentAuthorizable authorizable =
lookup.getControllerService(requestControllerServiceDTO.getId());
+ authorizable.getAuthorizable().authorize(authorizer,
RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
+
+ // authorize the current and new process groups
+ final ProcessGroupAuthorizable authorizableProcessGroupNew
= lookup.getProcessGroup(requestControllerServiceEntity.getParentGroupId());
+
authorizableProcessGroupNew.getAuthorizable().authorize(authorizer,
RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
+
+ final ProcessGroupAuthorizable authorizableProcessGroupOld
= lookup.getProcessGroup(requestControllerServiceDTO.getParentGroupId());
+
authorizableProcessGroupOld.getAuthorizable().authorize(authorizer,
RequestAction.WRITE, NiFiUserUtils.getNiFiUser());
+
+ // authorize any referenced services
+
AuthorizeControllerServiceReference.authorizeControllerServiceReferences(requestControllerServiceDTO.getProperties(),
authorizable, authorizer, lookup);
+
AuthorizeParameterReference.authorizeParameterReferences(requestControllerServiceDTO.getProperties(),
authorizer, authorizable.getParameterContext(),
+ NiFiUserUtils.getNiFiUser());
+
+ // authorize referencing components
+
requestControllerServiceDTO.getReferencingComponents().forEach(e -> {
+ final Authorizable controllerService =
lookup.getControllerServiceReferencingComponent(requestControllerServiceDTO.getId(),
e.getId());
+
OperationAuthorizable.authorizeOperation(controllerService, authorizer,
NiFiUserUtils.getNiFiUser());
+ });
+ },
+ null,
Review Comment:
Verification step should go here, to ensure that any components that are
referencing the Controller Service will still be able to reference the
Controller Service once it has been moved. Otherwise, it should throw an
IllegalStateException.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]