🌱 Improve addon template controller logging and template mode support (#1184)
Some checks failed
Post / coverage (push) Failing after 29s
Post / images (amd64, addon-manager) (push) Failing after 29s
Post / images (amd64, placement) (push) Failing after 24s
Post / images (amd64, registration) (push) Failing after 41s
Post / images (amd64, registration-operator) (push) Failing after 23s
Post / images (amd64, work) (push) Failing after 36s
Post / images (arm64, addon-manager) (push) Failing after 33s
Post / images (arm64, placement) (push) Failing after 29s
Post / images (arm64, registration) (push) Failing after 31s
Post / images (arm64, registration-operator) (push) Failing after 28s
Post / images (arm64, work) (push) Failing after 31s
Post / image manifest (addon-manager) (push) Has been skipped
Post / image manifest (placement) (push) Has been skipped
Post / image manifest (registration) (push) Has been skipped
Post / image manifest (registration-operator) (push) Has been skipped
Post / image manifest (work) (push) Has been skipped
Post / trigger clusteradm e2e (push) Has been skipped
Scorecard supply-chain security / Scorecard analysis (push) Failing after 41s
Close stale issues and PRs / stale (push) Failing after 31s

* Upgrade addon template to the latest version

Signed-off-by: zhujian <jiazhu@redhat.com>

* Improve addon template controller logging and template mode

- Reduce log verbosity for duplicate manager check to V(4)
- Enable template mode in addon manager for better template support

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: zhujian <jiazhu@redhat.com>

---------

Signed-off-by: zhujian <jiazhu@redhat.com>
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Jian Zhu
2025-09-16 14:41:01 +08:00
committed by GitHub
parent dfc7bdc969
commit cca5ba8b42
16 changed files with 191 additions and 36 deletions

2
go.mod
View File

@@ -39,7 +39,7 @@ require (
k8s.io/kube-aggregator v0.33.4
k8s.io/kubectl v0.33.4
k8s.io/utils v0.0.0-20241210054802-24370beab758
open-cluster-management.io/addon-framework v1.0.1-0.20250910091630-7f19b89a319b
open-cluster-management.io/addon-framework v1.0.1-0.20250916042555-c8a4fa748ce9
open-cluster-management.io/api v1.0.1-0.20250903073454-c6702adf44cc
open-cluster-management.io/sdk-go v1.0.1-0.20250911065113-bff262df709b
sigs.k8s.io/about-api v0.0.0-20250131010323-518069c31c03

4
go.sum
View File

@@ -555,8 +555,8 @@ k8s.io/kubectl v0.33.4 h1:nXEI6Vi+oB9hXxoAHyHisXolm/l1qutK3oZQMak4N98=
k8s.io/kubectl v0.33.4/go.mod h1:Xe7P9X4DfILvKmlBsVqUtzktkI56lEj22SJW7cFy6nE=
k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0=
k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
open-cluster-management.io/addon-framework v1.0.1-0.20250910091630-7f19b89a319b h1:/ZT+G/UyMa20gy2OnX30IByst0Ca3VV0lgyLt1miHjk=
open-cluster-management.io/addon-framework v1.0.1-0.20250910091630-7f19b89a319b/go.mod h1:IrMjmd3dLjJtrP2Aqa0Sf/3lDysJHa4j5lNQQ13NxVs=
open-cluster-management.io/addon-framework v1.0.1-0.20250916042555-c8a4fa748ce9 h1:x0InHHM8GqY0qGYGyJx8SG7qNIOtMGs7n4EwowLksGA=
open-cluster-management.io/addon-framework v1.0.1-0.20250916042555-c8a4fa748ce9/go.mod h1:IrMjmd3dLjJtrP2Aqa0Sf/3lDysJHa4j5lNQQ13NxVs=
open-cluster-management.io/api v1.0.1-0.20250903073454-c6702adf44cc h1:U8O6RhHjp088oWuQsGx6pwwFpOFgWo1gl9qhgIGgDpk=
open-cluster-management.io/api v1.0.1-0.20250903073454-c6702adf44cc/go.mod h1:lEc5Wkc9ON5ym/qAtIqNgrE7NW7IEOCOC611iQMlnKM=
open-cluster-management.io/sdk-go v1.0.1-0.20250911065113-bff262df709b h1:tzgcM+yJJBgMwYYbjfzW4kL8p7bsHnScE5lS/69lksE=

View File

@@ -168,7 +168,7 @@ func (c *addonTemplateController) sync(ctx context.Context, syncCtx factory.Sync
_, exist := c.addonManagers[addonName]
if exist {
logger.Info("There already is a manager started for addon, skipping", "addonName", addonName)
logger.V(4).Info("There already is a manager started for addon, skipping", "addonName", addonName)
return nil
}
@@ -206,7 +206,7 @@ func (c *addonTemplateController) startManager(
func (c *addonTemplateController) runController(ctx context.Context, addonName string) error {
logger := klog.FromContext(ctx)
mgr, err := addonmanager.New(c.kubeConfig)
mgr, err := addonmanager.NewWithOptionFuncs(c.kubeConfig, addonmanager.WithTemplateMode(true))
if err != nil {
return err
}

2
vendor/modules.txt vendored
View File

@@ -1729,7 +1729,7 @@ k8s.io/utils/path
k8s.io/utils/pointer
k8s.io/utils/ptr
k8s.io/utils/trace
# open-cluster-management.io/addon-framework v1.0.1-0.20250910091630-7f19b89a319b
# open-cluster-management.io/addon-framework v1.0.1-0.20250916042555-c8a4fa748ce9
## explicit; go 1.24.0
open-cluster-management.io/addon-framework/pkg/addonfactory
open-cluster-management.io/addon-framework/pkg/addonmanager

View File

@@ -26,13 +26,47 @@ import (
"open-cluster-management.io/sdk-go/pkg/basecontroller/factory"
)
// Option contains configuration options for BaseAddonManagerImpl.
type Option struct {
// TemplateBasedAddOn configures whether the manager is handling template-based addons.
// - true: all ManagedClusterAddOn controllers except "addon-config-controller" will only process addons
// when the referenced AddOnTemplate resources in their status.configReferences are properly set;
// the "addon-config-controller" is responsible for setting these values
// - false: process all addons without waiting for template configuration
//
// This prevents premature processing of template-based addons before their configurations
// are fully ready, avoiding unnecessary errors and retries.
// See https://github.com/open-cluster-management-io/ocm/issues/1181 for more context.
TemplateBasedAddOn bool
}
// OptionFunc is a function that modifies Option.
type OptionFunc func(*Option)
// WithTemplateMode returns an OptionFunc that sets the template mode.
func WithTemplateMode(enabled bool) OptionFunc {
return func(option *Option) {
option.TemplateBasedAddOn = enabled
}
}
// WithOption returns an OptionFunc that applies the given Option struct.
func WithOption(opt *Option) OptionFunc {
return func(option *Option) {
if opt != nil {
*option = *opt
}
}
}
// BaseAddonManagerImpl is the base implementation of BaseAddonManager
// that manages the addon agents and configs.
type BaseAddonManagerImpl struct {
addonAgents map[string]agent.AgentAddon
addonConfigs map[schema.GroupVersionResource]bool
config *rest.Config
syncContexts []factory.SyncContext
addonAgents map[string]agent.AgentAddon
addonConfigs map[schema.GroupVersionResource]bool
config *rest.Config
syncContexts []factory.SyncContext
templateBasedAddOn bool
}
// NewBaseAddonManagerImpl creates a new BaseAddonManagerImpl instance with the given config.
@@ -45,6 +79,15 @@ func NewBaseAddonManagerImpl(config *rest.Config) *BaseAddonManagerImpl {
}
}
// ApplyOptionFuncs applies OptionFunc functions to create and configure options.
func (a *BaseAddonManagerImpl) ApplyOptionFuncs(optionFuncs ...OptionFunc) {
option := &Option{}
for _, fn := range optionFuncs {
fn(option)
}
a.templateBasedAddOn = option.TemplateBasedAddOn
}
func (a *BaseAddonManagerImpl) GetConfig() *rest.Config {
return a.config
}
@@ -77,7 +120,13 @@ func (a *BaseAddonManagerImpl) StartWithInformers(ctx context.Context,
kubeInformers kubeinformers.SharedInformerFactory,
addonInformers addoninformers.SharedInformerFactory,
clusterInformers clusterv1informers.SharedInformerFactory,
dynamicInformers dynamicinformer.DynamicSharedInformerFactory) error {
dynamicInformers dynamicinformer.DynamicSharedInformerFactory,
) error {
// Determine the appropriate filter function based on templateBasedAddOn field
mcaFilterFunc := utils.AllowAllAddOns
if a.templateBasedAddOn {
mcaFilterFunc = utils.FilterTemplateBasedAddOns
}
kubeClient, err := kubernetes.NewForConfig(a.config)
if err != nil {
@@ -107,6 +156,7 @@ func (a *BaseAddonManagerImpl) StartWithInformers(ctx context.Context,
addonInformers.Addon().V1alpha1().ManagedClusterAddOns(),
workInformers,
a.addonAgents,
mcaFilterFunc,
)
registrationController := registration.NewAddonRegistrationController(
@@ -114,6 +164,7 @@ func (a *BaseAddonManagerImpl) StartWithInformers(ctx context.Context,
clusterInformers.Cluster().V1().ManagedClusters(),
addonInformers.Addon().V1alpha1().ManagedClusterAddOns(),
a.addonAgents,
mcaFilterFunc,
)
// This controller is used during migrating addons to be managed by addon-manager.
@@ -128,6 +179,13 @@ func (a *BaseAddonManagerImpl) StartWithInformers(ctx context.Context,
var addonConfigController, managementAddonConfigController factory.Controller
if len(a.addonConfigs) != 0 {
// ManagedClusterAddOn filter is intentionally disabled for the addon-config-controller.
// This is because template-based addons require this controller to set the specHash in
// managedclusteraddon.status.configReferences for addontemplates. Without this, all other
// ManagedClusterAddOn controllers would wait indefinitely for the template configurations
// to be applied.
// Consider moving the logic of setting managedclusteraddon.status.configReferences
// for addontemplates to the ocm addon-manager.
addonConfigController = addonconfig.NewAddonConfigController(
addonClient,
addonInformers.Addon().V1alpha1().ManagedClusterAddOns(),
@@ -159,6 +217,7 @@ func (a *BaseAddonManagerImpl) StartWithInformers(ctx context.Context,
nil,
addonInformers.Addon().V1alpha1().ManagedClusterAddOns(),
a.addonAgents,
mcaFilterFunc,
)
csrSignController = certificate.NewCSRSignController(
kubeClient,
@@ -166,6 +225,7 @@ func (a *BaseAddonManagerImpl) StartWithInformers(ctx context.Context,
kubeInformers.Certificates().V1().CertificateSigningRequests(),
addonInformers.Addon().V1alpha1().ManagedClusterAddOns(),
a.addonAgents,
mcaFilterFunc,
)
} else if v1beta1Supported {
csrApproveController = certificate.NewCSRApprovingController(
@@ -175,6 +235,7 @@ func (a *BaseAddonManagerImpl) StartWithInformers(ctx context.Context,
kubeInformers.Certificates().V1beta1().CertificateSigningRequests(),
addonInformers.Addon().V1alpha1().ManagedClusterAddOns(),
a.addonAgents,
mcaFilterFunc,
)
}

View File

@@ -36,7 +36,7 @@ type addonConfigController struct {
addonIndexer cache.Indexer
configListers map[schema.GroupResource]dynamiclister.Lister
queue workqueue.TypedRateLimitingInterface[string]
addonFilterFunc factory.EventFilterFunc
cmaFilterFunc factory.EventFilterFunc
configGVRs map[schema.GroupVersionResource]bool
clusterManagementAddonLister addonlisterv1alpha1.ClusterManagementAddOnLister
}
@@ -47,7 +47,7 @@ func NewAddonConfigController(
clusterManagementAddonInformers addoninformerv1alpha1.ClusterManagementAddOnInformer,
configInformerFactory dynamicinformer.DynamicSharedInformerFactory,
configGVRs map[schema.GroupVersionResource]bool,
addonFilterFunc factory.EventFilterFunc,
cmaFilterFunc factory.EventFilterFunc,
) factory.Controller {
syncCtx := factory.NewSyncContext(controllerName)
@@ -57,7 +57,7 @@ func NewAddonConfigController(
addonIndexer: addonInformers.Informer().GetIndexer(),
configListers: map[schema.GroupResource]dynamiclister.Lister{},
queue: syncCtx.Queue(),
addonFilterFunc: addonFilterFunc,
cmaFilterFunc: cmaFilterFunc,
configGVRs: configGVRs,
clusterManagementAddonLister: clusterManagementAddonInformers.Lister(),
}
@@ -153,7 +153,7 @@ func (c *addonConfigController) sync(ctx context.Context, syncCtx factory.SyncCo
return err
}
if !c.addonFilterFunc(cma) {
if c.cmaFilterFunc != nil && !c.cmaFilterFunc(cma) {
return nil
}

View File

@@ -32,6 +32,7 @@ import (
"open-cluster-management.io/addon-framework/pkg/addonmanager/constants"
"open-cluster-management.io/addon-framework/pkg/agent"
"open-cluster-management.io/addon-framework/pkg/index"
"open-cluster-management.io/addon-framework/pkg/utils"
"open-cluster-management.io/sdk-go/pkg/basecontroller/factory"
)
@@ -50,6 +51,7 @@ type addonDeployController struct {
workIndexer cache.Indexer
agentAddons map[string]agent.AgentAddon
queue workqueue.TypedRateLimitingInterface[string]
mcaFilterFunc utils.ManagedClusterAddOnFilterFunc
}
func NewAddonDeployController(
@@ -59,6 +61,7 @@ func NewAddonDeployController(
addonInformers addoninformerv1alpha1.ManagedClusterAddOnInformer,
workInformers workinformers.ManifestWorkInformer,
agentAddons map[string]agent.AgentAddon,
mcaFilterFunc utils.ManagedClusterAddOnFilterFunc,
) factory.Controller {
syncCtx := factory.NewSyncContext(controllerName)
@@ -74,6 +77,7 @@ func NewAddonDeployController(
managedClusterAddonIndexer: addonInformers.Informer().GetIndexer(),
workIndexer: workInformers.Informer().GetIndexer(),
agentAddons: agentAddons,
mcaFilterFunc: mcaFilterFunc,
}
c.setClusterInformerHandler(clusterInformers)
@@ -235,6 +239,10 @@ func (c *addonDeployController) sync(ctx context.Context, syncCtx factory.SyncCo
return err
}
if c.mcaFilterFunc != nil && !c.mcaFilterFunc(addon) {
return nil
}
// to deploy agents if there is RegistrationApplied condition.
if meta.FindStatusCondition(addon.Status.Conditions, addonapiv1alpha1.ManagedClusterAddOnRegistrationApplied) == nil {
return nil
@@ -307,7 +315,7 @@ func (c *addonDeployController) sync(ctx context.Context, syncCtx factory.SyncCo
}
if err = c.updateAddon(ctx, addon, oldAddon); err != nil {
return err
return fmt.Errorf("failed to update addon %s/%s: %w", addon.Namespace, addon.Name, err)
}
return errorsutil.NewAggregate(errs)
}
@@ -317,7 +325,10 @@ func (c *addonDeployController) sync(ctx context.Context, syncCtx factory.SyncCo
func (c *addonDeployController) updateAddon(ctx context.Context, new, old *addonapiv1alpha1.ManagedClusterAddOn) error {
if !equality.Semantic.DeepEqual(new.GetFinalizers(), old.GetFinalizers()) {
_, err := c.addonClient.AddonV1alpha1().ManagedClusterAddOns(new.Namespace).Update(ctx, new, metav1.UpdateOptions{})
return err
if err != nil {
return fmt.Errorf("failed to update addon finalizers: %w", err)
}
return nil
}
addonPatcher := patcher.NewPatcher[
@@ -326,7 +337,10 @@ func (c *addonDeployController) updateAddon(ctx context.Context, new, old *addon
addonapiv1alpha1.ManagedClusterAddOnStatus](c.addonClient.AddonV1alpha1().ManagedClusterAddOns(new.Namespace))
_, err := addonPatcher.PatchStatus(ctx, new, new.Status, old.Status)
return err
if err != nil {
return fmt.Errorf("failed to update addon status: %w", err)
}
return nil
}
func (c *addonDeployController) applyWork(ctx context.Context, appliedType string,

View File

@@ -27,6 +27,7 @@ import (
clusterv1 "open-cluster-management.io/api/cluster/v1"
"open-cluster-management.io/addon-framework/pkg/agent"
"open-cluster-management.io/addon-framework/pkg/utils"
"open-cluster-management.io/sdk-go/pkg/basecontroller/factory"
)
@@ -58,6 +59,7 @@ type csrApprovingController struct {
managedClusterAddonLister addonlisterv1alpha1.ManagedClusterAddOnLister
csrLister certificateslisters.CertificateSigningRequestLister
csrListerBeta v1beta1certificateslisters.CertificateSigningRequestLister
mcaFilterFunc utils.ManagedClusterAddOnFilterFunc
}
// NewCSRApprovingController creates a new csr approving controller
@@ -68,6 +70,7 @@ func NewCSRApprovingController(
csrBetaInformer v1beta1certificatesinformers.CertificateSigningRequestInformer,
addonInformers addoninformerv1alpha1.ManagedClusterAddOnInformer,
agentAddons map[string]agent.AgentAddon,
mcaFilterFunc utils.ManagedClusterAddOnFilterFunc,
) factory.Controller {
if (csrV1Informer != nil) == (csrBetaInformer != nil) {
klog.Fatalf("V1 and V1beta1 CSR informer cannot be present or absent at the same time")
@@ -77,6 +80,7 @@ func NewCSRApprovingController(
agentAddons: agentAddons,
managedClusterLister: clusterInformers.Lister(),
managedClusterAddonLister: addonInformers.Lister(),
mcaFilterFunc: mcaFilterFunc,
}
var csrInformer cache.SharedIndexInformer
if csrV1Informer != nil {
@@ -162,6 +166,9 @@ func (c *csrApprovingController) sync(ctx context.Context, syncCtx factory.SyncC
if err != nil {
return err
}
if c.mcaFilterFunc != nil && !c.mcaFilterFunc(managedClusterAddon) {
return nil
}
if registrationOption.CSRApproveCheck == nil {
klog.V(4).Infof("addon csr %q cannont be auto approved due to approve check not defined", csr.GetName())

View File

@@ -22,6 +22,7 @@ import (
clusterv1 "open-cluster-management.io/api/cluster/v1"
"open-cluster-management.io/addon-framework/pkg/agent"
"open-cluster-management.io/addon-framework/pkg/utils"
"open-cluster-management.io/sdk-go/pkg/basecontroller/factory"
)
@@ -32,6 +33,7 @@ type csrSignController struct {
managedClusterLister clusterlister.ManagedClusterLister
managedClusterAddonLister addonlisterv1alpha1.ManagedClusterAddOnLister
csrLister certificateslisters.CertificateSigningRequestLister
mcaFilterFunc utils.ManagedClusterAddOnFilterFunc
}
// NewCSRApprovingController creates a new csr approving controller
@@ -41,6 +43,7 @@ func NewCSRSignController(
csrInformer certificatesinformers.CertificateSigningRequestInformer,
addonInformers addoninformerv1alpha1.ManagedClusterAddOnInformer,
agentAddons map[string]agent.AgentAddon,
mcaFilterFunc utils.ManagedClusterAddOnFilterFunc,
) factory.Controller {
c := &csrSignController{
kubeClient: kubeClient,
@@ -48,6 +51,7 @@ func NewCSRSignController(
managedClusterLister: clusterInformers.Lister(),
managedClusterAddonLister: addonInformers.Lister(),
csrLister: csrInformer.Lister(),
mcaFilterFunc: mcaFilterFunc,
}
return factory.New().
WithFilteredEventsInformersQueueKeysFunc(
@@ -131,6 +135,9 @@ func (c *csrSignController) sync(ctx context.Context, syncCtx factory.SyncContex
if err != nil {
return err
}
if c.mcaFilterFunc != nil && !c.mcaFilterFunc(addon) {
return nil
}
if registrationOption.CSRSign == nil {
return nil

View File

@@ -37,7 +37,7 @@ type cmaConfigController struct {
clusterManagementAddonIndexer cache.Indexer
configListers map[schema.GroupResource]dynamiclister.Lister
queue workqueue.TypedRateLimitingInterface[string]
addonFilterFunc factory.EventFilterFunc
cmaFilterFunc factory.EventFilterFunc
configGVRs map[schema.GroupVersionResource]bool
addonPatcher patcher.Patcher[*addonapiv1alpha1.ClusterManagementAddOn,
addonapiv1alpha1.ClusterManagementAddOnSpec,
@@ -49,7 +49,7 @@ func NewCMAConfigController(
clusterManagementAddonInformers addoninformerv1alpha1.ClusterManagementAddOnInformer,
configInformerFactory dynamicinformer.DynamicSharedInformerFactory,
configGVRs map[schema.GroupVersionResource]bool,
addonFilterFunc factory.EventFilterFunc,
cmaFilterFunc factory.EventFilterFunc,
) factory.Controller {
syncCtx := factory.NewSyncContext(controllerName)
@@ -59,7 +59,7 @@ func NewCMAConfigController(
clusterManagementAddonIndexer: clusterManagementAddonInformers.Informer().GetIndexer(),
configListers: map[schema.GroupResource]dynamiclister.Lister{},
queue: syncCtx.Queue(),
addonFilterFunc: addonFilterFunc,
cmaFilterFunc: cmaFilterFunc,
configGVRs: configGVRs,
addonPatcher: patcher.NewPatcher[*addonapiv1alpha1.ClusterManagementAddOn,
addonapiv1alpha1.ClusterManagementAddOnSpec,
@@ -145,7 +145,7 @@ func (c *cmaConfigController) sync(ctx context.Context, syncCtx factory.SyncCont
return err
}
if !c.addonFilterFunc(cma) {
if c.cmaFilterFunc != nil && !c.cmaFilterFunc(cma) {
return nil
}

View File

@@ -29,7 +29,7 @@ type cmaManagedByController struct {
addonClient addonv1alpha1client.Interface
clusterManagementAddonLister addonlisterv1alpha1.ClusterManagementAddOnLister
agentAddons map[string]agent.AgentAddon
addonFilterFunc factory.EventFilterFunc
cmaFilterFunc factory.EventFilterFunc
addonPatcher patcher.Patcher[*addonapiv1alpha1.ClusterManagementAddOn,
addonapiv1alpha1.ClusterManagementAddOnSpec,
addonapiv1alpha1.ClusterManagementAddOnStatus]
@@ -39,7 +39,7 @@ func NewCMAManagedByController(
addonClient addonv1alpha1client.Interface,
clusterManagementAddonInformers addoninformerv1alpha1.ClusterManagementAddOnInformer,
agentAddons map[string]agent.AgentAddon,
addonFilterFunc factory.EventFilterFunc,
cmaFilterFunc factory.EventFilterFunc,
) factory.Controller {
syncCtx := factory.NewSyncContext(controllerName)
@@ -47,7 +47,7 @@ func NewCMAManagedByController(
addonClient: addonClient,
clusterManagementAddonLister: clusterManagementAddonInformers.Lister(),
agentAddons: agentAddons,
addonFilterFunc: addonFilterFunc,
cmaFilterFunc: cmaFilterFunc,
addonPatcher: patcher.NewPatcher[*addonapiv1alpha1.ClusterManagementAddOn,
addonapiv1alpha1.ClusterManagementAddOnSpec,
addonapiv1alpha1.ClusterManagementAddOnStatus](addonClient.AddonV1alpha1().ClusterManagementAddOns()),
@@ -60,7 +60,7 @@ func NewCMAManagedByController(
key, _ := cache.DeletionHandlingMetaNamespaceKeyFunc(obj)
return []string{key}
},
c.addonFilterFunc, clusterManagementAddonInformers.Informer()).
c.cmaFilterFunc, clusterManagementAddonInformers.Informer()).
WithSync(c.sync).ToController(controllerName)
}

View File

@@ -29,6 +29,7 @@ type addonRegistrationController struct {
managedClusterLister clusterlister.ManagedClusterLister
managedClusterAddonLister addonlisterv1alpha1.ManagedClusterAddOnLister
agentAddons map[string]agent.AgentAddon
mcaFilterFunc utils.ManagedClusterAddOnFilterFunc
}
func NewAddonRegistrationController(
@@ -36,12 +37,14 @@ func NewAddonRegistrationController(
clusterInformers clusterinformers.ManagedClusterInformer,
addonInformers addoninformerv1alpha1.ManagedClusterAddOnInformer,
agentAddons map[string]agent.AgentAddon,
mcaFilterFunc utils.ManagedClusterAddOnFilterFunc,
) factory.Controller {
c := &addonRegistrationController{
addonClient: addonClient,
managedClusterLister: clusterInformers.Lister(),
managedClusterAddonLister: addonInformers.Lister(),
agentAddons: agentAddons,
mcaFilterFunc: mcaFilterFunc,
}
return factory.New().WithFilteredEventsInformersQueueKeysFunc(
@@ -94,6 +97,10 @@ func (c *addonRegistrationController) sync(ctx context.Context, syncCtx factory.
return err
}
if c.mcaFilterFunc != nil && !c.mcaFilterFunc(managedClusterAddon) {
return nil
}
managedClusterAddonCopy := managedClusterAddon.DeepCopy()
// wait until the mca's ownerref is set.
@@ -119,7 +126,10 @@ func (c *addonRegistrationController) sync(ctx context.Context, syncCtx factory.
statusChanged, err := addonPatcher.PatchStatus(ctx, managedClusterAddonCopy, managedClusterAddonCopy.Status, managedClusterAddon.Status)
if statusChanged {
return err
if err != nil {
return fmt.Errorf("failed to patch status(supported configs) of managedclusteraddon: %w", err)
}
return nil
}
// if supported configs not change, continue to patch condition RegistrationApplied, status.Registrations and status.Namespace
@@ -132,7 +142,10 @@ func (c *addonRegistrationController) sync(ctx context.Context, syncCtx factory.
Message: "Registration of the addon agent is configured",
})
_, err = addonPatcher.PatchStatus(ctx, managedClusterAddonCopy, managedClusterAddonCopy.Status, managedClusterAddon.Status)
return err
if err != nil {
return fmt.Errorf("failed to patch status condition(registrationOption nil) of managedclusteraddon: %w", err)
}
return nil
}
if registrationOption.PermissionConfig != nil {
@@ -146,7 +159,7 @@ func (c *addonRegistrationController) sync(ctx context.Context, syncCtx factory.
})
if _, patchErr := addonPatcher.PatchStatus(
ctx, managedClusterAddonCopy, managedClusterAddonCopy.Status, managedClusterAddon.Status); patchErr != nil {
return patchErr
return fmt.Errorf("failed to patch status condition (set permission for hub agent) of managedclusteraddon: %w", patchErr)
}
return err
}
@@ -160,12 +173,15 @@ func (c *addonRegistrationController) sync(ctx context.Context, syncCtx factory.
Message: "Registration of the addon agent is configured",
})
_, err = addonPatcher.PatchStatus(ctx, managedClusterAddonCopy, managedClusterAddonCopy.Status, managedClusterAddon.Status)
return err
if err != nil {
return fmt.Errorf("failed to patch status condition(CSRConfigurations nil) of managedclusteraddon: %w", err)
}
return nil
}
configs, err := registrationOption.CSRConfigurations(managedCluster, managedClusterAddonCopy)
if err != nil {
return fmt.Errorf("get csr configurations failed: %v", err)
return fmt.Errorf("failed to get csr configurations: %w", err)
}
managedClusterAddonCopy.Status.Registrations = configs
@@ -194,6 +210,8 @@ func (c *addonRegistrationController) sync(ctx context.Context, syncCtx factory.
})
_, err = addonPatcher.PatchStatus(ctx, managedClusterAddonCopy, managedClusterAddonCopy.Status, managedClusterAddon.Status)
return err
if err != nil {
return fmt.Errorf("failed to patch status condition(successfully configured) of managedclusteraddon: %w", err)
}
return nil
}

View File

@@ -29,7 +29,8 @@ type BaseAddonManager interface {
kubeInformers kubeinformers.SharedInformerFactory,
addonInformers addoninformers.SharedInformerFactory,
clusterInformers clusterv1informers.SharedInformerFactory,
dynamicInformers dynamicinformer.DynamicSharedInformerFactory) error
dynamicInformers dynamicinformer.DynamicSharedInformerFactory,
) error
}
// AddonManager is the interface based on BaseAddonManager to initialize a manager on hub

View File

@@ -122,7 +122,8 @@ func (a *addonManager) Start(ctx context.Context) error {
return err
}
err = a.StartWithInformers(ctx, workClient, workInformers.Work().V1().ManifestWorks(), kubeInformers, addonInformers, clusterInformers, dynamicInformers)
err = a.StartWithInformers(ctx, workClient, workInformers.Work().V1().ManifestWorks(), kubeInformers,
addonInformers, clusterInformers, dynamicInformers)
if err != nil {
return err
}
@@ -141,3 +142,12 @@ func New(config *rest.Config) (AddonManager, error) {
NewBaseAddonManagerImpl(config),
}, nil
}
// NewWithOptionFuncs returns a new Manager for creating addon agents with OptionFunc functions.
func NewWithOptionFuncs(config *rest.Config, optionFuncs ...OptionFunc) (AddonManager, error) {
manager := NewBaseAddonManagerImpl(config)
manager.ApplyOptionFuncs(optionFuncs...)
return &addonManager{
manager,
}, nil
}

View File

@@ -0,0 +1,37 @@
package utils
import (
addonapiv1alpha1 "open-cluster-management.io/api/addon/v1alpha1"
)
// ManagedClusterAddOnFilterFunc is a function type that filters ManagedClusterAddOn objects.
// It returns true if the ManagedClusterAddOn should be processed, false otherwise.
// This is used to selectively process only certain types of addons based on custom criteria.
type ManagedClusterAddOnFilterFunc func(mca *addonapiv1alpha1.ManagedClusterAddOn) bool
// AllowAllAddOns is a filter function that accepts all ManagedClusterAddOn objects.
// This function always returns true, making it suitable as a no-op filter when
// no filtering is desired.
func AllowAllAddOns(mca *addonapiv1alpha1.ManagedClusterAddOn) bool {
return true
}
// FilterTemplateBasedAddOns is a filter function that only accepts ManagedClusterAddOn
// objects that are based on AddOnTemplate resources. It checks the status.configReferences
// to determine if any configuration reference points to an addontemplates resource.
func FilterTemplateBasedAddOns(mca *addonapiv1alpha1.ManagedClusterAddOn) bool {
if mca == nil {
return false
}
// Check if any of the config references is an addontemplates resource
for _, configRef := range mca.Status.ConfigReferences {
if configRef.Group == "addon.open-cluster-management.io" && configRef.Resource == "addontemplates" &&
configRef.DesiredConfig != nil && len(configRef.DesiredConfig.SpecHash) > 0 {
return true
}
}
return false
}

View File

@@ -53,7 +53,7 @@ func AgentInstallNamespaceFromDeploymentConfigFunc(
// so we can use the default namespace.
// TODO: Find a way to distinguish between the above two cases
if config == nil {
klog.InfoS("Addon deployment config is nil, return an empty string for agent install namespace",
klog.V(4).InfoS("Addon deployment config is nil, return an empty string for agent install namespace",
"addonNamespace", addon.Namespace, "addonName", addon.Name)
return "", nil
}