summaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
authorbaude <bbaude@redhat.com>2019-04-25 13:58:25 -0500
committerbaude <bbaude@redhat.com>2019-05-30 10:14:23 -0500
commit2df462024bc59fcf117e3c68bd94b667aa0cecd0 (patch)
treed361fc884d0aad34f108d1693990c1289341d7e5 /pkg
parentc871653e195d8051ddfb899c2b73cc95de8e6443 (diff)
downloadpodman-2df462024bc59fcf117e3c68bd94b667aa0cecd0.tar.gz
podman-2df462024bc59fcf117e3c68bd94b667aa0cecd0.tar.bz2
podman-2df462024bc59fcf117e3c68bd94b667aa0cecd0.zip
podman remote-client commit
add the ability to commit a container to an image using the remote client. Signed-off-by: baude <bbaude@redhat.com>
Diffstat (limited to 'pkg')
-rw-r--r--pkg/adapter/containers.go56
-rw-r--r--pkg/adapter/containers_remote.go23
-rw-r--r--pkg/varlinkapi/images.go67
3 files changed, 137 insertions, 9 deletions
diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go
index ff7b6377a..34ee70d3d 100644
--- a/pkg/adapter/containers.go
+++ b/pkg/adapter/containers.go
@@ -6,6 +6,7 @@ import (
"bufio"
"context"
"fmt"
+ "io"
"io/ioutil"
"os"
"path/filepath"
@@ -15,9 +16,12 @@ import (
"syscall"
"time"
+ "github.com/containers/buildah"
+ "github.com/containers/image/manifest"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/adapter/shortcuts"
"github.com/containers/libpod/pkg/systemdgen"
"github.com/containers/psgo"
@@ -1030,3 +1034,55 @@ func (r *LocalRuntime) GenerateSystemd(c *cliconfig.GenerateSystemdValues) (stri
func (r *LocalRuntime) GetNamespaces(container shared.PsContainerOutput) *shared.Namespace {
return shared.GetNamespaces(container.Pid)
}
+
+// Commit creates a local image from a container
+func (r *LocalRuntime) Commit(ctx context.Context, c *cliconfig.CommitValues, container, imageName string) (string, error) {
+ var (
+ writer io.Writer
+ mimeType string
+ )
+ switch c.Format {
+ case "oci":
+ mimeType = buildah.OCIv1ImageManifest
+ if c.Flag("message").Changed {
+ return "", errors.Errorf("messages are only compatible with the docker image format (-f docker)")
+ }
+ case "docker":
+ mimeType = manifest.DockerV2Schema2MediaType
+ default:
+ return "", errors.Errorf("unrecognized image format %q", c.Format)
+ }
+ if !c.Quiet {
+ writer = os.Stderr
+ }
+ ctr, err := r.Runtime.LookupContainer(container)
+ if err != nil {
+ return "", errors.Wrapf(err, "error looking up container %q", container)
+ }
+
+ rtc, err := r.Runtime.GetConfig()
+ if err != nil {
+ return "", err
+ }
+
+ sc := image.GetSystemContext(rtc.SignaturePolicyPath, "", false)
+ coptions := buildah.CommitOptions{
+ SignaturePolicyPath: rtc.SignaturePolicyPath,
+ ReportWriter: writer,
+ SystemContext: sc,
+ PreferredManifestType: mimeType,
+ }
+ options := libpod.ContainerCommitOptions{
+ CommitOptions: coptions,
+ Pause: c.Pause,
+ IncludeVolumes: c.IncludeVolumes,
+ Message: c.Message,
+ Changes: c.Change,
+ Author: c.Author,
+ }
+ newImage, err := ctr.Commit(ctx, imageName, options)
+ if err != nil {
+ return "", err
+ }
+ return newImage.ID(), nil
+}
diff --git a/pkg/adapter/containers_remote.go b/pkg/adapter/containers_remote.go
index c34495b3d..891a2137b 100644
--- a/pkg/adapter/containers_remote.go
+++ b/pkg/adapter/containers_remote.go
@@ -986,3 +986,26 @@ func (r *LocalRuntime) GetNamespaces(container shared.PsContainerOutput) *shared
}
return &ns
}
+
+// Commit creates a local image from a container
+func (r *LocalRuntime) Commit(ctx context.Context, c *cliconfig.CommitValues, container, imageName string) (string, error) {
+ var iid string
+ reply, err := iopodman.Commit().Send(r.Conn, varlink.More, container, imageName, c.Change, c.Author, c.Message, c.Pause, c.Format)
+ if err != nil {
+ return "", err
+ }
+ for {
+ responses, flags, err := reply()
+ if err != nil {
+ return "", err
+ }
+ for _, line := range responses.Logs {
+ fmt.Fprintln(os.Stderr, line)
+ }
+ iid = responses.Id
+ if flags&varlink.Continues == 0 {
+ break
+ }
+ }
+ return iid, nil
+}
diff --git a/pkg/varlinkapi/images.go b/pkg/varlinkapi/images.go
index fa1a0a109..1abc4f086 100644
--- a/pkg/varlinkapi/images.go
+++ b/pkg/varlinkapi/images.go
@@ -371,7 +371,6 @@ func (i *LibpodAPI) PushImage(call iopodman.VarlinkCall, name, tag string, compr
done = true
default:
if !call.WantsMore() {
- time.Sleep(1 * time.Second)
break
}
br := iopodman.MoreResponse{
@@ -495,6 +494,9 @@ func (i *LibpodAPI) DeleteUnusedImages(call iopodman.VarlinkCall) error {
// Commit ...
func (i *LibpodAPI) Commit(call iopodman.VarlinkCall, name, imageName string, changes []string, author, message string, pause bool, manifestType string) error {
+ var newImage *image.Image
+
+ output := bytes.NewBuffer([]byte{})
ctr, err := i.Runtime.LookupContainer(name)
if err != nil {
return call.ReplyContainerNotFound(name, err.Error())
@@ -515,7 +517,7 @@ func (i *LibpodAPI) Commit(call iopodman.VarlinkCall, name, imageName string, ch
}
coptions := buildah.CommitOptions{
SignaturePolicyPath: rtc.SignaturePolicyPath,
- ReportWriter: nil,
+ ReportWriter: output,
SystemContext: sc,
PreferredManifestType: mimeType,
}
@@ -527,11 +529,61 @@ func (i *LibpodAPI) Commit(call iopodman.VarlinkCall, name, imageName string, ch
Author: author,
}
- newImage, err := ctr.Commit(getContext(), imageName, options)
- if err != nil {
- return call.ReplyErrorOccurred(err.Error())
+ if call.WantsMore() {
+ call.Continues = true
}
- return call.ReplyCommit(newImage.ID())
+
+ c := make(chan error)
+
+ go func() {
+ newImage, err = ctr.Commit(getContext(), imageName, options)
+ if err != nil {
+ c <- err
+ }
+ c <- nil
+ close(c)
+ }()
+
+ var log []string
+ done := false
+ for {
+ line, err := output.ReadString('\n')
+ if err == nil {
+ log = append(log, line)
+ continue
+ } else if err == io.EOF {
+ select {
+ case err := <-c:
+ if err != nil {
+ logrus.Errorf("reading of output during commit failed for %s", name)
+ return call.ReplyErrorOccurred(err.Error())
+ }
+ done = true
+ default:
+ if !call.WantsMore() {
+ break
+ }
+ br := iopodman.MoreResponse{
+ Logs: log,
+ }
+ call.ReplyCommit(br)
+ log = []string{}
+ }
+ } else {
+ return call.ReplyErrorOccurred(err.Error())
+ }
+ if done {
+ break
+ }
+ }
+ call.Continues = false
+
+ br := iopodman.MoreResponse{
+ Logs: log,
+ Id: newImage.ID(),
+ }
+
+ return call.ReplyCommit(br)
}
// ImportImage imports an image from a tarball to the image store
@@ -633,7 +685,6 @@ func (i *LibpodAPI) PullImage(call iopodman.VarlinkCall, name string) error {
done = true
default:
if !call.WantsMore() {
- time.Sleep(1 * time.Second)
break
}
br := iopodman.MoreResponse{
@@ -764,7 +815,6 @@ func (i *LibpodAPI) ImageSave(call iopodman.VarlinkCall, options iopodman.ImageS
done = true
default:
if !call.WantsMore() {
- time.Sleep(1 * time.Second)
break
}
br := iopodman.MoreResponse{
@@ -844,7 +894,6 @@ func (i *LibpodAPI) LoadImage(call iopodman.VarlinkCall, name, inputFile string,
done = true
default:
if !call.WantsMore() {
- time.Sleep(1 * time.Second)
break
}
br := iopodman.MoreResponse{