This is an automated email from the ASF dual-hosted git repository.

heneveld pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/brooklyn-server.git

commit 26b1a9a0895f5fcc349e093bfd77604025b51aa5
Author: Alex Heneveld <[email protected]>
AuthorDate: Fri Mar 24 08:43:22 2023 +0000

    allow configurable interpolation mode on more workflow steps - blueprints 
and commands
---
 .../steps/appmodel/AddEntityWorkflowStep.java      | 24 +++----
 .../steps/appmodel/AddPolicyWorkflowStep.java      | 24 +++----
 .../appmodel/ApplyInitializerWorkflowStep.java     | 22 ++----
 .../appmodel/DeployApplicationWorkflowStep.java    | 25 +++----
 .../steps/appmodel/HasBlueprintWorkflowStep.java   | 78 ++++++++++++++++++++++
 .../workflow/steps/external/SshWorkflowStep.java   |  9 ++-
 .../brooklyn/location/winrm/WinrmWorkflowStep.java |  8 ++-
 7 files changed, 123 insertions(+), 67 deletions(-)

diff --git 
a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/AddEntityWorkflowStep.java
 
b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/AddEntityWorkflowStep.java
index ce38235543..4713391a9f 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/AddEntityWorkflowStep.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/AddEntityWorkflowStep.java
@@ -42,9 +42,11 @@ import 
org.apache.brooklyn.core.workflow.WorkflowExecutionContext;
 import org.apache.brooklyn.core.workflow.WorkflowStepDefinition;
 import org.apache.brooklyn.core.workflow.WorkflowStepInstanceExecutionContext;
 import 
org.apache.brooklyn.core.workflow.steps.appmodel.DeployApplicationWorkflowStep.StartMode;
+import 
org.apache.brooklyn.core.workflow.steps.variables.SetVariableWorkflowStep;
 import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.core.task.Tasks;
+import org.apache.brooklyn.util.core.text.TemplateProcessor;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.text.Identifiers;
@@ -57,24 +59,21 @@ import javax.annotation.Nullable;
 import java.util.List;
 import java.util.Map;
 
-public class AddEntityWorkflowStep extends WorkflowStepDefinition {
+public class AddEntityWorkflowStep extends WorkflowStepDefinition implements 
HasBlueprintWorkflowStep {
 
     private static final Logger LOG = 
LoggerFactory.getLogger(AddEntityWorkflowStep.class);
 
     public static final String SHORTHAND = "[ ${type} ]";
 
-    public static final ConfigKey<Object> BLUEPRINT = 
ConfigKeys.newConfigKey(Object.class, "blueprint");
-    public static final ConfigKey<String> TYPE = 
ConfigKeys.newStringConfigKey("type");
     public static final ConfigKey<String> FORMAT = 
ConfigKeys.newStringConfigKey("format");
 
     // sync is not completely idempotent (in the call to start it) but very 
useful for testing;
     // option not included in documentation, but used for tests
     public static final ConfigKey<StartMode> START = 
ConfigKeys.newConfigKey(StartMode.class, "start", "Default 'async'");
 
-    // don't try to instantiate 'type' here
-    @JsonDeserialize(using = JsonPassThroughDeserializer.class)
-    void setBlueprint(Object blueprint) {
-        setInput(BLUEPRINT, blueprint);
+    @Override
+    public Logger logger() {
+        return LOG;
     }
 
     @Override
@@ -85,11 +84,7 @@ public class AddEntityWorkflowStep extends 
WorkflowStepDefinition {
     @Override
     public void validateStep(@Nullable ManagementContext mgmt, @Nullable 
WorkflowExecutionContext workflow) {
         super.validateStep(mgmt, workflow);
-
-        boolean hasBlueprint = getInput().containsKey(BLUEPRINT.getName());
-        boolean hasType = getInput().containsKey(TYPE.getName());
-        if (!hasBlueprint && !hasType) throw new IllegalArgumentException("A 
'"+BLUEPRINT.getName()+"' must be defined or a type supplied in shorthand");
-        if (hasBlueprint && hasType) throw new 
IllegalArgumentException("Cannot provide both a '"+BLUEPRINT.getName()+"' and a 
type in shorthand");
+        validateStepBlueprint(mgmt, workflow);
     }
 
     @Override
@@ -102,10 +97,7 @@ public class AddEntityWorkflowStep extends 
WorkflowStepDefinition {
 
     @Override
     protected Object doTaskBody(WorkflowStepInstanceExecutionContext context) {
-        Object blueprint = input.get(BLUEPRINT.getName());
-        if (blueprint == null) {
-            blueprint = "type: " + 
StringEscapes.JavaStringEscapes.wrapJavaString(context.getInput(TYPE));
-        }
+        Object blueprint = resolveBlueprint(context);
 
         List<String> preCreatedEntityIds = 
Maybe.ofDisallowingNull(getStepState(context)).map(MutableList::copyOf).orNull();
         List<String> newCreatedEntityIds = MutableList.of();
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/AddPolicyWorkflowStep.java
 
b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/AddPolicyWorkflowStep.java
index 2ec1ab42eb..8995389c25 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/AddPolicyWorkflowStep.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/AddPolicyWorkflowStep.java
@@ -48,7 +48,7 @@ import org.slf4j.LoggerFactory;
 
 import javax.annotation.Nullable;
 
-public class AddPolicyWorkflowStep extends WorkflowStepDefinition {
+public class AddPolicyWorkflowStep extends WorkflowStepDefinition implements 
HasBlueprintWorkflowStep {
 
     private static final Logger LOG = 
LoggerFactory.getLogger(AddPolicyWorkflowStep.class);
 
@@ -60,24 +60,19 @@ public class AddPolicyWorkflowStep extends 
WorkflowStepDefinition {
     public static final ConfigKey<Object> ENTITY = 
ConfigKeys.newConfigKey(Object.class, "entity");
 
     @Override
-    public void populateFromShorthand(String expression) {
-        populateFromShorthandTemplate(SHORTHAND, expression);
+    public Logger logger() {
+        return LOG;
     }
 
-    // don't try to instantiate 'type' here
-    @JsonDeserialize(using = JsonPassThroughDeserializer.class)
-    void setBlueprint(Object blueprint) {
-        setInput(BLUEPRINT, blueprint);
+    @Override
+    public void populateFromShorthand(String expression) {
+        populateFromShorthandTemplate(SHORTHAND, expression);
     }
 
     @Override
     public void validateStep(@Nullable ManagementContext mgmt, @Nullable 
WorkflowExecutionContext workflow) {
         super.validateStep(mgmt, workflow);
-
-        boolean hasBlueprint = getInput().containsKey(BLUEPRINT.getName());
-        boolean hasType = getInput().containsKey(TYPE.getName());
-        if (!hasBlueprint && !hasType) throw new IllegalArgumentException("A 
'"+BLUEPRINT.getName()+"' must be defined or a type supplied in shorthand");
-        if (hasBlueprint && hasType) throw new 
IllegalArgumentException("Cannot provide both a '"+BLUEPRINT.getName()+"' and a 
type in shorthand");
+        validateStepBlueprint(mgmt, workflow);
     }
 
     @Override
@@ -85,10 +80,7 @@ public class AddPolicyWorkflowStep extends 
WorkflowStepDefinition {
         Object entityToFind = context.getInput(ENTITY);
         Entity entity = entityToFind != null ? 
DeleteEntityWorkflowStep.findEntity(context, entityToFind).get() : 
context.getEntity();
 
-        Object blueprint = input.get(BLUEPRINT.getName());
-        if (blueprint == null) {
-            blueprint = "type: " + 
StringEscapes.JavaStringEscapes.wrapJavaString(context.getInput(TYPE));
-        }
+        Object blueprint = resolveBlueprint(context);
 
         AbstractBrooklynObjectSpec spec = null;
         EntityAdjunct inst = null;
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/ApplyInitializerWorkflowStep.java
 
b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/ApplyInitializerWorkflowStep.java
index 086233982d..14d825781c 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/ApplyInitializerWorkflowStep.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/ApplyInitializerWorkflowStep.java
@@ -44,20 +44,17 @@ import org.slf4j.LoggerFactory;
 
 import javax.annotation.Nullable;
 
-public class ApplyInitializerWorkflowStep extends WorkflowStepDefinition {
+public class ApplyInitializerWorkflowStep extends WorkflowStepDefinition 
implements HasBlueprintWorkflowStep {
 
     private static final Logger LOG = 
LoggerFactory.getLogger(ApplyInitializerWorkflowStep.class);
 
     public static final String SHORTHAND = "[ ${type} [ \" at \" ${entity} ] 
]";
 
-    public static final ConfigKey<Object> BLUEPRINT = 
ConfigKeys.newConfigKey(Object.class, "blueprint");
-    public static final ConfigKey<String> TYPE = 
ConfigKeys.newStringConfigKey("type");
     public static final ConfigKey<Object> ENTITY = 
ConfigKeys.newConfigKey(Object.class, "entity");
 
-    // don't try to instantiate 'type' here
-    @JsonDeserialize(using = JsonPassThroughDeserializer.class)
-    void setBlueprint(Object blueprint) {
-        setInput(BLUEPRINT, blueprint);
+    @Override
+    public Logger logger() {
+        return LOG;
     }
 
     @Override
@@ -68,11 +65,7 @@ public class ApplyInitializerWorkflowStep extends 
WorkflowStepDefinition {
     @Override
     public void validateStep(@Nullable ManagementContext mgmt, @Nullable 
WorkflowExecutionContext workflow) {
         super.validateStep(mgmt, workflow);
-
-        boolean hasBlueprint = getInput().containsKey(BLUEPRINT.getName());
-        boolean hasType = getInput().containsKey(TYPE.getName());
-        if (!hasBlueprint && !hasType) throw new IllegalArgumentException("A 
'"+BLUEPRINT.getName()+"' must be defined or a type supplied in shorthand");
-        if (hasBlueprint && hasType) throw new 
IllegalArgumentException("Cannot provide both a '"+BLUEPRINT.getName()+"' and a 
type in shorthand");
+        validateStepBlueprint(mgmt, workflow);
     }
 
     @Override
@@ -80,10 +73,7 @@ public class ApplyInitializerWorkflowStep extends 
WorkflowStepDefinition {
         Object entityToFind = context.getInput(ENTITY);
         Entity entity = entityToFind != null ? 
DeleteEntityWorkflowStep.findEntity(context, entityToFind).get() : 
context.getEntity();
 
-        Object blueprint = input.get(BLUEPRINT.getName());
-        if (blueprint == null) {
-            blueprint = "type: " + 
StringEscapes.JavaStringEscapes.wrapJavaString(context.getInput(TYPE));
-        }
+        Object blueprint = resolveBlueprint(context);
 
         EntityInitializer initializer;
         try {
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/DeployApplicationWorkflowStep.java
 
b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/DeployApplicationWorkflowStep.java
index da018209ae..a065534071 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/DeployApplicationWorkflowStep.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/DeployApplicationWorkflowStep.java
@@ -42,14 +42,12 @@ import org.slf4j.LoggerFactory;
 
 import javax.annotation.Nullable;
 
-public class DeployApplicationWorkflowStep extends WorkflowStepDefinition {
+public class DeployApplicationWorkflowStep extends WorkflowStepDefinition 
implements HasBlueprintWorkflowStep {
 
     private static final Logger LOG = 
LoggerFactory.getLogger(DeployApplicationWorkflowStep.class);
 
     public static final String SHORTHAND = "[ ${type} ]";
 
-    public static final ConfigKey<Object> BLUEPRINT = 
ConfigKeys.newConfigKey(Object.class, "blueprint");
-    public static final ConfigKey<String> TYPE = 
ConfigKeys.newStringConfigKey("type");
     public static final ConfigKey<String> FORMAT = 
ConfigKeys.newStringConfigKey("format");
 
     // sync is not completely idempotent (in the call to start it) but very 
useful for testing;
@@ -61,24 +59,19 @@ public class DeployApplicationWorkflowStep extends 
WorkflowStepDefinition {
     }
 
     @Override
-    public void populateFromShorthand(String expression) {
-        populateFromShorthandTemplate(SHORTHAND, expression);
+    public Logger logger() {
+        return LOG;
     }
 
-    // don't try to instantiate 'type' here
-    @JsonDeserialize(using = JsonPassThroughDeserializer.class)
-    void setBlueprint(Object blueprint) {
-        setInput(BLUEPRINT, blueprint);
+    @Override
+    public void populateFromShorthand(String expression) {
+        populateFromShorthandTemplate(SHORTHAND, expression);
     }
 
     @Override
     public void validateStep(@Nullable ManagementContext mgmt, @Nullable 
WorkflowExecutionContext workflow) {
         super.validateStep(mgmt, workflow);
-
-        boolean hasBlueprint = getInput().containsKey(BLUEPRINT.getName());
-        boolean hasType = getInput().containsKey(TYPE.getName());
-        if (!hasBlueprint && !hasType) throw new IllegalArgumentException("A 
'"+BLUEPRINT.getName()+"' must be defined or a type supplied in shorthand");
-        if (hasBlueprint && hasType) throw new 
IllegalArgumentException("Cannot provide both a '"+BLUEPRINT.getName()+"' and a 
type in shorthand");
+        validateStepBlueprint(mgmt, workflow);
     }
 
     @Override
@@ -91,9 +84,7 @@ public class DeployApplicationWorkflowStep extends 
WorkflowStepDefinition {
 
     @Override
     protected Object doTaskBody(WorkflowStepInstanceExecutionContext context) {
-        Object blueprint = context.getInput(BLUEPRINT);
-        if (blueprint == null)
-            blueprint = "services: [ { type: " + 
StringEscapes.JavaStringEscapes.wrapJavaString(context.getInput(TYPE)) + " } ]";
+        Object blueprint = resolveBlueprint(context, () -> "services: [ { 
type: " + 
StringEscapes.JavaStringEscapes.wrapJavaString(context.getInput(TYPE)) + " } 
]");
 
         String createdAppId = getStepState(context);
         Application app = null;
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/HasBlueprintWorkflowStep.java
 
b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/HasBlueprintWorkflowStep.java
new file mode 100644
index 0000000000..4a7d0a8547
--- /dev/null
+++ 
b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/appmodel/HasBlueprintWorkflowStep.java
@@ -0,0 +1,78 @@
+/*
+ * 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.workflow.steps.appmodel;
+
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import org.apache.brooklyn.api.mgmt.ManagementContext;
+import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.resolve.jackson.JsonPassThroughDeserializer;
+import org.apache.brooklyn.core.workflow.WorkflowExecutionContext;
+import org.apache.brooklyn.core.workflow.WorkflowStepInstanceExecutionContext;
+import 
org.apache.brooklyn.core.workflow.steps.variables.SetVariableWorkflowStep;
+import org.apache.brooklyn.util.core.text.TemplateProcessor;
+import org.apache.brooklyn.util.text.StringEscapes;
+import org.slf4j.Logger;
+
+import javax.annotation.Nullable;
+import java.util.Map;
+import java.util.function.Supplier;
+
+public interface HasBlueprintWorkflowStep {
+
+    ConfigKey<Object> BLUEPRINT = ConfigKeys.newConfigKey(Object.class, 
"blueprint");
+    ConfigKey<String> TYPE = ConfigKeys.newStringConfigKey("type");
+
+    ConfigKey<SetVariableWorkflowStep.InterpolationMode> INTERPOLATION_MODE = 
ConfigKeys.newConfigKeyWithDefault(SetVariableWorkflowStep.INTERPOLATION_MODE, 
SetVariableWorkflowStep.InterpolationMode.FULL);
+    ConfigKey<TemplateProcessor.InterpolationErrorMode> INTERPOLATION_ERRORS = 
ConfigKeys.newConfigKeyWithDefault(SetVariableWorkflowStep.INTERPOLATION_ERRORS,
 TemplateProcessor.InterpolationErrorMode.IGNORE);
+
+    Map<String, Object> getInput();
+    Logger logger();
+
+    default void validateStepBlueprint(@Nullable ManagementContext mgmt, 
@Nullable WorkflowExecutionContext workflow) {
+        boolean hasBlueprint = getInput().containsKey(BLUEPRINT.getName());
+        boolean hasType = getInput().containsKey(TYPE.getName());
+        if (!hasBlueprint && !hasType) throw new IllegalArgumentException("A 
'"+BLUEPRINT.getName()+"' must be defined or a type supplied");
+        if (hasBlueprint && hasType) throw new 
IllegalArgumentException("Cannot provide both a '"+BLUEPRINT.getName()+"' and a 
'"+TYPE.getName()+"'");
+    }
+
+    default Object resolveBlueprint(WorkflowStepInstanceExecutionContext 
context) {
+        return resolveBlueprint(context, () -> "type: " + 
StringEscapes.JavaStringEscapes.wrapJavaString(context.getInput(TYPE)));
+    }
+    default Object resolveBlueprint(WorkflowStepInstanceExecutionContext 
context, Supplier<String> defaultValue) {
+        Object blueprint = getInput().get(BLUEPRINT.getName());
+        if (blueprint == null) {
+            return defaultValue.get();
+        }
+        logger().debug("Blueprint (pre-resolution) is: "+blueprint);
+        Object result = new 
SetVariableWorkflowStep.ConfigurableInterpolationEvaluation(context, null, 
blueprint,
+                context.getInputOrDefault(INTERPOLATION_MODE), 
context.getInputOrDefault(INTERPOLATION_ERRORS)).evaluate();
+        logger().debug("Blueprint (post-resolution: 
"+context.getInputOrDefault(INTERPOLATION_MODE)+"/"+context.getInputOrDefault(INTERPOLATION_ERRORS)+")
 is: "+result);
+        return result;
+    }
+
+    <T> void setInput(ConfigKey<T> key, T value);
+
+    // don't try to instantiate 'type' here
+    @JsonDeserialize(using = JsonPassThroughDeserializer.class)
+    default void setBlueprint(Object blueprint) {
+        setInput(BLUEPRINT, blueprint);
+    }
+
+}
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/external/SshWorkflowStep.java
 
b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/external/SshWorkflowStep.java
index 9a0d7c5092..1e08d59e6e 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/external/SshWorkflowStep.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/external/SshWorkflowStep.java
@@ -25,6 +25,7 @@ import org.apache.brooklyn.core.config.MapConfigKey;
 import org.apache.brooklyn.core.location.Locations;
 import org.apache.brooklyn.core.workflow.WorkflowStepDefinition;
 import org.apache.brooklyn.core.workflow.WorkflowStepInstanceExecutionContext;
+import 
org.apache.brooklyn.core.workflow.steps.variables.SetVariableWorkflowStep;
 import org.apache.brooklyn.location.ssh.SshMachineLocation;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.core.json.ShellEnvironmentSerializer;
@@ -33,6 +34,7 @@ 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.ProcessTaskFactory;
 import org.apache.brooklyn.util.core.task.system.ProcessTaskWrapper;
+import org.apache.brooklyn.util.core.text.TemplateProcessor;
 import org.apache.brooklyn.util.text.Strings;
 import org.apache.brooklyn.util.time.Duration;
 
@@ -50,6 +52,9 @@ public class SshWorkflowStep extends WorkflowStepDefinition {
     public static final ConfigKey<DslPredicates.DslPredicate<Integer>> 
EXIT_CODE = ConfigKeys.newConfigKey(new 
TypeToken<DslPredicates.DslPredicate<Integer>>() {}, "exit_code");
     public static final ConfigKey<Integer> OUTPUT_MAX_SIZE = 
ConfigKeys.newIntegerConfigKey("output_max_size", "Maximum size for stdout and 
stderr, or -1 for no limit", 100000);
 
+    ConfigKey<SetVariableWorkflowStep.InterpolationMode> INTERPOLATION_MODE = 
ConfigKeys.newConfigKeyWithDefault(SetVariableWorkflowStep.INTERPOLATION_MODE, 
SetVariableWorkflowStep.InterpolationMode.FULL);
+    ConfigKey<TemplateProcessor.InterpolationErrorMode> INTERPOLATION_ERRORS = 
ConfigKeys.newConfigKeyWithDefault(SetVariableWorkflowStep.INTERPOLATION_ERRORS,
 TemplateProcessor.InterpolationErrorMode.IGNORE);
+
     @Override
     public void populateFromShorthand(String expression) {
         populateFromShorthandTemplate(SHORTHAND, expression);
@@ -57,7 +62,9 @@ public class SshWorkflowStep extends WorkflowStepDefinition {
 
     @Override
     protected Object doTaskBody(WorkflowStepInstanceExecutionContext context) {
-        String command = context.getInput(COMMAND);
+        String command = new 
SetVariableWorkflowStep.ConfigurableInterpolationEvaluation<>(context, 
TypeToken.of(String.class), getInput().get(COMMAND.getName()),
+                context.getInputOrDefault(INTERPOLATION_MODE), 
context.getInputOrDefault(INTERPOLATION_ERRORS)).evaluate();
+
         if (Strings.isBlank(command)) throw new 
IllegalStateException("'command' is required");
 
         SshMachineLocation machine;
diff --git 
a/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/WinrmWorkflowStep.java
 
b/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/WinrmWorkflowStep.java
index ec93d75a27..26e05d8737 100644
--- 
a/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/WinrmWorkflowStep.java
+++ 
b/software/winrm/src/main/java/org/apache/brooklyn/location/winrm/WinrmWorkflowStep.java
@@ -26,12 +26,14 @@ import org.apache.brooklyn.core.location.Machines;
 import org.apache.brooklyn.core.workflow.WorkflowStepDefinition;
 import org.apache.brooklyn.core.workflow.WorkflowStepInstanceExecutionContext;
 import org.apache.brooklyn.core.workflow.steps.external.SshWorkflowStep;
+import 
org.apache.brooklyn.core.workflow.steps.variables.SetVariableWorkflowStep;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.core.json.ShellEnvironmentSerializer;
 import org.apache.brooklyn.util.core.predicates.DslPredicates;
 import org.apache.brooklyn.util.core.task.DynamicTasks;
 import org.apache.brooklyn.util.core.task.system.ProcessTaskFactory;
 import org.apache.brooklyn.util.core.task.system.ProcessTaskWrapper;
+import org.apache.brooklyn.util.core.text.TemplateProcessor;
 import org.apache.brooklyn.util.text.Strings;
 
 import java.util.Map;
@@ -46,6 +48,9 @@ public class WinrmWorkflowStep extends WorkflowStepDefinition 
{
     public static final ConfigKey<DslPredicates.DslPredicate<Integer>> 
EXIT_CODE = ConfigKeys.newConfigKey(new 
TypeToken<DslPredicates.DslPredicate<Integer>>() {}, "exit_code");
     public static final ConfigKey<Integer> OUTPUT_MAX_SIZE = 
ConfigKeys.newIntegerConfigKey("output_max_size", "Maximum size for stdout and 
stderr, or -1 for no limit", 100000);
 
+    ConfigKey<SetVariableWorkflowStep.InterpolationMode> INTERPOLATION_MODE = 
ConfigKeys.newConfigKeyWithDefault(SetVariableWorkflowStep.INTERPOLATION_MODE, 
SetVariableWorkflowStep.InterpolationMode.FULL);
+    ConfigKey<TemplateProcessor.InterpolationErrorMode> INTERPOLATION_ERRORS = 
ConfigKeys.newConfigKeyWithDefault(SetVariableWorkflowStep.INTERPOLATION_ERRORS,
 TemplateProcessor.InterpolationErrorMode.IGNORE);
+
     @Override
     public void populateFromShorthand(String expression) {
         populateFromShorthandTemplate(SHORTHAND, expression);
@@ -53,7 +58,8 @@ public class WinrmWorkflowStep extends WorkflowStepDefinition 
{
 
     @Override
     protected Object doTaskBody(WorkflowStepInstanceExecutionContext context) {
-        String command = context.getInput(COMMAND);
+        String command = new 
SetVariableWorkflowStep.ConfigurableInterpolationEvaluation<>(context, 
TypeToken.of(String.class), getInput().get(COMMAND.getName()),
+                context.getInputOrDefault(INTERPOLATION_MODE), 
context.getInputOrDefault(INTERPOLATION_ERRORS)).evaluate();
         if (Strings.isBlank(command)) throw new 
IllegalStateException("'command' is required");
 
         WinRmMachineLocation machine;

Reply via email to