From 1433e274204f6bd239f59d14eaf103dfa859ad8c Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Thu, 16 May 2019 14:47:07 +0100 Subject: [PATCH] Allow dynamically registered context endpoint to provide their defaults. Previously an endpoint registered using `RegisterDefaultStoreEndpoints` would not be taken into consideration by `resolveDefaultContext` and so could not provide any details. Resolve this by passing a `store.Config` to `resolveDefaultContext` and using it to iterate over all registered endpoints. Any endpoint can ensure that their type implements the new `EndpointDefaultResolver` in order to provide a default. The Docker and Kubernetes endpoints are special cased, shortly the Kubernetes one will be refactored to be dynamically registered. Signed-off-by: Ian Campbell --- cli/command/cli.go | 7 +++--- cli/command/defaultcontextstore.go | 31 ++++++++++++++++++++++++- cli/command/defaultcontextstore_test.go | 2 +- 3 files changed, 35 insertions(+), 5 deletions(-) diff --git a/cli/command/cli.go b/cli/command/cli.go index 776688691f..5abc54e0fc 100644 --- a/cli/command/cli.go +++ b/cli/command/cli.go @@ -214,7 +214,7 @@ func (cli *DockerCli) Initialize(opts *cliflags.ClientOptions, ops ...Initialize cli.contextStore = &ContextStoreWithDefault{ Store: baseContextStore, Resolver: func() (*DefaultContext, error) { - return resolveDefaultContext(opts.Common, cli.ConfigFile(), cli.Err()) + return resolveDefaultContext(opts.Common, cli.ConfigFile(), cli.contextStoreConfig, cli.Err()) }, } cli.currentContext, err = resolveContextName(opts.Common, cli.configFile, cli.contextStore) @@ -259,10 +259,11 @@ func (cli *DockerCli) Initialize(opts *cliflags.ClientOptions, ops ...Initialize // NewAPIClientFromFlags creates a new APIClient from command line flags func NewAPIClientFromFlags(opts *cliflags.CommonOptions, configFile *configfile.ConfigFile) (client.APIClient, error) { + storeConfig := defaultContextStoreConfig() store := &ContextStoreWithDefault{ - Store: store.New(cliconfig.ContextStoreDir(), defaultContextStoreConfig()), + Store: store.New(cliconfig.ContextStoreDir(), storeConfig), Resolver: func() (*DefaultContext, error) { - return resolveDefaultContext(opts, configFile, ioutil.Discard) + return resolveDefaultContext(opts, configFile, storeConfig, ioutil.Discard) }, } contextName, err := resolveContextName(opts, configFile, store) diff --git a/cli/command/defaultcontextstore.go b/cli/command/defaultcontextstore.go index 6a55b79086..1489990947 100644 --- a/cli/command/defaultcontextstore.go +++ b/cli/command/defaultcontextstore.go @@ -35,8 +35,16 @@ type ContextStoreWithDefault struct { Resolver DefaultContextResolver } +// EndpointDefaultResolver is implemented by any EndpointMeta object +// 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) +} + // resolveDefaultContext creates a Metadata for the current CLI invocation parameters -func resolveDefaultContext(opts *cliflags.CommonOptions, config *configfile.ConfigFile, stderr io.Writer) (*DefaultContext, error) { +func resolveDefaultContext(opts *cliflags.CommonOptions, config *configfile.ConfigFile, storeconfig store.Config, stderr io.Writer) (*DefaultContext, error) { stackOrchestrator, err := GetStackOrchestrator("", "", config.StackOrchestrator, stderr) if err != nil { return nil, err @@ -78,6 +86,27 @@ func resolveDefaultContext(opts *cliflags.CommonOptions, config *configfile.Conf } } + if err := storeconfig.ForeachEndpointType(func(n string, get store.TypeGetter) error { + if n == docker.DockerEndpoint || n == kubernetes.KubernetesEndpoint { // handled above + return nil + } + ep := get() + if i, ok := ep.(EndpointDefaultResolver); ok { + meta, tls := i.ResolveDefault() + if meta == nil { + return nil + } + contextMetadata.Endpoints[n] = meta + if tls != nil { + contextTLSData.Endpoints[n] = *tls + } + } + // Nothing to be done + return nil + }); err != nil { + return nil, err + } + return &DefaultContext{Meta: contextMetadata, TLS: contextTLSData}, nil } diff --git a/cli/command/defaultcontextstore_test.go b/cli/command/defaultcontextstore_test.go index 7acdfd3dbc..493d0f4fe5 100644 --- a/cli/command/defaultcontextstore_test.go +++ b/cli/command/defaultcontextstore_test.go @@ -72,7 +72,7 @@ func TestDefaultContextInitializer(t *testing.T) { TLSOptions: &tlsconfig.Options{ CAFile: "./testdata/ca.pem", }, - }, cli.ConfigFile(), cli.Err()) + }, cli.ConfigFile(), defaultContextStoreConfig(), cli.Err()) assert.NilError(t, err) assert.Equal(t, "default", ctx.Meta.Name) assert.Equal(t, OrchestratorAll, ctx.Meta.Metadata.(DockerContext).StackOrchestrator)