Skip to content

Commit 1b74ff3

Browse files
chitrangpateltekton-robot
authored andcommitted
Propagate params in pipelines
Prior to this, we allowed parameter propagation in an inlined pipelinerun. However, within a pipeline, we requrie a verbose spec. This was an oversight as indicated in #7901. This PR fixes that issue by updating the validation logic in the webhook. Fixes #7901. Propagate params in pipelines Prior to this, we allowed parameter propagation in an inlined pipelinerun. However, within a pipeline, we requrie a verbose spec. This was an oversight as indicated in #7901. This PR fixes that issue by updating the validation logic in the webhook. Fixes #7901.
1 parent 13f45bf commit 1b74ff3

7 files changed

+378
-8
lines changed

docs/pipelines.md

+39
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,45 @@ any resolved `param` value against the `enum` specified in each `PipelineTask` b
369369

370370
See usage in this [example](../examples/v1/pipelineruns/alpha/param-enum.yaml)
371371

372+
#### Propagated Params
373+
374+
Like with embedded [pipelineruns](pipelineruns.md#propagated-parameters), you can propagate `params` declared in the `pipeline` down to the inlined `pipelineTasks` and its inlined `Steps`. Wherever a resource (e.g. a `pipelineTask`) or a `StepAction` is referenced, the parameters need to be passed explicitly.
375+
376+
For example, the following is a valid yaml.
377+
378+
```yaml
379+
apiVersion: tekton.dev/v1 # or tekton.dev/v1beta1
380+
kind: Pipeline
381+
metadata:
382+
name: pipelien-propagated-params
383+
spec:
384+
params:
385+
- name: HELLO
386+
default: "Hello World!"
387+
- name: BYE
388+
default: "Bye World!"
389+
tasks:
390+
- name: echo-hello
391+
taskSpec:
392+
steps:
393+
- name: echo
394+
image: ubuntu
395+
script: |
396+
#!/usr/bin/env bash
397+
echo "$(params.HELLO)"
398+
- name: echo-bye
399+
taskSpec:
400+
steps:
401+
- name: echo-action
402+
ref:
403+
name: step-action-echo
404+
params:
405+
- name: msg
406+
value: "$(params.BYE)"
407+
```
408+
The same rules defined in [pipelineruns](pipelineruns.md#propagated-parameters) apply here.
409+
410+
372411
## Adding `Tasks` to the `Pipeline`
373412

374413
Your `Pipeline` definition must reference at least one [`Task`](tasks.md).
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
apiVersion: tekton.dev/v1
2+
kind: Pipeline
3+
metadata:
4+
name: workspace-example
5+
spec:
6+
workspaces:
7+
- name: shared-data
8+
tasks:
9+
- name: t1
10+
taskSpec:
11+
steps:
12+
- image: ubuntu
13+
command: ["ls"]
14+
args: ["$(workspaces.shared-data.path)"]
15+
---
16+
apiVersion: tekton.dev/v1
17+
kind: PipelineRun
18+
metadata:
19+
name: workspace-example-run
20+
spec:
21+
pipelineRef:
22+
name: workspace-example
23+
workspaces:
24+
- name: shared-data
25+
volumeClaimTemplate:
26+
spec:
27+
accessModes:
28+
- ReadWriteOnce
29+
resources:
30+
requests:
31+
storage: 16Mi
32+
volumeMode: Filesystem
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
apiVersion: tekton.dev/v1
2+
kind: Pipeline
3+
metadata:
4+
name: propagating-params-in-pipeline
5+
spec:
6+
params:
7+
- name: HELLO
8+
default: "Pipeline Hello World!"
9+
tasks:
10+
- name: echo-hello
11+
taskSpec:
12+
steps:
13+
- name: echo
14+
image: ubuntu
15+
script: |
16+
#!/usr/bin/env bash
17+
echo "$(params.HELLO)"
18+
finally:
19+
- name: echo-hello-finally
20+
taskSpec:
21+
steps:
22+
- name: echo
23+
image: ubuntu
24+
script: |
25+
#!/usr/bin/env bash
26+
echo "And Finally ... $(params.HELLO)"
27+
---
28+
apiVersion: tekton.dev/v1
29+
kind: PipelineRun
30+
metadata:
31+
generateName: propagating-params-in-pipeline-
32+
spec:
33+
params:
34+
- name: HELLO
35+
value: "Hello from pipeline run"
36+
pipelineRef:
37+
name: propagating-params-in-pipeline

pkg/apis/pipeline/v1/pipeline_validation.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,10 @@ func (l PipelineTaskList) Validate(ctx context.Context, taskNames sets.String, p
151151
}
152152

153153
// validateUsageOfDeclaredPipelineTaskParameters validates that all parameters referenced in the pipeline Task are declared by the pipeline Task.
154-
func (l PipelineTaskList) validateUsageOfDeclaredPipelineTaskParameters(ctx context.Context, path string) (errs *apis.FieldError) {
154+
func (l PipelineTaskList) validateUsageOfDeclaredPipelineTaskParameters(ctx context.Context, additionalParams []ParamSpec, path string) (errs *apis.FieldError) {
155155
for i, t := range l {
156156
if t.TaskSpec != nil {
157-
errs = errs.Also(ValidateUsageOfDeclaredParameters(ctx, t.TaskSpec.Steps, t.TaskSpec.Params).ViaFieldIndex(path, i))
157+
errs = errs.Also(ValidateUsageOfDeclaredParameters(ctx, t.TaskSpec.Steps, append(t.TaskSpec.Params, additionalParams...)).ViaFieldIndex(path, i))
158158
}
159159
}
160160
return errs
@@ -385,8 +385,8 @@ func validatePipelineWorkspacesDeclarations(wss []PipelineWorkspaceDeclaration)
385385

386386
// validatePipelineParameterUsage validates that parameters referenced in the Pipeline are declared by the Pipeline
387387
func (ps *PipelineSpec) validatePipelineParameterUsage(ctx context.Context) (errs *apis.FieldError) {
388-
errs = errs.Also(PipelineTaskList(ps.Tasks).validateUsageOfDeclaredPipelineTaskParameters(ctx, "tasks"))
389-
errs = errs.Also(PipelineTaskList(ps.Finally).validateUsageOfDeclaredPipelineTaskParameters(ctx, "finally"))
388+
errs = errs.Also(PipelineTaskList(ps.Tasks).validateUsageOfDeclaredPipelineTaskParameters(ctx, ps.Params, "tasks"))
389+
errs = errs.Also(PipelineTaskList(ps.Finally).validateUsageOfDeclaredPipelineTaskParameters(ctx, ps.Params, "finally"))
390390
errs = errs.Also(validatePipelineTaskParameterUsage(ps.Tasks, ps.Params).ViaField("tasks"))
391391
errs = errs.Also(validatePipelineTaskParameterUsage(ps.Finally, ps.Params).ViaField("finally"))
392392
return errs

pkg/apis/pipeline/v1/pipeline_validation_test.go

+131
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,65 @@ func TestPipeline_Validate_Success(t *testing.T) {
114114
},
115115
},
116116
},
117+
}, {
118+
name: "propagating params into Step",
119+
p: &Pipeline{
120+
ObjectMeta: metav1.ObjectMeta{
121+
Name: "pipelinelinename",
122+
},
123+
Spec: PipelineSpec{
124+
Params: ParamSpecs{{
125+
Name: "pipeline-words",
126+
Type: ParamTypeArray,
127+
Default: &ParamValue{
128+
Type: ParamTypeArray,
129+
ArrayVal: []string{"hello", "pipeline"},
130+
},
131+
}},
132+
Tasks: []PipelineTask{{
133+
Name: "echoit",
134+
TaskSpec: &EmbeddedTask{TaskSpec: TaskSpec{
135+
Steps: []Step{{
136+
Name: "echo",
137+
Image: "ubuntu",
138+
Command: []string{"echo"},
139+
Args: []string{"$(params.pipeline-words[*])"},
140+
}},
141+
}},
142+
}},
143+
},
144+
},
145+
}, {
146+
name: "propagating object params with pipelinespec and taskspec",
147+
p: &Pipeline{
148+
ObjectMeta: metav1.ObjectMeta{
149+
Name: "pipelinelinename",
150+
},
151+
Spec: PipelineSpec{
152+
Params: ParamSpecs{{
153+
Name: "pipeline-words",
154+
Default: &ParamValue{
155+
Type: ParamTypeObject,
156+
ObjectVal: map[string]string{"hello": "pipeline"},
157+
},
158+
Type: ParamTypeObject,
159+
Properties: map[string]PropertySpec{
160+
"hello": {Type: ParamTypeString},
161+
},
162+
}},
163+
Tasks: []PipelineTask{{
164+
Name: "echoit",
165+
TaskSpec: &EmbeddedTask{TaskSpec: TaskSpec{
166+
Steps: []Step{{
167+
Name: "echo",
168+
Image: "ubuntu",
169+
Command: []string{"echo"},
170+
Args: []string{"$(params.pipeline-words.hello)"},
171+
}},
172+
}},
173+
}},
174+
},
175+
},
117176
}}
118177
for _, tt := range tests {
119178
t.Run(tt.name, func(t *testing.T) {
@@ -365,6 +424,78 @@ func TestPipeline_Validate_Failure(t *testing.T) {
365424
},
366425
})
367426
},
427+
}, {
428+
name: "propagating params with pipelinespec and taskspec",
429+
p: &Pipeline{
430+
ObjectMeta: metav1.ObjectMeta{
431+
Name: "pipelinename",
432+
},
433+
Spec: PipelineSpec{
434+
Params: ParamSpecs{{
435+
Name: "pipeline-words",
436+
Type: ParamTypeArray,
437+
Default: &ParamValue{
438+
Type: ParamTypeArray,
439+
ArrayVal: []string{"hello", "pipeline"},
440+
},
441+
}},
442+
Tasks: []PipelineTask{{
443+
Name: "echoit",
444+
TaskSpec: &EmbeddedTask{TaskSpec: TaskSpec{
445+
Steps: []Step{{
446+
Name: "echo",
447+
Image: "ubuntu",
448+
Command: []string{"echo"},
449+
Args: []string{"$(params.random-words[*])"},
450+
}},
451+
}},
452+
}},
453+
},
454+
},
455+
expectedError: apis.FieldError{
456+
Message: `non-existent variable in "$(params.random-words[*])"`,
457+
Paths: []string{"spec.tasks[0].steps[0].args[0]"},
458+
},
459+
}, {
460+
name: "propagating params to taskRef",
461+
p: &Pipeline{
462+
ObjectMeta: metav1.ObjectMeta{
463+
Name: "pipelinename",
464+
},
465+
Spec: PipelineSpec{
466+
Params: ParamSpecs{{
467+
Name: "hello",
468+
Type: ParamTypeString,
469+
Default: &ParamValue{
470+
Type: ParamTypeString,
471+
StringVal: "hi",
472+
},
473+
}},
474+
Tasks: []PipelineTask{{
475+
Name: "echoit",
476+
TaskRef: &TaskRef{
477+
Name: "remote-task",
478+
},
479+
Params: Params{{
480+
Name: "param1",
481+
Value: ParamValue{
482+
Type: ParamTypeString,
483+
StringVal: "$(params.param1)",
484+
},
485+
}, {
486+
Name: "holla",
487+
Value: ParamValue{
488+
Type: ParamTypeString,
489+
StringVal: "$(params.hello)",
490+
},
491+
}},
492+
}},
493+
},
494+
},
495+
expectedError: apis.FieldError{
496+
Message: `non-existent variable in "$(params.param1)"`,
497+
Paths: []string{"spec.tasks[0].params[param1]"},
498+
},
368499
}}
369500
for _, tt := range tests {
370501
t.Run(tt.name, func(t *testing.T) {

pkg/apis/pipeline/v1beta1/pipeline_validation.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -153,10 +153,10 @@ func (l PipelineTaskList) Validate(ctx context.Context, taskNames sets.String, p
153153
}
154154

155155
// validateUsageOfDeclaredPipelineTaskParameters validates that all parameters referenced in the pipeline Task are declared by the pipeline Task.
156-
func (l PipelineTaskList) validateUsageOfDeclaredPipelineTaskParameters(ctx context.Context, path string) (errs *apis.FieldError) {
156+
func (l PipelineTaskList) validateUsageOfDeclaredPipelineTaskParameters(ctx context.Context, additionalParams []ParamSpec, path string) (errs *apis.FieldError) {
157157
for i, t := range l {
158158
if t.TaskSpec != nil {
159-
errs = errs.Also(ValidateUsageOfDeclaredParameters(ctx, t.TaskSpec.Steps, t.TaskSpec.Params).ViaFieldIndex(path, i))
159+
errs = errs.Also(ValidateUsageOfDeclaredParameters(ctx, t.TaskSpec.Steps, append(t.TaskSpec.Params, additionalParams...)).ViaFieldIndex(path, i))
160160
}
161161
}
162162
return errs
@@ -403,8 +403,8 @@ func validatePipelineWorkspacesDeclarations(wss []PipelineWorkspaceDeclaration)
403403

404404
// validatePipelineParameterUsage validates that parameters referenced in the Pipeline are declared by the Pipeline
405405
func (ps *PipelineSpec) validatePipelineParameterUsage(ctx context.Context) (errs *apis.FieldError) {
406-
errs = errs.Also(PipelineTaskList(ps.Tasks).validateUsageOfDeclaredPipelineTaskParameters(ctx, "tasks"))
407-
errs = errs.Also(PipelineTaskList(ps.Finally).validateUsageOfDeclaredPipelineTaskParameters(ctx, "finally"))
406+
errs = errs.Also(PipelineTaskList(ps.Tasks).validateUsageOfDeclaredPipelineTaskParameters(ctx, ps.Params, "tasks"))
407+
errs = errs.Also(PipelineTaskList(ps.Finally).validateUsageOfDeclaredPipelineTaskParameters(ctx, ps.Params, "finally"))
408408
errs = errs.Also(validatePipelineTaskParameterUsage(ps.Tasks, ps.Params).ViaField("tasks"))
409409
errs = errs.Also(validatePipelineTaskParameterUsage(ps.Finally, ps.Params).ViaField("finally"))
410410
return errs

0 commit comments

Comments
 (0)