diff --git a/pkg/operator/ceph/object/cosi/controller.go b/pkg/operator/ceph/object/cosi/controller.go index a11838bf7..b57c8ef0a 100644 --- a/pkg/operator/ceph/object/cosi/controller.go +++ b/pkg/operator/ceph/object/cosi/controller.go @@ -118,11 +118,17 @@ func (r *ReconcileCephCOSIDriver) Reconcile(context context.Context, request rec func (r *ReconcileCephCOSIDriver) reconcile(request reconcile.Request) (reconcile.Result, cephv1.CephCOSIDriver, error) { cephCOSIDriver := &cephv1.CephCOSIDriver{} - // Fetch the CephCOSIDriver instance - err := r.client.Get(r.opManagerContext, request.NamespacedName, cephCOSIDriver) - logger.Debugf("CephCOSIDriver: %+v", cephCOSIDriver) + // Check No of instances of CephCOSIDriver + cephCOSIDriverList := &cephv1.CephCOSIDriverList{} + err := r.client.List(r.opManagerContext, cephCOSIDriverList) if err != nil && client.IgnoreNotFound(err) != nil { - return reconcile.Result{}, *cephCOSIDriver, errors.Wrapf(err, "failed to get Ceph COSI Driver %s", request.NamespacedName) + return reconcile.Result{}, *cephCOSIDriver, errors.Wrap(err, "failed to list CephCOSIDriver") + } + if len(cephCOSIDriverList.Items) > 1 { + return reconcile.Result{}, *cephCOSIDriver, errors.New("more than one instance of CephCOSIDriver found") + } else if len(cephCOSIDriverList.Items) == 1 { + cephCOSIDriver = &cephCOSIDriverList.Items[0] + logger.Debugf("CephCOSIDriver: %+v", cephCOSIDriver) } // While in experimental mode, the COSI driver is not enabled by default @@ -157,9 +163,9 @@ func (r *ReconcileCephCOSIDriver) reconcile(request reconcile.Request) (reconcil cephCOSIDriver.Name = CephCOSIDriverName } - // Set the default CephCOSIDriver namespace if not already set - if cephCOSIDriver.Namespace == "" { - cephCOSIDriver.Namespace = os.Getenv(k8sutil.PodNamespaceEnvVar) + // The ceph-cosi-driver CRD should be same namespace as the operator + if cephCOSIDriver.Namespace != os.Getenv(k8sutil.PodNamespaceEnvVar) { + return reconcile.Result{}, *cephCOSIDriver, errors.New("Ceph COSI Driver namespace must be same as operator") } // Check whether object store is running diff --git a/pkg/operator/ceph/object/cosi/controller_test.go b/pkg/operator/ceph/object/cosi/controller_test.go index ec6761e3c..6b4e9eba7 100644 --- a/pkg/operator/ceph/object/cosi/controller_test.go +++ b/pkg/operator/ceph/object/cosi/controller_test.go @@ -255,4 +255,60 @@ func TestCephCOSIDriverController(t *testing.T) { assert.NoError(t, err) assert.Equal(t, "quay.io/ceph/cosi:custom", cephCOSIDriverDeployment.Spec.Template.Spec.Containers[0].Image) }) + + t.Run("ceph cosi driver CRD with custom namespace", func(t *testing.T) { + cephCOSIDriver := &cephv1.CephCOSIDriver{ + ObjectMeta: metav1.ObjectMeta{ + Name: CephCOSIDriverName, + Namespace: "custom-namespace", + }, + Spec: cephv1.CephCOSIDriverSpec{ + Image: "quay.io/ceph/cosi:custom", + DeploymentStrategy: cephv1.COSIDeploymentStrategyAuto, + }, + } + r := setupNewEnvironment(cephCOSIDriver) + req := reconcile.Request{ + NamespacedName: types.NamespacedName{ + Name: CephCOSIDriverName, + Namespace: "custom-namespace", + }, + } + res, err := r.Reconcile(ctx, req) + assert.Error(t, err) + assert.Equal(t, false, res.Requeue) + }) + + t.Run("multiple ceph cosi driver CRDs", func(t *testing.T) { + cephCOSIDriver1 := &cephv1.CephCOSIDriver{ + ObjectMeta: metav1.ObjectMeta{ + Name: "ceph-cosi-driver-1", + Namespace: namespace, + }, + Spec: cephv1.CephCOSIDriverSpec{ + Image: "quay.io/ceph/cosi:custom", + DeploymentStrategy: cephv1.COSIDeploymentStrategyAuto, + }, + } + cephCOSIDriver2 := &cephv1.CephCOSIDriver{ + ObjectMeta: metav1.ObjectMeta{ + Name: "ceph-cosi-driver-2", + Namespace: namespace, + }, + Spec: cephv1.CephCOSIDriverSpec{ + Image: "quay.io/ceph/cosi:custom", + DeploymentStrategy: cephv1.COSIDeploymentStrategyAuto, + }, + } + r := setupNewEnvironment(cephCOSIDriver1, cephCOSIDriver2) + req := reconcile.Request{ + NamespacedName: types.NamespacedName{ + Name: "ceph-cosi-driver-1", + Namespace: namespace, + }, + } + res, err := r.Reconcile(ctx, req) + assert.Error(t, err) + assert.Equal(t, false, res.Requeue) + }) }