diff options
-rwxr-xr-x | API.md | 6 | ||||
-rw-r--r-- | cmd/podman/commands.go | 2 | ||||
-rw-r--r-- | cmd/podman/commit.go | 56 | ||||
-rw-r--r-- | cmd/podman/container.go | 1 | ||||
-rw-r--r-- | cmd/podman/main.go | 1 | ||||
-rw-r--r-- | cmd/podman/varlink/io.podman.varlink | 4 | ||||
-rw-r--r-- | contrib/cirrus/container_test.sh | 4 | ||||
-rwxr-xr-x | contrib/cirrus/integration_test.sh | 16 | ||||
-rwxr-xr-x | contrib/cirrus/rootless_test.sh | 10 | ||||
-rw-r--r-- | contrib/podmanimage/README.md | 44 | ||||
-rw-r--r-- | contrib/podmanimage/stable/Dockerfile | 26 | ||||
-rw-r--r-- | contrib/podmanimage/testing/Dockerfile | 28 | ||||
-rw-r--r-- | contrib/podmanimage/upstream/Dockerfile | 78 | ||||
-rw-r--r-- | docs/podman.1.md | 4 | ||||
-rw-r--r-- | install.md | 2 | ||||
-rw-r--r-- | pkg/adapter/containers.go | 56 | ||||
-rw-r--r-- | pkg/adapter/containers_remote.go | 23 | ||||
-rw-r--r-- | pkg/varlinkapi/images.go | 67 | ||||
-rw-r--r-- | test/e2e/commit_test.go | 5 |
19 files changed, 352 insertions, 81 deletions
@@ -11,7 +11,7 @@ in the [API.md](https://github.com/containers/libpod/blob/master/API.md) file in [func BuildImageHierarchyMap(name: string) string](#BuildImageHierarchyMap) -[func Commit(name: string, image_name: string, changes: []string, author: string, message: string, pause: bool, manifestType: string) string](#Commit) +[func Commit(name: string, image_name: string, changes: []string, author: string, message: string, pause: bool, manifestType: string) MoreResponse](#Commit) [func ContainerArtifacts(name: string, artifactName: string) string](#ContainerArtifacts) @@ -308,14 +308,14 @@ BuildImageHierarchyMap is for the development of Podman and should not be used. ### <a name="Commit"></a>func Commit <div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;"> -method Commit(name: [string](https://godoc.org/builtin#string), image_name: [string](https://godoc.org/builtin#string), changes: [[]string](#[]string), author: [string](https://godoc.org/builtin#string), message: [string](https://godoc.org/builtin#string), pause: [bool](https://godoc.org/builtin#bool), manifestType: [string](https://godoc.org/builtin#string)) [string](https://godoc.org/builtin#string)</div> +method Commit(name: [string](https://godoc.org/builtin#string), image_name: [string](https://godoc.org/builtin#string), changes: [[]string](#[]string), author: [string](https://godoc.org/builtin#string), message: [string](https://godoc.org/builtin#string), pause: [bool](https://godoc.org/builtin#bool), manifestType: [string](https://godoc.org/builtin#string)) [MoreResponse](#MoreResponse)</div> Commit, creates an image from an existing container. It requires the name or ID of the container as well as the resulting image name. Optionally, you can define an author and message to be added to the resulting image. You can also define changes to the resulting image for the following attributes: _CMD, ENTRYPOINT, ENV, EXPOSE, LABEL, ONBUILD, STOPSIGNAL, USER, VOLUME, and WORKDIR_. To pause the container while it is being committed, pass a _true_ bool for the pause argument. If the container cannot be found by the ID or name provided, a (ContainerNotFound)[#ContainerNotFound] error will be returned; otherwise, -the resulting image's ID will be returned as a string. +the resulting image's ID will be returned as a string inside a MoreResponse. ### <a name="ContainerArtifacts"></a>func ContainerArtifacts <div style="background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;"> diff --git a/cmd/podman/commands.go b/cmd/podman/commands.go index 2ac465b9d..18b0b7857 100644 --- a/cmd/podman/commands.go +++ b/cmd/podman/commands.go @@ -11,7 +11,6 @@ const remoteclient = false // Commands that the local client implements func getMainCommands() []*cobra.Command { rootCommands := []*cobra.Command{ - _commitCommand, _execCommand, _playCommand, _loginCommand, @@ -41,7 +40,6 @@ func getContainerSubCommands() []*cobra.Command { return []*cobra.Command{ _cleanupCommand, - _commitCommand, _execCommand, _mountCommand, _refreshCommand, diff --git a/cmd/podman/commit.go b/cmd/podman/commit.go index 2b38bab35..01e2ec701 100644 --- a/cmd/podman/commit.go +++ b/cmd/podman/commit.go @@ -2,16 +2,11 @@ package main import ( "fmt" - "io" - "os" "strings" - "github.com/containers/buildah" - "github.com/containers/image/manifest" "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/cmd/podman/libpodruntime" "github.com/containers/libpod/libpod" - "github.com/containers/libpod/libpod/image" + "github.com/containers/libpod/pkg/adapter" "github.com/containers/libpod/pkg/util" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -52,32 +47,17 @@ func init() { } func commitCmd(c *cliconfig.CommitValues) error { - runtime, err := libpodruntime.GetRuntime(getContext(), &c.PodmanCommand) + runtime, err := adapter.GetRuntime(getContext(), &c.PodmanCommand) if err != nil { return errors.Wrapf(err, "could not get runtime") } defer runtime.Shutdown(false) - var ( - writer io.Writer - mimeType string - ) args := c.InputArgs if len(args) != 2 { return errors.Errorf("you must provide a container name or ID and a target image name") } - 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) - } container := args[0] reference := args[1] if c.Flag("change").Changed { @@ -92,38 +72,10 @@ func commitCmd(c *cliconfig.CommitValues) error { } } - if !c.Quiet { - writer = os.Stderr - } - ctr, err := runtime.LookupContainer(container) - if err != nil { - return errors.Wrapf(err, "error looking up container %q", container) - } - - rtc, err := 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(getContext(), reference, options) + iid, err := runtime.Commit(getContext(), c, container, reference) if err != nil { return err } - fmt.Println(newImage.ID()) + fmt.Println(iid) return nil } diff --git a/cmd/podman/container.go b/cmd/podman/container.go index 839ae3a0e..cb54317c0 100644 --- a/cmd/podman/container.go +++ b/cmd/podman/container.go @@ -52,6 +52,7 @@ var ( containerCommands = []*cobra.Command{ _attachCommand, _checkpointCommand, + _commitCommand, _containerExistsCommand, _contInspectSubCommand, _cpCommand, diff --git a/cmd/podman/main.go b/cmd/podman/main.go index 787dd55c0..a149a47f9 100644 --- a/cmd/podman/main.go +++ b/cmd/podman/main.go @@ -30,6 +30,7 @@ var ( var mainCommands = []*cobra.Command{ _attachCommand, _buildCommand, + _commitCommand, _diffCommand, _createCommand, _eventsCommand, diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink index ed7b49c68..5b3d5ae4c 100644 --- a/cmd/podman/varlink/io.podman.varlink +++ b/cmd/podman/varlink/io.podman.varlink @@ -802,8 +802,8 @@ method DeleteUnusedImages() -> (images: []string) # attributes: _CMD, ENTRYPOINT, ENV, EXPOSE, LABEL, ONBUILD, STOPSIGNAL, USER, VOLUME, and WORKDIR_. To pause the # container while it is being committed, pass a _true_ bool for the pause argument. If the container cannot # be found by the ID or name provided, a (ContainerNotFound)[#ContainerNotFound] error will be returned; otherwise, -# the resulting image's ID will be returned as a string. -method Commit(name: string, image_name: string, changes: []string, author: string, message: string, pause: bool, manifestType: string) -> (image: string) +# the resulting image's ID will be returned as a string inside a MoreResponse. +method Commit(name: string, image_name: string, changes: []string, author: string, message: string, pause: bool, manifestType: string) -> (reply: MoreResponse) # ImportImage imports an image from a source (like tarball) into local storage. The image can have additional # descriptions added to it using the message and changes options. See also [ExportImage](ExportImage). diff --git a/contrib/cirrus/container_test.sh b/contrib/cirrus/container_test.sh index a0542f4a0..27baf0ad7 100644 --- a/contrib/cirrus/container_test.sh +++ b/contrib/cirrus/container_test.sh @@ -133,8 +133,8 @@ fi if [ $integrationtest -eq 1 ]; then make TAGS="${TAGS}" test-binaries make varlink_generate - make ginkgo $INTEGRATION_TEST_ENVS + make localintegration $INTEGRATION_TEST_ENVS if [ $remote -eq 1 ]; then - make ginkgo-remote $INTEGRATION_TEST_ENVS + make remoteintegration $INTEGRATION_TEST_ENVS fi fi diff --git a/contrib/cirrus/integration_test.sh b/contrib/cirrus/integration_test.sh index 88e57fa53..f9ba010cd 100755 --- a/contrib/cirrus/integration_test.sh +++ b/contrib/cirrus/integration_test.sh @@ -5,6 +5,14 @@ source $(dirname $0)/lib.sh req_env_var GOSRC SCRIPT_BASE OS_RELEASE_ID OS_RELEASE_VER CONTAINER_RUNTIME +# Our name must be of the form xxxx_test or xxxx_test.sh, where xxxx is +# the test suite to run; currently (2019-05) the only option is 'integration' +# but pr2947 intends to add 'system'. +TESTSUITE=$(expr $(basename $0) : '\(.*\)_test') +if [[ -z $TESTSUITE ]]; then + die 1 "Script name is not of the form xxxx_test.sh" +fi + cd "$GOSRC" if [[ "$SPECIALMODE" == "in_podman" ]] @@ -28,11 +36,11 @@ then if [[ "$USER" == "$ROOTLESS_USER" ]] then - $GOSRC/$SCRIPT_BASE/rootless_test.sh + $GOSRC/$SCRIPT_BASE/rootless_test.sh ${TESTSUITE} else ssh $ROOTLESS_USER@localhost \ -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o CheckHostIP=no \ - $GOSRC/$SCRIPT_BASE/rootless_test.sh + $GOSRC/$SCRIPT_BASE/rootless_test.sh ${TESTSUITE} fi else make @@ -40,9 +48,9 @@ else make test-binaries if [[ "$TEST_REMOTE_CLIENT" == "true" ]] then - make remoteintegration + make remote${TESTSUITE} else - make localintegration + make local${TESTSUITE} fi exit $? fi diff --git a/contrib/cirrus/rootless_test.sh b/contrib/cirrus/rootless_test.sh index ef0d05cfd..b5744671b 100755 --- a/contrib/cirrus/rootless_test.sh +++ b/contrib/cirrus/rootless_test.sh @@ -18,6 +18,12 @@ then exit 1 fi +# Which set of tests to run; possible alternative is "system" +TESTSUITE=integration +if [[ -n "$*" ]]; then + TESTSUITE="$1" +fi + # Ensure environment setup correctly req_env_var GOSRC ROOTLESS_USER @@ -34,7 +40,7 @@ make make varlink_generate make test-binaries if [ $remote -eq 0 ]; then - make ginkgo + make local${TESTSUITE} else - make ginkgo-remote + make remote${TESTSUITE} fi diff --git a/contrib/podmanimage/README.md b/contrib/podmanimage/README.md new file mode 100644 index 000000000..79484d4a3 --- /dev/null +++ b/contrib/podmanimage/README.md @@ -0,0 +1,44 @@ +![PODMAN logo](logo/podman-logo-source.svg) + +# podmanimage + +## Overview + +This directory contains the Dockerfiles necessary to create the three podmanimage container +images that are housed on quay.io under the podman account. All three repositories where +the images live are public and can be pulled without credentials. These container images are secured and the +resulting containers can run safely with privileges within the container. The container images are built +using the latest Fedora and then Podman is installed into them: + + * quay.io/podman/stable - This image is built using the latest stable version of Podman in a Fedora based container. Built with podman/stable/Dockerfile. + * quay.io/podman/upstream - This image is built using the latest code found in this GitHub repository. When someone creates a commit and pushes it, the image is created. Due to that the image changes frequently and is not guaranteed to be stable. Built with podmanimage/upstream/Dockerfile. + * quay.io/podman/testing - This image is built using the latest version of Podman that is or was in updates testing for Fedora. At times this may be the same as the stable image. This container image will primarily be used by the development teams for verification testing when a new package is created. Built with podmanimage/testing/Dockerfile. + +## Sample Usage + + +``` +podman pull docker://quay.io/podman/stable:latest + +podman run --privileged stable podman version + +# Create a directory on the host to mount the container's +# /var/lib/container directory to so containers can be +# run within the container. +mkdir /var/lib/mycontainer + +# Run the image detached using the host's network in a container name +# podmanctr, turn off label and seccomp confinement in the container +# and then do a little shell hackery to keep the container up and running. +podman run --detach --name=podmanctr --net=host --security-opt label=disable --security-opt seccomp=unconfined --device /dev/fuse:rw -v /var/lib/mycontainer:/var/lib/containers:Z --privileged stable sh -c 'while true ;do wait; done' + +podman exec -it podmanctr /bin/sh + +# Now inside of the container + +podman pull alpine + +podman images + +exit +``` diff --git a/contrib/podmanimage/stable/Dockerfile b/contrib/podmanimage/stable/Dockerfile new file mode 100644 index 000000000..056f62624 --- /dev/null +++ b/contrib/podmanimage/stable/Dockerfile @@ -0,0 +1,26 @@ +# stable/Dockerfile +# +# Build a Podman container image from the latest +# stable version of Podman on the Fedoras Updates System. +# https://bodhi.fedoraproject.org/updates/?search=podman +# This image can be used to create a secured container +# that runs safely with privileges within the container. +# +FROM fedora:latest + +# Don't include container-selinux and remove +# directories used by dnf that are just taking +# up space. +RUN yum -y install podman fuse-overlayfs --exclude container-selinux; rm -rf /var/cache /var/log/dnf* /var/log/yum.* + +# Adjust storage.conf to enable Fuse storage. +RUN sed -i -e 's|^#mount_program|mount_program|g' -e '/additionalimage.*/a "/var/lib/shared",' /etc/containers/storage.conf +RUN mkdir -p /var/lib/shared/overlay-images /var/lib/shared/overlay-layers; touch /var/lib/shared/overlay-images/images.lock; touch /var/lib/shared/overlay-layers/layers.lock + +# Adjust libpod.conf to write logging to a file +RUN sed -i 's/events_logger = "journald"/events_logger = "file"/g' /usr/share/containers/libpod.conf + +# Set up environment variables to note that this is +# not starting with usernamespace and default to +# isolate the filesystem with chroot. +ENV _BUILDAH_STARTED_IN_USERNS="" BUILDAH_ISOLATION=chroot diff --git a/contrib/podmanimage/testing/Dockerfile b/contrib/podmanimage/testing/Dockerfile new file mode 100644 index 000000000..50d8ed7f2 --- /dev/null +++ b/contrib/podmanimage/testing/Dockerfile @@ -0,0 +1,28 @@ +# testing/Dockerfile +# +# Build a Podman image using the latest +# version of Podman that is in updates-testing +# on the Fedoras Updates System. At times this +# may be the same the latest stable version. +# https://bodhi.fedoraproject.org/updates/?search=podman +# This image can be used to create a secured container +# that runs safely with privileges within the container. +# +FROM fedora:latest + +# Don't include container-selinux and remove +# directories used by dnf that are just taking +# up space. +RUN yum -y install podman fuse-overlayfs --exclude container-selinux --enablerepo updates-testing; rm -rf /var/cache /var/log/dnf* /var/log/yum.* + +# Adjust storage.conf to enable Fuse storage. +RUN sed -i -e 's|^#mount_program|mount_program|g' -e '/additionalimage.*/a "/var/lib/shared",' /etc/containers/storage.conf +RUN mkdir -p /var/lib/shared/overlay-images /var/lib/shared/overlay-layers; touch /var/lib/shared/overlay-images/images.lock; touch /var/lib/shared/overlay-layers/layers.lock + +# Adjust libpod.conf to write logging to a file +RUN sed -i 's/events_logger = "journald"/events_logger = "file"/g' /usr/share/containers/libpod.conf + +# Set up environment variables to note that this is +# not starting with usernamespace and default to +# isolate the filesystem with chroot. +ENV _BUILDAH_STARTED_IN_USERNS="" BUILDAH_ISOLATION=chroot diff --git a/contrib/podmanimage/upstream/Dockerfile b/contrib/podmanimage/upstream/Dockerfile new file mode 100644 index 000000000..6ab082efc --- /dev/null +++ b/contrib/podmanimage/upstream/Dockerfile @@ -0,0 +1,78 @@ +# git/Dockerfile +# +# Build a Podman container image from the latest +# upstream version of Podman on GitHub. +# https://github.com/containers/libpod +# This image can be used to create a secured container +# that runs safely with privileges within the container. +# The containers created by this image also come with a +# Podman development environment in /root/podman. +# +FROM fedora:latest +ENV GOPATH=/root/podman + +# Install the software required to build Podman. +# Then create a directory and clone from the Podman +# GitHub repository, make and install Podman +# to the container. +# Finally remove the podman directory and a few other packages +# that are needed for building but not running Podman +RUN dnf -y install --exclude container-selinux \ + --enablerepo=updates-testing \ + atomic-registries \ + btrfs-progs-devel \ + conmon \ + containernetworking-cni \ + device-mapper-devel \ + git \ + glib2-devel \ + glibc-devel \ + glibc-static \ + go \ + golang-github-cpuguy83-go-md2man \ + gpgme-devel \ + iptables \ + libassuan-devel \ + libgpg-error-devel \ + libseccomp-devel \ + libselinux-devel \ + make \ + ostree-devel \ + pkgconfig \ + runc \ + fuse-overlayfs \ + fuse3 \ + containers-common; \ + mkdir /root/podman; \ + git clone https://github.com/containers/libpod /root/podman/src/github.com/containers/libpod; \ + cd /root/podman/src/github.com/containers/libpod; \ + make BUILDTAGS="selinux seccomp"; \ + make install PREFIX=/usr; \ + cd /root/podman; \ + git clone https://github.com/containers/conmon; \ + cd conmon; \ + make; \ + install -D -m 755 bin/conmon /usr/libexec/podman/conmon; \ + git clone https://github.com/containernetworking/plugins.git $GOPATH/src/github.com/containernetworking/plugins; \ + cd $GOPATH/src/github.com/containernetworking/plugins; \ + ./build_linux.sh; \ + mkdir -p /usr/libexec/cni; \ + cp bin/* /usr/libexec/cni; \ + mkdir -p /etc/cni/net.d; \ + curl -qsSL https://raw.githubusercontent.com/containers/libpod/master/cni/87-podman-bridge.conflist | sudo tee /etc/cni/net.d/99-loopback.conf; \ + mkdir -p /usr/share/containers; \ + cp $GOPATH/podman/src/github.com/containers/libpod/libpod.conf /usr/share/containers; \ + # Adjust libpod.conf to write logging to a file + sed -i 's/events_logger = "journald"/events_logger = "file"/g' /usr/share/containers/libpod.conf; \ + rm -rf /root/podman/*; \ + dnf -y remove bats git golang go-md2man make; \ + dnf clean all; + +# Adjust storage.conf to enable Fuse storage. +RUN sed -i -e 's|^#mount_program|mount_program|g' -e '/additionalimage.*/a "/var/lib/shared",' /etc/containers/storage.conf +RUN mkdir -p /var/lib/shared/overlay-images /var/lib/shared/overlay-layers; touch /var/lib/shared/overlay-images/images.lock; touch /var/lib/shared/overlay-layers/layers.lock + +# Set up environment variables to note that this is +# not starting with usernamespace and default to +# isolate the filesystem with chroot. +ENV _BUILDAH_STARTED_IN_USERNS="" BUILDAH_ISOLATION=chroot diff --git a/docs/podman.1.md b/docs/podman.1.md index ff942a3c4..b51cdb854 100644 --- a/docs/podman.1.md +++ b/docs/podman.1.md @@ -177,8 +177,8 @@ the exit codes follow the `chroot` standard, see below: | [podman-umount(1)](podman-umount.1.md) | Unmount a working container's root filesystem. | | [podman-unpause(1)](podman-unpause.1.md) | Unpause one or more containers. | | [podman-unshare(1)](podman-unshare.1.md) | Run a command inside of a modified user namespace. | -| [podman-version(1)](podman-varlink.1.md) | Runs the varlink backend interface. | -| [podman-varlink(1)](podman-version.1.md) | Display the Podman version information. | +| [podman-varlink(1)](podman-varlink.1.md) | Runs the varlink backend interface. | +| [podman-version(1)](podman-version.1.md) | Display the Podman version information. | | [podman-volume(1)](podman-volume.1.md) | Manage Volumes. | | [podman-wait(1)](podman-wait.1.md) | Wait on one or more containers to stop and print their exit codes. | diff --git a/install.md b/install.md index 94de2ea74..4b2c5a119 100644 --- a/install.md +++ b/install.md @@ -273,7 +273,7 @@ First, ensure that the go version that is found first on the $PATH (in case you git clone https://github.com/containers/libpod/ $GOPATH/src/github.com/containers/libpod cd $GOPATH/src/github.com/containers/libpod make BUILDTAGS="selinux seccomp" -sudo make install PREFIX= +sudo make install PREFIX=/usr ``` #### Build Tags 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 0c0bce813..bc6a9cfcd 100644 --- a/pkg/adapter/containers_remote.go +++ b/pkg/adapter/containers_remote.go @@ -994,3 +994,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{ diff --git a/test/e2e/commit_test.go b/test/e2e/commit_test.go index 50577fdfb..e9d274649 100644 --- a/test/e2e/commit_test.go +++ b/test/e2e/commit_test.go @@ -1,5 +1,3 @@ -// +build !remoteclient - package integration import ( @@ -174,6 +172,9 @@ var _ = Describe("Podman commit", func() { }) It("podman commit with volume mounts and --include-volumes", func() { + // We need to figure out how volumes are going to work correctly with the remote + // client. This does not currently work. + SkipIfRemote() s := podmanTest.Podman([]string{"run", "--name", "test1", "-v", "/tmp:/foo", "alpine", "date"}) s.WaitWithDefaultTimeout() Expect(s.ExitCode()).To(Equal(0)) |