diff --git a/workflow/controller/scope.go b/workflow/controller/scope.go index 30eb60a54230..f709708dce98 100644 --- a/workflow/controller/scope.go +++ b/workflow/controller/scope.go @@ -144,7 +144,11 @@ func (s *wfScope) resolveArtifact(art *wfv1.Artifact) (*wfv1.Artifact, error) { return copyArt, errors.New(errors.CodeBadRequest, "failed to unmarshal artifact subpath for templating") } - return copyArt, copyArt.AppendToKey(resolvedSubPath) + err = copyArt.AppendToKey(resolvedSubPath) + if err != nil && copyArt.Optional { //Ignore error when artifact optional + return copyArt, nil + } + return copyArt, err } return &valArt, nil diff --git a/workflow/controller/steps_test.go b/workflow/controller/steps_test.go index 13a877071498..204ecead34ee 100644 --- a/workflow/controller/steps_test.go +++ b/workflow/controller/steps_test.go @@ -314,3 +314,133 @@ func TestOptionalArgumentAndParameter(t *testing.T) { woc.operate(ctx) assert.Equal(t, wfv1.WorkflowRunning, woc.wf.Status.Phase) } + +var artifactResolutionWhenOptionalAndSubpath = ` +apiVersion: argoproj.io/v1alpha1 +kind: Workflow +metadata: + name: artifact-passing-subpath-rx7f4 +spec: + entrypoint: artifact-example + templates: + - name: artifact-example + steps: + - - name: hello-world-to-file + template: hello-world-to-file + - - name: hello-world-to-file2 + template: hello-world-to-file2 + arguments: + artifacts: + - name: bar + from: "{{steps.hello-world-to-file.outputs.artifacts.foo}}" + optional: true + subpath: bar.txt + withParam: "[0, 1]" + + - name: hello-world-to-file + container: + image: busybox:latest + imagePullPolicy: IfNotPresent + command: [sh, -c] + args: ["sleep 1; echo hello world"] + outputs: + artifacts: + - name: foo + path: /tmp/foo + optional: true + archive: + none: {} + + - name: hello-world-to-file2 + inputs: + artifacts: + - name: bar + path: /tmp/bar.txt + optional: true + archive: + none: {} + container: + image: busybox:latest + imagePullPolicy: IfNotPresent + command: [sh, -c] + args: ["sleep 1; echo hello world"] +status: + nodes: + artifact-passing-subpath-rx7f4: + children: + - artifact-passing-subpath-rx7f4-1763046061 + displayName: artifact-passing-subpath-rx7f4 + id: artifact-passing-subpath-rx7f4 + name: artifact-passing-subpath-rx7f4 + phase: Running + progress: 1/1 + resourcesDuration: + cpu: 0 + memory: 5 + startedAt: "2024-09-06T04:53:32Z" + templateName: artifact-example + templateScope: local/artifact-passing-subpath-rx7f4 + type: Steps + artifact-passing-subpath-rx7f4-511855021: + boundaryID: artifact-passing-subpath-rx7f4 + children: + - artifact-passing-subpath-rx7f4-1696082680 + displayName: hello-world-to-file + finishedAt: "2024-09-06T04:53:39Z" + id: artifact-passing-subpath-rx7f4-511855021 + name: artifact-passing-subpath-rx7f4[0].hello-world-to-file + outputs: + artifacts: + - archive: + none: {} + name: foo + optional: true + path: /tmp/foo + - name: main-logs + s3: + key: artifact-passing-subpath-rx7f4/artifact-passing-subpath-rx7f4-hello-world-to-file-511855021/main.log + exitCode: "0" + phase: Succeeded + progress: 1/1 + resourcesDuration: + cpu: 0 + memory: 5 + startedAt: "2024-09-06T04:53:32Z" + templateName: hello-world-to-file + templateScope: local/artifact-passing-subpath-rx7f4 + type: Pod + artifact-passing-subpath-rx7f4-1763046061: + boundaryID: artifact-passing-subpath-rx7f4 + children: + - artifact-passing-subpath-rx7f4-511855021 + displayName: '[0]' + finishedAt: "2024-09-06T04:53:41Z" + id: artifact-passing-subpath-rx7f4-1763046061 + name: artifact-passing-subpath-rx7f4[0] + nodeFlag: {} + phase: Succeeded + progress: 1/1 + resourcesDuration: + cpu: 0 + memory: 5 + startedAt: "2024-09-06T04:53:32Z" + templateScope: local/artifact-passing-subpath-rx7f4 + type: StepGroup + phase: Running + taskResultsCompletionStatus: + artifact-passing-subpath-rx7f4-511855021: true` + +func TestOptionalArgumentUseSubPathInLoop(t *testing.T) { + cancel, controller := newController() + defer cancel() + wfcset := controller.wfclientset.ArgoprojV1alpha1().Workflows("") + + ctx := context.Background() + wf := wfv1.MustUnmarshalWorkflow(artifactResolutionWhenOptionalAndSubpath) + wf, err := wfcset.Create(ctx, wf, metav1.CreateOptions{}) + require.NoError(t, err) + woc := newWorkflowOperationCtx(wf, controller) + + woc.operate(ctx) + assert.Equal(t, wfv1.WorkflowRunning, woc.wf.Status.Phase) +}