This is an automated email from the ASF dual-hosted git repository.

heneveld pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brooklyn-server.git


The following commit(s) were added to refs/heads/master by this push:
     new 05e973ecb3 Adds iconUrl to bundles
     new 4e2fcaa300 Merge remote-tracking branch 'nakomis/bundle-icons'
05e973ecb3 is described below

commit 05e973ecb3e4ff25133cbedc7c4ae8afc2ed4729
Author: Martin Harris <[email protected]>
AuthorDate: Fri Feb 3 13:37:54 2023 +0000

    Adds iconUrl to bundles
---
 .../brooklyn/core/typereg/BasicManagedBundle.java  |  1 +
 .../BrooklynBomYamlCatalogBundleResolver.java      |  7 +++++
 .../org/apache/brooklyn/rest/api/BundleApi.java    | 19 ++++++++++++
 .../brooklyn/rest/resources/BundleResource.java    | 34 +++++++++++++++++++++-
 .../brooklyn/rest/transform/TypeTransformer.java   |  5 ++++
 5 files changed, 65 insertions(+), 1 deletion(-)

diff --git 
a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicManagedBundle.java 
b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicManagedBundle.java
index 826db9a63d..42f7dbd96d 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/typereg/BasicManagedBundle.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/typereg/BasicManagedBundle.java
@@ -96,6 +96,7 @@ public class BasicManagedBundle extends 
AbstractBrooklynObject implements Manage
      */
     public static BasicManagedBundle copyFirstWithCoordsOfSecond(ManagedBundle 
update, ManagedBundle oldOneForCoordinates) {
         BasicManagedBundle result = new 
BasicManagedBundle(oldOneForCoordinates.getId(), update.getSymbolicName(), 
update.getSuppliedVersionString(), update.getUrl(), update.getFormat(), 
update.getUrlCredential(), update.getChecksum(), update.getDeleteable());
+        result.tags().addTags(update.tags().getTags());
         // we have secondary logic which should accept a change in the OSGi 
unique URL,
         // but more efficient if we use the original URL
         result.osgiUniqueUrl = oldOneForCoordinates.getOsgiUniqueUrl();
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynBomYamlCatalogBundleResolver.java
 
b/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynBomYamlCatalogBundleResolver.java
index f4ed4b02aa..aeb726f05b 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynBomYamlCatalogBundleResolver.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/typereg/BrooklynBomYamlCatalogBundleResolver.java
@@ -27,11 +27,13 @@ import java.util.jar.Manifest;
 import java.util.zip.ZipEntry;
 import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog;
 import org.apache.brooklyn.core.config.ConfigUtils;
+import org.apache.brooklyn.core.mgmt.BrooklynTags;
 import org.apache.brooklyn.core.mgmt.ha.OsgiBundleInstallationResult;
 import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.core.osgi.BundleMaker;
 import org.apache.brooklyn.util.exceptions.ReferenceWithError;
+import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.osgi.VersionedName;
 import org.apache.brooklyn.util.stream.InputStreamSource;
 import org.apache.brooklyn.util.stream.Streams;
@@ -133,6 +135,11 @@ public class BrooklynBomYamlCatalogBundleResolver extends 
AbstractCatalogBundleR
             if( cm.containsKey("tags") && cm.get("tags") instanceof Iterable) {
                 basicManagedBundle.tags().addTags((Iterable<?>)cm.get("tags"));
             }
+            // Store the bundleIconUrl as an ICON_URL tag
+            Maybe<String> bundleIconUrl = ConfigUtils.getFirstAs(cm, 
String.class, "bundleIconUrl");
+            if (bundleIconUrl.isPresentAndNonNull()) {
+                
basicManagedBundle.tags().addTag(BrooklynTags.newIconUrlTag(bundleIconUrl.get()));
+            }
             result = 
((ManagementContextInternal)mgmt).getOsgiManager().get().installBrooklynBomBundle(
                     basicManagedBundle, InputStreamSource.of("ZIP generated 
for "+vn+": "+bf, bf), options.isStart(), options.isLoadCatalogBom(), 
options.isForceUpdateOfNonSnapshots(),
                     options.isValidateTypes(), 
options.isDeferredStart()).get();
diff --git 
a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/BundleApi.java 
b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/BundleApi.java
index 7ed018ecf0..033533b5ac 100644
--- a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/BundleApi.java
+++ b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/BundleApi.java
@@ -309,4 +309,23 @@ public interface BundleApi {
             @QueryParam("force") @DefaultValue("false")
                     Boolean force);
 
+    @Path("/{symbolicName}/{version}/icon")
+    @GET
+    @ApiOperation(value = "Gets the icon for a specific bundle given its 
symbolic name and version, if defined",
+            response = BundleSummary.class)
+    @ApiResponses(value = {
+            @ApiResponse(code = 200, message = "OK"),
+            @ApiResponse(code = 400, message = "Bad Request"),
+            @ApiResponse(code = 401, message = "Unauthorized"),
+            @ApiResponse(code = 404, message = "Symbolic name not found"),
+            @ApiResponse(code = 500, message = "Internal Server Error")
+    })
+    public Response getIcon(
+            @ApiParam(name = "symbolicName", value = "Bundle name to query", 
required = true)
+            @PathParam("symbolicName")
+            String symbolicName,
+            @ApiParam(name = "version", value = "Version to query", required = 
true)
+            @PathParam("version")
+            String version);
+
 }
diff --git 
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/BundleResource.java
 
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/BundleResource.java
index b6b3f4e79b..d9dea6693f 100644
--- 
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/BundleResource.java
+++ 
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/BundleResource.java
@@ -20,15 +20,22 @@ package org.apache.brooklyn.rest.resources;
 
 import java.io.File;
 import java.io.IOException;
+import java.net.URI;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.TreeMap;
 
+import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.Response.Status;
 
+import com.google.common.io.Files;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.objs.EntityAdjunct;
 import org.apache.brooklyn.api.typereg.ManagedBundle;
 import org.apache.brooklyn.api.typereg.RegisteredType;
+import org.apache.brooklyn.core.mgmt.BrooklynTags;
 import org.apache.brooklyn.core.mgmt.entitlement.Entitlements;
 import org.apache.brooklyn.core.mgmt.ha.OsgiBundleInstallationResult;
 import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
@@ -47,6 +54,7 @@ import org.apache.brooklyn.rest.filter.HaHotStateRequired;
 import org.apache.brooklyn.rest.transform.TypeTransformer;
 import org.apache.brooklyn.rest.util.WebResourceUtils;
 import org.apache.brooklyn.util.collections.MutableList;
+import org.apache.brooklyn.util.core.ResourceUtils;
 import org.apache.brooklyn.util.exceptions.ReferenceWithError;
 import org.apache.brooklyn.util.io.FileUtil;
 import org.apache.brooklyn.util.osgi.VersionedName;
@@ -255,5 +263,29 @@ public class BundleResource extends 
AbstractBrooklynRestResource implements Bund
         }
         return Response.status(status).entity(resultR).build();
     }
-    
+
+    @Override
+    public Response getIcon(String symbolicName, String version) {
+        ManagedBundle b = lookup(symbolicName, version);
+        final Optional<String> iconUrl = 
Optional.ofNullable(BrooklynTags.findFirstNamedStringTag(BrooklynTags.ICON_URL, 
b.tags().getTags()))
+                .map(BrooklynTags.NamedStringTag::getContents);
+
+        if (!iconUrl.isPresent())
+            return 
Response.status(javax.ws.rs.core.Response.Status.NO_CONTENT).build();
+
+        String url = iconUrl.get();
+
+        if (brooklyn().isUrlServerSideAndSafe(url)) {
+            // classpath URL's we will serve IF they end with a recognised 
image format;
+            // paths (ie non-protocol) and
+            // NB, for security, file URL's are NOT served
+            MediaType mime = 
WebResourceUtils.getImageMediaTypeFromExtension(Files.getFileExtension(url));
+            Object content = ResourceUtils.create(b).getResourceFromUrl(url);
+            return Response.ok(content, mime).build();
+        }
+
+        // for anything else we do a redirect (e.g. http / https; perhaps ftp)
+        return Response.temporaryRedirect(URI.create(url)).build();
+    }
+
 }
diff --git 
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/transform/TypeTransformer.java
 
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/transform/TypeTransformer.java
index 573da6615a..0b522a4553 100644
--- 
a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/transform/TypeTransformer.java
+++ 
b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/transform/TypeTransformer.java
@@ -205,6 +205,11 @@ public class TypeTransformer {
                 result.addType(summary(brooklyn, t, baseUriBuilder));
             }
         }
+        Optional<String> iconUrl = 
Optional.ofNullable(BrooklynTags.findFirstNamedStringTag(BrooklynTags.ICON_URL, 
b.tags().getTags()))
+                .map(BrooklynTags.NamedStringTag::getContents);
+        if (iconUrl.isPresent()) {
+            result.setExtraField("iconUrl", serviceUriBuilder(baseUriBuilder, 
BundleApi.class, "getIcon").build(b.getSymbolicName(), 
b.getOsgiVersionString()));
+        }
         return result;
     }
     

Reply via email to