mirror of https://github.com/docker/compose.git
build full compose model from resources, then filter by services
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
parent
ce944520ff
commit
158b5ff6a3
|
@ -59,13 +59,13 @@ 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.toProject(services)
|
||||
project, err := opts.toProjectName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if opts.stop {
|
||||
err := backend.Stop(ctx, project.Name, api.StopOptions{
|
||||
err := backend.Stop(ctx, project, api.StopOptions{
|
||||
Services: services,
|
||||
})
|
||||
if err != nil {
|
||||
|
|
|
@ -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) error
|
||||
Remove(ctx context.Context, project string, options RemoveOptions) error
|
||||
// Exec executes a command in a running service container
|
||||
Exec(ctx context.Context, project string, opts RunOptions) (int, error)
|
||||
// Copy copies a file/folder between a service container and the local filesystem
|
||||
|
|
|
@ -39,7 +39,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) error
|
||||
RemoveFn func(ctx context.Context, project string, options RemoveOptions) error
|
||||
ExecFn func(ctx context.Context, project string, opts RunOptions) (int, error)
|
||||
CopyFn func(ctx context.Context, project string, options CopyOptions) error
|
||||
PauseFn func(ctx context.Context, project string, options PauseOptions) error
|
||||
|
@ -241,13 +241,10 @@ 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) error {
|
||||
func (s *ServiceProxy) Remove(ctx context.Context, project string, options RemoveOptions) error {
|
||||
if s.RemoveFn == nil {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
for _, i := range s.interceptors {
|
||||
i(ctx, project)
|
||||
}
|
||||
return s.RemoveFn(ctx, project, options)
|
||||
}
|
||||
|
||||
|
|
|
@ -149,3 +149,23 @@ 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
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
"github.com/docker/compose/v2/pkg/api"
|
||||
moby "github.com/docker/docker/api/types"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
@ -30,13 +29,8 @@ import (
|
|||
"github.com/docker/compose/v2/pkg/prompt"
|
||||
)
|
||||
|
||||
func (s *composeService) Remove(ctx context.Context, project *types.Project, options api.RemoveOptions) error {
|
||||
services := options.Services
|
||||
if len(services) == 0 {
|
||||
services = project.ServiceNames()
|
||||
}
|
||||
|
||||
containers, err := s.getContainers(ctx, project.Name, oneOffInclude, true, services...)
|
||||
func (s *composeService) Remove(ctx context.Context, projectName string, options api.RemoveOptions) error {
|
||||
containers, _, err := s.actualState(ctx, projectName, options.Services)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -32,26 +32,11 @@ 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)
|
||||
|
||||
services := options.Services
|
||||
if len(services) == 0 {
|
||||
services = []string{}
|
||||
}
|
||||
|
||||
var containers Containers
|
||||
containers, err := s.getContainers(ctx, projectName, oneOffInclude, true, services...)
|
||||
containers, project, err := s.actualState(ctx, projectName, options.Services)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
project, err := s.projectFromName(containers, projectName, services...)
|
||||
if err != nil && !api.IsNotFoundError(err) {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(services) > 0 {
|
||||
containers = containers.filter(isService(services...))
|
||||
}
|
||||
|
||||
return InReverseDependencyOrder(ctx, project, func(c context.Context, service string) error {
|
||||
return s.stopContainers(ctx, w, containers.filter(isService(service)), options.Timeout)
|
||||
})
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
services:
|
||||
foo:
|
||||
image: nginx:alpine
|
||||
depends_on:
|
||||
- bar
|
||||
|
||||
bar:
|
||||
image: nginx:alpine
|
|
@ -95,3 +95,27 @@ func TestStartStop(t *testing.T) {
|
|||
_ = c.RunDockerComposeCmd("--project-name", projectName, "down")
|
||||
})
|
||||
}
|
||||
|
||||
func TestStopWithDependencies(t *testing.T) {
|
||||
c := NewParallelE2eCLI(t, binDir)
|
||||
const projectName = "e2e-stop-with-dependencies"
|
||||
|
||||
defer c.RunDockerComposeCmd("--project-name", projectName, "rm", "-fsv")
|
||||
|
||||
t.Run("Up", func(t *testing.T) {
|
||||
res := c.RunDockerComposeCmd("-f", "./fixtures/dependencies/compose.yaml", "--project-name", projectName, "up", "-d")
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-stop-with-dependencies-foo-1 Started"), res.Combined())
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-stop-with-dependencies-bar-1 Started"), res.Combined())
|
||||
})
|
||||
|
||||
t.Run("stop foo", func(t *testing.T) {
|
||||
res := c.RunDockerComposeCmd("--project-name", projectName, "stop", "foo")
|
||||
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "Container e2e-stop-with-dependencies-foo-1 Stopped"), res.Combined())
|
||||
|
||||
res = c.RunDockerComposeCmd("--project-name", projectName, "ps", "--status", "running")
|
||||
assert.Assert(t, strings.Contains(res.Combined(), "e2e-stop-with-dependencies-bar-1"), res.Combined())
|
||||
assert.Assert(t, !strings.Contains(res.Combined(), "e2e-stop-with-dependencies-foo-1"), res.Combined())
|
||||
})
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue