浏览代码

align cp command index management with exec command

Signed-off-by: Guillaume Lours <[email protected]>
Guillaume Lours 3 年之前
父节点
当前提交
a964d5587b
共有 3 个文件被更改,包括 51 次插入47 次删除
  1. 34 19
      pkg/compose/containers.go
  2. 16 11
      pkg/compose/cp.go
  3. 1 17
      pkg/compose/exec.go

+ 34 - 19
pkg/compose/containers.go

@@ -18,14 +18,13 @@ package compose
 
 import (
 	"context"
+	"fmt"
 	"sort"
-	"strconv"
-
-	moby "github.com/docker/docker/api/types"
-	"github.com/docker/docker/api/types/filters"
 
 	"github.com/docker/compose/v2/pkg/api"
 	"github.com/docker/compose/v2/pkg/utils"
+	moby "github.com/docker/docker/api/types"
+	"github.com/docker/docker/api/types/filters"
 )
 
 // Containers is a set of moby Container
@@ -41,7 +40,22 @@ const (
 
 func (s *composeService) getContainers(ctx context.Context, project string, oneOff oneOff, stopped bool, selectedServices ...string) (Containers, error) {
 	var containers Containers
-	f := []filters.KeyValuePair{projectFilter(project)}
+	f := getDefaultFilters(project, oneOff, selectedServices...)
+	containers, err := s.apiClient().ContainerList(ctx, moby.ContainerListOptions{
+		Filters: filters.NewArgs(f...),
+		All:     stopped,
+	})
+	if err != nil {
+		return nil, err
+	}
+	if len(selectedServices) > 1 {
+		containers = containers.filter(isService(selectedServices...))
+	}
+	return containers, nil
+}
+
+func getDefaultFilters(projectName string, oneOff oneOff, selectedServices ...string) []filters.KeyValuePair {
+	f := []filters.KeyValuePair{projectFilter(projectName)}
 	if len(selectedServices) == 1 {
 		f = append(f, serviceFilter(selectedServices[0]))
 	}
@@ -52,17 +66,26 @@ func (s *composeService) getContainers(ctx context.Context, project string, oneO
 		f = append(f, oneOffFilter(false))
 	case oneOffInclude:
 	}
+	return f
+}
+
+func (s *composeService) getSpecifiedContainer(ctx context.Context, projectName string, oneOff oneOff, stopped bool, serviceName string, containerIndex int) (moby.Container, error) {
+	defaultFilters := getDefaultFilters(projectName, oneOff, serviceName)
+	defaultFilters = append(defaultFilters, containerNumberFilter(containerIndex))
 	containers, err := s.apiClient().ContainerList(ctx, moby.ContainerListOptions{
-		Filters: filters.NewArgs(f...),
-		All:     stopped,
+		Filters: filters.NewArgs(
+			defaultFilters...,
+		),
+		All: stopped,
 	})
 	if err != nil {
-		return nil, err
+		return moby.Container{}, err
 	}
-	if len(selectedServices) > 1 {
-		containers = containers.filter(isService(selectedServices...))
+	if len(containers) < 1 {
+		return moby.Container{}, fmt.Errorf("service %q is not running container #%d", serviceName, containerIndex)
 	}
-	return containers, nil
+	container := containers[0]
+	return container, nil
 }
 
 // containerPredicate define a predicate we want container to satisfy for filtering operations
@@ -87,14 +110,6 @@ func isNotOneOff(c moby.Container) bool {
 	return !ok || v == "False"
 }
 
-func indexed(index int) containerPredicate {
-	return func(c moby.Container) bool {
-		number := c.Labels[api.ContainerNumberLabel]
-		idx, err := strconv.Atoi(number)
-		return err == nil && index == idx
-	}
-}
-
 // filter return Containers with elements to match predicate
 func (containers Containers) filter(predicate containerPredicate) Containers {
 	var filtered Containers

+ 16 - 11
pkg/compose/cp.go

@@ -66,18 +66,23 @@ func (s *composeService) Copy(ctx context.Context, projectName string, options a
 		direction |= toService
 		serviceName = destService
 	}
-
-	containers, err := s.getContainers(ctx, projectName, oneOffExclude, true, serviceName)
-	if err != nil {
-		return err
-	}
-
-	if len(containers) < 1 {
-		return fmt.Errorf("no container found for service %q", serviceName)
-	}
-
+	var containers Containers
+	var err error
 	if direction == fromService || (direction == toService && options.Index > 0) {
-		containers = containers.filter(indexed(options.Index))
+		container, err := s.getSpecifiedContainer(ctx, projectName, oneOffExclude, true, serviceName, options.Index)
+		if err != nil {
+			return err
+		}
+		containers = append(containers, container)
+	} else {
+		containers, err = s.getContainers(ctx, projectName, oneOffExclude, true, serviceName)
+		if err != nil {
+			return err
+		}
+
+		if len(containers) < 1 {
+			return fmt.Errorf("no container found for service %q", serviceName)
+		}
 	}
 
 	g := errgroup.Group{}

+ 1 - 17
pkg/compose/exec.go

@@ -18,14 +18,12 @@ package compose
 
 import (
 	"context"
-	"fmt"
 	"strings"
 
 	"github.com/docker/cli/cli"
 	"github.com/docker/cli/cli/command/container"
 	"github.com/docker/compose/v2/pkg/api"
 	moby "github.com/docker/docker/api/types"
-	"github.com/docker/docker/api/types/filters"
 )
 
 func (s *composeService) Exec(ctx context.Context, projectName string, options api.RunOptions) (int, error) {
@@ -59,19 +57,5 @@ func (s *composeService) Exec(ctx context.Context, projectName string, options a
 }
 
 func (s *composeService) getExecTarget(ctx context.Context, projectName string, opts api.RunOptions) (moby.Container, error) {
-	containers, err := s.apiClient().ContainerList(ctx, moby.ContainerListOptions{
-		Filters: filters.NewArgs(
-			projectFilter(projectName),
-			serviceFilter(opts.Service),
-			containerNumberFilter(opts.Index),
-		),
-	})
-	if err != nil {
-		return moby.Container{}, err
-	}
-	if len(containers) < 1 {
-		return moby.Container{}, fmt.Errorf("service %q is not running container #%d", opts.Service, opts.Index)
-	}
-	container := containers[0]
-	return container, nil
+	return s.getSpecifiedContainer(ctx, projectName, oneOffInclude, false, opts.Service, opts.Index)
 }