@@ -161,6 +161,9 @@ var _ = Context("creating resourceOverride with multiple jsonPatchOverrides to o
161161 Namespace : roNamespace ,
162162 },
163163 Spec : placementv1alpha1.ResourceOverrideSpec {
164+ Placement : & placementv1alpha1.PlacementRef {
165+ Name : crpName , // assigned CRP name
166+ },
164167 ResourceSelectors : configMapSelector (),
165168 Policy : & placementv1alpha1.OverridePolicy {
166169 OverrideRules : []placementv1alpha1.OverrideRule {
@@ -599,6 +602,9 @@ var _ = Context("creating resourceOverride with a templated rules with cluster n
599602 Namespace : roNamespace ,
600603 },
601604 Spec : placementv1alpha1.ResourceOverrideSpec {
605+ Placement : & placementv1alpha1.PlacementRef {
606+ Name : crpName , // assigned CRP name
607+ },
602608 ResourceSelectors : configMapSelector (),
603609 Policy : & placementv1alpha1.OverridePolicy {
604610 OverrideRules : []placementv1alpha1.OverrideRule {
@@ -693,6 +699,9 @@ var _ = Context("creating resourceOverride with delete configMap", Ordered, func
693699 Namespace : roNamespace ,
694700 },
695701 Spec : placementv1alpha1.ResourceOverrideSpec {
702+ Placement : & placementv1alpha1.PlacementRef {
703+ Name : crpName , // assigned CRP name
704+ },
696705 ResourceSelectors : configMapSelector (),
697706 Policy : & placementv1alpha1.OverridePolicy {
698707 OverrideRules : []placementv1alpha1.OverrideRule {
@@ -789,3 +798,138 @@ var _ = Context("creating resourceOverride with delete configMap", Ordered, func
789798 }, consistentlyDuration , consistentlyInterval ).Should (BeTrue (), "Failed to delete work resources on member cluster %s" , memberCluster .ClusterName )
790799 })
791800})
801+
802+ var _ = FContext ("creating resourceOverride with a templated rules with cluster label key replacement" , Ordered , func () {
803+ crpName := fmt .Sprintf (crpNameTemplate , GinkgoParallelProcess ())
804+ roName := fmt .Sprintf (roNameTemplate , GinkgoParallelProcess ())
805+ roNamespace := fmt .Sprintf (workNamespaceNameTemplate , GinkgoParallelProcess ())
806+
807+ BeforeAll (func () {
808+ By ("creating work resources" )
809+ createWorkResources ()
810+
811+ // Create the ro before crp so that the observed resource index is predictable.
812+ ro := & placementv1alpha1.ResourceOverride {
813+ ObjectMeta : metav1.ObjectMeta {
814+ Name : roName ,
815+ Namespace : roNamespace ,
816+ },
817+ Spec : placementv1alpha1.ResourceOverrideSpec {
818+ Placement : & placementv1alpha1.PlacementRef {
819+ Name : crpName , // assigned CRP name
820+ },
821+ ResourceSelectors : configMapSelector (),
822+ Policy : & placementv1alpha1.OverridePolicy {
823+ OverrideRules : []placementv1alpha1.OverrideRule {
824+ {
825+ ClusterSelector : & placementv1beta1.ClusterSelector {
826+ ClusterSelectorTerms : []placementv1beta1.ClusterSelectorTerm {
827+ {
828+ LabelSelector : & metav1.LabelSelector {
829+ MatchExpressions : []metav1.LabelSelectorRequirement {
830+ {
831+ Key : regionLabelName ,
832+ Operator : metav1 .LabelSelectorOpExists ,
833+ },
834+ {
835+ Key : envLabelName ,
836+ Operator : metav1 .LabelSelectorOpExists ,
837+ },
838+ },
839+ },
840+ },
841+ },
842+ },
843+ JSONPatchOverrides : []placementv1alpha1.JSONPatchOverride {
844+ {
845+ Operator : placementv1alpha1 .JSONPatchOverrideOpAdd ,
846+ Path : "/data/region" ,
847+ Value : apiextensionsv1.JSON {Raw : []byte (fmt .Sprintf (`"%s%s}"` , placementv1alpha1 .OverrideClusterLabelKeyVariablePrefix , regionLabelName ))},
848+ },
849+ {
850+ Operator : placementv1alpha1 .JSONPatchOverrideOpReplace ,
851+ Path : "/data/data" ,
852+ Value : apiextensionsv1.JSON {Raw : []byte (fmt .Sprintf (`"newdata-%s%s}"` , placementv1alpha1 .OverrideClusterLabelKeyVariablePrefix , regionLabelName ))},
853+ },
854+ },
855+ },
856+ },
857+ },
858+ },
859+ }
860+ By (fmt .Sprintf ("creating resourceOverride %s" , roName ))
861+ Expect (hubClient .Create (ctx , ro )).To (Succeed (), "Failed to create resourceOverride %s" , roName )
862+
863+ // Create the CRP.
864+ createCRP (crpName )
865+ })
866+
867+ AfterAll (func () {
868+ By (fmt .Sprintf ("deleting placement %s and related resources" , crpName ))
869+ ensureCRPAndRelatedResourcesDeleted (crpName , allMemberClusters )
870+
871+ By (fmt .Sprintf ("deleting resourceOverride %s" , roName ))
872+ cleanupResourceOverride (roName , roNamespace )
873+ })
874+
875+ It ("should update CRP status as expected" , func () {
876+ wantRONames := []placementv1beta1.NamespacedName {
877+ {Namespace : roNamespace , Name : fmt .Sprintf (placementv1alpha1 .OverrideSnapshotNameFmt , roName , 0 )},
878+ }
879+ crpStatusUpdatedActual := crpStatusWithOverrideUpdatedActual (workResourceIdentifiers (), allMemberClusterNames , "0" , nil , wantRONames )
880+ Eventually (crpStatusUpdatedActual , eventuallyDuration , eventuallyInterval ).Should (Succeed (), "Failed to update CRP %s status as expected" , crpName )
881+ })
882+
883+ It ("should replace the cluster label key in the configMap" , func () {
884+ cmName := fmt .Sprintf (appConfigMapNameTemplate , GinkgoParallelProcess ())
885+ cmNamespace := fmt .Sprintf (workNamespaceNameTemplate , GinkgoParallelProcess ())
886+ for _ , cluster := range allMemberClusters {
887+
888+ wantConfigMap := & corev1.ConfigMap {
889+ ObjectMeta : metav1.ObjectMeta {
890+ Name : cmName ,
891+ Namespace : cmNamespace ,
892+ },
893+ Data : map [string ]string {
894+ "data" : fmt .Sprintf ("newdata-%s" , labelsByClusterName [cluster.ClusterName ][envLabelName ]),
895+ "region" : labelsByClusterName [cluster.ClusterName ][regionLabelName ],
896+ },
897+ }
898+ configMapActual := configMapPlacedOnClusterActual (cluster , wantConfigMap )
899+ Eventually (configMapActual , eventuallyDuration , eventuallyInterval ).Should (Succeed (), "Failed to update configmap %s data as expected" , cmName )
900+ }
901+ })
902+
903+ It ("should handle non-existent cluster label key gracefully" , func () {
904+ By ("Update the ResourceOverride to use a non-existent label key" )
905+ Eventually (func () error {
906+ ro := & placementv1alpha1.ResourceOverride {}
907+ if err := hubClient .Get (ctx , types.NamespacedName {Name : roName , Namespace : roNamespace }, ro ); err != nil {
908+ return err
909+ }
910+ ro .Spec .Policy .OverrideRules [0 ].JSONPatchOverrides [0 ].Value = apiextensionsv1.JSON {Raw : []byte (fmt .Sprintf (`"%snon-existent-label}"` , placementv1alpha1 .OverrideClusterLabelKeyVariablePrefix ))}
911+ return hubClient .Update (ctx , ro )
912+ }, eventuallyDuration , eventuallyInterval ).Should (Succeed (), "Failed to update resourceOverride %s with non-existent label key" , roName )
913+
914+ // Verify CRP status reflects the error
915+ crpStatusUpdatedActual := crpStatusWithOverrideUpdatedFailedActual (workResourceIdentifiers (), allMemberClusterNames , "0" , nil , nil )
916+ Eventually (crpStatusUpdatedActual , eventuallyDuration , eventuallyInterval ).Should (Succeed (), "CRP %s status should reflect the error due to non-existent label key" , crpName )
917+
918+ // Verify the configMap remains unchanged
919+ cmName := fmt .Sprintf (appConfigMapNameTemplate , GinkgoParallelProcess ())
920+ cmNamespace := fmt .Sprintf (workNamespaceNameTemplate , GinkgoParallelProcess ())
921+ for _ , cluster := range allMemberClusters {
922+ wantConfigMap := & corev1.ConfigMap {
923+ ObjectMeta : metav1.ObjectMeta {
924+ Name : cmName ,
925+ Namespace : cmNamespace ,
926+ },
927+ Data : map [string ]string {
928+ "region" : labelsByClusterName [cluster.ClusterName ][regionLabelName ],
929+ },
930+ }
931+ configMapActual := configMapPlacedOnClusterActual (cluster , wantConfigMap )
932+ Consistently (configMapActual , consistentlyDuration , consistentlyInterval ).Should (Succeed (), "ConfigMap %s should remain unchanged" , cmName )
933+ }
934+ })
935+ })
0 commit comments