github.com/itscaro/cli@v0.0.0-20190705081621-c9db0fe93829/cli/context/kubernetes/load.go (about)

     1  package kubernetes
     2  
     3  import (
     4  	"os"
     5  	"path/filepath"
     6  
     7  	"github.com/docker/cli/cli/command"
     8  	"github.com/docker/cli/cli/context"
     9  	"github.com/docker/cli/cli/context/store"
    10  	api "github.com/docker/compose-on-kubernetes/api"
    11  	"github.com/docker/docker/pkg/homedir"
    12  	"github.com/pkg/errors"
    13  	"k8s.io/client-go/tools/clientcmd"
    14  	clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
    15  )
    16  
    17  // EndpointMeta is a typed wrapper around a context-store generic endpoint describing
    18  // a Kubernetes endpoint, without TLS data
    19  type EndpointMeta struct {
    20  	context.EndpointMetaBase
    21  	DefaultNamespace string                           `json:",omitempty"`
    22  	AuthProvider     *clientcmdapi.AuthProviderConfig `json:",omitempty"`
    23  	Exec             *clientcmdapi.ExecConfig         `json:",omitempty"`
    24  }
    25  
    26  var _ command.EndpointDefaultResolver = &EndpointMeta{}
    27  
    28  // Endpoint is a typed wrapper around a context-store generic endpoint describing
    29  // a Kubernetes endpoint, with TLS data
    30  type Endpoint struct {
    31  	EndpointMeta
    32  	TLSData *context.TLSData
    33  }
    34  
    35  func init() {
    36  	command.RegisterDefaultStoreEndpoints(
    37  		store.EndpointTypeGetter(KubernetesEndpoint, func() interface{} { return &EndpointMeta{} }),
    38  	)
    39  }
    40  
    41  // WithTLSData loads TLS materials for the endpoint
    42  func (c *EndpointMeta) WithTLSData(s store.Reader, contextName string) (Endpoint, error) {
    43  	tlsData, err := context.LoadTLSData(s, contextName, KubernetesEndpoint)
    44  	if err != nil {
    45  		return Endpoint{}, err
    46  	}
    47  	return Endpoint{
    48  		EndpointMeta: *c,
    49  		TLSData:      tlsData,
    50  	}, nil
    51  }
    52  
    53  // KubernetesConfig creates the kubernetes client config from the endpoint
    54  func (c *Endpoint) KubernetesConfig() clientcmd.ClientConfig {
    55  	cfg := clientcmdapi.NewConfig()
    56  	cluster := clientcmdapi.NewCluster()
    57  	cluster.Server = c.Host
    58  	cluster.InsecureSkipTLSVerify = c.SkipTLSVerify
    59  	authInfo := clientcmdapi.NewAuthInfo()
    60  	if c.TLSData != nil {
    61  		cluster.CertificateAuthorityData = c.TLSData.CA
    62  		authInfo.ClientCertificateData = c.TLSData.Cert
    63  		authInfo.ClientKeyData = c.TLSData.Key
    64  	}
    65  	authInfo.AuthProvider = c.AuthProvider
    66  	authInfo.Exec = c.Exec
    67  	cfg.Clusters["cluster"] = cluster
    68  	cfg.AuthInfos["authInfo"] = authInfo
    69  	ctx := clientcmdapi.NewContext()
    70  	ctx.AuthInfo = "authInfo"
    71  	ctx.Cluster = "cluster"
    72  	ctx.Namespace = c.DefaultNamespace
    73  	cfg.Contexts["context"] = ctx
    74  	cfg.CurrentContext = "context"
    75  	return clientcmd.NewDefaultClientConfig(*cfg, &clientcmd.ConfigOverrides{})
    76  }
    77  
    78  // ResolveDefault returns endpoint metadata for the default Kubernetes
    79  // endpoint, which is derived from the env-based kubeconfig.
    80  func (c *EndpointMeta) ResolveDefault(stackOrchestrator command.Orchestrator) (interface{}, *store.EndpointTLSData, error) {
    81  	kubeconfig := os.Getenv("KUBECONFIG")
    82  	if kubeconfig == "" {
    83  		kubeconfig = filepath.Join(homedir.Get(), ".kube/config")
    84  	}
    85  	kubeEP, err := FromKubeConfig(kubeconfig, "", "")
    86  	if err != nil {
    87  		if stackOrchestrator == command.OrchestratorKubernetes || stackOrchestrator == command.OrchestratorAll {
    88  			return nil, nil, errors.Wrapf(err, "default orchestrator is %s but unable to resolve kubernetes endpoint", stackOrchestrator)
    89  		}
    90  
    91  		// We deliberately quash the error here, returning nil
    92  		// for the first argument is sufficient to indicate we weren't able to
    93  		// provide a default
    94  		return nil, nil, nil
    95  	}
    96  
    97  	var tls *store.EndpointTLSData
    98  	if kubeEP.TLSData != nil {
    99  		tls = kubeEP.TLSData.ToStoreTLSData()
   100  	}
   101  	return kubeEP.EndpointMeta, tls, nil
   102  }
   103  
   104  // EndpointFromContext extracts kubernetes endpoint info from current context
   105  func EndpointFromContext(metadata store.Metadata) *EndpointMeta {
   106  	ep, ok := metadata.Endpoints[KubernetesEndpoint]
   107  	if !ok {
   108  		return nil
   109  	}
   110  	typed, ok := ep.(EndpointMeta)
   111  	if !ok {
   112  		return nil
   113  	}
   114  	return &typed
   115  }
   116  
   117  // ConfigFromContext resolves a kubernetes client config for the specified context.
   118  // If kubeconfigOverride is specified, use this config file instead of the context defaults.ConfigFromContext
   119  // if command.ContextDockerHost is specified as the context name, fallsback to the default user's kubeconfig file
   120  func ConfigFromContext(name string, s store.Reader) (clientcmd.ClientConfig, error) {
   121  	ctxMeta, err := s.GetMetadata(name)
   122  	if err != nil {
   123  		return nil, err
   124  	}
   125  	epMeta := EndpointFromContext(ctxMeta)
   126  	if epMeta != nil {
   127  		ep, err := epMeta.WithTLSData(s, name)
   128  		if err != nil {
   129  			return nil, err
   130  		}
   131  		return ep.KubernetesConfig(), nil
   132  	}
   133  	// context has no kubernetes endpoint
   134  	return api.NewKubernetesConfig(""), nil
   135  }