summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml8
-rw-r--r--Makefile28
-rw-r--r--README.md4
-rw-r--r--RELEASE_NOTES.md23
-rw-r--r--changelog.txt45
-rw-r--r--cmd/podman/commands.go1
-rw-r--r--cmd/podman/events.go2
-rw-r--r--cmd/podman/unshare.go54
-rw-r--r--cmd/podman/varlink.go4
-rw-r--r--cmd/podman/version.go2
-rw-r--r--commands.md165
-rwxr-xr-xcontrib/cirrus/integration_test.sh8
-rwxr-xr-xcontrib/cirrus/setup_environment.sh3
-rw-r--r--contrib/spec/podman.spec.in15
-rw-r--r--docs/podman-unshare.1.md37
-rw-r--r--docs/podman.1.md105
-rwxr-xr-xhack/systemd_tag.sh4
-rw-r--r--libpod.conf12
-rw-r--r--libpod/container_api.go12
-rw-r--r--libpod/container_attach_linux.go17
-rw-r--r--libpod/container_attach_unsupported.go4
-rw-r--r--libpod/events/events.go4
-rw-r--r--libpod/events/events_linux.go8
-rw-r--r--libpod/events/journal_linux.go10
-rw-r--r--libpod/events/journal_unsupported.go11
-rw-r--r--libpod/healthcheck_linux.go11
-rw-r--r--libpod/networking_linux.go4
-rw-r--r--libpod/runtime.go2
-rw-r--r--libpod/runtime_pod_linux.go10
-rw-r--r--test/e2e/checkpoint_test.go10
-rw-r--r--test/e2e/cp_test.go37
-rw-r--r--test/e2e/info_test.go1
-rw-r--r--test/e2e/libpod_suite_remoteclient_test.go1
-rw-r--r--test/e2e/rootless_test.go312
-rw-r--r--test/e2e/run_test.go41
-rw-r--r--test/e2e/unshare_test.go52
-rw-r--r--vendor.conf4
-rw-r--r--vendor/github.com/containerd/cgroups/cgroup.go45
-rw-r--r--vendor/github.com/containerd/cgroups/opts.go61
-rw-r--r--vendor/github.com/containerd/cgroups/paths.go5
-rw-r--r--vendor/github.com/containers/storage/layers.go4
-rw-r--r--vendor/github.com/containers/storage/layers_ffjson.go2
-rw-r--r--vendor/github.com/containers/storage/store.go24
-rw-r--r--version/version.go2
44 files changed, 685 insertions, 529 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index 514889969..d26c1ec11 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -73,6 +73,7 @@ env:
#### Default to NOT operating in any special-case testing mode
####
SPECIALMODE: "none" # don't do anything special
+ TEST_REMOTE_CLIENT: false # don't test remote client by default
####
#### Credentials and other secret-sauces, decrypted at runtime when authorized.
@@ -266,6 +267,11 @@ testing_task:
- "vendor"
- "build_each_commit"
+ env:
+ matrix:
+ TEST_REMOTE_CLIENT: true
+ TEST_REMOTE_CLIENT: false
+
gce_instance:
image_project: "libpod-218412"
zone: "us-central1-a" # Required by Cirrus for the time being
@@ -292,12 +298,14 @@ testing_task:
setup_environment_script: '$SCRIPT_BASE/setup_environment.sh |& ${TIMESTAMP}'
unit_test_script: '$SCRIPT_BASE/unit_test.sh |& ${TIMESTAMP}'
integration_test_script: '$SCRIPT_BASE/integration_test.sh |& ${TIMESTAMP}'
+ ginkgo_node_logs_script: 'cat $CIRRUS_WORKING_DIR/test/e2e/ginkgo-node-*.log || echo "Ginkgo node logs not found"'
audit_log_script: 'cat /var/log/audit/audit.log || cat /var/log/kern.log'
journalctl_b_script: 'journalctl -b'
on_failure:
failed_master_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_master_failure.sh'
# Job has already failed, don't fail again and miss collecting data
+ failed_ginkgo_node_logs_script: 'cat $CIRRUS_WORKING_DIR/test/e2e/ginkgo-node-*.log || echo "Ginkgo node logs not found"'
failed_audit_log_script: 'cat /var/log/audit/audit.log || cat /var/log/kern.log || echo "Uh oh, cat audit.log failed"'
failed_journalctl_b_script: 'journalctl -b || echo "Uh oh, journalctl -b failed"'
diff --git a/Makefile b/Makefile
index 86d0d99d2..f73aff2e9 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
GO ?= go
DESTDIR ?= /
-EPOCH_TEST_COMMIT ?= a9fc570dd844bf1ebd1f106f1b8091882b4a2b29
+EPOCH_TEST_COMMIT ?= 8161802f7df857e0850f842261079c83290f9891
HEAD ?= HEAD
CHANGELOG_BASE ?= HEAD~
CHANGELOG_TARGET ?= HEAD
@@ -18,7 +18,23 @@ SHAREDIR_CONTAINERS ?= ${PREFIX}/share/containers
ETCDIR ?= ${DESTDIR}/etc
TMPFILESDIR ?= ${PREFIX}/lib/tmpfiles.d
SYSTEMDDIR ?= ${PREFIX}/lib/systemd/system
-BUILDTAGS ?= seccomp $(shell hack/btrfs_tag.sh) $(shell hack/btrfs_installed_tag.sh) $(shell hack/ostree_tag.sh) $(shell hack/selinux_tag.sh) $(shell hack/apparmor_tag.sh) varlink exclude_graphdriver_devicemapper
+BUILDTAGS ?= \
+ $(shell hack/apparmor_tag.sh) \
+ $(shell hack/btrfs_installed_tag.sh) \
+ $(shell hack/btrfs_tag.sh) \
+ $(shell hack/ostree_tag.sh) \
+ $(shell hack/selinux_tag.sh) \
+ $(shell hack/systemd_tag.sh) \
+ exclude_graphdriver_devicemapper \
+ seccomp \
+ varlink
+
+ifeq (,$(findstring systemd,$(BUILDTAGS)))
+$(warning \
+ Podman is being compiled without the systemd build tag.\
+ Install libsystemd for journald support)
+endif
+
BUILDTAGS_CROSS ?= containers_image_openpgp containers_image_ostree_stub exclude_graphdriver_btrfs exclude_graphdriver_devicemapper exclude_graphdriver_overlay
ifneq (,$(findstring varlink,$(BUILDTAGS)))
PODMAN_VARLINK_DEPENDENCIES = cmd/podman/varlink/iopodman.go
@@ -191,12 +207,14 @@ localunit: test/goecho/goecho varlink_generate
./contrib/cirrus/lib.sh.t
ginkgo:
- ginkgo -v -tags "$(BUILDTAGS)" $(GINKGOTIMEOUT) -cover -flakeAttempts 3 -progress -trace -noColor -nodes 3 test/e2e/.
+ ginkgo -v -tags "$(BUILDTAGS)" $(GINKGOTIMEOUT) -cover -flakeAttempts 3 -progress -trace -noColor -nodes 3 -debug test/e2e/.
ginkgo-remote:
ginkgo -v -tags "$(BUILDTAGS) remoteclient" $(GINKGOTIMEOUT) -cover -flakeAttempts 3 -progress -trace -noColor test/e2e/.
-localintegration: varlink_generate test-binaries ginkgo ginkgo-remote
+localintegration: varlink_generate test-binaries ginkgo
+
+remoteintegration: varlink_generate test-binaries ginkgo-remote
localsystem: .install.ginkgo
ginkgo -v -noColor test/system/
@@ -246,7 +264,9 @@ install: .gopathok install.bin install.man install.cni install.systemd ## Insta
install.bin:
install ${SELINUXOPT} -d -m 755 $(BINDIR)
install ${SELINUXOPT} -m 755 bin/podman $(BINDIR)/podman
+ install ${SELINUXOPT} -m 755 bin/podman-remote $(BINDIR)/podman-remote
test -z "${SELINUXOPT}" || chcon --verbose --reference=$(BINDIR)/podman bin/podman
+ test -z "${SELINUXOPT}" || chcon --verbose --reference=$(BINDIR)/podman bin/podman-remote
install.man: docs
install ${SELINUXOPT} -d -m 755 $(MANDIR)/man1
diff --git a/README.md b/README.md
index a5545bb36..aba6f355d 100644
--- a/README.md
+++ b/README.md
@@ -5,12 +5,12 @@
Libpod provides a library for applications looking to use the Container Pod concept,
popularized by Kubernetes. Libpod also contains the Pod Manager tool `(Podman)`. Podman manages pods, containers, container images, and container volumes.
-* [Latest Version: 1.2.0](https://github.com/containers/libpod/releases/latest)
+* [Latest Version: 1.3.1](https://github.com/containers/libpod/releases/latest)
* [Continuous Integration:](contrib/cirrus/README.md) [![Build Status](https://api.cirrus-ci.com/github/containers/libpod.svg)](https://cirrus-ci.com/github/containers/libpod/master)
## Overview and scope
-At a high level, the scope of libpod and podman is the following:
+At a high level, the scope of libpod and Podman is the following:
* Support multiple image formats including the OCI and Docker image formats.
* Support for multiple means to download images including trust & image verification.
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 499f46317..5eb85d0bc 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,8 +1,29 @@
# Release Notes
+## 1.3.1
+### Features
+- The `podman cp` command can now read input redirected to `STDIN`, and output to `STDOUT` instead of a file, using `-` instead of an argument.
+- The Podman remote client now displays version information from both the client and server in `podman version`
+- The `podman unshare` command has been added, allowing easy entry into the user namespace set up by rootless Podman (allowing the removal of files created by rootless Podman, among other things)
+
+### Bugfixes
+- Fixed a bug where Podman containers with the `--rm` flag were removing created volumes when they were automatically removed ([#3071](https://github.com/containers/libpod/issues/3071))
+- Fixed a bug where container and pod locks were incorrectly marked as released after a system reboot, causing errors on container and pod removal ([#2900](https://github.com/containers/libpod/issues/2900))
+- Fixed a bug where Podman pods could not be removed if any container in the pod encountered an error during removal ([#3088](https://github.com/containers/libpod/issues/3088))
+- Fixed a bug where Podman pods run with the `cgroupfs` CGroup driver would encounter a race condition during removal, potentially failing to remove the pod CGroup
+- Fixed a bug where the `podman container checkpoint` and `podman container restore` commands were not visible in the remote client
+- Fixed a bug where `podman remote ps --ns` would not print the container's namespaces ([#2938](https://github.com/containers/libpod/issues/2938))
+- Fixed a bug where removing stopped containers with healthchecks could cause an error
+- Fixed a bug where the default `libpod.conf` file was causing parsing errors ([#3095](https://github.com/containers/libpod/issues/3095))
+- Fixed a bug where pod locks were not being freed when pods were removed, potentially leading to lock exhaustion
+- Fixed a bug where 'podman run' with SD_NOTIFY set could, on short-running containers, create an inconsistent state rendering the container unusable
+
+### Misc
+- The remote Podman client now uses the Varlink bridge to establish remote connections by default
+
## 1.3.0
### Features
-- Podman now supports container restart policies! The `--restart-policy` flag on `podman create` and `podman run` allows containers to be restarted after they exit. Please note that Podman cannot restart containers after a system reboot - for that, see our next feature
+- Podman now supports container restart policies! The `--restart` flag on `podman create` and `podman run` allows containers to be restarted after they exit. Please note that Podman cannot restart containers after a system reboot - for that, see our next feature
- Podman `podman generate systemd` command was added to generate systemd unit files for managing Podman containers
- The `podman runlabel` command now allows a `$GLOBAL_OPTS` variable, which will be populated by global options passed to the `podman runlabel` command, allowing custom storage configurations to be passed into containers run with `runlabel` ([#2399](https://github.com/containers/libpod/issues/2399))
- The `podman play kube` command now allows `File` and `FileOrCreate` volumes
diff --git a/changelog.txt b/changelog.txt
index c72117d7f..ec0a62f26 100644
--- a/changelog.txt
+++ b/changelog.txt
@@ -1,3 +1,48 @@
+- Changelog for v1.3.1 (2019-05-16)
+ * More release notes
+ * Add unshare to podman
+ * Release notes for 1.3.1
+ * Kill os.Exit() in tests, replace with asserts
+ * Minor capitalization fix in Readme
+ * Add debug mode to Ginkgo, collect debug logs in Cirrus
+ * set default event logger based on build tags
+ * Add VarlinkCall.RequiresUpgrade() type and method
+ * Ensure that start() in StartAndAttach() is locked
+ * When removing pods, free their locks
+ * network: raise a clearer error when using CNI
+ * Fix libpod.conf option ordering
+ * split remote tests from distro tests
+ * varlink: fix usage message, URI is now optional
+ * Update containerd/cgroups to 4994991857f9b0ae
+ * healthcheck benign error
+ * Add `systemd` build tag
+ * podman: fix events help string
+ * When removing a pod with CGroupfs, set pids limit to 0
+ * Add fix for an issue breaking our CI
+ * Use standard remove functions for removing pod ctrs
+ * implement cp reads tar file from stdin/stdout
+ * Add information when running podman version on client
+ * add varlink bridge
+ * Add negative command-line test
+ * Preserve errors returned by removing pods
+ * Improve robustness of pod removal
+ * enable integration tests for remote-client
+ * fix podman-remote ps --ns
+ * podman-run|create man updates
+ * Update installation instructions
+ * remote-podman checkpoint and restore add to container submenu
+ * Remove tests for deprecated podman-refresh command
+ * When refreshing after a reboot, force lock allocation
+ * Do not remove volumes when --rm removes a container
+ * add unit tests for generate systemd
+ * Bump gitvalidation epoch
+ * Bump to v1.3.1-dev
+ * Upgrade to latest criu and selinux-policy
+ * Only run checkpoint/restore tests on Fedora >= 29
+ * Fix API.md
+ * Cirrus: Add missing task dependencies
+ * Cirrus: Add check for make varlink_api_generate
+
- Changelog for v1.3.0 (2019-05-06)
* Update release notes for 1.3.0 release
* Bump to Buildah v1.8.2
diff --git a/cmd/podman/commands.go b/cmd/podman/commands.go
index 3a409f503..2ac465b9d 100644
--- a/cmd/podman/commands.go
+++ b/cmd/podman/commands.go
@@ -20,6 +20,7 @@ func getMainCommands() []*cobra.Command {
_refreshCommand,
_searchCommand,
_statsCommand,
+ _unshareCommand,
}
if len(_varlinkCommand.Use) > 0 {
diff --git a/cmd/podman/events.go b/cmd/podman/events.go
index 15f5e9571..88c1010e3 100644
--- a/cmd/podman/events.go
+++ b/cmd/podman/events.go
@@ -13,7 +13,7 @@ var (
_eventsCommand = &cobra.Command{
Use: "events",
Args: noSubArgs,
- Short: "show podman events",
+ Short: "Show podman events",
Long: eventsDescription,
RunE: func(cmd *cobra.Command, args []string) error {
eventsCommand.InputArgs = args
diff --git a/cmd/podman/unshare.go b/cmd/podman/unshare.go
new file mode 100644
index 000000000..1db647dba
--- /dev/null
+++ b/cmd/podman/unshare.go
@@ -0,0 +1,54 @@
+// +build linux
+
+package main
+
+import (
+ "os"
+ "os/exec"
+
+ "github.com/containers/buildah/pkg/unshare"
+ "github.com/pkg/errors"
+ "github.com/spf13/cobra"
+)
+
+var (
+ unshareDescription = "Runs a command in a modified user namespace."
+ _unshareCommand = &cobra.Command{
+ Use: "unshare [flags] [COMMAND [ARG]]",
+ Short: "Run a command in a modified user namespace",
+ Long: unshareDescription,
+ RunE: unshareCmd,
+ Example: `podman unshare id
+ podman unshare cat /proc/self/uid_map,
+ podman unshare podman-script.sh`,
+ }
+)
+
+func init() {
+ _unshareCommand.SetUsageTemplate(UsageTemplate())
+ flags := _unshareCommand.Flags()
+ flags.SetInterspersed(false)
+}
+
+// unshareCmd execs whatever using the ID mappings that we want to use for ourselves
+func unshareCmd(c *cobra.Command, args []string) error {
+ if isRootless := unshare.IsRootless(); !isRootless {
+ return errors.Errorf("please use unshare with rootless")
+ }
+ // exec the specified command, if there is one
+ if len(args) < 1 {
+ // try to exec the shell, if one's set
+ shell, shellSet := os.LookupEnv("SHELL")
+ if !shellSet {
+ return errors.Errorf("no command specified and no $SHELL specified")
+ }
+ args = []string{shell}
+ }
+ cmd := exec.Command(args[0], args[1:]...)
+ cmd.Env = unshare.RootlessEnv()
+ cmd.Stdin = os.Stdin
+ cmd.Stdout = os.Stdout
+ cmd.Stderr = os.Stderr
+ unshare.ExecRunnable(cmd)
+ return nil
+}
diff --git a/cmd/podman/varlink.go b/cmd/podman/varlink.go
index 215542d2c..698a30d84 100644
--- a/cmd/podman/varlink.go
+++ b/cmd/podman/varlink.go
@@ -29,7 +29,7 @@ var (
Tools speaking varlink protocol can remotely manage pods, containers and images.
`
_varlinkCommand = &cobra.Command{
- Use: "varlink [flags] URI",
+ Use: "varlink [flags] [URI]",
Short: "Run varlink interface",
Long: varlinkDescription,
RunE: func(cmd *cobra.Command, args []string) error {
@@ -68,7 +68,7 @@ func varlinkCmd(c *cliconfig.VarlinkValues) error {
args := c.InputArgs
if len(args) > 1 {
- return errors.Errorf("too many arguments. you may optionally provide 1")
+ return errors.Errorf("too many arguments. You may optionally provide 1")
}
if len(args) > 0 {
diff --git a/cmd/podman/version.go b/cmd/podman/version.go
index 439a1cca6..52a518db8 100644
--- a/cmd/podman/version.go
+++ b/cmd/podman/version.go
@@ -70,7 +70,7 @@ func versionCmd(c *cliconfig.VersionValues) error {
if remote {
fmt.Fprintf(w, "\nService:\n")
- runtime, err := adapter.GetRuntime(getContext(), nil)
+ runtime, err := adapter.GetRuntime(getContext(), &c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
diff --git a/commands.md b/commands.md
index e6c211254..d3ceca9dc 100644
--- a/commands.md
+++ b/commands.md
@@ -4,85 +4,86 @@
## Podman Commands
-Command | Description | Demo | Script
-:----------------------------------------------------------------------- | :------------------------------------------------------------------------- | :-------------------------------------------------------------------------- | :--------------------------------------------------------------------------
-[podman(1)](/docs/podman.1.md) | Simple management tool for pods and images |
-[podman-attach(1)](/docs/podman-attach.1.md) | Attach to a running container |
-[podman-build(1)](/docs/podman-build.1.md) | Build an image using instructions from Dockerfiles |
-[podman-commit(1)](/docs/podman-commit.1.md) | Create new image based on the changed container |
-[podman-container(1)](/docs/podman-container.1.md) | Manage Containers |
-[podman-container-checkpoint(1)](/docs/podman-container-checkpoint.1.md) | Checkpoints one or more running containers |
-[podman-container-cleanup(1)](/docs/podman-container-cleanup.1.md) | Cleanup Container storage and networks |
-[podman-container-exists(1)](/docs/podman-container-exists.1.md) | Check if an container exists in local storage |
-[podman-container-prune(1)](/docs/podman-container-prune.1.md) | Remove all stopped containers |
-[podman-container-refresh(1)](/docs/podman-container-refresh.1.md) | Refresh all containers state in database |
-[podman-container-restore(1)](/docs/podman-container-restore.1.md) | Restores one or more running containers |
-[podman-container-runlabel(1)](/docs/podman-container-runlabel.1.md) | Execute Image Label Method |
-[podman-cp(1)](/docs/podman-cp.1.md) | Copy files/folders between a container and the local filesystem |
-[podman-create(1)](/docs/podman-create.1.md) | Create a new container |
-[podman-diff(1)](/docs/podman-diff.1.md) | Inspect changes on a container or image's filesystem |
-[podman-events(1)](/docs/podman-events.1.md) | Monitor Podman events |
-[podman-exec(1)](/docs/podman-exec.1.md) | Execute a command in a running container |
-[podman-export(1)](/docs/podman-export.1.md) | Export container's filesystem contents as a tar archive |
-[podman-generate(1)](/docs/podman-generate.1.md) | Generate structured output based on Podman containers and pods |
-[podman-generate-kube(1)](/docs/podman-generate-kube.1.md) | Generate Kubernetes YAML based on a container or Pod |
-[podman-generate-systemd(1)](/docs/podman-generate-systemd.1.md) | Generate a Systemd unit file for a container |
-[podman-history(1)](/docs/podman-history.1.md) | Shows the history of an image |
-[podman-image(1)](/docs/podman-image.1.md) | Manage Images |
-[podman-image-exists(1)](/docs/podman-image-exists.1.md) | Check if an image exists in local storage |
-[podman-image-prune(1)](/docs/podman-image-prune.1.md) | Remove all unused images |
-[podman-image-sign(1)](/docs/podman-image-sign.1.md) | Create a signature for an image |
-[podman-image-trust(1)](/docs/podman-image-trust.1.md) | Manage container registry image trust policy |
-[podman-images(1)](/docs/podman-images.1.md) | List images in local storage | [![...](/docs/play.png)](https://podman.io/asciinema/podman/images/) | [Here](https://github.com/containers/Demos/blob/master/podman_cli/podman_images.sh)
-[podman-import(1)](/docs/podman-import.1.md) | Import a tarball and save it as a filesystem image |
-[podman-info(1)](/docs/podman-info.1.md) | Display system information |
-[podman-init(1)](/docs/podman-init.1.md) | Initialize a container |
-[podman-inspect(1)](/docs/podman-inspect.1.md) | Display the configuration of a container or image | [![...](/docs/play.png)](https://asciinema.org/a/133418)
-[podman-kill(1)](/docs/podman-kill.1.md) | Kill the main process in one or more running containers |
-[podman-load(1)](/docs/podman-load.1.md) | Load an image from a container image archive |
-[podman-login(1)](/docs/podman-login.1.md) | Login to a container registry |
-[podman-logout(1)](/docs/podman-logout.1.md) | Logout of a container registry |
-[podman-logs(1)](/docs/podman-logs.1.md) | Display the logs of a container |
-[podman-mount(1)](/docs/podman-mount.1.md) | Mount a working container's root filesystem |
-[podman-pause(1)](/docs/podman-pause.1.md) | Pause one or more running containers | [![...](/docs/play.png)](https://asciinema.org/a/141292)
-[podman-play(1)](/docs/podman-play.1.md) | Play pods and containers based on a structured input file |
-[podman-pod(1)](/docs/podman-pod.1.md) | Simple management tool for groups of containers, called pods |
-[podman-pod-create(1)](/docs/podman-pod-create.1.md) | Create a new pod |
-[podman-pod-inspect(1)](/docs/podman-pod-inspect.1.md) | Inspect a pod |
-[podman-pod-kill(1)](podman-pod-kill.1.md) | Kill the main process of each container in pod. |
-[podman-pod-ps(1)](/docs/podman-pod-ps.1.md) | List the pods on the system |
-[podman-pod-pause(1)](podman-pod-pause.1.md) | Pause one or more pods. |
-[podman-pod-restart](/docs/podman-pod-restart.1.md) | Restart one or more pods |
-[podman-pod-rm(1)](/docs/podman-pod-rm.1.md) | Remove one or more pods |
-[podman-pod-start(1)](/docs/podman-pod-start.1.md) | Start one or more pods |
-[podman-pod-stats(1)](/docs/podman-pod-stats.1.md) | Display a live stream of one or more pods' resource usage statistics | | |
-[podman-pod-stop(1)](/docs/podman-pod-stop.1.md) | Stop one or more pods |
-[podman-pod-top(1)](/docs/podman-pod-top.1.md) | Display the running processes of a pod |
-[podman-pod-unpause(1)](podman-pod-unpause.1.md) | Unpause one or more pods. |
-[podman-port(1)](/docs/podman-port.1.md) | List port mappings for running containers |
-[podman-ps(1)](/docs/podman-ps.1.md) | Prints out information about containers |
-[podman-pull(1)](/docs/podman-pull.1.md) | Pull an image from a registry |
-[podman-push(1)](/docs/podman-push.1.md) | Push an image to a specified destination | [![...](/docs/play.png)](https://asciinema.org/a/133276)
-[podman-restart](/docs/podman-restart.1.md) | Restarts one or more containers | [![...](/docs/play.png)](https://asciinema.org/a/jiqxJAxcVXw604xdzMLTkQvHM)
-[podman-rm(1)](/docs/podman-rm.1.md) | Removes one or more containers |
-[podman-rmi(1)](/docs/podman-rmi.1.md) | Removes one or more images |
-[podman-run(1)](/docs/podman-run.1.md) | Run a command in a container |
-[podman-save(1)](/docs/podman-save.1.md) | Saves an image to an archive |
-[podman-search(1)](/docs/podman-search.1.md) | Search a registry for an image |
-[podman-start(1)](/docs/podman-start.1.md) | Starts one or more containers |
-[podman-stats(1)](/docs/podman-stats.1.md) | Display a live stream of one or more containers' resource usage statistics |
-[podman-stop(1)](/docs/podman-stop.1.md) | Stops one or more running containers |
-[podman-system(1)](/docs/podman-system.1.md) | Manage podman |
-[podman-tag(1)](/docs/podman-tag.1.md) | Add an additional name to a local image | [![...](/docs/play.png)](https://asciinema.org/a/133803)
-[podman-top(1)](/docs/podman-top.1.md) | Display the running processes of a container |
-[podman-umount(1)](/docs/podman-umount.1.md) | Unmount a working container's root filesystem |
-[podman-unpause(1)](/docs/podman-unpause.1.md) | Unpause one or more running containers | [![...](/docs/play.png)](https://asciinema.org/a/141292)
-[podman-varlink(1)](/docs/podman-varlink.1.md) | Run the varlink backend |
-[podman-version(1)](/docs/podman-version.1.md) | Display the version information |
-[podman-volume(1)](/docs/podman-volume.1.md) | Manage Volumes |
-[podman-volume-create(1)](/docs/podman-volume-create.1.md) | Create a volume |
-[podman-volume-inspect(1)](/docs/podman-volume-inspect.1.md) | Get detailed information on one or more volumes |
-[podman-volume-ls(1)](/docs/podman-volume-ls.1.md) | List all the available volumes |
-[podman-volume-rm(1)](/docs/podman-volume-rm.1.md) | Remove one or more volumes |
-[podman-volume-prune(1)](/docs/podman-volume-prune.1.md) | Remove all unused volumes |
-[podman-wait(1)](/docs/podman-wait.1.md) | Wait on one or more containers to stop and print their exit codes
+| Command | Description | Demo | Script |
+| :----------------------------------------------------------------------- | :------------------------------------------------------------------------- | :-------------------------------------------------------------------------- | :---------------------------------------------------------------------------------- |
+| [podman(1)](/docs/podman.1.md) | Simple management tool for pods and images |
+| [podman-attach(1)](/docs/podman-attach.1.md) | Attach to a running container |
+| [podman-build(1)](/docs/podman-build.1.md) | Build an image using instructions from Dockerfiles |
+| [podman-commit(1)](/docs/podman-commit.1.md) | Create new image based on the changed container |
+| [podman-container(1)](/docs/podman-container.1.md) | Manage Containers |
+| [podman-container-checkpoint(1)](/docs/podman-container-checkpoint.1.md) | Checkpoints one or more running containers |
+| [podman-container-cleanup(1)](/docs/podman-container-cleanup.1.md) | Cleanup Container storage and networks |
+| [podman-container-exists(1)](/docs/podman-container-exists.1.md) | Check if an container exists in local storage |
+| [podman-container-prune(1)](/docs/podman-container-prune.1.md) | Remove all stopped containers |
+| [podman-container-refresh(1)](/docs/podman-container-refresh.1.md) | Refresh all containers state in database |
+| [podman-container-restore(1)](/docs/podman-container-restore.1.md) | Restores one or more running containers |
+| [podman-container-runlabel(1)](/docs/podman-container-runlabel.1.md) | Execute Image Label Method |
+| [podman-cp(1)](/docs/podman-cp.1.md) | Copy files/folders between a container and the local filesystem |
+| [podman-create(1)](/docs/podman-create.1.md) | Create a new container |
+| [podman-diff(1)](/docs/podman-diff.1.md) | Inspect changes on a container or image's filesystem |
+| [podman-events(1)](/docs/podman-events.1.md) | Monitor Podman events |
+| [podman-exec(1)](/docs/podman-exec.1.md) | Execute a command in a running container |
+| [podman-export(1)](/docs/podman-export.1.md) | Export container's filesystem contents as a tar archive |
+| [podman-generate(1)](/docs/podman-generate.1.md) | Generate structured output based on Podman containers and pods |
+| [podman-generate-kube(1)](/docs/podman-generate-kube.1.md) | Generate Kubernetes YAML based on a container or Pod |
+| [podman-generate-systemd(1)](/docs/podman-generate-systemd.1.md) | Generate a Systemd unit file for a container |
+| [podman-history(1)](/docs/podman-history.1.md) | Shows the history of an image |
+| [podman-image(1)](/docs/podman-image.1.md) | Manage Images |
+| [podman-image-exists(1)](/docs/podman-image-exists.1.md) | Check if an image exists in local storage |
+| [podman-image-prune(1)](/docs/podman-image-prune.1.md) | Remove all unused images |
+| [podman-image-sign(1)](/docs/podman-image-sign.1.md) | Create a signature for an image |
+| [podman-image-trust(1)](/docs/podman-image-trust.1.md) | Manage container registry image trust policy |
+| [podman-images(1)](/docs/podman-images.1.md) | List images in local storage | [![...](/docs/play.png)](https://podman.io/asciinema/podman/images/) | [Here](https://github.com/containers/Demos/blob/master/podman_cli/podman_images.sh) |
+| [podman-import(1)](/docs/podman-import.1.md) | Import a tarball and save it as a filesystem image |
+| [podman-info(1)](/docs/podman-info.1.md) | Display system information |
+| [podman-init(1)](/docs/podman-init.1.md) | Initialize a container |
+| [podman-inspect(1)](/docs/podman-inspect.1.md) | Display the configuration of a container or image | [![...](/docs/play.png)](https://asciinema.org/a/133418) |
+| [podman-kill(1)](/docs/podman-kill.1.md) | Kill the main process in one or more running containers |
+| [podman-load(1)](/docs/podman-load.1.md) | Load an image from a container image archive |
+| [podman-login(1)](/docs/podman-login.1.md) | Login to a container registry |
+| [podman-logout(1)](/docs/podman-logout.1.md) | Logout of a container registry |
+| [podman-logs(1)](/docs/podman-logs.1.md) | Display the logs of a container |
+| [podman-mount(1)](/docs/podman-mount.1.md) | Mount a working container's root filesystem |
+| [podman-pause(1)](/docs/podman-pause.1.md) | Pause one or more running containers | [![...](/docs/play.png)](https://asciinema.org/a/141292) |
+| [podman-play(1)](/docs/podman-play.1.md) | Play pods and containers based on a structured input file |
+| [podman-pod(1)](/docs/podman-pod.1.md) | Simple management tool for groups of containers, called pods |
+| [podman-pod-create(1)](/docs/podman-pod-create.1.md) | Create a new pod |
+| [podman-pod-inspect(1)](/docs/podman-pod-inspect.1.md) | Inspect a pod |
+| [podman-pod-kill(1)](podman-pod-kill.1.md) | Kill the main process of each container in pod. |
+| [podman-pod-ps(1)](/docs/podman-pod-ps.1.md) | List the pods on the system |
+| [podman-pod-pause(1)](podman-pod-pause.1.md) | Pause one or more pods. |
+| [podman-pod-restart](/docs/podman-pod-restart.1.md) | Restart one or more pods |
+| [podman-pod-rm(1)](/docs/podman-pod-rm.1.md) | Remove one or more pods |
+| [podman-pod-start(1)](/docs/podman-pod-start.1.md) | Start one or more pods |
+| [podman-pod-stats(1)](/docs/podman-pod-stats.1.md) | Display a live stream of one or more pods' resource usage statistics | | |
+| [podman-pod-stop(1)](/docs/podman-pod-stop.1.md) | Stop one or more pods |
+| [podman-pod-top(1)](/docs/podman-pod-top.1.md) | Display the running processes of a pod |
+| [podman-pod-unpause(1)](podman-pod-unpause.1.md) | Unpause one or more pods. |
+| [podman-port(1)](/docs/podman-port.1.md) | List port mappings for running containers |
+| [podman-ps(1)](/docs/podman-ps.1.md) | Prints out information about containers |
+| [podman-pull(1)](/docs/podman-pull.1.md) | Pull an image from a registry |
+| [podman-push(1)](/docs/podman-push.1.md) | Push an image to a specified destination | [![...](/docs/play.png)](https://asciinema.org/a/133276) |
+| [podman-restart](/docs/podman-restart.1.md) | Restarts one or more containers | [![...](/docs/play.png)](https://asciinema.org/a/jiqxJAxcVXw604xdzMLTkQvHM) |
+| [podman-rm(1)](/docs/podman-rm.1.md) | Removes one or more containers |
+| [podman-rmi(1)](/docs/podman-rmi.1.md) | Removes one or more images |
+| [podman-run(1)](/docs/podman-run.1.md) | Run a command in a container |
+| [podman-save(1)](/docs/podman-save.1.md) | Saves an image to an archive |
+| [podman-search(1)](/docs/podman-search.1.md) | Search a registry for an image |
+| [podman-start(1)](/docs/podman-start.1.md) | Starts one or more containers |
+| [podman-stats(1)](/docs/podman-stats.1.md) | Display a live stream of one or more containers' resource usage statistics |
+| [podman-stop(1)](/docs/podman-stop.1.md) | Stops one or more running containers |
+| [podman-system(1)](/docs/podman-system.1.md) | Manage podman |
+| [podman-tag(1)](/docs/podman-tag.1.md) | Add an additional name to a local image | [![...](/docs/play.png)](https://asciinema.org/a/133803) |
+| [podman-top(1)](/docs/podman-top.1.md) | Display the running processes of a container |
+| [podman-umount(1)](/docs/podman-umount.1.md) | Unmount a working container's root filesystem |
+| [podman-unpause(1)](/docs/podman-unpause.1.md) | Unpause one or more running containers | [![...](/docs/play.png)](https://asciinema.org/a/141292) |
+| [podman-unshare(1)](/docs/podman-unshare.1.md) | Run a command inside of a modified user namespace. |
+| [podman-varlink(1)](/docs/podman-varlink.1.md) | Run the varlink backend |
+| [podman-version(1)](/docs/podman-version.1.md) | Display the version information |
+| [podman-volume(1)](/docs/podman-volume.1.md) | Manage Volumes |
+| [podman-volume-create(1)](/docs/podman-volume-create.1.md) | Create a volume |
+| [podman-volume-inspect(1)](/docs/podman-volume-inspect.1.md) | Get detailed information on one or more volumes |
+| [podman-volume-ls(1)](/docs/podman-volume-ls.1.md) | List all the available volumes |
+| [podman-volume-rm(1)](/docs/podman-volume-rm.1.md) | Remove one or more volumes |
+| [podman-volume-prune(1)](/docs/podman-volume-prune.1.md) | Remove all unused volumes |
+| [podman-wait(1)](/docs/podman-wait.1.md) | Wait on one or more containers to stop and print their exit codes |
diff --git a/contrib/cirrus/integration_test.sh b/contrib/cirrus/integration_test.sh
index 5b73f0c6c..c7d381318 100755
--- a/contrib/cirrus/integration_test.sh
+++ b/contrib/cirrus/integration_test.sh
@@ -36,6 +36,7 @@ else
make
make install PREFIX=/usr ETCDIR=/etc
make test-binaries
+ make install.tools
clean_env
case "${OS_RELEASE_ID}-${OS_RELEASE_VER}" in
@@ -49,6 +50,11 @@ else
;;
*) bad_os_id_ver ;;
esac
- make localintegration
+ if [[ "$TEST_REMOTE_CLIENT" == "true" ]]
+ then
+ make remoteintegration
+ else
+ make localintegration
+ fi
exit $?
fi
diff --git a/contrib/cirrus/setup_environment.sh b/contrib/cirrus/setup_environment.sh
index 2f9b1d796..4dbd56ed9 100755
--- a/contrib/cirrus/setup_environment.sh
+++ b/contrib/cirrus/setup_environment.sh
@@ -36,6 +36,7 @@ then
"export OS_RELEASE_ID=\"$(os_release_id)\"" \
"export OS_RELEASE_VER=\"$(os_release_ver)\"" \
"export OS_REL_VER=\"$(os_release_id)-$(os_release_ver)\"" \
+ "export TEST_REMOTE_CLIENT=\"$TEST_REMOTE_CLIENT\"" \
"export BUILT_IMAGE_SUFFIX=\"-$CIRRUS_REPO_NAME-${CIRRUS_CHANGE_IN_REPO:0:8}\"" \
"export GOPATH=\"/var/tmp/go\"" \
'export PATH="$HOME/bin:$GOPATH/bin:/usr/local/bin:$PATH"' \
@@ -55,6 +56,8 @@ then
CON_SEL="https://kojipkgs.fedoraproject.org/packages/container-selinux/2.100/1.git3b78187.fc29/noarch/container-selinux-2.100-1.git3b78187.fc29.noarch.rpm"
echo ">>>>> OVERRIDING container-selinux WITH $CON_SEL <<<<<"
dnf -y install $CON_SEL
+ echo ">>>>> OVERRIDING criu and selinux-policy with latest package <<<<<"
+ dnf -y upgrade criu selinux-policy
;& # Continue to the next item
fedora-28)
echo ">>>>> OVERRIDING source-built runc with latest package <<<<<"
diff --git a/contrib/spec/podman.spec.in b/contrib/spec/podman.spec.in
index d69b673e0..5e5789cf5 100644
--- a/contrib/spec/podman.spec.in
+++ b/contrib/spec/podman.spec.in
@@ -39,7 +39,7 @@
%global shortcommit_conmon %(c=%{commit_conmon}; echo ${c:0:7})
Name: podman
-Version: 1.3.1
+Version: 1.3.2
Release: #COMMITDATE#.git%{shortcommit0}%{?dist}
Summary: Manage Pods, Containers and Container Images
License: ASL 2.0
@@ -185,6 +185,14 @@ Provides: bundled(golang(k8s.io/utils)) = 258e2a2fa64568210fbd6267cf1d8fd87c3cb8
%{repo} provides a library for applications looking to use
the Container Pod concept popularized by Kubernetes.
+%package remote
+Summary: Remote Podman client
+
+%description -n podman-remote
+%{summary}
+This package provides the Podman remote client which
+can be used to access Podman running on a server.
+
%if 0%{?with_devel}
%package devel
Summary: Library for applications looking to use Container Pods
@@ -491,6 +499,11 @@ export GOPATH=%{buildroot}/%{gopath}:$(pwd)/vendor:%{gopath}
%doc README.md CONTRIBUTING.md pkg/hooks/README-hooks.md install.md code-of-conduct.md transfer.md
%endif
+%files -n podman-remote
+%license LICENSE
+%doc README.md CONTRIBUTING.md pkg/hooks/README-hooks.md install.md code-of-conduct.md transfer.md
+%{_bindir}/%{name}-remote
+
%changelog
* Sat Aug 4 2018 Dan Walsh <dwalsh@redhat.com> - 0.8.1-1.git6b4ab2a
- Bump to v0.8.1
diff --git a/docs/podman-unshare.1.md b/docs/podman-unshare.1.md
new file mode 100644
index 000000000..a7f018ce1
--- /dev/null
+++ b/docs/podman-unshare.1.md
@@ -0,0 +1,37 @@
+% podman-unshare "1"
+
+## NAME
+podman\-unshare - Run a command inside of a modified user namespace.
+
+## SYNOPSIS
+**podman unshare** [*options*] [**--**] [*command*]
+
+## DESCRIPTION
+Launches a process (by default, *$SHELL*) in a new user namespace. The user
+namespace is configured so that the invoking user's UID and primary GID appear
+to be UID 0 and GID 0, respectively. Any ranges which match that user and
+group in /etc/subuid and /etc/subgid are also mapped in as themselves with the
+help of the *newuidmap(1)* and *newgidmap(1)* helpers.
+
+podman unshare is useful for troubleshooting unprivileged operations and for
+manually clearing storage and other data related to images and containers.
+
+It is also useful if you want to use the `podman mount` command. If an unprivileged users wants to mount and work with a container, then they need to execute
+podman unshare. Executing `podman mount` fails for unprivileged users unless the user is running inside a `podman unshare` session.
+
+## EXAMPLE
+
+```
+$ podman unshare id
+uid=0(root) gid=0(root) groups=0(root),65534(nobody)
+
+$ podman unshare cat /proc/self/uid_map /proc/self/gid_map
+ 0 1000 1
+ 1 10000 65536
+ 0 1000 1
+ 1 10000 65536
+```
+
+
+## SEE ALSO
+podman(1), podman-mount(1), namespaces(7), newuidmap(1), newgidmap(1), user\_namespaces(7) \ No newline at end of file
diff --git a/docs/podman.1.md b/docs/podman.1.md
index ef12cf1cc..ff942a3c4 100644
--- a/docs/podman.1.md
+++ b/docs/podman.1.md
@@ -128,58 +128,59 @@ the exit codes follow the `chroot` standard, see below:
## COMMANDS
-| Command | Description |
-| ----------------------------------------- | ------------------------------------------------------------------------------ |
-| [podman-attach(1)](podman-attach.1.md) | Attach to a running container. |
-| [podman-build(1)](podman-build.1.md) | Build a container image using a Dockerfile. |
-| [podman-commit(1)](podman-commit.1.md) | Create new image based on the changed container. |
-| [podman-container(1)](podman-container.1.md) | Manage containers. |
-| [podman-cp(1)](podman-cp.1.md) | Copy files/folders between a container and the local filesystem. |
-| [podman-create(1)](podman-create.1.md) | Create a new container. |
-| [podman-diff(1)](podman-diff.1.md) | Inspect changes on a container or image's filesystem. |
-| [podman-events(1)](podman-events.1.md) | Monitor Podman events |
-| [podman-exec(1)](podman-exec.1.md) | Execute a command in a running container. |
-| [podman-export(1)](podman-export.1.md) | Export a container's filesystem contents as a tar archive. |
-| [podman-generate(1)](podman-generate.1.md)| Generate structured data based for a containers and pods. |
-| [podman-healthcheck(1)](podman-healthcheck.1.md)| Manage healthchecks for containers |
-| [podman-history(1)](podman-history.1.md) | Show the history of an image. |
-| [podman-image(1)](podman-image.1.md) | Manage images. |
-| [podman-images(1)](podman-images.1.md) | List images in local storage. |
-| [podman-import(1)](podman-import.1.md) | Import a tarball and save it as a filesystem image. |
-| [podman-info(1)](podman-info.1.md) | Displays Podman related system information. |
-| [podman-init(1)](podman-init.1.md) | Initialize a container |
-| [podman-inspect(1)](podman-inspect.1.md) | Display a container or image's configuration. |
-| [podman-kill(1)](podman-kill.1.md) | Kill the main process in one or more containers. |
-| [podman-load(1)](podman-load.1.md) | Load an image from a container image archive into container storage. |
-| [podman-login(1)](podman-login.1.md) | Login to a container registry. |
-| [podman-logout(1)](podman-logout.1.md) | Logout of a container registry. |
-| [podman-logs(1)](podman-logs.1.md) | Display the logs of a container. |
-| [podman-mount(1)](podman-mount.1.md) | Mount a working container's root filesystem. |
-| [podman-pause(1)](podman-pause.1.md) | Pause one or more containers. |
-| [podman-play(1)](podman-play.1.md) | Play pods and containers based on a structured input file. |
-| [podman-pod(1)](podman-pod.1.md) | Management tool for groups of containers, called pods. |
-| [podman-port(1)](podman-port.1.md) | List port mappings for a container. |
-| [podman-ps(1)](podman-ps.1.md) | Prints out information about containers. |
-| [podman-pull(1)](podman-pull.1.md) | Pull an image from a registry. |
-| [podman-push(1)](podman-push.1.md) | Push an image from local storage to elsewhere. |
-| [podman-restart(1)](podman-restart.1.md) | Restart one or more containers. |
-| [podman-rm(1)](podman-rm.1.md) | Remove one or more containers. |
-| [podman-rmi(1)](podman-rmi.1.md) | Removes one or more locally stored images. |
-| [podman-run(1)](podman-run.1.md) | Run a command in a new container. |
-| [podman-save(1)](podman-save.1.md) | Save an image to a container archive. |
-| [podman-search(1)](podman-search.1.md) | Search a registry for an image. |
-| [podman-start(1)](podman-start.1.md) | Start one or more containers. |
-| [podman-stats(1)](podman-stats.1.md) | Display a live stream of one or more container's resource usage statistics. |
-| [podman-stop(1)](podman-stop.1.md) | Stop one or more running containers. |
-| [podman-system(1)](podman-system.1.md) | Manage podman. |
-| [podman-tag(1)](podman-tag.1.md) | Add an additional name to a local image. |
-| [podman-top(1)](podman-top.1.md) | Display the running processes of a container. |
-| [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-version(1)](podman-varlink.1.md) | Runs the varlink backend interface. |
-| [podman-varlink(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. |
+| Command | Description |
+| ------------------------------------------------ | --------------------------------------------------------------------------- |
+| [podman-attach(1)](podman-attach.1.md) | Attach to a running container. |
+| [podman-build(1)](podman-build.1.md) | Build a container image using a Dockerfile. |
+| [podman-commit(1)](podman-commit.1.md) | Create new image based on the changed container. |
+| [podman-container(1)](podman-container.1.md) | Manage containers. |
+| [podman-cp(1)](podman-cp.1.md) | Copy files/folders between a container and the local filesystem. |
+| [podman-create(1)](podman-create.1.md) | Create a new container. |
+| [podman-diff(1)](podman-diff.1.md) | Inspect changes on a container or image's filesystem. |
+| [podman-events(1)](podman-events.1.md) | Monitor Podman events |
+| [podman-exec(1)](podman-exec.1.md) | Execute a command in a running container. |
+| [podman-export(1)](podman-export.1.md) | Export a container's filesystem contents as a tar archive. |
+| [podman-generate(1)](podman-generate.1.md) | Generate structured data based for a containers and pods. |
+| [podman-healthcheck(1)](podman-healthcheck.1.md) | Manage healthchecks for containers |
+| [podman-history(1)](podman-history.1.md) | Show the history of an image. |
+| [podman-image(1)](podman-image.1.md) | Manage images. |
+| [podman-images(1)](podman-images.1.md) | List images in local storage. |
+| [podman-import(1)](podman-import.1.md) | Import a tarball and save it as a filesystem image. |
+| [podman-info(1)](podman-info.1.md) | Displays Podman related system information. |
+| [podman-init(1)](podman-init.1.md) | Initialize a container |
+| [podman-inspect(1)](podman-inspect.1.md) | Display a container or image's configuration. |
+| [podman-kill(1)](podman-kill.1.md) | Kill the main process in one or more containers. |
+| [podman-load(1)](podman-load.1.md) | Load an image from a container image archive into container storage. |
+| [podman-login(1)](podman-login.1.md) | Login to a container registry. |
+| [podman-logout(1)](podman-logout.1.md) | Logout of a container registry. |
+| [podman-logs(1)](podman-logs.1.md) | Display the logs of a container. |
+| [podman-mount(1)](podman-mount.1.md) | Mount a working container's root filesystem. |
+| [podman-pause(1)](podman-pause.1.md) | Pause one or more containers. |
+| [podman-play(1)](podman-play.1.md) | Play pods and containers based on a structured input file. |
+| [podman-pod(1)](podman-pod.1.md) | Management tool for groups of containers, called pods. |
+| [podman-port(1)](podman-port.1.md) | List port mappings for a container. |
+| [podman-ps(1)](podman-ps.1.md) | Prints out information about containers. |
+| [podman-pull(1)](podman-pull.1.md) | Pull an image from a registry. |
+| [podman-push(1)](podman-push.1.md) | Push an image from local storage to elsewhere. |
+| [podman-restart(1)](podman-restart.1.md) | Restart one or more containers. |
+| [podman-rm(1)](podman-rm.1.md) | Remove one or more containers. |
+| [podman-rmi(1)](podman-rmi.1.md) | Removes one or more locally stored images. |
+| [podman-run(1)](podman-run.1.md) | Run a command in a new container. |
+| [podman-save(1)](podman-save.1.md) | Save an image to a container archive. |
+| [podman-search(1)](podman-search.1.md) | Search a registry for an image. |
+| [podman-start(1)](podman-start.1.md) | Start one or more containers. |
+| [podman-stats(1)](podman-stats.1.md) | Display a live stream of one or more container's resource usage statistics. |
+| [podman-stop(1)](podman-stop.1.md) | Stop one or more running containers. |
+| [podman-system(1)](podman-system.1.md) | Manage podman. |
+| [podman-tag(1)](podman-tag.1.md) | Add an additional name to a local image. |
+| [podman-top(1)](podman-top.1.md) | Display the running processes of a container. |
+| [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-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. |
## FILES
diff --git a/hack/systemd_tag.sh b/hack/systemd_tag.sh
new file mode 100755
index 000000000..c59cad559
--- /dev/null
+++ b/hack/systemd_tag.sh
@@ -0,0 +1,4 @@
+#!/usr/bin/env bash
+if pkg-config --exists libsystemd; then
+ echo systemd
+fi
diff --git a/libpod.conf b/libpod.conf
index ca8d0fb36..ce6b95cda 100644
--- a/libpod.conf
+++ b/libpod.conf
@@ -99,6 +99,10 @@ num_locks = 2048
# Uncomment to change location from this default.
#volume_path = "/var/lib/containers/storage/volumes"
+# Selects which logging mechanism to use for Podman events. Valid values
+# are `journald` or `file`.
+# events_logger = "journald"
+
# Default OCI runtime
runtime = "runc"
@@ -114,6 +118,8 @@ runc = [
"/usr/lib/cri-o-runc/sbin/runc"
]
-# Selects which logging mechanism to use for Podman events. Valid values
-# are `journald` or `file`.
-events_logger = "journald"
+# The [runtimes] table MUST be the last thing in this file.
+# (Unless another table is added)
+# TOML does not provide a way to end a table other than a further table being
+# defined, so every key hereafter will be part of [runtimes] and not the main
+# config.
diff --git a/libpod/container_api.go b/libpod/container_api.go
index 5bb610aab..06a31da11 100644
--- a/libpod/container_api.go
+++ b/libpod/container_api.go
@@ -7,6 +7,7 @@ import (
"io/ioutil"
"os"
"strconv"
+ "sync"
"time"
"github.com/containers/libpod/libpod/driver"
@@ -119,13 +120,20 @@ func (c *Container) StartAndAttach(ctx context.Context, streams *AttachStreams,
attachChan := make(chan error)
+ // We need to ensure that we don't return until start() fired in attach.
+ // Use a WaitGroup to sync this.
+ wg := new(sync.WaitGroup)
+ wg.Add(1)
+
// Attach to the container before starting it
go func() {
- if err := c.attach(streams, keys, resize, true); err != nil {
+ if err := c.attach(streams, keys, resize, true, wg); err != nil {
attachChan <- err
}
close(attachChan)
}()
+
+ wg.Wait()
c.newContainerEvent(events.Attach)
return attachChan, nil
}
@@ -398,7 +406,7 @@ func (c *Container) Attach(streams *AttachStreams, keys string, resize <-chan re
return errors.Wrapf(ErrCtrStateInvalid, "can only attach to created or running containers")
}
defer c.newContainerEvent(events.Attach)
- return c.attach(streams, keys, resize, false)
+ return c.attach(streams, keys, resize, false, nil)
}
// Mount mounts a container's filesystem on the host
diff --git a/libpod/container_attach_linux.go b/libpod/container_attach_linux.go
index 3ff6ddc76..7e9b7697b 100644
--- a/libpod/container_attach_linux.go
+++ b/libpod/container_attach_linux.go
@@ -8,6 +8,7 @@ import (
"net"
"os"
"path/filepath"
+ "sync"
"github.com/containers/libpod/pkg/kubeutils"
"github.com/containers/libpod/utils"
@@ -31,7 +32,7 @@ const (
// Attach to the given container
// Does not check if state is appropriate
-func (c *Container) attach(streams *AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, startContainer bool) error {
+func (c *Container) attach(streams *AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, startContainer bool, wg *sync.WaitGroup) error {
if !streams.AttachOutput && !streams.AttachError && !streams.AttachInput {
return errors.Wrapf(ErrInvalidArg, "must provide at least one stream to attach to")
}
@@ -48,12 +49,17 @@ func (c *Container) attach(streams *AttachStreams, keys string, resize <-chan re
logrus.Debugf("Attaching to container %s", c.ID())
- return c.attachContainerSocket(resize, detachKeys, streams, startContainer)
+ return c.attachContainerSocket(resize, detachKeys, streams, startContainer, wg)
}
-// attachContainerSocket connects to the container's attach socket and deals with the IO
+// attachContainerSocket connects to the container's attach socket and deals with the IO.
+// wg is only required if startContainer is true
// TODO add a channel to allow interrupting
-func (c *Container) attachContainerSocket(resize <-chan remotecommand.TerminalSize, detachKeys []byte, streams *AttachStreams, startContainer bool) error {
+func (c *Container) attachContainerSocket(resize <-chan remotecommand.TerminalSize, detachKeys []byte, streams *AttachStreams, startContainer bool, wg *sync.WaitGroup) error {
+ if startContainer && wg == nil {
+ return errors.Wrapf(ErrInternal, "wait group not passed when startContainer set")
+ }
+
kubeutils.HandleResizing(resize, func(size remotecommand.TerminalSize) {
controlPath := filepath.Join(c.bundlePath(), "ctl")
controlFile, err := os.OpenFile(controlPath, unix.O_WRONLY, 0)
@@ -84,10 +90,13 @@ func (c *Container) attachContainerSocket(resize <-chan remotecommand.TerminalSi
}
defer conn.Close()
+ // If starting was requested, start the container and notify when that's
+ // done.
if startContainer {
if err := c.start(); err != nil {
return err
}
+ wg.Done()
}
receiveStdoutError := make(chan error)
diff --git a/libpod/container_attach_unsupported.go b/libpod/container_attach_unsupported.go
index 068652b29..9e8badeaf 100644
--- a/libpod/container_attach_unsupported.go
+++ b/libpod/container_attach_unsupported.go
@@ -3,9 +3,11 @@
package libpod
import (
+ "sync"
+
"k8s.io/client-go/tools/remotecommand"
)
-func (c *Container) attach(streams *AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, startContainer bool) error {
+func (c *Container) attach(streams *AttachStreams, keys string, resize <-chan remotecommand.TerminalSize, startContainer bool, wg *sync.WaitGroup) error {
return ErrNotImplemented
}
diff --git a/libpod/events/events.go b/libpod/events/events.go
index 650a47bfb..1ec79bcd7 100644
--- a/libpod/events/events.go
+++ b/libpod/events/events.go
@@ -10,6 +10,10 @@ import (
"github.com/pkg/errors"
)
+// ErrNoJournaldLogging indicates that there is no journald logging
+// supported (requires libsystemd)
+var ErrNoJournaldLogging = errors.New("No support for journald logging")
+
// String returns a string representation of EventerType
func (et EventerType) String() string {
if et == LogFile {
diff --git a/libpod/events/events_linux.go b/libpod/events/events_linux.go
index da5d7965e..11f309574 100644
--- a/libpod/events/events_linux.go
+++ b/libpod/events/events_linux.go
@@ -8,12 +8,14 @@ import (
)
// NewEventer creates an eventer based on the eventer type
-func NewEventer(options EventerOptions) (Eventer, error) {
- var eventer Eventer
+func NewEventer(options EventerOptions) (eventer Eventer, err error) {
logrus.Debugf("Initializing event backend %s", options.EventerType)
switch strings.ToUpper(options.EventerType) {
case strings.ToUpper(Journald.String()):
- eventer = EventJournalD{options}
+ eventer, err = newEventJournalD(options)
+ if err != nil {
+ return nil, errors.Wrapf(err, "eventer creation")
+ }
case strings.ToUpper(LogFile.String()):
eventer = EventLogFile{options}
default:
diff --git a/libpod/events/journal_linux.go b/libpod/events/journal_linux.go
index 8ba5bc2c7..78a630e9a 100644
--- a/libpod/events/journal_linux.go
+++ b/libpod/events/journal_linux.go
@@ -1,3 +1,5 @@
+// +build systemd
+
package events
import (
@@ -10,11 +12,19 @@ import (
"github.com/sirupsen/logrus"
)
+// DefaultEventerType is journald when systemd is available
+const DefaultEventerType = Journald
+
// EventJournalD is the journald implementation of an eventer
type EventJournalD struct {
options EventerOptions
}
+// newEventJournalD creates a new journald Eventer
+func newEventJournalD(options EventerOptions) (Eventer, error) {
+ return EventJournalD{options}, nil
+}
+
// Write to journald
func (e EventJournalD) Write(ee Event) error {
m := make(map[string]string)
diff --git a/libpod/events/journal_unsupported.go b/libpod/events/journal_unsupported.go
new file mode 100644
index 000000000..004efdab2
--- /dev/null
+++ b/libpod/events/journal_unsupported.go
@@ -0,0 +1,11 @@
+// +build !systemd
+
+package events
+
+// DefaultEventerType is logfile when systemd is not present
+const DefaultEventerType = LogFile
+
+// newEventJournalD always returns an error if libsystemd not found
+func newEventJournalD(options EventerOptions) (Eventer, error) {
+ return nil, ErrNoJournaldLogging
+}
diff --git a/libpod/healthcheck_linux.go b/libpod/healthcheck_linux.go
index 869605ea8..d47a3b7cd 100644
--- a/libpod/healthcheck_linux.go
+++ b/libpod/healthcheck_linux.go
@@ -4,6 +4,7 @@ import (
"fmt"
"os"
"os/exec"
+ "strings"
"github.com/coreos/go-systemd/dbus"
"github.com/pkg/errors"
@@ -61,7 +62,13 @@ func (c *Container) removeTimer() error {
return errors.Wrapf(err, "unable to get systemd connection to remove healthchecks")
}
defer conn.Close()
- serviceFile := fmt.Sprintf("%s.timer", c.ID())
- _, err = conn.StopUnit(serviceFile, "fail", nil)
+ timerFile := fmt.Sprintf("%s.timer", c.ID())
+ _, err = conn.StopUnit(timerFile, "fail", nil)
+
+ // We want to ignore errors where the timer unit has already been removed. The error
+ // return is generic so we have to check against the string in the error
+ if err != nil && strings.HasSuffix(err.Error(), ".timer not loaded.") {
+ return nil
+ }
return err
}
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go
index 2450bd6b1..b8a916de3 100644
--- a/libpod/networking_linux.go
+++ b/libpod/networking_linux.go
@@ -19,6 +19,7 @@ import (
"github.com/containers/libpod/pkg/firewall"
"github.com/containers/libpod/pkg/inspect"
"github.com/containers/libpod/pkg/netns"
+ "github.com/containers/libpod/pkg/rootless"
"github.com/cri-o/ocicni/pkg/ocicni"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -100,6 +101,9 @@ func (r *Runtime) configureNetNS(ctr *Container, ctrNS ns.NetNS) ([]*cnitypes.Re
// Create and configure a new network namespace for a container
func (r *Runtime) createNetNS(ctr *Container) (n ns.NetNS, q []*cnitypes.Result, err error) {
+ if rootless.IsRootless() {
+ return nil, nil, errors.New("cannot configure a new network namespace in rootless mode, only --network=slirp4netns is supported")
+ }
ctrNS, err := netns.NewNS()
if err != nil {
return nil, nil, errors.Wrapf(err, "error creating network namespace for container %s", ctr.ID())
diff --git a/libpod/runtime.go b/libpod/runtime.go
index e6b84014e..18e9dfeb3 100644
--- a/libpod/runtime.go
+++ b/libpod/runtime.go
@@ -304,7 +304,7 @@ func defaultRuntimeConfig() (RuntimeConfig, error) {
EnablePortReservation: true,
EnableLabeling: true,
NumLocks: 2048,
- EventsLogger: "journald",
+ EventsLogger: events.DefaultEventerType.String(),
}, nil
}
diff --git a/libpod/runtime_pod_linux.go b/libpod/runtime_pod_linux.go
index 456ad365f..124d0daf8 100644
--- a/libpod/runtime_pod_linux.go
+++ b/libpod/runtime_pod_linux.go
@@ -308,5 +308,15 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool)
// Mark pod invalid
p.valid = false
p.newPodEvent(events.Remove)
+
+ // Deallocate the pod lock
+ if err := p.lock.Free(); err != nil {
+ if removalErr == nil {
+ removalErr = errors.Wrapf(err, "error freeing pod %s lock", p.ID())
+ } else {
+ logrus.Errorf("Error freeing pod %s lock: %v", p.ID(), err)
+ }
+ }
+
return removalErr
}
diff --git a/test/e2e/checkpoint_test.go b/test/e2e/checkpoint_test.go
index 5b549755e..c2f5a592c 100644
--- a/test/e2e/checkpoint_test.go
+++ b/test/e2e/checkpoint_test.go
@@ -21,6 +21,7 @@ var _ = Describe("Podman checkpoint", func() {
)
BeforeEach(func() {
+ SkipIfRootless()
tempdir, err = CreateTempDirInTempDir()
if err != nil {
os.Exit(1)
@@ -41,11 +42,12 @@ var _ = Describe("Podman checkpoint", func() {
if !criu.CheckForCriu() {
Skip("CRIU is missing or too old.")
}
- // TODO: Remove the skip when the current CRIU SELinux problem is solved.
- // See: https://github.com/containers/libpod/issues/2334
+ // Only Fedora 29 and newer has a new enough selinux-policy and
+ // container-selinux package to support CRIU in correctly
+ // restoring threaded processes
hostInfo := podmanTest.Host
- if hostInfo.Distribution == "fedora" {
- Skip("Checkpointing containers on Fedora currently broken.")
+ if hostInfo.Distribution == "fedora" && hostInfo.Version < "29" {
+ Skip("Checkpoint/Restore with SELinux only works on Fedora >= 29")
}
})
diff --git a/test/e2e/cp_test.go b/test/e2e/cp_test.go
index 273668f35..1dfa8f50d 100644
--- a/test/e2e/cp_test.go
+++ b/test/e2e/cp_test.go
@@ -40,15 +40,11 @@ var _ = Describe("Podman cp", func() {
It("podman cp file", func() {
path, err := os.Getwd()
- if err != nil {
- os.Exit(1)
- }
+ Expect(err).To(BeNil())
filePath := filepath.Join(path, "cp_test.txt")
fromHostToContainer := []byte("copy from host to container")
err = ioutil.WriteFile(filePath, fromHostToContainer, 0644)
- if err != nil {
- os.Exit(1)
- }
+ Expect(err).To(BeNil())
session := podmanTest.Podman([]string{"create", ALPINE, "cat", "foo"})
session.WaitWithDefaultTimeout()
@@ -69,15 +65,12 @@ var _ = Describe("Podman cp", func() {
It("podman cp file to dir", func() {
path, err := os.Getwd()
- if err != nil {
- os.Exit(1)
- }
+ Expect(err).To(BeNil())
filePath := filepath.Join(path, "cp_test.txt")
fromHostToContainer := []byte("copy from host to container directory")
err = ioutil.WriteFile(filePath, fromHostToContainer, 0644)
- if err != nil {
- os.Exit(1)
- }
+ Expect(err).To(BeNil())
+
session := podmanTest.Podman([]string{"create", ALPINE, "ls", "foodir/"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
@@ -97,14 +90,10 @@ var _ = Describe("Podman cp", func() {
It("podman cp dir to dir", func() {
path, err := os.Getwd()
- if err != nil {
- os.Exit(1)
- }
+ Expect(err).To(BeNil())
testDirPath := filepath.Join(path, "TestDir")
err = os.Mkdir(testDirPath, 0777)
- if err != nil {
- os.Exit(1)
- }
+ Expect(err).To(BeNil())
session := podmanTest.Podman([]string{"create", ALPINE, "ls", "/foodir"})
session.WaitWithDefaultTimeout()
@@ -124,19 +113,13 @@ var _ = Describe("Podman cp", func() {
It("podman cp stdin/stdout", func() {
path, err := os.Getwd()
- if err != nil {
- os.Exit(1)
- }
+ Expect(err).To(BeNil())
testDirPath := filepath.Join(path, "TestDir")
err = os.Mkdir(testDirPath, 0777)
- if err != nil {
- os.Exit(1)
- }
+ Expect(err).To(BeNil())
cmd := exec.Command("tar", "-zcvf", "file.tar.gz", testDirPath)
_, err = cmd.Output()
- if err != nil {
- os.Exit(1)
- }
+ Expect(err).To(BeNil())
session := podmanTest.Podman([]string{"create", ALPINE, "ls", "foo"})
session.WaitWithDefaultTimeout()
diff --git a/test/e2e/info_test.go b/test/e2e/info_test.go
index ca4012dde..c960fb311 100644
--- a/test/e2e/info_test.go
+++ b/test/e2e/info_test.go
@@ -24,7 +24,6 @@ var _ = Describe("Podman Info", func() {
}
podmanTest = PodmanTestCreate(tempdir)
podmanTest.Setup()
- podmanTest.DelayForVarlink()
})
AfterEach(func() {
diff --git a/test/e2e/libpod_suite_remoteclient_test.go b/test/e2e/libpod_suite_remoteclient_test.go
index 05c355711..b7fd8537d 100644
--- a/test/e2e/libpod_suite_remoteclient_test.go
+++ b/test/e2e/libpod_suite_remoteclient_test.go
@@ -77,6 +77,7 @@ func (p *PodmanTestIntegration) StartVarlink() {
command.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
p.VarlinkCommand = command
p.VarlinkSession = command.Process
+ p.DelayForVarlink()
}
func (p *PodmanTestIntegration) StopVarlink() {
diff --git a/test/e2e/rootless_test.go b/test/e2e/rootless_test.go
deleted file mode 100644
index 51544ff8b..000000000
--- a/test/e2e/rootless_test.go
+++ /dev/null
@@ -1,312 +0,0 @@
-// +build !remoteclient
-
-package integration
-
-import (
- "fmt"
- "io/ioutil"
- "os"
- "os/exec"
- "path/filepath"
- "runtime"
- "strings"
- "syscall"
-
- . "github.com/containers/libpod/test/utils"
- . "github.com/onsi/ginkgo"
- . "github.com/onsi/gomega"
-)
-
-func canExec() bool {
- const nsGetParent = 0xb702
-
- u, err := os.Open("/proc/self/ns/user")
- if err != nil {
- return false
- }
- defer u.Close()
-
- _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, u.Fd(), uintptr(nsGetParent), 0)
- return errno != syscall.ENOTTY
-}
-
-var _ = Describe("Podman rootless", func() {
- var (
- tempdir string
- err error
- podmanTest *PodmanTestIntegration
- )
-
- BeforeEach(func() {
- SkipIfRootless()
- tempdir, err = CreateTempDirInTempDir()
- if err != nil {
- os.Exit(1)
- }
- podmanTest = PodmanTestCreate(tempdir)
- podmanTest.CgroupManager = "cgroupfs"
- podmanTest.StorageOptions = ROOTLESS_STORAGE_OPTIONS
- podmanTest.Setup()
- podmanTest.RestoreAllArtifacts()
- })
-
- AfterEach(func() {
- podmanTest.Cleanup()
- f := CurrentGinkgoTestDescription()
- processTestResult(f)
-
- })
-
- It("podman rootless help|version", func() {
- commands := []string{"help", "version"}
- for _, v := range commands {
- env := os.Environ()
- env = append(env, "USER=foo")
- cmd := podmanTest.PodmanAsUser([]string{v}, 1000, 1000, "", env)
- cmd.WaitWithDefaultTimeout()
- Expect(cmd.ExitCode()).To(Equal(0))
- }
- })
-
- chownFunc := func(p string, info os.FileInfo, err error) error {
- if err != nil {
- return err
- }
- return os.Lchown(p, 1000, 1000)
- }
-
- type rootlessCB func(test *PodmanTestIntegration, xdgRuntimeDir string, home string, mountPath string)
-
- runInRootlessContext := func(cb rootlessCB) {
- // Check if we can create an user namespace
- err := exec.Command("unshare", "-r", "echo", "hello").Run()
- if err != nil {
- Skip("User namespaces not supported.")
- }
- setup := podmanTest.Podman([]string{"create", ALPINE, "ls"})
- setup.WaitWithDefaultTimeout()
- Expect(setup.ExitCode()).To(Equal(0))
- cid := setup.OutputToString()
-
- mount := podmanTest.Podman([]string{"mount", cid})
- mount.WaitWithDefaultTimeout()
- Expect(mount.ExitCode()).To(Equal(0))
- mountPath := mount.OutputToString()
-
- err = filepath.Walk(tempdir, chownFunc)
- Expect(err).To(BeNil())
-
- tempdir, err := CreateTempDirInTempDir()
- Expect(err).To(BeNil())
- rootlessTest := PodmanTestCreate(tempdir)
- rootlessTest.CgroupManager = "cgroupfs"
- rootlessTest.StorageOptions = ROOTLESS_STORAGE_OPTIONS
- err = filepath.Walk(tempdir, chownFunc)
- Expect(err).To(BeNil())
-
- xdgRuntimeDir, err := ioutil.TempDir("/run", "")
- Expect(err).To(BeNil())
- defer os.RemoveAll(xdgRuntimeDir)
- err = filepath.Walk(xdgRuntimeDir, chownFunc)
- Expect(err).To(BeNil())
-
- home, err := CreateTempDirInTempDir()
- Expect(err).To(BeNil())
- err = filepath.Walk(home, chownFunc)
- Expect(err).To(BeNil())
-
- cb(rootlessTest, xdgRuntimeDir, home, mountPath)
-
- umount := podmanTest.Podman([]string{"umount", cid})
- umount.WaitWithDefaultTimeout()
- Expect(umount.ExitCode()).To(Equal(0))
- }
-
- It("podman rootless pod", func() {
- f := func(rootlessTest *PodmanTestIntegration, xdgRuntimeDir string, home string, mountPath string) {
- env := os.Environ()
- env = append(env, fmt.Sprintf("XDG_RUNTIME_DIR=%s", xdgRuntimeDir))
- env = append(env, fmt.Sprintf("HOME=%s", home))
- env = append(env, "USER=foo")
-
- cmd := rootlessTest.PodmanAsUser([]string{"pod", "create", "--infra=false"}, 1000, 1000, "", env)
- cmd.WaitWithDefaultTimeout()
- Expect(cmd.ExitCode()).To(Equal(0))
- podId := cmd.OutputToString()
-
- args := []string{"run", "--pod", podId, "--rootfs", mountPath, "echo", "hello"}
- cmd = rootlessTest.PodmanAsUser(args, 1000, 1000, "", env)
- cmd.WaitWithDefaultTimeout()
- Expect(cmd.ExitCode()).To(Equal(0))
- Expect(cmd.LineInOutputContains("hello")).To(BeTrue())
-
- args = []string{"pod", "top", podId}
- cmd = rootlessTest.PodmanAsUser(args, 1000, 1000, "", env)
- cmd.WaitWithDefaultTimeout()
- Expect(cmd.ExitCode()).To(Not(Equal(0)))
-
- args = []string{"run", "--pod", podId, "-d", "--rootfs", mountPath, "sleep", "100"}
- cmd = rootlessTest.PodmanAsUser(args, 1000, 1000, "", env)
- cmd.WaitWithDefaultTimeout()
- Expect(cmd.ExitCode()).To(Equal(0))
-
- args = []string{"pod", "top", podId}
- cmd = rootlessTest.PodmanAsUser(args, 1000, 1000, "", env)
- cmd.WaitWithDefaultTimeout()
- Expect(cmd.ExitCode()).To(Equal(0))
- }
- runInRootlessContext(f)
- })
-
- It("podman rootless search", func() {
- xdgRuntimeDir, err := ioutil.TempDir("/run", "")
- Expect(err).To(BeNil())
- defer os.RemoveAll(xdgRuntimeDir)
- err = filepath.Walk(xdgRuntimeDir, chownFunc)
- Expect(err).To(BeNil())
-
- home, err := CreateTempDirInTempDir()
- Expect(err).To(BeNil())
- err = filepath.Walk(home, chownFunc)
- Expect(err).To(BeNil())
-
- env := os.Environ()
- env = append(env, fmt.Sprintf("XDG_RUNTIME_DIR=%s", xdgRuntimeDir))
- env = append(env, fmt.Sprintf("HOME=%s", home))
- env = append(env, "USER=foo")
- cmd := podmanTest.PodmanAsUser([]string{"search", "docker.io/busybox"}, 1000, 1000, "", env)
- cmd.WaitWithDefaultTimeout()
- Expect(cmd.ExitCode()).To(Equal(0))
- })
-
- runRootlessHelper := func(args []string) {
- f := func(rootlessTest *PodmanTestIntegration, xdgRuntimeDir string, home string, mountPath string) {
- runtime.LockOSThread()
- defer runtime.UnlockOSThread()
- env := os.Environ()
- env = append(env, fmt.Sprintf("XDG_RUNTIME_DIR=%s", xdgRuntimeDir))
- env = append(env, fmt.Sprintf("HOME=%s", home))
- env = append(env, "USER=foo")
-
- allArgs := append([]string{"run"}, args...)
- allArgs = append(allArgs, "--rootfs", mountPath, "echo", "hello")
- cmd := rootlessTest.PodmanAsUser(allArgs, 1000, 1000, "", env)
- cmd.WaitWithDefaultTimeout()
- Expect(cmd.ExitCode()).To(Equal(0))
- Expect(cmd.LineInOutputContains("hello")).To(BeTrue())
-
- cmd = rootlessTest.PodmanAsUser([]string{"rm", "-l", "-f"}, 1000, 1000, "", env)
- cmd.WaitWithDefaultTimeout()
- Expect(cmd.ExitCode()).To(Equal(0))
-
- allArgs = append([]string{"run", "-d"}, args...)
- allArgs = append(allArgs, "--security-opt", "seccomp=unconfined", "--rootfs", mountPath, "top")
- cmd = rootlessTest.PodmanAsUser(allArgs, 1000, 1000, "", env)
- cmd.WaitWithDefaultTimeout()
- Expect(cmd.ExitCode()).To(Equal(0))
-
- cmd = rootlessTest.PodmanAsUser([]string{"restart", "-l", "-t", "0"}, 1000, 1000, "", env)
- cmd.WaitWithDefaultTimeout()
- Expect(cmd.ExitCode()).To(Equal(0))
-
- canUseExec := canExec()
-
- if canUseExec {
- cmd = rootlessTest.PodmanAsUser([]string{"top", "-l"}, 1000, 1000, "", env)
- cmd.WaitWithDefaultTimeout()
- Expect(cmd.ExitCode()).To(Equal(0))
- }
-
- cmd = rootlessTest.PodmanAsUser([]string{"rm", "-l", "-f"}, 1000, 1000, "", env)
- cmd.WaitWithDefaultTimeout()
- Expect(cmd.ExitCode()).To(Equal(0))
-
- allArgs = append([]string{"run", "-d"}, args...)
- allArgs = append(allArgs, "--security-opt", "seccomp=unconfined", "--rootfs", mountPath, "unshare", "-r", "unshare", "-r", "top")
- cmd = rootlessTest.PodmanAsUser(allArgs, 1000, 1000, "", env)
- cmd.WaitWithDefaultTimeout()
- Expect(cmd.ExitCode()).To(Equal(0))
-
- cmd = rootlessTest.PodmanAsUser([]string{"stop", "-l", "-t", "0"}, 1000, 1000, "", env)
- cmd.WaitWithDefaultTimeout()
- Expect(cmd.ExitCode()).To(Equal(0))
-
- cmd = rootlessTest.PodmanAsUser([]string{"inspect", "-l", "--type", "container", "--format", "{{ .State.Status }}"}, 1000, 1000, "", env)
- cmd.WaitWithDefaultTimeout()
- Expect(cmd.LineInOutputContains("exited")).To(BeTrue())
-
- cmd = rootlessTest.PodmanAsUser([]string{"start", "-l"}, 1000, 1000, "", env)
- cmd.WaitWithDefaultTimeout()
- Expect(cmd.ExitCode()).To(Equal(0))
-
- cmd = rootlessTest.PodmanAsUser([]string{"stop", "-l", "-t", "0"}, 1000, 1000, "", env)
- cmd.WaitWithDefaultTimeout()
- Expect(cmd.ExitCode()).To(Equal(0))
-
- cmd = rootlessTest.PodmanAsUser([]string{"start", "-l"}, 1000, 1000, "", env)
- cmd.WaitWithDefaultTimeout()
- Expect(cmd.ExitCode()).To(Equal(0))
-
- if len(args) == 0 {
- cmd = rootlessTest.PodmanAsUser([]string{"inspect", "-l"}, 1000, 1000, "", env)
- cmd.WaitWithDefaultTimeout()
- Expect(cmd.ExitCode()).To(Equal(0))
- data := cmd.InspectContainerToJSON()
- Expect(data[0].HostConfig.NetworkMode).To(ContainSubstring("slirp4netns"))
- }
-
- if !canUseExec {
- Skip("ioctl(NS_GET_PARENT) not supported.")
- }
-
- cmd = rootlessTest.PodmanAsUser([]string{"exec", "-l", "echo", "hello"}, 1000, 1000, "", env)
- cmd.WaitWithDefaultTimeout()
- Expect(cmd.ExitCode()).To(Equal(0))
- Expect(cmd.LineInOutputContains("hello")).To(BeTrue())
-
- cmd = rootlessTest.PodmanAsUser([]string{"ps", "-l", "-q"}, 1000, 1000, "", env)
- cmd.WaitWithDefaultTimeout()
- Expect(cmd.ExitCode()).To(Equal(0))
- cid := cmd.OutputToString()
-
- cmd = rootlessTest.PodmanAsUser([]string{"exec", "-l", "sh", "-c", "echo SeCreTMessage > /file"}, 1000, 1000, "", env)
- cmd.WaitWithDefaultTimeout()
- Expect(cmd.ExitCode()).To(Equal(0))
-
- cmd = rootlessTest.PodmanAsUser([]string{"export", "-o", "export.tar", cid}, 1000, 1000, home, env)
- cmd.WaitWithDefaultTimeout()
- content, err := ioutil.ReadFile(filepath.Join(home, "export.tar"))
- Expect(err).To(BeNil())
- Expect(strings.Contains(string(content), "SeCreTMessage")).To(BeTrue())
- }
- runInRootlessContext(f)
- }
-
- It("podman rootless rootfs", func() {
- runRootlessHelper([]string{})
- })
-
- It("podman rootless rootfs --net host", func() {
- runRootlessHelper([]string{"--net", "host"})
- })
-
- It("podman rootless rootfs --pid host", func() {
- runRootlessHelper([]string{"--pid", "host"})
- })
-
- It("podman rootless rootfs --privileged", func() {
- runRootlessHelper([]string{"--privileged"})
- })
-
- It("podman rootless rootfs --net host --privileged", func() {
- runRootlessHelper([]string{"--net", "host", "--privileged"})
- })
-
- It("podman rootless rootfs --uts host", func() {
- runRootlessHelper([]string{"--uts", "host"})
- })
-
- It("podman rootless rootfs --ipc host", func() {
- runRootlessHelper([]string{"--ipc", "host"})
- })
-})
diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go
index 0e1f0d865..f908fe154 100644
--- a/test/e2e/run_test.go
+++ b/test/e2e/run_test.go
@@ -12,6 +12,7 @@ import (
"time"
. "github.com/containers/libpod/test/utils"
+ "github.com/containers/storage/pkg/stringid"
"github.com/mrunalp/fileutils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@@ -106,6 +107,46 @@ var _ = Describe("Podman run", func() {
Expect(session.ExitCode()).To(Equal(0))
})
+ It("podman run a container with a --rootfs", func() {
+ rootfs := filepath.Join(tempdir, "rootfs")
+ uls := filepath.Join("/", "usr", "local", "share")
+ uniqueString := stringid.GenerateNonCryptoID()
+ testFilePath := filepath.Join(uls, uniqueString)
+ tarball := filepath.Join(tempdir, "rootfs.tar")
+
+ err := os.Mkdir(rootfs, 0770)
+ Expect(err).Should(BeNil())
+
+ // Change image in predictable way to validate export
+ csession := podmanTest.Podman([]string{"run", "--name", uniqueString, ALPINE,
+ "/bin/sh", "-c", fmt.Sprintf("echo %s > %s", uniqueString, testFilePath)})
+ csession.WaitWithDefaultTimeout()
+ Expect(csession.ExitCode()).To(Equal(0))
+
+ // Export from working container image guarantees working root
+ esession := podmanTest.Podman([]string{"export", "--output", tarball, uniqueString})
+ esession.WaitWithDefaultTimeout()
+ Expect(esession.ExitCode()).To(Equal(0))
+ Expect(tarball).Should(BeARegularFile())
+
+ // N/B: This will loose any extended attributes like SELinux types
+ fmt.Fprintf(os.Stderr, "Extracting container root tarball\n")
+ tarsession := SystemExec("tar", []string{"xf", tarball, "-C", rootfs})
+ Expect(tarsession.ExitCode()).To(Equal(0))
+ Expect(filepath.Join(rootfs, uls)).Should(BeADirectory())
+
+ // Other tests confirm SELinux types, just confirm --rootfs is working.
+ session := podmanTest.Podman([]string{"run", "-i", "--security-opt", "label=disable",
+ "--rootfs", rootfs, "cat", testFilePath})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ // Validate changes made in original container and export
+ stdoutLines := session.OutputToStringArray()
+ Expect(stdoutLines).Should(HaveLen(1))
+ Expect(stdoutLines[0]).Should(Equal(uniqueString))
+ })
+
It("podman run a container with --init", func() {
session := podmanTest.Podman([]string{"run", "--init", ALPINE, "ls"})
session.WaitWithDefaultTimeout()
diff --git a/test/e2e/unshare_test.go b/test/e2e/unshare_test.go
new file mode 100644
index 000000000..1e3f06a62
--- /dev/null
+++ b/test/e2e/unshare_test.go
@@ -0,0 +1,52 @@
+package integration
+
+import (
+ "os"
+
+ . "github.com/containers/libpod/test/utils"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+)
+
+var _ = Describe("Podman unshare", func() {
+ var (
+ tempdir string
+ err error
+ podmanTest *PodmanTestIntegration
+ )
+ BeforeEach(func() {
+ SkipIfRemote()
+ if _, err := os.Stat("/proc/self/uid_map"); err != nil {
+ Skip("User namespaces not supported.")
+ }
+
+ if os.Geteuid() == 0 {
+ Skip("Use unshare in rootless only")
+ }
+
+ tempdir, err = CreateTempDirInTempDir()
+ if err != nil {
+ os.Exit(1)
+ }
+ podmanTest = PodmanTestCreate(tempdir)
+ podmanTest.CgroupManager = "cgroupfs"
+ podmanTest.StorageOptions = ROOTLESS_STORAGE_OPTIONS
+ podmanTest.Setup()
+ podmanTest.RestoreAllArtifacts()
+ })
+
+ AfterEach(func() {
+ podmanTest.Cleanup()
+ f := CurrentGinkgoTestDescription()
+ processTestResult(f)
+ })
+
+ It("podman unshare", func() {
+ userNS, _ := os.Readlink("/proc/self/ns/user")
+ session := podmanTest.Podman([]string{"unshare", "readlink", "/proc/self/ns/user"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ ok, _ := session.GrepString(userNS)
+ Expect(ok).To(BeFalse())
+ })
+})
diff --git a/vendor.conf b/vendor.conf
index 2f7e36d85..0b1f13304 100644
--- a/vendor.conf
+++ b/vendor.conf
@@ -11,7 +11,7 @@ github.com/boltdb/bolt v1.3.1
# TODO: no release, can we find an alternative?
github.com/buger/goterm c206103e1f37c0c6c5c039706305ea2aa6e8ad3b
github.com/checkpoint-restore/go-criu v3.11
-github.com/containerd/cgroups 39b18af02c4120960f517a3a4c2588fabb61d02c
+github.com/containerd/cgroups 4994991857f9b0ae8dc439551e8bebdbb4bf66c1
github.com/containerd/continuity 004b46473808b3e7a4a3049c20e4376c91eb966d
github.com/containernetworking/cni v0.7.0-rc2
github.com/containernetworking/plugins v0.7.4
@@ -19,7 +19,7 @@ github.com/containers/image v1.5.1
github.com/vbauerster/mpb v3.3.4
github.com/mattn/go-isatty v0.0.4
github.com/VividCortex/ewma v1.1.1
-github.com/containers/storage v1.12.6
+github.com/containers/storage v1.12.7
github.com/containers/psgo v1.2.1
github.com/coreos/go-systemd v14
github.com/coreos/pkg v4
diff --git a/vendor/github.com/containerd/cgroups/cgroup.go b/vendor/github.com/containerd/cgroups/cgroup.go
index 03fcb9284..e3ef07651 100644
--- a/vendor/github.com/containerd/cgroups/cgroup.go
+++ b/vendor/github.com/containerd/cgroups/cgroup.go
@@ -30,24 +30,49 @@ import (
)
// New returns a new control via the cgroup cgroups interface
-func New(hierarchy Hierarchy, path Path, resources *specs.LinuxResources) (Cgroup, error) {
+func New(hierarchy Hierarchy, path Path, resources *specs.LinuxResources, opts ...InitOpts) (Cgroup, error) {
+ config := newInitConfig()
+ for _, o := range opts {
+ if err := o(config); err != nil {
+ return nil, err
+ }
+ }
subsystems, err := hierarchy()
if err != nil {
return nil, err
}
+ var active []Subsystem
for _, s := range subsystems {
+ // check if subsystem exists
if err := initializeSubsystem(s, path, resources); err != nil {
+ if err == ErrControllerNotActive {
+ if config.InitCheck != nil {
+ if skerr := config.InitCheck(s, path, err); skerr != nil {
+ if skerr != ErrIgnoreSubsystem {
+ return nil, skerr
+ }
+ }
+ }
+ continue
+ }
return nil, err
}
+ active = append(active, s)
}
return &cgroup{
path: path,
- subsystems: subsystems,
+ subsystems: active,
}, nil
}
// Load will load an existing cgroup and allow it to be controlled
-func Load(hierarchy Hierarchy, path Path) (Cgroup, error) {
+func Load(hierarchy Hierarchy, path Path, opts ...InitOpts) (Cgroup, error) {
+ config := newInitConfig()
+ for _, o := range opts {
+ if err := o(config); err != nil {
+ return nil, err
+ }
+ }
var activeSubsystems []Subsystem
subsystems, err := hierarchy()
if err != nil {
@@ -60,6 +85,16 @@ func Load(hierarchy Hierarchy, path Path) (Cgroup, error) {
if os.IsNotExist(errors.Cause(err)) {
return nil, ErrCgroupDeleted
}
+ if err == ErrControllerNotActive {
+ if config.InitCheck != nil {
+ if skerr := config.InitCheck(s, path, err); skerr != nil {
+ if skerr != ErrIgnoreSubsystem {
+ return nil, skerr
+ }
+ }
+ }
+ continue
+ }
return nil, err
}
if _, err := os.Lstat(s.Path(p)); err != nil {
@@ -70,6 +105,10 @@ func Load(hierarchy Hierarchy, path Path) (Cgroup, error) {
}
activeSubsystems = append(activeSubsystems, s)
}
+ // if we do not have any active systems then the cgroup is deleted
+ if len(activeSubsystems) == 0 {
+ return nil, ErrCgroupDeleted
+ }
return &cgroup{
path: path,
subsystems: activeSubsystems,
diff --git a/vendor/github.com/containerd/cgroups/opts.go b/vendor/github.com/containerd/cgroups/opts.go
new file mode 100644
index 000000000..7c5d9fb9c
--- /dev/null
+++ b/vendor/github.com/containerd/cgroups/opts.go
@@ -0,0 +1,61 @@
+/*
+ Copyright The containerd Authors.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+package cgroups
+
+import (
+ "github.com/pkg/errors"
+)
+
+var (
+ // ErrIgnoreSubsystem allows the specific subsystem to be skipped
+ ErrIgnoreSubsystem = errors.New("skip subsystem")
+ // ErrDevicesRequired is returned when the devices subsystem is required but
+ // does not exist or is not active
+ ErrDevicesRequired = errors.New("devices subsystem is required")
+)
+
+// InitOpts allows configuration for the creation or loading of a cgroup
+type InitOpts func(*InitConfig) error
+
+// InitConfig provides configuration options for the creation
+// or loading of a cgroup and its subsystems
+type InitConfig struct {
+ // InitCheck can be used to check initialization errors from the subsystem
+ InitCheck InitCheck
+}
+
+func newInitConfig() *InitConfig {
+ return &InitConfig{
+ InitCheck: RequireDevices,
+ }
+}
+
+// InitCheck allows subsystems errors to be checked when initialized or loaded
+type InitCheck func(Subsystem, Path, error) error
+
+// AllowAny allows any subsystem errors to be skipped
+func AllowAny(s Subsystem, p Path, err error) error {
+ return ErrIgnoreSubsystem
+}
+
+// RequireDevices requires the device subsystem but no others
+func RequireDevices(s Subsystem, p Path, err error) error {
+ if s.Name() == Devices {
+ return ErrDevicesRequired
+ }
+ return ErrIgnoreSubsystem
+}
diff --git a/vendor/github.com/containerd/cgroups/paths.go b/vendor/github.com/containerd/cgroups/paths.go
index 455ce857f..f45fd4256 100644
--- a/vendor/github.com/containerd/cgroups/paths.go
+++ b/vendor/github.com/containerd/cgroups/paths.go
@@ -57,6 +57,9 @@ func PidPath(pid int) Path {
return existingPath(paths, "")
}
+// ErrControllerNotActive is returned when a controller is not supported or enabled
+var ErrControllerNotActive = errors.New("controller is not supported")
+
func existingPath(paths map[string]string, suffix string) Path {
// localize the paths based on the root mount dest for nested cgroups
for n, p := range paths {
@@ -77,7 +80,7 @@ func existingPath(paths map[string]string, suffix string) Path {
root, ok := paths[string(name)]
if !ok {
if root, ok = paths[fmt.Sprintf("name=%s", name)]; !ok {
- return "", fmt.Errorf("unable to find %q in controller set", name)
+ return "", ErrControllerNotActive
}
}
if suffix != "" {
diff --git a/vendor/github.com/containers/storage/layers.go b/vendor/github.com/containers/storage/layers.go
index 7bec0aea6..a35dd476b 100644
--- a/vendor/github.com/containers/storage/layers.go
+++ b/vendor/github.com/containers/storage/layers.go
@@ -402,12 +402,10 @@ func (r *layerStore) Save() error {
if err != nil {
return err
}
+ defer r.Touch()
if err := ioutils.AtomicWriteFile(rpath, jldata, 0600); err != nil {
return err
}
- if !r.IsReadWrite() {
- return nil
- }
r.mountsLockfile.Lock()
defer r.mountsLockfile.Unlock()
defer r.mountsLockfile.Touch()
diff --git a/vendor/github.com/containers/storage/layers_ffjson.go b/vendor/github.com/containers/storage/layers_ffjson.go
index 125b5d8c9..09b5d0f33 100644
--- a/vendor/github.com/containers/storage/layers_ffjson.go
+++ b/vendor/github.com/containers/storage/layers_ffjson.go
@@ -1,5 +1,5 @@
// Code generated by ffjson <https://github.com/pquerna/ffjson>. DO NOT EDIT.
-// source: layers.go
+// source: ./layers.go
package storage
diff --git a/vendor/github.com/containers/storage/store.go b/vendor/github.com/containers/storage/store.go
index 27b00f6fe..9b967db6d 100644
--- a/vendor/github.com/containers/storage/store.go
+++ b/vendor/github.com/containers/storage/store.go
@@ -1197,18 +1197,20 @@ func (s *store) CreateContainer(id string, names []string, image, layer, metadat
}
imageID = cimage.ID
- createMappedLayer := imageHomeStore == istore
+ if cimage.TopLayer != "" {
+ createMappedLayer := imageHomeStore == istore
+ ilayer, err := s.imageTopLayerForMapping(cimage, imageHomeStore, createMappedLayer, rlstore, lstores, idMappingsOptions)
+ if err != nil {
+ return nil, err
+ }
+ imageTopLayer = ilayer
- ilayer, err := s.imageTopLayerForMapping(cimage, imageHomeStore, createMappedLayer, rlstore, lstores, idMappingsOptions)
- if err != nil {
- return nil, err
- }
- imageTopLayer = ilayer
- if !options.HostUIDMapping && len(options.UIDMap) == 0 {
- uidMap = ilayer.UIDMap
- }
- if !options.HostGIDMapping && len(options.GIDMap) == 0 {
- gidMap = ilayer.GIDMap
+ if !options.HostUIDMapping && len(options.UIDMap) == 0 {
+ uidMap = ilayer.UIDMap
+ }
+ if !options.HostGIDMapping && len(options.GIDMap) == 0 {
+ gidMap = ilayer.GIDMap
+ }
}
} else {
rlstore.Lock()
diff --git a/version/version.go b/version/version.go
index c63f8b820..a917931b7 100644
--- a/version/version.go
+++ b/version/version.go
@@ -4,7 +4,7 @@ package version
// NOTE: remember to bump the version at the top
// of the top-level README.md file when this is
// bumped.
-const Version = "1.3.1-dev"
+const Version = "1.3.2-dev"
// RemoteAPIVersion is the version for the remote
// client API. It is used to determine compatibility