diff --git a/deploy/examples/operator-openshift.yaml b/deploy/examples/operator-openshift.yaml index e7eb9ea0f..df81d2530 100644 --- a/deploy/examples/operator-openshift.yaml +++ b/deploy/examples/operator-openshift.yaml @@ -638,6 +638,8 @@ data: # (Optional) QPS to use while communicating with the kubernetes apiserver. # CSI_KUBE_API_QPS: "5.0" + # RevisionHistoryLimit value for all deployments created by rook. + # ROOK_REVISION_HISTORY_LIMIT: "3" --- # The deployment for the rook operator # OLM: BEGIN OPERATOR DEPLOYMENT diff --git a/deploy/examples/operator.yaml b/deploy/examples/operator.yaml index 64d76d2d3..347524e13 100644 --- a/deploy/examples/operator.yaml +++ b/deploy/examples/operator.yaml @@ -568,6 +568,8 @@ data: # (Optional) QPS to use while communicating with the kubernetes apiserver. # CSI_KUBE_API_QPS: "5.0" + # RevisionHistoryLimit value for all deployments created by rook. + # ROOK_REVISION_HISTORY_LIMIT: "3" --- # OLM: BEGIN OPERATOR DEPLOYMENT apiVersion: apps/v1 diff --git a/pkg/operator/ceph/cluster/mgr/spec.go b/pkg/operator/ceph/cluster/mgr/spec.go index 01cfb5f2b..1c38893d0 100644 --- a/pkg/operator/ceph/cluster/mgr/spec.go +++ b/pkg/operator/ceph/cluster/mgr/spec.go @@ -128,6 +128,7 @@ func (c *Cluster) makeDeployment(mgrConfig *mgrConfig) (*apps.Deployment, error) Labels: c.getPodLabels(mgrConfig, true), }, Spec: apps.DeploymentSpec{ + RevisionHistoryLimit: controller.RevisionHistoryLimit(), Selector: &metav1.LabelSelector{ MatchLabels: c.getPodLabels(mgrConfig, false), }, diff --git a/pkg/operator/ceph/cluster/mon/spec.go b/pkg/operator/ceph/cluster/mon/spec.go index 9d79ace7b..8901f26bd 100644 --- a/pkg/operator/ceph/cluster/mon/spec.go +++ b/pkg/operator/ceph/cluster/mon/spec.go @@ -108,6 +108,7 @@ func (c *Cluster) makeDeployment(monConfig *monConfig, canary bool) (*apps.Deplo } replicaCount := int32(1) d.Spec = apps.DeploymentSpec{ + RevisionHistoryLimit: controller.RevisionHistoryLimit(), Selector: &metav1.LabelSelector{ MatchLabels: c.getLabels(monConfig, canary, false), }, diff --git a/pkg/operator/ceph/cluster/nodedaemon/exporter.go b/pkg/operator/ceph/cluster/nodedaemon/exporter.go index dec1809eb..ab4debc27 100644 --- a/pkg/operator/ceph/cluster/nodedaemon/exporter.go +++ b/pkg/operator/ceph/cluster/nodedaemon/exporter.go @@ -77,6 +77,7 @@ func (r *ReconcileNode) createOrUpdateCephExporter(node corev1.Node, tolerations Namespace: cephCluster.GetNamespace(), }, } + deploy.Spec.RevisionHistoryLimit = controller.RevisionHistoryLimit() err := controllerutil.SetControllerReference(&cephCluster, deploy, r.scheme) if err != nil { return controllerutil.OperationResultNone, errors.Errorf("failed to set owner reference of ceph-exporter deployment %q", deploy.Name) diff --git a/pkg/operator/ceph/cluster/osd/spec.go b/pkg/operator/ceph/cluster/osd/spec.go index b44aa4ee3..33477cdbf 100644 --- a/pkg/operator/ceph/cluster/osd/spec.go +++ b/pkg/operator/ceph/cluster/osd/spec.go @@ -713,6 +713,7 @@ func (c *Cluster) makeDeployment(osdProps osdProperties, osd *OSDInfo, provision OsdIdLabelKey: fmt.Sprintf("%d", osd.ID), }, }, + RevisionHistoryLimit: controller.RevisionHistoryLimit(), Strategy: apps.DeploymentStrategy{ Type: apps.RecreateDeploymentStrategyType, }, diff --git a/pkg/operator/ceph/cluster/rbd/spec.go b/pkg/operator/ceph/cluster/rbd/spec.go index 2b846eae8..dd627232b 100644 --- a/pkg/operator/ceph/cluster/rbd/spec.go +++ b/pkg/operator/ceph/cluster/rbd/spec.go @@ -82,6 +82,7 @@ func (r *ReconcileCephRBDMirror) makeDeployment(daemonConfig *daemonConfig, rbdM Labels: controller.CephDaemonAppLabels(AppName, rbdMirror.Namespace, config.RbdMirrorType, daemonConfig.DaemonID, rbdMirror.Name, "cephrbdmirrors.ceph.rook.io", true), }, Spec: apps.DeploymentSpec{ + RevisionHistoryLimit: controller.RevisionHistoryLimit(), Selector: &metav1.LabelSelector{ MatchLabels: podSpec.Labels, }, diff --git a/pkg/operator/ceph/controller.go b/pkg/operator/ceph/controller.go index 238dd29bd..c674854a5 100644 --- a/pkg/operator/ceph/controller.go +++ b/pkg/operator/ceph/controller.go @@ -133,6 +133,7 @@ func (r *ReconcileConfig) reconcile(request reconcile.Request) (reconcile.Result opcontroller.SetAllowLoopDevices(r.config.Parameters) opcontroller.SetEnforceHostNetwork(r.config.Parameters) + opcontroller.SetRevisionHistoryLimit(r.config.Parameters) logger.Infof("%s done reconciling", controllerName) return reconcile.Result{}, nil diff --git a/pkg/operator/ceph/controller/controller_utils.go b/pkg/operator/ceph/controller/controller_utils.go index f5cc1ca1d..9d5e20752 100644 --- a/pkg/operator/ceph/controller/controller_utils.go +++ b/pkg/operator/ceph/controller/controller_utils.go @@ -54,6 +54,9 @@ const ( enforceHostNetworkSettingName string = "ROOK_ENFORCE_HOST_NETWORK" enforceHostNetworkDefaultValue string = "false" + revisionHistoryLimitSettingName string = "ROOK_REVISION_HISTORY_LIMIT" + revisionHistoryLimitDefaultValue string = "" + // UninitializedCephConfigError refers to the error message printed by the Ceph CLI when there is no ceph configuration file // This typically is raised when the operator has not finished initializing UninitializedCephConfigError = "error calling conf_read_file" @@ -86,7 +89,8 @@ var ( OperatorCephBaseImageVersion string // loopDevicesAllowed indicates whether loop devices are allowed to be used - loopDevicesAllowed = false + loopDevicesAllowed = false + revisionHistoryLimit *int32 = nil ) func DiscoveryDaemonEnabled(data map[string]string) bool { @@ -133,6 +137,26 @@ func EnforceHostNetwork() bool { return cephv1.EnforceHostNetwork() } +func SetRevisionHistoryLimit(data map[string]string) { + strval := k8sutil.GetValue(data, revisionHistoryLimitSettingName, revisionHistoryLimitDefaultValue) + if strval != "" { + numval, err := strconv.ParseInt(strval, 10, 32) + if err != nil { + logger.Warningf("failed to parse value %q for %q. assuming default value.", strval, revisionHistoryLimitSettingName) + revisionHistoryLimit = nil + return + + } + limit := int32(numval) + revisionHistoryLimit = &limit + } + +} + +func RevisionHistoryLimit() *int32 { + return revisionHistoryLimit +} + // canIgnoreHealthErrStatusInReconcile determines whether a status of HEALTH_ERR in the CephCluster can be ignored safely. func canIgnoreHealthErrStatusInReconcile(cephCluster cephv1.CephCluster, controllerName string) bool { // Get a list of all the keys causing the HEALTH_ERR status. diff --git a/pkg/operator/ceph/controller/controller_utils_test.go b/pkg/operator/ceph/controller/controller_utils_test.go index 532cc0bcb..82774c8c7 100644 --- a/pkg/operator/ceph/controller/controller_utils_test.go +++ b/pkg/operator/ceph/controller/controller_utils_test.go @@ -133,6 +133,33 @@ func TestSetEnforceHostNetwork(t *testing.T) { assert.False(t, EnforceHostNetwork()) } +func TestSetRevisionHistoryLimit(t *testing.T) { + opConfig := map[string]string{} + t.Run("ROOK_REVISION_HISTORY_LIMIT: test default value", func(t *testing.T) { + SetRevisionHistoryLimit(opConfig) + assert.Nil(t, RevisionHistoryLimit()) + }) + + var value string = "foo" + t.Run("ROOK_REVISION_HISTORY_LIMIT: test invalid value 'foo'", func(t *testing.T) { + opConfig[revisionHistoryLimitSettingName] = value + SetRevisionHistoryLimit(opConfig) + assert.Nil(t, RevisionHistoryLimit()) + }) + + t.Run("ROOK_REVISION_HISTORY_LIMIT: test empty string value", func(t *testing.T) { + value = "" + opConfig[revisionHistoryLimitSettingName] = value + SetRevisionHistoryLimit(opConfig) + assert.Nil(t, RevisionHistoryLimit()) + }) + t.Run("ROOK_REVISION_HISTORY_LIMIT: test valig value '10'", func(t *testing.T) { + value = "10" + opConfig[revisionHistoryLimitSettingName] = value + SetRevisionHistoryLimit(opConfig) + assert.Equal(t, int32(10), *RevisionHistoryLimit()) + }) +} func TestIsReadyToReconcile(t *testing.T) { scheme := scheme.Scheme scheme.AddKnownTypes(cephv1.SchemeGroupVersion, &cephv1.CephCluster{}, &cephv1.CephClusterList{}) diff --git a/pkg/operator/ceph/file/mds/spec.go b/pkg/operator/ceph/file/mds/spec.go index 426957a24..31065deef 100644 --- a/pkg/operator/ceph/file/mds/spec.go +++ b/pkg/operator/ceph/file/mds/spec.go @@ -94,8 +94,9 @@ func (c *Cluster) makeDeployment(mdsConfig *mdsConfig, fsNamespacedname types.Na Selector: &metav1.LabelSelector{ MatchLabels: c.podLabels(mdsConfig, false), }, - Template: podSpec, - Replicas: &replicas, + RevisionHistoryLimit: controller.RevisionHistoryLimit(), + Template: podSpec, + Replicas: &replicas, Strategy: apps.DeploymentStrategy{ Type: apps.RecreateDeploymentStrategyType, }, diff --git a/pkg/operator/ceph/file/mirror/spec.go b/pkg/operator/ceph/file/mirror/spec.go index 8e9153b5b..d13d1848b 100644 --- a/pkg/operator/ceph/file/mirror/spec.go +++ b/pkg/operator/ceph/file/mirror/spec.go @@ -79,6 +79,7 @@ func (r *ReconcileFilesystemMirror) makeDeployment(daemonConfig *daemonConfig, f Annotations: fsMirror.Spec.Annotations, Labels: controller.CephDaemonAppLabels(AppName, fsMirror.Namespace, config.FilesystemMirrorType, userID, fsMirror.Name, "cephfilesystemmirrors.ceph.rook.io", true)}, Spec: apps.DeploymentSpec{ + RevisionHistoryLimit: controller.RevisionHistoryLimit(), Selector: &metav1.LabelSelector{ MatchLabels: podSpec.Labels, }, diff --git a/pkg/operator/ceph/nfs/spec.go b/pkg/operator/ceph/nfs/spec.go index 10edf9399..5834acf5c 100644 --- a/pkg/operator/ceph/nfs/spec.go +++ b/pkg/operator/ceph/nfs/spec.go @@ -191,6 +191,7 @@ func (r *ReconcileCephNFS) makeDeployment(nfs *cephv1.CephNFS, cfg daemonConfig) // Multiple replicas of the nfs service would be handled by creating a service and a new deployment for each one, rather than increasing the pod count here replicas := int32(1) deployment.Spec = apps.DeploymentSpec{ + RevisionHistoryLimit: controller.RevisionHistoryLimit(), Selector: &metav1.LabelSelector{ MatchLabels: getLabels(nfs, cfg.ID, false), }, diff --git a/pkg/operator/ceph/object/cosi/spec.go b/pkg/operator/ceph/object/cosi/spec.go index 50bf737c5..f0cc0a5a9 100644 --- a/pkg/operator/ceph/object/cosi/spec.go +++ b/pkg/operator/ceph/object/cosi/spec.go @@ -43,7 +43,6 @@ func createCephCOSIDriverDeployment(cephCOSIDriver *cephv1.CephCOSIDriver) (*app replica := int32(1) minReadySeconds := int32(30) progressDeadlineSeconds := int32(600) - revisionHistoryLimit := int32(3) cephcosidriverDeployment := &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ @@ -52,7 +51,8 @@ func createCephCOSIDriverDeployment(cephCOSIDriver *cephv1.CephCOSIDriver) (*app Labels: getCOSILabels(cephCOSIDriver.Name, cephCOSIDriver.Namespace), }, Spec: appsv1.DeploymentSpec{ - Replicas: &replica, + RevisionHistoryLimit: controller.RevisionHistoryLimit(), + Replicas: &replica, Selector: &metav1.LabelSelector{ MatchLabels: getCOSILabels(cephCOSIDriver.Name, cephCOSIDriver.Namespace), }, @@ -60,7 +60,6 @@ func createCephCOSIDriverDeployment(cephCOSIDriver *cephv1.CephCOSIDriver) (*app Strategy: strategy, MinReadySeconds: minReadySeconds, ProgressDeadlineSeconds: &progressDeadlineSeconds, - RevisionHistoryLimit: &revisionHistoryLimit, }, } diff --git a/pkg/operator/ceph/object/spec.go b/pkg/operator/ceph/object/spec.go index cd34dab8d..b72910fb9 100644 --- a/pkg/operator/ceph/object/spec.go +++ b/pkg/operator/ceph/object/spec.go @@ -117,6 +117,7 @@ func (c *clusterConfig) createDeployment(rgwConfig *rgwConfig) (*apps.Deployment Labels: getLabels(c.store.Name, c.store.Namespace, true), }, Spec: apps.DeploymentSpec{ + RevisionHistoryLimit: controller.RevisionHistoryLimit(), Selector: &metav1.LabelSelector{ MatchLabels: getLabels(c.store.Name, c.store.Namespace, false), }, diff --git a/pkg/operator/discover/discover.go b/pkg/operator/discover/discover.go index ee4cdb3f6..b895badd7 100644 --- a/pkg/operator/discover/discover.go +++ b/pkg/operator/discover/discover.go @@ -102,6 +102,7 @@ func (d *Discover) createDiscoverDaemonSet(ctx context.Context, namespace, disco Labels: getLabels(), }, Spec: apps.DaemonSetSpec{ + RevisionHistoryLimit: opcontroller.RevisionHistoryLimit(), Selector: &metav1.LabelSelector{ MatchLabels: map[string]string{ "app": discoverDaemonsetName,