Skip to content

Commit 2e808cf

Browse files
committed
test/e2e: Refactor the Operator e2e tests to clean up testing resources
Update test/e2e/operator_test.go and attempt to refactor the current e2e specs to reduce the number of testing artifacts that are left behind when individual tests pass/fail. Signed-off-by: timflannagan <[email protected]>
1 parent fd3322a commit 2e808cf

File tree

1 file changed

+127
-168
lines changed

1 file changed

+127
-168
lines changed

test/e2e/operator_test.go

Lines changed: 127 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ var _ = Describe("Operator API", func() {
3939
)
4040

4141
BeforeEach(func() {
42-
// Setup common utilities
4342
clientCtx = context.Background()
4443
scheme = ctx.Ctx().Scheme()
4544
listOpts = metav1.ListOptions{}
@@ -51,191 +50,148 @@ var _ = Describe("Operator API", func() {
5150
Expect(err).ToNot(HaveOccurred())
5251
})
5352

54-
// Ensures that an Operator resource can select its components by label and surface them correctly in its status.
55-
//
56-
// Steps:
57-
// 1. Create an Operator resource, o
58-
// 2. Ensure o's status eventually contains its component label selector
59-
// 3. Create namespaces ns-a and ns-b
60-
// 4. Label ns-a with o's component label
61-
// 5. Ensure o's status.components.refs field eventually contains a reference to ns-a
62-
// 6. Create ServiceAccounts sa-a and sa-b in namespaces ns-a and ns-b respectively
63-
// 7. Label sa-a and sa-b with o's component label
64-
// 8. Ensure o's status.components.refs field eventually contains references to sa-a and sa-b
65-
// 9. Remove the component label from sa-b
66-
// 10. Ensure the reference to sa-b is eventually removed from o's status.components.refs field
67-
// 11. Delete o
68-
// 12. Ensure o is re-created
69-
// 13. Delete ns-a
70-
// 14. Ensure the reference to ns-a is eventually removed from o's status.components.refs field
71-
// 15. Delete o
72-
// 16. Ensure o is not re-created
73-
It("should surface components in its status", func() {
74-
o := &operatorsv1.Operator{}
75-
o.SetName(genName("o-"))
76-
77-
Consistently(o).ShouldNot(ContainCopiedCSVReferences())
78-
53+
AfterEach(func() {
7954
Eventually(func() error {
80-
return client.Create(clientCtx, o)
55+
return operatorClient.DeleteCollection(clientCtx, metav1.DeleteOptions{}, listOpts)
8156
}).Should(Succeed())
57+
})
8258

83-
defer func() {
84-
Eventually(func() error {
85-
err := client.Delete(clientCtx, o)
86-
if apierrors.IsNotFound(err) {
87-
return nil
88-
}
59+
Context("when an Operator resource can select its components by label", func() {
60+
var (
61+
o *operatorsv1.Operator
62+
)
63+
BeforeEach(func() {
64+
o = &operatorsv1.Operator{}
65+
o.SetName(genName("o-"))
8966

90-
return err
67+
Eventually(func() error {
68+
return client.Create(clientCtx, o)
9169
}).Should(Succeed())
92-
}()
70+
})
71+
AfterEach(func() {
72+
Eventually(func() error {
73+
return controllerclient.IgnoreNotFound(client.Delete(clientCtx, o))
74+
}).Should(Succeed())
75+
})
9376

94-
By("eventually having a status that contains its component label selector")
95-
w, err := operatorClient.Watch(clientCtx, listOpts)
96-
Expect(err).ToNot(HaveOccurred())
97-
defer w.Stop()
77+
It("should not contain copied csv status references", func() {
78+
Consistently(o).ShouldNot(ContainCopiedCSVReferences())
79+
})
9880

99-
deadline, cancel := context.WithTimeout(clientCtx, 1*time.Minute)
100-
defer cancel()
81+
It("should surface referenced components in its status", func() {
82+
By("eventually having a status that contains its component label selector")
83+
w, err := operatorClient.Watch(clientCtx, listOpts)
84+
Expect(err).To(BeNil())
85+
defer w.Stop()
10186

102-
expectedKey := "operators.coreos.com/" + o.GetName()
103-
awaitPredicates(deadline, w, operatorPredicate(func(op *operatorsv1.Operator) bool {
104-
if op.Status.Components == nil || op.Status.Components.LabelSelector == nil {
105-
return false
106-
}
87+
deadline, cancel := context.WithTimeout(clientCtx, 1*time.Minute)
88+
defer cancel()
10789

108-
for _, requirement := range op.Status.Components.LabelSelector.MatchExpressions {
109-
if requirement.Key == expectedKey && requirement.Operator == metav1.LabelSelectorOpExists {
110-
return true
90+
expectedKey := "operators.coreos.com/" + o.GetName()
91+
awaitPredicates(deadline, w, operatorPredicate(func(op *operatorsv1.Operator) bool {
92+
if op.Status.Components == nil || op.Status.Components.LabelSelector == nil {
93+
return false
11194
}
112-
}
11395

114-
return false
115-
}))
116-
defer w.Stop()
96+
for _, requirement := range op.Status.Components.LabelSelector.MatchExpressions {
97+
if requirement.Key == expectedKey && requirement.Operator == metav1.LabelSelectorOpExists {
98+
return true
99+
}
100+
}
117101

118-
// Create namespaces ns-a and ns-b
119-
nsA := &corev1.Namespace{}
120-
nsA.SetName(genName("ns-a-"))
121-
nsB := &corev1.Namespace{}
122-
nsB.SetName(genName("ns-b-"))
102+
return false
103+
}))
104+
defer w.Stop()
123105

124-
for _, ns := range []*corev1.Namespace{nsA, nsB} {
125-
Eventually(func() error {
126-
return client.Create(clientCtx, ns)
127-
}).Should(Succeed())
106+
nsA := &corev1.Namespace{}
107+
nsA.SetName(genName("ns-a-"))
108+
nsB := &corev1.Namespace{}
109+
nsB.SetName(genName("ns-b-"))
128110

129-
defer func(n *corev1.Namespace) {
111+
for _, ns := range []*corev1.Namespace{nsA, nsB} {
130112
Eventually(func() error {
131-
err := client.Delete(clientCtx, n)
132-
if apierrors.IsNotFound(err) {
133-
return nil
134-
}
135-
return err
113+
return client.Create(clientCtx, ns)
136114
}).Should(Succeed())
137-
}(ns)
138-
}
139115

140-
// Label ns-a with o's component label
141-
setComponentLabel := func(m metav1.Object) error {
142-
m.SetLabels(map[string]string{expectedKey: ""})
143-
return nil
144-
}
145-
Eventually(Apply(nsA, setComponentLabel)).Should(Succeed())
116+
defer func(n *corev1.Namespace) {
117+
Eventually(func() error {
118+
err := client.Delete(clientCtx, n)
119+
if apierrors.IsNotFound(err) {
120+
return nil
121+
}
122+
return err
123+
}).Should(Succeed())
124+
}(ns)
125+
}
146126

147-
// Ensure o's status.components.refs field eventually contains a reference to ns-a
148-
By("eventually listing a single component reference")
149-
componentRefEventuallyExists(w, true, getReference(scheme, nsA))
127+
setComponentLabel := func(m metav1.Object) error {
128+
m.SetLabels(map[string]string{expectedKey: ""})
129+
return nil
130+
}
131+
Eventually(Apply(nsA, setComponentLabel)).Should(Succeed())
150132

151-
// Create ServiceAccounts sa-a and sa-b in namespaces ns-a and ns-b respectively
152-
saA := &corev1.ServiceAccount{}
153-
saA.SetName(genName("sa-a-"))
154-
saA.SetNamespace(nsA.GetName())
155-
saB := &corev1.ServiceAccount{}
156-
saB.SetName(genName("sa-b-"))
157-
saB.SetNamespace(nsB.GetName())
133+
By("eventually listing a single component reference")
134+
componentRefEventuallyExists(w, true, getReference(scheme, nsA))
158135

159-
for _, sa := range []*corev1.ServiceAccount{saA, saB} {
160-
Eventually(func() error {
161-
return client.Create(clientCtx, sa)
162-
}).Should(Succeed())
163-
defer func(sa *corev1.ServiceAccount) {
136+
// Create ServiceAccounts sa-a and sa-b in namespaces ns-a and ns-b respectively
137+
saA := &corev1.ServiceAccount{}
138+
saA.SetName(genName("sa-a-"))
139+
saA.SetNamespace(nsA.GetName())
140+
saB := &corev1.ServiceAccount{}
141+
saB.SetName(genName("sa-b-"))
142+
saB.SetNamespace(nsB.GetName())
143+
144+
for _, sa := range []*corev1.ServiceAccount{saA, saB} {
164145
Eventually(func() error {
165-
err := client.Delete(clientCtx, sa)
166-
if apierrors.IsNotFound(err) {
167-
return nil
168-
}
169-
return err
146+
return client.Create(clientCtx, sa)
170147
}).Should(Succeed())
171-
}(sa)
172-
}
148+
defer func(sa *corev1.ServiceAccount) {
149+
Eventually(func() error {
150+
return controllerclient.IgnoreNotFound(client.Delete(clientCtx, sa))
151+
}).Should(Succeed())
152+
}(sa)
153+
}
173154

174-
// Label sa-a and sa-b with o's component label
175-
Eventually(Apply(saA, setComponentLabel)).Should(Succeed())
176-
Eventually(Apply(saB, setComponentLabel)).Should(Succeed())
155+
Eventually(Apply(saA, setComponentLabel)).Should(Succeed())
156+
Eventually(Apply(saB, setComponentLabel)).Should(Succeed())
177157

178-
// Ensure o's status.components.refs field eventually contains references to sa-a and sa-b
179-
By("eventually listing multiple component references")
180-
componentRefEventuallyExists(w, true, getReference(scheme, saA))
181-
componentRefEventuallyExists(w, true, getReference(scheme, saB))
158+
By("eventually listing multiple component references")
159+
componentRefEventuallyExists(w, true, getReference(scheme, saA))
160+
componentRefEventuallyExists(w, true, getReference(scheme, saB))
182161

183-
// Remove the component label from sa-b
184-
Eventually(Apply(saB, func(m metav1.Object) error {
185-
m.SetLabels(nil)
186-
return nil
187-
})).Should(Succeed())
162+
Eventually(Apply(saB, func(m metav1.Object) error {
163+
m.SetLabels(nil)
164+
return nil
165+
})).Should(Succeed())
188166

189-
// Ensure the reference to sa-b is eventually removed from o's status.components.refs field
190-
By("removing a component's reference when it no longer bears the component label")
191-
componentRefEventuallyExists(w, false, getReference(scheme, saB))
167+
By("removing a component's reference when it no longer bears the component label")
168+
componentRefEventuallyExists(w, false, getReference(scheme, saB))
192169

193-
// Delete o
194-
Eventually(func() error {
195-
err := client.Delete(clientCtx, o)
196-
if err != nil && !apierrors.IsNotFound(err) {
197-
return err
198-
}
199-
return nil
200-
}).Should(Succeed())
170+
Eventually(func() error {
171+
return controllerclient.IgnoreNotFound(client.Delete(clientCtx, o))
172+
}).Should(Succeed())
201173

202-
// Ensure that o is eventually recreated (because some of its components still exist).
203-
By("recreating the Operator when any components still exist")
204-
Eventually(func() error {
205-
return client.Get(clientCtx, types.NamespacedName{Name: o.GetName()}, o)
206-
}).Should(Succeed())
174+
By("recreating the Operator when any components still exist")
175+
Eventually(func() error {
176+
return client.Get(clientCtx, types.NamespacedName{Name: o.GetName()}, o)
177+
}).Should(Succeed())
207178

208-
// Delete ns-a
209-
Eventually(func() error {
210-
err := client.Delete(clientCtx, nsA)
211-
if apierrors.IsNotFound(err) {
212-
return nil
213-
}
214-
return err
215-
}).Should(Succeed())
179+
Eventually(func() error {
180+
return controllerclient.IgnoreNotFound(client.Delete(clientCtx, nsA))
181+
}).Should(Succeed())
216182

217-
// Ensure the reference to ns-a is eventually removed from o's status.components.refs field
218-
By("removing a component's reference when it no longer exists")
219-
componentRefEventuallyExists(w, false, getReference(scheme, nsA))
183+
By("removing a component's reference when it no longer exists")
184+
componentRefEventuallyExists(w, false, getReference(scheme, nsA))
220185

221-
// Delete o
222-
Eventually(func() error {
223-
err := client.Delete(clientCtx, o)
224-
if apierrors.IsNotFound(err) {
225-
return nil
226-
}
227-
return err
228-
}).Should(Succeed())
186+
Eventually(func() error {
187+
return controllerclient.IgnoreNotFound(client.Delete(clientCtx, o))
188+
}).Should(Succeed())
229189

230-
// Ensure that o is consistently not found
231-
By("verifying the Operator is permanently deleted if it has no components")
232-
Consistently(func() error {
233-
err := client.Get(clientCtx, types.NamespacedName{Name: o.GetName()}, o)
234-
if apierrors.IsNotFound(err) {
235-
return nil
236-
}
237-
return err
238-
}).Should(Succeed())
190+
By("verifying the Operator is permanently deleted if it has no components")
191+
Consistently(func() error {
192+
return controllerclient.IgnoreNotFound(client.Get(clientCtx, types.NamespacedName{Name: o.GetName()}, o))
193+
}).Should(Succeed())
194+
})
239195
})
240196

241197
Context("when a subscription to a package exists", func() {
@@ -247,14 +203,12 @@ var _ = Describe("Operator API", func() {
247203
)
248204

249205
BeforeEach(func() {
250-
// Subscribe to a package and await a successful install
251206
ns = &corev1.Namespace{}
252207
ns.SetName(genName("ns-"))
253208
Eventually(func() error {
254209
return client.Create(clientCtx, ns)
255210
}).Should(Succeed())
256211

257-
// Default to AllNamespaces
258212
og := &operatorsv1.OperatorGroup{}
259213
og.SetNamespace(ns.GetName())
260214
og.SetName(genName("og-"))
@@ -274,7 +228,6 @@ var _ = Describe("Operator API", func() {
274228
return client.Create(clientCtx, cs)
275229
}).Should(Succeed())
276230

277-
// Wait for the CatalogSource to be ready
278231
_, err := fetchCatalogSourceOnStatus(newCRClient(), cs.GetName(), cs.GetNamespace(), catalogSourceRegistryPodSynced)
279232
Expect(err).ToNot(HaveOccurred())
280233

@@ -323,12 +276,21 @@ var _ = Describe("Operator API", func() {
323276
})
324277

325278
AfterEach(func() {
279+
By("Deleting the testing namespace")
326280
Eventually(func() error {
327-
err := client.Delete(clientCtx, ns)
328-
if apierrors.IsNotFound(err) {
329-
return nil
330-
}
331-
return err
281+
return controllerclient.IgnoreNotFound(client.Delete(clientCtx, ns))
282+
}).Should(Succeed())
283+
284+
By("Deleting the kiali-related CRDs")
285+
Eventually(func() error {
286+
return client.DeleteAllOf(clientCtx, &apiextensionsv1.CustomResourceDefinition{}, controllerclient.MatchingLabels{
287+
fmt.Sprintf("operators.coreos.com/%s", operatorName.Name): "",
288+
})
289+
}).Should(Succeed())
290+
291+
By("Deleting the test Operator resource")
292+
Eventually(func() error {
293+
return operatorClient.Delete(clientCtx, operatorName.Name, metav1.DeleteOptions{})
332294
}).Should(Succeed())
333295
})
334296

@@ -363,7 +325,7 @@ var _ = Describe("Operator API", func() {
363325
var newNs *corev1.Namespace
364326

365327
BeforeEach(func() {
366-
// Subscribe to a package and await a successful install
328+
By("Subscribe to a package and await a successful install")
367329
newNs = &corev1.Namespace{}
368330
newNs.SetName(genName("ns-"))
369331
Eventually(func() error {
@@ -372,11 +334,7 @@ var _ = Describe("Operator API", func() {
372334
})
373335
AfterEach(func() {
374336
Eventually(func() error {
375-
err := client.Delete(clientCtx, newNs)
376-
if apierrors.IsNotFound(err) {
377-
return nil
378-
}
379-
return err
337+
return controllerclient.IgnoreNotFound(client.Delete(clientCtx, newNs))
380338
}).Should(Succeed())
381339
})
382340
It("should not adopt copied csvs", func() {
@@ -514,6 +472,7 @@ func ReferenceComponents(refs []*corev1.ObjectReference) gomegatypes.GomegaMatch
514472

515473
for _, ref := range refs {
516474
if _, ok := actual[*ref]; !ok {
475+
ctx.Ctx().Logf("reference missing: %v - %v - %v", ref.GetObjectKind(), ref.Name, ref.Namespace)
517476
return false, nil
518477
}
519478
}

0 commit comments

Comments
 (0)