Skip to content

Commit 4328173

Browse files
UPSTREAM: <carry>: [OTE] Refac: refac helper and olmv1 test to create namespace instead to use pre-existent
1 parent 778bd57 commit 4328173

File tree

2 files changed

+179
-54
lines changed

2 files changed

+179
-54
lines changed

openshift/tests-extension/pkg/helpers/cluster_extension.go

Lines changed: 144 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,87 +2,195 @@ package helpers
22

33
import (
44
"context"
5+
"fmt"
6+
"time"
57

8+
//nolint:staticcheck // ST1001: dot-imports for readability
9+
. "github.com/onsi/ginkgo/v2"
610
//nolint:staticcheck // ST1001: dot-imports for readability
711
. "github.com/onsi/gomega"
812

913
corev1 "k8s.io/api/core/v1"
1014
rbacv1 "k8s.io/api/rbac/v1"
15+
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
16+
"k8s.io/apimachinery/pkg/api/errors"
17+
"k8s.io/apimachinery/pkg/api/meta"
1118
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1219
"k8s.io/apimachinery/pkg/util/rand"
20+
"sigs.k8s.io/controller-runtime/pkg/client"
1321

14-
ocv1 "github.com/operator-framework/operator-controller/api/v1"
22+
olmv1 "github.com/operator-framework/operator-controller/api/v1"
1523

1624
"github/operator-framework-operator-controller/openshift/tests-extension/pkg/env"
1725
)
1826

19-
const openshiftOperatorsNs = "openshift-operators"
20-
2127
// CreateClusterExtension creates a ServiceAccount, ClusterRoleBinding, and ClusterExtension using typed APIs.
2228
// It returns the unique suffix and a cleanup function.
23-
func CreateClusterExtension(packageName, version string) (string, func()) {
29+
func CreateClusterExtension(packageName, version, namespace string) (string, func()) {
2430
ctx := context.TODO()
2531
k8sClient := env.Get().K8sClient
26-
unique := rand.String(8)
32+
unique := rand.String(4)
2733

2834
saName := "install-test-sa-" + unique
2935
crbName := "install-test-crb-" + unique
3036
ceName := "install-test-ce-" + unique
3137

3238
// 1. Create ServiceAccount
33-
sa := &corev1.ServiceAccount{
34-
ObjectMeta: metav1.ObjectMeta{
35-
Name: saName,
36-
Namespace: openshiftOperatorsNs,
37-
},
38-
}
39-
Expect(k8sClient.Create(ctx, sa)).To(Succeed(), "failed to create ServiceAccount")
39+
sa := NewServiceAccount(saName, namespace)
40+
Expect(k8sClient.Create(ctx, sa)).To(Succeed(),
41+
"failed to create ServiceAccount")
42+
By("ensuring ServiceAccount is available before proceeding")
43+
ExpectServiceAccountExists(ctx, saName, namespace)
4044

4145
// 2. Create ClusterRoleBinding
42-
crb := &rbacv1.ClusterRoleBinding{
46+
crb := NewClusterRoleBinding(crbName, "cluster-admin", saName, namespace)
47+
Expect(k8sClient.Create(ctx, crb)).To(Succeed(), "failed to create ClusterRoleBinding")
48+
By("ensuring ClusterRoleBinding is available before proceeding")
49+
ExpectClusterRoleBindingExists(ctx, crbName)
50+
51+
// 3. Create ClusterExtension
52+
ce := NewClusterExtensionObject(packageName, version, ceName, saName, namespace)
53+
Expect(k8sClient.Create(ctx, ce)).To(Succeed(), "failed to create ClusterExtension")
54+
55+
// Cleanup closure
56+
return ceName, func() {
57+
_ = k8sClient.Delete(ctx, ce)
58+
_ = k8sClient.Delete(ctx, crb)
59+
_ = k8sClient.Delete(ctx, sa)
60+
}
61+
}
62+
63+
// NewServiceAccount creates a new ServiceAccount object in the openshift-operators namespace.
64+
func NewServiceAccount(name, namespace string) *corev1.ServiceAccount {
65+
return &corev1.ServiceAccount{
4366
ObjectMeta: metav1.ObjectMeta{
44-
Name: crbName,
67+
Name: name,
68+
Namespace: namespace,
4569
},
70+
}
71+
}
72+
73+
// NewClusterRoleBinding creates a new ClusterRoleBinding object that binds a ClusterRole to a ServiceAccount.
74+
func NewClusterRoleBinding(name, roleName, saName, namespace string) *rbacv1.ClusterRoleBinding {
75+
return &rbacv1.ClusterRoleBinding{
76+
ObjectMeta: metav1.ObjectMeta{Name: name},
4677
RoleRef: rbacv1.RoleRef{
4778
APIGroup: "rbac.authorization.k8s.io",
4879
Kind: "ClusterRole",
49-
Name: "cluster-admin",
80+
Name: roleName,
5081
},
5182
Subjects: []rbacv1.Subject{{
5283
Kind: "ServiceAccount",
5384
Name: saName,
54-
Namespace: openshiftOperatorsNs,
85+
Namespace: namespace,
5586
}},
5687
}
57-
Expect(k8sClient.Create(ctx, crb)).To(Succeed(), "failed to create ClusterRoleBinding")
88+
}
5889

59-
// 3. Create ClusterExtension
60-
ce := &ocv1.ClusterExtension{
61-
ObjectMeta: metav1.ObjectMeta{
62-
Name: ceName,
63-
},
64-
Spec: ocv1.ClusterExtensionSpec{
65-
Namespace: openshiftOperatorsNs,
66-
ServiceAccount: ocv1.ServiceAccountReference{
90+
// NewClusterExtensionObject creates a new ClusterExtension object with the specified package, version, name, and ServiceAccount.
91+
func NewClusterExtensionObject(pkg, version, ceName, saName, namespace string) *olmv1.ClusterExtension {
92+
return &olmv1.ClusterExtension{
93+
ObjectMeta: metav1.ObjectMeta{Name: ceName},
94+
Spec: olmv1.ClusterExtensionSpec{
95+
Namespace: namespace,
96+
ServiceAccount: olmv1.ServiceAccountReference{
6797
Name: saName,
6898
},
69-
Source: ocv1.SourceConfig{
70-
SourceType: ocv1.SourceTypeCatalog,
71-
Catalog: &ocv1.CatalogFilter{
72-
PackageName: packageName,
99+
Source: olmv1.SourceConfig{
100+
SourceType: olmv1.SourceTypeCatalog,
101+
Catalog: &olmv1.CatalogFilter{
102+
PackageName: pkg,
73103
Version: version,
74104
Selector: &metav1.LabelSelector{},
75-
UpgradeConstraintPolicy: ocv1.UpgradeConstraintPolicyCatalogProvided,
105+
UpgradeConstraintPolicy: olmv1.UpgradeConstraintPolicyCatalogProvided,
76106
},
77107
},
78108
},
79109
}
80-
Expect(k8sClient.Create(ctx, ce)).To(Succeed(), "failed to create ClusterExtension")
110+
}
81111

82-
// Cleanup closure
83-
return ceName, func() {
84-
_ = k8sClient.Delete(ctx, ce)
85-
_ = k8sClient.Delete(ctx, crb)
86-
_ = k8sClient.Delete(ctx, sa)
112+
// ExpectClusterExtensionToBeInstalled checks that the ClusterExtension has both Progressing=True and Installed=True.
113+
func ExpectClusterExtensionToBeInstalled(ctx context.Context, name string) {
114+
k8sClient := env.Get().K8sClient
115+
Eventually(func(g Gomega) {
116+
var ext olmv1.ClusterExtension
117+
err := k8sClient.Get(ctx, client.ObjectKey{Name: name}, &ext)
118+
g.Expect(err).ToNot(HaveOccurred(), fmt.Sprintf("failed to get ClusterExtension %q", name))
119+
120+
conditions := ext.Status.Conditions
121+
g.Expect(conditions).NotTo(BeEmpty(), fmt.Sprintf("ClusterExtension %q has empty status.conditions", name))
122+
123+
progressing := meta.FindStatusCondition(conditions, string(olmv1.TypeProgressing))
124+
g.Expect(progressing).ToNot(BeNil(), "Progressing condition not found")
125+
g.Expect(progressing.Status).To(Equal(metav1.ConditionTrue), "Progressing should be True")
126+
127+
installed := meta.FindStatusCondition(conditions, string(olmv1.TypeInstalled))
128+
g.Expect(installed).ToNot(BeNil(), "Installed condition not found")
129+
g.Expect(installed.Status).To(Equal(metav1.ConditionTrue), "Installed should be True")
130+
}).WithTimeout(5 * time.Minute).WithPolling(1 * time.Second).Should(Succeed())
131+
}
132+
133+
// EnsureCleanupClusterExtension attempts to delete any ClusterExtension and a specified CRD
134+
// that might be left over from previous test runs. This helps prevent conflicts in serial tests.
135+
func EnsureCleanupClusterExtension(ctx context.Context, packageName, crdName string) {
136+
k8sClient := env.Get().K8sClient
137+
138+
// 1. Clean up any ClusterExtensions related to this test/package
139+
ceList := &olmv1.ClusterExtensionList{}
140+
// List all ClusterExtensions, then filter in code by packageName
141+
if err := k8sClient.List(ctx, ceList); err == nil {
142+
for _, ce := range ceList.Items {
143+
if ce.Spec.Source.Catalog.PackageName == packageName {
144+
By(fmt.Sprintf("deleting ClusterExtension %s (package: %s)", ce.Name, packageName))
145+
propagationPolicy := metav1.DeletePropagationForeground
146+
deleteOpts := &client.DeleteOptions{PropagationPolicy: &propagationPolicy}
147+
if err := k8sClient.Delete(ctx, &ce, deleteOpts); err != nil && !errors.IsNotFound(err) {
148+
fmt.Fprintf(GinkgoWriter, "Warning: Failed to delete lingering ClusterExtension %s: %v\n", ce.Name, err)
149+
}
150+
Eventually(func() bool {
151+
err := k8sClient.Get(ctx, client.ObjectKey{Name: ce.Name}, &olmv1.ClusterExtension{})
152+
return errors.IsNotFound(err)
153+
}).WithTimeout(1*time.Minute).WithPolling(2*time.Second).Should(BeTrue(), "Lingering ClusterExtension %s failed to delete", ce.Name)
154+
}
155+
}
156+
} else if !errors.IsNotFound(err) {
157+
fmt.Fprintf(GinkgoWriter, "Warning: Failed to list ClusterExtensions during cleanup: %v\n", err)
158+
}
159+
160+
// 2. Clean up specific operator-created CRD if it exists
161+
if crdName != "" {
162+
crd := &apiextensionsv1.CustomResourceDefinition{}
163+
if err := k8sClient.Get(ctx, client.ObjectKey{Name: crdName}, crd); err == nil {
164+
By(fmt.Sprintf("deleting CRD %s", crdName))
165+
if err := k8sClient.Delete(ctx, crd); err != nil && !errors.IsNotFound(err) {
166+
fmt.Fprintf(GinkgoWriter, "Warning: Failed to delete lingering CRD %s: %v\n", crdName, err)
167+
}
168+
Eventually(func() bool {
169+
err := k8sClient.Get(ctx, client.ObjectKey{Name: crdName}, &apiextensionsv1.CustomResourceDefinition{})
170+
return errors.IsNotFound(err)
171+
}).WithTimeout(1*time.Minute).WithPolling(2*time.Second).Should(BeTrue(), "Lingering CRD %s failed to delete", crdName)
172+
} else if !errors.IsNotFound(err) {
173+
fmt.Fprintf(GinkgoWriter, "Warning: Failed to get CRD %s during cleanup: %v\n", crdName, err)
174+
}
87175
}
88176
}
177+
178+
// ExpectServiceAccountExists waits for a ServiceAccount to be available and visible to the client.
179+
func ExpectServiceAccountExists(ctx context.Context, name, namespace string) {
180+
k8sClient := env.Get().K8sClient
181+
sa := &corev1.ServiceAccount{}
182+
Eventually(func(g Gomega) {
183+
err := k8sClient.Get(ctx, client.ObjectKey{Name: name, Namespace: namespace}, sa)
184+
g.Expect(err).ToNot(HaveOccurred(), fmt.Sprintf("failed to get ServiceAccount %q/%q: %v", namespace, name, err))
185+
}).WithTimeout(10*time.Second).WithPolling(1*time.Second).Should(Succeed(), "ServiceAccount %q/%q did not become visible within timeout", namespace, name)
186+
}
187+
188+
// ExpectClusterRoleBindingExists waits for a ClusterRoleBinding to be available and visible to the client.
189+
func ExpectClusterRoleBindingExists(ctx context.Context, name string) {
190+
k8sClient := env.Get().K8sClient
191+
crb := &rbacv1.ClusterRoleBinding{}
192+
Eventually(func(g Gomega) {
193+
err := k8sClient.Get(ctx, client.ObjectKey{Name: name}, crb)
194+
g.Expect(err).ToNot(HaveOccurred(), fmt.Sprintf("failed to get ClusterRoleBinding %q: %v", name, err))
195+
}).WithTimeout(10*time.Second).WithPolling(1*time.Second).Should(Succeed(), "ClusterRoleBinding %q did not become visible within timeout", name)
196+
}

openshift/tests-extension/test/olmv1.go

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@ import (
1111
. "github.com/onsi/gomega"
1212

1313
configv1 "github.com/openshift/api/config/v1"
14+
corev1 "k8s.io/api/core/v1"
1415
apiextclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
1516
"k8s.io/apimachinery/pkg/api/meta"
1617
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
18+
"k8s.io/apimachinery/pkg/util/rand"
1719
"sigs.k8s.io/controller-runtime/pkg/client"
1820

1921
olmv1 "github.com/operator-framework/operator-controller/api/v1"
@@ -71,37 +73,49 @@ var _ = Describe("[sig-olmv1][OCPFeatureGate:NewOLM] OLMv1 CRDs", func() {
7173
})
7274

7375
var _ = Describe("[sig-olmv1][OCPFeatureGate:NewOLM][Skipped:Disconnected] OLMv1 operator installation", func() {
76+
var (
77+
namespace string
78+
k8sClient client.Client
79+
)
7480
BeforeEach(func() {
7581
helpers.RequireOLMv1CapabilityOnOpenshift()
82+
k8sClient = env.Get().K8sClient
83+
namespace = "install-test-ns-" + rand.String(4)
84+
85+
By(fmt.Sprintf("creating namespace %s for single-namespace tests", namespace))
86+
ns := &corev1.Namespace{
87+
ObjectMeta: metav1.ObjectMeta{
88+
Name: namespace,
89+
},
90+
}
91+
Expect(k8sClient.Create(context.Background(), ns)).To(Succeed(), "failed to create test namespace")
92+
DeferCleanup(func() {
93+
_ = k8sClient.Delete(context.Background(), ns)
94+
})
7695
})
96+
7797
It("should install a cluster extension", func(ctx SpecContext) {
7898
if !env.Get().IsOpenShift {
7999
Skip("Requires OCP Catalogs: not OpenShift")
80100
}
101+
102+
By("ensuring no ClusterExtension and CRD for quay-operator")
103+
helpers.EnsureCleanupClusterExtension(context.Background(), "quay-operator", "quayregistries.quay.redhat.com")
104+
81105
By("applying the ClusterExtension resource")
82-
name, cleanup := helpers.CreateClusterExtension("quay-operator", "3.13.0")
106+
name, cleanup := helpers.CreateClusterExtension("quay-operator", "3.13.0", namespace)
83107
DeferCleanup(cleanup)
84108

85109
By("waiting for the quay-operator ClusterExtension to be installed")
86-
Eventually(func(g Gomega) {
87-
k8sClient := env.Get().K8sClient
88-
ce := &olmv1.ClusterExtension{}
89-
err := k8sClient.Get(ctx, client.ObjectKey{Name: name}, ce)
90-
g.Expect(err).ToNot(HaveOccurred())
91-
92-
progressing := meta.FindStatusCondition(ce.Status.Conditions, olmv1.TypeProgressing)
93-
g.Expect(progressing).ToNot(BeNil())
94-
g.Expect(progressing.Status).To(Equal(metav1.ConditionTrue))
95-
96-
installed := meta.FindStatusCondition(ce.Status.Conditions, olmv1.TypeInstalled)
97-
g.Expect(installed).ToNot(BeNil())
98-
g.Expect(installed.Status).To(Equal(metav1.ConditionTrue))
99-
}).WithTimeout(5 * time.Minute).WithPolling(1 * time.Second).Should(Succeed())
110+
helpers.ExpectClusterExtensionToBeInstalled(ctx, name)
100111
})
101112

102113
It("should fail to install a non-existing cluster extension", func(ctx SpecContext) {
114+
By("ensuring no ClusterExtension and CRD for non-existing operator")
115+
helpers.EnsureCleanupClusterExtension(context.Background(), "does-not-exist", "") // No CRD expected for non-existing operator
116+
103117
By("applying the ClusterExtension resource")
104-
name, cleanup := helpers.CreateClusterExtension("does-not-exist", "99.99.99")
118+
name, cleanup := helpers.CreateClusterExtension("does-not-exist", "99.99.99", namespace)
105119
DeferCleanup(cleanup)
106120

107121
By("waiting for the ClusterExtension to exist")
@@ -135,11 +149,14 @@ var _ = Describe("[sig-olmv1][OCPFeatureGate:NewOLM][Skipped:Disconnected] OLMv1
135149
Skip("Requires OCP Catalogs: not OpenShift")
136150
}
137151

152+
By("ensuring no ClusterExtension no ClusterExtension and CRD for cluster-logging")
153+
helpers.EnsureCleanupClusterExtension(context.Background(), "cluster-logging", "clusterloggings.logging.openshift.io")
154+
138155
By("applying the ClusterExtension resource")
139-
name, cleanup := helpers.CreateClusterExtension("cluster-logging", "6.2.2")
156+
name, cleanup := helpers.CreateClusterExtension("cluster-logging", "6.2.2", namespace)
140157
DeferCleanup(cleanup)
141158

142-
By("waiting for the function-mesh ClusterExtension to be installed")
159+
By("waiting for the cluster-logging ClusterExtension to be installed")
143160
Eventually(func(g Gomega) {
144161
k8sClient := env.Get().K8sClient
145162
ce := &olmv1.ClusterExtension{}

0 commit comments

Comments
 (0)