* Client and server use types.CopyConfig
* API calls container.Copy directly
Signed-off-by: Alexander Morozov <lk4d4@docker.com>
| ... | ... |
@@ -5,7 +5,7 @@ import ( |
| 5 | 5 |
"io" |
| 6 | 6 |
"strings" |
| 7 | 7 |
|
| 8 |
- "github.com/docker/docker/engine" |
|
| 8 |
+ "github.com/docker/docker/api/types" |
|
| 9 | 9 |
"github.com/docker/docker/pkg/archive" |
| 10 | 10 |
flag "github.com/docker/docker/pkg/mflag" |
| 11 | 11 |
) |
| ... | ... |
@@ -21,17 +21,16 @@ func (cli *DockerCli) CmdCp(args ...string) error {
|
| 21 | 21 |
|
| 22 | 22 |
cmd.ParseFlags(args, true) |
| 23 | 23 |
|
| 24 |
- var copyData engine.Env |
|
| 25 | 24 |
info := strings.Split(cmd.Arg(0), ":") |
| 26 | 25 |
|
| 27 | 26 |
if len(info) != 2 {
|
| 28 | 27 |
return fmt.Errorf("Error: Path not specified")
|
| 29 | 28 |
} |
| 30 | 29 |
|
| 31 |
- copyData.Set("Resource", info[1])
|
|
| 32 |
- copyData.Set("HostPath", cmd.Arg(1))
|
|
| 33 |
- |
|
| 34 |
- stream, statusCode, err := cli.call("POST", "/containers/"+info[0]+"/copy", copyData, nil)
|
|
| 30 |
+ cfg := &types.CopyConfig{
|
|
| 31 |
+ Resource: info[1], |
|
| 32 |
+ } |
|
| 33 |
+ stream, statusCode, err := cli.call("POST", "/containers/"+info[0]+"/copy", cfg, nil)
|
|
| 35 | 34 |
if stream != nil {
|
| 36 | 35 |
defer stream.Close() |
| 37 | 36 |
} |
| ... | ... |
@@ -42,13 +41,12 @@ func (cli *DockerCli) CmdCp(args ...string) error {
|
| 42 | 42 |
return err |
| 43 | 43 |
} |
| 44 | 44 |
|
| 45 |
+ hostPath := cmd.Arg(1) |
|
| 45 | 46 |
if statusCode == 200 {
|
| 46 |
- dest := copyData.Get("HostPath")
|
|
| 47 |
- |
|
| 48 |
- if dest == "-" {
|
|
| 47 |
+ if hostPath == "-" {
|
|
| 49 | 48 |
_, err = io.Copy(cli.out, stream) |
| 50 | 49 |
} else {
|
| 51 |
- err = archive.Untar(stream, dest, &archive.TarOptions{NoLchown: true})
|
|
| 50 |
+ err = archive.Untar(stream, hostPath, &archive.TarOptions{NoLchown: true})
|
|
| 52 | 51 |
} |
| 53 | 52 |
if err != nil {
|
| 54 | 53 |
return err |
| ... | ... |
@@ -1203,37 +1203,48 @@ func postContainersCopy(eng *engine.Engine, version version.Version, w http.Resp |
| 1203 | 1203 |
return fmt.Errorf("Missing parameter")
|
| 1204 | 1204 |
} |
| 1205 | 1205 |
|
| 1206 |
- var copyData engine.Env |
|
| 1207 |
- |
|
| 1208 | 1206 |
if err := checkForJson(r); err != nil {
|
| 1209 | 1207 |
return err |
| 1210 | 1208 |
} |
| 1211 | 1209 |
|
| 1212 |
- if err := copyData.Decode(r.Body); err != nil {
|
|
| 1210 |
+ cfg := types.CopyConfig{}
|
|
| 1211 |
+ if err := json.NewDecoder(r.Body).Decode(&cfg); err != nil {
|
|
| 1213 | 1212 |
return err |
| 1214 | 1213 |
} |
| 1215 | 1214 |
|
| 1216 |
- if copyData.Get("Resource") == "" {
|
|
| 1215 |
+ if cfg.Resource == "" {
|
|
| 1217 | 1216 |
return fmt.Errorf("Path cannot be empty")
|
| 1218 | 1217 |
} |
| 1219 | 1218 |
|
| 1220 |
- origResource := copyData.Get("Resource")
|
|
| 1219 |
+ res := cfg.Resource |
|
| 1221 | 1220 |
|
| 1222 |
- if copyData.Get("Resource")[0] == '/' {
|
|
| 1223 |
- copyData.Set("Resource", copyData.Get("Resource")[1:])
|
|
| 1221 |
+ if res[0] == '/' {
|
|
| 1222 |
+ res = res[1:] |
|
| 1224 | 1223 |
} |
| 1225 | 1224 |
|
| 1226 |
- job := eng.Job("container_copy", vars["name"], copyData.Get("Resource"))
|
|
| 1227 |
- job.Stdout.Add(w) |
|
| 1228 |
- w.Header().Set("Content-Type", "application/x-tar")
|
|
| 1229 |
- if err := job.Run(); err != nil {
|
|
| 1225 |
+ cont, err := getDaemon(eng).Get(vars["name"]) |
|
| 1226 |
+ if err != nil {
|
|
| 1230 | 1227 |
logrus.Errorf("%v", err)
|
| 1231 | 1228 |
if strings.Contains(strings.ToLower(err.Error()), "no such id") {
|
| 1232 | 1229 |
w.WriteHeader(http.StatusNotFound) |
| 1233 |
- } else if strings.Contains(err.Error(), "no such file or directory") {
|
|
| 1234 |
- return fmt.Errorf("Could not find the file %s in container %s", origResource, vars["name"])
|
|
| 1230 |
+ return nil |
|
| 1231 |
+ } |
|
| 1232 |
+ } |
|
| 1233 |
+ |
|
| 1234 |
+ data, err := cont.Copy(res) |
|
| 1235 |
+ if err != nil {
|
|
| 1236 |
+ logrus.Errorf("%v", err)
|
|
| 1237 |
+ if os.IsNotExist(err) {
|
|
| 1238 |
+ return fmt.Errorf("Could not find the file %s in container %s", cfg.Resource, vars["name"])
|
|
| 1235 | 1239 |
} |
| 1240 |
+ return err |
|
| 1236 | 1241 |
} |
| 1242 |
+ defer data.Close() |
|
| 1243 |
+ w.Header().Set("Content-Type", "application/x-tar")
|
|
| 1244 |
+ if _, err := io.Copy(w, data); err != nil {
|
|
| 1245 |
+ return err |
|
| 1246 |
+ } |
|
| 1247 |
+ |
|
| 1237 | 1248 |
return nil |
| 1238 | 1249 |
} |
| 1239 | 1250 |
|
| 101 | 106 |
deleted file mode 100644 |
| ... | ... |
@@ -1,35 +0,0 @@ |
| 1 |
-package daemon |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "io" |
|
| 6 |
- |
|
| 7 |
- "github.com/docker/docker/engine" |
|
| 8 |
-) |
|
| 9 |
- |
|
| 10 |
-func (daemon *Daemon) ContainerCopy(job *engine.Job) error {
|
|
| 11 |
- if len(job.Args) != 2 {
|
|
| 12 |
- return fmt.Errorf("Usage: %s CONTAINER RESOURCE\n", job.Name)
|
|
| 13 |
- } |
|
| 14 |
- |
|
| 15 |
- var ( |
|
| 16 |
- name = job.Args[0] |
|
| 17 |
- resource = job.Args[1] |
|
| 18 |
- ) |
|
| 19 |
- |
|
| 20 |
- container, err := daemon.Get(name) |
|
| 21 |
- if err != nil {
|
|
| 22 |
- return err |
|
| 23 |
- } |
|
| 24 |
- |
|
| 25 |
- data, err := container.Copy(resource) |
|
| 26 |
- if err != nil {
|
|
| 27 |
- return err |
|
| 28 |
- } |
|
| 29 |
- defer data.Close() |
|
| 30 |
- |
|
| 31 |
- if _, err := io.Copy(job.Stdout, data); err != nil {
|
|
| 32 |
- return err |
|
| 33 |
- } |
|
| 34 |
- return nil |
|
| 35 |
-} |
| ... | ... |
@@ -117,7 +117,6 @@ type Daemon struct {
|
| 117 | 117 |
func (daemon *Daemon) Install(eng *engine.Engine) error {
|
| 118 | 118 |
for name, method := range map[string]engine.Handler{
|
| 119 | 119 |
"commit": daemon.ContainerCommit, |
| 120 |
- "container_copy": daemon.ContainerCopy, |
|
| 121 | 120 |
"container_inspect": daemon.ContainerInspect, |
| 122 | 121 |
"container_stats": daemon.ContainerStats, |
| 123 | 122 |
"create": daemon.ContainerCreate, |