You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2016/08/25 12:10:36 UTC
[1/5] brooklyn-server git commit: Adds a target configuration to the
SSH command executing member tracker
Repository: brooklyn-server
Updated Branches:
refs/heads/master 434e26211 -> c57fb6004
Adds a target configuration to the SSH command executing member tracker
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/e8cce9bc
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/e8cce9bc
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/e8cce9bc
Branch: refs/heads/master
Commit: e8cce9bc7c0f6b86dec8feb1b5f57fac34f416c1
Parents: b73cb73
Author: Andrew Donald Kennedy <an...@cloudsoftcorp.com>
Authored: Fri Aug 19 12:23:06 2016 +0100
Committer: Andrew Donald Kennedy <an...@cloudsoftcorp.com>
Committed: Sat Aug 20 15:05:08 2016 +0100
----------------------------------------------------------------------
.../SshCommandMembershipTrackingPolicy.java | 73 ++++++++++++++++++--
1 file changed, 67 insertions(+), 6 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/e8cce9bc/core/src/main/java/org/apache/brooklyn/entity/group/SshCommandMembershipTrackingPolicy.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/entity/group/SshCommandMembershipTrackingPolicy.java b/core/src/main/java/org/apache/brooklyn/entity/group/SshCommandMembershipTrackingPolicy.java
index e7dffb5..662202b 100644
--- a/core/src/main/java/org/apache/brooklyn/entity/group/SshCommandMembershipTrackingPolicy.java
+++ b/core/src/main/java/org/apache/brooklyn/entity/group/SshCommandMembershipTrackingPolicy.java
@@ -26,6 +26,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.CaseFormat;
+import com.google.common.base.Converter;
+import com.google.common.base.Preconditions;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.location.Location;
@@ -54,6 +56,11 @@ import org.apache.brooklyn.util.text.Strings;
* Sets the environment variable {@code EVENT_TYPE} to the value of the {@link EventType}
* for the invocation, and {@code MEMBER_ID} to the ID of the entity that is being
* added, removed or updated.
+ * <p>
+ * The {@code execution.target} configuration specifies where the command will be
+ * executed. This can be one of: the {@link ExecutionTarget#ENTITY owing entity};
+ * the {@link ExecutionTarget#MEMBER member} that was updated; or
+ * {@link ExecutionTarget#ALL_MEMBERS all members} of the group.
*/
public class SshCommandMembershipTrackingPolicy extends AbstractMembershipTrackingPolicy {
@@ -62,6 +69,38 @@ public class SshCommandMembershipTrackingPolicy extends AbstractMembershipTracki
public static final String EVENT_TYPE = "EVENT_TYPE";
public static final String MEMBER_ID = "MEMBER_ID";
+ public static enum ExecutionTarget {
+ ENTITY,
+ MEMBER,
+ ALL_MEMBERS;
+
+ private static Converter<String, String> converter = CaseFormat.LOWER_CAMEL.converterTo(CaseFormat.UPPER_UNDERSCORE);
+
+ public static ExecutionTarget fromString(String name) {
+ Maybe<ExecutionTarget> parsed = tryFromString(name);
+ return parsed.get();
+ }
+
+ public static Maybe<ExecutionTarget> tryFromString(String name) {
+ try {
+ ExecutionTarget scope = valueOf(converter.convert(name));
+ return Maybe.of(scope);
+ } catch (Exception cause) {
+ return Maybe.absent(cause);
+ }
+ }
+
+ public static boolean isValid(String name) {
+ Maybe<ExecutionTarget> check = tryFromString(name);
+ return check.isPresentAndNonNull();
+ }
+
+ @Override
+ public String toString() {
+ return converter.reverse().convert(name());
+ }
+ }
+
public static final ConfigKey<String> EXECUTION_DIR = ConfigKeys.newStringConfigKey("executionDir", "Directory where the command should run; "
+ "if not supplied, executes in the entity's run dir (or home dir if no run dir is defined); "
+ "use '~' to always execute in the home dir, or 'custom-feed/' to execute in a custom-feed dir relative to the run dir");
@@ -70,28 +109,50 @@ public class SshCommandMembershipTrackingPolicy extends AbstractMembershipTracki
public static final ConfigKey<String> UPDATE_COMMAND = ConfigKeys.newStringConfigKey("update.command", "Command to run on membership change events");
+ public static final ConfigKey<ExecutionTarget> EXECUTION_TARGET = ConfigKeys.newConfigKey(ExecutionTarget.class,
+ "execution.target",
+ "Strategy for executing the command on different targets (default to the entity the policy is attached to)", ExecutionTarget.ENTITY);
+
/**
* Called when a member is updated or group membership changes.
*/
@Override
protected void onEntityEvent(EventType type, Entity member) {
LOG.trace("Event {} received for {} in {}", new Object[] { type, member, getGroup() });
- String command = config().get(UPDATE_COMMAND);
+ String command = Preconditions.checkNotNull(config().get(UPDATE_COMMAND));
+ ExecutionTarget where = Preconditions.checkNotNull(config().get(EXECUTION_TARGET));
+
if (Strings.isNonBlank(command)) {
- execute(command, type.name(), member.getId());
+ // Execute the command at the appropriate target entity
+ switch (where) {
+ case ENTITY:
+ execute(entity, command, type.name(), member.getId());
+ break;
+ case MEMBER:
+ execute(member, command, type.name(), member.getId());
+ break;
+ case ALL_MEMBERS:
+ for (Entity each : getGroup().getMembers()) {
+ execute(each, command, type.name(), member.getId());
+ }
+ break;
+ default:
+ LOG.warn("Unknown value passed as execution target: {}", where.name());
+ }
}
}
- public void execute(String command, String type, String memberId) {
- Collection<? extends Location> locations = Locations.getLocationsCheckingAncestors(entity.getLocations(), entity);
+ public void execute(Entity target, String command, String type, String memberId) {
+ Collection<? extends Location> locations = Locations.getLocationsCheckingAncestors(target.getLocations(), target);
Maybe<SshMachineLocation> machine = Machines.findUniqueMachineLocation(locations, SshMachineLocation.class);
if (machine.isAbsentOrNull()) {
LOG.debug("No machine available to execute command");
return;
}
+
LOG.info("Executing command on {}: {}", machine.get(), command);
String executionDir = config().get(EXECUTION_DIR);
- String sshCommand = SshCommandSensor.makeCommandExecutingInDirectory(command, executionDir, entity);
+ String sshCommand = SshCommandSensor.makeCommandExecutingInDirectory(command, executionDir, (EntityInternal) target);
// Set things from the entities defined shell environment, overriding with our config
Map<String, Object> env = MutableMap.of();
@@ -117,7 +178,7 @@ public class SshCommandMembershipTrackingPolicy extends AbstractMembershipTracki
.summary("group-" + CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_HYPHEN, type))
.environmentVariables(serializer.serialize(env));
- String output = DynamicTasks.submit(task.newTask(), entity).getUnchecked();
+ String output = DynamicTasks.submit(task.newTask(), target).getUnchecked();
LOG.trace("Command returned: {}", output);
}
}
[4/5] brooklyn-server git commit: This closes #304
Posted by he...@apache.org.
This closes #304
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/30cf2d2c
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/30cf2d2c
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/30cf2d2c
Branch: refs/heads/master
Commit: 30cf2d2c5da3671f1d92fc94219ca2e34a27ba52
Parents: 434e262 6e1a00e
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu Aug 25 09:14:53 2016 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Thu Aug 25 09:14:53 2016 +0100
----------------------------------------------------------------------
.../brooklyn/core/entity/AbstractEntity.java | 11 ++-
.../apache/brooklyn/core/entity/Attributes.java | 6 +-
.../stock/AbstractMultipleSensorAggregator.java | 14 ++--
.../brooklyn/enricher/stock/Enrichers.java | 64 +++++++++------
.../apache/brooklyn/enricher/stock/Joiner.java | 40 +++++++---
.../brooklyn/enricher/stock/MapAggregator.java | 83 ++++++++++++++++++++
.../SshCommandMembershipTrackingPolicy.java | 73 +++++++++++++++--
.../brooklyn/core/entity/EntityTypeTest.java | 19 +++--
.../brooklyn/enricher/stock/EnrichersTest.java | 40 ++++++++++
9 files changed, 292 insertions(+), 58 deletions(-)
----------------------------------------------------------------------
[2/5] brooklyn-server git commit: Update Aggregator and Joiner
entichers to handle Map sensors
Posted by he...@apache.org.
Update Aggregator and Joiner entichers to handle Map sensors
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/c58fe29e
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/c58fe29e
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/c58fe29e
Branch: refs/heads/master
Commit: c58fe29e3f44baf4e647aec1e3147edfbdddfd87
Parents: e8cce9b
Author: Andrew Donald Kennedy <an...@cloudsoftcorp.com>
Authored: Sat Aug 20 15:05:33 2016 +0100
Committer: Andrew Donald Kennedy <an...@cloudsoftcorp.com>
Committed: Sat Aug 20 17:09:12 2016 +0100
----------------------------------------------------------------------
.../stock/AbstractMultipleSensorAggregator.java | 14 ++--
.../brooklyn/enricher/stock/Enrichers.java | 64 +++++++++------
.../apache/brooklyn/enricher/stock/Joiner.java | 40 +++++++---
.../brooklyn/enricher/stock/MapAggregator.java | 83 ++++++++++++++++++++
.../brooklyn/enricher/stock/EnrichersTest.java | 40 ++++++++++
5 files changed, 199 insertions(+), 42 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/c58fe29e/core/src/main/java/org/apache/brooklyn/enricher/stock/AbstractMultipleSensorAggregator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/enricher/stock/AbstractMultipleSensorAggregator.java b/core/src/main/java/org/apache/brooklyn/enricher/stock/AbstractMultipleSensorAggregator.java
index e0f0d6d..c0cd36d 100644
--- a/core/src/main/java/org/apache/brooklyn/enricher/stock/AbstractMultipleSensorAggregator.java
+++ b/core/src/main/java/org/apache/brooklyn/enricher/stock/AbstractMultipleSensorAggregator.java
@@ -42,20 +42,19 @@ public abstract class AbstractMultipleSensorAggregator<U> extends AbstractAggreg
private static final Logger LOG = LoggerFactory.getLogger(AbstractMultipleSensorAggregator.class);
-
/** access via {@link #getValues(Sensor)} */
private final Map<String, Map<Entity,Object>> values = Collections.synchronizedMap(new LinkedHashMap<String, Map<Entity,Object>>());
- public AbstractMultipleSensorAggregator() {}
+ public AbstractMultipleSensorAggregator() { }
protected abstract Collection<Sensor<?>> getSourceSensors();
-
+
@Override
protected void setEntityLoadingConfig() {
super.setEntityLoadingConfig();
Preconditions.checkNotNull(getSourceSensors(), "sourceSensors must be set");
}
-
+
@Override
protected void setEntityBeforeSubscribingProducerChildrenEvents() {
BrooklynLogging.log(LOG, BrooklynLogging.levelDebugOrTraceIfReadOnly(producer),
@@ -95,7 +94,7 @@ public abstract class AbstractMultipleSensorAggregator<U> extends AbstractAggreg
vs = new LinkedHashMap<Entity,Object>();
values.put(sensor.getName(), vs);
}
-
+
Object vo = vs.get(producer);
if (vo==null) {
Object initialVal;
@@ -107,11 +106,10 @@ public abstract class AbstractMultipleSensorAggregator<U> extends AbstractAggreg
vs.put(producer, initialVal != null ? initialVal : defaultMemberValue);
// NB: see notes on possible race, in Aggregator#onProducerAdded
}
-
}
}
}
-
+
@Override
protected void onProducerRemoved(Entity producer) {
synchronized (values) {
@@ -163,7 +161,7 @@ public abstract class AbstractMultipleSensorAggregator<U> extends AbstractAggreg
return MutableMap.copyOf(sv).asUnmodifiable();
}
}
-
+
@Override
protected abstract Object compute();
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/c58fe29e/core/src/main/java/org/apache/brooklyn/enricher/stock/Enrichers.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/enricher/stock/Enrichers.java b/core/src/main/java/org/apache/brooklyn/enricher/stock/Enrichers.java
index 3dfabcf..973933c 100644
--- a/core/src/main/java/org/apache/brooklyn/enricher/stock/Enrichers.java
+++ b/core/src/main/java/org/apache/brooklyn/enricher/stock/Enrichers.java
@@ -161,7 +161,11 @@ public class Enrichers {
}
/** as {@link #combining(Collection)} but the collection of values comes from the given sensor on multiple entities */
public <S> AggregatorBuilder<S, Object> aggregating(AttributeSensor<S> val) {
- return new AggregatorBuilder<S,Object>(val);
+ return new AggregatorBuilder<S, Object>(val);
+ }
+ /** as {@link #combining(Collection)} but the collection of values comes from the given sensor on multiple entities */
+ public <S> AggregatorBuilder<S, Object> aggregating(AttributeSensor<S> keySensor, AttributeSensor<S> valueSensor) {
+ return new AggregatorBuilder<S, Object>(keySensor, valueSensor);
}
/** creates an {@link UpdatingMap} enricher:
* {@link UpdatingMapBuilder#from(AttributeSensor)} and {@link UpdatingMapBuilder#computing(Function)} are required
@@ -182,13 +186,15 @@ public class Enrichers {
protected abstract static class AbstractAggregatorBuilder<S, T, B extends AbstractAggregatorBuilder<S, T, B>> extends AbstractEnricherBuilder<B> {
- protected final AttributeSensor<S> aggregating;
+ protected AttributeSensor<S> aggregating;
+ protected AttributeSensor<S> keySensor;
+ protected AttributeSensor<S> valueSensor;
protected AttributeSensor<T> publishing;
protected Entity fromEntity;
/** @deprecated since 0.7.0, kept for backwards compatibility for rebind, but not used otherwise */
@Deprecated protected Function<? super Collection<S>, ? extends T> computing;
// use supplier so latest values of other fields can be used
- protected Supplier<Function<? super Collection<S>, ? extends T>> computingSupplier;
+ protected Supplier<Function<? super Collection<S>, ? extends T>> computingSupplier = Suppliers.ofInstance(null);
protected Boolean fromMembers;
protected Boolean fromChildren;
protected Boolean excludingBlank;
@@ -197,11 +203,16 @@ public class Enrichers {
protected Predicate<Object> valueFilter;
protected Object defaultValueForUnreportedSensors;
protected Object valueToReportIfNoSensors;
-
+
public AbstractAggregatorBuilder(AttributeSensor<S> aggregating) {
super(Aggregator.class);
this.aggregating = aggregating;
}
+ public AbstractAggregatorBuilder(AttributeSensor<S> keySensor, AttributeSensor<S> valueSensor) {
+ super(MapAggregator.class);
+ this.keySensor = keySensor;
+ this.valueSensor = valueSensor;
+ }
@SuppressWarnings({ "unchecked", "rawtypes" })
public <T2 extends T> AggregatorBuilder<S,T2> publishing(AttributeSensor<? extends T2> val) {
this.publishing = (AttributeSensor) checkNotNull(val);
@@ -259,7 +270,6 @@ public class Enrichers {
};
return self();
}
-
public B computingAverage() {
this.computingSupplier = new Supplier<Function<? super Collection<S>, ? extends T>>() {
@Override
@@ -283,6 +293,10 @@ public class Enrichers {
this.entityFilter = val;
return self();
}
+ public B valueFilter(Predicate<Object> val) {
+ this.valueFilter = val;
+ return self();
+ }
public B excludingBlank() {
this.excludingBlank = true;
return self();
@@ -293,42 +307,33 @@ public class Enrichers {
return "aggregator:"+publishing.getName();
}
public EnricherSpec<?> build() {
- Predicate<Object> valueFilter;
- if (Boolean.TRUE.equals(excludingBlank)) {
- valueFilter = new Predicate<Object>() {
- @Override public boolean apply(Object input) {
- return (input != null) &&
- ((input instanceof CharSequence) ? Strings.isNonBlank((CharSequence)input) : true);
- }
- };
- // above kept for deserialization; not sure necessary
- valueFilter = StringPredicates.isNonBlank();
- } else {
- valueFilter = null;
- }
- // FIXME excludingBlank; use valueFilter? exclude means ignored entirely or substituted for defaultMemberValue?
return super.build().configure(MutableMap.builder()
.putIfNotNull(Aggregator.PRODUCER, fromEntity)
.put(Aggregator.TARGET_SENSOR, publishing)
- .put(Aggregator.SOURCE_SENSOR, aggregating)
+ .putIfNotNull(Aggregator.SOURCE_SENSOR, aggregating)
+ .putIfNotNull(MapAggregator.KEY_SENSOR, keySensor)
+ .putIfNotNull(MapAggregator.VALUE_SENSOR, valueSensor)
.putIfNotNull(Aggregator.FROM_CHILDREN, fromChildren)
.putIfNotNull(Aggregator.FROM_MEMBERS, fromMembers)
.putIfNotNull(Aggregator.TRANSFORMATION, computingSupplier.get())
.putIfNotNull(Aggregator.FROM_HARDCODED_PRODUCERS, fromHardcodedProducers)
+ .putIfNotNull(Aggregator.EXCLUDE_BLANK, excludingBlank)
.putIfNotNull(Aggregator.ENTITY_FILTER, entityFilter)
.putIfNotNull(Aggregator.VALUE_FILTER, valueFilter)
.putIfNotNull(Aggregator.DEFAULT_MEMBER_VALUE, defaultValueForUnreportedSensors)
.build());
}
-
+
@Override
public String toString() {
return Objects.toStringHelper(this)
.omitNullValues()
.add("aggregating", aggregating)
+ .add("keySensor", keySensor)
+ .add("valueSensor", valueSensor)
.add("publishing", publishing)
.add("fromEntity", fromEntity)
- .add("computing", computingSupplier)
+ .add("computing", computingSupplier.get())
.add("fromMembers", fromMembers)
.add("fromChildren", fromChildren)
.add("excludingBlank", excludingBlank)
@@ -638,6 +643,8 @@ public class Enrichers {
protected AttributeSensor<String> publishing;
protected Entity fromEntity;
protected String separator;
+ protected String keyValueSeparator;
+ protected Boolean joinMapEntries;
protected Boolean quote;
protected Integer minimum;
protected Integer maximum;
@@ -654,6 +661,14 @@ public class Enrichers {
this.separator = separator;
return self();
}
+ public B keyValueSeparator(String keyValueSeparator) {
+ this.keyValueSeparator = keyValueSeparator;
+ return self();
+ }
+ public B joinMapEntries(Boolean joinMapEntries) {
+ this.joinMapEntries = joinMapEntries;
+ return self();
+ }
public B quote(Boolean quote) {
this.quote = quote;
return self();
@@ -677,6 +692,8 @@ public class Enrichers {
.put(Joiner.TARGET_SENSOR, publishing)
.put(Joiner.SOURCE_SENSOR, transforming)
.putIfNotNull(Joiner.SEPARATOR, separator)
+ .putIfNotNull(Joiner.KEY_VALUE_SEPARATOR, keyValueSeparator)
+ .putIfNotNull(Joiner.JOIN_MAP_ENTRIES, joinMapEntries)
.putIfNotNull(Joiner.QUOTE, quote)
.putIfNotNull(Joiner.MINIMUM, minimum)
.putIfNotNull(Joiner.MAXIMUM, maximum)
@@ -757,6 +774,9 @@ public class Enrichers {
public AggregatorBuilder(AttributeSensor<S> aggregating) {
super(aggregating);
}
+ public AggregatorBuilder(AttributeSensor<S> keySensor, AttributeSensor<S> valueSensor) {
+ super(keySensor, valueSensor);
+ }
}
public static class PropagatorBuilder extends AbstractPropagatorBuilder<PropagatorBuilder> {
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/c58fe29e/core/src/main/java/org/apache/brooklyn/enricher/stock/Joiner.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/enricher/stock/Joiner.java b/core/src/main/java/org/apache/brooklyn/enricher/stock/Joiner.java
index 2e24676..02654bc 100644
--- a/core/src/main/java/org/apache/brooklyn/enricher/stock/Joiner.java
+++ b/core/src/main/java/org/apache/brooklyn/enricher/stock/Joiner.java
@@ -50,6 +50,10 @@ public class Joiner<T> extends AbstractEnricher implements SensorEventListener<T
public static ConfigKey<Sensor<?>> TARGET_SENSOR = ConfigKeys.newConfigKey(new TypeToken<Sensor<?>>() {}, "enricher.targetSensor");
@SetFromFlag("separator")
public static ConfigKey<String> SEPARATOR = ConfigKeys.newStringConfigKey("enricher.joiner.separator", "Separator string to insert between each argument", ",");
+ @SetFromFlag("keyValueSeparator")
+ public static ConfigKey<String> KEY_VALUE_SEPARATOR = ConfigKeys.newStringConfigKey("enricher.joiner.keyValueSeparator", "Separator string to insert between each key-value pair", "=");
+ @SetFromFlag("joinMapEntries")
+ public static ConfigKey<Boolean> JOIN_MAP_ENTRIES = ConfigKeys.newBooleanConfigKey("enricher.joiner.joinMapEntries", "Whether to add map entries as key-value pairs or just use the value, defaulting to false", false);
@SetFromFlag("quote")
public static ConfigKey<Boolean> QUOTE = ConfigKeys.newBooleanConfigKey("enricher.joiner.quote", "Whether to bash-escape each parameter and wrap in double-quotes, defaulting to true", true);
@SetFromFlag("minimum")
@@ -72,12 +76,12 @@ public class Joiner<T> extends AbstractEnricher implements SensorEventListener<T
this.producer = getConfig(PRODUCER) == null ? entity: getConfig(PRODUCER);
this.sourceSensor = (AttributeSensor<T>) getRequiredConfig(SOURCE_SENSOR);
this.targetSensor = (Sensor<String>) getRequiredConfig(TARGET_SENSOR);
-
+
subscriptions().subscribe(producer, sourceSensor, this);
-
- Object value = producer.getAttribute((AttributeSensor<?>)sourceSensor);
+
+ Object value = producer.getAttribute((AttributeSensor<?>) sourceSensor);
// TODO would be useful to have a convenience to "subscribeAndThenIfItIsAlreadySetRunItOnce"
- if (value!=null) {
+ if (value != null) {
onEvent(new BasicSensorEvent(sourceSensor, producer, value, -1));
}
}
@@ -92,36 +96,48 @@ public class Joiner<T> extends AbstractEnricher implements SensorEventListener<T
Object result = null;
if (v!=null) {
if (v instanceof Map) {
- v = ((Map<?,?>)v).values();
+ if (config().get(JOIN_MAP_ENTRIES)) {
+ v = ((Map<?,?>) v).entrySet();
+ } else {
+ v = ((Map<?,?>) v).values();
+ }
}
if (!(v instanceof Iterable)) {
LOG.warn("Enricher "+this+" received a non-iterable value "+v.getClass()+" "+v+"; refusing to join");
} else {
MutableList<Object> c1 = MutableList.of();
- Integer maximum = getConfig(MAXIMUM);
+ Integer maximum = config().get(MAXIMUM);
for (Object ci: (Iterable<?>)v) {
if (maximum!=null && maximum>=0) {
if (c1.size()>=maximum) break;
}
- c1.appendIfNotNull(Strings.toString(ci));
+ if (ci instanceof Map.Entry) {
+ String key = Strings.toString(((Map.Entry) ci).getKey());
+ Object value = ((Map.Entry) ci).getValue();
+ String keyValueSeparator = config().get(KEY_VALUE_SEPARATOR);
+ if (value != null) {
+ c1.append(String.format("%s%s%s", key, keyValueSeparator, Strings.toString(value)));
+ }
+ } else {
+ c1.appendIfNotNull(Strings.toString(ci));
+ }
}
- Integer minimum = getConfig(MINIMUM);
+ Integer minimum = config().get(MINIMUM);
if (minimum!=null && c1.size() < minimum) {
// use default null return value
} else {
- if (getConfig(QUOTE)) {
+ if (config().get(QUOTE)) {
MutableList<Object> c2 = MutableList.of();
for (Object ci: c1) {
c2.add(StringEscapes.BashStringEscapes.wrapBash((String)ci));
}
c1 = c2;
}
- result = Strings.join(c1, getConfig(SEPARATOR));
+ result = Strings.join(c1, config().get(SEPARATOR));
}
}
}
- if (LOG.isTraceEnabled())
- LOG.trace("Enricher "+this+" computed "+result+" from "+event);
+ LOG.trace("Enricher "+this+" computed "+result+" from "+event);
return result;
}
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/c58fe29e/core/src/main/java/org/apache/brooklyn/enricher/stock/MapAggregator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/enricher/stock/MapAggregator.java b/core/src/main/java/org/apache/brooklyn/enricher/stock/MapAggregator.java
new file mode 100644
index 0000000..af1cf20
--- /dev/null
+++ b/core/src/main/java/org/apache/brooklyn/enricher/stock/MapAggregator.java
@@ -0,0 +1,83 @@
+/*
+ * 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.enricher.stock;
+
+import java.util.Collection;
+import java.util.Map;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Maps;
+import com.google.common.reflect.TypeToken;
+
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.sensor.Sensor;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.text.StringPredicates;
+
+/**
+ * Building on {@link AbstractMultipleSensorAggregator} for a pair of source sensors(on multiple children and/or members)
+ * that are used as key-value pairs in a generated Map.
+ */
+@SuppressWarnings("serial")
+public class MapAggregator<U> extends AbstractMultipleSensorAggregator<U> {
+
+ public static final ConfigKey<Sensor<?>> KEY_SENSOR = ConfigKeys.newConfigKey(new TypeToken<Sensor<?>>() {}, "enricher.keySensor");
+ public static final ConfigKey<Sensor<?>> VALUE_SENSOR = ConfigKeys.newConfigKey(new TypeToken<Sensor<?>>() {}, "enricher.valueSensor");
+
+ public static final ConfigKey<Boolean> EXCLUDE_BLANK = Aggregator.EXCLUDE_BLANK;
+
+ private Sensor<?> keySensor;
+ private Sensor<?> valueSensor;
+
+ public MapAggregator() { }
+
+ @Override
+ protected Predicate<?> getDefaultValueFilter() {
+ if (config().get(EXCLUDE_BLANK)) {
+ return StringPredicates.isNonBlank();
+ } else {
+ return Predicates.alwaysTrue();
+ }
+ }
+
+ @Override
+ protected Object compute() {
+ Map<Entity, Object> ks = MutableMap.copyOf(Maps.filterValues(getValues(keySensor), valueFilter));
+ Map<Entity, Object> vs = MutableMap.copyOf(Maps.filterValues(getValues(valueSensor), valueFilter));
+ MutableMap<Object, Object> result = MutableMap.of();
+ for (Entity entity : ks.keySet()) {
+ if (vs.containsKey(entity)) {
+ result.put(ks.get(entity), vs.get(entity));
+ }
+ }
+ return result;
+ }
+
+ @Override
+ protected Collection<Sensor<?>> getSourceSensors() {
+ keySensor = config().get(KEY_SENSOR);
+ valueSensor = config().get(VALUE_SENSOR);
+ return ImmutableList.<Sensor<?>>of(keySensor, valueSensor);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/c58fe29e/core/src/test/java/org/apache/brooklyn/enricher/stock/EnrichersTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/enricher/stock/EnrichersTest.java b/core/src/test/java/org/apache/brooklyn/enricher/stock/EnrichersTest.java
index 6e5cc16..e20664b 100644
--- a/core/src/test/java/org/apache/brooklyn/enricher/stock/EnrichersTest.java
+++ b/core/src/test/java/org/apache/brooklyn/enricher/stock/EnrichersTest.java
@@ -393,6 +393,29 @@ public class EnrichersTest extends BrooklynAppUnitTestSupport {
entity.sensors().set(NUM1, 987654);
EntityAsserts.assertAttributeEqualsContinually(group, LONG1, Long.valueOf(123));
}
+
+ @Test
+ public void testAggregatingMap() {
+ group.addMember(entity);
+ group.enrichers().add(Enrichers.builder()
+ .aggregating(STR1, STR2)
+ .publishing(MAP1)
+ .fromMembers()
+ .excludingBlank()
+ .build());
+
+ EntityAsserts.assertAttributeEqualsEventually(group, MAP1, ImmutableMap.<String, String>of());
+
+ entity.sensors().set(STR1, "a");
+ EntityAsserts.assertAttributeEqualsEventually(group, MAP1, ImmutableMap.<String, String>of());
+
+ entity.sensors().set(STR2, "b");
+ EntityAsserts.assertAttributeEqualsEventually(group, MAP1, ImmutableMap.<String, String>of("a", "b"));
+
+ entity.sensors().set(STR2, "c");
+ EntityAsserts.assertAttributeEqualsEventually(group, MAP1, ImmutableMap.<String, String>of("a", "c"));
+ }
+
@Test
public void testUpdatingMap1() {
entity.enrichers().add(Enrichers.builder()
@@ -429,6 +452,7 @@ public class EnrichersTest extends BrooklynAppUnitTestSupport {
}
private static AttributeSensor<Object> LIST_SENSOR = Sensors.newSensor(Object.class, "sensor.list");
+ private static AttributeSensor<Object> MAP_SENSOR = Sensors.newSensor(Object.class, "sensor.map");
@Test
public void testJoinerDefault() {
@@ -490,5 +514,21 @@ public class EnrichersTest extends BrooklynAppUnitTestSupport {
EntityAsserts.assertAttributeEqualsEventually(entity, TestEntity.NAME, "a,b,c,d");
}
+ @Test
+ public void testJoinerMap() {
+ entity.enrichers().add(Enrichers.builder()
+ .joining(MAP_SENSOR)
+ .keyValueSeparator("=")
+ .joinMapEntries(true)
+ .publishing(TestEntity.NAME)
+ .build());
+ // check quotes
+ entity.sensors().set(MAP_SENSOR, MutableMap.<String, String>of("a", "\"v", "b", "w x y"));
+ EntityAsserts.assertAttributeEqualsEventually(entity, TestEntity.NAME, "\"a=\\\"v\",\"b=w x y\"");
+
+ // empty map causes ""
+ entity.sensors().set(MAP_SENSOR, MutableMap.<String, String>of());
+ EntityAsserts.assertAttributeEqualsEventually(entity, TestEntity.NAME, "");
+ }
}
[3/5] brooklyn-server git commit: Add sensors for IDs to entity
Posted by he...@apache.org.
Add sensors for IDs to entity
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/6e1a00eb
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/6e1a00eb
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/6e1a00eb
Branch: refs/heads/master
Commit: 6e1a00eb44f195dbeea39eeb430584aa14702f16
Parents: c58fe29
Author: Andrew Donald Kennedy <an...@cloudsoftcorp.com>
Authored: Sat Aug 20 16:03:52 2016 +0100
Committer: Andrew Donald Kennedy <an...@cloudsoftcorp.com>
Committed: Sat Aug 20 17:09:13 2016 +0100
----------------------------------------------------------------------
.../brooklyn/core/entity/AbstractEntity.java | 11 +++++++++--
.../apache/brooklyn/core/entity/Attributes.java | 6 +++++-
.../brooklyn/core/entity/EntityTypeTest.java | 19 ++++++++++++-------
3 files changed, 26 insertions(+), 10 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/6e1a00eb/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java b/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
index 8836f0a..49c1967 100644
--- a/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
+++ b/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
@@ -196,7 +196,11 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
"entity.group.added", "Group dynamically added to entity");
public static final BasicNotificationSensor<Group> GROUP_REMOVED = new BasicNotificationSensor<Group>(Group.class,
"entity.group.removed", "Group dynamically removed from entity");
-
+
+ public static final AttributeSensor<String> ENTITY_ID = Attributes.ENTITY_ID;
+ public static final AttributeSensor<String> APPLICATION_ID = Attributes.APPLICATION_ID;
+ public static final AttributeSensor<String> CATALOG_ID = Attributes.CATALOG_ID;
+
static {
RendererHints.register(Entity.class, RendererHints.displayValue(EntityFunctions.displayName()));
}
@@ -1615,7 +1619,7 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
// -------- INITIALIZATION --------------
/**
- * Default entity initialization, just calls {@link #initEnrichers()}.
+ * Default entity initialization sets ID sensors and calls {@link #initEnrichers()}.
*/
public void init() {
super.init();
@@ -1623,6 +1627,9 @@ public abstract class AbstractEntity extends AbstractBrooklynObject implements E
if (Strings.isNonBlank(getConfig(DEFAULT_DISPLAY_NAME))) {
setDefaultDisplayName(getConfig(DEFAULT_DISPLAY_NAME));
}
+ sensors().set(ENTITY_ID, getId());
+ sensors().set(APPLICATION_ID, getApplicationId());
+ sensors().set(CATALOG_ID, getCatalogItemId());
}
/**
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/6e1a00eb/core/src/main/java/org/apache/brooklyn/core/entity/Attributes.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/Attributes.java b/core/src/main/java/org/apache/brooklyn/core/entity/Attributes.java
index 06fb7ab..a59c484 100644
--- a/core/src/main/java/org/apache/brooklyn/core/entity/Attributes.java
+++ b/core/src/main/java/org/apache/brooklyn/core/entity/Attributes.java
@@ -42,7 +42,11 @@ import com.google.common.reflect.TypeToken;
* This interface should be used to access {@link Sensor} definitions.
*/
public interface Attributes {
-
+
+ AttributeSensor<String> ENTITY_ID = Sensors.newStringSensor("entity.id");
+ AttributeSensor<String> APPLICATION_ID = Sensors.newStringSensor("application.id");
+ AttributeSensor<String> CATALOG_ID = Sensors.newStringSensor("catalog.id");
+
BasicNotificationSensor<Void> LOCATION_CHANGED = new BasicNotificationSensor<Void>(
Void.class, "entity.locationChanged", "Indicates that an entity's location has been changed");
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/6e1a00eb/core/src/test/java/org/apache/brooklyn/core/entity/EntityTypeTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/entity/EntityTypeTest.java b/core/src/test/java/org/apache/brooklyn/core/entity/EntityTypeTest.java
index c6e3936..aac3cca 100644
--- a/core/src/test/java/org/apache/brooklyn/core/entity/EntityTypeTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/entity/EntityTypeTest.java
@@ -18,6 +18,8 @@
*/
package org.apache.brooklyn.core.entity;
+import static org.apache.brooklyn.core.entity.AbstractEntity.APPLICATION_ID;
+import static org.apache.brooklyn.core.entity.AbstractEntity.CATALOG_ID;
import static org.apache.brooklyn.core.entity.AbstractEntity.CHILD_ADDED;
import static org.apache.brooklyn.core.entity.AbstractEntity.CHILD_REMOVED;
import static org.apache.brooklyn.core.entity.AbstractEntity.CONFIG_KEY_ADDED;
@@ -25,6 +27,7 @@ import static org.apache.brooklyn.core.entity.AbstractEntity.CONFIG_KEY_REMOVED;
import static org.apache.brooklyn.core.entity.AbstractEntity.EFFECTOR_ADDED;
import static org.apache.brooklyn.core.entity.AbstractEntity.EFFECTOR_CHANGED;
import static org.apache.brooklyn.core.entity.AbstractEntity.EFFECTOR_REMOVED;
+import static org.apache.brooklyn.core.entity.AbstractEntity.ENTITY_ID;
import static org.apache.brooklyn.core.entity.AbstractEntity.GROUP_ADDED;
import static org.apache.brooklyn.core.entity.AbstractEntity.GROUP_REMOVED;
import static org.apache.brooklyn.core.entity.AbstractEntity.LOCATION_ADDED;
@@ -44,6 +47,14 @@ import java.util.Set;
import javax.annotation.Nullable;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterables;
+
import org.apache.brooklyn.api.effector.Effector;
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.entity.EntitySpec;
@@ -58,13 +69,6 @@ import org.apache.brooklyn.core.test.entity.TestEntity;
import org.apache.brooklyn.core.test.entity.TestEntityImpl;
import org.apache.brooklyn.test.Asserts;
import org.apache.brooklyn.util.collections.MutableSet;
-import org.testng.annotations.BeforeMethod;
-import org.testng.annotations.Test;
-
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
public class EntityTypeTest extends BrooklynAppUnitTestSupport {
private static final AttributeSensor<String> TEST_SENSOR = Sensors.newStringSensor("test.sensor");
@@ -73,6 +77,7 @@ public class EntityTypeTest extends BrooklynAppUnitTestSupport {
private RecordingSensorEventListener<Sensor> listener;
public final static Set<Sensor<?>> DEFAULT_SENSORS = ImmutableSet.<Sensor<?>>of(
+ ENTITY_ID, APPLICATION_ID, CATALOG_ID,
SENSOR_ADDED, SENSOR_REMOVED,
CONFIG_KEY_ADDED, CONFIG_KEY_REMOVED,
EFFECTOR_ADDED, EFFECTOR_REMOVED, EFFECTOR_CHANGED,
[5/5] brooklyn-server git commit: address PR comments on #304
Posted by he...@apache.org.
address PR comments on #304
mainly with TODO comments,
also promoting the default value filter
(it has no effect on the one other use of AbstractAggregator,
in ComputeService... -- which didn't previously use EXCLUDE_BLANK)
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/c57fb600
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/c57fb600
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/c57fb600
Branch: refs/heads/master
Commit: c57fb6004aa096488675507bef2e05df8776a590
Parents: 30cf2d2
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu Aug 25 09:26:17 2016 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Thu Aug 25 09:26:17 2016 +0100
----------------------------------------------------------------------
.../enricher/stock/AbstractAggregator.java | 9 +++++++--
.../brooklyn/enricher/stock/Aggregator.java | 13 +-----------
.../apache/brooklyn/enricher/stock/Joiner.java | 1 +
.../brooklyn/enricher/stock/MapAggregator.java | 11 ----------
.../SshCommandMembershipTrackingPolicy.java | 21 ++++++++++++--------
5 files changed, 22 insertions(+), 33 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/c57fb600/core/src/main/java/org/apache/brooklyn/enricher/stock/AbstractAggregator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/enricher/stock/AbstractAggregator.java b/core/src/main/java/org/apache/brooklyn/enricher/stock/AbstractAggregator.java
index 1d9870d..5a36177 100644
--- a/core/src/main/java/org/apache/brooklyn/enricher/stock/AbstractAggregator.java
+++ b/core/src/main/java/org/apache/brooklyn/enricher/stock/AbstractAggregator.java
@@ -35,6 +35,7 @@ import org.apache.brooklyn.core.entity.AbstractEntity;
import org.apache.brooklyn.core.entity.trait.Changeable;
import org.apache.brooklyn.util.exceptions.Exceptions;
import org.apache.brooklyn.util.guava.Maybe;
+import org.apache.brooklyn.util.text.StringPredicates;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -67,6 +68,7 @@ public abstract class AbstractAggregator<T,U> extends AbstractEnricher implement
public static final ConfigKey<Predicate<? super Entity>> ENTITY_FILTER = ConfigKeys.newConfigKey(new TypeToken<Predicate<? super Entity>>() {}, "enricher.aggregating.entityFilter");
public static final ConfigKey<Predicate<?>> VALUE_FILTER = ConfigKeys.newConfigKey(new TypeToken<Predicate<?>>() {}, "enricher.aggregating.valueFilter");
+ public static final ConfigKey<Boolean> EXCLUDE_BLANK = Aggregator.EXCLUDE_BLANK;
protected Entity producer;
protected Sensor<U> targetSensor;
@@ -123,9 +125,12 @@ public abstract class AbstractAggregator<T,U> extends AbstractEnricher implement
}
protected Predicate<?> getDefaultValueFilter() {
- return Predicates.alwaysTrue();
+ if (getConfig(EXCLUDE_BLANK))
+ return StringPredicates.isNonBlank();
+ else
+ return Predicates.alwaysTrue();
}
-
+
@SuppressWarnings({ "unchecked" })
protected void setEntityLoadingTargetConfig() {
this.targetSensor = (Sensor<U>) getRequiredConfig(TARGET_SENSOR);
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/c57fb600/core/src/main/java/org/apache/brooklyn/enricher/stock/Aggregator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/enricher/stock/Aggregator.java b/core/src/main/java/org/apache/brooklyn/enricher/stock/Aggregator.java
index f9a0988..a21aec3 100644
--- a/core/src/main/java/org/apache/brooklyn/enricher/stock/Aggregator.java
+++ b/core/src/main/java/org/apache/brooklyn/enricher/stock/Aggregator.java
@@ -38,13 +38,10 @@ import org.apache.brooklyn.util.collections.MutableMap;
import org.apache.brooklyn.util.collections.QuorumCheck.QuorumChecks;
import org.apache.brooklyn.util.core.flags.SetFromFlag;
import org.apache.brooklyn.util.exceptions.Exceptions;
-import org.apache.brooklyn.util.text.StringPredicates;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import com.google.common.reflect.TypeToken;
@@ -63,7 +60,7 @@ public class Aggregator<T,U> extends AbstractAggregator<T,U> implements SensorEv
+ "such as 'average' (for numbers), 'sum' (for numbers), or 'list' (the default, putting any collection of items into a list)");
public static final ConfigKey<Function<? super Collection<?>, ?>> TRANSFORMATION = ConfigKeys.newConfigKey(new TypeToken<Function<? super Collection<?>, ?>>() {}, "enricher.transformation");
- public static final ConfigKey<Boolean> EXCLUDE_BLANK = ConfigKeys.newBooleanConfigKey("enricher.aggregator.excludeBlank", "Whether explicit nulls or blank strings should be excluded (default false); this only applies if no value filter set", false);
+ public static final ConfigKey<Boolean> EXCLUDE_BLANK = ConfigKeys.newBooleanConfigKey("enricher.aggregator.excludeBlank", "Whether explicit nulls or blank strings should be excluded (default false); may only apply if no value filter set", false);
/**
* @see QuorumChecks
@@ -176,14 +173,6 @@ public class Aggregator<T,U> extends AbstractAggregator<T,U> implements SensorEv
}
@Override
- protected Predicate<?> getDefaultValueFilter() {
- if (getConfig(EXCLUDE_BLANK))
- return StringPredicates.isNonBlank();
- else
- return Predicates.alwaysTrue();
- }
-
- @Override
protected void onProducerRemoved(Entity producer) {
values.remove(producer);
onUpdated();
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/c57fb600/core/src/main/java/org/apache/brooklyn/enricher/stock/Joiner.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/enricher/stock/Joiner.java b/core/src/main/java/org/apache/brooklyn/enricher/stock/Joiner.java
index 02654bc..175c1df 100644
--- a/core/src/main/java/org/apache/brooklyn/enricher/stock/Joiner.java
+++ b/core/src/main/java/org/apache/brooklyn/enricher/stock/Joiner.java
@@ -115,6 +115,7 @@ public class Joiner<T> extends AbstractEnricher implements SensorEventListener<T
String key = Strings.toString(((Map.Entry) ci).getKey());
Object value = ((Map.Entry) ci).getValue();
String keyValueSeparator = config().get(KEY_VALUE_SEPARATOR);
+ // TODO we might want to handle QUOTE=true specially for this case, to quote keys and values if needed
if (value != null) {
c1.append(String.format("%s%s%s", key, keyValueSeparator, Strings.toString(value)));
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/c57fb600/core/src/main/java/org/apache/brooklyn/enricher/stock/MapAggregator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/enricher/stock/MapAggregator.java b/core/src/main/java/org/apache/brooklyn/enricher/stock/MapAggregator.java
index af1cf20..d5f79d3 100644
--- a/core/src/main/java/org/apache/brooklyn/enricher/stock/MapAggregator.java
+++ b/core/src/main/java/org/apache/brooklyn/enricher/stock/MapAggregator.java
@@ -44,23 +44,12 @@ public class MapAggregator<U> extends AbstractMultipleSensorAggregator<U> {
public static final ConfigKey<Sensor<?>> KEY_SENSOR = ConfigKeys.newConfigKey(new TypeToken<Sensor<?>>() {}, "enricher.keySensor");
public static final ConfigKey<Sensor<?>> VALUE_SENSOR = ConfigKeys.newConfigKey(new TypeToken<Sensor<?>>() {}, "enricher.valueSensor");
- public static final ConfigKey<Boolean> EXCLUDE_BLANK = Aggregator.EXCLUDE_BLANK;
-
private Sensor<?> keySensor;
private Sensor<?> valueSensor;
public MapAggregator() { }
@Override
- protected Predicate<?> getDefaultValueFilter() {
- if (config().get(EXCLUDE_BLANK)) {
- return StringPredicates.isNonBlank();
- } else {
- return Predicates.alwaysTrue();
- }
- }
-
- @Override
protected Object compute() {
Map<Entity, Object> ks = MutableMap.copyOf(Maps.filterValues(getValues(keySensor), valueFilter));
Map<Entity, Object> vs = MutableMap.copyOf(Maps.filterValues(getValues(valueSensor), valueFilter));
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/c57fb600/core/src/main/java/org/apache/brooklyn/entity/group/SshCommandMembershipTrackingPolicy.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/entity/group/SshCommandMembershipTrackingPolicy.java b/core/src/main/java/org/apache/brooklyn/entity/group/SshCommandMembershipTrackingPolicy.java
index 662202b..432364c 100644
--- a/core/src/main/java/org/apache/brooklyn/entity/group/SshCommandMembershipTrackingPolicy.java
+++ b/core/src/main/java/org/apache/brooklyn/entity/group/SshCommandMembershipTrackingPolicy.java
@@ -22,13 +22,6 @@ import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ExecutionException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.CaseFormat;
-import com.google.common.base.Converter;
-import com.google.common.base.Preconditions;
-
import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.location.Location;
import org.apache.brooklyn.config.ConfigKey;
@@ -48,6 +41,13 @@ import org.apache.brooklyn.util.core.task.Tasks;
import org.apache.brooklyn.util.exceptions.Exceptions;
import org.apache.brooklyn.util.guava.Maybe;
import org.apache.brooklyn.util.text.Strings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.CaseFormat;
+import com.google.common.base.Converter;
+import com.google.common.base.Preconditions;
/**
* Policy which tracks membership of a group, and executes SSH commands
@@ -62,6 +62,10 @@ import org.apache.brooklyn.util.text.Strings;
* the {@link ExecutionTarget#MEMBER member} that was updated; or
* {@link ExecutionTarget#ALL_MEMBERS all members} of the group.
*/
+// TODO might make sense to split up behaviour into two classes,
+// an InvokeEffectorMembershipTrackingPolicy and an SshMultiEntityCommandEffector --
+// where the latter has the configurable target introduced here
+@Beta
public class SshCommandMembershipTrackingPolicy extends AbstractMembershipTrackingPolicy {
private static final Logger LOG = LoggerFactory.getLogger(SshCommandMembershipTrackingPolicy.class);
@@ -76,11 +80,11 @@ public class SshCommandMembershipTrackingPolicy extends AbstractMembershipTracki
private static Converter<String, String> converter = CaseFormat.LOWER_CAMEL.converterTo(CaseFormat.UPPER_UNDERSCORE);
+ // TODO these methods maybe not needed due to EnumTypeCoercions
public static ExecutionTarget fromString(String name) {
Maybe<ExecutionTarget> parsed = tryFromString(name);
return parsed.get();
}
-
public static Maybe<ExecutionTarget> tryFromString(String name) {
try {
ExecutionTarget scope = valueOf(converter.convert(name));
@@ -142,6 +146,7 @@ public class SshCommandMembershipTrackingPolicy extends AbstractMembershipTracki
}
}
+ @SuppressWarnings("unchecked")
public void execute(Entity target, String command, String type, String memberId) {
Collection<? extends Location> locations = Locations.getLocationsCheckingAncestors(target.getLocations(), target);
Maybe<SshMachineLocation> machine = Machines.findUniqueMachineLocation(locations, SshMachineLocation.class);