NIFI-9443 Update NAR plugin to 1.3.3 and update data model for extension manifest to capture new fields

Signed-off-by: Joe Gresock <jgresock@gmail.com>

This closes #5570.
This commit is contained in:
Bryan Bende 2021-11-29 15:36:42 -05:00 committed by Joe Gresock
parent 53809dd83f
commit 0f027743d1
No known key found for this signature in database
GPG Key ID: 37F5B9B6E258C8B7
7 changed files with 317 additions and 33 deletions

View File

@ -94,7 +94,6 @@ public class XmlDocumentationWriter extends AbstractDocumentationWriter {
@Override @Override
protected void writeDeprecationNotice(final DeprecationNotice deprecationNotice) throws IOException { protected void writeDeprecationNotice(final DeprecationNotice deprecationNotice) throws IOException {
if (deprecationNotice == null) { if (deprecationNotice == null) {
writeEmptyElement("deprecationNotice");
return; return;
} }
@ -127,21 +126,29 @@ public class XmlDocumentationWriter extends AbstractDocumentationWriter {
@Override @Override
protected void writeDescription(final String description) throws IOException { protected void writeDescription(final String description) throws IOException {
if (description == null) {
return;
}
writeTextElement("description", description); writeTextElement("description", description);
} }
@Override @Override
protected void writeTags(final List<String> tags) throws IOException { protected void writeTags(final List<String> tags) throws IOException {
if (tags == null) {
return;
}
writeTextArray("tags", "tag", tags); writeTextArray("tags", "tag", tags);
} }
@Override @Override
protected void writeProperties(final List<PropertyDescriptor> properties, Map<String,ServiceAPI> propertyServices) throws IOException { protected void writeProperties(final List<PropertyDescriptor> properties, Map<String,ServiceAPI> propertyServices) throws IOException {
if (properties == null || properties.isEmpty()) {
return;
}
writeStartElement("properties"); writeStartElement("properties");
if (properties != null) { for (final PropertyDescriptor property : properties) {
for (final PropertyDescriptor property : properties) { writeProperty(property, propertyServices);
writeProperty(property, propertyServices);
}
} }
writeEndElement(); writeEndElement();
} }
@ -152,7 +159,9 @@ public class XmlDocumentationWriter extends AbstractDocumentationWriter {
writeTextElement("name", property.getName()); writeTextElement("name", property.getName());
writeTextElement("displayName", property.getDisplayName()); writeTextElement("displayName", property.getDisplayName());
writeTextElement("description", property.getDescription()); writeTextElement("description", property.getDescription());
writeTextElement("defaultValue", property.getDefaultValue()); if (property.getDefaultValue() != null) {
writeTextElement("defaultValue", property.getDefaultValue());
}
if (property.getControllerServiceDefinition() != null) { if (property.getControllerServiceDefinition() != null) {
writeStartElement("controllerServiceDefinition"); writeStartElement("controllerServiceDefinition");
@ -173,11 +182,16 @@ public class XmlDocumentationWriter extends AbstractDocumentationWriter {
writeEndElement(); writeEndElement();
} }
writeArray("allowableValues", property.getAllowableValues(), this::writeAllowableValue); if (property.getAllowableValues() != null && !property.getAllowableValues().isEmpty()) {
writeArray("allowableValues", property.getAllowableValues(), this::writeAllowableValue);
}
writeBooleanElement("required", property.isRequired()); writeBooleanElement("required", property.isRequired());
writeBooleanElement("sensitive", property.isSensitive()); writeBooleanElement("sensitive", property.isSensitive());
writeBooleanElement("expressionLanguageSupported", property.isExpressionLanguageSupported()); writeBooleanElement("expressionLanguageSupported", property.isExpressionLanguageSupported());
writeTextElement("expressionLanguageScope", property.getExpressionLanguageScope() == null ? null : property.getExpressionLanguageScope().name()); if (property.getExpressionLanguageScope() != null) {
writeTextElement("expressionLanguageScope", property.getExpressionLanguageScope().name());
}
writeBooleanElement("dynamicallyModifiesClasspath", property.isDynamicClasspathModifier()); writeBooleanElement("dynamicallyModifiesClasspath", property.isDynamicClasspathModifier());
writeBooleanElement("dynamic", property.isDynamic()); writeBooleanElement("dynamic", property.isDynamic());
writeResourceDefinition(property.getResourceDefinition()); writeResourceDefinition(property.getResourceDefinition());
@ -187,11 +201,13 @@ public class XmlDocumentationWriter extends AbstractDocumentationWriter {
} }
private void writeResourceDefinition(final ResourceDefinition resourceDefinition) throws IOException { private void writeResourceDefinition(final ResourceDefinition resourceDefinition) throws IOException {
writeStartElement("resourceDefinition"); if (resourceDefinition == null) {
if (resourceDefinition != null) { return;
writeTextElement("cardinality", resourceDefinition.getCardinality().name());
writeArray("resourceTypes", resourceDefinition.getResourceTypes(), this::writeResourceType);
} }
writeStartElement("resourceDefinition");
writeTextElement("cardinality", resourceDefinition.getCardinality().name());
writeArray("resourceTypes", resourceDefinition.getResourceTypes(), this::writeResourceType);
writeEndElement(); writeEndElement();
} }
@ -237,6 +253,9 @@ public class XmlDocumentationWriter extends AbstractDocumentationWriter {
@Override @Override
protected void writeDynamicProperties(final List<DynamicProperty> dynamicProperties) throws IOException { protected void writeDynamicProperties(final List<DynamicProperty> dynamicProperties) throws IOException {
if (dynamicProperties == null || dynamicProperties.isEmpty()) {
return;
}
writeArray("dynamicProperties", dynamicProperties, this::writeDynamicProperty); writeArray("dynamicProperties", dynamicProperties, this::writeDynamicProperty);
} }
@ -254,29 +273,31 @@ public class XmlDocumentationWriter extends AbstractDocumentationWriter {
@Override @Override
protected void writeStatefulInfo(final Stateful stateful) throws IOException { protected void writeStatefulInfo(final Stateful stateful) throws IOException {
writeStartElement("stateful"); if (stateful == null) {
return;
if (stateful != null) {
writeTextElement("description", stateful.description());
writeArray("scopes", Arrays.asList(stateful.scopes()), scope -> writeTextElement("scope", scope.name()));
} }
writeStartElement("stateful");
writeTextElement("description", stateful.description());
writeArray("scopes", Arrays.asList(stateful.scopes()), scope -> writeTextElement("scope", scope.name()));
writeEndElement(); writeEndElement();
} }
@Override @Override
protected void writeRestrictedInfo(final Restricted restricted) throws IOException { protected void writeRestrictedInfo(final Restricted restricted) throws IOException {
if (restricted == null) {
return;
}
writeStartElement("restricted"); writeStartElement("restricted");
if (restricted != null) { if (restricted.value() != null && !restricted.value().isEmpty()) {
if (restricted.value() != null && !restricted.value().isEmpty()) { writeTextElement("generalRestrictionExplanation", restricted.value());
writeTextElement("generalRestrictionExplanation", restricted.value()); }
}
final Restriction[] restrictions = restricted.restrictions(); final Restriction[] restrictions = restricted.restrictions();
if (restrictions != null) { if (restrictions != null) {
writeArray("restrictions", Arrays.asList(restrictions), this::writeRestriction); writeArray("restrictions", Arrays.asList(restrictions), this::writeRestriction);
}
} }
writeEndElement(); writeEndElement();
@ -295,11 +316,17 @@ public class XmlDocumentationWriter extends AbstractDocumentationWriter {
@Override @Override
protected void writeInputRequirementInfo(final InputRequirement.Requirement requirement) throws IOException { protected void writeInputRequirementInfo(final InputRequirement.Requirement requirement) throws IOException {
writeTextElement("inputRequirement", requirement == null ? null : requirement.name()); if (requirement == null) {
return;
}
writeTextElement("inputRequirement", requirement.name());
} }
@Override @Override
protected void writeSystemResourceConsiderationInfo(final List<SystemResourceConsideration> considerations) throws IOException { protected void writeSystemResourceConsiderationInfo(final List<SystemResourceConsideration> considerations) throws IOException {
if (considerations == null || considerations.isEmpty()) {
return;
}
writeArray("systemResourceConsiderations", considerations, this::writeSystemResourceConsideration); writeArray("systemResourceConsiderations", considerations, this::writeSystemResourceConsideration);
} }
@ -315,7 +342,6 @@ public class XmlDocumentationWriter extends AbstractDocumentationWriter {
@Override @Override
protected void writeSeeAlso(final SeeAlso seeAlso) throws IOException { protected void writeSeeAlso(final SeeAlso seeAlso) throws IOException {
if (seeAlso == null) { if (seeAlso == null) {
writeEmptyElement("seeAlso");
return; return;
} }
@ -338,6 +364,10 @@ public class XmlDocumentationWriter extends AbstractDocumentationWriter {
@Override @Override
protected void writeRelationships(final Set<Relationship> relationships) throws IOException { protected void writeRelationships(final Set<Relationship> relationships) throws IOException {
if (relationships == null || relationships.isEmpty()) {
return;
}
writeArray("relationships", relationships,rel -> { writeArray("relationships", relationships,rel -> {
writeStartElement("relationship"); writeStartElement("relationship");
@ -351,18 +381,21 @@ public class XmlDocumentationWriter extends AbstractDocumentationWriter {
@Override @Override
protected void writeDynamicRelationship(final DynamicRelationship dynamicRelationship) throws IOException { protected void writeDynamicRelationship(final DynamicRelationship dynamicRelationship) throws IOException {
writeStartElement("dynamicRelationship"); if (dynamicRelationship == null) {
return;
if (dynamicRelationship != null) {
writeTextElement("name", dynamicRelationship.name());
writeTextElement("description", dynamicRelationship.description());
} }
writeStartElement("dynamicRelationship");
writeTextElement("name", dynamicRelationship.name());
writeTextElement("description", dynamicRelationship.description());
writeEndElement(); writeEndElement();
} }
@Override @Override
protected void writeReadsAttributes(final List<ReadsAttribute> attributes) throws IOException { protected void writeReadsAttributes(final List<ReadsAttribute> attributes) throws IOException {
if (attributes == null || attributes.isEmpty()) {
return;
}
writeArray("readsAttributes", attributes, this::writeReadsAttribute); writeArray("readsAttributes", attributes, this::writeReadsAttribute);
} }
@ -375,6 +408,9 @@ public class XmlDocumentationWriter extends AbstractDocumentationWriter {
@Override @Override
protected void writeWritesAttributes(final List<WritesAttribute> attributes) throws IOException { protected void writeWritesAttributes(final List<WritesAttribute> attributes) throws IOException {
if (attributes == null) {
return;
}
writeArray("writesAttributes", attributes, this::writeWritesAttribute); writeArray("writesAttributes", attributes, this::writeWritesAttribute);
} }
@ -392,6 +428,9 @@ public class XmlDocumentationWriter extends AbstractDocumentationWriter {
@Override @Override
protected void writeProvidedServices(final Collection<ServiceAPI> providedServices) throws IOException { protected void writeProvidedServices(final Collection<ServiceAPI> providedServices) throws IOException {
if (providedServices == null || providedServices.isEmpty()) {
return;
}
writeArray("providedServiceAPIs", providedServices, this::writeProvidedService); writeArray("providedServiceAPIs", providedServices, this::writeProvidedService);
} }

View File

@ -247,6 +247,31 @@ public class TestJacksonExtensionManifestParser {
assertEquals(ResourceType.FILE, resourceTypes.get(0)); assertEquals(ResourceType.FILE, resourceTypes.get(0));
} }
@Test
public void testBundleAndBuildInfo() throws IOException {
final ExtensionManifest extensionManifest = parse("src/test/resources/descriptors/extension-manifest-kafka-2-6-nar.xml");
assertNotNull(extensionManifest);
assertEquals("org.apache.nifi", extensionManifest.getGroupId());
assertEquals("nifi-kafka-2-6-nar", extensionManifest.getArtifactId());
assertEquals("1.16.0-SNAPSHOT", extensionManifest.getVersion());
assertNotNull(extensionManifest.getParentNar());
assertEquals("org.apache.nifi", extensionManifest.getParentNar().getGroupId());
assertEquals("nifi-standard-services-api-nar", extensionManifest.getParentNar().getArtifactId());
assertEquals("1.16.0-SNAPSHOT", extensionManifest.getParentNar().getVersion());
assertNotNull(extensionManifest.getBuildInfo());
assertEquals("nifi-1.15.0-RC3", extensionManifest.getBuildInfo().getTag());
assertEquals("main", extensionManifest.getBuildInfo().getBranch());
assertEquals("123", extensionManifest.getBuildInfo().getRevision());
assertEquals("1.8.0_282", extensionManifest.getBuildInfo().getJdk());
assertEquals("jsmith", extensionManifest.getBuildInfo().getBuiltBy());
assertEquals("2021-11-29T15:18:55Z", extensionManifest.getBuildInfo().getTimestamp());
assertEquals("1.16.0-SNAPSHOT", extensionManifest.getSystemApiVersion());
}
private ExtensionManifest parse(final String file) throws IOException { private ExtensionManifest parse(final String file) throws IOException {
try (final InputStream inputStream = new FileInputStream(file)) { try (final InputStream inputStream = new FileInputStream(file)) {
return parser.parse(inputStream); return parser.parse(inputStream);

View File

@ -1,5 +1,21 @@
<extensionManifest> <extensionManifest>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-kafka-2-6-nar</artifactId>
<version>1.16.0-SNAPSHOT</version>
<parentNar>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-standard-services-api-nar</artifactId>
<version>1.16.0-SNAPSHOT</version>
</parentNar>
<systemApiVersion>1.16.0-SNAPSHOT</systemApiVersion> <systemApiVersion>1.16.0-SNAPSHOT</systemApiVersion>
<buildInfo>
<tag>nifi-1.15.0-RC3</tag>
<branch>main</branch>
<revision>123</revision>
<jdk>1.8.0_282</jdk>
<builtBy>jsmith</builtBy>
<timestamp>2021-11-29T15:18:55Z</timestamp>
</buildInfo>
<extensions> <extensions>
<extension> <extension>
<name>org.apache.nifi.processors.kafka.pubsub.ConsumeKafka_2_6</name> <name>org.apache.nifi.processors.kafka.pubsub.ConsumeKafka_2_6</name>

View File

@ -0,0 +1,89 @@
/*
* 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.registry.extension.component.manifest;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
@ApiModel
@XmlAccessorType(XmlAccessType.FIELD)
public class BuildInfo {
private String tag;
private String branch;
private String revision;
private String jdk;
private String builtBy;
private String timestamp;
@ApiModelProperty(value = "The tag the NAR was built from")
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
@ApiModelProperty(value = "The branch the NAR was built from")
public String getBranch() {
return branch;
}
public void setBranch(String branch) {
this.branch = branch;
}
@ApiModelProperty(value = "The revision the NAR was built from")
public String getRevision() {
return revision;
}
public void setRevision(String revision) {
this.revision = revision;
}
@ApiModelProperty(value = "The JDK the NAR was built with")
public String getJdk() {
return jdk;
}
public void setJdk(String jdk) {
this.jdk = jdk;
}
@ApiModelProperty(value = "The OS user that performed the build")
public String getBuiltBy() {
return builtBy;
}
public void setBuiltBy(String builtBy) {
this.builtBy = builtBy;
}
@ApiModelProperty(value = "The timestamp of the build")
public String getTimestamp() {
return timestamp;
}
public void setTimestamp(String timestamp) {
this.timestamp = timestamp;
}
}

View File

@ -17,6 +17,7 @@
package org.apache.nifi.registry.extension.component.manifest; package org.apache.nifi.registry.extension.component.manifest;
import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAccessorType;
@ -30,6 +31,14 @@ import java.util.List;
@XmlAccessorType(XmlAccessType.FIELD) @XmlAccessorType(XmlAccessType.FIELD)
public class ExtensionManifest { public class ExtensionManifest {
private String groupId;
private String artifactId;
private String version;
private ParentNar parentNar;
private BuildInfo buildInfo;
@XmlElement(required = true) @XmlElement(required = true)
private String systemApiVersion; private String systemApiVersion;
@ -45,6 +54,43 @@ public class ExtensionManifest {
this.extensions = extensions; this.extensions = extensions;
} }
@ApiModelProperty(value = "The group id of this NAR")
public String getGroupId() {
return groupId;
}
public void setGroupId(String groupId) {
this.groupId = groupId;
}
@ApiModelProperty(value = "The artifact id of this NAR")
public String getArtifactId() {
return artifactId;
}
public void setArtifactId(String artifactId) {
this.artifactId = artifactId;
}
@ApiModelProperty(value = "The version of this NAR")
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
@ApiModelProperty(value = "The info for the parent NAR of this NAR")
public ParentNar getParentNar() {
return parentNar;
}
public void setParentNar(ParentNar parentNar) {
this.parentNar = parentNar;
}
@ApiModelProperty(value = "The version of nifi-api this NAR was built against")
public String getSystemApiVersion() { public String getSystemApiVersion() {
return systemApiVersion; return systemApiVersion;
} }
@ -53,6 +99,16 @@ public class ExtensionManifest {
this.systemApiVersion = systemApiVersion; this.systemApiVersion = systemApiVersion;
} }
@ApiModelProperty(value = "The build info for the NAR")
public BuildInfo getBuildInfo() {
return buildInfo;
}
public void setBuildInfo(BuildInfo buildInfo) {
this.buildInfo = buildInfo;
}
@ApiModelProperty(value = "The list of extensions contained in this NAR")
public List<Extension> getExtensions() { public List<Extension> getExtensions() {
return extensions; return extensions;
} }

View File

@ -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.registry.extension.component.manifest;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
@ApiModel
@XmlAccessorType(XmlAccessType.FIELD)
public class ParentNar {
private String groupId;
private String artifactId;
private String version;
@ApiModelProperty(value = "The group id of the parent NAR")
public String getGroupId() {
return groupId;
}
public void setGroupId(String groupId) {
this.groupId = groupId;
}
@ApiModelProperty(value = "The artifact id of the parent NAR")
public String getArtifactId() {
return artifactId;
}
public void setArtifactId(String artifactId) {
this.artifactId = artifactId;
}
@ApiModelProperty(value = "The version of the parent NAR")
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
}

View File

@ -706,7 +706,7 @@
<plugin> <plugin>
<groupId>org.apache.nifi</groupId> <groupId>org.apache.nifi</groupId>
<artifactId>nifi-nar-maven-plugin</artifactId> <artifactId>nifi-nar-maven-plugin</artifactId>
<version>1.3.2</version> <version>1.3.3</version>
<extensions>true</extensions> <extensions>true</extensions>
<configuration> <configuration>
<enforceDocGeneration>true</enforceDocGeneration> <enforceDocGeneration>true</enforceDocGeneration>