From f2369a14d4a8a7a91ec4dc677382546e62b5ec56 Mon Sep 17 00:00:00 2001 From: YuChen Date: Wed, 29 Nov 2023 20:05:33 -0800 Subject: [PATCH 1/2] introduce maintennance mode into cs operator Signed-off-by: YuChen --- controllers/commonservice_controller.go | 17 +++++- controllers/recocile_pause.go | 74 +++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 controllers/recocile_pause.go diff --git a/controllers/commonservice_controller.go b/controllers/commonservice_controller.go index 943880f86..bfde9be26 100644 --- a/controllers/commonservice_controller.go +++ b/controllers/commonservice_controller.go @@ -56,6 +56,7 @@ type CommonServiceReconciler struct { const ( CRInitializing string = "Initializing" CRUpdating string = "Updating" + CRPending string = "Pending" CRSucceeded string = "Succeeded" CRFailed string = "Failed" ) @@ -101,10 +102,20 @@ func (r *CommonServiceReconciler) Reconcile(ctx context.Context, req ctrl.Reques klog.Error("Accept license by changing .spec.license.accept to true in the CommonService CR. Operator will not proceed until then") } - if r.checkNamespace(req.NamespacedName.String()) { - return r.ReconcileMasterCR(ctx, instance) + if !r.reconcilePauseRequest(instance) { + if r.checkNamespace(req.NamespacedName.String()) { + return r.ReconcileMasterCR(ctx, instance) + } + return r.ReconcileGeneralCR(ctx, instance) + } else { + if err := r.updatePhase(ctx, instance, CRPending); err != nil { + klog.Errorf("Fail to reconcile %s/%s: %v", instance.Namespace, instance.Name, err) + return ctrl.Result{}, err + } else { + klog.Infof("%s/%s is in pending status due to pause request", instance.Namespace, instance.Name) + return ctrl.Result{}, nil + } } - return r.ReconcileGeneralCR(ctx, instance) } func (r *CommonServiceReconciler) ReconcileMasterCR(ctx context.Context, instance *apiv3.CommonService) (ctrl.Result, error) { diff --git a/controllers/recocile_pause.go b/controllers/recocile_pause.go new file mode 100644 index 000000000..9490f7578 --- /dev/null +++ b/controllers/recocile_pause.go @@ -0,0 +1,74 @@ +// +// Copyright 2022 IBM Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package controllers + +import ( + apiv3 "github.com/IBM/ibm-common-service-operator/api/v3" + "k8s.io/klog" +) + +const ( + PauseRequestAnnoKey = "commonservices.operator.ibm.com/pause" + SelfPauseRequestAnnoKey = "commonservices.operator.ibm.com/self-pause" + PauseRequestValue = "true" +) + +func (r *CommonServiceReconciler) reconcilePauseRequest(instance *apiv3.CommonService) bool { + + klog.Info("Request Stage: reconcilePauseRequest") + + // if the given CommnService CR has not been existing + if instance == nil { + klog.Warningf("CommonService CR %s/%s is not existing", instance.Name, instance.Namespace) + return false + } + + // check if there is a pause request annotation in the CommonService CR + return r.pauseRequestExists(instance) + + // future implementation: TO DO + // check and set pauseExpire annotation + // if the time is expired, remove the pause annotation +} + +func (r *CommonServiceReconciler) pauseRequestExists(instance *apiv3.CommonService) bool { + klog.Info("Request Stage: Checking annotations for pause request") + + // if there is pause or self-pause request annotation in the CommonService CR, pause request takes precedence over self-pause request + var pauseRequestFound bool + var selfpauseRequestFound bool + if instance.ObjectMeta.Annotations != nil { + for key := range instance.ObjectMeta.Annotations { + if key == PauseRequestAnnoKey { + pauseRequestFound = true + klog.Infof("Found pause request annotation: %v", instance.ObjectMeta.Annotations[PauseRequestAnnoKey]) + } else if key == SelfPauseRequestAnnoKey { + selfpauseRequestFound = true + klog.Infof("Found self-pause request annotation: %v", instance.ObjectMeta.Annotations[SelfPauseRequestAnnoKey]) + } + } + // Pause request takes precedence over self-pause request + if pauseRequestFound { + return instance.ObjectMeta.Annotations[PauseRequestAnnoKey] == PauseRequestValue + } else if selfpauseRequestFound { + return instance.ObjectMeta.Annotations[SelfPauseRequestAnnoKey] == PauseRequestValue + } else { + return false + } + } + return false +} From a4606c565d9e58b3eb2184cba1c349653a13516b Mon Sep 17 00:00:00 2001 From: YuChen Date: Thu, 30 Nov 2023 10:31:12 -0800 Subject: [PATCH 2/2] add annotation and label change predicate Signed-off-by: YuChen --- controllers/commonservice_controller.go | 23 ++++++++++++++--------- controllers/recocile_pause.go | 8 ++++---- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/controllers/commonservice_controller.go b/controllers/commonservice_controller.go index bfde9be26..e13d619dc 100644 --- a/controllers/commonservice_controller.go +++ b/controllers/commonservice_controller.go @@ -102,20 +102,20 @@ func (r *CommonServiceReconciler) Reconcile(ctx context.Context, req ctrl.Reques klog.Error("Accept license by changing .spec.license.accept to true in the CommonService CR. Operator will not proceed until then") } + // If the CommonService CR is not paused, continue to reconcile if !r.reconcilePauseRequest(instance) { if r.checkNamespace(req.NamespacedName.String()) { return r.ReconcileMasterCR(ctx, instance) } return r.ReconcileGeneralCR(ctx, instance) - } else { - if err := r.updatePhase(ctx, instance, CRPending); err != nil { - klog.Errorf("Fail to reconcile %s/%s: %v", instance.Namespace, instance.Name, err) - return ctrl.Result{}, err - } else { - klog.Infof("%s/%s is in pending status due to pause request", instance.Namespace, instance.Name) - return ctrl.Result{}, nil - } } + // If the CommonService CR is paused, update the status to pending + if err := r.updatePhase(ctx, instance, CRPending); err != nil { + klog.Errorf("Fail to reconcile %s/%s: %v", instance.Namespace, instance.Name, err) + return ctrl.Result{}, err + } + klog.Infof("%s/%s is in pending status due to pause request", instance.Namespace, instance.Name) + return ctrl.Result{}, nil } func (r *CommonServiceReconciler) ReconcileMasterCR(ctx context.Context, instance *apiv3.CommonService) (ctrl.Result, error) { @@ -415,7 +415,12 @@ func (r *CommonServiceReconciler) mappingToCsRequest() handler.MapFunc { func (r *CommonServiceReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). - For(&apiv3.CommonService{}, builder.WithPredicates(predicate.GenerationChangedPredicate{})). + // AnnotationChangedPredicate is intended to be used in conjunction with the GenerationChangedPredicate + For(&apiv3.CommonService{}, builder.WithPredicates( + predicate.Or( + predicate.GenerationChangedPredicate{}, + predicate.AnnotationChangedPredicate{}, + predicate.LabelChangedPredicate{}))). Watches( &source.Kind{Type: &corev1.ConfigMap{}}, handler.EnqueueRequestsFromMapFunc(r.mappingToCsRequest()), diff --git a/controllers/recocile_pause.go b/controllers/recocile_pause.go index 9490f7578..f1cbfb8aa 100644 --- a/controllers/recocile_pause.go +++ b/controllers/recocile_pause.go @@ -17,8 +17,9 @@ package controllers import ( - apiv3 "github.com/IBM/ibm-common-service-operator/api/v3" "k8s.io/klog" + + apiv3 "github.com/IBM/ibm-common-service-operator/api/v3" ) const ( @@ -29,7 +30,7 @@ const ( func (r *CommonServiceReconciler) reconcilePauseRequest(instance *apiv3.CommonService) bool { - klog.Info("Request Stage: reconcilePauseRequest") + klog.Info("Request Stage: ReconcilePauseRequest") // if the given CommnService CR has not been existing if instance == nil { @@ -66,9 +67,8 @@ func (r *CommonServiceReconciler) pauseRequestExists(instance *apiv3.CommonServi return instance.ObjectMeta.Annotations[PauseRequestAnnoKey] == PauseRequestValue } else if selfpauseRequestFound { return instance.ObjectMeta.Annotations[SelfPauseRequestAnnoKey] == PauseRequestValue - } else { - return false } + return false } return false }