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
1 changed files with 41 additions and 30 deletions

View File

@ -49,62 +49,73 @@ func (s *composeService) Copy(ctx context.Context, projectName string, options a
var direction copyDirection
var serviceName string
var copyFunc func(ctx context.Context, containerID string, srcPath string, dstPath string, opts api.CopyOptions) error
if srcService != "" {
direction |= fromService
serviceName = srcService
copyFunc = s.copyFromContainer
// copying from multiple containers of a services doesn't make sense.
if options.All {
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 != "" {
direction |= toService
serviceName = destService
copyFunc = s.copyToContainer
}
if direction == acrossServices {
return errors.New("copying between services is not supported")
}
var containers Containers
var err error
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 {
return fmt.Errorf("no container found for service %q", serviceName)
}
if direction == 0 {
return errors.New("unknown copy direction")
}
containers, err := s.listContainersTargetedForCopy(ctx, projectName, options.Index, direction, serviceName)
if err != nil {
return err
}
g := errgroup.Group{}
for _, container := range containers {
containerID := container.ID
g.Go(func() error {
switch direction {
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 copyFunc(ctx, containerID, srcPath, dstPath, options)
})
}
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 {
var err error
if srcPath != "-" {