Skip to content

Commit

Permalink
Add support for dir transport to kpod save
Browse files Browse the repository at this point in the history
kpod save can now save images to directories using the
dir transport. Manifest conversion is also possible.
To save with the oci manifest type set --format to oci-dir
and to save with the v2s2(docker) manifest type, set --format
to docker-dir.
The layers can be compressed as well when saving to a directory
using the --compress flag.
Added functionality to kpod load to be able to load image from
a directory

Signed-off-by: umohnani8 <[email protected]>

Closes: #137
Approved by: rhatdan
  • Loading branch information
umohnani8 authored and rh-atomic-bot committed Dec 14, 2017
1 parent 1e7d880 commit d2ab53a
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 20 deletions.
12 changes: 8 additions & 4 deletions cmd/kpod/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,18 @@ func loadCmd(c *cli.Context) error {
src := libpod.DockerArchive + ":" + input
imgName, err := runtime.PullImage(src, options)
if err != nil {
src = libpod.OCIArchive + ":" + input
// generate full src name with specified image:tag
fullSrc := libpod.OCIArchive + ":" + input
if image != "" {
src = src + ":" + image
fullSrc = fullSrc + ":" + image
}
imgName, err = runtime.PullImage(src, options)
imgName, err = runtime.PullImage(fullSrc, options)
if err != nil {
return errors.Wrapf(err, "error pulling %q", src)
src = libpod.DirTransport + ":" + input
imgName, err = runtime.PullImage(src, options)
if err != nil {
return errors.Wrapf(err, "error pulling %q", src)
}
}
}
fmt.Println("Loaded image: ", imgName)
Expand Down
34 changes: 31 additions & 3 deletions cmd/kpod/save.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,27 @@ package main
import (
"io"
"os"
"strings"

"github.com/containers/image/manifest"
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
"github.com/projectatomic/libpod/libpod"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
)

const (
ociManifestDir = "oci-dir"
v2s2ManifestDir = "docker-dir"
)

var (
saveFlags = []cli.Flag{
cli.BoolFlag{
Name: "compress",
Usage: "compress tarball image layers when saving to a directory using the 'dir' transport. (default is same compression type as source)",
},
cli.StringFlag{
Name: "output, o",
Usage: "Write to a file, default is STDOUT",
Expand All @@ -23,7 +35,7 @@ var (
},
cli.StringFlag{
Name: "format",
Usage: "Save image to oci-archive",
Usage: "Save image to oci-archive, oci-dir (directory with oci manifest type), docker-dir (directory with v2s2 manifest type)",
},
}
saveDescription = `
Expand Down Expand Up @@ -56,6 +68,10 @@ func saveCmd(c *cli.Context) error {
}
defer runtime.Shutdown(false)

if c.IsSet("compress") && (c.String("format") != ociManifestDir && c.String("format") != v2s2ManifestDir && c.String("format") == "") {
return errors.Errorf("--compress can only be set when --format is either 'oci-dir' or 'docker-dir'")
}

var writer io.Writer
if !c.Bool("quiet") {
writer = os.Stdout
Expand All @@ -69,10 +85,16 @@ func saveCmd(c *cli.Context) error {
}
}

var dst string
var dst, manifestType string
switch c.String("format") {
case libpod.OCIArchive:
dst = libpod.OCIArchive + ":" + output
case "oci-dir":
dst = libpod.DirTransport + ":" + output
manifestType = imgspecv1.MediaTypeImageManifest
case "docker-dir":
dst = libpod.DirTransport + ":" + output
manifestType = manifest.DockerV2Schema2MediaType
case libpod.DockerArchive:
fallthrough
case "":
Expand All @@ -84,12 +106,18 @@ func saveCmd(c *cli.Context) error {
saveOpts := libpod.CopyOptions{
SignaturePolicyPath: "",
Writer: writer,
ManifestMIMEType: manifestType,
ForceCompress: c.Bool("compress"),
}

// only one image is supported for now
// future pull requests will fix this
for _, image := range args {
dest := dst + ":" + image
dest := dst
// need dest to be in the format transport:path:reference for the following transports
if strings.Contains(dst, libpod.OCIArchive) || strings.Contains(dst, libpod.DockerArchive) {
dest = dst + ":" + image
}
if err := runtime.PushImage(image, dest, saveOpts); err != nil {
if err2 := os.Remove(output); err2 != nil {
logrus.Errorf("error deleting %q: %v", output, err)
Expand Down
1 change: 1 addition & 0 deletions completions/bash/kpod
Original file line number Diff line number Diff line change
Expand Up @@ -1302,6 +1302,7 @@ _kpod_save() {
--format
"
local boolean_options="
--compress
--quiet -q
"
_complete_ "$options_with_args" "$boolean_options"
Expand Down
47 changes: 42 additions & 5 deletions docs/kpod-save.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ kpod-save - Save an image to docker-archive or oci-archive
[**--help**|**-h**]

## DESCRIPTION
**kpod save** saves an image to either **docker-archive** or **oci-archive**
on the local machine, default is **docker-archive**.
**kpod save** writes to STDOUT by default and can be redirected to a file using the **output** flag.
The **quiet** flag suppresses the output when set.
**kpod save** saves an image to either **docker-archive**, **oci-archive**, **oci-dir** (directory
with oci manifest type), or **docker-dir** (directory with v2s2 manifest type) on the local machine,
default is **docker-archive**. **kpod save** writes to STDOUT by default and can be redirected to a
file using the **output** flag. The **quiet** flag suppresses the output when set.

**kpod [GLOBAL OPTIONS]**

Expand All @@ -27,13 +27,20 @@ The **quiet** flag suppresses the output when set.

## OPTIONS

**--compress**

Compress tarball image layers when pushing to a directory using the 'dir' transport. (default is same compression type, compressed or uncompressed, as source)
Note: This flag can only be set when using the **dir** transport i.e --format=oci-dir or --format-docker-dir

**--output, -o**
Write to a file, default is STDOUT

**--format**
Save image to **oci-archive**
Save image to **oci-archive**, **oci-dir** (directory with oci manifest type), or **docker-dir** (directory with v2s2 manifest type)
```
--format oci-archive
--format oci-dir
--format docker-dir
```

**--quiet, -q**
Expand All @@ -53,6 +60,36 @@ Suppress the output
# kpod save -o oci-alpine.tar --format oci-archive alpine
```

```
# kpod save --compress --format oci-dir -o alp-dir alpine
Getting image source signatures
Copying blob sha256:2fdfe1cd78c20d05774f0919be19bc1a3e4729bce219968e4188e7e0f1af679d
1.97 MB / 1.97 MB [========================================================] 0s
Copying config sha256:501d1a8f0487e93128df34ea349795bc324d5e0c0d5112e08386a9dfaff620be
584 B / 584 B [============================================================] 0s
Writing manifest to image destination
Storing signatures
```

```
# kpod save --format docker-dir -o ubuntu-dir ubuntu
Getting image source signatures
Copying blob sha256:660c48dd555dcbfdfe19c80a30f557ac57a15f595250e67bfad1e5663c1725bb
45.55 MB / 45.55 MB [======================================================] 8s
Copying blob sha256:4c7380416e7816a5ab1f840482c9c3ca8de58c6f3ee7f95e55ad299abbfe599f
846 B / 846 B [============================================================] 0s
Copying blob sha256:421e436b5f80d876128b74139531693be9b4e59e4f1081c9a3c379c95094e375
620 B / 620 B [============================================================] 0s
Copying blob sha256:e4ce6c3651b3a090bb43688f512f687ea6e3e533132bcbc4a83fb97e7046cea3
849 B / 849 B [============================================================] 0s
Copying blob sha256:be588e74bd348ce48bb7161350f4b9d783c331f37a853a80b0b4abc0a33c569e
169 B / 169 B [============================================================] 0s
Copying config sha256:20c44cd7596ff4807aef84273c99588d22749e2a7e15a7545ac96347baa65eda
3.53 KB / 3.53 KB [========================================================] 0s
Writing manifest to image destination
Storing signatures
```

## SEE ALSO
kpod(1), kpod-load(1), crio(8), crio.conf(5)

Expand Down
31 changes: 23 additions & 8 deletions test/kpod_load.bats
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ function teardown() {
cleanup_test
}
@test "kpod load input flag" {
run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} save -o alpine.tar $IMAGE
run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} save -o alpine.tar $ALPINE
echo "$output"
[ "$status" -eq 0 ]
run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} rmi $IMAGE
run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} rmi $ALPINE
echo "$output"
[ "$status" -eq 0 ]
run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} load -i alpine.tar
Expand All @@ -23,9 +23,9 @@ function teardown() {
}

@test "kpod load oci-archive image" {
run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} save -o alpine.tar --format oci-archive $IMAGE
run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} save -o alpine.tar --format oci-archive $ALPINE
[ "$status" -eq 0 ]
run bash -c ${KPOD_BINARY} $KPOD_OPTIONS rmi $IMAGE
run bash -c ${KPOD_BINARY} $KPOD_OPTIONS rmi $ALPINE
[ "$status" -eq 0 ]
run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} load -i alpine.tar
echo "$output"
Expand All @@ -34,9 +34,9 @@ function teardown() {
}

@test "kpod load oci-archive image with signature-policy" {
run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} save -o alpine.tar --format oci-archive $IMAGE
run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} save -o alpine.tar --format oci-archive $ALPINE
[ "$status" -eq 0 ]
run bash -c ${KPOD_BINARY} $KPOD_OPTIONS rmi $IMAGE
run bash -c ${KPOD_BINARY} $KPOD_OPTIONS rmi $ALPINE
[ "$status" -eq 0 ]
cp /etc/containers/policy.json /tmp
run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} load --signature-policy /tmp/policy.json -i alpine.tar
Expand All @@ -47,10 +47,10 @@ function teardown() {
}

@test "kpod load using quiet flag" {
run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} save -o alpine.tar $IMAGE
run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} save -o alpine.tar $ALPINE
echo "$output"
[ "$status" -eq 0 ]
run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} rmi $IMAGE
run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} rmi $ALPINE
echo "$output"
[ "$status" -eq 0 ]
run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} load -q -i alpine.tar
Expand All @@ -59,6 +59,21 @@ function teardown() {
rm -f alpine.tar
}

@test "kpod load directory" {
run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} save --format oci-dir -o alp-dir $ALPINE
echo "$output"
[ "$status" -eq 0 ]
run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} rmi $ALPINE
echo "$output"
[ "$status" -eq 0 ]
run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} load -i alp-dir
echo "$output"
[ "$status" -eq 0 ]
run bash -c ${KPOD_BINARY} ${KPOD_OPTIONS} rmi alp-dir
echo "$output"
[ "$status" -eq 0 ]
}

@test "kpod load non-existent file" {
run ${KPOD_BINARY} ${KPOD_OPTIONS} load -i alpine.tar
echo "$output"
Expand Down
14 changes: 14 additions & 0 deletions test/kpod_save.bats
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,17 @@ function setup() {
echo "$output"
[ "$status" -ne 0 ]
}

@test "kpod save to directory wit oci format" {
run bash -c "${KPOD_BINARY} ${KPOD_OPTIONS} save --format oci-dir -o alp-dir $ALPINE"
echo "$output"
[ "$status" -eq 0 ]
rm -rf alp-dir
}

@test "kpod save to directory wit v2s2 (docker) format" {
run bash -c "${KPOD_BINARY} ${KPOD_OPTIONS} save --format docker-dir -o alp-dir $ALPINE"
echo "$output"
[ "$status" -eq 0 ]
rm -rf alp-dir
}

0 comments on commit d2ab53a

Please sign in to comment.