github.com/jenkins-x/jx/v2@v2.1.155/pkg/kube/config.go (about) 1 package kube 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 7 "github.com/pkg/errors" 8 "k8s.io/client-go/tools/clientcmd" 9 "k8s.io/client-go/tools/clientcmd/api" 10 ) 11 12 const ( 13 // DefaultNamespace the standard namespace for Jenkins X 14 DefaultNamespace = "jx" 15 16 // PodNamespaceFile the file path and name for pod namespace 17 PodNamespaceFile = "/var/run/secrets/kubernetes.io/serviceaccount/namespace" 18 ) 19 20 // KubeConfig implements kube interactions 21 type KubeConfig struct{} 22 23 // NewKubeConfig creates a new KubeConfig struct to be used to interact with the underlying kube system 24 func NewKubeConfig() Kuber { 25 return &KubeConfig{} 26 } 27 28 // CurrentContextName returns the current context name 29 func CurrentContextName(config *api.Config) string { 30 if config != nil { 31 return config.CurrentContext 32 } 33 return "" 34 } 35 36 // CurrentContext returns the current context 37 func CurrentContext(config *api.Config) *api.Context { 38 if config != nil { 39 name := config.CurrentContext 40 if name != "" && config.Contexts != nil { 41 return config.Contexts[name] 42 } 43 } 44 return nil 45 } 46 47 // CurrentCluster returns the current cluster 48 func CurrentCluster(config *api.Config) (string, *api.Cluster) { 49 if config != nil { 50 context := CurrentContext(config) 51 if context != nil && config.Clusters != nil { 52 return context.Cluster, config.Clusters[context.Cluster] 53 } 54 } 55 return "", nil 56 } 57 58 // Cluster returns the cluster of the given config 59 func Cluster(config *api.Config) string { 60 if config != nil { 61 context := CurrentContext(config) 62 if context != nil && config.Clusters != nil { 63 return context.Cluster 64 } 65 } 66 return "" 67 } 68 69 // CurrentServer returns the current context's server 70 func CurrentServer(config *api.Config) string { 71 context := CurrentContext(config) 72 return Server(config, context) 73 } 74 75 // Server returns the server of the given context 76 func Server(config *api.Config, context *api.Context) string { 77 if context != nil && config != nil && config.Clusters != nil { 78 cluster := config.Clusters[context.Cluster] 79 if cluster != nil { 80 return cluster.Server 81 } 82 } 83 return "" 84 } 85 86 // CertificateAuthorityData returns the certificate authority data for the given context 87 func CertificateAuthorityData(config *api.Config, context *api.Context) []byte { 88 if context != nil && config != nil && config.Clusters != nil { 89 cluster := config.Clusters[context.Cluster] 90 if cluster != nil { 91 return cluster.CertificateAuthorityData 92 } 93 } 94 return []byte{} 95 } 96 97 // UpdateConfig defines new config entries for jx 98 func (k *KubeConfig) UpdateConfig(namespace string, server string, caData string, user string, token string) error { 99 config, po, err := k.LoadConfig() 100 if err != nil { 101 return errors.Wrap(err, "loading existing config") 102 } 103 104 clusterName := "jx-cluster" 105 cluster := &api.Cluster{ 106 Server: server, 107 CertificateAuthorityData: []byte(caData), 108 } 109 110 authInfo := &api.AuthInfo{ 111 Token: token, 112 } 113 114 ctxName := fmt.Sprintf("jx-cluster-%s-ctx", user) 115 ctx := &api.Context{ 116 Cluster: clusterName, 117 AuthInfo: user, 118 Namespace: namespace, 119 } 120 121 config.Clusters[clusterName] = cluster 122 config.AuthInfos[user] = authInfo 123 config.Contexts[ctxName] = ctx 124 config.CurrentContext = ctxName 125 126 return clientcmd.ModifyConfig(po, *config, false) 127 } 128 129 // AddUserToConfig adds the given user to the config 130 func AddUserToConfig(user string, token string, config *api.Config) (*api.Config, error) { 131 currentClusterName, currentCluster := CurrentCluster(config) 132 if currentCluster == nil || currentClusterName == "" { 133 return config, errors.New("no cluster found in config") 134 } 135 currentCtx := CurrentContext(config) 136 currentNamespace := DefaultNamespace 137 if currentCtx != nil { 138 currentNamespace = currentCtx.Namespace 139 } 140 141 ctx := &api.Context{ 142 Cluster: currentClusterName, 143 AuthInfo: user, 144 Namespace: currentNamespace, 145 } 146 147 authInfo := &api.AuthInfo{ 148 Token: token, 149 } 150 151 config.AuthInfos[user] = authInfo 152 ctxName := fmt.Sprintf("jx-%s-%s-ctx", currentClusterName, user) 153 config.Contexts[ctxName] = ctx 154 config.CurrentContext = ctxName 155 156 return config, nil 157 } 158 159 // LoadConfig loads the Kubernetes configuration 160 func (k *KubeConfig) LoadConfig() (*api.Config, *clientcmd.PathOptions, error) { 161 po := clientcmd.NewDefaultPathOptions() 162 if po == nil { 163 return nil, po, fmt.Errorf("Could not find any default path options for the kubeconfig file usually found at ~/.kube/config") 164 } 165 config, err := po.GetStartingConfig() 166 if err != nil { 167 return nil, po, fmt.Errorf("Could not load the kube config file %s due to %s", po.GetDefaultFilename(), err) 168 } 169 return config, po, err 170 } 171 172 // CurrentNamespace returns the current namespace in the context 173 func CurrentNamespace(config *api.Config) string { 174 ctx := CurrentContext(config) 175 if ctx != nil { 176 n := ctx.Namespace 177 if n != "" { 178 return n 179 } 180 } 181 // if we are in a pod lets try load the pod namespace file 182 data, err := ioutil.ReadFile(PodNamespaceFile) 183 if err == nil { 184 n := string(data) 185 if n != "" { 186 return n 187 } 188 } 189 return "default" 190 }