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 <ijc@docker.com>
This commit is contained in:
Ian Campbell 2019-05-17 15:48:49 +01:00
parent 520be05c49
commit c455193d14
2 changed files with 22 additions and 18 deletions

View File

@ -35,8 +35,13 @@ type ContextStoreWithDefault struct {
// which wants to be able to populate the store with whatever their default is. // which wants to be able to populate the store with whatever their default is.
type EndpointDefaultResolver interface { type EndpointDefaultResolver interface {
// ResolveDefault returns values suitable for storing in store.Metadata.Endpoints // ResolveDefault returns values suitable for storing in store.Metadata.Endpoints
// and store.ContextTLSData.Endpoints. If there is no default then returns nil, nil. // and store.ContextTLSData.Endpoints.
ResolveDefault() (interface{}, *store.EndpointTLSData) //
// 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 // 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() 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 err := storeconfig.ForeachEndpointType(func(n string, get store.TypeGetter) error {
if n == docker.DockerEndpoint { // handled above if n == docker.DockerEndpoint { // handled above
return nil return nil
} }
ep := get() ep := get()
if i, ok := ep.(EndpointDefaultResolver); ok { 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 meta == nil {
if wantKubernetesEP && n == "kubernetes" {
return errors.Errorf("default orchestrator is %s but unable to resolve kubernetes endpoint", stackOrchestrator)
}
return nil return nil
} }
contextMetadata.Endpoints[n] = meta contextMetadata.Endpoints[n] = meta
@ -95,10 +95,6 @@ func ResolveDefaultContext(opts *cliflags.CommonOptions, config *configfile.Conf
return nil, err 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 return &DefaultContext{Meta: contextMetadata, TLS: contextTLSData}, nil
} }

View File

@ -9,6 +9,7 @@ import (
"github.com/docker/cli/cli/context/store" "github.com/docker/cli/cli/context/store"
api "github.com/docker/compose-on-kubernetes/api" api "github.com/docker/compose-on-kubernetes/api"
"github.com/docker/docker/pkg/homedir" "github.com/docker/docker/pkg/homedir"
"github.com/pkg/errors"
"k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/tools/clientcmd"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api" 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 // ResolveDefault returns endpoint metadata for the default Kubernetes
// endpoint, which is derived from the env-based kubeconfig. // 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") kubeconfig := os.Getenv("KUBECONFIG")
if kubeconfig == "" { if kubeconfig == "" {
kubeconfig = filepath.Join(homedir.Get(), ".kube/config") kubeconfig = filepath.Join(homedir.Get(), ".kube/config")
} }
kubeEP, err := FromKubeConfig(kubeconfig, "", "") kubeEP, err := FromKubeConfig(kubeconfig, "", "")
if err != nil { 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 var tls *store.EndpointTLSData
if kubeEP.TLSData != nil { if kubeEP.TLSData != nil {
tls = kubeEP.TLSData.ToStoreTLSData() tls = kubeEP.TLSData.ToStoreTLSData()
} }
return kubeEP.EndpointMeta, tls return kubeEP.EndpointMeta, tls, nil
} }
// EndpointFromContext extracts kubernetes endpoint info from current context // EndpointFromContext extracts kubernetes endpoint info from current context