diff --git a/aci/backend.go b/aci/backend.go index c9359c211..c18b32c6e 100644 --- a/aci/backend.go +++ b/aci/backend.go @@ -17,7 +17,6 @@ package aci import ( - "context" "strings" "github.com/Azure/azure-sdk-for-go/services/containerinstance/mgmt/2019-12-01/containerinstance" @@ -68,9 +67,9 @@ func init() { backend.Register(backendType, backendType, service, getCloudService) } -func service(ctx context.Context) (backend.Service, error) { - contextStore := store.ContextStore(ctx) - currentContext := apicontext.CurrentContext(ctx) +func service() (backend.Service, error) { + contextStore := store.Instance() + currentContext := apicontext.Current() var aciContext store.AciContext if err := contextStore.GetEndpoint(currentContext, &aciContext); err != nil { diff --git a/api/backend/backend.go b/api/backend/backend.go index b1aa3eadc..94e7d0a0e 100644 --- a/api/backend/backend.go +++ b/api/backend/backend.go @@ -17,7 +17,6 @@ package backend import ( - "context" "errors" "fmt" @@ -38,7 +37,7 @@ var ( errTypeRegistered = errors.New("backend: already registered") ) -type initFunc func(context.Context) (Service, error) +type initFunc func() (Service, error) type getCloudServiceFunc func() (cloud.Service, error) type registeredBackend struct { @@ -52,6 +51,18 @@ var backends = struct { r []*registeredBackend }{} +var instance Service + +// Current return the active backend instance +func Current() Service { + return instance +} + +// WithBackend set the active backend instance +func WithBackend(s Service) { + instance = s +} + // Service aggregates the service interfaces type Service interface { ContainerService() containers.Service @@ -85,10 +96,10 @@ func Register(name string, backendType string, init initFunc, getCoudService get // Get returns the backend registered for a particular type, it returns // an error if there is no registered backends for the given type. -func Get(ctx context.Context, backendType string) (Service, error) { +func Get(backendType string) (Service, error) { for _, b := range backends.r { if b.backendType == backendType { - return b.init(ctx) + return b.init() } } @@ -97,7 +108,7 @@ func Get(ctx context.Context, backendType string) (Service, error) { // GetCloudService returns the backend registered for a particular type, it returns // an error if there is no registered backends for the given type. -func GetCloudService(ctx context.Context, backendType string) (cloud.Service, error) { +func GetCloudService(backendType string) (cloud.Service, error) { for _, b := range backends.r { if b.backendType == backendType { return b.getCloudService() diff --git a/api/client/client.go b/api/client/client.go index bbcd759a4..faf081c42 100644 --- a/api/client/client.go +++ b/api/client/client.go @@ -25,6 +25,7 @@ import ( "github.com/docker/compose-cli/api/containers" apicontext "github.com/docker/compose-cli/api/context" "github.com/docker/compose-cli/api/context/store" + "github.com/docker/compose-cli/api/errdefs" "github.com/docker/compose-cli/api/resources" "github.com/docker/compose-cli/api/secrets" "github.com/docker/compose-cli/api/volumes" @@ -32,31 +33,17 @@ import ( // New returns a backend client associated with current context func New(ctx context.Context) (*Client, error) { - return newWithDefaultBackend(ctx, "") -} - -// NewWithDefaultLocalBackend returns a backend client associated with current context or local backend if on default context type -func NewWithDefaultLocalBackend(ctx context.Context) (*Client, error) { - return newWithDefaultBackend(ctx, store.LocalContextType) -} - -func newWithDefaultBackend(ctx context.Context, defaultBackend string) (*Client, error) { - currentContext := apicontext.CurrentContext(ctx) - s := store.ContextStore(ctx) + currentContext := apicontext.Current() + s := store.Instance() cc, err := s.Get(currentContext) if err != nil { return nil, err } - backendName := cc.Type() - if backendName == store.DefaultContextType && defaultBackend != "" { - backendName = defaultBackend - } - - service, err := backend.Get(ctx, backendName) - if err != nil { - return nil, err + service := backend.Current() + if service == nil { + return nil, errdefs.ErrNotFound } client := NewClient(cc.Type(), service) @@ -73,7 +60,7 @@ func NewClient(backendType string, service backend.Service) Client { // GetCloudService returns a backend CloudService (typically login, create context) func GetCloudService(ctx context.Context, backendType string) (cloud.Service, error) { - return backend.GetCloudService(ctx, backendType) + return backend.GetCloudService(backendType) } // Client is a multi-backend client diff --git a/api/config/config.go b/api/config/config.go index b771ded89..12fe9214e 100644 --- a/api/config/config.go +++ b/api/config/config.go @@ -17,7 +17,6 @@ package config import ( - "context" "encoding/json" "io/ioutil" "os" @@ -28,17 +27,16 @@ import ( "github.com/docker/compose-cli/api/context/store" ) -type dirKey struct{} +var configDir string // WithDir sets the config directory path in the context -func WithDir(ctx context.Context, path string) context.Context { - return context.WithValue(ctx, dirKey{}, path) +func WithDir(path string) { + configDir = path } // Dir returns the config directory path -func Dir(ctx context.Context) string { - cd, _ := ctx.Value(dirKey{}).(string) - return cd +func Dir() string { + return configDir } // LoadFile loads the docker configuration diff --git a/api/context/context.go b/api/context/context.go index 27ac5e36f..5d8577a4f 100644 --- a/api/context/context.go +++ b/api/context/context.go @@ -16,35 +16,14 @@ package context -import ( - gocontext "context" - - "golang.org/x/net/context" - - cliflags "github.com/docker/cli/cli/flags" -) - -type currentContextKey struct{} -type cliOptionsKey struct{} +var current string // WithCurrentContext sets the name of the current docker context -func WithCurrentContext(ctx gocontext.Context, contextName string) context.Context { - return context.WithValue(ctx, currentContextKey{}, contextName) +func WithCurrentContext(contextName string) { + current = contextName } -// CurrentContext returns the current context name -func CurrentContext(ctx context.Context) string { - cc, _ := ctx.Value(currentContextKey{}).(string) - return cc -} - -// WithCliOptions sets CLI options -func WithCliOptions(ctx gocontext.Context, options cliflags.CommonOptions) context.Context { - return context.WithValue(ctx, cliOptionsKey{}, options) -} - -// CliOptions returns common cli options -func CliOptions(ctx context.Context) cliflags.CommonOptions { - cc, _ := ctx.Value(cliOptionsKey{}).(cliflags.CommonOptions) - return cc +// Current returns the current context name +func Current() string { + return current } diff --git a/api/context/store/store.go b/api/context/store/store.go index 5427f7529..146ed21f8 100644 --- a/api/context/store/store.go +++ b/api/context/store/store.go @@ -17,7 +17,6 @@ package store import ( - "context" "encoding/json" "fmt" "io/ioutil" @@ -67,17 +66,16 @@ const ( metaFile = "meta.json" ) -type contextStoreKey struct{} +var instance Store // WithContextStore adds the store to the context -func WithContextStore(ctx context.Context, store Store) context.Context { - return context.WithValue(ctx, contextStoreKey{}, store) +func WithContextStore(store Store) { + instance = store } -// ContextStore returns the store from the context -func ContextStore(ctx context.Context) Store { - s, _ := ctx.Value(contextStoreKey{}).(Store) - return s +// Instance returns the store from the context +func Instance() Store { + return instance } // Store is the context store diff --git a/cli/cmd/compose/build.go b/cli/cmd/compose/build.go index 3bb7c3157..c5f58b731 100644 --- a/cli/cmd/compose/build.go +++ b/cli/cmd/compose/build.go @@ -63,7 +63,7 @@ func buildCommand(p *projectOptions) *cobra.Command { } func runBuild(ctx context.Context, opts buildOptions, services []string) error { - c, err := client.NewWithDefaultLocalBackend(ctx) + c, err := client.New(ctx) if err != nil { return err } diff --git a/cli/cmd/compose/convert.go b/cli/cmd/compose/convert.go index 46fb9a8ca..d4165f93b 100644 --- a/cli/cmd/compose/convert.go +++ b/cli/cmd/compose/convert.go @@ -77,7 +77,7 @@ func convertCommand(p *projectOptions) *cobra.Command { func runConvert(ctx context.Context, opts convertOptions, services []string) error { var json []byte - c, err := client.NewWithDefaultLocalBackend(ctx) + c, err := client.New(ctx) if err != nil { return err } @@ -88,7 +88,7 @@ func runConvert(ctx context.Context, opts convertOptions, services []string) err } if opts.resolve { - configFile, err := cliconfig.Load(config.Dir(ctx)) + configFile, err := cliconfig.Load(config.Dir()) if err != nil { return err } diff --git a/cli/cmd/compose/down.go b/cli/cmd/compose/down.go index 36ac97e5b..edc669682 100644 --- a/cli/cmd/compose/down.go +++ b/cli/cmd/compose/down.go @@ -69,7 +69,7 @@ func downCommand(p *projectOptions, contextType string) *cobra.Command { } func runDown(ctx context.Context, opts downOptions) error { - c, err := client.NewWithDefaultLocalBackend(ctx) + c, err := client.New(ctx) if err != nil { return err } diff --git a/cli/cmd/compose/events.go b/cli/cmd/compose/events.go index e37b150a2..0628f9708 100644 --- a/cli/cmd/compose/events.go +++ b/cli/cmd/compose/events.go @@ -51,7 +51,7 @@ func eventsCommand(p *projectOptions) *cobra.Command { } func runEvents(ctx context.Context, opts eventsOpts, services []string) error { - c, err := client.NewWithDefaultLocalBackend(ctx) + c, err := client.New(ctx) if err != nil { return err } diff --git a/cli/cmd/compose/exec.go b/cli/cmd/compose/exec.go index b9b92ae06..1cd0170d3 100644 --- a/cli/cmd/compose/exec.go +++ b/cli/cmd/compose/exec.go @@ -75,7 +75,7 @@ func execCommand(p *projectOptions) *cobra.Command { } func runExec(ctx context.Context, opts execOpts) error { - c, err := client.NewWithDefaultLocalBackend(ctx) + c, err := client.New(ctx) if err != nil { return err } diff --git a/cli/cmd/compose/kill.go b/cli/cmd/compose/kill.go index 7dbf08ff4..1ffb99dd6 100644 --- a/cli/cmd/compose/kill.go +++ b/cli/cmd/compose/kill.go @@ -49,7 +49,7 @@ func killCommand(p *projectOptions) *cobra.Command { } func runKill(ctx context.Context, opts killOptions, services []string) error { - c, err := client.NewWithDefaultLocalBackend(ctx) + c, err := client.New(ctx) if err != nil { return err } diff --git a/cli/cmd/compose/list.go b/cli/cmd/compose/list.go index 54f8d1d40..8ae601d87 100644 --- a/cli/cmd/compose/list.go +++ b/cli/cmd/compose/list.go @@ -69,7 +69,7 @@ func runList(ctx context.Context, opts lsOptions) error { return err } - c, err := client.NewWithDefaultLocalBackend(ctx) + c, err := client.New(ctx) if err != nil { return err } diff --git a/cli/cmd/compose/logs.go b/cli/cmd/compose/logs.go index a87b44429..75ec48039 100644 --- a/cli/cmd/compose/logs.go +++ b/cli/cmd/compose/logs.go @@ -62,7 +62,7 @@ func logsCommand(p *projectOptions, contextType string) *cobra.Command { } func runLogs(ctx context.Context, opts logsOptions, services []string) error { - c, err := client.NewWithDefaultLocalBackend(ctx) + c, err := client.New(ctx) if err != nil { return err } diff --git a/cli/cmd/compose/pause.go b/cli/cmd/compose/pause.go index 8cd08c266..87f8fc716 100644 --- a/cli/cmd/compose/pause.go +++ b/cli/cmd/compose/pause.go @@ -44,7 +44,7 @@ func pauseCommand(p *projectOptions) *cobra.Command { } func runPause(ctx context.Context, opts pauseOptions, services []string) error { - c, err := client.NewWithDefaultLocalBackend(ctx) + c, err := client.New(ctx) if err != nil { return err } @@ -79,7 +79,7 @@ func unpauseCommand(p *projectOptions) *cobra.Command { } func runUnPause(ctx context.Context, opts unpauseOptions, services []string) error { - c, err := client.NewWithDefaultLocalBackend(ctx) + c, err := client.New(ctx) if err != nil { return err } diff --git a/cli/cmd/compose/ps.go b/cli/cmd/compose/ps.go index 54161759a..be0f0a104 100644 --- a/cli/cmd/compose/ps.go +++ b/cli/cmd/compose/ps.go @@ -58,7 +58,7 @@ func psCommand(p *projectOptions) *cobra.Command { } func runPs(ctx context.Context, opts psOptions) error { - c, err := client.NewWithDefaultLocalBackend(ctx) + c, err := client.New(ctx) if err != nil { return err } diff --git a/cli/cmd/compose/pull.go b/cli/cmd/compose/pull.go index 0bbd6e418..44ccbae37 100644 --- a/cli/cmd/compose/pull.go +++ b/cli/cmd/compose/pull.go @@ -49,7 +49,7 @@ func pullCommand(p *projectOptions) *cobra.Command { } func runPull(ctx context.Context, opts pullOptions, services []string) error { - c, err := client.NewWithDefaultLocalBackend(ctx) + c, err := client.New(ctx) if err != nil { return err } diff --git a/cli/cmd/compose/push.go b/cli/cmd/compose/push.go index 21c6f1ee1..9c1b6a0d2 100644 --- a/cli/cmd/compose/push.go +++ b/cli/cmd/compose/push.go @@ -50,7 +50,7 @@ func pushCommand(p *projectOptions) *cobra.Command { } func runPush(ctx context.Context, opts pushOptions, services []string) error { - c, err := client.NewWithDefaultLocalBackend(ctx) + c, err := client.New(ctx) if err != nil { return err } diff --git a/cli/cmd/compose/remove.go b/cli/cmd/compose/remove.go index 02a0e0b8c..753f8300a 100644 --- a/cli/cmd/compose/remove.go +++ b/cli/cmd/compose/remove.go @@ -61,7 +61,7 @@ Any data which is not in a volume will be lost.`, } func runRemove(ctx context.Context, opts removeOptions, services []string) error { - c, err := client.NewWithDefaultLocalBackend(ctx) + c, err := client.New(ctx) if err != nil { return err } diff --git a/cli/cmd/compose/start.go b/cli/cmd/compose/start.go index ed17ced89..ac50b7199 100644 --- a/cli/cmd/compose/start.go +++ b/cli/cmd/compose/start.go @@ -45,7 +45,7 @@ func startCommand(p *projectOptions) *cobra.Command { } func runStart(ctx context.Context, opts startOptions, services []string) error { - c, err := client.NewWithDefaultLocalBackend(ctx) + c, err := client.New(ctx) if err != nil { return err } diff --git a/cli/cmd/compose/stop.go b/cli/cmd/compose/stop.go index a0c87007e..f80dc1c94 100644 --- a/cli/cmd/compose/stop.go +++ b/cli/cmd/compose/stop.go @@ -52,7 +52,7 @@ func stopCommand(p *projectOptions) *cobra.Command { } func runStop(ctx context.Context, opts stopOptions, services []string) error { - c, err := client.NewWithDefaultLocalBackend(ctx) + c, err := client.New(ctx) if err != nil { return err } diff --git a/cli/cmd/compose/top.go b/cli/cmd/compose/top.go index c7d839cc3..cc5719baf 100644 --- a/cli/cmd/compose/top.go +++ b/cli/cmd/compose/top.go @@ -49,7 +49,7 @@ func topCommand(p *projectOptions) *cobra.Command { } func runTop(ctx context.Context, opts topOptions, services []string) error { - c, err := client.NewWithDefaultLocalBackend(ctx) + c, err := client.New(ctx) if err != nil { return err } diff --git a/cli/cmd/compose/up.go b/cli/cmd/compose/up.go index f9ac8e16a..559557752 100644 --- a/cli/cmd/compose/up.go +++ b/cli/cmd/compose/up.go @@ -338,7 +338,7 @@ func setServiceScale(project *types.Project, name string, replicas int) error { } func setup(ctx context.Context, opts composeOptions, services []string) (*client.Client, *types.Project, error) { - c, err := client.NewWithDefaultLocalBackend(ctx) + c, err := client.New(ctx) if err != nil { return nil, nil, err } diff --git a/cli/cmd/context/create.go b/cli/cmd/context/create.go index aa24f15d1..b2dcd3ca6 100644 --- a/cli/cmd/context/create.go +++ b/cli/cmd/context/create.go @@ -17,7 +17,6 @@ package context import ( - "context" "fmt" "strings" @@ -103,15 +102,15 @@ func createLocalCommand() *cobra.Command { Args: cobra.ExactArgs(1), Hidden: true, RunE: func(cmd *cobra.Command, args []string) error { - return createDockerContext(cmd.Context(), args[0], store.LocalContextType, opts.description, store.LocalContext{}) + return createDockerContext(args[0], store.LocalContextType, opts.description, store.LocalContext{}) }, } addDescriptionFlag(cmd, &opts.description) return cmd } -func createDockerContext(ctx context.Context, name string, contextType string, description string, data interface{}) error { - s := store.ContextStore(ctx) +func createDockerContext(name string, contextType string, description string, data interface{}) error { + s := store.Instance() result := s.Create( name, contextType, @@ -122,8 +121,8 @@ func createDockerContext(ctx context.Context, name string, contextType string, d return result } -func contextExists(ctx context.Context, name string) bool { - s := store.ContextStore(ctx) +func contextExists(name string) bool { + s := store.Instance() return s.ContextExists(name) } diff --git a/cli/cmd/context/create_aci.go b/cli/cmd/context/create_aci.go index 0c6f7c41c..3efaee52c 100644 --- a/cli/cmd/context/create_aci.go +++ b/cli/cmd/context/create_aci.go @@ -57,7 +57,7 @@ func createAciCommand() *cobra.Command { } func runCreateAci(ctx context.Context, contextName string, opts aci.ContextParams) error { - if contextExists(ctx, contextName) { + if contextExists(contextName) { return errors.Wrapf(errdefs.ErrAlreadyExists, "context %s", contextName) } contextData, description, err := getAciContextData(ctx, opts) @@ -67,7 +67,7 @@ func runCreateAci(ctx context.Context, contextName string, opts aci.ContextParam } return err } - return createDockerContext(ctx, contextName, store.AciContextType, description, contextData) + return createDockerContext(contextName, store.AciContextType, description, contextData) } diff --git a/cli/cmd/context/create_ecs.go b/cli/cmd/context/create_ecs.go index 34ba11c42..6570020e4 100644 --- a/cli/cmd/context/create_ecs.go +++ b/cli/cmd/context/create_ecs.go @@ -109,7 +109,7 @@ func parseAccessKeysFile(file string, opts *ecs.ContextParams) error { } func runCreateLocalSimulation(ctx context.Context, contextName string, opts ecs.ContextParams) error { - if contextExists(ctx, contextName) { + if contextExists(contextName) { return errors.Wrapf(errdefs.ErrAlreadyExists, "context %q", contextName) } cs, err := client.GetCloudService(ctx, store.EcsLocalSimulationContextType) @@ -120,18 +120,18 @@ func runCreateLocalSimulation(ctx context.Context, contextName string, opts ecs. if err != nil { return err } - return createDockerContext(ctx, contextName, store.EcsLocalSimulationContextType, description, data) + return createDockerContext(contextName, store.EcsLocalSimulationContextType, description, data) } func runCreateEcs(ctx context.Context, contextName string, opts ecs.ContextParams) error { - if contextExists(ctx, contextName) { + if contextExists(contextName) { return errors.Wrapf(errdefs.ErrAlreadyExists, "context %q", contextName) } contextData, description, err := getEcsContextData(ctx, opts) if err != nil { return err } - return createDockerContext(ctx, contextName, store.EcsContextType, description, contextData) + return createDockerContext(contextName, store.EcsContextType, description, contextData) } diff --git a/cli/cmd/context/create_kube.go b/cli/cmd/context/create_kube.go index 609716e38..1eb269cd7 100644 --- a/cli/cmd/context/create_kube.go +++ b/cli/cmd/context/create_kube.go @@ -19,8 +19,6 @@ package context import ( - "context" - "github.com/pkg/errors" "github.com/spf13/cobra" @@ -45,7 +43,7 @@ func createKubeCommand() *cobra.Command { Short: "Create context for a Kubernetes Cluster", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - return runCreateKube(cmd.Context(), args[0], opts) + return runCreateKube(args[0], opts) }, } @@ -56,8 +54,8 @@ func createKubeCommand() *cobra.Command { return cmd } -func runCreateKube(ctx context.Context, contextName string, opts kube.ContextParams) error { - if contextExists(ctx, contextName) { +func runCreateKube(contextName string, opts kube.ContextParams) error { + if contextExists(contextName) { return errors.Wrapf(errdefs.ErrAlreadyExists, "context %q", contextName) } @@ -65,5 +63,5 @@ func runCreateKube(ctx context.Context, contextName string, opts kube.ContextPar if err != nil { return err } - return createDockerContext(ctx, contextName, store.KubeContextType, description, contextData) + return createDockerContext(contextName, store.KubeContextType, description, contextData) } diff --git a/cli/cmd/context/ls.go b/cli/cmd/context/ls.go index ffcd1b8e2..d301f3bc2 100644 --- a/cli/cmd/context/ls.go +++ b/cli/cmd/context/ls.go @@ -73,9 +73,8 @@ func runList(cmd *cobra.Command, opts lsOpts) error { return nil } - ctx := cmd.Context() - currentContext := apicontext.CurrentContext(ctx) - s := store.ContextStore(ctx) + currentContext := apicontext.Current() + s := store.Instance() contexts, err := s.List() if err != nil { return err diff --git a/cli/cmd/context/rm.go b/cli/cmd/context/rm.go index 473b13e6e..b6bbde59b 100644 --- a/cli/cmd/context/rm.go +++ b/cli/cmd/context/rm.go @@ -17,7 +17,6 @@ package context import ( - "context" "errors" "fmt" @@ -41,7 +40,7 @@ func removeCommand() *cobra.Command { Aliases: []string{"remove"}, Args: cobra.MinimumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - return runRemove(cmd.Context(), args, opts.force) + return runRemove(args, opts.force) }, } cmd.Flags().BoolVarP(&opts.force, "force", "f", false, "Force removing current context") @@ -49,15 +48,15 @@ func removeCommand() *cobra.Command { return cmd } -func runRemove(ctx context.Context, args []string, force bool) error { - currentContext := apicontext.CurrentContext(ctx) - s := store.ContextStore(ctx) +func runRemove(args []string, force bool) error { + currentContext := apicontext.Current() + s := store.Instance() var errs *multierror.Error for _, contextName := range args { if currentContext == contextName { if force { - if err := runUse(ctx, "default"); err != nil { + if err := runUse("default"); err != nil { errs = multierror.Append(errs, errors.New("cannot delete current context")) } else { errs = removeContext(s, contextName, errs) diff --git a/cli/cmd/context/show.go b/cli/cmd/context/show.go index 69dc91da1..8ba588a5d 100644 --- a/cli/cmd/context/show.go +++ b/cli/cmd/context/show.go @@ -17,7 +17,6 @@ package context import ( - "context" "fmt" "github.com/spf13/cobra" @@ -32,16 +31,16 @@ func showCommand() *cobra.Command { Short: "Print the current context", Args: cobra.NoArgs, RunE: func(cmd *cobra.Command, args []string) error { - return runShow(cmd.Context()) + return runShow() }, } } -func runShow(ctx context.Context) error { - name := apicontext.CurrentContext(ctx) +func runShow() error { + name := apicontext.Current() // Match behavior of existing CLI if name != store.DefaultContextName { - s := store.ContextStore(ctx) + s := store.Instance() if _, err := s.Get(name); err != nil { return err } diff --git a/cli/cmd/context/update.go b/cli/cmd/context/update.go index f21182b47..52e3bf7ee 100644 --- a/cli/cmd/context/update.go +++ b/cli/cmd/context/update.go @@ -72,7 +72,7 @@ $ docker context update my-context --description "some description" --docker "ho } func runUpdate(cmd *cobra.Command, name string) error { - s := store.ContextStore(cmd.Context()) + s := store.Instance() dockerContext, err := s.Get(name) if err == nil && dockerContext != nil { if dockerContext.Type() != store.DefaultContextType { diff --git a/cli/cmd/context/use.go b/cli/cmd/context/use.go index 8c4684c50..5e8bbfd6a 100644 --- a/cli/cmd/context/use.go +++ b/cli/cmd/context/use.go @@ -17,7 +17,6 @@ package context import ( - "context" "fmt" "github.com/spf13/cobra" @@ -32,20 +31,20 @@ func useCommand() *cobra.Command { Short: "Set the default context", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { - return runUse(cmd.Context(), args[0]) + return runUse(args[0]) }, } } -func runUse(ctx context.Context, name string) error { - s := store.ContextStore(ctx) +func runUse(name string) error { + s := store.Instance() // Match behavior of existing CLI if name != store.DefaultContextName { if _, err := s.Get(name); err != nil { return err } } - if err := config.WriteCurrentContext(config.Dir(ctx), name); err != nil { + if err := config.WriteCurrentContext(config.Dir(), name); err != nil { return err } fmt.Println(name) diff --git a/cli/main.go b/cli/main.go index 2500cf228..e6bbe0b03 100644 --- a/cli/main.go +++ b/cli/main.go @@ -28,10 +28,14 @@ import ( "syscall" "time" + "github.com/docker/cli/cli/command" + cliconfig "github.com/docker/cli/cli/config" + cliflags "github.com/docker/cli/cli/flags" "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/spf13/cobra" + "github.com/docker/compose-cli/api/backend" "github.com/docker/compose-cli/api/config" apicontext "github.com/docker/compose-cli/api/context" "github.com/docker/compose-cli/api/context/store" @@ -46,8 +50,7 @@ import ( "github.com/docker/compose-cli/cli/metrics" "github.com/docker/compose-cli/cli/mobycli" cliopts "github.com/docker/compose-cli/cli/options" - - cliflags "github.com/docker/cli/cli/flags" + "github.com/docker/compose-cli/local" // Backend registrations _ "github.com/docker/compose-cli/aci" @@ -191,16 +194,17 @@ func main() { if opts.Config == "" { fatal(errors.New("config path cannot be empty")) } - configDir := opts.Config - ctx = config.WithDir(ctx, configDir) + config.WithDir(configDir) currentContext := determineCurrentContext(opts.Context, configDir, opts.Hosts) + apicontext.WithCurrentContext(currentContext) s, err := store.New(configDir) if err != nil { mobycli.Exec(root) } + store.WithContextStore(s) ctype := store.DefaultContextType cc, _ := s.Get(currentContext) @@ -208,28 +212,17 @@ func main() { ctype = cc.Type() } + service, err := getBackend(ctype, configDir, opts) + if err != nil { + fatal(err) + } + backend.WithBackend(service) + root.AddCommand( run.Command(ctype), compose.Command(ctype), volume.Command(ctype), ) - if ctype == store.DefaultContextType || ctype == store.LocalContextType { - cnxOptions := cliflags.CommonOptions{ - Context: opts.Context, - Debug: opts.Debug, - Hosts: opts.Hosts, - LogLevel: opts.LogLevel, - TLS: opts.TLS, - TLSVerify: opts.TLSVerify, - } - - if opts.TLSVerify { - cnxOptions.TLSOptions = opts.TLSOptions - } - ctx = apicontext.WithCliOptions(ctx, cnxOptions) - } - ctx = apicontext.WithCurrentContext(ctx, currentContext) - ctx = store.WithContextStore(ctx, s) if err = root.ExecuteContext(ctx); err != nil { handleError(ctx, err, ctype, currentContext, cc, root) @@ -237,6 +230,38 @@ func main() { metrics.Track(ctype, os.Args[1:], metrics.SuccessStatus) } +func getBackend(ctype string, configDir string, opts cliopts.GlobalOpts) (backend.Service, error) { + switch ctype { + case store.DefaultContextType, store.LocalContextType: + configFile, err := cliconfig.Load(configDir) + if err != nil { + return nil, err + } + options := cliflags.CommonOptions{ + Context: opts.Context, + Debug: opts.Debug, + Hosts: opts.Hosts, + LogLevel: opts.LogLevel, + } + + if opts.TLSVerify { + options.TLS = opts.TLS + options.TLSVerify = opts.TLSVerify + options.TLSOptions = opts.TLSOptions + } + apiClient, err := command.NewAPIClientFromFlags(&options, configFile) + if err != nil { + return nil, err + } + return local.NewService(apiClient), nil + } + service, err := backend.Get(ctype) + if errdefs.IsNotFoundError(err) { + return service, nil + } + return service, err +} + func handleError(ctx context.Context, err error, ctype string, currentContext string, cc *store.DockerContext, root *cobra.Command) { // if user canceled request, simply exit without any error message if errdefs.IsErrCanceled(err) || errors.Is(ctx.Err(), context.Canceled) { diff --git a/cli/mobycli/exec.go b/cli/mobycli/exec.go index e264e2cd9..758ba53bb 100644 --- a/cli/mobycli/exec.go +++ b/cli/mobycli/exec.go @@ -39,9 +39,9 @@ const ComDockerCli = "com.docker.cli" // ExecIfDefaultCtxType delegates to com.docker.cli if on moby context func ExecIfDefaultCtxType(ctx context.Context, root *cobra.Command) { - currentContext := apicontext.CurrentContext(ctx) + currentContext := apicontext.Current() - s := store.ContextStore(ctx) + s := store.Instance() currentCtx, err := s.Get(currentContext) // Only run original docker command if the current context is not ours. diff --git a/cli/server/interceptor.go b/cli/server/interceptor.go index 7528a513d..617721a7d 100644 --- a/cli/server/interceptor.go +++ b/cli/server/interceptor.go @@ -40,7 +40,7 @@ func unaryServerInterceptor(clictx context.Context) grpc.UnaryServerInterceptor return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { currentContext, err := getIncomingContext(ctx) if err != nil { - currentContext, err = getConfigContext(clictx) + currentContext, err = getConfigContext() if err != nil { return nil, err } @@ -59,7 +59,7 @@ func streamServerInterceptor(clictx context.Context) grpc.StreamServerIntercepto return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { currentContext, err := getIncomingContext(ss.Context()) if err != nil { - currentContext, err = getConfigContext(clictx) + currentContext, err = getConfigContext() if err != nil { return err } @@ -77,8 +77,8 @@ func streamServerInterceptor(clictx context.Context) grpc.StreamServerIntercepto } // Returns the current context from the configuration file -func getConfigContext(ctx context.Context) (string, error) { - configDir := config.Dir(ctx) +func getConfigContext() (string, error) { + configDir := config.Dir() configFile, err := config.LoadFile(configDir) if err != nil { return "", err @@ -100,9 +100,9 @@ func getIncomingContext(ctx context.Context) (string, error) { // configureContext populates the request context with objects the client // needs: the context store and the api client func configureContext(ctx context.Context, currentContext string, method string) (context.Context, error) { - configDir := config.Dir(ctx) + configDir := config.Dir() - ctx = apicontext.WithCurrentContext(ctx, currentContext) + apicontext.WithCurrentContext(currentContext) // The contexts service doesn't need the client if !strings.Contains(method, "/com.docker.api.protos.context.v1.Contexts") { @@ -118,7 +118,7 @@ func configureContext(ctx context.Context, currentContext string, method string) if err != nil { return nil, err } - ctx = store.WithContextStore(ctx, s) + store.WithContextStore(s) return ctx, nil } diff --git a/cli/server/interceptor_test.go b/cli/server/interceptor_test.go index 66dbf4a70..3bc401a5c 100644 --- a/cli/server/interceptor_test.go +++ b/cli/server/interceptor_test.go @@ -41,7 +41,7 @@ func testContext(t *testing.T) context.Context { }) ctx := context.Background() - ctx = config.WithDir(ctx, dir) + config.WithDir(dir) err = ioutil.WriteFile(path.Join(dir, "config.json"), []byte(`{"currentContext": "default"}`), 0644) assert.NilError(t, err) @@ -100,7 +100,7 @@ func callStream(ctx context.Context, t *testing.T, interceptor grpc.StreamServer }, &grpc.StreamServerInfo{ FullMethod: "/com.docker.api.protos.context.v1.Contexts/test", }, func(srv interface{}, stream grpc.ServerStream) error { - currentContext = apicontext.CurrentContext(stream.Context()) + currentContext = apicontext.Current() return nil }) @@ -114,7 +114,7 @@ func callUnary(ctx context.Context, t *testing.T, interceptor grpc.UnaryServerIn resp, err := interceptor(ctx, nil, &grpc.UnaryServerInfo{ FullMethod: "/com.docker.api.protos.context.v1.Contexts/test", }, func(ctx context.Context, req interface{}) (interface{}, error) { - currentContext = apicontext.CurrentContext(ctx) + currentContext = apicontext.Current() return nil, nil }) diff --git a/cli/server/proxy/contexts.go b/cli/server/proxy/contexts.go index dead69214..2d6868257 100644 --- a/cli/server/proxy/contexts.go +++ b/cli/server/proxy/contexts.go @@ -37,7 +37,7 @@ func (cp *contextsProxy) SetCurrent(ctx context.Context, request *contextsv1.Set } func (cp *contextsProxy) List(ctx context.Context, request *contextsv1.ListRequest) (*contextsv1.ListResponse, error) { - s := store.ContextStore(ctx) + s := store.Instance() configFile, err := config.LoadFile(cp.configDir) if err != nil { return nil, err diff --git a/cli/server/proxy/proxy.go b/cli/server/proxy/proxy.go index 621b14f49..c6fd77776 100644 --- a/cli/server/proxy/proxy.go +++ b/cli/server/proxy/proxy.go @@ -62,7 +62,7 @@ type proxy struct { // New creates a new proxy server func New(ctx context.Context) Proxy { - configDir := config.Dir(ctx) + configDir := config.Dir() return &proxy{ configDir: configDir, streams: map[string]*streams.Stream{}, diff --git a/ecs/backend.go b/ecs/backend.go index bb075b4cc..a0663c745 100644 --- a/ecs/backend.go +++ b/ecs/backend.go @@ -63,9 +63,9 @@ func init() { backend.Register(backendType, backendType, service, getCloudService) } -func service(ctx context.Context) (backend.Service, error) { - contextStore := store.ContextStore(ctx) - currentContext := apicontext.CurrentContext(ctx) +func service() (backend.Service, error) { + contextStore := store.Instance() + currentContext := apicontext.Current() var ecsContext store.EcsContext if err := contextStore.GetEndpoint(currentContext, &ecsContext); err != nil { diff --git a/ecs/cloudformation.go b/ecs/cloudformation.go index e6e260abd..99d1af435 100644 --- a/ecs/cloudformation.go +++ b/ecs/cloudformation.go @@ -104,7 +104,7 @@ func (b *ecsAPIService) Convert(ctx context.Context, project *types.Project, opt } func (b *ecsAPIService) resolveServiceImagesDigests(ctx context.Context, project *types.Project) error { - configFile, err := cliconfig.Load(config.Dir(ctx)) + configFile, err := cliconfig.Load(config.Dir()) if err != nil { return err } diff --git a/ecs/local/backend.go b/ecs/local/backend.go index 7d80380de..8e26b768e 100644 --- a/ecs/local/backend.go +++ b/ecs/local/backend.go @@ -17,8 +17,6 @@ package local import ( - "context" - local_compose "github.com/docker/compose-cli/local/compose" "github.com/docker/docker/client" @@ -44,7 +42,7 @@ type ecsLocalSimulation struct { compose compose.Service } -func service(ctx context.Context) (backend.Service, error) { +func service() (backend.Service, error) { apiClient, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) if err != nil { return nil, err diff --git a/go.mod b/go.mod index 46af00622..ba63c4e46 100644 --- a/go.mod +++ b/go.mod @@ -54,7 +54,6 @@ require ( github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.6.1 github.com/valyala/fasttemplate v1.2.1 // indirect - golang.org/x/net v0.0.0-20201110031124-69a78807bb2b golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 google.golang.org/grpc v1.33.2 diff --git a/kube/backend.go b/kube/backend.go index b92a60f2f..fa61a7da0 100644 --- a/kube/backend.go +++ b/kube/backend.go @@ -19,8 +19,6 @@ package kube import ( - "context" - "github.com/docker/compose-cli/api/backend" "github.com/docker/compose-cli/api/cloud" "github.com/docker/compose-cli/api/compose" @@ -41,8 +39,8 @@ func init() { backend.Register(backendType, backendType, service, cloud.NotImplementedCloudService) } -func service(ctx context.Context) (backend.Service, error) { - s, err := NewComposeService(ctx) +func service() (backend.Service, error) { + s, err := NewComposeService() if err != nil { return nil, err } diff --git a/kube/compose.go b/kube/compose.go index 17dbfa3f7..adf4992f4 100644 --- a/kube/compose.go +++ b/kube/compose.go @@ -42,9 +42,9 @@ type composeService struct { } // NewComposeService create a kubernetes implementation of the compose.Service API -func NewComposeService(ctx context.Context) (compose.Service, error) { - contextStore := store.ContextStore(ctx) - currentContext := apicontext.CurrentContext(ctx) +func NewComposeService() (compose.Service, error) { + contextStore := store.Instance() + currentContext := apicontext.Current() var kubeContext store.KubeContext if err := contextStore.GetEndpoint(currentContext, &kubeContext); err != nil { diff --git a/local/backend.go b/local/backend.go index fa79f1ebf..e315f5a08 100644 --- a/local/backend.go +++ b/local/backend.go @@ -17,22 +17,15 @@ package local import ( - "context" + "github.com/docker/docker/client" - "github.com/docker/cli/cli/command" "github.com/docker/compose-cli/api/backend" - "github.com/docker/compose-cli/api/cloud" - "github.com/docker/compose-cli/api/compose" - apiconfig "github.com/docker/compose-cli/api/config" "github.com/docker/compose-cli/api/containers" - apicontext "github.com/docker/compose-cli/api/context" "github.com/docker/compose-cli/api/resources" "github.com/docker/compose-cli/api/secrets" "github.com/docker/compose-cli/api/volumes" local_compose "github.com/docker/compose-cli/local/compose" - - cliconfig "github.com/docker/cli/cli/config" ) type local struct { @@ -41,27 +34,13 @@ type local struct { composeService compose.Service } -func init() { - backend.Register("local", "local", service, cloud.NotImplementedCloudService) -} - -func service(ctx context.Context) (backend.Service, error) { - options := apicontext.CliOptions(ctx) - config := apiconfig.Dir(ctx) - configFile, err := cliconfig.Load(config) - if err != nil { - return nil, err - } - apiClient, err := command.NewAPIClientFromFlags(&options, configFile) - if err != nil { - return nil, err - } - +// NewService build a backend for "local" context, using Docker API client +func NewService(apiClient client.APIClient) backend.Service { return &local{ containerService: &containerService{apiClient}, volumeService: &volumeService{apiClient}, composeService: local_compose.NewComposeService(apiClient), - }, nil + } } func (s *local) ContainerService() containers.Service { diff --git a/local/compose/pull.go b/local/compose/pull.go index 9c4772fe0..e0a277c1a 100644 --- a/local/compose/pull.go +++ b/local/compose/pull.go @@ -37,7 +37,7 @@ import ( ) func (s *composeService) Pull(ctx context.Context, project *types.Project) error { - configFile, err := cliconfig.Load(config.Dir(ctx)) + configFile, err := cliconfig.Load(config.Dir()) if err != nil { return err } diff --git a/local/compose/push.go b/local/compose/push.go index 67056fd36..ac0185f6e 100644 --- a/local/compose/push.go +++ b/local/compose/push.go @@ -39,7 +39,7 @@ import ( ) func (s *composeService) Push(ctx context.Context, project *types.Project, options compose.PushOptions) error { - configFile, err := cliconfig.Load(config.Dir(ctx)) + configFile, err := cliconfig.Load(config.Dir()) if err != nil { return err }