You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by al...@apache.org on 2016/11/11 11:56:21 UTC
[3/4] brooklyn-server git commit: BROOKLYN-381: nested DSL support in
$brooklyn:entity()
BROOKLYN-381: nested DSL support in $brooklyn:entity()
For example, $brooklyn:entity(attributeWhenReady(\u201ctargetId\u201d))
Also tests this in the context of a TestHttpCall, in TestHttpCallTest
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/62a295cc
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/62a295cc
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/62a295cc
Branch: refs/heads/master
Commit: 62a295cc6967ed507f041365f91bd1fbfd377d8e
Parents: d7b4459
Author: Aled Sage <al...@gmail.com>
Authored: Tue Nov 8 15:59:39 2016 +0000
Committer: Aled Sage <al...@gmail.com>
Committed: Fri Nov 11 09:30:22 2016 +0000
----------------------------------------------------------------------
.../spi/dsl/methods/BrooklynDslCommon.java | 31 ++--
.../brooklyn/spi/dsl/methods/DslComponent.java | 175 ++++++++++++++++---
.../camp/brooklyn/DslAndRebindYamlTest.java | 74 ++++++++
.../framework/yaml/TestHttpCallYamlTest.java | 21 +++
4 files changed, 258 insertions(+), 43 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/62a295cc/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
index 8fb48cf..1bf93d7 100644
--- a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
+++ b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
@@ -39,7 +39,6 @@ import org.apache.brooklyn.camp.brooklyn.spi.creation.BrooklynYamlTypeInstantiat
import org.apache.brooklyn.camp.brooklyn.spi.creation.EntitySpecConfiguration;
import org.apache.brooklyn.camp.brooklyn.spi.dsl.BrooklynDslDeferredSupplier;
import org.apache.brooklyn.camp.brooklyn.spi.dsl.methods.DslComponent.Scope;
-import org.apache.brooklyn.core.config.ConfigKeys;
import org.apache.brooklyn.core.config.external.ExternalConfigSupplier;
import org.apache.brooklyn.core.entity.EntityDynamicType;
import org.apache.brooklyn.core.entity.EntityInternal;
@@ -53,8 +52,8 @@ import org.apache.brooklyn.util.collections.MutableMap;
import org.apache.brooklyn.util.core.ClassLoaderUtils;
import org.apache.brooklyn.util.core.config.ConfigBag;
import org.apache.brooklyn.util.core.flags.FlagUtils;
+import org.apache.brooklyn.util.core.task.DeferredSupplier;
import org.apache.brooklyn.util.core.task.Tasks;
-import org.apache.brooklyn.util.core.task.ValueResolver;
import org.apache.brooklyn.util.exceptions.Exceptions;
import org.apache.brooklyn.util.guava.Maybe;
import org.apache.brooklyn.util.javalang.Reflections;
@@ -78,31 +77,31 @@ public class BrooklynDslCommon {
// Access specific entities
public static DslComponent self() {
- return new DslComponent(Scope.THIS, null);
+ return new DslComponent(Scope.THIS);
}
- public static DslComponent entity(String id) {
- return new DslComponent(Scope.GLOBAL, id);
+ public static DslComponent entity(Object id) {
+ return DslComponent.newInstance(Scope.GLOBAL, id);
}
public static DslComponent parent() {
- return new DslComponent(Scope.PARENT, null);
+ return new DslComponent(Scope.PARENT);
}
- public static DslComponent child(String id) {
- return new DslComponent(Scope.CHILD, id);
+ public static DslComponent child(Object id) {
+ return DslComponent.newInstance(Scope.CHILD, id);
}
- public static DslComponent sibling(String id) {
- return new DslComponent(Scope.SIBLING, id);
+ public static DslComponent sibling(Object id) {
+ return DslComponent.newInstance(Scope.SIBLING, id);
}
- public static DslComponent descendant(String id) {
- return new DslComponent(Scope.DESCENDANT, id);
+ public static DslComponent descendant(Object id) {
+ return DslComponent.newInstance(Scope.DESCENDANT, id);
}
- public static DslComponent ancestor(String id) {
- return new DslComponent(Scope.ANCESTOR, id);
+ public static DslComponent ancestor(Object id) {
+ return DslComponent.newInstance(Scope.ANCESTOR, id);
}
public static DslComponent root() {
- return new DslComponent(Scope.ROOT, null);
+ return new DslComponent(Scope.ROOT);
}
public static DslComponent scopeRoot() {
- return new DslComponent(Scope.SCOPE_ROOT, null);
+ return new DslComponent(Scope.SCOPE_ROOT);
}
// prefer the syntax above to the below now, but not deprecating the below
public static DslComponent component(String id) {
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/62a295cc/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java
index b2f20d3..1bd20eb 100644
--- a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java
+++ b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java
@@ -18,6 +18,8 @@
*/
package org.apache.brooklyn.camp.brooklyn.spi.dsl.methods;
+import static org.apache.brooklyn.camp.brooklyn.spi.dsl.DslUtils.resolved;
+
import java.util.NoSuchElementException;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
@@ -38,6 +40,9 @@ import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
import org.apache.brooklyn.core.mgmt.internal.EntityManagerInternal;
import org.apache.brooklyn.core.sensor.DependentConfiguration;
import org.apache.brooklyn.core.sensor.Sensors;
+import org.apache.brooklyn.util.core.flags.TypeCoercions;
+import org.apache.brooklyn.util.core.task.BasicExecutionContext;
+import org.apache.brooklyn.util.core.task.DeferredSupplier;
import org.apache.brooklyn.util.core.task.ImmediateSupplier;
import org.apache.brooklyn.util.core.task.TaskBuilder;
import org.apache.brooklyn.util.core.task.Tasks;
@@ -45,6 +50,7 @@ import org.apache.brooklyn.util.exceptions.Exceptions;
import org.apache.brooklyn.util.groovy.GroovyJavaMethods;
import org.apache.brooklyn.util.guava.Maybe;
import org.apache.brooklyn.util.text.StringEscapes.JavaStringEscapes;
+import org.apache.brooklyn.util.text.Strings;
import com.google.common.base.CaseFormat;
import com.google.common.base.Converter;
@@ -61,10 +67,39 @@ public class DslComponent extends BrooklynDslDeferredSupplier<Entity> {
private static final long serialVersionUID = -7715984495268724954L;
private final String componentId;
+ private final DeferredSupplier<?> componentIdSupplier;
private final DslComponent scopeComponent;
private final Scope scope;
/**
+ * Checks the type of {@code componentId} to create the right kind of {@link DslComponent}
+ * (based on whether the componentId is already resolved. Accepts either a {@link String} or a
+ * {@link DeferredSupplier}.
+ */
+ public static DslComponent newInstance(DslComponent scopeComponent, Scope scope, Object componentId) {
+ if (resolved(componentId)) {
+ // if all args are resolved, apply the componentId now
+ return new DslComponent(scopeComponent, scope, (String) componentId);
+ } else {
+ return new DslComponent(scopeComponent, scope, (DeferredSupplier<?>)componentId);
+ }
+ }
+
+ /**
+ * Checks the type of {@code componentId} to create the right kind of {@link DslComponent}
+ * (based on whether the componentId is already resolved. Accepts either a {@link String} or a
+ * {@link DeferredSupplier}.
+ */
+ public static DslComponent newInstance(Scope scope, Object componentId) {
+ if (resolved(componentId)) {
+ // if all args are resolved, apply the componentId now
+ return new DslComponent(scope, (String) componentId);
+ } else {
+ return new DslComponent(scope, (DeferredSupplier<?>)componentId);
+ }
+ }
+
+ /**
* Resolve componentId in the {@link Scope#GLOBAL} scope.
*
* @deprecated since 0.10.0; pass the {@link Scope} explicitly.
@@ -75,6 +110,25 @@ public class DslComponent extends BrooklynDslDeferredSupplier<Entity> {
}
/**
+ * Resolve in scope relative to the current
+ * {@link BrooklynTaskTags#getTargetOrContextEntity) target or context} entity
+ * (where the scope defines an unambiguous relationship that will resolve to a single
+ * component - e.g. "parent").
+ */
+ public DslComponent(Scope scope) {
+ this(null, scope);
+ }
+
+ /**
+ * Resolve in scope relative to {@code scopeComponent} entity
+ * (where the scope defines an unambiguous relationship that will resolve to a single
+ * component - e.g. "parent").
+ */
+ public DslComponent(DslComponent scopeComponent, Scope scope) {
+ this(scopeComponent, scope, (String)null);
+ }
+
+ /**
* Resolve componentId in scope relative to the current
* {@link BrooklynTaskTags#getTargetOrContextEntity) target or context} entity.
*/
@@ -82,6 +136,10 @@ public class DslComponent extends BrooklynDslDeferredSupplier<Entity> {
this(null, scope, componentId);
}
+ public DslComponent(Scope scope, DeferredSupplier<?> componentIdSupplier) {
+ this(null, scope, componentIdSupplier);
+ }
+
/**
* Resolve componentId in scope relative to scopeComponent.
*/
@@ -89,6 +147,18 @@ public class DslComponent extends BrooklynDslDeferredSupplier<Entity> {
Preconditions.checkNotNull(scope, "scope");
this.scopeComponent = scopeComponent;
this.componentId = componentId;
+ this.componentIdSupplier = null;
+ this.scope = scope;
+ }
+
+ /**
+ * Resolve componentId in scope relative to scopeComponent.
+ */
+ public DslComponent(DslComponent scopeComponent, Scope scope, DeferredSupplier<?> componentIdSupplier) {
+ Preconditions.checkNotNull(scope, "scope");
+ this.scopeComponent = scopeComponent;
+ this.componentId = null;
+ this.componentIdSupplier = componentIdSupplier;
this.scope = scope;
}
@@ -96,7 +166,7 @@ public class DslComponent extends BrooklynDslDeferredSupplier<Entity> {
@Override
public final Maybe<Entity> getImmediately() {
- return new EntityInScopeFinder(scopeComponent, scope, componentId).getImmediately();
+ return new EntityInScopeFinder(scopeComponent, scope, componentId, componentIdSupplier).getImmediately();
}
@Override
@@ -104,7 +174,7 @@ public class DslComponent extends BrooklynDslDeferredSupplier<Entity> {
return TaskBuilder.<Entity>builder()
.displayName(toString())
.tag(BrooklynTaskTags.TRANSIENT_TASK_TAG)
- .body(new EntityInScopeFinder(scopeComponent, scope, componentId))
+ .body(new EntityInScopeFinder(scopeComponent, scope, componentId, componentIdSupplier))
.build();
}
@@ -112,11 +182,13 @@ public class DslComponent extends BrooklynDslDeferredSupplier<Entity> {
protected final DslComponent scopeComponent;
protected final Scope scope;
protected final String componentId;
-
- public EntityInScopeFinder(DslComponent scopeComponent, Scope scope, String componentId) {
+ protected final DeferredSupplier<?> componentIdSupplier;
+
+ public EntityInScopeFinder(DslComponent scopeComponent, Scope scope, String componentId, DeferredSupplier<?> componentIdSupplier) {
this.scopeComponent = scopeComponent;
this.scope = scope;
this.componentId = componentId;
+ this.componentIdSupplier = componentIdSupplier;
}
@Override
@@ -185,63 +257,112 @@ public class DslComponent extends BrooklynDslDeferredSupplier<Entity> {
throw new IllegalStateException("Unexpected scope "+scope);
}
- Optional<Entity> result = Iterables.tryFind(entitiesToSearch, EntityPredicates.configEqualTo(BrooklynCampConstants.PLAN_ID, componentId));
+ String desiredComponentId;
+ if (componentId == null) {
+ if (componentIdSupplier == null) {
+ throw new IllegalArgumentException("No component-id or component-id supplier, when resolving entity in scope '" + scope + "' wrt " + entity);
+ }
+
+ Maybe<Object> maybeComponentId = Tasks.resolving(componentIdSupplier)
+ .as(Object.class)
+ .context(getExecutionContext())
+ .immediately(immediate)
+ .description("Resolving component-id from " + componentIdSupplier)
+ .getMaybe();
+
+ if (immediate) {
+ if (maybeComponentId.isAbsent()) {
+ return Maybe.absent(Maybe.getException(maybeComponentId));
+ }
+ }
+
+ // Support being passes an explicit entity via the DSL
+ if (maybeComponentId.get() instanceof Entity) {
+ if (Iterables.contains(entitiesToSearch, maybeComponentId.get())) {
+ return Maybe.of((Entity)maybeComponentId.get());
+ } else {
+ throw new IllegalStateException("Resolved component " + maybeComponentId.get() + " is not in scope '" + scope + "' wrt " + entity);
+ }
+ }
+
+ desiredComponentId = TypeCoercions.coerce(maybeComponentId.get(), String.class);
+
+ if (Strings.isBlank(desiredComponentId)) {
+ throw new IllegalStateException("component-id blank, from " + componentIdSupplier);
+ }
+
+ } else {
+ desiredComponentId = componentId;
+ }
+
+ Optional<Entity> result = Iterables.tryFind(entitiesToSearch, EntityPredicates.configEqualTo(BrooklynCampConstants.PLAN_ID, desiredComponentId));
if (result.isPresent()) {
return Maybe.of(result.get());
}
// TODO may want to block and repeat on new entities joining?
- throw new NoSuchElementException("No entity matching id " + componentId+
+ throw new NoSuchElementException("No entity matching id " + desiredComponentId+
(scope==Scope.GLOBAL ? "" : ", in scope "+scope+" wrt "+entity+
(scopeComponent!=null ? " ("+scopeComponent+" from "+entity()+")" : "")));
- }
+ }
+
+ private ExecutionContext getExecutionContext() {
+ EntityInternal contextEntity = (EntityInternal) BrooklynTaskTags.getTargetOrContextEntity(Tasks.current());
+ ExecutionContext execContext =
+ (contextEntity != null) ? contextEntity.getExecutionContext()
+ : BasicExecutionContext.getCurrentExecutionContext();
+ if (execContext == null) {
+ throw new IllegalStateException("No execution context available to resolve " + toString());
+ }
+ return execContext;
+ }
}
// -------------------------------
// DSL words which move to a new component
- public DslComponent entity(String scopeOrId) {
- return new DslComponent(this, Scope.GLOBAL, scopeOrId);
+ public DslComponent entity(Object id) {
+ return DslComponent.newInstance(this, Scope.GLOBAL, id);
}
- public DslComponent child(String scopeOrId) {
- return new DslComponent(this, Scope.CHILD, scopeOrId);
+ public DslComponent child(Object id) {
+ return DslComponent.newInstance(this, Scope.CHILD, id);
}
- public DslComponent sibling(String scopeOrId) {
- return new DslComponent(this, Scope.SIBLING, scopeOrId);
+ public DslComponent sibling(Object id) {
+ return DslComponent.newInstance(this, Scope.SIBLING, id);
}
- public DslComponent descendant(String scopeOrId) {
- return new DslComponent(this, Scope.DESCENDANT, scopeOrId);
+ public DslComponent descendant(Object id) {
+ return DslComponent.newInstance(this, Scope.DESCENDANT, id);
}
- public DslComponent ancestor(String scopeOrId) {
- return new DslComponent(this, Scope.ANCESTOR, scopeOrId);
+ public DslComponent ancestor(Object id) {
+ return DslComponent.newInstance(this, Scope.ANCESTOR, id);
}
public DslComponent root() {
- return new DslComponent(this, Scope.ROOT, "");
+ return new DslComponent(this, Scope.ROOT);
}
public DslComponent scopeRoot() {
- return new DslComponent(this, Scope.SCOPE_ROOT, "");
+ return new DslComponent(this, Scope.SCOPE_ROOT);
}
@Deprecated /** @deprecated since 0.7.0 */
- public DslComponent component(String scopeOrId) {
- return new DslComponent(this, Scope.GLOBAL, scopeOrId);
+ public DslComponent component(Object id) {
+ return DslComponent.newInstance(this, Scope.GLOBAL, id);
}
public DslComponent self() {
- return new DslComponent(this, Scope.THIS, null);
+ return new DslComponent(this, Scope.THIS);
}
public DslComponent parent() {
- return new DslComponent(this, Scope.PARENT, "");
+ return new DslComponent(this, Scope.PARENT);
}
- public DslComponent component(String scope, String id) {
+ public DslComponent component(String scope, Object id) {
if (!DslComponent.Scope.isValid(scope)) {
- throw new IllegalArgumentException(scope + " is not a vlaid scope");
+ throw new IllegalArgumentException(scope + " is not a valid scope");
}
- return new DslComponent(this, DslComponent.Scope.fromString(scope), id);
+ return DslComponent.newInstance(this, DslComponent.Scope.fromString(scope), id);
}
// DSL words which return things
@@ -564,7 +685,7 @@ public class DslComponent extends BrooklynDslDeferredSupplier<Entity> {
return "$brooklyn:entity("+
(scopeComponent==null ? "" : JavaStringEscapes.wrapJavaString(scopeComponent.toString())+", ")+
(scope==Scope.GLOBAL ? "" : JavaStringEscapes.wrapJavaString(scope.toString())+", ")+
- JavaStringEscapes.wrapJavaString(componentId)+
+ (componentId != null ? JavaStringEscapes.wrapJavaString(componentId) : componentIdSupplier)+
")";
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/62a295cc/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/DslAndRebindYamlTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/DslAndRebindYamlTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/DslAndRebindYamlTest.java
index 16ff411..91da883 100644
--- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/DslAndRebindYamlTest.java
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/DslAndRebindYamlTest.java
@@ -45,7 +45,9 @@ import org.apache.brooklyn.core.mgmt.persist.BrooklynPersistenceUtils;
import org.apache.brooklyn.core.sensor.Sensors;
import org.apache.brooklyn.core.test.entity.TestEntity;
import org.apache.brooklyn.entity.group.DynamicCluster;
+import org.apache.brooklyn.test.Asserts;
import org.apache.brooklyn.util.core.task.Tasks;
+import org.apache.brooklyn.util.exceptions.Exceptions;
import org.apache.brooklyn.util.guava.Maybe;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -432,6 +434,78 @@ public class DslAndRebindYamlTest extends AbstractYamlRebindTest {
Assert.assertEquals(getConfigInTask(e2, TestEntity.CONF_NAME), "hello world");
}
+ @Test
+ public void testDslEntityById() throws Exception {
+ Entity testEntity = setupAndCheckTestEntityInBasicYamlWith(
+ " id: x",
+ " brooklyn.config:",
+ " test.confObject: $brooklyn:entity(\"x\")");
+ Assert.assertEquals(getConfigInTask(testEntity, TestEntity.CONF_OBJECT), testEntity);
+
+ Entity e2 = rebind(testEntity);
+ Assert.assertEquals(getConfigInTask(e2, TestEntity.CONF_OBJECT), e2);
+ }
+
+ @Test
+ public void testDslEntityWhereIdRetrievedFromAttributeWhenReadyDsl() throws Exception {
+ Entity testEntity = setupAndCheckTestEntityInBasicYamlWith(
+ " id: x",
+ " brooklyn.config:",
+ " test.confObject: $brooklyn:entity(attributeWhenReady(\"mySensor\"))");
+ testEntity.sensors().set(Sensors.newStringSensor("mySensor"), "x");
+ Assert.assertEquals(getConfigInTask(testEntity, TestEntity.CONF_OBJECT), testEntity);
+
+ Entity e2 = rebind(testEntity);
+ Assert.assertEquals(getConfigInTask(e2, TestEntity.CONF_OBJECT), e2);
+ }
+
+ @Test
+ public void testDslEntityWhereAttributeWhenReadyDslReturnsEntity() throws Exception {
+ Entity testEntity = setupAndCheckTestEntityInBasicYamlWith(
+ " id: x",
+ " brooklyn.config:",
+ " test.confObject: $brooklyn:entity(attributeWhenReady(\"mySensor\"))");
+ testEntity.sensors().set(Sensors.newSensor(Entity.class, "mySensor"), testEntity);
+ Assert.assertEquals(getConfigInTask(testEntity, TestEntity.CONF_OBJECT), testEntity);
+
+ Entity e2 = rebind(testEntity);
+ Assert.assertEquals(getConfigInTask(e2, TestEntity.CONF_OBJECT), e2);
+ }
+
+ @Test
+ public void testDslChildWhereIdRetrievedFromAttributeWhenReadyDsl() throws Exception {
+ Entity testEntity = setupAndCheckTestEntityInBasicYamlWith(
+ " id: x",
+ " brooklyn.config:",
+ " test.confObject: $brooklyn:child(attributeWhenReady(\"mySensor\"))",
+ " brooklyn.children:",
+ " - type: " + TestEntity.class.getName(),
+ " id: x");
+ Entity childEntity = Iterables.getOnlyElement(testEntity.getChildren());
+ testEntity.sensors().set(Sensors.newStringSensor("mySensor"), "x");
+ Assert.assertEquals(getConfigInTask(testEntity, TestEntity.CONF_OBJECT), childEntity);
+
+ Entity e2 = rebind(testEntity);
+ Entity child2 = Iterables.getOnlyElement(e2.getChildren());
+ Assert.assertEquals(getConfigInTask(e2, TestEntity.CONF_OBJECT), child2);
+ }
+
+ @Test
+ public void testDslChildWhereAttributeWhenReadyDslReturnsEntityOutOfScopeFails() throws Exception {
+ Entity testEntity = setupAndCheckTestEntityInBasicYamlWith(
+ " id: x",
+ " brooklyn.config:",
+ " test.confObject: $brooklyn:child(attributeWhenReady(\"mySensor\"))");
+ testEntity.sensors().set(Sensors.newSensor(Entity.class, "mySensor"), testEntity);
+ try {
+ Object val = getConfigInTask(testEntity, TestEntity.CONF_OBJECT);
+ Asserts.shouldHaveFailedPreviously("actual="+val);
+ } catch (Exception e) {
+ IllegalStateException ise = Exceptions.getFirstThrowableOfType(e, IllegalStateException.class);
+ if (ise == null || !ise.toString().contains("is not in scope 'child'")) throw e;
+ }
+ }
+
/*
- type: org.apache.brooklyn.enricher.stock.Transformer
brooklyn.config:
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/62a295cc/test-framework/src/test/java/org/apache/brooklyn/test/framework/yaml/TestHttpCallYamlTest.java
----------------------------------------------------------------------
diff --git a/test-framework/src/test/java/org/apache/brooklyn/test/framework/yaml/TestHttpCallYamlTest.java b/test-framework/src/test/java/org/apache/brooklyn/test/framework/yaml/TestHttpCallYamlTest.java
index 38a6328..671b2c4 100644
--- a/test-framework/src/test/java/org/apache/brooklyn/test/framework/yaml/TestHttpCallYamlTest.java
+++ b/test-framework/src/test/java/org/apache/brooklyn/test/framework/yaml/TestHttpCallYamlTest.java
@@ -90,4 +90,25 @@ public class TestHttpCallYamlTest extends AbstractYamlRebindTest {
" equals: 200"
);
}
+
+ @Test
+ public void testUrlConstructedFromTargetEntity() throws Exception {
+ origApp = (BasicApplication) createStartWaitAndLogApplication(
+ "services:",
+ "- type: " + TestEntity.class.getName(),
+ " id: target-app",
+ " brooklyn.config:",
+ " main.uri: " + server.getUrl(),
+ "- type: " + TestHttpCall.class.getName(),
+ " brooklyn.config:",
+ " targetId: target-app",
+ " url:",
+ " $brooklyn:formatString:",
+ " - \"%s/index.html\"",
+ " - $brooklyn:entity(config(\"targetId\")).config(\"main.uri\")",
+ " applyAssertionTo: status",
+ " assert:",
+ " equals: 200"
+ );
+ }
}