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 <ijc@docker.com>
This commit is contained in:
Ian Campbell 2019-05-16 14:47:07 +01:00
parent 4f14c4995e
commit 1433e27420
3 changed files with 35 additions and 5 deletions

View File

@ -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)

View File

@ -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
}

View File

@ -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)