From e15d0d253ced188e3175a4f59ff5ac67eb6b22f7 Mon Sep 17 00:00:00 2001 From: Ryan Zhang Date: Wed, 7 Sep 2022 23:28:52 -0700 Subject: [PATCH 1/3] feat: force delete work in the cluster namespace --- .../membercluster/membercluster_controller.go | 62 ++++++++++++++++++- pkg/utils/common.go | 4 +- test/integration/cluster_placement_test.go | 58 ++++++++++++++++- test/integration/utils_test.go | 2 + 4 files changed, 119 insertions(+), 7 deletions(-) diff --git a/pkg/controllers/membercluster/membercluster_controller.go b/pkg/controllers/membercluster/membercluster_controller.go index db6af0fb4..6c8a7c424 100644 --- a/pkg/controllers/membercluster/membercluster_controller.go +++ b/pkg/controllers/membercluster/membercluster_controller.go @@ -25,7 +25,9 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/predicate" + workv1alpha1 "sigs.k8s.io/work-api/pkg/apis/v1alpha1" "go.goms.io/fleet/apis" fleetv1alpha1 "go.goms.io/fleet/apis/v1alpha1" @@ -65,6 +67,18 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu klog.ErrorS(err, "failed to get member cluster", "memberCluster", req.Name) return ctrl.Result{}, client.IgnoreNotFound(err) } + mcObjRef := klog.KObj(&mc) + + // Handle deleting member cluster, garbage collect all the resources in the cluster namespace + if !mc.DeletionTimestamp.IsZero() { + klog.V(2).InfoS("the member cluster is in the process of being deleted", "memberCluster", mcObjRef) + return r.garbageCollectWork(ctx, &mc) + } + // Add the finalizer to the member cluster + if err := r.ensureFinalizer(ctx, &mc); err != nil { + klog.ErrorS(err, "failed to add the finalizer to member cluster", "memberCluster", mcObjRef) + return ctrl.Result{}, err + } // Get current internal member cluster. namespaceName := fmt.Sprintf(utils.NamespaceNameFormat, mc.Name) @@ -83,13 +97,13 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu switch mc.Spec.State { case fleetv1alpha1.ClusterStateJoin: if err := r.join(ctx, &mc, currentImc); err != nil { - klog.ErrorS(err, "failed to join", "memberCluster", klog.KObj(&mc)) + klog.ErrorS(err, "failed to join", "memberCluster", mcObjRef) return ctrl.Result{}, err } case fleetv1alpha1.ClusterStateLeave: if err := r.leave(ctx, &mc, currentImc); err != nil { - klog.ErrorS(err, "failed to leave", "memberCluster", klog.KObj(&mc)) + klog.ErrorS(err, "failed to leave", "memberCluster", mcObjRef) return ctrl.Result{}, err } @@ -108,6 +122,50 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu return ctrl.Result{}, nil } +// garbageCollectWork remove all the finalizers on the work that are in the cluster namespace +func (r *Reconciler) garbageCollectWork(ctx context.Context, mc *fleetv1alpha1.MemberCluster) (ctrl.Result, error) { + var works workv1alpha1.WorkList + var clusterNS corev1.Namespace + // check if the namespace still exist + namespaceName := fmt.Sprintf(utils.NamespaceNameFormat, mc.Name) + if err := r.Client.Get(ctx, types.NamespacedName{Name: namespaceName}, &clusterNS); apierrors.IsNotFound(err) { + klog.V(2).InfoS("the member cluster namespace is successfully deleted", "memberCluster", klog.KObj(mc)) + return ctrl.Result{}, nil + } + // list all the work object we created in the member cluster namespace + listOpts := []client.ListOption{ + client.MatchingLabels{utils.LabelFleetObj: utils.LabelFleetObjValue}, + client.InNamespace(namespaceName), + } + if err := r.Client.List(ctx, &works, listOpts...); err != nil { + klog.ErrorS(err, "failed to list all the work object", "memberCluster", klog.KObj(mc)) + return ctrl.Result{}, client.IgnoreNotFound(err) + } + for _, work := range works.Items { + staleWork := work.DeepCopy() + staleWork.SetFinalizers(nil) + if updateErr := r.Update(ctx, staleWork, &client.UpdateOptions{}); updateErr != nil { + klog.ErrorS(updateErr, "failed to remove the finalizer from the work", + "memberCluster", klog.KObj(mc), "work", klog.KObj(staleWork)) + return ctrl.Result{}, updateErr + } + } + klog.V(2).InfoS("successfully removed all the work finalizers in the cluster namespace", + "memberCluster", klog.KObj(mc), "number of work", len(works.Items)) + controllerutil.RemoveFinalizer(mc, utils.MemberClusterFinalizer) + return ctrl.Result{}, r.Update(ctx, mc, &client.UpdateOptions{}) +} + +// ensureFinalizer makes sure that the member cluster CR has a finalizer on it +func (r *Reconciler) ensureFinalizer(ctx context.Context, mc *fleetv1alpha1.MemberCluster) error { + if controllerutil.ContainsFinalizer(mc, utils.MemberClusterFinalizer) { + return nil + } + klog.InfoS("add the member cluster finalizer", "memberCluster", klog.KObj(mc)) + controllerutil.AddFinalizer(mc, utils.MemberClusterFinalizer) + return r.Update(ctx, mc, client.FieldOwner(utils.MCControllerFieldManagerName)) +} + // join takes the actions to make hub cluster ready for member cluster to join, including: // - Create namespace for member cluster // - Create role & role bindings for member cluster to access hub cluster diff --git a/pkg/utils/common.go b/pkg/utils/common.go index 4a57e15c3..6129d13ae 100644 --- a/pkg/utils/common.go +++ b/pkg/utils/common.go @@ -57,8 +57,8 @@ const ( // This label aims to enable different work objects to be managed by different placement. LabelWorkPlacementName = "work.fleet.azure.com/placement-name" - // PlacementFinalizer is used to make sure that we handle gc of placement resources. - PlacementFinalizer = "work.fleet.azure.com/placement-protection" + // MemberClusterFinalizer is used to make sure that we handle gc of all the member cluster resources on the hub cluster + MemberClusterFinalizer = "work.fleet.azure.com/membercluster-finalizer" ) var ( diff --git a/test/integration/cluster_placement_test.go b/test/integration/cluster_placement_test.go index 76e41b93b..2edb21e34 100644 --- a/test/integration/cluster_placement_test.go +++ b/test/integration/cluster_placement_test.go @@ -17,6 +17,7 @@ import ( discoveryv1 "k8s.io/api/discovery/v1" rbacv1 "k8s.io/api/rbac/v1" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/types" @@ -93,9 +94,9 @@ var _ = Describe("Test Cluster Resource Placement Controller", func() { AfterEach(func() { By("Delete member clusters", func() { - Expect(k8sClient.Delete(ctx, &clusterA)).Should(Succeed()) - Expect(k8sClient.Delete(ctx, &clusterB)).Should(Succeed()) - Expect(k8sClient.Delete(ctx, crp)).Should(Succeed()) + Expect(k8sClient.Delete(ctx, &clusterA)).Should(SatisfyAny(Succeed(), utils.NotFoundMatcher{})) + Expect(k8sClient.Delete(ctx, &clusterB)).Should(SatisfyAny(Succeed(), utils.NotFoundMatcher{})) + Expect(k8sClient.Delete(ctx, crp)).Should(SatisfyAny(Succeed(), utils.NotFoundMatcher{})) }) }) @@ -1225,6 +1226,57 @@ var _ = Describe("Test Cluster Resource Placement Controller", func() { markInternalMCJoined(clusterB) }) + FIt("Test force delete member cluster after work agent lost connection/deleted", func() { + By("create clusterResourcePlacement CR") + crp = &fleetv1alpha1.ClusterResourcePlacement{ + ObjectMeta: metav1.ObjectMeta{ + Name: "resource-test-change", + }, + Spec: fleetv1alpha1.ClusterResourcePlacementSpec{ + ResourceSelectors: []fleetv1alpha1.ClusterResourceSelector{ + { + Group: rbacv1.GroupName, + Version: "v1", + Kind: ClusterRoleKind, + LabelSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "fleet.azure.com/name": "test", + }, + }, + }, + }, + }, + } + Expect(k8sClient.Create(ctx, crp)).Should(Succeed()) + + By("verify that we have created work objects that contain the resource selected") + verifyWorkObjects(crp, []string{ClusterRoleKind}, []*fleetv1alpha1.MemberCluster{&clusterA, &clusterB}) + + By("add finalizer to the work and mark it as applied") + markWorkAppliedStatusSuccess(crp, &clusterA) + + By("delete the member cluster") + Expect(k8sClient.Delete(ctx, &clusterA)).Should(Succeed()) + + // the namespace won't be deleted as the GC controller does not run there + By("verify that the work is deleted") + nsName := fmt.Sprintf(utils.NamespaceNameFormat, clusterA.Name) + Eventually(func() bool { + var clusterWork workv1alpha1.Work + return apierrors.IsNotFound(k8sClient.Get(ctx, types.NamespacedName{ + Name: crp.Name, + Namespace: nsName, + }, &clusterWork)) + }, timeout, interval).Should(BeTrue()) + + By("verify that the member cluster is deleted") + Eventually(func() bool { + return apierrors.IsNotFound(k8sClient.Get(ctx, types.NamespacedName{ + Name: clusterA.Name, + }, &clusterA)) + }, timeout, interval).Should(BeTrue()) + }) + XIt("Test partial failed apply", func() { }) diff --git a/test/integration/utils_test.go b/test/integration/utils_test.go index ad8054dd4..38ec0aa92 100644 --- a/test/integration/utils_test.go +++ b/test/integration/utils_test.go @@ -27,6 +27,7 @@ import ( "k8s.io/apimachinery/pkg/util/yaml" "k8s.io/client-go/rest" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/envtest" workv1alpha1 "sigs.k8s.io/work-api/pkg/apis/v1alpha1" @@ -358,6 +359,7 @@ func markWorkAppliedStatusSuccess(crp *fleetv1alpha1.ClusterResourcePlacement, c ObservedGeneration: crp.Generation, }, } + controllerutil.AddFinalizer(&clusterWork, "fleet.azure.com/work-cleanup") Expect(k8sClient.Status().Update(ctx, &clusterWork)).Should(Succeed()) } From 14e2dceeda79352aad2c37bd9909ca6b0d8fb08f Mon Sep 17 00:00:00 2001 From: Ryan Zhang Date: Thu, 8 Sep 2022 11:38:24 -0700 Subject: [PATCH 2/3] fix test --- .../membercluster/membercluster_controller.go | 28 ++++---- pkg/utils/test_util.go | 23 +++++++ test/e2e/utils/helper.go | 24 ------- test/e2e/work_api_test.go | 3 +- test/integration/cluster_placement_test.go | 68 +++++++++++++++---- 5 files changed, 92 insertions(+), 54 deletions(-) diff --git a/pkg/controllers/membercluster/membercluster_controller.go b/pkg/controllers/membercluster/membercluster_controller.go index 6c8a7c424..f0aa5cce8 100644 --- a/pkg/controllers/membercluster/membercluster_controller.go +++ b/pkg/controllers/membercluster/membercluster_controller.go @@ -62,20 +62,22 @@ type Reconciler struct { func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { klog.V(3).InfoS("Reconcile", "memberCluster", req.NamespacedName) - var mc fleetv1alpha1.MemberCluster - if err := r.Client.Get(ctx, req.NamespacedName, &mc); err != nil { + var oldMC fleetv1alpha1.MemberCluster + if err := r.Client.Get(ctx, req.NamespacedName, &oldMC); err != nil { klog.ErrorS(err, "failed to get member cluster", "memberCluster", req.Name) return ctrl.Result{}, client.IgnoreNotFound(err) } - mcObjRef := klog.KObj(&mc) // Handle deleting member cluster, garbage collect all the resources in the cluster namespace - if !mc.DeletionTimestamp.IsZero() { - klog.V(2).InfoS("the member cluster is in the process of being deleted", "memberCluster", mcObjRef) - return r.garbageCollectWork(ctx, &mc) + if !oldMC.DeletionTimestamp.IsZero() { + klog.V(2).InfoS("the member cluster is in the process of being deleted", "memberCluster", klog.KObj(&oldMC)) + return r.garbageCollectWork(ctx, &oldMC) } + + mc := oldMC.DeepCopy() + mcObjRef := klog.KObj(mc) // Add the finalizer to the member cluster - if err := r.ensureFinalizer(ctx, &mc); err != nil { + if err := r.ensureFinalizer(ctx, mc); err != nil { klog.ErrorS(err, "failed to add the finalizer to member cluster", "memberCluster", mcObjRef) return ctrl.Result{}, err } @@ -96,26 +98,26 @@ func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Resu switch mc.Spec.State { case fleetv1alpha1.ClusterStateJoin: - if err := r.join(ctx, &mc, currentImc); err != nil { + if err := r.join(ctx, mc, currentImc); err != nil { klog.ErrorS(err, "failed to join", "memberCluster", mcObjRef) return ctrl.Result{}, err } case fleetv1alpha1.ClusterStateLeave: - if err := r.leave(ctx, &mc, currentImc); err != nil { + if err := r.leave(ctx, mc, currentImc); err != nil { klog.ErrorS(err, "failed to leave", "memberCluster", mcObjRef) return ctrl.Result{}, err } default: - klog.Errorf("encountered a fatal error. unknown state %v in MemberCluster: %s", mc.Spec.State, klog.KObj(&mc)) + klog.Errorf("encountered a fatal error. unknown state %v in MemberCluster: %s", mc.Spec.State, mcObjRef) return ctrl.Result{}, nil } // Copy status from InternalMemberCluster to MemberCluster. - r.syncInternalMemberClusterStatus(currentImc, &mc) - if err := r.updateMemberClusterStatus(ctx, &mc); err != nil { - klog.ErrorS(err, "failed to update status for", klog.KObj(&mc)) + r.syncInternalMemberClusterStatus(currentImc, mc) + if err := r.updateMemberClusterStatus(ctx, mc); err != nil { + klog.ErrorS(err, "failed to update status for", klog.KObj(mc)) return ctrl.Result{}, client.IgnoreNotFound(err) } diff --git a/pkg/utils/test_util.go b/pkg/utils/test_util.go index 7ce38e454..f644ed292 100644 --- a/pkg/utils/test_util.go +++ b/pkg/utils/test_util.go @@ -85,3 +85,26 @@ func (matcher NotFoundMatcher) FailureMessage(actual interface{}) (message strin func (matcher NotFoundMatcher) NegatedFailureMessage(actual interface{}) (message string) { return format.Message(actual, "to be found") } + +// AlreadyExistMatcher matches the error to be already exist +type AlreadyExistMatcher struct { +} + +// Match matches error. +func (matcher AlreadyExistMatcher) Match(actual interface{}) (success bool, err error) { + if actual == nil { + return false, nil + } + actualError := actual.(error) + return apierrors.IsAlreadyExists(actualError), nil +} + +// FailureMessage builds an error message. +func (matcher AlreadyExistMatcher) FailureMessage(actual interface{}) (message string) { + return format.Message(actual, "to be already exist") +} + +// NegatedFailureMessage builds an error message. +func (matcher AlreadyExistMatcher) NegatedFailureMessage(actual interface{}) (message string) { + return format.Message(actual, "not to be already exist") +} diff --git a/test/e2e/utils/helper.go b/test/e2e/utils/helper.go index 4d9c2b997..2b58a9a96 100644 --- a/test/e2e/utils/helper.go +++ b/test/e2e/utils/helper.go @@ -11,7 +11,6 @@ import ( "github.com/onsi/ginkgo/v2" "github.com/onsi/gomega" - "github.com/onsi/gomega/format" corev1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -247,26 +246,3 @@ func DeleteServiceAccount(cluster framework.Cluster, sa *corev1.ServiceAccount) gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) }) } - -// AlreadyExistMatcher matches the error to be already exist -type AlreadyExistMatcher struct { -} - -// Match matches error. -func (matcher AlreadyExistMatcher) Match(actual interface{}) (success bool, err error) { - if actual == nil { - return false, nil - } - actualError := actual.(error) - return apierrors.IsAlreadyExists(actualError), nil -} - -// FailureMessage builds an error message. -func (matcher AlreadyExistMatcher) FailureMessage(actual interface{}) (message string) { - return format.Message(actual, "to be already exist") -} - -// NegatedFailureMessage builds an error message. -func (matcher AlreadyExistMatcher) NegatedFailureMessage(actual interface{}) (message string) { - return format.Message(actual, "not to be already exist") -} diff --git a/test/e2e/work_api_test.go b/test/e2e/work_api_test.go index 996bfcc13..2641ccff6 100644 --- a/test/e2e/work_api_test.go +++ b/test/e2e/work_api_test.go @@ -25,7 +25,6 @@ import ( fleetv1alpha1 "go.goms.io/fleet/apis/v1alpha1" fleetutil "go.goms.io/fleet/pkg/utils" - "go.goms.io/fleet/test/e2e/utils" ) const ( @@ -45,7 +44,7 @@ var _ = Describe("work-api testing", Ordered, func() { BeforeAll(func() { _, err := HubCluster.KubeClientSet.CoreV1().Namespaces().Create(context.Background(), wns, metav1.CreateOptions{}) - Expect(err).Should(SatisfyAny(Succeed(), &utils.AlreadyExistMatcher{})) + Expect(err).Should(SatisfyAny(Succeed(), &fleetutil.AlreadyExistMatcher{})) }) Context("with a Work resource that has two manifests: Deployment & Service", func() { diff --git a/test/integration/cluster_placement_test.go b/test/integration/cluster_placement_test.go index 2edb21e34..abf3a6ef6 100644 --- a/test/integration/cluster_placement_test.go +++ b/test/integration/cluster_placement_test.go @@ -12,6 +12,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + adminv1 "k8s.io/api/admissionregistration/v1" coordv1 "k8s.io/api/coordination/v1" corev1 "k8s.io/api/core/v1" discoveryv1 "k8s.io/api/discovery/v1" @@ -1174,6 +1175,40 @@ var _ = Describe("Test Cluster Resource Placement Controller", func() { }) It("Test a placement select some resources and then not any", func() { + By("Create a webhook resource") + webhookName := "test-mutating-webhook" + sideEffect := adminv1.SideEffectClassNone + mutatingWebhook := adminv1.MutatingWebhookConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: webhookName, + Namespace: testService.GetNamespace(), + }, + Webhooks: []adminv1.MutatingWebhook{ + { + Name: "test.azure.com", + Rules: []adminv1.RuleWithOperations{ + { + Operations: []adminv1.OperationType{ + adminv1.OperationAll, + }, + Rule: adminv1.Rule{ + APIGroups: []string{"*"}, + APIVersions: []string{"*"}, + Resources: []string{"pod"}, + }, + }, + }, + ClientConfig: adminv1.WebhookClientConfig{ + URL: pointer.String("https://test.azure.com/test-crp"), + }, + AdmissionReviewVersions: []string{"v1"}, + SideEffects: &sideEffect, + }, + }, + } + Expect(k8sClient.Create(ctx, &mutatingWebhook)).Should(Succeed()) + + By("Select webhook clusterResourcePlacement created") crp = &fleetv1alpha1.ClusterResourcePlacement{ ObjectMeta: metav1.ObjectMeta{ Name: "resource-test-change", @@ -1181,26 +1216,30 @@ var _ = Describe("Test Cluster Resource Placement Controller", func() { Spec: fleetv1alpha1.ClusterResourcePlacementSpec{ ResourceSelectors: []fleetv1alpha1.ClusterResourceSelector{ { - Group: rbacv1.GroupName, + Group: adminv1.GroupName, Version: "v1", - Kind: ClusterRoleKind, - LabelSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "fleet.azure.com/name": "test", - }, - }, + Kind: "MutatingWebhookConfiguration", + Name: webhookName, }, }, }, } Expect(k8sClient.Create(ctx, crp)).Should(Succeed()) - By("Select resource by label clusterResourcePlacement created") - // verify that we have created work objects that contain the resource selected - verifyWorkObjects(crp, []string{ClusterRoleKind}, []*fleetv1alpha1.MemberCluster{&clusterA}) + By("verify that we have created work objects that contain the resource selected") + var clusterWork workv1alpha1.Work + waitForPlacementScheduleStopped(crp.Name) + Expect(k8sClient.Get(ctx, types.NamespacedName{ + Name: crp.Name, + Namespace: fmt.Sprintf(utils.NamespaceNameFormat, clusterA.Name), + }, &clusterWork)).Should(Succeed()) + Expect(len(clusterWork.Spec.Workload.Manifests)).Should(Equal(1)) + var uObj unstructured.Unstructured + GetObjectFromRawExtension(clusterWork.Spec.Workload.Manifests[0].Raw, &uObj) + Expect(uObj.GroupVersionKind().Kind).Should(Equal("MutatingWebhookConfiguration")) - By("Delete the clusterRole resources") - Expect(k8sClient.Delete(ctx, &testClusterRole)).Should(Succeed()) + By("Delete the webhook resources") + Expect(k8sClient.Delete(ctx, &mutatingWebhook)).Should(Succeed()) By("Verify that do not schedule anything") waitForPlacementScheduleStopped(crp.Name) @@ -1208,12 +1247,11 @@ var _ = Describe("Test Cluster Resource Placement Controller", func() { verifyPlacementScheduleStatus(crp, 0, 0, metav1.ConditionFalse) By("Verified that placement has nothing scheduled") - var clusterWork workv1alpha1.Work Expect(k8sClient.Get(ctx, types.NamespacedName{ Name: crp.Name, Namespace: fmt.Sprintf(utils.NamespaceNameFormat, clusterA.Name), }, &clusterWork)).Should(utils.NotFoundMatcher{}) - By("Verified that the deleted clusterRole is removed from the work") + By("Verified that the deleted webhook is removed from the work") }) }) @@ -1226,7 +1264,7 @@ var _ = Describe("Test Cluster Resource Placement Controller", func() { markInternalMCJoined(clusterB) }) - FIt("Test force delete member cluster after work agent lost connection/deleted", func() { + It("Test force delete member cluster after work agent lost connection/deleted", func() { By("create clusterResourcePlacement CR") crp = &fleetv1alpha1.ClusterResourcePlacement{ ObjectMeta: metav1.ObjectMeta{ From 7e763fd3062ae72906e9edc7923f5adcb8c7a77d Mon Sep 17 00:00:00 2001 From: Ryan Zhang Date: Thu, 8 Sep 2022 12:30:35 -0700 Subject: [PATCH 3/3] change some logs --- pkg/resourcewatcher/event_handlers.go | 7 ++++--- test/e2e/README.md | 17 ++++++++++++++--- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/pkg/resourcewatcher/event_handlers.go b/pkg/resourcewatcher/event_handlers.go index af744a574..da8b82238 100644 --- a/pkg/resourcewatcher/event_handlers.go +++ b/pkg/resourcewatcher/event_handlers.go @@ -168,12 +168,13 @@ func (d *ChangeDetector) onResourceUpdated(oldObj, newObj interface{}) { return } if oldObjMeta.GetResourceVersion() != newObjMeta.GetResourceVersion() { - klog.V(5).InfoS("A resource is updated", "obj", klog.KObj(oldObjMeta), - "gvk", runtimeObject.GetObjectKind().GroupVersionKind().String()) + klog.V(5).InfoS("A resource is updated", "obj", oldObjMeta.GetName(), + "namespace", oldObjMeta.GetNamespace(), "gvk", runtimeObject.GetObjectKind().GroupVersionKind().String()) d.ResourceChangeController.Enqueue(newObj) return } - klog.V(5).InfoS("Received a resource updated event with no change", "obj", klog.KObj(oldObjMeta)) + klog.V(5).InfoS("Received a resource updated event with no change", "obj", oldObjMeta.GetName(), + "namespace", oldObjMeta.GetNamespace(), "gvk", runtimeObject.GetObjectKind().GroupVersionKind().String()) } // onResourceDeleted handles object delete event and push the deleted object to the resource queue. diff --git a/test/e2e/README.md b/test/e2e/README.md index 901e71aed..145b428e6 100644 --- a/test/e2e/README.md +++ b/test/e2e/README.md @@ -18,21 +18,32 @@ make install-helm ``` 3. Run the test + +run the e2e test suite ```shell make run-e2e ``` +or test manually +```shell +kubectl --context=kind-hub-testing apply -f examples/fleet_v1alpha1_membercluster.yaml +kubectl --context=kind-hub-testing apply -f test/integration/manifests/resources +kubectl --context=kind-hub-testing apply -f test/integration/manifests/resources +kubectl --context=kind-hub-testing apply -f test/integration/manifests/placement/select-namespace.yaml +``` + +4. Check the controller logs -4. Check the logs of the hub cluster controller +check the logs of the hub cluster controller ```shell kubectl --context=kind-hub-testing -n fleet-system get pod ``` -4. Check the logs of the member cluster controller +check the logs of the member cluster controller ```shell kubectl --context=kind-member-testing -n fleet-system get pod ``` -5. uninstall the resources +5.uninstall the resources ```shell make uninstall-helm ``` \ No newline at end of file