NIFI-12479 Add pg-export to toolkit CLI

Signed-off-by: Pierre Villard <pierre.villard.fr@gmail.com>

This closes #8137.
This commit is contained in:
Timea Barna 2023-12-07 07:45:55 +01:00 committed by Pierre Villard
parent a126f6a7df
commit 71d99aff5d
No known key found for this signature in database
GPG Key ID: F92A93B30C07C6D5
7 changed files with 156 additions and 17 deletions

View File

@ -73,12 +73,13 @@ The following are available commands:
nifi update-reg-client
nifi get-reg-client-id
nifi pg-import
nifi pg-connect
nifi pg-start
nifi pg-stop
nifi pg-create
nifi pg-get-vars
nifi pg-set-var
nifi pg-export
nifi pg-get-version
nifi pg-stop-version-control
nifi pg-change-version
nifi pg-get-all-versions
nifi pg-list
@ -101,6 +102,9 @@ The following are available commands:
nifi delete-reporting-task
nifi start-reporting-tasks
nifi stop-reporting-tasks
nifi export-reporting-tasks
nifi export-reporting-task
nifi import-reporting-tasks
nifi list-users
nifi create-user
nifi list-user-groups
@ -130,6 +134,7 @@ The following are available commands:
nifi logout-access-token
nifi get-controller-configuration
nifi update-controller-configuration
nifi change-version-processor
registry current-user
registry list-buckets
registry create-bucket
@ -290,21 +295,21 @@ For example, typing tab at an empty prompt should display possible commands for
Typing "nifi " and then a tab will show the sub-commands for NiFi:
#> nifi
cluster-summary export-param-context list-users pg-set-param-context
connect-node get-node merge-param-context pg-set-var
create-param-context get-nodes offload-node pg-start
create-reg-client get-param-context pg-change-version pg-status
create-reporting-task get-policy pg-create-service pg-stop
create-service get-reg-client-id pg-create-service set-param
create-user get-reporting-task pg-disable-services start-reporting-tasks
create-user-group get-reporting-tasks pg-enable-services stop-reporting-tasks
current-user get-root-id pg-get-all-versions update-policy
delete-node get-service pg-get-param-context update-reg-client
delete-param get-services pg-get-services update-user-group
delete-param-context import-param-context pg-get-vars delete-reporting-task
disable-services list-param-contexts pg-get-version
disconnect-node list-reg-clients pg-import
enable-services list-user-groups pg-list
change-version-processor delete-reporting-task get-policy merge-param-context pg-replace update-user-group
cluster-summary disable-services get-reg-client-id offload-node pg-set-param-context
connect-node disconnect-node get-reporting-task pg-change-version pg-start
create-param-context enable-services get-reporting-tasks pg-connect pg-status
create-param-provider export-param-context get-root-id pg-create pg-stop
create-reg-client export-reporting-task get-service pg-create-service pg-stop-version-control
create-reporting-task export-reporting-tasks get-services pg-disable-services remove-inherited-param-contexts
create-service fetch-params import-param-context pg-enable-services set-inherited-param-contexts
create-user get-access-token import-reporting-tasks pg-export set-param
create-user-group get-access-token-spnego list-param-contexts pg-get-all-versions set-param-provider-property
current-user get-controller-configuration list-param-providers pg-get-param-context start-reporting-tasks
delete-node get-node list-reg-clients pg-get-services stop-reporting-tasks
delete-param get-nodes list-user-groups pg-get-version update-controller-configuration
delete-param-context get-param-context list-users pg-import update-policy
delete-param-provider get-param-provider logout-access-token pg-list update-reg-client
Arguments that represent a path to a file, such as `-p` or when setting a properties file in the session, will auto-complete the path being typed:

View File

@ -24,6 +24,7 @@ import org.apache.nifi.web.api.entity.ProcessGroupEntity;
import org.apache.nifi.web.api.entity.ProcessGroupImportEntity;
import org.apache.nifi.web.api.entity.ProcessGroupReplaceRequestEntity;
import java.io.File;
import java.io.IOException;
/**
@ -57,4 +58,6 @@ public interface ProcessGroupClient {
throws NiFiClientException, IOException;
FlowComparisonEntity getLocalModifications(String processGroupId) throws NiFiClientException, IOException;
File exportProcessGroup(String processGroupId, boolean includeReferencedServices, File outputFile) throws NiFiClientException, IOException;
}

View File

@ -16,10 +16,12 @@
*/
package org.apache.nifi.toolkit.cli.impl.client.nifi.impl;
import jakarta.ws.rs.core.Response;
import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClientException;
import org.apache.nifi.toolkit.cli.impl.client.nifi.ProcessGroupClient;
import org.apache.nifi.toolkit.cli.impl.client.nifi.RequestConfig;
import org.apache.nifi.toolkit.cli.impl.util.FileUtils;
import org.apache.nifi.web.api.entity.ControllerServiceEntity;
import org.apache.nifi.web.api.entity.CopySnippetRequestEntity;
import org.apache.nifi.web.api.entity.FlowComparisonEntity;
@ -31,6 +33,8 @@ import org.apache.nifi.web.api.entity.ProcessGroupReplaceRequestEntity;
import jakarta.ws.rs.client.Entity;
import jakarta.ws.rs.client.WebTarget;
import jakarta.ws.rs.core.MediaType;
import java.io.File;
import java.io.IOException;
/**
@ -240,4 +244,23 @@ public class JerseyProcessGroupClient extends AbstractJerseyClient implements Pr
});
}
@Override
public File exportProcessGroup(final String processGroupId, final boolean includeReferencedServices, final File outputFile) throws NiFiClientException, IOException {
if (StringUtils.isBlank(processGroupId)) {
throw new IllegalArgumentException("Process group id cannot be null or blank");
}
return executeAction("Error getting process group", () -> {
final WebTarget target = processGroupsTarget
.path("{id}/download")
.resolveTemplate("id", processGroupId)
.queryParam("includeReferencedServices", includeReferencedServices);
final Response response = getRequestBuilder(target)
.accept(MediaType.APPLICATION_JSON)
.get();
return FileUtils.getFileContent(response, outputFile);
});
}
}

View File

@ -88,6 +88,8 @@ public enum CommandOption {
PG_VAR_VALUE("val", "varValue", "The value of a variable", true),
KEEP_EXISTING_PARAMETER_CONTEXT("kepc", "keep-existing-parameter-context", "If false, only directly associated Parameter Contexts will be copied, "
+ "inherited Contexts with no direct assignment to a Process Group are ignored", true),
INCLUDE_REFERENCED_SERVICES("irs", "include-referenced-services", "Indicates that " +
"referenced services from outside the target group will be included.", false),
POS_X("px", "posX", "The x coordinate of a position", true),
POS_Y("py", "posY", "The y coordinate of a position", true),

View File

@ -68,6 +68,7 @@ import org.apache.nifi.toolkit.cli.impl.command.nifi.pg.PGCreate;
import org.apache.nifi.toolkit.cli.impl.command.nifi.pg.PGCreateControllerService;
import org.apache.nifi.toolkit.cli.impl.command.nifi.pg.PGDisableControllerServices;
import org.apache.nifi.toolkit.cli.impl.command.nifi.pg.PGEnableControllerServices;
import org.apache.nifi.toolkit.cli.impl.command.nifi.pg.PGExport;
import org.apache.nifi.toolkit.cli.impl.command.nifi.pg.PGGetAllVersions;
import org.apache.nifi.toolkit.cli.impl.command.nifi.pg.PGGetControllerServices;
import org.apache.nifi.toolkit.cli.impl.command.nifi.pg.PGGetParamContext;
@ -142,6 +143,7 @@ public class NiFiCommandGroup extends AbstractCommandGroup {
commands.add(new PGGetParamContext());
commands.add(new PGSetParamContext());
commands.add(new PGReplace());
commands.add(new PGExport());
commands.add(new GetControllerServices());
commands.add(new GetControllerService());
commands.add(new CreateControllerService());

View File

@ -0,0 +1,63 @@
/*
* 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.toolkit.cli.impl.command.nifi.pg;
import org.apache.commons.cli.MissingOptionException;
import org.apache.nifi.toolkit.cli.api.CommandException;
import org.apache.nifi.toolkit.cli.api.Context;
import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClient;
import org.apache.nifi.toolkit.cli.impl.client.nifi.NiFiClientException;
import org.apache.nifi.toolkit.cli.impl.client.nifi.ProcessGroupClient;
import org.apache.nifi.toolkit.cli.impl.command.CommandOption;
import org.apache.nifi.toolkit.cli.impl.command.nifi.AbstractNiFiCommand;
import org.apache.nifi.toolkit.cli.impl.result.VoidResult;
import java.io.File;
import java.io.IOException;
import java.util.Properties;
/**
* Command to export a given process-group to a json representation.
*/
public class PGExport extends AbstractNiFiCommand<VoidResult> {
public PGExport() {
super("pg-export", VoidResult.class);
}
@Override
public String getDescription() {
return "Exports a given process group to a json representation, with or without the referenced services from outside the target group.";
}
@Override
protected void doInitialize(Context context) {
addOption(CommandOption.PG_ID.createOption());
addOption(CommandOption.OUTPUT_FILE.createOption());
addOption(CommandOption.INCLUDE_REFERENCED_SERVICES.createOption());
}
@Override
public VoidResult doExecute(final NiFiClient client, final Properties properties) throws NiFiClientException, IOException, MissingOptionException, CommandException {
final String id = getRequiredArg(properties, CommandOption.PG_ID);
final boolean includeReferencedServices = getArg(properties, CommandOption.INCLUDE_REFERENCED_SERVICES) == null ? Boolean.FALSE : Boolean.TRUE;
final File outputFile = new File(getRequiredArg(properties, CommandOption.OUTPUT_FILE));
final ProcessGroupClient processGroupClient = client.getProcessGroupClient();
processGroupClient.exportProcessGroup(id, includeReferencedServices, outputFile);
return VoidResult.getInstance();
}
}

View File

@ -0,0 +1,41 @@
/*
* 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.toolkit.cli.impl.util;
import jakarta.ws.rs.core.Response;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
public class FileUtils {
public static File getFileContent(final Response response, final File outputFile) {
final String contentDispositionHeader = response.getHeaderString("Content-Disposition");
if (StringUtils.isBlank(contentDispositionHeader)) {
throw new IllegalStateException("Content-Disposition header was blank or missing");
}
try (final InputStream responseInputStream = response.readEntity(InputStream.class)) {
Files.copy(responseInputStream, outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
return outputFile;
} catch (Exception e) {
throw new IllegalStateException("Unable to write content due to: " + e.getMessage(), e);
}
}
}