Skip to content

Commit 158b5ff

Browse files
committed
build full compose model from resources, then filter by services
Signed-off-by: Nicolas De Loof <[email protected]>
1 parent ce94452 commit 158b5ff

File tree

8 files changed

+60
-32
lines changed

8 files changed

+60
-32
lines changed

cmd/compose/remove.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,13 @@ Any data which is not in a volume will be lost.`,
5959
}
6060

6161
func runRemove(ctx context.Context, backend api.Service, opts removeOptions, services []string) error {
62-
project, err := opts.toProject(services)
62+
project, err := opts.toProjectName()
6363
if err != nil {
6464
return err
6565
}
6666

6767
if opts.stop {
68-
err := backend.Stop(ctx, project.Name, api.StopOptions{
68+
err := backend.Stop(ctx, project, api.StopOptions{
6969
Services: services,
7070
})
7171
if err != nil {

pkg/api/api.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ type Service interface {
5959
// RunOneOffContainer creates a service oneoff container and starts its dependencies
6060
RunOneOffContainer(ctx context.Context, project *types.Project, opts RunOptions) (int, error)
6161
// Remove executes the equivalent to a `compose rm`
62-
Remove(ctx context.Context, project *types.Project, options RemoveOptions) error
62+
Remove(ctx context.Context, project string, options RemoveOptions) error
6363
// Exec executes a command in a running service container
6464
Exec(ctx context.Context, project string, opts RunOptions) (int, error)
6565
// Copy copies a file/folder between a service container and the local filesystem

pkg/api/proxy.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ type ServiceProxy struct {
3939
ConvertFn func(ctx context.Context, project *types.Project, options ConvertOptions) ([]byte, error)
4040
KillFn func(ctx context.Context, project *types.Project, options KillOptions) error
4141
RunOneOffContainerFn func(ctx context.Context, project *types.Project, opts RunOptions) (int, error)
42-
RemoveFn func(ctx context.Context, project *types.Project, options RemoveOptions) error
42+
RemoveFn func(ctx context.Context, project string, options RemoveOptions) error
4343
ExecFn func(ctx context.Context, project string, opts RunOptions) (int, error)
4444
CopyFn func(ctx context.Context, project string, options CopyOptions) error
4545
PauseFn func(ctx context.Context, project string, options PauseOptions) error
@@ -241,13 +241,10 @@ func (s *ServiceProxy) RunOneOffContainer(ctx context.Context, project *types.Pr
241241
}
242242

243243
// Remove implements Service interface
244-
func (s *ServiceProxy) Remove(ctx context.Context, project *types.Project, options RemoveOptions) error {
244+
func (s *ServiceProxy) Remove(ctx context.Context, project string, options RemoveOptions) error {
245245
if s.RemoveFn == nil {
246246
return ErrNotImplemented
247247
}
248-
for _, i := range s.interceptors {
249-
i(ctx, project)
250-
}
251248
return s.RemoveFn(ctx, project, options)
252249
}
253250

pkg/compose/compose.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,3 +149,23 @@ SERVICES:
149149

150150
return project, nil
151151
}
152+
153+
// actualState list resources labelled by projectName to rebuild compose project model
154+
func (s *composeService) actualState(ctx context.Context, projectName string, services []string) (Containers, *types.Project, error) {
155+
var containers Containers
156+
// don't filter containers by options.Services so projectFromName can rebuild project with all existing resources
157+
containers, err := s.getContainers(ctx, projectName, oneOffInclude, true)
158+
if err != nil {
159+
return nil, nil, err
160+
}
161+
162+
project, err := s.projectFromName(containers, projectName, services...)
163+
if err != nil && !api.IsNotFoundError(err) {
164+
return nil, nil, err
165+
}
166+
167+
if len(services) > 0 {
168+
containers = containers.filter(isService(services...))
169+
}
170+
return containers, project, nil
171+
}

pkg/compose/remove.go

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import (
2121
"fmt"
2222
"strings"
2323

24-
"github.com/compose-spec/compose-go/types"
2524
"github.com/docker/compose/v2/pkg/api"
2625
moby "github.com/docker/docker/api/types"
2726
"golang.org/x/sync/errgroup"
@@ -30,13 +29,8 @@ import (
3029
"github.com/docker/compose/v2/pkg/prompt"
3130
)
3231

33-
func (s *composeService) Remove(ctx context.Context, project *types.Project, options api.RemoveOptions) error {
34-
services := options.Services
35-
if len(services) == 0 {
36-
services = project.ServiceNames()
37-
}
38-
39-
containers, err := s.getContainers(ctx, project.Name, oneOffInclude, true, services...)
32+
func (s *composeService) Remove(ctx context.Context, projectName string, options api.RemoveOptions) error {
33+
containers, _, err := s.actualState(ctx, projectName, options.Services)
4034
if err != nil {
4135
return err
4236
}

pkg/compose/stop.go

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,26 +32,11 @@ func (s *composeService) Stop(ctx context.Context, projectName string, options a
3232
func (s *composeService) stop(ctx context.Context, projectName string, options api.StopOptions) error {
3333
w := progress.ContextWriter(ctx)
3434

35-
services := options.Services
36-
if len(services) == 0 {
37-
services = []string{}
38-
}
39-
40-
var containers Containers
41-
containers, err := s.getContainers(ctx, projectName, oneOffInclude, true, services...)
35+
containers, project, err := s.actualState(ctx, projectName, options.Services)
4236
if err != nil {
4337
return err
4438
}
4539

46-
project, err := s.projectFromName(containers, projectName, services...)
47-
if err != nil && !api.IsNotFoundError(err) {
48-
return err
49-
}
50-
51-
if len(services) > 0 {
52-
containers = containers.filter(isService(services...))
53-
}
54-
5540
return InReverseDependencyOrder(ctx, project, func(c context.Context, service string) error {
5641
return s.stopContainers(ctx, w, containers.filter(isService(service)), options.Timeout)
5742
})
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
services:
2+
foo:
3+
image: nginx:alpine
4+
depends_on:
5+
- bar
6+
7+
bar:
8+
image: nginx:alpine

pkg/e2e/start_stop_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,3 +95,27 @@ func TestStartStop(t *testing.T) {
9595
_ = c.RunDockerComposeCmd("--project-name", projectName, "down")
9696
})
9797
}
98+
99+
func TestStopWithDependencies(t *testing.T) {
100+
c := NewParallelE2eCLI(t, binDir)
101+
const projectName = "e2e-stop-with-dependencies"
102+
103+
defer c.RunDockerComposeCmd("--project-name", projectName, "rm", "-fsv")
104+
105+
t.Run("Up", func(t *testing.T) {
106+
res := c.RunDockerComposeCmd("-f", "./fixtures/dependencies/compose.yaml", "--project-name", projectName, "up", "-d")
107+
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-stop-with-dependencies-foo-1 Started"), res.Combined())
108+
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-stop-with-dependencies-bar-1 Started"), res.Combined())
109+
})
110+
111+
t.Run("stop foo", func(t *testing.T) {
112+
res := c.RunDockerComposeCmd("--project-name", projectName, "stop", "foo")
113+
114+
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-stop-with-dependencies-foo-1 Stopped"), res.Combined())
115+
116+
res = c.RunDockerComposeCmd("--project-name", projectName, "ps", "--status", "running")
117+
assert.Assert(t, strings.Contains(res.Combined(), "e2e-stop-with-dependencies-bar-1"), res.Combined())
118+
assert.Assert(t, !strings.Contains(res.Combined(), "e2e-stop-with-dependencies-foo-1"), res.Combined())
119+
})
120+
121+
}

0 commit comments

Comments
 (0)