Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Merge WorkflowTemplateRef with defaults workflow spec #3480

Merged
merged 18 commits into from Jul 16, 2020
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion workflow/controller/controller_test.go
Expand Up @@ -395,7 +395,7 @@ func TestCheckAndInitWorkflowTmplRef(t *testing.T) {
wf: wf}
_, _, err := woc.loadExecutionSpec()
assert.NoError(t, err)
assert.Equal(t, &wftmpl.Spec.WorkflowSpec, woc.wfSpec)
assert.Equal(t, wftmpl.Spec.WorkflowSpec.Templates, woc.wfSpec.Templates)
}

func TestIsArchivable(t *testing.T) {
Expand Down
14 changes: 6 additions & 8 deletions workflow/controller/operator.go
Expand Up @@ -2829,17 +2829,15 @@ func (woc *wfOperationCtx) loadExecutionSpec() (wfv1.TemplateReferenceHolder, wf
}
}

woc.wfSpec = woc.wf.Status.StoredWorkflowSpec

entrypoint := woc.wf.Spec.Entrypoint
if entrypoint == "" {
entrypoint = woc.wfSpec.Entrypoint
// Set the workflow properties to execution spec.
mergedWf, err := wfutil.MergeWorkflows(wfv1.Workflow{Spec: *woc.wf.Status.StoredWorkflowSpec}, wfv1.Workflow{Spec: woc.wf.Spec})
sarabala1979 marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return nil, executionParameters, err
}

woc.wfSpec = &mergedWf.Spec
woc.volumes = woc.wfSpec.DeepCopy().Volumes

tmplRef := &wfv1.WorkflowStep{TemplateRef: woc.wf.Spec.WorkflowTemplateRef.ToTemplateRef(entrypoint)}

tmplRef := &wfv1.WorkflowStep{TemplateRef: woc.wf.Spec.WorkflowTemplateRef.ToTemplateRef(woc.wfSpec.Entrypoint)}
if len(woc.wfSpec.Arguments.Parameters) > 0 {
executionParameters.Parameters = util.MergeParameters(executionParameters.Parameters, woc.wfSpec.Arguments.Parameters)
}
Expand Down
3 changes: 2 additions & 1 deletion workflow/controller/operator_workflow_template_ref_test.go
Expand Up @@ -15,7 +15,8 @@ func TestWorkflowTemplateRef(t *testing.T) {
defer cancel()
woc := newWorkflowOperationCtx(unmarshalWF(wfWithTmplRef), controller)
woc.operate()
assert.Equal(t, &unmarshalWFTmpl(wfTmpl).Spec.WorkflowSpec, woc.wfSpec)
assert.Equal(t, unmarshalWFTmpl(wfTmpl).Spec.WorkflowSpec.Templates, woc.wfSpec.Templates)
assert.Equal(t, woc.wf.Spec.Entrypoint, woc.wfSpec.Entrypoint)
// verify we copy these values
assert.Len(t, woc.volumes, 1, "volumes from workflow template")
// and these
Expand Down
26 changes: 26 additions & 0 deletions workflow/util/util.go
Expand Up @@ -907,3 +907,29 @@ func GetNodeType(tmpl *wfv1.Template) wfv1.NodeType {
}
return ""
}

// MergeWorkflows will do strategic merge the workflows
func MergeWorkflows(originalWf, patchWf wfv1.Workflow) (*wfv1.Workflow, error) {
sarabala1979 marked this conversation as resolved.
Show resolved Hide resolved
workflowBytes, err := json.Marshal(wfv1.Workflow{Spec: patchWf.Spec})
if err != nil {
return nil, err
}

storedWFByte, err := json.Marshal(wfv1.Workflow{Spec: originalWf.Spec})
sarabala1979 marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return nil, err
}

mergedWFByte, err := strategicpatch.StrategicMergePatch(storedWFByte, workflowBytes, wfv1.Workflow{})
if err != nil {
return nil, err
}

var mergedWf wfv1.Workflow
err = json.Unmarshal(mergedWFByte, &mergedWf)
if err != nil {
return nil, err
}
return &mergedWf, nil

}
43 changes: 43 additions & 0 deletions workflow/util/util_test.go
Expand Up @@ -396,3 +396,46 @@ func TestApplySubmitOpts(t *testing.T) {
}
})
}

var origWF = `
sarabala1979 marked this conversation as resolved.
Show resolved Hide resolved
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: workflow-template-hello-world-
spec:
arguments:
parameters:
- name: message
value: original
entrypoint: start
onExit: end
serviceAccountName: argo
workflowTemplateRef:
name: workflow-template-submittable
`
var patchWF = `
apiVersion: argoproj.io/v1alpha1
kind: Workflow
metadata:
generateName: workflow-template-hello-world-
spec:
arguments:
parameters:
- name: message
value: patch
serviceAccountName: argo1
podGC:
strategy: OnPodSuccess
`

func TestMergeWorkflows(t *testing.T) {
origWf := unmarshalWF(origWF)
patchWf := unmarshalWF(patchWF)

mergedWf, err := MergeWorkflows(*origWf, *patchWf)
assert.NoError(t, err)
assert.Equal(t, origWf.Spec.Entrypoint, mergedWf.Spec.Entrypoint)
sarabala1979 marked this conversation as resolved.
Show resolved Hide resolved
assert.Equal(t, patchWf.Spec.ServiceAccountName, mergedWf.Spec.ServiceAccountName)
assert.Equal(t, patchWf.Spec.Arguments.Parameters[0].Name, mergedWf.Spec.Arguments.Parameters[0].Name)
assert.Equal(t, patchWf.Spec.Arguments.Parameters[0].Value, mergedWf.Spec.Arguments.Parameters[0].Value)
}
7 changes: 7 additions & 0 deletions workflow/validate/validate.go
Expand Up @@ -98,6 +98,13 @@ var wfTmplRefAllowedWfSpecValidFields = map[string]bool{
"Arguments": true,
"WorkflowTemplateRef": true,
"TTLStrategy": true,
"Parallelism": true,
sarabala1979 marked this conversation as resolved.
Show resolved Hide resolved
"Volumes": true,
"VolumeClaimTemplates": true,
"NodeSelector": true,
"OnExit": true,
"PodGC": true,
"ServiceAccountName": true,
}

type FakeArguments struct{}
Expand Down