Skip to content

Commit 0b054e2

Browse files
UPSTREAM: <carry>: Migrate single/own namespace tests
This commit migrates the OLMv1 single and own namespace watch mode tests from openshift/origin/test/extended/olm/olmv1-singleownnamespace.go to this repository. This is part of the effort to move component-specific tests into their respective downstream locations. Assisted-by: Gemini
1 parent 778bd57 commit 0b054e2

File tree

4 files changed

+322
-53
lines changed

4 files changed

+322
-53
lines changed

openshift/tests-extension/.openshift-tests-extension/openshift_payload_olmv1.json

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,34 @@
11
[
2+
{
3+
"name": "[sig-olmv1][OCPFeatureGate:NewOLMOwnSingleNamespace][Skipped:Disconnected] OLMv1 operator installation support for singleNamespace watch mode with quay-operator should install a cluster extension successfully",
4+
"labels": {},
5+
"resources": {
6+
"isolation": {}
7+
},
8+
"source": "openshift:payload:olmv1",
9+
"lifecycle": "blocking",
10+
"environmentSelector": {}
11+
},
12+
{
13+
"name": "[sig-olmv1][OCPFeatureGate:NewOLMOwnSingleNamespace][Skipped:Disconnected] OLMv1 operator installation support for ownNamespace watch mode with quay-operator should install a cluster extension successfully",
14+
"labels": {},
15+
"resources": {
16+
"isolation": {}
17+
},
18+
"source": "openshift:payload:olmv1",
19+
"lifecycle": "blocking",
20+
"environmentSelector": {}
21+
},
22+
{
23+
"name": "[sig-olmv1][OCPFeatureGate:NewOLMOwnSingleNamespace][Skipped:Disconnected] OLMv1 operator installation support for ownNamespace watch mode with an operator that does not support ownNamespace installation mode should fail to install a cluster extension successfully",
24+
"labels": {},
25+
"resources": {
26+
"isolation": {}
27+
},
28+
"source": "openshift:payload:olmv1",
29+
"lifecycle": "blocking",
30+
"environmentSelector": {}
31+
},
232
{
333
"name": "[sig-olmv1] OLMv1 should pass a trivial sanity check",
434
"labels": {},

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

Lines changed: 71 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,27 @@ package helpers
22

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

68
//nolint:staticcheck // ST1001: dot-imports for readability
79
. "github.com/onsi/gomega"
810

911
corev1 "k8s.io/api/core/v1"
1012
rbacv1 "k8s.io/api/rbac/v1"
13+
"k8s.io/apimachinery/pkg/api/meta"
1114
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1215
"k8s.io/apimachinery/pkg/util/rand"
16+
"sigs.k8s.io/controller-runtime/pkg/client"
1317

14-
ocv1 "github.com/operator-framework/operator-controller/api/v1"
18+
olmv1 "github.com/operator-framework/operator-controller/api/v1"
1519

1620
"github/operator-framework-operator-controller/openshift/tests-extension/pkg/env"
1721
)
1822

19-
const openshiftOperatorsNs = "openshift-operators"
20-
2123
// CreateClusterExtension creates a ServiceAccount, ClusterRoleBinding, and ClusterExtension using typed APIs.
2224
// It returns the unique suffix and a cleanup function.
23-
func CreateClusterExtension(packageName, version string) (string, func()) {
25+
func CreateClusterExtension(packageName, version, namespace string) (string, func()) {
2426
ctx := context.TODO()
2527
k8sClient := env.Get().K8sClient
2628
unique := rand.String(8)
@@ -30,59 +32,92 @@ func CreateClusterExtension(packageName, version string) (string, func()) {
3032
ceName := "install-test-ce-" + unique
3133

3234
// 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")
35+
sa := NewServiceAccount(saName, namespace)
36+
Expect(k8sClient.Create(ctx, sa)).To(Succeed(),
37+
"failed to create ServiceAccount")
4038

4139
// 2. Create ClusterRoleBinding
42-
crb := &rbacv1.ClusterRoleBinding{
40+
crb := NewClusterRoleBinding(crbName, "cluster-admin", saName, namespace)
41+
Expect(k8sClient.Create(ctx, crb)).To(Succeed(), "failed to create ClusterRoleBinding")
42+
43+
// 3. Create ClusterExtension
44+
ce := NewClusterExtensionObject(packageName, version, ceName, saName, namespace)
45+
Expect(k8sClient.Create(ctx, ce)).To(Succeed(), "failed to create ClusterExtension")
46+
47+
// Cleanup closure
48+
return ceName, func() {
49+
_ = k8sClient.Delete(ctx, ce)
50+
_ = k8sClient.Delete(ctx, crb)
51+
_ = k8sClient.Delete(ctx, sa)
52+
}
53+
}
54+
55+
// NewServiceAccount creates a new ServiceAccount object in the openshift-operators namespace.
56+
func NewServiceAccount(name, namespace string) *corev1.ServiceAccount {
57+
return &corev1.ServiceAccount{
4358
ObjectMeta: metav1.ObjectMeta{
44-
Name: crbName,
59+
Name: name,
60+
Namespace: namespace,
4561
},
62+
}
63+
}
64+
65+
// NewClusterRoleBinding creates a new ClusterRoleBinding object that binds a ClusterRole to a ServiceAccount.
66+
func NewClusterRoleBinding(name, roleName, saName, namespace string) *rbacv1.ClusterRoleBinding {
67+
return &rbacv1.ClusterRoleBinding{
68+
ObjectMeta: metav1.ObjectMeta{Name: name},
4669
RoleRef: rbacv1.RoleRef{
4770
APIGroup: "rbac.authorization.k8s.io",
4871
Kind: "ClusterRole",
49-
Name: "cluster-admin",
72+
Name: roleName,
5073
},
5174
Subjects: []rbacv1.Subject{{
5275
Kind: "ServiceAccount",
5376
Name: saName,
54-
Namespace: openshiftOperatorsNs,
77+
Namespace: namespace,
5578
}},
5679
}
57-
Expect(k8sClient.Create(ctx, crb)).To(Succeed(), "failed to create ClusterRoleBinding")
80+
}
5881

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{
82+
// NewClusterExtensionObject creates a new ClusterExtension object with the specified package, version, name, and ServiceAccount.
83+
func NewClusterExtensionObject(pkg, version, ceName, saName, namespace string) *olmv1.ClusterExtension {
84+
return &olmv1.ClusterExtension{
85+
ObjectMeta: metav1.ObjectMeta{Name: ceName},
86+
Spec: olmv1.ClusterExtensionSpec{
87+
Namespace: namespace,
88+
ServiceAccount: olmv1.ServiceAccountReference{
6789
Name: saName,
6890
},
69-
Source: ocv1.SourceConfig{
70-
SourceType: ocv1.SourceTypeCatalog,
71-
Catalog: &ocv1.CatalogFilter{
72-
PackageName: packageName,
91+
Source: olmv1.SourceConfig{
92+
SourceType: olmv1.SourceTypeCatalog,
93+
Catalog: &olmv1.CatalogFilter{
94+
PackageName: pkg,
7395
Version: version,
7496
Selector: &metav1.LabelSelector{},
75-
UpgradeConstraintPolicy: ocv1.UpgradeConstraintPolicyCatalogProvided,
97+
UpgradeConstraintPolicy: olmv1.UpgradeConstraintPolicyCatalogProvided,
7698
},
7799
},
78100
},
79101
}
80-
Expect(k8sClient.Create(ctx, ce)).To(Succeed(), "failed to create ClusterExtension")
102+
}
81103

82-
// Cleanup closure
83-
return ceName, func() {
84-
_ = k8sClient.Delete(ctx, ce)
85-
_ = k8sClient.Delete(ctx, crb)
86-
_ = k8sClient.Delete(ctx, sa)
87-
}
104+
// ExpectClusterExtensionToBeInstalled checks that the ClusterExtension has both Progressing=True and Installed=True.
105+
func ExpectClusterExtensionToBeInstalled(ctx context.Context, name string) {
106+
k8sClient := env.Get().K8sClient
107+
Eventually(func(g Gomega) {
108+
var ext olmv1.ClusterExtension
109+
err := k8sClient.Get(ctx, client.ObjectKey{Name: name}, &ext)
110+
g.Expect(err).ToNot(HaveOccurred(), fmt.Sprintf("failed to get ClusterExtension %q", name))
111+
112+
conditions := ext.Status.Conditions
113+
g.Expect(conditions).NotTo(BeEmpty(), fmt.Sprintf("ClusterExtension %q has empty status.conditions", name))
114+
115+
progressing := meta.FindStatusCondition(conditions, olmv1.TypeProgressing)
116+
g.Expect(progressing).ToNot(BeNil(), "Progressing condition not found")
117+
g.Expect(progressing.Status).To(Equal(metav1.ConditionTrue), "Progressing should be True")
118+
119+
installed := meta.FindStatusCondition(conditions, olmv1.TypeInstalled)
120+
g.Expect(installed).ToNot(BeNil(), "Installed condition not found")
121+
g.Expect(installed.Status).To(Equal(metav1.ConditionTrue), "Installed should be True")
122+
}).WithTimeout(5 * time.Minute).WithPolling(1 * time.Second).Should(Succeed())
88123
}
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
package test
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"time"
7+
8+
//nolint:staticcheck // ST1001: dot-imports for readability
9+
. "github.com/onsi/ginkgo/v2"
10+
//nolint:staticcheck // ST1001: dot-imports for readability
11+
. "github.com/onsi/gomega"
12+
13+
corev1 "k8s.io/api/core/v1"
14+
"k8s.io/apimachinery/pkg/api/meta"
15+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
16+
"k8s.io/apimachinery/pkg/util/rand"
17+
"sigs.k8s.io/controller-runtime/pkg/client"
18+
19+
olmv1 "github.com/operator-framework/operator-controller/api/v1"
20+
21+
"github/operator-framework-operator-controller/openshift/tests-extension/pkg/env"
22+
"github/operator-framework-operator-controller/openshift/tests-extension/pkg/helpers"
23+
)
24+
25+
var _ = Describe("[sig-olmv1][OCPFeatureGate:NewOLMOwnSingleNamespace][Skipped:Disconnected] OLMv1 operator installation support for singleNamespace watch mode with quay-operator", Serial, func() {
26+
var (
27+
k8sClient client.Client
28+
namespace string
29+
)
30+
31+
BeforeEach(func() {
32+
if !env.Get().IsOpenShift {
33+
Skip("Requires OpenShift for the tests")
34+
}
35+
36+
k8sClient = env.Get().K8sClient
37+
namespace = "olmv1-single-own-ns-" + rand.String(4)
38+
39+
By(fmt.Sprintf("creating namespace %s for single-namespace tests", namespace))
40+
ns := &corev1.Namespace{
41+
ObjectMeta: metav1.ObjectMeta{
42+
Name: namespace,
43+
},
44+
}
45+
Expect(k8sClient.Create(context.Background(), ns)).To(Succeed(), "failed to create test namespace %q", namespace)
46+
DeferCleanup(func() {
47+
By(fmt.Sprintf("cleaning up namespace %s", namespace))
48+
_ = k8sClient.Delete(context.Background(), ns)
49+
})
50+
})
51+
52+
It("should install a cluster extension successfully", func(ctx SpecContext) {
53+
unique := rand.String(4)
54+
saName := "install-test-sa-" + unique
55+
crbName := "install-test-crb-" + unique
56+
ceName := "install-test-ce-" + unique
57+
58+
By("creating ServiceAccount, ClusterRoleBinding, and ClusterExtension with the watch-namespace annotation")
59+
sa := helpers.NewServiceAccount(saName, namespace)
60+
Expect(k8sClient.Create(ctx, sa)).To(Succeed(), "failed to create ServiceAccount %q", saName)
61+
DeferCleanup(func() { _ = k8sClient.Delete(ctx, sa) })
62+
63+
crb := helpers.NewClusterRoleBinding(crbName, "cluster-admin", saName, namespace)
64+
Expect(k8sClient.Create(ctx, crb)).To(Succeed(), "failed to create ClusterRoleBinding %q", crbName)
65+
DeferCleanup(func() { _ = k8sClient.Delete(ctx, crb) })
66+
67+
ce := helpers.NewClusterExtensionObject("quay-operator", "3.14.2", ceName, saName, namespace)
68+
ce.Annotations = map[string]string{
69+
"olm.operatorframework.io/watch-namespace": namespace,
70+
}
71+
Expect(k8sClient.Create(ctx, ce)).To(Succeed(), "failed to create ClusterExtension %q", ceName)
72+
DeferCleanup(func() { _ = k8sClient.Delete(ctx, ce) })
73+
74+
By("waiting for the ClusterExtension to be installed")
75+
helpers.ExpectClusterExtensionToBeInstalled(ctx, ceName)
76+
})
77+
})
78+
79+
var _ = Describe("[sig-olmv1][OCPFeatureGate:NewOLMOwnSingleNamespace][Skipped:Disconnected] OLMv1 operator installation support for ownNamespace watch mode with quay-operator", Serial, func() {
80+
var (
81+
k8sClient client.Client
82+
namespace string
83+
)
84+
85+
BeforeEach(func() {
86+
if !env.Get().IsOpenShift {
87+
Skip("Requires OpenShift for the tests")
88+
}
89+
90+
k8sClient = env.Get().K8sClient
91+
namespace = "olmv1-own-ns-" + rand.String(4)
92+
93+
By(fmt.Sprintf("creating namespace %s for own-namespace tests", namespace))
94+
ns := &corev1.Namespace{
95+
ObjectMeta: metav1.ObjectMeta{
96+
Name: namespace,
97+
},
98+
}
99+
Expect(k8sClient.Create(context.Background(), ns)).To(Succeed(), "failed to create test namespace %q", namespace)
100+
DeferCleanup(func() {
101+
By(fmt.Sprintf("cleaning up namespace %s", namespace))
102+
_ = k8sClient.Delete(context.Background(), ns)
103+
})
104+
})
105+
106+
It("should install a cluster extension successfully", func(ctx SpecContext) {
107+
unique := rand.String(4)
108+
saName := "install-test-sa-" + unique
109+
crbName := "install-test-crb-" + unique
110+
ceName := "install-test-ce-" + unique
111+
112+
By("creating ServiceAccount, ClusterRoleBinding, and ClusterExtension with the watch-namespace annotation")
113+
sa := helpers.NewServiceAccount(saName, namespace)
114+
Expect(k8sClient.Create(ctx, sa)).To(Succeed(), "failed to create ServiceAccount %q", saName)
115+
DeferCleanup(func() { _ = k8sClient.Delete(ctx, sa) })
116+
117+
crb := helpers.NewClusterRoleBinding(crbName, "cluster-admin", saName, namespace)
118+
Expect(k8sClient.Create(ctx, crb)).To(Succeed(), "failed to create ClusterRoleBinding %q", crbName)
119+
DeferCleanup(func() { _ = k8sClient.Delete(ctx, crb) })
120+
121+
ce := helpers.NewClusterExtensionObject("quay-operator", "3.14.2", ceName, saName, namespace)
122+
ce.Annotations = map[string]string{
123+
"olm.operatorframework.io/watch-namespace": namespace,
124+
}
125+
Expect(k8sClient.Create(ctx, ce)).To(Succeed(), "failed to create ClusterExtension %q", ceName)
126+
DeferCleanup(func() { _ = k8sClient.Delete(ctx, ce) })
127+
128+
By("waiting for the ClusterExtension to be installed")
129+
helpers.ExpectClusterExtensionToBeInstalled(ctx, ceName)
130+
})
131+
})
132+
133+
var _ = Describe("[sig-olmv1][OCPFeatureGate:NewOLMOwnSingleNamespace][Skipped:Disconnected] OLMv1 operator installation support for ownNamespace watch mode with an operator that does not support ownNamespace installation mode", func() {
134+
var (
135+
k8sClient client.Client
136+
namespace string
137+
)
138+
139+
BeforeEach(func() {
140+
if !env.Get().IsOpenShift {
141+
Skip("Requires OpenShift for the tests")
142+
}
143+
144+
k8sClient = env.Get().K8sClient
145+
namespace = "olmv1-failing-own-ns-" + rand.String(4)
146+
147+
By(fmt.Sprintf("creating namespace %s for failing tests", namespace))
148+
ns := &corev1.Namespace{
149+
ObjectMeta: metav1.ObjectMeta{
150+
Name: namespace,
151+
},
152+
}
153+
Expect(k8sClient.Create(context.Background(), ns)).To(Succeed(), "failed to create test namespace %q", namespace)
154+
DeferCleanup(func() {
155+
By(fmt.Sprintf("cleaning up namespace %s", namespace))
156+
_ = k8sClient.Delete(context.Background(), ns)
157+
})
158+
})
159+
160+
It("should fail to install a cluster extension successfully", func(ctx SpecContext) {
161+
unique := rand.String(4)
162+
saName := "install-test-sa-" + unique
163+
crbName := "install-test-crb-" + unique
164+
ceName := "install-test-ce-" + unique
165+
166+
By("creating ServiceAccount, ClusterRoleBinding, and ClusterExtension with the watch-namespace annotation")
167+
sa := helpers.NewServiceAccount(saName, namespace)
168+
Expect(k8sClient.Create(ctx, sa)).To(Succeed(), "failed to create ServiceAccount %q", saName)
169+
DeferCleanup(func() { _ = k8sClient.Delete(ctx, sa) })
170+
171+
crb := helpers.NewClusterRoleBinding(crbName, "cluster-admin", saName, namespace)
172+
Expect(k8sClient.Create(ctx, crb)).To(Succeed(), "failed to create ClusterRoleBinding %q", crbName)
173+
DeferCleanup(func() { _ = k8sClient.Delete(ctx, crb) })
174+
175+
ce := helpers.NewClusterExtensionObject("openshift-pipelines-operator-rh", "1.17.1", ceName, saName, namespace)
176+
ce.Annotations = map[string]string{
177+
"olm.operatorframework.io/watch-namespace": namespace,
178+
}
179+
Expect(k8sClient.Create(ctx, ce)).To(Succeed(), "failed to create ClusterExtension %q", ceName)
180+
DeferCleanup(func() { _ = k8sClient.Delete(ctx, ce) })
181+
182+
By("waiting for the ClusterExtension to fail installation")
183+
Eventually(func(g Gomega) {
184+
var ext olmv1.ClusterExtension
185+
err := k8sClient.Get(ctx, client.ObjectKey{Name: ceName}, &ext)
186+
g.Expect(err).ToNot(HaveOccurred(), "failed to get ClusterExtension %q", ceName)
187+
188+
conditions := ext.Status.Conditions
189+
g.Expect(conditions).ToNot(BeEmpty(), "ClusterExtension %q has empty status.conditions", ceName)
190+
191+
installed := meta.FindStatusCondition(conditions, olmv1.TypeInstalled)
192+
g.Expect(installed).ToNot(BeNil(), "Installed condition not found")
193+
g.Expect(installed.Status).To(Equal(metav1.ConditionFalse), "Installed should be False")
194+
g.Expect(installed.Reason).To(Equal("Failed"))
195+
}).WithTimeout(5 * time.Minute).WithPolling(1 * time.Second).Should(Succeed())
196+
})
197+
})

0 commit comments

Comments
 (0)