diff --git a/engine/engine_test.go b/engine/engine_test.go index d89c2fad..488615c5 100644 --- a/engine/engine_test.go +++ b/engine/engine_test.go @@ -235,6 +235,29 @@ func TestFunctionCustomState(t *testing.T) { assert.Equal(t, []string{"STATE_HELLO"}, customStates) } +func TestFunctionConditions(t *testing.T) { + input := map[string]interface{}{} + res, err := runTask("functionConditions.yaml", input, nil) + + require.Nil(t, err) + + assert.Equal(t, map[string]interface{}{ + "value": "Hello foobar !", + }, res.Steps["asExpected"].Output) + assert.Equal(t, "SAID_HELLO", res.Steps["asExpected"].State) + assert.Equal(t, "Said hello to foobar", res.Steps["asExpected"].Error) + + assert.Equal(t, map[string]interface{}{ + "value": "Hello foo !", + }, res.Steps["notExpected"].Output) + assert.Equal(t, "NOT_EXPECTED", res.Steps["notExpected"].State) + assert.Equal(t, "Expected bar, got foo", res.Steps["notExpected"].Error) + + assert.Nil(t, res.Steps["skipped"].Output) + assert.Equal(t, "PRUNE", res.Steps["skipped"].State) + assert.Equal(t, "No hello foo !", res.Steps["skipped"].Error) +} + func TestFunctionPreHook(t *testing.T) { input := map[string]interface{}{} res, err := runTask("functionPreHook.yaml", input, nil) diff --git a/engine/functions_tests/hello-with-conditions.yaml b/engine/functions_tests/hello-with-conditions.yaml new file mode 100644 index 00000000..b4b27421 --- /dev/null +++ b/engine/functions_tests/hello-with-conditions.yaml @@ -0,0 +1,34 @@ +name: hello-with-conditions +description: Say hello with conditions +action: + type: echo::hello::world + configuration: + name: '{{.function_args.name}}' +custom_states: + - SAID_HELLO + - NOT_EXPECTED +conditions: + - type: skip + if: + - value: '{{.function_args.skip | default `false`}}' + operator: EQ + expected: 'true' + then: + this: PRUNE + message: 'No hello {{.function_args.name}} !' + - type: check + if: + - value: '{{.function_args.name}}' + operator: NE + expected: '{{.function_args.expected}}' + then: + this: NOT_EXPECTED + message: 'Expected {{.function_args.expected}}, got {{.function_args.name}}' + - type: check + if: + - value: '{{.function_args.name}}' + operator: EQ + expected: '{{.function_args.expected}}' + then: + this: SAID_HELLO + message: 'Said hello to {{.function_args.name}}' diff --git a/engine/functions_tests/nested1.yaml b/engine/functions_tests/nested1.yaml index 05a60df7..c50c0bf2 100644 --- a/engine/functions_tests/nested1.yaml +++ b/engine/functions_tests/nested1.yaml @@ -16,5 +16,8 @@ conditions: - value: '{{.step.this.state}}' operator: EQ expected: 'NESTED2_STATE2' + - value: '{{ .function_args.name }}' + operator: EQ + expected: foobar then: this: NESTED1_STATE diff --git a/engine/functions_tests/nested2.yaml b/engine/functions_tests/nested2.yaml index 0f4f9b29..9d065c3c 100644 --- a/engine/functions_tests/nested2.yaml +++ b/engine/functions_tests/nested2.yaml @@ -22,6 +22,9 @@ conditions: - value: '{{.step.this.state}}' operator: EQ expected: 'NESTED2_STATE1' + - value: '{{ .function_args.name1 }}' + operator: EQ + expected: foobar then: this: NESTED2_STATE2 diff --git a/engine/step/step.go b/engine/step/step.go index 4104469e..50f8fdce 100644 --- a/engine/step/step.go +++ b/engine/step/step.go @@ -477,6 +477,23 @@ func PreRun(st *Step, values *values.Values, ss StateSetter, executedSteps map[s return } + // Check if we have a function as runner or not. + runner, err := getRunner(st.Action.Type) + if err != nil { + ss(st.Name, StateServerError, err.Error()) + return + } + + _, isFunction := runner.(*functions.Function) + if isFunction { + var functionInput map[string]interface{} + if err := utils.JSONnumberUnmarshal(bytes.NewBuffer(st.Action.Configuration), &functionInput); err != nil { + ss(st.Name, StateServerError, err.Error()) + return + } + values.SetFunctionsArgs(functionInput) + } + for _, sc := range conditions { if sc.Type != condition.SKIP { continue @@ -521,6 +538,23 @@ func AfterRun(st *Step, values *values.Values, ss StateSetter) { return } + // Check if we have a function as runner or not. + runner, err := getRunner(st.Action.Type) + if err != nil { + ss(st.Name, StateServerError, err.Error()) + return + } + + _, isFunction := runner.(*functions.Function) + if isFunction { + var functionInput map[string]interface{} + if err := utils.JSONnumberUnmarshal(bytes.NewBuffer(st.Action.Configuration), &functionInput); err != nil { + ss(st.Name, StateServerError, err.Error()) + return + } + values.SetFunctionsArgs(functionInput) + } + for _, sc := range conditions { if sc.Type != condition.CHECK { continue diff --git a/engine/templates_tests/functionConditions.yaml b/engine/templates_tests/functionConditions.yaml new file mode 100644 index 00000000..f3a325b9 --- /dev/null +++ b/engine/templates_tests/functionConditions.yaml @@ -0,0 +1,29 @@ +name: functionConditions +description: Test function conditions +title_format: "[test] Test function conditions" +auto_runnable: true +steps: + asExpected: + description: Say hello to foobar + action: + type: hello-with-conditions + configuration: + name: foobar + expected: foobar + + notExpected: + description: Say hello to foo but expect bar + action: + type: hello-with-conditions + configuration: + name: foo + expected: bar + + skipped: + description: Say hello to foo but skipping step before it starts + action: + type: hello-with-conditions + configuration: + name: foo + expected: foor + skip: true