Skip to content
This repository was archived by the owner on Nov 27, 2023. It is now read-only.

Commit 8f9ce9d

Browse files
committed
Add cp command
Signed-off-by: Julien Tant <[email protected]>
1 parent 63057f6 commit 8f9ce9d

File tree

12 files changed

+392
-0
lines changed

12 files changed

+392
-0
lines changed

aci/compose.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ func (cs *aciComposeService) UnPause(ctx context.Context, project string, option
8080
return errdefs.ErrNotImplemented
8181
}
8282

83+
func (cs *aciComposeService) Copy(ctx context.Context, project *types.Project, options compose.CopyOptions) error {
84+
return errdefs.ErrNotImplemented
85+
}
86+
8387
func (cs *aciComposeService) Up(ctx context.Context, project *types.Project, options compose.UpOptions) error {
8488
logrus.Debugf("Up on project with name %q", project.Name)
8589

api/client/compose.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,10 @@ func (c *composeService) Exec(ctx context.Context, project *types.Project, opts
9696
return 0, errdefs.ErrNotImplemented
9797
}
9898

99+
func (c *composeService) Copy(ctx context.Context, project *types.Project, opts compose.CopyOptions) error {
100+
return errdefs.ErrNotImplemented
101+
}
102+
99103
func (c *composeService) Pause(ctx context.Context, project string, options compose.PauseOptions) error {
100104
return errdefs.ErrNotImplemented
101105
}

api/compose/api.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ type Service interface {
6262
Remove(ctx context.Context, project *types.Project, options RemoveOptions) ([]string, error)
6363
// Exec executes a command in a running service container
6464
Exec(ctx context.Context, project *types.Project, opts RunOptions) (int, error)
65+
// Copy copies a file/folder between a service container and the local filesystem
66+
Copy(ctx context.Context, project *types.Project, opts CopyOptions) error
6567
// Pause executes the equivalent to a `compose pause`
6668
Pause(ctx context.Context, project string, options PauseOptions) error
6769
// UnPause executes the equivalent to a `compose unpause`
@@ -271,6 +273,15 @@ type PsOptions struct {
271273
All bool
272274
}
273275

276+
// CopyOptions group options of the cp API
277+
type CopyOptions struct {
278+
Source string
279+
Destination string
280+
Index int
281+
FollowLink bool
282+
CopyUIDGID bool
283+
}
284+
274285
// PortPublisher hold status about published port
275286
type PortPublisher struct {
276287
URL string

api/compose/delegator.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,11 @@ func (s *ServiceDelegator) Exec(ctx context.Context, project *types.Project, opt
112112
return s.Delegate.Exec(ctx, project, options)
113113
}
114114

115+
//Copy implements Service interface
116+
func (s *ServiceDelegator) Copy(ctx context.Context, project *types.Project, options CopyOptions) error {
117+
return s.Delegate.Copy(ctx, project, options)
118+
}
119+
115120
//Pause implements Service interface
116121
func (s *ServiceDelegator) Pause(ctx context.Context, project string, options PauseOptions) error {
117122
return s.Delegate.Pause(ctx, project, options)

api/compose/noimpl.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,11 @@ func (s NoImpl) Exec(ctx context.Context, project *types.Project, opts RunOption
112112
return 0, errdefs.ErrNotImplemented
113113
}
114114

115+
//Copy implements Service interface
116+
func (s NoImpl) Copy(ctx context.Context, project *types.Project, opts CopyOptions) error {
117+
return errdefs.ErrNotImplemented
118+
}
119+
115120
//Pause implements Service interface
116121
func (s NoImpl) Pause(ctx context.Context, project string, options PauseOptions) error {
117122
return errdefs.ErrNotImplemented

cli/cmd/compose/compose.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ func RootCommand(contextType string, backend compose.Service) *cobra.Command {
228228
pushCommand(&opts, backend),
229229
pullCommand(&opts, backend),
230230
createCommand(&opts, backend),
231+
copyCommand(&opts, backend),
231232
)
232233
}
233234
command.Flags().SetInterspersed(false)

cli/cmd/compose/cp.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
Copyright 2020 Docker Compose CLI authors
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package compose
18+
19+
import (
20+
"context"
21+
"errors"
22+
23+
"github.com/docker/cli/cli"
24+
"github.com/spf13/cobra"
25+
26+
"github.com/docker/compose-cli/api/compose"
27+
)
28+
29+
type copyOptions struct {
30+
*projectOptions
31+
32+
source string
33+
destination string
34+
index int
35+
followLink bool
36+
copyUIDGID bool
37+
}
38+
39+
func copyCommand(p *projectOptions, backend compose.Service) *cobra.Command {
40+
opts := copyOptions{
41+
projectOptions: p,
42+
}
43+
copyCmd := &cobra.Command{
44+
Use: `cp [OPTIONS] SERVICE:SRC_PATH DEST_PATH|-
45+
docker compose cp [OPTIONS] SRC_PATH|- SERVICE:DEST_PATH`,
46+
Short: "Copy files/folders between a service container and the local filesystem",
47+
Args: cli.ExactArgs(2),
48+
RunE: Adapt(func(ctx context.Context, args []string) error {
49+
if args[0] == "" {
50+
return errors.New("source can not be empty")
51+
}
52+
if args[1] == "" {
53+
return errors.New("destination can not be empty")
54+
}
55+
56+
opts.source = args[0]
57+
opts.destination = args[1]
58+
return runCopy(ctx, backend, opts)
59+
}),
60+
}
61+
62+
flags := copyCmd.Flags()
63+
flags.IntVar(&opts.index, "index", 1, "index of the container if there are multiple instances of a service [default: 1].")
64+
flags.BoolVarP(&opts.followLink, "follow-link", "L", false, "Always follow symbol link in SRC_PATH")
65+
flags.BoolVarP(&opts.copyUIDGID, "archive", "a", false, "Archive mode (copy all uid/gid information)")
66+
67+
return copyCmd
68+
}
69+
70+
func runCopy(ctx context.Context, backend compose.Service, opts copyOptions) error {
71+
projects, err := opts.toProject(nil)
72+
if err != nil {
73+
return err
74+
}
75+
76+
return backend.Copy(ctx, projects, compose.CopyOptions{
77+
Source: opts.source,
78+
Destination: opts.destination,
79+
Index: opts.index,
80+
FollowLink: opts.followLink,
81+
CopyUIDGID: opts.copyUIDGID,
82+
})
83+
}

cli/metrics/commands.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ var commands = []string{
6363
"deploy",
6464
"list",
6565
"ls",
66+
"cp",
6667
"merge",
6768
"pull",
6869
"push",

ecs/local/compose.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,10 @@ func (e ecsLocalSimulation) Exec(ctx context.Context, project *types.Project, op
188188
return 0, errdefs.ErrNotImplemented
189189
}
190190

191+
func (e ecsLocalSimulation) Copy(ctx context.Context, project *types.Project, opts compose.CopyOptions) error {
192+
return e.compose.Copy(ctx, project, opts)
193+
}
194+
191195
func (e ecsLocalSimulation) Pause(ctx context.Context, project string, options compose.PauseOptions) error {
192196
return e.compose.Pause(ctx, project, options)
193197
}

ecs/up.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ func (b *ecsAPIService) Port(ctx context.Context, project string, service string
7575
return "", 0, errdefs.ErrNotImplemented
7676
}
7777

78+
func (b *ecsAPIService) Copy(ctx context.Context, project *types.Project, options compose.CopyOptions) error {
79+
return errdefs.ErrNotImplemented
80+
}
81+
7882
func (b *ecsAPIService) Up(ctx context.Context, project *types.Project, options compose.UpOptions) error {
7983
logrus.Debugf("deploying on AWS with region=%q", b.Region)
8084
err := b.aws.CheckRequirements(ctx, b.Region)

0 commit comments

Comments
 (0)