Expose features in /v1/server/version response
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/283b6e3e Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/283b6e3e Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/283b6e3e Branch: refs/heads/master Commit: 283b6e3ea335c14a19a1eb9dfbe2b9fadeb9e80e Parents: f187073 Author: Sam Corbett <[email protected]> Authored: Tue Jun 2 18:05:54 2015 +0100 Committer: Sam Corbett <[email protected]> Committed: Tue Jun 2 18:07:41 2015 +0100 ---------------------------------------------------------------------- .../rest/domain/BrooklynFeatureSummary.java | 91 ++++++++++++++++++++ .../brooklyn/rest/domain/VersionSummary.java | 20 ++++- .../rest/domain/VersionSummaryTest.java | 62 +++++++++++++ .../test/resources/fixtures/server-version.json | 14 +++ .../brooklyn/rest/resources/ServerResource.java | 24 +++--- .../transform/BrooklynFeatureTransformer.java | 45 ++++++++++ .../rest/transform/PolicyTransformer.java | 1 - .../rest/transform/SensorTransformer.java | 3 +- 8 files changed, 243 insertions(+), 17 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/283b6e3e/usage/rest-api/src/main/java/brooklyn/rest/domain/BrooklynFeatureSummary.java ---------------------------------------------------------------------- diff --git a/usage/rest-api/src/main/java/brooklyn/rest/domain/BrooklynFeatureSummary.java b/usage/rest-api/src/main/java/brooklyn/rest/domain/BrooklynFeatureSummary.java new file mode 100644 index 0000000..461be65 --- /dev/null +++ b/usage/rest-api/src/main/java/brooklyn/rest/domain/BrooklynFeatureSummary.java @@ -0,0 +1,91 @@ +/* + * 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 brooklyn.rest.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.io.Serializable; +import java.util.Map; + +import org.codehaus.jackson.annotate.JsonAnyGetter; +import org.codehaus.jackson.annotate.JsonAnySetter; +import org.codehaus.jackson.annotate.JsonIgnore; +import org.codehaus.jackson.annotate.JsonProperty; + +import com.google.common.collect.Maps; + +public class BrooklynFeatureSummary implements Serializable { + + private static final long serialVersionUID = 4595452639602650453L; + + private final String name; + private final String symbolicName; + private final String version; + private final String lastModified; + private Map<String, String> additionalData = Maps.newHashMap(); + + public BrooklynFeatureSummary( + @JsonProperty("name") String name, + @JsonProperty("symbolicName") String symbolicName, + @JsonProperty("version") String version, + @JsonProperty("lastModified") String lastModified) { + this.symbolicName = checkNotNull(symbolicName, "symbolicName"); + this.name = name; + this.version = version; + this.lastModified = lastModified; + } + + public BrooklynFeatureSummary(String name, String symbolicName, String version, String lastModified, Map<String, String> additionalData) { + this(name, symbolicName, version, lastModified); + this.additionalData = additionalData; + } + + @JsonIgnore + public Map<String, String> getAdditionalData() { + return additionalData; + } + + public String getLastModified() { + return lastModified; + } + + public String getName() { + return name; + } + + public String getSymbolicName() { + return symbolicName; + } + + public String getVersion() { + return version; + } + + @JsonAnyGetter + private Map<String, String> any() { + return additionalData; + } + + @JsonAnySetter + private void set(String name, String value) { + additionalData.put(name, value); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/283b6e3e/usage/rest-api/src/main/java/brooklyn/rest/domain/VersionSummary.java ---------------------------------------------------------------------- diff --git a/usage/rest-api/src/main/java/brooklyn/rest/domain/VersionSummary.java b/usage/rest-api/src/main/java/brooklyn/rest/domain/VersionSummary.java index 7b1d6e0..0127735 100644 --- a/usage/rest-api/src/main/java/brooklyn/rest/domain/VersionSummary.java +++ b/usage/rest-api/src/main/java/brooklyn/rest/domain/VersionSummary.java @@ -21,6 +21,9 @@ package brooklyn.rest.domain; import static com.google.common.base.Preconditions.checkNotNull; import java.io.Serializable; +import java.util.Collections; +import java.util.List; +import java.util.Map; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -34,18 +37,25 @@ public class VersionSummary implements Serializable { private final String version; private final String buildSha1; private final String buildBranch; + private final List<BrooklynFeatureSummary> features; public VersionSummary(String version) { this(version, null, null); } + public VersionSummary(String version, String buildSha1, String buildBranch) { + this(version, buildSha1, buildBranch, Collections.<BrooklynFeatureSummary>emptyList()); + } + public VersionSummary( @JsonProperty("version") String version, - @JsonProperty("buildSha1")String buildSha1, - @JsonProperty("buildBranch") String buildBranch) { + @JsonProperty("buildSha1") String buildSha1, + @JsonProperty("buildBranch") String buildBranch, + @JsonProperty("features") List<BrooklynFeatureSummary> features) { this.version = checkNotNull(version, "version"); this.buildSha1 = buildSha1; this.buildBranch = buildBranch; + this.features = checkNotNull(features, "features"); } @Nonnull @@ -62,4 +72,10 @@ public class VersionSummary implements Serializable { public String getBuildBranch() { return buildBranch; } + + @Nonnull + public List<BrooklynFeatureSummary> getFeatures() { + return features; + } + } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/283b6e3e/usage/rest-api/src/test/java/brooklyn/rest/domain/VersionSummaryTest.java ---------------------------------------------------------------------- diff --git a/usage/rest-api/src/test/java/brooklyn/rest/domain/VersionSummaryTest.java b/usage/rest-api/src/test/java/brooklyn/rest/domain/VersionSummaryTest.java new file mode 100644 index 0000000..eea0249 --- /dev/null +++ b/usage/rest-api/src/test/java/brooklyn/rest/domain/VersionSummaryTest.java @@ -0,0 +1,62 @@ +/* + * 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 brooklyn.rest.domain; + +import static brooklyn.rest.util.RestApiTestUtils.asJson; +import static brooklyn.rest.util.RestApiTestUtils.fromJson; +import static brooklyn.rest.util.RestApiTestUtils.jsonFixture; +import static org.testng.Assert.assertEquals; + +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; + +public class VersionSummaryTest { + + BrooklynFeatureSummary features = new BrooklynFeatureSummary( + "Sample Brooklyn Project com.acme.sample:brooklyn-sample v0.1.0-SNAPSHOT", + "com.acme.sample.brooklyn-sample", + "0.1.0.SNAPSHOT", + "523305000", + ImmutableMap.of("Brooklyn-Feature-Build-Id", "e0fee1adf795c84eec4735f039503eb18d9c35cc") + ); + VersionSummary summary = new VersionSummary( + "0.7.0-SNAPSHOT", + "cb4f0a3af2f5042222dd176edc102bfa64e7e0b5", + "versions", + ImmutableList.of(features) + ); + + @Test + public void testSerialize() { + assertEquals(asJson(summary), jsonFixture("fixtures/server-version.json")); + } + + @Test + public void testDeserialize() { + VersionSummary deserialized = fromJson(jsonFixture("fixtures/server-version.json"), VersionSummary.class); + assertEquals(deserialized.getBuildSha1(), summary.getBuildSha1()); + assertEquals(deserialized.getFeatures().size(), 1); + assertEquals(deserialized.getFeatures().get(0).getSymbolicName(), features.getSymbolicName()); + assertEquals(deserialized.getFeatures().get(0).getAdditionalData().get("Brooklyn-Feature-Build-Id"), "e0fee1adf795c84eec4735f039503eb18d9c35cc"); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/283b6e3e/usage/rest-api/src/test/resources/fixtures/server-version.json ---------------------------------------------------------------------- diff --git a/usage/rest-api/src/test/resources/fixtures/server-version.json b/usage/rest-api/src/test/resources/fixtures/server-version.json new file mode 100644 index 0000000..affd707 --- /dev/null +++ b/usage/rest-api/src/test/resources/fixtures/server-version.json @@ -0,0 +1,14 @@ +{ + "version": "0.7.0-SNAPSHOT", + "buildSha1": "cb4f0a3af2f5042222dd176edc102bfa64e7e0b5", + "buildBranch":"versions", + "features":[ + { + "name": "Sample Brooklyn Project com.acme.sample:brooklyn-sample v0.1.0-SNAPSHOT", + "symbolicName":"com.acme.sample.brooklyn-sample", + "version":"0.1.0.SNAPSHOT", + "lastModified":"523305000", + "Brooklyn-Feature-Build-Id":"e0fee1adf795c84eec4735f039503eb18d9c35cc" + } + ] +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/283b6e3e/usage/rest-server/src/main/java/brooklyn/rest/resources/ServerResource.java ---------------------------------------------------------------------- diff --git a/usage/rest-server/src/main/java/brooklyn/rest/resources/ServerResource.java b/usage/rest-server/src/main/java/brooklyn/rest/resources/ServerResource.java index cc1c312..1bb3d95 100644 --- a/usage/rest-server/src/main/java/brooklyn/rest/resources/ServerResource.java +++ b/usage/rest-server/src/main/java/brooklyn/rest/resources/ServerResource.java @@ -23,6 +23,7 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Properties; @@ -57,8 +58,10 @@ import brooklyn.management.ha.ManagementPlaneSyncRecord; import brooklyn.management.ha.MementoCopyMode; import brooklyn.management.internal.ManagementContextInternal; import brooklyn.rest.api.ServerApi; +import brooklyn.rest.domain.BrooklynFeatureSummary; import brooklyn.rest.domain.HighAvailabilitySummary; import brooklyn.rest.domain.VersionSummary; +import brooklyn.rest.transform.BrooklynFeatureTransformer; import brooklyn.rest.transform.HighAvailabilityTransformer; import brooklyn.rest.util.WebResourceUtils; import brooklyn.util.ResourceUtils; @@ -75,6 +78,7 @@ import brooklyn.util.time.Duration; import brooklyn.util.time.Time; import com.google.common.base.Preconditions; +import com.google.common.collect.FluentIterable; public class ServerResource extends AbstractBrooklynRestResource implements ServerApi { @@ -255,21 +259,10 @@ public class ServerResource extends AbstractBrooklynRestResource implements Serv if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.SERVER_STATUS, null)) throw WebResourceUtils.unauthorized("User '%s' is not authorized for this operation", Entitlements.getEntitlementContext().user()); - // TODO reconcile this with BrooklynVersion reading from the OSGi manifest - // @ahgittin / @sjcorbett to decide, is there need for this in addition to the OSGi manifest? - // TODO as part of this call should we have a strategy for reporting downstream builds in this call? - // for instance, we could look for - // * ALL "brooklyn-build-metadata.properties" files on the classpath - // * and/or ALL items on classpath with a custom header (eg "Brooklyn-OSGi-Feature-Name: My Project") in MANIFEST.MF - // i tend to favour the latter as MANIFEST.MF is already recognised; is there a reason to introduce a new file? - // whichever we do, i think: + // TODO // * "build-metadata.properties" is probably the wrong name // * we should include brooklyn.version and a build timestamp in this file // * the authority for brooklyn should probably be core rather than brooklyn-rest-server - - // TODO in version summary, maybe also have: - // features: [ { name: my-project, version: 0.1.0-SNAPSHOT, git-sha1: xxx }, ... ] - // osgi: [ /* similar metadata extracted from all active osgi bundles */ ] InputStream input = ResourceUtils.create().getResourceFromUrl("classpath://build-metadata.properties"); Properties properties = new Properties(); String gitSha1 = null, gitBranch = null; @@ -280,7 +273,12 @@ public class ServerResource extends AbstractBrooklynRestResource implements Serv } catch (IOException e) { log.error("Failed to load build-metadata.properties", e); } - return new VersionSummary(BrooklynVersion.get(), gitSha1, gitBranch); + gitSha1 = BrooklynVersion.INSTANCE.getSha1FromOsgiManifest(); + + FluentIterable<BrooklynFeatureSummary> features = FluentIterable.from(BrooklynVersion.getFeatures(mgmt())) + .transform(BrooklynFeatureTransformer.FROM_FEATURE); + + return new VersionSummary(BrooklynVersion.get(), gitSha1, gitBranch, features.toList()); } @Override http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/283b6e3e/usage/rest-server/src/main/java/brooklyn/rest/transform/BrooklynFeatureTransformer.java ---------------------------------------------------------------------- diff --git a/usage/rest-server/src/main/java/brooklyn/rest/transform/BrooklynFeatureTransformer.java b/usage/rest-server/src/main/java/brooklyn/rest/transform/BrooklynFeatureTransformer.java new file mode 100644 index 0000000..7dc9b8b --- /dev/null +++ b/usage/rest-server/src/main/java/brooklyn/rest/transform/BrooklynFeatureTransformer.java @@ -0,0 +1,45 @@ +/* + * 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 brooklyn.rest.transform; + +import com.google.common.base.Function; + +import brooklyn.BrooklynVersion.BrooklynFeature; +import brooklyn.rest.domain.BrooklynFeatureSummary; + +public class BrooklynFeatureTransformer { + + public static final Function<BrooklynFeature, BrooklynFeatureSummary> FROM_FEATURE = new Function<BrooklynFeature, BrooklynFeatureSummary>() { + @Override + public BrooklynFeatureSummary apply(BrooklynFeature feature) { + return featureSummary(feature); + } + }; + + public static BrooklynFeatureSummary featureSummary(BrooklynFeature feature) { + return new BrooklynFeatureSummary( + feature.getName(), + feature.getSymbolicName(), + feature.getVersion(), + feature.getLastModified(), + feature.getAdditionalData()); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/283b6e3e/usage/rest-server/src/main/java/brooklyn/rest/transform/PolicyTransformer.java ---------------------------------------------------------------------- diff --git a/usage/rest-server/src/main/java/brooklyn/rest/transform/PolicyTransformer.java b/usage/rest-server/src/main/java/brooklyn/rest/transform/PolicyTransformer.java index 84baf3b..9478de7 100644 --- a/usage/rest-server/src/main/java/brooklyn/rest/transform/PolicyTransformer.java +++ b/usage/rest-server/src/main/java/brooklyn/rest/transform/PolicyTransformer.java @@ -38,7 +38,6 @@ import com.google.common.collect.ImmutableMap; * Converts from Brooklyn entities to restful API summary objects */ public class PolicyTransformer { -// private static final org.slf4j.Logger log = LoggerFactory.getLogger(PolicyTransformer.class); public static PolicySummary policySummary(Entity entity, Policy policy) { String applicationUri = "/v1/applications/" + entity.getApplicationId(); http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/283b6e3e/usage/rest-server/src/main/java/brooklyn/rest/transform/SensorTransformer.java ---------------------------------------------------------------------- diff --git a/usage/rest-server/src/main/java/brooklyn/rest/transform/SensorTransformer.java b/usage/rest-server/src/main/java/brooklyn/rest/transform/SensorTransformer.java index 21a4598..4246785 100644 --- a/usage/rest-server/src/main/java/brooklyn/rest/transform/SensorTransformer.java +++ b/usage/rest-server/src/main/java/brooklyn/rest/transform/SensorTransformer.java @@ -20,6 +20,7 @@ package brooklyn.rest.transform; import java.net.URI; +import org.slf4j.Logger; import org.slf4j.LoggerFactory; import brooklyn.config.render.RendererHints; @@ -36,7 +37,7 @@ import com.google.common.collect.Iterables; public class SensorTransformer { - private static final org.slf4j.Logger log = LoggerFactory.getLogger(SensorTransformer.class); + private static final Logger log = LoggerFactory.getLogger(SensorTransformer.class); public static SensorSummary sensorSummaryForCatalog(Sensor<?> sensor) { return new SensorSummary(sensor.getName(), sensor.getTypeName(),
