From a031b83a09a8628435317a03f199cdc18b78262f Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Wed, 1 Nov 2017 11:24:59 -0400 Subject: Initial checkin from CRI-O repo Signed-off-by: Matthew Heon --- cmd/kpod/export.go | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 cmd/kpod/export.go (limited to 'cmd/kpod/export.go') diff --git a/cmd/kpod/export.go b/cmd/kpod/export.go new file mode 100644 index 000000000..94f05ce10 --- /dev/null +++ b/cmd/kpod/export.go @@ -0,0 +1,106 @@ +package main + +import ( + "io" + "os" + + "fmt" + + "github.com/containers/storage" + "github.com/containers/storage/pkg/archive" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" + "github.com/urfave/cli" +) + +type exportOptions struct { + output string + container string +} + +var ( + exportFlags = []cli.Flag{ + cli.StringFlag{ + Name: "output, o", + Usage: "Write to a file, default is STDOUT", + Value: "/dev/stdout", + }, + } + exportDescription = "Exports container's filesystem contents as a tar archive" + + " and saves it on the local machine." + exportCommand = cli.Command{ + Name: "export", + Usage: "Export container's filesystem contents as a tar archive", + Description: exportDescription, + Flags: exportFlags, + Action: exportCmd, + ArgsUsage: "CONTAINER", + } +) + +// exportCmd saves a container to a tarball on disk +func exportCmd(c *cli.Context) error { + args := c.Args() + if len(args) == 0 { + return errors.Errorf("container id must be specified") + } + if len(args) > 1 { + return errors.Errorf("too many arguments given, need 1 at most.") + } + container := args[0] + if err := validateFlags(c, exportFlags); err != nil { + return err + } + + config, err := getConfig(c) + if err != nil { + return errors.Wrapf(err, "could not get config") + } + store, err := getStore(config) + if err != nil { + return err + } + + output := c.String("output") + if output == "/dev/stdout" { + file := os.Stdout + if logrus.IsTerminal(file) { + return errors.Errorf("refusing to export to terminal. Use -o flag or redirect") + } + } + + opts := exportOptions{ + output: output, + container: container, + } + + return exportContainer(store, opts) +} + +// exportContainer exports the contents of a container and saves it as +// a tarball on disk +func exportContainer(store storage.Store, opts exportOptions) error { + mountPoint, err := store.Mount(opts.container, "") + if err != nil { + return errors.Wrapf(err, "error finding container %q", opts.container) + } + defer func() { + if err := store.Unmount(opts.container); err != nil { + fmt.Printf("error unmounting container %q: %v\n", opts.container, err) + } + }() + + input, err := archive.Tar(mountPoint, archive.Uncompressed) + if err != nil { + return errors.Wrapf(err, "error reading container directory %q", opts.container) + } + + outFile, err := os.Create(opts.output) + if err != nil { + return errors.Wrapf(err, "error creating file %q", opts.output) + } + defer outFile.Close() + + _, err = io.Copy(outFile, input) + return err +} -- cgit v1.2.3-54-g00ecf