diff --git a/controllers/commonservice_controller.go b/controllers/commonservice_controller.go index 53acc6e45..92a87fb72 100644 --- a/controllers/commonservice_controller.go +++ b/controllers/commonservice_controller.go @@ -53,6 +53,7 @@ type CommonServiceReconciler struct { const ( CRInitializing string = "Initializing" CRUpdating string = "Updating" + CRPending string = "Pending" CRSucceeded string = "Succeeded" CRFailed string = "Failed" ) @@ -133,10 +134,20 @@ func (r *CommonServiceReconciler) Reconcile(ctx context.Context, req ctrl.Reques return ctrl.Result{}, client.IgnoreNotFound(err) } - if r.checkNamespace(req.NamespacedName.String()) { - return r.ReconcileMasterCR(ctx, instance, inScope) + // 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, inScope) + } + return r.ReconcileGeneralCR(ctx, instance, inScope) } - return r.ReconcileGeneralCR(ctx, instance, inScope) + // 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, inScope bool) (ctrl.Result, error) { @@ -352,7 +363,12 @@ func (r *CommonServiceReconciler) certSubToCsRequest() 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 new file mode 100644 index 000000000..f1cbfb8aa --- /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 ( + "k8s.io/klog" + + apiv3 "github.com/IBM/ibm-common-service-operator/api/v3" +) + +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 + } + return false + } + return false +}