Merge pull request #737 from umohnani8/kpod_export

Add 'kpod export' command
This commit is contained in:
Mrunal Patel 2017-08-11 10:54:34 -07:00 committed by GitHub
commit fb2ee59225
5 changed files with 196 additions and 0 deletions

103
cmd/kpod/export.go Normal file
View file

@ -0,0 +1,103 @@
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]
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
}

View file

@ -22,6 +22,7 @@ func main() {
app.Version = Version
app.Commands = []cli.Command{
exportCommand,
historyCommand,
imagesCommand,
infoCommand,

View file

@ -182,6 +182,15 @@ _kpod_save() {
_complete_ "$options_with_args" "$boolean_options"
}
_kpod_export() {
local options_with_args="
--output -o
"
local boolean_options="
"
_complete_ "$options_with_args" "$boolean_options"
}
_complete_() {
local options_with_args=$1
local boolean_options="$2 -h --help"

48
docs/kpod-export.1.md Normal file
View file

@ -0,0 +1,48 @@
% kpod(1) kpod-export - Simple tool to export a container's filesystem as a tarball
% Urvashi Mohnani
# kpod-export "1" "July 2017" "kpod"
## NAME
kpod-export - Export container's filesystem contents as a tar archive
## SYNOPSIS
**kpod export**
**CONTAINER**
[**--help**|**-h**]
## DESCRIPTION
**kpod export** exports the filesystem of a container and saves it as a tarball
on the local machine. **kpod export** writes to STDOUT by default and can be
redirected to a file using the **output flag**.
**kpod [GLOBAL OPTIONS]**
**kpod export [GLOBAL OPTIONS]**
**kpod export [OPTIONS] CONTAINER [GLOBAL OPTIONS]**
## OPTIONS
**--output, -o**
Write to a file, default is STDOUT
## GLOBAL OPTIONS
**--help, -h**
Print usage statement
## EXAMPLES
```
# kpod export -o redis-container.tar 883504668ec465463bc0fe7e63d53154ac3b696ea8d7b233748918664ea90e57
```
```
# kpod export > redis-container.tar 883504668ec465463bc0fe7e63d53154ac3b696ea8d7b233748918664ea90e57
```
## SEE ALSO
kpod(1), kpod-import(1), crio(8), crio.conf(5)
## HISTORY
August 2017, Originally compiled by Urvashi Mohnani <umohnani@redhat.com>

35
test/kpod_export.bats Normal file
View file

@ -0,0 +1,35 @@
#!/usr/bin/env bats
load helpers
IMAGE="redis:alpine"
ROOT="$TESTDIR/crio"
RUNROOT="$TESTDIR/crio-run"
KPOD_OPTIONS="--root $ROOT --runroot $RUNROOT ${STORAGE_OPTS}"
@test "kpod export output flag" {
start_crio
[ "$status" -eq 0 ]
run crioctl pod run --config "$TESTDATA"/sandbox_config.json
echo "$output"
[ "$status" -eq 0 ]
pod_id="$output"
run crioctl image pull "$IMAGE"
[ "$status" -eq 0 ]
run crioctl ctr create --config "$TESTDATA"/container_config.json --pod "$pod_id"
echo "$output"
[ "$status" -eq 0 ]
ctr_id="$output"
run ${KPOD_BINARY} ${KPOD_OPTIONS} export -o container.tar "$ctr_id"
echo "$output"
[ "$status" -eq 0 ]
cleanup_ctrs
[ "$status" -eq 0 ]
cleanup_pods
[ "$status" -eq 0 ]
stop_crio
[ "$status" -eq 0 ]
rm -f container.tar
[ "$status" -eq 0 ]
}