Skip to content

Commit a5c02ae

Browse files
committed
pipelinetask metadata
Adding metadata to TaskSpec in PipelineTask to allow specifying metadata. This metadata will be propogated to taskRun and then to the pods. ``` apiVersion: tekton.dev/v1beta1 kind: PipelineRun metadata: name: pipelinerun-with-taskspec-to-echo-greetings spec: pipelineSpec: tasks: - name: echo-greetings taskSpec: metadata: labels: [ …] steps: ... ``` Metadata is already supported as part of Tasks and Pipelines while respective CRDs are created. But was not possible to specify with embedded resources.
1 parent 3a7a693 commit a5c02ae

13 files changed

+347
-77
lines changed

docs/pipelineruns.md

+22
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,28 @@ spec:
119119
In the [`taskSpec` in `pipelineSpec` example](../examples/v1beta1/pipelineruns/pipelinerun-with-pipelinespec-and-taskspec.yaml)
120120
it's `Tasks` all the way down!
121121

122+
You can also specify labels and annotations with `taskSpec` which are propagated to each `taskRun` and then to the
123+
respective pods. These labels can be used to identify and filter pods for further actions (such as collecting pod metrics,
124+
and cleaning up completed pod with certain labels, etc) even being part of one single Pipeline.
125+
126+
```yaml
127+
spec:
128+
pipelineSpec:
129+
tasks:
130+
- name: task1
131+
metadata:
132+
labels:
133+
pipeline-sdk-type: kfp
134+
taskSpec:
135+
...
136+
- name: task2
137+
metadata:
138+
labels:
139+
pipeline-sdk-type: tfx
140+
taskSpec:
141+
...
142+
```
143+
122144
## Specifying `Resources`
123145

124146
A `Pipeline` requires [`PipelineResources`](resources.md) to provide inputs and store outputs

examples/v1beta1/pipelineruns/pipelinerun-with-pipelinespec-and-taskspec.yaml

+3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ spec:
77
tasks:
88
- name: echo-good-morning
99
taskSpec:
10+
metadata:
11+
labels:
12+
app: "example"
1013
steps:
1114
- name: echo
1215
image: ubuntu

internal/builder/v1beta1/pipeline.go

+14-1
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,20 @@ func PipelineRunResult(name, value string) PipelineRunStatusOp {
198198
// PipelineTaskSpec sets the TaskSpec on a PipelineTask.
199199
func PipelineTaskSpec(spec *v1beta1.TaskSpec) PipelineTaskOp {
200200
return func(pt *v1beta1.PipelineTask) {
201-
pt.TaskSpec = spec
201+
if pt.TaskSpec == nil {
202+
pt.TaskSpec = &v1beta1.EmbeddedTask{}
203+
}
204+
pt.TaskSpec.TaskSpec = spec
205+
}
206+
}
207+
208+
// TaskSpecMetadata sets the Metadata on a TaskSpec within PipelineTask.
209+
func TaskSpecMetadata(metadata v1beta1.Metadata) PipelineTaskOp {
210+
return func(pt *v1beta1.PipelineTask) {
211+
if pt.TaskSpec == nil {
212+
pt.TaskSpec = &v1beta1.EmbeddedTask{}
213+
}
214+
pt.TaskSpec.Metadata = metadata
202215
}
203216
}
204217

internal/builder/v1beta1/pipeline_test.go

+28-12
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,14 @@ func TestPipeline(t *testing.T) {
5757
tb.RunAfter("foo"),
5858
tb.PipelineTaskTimeout(5*time.Second),
5959
),
60-
tb.PipelineTask("foo", "", tb.PipelineTaskSpec(&v1beta1.TaskSpec{
61-
Steps: []v1beta1.Step{{Container: corev1.Container{
62-
Name: "step",
63-
Image: "myimage",
64-
}}},
65-
})),
60+
tb.PipelineTask("foo", "", tb.PipelineTaskSpec(getTaskSpec())),
61+
tb.PipelineTask("task-with-taskSpec", "",
62+
tb.TaskSpecMetadata(v1beta1.Metadata{
63+
Labels: map[string]string{"label": "labelvalue"},
64+
Annotations: map[string]string{"annotation": "annotationvalue"}},
65+
),
66+
tb.PipelineTaskSpec(getTaskSpec()),
67+
),
6668
tb.PipelineWorkspaceDeclaration("workspace1"),
6769
),
6870
tb.PipelineCreationTimestamp(creationTime),
@@ -137,13 +139,19 @@ func TestPipeline(t *testing.T) {
137139
Timeout: &metav1.Duration{Duration: 5 * time.Second},
138140
}, {
139141
Name: "foo",
140-
TaskSpec: &v1beta1.TaskSpec{
141-
Steps: []v1beta1.Step{{Container: corev1.Container{
142-
Name: "step",
143-
Image: "myimage",
144-
}}},
142+
TaskSpec: &v1beta1.EmbeddedTask{
143+
TaskSpec: getTaskSpec()},
144+
}, {
145+
Name: "task-with-taskSpec",
146+
TaskSpec: &v1beta1.EmbeddedTask{
147+
Metadata: v1beta1.Metadata{
148+
Labels: map[string]string{"label": "labelvalue"},
149+
Annotations: map[string]string{"annotation": "annotationvalue"},
150+
},
151+
TaskSpec: getTaskSpec(),
145152
},
146-
}},
153+
},
154+
},
147155
Workspaces: []v1beta1.PipelineWorkspaceDeclaration{{
148156
Name: "workspace1",
149157
}},
@@ -426,5 +434,13 @@ func TestPipelineRunWithFinalTask(t *testing.T) {
426434
if diff := cmp.Diff(expectedPipelineRun, pipelineRun); diff != "" {
427435
t.Fatalf("PipelineRun diff -want, +got: %s", diff)
428436
}
437+
}
429438

439+
func getTaskSpec() *v1beta1.TaskSpec {
440+
return &v1beta1.TaskSpec{
441+
Steps: []v1beta1.Step{{Container: corev1.Container{
442+
Name: "step",
443+
Image: "myimage",
444+
}}},
445+
}
430446
}

pkg/apis/pipeline/v1alpha1/pipeline_conversion.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ func (source *PipelineTask) ConvertTo(ctx context.Context, sink *v1beta1.Pipelin
6161
sink.Name = source.Name
6262
sink.TaskRef = source.TaskRef
6363
if source.TaskSpec != nil {
64-
sink.TaskSpec = &v1beta1.TaskSpec{}
65-
if err := source.TaskSpec.ConvertTo(ctx, sink.TaskSpec); err != nil {
64+
sink.TaskSpec = &v1beta1.EmbeddedTask{TaskSpec: &v1beta1.TaskSpec{}}
65+
if err := source.TaskSpec.ConvertTo(ctx, sink.TaskSpec.TaskSpec); err != nil {
6666
return err
6767
}
6868
}
@@ -112,7 +112,7 @@ func (sink *PipelineTask) ConvertFrom(ctx context.Context, source v1beta1.Pipeli
112112
sink.TaskRef = source.TaskRef
113113
if source.TaskSpec != nil {
114114
sink.TaskSpec = &TaskSpec{}
115-
if err := sink.TaskSpec.ConvertFrom(ctx, source.TaskSpec); err != nil {
115+
if err := sink.TaskSpec.ConvertFrom(ctx, source.TaskSpec.TaskSpec); err != nil {
116116
return err
117117
}
118118
}

pkg/apis/pipeline/v1beta1/pipeline_defaults_test.go

+26-18
Original file line numberDiff line numberDiff line change
@@ -85,41 +85,49 @@ func TestPipelineSpec_SetDefaults(t *testing.T) {
8585
desc: "pipeline task with taskSpec - default param type must be " + string(v1beta1.ParamTypeString),
8686
ps: &v1beta1.PipelineSpec{
8787
Tasks: []v1beta1.PipelineTask{{
88-
Name: "foo", TaskSpec: &v1beta1.TaskSpec{
89-
Params: []v1beta1.ParamSpec{{
90-
Name: "string-param",
91-
}},
88+
Name: "foo", TaskSpec: &v1beta1.EmbeddedTask{
89+
TaskSpec: &v1beta1.TaskSpec{
90+
Params: []v1beta1.ParamSpec{{
91+
Name: "string-param",
92+
}},
93+
},
9294
},
9395
}},
9496
},
9597
want: &v1beta1.PipelineSpec{
9698
Tasks: []v1beta1.PipelineTask{{
97-
Name: "foo", TaskSpec: &v1beta1.TaskSpec{
98-
Params: []v1beta1.ParamSpec{{
99-
Name: "string-param",
100-
Type: v1beta1.ParamTypeString,
101-
}},
99+
Name: "foo", TaskSpec: &v1beta1.EmbeddedTask{
100+
TaskSpec: &v1beta1.TaskSpec{
101+
Params: []v1beta1.ParamSpec{{
102+
Name: "string-param",
103+
Type: v1beta1.ParamTypeString,
104+
}},
105+
},
102106
},
103107
}},
104108
},
105109
}, {
106110
desc: "final pipeline task with taskSpec - default param type must be " + string(v1beta1.ParamTypeString),
107111
ps: &v1beta1.PipelineSpec{
108112
Finally: []v1beta1.PipelineTask{{
109-
Name: "foo", TaskSpec: &v1beta1.TaskSpec{
110-
Params: []v1beta1.ParamSpec{{
111-
Name: "string-param",
112-
}},
113+
Name: "foo", TaskSpec: &v1beta1.EmbeddedTask{
114+
TaskSpec: &v1beta1.TaskSpec{
115+
Params: []v1beta1.ParamSpec{{
116+
Name: "string-param",
117+
}},
118+
},
113119
},
114120
}},
115121
},
116122
want: &v1beta1.PipelineSpec{
117123
Finally: []v1beta1.PipelineTask{{
118-
Name: "foo", TaskSpec: &v1beta1.TaskSpec{
119-
Params: []v1beta1.ParamSpec{{
120-
Name: "string-param",
121-
Type: v1beta1.ParamTypeString,
122-
}},
124+
Name: "foo", TaskSpec: &v1beta1.EmbeddedTask{
125+
TaskSpec: &v1beta1.TaskSpec{
126+
Params: []v1beta1.ParamSpec{{
127+
Name: "string-param",
128+
Type: v1beta1.ParamTypeString,
129+
}},
130+
},
123131
},
124132
}},
125133
},

pkg/apis/pipeline/v1beta1/pipeline_types.go

+22-1
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,23 @@ type PipelineResult struct {
9090
Value string `json:"value"`
9191
}
9292

93+
type Metadata struct {
94+
// +optional
95+
Labels map[string]string `json:"labels,omitempty"`
96+
97+
// +optional
98+
Annotations map[string]string `json:"annotations,omitempty"`
99+
}
100+
101+
type EmbeddedTask struct {
102+
// +optional
103+
Metadata Metadata `json:"metadata,omitempty"`
104+
105+
// TaskSpec is a specification of a task
106+
// +optional
107+
*TaskSpec `json:",inline,omitempty"`
108+
}
109+
93110
// PipelineTask defines a task in a Pipeline, passing inputs from both
94111
// Params and from the output of previous tasks.
95112
type PipelineTask struct {
@@ -104,7 +121,7 @@ type PipelineTask struct {
104121

105122
// TaskSpec is a specification of a task
106123
// +optional
107-
TaskSpec *TaskSpec `json:"taskSpec,omitempty"`
124+
TaskSpec *EmbeddedTask `json:"taskSpec,inline,omitempty"`
108125

109126
// Conditions is a list of conditions that need to be true for the task to run
110127
// +optional
@@ -139,6 +156,10 @@ type PipelineTask struct {
139156
Timeout *metav1.Duration `json:"timeout,omitempty"`
140157
}
141158

159+
func (pt *PipelineTask) TaskSpecMetadata() Metadata {
160+
return pt.TaskSpec.Metadata
161+
}
162+
142163
func (pt PipelineTask) HashKey() string {
143164
return pt.Name
144165
}

pkg/apis/pipeline/v1beta1/pipeline_validation_test.go

+24-36
Original file line numberDiff line numberDiff line change
@@ -152,13 +152,9 @@ func TestPipelineSpec_Validate_Failure(t *testing.T) {
152152
Name: "valid-pipeline-task",
153153
TaskRef: &TaskRef{Name: "foo-task"},
154154
}, {
155-
Name: "invalid-pipeline-task",
156-
TaskRef: &TaskRef{Name: "foo-task"},
157-
TaskSpec: &TaskSpec{
158-
Steps: []Step{{
159-
Container: corev1.Container{Name: "foo", Image: "bar"},
160-
}},
161-
},
155+
Name: "invalid-pipeline-task",
156+
TaskRef: &TaskRef{Name: "foo-task"},
157+
TaskSpec: &EmbeddedTask{TaskSpec: getTaskSpec()},
162158
}},
163159
},
164160
}, {
@@ -250,12 +246,8 @@ func TestValidatePipelineTasks_Success(t *testing.T) {
250246
}, {
251247
name: "pipeline task with valid taskspec",
252248
tasks: []PipelineTask{{
253-
Name: "foo",
254-
TaskSpec: &TaskSpec{
255-
Steps: []Step{{
256-
Container: corev1.Container{Name: "foo", Image: "bar"},
257-
}},
258-
},
249+
Name: "foo",
250+
TaskSpec: &EmbeddedTask{TaskSpec: getTaskSpec()},
259251
}},
260252
}}
261253
for _, tt := range tests {
@@ -280,19 +272,15 @@ func TestValidatePipelineTasks_Failure(t *testing.T) {
280272
}, {
281273
name: "pipeline task with both taskref and taskspec",
282274
tasks: []PipelineTask{{
283-
Name: "foo",
284-
TaskRef: &TaskRef{Name: "foo-task"},
285-
TaskSpec: &TaskSpec{
286-
Steps: []Step{{
287-
Container: corev1.Container{Name: "foo", Image: "bar"},
288-
}},
289-
},
275+
Name: "foo",
276+
TaskRef: &TaskRef{Name: "foo-task"},
277+
TaskSpec: &EmbeddedTask{TaskSpec: getTaskSpec()},
290278
}},
291279
}, {
292280
name: "pipeline task with invalid taskspec",
293281
tasks: []PipelineTask{{
294282
Name: "foo",
295-
TaskSpec: &TaskSpec{},
283+
TaskSpec: &EmbeddedTask{TaskSpec: &TaskSpec{}},
296284
}},
297285
}, {
298286
name: "pipeline tasks invalid (duplicate tasks)",
@@ -660,14 +648,14 @@ func TestValidateGraph_Failure(t *testing.T) {
660648
func TestValidateParamResults_Success(t *testing.T) {
661649
desc := "valid pipeline task referencing task result along with parameter variable"
662650
tasks := []PipelineTask{{
663-
TaskSpec: &TaskSpec{
651+
TaskSpec: &EmbeddedTask{TaskSpec: &TaskSpec{
664652
Results: []TaskResult{{
665653
Name: "output",
666654
}},
667655
Steps: []Step{{
668656
Container: corev1.Container{Name: "foo", Image: "bar"},
669657
}},
670-
},
658+
}},
671659
Name: "a-task",
672660
}, {
673661
Name: "foo",
@@ -1041,12 +1029,8 @@ func TestValidatePipelineWithFinalTasks_Success(t *testing.T) {
10411029
Name: "final-task-1",
10421030
TaskRef: &TaskRef{Name: "final-task"},
10431031
}, {
1044-
Name: "final-task-2",
1045-
TaskSpec: &TaskSpec{
1046-
Steps: []Step{{
1047-
Container: corev1.Container{Name: "foo", Image: "bar"},
1048-
}},
1049-
},
1032+
Name: "final-task-2",
1033+
TaskSpec: &EmbeddedTask{TaskSpec: getTaskSpec()},
10501034
}},
10511035
},
10521036
},
@@ -1200,13 +1184,9 @@ func TestValidatePipelineWithFinalTasks_Failure(t *testing.T) {
12001184
TaskRef: &TaskRef{Name: "non-final-task"},
12011185
}},
12021186
Finally: []PipelineTask{{
1203-
Name: "final-task",
1204-
TaskRef: &TaskRef{Name: "non-final-task"},
1205-
TaskSpec: &TaskSpec{
1206-
Steps: []Step{{
1207-
Container: corev1.Container{Name: "foo", Image: "bar"},
1208-
}},
1209-
},
1187+
Name: "final-task",
1188+
TaskRef: &TaskRef{Name: "non-final-task"},
1189+
TaskSpec: &EmbeddedTask{TaskSpec: getTaskSpec()},
12101190
}},
12111191
},
12121192
},
@@ -1491,3 +1471,11 @@ func TestContextInvalid(t *testing.T) {
14911471
})
14921472
}
14931473
}
1474+
1475+
func getTaskSpec() *TaskSpec {
1476+
return &TaskSpec{
1477+
Steps: []Step{{
1478+
Container: corev1.Container{Name: "foo", Image: "bar"},
1479+
}},
1480+
}
1481+
}

0 commit comments

Comments
 (0)