From ebbf332d8dbf1cbf82c9e591fc0fb59d430fa7c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Han?= Date: Thu, 21 Jan 2021 18:56:22 +0100 Subject: [PATCH] ceph: update rgw and mds deployment for logCollector MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the CephCluster CR spec is updated to activate the logCollector, we must reflect that change onto child CRDs, like the mds and rgw since their configurationn would be impacted too. Now we watch for the CephCluster object changes from the object/file controllers and react upon the appropriate event. Closes: https://github.com/rook/rook/issues/7022 Signed-off-by: Sébastien Han --- pkg/operator/ceph/cluster/controller.go | 6 +-- pkg/operator/ceph/cluster/rbd/controller.go | 19 ++++++++ pkg/operator/ceph/controller/predicate.go | 53 +++++++++++++++++++++ pkg/operator/ceph/file/controller.go | 19 ++++++++ pkg/operator/ceph/object/controller.go | 19 ++++++++ 5 files changed, 113 insertions(+), 3 deletions(-) diff --git a/pkg/operator/ceph/cluster/controller.go b/pkg/operator/ceph/cluster/controller.go index 35b6b1c70..c3264a0cc 100644 --- a/pkg/operator/ceph/cluster/controller.go +++ b/pkg/operator/ceph/cluster/controller.go @@ -165,7 +165,7 @@ func add(mgr manager.Manager, r reconcile.Reconciler, context *clusterd.Context) // Build Handler function to return the list of ceph clusters // This is used by the watchers below - handerFunc, err := opcontroller.ObjectToCRMapper(mgr.GetClient(), &cephv1.CephClusterList{}, mgr.GetScheme()) + handlerFunc, err := opcontroller.ObjectToCRMapper(mgr.GetClient(), &cephv1.CephClusterList{}, mgr.GetScheme()) if err != nil { return err } @@ -180,7 +180,7 @@ func add(mgr manager.Manager, r reconcile.Reconciler, context *clusterd.Context) }, }, }, - handler.EnqueueRequestsFromMapFunc(handerFunc), + handler.EnqueueRequestsFromMapFunc(handlerFunc), predicateForNodeWatcher(mgr.GetClient(), context)) if err != nil { return err @@ -200,7 +200,7 @@ func add(mgr manager.Manager, r reconcile.Reconciler, context *clusterd.Context) }, }, }, - handler.EnqueueRequestsFromMapFunc(handerFunc), + handler.EnqueueRequestsFromMapFunc(handlerFunc), predicateForHotPlugCMWatcher(mgr.GetClient())) if err != nil { return err diff --git a/pkg/operator/ceph/cluster/rbd/controller.go b/pkg/operator/ceph/cluster/rbd/controller.go index 4e0936b91..3feccf381 100644 --- a/pkg/operator/ceph/cluster/rbd/controller.go +++ b/pkg/operator/ceph/cluster/rbd/controller.go @@ -128,6 +128,25 @@ func add(mgr manager.Manager, r reconcile.Reconciler) error { } } + // Build Handler function to return the list of ceph rbd-mirror + // This is used by the watchers below + handlerFunc, err := opcontroller.ObjectToCRMapper(mgr.GetClient(), &cephv1.CephRBDMirrorList{}, mgr.GetScheme()) + if err != nil { + return err + } + + // Watch for CephCluster Spec changes that we want to propagate to us + err = c.Watch(&source.Kind{Type: &cephv1.CephCluster{ + TypeMeta: metav1.TypeMeta{ + Kind: opcontroller.ClusterResource.Kind, + APIVersion: opcontroller.ClusterResource.APIVersion, + }, + }, + }, handler.EnqueueRequestsFromMapFunc(handlerFunc), opcontroller.WatchCephClusterPredicate()) + if err != nil { + return err + } + return nil } diff --git a/pkg/operator/ceph/controller/predicate.go b/pkg/operator/ceph/controller/predicate.go index da6f0e338..e2fe3938b 100644 --- a/pkg/operator/ceph/controller/predicate.go +++ b/pkg/operator/ceph/controller/predicate.go @@ -295,6 +295,59 @@ func WatchControllerPredicate() predicate.Funcs { } } +// WatchCephClusterPredicate is a predicate used by child controllers such as Filesystem or Object +// It watch for CR changes on the CephCluster object and reconciles if this needs to be propagated +// For instance the logCollector option from the CephCluster spec affects the configuration of rgw pods +// So if it changes we must update the deployment +func WatchCephClusterPredicate() predicate.Funcs { + return predicate.Funcs{ + CreateFunc: func(e event.CreateEvent) bool { + logger.Debug("create event from a CR") + return true + }, + DeleteFunc: func(e event.DeleteEvent) bool { + logger.Debug("delete event from a CR") + return true + }, + UpdateFunc: func(e event.UpdateEvent) bool { + logger.Debug("update event from a CR") + // resource.Quantity has non-exportable fields, so we use its comparator method + resourceQtyComparer := cmp.Comparer(func(x, y resource.Quantity) bool { return x.Cmp(y) == 0 }) + + switch objOld := e.ObjectOld.(type) { + case *cephv1.CephCluster: + objNew := e.ObjectNew.(*cephv1.CephCluster) + logger.Debug("update event on CephCluster CR") + // If the labels "do_not_reconcile" is set on the object, let's not reconcile that request + isDoNotReconcile := IsDoNotReconcile(objNew.GetLabels()) + if isDoNotReconcile { + logger.Debugf("object %q matched on update but %q label is set, doing nothing", DoNotReconcileLabelName, objNew.Name) + return false + } + diff := cmp.Diff(objOld.Spec, objNew.Spec, resourceQtyComparer) + if diff != "" { + // The image change (upgrade) is being taking care by watchControllerPredicate() in the cluster package + if objOld.Spec.CephVersion.Image != objNew.Spec.CephVersion.Image { + return false + } + // If the log collector setting changes let's reconcile the child controllers + if !cmp.Equal(objOld.Spec.LogCollector, objNew.Spec.LogCollector) { + logger.Debug("log collector option changed, reconciling") + return true + } + } else if objOld.GetGeneration() != objNew.GetGeneration() { + logger.Debugf("skipping resource %q update with unchanged spec", objNew.Name) + } + } + + return false + }, + GenericFunc: func(e event.GenericEvent) bool { + return false + }, + } +} + // objectChanged checks whether the object has been updated func objectChanged(oldObj, newObj runtime.Object, objectName string) (bool, error) { var doReconcile bool diff --git a/pkg/operator/ceph/file/controller.go b/pkg/operator/ceph/file/controller.go index 37c3ba550..4da7beaba 100644 --- a/pkg/operator/ceph/file/controller.go +++ b/pkg/operator/ceph/file/controller.go @@ -120,6 +120,25 @@ func add(mgr manager.Manager, r reconcile.Reconciler) error { } } + // Build Handler function to return the list of ceph filesystems + // This is used by the watchers below + handlerFunc, err := opcontroller.ObjectToCRMapper(mgr.GetClient(), &cephv1.CephFilesystemList{}, mgr.GetScheme()) + if err != nil { + return err + } + + // Watch for CephCluster Spec changes that we want to propagate to us + err = c.Watch(&source.Kind{Type: &cephv1.CephCluster{ + TypeMeta: metav1.TypeMeta{ + Kind: opcontroller.ClusterResource.Kind, + APIVersion: opcontroller.ClusterResource.APIVersion, + }, + }, + }, handler.EnqueueRequestsFromMapFunc(handlerFunc), opcontroller.WatchCephClusterPredicate()) + if err != nil { + return err + } + return nil } diff --git a/pkg/operator/ceph/object/controller.go b/pkg/operator/ceph/object/controller.go index b600b2395..2fde3d18f 100644 --- a/pkg/operator/ceph/object/controller.go +++ b/pkg/operator/ceph/object/controller.go @@ -136,6 +136,25 @@ func add(mgr manager.Manager, r reconcile.Reconciler) error { } } + // Build Handler function to return the list of ceph object + // This is used by the watchers below + handlerFunc, err := opcontroller.ObjectToCRMapper(mgr.GetClient(), &cephv1.CephObjectStoreList{}, mgr.GetScheme()) + if err != nil { + return err + } + + // Watch for CephCluster Spec changes that we want to propagate to us + err = c.Watch(&source.Kind{Type: &cephv1.CephCluster{ + TypeMeta: metav1.TypeMeta{ + Kind: opcontroller.ClusterResource.Kind, + APIVersion: opcontroller.ClusterResource.APIVersion, + }, + }, + }, handler.EnqueueRequestsFromMapFunc(handlerFunc), opcontroller.WatchCephClusterPredicate()) + if err != nil { + return err + } + return nil }