summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml3
-rw-r--r--.copr/Makefile2
-rw-r--r--.copr/prepare.sh4
-rw-r--r--Dockerfile8
-rw-r--r--Dockerfile.centos9
-rw-r--r--Dockerfile.fedora9
-rw-r--r--Makefile11
-rw-r--r--OWNERS2
-rw-r--r--README.md6
-rw-r--r--RELEASE_NOTES.md3
-rw-r--r--changelog.txt45
-rw-r--r--cmd/podman/info.go10
-rw-r--r--cmd/podman/libpodruntime/runtime.go6
-rw-r--r--cmd/podman/runlabel.go2
-rw-r--r--cmd/podman/shared/create_cli.go7
-rw-r--r--cmd/podman/version.go2
-rw-r--r--contrib/cirrus/lib.sh12
-rw-r--r--contrib/cirrus/required_host_ports.txt4
-rw-r--r--contrib/spec/podman.spec.in19
-rw-r--r--docs/libpod.conf.5.md2
-rw-r--r--install.md10
-rw-r--r--libpod/container_api.go2
-rw-r--r--libpod/container_commit.go2
-rw-r--r--libpod/networking_linux.go4
-rw-r--r--libpod/util.go73
-rw-r--r--pkg/adapter/client.go50
-rw-r--r--pkg/adapter/client_config.go32
-rw-r--r--pkg/adapter/runtime.go5
-rw-r--r--pkg/hooks/0.1.0/hook.go2
-rw-r--r--pkg/spec/spec.go14
-rw-r--r--pkg/util/utils_supported.go24
-rw-r--r--pkg/util/utils_windows.go5
-rw-r--r--test/e2e/commit_test.go20
-rw-r--r--test/e2e/rootless_test.go312
-rw-r--r--test/e2e/run_test.go41
-rw-r--r--transfer.md2
-rw-r--r--vendor.conf2
-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
41 files changed, 345 insertions, 453 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index d26c1ec11..fe09ea988 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -123,6 +123,9 @@ gating_task:
timeout_in: 20m
+ networking_script: # Don't bother going further if something is down
+ - 'while read host port; do nc -zv -w 13 $host $port || exit 1; done < ${CIRRUS_WORKING_DIR}/${SCRIPT_BASE}/required_host_ports.txt'
+
gate_script:
# N/B: entrypoint.sh resets $GOSRC (same as make clean)
- '/usr/local/bin/entrypoint.sh install.tools |& ${TIMESTAMP}'
diff --git a/.copr/Makefile b/.copr/Makefile
index 05d9eb592..71142920b 100644
--- a/.copr/Makefile
+++ b/.copr/Makefile
@@ -16,4 +16,4 @@ build_binary:
clean:
rm -fr rpms
- rm -fr cri-o
+ rm -fr conmon
diff --git a/.copr/prepare.sh b/.copr/prepare.sh
index 1ad29da36..a40e2aadb 100644
--- a/.copr/prepare.sh
+++ b/.copr/prepare.sh
@@ -28,5 +28,5 @@ fi
mkdir build/
git archive --prefix "libpod-${COMMIT_SHORT}/" --format "tar.gz" HEAD -o "build/libpod-${COMMIT_SHORT}.tar.gz"
-git clone https://github.com/kubernetes-incubator/cri-o
-cd cri-o && git checkout 4cd5a7c60349be0678d9f1b0657683324c1a2726 && git archive --prefix "crio/" --format "tar.gz" HEAD -o "../build/crio.tar.gz"
+git clone https://github.com/containers/conmon
+cd conmon && git checkout f02c053eb37010fc76d1e2966de7f2cb9f969ef2 && git archive --prefix "conmon/" --format "tar.gz" HEAD -o "../build/conmon.tar.gz"
diff --git a/Dockerfile b/Dockerfile
index 767e64570..f3afd5e25 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -56,13 +56,13 @@ RUN set -x \
&& rm -rf "$GOPATH"
# Install conmon
-ENV CRIO_COMMIT 7a283c391abb7bd25086a8ff91dbb36ebdd24466
+ENV CONMON_COMMIT f02c053eb37010fc76d1e2966de7f2cb9f969ef2
RUN set -x \
&& export GOPATH="$(mktemp -d)" \
- && git clone https://github.com/kubernetes-sigs/cri-o.git "$GOPATH/src/github.com/kubernetes-sigs/cri-o.git" \
- && cd "$GOPATH/src/github.com/kubernetes-sigs/cri-o.git" \
+ && git clone https://github.com/containers/conmon.git "$GOPATH/src/github.com/containers/conmon.git" \
+ && cd "$GOPATH/src/github.com/containers/conmon.git" \
&& git fetch origin --tags \
- && git checkout -q "$CRIO_COMMIT" \
+ && git checkout -q "$CONMON_COMMIT" \
&& make \
&& install -D -m 755 bin/conmon /usr/libexec/podman/conmon \
&& rm -rf "$GOPATH"
diff --git a/Dockerfile.centos b/Dockerfile.centos
index 605dc9df4..47f7182b6 100644
--- a/Dockerfile.centos
+++ b/Dockerfile.centos
@@ -64,15 +64,14 @@ RUN set -x \
&& install -D -m 755 "$GOPATH"/bin/easyjson /usr/bin/
# Install conmon
-ENV CRIO_COMMIT 7a283c391abb7bd25086a8ff91dbb36ebdd24466
+ENV CONMON_COMMIT f02c053eb37010fc76d1e2966de7f2cb9f969ef2
RUN set -x \
&& export GOPATH="$(mktemp -d)" \
- && git clone https://github.com/kubernetes-sigs/cri-o.git "$GOPATH/src/github.com/kubernetes-sigs/cri-o.git" \
- && cd "$GOPATH/src/github.com/kubernetes-sigs/cri-o.git" \
+ && git clone https://github.com/containers/conmon.git "$GOPATH/src/github.com/containers/conmon.git" \
+ && cd "$GOPATH/src/github.com/containers/conmon.git" \
&& git fetch origin --tags \
- && git checkout -q "$CRIO_COMMIT" \
+ && git checkout -q "$CONMON_COMMIT" \
&& make \
- && make bin/conmon \
&& install -D -m 755 bin/conmon /usr/libexec/podman/conmon \
&& rm -rf "$GOPATH"
diff --git a/Dockerfile.fedora b/Dockerfile.fedora
index d4bcc11ea..290fe3f82 100644
--- a/Dockerfile.fedora
+++ b/Dockerfile.fedora
@@ -68,15 +68,14 @@ RUN set -x \
&& install -D -m 755 "$GOPATH"/bin/easyjson /usr/bin/
# Install conmon
-ENV CRIO_COMMIT 7a283c391abb7bd25086a8ff91dbb36ebdd24466
+ENV CONMON_COMMIT f02c053eb37010fc76d1e2966de7f2cb9f969ef2
RUN set -x \
&& export GOPATH="$(mktemp -d)" \
- && git clone https://github.com/kubernetes-sigs/cri-o.git "$GOPATH/src/github.com/kubernetes-sigs/cri-o.git" \
- && cd "$GOPATH/src/github.com/kubernetes-sigs/cri-o.git" \
+ && git clone https://github.com/containers/conmon.git "$GOPATH/src/github.com/containers/conmon.git" \
+ && cd "$GOPATH/src/github.com/containers/conmon.git" \
&& git fetch origin --tags \
- && git checkout -q "$CRIO_COMMIT" \
+ && git checkout -q "$CONMON_COMMIT" \
&& make \
- && make bin/conmon \
&& install -D -m 755 bin/conmon /usr/libexec/podman/conmon \
&& rm -rf "$GOPATH"
diff --git a/Makefile b/Makefile
index 10de8ad4e..c7c3a0d17 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
@@ -259,14 +259,17 @@ changelog: ## Generate changelog
$(shell cat $(TMPFILE) >> changelog.txt)
$(shell rm $(TMPFILE))
-install: .gopathok install.bin install.man install.cni install.systemd ## Install binaries to system locations
+install: .gopathok install.bin install.remote install.man install.cni install.systemd ## Install binaries to system locations
+
+install.remote:
+ install ${SELINUXOPT} -d -m 755 $(BINDIR)
+ install ${SELINUXOPT} -m 755 bin/podman-remote $(BINDIR)/podman-remote
+ test -z "${SELINUXOPT}" || chcon --verbose --reference=$(BINDIR)/podman bin/podman-remote
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/OWNERS b/OWNERS
index a03622b2e..227c97d6a 100644
--- a/OWNERS
+++ b/OWNERS
@@ -7,6 +7,7 @@ approvers:
- umohnani8
- giuseppe
- vrothberg
+ - jwhonce
reviewers:
- mheon
- baude
@@ -16,3 +17,4 @@ reviewers:
- umohnani8
- giuseppe
- vrothberg
+ - jwhonce
diff --git a/README.md b/README.md
index 3abe27fcf..820ce7dc8 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
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
@@ -44,7 +44,7 @@ Any recent Podman release should be able to run rootless without any additional
* Specializing in signing and pushing images to various storage backends.
See [Skopeo](https://github.com/containers/skopeo/) for those tasks.
* Container runtimes daemons for working with the Kubernetes CRI interface.
- [CRI-O](https://github.com/kubernetes-sigs/cri-o) specializes in that.
+ [CRI-O](https://github.com/cri-o/cri-o) specializes in that.
* Supporting `docker-compose`. We believe that Kubernetes is the defacto
standard for composing Pods and for orchestrating containers, making
Kubernetes YAML a defacto standard file format. Hence, Podman allows the
@@ -67,7 +67,7 @@ The plan is to use OCI projects and best of breed libraries for different aspect
- Storage: Container and image storage is managed by [containers/storage](https://github.com/containers/storage)
- Networking: Networking support through use of [CNI](https://github.com/containernetworking/cni)
- Builds: Builds are supported via [Buildah](https://github.com/containers/buildah).
-- Conmon: [Conmon](https://github.com/kubernetes-sigs/cri-o) is a tool for monitoring OCI runtimes. It is part of the CRI-O package
+- Conmon: [Conmon](https://github.com/containers/conmon) is a tool for monitoring OCI runtimes.
## Podman Information for Developers
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index b41714d45..5eb85d0bc 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -4,6 +4,7 @@
### 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))
@@ -22,7 +23,7 @@
## 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/info.go b/cmd/podman/info.go
index a6fce7fcb..823303354 100644
--- a/cmd/podman/info.go
+++ b/cmd/podman/info.go
@@ -10,6 +10,7 @@ import (
"github.com/containers/libpod/pkg/adapter"
"github.com/containers/libpod/version"
"github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
@@ -60,7 +61,16 @@ func infoCmd(c *cliconfig.InfoValues) error {
if err != nil {
return errors.Wrapf(err, "error getting info")
}
+
if runtime.Remote {
+ endpoint, err := runtime.RemoteEndpoint()
+ if err != nil {
+ logrus.Errorf("Failed to obtain server connection: %s", err.Error())
+ } else {
+ remoteClientInfo["Connection"] = endpoint.Connection
+ remoteClientInfo["Connection Type"] = endpoint.Type.String()
+ }
+
remoteClientInfo["RemoteAPI Version"] = version.RemoteAPIVersion
remoteClientInfo["Podman Version"] = version.Version
remoteClientInfo["OS Arch"] = fmt.Sprintf("%s/%s", rt.GOOS, rt.GOARCH)
diff --git a/cmd/podman/libpodruntime/runtime.go b/cmd/podman/libpodruntime/runtime.go
index b533dc056..b8d77602d 100644
--- a/cmd/podman/libpodruntime/runtime.go
+++ b/cmd/podman/libpodruntime/runtime.go
@@ -107,7 +107,11 @@ func getRuntime(ctx context.Context, c *cliconfig.PodmanCommand, renumber bool,
if c.Flags().Changed("cgroup-manager") {
options = append(options, libpod.WithCgroupManager(c.GlobalFlags.CGroupManager))
} else {
- if rootless.IsRootless() {
+ unified, err := util.IsCgroup2UnifiedMode()
+ if err != nil {
+ return nil, err
+ }
+ if rootless.IsRootless() && !unified {
options = append(options, libpod.WithCgroupManager("cgroupfs"))
}
}
diff --git a/cmd/podman/runlabel.go b/cmd/podman/runlabel.go
index c426817de..e87b88992 100644
--- a/cmd/podman/runlabel.go
+++ b/cmd/podman/runlabel.go
@@ -152,7 +152,7 @@ func runlabelCmd(c *cliconfig.RunlabelValues) error {
return err
}
if !c.Quiet {
- fmt.Printf("command: %s\n", strings.Join(cmd, " "))
+ fmt.Printf("command: %s\n", strings.Join(append([]string{os.Args[0]}, cmd[1:]...), " "))
if c.Display {
return nil
}
diff --git a/cmd/podman/shared/create_cli.go b/cmd/podman/shared/create_cli.go
index f731e8db5..7f158b09a 100644
--- a/cmd/podman/shared/create_cli.go
+++ b/cmd/podman/shared/create_cli.go
@@ -7,6 +7,7 @@ import (
"github.com/containers/libpod/cmd/podman/shared/parse"
cc "github.com/containers/libpod/pkg/spec"
"github.com/containers/libpod/pkg/sysinfo"
+ "github.com/containers/libpod/pkg/util"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -76,6 +77,12 @@ func addWarning(warnings []string, msg string) []string {
func verifyContainerResources(config *cc.CreateConfig, update bool) ([]string, error) {
warnings := []string{}
+
+ cgroup2, err := util.IsCgroup2UnifiedMode()
+ if err != nil || cgroup2 {
+ return warnings, err
+ }
+
sysInfo := sysinfo.New(true)
// memory subsystem checks and adjustments
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/contrib/cirrus/lib.sh b/contrib/cirrus/lib.sh
index f422fe935..a285b133b 100644
--- a/contrib/cirrus/lib.sh
+++ b/contrib/cirrus/lib.sh
@@ -283,16 +283,16 @@ install_buildah() {
ooe.sh sudo make install
}
-# Requires $GOPATH and $CRIO_COMMIT to be set
+# Requires $GOPATH and $CONMON_COMMIT to be set
install_conmon(){
- echo "Installing conmon from commit $CRIO_COMMIT"
- req_env_var GOPATH CRIO_COMMIT
- DEST="$GOPATH/src/github.com/kubernetes-sigs/cri-o.git"
+ echo "Installing conmon from commit $CONMON_COMMIT"
+ req_env_var GOPATH CONMON_COMMIT
+ DEST="$GOPATH/src/github.com/containers/conmon.git"
rm -rf "$DEST"
- ooe.sh git clone https://github.com/kubernetes-sigs/cri-o.git "$DEST"
+ ooe.sh git clone https://github.com/containers/conmon.git "$DEST"
cd "$DEST"
ooe.sh git fetch origin --tags
- ooe.sh git checkout -q "$CRIO_COMMIT"
+ ooe.sh git checkout -q "$CONMON_COMMIT"
ooe.sh make
sudo install -D -m 755 bin/conmon /usr/libexec/podman/conmon
}
diff --git a/contrib/cirrus/required_host_ports.txt b/contrib/cirrus/required_host_ports.txt
new file mode 100644
index 000000000..9248e497a
--- /dev/null
+++ b/contrib/cirrus/required_host_ports.txt
@@ -0,0 +1,4 @@
+github.com 22
+docker.io 443
+quay.io 443
+registry.fedoraproject.org 443
diff --git a/contrib/spec/podman.spec.in b/contrib/spec/podman.spec.in
index 29c786ca6..985dbbc74 100644
--- a/contrib/spec/podman.spec.in
+++ b/contrib/spec/podman.spec.in
@@ -33,19 +33,19 @@
%global shortcommit0 %(c=%{commit0}; echo ${c:0:8})
# People want conmon packaged with the copr rpm
-%global import_path_conmon github.com/kubernetes-sigs/cri-o
+%global import_path_conmon github.com/containers/conmon
%global git_conmon https://%{import_path_conmon}
-%global commit_conmon 4cd5a7c60349be0678d9f1b0657683324c1a2726
+%global commit_conmon f02c053eb37010fc76d1e2966de7f2cb9f969ef2
%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
URL: %{git_podman}
Source0: %{git0}/archive/%{commit0}/%{repo}-%{shortcommit0}.tar.gz
-Source1: crio.tar.gz
+Source1: conmon.tar.gz
# e.g. el6 has ppc64 arch without gcc-go, so EA tag is required
#ExclusiveArch: %%{?go_arches:%%{go_arches}}%%{!?go_arches:%%{ix86} x86_64 aarch64 %%{arm}}
ExclusiveArch: aarch64 %{arm} ppc64le s390x x86_64
@@ -371,24 +371,23 @@ GOPATH=$GOPATH go generate ./cmd/podman/varlink/...
BUILDTAGS=$BUILDTAGS make binaries docs
# build conmon
-pushd crio
+pushd conmon
mkdir _output
pushd _output
-mkdir -p src/%{provider}.%{provider_tld}/{kubernetes-sigs,opencontainers}
+mkdir -p src/%{provider}.%{provider_tld}/{containers,opencontainers}
ln -s $(dirs +1 -l) src/%{import_path_conmon}
popd
-ln -s vendor src
-export GOPATH=$(pwd)/_output:$(pwd):%{gopath}
export BUILDTAGS="selinux seccomp $(hack/btrfs_installed_tag.sh) $(hack/btrfs_tag.sh) containers_image_ostree_stub"
-BUILDTAGS=$BUILDTAGS make -C conmon
+BUILDTAGS=$BUILDTAGS make
popd
%install
install -dp %{buildroot}%{_unitdir}
PODMAN_VERSION=%{version} %{__make} PREFIX=%{buildroot}%{_prefix} ETCDIR=%{buildroot}%{_sysconfdir} \
install.bin \
+ install.remote \
install.man \
install.cni \
install.systemd \
@@ -402,7 +401,7 @@ install -p -m 644 %{repo}.conf %{buildroot}%{_datadir}/containers
# install conmon
install -dp %{buildroot}%{_libexecdir}/%{name}
-install -p -m 755 crio/bin/conmon %{buildroot}%{_libexecdir}/%{name}
+install -p -m 755 conmon/bin/conmon %{buildroot}%{_libexecdir}/%{name}
# source codes for building projects
%if 0%{?with_devel}
diff --git a/docs/libpod.conf.5.md b/docs/libpod.conf.5.md
index 2f0b3f303..cb08f0eb0 100644
--- a/docs/libpod.conf.5.md
+++ b/docs/libpod.conf.5.md
@@ -34,7 +34,7 @@ libpod to manage containers.
Each `*.json` file in the path configures a hook for Podman containers. For more details on the syntax of the JSON files and the semantics of hook injection, see `oci-hooks(5)`. Podman and libpod currently support both the 1.0.0 and 0.1.0 hook schemas, although the 0.1.0 schema is deprecated.
- Paths listed later in the array higher precedence (`oci-hooks(5)` discusses directory precedence).
+ Paths listed later in the array have higher precedence (`oci-hooks(5)` discusses directory precedence).
For the annotation conditions, libpod uses any annotations set in the generated OCI configuration.
diff --git a/install.md b/install.md
index 82dd4c36a..ae74acdf8 100644
--- a/install.md
+++ b/install.md
@@ -91,7 +91,6 @@ Fedora, CentOS, RHEL, and related distributions:
sudo yum install -y \
atomic-registries \
btrfs-progs-devel \
- conmon \
containernetworking-cni \
device-mapper-devel \
git \
@@ -188,13 +187,12 @@ export PATH=$GOPATH/bin:$PATH
#### conmon
The latest version of `conmon` is expected to be installed on the system. Conmon is used to monitor OCI Runtimes.
-To build from source, use the following (if not already executed above, run `export GOPATH=~/go && mkdir -p $GOPATH`):
+To build from source, use the following:
```bash
-git clone https://github.com/cri-o/cri-o $GOPATH/src/github.com/cri-o/cri-o
-cd $GOPATH/src/github.com/cri-o/cri-o
-mkdir bin
-make bin/conmon
+git clone https://github.com/containers/conmon
+cd conmon
+make
sudo install -D -m 755 bin/conmon /usr/libexec/podman/conmon
```
diff --git a/libpod/container_api.go b/libpod/container_api.go
index 06a31da11..eff5bfe5f 100644
--- a/libpod/container_api.go
+++ b/libpod/container_api.go
@@ -289,8 +289,8 @@ func (c *Container) Exec(tty, privileged bool, env, cmd []string, user, workDir
chWait := make(chan error)
go func() {
chWait <- execCmd.Wait()
+ close(chWait)
}()
- defer close(chWait)
pidFile := c.execPidPath(sessionID)
// 60 second seems a reasonable time to wait
diff --git a/libpod/container_commit.go b/libpod/container_commit.go
index ae04f67bb..739fcd80e 100644
--- a/libpod/container_commit.go
+++ b/libpod/container_commit.go
@@ -99,7 +99,7 @@ func (c *Container) Commit(ctx context.Context, destImage string, options Contai
// Should we store the ENV we actually want in the spec separately?
if c.config.Spec.Process != nil {
for _, e := range c.config.Spec.Process.Env {
- splitEnv := strings.Split(e, "=")
+ splitEnv := strings.SplitN(e, "=", 2)
importBuilder.SetEnv(splitEnv[0], splitEnv[1])
}
}
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/util.go b/libpod/util.go
index 7e2dff21a..3a15f9e39 100644
--- a/libpod/util.go
+++ b/libpod/util.go
@@ -90,11 +90,7 @@ func MountExists(specMounts []spec.Mount, dest string) bool {
// WaitForFile waits until a file has been created or the given timeout has occurred
func WaitForFile(path string, chWait chan error, timeout time.Duration) (bool, error) {
- done := make(chan struct{})
- chControl := make(chan struct{})
-
var inotifyEvents chan fsnotify.Event
- var timer chan struct{}
watcher, err := fsnotify.NewWatcher()
if err == nil {
if err := watcher.Add(filepath.Dir(path)); err == nil {
@@ -102,51 +98,36 @@ func WaitForFile(path string, chWait chan error, timeout time.Duration) (bool, e
}
defer watcher.Close()
}
- if inotifyEvents == nil {
- // If for any reason we fail to create the inotify
- // watcher, fallback to polling the file
- timer = make(chan struct{})
- go func() {
- select {
- case <-chControl:
- close(timer)
- return
- default:
- time.Sleep(25 * time.Millisecond)
- timer <- struct{}{}
- }
- }()
- }
- go func() {
- for {
- select {
- case <-chControl:
- return
- case <-timer:
- _, err := os.Stat(path)
- if err == nil {
- close(done)
- return
- }
- case <-inotifyEvents:
- _, err := os.Stat(path)
- if err == nil {
- close(done)
- return
- }
+ timeoutChan := time.After(timeout)
+
+ for {
+ select {
+ case e := <-chWait:
+ return true, e
+ case <-inotifyEvents:
+ _, err := os.Stat(path)
+ if err == nil {
+ return false, nil
+ }
+ if !os.IsNotExist(err) {
+ return false, errors.Wrapf(err, "checking file %s", path)
+ }
+ case <-time.After(25 * time.Millisecond):
+ // Check periodically for the file existence. It is needed
+ // if the inotify watcher could not have been created. It is
+ // also useful when using inotify as if for any reasons we missed
+ // a notification, we won't hang the process.
+ _, err := os.Stat(path)
+ if err == nil {
+ return false, nil
+ }
+ if !os.IsNotExist(err) {
+ return false, errors.Wrapf(err, "checking file %s", path)
}
+ case <-timeoutChan:
+ return false, errors.Wrapf(ErrInternal, "timed out waiting for file %s", path)
}
- }()
-
- select {
- case e := <-chWait:
- return true, e
- case <-done:
- return false, nil
- case <-time.After(timeout):
- close(chControl)
- return false, errors.Wrapf(ErrInternal, "timed out waiting for file %s", path)
}
}
diff --git a/pkg/adapter/client.go b/pkg/adapter/client.go
index f672a92a6..01914834f 100644
--- a/pkg/adapter/client.go
+++ b/pkg/adapter/client.go
@@ -10,44 +10,56 @@ import (
"github.com/varlink/go/varlink"
)
-type VarlinkConnectionInfo struct {
- RemoteUserName string
- RemoteHost string
- VarlinkAddress string
-}
-
-// Connect provides a varlink connection
-func (r RemoteRuntime) Connect() (*varlink.Connection, error) {
- var (
- err error
- connection *varlink.Connection
- )
+var remoteEndpoint *Endpoint
- logLevel := r.cmd.LogLevel
+func (r RemoteRuntime) RemoteEndpoint() (remoteEndpoint *Endpoint, err error) {
+ if remoteEndpoint == nil {
+ remoteEndpoint = &Endpoint{Unknown, ""}
+ } else {
+ return remoteEndpoint, nil
+ }
// I'm leaving this here for now as a document of the birdge format. It can be removed later once the bridge
// function is more flushed out.
- //bridge := `ssh -T root@192.168.122.1 "/usr/bin/varlink -A '/usr/bin/podman varlink \$VARLINK_ADDRESS' bridge"`
+ // bridge := `ssh -T root@192.168.122.1 "/usr/bin/varlink -A '/usr/bin/podman varlink \$VARLINK_ADDRESS' bridge"`
if len(r.cmd.RemoteHost) > 0 {
// The user has provided a remote host endpoint
if len(r.cmd.RemoteUserName) < 1 {
return nil, errors.New("you must provide a username when providing a remote host name")
}
- bridge := fmt.Sprintf(`ssh -T %s@%s /usr/bin/varlink -A \'/usr/bin/podman --log-level=%s varlink \\\$VARLINK_ADDRESS\' bridge`, r.cmd.RemoteUserName, r.cmd.RemoteHost, logLevel)
- connection, err = varlink.NewBridge(bridge)
+ remoteEndpoint.Type = BridgeConnection
+ remoteEndpoint.Connection = fmt.Sprintf(
+ `ssh -T %s@%s /usr/bin/varlink -A \'/usr/bin/podman --log-level=%s varlink \\\$VARLINK_ADDRESS\' bridge`,
+ r.cmd.RemoteUserName, r.cmd.RemoteHost, r.cmd.LogLevel)
+
} else if bridge := os.Getenv("PODMAN_VARLINK_BRIDGE"); bridge != "" {
- connection, err = varlink.NewBridge(bridge)
+ remoteEndpoint.Type = BridgeConnection
+ remoteEndpoint.Connection = bridge
} else {
address := os.Getenv("PODMAN_VARLINK_ADDRESS")
if address == "" {
address = DefaultAddress
}
- connection, err = varlink.NewConnection(address)
+ remoteEndpoint.Type = DirectConnection
+ remoteEndpoint.Connection = address
}
+ return
+}
+
+// Connect provides a varlink connection
+func (r RemoteRuntime) Connect() (*varlink.Connection, error) {
+ ep, err := r.RemoteEndpoint()
if err != nil {
return nil, err
}
- return connection, nil
+
+ switch ep.Type {
+ case DirectConnection:
+ return varlink.NewConnection(ep.Connection)
+ case BridgeConnection:
+ return varlink.NewBridge(ep.Connection)
+ }
+ return nil, errors.New(fmt.Sprintf("Unable to determine type of varlink connection: %s", ep.Connection))
}
// RefreshConnection is used to replace the current r.Conn after things like
diff --git a/pkg/adapter/client_config.go b/pkg/adapter/client_config.go
index d165ef1cc..3559b16e3 100644
--- a/pkg/adapter/client_config.go
+++ b/pkg/adapter/client_config.go
@@ -2,3 +2,35 @@ package adapter
// DefaultAddress is the default address of the varlink socket
const DefaultAddress = "unix:/run/podman/io.podman"
+
+// EndpointType declares the type of server connection
+type EndpointType int
+
+// Enum of connection types
+const (
+ Unknown = iota - 1 // Unknown connection type
+ BridgeConnection // BridgeConnection proxy connection via ssh
+ DirectConnection // DirectConnection socket connection to server
+)
+
+// String prints ASCII string for EndpointType
+func (e EndpointType) String() string {
+ // declare an array of strings
+ // ... operator counts how many
+ // items in the array (7)
+ names := [...]string{
+ "BridgeConnection",
+ "DirectConnection",
+ }
+
+ if e < BridgeConnection || e > DirectConnection {
+ return "Unknown"
+ }
+ return names[e]
+}
+
+// Endpoint type and connection string to use
+type Endpoint struct {
+ Type EndpointType
+ Connection string
+}
diff --git a/pkg/adapter/runtime.go b/pkg/adapter/runtime.go
index 21613c425..37ee1b737 100644
--- a/pkg/adapter/runtime.go
+++ b/pkg/adapter/runtime.go
@@ -398,3 +398,8 @@ func (r *LocalRuntime) GetPodsByStatus(statuses []string) ([]*libpod.Pod, error)
func (r *LocalRuntime) GetVersion() (libpod.Version, error) {
return libpod.GetVersion()
}
+
+// RemoteEndpoint resolve interface requirement
+func (r *LocalRuntime) RemoteEndpoint() (*Endpoint, error) {
+ return nil, errors.New("RemoteEndpoint() not implemented for local connection")
+}
diff --git a/pkg/hooks/0.1.0/hook.go b/pkg/hooks/0.1.0/hook.go
index 49d833aa8..ba68b0f10 100644
--- a/pkg/hooks/0.1.0/hook.go
+++ b/pkg/hooks/0.1.0/hook.go
@@ -19,7 +19,7 @@ type Hook struct {
Hook *string `json:"hook"`
Arguments []string `json:"arguments,omitempty"`
- // https://github.com/kubernetes-sigs/cri-o/pull/1235
+ // https://github.com/cri-o/cri-o/pull/1235
Stages []string `json:"stages"`
Stage []string `json:"stage"`
diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go
index 20c649f9a..df303db6d 100644
--- a/pkg/spec/spec.go
+++ b/pkg/spec/spec.go
@@ -7,6 +7,7 @@ import (
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/rootless"
+ "github.com/containers/libpod/pkg/util"
pmount "github.com/containers/storage/pkg/mount"
"github.com/docker/docker/oci/caps"
"github.com/docker/go-units"
@@ -267,7 +268,9 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
// SECURITY OPTS
g.SetProcessNoNewPrivileges(config.NoNewPrivs)
- g.SetProcessApparmorProfile(config.ApparmorProfile)
+ if !config.Privileged {
+ g.SetProcessApparmorProfile(config.ApparmorProfile)
+ }
blockAccessToKernelFilesystems(config, &g)
@@ -347,10 +350,13 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM
}
if rootless.IsRootless() {
- if addedResources {
- return nil, errors.New("invalid configuration, cannot set resources with rootless containers")
+ cgroup2, err := util.IsCgroup2UnifiedMode()
+ if err != nil {
+ return nil, err
+ }
+ if addedResources && !cgroup2 {
+ return nil, errors.New("invalid configuration, cannot set resources with rootless containers not using cgroups v2 unified mode")
}
- configSpec.Linux.Resources = &spec.LinuxResources{}
}
// Make sure that the bind mounts keep options like nosuid, noexec, nodev.
diff --git a/pkg/util/utils_supported.go b/pkg/util/utils_supported.go
index af5e67fc1..8b98658c2 100644
--- a/pkg/util/utils_supported.go
+++ b/pkg/util/utils_supported.go
@@ -11,9 +11,33 @@ import (
"github.com/pkg/errors"
"os"
"path/filepath"
+ "sync"
"syscall"
)
+const (
+ _cgroup2SuperMagic = 0x63677270
+)
+
+var (
+ isUnifiedOnce sync.Once
+ isUnified bool
+ isUnifiedErr error
+)
+
+// IsCgroup2UnifiedMode returns whether we are running in cgroup 2 unified mode.
+func IsCgroup2UnifiedMode() (bool, error) {
+ isUnifiedOnce.Do(func() {
+ var st syscall.Statfs_t
+ if err := syscall.Statfs("/sys/fs/cgroup", &st); err != nil {
+ isUnified, isUnifiedErr = false, err
+ } else {
+ isUnified, isUnifiedErr = st.Type == _cgroup2SuperMagic, nil
+ }
+ })
+ return isUnified, isUnifiedErr
+}
+
// GetRootlessRuntimeDir returns the runtime directory when running as non root
func GetRootlessRuntimeDir() (string, error) {
var rootlessRuntimeDirError error
diff --git a/pkg/util/utils_windows.go b/pkg/util/utils_windows.go
index 1e9ccea90..b33733da9 100644
--- a/pkg/util/utils_windows.go
+++ b/pkg/util/utils_windows.go
@@ -10,3 +10,8 @@ import (
func GetRootlessRuntimeDir() (string, error) {
return "", errors.New("this function is not implemented for windows")
}
+
+// IsCgroup2UnifiedMode returns whether we are running in cgroup 2 unified mode.
+func IsCgroup2UnifiedMode() (bool, error) {
+ return false, errors.New("this function is not implemented for windows")
+}
diff --git a/test/e2e/commit_test.go b/test/e2e/commit_test.go
index 3ece4887e..bf20ac999 100644
--- a/test/e2e/commit_test.go
+++ b/test/e2e/commit_test.go
@@ -194,4 +194,24 @@ var _ = Describe("Podman commit", func() {
Expect(r.ExitCode()).To(Equal(0))
})
+ It("podman commit container check env variables", func() {
+ s := podmanTest.Podman([]string{"run", "--name", "test1", "-e", "TEST=1=1-01=9.01", "-it", "alpine", "true"})
+ s.WaitWithDefaultTimeout()
+ Expect(s.ExitCode()).To(Equal(0))
+
+ c := podmanTest.Podman([]string{"commit", "test1", "newimage"})
+ c.WaitWithDefaultTimeout()
+ Expect(c.ExitCode()).To(Equal(0))
+
+ inspect := podmanTest.Podman([]string{"inspect", "newimage"})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect.ExitCode()).To(Equal(0))
+ image := inspect.InspectImageJSON()
+
+ envMap := make(map[string]bool)
+ for _, v := range image[0].Config.Env {
+ envMap[v] = true
+ }
+ Expect(envMap["TEST=1=1-01=9.01"]).To(BeTrue())
+ })
})
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/transfer.md b/transfer.md
index df91cdf21..79b6d3461 100644
--- a/transfer.md
+++ b/transfer.md
@@ -98,7 +98,7 @@ Those Docker commands currently do not have equivalents in `podman`:
| `docker secret` ||
| `docker service` ||
| `docker stack` ||
-| `docker swarm` | podman does not support swarm. We support Kubernetes for orchestration using [CRI-O](https://github.com/kubernetes-sigs/cri-o).|
+| `docker swarm` | podman does not support swarm. We support Kubernetes for orchestration using [CRI-O](https://github.com/cri-o/cri-o).|
| `docker volume` | podman currently supports file volumes. Future enhancement planned to support Docker Volumes Plugins
## Missing commands in Docker
diff --git a/vendor.conf b/vendor.conf
index b71e947dc..0b1f13304 100644
--- a/vendor.conf
+++ b/vendor.conf
@@ -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/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