mirror of
https://github.com/open-cluster-management-io/ocm.git
synced 2026-08-23 14:17:00 +00:00
* test: add v1beta1 e2e tests for addon lifecycle and install strategy Add v1beta1 e2e test coverage following the alpha/beta split pattern from integration tests. Rename framework helper functions to use explicit V1Alpha1/V1Beta1 suffixes for consistency. Framework changes (test/framework/managedclusteraddon.go): - Rename CreateManagedClusterAddOn to CreateManagedClusterAddOnV1Alpha1 - Rename CheckManagedClusterAddOnStatus to CheckManagedClusterAddOnStatusV1Alpha1 - Add CheckManagedClusterAddOnStatusV1Beta1 helper - Organize functions with Alpha version followed by Beta counterpart E2E test changes: - Rename addon_test.go to addon_alpha_test.go (v1alpha1 API) - Create new addon_test.go with v1beta1 API using V1Beta1 helpers - Rename addon_install_test.go to addon_install_alpha_test.go (v1alpha1 API) - Create new addon_install_test.go with v1beta1 API - Update addon_lease_test.go, addon_token_auth_test.go, addonmanagement_test.go to use V1Alpha1 helpers Test coverage (both alpha and v1beta1): - addon_test.go: Basic ManagedClusterAddOn lifecycle and availability - addon_install_test.go: ClusterManagementAddOn with placement-based install strategy, addon annotation syncing Naming pattern matches integration tests: *_alpha_test.go for v1alpha1, *_test.go (no suffix) for v1beta1. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> Signed-off-by: Tesshu Flower <tflower@redhat.com> * test: add v1beta1 e2e tests for addon lease health check Add v1beta1 e2e test coverage for addon lease-based health checking following the alpha/beta split pattern. Changes: - Rename addon_lease_test.go to addon_lease_alpha_test.go (v1alpha1 API) - Create new addon_lease_test.go with v1beta1 API using V1Beta1 helpers - Update all AddonClient.AddonV1alpha1() calls to AddonV1beta1() in beta test Both alpha and v1beta1 tests cover: - Addon status remains available while lease is updated - Addon status changes to unavailable when lease stops updating - Addon status changes to unknown when no lease exists - Addon status changes to unknown when managed cluster lease stops updating Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> Signed-off-by: Tesshu Flower <tflower@redhat.com> * test: migrate addon_token_auth test to alpha/beta versions - Rename addon_token_auth_test.go to addon_token_auth_alpha_test.go - Update alpha Describe to include (v1alpha1) - Create new addon_token_auth_test.go for v1beta1 - Update imports and client calls to use v1beta1 API Signed-off-by: Tesshu Flower <tflower@redhat.com> --------- Signed-off-by: Tesshu Flower <tflower@redhat.com> Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
252 lines
9.0 KiB
Go
252 lines
9.0 KiB
Go
package e2e
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
ginkgo "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/util/rand"
|
|
|
|
addonapiv1alpha1 "open-cluster-management.io/api/addon/v1alpha1"
|
|
clusterv1 "open-cluster-management.io/api/cluster/v1"
|
|
clusterv1alpha1 "open-cluster-management.io/api/cluster/v1alpha1"
|
|
clusterv1beta1 "open-cluster-management.io/api/cluster/v1beta1"
|
|
clusterv1beta2 "open-cluster-management.io/api/cluster/v1beta2"
|
|
)
|
|
|
|
var _ = ginkgo.Describe("Addon install with install strategy (v1alpha1)", ginkgo.Ordered, ginkgo.Label("addon-install"), func() {
|
|
var addOnName string
|
|
var clusterNames []string
|
|
|
|
ginkgo.BeforeAll(func() {
|
|
suffix := rand.String(6)
|
|
addOnName = fmt.Sprintf("addon-%s", suffix)
|
|
clusterNames = nil
|
|
|
|
ginkgo.By("create namespace open-cluster-management-global-set")
|
|
ns := &corev1.Namespace{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "open-cluster-management-global-set",
|
|
},
|
|
}
|
|
_, err := hub.KubeClient.CoreV1().Namespaces().Create(context.TODO(), ns, metav1.CreateOptions{})
|
|
if err != nil && !errors.IsAlreadyExists(err) {
|
|
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
|
}
|
|
|
|
ginkgo.By("create Placement global in open-cluster-management-global-set")
|
|
placement := &clusterv1beta1.Placement{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "global",
|
|
Namespace: "open-cluster-management-global-set",
|
|
},
|
|
Spec: clusterv1beta1.PlacementSpec{
|
|
ClusterSets: []string{"global"},
|
|
Tolerations: []clusterv1beta1.Toleration{
|
|
{
|
|
Key: "cluster.open-cluster-management.io/unreachable",
|
|
Operator: clusterv1beta1.TolerationOpEqual,
|
|
},
|
|
{
|
|
Key: "cluster.open-cluster-management.io/unavailable",
|
|
Operator: clusterv1beta1.TolerationOpEqual,
|
|
},
|
|
},
|
|
DecisionStrategy: clusterv1beta1.DecisionStrategy{
|
|
GroupStrategy: clusterv1beta1.GroupStrategy{},
|
|
},
|
|
PrioritizerPolicy: clusterv1beta1.PrioritizerPolicy{
|
|
Mode: clusterv1beta1.PrioritizerPolicyModeAdditive,
|
|
},
|
|
},
|
|
}
|
|
_, err = hub.ClusterClient.ClusterV1beta1().Placements("open-cluster-management-global-set").Create(
|
|
context.TODO(), placement, metav1.CreateOptions{})
|
|
if err != nil && !errors.IsAlreadyExists(err) {
|
|
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
|
}
|
|
|
|
ginkgo.By("create ManagedClusterSetBinding global in open-cluster-management-global-set")
|
|
binding := &clusterv1beta2.ManagedClusterSetBinding{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "global",
|
|
Namespace: "open-cluster-management-global-set",
|
|
},
|
|
Spec: clusterv1beta2.ManagedClusterSetBindingSpec{
|
|
ClusterSet: "global",
|
|
},
|
|
}
|
|
_, err = hub.ClusterClient.ClusterV1beta2().ManagedClusterSetBindings("open-cluster-management-global-set").Create(
|
|
context.TODO(), binding, metav1.CreateOptions{})
|
|
if err != nil && !errors.IsAlreadyExists(err) {
|
|
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
|
}
|
|
|
|
ginkgo.By(fmt.Sprintf("create ClusterManagementAddOn %s with install strategy", addOnName))
|
|
cma := &addonapiv1alpha1.ClusterManagementAddOn{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: addOnName,
|
|
},
|
|
Spec: addonapiv1alpha1.ClusterManagementAddOnSpec{
|
|
InstallStrategy: addonapiv1alpha1.InstallStrategy{
|
|
Type: addonapiv1alpha1.AddonInstallStrategyPlacements,
|
|
Placements: []addonapiv1alpha1.PlacementStrategy{
|
|
{
|
|
PlacementRef: addonapiv1alpha1.PlacementRef{
|
|
Name: "global",
|
|
Namespace: "open-cluster-management-global-set",
|
|
},
|
|
RolloutStrategy: clusterv1alpha1.RolloutStrategy{
|
|
Type: clusterv1alpha1.All,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
_, err = hub.AddonClient.AddonV1alpha1().ClusterManagementAddOns().Create(
|
|
context.TODO(), cma, metav1.CreateOptions{})
|
|
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
|
})
|
|
|
|
ginkgo.AfterAll(func() {
|
|
ginkgo.By(fmt.Sprintf("delete ClusterManagementAddOn %s", addOnName))
|
|
err := hub.AddonClient.AddonV1alpha1().ClusterManagementAddOns().Delete(
|
|
context.TODO(), addOnName, metav1.DeleteOptions{})
|
|
if err != nil && !errors.IsNotFound(err) {
|
|
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
|
}
|
|
|
|
for _, clusterName := range clusterNames {
|
|
ginkgo.By(fmt.Sprintf("delete ManagedCluster %s", clusterName))
|
|
err := hub.ClusterClient.ClusterV1().ManagedClusters().Delete(
|
|
context.TODO(), clusterName, metav1.DeleteOptions{})
|
|
if err != nil && !errors.IsNotFound(err) {
|
|
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
|
}
|
|
}
|
|
|
|
ginkgo.By("delete namespace open-cluster-management-global-set")
|
|
err = hub.KubeClient.CoreV1().Namespaces().Delete(
|
|
context.TODO(), "open-cluster-management-global-set", metav1.DeleteOptions{})
|
|
if err != nil && !errors.IsNotFound(err) {
|
|
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
|
}
|
|
})
|
|
|
|
ginkgo.It("Should create addon without addon annotations when managed cluster has no addon annotations", func() {
|
|
clusterName := fmt.Sprintf("e2e-addon-install-%s", rand.String(6))
|
|
clusterNames = append(clusterNames, clusterName)
|
|
|
|
ginkgo.By(fmt.Sprintf("create ManagedCluster %s with non-addon annotations", clusterName))
|
|
managedCluster := &clusterv1.ManagedCluster{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: clusterName,
|
|
Annotations: map[string]string{
|
|
"foo.example.com/bar": "value1",
|
|
"baz.example.com/qux": "value2",
|
|
},
|
|
},
|
|
Spec: clusterv1.ManagedClusterSpec{
|
|
HubAcceptsClient: true,
|
|
},
|
|
}
|
|
_, err := hub.ClusterClient.ClusterV1().ManagedClusters().Create(
|
|
context.TODO(), managedCluster, metav1.CreateOptions{})
|
|
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
|
|
|
ginkgo.By(fmt.Sprintf("check ManagedClusterAddOn %s is created in cluster namespace %s", addOnName, clusterName))
|
|
gomega.Eventually(func() error {
|
|
addon, err := hub.AddonClient.AddonV1alpha1().ManagedClusterAddOns(clusterName).Get(
|
|
context.TODO(), addOnName, metav1.GetOptions{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if len(addon.Annotations) != 0 {
|
|
return fmt.Errorf("expected no annotations on ManagedClusterAddOn, got %v", addon.Annotations)
|
|
}
|
|
return nil
|
|
}).Should(gomega.Succeed())
|
|
})
|
|
|
|
ginkgo.It("Should sync addon annotations from managed cluster to addon", func() {
|
|
clusterName := fmt.Sprintf("e2e-addon-install-%s", rand.String(6))
|
|
clusterNames = append(clusterNames, clusterName)
|
|
|
|
annotations := map[string]string{
|
|
"addon.open-cluster-management.io/hosting-cluster-name": "hosting-cluster",
|
|
"addon.open-cluster-management.io/test-annotation": "test-value",
|
|
}
|
|
|
|
ginkgo.By(fmt.Sprintf("create ManagedCluster %s with addon annotations", clusterName))
|
|
managedCluster := &clusterv1.ManagedCluster{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: clusterName,
|
|
Annotations: annotations,
|
|
},
|
|
Spec: clusterv1.ManagedClusterSpec{
|
|
HubAcceptsClient: true,
|
|
},
|
|
}
|
|
_, err := hub.ClusterClient.ClusterV1().ManagedClusters().Create(
|
|
context.TODO(), managedCluster, metav1.CreateOptions{})
|
|
gomega.Expect(err).ToNot(gomega.HaveOccurred())
|
|
|
|
ginkgo.By(fmt.Sprintf("check ManagedClusterAddOn %s is created with synced annotations", addOnName))
|
|
gomega.Eventually(func() error {
|
|
addon, err := hub.AddonClient.AddonV1alpha1().ManagedClusterAddOns(clusterName).Get(
|
|
context.TODO(), addOnName, metav1.GetOptions{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for key, expectedValue := range annotations {
|
|
actualValue, ok := addon.Annotations[key]
|
|
if !ok {
|
|
return fmt.Errorf("expected annotation %s not found on ManagedClusterAddOn", key)
|
|
}
|
|
if actualValue != expectedValue {
|
|
return fmt.Errorf("annotation %s: expected %q, got %q", key, expectedValue, actualValue)
|
|
}
|
|
}
|
|
return nil
|
|
}).Should(gomega.Succeed())
|
|
|
|
ginkgo.By(fmt.Sprintf("update annotation on ManagedCluster %s", clusterName))
|
|
gomega.Eventually(func() error {
|
|
cluster, err := hub.ClusterClient.ClusterV1().ManagedClusters().Get(
|
|
context.TODO(), clusterName, metav1.GetOptions{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
cluster.Annotations["addon.open-cluster-management.io/test-annotation"] = "updated-value"
|
|
_, err = hub.ClusterClient.ClusterV1().ManagedClusters().Update(
|
|
context.TODO(), cluster, metav1.UpdateOptions{})
|
|
return err
|
|
}).Should(gomega.Succeed())
|
|
|
|
ginkgo.By(fmt.Sprintf("check updated annotation is synced to ManagedClusterAddOn %s", addOnName))
|
|
gomega.Eventually(func() error {
|
|
addon, err := hub.AddonClient.AddonV1alpha1().ManagedClusterAddOns(clusterName).Get(
|
|
context.TODO(), addOnName, metav1.GetOptions{})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
actualValue, ok := addon.Annotations["addon.open-cluster-management.io/test-annotation"]
|
|
if !ok {
|
|
return fmt.Errorf("expected annotation addon.open-cluster-management.io/test-annotation not found on ManagedClusterAddOn")
|
|
}
|
|
if actualValue != "updated-value" {
|
|
return fmt.Errorf("annotation addon.open-cluster-management.io/test-annotation: expected %q, got %q", "updated-value", actualValue)
|
|
}
|
|
return nil
|
|
}).Should(gomega.Succeed())
|
|
})
|
|
})
|