Skip to content

Commit

Permalink
Set a finalizer on ClusterManagementAddOn objects
Browse files Browse the repository at this point in the history
Ref: https://issues.redhat.com/browse/ACM-8473
Signed-off-by: yiraeChristineKim <[email protected]>
  • Loading branch information
yiraeChristineKim committed Apr 24, 2024
1 parent be542a6 commit b65f83f
Show file tree
Hide file tree
Showing 21 changed files with 734 additions and 79 deletions.
16 changes: 8 additions & 8 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,17 @@ require (
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.8.4
helm.sh/helm/v3 v3.14.2
k8s.io/api v0.29.1
k8s.io/apiextensions-apiserver v0.29.0
k8s.io/apimachinery v0.29.1
k8s.io/apiserver v0.29.0
k8s.io/client-go v0.29.1
k8s.io/component-base v0.29.1
k8s.io/api v0.29.2
k8s.io/apiextensions-apiserver v0.29.2
k8s.io/apimachinery v0.29.2
k8s.io/apiserver v0.29.2
k8s.io/client-go v0.29.2
k8s.io/component-base v0.29.2
k8s.io/klog/v2 v2.110.1
k8s.io/utils v0.0.0-20240102154912-e7106e64919e
open-cluster-management.io/api v0.13.0
open-cluster-management.io/sdk-go v0.13.0
sigs.k8s.io/controller-runtime v0.17.2
sigs.k8s.io/controller-runtime v0.17.3
)

require (
Expand Down Expand Up @@ -121,7 +121,7 @@ require (
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/kms v0.29.0 // indirect
k8s.io/kms v0.29.2 // indirect
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.28.0 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
Expand Down
32 changes: 16 additions & 16 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -398,22 +398,22 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
helm.sh/helm/v3 v3.14.2 h1:V71fv+NGZv0icBlr+in1MJXuUIHCiPG1hW9gEBISTIA=
helm.sh/helm/v3 v3.14.2/go.mod h1:2itvvDv2WSZXTllknfQo6j7u3VVgMAvm8POCDgYH424=
k8s.io/api v0.29.1 h1:DAjwWX/9YT7NQD4INu49ROJuZAAAP/Ijki48GUPzxqw=
k8s.io/api v0.29.1/go.mod h1:7Kl10vBRUXhnQQI8YR/R327zXC8eJ7887/+Ybta+RoQ=
k8s.io/apiextensions-apiserver v0.29.0 h1:0VuspFG7Hj+SxyF/Z/2T0uFbI5gb5LRgEyUVE3Q4lV0=
k8s.io/apiextensions-apiserver v0.29.0/go.mod h1:TKmpy3bTS0mr9pylH0nOt/QzQRrW7/h7yLdRForMZwc=
k8s.io/apimachinery v0.29.1 h1:KY4/E6km/wLBguvCZv8cKTeOwwOBqFNjwJIdMkMbbRc=
k8s.io/apimachinery v0.29.1/go.mod h1:6HVkd1FwxIagpYrHSwJlQqZI3G9LfYWRPAkUvLnXTKU=
k8s.io/apiserver v0.29.0 h1:Y1xEMjJkP+BIi0GSEv1BBrf1jLU9UPfAnnGGbbDdp7o=
k8s.io/apiserver v0.29.0/go.mod h1:31n78PsRKPmfpee7/l9NYEv67u6hOL6AfcE761HapDM=
k8s.io/client-go v0.29.1 h1:19B/+2NGEwnFLzt0uB5kNJnfTsbV8w6TgQRz9l7ti7A=
k8s.io/client-go v0.29.1/go.mod h1:TDG/psL9hdet0TI9mGyHJSgRkW3H9JZk2dNEUS7bRks=
k8s.io/component-base v0.29.1 h1:MUimqJPCRnnHsskTTjKD+IC1EHBbRCVyi37IoFBrkYw=
k8s.io/component-base v0.29.1/go.mod h1:fP9GFjxYrLERq1GcWWZAE3bqbNcDKDytn2srWuHTtKc=
k8s.io/api v0.29.2 h1:hBC7B9+MU+ptchxEqTNW2DkUosJpp1P+Wn6YncZ474A=
k8s.io/api v0.29.2/go.mod h1:sdIaaKuU7P44aoyyLlikSLayT6Vb7bvJNCX105xZXY0=
k8s.io/apiextensions-apiserver v0.29.2 h1:UK3xB5lOWSnhaCk0RFZ0LUacPZz9RY4wi/yt2Iu+btg=
k8s.io/apiextensions-apiserver v0.29.2/go.mod h1:aLfYjpA5p3OwtqNXQFkhJ56TB+spV8Gc4wfMhUA3/b8=
k8s.io/apimachinery v0.29.2 h1:EWGpfJ856oj11C52NRCHuU7rFDwxev48z+6DSlGNsV8=
k8s.io/apimachinery v0.29.2/go.mod h1:6HVkd1FwxIagpYrHSwJlQqZI3G9LfYWRPAkUvLnXTKU=
k8s.io/apiserver v0.29.2 h1:+Z9S0dSNr+CjnVXQePG8TcBWHr3Q7BmAr7NraHvsMiQ=
k8s.io/apiserver v0.29.2/go.mod h1:B0LieKVoyU7ykQvPFm7XSdIHaCHSzCzQWPFa5bqbeMQ=
k8s.io/client-go v0.29.2 h1:FEg85el1TeZp+/vYJM7hkDlSTFZ+c5nnK44DJ4FyoRg=
k8s.io/client-go v0.29.2/go.mod h1:knlvFZE58VpqbQpJNbCbctTVXcd35mMyAAwBdpt4jrA=
k8s.io/component-base v0.29.2 h1:lpiLyuvPA9yV1aQwGLENYyK7n/8t6l3nn3zAtFTJYe8=
k8s.io/component-base v0.29.2/go.mod h1:BfB3SLrefbZXiBfbM+2H1dlat21Uewg/5qtKOl8degM=
k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0=
k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo=
k8s.io/kms v0.29.0 h1:KJ1zaZt74CgvgV3NR7tnURJ/mJOKC5X3nwon/WdwgxI=
k8s.io/kms v0.29.0/go.mod h1:mB0f9HLxRXeXUfHfn1A7rpwOlzXI1gIWu86z6buNoYA=
k8s.io/kms v0.29.2 h1:MDsbp98gSlEQs7K7dqLKNNTwKFQRYYvO4UOlBOjNy6Y=
k8s.io/kms v0.29.2/go.mod h1:s/9RC4sYRZ/6Tn6yhNjbfJuZdb8LzlXhdlBnKizeFDo=
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780=
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA=
k8s.io/utils v0.0.0-20240102154912-e7106e64919e h1:eQ/4ljkx21sObifjzXwlPKpdGLrCfRziVtos3ofG/sQ=
Expand All @@ -424,8 +424,8 @@ open-cluster-management.io/sdk-go v0.13.0 h1:ddMGsPUekQr9z03tVN6vF39Uf+WEKMtGU/x
open-cluster-management.io/sdk-go v0.13.0/go.mod h1:UnsjzYOrDTF9a8rHEXksoIAtAdO1o5CD5Jtaw6T5B9w=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.28.0 h1:TgtAeesdhpm2SGwkQasmbeqDo8th5wOBA5h/AjTKA4I=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.28.0/go.mod h1:VHVDI/KrK4fjnV61bE2g3sA7tiETLn8sooImelsCx3Y=
sigs.k8s.io/controller-runtime v0.17.2 h1:FwHwD1CTUemg0pW2otk7/U5/i5m2ymzvOXdbeGOUvw0=
sigs.k8s.io/controller-runtime v0.17.2/go.mod h1:+MngTvIQQQhfXtwfdGw/UOQ/aIaqsYywfCINOtwMO/s=
sigs.k8s.io/controller-runtime v0.17.3 h1:65QmN7r3FWgTxDMz9fvGnO1kbf2nu+acg9p2R9oYYYk=
sigs.k8s.io/controller-runtime v0.17.3/go.mod h1:N0jpP5Lo7lMTF9aL56Z/B2oWBJjey6StQM0jRbKQXtY=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
Expand Down
36 changes: 33 additions & 3 deletions pkg/addonmanager/controllers/cmamanagedby/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,19 @@ package cmamanagedby

import (
"context"
"fmt"

"k8s.io/apimachinery/pkg/api/errors"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/tools/cache"
"open-cluster-management.io/addon-framework/pkg/agent"
"open-cluster-management.io/addon-framework/pkg/basecontroller/factory"
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 (
Expand Down Expand Up @@ -80,6 +81,11 @@ func (c *cmaManagedByController) sync(ctx context.Context, syncCtx factory.SyncC
return err
}

err = c.handleFinalizer(ctx, cma, addonName)
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()
Expand All @@ -92,3 +98,27 @@ func (c *cmaManagedByController) sync(ctx context.Context, syncCtx factory.SyncC
_, err = c.addonPatcher.PatchLabelAnnotations(ctx, cmaCopy, cmaCopy.ObjectMeta, cma.ObjectMeta)
return err
}

func (c *cmaManagedByController) handleFinalizer(ctx context.Context, cma *addonapiv1alpha1.ClusterManagementAddOn, addonName string) error {
managedClusterAddonList, err := c.addonClient.AddonV1alpha1().ManagedClusterAddOns("").List(ctx, v1.ListOptions{
FieldSelector: fmt.Sprintf("metadata.name=%s", addonName),
})
if err != nil {
return err
}

if len(managedClusterAddonList.Items) == 0 {
err = c.addonPatcher.RemoveFinalizer(ctx, cma, addonapiv1alpha1.AddonPreDeleteHookFinalizer)
if err != nil {
return err
}
} else {
// length of managedClusterAddonList.Items > 0
_, err = c.addonPatcher.AddFinalizer(ctx, cma, addonapiv1alpha1.AddonPreDeleteHookFinalizer)
if err != nil {
return err
}
}

return nil
}
16 changes: 11 additions & 5 deletions pkg/addonmanager/controllers/cmamanagedby/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func TestReconcile(t *testing.T) {
{
name: "no patch annotation if nil",
cma: []runtime.Object{newClusterManagementAddonWithAnnotation("test", nil)},
validateAddonActions: addontesting.AssertNoActions,
validateAddonActions: validateWithFinalizerAction,
testaddons: map[string]agent.AgentAddon{
"test": &testAgent{name: "test"},
},
Expand All @@ -58,7 +58,7 @@ func TestReconcile(t *testing.T) {
cma: []runtime.Object{newClusterManagementAddonWithAnnotation("test", map[string]string{
"test": "test",
})},
validateAddonActions: addontesting.AssertNoActions,
validateAddonActions: validateWithFinalizerAction,
testaddons: map[string]agent.AgentAddon{
"test": &testAgent{name: "test"},
},
Expand All @@ -69,7 +69,7 @@ func TestReconcile(t *testing.T) {
"test": "test",
addonapiv1alpha1.AddonLifecycleAnnotationKey: "xxx",
})},
validateAddonActions: addontesting.AssertNoActions,
validateAddonActions: validateWithFinalizerAction,
testaddons: map[string]agent.AgentAddon{
"test": &testAgent{name: "test"},
},
Expand All @@ -81,8 +81,9 @@ func TestReconcile(t *testing.T) {
addonapiv1alpha1.AddonLifecycleAnnotationKey: addonapiv1alpha1.AddonLifecycleSelfManageAnnotationValue,
})},
validateAddonActions: func(t *testing.T, actions []clienttesting.Action) {
addontesting.AssertActions(t, actions, "patch")
patch := actions[0].(clienttesting.PatchActionImpl).Patch
addontesting.AssertActions(t, actions, "patch", "patch")
// action[0] is setting finalizer. Ignore this action
patch := actions[1].(clienttesting.PatchActionImpl).Patch
cma := &addonapiv1alpha1.ClusterManagementAddOn{}
err := json.Unmarshal(patch, cma)
if err != nil {
Expand Down Expand Up @@ -132,3 +133,8 @@ func TestReconcile(t *testing.T) {
})
}
}

// Expect that the incoming test case has only one action that is setting finalizer
func validateWithFinalizerAction(t *testing.T, actions []clienttesting.Action) {
addontesting.AssertActions(t, actions, "patch")
}
17 changes: 13 additions & 4 deletions test/integration/agent_deploy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
apiequality "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/apis/meta/v1/unstructured"
Expand Down Expand Up @@ -145,17 +146,25 @@ var _ = ginkgo.Describe("Agent deploy", func() {
cma, err = hubAddonClient.AddonV1alpha1().ClusterManagementAddOns().Create(context.Background(),
cma, metav1.CreateOptions{})
gomega.Expect(err).ToNot(gomega.HaveOccurred())

})

ginkgo.AfterEach(func() {
err = hubAddonClient.AddonV1alpha1().ClusterManagementAddOns().Delete(context.Background(),
testAddonImpl.name, metav1.DeleteOptions{})
gomega.Expect(err).ToNot(gomega.HaveOccurred())
gomega.Eventually(func() bool {
_, err := hubAddonClient.AddonV1alpha1().ClusterManagementAddOns().
Get(context.Background(), testAddonImpl.name, metav1.GetOptions{})
if errors.IsNotFound(err) {
return true
}

return false
}, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue(), "ClusterManagementAddOns should be deleted")
err = hubKubeClient.CoreV1().Namespaces().Delete(context.Background(), managedClusterName, metav1.DeleteOptions{})
gomega.Expect(err).ToNot(gomega.HaveOccurred())
err = hubClusterClient.ClusterV1().ManagedClusters().Delete(context.Background(), managedClusterName, metav1.DeleteOptions{})
gomega.Expect(err).ToNot(gomega.HaveOccurred())
err = hubAddonClient.AddonV1alpha1().ClusterManagementAddOns().Delete(context.Background(),
testAddonImpl.name, metav1.DeleteOptions{})
gomega.Expect(err).ToNot(gomega.HaveOccurred())
})

ginkgo.It("Should deploy agent when cma is managed by self successfully", func() {
Expand Down
17 changes: 12 additions & 5 deletions test/integration/agent_hook_deploy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,22 @@ var _ = ginkgo.Describe("Agent hook deploy", func() {
})

ginkgo.AfterEach(func() {
err = hubAddonClient.AddonV1alpha1().ClusterManagementAddOns().Delete(context.Background(),
testAddonImpl.name, metav1.DeleteOptions{})
gomega.Expect(err).ToNot(gomega.HaveOccurred())
gomega.Eventually(func() bool {
_, err := hubAddonClient.AddonV1alpha1().ClusterManagementAddOns().
Get(context.Background(), testAddonImpl.name, metav1.GetOptions{})
if errors.IsNotFound(err) {
return true
}

return false
}, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue(), "ClusterManagementAddOns should be deleted")
err = hubKubeClient.CoreV1().Namespaces().Delete(context.Background(), managedClusterName, metav1.DeleteOptions{})
gomega.Expect(err).ToNot(gomega.HaveOccurred())
err = hubClusterClient.ClusterV1().ManagedClusters().Delete(context.Background(), managedClusterName, metav1.DeleteOptions{})
gomega.Expect(err).ToNot(gomega.HaveOccurred())
err = hubAddonClient.AddonV1alpha1().ClusterManagementAddOns().Delete(context.Background(),
testAddonImpl.name, metav1.DeleteOptions{})
gomega.Expect(err).ToNot(gomega.HaveOccurred())
})

ginkgo.It("Should install and uninstall agent successfully", func() {
Expand Down Expand Up @@ -261,7 +270,5 @@ var _ = ginkgo.Describe("Agent hook deploy", func() {
}
return fmt.Errorf("addon is expceted to be deleted")
}, eventuallyTimeout, eventuallyInterval).ShouldNot(gomega.HaveOccurred())

})

})
17 changes: 12 additions & 5 deletions test/integration/agent_hosting_deploy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,18 @@ var _ = ginkgo.Describe("Agent deploy", func() {
})

ginkgo.AfterEach(func() {
err = hubAddonClient.AddonV1alpha1().ClusterManagementAddOns().Delete(context.Background(),
testHostedAddonImpl.name, metav1.DeleteOptions{})
gomega.Expect(err).ToNot(gomega.HaveOccurred())
gomega.Eventually(func() bool {
_, err := hubAddonClient.AddonV1alpha1().ClusterManagementAddOns().
Get(context.Background(), testHostedAddonImpl.name, metav1.GetOptions{})
if errors.IsNotFound(err) {
return true
}

return false
}, eventuallyTimeout*100, eventuallyInterval).Should(gomega.BeTrue(), "ClusterManagementAddOns should be deleted")
err = hubKubeClient.CoreV1().Namespaces().Delete(
context.Background(), managedClusterName, metav1.DeleteOptions{})
gomega.Expect(err).ToNot(gomega.HaveOccurred())
Expand All @@ -131,10 +143,6 @@ var _ = ginkgo.Describe("Agent deploy", func() {
err = hubClusterClient.ClusterV1().ManagedClusters().Delete(
context.Background(), hostingClusterName, metav1.DeleteOptions{})
gomega.Expect(err).ToNot(gomega.HaveOccurred())

err = hubAddonClient.AddonV1alpha1().ClusterManagementAddOns().Delete(context.Background(),
testHostedAddonImpl.name, metav1.DeleteOptions{})
gomega.Expect(err).ToNot(gomega.HaveOccurred())
})

ginkgo.It("Should deploy and delete agent on hosting cluster successfully", func() {
Expand Down Expand Up @@ -477,5 +485,4 @@ var _ = ginkgo.Describe("Agent deploy", func() {
}
testHostedAddonImpl.hostInfoFn = constants.GetHostedModeInfo
})

})
17 changes: 13 additions & 4 deletions test/integration/agent_hosting_hook_deploy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ var _ = ginkgo.Describe("Agent hook deploy", func() {
var managedClusterName, hostingClusterName string
var err error
var hostingManifestWorkName string
var hostingJobCompleteValue = "True"
hostingJobCompleteValue := "True"
var cma *addonapiv1alpha1.ClusterManagementAddOn
ginkgo.BeforeEach(func() {
suffix := rand.String(5)
Expand Down Expand Up @@ -121,6 +121,18 @@ var _ = ginkgo.Describe("Agent hook deploy", func() {
})

ginkgo.AfterEach(func() {
err = hubAddonClient.AddonV1alpha1().ClusterManagementAddOns().Delete(context.Background(),
testHostedAddonImpl.name, metav1.DeleteOptions{})
gomega.Expect(err).ToNot(gomega.HaveOccurred())
gomega.Eventually(func() bool {
_, err := hubAddonClient.AddonV1alpha1().ClusterManagementAddOns().
Get(context.Background(), testHostedAddonImpl.name, metav1.GetOptions{})
if errors.IsNotFound(err) {
return true
}

return false
}, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue(), "ClusterManagementAddOns should be deleted")
err = hubKubeClient.CoreV1().Namespaces().Delete(
context.Background(), managedClusterName, metav1.DeleteOptions{})
gomega.Expect(err).ToNot(gomega.HaveOccurred())
Expand All @@ -134,9 +146,6 @@ var _ = ginkgo.Describe("Agent hook deploy", func() {
err = hubClusterClient.ClusterV1().ManagedClusters().Delete(
context.Background(), hostingClusterName, metav1.DeleteOptions{})
gomega.Expect(err).ToNot(gomega.HaveOccurred())
err = hubAddonClient.AddonV1alpha1().ClusterManagementAddOns().Delete(context.Background(),
testHostedAddonImpl.name, metav1.DeleteOptions{})
gomega.Expect(err).ToNot(gomega.HaveOccurred())
})

ginkgo.It("Should install and uninstall agent successfully", func() {
Expand Down
Loading

0 comments on commit b65f83f

Please sign in to comment.