From c455193d143327d2bc4b0eaee55b0e5d086300ff Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Fri, 17 May 2019 15:48:49 +0100 Subject: [PATCH] Push check for kubernetes requirement down into the endpoint This is less of a layering violation and removes some ugly hardcoded `"kubernetes"` strings which were needed to avoid an import loop. Signed-off-by: Ian Campbell --- cli/command/defaultcontextstore.go | 26 +++++++++++--------------- cli/context/kubernetes/load.go | 14 +++++++++++--- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/cli/command/defaultcontextstore.go b/cli/command/defaultcontextstore.go index 6187cdd89e..3140dc5030 100644 --- a/cli/command/defaultcontextstore.go +++ b/cli/command/defaultcontextstore.go @@ -35,8 +35,13 @@ type ContextStoreWithDefault struct { // which wants to be able to populate the store with whatever their default is. type EndpointDefaultResolver interface { // ResolveDefault returns values suitable for storing in store.Metadata.Endpoints - // and store.ContextTLSData.Endpoints. If there is no default then returns nil, nil. - ResolveDefault() (interface{}, *store.EndpointTLSData) + // and store.ContextTLSData.Endpoints. + // + // An error is only returned for something fatal, not simply + // the lack of a default (e.g. because the config file which + // would contain it is missing). If there is no default then + // returns nil, nil, nil. + ResolveDefault(Orchestrator) (interface{}, *store.EndpointTLSData, error) } // ResolveDefaultContext creates a Metadata for the current CLI invocation parameters @@ -66,22 +71,17 @@ func ResolveDefaultContext(opts *cliflags.CommonOptions, config *configfile.Conf contextTLSData.Endpoints[docker.DockerEndpoint] = *dockerEP.TLSData.ToStoreTLSData() } - // We open code the string "kubernetes" below because we - // cannot import KubernetesEndpoint from the corresponding - // package due to import loops. - wantKubernetesEP := stackOrchestrator == OrchestratorKubernetes || stackOrchestrator == OrchestratorAll - if err := storeconfig.ForeachEndpointType(func(n string, get store.TypeGetter) error { if n == docker.DockerEndpoint { // handled above return nil } ep := get() if i, ok := ep.(EndpointDefaultResolver); ok { - meta, tls := i.ResolveDefault() + meta, tls, err := i.ResolveDefault(stackOrchestrator) + if err != nil { + return err + } if meta == nil { - if wantKubernetesEP && n == "kubernetes" { - return errors.Errorf("default orchestrator is %s but unable to resolve kubernetes endpoint", stackOrchestrator) - } return nil } contextMetadata.Endpoints[n] = meta @@ -95,10 +95,6 @@ func ResolveDefaultContext(opts *cliflags.CommonOptions, config *configfile.Conf return nil, err } - if _, ok := contextMetadata.Endpoints["kubernetes"]; wantKubernetesEP && !ok { - return nil, errors.Errorf("default orchestrator is %s but kubernetes endpoint could not be found", stackOrchestrator) - } - return &DefaultContext{Meta: contextMetadata, TLS: contextTLSData}, nil } diff --git a/cli/context/kubernetes/load.go b/cli/context/kubernetes/load.go index 94044d8138..113ec1ad78 100644 --- a/cli/context/kubernetes/load.go +++ b/cli/context/kubernetes/load.go @@ -9,6 +9,7 @@ import ( "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" ) @@ -76,21 +77,28 @@ func (c *Endpoint) KubernetesConfig() clientcmd.ClientConfig { // ResolveDefault returns endpoint metadata for the default Kubernetes // endpoint, which is derived from the env-based kubeconfig. -func (c *EndpointMeta) ResolveDefault() (interface{}, *store.EndpointTLSData) { +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 { - return nil, 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 + return kubeEP.EndpointMeta, tls, nil } // EndpointFromContext extracts kubernetes endpoint info from current context