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 }