@@ -2,6 +2,7 @@ package pipelinerun
22
33import (
44 "context"
5+ "fmt"
56 "testing"
67
78 "github.com/google/go-cmp/cmp"
@@ -12,7 +13,14 @@ import (
1213 "github.com/tektoncd/pipeline/test/diff"
1314 "github.com/tektoncd/pipeline/test/names"
1415 corev1 "k8s.io/api/core/v1"
16+ apierrors "k8s.io/apimachinery/pkg/api/errors"
1517 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
18+ "k8s.io/apimachinery/pkg/runtime"
19+ "k8s.io/apimachinery/pkg/runtime/schema"
20+ "k8s.io/apimachinery/pkg/util/validation/field"
21+ ktesting "k8s.io/client-go/testing"
22+ "knative.dev/pkg/apis"
23+ "knative.dev/pkg/controller"
1624)
1725
1826// TestReconcile_ChildPipelineRunPipelineSpec verifies the reconciliation logic for PipelineRuns that create child
@@ -278,3 +286,138 @@ func TestReconcile_NestedChildPipelineRuns(t *testing.T) {
278286 []* v1.PipelineRun {expectedGrandchildPipelineRun },
279287 )
280288}
289+
290+ func TestReconcile_PropagateLabelsAndAnnotationsToChild (t * testing.T ) {
291+ names .TestingSeed ()
292+ // GIVEN
293+ namespace := "foo"
294+ parentPipeline ,
295+ parentPipelineRun ,
296+ expectedChildPipelineRun := th .OnePipelineInPipeline (t , namespace , "parent-pipeline-run" )
297+ expectedChildPipelineRun = th .WithAnnotationAndLabel (expectedChildPipelineRun , false )
298+ testData := test.Data {
299+ PipelineRuns : []* v1.PipelineRun {th .WithAnnotationAndLabel (parentPipelineRun , true )},
300+ Pipelines : []* v1.Pipeline {parentPipeline },
301+ ConfigMaps : []* corev1.ConfigMap {withEnabledAlphaAPIFields (newFeatureFlagsConfigMap ())},
302+ }
303+
304+ // WHEN
305+ reconciledRun , childPipelineRuns := reconcileOncePinP (
306+ t ,
307+ testData ,
308+ namespace ,
309+ parentPipelineRun .Name ,
310+ []string {},
311+ )
312+
313+ // THEN
314+ validatePinP (
315+ t ,
316+ reconciledRun .Status ,
317+ reconciledRun .Name ,
318+ childPipelineRuns ,
319+ []* v1.PipelineRun {expectedChildPipelineRun },
320+ )
321+ }
322+
323+ func TestReconcile_ChildPipelineRunHasDefaultLabels (t * testing.T ) {
324+ names .TestingSeed ()
325+ // GIVEN
326+ namespace := "foo"
327+ parentPipeline ,
328+ parentPipelineRun ,
329+ expectedChildPipelineRun := th .OnePipelineInPipeline (t , namespace , "parent-pipeline-run" )
330+ expectedLabels := map [string ]string {
331+ pipeline .PipelineRunLabelKey : parentPipelineRun .Name ,
332+ pipeline .PipelineLabelKey : parentPipelineRun .Spec .PipelineRef .Name ,
333+ pipeline .PipelineRunUIDLabelKey : string (parentPipelineRun .UID ),
334+ pipeline .PipelineTaskLabelKey : parentPipeline .Spec .Tasks [0 ].Name ,
335+ pipeline .MemberOfLabelKey : v1 .PipelineTasks ,
336+ }
337+ testData := test.Data {
338+ PipelineRuns : []* v1.PipelineRun {parentPipelineRun },
339+ Pipelines : []* v1.Pipeline {parentPipeline },
340+ ConfigMaps : []* corev1.ConfigMap {withEnabledAlphaAPIFields (newFeatureFlagsConfigMap ())},
341+ }
342+
343+ // WHEN
344+ _ , childPipelineRuns := reconcileOncePinP (
345+ t ,
346+ testData ,
347+ namespace ,
348+ parentPipelineRun .Name ,
349+ []string {},
350+ )
351+
352+ // THEN
353+ validateChildPipelineRunCount (t , childPipelineRuns , 1 )
354+
355+ child := childPipelineRuns [expectedChildPipelineRun .Name ]
356+ for k , v := range expectedLabels {
357+ if childPipelineRuns [expectedChildPipelineRun .Name ].Labels [k ] != v {
358+ t .Errorf ("Expected label %q=%q on child PipelineRun, got %q" , k , v , child .Labels [k ])
359+ }
360+ }
361+ }
362+
363+ func TestReconcile_ChildPipelineRunCreationError (t * testing.T ) {
364+ names .TestingSeed ()
365+ // GIVEN
366+ namespace := "foo"
367+ parentPipeline ,
368+ parentPipelineRun ,
369+ expectedChildPipelineRun := th .OnePipelineInPipeline (t , namespace , "parent-pipeline-run" )
370+
371+ testCases := []struct {
372+ name string
373+ creationErr error
374+ }{
375+ {
376+ name : "invalid" ,
377+ creationErr : apierrors .NewInvalid (
378+ schema.GroupKind {},
379+ expectedChildPipelineRun .Name ,
380+ field.ErrorList {}),
381+ },
382+ {
383+ name : "bad request" ,
384+ creationErr : apierrors .NewBadRequest ("bad request" ),
385+ },
386+ }
387+
388+ for _ , tc := range testCases {
389+ t .Run (tc .name , func (t * testing.T ) {
390+ testData := test.Data {
391+ PipelineRuns : []* v1.PipelineRun {parentPipelineRun },
392+ Pipelines : []* v1.Pipeline {parentPipeline },
393+ ConfigMaps : []* corev1.ConfigMap {withEnabledAlphaAPIFields (newFeatureFlagsConfigMap ())},
394+ }
395+ prt := newPipelineRunTest (t , testData )
396+ defer prt .Cancel ()
397+
398+ clients := prt .TestAssets .Clients
399+
400+ // Simulate error when creating child PipelineRun's TaskRun
401+ clients .Pipeline .PrependReactor ("create" , "pipelineruns" , func (action ktesting.Action ) (bool , runtime.Object , error ) {
402+ return true , nil , tc .creationErr
403+ })
404+
405+ err := prt .TestAssets .Controller .Reconciler .Reconcile (prt .TestAssets .Ctx , fmt .Sprintf ("%s/%s" , namespace , parentPipelineRun .Name ))
406+ if ! controller .IsPermanentError (err ) {
407+ t .Errorf ("expected permanent error but got %s" , err )
408+ }
409+ reconciledRun , err := clients .Pipeline .TektonV1 ().PipelineRuns (namespace ).Get (prt .TestAssets .Ctx , parentPipelineRun .Name , metav1.GetOptions {})
410+ if err != nil {
411+ t .Fatalf ("Somehow had error getting reconciled run out of fake client: %s" , err )
412+ }
413+
414+ if reconciledRun .Status .CompletionTime == nil {
415+ t .Errorf ("Expected a CompletionTime on invalid PipelineRun but was nil" )
416+ }
417+
418+ if reconciledRun .Status .GetCondition (apis .ConditionSucceeded ).Reason != "CreateRunFailed" {
419+ t .Errorf ("Expected PipelineRun to be create run failed, but condition reason is %s" , reconciledRun .Status .GetCondition (apis .ConditionSucceeded ))
420+ }
421+ })
422+ }
423+ }
0 commit comments