Skip to content

Commit e44d0c0

Browse files
dicarlo2tekton-robot
authored andcommitted
Propagate annotations from Pipeline/Task to PipelineRun/TaskRun
With this change, annotations are propagated from Pipeline and Task to PipelineRun and TaskRun, respectively, giving us full annotation propagation from Pipeline to PipelineRun to TaskRun to Pod and Task to TaskRun to Pod.
1 parent 93703fb commit e44d0c0

File tree

9 files changed

+231
-28
lines changed

9 files changed

+231
-28
lines changed

pkg/reconciler/v1alpha1/pipelinerun/pipelinerun.go

+24-8
Original file line numberDiff line numberDiff line change
@@ -216,11 +216,11 @@ func (c *Reconciler) Reconcile(ctx context.Context, key string) error {
216216
return err
217217
}
218218
// Since we are using the status subresource, it is not possible to update
219-
// the status and labels simultaneously.
220-
if !reflect.DeepEqual(original.ObjectMeta.Labels, pr.ObjectMeta.Labels) {
221-
if _, err := c.updateLabels(pr); err != nil {
222-
c.Logger.Warn("Failed to update PipelineRun labels", zap.Error(err))
223-
c.Recorder.Event(pr, corev1.EventTypeWarning, eventReasonFailed, "PipelineRun failed to update labels")
219+
// the status and labels/annotations simultaneously.
220+
if !reflect.DeepEqual(original.ObjectMeta.Labels, pr.ObjectMeta.Labels) || !reflect.DeepEqual(original.ObjectMeta.Annotations, pr.ObjectMeta.Annotations) {
221+
if _, err := c.updateLabelsAndAnnotations(pr); err != nil {
222+
c.Logger.Warn("Failed to update PipelineRun labels/annotations", zap.Error(err))
223+
c.Recorder.Event(pr, corev1.EventTypeWarning, eventReasonFailed, "PipelineRun failed to update labels/annotations")
224224
return err
225225
}
226226
}
@@ -281,6 +281,14 @@ func (c *Reconciler) reconcile(ctx context.Context, pr *v1alpha1.PipelineRun) er
281281
}
282282
pr.ObjectMeta.Labels[pipeline.GroupName+pipeline.PipelineLabelKey] = p.Name
283283

284+
// Propagate annotations from Pipeline to PipelineRun.
285+
if pr.ObjectMeta.Annotations == nil {
286+
pr.ObjectMeta.Annotations = make(map[string]string, len(p.ObjectMeta.Annotations))
287+
}
288+
for key, value := range p.ObjectMeta.Annotations {
289+
pr.ObjectMeta.Annotations[key] = value
290+
}
291+
284292
pipelineState, err := resources.ResolvePipelineRun(
285293
*pr,
286294
func(name string) (v1alpha1.TaskInterface, error) {
@@ -455,6 +463,12 @@ func (c *Reconciler) createTaskRun(logger *zap.SugaredLogger, rprt *resources.Re
455463
}
456464
labels[pipeline.GroupName+pipeline.PipelineRunLabelKey] = pr.Name
457465

466+
// Propagate annotations from PipelineRun to TaskRun.
467+
annotations := make(map[string]string, len(pr.ObjectMeta.Annotations)+1)
468+
for key, val := range pr.ObjectMeta.Annotations {
469+
annotations[key] = val
470+
}
471+
458472
tr, _ := c.taskRunLister.TaskRuns(pr.Namespace).Get(rprt.TaskRunName)
459473

460474
if tr != nil {
@@ -473,6 +487,7 @@ func (c *Reconciler) createTaskRun(logger *zap.SugaredLogger, rprt *resources.Re
473487
Namespace: pr.Namespace,
474488
OwnerReferences: pr.GetOwnerReference(),
475489
Labels: labels,
490+
Annotations: annotations,
476491
},
477492
Spec: v1alpha1.TaskRunSpec{
478493
TaskRef: &v1alpha1.TaskRef{
@@ -524,13 +539,14 @@ func (c *Reconciler) updateStatus(pr *v1alpha1.PipelineRun) (*v1alpha1.PipelineR
524539
return newPr, nil
525540
}
526541

527-
func (c *Reconciler) updateLabels(pr *v1alpha1.PipelineRun) (*v1alpha1.PipelineRun, error) {
542+
func (c *Reconciler) updateLabelsAndAnnotations(pr *v1alpha1.PipelineRun) (*v1alpha1.PipelineRun, error) {
528543
newPr, err := c.pipelineRunLister.PipelineRuns(pr.Namespace).Get(pr.Name)
529544
if err != nil {
530-
return nil, fmt.Errorf("Error getting PipelineRun %s when updating labels: %s", pr.Name, err)
545+
return nil, fmt.Errorf("Error getting PipelineRun %s when updating labels/annotations: %s", pr.Name, err)
531546
}
532-
if !reflect.DeepEqual(pr.ObjectMeta.Labels, newPr.ObjectMeta.Labels) {
547+
if !reflect.DeepEqual(pr.ObjectMeta.Labels, newPr.ObjectMeta.Labels) || !reflect.DeepEqual(pr.ObjectMeta.Annotations, newPr.ObjectMeta.Annotations) {
533548
newPr.ObjectMeta.Labels = pr.ObjectMeta.Labels
549+
newPr.ObjectMeta.Annotations = pr.ObjectMeta.Annotations
534550
return c.PipelineClientSet.TektonV1alpha1().PipelineRuns(pr.Namespace).Update(newPr)
535551
}
536552
return newPr, nil

pkg/reconciler/v1alpha1/pipelinerun/pipelinerun_test.go

+62
Original file line numberDiff line numberDiff line change
@@ -892,3 +892,65 @@ func TestReconcileWithTimeoutAndRetry(t *testing.T) {
892892
})
893893
}
894894
}
895+
896+
func TestReconcilePropagateAnnotations(t *testing.T) {
897+
names.TestingSeed()
898+
899+
ps := []*v1alpha1.Pipeline{tb.Pipeline("test-pipeline", "foo", tb.PipelineSpec(
900+
tb.PipelineTask("hello-world-1", "hello-world"),
901+
))}
902+
prs := []*v1alpha1.PipelineRun{tb.PipelineRun("test-pipeline-run-with-annotations", "foo",
903+
tb.PipelineRunAnnotation("PipelineRunAnnotation", "PipelineRunValue"),
904+
tb.PipelineRunSpec("test-pipeline",
905+
tb.PipelineRunServiceAccount("test-sa"),
906+
),
907+
)}
908+
ts := []*v1alpha1.Task{tb.Task("hello-world", "foo")}
909+
910+
d := test.Data{
911+
PipelineRuns: prs,
912+
Pipelines: ps,
913+
Tasks: ts,
914+
}
915+
916+
// create fake recorder for testing
917+
fr := record.NewFakeRecorder(2)
918+
919+
testAssets := getPipelineRunController(t, d, fr)
920+
c := testAssets.Controller
921+
clients := testAssets.Clients
922+
923+
err := c.Reconciler.Reconcile(context.Background(), "foo/test-pipeline-run-with-annotations")
924+
if err != nil {
925+
t.Errorf("Did not expect to see error when reconciling completed PipelineRun but saw %s", err)
926+
}
927+
928+
// Check that the PipelineRun was reconciled correctly
929+
_, err = clients.Pipeline.Tekton().PipelineRuns("foo").Get("test-pipeline-run-with-annotations", metav1.GetOptions{})
930+
if err != nil {
931+
t.Fatalf("Somehow had error getting completed reconciled run out of fake client: %s", err)
932+
}
933+
934+
// Check that the expected TaskRun was created
935+
actual := clients.Pipeline.Actions()[0].(ktesting.CreateAction).GetObject().(*v1alpha1.TaskRun)
936+
if actual == nil {
937+
t.Errorf("Expected a TaskRun to be created, but it wasn't.")
938+
}
939+
expectedTaskRun := tb.TaskRun("test-pipeline-run-with-annotations-hello-world-1-9l9zj", "foo",
940+
tb.TaskRunOwnerReference("PipelineRun", "test-pipeline-run-with-annotations",
941+
tb.OwnerReferenceAPIVersion("tekton.dev/v1alpha1"),
942+
tb.Controller, tb.BlockOwnerDeletion,
943+
),
944+
tb.TaskRunLabel("tekton.dev/pipeline", "test-pipeline"),
945+
tb.TaskRunLabel("tekton.dev/pipelineRun", "test-pipeline-run-with-annotations"),
946+
tb.TaskRunAnnotation("PipelineRunAnnotation", "PipelineRunValue"),
947+
tb.TaskRunSpec(
948+
tb.TaskRunTaskRef("hello-world"),
949+
tb.TaskRunServiceAccount("test-sa"),
950+
),
951+
)
952+
953+
if d := cmp.Diff(actual, expectedTaskRun); d != "" {
954+
t.Errorf("expected to see TaskRun %v created. Diff %s", expectedTaskRun, d)
955+
}
956+
}

pkg/reconciler/v1alpha1/taskrun/resources/pod.go

+11-9
Original file line numberDiff line numberDiff line change
@@ -231,14 +231,6 @@ func TryGetPod(taskRunStatus v1alpha1.TaskRunStatus, gp GetPod) (*corev1.Pod, er
231231
// MakePod converts TaskRun and TaskSpec objects to a Pod which implements the taskrun specified
232232
// by the supplied CRD.
233233
func MakePod(taskRun *v1alpha1.TaskRun, taskSpec v1alpha1.TaskSpec, kubeclient kubernetes.Interface, cache *entrypoint.Cache, logger *zap.SugaredLogger) (*corev1.Pod, error) {
234-
// Copy annotations on the build through to the underlying pod to allow users
235-
// to specify pod annotations.
236-
annotations := map[string]string{}
237-
for key, val := range taskRun.Annotations {
238-
annotations[key] = val
239-
}
240-
annotations["sidecar.istio.io/inject"] = "false"
241-
242234
cred, secrets, err := makeCredentialInitializer(taskRun.Spec.ServiceAccount, taskRun.Namespace, kubeclient)
243235
if err != nil {
244236
return nil, err
@@ -329,7 +321,7 @@ func MakePod(taskRun *v1alpha1.TaskRun, taskSpec v1alpha1.TaskSpec, kubeclient k
329321
OwnerReferences: []metav1.OwnerReference{
330322
*metav1.NewControllerRef(taskRun, groupVersionKind),
331323
},
332-
Annotations: annotations,
324+
Annotations: makeAnnotations(taskRun),
333325
Labels: makeLabels(taskRun),
334326
},
335327
Spec: corev1.PodSpec{
@@ -355,6 +347,16 @@ func makeLabels(s *v1alpha1.TaskRun) map[string]string {
355347
return labels
356348
}
357349

350+
// makeAnnotations constructs the annotations we will propagate from TaskRuns to Pods.
351+
func makeAnnotations(s *v1alpha1.TaskRun) map[string]string {
352+
annotations := make(map[string]string, len(s.ObjectMeta.Annotations)+1)
353+
for k, v := range s.ObjectMeta.Annotations {
354+
annotations[k] = v
355+
}
356+
annotations["sidecar.istio.io/inject"] = "false"
357+
return annotations
358+
}
359+
358360
// zeroNonMaxResourceRequests zeroes out the container's cpu, memory, or
359361
// ephemeral storage resource requests if the container does not have the
360362
// largest request out of all containers in the pod. This is done because Tekton

pkg/reconciler/v1alpha1/taskrun/taskrun.go

+15-6
Original file line numberDiff line numberDiff line change
@@ -197,10 +197,10 @@ func (c *Reconciler) Reconcile(ctx context.Context, key string) error {
197197
return err
198198
}
199199
// Since we are using the status subresource, it is not possible to update
200-
// the status and labels simultaneously.
200+
// the status and labels/annotations simultaneously.
201201
if !reflect.DeepEqual(original.ObjectMeta.Labels, tr.ObjectMeta.Labels) {
202-
if _, err := c.updateLabels(tr); err != nil {
203-
c.Logger.Warn("Failed to update TaskRun labels", zap.Error(err))
202+
if _, err := c.updateLabelsAndAnnotations(tr); err != nil {
203+
c.Logger.Warn("Failed to update TaskRun labels/annotations", zap.Error(err))
204204
return err
205205
}
206206
}
@@ -264,6 +264,14 @@ func (c *Reconciler) reconcile(ctx context.Context, tr *v1alpha1.TaskRun) error
264264
tr.ObjectMeta.Labels[pipeline.GroupName+pipeline.TaskLabelKey] = taskMeta.Name
265265
}
266266

267+
// Propagate annotations from Task to TaskRun.
268+
if tr.ObjectMeta.Annotations == nil {
269+
tr.ObjectMeta.Annotations = make(map[string]string, len(taskMeta.Annotations))
270+
}
271+
for key, value := range taskMeta.Annotations {
272+
tr.ObjectMeta.Annotations[key] = value
273+
}
274+
267275
// Check if the TaskRun has timed out; if it is, this will set its status
268276
// accordingly.
269277
if timedOut, err := c.checkTimeout(tr, taskSpec, c.KubeClientSet.CoreV1().Pods(tr.Namespace).Delete); err != nil {
@@ -491,13 +499,14 @@ func (c *Reconciler) updateStatus(taskrun *v1alpha1.TaskRun) (*v1alpha1.TaskRun,
491499
return newtaskrun, nil
492500
}
493501

494-
func (c *Reconciler) updateLabels(tr *v1alpha1.TaskRun) (*v1alpha1.TaskRun, error) {
502+
func (c *Reconciler) updateLabelsAndAnnotations(tr *v1alpha1.TaskRun) (*v1alpha1.TaskRun, error) {
495503
newTr, err := c.taskRunLister.TaskRuns(tr.Namespace).Get(tr.Name)
496504
if err != nil {
497-
return nil, fmt.Errorf("Error getting TaskRun %s when updating labels: %s", tr.Name, err)
505+
return nil, fmt.Errorf("Error getting TaskRun %s when updating labels/annotations: %s", tr.Name, err)
498506
}
499-
if !reflect.DeepEqual(tr.ObjectMeta.Labels, newTr.ObjectMeta.Labels) {
507+
if !reflect.DeepEqual(tr.ObjectMeta.Labels, newTr.ObjectMeta.Labels) || !reflect.DeepEqual(tr.ObjectMeta.Annotations, newTr.ObjectMeta.Annotations) {
500508
newTr.ObjectMeta.Labels = tr.ObjectMeta.Labels
509+
newTr.ObjectMeta.Annotations = tr.ObjectMeta.Annotations
501510
return c.PipelineClientSet.TektonV1alpha1().TaskRuns(tr.Namespace).Update(newTr)
502511
}
503512
return newTr, nil

pkg/reconciler/v1alpha1/taskrun/taskrun_test.go

+44-1
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,13 @@ func TestReconcile(t *testing.T) {
304304
),
305305
)
306306

307+
taskRunWithAnnotations := tb.TaskRun("test-taskrun-with-annotations", "foo",
308+
tb.TaskRunAnnotation("TaskRunAnnotation", "TaskRunValue"),
309+
tb.TaskRunSpec(
310+
tb.TaskRunTaskRef(simpleTask.Name),
311+
),
312+
)
313+
307314
taskRunWithResourceRequests := tb.TaskRun("test-taskrun-with-resource-requests", "foo",
308315
tb.TaskRunSpec(
309316
tb.TaskRunTaskSpec(
@@ -347,7 +354,7 @@ func TestReconcile(t *testing.T) {
347354
taskRunSuccess, taskRunWithSaSuccess,
348355
taskRunTemplating, taskRunInputOutput,
349356
taskRunWithTaskSpec, taskRunWithClusterTask, taskRunWithResourceSpecAndTaskSpec,
350-
taskRunWithLabels, taskRunWithResourceRequests, taskRunTaskEnv, taskRunWithPod,
357+
taskRunWithLabels, taskRunWithAnnotations, taskRunWithResourceRequests, taskRunTaskEnv, taskRunWithPod,
351358
}
352359

353360
d := test.Data{
@@ -845,6 +852,42 @@ func TestReconcile(t *testing.T) {
845852
),
846853
),
847854
),
855+
}, {
856+
name: "taskrun-with-annotations",
857+
taskRun: taskRunWithAnnotations,
858+
wantPod: tb.Pod("test-taskrun-with-annotations-pod-123456", "foo",
859+
tb.PodAnnotation("sidecar.istio.io/inject", "false"),
860+
tb.PodAnnotation("TaskRunAnnotation", "TaskRunValue"),
861+
tb.PodLabel(taskNameLabelKey, "test-task"),
862+
tb.PodLabel(taskRunNameLabelKey, "test-taskrun-with-annotations"),
863+
tb.PodOwnerReference("TaskRun", "test-taskrun-with-annotations",
864+
tb.OwnerReferenceAPIVersion(currentApiVersion)),
865+
tb.PodSpec(
866+
tb.PodVolumes(toolsVolume, workspaceVolume, homeVolume),
867+
tb.PodRestartPolicy(corev1.RestartPolicyNever),
868+
getCredentialsInitContainer("9l9zj"),
869+
getPlaceToolsInitContainer(),
870+
tb.PodContainer("build-step-simple-step", "foo",
871+
tb.Command(entrypointLocation),
872+
tb.Args("-wait_file", "", "-post_file", "/builder/tools/0", "-entrypoint", "/mycmd", "--"),
873+
tb.WorkingDir(workspaceDir),
874+
tb.EnvVar("HOME", "/builder/home"),
875+
tb.VolumeMount("tools", "/builder/tools"),
876+
tb.VolumeMount("workspace", workspaceDir),
877+
tb.VolumeMount("home", "/builder/home"),
878+
tb.Resources(tb.Requests(
879+
tb.CPU("0"),
880+
tb.Memory("0"),
881+
tb.EphemeralStorage("0"),
882+
)),
883+
),
884+
tb.PodContainer("nop", "override-with-nop:latest",
885+
tb.Command("/builder/tools/entrypoint"),
886+
tb.Args("-wait_file", "/builder/tools/0", "-post_file", "/builder/tools/1", "-entrypoint", "/ko-app/nop", "--"),
887+
tb.VolumeMount(entrypoint.MountName, entrypoint.MountPoint),
888+
),
889+
),
890+
),
848891
}, {
849892
name: "task-env",
850893
taskRun: taskRunTaskEnv,

test/builder/pipeline.go

+10
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,16 @@ func PipelineRunLabel(key, value string) PipelineRunOp {
270270
}
271271
}
272272

273+
// PipelineRunAnnotations adds a annotation to the PipelineRun.
274+
func PipelineRunAnnotation(key, value string) PipelineRunOp {
275+
return func(pr *v1alpha1.PipelineRun) {
276+
if pr.ObjectMeta.Annotations == nil {
277+
pr.ObjectMeta.Annotations = map[string]string{}
278+
}
279+
pr.ObjectMeta.Annotations[key] = value
280+
}
281+
}
282+
273283
// PipelineRunResourceBinding adds bindings from actual instances to a Pipeline's declared resources.
274284
func PipelineRunResourceBinding(name string, ops ...PipelineResourceBindingOp) PipelineRunSpecOp {
275285
return func(prs *v1alpha1.PipelineRunSpec) {

test/builder/task.go

+12-2
Original file line numberDiff line numberDiff line change
@@ -266,8 +266,9 @@ func ParamDefault(value string) TaskParamOp {
266266
func TaskRun(name, namespace string, ops ...TaskRunOp) *v1alpha1.TaskRun {
267267
tr := &v1alpha1.TaskRun{
268268
ObjectMeta: metav1.ObjectMeta{
269-
Namespace: namespace,
270-
Name: name,
269+
Namespace: namespace,
270+
Name: name,
271+
Annotations: map[string]string{},
271272
},
272273
}
273274

@@ -395,6 +396,15 @@ func TaskRunLabel(key, value string) TaskRunOp {
395396
}
396397
}
397398

399+
func TaskRunAnnotation(key, value string) TaskRunOp {
400+
return func(tr *v1alpha1.TaskRun) {
401+
if tr.ObjectMeta.Annotations == nil {
402+
tr.ObjectMeta.Annotations = map[string]string{}
403+
}
404+
tr.ObjectMeta.Annotations[key] = value
405+
}
406+
}
407+
398408
// TaskRunSpec sets the specified spec of the TaskRun.
399409
// Any number of TaskRunSpec modifier can be passed to transform it.
400410
func TaskRunSpec(ops ...TaskRunSpecOp) TaskRunOp {

test/builder/task_test.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ func TestClusterTask(t *testing.T) {
117117
}
118118
}
119119

120-
func TestTaskRunWitTaskRef(t *testing.T) {
120+
func TestTaskRunWithTaskRef(t *testing.T) {
121121
var trueB = true
122122
taskRun := tb.TaskRun("test-taskrun", "foo",
123123
tb.TaskRunOwnerReference("PipelineRun", "test",
@@ -164,7 +164,8 @@ func TestTaskRunWitTaskRef(t *testing.T) {
164164
Controller: &trueB,
165165
BlockOwnerDeletion: &trueB,
166166
}},
167-
Labels: map[string]string{"label": "label-value"},
167+
Labels: map[string]string{"label": "label-value"},
168+
Annotations: map[string]string{},
168169
},
169170
Spec: v1alpha1.TaskRunSpec{
170171
Inputs: v1alpha1.TaskRunInputs{
@@ -223,6 +224,7 @@ func TestTaskRunWithTaskSpec(t *testing.T) {
223224
expectedTaskRun := &v1alpha1.TaskRun{
224225
ObjectMeta: metav1.ObjectMeta{
225226
Name: "test-taskrun", Namespace: "foo",
227+
Annotations: map[string]string{},
226228
},
227229
Spec: v1alpha1.TaskRunSpec{
228230
TaskSpec: &v1alpha1.TaskSpec{

0 commit comments

Comments
 (0)