mirror of
https://github.com/open-cluster-management-io/ocm.git
synced 2026-05-20 16:14:23 +00:00
Some checks failed
Scorecard supply-chain security / Scorecard analysis (push) Failing after 28s
Post / coverage (push) Failing after 22s
Post / images (amd64, addon-manager) (push) Failing after 30s
Post / images (amd64, placement) (push) Failing after 25s
Post / images (amd64, registration) (push) Failing after 16s
Post / images (amd64, registration-operator) (push) Failing after 23s
Post / images (amd64, work) (push) Failing after 17s
Post / images (arm64, addon-manager) (push) Failing after 14s
Post / images (arm64, placement) (push) Failing after 19s
Post / images (arm64, registration) (push) Failing after 23s
Post / images (arm64, registration-operator) (push) Failing after 17s
Post / images (arm64, work) (push) Failing after 19s
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
Close stale issues and PRs / stale (push) Failing after 31s
* Remove event after apply and add jitter when requeue Signed-off-by: Jian Qiu <jqiu@redhat.com> * Change event handler to avoid redundant reconciles Signed-off-by: Jian Qiu <jqiu@redhat.com> * Add unit tests for onAdd and onUpdate function Signed-off-by: Jian Qiu <jqiu@redhat.com> * Fix interegation test fail Signed-off-by: Jian Qiu <jqiu@redhat.com> * Set resync interval to 4-6 mins Signed-off-by: Jian Qiu <jqiu@redhat.com> --------- Signed-off-by: Jian Qiu <jqiu@redhat.com>
572 lines
23 KiB
Go
572 lines
23 KiB
Go
package work
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/onsi/ginkgo/v2"
|
|
"github.com/onsi/gomega"
|
|
corev1 "k8s.io/api/core/v1"
|
|
"k8s.io/apimachinery/pkg/api/errors"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/types"
|
|
"k8s.io/apimachinery/pkg/util/rand"
|
|
|
|
workapiv1 "open-cluster-management.io/api/work/v1"
|
|
|
|
"open-cluster-management.io/ocm/test/integration/util"
|
|
)
|
|
|
|
var _ = ginkgo.Describe("ManifestWork Delete Option", func() {
|
|
var cancel context.CancelFunc
|
|
|
|
var workName string
|
|
var clusterName string
|
|
var work *workapiv1.ManifestWork
|
|
var appliedManifestWorkName string
|
|
var manifests []workapiv1.Manifest
|
|
|
|
var err error
|
|
|
|
ginkgo.BeforeEach(func() {
|
|
clusterName = rand.String(5)
|
|
workName = fmt.Sprintf("work-delete-option-%s", rand.String(5))
|
|
|
|
ns := &corev1.Namespace{}
|
|
ns.Name = clusterName
|
|
_, err := spokeKubeClient.CoreV1().Namespaces().Create(context.Background(), ns, metav1.CreateOptions{})
|
|
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
|
|
|
var ctx context.Context
|
|
ctx, cancel = context.WithCancel(context.Background())
|
|
go startWorkAgent(ctx, clusterName)
|
|
|
|
// reset manifests
|
|
manifests = nil
|
|
})
|
|
|
|
ginkgo.JustBeforeEach(func() {
|
|
work = util.NewManifestWork(clusterName, workName, manifests)
|
|
})
|
|
|
|
ginkgo.AfterEach(func() {
|
|
if cancel != nil {
|
|
cancel()
|
|
}
|
|
err := spokeKubeClient.CoreV1().Namespaces().Delete(context.Background(), clusterName, metav1.DeleteOptions{})
|
|
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
|
})
|
|
|
|
ginkgo.Context("Resource sharing and adoption between manifestworks", func() {
|
|
var anotherWork *workapiv1.ManifestWork
|
|
var anotherAppliedManifestWorkName string
|
|
ginkgo.BeforeEach(func() {
|
|
manifests = []workapiv1.Manifest{
|
|
util.ToManifest(util.NewConfigmap(clusterName, cm1, map[string]string{"a": "b"}, []string{})),
|
|
util.ToManifest(util.NewConfigmap(clusterName, cm2, map[string]string{"c": "d"}, []string{})),
|
|
}
|
|
// Create another manifestworks with one shared resource.
|
|
anotherWork = util.NewManifestWork(clusterName, "sharing-resource-work", []workapiv1.Manifest{manifests[0]})
|
|
})
|
|
|
|
ginkgo.JustBeforeEach(func() {
|
|
work, err = hubWorkClient.WorkV1().ManifestWorks(clusterName).Create(context.Background(), work, metav1.CreateOptions{})
|
|
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
|
|
|
appliedManifestWorkName = util.AppliedManifestWorkName(hubHash, work)
|
|
|
|
util.AssertWorkCondition(work.Namespace, work.Name, hubWorkClient, workapiv1.WorkApplied, metav1.ConditionTrue,
|
|
[]metav1.ConditionStatus{metav1.ConditionTrue, metav1.ConditionTrue}, eventuallyTimeout, eventuallyInterval)
|
|
util.AssertWorkCondition(work.Namespace, work.Name, hubWorkClient, workapiv1.WorkAvailable, metav1.ConditionTrue,
|
|
[]metav1.ConditionStatus{metav1.ConditionTrue, metav1.ConditionTrue}, eventuallyTimeout, eventuallyInterval)
|
|
|
|
anotherWork, err = hubWorkClient.WorkV1().ManifestWorks(clusterName).Create(context.Background(), anotherWork, metav1.CreateOptions{})
|
|
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
|
util.AssertWorkCondition(anotherWork.Namespace, anotherWork.Name, hubWorkClient, workapiv1.WorkApplied, metav1.ConditionTrue,
|
|
[]metav1.ConditionStatus{metav1.ConditionTrue}, eventuallyTimeout, eventuallyInterval)
|
|
util.AssertWorkCondition(anotherWork.Namespace, anotherWork.Name, hubWorkClient, workapiv1.WorkAvailable, metav1.ConditionTrue,
|
|
[]metav1.ConditionStatus{metav1.ConditionTrue}, eventuallyTimeout, eventuallyInterval)
|
|
|
|
anotherAppliedManifestWorkName = util.AppliedManifestWorkName(hubHash, anotherWork)
|
|
})
|
|
|
|
ginkgo.It("shared resource between the manifestwork should be kept when one manifestwork is deleted", func() {
|
|
// ensure configmap exists and get its uid
|
|
util.AssertExistenceOfConfigMaps(manifests, spokeKubeClient, eventuallyTimeout, eventuallyInterval)
|
|
currentConfigMap, err := spokeKubeClient.CoreV1().ConfigMaps(clusterName).Get(context.Background(), cm1, metav1.GetOptions{})
|
|
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
|
currentUID := currentConfigMap.UID
|
|
|
|
// Ensure that uid recorded in the appliedmanifestwork and anotherappliedmanifestwork is correct.
|
|
gomega.Eventually(func() error {
|
|
appliedManifestWork, err := spokeWorkClient.WorkV1().AppliedManifestWorks().Get(context.Background(), appliedManifestWorkName, metav1.GetOptions{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, appliedResource := range appliedManifestWork.Status.AppliedResources {
|
|
if appliedResource.Name == cm1 && appliedResource.UID == string(currentUID) {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
return fmt.Errorf("resource name or uid in appliedmanifestwork does not match")
|
|
}, eventuallyTimeout, eventuallyInterval).ShouldNot(gomega.HaveOccurred())
|
|
|
|
gomega.Eventually(func() error {
|
|
anotherAppliedManifestWork, err := spokeWorkClient.WorkV1().AppliedManifestWorks().Get(
|
|
context.Background(), anotherAppliedManifestWorkName, metav1.GetOptions{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, appliedResource := range anotherAppliedManifestWork.Status.AppliedResources {
|
|
if appliedResource.Name == cm1 && appliedResource.UID == string(currentUID) {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
return fmt.Errorf("resource name or uid in appliedmanifestwork does not match")
|
|
}, eventuallyTimeout, eventuallyInterval).ShouldNot(gomega.HaveOccurred())
|
|
|
|
// Delete one manifestwork
|
|
err = hubWorkClient.WorkV1().ManifestWorks(clusterName).Delete(context.Background(), work.Name, metav1.DeleteOptions{})
|
|
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
|
|
|
// Ensure the appliedmanifestwork of deleted manifestwork is removed so it won't try to delete shared resource
|
|
gomega.Eventually(func() error {
|
|
appliedWork, err := spokeWorkClient.WorkV1().AppliedManifestWorks().Get(context.Background(), appliedManifestWorkName, metav1.GetOptions{})
|
|
if errors.IsNotFound(err) {
|
|
return nil
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return fmt.Errorf("appliedmanifestwork should not exist: %v", appliedWork.DeletionTimestamp)
|
|
}, eventuallyTimeout, eventuallyInterval).Should(gomega.Succeed())
|
|
|
|
// Ensure the configmap is kept and tracked by anotherappliedmanifestwork.
|
|
gomega.Eventually(func() error {
|
|
configMap, err := spokeKubeClient.CoreV1().ConfigMaps(clusterName).Get(context.Background(), cm1, metav1.GetOptions{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if currentUID != configMap.UID {
|
|
return fmt.Errorf("UID should be equal")
|
|
}
|
|
|
|
anotherAppliedManifestWork, err := spokeWorkClient.WorkV1().AppliedManifestWorks().Get(
|
|
context.Background(), anotherAppliedManifestWorkName, metav1.GetOptions{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, appliedResource := range anotherAppliedManifestWork.Status.AppliedResources {
|
|
if appliedResource.Name != cm1 {
|
|
return fmt.Errorf("resource Name should be cm1")
|
|
}
|
|
|
|
if appliedResource.UID != string(currentUID) {
|
|
return fmt.Errorf("UID should be equal")
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}, eventuallyTimeout, eventuallyInterval).ShouldNot(gomega.HaveOccurred())
|
|
})
|
|
|
|
ginkgo.It("shared resource between the manifestwork should be kept when the shared resource is removed from one manifestwork", func() {
|
|
// ensure configmap exists and get its uid
|
|
util.AssertExistenceOfConfigMaps(manifests, spokeKubeClient, eventuallyTimeout, eventuallyInterval)
|
|
curentConfigMap, err := spokeKubeClient.CoreV1().ConfigMaps(clusterName).Get(context.Background(), cm1, metav1.GetOptions{})
|
|
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
|
currentUID := curentConfigMap.UID
|
|
|
|
// Ensure that uid recorded in the appliedmanifestwork and anotherappliedmanifestwork is correct.
|
|
gomega.Eventually(func() error {
|
|
appliedManifestWork, err := spokeWorkClient.WorkV1().AppliedManifestWorks().Get(context.Background(), appliedManifestWorkName, metav1.GetOptions{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, appliedResource := range appliedManifestWork.Status.AppliedResources {
|
|
if appliedResource.Name == cm1 && appliedResource.UID == string(currentUID) {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
return fmt.Errorf("resource name or uid in appliedmanifestwork does not match")
|
|
}, eventuallyTimeout, eventuallyInterval).ShouldNot(gomega.HaveOccurred())
|
|
|
|
gomega.Eventually(func() error {
|
|
anotherAppliedManifestWork, err := spokeWorkClient.WorkV1().AppliedManifestWorks().Get(
|
|
context.Background(), anotherAppliedManifestWorkName, metav1.GetOptions{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, appliedResource := range anotherAppliedManifestWork.Status.AppliedResources {
|
|
if appliedResource.Name == cm1 && appliedResource.UID == string(currentUID) {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
return fmt.Errorf("resource name or uid in appliedmanifestwork does not match")
|
|
}, eventuallyTimeout, eventuallyInterval).ShouldNot(gomega.HaveOccurred())
|
|
|
|
// Update one manifestwork to remove the shared resource
|
|
updatedWork, err := hubWorkClient.WorkV1().ManifestWorks(clusterName).Get(context.Background(), work.Name, metav1.GetOptions{})
|
|
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
|
|
|
newWork := updatedWork.DeepCopy()
|
|
newWork.Spec.Workload.Manifests = []workapiv1.Manifest{manifests[1]}
|
|
|
|
pathBytes, err := util.NewWorkPatch(updatedWork, newWork)
|
|
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
|
|
|
_, err = hubWorkClient.WorkV1().ManifestWorks(clusterName).Patch(
|
|
context.Background(), updatedWork.Name, types.MergePatchType, pathBytes, metav1.PatchOptions{})
|
|
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
|
|
|
// Ensure the resource is not tracked by the appliedmanifestwork.
|
|
gomega.Eventually(func() error {
|
|
appliedManifestWork, err := spokeWorkClient.WorkV1().AppliedManifestWorks().Get(context.Background(), appliedManifestWorkName, metav1.GetOptions{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, appliedResource := range appliedManifestWork.Status.AppliedResources {
|
|
if appliedResource.Name == cm1 {
|
|
return fmt.Errorf("found applied resource name cm1")
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}, eventuallyTimeout, eventuallyInterval).ShouldNot(gomega.HaveOccurred())
|
|
|
|
// Ensure the configmap is kept and tracked by anotherappliedmanifestwork
|
|
gomega.Consistently(func() error {
|
|
configMap, err := spokeKubeClient.CoreV1().ConfigMaps(clusterName).Get(
|
|
context.Background(), cm1, metav1.GetOptions{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if currentUID != configMap.UID {
|
|
return fmt.Errorf("UID should not be changed in configmap")
|
|
}
|
|
|
|
anotherAppliedManifestWork, err := spokeWorkClient.WorkV1().AppliedManifestWorks().Get(
|
|
context.Background(), anotherAppliedManifestWorkName, metav1.GetOptions{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, appliedResource := range anotherAppliedManifestWork.Status.AppliedResources {
|
|
if appliedResource.Name != cm1 {
|
|
return fmt.Errorf("resource Name should be cm1")
|
|
}
|
|
|
|
if appliedResource.UID != string(currentUID) {
|
|
return fmt.Errorf("UID should not be changed in appliedmanifestwork, got %v, should be %s", appliedResource.UID, currentUID)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}, eventuallyTimeout, eventuallyInterval).ShouldNot(gomega.HaveOccurred())
|
|
})
|
|
|
|
})
|
|
|
|
ginkgo.Context("Delete options", func() {
|
|
ginkgo.BeforeEach(func() {
|
|
manifests = []workapiv1.Manifest{
|
|
util.ToManifest(util.NewConfigmap(clusterName, cm1, map[string]string{"a": "b"}, []string{})),
|
|
util.ToManifest(util.NewConfigmap(clusterName, cm2, map[string]string{"c": "d"}, []string{})),
|
|
}
|
|
})
|
|
|
|
ginkgo.It("Orphan deletion of the whole manifestwork", func() {
|
|
work.Spec.DeleteOption = &workapiv1.DeleteOption{
|
|
PropagationPolicy: workapiv1.DeletePropagationPolicyTypeOrphan,
|
|
}
|
|
|
|
_, err = hubWorkClient.WorkV1().ManifestWorks(clusterName).Create(context.Background(), work, metav1.CreateOptions{})
|
|
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
|
|
|
util.AssertWorkCondition(work.Namespace, work.Name, hubWorkClient, workapiv1.WorkApplied, metav1.ConditionTrue,
|
|
[]metav1.ConditionStatus{metav1.ConditionTrue, metav1.ConditionTrue}, eventuallyTimeout, eventuallyInterval)
|
|
util.AssertWorkCondition(work.Namespace, work.Name, hubWorkClient, workapiv1.WorkAvailable, metav1.ConditionTrue,
|
|
[]metav1.ConditionStatus{metav1.ConditionTrue, metav1.ConditionTrue}, eventuallyTimeout, eventuallyInterval)
|
|
|
|
// Ensure configmap exists
|
|
util.AssertExistenceOfConfigMaps(manifests, spokeKubeClient, eventuallyTimeout, eventuallyInterval)
|
|
|
|
// Ensure ownership of configmap is updated
|
|
gomega.Eventually(func() error {
|
|
cm, err := spokeKubeClient.CoreV1().ConfigMaps(clusterName).Get(context.Background(), cm1, metav1.GetOptions{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(cm.OwnerReferences) != 0 {
|
|
return fmt.Errorf("owner reference are not correctly updated, current ownerrefs are %v", cm.OwnerReferences)
|
|
}
|
|
|
|
return nil
|
|
}, eventuallyTimeout, eventuallyInterval).ShouldNot(gomega.HaveOccurred())
|
|
|
|
gomega.Eventually(func() error {
|
|
cm, err := spokeKubeClient.CoreV1().ConfigMaps(clusterName).Get(context.Background(), cm2, metav1.GetOptions{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(cm.OwnerReferences) != 0 {
|
|
return fmt.Errorf("owner reference are not correctly updated, current ownerrefs are %v", cm.OwnerReferences)
|
|
}
|
|
|
|
return nil
|
|
}, eventuallyTimeout, eventuallyInterval).ShouldNot(gomega.HaveOccurred())
|
|
|
|
// Delete the work
|
|
err = hubWorkClient.WorkV1().ManifestWorks(clusterName).Delete(context.Background(), work.Name, metav1.DeleteOptions{})
|
|
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
|
|
|
// Wait for deletion of manifest work
|
|
gomega.Eventually(func() bool {
|
|
_, err := hubWorkClient.WorkV1().ManifestWorks(clusterName).Get(context.Background(), work.Name, metav1.GetOptions{})
|
|
return errors.IsNotFound(err)
|
|
}, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue())
|
|
|
|
// Ensure configmap exists
|
|
util.AssertExistenceOfConfigMaps(manifests, spokeKubeClient, eventuallyTimeout, eventuallyInterval)
|
|
})
|
|
|
|
ginkgo.It("Selectively Orphan deletion of the manifestwork", func() {
|
|
work.Spec.DeleteOption = &workapiv1.DeleteOption{
|
|
PropagationPolicy: workapiv1.DeletePropagationPolicyTypeSelectivelyOrphan,
|
|
SelectivelyOrphan: &workapiv1.SelectivelyOrphan{
|
|
OrphaningRules: []workapiv1.OrphaningRule{
|
|
{
|
|
Group: "",
|
|
Resource: "configmaps",
|
|
Namespace: clusterName,
|
|
Name: cm1,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
work, err = hubWorkClient.WorkV1().ManifestWorks(clusterName).Create(context.Background(), work, metav1.CreateOptions{})
|
|
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
|
|
|
util.AssertWorkCondition(work.Namespace, work.Name, hubWorkClient, workapiv1.WorkApplied, metav1.ConditionTrue,
|
|
[]metav1.ConditionStatus{metav1.ConditionTrue, metav1.ConditionTrue}, eventuallyTimeout, eventuallyInterval)
|
|
util.AssertWorkCondition(work.Namespace, work.Name, hubWorkClient, workapiv1.WorkAvailable, metav1.ConditionTrue,
|
|
[]metav1.ConditionStatus{metav1.ConditionTrue, metav1.ConditionTrue}, eventuallyTimeout, eventuallyInterval)
|
|
|
|
// Ensure configmap exists
|
|
util.AssertExistenceOfConfigMaps(manifests, spokeKubeClient, eventuallyTimeout, eventuallyInterval)
|
|
|
|
// Ensure ownership of configmap is updated
|
|
gomega.Eventually(func() error {
|
|
cm, err := spokeKubeClient.CoreV1().ConfigMaps(clusterName).Get(context.Background(), cm1, metav1.GetOptions{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(cm.OwnerReferences) != 0 {
|
|
return fmt.Errorf("owner reference are not correctly updated, current ownerrefs are %v", cm.OwnerReferences)
|
|
}
|
|
|
|
return nil
|
|
}, eventuallyTimeout, eventuallyInterval).ShouldNot(gomega.HaveOccurred())
|
|
|
|
// Delete the work
|
|
err = hubWorkClient.WorkV1().ManifestWorks(clusterName).Delete(context.Background(), work.Name, metav1.DeleteOptions{})
|
|
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
|
|
|
// Wait for deletion of manifest work
|
|
gomega.Eventually(func() bool {
|
|
_, err := hubWorkClient.WorkV1().ManifestWorks(clusterName).Get(context.Background(), work.Name, metav1.GetOptions{})
|
|
return errors.IsNotFound(err)
|
|
}, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue())
|
|
|
|
// One of the resource should be deleted.
|
|
_, err = spokeKubeClient.CoreV1().ConfigMaps(clusterName).Get(context.Background(), cm2, metav1.GetOptions{})
|
|
gomega.Expect(errors.IsNotFound(err)).To(gomega.BeTrue())
|
|
|
|
// One of the resource should be kept
|
|
_, err = spokeKubeClient.CoreV1().ConfigMaps(clusterName).Get(context.Background(), cm1, metav1.GetOptions{})
|
|
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
|
})
|
|
|
|
ginkgo.It("Keep the resource when remove it from manifests with orphan deletion option", func() {
|
|
work.Spec.DeleteOption = &workapiv1.DeleteOption{
|
|
PropagationPolicy: workapiv1.DeletePropagationPolicyTypeSelectivelyOrphan,
|
|
SelectivelyOrphan: &workapiv1.SelectivelyOrphan{
|
|
OrphaningRules: []workapiv1.OrphaningRule{
|
|
{
|
|
Group: "",
|
|
Resource: "configmaps",
|
|
Namespace: clusterName,
|
|
Name: cm1,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
work, err = hubWorkClient.WorkV1().ManifestWorks(clusterName).Create(context.Background(), work, metav1.CreateOptions{})
|
|
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
|
|
|
util.AssertWorkCondition(work.Namespace, work.Name, hubWorkClient, workapiv1.WorkApplied, metav1.ConditionTrue,
|
|
[]metav1.ConditionStatus{metav1.ConditionTrue, metav1.ConditionTrue}, eventuallyTimeout, eventuallyInterval)
|
|
util.AssertWorkCondition(work.Namespace, work.Name, hubWorkClient, workapiv1.WorkAvailable, metav1.ConditionTrue,
|
|
[]metav1.ConditionStatus{metav1.ConditionTrue, metav1.ConditionTrue}, eventuallyTimeout, eventuallyInterval)
|
|
|
|
// Ensure configmap exists
|
|
util.AssertExistenceOfConfigMaps(manifests, spokeKubeClient, eventuallyTimeout, eventuallyInterval)
|
|
|
|
// Ensure ownership of configmap is updated
|
|
gomega.Eventually(func() error {
|
|
cm, err := spokeKubeClient.CoreV1().ConfigMaps(clusterName).Get(context.Background(), cm1, metav1.GetOptions{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(cm.OwnerReferences) != 0 {
|
|
return fmt.Errorf("owner reference are not correctly updated, current ownerrefs are %v", cm.OwnerReferences)
|
|
}
|
|
|
|
return nil
|
|
}, eventuallyTimeout, eventuallyInterval).ShouldNot(gomega.HaveOccurred())
|
|
|
|
// Remove the resource from the manifests
|
|
gomega.Eventually(func() error {
|
|
updatedWork, err := hubWorkClient.WorkV1().ManifestWorks(clusterName).Get(context.Background(), work.Name, metav1.GetOptions{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
newWork := updatedWork.DeepCopy()
|
|
newWork.Spec.Workload.Manifests = []workapiv1.Manifest{
|
|
util.ToManifest(util.NewConfigmap(clusterName, cm2, map[string]string{"c": "d"}, []string{})),
|
|
}
|
|
|
|
pathBytes, err := util.NewWorkPatch(updatedWork, newWork)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = hubWorkClient.WorkV1().ManifestWorks(clusterName).Patch(
|
|
context.Background(), updatedWork.Name, types.MergePatchType, pathBytes, metav1.PatchOptions{})
|
|
return err
|
|
}, eventuallyTimeout, eventuallyInterval).ShouldNot(gomega.HaveOccurred())
|
|
|
|
util.AssertWorkCondition(work.Namespace, work.Name, hubWorkClient, workapiv1.WorkApplied, metav1.ConditionTrue,
|
|
[]metav1.ConditionStatus{metav1.ConditionTrue}, eventuallyTimeout, eventuallyInterval)
|
|
util.AssertWorkCondition(work.Namespace, work.Name, hubWorkClient, workapiv1.WorkAvailable, metav1.ConditionTrue,
|
|
[]metav1.ConditionStatus{metav1.ConditionTrue}, eventuallyTimeout, eventuallyInterval)
|
|
|
|
// Wait for the resource to be observed
|
|
gomega.Eventually(func() error {
|
|
_, err := spokeKubeClient.CoreV1().ConfigMaps(clusterName).Get(context.Background(), cm1, metav1.GetOptions{})
|
|
return err
|
|
}, eventuallyTimeout, eventuallyInterval).ShouldNot(gomega.HaveOccurred())
|
|
})
|
|
|
|
ginkgo.It("Clean the resource when orphan deletion option is removed", func() {
|
|
work.Spec.DeleteOption = &workapiv1.DeleteOption{
|
|
PropagationPolicy: workapiv1.DeletePropagationPolicyTypeSelectivelyOrphan,
|
|
SelectivelyOrphan: &workapiv1.SelectivelyOrphan{
|
|
OrphaningRules: []workapiv1.OrphaningRule{
|
|
{
|
|
Group: "",
|
|
Resource: "configmaps",
|
|
Namespace: clusterName,
|
|
Name: cm1,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
work, err = hubWorkClient.WorkV1().ManifestWorks(clusterName).Create(context.Background(), work, metav1.CreateOptions{})
|
|
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
|
|
|
util.AssertWorkCondition(work.Namespace, work.Name, hubWorkClient, workapiv1.WorkApplied, metav1.ConditionTrue,
|
|
[]metav1.ConditionStatus{metav1.ConditionTrue, metav1.ConditionTrue}, eventuallyTimeout, eventuallyInterval)
|
|
util.AssertWorkCondition(work.Namespace, work.Name, hubWorkClient, workapiv1.WorkAvailable, metav1.ConditionTrue,
|
|
[]metav1.ConditionStatus{metav1.ConditionTrue, metav1.ConditionTrue}, eventuallyTimeout, eventuallyInterval)
|
|
|
|
// Ensure configmap exists
|
|
util.AssertExistenceOfConfigMaps(manifests, spokeKubeClient, eventuallyTimeout, eventuallyInterval)
|
|
|
|
// Ensure ownership of configmap is updated
|
|
gomega.Eventually(func() error {
|
|
cm, err := spokeKubeClient.CoreV1().ConfigMaps(clusterName).Get(context.Background(), cm1, metav1.GetOptions{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(cm.OwnerReferences) != 0 {
|
|
return fmt.Errorf("owner reference are not correctly updated, current ownerrefs are %v", cm.OwnerReferences)
|
|
}
|
|
|
|
return nil
|
|
}, eventuallyTimeout, eventuallyInterval).ShouldNot(gomega.HaveOccurred())
|
|
|
|
// Remove the delete option
|
|
gomega.Eventually(func() error {
|
|
updatedWork, err := hubWorkClient.WorkV1().ManifestWorks(clusterName).Get(context.Background(), work.Name, metav1.GetOptions{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
newWork := updatedWork.DeepCopy()
|
|
newWork.Spec.DeleteOption = nil
|
|
|
|
pathBytes, err := util.NewWorkPatch(updatedWork, newWork)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = hubWorkClient.WorkV1().ManifestWorks(clusterName).Patch(
|
|
context.Background(), updatedWork.Name, types.MergePatchType, pathBytes, metav1.PatchOptions{})
|
|
return err
|
|
}, eventuallyTimeout, eventuallyInterval).ShouldNot(gomega.HaveOccurred())
|
|
|
|
// Ensure ownership of configmap is updated
|
|
gomega.Eventually(func() error {
|
|
cm, err := spokeKubeClient.CoreV1().ConfigMaps(clusterName).Get(context.Background(), cm1, metav1.GetOptions{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(cm.OwnerReferences) != 1 {
|
|
return fmt.Errorf("owner reference are not correctly updated, current ownerrefs are %v", cm.OwnerReferences)
|
|
}
|
|
|
|
return nil
|
|
}, eventuallyTimeout, eventuallyInterval).ShouldNot(gomega.HaveOccurred())
|
|
|
|
// Delete the work
|
|
err = hubWorkClient.WorkV1().ManifestWorks(clusterName).Delete(context.Background(), work.Name, metav1.DeleteOptions{})
|
|
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
|
|
|
// Wait for deletion of manifest work
|
|
gomega.Eventually(func() bool {
|
|
_, err := hubWorkClient.WorkV1().ManifestWorks(clusterName).Get(context.Background(), work.Name, metav1.GetOptions{})
|
|
return errors.IsNotFound(err)
|
|
}, eventuallyTimeout, eventuallyInterval).Should(gomega.BeTrue())
|
|
|
|
// All the resources should be deleted.
|
|
_, err = spokeKubeClient.CoreV1().ConfigMaps(clusterName).Get(context.Background(), cm2, metav1.GetOptions{})
|
|
gomega.Expect(errors.IsNotFound(err)).To(gomega.BeTrue())
|
|
_, err = spokeKubeClient.CoreV1().ConfigMaps(clusterName).Get(context.Background(), cm1, metav1.GetOptions{})
|
|
gomega.Expect(errors.IsNotFound(err)).To(gomega.BeTrue())
|
|
})
|
|
})
|
|
})
|