Răsfoiți Sursa

fix --remove-orphans not to consider disabled services as orphaned

Signed-off-by: Nicolas De Loof <[email protected]>
Nicolas De Loof 1 an în urmă
părinte
comite
8e1b32365e
3 a modificat fișierele cu 38 adăugiri și 1 ștergeri
  1. 16 0
      pkg/compose/containers.go
  2. 1 1
      pkg/compose/down.go
  3. 21 0
      pkg/e2e/compose_test.go

+ 16 - 0
pkg/compose/containers.go

@@ -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"
@@ -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"

+ 1 - 1
pkg/compose/down.go

@@ -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 {

+ 21 - 0
pkg/e2e/compose_test.go

@@ -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)})
+}