From 5b9b4a2c080a671554bdbe73c18d782c7a5bea03 Mon Sep 17 00:00:00 2001 From: DangPeng Liu Date: Thu, 9 Jun 2022 14:46:14 +0800 Subject: [PATCH] add global clusterset (#251) Signed-off-by: ldpliu --- .../default_managedclusterset_controller.go | 52 +++---- ...fault_managedclusterset_controller_test.go | 12 +- .../global_managedclusterset_controller.go | 124 ++++++++++++++++ ...lobal_managedclusterset_controller_test.go | 136 ++++++++++++++++++ pkg/hub/manager.go | 8 +- ...fault_managedclusterset_controller_test.go | 23 +-- ...lobal_managedclusterset_controller_test.go | 111 ++++++++++++++ 7 files changed, 411 insertions(+), 55 deletions(-) create mode 100644 pkg/hub/managedclusterset/global_managedclusterset_controller.go create mode 100644 pkg/hub/managedclusterset/global_managedclusterset_controller_test.go create mode 100644 test/integration/global_managedclusterset_controller_test.go diff --git a/pkg/hub/managedclusterset/default_managedclusterset_controller.go b/pkg/hub/managedclusterset/default_managedclusterset_controller.go index 8d2e0201e..63bf5b04f 100644 --- a/pkg/hub/managedclusterset/default_managedclusterset_controller.go +++ b/pkg/hub/managedclusterset/default_managedclusterset_controller.go @@ -21,20 +21,18 @@ import ( const ( autoUpdateAnnotation = "cluster.open-cluster-management.io/autoupdate" - defaultManagedClusterSetName = "default" + DefaultManagedClusterSetName = "default" ) -var defaultManagedClusterSetSpec = clusterv1beta1.ManagedClusterSetSpec{ - ClusterSelector: clusterv1beta1.ManagedClusterSelector{ - SelectorType: clusterv1beta1.LegacyClusterSetLabel, - }, -} - -var defaultManagedClusterSet = &clusterv1beta1.ManagedClusterSet{ +var DefaultManagedClusterSet = &clusterv1beta1.ManagedClusterSet{ ObjectMeta: metav1.ObjectMeta{ - Name: defaultManagedClusterSetName, + Name: DefaultManagedClusterSetName, + }, + Spec: clusterv1beta1.ManagedClusterSetSpec{ + ClusterSelector: clusterv1beta1.ManagedClusterSelector{ + SelectorType: clusterv1beta1.LegacyClusterSetLabel, + }, }, - Spec: defaultManagedClusterSetSpec, } type defaultManagedClusterSetController struct { @@ -66,7 +64,7 @@ func NewDefaultManagedClusterSetController( return false } // filter clustersets except defaultManagedClusterSet. - return defaultManagedClusterSetName != metaObj.GetObjectMeta().GetName() + return DefaultManagedClusterSetName != metaObj.GetObjectMeta().GetName() }, clusterSetInformer.Informer(), ). @@ -79,31 +77,23 @@ func NewDefaultManagedClusterSetController( } func (c *defaultManagedClusterSetController) sync(ctx context.Context, syncCtx factory.SyncContext) error { - defaultClusterSetName := defaultManagedClusterSetName klog.V(4).Infof("Reconciling DefaultManagedClusterSet") - defaultClusterSet, err := c.clusterSetLister.Get(defaultClusterSetName) - - // if the defaultClusterSet not found, apply it. - if errors.IsNotFound(err) { - _, err := c.clusterSetClient.ManagedClusterSets().Create(ctx, defaultManagedClusterSet, metav1.CreateOptions{}) - if err == nil { - c.eventRecorder.Eventf("DefaultManagedClusterSetCreated", "Set the DefaultManagedClusterSet name to %+v. spec to %+v", defaultClusterSetName, defaultManagedClusterSetSpec) + defaultClusterSet, err := c.clusterSetLister.Get(DefaultManagedClusterSetName) + if err != nil { + // if the defaultClusterSet not found, apply it. + if errors.IsNotFound(err) { + _, err := c.clusterSetClient.ManagedClusterSets().Create(ctx, DefaultManagedClusterSet, metav1.CreateOptions{}) + if err == nil { + c.eventRecorder.Eventf("DefaultManagedClusterSetCreated", "Set the DefaultManagedClusterSet name to %+v. spec to %+v", DefaultManagedClusterSetName, DefaultManagedClusterSet.Spec) + } + return err } return err - - } else if err != nil { - return err - } - - // if defaultClusterSet is terminating, add the key to the controller queue with a second-long delay - if !defaultClusterSet.DeletionTimestamp.IsZero() { - syncCtx.Queue().AddAfter(defaultClusterSetName, 5*time.Second) - return nil } if err := c.syncDefaultClusterSet(ctx, defaultClusterSet); err != nil { - return fmt.Errorf("failed to sync DefaultManagedClusterSet %q: %w", defaultClusterSetName, err) + return fmt.Errorf("failed to sync DefaultManagedClusterSet %q: %w", DefaultManagedClusterSetName, err) } return nil @@ -120,8 +110,8 @@ func (c *defaultManagedClusterSetController) syncDefaultClusterSet(ctx context.C } // if defaultClusterSet.Spec is changed, rollback the change by update it to the original value. - if !equality.Semantic.DeepEqual(defaultClusterSet.Spec, defaultManagedClusterSetSpec) { - defaultClusterSet.Spec = defaultManagedClusterSetSpec + if !equality.Semantic.DeepEqual(defaultClusterSet.Spec, DefaultManagedClusterSet.Spec) { + defaultClusterSet.Spec = DefaultManagedClusterSet.Spec _, err := c.clusterSetClient.ManagedClusterSets().Update(ctx, defaultClusterSet, metav1.UpdateOptions{}) if err != nil { diff --git a/pkg/hub/managedclusterset/default_managedclusterset_controller_test.go b/pkg/hub/managedclusterset/default_managedclusterset_controller_test.go index 68884b4f0..4d4a6f9d2 100644 --- a/pkg/hub/managedclusterset/default_managedclusterset_controller_test.go +++ b/pkg/hub/managedclusterset/default_managedclusterset_controller_test.go @@ -31,27 +31,27 @@ func TestSyncDefaultClusterSet(t *testing.T) { }{ { name: "sync default cluster set", - existingClusterSet: newDefaultManagedClusterSet(defaultManagedClusterSetName, defaultManagedClusterSetSpec, false), + existingClusterSet: newDefaultManagedClusterSet(DefaultManagedClusterSetName, DefaultManagedClusterSet.Spec, false), validateActions: func(t *testing.T, actions []clienttesting.Action) { testinghelpers.AssertNoActions(t, actions) }, }, { name: "sync edited default cluster set", - existingClusterSet: newDefaultManagedClusterSet(defaultManagedClusterSetName, editedDefaultManagedClusterSetSpec, false), + existingClusterSet: newDefaultManagedClusterSet(DefaultManagedClusterSetName, editedDefaultManagedClusterSetSpec, false), validateActions: func(t *testing.T, actions []clienttesting.Action) { testinghelpers.AssertActions(t, actions, "update") clusterset := actions[0].(clienttesting.UpdateAction).GetObject().(*clusterv1beta1.ManagedClusterSet) // if spec not rollbacked, error - if !equality.Semantic.DeepEqual(clusterset.Spec, defaultManagedClusterSetSpec) { + if !equality.Semantic.DeepEqual(clusterset.Spec, DefaultManagedClusterSet.Spec) { t.Errorf("Failed to rollback default managed cluster set spec after it is edited") } }, }, { name: "sync deleting default cluster set", - existingClusterSet: newDefaultManagedClusterSet(defaultManagedClusterSetName, defaultManagedClusterSetSpec, true), + existingClusterSet: newDefaultManagedClusterSet(DefaultManagedClusterSetName, DefaultManagedClusterSet.Spec, true), validateActions: func(t *testing.T, actions []clienttesting.Action) { testinghelpers.AssertNoActions(t, actions) }, @@ -62,14 +62,14 @@ func TestSyncDefaultClusterSet(t *testing.T) { validateActions: func(t *testing.T, actions []clienttesting.Action) { testinghelpers.AssertActions(t, actions, "create") clusterset := actions[0].(clienttesting.CreateAction).GetObject().(*clusterv1beta1.ManagedClusterSet) - if clusterset.ObjectMeta.Name != defaultManagedClusterSetName { + if clusterset.ObjectMeta.Name != DefaultManagedClusterSetName { t.Errorf("Failed to create default managed cluster set") } }, }, { name: "sync default cluster set with disabled annotation", - existingClusterSet: newDefaultManagedClusterSetWithAnnotation(defaultManagedClusterSetName, autoUpdateAnnotation, "false", defaultManagedClusterSetSpec, false), + existingClusterSet: newDefaultManagedClusterSetWithAnnotation(DefaultManagedClusterSetName, autoUpdateAnnotation, "false", DefaultManagedClusterSet.Spec, false), validateActions: func(t *testing.T, actions []clienttesting.Action) { testinghelpers.AssertNoActions(t, actions) }, diff --git a/pkg/hub/managedclusterset/global_managedclusterset_controller.go b/pkg/hub/managedclusterset/global_managedclusterset_controller.go new file mode 100644 index 000000000..496d9e400 --- /dev/null +++ b/pkg/hub/managedclusterset/global_managedclusterset_controller.go @@ -0,0 +1,124 @@ +package managedclusterset + +import ( + "context" + "fmt" + "time" + + "github.com/openshift/library-go/pkg/controller/factory" + "github.com/openshift/library-go/pkg/operator/events" + "k8s.io/apimachinery/pkg/api/equality" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/klog/v2" + clustersetv1beta1 "open-cluster-management.io/api/client/cluster/clientset/versioned/typed/cluster/v1beta1" + clusterinformerv1beta1 "open-cluster-management.io/api/client/cluster/informers/externalversions/cluster/v1beta1" + clusterlisterv1beta1 "open-cluster-management.io/api/client/cluster/listers/cluster/v1beta1" + clusterv1beta1 "open-cluster-management.io/api/cluster/v1beta1" +) + +const ( + GlobalManagedClusterSetName = "global" +) + +var GlobalManagedClusterSet = &clusterv1beta1.ManagedClusterSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: GlobalManagedClusterSetName, + }, + Spec: clusterv1beta1.ManagedClusterSetSpec{ + ClusterSelector: clusterv1beta1.ManagedClusterSelector{ + SelectorType: clusterv1beta1.LabelSelector, + LabelSelector: &metav1.LabelSelector{}, + }, + }, +} + +type globalManagedClusterSetController struct { + clusterSetClient clustersetv1beta1.ClusterV1beta1Interface + clusterSetLister clusterlisterv1beta1.ManagedClusterSetLister + eventRecorder events.Recorder +} + +func NewGlobalManagedClusterSetController( + clusterSetClient clustersetv1beta1.ClusterV1beta1Interface, + clusterSetInformer clusterinformerv1beta1.ManagedClusterSetInformer, + recorder events.Recorder) factory.Controller { + + c := &globalManagedClusterSetController{ + clusterSetClient: clusterSetClient, + clusterSetLister: clusterSetInformer.Lister(), + eventRecorder: recorder.WithComponentSuffix("global-managed-cluster-set-controller"), + } + + return factory.New(). + WithFilteredEventsInformersQueueKeyFunc( + func(obj runtime.Object) string { + accessor, _ := meta.Accessor(obj) + return accessor.GetName() + }, + func(obj interface{}) bool { + metaObj, ok := obj.(metav1.ObjectMetaAccessor) + if !ok { + return false + } + // filter clustersets except globalManagedClusterSet. + return GlobalManagedClusterSetName != metaObj.GetObjectMeta().GetName() + }, + clusterSetInformer.Informer(), + ). + WithSync(c.sync). + // use ResyncEvery to make sure: + // 1. create the global clusterset once controller is launched + // 2. the global clusterset be recreated once it is deleted for some reason + ResyncEvery(10*time.Second). + ToController("GlobalManagedClusterSetController", recorder) +} + +func (c *globalManagedClusterSetController) sync(ctx context.Context, syncCtx factory.SyncContext) error { + klog.V(4).Infof("Reconciling GlobalManagedClusterSet") + globalClusterSet, err := c.clusterSetLister.Get(GlobalManagedClusterSetName) + // if the globalClusterSet not found, apply it. + if err != nil { + if errors.IsNotFound(err) { + _, err := c.clusterSetClient.ManagedClusterSets().Create(ctx, GlobalManagedClusterSet, metav1.CreateOptions{}) + if err == nil { + c.eventRecorder.Eventf("GlobalManagedClusterSetCreated", "Set the GlobalManagedClusterSet name to %+v. spec to %+v", GlobalManagedClusterSetName, GlobalManagedClusterSet.Spec) + } + return err + } + return err + } + + if err := c.applyGlobalClusterSet(ctx, globalClusterSet); err != nil { + return fmt.Errorf("failed to sync GlobalManagedClusterSet %q: %w", GlobalManagedClusterSetName, err) + } + + return nil +} + +// applyGlobalClusterSet syncs global cluster set. +func (c *globalManagedClusterSetController) applyGlobalClusterSet(ctx context.Context, originalGlobalClusterSet *clusterv1beta1.ManagedClusterSet) error { + globalClusterSet := originalGlobalClusterSet.DeepCopy() + + // if the annotation has set to disable, global clusterset controller will not work. + if hasAnnotation(globalClusterSet, autoUpdateAnnotation, "false") { + klog.V(4).Info("GlobalManagedClusterSetDisabled", "The GlobalManagedClusterSet is disabled by user") + return nil + } + + // if globalClusterSet.Spec is changed, rollback the change by update it to the original value. + if !equality.Semantic.DeepEqual(globalClusterSet.Spec, GlobalManagedClusterSet.Spec) { + globalClusterSet.Spec = GlobalManagedClusterSet.Spec + + _, err := c.clusterSetClient.ManagedClusterSets().Update(ctx, globalClusterSet, metav1.UpdateOptions{}) + if err != nil { + return fmt.Errorf("failed to update status of ManagedClusterSet %q: %w", globalClusterSet.Name, err) + } + + c.eventRecorder.Eventf("GlobalManagedClusterSetSpecRollbacked", "Rollback the GlobalManagedClusterSetSpec to %+v", globalClusterSet.Spec) + } + + return nil +} diff --git a/pkg/hub/managedclusterset/global_managedclusterset_controller_test.go b/pkg/hub/managedclusterset/global_managedclusterset_controller_test.go new file mode 100644 index 000000000..e5dfb4a08 --- /dev/null +++ b/pkg/hub/managedclusterset/global_managedclusterset_controller_test.go @@ -0,0 +1,136 @@ +package managedclusterset + +import ( + "context" + "testing" + "time" + + "github.com/openshift/library-go/pkg/operator/events/eventstesting" + "k8s.io/apimachinery/pkg/api/equality" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + clienttesting "k8s.io/client-go/testing" + clusterfake "open-cluster-management.io/api/client/cluster/clientset/versioned/fake" + clusterinformers "open-cluster-management.io/api/client/cluster/informers/externalversions" + clusterv1beta1 "open-cluster-management.io/api/cluster/v1beta1" + testinghelpers "open-cluster-management.io/registration/pkg/helpers/testing" +) + +func TestSyncGlobalClusterSet(t *testing.T) { + + var editedGlobalManagedClusterSetSpec = clusterv1beta1.ManagedClusterSetSpec{ + ClusterSelector: clusterv1beta1.ManagedClusterSelector{ + SelectorType: "non-LegacyClusterSetLabel", + }, + } + + cases := []struct { + name string + existingClusterSet *clusterv1beta1.ManagedClusterSet + validateActions func(t *testing.T, actions []clienttesting.Action) + }{ + { + name: "sync global cluster set", + existingClusterSet: newGlobalManagedClusterSet(GlobalManagedClusterSetName, GlobalManagedClusterSet.Spec, false), + validateActions: func(t *testing.T, actions []clienttesting.Action) { + testinghelpers.AssertNoActions(t, actions) + }, + }, + { + name: "sync edited global cluster set", + existingClusterSet: newGlobalManagedClusterSet(GlobalManagedClusterSetName, editedGlobalManagedClusterSetSpec, false), + validateActions: func(t *testing.T, actions []clienttesting.Action) { + + testinghelpers.AssertActions(t, actions, "update") + clusterset := actions[0].(clienttesting.UpdateAction).GetObject().(*clusterv1beta1.ManagedClusterSet) + // if spec not rollbacked, error + if !equality.Semantic.DeepEqual(clusterset.Spec, GlobalManagedClusterSet.Spec) { + t.Errorf("Failed to rollback global managed cluster set spec after it is edited") + } + }, + }, + { + name: "sync deleted global cluster set", + // global cluster set should be created if it is deleted. + validateActions: func(t *testing.T, actions []clienttesting.Action) { + testinghelpers.AssertActions(t, actions, "create") + clusterset := actions[0].(clienttesting.CreateAction).GetObject().(*clusterv1beta1.ManagedClusterSet) + if clusterset.ObjectMeta.Name != GlobalManagedClusterSetName { + t.Errorf("Failed to create global managed cluster set") + } + }, + }, + { + name: "sync global cluster set with disabled annotation", + existingClusterSet: newGlobalManagedClusterSetWithAnnotation(GlobalManagedClusterSetName, autoUpdateAnnotation, "false", GlobalManagedClusterSet.Spec, false), + validateActions: func(t *testing.T, actions []clienttesting.Action) { + testinghelpers.AssertNoActions(t, actions) + }, + }, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + objects := []runtime.Object{} + + if c.existingClusterSet != nil { + objects = append(objects, c.existingClusterSet) + } + + clusterSetClient := clusterfake.NewSimpleClientset(objects...) + informerFactory := clusterinformers.NewSharedInformerFactory(clusterSetClient, 5*time.Minute) + + if c.existingClusterSet != nil { + if err := informerFactory.Cluster().V1beta1().ManagedClusterSets().Informer().GetStore().Add(c.existingClusterSet); err != nil { + t.Fatal(err) + } + } + + ctrl := globalManagedClusterSetController{ + clusterSetClient: clusterSetClient.ClusterV1beta1(), + clusterSetLister: informerFactory.Cluster().V1beta1().ManagedClusterSets().Lister(), + eventRecorder: eventstesting.NewTestingEventRecorder(t), + } + + syncErr := ctrl.sync(context.TODO(), testinghelpers.NewFakeSyncContext(t, testinghelpers.TestManagedClusterName)) + if syncErr != nil { + t.Errorf("unexpected err: %v", syncErr) + } + + c.validateActions(t, clusterSetClient.Actions()) + }) + } +} + +func newGlobalManagedClusterSet(name string, spec clusterv1beta1.ManagedClusterSetSpec, terminating bool) *clusterv1beta1.ManagedClusterSet { + clusterSet := &clusterv1beta1.ManagedClusterSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + Spec: spec, + } + if terminating { + now := metav1.Now() + clusterSet.DeletionTimestamp = &now + } + + return clusterSet +} + +func newGlobalManagedClusterSetWithAnnotation(name string, k, v string, spec clusterv1beta1.ManagedClusterSetSpec, terminating bool) *clusterv1beta1.ManagedClusterSet { + clusterSet := &clusterv1beta1.ManagedClusterSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Annotations: map[string]string{ + k: v, + }, + }, + Spec: spec, + } + if terminating { + now := metav1.Now() + clusterSet.DeletionTimestamp = &now + } + + return clusterSet +} diff --git a/pkg/hub/manager.go b/pkg/hub/manager.go index 8e8628ed4..e6729d571 100644 --- a/pkg/hub/manager.go +++ b/pkg/hub/manager.go @@ -141,13 +141,18 @@ func RunControllerManager(ctx context.Context, controllerContext *controllercmd. controllerContext.EventRecorder, ) - var defaultManagedClusterSetController factory.Controller + var defaultManagedClusterSetController, globalManagedClusterSetController factory.Controller if features.DefaultHubMutableFeatureGate.Enabled(features.DefaultClusterSet) { defaultManagedClusterSetController = managedclusterset.NewDefaultManagedClusterSetController( clusterClient.ClusterV1beta1(), clusterInformers.Cluster().V1beta1().ManagedClusterSets(), controllerContext.EventRecorder, ) + globalManagedClusterSetController = managedclusterset.NewGlobalManagedClusterSetController( + clusterClient.ClusterV1beta1(), + clusterInformers.Cluster().V1beta1().ManagedClusterSets(), + controllerContext.EventRecorder, + ) } go clusterInformers.Start(ctx.Done()) @@ -167,6 +172,7 @@ func RunControllerManager(ctx context.Context, controllerContext *controllercmd. go addOnFeatureDiscoveryController.Run(ctx, 1) if features.DefaultHubMutableFeatureGate.Enabled(features.DefaultClusterSet) { go defaultManagedClusterSetController.Run(ctx, 1) + go globalManagedClusterSetController.Run(ctx, 1) } <-ctx.Done() diff --git a/test/integration/default_managedclusterset_controller_test.go b/test/integration/default_managedclusterset_controller_test.go index 28f726517..98f2469d9 100644 --- a/test/integration/default_managedclusterset_controller_test.go +++ b/test/integration/default_managedclusterset_controller_test.go @@ -7,31 +7,23 @@ import ( "github.com/onsi/ginkgo" "github.com/onsi/gomega" "k8s.io/apimachinery/pkg/api/equality" + setcontroller "open-cluster-management.io/registration/pkg/hub/managedclusterset" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - clusterv1beta1 "open-cluster-management.io/api/cluster/v1beta1" ) var _ = ginkgo.Describe("DefaultManagedClusterSet", func() { - var ( - defaultClusterSetName = "default" - defaultManagedClusterSetSpec = clusterv1beta1.ManagedClusterSetSpec{ - ClusterSelector: clusterv1beta1.ManagedClusterSelector{ - SelectorType: clusterv1beta1.LegacyClusterSetLabel, - }, - } - ) ginkgo.It("should create DefaultManagedClusterSet successfully", func() { ginkgo.By("check whether DefaultManagedClusterSet is created") gomega.Eventually(func() error { - mcs, err := clusterClient.ClusterV1beta1().ManagedClusterSets().Get(context.TODO(), defaultClusterSetName, metav1.GetOptions{}) + mcs, err := clusterClient.ClusterV1beta1().ManagedClusterSets().Get(context.TODO(), setcontroller.DefaultManagedClusterSetName, metav1.GetOptions{}) if err != nil { return err } - if mcs.ObjectMeta.Name == defaultClusterSetName && equality.Semantic.DeepEqual(mcs.Spec, defaultManagedClusterSetSpec) { + if mcs.ObjectMeta.Name == setcontroller.DefaultManagedClusterSetName && equality.Semantic.DeepEqual(mcs.Spec, setcontroller.DefaultManagedClusterSet.Spec) { return nil } return fmt.Errorf("check not pass!") @@ -42,24 +34,21 @@ var _ = ginkgo.Describe("DefaultManagedClusterSet", func() { ginkgo.It("should recreate DefaultManagedClusterSet successfully after deleted", func() { ginkgo.By("delete DefaultManagedClusterSet") - err := clusterClient.ClusterV1beta1().ManagedClusterSets().Delete(context.TODO(), defaultClusterSetName, metav1.DeleteOptions{}) + err := clusterClient.ClusterV1beta1().ManagedClusterSets().Delete(context.TODO(), setcontroller.DefaultManagedClusterSetName, metav1.DeleteOptions{}) gomega.Expect(err).NotTo(gomega.HaveOccurred(), "try to delete DefaultManagedClusterSet error") ginkgo.By("check whether DefaultManagedClusterSet is recreated") gomega.Eventually(func() error { - mcs, err := clusterClient.ClusterV1beta1().ManagedClusterSets().Get(context.TODO(), defaultClusterSetName, metav1.GetOptions{}) + mcs, err := clusterClient.ClusterV1beta1().ManagedClusterSets().Get(context.TODO(), setcontroller.DefaultManagedClusterSetName, metav1.GetOptions{}) if err != nil { return err } - if mcs.ObjectMeta.Name == defaultClusterSetName && equality.Semantic.DeepEqual(mcs.Spec, defaultManagedClusterSetSpec) { + if mcs.ObjectMeta.Name == setcontroller.DefaultManagedClusterSetName && equality.Semantic.DeepEqual(mcs.Spec, setcontroller.DefaultManagedClusterSet.Spec) { return nil } return fmt.Errorf("check not pass!") }, eventuallyTimeout, eventuallyInterval).ShouldNot(gomega.HaveOccurred()) }) - - // TODO: - // add test case for edit default managedclusterset spec operation }) diff --git a/test/integration/global_managedclusterset_controller_test.go b/test/integration/global_managedclusterset_controller_test.go new file mode 100644 index 000000000..ba610cf00 --- /dev/null +++ b/test/integration/global_managedclusterset_controller_test.go @@ -0,0 +1,111 @@ +package integration_test + +import ( + "context" + "fmt" + "reflect" + + "github.com/onsi/ginkgo" + "github.com/onsi/gomega" + "k8s.io/apimachinery/pkg/api/equality" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + setcontroller "open-cluster-management.io/registration/pkg/hub/managedclusterset" +) + +var _ = ginkgo.Describe("GlobalManagedClusterSet", func() { + ginkgo.It("should create GlobalManagedClusterSet successfully", func() { + ginkgo.By("check whether GlobalManagedClusterSet is created") + gomega.Eventually(func() error { + mcs, err := clusterClient.ClusterV1beta1().ManagedClusterSets().Get(context.TODO(), setcontroller.GlobalManagedClusterSetName, metav1.GetOptions{}) + if err != nil { + return err + } + + if mcs.ObjectMeta.Name == setcontroller.GlobalManagedClusterSetName && reflect.DeepEqual(mcs.Spec, setcontroller.GlobalManagedClusterSet.Spec) { + return nil + } + return fmt.Errorf("check not pass!") + + }, eventuallyTimeout, eventuallyInterval).ShouldNot(gomega.HaveOccurred()) + }) + + ginkgo.It("should reconcile GlobalManagedClusterSet successfully if it changed", func() { + ginkgo.By("check whether GlobalManagedClusterSet is reconciled after changed") + mcs, err := clusterClient.ClusterV1beta1().ManagedClusterSets().Get(context.TODO(), setcontroller.GlobalManagedClusterSetName, metav1.GetOptions{}) + gomega.Expect(err).NotTo(gomega.HaveOccurred()) + + updateMcs := mcs.DeepCopy() + updateMcs.Spec.ClusterSelector.LabelSelector = &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "vendor": "openshift", + }, + } + _, err = clusterClient.ClusterV1beta1().ManagedClusterSets().Update(context.TODO(), updateMcs, metav1.UpdateOptions{}) + gomega.Expect(err).NotTo(gomega.HaveOccurred()) + + gomega.Eventually(func() error { + mcs, err := clusterClient.ClusterV1beta1().ManagedClusterSets().Get(context.TODO(), setcontroller.GlobalManagedClusterSetName, metav1.GetOptions{}) + if err != nil { + return err + } + if mcs.ObjectMeta.Name == setcontroller.GlobalManagedClusterSetName && equality.Semantic.DeepEqual(mcs.Spec, setcontroller.GlobalManagedClusterSet.Spec) { + return nil + } + return fmt.Errorf("check not pass!") + }, eventuallyTimeout, eventuallyInterval).ShouldNot(gomega.HaveOccurred()) + }) + + ginkgo.It("should not change users labels/annotations in GlobalManagedClusterSet", func() { + ginkgo.By("check whether GlobalManagedClusterSet labels/annotations reconciled after changed") + mcs, err := clusterClient.ClusterV1beta1().ManagedClusterSets().Get(context.TODO(), setcontroller.GlobalManagedClusterSetName, metav1.GetOptions{}) + gomega.Expect(err).NotTo(gomega.HaveOccurred()) + + updateMcs := mcs.DeepCopy() + updateMcs.Annotations = map[string]string{ + "annotation-test": "a1", + } + updateMcs.Labels = map[string]string{ + "label-test": "l1", + } + updateMcs.Spec.ClusterSelector.LabelSelector = &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "vendor": "openshift", + }, + } + _, err = clusterClient.ClusterV1beta1().ManagedClusterSets().Update(context.TODO(), updateMcs, metav1.UpdateOptions{}) + gomega.Expect(err).NotTo(gomega.HaveOccurred()) + + gomega.Eventually(func() error { + mcs, err := clusterClient.ClusterV1beta1().ManagedClusterSets().Get(context.TODO(), setcontroller.GlobalManagedClusterSetName, metav1.GetOptions{}) + if err != nil { + return err + } + if equality.Semantic.DeepEqual(mcs.Spec, setcontroller.GlobalManagedClusterSet.Spec) && equality.Semantic.DeepEqual(mcs.Annotations, updateMcs.Annotations) && equality.Semantic.DeepEqual(mcs.Labels, updateMcs.Labels) { + return nil + } + return fmt.Errorf("check not pass!") + }, eventuallyTimeout, eventuallyInterval).ShouldNot(gomega.HaveOccurred()) + }) + + ginkgo.It("should recreate GlobalManagedClusterSet successfully after deleted", func() { + ginkgo.By("delete GlobalManagedClusterSet") + err := clusterClient.ClusterV1beta1().ManagedClusterSets().Delete(context.TODO(), setcontroller.GlobalManagedClusterSetName, metav1.DeleteOptions{}) + gomega.Expect(err).NotTo(gomega.HaveOccurred(), "try to delete GlobalManagedClusterSet error") + + ginkgo.By("check whether GlobalManagedClusterSet is recreated") + gomega.Eventually(func() error { + mcs, err := clusterClient.ClusterV1beta1().ManagedClusterSets().Get(context.TODO(), setcontroller.GlobalManagedClusterSetName, metav1.GetOptions{}) + if err != nil { + return err + } + + if mcs.ObjectMeta.Name == setcontroller.GlobalManagedClusterSetName && equality.Semantic.DeepEqual(mcs.Spec, setcontroller.GlobalManagedClusterSet.Spec) { + return nil + } + return fmt.Errorf("check not pass!") + + }, eventuallyTimeout, eventuallyInterval).ShouldNot(gomega.HaveOccurred()) + }) + +})