You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by tb...@apache.org on 2018/04/27 15:43:46 UTC
[1/3] brooklyn-server git commit: SshCommandSensor: no anonymous
inner classes
Repository: brooklyn-server
Updated Branches:
refs/heads/master cd40893d1 -> 7e2b497cb
SshCommandSensor: no anonymous inner classes
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/d4901150
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/d4901150
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/d4901150
Branch: refs/heads/master
Commit: d490115023b6c53d3a79b72f8ec190f14e5eb949
Parents: 3afc8fe
Author: Aled Sage <al...@gmail.com>
Authored: Thu Apr 26 20:57:33 2018 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Fri Apr 27 10:09:31 2018 +0100
----------------------------------------------------------------------
.../SshCommandSensorYamlRebindTest.java | 89 +++++++++++++
.../core/sensor/ssh/SshCommandSensor.java | 124 +++++++++++++++----
.../brooklyn/util/core/flags/TypeCoercions.java | 15 ++-
.../core/mgmt/rebind/RebindTestFixture.java | 33 ++++-
.../apache/brooklyn/util/guava/Functionals.java | 21 +++-
.../brooklyn/util/text/StringFunctions.java | 12 ++
6 files changed, 263 insertions(+), 31 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d4901150/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/SshCommandSensorYamlRebindTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/SshCommandSensorYamlRebindTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/SshCommandSensorYamlRebindTest.java
new file mode 100644
index 0000000..0c0730e
--- /dev/null
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/SshCommandSensorYamlRebindTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import org.apache.brooklyn.api.mgmt.rebind.mementos.BrooklynMementoRawData;
+import org.apache.brooklyn.core.entity.EntityAsserts;
+import org.apache.brooklyn.core.entity.EntityInternal;
+import org.apache.brooklyn.core.entity.StartableApplication;
+import org.apache.brooklyn.core.sensor.Sensors;
+import org.apache.brooklyn.entity.software.base.VanillaSoftwareProcess;
+import org.apache.brooklyn.feed.ssh.SshFeed;
+import org.apache.brooklyn.test.Asserts;
+import org.apache.brooklyn.util.core.internal.ssh.RecordingSshTool;
+import org.apache.brooklyn.util.core.internal.ssh.RecordingSshTool.ExecCmd;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicates;
+import com.google.common.collect.Iterables;
+
+@Test
+public class SshCommandSensorYamlRebindTest extends AbstractYamlRebindTest {
+
+ @Test
+ public void testSshCommandSensorWithEffectorInEnv() throws Exception {
+ RecordingSshTool.setCustomResponse(".*myCommand.*", new RecordingSshTool.CustomResponse(0, "myResponse", null));
+
+ createStartWaitAndLogApplication(
+ "location:",
+ " localhost:",
+ " sshToolClass: "+RecordingSshTool.class.getName(),
+ "services:",
+ "- type: " + VanillaSoftwareProcess.class.getName(),
+ " brooklyn.config:",
+ " onbox.base.dir.skipResolution: true",
+ " brooklyn.initializers:",
+ " - type: org.apache.brooklyn.core.sensor.ssh.SshCommandSensor",
+ " brooklyn.config:",
+ " name: mySensor",
+ " command: myCommand",
+ " executionDir: '/path/to/myexecutiondir'",
+ " shell.env:",
+ " MY_ENV: myEnvVal",
+ " period: 10ms",
+ " onlyIfServiceUp: false");
+
+ StartableApplication newApp = rebind();
+ VanillaSoftwareProcess newEntity = (VanillaSoftwareProcess) Iterables.getOnlyElement(newApp.getChildren());
+ SshFeed newFeed = (SshFeed) Iterables.find(((EntityInternal)newEntity).feeds().getFeeds(), Predicates.instanceOf(SshFeed.class));
+
+ // Clear history of commands, and the sensor, so can confirm it gets re-set by the ssh feed
+ RecordingSshTool.clearCmdHistory();
+ newEntity.sensors().set(Sensors.newStringSensor("mySensor"), null);
+
+ // Assert sensor is set, and command is executed as expected
+ EntityAsserts.assertAttributeEqualsEventually(newEntity, Sensors.newStringSensor("mySensor"), "myResponse");
+ ExecCmd cmd = Asserts.succeedsEventually(() -> RecordingSshTool.getLastExecCmd());
+
+ assertTrue(cmd.commands.toString().contains("myCommand"), "cmds="+cmd.commands);
+ assertEquals(cmd.env.get("MY_ENV"), "myEnvVal", "env="+cmd.env);
+ assertTrue(cmd.commands.toString().contains("/path/to/myexecutiondir"), "cmds="+cmd.commands);
+
+ // Confirm feed's memento is 'clean' - no anonymous inner classes
+ BrooklynMementoRawData rawMemento = loadMementoRawData();
+ String rawFeedMemento = rawMemento.getFeeds().get(newFeed.getId());
+ assertFalse(rawFeedMemento.contains("$1"), rawFeedMemento);
+ assertFalse(rawFeedMemento.contains("$2"), rawFeedMemento);
+ assertFalse(rawFeedMemento.contains("$3"), rawFeedMemento);
+ }
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d4901150/core/src/main/java/org/apache/brooklyn/core/sensor/ssh/SshCommandSensor.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/sensor/ssh/SshCommandSensor.java b/core/src/main/java/org/apache/brooklyn/core/sensor/ssh/SshCommandSensor.java
index b03b54f..b77dde3 100644
--- a/core/src/main/java/org/apache/brooklyn/core/sensor/ssh/SshCommandSensor.java
+++ b/core/src/main/java/org/apache/brooklyn/core/sensor/ssh/SshCommandSensor.java
@@ -41,7 +41,9 @@ import org.apache.brooklyn.util.core.flags.TypeCoercions;
import org.apache.brooklyn.util.core.json.ShellEnvironmentSerializer;
import org.apache.brooklyn.util.core.task.Tasks;
import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.guava.Functionals;
import org.apache.brooklyn.util.os.Os;
+import org.apache.brooklyn.util.text.StringFunctions;
import org.apache.brooklyn.util.text.Strings;
import org.apache.brooklyn.util.time.Duration;
import org.slf4j.Logger;
@@ -53,6 +55,7 @@ import com.google.common.base.Functions;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
+import com.google.common.reflect.TypeToken;
/**
* Configurable {@link EntityInitializer} which adds an SSH sensor feed running the <code>command</code> supplied
@@ -99,7 +102,34 @@ public final class SshCommandSensor<T> extends AbstractAddSensorFeed<T> {
final Duration logWarningGraceTimeOnStartup = EntityInitializers.resolve(params, LOG_WARNING_GRACE_TIME_ON_STARTUP);
final Duration logWarningGraceTime = EntityInitializers.resolve(params, LOG_WARNING_GRACE_TIME);
- Supplier<Map<String,String>> envSupplier = new Supplier<Map<String,String>>() {
+ Supplier<Map<String,String>> envSupplier = new EnvSupplier(entity, params);
+
+ Supplier<String> commandSupplier = new CommandSupplier(entity, params);
+
+ CommandPollConfig<T> pollConfig = new CommandPollConfig<T>(sensor)
+ .period(period)
+ .env(envSupplier)
+ .command(commandSupplier)
+ .suppressDuplicates(Boolean.TRUE.equals(suppressDuplicates))
+ .checkSuccess(SshValueFunctions.exitStatusEquals(0))
+ .onFailureOrException(Functions.constant((T)params.get(VALUE_ON_ERROR)))
+ .onSuccess(Functionals.chain(
+ SshValueFunctions.stdout(),
+ StringFunctions.trimEnd(),
+ TypeCoercions.function((Class<T>) sensor.getType())))
+ .logWarningGraceTimeOnStartup(logWarningGraceTimeOnStartup)
+ .logWarningGraceTime(logWarningGraceTime);
+
+ SshFeed feed = SshFeed.builder()
+ .entity(entity)
+ .onlyIfServiceUp()
+ .poll(pollConfig)
+ .build();
+
+ entity.addFeed(feed);
+
+ // Deprecated; kept for backwards compatibility with historic persisted state
+ new Supplier<Map<String,String>>() {
@Override
public Map<String, String> get() {
if (entity == null) return ImmutableMap.of(); // See BROOKLYN-568
@@ -123,7 +153,8 @@ public final class SshCommandSensor<T> extends AbstractAddSensorFeed<T> {
}
};
- Supplier<String> commandSupplier = new Supplier<String>() {
+ // Deprecated; kept for backwards compatibility with historic persisted state
+ new Supplier<String>() {
@Override
public String get() {
// Note that entity may be null during rebind (e.g. if this SshFeed is orphaned, with no associated entity):
@@ -135,28 +166,12 @@ public final class SshCommandSensor<T> extends AbstractAddSensorFeed<T> {
}
};
- CommandPollConfig<T> pollConfig = new CommandPollConfig<T>(sensor)
- .period(period)
- .env(envSupplier)
- .command(commandSupplier)
- .suppressDuplicates(Boolean.TRUE.equals(suppressDuplicates))
- .checkSuccess(SshValueFunctions.exitStatusEquals(0))
- .onFailureOrException(Functions.constant((T)params.get(VALUE_ON_ERROR)))
- .onSuccess(Functions.compose(new Function<String, T>() {
- @Override
- public T apply(String input) {
- return TypeCoercions.coerce(Strings.trimEnd(input), (Class<T>) sensor.getType());
- }}, SshValueFunctions.stdout()))
- .logWarningGraceTimeOnStartup(logWarningGraceTimeOnStartup)
- .logWarningGraceTime(logWarningGraceTime);
-
- SshFeed feed = SshFeed.builder()
- .entity(entity)
- .onlyIfServiceUp()
- .poll(pollConfig)
- .build();
-
- entity.addFeed(feed);
+ // Deprecated; kept for backwards compatibility with historic persisted state
+ new Function<String, T>() {
+ @Override public T apply(String input) {
+ return TypeCoercions.coerce(Strings.trimEnd(input), (Class<T>) sensor.getType());
+ }
+ };
}
@Beta
@@ -183,4 +198,65 @@ public final class SshCommandSensor<T> extends AbstractAddSensorFeed<T> {
return finalCommand;
}
+ private static class EnvSupplier implements Supplier<Map<String,String>> {
+ private final Entity entity;
+ private final Object rawSensorShellEnv;
+
+ EnvSupplier(Entity entity, ConfigBag params) {
+ this.entity = entity;
+ this.rawSensorShellEnv = params.getAllConfigRaw().getOrDefault(SENSOR_SHELL_ENVIRONMENT.getName(), SENSOR_SHELL_ENVIRONMENT.getDefaultValue());
+ }
+
+ @Override
+ public Map<String, String> get() {
+ if (entity == null) return ImmutableMap.of(); // See BROOKLYN-568
+
+ Map<String, Object> env = MutableMap.copyOf(entity.getConfig(BrooklynConfigKeys.SHELL_ENVIRONMENT));
+
+ // Add the shell environment entries from our configuration
+ if (rawSensorShellEnv != null) {
+ env.putAll(TypeCoercions.coerce(rawSensorShellEnv, new TypeToken<Map<String,Object>>() {}));
+ }
+
+ // Try to resolve the configuration in the env Map
+ try {
+ env = (Map<String, Object>) Tasks.resolveDeepValue(env, Object.class, ((EntityInternal) entity).getExecutionContext());
+ } catch (InterruptedException | ExecutionException e) {
+ Exceptions.propagateIfFatal(e);
+ }
+
+ // Convert the environment into strings with the serializer
+ ShellEnvironmentSerializer serializer = new ShellEnvironmentSerializer(((EntityInternal) entity).getManagementContext());
+ return serializer.serialize(env);
+ }
+ }
+
+ private static class CommandSupplier implements Supplier<String> {
+ private final Entity entity;
+ private final Object rawSensorCommand;
+ private final Object rawSensorExecDir;
+
+ CommandSupplier(Entity entity, ConfigBag params) {
+ this.entity = entity;
+ this.rawSensorCommand = params.getAllConfigRaw().get(SENSOR_COMMAND.getName());
+ this.rawSensorExecDir = params.getAllConfigRaw().get(SENSOR_EXECUTION_DIR.getName());
+ }
+
+ @Override
+ public String get() {
+ // Note that entity may be null during rebind (e.g. if this SshFeed is orphaned, with no associated entity):
+ // See https://issues.apache.org/jira/browse/BROOKLYN-568.
+ // We therefore guard against null in makeCommandExecutingInDirectory.
+ ConfigBag params = ConfigBag.newInstance();
+ if (rawSensorCommand != null) {
+ params.putStringKey(SENSOR_COMMAND.getName(), rawSensorCommand);
+ }
+ if (rawSensorExecDir != null) {
+ params.putStringKey(SENSOR_EXECUTION_DIR.getName(), rawSensorExecDir);
+ }
+ String command = Preconditions.checkNotNull(EntityInitializers.resolve(params, SENSOR_COMMAND));
+ String dir = EntityInitializers.resolve(params, SENSOR_EXECUTION_DIR);
+ return makeCommandExecutingInDirectory(command, dir, entity);
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d4901150/core/src/main/java/org/apache/brooklyn/util/core/flags/TypeCoercions.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/flags/TypeCoercions.java b/core/src/main/java/org/apache/brooklyn/util/core/flags/TypeCoercions.java
index a2dc398..3b3f874 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/flags/TypeCoercions.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/flags/TypeCoercions.java
@@ -28,7 +28,6 @@ import org.apache.brooklyn.api.sensor.AttributeSensor;
import org.apache.brooklyn.api.sensor.Sensor;
import org.apache.brooklyn.core.internal.BrooklynInitialization;
import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
-import org.apache.brooklyn.core.mgmt.usage.UsageListener;
import org.apache.brooklyn.core.sensor.Sensors;
import org.apache.brooklyn.util.JavaGroovyEquivalents;
import org.apache.brooklyn.util.core.ClassLoaderUtils;
@@ -93,7 +92,19 @@ public class TypeCoercions {
}
public static <T> Function<Object, T> function(final Class<T> type) {
- return coercer.function(type);
+ return new CoerceFunction<T>(type);
+ }
+
+ private static class CoerceFunction<T> implements Function<Object, T> {
+ private final Class<T> type;
+
+ public CoerceFunction(Class<T> type) {
+ this.type = type;
+ }
+ @Override
+ public T apply(Object input) {
+ return coerce(input, type);
+ }
}
public static void registerDeprecatedBrooklynAdapters() {
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d4901150/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindTestFixture.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindTestFixture.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindTestFixture.java
index b80d857..b09aba6 100644
--- a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindTestFixture.java
+++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindTestFixture.java
@@ -19,9 +19,11 @@
package org.apache.brooklyn.core.mgmt.rebind;
import java.io.File;
+import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
+import java.util.function.Function;
import org.apache.brooklyn.api.entity.Application;
import org.apache.brooklyn.api.mgmt.ManagementContext;
@@ -30,6 +32,7 @@ import org.apache.brooklyn.api.mgmt.ha.HighAvailabilityMode;
import org.apache.brooklyn.api.mgmt.rebind.RebindExceptionHandler;
import org.apache.brooklyn.api.mgmt.rebind.RebindManager;
import org.apache.brooklyn.api.mgmt.rebind.mementos.BrooklynMementoManifest;
+import org.apache.brooklyn.api.mgmt.rebind.mementos.BrooklynMementoRawData;
import org.apache.brooklyn.core.entity.Entities;
import org.apache.brooklyn.core.entity.EntityPredicates;
import org.apache.brooklyn.core.entity.StartableApplication;
@@ -41,6 +44,7 @@ import org.apache.brooklyn.core.mgmt.persist.FileBasedObjectStore;
import org.apache.brooklyn.core.mgmt.persist.PersistMode;
import org.apache.brooklyn.core.server.BrooklynServerConfig;
import org.apache.brooklyn.util.core.task.BasicExecutionManager;
+import org.apache.brooklyn.util.exceptions.Exceptions;
import org.apache.brooklyn.util.os.Os;
import org.apache.brooklyn.util.osgi.OsgiTestResources;
import org.apache.brooklyn.util.repeat.Repeater;
@@ -299,6 +303,24 @@ public abstract class RebindTestFixture<T extends StartableApplication> {
}
protected BrooklynMementoManifest loadMementoManifest() throws Exception {
+ return loadFromPersistedState((persister) -> {
+ RebindExceptionHandler exceptionHandler = new RecordingRebindExceptionHandler(RebindManager.RebindFailureMode.FAIL_AT_END, RebindManager.RebindFailureMode.FAIL_AT_END);
+ try {
+ return persister.loadMementoManifest(null, exceptionHandler);
+ } catch (IOException e) {
+ throw Exceptions.propagate(e);
+ }
+ });
+ }
+
+ protected BrooklynMementoRawData loadMementoRawData() throws Exception {
+ return loadFromPersistedState((persister) -> {
+ RebindExceptionHandler exceptionHandler = new RecordingRebindExceptionHandler(RebindManager.RebindFailureMode.FAIL_AT_END, RebindManager.RebindFailureMode.FAIL_AT_END);
+ return persister.loadMementoRawData(exceptionHandler);
+ });
+ }
+
+ protected <U> U loadFromPersistedState(Function<BrooklynMementoPersisterToObjectStore, U> loader) throws Exception {
newManagementContext = createNewManagementContext();
FileBasedObjectStore objectStore = new FileBasedObjectStore(mementoDir);
objectStore.injectManagementContext(newManagementContext);
@@ -307,10 +329,13 @@ public abstract class RebindTestFixture<T extends StartableApplication> {
objectStore,
newManagementContext,
classLoader);
- RebindExceptionHandler exceptionHandler = new RecordingRebindExceptionHandler(RebindManager.RebindFailureMode.FAIL_AT_END, RebindManager.RebindFailureMode.FAIL_AT_END);
- BrooklynMementoManifest mementoManifest = persister.loadMementoManifest(null, exceptionHandler);
- persister.stop(false);
- return mementoManifest;
+ U result;
+ try {
+ result = loader.apply(persister);
+ } finally {
+ persister.stop(false);
+ }
+ return result;
}
// protected void assertCatalogContains(BrooklynCatalog catalog, CatalogItem<?, ?> item) {
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d4901150/utils/common/src/main/java/org/apache/brooklyn/util/guava/Functionals.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/guava/Functionals.java b/utils/common/src/main/java/org/apache/brooklyn/util/guava/Functionals.java
index 18238d2..ef2400b 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/guava/Functionals.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/guava/Functionals.java
@@ -135,6 +135,9 @@ public class Functionals {
}
public static <T> Predicate<T> predicate(final Function<T,Boolean> f) {
+ // Deprecated use of anonymous class (even though it's got a name, it's in a method).
+ // Kept for rebinding to historic persisted state only.
+ @SuppressWarnings({ "unused", "hiding" })
class FunctionAsPredicate implements Predicate<T> {
@Override
public boolean apply(T input) {
@@ -145,7 +148,23 @@ public class Functionals {
return "predicate("+f+")";
}
}
- return new FunctionAsPredicate();
+ return new Functionals.FunctionAsPredicate<T>(f);
+ }
+
+ static class FunctionAsPredicate<T> implements Predicate<T> {
+ private final Function<T, Boolean> f;
+
+ FunctionAsPredicate(final Function<T,Boolean> f) {
+ this.f = f;
+ }
+ @Override
+ public boolean apply(T input) {
+ return f.apply(input);
+ }
+ @Override
+ public String toString() {
+ return "predicate("+f+")";
+ }
}
/**
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d4901150/utils/common/src/main/java/org/apache/brooklyn/util/text/StringFunctions.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/text/StringFunctions.java b/utils/common/src/main/java/org/apache/brooklyn/util/text/StringFunctions.java
index ddf1914..13f32fc 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/text/StringFunctions.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/text/StringFunctions.java
@@ -366,6 +366,18 @@ public class StringFunctions {
}
}
+ public static Function<String, String> trimEnd() {
+ return new TrimEndFunction();
+ }
+
+ protected static class TrimEndFunction implements Function<String, String> {
+ @Override
+ public String apply(@Nullable String input) {
+ if (input == null) return null;
+ return Strings.trimEnd(input);
+ }
+ }
+
public static Function<String, String> toLowerCase() {
return new LowerCaseFunction();
}
[3/3] brooklyn-server git commit: This closes #959
Posted by tb...@apache.org.
This closes #959
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/7e2b497c
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/7e2b497c
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/7e2b497c
Branch: refs/heads/master
Commit: 7e2b497cbf82ca143fd2276f44aca256fc92ee3b
Parents: cd40893 d490115
Author: Thomas Bouron <th...@cloudsoftcorp.com>
Authored: Fri Apr 27 16:43:31 2018 +0100
Committer: Thomas Bouron <th...@cloudsoftcorp.com>
Committed: Fri Apr 27 16:43:31 2018 +0100
----------------------------------------------------------------------
.../SshCommandSensorYamlRebindTest.java | 89 +++++++++++
.../core/sensor/ssh/SshCommandSensor.java | 134 +++++++++++++----
.../brooklyn/util/core/flags/TypeCoercions.java | 15 +-
.../RebindHistoricSshCommandSensorTest.java | 96 ++++++++++++
.../core/mgmt/rebind/RebindTestFixture.java | 33 +++-
.../rebind/ssh-command-sensor-entity-dnlz7hpbdg | 150 +++++++++++++++++++
.../rebind/ssh-command-sensor-feed-a9ekg3cnu0 | 143 ++++++++++++++++++
.../apache/brooklyn/util/guava/Functionals.java | 21 ++-
.../brooklyn/util/text/StringFunctions.java | 12 ++
9 files changed, 661 insertions(+), 32 deletions(-)
----------------------------------------------------------------------
[2/3] brooklyn-server git commit: Fix SshCommandSensor rebind
Posted by tb...@apache.org.
Fix SshCommandSensor rebind
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/3afc8fe3
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/3afc8fe3
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/3afc8fe3
Branch: refs/heads/master
Commit: 3afc8fe386dc1f6f4149143a7b205c96185a770e
Parents: cd40893
Author: Aled Sage <al...@gmail.com>
Authored: Thu Apr 26 19:36:30 2018 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Fri Apr 27 10:09:31 2018 +0100
----------------------------------------------------------------------
.../core/sensor/ssh/SshCommandSensor.java | 10 +-
.../RebindHistoricSshCommandSensorTest.java | 96 ++++++++++++
.../rebind/ssh-command-sensor-entity-dnlz7hpbdg | 150 +++++++++++++++++++
.../rebind/ssh-command-sensor-feed-a9ekg3cnu0 | 143 ++++++++++++++++++
4 files changed, 398 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/3afc8fe3/core/src/main/java/org/apache/brooklyn/core/sensor/ssh/SshCommandSensor.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/sensor/ssh/SshCommandSensor.java b/core/src/main/java/org/apache/brooklyn/core/sensor/ssh/SshCommandSensor.java
index 5ec9d22..b03b54f 100644
--- a/core/src/main/java/org/apache/brooklyn/core/sensor/ssh/SshCommandSensor.java
+++ b/core/src/main/java/org/apache/brooklyn/core/sensor/ssh/SshCommandSensor.java
@@ -74,7 +74,15 @@ public final class SshCommandSensor<T> extends AbstractAddSensorFeed<T> {
"Value to be used if an error occurs whilst executing the ssh command", null);
public static final MapConfigKey<Object> SENSOR_SHELL_ENVIRONMENT = BrooklynConfigKeys.SHELL_ENVIRONMENT;
-
+ // Fields are kept for deserialization purposes; however will rely on the values being
+ // re-computed from the config map, rather than being restored from persistence.
+ @SuppressWarnings("unused")
+ private String command;
+ @SuppressWarnings("unused")
+ private String executionDir;
+ @SuppressWarnings("unused")
+ private Map<String,Object> sensorEnv;
+
public SshCommandSensor(final ConfigBag params) {
super(params);
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/3afc8fe3/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindHistoricSshCommandSensorTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindHistoricSshCommandSensorTest.java b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindHistoricSshCommandSensorTest.java
new file mode 100644
index 0000000..f463d9e
--- /dev/null
+++ b/core/src/test/java/org/apache/brooklyn/core/mgmt/rebind/RebindHistoricSshCommandSensorTest.java
@@ -0,0 +1,96 @@
+/*
+ * 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.rebind;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.api.objs.BrooklynObjectType;
+import org.apache.brooklyn.core.entity.EntityInternal;
+import org.apache.brooklyn.location.ssh.SshMachineLocation;
+import org.apache.brooklyn.test.Asserts;
+import org.apache.brooklyn.util.core.internal.ssh.RecordingSshTool;
+import org.apache.brooklyn.util.core.internal.ssh.RecordingSshTool.ExecCmd;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+public class RebindHistoricSshCommandSensorTest extends AbstractRebindHistoricTest {
+
+ private static final String BLACKHOLE_IP = "240.0.0.1";
+
+ @Override
+ @BeforeMethod(alwaysRun=true)
+ public void setUp() throws Exception {
+ super.setUp();
+ }
+
+ /**
+ * The persisted state was generated when SshCommandSensor used fields for 'command' etc, populating
+ * them during init. Now it populates them lazily (thus handling deferred config suppliers).
+ *
+ * It also used anonymous inner classes for the deferred suppliers.
+ *
+ * Generated the persisted state using Brooklyn from Feb 2018, using the blueprint below:
+ * <pre>
+ * services:
+ * - type: org.apache.brooklyn.entity.stock.BasicApplication
+ * brooklyn.initializers:
+ * - type: org.apache.brooklyn.core.sensor.ssh.SshCommandSensor
+ * brooklyn.config:
+ * name: myconf
+ * targetType: String
+ * period: 100ms
+ * command: "echo 'myval'"
+ * shell.env:
+ * MY_ENV: myEnvVal
+ * executionDir: '/path/to/myexecutiondir'
+ * <pre>
+ */
+ @Test
+ public void testSshFeed_2018_02() throws Exception {
+ addMemento(BrooklynObjectType.ENTITY, "ssh-command-sensor-entity", "dnlz7hpbdg");
+ addMemento(BrooklynObjectType.FEED, "ssh-command-sensor-feed", "a9ekg3cnu0");
+ rebind();
+
+ EntityInternal entity = (EntityInternal) mgmt().getEntityManager().getEntity("dnlz7hpbdg");
+ entity.feeds().getFeeds();
+
+ SshMachineLocation recordingLocalhostMachine = mgmt().getLocationManager().createLocation(LocationSpec.create(SshMachineLocation.class)
+ .configure("address", BLACKHOLE_IP)
+ .configure(SshMachineLocation.SSH_TOOL_CLASS, RecordingSshTool.class.getName()));
+ entity.addLocations(ImmutableList.of(recordingLocalhostMachine));
+
+ ExecCmd cmd = Asserts.succeedsEventually(() -> RecordingSshTool.getLastExecCmd());
+
+ assertTrue(cmd.commands.toString().contains("echo 'myval'"), "cmds="+cmd.commands);
+ assertEquals(cmd.env.get("MY_ENV"), "myEnvVal", "env="+cmd.env);
+ assertTrue(cmd.commands.toString().contains("/path/to/myexecutiondir"), "cmds="+cmd.commands);
+ }
+
+ // This test is similar to testSshFeed_2017_01, except the persisted state file has been
+ // hand-crafted to remove the bundle prefixes for "org.apache.brooklyn.*" bundles.
+ @Test
+ public void testFoo_2017_01_withoutBundlePrefixes() throws Exception {
+ addMemento(BrooklynObjectType.FEED, "ssh-feed-no-bundle-prefixes", "zv7t8bim62");
+ rebind();
+ }
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/3afc8fe3/core/src/test/resources/org/apache/brooklyn/core/mgmt/rebind/ssh-command-sensor-entity-dnlz7hpbdg
----------------------------------------------------------------------
diff --git a/core/src/test/resources/org/apache/brooklyn/core/mgmt/rebind/ssh-command-sensor-entity-dnlz7hpbdg b/core/src/test/resources/org/apache/brooklyn/core/mgmt/rebind/ssh-command-sensor-entity-dnlz7hpbdg
new file mode 100644
index 0000000..cb16e80
--- /dev/null
+++ b/core/src/test/resources/org/apache/brooklyn/core/mgmt/rebind/ssh-command-sensor-entity-dnlz7hpbdg
@@ -0,0 +1,150 @@
+<!--
+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.
+-->
+
+<entity>
+ <brooklynVersion>1.0.0-20180227.1009</brooklynVersion>
+ <type>org.apache.brooklyn.core:org.apache.brooklyn.entity.stock.BasicApplicationImpl</type>
+ <id>dnlz7hpbdg</id>
+ <displayName>Basic Application</displayName>
+ <searchPath class="ImmutableList"/>
+ <tags>
+ <org.apache.brooklyn.core:org.apache.brooklyn.core.mgmt.BrooklynTags_-NamedStringTag>
+ <kind>yaml_spec</kind>
+ <contents>services:
+ - type: org.apache.brooklyn.entity.stock.BasicApplication
+ brooklyn.initializers:
+ - type: org.apache.brooklyn.core.sensor.ssh.SshCommandSensor
+ brooklyn.config:
+ name: myconf
+ targetType: String
+ period: 5s
+ command: echo 'myval'
+ shell.env:
+ MY_ENV: myEnvVal
+ executionDir: /path/to/myexecutiondir
+</contents>
+ </org.apache.brooklyn.core:org.apache.brooklyn.core.mgmt.BrooklynTags_-NamedStringTag>
+ <org.apache.brooklyn.core:org.apache.brooklyn.core.mgmt.BrooklynTags_-NamedStringTag>
+ <kind>yaml_spec</kind>
+ <contents>services:
+- type: org.apache.brooklyn.entity.stock.BasicApplication
+ name: Basic Application
+ description: The simplest application.</contents>
+ </org.apache.brooklyn.core:org.apache.brooklyn.core.mgmt.BrooklynTags_-NamedStringTag>
+ </tags>
+ <config>
+ <camp.template.id>kyb9EoI6</camp.template.id>
+ </config>
+ <attributes>
+ <service.notUp.indicators>
+ <MutableMap/>
+ </service.notUp.indicators>
+ <entity.id>dnlz7hpbdg</entity.id>
+ <application.id>dnlz7hpbdg</application.id>
+ <service.isUp type="boolean">true</service.isUp>
+ <service.problems>
+ <MutableMap/>
+ </service.problems>
+ <service.state type="org.apache.brooklyn.core:org.apache.brooklyn.core.entity.lifecycle.Lifecycle">RUNNING</service.state>
+ <service.state.expected>
+ <org.apache.brooklyn.core:org.apache.brooklyn.core.entity.lifecycle.Lifecycle_-Transition>
+ <state>RUNNING</state>
+ <timestampUtc>1524765391349</timestampUtc>
+ </org.apache.brooklyn.core:org.apache.brooklyn.core.entity.lifecycle.Lifecycle_-Transition>
+ </service.state.expected>
+ <myconf>
+ <null/>
+ </myconf>
+ </attributes>
+ <enrichers/>
+ <feeds>
+ <string>a9ekg3cnu0</string>
+ </feeds>
+ <configKeys>
+ <camp.template.id>
+ <configKey>
+ <name>camp.template.id</name>
+ <deprecatedNames class="ImmutableList" reference="../../../../searchPath"/>
+ <type>java.lang.String</type>
+ <description>UID of the component in the CAMP template from which this entity was created</description>
+ <reconfigurable>false</reconfigurable>
+ <runtimeInheritance class="org.apache.brooklyn.core:org.apache.brooklyn.core.config.BasicConfigInheritance$NeverInherited"/>
+ <constraint class="com.google.common.base.Predicates$ObjectPredicate">ALWAYS_TRUE</constraint>
+ </configKey>
+ </camp.template.id>
+ </configKeys>
+ <attributeKeys>
+ <service.notUp.indicators>
+ <attributeSensor>
+ <typeToken class="org.apache.brooklyn.core:org.apache.brooklyn.core.entity.Attributes$1" resolves-to="com.google.guava:com.google.common.reflect.TypeToken$SimpleTypeToken">
+ <runtimeType class="com.google.guava:com.google.common.reflect.Types$ParameterizedTypeImpl">
+ <argumentsList>
+ <java-class>java.lang.String</java-class>
+ <java-class>java.lang.Object</java-class>
+ </argumentsList>
+ <rawType>java.util.Map</rawType>
+ </runtimeType>
+ </typeToken>
+ <name>service.notUp.indicators</name>
+ <description>A map of namespaced indicators that the service is not up</description>
+ <persistence>REQUIRED</persistence>
+ </attributeSensor>
+ </service.notUp.indicators>
+ <service.problems>
+ <attributeSensor>
+ <typeToken class="org.apache.brooklyn.core:org.apache.brooklyn.core.entity.Attributes$2" resolves-to="com.google.guava:com.google.common.reflect.TypeToken$SimpleTypeToken">
+ <runtimeType class="com.google.guava:com.google.common.reflect.Types$ParameterizedTypeImpl">
+ <argumentsList>
+ <java-class>java.lang.String</java-class>
+ <java-class>java.lang.Object</java-class>
+ </argumentsList>
+ <rawType>java.util.Map</rawType>
+ </runtimeType>
+ </typeToken>
+ <name>service.problems</name>
+ <description>A map of namespaced indicators of problems with a service</description>
+ <persistence>REQUIRED</persistence>
+ </attributeSensor>
+ </service.problems>
+ <service.state>
+ <attributeSensor>
+ <type>org.apache.brooklyn.core:org.apache.brooklyn.core.entity.lifecycle.Lifecycle</type>
+ <name>service.state</name>
+ <description>Actual lifecycle state of the service</description>
+ <persistence>REQUIRED</persistence>
+ </attributeSensor>
+ </service.state>
+ <service.state.expected>
+ <attributeSensor>
+ <type>org.apache.brooklyn.core:org.apache.brooklyn.core.entity.lifecycle.Lifecycle$Transition</type>
+ <name>service.state.expected</name>
+ <description>Last controlled change to service state, indicating what the expected state should be</description>
+ <persistence>REQUIRED</persistence>
+ </attributeSensor>
+ </service.state.expected>
+ <myconf>
+ <attributeSensor>
+ <type>java.lang.String</type>
+ <name>myconf</name>
+ <description>myconf</description>
+ <persistence>REQUIRED</persistence>
+ </attributeSensor>
+ </myconf>
+ </attributeKeys>
+</entity>
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/3afc8fe3/core/src/test/resources/org/apache/brooklyn/core/mgmt/rebind/ssh-command-sensor-feed-a9ekg3cnu0
----------------------------------------------------------------------
diff --git a/core/src/test/resources/org/apache/brooklyn/core/mgmt/rebind/ssh-command-sensor-feed-a9ekg3cnu0 b/core/src/test/resources/org/apache/brooklyn/core/mgmt/rebind/ssh-command-sensor-feed-a9ekg3cnu0
new file mode 100644
index 0000000..240ff30
--- /dev/null
+++ b/core/src/test/resources/org/apache/brooklyn/core/mgmt/rebind/ssh-command-sensor-feed-a9ekg3cnu0
@@ -0,0 +1,143 @@
+<!--
+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.
+-->
+
+<feed>
+ <brooklynVersion>1.0.0-20180227.1009</brooklynVersion>
+ <type>org.apache.brooklyn.core:org.apache.brooklyn.feed.ssh.SshFeed</type>
+ <id>a9ekg3cnu0</id>
+ <displayName>org.apache.brooklyn.feed.ssh.SshFeed</displayName>
+ <searchPath class="ImmutableList"/>
+ <tags>
+ <string>SshFeed[ssh[mkdir -p '/path/to/myexecutio.../85a25c3b->myconf]]</string>
+ </tags>
+ <uniqueTag>SshFeed[ssh[mkdir -p '/path/to/myexecutio.../85a25c3b->myconf]]</uniqueTag>
+ <config>
+ <feed.onlyIfServiceUp type="boolean">true</feed.onlyIfServiceUp>
+ <machine>
+ <null/>
+ </machine>
+ <execAsCommand type="boolean">false</execAsCommand>
+ <polls>
+ <com.google.guava:com.google.common.collect.HashMultimap serialization="custom">
+ <unserializable-parents/>
+ <com.google.guava:com.google.common.collect.HashMultimap>
+ <default/>
+ <int>2</int>
+ <int>1</int>
+ <org.apache.brooklyn.core:org.apache.brooklyn.feed.AbstractCommandFeed_-CommandPollIdentifier>
+ <command class="org.apache.brooklyn.core:org.apache.brooklyn.core.sensor.ssh.SshCommandSensor$2">
+ <val_-entity>dnlz7hpbdg</val_-entity>
+ <outer-class>
+ <name>myconf</name>
+ <period>
+ <nanos>100000000</nanos>
+ </period>
+ <type>String</type>
+ <sensor class="attributeSensor">
+ <type>java.lang.String</type>
+ <name>myconf</name>
+ <description>myconf</description>
+ <persistence>REQUIRED</persistence>
+ </sensor>
+ <params>
+ <config>
+ <name>myconf</name>
+ <targetType>String</targetType>
+ <period>5s</period>
+ <command>echo 'myval'</command>
+ <shell.env>
+ <map>
+ <MY__ENV>myEnvVal</MY__ENV>
+ </map>
+ </shell.env>
+ <executionDir>/path/to/myexecutiondir</executionDir>
+ </config>
+ <unusedConfig/>
+ <live>false</live>
+ <sealed>false</sealed>
+ </params>
+ <command>echo 'myval'</command>
+ <executionDir>/path/to/myexecutiondir</executionDir>
+ <sensorEnv>
+ <MY__ENV>myEnvVal</MY__ENV>
+ </sensorEnv>
+ </outer-class>
+ </command>
+ <env class="org.apache.brooklyn.core:org.apache.brooklyn.feed.CommandPollConfig$CombiningEnvSupplier">
+ <dynamicEnvironmentSupplier class="MutableList" serialization="custom">
+ <unserializable-parents/>
+ <list>
+ <default>
+ <size>1</size>
+ </default>
+ <int>1</int>
+ <org.apache.brooklyn.core:org.apache.brooklyn.core.sensor.ssh.SshCommandSensor_-1>
+ <val_-entity reference="../../../../../command/val_-entity"/>
+ <outer-class reference="../../../../../command/outer-class"/>
+ </org.apache.brooklyn.core:org.apache.brooklyn.core.sensor.ssh.SshCommandSensor_-1>
+ </list>
+ </dynamicEnvironmentSupplier>
+ </env>
+ </org.apache.brooklyn.core:org.apache.brooklyn.feed.AbstractCommandFeed_-CommandPollIdentifier>
+ <int>1</int>
+ <org.apache.brooklyn.core:org.apache.brooklyn.feed.CommandPollConfig>
+ <sensor class="attributeSensor" reference="../../org.apache.brooklyn.core:org.apache.brooklyn.feed.AbstractCommandFeed_-CommandPollIdentifier/command/outer-class/sensor"/>
+ <onsuccess class="com.google.guava:com.google.common.base.Functions$FunctionComposition">
+ <g class="org.apache.brooklyn.core:org.apache.brooklyn.core.sensor.ssh.SshCommandSensor$3">
+ <outer-class reference="../../../../org.apache.brooklyn.core:org.apache.brooklyn.feed.AbstractCommandFeed_-CommandPollIdentifier/command/outer-class"/>
+ </g>
+ <f class="org.apache.brooklyn.core:org.apache.brooklyn.feed.ssh.SshValueFunctions$Stdout"/>
+ </onsuccess>
+ <onfailure class="com.google.guava:com.google.common.base.Functions$ConstantFunction"/>
+ <onexception class="com.google.guava:com.google.common.base.Functions$ConstantFunction" reference="../onfailure"/>
+ <checkSuccess class="org.apache.brooklyn.utils-common:org.apache.brooklyn.util.guava.Functionals$1FunctionAsPredicate">
+ <val_-f class="com.google.guava:com.google.common.base.Functions$FunctionComposition">
+ <g class="com.google.guava:com.google.common.base.Functions$PredicateFunction">
+ <predicate class="com.google.guava:com.google.common.base.Predicates$IsEqualToPredicate">
+ <target class="int">0</target>
+ </predicate>
+ </g>
+ <f class="org.apache.brooklyn.core:org.apache.brooklyn.feed.ssh.SshValueFunctions$ExitStatus"/>
+ </val_-f>
+ </checkSuccess>
+ <suppressDuplicates>false</suppressDuplicates>
+ <enabled>true</enabled>
+ <logWarningGraceTimeOnStartup>
+ <nanos>0</nanos>
+ </logWarningGraceTimeOnStartup>
+ <logWarningGraceTime>
+ <nanos>0</nanos>
+ </logWarningGraceTime>
+ <period>5000</period>
+ <commandSupplier class="org.apache.brooklyn.core:org.apache.brooklyn.core.sensor.ssh.SshCommandSensor$2" reference="../../org.apache.brooklyn.core:org.apache.brooklyn.feed.AbstractCommandFeed_-CommandPollIdentifier/command"/>
+ <dynamicEnvironmentSupplier class="MutableList" serialization="custom">
+ <unserializable-parents/>
+ <list>
+ <default>
+ <size>0</size>
+ </default>
+ <int>0</int>
+ </list>
+ </dynamicEnvironmentSupplier>
+ </org.apache.brooklyn.core:org.apache.brooklyn.feed.CommandPollConfig>
+ </com.google.guava:com.google.common.collect.HashMultimap>
+ </com.google.guava:com.google.common.collect.HashMultimap>
+ </polls>
+ </config>
+</feed>