-
Notifications
You must be signed in to change notification settings - Fork 2.8k
NIFI-3785: Added feature to move controller services between process … #8965
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
@markap14 @exceptionfactory I've resubmitted this PR with the changes done to the new UI. The backend is the same as it was in the closed PR(#7734), but the UI changes were done against the new UI. |
Thanks for putting in the work to refactor this for the new UI @Freedom9339. |
Thanks for the mention @exceptionfactory! I'll have a look... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR @Freedom9339! I've left a number of comments below that mostly appear to be from using the Enable/Disable Service dialog has a starting point. Since that dialog needs to be used for both Services in the Flow and in the Controller Settings there area a number of considerations there that are not needed here.
In addition to the items below, please ensure you run prettier and that this PR isn't introducing any new lint issues (I think there are currently 31 left that we're slowly trying to work through). From nifi/nifi-frontend/src/main/frontend
please run:
$ npx nx prettier:format
$ npx nx lint
I will defer to @exceptionfactory or @markap14 for a more thorough review of the back end changes.
...ps/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.effects.ts
Outdated
Show resolved
Hide resolved
...ps/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.effects.ts
Outdated
Show resolved
Hide resolved
...ps/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.reducer.ts
Outdated
Show resolved
Hide resolved
...i/common/controller-service/controller-service-table/controller-service-table.component.html
Outdated
Show resolved
Hide resolved
.../ui/common/controller-service/move-controller-service/move-controller-service.component.html
Outdated
Show resolved
Hide resolved
...pp/ui/common/controller-service/move-controller-service/move-controller-service.component.ts
Outdated
Show resolved
Hide resolved
...pp/ui/common/controller-service/move-controller-service/move-controller-service.component.ts
Outdated
Show resolved
Hide resolved
nifi-frontend/src/main/frontend/apps/nifi/src/app/state/shared/index.ts
Outdated
Show resolved
Hide resolved
...ps/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.effects.ts
Outdated
Show resolved
Hide resolved
.../common/controller-service/move-controller-service/move-controller-service.component.spec.ts
Outdated
Show resolved
Hide resolved
@mcgilman Just checking in. Any updates on this? |
Thanks for the ping. Sorry for the delay, I'll try to get some more eyes on this PR this week. |
@mcgilman Sorry the pinging again. Just want to make sure this doesn't fall through the cracks. |
I just pulled down the latest. After rebasing against current
I then tried running with the built application but I'm seeing this error in dev tools when attempting to open the
Once the PR is updated I should be able to get some more eyes on it quickly. |
9392904
to
9009d70
Compare
@mcgilman I fixed the issue caused by rebasing and pushed. Thank You! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the rebase! I've left some additional feedback below.
.../src/app/pages/flow-designer/ui/move-controller-service/move-controller-service.component.ts
Outdated
Show resolved
Hide resolved
...ps/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.effects.ts
Outdated
Show resolved
Hide resolved
...d/src/main/frontend/apps/nifi/src/app/pages/flow-designer/state/controller-services/index.ts
Outdated
Show resolved
Hide resolved
.../src/app/pages/flow-designer/ui/move-controller-service/move-controller-service.component.ts
Outdated
Show resolved
Hide resolved
...ps/nifi/src/app/pages/flow-designer/state/controller-services/controller-services.effects.ts
Outdated
Show resolved
Hide resolved
9009d70
to
5a86dbe
Compare
@mcgilman I've completed the change/fixes requested. Thank You! |
@mcgilman Sorry, I just realized my latest commit didn't go through. It's there now. |
c368f43
to
712413e
Compare
@mcgilman Any update on this? I just did a fresh rebase. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the updates @Freedom9339! I've left a few more comments below.
.../src/app/pages/flow-designer/ui/move-controller-service/move-controller-service.component.ts
Outdated
Show resolved
Hide resolved
.../src/app/pages/flow-designer/ui/move-controller-service/move-controller-service.component.ts
Outdated
Show resolved
Hide resolved
...rc/app/pages/flow-designer/ui/move-controller-service/move-controller-service.component.html
Outdated
Show resolved
Hide resolved
.../src/app/pages/flow-designer/ui/move-controller-service/move-controller-service.component.ts
Outdated
Show resolved
Hide resolved
...rc/app/pages/flow-designer/ui/move-controller-service/move-controller-service.component.html
Outdated
Show resolved
Hide resolved
...rc/app/pages/flow-designer/ui/move-controller-service/move-controller-service.component.html
Outdated
Show resolved
Hide resolved
...rc/app/pages/flow-designer/ui/move-controller-service/move-controller-service.component.html
Outdated
Show resolved
Hide resolved
712413e
to
275c18d
Compare
@mcgilman Thank you for the review. I've made the requested changes. Thank You. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Freedom9339 Thanks again for the updates! It's looking good. I've left a couple comments and I've noted a number of nit-picky coding style things to better follow some of the conventions currently practiced.
.../src/app/pages/flow-designer/ui/move-controller-service/move-controller-service.component.ts
Outdated
Show resolved
Hide resolved
...rc/app/pages/flow-designer/ui/move-controller-service/move-controller-service.component.html
Outdated
Show resolved
Hide resolved
|
||
// build the form | ||
this.moveControllerServiceForm = this.formBuilder.group({ | ||
processGroups: new FormControl('Process Group', Validators.required) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Process Group
is not a valid value for this field. We could initialize the value to null
but we're setting the value below. We could instead determine the value before creating the form and then just use the correct value when creating the FormControl
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what you mean by this. "Process Group" is what is shown whenever there is no process group selected. The only time this happens is if there are no valid process groups available.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The first argument to the FormControl is the value. The string Process Group
is not a valid value. What you see in the control when no value is select comes from the mat-label
in the mat-form-field
. If you want something else than the mat-label
value you can specify a placeholder
on the mat-select
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. I've removed the initial value.
.../src/app/pages/flow-designer/ui/move-controller-service/move-controller-service.component.ts
Outdated
Show resolved
Hide resolved
.../src/app/pages/flow-designer/ui/move-controller-service/move-controller-service.component.ts
Outdated
Show resolved
Hide resolved
.../src/app/pages/flow-designer/ui/move-controller-service/move-controller-service.component.ts
Outdated
Show resolved
Hide resolved
.../src/app/pages/flow-designer/ui/move-controller-service/move-controller-service.component.ts
Outdated
Show resolved
Hide resolved
.../src/app/pages/flow-designer/ui/move-controller-service/move-controller-service.component.ts
Outdated
Show resolved
Hide resolved
.../src/app/pages/flow-designer/ui/move-controller-service/move-controller-service.component.ts
Outdated
Show resolved
Hide resolved
nifi-frontend/src/main/frontend/apps/nifi/src/app/pages/flow-designer/service/flow.service.ts
Outdated
Show resolved
Hide resolved
59ef48f
to
47df567
Compare
...esigner/ui/controller-service/move-controller-service/move-controller-service.component.html
Outdated
Show resolved
Hide resolved
94b6dd4
to
bedb313
Compare
@mcgilman Sorry for the delay. I addressed the issues you mentioned and added more user validation to not expose any unauthorized components. I've tested every scenario I could think of. Please let me know if there is one I missed. |
bedb313
to
06a1e13
Compare
@mcgilman Any update on this? I've just rebased to fix merge conflicts. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the updates and the mention @Freedom9339! The front end changes are starting to look good. I've noted a couple minor things below. I've also noted a few things on the back end code but we'll want to get a closer look from @markap14 or @exceptionfactory before we sign off.
<div | ||
*ngIf="option.description != undefined; else valid" | ||
class="pointer fa fa-warning has-errors caution-color" | ||
style="padding: 3px"></div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure we should be using the warning icon here. When we use this, the user can hover to reveal the issue. However, here the icon cannot be interacted with and instead the warning is revealed as a tooltip on the menu item.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've removed the warning icon.
if (authorizableProcessGroupCurrent.getProcessGroup().getParent() != null) { | ||
final ProcessGroupAuthorizable authorizableProcessGroupParent = lookup.getProcessGroup(authorizableProcessGroupCurrent.getProcessGroup().getParent().getIdentifier()); | ||
if (authorizableProcessGroupParent.getAuthorizable().isAuthorized(authorizer, RequestAction.READ, user) | ||
&& authorizableProcessGroupParent.getAuthorizable().isAuthorized(authorizer, RequestAction.WRITE, user)) { | ||
options.add(generateProcessGroupOption(controllerServiceDTO, authorizableProcessGroupParent, lookup, user)); | ||
} | ||
} | ||
|
||
authorizableProcessGroupCurrent.getProcessGroup().getProcessGroups().forEach(processGroup -> { | ||
final ProcessGroupAuthorizable authorizableProcessGroup = lookup.getProcessGroup(processGroup.getIdentifier()); | ||
if (authorizableProcessGroup.getAuthorizable().isAuthorized(authorizer, RequestAction.READ, user) | ||
&& authorizableProcessGroup.getAuthorizable().isAuthorized(authorizer, RequestAction.WRITE, user)) { | ||
options.add(generateProcessGroupOption(controllerServiceDTO, authorizableProcessGroup, lookup, user)); | ||
} | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both parent and child options are added to the same collection. Do you think it would be helpful to differentiate between the parent Process Group from the child Process Groups in the listing shown to the user. I'm not suggesting we have to do this, just looking for feedback if you think it may be helpful to the user especially when dealing with a large flow.
The options collection is already ordered and should position the parent Process Group first but it'll only be present when the user has permissions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added "(Parent)" to the end of the parent process group and added a divider between the parent and child options.
return generateOkResponse(options).build(); | ||
} | ||
|
||
private ProcessGroupOptionEntity generateProcessGroupOption(ControllerServiceDTO controllerServiceDTO, ProcessGroupAuthorizable processGroup, AuthorizableLookup lookup, NiFiUser user) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This sort of logic is typically within the service facade. The Resource tier handles request validation, authorization, and request replication. It would defer to the service facade to handle the actual logic of the request.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've moved all the logic to the service facade.
@SecurityRequirement(name = "Read - /flow") | ||
} | ||
) | ||
public Response getProcessGroupOptions( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This endpoint needs to be replicated across the cluster. NiFi supports an extensible authorization model. That considered, for endpoints like we the call would be replicated to each node in the cluster. When in the response merger, we need to essentially return the intersection of options that are approved and in common for all nodes in the cluster.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added endpoint replication for clusters.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method implementation still appears to be limited to the current node, as opposed to replicating the request. In addition, I don't see the response merger implemented.
}) | ||
), | ||
catchError((errorResponse: HttpErrorResponse) => | ||
of(ErrorActions.snackBarError({ error: this.errorHelper.getErrorString(errorResponse) })) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this action happens with the dialog open and the dialog remains open, we should be using a banner error here. This will show the error in a banner within the dialog.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've changed this to use the banner instead of a toast.
return of( | ||
ErrorActions.snackBarError({ error: this.errorHelper.getErrorString(errorResponse) }) | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The effects for this action does not dispatch so this return
has no effect. You'll want to replace this with this.store.dispatch(...)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed this to tap and used store.dispatch. Error show up correctly now.
@@ -99,6 +100,17 @@ export const controllerServicesReducer = createReducer( | |||
draftState.saving = false; | |||
}); | |||
}), | |||
on(moveControllerServiceSuccess, (state, { response }) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
moveControllerService
should be added to the reducer above to ensure that the saving
flag is set to true
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added it to the reducers.
06a1e13
to
31a70f4
Compare
@mcgilman Thank you for the review. I've made the changed requested. |
@mcgilman Any new updates on this? |
@Freedom9339 In my last review I mentioned the UI portions were looking good but I will take a peek at your latest updates. I also provided some initial feedback on some of the back end changes but we'll want some additional eyes on those from someone more familiar with those portions of the code base. |
openMoveControllerServiceDialog$ = createEffect( | ||
() => | ||
this.actions$.pipe( | ||
ofType(ControllerServicesActions.openMoveControllerServiceDialog), | ||
map((action) => action.request), | ||
switchMap((request) => | ||
from(this.controllerServiceService.getMoveOptions(request.controllerService.id)).pipe( | ||
map((response: SelectOption[]) => { | ||
const moveDialogReference = this.dialog.open(MoveControllerService, { | ||
...LARGE_DIALOG, | ||
data: { | ||
controllerService: request.controllerService, | ||
options: response | ||
} | ||
}); | ||
|
||
moveDialogReference.componentInstance.goToReferencingComponent = ( | ||
component: ControllerServiceReferencingComponent | ||
) => { | ||
const route: string[] = this.getRouteForReference(component); | ||
this.router.navigate(route); | ||
}; | ||
|
||
moveDialogReference.afterClosed().subscribe((response) => { | ||
if (response != 'ROUTED') { | ||
this.store.dispatch( | ||
ControllerServicesActions.loadControllerServices({ | ||
request: { | ||
processGroupId: request.controllerService.parentGroupId! | ||
} | ||
}) | ||
); | ||
} | ||
}); | ||
}), | ||
tap({ | ||
error: (errorResponse: HttpErrorResponse) => { | ||
this.dialog.closeAll(); | ||
this.store.dispatch( | ||
ErrorActions.snackBarError({ | ||
error: this.errorHelper.getErrorString(errorResponse) | ||
}) | ||
); | ||
} | ||
}) | ||
) | ||
) | ||
), | ||
{ dispatch: false } | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
openMoveControllerServiceDialog$ = createEffect( | |
() => | |
this.actions$.pipe( | |
ofType(ControllerServicesActions.openMoveControllerServiceDialog), | |
map((action) => action.request), | |
switchMap((request) => | |
from(this.controllerServiceService.getMoveOptions(request.controllerService.id)).pipe( | |
map((response: SelectOption[]) => { | |
const moveDialogReference = this.dialog.open(MoveControllerService, { | |
...LARGE_DIALOG, | |
data: { | |
controllerService: request.controllerService, | |
options: response | |
} | |
}); | |
moveDialogReference.componentInstance.goToReferencingComponent = ( | |
component: ControllerServiceReferencingComponent | |
) => { | |
const route: string[] = this.getRouteForReference(component); | |
this.router.navigate(route); | |
}; | |
moveDialogReference.afterClosed().subscribe((response) => { | |
if (response != 'ROUTED') { | |
this.store.dispatch( | |
ControllerServicesActions.loadControllerServices({ | |
request: { | |
processGroupId: request.controllerService.parentGroupId! | |
} | |
}) | |
); | |
} | |
}); | |
}), | |
tap({ | |
error: (errorResponse: HttpErrorResponse) => { | |
this.dialog.closeAll(); | |
this.store.dispatch( | |
ErrorActions.snackBarError({ | |
error: this.errorHelper.getErrorString(errorResponse) | |
}) | |
); | |
} | |
}) | |
) | |
) | |
), | |
{ dispatch: false } | |
); | |
openMoveControllerServiceDialog$ = createEffect( | |
() => | |
this.actions$.pipe( | |
ofType(ControllerServicesActions.openMoveControllerServiceDialog), | |
map((action) => action.request), | |
switchMap((request) => | |
from(this.controllerServiceService.getMoveOptions(request.controllerService.id)).pipe( | |
map((options: SelectOption[]) => { | |
return { request, options }; | |
}), | |
tap({ | |
error: (errorResponse: HttpErrorResponse) => { | |
this.store.dispatch( | |
ErrorActions.snackBarError({ | |
error: this.errorHelper.getErrorString(errorResponse) | |
}) | |
); | |
} | |
}) | |
) | |
), | |
tap(({ request, options }) => { | |
const moveDialogReference = this.dialog.open(MoveControllerService, { | |
...LARGE_DIALOG, | |
data: { | |
controllerService: request.controllerService, | |
options | |
} | |
}); | |
moveDialogReference.componentInstance.goToReferencingComponent = ( | |
component: ControllerServiceReferencingComponent | |
) => { | |
const route: string[] = this.getRouteForReference(component); | |
this.router.navigate(route); | |
}; | |
moveDialogReference.afterClosed().subscribe((response) => { | |
if (response != 'ROUTED') { | |
this.store.dispatch( | |
ControllerServicesActions.loadControllerServices({ | |
request: { | |
processGroupId: request.controllerService.parentGroupId! | |
} | |
}) | |
); | |
} | |
}); | |
}) | |
), | |
{ dispatch: false } | |
); |
Here's a suggestion for the effect for querying for the available options prior to opening the dialog.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Applied this suggestion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the substantive effort on this feature @Freedom9339, and for the significant review work @mcgilman.
Unfortunately, I think the length of time this pull request has remained open, and the remaining issues around the service implementation, raise a concern about this going forward. As evidenced by the amount of changes required thus far, this feature presents a number of complexities related to request replication and permission checking that must be implemented correctly. Part of the challenge relates to the current complexity surrounding fine-grained permissions.
Although this provides helpful background, it seems like it may require a project maintainer to bring it to a state that is ready for merging. Again, this is primarily due to the significant complexity around permissions and clustering, requiring direct development as opposed a more standard pull request feedback cycle. That may mean this is put on hold for a time until there are sufficient cycles to bring it to completion.
@SecurityRequirement(name = "Read - /flow") | ||
} | ||
) | ||
public Response getProcessGroupOptions( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method implementation still appears to be limited to the current node, as opposed to replicating the request. In addition, I don't see the response merger implemented.
…groups with the new UI
… component to flow-designer. Added disabling options that have a move conflict
…upflow in the state and just load the info needed.
…I call. Moved move dialog to ui/controller-service.
…replication. Fixed error handling and made error message be a banner instead of a toast.
@exceptionfactory I've added the replicating of the move-options end point as well as merging the responses. Please let me know if this is being placed on hold or if there is anything else I need to do. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Freedom9339 I raised a few questions and noted several concerns on the REST API and service implementation. As mentioned, this is a complex feature, so I appreciate the effort. However, it is complex enough that it appears to require direct maintainer involvement to move forward. The work here is very helpful background, I'm not in a position to work on it right now, so it seems best to leave and restart down the road.
} | ||
} | ||
} | ||
} catch (Exception ignored) { } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is the exception ignored?
String errorMessage = "Cannot move to this process group because the following components would be out of scope: "; | ||
errorMessage += String.join(" ", conflictingComponents); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This message declaration could be collapsed into a single line.
} | ||
|
||
@Override | ||
public List<String> getConflictingComponents(ControllerServiceDTO controllerServiceDTO, ProcessGroupAuthorizable processGroup) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method returns the name or ID of referencing components, but "Conflicting Components" doesn't make that clear, so it seems like the naming is questionable, and it would probably be clearer to return a list of objects.
} | ||
|
||
@Override | ||
public ProcessGroupOptionEntity generateProcessGroupOption(ControllerServiceDTO controllerServiceDTO, ProcessGroupAuthorizable processGroup) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This ProcessGroupOptionEntity
is very generic, whereas it seems like it should be more targeted to the use case in question.
@@ -0,0 +1,44 @@ | |||
package org.apache.nifi.cluster.coordination.http.endpoints; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This class is missing a license header.
@GET | ||
@Consumes(MediaType.WILDCARD) | ||
@Produces(MediaType.APPLICATION_JSON) | ||
@Path("{id}/move-options") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
move-options
seems too generic for the purpose of the method. It seems more accurate to name this in relation to Process Groups, such as Destination Process Groups, or Available Process Groups.
@PUT | ||
@Consumes(MediaType.APPLICATION_JSON) | ||
@Produces(MediaType.APPLICATION_JSON) | ||
@Path("{id}/move") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although the REST API is not completely consistent, the general pattern is to have the path as a resource, which would change the approach to have the Process Group in the path.
@@ -2580,7 +2580,9 @@ public void removeControllerService(final ControllerServiceNode service) { | |||
throw new IllegalStateException("ControllerService " + service.getIdentifier() + " is not a member of this Process Group"); | |||
} | |||
|
|||
service.verifyCanDelete(); | |||
if (!service.isMoving()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason for not checking moving status inside the verifyCanDelete
method?
@@ -134,6 +135,7 @@ public StandardControllerServiceNode(final LoggableComponent<ControllerService> | |||
super(id, validationContextFactory, serviceProvider, componentType, componentCanonicalClass, reloadComponent, extensionManager, validationTrigger, isExtensionMissing); | |||
this.serviceProvider = serviceProvider; | |||
this.active = new AtomicBoolean(); | |||
this.moving = new AtomicBoolean(false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding this temporary state to the Node object raises a number of questions about the implementation, as it does not seem to fit with the other stateful properties.
…groups with the new UI
Summary
NIFI-3785: Added an option on the controller services grid that moves a controller service to a specified process group. The controller service can be moved to the parent process group or a child process group. However, it can only be moved one level at a time. If there are any scope conflicts with referencing components, the move will fail displaying the reason.
Tracking
Please complete the following tracking steps prior to pull request creation.
Issue Tracking
Pull Request Tracking
NIFI-00000
NIFI-00000
Pull Request Formatting
main
branchVerification
Please indicate the verification steps performed prior to pull request creation.
Build
mvn clean install -P contrib-check
Licensing
LICENSE
andNOTICE
filesDocumentation