cp command from service to host: use the first container found to copy source on the host

Signed-off-by: Guillaume Lours <guillaume.lours@docker.com>
This commit is contained in:
Guillaume Lours 2022-05-06 11:37:33 +02:00 committed by Nicolas De loof
parent 6d9d75406c
commit a603e27117

View File

@ -49,62 +49,73 @@ func (s *composeService) Copy(ctx context.Context, projectName string, options a
var direction copyDirection var direction copyDirection
var serviceName string var serviceName string
var copyFunc func(ctx context.Context, containerID string, srcPath string, dstPath string, opts api.CopyOptions) error
if srcService != "" { if srcService != "" {
direction |= fromService direction |= fromService
serviceName = srcService serviceName = srcService
copyFunc = s.copyFromContainer
// copying from multiple containers of a services doesn't make sense. // copying from multiple containers of a services doesn't make sense.
if options.All { if options.All {
return errors.New("cannot use the --all flag when copying from a service") return errors.New("cannot use the --all flag when copying from a service")
} }
// due to remove of the --all flag, restore the default value to 1 when copying from a service container to the host.
if options.Index == 0 {
options.Index = 1
}
} }
if destService != "" { if destService != "" {
direction |= toService direction |= toService
serviceName = destService serviceName = destService
copyFunc = s.copyToContainer
} }
var containers Containers if direction == acrossServices {
var err error return errors.New("copying between services is not supported")
if direction == fromService || (direction == toService && options.Index > 0) {
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 { if direction == 0 {
return fmt.Errorf("no container found for service %q", serviceName) return errors.New("unknown copy direction")
} }
containers, err := s.listContainersTargetedForCopy(ctx, projectName, options.Index, direction, serviceName)
if err != nil {
return err
} }
g := errgroup.Group{} g := errgroup.Group{}
for _, container := range containers { for _, container := range containers {
containerID := container.ID containerID := container.ID
g.Go(func() error { g.Go(func() error {
switch direction { return copyFunc(ctx, containerID, srcPath, dstPath, options)
case fromService:
return s.copyFromContainer(ctx, containerID, srcPath, dstPath, options)
case toService:
return s.copyToContainer(ctx, containerID, srcPath, dstPath, options)
case acrossServices:
return errors.New("copying between services is not supported")
default:
return errors.New("unknown copy direction")
}
}) })
} }
return g.Wait() return g.Wait()
} }
func (s *composeService) listContainersTargetedForCopy(ctx context.Context, projectName string, index int, direction copyDirection, serviceName string) (Containers, error) {
var containers Containers
var err error
switch {
case index > 0:
container, err := s.getSpecifiedContainer(ctx, projectName, oneOffExclude, true, serviceName, index)
if err != nil {
return nil, err
}
return append(containers, container), nil
default:
containers, err = s.getContainers(ctx, projectName, oneOffExclude, true, serviceName)
if err != nil {
return nil, err
}
if len(containers) < 1 {
return nil, fmt.Errorf("no container found for service %q", serviceName)
}
if direction == fromService {
return containers[:1], err
}
return containers, err
}
}
func (s *composeService) copyToContainer(ctx context.Context, containerID string, srcPath string, dstPath string, opts api.CopyOptions) error { func (s *composeService) copyToContainer(ctx context.Context, containerID string, srcPath string, dstPath string, opts api.CopyOptions) error {
var err error var err error
if srcPath != "-" { if srcPath != "-" {