Files
open-cluster-management/pkg/hub/managedclusterset/default_managedclusterset_controller.go
DangPeng Liu 5b9b4a2c08 add global clusterset (#251)
Signed-off-by: ldpliu <daliu@redhat.com>
2022-06-09 02:46:14 -04:00

136 lines
4.8 KiB
Go

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 (
autoUpdateAnnotation = "cluster.open-cluster-management.io/autoupdate"
DefaultManagedClusterSetName = "default"
)
var DefaultManagedClusterSet = &clusterv1beta1.ManagedClusterSet{
ObjectMeta: metav1.ObjectMeta{
Name: DefaultManagedClusterSetName,
},
Spec: clusterv1beta1.ManagedClusterSetSpec{
ClusterSelector: clusterv1beta1.ManagedClusterSelector{
SelectorType: clusterv1beta1.LegacyClusterSetLabel,
},
},
}
type defaultManagedClusterSetController struct {
clusterSetClient clustersetv1beta1.ClusterV1beta1Interface
clusterSetLister clusterlisterv1beta1.ManagedClusterSetLister
eventRecorder events.Recorder
}
func NewDefaultManagedClusterSetController(
clusterSetClient clustersetv1beta1.ClusterV1beta1Interface,
clusterSetInformer clusterinformerv1beta1.ManagedClusterSetInformer,
recorder events.Recorder) factory.Controller {
c := &defaultManagedClusterSetController{
clusterSetClient: clusterSetClient,
clusterSetLister: clusterSetInformer.Lister(),
eventRecorder: recorder.WithComponentSuffix("default-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 defaultManagedClusterSet.
return DefaultManagedClusterSetName != metaObj.GetObjectMeta().GetName()
},
clusterSetInformer.Informer(),
).
WithSync(c.sync).
// use ResyncEvery to make sure:
// 1. create the default clusterset once controller is launched
// 2. the default clusterset be recreated once it is deleted for some reason
ResyncEvery(10*time.Second).
ToController("DefaultManagedClusterSetController", recorder)
}
func (c *defaultManagedClusterSetController) sync(ctx context.Context, syncCtx factory.SyncContext) error {
klog.V(4).Infof("Reconciling DefaultManagedClusterSet")
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
}
if err := c.syncDefaultClusterSet(ctx, defaultClusterSet); err != nil {
return fmt.Errorf("failed to sync DefaultManagedClusterSet %q: %w", DefaultManagedClusterSetName, err)
}
return nil
}
// syncDefaultClusterSet syncs default cluster set.
func (c *defaultManagedClusterSetController) syncDefaultClusterSet(ctx context.Context, originalDefaultClusterSet *clusterv1beta1.ManagedClusterSet) error {
defaultClusterSet := originalDefaultClusterSet.DeepCopy()
// if the annotation has set to disable, default clusterset controller will not work.
if hasAnnotation(defaultClusterSet, autoUpdateAnnotation, "false") {
klog.V(4).Info("DefaultManagedClusterSetDisabled", "The DefaultManagedClusterSet is disabled by user")
return nil
}
// if defaultClusterSet.Spec is changed, rollback the change by update it to the original value.
if !equality.Semantic.DeepEqual(defaultClusterSet.Spec, DefaultManagedClusterSet.Spec) {
defaultClusterSet.Spec = DefaultManagedClusterSet.Spec
_, err := c.clusterSetClient.ManagedClusterSets().Update(ctx, defaultClusterSet, metav1.UpdateOptions{})
if err != nil {
return fmt.Errorf("failed to update status of ManagedClusterSet %q: %w", defaultClusterSet.Name, err)
}
c.eventRecorder.Eventf("DefaultManagedClusterSetSpecRollbacked", "Rollback the DefaultManagedClusterSetSpec to %+v", defaultClusterSet.Spec)
}
return nil
}
func hasAnnotation(set *clusterv1beta1.ManagedClusterSet, key, value string) bool {
if set.Annotations == nil {
return false
}
if v, ok := set.Annotations[key]; ok && v == value {
return true
}
return false
}