NIFIREG-215 - Extension Bundle Improvements
- Adding content size field extension bundle version
- Adding optional filters to the get all bundles end-point
- Bumping minor versions of spring boot and spring security
- Adding /bundles/versions with filter params
- Added new client method to return an optional checksum for a given group, artifact, and version
- Adding support for SNAPSHOT versions
- Adding flag on buckets to indicate if redeploying extension bundle versions is allowed
This closes #149.
Signed-off-by: Kevin Doran <kdoran@apache.org>
diff --git a/nifi-registry-core/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/ExtensionBundleClient.java b/nifi-registry-core/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/ExtensionBundleClient.java
index 32eb3c9..b2724ae 100644
--- a/nifi-registry-core/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/ExtensionBundleClient.java
+++ b/nifi-registry-core/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/ExtensionBundleClient.java
@@ -17,6 +17,7 @@
package org.apache.nifi.registry.client;
import org.apache.nifi.registry.extension.ExtensionBundle;
+import org.apache.nifi.registry.extension.filter.ExtensionBundleFilterParams;
import java.io.IOException;
import java.util.List;
@@ -37,6 +38,17 @@
List<ExtensionBundle> getAll() throws IOException, NiFiRegistryException;
/**
+ * Retrieves all extension bundles matching the specified filters, located in buckets the current user is authorized for.
+ *
+ * @param filterParams the filter params
+ * @return the list of extension bundles
+ *
+ * @throws IOException if an I/O error occurs
+ * @throws NiFiRegistryException if an non I/O error occurs
+ */
+ List<ExtensionBundle> getAll(ExtensionBundleFilterParams filterParams) throws IOException, NiFiRegistryException;
+
+ /**
* Retrieves the extension bundles located in the given bucket.
*
* @param bucketId the bucket id
diff --git a/nifi-registry-core/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/ExtensionBundleVersionClient.java b/nifi-registry-core/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/ExtensionBundleVersionClient.java
index 8bad8c9..dd07df3 100644
--- a/nifi-registry-core/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/ExtensionBundleVersionClient.java
+++ b/nifi-registry-core/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/ExtensionBundleVersionClient.java
@@ -19,6 +19,7 @@
import org.apache.nifi.registry.extension.ExtensionBundleType;
import org.apache.nifi.registry.extension.ExtensionBundleVersion;
import org.apache.nifi.registry.extension.ExtensionBundleVersionMetadata;
+import org.apache.nifi.registry.extension.filter.ExtensionBundleVersionFilterParams;
import java.io.File;
import java.io.IOException;
@@ -88,6 +89,18 @@
ExtensionBundleVersion create(String bucketId, ExtensionBundleType bundleType, File bundleFile, String sha256)
throws IOException, NiFiRegistryException;
+ /**
+ * Retrieves all the extension bundle versions located in buckets the current user is authorized for, and
+ * matching any of the provided filter params.
+ *
+ * @param filterParams the filter params
+ * @return the list of bundle version metadata
+ *
+ * @throws IOException if an I/O error occurs
+ * @throws NiFiRegistryException if an non I/O error occurs
+ */
+ List<ExtensionBundleVersionMetadata> getBundleVersions(ExtensionBundleVersionFilterParams filterParams)
+ throws IOException, NiFiRegistryException;
/**
* Retrieves the metadata about the versions of the given bundle.
diff --git a/nifi-registry-core/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/ExtensionRepoClient.java b/nifi-registry-core/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/ExtensionRepoClient.java
index 6682921..bcb1b30 100644
--- a/nifi-registry-core/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/ExtensionRepoClient.java
+++ b/nifi-registry-core/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/ExtensionRepoClient.java
@@ -25,6 +25,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
+import java.util.Optional;
/**
* Client for interacting with the extension repository.
@@ -123,4 +124,21 @@
String getVersionSha256(String bucketName, String groupId, String artifactId, String version)
throws IOException, NiFiRegistryException;
+ /**
+ * Gets the hex representation of the SHA-256 hash of the binary content for the given version.
+ *
+ * If the version is a SNAPSHOT version, there may be more than one instance of the SNAPSHOT version in different
+ * buckets. In this case the instance with the latest created timestamp will be used to obtain the checksum.
+ *
+ * @param groupId the group id
+ * @param artifactId the artifact id
+ * @param version the version
+ * @return the SHA-256 hex string
+ *
+ * @throws IOException if an I/O error occurs
+ * @throws NiFiRegistryException if an non I/O error occurs
+ */
+ Optional<String> getVersionSha256(String groupId, String artifactId, String version)
+ throws IOException, NiFiRegistryException;
+
}
diff --git a/nifi-registry-core/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/impl/JerseyExtensionBundleClient.java b/nifi-registry-core/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/impl/JerseyExtensionBundleClient.java
index b70a653..9f748d5 100644
--- a/nifi-registry-core/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/impl/JerseyExtensionBundleClient.java
+++ b/nifi-registry-core/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/impl/JerseyExtensionBundleClient.java
@@ -20,6 +20,7 @@
import org.apache.nifi.registry.client.ExtensionBundleClient;
import org.apache.nifi.registry.client.NiFiRegistryException;
import org.apache.nifi.registry.extension.ExtensionBundle;
+import org.apache.nifi.registry.extension.filter.ExtensionBundleFilterParams;
import javax.ws.rs.client.WebTarget;
import java.io.IOException;
@@ -48,9 +49,23 @@
@Override
public List<ExtensionBundle> getAll() throws IOException, NiFiRegistryException {
+ return getAll(null);
+ }
+
+ @Override
+ public List<ExtensionBundle> getAll(final ExtensionBundleFilterParams filterParams) throws IOException, NiFiRegistryException {
return executeAction("Error getting extension bundles", () -> {
WebTarget target = extensionBundlesTarget;
+ if (filterParams != null) {
+ if (!StringUtils.isBlank(filterParams.getGroupId())) {
+ target = target.queryParam("groupId", filterParams.getGroupId());
+ }
+ if (!StringUtils.isBlank(filterParams.getArtifactId())) {
+ target = target.queryParam("artifactId", filterParams.getArtifactId());
+ }
+ }
+
final ExtensionBundle[] bundles = getRequestBuilder(target).get(ExtensionBundle[].class);
return bundles == null ? Collections.emptyList() : Arrays.asList(bundles);
});
diff --git a/nifi-registry-core/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/impl/JerseyExtensionBundleVersionClient.java b/nifi-registry-core/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/impl/JerseyExtensionBundleVersionClient.java
index 6969317..0332412 100644
--- a/nifi-registry-core/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/impl/JerseyExtensionBundleVersionClient.java
+++ b/nifi-registry-core/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/impl/JerseyExtensionBundleVersionClient.java
@@ -22,6 +22,7 @@
import org.apache.nifi.registry.extension.ExtensionBundleType;
import org.apache.nifi.registry.extension.ExtensionBundleVersion;
import org.apache.nifi.registry.extension.ExtensionBundleVersionMetadata;
+import org.apache.nifi.registry.extension.filter.ExtensionBundleVersionFilterParams;
import org.glassfish.jersey.media.multipart.FormDataMultiPart;
import org.glassfish.jersey.media.multipart.file.FileDataBodyPart;
import org.glassfish.jersey.media.multipart.file.StreamDataBodyPart;
@@ -149,6 +150,32 @@
}
@Override
+ public List<ExtensionBundleVersionMetadata> getBundleVersions(final ExtensionBundleVersionFilterParams filterParams)
+ throws IOException, NiFiRegistryException {
+
+ return executeAction("Error getting extension bundle versions", () -> {
+ WebTarget target = extensionBundlesTarget.path("/versions");
+
+ if (filterParams != null) {
+ if (!StringUtils.isBlank(filterParams.getGroupId())) {
+ target = target.queryParam("groupId", filterParams.getGroupId());
+ }
+
+ if (!StringUtils.isBlank(filterParams.getArtifactId())) {
+ target = target.queryParam("artifactId", filterParams.getArtifactId());
+ }
+
+ if (!StringUtils.isBlank(filterParams.getVersion())) {
+ target = target.queryParam("version", filterParams.getVersion());
+ }
+ }
+
+ final ExtensionBundleVersionMetadata[] bundleVersions = getRequestBuilder(target).get(ExtensionBundleVersionMetadata[].class);
+ return bundleVersions == null ? Collections.emptyList() : Arrays.asList(bundleVersions);
+ });
+ }
+
+ @Override
public List<ExtensionBundleVersionMetadata> getBundleVersions(final String bundleId)
throws IOException, NiFiRegistryException {
diff --git a/nifi-registry-core/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/impl/JerseyExtensionRepoClient.java b/nifi-registry-core/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/impl/JerseyExtensionRepoClient.java
index 18a6979..dc67b97 100644
--- a/nifi-registry-core/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/impl/JerseyExtensionRepoClient.java
+++ b/nifi-registry-core/nifi-registry-client/src/main/java/org/apache/nifi/registry/client/impl/JerseyExtensionRepoClient.java
@@ -25,6 +25,7 @@
import org.apache.nifi.registry.extension.repo.ExtensionRepoVersion;
import org.apache.nifi.registry.extension.repo.ExtensionRepoVersionSummary;
+import javax.ws.rs.NotFoundException;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.MediaType;
import java.io.IOException;
@@ -33,6 +34,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
public class JerseyExtensionRepoClient extends AbstractJerseyClient implements ExtensionRepoClient {
@@ -179,6 +181,38 @@
});
}
+ @Override
+ public Optional<String> getVersionSha256(final String groupId, final String artifactId, final String version)
+ throws IOException, NiFiRegistryException {
+
+ if (StringUtils.isBlank(groupId)) {
+ throw new IllegalArgumentException("Group id cannot be null or blank");
+ }
+
+ if (StringUtils.isBlank(artifactId)) {
+ throw new IllegalArgumentException("Artifact id cannot be null or blank");
+ }
+
+ if (StringUtils.isBlank(version)) {
+ throw new IllegalArgumentException("Version cannot be null or blank");
+ }
+
+ return executeAction("Error retrieving version content for extension repo", () -> {
+ final WebTarget target = extensionRepoTarget
+ .path("{groupId}/{artifactId}/{version}/sha256")
+ .resolveTemplate("groupId", groupId)
+ .resolveTemplate("artifactId", artifactId)
+ .resolveTemplate("version", version);
+
+ try {
+ final String sha256 = getRequestBuilder(target).accept(MediaType.TEXT_PLAIN_TYPE).get(String.class);
+ return Optional.of(sha256);
+ } catch (NotFoundException nfe) {
+ return Optional.empty();
+ }
+ });
+ }
+
private void validate(String bucketName, String groupId, String artifactId, String version) {
if (StringUtils.isBlank(bucketName)) {
throw new IllegalArgumentException("Bucket name cannot be null or blank");
diff --git a/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/bucket/Bucket.java b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/bucket/Bucket.java
index 94402a9..a5f9f51 100644
--- a/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/bucket/Bucket.java
+++ b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/bucket/Bucket.java
@@ -41,6 +41,8 @@
private String description;
+ private Boolean allowExtensionBundleRedeploy;
+
private Permissions permissions;
@ApiModelProperty(value = "An ID to uniquely identify this object.", readOnly = true)
@@ -79,6 +81,15 @@
this.description = description;
}
+ @ApiModelProperty("Indicates if this bucket allows the same version of an extension bundle to be redeployed and thus overwrite the existing artifact. By default this is false.")
+ public Boolean isAllowExtensionBundleRedeploy() {
+ return allowExtensionBundleRedeploy;
+ }
+
+ public void setAllowExtensionBundleRedeploy(final Boolean allowExtensionBundleRedeploy) {
+ this.allowExtensionBundleRedeploy = allowExtensionBundleRedeploy;
+ }
+
@ApiModelProperty(value = "The access that the current user has to this bucket.", readOnly = true)
public Permissions getPermissions() {
return permissions;
diff --git a/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/extension/ExtensionBundleVersionMetadata.java b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/extension/ExtensionBundleVersionMetadata.java
index 35756f9..6902083 100644
--- a/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/extension/ExtensionBundleVersionMetadata.java
+++ b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/extension/ExtensionBundleVersionMetadata.java
@@ -56,6 +56,10 @@
@NotNull
private Boolean sha256Supplied;
+ @NotNull
+ @Min(0)
+ private long contentSize;
+
@ApiModelProperty(value = "The id of this version of the extension bundle")
public String getId() {
@@ -138,6 +142,15 @@
this.sha256Supplied = sha256Supplied;
}
+ @ApiModelProperty(value = "The size of the binary content for this version in bytes")
+ public long getContentSize() {
+ return contentSize;
+ }
+
+ public void setContentSize(long contentSize) {
+ this.contentSize = contentSize;
+ }
+
@Override
public int compareTo(final ExtensionBundleVersionMetadata o) {
return o == null ? -1 : version.compareTo(o.version);
diff --git a/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/extension/filter/ExtensionBundleFilterParams.java b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/extension/filter/ExtensionBundleFilterParams.java
new file mode 100644
index 0000000..eb4490f
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/extension/filter/ExtensionBundleFilterParams.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.registry.extension.filter;
+
+/**
+ * Filter parameters for retrieving extension bundles.
+ */
+public class ExtensionBundleFilterParams {
+
+ private static final ExtensionBundleFilterParams EMPTY_PARAMS = new Builder().build();
+
+ private final String groupId;
+ private final String artifactId;
+
+ private ExtensionBundleFilterParams(final Builder builder) {
+ this.groupId = builder.groupId;
+ this.artifactId = builder.artifactId;
+ }
+
+ public String getGroupId() {
+ return groupId;
+ }
+
+ public String getArtifactId() {
+ return artifactId;
+ }
+
+ public static ExtensionBundleFilterParams of(final String groupId, final String artifactId) {
+ return new Builder().group(groupId).artifact(artifactId).build();
+ }
+
+ public static ExtensionBundleFilterParams empty() {
+ return EMPTY_PARAMS;
+ }
+
+ public static class Builder {
+
+ private String groupId;
+ private String artifactId;
+
+ public Builder group(final String groupId) {
+ this.groupId = groupId;
+ return this;
+ }
+
+ public Builder artifact(final String artifactId) {
+ this.artifactId = artifactId;
+ return this;
+ }
+
+ public ExtensionBundleFilterParams build() {
+ return new ExtensionBundleFilterParams(this);
+ }
+ }
+
+}
diff --git a/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/extension/filter/ExtensionBundleVersionFilterParams.java b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/extension/filter/ExtensionBundleVersionFilterParams.java
new file mode 100644
index 0000000..1402989
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-data-model/src/main/java/org/apache/nifi/registry/extension/filter/ExtensionBundleVersionFilterParams.java
@@ -0,0 +1,82 @@
+/*
+ * 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.filter;
+
+/**
+ * Filter parameters for extension bundle versions.
+ */
+public class ExtensionBundleVersionFilterParams {
+
+ private static final ExtensionBundleVersionFilterParams EMPTY_PARAMS = new Builder().build();
+
+ private final String groupId;
+ private final String artifactId;
+ private final String version;
+
+ private ExtensionBundleVersionFilterParams(final Builder builder) {
+ this.groupId = builder.groupId;
+ this.artifactId = builder.artifactId;
+ this.version = builder.version;
+ }
+
+ public String getGroupId() {
+ return groupId;
+ }
+
+ public String getArtifactId() {
+ return artifactId;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public static ExtensionBundleVersionFilterParams of(final String groupId, final String artifactId, final String version) {
+ return new Builder().group(groupId).artifact(artifactId).version(version).build();
+ }
+
+ public static ExtensionBundleVersionFilterParams empty() {
+ return EMPTY_PARAMS;
+ }
+
+ public static class Builder {
+
+ private String groupId;
+ private String artifactId;
+ private String version;
+
+ public Builder group(final String groupId) {
+ this.groupId = groupId;
+ return this;
+ }
+
+ public Builder artifact(final String artifactId) {
+ this.artifactId = artifactId;
+ return this;
+ }
+
+ public Builder version(final String version) {
+ this.version = version;
+ return this;
+ }
+
+ public ExtensionBundleVersionFilterParams build() {
+ return new ExtensionBundleVersionFilterParams(this);
+ }
+ }
+
+}
diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/DatabaseMetadataService.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/DatabaseMetadataService.java
index de9cf69..d80485d 100644
--- a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/DatabaseMetadataService.java
+++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/DatabaseMetadataService.java
@@ -16,6 +16,7 @@
*/
package org.apache.nifi.registry.db;
+import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.registry.db.entity.BucketEntity;
import org.apache.nifi.registry.db.entity.BucketItemEntity;
import org.apache.nifi.registry.db.entity.BucketItemEntityType;
@@ -35,6 +36,8 @@
import org.apache.nifi.registry.db.mapper.ExtensionEntityRowMapper;
import org.apache.nifi.registry.db.mapper.FlowEntityRowMapper;
import org.apache.nifi.registry.db.mapper.FlowSnapshotEntityRowMapper;
+import org.apache.nifi.registry.extension.filter.ExtensionBundleFilterParams;
+import org.apache.nifi.registry.extension.filter.ExtensionBundleVersionFilterParams;
import org.apache.nifi.registry.service.MetadataService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
@@ -65,8 +68,13 @@
@Override
public BucketEntity createBucket(final BucketEntity b) {
- final String sql = "INSERT INTO bucket (ID, NAME, DESCRIPTION, CREATED) VALUES (?, ?, ?, ?)";
- jdbcTemplate.update(sql, b.getId(), b.getName(), b.getDescription(), b.getCreated());
+ final String sql = "INSERT INTO bucket (ID, NAME, DESCRIPTION, CREATED, ALLOW_EXTENSION_BUNDLE_REDEPLOY) VALUES (?, ?, ?, ?, ?)";
+ jdbcTemplate.update(sql,
+ b.getId(),
+ b.getName(),
+ b.getDescription(),
+ b.getCreated(),
+ b.isAllowExtensionBundleRedeploy() ? 1 : 0);
return b;
}
@@ -88,8 +96,8 @@
@Override
public BucketEntity updateBucket(final BucketEntity bucket) {
- final String sql = "UPDATE bucket SET name = ?, description = ? WHERE id = ?";
- jdbcTemplate.update(sql, bucket.getName(), bucket.getDescription(), bucket.getId());
+ final String sql = "UPDATE bucket SET name = ?, description = ?, allow_extension_bundle_redeploy = ? WHERE id = ?";
+ jdbcTemplate.update(sql, bucket.getName(), bucket.getDescription(), bucket.isAllowExtensionBundleRedeploy() ? 1 : 0, bucket.getId());
return bucket;
}
@@ -495,12 +503,14 @@
}
@Override
- public List<ExtensionBundleEntity> getExtensionBundles(final Set<String> bucketIds) {
+ public List<ExtensionBundleEntity> getExtensionBundles(final Set<String> bucketIds, final ExtensionBundleFilterParams filterParams) {
if (bucketIds == null || bucketIds.isEmpty()) {
return Collections.emptyList();
}
- final String selectSql =
+ final List<Object> args = new ArrayList<>();
+
+ final StringBuilder sqlBuilder = new StringBuilder(
"SELECT " +
"item.id as ID, " +
"item.name as NAME, " +
@@ -519,19 +529,28 @@
"bucket b " +
"WHERE " +
"item.id = eb.id AND " +
- "b.id = item.bucket_id";
+ "b.id = item.bucket_id");
- final StringBuilder sqlBuilder = new StringBuilder(selectSql).append(" AND item.bucket_id IN (");
- for (int i=0; i < bucketIds.size(); i++) {
- if (i > 0) {
- sqlBuilder.append(", ");
+ if (filterParams != null) {
+ final String groupId = filterParams.getGroupId();
+ if (!StringUtils.isBlank(groupId)) {
+ sqlBuilder.append(" AND eb.group_id LIKE ? ");
+ args.add(groupId);
}
- sqlBuilder.append("?");
+
+ final String artifactId = filterParams.getArtifactId();
+ if (!StringUtils.isBlank(artifactId)) {
+ sqlBuilder.append(" AND eb.artifact_id LIKE ? ");
+ args.add(artifactId);
+ }
}
- sqlBuilder.append(") ");
+
+ addBucketIdentifiersClause(sqlBuilder, "item.bucket_id", bucketIds);
sqlBuilder.append("ORDER BY eb.group_id ASC, eb.artifact_id ASC");
- final List<ExtensionBundleEntity> bundleEntities = jdbcTemplate.query(sqlBuilder.toString(), bucketIds.toArray(), new ExtensionBundleEntityWithBucketNameRowMapper());
+ args.addAll(bucketIds);
+
+ final List<ExtensionBundleEntity> bundleEntities = jdbcTemplate.query(sqlBuilder.toString(), args.toArray(), new ExtensionBundleEntityWithBucketNameRowMapper());
return populateVersionCounts(bundleEntities);
}
@@ -607,8 +626,9 @@
"CREATED_BY, " +
"DESCRIPTION, " +
"SHA_256_HEX, " +
- "SHA_256_SUPPLIED " +
- ") VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
+ "SHA_256_SUPPLIED," +
+ "CONTENT_SIZE " +
+ ") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
jdbcTemplate.update(sql,
extensionBundleVersion.getId(),
@@ -618,26 +638,13 @@
extensionBundleVersion.getCreatedBy(),
extensionBundleVersion.getDescription(),
extensionBundleVersion.getSha256Hex(),
- extensionBundleVersion.getSha256Supplied() ? 1 : 0);
+ extensionBundleVersion.getSha256Supplied() ? 1 : 0,
+ extensionBundleVersion.getContentSize());
return extensionBundleVersion;
}
- @Override
- public ExtensionBundleVersionEntity getExtensionBundleVersion(final String extensionBundleId, final String version) {
- final String sql =
- "SELECT * " +
- "FROM extension_bundle_version " +
- "WHERE extension_bundle_id = ? AND version = ?";
-
- try {
- return jdbcTemplate.queryForObject(sql, new ExtensionBundleVersionEntityRowMapper(), extensionBundleId, version);
- } catch (EmptyResultDataAccessException e) {
- return null;
- }
- }
-
- private static final String BASE_EXTENSION_BUNDLE_SQL =
+ private static final String BASE_EXTENSION_BUNDLE_VERSION_SQL =
"SELECT " +
"ebv.id AS ID," +
"ebv.extension_bundle_id AS EXTENSION_BUNDLE_ID, " +
@@ -646,13 +653,26 @@
"ebv.created_by AS CREATED_BY, " +
"ebv.description AS DESCRIPTION, " +
"ebv.sha_256_hex AS SHA_256_HEX, " +
- "ebv.sha_256_supplied AS SHA_256_SUPPLIED " +
+ "ebv.sha_256_supplied AS SHA_256_SUPPLIED ," +
+ "ebv.content_size AS CONTENT_SIZE, " +
+ "eb.bucket_id AS BUCKET_ID " +
"FROM extension_bundle eb, extension_bundle_version ebv " +
"WHERE eb.id = ebv.extension_bundle_id ";
@Override
+ public ExtensionBundleVersionEntity getExtensionBundleVersion(final String extensionBundleId, final String version) {
+ final String sql = BASE_EXTENSION_BUNDLE_VERSION_SQL +
+ " AND ebv.extension_bundle_id = ? AND ebv.version = ?";
+ try {
+ return jdbcTemplate.queryForObject(sql, new ExtensionBundleVersionEntityRowMapper(), extensionBundleId, version);
+ } catch (EmptyResultDataAccessException e) {
+ return null;
+ }
+ }
+
+ @Override
public ExtensionBundleVersionEntity getExtensionBundleVersion(final String bucketId, final String groupId, final String artifactId, final String version) {
- final String sql = BASE_EXTENSION_BUNDLE_SQL +
+ final String sql = BASE_EXTENSION_BUNDLE_VERSION_SQL +
"AND eb.bucket_id = ? " +
"AND eb.group_id = ? " +
"AND eb.artifact_id = ? " +
@@ -666,14 +686,63 @@
}
@Override
+ public List<ExtensionBundleVersionEntity> getExtensionBundleVersions(final Set<String> bucketIdentifiers, final ExtensionBundleVersionFilterParams filterParams) {
+ if (bucketIdentifiers == null || bucketIdentifiers.isEmpty()) {
+ return Collections.emptyList();
+ }
+
+ final List<Object> args = new ArrayList<>();
+ final StringBuilder sqlBuilder = new StringBuilder(BASE_EXTENSION_BUNDLE_VERSION_SQL);
+
+ if (filterParams != null) {
+ final String groupId = filterParams.getGroupId();
+ if (!StringUtils.isBlank(groupId)) {
+ sqlBuilder.append(" AND eb.group_id LIKE ? ");
+ args.add(groupId);
+ }
+
+ final String artifactId = filterParams.getArtifactId();
+ if (!StringUtils.isBlank(artifactId)) {
+ sqlBuilder.append(" AND eb.artifact_id LIKE ? ");
+ args.add(artifactId);
+ }
+
+ final String version = filterParams.getVersion();
+ if (!StringUtils.isBlank(version)) {
+ sqlBuilder.append(" AND ebv.version LIKE ? ");
+ args.add(version);
+ }
+ }
+
+ addBucketIdentifiersClause(sqlBuilder, "eb.bucket_id", bucketIdentifiers);
+ args.addAll(bucketIdentifiers);
+
+ final List<ExtensionBundleVersionEntity> bundleVersionEntities = jdbcTemplate.query(
+ sqlBuilder.toString(), args.toArray(), new ExtensionBundleVersionEntityRowMapper());
+
+ return bundleVersionEntities;
+ }
+
+ private void addBucketIdentifiersClause(StringBuilder sqlBuilder, String bucketField, Set<String> bucketIdentifiers) {
+ sqlBuilder.append(" AND ").append(bucketField).append(" IN (");
+ for (int i = 0; i < bucketIdentifiers.size(); i++) {
+ if (i > 0) {
+ sqlBuilder.append(", ");
+ }
+ sqlBuilder.append("?");
+ }
+ sqlBuilder.append(") ");
+ }
+
+ @Override
public List<ExtensionBundleVersionEntity> getExtensionBundleVersions(final String extensionBundleId) {
- final String sql = "SELECT * FROM extension_bundle_version WHERE extension_bundle_id = ?";
+ final String sql = BASE_EXTENSION_BUNDLE_VERSION_SQL + " AND ebv.extension_bundle_id = ?";
return jdbcTemplate.query(sql, new Object[]{extensionBundleId}, new ExtensionBundleVersionEntityRowMapper());
}
@Override
public List<ExtensionBundleVersionEntity> getExtensionBundleVersions(final String bucketId, final String groupId, final String artifactId) {
- final String sql = BASE_EXTENSION_BUNDLE_SQL +
+ final String sql = BASE_EXTENSION_BUNDLE_VERSION_SQL +
"AND eb.bucket_id = ? " +
"AND eb.group_id = ? " +
"AND eb.artifact_id = ? ";
@@ -684,7 +753,7 @@
@Override
public List<ExtensionBundleVersionEntity> getExtensionBundleVersionsGlobal(final String groupId, final String artifactId, final String version) {
- final String sql = BASE_EXTENSION_BUNDLE_SQL +
+ final String sql = BASE_EXTENSION_BUNDLE_VERSION_SQL +
"AND eb.group_id = ? " +
"AND eb.artifact_id = ? " +
"AND ebv.version = ?";
diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/BucketEntity.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/BucketEntity.java
index 71d5a92..fe980d0 100644
--- a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/BucketEntity.java
+++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/BucketEntity.java
@@ -29,6 +29,8 @@
private Date created;
+ private boolean allowExtensionBundleRedeploy;
+
public String getId() {
return id;
@@ -62,6 +64,14 @@
this.description = description;
}
+ public boolean isAllowExtensionBundleRedeploy() {
+ return allowExtensionBundleRedeploy;
+ }
+
+ public void setAllowExtensionBundleRedeploy(final boolean allowExtensionBundleRedeploy) {
+ this.allowExtensionBundleRedeploy = allowExtensionBundleRedeploy;
+ }
+
@Override
public int hashCode() {
return Objects.hashCode(this.id);
diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/ExtensionBundleVersionEntity.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/ExtensionBundleVersionEntity.java
index 08fc2c2..0bc5a59 100644
--- a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/ExtensionBundleVersionEntity.java
+++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/entity/ExtensionBundleVersionEntity.java
@@ -26,6 +26,9 @@
// Foreign key to the extension bundle this version goes with
private String extensionBundleId;
+ // The bucket id where the bundle is located
+ private String bucketId;
+
// The version of this bundle
private String version;
@@ -40,6 +43,8 @@
// Indicates whether the SHA-256 was supplied by the client, which means it matched the server's calculation, or was not supplied by the client
private boolean sha256Supplied;
+ // The size of binary content in bytes
+ private long contentSize;
public String getId() {
return id;
@@ -57,6 +62,14 @@
this.extensionBundleId = extensionBundleId;
}
+ public String getBucketId() {
+ return bucketId;
+ }
+
+ public void setBucketId(String bucketId) {
+ this.bucketId = bucketId;
+ }
+
public String getVersion() {
return version;
}
@@ -104,4 +117,13 @@
public void setSha256Supplied(boolean sha256Supplied) {
this.sha256Supplied = sha256Supplied;
}
+
+ public long getContentSize() {
+ return contentSize;
+ }
+
+ public void setContentSize(long contentSize) {
+ this.contentSize = contentSize;
+ }
+
}
diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/mapper/BucketEntityRowMapper.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/mapper/BucketEntityRowMapper.java
index 6c5bc2e..5ef5c60 100644
--- a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/mapper/BucketEntityRowMapper.java
+++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/mapper/BucketEntityRowMapper.java
@@ -33,6 +33,7 @@
b.setName(rs.getString("NAME"));
b.setDescription(rs.getString("DESCRIPTION"));
b.setCreated(rs.getTimestamp("CREATED"));
+ b.setAllowExtensionBundleRedeploy(rs.getInt("ALLOW_EXTENSION_BUNDLE_REDEPLOY") == 0 ? false : true);
return b;
}
diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/mapper/ExtensionBundleVersionEntityRowMapper.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/mapper/ExtensionBundleVersionEntityRowMapper.java
index 60ca48f..4dd47b6 100644
--- a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/mapper/ExtensionBundleVersionEntityRowMapper.java
+++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/db/mapper/ExtensionBundleVersionEntityRowMapper.java
@@ -29,9 +29,11 @@
final ExtensionBundleVersionEntity entity = new ExtensionBundleVersionEntity();
entity.setId(rs.getString("ID"));
entity.setExtensionBundleId(rs.getString("EXTENSION_BUNDLE_ID"));
+ entity.setBucketId(rs.getString("BUCKET_ID"));
entity.setVersion(rs.getString("VERSION"));
entity.setSha256Hex(rs.getString("SHA_256_HEX"));
entity.setSha256Supplied(rs.getInt("SHA_256_SUPPLIED") == 1);
+ entity.setContentSize(rs.getLong("CONTENT_SIZE"));
entity.setCreated(rs.getTimestamp("CREATED"));
entity.setCreatedBy(rs.getString("CREATED_BY"));
diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/provider/extension/FileSystemExtensionBundlePersistenceProvider.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/provider/extension/FileSystemExtensionBundlePersistenceProvider.java
index 1d8c9cc..1b29ba9 100644
--- a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/provider/extension/FileSystemExtensionBundlePersistenceProvider.java
+++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/provider/extension/FileSystemExtensionBundlePersistenceProvider.java
@@ -76,7 +76,7 @@
}
@Override
- public synchronized void saveBundleVersion(final ExtensionBundleContext context, final InputStream contentStream)
+ public synchronized void saveBundleVersion(final ExtensionBundleContext context, final InputStream contentStream, boolean overwrite)
throws ExtensionBundlePersistenceException {
final File bundleVersionDir = getBundleVersionDirectory(bundleStorageDir, context.getBucketName(),
@@ -91,7 +91,7 @@
final File bundleFile = getBundleFile(bundleVersionDir, context.getBundleArtifactId(),
context.getBundleVersion(), context.getBundleType());
- if (bundleFile.exists()) {
+ if (bundleFile.exists() && !overwrite) {
throw new ExtensionBundlePersistenceException("Unable to save because an extension bundle already exists at "
+ bundleFile.getAbsolutePath());
}
diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/DataModelMapper.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/DataModelMapper.java
index 6974cb9..6be1929 100644
--- a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/DataModelMapper.java
+++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/DataModelMapper.java
@@ -53,6 +53,7 @@
bucketEntity.setName(bucket.getName());
bucketEntity.setDescription(bucket.getDescription());
bucketEntity.setCreated(new Date(bucket.getCreatedTimestamp()));
+ bucketEntity.setAllowExtensionBundleRedeploy(bucket.isAllowExtensionBundleRedeploy());
return bucketEntity;
}
@@ -62,6 +63,7 @@
bucket.setName(bucketEntity.getName());
bucket.setDescription(bucketEntity.getDescription());
bucket.setCreatedTimestamp(bucketEntity.getCreated().getTime());
+ bucket.setAllowExtensionBundleRedeploy(bucketEntity.isAllowExtensionBundleRedeploy());
return bucket;
}
@@ -224,30 +226,29 @@
final ExtensionBundleVersionEntity entity = new ExtensionBundleVersionEntity();
entity.setId(bundleVersionMetadata.getId());
entity.setExtensionBundleId(bundleVersionMetadata.getExtensionBundleId());
+ entity.setBucketId(bundleVersionMetadata.getBucketId());
entity.setVersion(bundleVersionMetadata.getVersion());
entity.setCreated(new Date(bundleVersionMetadata.getTimestamp()));
entity.setCreatedBy(bundleVersionMetadata.getAuthor());
entity.setDescription(bundleVersionMetadata.getDescription());
entity.setSha256Hex(bundleVersionMetadata.getSha256());
entity.setSha256Supplied(bundleVersionMetadata.getSha256Supplied());
+ entity.setContentSize(bundleVersionMetadata.getContentSize());
return entity;
}
- public static ExtensionBundleVersionMetadata map(final BucketEntity bucketEntity, final ExtensionBundleVersionEntity bundleVersionEntity) {
+ public static ExtensionBundleVersionMetadata map(final ExtensionBundleVersionEntity bundleVersionEntity) {
final ExtensionBundleVersionMetadata bundleVersionMetadata = new ExtensionBundleVersionMetadata();
bundleVersionMetadata.setId(bundleVersionEntity.getId());
bundleVersionMetadata.setExtensionBundleId(bundleVersionEntity.getExtensionBundleId());
+ bundleVersionMetadata.setBucketId(bundleVersionEntity.getBucketId());
bundleVersionMetadata.setVersion(bundleVersionEntity.getVersion());
bundleVersionMetadata.setTimestamp(bundleVersionEntity.getCreated().getTime());
bundleVersionMetadata.setAuthor(bundleVersionEntity.getCreatedBy());
bundleVersionMetadata.setDescription(bundleVersionEntity.getDescription());
bundleVersionMetadata.setSha256(bundleVersionEntity.getSha256Hex());
bundleVersionMetadata.setSha256Supplied(bundleVersionEntity.getSha256Supplied());
-
- if (bucketEntity != null) {
- bundleVersionMetadata.setBucketId(bucketEntity.getId());
- }
-
+ bundleVersionMetadata.setContentSize(bundleVersionEntity.getContentSize());
return bundleVersionMetadata;
}
diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/MetadataService.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/MetadataService.java
index 1dc90d4..260618d 100644
--- a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/MetadataService.java
+++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/MetadataService.java
@@ -25,6 +25,8 @@
import org.apache.nifi.registry.db.entity.ExtensionEntityCategory;
import org.apache.nifi.registry.db.entity.FlowEntity;
import org.apache.nifi.registry.db.entity.FlowSnapshotEntity;
+import org.apache.nifi.registry.extension.filter.ExtensionBundleFilterParams;
+import org.apache.nifi.registry.extension.filter.ExtensionBundleVersionFilterParams;
import java.util.List;
import java.util.Set;
@@ -246,9 +248,10 @@
* Retrieves all extension bundles in the buckets with the given bucket ids.
*
* @param bucketIds the bucket ids
+ * @param filterParams the optional filter params
* @return the list of all extension bundles in the given buckets
*/
- List<ExtensionBundleEntity> getExtensionBundles(Set<String> bucketIds);
+ List<ExtensionBundleEntity> getExtensionBundles(Set<String> bucketIds, ExtensionBundleFilterParams filterParams);
/**
* Retrieves the extension bundles for the given bucket.
@@ -312,6 +315,15 @@
ExtensionBundleVersionEntity getExtensionBundleVersion(String bucketId, String groupId, String artifactId, String version);
/**
+ * Retrieves the extension bundle versions in the given buckets, matching the optional filter parameters.
+ *
+ * @param bucketIdentifiers the bucket identifiers
+ * @param filterParams the optional filter params
+ * @return the extension bundle versions
+ */
+ List<ExtensionBundleVersionEntity> getExtensionBundleVersions(Set<String> bucketIdentifiers, ExtensionBundleVersionFilterParams filterParams);
+
+ /**
* Retrieves the extension bundle versions for the given extension bundle id.
*
* @param extensionBundleId the extension bundle id
diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/RegistryService.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/RegistryService.java
index 091803f..cdfaf79 100644
--- a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/RegistryService.java
+++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/RegistryService.java
@@ -33,6 +33,8 @@
import org.apache.nifi.registry.extension.ExtensionBundleType;
import org.apache.nifi.registry.extension.ExtensionBundleVersion;
import org.apache.nifi.registry.extension.ExtensionBundleVersionMetadata;
+import org.apache.nifi.registry.extension.filter.ExtensionBundleFilterParams;
+import org.apache.nifi.registry.extension.filter.ExtensionBundleVersionFilterParams;
import org.apache.nifi.registry.extension.repo.ExtensionRepoArtifact;
import org.apache.nifi.registry.extension.repo.ExtensionRepoBucket;
import org.apache.nifi.registry.extension.repo.ExtensionRepoGroup;
@@ -141,6 +143,10 @@
bucket.setIdentifier(UUID.randomUUID().toString());
bucket.setCreatedTimestamp(System.currentTimeMillis());
+ if (bucket.isAllowExtensionBundleRedeploy() == null) {
+ bucket.setAllowExtensionBundleRedeploy(false);
+ }
+
validate(bucket, "Cannot create Bucket");
writeLock.lock();
@@ -259,6 +265,10 @@
existingBucketById.setDescription(bucket.getDescription());
}
+ if (bucket.isAllowExtensionBundleRedeploy() != null) {
+ existingBucketById.setAllowExtensionBundleRedeploy(bucket.isAllowExtensionBundleRedeploy());
+ }
+
// perform the actual update
final BucketEntity updatedBucket = metadataService.updateBucket(existingBucketById);
return DataModelMapper.map(updatedBucket);
@@ -1027,10 +1037,10 @@
}
}
- public List<ExtensionBundle> getExtensionBundles(Set<String> bucketIdentifiers) {
+ public List<ExtensionBundle> getExtensionBundles(final Set<String> bucketIdentifiers, final ExtensionBundleFilterParams filterParams) {
readLock.lock();
try {
- return extensionService.getExtensionBundles(bucketIdentifiers);
+ return extensionService.getExtensionBundles(bucketIdentifiers, filterParams);
} finally {
readLock.unlock();
}
@@ -1063,6 +1073,17 @@
}
}
+ public SortedSet<ExtensionBundleVersionMetadata> getExtensionBundleVersions(final Set<String> bucketIdentifiers,
+ final ExtensionBundleVersionFilterParams filterParams) {
+ readLock.lock();
+ try {
+ return extensionService.getExtensionBundleVersions(bucketIdentifiers, filterParams);
+ } finally {
+ readLock.unlock();
+ }
+ }
+
+
public SortedSet<ExtensionBundleVersionMetadata> getExtensionBundleVersions(final String extensionBundleIdentifier) {
readLock.lock();
try {
@@ -1072,7 +1093,7 @@
}
}
- public ExtensionBundleVersion getExtensionBundleVersion(ExtensionBundleVersionCoordinate versionCoordinate) {
+ public ExtensionBundleVersion getExtensionBundleVersion(final ExtensionBundleVersionCoordinate versionCoordinate) {
readLock.lock();
try {
return extensionService.getExtensionBundleVersion(versionCoordinate);
diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/extension/ExtensionService.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/extension/ExtensionService.java
index 3ab8a07..8ffd4d3 100644
--- a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/extension/ExtensionService.java
+++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/extension/ExtensionService.java
@@ -21,6 +21,8 @@
import org.apache.nifi.registry.extension.ExtensionBundleType;
import org.apache.nifi.registry.extension.ExtensionBundleVersion;
import org.apache.nifi.registry.extension.ExtensionBundleVersionMetadata;
+import org.apache.nifi.registry.extension.filter.ExtensionBundleFilterParams;
+import org.apache.nifi.registry.extension.filter.ExtensionBundleVersionFilterParams;
import org.apache.nifi.registry.extension.repo.ExtensionRepoArtifact;
import org.apache.nifi.registry.extension.repo.ExtensionRepoBucket;
import org.apache.nifi.registry.extension.repo.ExtensionRepoGroup;
@@ -35,6 +37,8 @@
public interface ExtensionService {
+ // ----- Extension Bundles -----
+
/**
* Creates a version of an extension bundle.
*
@@ -57,9 +61,10 @@
* Retrieves the extension bundles in the given buckets.
*
* @param bucketIdentifiers the bucket identifiers
+ * @param filterParams the optional filter params
* @return the bundles in the given buckets
*/
- List<ExtensionBundle> getExtensionBundles(Set<String> bucketIdentifiers);
+ List<ExtensionBundle> getExtensionBundles(Set<String> bucketIdentifiers, ExtensionBundleFilterParams filterParams);
/**
* Retrieves the extension bundles in the given bucket.
@@ -85,6 +90,18 @@
*/
ExtensionBundle deleteExtensionBundle(ExtensionBundle extensionBundle);
+ // ----- Extension Bundle Versions -----
+
+ /**
+ * Retrieves the extension bundle versions in the given buckets.
+ *
+ * @param bucketIdentifiers the bucket identifiers
+ * @param filterParams the optional filter params
+ * @return the set of extension bundle versions
+ */
+ SortedSet<ExtensionBundleVersionMetadata> getExtensionBundleVersions(
+ Set<String> bucketIdentifiers, ExtensionBundleVersionFilterParams filterParams);
+
/**
* Retrieves the versions of the given extension bundle.
*
@@ -119,12 +136,39 @@
// ----- Extension Repo Methods -----
+ /**
+ * Retrieves the extension repo buckets for the given bucket ids.
+ *
+ * @param bucketIds the bucket ids
+ * @return the set of buckets
+ */
SortedSet<ExtensionRepoBucket> getExtensionRepoBuckets(Set<String> bucketIds);
+ /**
+ * Retrieves the extension repo groups for the given bucket.
+ *
+ * @param bucket the bucket
+ * @return the groups for the bucket
+ */
SortedSet<ExtensionRepoGroup> getExtensionRepoGroups(Bucket bucket);
+ /**
+ * Retrieves the extension repo artifacts for the given bucket and group.
+ *
+ * @param bucket the bucket
+ * @param groupId the group id
+ * @return the artifacts for the bucket and group
+ */
SortedSet<ExtensionRepoArtifact> getExtensionRepoArtifacts(Bucket bucket, String groupId);
+ /**
+ * Retrieves the extension repo version summaries for the given bucket, group, and artifact.
+ *
+ * @param bucket the bucket
+ * @param groupId the group id
+ * @param artifactId the artifact id
+ * @return the version summaries for the bucket, group, and artifact
+ */
SortedSet<ExtensionRepoVersionSummary> getExtensionRepoVersions(Bucket bucket, String groupId, String artifactId);
}
diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/extension/StandardExtensionService.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/extension/StandardExtensionService.java
index e737b75..ac69140 100644
--- a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/extension/StandardExtensionService.java
+++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/service/extension/StandardExtensionService.java
@@ -38,6 +38,8 @@
import org.apache.nifi.registry.extension.ExtensionBundleVersion;
import org.apache.nifi.registry.extension.ExtensionBundleVersionDependency;
import org.apache.nifi.registry.extension.ExtensionBundleVersionMetadata;
+import org.apache.nifi.registry.extension.filter.ExtensionBundleFilterParams;
+import org.apache.nifi.registry.extension.filter.ExtensionBundleVersionFilterParams;
import org.apache.nifi.registry.extension.repo.ExtensionRepoArtifact;
import org.apache.nifi.registry.extension.repo.ExtensionRepoBucket;
import org.apache.nifi.registry.extension.repo.ExtensionRepoGroup;
@@ -66,6 +68,7 @@
import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.util.Collections;
+import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -80,6 +83,8 @@
private static final Logger LOGGER = LoggerFactory.getLogger(StandardExtensionService.class);
+ static final String SNAPSHOT_VERSION_SUFFIX = "SNAPSHOT";
+
private final MetadataService metadataService;
private final Map<ExtensionBundleType, BundleExtractor> extractors;
private final ExtensionBundlePersistenceProvider bundlePersistenceProvider;
@@ -173,14 +178,18 @@
final String groupId = bundleCoordinate.getGroupId();
final String artifactId = bundleCoordinate.getArtifactId();
final String version = bundleCoordinate.getVersion();
+
+ final boolean isSnapshotVersion = version.endsWith(SNAPSHOT_VERSION_SUFFIX);
+ final boolean overwriteBundleVersion = isSnapshotVersion || existingBucket.isAllowExtensionBundleRedeploy();
+
LOGGER.debug("Extracted bundle details - '{}' - '{}' - '{}'", new Object[]{groupId, artifactId, version});
- // a bundle with the same group, artifact, and version can exist in multiple buckets, but only if it contains the same binary content,
+ // a bundle with the same group, artifact, and version can exist in multiple buckets, but only if it contains the same binary content, or if its a snapshot version
// we can determine that by comparing the SHA-256 digest of the incoming bundle against existing bundles with the same group, artifact, version
final List<ExtensionBundleVersionEntity> allExistingVersions = metadataService.getExtensionBundleVersionsGlobal(groupId, artifactId, version);
for (final ExtensionBundleVersionEntity existingVersionEntity : allExistingVersions) {
- if (!existingVersionEntity.getSha256Hex().equals(sha256Hex)) {
- throw new IllegalStateException("Found existing extension bundle with same group, artifact, and version, but different SHA-256 check-sum");
+ if (!existingVersionEntity.getSha256Hex().equals(sha256Hex) && !isSnapshotVersion) {
+ throw new IllegalStateException("Found existing extension bundle with same group, artifact, and version, but different SHA-256 checksums");
}
}
@@ -188,11 +197,17 @@
final long currentTime = System.currentTimeMillis();
final ExtensionBundleEntity extensionBundle = getOrCreateExtensionBundle(bucketIdentifier, groupId, artifactId, bundleType, currentTime);
- // ensure there isn't already a version of the bundle with the same version
+ // check if the version of incoming bundle already exists in the bucket
+ // if it exists and it is a snapshot version or the bucket allows redeploying, then first delete the row in the extension_bundle_version table so we can create a new one
+ // otherwise we throw an exception because we don't allow the same version in the same bucket
final ExtensionBundleVersionEntity existingVersion = metadataService.getExtensionBundleVersion(bucketIdentifier, groupId, artifactId, version);
if (existingVersion != null) {
- LOGGER.warn("The specified version [{}] already exists for extension bundle [{}].", new Object[]{version, extensionBundle.getId()});
- throw new IllegalStateException("The specified version already exists for the given extension bundle");
+ if (overwriteBundleVersion) {
+ metadataService.deleteExtensionBundleVersion(existingVersion);
+ } else {
+ LOGGER.warn("The specified version [{}] already exists for extension bundle [{}].", new Object[]{version, extensionBundle.getId()});
+ throw new IllegalStateException("The specified version already exists for the given extension bundle");
+ }
}
// create the version metadata instance and validate it has all the required fields
@@ -206,6 +221,7 @@
versionMetadata.setAuthor(userIdentity);
versionMetadata.setSha256(sha256Hex);
versionMetadata.setSha256Supplied(sha256Supplied);
+ versionMetadata.setContentSize(extensionWorkingFile.length());
validate(versionMetadata, "Cannot create extension bundle version");
@@ -248,9 +264,8 @@
try (final InputStream in = new FileInputStream(extensionWorkingFile);
final InputStream bufIn = new BufferedInputStream(in)) {
- bundlePersistenceProvider.saveBundleVersion(context, bufIn);
- LOGGER.debug("Bundle saved to persistence provider - '{}' - '{}' - '{}'",
- new Object[]{groupId, artifactId, version});
+ bundlePersistenceProvider.saveBundleVersion(context, bufIn, overwriteBundleVersion);
+ LOGGER.debug("Bundle saved to persistence provider - '{}' - '{}' - '{}'", new Object[]{groupId, artifactId, version});
}
// get the updated extension bundle so it contains the correct version count
@@ -315,12 +330,13 @@
}
@Override
- public List<ExtensionBundle> getExtensionBundles(Set<String> bucketIdentifiers) {
+ public List<ExtensionBundle> getExtensionBundles(final Set<String> bucketIdentifiers, final ExtensionBundleFilterParams filterParams) {
if (bucketIdentifiers == null) {
throw new IllegalArgumentException("Bucket identifiers cannot be null");
}
- final List<ExtensionBundleEntity> bundleEntities = metadataService.getExtensionBundles(bucketIdentifiers);
+ final List<ExtensionBundleEntity> bundleEntities = metadataService.getExtensionBundles(bucketIdentifiers,
+ filterParams == null ? ExtensionBundleFilterParams.empty() : filterParams);
return bundleEntities.stream().map(b -> DataModelMapper.map(null, b)).collect(Collectors.toList());
}
@@ -377,6 +393,26 @@
}
@Override
+ public SortedSet<ExtensionBundleVersionMetadata> getExtensionBundleVersions(final Set<String> bucketIdentifiers,
+ final ExtensionBundleVersionFilterParams filterParams) {
+ if (bucketIdentifiers == null) {
+ throw new IllegalArgumentException("Bucket identifiers cannot be null");
+ }
+
+ final SortedSet<ExtensionBundleVersionMetadata> sortedVersions = new TreeSet<>(
+ Comparator.comparing(ExtensionBundleVersionMetadata::getExtensionBundleId)
+ .thenComparing(ExtensionBundleVersionMetadata::getVersion)
+ );
+
+ final List<ExtensionBundleVersionEntity> bundleVersionEntities = metadataService.getExtensionBundleVersions(bucketIdentifiers,
+ filterParams == null ? ExtensionBundleVersionFilterParams.empty() : filterParams);
+ if (bundleVersionEntities != null) {
+ bundleVersionEntities.forEach(bv -> sortedVersions.add(DataModelMapper.map(bv)));
+ }
+ return sortedVersions;
+ }
+
+ @Override
public SortedSet<ExtensionBundleVersionMetadata> getExtensionBundleVersions(final String extensionBundleIdentifier) {
if (StringUtils.isBlank(extensionBundleIdentifier)) {
throw new IllegalArgumentException("Extension bundle identifier cannot be null or blank");
@@ -392,15 +428,13 @@
return getExtensionBundleVersionsSet(existingBundle);
}
- private SortedSet<ExtensionBundleVersionMetadata> getExtensionBundleVersionsSet(ExtensionBundleEntity existingBundle) {
+ private SortedSet<ExtensionBundleVersionMetadata> getExtensionBundleVersionsSet(final ExtensionBundleEntity existingBundle) {
final SortedSet<ExtensionBundleVersionMetadata> sortedVersions = new TreeSet<>(Collections.reverseOrder());
final List<ExtensionBundleVersionEntity> existingVersions = metadataService.getExtensionBundleVersions(existingBundle.getId());
if (existingVersions != null) {
- final BucketEntity existingBucket = metadataService.getBucketById(existingBundle.getBucketId());
- existingVersions.stream().forEach(s -> sortedVersions.add(DataModelMapper.map(existingBucket, s)));
+ existingVersions.stream().forEach(s -> sortedVersions.add(DataModelMapper.map(s)));
}
-
return sortedVersions;
}
@@ -451,7 +485,7 @@
// create the full ExtensionBundleVersion instance to return
final ExtensionBundleVersion extensionBundleVersion = new ExtensionBundleVersion();
- extensionBundleVersion.setVersionMetadata(DataModelMapper.map(existingBucket, existingVersion));
+ extensionBundleVersion.setVersionMetadata(DataModelMapper.map(existingVersion));
extensionBundleVersion.setExtensionBundle(DataModelMapper.map(existingBucket, existingBundle));
extensionBundleVersion.setBucket(DataModelMapper.map(existingBucket));
extensionBundleVersion.setDependencies(dependencies);
diff --git a/nifi-registry-core/nifi-registry-framework/src/main/resources/db/migration/V3__AddExtensions.sql b/nifi-registry-core/nifi-registry-framework/src/main/resources/db/migration/V3__AddExtensions.sql
index da66cd1..3cfb55a 100644
--- a/nifi-registry-core/nifi-registry-framework/src/main/resources/db/migration/V3__AddExtensions.sql
+++ b/nifi-registry-core/nifi-registry-framework/src/main/resources/db/migration/V3__AddExtensions.sql
@@ -34,6 +34,7 @@
DESCRIPTION TEXT,
SHA_256_HEX VARCHAR(512) NOT NULL,
SHA_256_SUPPLIED INT NOT NULL,
+ CONTENT_SIZE BIGINT NOT NULL,
CONSTRAINT PK__EXTENSION_BUNDLE_VERSION_ID PRIMARY KEY (ID),
CONSTRAINT FK__EXTENSION_BUNDLE_VERSION_EXTENSION_BUNDLE_ID FOREIGN KEY (EXTENSION_BUNDLE_ID) REFERENCES EXTENSION_BUNDLE(ID) ON DELETE CASCADE,
CONSTRAINT UNIQUE__EXTENSION_BUNDLE_VERSION_EXTENSION_BUNDLE_ID_VERSION UNIQUE (EXTENSION_BUNDLE_ID, VERSION)
@@ -68,4 +69,6 @@
TAG VARCHAR(200) NOT NULL,
CONSTRAINT PK__EXTENSION_TAG_EXTENSION_ID_AND_TAG PRIMARY KEY (EXTENSION_ID, TAG),
CONSTRAINT FK__EXTENSION_TAG_EXTENSION_ID FOREIGN KEY (EXTENSION_ID) REFERENCES EXTENSION(ID) ON DELETE CASCADE
-);
\ No newline at end of file
+);
+
+ALTER TABLE BUCKET ADD ALLOW_EXTENSION_BUNDLE_REDEPLOY INT NOT NULL DEFAULT (0);
\ No newline at end of file
diff --git a/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/TestDatabaseMetadataService.java b/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/TestDatabaseMetadataService.java
index a2bacd4..66be490 100644
--- a/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/TestDatabaseMetadataService.java
+++ b/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/db/TestDatabaseMetadataService.java
@@ -27,6 +27,8 @@
import org.apache.nifi.registry.db.entity.ExtensionEntityCategory;
import org.apache.nifi.registry.db.entity.FlowEntity;
import org.apache.nifi.registry.db.entity.FlowSnapshotEntity;
+import org.apache.nifi.registry.extension.filter.ExtensionBundleFilterParams;
+import org.apache.nifi.registry.extension.filter.ExtensionBundleVersionFilterParams;
import org.apache.nifi.registry.service.MetadataService;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
@@ -68,6 +70,7 @@
assertEquals(b.getName(), createdBucket.getName());
assertEquals(b.getDescription(), createdBucket.getDescription());
assertEquals(b.getCreated(), createdBucket.getCreated());
+ assertFalse(b.isAllowExtensionBundleRedeploy());
}
@Test
@@ -95,12 +98,14 @@
public void testUpdateBucket() {
final BucketEntity bucket = metadataService.getBucketById("1");
assertNotNull(bucket);
+ assertFalse(bucket.isAllowExtensionBundleRedeploy());
final String updatedName = bucket.getName() + " UPDATED";
final String updatedDesc = bucket.getDescription() + "DESC";
bucket.setName(updatedName);
bucket.setDescription(updatedDesc);
+ bucket.setAllowExtensionBundleRedeploy(true);
metadataService.updateBucket(bucket);
@@ -108,6 +113,7 @@
assertNotNull(updatedName);
assertEquals(updatedName, updatedBucket.getName());
assertEquals(updatedDesc, updatedBucket.getDescription());
+ assertTrue(updatedBucket.isAllowExtensionBundleRedeploy());
}
@Test
@@ -443,13 +449,13 @@
}
@Test
- public void testGetExtensionBundles() {
+ public void testGetExtensionBundlesWithEmptyFilterParams() {
final Set<String> bucketIds = new HashSet<>();
bucketIds.add("1");
bucketIds.add("2");
bucketIds.add("3");
- final List<ExtensionBundleEntity> bundles = metadataService.getExtensionBundles(bucketIds);
+ final List<ExtensionBundleEntity> bundles = metadataService.getExtensionBundles(bucketIds, ExtensionBundleFilterParams.empty());
assertNotNull(bundles);
assertEquals(3, bundles.size());
@@ -460,6 +466,44 @@
}
@Test
+ public void testGetExtensionBundlesWithFilterParams() {
+ final Set<String> bucketIds = new HashSet<>();
+ bucketIds.add("1");
+ bucketIds.add("2");
+ bucketIds.add("3");
+
+ final List<ExtensionBundleEntity> bundles = metadataService.getExtensionBundles(bucketIds,
+ ExtensionBundleFilterParams.empty());
+ assertNotNull(bundles);
+ assertEquals(3, bundles.size());
+
+ final List<ExtensionBundleEntity> bundles2 = metadataService.getExtensionBundles(bucketIds,
+ ExtensionBundleFilterParams.of("org.apache.nifi", null));
+ assertNotNull(bundles2);
+ assertEquals(2, bundles2.size());
+
+ final List<ExtensionBundleEntity> bundles3 = metadataService.getExtensionBundles(bucketIds,
+ ExtensionBundleFilterParams.of("org.apache.%", null));
+ assertNotNull(bundles3);
+ assertEquals(2, bundles3.size());
+
+ final List<ExtensionBundleEntity> bundles4 = metadataService.getExtensionBundles(bucketIds,
+ ExtensionBundleFilterParams.of("org.apache.nifi", "nifi-example-processors-nar"));
+ assertNotNull(bundles4);
+ assertEquals(1, bundles4.size());
+
+ final List<ExtensionBundleEntity> bundles5 = metadataService.getExtensionBundles(bucketIds,
+ ExtensionBundleFilterParams.of("org.apache.nifi", "nifi-example-processors-%"));
+ assertNotNull(bundles5);
+ assertEquals(1, bundles5.size());
+
+ final List<ExtensionBundleEntity> bundles6 = metadataService.getExtensionBundles(bucketIds,
+ ExtensionBundleFilterParams.of(null, "nifi-example-processors-%"));
+ assertNotNull(bundles6);
+ assertEquals(1, bundles6.size());
+ }
+
+ @Test
public void testGetExtensionBundlesByBucket() {
final List<ExtensionBundleEntity> bundles = metadataService.getExtensionBundlesByBucket("3");
assertNotNull(bundles);
@@ -474,7 +518,7 @@
public void testGetExtensionBundlesByBucketAndGroup() {
final List<ExtensionBundleEntity> bundles = metadataService.getExtensionBundlesByBucketAndGroup("3", "org.apache.nifi");
assertNotNull(bundles);
- assertEquals(3, bundles.size());
+ assertEquals(2, bundles.size());
final List<ExtensionBundleEntity> bundles2 = metadataService.getExtensionBundlesByBucketAndGroup("3", "does-not-exist");
assertNotNull(bundles2);
@@ -547,6 +591,7 @@
bundleVersion.setDescription("This is v1.1.0");
bundleVersion.setSha256Hex("123456789");
bundleVersion.setSha256Supplied(false);
+ bundleVersion.setContentSize(2048);
metadataService.createExtensionBundleVersion(bundleVersion);
@@ -557,6 +602,61 @@
}
@Test
+ public void testGetExtensionBundleVersionsWithEmptyBucketIdsAndEmptyFilterParams() {
+ final List<ExtensionBundleVersionEntity> versionEntities = metadataService.getExtensionBundleVersions(
+ Collections.emptySet(), ExtensionBundleVersionFilterParams.empty());
+ assertEquals(0, versionEntities.size());
+ }
+
+ @Test
+ public void testGetExtensionBundleVersionsWithEmptyFilterParams() {
+ final Set<String> bucketIds = new HashSet<>();
+ bucketIds.add("1");
+ bucketIds.add("2");
+ bucketIds.add("3");
+
+ final List<ExtensionBundleVersionEntity> versionEntities = metadataService.getExtensionBundleVersions(
+ bucketIds, ExtensionBundleVersionFilterParams.empty());
+ assertEquals(3, versionEntities.size());
+ }
+
+ @Test
+ public void testGetExtensionBundleVersionsWithFilterParams() {
+ final Set<String> bucketIds = new HashSet<>();
+ bucketIds.add("1");
+ bucketIds.add("2");
+ bucketIds.add("3");
+
+ final List<ExtensionBundleVersionEntity> versionEntities = metadataService.getExtensionBundleVersions(
+ bucketIds, ExtensionBundleVersionFilterParams.of("org.apache.nifi", null, null));
+ assertEquals(2, versionEntities.size());
+
+ final List<ExtensionBundleVersionEntity> versionEntities2 = metadataService.getExtensionBundleVersions(
+ bucketIds, ExtensionBundleVersionFilterParams.of("org.apache.%", null, null));
+ assertEquals(2, versionEntities2.size());
+
+ final List<ExtensionBundleVersionEntity> versionEntities3 = metadataService.getExtensionBundleVersions(
+ bucketIds, ExtensionBundleVersionFilterParams.of("org.apache.nifi", "nifi-example-processors-nar", null));
+ assertEquals(1, versionEntities3.size());
+
+ final List<ExtensionBundleVersionEntity> versionEntities4 = metadataService.getExtensionBundleVersions(
+ bucketIds, ExtensionBundleVersionFilterParams.of("org.apache.nifi", "nifi-example-processors-%", null));
+ assertEquals(1, versionEntities4.size());
+
+ final List<ExtensionBundleVersionEntity> versionEntities5 = metadataService.getExtensionBundleVersions(
+ bucketIds, ExtensionBundleVersionFilterParams.of("org.apache.nifi", "nifi-example-processors-nar", "1.0.0"));
+ assertEquals(1, versionEntities5.size());
+
+ final List<ExtensionBundleVersionEntity> versionEntities6 = metadataService.getExtensionBundleVersions(
+ bucketIds, ExtensionBundleVersionFilterParams.of("org.apache.nifi", "nifi-example-processors-nar", "1.0.%"));
+ assertEquals(1, versionEntities6.size());
+
+ final List<ExtensionBundleVersionEntity> versionEntities7 = metadataService.getExtensionBundleVersions(
+ bucketIds, ExtensionBundleVersionFilterParams.of("org.apache.nifi", "nifi-example-processors-nar", "NOT-FOUND"));
+ assertEquals(0, versionEntities7.size());
+ }
+
+ @Test
public void testGetExtensionBundleVersionByBundleIdAndVersion() {
final ExtensionBundleVersionEntity bundleVersion = metadataService.getExtensionBundleVersion("eb1", "1.0.0");
assertNotNull(bundleVersion);
@@ -567,6 +667,7 @@
assertEquals("user1", bundleVersion.getCreatedBy());
assertEquals("First version of eb1", bundleVersion.getDescription());
assertTrue(bundleVersion.getSha256Supplied());
+ assertEquals(1024, bundleVersion.getContentSize());
}
@Test
diff --git a/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/provider/MockExtensionBundlePersistenceProvider.java b/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/provider/MockExtensionBundlePersistenceProvider.java
index ba7f12f..42c5c49 100644
--- a/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/provider/MockExtensionBundlePersistenceProvider.java
+++ b/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/provider/MockExtensionBundlePersistenceProvider.java
@@ -29,7 +29,7 @@
private Map<String,String> properties;
@Override
- public void saveBundleVersion(ExtensionBundleContext context, InputStream contentStream)
+ public void saveBundleVersion(ExtensionBundleContext context, InputStream contentStream, boolean overwrite)
throws ExtensionBundlePersistenceException {
}
diff --git a/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/provider/extension/TestFileSystemExtensionBundlePersistenceProvider.java b/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/provider/extension/TestFileSystemExtensionBundlePersistenceProvider.java
index 5a611bb..ba7b3ab 100644
--- a/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/provider/extension/TestFileSystemExtensionBundlePersistenceProvider.java
+++ b/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/provider/extension/TestFileSystemExtensionBundlePersistenceProvider.java
@@ -254,7 +254,7 @@
final ExtensionBundleContext context = getExtensionBundleContext(bucketName, groupId, artifactId, version, bundleType);
try (final InputStream in = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8))) {
- persistenceProvider.saveBundleVersion(context, in);
+ persistenceProvider.saveBundleVersion(context, in, false);
}
}
diff --git a/nifi-registry-core/nifi-registry-framework/src/test/resources/db/migration/V999999.1__test-setup.sql b/nifi-registry-core/nifi-registry-framework/src/test/resources/db/migration/V999999.1__test-setup.sql
index b8e0d3a..80b58cb 100644
--- a/nifi-registry-core/nifi-registry-framework/src/test/resources/db/migration/V999999.1__test-setup.sql
+++ b/nifi-registry-core/nifi-registry-framework/src/test/resources/db/migration/V999999.1__test-setup.sql
@@ -112,7 +112,8 @@
created_by,
description,
sha_256_hex,
- sha_256_supplied
+ sha_256_supplied,
+ content_size
) values (
'eb1-v1',
'eb1',
@@ -121,7 +122,8 @@
'user1',
'First version of eb1',
'123456789',
- '1'
+ '1',
+ 1024
);
insert into extension_bundle_version_dependency (
@@ -167,7 +169,7 @@
'eb2',
'3',
'NIFI_NAR',
- 'org.apache.nifi',
+ 'com.foo',
'nifi-example-services-nar'
);
@@ -179,7 +181,8 @@
created_by,
description,
sha_256_hex,
- sha_256_supplied
+ sha_256_supplied,
+ content_size
) values (
'eb2-v1',
'eb2',
@@ -188,7 +191,8 @@
'user1',
'First version of eb2',
'123456789',
- '1'
+ '1',
+ 1024
);
insert into extension_bundle_version_dependency (
@@ -246,7 +250,8 @@
created_by,
description,
sha_256_hex,
- sha_256_supplied
+ sha_256_supplied,
+ content_size
) values (
'eb3-v1',
'eb3',
@@ -255,7 +260,8 @@
'user1',
'First version of eb3',
'123456789',
- '1'
+ '1',
+ 1024
);
-- test data for extensions
diff --git a/nifi-registry-core/nifi-registry-provider-api/src/main/java/org/apache/nifi/registry/extension/ExtensionBundlePersistenceProvider.java b/nifi-registry-core/nifi-registry-provider-api/src/main/java/org/apache/nifi/registry/extension/ExtensionBundlePersistenceProvider.java
index 9ef2646..6116d97 100644
--- a/nifi-registry-core/nifi-registry-provider-api/src/main/java/org/apache/nifi/registry/extension/ExtensionBundlePersistenceProvider.java
+++ b/nifi-registry-core/nifi-registry-provider-api/src/main/java/org/apache/nifi/registry/extension/ExtensionBundlePersistenceProvider.java
@@ -31,9 +31,11 @@
*
* @param context the context about the bundle version being persisted
* @param contentStream the stream of binary content to persist
+ * @param overwrite if true the persistence provider should overwrite any content that may already exist for the given bundle version,
+ * if false the persistence provider should throw an ExtensionBundlePersistenceException if content already exists
* @throws ExtensionBundlePersistenceException if an error occurs storing the content
*/
- void saveBundleVersion(ExtensionBundleContext context, InputStream contentStream) throws ExtensionBundlePersistenceException;
+ void saveBundleVersion(ExtensionBundleContext context, InputStream contentStream, boolean overwrite) throws ExtensionBundlePersistenceException;
/**
* Writes the binary content of the bundle specified by the bucket-group-artifact-version to the provided OutputStream.
diff --git a/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/ExtensionRepositoryResource.java b/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/ExtensionRepositoryResource.java
index 46be907..02820db 100644
--- a/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/ExtensionRepositoryResource.java
+++ b/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/ExtensionRepositoryResource.java
@@ -24,10 +24,13 @@
import io.swagger.annotations.Authorization;
import io.swagger.annotations.Extension;
import io.swagger.annotations.ExtensionProperty;
+import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.registry.bucket.Bucket;
-import org.apache.nifi.registry.bucket.BucketItem;
import org.apache.nifi.registry.event.EventService;
+import org.apache.nifi.registry.exception.ResourceNotFoundException;
import org.apache.nifi.registry.extension.ExtensionBundleVersion;
+import org.apache.nifi.registry.extension.ExtensionBundleVersionMetadata;
+import org.apache.nifi.registry.extension.filter.ExtensionBundleVersionFilterParams;
import org.apache.nifi.registry.extension.repo.ExtensionRepoArtifact;
import org.apache.nifi.registry.extension.repo.ExtensionRepoBucket;
import org.apache.nifi.registry.extension.repo.ExtensionRepoGroup;
@@ -97,7 +100,7 @@
final Set<String> authorizedBucketIds = getAuthorizedBucketIds(RequestAction.READ);
if (authorizedBucketIds == null || authorizedBucketIds.isEmpty()) {
// not authorized for any bucket, return empty list of items
- return Response.status(Response.Status.OK).entity(new ArrayList<BucketItem>()).build();
+ return Response.status(Response.Status.OK).entity(new ArrayList<>()).build();
}
final SortedSet<ExtensionRepoBucket> repoBuckets = registryService.getExtensionRepoBuckets(authorizedBucketIds);
@@ -370,5 +373,66 @@
return Response.ok(sha256Hex, MediaType.TEXT_PLAIN).build();
}
+ @GET
+ @Path("{groupId}/{artifactId}/{version}/sha256")
+ @Consumes(MediaType.WILDCARD)
+ @Produces(MediaType.TEXT_PLAIN)
+ @ApiOperation(
+ value = "Gets the hex representation of the SHA-256 digest for the binary content of the version of the extension bundle. Since the " +
+ "same group-artifact-version can exist in multiple buckets, this will return the checksum of the first one returned. This will be " +
+ "consistent since the checksum must be the same when existing in multiple buckets.",
+ response = String.class
+ )
+ @ApiResponses({
+ @ApiResponse(code = 400, message = HttpStatusMessages.MESSAGE_400),
+ @ApiResponse(code = 401, message = HttpStatusMessages.MESSAGE_401),
+ @ApiResponse(code = 403, message = HttpStatusMessages.MESSAGE_403),
+ @ApiResponse(code = 404, message = HttpStatusMessages.MESSAGE_404),
+ @ApiResponse(code = 409, message = HttpStatusMessages.MESSAGE_409) })
+ public Response getExtensionBundleVersionSha256(
+ @PathParam("groupId")
+ @ApiParam("The group identifier")
+ final String groupId,
+ @PathParam("artifactId")
+ @ApiParam("The artifact identifier")
+ final String artifactId,
+ @PathParam("version")
+ @ApiParam("The version")
+ final String version
+ ) {
+ final Set<String> authorizedBucketIds = getAuthorizedBucketIds(RequestAction.READ);
+ if (authorizedBucketIds == null || authorizedBucketIds.isEmpty()) {
+ // not authorized for any bucket, return empty list of items
+ return Response.status(Response.Status.OK).entity(new ArrayList<>()).build();
+ }
+ // Since we are using the filter params which are optional in the service layer, we need to validate these path params here
+
+ if (StringUtils.isBlank(groupId)) {
+ throw new IllegalArgumentException("Group id cannot be null or blank");
+ }
+
+ if (StringUtils.isBlank(artifactId)) {
+ throw new IllegalArgumentException("Artifact id cannot be null or blank");
+ }
+
+ if (StringUtils.isBlank(version)) {
+ throw new IllegalArgumentException("Version cannot be null or blank");
+ }
+
+ final ExtensionBundleVersionFilterParams filterParams = ExtensionBundleVersionFilterParams.of(groupId, artifactId, version);
+
+ final SortedSet<ExtensionBundleVersionMetadata> bundleVersions = registryService.getExtensionBundleVersions(authorizedBucketIds, filterParams);
+ if (bundleVersions.isEmpty()) {
+ throw new ResourceNotFoundException("An extension bundle version does not exist with the specific group, artifact, and version");
+ } else {
+ ExtensionBundleVersionMetadata latestVersionMetadata = null;
+ for (ExtensionBundleVersionMetadata versionMetadata : bundleVersions) {
+ if (latestVersionMetadata == null || versionMetadata.getTimestamp() > latestVersionMetadata.getTimestamp()) {
+ latestVersionMetadata = versionMetadata;
+ }
+ }
+ return Response.ok(latestVersionMetadata.getSha256(), MediaType.TEXT_PLAIN).build();
+ }
+ }
}
diff --git a/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/ExtensionResource.java b/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/ExtensionResource.java
index 62c4c08..d8c1e7a 100644
--- a/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/ExtensionResource.java
+++ b/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/ExtensionResource.java
@@ -25,12 +25,13 @@
import io.swagger.annotations.Extension;
import io.swagger.annotations.ExtensionProperty;
import org.apache.commons.lang3.StringUtils;
-import org.apache.nifi.registry.bucket.BucketItem;
import org.apache.nifi.registry.event.EventFactory;
import org.apache.nifi.registry.event.EventService;
import org.apache.nifi.registry.extension.ExtensionBundle;
import org.apache.nifi.registry.extension.ExtensionBundleVersion;
import org.apache.nifi.registry.extension.ExtensionBundleVersionMetadata;
+import org.apache.nifi.registry.extension.filter.ExtensionBundleFilterParams;
+import org.apache.nifi.registry.extension.filter.ExtensionBundleVersionFilterParams;
import org.apache.nifi.registry.security.authorization.RequestAction;
import org.apache.nifi.registry.service.AuthorizationService;
import org.apache.nifi.registry.service.RegistryService;
@@ -46,6 +47,7 @@
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.StreamingOutput;
@@ -81,6 +83,8 @@
this.permissionsService = permissionsService;
}
+ // ---------- Extension Bundles ----------
+
@GET
@Path("bundles")
@Consumes(MediaType.WILDCARD)
@@ -93,15 +97,25 @@
responseContainer = "List"
)
@ApiResponses({ @ApiResponse(code = 401, message = HttpStatusMessages.MESSAGE_401) })
- public Response getExtensionBundles() {
+ public Response getExtensionBundles(
+ @QueryParam("groupId")
+ @ApiParam("Optional groupId to filter results. The value may be an exact match, or a wildcard, " +
+ "such as 'com.%' to select all bundles where the groupId starts with 'com.'.")
+ final String groupId,
+ @QueryParam("artifactId")
+ @ApiParam("Optional artifactId to filter results. The value may be an exact match, or a wildcard, " +
+ "such as 'nifi-%' to select all bundles where the artifactId starts with 'nifi-'.")
+ final String artifactId) {
final Set<String> authorizedBucketIds = getAuthorizedBucketIds(RequestAction.READ);
if (authorizedBucketIds == null || authorizedBucketIds.isEmpty()) {
// not authorized for any bucket, return empty list of items
- return Response.status(Response.Status.OK).entity(new ArrayList<BucketItem>()).build();
+ return Response.status(Response.Status.OK).entity(new ArrayList<>()).build();
}
- List<ExtensionBundle> bundles = registryService.getExtensionBundles(authorizedBucketIds);
+ final ExtensionBundleFilterParams filterParams = ExtensionBundleFilterParams.of(groupId, artifactId);
+
+ List<ExtensionBundle> bundles = registryService.getExtensionBundles(authorizedBucketIds, filterParams);
if (bundles == null) {
bundles = Collections.emptyList();
}
@@ -180,6 +194,48 @@
return Response.status(Response.Status.OK).entity(deletedExtensionBundle).build();
}
+ // ---------- Extension Bundle Versions ----------
+
+ @GET
+ @Path("bundles/versions")
+ @Consumes(MediaType.WILDCARD)
+ @Produces(MediaType.APPLICATION_JSON)
+ @ApiOperation(
+ value = "Get extension bundles versions across all authorized buckets",
+ notes = "The returned items will include only items from buckets for which the user is authorized. " +
+ "If the user is not authorized to any buckets, an empty list will be returned.",
+ response = ExtensionBundleVersionMetadata.class,
+ responseContainer = "List"
+ )
+ @ApiResponses({ @ApiResponse(code = 401, message = HttpStatusMessages.MESSAGE_401) })
+ public Response getExtensionBundleVersions(
+ @QueryParam("groupId")
+ @ApiParam("Optional groupId to filter results. The value may be an exact match, or a wildcard, " +
+ "such as 'com.%' to select all bundle versions where the groupId starts with 'com.'.")
+ final String groupId,
+ @QueryParam("artifactId")
+ @ApiParam("Optional artifactId to filter results. The value may be an exact match, or a wildcard, " +
+ "such as 'nifi-%' to select all bundle versions where the artifactId starts with 'nifi-'.")
+ final String artifactId,
+ @QueryParam("version")
+ @ApiParam("Optional version to filter results. The value maye be an exact match, or a wildcard, " +
+ "such as '1.0.%' to select all bundle versions where the version starts with '1.0.'.")
+ final String version
+ ) {
+
+ final Set<String> authorizedBucketIds = getAuthorizedBucketIds(RequestAction.READ);
+ if (authorizedBucketIds == null || authorizedBucketIds.isEmpty()) {
+ // not authorized for any bucket, return empty list of items
+ return Response.status(Response.Status.OK).entity(new ArrayList<>()).build();
+ }
+
+ final ExtensionBundleVersionFilterParams filterParams = ExtensionBundleVersionFilterParams.of(groupId, artifactId, version);
+ final SortedSet<ExtensionBundleVersionMetadata> bundleVersions = registryService.getExtensionBundleVersions(authorizedBucketIds, filterParams);
+ linkService.populateLinks(bundleVersions);
+
+ return Response.status(Response.Status.OK).entity(bundleVersions).build();
+ }
+
@GET
@Path("bundles/{bundleId}/versions")
@Consumes(MediaType.WILDCARD)
diff --git a/nifi-registry-core/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/UnsecuredNiFiRegistryClientIT.java b/nifi-registry-core/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/UnsecuredNiFiRegistryClientIT.java
index 2fb2f4a..d5c0cf5 100644
--- a/nifi-registry-core/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/UnsecuredNiFiRegistryClientIT.java
+++ b/nifi-registry-core/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/UnsecuredNiFiRegistryClientIT.java
@@ -41,6 +41,8 @@
import org.apache.nifi.registry.extension.ExtensionBundleVersion;
import org.apache.nifi.registry.extension.ExtensionBundleVersionDependency;
import org.apache.nifi.registry.extension.ExtensionBundleVersionMetadata;
+import org.apache.nifi.registry.extension.filter.ExtensionBundleFilterParams;
+import org.apache.nifi.registry.extension.filter.ExtensionBundleVersionFilterParams;
import org.apache.nifi.registry.extension.repo.ExtensionRepoArtifact;
import org.apache.nifi.registry.extension.repo.ExtensionRepoBucket;
import org.apache.nifi.registry.extension.repo.ExtensionRepoGroup;
@@ -76,6 +78,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
@@ -161,6 +164,7 @@
for (final Bucket bucket : createdBuckets) {
final Bucket retrievedBucket = bucketClient.get(bucket.getIdentifier());
Assert.assertNotNull(retrievedBucket);
+ Assert.assertFalse(retrievedBucket.isAllowExtensionBundleRedeploy());
LOGGER.info("Retrieved bucket " + retrievedBucket.getIdentifier());
}
@@ -328,6 +332,7 @@
Assert.assertEquals(0, allBundles.size());
final Bucket bundlesBucket = createdBuckets.get(1);
+ final Bucket bundlesBucket2 = createdBuckets.get(2);
final ExtensionBundleVersionClient bundleVersionClient = client.getExtensionBundleVersionClient();
// create version 1.0.0 of nifi-test-nar
@@ -358,6 +363,7 @@
Assert.assertEquals(bundlesBucket.getIdentifier(), testNarV1Metadata.getBucketId());
Assert.assertTrue(testNarV1Metadata.getTimestamp() > 0);
Assert.assertFalse(testNarV1Metadata.getSha256Supplied());
+ Assert.assertTrue(testNarV1Metadata.getContentSize() > 1);
final Set<ExtensionBundleVersionDependency> dependencies = createdTestNarV1.getDependencies();
Assert.assertNotNull(dependencies);
@@ -395,10 +401,52 @@
final ExtensionBundle fooNarV1Bundle = createdFooNarV1.getExtensionBundle();
LOGGER.info("Created bundle with id {}", new Object[]{fooNarV1Bundle.getIdentifier()});
+ // verify that bucket 1 currently does not allow redeploying non-snapshot artifacts
+ Assert.assertFalse(bundlesBucket.isAllowExtensionBundleRedeploy());
+
+ // try to re-deploy version 1.0.0 of nifi-foo-nar, should fail
+ try {
+ createExtensionBundleVersionWithFile(bundlesBucket, bundleVersionClient, fooNar, null);
+ Assert.fail("Should have thrown exception when re-deploying foo nar");
+ } catch (Exception e) {
+ // Should throw exception
+ }
+
+ // now update bucket 1 to allow redeploy
+ bundlesBucket.setAllowExtensionBundleRedeploy(true);
+ final Bucket updatedBundlesBucket = bucketClient.update(bundlesBucket);
+ Assert.assertTrue(updatedBundlesBucket.isAllowExtensionBundleRedeploy());
+
+ // try to re-deploy version 1.0.0 of nifi-foo-nar again, this time should work
+ Assert.assertNotNull(createExtensionBundleVersionWithFile(bundlesBucket, bundleVersionClient, fooNar, null));
+
// verify there are 2 bundles now
final List<ExtensionBundle> allBundlesAfterCreate = bundleClient.getAll();
Assert.assertEquals(2, allBundlesAfterCreate.size());
+ // create version 2.0.0-SNAPSHOT (build 1 content) of nifi-foor-nar in the first bucket
+ final String fooNarV2SnapshotB1 = "src/test/resources/extensions/nars/nifi-foo-nar-2.0.0-SNAPSHOT-BUILD1.nar";
+ final ExtensionBundleVersion createdFooNarV2SnapshotB1 = createExtensionBundleVersionWithFile(bundlesBucket, bundleVersionClient, fooNarV2SnapshotB1, null);
+ Assert.assertFalse(createdFooNarV2SnapshotB1.getVersionMetadata().getSha256Supplied());
+
+ // create version 2.0.0-SNAPSHOT (build 2 content) of nifi-foor-nar in the second bucket
+ // proves that snapshots can have different checksums across buckets, non-snapshots can't
+ final String fooNarV2SnapshotB2 = "src/test/resources/extensions/nars/nifi-foo-nar-2.0.0-SNAPSHOT-BUILD2.nar";
+ final ExtensionBundleVersion createdFooNarV2SnapshotB2 = createExtensionBundleVersionWithFile(bundlesBucket2, bundleVersionClient, fooNarV2SnapshotB2, null);
+ Assert.assertFalse(createdFooNarV2SnapshotB2.getVersionMetadata().getSha256Supplied());
+
+ // create version 2.0.0-SNAPSHOT (build 2 content) of nifi-foor-nar in the second bucket
+ // proves that we can overwrite a snapshot in a given bucket
+ final String fooNarV2SnapshotB3 = "src/test/resources/extensions/nars/nifi-foo-nar-2.0.0-SNAPSHOT-BUILD3.nar";
+ final ExtensionBundleVersion createdFooNarV2SnapshotB3 = createExtensionBundleVersionWithFile(bundlesBucket2, bundleVersionClient, fooNarV2SnapshotB3, null);
+ Assert.assertFalse(createdFooNarV2SnapshotB3.getVersionMetadata().getSha256Supplied());
+
+ // verify retrieving nifi-foo-nar 2.0.0-SNAPSHOT from second bucket returns the build 3 content
+ final ExtensionBundleVersion retrievedFooNarV2SnapshotB3 = bundleVersionClient.getBundleVersion(
+ createdFooNarV2SnapshotB3.getVersionMetadata().getExtensionBundleId(),
+ createdFooNarV2SnapshotB3.getVersionMetadata().getVersion());
+ Assert.assertEquals(calculateSha256Hex(fooNarV2SnapshotB3), retrievedFooNarV2SnapshotB3.getVersionMetadata().getSha256());
+
// verify getting bundles by bucket
Assert.assertEquals(2, bundleClient.getByBucket(bundlesBucket.getIdentifier()).size());
Assert.assertEquals(0, bundleClient.getByBucket(flowsBucket.getIdentifier()).size());
@@ -455,6 +503,23 @@
// should catch exception
}
+ // Verify getting bundles with filter params
+ Assert.assertEquals(3, bundleClient.getAll(ExtensionBundleFilterParams.empty()).size());
+
+ final List<ExtensionBundle> filteredBundles = bundleClient.getAll(ExtensionBundleFilterParams.of("org.apache.nifi", "nifi-test-nar"));
+ Assert.assertEquals(1, filteredBundles.size());
+
+ // Verify getting bundle versions with filter params
+ Assert.assertEquals(4, bundleVersionClient.getBundleVersions(ExtensionBundleVersionFilterParams.empty()).size());
+
+ final List<ExtensionBundleVersionMetadata> filteredVersions = bundleVersionClient.getBundleVersions(
+ ExtensionBundleVersionFilterParams.of("org.apache.nifi", "nifi-foo-nar", "1.0.0"));
+ Assert.assertEquals(1, filteredVersions.size());
+
+ final List<ExtensionBundleVersionMetadata> filteredVersions2 = bundleVersionClient.getBundleVersions(
+ ExtensionBundleVersionFilterParams.of("org.apache.nifi", null, null));
+ Assert.assertEquals(4, filteredVersions2.size());
+
// ---------------------- TEST EXTENSION REPO ----------------------//
final ExtensionRepoClient extensionRepoClient = client.getExtensionRepoClient();
@@ -499,10 +564,26 @@
// verify the client methods for content input stream and content sha256
try (final InputStream repoVersionInputStream = extensionRepoClient.getVersionContent(bundlesBucketName, repoGroupId, repoArtifactId, repoVersionString)) {
final String sha256Hex = DigestUtils.sha256Hex(repoVersionInputStream);
+
final String repoSha256Hex = extensionRepoClient.getVersionSha256(bundlesBucketName, repoGroupId, repoArtifactId, repoVersionString);
Assert.assertEquals(sha256Hex, repoSha256Hex);
+
+ final Optional<String> repoSha256HexOptional = extensionRepoClient.getVersionSha256(repoGroupId, repoArtifactId, repoVersionString);
+ Assert.assertTrue(repoSha256HexOptional.isPresent());
+ Assert.assertEquals(sha256Hex, repoSha256HexOptional.get());
}
+ final Optional<String> repoSha256HexDoesNotExist = extensionRepoClient.getVersionSha256(repoGroupId, repoArtifactId, "DOES-NOT-EXIST");
+ Assert.assertFalse(repoSha256HexDoesNotExist.isPresent());
+
+ // since we uploaded two snapshot versions, make sure when we retrieve the sha that it's for the second snapshot that replaced the first
+ final Optional<String> fooNarV2SnapshotLatestSha = extensionRepoClient.getVersionSha256(
+ createdFooNarV2SnapshotB3.getExtensionBundle().getGroupId(),
+ createdFooNarV2SnapshotB3.getExtensionBundle().getArtifactId(),
+ createdFooNarV2SnapshotB2.getVersionMetadata().getVersion());
+ Assert.assertTrue(fooNarV2SnapshotLatestSha.isPresent());
+ Assert.assertEquals(calculateSha256Hex(fooNarV2SnapshotB3), fooNarV2SnapshotLatestSha.get());
+
// ---------------------- TEST ITEMS -------------------------- //
final ItemsClient itemsClient = client.getItemsClient();
@@ -514,7 +595,7 @@
// get all items
final List<BucketItem> allItems = itemsClient.getAll();
- Assert.assertEquals(4, allItems.size());
+ Assert.assertEquals(5, allItems.size());
allItems.stream().forEach(i -> {
Assert.assertNotNull(i.getBucketName());
Assert.assertNotNull(i.getLink());
@@ -527,11 +608,11 @@
.collect(Collectors.toList());
Assert.assertEquals(2, flowItems.size());
- // verify 2 bundle items
+ // verify 3 bundle items
final List<BucketItem> extensionBundleItems = allItems.stream()
.filter(i -> i.getType() == BucketItemType.Extension_Bundle)
.collect(Collectors.toList());
- Assert.assertEquals(2, extensionBundleItems.size());
+ Assert.assertEquals(3, extensionBundleItems.size());
// get items for bucket
final List<BucketItem> bucketItems = itemsClient.getByBucket(flowsBucket.getIdentifier());
diff --git a/nifi-registry-core/nifi-registry-web-api/src/test/resources/extensions/nars/nifi-foo-nar-2.0.0-SNAPSHOT-BUILD1.nar b/nifi-registry-core/nifi-registry-web-api/src/test/resources/extensions/nars/nifi-foo-nar-2.0.0-SNAPSHOT-BUILD1.nar
new file mode 100644
index 0000000..9a0743a
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-web-api/src/test/resources/extensions/nars/nifi-foo-nar-2.0.0-SNAPSHOT-BUILD1.nar
Binary files differ
diff --git a/nifi-registry-core/nifi-registry-web-api/src/test/resources/extensions/nars/nifi-foo-nar-2.0.0-SNAPSHOT-BUILD2.nar b/nifi-registry-core/nifi-registry-web-api/src/test/resources/extensions/nars/nifi-foo-nar-2.0.0-SNAPSHOT-BUILD2.nar
new file mode 100644
index 0000000..d23eb98
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-web-api/src/test/resources/extensions/nars/nifi-foo-nar-2.0.0-SNAPSHOT-BUILD2.nar
Binary files differ
diff --git a/nifi-registry-core/nifi-registry-web-api/src/test/resources/extensions/nars/nifi-foo-nar-2.0.0-SNAPSHOT-BUILD3.nar b/nifi-registry-core/nifi-registry-web-api/src/test/resources/extensions/nars/nifi-foo-nar-2.0.0-SNAPSHOT-BUILD3.nar
new file mode 100644
index 0000000..f114b12
--- /dev/null
+++ b/nifi-registry-core/nifi-registry-web-api/src/test/resources/extensions/nars/nifi-foo-nar-2.0.0-SNAPSHOT-BUILD3.nar
Binary files differ
diff --git a/pom.xml b/pom.xml
index 323c703..25fa752 100644
--- a/pom.xml
+++ b/pom.xml
@@ -94,8 +94,8 @@
<jax.rs.api.version>2.1</jax.rs.api.version>
<jersey.version>2.27</jersey.version>
<jackson.version>2.9.7</jackson.version>
- <spring.boot.version>2.1.0.RELEASE</spring.boot.version>
- <spring.security.version>5.1.1.RELEASE</spring.security.version>
+ <spring.boot.version>2.1.1.RELEASE</spring.boot.version>
+ <spring.security.version>5.1.2.RELEASE</spring.security.version>
<flyway.version>5.2.1</flyway.version>
<flyway.tests.version>5.1.0</flyway.tests.version>
<swagger.ui.version>3.12.0</swagger.ui.version>