summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cirrus.yml75
-rw-r--r--.gitignore3
-rw-r--r--Makefile107
-rw-r--r--README.md3
-rw-r--r--cmd/podman/cliconfig/config.go1
-rw-r--r--cmd/podman/main_local.go10
-rw-r--r--cmd/podman/sign.go19
-rw-r--r--completions/bash/podman1
-rw-r--r--contrib/cirrus/99-do-not-use-google-subnets.conflist21
-rwxr-xr-xcontrib/cirrus/build_release.sh30
-rwxr-xr-xcontrib/cirrus/cache_release_archive.sh140
-rwxr-xr-xcontrib/cirrus/cirrus_yaml_test.py43
-rw-r--r--contrib/cirrus/git_authors_to_irc_nicks.csv12
-rwxr-xr-xcontrib/cirrus/integration_test.sh4
-rw-r--r--contrib/cirrus/lib.sh25
-rwxr-xr-xcontrib/cirrus/setup_environment.sh10
-rwxr-xr-xcontrib/cirrus/success.sh51
l---------contrib/cirrus/uncache_release_archives.sh1
-rwxr-xr-xcontrib/cirrus/unit_test.sh4
-rwxr-xr-xcontrib/cirrus/upload_release_archive.sh52
-rwxr-xr-xcontrib/imgprune/entrypoint.sh14
-rw-r--r--contrib/imgts/lib_entrypoint.sh15
-rw-r--r--contrib/upldrel/Dockerfile9
-rw-r--r--contrib/upldrel/README.md9
-rwxr-xr-xcontrib/upldrel/entrypoint.sh62
-rw-r--r--docs/links/podman-container-umount.12
-rw-r--r--docs/links/podman-container-unmount.12
-rw-r--r--docs/links/podman-image-rm.12
-rw-r--r--docs/podman-attach.1.md2
-rw-r--r--docs/podman-build.1.md2
-rw-r--r--docs/podman-commit.1.md2
-rw-r--r--docs/podman-container-cleanup.1.md2
-rw-r--r--docs/podman-container-prune.1.md2
-rw-r--r--docs/podman-container-restore.1.md2
-rw-r--r--docs/podman-container-runlabel.1.md4
-rw-r--r--docs/podman-container.1.md4
-rw-r--r--docs/podman-cp.1.md2
-rw-r--r--docs/podman-create.1.md2
-rw-r--r--docs/podman-diff.1.md2
-rw-r--r--docs/podman-exec.1.md2
-rw-r--r--docs/podman-export.1.md2
-rw-r--r--docs/podman-generate-kube.1.md2
-rw-r--r--docs/podman-generate-systemd.1.md2
-rw-r--r--docs/podman-history.1.md2
-rw-r--r--docs/podman-image-prune.1.md2
-rw-r--r--docs/podman-image-sign.1.md15
-rw-r--r--docs/podman-image-trust.1.md2
-rw-r--r--docs/podman-image.1.md4
-rw-r--r--docs/podman-images.1.md4
-rw-r--r--docs/podman-import.1.md2
-rw-r--r--docs/podman-info.1.md4
-rw-r--r--docs/podman-init.1.md2
-rw-r--r--docs/podman-kill.1.md4
-rw-r--r--docs/podman-load.1.md2
-rw-r--r--docs/podman-logs.1.md6
-rw-r--r--docs/podman-mount.1.md4
-rw-r--r--docs/podman-network-inspect.1.md2
-rw-r--r--docs/podman-network-ls.1.md2
-rw-r--r--docs/podman-network-rm.1.md2
-rw-r--r--docs/podman-network.1.md2
-rw-r--r--docs/podman-pause.1.md2
-rw-r--r--docs/podman-play-kube.1.md2
-rw-r--r--docs/podman-play.1.md2
-rw-r--r--docs/podman-pod-kill.1.md2
-rw-r--r--docs/podman-pod-stats.1.md2
-rw-r--r--docs/podman-pod.1.md34
-rw-r--r--docs/podman-port.1.md2
-rw-r--r--docs/podman-ps.1.md10
-rw-r--r--docs/podman-pull.1.md2
-rw-r--r--docs/podman-push.1.md2
-rw-r--r--docs/podman-restart.1.md2
-rw-r--r--docs/podman-rm.1.md6
-rw-r--r--docs/podman-rmi.1.md6
-rw-r--r--docs/podman-run.1.md2
-rw-r--r--docs/podman-save.1.md2
-rw-r--r--docs/podman-start.1.md2
-rw-r--r--docs/podman-stats.1.md4
-rw-r--r--docs/podman-stop.1.md4
-rw-r--r--docs/podman-system-migrate.1.md2
-rw-r--r--docs/podman-system-renumber.1.md2
-rw-r--r--docs/podman-system.1.md2
-rw-r--r--docs/podman-tag.1.md1
-rw-r--r--docs/podman-top.1.md2
-rw-r--r--docs/podman-umount.1.md8
-rw-r--r--docs/podman-unpause.1.md2
-rw-r--r--docs/podman-unshare.1.md4
-rw-r--r--docs/podman-version.1.md2
-rw-r--r--docs/podman-volume-inspect.1.md2
-rw-r--r--docs/podman-volume-ls.1.md2
-rw-r--r--docs/podman-volume.1.md2
-rw-r--r--docs/podman-wait.1.md2
-rw-r--r--docs/podman.1.md10
-rw-r--r--docs/tutorials/rootless_tutorial.md30
-rwxr-xr-xhack/get_release_info.sh54
-rwxr-xr-xhack/man-page-checker5
-rw-r--r--libpod/container_api.go36
-rw-r--r--libpod/container_internal_linux.go30
-rw-r--r--libpod/util.go6
-rw-r--r--pkg/rootless/rootless_linux.go139
-rw-r--r--pkg/rootless/rootless_unsupported.go12
-rw-r--r--pkg/spec/config_linux.go75
-rw-r--r--pkg/util/utils.go16
-rw-r--r--pkg/varlinkapi/images.go2
-rw-r--r--test/e2e/run_device_test.go16
-rw-r--r--test/endpoint/commit.go47
-rw-r--r--test/endpoint/endpoint.go5
-rw-r--r--test/endpoint/exists_test.go2
-rw-r--r--troubleshooting.md19
-rw-r--r--vendor/k8s.io/apimachinery/pkg/util/wait/doc.go19
-rw-r--r--vendor/k8s.io/apimachinery/pkg/util/wait/wait.go504
-rw-r--r--vendor/modules.txt1
111 files changed, 983 insertions, 988 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index f49b1d312..d41828d5d 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -62,6 +62,10 @@ env:
GCE_SSH_USERNAME: cirrus-ci
# Name where this repositories cloud resources are located
GCP_PROJECT_ID: ENCRYPTED[7c80e728e046b1c76147afd156a32c1c57d4a1ac1eab93b7e68e718c61ca8564fc61fef815952b8ae0a64e7034b8fe4f]
+ RELEASE_GCPJSON: ENCRYPTED[789d8f7e9a5972ce350fd8e60f1032ccbf4a35c3938b604774b711aad280e12c21faf10e25af1e0ba33597ffb9e39e46]
+ RELEASE_GCPNAME: ENCRYPTED[417d50488a4bd197bcc925ba6574de5823b97e68db1a17e3a5fde4bcf26576987345e75f8d9ea1c15a156b4612c072a1]
+ RELEASE_GCPROJECT: ENCRYPTED[7c80e728e046b1c76147afd156a32c1c57d4a1ac1eab93b7e68e718c61ca8564fc61fef815952b8ae0a64e7034b8fe4f]
+
# Default VM to use unless set or modified by task
@@ -107,6 +111,7 @@ gating_task:
build_script:
- '/usr/local/bin/entrypoint.sh podman |& ${TIMESTAMP}'
- 'cd $GOSRC && ./hack/podman-commands.sh |& ${TIMESTAMP}'
+ - 'cd $GOSRC && ./hack/man-page-checker |& ${TIMESTAMP}'
# N/B: need 'clean' so some commited files are re-generated.
- '/usr/local/bin/entrypoint.sh clean podman-remote |& ${TIMESTAMP}'
- '/usr/local/bin/entrypoint.sh clean podman BUILDTAGS="exclude_graphdriver_devicemapper selinux seccomp" |& ${TIMESTAMP}'
@@ -295,11 +300,9 @@ image_prune_task:
memory: 1
env:
- # order is significant, Cirrus not always overriding alias values as intended
+ <<: *meta_env_vars
GCPJSON: ENCRYPTED[4c11d8e09c904c30fc70eecb95c73dec0ddf19976f9b981a0f80f3f6599e8f990bcef93c253ac0277f200850d98528e7]
GCPNAME: ENCRYPTED[7f54557ba6e5a437f11283a53e71baec9ca546f48a9835538cc54d297f79968eb1337d4596a1025b14f9d1c5723fbd29]
- GCPPROJECT: ENCRYPTED[7c80e728e046b1c76147afd156a32c1c57d4a1ac1eab93b7e68e718c61ca8564fc61fef815952b8ae0a64e7034b8fe4f]
- <<: *meta_env_vars
timeout_in: 10m
@@ -339,9 +342,8 @@ testing_task:
unit_test_script: '$SCRIPT_BASE/unit_test.sh |& ${TIMESTAMP}'
integration_test_script: '$SCRIPT_BASE/integration_test.sh |& ${TIMESTAMP}'
system_test_script: '$SCRIPT_BASE/system_test.sh |& ${TIMESTAMP}'
- cache_release_archive_script: >-
- [[ "$TEST_REMOTE_CLIENT" == "false" ]] || \
- $SCRIPT_BASE/cache_release_archive.sh |& ${TIMESTAMP}
+ build_release_script: '$SCRIPT_BASE/build_release.sh |& ${TIMESTAMP}'
+ upload_release_archive_script: '$SCRIPT_BASE/upload_release_archive.sh |& ${TIMESTAMP}'
on_failure:
failed_branch_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_branch_failure.sh'
@@ -379,9 +381,6 @@ testing_crun_task:
unit_test_script: '$SCRIPT_BASE/unit_test.sh |& ${TIMESTAMP}'
integration_test_script: '$SCRIPT_BASE/integration_test.sh |& ${TIMESTAMP}'
system_test_script: '$SCRIPT_BASE/system_test.sh |& ${TIMESTAMP}'
- cache_release_archive_script: >-
- [[ "$TEST_REMOTE_CLIENT" == "false" ]] || \
- $SCRIPT_BASE/cache_release_archive.sh |& ${TIMESTAMP}
on_failure:
failed_branch_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_branch_failure.sh'
@@ -462,14 +461,15 @@ special_testing_cross_task:
env:
matrix:
- SPECIALMODE: 'windows' # See docs
- SPECIALMODE: 'darwin'
+ CROSS_PLATFORM: 'windows'
+ CROSS_PLATFORM: 'darwin'
timeout_in: 20m
networking_script: '${CIRRUS_WORKING_DIR}/${SCRIPT_BASE}/networking.sh'
setup_environment_script: '$SCRIPT_BASE/setup_environment.sh |& ${TIMESTAMP}'
- cache_release_archive_script: '$SCRIPT_BASE/cache_release_archive.sh |& ${TIMESTAMP}'
+ build_release_script: '$SCRIPT_BASE/build_release.sh |& ${TIMESTAMP}'
+ upload_release_archive_script: '$SCRIPT_BASE/upload_release_archive.sh |& ${TIMESTAMP}'
on_failure:
failed_branch_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_branch_failure.sh'
@@ -618,6 +618,9 @@ verify_test_built_images_task:
integration_test_script: >-
[[ "$PACKER_BUILDER_NAME" == "xfedora-30" ]] || \
$SCRIPT_BASE/integration_test.sh |& ${TIMESTAMP}
+ build_release_script: >-
+ [[ "$PACKER_BUILDER_NAME" == "xfedora-30" ]] || \
+ '$SCRIPT_BASE/build_release.sh |& ${TIMESTAMP}'
system_test_script: >-
[[ "$PACKER_BUILDER_NAME" == "xfedora-30" ]] || \
$SCRIPT_BASE/system_test.sh |& ${TIMESTAMP}
@@ -632,7 +635,7 @@ success_task:
# it blocks PRs from merging if a depends_on task fails
only_if: $CIRRUS_BRANCH != $DEST_BRANCH
- # ignores any dependent task conditions, include everything except 'release'
+ # ignores any dependent task conditions
depends_on:
- "gating"
- "vendor"
@@ -663,49 +666,3 @@ success_task:
memory: 1
success_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/success.sh |& ${TIMESTAMP}'
-
-
-release_task:
-
- # Never do this when building images
- only_if: $CIRRUS_CHANGE_MESSAGE !=~ '.*\*\*\*\s*CIRRUS:\s*TEST\s*IMAGES\s*\*\*\*.*'
-
- # TODO: Uncomment both to not affect pass/fail status of entire job?
- # allow_failures: $CI == "true"
- # skip_notifications: $CI == "true"
-
- # Must include everything (YAML anchor/alias cannot be used here)
- depends_on:
- - "gating"
- - "vendor"
- - "varlink_api"
- - "build_each_commit"
- - "build_without_cgo"
- - "meta"
- - "image_prune"
- - "testing"
- - "testing_crun"
- - "special_testing_rootless"
- - "special_testing_in_podman"
- - "special_testing_cgroupv2"
- - "special_testing_cross"
- - "special_testing_endpoint"
- - "test_build_cache_images"
- - "test_building_snap"
- - "verify_test_built_images"
- - "success"
-
- gce_instance:
- image_name: "${IMAGE_BUILDER_CACHE_IMAGE_NAME}"
-
- timeout_in: 30m
-
- env:
- GCPJSON: ENCRYPTED[789d8f7e9a5972ce350fd8e60f1032ccbf4a35c3938b604774b711aad280e12c21faf10e25af1e0ba33597ffb9e39e46]
- GCPNAME: ENCRYPTED[417d50488a4bd197bcc925ba6574de5823b97e68db1a17e3a5fde4bcf26576987345e75f8d9ea1c15a156b4612c072a1]
- GCPROJECT: ENCRYPTED[7c80e728e046b1c76147afd156a32c1c57d4a1ac1eab93b7e68e718c61ca8564fc61fef815952b8ae0a64e7034b8fe4f]
-
- uncache_release_archives_script: '$SCRIPT_BASE/uncache_release_archives.sh |& ${TIMESTAMP}'
-
- on_failure:
- failed_branch_script: '$CIRRUS_WORKING_DIR/$SCRIPT_BASE/notice_branch_failure.sh'
diff --git a/.gitignore b/.gitignore
index 2d984cb5a..d3e56ecdf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,6 +20,7 @@ __pycache__
/cmd/podman/varlink/iopodman.go
.gopathok
test/e2e/e2e.coverprofile
-/podman*zip
+release.txt
+podman-remote*.zip
podman*.tar.gz
.idea*
diff --git a/Makefile b/Makefile
index 82a24306d..4f51adb67 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,5 @@
export GO111MODULE=off
+export GOPROXY=https://proxy.golang.org
GO ?= go
DESTDIR ?=
@@ -81,13 +82,12 @@ LIBSECCOMP_COMMIT := release-2.3
# caller may override in special circumstances if needed.
GINKGOTIMEOUT ?= -timeout=90m
-RELEASE_VERSION ?= $(shell git fetch --tags && git describe HEAD 2> /dev/null)
-RELEASE_NUMBER ?= $(shell echo $(RELEASE_VERSION) | sed 's/-.*//')
-RELEASE_DIST ?= $(shell ( source /etc/os-release; echo $$ID ))
-RELEASE_DIST_VER ?= $(shell ( source /etc/os-release; echo $$VERSION_ID | cut -d '.' -f 1))
-RELEASE_ARCH ?= $(shell go env GOARCH 2> /dev/null)
-RELEASE_BASENAME := $(shell basename $(PROJECT))
-
+RELEASE_VERSION ?= $(shell hack/get_release_info.sh VERSION)
+RELEASE_NUMBER ?= $(shell hack/get_release_info.sh NUMBER)
+RELEASE_DIST ?= $(shell hack/get_release_info.sh DIST)
+RELEASE_DIST_VER ?= $(shell hack/get_release_info.sh DIST_VER)
+RELEASE_ARCH ?= $(shell hack/get_release_info.sh ARCH)
+RELEASE_BASENAME := $(shell hack/get_release_info.sh BASENAME)
# If GOPATH not specified, use one in the local directory
ifeq ($(GOPATH),)
@@ -164,11 +164,9 @@ podman: .gopathok $(PODMAN_VARLINK_DEPENDENCIES) ## Build with podman
podman-remote: .gopathok $(PODMAN_VARLINK_DEPENDENCIES) ## Build with podman on remote environment
$(GO_BUILD) $(BUILDFLAGS) -gcflags '$(GCFLAGS)' -asmflags '$(ASMFLAGS)' -ldflags '$(LDFLAGS_PODMAN)' -tags "$(BUILDTAGS) remoteclient" -o bin/$@ $(PROJECT)/cmd/podman
-podman-remote-darwin: .gopathok $(PODMAN_VARLINK_DEPENDENCIES) ## Build with podman on remote OSX environment
- CGO_ENABLED=0 GOOS=darwin $(GO_BUILD) -gcflags '$(GCFLAGS)' -asmflags '$(ASMFLAGS)' -ldflags '$(LDFLAGS_PODMAN)' -tags "remoteclient containers_image_openpgp exclude_graphdriver_devicemapper" -o bin/$@ $(PROJECT)/cmd/podman
-
-podman-remote-windows: .gopathok $(PODMAN_VARLINK_DEPENDENCIES) ## Build with podman for a remote windows environment
- CGO_ENABLED=0 GOOS=windows $(GO_BUILD) -gcflags '$(GCFLAGS)' -asmflags '$(ASMFLAGS)' -ldflags '$(LDFLAGS_PODMAN)' -tags "remoteclient containers_image_openpgp exclude_graphdriver_devicemapper" -o bin/$@.exe $(PROJECT)/cmd/podman
+podman-remote-%: .gopathok $(PODMAN_VARLINK_DEPENDENCIES) ## Build podman for a specific GOOS
+ $(eval BINSFX := $(shell test "$*" != "windows" || echo ".exe"))
+ CGO_ENABLED=0 GOOS=$* $(GO_BUILD) -gcflags '$(GCFLAGS)' -asmflags '$(ASMFLAGS)' -ldflags '$(LDFLAGS_PODMAN)' -tags "remoteclient containers_image_openpgp exclude_graphdriver_devicemapper" -o bin/$@$(BINSFX) $(PROJECT)/cmd/podman
local-cross: $(CROSS_BUILD_TARGETS) ## Cross local compilation
@@ -182,8 +180,9 @@ clean: ## Clean artifacts
rm -rf \
.gopathok \
_output \
- podman*.zip \
- podman*.tar.gz \
+ release.txt
+ $(wildcard podman-remote*.zip) \
+ $(wildcard podman*.tar.gz) \
bin \
build \
docs/remote \
@@ -300,23 +299,6 @@ vagrant-check:
binaries: varlink_generate podman podman-remote ## Build podman
-# Zip archives are supported on all platforms + allows embedding metadata
-podman.zip: binaries docs
- $(eval TMPDIR := $(shell mktemp -d -p '' $@_XXXX))
- test -n "$(TMPDIR)"
- $(MAKE) install "DESTDIR=$(TMPDIR)" "PREFIX=$(TMPDIR)/usr"
- # Encoded RELEASE_INFO format depended upon by CI tooling
- # X-RELEASE-INFO format depended upon by CI tooling
- cd "$(TMPDIR)" && echo \
- "X-RELEASE-INFO: $(RELEASE_BASENAME) $(RELEASE_VERSION) $(RELEASE_DIST) $(RELEASE_DIST_VER) $(RELEASE_ARCH)" | \
- zip --recurse-paths --archive-comment "$(CURDIR)/$@" "./"
- -rm -rf "$(TMPDIR)"
-
-podman-remote-%.zip: podman-remote-%
- # Don't label darwin/windows cros-compiles with local distribution & version
- echo "X-RELEASE-INFO: podman-remote $(RELEASE_VERSION) $* cc $(RELEASE_ARCH)" | \
- zip --archive-comment "$(CURDIR)/$@" ./bin/$<*
-
install.catatonit:
./hack/install_catatonit.sh
@@ -333,19 +315,58 @@ docs: $(MANPAGES) ## Generate documentation
install-podman-remote-docs: docs
@(cd docs; ./podman-remote.sh ./remote)
+# When publishing releases include critical build-time details
+.PHONY: release.txt
+release.txt:
+ # X-RELEASE-INFO format depended upon by automated tooling
+ echo -n "X-RELEASE-INFO:" > "$@"
+ for field in "$(RELEASE_BASENAME)" "$(RELEASE_VERSION)" \
+ "$(RELEASE_DIST)" "$(RELEASE_DIST_VER)" "$(RELEASE_ARCH)"; do \
+ echo -n " $$field"; done >> "$@"
+ echo "" >> "$@"
+
+podman-$(RELEASE_NUMBER).tar.gz: binaries docs release.txt
+ $(eval TMPDIR := $(shell mktemp -d -p '' podman_XXXX))
+ $(eval SUBDIR := podman-$(RELEASE_NUMBER))
+ mkdir -p "$(TMPDIR)/$(SUBDIR)"
+ $(MAKE) install.bin install.man install.cni install.systemd "DESTDIR=$(TMPDIR)/$(SUBDIR)" "PREFIX=/usr"
+ # release.txt location and content depended upon by automated tooling
+ cp release.txt "$(TMPDIR)/"
+ tar -czvf $@ --xattrs -C "$(TMPDIR)" "./release.txt" "./$(SUBDIR)"
+ -rm -rf "$(TMPDIR)"
+
+# Must call make in-line: Dependency-spec. w/ wild-card also consumes variable value.
+podman-remote-$(RELEASE_NUMBER)-%.zip:
+ $(MAKE) podman-remote-$* install-podman-remote-docs release.txt \
+ RELEASE_BASENAME=$(shell hack/get_release_info.sh REMOTENAME) \
+ RELEASE_DIST=$* RELEASE_DIST_VER="-"
+ $(eval TMPDIR := $(shell mktemp -d -p '' $podman_remote_XXXX))
+ $(eval SUBDIR := podman-$(RELEASE_VERSION))
+ $(eval BINSFX := $(shell test "$*" != "windows" || echo ".exe"))
+ mkdir -p "$(TMPDIR)/$(SUBDIR)"
+ # release.txt location and content depended upon by automated tooling
+ cp release.txt "$(TMPDIR)/"
+ cp ./bin/podman-remote-$*$(BINSFX) "$(TMPDIR)/$(SUBDIR)/podman$(BINSFX)"
+ cp -r ./docs/remote "$(TMPDIR)/$(SUBDIR)/docs/"
+ $(eval DOCFILE := $(TMPDIR)/$(SUBDIR)/docs/podman.1)
+ cp docs/podman-remote.1 "$(DOCFILE)"
+ sed -i 's/podman\\*-remote/podman/g' "$(DOCFILE)"
+ sed -i 's/Podman\\*-remote/Podman\ for\ $*/g' "$(DOCFILE)"
+ sed -i 's/podman\.conf/podman\-remote\.conf/g' "$(DOCFILE)"
+ sed -i 's/A\ remote\ CLI\ for\ Podman\:\ //g' "$(DOCFILE)"
+ cd "$(TMPDIR)" && \
+ zip --recurse-paths "$(CURDIR)/$@" "./release.txt" "./"
+ -rm -rf "$(TMPDIR)"
+
+.PHONY: podman-release
+podman-release:
+ rm -f release.txt
+ $(MAKE) podman-$(RELEASE_NUMBER).tar.gz
-brew-pkg: install-podman-remote-docs podman-remote-darwin
- @mkdir -p ./brew
- @cp ./bin/podman-remote-darwin ./brew/podman
- @cp -r ./docs/remote ./brew/docs/
- @cp docs/podman-remote.1 ./brew/docs/podman.1
- @cp docs/podman-remote.conf.5 ./brew/docs/podman-remote.conf.5
- @sed -i 's/podman\\*-remote/podman/g' ./brew/docs/podman.1
- @sed -i 's/Podman\\*-remote/Podman\ for\ Mac/g' ./brew/docs/podman.1
- @sed -i 's/podman\.conf/podman\-remote\.conf/g' ./brew/docs/podman.1
- @sed -i 's/A\ remote\ CLI\ for\ Podman\:\ //g' ./brew/docs/podman.1
- tar -czvf podman-${RELEASE_NUMBER}.tar.gz ./brew
- @rm -rf ./brew
+.PHONY: podman-remote-%-release
+podman-remote-%-release:
+ rm -f release.txt
+ $(MAKE) podman-remote-$(RELEASE_NUMBER)-$*.zip
docker-docs: docs
(cd docs; ./dckrman.sh *.1)
diff --git a/README.md b/README.md
index f7c592671..34ed6d9e1 100644
--- a/README.md
+++ b/README.md
@@ -8,6 +8,9 @@ popularized by Kubernetes. Libpod also contains the Pod Manager tool `(Podman)`
* [Latest Version: 1.4.4](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)
* [GoDoc: ![GoDoc](https://godoc.org/github.com/containers/libpod/libpod?status.svg)](https://godoc.org/github.com/containers/libpod/libpod)
+* Automated continuous release downloads (including remote-client):
+ * Master Branch: [https://storage.cloud.google.com/libpod-master-releases/](https://storage.cloud.google.com/libpod-master-releases/)
+ * Pull-requests: [https://storage.cloud.google.com/libpod-pr-releases/](https://storage.cloud.google.com/libpod-pr-releases/)
## Overview and scope
diff --git a/cmd/podman/cliconfig/config.go b/cmd/podman/cliconfig/config.go
index 9bc47333d..98e7aed4b 100644
--- a/cmd/podman/cliconfig/config.go
+++ b/cmd/podman/cliconfig/config.go
@@ -509,6 +509,7 @@ type SignValues struct {
PodmanCommand
Directory string
SignBy string
+ CertDir string
}
type StartValues struct {
diff --git a/cmd/podman/main_local.go b/cmd/podman/main_local.go
index 648dc166e..0feba609b 100644
--- a/cmd/podman/main_local.go
+++ b/cmd/podman/main_local.go
@@ -120,6 +120,14 @@ func profileOff(cmd *cobra.Command) error {
}
func setupRootless(cmd *cobra.Command, args []string) error {
+ matches, err := rootless.ConfigurationMatches()
+ if err != nil {
+ return err
+ }
+ if !matches {
+ logrus.Warningf("the current user namespace doesn't match the configuration in /etc/subuid or /etc/subgid")
+ logrus.Warningf("you can use `%s system migrate` to recreate the user namespace and restart the containers", os.Args[0])
+ }
if os.Geteuid() == 0 || cmd == _searchCommand || cmd == _versionCommand || cmd == _mountCommand || cmd == _migrateCommand || strings.HasPrefix(cmd.Use, "help") {
return nil
}
@@ -140,7 +148,7 @@ func setupRootless(cmd *cobra.Command, args []string) error {
became, ret, err := rootless.TryJoinFromFilePaths("", false, []string{pausePidPath})
if err != nil {
logrus.Errorf("cannot join pause process. You may need to remove %s and stop all containers", pausePidPath)
- logrus.Errorf("you can use `%s system migrate` to recreate the pause process", os.Args[0])
+ logrus.Errorf("you can use `%s system migrate` to recreate the pause process and restart the containers", os.Args[0])
logrus.Errorf(err.Error())
os.Exit(1)
}
diff --git a/cmd/podman/sign.go b/cmd/podman/sign.go
index de289047a..63ba9b904 100644
--- a/cmd/podman/sign.go
+++ b/cmd/podman/sign.go
@@ -46,7 +46,7 @@ func init() {
flags := signCommand.Flags()
flags.StringVarP(&signCommand.Directory, "directory", "d", "", "Define an alternate directory to store signatures")
flags.StringVar(&signCommand.SignBy, "sign-by", "", "Name of the signing key")
-
+ flags.StringVar(&signCommand.CertDir, "cert-dir", "", "`Pathname` of a directory containing TLS certificates and keys")
}
// SignatureStoreDir defines default directory to store signatures
@@ -76,6 +76,13 @@ func signCmd(c *cliconfig.SignValues) error {
}
}
+ sc := runtime.SystemContext()
+ sc.DockerCertPath = c.CertDir
+
+ dockerRegistryOptions := image.DockerRegistryOptions{
+ DockerCertPath: c.CertDir,
+ }
+
mech, err := signature.NewGPGSigningMechanism()
if err != nil {
return errors.Wrap(err, "error initializing GPG")
@@ -85,7 +92,7 @@ func signCmd(c *cliconfig.SignValues) error {
return errors.Wrap(err, "signing is not supported")
}
- systemRegistriesDirPath := trust.RegistriesDirPath(runtime.SystemContext())
+ systemRegistriesDirPath := trust.RegistriesDirPath(sc)
registryConfigs, err := trust.LoadAndMergeConfig(systemRegistriesDirPath)
if err != nil {
return errors.Wrapf(err, "error reading registry configuration")
@@ -96,10 +103,14 @@ func signCmd(c *cliconfig.SignValues) error {
if err != nil {
return errors.Wrapf(err, "error parsing image name")
}
- rawSource, err := srcRef.NewImageSource(getContext(), runtime.SystemContext())
+ rawSource, err := srcRef.NewImageSource(getContext(), sc)
if err != nil {
return errors.Wrapf(err, "error getting image source")
}
+ err = rawSource.Close()
+ if err != nil {
+ logrus.Errorf("unable to close new image source %q", err)
+ }
manifest, _, err := rawSource.GetManifest(getContext(), nil)
if err != nil {
return errors.Wrapf(err, "error getting manifest")
@@ -114,7 +125,7 @@ func signCmd(c *cliconfig.SignValues) error {
if err != nil {
return err
}
- newImage, err := runtime.ImageRuntime().New(getContext(), signimage, rtc.SignaturePolicyPath, "", os.Stderr, nil, image.SigningOptions{SignBy: signby}, nil, util.PullImageMissing)
+ newImage, err := runtime.ImageRuntime().New(getContext(), signimage, rtc.SignaturePolicyPath, "", os.Stderr, &dockerRegistryOptions, image.SigningOptions{SignBy: signby}, nil, util.PullImageMissing)
if err != nil {
return errors.Wrapf(err, "error pulling image %s", signimage)
}
diff --git a/completions/bash/podman b/completions/bash/podman
index 7280f4040..e6ffb135f 100644
--- a/completions/bash/podman
+++ b/completions/bash/podman
@@ -2669,6 +2669,7 @@ _podman_container_runlabel() {
_podman_image_sign() {
local options_with_args="
+ --cert-dir
-d
--directory
--sign-by
diff --git a/contrib/cirrus/99-do-not-use-google-subnets.conflist b/contrib/cirrus/99-do-not-use-google-subnets.conflist
new file mode 100644
index 000000000..e9ab638ed
--- /dev/null
+++ b/contrib/cirrus/99-do-not-use-google-subnets.conflist
@@ -0,0 +1,21 @@
+{
+ "cniVersion": "0.4.0",
+ "name": "do-not-use-google-subnets",
+ "plugins": [
+ {
+ "type": "bridge",
+ "name": "do-not-use-google-subnets",
+ "bridge": "do-not-use-google-subnets",
+ "ipam": {
+ "type": "host-local",
+ "ranges": [
+ [
+ {
+ "subnet": "10.128.0.0/9"
+ }
+ ]
+ ]
+ }
+ }
+ ]
+}
diff --git a/contrib/cirrus/build_release.sh b/contrib/cirrus/build_release.sh
new file mode 100755
index 000000000..287643f47
--- /dev/null
+++ b/contrib/cirrus/build_release.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+source $(dirname $0)/lib.sh
+
+req_env_var TEST_REMOTE_CLIENT OS_RELEASE_ID GOSRC
+
+cd $GOSRC
+
+if [[ "$TEST_REMOTE_CLIENT" == "true" ]] && [[ -z "$CROSS_PLATFORM" ]]
+then
+ CROSS_PLATFORM=linux
+fi
+
+if [[ -n "$CROSS_PLATFORM" ]]
+then
+ echo "Compiling podman-remote release archive for ${CROSS_PLATFORM}"
+ case "$CROSS_PLATFORM" in
+ linux) ;&
+ windows) ;&
+ darwin)
+ make podman-remote-${CROSS_PLATFORM}-release
+ ;;
+ *)
+ die 1 "Unknown/unsupported cross-compile platform '$CROSS_PLATFORM'"
+ ;;
+ esac
+else
+ echo "Compiling release archive for $OS_RELEASE_ID"
+ make podman-release
+fi
diff --git a/contrib/cirrus/cache_release_archive.sh b/contrib/cirrus/cache_release_archive.sh
deleted file mode 100755
index 2365f7593..000000000
--- a/contrib/cirrus/cache_release_archive.sh
+++ /dev/null
@@ -1,140 +0,0 @@
-#!/bin/bash
-
-set -eo pipefail
-
-source $(dirname $0)/lib.sh
-
-req_env_var GOSRC
-
-RELEASE_ARCHIVE_NAMES=""
-
-handle_archive() { # Assumed to be called with set +e
- TASK_NUMBER=$1
- PR_OR_BRANCH=$2
- CACHE_URL=$3
- ARCHIVE_NAME="$(basename $CACHE_URL)"
- req_env_var TASK_NUMBER PR_OR_BRANCH CACHE_URL ARCHIVE_NAME
-
- cd /tmp
- curl -sO "$CACHE_URL" || return $(warn 0 "Couldn't download file, skipping.")
- [[ -r "/tmp/$ARCHIVE_NAME" ]] || return $(warn 0 "Unreadable archive '/tmp/$ARCHIVE_NAME', skipping.")
-
- ZIPCOMMENT=$(unzip -qqz "$ARCHIVE_NAME" 2>/dev/null) # noisy bugger
- if [[ "$?" -ne "0" ]] || [[ -z "$ZIPCOMMENT" ]]
- then
- return $(warn 0 "Could not unzip metadata from downloaded '/tmp/$ARCHIVE_NAME', skipping.")
- fi
-
- RELEASE_INFO=$(echo "$ZIPCOMMENT" | grep -m 1 'X-RELEASE-INFO:' | sed -r -e 's/X-RELEASE-INFO:\s*(.+)/\1/')
- if [[ "$?" -ne "0" ]] || [[ -z "$RELEASE_INFO" ]]
- then
- return $(warn 0 "Metadata empty or invalid: '$ZIPCOMMENT', skipping.")
- fi
-
- # e.g. libpod v1.3.1-166-g60df124e fedora 29 amd64
- # or libpod v1.3.1-166-g60df124e amd64
- FIELDS="RELEASE_BASENAME RELEASE_VERSION RELEASE_DIST RELEASE_DIST_VER RELEASE_ARCH"
- read $FIELDS <<< $RELEASE_INFO
- for f in $FIELDS
- do
- [[ -n "${!f}" ]] || return $(warn 0 "Expecting $f to be non-empty in metadata: '$RELEASE_INFO', skipping.")
- done
-
- echo -n "Preparing $RELEASE_BASENAME archive: "
- # Drop version number to enable "latest" representation
- # (version available w/in zip-file comment)
- RELEASE_ARCHIVE_NAME="${RELEASE_BASENAME}-${PR_OR_BRANCH}-${RELEASE_DIST}-${RELEASE_DIST_VER}-${RELEASE_ARCH}.zip"
- # Allow uploading all gathered files in parallel, later with gsutil.
- mv -v "$ARCHIVE_NAME" "/$RELEASE_ARCHIVE_NAME"
- RELEASE_ARCHIVE_NAMES="$RELEASE_ARCHIVE_NAMES $RELEASE_ARCHIVE_NAME"
-}
-
-make_release() {
- ARCHIVE_NAME="$1"
- req_env_var ARCHIVE_NAME
-
- # There's no actual testing of windows/darwin targets yet
- # but we still want to cross-compile and publish binaries
- if [[ "$SPECIALMODE" == "windows" ]] || [[ "$SPECIALMODE" == "darwin" ]]
- then
- RELFILE="podman-remote-${SPECIALMODE}.zip"
- elif [[ "$SPECIALMODE" == "none" ]]
- then
- RELFILE="podman.zip"
- else
- die 55 "$(basename $0) unable to handle \$SPECIALMODE=$SPECIALMODE for $ARCHIVE_NAME"
- fi
- echo "Calling make $RELFILE"
- cd $GOSRC
- make "$RELFILE"
- echo "Renaming archive so it can be identified/downloaded for publishing"
- mv -v "$RELFILE" "$ARCHIVE_NAME"
- echo "Success!"
-}
-
-[[ "$CI" == "true" ]] || \
- die 56 "$0 requires a Cirrus-CI cross-task cache to function"
-
-cd $GOSRC
-# Same script re-used for both uploading and downloading to avoid duplication
-if [[ "$(basename $0)" == "cache_release_archive.sh" ]]
-then
- # ref: https://cirrus-ci.org/guide/writing-tasks/#environment-variables
- req_env_var CI_NODE_INDEX CIRRUS_BUILD_ID
- # Use unique names for uncache_release_archives.sh to find/download them all
- ARCHIVE_NAME="build-${CIRRUS_BUILD_ID}-task-${CI_NODE_INDEX}.zip"
- make_release "$ARCHIVE_NAME"
-
- # ref: https://cirrus-ci.org/guide/writing-tasks/#http-cache
- URL="http://$CIRRUS_HTTP_CACHE_HOST/${ARCHIVE_NAME}"
- echo "Uploading $ARCHIVE_NAME to Cirrus-CI cache at $URL"
- curl -s -X POST --data-binary "@$ARCHIVE_NAME" "$URL"
-elif [[ "$(basename $0)" == "uncache_release_archives.sh" ]]
-then
- req_env_var CIRRUS_BUILD_ID CI_NODE_TOTAL GCPJSON GCPNAME GCPROJECT
- [[ "${CI_NODE_INDEX}" -eq "$[CI_NODE_TOTAL-1]" ]] || \
- die 0 "WARNING: This task depends on cache data from other tasks, otherwise it is a no-op."
-
- if [[ -n "$CIRRUS_PR" ]]
- then
- PR_OR_BRANCH="pr$CIRRUS_PR"
- BUCKET="libpod-pr-releases"
- elif [[ -n "$CIRRUS_BRANCH" ]]
- then
- PR_OR_BRANCH="$CIRRUS_BRANCH"
- BUCKET="libpod-$CIRRUS_BRANCH-releases"
- else
- die 10 "Expecting either \$CIRRUS_PR or \$CIRRUS_BRANCH to be non-empty."
- fi
-
- echo "Blindly downloading Cirrus-CI cache files for task (some will fail)."
- set +e # Don't stop looping until all task's cache is attempted
- for (( task_number = 0 ; task_number < $CI_NODE_TOTAL ; task_number++ ))
- do
- ARCHIVE_NAME="build-${CIRRUS_BUILD_ID}-task-${task_number}.zip"
- URL="http://$CIRRUS_HTTP_CACHE_HOST/${ARCHIVE_NAME}"
- echo "Attempting to download cached archive from $URL"
- handle_archive "$task_number" "$PR_OR_BRANCH" "$URL"
- echo "----------------------------------------"
- done
- set -e
-
- [[ -n "$RELEASE_ARCHIVE_NAMES" ]] || \
- die 67 "Error: No release archives found in CI cache, expecting at least one."
-
- echo "Preparing to upload release archives."
- gcloud config set project "$GCPROJECT"
- echo "$GCPJSON" > /tmp/gcp.json
- gcloud auth activate-service-account --key-file=/tmp/gcp.json
- rm /tmp/gcp.json
- # handle_archive() placed all uploadable files under /
- gsutil -m cp /*.zip "gs://$BUCKET" # Upload in parallel
- echo "Successfully uploaded archives:"
- for ARCHIVE_NAME in $RELEASE_ARCHIVE_NAMES
- do
- echo " https://storage.cloud.google.com/$BUCKET/$ARCHIVE_NAME"
- done
- echo "These will remain available until automatic pruning by bucket policy."
-else
- die 9 "I don't know what to do when called $0"
-fi
diff --git a/contrib/cirrus/cirrus_yaml_test.py b/contrib/cirrus/cirrus_yaml_test.py
index c8faee65f..c2ff8e69e 100755
--- a/contrib/cirrus/cirrus_yaml_test.py
+++ b/contrib/cirrus/cirrus_yaml_test.py
@@ -26,7 +26,6 @@ class TestCaseBase(unittest.TestCase):
class TestDependsOn(TestCaseBase):
ALL_TASK_NAMES = None
- SUCCESS_RELEASE = set(['success', 'release'])
def setUp(self):
super().setUp()
@@ -34,34 +33,22 @@ class TestDependsOn(TestCaseBase):
for key, _ in self.CIRRUS_YAML.items()
if key.endswith('_task')])
- def test_dicts(self):
+ def test_00_dicts(self):
"""Expected dictionaries are present and non-empty"""
- for name in ('success_task', 'release_task'):
- # tests all names then show specific failures
- with self.subTest(name=name):
- self.assertIn(name, self.CIRRUS_YAML)
- self.assertIn(name.replace('_task', ''), self.ALL_TASK_NAMES)
- self.assertIn('depends_on', self.CIRRUS_YAML[name])
- self.assertGreater(len(self.CIRRUS_YAML[name]['depends_on']), 0)
-
- def _check_dep(self, name, task_name, deps):
- # name includes '_task' suffix, task_name does not
- msg=('Please add "{0}" to the "depends_on" list in "{1}"'
- "".format(task_name, name))
- self.assertIn(task_name, deps, msg=msg)
-
- def test_depends(self):
- """Success and Release tasks depend on all other tasks"""
- for name in ('success_task', 'release_task'):
- deps = set(self.CIRRUS_YAML[name]['depends_on'])
- for task_name in self.ALL_TASK_NAMES - self.SUCCESS_RELEASE:
- with self.subTest(name=name, task_name=task_name):
- self._check_dep(name, task_name, deps)
-
- def test_release(self):
- """Release task must always execute last"""
- deps = set(self.CIRRUS_YAML['release_task']['depends_on'])
- self._check_dep('release_task', 'success', deps)
+ self.assertIn('success_task', self.CIRRUS_YAML)
+ self.assertIn('success_task'.replace('_task', ''), self.ALL_TASK_NAMES)
+ self.assertIn('depends_on', self.CIRRUS_YAML['success_task'])
+ self.assertGreater(len(self.CIRRUS_YAML['success_task']['depends_on']), 0)
+
+ def test_01_depends(self):
+ """Success task depends on all other tasks"""
+ success_deps = set(self.CIRRUS_YAML['success_task']['depends_on'])
+ for task_name in self.ALL_TASK_NAMES - set(['success']):
+ with self.subTest(task_name=task_name):
+ msg=('Please add "{0}" to the "depends_on" list in "success_task"'
+ "".format(task_name))
+ self.assertIn(task_name, success_deps, msg=msg)
+
if __name__ == "__main__":
diff --git a/contrib/cirrus/git_authors_to_irc_nicks.csv b/contrib/cirrus/git_authors_to_irc_nicks.csv
new file mode 100644
index 000000000..a584cc76a
--- /dev/null
+++ b/contrib/cirrus/git_authors_to_irc_nicks.csv
@@ -0,0 +1,12 @@
+# Comma separated mapping of author e-mail, to Freenode IRC nick.
+# When no match is found here, the username portion of the e-mail is used.
+# Sorting is done at runtime - first-found e-mail match wins.
+# Comments (like this) and blank lines are ignored.
+
+bbaude@redhat.com,baude
+matthew.heon@pm.me,mheon
+matthew.heon@gmail.com,mheon
+emilien@redhat.com,EmilienM
+rothberg@redhat.com,vrothberg
+santiago@redhat.com,edsantiago
+gscrivan@redhat.com,giuseppe
diff --git a/contrib/cirrus/integration_test.sh b/contrib/cirrus/integration_test.sh
index a3d18d440..552f2ba73 100755
--- a/contrib/cirrus/integration_test.sh
+++ b/contrib/cirrus/integration_test.sh
@@ -65,10 +65,6 @@ case "$SPECIALMODE" in
make local${TESTSUITE}
fi
;;
- windows) ;& # for podman-remote building only
- darwin)
- warn '' "No $SPECIALMODE remote client integration tests configured"
- ;;
*)
die 110 "Unsupported \$SPECIALMODE: $SPECIALMODE"
esac
diff --git a/contrib/cirrus/lib.sh b/contrib/cirrus/lib.sh
index a20ee5a62..cd8b2ef61 100644
--- a/contrib/cirrus/lib.sh
+++ b/contrib/cirrus/lib.sh
@@ -28,11 +28,12 @@ CIRRUS_WORKING_DIR="${CIRRUS_WORKING_DIR:-$GOPATH/src/github.com/containers/libp
export GOSRC="${GOSRC:-$CIRRUS_WORKING_DIR}"
export PATH="$HOME/bin:$GOPATH/bin:/usr/local/bin:$PATH"
export LD_LIBRARY_PATH="/usr/local/lib${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}"
-TIMESTAMPS_FILEPATH="${TIMESTAMPS_FILEPATH:-/var/tmp/timestamps}"
-SETUP_MARKER_FILEPATH="${SETUP_MARKER_FILEPATH:-/var/tmp/.setup_environment_sh_complete}"
# Saves typing / in case location ever moves
SCRIPT_BASE=${SCRIPT_BASE:-./contrib/cirrus}
PACKER_BASE=${PACKER_BASE:-./contrib/cirrus/packer}
+# Important filepaths
+SETUP_MARKER_FILEPATH="${SETUP_MARKER_FILEPATH:-/var/tmp/.setup_environment_sh_complete}"
+AUTHOR_NICKS_FILEPATH="${CIRRUS_WORKING_DIR}/${SCRIPT_BASE}/git_authors_to_irc_nicks.csv"
cd $GOSRC
if type -P git &> /dev/null
@@ -64,6 +65,8 @@ export PRIOR_FEDORA_BASE_IMAGE="fedora-cloud-base-29-1-2-1559164849"
export BUILT_IMAGE_SUFFIX="${BUILT_IMAGE_SUFFIX:--$CIRRUS_REPO_NAME-${CIRRUS_BUILD_ID}}"
# IN_PODMAN container image
IN_PODMAN_IMAGE="quay.io/libpod/in_podman:latest"
+# Image for uploading releases
+UPLDREL_IMAGE="quay.io/libpod/upldrel:latest"
# Avoid getting stuck waiting for user input
export DEBIAN_FRONTEND="noninteractive"
@@ -76,7 +79,7 @@ BIGTO="timeout_attempt_delay_command 300s 5 30s"
# Safe env. vars. to transfer from root -> $ROOTLESS_USER (go env handled separetly)
ROOTLESS_ENV_RE='(CIRRUS_.+)|(ROOTLESS_.+)|(.+_IMAGE.*)|(.+_BASE)|(.*DIRPATH)|(.*FILEPATH)|(SOURCE.*)|(DEPEND.*)|(.+_DEPS_.+)|(OS_REL.*)|(.+_ENV_RE)|(TRAVIS)|(CI.+)|(TEST_REMOTE.*)'
# Unsafe env. vars for display
-SECRET_ENV_RE='(IRCID)|(ACCOUNT)|(^GC[EP]..+)|(SSH)'
+SECRET_ENV_RE='(IRCID)|(ACCOUNT)|(GC[EP]..+)|(SSH)'
# Names of systemd units which should never be running
EVIL_UNITS="cron crond atd apt-daily-upgrade apt-daily fstrim motd-news systemd-tmpfiles-clean"
@@ -321,13 +324,15 @@ EOF
install_test_configs(){
echo "Installing cni config, policy and registry config"
- req_env_var GOSRC
- sudo install -D -m 755 $GOSRC/cni/87-podman-bridge.conflist \
- /etc/cni/net.d/87-podman-bridge.conflist
- sudo install -D -m 755 $GOSRC/test/policy.json \
- /etc/containers/policy.json
- sudo install -D -m 755 $GOSRC/test/registries.conf \
- /etc/containers/registries.conf
+ req_env_var GOSRC SCRIPT_BASE
+ cd $GOSRC
+ install -v -D -m 644 ./cni/87-podman-bridge.conflist /etc/cni/net.d/
+ # This config must always sort last in the list of networks (podman picks first one
+ # as the default). This config prevents allocation of network address space used
+ # by default in google cloud. https://cloud.google.com/vpc/docs/vpc#ip-ranges
+ install -v -D -m 644 $SCRIPT_BASE/99-do-not-use-google-subnets.conflist /etc/cni/net.d/
+ install -v -D -m 644 ./test/policy.json /etc/containers/
+ install -v -D -m 644 ./test/registries.conf /etc/containers/
}
# Remove all files (except conmon, for now) provided by the distro version of podman.
diff --git a/contrib/cirrus/setup_environment.sh b/contrib/cirrus/setup_environment.sh
index 416a96c4e..7c7659169 100755
--- a/contrib/cirrus/setup_environment.sh
+++ b/contrib/cirrus/setup_environment.sh
@@ -61,8 +61,7 @@ esac
# Reload to incorporate any changes from above
source "$SCRIPT_BASE/lib.sh"
-install_test_configs
-
+# Must execute before possible setup_rootless()
make install.tools
case "$SPECIALMODE" in
@@ -70,7 +69,8 @@ case "$SPECIALMODE" in
remove_packaged_podman_files # we're building from source
;;
none)
- remove_packaged_podman_files
+ [[ -n "$CROSS_PLATFORM" ]] || \
+ remove_packaged_podman_files
;;
endpoint)
remove_packaged_podman_files
@@ -92,8 +92,8 @@ case "$SPECIALMODE" in
in_podman) # Assumed to be Fedora
$SCRIPT_BASE/setup_container_environment.sh
;;
- windows) ;& # for podman-remote building only
- darwin) ;;
*)
die 111 "Unsupported \$SPECIALMODE: $SPECIALMODE"
esac
+
+install_test_configs
diff --git a/contrib/cirrus/success.sh b/contrib/cirrus/success.sh
index c4e150514..30d375d95 100755
--- a/contrib/cirrus/success.sh
+++ b/contrib/cirrus/success.sh
@@ -4,14 +4,55 @@ set -e
source $(dirname $0)/lib.sh
-req_env_var CIRRUS_BRANCH CIRRUS_BUILD_ID
+req_env_var CIRRUS_BRANCH CIRRUS_BUILD_ID CIRRUS_REPO_FULL_NAME CIRRUS_BASE_SHA CIRRUS_CHANGE_IN_REPO
-REF=$(basename $CIRRUS_BRANCH) # PR number or branch named
-URL="https://cirrus-ci.com/build/$CIRRUS_BUILD_ID"
+cd $CIRRUS_WORKING_DIR
if [[ "$CIRRUS_BRANCH" =~ "pull" ]]
then
- ircmsg "Cirrus-CI testing successful for PR #$REF: $URL"
+ echo "Retrieving latest HEADS and tags"
+ git fetch --all --tags
+ echo "Finding commit authors for PR $CIRRUS_PR"
+ unset NICKS
+ if [[ -r "$AUTHOR_NICKS_FILEPATH" ]]
+ then
+ SHARANGE="${CIRRUS_BASE_SHA}..${CIRRUS_CHANGE_IN_REPO}"
+ EXCLUDE_RE='merge-robot'
+ AUTHOR_NICKS=$(egrep -v '(^[[:space:]]*$)|(^[[:space:]]*#)' "$AUTHOR_NICKS_FILEPATH" | sort -u)
+ # Depending on branch-state, it's possible SHARANGE could be _WAY_ too big
+ MAX_NICKS=10
+ # newline separated
+ GITLOG="git log --format='%ae'"
+ COMMIT_AUTHORS=$($GITLOGt $SHARANGE || $GITLOG -1 HEAD | \
+ sort -u | \
+ egrep -v "$EXCLUDE_RE" | \
+ tail -$MAX_NICKS)
+
+ for c_email in $COMMIT_AUTHORS
+ do
+ echo -e "\tExamining $c_email"
+ NICK=$(echo "$AUTHOR_NICKS" | grep -m 1 "$c_email" | \
+ awk --field-separator ',' '{print $2}' | tr -d '[[:blank:]]')
+ if [[ -n "$NICK" ]]
+ then
+ echo -e "\t\tFound $c_email -> $NICK in $(basename $AUTHOR_NICKS_FILEPATH)"
+ else
+ echo -e "\t\tNot found in $(basename $AUTHOR_NICKS_FILEPATH), using e-mail username."
+ NICK=$(echo "$c_email" | cut -d '@' -f 1)
+ fi
+ echo -e "\tUsing nick $NICK"
+ NICKS="${NICKS:+$NICKS, }$NICK"
+ done
+ fi
+
+ unset MENTION_PREFIX
+ [[ -z "$NICKS" ]] || \
+ MENTION_PREFIX="$NICKS: "
+
+ URL="https://github.com/$CIRRUS_REPO_FULL_NAME/pull/$CIRRUS_PR"
+ PR_SUBJECT=$(echo "$CIRRUS_CHANGE_MESSAGE" | head -1)
+ ircmsg "${MENTION_PREFIX}Cirrus-CI testing successful for PR '$PR_SUBJECT': $URL"
else
- ircmsg "Cirrus-CI testing branch $REF successful: $URL"
+ URL="https://cirrus-ci.com/github/containers/libpod/$CIRRUS_BRANCH"
+ ircmsg "Cirrus-CI testing branch $(basename $CIRRUS_BRANCH) successful: $URL"
fi
diff --git a/contrib/cirrus/uncache_release_archives.sh b/contrib/cirrus/uncache_release_archives.sh
deleted file mode 120000
index e9fc6edff..000000000
--- a/contrib/cirrus/uncache_release_archives.sh
+++ /dev/null
@@ -1 +0,0 @@
-cache_release_archive.sh \ No newline at end of file
diff --git a/contrib/cirrus/unit_test.sh b/contrib/cirrus/unit_test.sh
index 004839f17..c6c77d17e 100755
--- a/contrib/cirrus/unit_test.sh
+++ b/contrib/cirrus/unit_test.sh
@@ -16,10 +16,6 @@ case "$SPECIALMODE" in
none)
make
;;
- windows) ;&
- darwin)
- make podman-remote-$SPECIALMODE
- ;;
*)
die 109 "Unsupported \$SPECIAL_MODE: $SPECIALMODE"
esac
diff --git a/contrib/cirrus/upload_release_archive.sh b/contrib/cirrus/upload_release_archive.sh
new file mode 100755
index 000000000..942255821
--- /dev/null
+++ b/contrib/cirrus/upload_release_archive.sh
@@ -0,0 +1,52 @@
+#!/bin/bash
+
+set -eo pipefail
+
+source $(dirname $0)/lib.sh
+
+req_env_var CI UPLDREL_IMAGE CIRRUS_BUILD_ID GOSRC RELEASE_GCPJSON RELEASE_GCPNAME RELEASE_GCPROJECT
+
+[[ "$CI" == "true" ]] || \
+ die 56 "$0 must be run under Cirrus-CI to function"
+
+unset PR_OR_BRANCH BUCKET
+if [[ -n "$CIRRUS_PR" ]]
+then
+ PR_OR_BRANCH="pr$CIRRUS_PR"
+ BUCKET="libpod-pr-releases"
+elif [[ -n "$CIRRUS_BRANCH" ]]
+then
+ PR_OR_BRANCH="$CIRRUS_BRANCH"
+ BUCKET="libpod-$CIRRUS_BRANCH-releases"
+else
+ die 1 "Expecting either \$CIRRUS_PR or \$CIRRUS_BRANCH to be non-empty."
+fi
+
+# Functional local podman required for uploading a release
+cd $GOSRC
+[[ -n "$(type -P podman)" ]] || \
+ make install || \
+ die 57 "$0 requires working podman binary on path to function"
+
+TMPF=$(mktemp -p '' $(basename $0)_XXXX.json)
+trap "rm -f $TMPF" EXIT
+set +x
+echo "$RELEASE_GCPJSON" > "$TMPF"
+unset RELEASE_GCPJSON
+
+cd $GOSRC
+for filename in $(ls -1 *.tar.gz *.zip)
+do
+ echo "Running podman ... $UPLDREL_IMAGE $filename"
+ podman run -i --rm \
+ -e "GCPNAME=$RELEASE_GCPNAME" \
+ -e "GCPPROJECT=$RELEASE_GCPROJECT" \
+ -e "GCPJSON_FILEPATH=$TMPF" \
+ -e "REL_ARC_FILEPATH=/tmp/$filename" \
+ -e "PR_OR_BRANCH=$PR_OR_BRANCH" \
+ -e "BUCKET=$BUCKET" \
+ --security-opt label=disable \
+ -v "$TMPF:$TMPF:ro" \
+ -v "$GOSRC/$filename:/tmp/$filename:ro" \
+ $UPLDREL_IMAGE
+done
diff --git a/contrib/imgprune/entrypoint.sh b/contrib/imgprune/entrypoint.sh
index 829e9938e..b0f006332 100755
--- a/contrib/imgprune/entrypoint.sh
+++ b/contrib/imgprune/entrypoint.sh
@@ -6,13 +6,17 @@ source /usr/local/bin/lib_entrypoint.sh
req_env_var GCPJSON GCPNAME GCPPROJECT IMGNAMES
-BASE_IMAGES=""
-# When executing under Cirrus-CI, have access to current source
-if [[ "$CI" == "true" ]] && [[ -r "$CIRRUS_WORKING_DIR/$SCRIPT_BASE" ]]
+unset BASE_IMAGES
+# When executing under Cirrus-CI, script have access to current source
+LIB="$CIRRUS_WORKING_DIR/$SCRIPT_BASE/lib.sh"
+if [[ "$CI" == "true" ]] && [[ -r "$LIB" ]]
then
# Avoid importing anything that might conflict
- eval "$(egrep -sh '^export .+BASE_IMAGE=' < $CIRRUS_WORKING_DIR/$SCRIPT_BASE/lib.sh)"
- BASE_IMAGES="$UBUNTU_BASE_IMAGE $PRIOR_UBUNTU_BASE_IMAGE $FEDORA_BASE_IMAGE $PRIOR_FEDORA_BASE_IMAGE"
+ for env in $(sed -ne 's/^[^#]\+_BASE_IMAGE=/img=/p' "$LIB")
+ do
+ eval $env
+ BASE_IMAGES="$BASE_IMAGES $img"
+ done
else
# metadata labeling may have broken for some reason in the future
echo "Warning: Running outside of Cirrus-CI, very minor-risk of base-image deletion."
diff --git a/contrib/imgts/lib_entrypoint.sh b/contrib/imgts/lib_entrypoint.sh
index 7b76c823f..3f6b11128 100644
--- a/contrib/imgts/lib_entrypoint.sh
+++ b/contrib/imgts/lib_entrypoint.sh
@@ -35,10 +35,15 @@ req_env_var() {
gcloud_init() {
set +xe
- TMPF=$(mktemp -p '' .$(uuidgen)XXXX)
- trap "rm -f $TMPF" EXIT
- echo "$GCPJSON" > $TMPF && \
- $GCLOUD auth activate-service-account --project "$GCPPROJECT" --key-file=$TMPF || \
+ if [[ -n "$1" ]] && [[ -r "$1" ]]
+ then
+ TMPF="$1"
+ else
+ TMPF=$(mktemp -p '' .$(uuidgen)_XXXX.json)
+ trap "rm -f $TMPF &> /dev/null" EXIT
+ echo "$GCPJSON" > $TMPF
+ fi
+ $GCLOUD auth activate-service-account --project="$GCPPROJECT" --key-file="$TMPF" || \
die 5 FATAL auth
- rm -f $TMPF
+ rm -f $TMPF &> /dev/null || true # ignore any read-only error
}
diff --git a/contrib/upldrel/Dockerfile b/contrib/upldrel/Dockerfile
new file mode 100644
index 000000000..54a58c521
--- /dev/null
+++ b/contrib/upldrel/Dockerfile
@@ -0,0 +1,9 @@
+FROM quay.io/libpod/imgts:latest
+
+RUN yum -y update && \
+ yum -y install unzip && \
+ rpm -V unzip && \
+ yum clean all
+
+COPY /contrib/upldrel/entrypoint.sh /usr/local/bin/entrypoint.sh
+RUN chmod 755 /usr/local/bin/entrypoint.sh
diff --git a/contrib/upldrel/README.md b/contrib/upldrel/README.md
new file mode 100644
index 000000000..41f5ffef0
--- /dev/null
+++ b/contrib/upldrel/README.md
@@ -0,0 +1,9 @@
+![PODMAN logo](../../logo/podman-logo-source.svg)
+
+A container image for canonical-naming and uploading of
+libpod and remote-client archives. Only intended to ever
+be used by CI/CD, and depends heavily on an embedded
+`release.txt` file produced by `make`.
+
+Build script: [../cirrus/build_release.sh](../cirrus/build_release.sh)
+Upload script: [../cirrus/upload_release_archive.sh](../cirrus/upload_release_archive.sh)
diff --git a/contrib/upldrel/entrypoint.sh b/contrib/upldrel/entrypoint.sh
new file mode 100755
index 000000000..985b828a0
--- /dev/null
+++ b/contrib/upldrel/entrypoint.sh
@@ -0,0 +1,62 @@
+#!/bin/bash
+
+set -e
+
+source /usr/local/bin/lib_entrypoint.sh
+
+req_env_var GCPJSON_FILEPATH GCPNAME GCPPROJECT REL_ARC_FILEPATH PR_OR_BRANCH BUCKET
+
+[[ -r "$REL_ARC_FILEPATH" ]] || \
+ die 2 ERROR Cannot read release archive file: "$REL_ARC_FILEPATH"
+
+[[ -r "$GCPJSON_FILEPATH" ]] || \
+ die 3 ERROR Cannot read GCP credentials file: "$GCPJSON_FILEPATH"
+
+cd $TMPDIR
+echo "Attempting to extract release.txt from tar or zip $REL_ARC_FILEPATH"
+unset SFX
+if tar xzf "$REL_ARC_FILEPATH" "./release.txt"
+then
+ echo "It's a tarball"
+ SFX="tar.gz"
+elif unzip "$REL_ARC_FILEPATH" release.txt
+then
+ echo "It's a zip"
+ SFX="zip"
+else
+ die 5 ERROR Could not extract release.txt from $REL_ARC_FILEPATH
+fi
+
+echo "Parsing release.txt contents"
+RELEASETXT=$(<release.txt)
+cd -
+[[ -n "$RELEASETXT" ]] || \
+ die 3 ERROR Could not obtain metadata from release.txt in $REL_ARC_FILEPATH
+
+RELEASE_INFO=$(echo "$RELEASETXT" | grep -m 1 'X-RELEASE-INFO:' | sed -r -e 's/X-RELEASE-INFO:\s*(.+)/\1/')
+if [[ "$?" -ne "0" ]] || [[ -z "$RELEASE_INFO" ]]
+then
+ die 4 ERROR Metadata is empty or invalid: '$RELEASETXT'
+fi
+
+# e.g. libpod v1.3.1-166-g60df124e fedora 29 amd64
+# or libpod v1.3.1-166-g60df124e amd64
+FIELDS="RELEASE_BASENAME RELEASE_VERSION RELEASE_DIST RELEASE_DIST_VER RELEASE_ARCH"
+read $FIELDS <<< $RELEASE_INFO
+for f in $FIELDS
+do
+ [[ -n "${!f}" ]] || \
+ die 5 ERROR Expecting $f to be non-empty in metadata: '$RELEASE_INFO'
+done
+
+gcloud_init "$GCPJSON_FILEPATH"
+
+# Drop version number to enable "latest" representation
+# (version available w/in zip-file comment)
+RELEASE_ARCHIVE_NAME="${RELEASE_BASENAME}-${PR_OR_BRANCH}-${RELEASE_DIST}-${RELEASE_DIST_VER}-${RELEASE_ARCH}.${SFX}"
+
+echo "Uploading archive as $RELEASE_ARCHIVE_NAME"
+gsutil cp "$REL_ARC_FILEPATH" "gs://$BUCKET/$RELEASE_ARCHIVE_NAME"
+
+echo "Release now available at:"
+echo " https://storage.cloud.google.com/$BUCKET/$RELEASE_ARCHIVE_NAME"
diff --git a/docs/links/podman-container-umount.1 b/docs/links/podman-container-umount.1
index dadc63113..789dabbb0 100644
--- a/docs/links/podman-container-umount.1
+++ b/docs/links/podman-container-umount.1
@@ -1 +1 @@
-.so man1/podman-umount,.1
+.so man1/podman-umount.1
diff --git a/docs/links/podman-container-unmount.1 b/docs/links/podman-container-unmount.1
index dadc63113..789dabbb0 100644
--- a/docs/links/podman-container-unmount.1
+++ b/docs/links/podman-container-unmount.1
@@ -1 +1 @@
-.so man1/podman-umount,.1
+.so man1/podman-umount.1
diff --git a/docs/links/podman-image-rm.1 b/docs/links/podman-image-rm.1
index 6dfc6e98c..1007ad150 100644
--- a/docs/links/podman-image-rm.1
+++ b/docs/links/podman-image-rm.1
@@ -1 +1 @@
-.so man1/podman-rm.1
+.so man1/podman-rmi.1
diff --git a/docs/podman-attach.1.md b/docs/podman-attach.1.md
index 4caa87792..cef01f0f6 100644
--- a/docs/podman-attach.1.md
+++ b/docs/podman-attach.1.md
@@ -6,6 +6,8 @@ podman\-attach - Attach to a running container
## SYNOPSIS
**podman attach** [*options*] *container*
+**podman container attach** [*options*] *container*
+
## DESCRIPTION
The attach command allows you to attach to a running container using the container's ID
or name, either to view its ongoing output or to control it interactively.
diff --git a/docs/podman-build.1.md b/docs/podman-build.1.md
index 8deb8811e..74c07ab73 100644
--- a/docs/podman-build.1.md
+++ b/docs/podman-build.1.md
@@ -6,6 +6,8 @@ podman\-build - Build a container image using a Dockerfile
## SYNOPSIS
**podman build** [*options*] *context*
+**podman image build** [*options*] *context*
+
## DESCRIPTION
**podman build** Builds an image using instructions from one or more Dockerfiles and a specified build context directory.
diff --git a/docs/podman-commit.1.md b/docs/podman-commit.1.md
index a269d0fae..5b0ba48aa 100644
--- a/docs/podman-commit.1.md
+++ b/docs/podman-commit.1.md
@@ -6,6 +6,8 @@ podman\-commit - Create new image based on the changed container
## SYNOPSIS
**podman commit** [*options*] *container* *image*
+**podman container commit** [*options*] *container* *image*
+
## DESCRIPTION
**podman commit** creates an image based on a changed container. The author of the
image can be set using the `--author` flag. Various image instructions can be
diff --git a/docs/podman-container-cleanup.1.md b/docs/podman-container-cleanup.1.md
index f6bb84113..69e21ce9f 100644
--- a/docs/podman-container-cleanup.1.md
+++ b/docs/podman-container-cleanup.1.md
@@ -1,7 +1,7 @@
% podman-container-cleanup(1)
## NAME
-podman\-container\-cleanup - Cleanup Container storage and networks
+podman\-container\-cleanup - Cleanup the container's network and mountpoints
## SYNOPSIS
**podman container cleanup** [*options*] *container*
diff --git a/docs/podman-container-prune.1.md b/docs/podman-container-prune.1.md
index 26c6b0b49..d8a4b7f4e 100644
--- a/docs/podman-container-prune.1.md
+++ b/docs/podman-container-prune.1.md
@@ -1,7 +1,7 @@
% podman-container-prune(1)
## NAME
-podman-container-prune - Remove all stopped containers
+podman-container-prune - Remove all stopped containers from local storage
## SYNOPSIS
**podman container prune** [*options*]
diff --git a/docs/podman-container-restore.1.md b/docs/podman-container-restore.1.md
index a49cb7421..1d2cf0b3e 100644
--- a/docs/podman-container-restore.1.md
+++ b/docs/podman-container-restore.1.md
@@ -1,7 +1,7 @@
% podman-container-restore(1)
## NAME
-podman\-container\-restore - Restores one or more running containers
+podman\-container\-restore - Restores one or more containers from a checkpoint
## SYNOPSIS
**podman container restore** [*options*] *container* ...
diff --git a/docs/podman-container-runlabel.1.md b/docs/podman-container-runlabel.1.md
index c16d8c3f4..8511dd5cd 100644
--- a/docs/podman-container-runlabel.1.md
+++ b/docs/podman-container-runlabel.1.md
@@ -1,10 +1,10 @@
% podman-container-runlabel(1)
## NAME
-podman-container-runlabel - Execute Image Label Method
+podman-container-runlabel - Executes a command as described by a container image label
## SYNOPSIS
-**podman container runlabel** [*options*] *LABEL* *IMAGE* [ARG...]
+**podman container runlabel** [*options*] *label* *image* [*arg...*]
## DESCRIPTION
**podman container runlabel** reads the provided `LABEL` field in the container
diff --git a/docs/podman-container.1.md b/docs/podman-container.1.md
index eb53149bd..4ea7c7acc 100644
--- a/docs/podman-container.1.md
+++ b/docs/podman-container.1.md
@@ -14,8 +14,8 @@ The container command allows you to manage containers
| Command | Man Page | Description |
| --------- | --------------------------------------------------- | ---------------------------------------------------------------------------- |
| attach | [podman-attach(1)](podman-attach.1.md) | Attach to a running container. |
-| checkpoint | [podman-container-checkpoint(1)](podman-container-checkpoint.1.md) | Checkpoints one or more containers. |
-| cleanup | [podman-container-cleanup(1)](podman-container-cleanup.1.md) | Cleanup containers network and mountpoints. |
+| checkpoint | [podman-container-checkpoint(1)](podman-container-checkpoint.1.md) | Checkpoints one or more running containers. |
+| cleanup | [podman-container-cleanup(1)](podman-container-cleanup.1.md) | Cleanup the container's network and mountpoints. |
| commit | [podman-commit(1)](podman-commit.1.md) | Create new image based on the changed container. |
| cp | [podman-cp(1)](podman-cp.1.md) | Copy files/folders between a container and the local filesystem. |
| create | [podman-create(1)](podman-create.1.md) | Create a new container. |
diff --git a/docs/podman-cp.1.md b/docs/podman-cp.1.md
index 178a05018..e3d992b55 100644
--- a/docs/podman-cp.1.md
+++ b/docs/podman-cp.1.md
@@ -6,6 +6,8 @@ podman\-cp - Copy files/folders between a container and the local filesystem
## SYNOPSIS
**podman cp** [*options*] [*container*:]*src_path* [*container*:]*dest_path*
+**podman container cp** [*options*] [*container*:]*src_path* [*container*:]*dest_path*
+
## DESCRIPTION
Copies the contents of **src_path** to the **dest_path**. You can copy from the container's filesystem to the local machine or the reverse, from the local filesystem to the container.
If - is specified for either the SRC_PATH or DEST_PATH, you can also stream a tar archive from STDIN or to STDOUT.
diff --git a/docs/podman-create.1.md b/docs/podman-create.1.md
index 7634408f5..cee9a1640 100644
--- a/docs/podman-create.1.md
+++ b/docs/podman-create.1.md
@@ -6,6 +6,8 @@ podman\-create - Create a new container
## SYNOPSIS
**podman create** [*options*] *image* [*command* [*arg* ...]]
+**podman container create** [*options*] *image* [*command* [*arg* ...]]
+
## DESCRIPTION
Creates a writable container layer over the specified image and prepares it for
diff --git a/docs/podman-diff.1.md b/docs/podman-diff.1.md
index 8d67ed82c..5b0434a07 100644
--- a/docs/podman-diff.1.md
+++ b/docs/podman-diff.1.md
@@ -6,6 +6,8 @@ podman\-diff - Inspect changes on a container or image's filesystem
## SYNOPSIS
**podman diff** [*options*] *name*
+**podman container diff** [*options*] *name*
+
## DESCRIPTION
Displays changes on a container or image's filesystem. The container or image will be compared to its parent layer
diff --git a/docs/podman-exec.1.md b/docs/podman-exec.1.md
index ab8d75626..f71b21126 100644
--- a/docs/podman-exec.1.md
+++ b/docs/podman-exec.1.md
@@ -6,6 +6,8 @@ podman\-exec - Execute a command in a running container
## SYNOPSIS
**podman exec** [*options*] *container* [*command* [*arg* ...]]
+**podman container exec** [*options*] *container* [*command* [*arg* ...]]
+
## DESCRIPTION
**podman exec** executes a command in a running container.
diff --git a/docs/podman-export.1.md b/docs/podman-export.1.md
index 3ccd783d8..4286d0e2f 100644
--- a/docs/podman-export.1.md
+++ b/docs/podman-export.1.md
@@ -6,6 +6,8 @@ podman\-export - Export a container's filesystem contents as a tar archive
## SYNOPSIS
**podman export** [*options*] *container*
+**podman container export** [*options*] *container*
+
## DESCRIPTION
**podman export** exports the filesystem of a container and saves it as a tarball
on the local machine. **podman export** writes to STDOUT by default and can be
diff --git a/docs/podman-generate-kube.1.md b/docs/podman-generate-kube.1.md
index 93f746664..8f15e14ba 100644
--- a/docs/podman-generate-kube.1.md
+++ b/docs/podman-generate-kube.1.md
@@ -1,6 +1,6 @@
% podman-generate-kube(1)
## NAME
-podman-generate-kube - Generate Kubernetes YAML
+podman-generate-kube - Generate Kubernetes YAML based on a pod or container
## SYNOPSIS
**podman generate kube** [*options*] *container* | *pod*
diff --git a/docs/podman-generate-systemd.1.md b/docs/podman-generate-systemd.1.md
index b4962f28b..b81e68a46 100644
--- a/docs/podman-generate-systemd.1.md
+++ b/docs/podman-generate-systemd.1.md
@@ -1,7 +1,7 @@
% podman-generate-systemd(1)
## NAME
-podman-generate-systemd- Generate Systemd Unit file
+podman\-generate\-systemd - Generate systemd unit file(s) for a container. Not supported for the remote client
## SYNOPSIS
**podman generate systemd** [*options*] *container|pod*
diff --git a/docs/podman-history.1.md b/docs/podman-history.1.md
index 5ee87c185..a67cb0286 100644
--- a/docs/podman-history.1.md
+++ b/docs/podman-history.1.md
@@ -6,6 +6,8 @@ podman\-history - Show the history of an image
## SYNOPSIS
**podman history** [*options*] *image*[:*tag*|@*digest*]
+**podman image history** [*options*] *image*[:*tag*|@*digest*]
+
## DESCRIPTION
**podman history** displays the history of an image by printing out information
about each layer used in the image. The information printed out for each layer
diff --git a/docs/podman-image-prune.1.md b/docs/podman-image-prune.1.md
index 52278746d..b844a9f63 100644
--- a/docs/podman-image-prune.1.md
+++ b/docs/podman-image-prune.1.md
@@ -1,7 +1,7 @@
% podman-image-prune(1)
## NAME
-podman-image-prune - Remove all unused images
+podman-image-prune - Remove all unused images from the local store
## SYNOPSIS
**podman image prune** [*options*]
diff --git a/docs/podman-image-sign.1.md b/docs/podman-image-sign.1.md
index 61df3b3bd..ca438b438 100644
--- a/docs/podman-image-sign.1.md
+++ b/docs/podman-image-sign.1.md
@@ -12,14 +12,23 @@ been pulled from a registry. The signature will be written to a directory
derived from the registry configuration files in /etc/containers/registries.d. By default, the signature will be written into /var/lib/containers/sigstore directory.
## OPTIONS
+
**--help**, **-h**
- Print usage statement.
+
+Print usage statement.
+
+**--cert-dir**=*path*
+
+Use certificates at *path* (\*.crt, \*.cert, \*.key) to connect to the registry.
+Default certificates directory is _/etc/containers/certs.d_. (Not available for remote commands)
**--directory**, **-d**=*dir*
- Store the signatures in the specified directory. Default: /var/lib/containers/sigstore
+
+Store the signatures in the specified directory. Default: /var/lib/containers/sigstore
**--sign-by**=*identity*
- Override the default identity of the signature.
+
+Override the default identity of the signature.
## EXAMPLES
Sign the busybox image with the identify of foo@bar.com with a user's keyring and save the signature in /tmp/signatures/.
diff --git a/docs/podman-image-trust.1.md b/docs/podman-image-trust.1.md
index 7c5b70833..b35e883d7 100644
--- a/docs/podman-image-trust.1.md
+++ b/docs/podman-image-trust.1.md
@@ -5,7 +5,7 @@ podman\-image\-trust - Manage container registry image trust policy
## SYNOPSIS
-**podman image trust** set|show [*options*] *REGISTRY[/REPOSITORY]*
+**podman image trust** set|show [*options*] *registry[/repository]*
## DESCRIPTION
Manages which registries you trust as a source of container images based on its location. The location is determined
diff --git a/docs/podman-image.1.md b/docs/podman-image.1.md
index 01cf08d62..339a531dd 100644
--- a/docs/podman-image.1.md
+++ b/docs/podman-image.1.md
@@ -25,10 +25,10 @@ The image command allows you to manage images
| push | [podman-push(1)](podman-push.1.md) | Push an image from local storage to elsewhere. |
| rm | [podman-rmi(1)](podman-rmi.1.md) | Removes one or more locally stored images. |
| save | [podman-save(1)](podman-save.1.md) | Save an image to docker-archive or oci. |
-| sign | [podman-image-sign(1)](podman-image-sign.1.md) | Sign an image. |
+| sign | [podman-image-sign(1)](podman-image-sign.1.md) | Create a signature for an image. |
| tag | [podman-tag(1)](podman-tag.1.md) | Add an additional name to a local image. |
| tree | [podman-image-tree(1)](podman-image-tree.1.md) | Prints layer hierarchy of an image in a tree format. |
-| trust | [podman-image-trust(1)](podman-image-trust.1.md)| Manage container image trust policy. |
+| trust | [podman-image-trust(1)](podman-image-trust.1.md)| Manage container registry image trust policy. |
## SEE ALSO
podman
diff --git a/docs/podman-images.1.md b/docs/podman-images.1.md
index 6360bf580..3ac07fc43 100644
--- a/docs/podman-images.1.md
+++ b/docs/podman-images.1.md
@@ -6,6 +6,10 @@ podman\-images - List images in local storage
## SYNOPSIS
**podman images** [*options*]
+**podman image list** [*options*]
+
+**podman image ls** [*options*]
+
## DESCRIPTION
Displays locally stored images, their names, and their IDs.
diff --git a/docs/podman-import.1.md b/docs/podman-import.1.md
index 6c625bc8d..5e57c1bcb 100644
--- a/docs/podman-import.1.md
+++ b/docs/podman-import.1.md
@@ -6,6 +6,8 @@ podman\-import - Import a tarball and save it as a filesystem image
## SYNOPSIS
**podman import** [*options*] *path* [*reference*]
+**podman image import** [*options*] *path* [*reference*]
+
## DESCRIPTION
**podman import** imports a tarball (.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz)
and saves it as a filesystem image. Remote tarballs can be specified using a URL.
diff --git a/docs/podman-info.1.md b/docs/podman-info.1.md
index a7b259c95..9721755ef 100644
--- a/docs/podman-info.1.md
+++ b/docs/podman-info.1.md
@@ -1,12 +1,12 @@
% podman-info(1)
## NAME
-podman\-system\-info - Display system information
-podman\-info - Display system information
+podman\-info - Displays Podman related system information
## SYNOPSIS
**podman info** [*options*]
+**podman system info** [*options*]
## DESCRIPTION
diff --git a/docs/podman-init.1.md b/docs/podman-init.1.md
index a6bb391ec..3b49cfb99 100644
--- a/docs/podman-init.1.md
+++ b/docs/podman-init.1.md
@@ -6,6 +6,8 @@ podman\-init - Initialize one or more containers
## SYNOPSIS
**podman init** [*options*] *container* [*container*...]
+**podman container init** [*options*] *container* [*container*...]
+
## DESCRIPTION
Initialize one or more containers.
You may use container IDs or names as input.
diff --git a/docs/podman-kill.1.md b/docs/podman-kill.1.md
index 118246fdb..617d25b85 100644
--- a/docs/podman-kill.1.md
+++ b/docs/podman-kill.1.md
@@ -1,11 +1,13 @@
% podman-kill(1)
## NAME
-podman\-kill - Kills one or more containers with a signal
+podman\-kill - Kill the main process in one or more containers
## SYNOPSIS
**podman kill** [*options*] [*container* ...]
+**podman container kill** [*options*] [*container* ...]
+
## DESCRIPTION
The main process inside each container specified will be sent SIGKILL, or any signal specified with option --signal.
diff --git a/docs/podman-load.1.md b/docs/podman-load.1.md
index 6643538ce..deb4fb5ec 100644
--- a/docs/podman-load.1.md
+++ b/docs/podman-load.1.md
@@ -6,6 +6,8 @@ podman\-load - Load an image from a container image archive into container stora
## SYNOPSIS
**podman load** [*options*] [*name*[:*tag*]]
+**podman image load** [*options*] [*name*[:*tag*]]
+
## DESCRIPTION
**podman load** loads an image from either an **oci-archive** or **docker-archive** stored on the local machine into container storage. **podman load** reads from stdin by default or a file if the **input** option is set.
You can also specify a name for the image if the archive does not contain a named reference, of if you want an additional name for the local image.
diff --git a/docs/podman-logs.1.md b/docs/podman-logs.1.md
index 310eff438..405f180d9 100644
--- a/docs/podman-logs.1.md
+++ b/docs/podman-logs.1.md
@@ -1,13 +1,13 @@
% podman-logs(1)
## NAME
-podman\-container\-logs (podman\-logs) - Fetch the logs of one or more containers
+podman\-logs - Display the logs of one or more containers
## SYNOPSIS
-**podman container logs** [*options*] *container* [*container...*]
-
**podman logs** [*options*] *container* [*container...*]
+**podman container logs** [*options*] *container* [*container...*]
+
## DESCRIPTION
The podman logs command batch-retrieves whatever logs are present for one or more containers at the time of execution.
This does not guarantee execution order when combined with podman run (i.e. your run may not have generated
diff --git a/docs/podman-mount.1.md b/docs/podman-mount.1.md
index 2722f460c..8f4deeca6 100644
--- a/docs/podman-mount.1.md
+++ b/docs/podman-mount.1.md
@@ -1,11 +1,13 @@
% podman-mount(1)
## NAME
-podman\-mount - Mount the specified working containers' root filesystem
+podman\-mount - Mount a working container's root filesystem
## SYNOPSIS
**podman mount** [*container* ...]
+**podman container mount** [*container* ...]
+
## DESCRIPTION
Mounts the specified containers' root file system in a location which can be
accessed from the host, and returns its location.
diff --git a/docs/podman-network-inspect.1.md b/docs/podman-network-inspect.1.md
index 576e61c79..dfa7e4b0c 100644
--- a/docs/podman-network-inspect.1.md
+++ b/docs/podman-network-inspect.1.md
@@ -1,7 +1,7 @@
% podman-network-inspect(1)
## NAME
-podman\-network-inspect- Inspect one or more Podman networks
+podman\-network\-inspect - Displays the raw CNI network configuration for one or more networks
## SYNOPSIS
**podman network inspect** [*network* ...]
diff --git a/docs/podman-network-ls.1.md b/docs/podman-network-ls.1.md
index 725e07dbb..658b86c21 100644
--- a/docs/podman-network-ls.1.md
+++ b/docs/podman-network-ls.1.md
@@ -1,7 +1,7 @@
% podman-network-ls(1)
## NAME
-podman\-network-ls- Display a summary of CNI networks
+podman\-network\-ls - Display a summary of CNI networks
## SYNOPSIS
**podman network ls** [*options*]
diff --git a/docs/podman-network-rm.1.md b/docs/podman-network-rm.1.md
index f72d6a694..c95c93cd8 100644
--- a/docs/podman-network-rm.1.md
+++ b/docs/podman-network-rm.1.md
@@ -1,7 +1,7 @@
% podman-network-rm(1)
## NAME
-podman\-network-rm- Delete a Podman CNI network
+podman\-network\-rm - Remove one or more CNI networks
## SYNOPSIS
**podman network rm** [*network...*]
diff --git a/docs/podman-network.1.md b/docs/podman-network.1.md
index c01adc23e..c9f6725a3 100644
--- a/docs/podman-network.1.md
+++ b/docs/podman-network.1.md
@@ -1,7 +1,7 @@
% podman-network(1)
## NAME
-podman\-network- Manage podman CNI networks
+podman\-network - Manage Podman CNI networks
## SYNOPSIS
**podman network** *subcommand*
diff --git a/docs/podman-pause.1.md b/docs/podman-pause.1.md
index 18080ec04..dfd4da416 100644
--- a/docs/podman-pause.1.md
+++ b/docs/podman-pause.1.md
@@ -6,6 +6,8 @@ podman\-pause - Pause one or more containers
## SYNOPSIS
**podman pause** [*options*] [*container*...]
+**podman container pause** [*options*] [*container*...]
+
## DESCRIPTION
Pauses all the processes in one or more containers. You may use container IDs or names as input.
diff --git a/docs/podman-play-kube.1.md b/docs/podman-play-kube.1.md
index 8b78c83d0..2ac860a32 100644
--- a/docs/podman-play-kube.1.md
+++ b/docs/podman-play-kube.1.md
@@ -4,7 +4,7 @@
podman-play-kube - Create pods and containers based on Kubernetes YAML
## SYNOPSIS
-**podman play kube** [*options*] *file***.yml**
+**podman play kube** [*options*] *file*__.yml__
## DESCRIPTION
**podman play kube** will read in a structured file of Kubernetes YAML. It will then recreate
diff --git a/docs/podman-play.1.md b/docs/podman-play.1.md
index f0bf8ea41..364baad60 100644
--- a/docs/podman-play.1.md
+++ b/docs/podman-play.1.md
@@ -14,7 +14,7 @@ file input. Containers will be automatically started.
| Command | Man Page | Description |
| ------- | --------------------------------------------------- | ---------------------------------------------------------------------------- |
-| kube | [podman-play-kube(1)](podman-play-kube.1.md) | Recreate pods and containers based on Kubernetes YAML. |
+| kube | [podman-play-kube(1)](podman-play-kube.1.md) | Create pods and containers based on Kubernetes YAML. |
## SEE ALSO
podman, podman-pod(1), podman-container(1), podman-generate(1), podman-play(1), podman-play-kube(1)
diff --git a/docs/podman-pod-kill.1.md b/docs/podman-pod-kill.1.md
index 069db70d2..596e15cea 100644
--- a/docs/podman-pod-kill.1.md
+++ b/docs/podman-pod-kill.1.md
@@ -1,7 +1,7 @@
% podman-pod-kill(1)
## NAME
-podman\-pod\-kill - Kills all containers in one or more pods with a signal
+podman\-pod\-kill - Kill the main process of each container in one or more pods
## SYNOPSIS
**podman pod kill** [*options*] *pod* ...
diff --git a/docs/podman-pod-stats.1.md b/docs/podman-pod-stats.1.md
index 12fc83cff..962edbda0 100644
--- a/docs/podman-pod-stats.1.md
+++ b/docs/podman-pod-stats.1.md
@@ -1,7 +1,7 @@
% podman-pod-stats(1)
## NAME
-podman\-pod\-stats - Display a live stream of resource usage statistics for the containers in one or more pods
+podman\-pod\-stats - Display a live stream of resource usage stats for containers in one or more pods
## SYNOPSIS
**podman pod stats** [*options*] [*pod*]
diff --git a/docs/podman-pod.1.md b/docs/podman-pod.1.md
index d11614358..b3d002a06 100644
--- a/docs/podman-pod.1.md
+++ b/docs/podman-pod.1.md
@@ -1,7 +1,7 @@
% podman-pod(1)
## NAME
-podman\-pod - Simple management tool for groups of containers, called pods.
+podman\-pod - Management tool for groups of containers, called pods
## SYNOPSIS
**podman pod** *subcommand*
@@ -11,22 +11,22 @@ podman pod is a set of subcommands that manage pods, or groups of containers.
## SUBCOMMANDS
-| Command | Man Page | Description |
-| ------- | -------------------------------------------------------- | ------------------------------------------------------------------------------ |
-| create | [podman-pod-create(1)](podman-pod-create.1.md) | Create a new pod. |
-| exists | [podman-pod-exists(1)](podman-pod-exists.1.md) | Check if a pod exists in local storage. |
-| inspect | [podman-pod-inspect(1)](podman-pod-inspect.1.md) | Displays information describing a pod. |
-| kill | [podman-pod-kill(1)](podman-pod-kill.1.md) | Kill the main process of each container in pod. |
-| pause | [podman-pod-pause(1)](podman-pod-pause.1.md) | Pause one or more pods. |
-| prune | [podman-container-prune(1)](podman-container-prune.1.md) | Remove all stopped containers from local storage. |
-| ps | [podman-pod-ps(1)](podman-pod-ps.1.md) | Prints out information about pods. |
-| restart | [podman-pod-restart(1)](podman-pod-restart.1.md) | Restart one or more pods. |
-| rm | [podman-pod-rm(1)](podman-pod-rm.1.md) | Remove one or more pods. |
-| start | [podman-pod-start(1)](podman-pod-start.1.md) | Start one or more pods. |
-| stats | [podman-pod-stats(1)](podman-pod-stats.1.md) | Display live stream resource usage stats for containers in one or more pods. |
-| stop | [podman-pod-stop(1)](podman-pod-stop.1.md) | Stop one or more pods. |
-| top | [podman-pod-top(1)](podman-pod-top.1.md) | Display the running processes of containers in a pod. |
-| unpause | [podman-pod-unpause(1)](podman-pod-unpause.1.md) | Unpause one or more pods. |
+| Command | Man Page | Description |
+| ------- | ------------------------------------------------- | --------------------------------------------------------------------------------- |
+| create | [podman-pod-create(1)](podman-pod-create.1.md) | Create a new pod. |
+| exists | [podman-pod-exists(1)](podman-pod-exists.1.md) | Check if a pod exists in local storage. |
+| inspect | [podman-pod-inspect(1)](podman-pod-inspect.1.md) | Displays information describing a pod. |
+| kill | [podman-pod-kill(1)](podman-pod-kill.1.md) | Kill the main process of each container in one or more pods. |
+| pause | [podman-pod-pause(1)](podman-pod-pause.1.md) | Pause one or more pods. |
+| prune | [podman-pod-prune(1)](podman-pod-prune.1.md) | Remove all stopped pods. |
+| ps | [podman-pod-ps(1)](podman-pod-ps.1.md) | Prints out information about pods. |
+| restart | [podman-pod-restart(1)](podman-pod-restart.1.md) | Restart one or more pods. |
+| rm | [podman-pod-rm(1)](podman-pod-rm.1.md) | Remove one or more pods. |
+| start | [podman-pod-start(1)](podman-pod-start.1.md) | Start one or more pods. |
+| stats | [podman-pod-stats(1)](podman-pod-stats.1.md) | Display a live stream of resource usage stats for containers in one or more pods. |
+| stop | [podman-pod-stop(1)](podman-pod-stop.1.md) | Stop one or more pods. |
+| top | [podman-pod-top(1)](podman-pod-top.1.md) | Display the running processes of containers in a pod. |
+| unpause | [podman-pod-unpause(1)](podman-pod-unpause.1.md) | Unpause one or more pods. |
## SEE ALSO
podman(1)
diff --git a/docs/podman-port.1.md b/docs/podman-port.1.md
index bee15c881..c9833f447 100644
--- a/docs/podman-port.1.md
+++ b/docs/podman-port.1.md
@@ -6,6 +6,8 @@ podman\-port - List port mappings for a container
## SYNOPSIS
**podman port** [*options*] *container* [*private-port*[/*proto*]]
+**podman container port** [*options*] *container* [*private-port*[/*proto*]]
+
## DESCRIPTION
List port mappings for the *container* or lookup the public-facing port that is NAT-ed to the *private-port*.
diff --git a/docs/podman-ps.1.md b/docs/podman-ps.1.md
index e3aaf93e2..298de0b2b 100644
--- a/docs/podman-ps.1.md
+++ b/docs/podman-ps.1.md
@@ -6,6 +6,16 @@ podman\-ps - Prints out information about containers
## SYNOPSIS
**podman ps** [*options*]
+**podman container list** [*options*]
+
+**podman container ls** [*options*]
+
+**podman container ps** [*options*]
+
+**podman list** [*options*]
+
+**podman ls** [*options*]
+
## DESCRIPTION
**podman ps** lists the running containers on the system. Use the **--all** flag to view
all the containers information. By default it lists:
diff --git a/docs/podman-pull.1.md b/docs/podman-pull.1.md
index 8774075e1..9976bc586 100644
--- a/docs/podman-pull.1.md
+++ b/docs/podman-pull.1.md
@@ -6,6 +6,8 @@ podman\-pull - Pull an image from a registry
## SYNOPSIS
**podman pull** [*options*] *name*[:*tag*|@*digest*]
+**podman image pull** [*options*] *name*[:*tag*|@*digest*]
+
## DESCRIPTION
Copies an image from a registry onto the local machine. **podman pull** pulls an
image from Docker Hub if a registry is not specified in the command line argument.
diff --git a/docs/podman-push.1.md b/docs/podman-push.1.md
index 29e4044a3..1cf8fd1a6 100644
--- a/docs/podman-push.1.md
+++ b/docs/podman-push.1.md
@@ -6,6 +6,8 @@ podman\-push - Push an image from local storage to elsewhere
## SYNOPSIS
**podman push** [*options*] *image* [*destination*]
+**podman image push** [*options*] *image* [*destination*]
+
## DESCRIPTION
Pushes an image from local storage to a specified destination.
Push is mainly used to push images to registries, however **podman push**
diff --git a/docs/podman-restart.1.md b/docs/podman-restart.1.md
index 643eb1b03..08fa29244 100644
--- a/docs/podman-restart.1.md
+++ b/docs/podman-restart.1.md
@@ -6,6 +6,8 @@ podman\-restart - Restart one or more containers
## SYNOPSIS
**podman restart** [*options*] *container* ...
+**podman container restart** [*options*] *container* ...
+
## DESCRIPTION
The restart command allows containers to be restarted using their ID or name.
Containers will be stopped if they are running and then restarted. Stopped
diff --git a/docs/podman-rm.1.md b/docs/podman-rm.1.md
index 7f39c09ad..88339af16 100644
--- a/docs/podman-rm.1.md
+++ b/docs/podman-rm.1.md
@@ -1,13 +1,13 @@
% podman-rm(1)
## NAME
-podman\-container\-rm (podman\-rm) - Remove one or more containers
+podman\-rm - Remove one or more containers
## SYNOPSIS
-**podman container rm** [*options*] *container*
-
**podman rm** [*options*] *container*
+**podman container rm** [*options*] *container*
+
## DESCRIPTION
**podman rm** will remove one or more containers from the host. The container name or ID can be used. This does not remove images. Running containers will not be removed without the `-f` option
diff --git a/docs/podman-rmi.1.md b/docs/podman-rmi.1.md
index 6b242c94e..d911ee6cb 100644
--- a/docs/podman-rmi.1.md
+++ b/docs/podman-rmi.1.md
@@ -1,13 +1,13 @@
% podman-rmi(1)
## NAME
-podman\-image\-rm (podman\-rmi) - Removes one or more images
+podman\-rmi - Removes one or more locally stored images
## SYNOPSIS
-**podman image rm** *image* [...]
-
**podman rmi** *image* [...]
+**podman image rm** *image* [...]
+
## DESCRIPTION
Removes one or more locally stored images.
diff --git a/docs/podman-run.1.md b/docs/podman-run.1.md
index 447d4f282..8fb7453fe 100644
--- a/docs/podman-run.1.md
+++ b/docs/podman-run.1.md
@@ -6,6 +6,8 @@ podman\-run - Run a command in a new container
## SYNOPSIS
**podman run** [*options*] *image* [*command* [*arg* ...]]
+**podman container run** [*options*] *image* [*command* [*arg* ...]]
+
## DESCRIPTION
Run a process in a new container. **podman run** starts a process with its own
diff --git a/docs/podman-save.1.md b/docs/podman-save.1.md
index 034d2696f..b2b0995d3 100644
--- a/docs/podman-save.1.md
+++ b/docs/podman-save.1.md
@@ -6,6 +6,8 @@ podman\-save - Save an image to a container archive
## SYNOPSIS
**podman save** [*options*] *name*[:*tag*]
+**podman image save** [*options*] *name*[:*tag*]
+
## DESCRIPTION
**podman save** saves an image to either **docker-archive**, **oci-archive**, **oci-dir** (directory with oci manifest type), or **docker-dir** (directory with v2s2 manifest type) on the local machine,
default is **docker-archive**. **podman save** writes to STDOUT by default and can be redirected to a
diff --git a/docs/podman-start.1.md b/docs/podman-start.1.md
index 5ec6e2ea2..4c81d17bd 100644
--- a/docs/podman-start.1.md
+++ b/docs/podman-start.1.md
@@ -6,6 +6,8 @@ podman\-start - Start one or more containers
## SYNOPSIS
**podman start** [*options*] *container* ...
+**podman container start** [*options*] *container* ...
+
## DESCRIPTION
Start one or more containers. You may use container IDs or names as input. The *attach* and *interactive*
options cannot be used to override the *--tty* and *--interactive* options from when the container
diff --git a/docs/podman-stats.1.md b/docs/podman-stats.1.md
index 2f604644f..e0cff0dc2 100644
--- a/docs/podman-stats.1.md
+++ b/docs/podman-stats.1.md
@@ -1,11 +1,13 @@
% podman-stats(1)
## NAME
-podman\-stats - Display a live stream of 1 or more containers' resource usage statistics
+podman\-stats - Display a live stream of one or more container's resource usage statistics
## SYNOPSIS
**podman stats** [*options*] [*container*]
+**podman container stats** [*options*] [*container*]
+
## DESCRIPTION
Display a live stream of one or more containers' resource usage statistics
diff --git a/docs/podman-stop.1.md b/docs/podman-stop.1.md
index e2c4e8b44..b5ea670b0 100644
--- a/docs/podman-stop.1.md
+++ b/docs/podman-stop.1.md
@@ -1,11 +1,13 @@
% podman-stop(1)
## NAME
-podman\-stop - Stop one or more containers
+podman\-stop - Stop one or more running containers
## SYNOPSIS
**podman stop** [*options*] *container* ...
+**podman container stop** [*options*] *container* ...
+
## DESCRIPTION
Stops one or more containers. You may use container IDs or names as input. The **--timeout** switch
allows you to specify the number of seconds to wait before forcibly stopping the container after the stop command
diff --git a/docs/podman-system-migrate.1.md b/docs/podman-system-migrate.1.md
index 1efa779ce..d175d0344 100644
--- a/docs/podman-system-migrate.1.md
+++ b/docs/podman-system-migrate.1.md
@@ -1,7 +1,7 @@
% podman-system-migrate(1)
## NAME
-podman\-system\-migrate - Migrate container to the latest version of podman
+podman\-system\-migrate - Migrate existing containers to a new podman version
## SYNOPSIS
** podman system migrate**
diff --git a/docs/podman-system-renumber.1.md b/docs/podman-system-renumber.1.md
index af498f270..071eefe29 100644
--- a/docs/podman-system-renumber.1.md
+++ b/docs/podman-system-renumber.1.md
@@ -1,7 +1,7 @@
% podman-system-renumber(1)
## NAME
-podman\-system\-renumber - Renumber container locks
+podman\-system\-renumber - Migrate lock numbers to handle a change in maximum number of locks
## SYNOPSIS
**podman system renumber**
diff --git a/docs/podman-system.1.md b/docs/podman-system.1.md
index d36715feb..bbd541066 100644
--- a/docs/podman-system.1.md
+++ b/docs/podman-system.1.md
@@ -15,7 +15,7 @@ The system command allows you to manage the podman systems
| ------- | --------------------------------------------------- | ---------------------------------------------------------------------------- |
| df | [podman-system-df(1)](podman-system-df.1.md) | Show podman disk usage. |
| info | [podman-system-info(1)](podman-info.1.md) | Displays Podman related system information. |
-| prune | [podman-system-prune(1)](podman-system-prune.1.md) | Remove all unused data |
+| prune | [podman-system-prune(1)](podman-system-prune.1.md) | Remove all unused container, image and volume data |
| renumber | [podman-system-renumber(1)](podman-system-renumber.1.md)| Migrate lock numbers to handle a change in maximum number of locks. |
| migrate | [podman-system-migrate(1)](podman-system-migrate.1.md)| Migrate existing containers to a new podman version. |
diff --git a/docs/podman-tag.1.md b/docs/podman-tag.1.md
index f3851d8b6..291d95228 100644
--- a/docs/podman-tag.1.md
+++ b/docs/podman-tag.1.md
@@ -6,6 +6,7 @@ podman\-tag - Add an additional name to a local image
## SYNOPSIS
**podman tag** *image*[:*tag*] *target-name*[:*tag*] [*options*]
+**podman image tag** *image*[:*tag*] *target-name*[:*tag*] [*options*]
## DESCRIPTION
Assigns a new alias to an image. An alias refers to the entire image name, including the optional
diff --git a/docs/podman-top.1.md b/docs/podman-top.1.md
index 564c2f067..1410aa651 100644
--- a/docs/podman-top.1.md
+++ b/docs/podman-top.1.md
@@ -6,6 +6,8 @@ podman\-top - Display the running processes of a container
## SYNOPSIS
**podman top** [*options*] *container* [*format-descriptors*]
+**podman container top** [*options*] *container* [*format-descriptors*]
+
## DESCRIPTION
Display the running processes of the container. The *format-descriptors* are ps (1) compatible AIX format descriptors but extended to print additional information, such as the seccomp mode or the effective capabilities of a given process. The descriptors can either be passed as separated arguments or as a single comma-separated argument. Note that you can also specify options and or flags of ps(1); in this case, Podman will fallback to executing ps with the specified arguments and flags in the container.
diff --git a/docs/podman-umount.1.md b/docs/podman-umount.1.md
index 8ef7b20ac..100c47b32 100644
--- a/docs/podman-umount.1.md
+++ b/docs/podman-umount.1.md
@@ -1,11 +1,17 @@
% podman-umount(1)
## NAME
-podman\-umount - Unmount the specified working containers' root file system.
+podman\-umount - Unmount a working container's root filesystem
## SYNOPSIS
**podman umount** *container* [...]
+**podman container umount** *container* [...]
+
+**podman container unmount** *container* [...]
+
+**podman unmount** *container* [...]
+
## DESCRIPTION
Unmounts the specified containers' root file system, if no other processes
are using it.
diff --git a/docs/podman-unpause.1.md b/docs/podman-unpause.1.md
index ef8a4cdb6..f5538d6d5 100644
--- a/docs/podman-unpause.1.md
+++ b/docs/podman-unpause.1.md
@@ -6,6 +6,8 @@ podman\-unpause - Unpause one or more containers
## SYNOPSIS
**podman unpause** [*options*]|[*container* ...]
+**podman container unpause** [*options*]|[*container* ...]
+
## DESCRIPTION
Unpauses the processes in one or more containers. You may use container IDs or names as input.
diff --git a/docs/podman-unshare.1.md b/docs/podman-unshare.1.md
index d7fefb774..9052b97ab 100644
--- a/docs/podman-unshare.1.md
+++ b/docs/podman-unshare.1.md
@@ -1,10 +1,10 @@
% podman-unshare(1)
## NAME
-podman\-unshare - Run a command inside of a modified user namespace.
+podman\-unshare - Run a command inside of a modified user namespace
## SYNOPSIS
-**podman unshare** [*options*] [**--**] [*command*]
+**podman unshare** [*options*] [*--*] [*command*]
## DESCRIPTION
Launches a process (by default, *$SHELL*) in a new user namespace. The user
diff --git a/docs/podman-version.1.md b/docs/podman-version.1.md
index cb0a3785f..4499f6338 100644
--- a/docs/podman-version.1.md
+++ b/docs/podman-version.1.md
@@ -1,7 +1,7 @@
% podman-version(1)
## NAME
-podman\-version - Display the PODMAN Version Information
+podman\-version - Display the Podman version information
## SYNOPSIS
**podman version** [*options*]
diff --git a/docs/podman-volume-inspect.1.md b/docs/podman-volume-inspect.1.md
index b00c821bb..a6c99f6c8 100644
--- a/docs/podman-volume-inspect.1.md
+++ b/docs/podman-volume-inspect.1.md
@@ -1,7 +1,7 @@
% podman-volume-inspect(1)
## NAME
-podman\-volume\-inspect - Inspect one or more volumes
+podman\-volume\-inspect - Get detailed information on one or more volumes
## SYNOPSIS
**podman volume inspect** [*options*] *volume* [...]
diff --git a/docs/podman-volume-ls.1.md b/docs/podman-volume-ls.1.md
index ef1582153..d431c7c6e 100644
--- a/docs/podman-volume-ls.1.md
+++ b/docs/podman-volume-ls.1.md
@@ -1,7 +1,7 @@
% podman-volume-ls(1)
## NAME
-podman\-volume\-ls - List volumes
+podman\-volume\-ls - List all the available volumes
## SYNOPSIS
**podman volume ls** [*options*]
diff --git a/docs/podman-volume.1.md b/docs/podman-volume.1.md
index 77728b2b5..288e57b82 100644
--- a/docs/podman-volume.1.md
+++ b/docs/podman-volume.1.md
@@ -1,7 +1,7 @@
% podman-volume(1)
## NAME
-podman\-volume - Simple management tool for volumes.
+podman\-volume - Simple management tool for volumes
## SYNOPSIS
**podman volume** *subcommand*
diff --git a/docs/podman-wait.1.md b/docs/podman-wait.1.md
index e1a810ff1..ce1c70a5f 100644
--- a/docs/podman-wait.1.md
+++ b/docs/podman-wait.1.md
@@ -6,6 +6,8 @@ podman\-wait - Wait on one or more containers to stop and print their exit codes
## SYNOPSIS
**podman wait** [*options*] *container*
+**podman container wait** [*options*] *container*
+
## DESCRIPTION
Waits on one or more containers to stop. The container can be referred to by its
name or ID. In the case of multiple containers, podman will wait on each consecutively.
diff --git a/docs/podman.1.md b/docs/podman.1.md
index 33ea81ef6..742d94bd5 100644
--- a/docs/podman.1.md
+++ b/docs/podman.1.md
@@ -36,7 +36,7 @@ Note: CGroup manager is not supported in rootless mode when using CGroups Versio
Path to where the cpu performance results should be written
-**--events-logger**=*type*
+**--events-backend**=*type*
Backend to use for storing events. Allowed values are **file**, **journald**, and **none**.
@@ -153,15 +153,15 @@ the exit codes follow the `chroot` standard, see below:
| [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-init(1)](podman-init.1.md) | Initialize one or more containers |
| [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-logs(1)](podman-logs.1.md) | Display the logs of one or more containers. |
| [podman-mount(1)](podman-mount.1.md) | Mount a working container's root filesystem. |
-| [podman-network(1)](podman-network.1.md) | Manage Podman CNI networks. |
+| [podman-network(1)](podman-network.1.md) | Manage Podman CNI networks. |
| [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. |
@@ -186,7 +186,7 @@ the exit codes follow the `chroot` standard, see below:
| [podman-unshare(1)](podman-unshare.1.md) | Run a command inside of a modified user namespace. |
| [podman-varlink(1)](podman-varlink.1.md) | Runs the varlink backend interface. |
| [podman-version(1)](podman-version.1.md) | Display the Podman version information. |
-| [podman-volume(1)](podman-volume.1.md) | Manage Volumes. |
+| [podman-volume(1)](podman-volume.1.md) | Simple management tool for 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/docs/tutorials/rootless_tutorial.md b/docs/tutorials/rootless_tutorial.md
index 92595dd02..91962fead 100644
--- a/docs/tutorials/rootless_tutorial.md
+++ b/docs/tutorials/rootless_tutorial.md
@@ -80,6 +80,36 @@ The Podman configuration files for root reside in /usr/share/containers with ove
The default authorization file used by the `podman login` and `podman logout` commands reside in ${XDG\_RUNTIME\_DIR}/containers/auth.json.
+## Systemd unit for rootless container
+
+```
+[Unit]
+Description=nginx
+Requires=user@1001.service
+After=user@1001.service
+
+[Service]
+Type=simple
+KillMode=none
+MemoryMax=200M
+ExecStartPre=-/usr/bin/podman rm -f nginx
+ExecStartPre=/usr/bin/podman pull nginx
+ExecStart=/usr/bin/podman run --name=nginx -p 8080:80 -v /home/nginx/html:/usr/share/nginx/html:Z nginx
+ExecStop=/usr/bin/podman stop nginx
+Restart=always
+User=nginx
+Group=nginx
+
+[Install]
+WantedBy=multi-user.target
+```
+
+This example unit will launch a nginx container using the existing user nginx with id 1001, serving static content from /home/nginx/html and limited to 200MB of RAM.
+
+You can use all the usual systemd flags to control the process, including capabilities and cgroup directives to limit memory or CPU.
+
+See #3866 for more details.
+
## More information
If you are still experiencing problems running Podman in a rootless environment, please refer to the [Shortcomings of Rootless Podman](https://github.com/containers/libpod/blob/master/rootless.md) page which lists known issues and solutions to known issues in this environment.
diff --git a/hack/get_release_info.sh b/hack/get_release_info.sh
new file mode 100755
index 000000000..29b4237b4
--- /dev/null
+++ b/hack/get_release_info.sh
@@ -0,0 +1,54 @@
+#!/bin/bash
+
+# This script produces various bits of metadata needed by Makefile. Using
+# a script allows uniform behavior across multiple environments and
+# distributions. The script expects a single argument, as reflected below.
+
+set -e
+
+cd "${GOSRC:-$(dirname $0)/../}"
+
+valid_args() {
+ REGEX='^\s+[[:upper:]]+\*[)]'
+ egrep --text --no-filename --group-separator=' ' --only-matching "$REGEX" "$0" | \
+ cut -d '*' -f 1
+}
+
+unset OUTPUT
+case "$1" in
+ # Wild-card suffix needed by valid_args() e.g. possible bad grep of "$(echo $FOO)"
+ VERSION*)
+ OUTPUT="${CIRRUS_TAG:-$(git fetch --tags && git describe HEAD 2> /dev/null)}"
+ ;;
+ NUMBER*)
+ OUTPUT="$($0 VERSION | sed 's/-.*//')"
+ ;;
+ DIST_VER*)
+ OUTPUT="$(source /etc/os-release; echo $VERSION_ID | cut -d '.' -f 1)"
+ ;;
+ DIST*)
+ OUTPUT="$(source /etc/os-release; echo $ID)"
+ ;;
+ ARCH*)
+ OUTPUT="${GOARCH:-$(go env GOARCH 2> /dev/null)}"
+ ;;
+ BASENAME*)
+ OUTPUT="${CIRRUS_REPO_NAME:-$(basename $(git rev-parse --show-toplevel))}"
+ ;;
+ REMOTENAME*)
+ OUTPUT="$($0 BASENAME)-remote"
+ ;;
+ *)
+ echo "Error, unknown/unsupported argument '$1', valid arguments:"
+ valid_args
+ exit 1
+ ;;
+esac
+
+if [[ -n "$OUTPUT" ]]
+then
+ echo -n "$OUTPUT"
+else
+ echo "Error, empty output for info: '$1'" > /dev/stderr
+ exit 2
+fi
diff --git a/hack/man-page-checker b/hack/man-page-checker
index 8e9b5a50d..ab1921b86 100755
--- a/hack/man-page-checker
+++ b/hack/man-page-checker
@@ -39,8 +39,9 @@ done
# Pass 2: compare descriptions.
#
# Make sure the descriptive text in podman-foo.1.md matches the one
-# in the table in podman.1.md.
-for md in *.1.md;do
+# in the table in podman.1.md. podman-remote is not a podman subcommand,
+# so it is excluded here.
+for md in $(ls -1 *-*.1.md | grep -v remote);do
desc=$(egrep -A1 '^#* NAME' $md|tail -1|sed -e 's/^podman[^ ]\+ - //')
# podman.1.md has a two-column table; podman-*.1.md all have three.
diff --git a/libpod/container_api.go b/libpod/container_api.go
index 9e59104cc..9bf97c5d4 100644
--- a/libpod/container_api.go
+++ b/libpod/container_api.go
@@ -14,7 +14,6 @@ import (
"github.com/opentracing/opentracing-go"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
- "k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/tools/remotecommand"
)
@@ -524,24 +523,25 @@ func (c *Container) WaitWithInterval(waitTimeout time.Duration) (int32, error) {
if !c.valid {
return -1, define.ErrCtrRemoved
}
- err := wait.PollImmediateInfinite(waitTimeout,
- func() (bool, error) {
- logrus.Debugf("Checking container %s status...", c.ID())
- stopped, err := c.isStopped()
- if err != nil {
- return false, err
- }
- if !stopped {
- return false, nil
- }
- return true, nil
- },
- )
- if err != nil {
- return 0, err
+
+ exitFile := c.exitFilePath()
+ chWait := make(chan error, 1)
+
+ defer close(chWait)
+
+ for {
+ // ignore errors here, it is only used to avoid waiting
+ // too long.
+ _, _ = WaitForFile(exitFile, chWait, waitTimeout)
+
+ stopped, err := c.isStopped()
+ if err != nil {
+ return -1, err
+ }
+ if stopped {
+ return c.state.ExitCode, nil
+ }
}
- exitCode := c.state.ExitCode
- return exitCode, nil
}
// Cleanup unmounts all mount points in container and cleans up container storage
diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go
index 5aa4ee9a9..cb19b5484 100644
--- a/libpod/container_internal_linux.go
+++ b/libpod/container_internal_linux.go
@@ -1039,6 +1039,11 @@ func (c *Container) makeBindMounts() error {
// generateResolvConf generates a containers resolv.conf
func (c *Container) generateResolvConf() (string, error) {
+ var (
+ nameservers []string
+ cniNameServers []string
+ )
+
resolvConf := "/etc/resolv.conf"
for _, namespace := range c.config.Spec.Linux.Namespaces {
if namespace.Type == spec.NetworkNamespace {
@@ -1074,18 +1079,31 @@ func (c *Container) generateResolvConf() (string, error) {
return "", errors.Wrapf(err, "error parsing host resolv.conf")
}
- // Make a new resolv.conf
- nameservers := resolvconf.GetNameservers(resolv.Content)
- // slirp4netns has a built in DNS server.
- if c.config.NetMode.IsSlirp4netns() {
- nameservers = append([]string{"10.0.2.3"}, nameservers...)
+ // Check if CNI gave back and DNS servers for us to add in
+ cniResponse := c.state.NetworkStatus
+ for _, i := range cniResponse {
+ if i.DNS.Nameservers != nil {
+ cniNameServers = append(cniNameServers, i.DNS.Nameservers...)
+ logrus.Debugf("adding nameserver(s) from cni response of '%q'", i.DNS.Nameservers)
+ }
}
+
+ // If the user provided dns, it trumps all; then dns masq; then resolv.conf
if len(c.config.DNSServer) > 0 {
// We store DNS servers as net.IP, so need to convert to string
- nameservers = []string{}
for _, server := range c.config.DNSServer {
nameservers = append(nameservers, server.String())
}
+ } else if len(cniNameServers) > 0 {
+ nameservers = append(nameservers, cniNameServers...)
+ } else {
+ // Make a new resolv.conf
+ nameservers = resolvconf.GetNameservers(resolv.Content)
+ // slirp4netns has a built in DNS server.
+ if c.config.NetMode.IsSlirp4netns() {
+ nameservers = append([]string{"10.0.2.3"}, nameservers...)
+ }
+
}
search := resolvconf.GetSearchDomains(resolv.Content)
diff --git a/libpod/util.go b/libpod/util.go
index b60575264..164800af4 100644
--- a/libpod/util.go
+++ b/libpod/util.go
@@ -69,7 +69,11 @@ func WaitForFile(path string, chWait chan error, timeout time.Duration) (bool, e
defer watcher.Close()
}
- timeoutChan := time.After(timeout)
+ var timeoutChan <-chan time.Time
+
+ if timeout != 0 {
+ timeoutChan = time.After(timeout)
+ }
for {
select {
diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go
index 6e48988c5..ecb84f6a9 100644
--- a/pkg/rootless/rootless_linux.go
+++ b/pkg/rootless/rootless_linux.go
@@ -3,7 +3,9 @@
package rootless
import (
+ "bufio"
"fmt"
+ "io"
"io/ioutil"
"os"
"os/exec"
@@ -106,7 +108,7 @@ func tryMappingTool(tool string, pid int, hostID int, mappings []idtools.IDMap)
}
appendTriplet := func(l []string, a, b, c int) []string {
- return append(l, fmt.Sprintf("%d", a), fmt.Sprintf("%d", b), fmt.Sprintf("%d", c))
+ return append(l, strconv.Itoa(a), strconv.Itoa(b), strconv.Itoa(c))
}
args := []string{path, fmt.Sprintf("%d", pid)}
@@ -345,6 +347,32 @@ func joinUserAndMountNS(pid uint, pausePid string) (bool, int, error) {
return true, int(ret), nil
}
+// GetConfiguredMappings returns the additional IDs configured for the current user.
+func GetConfiguredMappings() ([]idtools.IDMap, []idtools.IDMap, error) {
+ var uids, gids []idtools.IDMap
+ username := os.Getenv("USER")
+ if username == "" {
+ var id string
+ if os.Geteuid() == 0 {
+ id = strconv.Itoa(GetRootlessUID())
+ } else {
+ id = strconv.Itoa(os.Geteuid())
+ }
+ userID, err := user.LookupId(id)
+ if err == nil {
+ username = userID.Username
+ }
+ }
+ mappings, err := idtools.NewIDMappings(username, username)
+ if err != nil {
+ logrus.Warnf("cannot find mappings for user %s: %v", username, err)
+ } else {
+ uids = mappings.UIDs()
+ gids = mappings.GIDs()
+ }
+ return uids, gids, nil
+}
+
func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (bool, int, error) {
if os.Geteuid() == 0 || os.Getenv("_CONTAINERS_USERNS_CONFIGURED") != "" {
if os.Getenv("_CONTAINERS_USERNS_CONFIGURED") == "init" {
@@ -386,25 +414,14 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (bool,
return false, -1, errors.Errorf("cannot re-exec process")
}
- var uids, gids []idtools.IDMap
- username := os.Getenv("USER")
- if username == "" {
- userID, err := user.LookupId(fmt.Sprintf("%d", os.Getuid()))
- if err == nil {
- username = userID.Username
- }
- }
- mappings, err := idtools.NewIDMappings(username, username)
+ uids, gids, err := GetConfiguredMappings()
if err != nil {
- logrus.Warnf("cannot find mappings for user %s: %v", username, err)
- } else {
- uids = mappings.UIDs()
- gids = mappings.GIDs()
+ return false, -1, err
}
uidsMapped := false
- if mappings != nil && uids != nil {
- err := tryMappingTool("newuidmap", pid, os.Getuid(), uids)
+ if uids != nil {
+ err := tryMappingTool("newuidmap", pid, os.Geteuid(), uids)
uidsMapped = err == nil
}
if !uidsMapped {
@@ -416,20 +433,20 @@ func becomeRootInUserNS(pausePid, fileToRead string, fileOutput *os.File) (bool,
}
uidMap := fmt.Sprintf("/proc/%d/uid_map", pid)
- err = ioutil.WriteFile(uidMap, []byte(fmt.Sprintf("%d %d 1\n", 0, os.Getuid())), 0666)
+ err = ioutil.WriteFile(uidMap, []byte(fmt.Sprintf("%d %d 1\n", 0, os.Geteuid())), 0666)
if err != nil {
return false, -1, errors.Wrapf(err, "cannot write uid_map")
}
}
gidsMapped := false
- if mappings != nil && gids != nil {
- err := tryMappingTool("newgidmap", pid, os.Getgid(), gids)
+ if gids != nil {
+ err := tryMappingTool("newgidmap", pid, os.Getegid(), gids)
gidsMapped = err == nil
}
if !gidsMapped {
gidMap := fmt.Sprintf("/proc/%d/gid_map", pid)
- err = ioutil.WriteFile(gidMap, []byte(fmt.Sprintf("%d %d 1\n", 0, os.Getgid())), 0666)
+ err = ioutil.WriteFile(gidMap, []byte(fmt.Sprintf("%d %d 1\n", 0, os.Getegid())), 0666)
if err != nil {
return false, -1, errors.Wrapf(err, "cannot write gid_map")
}
@@ -586,3 +603,85 @@ func TryJoinFromFilePaths(pausePidPath string, needNewNamespace bool, paths []st
return joinUserAndMountNS(uint(pausePid), pausePidPath)
}
+func readMappingsProc(path string) ([]idtools.IDMap, error) {
+ file, err := os.Open(path)
+ if err != nil {
+ return nil, errors.Wrapf(err, "cannot open %s", path)
+ }
+ defer file.Close()
+
+ mappings := []idtools.IDMap{}
+
+ buf := bufio.NewReader(file)
+ for {
+ line, _, err := buf.ReadLine()
+ if err != nil {
+ if err == io.EOF {
+ return mappings, nil
+ }
+ return nil, errors.Wrapf(err, "cannot read line from %s", path)
+ }
+ if line == nil {
+ return mappings, nil
+ }
+
+ containerID, hostID, size := 0, 0, 0
+ if _, err := fmt.Sscanf(string(line), "%d %d %d", &containerID, &hostID, &size); err != nil {
+ return nil, errors.Wrapf(err, "cannot parse %s", string(line))
+ }
+ mappings = append(mappings, idtools.IDMap{ContainerID: containerID, HostID: hostID, Size: size})
+ }
+}
+
+func matches(id int, configuredIDs []idtools.IDMap, currentIDs []idtools.IDMap) bool {
+ // The first mapping is the host user, handle it separately.
+ if currentIDs[0].HostID != id || currentIDs[0].Size != 1 {
+ return false
+ }
+
+ currentIDs = currentIDs[1:]
+ if len(currentIDs) != len(configuredIDs) {
+ return false
+ }
+
+ // It is fine to iterate sequentially as both slices are sorted.
+ for i := range currentIDs {
+ if currentIDs[i].HostID != configuredIDs[i].HostID {
+ return false
+ }
+ if currentIDs[i].Size != configuredIDs[i].Size {
+ return false
+ }
+ }
+
+ return true
+}
+
+// ConfigurationMatches checks whether the additional uids/gids configured for the user
+// match the current user namespace.
+func ConfigurationMatches() (bool, error) {
+ if !IsRootless() || os.Geteuid() != 0 {
+ return true, nil
+ }
+
+ uids, gids, err := GetConfiguredMappings()
+ if err != nil {
+ return false, err
+ }
+
+ currentUIDs, err := readMappingsProc("/proc/self/uid_map")
+ if err != nil {
+ return false, err
+ }
+
+ if !matches(GetRootlessUID(), uids, currentUIDs) {
+ return false, err
+ }
+
+ currentGIDs, err := readMappingsProc("/proc/self/gid_map")
+ if err != nil {
+ return false, err
+ }
+
+ return matches(GetRootlessGID(), gids, currentGIDs), nil
+}
diff --git a/pkg/rootless/rootless_unsupported.go b/pkg/rootless/rootless_unsupported.go
index a8485c083..ddd9182b0 100644
--- a/pkg/rootless/rootless_unsupported.go
+++ b/pkg/rootless/rootless_unsupported.go
@@ -5,6 +5,7 @@ package rootless
import (
"os"
+ "github.com/containers/storage/pkg/idtools"
"github.com/pkg/errors"
)
@@ -53,3 +54,14 @@ func EnableLinger() (string, error) {
func TryJoinFromFilePaths(pausePidPath string, needNewNamespace bool, paths []string) (bool, int, error) {
return false, -1, errors.New("this function is not supported on this os")
}
+
+// ConfigurationMatches checks whether the additional uids/gids configured for the user
+// match the current user namespace.
+func ConfigurationMatches() (bool, error) {
+ return true, nil
+}
+
+// GetConfiguredMappings returns the additional IDs configured for the current user.
+func GetConfiguredMappings() ([]idtools.IDMap, []idtools.IDMap, error) {
+ return nil, nil, errors.New("this function is not supported on this os")
+}
diff --git a/pkg/spec/config_linux.go b/pkg/spec/config_linux.go
index 60d31d78e..32d8cb4de 100644
--- a/pkg/spec/config_linux.go
+++ b/pkg/spec/config_linux.go
@@ -4,6 +4,7 @@ package createconfig
import (
"fmt"
+ "io/ioutil"
"os"
"path/filepath"
"strings"
@@ -98,6 +99,26 @@ func addDevice(g *generate.Generator, device string) error {
if err != nil {
return errors.Wrapf(err, "%s is not a valid device", src)
}
+ if rootless.IsRootless() {
+ if _, err := os.Stat(src); err != nil {
+ if os.IsNotExist(err) {
+ return errors.Wrapf(err, "the specified device %s doesn't exist", src)
+ }
+ return errors.Wrapf(err, "stat device %s exist", src)
+ }
+ perm := "ro"
+ if strings.Contains(permissions, "w") {
+ perm = "rw"
+ }
+ devMnt := spec.Mount{
+ Destination: dst,
+ Type: TypeBind,
+ Source: src,
+ Options: []string{"slave", "nosuid", "noexec", perm, "rbind"},
+ }
+ g.Config.Mounts = append(g.Config.Mounts, devMnt)
+ return nil
+ }
dev.Path = dst
linuxdev := spec.LinuxDevice{
Path: dev.Path,
@@ -113,8 +134,53 @@ func addDevice(g *generate.Generator, device string) error {
return nil
}
+// based on getDevices from runc (libcontainer/devices/devices.go)
+func getDevices(path string) ([]*configs.Device, error) {
+ files, err := ioutil.ReadDir(path)
+ if err != nil {
+ if rootless.IsRootless() && os.IsPermission(err) {
+ return nil, nil
+ }
+ return nil, err
+ }
+ out := []*configs.Device{}
+ for _, f := range files {
+ switch {
+ case f.IsDir():
+ switch f.Name() {
+ // ".lxc" & ".lxd-mounts" added to address https://github.com/lxc/lxd/issues/2825
+ case "pts", "shm", "fd", "mqueue", ".lxc", ".lxd-mounts":
+ continue
+ default:
+ sub, err := getDevices(filepath.Join(path, f.Name()))
+ if err != nil {
+ return nil, err
+ }
+ if sub != nil {
+ out = append(out, sub...)
+ }
+ continue
+ }
+ case f.Name() == "console":
+ continue
+ }
+ device, err := devices.DeviceFromPath(filepath.Join(path, f.Name()), "rwm")
+ if err != nil {
+ if err == devices.ErrNotADevice {
+ continue
+ }
+ if os.IsNotExist(err) {
+ continue
+ }
+ return nil, err
+ }
+ out = append(out, device)
+ }
+ return out, nil
+}
+
func (c *CreateConfig) addPrivilegedDevices(g *generate.Generator) error {
- hostDevices, err := devices.HostDevices()
+ hostDevices, err := getDevices("/dev")
if err != nil {
return err
}
@@ -153,15 +219,16 @@ func (c *CreateConfig) addPrivilegedDevices(g *generate.Generator) error {
newMounts = append(newMounts, devMnt)
}
g.Config.Mounts = append(newMounts, g.Config.Mounts...)
+ g.Config.Linux.Resources.Devices = nil
} else {
for _, d := range hostDevices {
g.AddDevice(Device(d))
}
+ // Add resources device - need to clear the existing one first.
+ g.Config.Linux.Resources.Devices = nil
+ g.AddLinuxResourcesDevice(true, "", nil, nil, "rwm")
}
- // Add resources device - need to clear the existing one first.
- g.Config.Linux.Resources.Devices = nil
- g.AddLinuxResourcesDevice(true, "", nil, nil, "rwm")
return nil
}
diff --git a/pkg/util/utils.go b/pkg/util/utils.go
index 3f73639e7..2261934f0 100644
--- a/pkg/util/utils.go
+++ b/pkg/util/utils.go
@@ -3,7 +3,6 @@ package util
import (
"fmt"
"os"
- ouser "os/user"
"path/filepath"
"strings"
"sync"
@@ -156,22 +155,15 @@ func ParseIDMapping(mode namespaces.UsernsMode, UIDMapSlice, GIDMapSlice []strin
uid := rootless.GetRootlessUID()
gid := rootless.GetRootlessGID()
- username := os.Getenv("USER")
- if username == "" {
- user, err := ouser.LookupId(fmt.Sprintf("%d", uid))
- if err == nil {
- username = user.Username
- }
- }
- mappings, err := idtools.NewIDMappings(username, username)
+ uids, gids, err := rootless.GetConfiguredMappings()
if err != nil {
- return nil, errors.Wrapf(err, "cannot find mappings for user %s", username)
+ return nil, errors.Wrapf(err, "cannot read mappings")
}
maxUID, maxGID := 0, 0
- for _, u := range mappings.UIDs() {
+ for _, u := range uids {
maxUID += u.Size
}
- for _, g := range mappings.GIDs() {
+ for _, g := range gids {
maxGID += g.Size
}
diff --git a/pkg/varlinkapi/images.go b/pkg/varlinkapi/images.go
index c184155a9..0bdbec177 100644
--- a/pkg/varlinkapi/images.go
+++ b/pkg/varlinkapi/images.go
@@ -563,7 +563,6 @@ func (i *LibpodAPI) Commit(call iopodman.VarlinkCall, name, imageName string, ch
}
c := make(chan error)
- defer close(c)
go func() {
newImage, err = ctr.Commit(getContext(), imageName, options)
@@ -571,6 +570,7 @@ func (i *LibpodAPI) Commit(call iopodman.VarlinkCall, name, imageName string, ch
c <- err
}
c <- nil
+ close(c)
}()
// reply is the func being sent to the output forwarder. in this case it is replying
diff --git a/test/e2e/run_device_test.go b/test/e2e/run_device_test.go
index cf7ce9cdf..d3b4b0e32 100644
--- a/test/e2e/run_device_test.go
+++ b/test/e2e/run_device_test.go
@@ -35,44 +35,40 @@ var _ = Describe("Podman run device", func() {
})
It("podman run bad device test", func() {
- session := podmanTest.Podman([]string{"run", "-q", "--device", "/dev/baddevice", ALPINE, "ls", "/dev/kmsg"})
+ session := podmanTest.Podman([]string{"run", "-q", "--device", "/dev/baddevice", ALPINE, "true"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Not(Equal(0)))
})
It("podman run device test", func() {
- SkipIfRootless()
- session := podmanTest.Podman([]string{"run", "-q", "--device", "/dev/kmsg", ALPINE, "ls", "--color=never", "/dev/kmsg"})
+ session := podmanTest.Podman([]string{"run", "-q", "--security-opt", "label=disable", "--device", "/dev/kmsg", ALPINE, "ls", "--color=never", "/dev/kmsg"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(Equal("/dev/kmsg"))
})
It("podman run device rename test", func() {
- SkipIfRootless()
- session := podmanTest.Podman([]string{"run", "-q", "--device", "/dev/kmsg:/dev/kmsg1", ALPINE, "ls", "--color=never", "/dev/kmsg1"})
+ session := podmanTest.Podman([]string{"run", "-q", "--security-opt", "label=disable", "--device", "/dev/kmsg:/dev/kmsg1", ALPINE, "ls", "--color=never", "/dev/kmsg1"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(Equal("/dev/kmsg1"))
})
It("podman run device permission test", func() {
- SkipIfRootless()
- session := podmanTest.Podman([]string{"run", "-q", "--device", "/dev/kmsg:r", ALPINE, "ls", "--color=never", "/dev/kmsg"})
+ session := podmanTest.Podman([]string{"run", "-q", "--security-opt", "label=disable", "--device", "/dev/kmsg:r", ALPINE, "ls", "--color=never", "/dev/kmsg"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(Equal("/dev/kmsg"))
})
It("podman run device rename and permission test", func() {
- SkipIfRootless()
- session := podmanTest.Podman([]string{"run", "-q", "--device", "/dev/kmsg:/dev/kmsg1:r", ALPINE, "ls", "--color=never", "/dev/kmsg1"})
+ session := podmanTest.Podman([]string{"run", "-q", "--security-opt", "label=disable", "--device", "/dev/kmsg:/dev/kmsg1:r", ALPINE, "ls", "--color=never", "/dev/kmsg1"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
Expect(session.OutputToString()).To(Equal("/dev/kmsg1"))
})
It("podman run device rename and bad permission test", func() {
- session := podmanTest.Podman([]string{"run", "-q", "--device", "/dev/kmsg:/dev/kmsg1:rd", ALPINE, "ls", "--color=never", "/dev/kmsg1"})
+ session := podmanTest.Podman([]string{"run", "-q", "--security-opt", "label=disable", "--device", "/dev/kmsg:/dev/kmsg1:rd", ALPINE, "ls", "--color=never", "/dev/kmsg1"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Not(Equal(0)))
})
diff --git a/test/endpoint/commit.go b/test/endpoint/commit.go
new file mode 100644
index 000000000..476ac6ca3
--- /dev/null
+++ b/test/endpoint/commit.go
@@ -0,0 +1,47 @@
+package endpoint
+
+import (
+ "encoding/json"
+ "os"
+
+ . "github.com/containers/libpod/test/utils"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+)
+
+var _ = Describe("Podman commit", func() {
+ var (
+ tempdir string
+ err error
+ endpointTest *EndpointTestIntegration
+ )
+
+ BeforeEach(func() {
+ tempdir, err = CreateTempDirInTempDir()
+ if err != nil {
+ os.Exit(1)
+ }
+ endpointTest = Setup(tempdir)
+ endpointTest.StartVarlinkWithCache()
+ })
+
+ AfterEach(func() {
+ endpointTest.Cleanup()
+
+ })
+
+ It("ensure commit with uppercase image name does not panic", func() {
+ body := make(map[string]string)
+ body["image_name"] = "FOO"
+ body["format"] = "oci"
+ body["name"] = "top"
+ b, err := json.Marshal(body)
+ Expect(err).To(BeNil())
+ // run the container to be committed
+ _ = endpointTest.startTopContainer("top")
+ result := endpointTest.Varlink("Commit", string(b), false)
+ // This indicates an error occured
+ Expect(len(result.StdErrToString())).To(BeNumerically(">", 0))
+ })
+
+})
diff --git a/test/endpoint/endpoint.go b/test/endpoint/endpoint.go
index 4f9e6055e..78aa957ab 100644
--- a/test/endpoint/endpoint.go
+++ b/test/endpoint/endpoint.go
@@ -189,6 +189,11 @@ func (p *EndpointTestIntegration) Varlink(endpoint, message string, more bool) *
return &EndpointSession{session}
}
+func (s *EndpointSession) StdErrToString() string {
+ fields := strings.Fields(fmt.Sprintf("%s", s.Err.Contents()))
+ return strings.Join(fields, " ")
+}
+
func (s *EndpointSession) OutputToString() string {
fields := strings.Fields(fmt.Sprintf("%s", s.Out.Contents()))
return strings.Join(fields, " ")
diff --git a/test/endpoint/exists_test.go b/test/endpoint/exists_test.go
index c8ab9e0f2..17e252a65 100644
--- a/test/endpoint/exists_test.go
+++ b/test/endpoint/exists_test.go
@@ -8,7 +8,7 @@ import (
. "github.com/onsi/gomega"
)
-var _ = Describe("Podman pull", func() {
+var _ = Describe("Podman exists", func() {
var (
tempdir string
err error
diff --git a/troubleshooting.md b/troubleshooting.md
index b88940dc8..9a5b38e01 100644
--- a/troubleshooting.md
+++ b/troubleshooting.md
@@ -391,3 +391,22 @@ Choose one of the following:
* Install and configure fuse-overlayfs.
* Install the fuse-overlayfs package for your Linux Distribution.
* Add `mount_program = "/usr/bin/fuse-overlayfs` under `[storage.options]` in your `~/.config/containers/storage.conf` file.
+
+### 16) rhel7-init based images don't work with cgroups v2
+
+The systemd version shipped in rhel7-init doesn't have support for cgroups v2. You'll need at least systemd 230.
+
+#### Symptom
+```console
+
+sh# podman run --name test -d registry.access.redhat.com/rhel7-init:latest && sleep 10 && podman exec test systemctl status
+c8567461948439bce72fad3076a91ececfb7b14d469bfa5fbc32c6403185beff
+Failed to get D-Bus connection: Operation not permitted
+Error: non zero exit code: 1: OCI runtime error
+```
+
+#### Solution
+You'll need to either:
+
+* configure the host to use cgroups v1
+* update the image to use an updated version of systemd.
diff --git a/vendor/k8s.io/apimachinery/pkg/util/wait/doc.go b/vendor/k8s.io/apimachinery/pkg/util/wait/doc.go
deleted file mode 100644
index 3f0c968ec..000000000
--- a/vendor/k8s.io/apimachinery/pkg/util/wait/doc.go
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
-Copyright 2014 The Kubernetes 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 wait provides tools for polling or listening for changes
-// to a condition.
-package wait // import "k8s.io/apimachinery/pkg/util/wait"
diff --git a/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go b/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go
deleted file mode 100644
index bc6b18d2b..000000000
--- a/vendor/k8s.io/apimachinery/pkg/util/wait/wait.go
+++ /dev/null
@@ -1,504 +0,0 @@
-/*
-Copyright 2014 The Kubernetes 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 wait
-
-import (
- "context"
- "errors"
- "math/rand"
- "sync"
- "time"
-
- "k8s.io/apimachinery/pkg/util/runtime"
-)
-
-// For any test of the style:
-// ...
-// <- time.After(timeout):
-// t.Errorf("Timed out")
-// The value for timeout should effectively be "forever." Obviously we don't want our tests to truly lock up forever, but 30s
-// is long enough that it is effectively forever for the things that can slow down a run on a heavily contended machine
-// (GC, seeks, etc), but not so long as to make a developer ctrl-c a test run if they do happen to break that test.
-var ForeverTestTimeout = time.Second * 30
-
-// NeverStop may be passed to Until to make it never stop.
-var NeverStop <-chan struct{} = make(chan struct{})
-
-// Group allows to start a group of goroutines and wait for their completion.
-type Group struct {
- wg sync.WaitGroup
-}
-
-func (g *Group) Wait() {
- g.wg.Wait()
-}
-
-// StartWithChannel starts f in a new goroutine in the group.
-// stopCh is passed to f as an argument. f should stop when stopCh is available.
-func (g *Group) StartWithChannel(stopCh <-chan struct{}, f func(stopCh <-chan struct{})) {
- g.Start(func() {
- f(stopCh)
- })
-}
-
-// StartWithContext starts f in a new goroutine in the group.
-// ctx is passed to f as an argument. f should stop when ctx.Done() is available.
-func (g *Group) StartWithContext(ctx context.Context, f func(context.Context)) {
- g.Start(func() {
- f(ctx)
- })
-}
-
-// Start starts f in a new goroutine in the group.
-func (g *Group) Start(f func()) {
- g.wg.Add(1)
- go func() {
- defer g.wg.Done()
- f()
- }()
-}
-
-// Forever calls f every period for ever.
-//
-// Forever is syntactic sugar on top of Until.
-func Forever(f func(), period time.Duration) {
- Until(f, period, NeverStop)
-}
-
-// Until loops until stop channel is closed, running f every period.
-//
-// Until is syntactic sugar on top of JitterUntil with zero jitter factor and
-// with sliding = true (which means the timer for period starts after the f
-// completes).
-func Until(f func(), period time.Duration, stopCh <-chan struct{}) {
- JitterUntil(f, period, 0.0, true, stopCh)
-}
-
-// UntilWithContext loops until context is done, running f every period.
-//
-// UntilWithContext is syntactic sugar on top of JitterUntilWithContext
-// with zero jitter factor and with sliding = true (which means the timer
-// for period starts after the f completes).
-func UntilWithContext(ctx context.Context, f func(context.Context), period time.Duration) {
- JitterUntilWithContext(ctx, f, period, 0.0, true)
-}
-
-// NonSlidingUntil loops until stop channel is closed, running f every
-// period.
-//
-// NonSlidingUntil is syntactic sugar on top of JitterUntil with zero jitter
-// factor, with sliding = false (meaning the timer for period starts at the same
-// time as the function starts).
-func NonSlidingUntil(f func(), period time.Duration, stopCh <-chan struct{}) {
- JitterUntil(f, period, 0.0, false, stopCh)
-}
-
-// NonSlidingUntilWithContext loops until context is done, running f every
-// period.
-//
-// NonSlidingUntilWithContext is syntactic sugar on top of JitterUntilWithContext
-// with zero jitter factor, with sliding = false (meaning the timer for period
-// starts at the same time as the function starts).
-func NonSlidingUntilWithContext(ctx context.Context, f func(context.Context), period time.Duration) {
- JitterUntilWithContext(ctx, f, period, 0.0, false)
-}
-
-// JitterUntil loops until stop channel is closed, running f every period.
-//
-// If jitterFactor is positive, the period is jittered before every run of f.
-// If jitterFactor is not positive, the period is unchanged and not jittered.
-//
-// If sliding is true, the period is computed after f runs. If it is false then
-// period includes the runtime for f.
-//
-// Close stopCh to stop. f may not be invoked if stop channel is already
-// closed. Pass NeverStop to if you don't want it stop.
-func JitterUntil(f func(), period time.Duration, jitterFactor float64, sliding bool, stopCh <-chan struct{}) {
- var t *time.Timer
- var sawTimeout bool
-
- for {
- select {
- case <-stopCh:
- return
- default:
- }
-
- jitteredPeriod := period
- if jitterFactor > 0.0 {
- jitteredPeriod = Jitter(period, jitterFactor)
- }
-
- if !sliding {
- t = resetOrReuseTimer(t, jitteredPeriod, sawTimeout)
- }
-
- func() {
- defer runtime.HandleCrash()
- f()
- }()
-
- if sliding {
- t = resetOrReuseTimer(t, jitteredPeriod, sawTimeout)
- }
-
- // NOTE: b/c there is no priority selection in golang
- // it is possible for this to race, meaning we could
- // trigger t.C and stopCh, and t.C select falls through.
- // In order to mitigate we re-check stopCh at the beginning
- // of every loop to prevent extra executions of f().
- select {
- case <-stopCh:
- return
- case <-t.C:
- sawTimeout = true
- }
- }
-}
-
-// JitterUntilWithContext loops until context is done, running f every period.
-//
-// If jitterFactor is positive, the period is jittered before every run of f.
-// If jitterFactor is not positive, the period is unchanged and not jittered.
-//
-// If sliding is true, the period is computed after f runs. If it is false then
-// period includes the runtime for f.
-//
-// Cancel context to stop. f may not be invoked if context is already expired.
-func JitterUntilWithContext(ctx context.Context, f func(context.Context), period time.Duration, jitterFactor float64, sliding bool) {
- JitterUntil(func() { f(ctx) }, period, jitterFactor, sliding, ctx.Done())
-}
-
-// Jitter returns a time.Duration between duration and duration + maxFactor *
-// duration.
-//
-// This allows clients to avoid converging on periodic behavior. If maxFactor
-// is 0.0, a suggested default value will be chosen.
-func Jitter(duration time.Duration, maxFactor float64) time.Duration {
- if maxFactor <= 0.0 {
- maxFactor = 1.0
- }
- wait := duration + time.Duration(rand.Float64()*maxFactor*float64(duration))
- return wait
-}
-
-// ErrWaitTimeout is returned when the condition exited without success.
-var ErrWaitTimeout = errors.New("timed out waiting for the condition")
-
-// ConditionFunc returns true if the condition is satisfied, or an error
-// if the loop should be aborted.
-type ConditionFunc func() (done bool, err error)
-
-// Backoff holds parameters applied to a Backoff function.
-type Backoff struct {
- // The initial duration.
- Duration time.Duration
- // Duration is multiplied by factor each iteration. Must be greater
- // than or equal to zero.
- Factor float64
- // The amount of jitter applied each iteration. Jitter is applied after
- // cap.
- Jitter float64
- // The number of steps before duration stops changing. If zero, initial
- // duration is always used. Used for exponential backoff in combination
- // with Factor.
- Steps int
- // The returned duration will never be greater than cap *before* jitter
- // is applied. The actual maximum cap is `cap * (1.0 + jitter)`.
- Cap time.Duration
-}
-
-// Step returns the next interval in the exponential backoff. This method
-// will mutate the provided backoff.
-func (b *Backoff) Step() time.Duration {
- if b.Steps < 1 {
- if b.Jitter > 0 {
- return Jitter(b.Duration, b.Jitter)
- }
- return b.Duration
- }
- b.Steps--
-
- duration := b.Duration
-
- // calculate the next step
- if b.Factor != 0 {
- b.Duration = time.Duration(float64(b.Duration) * b.Factor)
- if b.Cap > 0 && b.Duration > b.Cap {
- b.Duration = b.Cap
- b.Steps = 0
- }
- }
-
- if b.Jitter > 0 {
- duration = Jitter(duration, b.Jitter)
- }
- return duration
-}
-
-// contextForChannel derives a child context from a parent channel.
-//
-// The derived context's Done channel is closed when the returned cancel function
-// is called or when the parent channel is closed, whichever happens first.
-//
-// Note the caller must *always* call the CancelFunc, otherwise resources may be leaked.
-func contextForChannel(parentCh <-chan struct{}) (context.Context, context.CancelFunc) {
- ctx, cancel := context.WithCancel(context.Background())
-
- go func() {
- select {
- case <-parentCh:
- cancel()
- case <-ctx.Done():
- }
- }()
- return ctx, cancel
-}
-
-// ExponentialBackoff repeats a condition check with exponential backoff.
-//
-// It checks the condition up to Steps times, increasing the wait by multiplying
-// the previous duration by Factor.
-//
-// If Jitter is greater than zero, a random amount of each duration is added
-// (between duration and duration*(1+jitter)).
-//
-// If the condition never returns true, ErrWaitTimeout is returned. All other
-// errors terminate immediately.
-func ExponentialBackoff(backoff Backoff, condition ConditionFunc) error {
- for backoff.Steps > 0 {
- if ok, err := condition(); err != nil || ok {
- return err
- }
- if backoff.Steps == 1 {
- break
- }
- time.Sleep(backoff.Step())
- }
- return ErrWaitTimeout
-}
-
-// Poll tries a condition func until it returns true, an error, or the timeout
-// is reached.
-//
-// Poll always waits the interval before the run of 'condition'.
-// 'condition' will always be invoked at least once.
-//
-// Some intervals may be missed if the condition takes too long or the time
-// window is too short.
-//
-// If you want to Poll something forever, see PollInfinite.
-func Poll(interval, timeout time.Duration, condition ConditionFunc) error {
- return pollInternal(poller(interval, timeout), condition)
-}
-
-func pollInternal(wait WaitFunc, condition ConditionFunc) error {
- done := make(chan struct{})
- defer close(done)
- return WaitFor(wait, condition, done)
-}
-
-// PollImmediate tries a condition func until it returns true, an error, or the timeout
-// is reached.
-//
-// PollImmediate always checks 'condition' before waiting for the interval. 'condition'
-// will always be invoked at least once.
-//
-// Some intervals may be missed if the condition takes too long or the time
-// window is too short.
-//
-// If you want to immediately Poll something forever, see PollImmediateInfinite.
-func PollImmediate(interval, timeout time.Duration, condition ConditionFunc) error {
- return pollImmediateInternal(poller(interval, timeout), condition)
-}
-
-func pollImmediateInternal(wait WaitFunc, condition ConditionFunc) error {
- done, err := condition()
- if err != nil {
- return err
- }
- if done {
- return nil
- }
- return pollInternal(wait, condition)
-}
-
-// PollInfinite tries a condition func until it returns true or an error
-//
-// PollInfinite always waits the interval before the run of 'condition'.
-//
-// Some intervals may be missed if the condition takes too long or the time
-// window is too short.
-func PollInfinite(interval time.Duration, condition ConditionFunc) error {
- done := make(chan struct{})
- defer close(done)
- return PollUntil(interval, condition, done)
-}
-
-// PollImmediateInfinite tries a condition func until it returns true or an error
-//
-// PollImmediateInfinite runs the 'condition' before waiting for the interval.
-//
-// Some intervals may be missed if the condition takes too long or the time
-// window is too short.
-func PollImmediateInfinite(interval time.Duration, condition ConditionFunc) error {
- done, err := condition()
- if err != nil {
- return err
- }
- if done {
- return nil
- }
- return PollInfinite(interval, condition)
-}
-
-// PollUntil tries a condition func until it returns true, an error or stopCh is
-// closed.
-//
-// PollUntil always waits interval before the first run of 'condition'.
-// 'condition' will always be invoked at least once.
-func PollUntil(interval time.Duration, condition ConditionFunc, stopCh <-chan struct{}) error {
- ctx, cancel := contextForChannel(stopCh)
- defer cancel()
- return WaitFor(poller(interval, 0), condition, ctx.Done())
-}
-
-// PollImmediateUntil tries a condition func until it returns true, an error or stopCh is closed.
-//
-// PollImmediateUntil runs the 'condition' before waiting for the interval.
-// 'condition' will always be invoked at least once.
-func PollImmediateUntil(interval time.Duration, condition ConditionFunc, stopCh <-chan struct{}) error {
- done, err := condition()
- if err != nil {
- return err
- }
- if done {
- return nil
- }
- select {
- case <-stopCh:
- return ErrWaitTimeout
- default:
- return PollUntil(interval, condition, stopCh)
- }
-}
-
-// WaitFunc creates a channel that receives an item every time a test
-// should be executed and is closed when the last test should be invoked.
-type WaitFunc func(done <-chan struct{}) <-chan struct{}
-
-// WaitFor continually checks 'fn' as driven by 'wait'.
-//
-// WaitFor gets a channel from 'wait()'', and then invokes 'fn' once for every value
-// placed on the channel and once more when the channel is closed. If the channel is closed
-// and 'fn' returns false without error, WaitFor returns ErrWaitTimeout.
-//
-// If 'fn' returns an error the loop ends and that error is returned. If
-// 'fn' returns true the loop ends and nil is returned.
-//
-// ErrWaitTimeout will be returned if the 'done' channel is closed without fn ever
-// returning true.
-//
-// When the done channel is closed, because the golang `select` statement is
-// "uniform pseudo-random", the `fn` might still run one or multiple time,
-// though eventually `WaitFor` will return.
-func WaitFor(wait WaitFunc, fn ConditionFunc, done <-chan struct{}) error {
- stopCh := make(chan struct{})
- defer close(stopCh)
- c := wait(stopCh)
- for {
- select {
- case _, open := <-c:
- ok, err := fn()
- if err != nil {
- return err
- }
- if ok {
- return nil
- }
- if !open {
- return ErrWaitTimeout
- }
- case <-done:
- return ErrWaitTimeout
- }
- }
-}
-
-// poller returns a WaitFunc that will send to the channel every interval until
-// timeout has elapsed and then closes the channel.
-//
-// Over very short intervals you may receive no ticks before the channel is
-// closed. A timeout of 0 is interpreted as an infinity, and in such a case
-// it would be the caller's responsibility to close the done channel.
-// Failure to do so would result in a leaked goroutine.
-//
-// Output ticks are not buffered. If the channel is not ready to receive an
-// item, the tick is skipped.
-func poller(interval, timeout time.Duration) WaitFunc {
- return WaitFunc(func(done <-chan struct{}) <-chan struct{} {
- ch := make(chan struct{})
-
- go func() {
- defer close(ch)
-
- tick := time.NewTicker(interval)
- defer tick.Stop()
-
- var after <-chan time.Time
- if timeout != 0 {
- // time.After is more convenient, but it
- // potentially leaves timers around much longer
- // than necessary if we exit early.
- timer := time.NewTimer(timeout)
- after = timer.C
- defer timer.Stop()
- }
-
- for {
- select {
- case <-tick.C:
- // If the consumer isn't ready for this signal drop it and
- // check the other channels.
- select {
- case ch <- struct{}{}:
- default:
- }
- case <-after:
- return
- case <-done:
- return
- }
- }
- }()
-
- return ch
- })
-}
-
-// resetOrReuseTimer avoids allocating a new timer if one is already in use.
-// Not safe for multiple threads.
-func resetOrReuseTimer(t *time.Timer, d time.Duration, sawTimeout bool) *time.Timer {
- if t == nil {
- return time.NewTimer(d)
- }
- if !t.Stop() && !sawTimeout {
- <-t.C
- }
- t.Reset(d)
- return t
-}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index f566c74fa..f3564ebc6 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -543,7 +543,6 @@ gopkg.in/yaml.v2
k8s.io/api/core/v1
# k8s.io/apimachinery v0.0.0-20190624085041-961b39a1baa0
k8s.io/apimachinery/pkg/apis/meta/v1
-k8s.io/apimachinery/pkg/util/wait
k8s.io/apimachinery/pkg/util/runtime
k8s.io/apimachinery/pkg/api/resource
k8s.io/apimachinery/pkg/runtime