diff --git a/pkg/work/spoke/apply/server_side_apply.go b/pkg/work/spoke/apply/server_side_apply.go index 6e67fef60..40b2ea742 100644 --- a/pkg/work/spoke/apply/server_side_apply.go +++ b/pkg/work/spoke/apply/server_side_apply.go @@ -95,12 +95,8 @@ func (c *ServerSideApply) Apply( ctx, required.GetName(), metav1.GetOptions{}) switch { case errors.IsNotFound(err): - // if object is not found, directly apply without removing ignore fields in the object. - obj, createErr := c.client. - Resource(gvr). - Namespace(required.GetNamespace()). - Apply(ctx, required.GetName(), requiredOriginal, metav1.ApplyOptions{FieldManager: fieldManager, Force: force}) - return obj, createErr + // if object is not found, use requiredOriginal to apply so the ignore fields are kept when create + required = requiredOriginal case err != nil: return nil, err case len(existing.GetAnnotations()) > 0: diff --git a/test/e2e/work_workload_test.go b/test/e2e/work_workload_test.go index e3f0c0f2f..82688f454 100644 --- a/test/e2e/work_workload_test.go +++ b/test/e2e/work_workload_test.go @@ -787,7 +787,7 @@ var _ = ginkgo.Describe("Work agent", ginkgo.Label("work-agent", "sanity-check") IgnoreFields: []workapiv1.IgnoreField{ { Condition: workapiv1.IgnoreFieldsConditionOnSpokeChange, - JSONPaths: []string{"spec.replicas"}, + JSONPaths: []string{".spec.replicas"}, }, }, }, @@ -806,6 +806,9 @@ var _ = ginkgo.Describe("Work agent", ginkgo.Label("work-agent", "sanity-check") if *deploy.Spec.Replicas != int32(2) { return fmt.Errorf("expected 2 replicas, got %d", *deploy.Spec.Replicas) } + if len(deploy.OwnerReferences) == 0 { + return fmt.Errorf("expected owner references, got none") + } return nil }).ShouldNot(gomega.HaveOccurred()) @@ -850,6 +853,22 @@ var _ = ginkgo.Describe("Work agent", ginkgo.Label("work-agent", "sanity-check") return err }).ShouldNot(gomega.HaveOccurred()) + // wait until the work has been applied + gomega.Eventually(func() error { + actualWork, err := hub.WorkClient.WorkV1().ManifestWorks(universalClusterName).Get(context.Background(), workName, metav1.GetOptions{}) + if err != nil { + return err + } + appliedCond := meta.FindStatusCondition(actualWork.Status.Conditions, workapiv1.WorkApplied) + if appliedCond == nil { + return fmt.Errorf("expected a work applied condition") + } + if appliedCond.ObservedGeneration != actualWork.Generation { + return fmt.Errorf("expect work is applied.") + } + return nil + }).ShouldNot(gomega.HaveOccurred()) + // Check deployment status, it should not be changed gomega.Eventually(func() error { deploy, err := spoke.KubeClient.AppsV1().Deployments(deployment.Namespace).Get(context.Background(), deployment.Name, metav1.GetOptions{}) @@ -861,6 +880,23 @@ var _ = ginkgo.Describe("Work agent", ginkgo.Label("work-agent", "sanity-check") } return nil }).ShouldNot(gomega.HaveOccurred()) + + err = hub.WorkClient.WorkV1().ManifestWorks(universalClusterName).Delete( + context.Background(), work.Name, metav1.DeleteOptions{}) + gomega.Expect(err).ToNot(gomega.HaveOccurred()) + + // Check deployment is removed + gomega.Eventually(func() error { + _, err := spoke.KubeClient.AppsV1().Deployments(deployment.Namespace).Get( + context.Background(), deployment.Name, metav1.GetOptions{}) + if errors.IsNotFound(err) { + return nil + } + if err != nil { + return err + } + return fmt.Errorf("resource still exists") + }).ShouldNot(gomega.HaveOccurred()) }) }) })