open-cluster-management.io/governance-policy-propagator@v0.13.0/test/e2e/case1_propagation_test.go (about)

     1  // Copyright (c) 2020 Red Hat, Inc.
     2  // Copyright Contributors to the Open Cluster Management project
     3  
     4  package e2e
     5  
     6  import (
     7  	"context"
     8  	"strconv"
     9  
    10  	. "github.com/onsi/ginkgo/v2"
    11  	. "github.com/onsi/gomega"
    12  	"k8s.io/apimachinery/pkg/api/errors"
    13  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    14  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    15  	"k8s.io/apimachinery/pkg/runtime"
    16  	"k8s.io/apimachinery/pkg/types"
    17  	"k8s.io/client-go/dynamic"
    18  	appsv1 "open-cluster-management.io/multicloud-operators-subscription/pkg/apis/apps/placementrule/v1"
    19  
    20  	policiesv1 "open-cluster-management.io/governance-policy-propagator/api/v1"
    21  	"open-cluster-management.io/governance-policy-propagator/controllers/common"
    22  	"open-cluster-management.io/governance-policy-propagator/test/utils"
    23  )
    24  
    25  var _ = Describe("Test policy propagation", func() {
    26  	const (
    27  		case1PolicyName string = "case1-test-policy"
    28  		case1PolicyYaml string = "../resources/case1_propagation/case1-test-policy.yaml"
    29  	)
    30  
    31  	Describe("Test event emission when policy is disabled", Ordered, func() {
    32  		BeforeAll(func() {
    33  			By("Creating the policy, placementrule, and placementbinding")
    34  			utils.Kubectl("apply", "-f", case1PolicyYaml, "-n", testNamespace, "--kubeconfig="+kubeconfigHub)
    35  			plc := utils.GetWithTimeout(
    36  				clientHubDynamic, gvrPolicy, case1PolicyName, testNamespace, true, defaultTimeoutSeconds,
    37  			)
    38  			Expect(plc).NotTo(BeNil())
    39  
    40  			By("Patching test-policy-plr with decision of both managed1 and managed2")
    41  			plr := utils.GetWithTimeout(
    42  				clientHubDynamic, gvrPlacementRule, case1PolicyName+"-plr", testNamespace, true, defaultTimeoutSeconds,
    43  			)
    44  			plr.Object["status"] = utils.GeneratePlrStatus("managed1", "managed2")
    45  			_, err := clientHubDynamic.Resource(gvrPlacementRule).Namespace(testNamespace).UpdateStatus(
    46  				context.TODO(), plr, metav1.UpdateOptions{},
    47  			)
    48  			Expect(err).ToNot(HaveOccurred())
    49  			opt := metav1.ListOptions{
    50  				LabelSelector: common.RootPolicyLabel + "=" + testNamespace + "." + case1PolicyName,
    51  			}
    52  			utils.ListWithTimeout(clientHubDynamic, gvrPolicy, opt, 2, true, defaultTimeoutSeconds)
    53  		})
    54  
    55  		AfterAll(func() {
    56  			By("Removing the policy")
    57  			err := clientHubDynamic.Resource(gvrPolicy).Namespace(testNamespace).Delete(
    58  				context.TODO(),
    59  				case1PolicyName,
    60  				metav1.DeleteOptions{},
    61  			)
    62  			if !errors.IsNotFound(err) {
    63  				Expect(err).ToNot(HaveOccurred())
    64  			}
    65  
    66  			By("Removing the placementrule")
    67  			err = clientHubDynamic.Resource(gvrPlacementRule).Namespace(testNamespace).Delete(
    68  				context.TODO(),
    69  				case1PolicyName+"-plr",
    70  				metav1.DeleteOptions{},
    71  			)
    72  			if !errors.IsNotFound(err) {
    73  				Expect(err).ToNot(HaveOccurred())
    74  			}
    75  
    76  			By("Removing the PlacementBinding")
    77  			err = clientHubDynamic.Resource(gvrPlacementBinding).Namespace(testNamespace).Delete(
    78  				context.TODO(),
    79  				case1PolicyName+"-pb",
    80  				metav1.DeleteOptions{},
    81  			)
    82  			if !errors.IsNotFound(err) {
    83  				Expect(err).ToNot(HaveOccurred())
    84  			}
    85  		})
    86  
    87  		It("Should not create duplicate policy disable events", func() {
    88  			By("Disabling the root policy")
    89  			patch := []byte(`{"spec": {"disabled": ` + strconv.FormatBool(true) + `}}`)
    90  
    91  			_, err := clientHubDynamic.Resource(gvrPolicy).Namespace(testNamespace).Patch(
    92  				context.TODO(),
    93  				case1PolicyName,
    94  				types.MergePatchType,
    95  				patch,
    96  				metav1.PatchOptions{},
    97  			)
    98  			Expect(err).ToNot(HaveOccurred())
    99  
   100  			By("Checking the events emitted by the propagator in the root policy ns")
   101  			Consistently(func() int {
   102  				numEvents := len(utils.GetMatchingEvents(
   103  					clientHub,
   104  					testNamespace,
   105  					case1PolicyName,
   106  					"PolicyPropagation",
   107  					"disabled",
   108  					defaultTimeoutSeconds,
   109  				))
   110  
   111  				return numEvents
   112  			}, defaultTimeoutSeconds, 1).Should(BeNumerically("<", 2))
   113  		})
   114  	})
   115  
   116  	Describe("Create policy/pb/plc in ns:"+testNamespace+" and then update pb/plc", func() {
   117  		It("should be created in user ns", func() {
   118  			By("Creating " + case1PolicyYaml)
   119  			utils.Kubectl("apply",
   120  				"-f", case1PolicyYaml,
   121  				"-n", testNamespace,
   122  				"--kubeconfig="+kubeconfigHub)
   123  			plc := utils.GetWithTimeout(
   124  				clientHubDynamic, gvrPolicy, case1PolicyName, testNamespace, true, defaultTimeoutSeconds,
   125  			)
   126  			Expect(plc).NotTo(BeNil())
   127  		})
   128  		It("should propagate to cluster ns managed1", func() {
   129  			By("Patching test-policy-plr with decision of cluster managed1")
   130  			plr := utils.GetWithTimeout(
   131  				clientHubDynamic, gvrPlacementRule, case1PolicyName+"-plr", testNamespace, true, defaultTimeoutSeconds,
   132  			)
   133  			plr.Object["status"] = utils.GeneratePlrStatus("managed1")
   134  			_, err := clientHubDynamic.Resource(gvrPlacementRule).Namespace(testNamespace).UpdateStatus(
   135  				context.TODO(), plr, metav1.UpdateOptions{},
   136  			)
   137  			Expect(err).ToNot(HaveOccurred())
   138  			plc := utils.GetWithTimeout(
   139  				clientHubDynamic, gvrPolicy, testNamespace+"."+case1PolicyName, "managed1", true, defaultTimeoutSeconds,
   140  			)
   141  			Expect(plc).ToNot(BeNil())
   142  			opt := metav1.ListOptions{
   143  				LabelSelector: common.RootPolicyLabel + "=" + testNamespace + "." + case1PolicyName,
   144  			}
   145  			utils.ListWithTimeout(clientHubDynamic, gvrPolicy, opt, 1, true, defaultTimeoutSeconds)
   146  		})
   147  		It("should propagate to cluster ns managed2", func() {
   148  			By("Patching test-policy-plr with decision of cluster managed2")
   149  			plr := utils.GetWithTimeout(
   150  				clientHubDynamic, gvrPlacementRule, case1PolicyName+"-plr", testNamespace, true, defaultTimeoutSeconds,
   151  			)
   152  			plr.Object["status"] = utils.GeneratePlrStatus("managed2")
   153  			_, err := clientHubDynamic.Resource(gvrPlacementRule).Namespace(testNamespace).UpdateStatus(
   154  				context.TODO(), plr, metav1.UpdateOptions{},
   155  			)
   156  			Expect(err).ToNot(HaveOccurred())
   157  			plc := utils.GetWithTimeout(
   158  				clientHubDynamic, gvrPolicy, testNamespace+"."+case1PolicyName, "managed2", true, defaultTimeoutSeconds,
   159  			)
   160  			Expect(plc).ToNot(BeNil())
   161  			opt := metav1.ListOptions{
   162  				LabelSelector: common.RootPolicyLabel + "=" + testNamespace + "." + case1PolicyName,
   163  			}
   164  			utils.ListWithTimeout(clientHubDynamic, gvrPolicy, opt, 1, true, defaultTimeoutSeconds)
   165  		})
   166  		It("should propagate to cluster ns managed1 and managed2", func() {
   167  			By("Patching test-policy-plr with decision of both managed1 and managed2")
   168  			plr := utils.GetWithTimeout(
   169  				clientHubDynamic, gvrPlacementRule, case1PolicyName+"-plr", testNamespace, true, defaultTimeoutSeconds,
   170  			)
   171  			plr.Object["status"] = utils.GeneratePlrStatus("managed1", "managed2")
   172  			_, err := clientHubDynamic.Resource(gvrPlacementRule).Namespace(testNamespace).UpdateStatus(
   173  				context.TODO(), plr, metav1.UpdateOptions{},
   174  			)
   175  			Expect(err).ToNot(HaveOccurred())
   176  			opt := metav1.ListOptions{
   177  				LabelSelector: common.RootPolicyLabel + "=" + testNamespace + "." + case1PolicyName,
   178  			}
   179  			utils.ListWithTimeout(clientHubDynamic, gvrPolicy, opt, 2, true, defaultTimeoutSeconds)
   180  		})
   181  		It("should propagate to cluster ns managed1", func() {
   182  			By("Patching test-policy-plr with decision of cluster managed1")
   183  			plr := utils.GetWithTimeout(
   184  				clientHubDynamic, gvrPlacementRule, case1PolicyName+"-plr", testNamespace, true, defaultTimeoutSeconds,
   185  			)
   186  			plr.Object["status"] = utils.GeneratePlrStatus("managed1")
   187  			_, err := clientHubDynamic.Resource(gvrPlacementRule).Namespace(testNamespace).UpdateStatus(
   188  				context.TODO(), plr, metav1.UpdateOptions{},
   189  			)
   190  			Expect(err).ToNot(HaveOccurred())
   191  			plc := utils.GetWithTimeout(
   192  				clientHubDynamic,
   193  				gvrPolicy,
   194  				testNamespace+"."+case1PolicyName,
   195  				"managed1",
   196  				true,
   197  				defaultTimeoutSeconds,
   198  			)
   199  			Expect(plc).ToNot(BeNil())
   200  			plc = utils.GetWithTimeout(
   201  				clientHubDynamic,
   202  				gvrPolicy,
   203  				testNamespace+"."+case1PolicyName,
   204  				"managed2",
   205  				false,
   206  				defaultTimeoutSeconds,
   207  			)
   208  			Expect(plc).To(BeNil())
   209  			opt := metav1.ListOptions{
   210  				LabelSelector: common.RootPolicyLabel + "=" + testNamespace + "." + case1PolicyName,
   211  			}
   212  			utils.ListWithTimeout(clientHubDynamic, gvrPolicy, opt, 1, true, defaultTimeoutSeconds)
   213  		})
   214  		It("should propagate to cluster ns managed1 and managed2", func() {
   215  			By("Patching test-policy-plr with decision of both managed1 and managed2")
   216  			plr := utils.GetWithTimeout(
   217  				clientHubDynamic, gvrPlacementRule, case1PolicyName+"-plr", testNamespace, true, defaultTimeoutSeconds,
   218  			)
   219  			plr.Object["status"] = utils.GeneratePlrStatus("managed1", "managed2")
   220  			_, err := clientHubDynamic.Resource(gvrPlacementRule).Namespace(testNamespace).UpdateStatus(
   221  				context.TODO(), plr, metav1.UpdateOptions{},
   222  			)
   223  			Expect(err).ToNot(HaveOccurred())
   224  			opt := metav1.ListOptions{
   225  				LabelSelector: common.RootPolicyLabel + "=" + testNamespace + "." + case1PolicyName,
   226  			}
   227  			utils.ListWithTimeout(clientHubDynamic, gvrPolicy, opt, 2, true, defaultTimeoutSeconds)
   228  		})
   229  		It("should remove policy from ns managed1 and managed2", func() {
   230  			By("Patching test-policy-pb with a non existing plr")
   231  			pb := utils.GetWithTimeout(
   232  				clientHubDynamic,
   233  				gvrPlacementBinding,
   234  				case1PolicyName+"-pb",
   235  				testNamespace,
   236  				true,
   237  				defaultTimeoutSeconds,
   238  			)
   239  			pb.Object["placementRef"] = &policiesv1.Subject{
   240  				APIGroup: "apps.open-cluster-management.io",
   241  				Kind:     "PlacementRule",
   242  				Name:     case1PolicyName + "-plr-nonexists",
   243  			}
   244  			_, err := clientHubDynamic.Resource(gvrPlacementBinding).Namespace(testNamespace).Update(
   245  				context.TODO(), pb, metav1.UpdateOptions{},
   246  			)
   247  			Expect(err).ToNot(HaveOccurred())
   248  			opt := metav1.ListOptions{
   249  				LabelSelector: common.RootPolicyLabel + "=" + testNamespace + "." + case1PolicyName,
   250  			}
   251  			utils.ListWithTimeout(clientHubDynamic, gvrPolicy, opt, 0, true, defaultTimeoutSeconds)
   252  		})
   253  		It("should propagate to cluster ns managed1 and managed2", func() {
   254  			By("Patching test-policy-pb with correct plr")
   255  			pb := utils.GetWithTimeout(
   256  				clientHubDynamic,
   257  				gvrPlacementBinding,
   258  				case1PolicyName+"-pb",
   259  				testNamespace, true,
   260  				defaultTimeoutSeconds,
   261  			)
   262  			pb.Object["placementRef"] = &policiesv1.Subject{
   263  				APIGroup: "apps.open-cluster-management.io",
   264  				Kind:     "PlacementRule",
   265  				Name:     case1PolicyName + "-plr",
   266  			}
   267  			_, err := clientHubDynamic.Resource(gvrPlacementBinding).Namespace(testNamespace).Update(
   268  				context.TODO(), pb, metav1.UpdateOptions{},
   269  			)
   270  			Expect(err).ToNot(HaveOccurred())
   271  			opt := metav1.ListOptions{
   272  				LabelSelector: common.RootPolicyLabel + "=" + testNamespace + "." + case1PolicyName,
   273  			}
   274  			utils.ListWithTimeout(clientHubDynamic, gvrPolicy, opt, 2, true, defaultTimeoutSeconds)
   275  		})
   276  		It("should remove policy from ns managed1 and managed2", func() {
   277  			By("Patching test-policy-pb with a plc with wrong apigroup")
   278  			pb := utils.GetWithTimeout(
   279  				clientHubDynamic,
   280  				gvrPlacementBinding,
   281  				case1PolicyName+"-pb",
   282  				testNamespace,
   283  				true,
   284  				defaultTimeoutSeconds,
   285  			)
   286  			pb.Object["subjects"] = []policiesv1.Subject{
   287  				{
   288  					APIGroup: "policy1.open-cluster-management.io",
   289  					Kind:     "Policy",
   290  					Name:     case1PolicyName,
   291  				},
   292  			}
   293  			_, err := clientHubDynamic.Resource(gvrPlacementBinding).Namespace(testNamespace).Update(
   294  				context.TODO(), pb, metav1.UpdateOptions{},
   295  			)
   296  			Expect(err).To(HaveOccurred())
   297  		})
   298  		It("should propagate to cluster ns managed1 and managed2", func() {
   299  			By("Patching test-policy-pb with correct plc")
   300  			pb := utils.GetWithTimeout(
   301  				clientHubDynamic,
   302  				gvrPlacementBinding,
   303  				case1PolicyName+"-pb",
   304  				testNamespace, true,
   305  				defaultTimeoutSeconds,
   306  			)
   307  			pb.Object["subjects"] = []policiesv1.Subject{
   308  				{
   309  					APIGroup: "policy.open-cluster-management.io",
   310  					Kind:     "Policy",
   311  					Name:     case1PolicyName,
   312  				},
   313  			}
   314  			_, err := clientHubDynamic.Resource(gvrPlacementBinding).Namespace(testNamespace).Update(
   315  				context.TODO(), pb, metav1.UpdateOptions{},
   316  			)
   317  			Expect(err).ToNot(HaveOccurred())
   318  			opt := metav1.ListOptions{
   319  				LabelSelector: common.RootPolicyLabel + "=" + testNamespace + "." + case1PolicyName,
   320  			}
   321  			utils.ListWithTimeout(clientHubDynamic, gvrPolicy, opt, 2, true, defaultTimeoutSeconds)
   322  		})
   323  		It("should prevent user from creating subject with unsupported kind", func() {
   324  			By("Patching test-policy-pb with a plc with wrong kind")
   325  			pb := utils.GetWithTimeout(
   326  				clientHubDynamic,
   327  				gvrPlacementBinding,
   328  				case1PolicyName+"-pb",
   329  				testNamespace,
   330  				true,
   331  				defaultTimeoutSeconds,
   332  			)
   333  			pb.Object["subjects"] = []policiesv1.Subject{
   334  				{
   335  					APIGroup: "policy.open-cluster-management.io",
   336  					Kind:     "Policy1",
   337  					Name:     case1PolicyName,
   338  				},
   339  			}
   340  			_, err := clientHubDynamic.Resource(gvrPlacementBinding).Namespace(testNamespace).Update(
   341  				context.TODO(), pb, metav1.UpdateOptions{},
   342  			)
   343  			Expect(err).To(HaveOccurred())
   344  		})
   345  		It("should propagate to cluster ns managed1 and managed2", func() {
   346  			By("Patching test-policy-pb with correct plc")
   347  			pb := utils.GetWithTimeout(
   348  				clientHubDynamic,
   349  				gvrPlacementBinding,
   350  				case1PolicyName+"-pb",
   351  				testNamespace,
   352  				true,
   353  				defaultTimeoutSeconds,
   354  			)
   355  			pb.Object["subjects"] = []policiesv1.Subject{
   356  				{
   357  					APIGroup: "policy.open-cluster-management.io",
   358  					Kind:     "Policy",
   359  					Name:     case1PolicyName,
   360  				},
   361  			}
   362  			_, err := clientHubDynamic.Resource(gvrPlacementBinding).Namespace(testNamespace).Update(
   363  				context.TODO(), pb, metav1.UpdateOptions{},
   364  			)
   365  			Expect(err).ToNot(HaveOccurred())
   366  			opt := metav1.ListOptions{
   367  				LabelSelector: common.RootPolicyLabel + "=" + testNamespace + "." + case1PolicyName,
   368  			}
   369  			utils.ListWithTimeout(clientHubDynamic, gvrPolicy, opt, 2, true, defaultTimeoutSeconds)
   370  		})
   371  		It("should remove policy from ns managed1 and managed2", func() {
   372  			By("Patching test-policy-pb with a plc with wrong name")
   373  			pb := utils.GetWithTimeout(
   374  				clientHubDynamic,
   375  				gvrPlacementBinding,
   376  				case1PolicyName+"-pb",
   377  				testNamespace,
   378  				true,
   379  				defaultTimeoutSeconds,
   380  			)
   381  			pb.Object["subjects"] = []policiesv1.Subject{
   382  				{
   383  					APIGroup: "policy.open-cluster-management.io",
   384  					Kind:     "Policy",
   385  					Name:     case1PolicyName + "1",
   386  				},
   387  			}
   388  			_, err := clientHubDynamic.Resource(gvrPlacementBinding).Namespace(testNamespace).Update(
   389  				context.TODO(), pb, metav1.UpdateOptions{},
   390  			)
   391  			Expect(err).ToNot(HaveOccurred())
   392  			opt := metav1.ListOptions{
   393  				LabelSelector: common.RootPolicyLabel + "=" + testNamespace + "." + case1PolicyName,
   394  			}
   395  			utils.ListWithTimeout(clientHubDynamic, gvrPolicy, opt, 0, true, defaultTimeoutSeconds)
   396  		})
   397  		It("should propagate to cluster ns managed1 and managed2", func() {
   398  			By("Patching test-policy-pb with correct plc")
   399  			pb := utils.GetWithTimeout(
   400  				clientHubDynamic,
   401  				gvrPlacementBinding,
   402  				case1PolicyName+"-pb",
   403  				testNamespace,
   404  				true,
   405  				defaultTimeoutSeconds,
   406  			)
   407  			pb.Object["subjects"] = []policiesv1.Subject{
   408  				{
   409  					APIGroup: "policy.open-cluster-management.io",
   410  					Kind:     "Policy",
   411  					Name:     case1PolicyName,
   412  				},
   413  			}
   414  			_, err := clientHubDynamic.Resource(gvrPlacementBinding).Namespace(testNamespace).Update(
   415  				context.TODO(), pb, metav1.UpdateOptions{},
   416  			)
   417  			Expect(err).ToNot(HaveOccurred())
   418  			opt := metav1.ListOptions{
   419  				LabelSelector: common.RootPolicyLabel + "=" + testNamespace + "." + case1PolicyName,
   420  			}
   421  			utils.ListWithTimeout(clientHubDynamic, gvrPolicy, opt, 2, true, defaultTimeoutSeconds)
   422  		})
   423  		It("should remove policy from ns managed1 and managed2", func() {
   424  			By("Patching test-policy-plr with no decision")
   425  			plr := utils.GetWithTimeout(
   426  				clientHubDynamic, gvrPlacementRule, case1PolicyName+"-plr", testNamespace, true, defaultTimeoutSeconds,
   427  			)
   428  			plr.Object["status"] = &appsv1.PlacementRuleStatus{}
   429  			_, err := clientHubDynamic.Resource(gvrPlacementRule).Namespace(testNamespace).UpdateStatus(
   430  				context.TODO(), plr, metav1.UpdateOptions{},
   431  			)
   432  			Expect(err).ToNot(HaveOccurred())
   433  			opt := metav1.ListOptions{
   434  				LabelSelector: common.RootPolicyLabel + "=" + testNamespace + "." + case1PolicyName,
   435  			}
   436  			utils.ListWithTimeout(clientHubDynamic, gvrPolicy, opt, 0, true, defaultTimeoutSeconds)
   437  		})
   438  		It("should clean up", func() {
   439  			utils.Kubectl("delete",
   440  				"-f", case1PolicyYaml,
   441  				"-n", testNamespace,
   442  				"--kubeconfig="+kubeconfigHub)
   443  			opt := metav1.ListOptions{}
   444  			utils.ListWithTimeout(clientHubDynamic, gvrPolicy, opt, 0, false, 10)
   445  		})
   446  	})
   447  
   448  	Describe("Create policy/pb/plc in ns:"+testNamespace+" and then update policy", func() {
   449  		It("should be created in user ns", func() {
   450  			By("Creating " + case1PolicyYaml)
   451  			utils.Kubectl("apply",
   452  				"-f", case1PolicyYaml,
   453  				"-n", testNamespace,
   454  				"--kubeconfig="+kubeconfigHub)
   455  			plc := utils.GetWithTimeout(
   456  				clientHubDynamic, gvrPolicy, case1PolicyName, testNamespace, true, defaultTimeoutSeconds,
   457  			)
   458  			Expect(plc).NotTo(BeNil())
   459  		})
   460  		It("should propagate to cluster ns managed1", func() {
   461  			By("Patching test-policy-plr with decision of cluster managed1")
   462  			plr := utils.GetWithTimeout(
   463  				clientHubDynamic, gvrPlacementRule, case1PolicyName+"-plr", testNamespace, true, defaultTimeoutSeconds,
   464  			)
   465  			plr.Object["status"] = utils.GeneratePlrStatus("managed1")
   466  			_, err := clientHubDynamic.Resource(gvrPlacementRule).Namespace(testNamespace).UpdateStatus(
   467  				context.TODO(), plr, metav1.UpdateOptions{},
   468  			)
   469  			Expect(err).ToNot(HaveOccurred())
   470  			plc := utils.GetWithTimeout(
   471  				clientHubDynamic, gvrPolicy, testNamespace+"."+case1PolicyName, "managed1", true, defaultTimeoutSeconds,
   472  			)
   473  			Expect(plc).ToNot(BeNil())
   474  			opt := metav1.ListOptions{
   475  				LabelSelector: common.RootPolicyLabel + "=" + testNamespace + "." + case1PolicyName,
   476  			}
   477  			utils.ListWithTimeout(clientHubDynamic, gvrPolicy, opt, 1, true, defaultTimeoutSeconds)
   478  		})
   479  		It("should update replicated policy in ns managed1", func() {
   480  			By("Patching test-policy with spec.remediationAction = enforce")
   481  			rootPlc := utils.GetWithTimeout(
   482  				clientHubDynamic, gvrPolicy, case1PolicyName, testNamespace, true, defaultTimeoutSeconds,
   483  			)
   484  			Expect(rootPlc).NotTo(BeNil())
   485  			Expect(rootPlc.Object["spec"].(map[string]interface{})["remediationAction"]).To(Equal("inform"))
   486  			rootPlc.Object["spec"].(map[string]interface{})["remediationAction"] = "enforce"
   487  			rootPlc, err := clientHubDynamic.Resource(gvrPolicy).Namespace(testNamespace).Update(
   488  				context.TODO(), rootPlc, metav1.UpdateOptions{},
   489  			)
   490  			Expect(err).ToNot(HaveOccurred())
   491  			Eventually(func(g Gomega) interface{} {
   492  				replicatedPlc := utils.GetWithTimeout(
   493  					clientHubDynamic,
   494  					gvrPolicy,
   495  					testNamespace+"."+case1PolicyName,
   496  					"managed1",
   497  					true,
   498  					defaultTimeoutSeconds,
   499  				)
   500  
   501  				err := utils.RemovePolicyTemplateDBAnnotations(replicatedPlc)
   502  				g.Expect(err).ToNot(HaveOccurred())
   503  
   504  				return replicatedPlc.Object["spec"]
   505  			}, defaultTimeoutSeconds, 1).Should(utils.SemanticEqual(rootPlc.Object["spec"]))
   506  		})
   507  		It("should remove replicated policy in ns managed1", func() {
   508  			By("Patching test-policy with spec.disabled = true")
   509  			rootPlc := utils.GetWithTimeout(
   510  				clientHubDynamic, gvrPolicy, case1PolicyName, testNamespace, true, defaultTimeoutSeconds,
   511  			)
   512  			Expect(rootPlc).NotTo(BeNil())
   513  			Expect(rootPlc.Object["spec"].(map[string]interface{})["disabled"]).To(BeFalse())
   514  			rootPlc.Object["spec"].(map[string]interface{})["disabled"] = true
   515  			rootPlc, err := clientHubDynamic.Resource(gvrPolicy).Namespace(testNamespace).Update(
   516  				context.TODO(), rootPlc, metav1.UpdateOptions{},
   517  			)
   518  			Expect(err).ToNot(HaveOccurred())
   519  			Expect(rootPlc.Object["spec"].(map[string]interface{})["disabled"]).To(BeTrue())
   520  			opt := metav1.ListOptions{
   521  				LabelSelector: common.RootPolicyLabel + "=" + testNamespace + "." + case1PolicyName,
   522  			}
   523  			utils.ListWithTimeout(clientHubDynamic, gvrPolicy, opt, 0, true, defaultTimeoutSeconds)
   524  		})
   525  		It("should be created in user ns", func() {
   526  			By("Creating " + case1PolicyYaml)
   527  			utils.Kubectl("apply",
   528  				"-f", case1PolicyYaml,
   529  				"-n", testNamespace,
   530  				"--kubeconfig="+kubeconfigHub)
   531  			plc := utils.GetWithTimeout(
   532  				clientHubDynamic, gvrPolicy, case1PolicyName, testNamespace, true, defaultTimeoutSeconds,
   533  			)
   534  			Expect(plc).NotTo(BeNil())
   535  		})
   536  		It("should propagate to cluster ns managed1", func() {
   537  			By("Patching test-policy-plr with decision of cluster managed1")
   538  			plr := utils.GetWithTimeout(
   539  				clientHubDynamic, gvrPlacementRule, case1PolicyName+"-plr", testNamespace, true, defaultTimeoutSeconds,
   540  			)
   541  			plr.Object["status"] = utils.GeneratePlrStatus("managed1")
   542  			_, err := clientHubDynamic.Resource(gvrPlacementRule).Namespace(testNamespace).UpdateStatus(
   543  				context.TODO(), plr, metav1.UpdateOptions{},
   544  			)
   545  			Expect(err).ToNot(HaveOccurred())
   546  			plc := utils.GetWithTimeout(
   547  				clientHubDynamic, gvrPolicy, testNamespace+"."+case1PolicyName, "managed1", true, defaultTimeoutSeconds,
   548  			)
   549  			Expect(plc).ToNot(BeNil())
   550  			opt := metav1.ListOptions{
   551  				LabelSelector: common.RootPolicyLabel + "=" + testNamespace + "." + case1PolicyName,
   552  			}
   553  			utils.ListWithTimeout(clientHubDynamic, gvrPolicy, opt, 1, true, defaultTimeoutSeconds)
   554  		})
   555  		It("should update test-policy to a different policy template", func() {
   556  			By("Creating ../resources/case1_propagation/case1-test-policy2.yaml")
   557  			utils.Kubectl("apply",
   558  				"-f", "../resources/case1_propagation/case1-test-policy2.yaml",
   559  				"-n", testNamespace,
   560  				"--kubeconfig="+kubeconfigHub)
   561  			rootPlc := utils.GetWithTimeout(
   562  				clientHubDynamic, gvrPolicy, case1PolicyName, testNamespace, true, defaultTimeoutSeconds,
   563  			)
   564  			Expect(rootPlc).NotTo(BeNil())
   565  			yamlPlc := utils.ParseYaml("../resources/case1_propagation/case1-test-policy2.yaml")
   566  			Eventually(func(g Gomega) interface{} {
   567  				replicatedPlc := utils.GetWithTimeout(
   568  					clientHubDynamic,
   569  					gvrPolicy,
   570  					testNamespace+"."+case1PolicyName,
   571  					"managed1",
   572  					true,
   573  					defaultTimeoutSeconds,
   574  				)
   575  
   576  				err := utils.RemovePolicyTemplateDBAnnotations(replicatedPlc)
   577  				g.Expect(err).ToNot(HaveOccurred())
   578  
   579  				return replicatedPlc.Object["spec"]
   580  			}, defaultTimeoutSeconds, 1).Should(utils.SemanticEqual(yamlPlc.Object["spec"]))
   581  		})
   582  		It("should update labels on replicated policies when added to the root policy", func() {
   583  			By("Adding a label to the root policy")
   584  			rootPlc := utils.GetWithTimeout(
   585  				clientHubDynamic, gvrPolicy, case1PolicyName, testNamespace, true, defaultTimeoutSeconds,
   586  			)
   587  			labels := rootPlc.GetLabels()
   588  			if labels == nil {
   589  				labels = make(map[string]string)
   590  			}
   591  			labels["test.io/grc-prop-case1-label"] = "bellossom"
   592  			err := unstructured.SetNestedStringMap(rootPlc.Object, labels, "metadata", "labels")
   593  			Expect(err).ToNot(HaveOccurred())
   594  			_, err = clientHubDynamic.Resource(gvrPolicy).Namespace(testNamespace).Update(
   595  				context.TODO(), rootPlc, metav1.UpdateOptions{},
   596  			)
   597  			Expect(err).ToNot(HaveOccurred())
   598  
   599  			By("Checking the replicated policy for the label")
   600  			Eventually(func() map[string]string {
   601  				plc := utils.GetWithTimeout(clientHubDynamic, gvrPolicy, testNamespace+"."+case1PolicyName,
   602  					"managed1", true, defaultTimeoutSeconds)
   603  
   604  				return plc.GetLabels()
   605  			}, defaultTimeoutSeconds, 1).Should(HaveKey("test.io/grc-prop-case1-label"))
   606  		})
   607  		It("should update annotations on replicated policies when added to the root policy", func() {
   608  			By("Adding an annotation to the root policy")
   609  			rootPlc := utils.GetWithTimeout(
   610  				clientHubDynamic, gvrPolicy, case1PolicyName, testNamespace, true, defaultTimeoutSeconds,
   611  			)
   612  			annos := rootPlc.GetAnnotations()
   613  			if annos == nil {
   614  				annos = make(map[string]string)
   615  			}
   616  			annos["test.io/grc-prop-case1-annotation"] = "scizor"
   617  			err := unstructured.SetNestedStringMap(rootPlc.Object, annos, "metadata", "annotations")
   618  			Expect(err).ToNot(HaveOccurred())
   619  			_, err = clientHubDynamic.Resource(gvrPolicy).Namespace(testNamespace).Update(
   620  				context.TODO(), rootPlc, metav1.UpdateOptions{},
   621  			)
   622  			Expect(err).ToNot(HaveOccurred())
   623  
   624  			By("Checking the replicated policy for the annotation")
   625  			Eventually(func() map[string]string {
   626  				plc := utils.GetWithTimeout(clientHubDynamic, gvrPolicy, testNamespace+"."+case1PolicyName,
   627  					"managed1", true, defaultTimeoutSeconds)
   628  
   629  				return plc.GetAnnotations()
   630  			}, defaultTimeoutSeconds, 1).Should(HaveKey("test.io/grc-prop-case1-annotation"))
   631  		})
   632  		It("should clean up", func() {
   633  			utils.Kubectl("delete",
   634  				"-f", "../resources/case1_propagation/case1-test-policy2.yaml",
   635  				"-n", testNamespace, "--kubeconfig="+kubeconfigHub)
   636  			opt := metav1.ListOptions{}
   637  			utils.ListWithTimeout(clientHubDynamic, gvrPolicy, opt, 0, false, 10)
   638  		})
   639  	})
   640  
   641  	Describe("Test spec.copyPolicyMetadata", Ordered, func() {
   642  		const policyName = "case1-metadata"
   643  		policyClient := func() dynamic.ResourceInterface {
   644  			return clientHubDynamic.Resource(gvrPolicy).Namespace(testNamespace)
   645  		}
   646  
   647  		getPolicy := func() *policiesv1.Policy {
   648  			return &policiesv1.Policy{
   649  				TypeMeta: metav1.TypeMeta{
   650  					Kind:       policiesv1.Kind,
   651  					APIVersion: policiesv1.GroupVersion.String(),
   652  				},
   653  				ObjectMeta: metav1.ObjectMeta{
   654  					Name:      policyName,
   655  					Namespace: testNamespace,
   656  				},
   657  				Spec: policiesv1.PolicySpec{
   658  					Disabled:        false,
   659  					PolicyTemplates: []*policiesv1.PolicyTemplate{},
   660  				},
   661  			}
   662  		}
   663  
   664  		BeforeAll(func() {
   665  			By("Creating a PlacementRule")
   666  			plr := &unstructured.Unstructured{
   667  				Object: map[string]interface{}{
   668  					"apiVersion": "apps.open-cluster-management.io/v1",
   669  					"kind":       "PlacementRule",
   670  					"metadata": map[string]interface{}{
   671  						"name":      policyName,
   672  						"namespace": testNamespace,
   673  					},
   674  					"spec": map[string]interface{}{},
   675  				},
   676  			}
   677  			var err error
   678  			plr, err = clientHubDynamic.Resource(gvrPlacementRule).Namespace(testNamespace).Create(
   679  				context.TODO(), plr, metav1.CreateOptions{},
   680  			)
   681  			Expect(err).ToNot(HaveOccurred())
   682  
   683  			plr.Object["status"] = utils.GeneratePlrStatus("managed1")
   684  			_, err = clientHubDynamic.Resource(gvrPlacementRule).Namespace(testNamespace).UpdateStatus(
   685  				context.TODO(), plr, metav1.UpdateOptions{},
   686  			)
   687  			Expect(err).ToNot(HaveOccurred())
   688  
   689  			By("Creating a PlacementBinding")
   690  			plb := &unstructured.Unstructured{
   691  				Object: map[string]interface{}{
   692  					"apiVersion": policiesv1.GroupVersion.String(),
   693  					"kind":       "PlacementBinding",
   694  					"metadata": map[string]interface{}{
   695  						"name":      policyName,
   696  						"namespace": testNamespace,
   697  					},
   698  					"placementRef": map[string]interface{}{
   699  						"apiGroup": gvrPlacementRule.Group,
   700  						"kind":     "PlacementRule",
   701  						"name":     policyName,
   702  					},
   703  					"subjects": []interface{}{
   704  						map[string]interface{}{
   705  							"apiGroup": policiesv1.GroupVersion.Group,
   706  							"kind":     policiesv1.Kind,
   707  							"name":     policyName,
   708  						},
   709  					},
   710  				},
   711  			}
   712  
   713  			_, err = clientHubDynamic.Resource(gvrPlacementBinding).Namespace(testNamespace).Create(
   714  				context.TODO(), plb, metav1.CreateOptions{},
   715  			)
   716  			Expect(err).ToNot(HaveOccurred())
   717  		})
   718  
   719  		AfterEach(func() {
   720  			By("Removing the policy")
   721  			err := policyClient().Delete(context.TODO(), policyName, metav1.DeleteOptions{})
   722  			if !errors.IsNotFound(err) {
   723  				Expect(err).ToNot(HaveOccurred())
   724  			}
   725  
   726  			replicatedPolicy := utils.GetWithTimeout(
   727  				clientHubDynamic,
   728  				gvrPolicy,
   729  				testNamespace+"."+policyName,
   730  				"managed1",
   731  				false,
   732  				defaultTimeoutSeconds,
   733  			)
   734  			Expect(replicatedPolicy).To(BeNil())
   735  		})
   736  
   737  		AfterAll(func() {
   738  			By("Removing the PlacementRule")
   739  			err := clientHubDynamic.Resource(gvrPlacementRule).Namespace(testNamespace).Delete(
   740  				context.TODO(), policyName, metav1.DeleteOptions{},
   741  			)
   742  			if !errors.IsNotFound(err) {
   743  				Expect(err).ToNot(HaveOccurred())
   744  			}
   745  
   746  			By("Removing the PlacementBinding")
   747  			err = clientHubDynamic.Resource(gvrPlacementBinding).Namespace(testNamespace).Delete(
   748  				context.TODO(), policyName, metav1.DeleteOptions{},
   749  			)
   750  			if !errors.IsNotFound(err) {
   751  				Expect(err).ToNot(HaveOccurred())
   752  			}
   753  		})
   754  
   755  		It("Verifies that spec.copyPolicyMetadata defaults to unset", func() {
   756  			By("Creating an empty policy")
   757  			policy := getPolicy()
   758  			policyMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(policy)
   759  			Expect(err).ToNot(HaveOccurred())
   760  
   761  			_, err = policyClient().Create(
   762  				context.TODO(), &unstructured.Unstructured{Object: policyMap}, metav1.CreateOptions{},
   763  			)
   764  			Expect(err).ToNot(HaveOccurred())
   765  
   766  			Eventually(func(g Gomega) {
   767  				replicatedPlc := utils.GetWithTimeout(
   768  					clientHubDynamic,
   769  					gvrPolicy,
   770  					testNamespace+"."+policyName,
   771  					"managed1",
   772  					true,
   773  					defaultTimeoutSeconds,
   774  				)
   775  
   776  				_, found, _ := unstructured.NestedBool(replicatedPlc.Object, "spec", "copyPolicyMetadata")
   777  				g.Expect(found).To(BeFalse())
   778  			}, defaultTimeoutSeconds, 1).Should(Succeed())
   779  		})
   780  
   781  		It("verifies that the labels and annotations are copied with spec.copyPolicyMetadata=true", func() {
   782  			By("Creating a policy with labels and annotations")
   783  			policy := getPolicy()
   784  			copyPolicyMetadata := true
   785  			policy.Spec.CopyPolicyMetadata = &copyPolicyMetadata
   786  			policy.SetAnnotations(map[string]string{"do": "copy", "please": "do-copy"})
   787  			policy.SetLabels(map[string]string{"do": "copy", "please": "do-copy"})
   788  
   789  			policyMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(policy)
   790  			Expect(err).ToNot(HaveOccurred())
   791  
   792  			_, err = policyClient().Create(
   793  				context.TODO(), &unstructured.Unstructured{Object: policyMap}, metav1.CreateOptions{},
   794  			)
   795  			Expect(err).ToNot(HaveOccurred())
   796  
   797  			Eventually(func(g Gomega) {
   798  				replicatedPlc := utils.GetWithTimeout(
   799  					clientHubDynamic,
   800  					gvrPolicy,
   801  					testNamespace+"."+policyName,
   802  					"managed1",
   803  					true,
   804  					defaultTimeoutSeconds,
   805  				)
   806  
   807  				annotations := replicatedPlc.GetAnnotations()
   808  				g.Expect(annotations["do"]).To(Equal("copy"))
   809  				g.Expect(annotations["please"]).To(Equal("do-copy"))
   810  				// This annotation is always set.
   811  				g.Expect(annotations["argocd.argoproj.io/compare-options"]).To(Equal("IgnoreExtraneous"))
   812  
   813  				labels := replicatedPlc.GetLabels()
   814  				g.Expect(labels["do"]).To(Equal("copy"))
   815  				g.Expect(labels["please"]).To(Equal("do-copy"))
   816  			}, defaultTimeoutSeconds, 1).Should(Succeed())
   817  		})
   818  
   819  		It("verifies that the labels and annotations are not copied with spec.copyPolicyMetadata=false", func() {
   820  			By("Creating a policy with labels and annotations")
   821  			policy := getPolicy()
   822  			copyPolicyMetadata := false
   823  			policy.Spec.CopyPolicyMetadata = &copyPolicyMetadata
   824  			policy.SetAnnotations(map[string]string{"do-not": "copy", "please": "do-not-copy"})
   825  			policy.SetLabels(map[string]string{"do-not": "copy", "please": "do-not-copy"})
   826  
   827  			policyMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(policy)
   828  			Expect(err).ToNot(HaveOccurred())
   829  
   830  			_, err = policyClient().Create(
   831  				context.TODO(), &unstructured.Unstructured{Object: policyMap}, metav1.CreateOptions{},
   832  			)
   833  			Expect(err).ToNot(HaveOccurred())
   834  
   835  			Eventually(func(g Gomega) {
   836  				replicatedPlc := utils.GetWithTimeout(
   837  					clientHubDynamic,
   838  					gvrPolicy,
   839  					testNamespace+"."+policyName,
   840  					"managed1",
   841  					true,
   842  					defaultTimeoutSeconds,
   843  				)
   844  
   845  				annotations := replicatedPlc.GetAnnotations()
   846  				g.Expect(annotations["do-not"]).To(Equal(""))
   847  				g.Expect(annotations["please"]).To(Equal(""))
   848  				// This annotation is always set.
   849  				g.Expect(annotations["argocd.argoproj.io/compare-options"]).To(Equal("IgnoreExtraneous"))
   850  
   851  				labels := replicatedPlc.GetLabels()
   852  				g.Expect(labels["do-not"]).To(Equal(""))
   853  				g.Expect(labels["please"]).To(Equal(""))
   854  			}, defaultTimeoutSeconds, 1).Should(Succeed())
   855  		})
   856  	})
   857  })