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 72784da3f0a2276f92f3e1df1fd62afdbf6bc0c1 Author: Alex Heneveld <a...@cloudsoft.io> AuthorDate: Tue Feb 13 09:51:24 2024 +0000 infer type as a subworkflow step if `step` is omitted but `steps` are supplied --- .../core/workflow/WorkflowExecutionContext.java | 3 ++- .../core/workflow/WorkflowStepResolution.java | 26 ++++++++++++---------- .../WorkflowSubAndCustomExtensionEdgeTest.java | 25 ++++++++++++++++----- 3 files changed, 35 insertions(+), 19 deletions(-) diff --git a/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowExecutionContext.java b/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowExecutionContext.java index f154d92df3..302ef6144e 100644 --- a/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowExecutionContext.java +++ b/core/src/main/java/org/apache/brooklyn/core/workflow/WorkflowExecutionContext.java @@ -557,7 +557,8 @@ public class WorkflowExecutionContext { } log.debug("Request to replay resuming " + WorkflowExecutionContext.this + " at non-idempotent step; rolling back to " + replayableLastStep); if (replayableLastStep == null) { - throw new IllegalArgumentException("Cannot replay resuming as there are no replay points and last step " + currentStepIndex + " is not idempotent"); + throw new IllegalArgumentException("Cannot replay resuming as there are no replay points and last step " + currentStepIndex + " is not idempotent; " + + "should that step or a previous one declare 'idempotent: true' or 'replayable: from here' ?"); } return makeInstructionsForReplayingFromStep(replayableLastStep, reason, false); } 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 2d17c6cdf3..e127e782fa 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 @@ -97,20 +97,22 @@ public class WorkflowStepResolution { Object s = defM.remove("step"); if (s == null) s = defM.remove("shorthand"); if (s == null) s = defM.remove("s"); - if (s == null) { - if (defM.size()==1) { - // assume the colon caused it accidentally to be a map - s = Iterables.getOnlyElement(defM.keySet()); - if (s instanceof String && ((String)s).contains(" ")) { - s = s + " : " + Iterables.getOnlyElement(defM.values()); - } else { - s = null; - } - } - if (s==null) { - throw new IllegalArgumentException("Step definition must indicate a `type` or a `step` / `shorthand` / `s` (" + def + ")"); + if (s==null && defM.containsKey("steps")) { + // if it has steps, but no step or s, assume it is a subworkflow + s = "subworkflow"; + } + if (s == null && defM.size()==1) { + // assume the colon caused it accidentally to be a map + s = Iterables.getOnlyElement(defM.keySet()); + if (s instanceof String && ((String)s).contains(" ")) { + s = s + " : " + Iterables.getOnlyElement(defM.values()); + } else { + s = null; } } + if (s==null) { + throw new IllegalArgumentException("Step definition must indicate a `type` or a `step` / `shorthand` / `s` (" + def + ")"); + } if (!(s instanceof String)) { throw new IllegalArgumentException("step shorthand must be a string"); } diff --git a/core/src/test/java/org/apache/brooklyn/core/workflow/WorkflowSubAndCustomExtensionEdgeTest.java b/core/src/test/java/org/apache/brooklyn/core/workflow/WorkflowSubAndCustomExtensionEdgeTest.java index dc6fe61ffc..6431170142 100644 --- a/core/src/test/java/org/apache/brooklyn/core/workflow/WorkflowSubAndCustomExtensionEdgeTest.java +++ b/core/src/test/java/org/apache/brooklyn/core/workflow/WorkflowSubAndCustomExtensionEdgeTest.java @@ -143,18 +143,31 @@ public class WorkflowSubAndCustomExtensionEdgeTest extends RebindTestFixture<Tes @Test public void testSubWorkflowStep() throws Exception { + MutableList<String> steps = MutableList.of( + "let v0 = ${v0}B", + "let v1 = ${v1}B", + "let v3 = V3B", + "return done"); runWorkflow(MutableList.of( "let v1 = V1", "let v2 = V2", - MutableMap.of("step", "subworkflow", - "steps", MutableList.of( - "let v0 = ${v0}B", - "let v1 = ${v1}B", - "let v3 = V3B", - "return done")), + MutableMap.of( + "step", "subworkflow", + "steps", steps), "return ${v0}-${v1}-${v2}-${v3}-${output}"), ConfigBag.newInstance().configure(WorkflowCommonConfig.INPUT, MutableMap.of("v0", "V0")) ); Asserts.assertEquals(lastInvocation.getUnchecked(), "V0B-V1B-V2-V3B-done"); + + // subworkflow is chosen implicitly if step is omitted + runWorkflow(MutableList.of( + "let v1 = V1", + "let v2 = V2", + MutableMap.of( + //"step", "subworkflow", + "steps", steps), + "return ${v0}-${v1}-${v2}-${v3}-${output}"), + ConfigBag.newInstance().configure(WorkflowCommonConfig.INPUT, MutableMap.of("v0", "V0")) ); + Asserts.assertEquals(lastInvocation.getUnchecked(), "V0B-V1B-V2-V3B-done"); } }