Signed-off-by: Vincent Demeester <vincent@sbr.pm>
| ... | ... |
@@ -10,7 +10,6 @@ func (cli *DockerCli) Command(name string) func(...string) error {
|
| 10 | 10 |
"diff": cli.CmdDiff, |
| 11 | 11 |
"events": cli.CmdEvents, |
| 12 | 12 |
"exec": cli.CmdExec, |
| 13 |
- "export": cli.CmdExport, |
|
| 14 | 13 |
"history": cli.CmdHistory, |
| 15 | 14 |
"images": cli.CmdImages, |
| 16 | 15 |
"import": cli.CmdImport, |
| 17 | 16 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,59 @@ |
| 0 |
+package container |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "errors" |
|
| 4 |
+ "io" |
|
| 5 |
+ |
|
| 6 |
+ "golang.org/x/net/context" |
|
| 7 |
+ |
|
| 8 |
+ "github.com/docker/docker/api/client" |
|
| 9 |
+ "github.com/docker/docker/cli" |
|
| 10 |
+ "github.com/spf13/cobra" |
|
| 11 |
+) |
|
| 12 |
+ |
|
| 13 |
+type exportOptions struct {
|
|
| 14 |
+ container string |
|
| 15 |
+ output string |
|
| 16 |
+} |
|
| 17 |
+ |
|
| 18 |
+// NewExportCommand creates a new `docker export` command |
|
| 19 |
+func NewExportCommand(dockerCli *client.DockerCli) *cobra.Command {
|
|
| 20 |
+ var opts exportOptions |
|
| 21 |
+ |
|
| 22 |
+ cmd := &cobra.Command{
|
|
| 23 |
+ Use: "export [OPTIONS] CONTAINER", |
|
| 24 |
+ Short: "Export a container's filesystem as a tar archive", |
|
| 25 |
+ Args: cli.ExactArgs(1), |
|
| 26 |
+ RunE: func(cmd *cobra.Command, args []string) error {
|
|
| 27 |
+ opts.container = args[0] |
|
| 28 |
+ return runExport(dockerCli, opts) |
|
| 29 |
+ }, |
|
| 30 |
+ } |
|
| 31 |
+ |
|
| 32 |
+ flags := cmd.Flags() |
|
| 33 |
+ |
|
| 34 |
+ flags.StringVarP(&opts.output, "output", "o", "", "Write to a file, instead of STDOUT") |
|
| 35 |
+ |
|
| 36 |
+ return cmd |
|
| 37 |
+} |
|
| 38 |
+ |
|
| 39 |
+func runExport(dockerCli *client.DockerCli, opts exportOptions) error {
|
|
| 40 |
+ if opts.output == "" && dockerCli.IsTerminalOut() {
|
|
| 41 |
+ return errors.New("Cowardly refusing to save to a terminal. Use the -o flag or redirect.")
|
|
| 42 |
+ } |
|
| 43 |
+ |
|
| 44 |
+ clnt := dockerCli.Client() |
|
| 45 |
+ |
|
| 46 |
+ responseBody, err := clnt.ContainerExport(context.Background(), opts.container) |
|
| 47 |
+ if err != nil {
|
|
| 48 |
+ return err |
|
| 49 |
+ } |
|
| 50 |
+ defer responseBody.Close() |
|
| 51 |
+ |
|
| 52 |
+ if opts.output == "" {
|
|
| 53 |
+ _, err := io.Copy(dockerCli.Out(), responseBody) |
|
| 54 |
+ return err |
|
| 55 |
+ } |
|
| 56 |
+ |
|
| 57 |
+ return client.CopyToFile(opts.output, responseBody) |
|
| 58 |
+} |
| 0 | 59 |
deleted file mode 100644 |
| ... | ... |
@@ -1,41 +0,0 @@ |
| 1 |
-package client |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "errors" |
|
| 5 |
- "io" |
|
| 6 |
- |
|
| 7 |
- "golang.org/x/net/context" |
|
| 8 |
- |
|
| 9 |
- Cli "github.com/docker/docker/cli" |
|
| 10 |
- flag "github.com/docker/docker/pkg/mflag" |
|
| 11 |
-) |
|
| 12 |
- |
|
| 13 |
-// CmdExport exports a filesystem as a tar archive. |
|
| 14 |
-// |
|
| 15 |
-// The tar archive is streamed to STDOUT by default or written to a file. |
|
| 16 |
-// |
|
| 17 |
-// Usage: docker export [OPTIONS] CONTAINER |
|
| 18 |
-func (cli *DockerCli) CmdExport(args ...string) error {
|
|
| 19 |
- cmd := Cli.Subcmd("export", []string{"CONTAINER"}, Cli.DockerCommands["export"].Description, true)
|
|
| 20 |
- outfile := cmd.String([]string{"o", "-output"}, "", "Write to a file, instead of STDOUT")
|
|
| 21 |
- cmd.Require(flag.Exact, 1) |
|
| 22 |
- |
|
| 23 |
- cmd.ParseFlags(args, true) |
|
| 24 |
- |
|
| 25 |
- if *outfile == "" && cli.isTerminalOut {
|
|
| 26 |
- return errors.New("Cowardly refusing to save to a terminal. Use the -o flag or redirect.")
|
|
| 27 |
- } |
|
| 28 |
- |
|
| 29 |
- responseBody, err := cli.client.ContainerExport(context.Background(), cmd.Arg(0)) |
|
| 30 |
- if err != nil {
|
|
| 31 |
- return err |
|
| 32 |
- } |
|
| 33 |
- defer responseBody.Close() |
|
| 34 |
- |
|
| 35 |
- if *outfile == "" {
|
|
| 36 |
- _, err := io.Copy(cli.out, responseBody) |
|
| 37 |
- return err |
|
| 38 |
- } |
|
| 39 |
- |
|
| 40 |
- return copyToFile(*outfile, responseBody) |
|
| 41 |
-} |
| ... | ... |
@@ -162,7 +162,8 @@ func (cli *DockerCli) GetTtySize() (int, int) {
|
| 162 | 162 |
return int(ws.Height), int(ws.Width) |
| 163 | 163 |
} |
| 164 | 164 |
|
| 165 |
-func copyToFile(outfile string, r io.Reader) error {
|
|
| 165 |
+// CopyToFile writes the content of the reader to the specifed file |
|
| 166 |
+func CopyToFile(outfile string, r io.Reader) error {
|
|
| 166 | 167 |
tmpFile, err := ioutil.TempFile(filepath.Dir(outfile), ".docker_temp_") |
| 167 | 168 |
if err != nil {
|
| 168 | 169 |
return err |
| ... | ... |
@@ -34,6 +34,7 @@ func NewCobraAdaptor(clientFlags *cliflags.ClientFlags) CobraAdaptor {
|
| 34 | 34 |
rootCmd.SetOutput(stdout) |
| 35 | 35 |
rootCmd.AddCommand( |
| 36 | 36 |
container.NewCreateCommand(dockerCli), |
| 37 |
+ container.NewExportCommand(dockerCli), |
|
| 37 | 38 |
container.NewRunCommand(dockerCli), |
| 38 | 39 |
image.NewSearchCommand(dockerCli), |
| 39 | 40 |
volume.NewVolumeCommand(dockerCli), |
| ... | ... |
@@ -15,7 +15,6 @@ var DockerCommandUsage = []Command{
|
| 15 | 15 |
{"diff", "Inspect changes on a container's filesystem"},
|
| 16 | 16 |
{"events", "Get real time events from the server"},
|
| 17 | 17 |
{"exec", "Run a command in a running container"},
|
| 18 |
- {"export", "Export a container's filesystem as a tar archive"},
|
|
| 19 | 18 |
{"history", "Show the history of an image"},
|
| 20 | 19 |
{"images", "List images"},
|
| 21 | 20 |
{"import", "Import the contents from a tarball to create a filesystem image"},
|