diff --git a/workflow/controller/operator.go b/workflow/controller/operator.go index 005a819b6b98..a04483b08b7d 100644 --- a/workflow/controller/operator.go +++ b/workflow/controller/operator.go @@ -2286,6 +2286,16 @@ func getStepOrDAGTaskName(nodeName string) string { return nodeName } +func extractMainCtrFromScriptTemplate(tmpl *wfv1.Template) apiv1.Container { + mainCtr := tmpl.Script.Container + // If script source is provided then pass all container args to the + // script instead of passing them to the container command directly + if tmpl.Script.Source != "" { + mainCtr.Args = append([]string{common.ExecutorScriptSourcePath}, mainCtr.Args...) + } + return mainCtr +} + func (woc *wfOperationCtx) executeScript(nodeName string, templateScope string, tmpl *wfv1.Template, orgTmpl wfv1.TemplateReferenceHolder, opts *executeTemplateOpts) (*wfv1.NodeStatus, error) { node := woc.wf.GetNodeByName(nodeName) if node == nil { @@ -2301,8 +2311,7 @@ func (woc *wfOperationCtx) executeScript(nodeName string, templateScope string, return node, err } - mainCtr := tmpl.Script.Container - mainCtr.Args = append(mainCtr.Args, common.ExecutorScriptSourcePath) + mainCtr := extractMainCtrFromScriptTemplate(tmpl) _, err = woc.createWorkflowPod(nodeName, mainCtr, tmpl, &createWorkflowPodOpts{ includeScriptOutput: includeScriptOutput, onExitPod: opts.onExitTemplate, diff --git a/workflow/controller/workflowpod_test.go b/workflow/controller/workflowpod_test.go index 6a4734bd4564..019c07ea8b49 100644 --- a/workflow/controller/workflowpod_test.go +++ b/workflow/controller/workflowpod_test.go @@ -69,6 +69,42 @@ func TestScriptTemplateWithVolume(t *testing.T) { assert.NoError(t, err) } +var scriptTemplateWithArgsAndWithSource = ` +name: script-with-args-and-with-source +script: + image: alpine:latest + command: [sh] + args: ["hello world"] + source: | + echo $@ +` + +// TestScriptTemplateMainCtrArgsWhenArgsAndWhenSource ensure order of merged args +// and script path is correct when both args and script source are specified +func TestScriptTemplateMainCtrArgsWhenArgsAndWhenSource(t *testing.T) { + tmpl := unmarshalTemplate(scriptTemplateWithArgsAndWithSource) + mainCtr := extractMainCtrFromScriptTemplate(tmpl) + assert.Equal(t, []string{"sh"}, mainCtr.Command) + assert.Equal(t, []string{common.ExecutorScriptSourcePath, "hello world"}, mainCtr.Args) +} + +var scriptTemplateWithArgsAndWithoutSource = ` +name: script-with-args-and-without-source +script: + image: alpine:latest + command: [echo] + args: ["hello world"] +` + +// TestScriptTemplateMainCtrArgsWhenArgsAndWhenNoSource ensure only args are passed +// to the resulting container when script source is empty +func TestScriptTemplateMainCtrArgsWhenArgsAndWhenNoSource(t *testing.T) { + tmpl := unmarshalTemplate(scriptTemplateWithArgsAndWithoutSource) + mainCtr := extractMainCtrFromScriptTemplate(tmpl) + assert.Equal(t, []string{"echo"}, mainCtr.Command) + assert.Equal(t, []string{"hello world"}, mainCtr.Args) +} + var scriptTemplateWithOptionalInputArtifactProvided = ` name: script-with-input-artifact inputs: