Skip to content

Commit aedd8af

Browse files
committed
rebase on an early commit of operator-framework#250 and implement e2e tests
Signed-off-by: Bryce Palmer <[email protected]>
1 parent a5ce6e8 commit aedd8af

File tree

5 files changed

+293
-122
lines changed

5 files changed

+293
-122
lines changed

Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,10 @@ kind-cluster-cleanup: $(KIND) ## Delete the kind cluster
106106

107107
kind-load-test-artifacts: $(KIND) ## Load the e2e testdata container images into a kind cluster
108108
$(CONTAINER_RUNTIME) build $(TESTDATA_DIR)/bundles/registry-v1/prometheus-operator.v0.47.0 -t localhost/testdata/bundles/registry-v1/prometheus-operator:v0.47.0
109+
$(CONTAINER_RUNTIME) build $(TESTDATA_DIR)/bundles/plain-v0/plain.v0.1.0 -t localhost/testdata/bundles/plain-v0/plain:v0.1.0
109110
$(CONTAINER_RUNTIME) build $(TESTDATA_DIR)/catalogs -f $(TESTDATA_DIR)/catalogs/test-catalog.Dockerfile -t localhost/testdata/catalogs/test-catalog:e2e
110111
$(KIND) load docker-image localhost/testdata/bundles/registry-v1/prometheus-operator:v0.47.0 --name $(KIND_CLUSTER_NAME)
112+
$(KIND) load docker-image localhost/testdata/bundles/plain-v0/plain:v0.1.0 --name $(KIND_CLUSTER_NAME)
111113
$(KIND) load docker-image localhost/testdata/catalogs/test-catalog:e2e --name $(KIND_CLUSTER_NAME)
112114

113115
##@ Build

internal/controllers/operator_controller_test.go

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -960,6 +960,108 @@ var _ = Describe("Operator Controller Test", func() {
960960
err := cl.Delete(ctx, operator)
961961
Expect(err).To(Not(HaveOccurred()))
962962
})
963+
When("the operator specifies a package with a plain+v0 bundle", func() {
964+
var pkgName string
965+
var pkgVer string
966+
var pkgChan string
967+
BeforeEach(func() {
968+
By("initializing cluster state")
969+
pkgName = "plain"
970+
pkgVer = "0.1.0"
971+
pkgChan = "beta"
972+
operator = &operatorsv1alpha1.Operator{
973+
ObjectMeta: metav1.ObjectMeta{Name: opKey.Name},
974+
Spec: operatorsv1alpha1.OperatorSpec{
975+
PackageName: pkgName,
976+
Version: pkgVer,
977+
Channel: pkgChan,
978+
},
979+
}
980+
err := cl.Create(ctx, operator)
981+
Expect(err).NotTo(HaveOccurred())
982+
})
983+
It("sets resolution success status", func() {
984+
By("running reconcile")
985+
res, err := reconciler.Reconcile(ctx, ctrl.Request{NamespacedName: opKey})
986+
Expect(res).To(Equal(ctrl.Result{}))
987+
Expect(err).NotTo(HaveOccurred())
988+
989+
By("fetching updated operator after reconcile")
990+
Expect(cl.Get(ctx, opKey, operator)).NotTo(HaveOccurred())
991+
992+
By("Checking the status fields")
993+
Expect(operator.Status.ResolvedBundleResource).To(Equal("quay.io/operatorhub/plain@sha256:plain"))
994+
Expect(operator.Status.InstalledBundleResource).To(Equal(""))
995+
996+
By("checking the expected conditions")
997+
cond := apimeta.FindStatusCondition(operator.Status.Conditions, operatorsv1alpha1.TypeResolved)
998+
Expect(cond).NotTo(BeNil())
999+
Expect(cond.Status).To(Equal(metav1.ConditionTrue))
1000+
Expect(cond.Reason).To(Equal(operatorsv1alpha1.ReasonSuccess))
1001+
Expect(cond.Message).To(Equal("resolved to \"quay.io/operatorhub/plain@sha256:plain\""))
1002+
cond = apimeta.FindStatusCondition(operator.Status.Conditions, operatorsv1alpha1.TypeInstalled)
1003+
Expect(cond).NotTo(BeNil())
1004+
Expect(cond.Status).To(Equal(metav1.ConditionUnknown))
1005+
Expect(cond.Reason).To(Equal(operatorsv1alpha1.ReasonInstallationStatusUnknown))
1006+
Expect(cond.Message).To(Equal("bundledeployment status is unknown"))
1007+
1008+
By("fetching the bundled deployment")
1009+
bd := &rukpakv1alpha1.BundleDeployment{}
1010+
Expect(cl.Get(ctx, types.NamespacedName{Name: opKey.Name}, bd)).NotTo(HaveOccurred())
1011+
Expect(bd.Spec.ProvisionerClassName).To(Equal("core-rukpak-io-plain"))
1012+
Expect(bd.Spec.Template.Spec.ProvisionerClassName).To(Equal("core-rukpak-io-plain"))
1013+
Expect(bd.Spec.Template.Spec.Source.Type).To(Equal(rukpakv1alpha1.SourceTypeImage))
1014+
Expect(bd.Spec.Template.Spec.Source.Image).NotTo(BeNil())
1015+
Expect(bd.Spec.Template.Spec.Source.Image.Ref).To(Equal("quay.io/operatorhub/plain@sha256:plain"))
1016+
})
1017+
})
1018+
When("the operator specifies a package with a bade bundle mediatype", func() {
1019+
var pkgName string
1020+
var pkgVer string
1021+
var pkgChan string
1022+
BeforeEach(func() {
1023+
By("initializing cluster state")
1024+
pkgName = "badmedia"
1025+
pkgVer = "0.1.0"
1026+
pkgChan = "beta"
1027+
operator = &operatorsv1alpha1.Operator{
1028+
ObjectMeta: metav1.ObjectMeta{Name: opKey.Name},
1029+
Spec: operatorsv1alpha1.OperatorSpec{
1030+
PackageName: pkgName,
1031+
Version: pkgVer,
1032+
Channel: pkgChan,
1033+
},
1034+
}
1035+
err := cl.Create(ctx, operator)
1036+
Expect(err).NotTo(HaveOccurred())
1037+
})
1038+
It("sets resolution success status", func() {
1039+
By("running reconcile")
1040+
res, err := reconciler.Reconcile(ctx, ctrl.Request{NamespacedName: opKey})
1041+
Expect(res).To(Equal(ctrl.Result{}))
1042+
Expect(err).To(HaveOccurred())
1043+
Expect(err.Error()).To(Equal("unknown bundle mediatype: badmedia+v1"))
1044+
1045+
By("fetching updated operator after reconcile")
1046+
Expect(cl.Get(ctx, opKey, operator)).NotTo(HaveOccurred())
1047+
1048+
By("Checking the status fields")
1049+
Expect(operator.Status.ResolvedBundleResource).To(Equal("quay.io/operatorhub/badmedia@sha256:badmedia"))
1050+
Expect(operator.Status.InstalledBundleResource).To(Equal(""))
1051+
1052+
By("checking the expected conditions")
1053+
cond := apimeta.FindStatusCondition(operator.Status.Conditions, operatorsv1alpha1.TypeResolved)
1054+
Expect(cond).NotTo(BeNil())
1055+
Expect(cond.Status).To(Equal(metav1.ConditionTrue))
1056+
Expect(cond.Reason).To(Equal(operatorsv1alpha1.ReasonSuccess))
1057+
Expect(cond.Message).To(Equal("resolved to \"quay.io/operatorhub/badmedia@sha256:badmedia\""))
1058+
cond = apimeta.FindStatusCondition(operator.Status.Conditions, operatorsv1alpha1.TypeInstalled)
1059+
Expect(cond).NotTo(BeNil())
1060+
Expect(cond.Status).To(Equal(metav1.ConditionFalse))
1061+
Expect(cond.Reason).To(Equal(operatorsv1alpha1.ReasonInstallationFailed))
1062+
Expect(cond.Message).To(Equal("unknown bundle mediatype: badmedia+v1"))
1063+
})
1064+
})
9631065
})
9641066
When("an invalid semver is provided that bypasses the regex validation", func() {
9651067
var (
@@ -1061,4 +1163,18 @@ var testEntitySource = input.NewCacheQuerier(map[deppy.Identifier]input.Entity{
10611163
"olm.package": `{"packageName":"badimage","version":"0.1.0"}`,
10621164
"olm.gvk": `[]`,
10631165
}),
1166+
"operatorhub/plain/0.1.0": *input.NewEntity("operatorhub/plain/0.1.0", map[string]string{
1167+
"olm.bundle.path": `"quay.io/operatorhub/plain@sha256:plain"`,
1168+
"olm.channel": `{"channelName":"beta","priority":0}`,
1169+
"olm.package": `{"packageName":"plain","version":"0.1.0"}`,
1170+
"olm.gvk": `[]`,
1171+
"olm.bundle.mediatype": `"plain+v0"`,
1172+
}),
1173+
"operatorhub/badmedia/0.1.0": *input.NewEntity("operatorhub/badmedia/0.1.0", map[string]string{
1174+
"olm.bundle.path": `"quay.io/operatorhub/badmedia@sha256:badmedia"`,
1175+
"olm.channel": `{"channelName":"beta","priority":0}`,
1176+
"olm.package": `{"packageName":"badmedia","version":"0.1.0"}`,
1177+
"olm.gvk": `[]`,
1178+
"olm.bundle.mediatype": `"badmedia+v1"`,
1179+
}),
10641180
})

internal/resolution/entitysources/catalogdsource.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77

88
"github.com/operator-framework/deppy/pkg/deppy"
99
"github.com/operator-framework/deppy/pkg/deppy/input"
10+
"github.com/operator-framework/operator-controller/internal/resolution/variable_sources/entity"
1011
"github.com/operator-framework/operator-registry/alpha/property"
1112
"sigs.k8s.io/controller-runtime/pkg/client"
1213

@@ -86,6 +87,8 @@ func getEntities(ctx context.Context, client client.Client) (input.EntityList, e
8687
// this is already a json marshalled object, so it doesn't need to be marshalled
8788
// like the other ones
8889
props[property.TypePackage] = string(prop.Value)
90+
case entity.PropertyBundleMediaType:
91+
props[entity.PropertyBundleMediaType] = string(prop.Value)
8992
}
9093
}
9194

test/e2e/install_test.go

Lines changed: 124 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -29,25 +29,17 @@ var _ = Describe("Operator Install", func() {
2929
ctx context.Context
3030
pkgName string
3131
operatorName string
32+
catalogName string
3233
operator *operatorv1alpha1.Operator
3334
operatorCatalog *catalogd.Catalog
3435
)
3536
When("An operator is installed from an operator catalog", func() {
3637
BeforeEach(func() {
3738
ctx = context.Background()
38-
pkgName = "prometheus"
39-
operatorName = fmt.Sprintf("operator-%s", rand.String(8))
40-
operator = &operatorv1alpha1.Operator{
41-
ObjectMeta: metav1.ObjectMeta{
42-
Name: operatorName,
43-
},
44-
Spec: operatorv1alpha1.OperatorSpec{
45-
PackageName: pkgName,
46-
},
47-
}
39+
catalogName = fmt.Sprintf("catalog-%s", rand.String(8))
4840
operatorCatalog = &catalogd.Catalog{
4941
ObjectMeta: metav1.ObjectMeta{
50-
Name: testCatalogName,
42+
Name: catalogName,
5143
},
5244
Spec: catalogd.CatalogSpec{
5345
Source: catalogd.CatalogSource{
@@ -85,14 +77,14 @@ var _ = Describe("Operator Install", func() {
8577
cond := apimeta.FindStatusCondition(operator.Status.Conditions, operatorv1alpha1.TypeResolved)
8678
g.Expect(cond).ToNot(BeNil())
8779
g.Expect(cond.Status).To(Equal(metav1.ConditionTrue))
88-
g.Expect(cond.Reason).To(Equal(operatorv1alpha1.ReasonSuccess))
89-
g.Expect(cond.Message).To(ContainSubstring("resolved to"))
90-
g.Expect(operator.Status.ResolvedBundleResource).ToNot(BeEmpty())
91-
}).WithTimeout(defaultTimeout).WithPolling(defaultPoll).Should(Succeed())
80+
g.Expect(cond.Message).To(ContainSubstring("successfully unpacked the catalog image"))
9281

93-
By("eventually installing the package successfully")
94-
Eventually(func(g Gomega) {
95-
err = c.Get(ctx, types.NamespacedName{Name: operator.Name}, operator)
82+
// For some reason the above condition check is returning true and the
83+
// Operators end up being created before the packages exist. Adding this check
84+
// to ensure that there are some packages that exist before actually returning from this
85+
// check.
86+
pkgList := &catalogd.PackageList{}
87+
err = c.List(ctx, pkgList)
9688
g.Expect(err).ToNot(HaveOccurred())
9789
cond := apimeta.FindStatusCondition(operator.Status.Conditions, operatorv1alpha1.TypeInstalled)
9890
g.Expect(cond).ToNot(BeNil())
@@ -159,6 +151,7 @@ var _ = Describe("Operator Install", func() {
159151
g.Expect(cond.Reason).To(Equal(operatorv1alpha1.ReasonSuccess))
160152
}).WithTimeout(defaultTimeout).WithPolling(defaultPoll).Should(Succeed())
161153
})
154+
162155
AfterEach(func() {
163156
err := c.Delete(ctx, operator)
164157
Expect(err).ToNot(HaveOccurred())
@@ -196,5 +189,118 @@ var _ = Describe("Operator Install", func() {
196189
Expect(errors.IsNotFound(err)).To(BeTrue())
197190
}).WithTimeout(5 * time.Minute).WithPolling(defaultPoll).Should(Succeed())
198191
})
192+
193+
When("the operator bundle format is registry+v1", func() {
194+
BeforeEach(func() {
195+
pkgName = "prometheus"
196+
operatorName = fmt.Sprintf("operator-%s", rand.String(8))
197+
operator = &operatorv1alpha1.Operator{
198+
ObjectMeta: metav1.ObjectMeta{
199+
Name: operatorName,
200+
},
201+
Spec: operatorv1alpha1.OperatorSpec{
202+
PackageName: pkgName,
203+
},
204+
}
205+
})
206+
It("resolves the specified package with correct bundle path", func() {
207+
By("creating the Operator resource")
208+
err := c.Create(ctx, operator)
209+
Expect(err).ToNot(HaveOccurred())
210+
211+
By("eventually reporting a successful resolution and bundle path")
212+
Eventually(func(g Gomega) {
213+
err = c.Get(ctx, types.NamespacedName{Name: operator.Name}, operator)
214+
g.Expect(err).ToNot(HaveOccurred())
215+
g.Expect(len(operator.Status.Conditions)).To(Equal(2))
216+
cond := apimeta.FindStatusCondition(operator.Status.Conditions, operatorv1alpha1.TypeResolved)
217+
g.Expect(cond).ToNot(BeNil())
218+
g.Expect(cond.Status).To(Equal(metav1.ConditionTrue))
219+
g.Expect(cond.Reason).To(Equal(operatorv1alpha1.ReasonSuccess))
220+
g.Expect(cond.Message).To(ContainSubstring("resolved to"))
221+
g.Expect(operator.Status.ResolvedBundleResource).ToNot(BeEmpty())
222+
}).WithTimeout(defaultTimeout).WithPolling(defaultPoll).Should(Succeed())
223+
224+
By("eventually installing the package successfully")
225+
Eventually(func(g Gomega) {
226+
err = c.Get(ctx, types.NamespacedName{Name: operator.Name}, operator)
227+
g.Expect(err).ToNot(HaveOccurred())
228+
cond := apimeta.FindStatusCondition(operator.Status.Conditions, operatorv1alpha1.TypeInstalled)
229+
g.Expect(cond).ToNot(BeNil())
230+
g.Expect(cond.Status).To(Equal(metav1.ConditionTrue))
231+
g.Expect(cond.Reason).To(Equal(operatorv1alpha1.ReasonSuccess))
232+
g.Expect(cond.Message).To(ContainSubstring("installed from"))
233+
g.Expect(operator.Status.InstalledBundleResource).ToNot(BeEmpty())
234+
bd := rukpakv1alpha1.BundleDeployment{}
235+
err = c.Get(ctx, types.NamespacedName{Name: operatorName}, &bd)
236+
g.Expect(err).ToNot(HaveOccurred())
237+
g.Expect(len(bd.Status.Conditions)).To(Equal(2))
238+
g.Expect(bd.Status.Conditions[0].Reason).To(Equal("UnpackSuccessful"))
239+
g.Expect(bd.Status.Conditions[1].Reason).To(Equal("InstallationSucceeded"))
240+
}).WithTimeout(defaultTimeout).WithPolling(defaultPoll).Should(Succeed())
241+
242+
})
243+
AfterEach(func() {
244+
err := c.Delete(ctx, operator)
245+
Expect(err).ToNot(HaveOccurred())
246+
})
247+
})
248+
249+
When("the operator bundle format is plain+v0", func() {
250+
BeforeEach(func() {
251+
pkgName = "plain"
252+
operatorName = fmt.Sprintf("operator-%s", rand.String(8))
253+
operator = &operatorv1alpha1.Operator{
254+
ObjectMeta: metav1.ObjectMeta{
255+
Name: operatorName,
256+
},
257+
Spec: operatorv1alpha1.OperatorSpec{
258+
PackageName: pkgName,
259+
},
260+
}
261+
})
262+
It("resolves the specified package with correct bundle path", func() {
263+
By("creating the Operator resource")
264+
err := c.Create(ctx, operator)
265+
Expect(err).ToNot(HaveOccurred())
266+
267+
By("eventually reporting a successful resolution and bundle path")
268+
Eventually(func(g Gomega) {
269+
err = c.Get(ctx, types.NamespacedName{Name: operator.Name}, operator)
270+
g.Expect(err).ToNot(HaveOccurred())
271+
g.Expect(len(operator.Status.Conditions)).To(Equal(2))
272+
cond := apimeta.FindStatusCondition(operator.Status.Conditions, operatorv1alpha1.TypeResolved)
273+
g.Expect(cond).ToNot(BeNil())
274+
g.Expect(cond.Status).To(Equal(metav1.ConditionTrue))
275+
g.Expect(cond.Reason).To(Equal(operatorv1alpha1.ReasonSuccess))
276+
g.Expect(cond.Message).To(ContainSubstring("resolved to"))
277+
g.Expect(operator.Status.ResolvedBundleResource).ToNot(BeEmpty())
278+
}).WithTimeout(defaultTimeout).WithPolling(defaultPoll).Should(Succeed())
279+
280+
By("eventually installing the package successfully")
281+
Eventually(func(g Gomega) {
282+
err = c.Get(ctx, types.NamespacedName{Name: operator.Name}, operator)
283+
g.Expect(err).ToNot(HaveOccurred())
284+
cond := apimeta.FindStatusCondition(operator.Status.Conditions, operatorv1alpha1.TypeInstalled)
285+
g.Expect(cond).ToNot(BeNil())
286+
g.Expect(cond.Status).To(Equal(metav1.ConditionTrue))
287+
g.Expect(cond.Reason).To(Equal(operatorv1alpha1.ReasonSuccess))
288+
g.Expect(cond.Message).To(ContainSubstring("installed from"))
289+
g.Expect(operator.Status.InstalledBundleResource).ToNot(BeEmpty())
290+
bd := rukpakv1alpha1.BundleDeployment{}
291+
err = c.Get(ctx, types.NamespacedName{Name: operatorName}, &bd)
292+
g.Expect(err).ToNot(HaveOccurred())
293+
g.Expect(len(bd.Status.Conditions)).To(Equal(2))
294+
g.Expect(bd.Status.Conditions[0].Reason).To(Equal("UnpackSuccessful"))
295+
g.Expect(bd.Status.Conditions[1].Reason).To(Equal("InstallationSucceeded"))
296+
}).WithTimeout(defaultTimeout).WithPolling(defaultPoll).Should(Succeed())
297+
298+
})
299+
AfterEach(func() {
300+
err := c.Delete(ctx, operator)
301+
Expect(err).ToNot(HaveOccurred())
302+
})
303+
})
304+
199305
})
200306
})

0 commit comments

Comments
 (0)