diff options
author | baude <bbaude@redhat.com> | 2019-02-19 10:08:43 -0600 |
---|---|---|
committer | baude <bbaude@redhat.com> | 2019-02-20 12:58:05 -0600 |
commit | 711ac9305185e645f2970d09ff76c2761132202a (patch) | |
tree | e8c7c83be19cc075446b20ea49a88c529dda69f1 /libpod/adapter | |
parent | 4de0bf9c74624de8a2cab1e5cbebc0beaa67339a (diff) | |
download | podman-711ac9305185e645f2970d09ff76c2761132202a.tar.gz podman-711ac9305185e645f2970d09ff76c2761132202a.tar.bz2 podman-711ac9305185e645f2970d09ff76c2761132202a.zip |
podman-remote save [image]
Add the ability to save an image from the remote-host to the
remote-client.
Signed-off-by: baude <bbaude@redhat.com>
Diffstat (limited to 'libpod/adapter')
-rw-r--r-- | libpod/adapter/runtime.go | 12 | ||||
-rw-r--r-- | libpod/adapter/runtime_remote.go | 95 |
2 files changed, 90 insertions, 17 deletions
diff --git a/libpod/adapter/runtime.go b/libpod/adapter/runtime.go index 02ef9af07..b12f63cdc 100644 --- a/libpod/adapter/runtime.go +++ b/libpod/adapter/runtime.go @@ -310,3 +310,15 @@ func (r *LocalRuntime) Build(ctx context.Context, c *cliconfig.BuildValues, opti func (r *LocalRuntime) PruneVolumes(ctx context.Context) ([]string, []error) { return r.Runtime.PruneVolumes(ctx) } + +// SaveImage is a wrapper function for saving an image to the local filesystem +func (r *LocalRuntime) SaveImage(ctx context.Context, c *cliconfig.SaveValues) error { + source := c.InputArgs[0] + additionalTags := c.InputArgs[1:] + + newImage, err := r.Runtime.ImageRuntime().NewFromLocal(source) + if err != nil { + return err + } + return newImage.Save(ctx, source, c.Format, c.Output, additionalTags, c.Quiet, c.Compress) +} diff --git a/libpod/adapter/runtime_remote.go b/libpod/adapter/runtime_remote.go index b1d4d4d25..a79f93079 100644 --- a/libpod/adapter/runtime_remote.go +++ b/libpod/adapter/runtime_remote.go @@ -20,6 +20,7 @@ import ( "github.com/containers/libpod/cmd/podman/varlink" "github.com/containers/libpod/libpod" "github.com/containers/libpod/libpod/image" + "github.com/containers/libpod/utils" "github.com/containers/storage/pkg/archive" "github.com/opencontainers/go-digest" "github.com/pkg/errors" @@ -385,8 +386,11 @@ func (r *LocalRuntime) Export(name string, path string) error { if err != nil { return err } + return r.GetFileFromRemoteHost(tempPath, path, true) +} - outputFile, err := os.Create(path) +func (r *LocalRuntime) GetFileFromRemoteHost(remoteFilePath, outputPath string, delete bool) error { + outputFile, err := os.Create(outputPath) if err != nil { return err } @@ -395,7 +399,7 @@ func (r *LocalRuntime) Export(name string, path string) error { writer := bufio.NewWriter(outputFile) defer writer.Flush() - reply, err := iopodman.ReceiveFile().Send(r.Conn, varlink.Upgrade, tempPath, true) + reply, err := iopodman.ReceiveFile().Send(r.Conn, varlink.Upgrade, remoteFilePath, delete) if err != nil { return err } @@ -409,7 +413,6 @@ func (r *LocalRuntime) Export(name string, path string) error { if _, err := io.CopyN(writer, reader, length); err != nil { return errors.Wrap(err, "file transer failed") } - return nil } @@ -467,28 +470,17 @@ func (r *LocalRuntime) Build(ctx context.Context, c *cliconfig.BuildValues, opti Squash: options.Squash, } // tar the file - logrus.Debugf("creating tarball of context dir %s", options.ContextDirectory) - input, err := archive.Tar(options.ContextDirectory, archive.Uncompressed) - if err != nil { - return errors.Wrapf(err, "unable to create tarball of context dir %s", options.ContextDirectory) - } - - // Write the tarball to the fs - // TODO we might considering sending this without writing to the fs for the sake of performance - // under given conditions like memory availability. outputFile, err := ioutil.TempFile("", "varlink_tar_send") if err != nil { return err } defer outputFile.Close() - logrus.Debugf("writing context dir tarball to %s", outputFile.Name()) + defer os.Remove(outputFile.Name()) - _, err = io.Copy(outputFile, input) - if err != nil { + // Create the tarball of the context dir to a tempfile + if err := utils.TarToFilesystem(options.ContextDirectory, outputFile); err != nil { return err } - - logrus.Debugf("completed writing context dir tarball %s", outputFile.Name()) // Send the context dir tarball over varlink. tempFile, err := r.SendFileOverVarlink(outputFile.Name()) if err != nil { @@ -702,3 +694,72 @@ func (r *LocalRuntime) PruneVolumes(ctx context.Context) ([]string, []error) { } return prunedNames, errs } + +// SaveImage is a wrapper function for saving an image to the local filesystem +func (r *LocalRuntime) SaveImage(ctx context.Context, c *cliconfig.SaveValues) error { + source := c.InputArgs[0] + additionalTags := c.InputArgs[1:] + + options := iopodman.ImageSaveOptions{ + Name: source, + Format: c.Format, + Output: c.Output, + MoreTags: additionalTags, + Quiet: c.Quiet, + Compress: c.Compress, + } + reply, err := iopodman.ImageSave().Send(r.Conn, varlink.More, options) + if err != nil { + return err + } + + var fetchfile string + for { + responses, flags, err := reply() + if err != nil { + return err + } + if len(responses.Id) > 0 { + fetchfile = responses.Id + } + for _, line := range responses.Logs { + fmt.Print(line) + } + if flags&varlink.Continues == 0 { + break + } + + } + if err != nil { + return err + } + + outputToDir := false + outfile := c.Output + var outputFile *os.File + // If the result is supposed to be a dir, then we need to put the tarfile + // from the host in a temporary file + if options.Format != "oci-archive" && options.Format != "docker-archive" { + outputToDir = true + outputFile, err = ioutil.TempFile("", "saveimage_tempfile") + if err != nil { + return err + } + outfile = outputFile.Name() + defer outputFile.Close() + defer os.Remove(outputFile.Name()) + } + // We now need to fetch the tarball result back to the more system + if err := r.GetFileFromRemoteHost(fetchfile, outfile, true); err != nil { + return err + } + + // If the result is a tarball, we're done + // If it is a dir, we need to untar the temporary file into the dir + if outputToDir { + if err := utils.UntarToFileSystem(c.Output, outputFile, &archive.TarOptions{}); err != nil { + return err + } + } + return nil +} |