You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by dr...@apache.org on 2017/02/15 10:56:23 UTC

[1/2] brooklyn-server git commit: BROOKLYN-433: regex/obj config key constraint in yaml

Repository: brooklyn-server
Updated Branches:
  refs/heads/master 0f649fe17 -> 38396711d


BROOKLYN-433: regex/obj config key constraint in yaml


Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/4bda12b7
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/4bda12b7
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/4bda12b7

Branch: refs/heads/master
Commit: 4bda12b70ffc2146aa60ac0ab40de52b3b266a8d
Parents: 0f649fe
Author: Aled Sage <al...@gmail.com>
Authored: Fri Feb 3 13:30:09 2017 +0000
Committer: Aled Sage <al...@gmail.com>
Committed: Mon Feb 13 14:22:56 2017 +0000

----------------------------------------------------------------------
 .../camp/brooklyn/ConfigParametersYamlTest.java | 178 +++++++++++++++++++
 .../brooklyn/core/objs/BasicSpecParameter.java  |  69 +++++--
 2 files changed, 235 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/4bda12b7/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ConfigParametersYamlTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ConfigParametersYamlTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ConfigParametersYamlTest.java
index d7040e5..fe602fe 100644
--- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ConfigParametersYamlTest.java
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ConfigParametersYamlTest.java
@@ -22,6 +22,8 @@ import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertTrue;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
@@ -31,6 +33,7 @@ import org.apache.brooklyn.api.entity.EntitySpec;
 import org.apache.brooklyn.api.location.PortRange;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.config.ConstraintViolationException;
 import org.apache.brooklyn.core.entity.BrooklynConfigKeys;
 import org.apache.brooklyn.core.location.PortRanges;
 import org.apache.brooklyn.core.sensor.Sensors;
@@ -52,6 +55,7 @@ import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
 import com.google.common.base.Joiner;
+import com.google.common.base.Predicate;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 
@@ -750,6 +754,180 @@ public class ConfigParametersYamlTest extends AbstractYamlRebindTest {
         assertEquals(entity.sensors().get(Sensors.newSensor(Object.class, "my.param.key")), 1234);
     }
 
+    @Test
+    public void testConfigParameterConstraintRequired() throws Exception {
+        addCatalogItems(
+                "brooklyn.catalog:",
+                "  itemType: entity",
+                "  items:",
+                "  - id: entity-with-keys",
+                "    item:",
+                "      type: "+TestEntity.class.getName(),
+                "      brooklyn.parameters:",
+                "      - name: testRequired",
+                "        type: String",
+                "        constraints:",
+                "        - required");
+        
+        String yamlNoVal = Joiner.on("\n").join(
+                "services:",
+                "- type: entity-with-keys");
+
+        String yamlWithVal = Joiner.on("\n").join(
+                "services:",
+                "- type: entity-with-keys",
+                "  brooklyn.config:",
+                "    testRequired: myval");
+
+        try {
+            createStartWaitAndLogApplication(yamlNoVal);
+            Asserts.shouldHaveFailedPreviously();
+        } catch (ConstraintViolationException e) {
+            // success
+        }
+
+        Entity app = createStartWaitAndLogApplication(yamlWithVal);
+        TestEntity entity = (TestEntity) Iterables.getOnlyElement(app.getChildren());
+        assertKeyEquals(entity, "testRequired", null, String.class, null, "myval");
+
+        // Rebind, and then check again that the config key is listed
+        Entity newApp = rebind();
+        TestEntity newEntity = (TestEntity) Iterables.getOnlyElement(newApp.getChildren());
+        assertKeyEquals(newEntity, "testRequired", null, String.class, null, "myval");
+    }
+
+    @Test
+    public void testConfigParameterConstraintRegex() throws Exception {
+        addCatalogItems(
+                "brooklyn.catalog:",
+                "  itemType: entity",
+                "  items:",
+                "  - id: entity-with-keys",
+                "    item:",
+                "      type: "+TestEntity.class.getName(),
+                "      brooklyn.parameters:",
+                "      - name: testRequired",
+                "        type: String",
+                "        constraints:",
+                "        - regex: myprefix.*");
+        
+        String yamlNoVal = Joiner.on("\n").join(
+                "services:",
+                "- type: entity-with-keys");
+
+        String yamlWrongVal = Joiner.on("\n").join(
+                "services:",
+                "- type: entity-with-keys",
+                "  brooklyn.config:",
+                "    testRequired: wrongval");
+
+        String yamlWithVal = Joiner.on("\n").join(
+                "services:",
+                "- type: entity-with-keys",
+                "  brooklyn.config:",
+                "    testRequired: myprefix-myVal");
+
+        try {
+            createStartWaitAndLogApplication(yamlNoVal);
+            Asserts.shouldHaveFailedPreviously();
+        } catch (ConstraintViolationException e) {
+            Asserts.expectedFailureContains(e, "matchesRegex"); // success
+        }
+
+        try {
+            createStartWaitAndLogApplication(yamlWrongVal);
+            Asserts.shouldHaveFailedPreviously();
+        } catch (ConstraintViolationException e) {
+            Asserts.expectedFailureContains(e, "Invalid value for", "wrongval"); // success
+        }
+
+        Entity app = createStartWaitAndLogApplication(yamlWithVal);
+        TestEntity entity = (TestEntity) Iterables.getOnlyElement(app.getChildren());
+        assertKeyEquals(entity, "testRequired", null, String.class, null, "myprefix-myVal");
+
+        // Rebind, and then check again that the config key is listed
+        Entity newApp = rebind();
+        TestEntity newEntity = (TestEntity) Iterables.getOnlyElement(newApp.getChildren());
+        assertKeyEquals(newEntity, "testRequired", null, String.class, null, "myprefix-myVal");
+    }
+
+    @Test
+    public void testConfigParameterConstraintObject() throws Exception {
+        addCatalogItems(
+                "brooklyn.catalog:",
+                "  itemType: entity",
+                "  items:",
+                "  - id: entity-with-keys",
+                "    item:",
+                "      type: "+TestEntity.class.getName(),
+                "      brooklyn.parameters:",
+                "      - name: testRequired",
+                "        type: String",
+                "        constraints:",
+                "        - $brooklyn:object:",
+                "            type: " + PredicateRegexPojo.class.getName(),
+                "            object.fields:",
+                "              regex: myprefix.*");
+                
+        
+        String yamlNoVal = Joiner.on("\n").join(
+                "services:",
+                "- type: entity-with-keys");
+
+        String yamlWrongVal = Joiner.on("\n").join(
+                "services:",
+                "- type: entity-with-keys",
+                "  brooklyn.config:",
+                "    testRequired: wrongval");
+
+        String yamlWithVal = Joiner.on("\n").join(
+                "services:",
+                "- type: entity-with-keys",
+                "  brooklyn.config:",
+                "    testRequired: myprefix-myVal");
+
+        try {
+            createStartWaitAndLogApplication(yamlNoVal);
+            Asserts.shouldHaveFailedPreviously();
+        } catch (ConstraintViolationException e) {
+            Asserts.expectedFailureContains(e, "Error configuring", "PredicateRegexPojo(myprefix.*)"); // success
+        }
+
+        try {
+            createStartWaitAndLogApplication(yamlWrongVal);
+            Asserts.shouldHaveFailedPreviously();
+        } catch (ConstraintViolationException e) {
+            Asserts.expectedFailureContains(e, "Invalid value for", "wrongval"); // success
+        }
+
+        Entity app = createStartWaitAndLogApplication(yamlWithVal);
+        TestEntity entity = (TestEntity) Iterables.getOnlyElement(app.getChildren());
+        assertKeyEquals(entity, "testRequired", null, String.class, null, "myprefix-myVal");
+
+        // Rebind, and then check again that the config key is listed
+        Entity newApp = rebind();
+        TestEntity newEntity = (TestEntity) Iterables.getOnlyElement(newApp.getChildren());
+        assertKeyEquals(newEntity, "testRequired", null, String.class, null, "myprefix-myVal");
+    }
+
+    public static class PredicateRegexPojo implements Predicate<Object> {
+        private String regex;
+
+        public void setRegex(final String regex) {
+            this.regex = checkNotNull(regex, "regex");
+        }
+
+        @Override
+        public boolean apply(Object input) {
+            return (input instanceof String) && ((String)input).matches(regex);
+        }
+        
+        @Override
+        public String toString() {
+            return "PredicateRegexPojo("+regex+")";
+        }
+    }
+
     protected <T> void assertKeyEquals(Entity entity, String keyName, String expectedDescription, Class<T> expectedType, T expectedDefaultVal, T expectedEntityVal) {
         ConfigKey<?> key = entity.getEntityType().getConfigKey(keyName);
         assertNotNull(key, "No key '"+keyName+"'; keys="+entity.getEntityType().getConfigKeys());

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/4bda12b7/core/src/main/java/org/apache/brooklyn/core/objs/BasicSpecParameter.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/objs/BasicSpecParameter.java b/core/src/main/java/org/apache/brooklyn/core/objs/BasicSpecParameter.java
index cc9d66a..d8c0522 100644
--- a/core/src/main/java/org/apache/brooklyn/core/objs/BasicSpecParameter.java
+++ b/core/src/main/java/org/apache/brooklyn/core/objs/BasicSpecParameter.java
@@ -18,6 +18,8 @@
  */
 package org.apache.brooklyn.core.objs;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -56,6 +58,7 @@ import com.google.common.base.Predicates;
 import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
 import com.google.common.reflect.TypeToken;
 
 public class BasicSpecParameter<T> implements SpecParameter<T>{
@@ -203,7 +206,16 @@ public class BasicSpecParameter<T> implements SpecParameter<T>{
 
         private static final Map<String, Predicate<?>> BUILT_IN_CONSTRAINTS = ImmutableMap.<String, Predicate<?>>of(
                 "required", StringPredicates.isNonBlank());
-
+        
+        private static final Map<String, Function<Object, Predicate<?>>> BUILT_IN_CONSTRAINT_FACTORIES = ImmutableMap.<String, Function<Object, Predicate<?>>>of(
+                "regex", new Function<Object, Predicate<?>>() {
+                    @Override public Predicate<?> apply(Object input) {
+                        // TODO Could try to handle deferred supplier as well?
+                        checkArgument(input instanceof String, "Constraint regex value must be a string, but got %s (%s)",
+                                (input == null ? "null" : input.getClass().getName()), input);
+                        return StringPredicates.matchesRegex((String)input);
+                    }});
+        
         public static List<SpecParameter<?>> parseParameters(List<?> inputsRaw, Function<Object, Object> specialFlagTransformer, BrooklynClassLoadingContext loader) {
             if (inputsRaw == null) return ImmutableList.of();
             List<SpecParameter<?>> inputs = new ArrayList<>(inputsRaw.size());
@@ -279,25 +291,21 @@ public class BasicSpecParameter<T> implements SpecParameter<T>{
         }
 
         @SuppressWarnings({ "unchecked", "rawtypes" })
-        private static Predicate parseConstraints(Object obj, BrooklynClassLoadingContext loader) {
-            List constraintsRaw;
+        private static Predicate<?> parseConstraints(Object obj, BrooklynClassLoadingContext loader) {
+            List<?> constraintsRaw;
             if (obj == null) {
                 constraintsRaw = ImmutableList.of();
             } else if (obj instanceof String) {
                 constraintsRaw = ImmutableList.of(obj);
             } else if (obj instanceof List) {
-                constraintsRaw = (List) obj;
+                constraintsRaw = (List<?>) obj;
             } else {
-                throw new IllegalArgumentException ("The constraint '" + obj + "' for a catalog input is invalid format - string or list supported");
+                throw new IllegalArgumentException ("The constraint '" + obj + "' for a catalog input is invalid format - "
+                        + "string or list supported");
             }
-            List<Predicate> constraints = new ArrayList(constraintsRaw.size());
+            List<Predicate<?>> constraints = new ArrayList<>(constraintsRaw.size());
             for (Object untypedConstraint : constraintsRaw) {
-                String constraint = (String)untypedConstraint;
-                if (BUILT_IN_CONSTRAINTS.containsKey(constraint)) {
-                    constraints.add(BUILT_IN_CONSTRAINTS.get(constraint));
-                } else {
-                    throw new IllegalArgumentException("The constraint '" + constraint + "' for a catalog input is not recognized as a built-in (" + BUILT_IN_CONSTRAINTS.keySet() + ")");
-                }
+                constraints.add(parseConstraint(untypedConstraint, loader));
             }
             if (!constraints.isEmpty()) {
                 if (constraints.size() == 1) {
@@ -310,6 +318,43 @@ public class BasicSpecParameter<T> implements SpecParameter<T>{
             }
         }
         
+        private static Predicate<?> parseConstraint(Object untypedConstraint, BrooklynClassLoadingContext loader) {
+            // TODO Could try to handle deferred supplier as well?
+            if (untypedConstraint instanceof Predicate) {
+                // An explicit predicate (e.g. via "$brooklyn:object: ...")
+                return (Predicate<?>) untypedConstraint;
+            } else if (untypedConstraint instanceof String) {
+                // build-in simple declaration, such as "required"
+                String constraint = (String)untypedConstraint;
+                if (BUILT_IN_CONSTRAINTS.containsKey(constraint)) {
+                    return BUILT_IN_CONSTRAINTS.get(constraint);
+                } else {
+                    throw new IllegalArgumentException("The constraint '" + constraint + "' for a catalog input is not "
+                            + "recognized as a built-in (" + BUILT_IN_CONSTRAINTS.keySet() + " or " 
+                            + BUILT_IN_CONSTRAINT_FACTORIES.keySet() + ")");
+                }
+            } else if (untypedConstraint instanceof Map) {
+                // For example "regex: foo.*"
+                Map<?,?> constraint = (Map<?,?>)untypedConstraint;
+                if (constraint.size() == 1) {
+                    Object key = Iterables.getOnlyElement(constraint.keySet());
+                    Object val = constraint.get(key);
+                    if (BUILT_IN_CONSTRAINT_FACTORIES.containsKey(key)) {
+                        Function<Object, Predicate<?>> factory = BUILT_IN_CONSTRAINT_FACTORIES.get(key);
+                        return factory.apply(val);
+                    } else {
+                        throw new IllegalArgumentException("The constraint '" + constraint + "' for a catalog input is not "
+                                + "recognized as a built-in (" + BUILT_IN_CONSTRAINTS.keySet() + ")");
+                    }
+                } else {
+                    throw new IllegalArgumentException("The config key constraint '" + constraint + "' is not supported - "
+                            + "it can handle only single key:value constraint.");
+                }
+            } else {
+                throw new IllegalArgumentException("The constraint '" + untypedConstraint + "' for a catalog input is not recognized");
+            }
+        }
+        
         private static ConfigInheritance parseInheritance(Object obj, BrooklynClassLoadingContext loader) {
             if (obj == null || obj instanceof String) {
                 // TODO


[2/2] brooklyn-server git commit: This closes #558

Posted by dr...@apache.org.
This closes #558


Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/38396711
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/38396711
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/38396711

Branch: refs/heads/master
Commit: 38396711d3b26d37142bdd660253edf269c3216f
Parents: 0f649fe 4bda12b
Author: Duncan Godwin <dr...@googlemail.com>
Authored: Wed Feb 15 10:55:59 2017 +0000
Committer: Duncan Godwin <dr...@googlemail.com>
Committed: Wed Feb 15 10:55:59 2017 +0000

----------------------------------------------------------------------
 .../camp/brooklyn/ConfigParametersYamlTest.java | 178 +++++++++++++++++++
 .../brooklyn/core/objs/BasicSpecParameter.java  |  69 +++++--
 2 files changed, 235 insertions(+), 12 deletions(-)
----------------------------------------------------------------------