Skip to content

Commit fb2ee59

Browse files
author
Mrunal Patel
authored
Merge pull request cri-o#737 from umohnani8/kpod_export
Add 'kpod export' command
2 parents 5a3c168 + be8ba17 commit fb2ee59

File tree

5 files changed

+196
-0
lines changed

5 files changed

+196
-0
lines changed

cmd/kpod/export.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package main
2+
3+
import (
4+
"io"
5+
"os"
6+
7+
"fmt"
8+
9+
"github.com/containers/storage"
10+
"github.com/containers/storage/pkg/archive"
11+
"github.com/pkg/errors"
12+
"github.com/sirupsen/logrus"
13+
"github.com/urfave/cli"
14+
)
15+
16+
type exportOptions struct {
17+
output string
18+
container string
19+
}
20+
21+
var (
22+
exportFlags = []cli.Flag{
23+
cli.StringFlag{
24+
Name: "output, o",
25+
Usage: "Write to a file, default is STDOUT",
26+
Value: "/dev/stdout",
27+
},
28+
}
29+
exportDescription = "Exports container's filesystem contents as a tar archive" +
30+
" and saves it on the local machine."
31+
exportCommand = cli.Command{
32+
Name: "export",
33+
Usage: "Export container's filesystem contents as a tar archive",
34+
Description: exportDescription,
35+
Flags: exportFlags,
36+
Action: exportCmd,
37+
ArgsUsage: "CONTAINER",
38+
}
39+
)
40+
41+
// exportCmd saves a container to a tarball on disk
42+
func exportCmd(c *cli.Context) error {
43+
args := c.Args()
44+
if len(args) == 0 {
45+
return errors.Errorf("container id must be specified")
46+
}
47+
if len(args) > 1 {
48+
return errors.Errorf("too many arguments given, need 1 at most.")
49+
}
50+
container := args[0]
51+
52+
config, err := getConfig(c)
53+
if err != nil {
54+
return errors.Wrapf(err, "could not get config")
55+
}
56+
store, err := getStore(config)
57+
if err != nil {
58+
return err
59+
}
60+
61+
output := c.String("output")
62+
if output == "/dev/stdout" {
63+
file := os.Stdout
64+
if logrus.IsTerminal(file) {
65+
return errors.Errorf("refusing to export to terminal. Use -o flag or redirect")
66+
}
67+
}
68+
69+
opts := exportOptions{
70+
output: output,
71+
container: container,
72+
}
73+
74+
return exportContainer(store, opts)
75+
}
76+
77+
// exportContainer exports the contents of a container and saves it as
78+
// a tarball on disk
79+
func exportContainer(store storage.Store, opts exportOptions) error {
80+
mountPoint, err := store.Mount(opts.container, "")
81+
if err != nil {
82+
return errors.Wrapf(err, "error finding container %q", opts.container)
83+
}
84+
defer func() {
85+
if err := store.Unmount(opts.container); err != nil {
86+
fmt.Printf("error unmounting container %q: %v\n", opts.container, err)
87+
}
88+
}()
89+
90+
input, err := archive.Tar(mountPoint, archive.Uncompressed)
91+
if err != nil {
92+
return errors.Wrapf(err, "error reading container directory %q", opts.container)
93+
}
94+
95+
outFile, err := os.Create(opts.output)
96+
if err != nil {
97+
return errors.Wrapf(err, "error creating file %q", opts.output)
98+
}
99+
defer outFile.Close()
100+
101+
_, err = io.Copy(outFile, input)
102+
return err
103+
}

cmd/kpod/main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ func main() {
2222
app.Version = Version
2323

2424
app.Commands = []cli.Command{
25+
exportCommand,
2526
historyCommand,
2627
imagesCommand,
2728
infoCommand,

completions/bash/kpod

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,15 @@ _kpod_save() {
182182
_complete_ "$options_with_args" "$boolean_options"
183183
}
184184

185+
_kpod_export() {
186+
local options_with_args="
187+
--output -o
188+
"
189+
local boolean_options="
190+
"
191+
_complete_ "$options_with_args" "$boolean_options"
192+
}
193+
185194
_complete_() {
186195
local options_with_args=$1
187196
local boolean_options="$2 -h --help"

docs/kpod-export.1.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
% kpod(1) kpod-export - Simple tool to export a container's filesystem as a tarball
2+
% Urvashi Mohnani
3+
# kpod-export "1" "July 2017" "kpod"
4+
5+
## NAME
6+
kpod-export - Export container's filesystem contents as a tar archive
7+
8+
## SYNOPSIS
9+
**kpod export**
10+
**CONTAINER**
11+
[**--help**|**-h**]
12+
13+
## DESCRIPTION
14+
**kpod export** exports the filesystem of a container and saves it as a tarball
15+
on the local machine. **kpod export** writes to STDOUT by default and can be
16+
redirected to a file using the **output flag**.
17+
18+
**kpod [GLOBAL OPTIONS]**
19+
20+
**kpod export [GLOBAL OPTIONS]**
21+
22+
**kpod export [OPTIONS] CONTAINER [GLOBAL OPTIONS]**
23+
24+
## OPTIONS
25+
26+
**--output, -o**
27+
Write to a file, default is STDOUT
28+
29+
## GLOBAL OPTIONS
30+
31+
**--help, -h**
32+
Print usage statement
33+
34+
## EXAMPLES
35+
36+
```
37+
# kpod export -o redis-container.tar 883504668ec465463bc0fe7e63d53154ac3b696ea8d7b233748918664ea90e57
38+
```
39+
40+
```
41+
# kpod export > redis-container.tar 883504668ec465463bc0fe7e63d53154ac3b696ea8d7b233748918664ea90e57
42+
```
43+
44+
## SEE ALSO
45+
kpod(1), kpod-import(1), crio(8), crio.conf(5)
46+
47+
## HISTORY
48+
August 2017, Originally compiled by Urvashi Mohnani <[email protected]>

test/kpod_export.bats

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/usr/bin/env bats
2+
3+
load helpers
4+
5+
IMAGE="redis:alpine"
6+
ROOT="$TESTDIR/crio"
7+
RUNROOT="$TESTDIR/crio-run"
8+
KPOD_OPTIONS="--root $ROOT --runroot $RUNROOT ${STORAGE_OPTS}"
9+
10+
11+
@test "kpod export output flag" {
12+
start_crio
13+
[ "$status" -eq 0 ]
14+
run crioctl pod run --config "$TESTDATA"/sandbox_config.json
15+
echo "$output"
16+
[ "$status" -eq 0 ]
17+
pod_id="$output"
18+
run crioctl image pull "$IMAGE"
19+
[ "$status" -eq 0 ]
20+
run crioctl ctr create --config "$TESTDATA"/container_config.json --pod "$pod_id"
21+
echo "$output"
22+
[ "$status" -eq 0 ]
23+
ctr_id="$output"
24+
run ${KPOD_BINARY} ${KPOD_OPTIONS} export -o container.tar "$ctr_id"
25+
echo "$output"
26+
[ "$status" -eq 0 ]
27+
cleanup_ctrs
28+
[ "$status" -eq 0 ]
29+
cleanup_pods
30+
[ "$status" -eq 0 ]
31+
stop_crio
32+
[ "$status" -eq 0 ]
33+
rm -f container.tar
34+
[ "$status" -eq 0 ]
35+
}

0 commit comments

Comments
 (0)