From f6e96dd783dd57a58f9f51c05d9659a3209ab995 Mon Sep 17 00:00:00 2001 From: Nicolas De Loof Date: Mon, 11 Apr 2022 10:58:20 +0200 Subject: [PATCH 1/4] if command is ran with a compose file, apply the compose model, not just project name Signed-off-by: Nicolas De Loof --- cmd/compose/compose.go | 14 ++++++++++++++ cmd/compose/down.go | 13 +++---------- cmd/compose/events.go | 4 ++-- cmd/compose/kill.go | 4 ++-- cmd/compose/pause.go | 10 ++++++---- cmd/compose/remove.go | 8 +++++--- cmd/compose/restart.go | 5 +++-- cmd/compose/start.go | 5 +++-- cmd/compose/stop.go | 5 +++-- pkg/api/api.go | 12 +++++++++++- pkg/compose/compose.go | 20 -------------------- pkg/compose/down.go | 7 +++++-- pkg/compose/down_test.go | 6 +++--- pkg/compose/kill_test.go | 11 +++++++++-- pkg/compose/pause.go | 12 ++++++++++-- pkg/compose/remove.go | 6 +++++- pkg/compose/restart.go | 20 +++++++++----------- pkg/compose/stop.go | 24 +++++++++++++++++++----- pkg/compose/stop_test.go | 8 +++++++- pkg/e2e/compose_run_test.go | 3 ++- 20 files changed, 121 insertions(+), 76 deletions(-) diff --git a/cmd/compose/compose.go b/cmd/compose/compose.go index 2db045017..c15241415 100644 --- a/cmd/compose/compose.go +++ b/cmd/compose/compose.go @@ -136,6 +136,20 @@ func (o *projectOptions) addProjectFlags(f *pflag.FlagSet) { _ = f.MarkHidden("workdir") } +func (o *projectOptions) projectOrName() (*types.Project, string, error) { + name := o.ProjectName + var project *types.Project + if o.ProjectName == "" { + p, err := o.toProject(nil) + if err != nil { + return nil, "", err + } + project = p + name = p.Name + } + return project, name, nil +} + func (o *projectOptions) toProjectName() (string, error) { if o.ProjectName != "" { return o.ProjectName, nil diff --git a/cmd/compose/down.go b/cmd/compose/down.go index 9907f4cc6..cc14e25df 100644 --- a/cmd/compose/down.go +++ b/cmd/compose/down.go @@ -22,7 +22,6 @@ import ( "os" "time" - "github.com/compose-spec/compose-go/types" "github.com/docker/compose/v2/pkg/utils" "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -79,15 +78,9 @@ func downCommand(p *projectOptions, backend api.Service) *cobra.Command { } func runDown(ctx context.Context, backend api.Service, opts downOptions) error { - name := opts.ProjectName - var project *types.Project - if opts.ProjectName == "" { - p, err := opts.toProject(nil) - if err != nil { - return err - } - project = p - name = p.Name + project, name, err := opts.projectOrName() + if err != nil { + return err } var timeout *time.Duration diff --git a/cmd/compose/events.go b/cmd/compose/events.go index 1731f6bac..f50605b4f 100644 --- a/cmd/compose/events.go +++ b/cmd/compose/events.go @@ -51,12 +51,12 @@ func eventsCommand(p *projectOptions, backend api.Service) *cobra.Command { } func runEvents(ctx context.Context, backend api.Service, opts eventsOpts, services []string) error { - project, err := opts.toProjectName() + name, err := opts.toProjectName() if err != nil { return err } - return backend.Events(ctx, project, api.EventsOptions{ + return backend.Events(ctx, name, api.EventsOptions{ Services: services, Consumer: func(event api.Event) error { if opts.json { diff --git a/cmd/compose/kill.go b/cmd/compose/kill.go index 7ea5b6cb9..6a96dee09 100644 --- a/cmd/compose/kill.go +++ b/cmd/compose/kill.go @@ -49,12 +49,12 @@ func killCommand(p *projectOptions, backend api.Service) *cobra.Command { } func runKill(ctx context.Context, backend api.Service, opts killOptions, services []string) error { - projectName, err := opts.toProjectName() + name, err := opts.toProjectName() if err != nil { return err } - return backend.Kill(ctx, projectName, api.KillOptions{ + return backend.Kill(ctx, name, api.KillOptions{ Services: services, Signal: opts.signal, }) diff --git a/cmd/compose/pause.go b/cmd/compose/pause.go index f51f47c7a..9afbcaec4 100644 --- a/cmd/compose/pause.go +++ b/cmd/compose/pause.go @@ -44,13 +44,14 @@ func pauseCommand(p *projectOptions, backend api.Service) *cobra.Command { } func runPause(ctx context.Context, backend api.Service, opts pauseOptions, services []string) error { - project, err := opts.toProjectName() + project, name, err := opts.projectOrName() if err != nil { return err } - return backend.Pause(ctx, project, api.PauseOptions{ + return backend.Pause(ctx, name, api.PauseOptions{ Services: services, + Project: project, }) } @@ -74,12 +75,13 @@ func unpauseCommand(p *projectOptions, backend api.Service) *cobra.Command { } func runUnPause(ctx context.Context, backend api.Service, opts unpauseOptions, services []string) error { - project, err := opts.toProjectName() + project, name, err := opts.projectOrName() if err != nil { return err } - return backend.UnPause(ctx, project, api.PauseOptions{ + return backend.UnPause(ctx, name, api.PauseOptions{ Services: services, + Project: project, }) } diff --git a/cmd/compose/remove.go b/cmd/compose/remove.go index 2fa933057..2c1152494 100644 --- a/cmd/compose/remove.go +++ b/cmd/compose/remove.go @@ -59,23 +59,25 @@ Any data which is not in a volume will be lost.`, } func runRemove(ctx context.Context, backend api.Service, opts removeOptions, services []string) error { - project, err := opts.toProjectName() + project, name, err := opts.projectOrName() if err != nil { return err } if opts.stop { - err := backend.Stop(ctx, project, api.StopOptions{ + err := backend.Stop(ctx, name, api.StopOptions{ Services: services, + Project: project, }) if err != nil { return err } } - return backend.Remove(ctx, project, api.RemoveOptions{ + return backend.Remove(ctx, name, api.RemoveOptions{ Services: services, Force: opts.force, Volumes: opts.volumes, + Project: project, }) } diff --git a/cmd/compose/restart.go b/cmd/compose/restart.go index e8b786d22..2bb8c8f3e 100644 --- a/cmd/compose/restart.go +++ b/cmd/compose/restart.go @@ -49,14 +49,15 @@ func restartCommand(p *projectOptions, backend api.Service) *cobra.Command { } func runRestart(ctx context.Context, backend api.Service, opts restartOptions, services []string) error { - projectName, err := opts.toProjectName() + project, name, err := opts.projectOrName() if err != nil { return err } timeout := time.Duration(opts.timeout) * time.Second - return backend.Restart(ctx, projectName, api.RestartOptions{ + return backend.Restart(ctx, name, api.RestartOptions{ Timeout: &timeout, Services: services, + Project: project, }) } diff --git a/cmd/compose/start.go b/cmd/compose/start.go index e9b67ae44..45da76122 100644 --- a/cmd/compose/start.go +++ b/cmd/compose/start.go @@ -43,12 +43,13 @@ func startCommand(p *projectOptions, backend api.Service) *cobra.Command { } func runStart(ctx context.Context, backend api.Service, opts startOptions, services []string) error { - projectName, err := opts.toProjectName() + project, name, err := opts.projectOrName() if err != nil { return err } - return backend.Start(ctx, projectName, api.StartOptions{ + return backend.Start(ctx, name, api.StartOptions{ AttachTo: services, + Project: project, }) } diff --git a/cmd/compose/stop.go b/cmd/compose/stop.go index b13163514..484bed824 100644 --- a/cmd/compose/stop.go +++ b/cmd/compose/stop.go @@ -53,7 +53,7 @@ func stopCommand(p *projectOptions, backend api.Service) *cobra.Command { } func runStop(ctx context.Context, backend api.Service, opts stopOptions, services []string) error { - projectName, err := opts.toProjectName() + project, name, err := opts.projectOrName() if err != nil { return err } @@ -63,8 +63,9 @@ func runStop(ctx context.Context, backend api.Service, opts stopOptions, service timeoutValue := time.Duration(opts.timeout) * time.Second timeout = &timeoutValue } - return backend.Stop(ctx, projectName, api.StopOptions{ + return backend.Stop(ctx, name, api.StopOptions{ Timeout: timeout, Services: services, + Project: project, }) } diff --git a/pkg/api/api.go b/pkg/api/api.go index 30b1ac06e..947522854 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -117,7 +117,7 @@ type CreateOptions struct { // StartOptions group options of the Start API type StartOptions struct { - // Project is the compose project used to define this app. Might be nil if user ran `start` just with project name + // Project is the compose project used to define this app. Might be nil if user ran command just with project name Project *types.Project // Attach to container and forward logs if not nil Attach LogConsumer @@ -133,6 +133,8 @@ type StartOptions struct { // RestartOptions group options of the Restart API type RestartOptions struct { + // Project is the compose project used to define this app. Might be nil if user ran command just with project name + Project *types.Project // Timeout override container restart timeout Timeout *time.Duration // Services passed in the command line to be restarted @@ -141,6 +143,8 @@ type RestartOptions struct { // StopOptions group options of the Stop API type StopOptions struct { + // Project is the compose project used to define this app. Might be nil if user ran command just with project name + Project *types.Project // Timeout override container stop timeout Timeout *time.Duration // Services passed in the command line to be stopped @@ -201,6 +205,8 @@ type KillOptions struct { // RemoveOptions group options of the Remove API type RemoveOptions struct { + // Project is the compose project used to define this app. Might be nil if user ran command just with project name + Project *types.Project // DryRun just list removable resources DryRun bool // Volumes remove anonymous volumes @@ -213,6 +219,8 @@ type RemoveOptions struct { // RunOptions group options of the Run API type RunOptions struct { + // Project is the compose project used to define this app. Might be nil if user ran command just with project name + Project *types.Project Name string Service string Command []string @@ -377,6 +385,8 @@ type LogOptions struct { type PauseOptions struct { // Services passed in the command line to be started Services []string + // Project is the compose project used to define this app. Might be nil if user ran command just with project name + Project *types.Project } const ( diff --git a/pkg/compose/compose.go b/pkg/compose/compose.go index bfd4bdbf1..6d2c4021c 100644 --- a/pkg/compose/compose.go +++ b/pkg/compose/compose.go @@ -172,26 +172,6 @@ SERVICES: return project, nil } -// actualState list resources labelled by projectName to rebuild compose project model -func (s *composeService) actualState(ctx context.Context, projectName string, services []string) (Containers, *types.Project, error) { - var containers Containers - // don't filter containers by options.Services so projectFromName can rebuild project with all existing resources - containers, err := s.getContainers(ctx, projectName, oneOffInclude, true) - if err != nil { - return nil, nil, err - } - - project, err := s.projectFromName(containers, projectName, services...) - if err != nil && !api.IsNotFoundError(err) { - return nil, nil, err - } - - if len(services) > 0 { - containers = containers.filter(isService(services...)) - } - return containers, project, nil -} - func (s *composeService) actualVolumes(ctx context.Context, projectName string) (types.Volumes, error) { volumes, err := s.apiClient().VolumeList(ctx, filters.NewArgs(projectFilter(projectName))) if err != nil { diff --git a/pkg/compose/down.go b/pkg/compose/down.go index 4251a8dc1..cd5af07bb 100644 --- a/pkg/compose/down.go +++ b/pkg/compose/down.go @@ -45,8 +45,11 @@ func (s *composeService) down(ctx context.Context, projectName string, options a w := progress.ContextWriter(ctx) resourceToRemove := false - var containers Containers - containers, err := s.getContainers(ctx, projectName, oneOffInclude, true) + include := oneOffExclude + if options.RemoveOrphans { + include = oneOffInclude + } + containers, err := s.getContainers(ctx, projectName, include, true) if err != nil { return err } diff --git a/pkg/compose/down_test.go b/pkg/compose/down_test.go index ea9527939..0111fdea8 100644 --- a/pkg/compose/down_test.go +++ b/pkg/compose/down_test.go @@ -40,7 +40,7 @@ func TestDown(t *testing.T) { tested.dockerCli = cli cli.EXPECT().Client().Return(api).AnyTimes() - api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt()).Return( + api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt(false)).Return( []moby.Container{ testContainer("service1", "123", false), testContainer("service2", "456", false), @@ -88,7 +88,7 @@ func TestDownRemoveOrphans(t *testing.T) { tested.dockerCli = cli cli.EXPECT().Client().Return(api).AnyTimes() - api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt()).Return( + api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt(true)).Return( []moby.Container{ testContainer("service1", "123", false), testContainer("service2", "789", false), @@ -125,7 +125,7 @@ func TestDownRemoveVolumes(t *testing.T) { tested.dockerCli = cli cli.EXPECT().Client().Return(api).AnyTimes() - api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt()).Return( + api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt(false)).Return( []moby.Container{testContainer("service1", "123", false)}, nil) api.EXPECT().VolumeList(gomock.Any(), filters.NewArgs(projectFilter(strings.ToLower(testProject)))). Return(volume.VolumeListOKBody{ diff --git a/pkg/compose/kill_test.go b/pkg/compose/kill_test.go index 9680afe30..1455b6c2d 100644 --- a/pkg/compose/kill_test.go +++ b/pkg/compose/kill_test.go @@ -18,6 +18,7 @@ package compose import ( "context" + "fmt" "path/filepath" "strings" "testing" @@ -110,9 +111,15 @@ func anyCancellableContext() gomock.Matcher { return gomock.AssignableToTypeOf(ctxWithCancel) } -func projectFilterListOpt() moby.ContainerListOptions { +func projectFilterListOpt(withOneOff bool) moby.ContainerListOptions { + filter := filters.NewArgs( + projectFilter(strings.ToLower(testProject)), + ) + if !withOneOff { + filter.Add("label", fmt.Sprintf("%s=False", compose.OneoffLabel)) + } return moby.ContainerListOptions{ - Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject))), + Filters: filter, All: true, } } diff --git a/pkg/compose/pause.go b/pkg/compose/pause.go index 3ea593eef..02434b4f9 100644 --- a/pkg/compose/pause.go +++ b/pkg/compose/pause.go @@ -33,12 +33,16 @@ func (s *composeService) Pause(ctx context.Context, projectName string, options }) } -func (s *composeService) pause(ctx context.Context, project string, options api.PauseOptions) error { - containers, err := s.getContainers(ctx, project, oneOffExclude, false, options.Services...) +func (s *composeService) pause(ctx context.Context, projectName string, options api.PauseOptions) error { + containers, err := s.getContainers(ctx, projectName, oneOffExclude, false, options.Services...) if err != nil { return err } + if options.Project != nil { + containers = containers.filter(isService(options.Project.ServiceNames()...)) + } + w := progress.ContextWriter(ctx) eg, ctx := errgroup.WithContext(ctx) containers.forEach(func(container moby.Container) { @@ -67,6 +71,10 @@ func (s *composeService) unPause(ctx context.Context, projectName string, option return err } + if options.Project != nil { + containers = containers.filter(isService(options.Project.ServiceNames()...)) + } + w := progress.ContextWriter(ctx) eg, ctx := errgroup.WithContext(ctx) containers.forEach(func(container moby.Container) { diff --git a/pkg/compose/remove.go b/pkg/compose/remove.go index cc10b71a9..557572b64 100644 --- a/pkg/compose/remove.go +++ b/pkg/compose/remove.go @@ -31,7 +31,7 @@ import ( func (s *composeService) Remove(ctx context.Context, projectName string, options api.RemoveOptions) error { projectName = strings.ToLower(projectName) - containers, _, err := s.actualState(ctx, projectName, options.Services) + containers, err := s.getContainers(ctx, projectName, oneOffExclude, true, options.Services...) if err != nil { if api.IsNotFoundError(err) { fmt.Fprintln(s.stderr(), "No stopped containers") @@ -40,6 +40,10 @@ func (s *composeService) Remove(ctx context.Context, projectName string, options return err } + if options.Project != nil { + containers = containers.filter(isService(options.Project.ServiceNames()...)) + } + stoppedContainers := containers.filter(func(c moby.Container) bool { return c.State != ContainerRunning }) diff --git a/pkg/compose/restart.go b/pkg/compose/restart.go index 87d236cc8..9b3178e3c 100644 --- a/pkg/compose/restart.go +++ b/pkg/compose/restart.go @@ -34,15 +34,17 @@ func (s *composeService) Restart(ctx context.Context, projectName string, option } func (s *composeService) restart(ctx context.Context, projectName string, options api.RestartOptions) error { - - observedState, err := s.getContainers(ctx, projectName, oneOffExclude, true) + containers, err := s.getContainers(ctx, projectName, oneOffExclude, true) if err != nil { return err } - project, err := s.projectFromName(observedState, projectName, options.Services...) - if err != nil { - return err + project := options.Project + if project == nil { + project, err = s.getProjectWithResources(ctx, containers, projectName) + if err != nil { + return err + } } if len(options.Services) == 0 { @@ -50,12 +52,12 @@ func (s *composeService) restart(ctx context.Context, projectName string, option } w := progress.ContextWriter(ctx) - err = InDependencyOrder(ctx, project, func(c context.Context, service string) error { + return InDependencyOrder(ctx, project, func(c context.Context, service string) error { if !utils.StringContains(options.Services, service) { return nil } eg, ctx := errgroup.WithContext(ctx) - for _, container := range observedState.filter(isService(service)) { + for _, container := range containers.filter(isService(service)) { container := container eg.Go(func() error { eventName := getContainerProgressName(container) @@ -69,8 +71,4 @@ func (s *composeService) restart(ctx context.Context, projectName string, option } return eg.Wait() }) - if err != nil { - return err - } - return nil } diff --git a/pkg/compose/stop.go b/pkg/compose/stop.go index d17e01a94..971b7e998 100644 --- a/pkg/compose/stop.go +++ b/pkg/compose/stop.go @@ -22,6 +22,7 @@ import ( "github.com/docker/compose/v2/pkg/api" "github.com/docker/compose/v2/pkg/progress" + "github.com/docker/compose/v2/pkg/utils" ) func (s *composeService) Stop(ctx context.Context, projectName string, options api.StopOptions) error { @@ -31,15 +32,28 @@ func (s *composeService) Stop(ctx context.Context, projectName string, options a } func (s *composeService) stop(ctx context.Context, projectName string, options api.StopOptions) error { - w := progress.ContextWriter(ctx) - - containers, project, err := s.actualState(ctx, projectName, options.Services) + containers, err := s.getContainers(ctx, projectName, oneOffExclude, true) if err != nil { return err } + project := options.Project + if project == nil { + project, err = s.getProjectWithResources(ctx, containers, projectName) + if err != nil { + return err + } + } + + if len(options.Services) == 0 { + options.Services = project.ServiceNames() + } + + w := progress.ContextWriter(ctx) return InReverseDependencyOrder(ctx, project, func(c context.Context, service string) error { - containersToStop := containers.filter(isService(service)).filter(isNotOneOff) - return s.stopContainers(ctx, w, containersToStop, options.Timeout) + if !utils.StringContains(options.Services, service) { + return nil + } + return s.stopContainers(ctx, w, containers.filter(isService(service)).filter(isNotOneOff), options.Timeout) }) } diff --git a/pkg/compose/stop_test.go b/pkg/compose/stop_test.go index e5848780e..97a83356e 100644 --- a/pkg/compose/stop_test.go +++ b/pkg/compose/stop_test.go @@ -26,6 +26,8 @@ import ( "github.com/docker/compose/v2/pkg/mocks" moby "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/filters" + "github.com/docker/docker/api/types/volume" "github.com/golang/mock/gomock" "gotest.tools/v3/assert" ) @@ -40,12 +42,16 @@ func TestStopTimeout(t *testing.T) { cli.EXPECT().Client().Return(api).AnyTimes() ctx := context.Background() - api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt()).Return( + api.EXPECT().ContainerList(gomock.Any(), projectFilterListOpt(false)).Return( []moby.Container{ testContainer("service1", "123", false), testContainer("service1", "456", false), testContainer("service2", "789", false), }, nil) + api.EXPECT().VolumeList(gomock.Any(), filters.NewArgs(projectFilter(strings.ToLower(testProject)))). + Return(volume.VolumeListOKBody{}, nil) + api.EXPECT().NetworkList(gomock.Any(), moby.NetworkListOptions{Filters: filters.NewArgs(projectFilter(strings.ToLower(testProject)))}). + Return([]moby.NetworkResource{}, nil) timeout := time.Duration(2) * time.Second api.EXPECT().ContainerStop(gomock.Any(), "123", &timeout).Return(nil) diff --git a/pkg/e2e/compose_run_test.go b/pkg/e2e/compose_run_test.go index e1abb581e..4df783251 100644 --- a/pkg/e2e/compose_run_test.go +++ b/pkg/e2e/compose_run_test.go @@ -79,7 +79,7 @@ func TestLocalComposeRun(t *testing.T) { }) t.Run("down", func(t *testing.T) { - c.RunDockerComposeCmd(t, "-f", "./fixtures/run-test/compose.yaml", "down") + c.RunDockerComposeCmd(t, "-f", "./fixtures/run-test/compose.yaml", "down", "--remove-orphans") res := c.RunDockerCmd(t, "ps", "--all") assert.Assert(t, !strings.Contains(res.Stdout(), "run-test"), res.Stdout()) }) @@ -121,6 +121,7 @@ func TestLocalComposeRun(t *testing.T) { c.Env = append(c.Env, "COMPOSE_REMOVE_ORPHANS=True") }) res := c.RunDockerCmd(t, "ps", "--all") + assert.Assert(t, !strings.Contains(res.Stdout(), "run-test"), res.Stdout()) }) From d2a6c2c200c9630965d36ca9becd91939eed1cc0 Mon Sep 17 00:00:00 2001 From: Laura Brehm Date: Mon, 1 Aug 2022 16:56:26 +0200 Subject: [PATCH 2/4] Add E2E tests for `compose stop` with compose file Signed-off-by: Laura Brehm --- pkg/e2e/fixtures/start-stop/other.yaml | 5 +++++ pkg/e2e/start_stop_test.go | 16 ++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 pkg/e2e/fixtures/start-stop/other.yaml diff --git a/pkg/e2e/fixtures/start-stop/other.yaml b/pkg/e2e/fixtures/start-stop/other.yaml new file mode 100644 index 000000000..c28cbd09b --- /dev/null +++ b/pkg/e2e/fixtures/start-stop/other.yaml @@ -0,0 +1,5 @@ +services: + a-different-one: + image: nginx:alpine + and-another-one: + image: nginx:alpine \ No newline at end of file diff --git a/pkg/e2e/start_stop_test.go b/pkg/e2e/start_stop_test.go index bbfade1fb..1a16d089d 100644 --- a/pkg/e2e/start_stop_test.go +++ b/pkg/e2e/start_stop_test.go @@ -246,3 +246,19 @@ func TestStartStopMultipleServices(t *testing.T) { fmt.Sprintf("Missing start message for %s\n%s", svc, res.Combined())) } } + +func TestStartStopMultipleFiles(t *testing.T) { + cli := NewParallelCLI(t, WithEnv("COMPOSE_PROJECT_NAME=e2e-start-stop-svc-multiple-files")) + t.Cleanup(func() { + cli.RunDockerComposeCmd(t, "-p", "e2e-start-stop-svc-multiple-files", "down", "--remove-orphans") + }) + + cli.RunDockerComposeCmd(t, "-f", "./fixtures/start-stop/compose.yaml", "up", "-d") + cli.RunDockerComposeCmd(t, "-f", "./fixtures/start-stop/other.yaml", "up", "-d") + + res := cli.RunDockerComposeCmd(t, "-f", "./fixtures/start-stop/compose.yaml", "stop") + assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-svc-multiple-files-simple-1 Stopped"), res.Combined()) + assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-start-stop-svc-multiple-files-another-1 Stopped"), res.Combined()) + assert.Assert(t, !strings.Contains(res.Combined(), "Container e2e-start-stop-svc-multiple-files-a-different-one-1 Stopped"), res.Combined()) + assert.Assert(t, !strings.Contains(res.Combined(), "Container e2e-start-stop-svc-multiple-files-and-another-one-1 Stopped"), res.Combined()) +} From be495ab8e603ca9615996a41100569d66f0b8d82 Mon Sep 17 00:00:00 2001 From: Laura Brehm Date: Tue, 2 Aug 2022 21:08:15 +0200 Subject: [PATCH 3/4] Filter `compose ps` output by provided compose model Signed-off-by: Laura Brehm --- cmd/compose/ps.go | 5 +++-- pkg/api/api.go | 1 + pkg/compose/ps.go | 13 +++++++++++++ pkg/compose/ps_test.go | 3 +++ 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/cmd/compose/ps.go b/cmd/compose/ps.go index d79d35ed1..17581aec2 100644 --- a/cmd/compose/ps.go +++ b/cmd/compose/ps.go @@ -91,11 +91,12 @@ func psCommand(p *projectOptions, backend api.Service) *cobra.Command { } func runPs(ctx context.Context, backend api.Service, services []string, opts psOptions) error { - projectName, err := opts.toProjectName() + project, name, err := opts.projectOrName() if err != nil { return err } - containers, err := backend.Ps(ctx, projectName, api.PsOptions{ + containers, err := backend.Ps(ctx, name, api.PsOptions{ + Project: project, All: opts.All, Services: services, }) diff --git a/pkg/api/api.go b/pkg/api/api.go index 947522854..9c3fc240b 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -280,6 +280,7 @@ type ListOptions struct { // PsOptions group options of the Ps API type PsOptions struct { + Project *types.Project All bool Services []string } diff --git a/pkg/compose/ps.go b/pkg/compose/ps.go index de4b25f2e..7df826a08 100644 --- a/pkg/compose/ps.go +++ b/pkg/compose/ps.go @@ -37,6 +37,19 @@ func (s *composeService) Ps(ctx context.Context, projectName string, options api return nil, err } + project := options.Project + if project == nil { + project, err = s.getProjectWithResources(ctx, containers, projectName) + if err != nil { + return nil, err + } + } + + if len(options.Services) == 0 { + options.Services = project.ServiceNames() + } + + containers = containers.filter(isService(options.Services...)) summary := make([]api.ContainerSummary, len(containers)) eg, ctx := errgroup.WithContext(ctx) for i, container := range containers { diff --git a/pkg/compose/ps_test.go b/pkg/compose/ps_test.go index 2f17616e4..669b09e21 100644 --- a/pkg/compose/ps_test.go +++ b/pkg/compose/ps_test.go @@ -26,6 +26,7 @@ import ( moby "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/filters" + "github.com/docker/docker/api/types/volume" compose "github.com/docker/compose/v2/pkg/api" "github.com/docker/compose/v2/pkg/mocks" @@ -48,6 +49,8 @@ func TestPs(t *testing.T) { c2, inspect2 := containerDetails("service1", "456", "running", "", 0) c2.Ports = []moby.Port{{PublicPort: 80, PrivatePort: 90, IP: "localhost"}} c3, inspect3 := containerDetails("service2", "789", "exited", "", 130) + api.EXPECT().VolumeList(ctx, gomock.Any()).Return(volume.VolumeListOKBody{}, nil) + api.EXPECT().NetworkList(ctx, gomock.Any()).Return([]moby.NetworkResource{}, nil) api.EXPECT().ContainerList(ctx, listOpts).Return([]moby.Container{c1, c2, c3}, nil) api.EXPECT().ContainerInspect(anyCancellableContext(), "123").Return(inspect1, nil) api.EXPECT().ContainerInspect(anyCancellableContext(), "456").Return(inspect2, nil) From c586ca4d0e0d84f7ed97c6c6cc4a5abc1e5e463a Mon Sep 17 00:00:00 2001 From: Laura Brehm Date: Wed, 3 Aug 2022 14:50:33 +0200 Subject: [PATCH 4/4] Change `projectOrName()` to check COMPOSE_PROJECT_NAME env var Signed-off-by: Laura Brehm --- cmd/compose/compose.go | 4 ++++ pkg/e2e/fixtures/start-stop/other.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/cmd/compose/compose.go b/cmd/compose/compose.go index c15241415..cfa5154a1 100644 --- a/cmd/compose/compose.go +++ b/cmd/compose/compose.go @@ -142,6 +142,10 @@ func (o *projectOptions) projectOrName() (*types.Project, string, error) { if o.ProjectName == "" { p, err := o.toProject(nil) if err != nil { + envProjectName := os.Getenv("COMPOSE_PROJECT_NAME") + if envProjectName != "" { + return nil, envProjectName, nil + } return nil, "", err } project = p diff --git a/pkg/e2e/fixtures/start-stop/other.yaml b/pkg/e2e/fixtures/start-stop/other.yaml index c28cbd09b..587827261 100644 --- a/pkg/e2e/fixtures/start-stop/other.yaml +++ b/pkg/e2e/fixtures/start-stop/other.yaml @@ -2,4 +2,4 @@ services: a-different-one: image: nginx:alpine and-another-one: - image: nginx:alpine \ No newline at end of file + image: nginx:alpine