diff --git a/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/ExtensionComponent.java b/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/ExtensionComponent.java index b1bdf301b7c6..901bb5a44d77 100644 --- a/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/ExtensionComponent.java +++ b/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/ExtensionComponent.java @@ -41,6 +41,10 @@ public class ExtensionComponent extends DefinedType { private Boolean deprecated; private String deprecationReason; + private Boolean restricted; + private String restrictedExplanation; + private Set explicitRestrictions; + @ApiModelProperty("The build metadata for this component") public BuildInfo getBuildInfo() { return buildInfo; @@ -87,6 +91,33 @@ public void setDeprecationReason(String deprecationReason) { this.deprecationReason = deprecationReason; } + @ApiModelProperty("Whether or not the component has a general restriction") + public Boolean isRestricted() { + return restricted; + } + + public void setRestricted(Boolean restricted) { + this.restricted = restricted; + } + + @ApiModelProperty("An optional description of the general restriction") + public String getRestrictedExplanation() { + return restrictedExplanation; + } + + public void setRestrictedExplanation(String restrictedExplanation) { + this.restrictedExplanation = restrictedExplanation; + } + + @ApiModelProperty("Explicit restrictions that indicate a require permission to use the component") + public Set getExplicitRestrictions() { + return explicitRestrictions; + } + + public void setExplicitRestrictions(Set explicitRestrictions) { + this.explicitRestrictions = explicitRestrictions; + } + @Override public boolean equals(Object o) { if (this == o) { diff --git a/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/Restriction.java b/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/Restriction.java new file mode 100644 index 000000000000..9b0f24dbab75 --- /dev/null +++ b/c2/c2-protocol/c2-protocol-component-api/src/main/java/org/apache/nifi/c2/protocol/component/api/Restriction.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.c2.protocol.component.api; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +import java.util.Objects; + +@ApiModel +public class Restriction { + + private String requiredPermission; + private String explanation; + + @ApiModelProperty(value = "The permission required for this restriction") + public String getRequiredPermission() { + return requiredPermission; + } + + public void setRequiredPermission(String requiredPermission) { + this.requiredPermission = requiredPermission; + } + + @ApiModelProperty(value = "The explanation of this restriction") + public String getExplanation() { + return explanation; + } + + public void setExplanation(String explanation) { + this.explanation = explanation; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Restriction that = (Restriction) o; + return Objects.equals(requiredPermission, that.requiredPermission) && Objects.equals(explanation, that.explanation); + } + + @Override + public int hashCode() { + return Objects.hash(requiredPermission, explanation); + } + +} diff --git a/nifi-manifest/nifi-runtime-manifest-core/src/main/java/org/apache/nifi/runtime/manifest/impl/StandardRuntimeManifestBuilder.java b/nifi-manifest/nifi-runtime-manifest-core/src/main/java/org/apache/nifi/runtime/manifest/impl/StandardRuntimeManifestBuilder.java index aac02bc0c8b9..3bf49fd1e24a 100644 --- a/nifi-manifest/nifi-runtime-manifest-core/src/main/java/org/apache/nifi/runtime/manifest/impl/StandardRuntimeManifestBuilder.java +++ b/nifi-manifest/nifi-runtime-manifest-core/src/main/java/org/apache/nifi/runtime/manifest/impl/StandardRuntimeManifestBuilder.java @@ -30,6 +30,7 @@ import org.apache.nifi.c2.protocol.component.api.PropertyResourceDefinition; import org.apache.nifi.c2.protocol.component.api.Relationship; import org.apache.nifi.c2.protocol.component.api.ReportingTaskDefinition; +import org.apache.nifi.c2.protocol.component.api.Restriction; import org.apache.nifi.c2.protocol.component.api.RuntimeManifest; import org.apache.nifi.c2.protocol.component.api.SchedulingDefaults; import org.apache.nifi.components.resource.ResourceCardinality; @@ -46,6 +47,7 @@ import org.apache.nifi.extension.manifest.Property; import org.apache.nifi.extension.manifest.ProvidedServiceAPI; import org.apache.nifi.extension.manifest.ResourceDefinition; +import org.apache.nifi.extension.manifest.Restricted; import org.apache.nifi.logging.LogLevel; import org.apache.nifi.runtime.manifest.ComponentManifestBuilder; import org.apache.nifi.runtime.manifest.RuntimeManifestBuilder; @@ -57,6 +59,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; /** @@ -348,6 +351,24 @@ private void populateExtensionComponent(final ExtensionManifest extensionManifes providedServiceApis.forEach(providedServiceApi -> providedApiTypes.add(createProvidedApiType(providedServiceApi))); extensionComponent.setProvidedApiImplementations(providedApiTypes); } + + final Restricted restricted = extension.getRestricted(); + if (restricted != null) { + extensionComponent.setRestricted(true); + extensionComponent.setRestrictedExplanation(restricted.getGeneralRestrictionExplanation()); + if (restricted.getRestrictions() != null) { + final Set explicitRestrictions = new HashSet<>(); + restricted.getRestrictions().forEach(r -> explicitRestrictions.add(createRestriction(r))); + extensionComponent.setExplicitRestrictions(explicitRestrictions); + } + } + } + + private Restriction createRestriction(final org.apache.nifi.extension.manifest.Restriction extensionRestriction) { + final Restriction restriction = new Restriction(); + restriction.setExplanation(extensionRestriction.getExplanation()); + restriction.setRequiredPermission(extensionRestriction.getRequiredPermission()); + return restriction; } private DefinedType createProvidedApiType(final ProvidedServiceAPI providedServiceApi) { diff --git a/nifi-manifest/nifi-runtime-manifest-test/src/test/java/org/apache/nifi/runtime/manifest/TestRuntimeManifest.java b/nifi-manifest/nifi-runtime-manifest-test/src/test/java/org/apache/nifi/runtime/manifest/TestRuntimeManifest.java index f3eb71d294bb..16c567489a49 100644 --- a/nifi-manifest/nifi-runtime-manifest-test/src/test/java/org/apache/nifi/runtime/manifest/TestRuntimeManifest.java +++ b/nifi-manifest/nifi-runtime-manifest-test/src/test/java/org/apache/nifi/runtime/manifest/TestRuntimeManifest.java @@ -27,8 +27,10 @@ import org.apache.nifi.c2.protocol.component.api.PropertyResourceDefinition; import org.apache.nifi.c2.protocol.component.api.Relationship; import org.apache.nifi.c2.protocol.component.api.ReportingTaskDefinition; +import org.apache.nifi.c2.protocol.component.api.Restriction; import org.apache.nifi.c2.protocol.component.api.RuntimeManifest; import org.apache.nifi.c2.protocol.component.api.SchedulingDefaults; +import org.apache.nifi.components.RequiredPermission; import org.apache.nifi.components.resource.ResourceCardinality; import org.apache.nifi.components.resource.ResourceType; import org.apache.nifi.scheduling.SchedulingStrategy; @@ -39,10 +41,12 @@ import java.io.InputStream; import java.util.List; import java.util.Map; +import java.util.Set; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; public class TestRuntimeManifest { @@ -139,6 +143,24 @@ public void testRuntimeManifest() throws IOException { assertEquals(1, resourceDefinition.getResourceTypes().size()); assertEquals(ResourceType.FILE, resourceDefinition.getResourceTypes().stream().findFirst().get()); + assertNull(listHdfsDefinition.isRestricted()); + assertNull(listHdfsDefinition.getRestrictedExplanation()); + assertNull(listHdfsDefinition.getExplicitRestrictions()); + + // Verify FetchHDFS definition has restrictions + final ProcessorDefinition fetchHdfsDefinition = getProcessorDefinition(bundles, "nifi-hadoop-nar", + "org.apache.nifi.processors.hadoop.FetchHDFS"); + assertNotNull(fetchHdfsDefinition.isRestricted()); + assertTrue(fetchHdfsDefinition.isRestricted()); + + final Set restrictions = fetchHdfsDefinition.getExplicitRestrictions(); + assertNotNull(restrictions); + assertEquals(1, restrictions.size()); + + final Restriction restriction = restrictions.stream().findFirst().orElse(null); + assertEquals(RequiredPermission.READ_DISTRIBUTED_FILESYSTEM.getPermissionLabel(), restriction.getRequiredPermission()); + assertNotNull(restriction.getExplanation()); + // Verify ConsumeKafka_2_6 definition which has properties with dependencies final ProcessorDefinition consumeKafkaDefinition = getProcessorDefinition(bundles, "nifi-kafka-2-6-nar", "org.apache.nifi.processors.kafka.pubsub.ConsumeKafka_2_6");