From c1a991907b2aa3c9fc0872c3bc507096d657b8fc Mon Sep 17 00:00:00 2001 From: Svetoslav Neykov Date: Thu, 23 Jun 2016 15:23:06 +0300 Subject: [PATCH] Serialize environment values - implement for all entities --- .../core/effector/ssh/SshCommandEffector.java | 6 +++- .../core/entity/BrooklynConfigKeys.java | 2 +- .../core/sensor/ssh/SshCommandSensor.java | 6 +++- .../json}/ShellEnvironmentSerializer.java | 28 +++++++++++++++++-- .../AbstractSoftwareProcessSshDriver.java | 18 ++---------- .../base/ShellEnvironmentSerializerTest.java | 1 + .../test/framework/TestSshCommandImpl.java | 12 ++++---- 7 files changed, 47 insertions(+), 26 deletions(-) rename {software/base/src/main/java/org/apache/brooklyn/entity/software/base => core/src/main/java/org/apache/brooklyn/util/core/json}/ShellEnvironmentSerializer.java (68%) diff --git a/core/src/main/java/org/apache/brooklyn/core/effector/ssh/SshCommandEffector.java b/core/src/main/java/org/apache/brooklyn/core/effector/ssh/SshCommandEffector.java index b22f717fc1..ca952fee08 100644 --- a/core/src/main/java/org/apache/brooklyn/core/effector/ssh/SshCommandEffector.java +++ b/core/src/main/java/org/apache/brooklyn/core/effector/ssh/SshCommandEffector.java @@ -29,9 +29,11 @@ import org.apache.brooklyn.core.effector.Effectors; import org.apache.brooklyn.core.effector.Effectors.EffectorBuilder; import org.apache.brooklyn.core.entity.BrooklynConfigKeys; +import org.apache.brooklyn.core.entity.EntityInternal; import org.apache.brooklyn.core.sensor.ssh.SshCommandSensor; import org.apache.brooklyn.util.collections.MutableMap; import org.apache.brooklyn.util.core.config.ConfigBag; +import org.apache.brooklyn.util.core.json.ShellEnvironmentSerializer; import org.apache.brooklyn.util.text.Strings; import com.google.common.base.Preconditions; @@ -81,7 +83,9 @@ public String call(ConfigBag params) { } // then set things from the entities defined shell environment, if applicable - env.putAll(Strings.toStringMap(entity().getConfig(BrooklynConfigKeys.SHELL_ENVIRONMENT), "")); + Map shellEnv = entity().getConfig(BrooklynConfigKeys.SHELL_ENVIRONMENT); + ShellEnvironmentSerializer envSerializer = new ShellEnvironmentSerializer(((EntityInternal)entity()).getManagementContext()); + env.putAll(envSerializer.serialize(shellEnv)); // if we wanted to resolve the surrounding environment in real time -- see above // Map paramsResolved = (Map) Tasks.resolveDeepValue(effectorShellEnv, Map.class, entity().getExecutionContext()); diff --git a/core/src/main/java/org/apache/brooklyn/core/entity/BrooklynConfigKeys.java b/core/src/main/java/org/apache/brooklyn/core/entity/BrooklynConfigKeys.java index d9cb7ad548..3530760e85 100644 --- a/core/src/main/java/org/apache/brooklyn/core/entity/BrooklynConfigKeys.java +++ b/core/src/main/java/org/apache/brooklyn/core/entity/BrooklynConfigKeys.java @@ -113,7 +113,7 @@ public class BrooklynConfigKeys { "Command to be run after the launch method being called on the driver"); public static final MapConfigKey SHELL_ENVIRONMENT = new MapConfigKey.Builder(Object.class, "shell.env") - .description("Map of environment variables to pass to the runtime shell") + .description("Map of environment variables to pass to the runtime shell. Non-string values are serialized to json before passed to the shell.") .defaultValue(ImmutableMap.of()) .typeInheritance(ConfigInheritance.DEEP_MERGE) .build(); 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 25ae2b5f3a..3464281d95 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 @@ -35,6 +35,7 @@ import org.apache.brooklyn.core.config.ConfigKeys; import org.apache.brooklyn.core.effector.AddSensor; import org.apache.brooklyn.core.entity.BrooklynConfigKeys; +import org.apache.brooklyn.core.entity.EntityInternal; import org.apache.brooklyn.core.sensor.http.HttpRequestSensor; import org.apache.brooklyn.feed.ssh.SshFeed; import org.apache.brooklyn.feed.ssh.SshPollConfig; @@ -42,6 +43,7 @@ import org.apache.brooklyn.util.collections.MutableMap; import org.apache.brooklyn.util.core.config.ConfigBag; import org.apache.brooklyn.util.core.flags.TypeCoercions; +import org.apache.brooklyn.util.core.json.ShellEnvironmentSerializer; import org.apache.brooklyn.util.os.Os; import org.apache.brooklyn.util.text.Strings; @@ -85,7 +87,9 @@ public void apply(final EntityLocal entity) { Supplier> envSupplier = new Supplier>() { @Override public Map get() { - return MutableMap.copyOf(Strings.toStringMap(entity.getConfig(BrooklynConfigKeys.SHELL_ENVIRONMENT), "")); + Map env = entity.getConfig(BrooklynConfigKeys.SHELL_ENVIRONMENT); + ShellEnvironmentSerializer envSerializer = new ShellEnvironmentSerializer(((EntityInternal)entity).getManagementContext()); + return envSerializer.serialize(env); } }; diff --git a/software/base/src/main/java/org/apache/brooklyn/entity/software/base/ShellEnvironmentSerializer.java b/core/src/main/java/org/apache/brooklyn/util/core/json/ShellEnvironmentSerializer.java similarity index 68% rename from software/base/src/main/java/org/apache/brooklyn/entity/software/base/ShellEnvironmentSerializer.java rename to core/src/main/java/org/apache/brooklyn/util/core/json/ShellEnvironmentSerializer.java index 9b71b8ba9d..9ec0881d40 100644 --- a/software/base/src/main/java/org/apache/brooklyn/entity/software/base/ShellEnvironmentSerializer.java +++ b/core/src/main/java/org/apache/brooklyn/util/core/json/ShellEnvironmentSerializer.java @@ -13,14 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.brooklyn.entity.software.base; +package org.apache.brooklyn.util.core.json; + +import java.util.Map; +import java.util.Map.Entry; + +import javax.annotation.Nullable; import org.apache.brooklyn.api.mgmt.ManagementContext; -import org.apache.brooklyn.util.core.json.BrooklynObjectsJsonMapper; import org.apache.brooklyn.util.exceptions.Exceptions; +import org.apache.commons.lang3.StringUtils; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.collect.Maps; public class ShellEnvironmentSerializer { private ObjectMapper mapper; @@ -44,8 +50,26 @@ public String serialize(Object value) { throw Exceptions.propagate(e); } } + + public Map serialize(@Nullable Map env) { + if (env == null) { + return null; + } + Map serializedEnv = Maps.newHashMap(); + for (Entry entry : env.entrySet()) { + String key = serializeShellEnv(entry.getKey()); + String value = serializeShellEnv(entry.getValue()); + serializedEnv.put(key, value); + } + return serializedEnv; + } protected boolean isJsonString(String str) { return str.length() > 0 && str.charAt(0) == '"'; } + + private String serializeShellEnv(Object value) { + return StringUtils.defaultString(serialize(value)); + } + } diff --git a/software/base/src/main/java/org/apache/brooklyn/entity/software/base/AbstractSoftwareProcessSshDriver.java b/software/base/src/main/java/org/apache/brooklyn/entity/software/base/AbstractSoftwareProcessSshDriver.java index c3a55674aa..a1f2f87ba1 100644 --- a/software/base/src/main/java/org/apache/brooklyn/entity/software/base/AbstractSoftwareProcessSshDriver.java +++ b/software/base/src/main/java/org/apache/brooklyn/entity/software/base/AbstractSoftwareProcessSshDriver.java @@ -25,7 +25,6 @@ import java.io.InputStream; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.Set; import org.apache.brooklyn.api.entity.EntityLocal; @@ -45,6 +44,7 @@ import org.apache.brooklyn.location.ssh.SshMachineLocation; import org.apache.brooklyn.util.core.internal.ssh.SshTool; import org.apache.brooklyn.util.core.internal.ssh.sshj.SshjTool; +import org.apache.brooklyn.util.core.json.ShellEnvironmentSerializer; import org.apache.brooklyn.util.core.task.DynamicTasks; import org.apache.brooklyn.util.core.task.Tasks; import org.apache.brooklyn.util.core.task.system.ProcessTaskWrapper; @@ -56,7 +56,6 @@ import org.apache.brooklyn.util.text.StringPredicates; import org.apache.brooklyn.util.text.Strings; import org.apache.brooklyn.util.time.Duration; -import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -347,21 +346,8 @@ public void runPostLaunchCommand() { */ public Map getShellEnvironment() { Map env = entity.getConfig(SoftwareProcess.SHELL_ENVIRONMENT); - if (env == null) { - return null; - } ShellEnvironmentSerializer envSerializer = new ShellEnvironmentSerializer(((EntityInternal)entity).getManagementContext()); - Map serializedEnv = Maps.newHashMap(); - for (Entry entry : env.entrySet()) { - String key = serializeShellEnv(envSerializer, entry.getKey()); - String value = serializeShellEnv(envSerializer, entry.getValue()); - serializedEnv.put(key, value); - } - return serializedEnv; - } - - private String serializeShellEnv(ShellEnvironmentSerializer envSerializer, Object value) { - return StringUtils.defaultString(envSerializer.serialize(value)); + return envSerializer.serialize(env); } /** diff --git a/software/base/src/test/java/org/apache/brooklyn/entity/software/base/ShellEnvironmentSerializerTest.java b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/ShellEnvironmentSerializerTest.java index 5a44da5ba4..9eb157552a 100644 --- a/software/base/src/test/java/org/apache/brooklyn/entity/software/base/ShellEnvironmentSerializerTest.java +++ b/software/base/src/test/java/org/apache/brooklyn/entity/software/base/ShellEnvironmentSerializerTest.java @@ -20,6 +20,7 @@ import java.util.Date; import org.apache.brooklyn.core.test.BrooklynAppUnitTestSupport; +import org.apache.brooklyn.util.core.json.ShellEnvironmentSerializer; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; diff --git a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSshCommandImpl.java b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSshCommandImpl.java index 33321e9d7b..19f85899fb 100644 --- a/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSshCommandImpl.java +++ b/test-framework/src/main/java/org/apache/brooklyn/test/framework/TestSshCommandImpl.java @@ -45,6 +45,7 @@ import org.apache.brooklyn.core.location.Machines; import org.apache.brooklyn.location.ssh.SshMachineLocation; import org.apache.brooklyn.util.collections.MutableList; +import org.apache.brooklyn.util.core.json.ShellEnvironmentSerializer; import org.apache.brooklyn.util.core.task.DynamicTasks; import org.apache.brooklyn.util.core.task.ssh.SshTasks; import org.apache.brooklyn.util.core.task.system.ProcessTaskWrapper; @@ -172,7 +173,8 @@ private Result executeCommand(SshMachineLocation machineLocation) { String downloadUrl = getConfig(DOWNLOAD_URL); String command = getConfig(COMMAND); - Map env = getConfig(SHELL_ENVIRONMENT); + ShellEnvironmentSerializer envSerializer = new ShellEnvironmentSerializer(getManagementContext()); + Map env = envSerializer.serialize(getConfig(SHELL_ENVIRONMENT)); if (env == null) env = ImmutableMap.of(); if (isNonBlank(downloadUrl)) { @@ -217,7 +219,7 @@ protected void handle(Result result) { support.validate(); } - private Result executeDownloadedScript(SshMachineLocation machineLocation, String url, String scriptPath, Map env) { + private Result executeDownloadedScript(SshMachineLocation machineLocation, String url, String scriptPath, Map env) { TaskFactory install = SshTasks.installFromUrl(ImmutableMap.of(), machineLocation, url, scriptPath); DynamicTasks.queue(install); @@ -232,7 +234,7 @@ private Result executeDownloadedScript(SshMachineLocation machineLocation, Strin return runCommands(machineLocation, commands, env); } - private Result executeShellCommand(SshMachineLocation machineLocation, String command, Map env) { + private Result executeShellCommand(SshMachineLocation machineLocation, String command, Map env) { List commands = ImmutableList.builder() .addAll(maybeCdToRunDirCmd()) @@ -251,10 +253,10 @@ private List maybeCdToRunDirCmd() { } } - private Result runCommands(SshMachineLocation machine, List commands, Map env) { + private Result runCommands(SshMachineLocation machine, List commands, Map env) { @SuppressWarnings({ "unchecked", "rawtypes" }) SshEffectorTasks.SshEffectorTaskFactory etf = SshEffectorTasks.ssh(commands.toArray(new String[]{})) - .environmentVariables((Map)(Map)env) + .environmentVariables(env) .machine(machine); ProcessTaskWrapper job = DynamicTasks.queue(etf);