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();

Reply via email to