mirror of
https://github.com/open-cluster-management-io/ocm.git
synced 2026-08-20 12:46:59 +00:00
* 🐛 fix flaky e2e cleanup and addon conversion test Pre-delete ManagedClusterAddOns and wait for ManifestWorks before ManagedCluster deletion in CleanKlusterletRelatedResources. Merge CMA status update and v1beta1 conversion verify into one Eventually loop to avoid race with cmaInstallProgressionController. Fixes #1402 Signed-off-by: bot69dude <nrithvik19@gmail.com> * Wait for ManagedClusterAddOn deletion in cleanup helper DeleteAllManagedClusterAddOnsInCluster now waits until all addons are removed before proceeding, so ManifestWork drain is not racing with still-active addon controllers. Addresses CodeRabbit review on #1573 Signed-off-by: bot69dude <nrithvik19@gmail.com> * Address review: use single MCA API version and drop nested RetryOnConflict Eventually already retries; listing both converted API versions is redundant. Signed-off-by: bot69dude <nrithvik19@gmail.com> --------- Signed-off-by: bot69dude <nrithvik19@gmail.com>
209 lines
7.4 KiB
Go
209 lines
7.4 KiB
Go
package framework
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
. "github.com/onsi/gomega"
|
|
coordv1 "k8s.io/api/coordination/v1"
|
|
corev1 "k8s.io/api/core/v1"
|
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
|
"k8s.io/apimachinery/pkg/api/meta"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/client-go/util/retry"
|
|
"k8s.io/klog/v2"
|
|
|
|
addonv1alpha1 "open-cluster-management.io/api/addon/v1alpha1"
|
|
addonv1beta1 "open-cluster-management.io/api/addon/v1beta1"
|
|
)
|
|
|
|
// CreateManagedClusterAddOnV1Alpha1 creates a ManagedClusterAddOn using v1alpha1 API
|
|
func (hub *Hub) CreateManagedClusterAddOnV1Alpha1(managedClusterNamespace, addOnName, installNamespace string) error {
|
|
_, err := hub.AddonClient.AddonV1alpha1().ManagedClusterAddOns(managedClusterNamespace).Create(
|
|
context.TODO(),
|
|
&addonv1alpha1.ManagedClusterAddOn{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Namespace: managedClusterNamespace,
|
|
Name: addOnName,
|
|
},
|
|
Spec: addonv1alpha1.ManagedClusterAddOnSpec{},
|
|
},
|
|
metav1.CreateOptions{},
|
|
)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return retry.RetryOnConflict(retry.DefaultBackoff, func() error {
|
|
addOn, err := hub.AddonClient.AddonV1alpha1().ManagedClusterAddOns(managedClusterNamespace).Get(
|
|
context.TODO(), addOnName, metav1.GetOptions{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if addOn.Status.Namespace == installNamespace {
|
|
return nil
|
|
}
|
|
addOn.Status.Namespace = installNamespace
|
|
_, err = hub.AddonClient.AddonV1alpha1().ManagedClusterAddOns(managedClusterNamespace).UpdateStatus(
|
|
context.TODO(), addOn, metav1.UpdateOptions{})
|
|
return err
|
|
})
|
|
}
|
|
|
|
func (hub *Hub) CreateManagedClusterAddOnLease(addOnInstallNamespace, addOnName string) error {
|
|
if _, err := hub.KubeClient.CoreV1().Namespaces().Create(
|
|
context.TODO(),
|
|
&corev1.Namespace{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: addOnInstallNamespace,
|
|
},
|
|
},
|
|
metav1.CreateOptions{},
|
|
); err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err := hub.KubeClient.CoordinationV1().Leases(addOnInstallNamespace).Create(
|
|
context.TODO(),
|
|
&coordv1.Lease{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: addOnName,
|
|
Namespace: addOnInstallNamespace,
|
|
},
|
|
Spec: coordv1.LeaseSpec{
|
|
RenewTime: &metav1.MicroTime{Time: time.Now()},
|
|
},
|
|
},
|
|
metav1.CreateOptions{},
|
|
)
|
|
return err
|
|
}
|
|
|
|
// CheckManagedClusterAddOnStatusV1Alpha1 checks the status of a ManagedClusterAddOn using v1alpha1 API
|
|
func (hub *Hub) CheckManagedClusterAddOnStatusV1Alpha1(managedClusterNamespace, addOnName string) error {
|
|
addOn, err := hub.AddonClient.AddonV1alpha1().ManagedClusterAddOns(managedClusterNamespace).Get(context.TODO(), addOnName, metav1.GetOptions{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if addOn.Status.Conditions == nil {
|
|
return fmt.Errorf("there is no conditions in addon %v/%v", managedClusterNamespace, addOnName)
|
|
}
|
|
|
|
if !meta.IsStatusConditionTrue(addOn.Status.Conditions, "Available") {
|
|
return fmt.Errorf("the addon %v/%v available condition is not true, %v",
|
|
managedClusterNamespace, addOnName, addOn.Status.Conditions)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// CheckManagedClusterAddOnStatusV1Beta1 checks the status of a ManagedClusterAddOn using v1beta1 API
|
|
func (hub *Hub) CheckManagedClusterAddOnStatusV1Beta1(managedClusterNamespace, addOnName string) error {
|
|
addOn, err := hub.AddonClient.AddonV1beta1().ManagedClusterAddOns(managedClusterNamespace).Get(context.TODO(), addOnName, metav1.GetOptions{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if addOn.Status.Conditions == nil {
|
|
return fmt.Errorf("there is no conditions in addon %v/%v", managedClusterNamespace, addOnName)
|
|
}
|
|
|
|
if !meta.IsStatusConditionTrue(addOn.Status.Conditions, "Available") {
|
|
return fmt.Errorf("the addon %v/%v available condition is not true, %v",
|
|
managedClusterNamespace, addOnName, addOn.Status.Conditions)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// CreateManagedClusterAddOnV1Beta1 creates a ManagedClusterAddOn using v1beta1 API
|
|
func (hub *Hub) CreateManagedClusterAddOnV1Beta1(managedClusterNamespace, addOnName, installNamespace string) error {
|
|
_, err := hub.AddonClient.AddonV1beta1().ManagedClusterAddOns(managedClusterNamespace).Create(
|
|
context.TODO(),
|
|
&addonv1beta1.ManagedClusterAddOn{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Namespace: managedClusterNamespace,
|
|
Name: addOnName,
|
|
},
|
|
Spec: addonv1beta1.ManagedClusterAddOnSpec{},
|
|
},
|
|
metav1.CreateOptions{},
|
|
)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return retry.RetryOnConflict(retry.DefaultBackoff, func() error {
|
|
addOn, err := hub.AddonClient.AddonV1beta1().ManagedClusterAddOns(managedClusterNamespace).Get(
|
|
context.TODO(), addOnName, metav1.GetOptions{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if addOn.Status.Namespace == installNamespace {
|
|
return nil
|
|
}
|
|
addOn.Status.Namespace = installNamespace
|
|
_, err = hub.AddonClient.AddonV1beta1().ManagedClusterAddOns(managedClusterNamespace).UpdateStatus(
|
|
context.TODO(), addOn, metav1.UpdateOptions{})
|
|
return err
|
|
})
|
|
}
|
|
|
|
// GetManagedClusterAddOnV1Beta1 gets a ManagedClusterAddOn using v1beta1 API
|
|
func (hub *Hub) GetManagedClusterAddOnV1Beta1(managedClusterNamespace, addOnName string) (*addonv1beta1.ManagedClusterAddOn, error) {
|
|
return hub.AddonClient.AddonV1beta1().ManagedClusterAddOns(managedClusterNamespace).Get(
|
|
context.TODO(), addOnName, metav1.GetOptions{})
|
|
}
|
|
|
|
// UpdateManagedClusterAddOnV1Beta1 updates a ManagedClusterAddOn using v1beta1 API
|
|
func (hub *Hub) UpdateManagedClusterAddOnV1Beta1(addon *addonv1beta1.ManagedClusterAddOn) (*addonv1beta1.ManagedClusterAddOn, error) {
|
|
return hub.AddonClient.AddonV1beta1().ManagedClusterAddOns(addon.Namespace).Update(
|
|
context.TODO(), addon, metav1.UpdateOptions{})
|
|
}
|
|
|
|
// GetManagedClusterAddOnV1Alpha1 gets a ManagedClusterAddOn using v1alpha1 API
|
|
func (hub *Hub) GetManagedClusterAddOnV1Alpha1(managedClusterNamespace, addOnName string) (*addonv1alpha1.ManagedClusterAddOn, error) {
|
|
return hub.AddonClient.AddonV1alpha1().ManagedClusterAddOns(managedClusterNamespace).Get(
|
|
context.TODO(), addOnName, metav1.GetOptions{})
|
|
}
|
|
|
|
// UpdateManagedClusterAddOnV1Alpha1 updates a ManagedClusterAddOn using v1alpha1 API
|
|
func (hub *Hub) UpdateManagedClusterAddOnV1Alpha1(addon *addonv1alpha1.ManagedClusterAddOn) (*addonv1alpha1.ManagedClusterAddOn, error) {
|
|
return hub.AddonClient.AddonV1alpha1().ManagedClusterAddOns(addon.Namespace).Update(
|
|
context.TODO(), addon, metav1.UpdateOptions{})
|
|
}
|
|
|
|
// DeleteAllManagedClusterAddOnsInCluster deletes every ManagedClusterAddOn in the cluster namespace.
|
|
// A single API version is enough because both versions share the same storage.
|
|
func (hub *Hub) DeleteAllManagedClusterAddOnsInCluster(clusterName string) {
|
|
addons, err := hub.AddonClient.AddonV1beta1().ManagedClusterAddOns(clusterName).List(context.TODO(), metav1.ListOptions{})
|
|
if err != nil && !apierrors.IsNotFound(err) {
|
|
klog.Errorf("failed to list managed cluster addons in %s: %v", clusterName, err)
|
|
} else {
|
|
for _, addon := range addons.Items {
|
|
err := hub.AddonClient.AddonV1beta1().ManagedClusterAddOns(clusterName).Delete(
|
|
context.TODO(), addon.Name, metav1.DeleteOptions{})
|
|
if err != nil && !apierrors.IsNotFound(err) {
|
|
klog.Errorf("failed to delete managed cluster addon %s/%s: %v", clusterName, addon.Name, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
Eventually(func() error {
|
|
addons, err := hub.AddonClient.AddonV1beta1().ManagedClusterAddOns(clusterName).List(context.TODO(), metav1.ListOptions{})
|
|
if err != nil && !apierrors.IsNotFound(err) {
|
|
return err
|
|
}
|
|
if len(addons.Items) > 0 {
|
|
return fmt.Errorf("managed cluster addons still exist in %s", clusterName)
|
|
}
|
|
return nil
|
|
}).Should(Succeed())
|
|
}
|