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 2022/10/21 13:57:54 UTC

[brooklyn-server] 02/11: make step output available on errors, and improve short name metadata for types

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 84876d12fde500c4054228a7fa22516e98fafb2f
Author: Alex Heneveld <al...@cloudsoft.io>
AuthorDate: Wed Oct 19 15:55:18 2022 +0100

    make step output available on errors, and improve short name metadata for types
---
 .../brooklyn/core/workflow/WorkflowStepDefinition.java       |  8 +++++++-
 .../core/workflow/WorkflowStepInstanceExecutionContext.java  |  7 +++++++
 .../brooklyn/core/workflow/WorkflowStepResolution.java       |  3 +++
 .../brooklyn/core/workflow/steps/HttpWorkflowStep.java       |  4 +++-
 .../apache/brooklyn/core/workflow/steps/SshWorkflowStep.java |  9 ++++++---
 .../org/apache/brooklyn/core/workflow/WorkflowBasicTest.java | 12 ++++++++++--
 .../core/workflow/WorkflowPersistReplayErrorsTest.java       |  2 +-
 7 files changed, 37 insertions(+), 8 deletions(-)

diff --git a/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowStepDefinition.java b/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowStepDefinition.java
index 92532a0bc9..9a2d5b2d05 100644
--- a/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowStepDefinition.java
+++ b/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowStepDefinition.java
@@ -43,6 +43,7 @@ import javax.annotation.Nonnull;
 import java.util.List;
 import java.util.Map;
 
+@JsonInclude(JsonInclude.Include.NON_EMPTY)
 public abstract class WorkflowStepDefinition {
 
     private static final Logger log = LoggerFactory.getLogger(WorkflowStepDefinition.class);
@@ -59,6 +60,7 @@ public abstract class WorkflowStepDefinition {
     }
 
     protected String userSuppliedShorthand;
+    protected String shorthandTypeName;
 
     @JsonInclude(JsonInclude.Include.NON_EMPTY)
     protected Map<String,Object> input = MutableMap.of();
@@ -229,7 +231,11 @@ public abstract class WorkflowStepDefinition {
         return Strings.join(parts, " - ");
     }
 
-    protected String getShorthandTypeName() {
+    public void setShorthandTypeName(String shorthandTypeDefinition) { this.shorthandTypeName = shorthandTypeDefinition; }
+    @JsonProperty("shorthandTypeName")  // REST API should prefer this accessor
+    public String getShorthandTypeName() {
+        if (Strings.isNonBlank(shorthandTypeName)) return shorthandTypeName;
+
         String name = getClass().getSimpleName();
         if (Strings.isBlank(name)) return getClass().getCanonicalName();
         name = Strings.removeFromEnd(name, "WorkflowStep");
diff --git a/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowStepInstanceExecutionContext.java b/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowStepInstanceExecutionContext.java
index 85d238e552..b3bc5065f5 100644
--- a/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowStepInstanceExecutionContext.java
+++ b/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowStepInstanceExecutionContext.java
@@ -136,6 +136,13 @@ public class WorkflowStepInstanceExecutionContext {
         return context;
     }
 
+    public Object getOutput() {
+        return output;
+    }
+    public void setOutput(Object output) {
+        this.output = output;
+    }
+
     @JsonIgnore
     public Object getPreviousStepOutput() {
         return getWorkflowExectionContext().getPreviousStepOutput();
diff --git a/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowStepResolution.java b/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowStepResolution.java
index 439e0ffe78..464f7f217f 100644
--- a/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowStepResolution.java
+++ b/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowStepResolution.java
@@ -105,6 +105,9 @@ public class WorkflowStepResolution {
             if (userSuppliedShorthand!=null) {
                 defW.userSuppliedShorthand = userSuppliedShorthand;
             }
+            if (typeBestGuess!=null) {
+                defW.shorthandTypeName = typeBestGuess;
+            }
 
             List<Object> onError = defW.getOnError();
             if (onError!=null && !onError.isEmpty()) {
diff --git a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/HttpWorkflowStep.java b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/HttpWorkflowStep.java
index 8a4988029b..d003510cc5 100644
--- a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/HttpWorkflowStep.java
+++ b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/HttpWorkflowStep.java
@@ -160,8 +160,10 @@ public class HttpWorkflowStep extends WorkflowStepDefinition {
         Predicate<Integer> exitcode = context.getInput(STATUS_CODE);
         if (exitcode==null) exitcode = code -> HttpTool.isStatusCodeHealthy(code);
 
+        context.setOutput(MutableMap.of("status_code", response.code(), "headers", response.headers(), "content", contentString, "content_bytes", contentBytes, "duration", Duration.millis(endTime - startTime)));
+        // make sure the output is set even if there is an error
         checkExitCode(response.code(), exitcode);
-        return MutableMap.of("status_code", response.code(), "headers", response.headers(), "content", contentString, "content_bytes", contentBytes, "duration", Duration.millis(endTime - startTime));
+        return context.getOutput();
     }
 
     protected void checkExitCode(Integer code, Predicate<Integer> exitcode) {
diff --git a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/SshWorkflowStep.java b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/SshWorkflowStep.java
index 5b084c8bd9..8db28cbd51 100644
--- a/core/src/main/java/org/apache/brooklyn/core/workflow/steps/SshWorkflowStep.java
+++ b/core/src/main/java/org/apache/brooklyn/core/workflow/steps/SshWorkflowStep.java
@@ -34,6 +34,7 @@ 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.text.Strings;
+import org.apache.brooklyn.util.time.Duration;
 
 import java.util.Map;
 
@@ -75,10 +76,12 @@ public class SshWorkflowStep extends WorkflowStepDefinition {
         Map<String, Object> env = context.getInput(ENV);
         if (env!=null) tf.environmentVariables(new ShellEnvironmentSerializer(context.getWorkflowExectionContext().getManagementContext()).serialize(env));
         return tf.returning(ptw -> {
-            checkExitCode(ptw, exitcode);
-            return MutableMap.of("stdout", ptw.getStdout(),
+            context.setOutput(MutableMap.of("stdout", ptw.getStdout(),
                     "stderr", ptw.getStderr(),
-                    "exit_code", ptw.getExitCode());
+                    "exit_code", ptw.getExitCode()));
+            // make sure the output is set even if there is an error
+            checkExitCode(ptw, exitcode);
+            return (Map<?,?>) context.getOutput();
         });
     }
 
diff --git a/core/src/test/java/org/apache/brooklyn/core/workflow/WorkflowBasicTest.java b/core/src/test/java/org/apache/brooklyn/core/workflow/WorkflowBasicTest.java
index e1cf23932a..08c5f7f467 100644
--- a/core/src/test/java/org/apache/brooklyn/core/workflow/WorkflowBasicTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/workflow/WorkflowBasicTest.java
@@ -46,8 +46,10 @@ import org.apache.brooklyn.test.ClassLogWatcher;
 import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.collections.MutableMap;
 import org.apache.brooklyn.util.core.config.ConfigBag;
+import org.apache.brooklyn.util.core.json.BrooklynObjectsJsonMapper;
 import org.apache.brooklyn.util.exceptions.Exceptions;
 import org.apache.brooklyn.util.time.Duration;
+import org.apache.brooklyn.util.yaml.Yamls;
 import org.testng.annotations.Test;
 
 import java.io.IOException;
@@ -122,14 +124,20 @@ public class WorkflowBasicTest extends BrooklynMgmtUnitTestSupport {
     }
 
     @Test
-    public void testShorthandStepResolution() {
+    public void testShorthandStepResolution() throws JsonProcessingException {
         loadTypes();
         String input = "sleep 1s";
 
-        // only util will work for shorthand
+        // jackson doesn't handle shorthand; our custom method does that
         WorkflowStepDefinition s = WorkflowStepResolution.resolveStep(mgmt, input);
         Asserts.assertInstanceOf(s, SleepWorkflowStep.class);
         Asserts.assertEquals( Duration.of(s.getInput().get(SleepWorkflowStep.DURATION.getName())), Duration.ONE_SECOND);
+
+        String output1 = BrooklynObjectsJsonMapper.newDslToStringSerializingMapper(mgmt).writeValueAsString(s);
+        String output2 = BeanWithTypeUtils.newYamlMapper(mgmt, false, null, false).writerFor(Object.class).writeValueAsString(s);
+
+        Asserts.assertStringContains(output1, "\"shorthandTypeName\":\"sleep\"");
+        Asserts.assertStringContains(output2, "shorthandTypeName: \"sleep\"");
     }
 
     @Test
diff --git a/core/src/test/java/org/apache/brooklyn/core/workflow/WorkflowPersistReplayErrorsTest.java b/core/src/test/java/org/apache/brooklyn/core/workflow/WorkflowPersistReplayErrorsTest.java
index 3987e3cfdb..049a69235d 100644
--- a/core/src/test/java/org/apache/brooklyn/core/workflow/WorkflowPersistReplayErrorsTest.java
+++ b/core/src/test/java/org/apache/brooklyn/core/workflow/WorkflowPersistReplayErrorsTest.java
@@ -577,7 +577,7 @@ public class WorkflowPersistReplayErrorsTest extends RebindTestFixture<BasicAppl
                     m -> m.matches("Encountered error in workflow .*/.* 'myWorkflow' .handler present.: No effector matching 'does-not-exist'"),
                     m -> m.matches("Creating workflow .* error handler .*-error-handler in task .*"),
                     m -> m.matches("Starting .*-error-handler with 1 handler in task .*"),
-                    m -> m.matches("Creating handler .*-error-handler-1 'NoOp' in task .*"),
+                    m -> m.matches("Creating handler .*-error-handler-1 'no-op' in task .*"),
                     m -> m.matches("Starting .*-error-handler-1 in task .*"),
                     m -> m.matches("Completed handler .*-error-handler-1; proceeding to default next step"),
                     m -> m.matches("Handled error in workflow around step .*-1; explicit next 'end': Workflow completed")));