From 8680e6061b64e111737491a53a527a96f6dd6991 Mon Sep 17 00:00:00 2001 From: jiajliu Date: Wed, 14 Jan 2026 16:24:33 +0800 Subject: [PATCH] migrate ocp-46922 from otp to cvo repo --- ...hift_payload_cluster-version-operator.json | 10 ++++ test/cvo/cvo.go | 52 ++++++++++++++++++ test/cvo/util.go | 54 +++++++++++++++++++ 3 files changed, 116 insertions(+) create mode 100644 test/cvo/util.go diff --git a/.openshift-tests-extension/openshift_payload_cluster-version-operator.json b/.openshift-tests-extension/openshift_payload_cluster-version-operator.json index d47f7297a..e49b764fd 100644 --- a/.openshift-tests-extension/openshift_payload_cluster-version-operator.json +++ b/.openshift-tests-extension/openshift_payload_cluster-version-operator.json @@ -18,5 +18,15 @@ "source": "openshift:payload:cluster-version-operator", "lifecycle": "blocking", "environmentSelector": {} + }, + { + "name": "[Jira:\"Cluster Version Operator\"] cluster-version-operator tests with cluster access should have correct runlevel and scc", + "labels": {}, + "resources": { + "isolation": {} + }, + "source": "openshift:payload:cluster-version-operator", + "lifecycle": "blocking", + "environmentSelector": {} } ] \ No newline at end of file diff --git a/test/cvo/cvo.go b/test/cvo/cvo.go index 71da3f26e..c278a6f08 100644 --- a/test/cvo/cvo.go +++ b/test/cvo/cvo.go @@ -1,6 +1,12 @@ package cvo import ( + "context" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -25,3 +31,49 @@ var _ = Describe(`[Jira:"Cluster Version Operator"] cluster-version-operator-tes Expect(output).To(ContainSubstring("Client Version:")) }) }) + +// CVO tests which need access the live cluster will be placed here +var _ = Describe(`[Jira:"Cluster Version Operator"] cluster-version-operator tests with cluster access`, func() { + const cvoNamespace = "openshift-cluster-version" + var ( + restCfg *rest.Config + kubeClient kubernetes.Interface + ) + + BeforeEach(func() { + var err error + // Respects KUBECONFIG env var + restCfg, err = GetRestConfig() + Expect(err).NotTo(HaveOccurred(), "Failed to load Kubernetes configuration. Please ensure KUBECONFIG environment variable is set.") + + kubeClient, err = GetKubeClient(restCfg) + Expect(err).NotTo(HaveOccurred(), "Failed to create Kubernetes client") + }) + + // Migrated from case NonHyperShiftHOST-Author:jiajliu-Low-46922-check runlevel and scc in cvo ns + // Refer to https://github.com/openshift/openshift-tests-private/blob/40374cf20946ff03c88712839a5626af2c88ab31/test/extended/ota/cvo/cvo.go#L1081 + It("should have correct runlevel and scc", func() { + ctx := context.Background() + SkipIfHypershift(ctx, restCfg) + + By("Checking that openshift.io/run-level label exists and is empty") + ns, err := kubeClient.CoreV1().Namespaces().Get(ctx, cvoNamespace, metav1.GetOptions{}) + Expect(err).NotTo(HaveOccurred(), "Failed to get namespace %s", cvoNamespace) + + runLevel, exists := ns.ObjectMeta.Labels["openshift.io/run-level"] + Expect(exists).To(BeTrue(), "Expected 'openshift.io/run-level' label to exist") + Expect(runLevel).To(BeEmpty(), "Expected 'openshift.io/run-level' label value to be empty, but got %s", runLevel) + + By("Checking that CVO pod's SCC annotation is hostaccess") + podList, err := kubeClient.CoreV1().Pods(cvoNamespace).List(ctx, metav1.ListOptions{ + LabelSelector: "k8s-app=cluster-version-operator", + FieldSelector: "status.phase=Running", + }) + Expect(err).NotTo(HaveOccurred(), "Failed to list running CVO pods") + Expect(podList.Items).To(HaveLen(1), "Expected exactly one running CVO pod, but found: %d", len(podList.Items)) + + cvoPod := podList.Items[0] + sccAnnotation := cvoPod.ObjectMeta.Annotations["openshift.io/scc"] + Expect(sccAnnotation).To(Equal("hostaccess"), "Expected SCC for pod %s to be 'hostaccess', but got %s", cvoPod.Name, sccAnnotation) + }) +}) diff --git a/test/cvo/util.go b/test/cvo/util.go new file mode 100644 index 000000000..0c8c5c02f --- /dev/null +++ b/test/cvo/util.go @@ -0,0 +1,54 @@ +package cvo + +import ( + "context" + + . "github.com/onsi/ginkgo/v2" + configv1 "github.com/openshift/api/config/v1" + clientconfigv1 "github.com/openshift/client-go/config/clientset/versioned" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" +) + +// IsHypershift checks if running on a HyperShift hosted cluster +// Refer to https://github.com/openshift/origin/blob/31704414237b8bd5c66ad247c105c94abc9470b1/test/extended/util/framework.go#L2301 +func IsHypershift(ctx context.Context, restConfig *rest.Config) (bool, error) { + configClient, err := GetConfigClient(restConfig) + if err != nil { + return false, err + } + + infrastructure, err := configClient.ConfigV1().Infrastructures().Get(ctx, "cluster", metav1.GetOptions{}) + if err != nil { + return false, nil + } + + return infrastructure.Status.ControlPlaneTopology == configv1.ExternalTopologyMode, nil +} + +// SkipIfHypershift skips the test if running on a HyperShift hosted cluster +func SkipIfHypershift(ctx context.Context, restConfig *rest.Config) { + isHypershift, _ := IsHypershift(ctx, restConfig) + if isHypershift { + Skip("Skipping test: running on HyperShift hosted cluster!") + } +} + +// GetRestConfig loads the Kubernetes REST configuration from KUBECONFIG environment variable. +func GetRestConfig() (*rest.Config, error) { + loadingRules := clientcmd.NewDefaultClientConfigLoadingRules() + cfg := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, &clientcmd.ConfigOverrides{}) + return cfg.ClientConfig() +} + +// GetKubeClient creates a Kubernetes client from the given REST config. +func GetKubeClient(restConfig *rest.Config) (kubernetes.Interface, error) { + return kubernetes.NewForConfig(restConfig) +} + +// GetConfigClient creates an OpenShift config client from the given REST config. +func GetConfigClient(restConfig *rest.Config) (clientconfigv1.Interface, error) { + return clientconfigv1.NewForConfig(restConfig) +}