Repository: incubator-brooklyn Updated Branches: refs/heads/master 0f6041e41 -> fb6a4a1d0
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6ed695e5/core/src/test/resources/org/apache/brooklyn/core/test/camp/brooklyn/lite/test-app-service-blueprint.yaml ---------------------------------------------------------------------- diff --git a/core/src/test/resources/org/apache/brooklyn/core/test/camp/brooklyn/lite/test-app-service-blueprint.yaml b/core/src/test/resources/org/apache/brooklyn/core/test/camp/brooklyn/lite/test-app-service-blueprint.yaml deleted file mode 100644 index c0bb607..0000000 --- a/core/src/test/resources/org/apache/brooklyn/core/test/camp/brooklyn/lite/test-app-service-blueprint.yaml +++ /dev/null @@ -1,38 +0,0 @@ -# -# 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. -# -name: sample -description: Tomcat sample JSP and servlet application. -origin: http://www.oracle.com/nCAMP/Hand -services: - - - type: io.camp.mock:AppServer - name: Hello WAR - wars: - /: hello.war - controller.spec: - port: 80 - -brooklyn.catalog: - name: catalog-name - type: io.camp.mock.MyApplication - version: 0.9 - libraries: - - name: org.apache.brooklyn.test.resources.osgi.brooklyn-test-osgi-entities - version: 0.1.0 - url: classpath:/brooklyn/osgi/brooklyn-test-osgi-entities.jar \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6ed695e5/usage/camp/pom.xml ---------------------------------------------------------------------- diff --git a/usage/camp/pom.xml b/usage/camp/pom.xml index 9a643e1..34da33c 100644 --- a/usage/camp/pom.xml +++ b/usage/camp/pom.xml @@ -36,6 +36,11 @@ <dependencies> <dependency> + <groupId>org.apache.brooklyn.camp</groupId> + <artifactId>camp-base</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> <groupId>org.apache.brooklyn</groupId> <artifactId>brooklyn-core</artifactId> <version>${project.version}</version> @@ -112,6 +117,13 @@ <!-- demo and tests --> <dependency> + <groupId>org.apache.brooklyn.camp</groupId> + <artifactId>camp-base</artifactId> + <version>${project.version}</version> + <classifier>tests</classifier> + <scope>test</scope> + </dependency> + <dependency> <groupId>org.apache.brooklyn</groupId> <artifactId>brooklyn-core</artifactId> <version>${project.version}</version> http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6ed695e5/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/BrooklynCampConstants.java ---------------------------------------------------------------------- diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/BrooklynCampConstants.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/BrooklynCampConstants.java index 09dcd78..515ec9f 100644 --- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/BrooklynCampConstants.java +++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/BrooklynCampConstants.java @@ -43,7 +43,8 @@ public class BrooklynCampConstants { .inheritance(ConfigInheritance.NONE) .build(); - public static final ConfigKey<CampPlatform> CAMP_PLATFORM = BrooklynServerConfig.CAMP_PLATFORM; + public static final ConfigKey<CampPlatform> CAMP_PLATFORM = ConfigKeys.newConfigKey(CampPlatform.class, "brooklyn.camp.platform", + "Config set at brooklyn management platform to find the CampPlatform instance (bi-directional)"); public static final Set<String> YAML_URL_PROTOCOL_WHITELIST = ImmutableSet.of("classpath", "http"); } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6ed695e5/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/api/AssemblyTemplateSpecInstantiator.java ---------------------------------------------------------------------- diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/api/AssemblyTemplateSpecInstantiator.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/api/AssemblyTemplateSpecInstantiator.java new file mode 100644 index 0000000..c345a9d --- /dev/null +++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/api/AssemblyTemplateSpecInstantiator.java @@ -0,0 +1,35 @@ +/* + * 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.camp.brooklyn.api; + +import java.util.Set; + +import org.apache.brooklyn.api.entity.EntitySpec; +import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext; +import org.apache.brooklyn.camp.CampPlatform; +import org.apache.brooklyn.camp.spi.AssemblyTemplate; +import org.apache.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator; + +public interface AssemblyTemplateSpecInstantiator extends AssemblyTemplateInstantiator { + + EntitySpec<?> createSpec(AssemblyTemplate template, CampPlatform platform, BrooklynClassLoadingContext loader, boolean autoUnwrapIfAppropriate); + EntitySpec<?> createNestedSpec(AssemblyTemplate template, CampPlatform platform, BrooklynClassLoadingContext itemLoader, Set<String> encounteredCatalogTypes); + + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6ed695e5/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java ---------------------------------------------------------------------- diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java index 82bef64..8285a26 100644 --- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java +++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynAssemblyTemplateInstantiator.java @@ -26,8 +26,6 @@ import java.util.List; import java.util.Map.Entry; import java.util.Set; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.apache.brooklyn.api.catalog.CatalogItem; import org.apache.brooklyn.api.entity.Application; import org.apache.brooklyn.api.entity.Entity; @@ -40,20 +38,23 @@ import org.apache.brooklyn.camp.brooklyn.api.AssemblyTemplateSpecInstantiator; import org.apache.brooklyn.camp.brooklyn.api.HasBrooklynManagementContext; import org.apache.brooklyn.camp.spi.Assembly; import org.apache.brooklyn.camp.spi.AssemblyTemplate; -import org.apache.brooklyn.camp.spi.PlatformComponentTemplate; import org.apache.brooklyn.camp.spi.AssemblyTemplate.Builder; +import org.apache.brooklyn.camp.spi.PlatformComponentTemplate; import org.apache.brooklyn.camp.spi.collection.ResolvableLink; import org.apache.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator; -import org.apache.brooklyn.core.catalog.internal.CatalogUtils; import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog.BrooklynLoaderTracker; +import org.apache.brooklyn.core.catalog.internal.CatalogUtils; import org.apache.brooklyn.core.mgmt.EntityManagementUtils; import org.apache.brooklyn.core.mgmt.EntityManagementUtils.CreationResult; -import org.apache.brooklyn.core.server.BrooklynServerConfig; +import org.apache.brooklyn.core.mgmt.classloading.JavaBrooklynClassLoadingContext; +import org.apache.brooklyn.entity.core.Entities; import org.apache.brooklyn.entity.stock.BasicApplicationImpl; import org.apache.brooklyn.util.core.ResourceUtils; import org.apache.brooklyn.util.core.flags.TypeCoercions; import org.apache.brooklyn.util.exceptions.Exceptions; import org.apache.brooklyn.util.net.Urls; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; @@ -74,11 +75,15 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe } public Application create(AssemblyTemplate template, CampPlatform platform) { - Application instance = EntityManagementUtils.createUnstarted(getBrooklynManagementContext(platform), template); - log.debug("CAMP created {}", instance); + ManagementContext mgmt = getBrooklynManagementContext(platform); + BrooklynClassLoadingContext loader = JavaBrooklynClassLoadingContext.create(mgmt); + EntitySpec<? extends Application> spec = createSpec(template, platform, loader, true); + Application instance = mgmt.getEntityManager().createEntity(spec); + log.info("CAMP placing '{}' under management", instance); + Entities.startManagement(instance, mgmt); return instance; } - + private ManagementContext getBrooklynManagementContext(CampPlatform platform) { return ((HasBrooklynManagementContext)platform).getBrooklynManagementContext(); } @@ -92,6 +97,7 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe BrooklynComponentTemplateResolver resolver = BrooklynComponentTemplateResolver.Factory.newInstance( loader, buildWrapperAppTemplate(template)); EntitySpec<? extends Application> app = resolver.resolveSpec(null); + app.configure(EntityManagementUtils.WRAPPER_APP_MARKER, Boolean.TRUE); // first build the children into an empty shell app List<EntitySpec<?>> childSpecs = buildTemplateServicesAsSpecs(loader, template, platform); @@ -106,8 +112,6 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe // if promoted, apply the transformations done to the app // (transformations will be done by the resolveSpec call above, but we are collapsing oldApp so transfer to app=newApp) EntityManagementUtils.collapseSpec(oldApp, app); - } else { - app.configure(EntityManagementUtils.WRAPPER_APP_MARKER, Boolean.TRUE); } return app; @@ -141,7 +145,7 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe if (childSpec.getType()==null || !Application.class.isAssignableFrom(childSpec.getType())) return false; - return EntityManagementUtils.hasNoNameOrCustomKeysOrRoot(template, app); + return EntityManagementUtils.canPromote(app); } private List<EntitySpec<?>> buildTemplateServicesAsSpecs(BrooklynClassLoadingContext loader, AssemblyTemplate template, CampPlatform platform) { @@ -154,14 +158,16 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe for (ResolvableLink<PlatformComponentTemplate> ctl: template.getPlatformComponentTemplates().links()) { PlatformComponentTemplate appChildComponentTemplate = ctl.resolve(); BrooklynComponentTemplateResolver entityResolver = BrooklynComponentTemplateResolver.Factory.newInstance(loader, appChildComponentTemplate); - EntitySpec<?> spec = resolveSpec(ResourceUtils.create(this), entityResolver, encounteredCatalogTypes); + EntitySpec<?> spec = resolveSpec(platform, ResourceUtils.create(this), entityResolver, encounteredCatalogTypes); result.add(spec); } return result; } - static EntitySpec<?> resolveSpec(ResourceUtils ru, + static EntitySpec<?> resolveSpec( + CampPlatform platform, + ResourceUtils ru, BrooklynComponentTemplateResolver entityResolver, Set<String> encounteredCatalogTypes) { String brooklynType = entityResolver.getServiceTypeResolver().getBrooklynType(entityResolver.getDeclaredType()); @@ -173,7 +179,7 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe String protocol = Urls.getProtocol(brooklynType); if (protocol != null) { if (BrooklynCampConstants.YAML_URL_PROTOCOL_WHITELIST.contains(protocol)) { - spec = tryResolveYamlUrlReferenceSpec(ru, brooklynType, entityResolver.getLoader(), encounteredCatalogTypes); + spec = tryResolveYamlUrlReferenceSpec(platform, ru, brooklynType, entityResolver.getLoader(), encounteredCatalogTypes); if (spec != null) { entityResolver.populateSpec(spec); } @@ -196,10 +202,10 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe } private static EntitySpec<?> tryResolveYamlUrlReferenceSpec( + CampPlatform platform, ResourceUtils ru, String brooklynType, BrooklynClassLoadingContext itemLoader, Set<String> encounteredCatalogTypes) { - ManagementContext mgmt = itemLoader.getManagementContext(); Reader yaml; try { yaml = new InputStreamReader(ru.getResourceFromUrl(brooklynType), "UTF-8"); @@ -208,7 +214,7 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe return null; } try { - return createNestedSpec(mgmt, encounteredCatalogTypes, yaml, itemLoader); + return createNestedSpec(platform, encounteredCatalogTypes, yaml, itemLoader); } finally { try { yaml.close(); @@ -219,21 +225,20 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe } static EntitySpec<?> resolveCatalogYamlReferenceSpec( - ManagementContext mgmt, + CampPlatform platform, CatalogItem<Entity, EntitySpec<?>> item, Set<String> encounteredCatalogTypes) { - + ManagementContext mgmt = getManagementContext(platform); String yaml = item.getPlanYaml(); Reader input = new StringReader(yaml); BrooklynClassLoadingContext itemLoader = CatalogUtils.newClassLoadingContext(mgmt, item); - return createNestedSpec(mgmt, encounteredCatalogTypes, input, itemLoader); + return createNestedSpec(platform, encounteredCatalogTypes, input, itemLoader); } - private static EntitySpec<?> createNestedSpec(ManagementContext mgmt, + private static EntitySpec<?> createNestedSpec(CampPlatform platform, Set<String> encounteredCatalogTypes, Reader input, BrooklynClassLoadingContext itemLoader) { - CampPlatform platform = BrooklynServerConfig.getCampPlatform(mgmt).get(); AssemblyTemplate at; BrooklynLoaderTracker.setLoader(itemLoader); @@ -277,4 +282,8 @@ public class BrooklynAssemblyTemplateInstantiator implements AssemblyTemplateSpe } } + private static ManagementContext getManagementContext(CampPlatform platform) { + return ((HasBrooklynManagementContext)platform).getBrooklynManagementContext(); + } + } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6ed695e5/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java ---------------------------------------------------------------------- diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java index f858370..32bfa24 100644 --- a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java +++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java @@ -28,8 +28,6 @@ import java.util.concurrent.atomic.AtomicBoolean; import javax.annotation.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.apache.brooklyn.api.catalog.CatalogItem; import org.apache.brooklyn.api.entity.Application; import org.apache.brooklyn.api.entity.Entity; @@ -37,6 +35,7 @@ import org.apache.brooklyn.api.entity.EntitySpec; import org.apache.brooklyn.api.location.Location; import org.apache.brooklyn.api.mgmt.ManagementContext; import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext; +import org.apache.brooklyn.camp.CampPlatform; import org.apache.brooklyn.camp.brooklyn.BrooklynCampConstants; import org.apache.brooklyn.camp.brooklyn.BrooklynCampReservedKeys; import org.apache.brooklyn.camp.brooklyn.spi.creation.service.BrooklynServiceTypeResolver; @@ -65,6 +64,8 @@ import org.apache.brooklyn.util.core.task.Tasks; import org.apache.brooklyn.util.guava.Maybe; import org.apache.brooklyn.util.javalang.Reflections; 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.Splitter; @@ -250,7 +251,7 @@ public class BrooklynComponentTemplateResolver { // including it's OSGi bundles in the loader classpath. } else { // TODO perhaps migrate to catalog.createSpec ? - EntitySpec<?> spec = BrooklynAssemblyTemplateInstantiator.resolveCatalogYamlReferenceSpec(mgmt, item, encounteredCatalogTypes); + EntitySpec<?> spec = BrooklynAssemblyTemplateInstantiator.resolveCatalogYamlReferenceSpec(getCampPlatform(), item, encounteredCatalogTypes); spec.catalogItemId(item.getId()); return (EntitySpec<T>)spec; @@ -303,7 +304,7 @@ public class BrooklynComponentTemplateResolver { Iterable<Map<String,?>> children = (Iterable<Map<String,?>>)childrenObj; for (Map<String,?> childAttrs : children) { BrooklynComponentTemplateResolver entityResolver = BrooklynComponentTemplateResolver.Factory.newInstance(loader, childAttrs); - EntitySpec<? extends Entity> childSpec = BrooklynAssemblyTemplateInstantiator.resolveSpec(ResourceUtils.create(this), entityResolver, encounteredCatalogTypes); + EntitySpec<? extends Entity> childSpec = BrooklynAssemblyTemplateInstantiator.resolveSpec(getCampPlatform(), ResourceUtils.create(this), entityResolver, encounteredCatalogTypes); spec.child(childSpec); } } @@ -486,4 +487,7 @@ public class BrooklynComponentTemplateResolver { return (List<Map<String, Object>>) attrs.get(BrooklynCampReservedKeys.BROOKLYN_CHILDREN); } + private CampPlatform getCampPlatform() { + return CampCatalogUtils.getCampPlatform(mgmt); + } } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6ed695e5/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampCatalogUtils.java ---------------------------------------------------------------------- diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampCatalogUtils.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampCatalogUtils.java new file mode 100644 index 0000000..71aded1 --- /dev/null +++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampCatalogUtils.java @@ -0,0 +1,244 @@ +/* + * 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.camp.brooklyn.spi.creation; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Map; +import java.util.Set; + +import org.apache.brooklyn.api.catalog.CatalogItem; +import org.apache.brooklyn.api.catalog.CatalogItem.CatalogItemType; +import org.apache.brooklyn.api.entity.EntitySpec; +import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec; +import org.apache.brooklyn.api.location.Location; +import org.apache.brooklyn.api.location.LocationSpec; +import org.apache.brooklyn.api.mgmt.ManagementContext; +import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext; +import org.apache.brooklyn.api.policy.Policy; +import org.apache.brooklyn.api.policy.PolicySpec; +import org.apache.brooklyn.camp.CampPlatform; +import org.apache.brooklyn.camp.brooklyn.BrooklynCampConstants; +import org.apache.brooklyn.camp.brooklyn.api.AssemblyTemplateSpecInstantiator; +import org.apache.brooklyn.camp.spi.AssemblyTemplate; +import org.apache.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator; +import org.apache.brooklyn.camp.spi.pdp.DeploymentPlan; +import org.apache.brooklyn.camp.util.yaml.Yamls; +import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog; +import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog.BrooklynLoaderTracker; +import org.apache.brooklyn.core.catalog.internal.CatalogUtils; +import org.apache.brooklyn.core.objs.BrooklynObjectInternal.ConfigurationSupportInternal; +import org.apache.brooklyn.util.collections.MutableSet; +import org.apache.brooklyn.util.exceptions.Exceptions; +import org.apache.brooklyn.util.guava.Maybe; +import org.apache.brooklyn.util.stream.Streams; +import org.apache.brooklyn.util.text.Strings; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; + +public class CampCatalogUtils { + + public static AbstractBrooklynObjectSpec<?, ?> createSpec(ManagementContext mgmt, CatalogItem<?, ?> item) { + // preferred way is to parse the yaml, to resolve references late; + // the parsing on load is to populate some fields, but it is optional. + // TODO messy for location and policy that we need brooklyn.{locations,policies} root of the yaml, but it works; + // see related comment when the yaml is set, in addAbstractCatalogItems + // (not sure if anywhere else relies on that syntax; if not, it should be easy to fix!) + BrooklynClassLoadingContext loader = CatalogUtils.newClassLoadingContext(mgmt, item); + DeploymentPlan plan = makePlanFromYaml(loader.getManagementContext(), item.getPlanYaml()); + Preconditions.checkNotNull(item.getCatalogItemType(), "catalog item type for "+plan); + AbstractBrooklynObjectSpec<?, ?> spec; + switch (item.getCatalogItemType()) { + case TEMPLATE: + case ENTITY: + spec = createEntitySpec(item.getSymbolicName(), plan, loader); + break; + case LOCATION: + spec = createLocationSpec(plan, loader); + break; + case POLICY: + spec = createPolicySpec(item.getSymbolicName(), plan, loader); + break; + default: + throw new IllegalStateException("Unknown CI Type "+item.getCatalogItemType()+" for "+plan); + } + + ((AbstractBrooklynObjectSpec<?, ?>)spec).catalogItemId(item.getId()); + + if (Strings.isBlank( ((AbstractBrooklynObjectSpec<?, ?>)spec).getDisplayName() )) + ((AbstractBrooklynObjectSpec<?, ?>)spec).displayName(item.getDisplayName()); + + return spec; + } + + private static EntitySpec<?> createEntitySpec(String symbolicName, DeploymentPlan plan, BrooklynClassLoadingContext loader) { + CampPlatform camp = getCampPlatform(loader.getManagementContext()); + + // TODO should not register new AT each time we instantiate from the same plan; use some kind of cache + AssemblyTemplate at; + BrooklynLoaderTracker.setLoader(loader); + try { + at = camp.pdp().registerDeploymentPlan(plan); + } finally { + BrooklynLoaderTracker.unsetLoader(loader); + } + + try { + AssemblyTemplateInstantiator instantiator = at.getInstantiator().newInstance(); + if (instantiator instanceof AssemblyTemplateSpecInstantiator) { + return ((AssemblyTemplateSpecInstantiator)instantiator).createNestedSpec(at, camp, loader, + getInitialEncounteredSymbol(symbolicName)); + } + throw new IllegalStateException("Unable to instantiate YAML; incompatible instantiator "+instantiator+" for "+at); + } catch (Exception e) { + throw Exceptions.propagate(e); + } + } + + private static MutableSet<String> getInitialEncounteredSymbol(String symbolicName) { + return symbolicName==null ? MutableSet.<String>of() : MutableSet.of(symbolicName); + } + + private static PolicySpec<?> createPolicySpec(String symbolicName, DeploymentPlan plan, BrooklynClassLoadingContext loader) { + return createPolicySpec(plan, loader, getInitialEncounteredSymbol(symbolicName)); + } + + private static PolicySpec<?> createPolicySpec(DeploymentPlan plan, BrooklynClassLoadingContext loader, Set<String> encounteredCatalogTypes) { + //Would ideally re-use io.brooklyn.camp.brooklyn.spi.creation.BrooklynEntityDecorationResolver.PolicySpecResolver + //but it is CAMP specific and there is no easy way to get hold of it. + Object policies = checkNotNull(plan.getCustomAttributes().get(BasicBrooklynCatalog.POLICIES_KEY), "policy config"); + if (!(policies instanceof Iterable<?>)) { + throw new IllegalStateException("The value of " + BasicBrooklynCatalog.POLICIES_KEY + " must be an Iterable."); + } + + Object policy = Iterables.getOnlyElement((Iterable<?>)policies); + + return createPolicySpec(loader, policy, encounteredCatalogTypes); + } + + @SuppressWarnings("unchecked") + private static PolicySpec<?> createPolicySpec(BrooklynClassLoadingContext loader, Object policy, Set<String> encounteredCatalogTypes) { + Map<String, Object> itemMap; + if (policy instanceof String) { + itemMap = ImmutableMap.<String, Object>of("type", policy); + } else if (policy instanceof Map) { + itemMap = (Map<String, Object>) policy; + } else { + throw new IllegalStateException("Policy expected to be string or map. Unsupported object type " + policy.getClass().getName() + " (" + policy.toString() + ")"); + } + + String versionedId = (String) checkNotNull(Yamls.getMultinameAttribute(itemMap, "policy_type", "policyType", "type"), "policy type"); + PolicySpec<? extends Policy> spec; + CatalogItem<?, ?> policyItem = CatalogUtils.getCatalogItemOptionalVersion(loader.getManagementContext(), versionedId); + if (policyItem != null && !encounteredCatalogTypes.contains(policyItem.getSymbolicName())) { + if (policyItem.getCatalogItemType() != CatalogItemType.POLICY) { + throw new IllegalStateException("Non-policy catalog item in policy context: " + policyItem); + } + //TODO re-use createSpec + BrooklynClassLoadingContext itemLoader = CatalogUtils.newClassLoadingContext(loader.getManagementContext(), policyItem); + if (policyItem.getPlanYaml() != null) { + DeploymentPlan plan = makePlanFromYaml(loader.getManagementContext(), policyItem.getPlanYaml()); + encounteredCatalogTypes.add(policyItem.getSymbolicName()); + return createPolicySpec(plan, itemLoader, encounteredCatalogTypes); + } else if (policyItem.getJavaType() != null) { + spec = PolicySpec.create((Class<Policy>)itemLoader.loadClass(policyItem.getJavaType())); + } else { + throw new IllegalStateException("Invalid policy item - neither yaml nor javaType: " + policyItem); + } + } else { + spec = PolicySpec.create(loader.loadClass(versionedId, Policy.class)); + } + Map<String, Object> brooklynConfig = (Map<String, Object>) itemMap.get("brooklyn.config"); + if (brooklynConfig != null) { + spec.configure(brooklynConfig); + } + return spec; + } + + private static LocationSpec<?> createLocationSpec(DeploymentPlan plan, BrooklynClassLoadingContext loader) { + // See #createPolicySpec; this impl is modeled on that. + // spec.catalogItemId is set by caller + Object locations = checkNotNull(plan.getCustomAttributes().get(BasicBrooklynCatalog.LOCATIONS_KEY), "location config"); + if (!(locations instanceof Iterable<?>)) { + throw new IllegalStateException("The value of " + BasicBrooklynCatalog.LOCATIONS_KEY + " must be an Iterable."); + } + + Object location = Iterables.getOnlyElement((Iterable<?>)locations); + + return createLocationSpec(loader, location); + } + + @SuppressWarnings("unchecked") + private static LocationSpec<?> createLocationSpec(BrooklynClassLoadingContext loader, Object location) { + Map<String, Object> itemMap; + if (location instanceof String) { + itemMap = ImmutableMap.<String, Object>of("type", location); + } else if (location instanceof Map) { + itemMap = (Map<String, Object>) location; + } else { + throw new IllegalStateException("Location expected to be string or map. Unsupported object type " + location.getClass().getName() + " (" + location.toString() + ")"); + } + + String type = (String) checkNotNull(Yamls.getMultinameAttribute(itemMap, "location_type", "locationType", "type"), "location type"); + Map<String, Object> brooklynConfig = (Map<String, Object>) itemMap.get("brooklyn.config"); + Maybe<Class<? extends Location>> javaClass = loader.tryLoadClass(type, Location.class); + if (javaClass.isPresent()) { + LocationSpec<?> spec = LocationSpec.create(javaClass.get()); + if (brooklynConfig != null) { + spec.configure(brooklynConfig); + } + return spec; + } else { + Maybe<Location> loc = loader.getManagementContext().getLocationRegistry().resolve(type, false, brooklynConfig); + if (loc.isPresent()) { + // TODO extensions? + Map<String, Object> locConfig = ((ConfigurationSupportInternal)loc.get().config()).getBag().getAllConfig(); + Class<? extends Location> locType = loc.get().getClass(); + Set<Object> locTags = loc.get().tags().getTags(); + String locDisplayName = loc.get().getDisplayName(); + return LocationSpec.create(locType) + .configure(locConfig) + .displayName(locDisplayName) + .tags(locTags); + } else { + throw new IllegalStateException("No class or resolver found for location type "+type); + } + } + } + + private static DeploymentPlan makePlanFromYaml(ManagementContext mgmt, String yaml) { + CampPlatform camp = getCampPlatform(mgmt); + return camp.pdp().parseDeploymentPlan(Streams.newReaderWithContents(yaml)); + } + + /** + * @return the CAMP platform associated with a management context, if there is one. + */ + public static CampPlatform getCampPlatform(ManagementContext mgmt) { + CampPlatform result = mgmt.getConfig().getConfig(BrooklynCampConstants.CAMP_PLATFORM); + if (result!=null) { + return result; + } else { + throw new IllegalStateException("No CAMP Platform is registered with this Brooklyn management context."); + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6ed695e5/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampToSpecTransformer.java ---------------------------------------------------------------------- diff --git a/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampToSpecTransformer.java b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampToSpecTransformer.java new file mode 100644 index 0000000..7650a9b --- /dev/null +++ b/usage/camp/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/CampToSpecTransformer.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 org.apache.brooklyn.camp.brooklyn.spi.creation; + +import java.io.StringReader; + +import org.apache.brooklyn.api.catalog.CatalogItem; +import org.apache.brooklyn.api.entity.Application; +import org.apache.brooklyn.api.entity.EntitySpec; +import org.apache.brooklyn.api.internal.AbstractBrooklynObjectSpec; +import org.apache.brooklyn.api.mgmt.ManagementContext; +import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext; +import org.apache.brooklyn.camp.CampPlatform; +import org.apache.brooklyn.camp.brooklyn.api.AssemblyTemplateSpecInstantiator; +import org.apache.brooklyn.camp.spi.AssemblyTemplate; +import org.apache.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator; +import org.apache.brooklyn.core.mgmt.classloading.JavaBrooklynClassLoadingContext; +import org.apache.brooklyn.core.plan.PlanToSpecTransformer; +import org.apache.brooklyn.util.exceptions.Exceptions; + +public class CampToSpecTransformer implements PlanToSpecTransformer { + + public static final String YAML_CAMP_PLAN_TYPE = "org.apache.brooklyn.camp/yaml"; + + private ManagementContext mgmt; + + @Override + public String getName() { + return YAML_CAMP_PLAN_TYPE; + } + + @Override + public boolean accepts(String mime) { + return YAML_CAMP_PLAN_TYPE.equals(mime); + } + + @Override + public <T extends Application> EntitySpec<T> createApplicationSpec(String plan) { + CampPlatform camp = CampCatalogUtils.getCampPlatform(mgmt); + AssemblyTemplate at = camp.pdp().registerDeploymentPlan( new StringReader(plan) ); + AssemblyTemplateInstantiator instantiator; + try { + instantiator = at.getInstantiator().newInstance(); + } catch (Exception e) { + throw Exceptions.propagate(e); + } + if (instantiator instanceof AssemblyTemplateSpecInstantiator) { + BrooklynClassLoadingContext loader = JavaBrooklynClassLoadingContext.create(mgmt); + @SuppressWarnings("unchecked") + EntitySpec<T> createSpec = (EntitySpec<T>) ((AssemblyTemplateSpecInstantiator) instantiator).createSpec(at, camp, loader, true); + return createSpec; + } else { + // The unknown instantiator can create the app (Assembly), but not a spec. + // Currently, all brooklyn plans should produce the above. + if (at.getPlatformComponentTemplates()==null || at.getPlatformComponentTemplates().isEmpty()) { + if (at.getCustomAttributes().containsKey("brooklyn.catalog")) + throw new IllegalArgumentException("Unrecognized application blueprint format: expected an application, not a brooklyn.catalog"); + throw new IllegalArgumentException("Unrecognized application blueprint format: no services defined"); + } + // map this (expected) error to a nicer message + throw new IllegalArgumentException("Unrecognized application blueprint format"); + } + } + + @Override + public AbstractBrooklynObjectSpec<?, ?> createCatalogSpec(CatalogItem<?, ?> item) { + return CampCatalogUtils.createSpec(mgmt, item); + } + + @Override + public void injectManagementContext(ManagementContext mgmt) { + this.mgmt = mgmt; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6ed695e5/usage/camp/src/main/resources/META-INF/services/org.apache.brooklyn.core.plan.PlanToSpecTransformer ---------------------------------------------------------------------- diff --git a/usage/camp/src/main/resources/META-INF/services/org.apache.brooklyn.core.plan.PlanToSpecTransformer b/usage/camp/src/main/resources/META-INF/services/org.apache.brooklyn.core.plan.PlanToSpecTransformer new file mode 100644 index 0000000..e93291e --- /dev/null +++ b/usage/camp/src/main/resources/META-INF/services/org.apache.brooklyn.core.plan.PlanToSpecTransformer @@ -0,0 +1,19 @@ +# +# 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. +# +org.apache.brooklyn.camp.brooklyn.spi.creation.CampToSpecTransformer http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6ed695e5/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlCombiTest.java ---------------------------------------------------------------------- diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlCombiTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlCombiTest.java index 67ccb1b..30a93e4 100644 --- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlCombiTest.java +++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/catalog/CatalogYamlCombiTest.java @@ -46,7 +46,12 @@ public class CatalogYamlCombiTest extends AbstractYamlTest { "brooklyn.catalog:", " version: "+TEST_VERSION, " items:", - " - item:", + + " - itemType: entity", + " item:", + // TODO inclusion of the above information gives a better error message when no transformers +// " - item:", + " id: A", " type: "+BasicEntity.class.getName(), " brooklyn.config: { a: 1, b: 0 }", http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6ed695e5/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampPlatformWithJustBrooklynMgmt.java ---------------------------------------------------------------------- diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampPlatformWithJustBrooklynMgmt.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampPlatformWithJustBrooklynMgmt.java new file mode 100644 index 0000000..e65d49d --- /dev/null +++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampPlatformWithJustBrooklynMgmt.java @@ -0,0 +1,41 @@ +/* + * 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.camp.brooklyn.test.lite; + +import org.apache.brooklyn.api.mgmt.ManagementContext; +import org.apache.brooklyn.camp.BasicCampPlatform; +import org.apache.brooklyn.camp.brooklyn.BrooklynCampConstants; +import org.apache.brooklyn.camp.brooklyn.api.HasBrooklynManagementContext; +import org.apache.brooklyn.core.internal.BrooklynProperties; + +public class CampPlatformWithJustBrooklynMgmt extends BasicCampPlatform implements HasBrooklynManagementContext { + + private ManagementContext mgmt; + + public CampPlatformWithJustBrooklynMgmt(ManagementContext mgmt) { + this.mgmt = mgmt; + ((BrooklynProperties)mgmt.getConfig()).put(BrooklynCampConstants.CAMP_PLATFORM, this); + } + + @Override + public ManagementContext getBrooklynManagementContext() { + return mgmt; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6ed695e5/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampYamlLiteTest.java ---------------------------------------------------------------------- diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampYamlLiteTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampYamlLiteTest.java new file mode 100644 index 0000000..cfd5b38 --- /dev/null +++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/CampYamlLiteTest.java @@ -0,0 +1,254 @@ +/* + * 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.camp.brooklyn.test.lite; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNotNull; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.apache.brooklyn.api.catalog.CatalogItem; +import org.apache.brooklyn.api.catalog.CatalogItem.CatalogBundle; +import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.api.entity.EntitySpec; +import org.apache.brooklyn.api.mgmt.Task; +import org.apache.brooklyn.camp.spi.Assembly; +import org.apache.brooklyn.camp.spi.AssemblyTemplate; +import org.apache.brooklyn.camp.spi.pdp.PdpYamlTest; +import org.apache.brooklyn.camp.test.mock.web.MockWebPlatform; +import org.apache.brooklyn.core.catalog.CatalogPredicates; +import org.apache.brooklyn.core.catalog.internal.BasicBrooklynCatalog; +import org.apache.brooklyn.core.catalog.internal.CatalogDto; +import org.apache.brooklyn.core.catalog.internal.CatalogUtils; +import org.apache.brooklyn.core.config.ConfigKeys; +import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext; +import org.apache.brooklyn.core.mgmt.osgi.OsgiStandaloneTest; +import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests; +import org.apache.brooklyn.core.test.entity.TestApplication; +import org.apache.brooklyn.core.test.entity.TestEntity; +import org.apache.brooklyn.effector.core.AddChildrenEffector; +import org.apache.brooklyn.effector.core.Effectors; +import org.apache.brooklyn.entity.core.Entities; +import org.apache.brooklyn.entity.factory.ApplicationBuilder; +import org.apache.brooklyn.test.TestResourceUnavailableException; +import org.apache.brooklyn.util.collections.MutableMap; +import org.apache.brooklyn.util.core.ResourceUtils; +import org.apache.brooklyn.util.core.config.ConfigBag; +import org.apache.brooklyn.util.stream.Streams; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import com.google.common.base.Joiner; +import com.google.common.base.Predicates; +import com.google.common.collect.Iterables; + +/** Tests of lightweight CAMP integration. Since the "real" integration is in brooklyn-camp project, + * but some aspects of CAMP we want to be able to test here. */ +public class CampYamlLiteTest { + private static final String TEST_VERSION = "0.1.2"; + + private static final Logger log = LoggerFactory.getLogger(CampYamlLiteTest.class); + + protected LocalManagementContext mgmt; + protected CampPlatformWithJustBrooklynMgmt platform; + + @BeforeMethod(alwaysRun=true) + public void setUp() { + mgmt = LocalManagementContextForTests.newInstanceWithOsgi(); + platform = new CampPlatformWithJustBrooklynMgmt(mgmt); + MockWebPlatform.populate(platform, TestAppAssemblyInstantiator.class); + } + + @AfterMethod(alwaysRun=true) + public void tearDown() { + if (mgmt!=null) mgmt.terminate(); + } + + /** based on {@link PdpYamlTest} for parsing, + * then creating a {@link TestAppAssembly} */ + @Test + public void testYamlServiceMatchAndBrooklynInstantiate() throws Exception { + Reader input = new InputStreamReader(getClass().getResourceAsStream("test-app-service-blueprint.yaml")); + AssemblyTemplate at = platform.pdp().registerDeploymentPlan(input); + log.info("AT is:\n"+at.toString()); + Assert.assertEquals(at.getName(), "sample"); + Assert.assertEquals(at.getPlatformComponentTemplates().links().size(), 1); + + // now use brooklyn to instantiate - note it won't be faithful, but it will set some config keys + Assembly assembly = at.getInstantiator().newInstance().instantiate(at, platform); + + TestApplication app = ((TestAppAssembly)assembly).getBrooklynApp(); + Assert.assertEquals( app.getConfig(TestEntity.CONF_NAME), "sample" ); + Map<String, String> map = app.getConfig(TestEntity.CONF_MAP_THING); + Assert.assertEquals( map.get("desc"), "Tomcat sample JSP and servlet application." ); + + Assert.assertEquals( app.getChildren().size(), 1 ); + Entity svc = Iterables.getOnlyElement(app.getChildren()); + Assert.assertEquals( svc.getConfig(TestEntity.CONF_NAME), "Hello WAR" ); + map = svc.getConfig(TestEntity.CONF_MAP_THING); + Assert.assertEquals( map.get("type"), MockWebPlatform.APPSERVER.getType() ); + // desc ensures we got the information from the matcher, as this value is NOT in the yaml + Assert.assertEquals( map.get("desc"), MockWebPlatform.APPSERVER.getDescription() ); + } + + /** based on {@link PdpYamlTest} for parsing, + * then creating a {@link TestAppAssembly} */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Test + public void testAddChildrenEffector() throws Exception { + String childYaml = Streams.readFullyString(getClass().getResourceAsStream("test-app-service-blueprint.yaml")); + AddChildrenEffector newEff = new AddChildrenEffector(ConfigBag.newInstance() + .configure(AddChildrenEffector.EFFECTOR_NAME, "add_tomcat") + .configure(AddChildrenEffector.BLUEPRINT_YAML, childYaml) + .configure(AddChildrenEffector.EFFECTOR_PARAMETER_DEFS, MutableMap.of("war", (Object)MutableMap.of( + "defaultValue", "foo.war"))) ) ; + TestApplication app = ApplicationBuilder.newManagedApp(EntitySpec.create(TestApplication.class).addInitializer(newEff), mgmt); + + // test adding, with a parameter + Task<List> task = app.invoke(Effectors.effector(List.class, "add_tomcat").buildAbstract(), MutableMap.of("war", "foo.bar")); + List result = task.get(); + + Entity newChild = Iterables.getOnlyElement(app.getChildren()); + Assert.assertEquals(newChild.getConfig(ConfigKeys.newStringConfigKey("war")), "foo.bar"); + + Assert.assertEquals(Iterables.getOnlyElement(result), newChild.getId()); + Entities.unmanage(newChild); + + // and test default value + task = app.invoke(Effectors.effector(List.class, "add_tomcat").buildAbstract(), MutableMap.<String,Object>of()); + result = task.get(); + + newChild = Iterables.getOnlyElement(app.getChildren()); + Assert.assertEquals(newChild.getConfig(ConfigKeys.newStringConfigKey("war")), "foo.war"); + + Assert.assertEquals(Iterables.getOnlyElement(result), newChild.getId()); + Entities.unmanage(newChild); + } + + @Test + public void testYamlServiceForCatalog() { + TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH); + + CatalogItem<?, ?> realItem = Iterables.getOnlyElement(mgmt.getCatalog().addItems(Streams.readFullyString(getClass().getResourceAsStream("test-app-service-blueprint.yaml")))); + Iterable<CatalogItem<Object, Object>> retrievedItems = mgmt.getCatalog() + .getCatalogItems(CatalogPredicates.symbolicName(Predicates.equalTo("catalog-name"))); + + Assert.assertEquals(Iterables.size(retrievedItems), 1, "Wrong retrieved items: "+retrievedItems); + CatalogItem<Object, Object> retrievedItem = Iterables.getOnlyElement(retrievedItems); + Assert.assertEquals(retrievedItem, realItem); + + Collection<CatalogBundle> bundles = retrievedItem.getLibraries(); + Assert.assertEquals(bundles.size(), 1); + CatalogBundle bundle = Iterables.getOnlyElement(bundles); + Assert.assertEquals(bundle.getUrl(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL); + Assert.assertEquals(bundle.getVersion(), "0.1.0"); + + EntitySpec<?> spec1 = (EntitySpec<?>) mgmt.getCatalog().createSpec(retrievedItem); + assertNotNull(spec1); + Assert.assertEquals(spec1.getConfig().get(TestEntity.CONF_NAME), "sample"); + + // TODO other assertions, about children + } + + @Test + public void testRegisterCustomEntityWithBundleWhereEntityIsFromCoreAndIconFromBundle() throws IOException { + TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH); + + String symbolicName = "my.catalog.app.id"; + String bundleUrl = OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL; + String yaml = getSampleMyCatalogAppYaml(symbolicName, bundleUrl); + + mgmt.getCatalog().addItems(yaml); + + assertMgmtHasSampleMyCatalogApp(symbolicName, bundleUrl); + } + + @Test + public void testResetXmlWithCustomEntity() throws IOException { + TestResourceUnavailableException.throwIfResourceUnavailable(getClass(), OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_PATH); + + String symbolicName = "my.catalog.app.id"; + String bundleUrl = OsgiStandaloneTest.BROOKLYN_TEST_OSGI_ENTITIES_URL; + String yaml = getSampleMyCatalogAppYaml(symbolicName, bundleUrl); + + LocalManagementContext mgmt2 = LocalManagementContextForTests.newInstanceWithOsgi(); + try { + CampPlatformWithJustBrooklynMgmt platform2 = new CampPlatformWithJustBrooklynMgmt(mgmt2); + MockWebPlatform.populate(platform2, TestAppAssemblyInstantiator.class); + + mgmt2.getCatalog().addItems(yaml); + String xml = ((BasicBrooklynCatalog) mgmt2.getCatalog()).toXmlString(); + ((BasicBrooklynCatalog) mgmt.getCatalog()).reset(CatalogDto.newDtoFromXmlContents(xml, "copy of temporary catalog")); + } finally { + mgmt2.terminate(); + } + + assertMgmtHasSampleMyCatalogApp(symbolicName, bundleUrl); + } + + private String getSampleMyCatalogAppYaml(String symbolicName, String bundleUrl) { + return "brooklyn.catalog:\n" + + " id: " + symbolicName + "\n" + + " name: My Catalog App\n" + + " description: My description\n" + + " icon_url: classpath:/brooklyn/osgi/tests/icon.gif\n" + + " version: " + TEST_VERSION + "\n" + + " libraries:\n" + + " - url: " + bundleUrl + "\n" + + "\n" + + "services:\n" + + "- type: io.camp.mock:AppServer\n"; + } + + private void assertMgmtHasSampleMyCatalogApp(String symbolicName, String bundleUrl) { + CatalogItem<?, ?> item = mgmt.getCatalog().getCatalogItem(symbolicName, TEST_VERSION); + assertNotNull(item, "failed to load item with id=" + symbolicName + " from catalog. Entries were: " + + Joiner.on(",").join(mgmt.getCatalog().getCatalogItems())); + assertEquals(item.getSymbolicName(), symbolicName); + + // stored as yaml, not java + assertNotNull(item.getPlanYaml()); + Assert.assertTrue(item.getPlanYaml().contains("io.camp.mock:AppServer")); + + // and let's check we have libraries + Collection<CatalogBundle> libs = item.getLibraries(); + assertEquals(libs.size(), 1); + CatalogBundle bundle = Iterables.getOnlyElement(libs); + assertEquals(bundle.getUrl(), bundleUrl); + + // now let's check other things on the item + assertEquals(item.getDisplayName(), "My Catalog App"); + assertEquals(item.getDescription(), "My description"); + assertEquals(item.getIconUrl(), "classpath:/brooklyn/osgi/tests/icon.gif"); + + // and confirm we can resolve ICON + byte[] iconData = Streams.readFully(ResourceUtils.create(CatalogUtils.newClassLoadingContext(mgmt, item)).getResourceFromUrl(item.getIconUrl())); + assertEquals(iconData.length, 43); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6ed695e5/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/TestAppAssembly.java ---------------------------------------------------------------------- diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/TestAppAssembly.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/TestAppAssembly.java new file mode 100644 index 0000000..877c00b --- /dev/null +++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/TestAppAssembly.java @@ -0,0 +1,36 @@ +/* + * 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.camp.brooklyn.test.lite; + +import org.apache.brooklyn.camp.spi.Assembly; +import org.apache.brooklyn.core.test.entity.TestApplication; + +public class TestAppAssembly extends Assembly { + + private TestApplication brooklynApp; + + public TestAppAssembly(TestApplication brooklynApp) { + this.brooklynApp = brooklynApp; + } + + public TestApplication getBrooklynApp() { + return brooklynApp; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6ed695e5/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/TestAppAssemblyInstantiator.java ---------------------------------------------------------------------- diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/TestAppAssemblyInstantiator.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/TestAppAssemblyInstantiator.java new file mode 100644 index 0000000..512e8ef --- /dev/null +++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/test/lite/TestAppAssemblyInstantiator.java @@ -0,0 +1,90 @@ +/* + * 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.camp.brooklyn.test.lite; + +import java.util.Map; +import java.util.Set; + +import org.apache.brooklyn.api.entity.EntitySpec; +import org.apache.brooklyn.api.mgmt.ManagementContext; +import org.apache.brooklyn.api.mgmt.classloading.BrooklynClassLoadingContext; +import org.apache.brooklyn.camp.CampPlatform; +import org.apache.brooklyn.camp.brooklyn.api.AssemblyTemplateSpecInstantiator; +import org.apache.brooklyn.camp.brooklyn.api.HasBrooklynManagementContext; +import org.apache.brooklyn.camp.spi.AbstractResource; +import org.apache.brooklyn.camp.spi.Assembly; +import org.apache.brooklyn.camp.spi.AssemblyTemplate; +import org.apache.brooklyn.camp.spi.PlatformComponentTemplate; +import org.apache.brooklyn.camp.spi.collection.ResolvableLink; +import org.apache.brooklyn.camp.spi.instantiate.BasicAssemblyTemplateInstantiator; +import org.apache.brooklyn.core.test.entity.TestApplication; +import org.apache.brooklyn.core.test.entity.TestEntity; +import org.apache.brooklyn.util.collections.MutableMap; +import org.apache.brooklyn.util.core.config.ConfigBag; + +/** simple illustrative instantiator which always makes a {@link TestApplication}, populated with {@link TestEntity} children, + * all setting {@link TestEntity#CONF_NAME} for the name in the plan and in the service specs + * <p> + * the "real" instantiator for brooklyn is in brooklyn-camp project, not visible here, so let's have something we can test */ +public class TestAppAssemblyInstantiator extends BasicAssemblyTemplateInstantiator implements AssemblyTemplateSpecInstantiator { + + @Override + public Assembly instantiate(AssemblyTemplate template, CampPlatform platform) { + if (!(platform instanceof HasBrooklynManagementContext)) { + throw new IllegalStateException("Instantiator can only be used with CAMP platforms with a Brooklyn management context"); + } + ManagementContext mgmt = ((HasBrooklynManagementContext)platform).getBrooklynManagementContext(); + + TestApplication app = (TestApplication) mgmt.getEntityManager().createEntity( createSpec(template, platform, null, false) ); + mgmt.getEntityManager().manage(app); + + return new TestAppAssembly(app); + } + + @Override + public EntitySpec<?> createSpec(AssemblyTemplate template, CampPlatform platform, BrooklynClassLoadingContext loader, boolean autoUnwrap) { + EntitySpec<TestApplication> app = EntitySpec.create(TestApplication.class) + .configure(TestEntity.CONF_NAME, template.getName()) + .configure(TestEntity.CONF_MAP_THING, MutableMap.of("type", template.getType(), "desc", template.getDescription())); + applyBrooklynConfig(template, app); + + for (ResolvableLink<PlatformComponentTemplate> t: template.getPlatformComponentTemplates().links()) { + EntitySpec<TestEntity> spec = EntitySpec.create(TestEntity.class) + .configure(TestEntity.CONF_NAME, t.getName()) + .configure(TestEntity.CONF_MAP_THING, MutableMap.of("type", t.resolve().getType(), "desc", t.resolve().getDescription())); + applyBrooklynConfig(t.resolve(), app); + app.child(spec); + } + + return app; + } + + @SuppressWarnings("rawtypes") + private void applyBrooklynConfig(AbstractResource template, EntitySpec<TestApplication> app) { + Object bc = template.getCustomAttributes().get("brooklyn.config"); + if (bc instanceof Map) + app.configure(ConfigBag.newInstance().putAll((Map)bc).getAllConfigAsConfigKeyMap()); + } + + @Override + public EntitySpec<?> createNestedSpec(AssemblyTemplate template, CampPlatform platform, BrooklynClassLoadingContext itemLoader, Set<String> encounteredCatalogTypes) { + return createSpec(template, platform, itemLoader, true); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6ed695e5/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/test/lite/test-app-service-blueprint.yaml ---------------------------------------------------------------------- diff --git a/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/test/lite/test-app-service-blueprint.yaml b/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/test/lite/test-app-service-blueprint.yaml new file mode 100644 index 0000000..c0bb607 --- /dev/null +++ b/usage/camp/src/test/resources/org/apache/brooklyn/camp/brooklyn/test/lite/test-app-service-blueprint.yaml @@ -0,0 +1,38 @@ +# +# 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. +# +name: sample +description: Tomcat sample JSP and servlet application. +origin: http://www.oracle.com/nCAMP/Hand +services: + - + type: io.camp.mock:AppServer + name: Hello WAR + wars: + /: hello.war + controller.spec: + port: 80 + +brooklyn.catalog: + name: catalog-name + type: io.camp.mock.MyApplication + version: 0.9 + libraries: + - name: org.apache.brooklyn.test.resources.osgi.brooklyn-test-osgi-entities + version: 0.1.0 + url: classpath:/brooklyn/osgi/brooklyn-test-osgi-entities.jar \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6ed695e5/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynLauncher.java ---------------------------------------------------------------------- diff --git a/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynLauncher.java b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynLauncher.java index 5ea82f7..d8a0fc9 100644 --- a/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynLauncher.java +++ b/usage/launcher/src/main/java/org/apache/brooklyn/launcher/BrooklynLauncher.java @@ -22,7 +22,6 @@ import static com.google.common.base.Preconditions.checkNotNull; import java.io.Closeable; import java.io.File; -import java.io.StringReader; import java.net.InetAddress; import java.util.ArrayList; import java.util.Arrays; @@ -49,13 +48,11 @@ import org.apache.brooklyn.api.mgmt.rebind.RebindManager; import org.apache.brooklyn.api.mgmt.rebind.mementos.BrooklynMementoRawData; import org.apache.brooklyn.camp.CampPlatform; import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatformLauncherNoServer; -import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynAssemblyTemplateInstantiator; -import org.apache.brooklyn.camp.spi.AssemblyTemplate; -import org.apache.brooklyn.camp.spi.instantiate.AssemblyTemplateInstantiator; import org.apache.brooklyn.config.ConfigKey; import org.apache.brooklyn.core.catalog.internal.CatalogInitialization; import org.apache.brooklyn.core.config.ConfigPredicates; import org.apache.brooklyn.core.internal.BrooklynProperties; +import org.apache.brooklyn.core.mgmt.EntityManagementUtils; import org.apache.brooklyn.core.mgmt.ha.HighAvailabilityManagerImpl; import org.apache.brooklyn.core.mgmt.ha.ManagementPlaneSyncRecordPersisterToObjectStore; import org.apache.brooklyn.core.mgmt.internal.BrooklynShutdownHooks; @@ -77,17 +74,6 @@ import org.apache.brooklyn.entity.core.StartableApplication; import org.apache.brooklyn.entity.factory.ApplicationBuilder; import org.apache.brooklyn.entity.software.base.SoftwareProcess; import org.apache.brooklyn.entity.trait.Startable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.google.common.annotations.Beta; -import com.google.common.base.Function; -import com.google.common.base.Splitter; -import com.google.common.base.Stopwatch; -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; - import org.apache.brooklyn.launcher.config.StopWhichAppsOnShutdown; import org.apache.brooklyn.location.core.PortRanges; import org.apache.brooklyn.location.localhost.LocalhostMachineProvisioningLocation.LocalhostMachine; @@ -107,6 +93,16 @@ import org.apache.brooklyn.util.stream.Streams; import org.apache.brooklyn.util.text.Strings; import org.apache.brooklyn.util.time.Duration; import org.apache.brooklyn.util.time.Time; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.annotations.Beta; +import com.google.common.base.Function; +import com.google.common.base.Splitter; +import com.google.common.base.Stopwatch; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; /** * Example usage is: @@ -172,6 +168,7 @@ public class BrooklynLauncher { private Duration haHeartbeatPeriodOverride = null; private volatile BrooklynWebServer webServer; + @SuppressWarnings("unused") private CampPlatform campPlatform; private boolean started; @@ -916,7 +913,7 @@ public class BrooklynLauncher { apps.add(app); } for (String blueprint : yamlAppsToManage) { - Application app = getAppFromYaml(blueprint); + Application app = EntityManagementUtils.createUnstarted(managementContext, blueprint); // Note: BrooklynAssemblyTemplateInstantiator automatically puts applications under management. apps.add(app); } @@ -956,23 +953,6 @@ public class BrooklynLauncher { .start(ImmutableList.of(localhost)); } - protected Application getAppFromYaml(String input) { - AssemblyTemplate at = campPlatform.pdp().registerDeploymentPlan(new StringReader(input)); - BrooklynAssemblyTemplateInstantiator instantiator; - try { - AssemblyTemplateInstantiator ati = at.getInstantiator().newInstance(); - if (ati instanceof BrooklynAssemblyTemplateInstantiator) { - instantiator = BrooklynAssemblyTemplateInstantiator.class.cast(ati); - } else { - throw new IllegalStateException("Cannot create application with instantiator: " + ati); - } - } catch (Exception e) { - throw Exceptions.propagate(e); - } - Application app = instantiator.create(at, campPlatform); - return app; - } - protected void startApps() { if ((stopWhichAppsOnShutdown==StopWhichAppsOnShutdown.ALL) || (stopWhichAppsOnShutdown==StopWhichAppsOnShutdown.ALL_IF_NOT_PERSISTED && persistMode==PersistMode.DISABLED)) { http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6ed695e5/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/AbstractBrooklynRestResource.java ---------------------------------------------------------------------- diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/AbstractBrooklynRestResource.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/AbstractBrooklynRestResource.java index edeedaa..2df17f3 100644 --- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/AbstractBrooklynRestResource.java +++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/AbstractBrooklynRestResource.java @@ -144,8 +144,4 @@ public abstract class AbstractBrooklynRestResource implements ManagementContextI } - protected CampPlatform camp() { - return BrooklynServerConfig.getCampPlatform(mgmt()).get(); - } - } http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/6ed695e5/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java ---------------------------------------------------------------------- diff --git a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java index 84e5190..dcb8b74 100644 --- a/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java +++ b/usage/rest-server/src/main/java/org/apache/brooklyn/rest/resources/ApplicationResource.java @@ -23,7 +23,6 @@ import static javax.ws.rs.core.Response.created; import static javax.ws.rs.core.Response.status; import static javax.ws.rs.core.Response.Status.ACCEPTED; -import java.io.StringReader; import java.net.URI; import java.net.URISyntaxException; import java.util.Collection; @@ -37,19 +36,14 @@ import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.ResponseBuilder; import javax.ws.rs.core.UriInfo; -import org.codehaus.jackson.JsonNode; -import org.codehaus.jackson.node.ArrayNode; -import org.codehaus.jackson.node.ObjectNode; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.apache.brooklyn.api.entity.Application; import org.apache.brooklyn.api.entity.Entity; +import org.apache.brooklyn.api.entity.EntitySpec; import org.apache.brooklyn.api.entity.Group; import org.apache.brooklyn.api.location.Location; import org.apache.brooklyn.api.mgmt.Task; import org.apache.brooklyn.api.sensor.AttributeSensor; import org.apache.brooklyn.api.sensor.Sensor; -import org.apache.brooklyn.camp.spi.AssemblyTemplate; import org.apache.brooklyn.core.catalog.internal.CatalogUtils; import org.apache.brooklyn.core.mgmt.EntityManagementUtils; import org.apache.brooklyn.core.mgmt.EntityManagementUtils.CreationResult; @@ -65,7 +59,6 @@ import org.apache.brooklyn.entity.trait.Startable; import org.apache.brooklyn.rest.api.ApplicationApi; import org.apache.brooklyn.rest.domain.ApplicationSpec; import org.apache.brooklyn.rest.domain.ApplicationSummary; -import org.apache.brooklyn.rest.domain.EntitySpec; import org.apache.brooklyn.rest.domain.EntitySummary; import org.apache.brooklyn.rest.domain.TaskSummary; import org.apache.brooklyn.rest.filter.HaHotStateRequired; @@ -79,6 +72,11 @@ import org.apache.brooklyn.util.collections.MutableMap; import org.apache.brooklyn.util.core.ResourceUtils; import org.apache.brooklyn.util.exceptions.Exceptions; import org.apache.brooklyn.util.text.Strings; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.node.ArrayNode; +import org.codehaus.jackson.node.ObjectNode; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.google.common.base.Throwables; import com.google.common.collect.FluentIterable; @@ -274,28 +272,32 @@ public class ApplicationResource extends AbstractBrooklynRestResource implements } log.debug("Creating app from yaml:\n{}", yaml); - AssemblyTemplate at = camp().pdp().registerDeploymentPlan( new StringReader(yaml) ); + EntitySpec<? extends Application> spec = EntityManagementUtils.createEntitySpec(mgmt(), yaml); - if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.DEPLOY_APPLICATION, at)) { + if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.DEPLOY_APPLICATION, spec)) { throw WebResourceUtils.unauthorized("User '%s' is not authorized to start application %s", Entitlements.getEntitlementContext().user(), yaml); } - return launch(at); + return launch(yaml, spec); } - private Response launch(AssemblyTemplate at) { + private Response launch(String yaml, EntitySpec<? extends Application> spec) { try { - CreationResult<? extends Application, Void> result = EntityManagementUtils.createStarting(mgmt(), at); + Application app = EntityManagementUtils.createUnstarted(mgmt(), spec); + CreationResult<Application,Void> result = EntityManagementUtils.start(app); - Application app = result.get(); - if (!Entitlements.isEntitled(mgmt().getEntitlementManager(), Entitlements.INVOKE_EFFECTOR, EntityAndItem.of(app, - StringAndArgument.of(Startable.START.getName(), null)))) { + boolean isEntitled = Entitlements.isEntitled( + mgmt().getEntitlementManager(), + Entitlements.INVOKE_EFFECTOR, + EntityAndItem.of(app, StringAndArgument.of(Startable.START.getName(), null))); + + if (!isEntitled) { throw WebResourceUtils.unauthorized("User '%s' is not authorized to start application %s", - Entitlements.getEntitlementContext().user(), at.getType()); + Entitlements.getEntitlementContext().user(), spec.getType()); } - log.info("Launched from YAML: " + at + " -> " + app + " (" + result.task() + ")"); + log.info("Launched from YAML: " + yaml + " -> " + app + " (" + result.task() + ")"); URI ref = URI.create(app.getApplicationId()); ResponseBuilder response = created(ref); @@ -316,6 +318,9 @@ public class ApplicationResource extends AbstractBrooklynRestResource implements // attempt legacy format try { ApplicationSpec appSpec = mapper().readValue(inputToAutodetectType, ApplicationSpec.class); + if (appSpec.getType() != null || appSpec.getEntities() != null) { + looksLikeLegacy = true; + } return createFromAppSpec(appSpec); } catch (Exception e) { Exceptions.propagateIfFatal(e); @@ -323,39 +328,19 @@ public class ApplicationResource extends AbstractBrooklynRestResource implements log.debug("Input is not legacy ApplicationSpec JSON (will try others): "+e, e); } - AssemblyTemplate template = null; - boolean looksLikeYaml = false; - try { - template = camp().pdp().registerDeploymentPlan(new StringReader(new String(inputToAutodetectType))); - if (!template.getPlatformComponentTemplates().isEmpty() || !template.getApplicationComponentTemplates().isEmpty()) { - looksLikeYaml = true; - } else { - if (template.getCustomAttributes().containsKey("type") || template.getCustomAttributes().containsKey("entities")) { - looksLikeLegacy = true; - } - } - } catch (Exception e) { - Exceptions.propagateIfFatal(e); - log.debug("Input is not valid YAML: "+e); - } + //TODO infer encoding from request + String potentialYaml = new String(inputToAutodetectType); + EntitySpec<? extends Application> spec = EntityManagementUtils.createEntitySpec(mgmt(), potentialYaml); // TODO not json - try ZIP, etc - if (template!=null) { - try { - return launch(template); - } catch (Exception e) { - Exceptions.propagateIfFatal(e); - if (looksLikeYaml) - throw Exceptions.propagate(e); - } - } - - if ((looksLikeLegacy || !looksLikeYaml) && legacyFormatException!=null) - // throw the error from legacy creation if it looks like it was the legacy format + if (spec != null) { + return launch(potentialYaml, spec); + } else if (looksLikeLegacy) { throw Throwables.propagate(legacyFormatException); - - return Response.serverError().entity("Unsupported format; not able to autodetect.").build(); + } else { + return Response.serverError().entity("Unsupported format; not able to autodetect.").build(); + } } @Override @@ -388,7 +373,7 @@ public class ApplicationResource extends AbstractBrooklynRestResource implements return; } - for (EntitySpec entitySpec : applicationSpec.getEntities()) { + for (org.apache.brooklyn.rest.domain.EntitySpec entitySpec : applicationSpec.getEntities()) { String entityType = entitySpec.getType(); checkEntityTypeIsValid(checkNotNull(entityType, "entityType")); } @@ -458,4 +443,4 @@ public class ApplicationResource extends AbstractBrooklynRestResource implements return result; } -} \ No newline at end of file +}
