diff --git a/pkg/testworkflows/testworkflowresolver/apply.go b/pkg/testworkflows/testworkflowresolver/apply.go index 07ee151165..a5ab59b346 100644 --- a/pkg/testworkflows/testworkflowresolver/apply.go +++ b/pkg/testworkflows/testworkflowresolver/apply.go @@ -133,7 +133,8 @@ func InjectServiceTemplate(svc *testworkflowsv1.ServiceSpec, template testworkfl func applyTemplatesToStep(step testworkflowsv1.Step, templates map[string]testworkflowsv1.TestWorkflowTemplate, externalize func(key, value string) (*corev1.EnvVarSource, error)) (testworkflowsv1.Step, error) { // Apply regular templates - for i, ref := range step.Use { + for i := len(step.Use) - 1; i >= 0; i-- { + ref := step.Use[i] tpl, err := getConfiguredTemplate(ref.Name, ref.Config, templates, externalize) if err != nil { return step, errors.Wrap(err, fmt.Sprintf(".use[%d]: resolving template", i)) @@ -170,7 +171,8 @@ func applyTemplatesToStep(step testworkflowsv1.Step, templates map[string]testwo // Apply templates to the services for name, svc := range step.Services { - for i, ref := range svc.Use { + for i := len(svc.Use) - 1; i >= 0; i-- { + ref := svc.Use[i] tpl, err := getConfiguredTemplate(ref.Name, ref.Config, templates, externalize) if err != nil { return step, errors.Wrap(err, fmt.Sprintf("services[%s].use[%d]: resolving template", name, i)) @@ -268,7 +270,8 @@ func applyTemplatesToSpec(spec *testworkflowsv1.TestWorkflowSpec, templates map[ defer expressions.Simplify(spec, expressions.ReplacePrefixMachine(random+".", "config.")) // Apply top-level templates - for i, ref := range spec.Use { + for i := len(spec.Use) - 1; i >= 0; i-- { + ref := spec.Use[i] tpl, err := getConfiguredTemplate(ref.Name, ref.Config, templates, externalize) if err != nil { return errors.Wrap(err, fmt.Sprintf("spec.use[%d]: resolving template", i)) @@ -282,7 +285,8 @@ func applyTemplatesToSpec(spec *testworkflowsv1.TestWorkflowSpec, templates map[ // Apply templates to the services for name, svc := range spec.Services { - for i, ref := range svc.Use { + for i := len(svc.Use) - 1; i >= 0; i-- { + ref := svc.Use[i] tpl, err := getConfiguredTemplate(ref.Name, ref.Config, templates, externalize) if err != nil { return errors.Wrap(err, fmt.Sprintf("services[%s].use[%d]: resolving template", name, i)) diff --git a/pkg/testworkflows/testworkflowresolver/apply_test.go b/pkg/testworkflows/testworkflowresolver/apply_test.go index 8e5137fd3d..e0617373ae 100644 --- a/pkg/testworkflows/testworkflowresolver/apply_test.go +++ b/pkg/testworkflows/testworkflowresolver/apply_test.go @@ -296,23 +296,23 @@ func TestApplyTemplatesMergeMultipleTopLevelSteps(t *testing.T) { want := workflowSteps.DeepCopy() want.Spec.Setup = []testworkflowsv1.Step{ - ConvertIndependentStepToStep(tplStepsConfig.Spec.Setup[0]), ConvertIndependentStepToStep(tplSteps.Spec.Setup[0]), + ConvertIndependentStepToStep(tplStepsConfig.Spec.Setup[0]), want.Spec.Setup[0], } - want.Spec.Setup[0].Name = "setup-tpl-test-20" + want.Spec.Setup[1].Name = "setup-tpl-test-20" want.Spec.Steps = []testworkflowsv1.Step{ - ConvertIndependentStepToStep(tplStepsConfig.Spec.Steps[0]), ConvertIndependentStepToStep(tplSteps.Spec.Steps[0]), + ConvertIndependentStepToStep(tplStepsConfig.Spec.Steps[0]), want.Spec.Steps[0], } - want.Spec.Steps[0].Name = "steps-tpl-test-20" + want.Spec.Steps[1].Name = "steps-tpl-test-20" want.Spec.After = []testworkflowsv1.Step{ want.Spec.After[0], - ConvertIndependentStepToStep(tplSteps.Spec.After[0]), ConvertIndependentStepToStep(tplStepsConfig.Spec.After[0]), + ConvertIndependentStepToStep(tplSteps.Spec.After[0]), } - want.Spec.After[2].Name = "after-tpl-test-20" + want.Spec.After[1].Name = "after-tpl-test-20" assert.NoError(t, err) assert.Equal(t, want, wf) @@ -329,22 +329,22 @@ func TestApplyTemplatesMergeMultipleConfigurable(t *testing.T) { ConvertIndependentStepToStep(tplStepsConfig.Spec.Setup[0]), want.Spec.Setup[0], } - want.Spec.Setup[0].Name = "setup-tpl-test-20" - want.Spec.Setup[1].Name = "setup-tpl-test-10" + want.Spec.Setup[0].Name = "setup-tpl-test-10" + want.Spec.Setup[1].Name = "setup-tpl-test-20" want.Spec.Steps = []testworkflowsv1.Step{ ConvertIndependentStepToStep(tplStepsConfig.Spec.Steps[0]), ConvertIndependentStepToStep(tplStepsConfig.Spec.Steps[0]), want.Spec.Steps[0], } - want.Spec.Steps[0].Name = "steps-tpl-test-20" - want.Spec.Steps[1].Name = "steps-tpl-test-10" + want.Spec.Steps[0].Name = "steps-tpl-test-10" + want.Spec.Steps[1].Name = "steps-tpl-test-20" want.Spec.After = []testworkflowsv1.Step{ want.Spec.After[0], ConvertIndependentStepToStep(tplStepsConfig.Spec.After[0]), ConvertIndependentStepToStep(tplStepsConfig.Spec.After[0]), } - want.Spec.After[1].Name = "after-tpl-test-10" - want.Spec.After[2].Name = "after-tpl-test-20" + want.Spec.After[1].Name = "after-tpl-test-20" + want.Spec.After[2].Name = "after-tpl-test-10" assert.NoError(t, err) assert.Equal(t, want, wf) @@ -449,19 +449,19 @@ func TestApplyTemplatesStepBasicMultipleSteps(t *testing.T) { want := *basicStep.DeepCopy() want.Setup = []testworkflowsv1.Step{ - ConvertIndependentStepToStep(tplStepsConfig.Spec.Setup[0]), ConvertIndependentStepToStep(tplSteps.Spec.Setup[0]), + ConvertIndependentStepToStep(tplStepsConfig.Spec.Setup[0]), } want.Steps = append([]testworkflowsv1.Step{ - ConvertIndependentStepToStep(tplStepsConfig.Spec.Steps[0]), ConvertIndependentStepToStep(tplSteps.Spec.Steps[0]), + ConvertIndependentStepToStep(tplStepsConfig.Spec.Steps[0]), }, append(want.Steps, []testworkflowsv1.Step{ - ConvertIndependentStepToStep(tplSteps.Spec.After[0]), ConvertIndependentStepToStep(tplStepsConfig.Spec.After[0]), + ConvertIndependentStepToStep(tplSteps.Spec.After[0]), }...)...) - want.Setup[0].Name = "setup-tpl-test-20" - want.Steps[0].Name = "steps-tpl-test-20" - want.Steps[3].Name = "after-tpl-test-20" + want.Setup[1].Name = "setup-tpl-test-20" + want.Steps[1].Name = "steps-tpl-test-20" + want.Steps[2].Name = "after-tpl-test-20" assert.NoError(t, err) assert.Equal(t, want, s) @@ -569,19 +569,19 @@ func TestApplyTemplatesStepAdvancedMultipleSteps(t *testing.T) { want := *advancedStep.DeepCopy() want.Setup = []testworkflowsv1.Step{ - ConvertIndependentStepToStep(tplStepsConfig.Spec.Setup[0]), ConvertIndependentStepToStep(tplSteps.Spec.Setup[0]), + ConvertIndependentStepToStep(tplStepsConfig.Spec.Setup[0]), } want.Steps = append([]testworkflowsv1.Step{ - ConvertIndependentStepToStep(tplStepsConfig.Spec.Steps[0]), ConvertIndependentStepToStep(tplSteps.Spec.Steps[0]), + ConvertIndependentStepToStep(tplStepsConfig.Spec.Steps[0]), }, append(want.Steps, []testworkflowsv1.Step{ - ConvertIndependentStepToStep(tplSteps.Spec.After[0]), ConvertIndependentStepToStep(tplStepsConfig.Spec.After[0]), + ConvertIndependentStepToStep(tplSteps.Spec.After[0]), }...)...) - want.Setup[0].Name = "setup-tpl-test-20" - want.Steps[0].Name = "steps-tpl-test-20" - want.Steps[4].Name = "after-tpl-test-20" + want.Setup[1].Name = "setup-tpl-test-20" + want.Steps[1].Name = "steps-tpl-test-20" + want.Steps[3].Name = "after-tpl-test-20" assert.NoError(t, err) assert.Equal(t, want, s) @@ -673,3 +673,72 @@ func TestApplyTemplates_ConditionAlways(t *testing.T) { assert.NoError(t, err) assert.Equal(t, want, wf) } + +func TestApplyTemplates_MergePodValues(t *testing.T) { + tpls := map[string]testworkflowsv1.TestWorkflowTemplate{ + "top": { + Spec: testworkflowsv1.TestWorkflowTemplateSpec{ + TestWorkflowSpecBase: testworkflowsv1.TestWorkflowSpecBase{ + Pod: &testworkflowsv1.PodConfig{ + Labels: map[string]string{ + "label1": "topvalue", + "label2": "topvalue", + "label3": "topvalue", + }, + }, + }, + }, + }, + "middle": { + Spec: testworkflowsv1.TestWorkflowTemplateSpec{ + TestWorkflowSpecBase: testworkflowsv1.TestWorkflowSpecBase{ + Pod: &testworkflowsv1.PodConfig{ + Labels: map[string]string{ + "label1": "middlevalue", + "label2": "middlevalue", + }, + }, + }, + }, + }, + } + wf := &testworkflowsv1.TestWorkflow{ + Spec: testworkflowsv1.TestWorkflowSpec{ + TestWorkflowSpecBase: testworkflowsv1.TestWorkflowSpecBase{ + Pod: &testworkflowsv1.PodConfig{ + Labels: map[string]string{ + "label1": "workflowvalue", + }, + }, + }, + Use: []testworkflowsv1.TemplateRef{ + {Name: "top"}, + {Name: "middle"}, + }, + Steps: []testworkflowsv1.Step{ + {StepOperations: testworkflowsv1.StepOperations{Shell: "exit 0"}}, + }, + }, + } + err := ApplyTemplates(wf, tpls, nil) + + want := &testworkflowsv1.TestWorkflow{ + Spec: testworkflowsv1.TestWorkflowSpec{ + TestWorkflowSpecBase: testworkflowsv1.TestWorkflowSpecBase{ + Pod: &testworkflowsv1.PodConfig{ + Labels: map[string]string{ + "label1": "workflowvalue", + "label2": "middlevalue", + "label3": "topvalue", + }, + }, + }, + Steps: []testworkflowsv1.Step{ + {StepOperations: testworkflowsv1.StepOperations{Shell: "exit 0"}}, + }, + }, + } + + assert.NoError(t, err) + assert.Equal(t, want, wf) +}