@@ -350,6 +350,153 @@ metadata:
350350 })
351351}
352352
353+ func TestKustomizationReconciler_VarsubAlways (t * testing.T ) {
354+ ctx := context .Background ()
355+
356+ g := NewWithT (t )
357+ id := "vars-" + randStringRunes (5 )
358+ revision := "v1.0.0/" + randStringRunes (7 )
359+
360+ err := createNamespace (id )
361+ g .Expect (err ).NotTo (HaveOccurred (), "failed to create test namespace" )
362+
363+ err = createKubeConfigSecret (id )
364+ g .Expect (err ).NotTo (HaveOccurred (), "failed to create kubeconfig secret" )
365+
366+ // The manifest only relies on substitution expressions with defaults and
367+ // defines no variables through substitute or substituteFrom.
368+ manifests := func (name string ) []testserver.File {
369+ return []testserver.File {
370+ {
371+ Name : "service-account.yaml" ,
372+ Body : fmt .Sprintf (`
373+ apiVersion: v1
374+ kind: ServiceAccount
375+ metadata:
376+ name: %[1]s
377+ namespace: %[1]s
378+ labels:
379+ color: "${color:=blue}"
380+ shape: "${shape:=square}"
381+ ` , name ),
382+ },
383+ }
384+ }
385+
386+ artifact , err := testServer .ArtifactFromFiles (manifests (id ))
387+ g .Expect (err ).NotTo (HaveOccurred ())
388+
389+ repositoryName := types.NamespacedName {
390+ Name : randStringRunes (5 ),
391+ Namespace : id ,
392+ }
393+
394+ err = applyGitRepository (repositoryName , artifact , revision )
395+ g .Expect (err ).NotTo (HaveOccurred ())
396+
397+ resultSA := & corev1.ServiceAccount {}
398+
399+ t .Run ("WithVariables strategy skips substitution without variables" , func (t * testing.T ) {
400+ g := NewWithT (t )
401+
402+ name := id + "-with-variables"
403+ inputK := & kustomizev1.Kustomization {
404+ ObjectMeta : metav1.ObjectMeta {
405+ Name : name ,
406+ Namespace : id ,
407+ },
408+ Spec : kustomizev1.KustomizationSpec {
409+ KubeConfig : & meta.KubeConfigReference {
410+ SecretRef : & meta.SecretKeyReference {
411+ Name : "kubeconfig" ,
412+ },
413+ },
414+ Interval : metav1.Duration {Duration : reconciliationInterval },
415+ Path : "./" ,
416+ Prune : true ,
417+ TargetNamespace : id ,
418+ SourceRef : kustomizev1.CrossNamespaceSourceReference {
419+ Kind : sourcev1 .GitRepositoryKind ,
420+ Name : repositoryName .Name ,
421+ },
422+ // PostBuild without variables and the default WithVariables strategy.
423+ PostBuild : & kustomizev1.PostBuild {},
424+ Wait : true ,
425+ },
426+ }
427+ g .Expect (k8sClient .Create (ctx , inputK )).Should (Succeed ())
428+ defer func () { g .Expect (k8sClient .Delete (ctx , inputK )).To (Succeed ()) }()
429+
430+ // The ServiceAccount fails to apply because the unresolved expressions
431+ // are invalid label values, proving substitution was skipped.
432+ g .Eventually (func () bool {
433+ resultK := & kustomizev1.Kustomization {}
434+ _ = k8sClient .Get (ctx , client .ObjectKeyFromObject (inputK ), resultK )
435+ for _ , c := range resultK .Status .Conditions {
436+ if c .Reason == meta .ReconciliationFailedReason && c .Status == metav1 .ConditionFalse {
437+ return true
438+ }
439+ }
440+ return false
441+ }, timeout , interval ).Should (BeTrue ())
442+ })
443+
444+ t .Run ("Always strategy substitutes defaults without variables" , func (t * testing.T ) {
445+ g := NewWithT (t )
446+
447+ name := id + "-always"
448+ inputK := & kustomizev1.Kustomization {
449+ ObjectMeta : metav1.ObjectMeta {
450+ Name : name ,
451+ Namespace : id ,
452+ },
453+ Spec : kustomizev1.KustomizationSpec {
454+ KubeConfig : & meta.KubeConfigReference {
455+ SecretRef : & meta.SecretKeyReference {
456+ Name : "kubeconfig" ,
457+ },
458+ },
459+ Interval : metav1.Duration {Duration : reconciliationInterval },
460+ Path : "./" ,
461+ Prune : true ,
462+ SourceRef : kustomizev1.CrossNamespaceSourceReference {
463+ Kind : sourcev1 .GitRepositoryKind ,
464+ Name : repositoryName .Name ,
465+ },
466+ // PostBuild with no variables but the Always strategy.
467+ PostBuild : & kustomizev1.PostBuild {
468+ SubstituteStrategy : kustomizev1 .SubstituteStrategyAlways ,
469+ },
470+ HealthChecks : []meta.NamespacedObjectKindReference {
471+ {
472+ APIVersion : "v1" ,
473+ Kind : "ServiceAccount" ,
474+ Name : id ,
475+ Namespace : id ,
476+ },
477+ },
478+ },
479+ }
480+ g .Expect (k8sClient .Create (ctx , inputK )).Should (Succeed ())
481+ defer func () { g .Expect (k8sClient .Delete (ctx , inputK )).To (Succeed ()) }()
482+
483+ g .Eventually (func () bool {
484+ resultK := & kustomizev1.Kustomization {}
485+ _ = k8sClient .Get (ctx , client .ObjectKeyFromObject (inputK ), resultK )
486+ for _ , c := range resultK .Status .Conditions {
487+ if c .Reason == meta .ReconciliationSucceededReason {
488+ return true
489+ }
490+ }
491+ return false
492+ }, timeout , interval ).Should (BeTrue ())
493+
494+ g .Expect (k8sClient .Get (ctx , types.NamespacedName {Name : id , Namespace : id }, resultSA )).Should (Succeed ())
495+ g .Expect (resultSA .Labels ["color" ]).To (Equal ("blue" ))
496+ g .Expect (resultSA .Labels ["shape" ]).To (Equal ("square" ))
497+ })
498+ }
499+
353500func TestKustomizationReconciler_VarsubNumberBool (t * testing.T ) {
354501 ctx := context .Background ()
355502
0 commit comments