Repository: nifi-registry
Updated Branches:
  refs/heads/master f1e5aef7b -> ce405b576


http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/ce405b57/nifi-registry-core/nifi-registry-framework/src/test/resources/db/migration/V999999.1__test-setup.sql
----------------------------------------------------------------------
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 @@ insert into extension_bundle_version (
   created_by,
   description,
   sha_256_hex,
-  sha_256_supplied
+  sha_256_supplied,
+  content_size
 ) values (
   'eb1-v1',
   'eb1',
@@ -121,7 +122,8 @@ insert into extension_bundle_version (
   'user1',
   'First version of eb1',
   '123456789',
-  '1'
+  '1',
+  1024
 );
 
 insert into extension_bundle_version_dependency (
@@ -167,7 +169,7 @@ insert into extension_bundle (
   'eb2',
   '3',
   'NIFI_NAR',
-  'org.apache.nifi',
+  'com.foo',
   'nifi-example-services-nar'
 );
 
@@ -179,7 +181,8 @@ insert into extension_bundle_version (
   created_by,
   description,
   sha_256_hex,
-  sha_256_supplied
+  sha_256_supplied,
+  content_size
 ) values (
   'eb2-v1',
   'eb2',
@@ -188,7 +191,8 @@ insert into extension_bundle_version (
   'user1',
   'First version of eb2',
   '123456789',
-  '1'
+  '1',
+  1024
 );
 
 insert into extension_bundle_version_dependency (
@@ -246,7 +250,8 @@ insert into extension_bundle_version (
   created_by,
   description,
   sha_256_hex,
-  sha_256_supplied
+  sha_256_supplied,
+  content_size
 ) values (
   'eb3-v1',
   'eb3',
@@ -255,7 +260,8 @@ insert into extension_bundle_version (
   'user1',
   'First version of eb3',
   '123456789',
-  '1'
+  '1',
+  1024
 );
 
 -- test data for extensions

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/ce405b57/nifi-registry-core/nifi-registry-provider-api/src/main/java/org/apache/nifi/registry/extension/ExtensionBundlePersistenceProvider.java
----------------------------------------------------------------------
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 @@ public interface ExtensionBundlePersistenceProvider extends 
Provider {
      *
      * @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.

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/ce405b57/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/ExtensionRepositoryResource.java
----------------------------------------------------------------------
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.ApiResponses;
 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 @@ public class ExtensionRepositoryResource extends 
AuthorizableApplicationResource
         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 @@ public class ExtensionRepositoryResource extends 
AuthorizableApplicationResource
         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();
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/ce405b57/nifi-registry-core/nifi-registry-web-api/src/main/java/org/apache/nifi/registry/web/api/ExtensionResource.java
----------------------------------------------------------------------
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.Authorization;
 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.GET;
 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 @@ public class ExtensionResource extends 
AuthorizableApplicationResource {
         this.permissionsService = permissionsService;
     }
 
+    // ---------- Extension Bundles ----------
+
     @GET
     @Path("bundles")
     @Consumes(MediaType.WILDCARD)
@@ -93,15 +97,25 @@ public class ExtensionResource extends 
AuthorizableApplicationResource {
             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 @@ public class ExtensionResource extends 
AuthorizableApplicationResource {
         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)

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/ce405b57/nifi-registry-core/nifi-registry-web-api/src/test/java/org/apache/nifi/registry/web/api/UnsecuredNiFiRegistryClientIT.java
----------------------------------------------------------------------
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.ExtensionBundleType;
 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.ArrayList;
 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 @@ public class UnsecuredNiFiRegistryClientIT extends 
UnsecuredITBase {
         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 @@ public class UnsecuredNiFiRegistryClientIT extends 
UnsecuredITBase {
         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 @@ public class UnsecuredNiFiRegistryClientIT extends 
UnsecuredITBase {
         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 @@ public class UnsecuredNiFiRegistryClientIT extends 
UnsecuredITBase {
         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 @@ public class UnsecuredNiFiRegistryClientIT extends 
UnsecuredITBase {
             // 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 @@ public class UnsecuredNiFiRegistryClientIT extends 
UnsecuredITBase {
         // 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 @@ public class UnsecuredNiFiRegistryClientIT extends 
UnsecuredITBase {
 
         // 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 @@ public class UnsecuredNiFiRegistryClientIT extends 
UnsecuredITBase {
                 .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());

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/ce405b57/nifi-registry-core/nifi-registry-web-api/src/test/resources/extensions/nars/nifi-foo-nar-2.0.0-SNAPSHOT-BUILD1.nar
----------------------------------------------------------------------
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
Binary files /dev/null and 
b/nifi-registry-core/nifi-registry-web-api/src/test/resources/extensions/nars/nifi-foo-nar-2.0.0-SNAPSHOT-BUILD1.nar
 differ

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/ce405b57/nifi-registry-core/nifi-registry-web-api/src/test/resources/extensions/nars/nifi-foo-nar-2.0.0-SNAPSHOT-BUILD2.nar
----------------------------------------------------------------------
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
Binary files /dev/null and 
b/nifi-registry-core/nifi-registry-web-api/src/test/resources/extensions/nars/nifi-foo-nar-2.0.0-SNAPSHOT-BUILD2.nar
 differ

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/ce405b57/nifi-registry-core/nifi-registry-web-api/src/test/resources/extensions/nars/nifi-foo-nar-2.0.0-SNAPSHOT-BUILD3.nar
----------------------------------------------------------------------
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
Binary files /dev/null and 
b/nifi-registry-core/nifi-registry-web-api/src/test/resources/extensions/nars/nifi-foo-nar-2.0.0-SNAPSHOT-BUILD3.nar
 differ

http://git-wip-us.apache.org/repos/asf/nifi-registry/blob/ce405b57/pom.xml
----------------------------------------------------------------------
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>

Reply via email to