Repository: brooklyn-server Updated Branches: refs/heads/master 34b4c0df9 -> b6bdc80b4
Freemarker DSL Provides "$brooklyn:template(...)" evaluated against the context entity as freemarker template. Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/ca02bfa1 Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/ca02bfa1 Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/ca02bfa1 Branch: refs/heads/master Commit: ca02bfa1c0142f6b7ef1f57882d681e3a3fc7b00 Parents: 092edf1 Author: Svetoslav Neykov <[email protected]> Authored: Wed Aug 2 19:22:07 2017 +0300 Committer: Svetoslav Neykov <[email protected]> Committed: Thu Aug 3 17:07:45 2017 +0300 ---------------------------------------------------------------------- .../spi/dsl/methods/BrooklynDslCommon.java | 4 ++ .../brooklyn/spi/dsl/methods/DslComponent.java | 55 ++++++++++++++++++++ .../camp/brooklyn/DslAndRebindYamlTest.java | 18 +++++++ .../camp/brooklyn/spi/dsl/DslYamlTest.java | 55 ++++++++++++++++++++ 4 files changed, 132 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/ca02bfa1/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 e063cd9..49cf855 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 @@ -798,6 +798,10 @@ public class BrooklynDslCommon { } } + public static Object template(Object template) { + return new DslComponent(Scope.THIS, "").template(template); + } + public static class Functions { @DslAccessible public static Object regexReplacement(final Object pattern, final Object replacement) { http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/ca02bfa1/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 d7e80d2..1693099 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 @@ -51,6 +51,7 @@ import org.apache.brooklyn.util.core.task.ImmediateSupplier; import org.apache.brooklyn.util.core.task.TaskBuilder; import org.apache.brooklyn.util.core.task.TaskTags; import org.apache.brooklyn.util.core.task.Tasks; +import org.apache.brooklyn.util.core.text.TemplateProcessor; import org.apache.brooklyn.util.core.xstream.ObjectWithDefaultStringImplConverter; import org.apache.brooklyn.util.exceptions.Exceptions; import org.apache.brooklyn.util.guava.Maybe; @@ -63,6 +64,7 @@ import com.google.common.base.Optional; import com.google.common.base.Preconditions; import com.google.common.base.Predicate; import com.google.common.base.Predicates; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterables; import com.google.common.util.concurrent.Callables; import com.thoughtworks.xstream.annotations.XStreamConverter; @@ -738,6 +740,59 @@ public class DslComponent extends BrooklynDslDeferredSupplier<Entity> implements } } + public Object template(Object template) { + return new DslTemplate(this, template); + } + + protected final static class DslTemplate extends BrooklynDslDeferredSupplier<Object> { + private static final long serialVersionUID = -585564936781673667L; + private DslComponent component; + private Object template; + + public DslTemplate(DslComponent component, Object template) { + this.component = component; + this.template = template; + } + + private String resolveTemplate(boolean immediately) { + if (template instanceof String) { + return (String)template; + } + + return Tasks.resolving(template) + .as(String.class) + .context(findExecutionContext(this)) + .immediately(immediately) + .description("Resolving template from " + template) + .get(); + } + + @Override + public Maybe<Object> getImmediately() { + String resolvedTemplate = resolveTemplate(true); + + Maybe<Entity> targetEntityMaybe = component.getImmediately(); + if (targetEntityMaybe.isAbsent()) return ImmediateValueNotAvailableException.newAbsentWrapping("Target entity is not available: "+component, targetEntityMaybe); + Entity targetEntity = targetEntityMaybe.get(); + + String evaluatedTemplate = TemplateProcessor.processTemplateContents( + resolvedTemplate, (EntityInternal)targetEntity, ImmutableMap.<String, Object>of()); + return Maybe.of(evaluatedTemplate); + } + + @Override + public Task<Object> newTask() { + return Tasks.<Object>builder().displayName("evaluating template "+template ).dynamic(false).body(new Callable<Object>() { + @Override + public Object call() throws Exception { + Entity targetEntity = component.get(); + return TemplateProcessor.processTemplateContents( + resolveTemplate(false), (EntityInternal)targetEntity, ImmutableMap.<String, Object>of()); + } + }).build(); + } + } + public static enum Scope { GLOBAL, CHILD, http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/ca02bfa1/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 a9c72c8..a88eb9f 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 @@ -29,6 +29,7 @@ import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.apache.brooklyn.api.entity.Application; import org.apache.brooklyn.api.entity.Entity; import org.apache.brooklyn.api.mgmt.ha.MementoCopyMode; import org.apache.brooklyn.api.mgmt.rebind.mementos.BrooklynMementoRawData; @@ -619,4 +620,21 @@ public class DslAndRebindYamlTest extends AbstractYamlRebindTest { EntityAsserts.assertAttributeEqualsEventually(testEntity, transformedSensor, "somebarname"); } + @Test + public void testDslTemplateRebind() throws Exception { + Entity testEntity = entityWithTemplatedString(); + Application app2 = rebind(testEntity.getApplication()); + Entity e2 = Iterables.getOnlyElement(app2.getChildren()); + + Assert.assertEquals(getConfigInTask(e2, TestEntity.CONF_NAME), "hello world"); + } + + protected Entity entityWithTemplatedString() throws Exception { + return setupAndCheckTestEntityInBasicYamlWith( + " id: x", + " brooklyn.config:", + " test.sourceName: hello world", + " test.confName: $brooklyn:template(\"${config['test.sourceName']}\")"); + } + } http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/ca02bfa1/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslYamlTest.java ---------------------------------------------------------------------- diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslYamlTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslYamlTest.java index c995c11..99c1b62 100644 --- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslYamlTest.java +++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslYamlTest.java @@ -38,12 +38,14 @@ import org.apache.brooklyn.core.config.ConfigKeys; import org.apache.brooklyn.core.entity.EntityInternal; import org.apache.brooklyn.core.sensor.Sensors; import org.apache.brooklyn.core.test.entity.TestApplication; +import org.apache.brooklyn.core.test.entity.TestEntity; import org.apache.brooklyn.entity.stock.BasicApplication; import org.apache.brooklyn.entity.stock.BasicEntity; import org.apache.brooklyn.test.Asserts; import org.apache.brooklyn.util.collections.MutableMap; import org.apache.brooklyn.util.exceptions.CompoundRuntimeException; import org.apache.brooklyn.util.guava.Maybe; +import org.testng.Assert; import org.testng.annotations.Test; import com.google.common.base.Function; @@ -790,6 +792,59 @@ public class DslYamlTest extends AbstractYamlTest { assertEquals(getConfigEventually(app, DEST), Boolean.TRUE); } + @Test + public void testDslTemplate() throws Exception { + final Entity app = createAndStartApplication( + "services:", + "- type: " + BasicApplication.class.getName(), + " brooklyn.config:", + " test.sourceName: hello world", + " dest: $brooklyn:template(\"${config['test.sourceName']}\")"); + assertEquals(getConfigEventually(app, DEST), "hello world"); + } + + @Test + public void testDslTemplateOnEntity() throws Exception { + final Entity app = createAndStartApplication( + "services:", + "- type: " + BasicApplication.class.getName(), + " brooklyn.config:", + " dest: $brooklyn:entity(\"configSource\").template(\"${config['test.sourceName']}\")", + "- type: " + BasicApplication.class.getName(), + " id: configSource", + " brooklyn.config:", + " test.sourceName: hello world"); + assertEquals(getConfigEventually(app.getChildren().iterator().next(), DEST), "hello world"); + } + + @Test + public void testDslMultilineTemplate() throws Exception { + final Entity app = createAndStartApplication( + "services:", + "- type: " + BasicApplication.class.getName(), + " brooklyn.config:", + " test.sourceName: hello world", + " dest: ", + " $brooklyn:template:", + " - |", + " ${config['test.sourceName']}"); + assertEquals(getConfigEventually(app, DEST), "hello world"); + } + + @Test + public void testDslTemplateOverDsl() throws Exception { + final Entity app = createAndStartApplication( + "services:", + "- type: " + BasicApplication.class.getName(), + " brooklyn.config:", + " test.value: hello world", + " test.sourceDsl: $brooklyn:config(\"test.value\")", + " test.sourceTemplate: ${config['test.sourceDsl']}", + " dest: $brooklyn:template($brooklyn:config(\"test.sourceTemplate\"))"); + assertEquals(getConfigEventually(app, DEST), "hello world"); + } + + private static <T> T getConfigEventually(final Entity entity, final ConfigKey<T> configKey) throws Exception { // Use an executor, in case config().get() blocks forever, waiting for the config value. ExecutorService executor = Executors.newSingleThreadExecutor();
