Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[submodule "alien4cloud"]
path = alien4cloud
url = ../alien4cloud.git
commit = adc7c36
commit = 90413c99
2 changes: 1 addition & 1 deletion a4c-brooklyn-plugin/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>io.cloudsoft.brooklyn.tosca</groupId>
<artifactId>brooklyn-tosca-parent</artifactId>
<version>1.0.0-SNAPSHOT</version> <!-- BROOKLYN_TOSCA_VERSION -->
<version>1.1.0-SNAPSHOT</version> <!-- BROOKLYN_TOSCA_VERSION -->
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion brooklyn-tosca-common/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<parent>
<groupId>io.cloudsoft.brooklyn.tosca</groupId>
<artifactId>brooklyn-tosca-parent</artifactId>
<version>1.0.0-SNAPSHOT</version> <!-- BROOKLYN_TOSCA_VERSION -->
<version>1.1.0-SNAPSHOT</version> <!-- BROOKLYN_TOSCA_VERSION -->
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion brooklyn-tosca-dist/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>io.cloudsoft.brooklyn.tosca</groupId>
<artifactId>brooklyn-tosca-parent</artifactId>
<version>1.0.0-SNAPSHOT</version> <!-- BROOKLYN_TOSCA_VERSION -->
<version>1.1.0-SNAPSHOT</version> <!-- BROOKLYN_TOSCA_VERSION -->
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
2 changes: 1 addition & 1 deletion brooklyn-tosca-transformer/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<parent>
<groupId>io.cloudsoft.brooklyn.tosca</groupId>
<artifactId>brooklyn-tosca-parent</artifactId>
<version>1.0.0-SNAPSHOT</version> <!-- BROOKLYN_TOSCA_VERSION -->
<version>1.1.0-SNAPSHOT</version> <!-- BROOKLYN_TOSCA_VERSION -->
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ public AbstractToscaPolicyDecorator(ManagementContext mgmt) {
this.mgmt = mgmt;
}

public Map<String, ?> getToscaObjectPropertiesExtended(Map<String, ?> toscaObjectData) {
return getToscaObjectPropertiesExtendedExcluding(toscaObjectData, true, false, POLICY_FLAG_NAME, POLICY_FLAG_TYPE);
}

/**
* Given a map eg of a tosca type,
* return everything under the TOSCA "properties" key, merged on top of things at the root
Expand All @@ -32,14 +36,25 @@ public AbstractToscaPolicyDecorator(ManagementContext mgmt) {
* @param toscaObjectData
*/
@SuppressWarnings("unchecked")
public Map<String, ?> getToscaObjectPropertiesExtended(Map<String, ?> toscaObjectData){
public Map<String, ?> getToscaObjectPropertiesExtendedExcluding(Map<String, ?> toscaObjectData,
boolean promoteToscaProperties, boolean promoteBrooklynConfig, String... keysToOmit){
Map<String, Object> data = MutableMap.copyOf(toscaObjectData);
data.remove(POLICY_FLAG_NAME);
data.remove(POLICY_FLAG_TYPE);
for (String keyToOmit: keysToOmit) {
data.remove(keyToOmit);
}

if (promoteToscaProperties) {
Map<String,?> props = (Map<String,?>) data.remove(POLICY_FLAG_PROPERTIES);
if (props!=null) {
data.putAll(props);
}
}

Map<String,?> props = (Map<String,?>) data.remove(POLICY_FLAG_PROPERTIES);
if (props!=null) {
data.putAll(props);
if (promoteBrooklynConfig) {
Object brooklynConfig = data.remove(POLICY_FLAG_BROOKLYN_CONFIG);
if (brooklynConfig!=null) {
data.putAll((Map<String,?>)brooklynConfig);
}
}

// evaluate DSL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
import alien4cloud.model.components.IndexedInheritableToscaElement;
import alien4cloud.model.components.IndexedRelationshipType;
import alien4cloud.model.components.Interface;
import alien4cloud.model.components.ListPropertyValue;
import alien4cloud.model.components.Operation;
import alien4cloud.model.components.ScalarPropertyValue;
import alien4cloud.model.deployment.DeploymentTopology;
Expand Down Expand Up @@ -240,6 +241,9 @@ private Optional<Object> getToscaScalarValueUnlessItsAFunction(IValue v) {
if (v instanceof ComplexPropertyValue) {
return Optional.<Object>fromNullable(((ComplexPropertyValue) v).getValue());
}
if (v instanceof ListPropertyValue) {
return Optional.<Object>fromNullable(((ListPropertyValue) v).getValue());
}
if (!(v instanceof FunctionPropertyValue)) {
LOG.warn("Ignoring unsupported property value " + v);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ public void decorate(Map<String, ?> policyData, String toscaPolicyName, Optional
protected ConfigBag getBrooklynObjectDefinition(String type, Map<String, ?> toscaObjectData) {
List<?> policies = ImmutableList.of(ImmutableMap.of(
"type", type,
BrooklynCampReservedKeys.BROOKLYN_CONFIG, getToscaObjectPropertiesExtended(toscaObjectData)
BrooklynCampReservedKeys.BROOKLYN_CONFIG, getToscaObjectPropertiesExtendedExcluding(toscaObjectData, true, true, POLICY_FLAG_NAME, POLICY_FLAG_TYPE)
)
);
Map<?, ?> policyDefinition = ImmutableMap.of(brooklynYamlKey, policies);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public void decorate(Map<String, ?> policyData, String policyName, Optional<Stri
private List<LocationSpec<?>> getLocationSpecs(Map<String, ?> policyData) {
Object data = policyData.containsKey(GroupPolicyParser.VALUE)
? policyData.get(GroupPolicyParser.VALUE)
: getToscaObjectPropertiesExtended(policyData);
: getToscaObjectPropertiesExtendedExcluding(policyData, true, true, POLICY_FLAG_NAME, POLICY_FLAG_TYPE);
return resolveLocationSpecs(ImmutableMap.of("location", data));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ public interface ToscaPolicyDecorator {
String POLICY_FLAG_TYPE = "type";
String POLICY_FLAG_NAME = "name";
String POLICY_FLAG_PROPERTIES = "properties";
String POLICY_FLAG_BROOKLYN_CONFIG = "brooklyn.config";

void decorate(Map<String, ?> policyData, String policyName, Optional<String> type, Set<String> groupMembers);
}
Original file line number Diff line number Diff line change
@@ -1,25 +1,14 @@
package io.cloudsoft.tosca.a4c.brooklyn.spec;

import java.util.Map;

import javax.annotation.Nullable;

import org.apache.brooklyn.api.entity.EntitySpec;
import org.apache.brooklyn.api.mgmt.ManagementContext;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampPlatform;
import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynComponentTemplateResolver;
import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
import org.apache.brooklyn.util.collections.MutableSet;
import org.apache.brooklyn.util.core.flags.TypeCoercions;
import org.apache.brooklyn.util.core.task.DeferredSupplier;
import org.apache.brooklyn.util.yaml.Yamls;
import org.elasticsearch.common.collect.Iterables;
import org.apache.brooklyn.camp.brooklyn.spi.dsl.DslUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.reflect.TypeToken;

import io.cloudsoft.tosca.a4c.brooklyn.ToscaApplication;
Expand All @@ -46,61 +35,8 @@ protected ToscaFacade<ToscaApplication> getToscaFacade() {
protected Optional<Object> resolveBrooklynDslValue(Object unresolvedValue, @SuppressWarnings("rawtypes") Optional<TypeToken> desiredType, @Nullable EntitySpec<?> spec) {
return resolveBrooklynDslValue(unresolvedValue, desiredType, mgmt, spec);
}

protected static Object transformSpecialFlags(ManagementContext mgmt, EntitySpec<?> spec, Object v) {
return new BrooklynComponentTemplateResolver.SpecialFlagsTransformer(
CatalogUtils.newClassLoadingContext(mgmt, spec.getCatalogItemId(), ImmutableList.of()),
MutableSet.of()).apply(v);
}

public static Optional<Object> resolveBrooklynDslValue(Object originalValue, @SuppressWarnings("rawtypes") Optional<TypeToken> desiredType, @Nullable ManagementContext mgmt, @Nullable EntitySpec<?> spec) {
if (originalValue == null) {
return Optional.absent();
}
Object value = originalValue;
if (mgmt!=null) {
if (value instanceof String && ((String)value).matches("\\$brooklyn:[A-Za-z_]+:\\s(?s).*")) {
// input is a map as a string, parse it as yaml first
value = Iterables.getOnlyElement( Yamls.parseAll((String)value) );
}

// The 'dsl' key is arbitrary, but the interpreter requires a map
ImmutableMap<String, Object> inputToPdpParse = ImmutableMap.of("dsl", value);
Map<String, Object> resolvedConfigMap = BrooklynCampPlatform.findPlatform(mgmt)
.pdp()
.applyInterpreters(inputToPdpParse);
value = resolvedConfigMap.get("dsl");
// TODO if it fails log a warning -- eg entitySpec with root.war that doesn't exist

if (spec!=null) {
value = transformSpecialFlags(mgmt, spec, value);
}
}

if (value instanceof DeferredSupplier) {
// Don't cast - let Brooklyn evaluate it later (the value is a resolved DSL expression).
return Optional.of(value);
}

if (desiredType.isPresent()) {
// Don't look at generics when casting.
//
// Let Brooklyn do that later when it uses/evaluates the config. We just need to create
// the EntitySpec object.
//
// This is important for DSL expressions (e.g. in a Map<String, String> such as
// TomcatServer's javaSysProps, a DSL expression could not be coerced to a string.
//
// By stripping the generics, it restores the brooklyn behaviour prior to snapshot at
// 31st Aug 2018 (commit 3e57b14b220bd7a994a9143d83bc123879086aff) when map/collection
// generics were not respected during coercion.

Class<?> desiredRawType = desiredType.get().getRawType();

return Optional.of(TypeCoercions.coerce(value, desiredRawType));

} else {
return Optional.of(value);
}
return DslUtils.resolveBrooklynDslValue(originalValue, desiredType.orNull(), mgmt, spec);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public class EntitySpecs {

public static EntitySpec<?> findChildEntitySpecByPlanId(EntitySpec<? extends Application> app, String planId){

// TODO find all!!
Optional<EntitySpec<?>> result = Iterables.tryFind(app.getChildren(),
configSatisfies(BrooklynCampConstants.PLAN_ID, planId));

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package io.cloudsoft.tosca.a4c.brooklyn.plan;

import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;

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.sensor.Feed;
import org.apache.brooklyn.core.entity.Dumper;
import org.apache.brooklyn.core.entity.EntityInternal;
import org.apache.brooklyn.core.mgmt.EntityManagementUtils;
import org.apache.brooklyn.core.mgmt.EntityManagementUtils.CreationResult;
import org.apache.brooklyn.feed.http.HttpFeed;
import org.apache.brooklyn.test.Asserts;
import org.testng.annotations.Test;

import io.cloudsoft.tosca.a4c.Alien4CloudIntegrationTest;

public class ToscaPlanExtraIntegrationTest extends Alien4CloudIntegrationTest {

@Test
public void testSensorParamsUsingProperties() throws Exception {
doNamedSensorTest("properties");
}

@Test
public void testSensorParamsFlatNotAllowed() throws Exception {
try {
doNamedSensorTest("flat");
Asserts.shouldHaveFailedPreviously("'name' should not be recognised unless nested");
} catch (Exception e) {
// expected
}
}

@Test
public void testSensorParamsUsingBrooklynConfig() throws Exception {
doNamedSensorTest("brooklyn-config");
}

protected void doNamedSensorTest(String suffix) throws Exception {
EntitySpec<? extends Application> appSpec = create("classpath://templates/extra/named-sensors-"+suffix+".yaml");
assertNotNull(appSpec);
assertEquals(appSpec.getChildren().size(), 1);

CreationResult<? extends Application, Void> app = EntityManagementUtils.createStarting(mgmt, appSpec);
app.blockUntilComplete();

Entity server = app.get().getChildren().iterator().next();
Dumper.dumpInfo(server);

Feed f = ((EntityInternal)server).feeds().getFeeds().iterator().next();
Asserts.assertInstanceOf(f, HttpFeed.class);
// very hard to get at the HttpConfig of the poll job buried, so we don't make further assertions
// but if "name" isn't being passed correctly, creation above will have failed, so this is a reasonable test
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

Expand Down Expand Up @@ -626,6 +627,35 @@ public void testOverwriteInterfaceOnCustom1Topology() throws Exception {
assertFlagValueContains(custom1, VanillaSoftwareProcess.CUSTOMIZE_COMMAND.getName(), "echo configure arg1"); // in configure.sh
}

@Test
public void testPropertiesIncludingList() throws Exception {
EntitySpec<? extends Application> appSpec = create("classpath://templates/properties-tosca-list.yaml");
// Check the basic structure
assertNotNull(appSpec, "spec");
assertEquals(appSpec.getType(), BasicApplication.class);

assertEquals(appSpec.getChildren().size(), 1, "Expected exactly one child of root application");
EntitySpec<?> compute = Iterators.getOnlyElement(appSpec.getChildren().iterator());
assertEquals(compute.getType(), SameServerEntity.class);

assertEquals(compute.getChildren().size(), 1, "Expected exactly one grandchild of root application");
EntitySpec<?> custom1 = Iterators.getOnlyElement(compute.getChildren().iterator());
assertEquals(custom1.getType(), VanillaSoftwareProcess.class);

// Check that the inputs have been set as exports on the scripts
List<String> expected = Arrays.asList("arg1=\"foo\"", "arg2=\"bar\"", "arg3=\"boo\"");
expected.forEach(s -> assertFlagValueContains(custom1, VanillaSoftwareProcess.CUSTOMIZE_COMMAND.getName(), s));

// and deploy and ensure we get the attribute

Application appInst = this.mgmt.getEntityManager().createEntity(appSpec);
Entity custom1I = Iterables.getOnlyElement( Iterables.getOnlyElement( appInst.getChildren() ).getChildren() );
Dumper.dumpInfo(custom1I);
String customCmd = custom1I.config().get(VanillaSoftwareProcess.CUSTOMIZE_COMMAND);
expected.forEach(s -> Asserts.assertStringContains(customCmd, s));
Asserts.assertStringDoesNotContain(customCmd, "attributeWhenReady", "bip", "baz");
}

// quite restrictive what is supported in A4C:
// attribute can only be set on node type, not in node template.
// it can only define a static _default_ or a subset of functions, operation output or concat.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
tosca_definitions_version: tosca_simple_yaml_1_0_0_wd03

description: Test TOSCA

template_name: test
template_version: 0.1.0-SNAPSHOT

imports:
- tosca-normative-types:1.0.0.wd06-SNAPSHOT

node_types:

x-node:
derived_from: tosca.nodes.Compute
attributes:
x.url:
type: string

x-instance:
derived_from: tosca.nodes.WebServer





topology_template:

node_templates:
x-host:
type: x-node

x:
type: x-instance
artifacts: {}
requirements:
- host: x-host

groups:
add_brooklyn_location:
members: [x-host]
policies:
- brooklyn.location: localhost


latency:
members: [ x-host ]
policies:
- latency_detector:
type: org.apache.brooklyn.policy.enricher.HttpLatencyDetector
name: http.latecy
latencyDetector.period: 1s
latencyDetector.requireServiceUp: true
latencyDetector.rollup: 600s
latencyDetector.url: http://localhost:8069

http_sensor_mgt:
members: [ x-host ]
policies:
- http_sensor:
type: org.apache.brooklyn.core.sensor.http.HttpRequestSensor
brooklyn.config:
name: http.healthy2
period: 10s
suppressDuplicates: true
jsonPath: "$"
uri: http://localhost:8081/v1/server/up/extended/2
Loading