From 69367ff0bf9321c498973e64103e2a1477037383 Mon Sep 17 00:00:00 2001 From: Bryan Bende Date: Sun, 11 Feb 2018 11:13:18 -0500 Subject: [PATCH] NIFI-4839 - Updating README and cleaning up descriptions and comments - Making registryClientId optional and auto selecting when only one is available - Added delete-bucket command - Added delete-flow command for registry --- nifi-toolkit/nifi-toolkit-cli/README.md | 31 +++++++- .../apache/nifi/toolkit/cli/api/Command.java | 4 +- .../cli/impl/command/CommandOption.java | 1 + .../cli/impl/command/nifi/pg/PGImport.java | 26 ++++++- .../registry/NiFiRegistryCommandGroup.java | 4 ++ .../command/registry/bucket/DeleteBucket.java | 70 ++++++++++++++++++ .../command/registry/flow/DeleteFlow.java | 72 +++++++++++++++++++ .../registry/flow/ImportFlowVersion.java | 2 +- 8 files changed, 204 insertions(+), 6 deletions(-) create mode 100644 nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/bucket/DeleteBucket.java create mode 100644 nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/flow/DeleteFlow.java diff --git a/nifi-toolkit/nifi-toolkit-cli/README.md b/nifi-toolkit/nifi-toolkit-cli/README.md index ed3bdb16fd..02fae89c3e 100644 --- a/nifi-toolkit/nifi-toolkit-cli/README.md +++ b/nifi-toolkit/nifi-toolkit-cli/README.md @@ -122,4 +122,33 @@ Example of json output for list-buckets: }, "href" : "buckets/3c7b7467-0012-4d8f-a918-6aa42b6b9d39" } - } ] \ No newline at end of file + } ] + +## Adding Commands + +To add a NiFi command, create a new class that extends AbstractNiFiCommand: + + public class MyCommand extends AbstractNiFiCommand { + + public MyCommand() { + super("my-command"); + } + + @Override + protected void doExecute(NiFiClient client, Properties properties) + throws NiFiClientException, IOException, MissingOptionException, CommandException { + // TODO implement + } + + @Override + public String getDescription() { + return "This is my new command"; + } + } + +Add the new command to NiFiCommandGroup: + + commands.add(new MyCommand()); + +To add a NiFi Registry command, perform the same steps, but extend from +AbstractNiFiRegistryCommand, and add the command to NiFiRegistryCommandGroup. \ No newline at end of file diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/api/Command.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/api/Command.java index 09ba5c8f84..1a21a8bbc6 100644 --- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/api/Command.java +++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/api/Command.java @@ -20,7 +20,7 @@ import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.Options; /** - * Represents a command to execute against NiFi registry. + * Represents a command to execute. */ public interface Command { @@ -32,7 +32,7 @@ public interface Command { void initialize(Context context); /** - * @return the name of the command that will be specified as the first argument to the tool + * @return the name of the command */ String getName(); diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/CommandOption.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/CommandOption.java index 50986d2a49..cf325a1bf9 100644 --- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/CommandOption.java +++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/CommandOption.java @@ -65,6 +65,7 @@ public enum CommandOption { PROTOCOL("pro", "protocol", "The security protocol to use, such as TLSv.1.2", true), // Miscellaneous + FORCE("force", "force", "Indicates to force a delete operation", false), OUTPUT_TYPE("ot", "outputType", "The type of output to produce (json or simple)", true), VERBOSE("verbose", "verbose", "Indicates that verbose output should be provided", false), HELP("h", "help", "Help", false) diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/pg/PGImport.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/pg/PGImport.java index d3a3866e80..494b3fbccd 100644 --- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/pg/PGImport.java +++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/pg/PGImport.java @@ -30,9 +30,12 @@ import org.apache.nifi.web.api.dto.PositionDTO; import org.apache.nifi.web.api.dto.ProcessGroupDTO; import org.apache.nifi.web.api.dto.VersionControlInformationDTO; import org.apache.nifi.web.api.entity.ProcessGroupEntity; +import org.apache.nifi.web.api.entity.RegistryClientEntity; +import org.apache.nifi.web.api.entity.RegistryClientsEntity; import java.io.IOException; import java.util.Properties; +import java.util.Set; /** * Command for importing a flow to NiFi from NiFi Registry. @@ -46,7 +49,8 @@ public class PGImport extends AbstractNiFiCommand { @Override public String getDescription() { return "Creates a new process group by importing a versioned flow from a registry. If no process group id is " + - "specified, then the created process group will be placed in the root group."; + "specified, then the created process group will be placed in the root group. If only one registry client " + + "exists in NiFi, then it does not need to be specified and will be automatically selected."; } @Override @@ -62,11 +66,29 @@ public class PGImport extends AbstractNiFiCommand { protected void doExecute(final NiFiClient client, final Properties properties) throws NiFiClientException, IOException, MissingOptionException { - final String registryId = getRequiredArg(properties, CommandOption.REGISTRY_CLIENT_ID); final String bucketId = getRequiredArg(properties, CommandOption.BUCKET_ID); final String flowId = getRequiredArg(properties, CommandOption.FLOW_ID); final Integer flowVersion = getRequiredIntArg(properties, CommandOption.FLOW_VERSION); + // if a registry client is specified use it, otherwise see if there is only one available and use that, + // if more than one is available then throw an exception because we don't know which one to use + String registryId = getArg(properties, CommandOption.REGISTRY_CLIENT_ID); + if (StringUtils.isBlank(registryId)) { + final RegistryClientsEntity registries = client.getControllerClient().getRegistryClients(); + + final Set entities = registries.getRegistries(); + if (entities == null || entities.isEmpty()) { + throw new NiFiClientException("No registry clients available"); + } + + if (entities.size() == 1) { + registryId = entities.stream().findFirst().get().getId(); + } else { + throw new MissingOptionException(CommandOption.REGISTRY_CLIENT_ID.getLongName() + + " must be provided when there is more than one available"); + } + } + // get the optional id of the parent PG, otherwise fallback to the root group String parentPgId = getArg(properties, CommandOption.PG_ID); if (StringUtils.isBlank(parentPgId)) { diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/NiFiRegistryCommandGroup.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/NiFiRegistryCommandGroup.java index 12a75d8510..be40808f17 100644 --- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/NiFiRegistryCommandGroup.java +++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/NiFiRegistryCommandGroup.java @@ -19,8 +19,10 @@ package org.apache.nifi.toolkit.cli.impl.command.registry; import org.apache.nifi.toolkit.cli.api.Command; import org.apache.nifi.toolkit.cli.impl.command.AbstractCommandGroup; import org.apache.nifi.toolkit.cli.impl.command.registry.bucket.CreateBucket; +import org.apache.nifi.toolkit.cli.impl.command.registry.bucket.DeleteBucket; import org.apache.nifi.toolkit.cli.impl.command.registry.bucket.ListBuckets; import org.apache.nifi.toolkit.cli.impl.command.registry.flow.CreateFlow; +import org.apache.nifi.toolkit.cli.impl.command.registry.flow.DeleteFlow; import org.apache.nifi.toolkit.cli.impl.command.registry.flow.ExportFlowVersion; import org.apache.nifi.toolkit.cli.impl.command.registry.flow.ImportFlowVersion; import org.apache.nifi.toolkit.cli.impl.command.registry.flow.ListFlowVersions; @@ -47,8 +49,10 @@ public class NiFiRegistryCommandGroup extends AbstractCommandGroup { commandList.add(new CurrentUser()); commandList.add(new ListBuckets()); commandList.add(new CreateBucket()); + commandList.add(new DeleteBucket()); commandList.add(new ListFlows()); commandList.add(new CreateFlow()); + commandList.add(new DeleteFlow()); commandList.add(new ListFlowVersions()); commandList.add(new ExportFlowVersion()); commandList.add(new ImportFlowVersion()); diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/bucket/DeleteBucket.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/bucket/DeleteBucket.java new file mode 100644 index 0000000000..8dc4630b3f --- /dev/null +++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/bucket/DeleteBucket.java @@ -0,0 +1,70 @@ +/* + * 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.registry.bucket; + +import org.apache.commons.cli.ParseException; +import org.apache.nifi.registry.client.BucketClient; +import org.apache.nifi.registry.client.FlowClient; +import org.apache.nifi.registry.client.NiFiRegistryClient; +import org.apache.nifi.registry.client.NiFiRegistryException; +import org.apache.nifi.registry.flow.VersionedFlow; +import org.apache.nifi.toolkit.cli.api.Context; +import org.apache.nifi.toolkit.cli.impl.command.CommandOption; +import org.apache.nifi.toolkit.cli.impl.command.registry.AbstractNiFiRegistryCommand; + +import java.io.IOException; +import java.util.List; +import java.util.Properties; + +/** + * Deletes a bucket from the given registry. + */ +public class DeleteBucket extends AbstractNiFiRegistryCommand { + + public DeleteBucket() { + super("delete-bucket"); + } + + @Override + public String getDescription() { + return "Deletes the bucket with the given id. If the bucket contains any items then the force option must be used."; + } + + @Override + protected void doInitialize(Context context) { + addOption(CommandOption.BUCKET_ID.createOption()); + addOption(CommandOption.FORCE.createOption()); + } + + @Override + protected void doExecute(final NiFiRegistryClient client, final Properties properties) + throws IOException, NiFiRegistryException, ParseException { + + final String bucketId = getRequiredArg(properties, CommandOption.BUCKET_ID); + final boolean forceDelete = properties.containsKey(CommandOption.FORCE.getLongName()); + + final FlowClient flowClient = client.getFlowClient(); + final List flowsInBucket = flowClient.getByBucket(bucketId); + + if (flowsInBucket != null && flowsInBucket.size() > 0 && !forceDelete) { + throw new NiFiRegistryException("Bucket is not empty, use --" + CommandOption.FORCE.getLongName() + " to delete"); + } else { + final BucketClient bucketClient = client.getBucketClient(); + bucketClient.delete(bucketId); + } + } +} diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/flow/DeleteFlow.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/flow/DeleteFlow.java new file mode 100644 index 0000000000..8dbc9195bd --- /dev/null +++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/flow/DeleteFlow.java @@ -0,0 +1,72 @@ +/* + * 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.registry.flow; + +import org.apache.commons.cli.ParseException; +import org.apache.nifi.registry.client.FlowClient; +import org.apache.nifi.registry.client.FlowSnapshotClient; +import org.apache.nifi.registry.client.NiFiRegistryClient; +import org.apache.nifi.registry.client.NiFiRegistryException; +import org.apache.nifi.registry.flow.VersionedFlowSnapshotMetadata; +import org.apache.nifi.toolkit.cli.api.Context; +import org.apache.nifi.toolkit.cli.impl.command.CommandOption; +import org.apache.nifi.toolkit.cli.impl.command.registry.AbstractNiFiRegistryCommand; + +import java.io.IOException; +import java.util.List; +import java.util.Properties; + +/** + * Deletes a flow from the given registry. + */ +public class DeleteFlow extends AbstractNiFiRegistryCommand { + + public DeleteFlow() { + super("delete-flow"); + } + + @Override + public String getDescription() { + return "Deletes a flow from the registry. If the flow has one or more versions then the force option must be used."; + } + + @Override + protected void doInitialize(Context context) { + addOption(CommandOption.FLOW_ID.createOption()); + addOption(CommandOption.FORCE.createOption()); + } + + @Override + protected void doExecute(final NiFiRegistryClient client, final Properties properties) + throws IOException, NiFiRegistryException, ParseException { + + final String flowId = getRequiredArg(properties, CommandOption.FLOW_ID); + final boolean forceDelete = properties.containsKey(CommandOption.FORCE.getLongName()); + + final String bucketId = getBucketId(client, flowId); + + final FlowSnapshotClient flowSnapshotClient = client.getFlowSnapshotClient(); + final List snapshotMetadata = flowSnapshotClient.getSnapshotMetadata(bucketId, flowId); + + if (snapshotMetadata != null && snapshotMetadata.size() > 0 && !forceDelete) { + throw new NiFiRegistryException("Flow has versions, use --" + CommandOption.FORCE.getLongName() + " to delete"); + } else { + final FlowClient flowClient = client.getFlowClient(); + flowClient.delete(bucketId, flowId); + } + } +} diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/flow/ImportFlowVersion.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/flow/ImportFlowVersion.java index 21df12340a..fe2539e1fa 100644 --- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/flow/ImportFlowVersion.java +++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/registry/flow/ImportFlowVersion.java @@ -48,7 +48,7 @@ public class ImportFlowVersion extends AbstractNiFiRegistryCommand { @Override public String getDescription() { - return "Imports a version of a flow that was previously exported. The imported version automatically becomes " + + return "Imports a version of a flow from a local file, or a URL. The imported version automatically becomes " + "the next version of the given flow."; }