github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/controllers/apps/operations/vertical_scaling.go (about)

     1  /*
     2  Copyright (C) 2022-2023 ApeCloud Co., Ltd
     3  
     4  This file is part of KubeBlocks project
     5  
     6  This program is free software: you can redistribute it and/or modify
     7  it under the terms of the GNU Affero General Public License as published by
     8  the Free Software Foundation, either version 3 of the License, or
     9  (at your option) any later version.
    10  
    11  This program is distributed in the hope that it will be useful
    12  but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14  GNU Affero General Public License for more details.
    15  
    16  You should have received a copy of the GNU Affero General Public License
    17  along with this program.  If not, see <http://www.gnu.org/licenses/>.
    18  */
    19  
    20  package operations
    21  
    22  import (
    23  	"time"
    24  
    25  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    26  	"sigs.k8s.io/controller-runtime/pkg/client"
    27  
    28  	appsv1alpha1 "github.com/1aal/kubeblocks/apis/apps/v1alpha1"
    29  	intctrlutil "github.com/1aal/kubeblocks/pkg/controllerutil"
    30  )
    31  
    32  type verticalScalingHandler struct{}
    33  
    34  var _ OpsHandler = verticalScalingHandler{}
    35  
    36  func init() {
    37  	vsHandler := verticalScalingHandler{}
    38  	verticalScalingBehaviour := OpsBehaviour{
    39  		// if cluster is Abnormal or Failed, new opsRequest may can repair it.
    40  		// TODO: we should add "force" flag for these opsRequest.
    41  		FromClusterPhases:                  appsv1alpha1.GetClusterUpRunningPhases(),
    42  		ToClusterPhase:                     appsv1alpha1.UpdatingClusterPhase,
    43  		OpsHandler:                         vsHandler,
    44  		ProcessingReasonInClusterCondition: ProcessingReasonVerticalScaling,
    45  		CancelFunc:                         vsHandler.Cancel,
    46  	}
    47  
    48  	opsMgr := GetOpsManager()
    49  	opsMgr.RegisterOps(appsv1alpha1.VerticalScalingType, verticalScalingBehaviour)
    50  }
    51  
    52  // ActionStartedCondition the started condition when handle the vertical scaling request.
    53  func (vs verticalScalingHandler) ActionStartedCondition(reqCtx intctrlutil.RequestCtx, cli client.Client, opsRes *OpsResource) (*metav1.Condition, error) {
    54  	return appsv1alpha1.NewVerticalScalingCondition(opsRes.OpsRequest), nil
    55  }
    56  
    57  // Action modifies cluster component resources according to
    58  // the definition of opsRequest with spec.componentNames and spec.componentOps.verticalScaling
    59  func (vs verticalScalingHandler) Action(reqCtx intctrlutil.RequestCtx, cli client.Client, opsRes *OpsResource) error {
    60  	verticalScalingMap := opsRes.OpsRequest.Spec.ToVerticalScalingListToMap()
    61  	for index, component := range opsRes.Cluster.Spec.ComponentSpecs {
    62  		verticalScaling, ok := verticalScalingMap[component.Name]
    63  		if !ok {
    64  			continue
    65  		}
    66  		// TODO: support specify class object name in the Class field
    67  		if verticalScaling.ClassDefRef != nil {
    68  			component.ClassDefRef = verticalScaling.ClassDefRef
    69  		} else {
    70  			// clear old class ref
    71  			component.ClassDefRef = &appsv1alpha1.ClassDefRef{}
    72  			component.Resources = verticalScaling.ResourceRequirements
    73  		}
    74  		opsRes.Cluster.Spec.ComponentSpecs[index] = component
    75  	}
    76  	return cli.Update(reqCtx.Ctx, opsRes.Cluster)
    77  }
    78  
    79  // ReconcileAction will be performed when action is done and loops till OpsRequest.status.phase is Succeed/Failed.
    80  // the Reconcile function for vertical scaling opsRequest.
    81  func (vs verticalScalingHandler) ReconcileAction(reqCtx intctrlutil.RequestCtx, cli client.Client, opsRes *OpsResource) (appsv1alpha1.OpsPhase, time.Duration, error) {
    82  	return reconcileActionWithComponentOps(reqCtx, cli, opsRes, "vertical scale", handleComponentStatusProgress)
    83  }
    84  
    85  // SaveLastConfiguration records last configuration to the OpsRequest.status.lastConfiguration
    86  func (vs verticalScalingHandler) SaveLastConfiguration(reqCtx intctrlutil.RequestCtx, cli client.Client, opsRes *OpsResource) error {
    87  	componentNameSet := opsRes.OpsRequest.GetComponentNameSet()
    88  	lastComponentInfo := map[string]appsv1alpha1.LastComponentConfiguration{}
    89  	for _, v := range opsRes.Cluster.Spec.ComponentSpecs {
    90  		if _, ok := componentNameSet[v.Name]; !ok {
    91  			continue
    92  		}
    93  		lastConfiguration := appsv1alpha1.LastComponentConfiguration{
    94  			ResourceRequirements: v.Resources,
    95  		}
    96  		if v.ClassDefRef != nil {
    97  			lastConfiguration.ClassDefRef = v.ClassDefRef
    98  		}
    99  		lastComponentInfo[v.Name] = lastConfiguration
   100  	}
   101  	opsRes.OpsRequest.Status.LastConfiguration.Components = lastComponentInfo
   102  	return nil
   103  }
   104  
   105  // Cancel this function defines the cancel verticalScaling action.
   106  func (vs verticalScalingHandler) Cancel(reqCxt intctrlutil.RequestCtx, cli client.Client, opsRes *OpsResource) error {
   107  	return cancelComponentOps(reqCxt.Ctx, cli, opsRes, func(lastConfig *appsv1alpha1.LastComponentConfiguration, comp *appsv1alpha1.ClusterComponentSpec) error {
   108  		comp.Resources = lastConfig.ResourceRequirements
   109  		if lastConfig.ClassDefRef != nil {
   110  			comp.ClassDefRef = lastConfig.ClassDefRef
   111  		}
   112  		return nil
   113  	})
   114  }