From b91ac8ca13707fe492909eacd7de628b7b1f4e38 Mon Sep 17 00:00:00 2001 From: Joe Lanford Date: Thu, 2 Feb 2023 12:35:41 -0500 Subject: [PATCH] refactor and add unit tests for operator reconciler --- controllers/operator_controller.go | 17 +- controllers/operator_controller_test.go | 344 ++++++++++++++++++++++++ controllers/suite_test.go | 138 +--------- main.go | 18 +- 4 files changed, 366 insertions(+), 151 deletions(-) create mode 100644 controllers/operator_controller_test.go diff --git a/controllers/operator_controller.go b/controllers/operator_controller.go index 306dc5a06..968c9d47f 100644 --- a/controllers/operator_controller.go +++ b/controllers/operator_controller.go @@ -38,17 +38,8 @@ import ( // OperatorReconciler reconciles a Operator object type OperatorReconciler struct { client.Client - Scheme *runtime.Scheme - - resolver *resolution.OperatorResolver -} - -func NewOperatorReconciler(c client.Client, s *runtime.Scheme, r *resolution.OperatorResolver) *OperatorReconciler { - return &OperatorReconciler{ - Client: c, - Scheme: s, - resolver: r, - } + Scheme *runtime.Scheme + Resolver *resolution.OperatorResolver } //+kubebuilder:rbac:groups=operators.operatorframework.io,resources=operators,verbs=get;list;watch;create;update;patch;delete @@ -118,9 +109,9 @@ func (r *OperatorReconciler) reconcile(ctx context.Context, op *operatorsv1alpha var message = "resolution was successful" // run resolution - solution, err := r.resolver.Resolve(ctx) + solution, err := r.Resolver.Resolve(ctx) if err != nil { - status = metav1.ConditionTrue + status = metav1.ConditionFalse reason = operatorsv1alpha1.ReasonResolutionFailed message = err.Error() } else { diff --git a/controllers/operator_controller_test.go b/controllers/operator_controller_test.go new file mode 100644 index 000000000..aa568786a --- /dev/null +++ b/controllers/operator_controller_test.go @@ -0,0 +1,344 @@ +package controllers_test + +import ( + "context" + "fmt" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "github.com/operator-framework/deppy/pkg/deppy" + "github.com/operator-framework/deppy/pkg/deppy/input" + rukpakv1alpha1 "github.com/operator-framework/rukpak/api/v1alpha1" + apimeta "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/rand" + "k8s.io/utils/pointer" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + + operatorsv1alpha1 "github.com/operator-framework/operator-controller/api/v1alpha1" + "github.com/operator-framework/operator-controller/controllers" + "github.com/operator-framework/operator-controller/internal/resolution" + operatorutil "github.com/operator-framework/operator-controller/internal/util" +) + +var _ = Describe("Reconcile Test", func() { + var ( + ctx context.Context + reconciler *controllers.OperatorReconciler + ) + BeforeEach(func() { + ctx = context.Background() + reconciler = &controllers.OperatorReconciler{ + Client: cl, + Scheme: sch, + Resolver: resolution.NewOperatorResolver(cl, testEntitySource), + } + }) + When("the operator does not exist", func() { + It("returns no error", func() { + res, err := reconciler.Reconcile(context.Background(), ctrl.Request{NamespacedName: types.NamespacedName{Name: "non-existent"}}) + Expect(res).To(Equal(ctrl.Result{})) + Expect(err).NotTo(HaveOccurred()) + }) + }) + When("the operator exists", func() { + var ( + operator *operatorsv1alpha1.Operator + opKey types.NamespacedName + ) + BeforeEach(func() { + opKey = types.NamespacedName{Name: fmt.Sprintf("operator-test-%s", rand.String(8))} + }) + When("the operator specifies a non-existent package", func() { + var pkgName string + BeforeEach(func() { + By("initializing cluster state") + pkgName = fmt.Sprintf("non-existent-%s", rand.String(6)) + operator = &operatorsv1alpha1.Operator{ + ObjectMeta: metav1.ObjectMeta{Name: opKey.Name}, + Spec: operatorsv1alpha1.OperatorSpec{PackageName: pkgName}, + } + 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{})) + // TODO: should resolution failure return an error? + 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.ConditionFalse)) + Expect(cond.Reason).To(Equal(operatorsv1alpha1.ReasonResolutionFailed)) + Expect(cond.Message).To(Equal(fmt.Sprintf("package '%s' not found", pkgName))) + }) + }) + When("the operator specifies a valid available package", func() { + const pkgName = "prometheus" + BeforeEach(func() { + By("initializing cluster state") + operator = &operatorsv1alpha1.Operator{ + ObjectMeta: metav1.ObjectMeta{Name: opKey.Name}, + Spec: operatorsv1alpha1.OperatorSpec{PackageName: pkgName}, + } + err := cl.Create(ctx, operator) + Expect(err).NotTo(HaveOccurred()) + }) + When("the BundleDeployment does not exist", func() { + BeforeEach(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()) + }) + It("results in the expected BundleDeployment", func() { + bd := &rukpakv1alpha1.BundleDeployment{} + err := cl.Get(ctx, types.NamespacedName{Name: opKey.Name}, bd) + Expect(err).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")) + }) + It("sets resolution success status", func() { + cond := apimeta.FindStatusCondition(operator.Status.Conditions, operatorsv1alpha1.TypeReady) + Expect(cond).NotTo(BeNil()) + Expect(cond.Status).To(Equal(metav1.ConditionTrue)) + Expect(cond.Reason).To(Equal(operatorsv1alpha1.ReasonResolutionSucceeded)) + Expect(cond.Message).To(Equal("resolution was successful")) + }) + }) + When("the expected BundleDeployment already exists", func() { + BeforeEach(func() { + By("patching the existing BD") + err := cl.Create(ctx, &rukpakv1alpha1.BundleDeployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: opKey.Name, + OwnerReferences: []metav1.OwnerReference{ + { + APIVersion: operatorsv1alpha1.GroupVersion.String(), + Kind: "Operator", + Name: operator.Name, + UID: operator.UID, + Controller: pointer.Bool(true), + BlockOwnerDeletion: pointer.Bool(true), + }, + }, + }, + Spec: rukpakv1alpha1.BundleDeploymentSpec{ + ProvisionerClassName: "core-rukpak-io-plain", + Template: &rukpakv1alpha1.BundleTemplate{ + Spec: rukpakv1alpha1.BundleSpec{ + ProvisionerClassName: "core-rukpak-io-registry", + Source: rukpakv1alpha1.BundleSource{ + Type: rukpakv1alpha1.SourceTypeImage, + Image: &rukpakv1alpha1.ImageSource{ + Ref: "quay.io/operatorhubio/prometheus@sha256:5b04c49d8d3eff6a338b56ec90bdf491d501fe301c9cdfb740e5bff6769a21ed", + }, + }, + }, + }, + }, + }) + Expect(err).NotTo(HaveOccurred()) + + 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()) + }) + PIt("does not patch the BundleDeployment", func() { + // TODO: verify that no patch call is made. + }) + It("results in the expected BundleDeployment", func() { + bd := &rukpakv1alpha1.BundleDeployment{} + err := cl.Get(ctx, types.NamespacedName{Name: opKey.Name}, bd) + Expect(err).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")) + }) + It("sets resolution success status", func() { + cond := apimeta.FindStatusCondition(operator.Status.Conditions, operatorsv1alpha1.TypeReady) + Expect(cond).NotTo(BeNil()) + Expect(cond.Status).To(Equal(metav1.ConditionTrue)) + Expect(cond.Reason).To(Equal(operatorsv1alpha1.ReasonResolutionSucceeded)) + Expect(cond.Message).To(Equal("resolution was successful")) + }) + }) + When("an out-of-date BundleDeployment exists", func() { + BeforeEach(func() { + By("creating the expected BD") + err := cl.Create(ctx, &rukpakv1alpha1.BundleDeployment{ + ObjectMeta: metav1.ObjectMeta{Name: opKey.Name}, + Spec: rukpakv1alpha1.BundleDeploymentSpec{ + ProvisionerClassName: "foo", + Template: &rukpakv1alpha1.BundleTemplate{ + Spec: rukpakv1alpha1.BundleSpec{ + ProvisionerClassName: "bar", + Source: rukpakv1alpha1.BundleSource{ + Type: rukpakv1alpha1.SourceTypeHTTP, + HTTP: &rukpakv1alpha1.HTTPSource{ + URL: "http://localhost:8080/", + }, + }, + }, + }, + }, + }) + Expect(err).NotTo(HaveOccurred()) + + 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()) + }) + It("results in the expected BundleDeployment", func() { + bd := &rukpakv1alpha1.BundleDeployment{} + err := cl.Get(ctx, types.NamespacedName{Name: opKey.Name}, bd) + Expect(err).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")) + }) + It("sets resolution success status", func() { + cond := apimeta.FindStatusCondition(operator.Status.Conditions, operatorsv1alpha1.TypeReady) + Expect(cond).NotTo(BeNil()) + Expect(cond.Status).To(Equal(metav1.ConditionTrue)) + Expect(cond.Reason).To(Equal(operatorsv1alpha1.ReasonResolutionSucceeded)) + Expect(cond.Message).To(Equal("resolution was successful")) + }) + }) + }) + When("the selected bundle's image ref cannot be parsed", func() { + const pkgName = "badimage" + BeforeEach(func() { + By("initializing cluster state") + operator = &operatorsv1alpha1.Operator{ + ObjectMeta: metav1.ObjectMeta{Name: opKey.Name}, + Spec: operatorsv1alpha1.OperatorSpec{PackageName: pkgName}, + } + err := cl.Create(ctx, operator) + Expect(err).NotTo(HaveOccurred()) + }) + PIt("sets resolution failure status and returns an error", func() { + By("running reconcile") + res, err := reconciler.Reconcile(ctx, ctrl.Request{NamespacedName: opKey}) + Expect(res).To(Equal(ctrl.Result{})) + Expect(err).To(MatchError(ContainSubstring(`error determining bundle path for entity`))) + + By("fetching updated operator after reconcile") + Expect(cl.Get(ctx, opKey, operator)).NotTo(HaveOccurred()) + + By("checking the expected conditions") + // TODO: there should be a condition update that sets Ready false in this scenario + }) + }) + When("the operator specifies a duplicate package", func() { + const pkgName = "prometheus" + BeforeEach(func() { + By("initializing cluster state") + err := cl.Create(ctx, &operatorsv1alpha1.Operator{ + ObjectMeta: metav1.ObjectMeta{Name: fmt.Sprintf("orig-%s", opKey.Name)}, + Spec: operatorsv1alpha1.OperatorSpec{PackageName: pkgName}, + }) + Expect(err).NotTo(HaveOccurred()) + + operator = &operatorsv1alpha1.Operator{ + ObjectMeta: metav1.ObjectMeta{Name: opKey.Name}, + Spec: operatorsv1alpha1.OperatorSpec{PackageName: pkgName}, + } + 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{})) + // TODO: should this scenario return an error? + 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.ConditionFalse)) + Expect(cond.Reason).To(Equal(operatorsv1alpha1.ReasonResolutionFailed)) + Expect(cond.Message).To(Equal(`duplicate identifier "required package prometheus" in input`)) + }) + }) + AfterEach(func() { + verifyInvariants(ctx, operator) + + err := cl.Delete(ctx, operator) + Expect(err).To(Not(HaveOccurred())) + }) + }) +}) + +func verifyInvariants(ctx context.Context, op *operatorsv1alpha1.Operator) { + key := client.ObjectKeyFromObject(op) + err := cl.Get(ctx, key, op) + Expect(err).To(BeNil()) + + verifyConditionsInvariants(op) +} + +func verifyConditionsInvariants(op *operatorsv1alpha1.Operator) { + // Expect that the operator's set of conditions contains all defined + // condition types for the Operator API. Every reconcile should always + // ensure every condition type's status/reason/message reflects the state + // read during _this_ reconcile call. + Expect(op.Status.Conditions).To(HaveLen(len(operatorutil.ConditionTypes))) + for _, t := range operatorutil.ConditionTypes { + cond := apimeta.FindStatusCondition(op.Status.Conditions, t) + Expect(cond).To(Not(BeNil())) + Expect(cond.Status).NotTo(BeEmpty()) + Expect(cond.Reason).To(BeElementOf(operatorutil.ConditionReasons)) + Expect(cond.ObservedGeneration).To(Equal(op.GetGeneration())) + } +} + +var testEntitySource = input.NewCacheQuerier(map[deppy.Identifier]input.Entity{ + "operatorhub/prometheus/0.37.0": *input.NewEntity("operatorhub/prometheus/0.37.0", map[string]string{ + "olm.bundle.path": `"quay.io/operatorhubio/prometheus@sha256:3e281e587de3d03011440685fc4fb782672beab044c1ebadc42788ce05a21c35"`, + "olm.channel": `{"channelName":"beta","priority":0}`, + "olm.package": `{"packageName":"prometheus","version":"0.37.0"}`, + "olm.gvk": `[]`, + }), + "operatorhub/prometheus/0.47.0": *input.NewEntity("operatorhub/prometheus/0.47.0", map[string]string{ + "olm.bundle.path": `"quay.io/operatorhubio/prometheus@sha256:5b04c49d8d3eff6a338b56ec90bdf491d501fe301c9cdfb740e5bff6769a21ed"`, + "olm.channel": `{"channelName":"beta","priority":0,"replaces":"prometheusoperator.0.37.0"}`, + "olm.package": `{"packageName":"prometheus","version":"0.47.0"}`, + "olm.gvk": `[]`, + }), + "operatorhub/badimage/0.1.0": *input.NewEntity("operatorhub/badimage/0.1.0", map[string]string{ + "olm.bundle.path": `{"name": "quay.io/operatorhubio/badimage:v0.1.0"}`, + "olm.package": `{"packageName":"badimage","version":"0.1.0"}`, + "olm.gvk": `[]`, + }), +}) diff --git a/controllers/suite_test.go b/controllers/suite_test.go index 8925bfcb8..556b0bc1c 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -17,42 +17,30 @@ limitations under the License. package controllers_test import ( - "context" - "fmt" "path/filepath" "testing" - "time" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - apimeta "k8s.io/apimachinery/pkg/api/meta" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/rand" - "k8s.io/client-go/kubernetes/scheme" + rukpakv1alpha1 "github.com/operator-framework/rukpak/api/v1alpha1" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/rest" - ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" operatorsv1alpha1 "github.com/operator-framework/operator-controller/api/v1alpha1" - "github.com/operator-framework/operator-controller/controllers" - "github.com/operator-framework/operator-controller/internal/resolution" - operatorutil "github.com/operator-framework/operator-controller/internal/util" - rukpakv1alpha1 "github.com/operator-framework/rukpak/api/v1alpha1" - //+kubebuilder:scaffold:imports ) // These tests use Ginkgo (BDD-style Go testing framework). Refer to // http://onsi.github.io/ginkgo/ to learn more about Ginkgo. var ( - cfg *rest.Config - k8sClient client.Client - testEnv *envtest.Environment - ctx context.Context - cancel context.CancelFunc + cfg *rest.Config + cl client.Client + sch *runtime.Scheme + testEnv *envtest.Environment ) func TestAPIs(t *testing.T) { @@ -77,123 +65,19 @@ var _ = BeforeSuite(func() { Expect(err).NotTo(HaveOccurred()) Expect(cfg).NotTo(BeNil()) - err = operatorsv1alpha1.AddToScheme(scheme.Scheme) + sch = runtime.NewScheme() + err = operatorsv1alpha1.AddToScheme(sch) Expect(err).NotTo(HaveOccurred()) - - err = rukpakv1alpha1.AddToScheme(scheme.Scheme) + err = rukpakv1alpha1.AddToScheme(sch) Expect(err).NotTo(HaveOccurred()) - //+kubebuilder:scaffold:scheme - - k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) + cl, err = client.New(cfg, client.Options{Scheme: sch}) Expect(err).NotTo(HaveOccurred()) - Expect(k8sClient).NotTo(BeNil()) - - k8sManager, err := ctrl.NewManager(cfg, ctrl.Options{ - Scheme: scheme.Scheme, - }) - Expect(err).ToNot(HaveOccurred()) - - err = controllers.NewOperatorReconciler( - k8sManager.GetClient(), - k8sManager.GetScheme(), - resolution.NewOperatorResolver(k8sManager.GetClient(), resolution.HardcodedEntitySource), - ).SetupWithManager(k8sManager) - Expect(err).ToNot(HaveOccurred()) - - ctx, cancel = context.WithCancel(context.Background()) - go func() { - defer GinkgoRecover() - err = k8sManager.Start(ctx) - Expect(err).ToNot(HaveOccurred(), "failed to run manager") - }() - + Expect(cl).NotTo(BeNil()) }) var _ = AfterSuite(func() { - cancel() By("tearing down the test environment") err := testEnv.Stop() Expect(err).NotTo(HaveOccurred()) }) - -var _ = Describe("Reconcile Test", func() { - const ( - timeout = time.Second * 10 - interval = time.Millisecond * 250 - ) - - When("an Operator is created", func() { - var ( - operator *operatorsv1alpha1.Operator - ctx context.Context - opName string - pkgName string - err error - ) - BeforeEach(func() { - ctx = context.Background() - opName = fmt.Sprintf("operator-test-%s", rand.String(8)) - pkgName = fmt.Sprintf("package-test-%s", rand.String(8)) - operator = &operatorsv1alpha1.Operator{ - ObjectMeta: metav1.ObjectMeta{ - Name: opName, - }, - Spec: operatorsv1alpha1.OperatorSpec{ - PackageName: pkgName, - }, - } - err = k8sClient.Create(ctx, operator) - Expect(err).To(Not(HaveOccurred())) - }) - AfterEach(func() { - err = k8sClient.Delete(ctx, operator) - Expect(err).To(Not(HaveOccurred())) - }) - It("has all Conditions created", func() { - op := &operatorsv1alpha1.Operator{} - opLookupKey := client.ObjectKey{Name: opName} - Eventually(func() bool { - err := k8sClient.Get(ctx, opLookupKey, op) - if err != nil { - return false - } - return len(op.Status.Conditions) > 0 - }, timeout, interval).Should(BeTrue()) - - // All defined condition Types MUST exist after reconciliation - conds := op.Status.Conditions - Expect(conds).To(Not(BeEmpty())) - Expect(conds).To(HaveLen(len(operatorutil.ConditionTypes))) - for _, t := range operatorutil.ConditionTypes { - Expect(apimeta.FindStatusCondition(conds, t)).To(Not(BeNil())) - } - }) - It("has matching generations in Conditions", func() { - op := &operatorsv1alpha1.Operator{} - - err = k8sClient.Get(ctx, client.ObjectKey{ - Name: opName, - }, op) - Expect(err).To(Not(HaveOccurred())) - - // The ObservedGeneration MUST match the resource generation after reconciliation - for _, c := range op.Status.Conditions { - Expect(c.ObservedGeneration).To(Equal(op.GetGeneration())) - } - }) - It("has only pre-defined Reasons", func() { - op := &operatorsv1alpha1.Operator{} - - err = k8sClient.Get(ctx, client.ObjectKey{ - Name: opName, - }, op) - Expect(err).To(Not(HaveOccurred())) - - // A given Reason MUST be in the list of ConditionReasons - for _, c := range op.Status.Conditions { - Expect(c.Reason).To(BeElementOf(operatorutil.ConditionReasons)) - } - }) - }) -}) diff --git a/main.go b/main.go index a11ae31c1..8e098cd0b 100644 --- a/main.go +++ b/main.go @@ -20,13 +20,11 @@ import ( "flag" "os" - // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) - // to ensure that exec-entrypoint and run can make use of them. - _ "k8s.io/client-go/plugin/pkg/client/auth" - + rukpakv1alpha1 "github.com/operator-framework/rukpak/api/v1alpha1" "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" + _ "k8s.io/client-go/plugin/pkg/client/auth" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/healthz" "sigs.k8s.io/controller-runtime/pkg/log/zap" @@ -34,8 +32,6 @@ import ( operatorsv1alpha1 "github.com/operator-framework/operator-controller/api/v1alpha1" "github.com/operator-framework/operator-controller/controllers" "github.com/operator-framework/operator-controller/internal/resolution" - rukpakv1alpha1 "github.com/operator-framework/rukpak/api/v1alpha1" - //+kubebuilder:scaffold:imports ) var ( @@ -92,11 +88,11 @@ func main() { os.Exit(1) } - if err = controllers.NewOperatorReconciler( - mgr.GetClient(), - mgr.GetScheme(), - resolution.NewOperatorResolver(mgr.GetClient(), resolution.HardcodedEntitySource), - ).SetupWithManager(mgr); err != nil { + if err = (&controllers.OperatorReconciler{ + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + Resolver: resolution.NewOperatorResolver(mgr.GetClient(), resolution.HardcodedEntitySource), + }).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "Operator") os.Exit(1) }