Skip to content

Commit

Permalink
NIFI-3785: Moved the logic for getting process group options to an AP…
Browse files Browse the repository at this point in the history
…I call. Moved move dialog to ui/controller-service.
  • Loading branch information
Freedom9339 committed Oct 28, 2024
1 parent 6491b39 commit 47df567
Show file tree
Hide file tree
Showing 17 changed files with 747 additions and 3,833 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.nifi.web.api.entity;

import io.swagger.v3.oas.annotations.media.Schema;

import jakarta.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "processGroupOptionEntity")
public class ProcessGroupOptionEntity extends Entity {

private String text;
private String value;
private String description;
private boolean disabled;

/**
* The name for this ProcessGroup.
*
* @return The name
*/
@Schema(description = "The name of this ProcessGroup.")
public String getText() {
return text;
}

public void setText(String id) {
this.text = id;
}

/**
* The id for this ProcessGroup.
*
* @return The id
*/
@Schema(description = "The id of this ProcessGroup.")
public String getValue() {
return value;
}

public void setValue(String value) {
this.value = value;
}

/**
* Text containing any conflicts for this ProcessGroup.
*
* @return The text
*/
@Schema(description = "Text containing any conflicts for this ProcessGroup.")
public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

/**
* Boolean showing whether this option is disabled.
*
* @return The disabled boolean
*/
@Schema(description = "Boolean showing whether this option is disabled.")
public boolean isDisabled() {
return disabled;
}

public void setDisabled(boolean disabled) {
this.disabled = disabled;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1127,15 +1127,6 @@ Set<DocumentedTypeDTO> getControllerServiceTypes(final String serviceType, final
*/
ProcessGroupEntity getProcessGroup(String groupId);

/**
* Returns the process group.
*
* @param groupId group
* @param recurse boolean
* @return ProcessGroup transfer object
*/
ProcessGroupEntity getProcessGroup(String groupId, boolean recurse);

/**
* Verifies that a Parameter Context matching the given DTO can be created
* @param parameterContext the DTO that represents the Parameter Context
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4798,14 +4798,11 @@ public Set<PortEntity> getOutputPorts(final String groupId) {
}

private ProcessGroupEntity createProcessGroupEntity(final ProcessGroup group) {
return createProcessGroupEntity(group, false);
}
private ProcessGroupEntity createProcessGroupEntity(final ProcessGroup group, final boolean recurse) {
final RevisionDTO revision = dtoFactory.createRevisionDTO(revisionManager.getRevision(group.getIdentifier()));
final PermissionsDTO permissions = dtoFactory.createPermissionsDto(group);
final ProcessGroupStatusDTO status = dtoFactory.createConciseProcessGroupStatusDto(controllerFacade.getProcessGroupStatus(group.getIdentifier()));
final List<BulletinEntity> bulletins = getProcessGroupBulletins(group);
return entityFactory.createProcessGroupEntity(dtoFactory.createProcessGroupDto(group, recurse), revision, permissions, status, bulletins);
return entityFactory.createProcessGroupEntity(dtoFactory.createProcessGroupDto(group), revision, permissions, status, bulletins);
}

private List<BulletinEntity> getProcessGroupBulletins(final ProcessGroup group) {
Expand Down Expand Up @@ -4985,13 +4982,8 @@ public FlowBreadcrumbEntity getProcessGroupBreadcrumbs(final String groupId) {

@Override
public ProcessGroupEntity getProcessGroup(final String groupId) {
return getProcessGroup(groupId, false);
}

@Override
public ProcessGroupEntity getProcessGroup(final String groupId, final boolean recurse) {
final ProcessGroup processGroup = processGroupDAO.getProcessGroup(groupId);
return createProcessGroupEntity(processGroup, recurse);
return createProcessGroupEntity(processGroup);
}

private ControllerServiceEntity createControllerServiceEntity(final ControllerServiceNode serviceNode, final boolean includeReferencingComponents) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
import org.apache.nifi.web.api.entity.ControllerServiceEntity;
import org.apache.nifi.web.api.entity.ControllerServiceReferencingComponentsEntity;
import org.apache.nifi.web.api.entity.ControllerServiceRunStatusEntity;
import org.apache.nifi.web.api.entity.ProcessGroupOptionEntity;
import org.apache.nifi.web.api.entity.PropertyDescriptorEntity;
import org.apache.nifi.web.api.entity.UpdateControllerServiceReferenceRequestEntity;
import org.apache.nifi.web.api.entity.VerifyConfigRequestEntity;
Expand Down Expand Up @@ -685,6 +686,98 @@ public Response updateControllerService(
);
}

@GET
@Consumes(MediaType.WILDCARD)
@Produces(MediaType.APPLICATION_JSON)
@Path("{id}/move-options")
@Operation(
summary = "Gets the move options for a controller service",
responses = @ApiResponse(content = @Content(schema = @Schema(implementation = ProcessGroupOptionEntity.class))),
security = {
@SecurityRequirement(name = "Read - /flow")
}
)
@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 getProcessGroupOptions(
@Parameter(description = "The controller service id.")
@PathParam("id") final String controllerServiceId) {

if (controllerServiceId == null) {
throw new IllegalArgumentException("Controller service id must be specified.");
}

List<ProcessGroupOptionEntity> options = new ArrayList<>();
serviceFacade.authorizeAccess(lookup -> {
final NiFiUser user = NiFiUserUtils.getNiFiUser();

final ComponentAuthorizable authorizableControllerService = lookup.getControllerService(controllerServiceId);
authorizableControllerService.getAuthorizable().authorize(authorizer, RequestAction.WRITE, user);

final ControllerServiceDTO controllerServiceDTO = serviceFacade.getControllerService(controllerServiceId, true).getComponent();

final ProcessGroupAuthorizable authorizableProcessGroupCurrent = lookup.getProcessGroup(controllerServiceDTO.getParentGroupId());
authorizableProcessGroupCurrent.getAuthorizable().authorize(authorizer, RequestAction.WRITE, user);

if (authorizableProcessGroupCurrent.getProcessGroup().getParent() != null) {
final ProcessGroupAuthorizable authorizableProcessGroupParent = lookup.getProcessGroup(authorizableProcessGroupCurrent.getProcessGroup().getParent().getIdentifier());
authorizableProcessGroupParent.getAuthorizable().authorize(authorizer, RequestAction.WRITE, user);

options.add(generateProcessGroupOption(controllerServiceDTO, authorizableProcessGroupParent));
}

authorizableProcessGroupCurrent.getProcessGroup().getProcessGroups().forEach(processGroup -> {
final ProcessGroupAuthorizable authorizableProcessGroup = lookup.getProcessGroup(processGroup.getIdentifier());
authorizableProcessGroup.getAuthorizable().authorize(authorizer, RequestAction.WRITE, user);
options.add(generateProcessGroupOption(controllerServiceDTO, authorizableProcessGroup));
});
});

return generateOkResponse(options).build();
}

private ProcessGroupOptionEntity generateProcessGroupOption(ControllerServiceDTO controllerServiceDTO, ProcessGroupAuthorizable processGroup) {
List<String> conflictingComponents = new ArrayList<>();
controllerServiceDTO.getReferencingComponents().forEach(e -> {
if (processGroup.getProcessGroup().findProcessor(e.getId()) == null
&& processGroup.getProcessGroup().findControllerService(e.getId(), true, false) == null) {
conflictingComponents.add("[" + e.getComponent().getName() + "]");
}
});

controllerServiceDTO.getProperties().forEach((key, value) -> {
try {
ControllerServiceEntity refControllerService = serviceFacade.getControllerService(value, false);
if (refControllerService != null) {
if (processGroup.getProcessGroup().findControllerService(value, false, true) == null) {
conflictingComponents.add("[" + refControllerService.getComponent().getName() + "]");
}
}
} catch (Exception ignored) { }
});

ProcessGroupOptionEntity option = new ProcessGroupOptionEntity();
option.setText(processGroup.getProcessGroup().getName());
option.setValue(processGroup.getProcessGroup().getIdentifier());
option.setDisabled(false);

if (!conflictingComponents.isEmpty()) {
String errorMessage = "Could not move controller service because the following components would be out of scope: ";
errorMessage += String.join(" ", conflictingComponents);
option.setDescription(errorMessage);
option.setDisabled(true);
}

return option;
}

/**
* Moves the specified Controller Service to parent/child process groups.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,9 +247,7 @@ private FlowDTO populateRemainingSnippetContent(FlowDTO flow) {
)
public Response getProcessGroup(
@Parameter(description = "The process group id.")
@PathParam("id") final String groupId,
@QueryParam("includeContent") @DefaultValue("false")
@Parameter(description = "Include content for process group") boolean includeContent) {
@PathParam("id") final String groupId) {

if (isReplicateRequest()) {
return replicate(HttpMethod.GET);
Expand All @@ -262,10 +260,10 @@ public Response getProcessGroup(
});

// get this process group contents
final ProcessGroupEntity entity = serviceFacade.getProcessGroup(groupId, includeContent);
final ProcessGroupEntity entity = serviceFacade.getProcessGroup(groupId);
populateRemainingProcessGroupEntityContent(entity);

if (entity.getComponent() != null && !includeContent) {
if (entity.getComponent() != null) {
entity.getComponent().setContents(null);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,17 @@ export class ControllerServiceService implements ControllerServiceCreator, Prope

moveControllerService(moveControllerService: MoveControllerServiceRequest): Observable<any> {
return this.httpClient.put(
this.nifiCommon.stripProtocol(moveControllerService.controllerService.uri + '/move'),
this.nifiCommon.stripProtocol(`${moveControllerService.controllerService.uri}/move`),
moveControllerService.data
);
}

getMoveOptions(controllerServiceId: string): Observable<any> {
return this.httpClient.get(
`${ControllerServiceService.API}/controller-services/${controllerServiceId}/move-options`
);
}

deleteControllerService(deleteControllerService: DeleteControllerServiceRequest): Observable<any> {
const entity: ControllerServiceEntity = deleteControllerService.controllerService;
const params = new HttpParams({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,6 @@ export class FlowService implements PropertyDescriptorRetriever {
return this.httpClient.get(`${FlowService.API}/process-groups/${id}`);
}

getProcessGroupWithContent(id: string): Observable<any> {
const params = new HttpParams().set('includeContent', true);
return this.httpClient.get(`${FlowService.API}/process-groups/${id}`, { params: params });
}

createFunnel(processGroupId = 'root', createFunnel: CreateComponentRequest): Observable<any> {
return this.httpClient.post(`${FlowService.API}/process-groups/${processGroupId}/funnels`, {
revision: createFunnel.revision,
Expand Down
Loading

0 comments on commit 47df567

Please sign in to comment.