diff options
-rw-r--r-- | .cirrus.yml | 6 | ||||
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | Makefile | 65 | ||||
-rw-r--r-- | cmd/podman/build.go | 4 | ||||
-rw-r--r-- | cmd/podman/cliconfig/config.go | 2 | ||||
-rw-r--r-- | cmd/podman/cp.go | 11 | ||||
-rw-r--r-- | cmd/podman/logs.go | 2 | ||||
-rw-r--r-- | cmd/podman/main_local.go | 11 | ||||
-rw-r--r-- | cmd/podman/utils.go | 3 | ||||
-rw-r--r-- | contrib/cirrus/lib.sh | 46 | ||||
-rwxr-xr-x | contrib/cirrus/lib.sh.t | 17 | ||||
-rw-r--r-- | docs/Makefile | 23 | ||||
-rw-r--r-- | docs/Readme.md | 21 | ||||
-rw-r--r-- | docs/make.bat (renamed from docs/rtd/make.bat) | 0 | ||||
-rwxr-xr-x | docs/remote-docs.sh (renamed from docs/podman-remote.sh) | 55 | ||||
-rw-r--r-- | docs/requirements.txt (renamed from docs/rtd/requirements.txt) | 0 | ||||
-rw-r--r-- | docs/rtd/Makefile | 123 | ||||
-rw-r--r-- | docs/rtd/source/Commands.rst | 107 | ||||
-rw-r--r-- | docs/rtd/source/man/generate.rst | 6 | ||||
-rw-r--r-- | docs/rtd/source/man/healthcheck.rst | 4 | ||||
-rw-r--r-- | docs/rtd/source/man/image.rst | 35 | ||||
-rw-r--r-- | docs/rtd/source/man/managecontainers.rst | 64 | ||||
-rw-r--r-- | docs/rtd/source/man/network.rst | 10 | ||||
-rw-r--r-- | docs/rtd/source/man/play.rst | 4 | ||||
-rw-r--r-- | docs/rtd/source/man/pod.rst | 30 | ||||
-rw-r--r-- | docs/rtd/source/man/system.rst | 12 | ||||
-rw-r--r-- | docs/rtd/source/man/volume.rst | 11 | ||||
-rw-r--r-- | docs/source/Commands.rst | 107 | ||||
-rw-r--r-- | docs/source/Introduction.rst (renamed from docs/rtd/source/Introduction.rst) | 0 | ||||
-rw-r--r-- | docs/source/Reference.rst (renamed from docs/rtd/source/Reference.rst) | 0 | ||||
-rw-r--r-- | docs/source/Tutorials.rst (renamed from docs/rtd/source/Tutorials.rst) | 0 | ||||
-rw-r--r-- | docs/source/conf.py (renamed from docs/rtd/source/conf.py) | 0 | ||||
-rw-r--r-- | docs/source/generate.rst | 6 | ||||
-rw-r--r-- | docs/source/healthcheck.rst | 4 | ||||
-rw-r--r-- | docs/source/image.rst | 35 | ||||
-rw-r--r-- | docs/source/index.rst (renamed from docs/rtd/source/index.rst) | 0 | ||||
-rw-r--r-- | docs/source/managecontainers.rst | 64 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-container-attach.1 (renamed from docs/links/podman-container-attach.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-container-commit.1 (renamed from docs/links/podman-container-commit.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-container-cp.1 (renamed from docs/links/podman-container-cp.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-container-create.1 (renamed from docs/links/podman-container-create.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-container-diff.1 (renamed from docs/links/podman-container-diff.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-container-exec.1 (renamed from docs/links/podman-container-exec.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-container-export.1 (renamed from docs/links/podman-container-export.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-container-init.1 (renamed from docs/links/podman-container-init.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-container-inspect.1 (renamed from docs/links/podman-container-inspect.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-container-kill.1 (renamed from docs/links/podman-container-kill.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-container-list.1 (renamed from docs/links/podman-container-list.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-container-logs.1 (renamed from docs/links/podman-container-logs.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-container-ls.1 (renamed from docs/links/podman-container-ls.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-container-mount.1 (renamed from docs/links/podman-container-mount.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-container-pause.1 (renamed from docs/links/podman-container-pause.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-container-port.1 (renamed from docs/links/podman-container-port.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-container-ps.1 (renamed from docs/links/podman-container-ps.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-container-restart.1 (renamed from docs/links/podman-container-restart.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-container-rm.1 (renamed from docs/links/podman-container-rm.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-container-run.1 (renamed from docs/links/podman-container-run.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-container-start.1 (renamed from docs/links/podman-container-start.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-container-stats.1 (renamed from docs/links/podman-container-stats.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-container-stop.1 (renamed from docs/links/podman-container-stop.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-container-top.1 (renamed from docs/links/podman-container-top.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-container-umount.1 (renamed from docs/links/podman-container-umount.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-container-unmount.1 (renamed from docs/links/podman-container-unmount.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-container-unpause.1 (renamed from docs/links/podman-container-unpause.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-container-wait.1 (renamed from docs/links/podman-container-wait.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-help.1 (renamed from docs/links/podman-help.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-image-build.1 (renamed from docs/links/podman-image-build.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-image-history.1 (renamed from docs/links/podman-image-history.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-image-import.1 (renamed from docs/links/podman-image-import.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-image-inspect.1 (renamed from docs/links/podman-image-inspect.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-image-list.1 (renamed from docs/links/podman-image-list.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-image-load.1 (renamed from docs/links/podman-image-load.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-image-ls.1 (renamed from docs/links/podman-image-ls.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-image-pull.1 (renamed from docs/links/podman-image-pull.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-image-push.1 (renamed from docs/links/podman-image-push.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-image-rm.1 (renamed from docs/links/podman-image-rm.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-image-save.1 (renamed from docs/links/podman-image-save.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-image-tag.1 (renamed from docs/links/podman-image-tag.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-list.1 (renamed from docs/links/podman-list.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-ls.1 (renamed from docs/links/podman-ls.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-system-info.1 (renamed from docs/links/podman-system-info.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/links/podman-unmount.1 (renamed from docs/links/podman-unmount.1) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-attach.1.md (renamed from docs/podman-attach.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-build.1.md (renamed from docs/podman-build.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-commit.1.md (renamed from docs/podman-commit.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-container-checkpoint.1.md (renamed from docs/podman-container-checkpoint.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-container-cleanup.1.md (renamed from docs/podman-container-cleanup.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-container-exists.1.md (renamed from docs/podman-container-exists.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-container-prune.1.md (renamed from docs/podman-container-prune.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-container-restore.1.md (renamed from docs/podman-container-restore.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-container-runlabel.1.md (renamed from docs/podman-container-runlabel.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-container.1.md (renamed from docs/podman-container.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-cp.1.md (renamed from docs/podman-cp.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-create.1.md (renamed from docs/podman-create.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-diff.1.md (renamed from docs/podman-diff.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-events.1.md (renamed from docs/podman-events.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-exec.1.md (renamed from docs/podman-exec.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-export.1.md (renamed from docs/podman-export.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-generate-kube.1.md (renamed from docs/podman-generate-kube.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-generate-systemd.1.md (renamed from docs/podman-generate-systemd.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-generate.1.md (renamed from docs/podman-generate.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-healthcheck-run.1.md (renamed from docs/podman-healthcheck-run.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-healthcheck.1.md (renamed from docs/podman-healthcheck.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-history.1.md (renamed from docs/podman-history.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-image-exists.1.md (renamed from docs/podman-image-exists.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-image-prune.1.md (renamed from docs/podman-image-prune.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-image-sign.1.md (renamed from docs/podman-image-sign.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-image-tree.1.md (renamed from docs/podman-image-tree.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-image-trust.1.md (renamed from docs/podman-image-trust.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-image.1.md (renamed from docs/podman-image.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-images.1.md (renamed from docs/podman-images.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-import.1.md (renamed from docs/podman-import.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-info.1.md (renamed from docs/podman-info.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-init.1.md (renamed from docs/podman-init.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-inspect.1.md (renamed from docs/podman-inspect.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-kill.1.md (renamed from docs/podman-kill.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-load.1.md (renamed from docs/podman-load.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-login.1.md (renamed from docs/podman-login.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-logout.1.md (renamed from docs/podman-logout.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-logs.1.md (renamed from docs/podman-logs.1.md) | 2 | ||||
-rw-r--r-- | docs/source/markdown/podman-mount.1.md (renamed from docs/podman-mount.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-network-create.1.md (renamed from docs/podman-network-create.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-network-inspect.1.md (renamed from docs/podman-network-inspect.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-network-ls.1.md (renamed from docs/podman-network-ls.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-network-rm.1.md (renamed from docs/podman-network-rm.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-network.1.md (renamed from docs/podman-network.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-pause.1.md (renamed from docs/podman-pause.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-play-kube.1.md (renamed from docs/podman-play-kube.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-play.1.md (renamed from docs/podman-play.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-pod-create.1.md (renamed from docs/podman-pod-create.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-pod-exists.1.md (renamed from docs/podman-pod-exists.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-pod-inspect.1.md (renamed from docs/podman-pod-inspect.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-pod-kill.1.md (renamed from docs/podman-pod-kill.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-pod-pause.1.md (renamed from docs/podman-pod-pause.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-pod-prune.1.md (renamed from docs/podman-pod-prune.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-pod-ps.1.md (renamed from docs/podman-pod-ps.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-pod-restart.1.md (renamed from docs/podman-pod-restart.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-pod-rm.1.md (renamed from docs/podman-pod-rm.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-pod-start.1.md (renamed from docs/podman-pod-start.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-pod-stats.1.md (renamed from docs/podman-pod-stats.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-pod-stop.1.md (renamed from docs/podman-pod-stop.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-pod-top.1.md (renamed from docs/podman-pod-top.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-pod-unpause.1.md (renamed from docs/podman-pod-unpause.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-pod.1.md (renamed from docs/podman-pod.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-port.1.md (renamed from docs/podman-port.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-ps.1.md (renamed from docs/podman-ps.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-pull.1.md (renamed from docs/podman-pull.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-push.1.md (renamed from docs/podman-push.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-remote.1.md (renamed from docs/podman-remote.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-restart.1.md (renamed from docs/podman-restart.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-rm.1.md (renamed from docs/podman-rm.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-rmi.1.md (renamed from docs/podman-rmi.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-run.1.md (renamed from docs/podman-run.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-save.1.md (renamed from docs/podman-save.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-search.1.md (renamed from docs/podman-search.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-start.1.md (renamed from docs/podman-start.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-stats.1.md (renamed from docs/podman-stats.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-stop.1.md (renamed from docs/podman-stop.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-system-df.1.md (renamed from docs/podman-system-df.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-system-migrate.1.md (renamed from docs/podman-system-migrate.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-system-prune.1.md (renamed from docs/podman-system-prune.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-system-renumber.1.md (renamed from docs/podman-system-renumber.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-system.1.md (renamed from docs/podman-system.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-tag.1.md (renamed from docs/podman-tag.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-top.1.md (renamed from docs/podman-top.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-umount.1.md (renamed from docs/podman-umount.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-unpause.1.md (renamed from docs/podman-unpause.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-unshare.1.md (renamed from docs/podman-unshare.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-varlink.1.md (renamed from docs/podman-varlink.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-version.1.md (renamed from docs/podman-version.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-volume-create.1.md (renamed from docs/podman-volume-create.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-volume-inspect.1.md (renamed from docs/podman-volume-inspect.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-volume-ls.1.md (renamed from docs/podman-volume-ls.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-volume-prune.1.md (renamed from docs/podman-volume-prune.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-volume-rm.1.md (renamed from docs/podman-volume-rm.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-volume.1.md (renamed from docs/podman-volume.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman-wait.1.md (renamed from docs/podman-wait.1.md) | 0 | ||||
-rw-r--r-- | docs/source/markdown/podman.1.md (renamed from docs/podman.1.md) | 0 | ||||
-rw-r--r-- | docs/source/network.rst | 10 | ||||
-rw-r--r-- | docs/source/play.rst | 4 | ||||
-rw-r--r-- | docs/source/pod.rst | 30 | ||||
-rw-r--r-- | docs/source/system.rst | 12 | ||||
-rw-r--r-- | docs/source/volume.rst | 11 | ||||
-rw-r--r-- | go.mod | 2 | ||||
-rw-r--r-- | go.sum | 17 | ||||
-rwxr-xr-x | hack/man-page-checker | 2 | ||||
-rwxr-xr-x | hack/podman-commands.sh | 6 | ||||
-rw-r--r-- | libpod/boltdb_state.go | 5 | ||||
-rw-r--r-- | libpod/common_test.go | 3 | ||||
-rw-r--r-- | libpod/config/config.go | 549 | ||||
-rw-r--r-- | libpod/config/config_test.go | 64 | ||||
-rw-r--r-- | libpod/config/default.go | 137 | ||||
-rw-r--r-- | libpod/config/merge.go | 183 | ||||
-rw-r--r-- | libpod/config/merge_test.go | 157 | ||||
-rw-r--r-- | libpod/config/testdata/empty.conf | 0 | ||||
l--------- | libpod/config/testdata/libpod.conf | 1 | ||||
-rw-r--r-- | libpod/container.go | 4 | ||||
-rw-r--r-- | libpod/container_inspect.go | 4 | ||||
-rw-r--r-- | libpod/container_internal_linux.go | 4 | ||||
-rw-r--r-- | libpod/container_log_linux.go | 9 | ||||
-rw-r--r-- | libpod/define/config.go | 18 | ||||
-rw-r--r-- | libpod/define/runtime.go | 37 | ||||
-rw-r--r-- | libpod/in_memory_state.go | 5 | ||||
-rw-r--r-- | libpod/logs/log.go | 6 | ||||
-rw-r--r-- | libpod/oci_attach_linux.go | 2 | ||||
-rw-r--r-- | libpod/oci_conmon_linux.go | 21 | ||||
-rw-r--r-- | libpod/oci_conmon_unsupported.go | 3 | ||||
-rw-r--r-- | libpod/oci_util.go | 26 | ||||
-rw-r--r-- | libpod/options.go | 24 | ||||
-rw-r--r-- | libpod/pod_internal.go | 4 | ||||
-rw-r--r-- | libpod/runtime.go | 828 | ||||
-rw-r--r-- | libpod/runtime_ctr.go | 6 | ||||
-rw-r--r-- | libpod/runtime_pod_linux.go | 10 | ||||
-rw-r--r-- | libpod/state.go | 13 | ||||
-rw-r--r-- | libpod/state_test.go | 3 | ||||
-rw-r--r-- | libpod/util.go | 17 | ||||
-rw-r--r-- | libpod/volume_internal_linux.go | 16 | ||||
-rw-r--r-- | pkg/adapter/containers.go | 35 | ||||
-rw-r--r-- | pkg/spec/spec.go | 8 | ||||
-rw-r--r-- | pkg/util/utils.go | 14 | ||||
-rw-r--r-- | pkg/varlinkapi/containers.go | 8 | ||||
-rw-r--r-- | test/e2e/logs_test.go | 12 | ||||
-rw-r--r-- | test/e2e/run_selinux_test.go | 2 | ||||
-rw-r--r-- | test/e2e/run_volume_test.go | 11 | ||||
-rw-r--r-- | test/e2e/start_test.go | 21 | ||||
-rw-r--r-- | vendor/github.com/onsi/ginkgo/.travis.yml | 3 | ||||
-rw-r--r-- | vendor/github.com/onsi/ginkgo/CHANGELOG.md | 22 | ||||
-rw-r--r-- | vendor/github.com/onsi/ginkgo/config/config.go | 9 | ||||
-rw-r--r-- | vendor/github.com/onsi/ginkgo/extensions/table/table_entry.go | 13 | ||||
-rw-r--r-- | vendor/github.com/onsi/ginkgo/ginkgo/run_command.go | 17 | ||||
-rw-r--r-- | vendor/github.com/onsi/ginkgo/ginkgo_dsl.go | 5 | ||||
-rw-r--r-- | vendor/github.com/onsi/ginkgo/reporters/junit_reporter.go | 21 | ||||
-rw-r--r-- | vendor/modules.txt | 2 |
233 files changed, 1863 insertions, 1485 deletions
diff --git a/.cirrus.yml b/.cirrus.yml index 0713f6dda..fe7a1c332 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -32,7 +32,7 @@ env: ### _BUILT_IMAGE_SUFFIX: "libpod-5642998972416000" FEDORA_CACHE_IMAGE_NAME: "fedora-30-${_BUILT_IMAGE_SUFFIX}" - PRIOR_FEDORA_CACHE_IMAGE_NAME: "fedora-29-${_BUILT_IMAGE_SUFFIX}" + PRIOR_FEDORA_CACHE_IMAGE_NAME: "fedora-30-${_BUILT_IMAGE_SUFFIX}" SPECIAL_FEDORA_CACHE_IMAGE_NAME: "xfedora-30-${_BUILT_IMAGE_SUFFIX}" UBUNTU_CACHE_IMAGE_NAME: "ubuntu-19-${_BUILT_IMAGE_SUFFIX}" PRIOR_UBUNTU_CACHE_IMAGE_NAME: "ubuntu-18-${_BUILT_IMAGE_SUFFIX}" @@ -331,7 +331,7 @@ testing_task: gce_instance: matrix: # Images are generated separately, from build_images_task (below) - image_name: "${FEDORA_CACHE_IMAGE_NAME}" + #image_name: "${FEDORA_CACHE_IMAGE_NAME}" image_name: "${PRIOR_FEDORA_CACHE_IMAGE_NAME}" # Multiple test failures on Ubuntu 19 - Fixes TBD in future PR # TODO: image_name: "${UBUNTU_CACHE_IMAGE_NAME}" @@ -589,8 +589,8 @@ verify_test_built_images_task: TEST_REMOTE_CLIENT: false matrix: # Required env. var. by check_image_script - PACKER_BUILDER_NAME: "fedora-29" PACKER_BUILDER_NAME: "fedora-30" + #PACKER_BUILDER_NAME: "fedora-31" PACKER_BUILDER_NAME: "xfedora-30" PACKER_BUILDER_NAME: "ubuntu-18" # TODO support $UBUNTU_CACHE_IMAGE_NAME: PACKER_BUILDER_NAME: "ubuntu-19" diff --git a/.gitignore b/.gitignore index 598384582..54b63518f 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ /docs/*.[158] /docs/*.[158].gz /docs/remote +/docs/build/ *.o *.orig /pause/pause.o @@ -25,3 +26,4 @@ release.txt podman-remote*.zip podman*.tar.gz .idea* +.vscode* @@ -3,7 +3,7 @@ export GOPROXY=https://proxy.golang.org GO ?= go DESTDIR ?= -EPOCH_TEST_COMMIT ?= 2b0892e757c878cdb087dd22b8986bccef0276ed +EPOCH_TEST_COMMIT ?= ac73fd3fe5dcbf2647d589f9c9f37fe9531ed663 HEAD ?= HEAD CHANGELOG_BASE ?= HEAD~ CHANGELOG_TARGET ?= HEAD @@ -73,8 +73,8 @@ ASMFLAGS ?= all=-trimpath=${PWD} LDFLAGS_PODMAN ?= $(LDFLAGS) \ -X $(LIBPOD)/define.gitCommit=$(GIT_COMMIT) \ -X $(LIBPOD)/define.buildInfo=$(BUILD_INFO) \ - -X $(LIBPOD).installPrefix=$(PREFIX) \ - -X $(LIBPOD).etcDir=$(ETCDIR) + -X $(LIBPOD)/config._installPrefix=$(PREFIX) \ + -X $(LIBPOD)/config._etcDir=$(ETCDIR) #Update to LIBSECCOMP_COMMIT should reflect in Dockerfile too. LIBSECCOMP_COMMIT := release-2.3 # Rarely if ever should integration tests take more than 50min, @@ -167,13 +167,11 @@ podman-remote: .gopathok $(PODMAN_VARLINK_DEPENDENCIES) ## Build with podman on $(GO_BUILD) $(BUILDFLAGS) -gcflags '$(GCFLAGS)' -asmflags '$(ASMFLAGS)' -ldflags '$(LDFLAGS_PODMAN)' -tags "$(BUILDTAGS) remoteclient" -o bin/$@ $(PROJECT)/cmd/podman .PHONY: podman.msi -podman.msi: podman-remote podman-remote-windows docs ## Will always rebuild exe as there is no podman-remote-windows.exe target to verify timestamp - rm -rf bin/windows - mkdir -p bin/windows - docs/podman-remote.sh windows bin/windows docs - find bin/windows -print \ - |wixl-heat --var var.ManSourceDir --component-group ManFiles --directory-ref INSTALLDIR --prefix bin/windows/ >bin/windows/pages.wsx - wixl -D VERSION=$(RELEASE_NUMBER) -D ManSourceDir=bin/windows -o podman-v$(RELEASE_NUMBER).msi contrib/msi/podman.wxs bin/windows/pages.wsx +podman.msi: podman-remote podman-remote-windows install-podman-remote-windows-docs ## Will always rebuild exe as there is no podman-remote-windows.exe target to verify timestamp + $(eval DOCFILE := docs/build/remote/windows) + find $(DOCFILE) -print \ + |wixl-heat --var var.ManSourceDir --component-group ManFiles --directory-ref INSTALLDIR --prefix $(DOCFILE)/ >$(DOCFILE)/pages.wsx + wixl -D VERSION=$(RELEASE_NUMBER) -D ManSourceDir=$(DOCFILE) -o podman-v$(RELEASE_NUMBER).msi contrib/msi/podman.wxs $(DOCFILE)/pages.wsx podman-remote-%: .gopathok $(PODMAN_VARLINK_DEPENDENCIES) ## Build podman for a specific GOOS $(eval BINSFX := $(shell test "$*" != "windows" || echo ".exe")) @@ -196,7 +194,6 @@ clean: ## Clean artifacts $(wildcard podman*.tar.gz) \ bin \ build \ - docs/remote \ test/checkseccomp/checkseccomp \ test/goecho/goecho \ test/testdata/redis-image \ @@ -205,9 +202,7 @@ clean: ## Clean artifacts libpod/pod_ffjson.go \ libpod/container_easyjson.go \ libpod/pod_easyjson.go \ - $(MANPAGES) ||: - find . -name \*~ -delete - find . -name \#\* -delete + docs/build libpodimage: ## Build the libpod image ${CONTAINER_RUNTIME} build -t ${LIBPOD_IMAGE} . @@ -312,20 +307,26 @@ install.catatonit: test-binaries: test/checkseccomp/checkseccomp test/goecho/goecho install.catatonit -MANPAGES_MD ?= $(wildcard docs/*.md pkg/*/docs/*.md) +MANPAGES_MD ?= $(wildcard docs/source/markdown/*.md pkg/*/docs/*.md) MANPAGES ?= $(MANPAGES_MD:%.md=%) +MANPAGES_DEST ?= $(subst markdown,man, $(subst source,build,$(MANPAGES))) $(MANPAGES): %: %.md .gopathok - @sed -e 's/\((podman.*\.md)\)//' -e 's/\[\(podman.*\)\]/\1/' $< | $(GOMD2MAN) -in /dev/stdin -out $@ + @sed -e 's/\((podman.*\.md)\)//' -e 's/\[\(podman.*\)\]/\1/' $< | $(GOMD2MAN) -in /dev/stdin -out $(subst source/markdown,build/man,$@) -docs: $(MANPAGES) ## Generate documentation +docdir: + mkdir -p docs/build/man -install-podman-remote-docs: podman-remote docs - rm -rf docs/remote - docs/podman-remote.sh darwin docs/remote docs +docs: docdir $(MANPAGES) ## Generate documentation + +install-podman-remote-%-docs: podman-remote docs $(MANPAGES) + rm -rf docs/build/remote + mkdir -p docs/build/remote + ln -sf $(shell pwd)/docs/source/markdown/links docs/build/man/ + docs/remote-docs.sh $* docs/build/remote/$* $(if $(findstring windows,$*),docs/source/markdown,docs/build/man) man-page-check: - ./hack/man-page-checker + hack/man-page-checker # When publishing releases include critical build-time details .PHONY: release.txt @@ -349,7 +350,7 @@ podman-v$(RELEASE_NUMBER).tar.gz: binaries docs release.txt # Must call make in-line: Dependency-spec. w/ wild-card also consumes variable value. podman-remote-v$(RELEASE_NUMBER)-%.zip: - $(MAKE) podman-remote-$* install-podman-remote-docs release.txt \ + $(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)) @@ -359,13 +360,7 @@ podman-remote-v$(RELEASE_NUMBER)-%.zip: # 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)" + cp -r ./docs/build/remote/$* "$(TMPDIR)/$(SUBDIR)/docs/" cd "$(TMPDIR)" && \ zip --recurse-paths "$(CURDIR)/$@" "./release.txt" "./" -rm -rf "$(TMPDIR)" @@ -408,9 +403,9 @@ install.bin: podman install.man: docs install ${SELINUXOPT} -d -m 755 $(DESTDIR)$(MANDIR)/man1 install ${SELINUXOPT} -d -m 755 $(DESTDIR)$(MANDIR)/man5 - install ${SELINUXOPT} -m 644 $(filter %.1,$(MANPAGES)) -t $(DESTDIR)$(MANDIR)/man1 - install ${SELINUXOPT} -m 644 $(filter %.5,$(MANPAGES)) -t $(DESTDIR)$(MANDIR)/man5 - install ${SELINUXOPT} -m 644 docs/links/*1 -t $(DESTDIR)$(MANDIR)/man1 + install ${SELINUXOPT} -m 644 $(filter %.1,$(MANPAGES_DEST)) -t $(DESTDIR)$(MANDIR)/man1 + install ${SELINUXOPT} -m 644 $(filter %.5,$(MANPAGES_DEST)) -t $(DESTDIR)$(MANDIR)/man5 + install ${SELINUXOPT} -m 644 docs/source/markdown/links/*1 -t $(DESTDIR)$(MANDIR)/man1 install.config: install ${SELINUXOPT} -d -m 755 $(DESTDIR)$(SHAREDIR_CONTAINERS) @@ -444,16 +439,16 @@ install.systemd: install ${SELINUXOPT} -m 644 contrib/varlink/podman.conf ${DESTDIR}${TMPFILESDIR}/podman.conf uninstall: - for i in $(filter %.1,$(MANPAGES)); do \ + for i in $(filter %.1,$(MANPAGES_DEST)); do \ rm -f $(DESTDIR)$(MANDIR)/man1/$$(basename $${i}); \ done; \ - for i in $(filter %.5,$(MANPAGES)); do \ + for i in $(filter %.5,$(MANPAGES_DEST)); do \ rm -f $(DESTDIR)$(MANDIR)/man5/$$(basename $${i}); \ done .PHONY: .gitvalidation .gitvalidation: .gopathok - GIT_CHECK_EXCLUDE="./vendor:docs/rtd/make.bat" $(GOBIN)/git-validation -v -run DCO,short-subject,dangling-whitespace -range $(EPOCH_TEST_COMMIT)..$(HEAD) + GIT_CHECK_EXCLUDE="./vendor:docs/make.bat" $(GOBIN)/git-validation -v -run DCO,short-subject,dangling-whitespace -range $(EPOCH_TEST_COMMIT)..$(HEAD) .PHONY: install.tools install.tools: .install.gitvalidation .install.gometalinter .install.md2man .install.ginkgo .install.golangci-lint ## Install needed tools diff --git a/cmd/podman/build.go b/cmd/podman/build.go index e9ebc50aa..896d5661a 100644 --- a/cmd/podman/build.go +++ b/cmd/podman/build.go @@ -11,7 +11,7 @@ import ( buildahcli "github.com/containers/buildah/pkg/cli" "github.com/containers/image/v5/types" "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/libpod" + "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/adapter" "github.com/docker/go-units" "github.com/opencontainers/runtime-spec/specs-go" @@ -260,7 +260,7 @@ func buildCmd(c *cliconfig.BuildValues) error { if err != nil { return err } - if conf != nil && conf.CgroupManager == libpod.SystemdCgroupsManager { + if conf != nil && conf.CgroupManager == define.SystemdCgroupsManager { runtimeFlags = append(runtimeFlags, "--systemd-cgroup") } // end from buildah diff --git a/cmd/podman/cliconfig/config.go b/cmd/podman/cliconfig/config.go index 1bb5fa30c..58d67ddc1 100644 --- a/cmd/podman/cliconfig/config.go +++ b/cmd/podman/cliconfig/config.go @@ -251,7 +251,7 @@ type LogsValues struct { Details bool Follow bool Since string - Tail uint64 + Tail int64 Timestamps bool Latest bool } diff --git a/cmd/podman/cp.go b/cmd/podman/cp.go index 75a23afd6..c53a97df3 100644 --- a/cmd/podman/cp.go +++ b/cmd/podman/cp.go @@ -257,8 +257,15 @@ func parsePath(runtime *libpod.Runtime, path string) (*libpod.Container, string) return nil, path } +func evalSymlinks(path string) (string, error) { + if path == os.Stdin.Name() { + return path, nil + } + return filepath.EvalSymlinks(path) +} + func getPathInfo(path string) (string, os.FileInfo, error) { - path, err := filepath.EvalSymlinks(path) + path, err := evalSymlinks(path) if err != nil { return "", nil, errors.Wrapf(err, "error evaluating symlinks %q", path) } @@ -270,7 +277,7 @@ func getPathInfo(path string) (string, os.FileInfo, error) { } func copy(src, destPath, dest string, idMappingOpts storage.IDMappingOptions, chownOpts *idtools.IDPair, extract, isFromHostToCtr bool) error { - srcPath, err := filepath.EvalSymlinks(src) + srcPath, err := evalSymlinks(src) if err != nil { return errors.Wrapf(err, "error evaluating symlinks %q", srcPath) } diff --git a/cmd/podman/logs.go b/cmd/podman/logs.go index 32605389e..a2594b5bf 100644 --- a/cmd/podman/logs.go +++ b/cmd/podman/logs.go @@ -52,7 +52,7 @@ func init() { flags.BoolVarP(&logsCommand.Follow, "follow", "f", false, "Follow log output. The default is false") flags.BoolVarP(&logsCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of") flags.StringVar(&logsCommand.Since, "since", "", "Show logs since TIMESTAMP") - flags.Uint64Var(&logsCommand.Tail, "tail", 0, "Output the specified number of LINES at the end of the logs. Defaults to 0, which prints all lines") + flags.Int64Var(&logsCommand.Tail, "tail", -1, "Output the specified number of LINES at the end of the logs. Defaults to -1, which prints all lines") flags.BoolVarP(&logsCommand.Timestamps, "timestamps", "t", false, "Output the timestamps in the log") markFlagHidden(flags, "details") flags.SetInterspersed(false) diff --git a/cmd/podman/main_local.go b/cmd/podman/main_local.go index 202d93b35..6057eeec3 100644 --- a/cmd/podman/main_local.go +++ b/cmd/podman/main_local.go @@ -16,7 +16,8 @@ import ( "github.com/containers/libpod/cmd/podman/cliconfig" "github.com/containers/libpod/cmd/podman/libpodruntime" - "github.com/containers/libpod/libpod" + "github.com/containers/libpod/libpod/config" + "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/cgroups" "github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/tracing" @@ -32,8 +33,8 @@ import ( const remote = false func init() { - cgroupManager := libpod.SystemdCgroupsManager - if runtimeConfig, err := libpod.DefaultRuntimeConfig(); err == nil { + cgroupManager := define.SystemdCgroupsManager + if runtimeConfig, err := config.NewConfig(""); err == nil { cgroupManager = runtimeConfig.CgroupManager } cgroupHelp := "Cgroup manager to use (cgroupfs or systemd)" @@ -181,7 +182,7 @@ func setupRootless(cmd *cobra.Command, args []string) error { if !ownsCgroup { unitName := fmt.Sprintf("podman-%d.scope", os.Getpid()) if err := utils.RunUnderSystemdScope(os.Getpid(), "user.slice", unitName); err != nil { - if conf.CgroupManager == libpod.SystemdCgroupsManager { + if conf.CgroupManager == define.SystemdCgroupsManager { logrus.Warnf("Failed to add podman to systemd sandbox cgroup: %v", err) } else { logrus.Debugf("Failed to add podman to systemd sandbox cgroup: %v", err) @@ -225,7 +226,7 @@ func setupRootless(cmd *cobra.Command, args []string) error { if err != nil { return err } - if conf.CgroupManager == libpod.SystemdCgroupsManager { + if conf.CgroupManager == define.SystemdCgroupsManager { logrus.Warnf("Failed to add pause process to systemd sandbox cgroup: %v", err) } else { logrus.Debugf("Failed to add pause process to systemd sandbox cgroup: %v", err) diff --git a/cmd/podman/utils.go b/cmd/podman/utils.go index 592d7a1d1..c19e6391e 100644 --- a/cmd/podman/utils.go +++ b/cmd/podman/utils.go @@ -68,7 +68,8 @@ func aliasFlags(f *pflag.FlagSet, name string) pflag.NormalizedName { // Check if a file exists and is not a directory func checkIfFileExists(name string) bool { file, err := os.Stat(name) - if os.IsNotExist(err) { + // All errors return file == nil + if err != nil { return false } return !file.IsDir() diff --git a/contrib/cirrus/lib.sh b/contrib/cirrus/lib.sh index 051157702..297ed49ce 100644 --- a/contrib/cirrus/lib.sh +++ b/contrib/cirrus/lib.sh @@ -238,34 +238,46 @@ ircmsg() { # there is at least one release tag not having any '-' characters (return 0) # or otherwise (return non-0). is_release() { - req_env_var CIRRUS_BASE_SHA CIRRUS_CHANGE_IN_REPO - local range="${CIRRUS_BASE_SHA}..${CIRRUS_CHANGE_IN_REPO}" - # Easy check first, default non-useful values - if echo "${range}$CIRRUS_TAG" | grep -iq 'unknown'; then - die 11 "is_release() unusable range ${range} or tag $CIRRUS_TAG" - fi - # Next easy check, is CIRRUS_TAG set unset RELVER + local ret + req_env_var CIRRUS_CHANGE_IN_REPO if [[ -n "$CIRRUS_TAG" ]]; then RELVER="$CIRRUS_TAG" - else # Lastly, look through the range for tags - git fetch --all --tags &> /dev/null|| \ - die 12 "is_release() failed to fetch tags" - RELVER=$(git log --pretty='format:%d' $range | \ - grep '(tag:' | sed -r -e 's/\s+[(]tag:\s+(v[0-9].*)[)]/\1/' | \ - sort -uV | tail -1) - [[ "$?" -eq "0" ]] || \ + elif [[ ! "$CIRRUS_BASE_SHA" =~ "unknown" ]] + then + # Normally not possible for this to be empty, except when unittesting. + req_env_var CIRRUS_BASE_SHA + local range="${CIRRUS_BASE_SHA}..${CIRRUS_CHANGE_IN_REPO}" + if echo "${range}$CIRRUS_TAG" | grep -iq 'unknown'; then + die 11 "is_release() unusable range ${range} or tag $CIRRUS_TAG" + fi + + if type -P git &> /dev/null + then + git fetch --all --tags &> /dev/null|| \ + die 12 "is_release() failed to fetch tags" + RELVER=$(git log --pretty='format:%d' $range | \ + grep '(tag:' | sed -r -e 's/\s+[(]tag:\s+(v[0-9].*)[)]/\1/' | \ + sort -uV | tail -1) + ret=$? + else + warn -1 "Git command not found while checking for release" + ret="-1" + fi + [[ "$ret" -eq "0" ]] || \ die 13 "is_release() failed to parse tags" + else # Not testing a PR, but neither CIRRUS_BASE_SHA or CIRRUS_TAG are set + return 1 fi - echo "Found \$RELVER $RELVER" if [[ -n "$RELVER" ]]; then + echo "Found \$RELVER $RELVER" if echo "$RELVER" | grep -q '-'; then - return 2 + return 2 # development tag else return 0 fi else - return 1 + return 1 # not a release fi } diff --git a/contrib/cirrus/lib.sh.t b/contrib/cirrus/lib.sh.t index 9915b42a4..8f4080dd5 100755 --- a/contrib/cirrus/lib.sh.t +++ b/contrib/cirrus/lib.sh.t @@ -138,16 +138,19 @@ function test_is_release() { } # FROM TO TAG RET MSG -#test_is_release "" "" "" "" "" - -test_is_release "" "" "" "9" "FATAL: is_release() requires \$CIRRUS_BASE_SHA to be non-empty" +test_is_release "" "" "" "9" "FATAL: is_release() requires \$CIRRUS_CHANGE_IN_REPO to be non-empty" test_is_release "x" "" "" "9" "FATAL: is_release() requires \$CIRRUS_CHANGE_IN_REPO to be non-empty" -test_is_release "unknown" "x" "" "11" "is_release() unusable range unknown..x or tag " -test_is_release "x" "unknown" "" "11" "is_release() unusable range x..unknown or tag " -test_is_release "x" "x" "unknown" "11" "is_release() unusable range x..x or tag unknown" +# post-merge / tag-push testing, FROM will be set 'unknown' by (lib.sh default) +test_is_release "unknown" "x" "" "1" "" +# post-merge / tag-push testing, oddball tag is set, FROM will be set 'unknown' +test_is_release "unknown" "unknown" "test-tag" "2" "Found \$RELVER test-tag" +# post-merge / tag-push testing, sane tag is set, FROM will be set 'unknown' +test_is_release "unknown" "unknown" "0.0.0" "0" "Found \$RELVER 0.0.0" +# hack/get_ci_vm or PR testing, FROM and TO are set, no tag is set +test_is_release "x" "x" "" "1" "" -# Negative-testing git with this function is very difficult, assume it works +# Negative-testing git with this function is very difficult, assume git works # test_is_release ... "is_release() failed to fetch tags" # test_is_release ... "is_release() failed to parse tags" diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 000000000..fb67e266c --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,23 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +clean: + rm -fr build/ + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/Readme.md b/docs/Readme.md new file mode 100644 index 000000000..4514afa77 --- /dev/null +++ b/docs/Readme.md @@ -0,0 +1,21 @@ +# Build the Docs + +## Directory Structure + +| | Directory | +| ------------------------------------ | --------------------------- | +| Markdown source for man pages | docs/source/markdown/ | +| man pages aliases as .so files | docs/source/markdown/links/ | +| restructured text for readthedocs.io | docs/rst/ | +| target for output | docs/build | +| man pages | docs/build/man | +| remote linux man pages | docs/build/remote/linux | +| remote darwin man pages | docs/build/remote/darwin | +| remote windows html pages | docs/build/remote/windows | + +## Support files + +| | | +| ------------------------------------ | --------------------------- | +| docs/remote-docs.sh | Read the docs/source/markdown files and format for each platform | +| docs/links-to-html.lua | pandoc filter to do aliases for html files |
\ No newline at end of file diff --git a/docs/rtd/make.bat b/docs/make.bat index 6247f7e23..6247f7e23 100644 --- a/docs/rtd/make.bat +++ b/docs/make.bat diff --git a/docs/podman-remote.sh b/docs/remote-docs.sh index 2f8e76d1b..1440b0926 100755 --- a/docs/podman-remote.sh +++ b/docs/remote-docs.sh @@ -1,17 +1,17 @@ #!/bin/bash -e # Assemble remote man pages for darwin or windows from markdown files -PLATFORM=$1 ## windows or darwin -TARGET=$2 ## where to output files +PLATFORM=$1 ## linux, windows or darwin +TARGET=${2} ## where to output files SOURCES=${@:3} ## directories to find markdown files PODMAN=${PODMAN:-bin/podman-remote} ## location overridden for testing function usage() { echo >&2 "$0 PLATFORM TARGET SOURCES..." - echo >&2 "PLATFORM: Is either darwin or windows." - echo >&2 "TARGET: Is the directory where files will be staged." - echo >&2 "SOURCES: Are the directories to source markdown files." + echo >&2 "PLATFORM: Is either linux, darwin or windows." + echo >&2 "TARGET: Is the directory where files will be staged. eg, docs/build/remote/linux" + echo >&2 "SOURCES: Are the directories of source files. eg, docs/markdown" } function fail() { @@ -21,19 +21,17 @@ function fail() { } case $PLATFORM in -'darwin') - EXT=1 - PUBLISHER=darwin_fn +darwin|linux) + PUBLISHER=man_fn ;; -'windows') - EXT=1.md - PUBLISHER=windows_fn +windows) + PUBLISHER=html_fn ;; -'-help') +-help) usage exit 0 ;; -*) fail '"darwin" and "windows" are currently the only supported platforms.' ;; +*) fail '"linux", "darwin" and "windows" are the only supported platforms.' ;; esac if [[ -z $TARGET ]]; then @@ -48,20 +46,20 @@ if [[ ! -x $PODMAN ]]; then fail "$PODMAN does not exist" fi -## darwin_fn copies the markdown page or link to flattened directory -function darwin_fn() { - local markdown=$1 - local file=$(basename $markdown) - local dir=$(dirname $markdown) +## man_fn copies the man page or link to flattened directory +function man_fn() { + local page=$1 + local file=$(basename $page) + local dir=$(dirname $page) - if [[ -f $dir/links/$file ]]; then - markdown=$dir/links/$file + if [[ ! -f $page ]]; then + page=$dir/links/${file%.*}.1 fi - install $markdown $TARGET + install $page $TARGET/${file%%.*}.1 } -## windows_fn converts the markdown page or link to HTML -function windows_fn() { +## html_fn converts the markdown page or link to HTML +function html_fn() { local markdown=$1 local file=$(basename $markdown) local dir=$(dirname $markdown) @@ -70,21 +68,26 @@ function windows_fn() { local link=$(sed -e 's?.so man1/\(.*\)?\1?' <$dir/links/${file%.md}) markdown=$dir/$link.md fi - pandoc --ascii --lua-filter=$dir/links-to-html.lua -o $TARGET/${file%.$EXT}.html $markdown + pandoc --ascii --lua-filter=docs/links-to-html.lua -o $TARGET/${file%%.*}.html $markdown } ## pub_pages finds and publishes the remote manual pages function pub_pages() { local source=$1 local publisher=$2 - for f in $(ls $source/podman-remote*$EXT); do + for f in $(ls $source/podman-remote*); do $publisher $f done + # rename podman-remote.ext to podman.ext and copy + local remote=$(echo $TARGET/podman-remote.*) + local ext=${remote##*.} + cp -f $remote $TARGET/podman.$ext + for c in "container" "image" "pod" "volume" ""; do local cmd=${c:+-$c} for s in $($PODMAN $c --help | sed -n '/^Available Commands:/,/^Flags:/p' | sed -e '1d;$d' -e '/^$/d' | awk '{print $1}'); do - $publisher $source/podman$cmd-$s.$EXT + $publisher $(echo $source/podman$cmd-$s.*) done done } diff --git a/docs/rtd/requirements.txt b/docs/requirements.txt index 44af373ac..44af373ac 100644 --- a/docs/rtd/requirements.txt +++ b/docs/requirements.txt diff --git a/docs/rtd/Makefile b/docs/rtd/Makefile deleted file mode 100644 index 50af6490a..000000000 --- a/docs/rtd/Makefile +++ /dev/null @@ -1,123 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line, and also -# from the environment for the first two. -SPHINXOPTS ?= -SPHINXBUILD ?= sphinx-build -SOURCEDIR = source -BUILDDIR = build - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -clean: - rm -fr build/ - rm -f source/man/podman-*.1.md - -copy: - cp -v ../podman-attach.1.md source/man/ - cp -v ../podman-build.1.md source/man/ - cp -v ../podman-commit.1.md source/man/ - # container - cp -v ../podman-container-checkpoint.1.md source/man/ - cp -v ../podman-container-exists.1.md source/man/ - cp -v ../podman-container-restore.1.md source/man/ - cp -v ../podman-container-cleanup.1.md source/man/ - cp -v ../podman-container-prune.1.md source/man/ - cp -v ../podman-container-runlabel.1.md source/man/ - cp -v ../podman-cp.1.md source/man/ - cp -v ../podman-create.1.md source/man/ - cp -v ../podman-diff.1.md source/man/ - cp -v ../podman-events.1.md source/man/ - cp -v ../podman-exec.1.md source/man/ - cp -v ../podman-export.1.md source/man/ - # generate - cp -v ../podman-generate-systemd.1.md source/man/ - cp -v ../podman-generate-kube.1.md source/man/ - # healthcheck - cp -v ../podman-healthcheck-run.1.md source/man/ - #cp -v ../podman-help.1.md source/ - cp -v ../podman-history.1.md source/man/ - # image - cp -v ../podman-image-prune.1.md source/man/ - cp -v ../podman-image-tree.1.md source/man/ - cp -v ../podman-image-trust.1.md source/man/ - cp -v ../podman-image-exists.1.md source/man/ - cp -v ../podman-image-sign.1.md source/man/ - cp -v ../podman-images.1.md source/man/ - cp -v ../podman-import.1.md source/man/ - cp -v ../podman-info.1.md source/man/ - cp -v ../podman-init.1.md source/man/ - cp -v ../podman-inspect.1.md source/man/ - cp -v ../podman-kill.1.md source/man/ - cp -v ../podman-load.1.md source/man/ - cp -v ../podman-login.1.md source/man/ - cp -v ../podman-logout.1.md source/man/ - cp -v ../podman-logs.1.md source/man/ - cp -v ../podman-mount.1.md source/man/ - # network - cp -v ../podman-network-create.1.md source/man/ - cp -v ../podman-network-ls.1.md source/man/ - cp -v ../podman-network-inspect.1.md source/man/ - cp -v ../podman-network-rm.1.md source/man/ - cp -v ../podman-pause.1.md source/man/ - # play - cp -v ../podman-play-kube.1.md source/man/ - # pod - cp -v ../podman-pod-create.1.md source/man/ - cp -v ../podman-pod-pause.1.md source/man/ - cp -v ../podman-pod-rm.1.md source/man/ - cp -v ../podman-pod-top.1.md source/man/ - cp -v ../podman-pod-exists.1.md source/man/ - cp -v ../podman-pod-prune.1.md source/man/ - cp -v ../podman-pod-start.1.md source/man/ - cp -v ../podman-pod-unpause.1.md source/man/ - cp -v ../podman-pod-inspect.1.md source/man/ - cp -v ../podman-pod-ps.1.md source/man/ - cp -v ../podman-pod-stats.1.md source/man/ - cp -v ../podman-pod-kill.1.md source/man/ - cp -v ../podman-pod-restart.1.md source/man/ - cp -v ../podman-pod-stop.1.md source/man/ - cp -v ../podman-port.1.md source/man/ - cp -v ../podman-ps.1.md source/man/ - cp -v ../podman-pull.1.md source/man/ - cp -v ../podman-push.1.md source/man/ - cp -v ../podman-restart.1.md source/man/ - cp -v ../podman-rm.1.md source/man/ - cp -v ../podman-rmi.1.md source/man/ - cp -v ../podman-run.1.md source/man/ - cp -v ../podman-save.1.md source/man/ - cp -v ../podman-search.1.md source/man/ - cp -v ../podman-start.1.md source/man/ - cp -v ../podman-stats.1.md source/man/ - cp -v ../podman-stop.1.md source/man/ - # system - cp -v ../podman-system-migrate.1.md source/man/ - cp -v ../podman-system-renumber.1.md source/man/ - cp -v ../podman-system-df.1.md source/man/ - cp -v ../podman-system-prune.1.md source/man/ - cp -v ../podman-top.1.md source/man/ - cp -v ../podman-umount.1.md source/man/ - cp -v ../podman-unpause.1.md source/man/ - cp -v ../podman-unshare.1.md source/man/ - cp -v ../podman-varlink.1.md source/man/ - cp -v ../podman-version.1.md source/man/ - # volume - cp -v ../podman-volume-inspect.1.md source/man/ - cp -v ../podman-volume-prune.1.md source/man/ - cp -v ../podman-volume-create.1.md source/man/ - cp -v ../podman-volume-ls.1.md source/man/ - cp -v ../podman-volume-rm.1.md source/man/ - cp -v ../podman-wait.1.md source/man/ - -.PHONY: help Makefile copy - -html: copy - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/rtd/source/Commands.rst b/docs/rtd/source/Commands.rst deleted file mode 100644 index f6ba5b20d..000000000 --- a/docs/rtd/source/Commands.rst +++ /dev/null @@ -1,107 +0,0 @@ -Commands -======== - - -:doc:`attach <man/podman-attach.1>` Attach to a running container - -:doc:`build <man/podman-build.1>` Build an image using instructions from Containerfiles - -:doc:`commit <man/podman-commit.1>` Create new image based on the changed container - -:doc:`containers <man/managecontainers>` Manage Containers - -:doc:`cp <man/podman-cp.1>` Copy files/folders between a container and the local filesystem - -:doc:`create <man/podman-create.1>` Create but do not start a container - -:doc:`diff <man/podman-diff.1>` Inspect changes on container's file systems - -:doc:`events <man/podman-events.1>` Show podman events - -:doc:`exec <man/podman-exec.1>` Run a process in a running container - -:doc:`export <man/podman-export.1>` Export container's filesystem contents as a tar archive - -:doc:`generate <man/generate>` Generated structured data - -:doc:`healthcheck <man/healthcheck>` Manage Healthcheck - -:doc:`history <man/podman-history.1>` Show history of a specified image - -:doc:`image <man/image>` Manage images - -:doc:`images <man/podman-images.1>` List images in local storage - -:doc:`import <man/podman-import.1>` Import a tarball to create a filesystem image - -:doc:`info <man/podman-info.1>` Display podman system information - -:doc:`init <man/podman-init.1>` Initialize one or more containers - -:doc:`inspect <man/podman-inspect.1>` Display the configuration of a container or image - -:doc:`kill <man/podman-kill.1>` Kill one or more running containers with a specific signal - -:doc:`load <man/podman-load.1>` Load an image from container archive - -:doc:`login <man/podman-login.1>` Login to a container registry - -:doc:`logout <man/podman-logout.1>` Logout of a container registry - -:doc:`logs <man/podman-logs.1>` Fetch the logs of a container - -:doc:`mount <man/podman-mount.1>` Mount a working container's root filesystem - -:doc:`network <man/network>` Manage Networks - -:doc:`pause <man/podman-pause.1>` Pause all the processes in one or more containers - -:doc:`play <man/play>` Play a pod - -:doc:`pod <man/pod>` Manage pods - -:doc:`port <man/podman-port.1>` List port mappings or a specific mapping for the container - -:doc:`ps <man/podman-ps.1>` List containers - -:doc:`pull <man/podman-pull.1>` Pull an image from a registry - -:doc:`push <man/podman-push.1>` Push an image to a specified destination - -:doc:`restart <man/podman-restart.1>` Restart one or more containers - -:doc:`rm <man/podman-rm.1>` Remove one or more containers - -:doc:`rmi <man/podman-rmi.1>` Removes one or more images from local storage - -:doc:`run <man/podman-run.1>` Run a command in a new container - -:doc:`save <man/podman-save.1>` Save image to an archive - -:doc:`search <man/podman-search.1>` Search registry for image - -:doc:`start <man/podman-start.1>` Start one or more containers - -:doc:`stats <man/podman-stats.1>` Display a live stream of container resource usage statistics - -:doc:`stop <man/podman-stop.1>` Stop one or more containers - -:doc:`system <man/system>` Manage podman - -:doc:`tag <man/podman-tag.1>` Add an additional name to a local image - -:doc:`top <man/podman-top.1>` Display the running processes of a container - -:doc:`umount <man/podman-umount.1>` Unmounts working container's root filesystem - -:doc:`unpause <man/podman-unpause.1>` Unpause the processes in one or more containers - -:doc:`unshare <man/podman-unshare.1>` Run a command in a modified user namespace - -:doc:`varlink <man/podman-varlink.1>` Run varlink interface - -:doc:`version <man/podman-version.1>` Display the Podman Version Information - -:doc:`volume <man/volume>` Manage volumes - -:doc:`wait <man/podman-wait.1>` Block on one or more containers
\ No newline at end of file diff --git a/docs/rtd/source/man/generate.rst b/docs/rtd/source/man/generate.rst deleted file mode 100644 index e82a15735..000000000 --- a/docs/rtd/source/man/generate.rst +++ /dev/null @@ -1,6 +0,0 @@ -Generate -======== - -:doc:`kube <podman-generate-kube.1>` Generate Kubernetes pod YAML from a container or pod - -:doc:`systemd <podman-generate-systemd.1>` Generate a systemd unit file for a Podman container diff --git a/docs/rtd/source/man/healthcheck.rst b/docs/rtd/source/man/healthcheck.rst deleted file mode 100644 index 697c1358b..000000000 --- a/docs/rtd/source/man/healthcheck.rst +++ /dev/null @@ -1,4 +0,0 @@ -HealthCheck -=========== - -:doc:`run <podman-healthcheck-run.1>` run the health check of a container diff --git a/docs/rtd/source/man/image.rst b/docs/rtd/source/man/image.rst deleted file mode 100644 index ad963cd41..000000000 --- a/docs/rtd/source/man/image.rst +++ /dev/null @@ -1,35 +0,0 @@ -Image -===== - - -:doc:`build <podman-build.1>` Build an image using instructions from Containerfiles - -:doc:`exists <podman-image-exists.1>` Check if an image exists in local storage - -:doc:`history <podman-history.1>` Show history of a specified image - -:doc:`import <podman-import.1>` Import a tarball to create a filesystem image - -:doc:`inspect <podman-inspect.1>` Display the configuration of an image - -:doc:`list <podman-images.1>` List images in local storage - -:doc:`load <podman-load.1>` Load an image from container archive - -:doc:`prune <podman-image-prune.1>` Remove unused images - -:doc:`pull <podman-pull.1>` Pull an image from a registry - -:doc:`push <podman-push.1>` Push an image to a specified destination - -:doc:`rm <podman-rmi.1>` Removes one or more images from local storage - -:doc:`save <podman-save.1>` Save image to an archive - -:doc:`sign <podman-image-sign.1>` Sign an image - -:doc:`tag <podman-tag.1>` Add an additional name to a local image - -:doc:`tree <podman-image-tree.1>` Prints layer hierarchy of an image in a tree format - -:doc:`trust <podman-image-trust.1>` Manage container image trust policy diff --git a/docs/rtd/source/man/managecontainers.rst b/docs/rtd/source/man/managecontainers.rst deleted file mode 100644 index 20e8c0679..000000000 --- a/docs/rtd/source/man/managecontainers.rst +++ /dev/null @@ -1,64 +0,0 @@ -Manage Containers -================= - -:doc:`attach <podman-attach.1>` Attach to a running container - -:doc:`checkpoint <podman-container-checkpoint.1>` Checkpoints one or more containers - -:doc:`cleanup <podman-container-cleanup.1>` Cleanup network and mountpoints of one or more containers - -:doc:`commit <podman-commit.1>` Create new image based on the changed container - -:doc:`cp <podman-cp.1>` Copy files/folders between a container and the local filesystem - -:doc:`create <podman-create.1>` Create but do not start a container - -:doc:`diff <podman-diff.1>` Inspect changes on container's file systems - -:doc:`exec <podman-exec.1>` Run a process in a running container - -:doc:`exists <podman-exists.1>` Check if a container exists in local storage - -:doc:`export <podman-export.1>` Export container's filesystem contents as a tar archive - -:doc:`init <podman-init.1>` Initialize one or more containers - -:doc:`inspect <podman-inspect.1>` Display the configuration of a container or image - -:doc:`kill <podman-kill.1>` Kill one or more running containers with a specific signal - -:doc:`list <podman-ps.1>` List containers - -:doc:`logs <podman-logs.1>` Fetch the logs of a container - -:doc:`mount <podman-mount.1>` Mount a working container's root filesystem - -:doc:`pause <podman-pause.1>` Pause all the processes in one or more containers - -:doc:`port <podman-port.1>` List port mappings or a specific mapping for the container - -:doc:`restart <podman-restart.1>` Restart one or more containers - -:doc:`prune <podman-container-prune.1>` Remove all stopped containers - -:doc:`restore <podman-container-restore.1>` Restores one or more containers from a checkpoint - -:doc:`rm <podman-rm.1>` Remove one or more containers - -:doc:`run <podman-run.1>` Run a command in a new container - -:doc:`runlabel <podman-container-runlabel.1>` Execute the command described by an image label - -:doc:`start <podman-start.1>` Start one or more containers - -:doc:`stats <podman-stats.1>` Display a live stream of container resource usage statistics - -:doc:`stop <podman-stop.1>` Stop one or more containers - -:doc:`top <podman-top.1>` Display the running processes of a container - -:doc:`umount <podman-umount.1>` Unmounts working container's root filesystem - -:doc:`unpause <podman-unpause.1>` Unpause the processes in one or more containers - -:doc:`wait <podman-wait.1>` Block on one or more containers diff --git a/docs/rtd/source/man/network.rst b/docs/rtd/source/man/network.rst deleted file mode 100644 index 6d6a4c022..000000000 --- a/docs/rtd/source/man/network.rst +++ /dev/null @@ -1,10 +0,0 @@ -Network -===== - -:doc:`create <podman-network-create.1>` network create - -:doc:`inspect <podman-network-inspect.1>` network inspect - -:doc:`ls <podman-network-ls.1>` network list - -:doc:`rm <podman-network-rm.1>` network rm
\ No newline at end of file diff --git a/docs/rtd/source/man/play.rst b/docs/rtd/source/man/play.rst deleted file mode 100644 index 93e1a9a1e..000000000 --- a/docs/rtd/source/man/play.rst +++ /dev/null @@ -1,4 +0,0 @@ -Play -==== - -:doc:`kube <podman-play-kube.1>` Play a pod based on Kubernetes YAML diff --git a/docs/rtd/source/man/pod.rst b/docs/rtd/source/man/pod.rst deleted file mode 100644 index 13c1740f8..000000000 --- a/docs/rtd/source/man/pod.rst +++ /dev/null @@ -1,30 +0,0 @@ -Pod -=== - -:doc:`create <podman-pod-create.1>` Create a new empty pod - -:doc:`exists <podman-pod-exists.1>` Check if a pod exists in local storage - -:doc:`inspect <podman-pod-inspect.1>` Displays a pod configuration - -:doc:`kill <podman-pod-kill.1>` Send the specified signal or SIGKILL to containers in pod - -:doc:`pause <podman-pause.1>` Pause one or more pods - -:doc:`prune <podman-pod-prune.1>` Remove all stopped pods - -:doc:`ps <podman-pod-ps.1>` List pods - -:doc:`restart <podman-pod-restart.1>` Restart one or more pods - -:doc:`rm <podman-pod-rm.1>` Remove one or more pods - -:doc:`start <podman-pod-start.1>` Start one or more pods - -:doc:`stats <podman-pod-stats.1>` Display a live stream of resource usage statistics for the containers in one or more pods - -:doc:`stop <podman-pod-stop.1>` Stop one or more pods - -:doc:`top <podman-pod-top.1>` Display the running processes of containers in a pod - -:doc:`unpause <podman-pod-unpause.1>` Unpause one or more pods diff --git a/docs/rtd/source/man/system.rst b/docs/rtd/source/man/system.rst deleted file mode 100644 index 764ec01c1..000000000 --- a/docs/rtd/source/man/system.rst +++ /dev/null @@ -1,12 +0,0 @@ -System -====== - -:doc:`df <podman-system-df.1>` Show podman disk usage - -:doc:`info <podman-info.1>` Display podman system information - -:doc:`migrate <podman-system-migrate.1>` Migrate containers - -:doc:`prune <podman-system-prune.1>` Remove unused data - -:doc:`renumber <podman-system-renumber.1>` Migrate lock numbers diff --git a/docs/rtd/source/man/volume.rst b/docs/rtd/source/man/volume.rst deleted file mode 100644 index ee18e4b2e..000000000 --- a/docs/rtd/source/man/volume.rst +++ /dev/null @@ -1,11 +0,0 @@ -Volume -====== -:doc:`create <podman-volume-create.1>` Create a new volume - -:doc:`inspect <podman-volume-inspect.1>` Display detailed information on one or more volumes - -:doc:`ls <podman-volume-ls.1>` List volumes - -:doc:`prune <podman-volume-prune.1>` Remove all unused volumes - -:doc:`rm <podman-volume-rm.1>` Remove one or more volumes
\ No newline at end of file diff --git a/docs/source/Commands.rst b/docs/source/Commands.rst new file mode 100644 index 000000000..276a9c4fb --- /dev/null +++ b/docs/source/Commands.rst @@ -0,0 +1,107 @@ +Commands +======== + + +:doc:`attach <markdown/podman-attach.1>` Attach to a running container + +:doc:`build <markdown/podman-build.1>` Build an image using instructions from Containerfiles + +:doc:`commit <markdown/podman-commit.1>` Create new image based on the changed container + +:doc:`containers <managecontainers>` Manage Containers + +:doc:`cp <markdown/podman-cp.1>` Copy files/folders between a container and the local filesystem + +:doc:`create <markdown/podman-create.1>` Create but do not start a container + +:doc:`diff <markdown/podman-diff.1>` Inspect changes on container's file systems + +:doc:`events <markdown/podman-events.1>` Show podman events + +:doc:`exec <markdown/podman-exec.1>` Run a process in a running container + +:doc:`export <markdown/podman-export.1>` Export container's filesystem contents as a tar archive + +:doc:`generate <generate>` Generated structured data + +:doc:`healthcheck <healthcheck>` Manage Healthcheck + +:doc:`history <markdown/podman-history.1>` Show history of a specified image + +:doc:`image <image>` Manage images + +:doc:`images <markdown/podman-images.1>` List images in local storage + +:doc:`import <markdown/podman-import.1>` Import a tarball to create a filesystem image + +:doc:`info <markdown/podman-info.1>` Display podman system information + +:doc:`init <markdown/podman-init.1>` Initialize one or more containers + +:doc:`inspect <markdown/podman-inspect.1>` Display the configuration of a container or image + +:doc:`kill <markdown/podman-kill.1>` Kill one or more running containers with a specific signal + +:doc:`load <markdown/podman-load.1>` Load an image from container archive + +:doc:`login <markdown/podman-login.1>` Login to a container registry + +:doc:`logout <markdown/podman-logout.1>` Logout of a container registry + +:doc:`logs <markdown/podman-logs.1>` Fetch the logs of a container + +:doc:`mount <markdown/podman-mount.1>` Mount a working container's root filesystem + +:doc:`network <network>` Manage Networks + +:doc:`pause <markdown/podman-pause.1>` Pause all the processes in one or more containers + +:doc:`play <play>` Play a pod + +:doc:`pod <pod>` Manage pods + +:doc:`port <markdown/podman-port.1>` List port mappings or a specific mapping for the container + +:doc:`ps <markdown/podman-ps.1>` List containers + +:doc:`pull <markdown/podman-pull.1>` Pull an image from a registry + +:doc:`push <markdown/podman-push.1>` Push an image to a specified destination + +:doc:`restart <markdown/podman-restart.1>` Restart one or more containers + +:doc:`rm <markdown/podman-rm.1>` Remove one or more containers + +:doc:`rmi <markdown/podman-rmi.1>` Removes one or more images from local storage + +:doc:`run <markdown/podman-run.1>` Run a command in a new container + +:doc:`save <markdown/podman-save.1>` Save image to an archive + +:doc:`search <markdown/podman-search.1>` Search registry for image + +:doc:`start <markdown/podman-start.1>` Start one or more containers + +:doc:`stats <markdown/podman-stats.1>` Display a live stream of container resource usage statistics + +:doc:`stop <markdown/podman-stop.1>` Stop one or more containers + +:doc:`system <system>` Manage podman + +:doc:`tag <markdown/podman-tag.1>` Add an additional name to a local image + +:doc:`top <markdown/podman-top.1>` Display the running processes of a container + +:doc:`umount <markdown/podman-umount.1>` Unmounts working container's root filesystem + +:doc:`unpause <markdown/podman-unpause.1>` Unpause the processes in one or more containers + +:doc:`unshare <markdown/podman-unshare.1>` Run a command in a modified user namespace + +:doc:`varlink <markdown/podman-varlink.1>` Run varlink interface + +:doc:`version <markdown/podman-version.1>` Display the Podman Version Information + +:doc:`volume <volume>` Manage volumes + +:doc:`wait <markdown/podman-wait.1>` Block on one or more containers
\ No newline at end of file diff --git a/docs/rtd/source/Introduction.rst b/docs/source/Introduction.rst index c516b3317..c516b3317 100644 --- a/docs/rtd/source/Introduction.rst +++ b/docs/source/Introduction.rst diff --git a/docs/rtd/source/Reference.rst b/docs/source/Reference.rst index 9a771c87f..9a771c87f 100644 --- a/docs/rtd/source/Reference.rst +++ b/docs/source/Reference.rst diff --git a/docs/rtd/source/Tutorials.rst b/docs/source/Tutorials.rst index 0c7e28c3b..0c7e28c3b 100644 --- a/docs/rtd/source/Tutorials.rst +++ b/docs/source/Tutorials.rst diff --git a/docs/rtd/source/conf.py b/docs/source/conf.py index d95290f72..d95290f72 100644 --- a/docs/rtd/source/conf.py +++ b/docs/source/conf.py diff --git a/docs/source/generate.rst b/docs/source/generate.rst new file mode 100644 index 000000000..fd267ce62 --- /dev/null +++ b/docs/source/generate.rst @@ -0,0 +1,6 @@ +Generate +======== + +:doc:`kube <markdown/podman-generate-kube.1>` Generate Kubernetes pod YAML from a container or pod + +:doc:`systemd <markdown/podman-generate-systemd.1>` Generate a systemd unit file for a Podman container diff --git a/docs/source/healthcheck.rst b/docs/source/healthcheck.rst new file mode 100644 index 000000000..2e2f88fbc --- /dev/null +++ b/docs/source/healthcheck.rst @@ -0,0 +1,4 @@ +HealthCheck +=========== + +:doc:`run <markdown/podman-healthcheck-run.1>` run the health check of a container diff --git a/docs/source/image.rst b/docs/source/image.rst new file mode 100644 index 000000000..a8c6171e1 --- /dev/null +++ b/docs/source/image.rst @@ -0,0 +1,35 @@ +Image +===== + + +:doc:`build <markdown/podman-build.1>` Build an image using instructions from Containerfiles + +:doc:`exists <markdown/podman-image-exists.1>` Check if an image exists in local storage + +:doc:`history <markdown/podman-history.1>` Show history of a specified image + +:doc:`import <markdown/podman-import.1>` Import a tarball to create a filesystem image + +:doc:`inspect <markdown/podman-inspect.1>` Display the configuration of an image + +:doc:`list <markdown/podman-images.1>` List images in local storage + +:doc:`load <markdown/podman-load.1>` Load an image from container archive + +:doc:`prune <markdown/podman-image-prune.1>` Remove unused images + +:doc:`pull <markdown/podman-pull.1>` Pull an image from a registry + +:doc:`push <markdown/podman-push.1>` Push an image to a specified destination + +:doc:`rm <markdown/podman-rmi.1>` Removes one or more images from local storage + +:doc:`save <markdown/podman-save.1>` Save image to an archive + +:doc:`sign <markdown/podman-image-sign.1>` Sign an image + +:doc:`tag <markdown/podman-tag.1>` Add an additional name to a local image + +:doc:`tree <markdown/podman-image-tree.1>` Prints layer hierarchy of an image in a tree format + +:doc:`trust <markdown/podman-image-trust.1>` Manage container image trust policy diff --git a/docs/rtd/source/index.rst b/docs/source/index.rst index 9dd61a6a6..9dd61a6a6 100644 --- a/docs/rtd/source/index.rst +++ b/docs/source/index.rst diff --git a/docs/source/managecontainers.rst b/docs/source/managecontainers.rst new file mode 100644 index 000000000..5c5a83a82 --- /dev/null +++ b/docs/source/managecontainers.rst @@ -0,0 +1,64 @@ +Manage Containers +================= + +:doc:`attach <markdown/podman-attach.1>` Attach to a running container + +:doc:`checkpoint <markdown/podman-container-checkpoint.1>` Checkpoints one or more containers + +:doc:`cleanup <markdown/podman-container-cleanup.1>` Cleanup network and mountpoints of one or more containers + +:doc:`commit <markdown/podman-commit.1>` Create new image based on the changed container + +:doc:`cp <markdown/podman-cp.1>` Copy files/folders between a container and the local filesystem + +:doc:`create <markdown/podman-create.1>` Create but do not start a container + +:doc:`diff <markdown/podman-diff.1>` Inspect changes on container's file systems + +:doc:`exec <markdown/podman-exec.1>` Run a process in a running container + +:doc:`exists <markdown/podman-container-exists.1>` Check if a container exists in local storage + +:doc:`export <markdown/podman-export.1>` Export container's filesystem contents as a tar archive + +:doc:`init <markdown/podman-init.1>` Initialize one or more containers + +:doc:`inspect <markdown/podman-inspect.1>` Display the configuration of a container or image + +:doc:`kill <markdown/podman-kill.1>` Kill one or more running containers with a specific signal + +:doc:`list <markdown/podman-ps.1>` List containers + +:doc:`logs <markdown/podman-logs.1>` Fetch the logs of a container + +:doc:`mount <markdown/podman-mount.1>` Mount a working container's root filesystem + +:doc:`pause <markdown/podman-pause.1>` Pause all the processes in one or more containers + +:doc:`port <markdown/podman-port.1>` List port mappings or a specific mapping for the container + +:doc:`restart <markdown/podman-restart.1>` Restart one or more containers + +:doc:`prune <markdown/podman-container-prune.1>` Remove all stopped containers + +:doc:`restore <markdown/podman-container-restore.1>` Restores one or more containers from a checkpoint + +:doc:`rm <markdown/podman-rm.1>` Remove one or more containers + +:doc:`run <markdown/podman-run.1>` Run a command in a new container + +:doc:`runlabel <markdown/podman-container-runlabel.1>` Execute the command described by an image label + +:doc:`start <markdown/podman-start.1>` Start one or more containers + +:doc:`stats <markdown/podman-stats.1>` Display a live stream of container resource usage statistics + +:doc:`stop <markdown/podman-stop.1>` Stop one or more containers + +:doc:`top <markdown/podman-top.1>` Display the running processes of a container + +:doc:`umount <markdown/podman-umount.1>` Unmounts working container's root filesystem + +:doc:`unpause <markdown/podman-unpause.1>` Unpause the processes in one or more containers + +:doc:`wait <markdown/podman-wait.1>` Block on one or more containers diff --git a/docs/links/podman-container-attach.1 b/docs/source/markdown/links/podman-container-attach.1 index be3b5efd3..be3b5efd3 100644 --- a/docs/links/podman-container-attach.1 +++ b/docs/source/markdown/links/podman-container-attach.1 diff --git a/docs/links/podman-container-commit.1 b/docs/source/markdown/links/podman-container-commit.1 index cdff06766..cdff06766 100644 --- a/docs/links/podman-container-commit.1 +++ b/docs/source/markdown/links/podman-container-commit.1 diff --git a/docs/links/podman-container-cp.1 b/docs/source/markdown/links/podman-container-cp.1 index 6ad859c84..6ad859c84 100644 --- a/docs/links/podman-container-cp.1 +++ b/docs/source/markdown/links/podman-container-cp.1 diff --git a/docs/links/podman-container-create.1 b/docs/source/markdown/links/podman-container-create.1 index f6b07d946..f6b07d946 100644 --- a/docs/links/podman-container-create.1 +++ b/docs/source/markdown/links/podman-container-create.1 diff --git a/docs/links/podman-container-diff.1 b/docs/source/markdown/links/podman-container-diff.1 index ac4881f98..ac4881f98 100644 --- a/docs/links/podman-container-diff.1 +++ b/docs/source/markdown/links/podman-container-diff.1 diff --git a/docs/links/podman-container-exec.1 b/docs/source/markdown/links/podman-container-exec.1 index 6bb98ec75..6bb98ec75 100644 --- a/docs/links/podman-container-exec.1 +++ b/docs/source/markdown/links/podman-container-exec.1 diff --git a/docs/links/podman-container-export.1 b/docs/source/markdown/links/podman-container-export.1 index 85b1d5438..85b1d5438 100644 --- a/docs/links/podman-container-export.1 +++ b/docs/source/markdown/links/podman-container-export.1 diff --git a/docs/links/podman-container-init.1 b/docs/source/markdown/links/podman-container-init.1 index 3a8bee249..3a8bee249 100644 --- a/docs/links/podman-container-init.1 +++ b/docs/source/markdown/links/podman-container-init.1 diff --git a/docs/links/podman-container-inspect.1 b/docs/source/markdown/links/podman-container-inspect.1 index 261043845..261043845 100644 --- a/docs/links/podman-container-inspect.1 +++ b/docs/source/markdown/links/podman-container-inspect.1 diff --git a/docs/links/podman-container-kill.1 b/docs/source/markdown/links/podman-container-kill.1 index 71960113d..71960113d 100644 --- a/docs/links/podman-container-kill.1 +++ b/docs/source/markdown/links/podman-container-kill.1 diff --git a/docs/links/podman-container-list.1 b/docs/source/markdown/links/podman-container-list.1 index f7f44c704..f7f44c704 100644 --- a/docs/links/podman-container-list.1 +++ b/docs/source/markdown/links/podman-container-list.1 diff --git a/docs/links/podman-container-logs.1 b/docs/source/markdown/links/podman-container-logs.1 index 7e0ce6307..7e0ce6307 100644 --- a/docs/links/podman-container-logs.1 +++ b/docs/source/markdown/links/podman-container-logs.1 diff --git a/docs/links/podman-container-ls.1 b/docs/source/markdown/links/podman-container-ls.1 index f7f44c704..f7f44c704 100644 --- a/docs/links/podman-container-ls.1 +++ b/docs/source/markdown/links/podman-container-ls.1 diff --git a/docs/links/podman-container-mount.1 b/docs/source/markdown/links/podman-container-mount.1 index b14e594a4..b14e594a4 100644 --- a/docs/links/podman-container-mount.1 +++ b/docs/source/markdown/links/podman-container-mount.1 diff --git a/docs/links/podman-container-pause.1 b/docs/source/markdown/links/podman-container-pause.1 index 3ed8d7cef..3ed8d7cef 100644 --- a/docs/links/podman-container-pause.1 +++ b/docs/source/markdown/links/podman-container-pause.1 diff --git a/docs/links/podman-container-port.1 b/docs/source/markdown/links/podman-container-port.1 index adfeda201..adfeda201 100644 --- a/docs/links/podman-container-port.1 +++ b/docs/source/markdown/links/podman-container-port.1 diff --git a/docs/links/podman-container-ps.1 b/docs/source/markdown/links/podman-container-ps.1 index f7f44c704..f7f44c704 100644 --- a/docs/links/podman-container-ps.1 +++ b/docs/source/markdown/links/podman-container-ps.1 diff --git a/docs/links/podman-container-restart.1 b/docs/source/markdown/links/podman-container-restart.1 index 9fb09ae50..9fb09ae50 100644 --- a/docs/links/podman-container-restart.1 +++ b/docs/source/markdown/links/podman-container-restart.1 diff --git a/docs/links/podman-container-rm.1 b/docs/source/markdown/links/podman-container-rm.1 index 6dfc6e98c..6dfc6e98c 100644 --- a/docs/links/podman-container-rm.1 +++ b/docs/source/markdown/links/podman-container-rm.1 diff --git a/docs/links/podman-container-run.1 b/docs/source/markdown/links/podman-container-run.1 index 6c70caa37..6c70caa37 100644 --- a/docs/links/podman-container-run.1 +++ b/docs/source/markdown/links/podman-container-run.1 diff --git a/docs/links/podman-container-start.1 b/docs/source/markdown/links/podman-container-start.1 index aa042cbfe..aa042cbfe 100644 --- a/docs/links/podman-container-start.1 +++ b/docs/source/markdown/links/podman-container-start.1 diff --git a/docs/links/podman-container-stats.1 b/docs/source/markdown/links/podman-container-stats.1 index 5f2e2e7d6..5f2e2e7d6 100644 --- a/docs/links/podman-container-stats.1 +++ b/docs/source/markdown/links/podman-container-stats.1 diff --git a/docs/links/podman-container-stop.1 b/docs/source/markdown/links/podman-container-stop.1 index 6b7e87c69..6b7e87c69 100644 --- a/docs/links/podman-container-stop.1 +++ b/docs/source/markdown/links/podman-container-stop.1 diff --git a/docs/links/podman-container-top.1 b/docs/source/markdown/links/podman-container-top.1 index ddcf7b5ec..ddcf7b5ec 100644 --- a/docs/links/podman-container-top.1 +++ b/docs/source/markdown/links/podman-container-top.1 diff --git a/docs/links/podman-container-umount.1 b/docs/source/markdown/links/podman-container-umount.1 index 789dabbb0..789dabbb0 100644 --- a/docs/links/podman-container-umount.1 +++ b/docs/source/markdown/links/podman-container-umount.1 diff --git a/docs/links/podman-container-unmount.1 b/docs/source/markdown/links/podman-container-unmount.1 index 789dabbb0..789dabbb0 100644 --- a/docs/links/podman-container-unmount.1 +++ b/docs/source/markdown/links/podman-container-unmount.1 diff --git a/docs/links/podman-container-unpause.1 b/docs/source/markdown/links/podman-container-unpause.1 index b8d970744..b8d970744 100644 --- a/docs/links/podman-container-unpause.1 +++ b/docs/source/markdown/links/podman-container-unpause.1 diff --git a/docs/links/podman-container-wait.1 b/docs/source/markdown/links/podman-container-wait.1 index bd2505dde..bd2505dde 100644 --- a/docs/links/podman-container-wait.1 +++ b/docs/source/markdown/links/podman-container-wait.1 diff --git a/docs/links/podman-help.1 b/docs/source/markdown/links/podman-help.1 index 6b7954b0d..6b7954b0d 100644 --- a/docs/links/podman-help.1 +++ b/docs/source/markdown/links/podman-help.1 diff --git a/docs/links/podman-image-build.1 b/docs/source/markdown/links/podman-image-build.1 index 27c751cf6..27c751cf6 100644 --- a/docs/links/podman-image-build.1 +++ b/docs/source/markdown/links/podman-image-build.1 diff --git a/docs/links/podman-image-history.1 b/docs/source/markdown/links/podman-image-history.1 index 6b6dc17e1..6b6dc17e1 100644 --- a/docs/links/podman-image-history.1 +++ b/docs/source/markdown/links/podman-image-history.1 diff --git a/docs/links/podman-image-import.1 b/docs/source/markdown/links/podman-image-import.1 index 4564fc6c9..4564fc6c9 100644 --- a/docs/links/podman-image-import.1 +++ b/docs/source/markdown/links/podman-image-import.1 diff --git a/docs/links/podman-image-inspect.1 b/docs/source/markdown/links/podman-image-inspect.1 index 261043845..261043845 100644 --- a/docs/links/podman-image-inspect.1 +++ b/docs/source/markdown/links/podman-image-inspect.1 diff --git a/docs/links/podman-image-list.1 b/docs/source/markdown/links/podman-image-list.1 index 17d6ca880..17d6ca880 100644 --- a/docs/links/podman-image-list.1 +++ b/docs/source/markdown/links/podman-image-list.1 diff --git a/docs/links/podman-image-load.1 b/docs/source/markdown/links/podman-image-load.1 index 21b6d8e9c..21b6d8e9c 100644 --- a/docs/links/podman-image-load.1 +++ b/docs/source/markdown/links/podman-image-load.1 diff --git a/docs/links/podman-image-ls.1 b/docs/source/markdown/links/podman-image-ls.1 index 17d6ca880..17d6ca880 100644 --- a/docs/links/podman-image-ls.1 +++ b/docs/source/markdown/links/podman-image-ls.1 diff --git a/docs/links/podman-image-pull.1 b/docs/source/markdown/links/podman-image-pull.1 index d14519be3..d14519be3 100644 --- a/docs/links/podman-image-pull.1 +++ b/docs/source/markdown/links/podman-image-pull.1 diff --git a/docs/links/podman-image-push.1 b/docs/source/markdown/links/podman-image-push.1 index 51d52ad11..51d52ad11 100644 --- a/docs/links/podman-image-push.1 +++ b/docs/source/markdown/links/podman-image-push.1 diff --git a/docs/links/podman-image-rm.1 b/docs/source/markdown/links/podman-image-rm.1 index 1007ad150..1007ad150 100644 --- a/docs/links/podman-image-rm.1 +++ b/docs/source/markdown/links/podman-image-rm.1 diff --git a/docs/links/podman-image-save.1 b/docs/source/markdown/links/podman-image-save.1 index 715d7d6ee..715d7d6ee 100644 --- a/docs/links/podman-image-save.1 +++ b/docs/source/markdown/links/podman-image-save.1 diff --git a/docs/links/podman-image-tag.1 b/docs/source/markdown/links/podman-image-tag.1 index e41c50de9..e41c50de9 100644 --- a/docs/links/podman-image-tag.1 +++ b/docs/source/markdown/links/podman-image-tag.1 diff --git a/docs/links/podman-list.1 b/docs/source/markdown/links/podman-list.1 index f7f44c704..f7f44c704 100644 --- a/docs/links/podman-list.1 +++ b/docs/source/markdown/links/podman-list.1 diff --git a/docs/links/podman-ls.1 b/docs/source/markdown/links/podman-ls.1 index f7f44c704..f7f44c704 100644 --- a/docs/links/podman-ls.1 +++ b/docs/source/markdown/links/podman-ls.1 diff --git a/docs/links/podman-system-info.1 b/docs/source/markdown/links/podman-system-info.1 index 809a71b8b..809a71b8b 100644 --- a/docs/links/podman-system-info.1 +++ b/docs/source/markdown/links/podman-system-info.1 diff --git a/docs/links/podman-unmount.1 b/docs/source/markdown/links/podman-unmount.1 index 789dabbb0..789dabbb0 100644 --- a/docs/links/podman-unmount.1 +++ b/docs/source/markdown/links/podman-unmount.1 diff --git a/docs/podman-attach.1.md b/docs/source/markdown/podman-attach.1.md index cef01f0f6..cef01f0f6 100644 --- a/docs/podman-attach.1.md +++ b/docs/source/markdown/podman-attach.1.md diff --git a/docs/podman-build.1.md b/docs/source/markdown/podman-build.1.md index 567d0ead3..567d0ead3 100644 --- a/docs/podman-build.1.md +++ b/docs/source/markdown/podman-build.1.md diff --git a/docs/podman-commit.1.md b/docs/source/markdown/podman-commit.1.md index 07a885ae2..07a885ae2 100644 --- a/docs/podman-commit.1.md +++ b/docs/source/markdown/podman-commit.1.md diff --git a/docs/podman-container-checkpoint.1.md b/docs/source/markdown/podman-container-checkpoint.1.md index 034d338bb..034d338bb 100644 --- a/docs/podman-container-checkpoint.1.md +++ b/docs/source/markdown/podman-container-checkpoint.1.md diff --git a/docs/podman-container-cleanup.1.md b/docs/source/markdown/podman-container-cleanup.1.md index 69e21ce9f..69e21ce9f 100644 --- a/docs/podman-container-cleanup.1.md +++ b/docs/source/markdown/podman-container-cleanup.1.md diff --git a/docs/podman-container-exists.1.md b/docs/source/markdown/podman-container-exists.1.md index 4d988132b..4d988132b 100644 --- a/docs/podman-container-exists.1.md +++ b/docs/source/markdown/podman-container-exists.1.md diff --git a/docs/podman-container-prune.1.md b/docs/source/markdown/podman-container-prune.1.md index d8a4b7f4e..d8a4b7f4e 100644 --- a/docs/podman-container-prune.1.md +++ b/docs/source/markdown/podman-container-prune.1.md diff --git a/docs/podman-container-restore.1.md b/docs/source/markdown/podman-container-restore.1.md index 1d2cf0b3e..1d2cf0b3e 100644 --- a/docs/podman-container-restore.1.md +++ b/docs/source/markdown/podman-container-restore.1.md diff --git a/docs/podman-container-runlabel.1.md b/docs/source/markdown/podman-container-runlabel.1.md index 8511dd5cd..8511dd5cd 100644 --- a/docs/podman-container-runlabel.1.md +++ b/docs/source/markdown/podman-container-runlabel.1.md diff --git a/docs/podman-container.1.md b/docs/source/markdown/podman-container.1.md index 4ea7c7acc..4ea7c7acc 100644 --- a/docs/podman-container.1.md +++ b/docs/source/markdown/podman-container.1.md diff --git a/docs/podman-cp.1.md b/docs/source/markdown/podman-cp.1.md index 0f54b2e8b..0f54b2e8b 100644 --- a/docs/podman-cp.1.md +++ b/docs/source/markdown/podman-cp.1.md diff --git a/docs/podman-create.1.md b/docs/source/markdown/podman-create.1.md index 6617850fd..6617850fd 100644 --- a/docs/podman-create.1.md +++ b/docs/source/markdown/podman-create.1.md diff --git a/docs/podman-diff.1.md b/docs/source/markdown/podman-diff.1.md index 5b0434a07..5b0434a07 100644 --- a/docs/podman-diff.1.md +++ b/docs/source/markdown/podman-diff.1.md diff --git a/docs/podman-events.1.md b/docs/source/markdown/podman-events.1.md index bb1923574..bb1923574 100644 --- a/docs/podman-events.1.md +++ b/docs/source/markdown/podman-events.1.md diff --git a/docs/podman-exec.1.md b/docs/source/markdown/podman-exec.1.md index 4c17c056a..4c17c056a 100644 --- a/docs/podman-exec.1.md +++ b/docs/source/markdown/podman-exec.1.md diff --git a/docs/podman-export.1.md b/docs/source/markdown/podman-export.1.md index 4286d0e2f..4286d0e2f 100644 --- a/docs/podman-export.1.md +++ b/docs/source/markdown/podman-export.1.md diff --git a/docs/podman-generate-kube.1.md b/docs/source/markdown/podman-generate-kube.1.md index f4b4cd482..f4b4cd482 100644 --- a/docs/podman-generate-kube.1.md +++ b/docs/source/markdown/podman-generate-kube.1.md diff --git a/docs/podman-generate-systemd.1.md b/docs/source/markdown/podman-generate-systemd.1.md index b81e68a46..b81e68a46 100644 --- a/docs/podman-generate-systemd.1.md +++ b/docs/source/markdown/podman-generate-systemd.1.md diff --git a/docs/podman-generate.1.md b/docs/source/markdown/podman-generate.1.md index 50050f2c1..50050f2c1 100644 --- a/docs/podman-generate.1.md +++ b/docs/source/markdown/podman-generate.1.md diff --git a/docs/podman-healthcheck-run.1.md b/docs/source/markdown/podman-healthcheck-run.1.md index 21f2d9b20..21f2d9b20 100644 --- a/docs/podman-healthcheck-run.1.md +++ b/docs/source/markdown/podman-healthcheck-run.1.md diff --git a/docs/podman-healthcheck.1.md b/docs/source/markdown/podman-healthcheck.1.md index 91c3e4345..91c3e4345 100644 --- a/docs/podman-healthcheck.1.md +++ b/docs/source/markdown/podman-healthcheck.1.md diff --git a/docs/podman-history.1.md b/docs/source/markdown/podman-history.1.md index a67cb0286..a67cb0286 100644 --- a/docs/podman-history.1.md +++ b/docs/source/markdown/podman-history.1.md diff --git a/docs/podman-image-exists.1.md b/docs/source/markdown/podman-image-exists.1.md index f6a89e2aa..f6a89e2aa 100644 --- a/docs/podman-image-exists.1.md +++ b/docs/source/markdown/podman-image-exists.1.md diff --git a/docs/podman-image-prune.1.md b/docs/source/markdown/podman-image-prune.1.md index b844a9f63..b844a9f63 100644 --- a/docs/podman-image-prune.1.md +++ b/docs/source/markdown/podman-image-prune.1.md diff --git a/docs/podman-image-sign.1.md b/docs/source/markdown/podman-image-sign.1.md index 62845e715..62845e715 100644 --- a/docs/podman-image-sign.1.md +++ b/docs/source/markdown/podman-image-sign.1.md diff --git a/docs/podman-image-tree.1.md b/docs/source/markdown/podman-image-tree.1.md index c4624e05c..c4624e05c 100644 --- a/docs/podman-image-tree.1.md +++ b/docs/source/markdown/podman-image-tree.1.md diff --git a/docs/podman-image-trust.1.md b/docs/source/markdown/podman-image-trust.1.md index 3fe4f7f52..3fe4f7f52 100644 --- a/docs/podman-image-trust.1.md +++ b/docs/source/markdown/podman-image-trust.1.md diff --git a/docs/podman-image.1.md b/docs/source/markdown/podman-image.1.md index 339a531dd..339a531dd 100644 --- a/docs/podman-image.1.md +++ b/docs/source/markdown/podman-image.1.md diff --git a/docs/podman-images.1.md b/docs/source/markdown/podman-images.1.md index 3ac07fc43..3ac07fc43 100644 --- a/docs/podman-images.1.md +++ b/docs/source/markdown/podman-images.1.md diff --git a/docs/podman-import.1.md b/docs/source/markdown/podman-import.1.md index 946b680dd..946b680dd 100644 --- a/docs/podman-import.1.md +++ b/docs/source/markdown/podman-import.1.md diff --git a/docs/podman-info.1.md b/docs/source/markdown/podman-info.1.md index 9721755ef..9721755ef 100644 --- a/docs/podman-info.1.md +++ b/docs/source/markdown/podman-info.1.md diff --git a/docs/podman-init.1.md b/docs/source/markdown/podman-init.1.md index 3b49cfb99..3b49cfb99 100644 --- a/docs/podman-init.1.md +++ b/docs/source/markdown/podman-init.1.md diff --git a/docs/podman-inspect.1.md b/docs/source/markdown/podman-inspect.1.md index f1630c713..f1630c713 100644 --- a/docs/podman-inspect.1.md +++ b/docs/source/markdown/podman-inspect.1.md diff --git a/docs/podman-kill.1.md b/docs/source/markdown/podman-kill.1.md index 617d25b85..617d25b85 100644 --- a/docs/podman-kill.1.md +++ b/docs/source/markdown/podman-kill.1.md diff --git a/docs/podman-load.1.md b/docs/source/markdown/podman-load.1.md index deb4fb5ec..deb4fb5ec 100644 --- a/docs/podman-load.1.md +++ b/docs/source/markdown/podman-load.1.md diff --git a/docs/podman-login.1.md b/docs/source/markdown/podman-login.1.md index 9d368e9f2..9d368e9f2 100644 --- a/docs/podman-login.1.md +++ b/docs/source/markdown/podman-login.1.md diff --git a/docs/podman-logout.1.md b/docs/source/markdown/podman-logout.1.md index 01dc52ecd..01dc52ecd 100644 --- a/docs/podman-logout.1.md +++ b/docs/source/markdown/podman-logout.1.md diff --git a/docs/podman-logs.1.md b/docs/source/markdown/podman-logs.1.md index 405f180d9..5507ba13a 100644 --- a/docs/podman-logs.1.md +++ b/docs/source/markdown/podman-logs.1.md @@ -39,7 +39,7 @@ and 2006-01-02. **--tail**=*LINES* -Output the specified number of LINES at the end of the logs. LINES must be a positive integer. Defaults to 0, +Output the specified number of LINES at the end of the logs. LINES must be an integer. Defaults to -1, which prints all lines **--timestamps**, **-t** diff --git a/docs/podman-mount.1.md b/docs/source/markdown/podman-mount.1.md index 8f4deeca6..8f4deeca6 100644 --- a/docs/podman-mount.1.md +++ b/docs/source/markdown/podman-mount.1.md diff --git a/docs/podman-network-create.1.md b/docs/source/markdown/podman-network-create.1.md index c281d50d9..c281d50d9 100644 --- a/docs/podman-network-create.1.md +++ b/docs/source/markdown/podman-network-create.1.md diff --git a/docs/podman-network-inspect.1.md b/docs/source/markdown/podman-network-inspect.1.md index dfa7e4b0c..dfa7e4b0c 100644 --- a/docs/podman-network-inspect.1.md +++ b/docs/source/markdown/podman-network-inspect.1.md diff --git a/docs/podman-network-ls.1.md b/docs/source/markdown/podman-network-ls.1.md index 46e424593..46e424593 100644 --- a/docs/podman-network-ls.1.md +++ b/docs/source/markdown/podman-network-ls.1.md diff --git a/docs/podman-network-rm.1.md b/docs/source/markdown/podman-network-rm.1.md index c71f0d8fd..c71f0d8fd 100644 --- a/docs/podman-network-rm.1.md +++ b/docs/source/markdown/podman-network-rm.1.md diff --git a/docs/podman-network.1.md b/docs/source/markdown/podman-network.1.md index f05b2b78f..f05b2b78f 100644 --- a/docs/podman-network.1.md +++ b/docs/source/markdown/podman-network.1.md diff --git a/docs/podman-pause.1.md b/docs/source/markdown/podman-pause.1.md index dfd4da416..dfd4da416 100644 --- a/docs/podman-pause.1.md +++ b/docs/source/markdown/podman-pause.1.md diff --git a/docs/podman-play-kube.1.md b/docs/source/markdown/podman-play-kube.1.md index 2ac860a32..2ac860a32 100644 --- a/docs/podman-play-kube.1.md +++ b/docs/source/markdown/podman-play-kube.1.md diff --git a/docs/podman-play.1.md b/docs/source/markdown/podman-play.1.md index 364baad60..364baad60 100644 --- a/docs/podman-play.1.md +++ b/docs/source/markdown/podman-play.1.md diff --git a/docs/podman-pod-create.1.md b/docs/source/markdown/podman-pod-create.1.md index cd1de6401..cd1de6401 100644 --- a/docs/podman-pod-create.1.md +++ b/docs/source/markdown/podman-pod-create.1.md diff --git a/docs/podman-pod-exists.1.md b/docs/source/markdown/podman-pod-exists.1.md index cf2852934..cf2852934 100644 --- a/docs/podman-pod-exists.1.md +++ b/docs/source/markdown/podman-pod-exists.1.md diff --git a/docs/podman-pod-inspect.1.md b/docs/source/markdown/podman-pod-inspect.1.md index 831d28259..831d28259 100644 --- a/docs/podman-pod-inspect.1.md +++ b/docs/source/markdown/podman-pod-inspect.1.md diff --git a/docs/podman-pod-kill.1.md b/docs/source/markdown/podman-pod-kill.1.md index 596e15cea..596e15cea 100644 --- a/docs/podman-pod-kill.1.md +++ b/docs/source/markdown/podman-pod-kill.1.md diff --git a/docs/podman-pod-pause.1.md b/docs/source/markdown/podman-pod-pause.1.md index 9533ed4a1..9533ed4a1 100644 --- a/docs/podman-pod-pause.1.md +++ b/docs/source/markdown/podman-pod-pause.1.md diff --git a/docs/podman-pod-prune.1.md b/docs/source/markdown/podman-pod-prune.1.md index f79961b2f..f79961b2f 100644 --- a/docs/podman-pod-prune.1.md +++ b/docs/source/markdown/podman-pod-prune.1.md diff --git a/docs/podman-pod-ps.1.md b/docs/source/markdown/podman-pod-ps.1.md index 65a7072ab..65a7072ab 100644 --- a/docs/podman-pod-ps.1.md +++ b/docs/source/markdown/podman-pod-ps.1.md diff --git a/docs/podman-pod-restart.1.md b/docs/source/markdown/podman-pod-restart.1.md index 57f479102..57f479102 100644 --- a/docs/podman-pod-restart.1.md +++ b/docs/source/markdown/podman-pod-restart.1.md diff --git a/docs/podman-pod-rm.1.md b/docs/source/markdown/podman-pod-rm.1.md index 6659534b4..6659534b4 100644 --- a/docs/podman-pod-rm.1.md +++ b/docs/source/markdown/podman-pod-rm.1.md diff --git a/docs/podman-pod-start.1.md b/docs/source/markdown/podman-pod-start.1.md index 29960d6aa..29960d6aa 100644 --- a/docs/podman-pod-start.1.md +++ b/docs/source/markdown/podman-pod-start.1.md diff --git a/docs/podman-pod-stats.1.md b/docs/source/markdown/podman-pod-stats.1.md index 962edbda0..962edbda0 100644 --- a/docs/podman-pod-stats.1.md +++ b/docs/source/markdown/podman-pod-stats.1.md diff --git a/docs/podman-pod-stop.1.md b/docs/source/markdown/podman-pod-stop.1.md index b3ce47d72..b3ce47d72 100644 --- a/docs/podman-pod-stop.1.md +++ b/docs/source/markdown/podman-pod-stop.1.md diff --git a/docs/podman-pod-top.1.md b/docs/source/markdown/podman-pod-top.1.md index 48f10055a..48f10055a 100644 --- a/docs/podman-pod-top.1.md +++ b/docs/source/markdown/podman-pod-top.1.md diff --git a/docs/podman-pod-unpause.1.md b/docs/source/markdown/podman-pod-unpause.1.md index e0a88c2e3..e0a88c2e3 100644 --- a/docs/podman-pod-unpause.1.md +++ b/docs/source/markdown/podman-pod-unpause.1.md diff --git a/docs/podman-pod.1.md b/docs/source/markdown/podman-pod.1.md index b3d002a06..b3d002a06 100644 --- a/docs/podman-pod.1.md +++ b/docs/source/markdown/podman-pod.1.md diff --git a/docs/podman-port.1.md b/docs/source/markdown/podman-port.1.md index c9833f447..c9833f447 100644 --- a/docs/podman-port.1.md +++ b/docs/source/markdown/podman-port.1.md diff --git a/docs/podman-ps.1.md b/docs/source/markdown/podman-ps.1.md index 298de0b2b..298de0b2b 100644 --- a/docs/podman-ps.1.md +++ b/docs/source/markdown/podman-ps.1.md diff --git a/docs/podman-pull.1.md b/docs/source/markdown/podman-pull.1.md index de9688f5e..de9688f5e 100644 --- a/docs/podman-pull.1.md +++ b/docs/source/markdown/podman-pull.1.md diff --git a/docs/podman-push.1.md b/docs/source/markdown/podman-push.1.md index 3f0350bcd..3f0350bcd 100644 --- a/docs/podman-push.1.md +++ b/docs/source/markdown/podman-push.1.md diff --git a/docs/podman-remote.1.md b/docs/source/markdown/podman-remote.1.md index 04010abaf..04010abaf 100644 --- a/docs/podman-remote.1.md +++ b/docs/source/markdown/podman-remote.1.md diff --git a/docs/podman-restart.1.md b/docs/source/markdown/podman-restart.1.md index 08fa29244..08fa29244 100644 --- a/docs/podman-restart.1.md +++ b/docs/source/markdown/podman-restart.1.md diff --git a/docs/podman-rm.1.md b/docs/source/markdown/podman-rm.1.md index 207d9d61d..207d9d61d 100644 --- a/docs/podman-rm.1.md +++ b/docs/source/markdown/podman-rm.1.md diff --git a/docs/podman-rmi.1.md b/docs/source/markdown/podman-rmi.1.md index d911ee6cb..d911ee6cb 100644 --- a/docs/podman-rmi.1.md +++ b/docs/source/markdown/podman-rmi.1.md diff --git a/docs/podman-run.1.md b/docs/source/markdown/podman-run.1.md index d6d8f4c1e..d6d8f4c1e 100644 --- a/docs/podman-run.1.md +++ b/docs/source/markdown/podman-run.1.md diff --git a/docs/podman-save.1.md b/docs/source/markdown/podman-save.1.md index b2b0995d3..b2b0995d3 100644 --- a/docs/podman-save.1.md +++ b/docs/source/markdown/podman-save.1.md diff --git a/docs/podman-search.1.md b/docs/source/markdown/podman-search.1.md index 31de6f839..31de6f839 100644 --- a/docs/podman-search.1.md +++ b/docs/source/markdown/podman-search.1.md diff --git a/docs/podman-start.1.md b/docs/source/markdown/podman-start.1.md index 4c81d17bd..4c81d17bd 100644 --- a/docs/podman-start.1.md +++ b/docs/source/markdown/podman-start.1.md diff --git a/docs/podman-stats.1.md b/docs/source/markdown/podman-stats.1.md index 741873c3f..741873c3f 100644 --- a/docs/podman-stats.1.md +++ b/docs/source/markdown/podman-stats.1.md diff --git a/docs/podman-stop.1.md b/docs/source/markdown/podman-stop.1.md index b5ea670b0..b5ea670b0 100644 --- a/docs/podman-stop.1.md +++ b/docs/source/markdown/podman-stop.1.md diff --git a/docs/podman-system-df.1.md b/docs/source/markdown/podman-system-df.1.md index d0b1755ee..d0b1755ee 100644 --- a/docs/podman-system-df.1.md +++ b/docs/source/markdown/podman-system-df.1.md diff --git a/docs/podman-system-migrate.1.md b/docs/source/markdown/podman-system-migrate.1.md index d5e3bcb95..d5e3bcb95 100644 --- a/docs/podman-system-migrate.1.md +++ b/docs/source/markdown/podman-system-migrate.1.md diff --git a/docs/podman-system-prune.1.md b/docs/source/markdown/podman-system-prune.1.md index e6297dc0b..e6297dc0b 100644 --- a/docs/podman-system-prune.1.md +++ b/docs/source/markdown/podman-system-prune.1.md diff --git a/docs/podman-system-renumber.1.md b/docs/source/markdown/podman-system-renumber.1.md index 071eefe29..071eefe29 100644 --- a/docs/podman-system-renumber.1.md +++ b/docs/source/markdown/podman-system-renumber.1.md diff --git a/docs/podman-system.1.md b/docs/source/markdown/podman-system.1.md index bbd541066..bbd541066 100644 --- a/docs/podman-system.1.md +++ b/docs/source/markdown/podman-system.1.md diff --git a/docs/podman-tag.1.md b/docs/source/markdown/podman-tag.1.md index 291d95228..291d95228 100644 --- a/docs/podman-tag.1.md +++ b/docs/source/markdown/podman-tag.1.md diff --git a/docs/podman-top.1.md b/docs/source/markdown/podman-top.1.md index 1410aa651..1410aa651 100644 --- a/docs/podman-top.1.md +++ b/docs/source/markdown/podman-top.1.md diff --git a/docs/podman-umount.1.md b/docs/source/markdown/podman-umount.1.md index 100c47b32..100c47b32 100644 --- a/docs/podman-umount.1.md +++ b/docs/source/markdown/podman-umount.1.md diff --git a/docs/podman-unpause.1.md b/docs/source/markdown/podman-unpause.1.md index f5538d6d5..f5538d6d5 100644 --- a/docs/podman-unpause.1.md +++ b/docs/source/markdown/podman-unpause.1.md diff --git a/docs/podman-unshare.1.md b/docs/source/markdown/podman-unshare.1.md index 9052b97ab..9052b97ab 100644 --- a/docs/podman-unshare.1.md +++ b/docs/source/markdown/podman-unshare.1.md diff --git a/docs/podman-varlink.1.md b/docs/source/markdown/podman-varlink.1.md index 0d2ab1668..0d2ab1668 100644 --- a/docs/podman-varlink.1.md +++ b/docs/source/markdown/podman-varlink.1.md diff --git a/docs/podman-version.1.md b/docs/source/markdown/podman-version.1.md index 4499f6338..4499f6338 100644 --- a/docs/podman-version.1.md +++ b/docs/source/markdown/podman-version.1.md diff --git a/docs/podman-volume-create.1.md b/docs/source/markdown/podman-volume-create.1.md index b354f396f..b354f396f 100644 --- a/docs/podman-volume-create.1.md +++ b/docs/source/markdown/podman-volume-create.1.md diff --git a/docs/podman-volume-inspect.1.md b/docs/source/markdown/podman-volume-inspect.1.md index ac5b6c977..ac5b6c977 100644 --- a/docs/podman-volume-inspect.1.md +++ b/docs/source/markdown/podman-volume-inspect.1.md diff --git a/docs/podman-volume-ls.1.md b/docs/source/markdown/podman-volume-ls.1.md index d431c7c6e..d431c7c6e 100644 --- a/docs/podman-volume-ls.1.md +++ b/docs/source/markdown/podman-volume-ls.1.md diff --git a/docs/podman-volume-prune.1.md b/docs/source/markdown/podman-volume-prune.1.md index 25ea701a3..25ea701a3 100644 --- a/docs/podman-volume-prune.1.md +++ b/docs/source/markdown/podman-volume-prune.1.md diff --git a/docs/podman-volume-rm.1.md b/docs/source/markdown/podman-volume-rm.1.md index 9a2fe8c99..9a2fe8c99 100644 --- a/docs/podman-volume-rm.1.md +++ b/docs/source/markdown/podman-volume-rm.1.md diff --git a/docs/podman-volume.1.md b/docs/source/markdown/podman-volume.1.md index 288e57b82..288e57b82 100644 --- a/docs/podman-volume.1.md +++ b/docs/source/markdown/podman-volume.1.md diff --git a/docs/podman-wait.1.md b/docs/source/markdown/podman-wait.1.md index ce1c70a5f..ce1c70a5f 100644 --- a/docs/podman-wait.1.md +++ b/docs/source/markdown/podman-wait.1.md diff --git a/docs/podman.1.md b/docs/source/markdown/podman.1.md index f6fa1a457..f6fa1a457 100644 --- a/docs/podman.1.md +++ b/docs/source/markdown/podman.1.md diff --git a/docs/source/network.rst b/docs/source/network.rst new file mode 100644 index 000000000..c1c53bc34 --- /dev/null +++ b/docs/source/network.rst @@ -0,0 +1,10 @@ +Network +===== + +:doc:`create <markdown/podman-network-create.1>` network create + +:doc:`inspect <markdown/podman-network-inspect.1>` network inspect + +:doc:`ls <markdown/podman-network-ls.1>` network list + +:doc:`rm <markdown/podman-network-rm.1>` network rm
\ No newline at end of file diff --git a/docs/source/play.rst b/docs/source/play.rst new file mode 100644 index 000000000..8f00d2f45 --- /dev/null +++ b/docs/source/play.rst @@ -0,0 +1,4 @@ +Play +==== + +:doc:`kube <markdown/podman-play-kube.1>` Play a pod based on Kubernetes YAML diff --git a/docs/source/pod.rst b/docs/source/pod.rst new file mode 100644 index 000000000..391686ce5 --- /dev/null +++ b/docs/source/pod.rst @@ -0,0 +1,30 @@ +Pod +=== + +:doc:`create <markdown/podman-pod-create.1>` Create a new empty pod + +:doc:`exists <markdown/podman-pod-exists.1>` Check if a pod exists in local storage + +:doc:`inspect <markdown/podman-pod-inspect.1>` Displays a pod configuration + +:doc:`kill <markdown/podman-pod-kill.1>` Send the specified signal or SIGKILL to containers in pod + +:doc:`pause <markdown/podman-pause.1>` Pause one or more pods + +:doc:`prune <markdown/podman-pod-prune.1>` Remove all stopped pods + +:doc:`ps <markdown/podman-pod-ps.1>` List pods + +:doc:`restart <markdown/podman-pod-restart.1>` Restart one or more pods + +:doc:`rm <markdown/podman-pod-rm.1>` Remove one or more pods + +:doc:`start <markdown/podman-pod-start.1>` Start one or more pods + +:doc:`stats <markdown/podman-pod-stats.1>` Display a live stream of resource usage statistics for the containers in one or more pods + +:doc:`stop <markdown/podman-pod-stop.1>` Stop one or more pods + +:doc:`top <markdown/podman-pod-top.1>` Display the running processes of containers in a pod + +:doc:`unpause <markdown/podman-pod-unpause.1>` Unpause one or more pods diff --git a/docs/source/system.rst b/docs/source/system.rst new file mode 100644 index 000000000..2f2b7ea8f --- /dev/null +++ b/docs/source/system.rst @@ -0,0 +1,12 @@ +System +====== + +:doc:`df <markdown/podman-system-df.1>` Show podman disk usage + +:doc:`info <markdown/podman-info.1>` Display podman system information + +:doc:`migrate <markdown/podman-system-migrate.1>` Migrate containers + +:doc:`prune <markdown/podman-system-prune.1>` Remove unused data + +:doc:`renumber <markdown/podman-system-renumber.1>` Migrate lock numbers diff --git a/docs/source/volume.rst b/docs/source/volume.rst new file mode 100644 index 000000000..43fe87054 --- /dev/null +++ b/docs/source/volume.rst @@ -0,0 +1,11 @@ +Volume +====== +:doc:`create <markdown/podman-volume-create.1>` Create a new volume + +:doc:`inspect <markdown/podman-volume-inspect.1>` Display detailed information on one or more volumes + +:doc:`ls <markdown/podman-volume-ls.1>` List volumes + +:doc:`prune <markdown/podman-volume-prune.1>` Remove all unused volumes + +:doc:`rm <markdown/podman-volume-rm.1>` Remove one or more volumes
\ No newline at end of file @@ -40,7 +40,7 @@ require ( github.com/json-iterator/go v1.1.7 github.com/mattn/go-isatty v0.0.8 // indirect github.com/mrunalp/fileutils v0.0.0-20171103030105-7d4729fb3618 - github.com/onsi/ginkgo v1.10.1 + github.com/onsi/ginkgo v1.10.3 github.com/onsi/gomega v1.7.0 github.com/opencontainers/go-digest v1.0.0-rc1 github.com/opencontainers/image-spec v1.0.2-0.20190823105129-775207bd45b6 @@ -55,12 +55,8 @@ github.com/containernetworking/cni v0.7.1 h1:fE3r16wpSEyaqY4Z4oFrLMmIGfBYIKpPrHK github.com/containernetworking/cni v0.7.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= github.com/containernetworking/plugins v0.8.2 h1:5lnwfsAYO+V7yXhysJKy3E1A2Gy9oVut031zfdOzI9w= github.com/containernetworking/plugins v0.8.2/go.mod h1:TxALKWZpWL79BC3GOYKJzzXr7U8R23PdhwaLp6F3adc= -github.com/containers/buildah v1.11.3 h1:L5vFj+ao58IGq3G30jN94vRQrIgMU/uTOEKduDr3Nyg= -github.com/containers/buildah v1.11.3/go.mod h1:jqZmSU/PhFwTHHlOotnw4bbs1JbkRQLh8dut5DF4Qek= github.com/containers/buildah v1.11.4-0.20191028173731-21b4778b359e h1:iDavHEx5Yr7o+0l6495Ya6N0YEPplIUZuWC2e14baDM= github.com/containers/buildah v1.11.4-0.20191028173731-21b4778b359e/go.mod h1:Igrk75FAxLnzDaHUbtpWB8pwL+Bv+cnakWMvqAXW2v8= -github.com/containers/image/v4 v4.0.1 h1:idNGHChj0Pyv3vLrxul2oSVMZLeFqpoq3CjLeVgapSQ= -github.com/containers/image/v4 v4.0.1/go.mod h1:0ASJH1YgJiX/eqFZObqepgsvIA4XjCgpyfwn9pDGafA= github.com/containers/image/v5 v5.0.0 h1:arnXgbt1ucsC/ndtSpiQY87rA0UjhF+/xQnPzqdBDn4= github.com/containers/image/v5 v5.0.0/go.mod h1:MgiLzCfIeo8lrHi+4Lb8HP+rh513sm0Mlk6RrhjFOLY= github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b h1:Q8ePgVfHDplZ7U33NwHZkrVELsZP5fYj9pM5WBZB2GE= @@ -102,8 +98,6 @@ github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BU github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v0.0.0-20171019062838-86f080cff091/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v0.0.0-20180522102801-da99009bbb11/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v1.4.2-0.20190710153559-aa8249ae1b8b h1:+Ga+YpCDpcY1fln6GI0fiiirpqHGcob5/Vk3oKNuGdU= -github.com/docker/docker v1.4.2-0.20190710153559-aa8249ae1b8b/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v1.4.2-0.20190927142053-ada3c14355ce h1:H3csZuxZESJeeEiOxq4YXPNmLFbjl7u2qVBrAAGX/sA= github.com/docker/docker v1.4.2-0.20190927142053-ada3c14355ce/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker-credential-helpers v0.6.0/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= @@ -139,8 +133,6 @@ github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8 github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsouza/go-dockerclient v1.4.4 h1:Sd5nD4wdAgiPxvrbYUzT2ZZNmPk3z+GGnZ+frvw8z04= -github.com/fsouza/go-dockerclient v1.4.4/go.mod h1:PrwszSL5fbmsESocROrOGq/NULMXRw+bajY0ltzD6MA= github.com/fsouza/go-dockerclient v1.5.0 h1:7OtayOe5HnoG+KWMHgyyPymwaodnB2IDYuVfseKyxbA= github.com/fsouza/go-dockerclient v1.5.0/go.mod h1:AqZZK/zFO3phxYxlTsAaeAMSdQ9mgHuhy+bjN034Qds= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -210,8 +202,6 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/ijc/Gotty v0.0.0-20170406111628-a8b993ba6abd h1:anPrsicrIi2ColgWTVPk+TrN42hJIWlfPHSBP9S0ZkM= -github.com/ijc/Gotty v0.0.0-20170406111628-a8b993ba6abd/go.mod h1:3LVOLeyx9XVvwPgrt2be44XgSqndprz1G18rSk8KD84= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28= github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= @@ -293,6 +283,8 @@ github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.1 h1:q/mM8GF/n0shIN8SaAZ0V+jnLPzen6WIVZdiwrRlMlo= github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.3 h1:OoxbjfXVZyod1fmWYhI7SEyaD8B00ynP3T+D5GiyHOY= +github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20190113212917-5533ce8a0da3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -322,8 +314,6 @@ github.com/opencontainers/selinux v1.3.0 h1:xsI95WzPZu5exzA6JzkLSfdr/DilzOhCJOqG github.com/opencontainers/selinux v1.3.0/go.mod h1:+BLncwf63G4dgOzykXAxcmnFlUaOlkDdmw/CqsW6pjs= github.com/openshift/api v3.9.1-0.20190810003144-27fb16909b15+incompatible h1:s55wx8JIG/CKnewev892HifTBrtKzMdvgB3rm4rxC2s= github.com/openshift/api v3.9.1-0.20190810003144-27fb16909b15+incompatible/go.mod h1:dh9o4Fs58gpFXGSYfnVxGR9PnV53I8TW84pQaJDdGiY= -github.com/openshift/imagebuilder v1.1.0 h1:oT704SkwMEzmIMU/+Uv1Wmvt+p10q3v2WuYMeFI18c4= -github.com/openshift/imagebuilder v1.1.0/go.mod h1:9aJRczxCH0mvT6XQ+5STAQaPWz7OsWcU5/mRkt8IWeo= github.com/openshift/imagebuilder v1.1.1 h1:KAUR31p8UBJdfVO42azWgb+LeMAed2zaKQ19e0C0X2I= github.com/openshift/imagebuilder v1.1.1/go.mod h1:9aJRczxCH0mvT6XQ+5STAQaPWz7OsWcU5/mRkt8IWeo= github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU= @@ -444,8 +434,6 @@ golang.org/x/crypto v0.0.0-20181025213731-e84da0312774/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad h1:5E5raQxcv+6CZ11RrBYQe5WRbUIWpScjh0kvHZkZIrQ= golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -495,7 +483,6 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb h1:fgwFCsaw9buMuxNd6+DQfAuSFqbNiQZpcgJQAgJsK6k= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190710143415-6ec70d6a5542/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190902133755-9109b7679e13 h1:tdsQdquKbTNMsSZLqnLELJGzCANp9oXhu6zFBW6ODx4= golang.org/x/sys v0.0.0-20190902133755-9109b7679e13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/hack/man-page-checker b/hack/man-page-checker index 30d0b2113..99d280539 100755 --- a/hack/man-page-checker +++ b/hack/man-page-checker @@ -18,7 +18,7 @@ die() { exit 1 } -cd $(dirname $0)/../docs || die "Please run me from top-level libpod dir" +cd $(dirname $0)/../docs/source/markdown || die "Please run me from top-level libpod dir" rc=0 diff --git a/hack/podman-commands.sh b/hack/podman-commands.sh index 7530e20d0..32f94fc7b 100755 --- a/hack/podman-commands.sh +++ b/hack/podman-commands.sh @@ -34,7 +34,7 @@ function podman_man() { # This md file has a table of the form: # | [podman-cmd(1)\[(podman-cmd.1.md) | Description ... | # For all such, print the 'cmd' portion (the one in brackets). - sed -ne 's/^|\s\+\[podman-\([a-z]\+\)(1.*/\1/p' <docs/$1.1.md + sed -ne 's/^|\s\+\[podman-\([a-z]\+\)(1.*/\1/p' <docs/source/markdown/$1.1.md # Special case: there is no podman-help man page, nor need for such. echo "help" @@ -48,7 +48,7 @@ function podman_man() { # | cmd | [podman-cmd(1)](podman-cmd.1.md) | Description ... | # For all such we find, with 'podman- in the second column, print the # first column (with whitespace trimmed) - awk -F\| '$3 ~ /podman-/ { gsub(" ","",$2); print $2 }' < docs/$1.1.md + awk -F\| '$3 ~ /podman-/ { gsub(" ","",$2); print $2 }' < docs/source/markdown/$1.1.md fi } @@ -93,7 +93,7 @@ if [ $rc -ne 0 ]; then * podman man pages. * * The 'checking:' header indicates the specific command (and possibly -* subcommand) being tested, e.g. podman --help vs docs/podman.1.md. +* subcommand) being tested, e.g. podman --help vs docs/source/podman.1.md. * * A '-' indicates a subcommand present in 'podman --help' but not the * corresponding man page. diff --git a/libpod/boltdb_state.go b/libpod/boltdb_state.go index 0bb1df7b8..608a279c3 100644 --- a/libpod/boltdb_state.go +++ b/libpod/boltdb_state.go @@ -6,6 +6,7 @@ import ( "strings" "sync" + "github.com/containers/libpod/libpod/config" "github.com/containers/libpod/libpod/define" bolt "github.com/etcd-io/bbolt" jsoniter "github.com/json-iterator/go" @@ -291,12 +292,12 @@ func (s *BoltState) Refresh() error { // GetDBConfig retrieves runtime configuration fields that were created when // the database was first initialized -func (s *BoltState) GetDBConfig() (*DBConfig, error) { +func (s *BoltState) GetDBConfig() (*config.DBConfig, error) { if !s.valid { return nil, define.ErrDBClosed } - cfg := new(DBConfig) + cfg := new(config.DBConfig) db, err := s.getDBCon() if err != nil { diff --git a/libpod/common_test.go b/libpod/common_test.go index 93ca7bc71..83b162c8a 100644 --- a/libpod/common_test.go +++ b/libpod/common_test.go @@ -7,6 +7,7 @@ import ( "testing" "time" + "github.com/containers/libpod/libpod/config" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/libpod/lock" "github.com/cri-o/ocicni/pkg/ocicni" @@ -74,7 +75,7 @@ func getTestContainer(id, name string, manager lock.Manager) (*Container, error) }, }, runtime: &Runtime{ - config: &RuntimeConfig{ + config: &config.Config{ VolumePath: "/does/not/exist/tmp/volumes", }, }, diff --git a/libpod/config/config.go b/libpod/config/config.go new file mode 100644 index 000000000..5b4b57f3a --- /dev/null +++ b/libpod/config/config.go @@ -0,0 +1,549 @@ +package config + +import ( + "bytes" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "regexp" + "strconv" + "strings" + + "github.com/BurntSushi/toml" + "github.com/containers/libpod/libpod/define" + "github.com/containers/libpod/pkg/rootless" + "github.com/containers/libpod/pkg/util" + "github.com/containers/storage" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" +) + +const ( + // _defaultTransport is a prefix that we apply to an image name to check + // docker hub first for the image. + _defaultTransport = "docker://" + + // _rootlessConfigPath is the path to the rootless libpod.conf in $HOME. + _rootlessConfigPath = ".config/containers/libpod.conf" + + // _conmonMinMajorVersion is the major version required for conmon. + _conmonMinMajorVersion = 2 + + // _conmonMinMinorVersion is the minor version required for conmon. + _conmonMinMinorVersion = 0 + + // _conmonMinPatchVersion is the sub-minor version required for conmon. + _conmonMinPatchVersion = 1 + + // _conmonVersionFormatErr is used when the expected versio-format of conmon + // has changed. + _conmonVersionFormatErr = "conmon version changed format" + + // InstallPrefix is the prefix where podman will be installed. + // It can be overridden at build time. + _installPrefix = "/usr" + + // EtcDir is the sysconfdir where podman should look for system config files. + // It can be overridden at build time. + _etcDir = "/etc" + + // SeccompDefaultPath defines the default seccomp path. + SeccompDefaultPath = _installPrefix + "/share/containers/seccomp.json" + + // SeccompOverridePath if this exists it overrides the default seccomp path. + SeccompOverridePath = _etcDir + "/crio/seccomp.json" + + // _rootConfigPath is the path to the libpod configuration file + // This file is loaded to replace the builtin default config before + // runtime options (e.g. WithStorageConfig) are applied. + // If it is not present, the builtin default config is used instead + // This path can be overridden when the runtime is created by using + // NewRuntimeFromConfig() instead of NewRuntime(). + _rootConfigPath = _installPrefix + "/share/containers/libpod.conf" + + // _rootOverrideConfigPath is the path to an override for the default libpod + // configuration file. If OverrideConfigPath exists, it will be used in + // place of the configuration file pointed to by ConfigPath. + _rootOverrideConfigPath = _etcDir + "/containers/libpod.conf" +) + +// SetOptions contains a subset of options in a Config. It's used to indicate if +// a given option has either been set by the user or by a parsed libpod +// configuration file. If not, the corresponding option might be overwritten by +// values from the database. This behavior guarantess backwards compat with +// older version of libpod and Podman. +type SetOptions struct { + // StorageConfigRunRootSet indicates if the RunRoot has been explicitly set + // by the config or by the user. It's required to guarantee backwards + // compatibility with older versions of libpod for which we must query the + // database configuration. Not included in the on-disk config. + StorageConfigRunRootSet bool `toml:"-"` + + // StorageConfigGraphRootSet indicates if the RunRoot has been explicitly + // set by the config or by the user. It's required to guarantee backwards + // compatibility with older versions of libpod for which we must query the + // database configuration. Not included in the on-disk config. + StorageConfigGraphRootSet bool `toml:"-"` + + // StorageConfigGraphDriverNameSet indicates if the GraphDriverName has been + // explicitly set by the config or by the user. It's required to guarantee + // backwards compatibility with older versions of libpod for which we must + // query the database configuration. Not included in the on-disk config. + StorageConfigGraphDriverNameSet bool `toml:"-"` + + // VolumePathSet indicates if the VolumePath has been explicitly set by the + // config or by the user. It's required to guarantee backwards compatibility + // with older versions of libpod for which we must query the database + // configuration. Not included in the on-disk config. + VolumePathSet bool `toml:"-"` + + // StaticDirSet indicates if the StaticDir has been explicitly set by the + // config or by the user. It's required to guarantee backwards compatibility + // with older versions of libpod for which we must query the database + // configuration. Not included in the on-disk config. + StaticDirSet bool `toml:"-"` + + // TmpDirSet indicates if the TmpDir has been explicitly set by the config + // or by the user. It's required to guarantee backwards compatibility with + // older versions of libpod for which we must query the database + // configuration. Not included in the on-disk config. + TmpDirSet bool `toml:"-"` +} + +// Config contains configuration options used to set up a libpod runtime +type Config struct { + // NOTE: when changing this struct, make sure to update (*Config).Merge(). + + // SetOptions contains a subset of config options. It's used to indicate if + // a given option has either been set by the user or by a parsed libpod + // configuration file. If not, the corresponding option might be + // overwritten by values from the database. This behavior guarantess + // backwards compat with older version of libpod and Podman. + SetOptions + + // StateType is the type of the backing state store. Avoid using multiple + // values for this with the same containers/storage configuration on the + // same system. Different state types do not interact, and each will see a + // separate set of containers, which may cause conflicts in + // containers/storage. As such this is not exposed via the config file. + StateType define.RuntimeStateStore `toml:"-"` + + // StorageConfig is the configuration used by containers/storage Not + // included in the on-disk config, use the dedicated containers/storage + // configuration file instead. + StorageConfig storage.StoreOptions `toml:"-"` + + // VolumePath is the default location that named volumes will be created + // under. This convention is followed by the default volume driver, but + // may not be by other drivers. + VolumePath string `toml:"volume_path"` + + // ImageDefaultTransport is the default transport method used to fetch + // images. + ImageDefaultTransport string `toml:"image_default_transport"` + + // SignaturePolicyPath is the path to a signature policy to use for + // validating images. If left empty, the containers/image default signature + // policy will be used. + SignaturePolicyPath string `toml:"signature_policy_path,omitempty"` + + // OCIRuntime is the OCI runtime to use. + OCIRuntime string `toml:"runtime"` + + // OCIRuntimes are the set of configured OCI runtimes (default is runc). + OCIRuntimes map[string][]string `toml:"runtimes"` + + // RuntimeSupportsJSON is the list of the OCI runtimes that support + // --format=json. + RuntimeSupportsJSON []string `toml:"runtime_supports_json"` + + // RuntimeSupportsNoCgroups is a list of OCI runtimes that support + // running containers without CGroups. + RuntimeSupportsNoCgroups []string `toml:"runtime_supports_nocgroups"` + + // RuntimePath is the path to OCI runtime binary for launching containers. + // The first path pointing to a valid file will be used This is used only + // when there are no OCIRuntime/OCIRuntimes defined. It is used only to be + // backward compatible with older versions of Podman. + RuntimePath []string `toml:"runtime_path"` + + // ConmonPath is the path to the Conmon binary used for managing containers. + // The first path pointing to a valid file will be used. + ConmonPath []string `toml:"conmon_path"` + + // ConmonEnvVars are environment variables to pass to the Conmon binary + // when it is launched. + ConmonEnvVars []string `toml:"conmon_env_vars"` + + // CGroupManager is the CGroup Manager to use Valid values are "cgroupfs" + // and "systemd". + CgroupManager string `toml:"cgroup_manager"` + + // InitPath is the path to the container-init binary. + InitPath string `toml:"init_path"` + + // StaticDir is the path to a persistent directory to store container + // files. + StaticDir string `toml:"static_dir"` + + // TmpDir is the path to a temporary directory to store per-boot container + // files. Must be stored in a tmpfs. + TmpDir string `toml:"tmp_dir"` + + // MaxLogSize is the maximum size of container logfiles. + MaxLogSize int64 `toml:"max_log_size,omitempty"` + + // NoPivotRoot sets whether to set no-pivot-root in the OCI runtime. + NoPivotRoot bool `toml:"no_pivot_root"` + + // CNIConfigDir sets the directory where CNI configuration files are + // stored. + CNIConfigDir string `toml:"cni_config_dir"` + + // CNIPluginDir sets a number of directories where the CNI network + // plugins can be located. + CNIPluginDir []string `toml:"cni_plugin_dir"` + + // CNIDefaultNetwork is the network name of the default CNI network + // to attach pods to. + CNIDefaultNetwork string `toml:"cni_default_network,omitempty"` + + // HooksDir holds paths to the directories containing hooks + // configuration files. When the same filename is present in in + // multiple directories, the file in the directory listed last in + // this slice takes precedence. + HooksDir []string `toml:"hooks_dir"` + + // DefaultMountsFile is the path to the default mounts file for testing + // purposes only. + DefaultMountsFile string `toml:"-"` + + // Namespace is the libpod namespace to use. Namespaces are used to create + // scopes to separate containers and pods in the state. When namespace is + // set, libpod will only view containers and pods in the same namespace. All + // containers and pods created will default to the namespace set here. A + // namespace of "", the empty string, is equivalent to no namespace, and all + // containers and pods will be visible. The default namespace is "". + Namespace string `toml:"namespace,omitempty"` + + // InfraImage is the image a pod infra container will use to manage + // namespaces. + InfraImage string `toml:"infra_image"` + + // InfraCommand is the command run to start up a pod infra container. + InfraCommand string `toml:"infra_command"` + + // EnablePortReservation determines whether libpod will reserve ports on the + // host when they are forwarded to containers. When enabled, when ports are + // forwarded to containers, they are held open by conmon as long as the + // container is running, ensuring that they cannot be reused by other + // programs on the host. However, this can cause significant memory usage if + // a container has many ports forwarded to it. Disabling this can save + // memory. + EnablePortReservation bool `toml:"enable_port_reservation"` + + // EnableLabeling indicates whether libpod will support container labeling. + EnableLabeling bool `toml:"label"` + + // NetworkCmdPath is the path to the slirp4netns binary. + NetworkCmdPath string `toml:"network_cmd_path"` + + // NumLocks is the number of locks to make available for containers and + // pods. + NumLocks uint32 `toml:"num_locks,omitempty"` + + // LockType is the type of locking to use. + LockType string `toml:"lock_type,omitempty"` + + // EventsLogger determines where events should be logged. + EventsLogger string `toml:"events_logger"` + + // EventsLogFilePath is where the events log is stored. + EventsLogFilePath string `toml:"events_logfile_path"` + + //DetachKeys is the sequence of keys used to detach a container. + DetachKeys string `toml:"detach_keys"` + + // SDNotify tells Libpod to allow containers to notify the host systemd of + // readiness using the SD_NOTIFY mechanism. + SDNotify bool +} + +// DBConfig is a set of Libpod runtime configuration settings that are saved in +// a State when it is first created, and can subsequently be retrieved. +type DBConfig struct { + LibpodRoot string + LibpodTmp string + StorageRoot string + StorageTmp string + GraphDriver string + VolumePath string +} + +// readConfigFromFile reads the specified config file at `path` and attempts to +// unmarshal its content into a Config. +func readConfigFromFile(path string) (*Config, error) { + var config Config + + configBytes, err := ioutil.ReadFile(path) + if err != nil { + return nil, err + } + + logrus.Debugf("Reading configuration file %q", path) + err = toml.Unmarshal(configBytes, &config) + + // For the sake of backwards compat we need to check if the config fields + // with *Set suffix are set in the config. Note that the storage-related + // fields are NOT set in the config here but in the storage.conf OR directly + // by the user. + if config.VolumePath != "" { + config.VolumePathSet = true + } + if config.StaticDir != "" { + config.StaticDirSet = true + } + if config.TmpDir != "" { + config.TmpDirSet = true + } + + return &config, err +} + +// Write decodes the config as TOML and writes it to the specified path. +func (c *Config) Write(path string) error { + f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0666) + if err != nil { + return errors.Wrapf(err, "error opening config file %q", path) + } + + buffer := new(bytes.Buffer) + if err := toml.NewEncoder(buffer).Encode(c); err != nil { + return errors.Wrapf(err, "error encoding config") + } + + if _, err := f.WriteString(buffer.String()); err != nil { + return errors.Wrapf(err, "error writing config %q", path) + } + return err +} + +// FindConmon iterates over (*Config).ConmonPath and returns the path to first +// (version) matching conmon binary. If non is found, we try to do a path lookup +// of "conmon". +func (c *Config) FindConmon() (string, error) { + foundOutdatedConmon := false + for _, path := range c.ConmonPath { + stat, err := os.Stat(path) + if err != nil { + continue + } + if stat.IsDir() { + continue + } + if err := probeConmon(path); err != nil { + logrus.Warnf("Conmon at %s invalid: %v", path, err) + foundOutdatedConmon = true + continue + } + logrus.Debugf("Using conmon: %q", path) + return path, nil + } + + // Search the $PATH as last fallback + if path, err := exec.LookPath("conmon"); err == nil { + if err := probeConmon(path); err != nil { + logrus.Warnf("Conmon at %s is invalid: %v", path, err) + foundOutdatedConmon = true + } else { + logrus.Debugf("Using conmon from $PATH: %q", path) + return path, nil + } + } + + if foundOutdatedConmon { + return "", errors.Wrapf(define.ErrConmonOutdated, + "please update to v%d.%d.%d or later", + _conmonMinMajorVersion, _conmonMinMinorVersion, _conmonMinPatchVersion) + } + + return "", errors.Wrapf(define.ErrInvalidArg, + "could not find a working conmon binary (configured options: %v)", + c.ConmonPath) +} + +// probeConmon calls conmon --version and verifies it is a new enough version for +// the runtime expectations podman currently has. +func probeConmon(conmonBinary string) error { + cmd := exec.Command(conmonBinary, "--version") + var out bytes.Buffer + cmd.Stdout = &out + err := cmd.Run() + if err != nil { + return err + } + r := regexp.MustCompile(`^conmon version (?P<Major>\d+).(?P<Minor>\d+).(?P<Patch>\d+)`) + + matches := r.FindStringSubmatch(out.String()) + if len(matches) != 4 { + return errors.Wrap(err, _conmonVersionFormatErr) + } + major, err := strconv.Atoi(matches[1]) + if err != nil { + return errors.Wrap(err, _conmonVersionFormatErr) + } + if major < _conmonMinMajorVersion { + return define.ErrConmonOutdated + } + if major > _conmonMinMajorVersion { + return nil + } + + minor, err := strconv.Atoi(matches[2]) + if err != nil { + return errors.Wrap(err, _conmonVersionFormatErr) + } + if minor < _conmonMinMinorVersion { + return define.ErrConmonOutdated + } + if minor > _conmonMinMinorVersion { + return nil + } + + patch, err := strconv.Atoi(matches[3]) + if err != nil { + return errors.Wrap(err, _conmonVersionFormatErr) + } + if patch < _conmonMinPatchVersion { + return define.ErrConmonOutdated + } + if patch > _conmonMinPatchVersion { + return nil + } + + return nil +} + +// NewConfig creates a new Config. It starts with an empty config and, if +// specified, merges the config at `userConfigPath` path. Depending if we're +// running as root or rootless, we then merge the system configuration followed +// by merging the default config (hard-coded default in memory). +// +// Note that the OCI runtime is hard-set to `crun` if we're running on a system +// with cgroupsv2. Other OCI runtimes are not yet supporting cgroupsv2. This +// might change in the future. +func NewConfig(userConfigPath string) (*Config, error) { + config := &Config{} // start with an empty config + + // First, try to read the user-specified config + if userConfigPath != "" { + var err error + config, err = readConfigFromFile(userConfigPath) + if err != nil { + return nil, errors.Wrapf(err, "error reading user config %q", userConfigPath) + } + } + + // Now, check if the user can access system configs and merge them if needed. + if configs, err := systemConfigs(); err != nil { + return nil, errors.Wrapf(err, "error finding config on system") + } else { + for _, path := range configs { + systemConfig, err := readConfigFromFile(path) + if err != nil { + return nil, errors.Wrapf(err, "error reading system config %q", path) + } + // Merge the it into the config. Any unset field in config will be + // over-written by the systemConfig. + if err := config.mergeConfig(systemConfig); err != nil { + return nil, errors.Wrapf(err, "error merging system config") + } + logrus.Debugf("Merged system config %q: %v", path, config) + } + } + + // Finally, create a default config from memory and forcefully merge it into + // the config. This way we try to make sure that all fields are properly set + // and that user AND system config can partially set. + if defaultConfig, err := defaultConfigFromMemory(); err != nil { + return nil, errors.Wrapf(err, "error generating default config from memory") + } else { + if err := config.mergeConfig(defaultConfig); err != nil { + return nil, errors.Wrapf(err, "error merging default config from memory") + } + } + + // Relative paths can cause nasty bugs, because core paths we use could + // shift between runs (or even parts of the program - the OCI runtime + // uses a different working directory than we do, for example. + if !filepath.IsAbs(config.StaticDir) { + return nil, errors.Wrapf(define.ErrInvalidArg, "static directory must be an absolute path - instead got %q", config.StaticDir) + } + if !filepath.IsAbs(config.TmpDir) { + return nil, errors.Wrapf(define.ErrInvalidArg, "temporary directory must be an absolute path - instead got %q", config.TmpDir) + } + if !filepath.IsAbs(config.VolumePath) { + return nil, errors.Wrapf(define.ErrInvalidArg, "volume path must be an absolute path - instead got %q", config.VolumePath) + } + + // Check if we need to switch to cgroupfs on rootless. + config.checkCgroupsAndAdjustConfig() + + return config, nil +} + +func rootlessConfigPath() (string, error) { + home, err := util.HomeDir() + if err != nil { + return "", err + } + + return filepath.Join(home, _rootlessConfigPath), nil +} + +func systemConfigs() ([]string, error) { + if rootless.IsRootless() { + path, err := rootlessConfigPath() + if err != nil { + return nil, err + } + if _, err := os.Stat(path); err == nil { + return []string{path}, nil + } + return nil, err + } + + configs := []string{} + if _, err := os.Stat(_rootOverrideConfigPath); err == nil { + configs = append(configs, _rootOverrideConfigPath) + } + if _, err := os.Stat(_rootConfigPath); err == nil { + configs = append(configs, _rootConfigPath) + } + return configs, nil +} + +// checkCgroupsAndAdjustConfig checks if we're running rootless with the systemd +// cgroup manager. In case the user session isn't available, we're switching the +// cgroup manager to cgroupfs. Note, this only applies to rootless. +func (c *Config) checkCgroupsAndAdjustConfig() { + if !rootless.IsRootless() || c.CgroupManager != define.SystemdCgroupsManager { + return + } + + session := os.Getenv("DBUS_SESSION_BUS_ADDRESS") + hasSession := session != "" + if hasSession && strings.HasPrefix(session, "unix:path=") { + _, err := os.Stat(strings.TrimPrefix(session, "unix:path=")) + hasSession = err == nil + } + + if !hasSession { + logrus.Warningf("The cgroups manager is set to systemd but there is no systemd user session available") + logrus.Warningf("For using systemd, you may need to login using an user session") + logrus.Warningf("Alternatively, you can enable lingering with: `loginctl enable-linger %d` (possibly as root)", rootless.GetRootlessUID()) + logrus.Warningf("Falling back to --cgroup-manager=cgroupfs") + c.CgroupManager = define.CgroupfsCgroupsManager + } +} diff --git a/libpod/config/config_test.go b/libpod/config/config_test.go new file mode 100644 index 000000000..47c092440 --- /dev/null +++ b/libpod/config/config_test.go @@ -0,0 +1,64 @@ +package config + +import ( + "reflect" + "testing" + + "github.com/containers/libpod/libpod/define" + "github.com/containers/storage" + "github.com/stretchr/testify/assert" +) + +func TestEmptyConfig(t *testing.T) { + // Make sure that we can read empty configs + config, err := readConfigFromFile("testdata/empty.conf") + assert.NotNil(t, config) + assert.Nil(t, err) +} + +func TestDefaultLibpodConf(t *testing.T) { + // Make sure that we can read the default libpod.conf + config, err := readConfigFromFile("testdata/libpod.conf") + assert.NotNil(t, config) + assert.Nil(t, err) +} + +func TestMergeEmptyAndDefaultMemoryConfig(t *testing.T) { + // Make sure that when we merge the default config into an empty one that we + // effectively get the default config. + defaultConfig, err := defaultConfigFromMemory() + assert.NotNil(t, defaultConfig) + assert.Nil(t, err) + defaultConfig.StateType = define.InvalidStateStore + defaultConfig.StorageConfig = storage.StoreOptions{} + + emptyConfig, err := readConfigFromFile("testdata/empty.conf") + assert.NotNil(t, emptyConfig) + assert.Nil(t, err) + + err = emptyConfig.mergeConfig(defaultConfig) + assert.Nil(t, err) + + equal := reflect.DeepEqual(emptyConfig, defaultConfig) + assert.True(t, equal) +} + +func TestMergeEmptyAndLibpodConfig(t *testing.T) { + // Make sure that when we merge the default config into an empty one that we + // effectively get the default config. + libpodConfig, err := readConfigFromFile("testdata/libpod.conf") + assert.NotNil(t, libpodConfig) + assert.Nil(t, err) + libpodConfig.StateType = define.InvalidStateStore + libpodConfig.StorageConfig = storage.StoreOptions{} + + emptyConfig, err := readConfigFromFile("testdata/empty.conf") + assert.NotNil(t, emptyConfig) + assert.Nil(t, err) + + err = emptyConfig.mergeConfig(libpodConfig) + assert.Nil(t, err) + + equal := reflect.DeepEqual(emptyConfig, libpodConfig) + assert.True(t, equal) +} diff --git a/libpod/config/default.go b/libpod/config/default.go new file mode 100644 index 000000000..17574c059 --- /dev/null +++ b/libpod/config/default.go @@ -0,0 +1,137 @@ +package config + +import ( + "os" + "path/filepath" + + "github.com/containers/libpod/libpod/define" + "github.com/containers/libpod/libpod/events" + "github.com/containers/libpod/pkg/rootless" + "github.com/containers/libpod/pkg/util" + "github.com/containers/storage" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" +) + +const ( + // _defaultGraphRoot points to the default path of the graph root. + _defaultGraphRoot = "/var/lib/containers/storage" + // _defaultRootlessSignaturePolicyPath points to the default path of the + // rootless policy.json file. + _defaultRootlessSignaturePolicyPath = ".config/containers/policy.json" +) + +// defaultConfigFromMemory returns a default libpod configuration. Note that the +// config is different for root and rootless. It also parses the storage.conf. +func defaultConfigFromMemory() (*Config, error) { + c := new(Config) + if tmp, err := defaultTmpDir(); err != nil { + return nil, err + } else { + c.TmpDir = tmp + } + c.EventsLogFilePath = filepath.Join(c.TmpDir, "events", "events.log") + + storeOpts, err := storage.DefaultStoreOptions(rootless.IsRootless(), rootless.GetRootlessUID()) + if err != nil { + return nil, err + } + if storeOpts.GraphRoot == "" { + logrus.Warnf("Storage configuration is unset - using hardcoded default graph root %q", _defaultGraphRoot) + storeOpts.GraphRoot = _defaultGraphRoot + } + c.StaticDir = filepath.Join(storeOpts.GraphRoot, "libpod") + c.VolumePath = filepath.Join(storeOpts.GraphRoot, "volumes") + c.StorageConfig = storeOpts + + c.ImageDefaultTransport = _defaultTransport + c.StateType = define.BoltDBStateStore + c.OCIRuntime = "runc" + c.OCIRuntimes = map[string][]string{ + "runc": { + "/usr/bin/runc", + "/usr/sbin/runc", + "/usr/local/bin/runc", + "/usr/local/sbin/runc", + "/sbin/runc", + "/bin/runc", + "/usr/lib/cri-o-runc/sbin/runc", + "/run/current-system/sw/bin/runc", + }, + // TODO - should we add "crun" defaults here as well? + } + c.ConmonPath = []string{ + "/usr/libexec/podman/conmon", + "/usr/local/libexec/podman/conmon", + "/usr/local/lib/podman/conmon", + "/usr/bin/conmon", + "/usr/sbin/conmon", + "/usr/local/bin/conmon", + "/usr/local/sbin/conmon", + "/run/current-system/sw/bin/conmon", + } + c.ConmonEnvVars = []string{ + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", + } + c.RuntimeSupportsJSON = []string{ + "crun", + "runc", + } + c.RuntimeSupportsNoCgroups = []string{"crun"} + c.InitPath = define.DefaultInitPath + c.CgroupManager = define.SystemdCgroupsManager + c.MaxLogSize = -1 + c.NoPivotRoot = false + c.CNIConfigDir = _etcDir + "/cni/net.d/" + c.CNIPluginDir = []string{ + "/usr/libexec/cni", + "/usr/lib/cni", + "/usr/local/lib/cni", + "/opt/cni/bin", + } + c.CNIDefaultNetwork = "podman" + c.InfraCommand = define.DefaultInfraCommand + c.InfraImage = define.DefaultInfraImage + c.EnablePortReservation = true + c.EnableLabeling = true + c.NumLocks = 2048 + c.EventsLogger = events.DefaultEventerType.String() + c.DetachKeys = define.DefaultDetachKeys + // TODO - ideally we should expose a `type LockType string` along with + // constants. + c.LockType = "shm" + + if rootless.IsRootless() { + home, err := util.HomeDir() + if err != nil { + return nil, err + } + sigPath := filepath.Join(home, _defaultRootlessSignaturePolicyPath) + if _, err := os.Stat(sigPath); err == nil { + c.SignaturePolicyPath = sigPath + } + } + return c, nil +} + +func defaultTmpDir() (string, error) { + if !rootless.IsRootless() { + return "/var/run/libpod", nil + } + + runtimeDir, err := util.GetRuntimeDir() + if err != nil { + return "", err + } + libpodRuntimeDir := filepath.Join(runtimeDir, "libpod") + + if err := os.Mkdir(libpodRuntimeDir, 0700|os.ModeSticky); err != nil { + if !os.IsExist(err) { + return "", errors.Wrapf(err, "cannot mkdir %s", libpodRuntimeDir) + } else if err := os.Chmod(libpodRuntimeDir, 0700|os.ModeSticky); err != nil { + // The directory already exist, just set the sticky bit + return "", errors.Wrapf(err, "could not set sticky bit on %s", libpodRuntimeDir) + } + } + return filepath.Join(libpodRuntimeDir, "tmp"), nil +} diff --git a/libpod/config/merge.go b/libpod/config/merge.go new file mode 100644 index 000000000..798a63da7 --- /dev/null +++ b/libpod/config/merge.go @@ -0,0 +1,183 @@ +package config + +import ( + "path/filepath" + + "github.com/containers/libpod/libpod/define" + "github.com/sirupsen/logrus" +) + +// Merge merges the other config into the current one. Note that a field of the +// other config is only merged when it's not already set in the current one. +// +// Note that the StateType and the StorageConfig will NOT be changed. +func (c *Config) mergeConfig(other *Config) error { + // strings + c.CgroupManager = mergeStrings(c.CgroupManager, other.CgroupManager) + c.CNIConfigDir = mergeStrings(c.CNIConfigDir, other.CNIConfigDir) + c.CNIDefaultNetwork = mergeStrings(c.CNIDefaultNetwork, other.CNIDefaultNetwork) + c.DefaultMountsFile = mergeStrings(c.DefaultMountsFile, other.DefaultMountsFile) + c.DetachKeys = mergeStrings(c.DetachKeys, other.DetachKeys) + c.EventsLogFilePath = mergeStrings(c.EventsLogFilePath, other.EventsLogFilePath) + c.EventsLogger = mergeStrings(c.EventsLogger, other.EventsLogger) + c.ImageDefaultTransport = mergeStrings(c.ImageDefaultTransport, other.ImageDefaultTransport) + c.InfraCommand = mergeStrings(c.InfraCommand, other.InfraCommand) + c.InfraImage = mergeStrings(c.InfraImage, other.InfraImage) + c.InitPath = mergeStrings(c.InitPath, other.InitPath) + c.LockType = mergeStrings(c.LockType, other.LockType) + c.Namespace = mergeStrings(c.Namespace, other.Namespace) + c.NetworkCmdPath = mergeStrings(c.NetworkCmdPath, other.NetworkCmdPath) + c.OCIRuntime = mergeStrings(c.OCIRuntime, other.OCIRuntime) + c.SignaturePolicyPath = mergeStrings(c.SignaturePolicyPath, other.SignaturePolicyPath) + c.StaticDir = mergeStrings(c.StaticDir, other.StaticDir) + c.TmpDir = mergeStrings(c.TmpDir, other.TmpDir) + c.VolumePath = mergeStrings(c.VolumePath, other.VolumePath) + + // string map of slices + c.OCIRuntimes = mergeStringMaps(c.OCIRuntimes, other.OCIRuntimes) + + // string slices + c.CNIPluginDir = mergeStringSlices(c.CNIPluginDir, other.CNIPluginDir) + c.ConmonEnvVars = mergeStringSlices(c.ConmonEnvVars, other.ConmonEnvVars) + c.ConmonPath = mergeStringSlices(c.ConmonPath, other.ConmonPath) + c.HooksDir = mergeStringSlices(c.HooksDir, other.HooksDir) + c.RuntimePath = mergeStringSlices(c.RuntimePath, other.RuntimePath) + c.RuntimeSupportsJSON = mergeStringSlices(c.RuntimeSupportsJSON, other.RuntimeSupportsJSON) + c.RuntimeSupportsNoCgroups = mergeStringSlices(c.RuntimeSupportsNoCgroups, other.RuntimeSupportsNoCgroups) + + // int64s + c.MaxLogSize = mergeInt64s(c.MaxLogSize, other.MaxLogSize) + + // uint32s + c.NumLocks = mergeUint32s(c.NumLocks, other.NumLocks) + + // bools + c.EnableLabeling = mergeBools(c.EnableLabeling, other.EnableLabeling) + c.EnablePortReservation = mergeBools(c.EnablePortReservation, other.EnablePortReservation) + c.NoPivotRoot = mergeBools(c.NoPivotRoot, other.NoPivotRoot) + c.SDNotify = mergeBools(c.SDNotify, other.SDNotify) + + // state type + if c.StateType == define.InvalidStateStore { + c.StateType = other.StateType + } + + // store options - need to check all fields since some configs might only + // set it partially + c.StorageConfig.RunRoot = mergeStrings(c.StorageConfig.RunRoot, other.StorageConfig.RunRoot) + c.StorageConfig.GraphRoot = mergeStrings(c.StorageConfig.GraphRoot, other.StorageConfig.GraphRoot) + c.StorageConfig.GraphDriverName = mergeStrings(c.StorageConfig.GraphDriverName, other.StorageConfig.GraphDriverName) + c.StorageConfig.GraphDriverOptions = mergeStringSlices(c.StorageConfig.GraphDriverOptions, other.StorageConfig.GraphDriverOptions) + if c.StorageConfig.UIDMap == nil { + c.StorageConfig.UIDMap = other.StorageConfig.UIDMap + } + if c.StorageConfig.GIDMap == nil { + c.StorageConfig.GIDMap = other.StorageConfig.GIDMap + } + + // backwards compat *Set fields + c.StorageConfigRunRootSet = mergeBools(c.StorageConfigRunRootSet, other.StorageConfigRunRootSet) + c.StorageConfigGraphRootSet = mergeBools(c.StorageConfigGraphRootSet, other.StorageConfigGraphRootSet) + c.StorageConfigGraphDriverNameSet = mergeBools(c.StorageConfigGraphDriverNameSet, other.StorageConfigGraphDriverNameSet) + c.VolumePathSet = mergeBools(c.VolumePathSet, other.VolumePathSet) + c.StaticDirSet = mergeBools(c.StaticDirSet, other.StaticDirSet) + c.TmpDirSet = mergeBools(c.TmpDirSet, other.TmpDirSet) + + return nil +} + +// MergeDBConfig merges the configuration from the database. +func (c *Config) MergeDBConfig(dbConfig *DBConfig) error { + + if !c.StorageConfigRunRootSet && dbConfig.StorageTmp != "" { + if c.StorageConfig.RunRoot != dbConfig.StorageTmp && + c.StorageConfig.RunRoot != "" { + logrus.Debugf("Overriding run root %q with %q from database", + c.StorageConfig.RunRoot, dbConfig.StorageTmp) + } + c.StorageConfig.RunRoot = dbConfig.StorageTmp + } + + if !c.StorageConfigGraphRootSet && dbConfig.StorageRoot != "" { + if c.StorageConfig.GraphRoot != dbConfig.StorageRoot && + c.StorageConfig.GraphRoot != "" { + logrus.Debugf("Overriding graph root %q with %q from database", + c.StorageConfig.GraphRoot, dbConfig.StorageRoot) + } + c.StorageConfig.GraphRoot = dbConfig.StorageRoot + } + + if !c.StorageConfigGraphDriverNameSet && dbConfig.GraphDriver != "" { + if c.StorageConfig.GraphDriverName != dbConfig.GraphDriver && + c.StorageConfig.GraphDriverName != "" { + logrus.Errorf("User-selected graph driver %q overwritten by graph driver %q from database - delete libpod local files to resolve", + c.StorageConfig.GraphDriverName, dbConfig.GraphDriver) + } + c.StorageConfig.GraphDriverName = dbConfig.GraphDriver + } + + if !c.StaticDirSet && dbConfig.LibpodRoot != "" { + if c.StaticDir != dbConfig.LibpodRoot && c.StaticDir != "" { + logrus.Debugf("Overriding static dir %q with %q from database", c.StaticDir, dbConfig.LibpodRoot) + } + c.StaticDir = dbConfig.LibpodRoot + } + + if !c.TmpDirSet && dbConfig.LibpodTmp != "" { + if c.TmpDir != dbConfig.LibpodTmp && c.TmpDir != "" { + logrus.Debugf("Overriding tmp dir %q with %q from database", c.TmpDir, dbConfig.LibpodTmp) + } + c.TmpDir = dbConfig.LibpodTmp + c.EventsLogFilePath = filepath.Join(dbConfig.LibpodTmp, "events", "events.log") + } + + if !c.VolumePathSet && dbConfig.VolumePath != "" { + if c.VolumePath != dbConfig.VolumePath && c.VolumePath != "" { + logrus.Debugf("Overriding volume path %q with %q from database", c.VolumePath, dbConfig.VolumePath) + } + c.VolumePath = dbConfig.VolumePath + } + return nil +} + +func mergeStrings(a, b string) string { + if a == "" { + return b + } + return a +} + +func mergeStringSlices(a, b []string) []string { + if len(a) == 0 && b != nil { + return b + } + return a +} + +func mergeStringMaps(a, b map[string][]string) map[string][]string { + if len(a) == 0 && b != nil { + return b + } + return a +} + +func mergeInt64s(a, b int64) int64 { + if a == 0 { + return b + } + return a +} + +func mergeUint32s(a, b uint32) uint32 { + if a == 0 { + return b + } + return a +} + +func mergeBools(a, b bool) bool { + if !a { + return b + } + return a +} diff --git a/libpod/config/merge_test.go b/libpod/config/merge_test.go new file mode 100644 index 000000000..eb450b273 --- /dev/null +++ b/libpod/config/merge_test.go @@ -0,0 +1,157 @@ +package config + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestMergeStrings(t *testing.T) { + testData := []struct { + a string + b string + res string + }{ + {"", "", ""}, + {"a", "", "a"}, + {"a", "b", "a"}, + {"", "b", "b"}, + } + for _, data := range testData { + res := mergeStrings(data.a, data.b) + assert.Equal(t, data.res, res) + } +} + +func TestMergeStringSlices(t *testing.T) { + testData := []struct { + a []string + b []string + res []string + }{ + { + nil, nil, nil, + }, + { + nil, + []string{}, + []string{}, + }, + { + []string{}, + nil, + []string{}, + }, + { + []string{}, + []string{}, + []string{}, + }, + { + []string{"a"}, + []string{}, + []string{"a"}, + }, + { + []string{"a"}, + []string{"b"}, + []string{"a"}, + }, + { + []string{}, + []string{"b"}, + []string{"b"}, + }, + } + for _, data := range testData { + res := mergeStringSlices(data.a, data.b) + assert.Equal(t, data.res, res) + } +} + +func TestMergeStringMaps(t *testing.T) { + testData := []struct { + a map[string][]string + b map[string][]string + res map[string][]string + }{ + { + nil, nil, nil, + }, + { + nil, + map[string][]string{}, + map[string][]string{}}, + { + map[string][]string{"a": {"a"}}, + nil, + map[string][]string{"a": {"a"}}, + }, + { + nil, + map[string][]string{"b": {"b"}}, + map[string][]string{"b": {"b"}}, + }, + { + map[string][]string{"a": {"a"}}, + map[string][]string{"b": {"b"}}, + map[string][]string{"a": {"a"}}, + }, + } + for _, data := range testData { + res := mergeStringMaps(data.a, data.b) + assert.Equal(t, data.res, res) + } +} + +func TestMergeInts64(t *testing.T) { + testData := []struct { + a int64 + b int64 + res int64 + }{ + {int64(0), int64(0), int64(0)}, + {int64(1), int64(0), int64(1)}, + {int64(0), int64(1), int64(1)}, + {int64(2), int64(1), int64(2)}, + {int64(-1), int64(1), int64(-1)}, + {int64(0), int64(-1), int64(-1)}, + } + for _, data := range testData { + res := mergeInt64s(data.a, data.b) + assert.Equal(t, data.res, res) + } +} +func TestMergeUint32(t *testing.T) { + testData := []struct { + a uint32 + b uint32 + res uint32 + }{ + {uint32(0), uint32(0), uint32(0)}, + {uint32(1), uint32(0), uint32(1)}, + {uint32(0), uint32(1), uint32(1)}, + {uint32(2), uint32(1), uint32(2)}, + } + for _, data := range testData { + res := mergeUint32s(data.a, data.b) + assert.Equal(t, data.res, res) + } +} + +func TestMergeBools(t *testing.T) { + testData := []struct { + a bool + b bool + res bool + }{ + {false, false, false}, + {true, false, true}, + {false, true, true}, + {true, true, true}, + } + for _, data := range testData { + res := mergeBools(data.a, data.b) + assert.Equal(t, data.res, res) + } +} diff --git a/libpod/config/testdata/empty.conf b/libpod/config/testdata/empty.conf new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/libpod/config/testdata/empty.conf diff --git a/libpod/config/testdata/libpod.conf b/libpod/config/testdata/libpod.conf new file mode 120000 index 000000000..17d09fe4a --- /dev/null +++ b/libpod/config/testdata/libpod.conf @@ -0,0 +1 @@ +../../../libpod.conf
\ No newline at end of file diff --git a/libpod/container.go b/libpod/container.go index 5a7cf202b..8e24391b9 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -1059,9 +1059,9 @@ func (c *Container) NamespacePath(linuxNS LinuxNS) (string, error) { //nolint:in // CGroupPath returns a cgroups "path" for a given container. func (c *Container) CGroupPath() (string, error) { switch c.runtime.config.CgroupManager { - case CgroupfsCgroupsManager: + case define.CgroupfsCgroupsManager: return filepath.Join(c.config.CgroupParent, fmt.Sprintf("libpod-%s", c.ID())), nil - case SystemdCgroupsManager: + case define.SystemdCgroupsManager: if rootless.IsRootless() { uid := rootless.GetRootlessUID() return filepath.Join(c.config.CgroupParent, fmt.Sprintf("user-%d.slice/user@%d.service/user.slice", uid, uid), createUnitName("libpod", c.ID())), nil diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go index d28d37937..66aca23ed 100644 --- a/libpod/container_inspect.go +++ b/libpod/container_inspect.go @@ -1322,9 +1322,9 @@ func (c *Container) generateInspectContainerHostConfig(ctrSpec *spec.Spec, named // Need to check if it's the default, and not print if so. defaultCgroupParent := "" switch c.runtime.config.CgroupManager { - case CgroupfsCgroupsManager: + case define.CgroupfsCgroupsManager: defaultCgroupParent = CgroupfsDefaultCgroupParent - case SystemdCgroupsManager: + case define.SystemdCgroupsManager: defaultCgroupParent = SystemdDefaultCgroupParent } if c.config.CgroupParent != defaultCgroupParent { diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 283d38a0f..94184b6eb 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -1326,14 +1326,14 @@ func (c *Container) getOCICgroupPath() (string, error) { } if (rootless.IsRootless() && !unified) || c.config.NoCgroups { return "", nil - } else if c.runtime.config.CgroupManager == SystemdCgroupsManager { + } else if c.runtime.config.CgroupManager == define.SystemdCgroupsManager { // When runc is set to use Systemd as a cgroup manager, it // expects cgroups to be passed as follows: // slice:prefix:name systemdCgroups := fmt.Sprintf("%s:libpod:%s", path.Base(c.config.CgroupParent), c.ID()) logrus.Debugf("Setting CGroups for container %s to %s", c.ID(), systemdCgroups) return systemdCgroups, nil - } else if c.runtime.config.CgroupManager == CgroupfsCgroupsManager { + } else if c.runtime.config.CgroupManager == define.CgroupfsCgroupsManager { cgroupPath, err := c.CGroupPath() if err != nil { return "", err diff --git a/libpod/container_log_linux.go b/libpod/container_log_linux.go index 8a87a8796..c4acc3d4f 100644 --- a/libpod/container_log_linux.go +++ b/libpod/container_log_linux.go @@ -6,6 +6,7 @@ package libpod import ( "fmt" "io" + "math" "strings" "time" @@ -30,7 +31,11 @@ const ( func (c *Container) readFromJournal(options *logs.LogOptions, logChannel chan *logs.LogLine) error { var config journal.JournalReaderConfig - config.NumFromTail = options.Tail + if options.Tail < 0 { + config.NumFromTail = math.MaxUint64 + } else { + config.NumFromTail = uint64(options.Tail) + } config.Formatter = journalFormatter defaultTime := time.Time{} if options.Since != defaultTime { @@ -54,7 +59,7 @@ func (c *Container) readFromJournal(options *logs.LogOptions, logChannel chan *l if r == nil { return errors.Errorf("journal reader creation failed") } - if options.Tail == 0 { + if options.Tail == math.MaxInt64 { r.Rewind() } diff --git a/libpod/define/config.go b/libpod/define/config.go index c66f67feb..8bd59be75 100644 --- a/libpod/define/config.go +++ b/libpod/define/config.go @@ -7,11 +7,23 @@ var ( DefaultInfraImage = "k8s.gcr.io/pause:3.1" // DefaultInfraCommand to be run in an infra container DefaultInfraCommand = "/pause" + // DefaultSHMLockPath is the default path for SHM locks + DefaultSHMLockPath = "/libpod_lock" + // DefaultRootlessSHMLockPath is the default path for rootless SHM locks + DefaultRootlessSHMLockPath = "/libpod_rootless_lock" + // DefaultDetachKeys is the default keys sequence for detaching a + // container + DefaultDetachKeys = "ctrl-p,ctrl-q" ) -// CtrRemoveTimeout is the default number of seconds to wait after stopping a container -// before sending the kill signal -const CtrRemoveTimeout = 10 +const ( + // CtrRemoveTimeout is the default number of seconds to wait after stopping a container + // before sending the kill signal + CtrRemoveTimeout = 10 + // DefaultTransport is a prefix that we apply to an image name + // to check docker hub first for the image + DefaultTransport = "docker://" +) // InfoData holds the info type, i.e store, host etc and the data for each type type InfoData struct { diff --git a/libpod/define/runtime.go b/libpod/define/runtime.go new file mode 100644 index 000000000..4d8c6cb4d --- /dev/null +++ b/libpod/define/runtime.go @@ -0,0 +1,37 @@ +package define + +import "time" + +// RuntimeStateStore is a constant indicating which state store implementation +// should be used by libpod +type RuntimeStateStore int + +const ( + // InvalidStateStore is an invalid state store + InvalidStateStore RuntimeStateStore = iota + // InMemoryStateStore is an in-memory state that will not persist data + // on containers and pods between libpod instances or after system + // reboot + InMemoryStateStore RuntimeStateStore = iota + // SQLiteStateStore is a state backed by a SQLite database + // It is presently disabled + SQLiteStateStore RuntimeStateStore = iota + // BoltDBStateStore is a state backed by a BoltDB database + BoltDBStateStore RuntimeStateStore = iota + // CgroupfsCgroupsManager represents cgroupfs native cgroup manager + CgroupfsCgroupsManager = "cgroupfs" + // SystemdCgroupsManager represents systemd native cgroup manager + SystemdCgroupsManager = "systemd" + // ContainerCreateTimeout is the timeout before we decide we've failed + // to create a container. + // TODO: Make this generic - all OCI runtime operations should use the + // same timeout, this one. + // TODO: Consider dropping from 240 to 60 seconds. I don't think waiting + // 4 minutes versus 1 minute makes a real difference. + ContainerCreateTimeout = 240 * time.Second + // DefaultShmSize is the default shm size + DefaultShmSize = 64 * 1024 * 1024 + // NsRunDir is the default directory in which running network namespaces + // are stored + NsRunDir = "/var/run/netns" +) diff --git a/libpod/in_memory_state.go b/libpod/in_memory_state.go index 5ab258772..2144671a5 100644 --- a/libpod/in_memory_state.go +++ b/libpod/in_memory_state.go @@ -3,6 +3,7 @@ package libpod import ( "strings" + "github.com/containers/libpod/libpod/config" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/registrar" "github.com/containers/storage/pkg/truncindex" @@ -80,8 +81,8 @@ func (s *InMemoryState) Refresh() error { // GetDBConfig is not implemented for in-memory state. // As we do not store a config, return an empty one. -func (s *InMemoryState) GetDBConfig() (*DBConfig, error) { - return &DBConfig{}, nil +func (s *InMemoryState) GetDBConfig() (*config.DBConfig, error) { + return &config.DBConfig{}, nil } // ValidateDBConfig is not implemented for the in-memory state. diff --git a/libpod/logs/log.go b/libpod/logs/log.go index 0b1703567..0330df06a 100644 --- a/libpod/logs/log.go +++ b/libpod/logs/log.go @@ -31,7 +31,7 @@ type LogOptions struct { Details bool Follow bool Since time.Time - Tail uint64 + Tail int64 Timestamps bool Multi bool WaitGroup *sync.WaitGroup @@ -54,8 +54,10 @@ func GetLogFile(path string, options *LogOptions) (*tail.Tail, []*LogLine, error logTail []*LogLine ) // whence 0=origin, 2=end - if options.Tail > 0 { + if options.Tail >= 0 { whence = 2 + } + if options.Tail > 0 { logTail, err = getTailLog(path, int(options.Tail)) if err != nil { return nil, nil, err diff --git a/libpod/oci_attach_linux.go b/libpod/oci_attach_linux.go index a383f6eab..eeaee6d43 100644 --- a/libpod/oci_attach_linux.go +++ b/libpod/oci_attach_linux.go @@ -152,7 +152,7 @@ func (c *Container) attachToExec(streams *AttachStreams, keys string, resize <-c func processDetachKeys(keys string) ([]byte, error) { // Check the validity of the provided keys first if len(keys) == 0 { - keys = DefaultDetachKeys + keys = define.DefaultDetachKeys } detachKeys, err := term.ToBytes(keys) if err != nil { diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go index 2798c3043..026b13129 100644 --- a/libpod/oci_conmon_linux.go +++ b/libpod/oci_conmon_linux.go @@ -16,6 +16,7 @@ import ( "syscall" "time" + "github.com/containers/libpod/libpod/config" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/cgroups" "github.com/containers/libpod/pkg/errorhandling" @@ -58,7 +59,7 @@ type ConmonOCIRuntime struct { // The first path that points to a valid executable will be used. // Deliberately private. Someone should not be able to construct this outside of // libpod. -func newConmonOCIRuntime(name string, paths []string, conmonPath string, runtimeCfg *RuntimeConfig, supportsJSON, supportsNoCgroups bool) (OCIRuntime, error) { +func newConmonOCIRuntime(name string, paths []string, conmonPath string, runtimeCfg *config.Config, supportsJSON, supportsNoCgroups bool) (OCIRuntime, error) { if name == "" { return nil, errors.Wrapf(define.ErrInvalidArg, "the OCI runtime must be provided a non-empty name") } @@ -114,7 +115,7 @@ func newConmonOCIRuntime(name string, paths []string, conmonPath string, runtime runtime.exitsDir = filepath.Join(runtime.tmpDir, "exits") runtime.socketsDir = filepath.Join(runtime.tmpDir, "socket") - if runtime.cgroupManager != CgroupfsCgroupsManager && runtime.cgroupManager != SystemdCgroupsManager { + if runtime.cgroupManager != define.CgroupfsCgroupsManager && runtime.cgroupManager != define.SystemdCgroupsManager { return nil, errors.Wrapf(define.ErrInvalidArg, "invalid cgroup manager specified: %s", runtime.cgroupManager) } @@ -1092,7 +1093,7 @@ func (r *ConmonOCIRuntime) configureConmonEnv(runtimeDir string) ([]string, []*o env = append(env, fmt.Sprintf("XDG_RUNTIME_DIR=%s", runtimeDir)) env = append(env, fmt.Sprintf("_CONTAINERS_USERNS_CONFIGURED=%s", os.Getenv("_CONTAINERS_USERNS_CONFIGURED"))) env = append(env, fmt.Sprintf("_CONTAINERS_ROOTLESS_UID=%s", os.Getenv("_CONTAINERS_ROOTLESS_UID"))) - home, err := homeDir() + home, err := util.HomeDir() if err != nil { return nil, nil, err } @@ -1118,7 +1119,7 @@ func (r *ConmonOCIRuntime) configureConmonEnv(runtimeDir string) ([]string, []*o func (r *ConmonOCIRuntime) sharedConmonArgs(ctr *Container, cuuid, bundlePath, pidPath, logPath, exitDir, ociLogPath string) []string { // set the conmon API version to be able to use the correct sync struct keys args := []string{"--api-version", "1"} - if r.cgroupManager == SystemdCgroupsManager && !ctr.config.NoCgroups { + if r.cgroupManager == define.SystemdCgroupsManager && !ctr.config.NoCgroups { args = append(args, "-s") } args = append(args, "-c", ctr.ID()) @@ -1220,17 +1221,9 @@ func (r *ConmonOCIRuntime) moveConmonToCgroupAndSignal(ctr *Container, cmd *exec mustCreateCgroup = false } - if rootless.IsRootless() { - ownsCgroup, err := cgroups.UserOwnsCurrentSystemdCgroup() - if err != nil { - return err - } - mustCreateCgroup = !ownsCgroup - } - if mustCreateCgroup { cgroupParent := ctr.CgroupParent() - if r.cgroupManager == SystemdCgroupsManager { + if r.cgroupManager == define.SystemdCgroupsManager { unitName := createUnitName("libpod-conmon", ctr.ID()) realCgroupParent := cgroupParent @@ -1353,7 +1346,7 @@ func readConmonPipeData(pipe *os.File, ociLog string) (int, error) { return ss.si.Data, errors.Wrapf(define.ErrInternal, "container create failed") } data = ss.si.Data - case <-time.After(ContainerCreateTimeout): + case <-time.After(define.ContainerCreateTimeout): return -1, errors.Wrapf(define.ErrInternal, "container creation timeout") } return data, nil diff --git a/libpod/oci_conmon_unsupported.go b/libpod/oci_conmon_unsupported.go index 77b06eed3..a2f52f527 100644 --- a/libpod/oci_conmon_unsupported.go +++ b/libpod/oci_conmon_unsupported.go @@ -3,6 +3,7 @@ package libpod import ( + "github.com/containers/libpod/libpod/config" "github.com/containers/libpod/libpod/define" ) @@ -15,7 +16,7 @@ type ConmonOCIRuntime struct { } // newConmonOCIRuntime is not supported on this OS. -func newConmonOCIRuntime(name string, paths []string, conmonPath string, runtimeCfg *RuntimeConfig, supportsJSON, supportsNoCgroups bool) (OCIRuntime, error) { +func newConmonOCIRuntime(name string, paths []string, conmonPath string, runtimeCfg *config.Config, supportsJSON, supportsNoCgroups bool) (OCIRuntime, error) { return nil, define.ErrNotImplemented } diff --git a/libpod/oci_util.go b/libpod/oci_util.go index cb85b153d..c1a7f1c9a 100644 --- a/libpod/oci_util.go +++ b/libpod/oci_util.go @@ -14,29 +14,9 @@ import ( "github.com/sirupsen/logrus" ) -const ( - // CgroupfsCgroupsManager represents cgroupfs native cgroup manager - CgroupfsCgroupsManager = "cgroupfs" - // SystemdCgroupsManager represents systemd native cgroup manager - SystemdCgroupsManager = "systemd" - - // ContainerCreateTimeout is the timeout before we decide we've failed - // to create a container. - // TODO: Make this generic - all OCI runtime operations should use the - // same timeout, this one. - // TODO: Consider dropping from 240 to 60 seconds. I don't think waiting - // 4 minutes versus 1 minute makes a real difference. - ContainerCreateTimeout = 240 * time.Second - - // Timeout before declaring that runtime has failed to kill a given - // container - killContainerTimeout = 5 * time.Second - // DefaultShmSize is the default shm size - DefaultShmSize = 64 * 1024 * 1024 - // NsRunDir is the default directory in which running network namespaces - // are stored - NsRunDir = "/var/run/netns" -) +// Timeout before declaring that runtime has failed to kill a given +// container +const killContainerTimeout = 5 * time.Second // ociError is used to parse the OCI runtime JSON log. It is not part of the // OCI runtime specifications, it follows what runc does diff --git a/libpod/options.go b/libpod/options.go index f79c75e98..66e8ef93c 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -39,30 +39,30 @@ func WithStorageConfig(config storage.StoreOptions) RuntimeOption { if config.RunRoot != "" { rt.config.StorageConfig.RunRoot = config.RunRoot - rt.configuredFrom.storageRunRootSet = true + rt.config.StorageConfigRunRootSet = true setField = true } if config.GraphRoot != "" { rt.config.StorageConfig.GraphRoot = config.GraphRoot - rt.configuredFrom.storageGraphRootSet = true + rt.config.StorageConfigGraphRootSet = true // Also set libpod static dir, so we are a subdirectory // of the c/storage store by default rt.config.StaticDir = filepath.Join(config.GraphRoot, "libpod") - rt.configuredFrom.libpodStaticDirSet = true + rt.config.StaticDirSet = true // Also set libpod volume path, so we are a subdirectory // of the c/storage store by default rt.config.VolumePath = filepath.Join(config.GraphRoot, "volumes") - rt.configuredFrom.volPathSet = true + rt.config.VolumePathSet = true setField = true } if config.GraphDriverName != "" { rt.config.StorageConfig.GraphDriverName = config.GraphDriverName - rt.configuredFrom.storageGraphDriverSet = true + rt.config.StorageConfigGraphDriverNameSet = true setField = true } @@ -135,13 +135,13 @@ func WithSignaturePolicy(path string) RuntimeOption { // Please note that information is not portable between backing states. // As such, if this differs between two libpods running on the same system, // they will not share containers, and unspecified behavior may occur. -func WithStateType(storeType RuntimeStateStore) RuntimeOption { +func WithStateType(storeType define.RuntimeStateStore) RuntimeOption { return func(rt *Runtime) error { if rt.valid { return define.ErrRuntimeFinalized } - if storeType == InvalidStateStore { + if storeType == define.InvalidStateStore { return errors.Wrapf(define.ErrInvalidArg, "must provide a valid state store type") } @@ -224,9 +224,9 @@ func WithCgroupManager(manager string) RuntimeOption { return define.ErrRuntimeFinalized } - if manager != CgroupfsCgroupsManager && manager != SystemdCgroupsManager { + if manager != define.CgroupfsCgroupsManager && manager != define.SystemdCgroupsManager { return errors.Wrapf(define.ErrInvalidArg, "CGroup manager must be one of %s and %s", - CgroupfsCgroupsManager, SystemdCgroupsManager) + define.CgroupfsCgroupsManager, define.SystemdCgroupsManager) } rt.config.CgroupManager = manager @@ -244,7 +244,7 @@ func WithStaticDir(dir string) RuntimeOption { } rt.config.StaticDir = dir - rt.configuredFrom.libpodStaticDirSet = true + rt.config.StaticDirSet = true return nil } @@ -295,7 +295,7 @@ func WithTmpDir(dir string) RuntimeOption { return define.ErrRuntimeFinalized } rt.config.TmpDir = dir - rt.configuredFrom.libpodTmpDirSet = true + rt.config.TmpDirSet = true return nil } @@ -395,7 +395,7 @@ func WithVolumePath(volPath string) RuntimeOption { } rt.config.VolumePath = volPath - rt.configuredFrom.volPathSet = true + rt.config.VolumePathSet = true return nil } diff --git a/libpod/pod_internal.go b/libpod/pod_internal.go index 7aacda482..b5895d133 100644 --- a/libpod/pod_internal.go +++ b/libpod/pod_internal.go @@ -66,13 +66,13 @@ func (p *Pod) refresh() error { // We need to recreate the pod's cgroup if p.config.UsePodCgroup { switch p.runtime.config.CgroupManager { - case SystemdCgroupsManager: + case define.SystemdCgroupsManager: cgroupPath, err := systemdSliceFromPath(p.config.CgroupParent, fmt.Sprintf("libpod_pod_%s", p.ID())) if err != nil { logrus.Errorf("Error creating CGroup for pod %s: %v", p.ID(), err) } p.state.CgroupPath = cgroupPath - case CgroupfsCgroupsManager: + case define.CgroupfsCgroupsManager: p.state.CgroupPath = filepath.Join(p.config.CgroupParent, p.ID()) logrus.Debugf("setting pod cgroup to %s", p.state.CgroupPath) diff --git a/libpod/runtime.go b/libpod/runtime.go index 300477c09..42e6782e9 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -1,28 +1,21 @@ package libpod import ( - "bytes" "context" "fmt" - "io/ioutil" "os" - "os/exec" - "os/user" "path/filepath" - "regexp" - "strconv" "strings" "sync" "syscall" - "github.com/BurntSushi/toml" is "github.com/containers/image/v5/storage" "github.com/containers/image/v5/types" + "github.com/containers/libpod/libpod/config" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/libpod/events" "github.com/containers/libpod/libpod/image" "github.com/containers/libpod/libpod/lock" - "github.com/containers/libpod/pkg/cgroups" sysreg "github.com/containers/libpod/pkg/registries" "github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/util" @@ -33,75 +26,13 @@ import ( "github.com/sirupsen/logrus" ) -// RuntimeStateStore is a constant indicating which state store implementation -// should be used by libpod -type RuntimeStateStore int - -const ( - // InvalidStateStore is an invalid state store - InvalidStateStore RuntimeStateStore = iota - // InMemoryStateStore is an in-memory state that will not persist data - // on containers and pods between libpod instances or after system - // reboot - InMemoryStateStore RuntimeStateStore = iota - // SQLiteStateStore is a state backed by a SQLite database - // It is presently disabled - SQLiteStateStore RuntimeStateStore = iota - // BoltDBStateStore is a state backed by a BoltDB database - BoltDBStateStore RuntimeStateStore = iota -) - -var ( - // InstallPrefix is the prefix where podman will be installed. - // It can be overridden at build time. - installPrefix = "/usr" - // EtcDir is the sysconfdir where podman should look for system config files. - // It can be overridden at build time. - etcDir = "/etc" - - // SeccompDefaultPath defines the default seccomp path - SeccompDefaultPath = installPrefix + "/share/containers/seccomp.json" - // SeccompOverridePath if this exists it overrides the default seccomp path - SeccompOverridePath = etcDir + "/crio/seccomp.json" - - // ConfigPath is the path to the libpod configuration file - // This file is loaded to replace the builtin default config before - // runtime options (e.g. WithStorageConfig) are applied. - // If it is not present, the builtin default config is used instead - // This path can be overridden when the runtime is created by using - // NewRuntimeFromConfig() instead of NewRuntime() - ConfigPath = installPrefix + "/share/containers/libpod.conf" - // OverrideConfigPath is the path to an override for the default libpod - // configuration file. If OverrideConfigPath exists, it will be used in - // place of the configuration file pointed to by ConfigPath. - OverrideConfigPath = etcDir + "/containers/libpod.conf" - - // DefaultSHMLockPath is the default path for SHM locks - DefaultSHMLockPath = "/libpod_lock" - // DefaultRootlessSHMLockPath is the default path for rootless SHM locks - DefaultRootlessSHMLockPath = "/libpod_rootless_lock" - - // DefaultDetachKeys is the default keys sequence for detaching a - // container - DefaultDetachKeys = "ctrl-p,ctrl-q" - - // minConmonMajor is the major version required for conmon - minConmonMajor = 2 - - // minConmonMinor is the minor version required for conmon - minConmonMinor = 0 - - // minConmonPatch is the sub-minor version required for conmon - minConmonPatch = 1 -) - // A RuntimeOption is a functional option which alters the Runtime created by // NewRuntime type RuntimeOption func(*Runtime) error // Runtime is the core libpod runtime type Runtime struct { - config *RuntimeConfig + config *config.Config state State store storage.Store @@ -113,7 +44,6 @@ type Runtime struct { conmonPath string imageRuntime *image.Runtime lockManager lock.Manager - configuredFrom *runtimeConfiguredFrom // doRenumber indicates that the runtime should perform a lock renumber // during initialization. @@ -141,223 +71,6 @@ type Runtime struct { noStore bool } -// RuntimeConfig contains configuration options used to set up the runtime -type RuntimeConfig struct { - // StorageConfig is the configuration used by containers/storage - // Not included in on-disk config, use the dedicated containers/storage - // configuration file instead - StorageConfig storage.StoreOptions `toml:"-"` - // VolumePath is the default location that named volumes will be created - // under. This convention is followed by the default volume driver, but - // may not be by other drivers. - VolumePath string `toml:"volume_path"` - // ImageDefaultTransport is the default transport method used to fetch - // images - ImageDefaultTransport string `toml:"image_default_transport"` - // SignaturePolicyPath is the path to a signature policy to use for - // validating images - // If left empty, the containers/image default signature policy will - // be used - SignaturePolicyPath string `toml:"signature_policy_path,omitempty"` - // StateType is the type of the backing state store. - // Avoid using multiple values for this with the same containers/storage - // configuration on the same system. Different state types do not - // interact, and each will see a separate set of containers, which may - // cause conflicts in containers/storage - // As such this is not exposed via the config file - StateType RuntimeStateStore `toml:"-"` - // OCIRuntime is the OCI runtime to use. - OCIRuntime string `toml:"runtime"` - // OCIRuntimes are the set of configured OCI runtimes (default is runc) - OCIRuntimes map[string][]string `toml:"runtimes"` - // RuntimeSupportsJSON is the list of the OCI runtimes that support - // --format=json. - RuntimeSupportsJSON []string `toml:"runtime_supports_json"` - // RuntimeSupportsNoCgroups is a list of OCI runtimes that support - // running containers without CGroups. - RuntimeSupportsNoCgroups []string `toml:"runtime_supports_nocgroups"` - // RuntimePath is the path to OCI runtime binary for launching - // containers. - // The first path pointing to a valid file will be used - // This is used only when there are no OCIRuntime/OCIRuntimes defined. It - // is used only to be backward compatible with older versions of Podman. - RuntimePath []string `toml:"runtime_path"` - // ConmonPath is the path to the Conmon binary used for managing - // containers - // The first path pointing to a valid file will be used - ConmonPath []string `toml:"conmon_path"` - // ConmonEnvVars are environment variables to pass to the Conmon binary - // when it is launched - ConmonEnvVars []string `toml:"conmon_env_vars"` - // CGroupManager is the CGroup Manager to use - // Valid values are "cgroupfs" and "systemd" - CgroupManager string `toml:"cgroup_manager"` - // InitPath is the path to the container-init binary. - InitPath string `toml:"init_path"` - // StaticDir is the path to a persistent directory to store container - // files - StaticDir string `toml:"static_dir"` - // TmpDir is the path to a temporary directory to store per-boot - // container files - // Must be stored in a tmpfs - TmpDir string `toml:"tmp_dir"` - // MaxLogSize is the maximum size of container logfiles - MaxLogSize int64 `toml:"max_log_size,omitempty"` - // NoPivotRoot sets whether to set no-pivot-root in the OCI runtime - NoPivotRoot bool `toml:"no_pivot_root"` - // CNIConfigDir sets the directory where CNI configuration files are - // stored - CNIConfigDir string `toml:"cni_config_dir"` - // CNIPluginDir sets a number of directories where the CNI network - // plugins can be located - CNIPluginDir []string `toml:"cni_plugin_dir"` - // CNIDefaultNetwork is the network name of the default CNI network - // to attach pods to - CNIDefaultNetwork string `toml:"cni_default_network,omitempty"` - // HooksDir holds paths to the directories containing hooks - // configuration files. When the same filename is present in in - // multiple directories, the file in the directory listed last in - // this slice takes precedence. - HooksDir []string `toml:"hooks_dir"` - // DefaultMountsFile is the path to the default mounts file for testing - // purposes only - DefaultMountsFile string `toml:"-"` - // Namespace is the libpod namespace to use. - // Namespaces are used to create scopes to separate containers and pods - // in the state. - // When namespace is set, libpod will only view containers and pods in - // the same namespace. All containers and pods created will default to - // the namespace set here. - // A namespace of "", the empty string, is equivalent to no namespace, - // and all containers and pods will be visible. - // The default namespace is "". - Namespace string `toml:"namespace,omitempty"` - - // InfraImage is the image a pod infra container will use to manage namespaces - InfraImage string `toml:"infra_image"` - // InfraCommand is the command run to start up a pod infra container - InfraCommand string `toml:"infra_command"` - // EnablePortReservation determines whether libpod will reserve ports on - // the host when they are forwarded to containers. - // When enabled, when ports are forwarded to containers, they are - // held open by conmon as long as the container is running, ensuring - // that they cannot be reused by other programs on the host. - // However, this can cause significant memory usage if a container has - // many ports forwarded to it. Disabling this can save memory. - EnablePortReservation bool `toml:"enable_port_reservation"` - // EnableLabeling indicates wether libpod will support container labeling - EnableLabeling bool `toml:"label"` - // NetworkCmdPath is the path to the slirp4netns binary - NetworkCmdPath string `toml:"network_cmd_path"` - - // NumLocks is the number of locks to make available for containers and - // pods. - NumLocks uint32 `toml:"num_locks,omitempty"` - - // LockType is the type of locking to use. - LockType string `toml:"lock_type,omitempty"` - - // EventsLogger determines where events should be logged - EventsLogger string `toml:"events_logger"` - // EventsLogFilePath is where the events log is stored. - EventsLogFilePath string `toml:"events_logfile_path"` - //DetachKeys is the sequence of keys used to detach a container - DetachKeys string `toml:"detach_keys"` - - // SDNotify tells Libpod to allow containers to notify the host - // systemd of readiness using the SD_NOTIFY mechanism - SDNotify bool - // CgroupCheck verifies if the cgroup check for correct OCI runtime has been done. - CgroupCheck bool `toml:"cgroup_check,omitempty"` -} - -// runtimeConfiguredFrom is a struct used during early runtime init to help -// assemble the full RuntimeConfig struct from defaults. -// It indicated whether several fields in the runtime configuration were set -// explicitly. -// If they were not, we may override them with information from the database, -// if it exists and differs from what is present in the system already. -type runtimeConfiguredFrom struct { - storageGraphDriverSet bool - storageGraphRootSet bool - storageRunRootSet bool - libpodStaticDirSet bool - libpodTmpDirSet bool - volPathSet bool - conmonPath bool - conmonEnvVars bool - initPath bool - ociRuntimes bool - runtimePath bool - cniPluginDir bool - noPivotRoot bool - runtimeSupportsJSON bool - runtimeSupportsNoCgroups bool - ociRuntime bool -} - -func defaultRuntimeConfig() (RuntimeConfig, error) { - storeOpts, err := storage.DefaultStoreOptions(rootless.IsRootless(), rootless.GetRootlessUID()) - if err != nil { - return RuntimeConfig{}, err - } - graphRoot := storeOpts.GraphRoot - if graphRoot == "" { - logrus.Warnf("Storage configuration is unset - using hardcoded default paths") - graphRoot = "/var/lib/containers/storage" - } - volumePath := filepath.Join(graphRoot, "volumes") - staticDir := filepath.Join(graphRoot, "libpod") - return RuntimeConfig{ - // Leave this empty so containers/storage will use its defaults - StorageConfig: storage.StoreOptions{}, - VolumePath: volumePath, - ImageDefaultTransport: DefaultTransport, - StateType: BoltDBStateStore, - OCIRuntime: "runc", - OCIRuntimes: map[string][]string{ - "runc": { - "/usr/bin/runc", - "/usr/sbin/runc", - "/usr/local/bin/runc", - "/usr/local/sbin/runc", - "/sbin/runc", - "/bin/runc", - "/usr/lib/cri-o-runc/sbin/runc", - "/run/current-system/sw/bin/runc", - }, - }, - ConmonPath: []string{ - "/usr/libexec/podman/conmon", - "/usr/local/lib/podman/conmon", - "/usr/bin/conmon", - "/usr/sbin/conmon", - "/usr/local/bin/conmon", - "/usr/local/sbin/conmon", - "/run/current-system/sw/bin/conmon", - }, - ConmonEnvVars: []string{ - "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", - }, - InitPath: define.DefaultInitPath, - CgroupManager: SystemdCgroupsManager, - StaticDir: staticDir, - TmpDir: "", - MaxLogSize: -1, - NoPivotRoot: false, - CNIConfigDir: etcDir + "/cni/net.d/", - CNIPluginDir: []string{"/usr/libexec/cni", "/usr/lib/cni", "/usr/local/lib/cni", "/opt/cni/bin"}, - InfraCommand: define.DefaultInfraCommand, - InfraImage: define.DefaultInfraImage, - EnablePortReservation: true, - EnableLabeling: true, - NumLocks: 2048, - EventsLogger: events.DefaultEventerType.String(), - DetachKeys: DefaultDetachKeys, - LockType: "shm", - }, nil -} - // SetXdgDirs ensures the XDG_RUNTIME_DIR env and XDG_CONFIG_HOME variables are set. // containers/image uses XDG_RUNTIME_DIR to locate the auth file, XDG_CONFIG_HOME is // use for the libpod.conf configuration file. @@ -400,28 +113,6 @@ func SetXdgDirs() error { return nil } -func getDefaultTmpDir() (string, error) { - if !rootless.IsRootless() { - return "/var/run/libpod", nil - } - - runtimeDir, err := util.GetRuntimeDir() - if err != nil { - return "", err - } - libpodRuntimeDir := filepath.Join(runtimeDir, "libpod") - - if err := os.Mkdir(libpodRuntimeDir, 0700|os.ModeSticky); err != nil { - if !os.IsExist(err) { - return "", errors.Wrapf(err, "cannot mkdir %s", libpodRuntimeDir) - } else if err := os.Chmod(libpodRuntimeDir, 0700|os.ModeSticky); err != nil { - // The directory already exist, just set the sticky bit - return "", errors.Wrapf(err, "could not set sticky bit on %s", libpodRuntimeDir) - } - } - return filepath.Join(libpodRuntimeDir, "tmp"), nil -} - // NewRuntime creates a new container runtime // Options can be passed to override the default configuration for the runtime func NewRuntime(ctx context.Context, options ...RuntimeOption) (runtime *Runtime, err error) { @@ -440,260 +131,14 @@ func NewRuntimeFromConfig(ctx context.Context, userConfigPath string, options .. return newRuntimeFromConfig(ctx, userConfigPath, options...) } -func homeDir() (string, error) { - home := os.Getenv("HOME") - if home == "" { - usr, err := user.LookupId(fmt.Sprintf("%d", rootless.GetRootlessUID())) - if err != nil { - return "", errors.Wrapf(err, "unable to resolve HOME directory") - } - home = usr.HomeDir - } - return home, nil -} - -func getRootlessConfigPath() (string, error) { - home, err := homeDir() - if err != nil { - return "", err - } - - return filepath.Join(home, ".config/containers/libpod.conf"), nil -} - -func getConfigPath() (string, error) { - if rootless.IsRootless() { - path, err := getRootlessConfigPath() - if err != nil { - return "", err - } - if _, err := os.Stat(path); err == nil { - return path, nil - } - return "", err - } - if _, err := os.Stat(OverrideConfigPath); err == nil { - // Use the override configuration path - return OverrideConfigPath, nil - } - if _, err := os.Stat(ConfigPath); err == nil { - return ConfigPath, nil - } - return "", nil -} - -// DefaultRuntimeConfig reads default config path and returns the RuntimeConfig -func DefaultRuntimeConfig() (*RuntimeConfig, error) { - configPath, err := getConfigPath() - if err != nil { - return nil, err - } - - contents, err := ioutil.ReadFile(configPath) - if err != nil { - return nil, errors.Wrapf(err, "error reading configuration file %s", configPath) - } - - // This is ugly, but we need to decode twice. - // Once to check if libpod static and tmp dirs were explicitly - // set (not enough to check if they're not the default value, - // might have been explicitly configured to the default). - // A second time to actually get a usable config. - tmpConfig := new(RuntimeConfig) - if _, err := toml.Decode(string(contents), tmpConfig); err != nil { - return nil, errors.Wrapf(err, "error decoding configuration file %s", - configPath) - } - return tmpConfig, nil -} - func newRuntimeFromConfig(ctx context.Context, userConfigPath string, options ...RuntimeOption) (runtime *Runtime, err error) { runtime = new(Runtime) - runtime.config = new(RuntimeConfig) - runtime.configuredFrom = new(runtimeConfiguredFrom) - - // Copy the default configuration - tmpDir, err := getDefaultTmpDir() - if err != nil { - return nil, err - } - - // storage.conf - storageConfFile, err := storage.DefaultConfigFile(rootless.IsRootless()) - if err != nil { - return nil, err - } - createStorageConfFile := false - if _, err := os.Stat(storageConfFile); os.IsNotExist(err) { - createStorageConfFile = true - } - - defRunConf, err := defaultRuntimeConfig() + conf, err := config.NewConfig(userConfigPath) if err != nil { return nil, err } - if err := JSONDeepCopy(defRunConf, runtime.config); err != nil { - return nil, errors.Wrapf(err, "error copying runtime default config") - } - runtime.config.TmpDir = tmpDir - - storageConf, err := storage.DefaultStoreOptions(rootless.IsRootless(), rootless.GetRootlessUID()) - if err != nil { - return nil, errors.Wrapf(err, "error retrieving storage config") - } - runtime.config.StorageConfig = storageConf - runtime.config.StaticDir = filepath.Join(storageConf.GraphRoot, "libpod") - runtime.config.VolumePath = filepath.Join(storageConf.GraphRoot, "volumes") - - configPath, err := getConfigPath() - if err != nil { - return nil, err - } - if rootless.IsRootless() { - home, err := homeDir() - if err != nil { - return nil, err - } - if runtime.config.SignaturePolicyPath == "" { - newPath := filepath.Join(home, ".config/containers/policy.json") - if _, err := os.Stat(newPath); err == nil { - runtime.config.SignaturePolicyPath = newPath - } - } - } - - if userConfigPath != "" { - configPath = userConfigPath - if _, err := os.Stat(configPath); err != nil { - // If the user specified a config file, we must fail immediately - // when it doesn't exist - return nil, errors.Wrapf(err, "cannot stat %s", configPath) - } - } - - // If we have a valid configuration file, load it in - if configPath != "" { - contents, err := ioutil.ReadFile(configPath) - if err != nil { - return nil, errors.Wrapf(err, "error reading configuration file %s", configPath) - } - - // This is ugly, but we need to decode twice. - // Once to check if libpod static and tmp dirs were explicitly - // set (not enough to check if they're not the default value, - // might have been explicitly configured to the default). - // A second time to actually get a usable config. - tmpConfig := new(RuntimeConfig) - if _, err := toml.Decode(string(contents), tmpConfig); err != nil { - return nil, errors.Wrapf(err, "error decoding configuration file %s", - configPath) - } - - if err := cgroupV2Check(configPath, tmpConfig); err != nil { - return nil, err - } - - if tmpConfig.StaticDir != "" { - runtime.configuredFrom.libpodStaticDirSet = true - } - if tmpConfig.TmpDir != "" { - runtime.configuredFrom.libpodTmpDirSet = true - } - if tmpConfig.VolumePath != "" { - runtime.configuredFrom.volPathSet = true - } - if tmpConfig.ConmonPath != nil { - runtime.configuredFrom.conmonPath = true - } - if tmpConfig.ConmonEnvVars != nil { - runtime.configuredFrom.conmonEnvVars = true - } - if tmpConfig.InitPath != "" { - runtime.configuredFrom.initPath = true - } - if tmpConfig.OCIRuntimes != nil { - runtime.configuredFrom.ociRuntimes = true - } - if tmpConfig.RuntimePath != nil { - runtime.configuredFrom.runtimePath = true - } - if tmpConfig.CNIPluginDir != nil { - runtime.configuredFrom.cniPluginDir = true - } - if tmpConfig.NoPivotRoot { - runtime.configuredFrom.noPivotRoot = true - } - if tmpConfig.RuntimeSupportsJSON != nil { - runtime.configuredFrom.runtimeSupportsJSON = true - } - if tmpConfig.RuntimeSupportsNoCgroups != nil { - runtime.configuredFrom.runtimeSupportsNoCgroups = true - } - if tmpConfig.OCIRuntime != "" { - runtime.configuredFrom.ociRuntime = true - } - - if _, err := toml.Decode(string(contents), runtime.config); err != nil { - return nil, errors.Wrapf(err, "error decoding configuration file %s", configPath) - } - } else if rootless.IsRootless() { - // If the configuration file was not found but we are running in rootless, a subset of the - // global config file is used. - for _, path := range []string{OverrideConfigPath, ConfigPath} { - contents, err := ioutil.ReadFile(path) - if err != nil { - // Ignore any error, the file might not be readable by us. - continue - } - tmpConfig := new(RuntimeConfig) - if _, err := toml.Decode(string(contents), tmpConfig); err != nil { - return nil, errors.Wrapf(err, "error decoding configuration file %s", path) - } - - // Cherry pick the settings we want from the global configuration - if !runtime.configuredFrom.conmonPath { - runtime.config.ConmonPath = tmpConfig.ConmonPath - } - if !runtime.configuredFrom.conmonEnvVars { - runtime.config.ConmonEnvVars = tmpConfig.ConmonEnvVars - } - if !runtime.configuredFrom.initPath { - runtime.config.InitPath = tmpConfig.InitPath - } - if !runtime.configuredFrom.ociRuntimes { - runtime.config.OCIRuntimes = tmpConfig.OCIRuntimes - } - if !runtime.configuredFrom.runtimePath { - runtime.config.RuntimePath = tmpConfig.RuntimePath - } - if !runtime.configuredFrom.cniPluginDir { - runtime.config.CNIPluginDir = tmpConfig.CNIPluginDir - } - if !runtime.configuredFrom.noPivotRoot { - runtime.config.NoPivotRoot = tmpConfig.NoPivotRoot - } - if !runtime.configuredFrom.runtimeSupportsJSON { - runtime.config.RuntimeSupportsJSON = tmpConfig.RuntimeSupportsJSON - } - if !runtime.configuredFrom.runtimeSupportsNoCgroups { - runtime.config.RuntimeSupportsNoCgroups = tmpConfig.RuntimeSupportsNoCgroups - } - if !runtime.configuredFrom.ociRuntime { - runtime.config.OCIRuntime = tmpConfig.OCIRuntime - } - - cgroupsV2, err := cgroups.IsCgroup2UnifiedMode() - if err != nil { - return nil, err - } - if cgroupsV2 { - runtime.config.CgroupCheck = true - } - - break - } - } + runtime.config = conf // Overwrite config with user-given configuration options for _, opt := range options { @@ -702,36 +147,6 @@ func newRuntimeFromConfig(ctx context.Context, userConfigPath string, options .. } } - if rootless.IsRootless() && configPath == "" { - if createStorageConfFile { - if err := util.WriteStorageConfigFile(&runtime.config.StorageConfig, storageConfFile); err != nil { - return nil, errors.Wrapf(err, "cannot write config file %s", storageConfFile) - } - } - - configPath, err := getRootlessConfigPath() - if err != nil { - return nil, err - } - if configPath != "" { - if err := os.MkdirAll(filepath.Dir(configPath), 0711); err != nil { - return nil, err - } - file, err := os.OpenFile(configPath, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600) - if err != nil && !os.IsExist(err) { - return nil, errors.Wrapf(err, "cannot open file %s", configPath) - } - if err == nil { - defer file.Close() - enc := toml.NewEncoder(file) - if err := enc.Encode(runtime.config); err != nil { - if removeErr := os.Remove(configPath); removeErr != nil { - logrus.Debugf("unable to remove %s: %q", configPath, err) - } - } - } - } - } if err := makeRuntime(ctx, runtime); err != nil { return nil, err } @@ -758,9 +173,9 @@ func getLockManager(runtime *Runtime) (lock.Manager, error) { } case "", "shm": - lockPath := DefaultSHMLockPath + lockPath := define.DefaultSHMLockPath if rootless.IsRootless() { - lockPath = fmt.Sprintf("%s_%d", DefaultRootlessSHMLockPath, rootless.GetRootlessUID()) + lockPath = fmt.Sprintf("%s_%d", define.DefaultRootlessSHMLockPath, rootless.GetRootlessUID()) } // Set up the lock manager manager, err = lock.OpenSHMLockManager(lockPath, runtime.config.NumLocks) @@ -794,119 +209,14 @@ func getLockManager(runtime *Runtime) (lock.Manager, error) { return manager, nil } -// probeConmon calls conmon --version and verifies it is a new enough version for -// the runtime expectations podman currently has -func probeConmon(conmonBinary string) error { - versionFormatErr := "conmon version changed format" - cmd := exec.Command(conmonBinary, "--version") - var out bytes.Buffer - cmd.Stdout = &out - err := cmd.Run() - if err != nil { - return err - } - r := regexp.MustCompile(`^conmon version (?P<Major>\d+).(?P<Minor>\d+).(?P<Patch>\d+)`) - - matches := r.FindStringSubmatch(out.String()) - if len(matches) != 4 { - return errors.Wrapf(err, versionFormatErr) - } - major, err := strconv.Atoi(matches[1]) - if err != nil { - return errors.Wrapf(err, versionFormatErr) - } - if major < minConmonMajor { - return define.ErrConmonOutdated - } - if major > minConmonMajor { - return nil - } - - minor, err := strconv.Atoi(matches[2]) - if err != nil { - return errors.Wrapf(err, versionFormatErr) - } - if minor < minConmonMinor { - return define.ErrConmonOutdated - } - if minor > minConmonMinor { - return nil - } - - patch, err := strconv.Atoi(matches[3]) - if err != nil { - return errors.Wrapf(err, versionFormatErr) - } - if patch < minConmonPatch { - return define.ErrConmonOutdated - } - if patch > minConmonPatch { - return nil - } - - return nil -} - // Make a new runtime based on the given configuration // Sets up containers/storage, state store, OCI runtime func makeRuntime(ctx context.Context, runtime *Runtime) (err error) { - // Let's sanity-check some paths first. - // Relative paths can cause nasty bugs, because core paths we use could - // shift between runs (or even parts of the program - the OCI runtime - // uses a different working directory than we do, for example. - if !filepath.IsAbs(runtime.config.StaticDir) { - return errors.Wrapf(define.ErrInvalidArg, "static directory must be an absolute path - instead got %q", runtime.config.StaticDir) - } - if !filepath.IsAbs(runtime.config.TmpDir) { - return errors.Wrapf(define.ErrInvalidArg, "temporary directory must be an absolute path - instead got %q", runtime.config.TmpDir) - } - if !filepath.IsAbs(runtime.config.VolumePath) { - return errors.Wrapf(define.ErrInvalidArg, "volume path must be an absolute path - instead got %q", runtime.config.VolumePath) - } - // Find a working conmon binary - foundConmon := false - foundOutdatedConmon := false - for _, path := range runtime.config.ConmonPath { - stat, err := os.Stat(path) - if err != nil { - continue - } - if stat.IsDir() { - continue - } - if err := probeConmon(path); err != nil { - logrus.Warnf("conmon at %s invalid: %v", path, err) - foundOutdatedConmon = true - continue - } - foundConmon = true - runtime.conmonPath = path - logrus.Debugf("using conmon: %q", path) - break - } - - // Search the $PATH as last fallback - if !foundConmon { - if conmon, err := exec.LookPath("conmon"); err == nil { - if err := probeConmon(conmon); err != nil { - logrus.Warnf("conmon at %s is invalid: %v", conmon, err) - foundOutdatedConmon = true - } else { - foundConmon = true - runtime.conmonPath = conmon - logrus.Debugf("using conmon from $PATH: %q", conmon) - } - } - } - - if !foundConmon { - if foundOutdatedConmon { - return errors.Errorf("please update to v%d.%d.%d or later: %v", minConmonMajor, minConmonMinor, minConmonPatch, define.ErrConmonOutdated) - } - return errors.Wrapf(define.ErrInvalidArg, - "could not find a working conmon binary (configured options: %v)", - runtime.config.ConmonPath) + if cPath, err := runtime.config.FindConmon(); err != nil { + return err + } else { + runtime.conmonPath = cPath } // Make the static files directory if it does not exist @@ -918,17 +228,22 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (err error) { } } - // Set up the state + // Set up the state. + // + // TODO - if we further break out the state implementation into + // libpod/state, the config could take care of the code below. It + // would further allow to move the types and consts into a coherent + // package. switch runtime.config.StateType { - case InMemoryStateStore: + case define.InMemoryStateStore: state, err := NewInMemoryState() if err != nil { return err } runtime.state = state - case SQLiteStateStore: + case define.SQLiteStateStore: return errors.Wrapf(define.ErrInvalidArg, "SQLite state is currently disabled") - case BoltDBStateStore: + case define.BoltDBStateStore: dbPath := filepath.Join(runtime.config.StaticDir, "bolt_state.db") state, err := NewBoltState(dbPath, runtime) @@ -937,7 +252,7 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (err error) { } runtime.state = state default: - return errors.Wrapf(define.ErrInvalidArg, "unrecognized state type passed") + return errors.Wrapf(define.ErrInvalidArg, "unrecognized state type passed (%v)", runtime.config.StateType) } // Grab config from the database so we can reset some defaults @@ -946,51 +261,9 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (err error) { return errors.Wrapf(err, "error retrieving runtime configuration from database") } - // Reset defaults if they were not explicitly set - if !runtime.configuredFrom.storageGraphDriverSet && dbConfig.GraphDriver != "" { - if runtime.config.StorageConfig.GraphDriverName != dbConfig.GraphDriver && - runtime.config.StorageConfig.GraphDriverName != "" { - logrus.Errorf("User-selected graph driver %q overwritten by graph driver %q from database - delete libpod local files to resolve", - runtime.config.StorageConfig.GraphDriverName, dbConfig.GraphDriver) - } - runtime.config.StorageConfig.GraphDriverName = dbConfig.GraphDriver - } - if !runtime.configuredFrom.storageGraphRootSet && dbConfig.StorageRoot != "" { - if runtime.config.StorageConfig.GraphRoot != dbConfig.StorageRoot && - runtime.config.StorageConfig.GraphRoot != "" { - logrus.Debugf("Overriding graph root %q with %q from database", - runtime.config.StorageConfig.GraphRoot, dbConfig.StorageRoot) - } - runtime.config.StorageConfig.GraphRoot = dbConfig.StorageRoot + if err := runtime.config.MergeDBConfig(dbConfig); err != nil { + return errors.Wrapf(err, "error merging database config into runtime config") } - if !runtime.configuredFrom.storageRunRootSet && dbConfig.StorageTmp != "" { - if runtime.config.StorageConfig.RunRoot != dbConfig.StorageTmp && - runtime.config.StorageConfig.RunRoot != "" { - logrus.Debugf("Overriding run root %q with %q from database", - runtime.config.StorageConfig.RunRoot, dbConfig.StorageTmp) - } - runtime.config.StorageConfig.RunRoot = dbConfig.StorageTmp - } - if !runtime.configuredFrom.libpodStaticDirSet && dbConfig.LibpodRoot != "" { - if runtime.config.StaticDir != dbConfig.LibpodRoot && runtime.config.StaticDir != "" { - logrus.Debugf("Overriding static dir %q with %q from database", runtime.config.StaticDir, dbConfig.LibpodRoot) - } - runtime.config.StaticDir = dbConfig.LibpodRoot - } - if !runtime.configuredFrom.libpodTmpDirSet && dbConfig.LibpodTmp != "" { - if runtime.config.TmpDir != dbConfig.LibpodTmp && runtime.config.TmpDir != "" { - logrus.Debugf("Overriding tmp dir %q with %q from database", runtime.config.TmpDir, dbConfig.LibpodTmp) - } - runtime.config.TmpDir = dbConfig.LibpodTmp - } - if !runtime.configuredFrom.volPathSet && dbConfig.VolumePath != "" { - if runtime.config.VolumePath != dbConfig.VolumePath && runtime.config.VolumePath != "" { - logrus.Debugf("Overriding volume path %q with %q from database", runtime.config.VolumePath, dbConfig.VolumePath) - } - runtime.config.VolumePath = dbConfig.VolumePath - } - - runtime.config.EventsLogFilePath = filepath.Join(runtime.config.TmpDir, "events", "events.log") logrus.Debugf("Using graph driver %s", runtime.config.StorageConfig.GraphDriverName) logrus.Debugf("Using graph root %s", runtime.config.StorageConfig.GraphRoot) @@ -1269,7 +542,7 @@ func makeRuntime(ctx context.Context, runtime *Runtime) (err error) { } // GetConfig returns a copy of the configuration used by the runtime -func (r *Runtime) GetConfig() (*RuntimeConfig, error) { +func (r *Runtime) GetConfig() (*config.Config, error) { r.lock.RLock() defer r.lock.RUnlock() @@ -1277,7 +550,7 @@ func (r *Runtime) GetConfig() (*RuntimeConfig, error) { return nil, define.ErrRuntimeStopped } - config := new(RuntimeConfig) + config := new(config.Config) // Copy so the caller won't be able to modify the actual config if err := JSONDeepCopy(r.config, config); err != nil { @@ -1499,56 +772,3 @@ func (r *Runtime) SystemContext() *types.SystemContext { func (r *Runtime) GetOCIRuntimePath() string { return r.defaultOCIRuntime.Path() } - -// Since runc does not currently support cgroupV2 -// Change to default crun on first running of libpod.conf -// TODO Once runc has support for cgroups, this function should be removed. -func cgroupV2Check(configPath string, tmpConfig *RuntimeConfig) error { - if !tmpConfig.CgroupCheck && rootless.IsRootless() { - if tmpConfig.CgroupManager == SystemdCgroupsManager { - // If we are running rootless and the systemd manager is requested, be sure that dbus is accessible - session := os.Getenv("DBUS_SESSION_BUS_ADDRESS") - hasSession := session != "" - if hasSession && strings.HasPrefix(session, "unix:path=") { - _, err := os.Stat(strings.TrimPrefix(session, "unix:path=")) - hasSession = err == nil - } - - if !hasSession { - logrus.Warningf("The cgroups manager is set to systemd but there is no systemd user session available") - logrus.Warningf("For using systemd, you may need to login using an user session") - logrus.Warningf("Alternatively, you can enable lingering with: `loginctl enable-linger %d` (possibily as root)", rootless.GetRootlessUID()) - logrus.Warningf("Falling back to --cgroup-manager=cgroupfs") - - tmpConfig.CgroupManager = CgroupfsCgroupsManager - } - - } - cgroupsV2, err := cgroups.IsCgroup2UnifiedMode() - if err != nil { - return err - } - if cgroupsV2 { - path, err := exec.LookPath("crun") - if err != nil { - logrus.Warnf("Can not find crun package on the host, containers might fail to run on cgroup V2 systems without crun: %q", err) - // Can't find crun path so do nothing - return nil - } - tmpConfig.CgroupCheck = true - tmpConfig.OCIRuntime = path - file, err := os.OpenFile(configPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0666) - if err != nil { - return errors.Wrapf(err, "cannot open file %s", configPath) - } - defer file.Close() - enc := toml.NewEncoder(file) - if err := enc.Encode(tmpConfig); err != nil { - if removeErr := os.Remove(configPath); removeErr != nil { - logrus.Debugf("unable to remove %s: %q", configPath, err) - } - } - } - } - return nil -} diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go index 2b214d572..7069d3494 100644 --- a/libpod/runtime_ctr.go +++ b/libpod/runtime_ctr.go @@ -75,7 +75,7 @@ func (r *Runtime) initContainerVariables(rSpec *spec.Spec, config *ContainerConf if config == nil { ctr.config.ID = stringid.GenerateNonCryptoID() - ctr.config.ShmSize = DefaultShmSize + ctr.config.ShmSize = define.DefaultShmSize } else { // This is a restore from an imported checkpoint ctr.restoreFromCheckpoint = true @@ -215,7 +215,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (c *Contai // Only if we're actually configuring CGroups. if !ctr.config.NoCgroups { switch r.config.CgroupManager { - case CgroupfsCgroupsManager: + case define.CgroupfsCgroupsManager: if ctr.config.CgroupParent == "" { if pod != nil && pod.config.UsePodCgroup { podCgroup, err := pod.CgroupPath() @@ -232,7 +232,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (c *Contai } else if strings.HasSuffix(path.Base(ctr.config.CgroupParent), ".slice") { return nil, errors.Wrapf(define.ErrInvalidArg, "systemd slice received as cgroup parent when using cgroupfs") } - case SystemdCgroupsManager: + case define.SystemdCgroupsManager: if ctr.config.CgroupParent == "" { if pod != nil && pod.config.UsePodCgroup { podCgroup, err := pod.CgroupPath() diff --git a/libpod/runtime_pod_linux.go b/libpod/runtime_pod_linux.go index 05866d05a..704aaf9d0 100644 --- a/libpod/runtime_pod_linux.go +++ b/libpod/runtime_pod_linux.go @@ -76,7 +76,7 @@ func (r *Runtime) NewPod(ctx context.Context, options ...PodCreateOption) (_ *Po // Check CGroup parent sanity, and set it if it was not set switch r.config.CgroupManager { - case CgroupfsCgroupsManager: + case define.CgroupfsCgroupsManager: if pod.config.CgroupParent == "" { pod.config.CgroupParent = CgroupfsDefaultCgroupParent } else if strings.HasSuffix(path.Base(pod.config.CgroupParent), ".slice") { @@ -89,7 +89,7 @@ func (r *Runtime) NewPod(ctx context.Context, options ...PodCreateOption) (_ *Po if pod.config.UsePodCgroup { pod.state.CgroupPath = filepath.Join(pod.config.CgroupParent, pod.ID()) } - case SystemdCgroupsManager: + case define.SystemdCgroupsManager: if pod.config.CgroupParent == "" { if rootless.IsRootless() { pod.config.CgroupParent = SystemdDefaultRootlessCgroupParent @@ -200,7 +200,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool) // the pod and conmon CGroups with a PID limit to prevent them from // spawning any further processes (particularly cleanup processes) which // would prevent removing the CGroups. - if p.runtime.config.CgroupManager == CgroupfsCgroupsManager { + if p.runtime.config.CgroupManager == define.CgroupfsCgroupsManager { // Get the conmon CGroup conmonCgroupPath := filepath.Join(p.state.CgroupPath, "conmon") conmonCgroup, err := cgroups.Load(conmonCgroupPath) @@ -251,7 +251,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool) logrus.Debugf("Removing pod cgroup %s", p.state.CgroupPath) switch p.runtime.config.CgroupManager { - case SystemdCgroupsManager: + case define.SystemdCgroupsManager: if err := deleteSystemdCgroup(p.state.CgroupPath); err != nil { if removalErr == nil { removalErr = errors.Wrapf(err, "error removing pod %s cgroup", p.ID()) @@ -259,7 +259,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool) logrus.Errorf("Error deleting pod %s cgroup %s: %v", p.ID(), p.state.CgroupPath, err) } } - case CgroupfsCgroupsManager: + case define.CgroupfsCgroupsManager: // Delete the cgroupfs cgroup // Make sure the conmon cgroup is deleted first // Since the pod is almost gone, don't bother failing diff --git a/libpod/state.go b/libpod/state.go index e38f820b5..b246b5eac 100644 --- a/libpod/state.go +++ b/libpod/state.go @@ -1,15 +1,6 @@ package libpod -// DBConfig is a set of Libpod runtime configuration settings that are saved -// in a State when it is first created, and can subsequently be retrieved. -type DBConfig struct { - LibpodRoot string - LibpodTmp string - StorageRoot string - StorageTmp string - GraphDriver string - VolumePath string -} +import "github.com/containers/libpod/libpod/config" // State is a storage backend for libpod's current state. // A State is only initialized once per instance of libpod. @@ -37,7 +28,7 @@ type State interface { // root and tmp dirs, and c/storage graph driver. // This is not implemented by the in-memory state, as it has no need to // validate runtime configuration. - GetDBConfig() (*DBConfig, error) + GetDBConfig() (*config.DBConfig, error) // ValidateDBConfig validates the config in the given Runtime struct // against paths stored in the configured database. diff --git a/libpod/state_test.go b/libpod/state_test.go index 5db1f301c..d4a4149f9 100644 --- a/libpod/state_test.go +++ b/libpod/state_test.go @@ -8,6 +8,7 @@ import ( "testing" "time" + "github.com/containers/libpod/libpod/config" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/libpod/lock" "github.com/containers/storage" @@ -52,7 +53,7 @@ func getEmptyBoltState() (s State, p string, m lock.Manager, err error) { } runtime := new(Runtime) - runtime.config = new(RuntimeConfig) + runtime.config = new(config.Config) runtime.config.StorageConfig = storage.StoreOptions{} runtime.lockManager = lockManager diff --git a/libpod/util.go b/libpod/util.go index 5ae5ab491..7bd834e30 100644 --- a/libpod/util.go +++ b/libpod/util.go @@ -10,6 +10,7 @@ import ( "strings" "time" + "github.com/containers/libpod/libpod/config" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/utils" "github.com/fsnotify/fsnotify" @@ -19,10 +20,6 @@ import ( // Runtime API constants const ( - // DefaultTransport is a prefix that we apply to an image name - // to check docker hub first for the image - DefaultTransport = "docker://" - unknownPackage = "Unknown" ) @@ -191,18 +188,18 @@ func programVersion(mountProgram string) (string, error) { } func DefaultSeccompPath() (string, error) { - _, err := os.Stat(SeccompOverridePath) + _, err := os.Stat(config.SeccompOverridePath) if err == nil { - return SeccompOverridePath, nil + return config.SeccompOverridePath, nil } if !os.IsNotExist(err) { - return "", errors.Wrapf(err, "can't check if %q exists", SeccompOverridePath) + return "", errors.Wrapf(err, "can't check if %q exists", config.SeccompOverridePath) } - if _, err := os.Stat(SeccompDefaultPath); err != nil { + if _, err := os.Stat(config.SeccompDefaultPath); err != nil { if !os.IsNotExist(err) { - return "", errors.Wrapf(err, "can't check if %q exists", SeccompDefaultPath) + return "", errors.Wrapf(err, "can't check if %q exists", config.SeccompDefaultPath) } return "", nil } - return SeccompDefaultPath, nil + return config.SeccompDefaultPath, nil } diff --git a/libpod/volume_internal_linux.go b/libpod/volume_internal_linux.go index 4c0332018..70eccbecb 100644 --- a/libpod/volume_internal_linux.go +++ b/libpod/volume_internal_linux.go @@ -3,8 +3,8 @@ package libpod import ( - "io/ioutil" "os/exec" + "strings" "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/rootless" @@ -72,16 +72,10 @@ func (v *Volume) mount() error { mountArgs = append(mountArgs, volDevice, v.config.MountPoint) mountCmd := exec.Command(mountPath, mountArgs...) - errPipe, err := mountCmd.StderrPipe() - if err != nil { - return errors.Wrapf(err, "error getting stderr pipe for mount") - } - if err := mountCmd.Start(); err != nil { - out, err2 := ioutil.ReadAll(errPipe) - if err2 != nil { - return errors.Wrapf(err2, "error reading mount STDERR") - } - return errors.Wrapf(errors.New(string(out)), "error mounting volume %s", v.Name()) + logrus.Debugf("Running mount command: %s %s", mountPath, strings.Join(mountArgs, " ")) + if output, err := mountCmd.CombinedOutput(); err != nil { + logrus.Debugf("Mount failed with %v", err) + return errors.Wrapf(errors.Errorf(string(output)), "error mounting volume %s", v.Name()) } logrus.Debugf("Mounted volume %s", v.Name()) diff --git a/pkg/adapter/containers.go b/pkg/adapter/containers.go index 27fd42899..64550f545 100644 --- a/pkg/adapter/containers.go +++ b/pkg/adapter/containers.go @@ -307,7 +307,11 @@ func (r *LocalRuntime) Log(c *cliconfig.LogsValues, options *logs.LogOptions) er if len(c.InputArgs) > 1 { options.Multi = true } - logChannel := make(chan *logs.LogLine, int(c.Tail)*len(c.InputArgs)+1) + tailLen := int(c.Tail) + if tailLen < 0 { + tailLen = 0 + } + logChannel := make(chan *logs.LogLine, tailLen*len(c.InputArgs)+1) containers, err := shortcuts.GetContainersByContext(false, c.Latest, c.InputArgs, r.Runtime) if err != nil { return err @@ -656,20 +660,25 @@ func (r *LocalRuntime) Start(ctx context.Context, c *cliconfig.StartValues, sigP return exitCode, nil } - if ctrRunning { - fmt.Println(ctr.ID()) - continue - } - // Handle non-attach start - // If the container is in a pod, also set to recursively start dependencies - if err := ctr.Start(ctx, ctr.PodID() != ""); err != nil { - if lastError != nil { - fmt.Fprintln(os.Stderr, lastError) + // Start the container if it's not running already. + if !ctrRunning { + // Handle non-attach start + // If the container is in a pod, also set to recursively start dependencies + if err := ctr.Start(ctx, ctr.PodID() != ""); err != nil { + if lastError != nil { + fmt.Fprintln(os.Stderr, lastError) + } + lastError = errors.Wrapf(err, "unable to start container %q", container) + continue } - lastError = errors.Wrapf(err, "unable to start container %q", container) - continue } - fmt.Println(ctr.ID()) + // Check if the container is referenced by ID or by name and print + // it accordingly. + if strings.HasPrefix(ctr.ID(), container) { + fmt.Println(ctr.ID()) + } else { + fmt.Println(container) + } } return exitCode, lastError } diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go index da5c14948..86d701f7e 100644 --- a/pkg/spec/spec.go +++ b/pkg/spec/spec.go @@ -5,6 +5,8 @@ import ( "strings" "github.com/containers/libpod/libpod" + libpodconfig "github.com/containers/libpod/libpod/config" + "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/cgroups" "github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/sysinfo" @@ -300,7 +302,7 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM blockAccessToKernelFilesystems(config, &g) - var runtimeConfig *libpod.RuntimeConfig + var runtimeConfig *libpodconfig.Config if runtime != nil { runtimeConfig, err = runtime.GetConfig() @@ -321,7 +323,7 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM if err != nil { return nil, err } - if (!cgroup2 || (runtimeConfig != nil && runtimeConfig.CgroupManager != libpod.SystemdCgroupsManager)) && config.Resources.PidsLimit == sysinfo.GetDefaultPidsLimit() { + if (!cgroup2 || (runtimeConfig != nil && runtimeConfig.CgroupManager != define.SystemdCgroupsManager)) && config.Resources.PidsLimit == sysinfo.GetDefaultPidsLimit() { setPidLimit = false } } @@ -417,7 +419,7 @@ func (config *CreateConfig) createConfigToOCISpec(runtime *libpod.Runtime, userM configSpec.Linux.Resources = &spec.LinuxResources{} } - canUseResources := cgroup2 && runtimeConfig != nil && (runtimeConfig.CgroupManager == libpod.SystemdCgroupsManager) + canUseResources := cgroup2 && runtimeConfig != nil && (runtimeConfig.CgroupManager == define.SystemdCgroupsManager) if addedResources && !canUseResources { return nil, errors.New("invalid configuration, cannot specify resource limits without cgroups v2 and --cgroup-manager=systemd") diff --git a/pkg/util/utils.go b/pkg/util/utils.go index 71f3e26dc..633d8a124 100644 --- a/pkg/util/utils.go +++ b/pkg/util/utils.go @@ -3,6 +3,7 @@ package util import ( "fmt" "os" + "os/user" "path/filepath" "regexp" "strings" @@ -440,3 +441,16 @@ func ExitCode(err error) int { return 126 } + +// HomeDir returns the home directory for the current user. +func HomeDir() (string, error) { + home := os.Getenv("HOME") + if home == "" { + usr, err := user.LookupId(fmt.Sprintf("%d", rootless.GetRootlessUID())) + if err != nil { + return "", errors.Wrapf(err, "unable to resolve HOME directory") + } + home = usr.HomeDir + } + return home, nil +} diff --git a/pkg/varlinkapi/containers.go b/pkg/varlinkapi/containers.go index b471ee2cf..94726bbbd 100644 --- a/pkg/varlinkapi/containers.go +++ b/pkg/varlinkapi/containers.go @@ -739,7 +739,7 @@ func (i *LibpodAPI) GetContainersLogs(call iopodman.VarlinkCall, names []string, options := logs.LogOptions{ Follow: follow, Since: sinceTime, - Tail: uint64(tail), + Tail: tail, Timestamps: timestamps, } @@ -747,7 +747,11 @@ func (i *LibpodAPI) GetContainersLogs(call iopodman.VarlinkCall, names []string, if len(names) > 1 { options.Multi = true } - logChannel := make(chan *logs.LogLine, int(tail)*len(names)+1) + tailLen := int(tail) + if tailLen < 0 { + tailLen = 0 + } + logChannel := make(chan *logs.LogLine, tailLen*len(names)+1) containers, err := shortcuts.GetContainersByContext(false, latest, names, i.Runtime) if err != nil { return call.ReplyErrorOccurred(err.Error()) diff --git a/test/e2e/logs_test.go b/test/e2e/logs_test.go index f34d85d76..e25364695 100644 --- a/test/e2e/logs_test.go +++ b/test/e2e/logs_test.go @@ -57,6 +57,18 @@ var _ = Describe("Podman logs", func() { Expect(len(results.OutputToStringArray())).To(Equal(2)) }) + It("podman logs tail zero lines", func() { + logc := podmanTest.Podman([]string{"run", "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"}) + logc.WaitWithDefaultTimeout() + Expect(logc.ExitCode()).To(Equal(0)) + cid := logc.OutputToString() + + results := podmanTest.Podman([]string{"logs", "--tail", "0", cid}) + results.WaitWithDefaultTimeout() + Expect(results.ExitCode()).To(Equal(0)) + Expect(len(results.OutputToStringArray())).To(Equal(0)) + }) + It("podman logs tail 99 lines", func() { logc := podmanTest.Podman([]string{"run", "-dt", ALPINE, "sh", "-c", "echo podman; echo podman; echo podman"}) logc.WaitWithDefaultTimeout() diff --git a/test/e2e/run_selinux_test.go b/test/e2e/run_selinux_test.go index ebc36b7f1..358137aa9 100644 --- a/test/e2e/run_selinux_test.go +++ b/test/e2e/run_selinux_test.go @@ -170,7 +170,7 @@ var _ = Describe("Podman run", func() { setup.WaitWithDefaultTimeout() Expect(setup.ExitCode()).To(Equal(0)) - session := podmanTest.Podman([]string{"exec", "test1", "cat", "/proc/self/attr/current"}) + session := podmanTest.Podman([]string{"exec", "test1", "cat", "/proc/1/attr/current"}) session.WaitWithDefaultTimeout() session1 := podmanTest.Podman([]string{"exec", "test1", "cat", "/proc/self/attr/current"}) session1.WaitWithDefaultTimeout() diff --git a/test/e2e/run_volume_test.go b/test/e2e/run_volume_test.go index c96059787..8e5de85e4 100644 --- a/test/e2e/run_volume_test.go +++ b/test/e2e/run_volume_test.go @@ -364,4 +364,15 @@ var _ = Describe("Podman run with volumes", func() { Expect(session.ExitCode()).To(Equal(0)) Expect(session.OutputToString()).To(Not(ContainSubstring("noexec"))) }) + + It("podman mount with invalid option fails", func() { + volName := "testVol" + volCreate := podmanTest.Podman([]string{"volume", "create", "--opt", "type=tmpfs", "--opt", "device=tmpfs", "--opt", "o=invalid", volName}) + volCreate.WaitWithDefaultTimeout() + Expect(volCreate.ExitCode()).To(Equal(0)) + + volMount := podmanTest.Podman([]string{"run", "--rm", "-v", fmt.Sprintf("%s:/tmp", volName), ALPINE, "ls"}) + volMount.WaitWithDefaultTimeout() + Expect(volMount.ExitCode()).To(Not(Equal(0))) + }) }) diff --git a/test/e2e/start_test.go b/test/e2e/start_test.go index da581f158..47b058845 100644 --- a/test/e2e/start_test.go +++ b/test/e2e/start_test.go @@ -57,15 +57,32 @@ var _ = Describe("Podman start", func() { session = podmanTest.Podman([]string{"container", "start", cid}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(Equal(cid)) + }) + + It("podman container start single container by short id", func() { + session := podmanTest.Podman([]string{"container", "create", "-d", ALPINE, "ls"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + cid := session.OutputToString() + session = podmanTest.Podman([]string{"container", "start", cid[0:10]}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(Equal(cid)) }) It("podman start single container by name", func() { - session := podmanTest.Podman([]string{"create", "-d", "--name", "foobar99", ALPINE, "ls"}) + name := "foobar99" + session := podmanTest.Podman([]string{"create", "-d", "--name", name, ALPINE, "ls"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) - session = podmanTest.Podman([]string{"start", "foobar99"}) + session = podmanTest.Podman([]string{"start", name}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) + if podmanTest.RemoteTest { + Skip("Container-start name check doesn't work on remote client. It always returns the full ID.") + } + Expect(session.OutputToString()).To(Equal(name)) }) It("podman start multiple containers", func() { diff --git a/vendor/github.com/onsi/ginkgo/.travis.yml b/vendor/github.com/onsi/ginkgo/.travis.yml index 72e8ccf0b..9da4c5b5e 100644 --- a/vendor/github.com/onsi/ginkgo/.travis.yml +++ b/vendor/github.com/onsi/ginkgo/.travis.yml @@ -5,6 +5,9 @@ go: - 1.12.x - tip +# allow internal package imports, necessary for forked repositories +go_import_path: github.com/onsi/ginkgo + install: - go get -v -t ./... - go get golang.org/x/tools/cmd/cover diff --git a/vendor/github.com/onsi/ginkgo/CHANGELOG.md b/vendor/github.com/onsi/ginkgo/CHANGELOG.md index aeadb66e0..020496c9d 100644 --- a/vendor/github.com/onsi/ginkgo/CHANGELOG.md +++ b/vendor/github.com/onsi/ginkgo/CHANGELOG.md @@ -1,20 +1,34 @@ +## 1.10.3 + +### Fixes +- Set go_import_path in travis.yml to allow internal packages in forks (#607) [3b721db] +- Add integration test [d90e0dc] +- Fix coverage files combining [e5dde8c] +- A new CLI option: -ginkgo.reportFile <file path> (#601) [034fd25] + +## 1.10.2 + +### Fixes +- speed up table entry generateIt() (#609) [5049dc5] +- Fix. Write errors to stderr instead of stdout (#610) [7bb3091] + ## 1.10.1 -## Fixes +### Fixes - stack backtrace: fix skipping (#600) [2a4c0bd] ## 1.10.0 -## Fixes +### Fixes - stack backtrace: fix alignment and skipping [66915d6] - fix typo in documentation [8f97b93] ## 1.9.0 -## Features +### Features - Option to print output into report, when tests have passed [0545415] -## Fixes +### Fixes - Fixed typos in comments [0ecbc58] - gofmt code [a7f8bfb] - Simplify code [7454d00] diff --git a/vendor/github.com/onsi/ginkgo/config/config.go b/vendor/github.com/onsi/ginkgo/config/config.go index ac55a5ad2..89ec2b29a 100644 --- a/vendor/github.com/onsi/ginkgo/config/config.go +++ b/vendor/github.com/onsi/ginkgo/config/config.go @@ -20,7 +20,7 @@ import ( "fmt" ) -const VERSION = "1.10.1" +const VERSION = "1.10.3" type GinkgoConfigType struct { RandomSeed int64 @@ -53,6 +53,7 @@ type DefaultReporterConfigType struct { Verbose bool FullTrace bool ReportPassed bool + ReportFile string } var DefaultReporterConfig = DefaultReporterConfigType{} @@ -100,6 +101,8 @@ func Flags(flagSet *flag.FlagSet, prefix string, includeParallelFlags bool) { flagSet.BoolVar(&(DefaultReporterConfig.Succinct), prefix+"succinct", false, "If set, default reporter prints out a very succinct report") flagSet.BoolVar(&(DefaultReporterConfig.FullTrace), prefix+"trace", false, "If set, default reporter prints out the full stack trace when a failure occurs") flagSet.BoolVar(&(DefaultReporterConfig.ReportPassed), prefix+"reportPassed", false, "If set, default reporter prints out captured output of passed tests.") + flagSet.StringVar(&(DefaultReporterConfig.ReportFile), prefix+"reportFile", "", "Override the default reporter output file path.") + } func BuildFlagArgs(prefix string, ginkgo GinkgoConfigType, reporter DefaultReporterConfigType) []string { @@ -202,5 +205,9 @@ func BuildFlagArgs(prefix string, ginkgo GinkgoConfigType, reporter DefaultRepor result = append(result, fmt.Sprintf("--%sreportPassed", prefix)) } + if reporter.ReportFile != "" { + result = append(result, fmt.Sprintf("--%sreportFile=%s", prefix, reporter.ReportFile)) + } + return result } diff --git a/vendor/github.com/onsi/ginkgo/extensions/table/table_entry.go b/vendor/github.com/onsi/ginkgo/extensions/table/table_entry.go index 5fa645bce..93f3bc3b0 100644 --- a/vendor/github.com/onsi/ginkgo/extensions/table/table_entry.go +++ b/vendor/github.com/onsi/ginkgo/extensions/table/table_entry.go @@ -22,18 +22,15 @@ func (t TableEntry) generateIt(itBody reflect.Value) { return } - values := []reflect.Value{} + values := make([]reflect.Value, len(t.Parameters)) + iBodyType := itBody.Type() for i, param := range t.Parameters { - var value reflect.Value - if param == nil { - inType := itBody.Type().In(i) - value = reflect.Zero(inType) + inType := iBodyType.In(i) + values[i] = reflect.Zero(inType) } else { - value = reflect.ValueOf(param) + values[i] = reflect.ValueOf(param) } - - values = append(values, value) } body := func() { diff --git a/vendor/github.com/onsi/ginkgo/ginkgo/run_command.go b/vendor/github.com/onsi/ginkgo/ginkgo/run_command.go index 569b6a29c..1d06e08fd 100644 --- a/vendor/github.com/onsi/ginkgo/ginkgo/run_command.go +++ b/vendor/github.com/onsi/ginkgo/ginkgo/run_command.go @@ -5,6 +5,7 @@ import ( "fmt" "math/rand" "os" + "regexp" "strings" "time" @@ -163,17 +164,27 @@ func (r *SpecRunner) combineCoverprofiles(runners []*testrunner.TestRunner) erro fmt.Println("path is " + path) - combined, err := os.OpenFile(filepath.Join(path, r.getCoverprofile()), - os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0666) + combined, err := os.OpenFile( + filepath.Join(path, r.getCoverprofile()), + os.O_WRONLY|os.O_CREATE, + 0666, + ) if err != nil { fmt.Printf("Unable to create combined profile, %v\n", err) return nil // non-fatal error } - for _, runner := range runners { + modeRegex := regexp.MustCompile(`^mode: .*\n`) + for index, runner := range runners { contents, err := ioutil.ReadFile(runner.CoverageFile) + // remove the cover mode line from every file + // except the first one + if index > 0 { + contents = modeRegex.ReplaceAll(contents, []byte{}) + } + if err != nil { fmt.Printf("Unable to read coverage file %s to combine, %v\n", runner.CoverageFile, err) return nil // non-fatal error diff --git a/vendor/github.com/onsi/ginkgo/ginkgo_dsl.go b/vendor/github.com/onsi/ginkgo/ginkgo_dsl.go index 8734c061d..3cbf89a35 100644 --- a/vendor/github.com/onsi/ginkgo/ginkgo_dsl.go +++ b/vendor/github.com/onsi/ginkgo/ginkgo_dsl.go @@ -199,6 +199,11 @@ type Benchmarker interface { // ginkgo bootstrap func RunSpecs(t GinkgoTestingT, description string) bool { specReporters := []Reporter{buildDefaultReporter()} + if config.DefaultReporterConfig.ReportFile != "" { + reportFile := config.DefaultReporterConfig.ReportFile + specReporters[0] = reporters.NewJUnitReporter(reportFile) + return RunSpecsWithDefaultAndCustomReporters(t, description, specReporters) + } return RunSpecsWithCustomReporters(t, description, specReporters) } diff --git a/vendor/github.com/onsi/ginkgo/reporters/junit_reporter.go b/vendor/github.com/onsi/ginkgo/reporters/junit_reporter.go index 89a7c8465..d76e2fe77 100644 --- a/vendor/github.com/onsi/ginkgo/reporters/junit_reporter.go +++ b/vendor/github.com/onsi/ginkgo/reporters/junit_reporter.go @@ -13,6 +13,7 @@ import ( "fmt" "math" "os" + "path/filepath" "strings" "github.com/onsi/ginkgo/config" @@ -141,17 +142,29 @@ func (reporter *JUnitReporter) SpecSuiteDidEnd(summary *types.SuiteSummary) { reporter.suite.Time = math.Trunc(summary.RunTime.Seconds()*1000) / 1000 reporter.suite.Failures = summary.NumberOfFailedSpecs reporter.suite.Errors = 0 - file, err := os.Create(reporter.filename) + if reporter.ReporterConfig.ReportFile != "" { + reporter.filename = reporter.ReporterConfig.ReportFile + fmt.Printf("\nJUnit path was configured: %s\n", reporter.filename) + } + filePath, _ := filepath.Abs(reporter.filename) + dirPath := filepath.Dir(filePath) + err := os.MkdirAll(dirPath, os.ModePerm) + if err != nil { + fmt.Printf("\nFailed to create JUnit directory: %s\n\t%s", filePath, err.Error()) + } + file, err := os.Create(filePath) if err != nil { - fmt.Printf("Failed to create JUnit report file: %s\n\t%s", reporter.filename, err.Error()) + fmt.Fprintf(os.Stderr, "Failed to create JUnit report file: %s\n\t%s", filePath, err.Error()) } defer file.Close() file.WriteString(xml.Header) encoder := xml.NewEncoder(file) encoder.Indent(" ", " ") err = encoder.Encode(reporter.suite) - if err != nil { - fmt.Printf("Failed to generate JUnit report\n\t%s", err.Error()) + if err == nil { + fmt.Fprintf(os.Stdout, "\nJUnit report was created: %s\n", filePath) + } else { + fmt.Fprintf(os.Stderr,"\nFailed to generate JUnit report data:\n\t%s", err.Error()) } } diff --git a/vendor/modules.txt b/vendor/modules.txt index cda4bcd9e..489914a31 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -317,7 +317,7 @@ github.com/morikuni/aec github.com/mrunalp/fileutils # github.com/mtrmac/gpgme v0.0.0-20170102180018-b2432428689c github.com/mtrmac/gpgme -# github.com/onsi/ginkgo v1.10.1 +# github.com/onsi/ginkgo v1.10.3 github.com/onsi/ginkgo/ginkgo github.com/onsi/ginkgo github.com/onsi/ginkgo/config |