github.com/argoproj-labs/argocd-operator@v0.10.0/controllers/argocd/hpa.go (about)

     1  // Copyright 2019 ArgoCD Operator Developers
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  // 	http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package argocd
    16  
    17  import (
    18  	"context"
    19  	"reflect"
    20  
    21  	autoscaling "k8s.io/api/autoscaling/v1"
    22  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    23  
    24  	argoproj "github.com/argoproj-labs/argocd-operator/api/v1beta1"
    25  	"github.com/argoproj-labs/argocd-operator/common"
    26  	"github.com/argoproj-labs/argocd-operator/controllers/argoutil"
    27  )
    28  
    29  var (
    30  	maxReplicas int32 = 3
    31  	minReplicas int32 = 1
    32  	tcup        int32 = 50
    33  )
    34  
    35  func newHorizontalPodAutoscaler(cr *argoproj.ArgoCD) *autoscaling.HorizontalPodAutoscaler {
    36  	return &autoscaling.HorizontalPodAutoscaler{
    37  		ObjectMeta: metav1.ObjectMeta{
    38  			Name:      cr.Name,
    39  			Namespace: cr.Namespace,
    40  			Labels:    argoutil.LabelsForCluster(cr),
    41  		},
    42  	}
    43  }
    44  
    45  func newHorizontalPodAutoscalerWithName(name string, cr *argoproj.ArgoCD) *autoscaling.HorizontalPodAutoscaler {
    46  	hpa := newHorizontalPodAutoscaler(cr)
    47  	hpa.ObjectMeta.Name = name
    48  
    49  	lbls := hpa.ObjectMeta.Labels
    50  	lbls[common.ArgoCDKeyName] = name
    51  	hpa.ObjectMeta.Labels = lbls
    52  
    53  	return hpa
    54  }
    55  
    56  func newHorizontalPodAutoscalerWithSuffix(suffix string, cr *argoproj.ArgoCD) *autoscaling.HorizontalPodAutoscaler {
    57  	return newHorizontalPodAutoscalerWithName(nameWithSuffix(suffix, cr), cr)
    58  }
    59  
    60  // reconcileServerHPA will ensure that the HorizontalPodAutoscaler is present for the Argo CD Server component, and reconcile any detected changes.
    61  func (r *ReconcileArgoCD) reconcileServerHPA(cr *argoproj.ArgoCD) error {
    62  
    63  	defaultHPA := newHorizontalPodAutoscalerWithSuffix("server", cr)
    64  	defaultHPA.Spec = autoscaling.HorizontalPodAutoscalerSpec{
    65  		MaxReplicas:                    maxReplicas,
    66  		MinReplicas:                    &minReplicas,
    67  		TargetCPUUtilizationPercentage: &tcup,
    68  		ScaleTargetRef: autoscaling.CrossVersionObjectReference{
    69  			APIVersion: "apps/v1",
    70  			Kind:       "Deployment",
    71  			Name:       nameWithSuffix("server", cr),
    72  		},
    73  	}
    74  
    75  	existingHPA := newHorizontalPodAutoscalerWithSuffix("server", cr)
    76  	if argoutil.IsObjectFound(r.Client, cr.Namespace, existingHPA.Name, existingHPA) {
    77  		if !cr.Spec.Server.Autoscale.Enabled {
    78  			return r.Client.Delete(context.TODO(), existingHPA) // HorizontalPodAutoscaler found but globally disabled, delete it.
    79  		}
    80  
    81  		changed := false
    82  		// HorizontalPodAutoscaler found, reconcile if necessary changes detected
    83  		if cr.Spec.Server.Autoscale.HPA != nil {
    84  			if !reflect.DeepEqual(existingHPA.Spec, cr.Spec.Server.Autoscale.HPA) {
    85  				existingHPA.Spec = *cr.Spec.Server.Autoscale.HPA
    86  				changed = true
    87  			}
    88  		}
    89  
    90  		if changed {
    91  			return r.Client.Update(context.TODO(), existingHPA)
    92  		}
    93  
    94  		// HorizontalPodAutoscaler found, no changes detected
    95  		return nil
    96  	}
    97  
    98  	if !cr.Spec.Server.Autoscale.Enabled {
    99  		return nil // AutoScale not enabled, move along...
   100  	}
   101  
   102  	// AutoScale enabled, no existing HPA found, create
   103  	if cr.Spec.Server.Autoscale.HPA != nil {
   104  		defaultHPA.Spec = *cr.Spec.Server.Autoscale.HPA
   105  	}
   106  
   107  	return r.Client.Create(context.TODO(), defaultHPA)
   108  }
   109  
   110  // reconcileAutoscalers will ensure that all HorizontalPodAutoscalers are present for the given ArgoCD.
   111  func (r *ReconcileArgoCD) reconcileAutoscalers(cr *argoproj.ArgoCD) error {
   112  	if err := r.reconcileServerHPA(cr); err != nil {
   113  		return err
   114  	}
   115  	return nil
   116  }