From 265eaa548738a961226558973f113ab08579cd33 Mon Sep 17 00:00:00 2001 From: Rashmi Gottipati Date: Tue, 1 Sep 2020 23:17:24 -0400 Subject: [PATCH] Refactor create/update for catalog source and registry pod --- .../operator/registry/index/registry_pod.go | 108 +++++++----------- .../registry/index/registry_pod_test.go | 62 +++++----- internal/olm/operator/registry/index_image.go | 98 +++++++++------- .../operator/registry/operator_installer.go | 33 +++--- 4 files changed, 144 insertions(+), 157 deletions(-) diff --git a/internal/olm/operator/registry/index/registry_pod.go b/internal/olm/operator/registry/index/registry_pod.go index f536094dbf..5ea9d01885 100644 --- a/internal/olm/operator/registry/index/registry_pod.go +++ b/internal/olm/operator/registry/index/registry_pod.go @@ -19,16 +19,20 @@ import ( "context" "errors" "fmt" + "path" "strings" "text/template" "time" + "github.com/operator-framework/api/pkg/operators/v1alpha1" + log "github.com/sirupsen/logrus" corev1 "k8s.io/api/core/v1" - k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/wait" - "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "github.com/operator-framework/operator-sdk/internal/olm/operator" "github.com/operator-framework/operator-sdk/internal/util/k8sutil" ) @@ -71,21 +75,17 @@ type RegistryPod struct { // if an index image is provided, the existing registry DB is located at /database/index.db DBPath string - // Namespace refers to the specific namespace in which the registry pod will be created and scoped to - Namespace string - // GRPCPort is the container grpc port GRPCPort int32 - // client refers to a controller runtime client - client client.Client - // pod represents a kubernetes *corev1.pod that will be created on a cluster using an index image pod *corev1.Pod + + cfg *operator.Configuration } // NewRegistryPod initializes the RegistryPod struct and sets defaults for empty fields -func NewRegistryPod(client client.Client, dbPath, bundleImage, namespace string) (*RegistryPod, error) { +func NewRegistryPod(cfg *operator.Configuration, dbPath, bundleImage string) (*RegistryPod, error) { rp := &RegistryPod{} if rp.GRPCPort == 0 { @@ -104,76 +104,63 @@ func NewRegistryPod(client client.Client, dbPath, bundleImage, namespace string) } } - rp.client = client + rp.cfg = cfg rp.DBPath = dbPath rp.BundleImage = bundleImage - rp.Namespace = namespace // validate the RegistryPod struct and ensure required fields are set if err := rp.validate(); err != nil { - return nil, fmt.Errorf("error in validating registry pod struct: %v", err) + return nil, fmt.Errorf("error validating registry pod struct: %v", err) } - // call podForBundleRegistry() to make the pod definition + // podForBundleRegistry() to make the pod definition pod, err := rp.podForBundleRegistry() if err != nil { - return nil, fmt.Errorf("error in building registry pod definition: %v", err) + return nil, fmt.Errorf("error building registry pod definition: %v", err) } rp.pod = pod return rp, nil } -// Create creates a bundle registry pod built from an index image -// and returns error -func (rp *RegistryPod) Create(ctx context.Context) error { +// Create creates a bundle registry pod built from an index image, +// sets the catalog source as the owner for the pod and verifies that +// the pod is running +func (rp *RegistryPod) Create(ctx context.Context, cs *v1alpha1.CatalogSource) (*corev1.Pod, error) { if rp.pod == nil { - return errPodNotInit - } - - podKey, err := client.ObjectKeyFromObject(rp.pod) - if err != nil { - return fmt.Errorf("error in getting object key from the registry pod name %s: %v", rp.pod.Name, err) + return nil, errPodNotInit } - if err := rp.client.Get(ctx, podKey, rp.pod); err != nil { - if k8serrors.IsNotFound(err) { - if err = rp.client.Create(ctx, rp.pod); err != nil { - return fmt.Errorf("error creating registry pod: %v", err) - } - } else { - return fmt.Errorf("registry pod name %s already exists: %v", rp.pod.Name, err) - } + // make catalog source the owner of registry pod object + if err := controllerutil.SetOwnerReference(cs, rp.pod, rp.cfg.Scheme); err != nil { + return nil, fmt.Errorf("set registry pod owner reference: %v", err) } - return nil -} -// VerifyPodRunning calls checkPodStatus to verify pod status -// and returns error if pod is not running -func (rp *RegistryPod) VerifyPodRunning(ctx context.Context) error { - if rp.pod == nil { - return errPodNotInit + if err := rp.cfg.Client.Create(ctx, rp.pod); err != nil { + return nil, fmt.Errorf("create registry pod: %v", err) } - podKey, err := client.ObjectKeyFromObject(rp.pod) - if err != nil { - return fmt.Errorf("error in getting object key from the registry pod name %s: %v", rp.pod.Name, err) + // get registry pod key + podKey := types.NamespacedName{ + Namespace: rp.cfg.Namespace, + Name: getPodName(rp.BundleImage), } - // upon creation of new pod, poll and verify that pod status is running + // poll and verify that pod is running podCheck := wait.ConditionFunc(func() (done bool, err error) { - err = rp.client.Get(ctx, podKey, rp.pod) + err = rp.cfg.Client.Get(ctx, podKey, rp.pod) if err != nil { return false, fmt.Errorf("error getting pod %s: %w", rp.pod.Name, err) } return rp.pod.Status.Phase == corev1.PodRunning, nil }) - // check pod status to be Running + // check pod status to be `Running` if err := rp.checkPodStatus(ctx, podCheck); err != nil { - return fmt.Errorf("registry pod did not become ready: %w", err) + return nil, fmt.Errorf("registry pod did not become ready: %w", err) } - return nil + log.Infof("Successfully created registry pod: %s", rp.pod.Name) + return rp.pod, nil } // checkPodStatus polls and verifies that the pod status is running @@ -197,10 +184,6 @@ func (rp *RegistryPod) validate() error { return errors.New("registry database path cannot be empty") } - if len(strings.TrimSpace(rp.Namespace)) < 1 { - return errors.New("pod namespace cannot be empty") - } - if len(strings.TrimSpace(rp.BundleAddMode)) < 1 { return errors.New("bundle add mode cannot be empty") } @@ -230,14 +213,14 @@ func (rp *RegistryPod) podForBundleRegistry() (*corev1.Pod, error) { // construct the container command for pod spec containerCmd, err := rp.getContainerCmd() if err != nil { - return nil, fmt.Errorf("error in parsing container command: %v", err) + return nil, fmt.Errorf("error parsing container command: %v", err) } // make the pod definition rp.pod = &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ Name: getPodName(rp.BundleImage), - Namespace: rp.Namespace, + Namespace: rp.cfg.Namespace, }, Spec: corev1.PodSpec{ Containers: []corev1.Container{ @@ -263,7 +246,7 @@ func (rp *RegistryPod) podForBundleRegistry() (*corev1.Pod, error) { // getContainerCmd uses templating to construct the container command // and throws error if unable to parse and execute the container command func (rp *RegistryPod) getContainerCmd() (string, error) { - const containerCommand = "/bin/mkdir -p {{ .DBPath }} &&" + + const containerCommand = "/bin/mkdir -p {{ .DBPath | dirname }} &&" + "/bin/opm registry add -d {{ .DBPath }} -b {{.BundleImage}} --mode={{.BundleAddMode}} &&" + "/bin/opm registry serve -d {{ .DBPath }} -p {{.GRPCPort}}" type bundleCmd struct { @@ -276,23 +259,20 @@ func (rp *RegistryPod) getContainerCmd() (string, error) { out := &bytes.Buffer{} - // add the custom basename template function to the + // create a custom dirname template function + funcMap := template.FuncMap{ + "dirname": path.Dir, + } + + // add the custom dirname template function to the // template's FuncMap and parse the containerCommand - tmp := template.Must(template.New("containerCommand").Parse(containerCommand)) + tmp := template.Must(template.New("containerCommand").Funcs(funcMap).Parse(containerCommand)) // execute the command by applying the parsed tmp to command // and write command output to out if err := tmp.Execute(out, command); err != nil { - return "", fmt.Errorf("error in parsing container command: %w", err) + return "", fmt.Errorf("parse container command: %w", err) } return out.String(), nil } - -// GetPod returns the registry pod -func (rp *RegistryPod) GetPod() (*corev1.Pod, error) { - if rp == nil { - return nil, errPodNotInit - } - return rp.pod, nil -} diff --git a/internal/olm/operator/registry/index/registry_pod_test.go b/internal/olm/operator/registry/index/registry_pod_test.go index 3077930ffe..149d7fb5c5 100644 --- a/internal/olm/operator/registry/index/registry_pod_test.go +++ b/internal/olm/operator/registry/index/registry_pod_test.go @@ -22,6 +22,8 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + "github.com/operator-framework/api/pkg/operators/v1alpha1" + "github.com/operator-framework/operator-sdk/internal/olm/operator" "k8s.io/apimachinery/pkg/util/wait" "sigs.k8s.io/controller-runtime/pkg/client" @@ -44,15 +46,20 @@ var _ = Describe("RegistryPod", func() { Context("with valid registry pod values", func() { expectedPodName := "quay-io-example-example-operator-bundle-0-2-0" - expectedOutput := "/bin/mkdir -p /database/index.db &&" + + expectedOutput := "/bin/mkdir -p /database &&" + "/bin/opm registry add -d /database/index.db -b quay.io/example/example-operator-bundle:0.2.0 --mode=semver &&" + "/bin/opm registry serve -d /database/index.db -p 50051" var rp *RegistryPod + var cfg *operator.Configuration var err error BeforeEach(func() { - rp, err = NewRegistryPod(newFakeClient(), "/database/index.db", "quay.io/example/example-operator-bundle:0.2.0", "default") + cfg = &operator.Configuration{ + Client: newFakeClient(), + Namespace: "test-default", + } + rp, err = NewRegistryPod(cfg, "/database/index.db", "quay.io/example/example-operator-bundle:0.2.0") Expect(err).To(BeNil()) }) @@ -65,7 +72,7 @@ var _ = Describe("RegistryPod", func() { It("should create the RegistryPod successfully", func() { Expect(rp).NotTo(BeNil()) Expect(rp.pod.Name).To(Equal(expectedPodName)) - Expect(rp.pod.Namespace).To(Equal(rp.Namespace)) + Expect(rp.pod.Namespace).To(Equal(rp.cfg.Namespace)) Expect(rp.pod.Spec.Containers[0].Name).To(Equal(defaultContainerName)) if len(rp.pod.Spec.Containers) > 0 { if len(rp.pod.Spec.Containers[0].Ports) > 0 { @@ -86,7 +93,7 @@ var _ = Describe("RegistryPod", func() { Expect(rp.pod).NotTo(BeNil()) Expect(rp.pod.Name).To(Equal(expectedPodName)) - Expect(rp.pod.Namespace).To(Equal(rp.Namespace)) + Expect(rp.pod.Namespace).To(Equal(rp.cfg.Namespace)) Expect(rp.pod.Spec.Containers[0].Name).To(Equal(defaultContainerName)) if len(rp.pod.Spec.Containers) > 0 { if len(rp.pod.Spec.Containers[0].Ports) > 0 { @@ -95,12 +102,6 @@ var _ = Describe("RegistryPod", func() { } }) - It("should create registry pod successfully", func() { - err := rp.Create(context.Background()) - - Expect(err).To(BeNil()) - }) - It("check pod status should return successfully when pod check is true", func() { mockGoodPodCheck := wait.ConditionFunc(func() (done bool, err error) { return true, nil @@ -113,22 +114,18 @@ var _ = Describe("RegistryPod", func() { }) Context("with invalid registry pod values", func() { + var cfg *operator.Configuration + BeforeEach(func() { + cfg = &operator.Configuration{ + Client: newFakeClient(), + Namespace: "test-default", + } + }) It("should error when bundle image is not provided", func() { expectedErr := "bundle image cannot be empty" - _, err := NewRegistryPod(newFakeClient(), "/database/index.db", - "", "default") - - Expect(err).NotTo(BeNil()) - Expect(err.Error()).Should(ContainSubstring(expectedErr)) - }) - - It("should not create a registry pod when namespace is not provided", func() { - expectedErr := "namespace cannot be empty" - - _, err := NewRegistryPod(newFakeClient(), "/database/index.db", - "quay.io/example/example-operator-bundle:0.2.0", "") + _, err := NewRegistryPod(cfg, "/database/index.db", "") Expect(err).NotTo(BeNil()) Expect(err.Error()).Should(ContainSubstring(expectedErr)) @@ -137,8 +134,8 @@ var _ = Describe("RegistryPod", func() { It("should not create a registry pod when database path is not provided", func() { expectedErr := "registry database path cannot be empty" - _, err := NewRegistryPod(newFakeClient(), "", - "quay.io/example/example-operator-bundle:0.2.0", "default") + _, err := NewRegistryPod(cfg, "", + "quay.io/example/example-operator-bundle:0.2.0") Expect(err).NotTo(BeNil()) Expect(err.Error()).Should(ContainSubstring(expectedErr)) @@ -147,8 +144,8 @@ var _ = Describe("RegistryPod", func() { It("should not create a registry pod when bundle add mode is empty", func() { expectedErr := "bundle add mode cannot be empty" - rp, _ := NewRegistryPod(newFakeClient(), "/database/index.db", - "quay.io/example/example-operator-bundle:0.2.0", "default") + rp, _ := NewRegistryPod(cfg, "/database/index.db", + "quay.io/example/example-operator-bundle:0.2.0") rp.BundleAddMode = "" err := rp.validate() @@ -159,8 +156,8 @@ var _ = Describe("RegistryPod", func() { It("should not accept any other bundle add mode other than semver or replaces", func() { expectedErr := "invalid bundle mode" - rp, _ := NewRegistryPod(newFakeClient(), "/database/index.db", - "quay.io/example/example-operator-bundle:0.2.0", "default") + rp, _ := NewRegistryPod(cfg, "/database/index.db", + "quay.io/example/example-operator-bundle:0.2.0") rp.BundleAddMode = "invalid" err := rp.validate() @@ -169,8 +166,8 @@ var _ = Describe("RegistryPod", func() { }) It("checkPodStatus should return error when pod check is false and context is done", func() { - rp, _ := NewRegistryPod(newFakeClient(), "/database/index.db", - "quay.io/example/example-operator-bundle:0.2.0", "default") + rp, _ := NewRegistryPod(cfg, "/database/index.db", + "quay.io/example/example-operator-bundle:0.2.0") mockBadPodCheck := wait.ConditionFunc(func() (done bool, err error) { return false, fmt.Errorf("error waiting for registry pod") @@ -189,13 +186,14 @@ var _ = Describe("RegistryPod", func() { It("Create should fail when registry pod is not initialized", func() { rp := RegistryPod{} - err := rp.Create(context.Background()) + cs := &v1alpha1.CatalogSource{} + pod, err := rp.Create(context.Background(), cs) Expect(err).NotTo(BeNil()) + Expect(pod).To(BeNil()) Expect(err).To(MatchError(errPodNotInit)) }) - // todo(rashmigottipati): add test to check VerifyPodRunning returning error }) }) }) diff --git a/internal/olm/operator/registry/index_image.go b/internal/olm/operator/registry/index_image.go index e880885f8c..704afc83b0 100644 --- a/internal/olm/operator/registry/index_image.go +++ b/internal/olm/operator/registry/index_image.go @@ -18,10 +18,11 @@ import ( "context" "encoding/json" "fmt" - "strings" "github.com/operator-framework/api/pkg/operators/v1alpha1" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/util/retry" "github.com/operator-framework/operator-sdk/internal/olm/operator" "github.com/operator-framework/operator-sdk/internal/olm/operator/registry/index" @@ -50,40 +51,24 @@ func (c IndexImageCatalogCreator) CreateCatalog(ctx context.Context, name string return nil, fmt.Errorf("get database path: %v", err) } - fmt.Printf("IndexImageCatalogCreator.IndexImage: %q\n", c.IndexImage) - fmt.Printf("IndexImageCatalogCreator.IndexImageDBPath: %v\n", dbPath) - fmt.Printf("IndexImageCatalogCreator.InjectBundles: %q\n", strings.Join(c.InjectBundles, ",")) - fmt.Printf("IndexImageCatalogCreator.InjectBundleMode: %q\n", c.InjectBundleMode) - // create a basic catalog source type cs := newCatalogSource(name, c.cfg.Namespace, withSDKPublisher(c.PackageName)) - // initialize and create the registry pod with provided index image - registryPod, err := c.createRegistryPod(ctx, dbPath) - if err != nil { - return nil, fmt.Errorf("error in creating registry pod: %v", err) + // create catalog source resource + if err := c.cfg.Client.Create(ctx, cs); err != nil { + return nil, fmt.Errorf("error creating catalog source: %v", err) } - // get registry pod i.e corev1.Pod type - pod, err := registryPod.GetPod() + // create registry pod + pod, err := c.createRegistryPod(ctx, dbPath, cs) if err != nil { - return nil, fmt.Errorf("error in getting registry pod: %v", err) - } - - // make catalog source the owner of registry pod object - if err := controllerutil.SetOwnerReference(cs, pod, c.cfg.Scheme); err != nil { - return nil, fmt.Errorf("error in setting registry pod owner reference: %v", err) - } - - // wait for registry pod to be running - if err := registryPod.VerifyPodRunning(ctx); err != nil { - return nil, fmt.Errorf("registry pod is not running: %v", err) + return nil, fmt.Errorf("error creating registry pod: %v", err) } // update catalog source with source type, address and annotations - if err := c.updateCatalogSource(pod.Status.PodIP, cs); err != nil { - return nil, fmt.Errorf("error in updating catalog source: %v", err) + if err := c.updateCatalogSource(ctx, pod.Status.PodIP, cs); err != nil { + return nil, fmt.Errorf("error updating catalog source: %v", err) } return cs, nil @@ -102,36 +87,65 @@ func (c IndexImageCatalogCreator) getDBPath(ctx context.Context) (string, error) return defaultDBPath, nil } -func (c IndexImageCatalogCreator) createRegistryPod(ctx context.Context, dbPath string) (*index.RegistryPod, error) { - // Create registry pod, assigning its owner as the catalog source - registryPod, err := index.NewRegistryPod(c.cfg.Client, dbPath, c.BundleImage, c.cfg.Namespace) +func (c IndexImageCatalogCreator) createRegistryPod(ctx context.Context, dbPath string, cs *v1alpha1.CatalogSource) (*corev1.Pod, error) { + // Initialize registry pod + registryPod, err := index.NewRegistryPod(c.cfg, dbPath, c.BundleImage) if err != nil { - return nil, fmt.Errorf("error in initializing registry pod") + return nil, fmt.Errorf("error initializing registry pod: %v", err) } - if err = registryPod.Create(ctx); err != nil { - return nil, fmt.Errorf("error in creating registry pod") + var pod *corev1.Pod + // Create registry pod + if pod, err = registryPod.Create(ctx, cs); err != nil { + return nil, fmt.Errorf("error creating registry pod: %v", err) } - return registryPod, nil + return pod, nil } -func (c IndexImageCatalogCreator) updateCatalogSource(podAddr string, cs *v1alpha1.CatalogSource) error { - // Update catalog source with source type as grpc and address to point to the pod IP - cs.Spec.SourceType = v1alpha1.SourceTypeGrpc - cs.Spec.Address = index.GetRegistryPodHost(podAddr) - - // Update catalog source with annotations for index image, - // injected bundle, and registry add mode +func (c IndexImageCatalogCreator) updateCatalogSource(ctx context.Context, podAddr string, cs *v1alpha1.CatalogSource) error { + // JSON marshal injected bundles injectedBundlesJSON, err := json.Marshal(c.InjectBundles) if err != nil { - return fmt.Errorf("error in json marshal injected bundles: %v", err) + return fmt.Errorf("error marshaling injected bundles: %v", err) + } + + // Get catalog source key + catsrcKey := types.NamespacedName{ + Namespace: cs.GetNamespace(), + Name: cs.GetName(), } - cs.ObjectMeta.Annotations = map[string]string{ + + // Annotations for catalog source + annotationMapping := map[string]string{ "operators.operatorframework.io/index-image": c.IndexImage, "operators.operatorframework.io/inject-bundle-mode": c.InjectBundleMode, "operators.operatorframework.io/injected-bundles": string(injectedBundlesJSON), } + // Update catalog source with source type as grpc and address as the pod IP, + // and annotations for index image, injected bundles, and registry bundle add mode + if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { + if err := c.cfg.Client.Get(ctx, catsrcKey, cs); err != nil { + return fmt.Errorf("error getting catalog source: %v", err) + } + cs.Spec.Address = index.GetRegistryPodHost(podAddr) + cs.Spec.SourceType = v1alpha1.SourceTypeGrpc + annotations := cs.GetAnnotations() + if annotations == nil { + annotations = make(map[string]string, len(annotationMapping)) + } + for k, v := range annotationMapping { + annotations[k] = v + } + cs.SetAnnotations(annotations) + + if err := c.cfg.Client.Update(ctx, cs); err != nil { + return err + } + return nil + }); err != nil { + return fmt.Errorf("error setting grpc source type and address for catalog source: %v", err) + } return nil } diff --git a/internal/olm/operator/registry/operator_installer.go b/internal/olm/operator/registry/operator_installer.go index 92e1a95bb3..44c3868aba 100644 --- a/internal/olm/operator/registry/operator_installer.go +++ b/internal/olm/operator/registry/operator_installer.go @@ -49,26 +49,20 @@ func NewOperatorInstaller(cfg *operator.Configuration) *OperatorInstaller { } func (o OperatorInstaller) InstallOperator(ctx context.Context) (*v1alpha1.ClusterServiceVersion, error) { - log.Info("Creating CatalogSource") cs, err := o.CatalogCreator.CreateCatalog(ctx, o.CatalogSourceName) if err != nil { return nil, fmt.Errorf("create catalog: %v", err) } + log.Infof("Created CatalogSource: %s", cs.GetName()) // TODO: OLM doesn't appear to propagate the "READY" connection status to the catalogsource in a timely manner - // even though its catalog-operator reports a connection almost immediately. This condition either needs to - // be propagated more quickly by OLM or we need to find a different resource to probe for readiness. - // + // even though its catalog-operator reports a connection almost immediately. This condition either needs + // to be propagated more quickly by OLM or we need to find a different resource to probe for readiness. + // wait for catalog source to be ready // if err := o.waitForCatalogSource(ctx, cs); err != nil { // return nil, err // } - log.Infof("OperatorInstaller.CatalogSourceName: %q\n", o.CatalogSourceName) - log.Infof("OperatorInstaller.PackageName: %q\n", o.PackageName) - log.Infof("OperatorInstaller.StartingCSV: %q\n", o.StartingCSV) - log.Infof("OperatorInstaller.Channel: %q\n", o.Channel) - log.Infof("OperatorInstaller.InstallMode: %q\n", o.InstallMode) - // Ensure Operator Group if err = o.createOperatorGroup(ctx); err != nil { return nil, err @@ -105,7 +99,7 @@ func (o OperatorInstaller) InstallOperator(ctx context.Context) (*v1alpha1.Clust func (o OperatorInstaller) waitForCatalogSource(ctx context.Context, cs *v1alpha1.CatalogSource) error { catSrcKey, err := client.ObjectKeyFromObject(cs) if err != nil { - return fmt.Errorf("error in getting catalog source key: %v", err) + return fmt.Errorf("error getting catalog source key: %v", err) } // verify that catalog source connection status is READY @@ -114,12 +108,9 @@ func (o OperatorInstaller) waitForCatalogSource(ctx context.Context, cs *v1alpha return false, err } if cs.Status.GRPCConnectionState != nil { - fmt.Println("grpc connection state:", cs.Status.GRPCConnectionState.LastObservedState) if cs.Status.GRPCConnectionState.LastObservedState == "READY" { return true, nil } - } else { - fmt.Println("grpc connection state: ") } return false, nil }) @@ -167,10 +158,11 @@ func (o OperatorInstaller) createOperatorGroup(ctx context.Context) error { // New SDK-managed OperatorGroup. og = newSDKOperatorGroup(o.cfg.Namespace, withTargetNamespaces(targetNamespaces...)) - log.Info("Creating OperatorGroup") if err = o.cfg.Client.Create(ctx, og); err != nil { return fmt.Errorf("error creating OperatorGroup: %w", err) } + log.Infof("Created OperatorGroup: %s", og.GetName()) + } return nil } @@ -202,10 +194,11 @@ func (o OperatorInstaller) createSubscription(ctx context.Context, cs *v1alpha1. withCatalogSource(cs.GetName(), o.cfg.Namespace), withInstallPlanApproval(v1alpha1.ApprovalManual)) - log.Info("Creating Subscription") if err := o.cfg.Client.Create(ctx, sub); err != nil { return nil, fmt.Errorf("error creating subscription: %w", err) } + log.Infof("Created Subscription: %s", sub.Name) + return sub, nil } @@ -221,7 +214,7 @@ func (o OperatorInstaller) getInstalledCSV(ctx context.Context) (*v1alpha1.Clust Name: o.StartingCSV, Namespace: o.cfg.Namespace, } - log.Printf("Waiting for ClusterServiceVersion %q to reach 'Succeeded' phase", nn) + log.Infof("Waiting for ClusterServiceVersion %q to reach 'Succeeded' phase", nn) if err = c.DoCSVWait(ctx, nn); err != nil { return nil, fmt.Errorf("error waiting for CSV to install: %w", err) } @@ -246,18 +239,20 @@ func (o OperatorInstaller) approveInstallPlan(ctx context.Context, sub *v1alpha1 if err := retry.RetryOnConflict(retry.DefaultBackoff, func() error { if err := o.cfg.Client.Get(ctx, ipKey, &ip); err != nil { - return fmt.Errorf("error in getting install plan: %v", err) + return fmt.Errorf("error getting install plan: %v", err) } // approve the install plan by setting Approved to true ip.Spec.Approved = true if err := o.cfg.Client.Update(ctx, &ip); err != nil { - return fmt.Errorf("error in approving install plan: %v", err) + return fmt.Errorf("error approving install plan: %v", err) } return nil }); err != nil { return err } + log.Infof("Approved InstallPlan %s for the Subscription: %s", ipKey.Name, sub.Name) + return nil }