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

     1  package k8s
     2  
     3  import (
     4  	"context"
     5  
     6  	corev1 "k8s.io/api/core/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  // Service the ServiceAccount service that knows how to interact with k8s to manage them
    16  type Service interface {
    17  	GetService(namespace string, name string) (*corev1.Service, error)
    18  	CreateService(namespace string, service *corev1.Service) error
    19  	CreateIfNotExistsService(namespace string, service *corev1.Service) error
    20  	UpdateService(namespace string, service *corev1.Service) error
    21  	CreateOrUpdateService(namespace string, service *corev1.Service) error
    22  	DeleteService(namespace string, name string) error
    23  	ListServices(namespace string) (*corev1.ServiceList, error)
    24  }
    25  
    26  // ServiceService is the service service implementation using API calls to kubernetes.
    27  type ServiceService struct {
    28  	kubeClient      kubernetes.Interface
    29  	logger          log.Logger
    30  	metricsRecorder metrics.Recorder
    31  }
    32  
    33  // NewServiceService returns a new Service KubeService.
    34  func NewServiceService(kubeClient kubernetes.Interface, logger log.Logger, metricsRecorder metrics.Recorder) *ServiceService {
    35  	logger = logger.With("service", "k8s.service")
    36  	return &ServiceService{
    37  		kubeClient:      kubeClient,
    38  		logger:          logger,
    39  		metricsRecorder: metricsRecorder,
    40  	}
    41  }
    42  
    43  func (s *ServiceService) GetService(namespace string, name string) (*corev1.Service, error) {
    44  	service, err := s.kubeClient.CoreV1().Services(namespace).Get(context.TODO(), name, metav1.GetOptions{})
    45  	recordMetrics(namespace, "Service", name, "GET", err, s.metricsRecorder)
    46  	if err != nil {
    47  		return nil, err
    48  	}
    49  	return service, err
    50  }
    51  
    52  func (s *ServiceService) CreateService(namespace string, service *corev1.Service) error {
    53  	_, err := s.kubeClient.CoreV1().Services(namespace).Create(context.TODO(), service, metav1.CreateOptions{})
    54  	recordMetrics(namespace, "Service", service.GetName(), "CREATE", err, s.metricsRecorder)
    55  	if err != nil {
    56  		return err
    57  	}
    58  	s.logger.WithField("namespace", namespace).WithField("serviceName", service.Name).Debugf("service created")
    59  	return nil
    60  }
    61  
    62  func (s *ServiceService) CreateIfNotExistsService(namespace string, service *corev1.Service) error {
    63  	if _, err := s.GetService(namespace, service.Name); err != nil {
    64  		// If no resource we need to create.
    65  		if errors.IsNotFound(err) {
    66  			return s.CreateService(namespace, service)
    67  		}
    68  		return err
    69  	}
    70  	return nil
    71  }
    72  
    73  func (s *ServiceService) UpdateService(namespace string, service *corev1.Service) error {
    74  	_, err := s.kubeClient.CoreV1().Services(namespace).Update(context.TODO(), service, metav1.UpdateOptions{})
    75  	recordMetrics(namespace, "Service", service.GetName(), "UPDATE", err, s.metricsRecorder)
    76  	if err != nil {
    77  		return err
    78  	}
    79  	s.logger.WithField("namespace", namespace).WithField("serviceName", service.Name).Debugf("service updated")
    80  	return nil
    81  }
    82  func (s *ServiceService) CreateOrUpdateService(namespace string, service *corev1.Service) error {
    83  	storedService, err := s.GetService(namespace, service.Name)
    84  	if err != nil {
    85  		// If no resource we need to create.
    86  		if errors.IsNotFound(err) {
    87  			return s.CreateService(namespace, service)
    88  		}
    89  		log.Errorf("Error while updating service %v in %v namespace : %v", service.GetName(), namespace, err)
    90  		return err
    91  	}
    92  
    93  	// Already exists, need to Update.
    94  	// Set the correct resource version to ensure we are on the latest version. This way the only valid
    95  	// namespace is our spec(https://github.com/kubernetes/community/blob/master/contributors/devel/api-conventions.md#concurrency-control-and-consistency),
    96  	// we will replace the current namespace state.
    97  	service.ResourceVersion = storedService.ResourceVersion
    98  	return s.UpdateService(namespace, service)
    99  }
   100  
   101  func (s *ServiceService) DeleteService(namespace string, name string) error {
   102  	propagation := metav1.DeletePropagationForeground
   103  	err := s.kubeClient.CoreV1().Services(namespace).Delete(context.TODO(), name, metav1.DeleteOptions{PropagationPolicy: &propagation})
   104  	recordMetrics(namespace, "Service", name, "DELETE", err, s.metricsRecorder)
   105  	return err
   106  }
   107  
   108  func (s *ServiceService) ListServices(namespace string) (*corev1.ServiceList, error) {
   109  	serviceList, err := s.kubeClient.CoreV1().Services(namespace).List(context.TODO(), metav1.ListOptions{})
   110  	recordMetrics(namespace, "Service", metrics.NOT_APPLICABLE, "LIST", err, s.metricsRecorder)
   111  	return serviceList, err
   112  }