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 }