diff --git a/aci/compose.go b/aci/compose.go index 06626f902..7712c818e 100644 --- a/aci/compose.go +++ b/aci/compose.go @@ -227,8 +227,8 @@ func (cs *aciComposeService) RunOneOffContainer(ctx context.Context, project *ty return 0, errdefs.ErrNotImplemented } -func (cs *aciComposeService) Remove(ctx context.Context, project *types.Project, options compose.RemoveOptions) ([]string, error) { - return nil, errdefs.ErrNotImplemented +func (cs *aciComposeService) Remove(ctx context.Context, project *types.Project, options compose.RemoveOptions) error { + return errdefs.ErrNotImplemented } func (cs *aciComposeService) Exec(ctx context.Context, project *types.Project, opts compose.RunOptions) (int, error) { diff --git a/api/client/compose.go b/api/client/compose.go index 381790574..84f09d400 100644 --- a/api/client/compose.go +++ b/api/client/compose.go @@ -88,8 +88,8 @@ func (c *composeService) RunOneOffContainer(ctx context.Context, project *types. return 0, errdefs.ErrNotImplemented } -func (c *composeService) Remove(ctx context.Context, project *types.Project, options compose.RemoveOptions) ([]string, error) { - return nil, errdefs.ErrNotImplemented +func (c *composeService) Remove(ctx context.Context, project *types.Project, options compose.RemoveOptions) error { + return errdefs.ErrNotImplemented } func (c *composeService) Exec(ctx context.Context, project *types.Project, opts compose.RunOptions) (int, error) { diff --git a/api/compose/api.go b/api/compose/api.go index 115dbc09d..979e51771 100644 --- a/api/compose/api.go +++ b/api/compose/api.go @@ -59,7 +59,7 @@ type Service interface { // RunOneOffContainer creates a service oneoff container and starts its dependencies RunOneOffContainer(ctx context.Context, project *types.Project, opts RunOptions) (int, error) // Remove executes the equivalent to a `compose rm` - Remove(ctx context.Context, project *types.Project, options RemoveOptions) ([]string, error) + Remove(ctx context.Context, project *types.Project, options RemoveOptions) error // Exec executes a command in a running service container Exec(ctx context.Context, project *types.Project, opts RunOptions) (int, error) // Copy copies a file/folder between a service container and the local filesystem @@ -169,8 +169,9 @@ type PushOptions struct { IgnoreFailures bool } -// PullOptions group options of the Push API +// PullOptions group options of the Pull API type PullOptions struct { + Quiet bool IgnoreFailures bool } diff --git a/api/compose/proxy.go b/api/compose/proxy.go index e01e1a847..765902b1d 100644 --- a/api/compose/proxy.go +++ b/api/compose/proxy.go @@ -41,7 +41,7 @@ type ServiceProxy struct { ConvertFn func(ctx context.Context, project *types.Project, options ConvertOptions) ([]byte, error) KillFn func(ctx context.Context, project *types.Project, options KillOptions) error RunOneOffContainerFn func(ctx context.Context, project *types.Project, opts RunOptions) (int, error) - RemoveFn func(ctx context.Context, project *types.Project, options RemoveOptions) ([]string, error) + RemoveFn func(ctx context.Context, project *types.Project, options RemoveOptions) error ExecFn func(ctx context.Context, project *types.Project, opts RunOptions) (int, error) CopyFn func(ctx context.Context, project *types.Project, opts CopyOptions) error PauseFn func(ctx context.Context, project string, options PauseOptions) error @@ -252,9 +252,9 @@ func (s *ServiceProxy) RunOneOffContainer(ctx context.Context, project *types.Pr } //Remove implements Service interface -func (s *ServiceProxy) Remove(ctx context.Context, project *types.Project, options RemoveOptions) ([]string, error) { +func (s *ServiceProxy) Remove(ctx context.Context, project *types.Project, options RemoveOptions) error { if s.RemoveFn == nil { - return nil, errdefs.ErrNotImplemented + return errdefs.ErrNotImplemented } for _, i := range s.interceptors { i(ctx, project) diff --git a/cli/cmd/compose/build.go b/cli/cmd/compose/build.go index dbbbfbc89..780f39550 100644 --- a/cli/cmd/compose/build.go +++ b/cli/cmd/compose/build.go @@ -25,7 +25,6 @@ import ( "github.com/spf13/cobra" "github.com/docker/compose-cli/api/compose" - "github.com/docker/compose-cli/api/progress" ) type buildOptions struct { @@ -88,14 +87,11 @@ func runBuild(ctx context.Context, backend compose.Service, opts buildOptions, s return err } - err = progress.Run(ctx, func(ctx context.Context) error { - return backend.Build(ctx, project, compose.BuildOptions{ - Pull: opts.pull, - Progress: opts.progress, - Args: types.NewMappingWithEquals(opts.args), - NoCache: opts.noCache, - Quiet: opts.quiet, - }) + return backend.Build(ctx, project, compose.BuildOptions{ + Pull: opts.pull, + Progress: opts.progress, + Args: types.NewMappingWithEquals(opts.args), + NoCache: opts.noCache, + Quiet: opts.quiet, }) - return err } diff --git a/cli/cmd/compose/pause.go b/cli/cmd/compose/pause.go index 046c7c5bd..1928e06fa 100644 --- a/cli/cmd/compose/pause.go +++ b/cli/cmd/compose/pause.go @@ -22,7 +22,6 @@ import ( "github.com/spf13/cobra" "github.com/docker/compose-cli/api/compose" - "github.com/docker/compose-cli/api/progress" ) type pauseOptions struct { @@ -49,12 +48,9 @@ func runPause(ctx context.Context, backend compose.Service, opts pauseOptions, s return err } - err = progress.Run(ctx, func(ctx context.Context) error { - return backend.Pause(ctx, project, compose.PauseOptions{ - Services: services, - }) + return backend.Pause(ctx, project, compose.PauseOptions{ + Services: services, }) - return err } type unpauseOptions struct { @@ -81,9 +77,7 @@ func runUnPause(ctx context.Context, backend compose.Service, opts unpauseOption return err } - return progress.Run(ctx, func(ctx context.Context) error { - return backend.UnPause(ctx, project, compose.PauseOptions{ - Services: services, - }) + return backend.UnPause(ctx, project, compose.PauseOptions{ + Services: services, }) } diff --git a/cli/cmd/compose/pull.go b/cli/cmd/compose/pull.go index b7d7ebbef..5dce96ba9 100644 --- a/cli/cmd/compose/pull.go +++ b/cli/cmd/compose/pull.go @@ -25,7 +25,6 @@ import ( "github.com/spf13/cobra" "github.com/docker/compose-cli/api/compose" - "github.com/docker/compose-cli/api/progress" "github.com/docker/compose-cli/utils" ) @@ -86,15 +85,8 @@ func runPull(ctx context.Context, backend compose.Service, opts pullOptions, ser project.Services = enabled } - apiOpts := compose.PullOptions{ + return backend.Pull(ctx, project, compose.PullOptions{ + Quiet: opts.quiet, IgnoreFailures: opts.ignorePullFailures, - } - - if opts.quiet { - return backend.Pull(ctx, project, apiOpts) - } - - return progress.Run(ctx, func(ctx context.Context) error { - return backend.Pull(ctx, project, apiOpts) }) } diff --git a/cli/cmd/compose/push.go b/cli/cmd/compose/push.go index 53903389f..f7cefd70c 100644 --- a/cli/cmd/compose/push.go +++ b/cli/cmd/compose/push.go @@ -22,7 +22,6 @@ import ( "github.com/spf13/cobra" "github.com/docker/compose-cli/api/compose" - "github.com/docker/compose-cli/api/progress" ) type pushOptions struct { @@ -54,9 +53,7 @@ func runPush(ctx context.Context, backend compose.Service, opts pushOptions, ser return err } - return progress.Run(ctx, func(ctx context.Context) error { - return backend.Push(ctx, project, compose.PushOptions{ - IgnoreFailures: opts.Ignorefailures, - }) + return backend.Push(ctx, project, compose.PushOptions{ + IgnoreFailures: opts.Ignorefailures, }) } diff --git a/cli/cmd/compose/remove.go b/cli/cmd/compose/remove.go index c9537231a..af0c46e91 100644 --- a/cli/cmd/compose/remove.go +++ b/cli/cmd/compose/remove.go @@ -18,13 +18,8 @@ package compose import ( "context" - "fmt" - "strings" "github.com/docker/compose-cli/api/compose" - "github.com/docker/compose-cli/api/progress" - "github.com/docker/compose-cli/utils/prompt" - "github.com/spf13/cobra" ) @@ -69,46 +64,12 @@ func runRemove(ctx context.Context, backend compose.Service, opts removeOptions, } if opts.stop { - err = progress.Run(ctx, func(ctx context.Context) error { - return backend.Stop(ctx, project, compose.StopOptions{ - Services: services, - }) + return backend.Stop(ctx, project, compose.StopOptions{ + Services: services, }) - if err != nil { - return err - } } - resources, err := backend.Remove(ctx, project, compose.RemoveOptions{ - DryRun: true, + return backend.Remove(ctx, project, compose.RemoveOptions{ Services: services, }) - if err != nil { - return err - } - - if len(resources) == 0 { - fmt.Println("No stopped containers") - return nil - } - msg := fmt.Sprintf("Going to remove %s", strings.Join(resources, ", ")) - if opts.force { - fmt.Println(msg) - } else { - confirm, err := prompt.User{}.Confirm(msg, false) - if err != nil { - return err - } - if !confirm { - return nil - } - } - - return progress.Run(ctx, func(ctx context.Context) error { - _, err := backend.Remove(ctx, project, compose.RemoveOptions{ - Volumes: opts.volumes, - Force: opts.force, - }) - return err - }) } diff --git a/cli/cmd/compose/restart.go b/cli/cmd/compose/restart.go index fdfbfc998..ad10e2261 100644 --- a/cli/cmd/compose/restart.go +++ b/cli/cmd/compose/restart.go @@ -23,7 +23,6 @@ import ( "github.com/spf13/cobra" "github.com/docker/compose-cli/api/compose" - "github.com/docker/compose-cli/api/progress" ) type restartOptions struct { @@ -55,10 +54,8 @@ func runRestart(ctx context.Context, backend compose.Service, opts restartOption } timeout := time.Duration(opts.timeout) * time.Second - return progress.Run(ctx, func(ctx context.Context) error { - return backend.Restart(ctx, project, compose.RestartOptions{ - Timeout: &timeout, - Services: services, - }) + return backend.Restart(ctx, project, compose.RestartOptions{ + Timeout: &timeout, + Services: services, }) } diff --git a/cli/cmd/compose/start.go b/cli/cmd/compose/start.go index 5e5b0f878..5ebbb923e 100644 --- a/cli/cmd/compose/start.go +++ b/cli/cmd/compose/start.go @@ -20,8 +20,6 @@ import ( "context" "github.com/docker/compose-cli/api/compose" - "github.com/docker/compose-cli/api/progress" - "github.com/spf13/cobra" ) @@ -49,7 +47,5 @@ func runStart(ctx context.Context, backend compose.Service, opts startOptions, s return err } - return progress.Run(ctx, func(ctx context.Context) error { - return backend.Start(ctx, project, compose.StartOptions{}) - }) + return backend.Start(ctx, project, compose.StartOptions{}) } diff --git a/cli/cmd/compose/stop.go b/cli/cmd/compose/stop.go index 102c0735e..195eafb27 100644 --- a/cli/cmd/compose/stop.go +++ b/cli/cmd/compose/stop.go @@ -23,7 +23,6 @@ import ( "github.com/spf13/cobra" "github.com/docker/compose-cli/api/compose" - "github.com/docker/compose-cli/api/progress" ) type stopOptions struct { @@ -63,10 +62,8 @@ func runStop(ctx context.Context, backend compose.Service, opts stopOptions, ser timeoutValue := time.Duration(opts.timeout) * time.Second timeout = &timeoutValue } - return progress.Run(ctx, func(ctx context.Context) error { - return backend.Stop(ctx, project, compose.StopOptions{ - Timeout: timeout, - Services: services, - }) + return backend.Stop(ctx, project, compose.StopOptions{ + Timeout: timeout, + Services: services, }) } diff --git a/ecs/local/compose.go b/ecs/local/compose.go index c0214b491..5b506d3d6 100644 --- a/ecs/local/compose.go +++ b/ecs/local/compose.go @@ -180,7 +180,7 @@ func (e ecsLocalSimulation) RunOneOffContainer(ctx context.Context, project *typ return 0, errors.Wrap(errdefs.ErrNotImplemented, "use docker-compose run") } -func (e ecsLocalSimulation) Remove(ctx context.Context, project *types.Project, options compose.RemoveOptions) ([]string, error) { +func (e ecsLocalSimulation) Remove(ctx context.Context, project *types.Project, options compose.RemoveOptions) error { return e.compose.Remove(ctx, project, options) } diff --git a/ecs/run.go b/ecs/run.go index 597f80783..8bd3a762f 100644 --- a/ecs/run.go +++ b/ecs/run.go @@ -29,6 +29,6 @@ func (b *ecsAPIService) RunOneOffContainer(ctx context.Context, project *types.P return 0, errdefs.ErrNotImplemented } -func (b *ecsAPIService) Remove(ctx context.Context, project *types.Project, options compose.RemoveOptions) ([]string, error) { - return nil, errdefs.ErrNotImplemented +func (b *ecsAPIService) Remove(ctx context.Context, project *types.Project, options compose.RemoveOptions) error { + return errdefs.ErrNotImplemented } diff --git a/kube/compose.go b/kube/compose.go index ced73d8fa..ac9a46b5f 100644 --- a/kube/compose.go +++ b/kube/compose.go @@ -248,8 +248,8 @@ func (s *composeService) RunOneOffContainer(ctx context.Context, project *types. return 0, errdefs.ErrNotImplemented } -func (s *composeService) Remove(ctx context.Context, project *types.Project, options compose.RemoveOptions) ([]string, error) { - return nil, errdefs.ErrNotImplemented +func (s *composeService) Remove(ctx context.Context, project *types.Project, options compose.RemoveOptions) error { + return errdefs.ErrNotImplemented } // Exec executes a command in a running service container diff --git a/local/compose/build.go b/local/compose/build.go index eb78869dc..030e39a7b 100644 --- a/local/compose/build.go +++ b/local/compose/build.go @@ -42,6 +42,12 @@ import ( ) func (s *composeService) Build(ctx context.Context, project *types.Project, options compose.BuildOptions) error { + return composeprogress.Run(ctx, func(ctx context.Context) error { + return s.build(ctx, project, options) + }) +} + +func (s *composeService) build(ctx context.Context, project *types.Project, options compose.BuildOptions) error { opts := map[string]build.Options{} imagesToBuild := []string{} @@ -76,7 +82,7 @@ func (s *composeService) Build(ctx context.Context, project *types.Project, opti } } - _, err := s.build(ctx, project, opts, Containers{}, options.Progress) + _, err := s.doBuild(ctx, project, opts, Containers{}, options.Progress) if err == nil { if len(imagesToBuild) > 0 && !options.Quiet { utils.DisplayScanSuggestMsg() @@ -100,7 +106,7 @@ func (s *composeService) ensureImagesExists(ctx context.Context, project *types. if err != nil { return err } - builtImages, err := s.build(ctx, project, opts, observedState, mode) + builtImages, err := s.doBuild(ctx, project, opts, observedState, mode) if err != nil { return err } @@ -188,7 +194,7 @@ func (s *composeService) getImageDigests(ctx context.Context, project *types.Pro return images, nil } -func (s *composeService) build(ctx context.Context, project *types.Project, opts map[string]build.Options, observedState Containers, mode string) (map[string]string, error) { +func (s *composeService) doBuild(ctx context.Context, project *types.Project, opts map[string]build.Options, observedState Containers, mode string) (map[string]string, error) { info, err := s.apiClient.Info(ctx) if err != nil { return nil, err diff --git a/local/compose/pause.go b/local/compose/pause.go index d1e880943..7642f1bdf 100644 --- a/local/compose/pause.go +++ b/local/compose/pause.go @@ -27,6 +27,12 @@ import ( ) func (s *composeService) Pause(ctx context.Context, project string, options compose.PauseOptions) error { + return progress.Run(ctx, func(ctx context.Context) error { + return s.pause(ctx, project, options) + }) +} + +func (s *composeService) pause(ctx context.Context, project string, options compose.PauseOptions) error { containers, err := s.getContainers(ctx, project, oneOffExclude, true, options.Services...) if err != nil { return err @@ -49,6 +55,12 @@ func (s *composeService) Pause(ctx context.Context, project string, options comp } func (s *composeService) UnPause(ctx context.Context, project string, options compose.PauseOptions) error { + return progress.Run(ctx, func(ctx context.Context) error { + return s.unPause(ctx, project, options) + }) +} + +func (s *composeService) unPause(ctx context.Context, project string, options compose.PauseOptions) error { containers, err := s.getContainers(ctx, project, oneOffExclude, true, options.Services...) if err != nil { return err diff --git a/local/compose/pull.go b/local/compose/pull.go index 0df5e45c7..8104c5700 100644 --- a/local/compose/pull.go +++ b/local/compose/pull.go @@ -38,6 +38,15 @@ import ( ) func (s *composeService) Pull(ctx context.Context, project *types.Project, opts compose.PullOptions) error { + if opts.Quiet { + return s.pull(ctx, project, opts) + } + return progress.Run(ctx, func(ctx context.Context) error { + return s.pull(ctx, project, opts) + }) +} + +func (s *composeService) pull(ctx context.Context, project *types.Project, opts compose.PullOptions) error { info, err := s.apiClient.Info(ctx) if err != nil { return err diff --git a/local/compose/push.go b/local/compose/push.go index a246753e5..a50b4a6ca 100644 --- a/local/compose/push.go +++ b/local/compose/push.go @@ -39,6 +39,12 @@ import ( ) func (s *composeService) Push(ctx context.Context, project *types.Project, options compose.PushOptions) error { + return progress.Run(ctx, func(ctx context.Context) error { + return s.push(ctx, project, options) + }) +} + +func (s *composeService) push(ctx context.Context, project *types.Project, options compose.PushOptions) error { configFile, err := cliconfig.Load(config.Dir()) if err != nil { return err diff --git a/local/compose/remove.go b/local/compose/remove.go index 713077d2c..dba81c69e 100644 --- a/local/compose/remove.go +++ b/local/compose/remove.go @@ -18,17 +18,20 @@ package compose import ( "context" + "fmt" + "strings" "github.com/docker/compose-cli/api/compose" "github.com/docker/compose-cli/api/progress" status "github.com/docker/compose-cli/local/moby" + "github.com/docker/compose-cli/utils/prompt" "github.com/compose-spec/compose-go/types" moby "github.com/docker/docker/api/types" "golang.org/x/sync/errgroup" ) -func (s *composeService) Remove(ctx context.Context, project *types.Project, options compose.RemoveOptions) ([]string, error) { +func (s *composeService) Remove(ctx context.Context, project *types.Project, options compose.RemoveOptions) error { services := options.Services if len(services) == 0 { services = project.ServiceNames() @@ -36,7 +39,7 @@ func (s *composeService) Remove(ctx context.Context, project *types.Project, opt containers, err := s.getContainers(ctx, project.Name, oneOffInclude, true, services...) if err != nil { - return nil, err + return err } stoppedContainers := containers.filter(func(c moby.Container) bool { @@ -48,18 +51,36 @@ func (s *composeService) Remove(ctx context.Context, project *types.Project, opt names = append(names, getCanonicalContainerName(c)) }) - if options.DryRun { - return names, nil + if len(names) == 0 { + fmt.Println("No stopped containers") + return nil } + msg := fmt.Sprintf("Going to remove %s", strings.Join(names, ", ")) + if options.Force { + fmt.Println(msg) + } else { + confirm, err := prompt.User{}.Confirm(msg, false) + if err != nil { + return err + } + if !confirm { + return nil + } + } + return progress.Run(ctx, func(ctx context.Context) error { + return s.remove(ctx, stoppedContainers, options) + }) +} +func (s *composeService) remove(ctx context.Context, containers Containers, options compose.RemoveOptions) error { w := progress.ContextWriter(ctx) eg, ctx := errgroup.WithContext(ctx) - for _, c := range stoppedContainers { + for _, c := range containers { c := c eg.Go(func() error { eventName := getContainerProgressName(c) w.Event(progress.RemovingEvent(eventName)) - err = s.apiClient.ContainerRemove(ctx, c.ID, moby.ContainerRemoveOptions{ + err := s.apiClient.ContainerRemove(ctx, c.ID, moby.ContainerRemoveOptions{ RemoveVolumes: options.Volumes, Force: options.Force, }) @@ -69,5 +90,5 @@ func (s *composeService) Remove(ctx context.Context, project *types.Project, opt return err }) } - return nil, eg.Wait() + return eg.Wait() } diff --git a/local/compose/restart.go b/local/compose/restart.go index 1c1038968..16eb7943a 100644 --- a/local/compose/restart.go +++ b/local/compose/restart.go @@ -20,12 +20,19 @@ import ( "context" "github.com/docker/compose-cli/api/compose" + "github.com/docker/compose-cli/api/progress" "github.com/docker/compose-cli/utils" "github.com/compose-spec/compose-go/types" ) func (s *composeService) Restart(ctx context.Context, project *types.Project, options compose.RestartOptions) error { + return progress.Run(ctx, func(ctx context.Context) error { + return s.restart(ctx, project, options) + }) +} + +func (s *composeService) restart(ctx context.Context, project *types.Project, options compose.RestartOptions) error { ctx, err := s.getUpdatedContainersStateContext(ctx, project.Name) if err != nil { return err diff --git a/local/compose/start.go b/local/compose/start.go index f09a4368b..724aeeef2 100644 --- a/local/compose/start.go +++ b/local/compose/start.go @@ -20,6 +20,7 @@ import ( "context" "github.com/docker/compose-cli/api/compose" + "github.com/docker/compose-cli/api/progress" "github.com/docker/compose-cli/utils" "github.com/compose-spec/compose-go/types" @@ -29,6 +30,12 @@ import ( ) func (s *composeService) Start(ctx context.Context, project *types.Project, options compose.StartOptions) error { + return progress.Run(ctx, func(ctx context.Context) error { + return s.start(ctx, project, options) + }) +} + +func (s *composeService) start(ctx context.Context, project *types.Project, options compose.StartOptions) error { listener := options.Attach if len(options.Services) == 0 { options.Services = project.ServiceNames() diff --git a/local/compose/stop.go b/local/compose/stop.go index 0e950e440..282c8359f 100644 --- a/local/compose/stop.go +++ b/local/compose/stop.go @@ -26,6 +26,12 @@ import ( ) func (s *composeService) Stop(ctx context.Context, project *types.Project, options compose.StopOptions) error { + return progress.Run(ctx, func(ctx context.Context) error { + return s.stop(ctx, project, options) + }) +} + +func (s *composeService) stop(ctx context.Context, project *types.Project, options compose.StopOptions) error { w := progress.ContextWriter(ctx) services := options.Services