aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/kpod/load.go12
-rw-r--r--cmd/kpod/save.go34
-rw-r--r--completions/bash/kpod1
-rw-r--r--docs/kpod-save.1.md47
-rw-r--r--test/kpod_load.bats31
-rw-r--r--test/kpod_save.bats14
6 files changed, 119 insertions, 20 deletions
diff --git a/cmd/kpod/load.go b/cmd/kpod/load.go
index d29da0c06..5ae75a7a2 100644
--- a/cmd/kpod/load.go
+++ b/cmd/kpod/load.go
@@ -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)
diff --git a/cmd/kpod/save.go b/cmd/kpod/save.go
index 0f5fcfa4d..85a8c7930 100644
--- a/cmd/kpod/save.go
+++ b/cmd/kpod/save.go
@@ -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",
@@ -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 = `
@@ -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
@@ -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 "":
@@ -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)
diff --git a/completions/bash/kpod b/completions/bash/kpod
index 417e9468d..3e291c526 100644
--- a/completions/bash/kpod
+++ b/completions/bash/kpod
@@ -1302,6 +1302,7 @@ _kpod_save() {
--format
"
local boolean_options="
+ --compress
--quiet -q
"
_complete_ "$options_with_args" "$boolean_options"
diff --git a/docs/kpod-save.1.md b/docs/kpod-save.1.md
index dbcf96d04..ece4bea5e 100644
--- a/docs/kpod-save.1.md
+++ b/docs/kpod-save.1.md
@@ -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]**
@@ -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**
@@ -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)
diff --git a/test/kpod_load.bats b/test/kpod_load.bats
index 7404cb76c..abbe8ee5d 100644
--- a/test/kpod_load.bats
+++ b/test/kpod_load.bats
@@ -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
@@ -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"
@@ -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
@@ -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
@@ -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"
diff --git a/test/kpod_save.bats b/test/kpod_save.bats
index 6da3279a2..56f23db91 100644
--- a/test/kpod_save.bats
+++ b/test/kpod_save.bats
@@ -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
+}