-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: haoqing0110 <[email protected]>
- Loading branch information
1 parent
4eca494
commit 03254b0
Showing
5 changed files
with
255 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
package cmamanagedby | ||
|
||
import ( | ||
"context" | ||
|
||
"k8s.io/apimachinery/pkg/api/errors" | ||
"k8s.io/apimachinery/pkg/runtime" | ||
"k8s.io/client-go/tools/cache" | ||
addonapiv1alpha1 "open-cluster-management.io/api/addon/v1alpha1" | ||
addonv1alpha1client "open-cluster-management.io/api/client/addon/clientset/versioned" | ||
addoninformerv1alpha1 "open-cluster-management.io/api/client/addon/informers/externalversions/addon/v1alpha1" | ||
addonlisterv1alpha1 "open-cluster-management.io/api/client/addon/listers/addon/v1alpha1" | ||
"open-cluster-management.io/sdk-go/pkg/patcher" | ||
|
||
"open-cluster-management.io/addon-framework/pkg/agent" | ||
"open-cluster-management.io/addon-framework/pkg/basecontroller/factory" | ||
) | ||
|
||
const ( | ||
controllerName = "cma-managed-by-controller" | ||
) | ||
|
||
// cmaManagedByController reconciles clustermanagementaddon on the hub | ||
// to update the annotation "addon.open-cluster-management.io/lifecycle" value. | ||
// It removes the value "self" if exist, which indicate the | ||
// the installation and upgrade of addon will no longer be managed by addon itself. | ||
// Once removed, the value will be set to "addon-manager" by the general addon manager. | ||
type cmaManagedByController struct { | ||
addonClient addonv1alpha1client.Interface | ||
clusterManagementAddonLister addonlisterv1alpha1.ClusterManagementAddOnLister | ||
agentAddons map[string]agent.AgentAddon | ||
addonFilterFunc factory.EventFilterFunc | ||
addonPatcher patcher.Patcher[*addonapiv1alpha1.ClusterManagementAddOn, | ||
addonapiv1alpha1.ClusterManagementAddOnSpec, | ||
addonapiv1alpha1.ClusterManagementAddOnStatus] | ||
} | ||
|
||
func NewCMAManagedByController( | ||
addonClient addonv1alpha1client.Interface, | ||
clusterManagementAddonInformers addoninformerv1alpha1.ClusterManagementAddOnInformer, | ||
agentAddons map[string]agent.AgentAddon, | ||
addonFilterFunc factory.EventFilterFunc, | ||
) factory.Controller { | ||
syncCtx := factory.NewSyncContext(controllerName) | ||
|
||
c := &cmaManagedByController{ | ||
addonClient: addonClient, | ||
clusterManagementAddonLister: clusterManagementAddonInformers.Lister(), | ||
agentAddons: agentAddons, | ||
addonFilterFunc: addonFilterFunc, | ||
addonPatcher: patcher.NewPatcher[*addonapiv1alpha1.ClusterManagementAddOn, | ||
addonapiv1alpha1.ClusterManagementAddOnSpec, | ||
addonapiv1alpha1.ClusterManagementAddOnStatus](addonClient.AddonV1alpha1().ClusterManagementAddOns()), | ||
} | ||
|
||
return factory.New(). | ||
WithSyncContext(syncCtx). | ||
WithFilteredEventsInformersQueueKeysFunc( | ||
func(obj runtime.Object) []string { | ||
key, _ := cache.DeletionHandlingMetaNamespaceKeyFunc(obj) | ||
return []string{key} | ||
}, | ||
c.addonFilterFunc, clusterManagementAddonInformers.Informer()). | ||
WithSync(c.sync).ToController(controllerName) | ||
} | ||
|
||
func (c *cmaManagedByController) sync(ctx context.Context, syncCtx factory.SyncContext, key string) error { | ||
_, addonName, err := cache.SplitMetaNamespaceKey(key) | ||
if err != nil { | ||
// ignore addon whose key is invalid | ||
return nil | ||
} | ||
|
||
cma, err := c.clusterManagementAddonLister.Get(addonName) | ||
if errors.IsNotFound(err) { | ||
// addon cloud be deleted, ignore | ||
return nil | ||
} | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Remove the annotation value "self" since the WithInstallStrategy() is removed in addon-framework. | ||
// The migration plan refer to https://github.com/open-cluster-management-io/ocm/issues/355. | ||
cmaCopy := cma.DeepCopy() | ||
if cmaCopy.Annotations == nil || | ||
cmaCopy.Annotations[addonapiv1alpha1.AddonLifecycleAnnotationKey] != addonapiv1alpha1.AddonLifecycleSelfManageAnnotationValue { | ||
return nil | ||
} | ||
cmaCopy.Annotations[addonapiv1alpha1.AddonLifecycleAnnotationKey] = "" | ||
|
||
_, err = c.addonPatcher.PatchLabelAnnotations(ctx, cmaCopy, cmaCopy.ObjectMeta, cma.ObjectMeta) | ||
return err | ||
} |
134 changes: 134 additions & 0 deletions
134
pkg/addonmanager/controllers/cmamanagedby/controller_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
package cmamanagedby | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"testing" | ||
"time" | ||
|
||
"k8s.io/apimachinery/pkg/runtime" | ||
clienttesting "k8s.io/client-go/testing" | ||
"open-cluster-management.io/addon-framework/pkg/addonmanager/addontesting" | ||
"open-cluster-management.io/addon-framework/pkg/agent" | ||
"open-cluster-management.io/addon-framework/pkg/utils" | ||
addonapiv1alpha1 "open-cluster-management.io/api/addon/v1alpha1" | ||
fakeaddon "open-cluster-management.io/api/client/addon/clientset/versioned/fake" | ||
addoninformers "open-cluster-management.io/api/client/addon/informers/externalversions" | ||
clusterv1 "open-cluster-management.io/api/cluster/v1" | ||
"open-cluster-management.io/sdk-go/pkg/patcher" | ||
) | ||
|
||
type testAgent struct { | ||
name string | ||
} | ||
|
||
func (t *testAgent) Manifests(cluster *clusterv1.ManagedCluster, addon *addonapiv1alpha1.ManagedClusterAddOn) ([]runtime.Object, error) { | ||
return nil, nil | ||
} | ||
|
||
func (t *testAgent) GetAgentAddonOptions() agent.AgentAddonOptions { | ||
return agent.AgentAddonOptions{ | ||
AddonName: t.name, | ||
} | ||
} | ||
|
||
func newClusterManagementAddonWithAnnotation(name string, annotations map[string]string) *addonapiv1alpha1.ClusterManagementAddOn { | ||
cma := addontesting.NewClusterManagementAddon(name, "", "").Build() | ||
cma.Annotations = annotations | ||
return cma | ||
} | ||
|
||
func TestReconcile(t *testing.T) { | ||
cases := []struct { | ||
name string | ||
cma []runtime.Object | ||
testaddons map[string]agent.AgentAddon | ||
validateAddonActions func(t *testing.T, actions []clienttesting.Action) | ||
}{ | ||
{ | ||
name: "no patch annotation if nil", | ||
cma: []runtime.Object{newClusterManagementAddonWithAnnotation("test", nil)}, | ||
validateAddonActions: addontesting.AssertNoActions, | ||
testaddons: map[string]agent.AgentAddon{ | ||
"test": &testAgent{name: "test"}, | ||
}, | ||
}, | ||
{ | ||
name: "no patch annotation if managed by not exist", | ||
cma: []runtime.Object{newClusterManagementAddonWithAnnotation("test", map[string]string{ | ||
"test": "test", | ||
})}, | ||
validateAddonActions: addontesting.AssertNoActions, | ||
testaddons: map[string]agent.AgentAddon{ | ||
"test": &testAgent{name: "test"}, | ||
}, | ||
}, | ||
{ | ||
name: "no patch annotation if managed by is not self", | ||
cma: []runtime.Object{newClusterManagementAddonWithAnnotation("test", map[string]string{ | ||
"test": "test", | ||
addonapiv1alpha1.AddonLifecycleAnnotationKey: "xxx", | ||
})}, | ||
validateAddonActions: addontesting.AssertNoActions, | ||
testaddons: map[string]agent.AgentAddon{ | ||
"test": &testAgent{name: "test"}, | ||
}, | ||
}, | ||
{ | ||
name: "patch annotation if managed by self", | ||
cma: []runtime.Object{newClusterManagementAddonWithAnnotation("test", map[string]string{ | ||
"test": "test", | ||
addonapiv1alpha1.AddonLifecycleAnnotationKey: addonapiv1alpha1.AddonLifecycleSelfManageAnnotationValue, | ||
})}, | ||
validateAddonActions: func(t *testing.T, actions []clienttesting.Action) { | ||
addontesting.AssertActions(t, actions, "patch") | ||
patch := actions[0].(clienttesting.PatchActionImpl).Patch | ||
cma := &addonapiv1alpha1.ClusterManagementAddOn{} | ||
err := json.Unmarshal(patch, cma) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
if len(cma.Annotations) != 1 || cma.Annotations[addonapiv1alpha1.AddonLifecycleAnnotationKey] != "" { | ||
t.Errorf("cma annotation is not correct, expected self but got %s", cma.Annotations[addonapiv1alpha1.AddonLifecycleAnnotationKey]) | ||
} | ||
}, | ||
testaddons: map[string]agent.AgentAddon{ | ||
"test": &testAgent{name: "test"}, | ||
}, | ||
}, | ||
} | ||
|
||
for _, c := range cases { | ||
t.Run(c.name, func(t *testing.T) { | ||
fakeAddonClient := fakeaddon.NewSimpleClientset(c.cma...) | ||
addonInformers := addoninformers.NewSharedInformerFactory(fakeAddonClient, 10*time.Minute) | ||
|
||
for _, obj := range c.cma { | ||
if err := addonInformers.Addon().V1alpha1().ClusterManagementAddOns().Informer().GetStore().Add(obj); err != nil { | ||
t.Fatal(err) | ||
} | ||
} | ||
|
||
controller := cmaManagedByController{ | ||
addonClient: fakeAddonClient, | ||
clusterManagementAddonLister: addonInformers.Addon().V1alpha1().ClusterManagementAddOns().Lister(), | ||
agentAddons: c.testaddons, | ||
addonFilterFunc: utils.FilterByAddonName(c.testaddons), | ||
addonPatcher: patcher.NewPatcher[*addonapiv1alpha1.ClusterManagementAddOn, | ||
addonapiv1alpha1.ClusterManagementAddOnSpec, | ||
addonapiv1alpha1.ClusterManagementAddOnStatus](fakeAddonClient.AddonV1alpha1().ClusterManagementAddOns()), | ||
} | ||
|
||
for _, obj := range c.cma { | ||
cma := obj.(*addonapiv1alpha1.ClusterManagementAddOn) | ||
syncContext := addontesting.NewFakeSyncContext(t) | ||
err := controller.sync(context.TODO(), syncContext, cma.Name) | ||
if err != nil { | ||
t.Errorf("expected no error when sync: %v", err) | ||
} | ||
} | ||
c.validateAddonActions(t, fakeAddonClient.Actions()) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters