From 2efcc9d2ad05b8c3e2fdbd5e6a0a231bdbb3ad87 Mon Sep 17 00:00:00 2001 From: Todd Short Date: Tue, 18 Apr 2023 11:11:52 -0400 Subject: [PATCH 1/6] Integrate channelName Signed-off-by: Todd Short --- .gitignore | 2 ++ internal/resolution/variable_sources/olm/olm.go | 3 +++ .../required_package/required_package.go | 11 +++++++++++ 3 files changed, 16 insertions(+) diff --git a/.gitignore b/.gitignore index e48b81835..2d49c9a2d 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,8 @@ install.sh *.swp *.swo *~ +\#*\# +.\#* # TODO dfranz remove this line and the bin folder when tools binaries are moved to their own folder !bin/.dockerignore diff --git a/internal/resolution/variable_sources/olm/olm.go b/internal/resolution/variable_sources/olm/olm.go index faf8b5c7d..97fae6f80 100644 --- a/internal/resolution/variable_sources/olm/olm.go +++ b/internal/resolution/variable_sources/olm/olm.go @@ -46,5 +46,8 @@ func (o *OLMVariableSource) requiredPackageFromOperator(operator *operatorsv1alp if operator.Spec.Version != "" { opts = append(opts, required_package.InVersionRange(operator.Spec.Version)) } + if operator.Spec.Channel != "" { + opts = append(opts, required_package.InChannel(operator.Spec.Channel)) + } return required_package.NewRequiredPackage(operator.Spec.PackageName, opts...) } diff --git a/internal/resolution/variable_sources/required_package/required_package.go b/internal/resolution/variable_sources/required_package/required_package.go index fd577a5b3..0c10cb7af 100644 --- a/internal/resolution/variable_sources/required_package/required_package.go +++ b/internal/resolution/variable_sources/required_package/required_package.go @@ -54,9 +54,20 @@ func InVersionRange(versionRange string) RequiredPackageOption { } } +func InChannel(channelName string) RequiredPackageOption { + return func(r *RequiredPackageVariableSource) error { + if channelName != "" { + r.channelName = channelName + r.predicates = append(r.predicates, predicates.InChannel(channelName)) + } + return nil + } +} + type RequiredPackageVariableSource struct { packageName string versionRange string + channelName string predicates []input.Predicate } From 4ddf729daed42bd5f9848f588fb9e0d94391f837 Mon Sep 17 00:00:00 2001 From: Todd Short Date: Tue, 18 Apr 2023 16:22:42 -0400 Subject: [PATCH 2/6] Add channelName unit tests Signed-off-by: Todd Short --- controllers/admission_test.go | 27 +++++++++ controllers/operator_controller_test.go | 78 ++++++++++++++++++++++++- 2 files changed, 103 insertions(+), 2 deletions(-) diff --git a/controllers/admission_test.go b/controllers/admission_test.go index 9e3414624..c43b1da74 100644 --- a/controllers/admission_test.go +++ b/controllers/admission_test.go @@ -72,4 +72,31 @@ var _ = Describe("Operator Spec Validations", func() { Expect(err.Error()).To(ContainSubstring("spec.version in body should match '^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(-(0|[1-9]\\d*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*)(\\.(0|[1-9]\\d*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\\+([0-9a-zA-Z-]+(\\.[0-9a-zA-Z-]+)*))?$'")) } }) + It("should fail if an invalid channel name is given", func() { + invalidChannels := []string{ + "spaces spaces", + "Capitalized", + "camelCase", + "many/invalid$characters+in_name", + "-start-with-hyphen", + "end-with-hyphen-", + "channel-has-version-1.0.1", + } + for _, invalidChannel := range invalidChannels { + err := cl.Create(ctx, operator(operatorsv1alpha1.OperatorSpec{ + PackageName: "package", + Channel: invalidChannel, + })) + Expect(err).To(HaveOccurred(), "expected error for invalid channel '%q'", invalidChannel) + Expect(err.Error()).To(ContainSubstring("spec.channel in body should match '^[a-z0-9]+(-[a-z0-9]+)*$'")) + } + }) + It("should fail if an invalid channel name length", func() { + err := cl.Create(ctx, operator(operatorsv1alpha1.OperatorSpec{ + PackageName: "package", + Channel: "longname01234567890123456789012345678901234567890", + })) + Expect(err).To(HaveOccurred(), "expected error for invalid channel length") + Expect(err.Error()).To(ContainSubstring("spec.channel: Too long: may not be longer than 48")) + }) }) diff --git a/controllers/operator_controller_test.go b/controllers/operator_controller_test.go index 822b50d2b..f0f8e9b80 100644 --- a/controllers/operator_controller_test.go +++ b/controllers/operator_controller_test.go @@ -85,7 +85,7 @@ var _ = Describe("Operator Controller Test", func() { var pkgName string BeforeEach(func() { By("initializing cluster state") - pkgName = fmt.Sprintf("exists-%s", rand.String(6)) + pkgName = "prometheus" operator = &operatorsv1alpha1.Operator{ ObjectMeta: metav1.ObjectMeta{Name: opKey.Name}, Spec: operatorsv1alpha1.OperatorSpec{ @@ -594,6 +594,80 @@ var _ = Describe("Operator Controller Test", func() { }) }) + When("the operator specifies a channel that exist", func() { + var pkgName string + var pkgVer string + var pkgChan string + BeforeEach(func() { + By("initializing cluster state") + pkgName = "prometheus" + pkgVer = "0.47.0" + pkgChan = "beta" + operator = &operatorsv1alpha1.Operator{ + ObjectMeta: metav1.ObjectMeta{Name: opKey.Name}, + Spec: operatorsv1alpha1.OperatorSpec{ + PackageName: pkgName, + Version: pkgVer, + Channel: pkgChan, + }, + } + err := cl.Create(ctx, operator) + Expect(err).NotTo(HaveOccurred()) + }) + It("sets resolution success status", func() { + By("running reconcile") + res, err := reconciler.Reconcile(ctx, ctrl.Request{NamespacedName: opKey}) + Expect(res).To(Equal(ctrl.Result{})) + Expect(err).NotTo(HaveOccurred()) + + By("fetching updated operator after reconcile") + Expect(cl.Get(ctx, opKey, operator)).NotTo(HaveOccurred()) + + By("checking the expected conditions") + cond := apimeta.FindStatusCondition(operator.Status.Conditions, operatorsv1alpha1.TypeReady) + Expect(cond).NotTo(BeNil()) + Expect(cond.Status).To(Equal(metav1.ConditionUnknown)) + Expect(cond.Reason).To(Equal(operatorsv1alpha1.ReasonInstallationStatusUnknown)) + Expect(cond.Message).To(ContainSubstring("waiting for BundleDeployment")) + }) + }) + When("the operator specifies a channel that does not exist", func() { + var pkgName string + var pkgVer string + var pkgChan string + BeforeEach(func() { + By("initializing cluster state") + pkgName = "prometheus" + pkgVer = "0.47.0" + pkgChan = "alpha" + operator = &operatorsv1alpha1.Operator{ + ObjectMeta: metav1.ObjectMeta{Name: opKey.Name}, + Spec: operatorsv1alpha1.OperatorSpec{ + PackageName: pkgName, + Version: pkgVer, + Channel: pkgChan, + }, + } + err := cl.Create(ctx, operator) + Expect(err).NotTo(HaveOccurred()) + }) + It("sets resolution failure status", func() { + By("running reconcile") + res, err := reconciler.Reconcile(ctx, ctrl.Request{NamespacedName: opKey}) + Expect(res).To(Equal(ctrl.Result{})) + Expect(err).To(MatchError(fmt.Sprintf("package '%s' at version '%s' not found", pkgName, pkgVer))) + + By("fetching updated operator after reconcile") + Expect(cl.Get(ctx, opKey, operator)).NotTo(HaveOccurred()) + + By("checking the expected conditions") + cond := apimeta.FindStatusCondition(operator.Status.Conditions, operatorsv1alpha1.TypeReady) + Expect(cond).NotTo(BeNil()) + Expect(cond.Status).To(Equal(metav1.ConditionFalse)) + Expect(cond.Reason).To(Equal(operatorsv1alpha1.ReasonResolutionFailed)) + Expect(cond.Message).To(Equal(fmt.Sprintf("package '%s' at version '%s' not found", pkgName, pkgVer))) + }) + }) AfterEach(func() { verifyInvariants(ctx, operator) @@ -648,7 +722,7 @@ var _ = Describe("Operator Controller Test", func() { Expect(cond.Reason).To(Equal(operatorsv1alpha1.ReasonInvalidSpec)) Expect(cond.Message).To(Equal("invalid .spec.version: Invalid character(s) found in prerelease \"123abc_def\"")) }) - }) + }) }) func verifyInvariants(ctx context.Context, op *operatorsv1alpha1.Operator) { From 14931637b1d471ce4765238976b835c10a7f5a6c Mon Sep 17 00:00:00 2001 From: Todd Short Date: Wed, 19 Apr 2023 09:43:03 -0400 Subject: [PATCH 3/6] Add more tests Signed-off-by: Todd Short --- controllers/operator_controller_test.go | 77 ++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 2 deletions(-) diff --git a/controllers/operator_controller_test.go b/controllers/operator_controller_test.go index f0f8e9b80..7e5a81561 100644 --- a/controllers/operator_controller_test.go +++ b/controllers/operator_controller_test.go @@ -594,7 +594,7 @@ var _ = Describe("Operator Controller Test", func() { }) }) - When("the operator specifies a channel that exist", func() { + When("the operator specifies a channel with version that exist", func() { var pkgName string var pkgVer string var pkgChan string @@ -631,6 +631,42 @@ var _ = Describe("Operator Controller Test", func() { Expect(cond.Message).To(ContainSubstring("waiting for BundleDeployment")) }) }) + When("the operator specifies a package that exists within a channel but no version specified", func() { + var pkgName string + var pkgVer string + var pkgChan string + BeforeEach(func() { + By("initializing cluster state") + pkgName = "prometheus" + pkgChan = "beta" + operator = &operatorsv1alpha1.Operator{ + ObjectMeta: metav1.ObjectMeta{Name: opKey.Name}, + Spec: operatorsv1alpha1.OperatorSpec{ + PackageName: pkgName, + Version: pkgVer, + Channel: pkgChan, + }, + } + err := cl.Create(ctx, operator) + Expect(err).NotTo(HaveOccurred()) + }) + It("sets resolution success status", func() { + By("running reconcile") + res, err := reconciler.Reconcile(ctx, ctrl.Request{NamespacedName: opKey}) + Expect(res).To(Equal(ctrl.Result{})) + Expect(err).NotTo(HaveOccurred()) + + By("fetching updated operator after reconcile") + Expect(cl.Get(ctx, opKey, operator)).NotTo(HaveOccurred()) + + By("checking the expected conditions") + cond := apimeta.FindStatusCondition(operator.Status.Conditions, operatorsv1alpha1.TypeReady) + Expect(cond).NotTo(BeNil()) + Expect(cond.Status).To(Equal(metav1.ConditionUnknown)) + Expect(cond.Reason).To(Equal(operatorsv1alpha1.ReasonInstallationStatusUnknown)) + Expect(cond.Message).To(ContainSubstring("waiting for BundleDeployment")) + }) + }) When("the operator specifies a channel that does not exist", func() { var pkgName string var pkgVer string @@ -668,6 +704,43 @@ var _ = Describe("Operator Controller Test", func() { Expect(cond.Message).To(Equal(fmt.Sprintf("package '%s' at version '%s' not found", pkgName, pkgVer))) }) }) + When("the operator specifies a package version that does not exist in the channel", func() { + var pkgName string + var pkgVer string + var pkgChan string + BeforeEach(func() { + By("initializing cluster state") + pkgName = "prometheus" + pkgVer = "0.57.0" + pkgChan = "beta" + operator = &operatorsv1alpha1.Operator{ + ObjectMeta: metav1.ObjectMeta{Name: opKey.Name}, + Spec: operatorsv1alpha1.OperatorSpec{ + PackageName: pkgName, + Version: pkgVer, + Channel: pkgChan, + }, + } + err := cl.Create(ctx, operator) + Expect(err).NotTo(HaveOccurred()) + }) + It("sets resolution failure status", func() { + By("running reconcile") + res, err := reconciler.Reconcile(ctx, ctrl.Request{NamespacedName: opKey}) + Expect(res).To(Equal(ctrl.Result{})) + Expect(err).To(MatchError(fmt.Sprintf("package '%s' at version '%s' not found", pkgName, pkgVer))) + + By("fetching updated operator after reconcile") + Expect(cl.Get(ctx, opKey, operator)).NotTo(HaveOccurred()) + + By("checking the expected conditions") + cond := apimeta.FindStatusCondition(operator.Status.Conditions, operatorsv1alpha1.TypeReady) + Expect(cond).NotTo(BeNil()) + Expect(cond.Status).To(Equal(metav1.ConditionFalse)) + Expect(cond.Reason).To(Equal(operatorsv1alpha1.ReasonResolutionFailed)) + Expect(cond.Message).To(Equal(fmt.Sprintf("package '%s' at version '%s' not found", pkgName, pkgVer))) + }) + }) AfterEach(func() { verifyInvariants(ctx, operator) @@ -722,7 +795,7 @@ var _ = Describe("Operator Controller Test", func() { Expect(cond.Reason).To(Equal(operatorsv1alpha1.ReasonInvalidSpec)) Expect(cond.Message).To(Equal("invalid .spec.version: Invalid character(s) found in prerelease \"123abc_def\"")) }) - }) + }) }) func verifyInvariants(ctx context.Context, op *operatorsv1alpha1.Operator) { From 5067bfce4b7011117d592bfbf43dcb685a87beb6 Mon Sep 17 00:00:00 2001 From: Todd Short Date: Wed, 19 Apr 2023 09:54:01 -0400 Subject: [PATCH 4/6] Update error messages Signed-off-by: Todd Short --- controllers/operator_controller_test.go | 44 ++++++++++++++++--- .../required_package/required_package.go | 6 +++ 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/controllers/operator_controller_test.go b/controllers/operator_controller_test.go index 7e5a81561..7b3f0ec5d 100644 --- a/controllers/operator_controller_test.go +++ b/controllers/operator_controller_test.go @@ -667,7 +667,7 @@ var _ = Describe("Operator Controller Test", func() { Expect(cond.Message).To(ContainSubstring("waiting for BundleDeployment")) }) }) - When("the operator specifies a channel that does not exist", func() { + When("the operator specifies a package version in a channel that does not exist", func() { var pkgName string var pkgVer string var pkgChan string @@ -691,7 +691,7 @@ var _ = Describe("Operator Controller Test", func() { By("running reconcile") res, err := reconciler.Reconcile(ctx, ctrl.Request{NamespacedName: opKey}) Expect(res).To(Equal(ctrl.Result{})) - Expect(err).To(MatchError(fmt.Sprintf("package '%s' at version '%s' not found", pkgName, pkgVer))) + Expect(err).To(MatchError(fmt.Sprintf("package '%s' at version '%s' in channel '%s' not found", pkgName, pkgVer, pkgChan))) By("fetching updated operator after reconcile") Expect(cl.Get(ctx, opKey, operator)).NotTo(HaveOccurred()) @@ -701,7 +701,41 @@ var _ = Describe("Operator Controller Test", func() { Expect(cond).NotTo(BeNil()) Expect(cond.Status).To(Equal(metav1.ConditionFalse)) Expect(cond.Reason).To(Equal(operatorsv1alpha1.ReasonResolutionFailed)) - Expect(cond.Message).To(Equal(fmt.Sprintf("package '%s' at version '%s' not found", pkgName, pkgVer))) + Expect(cond.Message).To(Equal(fmt.Sprintf("package '%s' at version '%s' in channel '%s' not found", pkgName, pkgVer, pkgChan))) + }) + }) + When("the operator specifies a package in a channel that does not exist", func() { + var pkgName string + var pkgChan string + BeforeEach(func() { + By("initializing cluster state") + pkgName = "prometheus" + pkgChan = "alpha" + operator = &operatorsv1alpha1.Operator{ + ObjectMeta: metav1.ObjectMeta{Name: opKey.Name}, + Spec: operatorsv1alpha1.OperatorSpec{ + PackageName: pkgName, + Channel: pkgChan, + }, + } + err := cl.Create(ctx, operator) + Expect(err).NotTo(HaveOccurred()) + }) + It("sets resolution failure status", func() { + By("running reconcile") + res, err := reconciler.Reconcile(ctx, ctrl.Request{NamespacedName: opKey}) + Expect(res).To(Equal(ctrl.Result{})) + Expect(err).To(MatchError(fmt.Sprintf("package '%s' in channel '%s' not found", pkgName, pkgChan))) + + By("fetching updated operator after reconcile") + Expect(cl.Get(ctx, opKey, operator)).NotTo(HaveOccurred()) + + By("checking the expected conditions") + cond := apimeta.FindStatusCondition(operator.Status.Conditions, operatorsv1alpha1.TypeReady) + Expect(cond).NotTo(BeNil()) + Expect(cond.Status).To(Equal(metav1.ConditionFalse)) + Expect(cond.Reason).To(Equal(operatorsv1alpha1.ReasonResolutionFailed)) + Expect(cond.Message).To(Equal(fmt.Sprintf("package '%s' in channel '%s' not found", pkgName, pkgChan))) }) }) When("the operator specifies a package version that does not exist in the channel", func() { @@ -728,7 +762,7 @@ var _ = Describe("Operator Controller Test", func() { By("running reconcile") res, err := reconciler.Reconcile(ctx, ctrl.Request{NamespacedName: opKey}) Expect(res).To(Equal(ctrl.Result{})) - Expect(err).To(MatchError(fmt.Sprintf("package '%s' at version '%s' not found", pkgName, pkgVer))) + Expect(err).To(MatchError(fmt.Sprintf("package '%s' at version '%s' in channel '%s' not found", pkgName, pkgVer, pkgChan))) By("fetching updated operator after reconcile") Expect(cl.Get(ctx, opKey, operator)).NotTo(HaveOccurred()) @@ -738,7 +772,7 @@ var _ = Describe("Operator Controller Test", func() { Expect(cond).NotTo(BeNil()) Expect(cond.Status).To(Equal(metav1.ConditionFalse)) Expect(cond.Reason).To(Equal(operatorsv1alpha1.ReasonResolutionFailed)) - Expect(cond.Message).To(Equal(fmt.Sprintf("package '%s' at version '%s' not found", pkgName, pkgVer))) + Expect(cond.Message).To(Equal(fmt.Sprintf("package '%s' at version '%s' in channel '%s' not found", pkgName, pkgVer, pkgChan))) }) }) AfterEach(func() { diff --git a/internal/resolution/variable_sources/required_package/required_package.go b/internal/resolution/variable_sources/required_package/required_package.go index 0c10cb7af..94bb13806 100644 --- a/internal/resolution/variable_sources/required_package/required_package.go +++ b/internal/resolution/variable_sources/required_package/required_package.go @@ -110,8 +110,14 @@ func (r *RequiredPackageVariableSource) notFoundError() error { // context: we originally wanted to support version ranges and take the highest version that satisfies the range // during the upstream call on the 2023-04-11 we decided to pin the version instead. But, we'll keep version range // support under the covers in case we decide to pivot back. + if r.versionRange != "" && r.channelName != "" { + return fmt.Errorf("package '%s' at version '%s' in channel '%s' not found", r.packageName, r.versionRange, r.channelName) + } if r.versionRange != "" { return fmt.Errorf("package '%s' at version '%s' not found", r.packageName, r.versionRange) } + if r.channelName != "" { + return fmt.Errorf("package '%s' in channel '%s' not found", r.packageName, r.channelName) + } return fmt.Errorf("package '%s' not found", r.packageName) } From a93f1378f2fef90fc0f9d5f251c7bf766fe39665 Mon Sep 17 00:00:00 2001 From: Todd Short Date: Wed, 19 Apr 2023 10:17:37 -0400 Subject: [PATCH 5/6] Update channel name regex Signed-off-by: Todd Short --- api/v1alpha1/operator_types.go | 2 +- ...rators.operatorframework.io_operators.yaml | 2 +- controllers/admission_test.go | 22 +++++++++++++++++-- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/api/v1alpha1/operator_types.go b/api/v1alpha1/operator_types.go index d0ab38f28..409abc5bd 100644 --- a/api/v1alpha1/operator_types.go +++ b/api/v1alpha1/operator_types.go @@ -39,7 +39,7 @@ type OperatorSpec struct { Version string `json:"version,omitempty"` //+kubebuilder:validation:MaxLength:=48 - //+kubebuilder:validation:Pattern:=^[a-z0-9]+(-[a-z0-9]+)*$ + //+kubebuilder:validation:Pattern:=^[a-z0-9]+([\.-][a-z0-9]+)*$ // Channel constraint defintion Channel string `json:"channel,omitempty"` } diff --git a/config/crd/bases/operators.operatorframework.io_operators.yaml b/config/crd/bases/operators.operatorframework.io_operators.yaml index 759934b44..6cce301f7 100644 --- a/config/crd/bases/operators.operatorframework.io_operators.yaml +++ b/config/crd/bases/operators.operatorframework.io_operators.yaml @@ -38,7 +38,7 @@ spec: channel: description: Channel constraint defintion maxLength: 48 - pattern: ^[a-z0-9]+(-[a-z0-9]+)*$ + pattern: ^[a-z0-9]+([\.-][a-z0-9]+)*$ type: string packageName: maxLength: 48 diff --git a/controllers/admission_test.go b/controllers/admission_test.go index c43b1da74..ae568d019 100644 --- a/controllers/admission_test.go +++ b/controllers/admission_test.go @@ -80,7 +80,8 @@ var _ = Describe("Operator Spec Validations", func() { "many/invalid$characters+in_name", "-start-with-hyphen", "end-with-hyphen-", - "channel-has-version-1.0.1", + ".start-with-period", + "end-with-period.", } for _, invalidChannel := range invalidChannels { err := cl.Create(ctx, operator(operatorsv1alpha1.OperatorSpec{ @@ -88,7 +89,24 @@ var _ = Describe("Operator Spec Validations", func() { Channel: invalidChannel, })) Expect(err).To(HaveOccurred(), "expected error for invalid channel '%q'", invalidChannel) - Expect(err.Error()).To(ContainSubstring("spec.channel in body should match '^[a-z0-9]+(-[a-z0-9]+)*$'")) + Expect(err.Error()).To(ContainSubstring("spec.channel in body should match '^[a-z0-9]+([\\.-][a-z0-9]+)*$'")) + } + }) + It("should pass if a valid channel name is given", func() { + validChannels := []string{ + "hyphenated-name", + "dotted.name", + "channel-has-version-1.0.1", + } + for _, validChannel := range validChannels { + op := operator(operatorsv1alpha1.OperatorSpec{ + PackageName: "package", + Channel: validChannel, + }) + err := cl.Create(ctx, op) + Expect(err).NotTo(HaveOccurred(), "unexpected error creating valid channel '%q': %w", validChannel, err) + err = cl.Delete(ctx, op) + Expect(err).NotTo(HaveOccurred(), "unexpected error deleting valid channel '%q': %w", validChannel, err) } }) It("should fail if an invalid channel name length", func() { From 1c538f037267fdfd354fc8c2df1a630bd455a4aa Mon Sep 17 00:00:00 2001 From: Todd Short Date: Wed, 19 Apr 2023 13:38:51 -0400 Subject: [PATCH 6/6] Look for BundleDeployments on success Signed-off-by: Todd Short --- controllers/operator_controller_test.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/controllers/operator_controller_test.go b/controllers/operator_controller_test.go index 7b3f0ec5d..5e7b27c15 100644 --- a/controllers/operator_controller_test.go +++ b/controllers/operator_controller_test.go @@ -629,6 +629,15 @@ var _ = Describe("Operator Controller Test", func() { Expect(cond.Status).To(Equal(metav1.ConditionUnknown)) Expect(cond.Reason).To(Equal(operatorsv1alpha1.ReasonInstallationStatusUnknown)) Expect(cond.Message).To(ContainSubstring("waiting for BundleDeployment")) + + By("fetching the bundled deployment") + bd := &rukpakv1alpha1.BundleDeployment{} + Expect(cl.Get(ctx, types.NamespacedName{Name: opKey.Name}, bd)).NotTo(HaveOccurred()) + Expect(bd.Spec.ProvisionerClassName).To(Equal("core-rukpak-io-plain")) + Expect(bd.Spec.Template.Spec.ProvisionerClassName).To(Equal("core-rukpak-io-registry")) + Expect(bd.Spec.Template.Spec.Source.Type).To(Equal(rukpakv1alpha1.SourceTypeImage)) + Expect(bd.Spec.Template.Spec.Source.Image).NotTo(BeNil()) + Expect(bd.Spec.Template.Spec.Source.Image.Ref).To(Equal("quay.io/operatorhubio/prometheus@sha256:5b04c49d8d3eff6a338b56ec90bdf491d501fe301c9cdfb740e5bff6769a21ed")) }) }) When("the operator specifies a package that exists within a channel but no version specified", func() { @@ -665,6 +674,15 @@ var _ = Describe("Operator Controller Test", func() { Expect(cond.Status).To(Equal(metav1.ConditionUnknown)) Expect(cond.Reason).To(Equal(operatorsv1alpha1.ReasonInstallationStatusUnknown)) Expect(cond.Message).To(ContainSubstring("waiting for BundleDeployment")) + + By("fetching the bundled deployment") + bd := &rukpakv1alpha1.BundleDeployment{} + Expect(cl.Get(ctx, types.NamespacedName{Name: opKey.Name}, bd)).NotTo(HaveOccurred()) + Expect(bd.Spec.ProvisionerClassName).To(Equal("core-rukpak-io-plain")) + Expect(bd.Spec.Template.Spec.ProvisionerClassName).To(Equal("core-rukpak-io-registry")) + Expect(bd.Spec.Template.Spec.Source.Type).To(Equal(rukpakv1alpha1.SourceTypeImage)) + Expect(bd.Spec.Template.Spec.Source.Image).NotTo(BeNil()) + Expect(bd.Spec.Template.Spec.Source.Image.Ref).To(Equal("quay.io/operatorhubio/prometheus@sha256:5b04c49d8d3eff6a338b56ec90bdf491d501fe301c9cdfb740e5bff6769a21ed")) }) }) When("the operator specifies a package version in a channel that does not exist", func() {