package addonmanagement import ( "context" "k8s.io/apimachinery/pkg/api/errors" utilerrors "k8s.io/apimachinery/pkg/util/errors" "k8s.io/client-go/tools/cache" "k8s.io/klog/v2" addonv1beta1 "open-cluster-management.io/api/addon/v1beta1" addonclient "open-cluster-management.io/api/client/addon/clientset/versioned" addoninformerv1beta1 "open-cluster-management.io/api/client/addon/informers/externalversions/addon/v1beta1" addonlisterv1beta1 "open-cluster-management.io/api/client/addon/listers/addon/v1beta1" clusterinformersv1 "open-cluster-management.io/api/client/cluster/informers/externalversions/cluster/v1" clusterinformersv1beta1 "open-cluster-management.io/api/client/cluster/informers/externalversions/cluster/v1beta1" "open-cluster-management.io/sdk-go/pkg/basecontroller/factory" addonindex "open-cluster-management.io/ocm/pkg/addon/index" "open-cluster-management.io/ocm/pkg/common/queue" ) type addonManagementController struct { addonClient addonclient.Interface clusterManagementAddonLister addonlisterv1beta1.ClusterManagementAddOnLister clusterManagementAddonIndexer cache.Indexer reconcilers []addonManagementReconcile } // addonManagementReconcile is a interface for reconcile logic. It creates ManagedClusterAddon based on install strategy type addonManagementReconcile interface { reconcile(ctx context.Context, cma *addonv1beta1.ClusterManagementAddOn) (*addonv1beta1.ClusterManagementAddOn, reconcileState, error) } type reconcileState int64 const ( reconcileStop reconcileState = iota reconcileContinue ) func NewAddonManagementController( addonClient addonclient.Interface, addonInformers addoninformerv1beta1.ManagedClusterAddOnInformer, clusterManagementAddonInformers addoninformerv1beta1.ClusterManagementAddOnInformer, managedClusterInformer clusterinformersv1.ManagedClusterInformer, placementInformer clusterinformersv1beta1.PlacementInformer, placementDecisionInformer clusterinformersv1beta1.PlacementDecisionInformer, addonFilterFunc factory.EventFilterFunc, ) factory.Controller { c := &addonManagementController{ addonClient: addonClient, clusterManagementAddonLister: clusterManagementAddonInformers.Lister(), clusterManagementAddonIndexer: clusterManagementAddonInformers.Informer().GetIndexer(), reconcilers: []addonManagementReconcile{ &managedClusterAddonInstallReconciler{ addonClient: addonClient, managedClusterLister: managedClusterInformer.Lister(), placementDecisionLister: placementDecisionInformer.Lister(), placementLister: placementInformer.Lister(), managedClusterAddonIndexer: addonInformers.Informer().GetIndexer(), addonFilterFunc: addonFilterFunc, }, }, } return factory.New().WithInformersQueueKeysFunc( queue.QueueKeyByMetaName, addonInformers.Informer(), clusterManagementAddonInformers.Informer()). WithInformersQueueKeysFunc( addonindex.ClusterManagementAddonByPlacementDecisionQueueKey( clusterManagementAddonInformers), placementDecisionInformer.Informer()). WithInformersQueueKeysFunc( addonindex.ClusterManagementAddonByPlacementQueueKey( clusterManagementAddonInformers), placementInformer.Informer()). WithSync(c.sync).ToController("addon-management-controller") } func (c *addonManagementController) sync(ctx context.Context, syncCtx factory.SyncContext, addonName string) error { logger := klog.FromContext(ctx).WithValues("addonName", addonName) logger.V(4).Info("Reconciling addon") cma, err := c.clusterManagementAddonLister.Get(addonName) switch { case errors.IsNotFound(err): return nil case err != nil: return err } cma = cma.DeepCopy() var state reconcileState var errs []error for _, reconciler := range c.reconcilers { cma, state, err = reconciler.reconcile(ctx, cma) if err != nil { errs = append(errs, err) } if state == reconcileStop { break } } return utilerrors.NewAggregate(errs) }