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 2015/12/17 13:54:25 UTC
[4/5] incubator-brooklyn git commit: BrooklynProperties handles
externalised config
BrooklynProperties handles externalised config
- Adds DeferredBrooklynProperties
- Adds tests (ExternalConfigBrooklynPropertiesTest)
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/f66a72d2
Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/f66a72d2
Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/f66a72d2
Branch: refs/heads/master
Commit: f66a72d2c16b076cfc0b6d902b52754a55b013aa
Parents: ea37bb6
Author: Aled Sage <al...@gmail.com>
Authored: Wed Dec 16 20:44:44 2015 +0000
Committer: Aled Sage <al...@gmail.com>
Committed: Thu Dec 17 12:53:03 2015 +0000
----------------------------------------------------------------------
.../core/location/BasicLocationRegistry.java | 7 +-
.../internal/AbstractManagementContext.java | 4 +-
.../internal/DeferredBrooklynProperties.java | 370 +++++++++++++++++++
.../mgmt/internal/LocalManagementContext.java | 2 +-
.../location/byon/ByonLocationResolverTest.java | 4 +-
docs/guide/ops/brooklyn_properties.md | 23 ++
docs/guide/ops/externalized-configuration.md | 11 +
.../ExternalConfigBrooklynPropertiesTest.java | 146 ++++++++
.../camp/brooklyn/ExternalConfigYamlTest.java | 16 +
9 files changed, 577 insertions(+), 6 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f66a72d2/core/src/main/java/org/apache/brooklyn/core/location/BasicLocationRegistry.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/location/BasicLocationRegistry.java b/core/src/main/java/org/apache/brooklyn/core/location/BasicLocationRegistry.java
index 202ecf4..9e81382 100644
--- a/core/src/main/java/org/apache/brooklyn/core/location/BasicLocationRegistry.java
+++ b/core/src/main/java/org/apache/brooklyn/core/location/BasicLocationRegistry.java
@@ -45,6 +45,7 @@ import org.apache.brooklyn.core.config.ConfigPredicates;
import org.apache.brooklyn.core.config.ConfigUtils;
import org.apache.brooklyn.core.location.internal.LocationInternal;
import org.apache.brooklyn.core.mgmt.internal.LocalLocationManager;
+import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
import org.apache.brooklyn.core.typereg.RegisteredTypePredicates;
import org.apache.brooklyn.util.collections.MutableList;
import org.apache.brooklyn.util.collections.MutableMap;
@@ -494,6 +495,11 @@ public class BasicLocationRegistry implements LocationRegistry {
}
@VisibleForTesting
+ public void putProperties(Map<String, ?> vals) {
+ ((ManagementContextInternal)mgmt).getBrooklynProperties().putAll(vals);
+ }
+
+ @VisibleForTesting
public static void setupLocationRegistryForTesting(ManagementContext mgmt) {
// ensure localhost is added (even on windows)
LocationDefinition l = mgmt.getLocationRegistry().getDefinedLocationByName("localhost");
@@ -502,5 +508,4 @@ public class BasicLocationRegistry implements LocationRegistry {
((BasicLocationRegistry)mgmt.getLocationRegistry()).disablePersistence();
}
-
}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f66a72d2/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java
index cfa1d29..d41e059 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/AbstractManagementContext.java
@@ -151,7 +151,7 @@ public abstract class AbstractManagementContext implements ManagementContextInte
private final AtomicLong totalEffectorInvocationCount = new AtomicLong();
- protected BrooklynProperties configMap;
+ protected DeferredBrooklynProperties configMap;
protected BasicLocationRegistry locationRegistry;
protected final BasicBrooklynCatalog catalog;
protected final BrooklynTypeRegistry typeRegistry;
@@ -184,7 +184,7 @@ public abstract class AbstractManagementContext implements ManagementContextInte
}
public AbstractManagementContext(BrooklynProperties brooklynProperties, DataGridFactory datagridFactory) {
- this.configMap = brooklynProperties;
+ this.configMap = new DeferredBrooklynProperties(brooklynProperties, this);
this.entityDriverManager = new BasicEntityDriverManager();
this.downloadsManager = BasicDownloadsManager.newDefault(configMap);
if (datagridFactory == null) {
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f66a72d2/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/DeferredBrooklynProperties.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/DeferredBrooklynProperties.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/DeferredBrooklynProperties.java
new file mode 100644
index 0000000..ae0c7a5
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/DeferredBrooklynProperties.java
@@ -0,0 +1,370 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.core.mgmt.internal;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.io.File;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+
+import org.apache.brooklyn.api.mgmt.ExecutionContext;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.config.ConfigKey.HasConfigKey;
+import org.apache.brooklyn.core.internal.BrooklynProperties;
+import org.apache.brooklyn.util.core.config.ConfigBag;
+import org.apache.brooklyn.util.core.flags.TypeCoercions;
+import org.apache.brooklyn.util.core.task.DeferredSupplier;
+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;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Maps;
+
+/**
+ * Delegates to another {@link BrooklynProperties} implementation, but intercepts all calls to get.
+ * The results are transformed: if they are in the external-config format then they are
+ * automatically converted to {@link DeferredSupplier}.
+ *
+ * The external-config format is that same as that for camp-yaml blueprints (i.e.
+ * {@code $brooklyn:external("myprovider", "mykey")}.
+ */
+public class DeferredBrooklynProperties implements BrooklynProperties {
+
+ private static final Logger LOG = LoggerFactory.getLogger(DeferredBrooklynProperties.class);
+
+ private static final String BROOKLYN_YAML_PREFIX = "$brooklyn:";
+
+ private final BrooklynProperties delegate;
+ private final ManagementContextInternal mgmt;
+
+ public DeferredBrooklynProperties(BrooklynProperties delegate, ManagementContextInternal mgmt) {
+ this.delegate = checkNotNull(delegate, "delegate");
+ this.mgmt = checkNotNull(mgmt, "mgmt");
+ }
+
+ private Object transform(ConfigKey<?> key, Object value) {
+ if (value instanceof CharSequence) {
+ String raw = value.toString();
+ if (raw.startsWith(BROOKLYN_YAML_PREFIX)) {
+ CampYamlParser parser = mgmt.getConfig().getConfig(CampYamlParser.YAML_PARSER_KEY);
+ if (parser == null) {
+ // TODO Should we fail or return the untransformed value?
+ // Problem is this gets called during initialisation, e.g. by BrooklynFeatureEnablement calling asMapWithStringKeys()
+ // throw new IllegalStateException("Cannot parse external-config for "+key+" because no camp-yaml parser available");
+ LOG.debug("Not transforming external-config {}, as no camp-yaml parser available", key);
+ return value;
+ }
+ return parser.parse(raw);
+ }
+ }
+ return value;
+ }
+
+ private <T> T resolve(ConfigKey<T> key, Object value) {
+ Object transformed = transform(key, value);
+
+ Object result;
+ if (transformed instanceof DeferredSupplier) {
+ ExecutionContext exec = mgmt.getServerExecutionContext();
+ try {
+ result = Tasks.resolveValue(transformed, key.getType(), exec);
+ } catch (ExecutionException | InterruptedException e) {
+ throw Exceptions.propagate(e);
+ }
+ } else {
+ result = transformed;
+ }
+
+ return TypeCoercions.coerce(result, key.getTypeToken());
+ }
+
+ @Override
+ public <T> T getConfig(ConfigKey<T> key) {
+ T raw = delegate.getConfig(key);
+ return resolve(key, raw);
+ }
+
+ @Override
+ public <T> T getConfig(HasConfigKey<T> key) {
+ T raw = delegate.getConfig(key);
+ return resolve(key.getConfigKey(), raw);
+ }
+
+ @Override
+ public <T> T getConfig(HasConfigKey<T> key, T defaultValue) {
+ T raw = delegate.getConfig(key, defaultValue);
+ return resolve(key.getConfigKey(), raw);
+ }
+
+ @Override
+ public <T> T getConfig(ConfigKey<T> key, T defaultValue) {
+ T raw = delegate.getConfig(key, defaultValue);
+ return resolve(key, raw);
+ }
+
+ @Deprecated
+ @Override
+ public Object getRawConfig(ConfigKey<?> key) {
+ return transform(key, delegate.getRawConfig(key));
+ }
+
+ @Override
+ public Maybe<Object> getConfigRaw(ConfigKey<?> key, boolean includeInherited) {
+ Maybe<Object> result = delegate.getConfigRaw(key, includeInherited);
+ return (result.isPresent()) ? Maybe.of(transform(key, result.get())) : Maybe.absent();
+ }
+
+ @Override
+ public Map<ConfigKey<?>, Object> getAllConfig() {
+ Map<ConfigKey<?>, Object> raw = delegate.getAllConfig();
+ Map<ConfigKey<?>, Object> result = Maps.newLinkedHashMap();
+ for (Map.Entry<ConfigKey<?>, Object> entry : raw.entrySet()) {
+ result.put(entry.getKey(), transform(entry.getKey(), entry.getValue()));
+ }
+ return result;
+ }
+
+ @Override
+ public Map<String, Object> asMapWithStringKeys() {
+ Map<ConfigKey<?>, Object> raw = delegate.getAllConfig();
+ Map<String, Object> result = Maps.newLinkedHashMap();
+ for (Map.Entry<ConfigKey<?>, Object> entry : raw.entrySet()) {
+ result.put(entry.getKey().getName(), transform(entry.getKey(), entry.getValue()));
+ }
+ return result;
+ }
+
+ /**
+ * Discouraged; returns the String so if it is external config, it will be the
+ * {@code $brooklyn:external(...)} format.
+ */
+ @Override
+ @SuppressWarnings("rawtypes")
+ @Deprecated
+ public String get(Map flags, String key) {
+ return delegate.get(flags, key);
+ }
+
+ /**
+ * Discouraged; returns the String so if it is external config, it will be the
+ * {@code $brooklyn:external(...)} format.
+ */
+ @Override
+ public String getFirst(String ...keys) {
+ return delegate.getFirst(keys);
+ }
+
+ /**
+ * Discouraged; returns the String so if it is external config, it will be the
+ * {@code $brooklyn:external(...)} format.
+ */
+ @Override
+ @SuppressWarnings("rawtypes")
+ public String getFirst(Map flags, String ...keys) {
+ return delegate.getFirst(flags, keys);
+ }
+
+ @Override
+ public BrooklynProperties submap(Predicate<ConfigKey<?>> filter) {
+ BrooklynProperties submap = delegate.submap(filter);
+ return new DeferredBrooklynProperties(submap, mgmt);
+ }
+
+ @Override
+ public BrooklynProperties addEnvironmentVars() {
+ delegate.addEnvironmentVars();
+ return this;
+ }
+
+ @Override
+ public BrooklynProperties addSystemProperties() {
+ delegate.addSystemProperties();
+ return this;
+ }
+
+ @Override
+ public BrooklynProperties addFrom(ConfigBag cfg) {
+ delegate.addFrom(cfg);
+ return this;
+ }
+
+ @Override
+ @SuppressWarnings("rawtypes")
+ public BrooklynProperties addFrom(Map map) {
+ delegate.addFrom(map);
+ return this;
+ }
+
+ @Override
+ public BrooklynProperties addFrom(InputStream i) {
+ delegate.addFrom(i);
+ return this;
+ }
+
+ @Override
+ public BrooklynProperties addFrom(File f) {
+ delegate.addFrom(f);
+ return this;
+ }
+
+ @Override
+ public BrooklynProperties addFrom(URL u) {
+ delegate.addFrom(u);
+ return this;
+ }
+
+ @Override
+ public BrooklynProperties addFromUrl(String url) {
+ delegate.addFromUrl(url);
+ return this;
+ }
+
+ @Override
+ public BrooklynProperties addFromUrlProperty(String urlProperty) {
+ delegate.addFromUrlProperty(urlProperty);
+ return this;
+ }
+
+ @Override
+ @SuppressWarnings("rawtypes")
+ public BrooklynProperties addFromMap(Map properties) {
+ delegate.addFromMap(properties);
+ return this;
+ }
+
+ @Override
+ public boolean putIfAbsent(String key, Object value) {
+ return delegate.putIfAbsent(key, value);
+ }
+
+ @Override
+ public String toString() {
+ return delegate.toString();
+ }
+
+ @Override
+ public Object put(Object key, Object value) {
+ return delegate.put(key, value);
+ }
+
+ @Override
+ @SuppressWarnings("rawtypes")
+ public void putAll(Map vals) {
+ delegate.putAll(vals);
+ }
+
+ @Override
+ public <T> Object put(HasConfigKey<T> key, T value) {
+ return delegate.put(key, value);
+ }
+
+ @Override
+ public <T> Object put(ConfigKey<T> key, T value) {
+ return delegate.put(key, value);
+ }
+
+ @Override
+ public <T> boolean putIfAbsent(ConfigKey<T> key, T value) {
+ return delegate.putIfAbsent(key, value);
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////////////
+ // Methods below from java.util.LinkedHashMap, which BrooklynProperties extends //
+ //////////////////////////////////////////////////////////////////////////////////
+
+ @Override
+ public int size() {
+ return delegate.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return delegate.isEmpty();
+ }
+
+ @Override
+ public boolean containsKey(Object key) {
+ return delegate.containsKey(key);
+ }
+
+ @Override
+ public boolean containsValue(Object value) {
+ return delegate.containsValue(value);
+ }
+
+ @Override
+ public Object get(Object key) {
+ return delegate.get(key);
+ }
+
+ @Override
+ public Object remove(Object key) {
+ return delegate.remove(key);
+ }
+
+ @Override
+ public void clear() {
+ delegate.clear();
+ }
+
+ @Override
+ @SuppressWarnings("rawtypes")
+ public Set keySet() {
+ return delegate.keySet();
+ }
+
+ @Override
+ @SuppressWarnings("rawtypes")
+ public Collection values() {
+ return delegate.values();
+ }
+
+ @Override
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ public Set<Map.Entry> entrySet() {
+ return delegate.entrySet();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return delegate.equals(o);
+ }
+
+ @Override
+ public int hashCode() {
+ return delegate.hashCode();
+ }
+
+ // put(Object, Object) already overridden
+ //@Override
+ //public Object put(Object key, Object value) {
+
+ // putAll(Map) already overridden
+ //@Override
+ //public void putAll(Map m) {
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f66a72d2/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalManagementContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalManagementContext.java b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalManagementContext.java
index f464d3b..d88a500 100644
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalManagementContext.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/internal/LocalManagementContext.java
@@ -380,7 +380,7 @@ public class LocalManagementContext extends AbstractManagementContext {
log.warn("When reloading, mgmt context "+this+" properties are fixed, so reload will be of limited utility");
BrooklynProperties properties = builder.build();
- configMap = properties;
+ configMap = new DeferredBrooklynProperties(properties, this);
if (brooklynAdditionalProperties != null) {
log.info("Reloading additional brooklyn properties from " + brooklynAdditionalProperties);
configMap.addFromMap(brooklynAdditionalProperties);
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f66a72d2/core/src/test/java/org/apache/brooklyn/location/byon/ByonLocationResolverTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/location/byon/ByonLocationResolverTest.java b/core/src/test/java/org/apache/brooklyn/location/byon/ByonLocationResolverTest.java
index edc374d..675125f 100644
--- a/core/src/test/java/org/apache/brooklyn/location/byon/ByonLocationResolverTest.java
+++ b/core/src/test/java/org/apache/brooklyn/location/byon/ByonLocationResolverTest.java
@@ -243,7 +243,7 @@ public class ByonLocationResolverTest {
@Test
public void testResolvesUserArg3() throws Exception {
String spec = "byon(hosts=\"1.1.1.1\")";
- managementContext.getLocationRegistry().getProperties().putAll(MutableMap.of(
+ ((BasicLocationRegistry)managementContext.getLocationRegistry()).putProperties(MutableMap.of(
"brooklyn.location.named.foo", spec,
"brooklyn.location.named.foo.user", "bob"));
((BasicLocationRegistry)managementContext.getLocationRegistry()).updateDefinedLocations();
@@ -267,7 +267,7 @@ public class ByonLocationResolverTest {
/** private key should be inherited, so confirm that happens correctly */
public void testResolvesPrivateKeyArgInheritance() throws Exception {
String spec = "byon(hosts=\"1.1.1.1\")";
- managementContext.getLocationRegistry().getProperties().putAll(MutableMap.of(
+ ((BasicLocationRegistry)managementContext.getLocationRegistry()).putProperties(MutableMap.of(
"brooklyn.location.named.foo", spec,
"brooklyn.location.named.foo.user", "bob",
"brooklyn.location.named.foo.privateKeyFile", "/tmp/x"));
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f66a72d2/docs/guide/ops/brooklyn_properties.md
----------------------------------------------------------------------
diff --git a/docs/guide/ops/brooklyn_properties.md b/docs/guide/ops/brooklyn_properties.md
index cb00ceb..e8335f1 100644
--- a/docs/guide/ops/brooklyn_properties.md
+++ b/docs/guide/ops/brooklyn_properties.md
@@ -52,6 +52,28 @@ brooklyn.webconsole.security.https.required=true
More information, including setting up a certificate, is described [further below](#https-configuration).
+## Camp YAML Expressions
+
+Values in `brooklyn.properties` can use the Camp YAML syntax. Any value starting `$brooklyn:` is
+parsed as a Camp YAML expression.
+
+This allows [externalized configuration](externalized-configuration.html) to be used from
+brooklyn.properties. For example:
+
+{% highlight properties %}
+brooklyn.location.jclouds.aws-ec2.identity=$brooklyn:external("vault", "aws-identity")
+brooklyn.location.jclouds.aws-ec2.credential=$brooklyn:external("vault", "aws-credential")
+{% endhighlight %}
+
+If for some reason one requires a literal value that really does start with `$brooklyn:` (i.e.
+for the value to not be parsed), then this can be achieved by using the syntax below. This
+example returns the property value `$brooklyn:myexample`:
+
+{% highlight properties %}
+example.property=$brooklyn:literal("$brooklyn:myexample")
+{% endhighlight %}
+
+
## Locations
Information on defining locations in the `brooklyn.properties` file is available [here](locations/).
@@ -83,6 +105,7 @@ brooklyn.webconsole.security.user.admin.sha256=91e16f94509fa8e3dd21c43d69cadfd7d
The `users` line should contain a comma-separated list. The special value `*` is accepted to permit all users.
To generate this, the brooklyn CLI can be used:
+
{% highlight bash %}
brooklyn generate-password --user admin
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f66a72d2/docs/guide/ops/externalized-configuration.md
----------------------------------------------------------------------
diff --git a/docs/guide/ops/externalized-configuration.md b/docs/guide/ops/externalized-configuration.md
index 3a80499..ea6c63c 100644
--- a/docs/guide/ops/externalized-configuration.md
+++ b/docs/guide/ops/externalized-configuration.md
@@ -111,6 +111,17 @@ brooklyn.config:
example: $brooklyn:formatString("%s", external("supplier", "key"))
{% endhighlight %}
+
+## Referring to External Configuration in brooklyn.properties
+
+The same blueprint language DSL can be used from `brooklyn.properties`. For example:
+
+{% highlight properties %}
+brooklyn.location.jclouds.aws-ec2.identity=$brooklyn:external("mysupplier", "aws-identity")
+brooklyn.location.jclouds.aws-ec2.credential=$brooklyn:external("mysupplier", "aws-credential")
+{% endhighlight %}
+
+
## Suppliers available with Brooklyn
Brooklyn ships with a number of external configuration suppliers ready to use.
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f66a72d2/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ExternalConfigBrooklynPropertiesTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ExternalConfigBrooklynPropertiesTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ExternalConfigBrooklynPropertiesTest.java
new file mode 100644
index 0000000..39b444d
--- /dev/null
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ExternalConfigBrooklynPropertiesTest.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.brooklyn.camp.brooklyn;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import org.apache.brooklyn.api.mgmt.ExecutionContext;
+import org.apache.brooklyn.camp.brooklyn.ExternalConfigYamlTest.MyExternalConfigSupplier;
+import org.apache.brooklyn.camp.brooklyn.ExternalConfigYamlTest.MyExternalConfigSupplierWithoutMapArg;
+import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.config.ConfigPredicates;
+import org.apache.brooklyn.core.internal.BrooklynProperties;
+import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext;
+import org.apache.brooklyn.core.mgmt.internal.ManagementContextInternal;
+import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
+import org.apache.brooklyn.location.jclouds.JcloudsLocation;
+import org.apache.brooklyn.test.Asserts;
+import org.apache.brooklyn.util.core.task.DeferredSupplier;
+import org.apache.brooklyn.util.core.task.Tasks;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableMap;
+
+@Test
+public class ExternalConfigBrooklynPropertiesTest extends AbstractYamlTest {
+
+ @Override
+ protected LocalManagementContext newTestManagementContext() {
+ BrooklynProperties props = BrooklynProperties.Factory.newEmpty();
+ props.put("brooklyn.external.myprovider", MyExternalConfigSupplier.class.getName());
+ props.put("brooklyn.external.myprovider.mykey", "myval");
+ props.put("brooklyn.external.myprovider.mykey2", "myval2");
+ props.put("brooklyn.external.myproviderWithoutMapArg", MyExternalConfigSupplierWithoutMapArg.class.getName());
+ props.put("myproperty", "$brooklyn:external(\"myprovider\", \"mykey\")");
+
+ return LocalManagementContextForTests.builder(true)
+ .useProperties(props)
+ .build();
+ }
+
+ // Yaml parsing support is more generic than just external-config.
+ // Test other parsing here, even though it's not directly related to external-config.
+ @Test
+ public void testYamlLiteralFromPropertiesInLocation() throws Exception {
+ ((ManagementContextInternal)mgmt()).getBrooklynProperties().put(
+ ConfigKeys.newStringConfigKey("myDynamicProperty"), "$brooklyn:literal(\"myliteral\")");
+
+ String val = mgmt().getConfig().getConfig(ConfigKeys.newStringConfigKey("myDynamicProperty"));
+ assertEquals(val, "myliteral");
+ }
+
+ @Test
+ public void testInvalidYamlExpression() throws Exception {
+ ((ManagementContextInternal)mgmt()).getBrooklynProperties().put(
+ ConfigKeys.newStringConfigKey("myInvalidExternal"), "$brooklyn:external");
+
+ try {
+ String val = mgmt().getConfig().getConfig(ConfigKeys.newStringConfigKey("myInvalidExternal"));
+ Asserts.shouldHaveFailedPreviously("val="+val);
+ } catch (IllegalArgumentException e) {
+ Asserts.expectedFailureContains(e, "Error evaluating node");
+ }
+ }
+
+ @Test
+ public void testExternalisedConfigFromPropertiesInLocation() throws Exception {
+ BrooklynProperties props = ((ManagementContextInternal)mgmt()).getBrooklynProperties();
+ props.put("brooklyn.location.jclouds.aws-ec2.identity", "$brooklyn:external(\"myprovider\", \"mykey\")");
+ props.put("brooklyn.location.jclouds.aws-ec2.credential", "$brooklyn:external(\"myprovider\", \"mykey2\")");
+
+ JcloudsLocation loc = (JcloudsLocation) mgmt().getLocationRegistry().resolve("jclouds:aws-ec2:us-east-1");
+ assertEquals(loc.getIdentity(), "myval");
+ assertEquals(loc.getCredential(), "myval2");
+ }
+
+ @Test
+ public void testExternalisedConfigInProperties() throws Exception {
+ runExternalisedConfigGetters("myproperty", "myval");
+ }
+
+ @Test
+ public void testExternalisedConfigInAddedStringProperty() throws Exception {
+ ((ManagementContextInternal)mgmt()).getBrooklynProperties().put(
+ "myDynamicProperty", "$brooklyn:external(\"myprovider\", \"mykey\")");
+ runExternalisedConfigGetters("myDynamicProperty", "myval");
+ }
+
+ @Test
+ public void testExternalisedConfigInAddedKeyProperty() throws Exception {
+ ((ManagementContextInternal)mgmt()).getBrooklynProperties().put(
+ ConfigKeys.newStringConfigKey("myDynamicProperty"), "$brooklyn:external(\"myprovider\", \"mykey\")");
+ runExternalisedConfigGetters("myDynamicProperty", "myval");
+ }
+
+ @Test
+ public void testExternalisedConfigInAddedMapProperty() throws Exception {
+ ((ManagementContextInternal)mgmt()).getBrooklynProperties().addFromMap(
+ ImmutableMap.of("myDynamicProperty", "$brooklyn:external(\"myprovider\", \"mykey\")"));
+ runExternalisedConfigGetters("myDynamicProperty", "myval");
+ }
+
+ protected void runExternalisedConfigGetters(String property, String expectedVal) throws Exception {
+ runExternalisedConfigGetters(((ManagementContextInternal)mgmt()).getBrooklynProperties(), property, expectedVal, true);
+ }
+
+ protected void runExternalisedConfigGetters(BrooklynProperties props, String property, String expectedVal, boolean testSubMap) throws Exception {
+ ExecutionContext exec = mgmt().getServerExecutionContext();
+
+ String val1 = props.getConfig(ConfigKeys.newStringConfigKey(property));
+ assertEquals(val1, expectedVal);
+
+ DeferredSupplier<?> val2 = (DeferredSupplier<?>) props.getRawConfig(ConfigKeys.newStringConfigKey(property));
+ assertEquals(Tasks.resolveValue(val2, String.class, exec), expectedVal);
+
+ DeferredSupplier<?> val3 = (DeferredSupplier<?>) props.getConfigRaw(ConfigKeys.newStringConfigKey(property), false).get();
+ assertEquals(Tasks.resolveValue(val3, String.class, exec), expectedVal);
+
+ DeferredSupplier<?> val4 = (DeferredSupplier<?>) props.getAllConfig().get(ConfigKeys.newStringConfigKey(property));
+ assertEquals(Tasks.resolveValue(val4, String.class, exec), expectedVal);
+
+ String val5 = props.getFirst(property);
+ assertTrue(val5.startsWith("$brooklyn:external"), "val="+val5);
+
+ if (testSubMap) {
+ BrooklynProperties submap = props.submap(ConfigPredicates.nameEqualTo(property));
+ runExternalisedConfigGetters(submap, property, expectedVal, false);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/f66a72d2/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ExternalConfigYamlTest.java
----------------------------------------------------------------------
diff --git a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ExternalConfigYamlTest.java b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ExternalConfigYamlTest.java
index e075080..210f158 100644
--- a/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ExternalConfigYamlTest.java
+++ b/usage/camp/src/test/java/org/apache/brooklyn/camp/brooklyn/ExternalConfigYamlTest.java
@@ -26,17 +26,22 @@ import java.util.Map;
import com.google.common.collect.Iterables;
import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.mgmt.ExecutionContext;
import org.apache.brooklyn.api.mgmt.ManagementContext;
import org.apache.brooklyn.config.ConfigKey;
import org.apache.brooklyn.core.config.ConfigKeys;
import org.apache.brooklyn.core.config.external.AbstractExternalConfigSupplier;
import org.apache.brooklyn.core.config.external.ExternalConfigSupplier;
import org.apache.brooklyn.core.internal.BrooklynProperties;
+import org.apache.brooklyn.core.location.AbstractLocation;
import org.apache.brooklyn.core.location.cloud.CloudLocationConfig;
+import org.apache.brooklyn.core.mgmt.internal.CampYamlParser;
import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext;
import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
import org.apache.brooklyn.core.test.entity.TestApplication;
import org.apache.brooklyn.entity.software.base.EmptySoftwareProcess;
+import org.apache.brooklyn.util.core.task.DeferredSupplier;
+import org.apache.brooklyn.util.core.task.Tasks;
import org.apache.brooklyn.util.exceptions.Exceptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -61,6 +66,17 @@ public class ExternalConfigYamlTest extends AbstractYamlTest {
}
@Test
+ public void testCampYamlParserHandlesExternalisedConfig() throws Exception {
+ CampYamlParser parser = mgmt().getConfig().getConfig(CampYamlParser.YAML_PARSER_KEY);
+
+ DeferredSupplier<?> supplier = (DeferredSupplier<?>) parser.parse("$brooklyn:external(\"myprovider\", \"mykey\")");
+
+ ExecutionContext exec = mgmt().getServerExecutionContext();
+ String result = Tasks.resolveValue(supplier, String.class, exec);
+ assertEquals(result, "myval");
+ }
+
+ @Test
public void testExternalisedConfigReferencedFromYaml() throws Exception {
ConfigKey<String> MY_CONFIG_KEY = ConfigKeys.newStringConfigKey("my.config.key");