diff --git a/pkg/reconciler/pipelinerun/resources/apply.go b/pkg/reconciler/pipelinerun/resources/apply.go index a2aba9fa6d7..a03a473c123 100644 --- a/pkg/reconciler/pipelinerun/resources/apply.go +++ b/pkg/reconciler/pipelinerun/resources/apply.go @@ -35,22 +35,35 @@ func ApplyParameters(p *v1beta1.PipelineSpec, pr *v1beta1.PipelineRun) *v1beta1. stringReplacements := map[string]string{} arrayReplacements := map[string][]string{} + patterns := []string{ + "params.%s", + "params[%q]", + } + // Set all the default stringReplacements for _, p := range p.Params { if p.Default != nil { if p.Default.Type == v1beta1.ParamTypeString { - stringReplacements[fmt.Sprintf("params.%s", p.Name)] = p.Default.StringVal + for _, pattern := range patterns { + stringReplacements[fmt.Sprintf(pattern, p.Name)] = p.Default.StringVal + } } else { - arrayReplacements[fmt.Sprintf("params.%s", p.Name)] = p.Default.ArrayVal + for _, pattern := range patterns { + arrayReplacements[fmt.Sprintf(pattern, p.Name)] = p.Default.ArrayVal + } } } } // Set and overwrite params with the ones from the PipelineRun for _, p := range pr.Spec.Params { if p.Value.Type == v1beta1.ParamTypeString { - stringReplacements[fmt.Sprintf("params.%s", p.Name)] = p.Value.StringVal + for _, pattern := range patterns { + stringReplacements[fmt.Sprintf(pattern, p.Name)] = p.Value.StringVal + } } else { - arrayReplacements[fmt.Sprintf("params.%s", p.Name)] = p.Value.ArrayVal + for _, pattern := range patterns { + arrayReplacements[fmt.Sprintf(pattern, p.Name)] = p.Value.ArrayVal + } } } diff --git a/pkg/reconciler/pipelinerun/resources/apply_test.go b/pkg/reconciler/pipelinerun/resources/apply_test.go index c2f0934f55d..07ab36186bb 100644 --- a/pkg/reconciler/pipelinerun/resources/apply_test.go +++ b/pkg/reconciler/pipelinerun/resources/apply_test.go @@ -271,6 +271,35 @@ func TestApplyParameters(t *testing.T) { }}, }}, }, + }, { + name: "parameter references with subscript notation and special characters", + original: v1beta1.PipelineSpec{ + Params: []v1beta1.ParamSpec{ + {Name: "first.param", Type: v1beta1.ParamTypeString, Default: v1beta1.NewArrayOrString("default-value")}, + {Name: "second/param", Type: v1beta1.ParamTypeString}, + }, + Tasks: []v1beta1.PipelineTask{{ + Params: []v1beta1.Param{ + {Name: "first-task-first-param", Value: *v1beta1.NewArrayOrString(`$(params["first.param"])`)}, + {Name: "first-task-second-param", Value: *v1beta1.NewArrayOrString(`$(params["second/param"])`)}, + {Name: "first-task-third-param", Value: *v1beta1.NewArrayOrString("static value")}, + }, + }}, + }, + params: []v1beta1.Param{{Name: "second/param", Value: *v1beta1.NewArrayOrString("second-value")}}, + expected: v1beta1.PipelineSpec{ + Params: []v1beta1.ParamSpec{ + {Name: "first.param", Type: v1beta1.ParamTypeString, Default: v1beta1.NewArrayOrString("default-value")}, + {Name: "second/param", Type: v1beta1.ParamTypeString}, + }, + Tasks: []v1beta1.PipelineTask{{ + Params: []v1beta1.Param{ + {Name: "first-task-first-param", Value: *v1beta1.NewArrayOrString("default-value")}, + {Name: "first-task-second-param", Value: *v1beta1.NewArrayOrString("second-value")}, + {Name: "first-task-third-param", Value: *v1beta1.NewArrayOrString("static value")}, + }, + }}, + }, }} { tt := tt // capture range variable t.Run(tt.name, func(t *testing.T) { @@ -300,7 +329,7 @@ func TestApplyTaskResults_MinimalExpression(t *testing.T) { Value: *v1beta1.NewArrayOrString("aResultValue"), ResultReference: v1beta1.ResultRef{ PipelineTask: "aTask", - Result: "aResult", + Result: "a.Result", }, FromTaskRun: "aTaskRun", }}, @@ -310,7 +339,7 @@ func TestApplyTaskResults_MinimalExpression(t *testing.T) { TaskRef: &v1beta1.TaskRef{Name: "bTask"}, Params: []v1beta1.Param{{ Name: "bParam", - Value: *v1beta1.NewArrayOrString("$(tasks.aTask.results.aResult)"), + Value: *v1beta1.NewArrayOrString(`$(tasks.aTask.results["a.Result"])`), }}, }, }}, diff --git a/pkg/reconciler/pipelinerun/resources/resultrefresolution.go b/pkg/reconciler/pipelinerun/resources/resultrefresolution.go index bc2be0090f0..a33f47eec97 100644 --- a/pkg/reconciler/pipelinerun/resources/resultrefresolution.go +++ b/pkg/reconciler/pipelinerun/resources/resultrefresolution.go @@ -185,12 +185,16 @@ func findTaskResultForParam(taskRun *v1beta1.TaskRun, reference *v1beta1.ResultR func (rs ResolvedResultRefs) getStringReplacements() map[string]string { replacements := map[string]string{} for _, r := range rs { - replaceTarget := r.getReplaceTarget() - replacements[replaceTarget] = r.Value.StringVal + for _, target := range r.getReplaceTarget() { + replacements[target] = r.Value.StringVal + } } return replacements } -func (r *ResolvedResultRef) getReplaceTarget() string { - return fmt.Sprintf("%s.%s.%s.%s", v1beta1.ResultTaskPart, r.ResultReference.PipelineTask, v1beta1.ResultResultPart, r.ResultReference.Result) +func (r *ResolvedResultRef) getReplaceTarget() []string { + return []string{ + fmt.Sprintf("%s.%s.%s.%s", v1beta1.ResultTaskPart, r.ResultReference.PipelineTask, v1beta1.ResultResultPart, r.ResultReference.Result), + fmt.Sprintf("%s.%s.%s[%q]", v1beta1.ResultTaskPart, r.ResultReference.PipelineTask, v1beta1.ResultResultPart, r.ResultReference.Result), + } } diff --git a/pkg/reconciler/taskrun/resources/apply.go b/pkg/reconciler/taskrun/resources/apply.go index b9671fa71e0..190fa965897 100644 --- a/pkg/reconciler/taskrun/resources/apply.go +++ b/pkg/reconciler/taskrun/resources/apply.go @@ -41,30 +41,37 @@ func ApplyParameters(spec *v1beta1.TaskSpec, tr *v1beta1.TaskRun, defaults ...v1 stringReplacements := map[string]string{} arrayReplacements := map[string][]string{} + patterns := []string{ + "params.%s", + "params[%q]", + // FIXME(vdemeester) Remove that with deprecating v1beta1 + "inputs.params.%s", + } + // Set all the default stringReplacements for _, p := range defaults { if p.Default != nil { if p.Default.Type == v1beta1.ParamTypeString { - stringReplacements[fmt.Sprintf("params.%s", p.Name)] = p.Default.StringVal - // FIXME(vdemeester) Remove that with deprecating v1beta1 - stringReplacements[fmt.Sprintf("inputs.params.%s", p.Name)] = p.Default.StringVal + for _, pattern := range patterns { + stringReplacements[fmt.Sprintf(pattern, p.Name)] = p.Default.StringVal + } } else { - arrayReplacements[fmt.Sprintf("params.%s", p.Name)] = p.Default.ArrayVal - // FIXME(vdemeester) Remove that with deprecating v1beta1 - arrayReplacements[fmt.Sprintf("inputs.params.%s", p.Name)] = p.Default.ArrayVal + for _, pattern := range patterns { + arrayReplacements[fmt.Sprintf(pattern, p.Name)] = p.Default.ArrayVal + } } } } // Set and overwrite params with the ones from the TaskRun for _, p := range tr.Spec.Params { if p.Value.Type == v1beta1.ParamTypeString { - stringReplacements[fmt.Sprintf("params.%s", p.Name)] = p.Value.StringVal - // FIXME(vdemeester) Remove that with deprecating v1beta1 - stringReplacements[fmt.Sprintf("inputs.params.%s", p.Name)] = p.Value.StringVal + for _, pattern := range patterns { + stringReplacements[fmt.Sprintf(pattern, p.Name)] = p.Value.StringVal + } } else { - arrayReplacements[fmt.Sprintf("params.%s", p.Name)] = p.Value.ArrayVal - // FIXME(vdemeester) Remove that with deprecating v1beta1 - arrayReplacements[fmt.Sprintf("inputs.params.%s", p.Name)] = p.Value.ArrayVal + for _, pattern := range patterns { + arrayReplacements[fmt.Sprintf(pattern, p.Name)] = p.Value.ArrayVal + } } } return ApplyReplacements(spec, stringReplacements, arrayReplacements) @@ -193,8 +200,15 @@ func applyWorkspaceMountPath(variable string, spec *v1beta1.TaskSpec, declaratio func ApplyTaskResults(spec *v1beta1.TaskSpec) *v1beta1.TaskSpec { stringReplacements := map[string]string{} + patterns := []string{ + "results.%s.path", + "results[%q].path", + } + for _, result := range spec.Results { - stringReplacements[fmt.Sprintf("results.%s.path", result.Name)] = filepath.Join(pipeline.DefaultResultPath, result.Name) + for _, pattern := range patterns { + stringReplacements[fmt.Sprintf(pattern, result.Name)] = filepath.Join(pipeline.DefaultResultPath, result.Name) + } } return ApplyReplacements(spec, stringReplacements, map[string][]string{}) } diff --git a/pkg/reconciler/taskrun/resources/apply_test.go b/pkg/reconciler/taskrun/resources/apply_test.go index d55f298512c..360aa77810d 100644 --- a/pkg/reconciler/taskrun/resources/apply_test.go +++ b/pkg/reconciler/taskrun/resources/apply_test.go @@ -52,22 +52,22 @@ var ( Sidecars: []v1beta1.Sidecar{{ Container: corev1.Container{ Name: "foo", - Image: "$(inputs.params.myimage)", + Image: `$(params["myimage"])`, Env: []corev1.EnvVar{{ Name: "foo", - Value: "$(inputs.params.FOO)", + Value: "$(params.FOO)", }}, }, }}, StepTemplate: &corev1.Container{ Env: []corev1.EnvVar{{ Name: "template-var", - Value: "$(inputs.params.FOO)", + Value: `$(params["FOO"])`, }}, }, Steps: []v1beta1.Step{{Container: corev1.Container{ Name: "foo", - Image: "$(inputs.params.myimage)", + Image: "$(params.myimage)", }}, {Container: corev1.Container{ Name: "baz", Image: "bat", @@ -75,14 +75,14 @@ var ( Args: []string{"$(inputs.resources.workspace.url)"}, }}, {Container: corev1.Container{ Name: "qux", - Image: "$(inputs.params.something)", + Image: "$(params.something)", Args: []string{"$(outputs.resources.imageToUse.url)"}, }}, {Container: corev1.Container{ Name: "foo", - Image: "$(inputs.params.myimage)", + Image: `$(params["myimage"])`, }}, {Container: corev1.Container{ Name: "baz", - Image: "$(inputs.params.somethingelse)", + Image: "$(params.somethingelse)", WorkingDir: "$(inputs.resources.workspace.path)", Args: []string{"$(inputs.resources.workspace.url)"}, }}, {Container: corev1.Container{ @@ -91,44 +91,44 @@ var ( Args: []string{"$(outputs.resources.imageToUse.url)"}, }}, {Container: corev1.Container{ Name: "foo", - Image: "busybox:$(inputs.params.FOO)", + Image: "busybox:$(params.FOO)", VolumeMounts: []corev1.VolumeMount{{ - Name: "$(inputs.params.FOO)", - MountPath: "path/to/$(inputs.params.FOO)", - SubPath: "sub/$(inputs.params.FOO)/path", + Name: "$(params.FOO)", + MountPath: "path/to/$(params.FOO)", + SubPath: "sub/$(params.FOO)/path", }}, }}, {Container: corev1.Container{ Name: "foo", - Image: "busybox:$(inputs.params.FOO)", + Image: "busybox:$(params.FOO)", Env: []corev1.EnvVar{{ Name: "foo", - Value: "value-$(inputs.params.FOO)", + Value: "value-$(params.FOO)", }, { Name: "bar", ValueFrom: &corev1.EnvVarSource{ ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: "config-$(inputs.params.FOO)"}, - Key: "config-key-$(inputs.params.FOO)", + LocalObjectReference: corev1.LocalObjectReference{Name: "config-$(params.FOO)"}, + Key: "config-key-$(params.FOO)", }, }, }, { Name: "baz", ValueFrom: &corev1.EnvVarSource{ SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{Name: "secret-$(inputs.params.FOO)"}, - Key: "secret-key-$(inputs.params.FOO)", + LocalObjectReference: corev1.LocalObjectReference{Name: "secret-$(params.FOO)"}, + Key: "secret-key-$(params.FOO)", }, }, }}, EnvFrom: []corev1.EnvFromSource{{ - Prefix: "prefix-0-$(inputs.params.FOO)", + Prefix: "prefix-0-$(params.FOO)", ConfigMapRef: &corev1.ConfigMapEnvSource{ - LocalObjectReference: corev1.LocalObjectReference{Name: "config-$(inputs.params.FOO)"}, + LocalObjectReference: corev1.LocalObjectReference{Name: "config-$(params.FOO)"}, }, }, { - Prefix: "prefix-1-$(inputs.params.FOO)", + Prefix: "prefix-1-$(params.FOO)", SecretRef: &corev1.SecretEnvSource{ - LocalObjectReference: corev1.LocalObjectReference{Name: "secret-$(inputs.params.FOO)"}, + LocalObjectReference: corev1.LocalObjectReference{Name: "secret-$(params.FOO)"}, }, }}, }}, {Container: corev1.Container{ @@ -139,15 +139,15 @@ var ( Image: "$(outputs.resources.imageToUse-re.path)", }}}, Volumes: []corev1.Volume{{ - Name: "$(inputs.params.FOO)", + Name: "$(params.FOO)", VolumeSource: corev1.VolumeSource{ ConfigMap: &corev1.ConfigMapVolumeSource{ LocalObjectReference: corev1.LocalObjectReference{ - Name: "$(inputs.params.FOO)", + Name: "$(params.FOO)", }, Items: []corev1.KeyToPath{{ - Key: "$(inputs.params.FOO)", - Path: "$(inputs.params.FOO)", + Key: "$(params.FOO)", + Path: "$(params.FOO)", }}, }, }, @@ -155,10 +155,10 @@ var ( Name: "some-secret", VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ - SecretName: "$(inputs.params.FOO)", + SecretName: "$(params.FOO)", Items: []corev1.KeyToPath{{ - Key: "$(inputs.params.FOO)", - Path: "$(inputs.params.FOO)", + Key: "$(params.FOO)", + Path: "$(params.FOO)", }}, }, }, @@ -166,7 +166,7 @@ var ( Name: "some-pvc", VolumeSource: corev1.VolumeSource{ PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ - ClaimName: "$(inputs.params.FOO)", + ClaimName: "$(params.FOO)", }, }, }, { @@ -176,16 +176,16 @@ var ( Sources: []corev1.VolumeProjection{{ ConfigMap: &corev1.ConfigMapProjection{ LocalObjectReference: corev1.LocalObjectReference{ - Name: "$(inputs.params.FOO)", + Name: "$(params.FOO)", }, }, Secret: &corev1.SecretProjection{ LocalObjectReference: corev1.LocalObjectReference{ - Name: "$(inputs.params.FOO)", + Name: "$(params.FOO)", }, }, ServiceAccountToken: &corev1.ServiceAccountTokenProjection{ - Audience: "$(inputs.params.FOO)", + Audience: "$(params.FOO)", }, }}, }, @@ -195,10 +195,10 @@ var ( VolumeSource: corev1.VolumeSource{ CSI: &corev1.CSIVolumeSource{ VolumeAttributes: map[string]string{ - "secretProviderClass": "$(inputs.params.FOO)", + "secretProviderClass": "$(params.FOO)", }, NodePublishSecretRef: &corev1.LocalObjectReference{ - Name: "$(inputs.params.FOO)", + Name: "$(params.FOO)", }, }, }, @@ -246,7 +246,7 @@ var ( Name: "image-with-c-specified", Image: "some-other-image", Command: []string{"echo"}, - Args: []string{"first", "second", "$(inputs.params.array-param)", "last"}, + Args: []string{"first", "second", "$(params.array-param)", "last"}, }}}, } @@ -258,7 +258,7 @@ var ( Name: "image-with-c-specified", Image: "some-other-image", Command: []string{"echo"}, - Args: []string{"$(inputs.params.normal-param)", "second", "$(inputs.params.array-param)", "last"}, + Args: []string{"$(params.normal-param)", "second", "$(params.array-param)", "last"}, }}}, } @@ -269,20 +269,20 @@ var ( }}, {Container: corev1.Container{ Name: "image-with-c-specified", Image: "some-other-image", - Command: []string{"cmd", "$(inputs.params.another-array-param)"}, - Args: []string{"first", "second", "$(inputs.params.array-param)", "last"}, + Command: []string{"cmd", "$(params.another-array-param)"}, + Args: []string{"first", "second", "$(params.array-param)", "last"}, }}}, } multipleArrayAndStringsParamsTaskSpec = &v1beta1.TaskSpec{ Steps: []v1beta1.Step{{Container: corev1.Container{ Name: "simple-image", - Image: "image-$(inputs.params.string-param2)", + Image: "image-$(params.string-param2)", }}, {Container: corev1.Container{ Name: "image-with-c-specified", Image: "some-other-image", - Command: []string{"cmd", "$(inputs.params.array-param1)"}, - Args: []string{"$(inputs.params.array-param2)", "second", "$(inputs.params.array-param1)", "$(inputs.params.string-param1)", "last"}, + Command: []string{"cmd", "$(params.array-param1)"}, + Args: []string{"$(params.array-param2)", "second", "$(params.array-param1)", "$(params.string-param1)", "last"}, }}}, } @@ -1145,7 +1145,7 @@ func TestTaskResults(t *testing.T) { names.TestingSeed() ts := &v1beta1.TaskSpec{ Results: []v1beta1.TaskResult{{ - Name: "current-date-unix-timestamp", + Name: "current.date.unix.timestamp", Description: "The current date in unix timestamp format", }, { Name: "current-date-human-readable", @@ -1155,9 +1155,9 @@ func TestTaskResults(t *testing.T) { Container: corev1.Container{ Name: "print-date-unix-timestamp", Image: "bash:latest", - Args: []string{"$(results.current-date-unix-timestamp.path)"}, + Args: []string{"$(results[\"current.date.unix.timestamp\"].path)"}, }, - Script: "#!/usr/bin/env bash\ndate +%s | tee $(results.current-date-unix-timestamp.path)", + Script: "#!/usr/bin/env bash\ndate +%s | tee $(results[\"current.date.unix.timestamp\"].path)", }, { Container: corev1.Container{ Name: "print-date-human-readable", @@ -1167,8 +1167,8 @@ func TestTaskResults(t *testing.T) { }}, } want := applyMutation(ts, func(spec *v1beta1.TaskSpec) { - spec.Steps[0].Script = "#!/usr/bin/env bash\ndate +%s | tee /tekton/results/current-date-unix-timestamp" - spec.Steps[0].Args[0] = "/tekton/results/current-date-unix-timestamp" + spec.Steps[0].Script = "#!/usr/bin/env bash\ndate +%s | tee /tekton/results/current.date.unix.timestamp" + spec.Steps[0].Args[0] = "/tekton/results/current.date.unix.timestamp" spec.Steps[1].Script = "#!/usr/bin/env bash\ndate | tee /tekton/results/current-date-human-readable" }) got := resources.ApplyTaskResults(ts) diff --git a/test/dag_test.go b/test/dag_test.go index 9e926adca94..6f3c2c91eeb 100644 --- a/test/dag_test.go +++ b/test/dag_test.go @@ -71,7 +71,7 @@ func TestDAGPipelineRun(t *testing.T) { }}, Steps: []v1beta1.Step{{ Container: corev1.Container{Image: "busybox"}, - Script: "echo $(params.text)", + Script: `echo $(params["text"])`, }, { Container: corev1.Container{Image: "busybox"}, Script: "ln -s $(resources.inputs.repo.path) $(resources.outputs.repo.path)", diff --git a/test/pipelinerun_test.go b/test/pipelinerun_test.go index c377dcfb623..676f756d7b1 100644 --- a/test/pipelinerun_test.go +++ b/test/pipelinerun_test.go @@ -104,7 +104,7 @@ func TestPipelineRun(t *testing.T) { ObjectMeta: metav1.ObjectMeta{Name: getName(taskName, index), Namespace: namespace}, Spec: v1beta1.TaskSpec{ Params: []v1beta1.ParamSpec{{ - Name: "path", Type: v1beta1.ParamTypeString, + Name: "the.path", Type: v1beta1.ParamTypeString, }, { Name: "dest", Type: v1beta1.ParamTypeString, }}, @@ -113,7 +113,7 @@ func TestPipelineRun(t *testing.T) { Name: "config-docker", Image: "gcr.io/tekton-releases/dogfooding/skopeo:latest", Command: []string{"skopeo"}, - Args: []string{"copy", "$(params.path)", "$(params.dest)"}, + Args: []string{"copy", `$(params["the.path"])`, "$(params.dest)"}, }}, }, }, @@ -181,7 +181,7 @@ func TestPipelineRun(t *testing.T) { ObjectMeta: metav1.ObjectMeta{Name: getName(taskName, index), Namespace: namespace}, Spec: v1beta1.TaskSpec{ Params: []v1beta1.ParamSpec{{ - Name: "path", Type: v1beta1.ParamTypeString, + Name: "the.path", Type: v1beta1.ParamTypeString, }, { Name: "dest", Type: v1beta1.ParamTypeString, }}, @@ -190,7 +190,7 @@ func TestPipelineRun(t *testing.T) { Name: "config-docker", Image: "gcr.io/tekton-releases/dogfooding/skopeo:latest", Command: []string{"skopeo"}, - Args: []string{"copy", "$(params.path)", "$(params.dest)"}, + Args: []string{"copy", `$(params["the.path"])`, `$(params["dest"])`}, }}, }, }, @@ -309,7 +309,7 @@ func getHelloWorldPipelineWithSingularTask(suffix int, namespace string) *v1beta ObjectMeta: metav1.ObjectMeta{Name: getName(pipelineName, suffix), Namespace: namespace}, Spec: v1beta1.PipelineSpec{ Params: []v1beta1.ParamSpec{{ - Name: "path", Type: v1beta1.ParamTypeString, + Name: "the.path", Type: v1beta1.ParamTypeString, }, { Name: "dest", Type: v1beta1.ParamTypeString, }}, @@ -317,7 +317,7 @@ func getHelloWorldPipelineWithSingularTask(suffix int, namespace string) *v1beta Name: task1Name, TaskRef: &v1beta1.TaskRef{Name: getName(taskName, suffix)}, Params: []v1beta1.Param{{ - Name: "path", Value: *v1beta1.NewArrayOrString("$(params.path)"), + Name: "the.path", Value: *v1beta1.NewArrayOrString(`$(params["the.path"])`), }, { Name: "dest", Value: *v1beta1.NewArrayOrString("$(params.dest)"), }}, @@ -694,7 +694,7 @@ func getHelloWorldPipelineRun(suffix int, namespace string) *v1beta1.PipelineRun Spec: v1beta1.PipelineRunSpec{ PipelineRef: &v1beta1.PipelineRef{Name: getName(pipelineName, suffix)}, Params: []v1beta1.Param{{ - Name: "path", + Name: "the.path", Value: *v1beta1.NewArrayOrString("docker://gcr.io/build-crd-testing/secret-sauce"), }, { Name: "dest",