Skip to content

Commit 918a4d1

Browse files
timflannaganankitathomas
authored andcommitted
e2e: Introduce fail forward tests
Co-authored-by: Ankita Thomas <[email protected]> Co-authored-by: timflannagan <[email protected]> Signed-off-by: timflannagan <[email protected]>
1 parent 9d6e88c commit 918a4d1

11 files changed

+550
-0
lines changed

test/e2e/fail_forward_e2e_test.go

+285
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
1+
package e2e
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"path/filepath"
7+
8+
. "github.com/onsi/ginkgo"
9+
. "github.com/onsi/gomega"
10+
corev1 "k8s.io/api/core/v1"
11+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
12+
"sigs.k8s.io/controller-runtime/pkg/client"
13+
14+
operatorsv1 "github.com/operator-framework/api/pkg/operators/v1"
15+
operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1"
16+
"github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/clientset/versioned"
17+
"github.com/operator-framework/operator-lifecycle-manager/test/e2e/ctx"
18+
)
19+
20+
const (
21+
failForwardTestDataBaseDir = "fail-forward/base/"
22+
)
23+
24+
var _ = Describe("Fail Forward Upgrades", func() {
25+
var (
26+
ns corev1.Namespace
27+
crclient versioned.Interface
28+
c client.Client
29+
)
30+
BeforeEach(func() {
31+
crclient = newCRClient()
32+
c = ctx.Ctx().Client()
33+
34+
By("creating the testing namespace with an OG that enabled fail forward behavior")
35+
namespaceName := genName("ff-e2e-")
36+
og := operatorsv1.OperatorGroup{
37+
ObjectMeta: metav1.ObjectMeta{
38+
Name: fmt.Sprintf("%s-operatorgroup", namespaceName),
39+
Namespace: namespaceName,
40+
},
41+
Spec: operatorsv1.OperatorGroupSpec{
42+
UpgradeStrategy: operatorsv1.UpgradeStrategyUnsafeFailForward,
43+
},
44+
}
45+
ns = SetupGeneratedTestNamespaceWithOperatorGroup(namespaceName, og)
46+
})
47+
48+
AfterEach(func() {
49+
By("deleting the testing namespace")
50+
TeardownNamespace(ns.GetName())
51+
})
52+
53+
When("an InstallPlan is reporting a failed state", func() {
54+
var (
55+
magicCatalog MagicCatalog
56+
catalogSourceName string
57+
subscription *operatorsv1alpha1.Subscription
58+
)
59+
BeforeEach(func() {
60+
provider, err := NewFileBasedFiledBasedCatalogProvider(filepath.Join(testdataDir, failForwardTestDataBaseDir, "example-operator.v0.1.0.yaml"))
61+
Expect(err).To(BeNil())
62+
63+
catalogSourceName = genName("mc-ip-failed-")
64+
magicCatalog = NewMagicCatalog(c, ns.GetName(), catalogSourceName, provider)
65+
Expect(magicCatalog.DeployCatalog(context.Background())).To(BeNil())
66+
67+
By("creating the testing subscription")
68+
subscription = &operatorsv1alpha1.Subscription{
69+
ObjectMeta: metav1.ObjectMeta{
70+
Name: fmt.Sprintf("%s-sub", catalogSourceName),
71+
Namespace: ns.GetName(),
72+
},
73+
Spec: &operatorsv1alpha1.SubscriptionSpec{
74+
CatalogSource: catalogSourceName,
75+
CatalogSourceNamespace: ns.GetName(),
76+
Channel: "stable",
77+
Package: "packageA",
78+
},
79+
}
80+
Expect(c.Create(context.Background(), subscription)).To(BeNil())
81+
82+
By("waiting until the subscription has an IP reference")
83+
subscription, err := fetchSubscription(crclient, subscription.GetNamespace(), subscription.GetName(), subscriptionHasInstallPlanChecker)
84+
Expect(err).Should(BeNil())
85+
86+
originalInstallPlanRef := subscription.Status.InstallPlanRef
87+
88+
By("waiting for the v0.1.0 CSV to report a succeeded phase")
89+
_, err = fetchCSV(crclient, subscription.Status.CurrentCSV, ns.GetName(), buildCSVConditionChecker(operatorsv1alpha1.CSVPhaseSucceeded))
90+
Expect(err).ShouldNot(HaveOccurred())
91+
92+
By("updating the catalog with a broken v0.2.0 bundle image")
93+
brokenProvider, err := NewFileBasedFiledBasedCatalogProvider(filepath.Join(testdataDir, failForwardTestDataBaseDir, "example-operator.v0.2.0.yaml"))
94+
Expect(err).To(BeNil())
95+
96+
err = magicCatalog.UpdateCatalog(context.Background(), brokenProvider)
97+
Expect(err).To(BeNil())
98+
99+
By("verifying the subscription is referencing a new installplan")
100+
subscription, err = fetchSubscription(crclient, subscription.GetNamespace(), subscription.GetName(), subscriptionHasInstallPlanDifferentChecker(originalInstallPlanRef.Name))
101+
Expect(err).Should(BeNil())
102+
103+
By("patching the installplan to reduce the bundle unpacking timeout")
104+
addBundleUnpackTimeoutIPAnnotation(context.Background(), c, objectRefToNamespacedName(subscription.Status.InstallPlanRef), "1s")
105+
106+
By("waiting for the bad InstallPlan to report a failed installation state")
107+
ref := subscription.Status.InstallPlanRef
108+
_, err = fetchInstallPlan(GinkgoT(), crclient, ref.Name, ref.Namespace, buildInstallPlanPhaseCheckFunc(operatorsv1alpha1.InstallPlanPhaseFailed))
109+
Expect(err).To(BeNil())
110+
111+
})
112+
AfterEach(func() {
113+
By("removing the testing catalog resources")
114+
Expect(magicCatalog.UndeployCatalog(context.Background())).To(BeNil())
115+
})
116+
It("eventually reports a successful state when multiple bad versions are rolled forward", func() {
117+
By("patching the catalog with another bad bundle version")
118+
badProvider, err := NewFileBasedFiledBasedCatalogProvider(filepath.Join(testdataDir, "fail-forward/multiple-bad-versions", "example-operator.v0.2.1.yaml"))
119+
Expect(err).To(BeNil())
120+
121+
err = magicCatalog.UpdateCatalog(context.Background(), badProvider)
122+
Expect(err).To(BeNil())
123+
124+
By("waiting for the subscription to have the example-operator.v0.2.1 status.updatedCSV")
125+
subscription, err = fetchSubscription(crclient, subscription.GetNamespace(), subscription.GetName(), subscriptionHasCurrentCSV("example-operator.v0.2.1"))
126+
Expect(err).Should(BeNil())
127+
128+
By("patching the installplan to reduce the bundle unpacking timeout")
129+
addBundleUnpackTimeoutIPAnnotation(context.Background(), c, objectRefToNamespacedName(subscription.Status.InstallPlanRef), "1s")
130+
131+
By("waiting for the bad v0.2.1 InstallPlan to report a failed installation state")
132+
ref := subscription.Status.InstallPlanRef
133+
_, err = fetchInstallPlan(GinkgoT(), crclient, ref.Name, ref.Namespace, buildInstallPlanPhaseCheckFunc(operatorsv1alpha1.InstallPlanPhaseFailed))
134+
Expect(err).To(BeNil())
135+
136+
By("patching the catalog with a fixed version")
137+
fixedProvider, err := NewFileBasedFiledBasedCatalogProvider(filepath.Join(testdataDir, "fail-forward/multiple-bad-versions", "example-operator.v0.3.0.yaml"))
138+
Expect(err).To(BeNil())
139+
140+
err = magicCatalog.UpdateCatalog(context.Background(), fixedProvider)
141+
Expect(err).To(BeNil())
142+
143+
By("waiting for the subscription to have the example-operator.v0.3.0 status.updatedCSV")
144+
subscription, err = fetchSubscription(crclient, subscription.GetNamespace(), subscription.GetName(), subscriptionHasCurrentCSV("example-operator.v0.3.0"))
145+
Expect(err).Should(BeNil())
146+
})
147+
148+
It("eventually reports a successful state when using skip ranges", func() {
149+
By("patching the catalog with a fixed version")
150+
fixedProvider, err := NewFileBasedFiledBasedCatalogProvider(filepath.Join(testdataDir, "fail-forward/skip-range", "example-operator.v0.3.0.yaml"))
151+
Expect(err).To(BeNil())
152+
153+
err = magicCatalog.UpdateCatalog(context.Background(), fixedProvider)
154+
Expect(err).To(BeNil())
155+
156+
By("waiting for the subscription to have the example-operator.v0.3.0 status.updatedCSV")
157+
subscription, err = fetchSubscription(crclient, subscription.GetNamespace(), subscription.GetName(), subscriptionHasCurrentCSV("example-operator.v0.3.0"))
158+
Expect(err).Should(BeNil())
159+
})
160+
It("eventually reports a successful state when using skips", func() {
161+
By("patching the catalog with a fixed version")
162+
fixedProvider, err := NewFileBasedFiledBasedCatalogProvider(filepath.Join(testdataDir, "fail-forward/skips", "example-operator.v0.3.0.yaml"))
163+
Expect(err).To(BeNil())
164+
165+
err = magicCatalog.UpdateCatalog(context.Background(), fixedProvider)
166+
Expect(err).To(BeNil())
167+
168+
By("waiting for the subscription to have the example-operator.v0.3.0 status.updatedCSV")
169+
subscription, err = fetchSubscription(crclient, subscription.GetNamespace(), subscription.GetName(), subscriptionHasCurrentCSV("example-operator.v0.3.0"))
170+
Expect(err).Should(BeNil())
171+
})
172+
It("eventually reports a failed state when using replaces", func() {
173+
By("patching the catalog with a fixed version")
174+
fixedProvider, err := NewFileBasedFiledBasedCatalogProvider(filepath.Join(testdataDir, "fail-forward/replaces", "example-operator.v0.3.0.yaml"))
175+
Expect(err).To(BeNil())
176+
177+
err = magicCatalog.UpdateCatalog(context.Background(), fixedProvider)
178+
Expect(err).To(BeNil())
179+
180+
By("waiting for the subscription to maintain the example-operator.v0.2.0 status.updatedCSV")
181+
Consistently(func() string {
182+
subscription, err := crclient.OperatorsV1alpha1().Subscriptions(subscription.GetNamespace()).Get(context.Background(), subscription.GetName(), metav1.GetOptions{})
183+
if err != nil || subscription == nil {
184+
return ""
185+
}
186+
return subscription.Status.CurrentCSV
187+
}).Should(Equal("example-operator.v0.2.0"))
188+
})
189+
})
190+
When("a CSV resource is in a failed state", func() {
191+
var (
192+
magicCatalog MagicCatalog
193+
catalogSourceName string
194+
subscription *operatorsv1alpha1.Subscription
195+
)
196+
BeforeEach(func() {
197+
provider, err := NewFileBasedFiledBasedCatalogProvider(filepath.Join(testdataDir, failForwardTestDataBaseDir, "example-operator.v0.1.0.yaml"))
198+
Expect(err).To(BeNil())
199+
200+
catalogSourceName = genName("mc-csv-failed-")
201+
magicCatalog = NewMagicCatalog(c, ns.GetName(), catalogSourceName, provider)
202+
Expect(magicCatalog.DeployCatalog(context.Background())).To(BeNil())
203+
204+
By("creating the testing subscription")
205+
subscription = &operatorsv1alpha1.Subscription{
206+
ObjectMeta: metav1.ObjectMeta{
207+
Name: fmt.Sprintf("%s-sub", catalogSourceName),
208+
Namespace: ns.GetName(),
209+
},
210+
Spec: &operatorsv1alpha1.SubscriptionSpec{
211+
CatalogSource: catalogSourceName,
212+
CatalogSourceNamespace: ns.GetName(),
213+
Channel: "stable",
214+
Package: "packageA",
215+
},
216+
}
217+
Expect(c.Create(context.Background(), subscription)).To(BeNil())
218+
219+
By("waiting until the subscription has an IP reference")
220+
subscription, err := fetchSubscription(crclient, subscription.GetNamespace(), subscription.GetName(), subscriptionHasInstallPlanChecker)
221+
Expect(err).Should(BeNil())
222+
223+
By("waiting for the v0.1.0 CSV to report a succeeded phase")
224+
_, err = fetchCSV(crclient, subscription.Status.CurrentCSV, ns.GetName(), buildCSVConditionChecker(operatorsv1alpha1.CSVPhaseSucceeded))
225+
Expect(err).ShouldNot(HaveOccurred())
226+
227+
By("updating the catalog with a broken v0.2.0 csv")
228+
brokenProvider, err := NewFileBasedFiledBasedCatalogProvider(filepath.Join(testdataDir, failForwardTestDataBaseDir, "example-operator.v0.2.0-2.yaml"))
229+
Expect(err).To(BeNil())
230+
231+
err = magicCatalog.UpdateCatalog(context.Background(), brokenProvider)
232+
Expect(err).To(BeNil())
233+
234+
badCSV := "example-operator.v0.2.0"
235+
By("verifying the subscription has installed the current csv")
236+
subscription, err = fetchSubscription(crclient, subscription.GetNamespace(), subscription.GetName(), subscriptionHasCurrentCSV(badCSV))
237+
Expect(err).Should(BeNil())
238+
239+
By("waiting for the bad CSV to report a failed state")
240+
_, err = fetchCSV(crclient, subscription.Status.CurrentCSV, ns.GetName(), csvFailedChecker)
241+
Expect(err).To(BeNil())
242+
243+
})
244+
AfterEach(func() {
245+
By("removing the testing catalog resources")
246+
Expect(magicCatalog.UndeployCatalog(context.Background())).To(BeNil())
247+
})
248+
It("eventually reports a successful state when using skip ranges", func() {
249+
By("patching the catalog with a fixed version")
250+
fixedProvider, err := NewFileBasedFiledBasedCatalogProvider(filepath.Join(testdataDir, "fail-forward/skip-range", "example-operator.v0.3.0.yaml"))
251+
Expect(err).To(BeNil())
252+
253+
err = magicCatalog.UpdateCatalog(context.Background(), fixedProvider)
254+
Expect(err).To(BeNil())
255+
256+
By("waiting for the subscription to have the example-operator.v0.3.0 status.updatedCSV")
257+
subscription, err = fetchSubscription(crclient, subscription.GetNamespace(), subscription.GetName(), subscriptionHasCurrentCSV("example-operator.v0.3.0"))
258+
Expect(err).Should(BeNil())
259+
})
260+
It("eventually reports a successful state when using skips", func() {
261+
By("patching the catalog with a fixed version")
262+
fixedProvider, err := NewFileBasedFiledBasedCatalogProvider(filepath.Join(testdataDir, "fail-forward/skips", "example-operator.v0.3.0.yaml"))
263+
Expect(err).To(BeNil())
264+
265+
err = magicCatalog.UpdateCatalog(context.Background(), fixedProvider)
266+
Expect(err).To(BeNil())
267+
268+
By("waiting for the subscription to have the example-operator.v0.3.0 status.updatedCSV")
269+
subscription, err = fetchSubscription(crclient, subscription.GetNamespace(), subscription.GetName(), subscriptionHasCurrentCSV("example-operator.v0.3.0"))
270+
Expect(err).Should(BeNil())
271+
})
272+
It("eventually reports a successful state when using replaces", func() {
273+
By("patching the catalog with a fixed version")
274+
fixedProvider, err := NewFileBasedFiledBasedCatalogProvider(filepath.Join(testdataDir, "fail-forward/replaces", "example-operator.v0.3.0.yaml"))
275+
Expect(err).To(BeNil())
276+
277+
err = magicCatalog.UpdateCatalog(context.Background(), fixedProvider)
278+
Expect(err).To(BeNil())
279+
280+
By("waiting for the subscription to have the example-operator.v0.3.0 status.updatedCSV")
281+
subscription, err = fetchSubscription(crclient, subscription.GetNamespace(), subscription.GetName(), subscriptionHasCurrentCSV("example-operator.v0.3.0"))
282+
Expect(err).Should(BeNil())
283+
})
284+
})
285+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
---
2+
schema: olm.package
3+
name: packageA
4+
defaultChannel: stable
5+
---
6+
schema: olm.channel
7+
package: packageA
8+
name: stable
9+
entries:
10+
- name: example-operator.v0.1.0
11+
---
12+
schema: olm.bundle
13+
name: example-operator.v0.1.0
14+
package: packageA
15+
image: quay.io/olmtest/example-operator-bundle:0.1.0
16+
properties:
17+
- type: olm.gvk
18+
value:
19+
group: example.com
20+
kind: TestA
21+
version: v1alpha1
22+
- type: olm.package
23+
value:
24+
packageName: packageA
25+
version: 1.0.0
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
schema: olm.package
3+
name: packageA
4+
defaultChannel: stable
5+
---
6+
schema: olm.channel
7+
package: packageA
8+
name: stable
9+
entries:
10+
- name: example-operator.v0.2.0
11+
replaces: example-operator.v0.1.0
12+
---
13+
schema: olm.bundle
14+
name: example-operator.v0.2.0
15+
package: packageA
16+
image: quay.io/olmtest/example-operator-bundle:0.2.0-invalid-csv
17+
properties:
18+
- type: olm.gvk
19+
value:
20+
group: example.com
21+
kind: TestA
22+
version: v1alpha1
23+
- type: olm.package
24+
value:
25+
packageName: packageA
26+
version: 1.0.1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
schema: olm.package
3+
name: packageA
4+
defaultChannel: stable
5+
---
6+
schema: olm.channel
7+
package: packageA
8+
name: stable
9+
entries:
10+
- name: example-operator.v0.2.0
11+
replaces: example-operator.v0.1.0
12+
---
13+
schema: olm.bundle
14+
name: example-operator.v0.2.0
15+
package: packageA
16+
image: quay.io/olmtest/example-operator-bundle:non-existent-tag
17+
properties:
18+
- type: olm.gvk
19+
value:
20+
group: example.com
21+
kind: TestA
22+
version: v1alpha1
23+
- type: olm.package
24+
value:
25+
packageName: packageA
26+
version: 1.0.1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
schema: olm.package
3+
name: packageA
4+
defaultChannel: stable
5+
---
6+
schema: olm.channel
7+
package: packageA
8+
name: stable
9+
entries:
10+
- name: example-operator.v0.3.0
11+
replaces: example-operator.v0.2.0
12+
---
13+
schema: olm.bundle
14+
name: example-operator.v0.3.0
15+
package: packageA
16+
image: quay.io/olmtest/example-operator-bundle:0.3.0
17+
properties:
18+
- type: olm.gvk
19+
value:
20+
group: example.com
21+
kind: TestA
22+
version: v1alpha1
23+
- type: olm.package
24+
value:
25+
packageName: packageA
26+
version: 0.3.0

0 commit comments

Comments
 (0)