Merge branch 'master' into adjunct-rest-2 Big changes to config key construction, following on from previous deprecation
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/62bcbc5f Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/62bcbc5f Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/62bcbc5f Branch: refs/heads/master Commit: 62bcbc5f4b7695420b026952ce6ae7f180dcaec6 Parents: 45261c7 df83d44 Author: Alex Heneveld <[email protected]> Authored: Mon Sep 25 11:29:45 2017 +0100 Committer: Alex Heneveld <[email protected]> Committed: Mon Sep 25 11:29:45 2017 +0100 ---------------------------------------------------------------------- api/pom.xml | 2 +- .../brooklyn/api/catalog/BrooklynCatalog.java | 4 + .../brooklyn/api/typereg/RegisteredType.java | 5 +- camp/camp-base/pom.xml | 2 +- camp/camp-brooklyn/pom.xml | 2 +- .../camp/brooklyn/AbstractYamlTest.java | 31 +- .../brooklyn/EmptySoftwareProcessYamlTest.java | 94 +- .../camp/brooklyn/FunctionSensorYamlTest.java | 123 ++ .../VanillaSoftwareProcessYamlTest.java | 299 +++++ .../CatalogOsgiVersionMoreEntityRebindTest.java | 10 +- .../CatalogOsgiVersionMoreEntityTest.java | 3 + .../java-web-app-and-db-with-function-2.yaml | 9 +- .../java-web-app-and-db-with-function.yaml | 7 +- ...-java-web-app-spec-and-db-with-function.yaml | 7 +- .../test/resources/visitors-creation-script.sql | 19 +- camp/camp-server/pom.xml | 2 +- camp/pom.xml | 2 +- core/pom.xml | 2 +- .../apache/brooklyn/core/BrooklynVersion.java | 2 +- .../brooklyn/core/config/BasicConfigKey.java | 41 +- .../brooklyn/core/entity/AbstractEntity.java | 6 +- .../apache/brooklyn/core/entity/Attributes.java | 10 +- .../core/entity/BrooklynConfigKeys.java | 124 +- .../core/mgmt/entitlement/Entitlements.java | 1 + .../mgmt/ha/OsgiBundleInstallationResult.java | 4 +- .../BasicExternalConfigSupplierRegistry.java | 12 +- .../core/objs/AbstractEntityAdjunct.java | 61 +- .../core/sensor/BasicAttributeSensor.java | 11 +- .../brooklyn/core/sensor/BasicSensor.java | 19 +- .../apache/brooklyn/core/sensor/Sensors.java | 9 +- .../core/sensor/function/FunctionSensor.java | 89 ++ .../core/typereg/BasicBrooklynTypeRegistry.java | 20 +- .../typereg/BasicTypeImplementationPlan.java | 4 +- .../typereg/RegisteredTypeLoadingContexts.java | 6 +- .../core/typereg/RegisteredTypePredicates.java | 78 +- .../brooklyn/core/typereg/RegisteredTypes.java | 2 +- .../enricher/stock/AbstractAggregator.java | 37 +- .../enricher/stock/AbstractTransformer.java | 22 +- .../brooklyn/enricher/stock/Aggregator.java | 15 +- .../brooklyn/enricher/stock/Combiner.java | 33 +- .../apache/brooklyn/enricher/stock/Joiner.java | 17 +- .../brooklyn/enricher/stock/MapAggregator.java | 11 +- .../enricher/stock/PercentageEnricher.java | 7 +- .../brooklyn/enricher/stock/Transformer.java | 23 +- .../brooklyn/enricher/stock/UpdatingMap.java | 23 +- .../YamlRollingTimeWindowMeanEnricher.java | 13 +- .../stock/YamlTimeWeightedDeltaEnricher.java | 7 +- .../enricher/stock/reducer/Reducer.java | 26 +- .../brooklyn/entity/group/AbstractGroup.java | 13 +- .../apache/brooklyn/entity/group/Cluster.java | 2 + .../brooklyn/entity/group/DynamicCluster.java | 21 +- .../brooklyn/entity/group/DynamicFabric.java | 23 +- .../brooklyn/entity/group/DynamicGroup.java | 6 +- .../brooklyn/entity/stock/BasicStartable.java | 6 +- .../brooklyn/entity/stock/DelegateEntity.java | 7 +- core/src/main/resources/catalog.bom | 57 +- .../entity/RecordingSensorEventListener.java | 12 + .../core/mgmt/osgi/OsgiStandaloneTest.java | 4 +- .../core/policy/basic/EnricherTypeTest.java | 6 - .../sensor/function/FunctionSensorTest.java | 77 ++ .../core/test/entity/TestEntityImpl.java | 2 +- .../stock/TransformingEnricherTest.java | 7 +- .../util/core/internal/ssh/ExecCmdAsserts.java | 12 +- core/src/test/resources/catalog.bom | 2 +- karaf/commands/pom.xml | 2 +- karaf/features/pom.xml | 2 +- karaf/httpcomponent-extension/pom.xml | 2 +- karaf/init/pom.xml | 2 +- .../init/src/main/resources/catalog-classes.bom | 107 +- karaf/jetty-config/pom.xml | 2 +- karaf/pom.xml | 2 +- karaf/start/pom.xml | 2 +- launcher-common/pom.xml | 2 +- launcher/pom.xml | 2 +- .../java-web-app-and-db-with-function.yaml | 3 +- .../test/resources/visitors-creation-script.sql | 19 +- locations/container/pom.xml | 2 +- .../resources/generic-application.tests.bom | 8 +- .../src/test/resources/generic.tests.bom | 2 +- locations/jclouds/pom.xml | 2 +- .../location/jclouds/JcloudsLocation.java | 73 +- .../api/JcloudsLocationConfigPublic.java | 6 + .../JcloudsMaxConcurrencyStubbedTest.java | 225 ++++ logging/logback-includes/pom.xml | 2 +- logging/logback-xml/pom.xml | 2 +- parent/pom.xml | 2 +- policy/pom.xml | 2 +- .../action/AbstractScheduledEffectorPolicy.java | 292 +++++ .../policy/action/PeriodicEffectorPolicy.java | 116 ++ .../policy/action/ScheduledEffectorPolicy.java | 100 ++ .../policy/autoscaling/AutoScalerPolicy.java | 25 +- .../policy/ha/ConnectionFailureDetector.java | 14 +- .../policy/ha/ServiceFailureDetector.java | 16 +- .../brooklyn/policy/ha/ServiceReplacer.java | 20 +- .../brooklyn/policy/ha/ServiceRestarter.java | 16 +- .../policy/ha/SshMachineFailureDetector.java | 4 +- policy/src/main/resources/catalog.bom | 92 +- .../action/AbstractEffectorPolicyTest.java | 81 ++ .../action/PeriodicEffectorPolicyTest.java | 123 ++ .../action/ScheduledEffectorPolicyTest.java | 121 ++ .../action/ScheduledPolicyRebindTest.java | 137 +++ .../AutoScalerPolicyPoolSizeTest.java | 18 +- .../AbstractLoadBalancingPolicyTest.java | 1 - pom.xml | 4 +- rest/rest-api/pom.xml | 2 +- .../apache/brooklyn/rest/api/AdjunctApi.java | 6 +- .../org/apache/brooklyn/rest/api/BundleApi.java | 37 +- .../apache/brooklyn/rest/api/CatalogApi.java | 56 +- .../brooklyn/rest/api/EntityConfigApi.java | 10 +- .../apache/brooklyn/rest/api/SubtypeApi.java | 96 -- .../org/apache/brooklyn/rest/api/TypeApi.java | 16 +- .../rest/domain/AdjunctConfigSummary.java | 85 -- .../brooklyn/rest/domain/AdjunctDetail.java | 4 +- .../brooklyn/rest/domain/BundleSummary.java | 7 + .../brooklyn/rest/domain/ConfigSummary.java | 66 +- .../rest/domain/EnricherConfigSummary.java | 11 +- .../rest/domain/EntityConfigSummary.java | 67 +- .../rest/domain/LocationConfigSummary.java | 40 +- .../rest/domain/PolicyConfigSummary.java | 29 +- .../apache/brooklyn/rest/domain/TypeDetail.java | 3 +- .../brooklyn/rest/domain/TypeSummary.java | 12 +- rest/rest-resources/pom.xml | 2 +- .../apache/brooklyn/rest/BrooklynRestApi.java | 2 - .../rest/resources/AdjunctResource.java | 8 +- .../brooklyn/rest/resources/BundleResource.java | 45 +- .../rest/resources/EntityConfigResource.java | 8 +- .../rest/resources/SubtypeResource.java | 82 -- .../brooklyn/rest/resources/TypeResource.java | 23 +- .../rest/transform/AdjunctTransformer.java | 41 +- .../rest/transform/EntityTransformer.java | 111 +- .../rest/transform/PolicyTransformer.java | 3 +- .../rest/transform/TypeTransformer.java | 43 +- .../BundleAndTypeAndSubtypeResourcesTest.java | 1093 ----------------- .../resources/BundleAndTypeResourcesTest.java | 1098 ++++++++++++++++++ .../resources/EntityConfigResourceTest.java | 2 +- rest/rest-server/pom.xml | 2 +- server-cli/pom.xml | 2 +- .../brooklyn/cli/lister/ItemDescriptors.java | 28 +- .../main/resources/brooklyn/default.catalog.bom | 2 +- server-cli/src/main/resources/catalog.bom | 2 +- software/base/pom.xml | 2 +- .../entity/brooklynnode/BrooklynNode.java | 2 +- .../brooklynnode/BrooklynNodeSshDriver.java | 2 +- .../brooklyn/entity/java/JmxmpSslSupport.java | 2 +- .../apache/brooklyn/entity/java/UsesJava.java | 10 +- .../apache/brooklyn/entity/java/UsesJmx.java | 37 +- .../software/base/AbstractVanillaProcess.java | 21 +- .../software/base/EmptySoftwareProcessImpl.java | 4 +- .../entity/software/base/SoftwareProcess.java | 37 +- .../software/base/SoftwareProcessImpl.java | 1 - .../software/base/VanillaSoftwareProcess.java | 5 +- .../base/VanillaSoftwareProcessImpl.java | 16 +- .../base/VanillaSoftwareProcessSshDriver.java | 12 +- .../software/base/VanillaWindowsProcess.java | 22 +- software/base/src/main/resources/catalog.bom | 17 +- software/winrm/pom.xml | 2 +- test-framework/pom.xml | 2 +- test-framework/src/main/resources/catalog.bom | 12 +- test-support/pom.xml | 2 +- .../test/performance/PerformanceTestUtils.java | 50 +- .../osgi/com-example-entities/pom.xml | 2 +- utils/common/dependencies/osgi/entities/pom.xml | 2 +- .../dependencies/osgi/more-entities-v1/pom.xml | 2 +- .../osgi/more-entities-v2-evil-twin/pom.xml | 2 +- .../dependencies/osgi/more-entities-v2/pom.xml | 2 +- utils/common/pom.xml | 2 +- .../apache/brooklyn/util/guava/TypeTokens.java | 38 +- .../javalang/coerce/TypeCoercerExtensible.java | 15 +- .../brooklyn/util/maven/MavenArtifactTest.java | 4 +- utils/groovy/pom.xml | 2 +- utils/jmx/jmxmp-ssl-agent/pom.xml | 2 +- utils/jmx/jmxrmi-agent/pom.xml | 2 +- utils/rest-swagger/pom.xml | 2 +- utils/rt-felix/pom.xml | 2 +- utils/test-support/pom.xml | 2 +- 175 files changed, 4572 insertions(+), 2177 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/62bcbc5f/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/62bcbc5f/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/AdjunctApi.java ---------------------------------------------------------------------- diff --cc rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/AdjunctApi.java index 5fc1366,0000000..1886f63 mode 100644,000000..100644 --- a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/AdjunctApi.java +++ b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/AdjunctApi.java @@@ -1,233 -1,0 +1,233 @@@ +/* + * 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.brooklyn.rest.api; + +import java.util.List; +import java.util.Map; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +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 org.apache.brooklyn.rest.domain.AdjunctConfigSummary; +import org.apache.brooklyn.rest.domain.AdjunctDetail; +import org.apache.brooklyn.rest.domain.AdjunctSummary; ++import org.apache.brooklyn.rest.domain.ConfigSummary; +import org.apache.brooklyn.rest.domain.Status; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; + +@Path("/applications/{application}/entities/{entity}/adjuncts") +@Api("Entity Adjuncts (policies, enrichers, feeds)") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +public interface AdjunctApi { + + @GET + @ApiOperation(value = "Fetch the adjuncts attached to a specific application entity", + response = org.apache.brooklyn.rest.domain.AdjunctSummary.class, + responseContainer = "List") + @ApiResponses(value = { + @ApiResponse(code = 404, message = "Could not find application or entity") + }) + public List<AdjunctSummary> list( + @ApiParam(value = "Application ID or name", required = true) + @PathParam("application") final String application, + @ApiParam(value = "Entity ID or name", required = true) + @PathParam("entity") final String entityToken, + @ApiParam(value = "Filter by adjunct type", required = false) + @QueryParam("adjunctType") final String adjunctType); + + @POST + @ApiOperation(value = "Add an adjunct (policy, enricher, or feed)", notes = "Returns a summary of the added adjunct") + @ApiResponses(value = { + @ApiResponse(code = 404, message = "Could not find application or entity"), + @ApiResponse(code = 400, message = "Type is not a suitable adjunct") + }) + public AdjunctSummary addAdjunct( + @ApiParam(name = "application", value = "Application ID or name", required = true) + @PathParam("application") String application, + + @ApiParam(name = "entity", value = "Entity ID or name", required = true) + @PathParam("entity") String entityToken, + + @ApiParam(name = "type", value = "Adjunct from the type registry to instantiate and add", required = true) + @QueryParam("type") + String adjunctRegisteredTypeName, + + // TODO would like to make this optional but jersey complains if we do + @ApiParam(name = "config", value = "Configuration for the adjunct (as key value pairs)", required = true) + Map<String, String> config); + + @GET + @Path("/{adjunct}") + @ApiOperation(value = "Gets detail of an adjunct") + @ApiResponses(value = { + @ApiResponse(code = 404, message = "Could not find application, entity or adjunct") + }) + public AdjunctDetail get( + @ApiParam(name = "application", value = "Application ID or name", required = true) + @PathParam("application") String application, + + @ApiParam(name = "entity", value = "Entity ID or name", required = true) + @PathParam("entity") String entityToken, + + @ApiParam(name = "adjunct", value = "Adjunct ID or name", required = true) + @PathParam("adjunct") String adjunctId); + + @GET + @Path("/{adjunct}/status") + @ApiOperation(value = "Gets status of an adjunct (RUNNING / SUSPENDED)") + @ApiResponses(value = { + @ApiResponse(code = 404, message = "Could not find application, entity or adjunct") + }) + public Status getStatus( + @ApiParam(name = "application", value = "Application ID or name", required = true) + @PathParam("application") String application, + + @ApiParam(name = "entity", value = "Entity ID or name", required = true) + @PathParam("entity") String entityToken, + + @ApiParam(name = "adjunct", value = "Adjunct ID or name", required = true) + @PathParam("adjunct") String adjunctId); + + @POST + @Path("/{adjunct}/start") + @ApiOperation(value = "Start or resume an adjunct") + @ApiResponses(value = { + @ApiResponse(code = 404, message = "Could not find application, entity or adjunct") + }) + public Response start( + @ApiParam(name = "application", value = "Application ID or name", required = true) + @PathParam("application") String application, + + @ApiParam(name = "entity", value = "Entity ID or name", required = true) + @PathParam("entity") String entityToken, + + @ApiParam(name = "adjunct", value = "Adjunct ID or name", required = true) + @PathParam("adjunct") String adjunctId); + + @POST + @Path("/{adjunct}/stop") + @ApiOperation(value = "Suspends an adjunct") + @ApiResponses(value = { + @ApiResponse(code = 404, message = "Could not find application, entity or adjunct") + }) + public Response stop( + @ApiParam(name = "application", value = "Application ID or name", required = true) + @PathParam("application") String application, + + @ApiParam(name = "entity", value = "Entity ID or name", required = true) + @PathParam("entity") String entityToken, + + @ApiParam(name = "adjunct", value = "Adjunct ID or name", required = true) + @PathParam("adjunct") String adjunctId); + + @DELETE + @Path("/{adjunct}") + @ApiOperation(value = "Destroy an adjunct", notes="Removes an adjunct from being associated with the entity and destroys it (stopping first if running)") + @ApiResponses(value = { + @ApiResponse(code = 404, message = "Could not find application, entity or adjunct") + }) + public Response destroy( + @ApiParam(name = "application", value = "Application ID or name", required = true) + @PathParam("application") String application, + + @ApiParam(name = "entity", value = "Entity ID or name", required = true) + @PathParam("entity") String entityToken, + + @ApiParam(name = "adjunct", value = "Adjunct ID or name", required = true) + @PathParam("adjunct") String adjunctId); + + /// ---------- config --------------- + + @GET + @Path("/{adjunct}/config") + @ApiOperation(value = "Fetch the config keys for a specific adjunct", - response = org.apache.brooklyn.rest.domain.AdjunctConfigSummary.class, ++ response = org.apache.brooklyn.rest.domain.ConfigSummary.class, + responseContainer = "List") + @ApiResponses(value = { + @ApiResponse(code = 404, message = "Could not find application or entity or adjunct") + }) - public List<AdjunctConfigSummary> listConfig( ++ public List<ConfigSummary> listConfig( + @ApiParam(value = "Application ID or name", required = true) + @PathParam("application") final String application, + @ApiParam(value = "Entity ID or name", required = true) + @PathParam("entity") final String entityToken, + @ApiParam(value = "Adjunct ID or name", required = true) + @PathParam("adjunct") final String adjunctToken); + + // TODO support parameters ?show=value,summary&name=xxx &format={string,json,xml} + // (and in sensors class) + @GET + @Path("/{adjunct}/config-current") + @ApiOperation(value = "Fetch config key values in batch", notes="Returns a map of config name to value") + public Map<String, Object> batchConfigRead( + @ApiParam(value = "Application ID or name", required = true) + @PathParam("application") String application, + @ApiParam(value = "Entity ID or name", required = true) + @PathParam("entity") String entityToken, + @ApiParam(value = "Adjunct ID or name", required = true) + @PathParam("adjunct") String adjunctToken) ; + + @GET + @Path("/{adjunct}/config/{config}") + @ApiOperation(value = "Fetch config value", response = Object.class) + @ApiResponses(value = { + @ApiResponse(code = 404, message = "Could not find application, entity, adjunct or config key") + }) + public String getConfig( + @ApiParam(value = "Application ID or name", required = true) + @PathParam("application") String application, + @ApiParam(value = "Entity ID or name", required = true) + @PathParam("entity") String entityToken, + @ApiParam(value = "Adjunct ID or name", required = true) + @PathParam("adjunct") String adjunctToken, + @ApiParam(value = "Config key ID", required = true) + @PathParam("config") String configKeyName); + + @POST + @Path("/{adjunct}/config/{config}") + @Consumes(value = {"*/*"}) + @ApiOperation(value = "Sets the given config on this adjunct") + @ApiResponses(value = { + @ApiResponse(code = 404, message = "Could not find application, entity, adjunct or config key") + }) + public Response setConfig( + @ApiParam(value = "Application ID or name", required = true) + @PathParam("application") String application, + @ApiParam(value = "Entity ID or name", required = true) + @PathParam("entity") String entityToken, + @ApiParam(value = "Adjunct ID or name", required = true) + @PathParam("adjunct") String adjunctToken, + @ApiParam(value = "Config key ID", required = true) + @PathParam("config") String configKeyName, + @ApiParam(name = "value", value = "New value for the configuration", required = true) + Object value); +} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/62bcbc5f/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/EntityConfigApi.java ---------------------------------------------------------------------- diff --cc rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/EntityConfigApi.java index 4a5bbde,4a5bbde..a0e3604 --- a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/EntityConfigApi.java +++ b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/api/EntityConfigApi.java @@@ -18,7 -18,7 +18,6 @@@ */ package org.apache.brooklyn.rest.api; --import io.swagger.annotations.Api; import java.util.List; import java.util.Map; @@@ -32,12 -32,12 +31,13 @@@ import javax.ws.rs.Produces import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; --import org.apache.brooklyn.rest.domain.EntityConfigSummary; ++import org.apache.brooklyn.rest.domain.ConfigSummary; --import io.swagger.annotations.ApiResponse; --import io.swagger.annotations.ApiResponses; ++import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; ++import io.swagger.annotations.ApiResponse; ++import io.swagger.annotations.ApiResponses; @Path("/applications/{application}/entities/{entity}/config") @Api("Entity Config") @@@ -52,7 -52,7 +52,7 @@@ public interface EntityConfigApi @ApiResponses(value = { @ApiResponse(code = 404, message = "Could not find application or entity") }) -- public List<EntityConfigSummary> list( ++ public List<ConfigSummary> list( @ApiParam(value = "Application ID or name", required = true) @PathParam("application") final String application, @ApiParam(value = "Entity ID or name", required = true) http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/62bcbc5f/rest/rest-api/src/main/java/org/apache/brooklyn/rest/domain/AdjunctDetail.java ---------------------------------------------------------------------- diff --cc rest/rest-api/src/main/java/org/apache/brooklyn/rest/domain/AdjunctDetail.java index ddce5f4,0000000..a2f348c mode 100644,000000..100644 --- a/rest/rest-api/src/main/java/org/apache/brooklyn/rest/domain/AdjunctDetail.java +++ b/rest/rest-api/src/main/java/org/apache/brooklyn/rest/domain/AdjunctDetail.java @@@ -1,72 -1,0 +1,72 @@@ +/* + * 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.brooklyn.rest.domain; + +import java.util.Map; +import java.util.Set; + +import org.apache.brooklyn.api.objs.EntityAdjunct; +import org.apache.brooklyn.util.collections.MutableMap; +import org.apache.brooklyn.util.collections.MutableSet; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonInclude.Include; + +public class AdjunctDetail extends AdjunctSummary { + + private static final long serialVersionUID = -5086680835225136768L; + + @JsonInclude(Include.NON_EMPTY) + private String functionallyUniqueIdentifier; + @JsonInclude(Include.NON_EMPTY) + private Set<Object> tags; + @JsonInclude(Include.NON_EMPTY) - final Set<AdjunctConfigSummary> parameters = MutableSet.of(); ++ final Set<ConfigSummary> parameters = MutableSet.of(); + final Map<String,Object> config = MutableMap.of(); + + // for json + protected AdjunctDetail() {} + + public AdjunctDetail(EntityAdjunct a) { + super(a); + this.functionallyUniqueIdentifier = a.getUniqueTag(); + this.tags = a.tags().getTags(); + } + + public String getFunctionallyUniqueIdentifier() { + return functionallyUniqueIdentifier; + } + + public Set<Object> getTags() { + return tags; + } + - public AdjunctDetail parameter(AdjunctConfigSummary p) { ++ public AdjunctDetail parameter(ConfigSummary p) { + parameters.add(p); return this; + } + + public AdjunctDetail config(String key, Object val) { + config.put(key, val); return this; + } + + public AdjunctDetail config(Map<String,Object> vals) { + config.putAll(vals); return this; + } + +} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/62bcbc5f/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/BrooklynRestApi.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/62bcbc5f/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/AdjunctResource.java ---------------------------------------------------------------------- diff --cc rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/AdjunctResource.java index 9dd4c10,0000000..3b5185a mode 100644,000000..100644 --- a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/AdjunctResource.java +++ b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/AdjunctResource.java @@@ -1,263 -1,0 +1,263 @@@ +/* + * 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.brooklyn.rest.resources; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.ws.rs.core.Context; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec; +import org.apache.brooklyn.api.objs.BrooklynObjectType; +import org.apache.brooklyn.api.objs.EntityAdjunct; +import org.apache.brooklyn.api.policy.Policy; +import org.apache.brooklyn.api.policy.PolicySpec; +import org.apache.brooklyn.api.sensor.Enricher; +import org.apache.brooklyn.api.sensor.EnricherSpec; +import org.apache.brooklyn.api.sensor.Feed; +import org.apache.brooklyn.api.typereg.RegisteredType; +import org.apache.brooklyn.config.ConfigKey; +import org.apache.brooklyn.core.config.ConfigPredicates; +import org.apache.brooklyn.core.entity.EntityInternal; +import org.apache.brooklyn.core.mgmt.entitlement.Entitlements; +import org.apache.brooklyn.rest.api.AdjunctApi; - import org.apache.brooklyn.rest.domain.AdjunctConfigSummary; +import org.apache.brooklyn.rest.domain.AdjunctDetail; +import org.apache.brooklyn.rest.domain.AdjunctSummary; ++import org.apache.brooklyn.rest.domain.ConfigSummary; +import org.apache.brooklyn.rest.domain.Status; +import org.apache.brooklyn.rest.domain.SummaryComparators; +import org.apache.brooklyn.rest.filter.HaHotStateRequired; +import org.apache.brooklyn.rest.transform.AdjunctTransformer; +import org.apache.brooklyn.rest.transform.EntityTransformer; +import org.apache.brooklyn.rest.util.BrooklynRestResourceUtils; +import org.apache.brooklyn.rest.util.WebResourceUtils; +import org.apache.brooklyn.util.core.ClassLoaderUtils; +import org.apache.brooklyn.util.core.flags.TypeCoercions; +import org.apache.brooklyn.util.exceptions.Exceptions; +import org.apache.brooklyn.util.text.Strings; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.Function; +import com.google.common.base.Predicates; +import com.google.common.collect.FluentIterable; +import com.google.common.collect.Iterables; +import com.google.common.collect.Lists; + +@HaHotStateRequired +public class AdjunctResource extends AbstractBrooklynRestResource implements AdjunctApi { + + private static final Logger log = LoggerFactory.getLogger(AdjunctResource.class); + + private @Context UriInfo ui; + + @Override + public List<AdjunctSummary> list(String application, String entityToken, String adjunctType) { + final Entity entity = brooklyn().getEntity(application, entityToken); + Iterable<? extends EntityAdjunct> source = Collections.emptyList(); + boolean all = Strings.isBlank(adjunctType); + boolean any = false; + if (all || adjunctType.equalsIgnoreCase(BrooklynObjectType.POLICY.name())) { + any = true; + source = Iterables.concat(source, entity.policies()); + } + if (all || adjunctType.equalsIgnoreCase(BrooklynObjectType.ENRICHER.name())) { + any = true; + source = Iterables.concat(source, entity.enrichers()); + } + if (all || adjunctType.equalsIgnoreCase(BrooklynObjectType.FEED.name())) { + any = true; + source = Iterables.concat(source, ((EntityInternal)entity).feeds()); + } + if (!any) { + throw WebResourceUtils.badRequest("Unknown adjunct type '%s'; use 'policy', 'enricher', or 'feed'", adjunctType); + } + return FluentIterable.from(source) + .transform(new Function<EntityAdjunct, AdjunctSummary>() { + @Override + public AdjunctSummary apply(EntityAdjunct adjunct) { + return AdjunctTransformer.adjunctSummary(entity, adjunct, ui.getBaseUriBuilder()); + } + }) + .toSortedList(SummaryComparators.nameComparator()); + } + + // TODO would like to make 'config' arg optional but jersey complains if we do + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Override + public AdjunctSummary addAdjunct(String application, String entityToken, String adjunctTypeName, Map<String, String> config) { + Entity entity = brooklyn().getEntity(application, entityToken); + if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.MODIFY_ENTITY, entity)) { + throw WebResourceUtils.forbidden("User '%s' is not authorized to modify entity '%s'", + Entitlements.getEntitlementContext().user(), entity); + } + + RegisteredType rt = brooklyn().getTypeRegistry().get(adjunctTypeName); + AbstractBrooklynObjectSpec<?, ?> spec; + if (rt!=null) { + spec = brooklyn().getTypeRegistry().createSpec(rt, null, null); + } else { + try { + Class<?> type = new ClassLoaderUtils(this, mgmt()).loadClass(adjunctTypeName); + if (Policy.class.isAssignableFrom(type)) spec = PolicySpec.create((Class) type); + else if (Enricher.class.isAssignableFrom(type)) spec = EnricherSpec.create((Class) type); + else if (Feed.class.isAssignableFrom(type)) { + // TODO add FeedSpec ? would be needed even if using the type registry + throw WebResourceUtils.badRequest("Creation of feeds from java type (%s) not supported", adjunctTypeName); + } else { + throw WebResourceUtils.badRequest("Invalid type %s; not a support adjunct type", adjunctTypeName); + } + } catch (ClassNotFoundException e) { + throw WebResourceUtils.badRequest("No adjunct with type %s found", adjunctTypeName); + } catch (ClassCastException e) { + throw WebResourceUtils.badRequest("No adjunct with type %s found", adjunctTypeName); + } catch (Exception e) { + throw Exceptions.propagate(e); + } + } + + spec.configure(config); + + EntityAdjunct instance; + if (spec instanceof PolicySpec) instance = entity.policies().add((PolicySpec)spec); + else if (spec instanceof EnricherSpec) instance = entity.enrichers().add((EnricherSpec)spec); + else { + // TODO add FeedSpec + throw WebResourceUtils.badRequest("Unexpected spec type %s", spec); + } + + log.debug("REST API added adjunct " + instance + " to " + entity); + + return AdjunctTransformer.adjunctDetail(brooklyn(), entity, instance, ui.getBaseUriBuilder()); + } + + @Override + public AdjunctDetail get(String application, String entityToken, String adjunctId) { + Entity entity = brooklyn().getEntity(application, entityToken); + EntityAdjunct adjunct = brooklyn().getAdjunct(entity, adjunctId); + + return AdjunctTransformer.adjunctDetail(brooklyn(), entity, adjunct, ui.getBaseUriBuilder()); + } + + @Override + public Status getStatus(String application, String entityToken, String adjunctId) { + return AdjunctTransformer.inferStatus( brooklyn().getAdjunct(application, entityToken, adjunctId) ); + } + + @Override + public Response start(String application, String entityToken, String adjunctId) { + EntityAdjunct adjunct = brooklyn().getAdjunct(application, entityToken, adjunctId); + if (adjunct instanceof Policy) ((Policy)adjunct).resume(); + else if (adjunct instanceof Feed) ((Feed)adjunct).resume(); + else throw WebResourceUtils.badRequest("%s does not support start/resume", adjunct); + + return Response.status(Response.Status.NO_CONTENT).build(); + } + + @Override + public Response stop(String application, String entityToken, String adjunctId) { + EntityAdjunct adjunct = brooklyn().getAdjunct(application, entityToken, adjunctId); + if (adjunct instanceof Policy) ((Policy)adjunct).suspend(); + else if (adjunct instanceof Feed) ((Feed)adjunct).suspend(); + else throw WebResourceUtils.badRequest("%s does not support suspend", adjunct); + + return Response.status(Response.Status.NO_CONTENT).build(); + } + + @Override + public Response destroy(String application, String entityToken, String adjunctId) { + Entity entity = brooklyn().getEntity(application, entityToken); + EntityAdjunct adjunct = brooklyn().getAdjunct(entity, adjunctId); + + if (adjunct instanceof Policy) { + ((Policy)adjunct).suspend(); + entity.policies().remove((Policy) adjunct); + } else if (adjunct instanceof Enricher) { + entity.enrichers().remove((Enricher) adjunct); + } else if (adjunct instanceof Feed) { + ((Feed)adjunct).suspend(); + ((EntityInternal)entity).feeds().remove((Feed) adjunct); + } else { + throw WebResourceUtils.badRequest("Unexpected adjunct type %s", adjunct); + } + + return Response.status(Response.Status.NO_CONTENT).build(); + } + + // ---- config ---- + + @Override - public List<AdjunctConfigSummary> listConfig( ++ public List<ConfigSummary> listConfig( + final String application, final String entityToken, final String adjunctToken) { + Entity entity = brooklyn().getEntity(application, entityToken); + EntityAdjunct adjunct = brooklyn().getAdjunct(entity, adjunctToken); + - List<AdjunctConfigSummary> result = Lists.newArrayList(); ++ List<ConfigSummary> result = Lists.newArrayList(); + for (ConfigKey<?> key : adjunct.config().findKeysPresent(Predicates.alwaysTrue())) { - result.add(AdjunctTransformer.configSummary(brooklyn(), entity, adjunct, key, ui.getBaseUriBuilder())); ++ result.add(AdjunctTransformer.configSummary(brooklyn(), ui.getBaseUriBuilder(), entity, adjunct, key)); + } + return result; + } + + // TODO support parameters ?show=value,summary&name=xxx &format={string,json,xml} + // (and in sensors class) + @Override + public Map<String, Object> batchConfigRead(String application, String entityToken, String adjunctToken) { + // TODO: add test + return EntityTransformer.getConfigValues(brooklyn(), brooklyn().getAdjunct(application, entityToken, adjunctToken) ); + } + + @Override + public String getConfig(String application, String entityToken, String adjunctToken, String configKeyName) { + EntityAdjunct adjunct = brooklyn().getAdjunct(application, entityToken, adjunctToken); + Set<ConfigKey<?>> cki = adjunct.config().findKeysDeclared(ConfigPredicates.nameSatisfies(Predicates.equalTo(configKeyName))); + if (cki.isEmpty()) throw WebResourceUtils.notFound("Cannot find config key '%s' in policy '%s' of entity '%s'", configKeyName, adjunctToken, entityToken); + + return brooklyn().getStringValueForDisplay(adjunct.config().get(cki.iterator().next())); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + public Response setConfig(String application, String entityToken, String adjunctToken, String configKeyName, Object value) { + Entity entity = brooklyn().getEntity(application, entityToken); + if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.MODIFY_ENTITY, entity)) { + throw WebResourceUtils.forbidden("User '%s' is not authorized to modify entity '%s'", + Entitlements.getEntitlementContext().user(), entity); + } + + EntityAdjunct adjunct = brooklyn().getAdjunct(entity, adjunctToken); + Set<ConfigKey<?>> cki = adjunct.config().findKeysDeclared(ConfigPredicates.nameSatisfies(Predicates.equalTo(configKeyName))); + if (cki.isEmpty()) throw WebResourceUtils.notFound("Cannot find config key '%s' in policy '%s' of entity '%s'", configKeyName, adjunctToken, entityToken); + ConfigKey<?> ck = cki.iterator().next(); + + adjunct.config().set((ConfigKey) cki, TypeCoercions.coerce(value, ck.getTypeToken())); + + return Response.status(Response.Status.OK).build(); + } + + public static String getStringValueForDisplay(BrooklynRestResourceUtils utils, EntityAdjunct policy, Object value) { + return utils.getStringValueForDisplay(value); + } + +} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/62bcbc5f/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/EntityConfigResource.java ---------------------------------------------------------------------- diff --cc rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/EntityConfigResource.java index d85f1d7,d85f1d7..dd909e4 --- a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/EntityConfigResource.java +++ b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/resources/EntityConfigResource.java @@@ -32,7 -32,7 +32,7 @@@ import org.apache.brooklyn.core.entity. import org.apache.brooklyn.core.mgmt.entitlement.Entitlements; import org.apache.brooklyn.core.mgmt.entitlement.Entitlements.EntityAndItem; import org.apache.brooklyn.rest.api.EntityConfigApi; --import org.apache.brooklyn.rest.domain.EntityConfigSummary; ++import org.apache.brooklyn.rest.domain.ConfigSummary; import org.apache.brooklyn.rest.filter.HaHotStateRequired; import org.apache.brooklyn.rest.transform.EntityTransformer; import org.apache.brooklyn.rest.util.WebResourceUtils; @@@ -52,7 -52,7 +52,7 @@@ public class EntityConfigResource exten private static final Logger LOG = LoggerFactory.getLogger(EntityConfigResource.class); @Override -- public List<EntityConfigSummary> list(final String application, final String entityToken) { ++ public List<ConfigSummary> list(final String application, final String entityToken) { final Entity entity = brooklyn().getEntity(application, entityToken); if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SEE_ENTITY, entity)) { throw WebResourceUtils.forbidden("User '%s' is not authorized to see entity '%s'", @@@ -61,7 -61,7 +61,7 @@@ // TODO merge with keys which have values: // ((EntityInternal) entity).config().getBag().getAllConfigAsConfigKeyMap(); -- List<EntityConfigSummary> result = Lists.newArrayList(); ++ List<ConfigSummary> result = Lists.newArrayList(); for (ConfigKey<?> key : entity.getEntityType().getConfigKeys()) { // Exclude config that user is not allowed to see @@@ -70,7 -70,7 +70,7 @@@ new Object[] {Entitlements.getEntitlementContext().user(), key.getName(), entity}); continue; } -- result.add(EntityTransformer.entityConfigSummary(entity, key, ui.getBaseUriBuilder())); ++ result.add(EntityTransformer.configSummary(brooklyn(), ui.getBaseUriBuilder(), entity, key)); } return result; http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/62bcbc5f/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/transform/AdjunctTransformer.java ---------------------------------------------------------------------- diff --cc rest/rest-resources/src/main/java/org/apache/brooklyn/rest/transform/AdjunctTransformer.java index db7d4cd,0000000..f841f33 mode 100644,000000..100644 --- a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/transform/AdjunctTransformer.java +++ b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/transform/AdjunctTransformer.java @@@ -1,117 -1,0 +1,116 @@@ +/* + * 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.brooklyn.rest.transform; + +import static org.apache.brooklyn.rest.util.WebResourceUtils.serviceUriBuilder; + +import java.net.URI; +import java.util.Map; + ++import javax.annotation.Nullable; +import javax.ws.rs.core.UriBuilder; + +import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.api.objs.EntityAdjunct; ++import org.apache.brooklyn.api.objs.SpecParameter; +import org.apache.brooklyn.api.policy.Policy; +import org.apache.brooklyn.api.sensor.Feed; +import org.apache.brooklyn.config.ConfigKey; +import org.apache.brooklyn.core.policy.Policies; +import org.apache.brooklyn.rest.api.AdjunctApi; +import org.apache.brooklyn.rest.api.ApplicationApi; +import org.apache.brooklyn.rest.api.EntityApi; - import org.apache.brooklyn.rest.domain.AdjunctConfigSummary; +import org.apache.brooklyn.rest.domain.AdjunctDetail; +import org.apache.brooklyn.rest.domain.AdjunctSummary; - import org.apache.brooklyn.rest.domain.ApplicationSummary; ++import org.apache.brooklyn.rest.domain.ConfigSummary; +import org.apache.brooklyn.rest.domain.Status; +import org.apache.brooklyn.rest.util.BrooklynRestResourceUtils; +import org.apache.brooklyn.util.collections.MutableMap; + +import com.google.common.base.Predicates; - import com.google.common.collect.ImmutableMap; + +/** + * Converts from Brooklyn entities to restful API summary objects + */ +public class AdjunctTransformer { + + public static AdjunctSummary adjunctSummary(Entity entity, EntityAdjunct adjunct, UriBuilder ub) { + return embellish(new AdjunctSummary(adjunct), entity, adjunct, ub); + } + + @SuppressWarnings("unchecked") + private static <T extends AdjunctSummary> T embellish(T adjunctSummary, Entity entity, EntityAdjunct adjunct, UriBuilder ub) { + return (T) adjunctSummary.state(inferStatus(adjunct)).links( buildLinks(entity, adjunct, ub, adjunctSummary instanceof AdjunctDetail) ); + } + + public static AdjunctDetail adjunctDetail(BrooklynRestResourceUtils utils, Entity entity, EntityAdjunct adjunct, UriBuilder ub) { + AdjunctDetail result = embellish(new AdjunctDetail(adjunct), entity, adjunct, ub); + for (ConfigKey<?> key: adjunct.config().findKeysDeclared(Predicates.alwaysTrue())) { - result.parameter(configSummary(utils, entity, adjunct, key, ub)); ++ result.parameter(configSummary(utils, ub, entity, adjunct, key)); + } + result.config(EntityTransformer.getConfigValues(utils, adjunct)); + return result; + } + + protected static Map<String, URI> buildLinks(Entity entity, EntityAdjunct adjunct, UriBuilder ub, boolean detail) { + MutableMap<String,URI> links = MutableMap.of(); + + links.put("self", serviceUriBuilder(ub, AdjunctApi.class, "get").build(entity.getApplicationId(), entity.getId(), adjunct.getId())); + + if (detail) { + links.put("application", serviceUriBuilder(ub, ApplicationApi.class, "get").build(entity.getApplicationId())); + links.put("entity", serviceUriBuilder(ub, EntityApi.class, "get").build(entity.getApplicationId(), entity.getId())); + links.put("config", serviceUriBuilder(ub, AdjunctApi.class, "listConfig").build(entity.getApplicationId(), entity.getId(), adjunct.getId())); + links.put("status", serviceUriBuilder(ub, AdjunctApi.class, "getStatus").build(entity.getApplicationId(), entity.getId(), adjunct.getId())); + if (adjunct instanceof Policy || adjunct instanceof Feed) { + links.put("start", serviceUriBuilder(ub, AdjunctApi.class, "start").build(entity.getApplicationId(), entity.getId(), adjunct.getId())); + links.put("stop", serviceUriBuilder(ub, AdjunctApi.class, "stop").build(entity.getApplicationId(), entity.getId(), adjunct.getId())); + } + links.put("destroy", serviceUriBuilder(ub, AdjunctApi.class, "destroy").build(entity.getApplicationId(), entity.getId(), adjunct.getId())); + } + + return links.asUnmodifiable(); + } + + public static Status inferStatus(EntityAdjunct adjunct) { + return ApplicationTransformer.statusFromLifecycle( Policies.inferAdjunctStatus(adjunct) ); + } + - public static AdjunctConfigSummary configSummary(BrooklynRestResourceUtils utils, ApplicationSummary application, Entity entity, EntityAdjunct adjunct, ConfigKey<?> config, UriBuilder ub) { - return configSummary(utils, entity, adjunct, config, ub); ++ public static ConfigSummary configSummary(BrooklynRestResourceUtils utils, UriBuilder ub, @Nullable Entity entity, @Nullable EntityAdjunct adjunct, SpecParameter<?> input) { ++ Double priority = input.isPinned() ? Double.valueOf(1d) : null; ++ return configSummary(utils, ub, entity, adjunct, input.getConfigKey(), input.getLabel(), priority, input.isPinned()); + } + - public static AdjunctConfigSummary configSummary(BrooklynRestResourceUtils utils, Entity entity, EntityAdjunct adjunct, ConfigKey<?> config, UriBuilder ub) { - URI applicationUri = serviceUriBuilder(ub, ApplicationApi.class, "get").build(entity.getApplicationId()); - URI entityUri = serviceUriBuilder(ub, EntityApi.class, "get").build(entity.getApplicationId(), entity.getId()); - URI adjunctUri = serviceUriBuilder(ub, AdjunctApi.class, "get").build(entity.getApplicationId(), entity.getId(), adjunct.getId()); - URI configUri = serviceUriBuilder(ub, AdjunctApi.class, "getConfig").build(entity.getApplicationId(), entity.getId(), adjunct.getId(), config.getName()); - - Map<String, URI> links = ImmutableMap.<String, URI>builder() - .put("self", configUri) - .put("application", applicationUri) - .put("entity", entityUri) - .put("policy", adjunctUri) ++ public static ConfigSummary configSummary(BrooklynRestResourceUtils utils, UriBuilder ub, Entity entity, EntityAdjunct adjunct, ConfigKey<?> config) { ++ // TODO get catalog info from other sources? ++ // see EntityTransformer.configSummary ++ return configSummary(utils, ub, entity, adjunct, config, null, null, null); ++ } ++ public static ConfigSummary configSummary(BrooklynRestResourceUtils utils, UriBuilder ub, @Nullable Entity entity, @Nullable EntityAdjunct adjunct, ConfigKey<?> config, String label, Double priority, Boolean pinned) { ++ URI configUri = entity==null ? null : serviceUriBuilder(ub, AdjunctApi.class, "getConfig").build(entity.getApplicationId(), entity.getId(), adjunct.getId(), config.getName()); ++ Map<String, URI> links = MutableMap.<String, URI>builder() ++ .putIfNotNull("self", configUri) ++ // no point in including app/entity on every summary shown in a list ++ // (this is only ever used in a list, as self points at the value) + .build(); + - return new AdjunctConfigSummary(config.getName(), config.getTypeName(), config.getDescription(), - utils.getStringValueForDisplay(config.getDefaultValue()), - config.isReconfigurable(), - links); ++ // TODO get actions, see EntityTransformer.configSummary ++ return new ConfigSummary(config, label, priority, pinned, links); + } +} http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/62bcbc5f/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/transform/EntityTransformer.java ---------------------------------------------------------------------- diff --cc rest/rest-resources/src/main/java/org/apache/brooklyn/rest/transform/EntityTransformer.java index cb7877f,73b2831..9359bb5 --- a/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/transform/EntityTransformer.java +++ b/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/transform/EntityTransformer.java @@@ -126,58 -120,58 +126,78 @@@ public class EntityTransformer })); } ++ /** @deprecated since 0.13.0 use {@link #configSummary(BrooklynRestResourceUtils, UriBuilder, Entity, ConfigKey, String, Double, Boolean) */ ++ @Deprecated public static EntityConfigSummary entityConfigSummary(ConfigKey<?> config, String label, Double priority, Boolean pinned, Map<String, URI> links) { -- Map<String, URI> mapOfLinks = links==null ? null : ImmutableMap.copyOf(links); -- return new EntityConfigSummary(config, label, priority, pinned, mapOfLinks); -- } -- - public static AdjunctConfigSummary adjunctConfigSummary(ConfigKey<?> config, String label, Double priority, Map<String, URI> links) { - return new AdjunctConfigSummary(config, label, priority, links); - public static ConfigSummary configSummary(ConfigKey<?> config, String label, Double priority, Boolean pinned, Map<String, URI> links) { - return new ConfigSummary(config, label, priority, pinned, links); ++ return new EntityConfigSummary(config, label, priority, pinned, links); } ++ /** @deprecated since 0.13.0 use {@link AdjunctTransformer#configSummary(BrooklynRestResourceUtils, UriBuilder, Entity, org.apache.brooklyn.api.objs.EntityAdjunct, ConfigKey, String, Double, Boolean)} */ ++ @Deprecated public static PolicyConfigSummary policyConfigSummary(ConfigKey<?> config, String label, Double priority, Map<String, URI> links) { return new PolicyConfigSummary(config, label, priority, links); } ++ /** @deprecated since 0.13.0 use {@link AdjunctTransformer#configSummary(BrooklynRestResourceUtils, UriBuilder, Entity, org.apache.brooklyn.api.objs.EntityAdjunct, ConfigKey, String, Double, Boolean)} */ ++ @Deprecated public static EnricherConfigSummary enricherConfigSummary(ConfigKey<?> config, String label, Double priority, Map<String, URI> links) { return new EnricherConfigSummary(config, label, priority, links); } /** generates a representation for a given config key, * with label inferred from annoation in the entity class, -- * and links pointing to the entity and the applicaiton */ ++ * and links pointing to the entity and the application ++ * @deprecated since 0.13.0 use {@link #configSummary(BrooklynRestResourceUtils, UriBuilder, Entity, ConfigKey)} */ ++ @Deprecated public static EntityConfigSummary entityConfigSummary(Entity entity, ConfigKey<?> config, UriBuilder ub) { -- /* -- * following code nearly there to get the @CatalogConfig annotation -- * in the class and use that to populate a label -- */ -- --// EntityDynamicType typeMap = --// ((AbstractEntity)entity).getMutableEntityType(); --// // above line works if we can cast; line below won't work, but there should some way --// // to get back the handle to the spec from an entity local, which then *would* work --// EntityTypes.getDefinedEntityType(entity.getClass()); ++ return (EntityConfigSummary) configSummary(null, ub, entity, config); ++ } ++ ++ public static ConfigSummary configSummary(BrooklynRestResourceUtils utils, UriBuilder ub, Entity entity, ConfigKey<?> config) { ++ // TODO get catalog/display info ++ ++ /* ++ * following code nearly there to get the @CatalogConfig annotation ++ * in the class and use that to populate a label ++ */ --// String label = typeMap.getConfigKeyField(config.getName()); -- String label = null; -- Double priority = null; ++// EntityDynamicType typeMap = ++// ((AbstractEntity)entity).getMutableEntityType(); ++// // above line works if we can cast; line below won't work, but there should some way ++// // to get back the handle to the spec from an entity local, which then *would* work ++// EntityTypes.getDefinedEntityType(entity.getClass()); -- URI applicationUri = serviceUriBuilder(ub, ApplicationApi.class, "get").build(entity.getApplicationId()); -- URI entityUri = serviceUriBuilder(ub, EntityApi.class, "get").build(entity.getApplicationId(), entity.getId()); -- URI selfUri = serviceUriBuilder(ub, EntityConfigApi.class, "get").build(entity.getApplicationId(), entity.getId(), config.getName()); ++// String label = typeMap.getConfigKeyField(config.getName()); ++ return configSummary(null, ub, entity, config, null); ++ } ++ public static ConfigSummary configSummary(BrooklynRestResourceUtils utils, UriBuilder ub, Entity entity, ConfigKey<?> config, CatalogConfig annotation) { ++ String label = annotation==null ? null : annotation.label(); ++ Double priority = annotation==null ? null : annotation.priority(); ++ boolean pinned = annotation!=null && annotation.pinned(); ++ return configSummary(utils, ub, entity, config, label, priority, pinned); ++ } ++ public static ConfigSummary configSummary(BrooklynRestResourceUtils utils, UriBuilder ub, Entity entity, ConfigKey<?> config, String label, Double priority, Boolean pinned) { ++ // entity can be null if coming from catalog ++ URI applicationUri = entity==null ? null : serviceUriBuilder(ub, ApplicationApi.class, "get").build(entity.getApplicationId()); ++ URI entityUri = entity==null ? null : serviceUriBuilder(ub, EntityApi.class, "get").build(entity.getApplicationId(), entity.getId()); ++ URI selfUri = entity==null ? null : serviceUriBuilder(ub, EntityConfigApi.class, "get").build(entity.getApplicationId(), entity.getId(), config.getName()); MutableMap.Builder<String, URI> lb = MutableMap.<String, URI>builder() -- .put("self", selfUri) -- .put("application", applicationUri) -- .put("entity", entityUri) -- .put("action:json", selfUri); ++ .putIfNotNull("self", selfUri) ++ // TODO wasteful including these on every item as it is just a list, remove ++ .putIfNotNull("application", applicationUri) ++ .putIfNotNull("entity", entityUri) ++ // TODO is this json or a display value? ++ .putIfNotNull("action:json", selfUri); Iterable<RendererHints.NamedAction> hints = Iterables.filter(RendererHints.getHintsFor(config), RendererHints.NamedAction.class); for (RendererHints.NamedAction na : hints) { -- SensorTransformer.addNamedAction(lb, na, entity.getConfig(config), config, entity); ++ if (entity!=null) { ++ SensorTransformer.addNamedAction(lb, na, entity.getConfig(config), config, entity); ++ } } -- return entityConfigSummary(config, label, priority, null, lb.build()); ++ return new EntityConfigSummary(config, label, priority, pinned, lb.build()); } public static URI applicationUri(Application entity, UriBuilder ub) { @@@ -188,6 -182,6 +208,8 @@@ return serviceUriBuilder(ub, EntityApi.class, "get").build(entity.getApplicationId(), entity.getId()); } ++ /** @deprecated since 0.13.0 use {@link #configSummary(BrooklynRestResourceUtils, UriBuilder, Entity, ConfigKey, CatalogConfig) */ ++ @Deprecated public static EntityConfigSummary entityConfigSummary(ConfigKey<?> config, Field configKeyField) { CatalogConfig catalogConfig = configKeyField!=null ? configKeyField.getAnnotation(CatalogConfig.class) : null; String label = catalogConfig==null ? null : catalogConfig.label(); @@@ -196,6 -190,6 +218,8 @@@ return entityConfigSummary(config, label, priority, pinned, null); } ++ /** @deprecated since 0.13.0 use {@link #configSummary(BrooklynRestResourceUtils, UriBuilder, Entity, ConfigKey, AtomicInteger) */ ++ @Deprecated public static EntityConfigSummary entityConfigSummary(SpecParameter<?> input, AtomicInteger paramPriorityCnt) { // Increment the priority because the config container is a set. Server-side we are using an ordered set // which results in correctly ordered items on the wire (as a list). Clients which use the java bindings @@@ -204,16 -198,17 +228,39 @@@ return entityConfigSummary(input.getConfigKey(), input.getLabel(), priority, input.isPinned(), null); } - public static AdjunctConfigSummary adjunctConfigSummary(SpecParameter<?> input) { ++ /** @deprecated since 0.13.0 use {@link #configSummary(BrooklynRestResourceUtils, UriBuilder, Entity, SpecParameter) */ ++ @Deprecated + public static ConfigSummary configSummary(SpecParameter<?> input) { - // could increment priority, or take from annotation, or introduce new field ++ // TODO could increment priority, or take from annotation, or introduce new field Double priority = input.isPinned() ? Double.valueOf(1d) : null; - return policyConfigSummary(input.getConfigKey(), input.getLabel(), priority, null); - return configSummary(input.getConfigKey(), input.getLabel(), priority, input.isPinned(), null); ++ return new EntityConfigSummary(input.getConfigKey(), input.getLabel(), priority, input.isPinned(), null); } ++ ++ public static ConfigSummary configSummary(BrooklynRestResourceUtils utils, UriBuilder ub, Entity entity, SpecParameter<?> input, AtomicInteger paramPriorityCnt) { ++ // Increment the priority because the config container is a set. Server-side we are using an ordered set ++ // which results in correctly ordered items on the wire (as a list). Clients which use the java bindings ++ // though will push the items in an unordered set - so give them means to recover the correct order. ++ Double priority = input.isPinned() ? Double.valueOf(paramPriorityCnt.incrementAndGet()) : null; ++ return configSummary(utils, ub, entity, input.getConfigKey(), input.getLabel(), priority, input.isPinned()); ++ } ++ ++ public static ConfigSummary configSummary(BrooklynRestResourceUtils utils, UriBuilder ub, Entity entity, SpecParameter<?> input) { ++ // TODO allow taking priority from a setting somewhere? ++ // (this just sets priority 1 if no value specified) ++ return configSummary(utils, ub, entity, input, new AtomicInteger(0)); ++ } ++ ++ ++ /** @deprecated since 0.13.0 use {@link AdjunctTransformer#configSummary(BrooklynRestResourceUtils, UriBuilder, Entity, org.apache.brooklyn.api.objs.EntityAdjunct, SpecParameter)} */ ++ @Deprecated public static PolicyConfigSummary policyConfigSummary(SpecParameter<?> input) { Double priority = input.isPinned() ? Double.valueOf(1d) : null; return policyConfigSummary(input.getConfigKey(), input.getLabel(), priority, null); } ++ /** @deprecated since 0.13.0 use {@link AdjunctTransformer#configSummary(BrooklynRestResourceUtils, UriBuilder, Entity, org.apache.brooklyn.api.objs.EntityAdjunct, SpecParameter)} */ ++ @Deprecated public static EnricherConfigSummary enricherConfigSummary(SpecParameter<?> input) { Double priority = input.isPinned() ? Double.valueOf(1d) : null; return enricherConfigSummary(input.getConfigKey(), input.getLabel(), priority, null); http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/62bcbc5f/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/transform/PolicyTransformer.java ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/62bcbc5f/rest/rest-resources/src/main/java/org/apache/brooklyn/rest/transform/TypeTransformer.java ---------------------------------------------------------------------- diff --cc rest/rest-resources/src/main/java/org/apache/brooklyn/rest/transform/TypeTransformer.java index fb3fdd3,e37ee6a..d081efd --- 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 @@@ -50,11 -50,11 +50,10 @@@ import org.apache.brooklyn.core.objs.Br import org.apache.brooklyn.core.typereg.RegisteredTypePredicates; import org.apache.brooklyn.core.typereg.RegisteredTypes; import org.apache.brooklyn.rest.api.TypeApi; - import org.apache.brooklyn.rest.domain.AdjunctConfigSummary; import org.apache.brooklyn.rest.domain.BundleInstallationRestResult; import org.apache.brooklyn.rest.domain.BundleSummary; + import org.apache.brooklyn.rest.domain.ConfigSummary; import org.apache.brooklyn.rest.domain.EffectorSummary; --import org.apache.brooklyn.rest.domain.EntityConfigSummary; import org.apache.brooklyn.rest.domain.SensorSummary; import org.apache.brooklyn.rest.domain.SummaryComparators; import org.apache.brooklyn.rest.domain.TypeDetail; @@@ -96,14 -96,14 +95,15 @@@ public class TypeTransformer RegisteredTypes.isSubtypeOf(item, Policy.class) || RegisteredTypes.isSubtypeOf(item, Enricher.class) || RegisteredTypes.isSubtypeOf(item, Feed.class) ) { try { - Set<AdjunctConfigSummary> config = Sets.newLinkedHashSet(); + Set<ConfigSummary> config = Sets.newLinkedHashSet(); AbstractBrooklynObjectSpec<?,?> spec = b.getTypeRegistry().createSpec(item, null, null); ++ AtomicInteger priority = new AtomicInteger(0); for (final SpecParameter<?> input : spec.getParameters()){ - config.add(EntityTransformer.adjunctConfigSummary(input)); - config.add(EntityTransformer.configSummary(input)); ++ config.add(EntityTransformer.configSummary(null, null, null, input, priority)); } - result.getExtraFields().put("config", config); + result.setExtraField("config", config); } catch (Exception e) { Exceptions.propagateIfFatal(e); log.trace("Unable to create spec for "+item+": "+e, e); @@@ -119,7 -119,7 +119,7 @@@ protected static <T extends TypeSummary> void embellishEntity(T result, RegisteredType item, BrooklynRestResourceUtils b) { try { -- Set<EntityConfigSummary> config = Sets.newLinkedHashSet(); ++ Set<ConfigSummary> config = Sets.newLinkedHashSet(); Set<SensorSummary> sensors = Sets.newTreeSet(SummaryComparators.nameComparator()); Set<EffectorSummary> effectors = Sets.newTreeSet(SummaryComparators.nameComparator()); @@@ -129,7 -129,7 +129,7 @@@ AtomicInteger paramPriorityCnt = new AtomicInteger(); for (SpecParameter<?> input: spec.getParameters()) -- config.add(EntityTransformer.entityConfigSummary(input, paramPriorityCnt)); ++ config.add(EntityTransformer.configSummary(null, null, null, input, paramPriorityCnt)); for (Sensor<?> x: type.getSensors()) sensors.add(SensorTransformer.sensorSummaryForCatalog(x)); for (Effector<?> x: type.getEffectors()) http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/62bcbc5f/server-cli/src/main/java/org/apache/brooklyn/cli/lister/ItemDescriptors.java ---------------------------------------------------------------------- diff --cc server-cli/src/main/java/org/apache/brooklyn/cli/lister/ItemDescriptors.java index f245d06,f245d06..61a7a2a --- a/server-cli/src/main/java/org/apache/brooklyn/cli/lister/ItemDescriptors.java +++ b/server-cli/src/main/java/org/apache/brooklyn/cli/lister/ItemDescriptors.java @@@ -18,16 -18,16 +18,18 @@@ */ package org.apache.brooklyn.cli.lister; --import java.net.URI; ++import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Set; ++import java.util.concurrent.atomic.AtomicInteger; import org.apache.brooklyn.api.catalog.BrooklynCatalog; import org.apache.brooklyn.api.catalog.Catalog; ++import org.apache.brooklyn.api.catalog.CatalogConfig; import org.apache.brooklyn.api.catalog.CatalogItem; import org.apache.brooklyn.api.effector.Effector; import org.apache.brooklyn.api.entity.EntityType; @@@ -41,8 -41,8 +43,8 @@@ import org.apache.brooklyn.config.Confi import org.apache.brooklyn.core.entity.BrooklynConfigKeys; import org.apache.brooklyn.core.objs.BrooklynDynamicType; import org.apache.brooklyn.core.objs.BrooklynTypes; ++import org.apache.brooklyn.rest.domain.ConfigSummary; import org.apache.brooklyn.rest.domain.EffectorSummary; --import org.apache.brooklyn.rest.domain.EntityConfigSummary; import org.apache.brooklyn.rest.domain.SensorSummary; import org.apache.brooklyn.rest.domain.SummaryComparators; import org.apache.brooklyn.rest.transform.EffectorTransformer; @@@ -131,12 -131,12 +133,14 @@@ public class ItemDescriptors } if (!headingsOnly) { -- Set<EntityConfigSummary> config = Sets.newTreeSet(SummaryComparators.nameComparator()); ++ Set<ConfigSummary> config = Sets.newTreeSet(SummaryComparators.nameComparator()); Set<SensorSummary> sensors = Sets.newTreeSet(SummaryComparators.nameComparator()); Set<EffectorSummary> effectors = Sets.newTreeSet(SummaryComparators.nameComparator()); for (ConfigKey<?> x: type.getConfigKeys()) { -- config.add(EntityTransformer.entityConfigSummary(x, dynamicType.getConfigKeyField(x.getName()))); ++ Field field = dynamicType.getConfigKeyField(x.getName()); ++ CatalogConfig annotation = field==null ? null : field.getAnnotation(CatalogConfig.class); ++ config.add(EntityTransformer.configSummary(null, null, null, x, annotation)); } result.put("config", config); @@@ -184,7 -184,7 +188,7 @@@ public static Map<String, Object> toItemDescriptor(BrooklynCatalog catalog, CatalogItem<?, ?> item, boolean headingsOnly) { Map<String,Object> itemDescriptor = MutableMap.of(); AbstractBrooklynObjectSpec<?,?> spec = catalog.peekSpec(item); -- List<EntityConfigSummary> config = new ArrayList<>(); ++ List<ConfigSummary> config = new ArrayList<>(); if (item.getDisplayName() != null) { itemDescriptor.put("name", item.getDisplayName()); @@@ -199,19 -199,19 +203,9 @@@ itemDescriptor.put("iconUrl", blankIfNull(item.getIconUrl())); if (!headingsOnly) { -- double priorityCounter = 0.0d; ++ AtomicInteger priority = new AtomicInteger(0); for (SpecParameter<?> param: spec.getParameters()) { -- Double priority; -- if (param.isPinned()) { -- priority = priorityCounter; -- priorityCounter++; -- } else { -- priority = null; -- } -- -- EntityConfigSummary entityConfigSummary = EntityTransformer.entityConfigSummary(param.getConfigKey(), -- param.getLabel(), priority, param.isPinned(), MutableMap.<String,URI>of()); -- config.add(entityConfigSummary); ++ config.add(EntityTransformer.configSummary(null, null, null, param, priority)); } itemDescriptor.put("config", config); }
