mirror of https://github.com/docker/cli.git
147 lines
4.7 KiB
Go
147 lines
4.7 KiB
Go
package kubernetes
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/docker/cli/cli/command"
|
|
"github.com/docker/cli/cli/context"
|
|
"github.com/docker/cli/cli/context/store"
|
|
api "github.com/docker/compose-on-kubernetes/api"
|
|
"github.com/docker/docker/pkg/homedir"
|
|
"github.com/pkg/errors"
|
|
"k8s.io/client-go/tools/clientcmd"
|
|
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
|
)
|
|
|
|
// EndpointMeta is a typed wrapper around a context-store generic endpoint describing
|
|
// a Kubernetes endpoint, without TLS data
|
|
type EndpointMeta struct {
|
|
context.EndpointMetaBase
|
|
DefaultNamespace string `json:",omitempty"`
|
|
AuthProvider *clientcmdapi.AuthProviderConfig `json:",omitempty"`
|
|
Exec *clientcmdapi.ExecConfig `json:",omitempty"`
|
|
UsernamePassword *UsernamePassword `json:"usernamePassword,omitempty"`
|
|
}
|
|
|
|
// UsernamePassword contains username/password auth info
|
|
type UsernamePassword struct {
|
|
Username string `json:"username,omitempty"`
|
|
Password string `json:"password,omitempty"`
|
|
}
|
|
|
|
var _ command.EndpointDefaultResolver = &EndpointMeta{}
|
|
|
|
// Endpoint is a typed wrapper around a context-store generic endpoint describing
|
|
// a Kubernetes endpoint, with TLS data
|
|
type Endpoint struct {
|
|
EndpointMeta
|
|
TLSData *context.TLSData
|
|
}
|
|
|
|
func init() {
|
|
command.RegisterDefaultStoreEndpoints(
|
|
store.EndpointTypeGetter(KubernetesEndpoint, func() interface{} { return &EndpointMeta{} }),
|
|
)
|
|
}
|
|
|
|
// WithTLSData loads TLS materials for the endpoint
|
|
func (c *EndpointMeta) WithTLSData(s store.Reader, contextName string) (Endpoint, error) {
|
|
tlsData, err := context.LoadTLSData(s, contextName, KubernetesEndpoint)
|
|
if err != nil {
|
|
return Endpoint{}, err
|
|
}
|
|
return Endpoint{
|
|
EndpointMeta: *c,
|
|
TLSData: tlsData,
|
|
}, nil
|
|
}
|
|
|
|
// KubernetesConfig creates the kubernetes client config from the endpoint
|
|
func (c *Endpoint) KubernetesConfig() clientcmd.ClientConfig {
|
|
cfg := clientcmdapi.NewConfig()
|
|
cluster := clientcmdapi.NewCluster()
|
|
cluster.Server = c.Host
|
|
cluster.InsecureSkipTLSVerify = c.SkipTLSVerify
|
|
authInfo := clientcmdapi.NewAuthInfo()
|
|
if c.TLSData != nil {
|
|
cluster.CertificateAuthorityData = c.TLSData.CA
|
|
authInfo.ClientCertificateData = c.TLSData.Cert
|
|
authInfo.ClientKeyData = c.TLSData.Key
|
|
}
|
|
if c.UsernamePassword != nil {
|
|
authInfo.Username = c.UsernamePassword.Username
|
|
authInfo.Password = c.UsernamePassword.Password
|
|
}
|
|
authInfo.AuthProvider = c.AuthProvider
|
|
authInfo.Exec = c.Exec
|
|
cfg.Clusters["cluster"] = cluster
|
|
cfg.AuthInfos["authInfo"] = authInfo
|
|
ctx := clientcmdapi.NewContext()
|
|
ctx.AuthInfo = "authInfo"
|
|
ctx.Cluster = "cluster"
|
|
ctx.Namespace = c.DefaultNamespace
|
|
cfg.Contexts["context"] = ctx
|
|
cfg.CurrentContext = "context"
|
|
return clientcmd.NewDefaultClientConfig(*cfg, &clientcmd.ConfigOverrides{})
|
|
}
|
|
|
|
// ResolveDefault returns endpoint metadata for the default Kubernetes
|
|
// endpoint, which is derived from the env-based kubeconfig.
|
|
func (c *EndpointMeta) ResolveDefault(stackOrchestrator command.Orchestrator) (interface{}, *store.EndpointTLSData, error) {
|
|
kubeconfig := os.Getenv("KUBECONFIG")
|
|
if kubeconfig == "" {
|
|
kubeconfig = filepath.Join(homedir.Get(), ".kube/config")
|
|
}
|
|
kubeEP, err := FromKubeConfig(kubeconfig, "", "")
|
|
if err != nil {
|
|
if stackOrchestrator == command.OrchestratorKubernetes || stackOrchestrator == command.OrchestratorAll {
|
|
return nil, nil, errors.Wrapf(err, "default orchestrator is %s but unable to resolve kubernetes endpoint", stackOrchestrator)
|
|
}
|
|
|
|
// We deliberately quash the error here, returning nil
|
|
// for the first argument is sufficient to indicate we weren't able to
|
|
// provide a default
|
|
return nil, nil, nil
|
|
}
|
|
|
|
var tls *store.EndpointTLSData
|
|
if kubeEP.TLSData != nil {
|
|
tls = kubeEP.TLSData.ToStoreTLSData()
|
|
}
|
|
return kubeEP.EndpointMeta, tls, nil
|
|
}
|
|
|
|
// EndpointFromContext extracts kubernetes endpoint info from current context
|
|
func EndpointFromContext(metadata store.Metadata) *EndpointMeta {
|
|
ep, ok := metadata.Endpoints[KubernetesEndpoint]
|
|
if !ok {
|
|
return nil
|
|
}
|
|
typed, ok := ep.(EndpointMeta)
|
|
if !ok {
|
|
return nil
|
|
}
|
|
return &typed
|
|
}
|
|
|
|
// ConfigFromContext resolves a kubernetes client config for the specified context.
|
|
// If kubeconfigOverride is specified, use this config file instead of the context defaults.ConfigFromContext
|
|
// if command.ContextDockerHost is specified as the context name, fallsback to the default user's kubeconfig file
|
|
func ConfigFromContext(name string, s store.Reader) (clientcmd.ClientConfig, error) {
|
|
ctxMeta, err := s.GetMetadata(name)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
epMeta := EndpointFromContext(ctxMeta)
|
|
if epMeta != nil {
|
|
ep, err := epMeta.WithTLSData(s, name)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return ep.KubernetesConfig(), nil
|
|
}
|
|
// context has no kubernetes endpoint
|
|
return api.NewKubernetesConfig(""), nil
|
|
}
|