Skip to content

Commit

Permalink
fix --remove-orphans not to consider disabled services as orphaned
Browse files Browse the repository at this point in the history
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
  • Loading branch information
ndeloof committed Nov 20, 2023
1 parent a1b7bee commit 8e1b323
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 1 deletion.
16 changes: 16 additions & 0 deletions pkg/compose/containers.go
Expand Up @@ -22,6 +22,7 @@ import (
"sort"
"strconv"

"github.com/compose-spec/compose-go/types"
"github.com/docker/compose/v2/pkg/api"
"github.com/docker/compose/v2/pkg/utils"
moby "github.com/docker/docker/api/types"
Expand Down Expand Up @@ -123,6 +124,21 @@ func isNotService(services ...string) containerPredicate {
}
}

// isOrphaned is a predicate to select containers without a matching service definition in compose project
func isOrphaned(project *types.Project) containerPredicate {
var services []string
for _, s := range project.Services {
services = append(services, s.Name)
}
for _, s := range project.DisabledServices {
services = append(services, s.Name)
}
return func(c moby.Container) bool {
service := c.Labels[api.ServiceLabel]
return !utils.StringContains(services, service)
}
}

func isNotOneOff(c moby.Container) bool {
v, ok := c.Labels[api.OneoffLabel]
return !ok || v == "False"
Expand Down
2 changes: 1 addition & 1 deletion pkg/compose/down.go
Expand Up @@ -83,7 +83,7 @@ func (s *composeService) down(ctx context.Context, projectName string, options a
return err
}

orphans := containers.filter(isNotService(project.ServiceNames()...))
orphans := containers.filter(isOrphaned(project))
if options.RemoveOrphans && len(orphans) > 0 {
err := s.removeContainers(ctx, w, orphans, options.Timeout, false)
if err != nil {
Expand Down
21 changes: 21 additions & 0 deletions pkg/e2e/compose_test.go
Expand Up @@ -292,3 +292,24 @@ func TestStopWithDependenciesAttached(t *testing.T) {
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/dependencies/compose.yaml", "-p", projectName, "up", "--attach-dependencies", "foo")
res.Assert(t, icmd.Expected{Out: "exited with code 0"})
}

func TestRemoveOrphaned(t *testing.T) {
const projectName = "compose-e2e-remove-orphaned"
c := NewParallelCLI(t)

cleanup := func() {
c.RunDockerComposeCmd(t, "-p", projectName, "down", "--remove-orphans", "--timeout=0")
}
cleanup()
t.Cleanup(cleanup)

// run stack
c.RunDockerComposeCmd(t, "-f", "./fixtures/sentences/compose.yaml", "-p", projectName, "up", "-d")

// down "web" service with orphaned removed
c.RunDockerComposeCmd(t, "-f", "./fixtures/sentences/compose.yaml", "-p", projectName, "down", "--remove-orphans", "web")

// check "words" service has not been considered orphaned
res := c.RunDockerComposeCmd(t, "-f", "./fixtures/sentences/compose.yaml", "-p", projectName, "ps", "--format", "{{.Name}}")
res.Assert(t, icmd.Expected{Out: fmt.Sprintf("%s-words-1", projectName)})
}

0 comments on commit 8e1b323

Please sign in to comment.