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  }