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
commit b86c57e062c8a393d1ea2840a47d4e2f06e67a12 Author: Alex Heneveld <[email protected]> AuthorDate: Fri Oct 9 10:50:32 2020 +0100 rest api for bundle/catalog add now accepts format and includes more details for legacy compatibility --- .../org/apache/brooklyn/rest/api/BundleApi.java | 52 ++++++---- .../org/apache/brooklyn/rest/api/CatalogApi.java | 109 ++++++++++----------- .../brooklyn/rest/resources/BundleResource.java | 32 +++--- .../brooklyn/rest/resources/CatalogResource.java | 70 +++---------- .../brooklyn/rest/transform/TypeTransformer.java | 43 +++++--- 5 files changed, 143 insertions(+), 163 deletions(-) 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 2296fe3..33fa6f5 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 @@ -151,18 +151,11 @@ public interface BundleApi { @QueryParam("force") @DefaultValue("false") Boolean force); + /** @deprecated since 1.1 use {@link #create(byte[], String, Boolean)} instead */ + @Deprecated @POST - @Consumes({MediaType.APPLICATION_JSON, "application/x-yaml", - // see http://stackoverflow.com/questions/332129/yaml-mime-type - "text/yaml", "text/x-yaml", "application/yaml"}) - @ApiOperation( - value = "Adds types to the registry from a given BOM YAML/JSON descriptor (creating a bundle with just this file in it)", - response = BundleInstallationRestResult.class - ) - @ApiResponses(value = { - @ApiResponse(code = 400, message = "Error processing the given YAML"), - @ApiResponse(code = 201, message = "Items added successfully") - }) + @Consumes("application/deprecated-yaml") + @ApiOperation(value = "(deprecated)", hidden = true) public Response createFromYaml( @ApiParam(name = "yaml", value = "BOM YAML declaring the types to be installed", required = true) @Valid String yaml, @@ -170,25 +163,46 @@ public interface BundleApi { @QueryParam("force") @DefaultValue("false") Boolean forceUpdate); + /** @deprecated since 1.1 use {@link #create(byte[], String, Boolean)} instead */ + @Deprecated + @POST + @Consumes({"application/deprecated-zip"}) + @ApiOperation(value = "(deprecated)", hidden = true) + public Response createFromArchive( + @ApiParam( + name = "archive", + value = "Bundle to install, in ZIP or JAR format, requiring catalog.bom containing bundle name and version", + required = true) + byte[] archive, + @ApiParam(name = "force", value = "Whether to forcibly remove it, even if in use and/or errors", required = false, defaultValue = "false") + @QueryParam("force") @DefaultValue("false") + Boolean force); + + /** @deprecated since 1.1 use {@link #create(byte[], String, Boolean)} instead */ + @Deprecated @POST - @Consumes({"application/x-zip", "application/x-jar"}) + @Consumes // anything - now autodetect is done for everything unless 'format' is specified + // (mime type is ignored; though it could be useful in the "score" function, and probably is available on the thread) @ApiOperation( - value = "Adds types to the registry from a given JAR or ZIP", - notes = "Accepts either an OSGi bundle JAR, or ZIP which will be turned into bundle JAR. Either format must " - + "contain a catalog.bom at the root of the archive, which must contain the bundle and version key.", + value = "Add a bundle of types (entities, etc) to the type registry", + notes = "This will auto-detect the format, with the 'brooklyn-bom-bundle' being common and consisting of " + + "a ZIP/JAR containing a catalog.bom", response = BundleInstallationRestResult.class) @ApiResponses(value = { @ApiResponse(code = 400, message = "Error processing the given archive, or the catalog.bom is invalid"), @ApiResponse(code = 201, message = "Catalog items added successfully") }) - public Response createFromArchive( + public Response create( @ApiParam( name = "archive", - value = "Bundle to install, in ZIP or JAR format, requiring catalog.bom containing bundle name and version", + value = "Bundle contents to install, eg for brooklyn-catalog-bundle a ZIP or JAR containing a catalog.bom file", required = true) - byte[] archive, + byte[] archive, + @ApiParam(name = "format", value="Specify the format to indicate a specific resolver for handling this", required=false) + @QueryParam("format") @DefaultValue("") + String format, @ApiParam(name = "force", value = "Whether to forcibly remove it, even if in use and/or errors", required = false, defaultValue = "false") @QueryParam("force") @DefaultValue("false") - Boolean force); + Boolean force); } diff --git a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/CatalogApi.java b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/CatalogApi.java index 94de80e..3d7a908 100644 --- a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/CatalogApi.java +++ b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/CatalogApi.java @@ -53,38 +53,20 @@ import io.swagger.annotations.ApiResponses; @Produces(MediaType.APPLICATION_JSON) public interface CatalogApi { - /** @deprecated since 0.11.0 use {@link #createFromYaml(String)} instead */ + /** @deprecated since 0.11.0 use {@link #createFromYaml(String, boolean)} instead */ @Deprecated - @Consumes("application/json-deprecated") // prevent this from taking things + @Consumes("application/deprecated-yaml-old") // prevent this from taking things @POST - @ApiOperation( - value = "Add a catalog items (e.g. new type of entity, policy or location) by uploading YAML descriptor (deprecated, use POST of yaml or ZIP/JAR instead)", - notes = "Return value is map of ID to CatalogItemSummary.", - response = String.class, - hidden = true - ) - @ApiResponses(value = { - @ApiResponse(code = 400, message = "Error processing the given YAML"), - @ApiResponse(code = 201, message = "Catalog items added successfully") - }) + @ApiOperation(value = "(deprecated)", hidden = true) public Response create(String yaml, @ApiParam(name="forceUpdate", value="Force update of catalog item (overwriting existing catalog items with same name and version)") @QueryParam("forceUpdate") @DefaultValue("false") boolean forceUpdate); + /** @deprecated since 1.1 use {@link #create(byte[], String, boolean, boolean, boolean)} instead */ + @Deprecated @POST - @Consumes({MediaType.APPLICATION_JSON, "application/x-yaml", - // see http://stackoverflow.com/questions/332129/yaml-mime-type - "text/yaml", "text/x-yaml", "application/yaml"}) - @ApiOperation( - value = "Add a catalog items (e.g. new type of entity, policy or location) by uploading YAML descriptor.", - notes = "Return value is map of ID to CatalogItemSummary.", - response = String.class, - hidden = true - ) - @ApiResponses(value = { - @ApiResponse(code = 400, message = "Error processing the given YAML"), - @ApiResponse(code = 201, message = "Catalog items added successfully") - }) + @Consumes("application/deprecated-yaml") + @ApiOperation(value = "(deprecated)", hidden = true) public Response createFromYaml( @ApiParam(name = "yaml", value = "YAML descriptor of catalog item", required = true) @Valid String yaml, @@ -92,29 +74,11 @@ public interface CatalogApi { @QueryParam("forceUpdate") @DefaultValue("false") boolean forceUpdate); - @Beta - /* TODO the polymorphic return type dependent on 'detail' is ugly, - * but we're stuck in this API because backwards compatibility expects the types map - * whereas typical usage wants more feedback. we should introduce a - * /registry and/or /types and/or /bundles endpoint that always provides details - * (and an approach to handling types more aligned with BrooklynTypeRegistry and OSGi bundling). - * Not too concerned here as this method is beta and the above switch will probably naturally happen soon. - * The main client who cares about this is the Go CLI. */ + /** @deprecated since 1.1 use {@link #create(byte[], String, boolean, boolean, boolean)} instead */ + @Deprecated @POST - @Consumes({"application/x-zip", "application/x-jar"}) - @ApiOperation( - value = "Add a catalog items (e.g. new type of entity, policy or location) by uploading a ZIP/JAR archive.", - notes = "Accepts either an OSGi bundle JAR, or ZIP which will be turned into bundle JAR. Bother format must " - + "contain a catalog.bom at the root of the archive, which must contain the bundle and version key." - + "Return value is map of ID to CatalogItemSummary unless detail=true is passed as a parameter in which " - + "case the return value is a BundleInstallationRestResult map containing the types map in types along " - + "with a message, bundle, and code.", - response = String.class, - hidden = true) - @ApiResponses(value = { - @ApiResponse(code = 400, message = "Error processing the given archive, or the catalog.bom is invalid"), - @ApiResponse(code = 201, message = "Catalog items added successfully") - }) + @Consumes("application/deprecated-x-zip") + @ApiOperation(value = "(deprecated)", hidden = true) public Response createFromArchive( @ApiParam( name = "archive", @@ -129,26 +93,53 @@ public interface CatalogApi { boolean forceUpdate); @Beta + /** @deprecated since 1.1 use {@link #create(byte[], String, boolean, boolean, boolean)} instead */ + @Deprecated @POST - @Consumes // anything (if doesn't match other methods with specific content types + @Consumes("application/deprecated-autodetect") + @ApiOperation(value = "(deprecated)", hidden = true) + public Response createFromUpload( + @ApiParam( + name = "item", + value = "Item to install, as JAR/ZIP or Catalog YAML (autodetected)", + required = true) + byte[] item, + @ApiParam(name="forceUpdate", value="Force update of catalog item (overwriting existing catalog items with same name and version)") + @QueryParam("forceUpdate") @DefaultValue("false") + boolean forceUpdate); + + // the /bundles endpoint is preferred and things (Go client and UI) should be switched to use it exclusively + @Beta + @POST + @Consumes // anything - now autodetect is done for everything unless 'format' is specified + // (mime type is ignored; though it could be useful in the "score" function, and probably is available on the thread) @ApiOperation( - value = "Add a catalog items (e.g. new type of entity, policy or location) by uploading either YAML or ZIP/JAR archive (format autodetected)", - notes = "Specify a content-type header to skip auto-detection and invoke one of the more specific methods. " - + "Accepts either an OSGi bundle JAR, or ZIP which will be turned into bundle JAR. Bother format must " - + "contain a catalog.bom at the root of the archive, which must contain the bundle and version key." - + "Return value is map of ID to CatalogItemSummary.", - response = String.class - ) + value = "Add a bundle of types (entities, etc) to the type registry (catalog)", + notes = "This will auto-detect the format, with the 'brooklyn-bom-bundle' being common and consisting of " + + "a ZIP/JAR containing a catalog.bom. " + + "Return value is map of ID to CatalogItemSummary unless detail=true is passed as a parameter in which " + + "case the return value is a BundleInstallationRestResult map containing the types map in types along " + + "with a message, bundle, and code.", + response = String.class) @ApiResponses(value = { @ApiResponse(code = 400, message = "Error processing the given archive, or the catalog.bom is invalid"), @ApiResponse(code = 201, message = "Catalog items added successfully") }) - public Response createFromUpload( + public Response create( @ApiParam( - name = "item", - value = "Item to install, as JAR/ZIP or Catalog YAML (autodetected)", + name = "bundle", + value = "Bundle contents to install, eg for brooklyn-catalog-bundle a ZIP or JAR containing a catalog.bom file", required = true) - byte[] item, + byte[] archive, + @ApiParam(name="format", value="Specify the format to indicate a specific resolver for handling this", required=false) + @QueryParam("format") @DefaultValue("") + String format, + @ApiParam(name="detail", value="Provide a wrapping details map (false for backwards compatibility, but true is recommended for migration to bundle API)", required=false) + @QueryParam("detail") @DefaultValue("false") + boolean detail, + @ApiParam(name="itemDetails", value="Include legacy item details in the map of types (true for backwards compatibility, but false is recommended for migration to bundle API)", required=false) + @QueryParam("itemDetails") @DefaultValue("true") + boolean itemDetails, @ApiParam(name="forceUpdate", value="Force update of catalog item (overwriting existing catalog items with same name and version)") @QueryParam("forceUpdate") @DefaultValue("false") boolean forceUpdate); 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 33bc162..b2dd7d8 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 @@ -32,6 +32,8 @@ import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog; import org.apache.brooklyn.core.mgmt.entitlement.Entitlements; import org.apache.brooklyn.core.mgmt.ha.OsgiBundleInstallationResult; import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal; +import org.apache.brooklyn.core.typereg.BrooklynBomBundleCatalogBundleResolver; +import org.apache.brooklyn.core.typereg.BrooklynBomYamlCatalogBundleResolver; import org.apache.brooklyn.core.typereg.RegisteredTypePredicates; import org.apache.brooklyn.core.typereg.RegisteredTypes; import org.apache.brooklyn.rest.api.BundleApi; @@ -167,34 +169,26 @@ public class BundleResource extends AbstractBrooklynRestResource implements Bund } - @Override + @Override @Deprecated public Response createFromYaml(String yaml, Boolean force) { - if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.ADD_CATALOG_ITEM, yaml)) { - throw WebResourceUtils.forbidden("User '%s' is not authorized to add catalog items", - Entitlements.getEntitlementContext().user()); - } - if (force==null) force = false; - - try { - return Response.status(Status.CREATED).entity( - TypeTransformer.bundleInstallationResult( - ((BasicBrooklynCatalog)brooklyn().getCatalog()).addItemsBundleResult(yaml, force), mgmt(), brooklyn(), ui)).build(); - } catch (Exception e) { - Exceptions.propagateIfFatal(e); - return badRequest(e); - } + return create(yaml.getBytes(), BrooklynBomYamlCatalogBundleResolver.FORMAT, force); } - @Override + @Override @Deprecated public Response createFromArchive(byte[] zipInput, Boolean force) { + return create(zipInput, BrooklynBomBundleCatalogBundleResolver.FORMAT, force); + } + + @Override @Deprecated + public Response create(byte[] contents, String format, Boolean force) { if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.ROOT, null)) { throw WebResourceUtils.forbidden("User '%s' is not authorized to add catalog items", - Entitlements.getEntitlementContext().user()); + Entitlements.getEntitlementContext().user()); } if (force==null) force = false; ReferenceWithError<OsgiBundleInstallationResult> result = ((ManagementContextInternal)mgmt()).getOsgiManager().get() - .install(InputStreamSource.of("REST bundle upload", zipInput), null, force); + .install(InputStreamSource.of("REST bundle upload", contents), format, force); if (result.hasError()) { // (rollback already done as part of install, if necessary) @@ -206,7 +200,7 @@ public class BundleResource extends AbstractBrooklynRestResource implements Bund error = error.message(result.getWithoutError().getMessage()) .data(TypeTransformer.bundleInstallationResult(result.getWithoutError(), mgmt(), brooklyn(), ui)); } else { - error.message(result.getError().getMessage()); + error.message(Strings.isNonBlank(result.getError().getMessage()) ? result.getError().getMessage() : result.getError().toString()); } return error.build().asJsonResponse(); } diff --git a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java index 43d0c18..0afbc6f 100644 --- a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java +++ b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/CatalogResource.java @@ -24,7 +24,6 @@ import java.net.URI; import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import java.util.Map; import java.util.Set; import javax.annotation.Nullable; @@ -34,13 +33,13 @@ import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.UriInfo; -import org.apache.brooklyn.api.catalog.CatalogItem; import org.apache.brooklyn.api.typereg.RegisteredType; import org.apache.brooklyn.core.catalog.internal.CatalogUtils; import org.apache.brooklyn.core.mgmt.entitlement.Entitlements; import org.apache.brooklyn.core.mgmt.entitlement.Entitlements.StringAndArgument; import org.apache.brooklyn.core.mgmt.ha.OsgiBundleInstallationResult; import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal; +import org.apache.brooklyn.core.typereg.BrooklynBomYamlCatalogBundleResolver; import org.apache.brooklyn.core.typereg.RegisteredTypePredicates; import org.apache.brooklyn.core.typereg.RegisteredTypes; import org.apache.brooklyn.rest.api.CatalogApi; @@ -57,7 +56,6 @@ import org.apache.brooklyn.rest.transform.CatalogTransformer; 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.collections.MutableMap; import org.apache.brooklyn.util.collections.MutableSet; import org.apache.brooklyn.util.core.ResourceUtils; import org.apache.brooklyn.util.exceptions.Exceptions; @@ -105,8 +103,7 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat static Set<String> missingIcons = MutableSet.of(); - @Override - @Beta + @Override @Deprecated @Beta public Response createFromUpload(byte[] item, boolean forceUpdate) { Throwable yamlException = null; try { @@ -124,61 +121,48 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat return createFromArchive(item, false, forceUpdate); } - @Override - @Deprecated + @Override @Deprecated public Response create(String yaml, boolean forceUpdate) { return createFromYaml(yaml, forceUpdate); } - @SuppressWarnings("deprecation") - @Override + @Override @Deprecated public Response createFromYaml(String yaml, boolean forceUpdate) { - if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.ADD_CATALOG_ITEM, yaml)) { - throw WebResourceUtils.forbidden("User '%s' is not authorized to add catalog item", - Entitlements.getEntitlementContext().user()); - } + return create(yaml.getBytes(), BrooklynBomYamlCatalogBundleResolver.FORMAT, false, true, forceUpdate); + } - try { - final Iterable<? extends CatalogItem<?, ?>> items = brooklyn().getCatalog().addItems(yaml, true, forceUpdate); - List<RegisteredType> itemsRT = MutableList.of(); - for (CatalogItem<?, ?> ci: items) { - RegisteredType rt = brooklyn().getTypeRegistry().get(ci.getId()); - itemsRT.add(rt!=null ? rt : RegisteredTypes.of(ci)); - } - return buildCreateResponse(itemsRT); - } catch (Exception e) { - Exceptions.propagateIfFatal(e); - return badRequest(e); - } + @Override @Deprecated @Beta + public Response createFromArchive(byte[] zipInput, boolean detail, boolean forceUpdate) { + return create(zipInput, "", detail, false, forceUpdate); } @Override - @Beta - public Response createFromArchive(byte[] zipInput, boolean detail, boolean forceUpdate) { + public Response create(byte[] archive, String format, boolean detail, boolean itemDetails, boolean forceUpdate) { if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.ROOT, null)) { throw WebResourceUtils.forbidden("User '%s' is not authorized to add catalog item", - Entitlements.getEntitlementContext().user()); + Entitlements.getEntitlementContext().user()); } ReferenceWithError<OsgiBundleInstallationResult> result = ((ManagementContextInternal)mgmt()).getOsgiManager().get() - .install(InputStreamSource.of("REST bundle upload", zipInput), null, forceUpdate); + .install(InputStreamSource.of("REST bundle upload", archive), format, forceUpdate); if (result.hasError()) { // (rollback already done as part of install, if necessary) if (log.isTraceEnabled()) { - log.trace("Unable to create from archive, returning 400: "+result.getError().getMessage(), result.getError()); + log.trace("Unable to create, format '"+format+"', returning 400: "+result.getError().getMessage(), result.getError()); } Builder error = ApiError.builder().errorCode(Status.BAD_REQUEST); if (result.getWithoutError()!=null) { error = error.message(result.getWithoutError().getMessage()) .data(TypeTransformer.bundleInstallationResult(result.getWithoutError(), mgmt(), brooklyn(), ui)); } else { - error.message(result.getError().getMessage()); + error.message(Strings.isNonBlank(result.getError().getMessage()) ? result.getError().getMessage() : result.getError().toString()); } return error.build().asJsonResponse(); } - BundleInstallationRestResult resultR = TypeTransformer.bundleInstallationResult(result.get(), mgmt(), brooklyn(), ui); + BundleInstallationRestResult resultR = itemDetails ? TypeTransformer.bundleInstallationResultLegacyItemDetails(result.get(), mgmt(), brooklyn(), ui) + : TypeTransformer.bundleInstallationResult(result.get(), mgmt(), brooklyn(), ui); Status status; switch (result.get().getCode()) { case IGNORING_BUNDLE_AREADY_INSTALLED: @@ -193,28 +177,6 @@ public class CatalogResource extends AbstractBrooklynRestResource implements Cat return Response.status(status).entity( detail ? resultR : resultR.getTypes() ).build(); } - private Response buildCreateResponse(Iterable<RegisteredType> catalogItems) { - log.info("REST created catalog items: "+catalogItems); - - Map<String,Object> result = MutableMap.of(); - - for (RegisteredType catalogItem: catalogItems) { - try { - result.put( - catalogItem.getId(), - CatalogTransformer.catalogItemSummary(brooklyn(), catalogItem, ui.getBaseUriBuilder())); - } catch (Throwable t) { - log.warn("Error loading catalog item '"+catalogItem+"' (rethrowing): "+t); - // unfortunately items are already added to the catalog and hard to remove, - // but at least let the user know; - // happens eg if a class refers to a missing class, like - // loading nosql items including mongo without the mongo bson class on the classpath - throw Exceptions.propagateAnnotated("At least one unusable item was added ("+catalogItem.getId()+")", t); - } - } - return Response.status(Status.CREATED).entity(result).build(); - } - @Override @Deprecated public void deleteApplication(String symbolicName, String version) throws Exception { 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 0efcbe8..294745f 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 @@ -74,14 +74,18 @@ public class TypeTransformer { private static final org.slf4j.Logger log = LoggerFactory.getLogger(TypeTransformer.class); public static <T extends Entity> TypeSummary summary(BrooklynRestResourceUtils b, RegisteredType item, UriBuilder ub) { - return embellish(new TypeSummary(item), item, false, b, ub); + return embellish(new TypeSummary(item), item, false, false, b, ub); } public static TypeDetail detail(BrooklynRestResourceUtils b, RegisteredType item, UriBuilder ub) { - return embellish(new TypeDetail(item), item, true, b, ub); + return embellish(new TypeDetail(item), item, true, false, b, ub); } - private static <T extends TypeSummary> T embellish(T result, RegisteredType item, boolean detail, BrooklynRestResourceUtils b, UriBuilder ub) { + public static TypeDetail detailIncludingLegacyItemFields(BrooklynRestResourceUtils b, RegisteredType item, UriBuilder ub) { + return embellish(new TypeDetail(item), item, true, true, b, ub); + } + + private static <T extends TypeSummary> T embellish(T result, RegisteredType item, boolean detail, boolean legacyDetailFields, BrooklynRestResourceUtils b, UriBuilder ub) { result.setExtraField("links", makeLinks(item, ub)); if (RegisteredTypes.isTemplate(item)) { @@ -101,27 +105,32 @@ public class TypeTransformer { } else if (RegisteredTypes.isSubtypeOf(item, EntityAdjunct.class) || // when implied supertypes are used we won't need the code below RegisteredTypes.isSubtypeOf(item, Policy.class) || RegisteredTypes.isSubtypeOf(item, Enricher.class) || RegisteredTypes.isSubtypeOf(item, Feed.class) - ) { + ) { try { Set<ConfigSummary> config = Sets.newLinkedHashSet(); - - AbstractBrooklynObjectSpec<?,?> spec = b.getTypeRegistry().createSpec(item, null, null); + + AbstractBrooklynObjectSpec<?, ?> spec = b.getTypeRegistry().createSpec(item, null, null); AtomicInteger priority = new AtomicInteger(0); - for (final SpecParameter<?> input : spec.getParameters()){ + for (final SpecParameter<?> input : spec.getParameters()) { config.add(ConfigTransformer.of(input).uiIncrementAndSetPriorityIfPinned(priority).transform()); } - + result.setExtraField("config", config); } catch (Exception e) { Exceptions.propagateIfFatal(e); - log.trace("Unable to create spec for "+item+": "+e, e); + log.trace("Unable to create spec for " + item + ": " + e, e); } - + } else if (RegisteredTypes.isSubtypeOf(item, Location.class)) { // TODO include config on location specs? (wasn't done previously so not needed, but good for completeness) - result.setExtraField("config", Collections.emptyMap()); + result.setExtraField("config", Collections.emptySet()); } } + if (legacyDetailFields) { + // for legacy compatibility + result.setExtraField("planYaml", item.getPlan()==null ? null : item.getPlan().getPlanData()); + result.setExtraField("name", item.getDisplayName()); + } return result; } @@ -183,7 +192,7 @@ public class TypeTransformer { public static BundleInstallationRestResult bundleInstallationResult(OsgiBundleInstallationResult in, ManagementContext mgmt, BrooklynRestResourceUtils brooklynU, UriInfo ui) { BundleInstallationRestResult result = new BundleInstallationRestResult( - in.getMessage(), in.getVersionedName() != null ? in.getVersionedName().toString() : "", in.getCode()); + in.getMessage(), in.getVersionedName() != null ? in.getVersionedName().toString() : "", in.getCode()); for (RegisteredType t: in.getTypesInstalled()) { TypeSummary summary = TypeTransformer.summary(brooklynU, t, ui.getBaseUriBuilder()); result.getTypes().put(t.getId(), summary); @@ -191,6 +200,16 @@ public class TypeTransformer { return result; } + public static BundleInstallationRestResult bundleInstallationResultLegacyItemDetails(OsgiBundleInstallationResult in, ManagementContext mgmt, BrooklynRestResourceUtils brooklynU, UriInfo ui) { + BundleInstallationRestResult result = new BundleInstallationRestResult( + in.getMessage(), in.getVersionedName() != null ? in.getVersionedName().toString() : "", in.getCode()); + for (RegisteredType t: in.getTypesInstalled()) { + TypeSummary summary = TypeTransformer.detailIncludingLegacyItemFields(brooklynU, t, ui.getBaseUriBuilder()); + result.getTypes().put(t.getId(), summary); + } + return result; + } + protected static Map<String, URI> makeLinks(RegisteredType item, UriBuilder ub) { return MutableMap.<String, URI>of().addIfNotNull("self", getSelfLink(item, ub)); }
