align cp command index management with exec command

Signed-off-by: Guillaume Lours <guillaume.lours@docker.com>
This commit is contained in:
Guillaume Lours 2022-05-04 17:08:55 +02:00 committed by Nicolas De loof
parent a983cf551d
commit a964d5587b
3 changed files with 55 additions and 51 deletions

View File

@ -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,17 +40,7 @@ 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)}
if len(selectedServices) == 1 {
f = append(f, serviceFilter(selectedServices[0]))
}
switch oneOff {
case oneOffOnly:
f = append(f, oneOffFilter(true))
case oneOffExclude:
f = append(f, oneOffFilter(false))
case oneOffInclude:
}
f := getDefaultFilters(project, oneOff, selectedServices...)
containers, err := s.apiClient().ContainerList(ctx, moby.ContainerListOptions{
Filters: filters.NewArgs(f...),
All: stopped,
@ -65,6 +54,40 @@ func (s *composeService) getContainers(ctx context.Context, project string, oneO
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]))
}
switch oneOff {
case oneOffOnly:
f = append(f, oneOffFilter(true))
case oneOffExclude:
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(
defaultFilters...,
),
All: stopped,
})
if err != nil {
return moby.Container{}, err
}
if len(containers) < 1 {
return moby.Container{}, fmt.Errorf("service %q is not running container #%d", serviceName, containerIndex)
}
container := containers[0]
return container, nil
}
// containerPredicate define a predicate we want container to satisfy for filtering operations
type containerPredicate func(c moby.Container) bool
@ -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

View File

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

View File

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