2017-07-14 14:31:02 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2017-09-09 11:14:40 +00:00
|
|
|
"io"
|
2017-07-14 14:31:02 +00:00
|
|
|
"os"
|
|
|
|
|
2017-09-09 11:14:40 +00:00
|
|
|
"github.com/kubernetes-incubator/cri-o/libpod"
|
2017-07-14 14:31:02 +00:00
|
|
|
"github.com/pkg/errors"
|
2017-08-05 11:40:46 +00:00
|
|
|
"github.com/sirupsen/logrus"
|
2017-07-14 14:31:02 +00:00
|
|
|
"github.com/urfave/cli"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
saveFlags = []cli.Flag{
|
|
|
|
cli.StringFlag{
|
|
|
|
Name: "output, o",
|
|
|
|
Usage: "Write to a file, default is STDOUT",
|
|
|
|
Value: "/dev/stdout",
|
|
|
|
},
|
|
|
|
cli.BoolFlag{
|
|
|
|
Name: "quiet, q",
|
|
|
|
Usage: "Suppress the output",
|
|
|
|
},
|
2017-08-02 20:32:44 +00:00
|
|
|
cli.StringFlag{
|
|
|
|
Name: "format",
|
|
|
|
Usage: "Save image to oci-archive",
|
|
|
|
},
|
2017-07-14 14:31:02 +00:00
|
|
|
}
|
2017-08-02 20:32:44 +00:00
|
|
|
saveDescription = `
|
|
|
|
Save an image to docker-archive or oci-archive on the local machine.
|
|
|
|
Default is docker-archive`
|
|
|
|
|
|
|
|
saveCommand = cli.Command{
|
2017-07-14 14:31:02 +00:00
|
|
|
Name: "save",
|
|
|
|
Usage: "Save image to an archive",
|
|
|
|
Description: saveDescription,
|
|
|
|
Flags: saveFlags,
|
|
|
|
Action: saveCmd,
|
|
|
|
ArgsUsage: "",
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
// saveCmd saves the image to either docker-archive or oci
|
|
|
|
func saveCmd(c *cli.Context) error {
|
|
|
|
args := c.Args()
|
|
|
|
if len(args) == 0 {
|
|
|
|
return errors.Errorf("need at least 1 argument")
|
|
|
|
}
|
2017-09-28 18:44:48 +00:00
|
|
|
if err := validateFlags(c, saveFlags); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2017-07-14 14:31:02 +00:00
|
|
|
|
2017-09-09 11:14:40 +00:00
|
|
|
runtime, err := getRuntime(c)
|
2017-07-28 19:51:11 +00:00
|
|
|
if err != nil {
|
2017-09-09 11:14:40 +00:00
|
|
|
return errors.Wrapf(err, "could not create runtime")
|
2017-07-28 19:51:11 +00:00
|
|
|
}
|
2017-09-09 11:14:40 +00:00
|
|
|
defer runtime.Shutdown(false)
|
|
|
|
|
|
|
|
var writer io.Writer
|
|
|
|
if !c.Bool("quiet") {
|
|
|
|
writer = os.Stdout
|
2017-07-14 14:31:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
output := c.String("output")
|
|
|
|
if output == "/dev/stdout" {
|
|
|
|
fi := os.Stdout
|
|
|
|
if logrus.IsTerminal(fi) {
|
|
|
|
return errors.Errorf("refusing to save to terminal. Use -o flag or redirect")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-02 20:32:44 +00:00
|
|
|
var dst string
|
2017-09-09 11:14:40 +00:00
|
|
|
switch c.String("format") {
|
2017-09-21 19:21:56 +00:00
|
|
|
case libpod.OCIArchive:
|
|
|
|
dst = libpod.OCIArchive + ":" + output
|
|
|
|
case libpod.DockerArchive:
|
2017-08-02 20:32:44 +00:00
|
|
|
fallthrough
|
|
|
|
case "":
|
2017-09-21 19:21:56 +00:00
|
|
|
dst = libpod.DockerArchive + ":" + output
|
2017-08-02 20:32:44 +00:00
|
|
|
default:
|
2017-09-09 11:14:40 +00:00
|
|
|
return errors.Errorf("unknown format option %q", c.String("format"))
|
2017-08-02 20:32:44 +00:00
|
|
|
}
|
2017-07-14 14:31:02 +00:00
|
|
|
|
2017-09-09 11:14:40 +00:00
|
|
|
saveOpts := libpod.CopyOptions{
|
2017-07-14 14:31:02 +00:00
|
|
|
SignaturePolicyPath: "",
|
2017-10-13 21:04:57 +00:00
|
|
|
Writer: writer,
|
2017-07-14 14:31:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// only one image is supported for now
|
|
|
|
// future pull requests will fix this
|
2017-09-09 11:14:40 +00:00
|
|
|
for _, image := range args {
|
2017-07-14 14:31:02 +00:00
|
|
|
dest := dst + ":" + image
|
2017-10-13 21:04:57 +00:00
|
|
|
if err := runtime.PushImage(image, dest, saveOpts); err != nil {
|
2017-07-14 14:31:02 +00:00
|
|
|
return errors.Wrapf(err, "unable to save %q", image)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|