From 3508560b7aae2884400e6f0b225610dc6f0c001f Mon Sep 17 00:00:00 2001 From: Pierre Villard Date: Tue, 19 Nov 2024 17:28:02 +0100 Subject: [PATCH] NIFI-13950 Add commands to list branch, bucket, flows, versions to CLI (#9473) Signed-off-by: David Handermann --- .../cli/impl/command/CommandOption.java | 1 + .../impl/command/nifi/NiFiCommandGroup.java | 8 ++ .../command/nifi/registry/ListBranches.java | 59 +++++++++++ .../command/nifi/registry/ListBuckets.java | 61 ++++++++++++ .../nifi/registry/ListFlowVersions.java | 66 +++++++++++++ .../impl/command/nifi/registry/ListFlows.java | 63 ++++++++++++ .../result/nifi/RegistryBranchesResult.java | 77 +++++++++++++++ .../result/nifi/RegistryBucketsResult.java | 79 +++++++++++++++ .../nifi/RegistryFlowVersionsResult.java | 91 +++++++++++++++++ .../impl/result/nifi/RegistryFlowsResult.java | 79 +++++++++++++++ .../nifi/toolkit/client/FlowClient.java | 39 ++++++++ .../toolkit/client/impl/JerseyFlowClient.java | 98 +++++++++++++++++-- 12 files changed, 712 insertions(+), 9 deletions(-) create mode 100644 nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/registry/ListBranches.java create mode 100644 nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/registry/ListBuckets.java create mode 100644 nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/registry/ListFlowVersions.java create mode 100644 nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/registry/ListFlows.java create mode 100644 nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/result/nifi/RegistryBranchesResult.java create mode 100644 nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/result/nifi/RegistryBucketsResult.java create mode 100644 nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/result/nifi/RegistryFlowVersionsResult.java create mode 100644 nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/result/nifi/RegistryFlowsResult.java 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 5bcf04d945..84da0839cf 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 @@ -47,6 +47,7 @@ public enum CommandOption { FLOW_NAME("fn", "flowName", "A flow name", true), FLOW_DESC("fd", "flowDesc", "A flow description", true), FLOW_VERSION("fv", "flowVersion", "A version of a flow", true), + FLOW_BRANCH("fb", "flowBranch", "A branch for the flow", true), FLOW_VERSION_1("fv1", "flowVersion1", "A version of a flow", true), FLOW_VERSION_2("fv2", "flowVersion2", "A version of a flow", true), diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/NiFiCommandGroup.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/NiFiCommandGroup.java index e244a44333..f916f0fc5a 100644 --- a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/NiFiCommandGroup.java +++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/NiFiCommandGroup.java @@ -110,6 +110,10 @@ import org.apache.nifi.toolkit.cli.impl.command.nifi.processors.ProcessorRunOnce import org.apache.nifi.toolkit.cli.impl.command.nifi.processors.ProcessorStart; import org.apache.nifi.toolkit.cli.impl.command.nifi.registry.CreateRegistryClient; import org.apache.nifi.toolkit.cli.impl.command.nifi.registry.GetRegistryClientId; +import org.apache.nifi.toolkit.cli.impl.command.nifi.registry.ListBranches; +import org.apache.nifi.toolkit.cli.impl.command.nifi.registry.ListBuckets; +import org.apache.nifi.toolkit.cli.impl.command.nifi.registry.ListFlowVersions; +import org.apache.nifi.toolkit.cli.impl.command.nifi.registry.ListFlows; import org.apache.nifi.toolkit.cli.impl.command.nifi.registry.ListRegistryClients; import org.apache.nifi.toolkit.cli.impl.command.nifi.registry.UpdateRegistryClient; import org.apache.nifi.toolkit.cli.impl.command.nifi.reporting.DeleteReportingTask; @@ -149,6 +153,10 @@ public class NiFiCommandGroup extends AbstractCommandGroup { commands.add(new CreateRegistryClient()); commands.add(new UpdateRegistryClient()); commands.add(new GetRegistryClientId()); + commands.add(new ListBranches()); + commands.add(new ListBuckets()); + commands.add(new ListFlows()); + commands.add(new ListFlowVersions()); commands.add(new PGImport()); commands.add(new PGConnect()); commands.add(new PGStart()); diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/registry/ListBranches.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/registry/ListBranches.java new file mode 100644 index 0000000000..6d88ad5f30 --- /dev/null +++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/registry/ListBranches.java @@ -0,0 +1,59 @@ +/* + * 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.registry; + +import org.apache.commons.cli.MissingOptionException; +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.nifi.AbstractNiFiCommand; +import org.apache.nifi.toolkit.cli.impl.result.nifi.RegistryBranchesResult; +import org.apache.nifi.toolkit.client.NiFiClient; +import org.apache.nifi.toolkit.client.NiFiClientException; +import org.apache.nifi.web.api.entity.FlowRegistryBranchesEntity; + +import java.io.IOException; +import java.util.Properties; + +/** + * Lists the branches seen by the specified registry client. + */ +public class ListBranches extends AbstractNiFiCommand { + + public ListBranches() { + super("list-branches", RegistryBranchesResult.class); + } + + @Override + protected void doInitialize(Context context) { + super.doInitialize(context); + addOption(CommandOption.REGISTRY_CLIENT_ID.createOption()); + } + + @Override + public String getDescription() { + return "Returns the list of branches seen by the specified registry client."; + } + + @Override + public RegistryBranchesResult doExecute(final NiFiClient client, final Properties properties) + throws NiFiClientException, IOException, MissingOptionException { + final String regClientId = getRequiredArg(properties, CommandOption.REGISTRY_CLIENT_ID); + final FlowRegistryBranchesEntity branches = client.getFlowClient().getFlowRegistryBranches(regClientId); + return new RegistryBranchesResult(getResultType(properties), branches); + } + +} diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/registry/ListBuckets.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/registry/ListBuckets.java new file mode 100644 index 0000000000..31f9ed904d --- /dev/null +++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/registry/ListBuckets.java @@ -0,0 +1,61 @@ +/* + * 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.registry; + +import org.apache.commons.cli.MissingOptionException; +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.nifi.AbstractNiFiCommand; +import org.apache.nifi.toolkit.cli.impl.result.nifi.RegistryBucketsResult; +import org.apache.nifi.toolkit.client.NiFiClient; +import org.apache.nifi.toolkit.client.NiFiClientException; +import org.apache.nifi.web.api.entity.FlowRegistryBucketsEntity; + +import java.io.IOException; +import java.util.Properties; + +/** + * Lists buckets for a given branch seen by a given registry client + */ +public class ListBuckets extends AbstractNiFiCommand { + + public ListBuckets() { + super("list-buckets", RegistryBucketsResult.class); + } + + @Override + protected void doInitialize(Context context) { + super.doInitialize(context); + addOption(CommandOption.REGISTRY_CLIENT_ID.createOption()); + addOption(CommandOption.FLOW_BRANCH.createOption()); + } + + @Override + public String getDescription() { + return "Returns the list of branches seen by the specified registry client."; + } + + @Override + public RegistryBucketsResult doExecute(final NiFiClient client, final Properties properties) + throws NiFiClientException, IOException, MissingOptionException { + final String regClientId = getRequiredArg(properties, CommandOption.REGISTRY_CLIENT_ID); + final String branchName = getRequiredArg(properties, CommandOption.FLOW_BRANCH); + final FlowRegistryBucketsEntity buckets = client.getFlowClient().getFlowRegistryBuckets(regClientId, branchName); + return new RegistryBucketsResult(getResultType(properties), buckets); + } + +} diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/registry/ListFlowVersions.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/registry/ListFlowVersions.java new file mode 100644 index 0000000000..8d318eabff --- /dev/null +++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/registry/ListFlowVersions.java @@ -0,0 +1,66 @@ +/* + * 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.registry; + +import org.apache.commons.cli.MissingOptionException; +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.nifi.AbstractNiFiCommand; +import org.apache.nifi.toolkit.cli.impl.result.nifi.RegistryFlowVersionsResult; +import org.apache.nifi.toolkit.client.NiFiClient; +import org.apache.nifi.toolkit.client.NiFiClientException; +import org.apache.nifi.web.api.entity.VersionedFlowSnapshotMetadataSetEntity; + +import java.io.IOException; +import java.util.Properties; + +/** + * Lists flow versions for a given flow in a given branch and bucket seen by a + * given registry client + */ +public class ListFlowVersions extends AbstractNiFiCommand { + + public ListFlowVersions() { + super("list-flow-versions", RegistryFlowVersionsResult.class); + } + + @Override + protected void doInitialize(Context context) { + super.doInitialize(context); + addOption(CommandOption.REGISTRY_CLIENT_ID.createOption()); + addOption(CommandOption.FLOW_BRANCH.createOption()); + addOption(CommandOption.BUCKET_ID.createOption()); + addOption(CommandOption.FLOW_ID.createOption()); + } + + @Override + public String getDescription() { + return "Returns the list of flow versions for a given flow in a given branch and bucket seen by the specified registry client."; + } + + @Override + public RegistryFlowVersionsResult doExecute(final NiFiClient client, final Properties properties) + throws NiFiClientException, IOException, MissingOptionException { + final String regClientId = getRequiredArg(properties, CommandOption.REGISTRY_CLIENT_ID); + final String branchName = getRequiredArg(properties, CommandOption.FLOW_BRANCH); + final String bucketId = getRequiredArg(properties, CommandOption.BUCKET_ID); + final String flowId = getRequiredArg(properties, CommandOption.FLOW_ID); + final VersionedFlowSnapshotMetadataSetEntity flowVersions = client.getFlowClient().getVersions(regClientId, bucketId, flowId, branchName); + return new RegistryFlowVersionsResult(getResultType(properties), flowVersions); + } + +} diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/registry/ListFlows.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/registry/ListFlows.java new file mode 100644 index 0000000000..f97f479fa7 --- /dev/null +++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/command/nifi/registry/ListFlows.java @@ -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.registry; + +import org.apache.commons.cli.MissingOptionException; +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.nifi.AbstractNiFiCommand; +import org.apache.nifi.toolkit.cli.impl.result.nifi.RegistryFlowsResult; +import org.apache.nifi.toolkit.client.NiFiClient; +import org.apache.nifi.toolkit.client.NiFiClientException; +import org.apache.nifi.web.api.entity.VersionedFlowsEntity; + +import java.io.IOException; +import java.util.Properties; + +/** + * Lists flows for a given branch and bucket seen by a given registry client + */ +public class ListFlows extends AbstractNiFiCommand { + + public ListFlows() { + super("list-flows", RegistryFlowsResult.class); + } + + @Override + protected void doInitialize(Context context) { + super.doInitialize(context); + addOption(CommandOption.REGISTRY_CLIENT_ID.createOption()); + addOption(CommandOption.FLOW_BRANCH.createOption()); + addOption(CommandOption.BUCKET_ID.createOption()); + } + + @Override + public String getDescription() { + return "Returns the list of flows in a given branch and bucket seen by the specified registry client."; + } + + @Override + public RegistryFlowsResult doExecute(final NiFiClient client, final Properties properties) + throws NiFiClientException, IOException, MissingOptionException { + final String regClientId = getRequiredArg(properties, CommandOption.REGISTRY_CLIENT_ID); + final String branchName = getRequiredArg(properties, CommandOption.FLOW_BRANCH); + final String bucketId = getRequiredArg(properties, CommandOption.BUCKET_ID); + final VersionedFlowsEntity flows = client.getFlowClient().getFlowRegistryFlows(regClientId, branchName, bucketId); + return new RegistryFlowsResult(getResultType(properties), flows); + } + +} diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/result/nifi/RegistryBranchesResult.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/result/nifi/RegistryBranchesResult.java new file mode 100644 index 0000000000..4c8cec5213 --- /dev/null +++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/result/nifi/RegistryBranchesResult.java @@ -0,0 +1,77 @@ +/* + * 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.result.nifi; + +import org.apache.nifi.toolkit.cli.api.ResultType; +import org.apache.nifi.toolkit.cli.impl.result.AbstractWritableResult; +import org.apache.nifi.toolkit.cli.impl.result.writer.DynamicTableWriter; +import org.apache.nifi.toolkit.cli.impl.result.writer.Table; +import org.apache.nifi.toolkit.cli.impl.result.writer.TableWriter; +import org.apache.nifi.web.api.dto.FlowRegistryBranchDTO; +import org.apache.nifi.web.api.entity.FlowRegistryBranchEntity; +import org.apache.nifi.web.api.entity.FlowRegistryBranchesEntity; + +import java.io.PrintStream; +import java.util.Comparator; +import java.util.List; +import java.util.Objects; +import java.util.Set; + +/** + * Result for a FlowRegistryBranchesEntity. + */ +public class RegistryBranchesResult extends AbstractWritableResult { + + final FlowRegistryBranchesEntity branchesEntity; + + public RegistryBranchesResult(final ResultType resultType, final FlowRegistryBranchesEntity branchesEntity) { + super(resultType); + this.branchesEntity = Objects.requireNonNull(branchesEntity); + } + + @Override + public FlowRegistryBranchesEntity getResult() { + return this.branchesEntity; + } + + @Override + protected void writeSimpleResult(final PrintStream output) { + final Set branches = branchesEntity.getBranches(); + if (branches == null || branches.isEmpty()) { + return; + } + + final List branchesDTO = branches.stream() + .map(b -> b.getBranch()) + .sorted(Comparator.comparing(FlowRegistryBranchDTO::getName)) + .toList(); + + final Table table = new Table.Builder() + .column("#", 3, 3, false) + .column("Name", 20, 36, true) + .build(); + + for (int i = 0; i < branchesDTO.size(); i++) { + FlowRegistryBranchDTO branch = branchesDTO.get(i); + table.addRow("" + (i + 1), branch.getName()); + } + + final TableWriter tableWriter = new DynamicTableWriter(); + tableWriter.write(table, output); + } + +} diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/result/nifi/RegistryBucketsResult.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/result/nifi/RegistryBucketsResult.java new file mode 100644 index 0000000000..a6b5daf545 --- /dev/null +++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/result/nifi/RegistryBucketsResult.java @@ -0,0 +1,79 @@ +/* + * 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.result.nifi; + +import org.apache.nifi.toolkit.cli.api.ResultType; +import org.apache.nifi.toolkit.cli.impl.result.AbstractWritableResult; +import org.apache.nifi.toolkit.cli.impl.result.writer.DynamicTableWriter; +import org.apache.nifi.toolkit.cli.impl.result.writer.Table; +import org.apache.nifi.toolkit.cli.impl.result.writer.TableWriter; +import org.apache.nifi.web.api.dto.FlowRegistryBucketDTO; +import org.apache.nifi.web.api.entity.FlowRegistryBucketEntity; +import org.apache.nifi.web.api.entity.FlowRegistryBucketsEntity; + +import java.io.PrintStream; +import java.util.Comparator; +import java.util.List; +import java.util.Objects; +import java.util.Set; + +/** + * Result for a FlowRegistryBucketsEntity. + */ +public class RegistryBucketsResult extends AbstractWritableResult { + + final FlowRegistryBucketsEntity bucketsEntity; + + public RegistryBucketsResult(final ResultType resultType, final FlowRegistryBucketsEntity bucketsEntity) { + super(resultType); + this.bucketsEntity = Objects.requireNonNull(bucketsEntity); + } + + @Override + public FlowRegistryBucketsEntity getResult() { + return this.bucketsEntity; + } + + @Override + protected void writeSimpleResult(final PrintStream output) { + final Set buckets = bucketsEntity.getBuckets(); + if (buckets == null || buckets.isEmpty()) { + return; + } + + final List bucketsDTO = buckets.stream() + .map(b -> b.getBucket()) + .sorted(Comparator.comparing(FlowRegistryBucketDTO::getName)) + .toList(); + + final Table table = new Table.Builder() + .column("#", 3, 3, false) + .column("Name", 20, 36, true) + .column("Id", 36, 36, false) + .column("Description", 11, 40, true) + .build(); + + for (int i = 0; i < bucketsDTO.size(); i++) { + FlowRegistryBucketDTO bucket = bucketsDTO.get(i); + table.addRow("" + (i + 1), bucket.getName(), bucket.getId(), bucket.getDescription() == null ? "" : bucket.getDescription()); + } + + final TableWriter tableWriter = new DynamicTableWriter(); + tableWriter.write(table, output); + } + +} diff --git a/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/result/nifi/RegistryFlowVersionsResult.java b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/result/nifi/RegistryFlowVersionsResult.java new file mode 100644 index 0000000000..d47c982fb7 --- /dev/null +++ b/nifi-toolkit/nifi-toolkit-cli/src/main/java/org/apache/nifi/toolkit/cli/impl/result/nifi/RegistryFlowVersionsResult.java @@ -0,0 +1,91 @@ +/* + * 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.result.nifi; + +import org.apache.nifi.registry.flow.RegisteredFlowSnapshotMetadata; +import org.apache.nifi.toolkit.cli.api.ResultType; +import org.apache.nifi.toolkit.cli.impl.result.AbstractWritableResult; +import org.apache.nifi.toolkit.cli.impl.result.writer.DynamicTableWriter; +import org.apache.nifi.toolkit.cli.impl.result.writer.Table; +import org.apache.nifi.toolkit.cli.impl.result.writer.TableWriter; +import org.apache.nifi.web.api.entity.VersionedFlowSnapshotMetadataEntity; +import org.apache.nifi.web.api.entity.VersionedFlowSnapshotMetadataSetEntity; + +import java.io.PrintStream; +import java.util.Comparator; +import java.util.Date; +import java.util.List; +import java.util.Objects; +import java.util.Set; + +/** + * Result for a VersionedFlowSnapshotMetadataSetEntity. + */ +public class RegistryFlowVersionsResult extends AbstractWritableResult { + + final VersionedFlowSnapshotMetadataSetEntity flowVersionsEntity; + + public RegistryFlowVersionsResult(final ResultType resultType, final VersionedFlowSnapshotMetadataSetEntity flowVersionsEntity) { + super(resultType); + this.flowVersionsEntity = Objects.requireNonNull(flowVersionsEntity); + } + + @Override + public VersionedFlowSnapshotMetadataSetEntity getResult() { + return this.flowVersionsEntity; + } + + @Override + protected void writeSimpleResult(final PrintStream output) { + final Set flowVersions = flowVersionsEntity.getVersionedFlowSnapshotMetadataSet(); + if (flowVersions == null || flowVersions.isEmpty()) { + return; + } + + final List flowVersionsMetadata = flowVersions.stream() + .map(fv -> fv.getVersionedFlowSnapshotMetadata()) + .sorted(Comparator.comparingLong(RegisteredFlowSnapshotMetadata::getTimestamp)) + .toList(); + + // date length, with locale specifics + final String datePattern = "%1$ta, % { + + final VersionedFlowsEntity flowsEntity; + + public RegistryFlowsResult(final ResultType resultType, final VersionedFlowsEntity flowsEntity) { + super(resultType); + this.flowsEntity = Objects.requireNonNull(flowsEntity); + } + + @Override + public VersionedFlowsEntity getResult() { + return this.flowsEntity; + } + + @Override + protected void writeSimpleResult(final PrintStream output) { + final Set flows = flowsEntity.getVersionedFlows(); + if (flows == null || flows.isEmpty()) { + return; + } + + final List flowsDTO = flows.stream() + .map(f -> f.getVersionedFlow()) + .sorted(Comparator.comparing(VersionedFlowDTO::getFlowName)) + .toList(); + + final Table table = new Table.Builder() + .column("#", 3, 3, false) + .column("Name", 20, 36, true) + .column("Id", 36, 36, false) + .column("Description", 11, 40, true) + .build(); + + for (int i = 0; i < flowsDTO.size(); i++) { + VersionedFlowDTO flow = flowsDTO.get(i); + table.addRow("" + (i + 1), flow.getFlowName(), flow.getFlowId(), flow.getDescription() == null ? "" : flow.getDescription()); + } + + final TableWriter tableWriter = new DynamicTableWriter(); + tableWriter.write(table, output); + } + +} diff --git a/nifi-toolkit/nifi-toolkit-client/src/main/java/org/apache/nifi/toolkit/client/FlowClient.java b/nifi-toolkit/nifi-toolkit-client/src/main/java/org/apache/nifi/toolkit/client/FlowClient.java index 01c9cc93f6..e483f1c91a 100644 --- a/nifi-toolkit/nifi-toolkit-client/src/main/java/org/apache/nifi/toolkit/client/FlowClient.java +++ b/nifi-toolkit/nifi-toolkit-client/src/main/java/org/apache/nifi/toolkit/client/FlowClient.java @@ -23,6 +23,8 @@ import org.apache.nifi.web.api.entity.ConnectionStatusEntity; import org.apache.nifi.web.api.entity.ControllerServiceTypesEntity; import org.apache.nifi.web.api.entity.ControllerServicesEntity; import org.apache.nifi.web.api.entity.CurrentUserEntity; +import org.apache.nifi.web.api.entity.FlowRegistryBranchesEntity; +import org.apache.nifi.web.api.entity.FlowRegistryBucketsEntity; import org.apache.nifi.web.api.entity.ParameterProvidersEntity; import org.apache.nifi.web.api.entity.ProcessGroupFlowEntity; import org.apache.nifi.web.api.entity.ProcessGroupStatusEntity; @@ -31,6 +33,7 @@ import org.apache.nifi.web.api.entity.ReportingTaskTypesEntity; import org.apache.nifi.web.api.entity.ReportingTasksEntity; import org.apache.nifi.web.api.entity.ScheduleComponentsEntity; import org.apache.nifi.web.api.entity.VersionedFlowSnapshotMetadataSetEntity; +import org.apache.nifi.web.api.entity.VersionedFlowsEntity; import java.io.IOException; @@ -92,6 +95,18 @@ public interface FlowClient { VersionedFlowSnapshotMetadataSetEntity getVersions(String registryId, String bucketId, String flowId) throws NiFiClientException, IOException; + /** + * Gets the possible versions for the given flow in the given bucket/branch in the given registry. + * + * @param registryId the id of the registry client + * @param bucketId the bucket id + * @param flowId the flow id + * @param branch the branch name + * @return the set of snapshot metadata entities + */ + VersionedFlowSnapshotMetadataSetEntity getVersions(String registryId, String bucketId, String flowId, String branch) + throws NiFiClientException, IOException; + /** * Retrieves the controller services for the given group. * @@ -190,4 +205,28 @@ public interface FlowClient { * @return the reporting task types */ ReportingTaskTypesEntity getReportingTaskTypes() throws NiFiClientException, IOException; + + /** + * Returns the list of branches for the specified registry client ID + * @param registryClientId Registry Client ID + * @return list of branches + */ + FlowRegistryBranchesEntity getFlowRegistryBranches(String registryClientId) throws NiFiClientException, IOException; + + /** + * Returns the list of buckets in a given branch for the specified registry client ID + * @param registryClientId Registry Client ID + * @param branch Name of the branch + * @return list of buckets + */ + FlowRegistryBucketsEntity getFlowRegistryBuckets(String registryClientId, String branch) throws NiFiClientException, IOException; + + /** + * Returns the list of flows in a given branch and bucket for the specified registry client ID + * @param registryClientId Registry Client ID + * @param branch Name of the branch + * @param bucket ID of the bucket + * @return list of flows + */ + VersionedFlowsEntity getFlowRegistryFlows(String registryClientId, String branch, String bucket) throws NiFiClientException, IOException; } diff --git a/nifi-toolkit/nifi-toolkit-client/src/main/java/org/apache/nifi/toolkit/client/impl/JerseyFlowClient.java b/nifi-toolkit/nifi-toolkit-client/src/main/java/org/apache/nifi/toolkit/client/impl/JerseyFlowClient.java index f3e83b0ebe..114c4e01c2 100644 --- a/nifi-toolkit/nifi-toolkit-client/src/main/java/org/apache/nifi/toolkit/client/impl/JerseyFlowClient.java +++ b/nifi-toolkit/nifi-toolkit-client/src/main/java/org/apache/nifi/toolkit/client/impl/JerseyFlowClient.java @@ -35,6 +35,8 @@ import org.apache.nifi.web.api.entity.ConnectionStatusEntity; import org.apache.nifi.web.api.entity.ControllerServiceTypesEntity; import org.apache.nifi.web.api.entity.ControllerServicesEntity; import org.apache.nifi.web.api.entity.CurrentUserEntity; +import org.apache.nifi.web.api.entity.FlowRegistryBranchesEntity; +import org.apache.nifi.web.api.entity.FlowRegistryBucketsEntity; import org.apache.nifi.web.api.entity.ParameterProvidersEntity; import org.apache.nifi.web.api.entity.ProcessGroupFlowEntity; import org.apache.nifi.web.api.entity.ProcessGroupStatusEntity; @@ -43,6 +45,7 @@ import org.apache.nifi.web.api.entity.ReportingTaskTypesEntity; import org.apache.nifi.web.api.entity.ReportingTasksEntity; import org.apache.nifi.web.api.entity.ScheduleComponentsEntity; import org.apache.nifi.web.api.entity.VersionedFlowSnapshotMetadataSetEntity; +import org.apache.nifi.web.api.entity.VersionedFlowsEntity; import java.io.IOException; import java.util.ArrayList; @@ -164,6 +167,12 @@ public class JerseyFlowClient extends AbstractJerseyClient implements FlowClient @Override public VersionedFlowSnapshotMetadataSetEntity getVersions(final String registryId, final String bucketId, final String flowId) throws NiFiClientException, IOException { + return getVersions(registryId, bucketId, flowId, null); + } + + @Override + public VersionedFlowSnapshotMetadataSetEntity getVersions(final String registryId, final String bucketId, final String flowId, final String branch) + throws NiFiClientException, IOException { if (StringUtils.isBlank(registryId)) { throw new IllegalArgumentException("Registry id cannot be null"); @@ -177,15 +186,26 @@ public class JerseyFlowClient extends AbstractJerseyClient implements FlowClient throw new IllegalArgumentException("Flow id cannot be null"); } - return executeAction("Error retrieving versions", () -> { - final WebTarget target = flowTarget - .path("registries/{registry-id}/buckets/{bucket-id}/flows/{flow-id}/versions") - .resolveTemplate("registry-id", registryId) - .resolveTemplate("bucket-id", bucketId) - .resolveTemplate("flow-id", flowId); - - return getRequestBuilder(target).get(VersionedFlowSnapshotMetadataSetEntity.class); - }); + if (branch == null) { + return executeAction("Error retrieving versions", () -> { + final WebTarget target = flowTarget + .path("registries/{registry-id}/buckets/{bucket-id}/flows/{flow-id}/versions") + .resolveTemplate("registry-id", registryId) + .resolveTemplate("bucket-id", bucketId) + .resolveTemplate("flow-id", flowId); + return getRequestBuilder(target).get(VersionedFlowSnapshotMetadataSetEntity.class); + }); + } else { + return executeAction("Error retrieving versions", () -> { + final WebTarget target = flowTarget + .path("registries/{registry-id}/buckets/{bucket-id}/flows/{flow-id}/versions") + .resolveTemplate("registry-id", registryId) + .resolveTemplate("bucket-id", bucketId) + .resolveTemplate("flow-id", flowId) + .queryParam("branch", branch); + return getRequestBuilder(target).get(VersionedFlowSnapshotMetadataSetEntity.class); + }); + } } @Override @@ -320,4 +340,64 @@ public class JerseyFlowClient extends AbstractJerseyClient implements FlowClient return getRequestBuilder(target).get(ReportingTaskTypesEntity.class); }); } + + @Override + public FlowRegistryBranchesEntity getFlowRegistryBranches(String registryClientId) + throws NiFiClientException, IOException { + + if (StringUtils.isBlank(registryClientId)) { + throw new IllegalArgumentException("Registry ID cannot be null"); + } + + return executeAction("Error retrieving branches", () -> { + final WebTarget target = flowTarget.path("/registries/{id}/branches") + .resolveTemplate("id", registryClientId); + return getRequestBuilder(target).get(FlowRegistryBranchesEntity.class); + }); + } + + @Override + public FlowRegistryBucketsEntity getFlowRegistryBuckets(String registryClientId, String branch) + throws NiFiClientException, IOException { + + if (StringUtils.isBlank(registryClientId)) { + throw new IllegalArgumentException("Registry ID cannot be null"); + } + + if (StringUtils.isBlank(branch)) { + throw new IllegalArgumentException("Branch name cannot be null"); + } + + return executeAction("Error retrieving buckets", () -> { + final WebTarget target = flowTarget.path("/registries/{id}/buckets") + .resolveTemplate("id", registryClientId) + .queryParam("branch", branch); + return getRequestBuilder(target).get(FlowRegistryBucketsEntity.class); + }); + } + + @Override + public VersionedFlowsEntity getFlowRegistryFlows(String registryClientId, String branch, String bucket) + throws NiFiClientException, IOException { + + if (StringUtils.isBlank(registryClientId)) { + throw new IllegalArgumentException("Registry ID cannot be null"); + } + + if (StringUtils.isBlank(bucket)) { + throw new IllegalArgumentException("Bucket ID cannot be null"); + } + + if (StringUtils.isBlank(branch)) { + throw new IllegalArgumentException("Branch name cannot be null"); + } + + return executeAction("Error retrieving buckets", () -> { + final WebTarget target = flowTarget.path("/registries/{registry-id}/buckets/{bucket-id}/flows") + .resolveTemplate("registry-id", registryClientId) + .resolveTemplate("bucket-id", bucket) + .queryParam("branch", branch); + return getRequestBuilder(target).get(VersionedFlowsEntity.class); + }); + } }