github.com/olli-ai/jx/v2@v2.0.400-0.20210921045218-14731b4dd448/pkg/kube/serviceaccount/serviceaccounts.go (about)

     1  package serviceaccount
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  
     7  	"github.com/olli-ai/jx/v2/pkg/kube"
     8  
     9  	"github.com/pkg/errors"
    10  	v1 "k8s.io/api/core/v1"
    11  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    12  	"k8s.io/apimachinery/pkg/types"
    13  	"k8s.io/client-go/kubernetes"
    14  )
    15  
    16  type JsonPatch struct {
    17  	ImagePullSecret *[]ImagePullSecret `json:"imagePullSecrets"`
    18  }
    19  
    20  type ImagePullSecret struct {
    21  	Name string `json:"name"`
    22  }
    23  
    24  // PatchImagePullSecrets patches the specified ImagePullSecrets to the given service account
    25  func PatchImagePullSecrets(kubeClient kubernetes.Interface, ns string, sa string, imagePullSecrets []string) error {
    26  	var ips []ImagePullSecret
    27  	for _, secret := range imagePullSecrets {
    28  		jsonSecret := ImagePullSecret{
    29  			Name: secret,
    30  		}
    31  		ips = append(ips, jsonSecret)
    32  	}
    33  	payload := JsonPatch{
    34  		ImagePullSecret: &ips,
    35  	}
    36  	b, err := json.Marshal(payload)
    37  	if err != nil {
    38  		return err
    39  	}
    40  	//log.Logger().Infof("Resultant JSON: %s\n", string(b))
    41  	_, err = kubeClient.CoreV1().ServiceAccounts(ns).Patch(sa, types.StrategicMergePatchType, b)
    42  	if err != nil {
    43  		return err
    44  	}
    45  	return nil
    46  }
    47  
    48  const (
    49  	subjectKind  = "ServiceAccount"
    50  	tokenDataKey = "token"
    51  	certDataKey  = "ca.crt"
    52  )
    53  
    54  // CreateServiceAccount creates a new services account in the given namespace and returns the service account name
    55  func CreateServiceAccount(kubeClient kubernetes.Interface, namespace string, name string) (*v1.ServiceAccount, error) {
    56  	err := kube.EnsureNamespaceCreated(kubeClient, namespace, nil, nil)
    57  	if err != nil {
    58  		return nil, err
    59  	}
    60  	sa, err := kubeClient.CoreV1().ServiceAccounts(namespace).Get(name, metav1.GetOptions{})
    61  	// If a services account already exists just re-use it
    62  	if err == nil {
    63  		return sa, nil
    64  	}
    65  
    66  	sa = &v1.ServiceAccount{
    67  		TypeMeta: metav1.TypeMeta{
    68  			Kind:       subjectKind,
    69  			APIVersion: "v1",
    70  		},
    71  		ObjectMeta: metav1.ObjectMeta{
    72  			Name:      name,
    73  			Namespace: namespace,
    74  		},
    75  	}
    76  
    77  	sa, err = kubeClient.CoreV1().ServiceAccounts(namespace).Create(sa)
    78  	if err != nil {
    79  		return nil, errors.Wrapf(err, "creating service account '%s'", sa)
    80  	}
    81  
    82  	return sa, nil
    83  }
    84  
    85  // DeleteServiceAccount deletes a service account
    86  func DeleteServiceAccount(kubeClient kubernetes.Interface, namespace string, name string) error {
    87  	_, err := kubeClient.CoreV1().ServiceAccounts(namespace).Get(name, metav1.GetOptions{})
    88  	if err != nil {
    89  		// Nothing to delete because the service account does not exist
    90  		return nil
    91  	}
    92  	return kubeClient.CoreV1().ServiceAccounts(namespace).Delete(name, &metav1.DeleteOptions{})
    93  }
    94  
    95  // GetServiceAccountToken return the token of a service account
    96  func GetServiceAccountToken(kubeClient kubernetes.Interface, namespace string, serviceAccountName string) (string, error) {
    97  	return getServiceAccountSecret(kubeClient, namespace, serviceAccountName, tokenDataKey)
    98  }
    99  
   100  // GetServiceAccountCert returns the certificate data for the specified service account in the given namespace.
   101  // Returns an error if an error occurs retrieving the certificate.
   102  func GetServiceAccountCert(kubeClient kubernetes.Interface, namespace string, serviceAccountName string) (string, error) {
   103  	return getServiceAccountSecret(kubeClient, namespace, serviceAccountName, certDataKey)
   104  }
   105  
   106  func getServiceAccountSecret(kubeClient kubernetes.Interface, namespace string, serviceAccountName string, key string) (string, error) {
   107  	secretList, err := kubeClient.CoreV1().Secrets(namespace).List(metav1.ListOptions{})
   108  	if err != nil {
   109  		return "", errors.Wrap(err, "listing secrets")
   110  	}
   111  	for _, secret := range secretList.Items {
   112  		annotations := secret.ObjectMeta.Annotations
   113  		for k, v := range annotations {
   114  			if k == v1.ServiceAccountNameKey && v == serviceAccountName {
   115  				data, ok := secret.Data[key]
   116  				if !ok {
   117  					return "", fmt.Errorf("no %s found for service account %s in namespace %s", key, serviceAccountName, namespace)
   118  				}
   119  				return string(data), nil
   120  			}
   121  		}
   122  	}
   123  	return "", fmt.Errorf("no %s found for service account %s in namespace %s", key, serviceAccountName, namespace)
   124  }