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 }