Browse Source

Merge pull request #9004 from ndeloof/cp_stopped

compose cp doesn't need a full project and can copy from stopped containers
Ulysses Souza 3 years ago
parent
commit
9e52e9fbe3
5 changed files with 21 additions and 20 deletions
  1. 2 2
      cmd/compose/cp.go
  2. 1 1
      pkg/api/api.go
  3. 2 5
      pkg/api/proxy.go
  4. 9 0
      pkg/compose/containers.go
  5. 7 12
      pkg/compose/cp.go

+ 2 - 2
cmd/compose/cp.go

@@ -73,12 +73,12 @@ func copyCommand(p *projectOptions, backend api.Service) *cobra.Command {
 }
 }
 
 
 func runCopy(ctx context.Context, backend api.Service, opts copyOptions) error {
 func runCopy(ctx context.Context, backend api.Service, opts copyOptions) error {
-	projects, err := opts.toProject(nil)
+	name, err := opts.toProjectName()
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
 
 
-	return backend.Copy(ctx, projects, api.CopyOptions{
+	return backend.Copy(ctx, name, api.CopyOptions{
 		Source:      opts.source,
 		Source:      opts.source,
 		Destination: opts.destination,
 		Destination: opts.destination,
 		All:         opts.all,
 		All:         opts.all,

+ 1 - 1
pkg/api/api.go

@@ -63,7 +63,7 @@ type Service interface {
 	// Exec executes a command in a running service container
 	// Exec executes a command in a running service container
 	Exec(ctx context.Context, project string, opts RunOptions) (int, error)
 	Exec(ctx context.Context, project string, opts RunOptions) (int, error)
 	// Copy copies a file/folder between a service container and the local filesystem
 	// Copy copies a file/folder between a service container and the local filesystem
-	Copy(ctx context.Context, project *types.Project, opts CopyOptions) error
+	Copy(ctx context.Context, project string, options CopyOptions) error
 	// Pause executes the equivalent to a `compose pause`
 	// Pause executes the equivalent to a `compose pause`
 	Pause(ctx context.Context, project string, options PauseOptions) error
 	Pause(ctx context.Context, project string, options PauseOptions) error
 	// UnPause executes the equivalent to a `compose unpause`
 	// UnPause executes the equivalent to a `compose unpause`

+ 2 - 5
pkg/api/proxy.go

@@ -41,7 +41,7 @@ type ServiceProxy struct {
 	RunOneOffContainerFn func(ctx context.Context, project *types.Project, opts RunOptions) (int, error)
 	RunOneOffContainerFn func(ctx context.Context, project *types.Project, opts RunOptions) (int, error)
 	RemoveFn             func(ctx context.Context, project *types.Project, options RemoveOptions) error
 	RemoveFn             func(ctx context.Context, project *types.Project, options RemoveOptions) error
 	ExecFn               func(ctx context.Context, project string, opts RunOptions) (int, error)
 	ExecFn               func(ctx context.Context, project string, opts RunOptions) (int, error)
-	CopyFn               func(ctx context.Context, project *types.Project, opts CopyOptions) error
+	CopyFn               func(ctx context.Context, project string, options CopyOptions) error
 	PauseFn              func(ctx context.Context, project string, options PauseOptions) error
 	PauseFn              func(ctx context.Context, project string, options PauseOptions) error
 	UnPauseFn            func(ctx context.Context, project string, options PauseOptions) error
 	UnPauseFn            func(ctx context.Context, project string, options PauseOptions) error
 	TopFn                func(ctx context.Context, projectName string, services []string) ([]ContainerProcSummary, error)
 	TopFn                func(ctx context.Context, projectName string, services []string) ([]ContainerProcSummary, error)
@@ -269,13 +269,10 @@ func (s *ServiceProxy) Exec(ctx context.Context, project string, options RunOpti
 }
 }
 
 
 // Copy implements Service interface
 // Copy implements Service interface
-func (s *ServiceProxy) Copy(ctx context.Context, project *types.Project, options CopyOptions) error {
+func (s *ServiceProxy) Copy(ctx context.Context, project string, options CopyOptions) error {
 	if s.CopyFn == nil {
 	if s.CopyFn == nil {
 		return ErrNotImplemented
 		return ErrNotImplemented
 	}
 	}
-	for _, i := range s.interceptors {
-		i(ctx, project)
-	}
 	return s.CopyFn(ctx, project, options)
 	return s.CopyFn(ctx, project, options)
 }
 }
 
 

+ 9 - 0
pkg/compose/containers.go

@@ -19,6 +19,7 @@ package compose
 import (
 import (
 	"context"
 	"context"
 	"sort"
 	"sort"
+	"strconv"
 
 
 	moby "github.com/docker/docker/api/types"
 	moby "github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/filters"
 	"github.com/docker/docker/api/types/filters"
@@ -86,6 +87,14 @@ func isNotOneOff(c moby.Container) bool {
 	return !ok || v == "False"
 	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
 // filter return Containers with elements to match predicate
 func (containers Containers) filter(predicate containerPredicate) Containers {
 func (containers Containers) filter(predicate containerPredicate) Containers {
 	var filtered Containers
 	var filtered Containers

+ 7 - 12
pkg/compose/cp.go

@@ -26,11 +26,9 @@ import (
 
 
 	"golang.org/x/sync/errgroup"
 	"golang.org/x/sync/errgroup"
 
 
-	"github.com/compose-spec/compose-go/types"
 	"github.com/docker/cli/cli/command"
 	"github.com/docker/cli/cli/command"
 	"github.com/docker/compose/v2/pkg/api"
 	"github.com/docker/compose/v2/pkg/api"
 	moby "github.com/docker/docker/api/types"
 	moby "github.com/docker/docker/api/types"
-	"github.com/docker/docker/api/types/filters"
 	"github.com/docker/docker/pkg/archive"
 	"github.com/docker/docker/pkg/archive"
 	"github.com/docker/docker/pkg/system"
 	"github.com/docker/docker/pkg/system"
 	"github.com/pkg/errors"
 	"github.com/pkg/errors"
@@ -44,7 +42,7 @@ const (
 	acrossServices = fromService | toService
 	acrossServices = fromService | toService
 )
 )
 
 
-func (s *composeService) Copy(ctx context.Context, project *types.Project, opts api.CopyOptions) error {
+func (s *composeService) Copy(ctx context.Context, project string, opts api.CopyOptions) error {
 	srcService, srcPath := splitCpArg(opts.Source)
 	srcService, srcPath := splitCpArg(opts.Source)
 	destService, dstPath := splitCpArg(opts.Destination)
 	destService, dstPath := splitCpArg(opts.Destination)
 
 
@@ -64,20 +62,17 @@ func (s *composeService) Copy(ctx context.Context, project *types.Project, opts
 		serviceName = destService
 		serviceName = destService
 	}
 	}
 
 
-	f := filters.NewArgs(
-		projectFilter(project.Name),
-		serviceFilter(serviceName),
-	)
-	if !opts.All {
-		f.Add("label", fmt.Sprintf("%s=%d", api.ContainerNumberLabel, opts.Index))
-	}
-	containers, err := s.apiClient.ContainerList(ctx, moby.ContainerListOptions{Filters: f})
+	containers, err := s.getContainers(ctx, project, oneOffExclude, true, serviceName)
 	if err != nil {
 	if err != nil {
 		return err
 		return err
 	}
 	}
 
 
 	if len(containers) < 1 {
 	if len(containers) < 1 {
-		return fmt.Errorf("service %s not running", serviceName)
+		return fmt.Errorf("no container found for service %q", serviceName)
+	}
+
+	if !opts.All {
+		containers = containers.filter(indexed(opts.Index))
 	}
 	}
 
 
 	g := errgroup.Group{}
 	g := errgroup.Group{}