github.com/spotahome/redis-operator@v1.2.4/service/k8s/poddisruptionbudget.go (about)

     1  package k8s
     2  
     3  import (
     4  	"context"
     5  
     6  	policyv1 "k8s.io/api/policy/v1"
     7  	"k8s.io/apimachinery/pkg/api/errors"
     8  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
     9  	"k8s.io/client-go/kubernetes"
    10  
    11  	"github.com/spotahome/redis-operator/log"
    12  	"github.com/spotahome/redis-operator/metrics"
    13  )
    14  
    15  // PodDisruptionBudget the ServiceAccount service that knows how to interact with k8s to manage them
    16  type PodDisruptionBudget interface {
    17  	GetPodDisruptionBudget(namespace string, name string) (*policyv1.PodDisruptionBudget, error)
    18  	CreatePodDisruptionBudget(namespace string, podDisruptionBudget *policyv1.PodDisruptionBudget) error
    19  	UpdatePodDisruptionBudget(namespace string, podDisruptionBudget *policyv1.PodDisruptionBudget) error
    20  	CreateOrUpdatePodDisruptionBudget(namespace string, podDisruptionBudget *policyv1.PodDisruptionBudget) error
    21  	DeletePodDisruptionBudget(namespace string, name string) error
    22  }
    23  
    24  // PodDisruptionBudgetService is the podDisruptionBudget service implementation using API calls to kubernetes.
    25  type PodDisruptionBudgetService struct {
    26  	kubeClient      kubernetes.Interface
    27  	logger          log.Logger
    28  	metricsRecorder metrics.Recorder
    29  }
    30  
    31  // NewPodDisruptionBudgetService returns a new PodDisruptionBudget KubeService.
    32  func NewPodDisruptionBudgetService(kubeClient kubernetes.Interface, logger log.Logger, metricsRecorder metrics.Recorder) *PodDisruptionBudgetService {
    33  	logger = logger.With("service", "k8s.podDisruptionBudget")
    34  	return &PodDisruptionBudgetService{
    35  		kubeClient:      kubeClient,
    36  		logger:          logger,
    37  		metricsRecorder: metricsRecorder,
    38  	}
    39  }
    40  
    41  func (p *PodDisruptionBudgetService) GetPodDisruptionBudget(namespace string, name string) (*policyv1.PodDisruptionBudget, error) {
    42  	podDisruptionBudget, err := p.kubeClient.PolicyV1().PodDisruptionBudgets(namespace).Get(context.TODO(), name, metav1.GetOptions{})
    43  	recordMetrics(namespace, "PodDisruptionBudget", name, "GET", err, p.metricsRecorder)
    44  	if err != nil {
    45  		return nil, err
    46  	}
    47  	return podDisruptionBudget, nil
    48  }
    49  
    50  func (p *PodDisruptionBudgetService) CreatePodDisruptionBudget(namespace string, podDisruptionBudget *policyv1.PodDisruptionBudget) error {
    51  	_, err := p.kubeClient.PolicyV1().PodDisruptionBudgets(namespace).Create(context.TODO(), podDisruptionBudget, metav1.CreateOptions{})
    52  	recordMetrics(namespace, "PodDisruptionBudget", podDisruptionBudget.GetName(), "CREATE", err, p.metricsRecorder)
    53  	if err != nil {
    54  		return err
    55  	}
    56  	p.logger.WithField("namespace", namespace).WithField("podDisruptionBudget", podDisruptionBudget.Name).Debugf("podDisruptionBudget created")
    57  	return nil
    58  }
    59  
    60  func (p *PodDisruptionBudgetService) UpdatePodDisruptionBudget(namespace string, podDisruptionBudget *policyv1.PodDisruptionBudget) error {
    61  	_, err := p.kubeClient.PolicyV1().PodDisruptionBudgets(namespace).Update(context.TODO(), podDisruptionBudget, metav1.UpdateOptions{})
    62  	recordMetrics(namespace, "PodDisruptionBudget", podDisruptionBudget.GetName(), "UPDATE", err, p.metricsRecorder)
    63  	if err != nil {
    64  		return err
    65  	}
    66  	p.logger.WithField("namespace", namespace).WithField("podDisruptionBudget", podDisruptionBudget.Name).Debugf("podDisruptionBudget updated")
    67  	return nil
    68  }
    69  
    70  func (p *PodDisruptionBudgetService) CreateOrUpdatePodDisruptionBudget(namespace string, podDisruptionBudget *policyv1.PodDisruptionBudget) error {
    71  	storedPodDisruptionBudget, err := p.GetPodDisruptionBudget(namespace, podDisruptionBudget.Name)
    72  	if err != nil {
    73  		// If no resource we need to create.
    74  		if errors.IsNotFound(err) {
    75  			return p.CreatePodDisruptionBudget(namespace, podDisruptionBudget)
    76  		}
    77  		return err
    78  	}
    79  
    80  	// Already exists, need to Update.
    81  	// Set the correct resource version to ensure we are on the latest version. This way the only valid
    82  	// namespace is our spec(https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#concurrency-control-and-consistency),
    83  	// we will replace the current namespace state.
    84  	podDisruptionBudget.ResourceVersion = storedPodDisruptionBudget.ResourceVersion
    85  	return p.UpdatePodDisruptionBudget(namespace, podDisruptionBudget)
    86  }
    87  
    88  func (p *PodDisruptionBudgetService) DeletePodDisruptionBudget(namespace string, name string) error {
    89  	err := p.kubeClient.PolicyV1().PodDisruptionBudgets(namespace).Delete(context.TODO(), name, metav1.DeleteOptions{})
    90  	recordMetrics(namespace, "PodDisruptionBudget", name, "DELETE", err, p.metricsRecorder)
    91  	return err
    92  }