diff options
126 files changed, 1599 insertions, 439 deletions
diff --git a/.cirrus.yml b/.cirrus.yml index ad9edd404..4521866d1 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -118,6 +118,11 @@ gating_task: - '/usr/local/bin/entrypoint.sh vendor' - 'cd /go/src/github.com/containers/libpod && ./hack/tree_status.sh' + # This task builds Podman with different buildtags to ensure the build does + # not break. + build_script: + - '/usr/local/bin/entrypoint.sh clean podman BUILDTAGS="exclude_graphdriver_devicemapper selinux seccomp"' + build_each_commit_task: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b1b166fef..3778d6d7d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -329,10 +329,16 @@ author hold special privileges on the github repository. Others can be used by unintentionally. Instead, just write ``LGTM``, or spell it out. -* ``[skip ci]``: Within the HEAD commit will cause Cirrus CI to ***NOT*** execute - tests on the PR. This is useful in basically two cases: 1) You're still working - and don't want to waste resources. 2) You haven't modified any code that would - be exercised by the tests. For example, documentation updates (outside of code). +* ``/hold`` and ``/unhold``: Override the automatic handling of a request. Either + put it on hold (no handling) or remove the hold (normal handling). + +* ``[ci skip]``: [Adding `[ci skip]` within the HEAD commit](https://cirrus-ci.org/guide/writing-tasks/#conditional-task-execution) + will cause Cirrus CI to ***NOT*** execute tests for the PR or after merge. This + is useful in only one instance: Your changes are absolutely not exercised by + any test. For example, documentation changes. ***IMPORTANT NOTE*** **Other + automation may interpret the lack of test results as "PASSED" and unintentionall + merge a PR. Consider also using `/hold` in a comment, to add additional + protection.** [The complete list may be found on the command-help page.](https://prow.k8s.io/command-help) However, not all commands are implemented for this repository. If in doubt, ask a maintainer. @@ -1,6 +1,6 @@ GO ?= go DESTDIR ?= / -EPOCH_TEST_COMMIT ?= 4406e1cfeed18fe89c0ad4e20a3c3b2f4b9ffcae +EPOCH_TEST_COMMIT ?= 174e8997aa0d8fc648564a9ac2a79ab786e87362 HEAD ?= HEAD CHANGELOG_BASE ?= HEAD~ CHANGELOG_TARGET ?= HEAD @@ -82,6 +82,9 @@ includes tables showing Docker commands and their Podman equivalent commands. **[Tutorials](docs/tutorials)** Tutorials on using Podman. +**[Remote Client](remote_client.md)** +A brief how-to on using the Podman remote-client. + **[Release Notes](RELEASE_NOTES.md)** Release notes for recent Podman versions diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index b8b475362..0bacad0d7 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,74 @@ # Release Notes +## 1.1.0 +### Features +- Added `--latest` and `--all` flags to `podman mount` and `podman umount` +- Rootless Podman can now forward ports into containers (using the same `-p` and `-P` flags as root Podman) +- Rootless Podman will now pull some configuration options (for example, OCI runtime path) from the default root `libpod.conf` if they are not explicitly set in the user's own `libpod.conf` ([#2174](https://github.com/containers/libpod/issues/2174)) +- Added an alias `-f` for the `--format` flag of the `podman info` and `podman version` commands +- Added an alias `-s` for the `--size` flag of the `podman inspect` command +- Added the `podman system info` and `podman system prune` commands +- Added the `podman cp` command to copy files between containers and the host ([#613](https://github.com/containers/libpod/issues/613)) +- Added the `--password-stdin` flag to `podman login` +- Added the `--all-tags` flag to `podman pull` +- The `--rm` and `--detach` flags can now be used together with `podman run` +- The `podman start` and `podman run` commands for containers in pods will now start dependency containers if they are stopped +- Added the `podman system renumber` command to handle lock changes +- The `--net=host` and `--dns` flags for `podman run` and `podman create` no longer conflict +- Podman now handles mounting the shared /etc/resolv.conf from network namespaces created by `ip netns add` when they are passed in via `podman run --net=ns:` + +### Bugfixes +- Fixed a bug with `podman inspect` where different information would be returned when the container was running versus when it was stopped +- Fixed a bug where errors in Go templates passed to `podman inspect` were silently ignored instead of reported to the user ([#2159](https://github.com/containers/libpod/issues/2159)) +- Fixed a bug where rootless Podman with `--pid=host` containers was incorrectly masking paths in `/proc` +- Fixed a bug where full errors starting rootless `Podman` were not reported when a refresh was requested +- Fixed a bug where Podman would override the config file-specified storage driver with the driver the backing database was created with without warning users +- Fixed a bug where `podman prune` would prune all images not in use by a container, as opposed to only untagged images, by default ([#2192](https://github.com/containers/libpod/issues/2192)) +- Fixed a bug where `podman create --quiet` and `podman run --quiet` were not properly suppressing output +- Fixed a bug where the `table` keyword in Go template output of `podman ps` was not working ([#2221](https://github.com/containers/libpod/issues/2221)) +- Fixed a bug where `podman inspect` on images pulled by digest would double-print `@sha256` in output when printing digests ([#2086](https://github.com/containers/libpod/issues/2086)) +- Fixed a bug where `podman container runlabel` will return a non-0 exit code if the label does not exist +- Fixed a bug where container state was always reset to Created after a reboot ([#1703](https://github.com/containers/libpod/issues/1703)) +- Fixed a bug where `/dev/pts` was unconditionally overridden in rootless Podman, which was unnecessary except in very specific cases +- Fixed a bug where Podman run as root was ignoring some options in `/etc/containers/storage.conf` ([#2217](https://github.com/containers/libpod/issues/2217)) +- Fixed a bug where Podman cleanup processes were not being given the proper OCI runtime path if a custom one was specified +- Fixed a bug where `podman images --filter dangling=true` would crash if no dangling images were present ([#2246](https://github.com/containers/libpod/issues/2246)) +- Fixed a bug where `podman ps --format "{{.Mounts}}"` would not display a container's mounts ([#2238](https://github.com/containers/libpod/issues/2238)) +- Fixed a bug where `podman pod stats` was ignoring Go templates specified by `--format` ([#2258](https://github.com/containers/libpod/issues/2258)) +- Fixed a bug where `podman generate kube` would fail on containers with `--user` specified ([#2304](https://github.com/containers/libpod/issues/2304)) +- Fixed a bug where `podman images` displayed incorrect output for images pulled by digest ([#2175](https://github.com/containers/libpod/issues/2175)) +- Fixed a bug where `podman port` and `podman ps` did not properly display ports if the container joined a network namespace from a pod or another container ([#846](https://github.com/containers/libpod/issues/846)) +- Fixed a bug where detaching from a container using the detach keys would cause Podman to hang until the container exited +- Fixed a bug where `podman create --rm` did not work with `podman start --attach` +- Fixed a bug where invalid named volumes specified in `podman create` and `podman run` could cause segfaults ([#2301](https://github.com/containers/libpod/issues/2301)) +- Fixed a bug where the `runtime` field in `libpod.conf` was being ignored. `runtime` is legacy and deprecated, but will continue to be respected for the forseeable future +- Fixed a bug where `podman login` would sometimes report it logged in successfully when it did not +- Fixed a bug where `podman pod create` would not error on receiving unused CLI argument +- Fixed a bug where rootless `podman run` with the `--pod` argument would fail if the pod was stopped +- Fixed a bug where `podman images` did not print a trailing newline when not invoked on a TTY ([#2388](https://github.com/containers/libpod/issues/2388)) +- Fixed a bug where the `--runtime` option was sometimes not overriding `libpod.conf` +- Fixed a bug where `podman pull` and `podman runlabel` would sometimes exit with 0 when they should have exited with an error ([#2405](https://github.com/containers/libpod/issues/2405)) +- Fixed a bug where rootless `podman export -o` would fail ([#2381](https://github.com/containers/libpod/issues/2381)) +- Fixed a bug where read-only volumes would fail in rootless Podman when the volume originated on a filesystem mounted `nosuid`, `nodev`, or `noexec` ([#2312](https://github.com/containers/libpod/issues/2312)) +- Fixed a bug where some files used by checkpoint and restore received improper SELinux labels ([#2334](https://github.com/containers/libpod/issues/2334)) +- Fixed a bug where Podman's volume path was not properly changed when containers/storage changed location ([#2395](https://github.com/containers/libpod/issues/2395)) + +### Misc +- Podman migrated to a new, shared memory locking model in this release. As part of this, if you are running Podman with pods or dependency containers (e.g. `--net=container:`), you should run the `podman system renumber` command to migrate your containers to the new model - please reference the `podman-system-renumber(1)` man page for further details +- Podman migrated to a new command-line parsing library, and the output format of help and usage text has somewhat changed as a result +- Updated Buildah to v1.7, picking up a number of bugfixes +- Updated containers/image library to v1.5, picking up a number of bugfixes and performance improvements to pushing images +- Updated containers/storage library to v1.10, picking up a number of bugfixes +- Work on the remote Podman client for interacting with Podman remotely over Varlink is progressing steadily, and many image and pod commands are supported +- Added path masking to mounts with the `:z` and `:Z` options, preventing users from accidentally performing an SELinux relabel of their entire home directory +- The `podman container runlabel` command will not pull an image if it does not contain the requested label +- Many commands' usage information now includes examples +- `podman rm` can now delete containers in containers/storage, which can be used to resolve some situations where Podman fails to remove a container +- The `podman search` command now searches multiple registries in parallel for improved performance +- The `podman build` command now defaults `--pull-always` to true +- Containers which share a network namespace (for example, when in a pod) will now share /etc/hosts and /etc/resolv.conf between all containers in the pod, causing changes in one container to propogate to all containers sharing their networks +- The `podman rm` and `podman rmi` commands now return 1 (instead of 127) when all specified container or images are missing + ## 1.0.0 ### Features - The `podman exec` command now includes a `--workdir` option to set working directory for the executed command diff --git a/changelog.txt b/changelog.txt index 8ee11cdc4..803aad796 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,388 @@ +- Changelog for v1.1.0 (2019-02-26) + * Vendor in latest buildah 1.7.1 + * volume: do not create a volume if there is a bind + * Only remove image volumes when removing containers + * Fix podman logs -l + * start pod containers recursively + * Update release notes for v1.1.0 + * vendor containers/image v1.5 + * Record when volume path is explicitly set in config + * Add debug information when overriding paths with the DB + * Add path for named volumes to `podman info` + * Add volume path to default libpod.conf (and manpage) + * Validate VolumePath against DB configuration + * When location of c/storage root changes, set VolumePath + * docs: cross-reference `podman-{generate,play}-kube` + * README: refine "Out of scope" section + * oci: improve error message when the OCI runtime is not found + * Label CRIU log files correctly + * Add num_locks to the default libpod config + * podman-remote pod pause|unpause|restart + * podman: fix ro bind mounts if no* opts are on the source + * Change exit code to 1 on podman rmi nosuch image + * README.md: rephrase Buildah description + * README: update "out of scope" section + * Change exit code to 1 on podman rm nosuch container + * podman-remote create|ps + * remove duplicate commands in main + * issue template: run `podman info --debug` + * Fix play to show up in podman help + * Switch defaults for podman build versus buildah + * In shared networkNS /etc/resolv.conf&/etc/hosts should be shared + * Allow dns settings with --net=host + * Fix up handling of user defined network namespaces + * Enable more podman-remote pod commands + * tests, rootless: use relative path for export test + * rootless: force same cwd when re-execing + * Vendor Buildah v1.7 + * Exit with errors not just logging error + * cmd: support rootless mode for cp command + * hide --latest on the remote-client + * Improve command line validation + * make remote-client error messaging more robust + * podman: --runtime has higher priority on runtime_path + * podman-remote pod inspect|exists + * Cirrus: Install Go 1.11 on Ubuntu VMs + * Cirrus: Add 20m extra timeout for Ubuntu + * Introduce how to start to hack on libpod. + * update: remove duplicate newline + * Fix typo in comment + * podman-remote load image + * Do not make renumber shut down the runtime + * Add podman system renumber command + * Add ability to get a runtime that renumbers + * Recreate SHM locks when renumbering on count mismatch + * Move RenumberLocks into runtime init + * Remove locks from volumes + * Expand renumber to also renumber pod locks + * Add ability to rewrite pod configs in the database + * Add initial version of renumber backend + * Add a function for overwriting container config + * enable podman-remote pod rm + * vendor containers/image v1.4 + * Adjust LISTEN_PID for reexec in varlink mode + * Update c/storage vendor to v1.10 release + * add newline to images output + * podman-remote save [image] + * hack/tree_status.sh: preserve new lines + * remove duplicate kill from `podman --help` + * iopodman.SearchImages: add ImageSearchFilter to Varlink API + * image.SearchImages: use SearchFilter type + * SearchImages: extend API with filter parameter + * podman-search: refactor code to libpod/image/search.go + * podman-search: run in parallel + * Ensure that userns is created for stopped rootless pods + * Podman pod create now errors on receiving CLI args + * podman-remote pull + * Don't start running dependencies + * Fifth chunk of Cobra Examples + * Add 4th chunk of Cobra Examples + * OpenTracing support added to start, stop, run, create, pull, and ps + * packer: Make Makefile host arch sensitive + * Add 3rd chunk of Cobra examples + * pod infra container is started before a container in a pod is run, started, or attached. + * Add registry name to fields returned by varlink image search + * Second chunk of Cobra help + * podman: honor --storage-opt again + * docs: mention the new OCI runtime configuration + * libpod: honor runtime_path from libpod.conf + * rootless: open the correct file + * Fix `podman login` lying problem + * Fix error code retrieval for podman start --attach + * Enable --rm with --detach + * Add examples for Cobra + * Add tlsVerify bool to SearchImage for varlink + * Fix volume handling in podman + * enable podman-remote volume prune + * add build to main and as subcommand to image + * --password-stdin flag in `podman login` + * 'podman cp' copy between host and container + * podman-remote build + * Vendor in latest c/storage and c/image + * show container ports of network namespace + * podman-remote volume inspect|ls + * build varlink without GOPATH + * completions: add --pod to run/create + * Parse fq name correctly for images + * Try disabling --rm on notify_socket test + * podman-remote push + * get_ci_vm : allow running without sudo + * Only build varlink when buildtag is available + * Remove a lot of '--rm' options from unit tests + * Address review comments on #2319 + * Retain a copy of container exit file on cleanup + * Fix manual detach from containers to not wait for exit + * varlink: Rename `SearchImage` to `SearchImages` + * varlink: Rename `ContainerInList` to `Container` + * varlink: Rename `ImageInList` to `Image` + * varlink: Simplify GetVersion() call + * varlink: Return all times in RFC 3339 format + * Makefile: Don't include quotes around GIT_COMMIT + * varlink: Remove the Ping() method + * podman: Show error when creating varlink listener failed + * varlink: Remove `NotImplemented` type + * Don't show global flags except for podman command + * podman-remote volume rm + * Remove urfave/cli from libpod + * podman-remote volume create + * Separate remote and local commands + * lock and sync container before checking mountpoint + * oci: do not set XDG_RUNTIME_DIR twice + * pod: drop not valid check for rootless + * Podman pod stats -- fix GO template output + * Add troubleshooting information about running a rootless containers. + * Add --all-tags to pull command + * Add common_test.go to single test instructions + * Remove container from storage on --force + * do not crash when displaying dangling images + * Add volume mounts to PS output + * Update image-trust man with further comments + * Migrate to cobra CLI + * Remove some dead type declarations + * Fix down/missing registry.access.redhat.com + * cleanup: use the correct runtime + * make vendor: always check for latest vndr + * install.md: add section about vendoring + * Add varlink generate to the make documentation + * Mention OSes that pass the build + * Generate make helping message dynamicaly. + * Makefile: minor fix to reenable system tests + * Add StartPeriod to cmd/podman/docker.HealthConfig + * Unconditionally refresh storage options from config + * rootless: do not override /dev/pts if not needed + * Fix handling of memory limits via varlink + * Add documentation on running systemd on SELinux systems + * Cirrus: add vendor_check_task + * cleanup vendor directory + * Revert "Vendor containers/buildah" + * e2e tests: sigproxy: fix rare hang condition + * Preserve exited state across reboot + * Apply 50min timeout to integration tests + * Capatilize all usage and descriptions + * Add podman system prune and info commands + * podman-remote import|export + * tests: allow to override the OCI runtime + * rootless: copy some settings from the global configuration + * Vendor containers/buildah + * Increase e2e info/json test exit timeout + * Touch up image-trust man + * Rework Podman description + * vendor latest containers/image + * Reduce Dockerfile based build time for libpod. + * libpod/image: Use RepoDigests() in Inspect() + * add Pod Manager References + * Add support for short option -f in podman version + * Add support for short option -s in podman inspect + * Add support for short option -f + * Changes to container runlabel for toolbox project + * Fix regression in ps with custom format + * Set SELinux type on bin/podman after install + * Cirrus: Add RHEL-7 testing + * For consistency in usage output the verbs changed from 3rd person to 1st person. + * podman image prune -- implement all flag + * Alter varlink API for ListContainerMounts to return a map + * Make --quiet work in podman create/run + * apparmor: don't load default profile in rootless mode + * Cirrus: Enable AppArmor build and test + * Update ArchLinux installation instructions + * tutorials: describe how to use podman in updates-testing + * [skip ci] Cirrus: Container for tracking image use + * Cirrus: Use freshly built images + * remove sudo + * Vendor in latest containers/storage + * Show a better error message when podman info fails during a refresh + * enable podman-remote version + * Update transfer.md and commands.md to add missing commands. + * rootless: support port redirection from the host + * Mask unimplemeted commands for remote client + * Vendor in latest opencontainers/selinux + * podman-remote inspect + * Vendor in latest containers/storage + * rootless: fix --pid=host without --privileged + * Do not unmarshal into c.config.Spec + * podman-inspect: don't ignore errors + * Add openSUSE Kubic to install.md + * cirrus: Record start/end time of important things + * Cirrus: Consolidate VM image names in once place + * Update README for v1.0.0 + * Installing podman + * Ensure that wait exits on state transition + * Vendor in containers/storage + * Add --latest and --all to podman mount/umount + * Cleanup coverity scan issues + * Embed runtime struct in super localRuntime + * Collaberative podman-remote container exists + * Fix up `image sign` in PR 2108 + * add support for podman-remote history + * Rename localRuntime to runtime in cmd/podman + * podman remote integrations tests + * podman remote client -- add rmi + * Run integrations test with remote-client + * [skip ci] Hack: Fix get_ci_vm.sh w/ gcloud ssh/scp + * Update master branch with v1.0 changes from 1.0 branch + * Add local storage.conf example to troubleshoot + * config: store the runtime used to create each container + * oci: allow to define multiple OCI runtimes + * libpod: allow multiple oci runtimes + * Remove imageParts.{isTagged,registry,name,tag} + * Clarify comments about isRegistry a bit. + * Use imageParts.unnormalizedRef in GetImageBaseName + * FIXME? Introduce imageParts.suspiciousRefNameTagValuesForSearch + * Use imageParts.referenceWithRegistry in Image.getLocalImage + * Don't try to look up local images with an explicit :latest suffix + * Return a reference.Named from normalizedTag + * Use reference.TagNameOnly instead of manually adding imageParts.tag in normalizeTag + * Use imageParts.normalizedReference in normalizeTag + * Add imageParts.normalizedReference() + * Use imageparts.referenceWithRegistry in normalizeTag + * Remove no longer used imageParts.assemble() + * Use getPullRefPair / getSinglePullRefPairGoal in pullGoalFromPossiblyUnqualifiedName + * Use imageParts.referenceWithRegistry in pullGoalFromPossiblyUnqualifiedName + * Use imageParts.referenceWithRegistry in getPullRefPair + * Add imageParts.referenceWithRegistry + * Don't use imageParts.assemble when pulling from a qualified name + * Reorganize normalizeTag + * Simplify pullGoalFromPossiblyUnqualifiedName + * Remove imageParts.transport + * Simplify pullGoalFromPossiblyUnqualifiedName + * Inline imageParts.assembleWithTransport into callers + * Record the original reference.Named in imageParts + * Drop image.DecomposeString, make image.Parts private imageParts again + * Don't call image.DecomposeString in imageInListToContainerImage + * Add bridge support, for the varlink connection + * Add troubleshooting statement for homedirs mounted noexec + * Set default storage options from mounts.conf file. + * podman play kube: add containers to pod + * Add darwin support for remote-client + * vendor: update everything + * vendor make target + * rootless: create the userns immediately when creating a new pod + * rootless: join both userns and mount namespace with --pod + * spec: add nosuid,noexec,nodev to ro bind mount + * Use multi-arch images in test case scripts + * Add varlink support for prune + * Replace tab with spaces in MarshalIndent in libpod + * Remove one more usage of encoding/json in libpod + * Update vendor.conf for jsoniter vendor changes + * Move all libpod/ JSON references over to jsoniter + * Update json-iterator vendor to v1.1.5 + * Remove easyjson in preparation for switch to jsoniter + * remote-client support for images + * Move python code from contrib to it's own repo python-podman + * Use defaults if paths are not specified in storage.conf + * (Minor) Cirrus: Print timestamp at start + * fix up sigstore path + * Trivial readme updates + * podman: bump RLIMIT_NOFILE also without CAP_SYS_RESOURCE + * Fix handling of nil volumes + * sign: make all error messages lowercase + * sign: use filepath.Join instead of fmt.Sprintf + * createconfig: always cleanup a rootless container + * Fix 'image trust' from PR1899 + * libpod/image: Use ParseNormalizedNamed in RepoDigests + * apparmor: apply default profile at container initialization + * Fix up image sign and trust + * If you fail to open shm lock then attempt to create it + * List the long variant of each option before its shorter counterpart + * Use existing interface to request IP address during restore + * Added checkpoint/restore test for same IP + * Enable checkpoint test with established TCP connections + * .github/ISSUE_TEMPLATE: Suggest '/kind bug' and '/kind feature' + * pkg/hooks/exec: Include failed command in hook errors + * hooks/exec/runtimeconfigfilter: Log config changes + * hooks: Add pre-create hooks for runtime-config manipulation + * Add Validate completions + * Add a --workdir option to 'podman exec' + * Default --sig-proxy to true for 'podman start --attach' + * Test that 'podman start --sig-proxy' does not work without --attach + * [WIP]Support podman image sign + * vendor latest buildah + * Honor image environment variables with exec + * Minor: Remove redundant basename command in ooe.sh + * Rename libpod.Config back to ContainerConfig + * Add ability to build golang remote client + * vendor latest buildah + * Add the configuration file used to setup storage to podman info + * Address lingering review comments from SHM locking PR + * podman: set umask to 022 + * podman-login: adhere to user input + * Vendor in latest containers/buildah code + * Rootless with shmlocks was not working. + * Readd Python testing + * Update vendor of runc + * [skip ci] Docs: Add Bot Interactions section + * container runlabel NAME implementation + * Bump time for build_each_commit step + * Move lock init after tmp dir is populated properly + * DO NOT MERGE temporarily remove python tests + * When refreshing libpod, if SHM locks exist, remove them + * Ensure different error messages and creating/opening locks + * Update unit tests to use in-memory lock manager + * Remove runtime lockDir and add in-memory lock manager + * Convert pods to SHM locks + * Convert containers to SHM locking + * Add lock manager to libpod runtime + * Move to POSIX mutexes for SHM locks + * Disable lint on SHMLock struct + * Refactor locks package to build on non-Linux + * Add an SHM-backed Lock Manager implementation + * Add interface for libpod multiprocess locks + * Improve documentation and unit tests for SHM locks + * Propogate error codes from SHM lock creation and open + * Add mutex invariant to SHM semaphores. + * Initial skeleton of in-memory locks + * add container-init support + * If local storage file exists, then use it rather then defaults. + * vendor in new containers/storage + * Fix completions + * Touch up some troubleshooting nits + * Warn on overriding user-specified storage driver w/ DB + * Log container command before starting the container + * Use sprintf to generate port numbers while committing + * Add troubleshooting for sparse files + * Fix handling of symbolic links + * podman build is not using the default oci-runtime + * Re-enable checkpoint/restore CI tests on Fedora + * Fixes to handle /dev/shm correctly. + * rootless tests using stop is more reliable + * Allow alias for list, ls, ps to work + * Refactor: use idtools.ParseIDMap instead of bundling own version + * cirrus: Use updated images including new crui + * Switch all referencs to image.ContainerConfig to image.Config + * Allow users to specify a directory for additonal devices + * Change all 'can not' to 'cannot' for proper usage + * Invalid index for array + * Vendor in latest psgo code to fix race conditions + * test: add test for rootless export + * export: fix usage with rootless containers + * rootless: add function to join user and mount namespace + * libpod: always store the conmon pid file + * Use existing CRIU packages in CI setup + * skip test for blkio.weight when kernel does not support it + * Add Play + * Cirrus: Skip build all commits test on master + * prepare for move to validate on 1.11 only + * [skip ci] Gate: Update docs w/ safer local command + * Support podman image trust command + * Makefile: validate that each commit can at least build + * perf test a stress test to profile CPU load of podman + * all flakes must die + * Add information on --restart + * generate service object inline + * Cirrus: One IRC notice only + * docs/tutorials: add a basic network config + * display proper error when rmi -fa with infra containers + * add --get-login command to podman-login. + * Show image only once with images -q + * Add script to create CI VMs for debugging + * Cirrus: Migrate PAPR testing of F28 to Cirrus + * Skip checkpoint tests on Fedora <30 + * Cirrus: Add text editors to cache-images + * Bump gitvalidation epoch + * Bump to v0.12.2-dev + * Clean up some existing varlink endpoints + * mount: allow mount only when using vfs + - Changelog for v1.0.0 (2018-1-11) * Update release notes for v1.0 * Remove clientintegration from Makefile diff --git a/cmd/podman/attach.go b/cmd/podman/attach.go index 074675e45..a22aa92a1 100644 --- a/cmd/podman/attach.go +++ b/cmd/podman/attach.go @@ -14,7 +14,7 @@ var ( attachCommand cliconfig.AttachValues attachDescription = "The podman attach command allows you to attach to a running container using the container's ID or name, either to view its ongoing output or to control it interactively." _attachCommand = &cobra.Command{ - Use: "attach", + Use: "attach [flags] CONTAINER", Short: "Attach to a running container", Long: attachDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/build.go b/cmd/podman/build.go index e40e35cb5..cfeabfb4e 100644 --- a/cmd/podman/build.go +++ b/cmd/podman/build.go @@ -27,7 +27,7 @@ var ( namespaceValues buildahcli.NameSpaceResults _buildCommand = &cobra.Command{ - Use: "build", + Use: "build [flags] CONTEXT", Short: "Build an image using instructions from Dockerfiles", Long: buildDescription, RunE: func(cmd *cobra.Command, args []string) error { @@ -53,7 +53,7 @@ func init() { flags.SetInterspersed(false) budFlags := buildahcli.GetBudFlags(&budFlagsValues) - flag := budFlags.Lookup("pull-always") + flag := budFlags.Lookup("pull") flag.Value.Set("true") flag.DefValue = "true" layerFlags := buildahcli.GetLayerFlags(&layerValues) diff --git a/cmd/podman/checkpoint.go b/cmd/podman/checkpoint.go index c9de5638b..367065766 100644 --- a/cmd/podman/checkpoint.go +++ b/cmd/podman/checkpoint.go @@ -21,7 +21,7 @@ var ( Checkpoints one or more running containers. The container name or ID can be used. ` _checkpointCommand = &cobra.Command{ - Use: "checkpoint", + Use: "checkpoint [flags] CONTAINER [CONTAINER...]", Short: "Checkpoints one or more containers", Long: checkpointDescription, RunE: func(cmd *cobra.Command, args []string) error { @@ -32,9 +32,9 @@ var ( Args: func(cmd *cobra.Command, args []string) error { return checkAllAndLatest(cmd, args, false) }, - Example: `podman checkpoint --keep ctrID - podman checkpoint --all - podman checkpoint --leave-running --latest`, + Example: `podman container checkpoint --keep ctrID + podman container checkpoint --all + podman container checkpoint --leave-running --latest`, } ) diff --git a/cmd/podman/cleanup.go b/cmd/podman/cleanup.go index d68255aa2..fbbd337a7 100644 --- a/cmd/podman/cleanup.go +++ b/cmd/podman/cleanup.go @@ -18,7 +18,7 @@ var ( Cleans up mount points and network stacks on one or more containers from the host. The container name or ID can be used. This command is used internally when running containers, but can also be used if container cleanup has failed when a container exits. ` _cleanupCommand = &cobra.Command{ - Use: "cleanup", + Use: "cleanup [flags] CONTAINER [CONTAINER...]", Short: "Cleanup network and mountpoints of one or more containers", Long: cleanupDescription, RunE: func(cmd *cobra.Command, args []string) error { @@ -60,7 +60,7 @@ func cleanupCmd(c *cliconfig.CleanupValues) error { for _, ctr := range cleanupContainers { hadError := false if c.Remove { - if err := runtime.RemoveContainer(ctx, ctr, false, false); err != nil { + if err := runtime.RemoveContainer(ctx, ctr, false, true); err != nil { if lastError != nil { fmt.Fprintln(os.Stderr, lastError) } diff --git a/cmd/podman/cliconfig/commands.go b/cmd/podman/cliconfig/commands.go index 7d1e762d9..3361c14b8 100644 --- a/cmd/podman/cliconfig/commands.go +++ b/cmd/podman/cliconfig/commands.go @@ -1,5 +1,7 @@ package cliconfig +import "github.com/sirupsen/logrus" + // GlobalIsSet is a compatibility method for urfave func (p *PodmanCommand) GlobalIsSet(opt string) bool { flag := p.PersistentFlags().Lookup(opt) @@ -22,9 +24,13 @@ func (p *PodmanCommand) IsSet(opt string) bool { func (p *PodmanCommand) Bool(opt string) bool { flag := p.Flags().Lookup(opt) if flag == nil { + logrus.Errorf("Could not find flag %s", opt) return false } - val, _ := p.Flags().GetBool(opt) + val, err := p.Flags().GetBool(opt) + if err != nil { + logrus.Errorf("Error getting flag %s: %v", opt, err) + } return val } @@ -32,9 +38,13 @@ func (p *PodmanCommand) Bool(opt string) bool { func (p *PodmanCommand) String(opt string) string { flag := p.Flags().Lookup(opt) if flag == nil { + logrus.Errorf("Could not find flag %s", opt) return "" } - val, _ := p.Flags().GetString(opt) + val, err := p.Flags().GetString(opt) + if err != nil { + logrus.Errorf("Error getting flag %s: %v", opt, err) + } return val } @@ -42,9 +52,13 @@ func (p *PodmanCommand) String(opt string) string { func (p *PodmanCommand) StringArray(opt string) []string { flag := p.Flags().Lookup(opt) if flag == nil { + logrus.Errorf("Could not find flag %s", opt) return []string{} } - val, _ := p.Flags().GetStringArray(opt) + val, err := p.Flags().GetStringArray(opt) + if err != nil { + logrus.Errorf("Error getting flag %s: %v", opt, err) + } return val } @@ -52,9 +66,13 @@ func (p *PodmanCommand) StringArray(opt string) []string { func (p *PodmanCommand) StringSlice(opt string) []string { flag := p.Flags().Lookup(opt) if flag == nil { + logrus.Errorf("Could not find flag %s", opt) return []string{} } - val, _ := p.Flags().GetStringSlice(opt) + val, err := p.Flags().GetStringSlice(opt) + if err != nil { + logrus.Errorf("Error getting flag %s: %v", opt, err) + } return val } @@ -62,9 +80,13 @@ func (p *PodmanCommand) StringSlice(opt string) []string { func (p *PodmanCommand) Int(opt string) int { flag := p.Flags().Lookup(opt) if flag == nil { + logrus.Errorf("Could not find flag %s", opt) return 0 } - val, _ := p.Flags().GetInt(opt) + val, err := p.Flags().GetInt(opt) + if err != nil { + logrus.Errorf("Error getting flag %s: %v", opt, err) + } return val } @@ -72,9 +94,13 @@ func (p *PodmanCommand) Int(opt string) int { func (p *PodmanCommand) Uint(opt string) uint { flag := p.Flags().Lookup(opt) if flag == nil { + logrus.Errorf("Could not find flag %s", opt) return 0 } - val, _ := p.Flags().GetUint(opt) + val, err := p.Flags().GetUint(opt) + if err != nil { + logrus.Errorf("Error getting flag %s: %v", opt, err) + } return val } @@ -82,9 +108,13 @@ func (p *PodmanCommand) Uint(opt string) uint { func (p *PodmanCommand) Int64(opt string) int64 { flag := p.Flags().Lookup(opt) if flag == nil { + logrus.Errorf("Could not find flag %s", opt) return 0 } - val, _ := p.Flags().GetInt64(opt) + val, err := p.Flags().GetInt64(opt) + if err != nil { + logrus.Errorf("Error getting flag %s: %v", opt, err) + } return val } @@ -92,9 +122,13 @@ func (p *PodmanCommand) Int64(opt string) int64 { func (p *PodmanCommand) Uint64(opt string) uint64 { flag := p.Flags().Lookup(opt) if flag == nil { + logrus.Errorf("Could not find flag %s", opt) return 0 } - val, _ := p.Flags().GetUint64(opt) + val, err := p.Flags().GetUint64(opt) + if err != nil { + logrus.Errorf("Error getting flag %s: %v", opt, err) + } return val } @@ -102,8 +136,12 @@ func (p *PodmanCommand) Uint64(opt string) uint64 { func (p *PodmanCommand) Float64(opt string) float64 { flag := p.Flags().Lookup(opt) if flag == nil { + logrus.Errorf("Could not find flag %s", opt) return 0 } - val, _ := p.Flags().GetFloat64(opt) + val, err := p.Flags().GetFloat64(opt) + if err != nil { + logrus.Errorf("Error getting flag %s: %v", opt, err) + } return val } diff --git a/cmd/podman/commands.go b/cmd/podman/commands.go index fadcca689..2f9a9cfe2 100644 --- a/cmd/podman/commands.go +++ b/cmd/podman/commands.go @@ -18,7 +18,7 @@ func getMainCommands() []*cobra.Command { _execCommand, _generateCommand, _playCommand, - _psCommand, + &_psCommand, _loginCommand, _logoutCommand, _logsCommand, @@ -27,11 +27,9 @@ func getMainCommands() []*cobra.Command { _portCommand, _refreshCommand, _restartCommand, - _restoreCommand, _rmCommand, _runCommand, _searchCommand, - _signCommand, _startCommand, _statsCommand, _stopCommand, @@ -50,13 +48,16 @@ func getMainCommands() []*cobra.Command { // Commands that the local client implements func getImageSubCommands() []*cobra.Command { return []*cobra.Command{ - _loadCommand, _signCommand, } } // Commands that the local client implements func getContainerSubCommands() []*cobra.Command { + + var _listSubCommand = _psCommand + _listSubCommand.Use = "list" + return []*cobra.Command{ _attachCommand, _checkpointCommand, @@ -67,8 +68,8 @@ func getContainerSubCommands() []*cobra.Command { _execCommand, _exportCommand, _killCommand, + &_listSubCommand, _logsCommand, - _psCommand, _mountCommand, _pauseCommand, _portCommand, diff --git a/cmd/podman/commit.go b/cmd/podman/commit.go index d8ced0e36..43c54c320 100644 --- a/cmd/podman/commit.go +++ b/cmd/podman/commit.go @@ -25,7 +25,7 @@ var ( and make changes to the instructions with the --change flag.` _commitCommand = &cobra.Command{ - Use: "commit", + Use: "commit [flags] CONTAINER IMAGE", Short: "Create new image based on the changed container", Long: commitDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/common.go b/cmd/podman/common.go index e297f3921..e980e10f9 100644 --- a/cmd/podman/common.go +++ b/cmd/podman/common.go @@ -415,7 +415,7 @@ func getCreateFlags(c *cliconfig.PodmanCommand) { "stop-signal", "", "Signal to stop a container. Default is SIGTERM", ) - createFlags.Int( + createFlags.Uint( "stop-timeout", libpod.CtrRemoveTimeout, "Timeout (in seconds) to stop a container. Default is 10", ) @@ -519,7 +519,6 @@ func scrubServer(server string) string { func UsageTemplate() string { return `Usage:{{if .Runnable}} {{.UseLine}}{{end}}{{if .HasAvailableSubCommands}} - {{.CommandPath}} [command]{{end}}{{if gt (len .Aliases) 0}} Aliases: diff --git a/cmd/podman/container.go b/cmd/podman/container.go index d2450fdd3..338bb005c 100644 --- a/cmd/podman/container.go +++ b/cmd/podman/container.go @@ -18,11 +18,13 @@ var containerCommand = cliconfig.PodmanCommand{ // Commands that are universally implemented. var containerCommands = []*cobra.Command{ _containerExistsCommand, + _inspectCommand, } func init() { containerCommand.AddCommand(containerCommands...) containerCommand.AddCommand(getContainerSubCommands()...) containerCommand.SetUsageTemplate(UsageTemplate()) + rootCmd.AddCommand(containerCommand.Command) } diff --git a/cmd/podman/cp.go b/cmd/podman/cp.go index d9f230b67..30b6d75d2 100644 --- a/cmd/podman/cp.go +++ b/cmd/podman/cp.go @@ -29,7 +29,7 @@ var ( cpDescription = "Copy files/folders between a container and the local filesystem" _cpCommand = &cobra.Command{ - Use: "cp", + Use: "cp [flags] SRC_PATH DEST_PATH", Short: "Copy files/folders between a container and the local filesystem", Long: cpDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/create.go b/cmd/podman/create.go index 868f90d54..95cb732d9 100644 --- a/cmd/podman/create.go +++ b/cmd/podman/create.go @@ -42,7 +42,7 @@ var ( " any time with the podman start <container_id> command. The container" + " will be created with the initial state 'created'." _createCommand = &cobra.Command{ - Use: "create", + Use: "create [flags] IMAGE [COMMAND [ARG...]]", Short: "Create but do not start a container", Long: createDescription, RunE: func(cmd *cobra.Command, args []string) error { @@ -67,7 +67,7 @@ func init() { getCreateFlags(&createCommand.PodmanCommand) flags := createCommand.Flags() - flags.SetInterspersed(true) + flags.SetInterspersed(false) } @@ -408,7 +408,7 @@ func parseCreateOpts(ctx context.Context, c *cliconfig.PodmanCommand, runtime *l return nil, err } - if err = parseVolumesFrom(c.StringArray("volumes-from")); err != nil { + if err = parseVolumesFrom(c.StringSlice("volumes-from")); err != nil { return nil, err } @@ -707,23 +707,23 @@ func parseCreateOpts(ctx context.Context, c *cliconfig.PodmanCommand, runtime *l Entrypoint: entrypoint, Env: env, //ExposedPorts: ports, - GroupAdd: c.StringSlice("group-add"), - Hostname: c.String("hostname"), - HostAdd: c.StringSlice("add-host"), - IDMappings: idmappings, - Image: imageName, - ImageID: imageID, - Interactive: c.Bool("interactive"), - IP6Address: c.String("ipv6"), - IPAddress: c.String("ip"), - Labels: labels, - LinkLocalIP: c.StringSlice("link-local-ip"), - LogDriver: c.String("log-driver"), - LogDriverOpt: c.StringSlice("log-opt"), - MacAddress: c.String("mac-address"), - Name: c.String("name"), - Network: network, - NetworkAlias: c.StringSlice("network-alias"), + GroupAdd: c.StringSlice("group-add"), + Hostname: c.String("hostname"), + HostAdd: c.StringSlice("add-host"), + IDMappings: idmappings, + Image: imageName, + ImageID: imageID, + Interactive: c.Bool("interactive"), + //IP6Address: c.String("ipv6"), // Not implemented yet - needs CNI support for static v6 + IPAddress: c.String("ip"), + Labels: labels, + //LinkLocalIP: c.StringSlice("link-local-ip"), // Not implemented yet + LogDriver: c.String("log-driver"), + LogDriverOpt: c.StringSlice("log-opt"), + MacAddress: c.String("mac-address"), + Name: c.String("name"), + Network: network, + //NetworkAlias: c.StringSlice("network-alias"), // Not implemented - does this make sense in Podman? IpcMode: ipcMode, NetMode: netMode, UtsMode: utsMode, diff --git a/cmd/podman/diff.go b/cmd/podman/diff.go index e2d258ad4..e232d7e66 100644 --- a/cmd/podman/diff.go +++ b/cmd/podman/diff.go @@ -38,7 +38,7 @@ var ( container or image will be compared to its parent layer`) _diffCommand = &cobra.Command{ - Use: "diff", + Use: "diff [flags] CONTAINER | IMAGE", Short: "Inspect changes on container's file systems", Long: diffDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/exec.go b/cmd/podman/exec.go index 7040a7b09..4917fb606 100644 --- a/cmd/podman/exec.go +++ b/cmd/podman/exec.go @@ -21,7 +21,7 @@ var ( Run a command in a running container ` _execCommand = &cobra.Command{ - Use: "exec", + Use: "exec [flags] CONTAINER [COMMAND [ARG...]]", Short: "Run a process in a running container", Long: execDescription, RunE: func(cmd *cobra.Command, args []string) error { @@ -105,5 +105,13 @@ func execCmd(c *cliconfig.ExecValues) error { envs = append(envs, fmt.Sprintf("%s=%s", k, v)) } - return ctr.Exec(c.Tty, c.Privileged, envs, cmd, c.User, c.Workdir) + streams := new(libpod.AttachStreams) + streams.OutputStream = os.Stdout + streams.ErrorStream = os.Stderr + streams.InputStream = os.Stdin + streams.AttachOutput = true + streams.AttachError = true + streams.AttachInput = true + + return ctr.Exec(c.Tty, c.Privileged, envs, cmd, c.User, c.Workdir, streams) } diff --git a/cmd/podman/exists.go b/cmd/podman/exists.go index 74a4c841b..109831e74 100644 --- a/cmd/podman/exists.go +++ b/cmd/podman/exists.go @@ -32,7 +32,7 @@ var ( Check if a pod exists in local storage ` _imageExistsCommand = &cobra.Command{ - Use: "exists", + Use: "exists IMAGE", Short: "Check if an image exists in local storage", Long: imageExistsDescription, RunE: func(cmd *cobra.Command, args []string) error { @@ -40,11 +40,12 @@ var ( imageExistsCommand.GlobalFlags = MainGlobalOpts return imageExistsCmd(&imageExistsCommand) }, - Example: `podman image exists imageID`, + Example: `podman image exists imageID + podman image exists alpine || podman pull alpine`, } _containerExistsCommand = &cobra.Command{ - Use: "exists", + Use: "exists CONTAINER", Short: "Check if a container exists in local storage", Long: containerExistsDescription, RunE: func(cmd *cobra.Command, args []string) error { @@ -53,11 +54,12 @@ var ( return containerExistsCmd(&containerExistsCommand) }, - Example: `podman container exists containerID`, + Example: `podman container exists containerID + podman container exists myctr || podman run --name myctr [etc...]`, } _podExistsCommand = &cobra.Command{ - Use: "exists", + Use: "exists POD", Short: "Check if a pod exists in local storage", Long: podExistsDescription, RunE: func(cmd *cobra.Command, args []string) error { @@ -65,16 +67,20 @@ var ( podExistsCommand.GlobalFlags = MainGlobalOpts return podExistsCmd(&podExistsCommand) }, - Example: `podman pod exists podID`, + Example: `podman pod exists podID + podman pod exists mypod || podman pod create --name mypod`, } ) func init() { imageExistsCommand.Command = _imageExistsCommand + imageExistsCommand.DisableFlagsInUseLine = true imageExistsCommand.SetUsageTemplate(UsageTemplate()) containerExistsCommand.Command = _containerExistsCommand + containerExistsCommand.DisableFlagsInUseLine = true containerExistsCommand.SetUsageTemplate(UsageTemplate()) podExistsCommand.Command = _podExistsCommand + podExistsCommand.DisableFlagsInUseLine = true podExistsCommand.SetUsageTemplate(UsageTemplate()) } diff --git a/cmd/podman/export.go b/cmd/podman/export.go index 5873bad3d..d40c05019 100644 --- a/cmd/podman/export.go +++ b/cmd/podman/export.go @@ -17,7 +17,7 @@ var ( " and saves it on the local machine." _exportCommand = &cobra.Command{ - Use: "export", + Use: "export [flags] CONTAINER", Short: "Export container's filesystem contents as a tar archive", Long: exportDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/generate_kube.go b/cmd/podman/generate_kube.go index 15f374c73..fa2872b77 100644 --- a/cmd/podman/generate_kube.go +++ b/cmd/podman/generate_kube.go @@ -17,7 +17,7 @@ var ( containerKubeCommand cliconfig.GenerateKubeValues containerKubeDescription = "Generate Kubernetes Pod YAML" _containerKubeCommand = &cobra.Command{ - Use: "kube", + Use: "kube [flags] CONTAINER | POD", Short: "Generate Kubernetes pod YAML for a container or pod", Long: containerKubeDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/history.go b/cmd/podman/history.go index 103ef08e8..533ee91cb 100644 --- a/cmd/podman/history.go +++ b/cmd/podman/history.go @@ -40,7 +40,7 @@ var ( historyDescription = "Displays the history of an image. The information can be printed out in an easy to read, " + "or user specified format, and can be truncated." _historyCommand = &cobra.Command{ - Use: "history", + Use: "history [flags] IMAGE", Short: "Show history of a specified image", Long: historyDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/image.go b/cmd/podman/image.go index 14053cb0d..b5c1c3ccf 100644 --- a/cmd/podman/image.go +++ b/cmd/podman/image.go @@ -14,6 +14,8 @@ var ( Long: imageDescription, }, } + _imagesSubCommand = _imagesCommand + _rmSubCommand = _rmiCommand ) //imageSubCommands are implemented both in local and remote clients @@ -21,14 +23,12 @@ var imageSubCommands = []*cobra.Command{ _buildCommand, _historyCommand, _imageExistsCommand, - _imagesCommand, _importCommand, _inspectCommand, _loadCommand, _pruneImagesCommand, _pullCommand, _pushCommand, - _rmiCommand, _saveCommand, _tagCommand, } @@ -37,4 +37,13 @@ func init() { imageCommand.SetUsageTemplate(UsageTemplate()) imageCommand.AddCommand(imageSubCommands...) imageCommand.AddCommand(getImageSubCommands()...) + + // Setup of "images" to appear as "list" + _imagesSubCommand.Use = "list" + _imagesSubCommand.Aliases = []string{"ls"} + imageCommand.AddCommand(&_imagesSubCommand) + + // Setup of "rmi" to appears as "rm" + _rmSubCommand.Use = "rm" + imageCommand.AddCommand(&_rmSubCommand) } diff --git a/cmd/podman/images.go b/cmd/podman/images.go index 6e82195a9..e6f4d9a60 100644 --- a/cmd/podman/images.go +++ b/cmd/podman/images.go @@ -87,8 +87,8 @@ var ( imagesCommand cliconfig.ImagesValues imagesDescription = "lists locally stored images." - _imagesCommand = &cobra.Command{ - Use: "images", + _imagesCommand = cobra.Command{ + Use: "images [flags] [IMAGE]", Short: "List images in local storage", Long: imagesDescription, RunE: func(cmd *cobra.Command, args []string) error { @@ -103,8 +103,9 @@ var ( ) func init() { - imagesCommand.Command = _imagesCommand + imagesCommand.Command = &_imagesCommand imagesCommand.SetUsageTemplate(UsageTemplate()) + flags := imagesCommand.Flags() flags.BoolVarP(&imagesCommand.All, "all", "a", false, "Show all images (default hides intermediate images)") flags.BoolVar(&imagesCommand.Digests, "digests", false, "Show digests") diff --git a/cmd/podman/import.go b/cmd/podman/import.go index a64b03d6d..ddf1bd802 100644 --- a/cmd/podman/import.go +++ b/cmd/podman/import.go @@ -17,7 +17,7 @@ var ( Optionally tag the image. You can specify the instructions using the --change option. ` _importCommand = &cobra.Command{ - Use: "import", + Use: "import [flags] PATH [REFERENCE]", Short: "Import a tarball to create a filesystem image", Long: importDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/inspect.go b/cmd/podman/inspect.go index 46883b31d..1c93a03e1 100644 --- a/cmd/podman/inspect.go +++ b/cmd/podman/inspect.go @@ -26,7 +26,7 @@ var ( inspectDescription = "This displays the low-level information on containers and images identified by name or ID. By default, this will render all results in a JSON array. If the container and image have the same name, this will return container JSON for unspecified type." _inspectCommand = &cobra.Command{ - Use: "inspect", + Use: "inspect [flags] CONTAINER | IMAGE", Short: "Display the configuration of a container or image", Long: inspectDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/kill.go b/cmd/podman/kill.go index eb72d53e7..76d2516b7 100644 --- a/cmd/podman/kill.go +++ b/cmd/podman/kill.go @@ -20,7 +20,7 @@ var ( killDescription = "The main process inside each container specified will be sent SIGKILL, or any signal specified with option --signal." _killCommand = &cobra.Command{ - Use: "kill", + Use: "kill [flags] CONTAINER [CONTAINER...]", Short: "Kill one or more running containers with a specific signal", Long: killDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/libpodruntime/runtime.go b/cmd/podman/libpodruntime/runtime.go index f4ddf3521..2b96f0c20 100644 --- a/cmd/podman/libpodruntime/runtime.go +++ b/cmd/podman/libpodruntime/runtime.go @@ -5,6 +5,7 @@ import ( "github.com/containers/libpod/libpod" "github.com/containers/libpod/pkg/rootless" "github.com/containers/libpod/pkg/util" + "github.com/containers/storage" "github.com/pkg/errors" ) @@ -20,11 +21,8 @@ func GetRuntime(c *cliconfig.PodmanCommand) (*libpod.Runtime, error) { func getRuntime(c *cliconfig.PodmanCommand, renumber bool) (*libpod.Runtime, error) { options := []libpod.RuntimeOption{} - - storageOpts, _, err := util.GetDefaultStoreOptions() - if err != nil { - return nil, err - } + storageOpts := storage.StoreOptions{} + storageSet := false uidmapFlag := c.Flags().Lookup("uidmap") gidmapFlag := c.Flags().Lookup("gidmap") @@ -43,25 +41,33 @@ func getRuntime(c *cliconfig.PodmanCommand, renumber bool) (*libpod.Runtime, err storageOpts.UIDMap = mappings.UIDMap storageOpts.GIDMap = mappings.GIDMap + storageSet = true } if c.Flags().Changed("root") { + storageSet = true storageOpts.GraphRoot = c.GlobalFlags.Root } if c.Flags().Changed("runroot") { + storageSet = true storageOpts.RunRoot = c.GlobalFlags.Runroot } if len(storageOpts.RunRoot) > 50 { return nil, errors.New("the specified runroot is longer than 50 characters") } if c.Flags().Changed("storage-driver") { + storageSet = true storageOpts.GraphDriverName = c.GlobalFlags.StorageDriver } if len(c.GlobalFlags.StorageOpts) > 0 { + storageSet = true storageOpts.GraphDriverOptions = c.GlobalFlags.StorageOpts } - options = append(options, libpod.WithStorageConfig(storageOpts)) + // Only set this if the user changes storage config on the command line + if storageSet { + options = append(options, libpod.WithStorageConfig(storageOpts)) + } // TODO CLI flags for image config? // TODO CLI flag for signature policy? diff --git a/cmd/podman/load.go b/cmd/podman/load.go index 272cd78d2..5a0742aba 100644 --- a/cmd/podman/load.go +++ b/cmd/podman/load.go @@ -17,7 +17,7 @@ var ( loadDescription = "Loads the image from docker-archive stored on the local machine." _loadCommand = &cobra.Command{ - Use: "load", + Use: "load [flags] [PATH]", Short: "Load an image from docker archive", Long: loadDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/login.go b/cmd/podman/login.go index b02a4b3f9..48d4eefbc 100644 --- a/cmd/podman/login.go +++ b/cmd/podman/login.go @@ -21,7 +21,7 @@ var ( loginDescription = "Login to a container registry on a specified server." _loginCommand = &cobra.Command{ - Use: "login", + Use: "login [flags] REGISTRY", Short: "Login to a container registry", Long: loginDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/logout.go b/cmd/podman/logout.go index 4108887f0..2a540ceba 100644 --- a/cmd/podman/logout.go +++ b/cmd/podman/logout.go @@ -14,7 +14,7 @@ var ( logoutCommand cliconfig.LogoutValues logoutDescription = "Remove the cached username and password for the registry." _logoutCommand = &cobra.Command{ - Use: "logout", + Use: "logout [flags] REGISTRY", Short: "Logout of a container registry", Long: logoutDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/logs.go b/cmd/podman/logs.go index 40ae2c846..a02010eda 100644 --- a/cmd/podman/logs.go +++ b/cmd/podman/logs.go @@ -18,7 +18,7 @@ var ( logsDescription = "The podman logs command batch-retrieves whatever logs are present for a container at the time of execution. This does not guarantee execution" + "order when combined with podman run (i.e. your run may not have generated any logs at the time you execute podman logs" _logsCommand = &cobra.Command{ - Use: "logs", + Use: "logs [flags] CONTAINER", Short: "Fetch the logs of a container", Long: logsDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/main.go b/cmd/podman/main.go index 19bdb40d6..98e2f23ca 100644 --- a/cmd/podman/main.go +++ b/cmd/podman/main.go @@ -38,7 +38,7 @@ var mainCommands = []*cobra.Command{ _buildCommand, _exportCommand, _historyCommand, - _imagesCommand, + &_imagesCommand, _importCommand, _infoCommand, _inspectCommand, @@ -47,7 +47,7 @@ var mainCommands = []*cobra.Command{ podCommand.Command, _pullCommand, _pushCommand, - _rmiCommand, + &_rmiCommand, _saveCommand, _tagCommand, _versionCommand, diff --git a/cmd/podman/mount.go b/cmd/podman/mount.go index f4a7bd5ea..3a3432194 100644 --- a/cmd/podman/mount.go +++ b/cmd/podman/mount.go @@ -26,7 +26,7 @@ var ( ` _mountCommand = &cobra.Command{ - Use: "mount", + Use: "mount [flags] CONTAINER", Short: "Mount a working container's root filesystem", Long: mountDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/pause.go b/cmd/podman/pause.go index 94bb0edfe..3a5b80359 100644 --- a/cmd/podman/pause.go +++ b/cmd/podman/pause.go @@ -20,7 +20,7 @@ var ( Pauses one or more running containers. The container name or ID can be used. ` _pauseCommand = &cobra.Command{ - Use: "pause", + Use: "pause [flags] CONTAINER [CONTAINER...]", Short: "Pause all the processes in one or more containers", Long: pauseDescription, RunE: func(cmd *cobra.Command, args []string) error { @@ -30,7 +30,7 @@ var ( }, Example: `podman pause mywebserver podman pause 860a4b23 - podman stop -a`, + podman pause -a`, } ) diff --git a/cmd/podman/play_kube.go b/cmd/podman/play_kube.go index 69a15ba8d..ac46ad5c6 100644 --- a/cmd/podman/play_kube.go +++ b/cmd/podman/play_kube.go @@ -29,7 +29,7 @@ var ( playKubeCommand cliconfig.KubePlayValues playKubeDescription = "Play a Pod and its containers based on a Kubrernetes YAML" _playKubeCommand = &cobra.Command{ - Use: "kube", + Use: "kube [flags] KUBEFILE", Short: "Play a pod based on Kubernetes YAML", Long: playKubeDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/pod_inspect.go b/cmd/podman/pod_inspect.go index 5a32b5c5d..8b2747af0 100644 --- a/cmd/podman/pod_inspect.go +++ b/cmd/podman/pod_inspect.go @@ -14,7 +14,7 @@ var ( podInspectCommand cliconfig.PodInspectValues podInspectDescription = "Display the configuration for a pod by name or id" _podInspectCommand = &cobra.Command{ - Use: "inspect", + Use: "inspect [flags] POD", Short: "Displays a pod configuration", Long: podInspectDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/pod_kill.go b/cmd/podman/pod_kill.go index aaaae0f7d..70d86d186 100644 --- a/cmd/podman/pod_kill.go +++ b/cmd/podman/pod_kill.go @@ -16,7 +16,7 @@ var ( podKillCommand cliconfig.PodKillValues podKillDescription = "The main process of each container inside the specified pod will be sent SIGKILL, or any signal specified with option --signal." _podKillCommand = &cobra.Command{ - Use: "kill", + Use: "kill [flags] POD [POD...]", Short: "Send the specified signal or SIGKILL to containers in pod", Long: podKillDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/pod_pause.go b/cmd/podman/pod_pause.go index 284740d22..f7c90dbbe 100644 --- a/cmd/podman/pod_pause.go +++ b/cmd/podman/pod_pause.go @@ -13,7 +13,7 @@ var ( podPauseCommand cliconfig.PodPauseValues podPauseDescription = `Pauses one or more pods. The pod name or ID can be used.` _podPauseCommand = &cobra.Command{ - Use: "pause", + Use: "pause [flags] POD [POD...]", Short: "Pause one or more pods", Long: podPauseDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/pod_restart.go b/cmd/podman/pod_restart.go index 741fce588..ba77e1409 100644 --- a/cmd/podman/pod_restart.go +++ b/cmd/podman/pod_restart.go @@ -14,7 +14,7 @@ var ( podRestartCommand cliconfig.PodRestartValues podRestartDescription = `Restarts one or more pods. The pod ID or name can be used.` _podRestartCommand = &cobra.Command{ - Use: "restart", + Use: "restart [flags] POD [POD...]", Short: "Restart one or more pods", Long: podRestartDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/pod_rm.go b/cmd/podman/pod_rm.go index ba16d03c7..fa452b061 100644 --- a/cmd/podman/pod_rm.go +++ b/cmd/podman/pod_rm.go @@ -18,7 +18,7 @@ be used. A pod with containers will not be removed without --force. If --force is specified, all containers will be stopped, then removed. `) _podRmCommand = &cobra.Command{ - Use: "rm", + Use: "rm [flags] POD [POD...]", Short: "Remove one or more pods", Long: podRmDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/pod_start.go b/cmd/podman/pod_start.go index 5761afd52..eef9d2a71 100644 --- a/cmd/podman/pod_start.go +++ b/cmd/podman/pod_start.go @@ -18,7 +18,7 @@ var ( Starts one or more pods. The pod name or ID can be used. ` _podStartCommand = &cobra.Command{ - Use: "start", + Use: "start POD [POD...]", Short: "Start one or more pods", Long: podStartDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/pod_stats.go b/cmd/podman/pod_stats.go index 907d6a547..f5edd21f8 100644 --- a/cmd/podman/pod_stats.go +++ b/cmd/podman/pod_stats.go @@ -24,7 +24,7 @@ var ( podStatsCommand cliconfig.PodStatsValues podStatsDescription = "Display a live stream of resource usage statistics for the containers in or more pods" _podStatsCommand = &cobra.Command{ - Use: "stats", + Use: "stats [flags] POD [POD...]", Short: "Display percentage of CPU, memory, network I/O, block I/O and PIDs for containers in one or more pods", Long: podStatsDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/pod_stop.go b/cmd/podman/pod_stop.go index 62d0d4aa5..951cf082a 100644 --- a/cmd/podman/pod_stop.go +++ b/cmd/podman/pod_stop.go @@ -19,7 +19,7 @@ var ( ` _podStopCommand = &cobra.Command{ - Use: "stop", + Use: "stop [flags] POD [POD...]", Short: "Stop one or more pods", Long: podStopDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/pod_top.go b/cmd/podman/pod_top.go index 790118496..6a26e3dff 100644 --- a/cmd/podman/pod_top.go +++ b/cmd/podman/pod_top.go @@ -25,7 +25,7 @@ the latest pod. `, getDescriptorString()) _podTopCommand = &cobra.Command{ - Use: "top", + Use: "top [flags] CONTAINER [FORMAT-DESCRIPTORS]", Short: "Display the running processes of containers in a pod", Long: podTopDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/pod_unpause.go b/cmd/podman/pod_unpause.go index 16481d0e2..6b142d573 100644 --- a/cmd/podman/pod_unpause.go +++ b/cmd/podman/pod_unpause.go @@ -14,7 +14,7 @@ var ( podUnpauseCommand cliconfig.PodUnpauseValues podUnpauseDescription = `Unpauses one or more pods. The pod name or ID can be used.` _podUnpauseCommand = &cobra.Command{ - Use: "unpause", + Use: "unpause [flags] POD [POD...]", Short: "Unpause one or more pods", Long: podUnpauseDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/port.go b/cmd/podman/port.go index bcf372a51..ffb5749fb 100644 --- a/cmd/podman/port.go +++ b/cmd/podman/port.go @@ -20,7 +20,7 @@ var ( List port mappings for the CONTAINER, or lookup the public-facing port that is NAT-ed to the PRIVATE_PORT ` _portCommand = &cobra.Command{ - Use: "port", + Use: "port [flags] CONTAINER", Short: "List port mappings or a specific mapping for the container", Long: portDescription, RunE: func(cmd *cobra.Command, args []string) error { @@ -128,9 +128,6 @@ func portCmd(c *cliconfig.PortValues) error { if state, _ := con.State(); state != libpod.ContainerStateRunning { continue } - if c.All { - fmt.Println(con.ID()) - } portmappings, err := con.PortMappings() if err != nil { @@ -143,6 +140,9 @@ func portCmd(c *cliconfig.PortValues) error { if hostIP == "" { hostIP = "0.0.0.0" } + if c.All { + fmt.Printf("%s\t", con.ID()[:12]) + } // If not searching by port or port/proto, then dump what we see if port == "" { fmt.Printf("%d/%s -> %s:%d\n", v.ContainerPort, v.Protocol, hostIP, v.HostPort) diff --git a/cmd/podman/ps.go b/cmd/podman/ps.go index 9c165b836..fe4173fdd 100644 --- a/cmd/podman/ps.go +++ b/cmd/podman/ps.go @@ -157,11 +157,10 @@ func (a psSortedSize) Less(i, j int) bool { var ( psCommand cliconfig.PsValues psDescription = "Prints out information about the containers" - _psCommand = &cobra.Command{ - Use: "list", - Aliases: []string{"ls", "ps"}, - Short: "List containers", - Long: psDescription, + _psCommand = cobra.Command{ + Use: "ps", + Short: "List containers", + Long: psDescription, RunE: func(cmd *cobra.Command, args []string) error { psCommand.InputArgs = args psCommand.GlobalFlags = MainGlobalOpts @@ -174,7 +173,7 @@ var ( ) func init() { - psCommand.Command = _psCommand + psCommand.Command = &_psCommand psCommand.SetUsageTemplate(UsageTemplate()) flags := psCommand.Flags() flags.BoolVarP(&psCommand.All, "all", "a", false, "Show all the containers, default is only running containers") diff --git a/cmd/podman/pull.go b/cmd/podman/pull.go index 71f555162..5f4658fe1 100644 --- a/cmd/podman/pull.go +++ b/cmd/podman/pull.go @@ -29,7 +29,7 @@ An image can be pulled using its tag or digest. If a tag is not specified, the image with the 'latest' tag (if it exists) is pulled ` _pullCommand = &cobra.Command{ - Use: "pull", + Use: "pull [flags] IMAGE-PATH", Short: "Pull an image from a registry", Long: pullDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/push.go b/cmd/podman/push.go index 56261a8d3..bc909cb5e 100644 --- a/cmd/podman/push.go +++ b/cmd/podman/push.go @@ -26,7 +26,7 @@ var ( See podman-push(1) section "DESTINATION" for the expected format`) _pushCommand = &cobra.Command{ - Use: "push", + Use: "push [flags] IMAGE REGISTRY", Short: "Push an image to a specified destination", Long: pushDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/refresh.go b/cmd/podman/refresh.go index 641748452..193be6953 100644 --- a/cmd/podman/refresh.go +++ b/cmd/podman/refresh.go @@ -26,6 +26,7 @@ var ( ) func init() { + _refreshCommand.Hidden = true refreshCommand.Command = _refreshCommand refreshCommand.SetUsageTemplate(UsageTemplate()) } diff --git a/cmd/podman/restart.go b/cmd/podman/restart.go index 58fb38874..5aa12070e 100644 --- a/cmd/podman/restart.go +++ b/cmd/podman/restart.go @@ -18,7 +18,7 @@ var ( restartCommand cliconfig.RestartValues restartDescription = `Restarts one or more running containers. The container ID or name can be used. A timeout before forcibly stopping can be set, but defaults to 10 seconds` _restartCommand = &cobra.Command{ - Use: "restart", + Use: "restart [flags] CONTAINER [CONTAINER...]", Short: "Restart one or more containers", Long: restartDescription, RunE: func(cmd *cobra.Command, args []string) error { @@ -73,7 +73,7 @@ func restartCmd(c *cliconfig.RestartValues) error { defer runtime.Shutdown(false) timeout := c.Timeout - useTimeout := c.Flag("timeout").Changed + useTimeout := c.Flag("timeout").Changed || c.Flag("time").Changed // Handle --latest if c.Latest { diff --git a/cmd/podman/restore.go b/cmd/podman/restore.go index 5f6e7b892..73d355734 100644 --- a/cmd/podman/restore.go +++ b/cmd/podman/restore.go @@ -21,7 +21,7 @@ var ( Restores a container from a checkpoint. The container name or ID can be used. ` _restoreCommand = &cobra.Command{ - Use: "restore", + Use: "restore [flags] CONTAINER [CONTAINER...]", Short: "Restores one or more containers from a checkpoint", Long: restoreDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/rm.go b/cmd/podman/rm.go index 2dcb491d7..61b049840 100644 --- a/cmd/podman/rm.go +++ b/cmd/podman/rm.go @@ -21,7 +21,7 @@ The container name or ID can be used. This does not remove images. Running containers will not be removed without the -f option. `) _rmCommand = &cobra.Command{ - Use: "rm", + Use: "rm [flags] CONTAINER [CONTAINER...]", Short: "Remove one or more containers", Long: rmDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/rmi.go b/cmd/podman/rmi.go index 709ed14e0..5b8bf1ea3 100644 --- a/cmd/podman/rmi.go +++ b/cmd/podman/rmi.go @@ -5,8 +5,6 @@ import ( "os" "github.com/containers/libpod/cmd/podman/cliconfig" - "github.com/containers/libpod/cmd/podman/varlink" - "github.com/containers/libpod/libpod/image" "github.com/containers/libpod/pkg/adapter" "github.com/containers/storage" "github.com/pkg/errors" @@ -16,8 +14,8 @@ import ( var ( rmiCommand cliconfig.RmiValues rmiDescription = "Removes one or more locally stored images." - _rmiCommand = &cobra.Command{ - Use: "rmi", + _rmiCommand = cobra.Command{ + Use: "rmi [flags] IMAGE [IMAGE...]", Short: "Removes one or more images from local storage", Long: rmiDescription, RunE: func(cmd *cobra.Command, args []string) error { @@ -31,19 +29,8 @@ var ( } ) -func imageNotFound(err error) bool { - if errors.Cause(err) == image.ErrNoSuchImage { - return true - } - switch err.(type) { - case *iopodman.ImageNotFound: - return true - } - return false -} - func init() { - rmiCommand.Command = _rmiCommand + rmiCommand.Command = &_rmiCommand rmiCommand.SetUsageTemplate(UsageTemplate()) flags := rmiCommand.Flags() flags.BoolVarP(&rmiCommand.All, "all", "a", false, "Remove all images") @@ -80,7 +67,7 @@ func rmiCmd(c *cliconfig.RmiValues) error { if errors.Cause(err) == storage.ErrImageUsedByContainer { fmt.Printf("A container associated with containers/storage, i.e. via Buildah, CRI-O, etc., may be associated with this image: %-12.12s\n", img.ID()) } - if !imageNotFound(err) { + if !adapter.IsImageNotFound(err) { failureCnt++ } if lastError != nil { @@ -135,7 +122,7 @@ func rmiCmd(c *cliconfig.RmiValues) error { newImage, err := runtime.NewImageFromLocal(i) if err != nil { if lastError != nil { - if !imageNotFound(lastError) { + if !adapter.IsImageNotFound(lastError) { failureCnt++ } fmt.Fprintln(os.Stderr, lastError) @@ -147,7 +134,7 @@ func rmiCmd(c *cliconfig.RmiValues) error { } } - if imageNotFound(lastError) && failureCnt == 0 { + if adapter.IsImageNotFound(lastError) && failureCnt == 0 { exitCode = 1 } diff --git a/cmd/podman/run.go b/cmd/podman/run.go index bea9b1743..f66b939d3 100644 --- a/cmd/podman/run.go +++ b/cmd/podman/run.go @@ -23,7 +23,7 @@ var ( runDescription = "Runs a command in a new container from the given image" _runCommand = &cobra.Command{ - Use: "run", + Use: "run [flags] IMAGE [COMMAND [ARG...]]", Short: "Run a command in a new container", Long: runDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/runlabel.go b/cmd/podman/runlabel.go index d466651f3..bc4e650f9 100644 --- a/cmd/podman/runlabel.go +++ b/cmd/podman/runlabel.go @@ -22,7 +22,7 @@ var ( Executes a command as described by a container image label. ` _runlabelCommand = &cobra.Command{ - Use: "runlabel", + Use: "runlabel [flags] LABEL IMAGE [ARG...]", Short: "Execute the command described by an image label", Long: runlabelDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/save.go b/cmd/podman/save.go index 161540deb..3bc283772 100644 --- a/cmd/podman/save.go +++ b/cmd/podman/save.go @@ -28,7 +28,7 @@ var ( Default is docker-archive` _saveCommand = &cobra.Command{ - Use: "save", + Use: "save [flags] IMAGE", Short: "Save image to an archive", Long: saveDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/search.go b/cmd/podman/search.go index f63131c84..5c14f1ff1 100644 --- a/cmd/podman/search.go +++ b/cmd/podman/search.go @@ -22,7 +22,7 @@ var ( Search registries for a given image. Can search all the default registries or a specific registry. Can limit the number of results, and filter the output based on certain conditions.` _searchCommand = &cobra.Command{ - Use: "search", + Use: "search [flags] TERM", Short: "Search registry for image", Long: searchDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/sign.go b/cmd/podman/sign.go index 6e8f9ee95..2cf228d01 100644 --- a/cmd/podman/sign.go +++ b/cmd/podman/sign.go @@ -24,7 +24,7 @@ var ( signCommand cliconfig.SignValues signDescription = "Create a signature file that can be used later to verify the image" _signCommand = &cobra.Command{ - Use: "sign", + Use: "sign [flags] IMAGE [IMAGE...]", Short: "Sign an image", Long: signDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/start.go b/cmd/podman/start.go index c645a35c4..3ce04ea79 100644 --- a/cmd/podman/start.go +++ b/cmd/podman/start.go @@ -21,7 +21,7 @@ var ( Starts one or more containers. The container name or ID can be used. ` _startCommand = &cobra.Command{ - Use: "start", + Use: "start [flags] CONTAINER [CONTAINER...]", Short: "Start one or more containers", Long: startDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/stats.go b/cmd/podman/stats.go index 2bbcd0a17..dcb274471 100644 --- a/cmd/podman/stats.go +++ b/cmd/podman/stats.go @@ -33,7 +33,7 @@ var ( statsDescription = "display a live stream of one or more containers' resource usage statistics" _statsCommand = &cobra.Command{ - Use: "stats", + Use: "stats [flags] CONTAINER [CONTAINER...]", Short: "Display percentage of CPU, memory, network I/O, block I/O and PIDs for one or more containers", Long: statsDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/stop.go b/cmd/podman/stop.go index 67c15b2a8..ab9a2cf38 100644 --- a/cmd/podman/stop.go +++ b/cmd/podman/stop.go @@ -24,7 +24,7 @@ var ( seconds otherwise. ` _stopCommand = &cobra.Command{ - Use: "stop", + Use: "stop [flags] CONTAINER [CONTAINER...]", Short: "Stop one or more containers", Long: stopDescription, RunE: func(cmd *cobra.Command, args []string) error { @@ -73,21 +73,29 @@ func stopCmd(c *cliconfig.StopValues) error { fmt.Println(err.Error()) } + if c.Flag("timeout").Changed && c.Flag("time").Changed { + return errors.New("the --timeout and --time flags are mutually exclusive") + } + var stopFuncs []shared.ParallelWorkerInput for _, ctr := range containers { con := ctr var stopTimeout uint - if c.Flag("timeout").Changed { + if c.Flag("timeout").Changed || c.Flag("time").Changed { stopTimeout = c.Timeout } else { stopTimeout = ctr.StopTimeout() + logrus.Debugf("Set timeout to container %s default (%d)", ctr.ID(), stopTimeout) } f := func() error { - if err := con.StopWithTimeout(stopTimeout); err != nil && errors.Cause(err) != libpod.ErrCtrStopped { + if err := con.StopWithTimeout(stopTimeout); err != nil { + if errors.Cause(err) == libpod.ErrCtrStopped { + logrus.Debugf("Container %s already stopped", con.ID()) + return nil + } return err } return nil - } stopFuncs = append(stopFuncs, shared.ParallelWorkerInput{ ContainerID: con.ID(), diff --git a/cmd/podman/tag.go b/cmd/podman/tag.go index 2b9d67066..98c6e3449 100644 --- a/cmd/podman/tag.go +++ b/cmd/podman/tag.go @@ -12,7 +12,7 @@ var ( tagDescription = "Adds one or more additional names to locally-stored image" _tagCommand = &cobra.Command{ - Use: "tag", + Use: "tag [flags] IMAGE TAG [TAG...]", Short: "Add an additional name to a local image", Long: tagDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/top.go b/cmd/podman/top.go index 36d6bb6b4..cdf270fa7 100644 --- a/cmd/podman/top.go +++ b/cmd/podman/top.go @@ -34,7 +34,7 @@ the latest container. `, getDescriptorString()) _topCommand = &cobra.Command{ - Use: "top", + Use: "top [flags] CONTAINER [FORMAT-DESCRIPTIOS]", Short: "Display the running processes of a container", Long: topDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/trust_set_show.go b/cmd/podman/trust_set_show.go index 0a4783d0a..746854249 100644 --- a/cmd/podman/trust_set_show.go +++ b/cmd/podman/trust_set_show.go @@ -23,7 +23,7 @@ var ( showTrustCommand cliconfig.ShowTrustValues setTrustDescription = "Set default trust policy or add a new trust policy for a registry" _setTrustCommand = &cobra.Command{ - Use: "set", + Use: "set [flags] REGISTRY", Short: "Set default trust policy or a new trust policy for a registry", Long: setTrustDescription, Example: "", @@ -36,7 +36,7 @@ var ( showTrustDescription = "Display trust policy for the system" _showTrustCommand = &cobra.Command{ - Use: "show", + Use: "show [flags] [REGISTRY]", Short: "Display trust policy for the system", Long: showTrustDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/umount.go b/cmd/podman/umount.go index 6d9009388..48c97fa31 100644 --- a/cmd/podman/umount.go +++ b/cmd/podman/umount.go @@ -22,7 +22,7 @@ counter reaches zero indicating no other processes are using the mount. An unmount can be forced with the --force flag. ` _umountCommand = &cobra.Command{ - Use: "umount", + Use: "umount [flags] CONTAINER [CONTAINER...]", Aliases: []string{"unmount"}, Short: "Unmounts working container's root filesystem", Long: description, diff --git a/cmd/podman/unpause.go b/cmd/podman/unpause.go index efd9a20a3..58fd19fe1 100644 --- a/cmd/podman/unpause.go +++ b/cmd/podman/unpause.go @@ -21,7 +21,7 @@ var ( Unpauses one or more running containers. The container name or ID can be used. ` _unpauseCommand = &cobra.Command{ - Use: "unpause", + Use: "unpause [flags] CONTAINER [CONTAINER...]", Short: "Unpause the processes in one or more containers", Long: unpauseDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/varlink.go b/cmd/podman/varlink.go index d9c6cdb47..f19d03885 100644 --- a/cmd/podman/varlink.go +++ b/cmd/podman/varlink.go @@ -24,7 +24,7 @@ var ( run varlink interface ` _varlinkCommand = &cobra.Command{ - Use: "varlink", + Use: "varlink [flags] URI", Short: "Run varlink interface", Long: varlinkDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/volume_create.go b/cmd/podman/volume_create.go index 833191082..96b2ed8c7 100644 --- a/cmd/podman/volume_create.go +++ b/cmd/podman/volume_create.go @@ -18,7 +18,7 @@ Creates a new volume. If using the default driver, "local", the volume will be created at.` _volumeCreateCommand = &cobra.Command{ - Use: "create", + Use: "create [flags] [NAME]", Short: "Create a new volume", Long: volumeCreateDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/volume_inspect.go b/cmd/podman/volume_inspect.go index dc6afbc36..8add7a375 100644 --- a/cmd/podman/volume_inspect.go +++ b/cmd/podman/volume_inspect.go @@ -16,7 +16,7 @@ Display detailed information on one or more volumes. Can change the format from JSON to a Go template. ` _volumeInspectCommand = &cobra.Command{ - Use: "inspect", + Use: "inspect [flags] VOLUME [VOLUME...]", Short: "Display detailed information on one or more volumes", Long: volumeInspectDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/volume_rm.go b/cmd/podman/volume_rm.go index 03b6ccae1..73b1a6668 100644 --- a/cmd/podman/volume_rm.go +++ b/cmd/podman/volume_rm.go @@ -19,7 +19,7 @@ not being used by any containers. To remove the volumes anyways, use the --force flag. ` _volumeRmCommand = &cobra.Command{ - Use: "rm", + Use: "rm [flags] VOLUME [VOLUME...]", Aliases: []string{"remove"}, Short: "Remove one or more volumes", Long: volumeRmDescription, diff --git a/cmd/podman/wait.go b/cmd/podman/wait.go index 9df7cdbae..9df2e3208 100644 --- a/cmd/podman/wait.go +++ b/cmd/podman/wait.go @@ -20,7 +20,7 @@ var ( Block until one or more containers stop and then print their exit codes ` _waitCommand = &cobra.Command{ - Use: "wait", + Use: "wait [flags] CONTAINER [CONTAINER...]", Short: "Block on one or more containers", Long: waitDescription, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/contrib/gate/Dockerfile b/contrib/gate/Dockerfile index f9b57a6da..4d88ae9a6 100644 --- a/contrib/gate/Dockerfile +++ b/contrib/gate/Dockerfile @@ -49,8 +49,6 @@ WORKDIR $GOSRC # Install dependencies RUN set -x && \ - go get -u github.com/mailru/easyjson/... && \ - install -D -m 755 "$GOPATH"/bin/easyjson /usr/bin/ && \ make install.tools && \ install -D -m 755 $GOSRC/contrib/gate/entrypoint.sh /usr/local/bin/ && \ rm -rf "$GOSRC" diff --git a/contrib/spec/podman.spec.in b/contrib/spec/podman.spec.in index bf75522dc..703b942b6 100644 --- a/contrib/spec/podman.spec.in +++ b/contrib/spec/podman.spec.in @@ -39,7 +39,7 @@ %global shortcommit_conmon %(c=%{commit_conmon}; echo ${c:0:7}) Name: podman -Version: 1.0.1 +Version: 1.2.0 Release: #COMMITDATE#.git%{shortcommit0}%{?dist} Summary: Manage Pods, Containers and Container Images License: ASL 2.0 diff --git a/docs/podman-container-refresh.1.md b/docs/podman-container-refresh.1.md deleted file mode 100644 index 26552faa6..000000000 --- a/docs/podman-container-refresh.1.md +++ /dev/null @@ -1,25 +0,0 @@ -% podman-container-refresh(1) - -## NAME -podman\-container\-refresh - Refresh all containers - -## SYNOPSIS -**podman container refresh** - -## DESCRIPTION -The refresh command refreshes the state of all containers to pick up database -schema or general configuration changes. It is not necessary during normal -operation, and will typically be invoked by package managers after finishing an -upgrade of the Podman package. - -As part of refresh, all running containers will be restarted. - -## EXAMPLES ## - -``` -$ podman container refresh -[root@localhost /]# -``` - -## SEE ALSO -podman(1), podman-run(1) diff --git a/docs/podman-container.1.md b/docs/podman-container.1.md index 31ea88570..1ba957480 100644 --- a/docs/podman-container.1.md +++ b/docs/podman-container.1.md @@ -11,40 +11,37 @@ The container command allows you to manage containers ## COMMANDS -| Command | Man Page | Description | -| ------- | --------------------------------------------------- | ---------------------------------------------------------------------------- | -| attach | [podman-attach(1)](podman-attach.1.md) | Attach to a running container. | -| checkpoint | [podman-container-checkpoint(1)](podman-container-checkpoint.1.md) | Checkpoints one or more containers. | -| cleanup | [podman-container-cleanup(1)](podman-container-cleanup.1.md) | Cleanup containers network and mountpoints. | -| commit | [podman-commit(1)](podman-commit.1.md) | Create new image based on the changed container. | -| create | [podman-create(1)](podman-create.1.md) | Create a new container. | -| diff | [podman-diff(1)](podman-diff.1.md) | Inspect changes on a container or image's filesystem. | -| exec | [podman-exec(1)](podman-exec.1.md) | Execute a command in a running container. | -| exists | [podman-exists(1)](podman-container-exists.1.md) | Check if a container exists in local storage | -| export | [podman-export(1)](podman-export.1.md) | Export a container's filesystem contents as a tar archive. | -| inspect | [podman-inspect(1)](podman-inspect.1.md) | Display a container or image's configuration. | -| kill | [podman-kill(1)](podman-kill.1.md) | Kill the main process in one or more containers. | -| list | [podman-ps(1)](podman-ps.1.md) | List the containers on the system. | -| logs | [podman-logs(1)](podman-logs.1.md) | Display the logs of a container. | -| ls | [podman-ps(1)](podman-ps.1.md) | List the containers on the system. | -| mount | [podman-mount(1)](podman-mount.1.md) | Mount a working container's root filesystem. | -| pause | [podman-pause(1)](podman-pause.1.md) | Pause one or more containers. | -| port | [podman-port(1)](podman-port.1.md) | List port mappings for the container. | -| prune | [podman-container-prune(1)](podman-container-prune.1.md) | Remove all stopped containers from local storage | -| ps | [podman-ps(1)](podman-ps.1.md) | List the containers on the system. | -| refresh | [podman-refresh(1)](podman-container-refresh.1.md) | Refresh the state of all containers | -| restart | [podman-restart(1)](podman-restart.1.md) | Restart one or more containers. | -| restore | [podman-container-restore(1)](podman-container-restore.1.md) | Restores one or more containers from a checkpoint. | -| rm | [podman-rm(1)](podman-rm.1.md) | Remove one or more containers. | -| run | [podman-run(1)](podman-run.1.md) | Run a command in a container. | -| start | [podman-start(1)](podman-start.1.md) | Starts one or more containers. | -| stats | [podman-stats(1)](podman-stats.1.md) | Display a live stream of one or more container's resource usage statistics. | -| stop | [podman-stop(1)](podman-stop.1.md) | Stop one or more running containers. | -| top | [podman-top(1)](podman-top.1.md) | Display the running processes of a container. | -| umount | [podman-umount(1)](podman-umount.1.md) | Unmount a working container's root filesystem. | -| unmount | [podman-umount(1)](podman-umount.1.md) | Unmount a working container's root filesystem. | -| unpause | [podman-unpause(1)](podman-unpause.1.md) | Unpause one or more containers. | -| wait | [podman-wait(1)](podman-wait.1.md) | Wait on one or more containers to stop and print their exit codes. | +| Command | Man Page | Description | +| --------- | --------------------------------------------------- | ---------------------------------------------------------------------------- | +| attach | [podman-attach(1)](podman-attach.1.md) | Attach to a running container. | +| checkpoint | [podman-container-checkpoint(1)](podman-container-checkpoint.1.md) | Checkpoints one or more containers. | +| cleanup | [podman-container-cleanup(1)](podman-container-cleanup.1.md) | Cleanup containers network and mountpoints. | +| commit | [podman-commit(1)](podman-commit.1.md) | Create new image based on the changed container. | +| create | [podman-create(1)](podman-create.1.md) | Create a new container. | +| diff | [podman-diff(1)](podman-diff.1.md) | Inspect changes on a container or image's filesystem. | +| exec | [podman-exec(1)](podman-exec.1.md) | Execute a command in a running container. | +| exists | [podman-container-exists(1)](podman-container-exists.1.md) | Check if a container exists in local storage | +| export | [podman-export(1)](podman-export.1.md) | Export a container's filesystem contents as a tar archive. | +| inspect | [podman-inspect(1)](podman-inspect.1.md) | Display a container or image's configuration. | +| kill | [podman-kill(1)](podman-kill.1.md) | Kill the main process in one or more containers. | +| list | [podman-ps(1)](podman-ps.1.md) | List the containers on the system.(alias ls) | +| logs | [podman-logs(1)](podman-logs.1.md) | Display the logs of a container. | +| mount | [podman-mount(1)](podman-mount.1.md) | Mount a working container's root filesystem. | +| pause | [podman-pause(1)](podman-pause.1.md) | Pause one or more containers. | +| port | [podman-port(1)](podman-port.1.md) | List port mappings for the container. | +| prune | [podman-container-prune(1)](podman-container-prune.1.md)| Remove all stopped containers from local storage. | +| restart | [podman-restart(1)](podman-restart.1.md) | Restart one or more containers. | +| restore | [podman-container-restore(1)](podman-container-restore.1.md) | Restores one or more containers from a checkpoint. | +| rm | [podman-rm(1)](podman-rm.1.md) | Remove one or more containers. | +| run | [podman-run(1)](podman-run.1.md) | Run a command in a container. | +| runlabel | [podman-container-runlabel(1)](podman-container-runlabel.1.md) | Executes a command as described by a container image label. | +| start | [podman-start(1)](podman-start.1.md) | Starts one or more containers. | +| stats | [podman-stats(1)](podman-stats.1.md) | Display a live stream of one or more container's resource usage statistics. | +| stop | [podman-stop(1)](podman-stop.1.md) | Stop one or more running containers. | +| top | [podman-top(1)](podman-top.1.md) | Display the running processes of a container. | +| umount | [podman-umount(1)](podman-umount.1.md) | Unmount a working container's root filesystem.(Alias unmount) | +| unpause | [podman-unpause(1)](podman-unpause.1.md) | Unpause one or more containers. | +| wait | [podman-wait(1)](podman-wait.1.md) | Wait on one or more containers to stop and print their exit codes. | ## SEE ALSO podman, podman-exec, podman-run diff --git a/docs/podman-generate.1.md b/docs/podman-generate.1.md index f19f48511..66afacd0b 100644 --- a/docs/podman-generate.1.md +++ b/docs/podman-generate.1.md @@ -13,7 +13,7 @@ The generate command will create structured output (like YAML) based on a contai | Command | Man Page | Description | | ------- | --------------------------------------------------- | ---------------------------------------------------------------------------- | -| kube | [podman-generate-kube(1)](podman-generate-kube.1.md) | Generate Kubernetes YAML based on a pod or container +| kube | [podman-generate-kube(1)](podman-generate-kube.1.md)| Generate Kubernetes YAML based on a pod or container. | ## SEE ALSO podman, podman-pod, podman-container diff --git a/docs/podman-image.1.md b/docs/podman-image.1.md index 5a0c4e5f9..b4ae752f6 100644 --- a/docs/podman-image.1.md +++ b/docs/podman-image.1.md @@ -11,24 +11,23 @@ The image command allows you to manage images ## COMMANDS -| Command | Man Page | Description | -| -------- | ----------------------------------------- | ------------------------------------------------------------------------------ | -| build | [podman-build(1)](podman-build.1.md) | Build a container using a Dockerfile. | -| exists | [podman-exists(1)](podman-image-exists.1.md) | Check if a image exists in local storage | -| history | [podman-history(1)](podman-history.1.md) | Show the history of an image. | -| import | [podman-import(1)](podman-import.1.md) | Import a tarball and save it as a filesystem image. | -| inspect | [podman-inspect(1)](podman-inspect.1.md) | Display a image or image's configuration. | -| list | [podman-images(1)](podman-images.1.md) | List the container images on the system. | -| load | [podman-load(1)](podman-load.1.md) | Load an image from the docker archive. | -| ls | [podman-images(1)](podman-images.1.md) | List the container images on the system. | -| pull | [podman-pull(1)](podman-pull.1.md) | Pull an image from a registry. | -| prune| [podman-container-prune(1)](podman-container-prune.1.md) | Removed all unused images from the local store | -| push | [podman-push(1)](podman-push.1.md) | Push an image from local storage to elsewhere. | -| rm | [podman-rm(1)](podman-rmi.1.md) | Removes one or more locally stored images. | -| save | [podman-save(1)](podman-save.1.md) | Save an image to docker-archive or oci. | -| tag | [podman-tag(1)](podman-tag.1.md) | Add an additional name to a local image. | -| trust | [podman-image-trust(1)](podman-image-trust.1.md) | Manage container image trust policy. | -| sign | [podman-image-sign(1)](podman-image-sign.1.md) | Sign an image. | +| Command | Man Page | Description | +| -------- | ----------------------------------------------- | --------------------------------------------------------------------------- | +| build | [podman-build(1)](podman-build.1.md) | Build a container using a Dockerfile. | +| exists | [podman-image-exists(1)](podman-image-exists.1.md) | Check if a image exists in local storage. | +| history | [podman-history(1)](podman-history.1.md) | Show the history of an image. | +| import | [podman-import(1)](podman-import.1.md) | Import a tarball and save it as a filesystem image. | +| inspect | [podman-inspect(1)](podman-inspect.1.md) | Display a image or image's configuration. | +| list | [podman-images(1)](podman-images.1.md) | List the container images on the system.(alias ls) | +| load | [podman-load(1)](podman-load.1.md) | Load an image from the docker archive. | +| prune | [podman-image-prune(1)](podman-image-prune.1.md)| Removed all unused images from the local store. | +| pull | [podman-pull(1)](podman-pull.1.md) | Pull an image from a registry. | +| push | [podman-push(1)](podman-push.1.md) | Push an image from local storage to elsewhere. | +| rm | [podman-rmi(1)](podman-rmi.1.md) | Removes one or more locally stored images. | +| save | [podman-save(1)](podman-save.1.md) | Save an image to docker-archive or oci. | +| sign | [podman-image-sign(1)](podman-image-sign.1.md) | Sign an image. | +| tag | [podman-tag(1)](podman-tag.1.md) | Add an additional name to a local image. | +| trust | [podman-image-trust(1)](podman-image-trust.1.md)| Manage container image trust policy. | ## SEE ALSO podman diff --git a/docs/podman-import.1.md b/docs/podman-import.1.md index c80c4ff77..03055018a 100644 --- a/docs/podman-import.1.md +++ b/docs/podman-import.1.md @@ -4,13 +4,14 @@ podman\-import - Import a tarball and save it as a filesystem image ## SYNOPSIS -**podman import** [*options*] *path* +**podman import** [*options*] *path* [*reference*] ## DESCRIPTION **podman import** imports a tarball (.tar, .tar.gz, .tgz, .bzip, .tar.xz, .txz) and saves it as a filesystem image. Remote tarballs can be specified using a URL. Various image instructions can be configured with the **--change** flag and a commit message can be set using the **--message** flag. +**reference**, if present, is a tag to assign to the image. Note: `:` is a restricted character and cannot be part of the file name. ## OPTIONS diff --git a/docs/podman-play.1.md b/docs/podman-play.1.md index c703c1455..6d2a7beba 100644 --- a/docs/podman-play.1.md +++ b/docs/podman-play.1.md @@ -14,7 +14,7 @@ file input. Containers will be automatically started. | Command | Man Page | Description | | ------- | --------------------------------------------------- | ---------------------------------------------------------------------------- | -| kube | [podman-play-kube(1)](podman-play-kube.1.md) | Recreate pods and containers based on Kubernetes YAML. +| kube | [podman-play-kube(1)](podman-play-kube.1.md) | Recreate pods and containers based on Kubernetes YAML. | ## SEE ALSO podman, podman-pod(1), podman-container(1), podman-generate(1), podman-play(1), podman-play-kube(1) diff --git a/docs/podman-pod-stats.1.md b/docs/podman-pod-stats.1.md new file mode 100644 index 000000000..be32f05be --- /dev/null +++ b/docs/podman-pod-stats.1.md @@ -0,0 +1,92 @@ +% podman-pod-stats "1" + +## NAME +podman\-pod\-stats - Display a live stream of resource usage statistics for the containers in one or more pods + +## SYNOPSIS +**podman pod stats** [*options*] [*pod*] + +## DESCRIPTION +Display a live stream of containers in one or more pods resource usage statistics + +## OPTIONS + +**--all, -a** + +Show all containers. Only running containers are shown by default + +**--latest, -l** + +Instead of providing the pod name or ID, use the last created pod. + +The latest option is not supported on the remote client. + +**--no-reset** + +Do not clear the terminal/screen in between reporting intervals + +**--no-stream** + +Disable streaming pod stats and only pull the first result, default setting is false + +**--format="TEMPLATE"** + +Pretty-print container statistics to JSON or using a Go template + +Valid placeholders for the Go template are listed below: + +| **Placeholder** | **Description** | +| --------------- | --------------- | +| .Pod | Pod ID | +| .CID | Container ID | +| .Name | Container Name | +| .CPU | CPU percentage | +| .MemUsage | Memory usage | +| .Mem | Memory percentage | +| .NetIO | Network IO | +| .BlockIO | Block IO | +| .PIDS | Number of PIDs | + +When using a GO template, you may preceed the format with `table` to print headers. +## EXAMPLE + +``` +# podman pod stats -a --no-stream +ID NAME CPU % MEM USAGE / LIMIT MEM % NET IO BLOCK IO PIDS +a9f807ffaacd frosty_hodgkin -- 3.092MB / 16.7GB 0.02% -- / -- -- / -- 2 +3b33001239ee sleepy_stallman -- -- / -- -- -- / -- -- / -- -- +``` + +``` +# podman pod stats --no-stream a9f80 +ID NAME CPU % MEM USAGE / LIMIT MEM % NET IO BLOCK IO PIDS +a9f807ffaacd frosty_hodgkin -- 3.092MB / 16.7GB 0.02% -- / -- -- / -- 2 +``` + +``` +# podman pod stats --no-stream --format=json a9f80 +[ + { + "id": "a9f807ffaacd", + "name": "frosty_hodgkin", + "cpu_percent": "--", + "mem_usage": "3.092MB / 16.7GB", + "mem_percent": "0.02%", + "netio": "-- / --", + "blocki": "-- / --", + "pids": "2" + } +] +``` + +``` +# podman pod-stats --no-stream --format "table {{.ID}} {{.Name}} {{.MemUsage}}" 6eae +ID NAME MEM USAGE / LIMIT +6eae9e25a564 clever_bassi 3.031MB / 16.7GB +``` + +## SEE ALSO +podman-pod(1), podman(1) + +## HISTORY +February 2019, Originally compiled by Dan Walsh <dwalsh@redhat.com> diff --git a/docs/podman-pod.1.md b/docs/podman-pod.1.md index 621348c03..8f8403a40 100644 --- a/docs/podman-pod.1.md +++ b/docs/podman-pod.1.md @@ -11,16 +11,24 @@ podman pod is a set of subcommands that manage pods, or groups of containers. ## SUBCOMMANDS -| Subcommand | Description | -| ------------------------------------------------- | ------------------------------------------------------------------------------ | -| [podman-pod-create(1)](podman-pod-create.1.md) | Create a new pod. | -| [podman-pod-kill(1)](podman-pod-kill.1.md) | Kill the main process of each container in pod. | -| [podman-pod-pause(1)](podman-pod-pause.1.md) | Pause one or more pods. | -| [podman-pod-ps(1)](podman-pod-ps.1.md) | Prints out information about pods. | -| [podman-pod-rm(1)](podman-pod-rm.1.md) | Remove one or more pods. | -| [podman-pod-start(1)](podman-pod-start.1.md) | Start one or more pods. | -| [podman-pod-stop(1)](podman-pod-stop.1.md) | Stop one or more pods. | -| [podman-pod-unpause(1)](podman-pod-unpause.1.md) | Unpause one or more pods. | +| Command | Man Page | Description | +| ------- | ------------------------------------------------- | ------------------------------------------------------------------------------ | +| create | [podman-pod-create(1)](podman-pod-create.1.md) | Create a new pod. | +| exists | [podman-pod-exists(1)](podman-pod-exists.1.md) | Check if a pod exists in local storage. | +| inspect | [podman-pod-inspect(1)](podman-pod-inspect.1.md) | Displays information describing a pod. | +| kill | [podman-pod-kill(1)](podman-pod-kill.1.md) | Kill the main process of each container in pod. | +| pause | [podman-pod-pause(1)](podman-pod-pause.1.md) | Pause one or more pods. | +| ps | [podman-pod-ps(1)](podman-pod-ps.1.md) | Prints out information about pods. | +| restart | [podman-pod-restart(1)](podman-pod-restart.1.md) | Restart one or mode pods. | +| rm | [podman-pod-rm(1)](podman-pod-rm.1.md) | Remove one or more pods. | +| start | [podman-pod-start(1)](podman-pod-start.1.md) | Start one or more pods. | +| stats | [podman-pod-stats(1)](podman-pod-stats.1.md) | Display live stream resource usage stats for containers in one or more pods. | +| stop | [podman-pod-stop(1)](podman-pod-stop.1.md) | Stop one or more pods. | +| top | [podman-pod-top(1)](podman-pod-top.1.md) | Display the running processes of containers in a pod. | +| unpause | [podman-pod-unpause(1)](podman-pod-unpause.1.md) | Unpause one or more pods. | + +## SEE ALSO +podman(1) ## HISTORY July 2018, Originally compiled by Peter Hunt <pehunt@redhat.com> diff --git a/docs/podman-system.1.md b/docs/podman-system.1.md index 1b4bccdb9..6d87648e8 100644 --- a/docs/podman-system.1.md +++ b/docs/podman-system.1.md @@ -13,8 +13,9 @@ The system command allows you to manage the podman systems | Command | Man Page | Description | | ------- | --------------------------------------------------- | ---------------------------------------------------------------------------- | -| info | [podman-system-info(1)](podman-info.1.md) | Displays Podman related system information. | +| info | [podman-info(1)](podman-info.1.md) | Displays Podman related system information. | | prune | [podman-system-prune(1)](podman-system-prune.1.md) | Remove all unused data | +| renumber | [podman-system-renumber(1)](podman-system-renumber.1.md)| Migrate lock numbers to handle a change in maximum number of locks. | ## SEE ALSO -podman +podman(1) diff --git a/docs/podman-volume.1.md b/docs/podman-volume.1.md index ac32abbd6..77728b2b5 100644 --- a/docs/podman-volume.1.md +++ b/docs/podman-volume.1.md @@ -11,13 +11,16 @@ podman volume is a set of subcommands that manage volumes. ## SUBCOMMANDS -| Subcommand | Description | -| ------------------------------------------------- | ------------------------------------------------------------------------------ | -| [podman-volume-create(1)](podman-volume-create.1.md) | Create a new volume. | -| [podman-volume-inspect(1)](podman-volume-inspect.1.md) | Get detailed information on one or more volumes. | -| [podman-volume-ls(1)](podman-volume-ls.1.md) | List all the available volumes. | -| [podman-volume-rm(1)](podman-volume-rm.1.md) | Remove one or more volumes. | -| [podman-volume-prune(1)](podman-volume-prune.1.md) | Remove all unused volumes. | +| Command | Man Page | Description | +| ------- | ------------------------------------------------------ | ------------------------------------------------------------------------------ | +| create | [podman-volume-create(1)](podman-volume-create.1.md) | Create a new volume. | +| inspect | [podman-volume-inspect(1)](podman-volume-inspect.1.md) | Get detailed information on one or more volumes. | +| ls | [podman-volume-ls(1)](podman-volume-ls.1.md) | List all the available volumes. | +| prune | [podman-volume-prune(1)](podman-volume-prune.1.md) | Remove all unused volumes. | +| rm | [podman-volume-rm(1)](podman-volume-rm.1.md) | Remove one or more volumes. | + +## SEE ALSO +podman(1) ## HISTORY November 2018, Originally compiled by Urvashi Mohnani <umohnani@redhat.com> diff --git a/docs/podman.1.md b/docs/podman.1.md index 760f27310..bc03d3c5a 100644 --- a/docs/podman.1.md +++ b/docs/podman.1.md @@ -72,7 +72,7 @@ Default state dir is configured in /etc/containers/storage.conf. Name of the OCI runtime as specified in libpod.conf or absolute path to the OCI compatible binary used to run containers. -**--storage-driver, -s**=**value** +**--storage-driver**=**value** Storage driver. The default storage driver for UID 0 is configured in /etc/containers/storage.conf (`$HOME/.config/containers/storage.conf` in rootless mode), and is *vfs* for non-root users when *fuse-overlayfs* is not available. The `STORAGE_DRIVER` environment variable overrides the default. The --storage-driver specified driver overrides all. @@ -136,6 +136,7 @@ the exit codes follow the `chroot` standard, see below: | [podman-diff(1)](podman-diff.1.md) | Inspect changes on a container or image's filesystem. | | [podman-exec(1)](podman-exec.1.md) | Execute a command in a running container. | | [podman-export(1)](podman-export.1.md) | Export a container's filesystem contents as a tar archive. | +| [podman-generate(1)](podman-generate.1.md)| Generate structured data based for a containers and pods. | | [podman-history(1)](podman-history.1.md) | Show the history of an image. | | [podman-image(1)](podman-image.1.md) | Manage Images. | | [podman-images(1)](podman-images.1.md) | List images in local storage. | @@ -149,6 +150,8 @@ the exit codes follow the `chroot` standard, see below: | [podman-logs(1)](podman-logs.1.md) | Display the logs of a container. | | [podman-mount(1)](podman-mount.1.md) | Mount a working container's root filesystem. | | [podman-pause(1)](podman-pause.1.md) | Pause one or more containers. | +| [podman-play(1)](podman-play.1.md) | Play pods and containers based on a structured input file. | +| [podman-pod(1)](podman-pod.1.md) | Management tool for groups of containers, called pods. | | [podman-port(1)](podman-port.1.md) | List port mappings for the container. | | [podman-ps(1)](podman-ps.1.md) | Prints out information about containers. | | [podman-pull(1)](podman-pull.1.md) | Pull an image from a registry. | @@ -167,8 +170,9 @@ the exit codes follow the `chroot` standard, see below: | [podman-top(1)](podman-top.1.md) | Display the running processes of a container. | | [podman-umount(1)](podman-umount.1.md) | Unmount a working container's root filesystem. | | [podman-unpause(1)](podman-unpause.1.md) | Unpause one or more containers. | -| [podman-version(1)](podman-version.1.md) | Display the Podman version information. | -| [podman-volume(1)](podman-volume.1.md) | Manage Volumes. | +| [podman-varlink(1)](podman-varlink.1.md) | Display the Podman version information. | +| [podman-version(1)](podman-version.1.md) | Runs the varlink backend interface. | +| [podman-volume(1)](podman-volume.1.md) | Manage Volumes. | | [podman-wait(1)](podman-wait.1.md) | Wait on one or more containers to stop and print their exit codes. | ## FILES diff --git a/hack/podman-commands.sh b/hack/podman-commands.sh new file mode 100755 index 000000000..754f2923d --- /dev/null +++ b/hack/podman-commands.sh @@ -0,0 +1,82 @@ +#!/bin/bash +# +# Compare commands listed by 'podman help' against those in 'man podman'. +# Recurse into subcommands as well. +# +# Because we read metadoc files in the `docs` directory, this script +# must run from the top level of a git checkout. FIXME: if necessary, +# it could instead run 'man podman-XX'; my thinking is that this +# script should run early in CI. +# + +# override with, e.g., PODMAN=./bin/podman-remote +PODMAN=${PODMAN:-./bin/podman} + +function die() { + echo "FATAL: $*" >&2 + exit 1 +} + + +# Run 'podman help' (possibly against a subcommand, e.g. 'podman help image') +# and return a list of each first word under 'Available Commands', that is, +# the command name but not its description. +function podman_commands() { + $PODMAN help "$@" |\ + awk '/^Available Commands:/{ok=1;next}/^Flags:/{ok=0}ok { print $1 }' |\ + grep . +} + +# Read a list of subcommands from a command's metadoc +function podman_man() { + if [ "$@" = "podman" ]; then + # podman itself. + # 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 + elif [ "$@" = "podman-image-trust" ]; then + # Special case: set and show aren't actually in a table in the man page + echo set + echo show + else + # podman subcommand. + # Each md file has a table of the form: + # | 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 + fi +} + +# The main thing. Compares help and man page; if we find subcommands, recurse. +rc=0 +function compare_help_and_man() { + echo + echo "checking: podman $@" + + # e.g. podman, podman-image, podman-volume + local basename=$(echo podman "$@" | sed -e 's/ /-/g') + + podman_commands "$@" | sort > /tmp/${basename}_help.txt + podman_man $basename | sort > /tmp/${basename}_man.txt + + diff -u /tmp/${basename}_help.txt /tmp/${basename}_man.txt || rc=1 + + # Now look for subcommands, e.g. container, image + for cmd in $(< /tmp/${basename}_help.txt); do + usage=$($PODMAN "$@" $cmd --help | grep -A1 '^Usage:' | tail -1) + + # if string ends in '[command]', recurse into its subcommands + if expr "$usage" : '.*\[command\]$' >/dev/null; then + compare_help_and_man "$@" $cmd + fi + done + + rm -f /tmp/${basename}_{help,man}.txt +} + + +compare_help_and_man + +exit $rc diff --git a/libpod/container_api.go b/libpod/container_api.go index 09d7f220d..6bef3c47d 100644 --- a/libpod/container_api.go +++ b/libpod/container_api.go @@ -203,9 +203,8 @@ func (c *Container) Kill(signal uint) error { } // Exec starts a new process inside the container -// TODO allow specifying streams to attach to // TODO investigate allowing exec without attaching -func (c *Container) Exec(tty, privileged bool, env, cmd []string, user, workDir string) error { +func (c *Container) Exec(tty, privileged bool, env, cmd []string, user, workDir string, streams *AttachStreams) error { var capList []string locked := false @@ -267,7 +266,7 @@ func (c *Container) Exec(tty, privileged bool, env, cmd []string, user, workDir logrus.Debugf("Creating new exec session in container %s with session id %s", c.ID(), sessionID) - execCmd, err := c.runtime.ociRuntime.execContainer(c, cmd, capList, env, tty, workDir, hostUser, sessionID) + execCmd, err := c.runtime.ociRuntime.execContainer(c, cmd, capList, env, tty, workDir, hostUser, sessionID, streams) if err != nil { return errors.Wrapf(err, "error exec %s", c.ID()) } diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index b074efa3a..0e9a5124e 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -472,10 +472,19 @@ func (c *Container) addNamespaceContainer(g *generate.Generator, ns LinuxNS, ctr return nil } -func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointOptions) (err error) { - +func (c *Container) checkpointRestoreSupported() (err error) { if !criu.CheckForCriu() { - return errors.Errorf("checkpointing a container requires at least CRIU %d", criu.MinCriuVersion) + return errors.Errorf("Checkpoint/Restore requires at least CRIU %d", criu.MinCriuVersion) + } + if !c.runtime.ociRuntime.featureCheckCheckpointing() { + return errors.Errorf("Configured runtime does not support checkpoint/restore") + } + return nil +} + +func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointOptions) (err error) { + if err := c.checkpointRestoreSupported(); err != nil { + return err } if c.state.State != ContainerStateRunning { @@ -532,8 +541,8 @@ func (c *Container) checkpoint(ctx context.Context, options ContainerCheckpointO func (c *Container) restore(ctx context.Context, options ContainerCheckpointOptions) (err error) { - if !criu.CheckForCriu() { - return errors.Errorf("restoring a container requires at least CRIU %d", criu.MinCriuVersion) + if err := c.checkpointRestoreSupported(); err != nil { + return err } if (c.state.State != ContainerStateConfigured) && (c.state.State != ContainerStateExited) { diff --git a/libpod/oci.go b/libpod/oci.go index 26d2c6ef1..2b3cc5db5 100644 --- a/libpod/oci.go +++ b/libpod/oci.go @@ -733,7 +733,7 @@ func (r *OCIRuntime) unpauseContainer(ctr *Container) error { // TODO: Add --detach support // TODO: Convert to use conmon // TODO: add --pid-file and use that to generate exec session tracking -func (r *OCIRuntime) execContainer(c *Container, cmd, capAdd, env []string, tty bool, cwd, user, sessionID string) (*exec.Cmd, error) { +func (r *OCIRuntime) execContainer(c *Container, cmd, capAdd, env []string, tty bool, cwd, user, sessionID string, streams *AttachStreams) (*exec.Cmd, error) { if len(cmd) == 0 { return nil, errors.Wrapf(ErrInvalidArg, "must provide a command to execute") } @@ -789,9 +789,17 @@ func (r *OCIRuntime) execContainer(c *Container, cmd, capAdd, env []string, tty logrus.Debugf("Starting runtime %s with following arguments: %v", r.path, args) execCmd := exec.Command(r.path, args...) - execCmd.Stdout = os.Stdout - execCmd.Stderr = os.Stderr - execCmd.Stdin = os.Stdin + + if streams.AttachOutput { + execCmd.Stdout = streams.OutputStream + } + if streams.AttachInput { + execCmd.Stdin = streams.InputStream + } + if streams.AttachError { + execCmd.Stderr = streams.ErrorStream + } + execCmd.Env = append(execCmd.Env, fmt.Sprintf("XDG_RUNTIME_DIR=%s", runtimeDir)) if err := execCmd.Start(); err != nil { @@ -890,3 +898,16 @@ func (r *OCIRuntime) checkpointContainer(ctr *Container, options ContainerCheckp args = append(args, ctr.ID()) return utils.ExecCmdWithStdStreams(os.Stdin, os.Stdout, os.Stderr, nil, r.path, args...) } + +func (r *OCIRuntime) featureCheckCheckpointing() bool { + // Check if the runtime implements checkpointing. Currently only + // runc's checkpoint/restore implementation is supported. + cmd := exec.Command(r.path, "checkpoint", "-h") + if err := cmd.Start(); err != nil { + return false + } + if err := cmd.Wait(); err == nil { + return true + } + return false +} diff --git a/libpod/options.go b/libpod/options.go index 184d5d59f..1e8592a25 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -1248,6 +1248,22 @@ func WithVolumeOptions(options map[string]string) VolumeCreateOption { } } +// withSetCtrSpecific sets a bool notifying libpod that a volume was created +// specifically for a container. +// These volumes will be removed when the container is removed and volumes are +// also specified for removal. +func withSetCtrSpecific() VolumeCreateOption { + return func(volume *Volume) error { + if volume.valid { + return ErrVolumeFinalized + } + + volume.config.IsCtrSpecific = true + + return nil + } +} + // Pod Creation Options // WithPodName sets the name of the pod. diff --git a/libpod/runtime.go b/libpod/runtime.go index 827c22f5b..f53cdd8b8 100644 --- a/libpod/runtime.go +++ b/libpod/runtime.go @@ -331,16 +331,13 @@ func NewRuntime(options ...RuntimeOption) (runtime *Runtime, err error) { deepcopier.Copy(defaultRuntimeConfig).To(runtime.config) runtime.config.TmpDir = tmpDir - if rootless.IsRootless() { - // If we're rootless, override the default storage config - storageConf, volumePath, err := util.GetDefaultStoreOptions() - if err != nil { - return nil, errors.Wrapf(err, "error retrieving rootless storage config") - } - runtime.config.StorageConfig = storageConf - runtime.config.StaticDir = filepath.Join(storageConf.GraphRoot, "libpod") - runtime.config.VolumePath = volumePath + storageConf, err := util.GetDefaultStoreOptions() + if err != nil { + return nil, errors.Wrapf(err, "error retrieving rootless storage config") } + runtime.config.StorageConfig = storageConf + runtime.config.StaticDir = filepath.Join(storageConf.GraphRoot, "libpod") + runtime.config.VolumePath = filepath.Join(storageConf.GraphRoot, "volumes") configPath := ConfigPath foundConfig := true diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go index 2ec8d0795..cfa4f9654 100644 --- a/libpod/runtime_ctr.go +++ b/libpod/runtime_ctr.go @@ -180,7 +180,7 @@ func (r *Runtime) newContainer(ctx context.Context, rSpec *spec.Spec, options .. if vol.Source[0] != '/' && isNamedVolume(vol.Source) { volInfo, err := r.state.Volume(vol.Source) if err != nil { - newVol, err := r.newVolume(ctx, WithVolumeName(vol.Source)) + newVol, err := r.newVolume(ctx, WithVolumeName(vol.Source), withSetCtrSpecific()) if err != nil { return nil, errors.Wrapf(err, "error creating named volume %q", vol.Source) } @@ -421,6 +421,9 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force bool, for _, v := range volumes { if volume, err := runtime.state.Volume(v); err == nil { + if !volume.IsCtrSpecific() { + continue + } if err := runtime.removeVolume(ctx, volume, false); err != nil && err != ErrNoSuchVolume && err != ErrVolumeBeingUsed { logrus.Errorf("cleanup volume (%s): %v", v, err) } diff --git a/libpod/volume.go b/libpod/volume.go index 74878b6a4..0c7618841 100644 --- a/libpod/volume.go +++ b/libpod/volume.go @@ -15,11 +15,12 @@ type VolumeConfig struct { // Name of the volume Name string `json:"name"` - Labels map[string]string `json:"labels"` - MountPoint string `json:"mountPoint"` - Driver string `json:"driver"` - Options map[string]string `json:"options"` - Scope string `json:"scope"` + Labels map[string]string `json:"labels"` + MountPoint string `json:"mountPoint"` + Driver string `json:"driver"` + Options map[string]string `json:"options"` + Scope string `json:"scope"` + IsCtrSpecific bool `json:"ctrSpecific"` } // Name retrieves the volume's name @@ -60,3 +61,10 @@ func (v *Volume) Options() map[string]string { func (v *Volume) Scope() string { return v.config.Scope } + +// IsCtrSpecific returns whether this volume was created specifically for a +// given container. Images with this set to true will be removed when the +// container is removed with the Volumes parameter set to true. +func (v *Volume) IsCtrSpecific() bool { + return v.config.IsCtrSpecific +} diff --git a/pkg/adapter/runtime.go b/pkg/adapter/runtime.go index 4f5b98dbb..8624981b1 100644 --- a/pkg/adapter/runtime.go +++ b/pkg/adapter/runtime.go @@ -333,3 +333,11 @@ func (r *LocalRuntime) LoadImage(ctx context.Context, name string, cli *cliconfi } return r.Runtime.LoadImage(ctx, name, cli.Input, writer, cli.SignaturePolicy) } + +// IsImageNotFound checks if the error indicates that no image was found. +func IsImageNotFound(err error) bool { + if errors.Cause(err) == image.ErrNoSuchImage { + return true + } + return false +} diff --git a/pkg/adapter/runtime_remote.go b/pkg/adapter/runtime_remote.go index ca2fad852..29b43e9b0 100644 --- a/pkg/adapter/runtime_remote.go +++ b/pkg/adapter/runtime_remote.go @@ -796,3 +796,15 @@ func (r *LocalRuntime) LoadImage(ctx context.Context, name string, cli *cliconfi } return names, nil } + +// IsImageNotFound checks if the error indicates that no image was found. +func IsImageNotFound(err error) bool { + if errors.Cause(err) == image.ErrNoSuchImage { + return true + } + switch err.(type) { + case *iopodman.ImageNotFound: + return true + } + return false +} diff --git a/pkg/rootless/rootless_linux.go b/pkg/rootless/rootless_linux.go index 9a192c0fa..98692707f 100644 --- a/pkg/rootless/rootless_linux.go +++ b/pkg/rootless/rootless_linux.go @@ -93,7 +93,8 @@ func tryMappingTool(tool string, pid int, hostID int, mappings []idtools.IDMap) Args: args, } - if err := cmd.Run(); err != nil { + if output, err := cmd.CombinedOutput(); err != nil { + logrus.Debugf("error from %s: %s", tool, output) return errors.Wrapf(err, "cannot setup namespace using %s", tool) } return nil diff --git a/pkg/secrets/secrets.go b/pkg/secrets/secrets.go index 242953609..3b64f8952 100644 --- a/pkg/secrets/secrets.go +++ b/pkg/secrets/secrets.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/containers/libpod/pkg/rootless" + "github.com/containers/storage/pkg/idtools" rspec "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/selinux/go-selinux/label" "github.com/pkg/errors" @@ -176,7 +177,7 @@ func SecretMountsWithUIDGID(mountLabel, containerWorkingDir, mountFile, mountPre // Add FIPS mode secret if /etc/system-fips exists on the host _, err := os.Stat("/etc/system-fips") if err == nil { - if err := addFIPSModeSecret(&secretMounts, containerWorkingDir); err != nil { + if err := addFIPSModeSecret(&secretMounts, containerWorkingDir, mountPrefix, mountLabel, uid, gid); err != nil { logrus.Errorf("error adding FIPS mode secret to container: %v", err) } } else if os.IsNotExist(err) { @@ -264,13 +265,16 @@ func addSecretsFromMountsFile(filePath, mountLabel, containerWorkingDir, mountPr // root filesystem if /etc/system-fips exists on hosts. // This enables the container to be FIPS compliant and run openssl in // FIPS mode as the host is also in FIPS mode. -func addFIPSModeSecret(mounts *[]rspec.Mount, containerWorkingDir string) error { +func addFIPSModeSecret(mounts *[]rspec.Mount, containerWorkingDir, mountPrefix, mountLabel string, uid, gid int) error { secretsDir := "/run/secrets" ctrDirOnHost := filepath.Join(containerWorkingDir, secretsDir) if _, err := os.Stat(ctrDirOnHost); os.IsNotExist(err) { - if err = os.MkdirAll(ctrDirOnHost, 0755); err != nil { + if err = idtools.MkdirAllAs(ctrDirOnHost, 0755, uid, gid); err != nil { return errors.Wrapf(err, "making container directory on host failed") } + if err = label.Relabel(ctrDirOnHost, mountLabel, false); err != nil { + return errors.Wrap(err, "error applying correct labels") + } } fipsFile := filepath.Join(ctrDirOnHost, "system-fips") // In the event of restart, it is possible for the FIPS mode file to already exist @@ -284,7 +288,7 @@ func addFIPSModeSecret(mounts *[]rspec.Mount, containerWorkingDir string) error if !mountExists(*mounts, secretsDir) { m := rspec.Mount{ - Source: ctrDirOnHost, + Source: filepath.Join(mountPrefix, secretsDir), Destination: secretsDir, Type: "bind", Options: []string{"bind", "rprivate"}, diff --git a/pkg/spec/createconfig.go b/pkg/spec/createconfig.go index 50e07ee74..31039bfdf 100644 --- a/pkg/spec/createconfig.go +++ b/pkg/spec/createconfig.go @@ -240,7 +240,7 @@ func (c *CreateConfig) GetVolumeMounts(specMounts []spec.Mount) ([]spec.Mount, e } for vol := range c.BuiltinImgVolumes { - if libpod.MountExists(specMounts, vol) { + if libpod.MountExists(specMounts, vol) || libpod.MountExists(m, vol) { continue } diff --git a/pkg/util/utils.go b/pkg/util/utils.go index db8a3d5bb..a4576191b 100644 --- a/pkg/util/utils.go +++ b/pkg/util/utils.go @@ -259,15 +259,6 @@ func GetRootlessStorageOpts() (storage.StoreOptions, error) { return opts, nil } -// GetRootlessVolumePath returns where all the name volumes will be created in rootless mode -func GetRootlessVolumePath() (string, error) { - dataDir, _, err := GetRootlessDirInfo() - if err != nil { - return "", err - } - return filepath.Join(dataDir, "containers", "storage", "volumes"), nil -} - type tomlOptionsConfig struct { MountProgram string `toml:"mount_program"` } @@ -297,25 +288,18 @@ func getTomlStorage(storeOptions *storage.StoreOptions) *tomlConfig { return config } -// GetDefaultStoreOptions returns the storage ops for containers and the volume path -// for the volume API -// It also returns the path where all named volumes will be created using the volume API -func GetDefaultStoreOptions() (storage.StoreOptions, string, error) { +// GetDefaultStoreOptions returns the default storage ops for containers +func GetDefaultStoreOptions() (storage.StoreOptions, error) { var ( defaultRootlessRunRoot string defaultRootlessGraphRoot string err error ) storageOpts := storage.DefaultStoreOptions - volumePath := filepath.Join(storageOpts.GraphRoot, "volumes") if rootless.IsRootless() { storageOpts, err = GetRootlessStorageOpts() if err != nil { - return storageOpts, volumePath, err - } - volumePath, err = GetRootlessVolumePath() - if err != nil { - return storageOpts, volumePath, err + return storageOpts, err } } @@ -332,7 +316,7 @@ func GetDefaultStoreOptions() (storage.StoreOptions, string, error) { os.MkdirAll(filepath.Dir(storageConf), 0755) file, err := os.OpenFile(storageConf, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666) if err != nil { - return storageOpts, volumePath, errors.Wrapf(err, "cannot open %s", storageConf) + return storageOpts, errors.Wrapf(err, "cannot open %s", storageConf) } tomlConfiguration := getTomlStorage(&storageOpts) @@ -353,7 +337,7 @@ func GetDefaultStoreOptions() (storage.StoreOptions, string, error) { } } } - return storageOpts, volumePath, nil + return storageOpts, nil } // StorageConfigFile returns the path to the storage config file used diff --git a/remote_client.md b/remote_client.md new file mode 100644 index 000000000..be5c918c8 --- /dev/null +++ b/remote_client.md @@ -0,0 +1,77 @@ +# Podman remote-client tutorial + +## What is the remote-client + +First and foremost, the remote-client is under heavy development. We are adding new +commands and functions frequently. We also are working on a rootless implementation that +does not require privileged users. + +The purpose of the Podman remote-client is to allow users to interact with a Podman "backend" +while on a separate client. The command line interface of the remote client is exactly the +same as the regular Podman commands with the exception of some flags being removed as they +do not apply to the remote-client. + +## What you need +To use the remote-client, you will need a binary for your client and a Podman "backend"; hereafter +referred to as the Podman node. In this context, a Podman node is a Linux system with Podman +installed on it and the varlink service activated. You will also need to be able to ssh into this +system as a user with privileges to the varlink socket (more on this later). + +## Building the remote client +At this time, the remote-client is not being packaged for any distribution. It must be built from +source. To set up your build environment, see [Installation notes](install.md) and follow the +section [Building from scratch](install.md#building-from-scratch). Once you can successfully +build the regular Podman binary, you can now build the remote-client. +``` +$ make podman-remote +``` +Like building the regular Podman, the resulting binary will be in the *bin* directory. This is the binary +you will run on the remote node later in the instructions. + +## Setting up the remote and Podman nodes + +To use the remote-client, you must perform some setup on both the remote and Podman nodes. In this case, +the remote node refers to where the remote-client is being run; and the Podman node refers to where +Podman and its storage reside. + +### Podman node setup +The Podman node must have Podman (not the remote-client) installed as normal. If your system uses systemd, +then simply start the Podman varlink socket. +``` +$ sudo systemctl start io.podman.socket +``` + +If your system cannot use systemd, then you can manually establish the varlink socket with the Podman +command: +``` +$ sudo podman --log-level debug varlink --timeout 0 unix://run/podman/io.podman +``` + +### Required permissions +For now, the remote-client requires that you be able to run a privileged Podman and have privileged ssh +access to the remote system. This limitation is being worked on. + +### Remote node setup + +#### Initiate an ssh session to the Podman node +To use the remote client, we must establish an ssh connection to the Podman server. We will also use +that session to bind the remote varlink socket locally. + +``` +$ ssh -L 127.0.0.1:1234:/run/podman/io.podman root@remotehost +``` +Note here we are binding the Podman socket to a local TCP socket on port 1234. + +#### Running the remote client +With the ssh session established, we can now run the remote client in a different terminal window. You +must inform Podman where to look for the bound socket you created in the previous step using an +environment variable. + +``` +$ PODMAN_VARLINK_ADDRESS="tcp:127.0.0.1:1234" bin/podman-remote images +REPOSITORY TAG IMAGE ID CREATED SIZE +docker.io/library/ubuntu latest 47b19964fb50 2 weeks ago 90.7 MB +docker.io/library/alpine latest caf27325b298 3 weeks ago 5.8 MB +quay.io/cevich/gcloud_centos latest 641dad61989a 5 weeks ago 489 MB +k8s.gcr.io/pause 3.1 da86e6ba6ca1 14 months ago 747 kB +``` diff --git a/test/e2e/checkpoint_test.go b/test/e2e/checkpoint_test.go index fda6eb085..583432df1 100644 --- a/test/e2e/checkpoint_test.go +++ b/test/e2e/checkpoint_test.go @@ -6,6 +6,7 @@ import ( "fmt" "net" "os" + "os/exec" "github.com/containers/libpod/pkg/criu" . "github.com/containers/libpod/test/utils" @@ -27,9 +28,26 @@ var _ = Describe("Podman checkpoint", func() { } podmanTest = PodmanTestCreate(tempdir) podmanTest.RestoreAllArtifacts() + // Check if the runtime implements checkpointing. Currently only + // runc's checkpoint/restore implementation is supported. + cmd := exec.Command(podmanTest.OCIRuntime, "checkpoint", "-h") + if err := cmd.Start(); err != nil { + Skip("OCI runtime does not support checkpoint/restore") + } + if err := cmd.Wait(); err != nil { + Skip("OCI runtime does not support checkpoint/restore") + } + if !criu.CheckForCriu() { Skip("CRIU is missing or too old.") } + // TODO: Remove the skip when the current CRIU SELinux problem is solved. + // See: https://github.com/containers/libpod/issues/2334 + hostInfo := podmanTest.Host + if hostInfo.Distribution == "fedora" { + Skip("Checkpointing containers on Fedora currently broken.") + } + }) AfterEach(func() { diff --git a/test/e2e/load_test.go b/test/e2e/load_test.go index c85810454..571754347 100644 --- a/test/e2e/load_test.go +++ b/test/e2e/load_test.go @@ -59,7 +59,7 @@ var _ = Describe("Podman load", func() { Expect(save.ExitCode()).To(Equal(0)) compress := SystemExec("gzip", []string{outfile}) - compress.WaitWithDefaultTimeout() + Expect(compress.ExitCode()).To(Equal(0)) outfile = outfile + ".gz" rmi := podmanTest.Podman([]string{"rmi", ALPINE}) @@ -174,7 +174,6 @@ var _ = Describe("Podman load", func() { It("podman load localhost registry from scratch", func() { outfile := filepath.Join(podmanTest.TempDir, "load_test.tar.gz") - setup := podmanTest.Podman([]string{"tag", ALPINE, "hello:world"}) setup.WaitWithDefaultTimeout() Expect(setup.ExitCode()).To(Equal(0)) @@ -255,7 +254,6 @@ var _ = Describe("Podman load", func() { save.WaitWithDefaultTimeout() Expect(save.ExitCode()).To(Equal(0)) session := SystemExec("xz", []string{outfile}) - session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) rmi := podmanTest.Podman([]string{"rmi", BB}) diff --git a/test/e2e/pod_create_test.go b/test/e2e/pod_create_test.go index cb2b0e7b0..4717267a1 100644 --- a/test/e2e/pod_create_test.go +++ b/test/e2e/pod_create_test.go @@ -95,7 +95,6 @@ var _ = Describe("Podman pod create", func() { Expect(webserver.ExitCode()).To(Equal(0)) check := SystemExec("nc", []string{"-z", "localhost", "80"}) - check.WaitWithDefaultTimeout() Expect(check.ExitCode()).To(Equal(1)) }) @@ -111,7 +110,6 @@ var _ = Describe("Podman pod create", func() { Expect(webserver.ExitCode()).To(Equal(0)) check := SystemExec("nc", []string{"-z", "localhost", "80"}) - check.WaitWithDefaultTimeout() Expect(check.ExitCode()).To(Equal(0)) }) diff --git a/test/e2e/pull_test.go b/test/e2e/pull_test.go index faad8202e..d9b9c7213 100644 --- a/test/e2e/pull_test.go +++ b/test/e2e/pull_test.go @@ -6,10 +6,12 @@ import ( "os" "fmt" + "path/filepath" + "strings" + . "github.com/containers/libpod/test/utils" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "strings" ) var _ = Describe("Podman pull", func() { @@ -92,58 +94,56 @@ var _ = Describe("Podman pull", func() { }) It("podman pull from docker-archive", func() { - session := podmanTest.Podman([]string{"save", "-o", "/tmp/alp.tar", "alpine"}) + tarfn := filepath.Join(podmanTest.TempDir, "alp.tar") + session := podmanTest.Podman([]string{"save", "-o", tarfn, "alpine"}) session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) session = podmanTest.Podman([]string{"rmi", "alpine"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) - session = podmanTest.Podman([]string{"pull", "docker-archive:/tmp/alp.tar"}) + session = podmanTest.Podman([]string{"pull", fmt.Sprintf("docker-archive:%s", tarfn)}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) session = podmanTest.Podman([]string{"rmi", "alpine"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) - clean := SystemExec("rm", []string{"/tmp/alp.tar"}) - clean.WaitWithDefaultTimeout() - Expect(clean.ExitCode()).To(Equal(0)) }) It("podman pull from oci-archive", func() { - session := podmanTest.Podman([]string{"save", "--format", "oci-archive", "-o", "/tmp/oci-alp.tar", "alpine"}) + tarfn := filepath.Join(podmanTest.TempDir, "oci-alp.tar") + session := podmanTest.Podman([]string{"save", "--format", "oci-archive", "-o", tarfn, "alpine"}) session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) session = podmanTest.Podman([]string{"rmi", "alpine"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) - session = podmanTest.Podman([]string{"pull", "oci-archive:/tmp/oci-alp.tar"}) + session = podmanTest.Podman([]string{"pull", fmt.Sprintf("oci-archive:%s", tarfn)}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) session = podmanTest.Podman([]string{"rmi", "alpine"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) - clean := SystemExec("rm", []string{"/tmp/oci-alp.tar"}) - clean.WaitWithDefaultTimeout() }) It("podman pull from local directory", func() { - setup := SystemExec("mkdir", []string{"-p", "/tmp/podmantestdir"}) - setup.WaitWithDefaultTimeout() - session := podmanTest.Podman([]string{"push", "alpine", "dir:/tmp/podmantestdir"}) + dirpath := filepath.Join(podmanTest.TempDir, "alpine") + os.MkdirAll(dirpath, os.ModePerm) + imgPath := fmt.Sprintf("dir:%s", dirpath) + + session := podmanTest.Podman([]string{"push", "alpine", imgPath}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) session = podmanTest.Podman([]string{"rmi", "alpine"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) - session = podmanTest.Podman([]string{"pull", "dir:/tmp/podmantestdir"}) + session = podmanTest.Podman([]string{"pull", imgPath}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) - session = podmanTest.Podman([]string{"rmi", "podmantestdir"}) + session = podmanTest.Podman([]string{"rmi", "alpine"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) - - clean := SystemExec("rm", []string{"-fr", "/tmp/podmantestdir"}) - clean.WaitWithDefaultTimeout() }) It("podman pull check quiet", func() { diff --git a/test/e2e/push_test.go b/test/e2e/push_test.go index 42aefd1f7..fee117783 100644 --- a/test/e2e/push_test.go +++ b/test/e2e/push_test.go @@ -51,13 +51,11 @@ var _ = Describe("Podman push", func() { }) It("podman push to dir", func() { - session := podmanTest.Podman([]string{"push", "--remove-signatures", ALPINE, "dir:/tmp/busybox"}) + bbdir := filepath.Join(podmanTest.TempDir, "busybox") + session := podmanTest.Podman([]string{"push", "--remove-signatures", ALPINE, + fmt.Sprintf("dir:%s", bbdir)}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) - - clean := SystemExec("rm", []string{"-fr", "/tmp/busybox"}) - clean.WaitWithDefaultTimeout() - Expect(clean.ExitCode()).To(Equal(0)) }) It("podman push to local registry", func() { @@ -85,20 +83,21 @@ var _ = Describe("Podman push", func() { authPath := filepath.Join(podmanTest.TempDir, "auth") os.Mkdir(authPath, os.ModePerm) os.MkdirAll("/etc/containers/certs.d/localhost:5000", os.ModePerm) - debug := SystemExec("ls", []string{"-l", podmanTest.TempDir}) - debug.WaitWithDefaultTimeout() + defer os.RemoveAll("/etc/containers/certs.d/localhost:5000") cwd, _ := os.Getwd() certPath := filepath.Join(cwd, "../", "certs") if IsCommandAvailable("getenforce") { ge := SystemExec("getenforce", []string{}) - ge.WaitWithDefaultTimeout() + Expect(ge.ExitCode()).To(Equal(0)) if ge.OutputToString() == "Enforcing" { se := SystemExec("setenforce", []string{"0"}) - se.WaitWithDefaultTimeout() - - defer SystemExec("setenforce", []string{"1"}) + Expect(se.ExitCode()).To(Equal(0)) + defer func() { + se2 := SystemExec("setenforce", []string{"1"}) + Expect(se2.ExitCode()).To(Equal(0)) + }() } } podmanTest.RestoreArtifact(registry) @@ -111,8 +110,6 @@ var _ = Describe("Podman push", func() { f.WriteString(session.OutputToString()) f.Sync() - debug = SystemExec("cat", []string{filepath.Join(authPath, "htpasswd")}) - debug.WaitWithDefaultTimeout() session = podmanTest.Podman([]string{"run", "-d", "-p", "5000:5000", "--name", "registry", "-v", strings.Join([]string{authPath, "/auth"}, ":"), "-e", "REGISTRY_AUTH=htpasswd", "-e", @@ -138,8 +135,7 @@ var _ = Describe("Podman push", func() { Expect(push.ExitCode()).To(Equal(0)) setup := SystemExec("cp", []string{filepath.Join(certPath, "domain.crt"), "/etc/containers/certs.d/localhost:5000/ca.crt"}) - setup.WaitWithDefaultTimeout() - defer os.RemoveAll("/etc/containers/certs.d/localhost:5000") + Expect(setup.ExitCode()).To(Equal(0)) push = podmanTest.Podman([]string{"push", "--creds=podmantest:wrongpasswd", ALPINE, "localhost:5000/credstest"}) push.WaitWithDefaultTimeout() @@ -155,23 +151,22 @@ var _ = Describe("Podman push", func() { }) It("podman push to docker-archive", func() { - session := podmanTest.Podman([]string{"push", ALPINE, "docker-archive:/tmp/alp:latest"}) + tarfn := filepath.Join(podmanTest.TempDir, "alp.tar") + session := podmanTest.Podman([]string{"push", ALPINE, + fmt.Sprintf("docker-archive:%s:latest", tarfn)}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) - clean := SystemExec("rm", []string{"/tmp/alp"}) - clean.WaitWithDefaultTimeout() - Expect(clean.ExitCode()).To(Equal(0)) }) It("podman push to docker daemon", func() { setup := SystemExec("bash", []string{"-c", "systemctl status docker 2>&1"}) - setup.WaitWithDefaultTimeout() if setup.LineInOutputContains("Active: inactive") { setup = SystemExec("systemctl", []string{"start", "docker"}) - setup.WaitWithDefaultTimeout() - - defer SystemExec("systemctl", []string{"stop", "docker"}) + defer func() { + stop := SystemExec("systemctl", []string{"stop", "docker"}) + Expect(stop.ExitCode()).To(Equal(0)) + }() } else if setup.ExitCode() != 0 { Skip("Docker is not available") } @@ -181,22 +176,19 @@ var _ = Describe("Podman push", func() { Expect(session.ExitCode()).To(Equal(0)) check := SystemExec("docker", []string{"images", "--format", "{{.Repository}}:{{.Tag}}"}) - check.WaitWithDefaultTimeout() Expect(check.ExitCode()).To(Equal(0)) Expect(check.OutputToString()).To(ContainSubstring("alpine:podmantest")) clean := SystemExec("docker", []string{"rmi", "alpine:podmantest"}) - clean.WaitWithDefaultTimeout() Expect(clean.ExitCode()).To(Equal(0)) }) It("podman push to oci-archive", func() { - session := podmanTest.Podman([]string{"push", ALPINE, "oci-archive:/tmp/alp.tar:latest"}) + tarfn := filepath.Join(podmanTest.TempDir, "alp.tar") + session := podmanTest.Podman([]string{"push", ALPINE, + fmt.Sprintf("oci-archive:%s:latest", tarfn)}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) - clean := SystemExec("rm", []string{"/tmp/alp.tar"}) - clean.WaitWithDefaultTimeout() - Expect(clean.ExitCode()).To(Equal(0)) }) It("podman push to local ostree", func() { @@ -208,33 +200,29 @@ var _ = Describe("Podman push", func() { os.MkdirAll(ostreePath, os.ModePerm) setup := SystemExec("ostree", []string{strings.Join([]string{"--repo=", ostreePath}, ""), "init"}) - setup.WaitWithDefaultTimeout() + Expect(setup.ExitCode()).To(Equal(0)) session := podmanTest.Podman([]string{"push", ALPINE, strings.Join([]string{"ostree:alp@", ostreePath}, "")}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) - clean := SystemExec("rm", []string{"-rf", ostreePath}) - clean.WaitWithDefaultTimeout() - Expect(clean.ExitCode()).To(Equal(0)) }) It("podman push to docker-archive no reference", func() { - session := podmanTest.Podman([]string{"push", ALPINE, "docker-archive:/tmp/alp"}) + tarfn := filepath.Join(podmanTest.TempDir, "alp.tar") + session := podmanTest.Podman([]string{"push", ALPINE, + fmt.Sprintf("docker-archive:%s", tarfn)}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) - clean := SystemExec("rm", []string{"/tmp/alp"}) - clean.WaitWithDefaultTimeout() - Expect(clean.ExitCode()).To(Equal(0)) }) It("podman push to oci-archive no reference", func() { - session := podmanTest.Podman([]string{"push", ALPINE, "oci-archive:/tmp/alp-oci"}) + ociarc := filepath.Join(podmanTest.TempDir, "alp-oci") + session := podmanTest.Podman([]string{"push", ALPINE, + fmt.Sprintf("oci-archive:%s", ociarc)}) + session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) - clean := SystemExec("rm", []string{"/tmp/alp-oci"}) - clean.WaitWithDefaultTimeout() - Expect(clean.ExitCode()).To(Equal(0)) }) }) diff --git a/test/e2e/run_cleanup_test.go b/test/e2e/run_cleanup_test.go index aa823b4e6..1f2a4085d 100644 --- a/test/e2e/run_cleanup_test.go +++ b/test/e2e/run_cleanup_test.go @@ -36,14 +36,16 @@ var _ = Describe("Podman run exit", func() { It("podman run -d mount cleanup test", func() { mount := SystemExec("mount", nil) - mount.WaitWithDefaultTimeout() + Expect(mount.ExitCode()).To(Equal(0)) + out1 := mount.OutputToString() result := podmanTest.Podman([]string{"create", "-dt", ALPINE, "echo", "hello"}) result.WaitWithDefaultTimeout() Expect(result.ExitCode()).To(Equal(0)) mount = SystemExec("mount", nil) - mount.WaitWithDefaultTimeout() + Expect(mount.ExitCode()).To(Equal(0)) + out2 := mount.OutputToString() Expect(out1).To(Equal(out2)) }) diff --git a/test/e2e/run_networking_test.go b/test/e2e/run_networking_test.go index a07e4d047..c89a4f487 100644 --- a/test/e2e/run_networking_test.go +++ b/test/e2e/run_networking_test.go @@ -58,7 +58,6 @@ var _ = Describe("Podman run networking", func() { session.Wait(30) Expect(session.ExitCode()).To(Equal(0)) results := SystemExec("iptables", []string{"-t", "nat", "-L"}) - results.Wait(30) Expect(results.ExitCode()).To(Equal(0)) Expect(results.OutputToString()).To(ContainSubstring("222")) Expect(results.OutputToString()).To(ContainSubstring("223")) @@ -69,12 +68,10 @@ var _ = Describe("Podman run networking", func() { session.Wait(30) Expect(session.ExitCode()).To(Equal(0)) results := SystemExec("iptables", []string{"-t", "nat", "-L"}) - results.Wait(30) Expect(results.ExitCode()).To(Equal(0)) Expect(results.OutputToString()).To(ContainSubstring("8000")) ncBusy := SystemExec("nc", []string{"-l", "-p", "80"}) - ncBusy.Wait(10) Expect(ncBusy.ExitCode()).ToNot(Equal(0)) }) @@ -183,26 +180,40 @@ var _ = Describe("Podman run networking", func() { if Containerized() { Skip("Can not be run within a container.") } - SystemExec("ip", []string{"netns", "add", "xxx"}) + addXXX := SystemExec("ip", []string{"netns", "add", "xxx"}) + Expect(addXXX.ExitCode()).To(Equal(0)) + defer func() { + delXXX := SystemExec("ip", []string{"netns", "delete", "xxx"}) + Expect(delXXX.ExitCode()).To(Equal(0)) + }() + session := podmanTest.Podman([]string{"run", "-dt", "--net", "ns:/run/netns/xxx", ALPINE, "wget", "www.podman.io"}) session.Wait(90) Expect(session.ExitCode()).To(Equal(0)) - SystemExec("ip", []string{"netns", "delete", "xxx"}) }) It("podman run n user created network namespace with resolv.conf", func() { if Containerized() { Skip("Can not be run within a container.") } - SystemExec("ip", []string{"netns", "add", "xxx"}) - SystemExec("mkdir", []string{"-p", "/etc/netns/xxx"}) - SystemExec("bash", []string{"-c", "echo nameserver 11.11.11.11 > /etc/netns/xxx/resolv.conf"}) - session := podmanTest.Podman([]string{"run", "--net", "ns:/run/netns/xxx", ALPINE, "cat", "/etc/resolv.conf"}) + addXXX2 := SystemExec("ip", []string{"netns", "add", "xxx2"}) + Expect(addXXX2.ExitCode()).To(Equal(0)) + defer func() { + delXXX2 := SystemExec("ip", []string{"netns", "delete", "xxx2"}) + Expect(delXXX2.ExitCode()).To(Equal(0)) + }() + + mdXXX2 := SystemExec("mkdir", []string{"-p", "/etc/netns/xxx2"}) + Expect(mdXXX2.ExitCode()).To(Equal(0)) + defer os.RemoveAll("/etc/netns/xxx2") + + nsXXX2 := SystemExec("bash", []string{"-c", "echo nameserver 11.11.11.11 > /etc/netns/xxx2/resolv.conf"}) + Expect(nsXXX2.ExitCode()).To(Equal(0)) + + session := podmanTest.Podman([]string{"run", "--net", "ns:/run/netns/xxx2", ALPINE, "cat", "/etc/resolv.conf"}) session.Wait(90) Expect(session.ExitCode()).To(Equal(0)) Expect(session.OutputToString()).To(ContainSubstring("11.11.11.11")) - SystemExec("ip", []string{"netns", "delete", "xxx"}) - SystemExec("rm", []string{"-rf", "/etc/netns/xxx"}) }) It("podman run network in bogus user created network namespace", func() { diff --git a/test/e2e/run_ns_test.go b/test/e2e/run_ns_test.go index 9962185f2..3d95c3a0b 100644 --- a/test/e2e/run_ns_test.go +++ b/test/e2e/run_ns_test.go @@ -53,7 +53,6 @@ var _ = Describe("Podman run ns", func() { It("podman run ipcns test", func() { setup := SystemExec("ls", []string{"--inode", "-d", "/dev/shm"}) - setup.WaitWithDefaultTimeout() Expect(setup.ExitCode()).To(Equal(0)) hostShm := setup.OutputToString() @@ -65,7 +64,6 @@ var _ = Describe("Podman run ns", func() { It("podman run ipcns ipcmk host test", func() { setup := SystemExec("ipcmk", []string{"-M", "1024"}) - setup.WaitWithDefaultTimeout() Expect(setup.ExitCode()).To(Equal(0)) output := strings.Split(setup.OutputToString(), " ") ipc := output[len(output)-1] @@ -74,7 +72,6 @@ var _ = Describe("Podman run ns", func() { Expect(session.ExitCode()).To(Equal(0)) setup = SystemExec("ipcrm", []string{"-m", ipc}) - setup.WaitWithDefaultTimeout() Expect(setup.ExitCode()).To(Equal(0)) }) diff --git a/test/e2e/run_privileged_test.go b/test/e2e/run_privileged_test.go index 0c0de30c5..ee6e8e950 100644 --- a/test/e2e/run_privileged_test.go +++ b/test/e2e/run_privileged_test.go @@ -46,7 +46,6 @@ var _ = Describe("Podman privileged container tests", func() { It("podman privileged CapEff", func() { cap := SystemExec("grep", []string{"CapEff", "/proc/self/status"}) - cap.WaitWithDefaultTimeout() Expect(cap.ExitCode()).To(Equal(0)) session := podmanTest.Podman([]string{"run", "--privileged", "busybox", "grep", "CapEff", "/proc/self/status"}) @@ -57,7 +56,6 @@ var _ = Describe("Podman privileged container tests", func() { It("podman cap-add CapEff", func() { cap := SystemExec("grep", []string{"CapEff", "/proc/self/status"}) - cap.WaitWithDefaultTimeout() Expect(cap.ExitCode()).To(Equal(0)) session := podmanTest.Podman([]string{"run", "--cap-add", "all", "busybox", "grep", "CapEff", "/proc/self/status"}) @@ -97,7 +95,6 @@ var _ = Describe("Podman privileged container tests", func() { } cap := SystemExec("grep", []string{"NoNewPrivs", "/proc/self/status"}) - cap.WaitWithDefaultTimeout() if cap.ExitCode() != 0 { Skip("Can't determine NoNewPrivs") } diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index 6bd49de33..93ee5036f 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -387,7 +387,6 @@ var _ = Describe("Podman run", func() { err = ioutil.WriteFile(keyFile, []byte(mountString), 0755) Expect(err).To(BeNil()) execSession := SystemExec("ln", []string{"-s", targetDir, filepath.Join(secretsDir, "mysymlink")}) - execSession.WaitWithDefaultTimeout() Expect(execSession.ExitCode()).To(Equal(0)) session := podmanTest.Podman([]string{"--default-mounts-file=" + mountsFile, "run", "--rm", ALPINE, "cat", "/run/secrets/test.txt"}) diff --git a/test/e2e/systemd_test.go b/test/e2e/systemd_test.go index a7e7a1500..252361288 100644 --- a/test/e2e/systemd_test.go +++ b/test/e2e/systemd_test.go @@ -53,31 +53,27 @@ WantedBy=multi-user.target sys_file := ioutil.WriteFile("/etc/systemd/system/redis.service", []byte(systemd_unit_file), 0644) Expect(sys_file).To(BeNil()) + defer func() { + stop := SystemExec("bash", []string{"-c", "systemctl stop redis"}) + os.Remove("/etc/systemd/system/redis.service") + SystemExec("bash", []string{"-c", "systemctl daemon-reload"}) + Expect(stop.ExitCode()).To(Equal(0)) + }() create := podmanTest.Podman([]string{"create", "-d", "--name", "redis", "redis"}) create.WaitWithDefaultTimeout() Expect(create.ExitCode()).To(Equal(0)) - enable := SystemExec("bash", []string{"-c", "systemctl daemon-reload && systemctl enable --now redis"}) - enable.WaitWithDefaultTimeout() + enable := SystemExec("bash", []string{"-c", "systemctl daemon-reload"}) Expect(enable.ExitCode()).To(Equal(0)) start := SystemExec("bash", []string{"-c", "systemctl start redis"}) - start.WaitWithDefaultTimeout() + Expect(start.ExitCode()).To(Equal(0)) logs := SystemExec("bash", []string{"-c", "journalctl -n 20 -u redis"}) - logs.WaitWithDefaultTimeout() + Expect(logs.ExitCode()).To(Equal(0)) status := SystemExec("bash", []string{"-c", "systemctl status redis"}) - status.WaitWithDefaultTimeout() Expect(status.OutputToString()).To(ContainSubstring("active (running)")) - - cleanup := SystemExec("bash", []string{"-c", "systemctl stop redis && systemctl disable redis"}) - cleanup.WaitWithDefaultTimeout() - Expect(cleanup.ExitCode()).To(Equal(0)) - os.Remove("/etc/systemd/system/redis.service") - sys_clean := SystemExec("bash", []string{"-c", "systemctl daemon-reload"}) - sys_clean.WaitWithDefaultTimeout() - Expect(sys_clean.ExitCode()).To(Equal(0)) }) }) diff --git a/test/test_podman_baseline.sh b/test/test_podman_baseline.sh index 8a878b4e7..664fd2b03 100755 --- a/test/test_podman_baseline.sh +++ b/test/test_podman_baseline.sh @@ -195,7 +195,7 @@ podman rmi --all ######## # 1.004608 MB is 1,004,608 bytes. The container overhead is 4608 bytes (or 9 512 byte pages), so this allocates 1 MB of usable storage -PODMANBASE="-s overlay --storage-opt overlay.size=1.004608M --root /tmp/podman_test/crio" +PODMANBASE="--storage-driver overlay --storage-opt overlay.size=1.004608M --root /tmp/podman_test/crio" TMPDIR=/tmp/podman_test mkdir $TMPDIR dd if=/dev/zero of=$TMPDIR/virtfs bs=1024 count=30720 diff --git a/test/utils/utils.go b/test/utils/utils.go index 098779321..499466f5a 100644 --- a/test/utils/utils.go +++ b/test/utils/utils.go @@ -326,6 +326,7 @@ func SystemExec(command string, args []string) *PodmanSession { if err != nil { Fail(fmt.Sprintf("unable to run command: %s %s", command, strings.Join(args, " "))) } + session.Wait(defaultWaitTimeout) return &PodmanSession{session} } diff --git a/vendor.conf b/vendor.conf index 678807d1c..f739c76f4 100644 --- a/vendor.conf +++ b/vendor.conf @@ -93,7 +93,7 @@ k8s.io/apimachinery kubernetes-1.10.13-beta.0 https://github.com/kubernetes/apim k8s.io/client-go kubernetes-1.10.13-beta.0 https://github.com/kubernetes/client-go github.com/mrunalp/fileutils 7d4729fb36185a7c1719923406c9d40e54fb93c7 github.com/varlink/go 3ac79db6fd6aec70924193b090962f92985fe199 -github.com/containers/buildah v1.7 +github.com/containers/buildah v1.7.1 # TODO: Gotty has not been updated since 2012. Can we find replacement? github.com/Nvveen/Gotty cd527374f1e5bff4938207604a14f2e38a9cf512 # do not go beyond the below commit as the next one requires a more recent diff --git a/vendor/github.com/containers/buildah/README.md b/vendor/github.com/containers/buildah/README.md index 12eafdf88..913a4336f 100644 --- a/vendor/github.com/containers/buildah/README.md +++ b/vendor/github.com/containers/buildah/README.md @@ -35,18 +35,23 @@ For blogs, release announcements and more, please checkout the [buildah.io](http ## Buildah and Podman relationship -Buildah and Podman are two complementary Open-source projects that are available on -most Linux platforms and both projects reside at [GitHub.com](https://github.com) -with Buildah [here](https://github.com/containers/buildah) and -Podman [here](https://github.com/containers/libpod). Both Buildah and Podman are -command line tools that work on OCI images and containers. The two projects -differentiate in their specialization. +Buildah and Podman are two complementary open-source projects that are +available on most Linux platforms and both projects reside at +[GitHub.com](https://github.com) with Buildah +[here](https://github.com/containers/buildah) and Podman +[here](https://github.com/containers/libpod). Both, Buildah and Podman are +command line tools that work on Open Container Initiative (OCI) images and +containers. The two projects differentiate in their specialization. Buildah specializes in building OCI images. Buildah's commands replicate all -of the commands that are found in a Dockerfile. Buildah’s goal is also to -provide a lower level coreutils interface to build images, allowing people to build -containers without requiring a Dockerfile. The intent with Buildah is to allow other -scripting languages to build container images, without requiring a daemon. +of the commands that are found in a Dockerfile. This allows building images +with and without Dockerfiles while not requiring any root privileges. +Buildah’s ultimate goal is to provide a lower-level coreutils interface to +build images. The flexibility of building images without Dockerfiles allows +for the integration of other scripting languages into the build process. +Buildah follows a simple fork-exec model and does not run as a daemon +but it is based on a comprehensive API in golang, which can be vendored +into other tools. Podman specializes in all of the commands and functions that help you to maintain and modify OCI images, such as pulling and tagging. It also allows you to create, run, and maintain those containers @@ -55,12 +60,12 @@ created from those images. A major difference between Podman and Buildah is their concept of a container. Podman allows users to create "traditional containers" where the intent of these containers is to be long lived. While Buildah containers are really just created to allow content -to be added back to the container image. An easy way to think of it is the +to be added back to the container image. An easy way to think of it is the `buildah run` command emulates the RUN command in a Dockerfile while the `podman run` command emulates the `docker run` command in functionality. Because of this and their underlying storage differences, you can not see Podman containers from within Buildah or vice versa. -In short Buildah is an efficient way to create OCI images while Podman allows +In short, Buildah is an efficient way to create OCI images while Podman allows you to manage and maintain those images and containers in a production environment using familiar container cli commands. For more details, see the [Container Tools Guide](https://github.com/containers/buildah/tree/master/docs/containertools). diff --git a/vendor/github.com/containers/buildah/buildah.go b/vendor/github.com/containers/buildah/buildah.go index 755bc348e..cca80a308 100644 --- a/vendor/github.com/containers/buildah/buildah.go +++ b/vendor/github.com/containers/buildah/buildah.go @@ -26,7 +26,7 @@ const ( Package = "buildah" // Version for the Package. Bump version in contrib/rpm/buildah.spec // too. - Version = "1.7" + Version = "1.7.1" // The value we use to identify what type of information, currently a // serialized Builder structure, we are using as per-container state. // This should only be changed when we make incompatible changes to diff --git a/vendor/github.com/containers/buildah/new.go b/vendor/github.com/containers/buildah/new.go index 01c2e733f..768cdd0c6 100644 --- a/vendor/github.com/containers/buildah/new.go +++ b/vendor/github.com/containers/buildah/new.go @@ -303,7 +303,7 @@ func newBuilder(ctx context.Context, store storage.Store, options BuilderOptions } conflict := 100 - for true { + for { coptions := storage.ContainerOptions{ LabelOpts: options.CommonBuildOpts.LabelOpts, IDMappingOptions: newContainerIDMappingOptions(options.IDMappingOptions), diff --git a/vendor/github.com/containers/buildah/pkg/cli/common.go b/vendor/github.com/containers/buildah/pkg/cli/common.go index 09f951b35..f167353b8 100644 --- a/vendor/github.com/containers/buildah/pkg/cli/common.go +++ b/vendor/github.com/containers/buildah/pkg/cli/common.go @@ -125,7 +125,7 @@ func GetNameSpaceFlags(flags *NameSpaceResults) pflag.FlagSet { func GetLayerFlags(flags *LayerResults) pflag.FlagSet { fs := pflag.FlagSet{} fs.BoolVar(&flags.ForceRm, "force-rm", false, "Always remove intermediate containers after a build, even if the build is unsuccessful.") - fs.BoolVar(&flags.Layers, "layers", false, fmt.Sprintf("cache intermediate layers during build. Use BUILDAH_LAYERS environment variable to override. (default %t)", UseLayers())) + fs.BoolVar(&flags.Layers, "layers", UseLayers(), fmt.Sprintf("cache intermediate layers during build. Use BUILDAH_LAYERS environment variable to override.")) return fs } @@ -152,7 +152,7 @@ func GetBudFlags(flags *BudResults) pflag.FlagSet { fs.BoolVar(&flags.Pull, "pull", true, "pull the image if not present") fs.BoolVar(&flags.PullAlways, "pull-always", false, "pull the image, even if a version is present") fs.BoolVarP(&flags.Quiet, "quiet", "q", false, "refrain from announcing build instructions and image read/write progress") - fs.BoolVar(&flags.Rm, "rm", true, "Remove intermediate containers after a successful build (default true)") + fs.BoolVar(&flags.Rm, "rm", true, "Remove intermediate containers after a successful build") fs.StringVar(&flags.Runtime, "runtime", util.Runtime(), "`path` to an alternate runtime. Use BUILDAH_RUNTIME environment variable to override.") fs.StringSliceVar(&flags.RuntimeFlags, "runtime-flag", []string{}, "add global flags for the container runtime") fs.StringVar(&flags.SignaturePolicy, "signature-policy", "", "`pathname` of signature policy file (not usually used)") diff --git a/vendor/github.com/containers/buildah/pkg/secrets/secrets.go b/vendor/github.com/containers/buildah/pkg/secrets/secrets.go new file mode 100644 index 000000000..242953609 --- /dev/null +++ b/vendor/github.com/containers/buildah/pkg/secrets/secrets.go @@ -0,0 +1,319 @@ +package secrets + +import ( + "bufio" + "io/ioutil" + "os" + "path/filepath" + "strings" + + "github.com/containers/libpod/pkg/rootless" + rspec "github.com/opencontainers/runtime-spec/specs-go" + "github.com/opencontainers/selinux/go-selinux/label" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" +) + +var ( + // DefaultMountsFile holds the default mount paths in the form + // "host_path:container_path" + DefaultMountsFile = "/usr/share/containers/mounts.conf" + // OverrideMountsFile holds the default mount paths in the form + // "host_path:container_path" overridden by the user + OverrideMountsFile = "/etc/containers/mounts.conf" + // UserOverrideMountsFile holds the default mount paths in the form + // "host_path:container_path" overridden by the rootless user + UserOverrideMountsFile = filepath.Join(os.Getenv("HOME"), ".config/containers/mounts.conf") +) + +// secretData stores the name of the file and the content read from it +type secretData struct { + name string + data []byte +} + +// saveTo saves secret data to given directory +func (s secretData) saveTo(dir string) error { + path := filepath.Join(dir, s.name) + if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil && !os.IsExist(err) { + return err + } + return ioutil.WriteFile(path, s.data, 0700) +} + +func readAll(root, prefix string) ([]secretData, error) { + path := filepath.Join(root, prefix) + + data := []secretData{} + + files, err := ioutil.ReadDir(path) + if err != nil { + if os.IsNotExist(err) { + return data, nil + } + + return nil, err + } + + for _, f := range files { + fileData, err := readFile(root, filepath.Join(prefix, f.Name())) + if err != nil { + // If the file did not exist, might be a dangling symlink + // Ignore the error + if os.IsNotExist(err) { + continue + } + return nil, err + } + data = append(data, fileData...) + } + + return data, nil +} + +func readFile(root, name string) ([]secretData, error) { + path := filepath.Join(root, name) + + s, err := os.Stat(path) + if err != nil { + return nil, err + } + + if s.IsDir() { + dirData, err := readAll(root, name) + if err != nil { + return nil, err + } + return dirData, nil + } + bytes, err := ioutil.ReadFile(path) + if err != nil { + return nil, err + } + return []secretData{{name: name, data: bytes}}, nil +} + +func getHostSecretData(hostDir string) ([]secretData, error) { + var allSecrets []secretData + hostSecrets, err := readAll(hostDir, "") + if err != nil { + return nil, errors.Wrapf(err, "failed to read secrets from %q", hostDir) + } + return append(allSecrets, hostSecrets...), nil +} + +func getMounts(filePath string) []string { + file, err := os.Open(filePath) + if err != nil { + // This is expected on most systems + logrus.Debugf("file %q not found, skipping...", filePath) + return nil + } + defer file.Close() + scanner := bufio.NewScanner(file) + if err = scanner.Err(); err != nil { + logrus.Errorf("error reading file %q, %v skipping...", filePath, err) + return nil + } + var mounts []string + for scanner.Scan() { + mounts = append(mounts, scanner.Text()) + } + return mounts +} + +// getHostAndCtrDir separates the host:container paths +func getMountsMap(path string) (string, string, error) { + arr := strings.SplitN(path, ":", 2) + if len(arr) == 2 { + return arr[0], arr[1], nil + } + return "", "", errors.Errorf("unable to get host and container dir") +} + +// SecretMounts copies, adds, and mounts the secrets to the container root filesystem +func SecretMounts(mountLabel, containerWorkingDir, mountFile string) []rspec.Mount { + return SecretMountsWithUIDGID(mountLabel, containerWorkingDir, mountFile, containerWorkingDir, 0, 0) +} + +// SecretMountsWithUIDGID specifies the uid/gid of the owner +func SecretMountsWithUIDGID(mountLabel, containerWorkingDir, mountFile, mountPrefix string, uid, gid int) []rspec.Mount { + var ( + secretMounts []rspec.Mount + mountFiles []string + ) + // Add secrets from paths given in the mounts.conf files + // mountFile will have a value if the hidden --default-mounts-file flag is set + // Note for testing purposes only + if mountFile == "" { + mountFiles = append(mountFiles, []string{OverrideMountsFile, DefaultMountsFile}...) + if rootless.IsRootless() { + mountFiles = append([]string{UserOverrideMountsFile}, mountFiles...) + _, err := os.Stat(UserOverrideMountsFile) + if err != nil && os.IsNotExist(err) { + os.MkdirAll(filepath.Dir(UserOverrideMountsFile), 0755) + if f, err := os.Create(UserOverrideMountsFile); err != nil { + logrus.Warnf("could not create file %s: %v", UserOverrideMountsFile, err) + } else { + f.Close() + } + } + } + } else { + mountFiles = append(mountFiles, mountFile) + } + for _, file := range mountFiles { + if _, err := os.Stat(file); err == nil { + mounts, err := addSecretsFromMountsFile(file, mountLabel, containerWorkingDir, mountPrefix, uid, gid) + if err != nil { + logrus.Warnf("error mounting secrets, skipping: %v", err) + } + secretMounts = mounts + break + } + } + + // Add FIPS mode secret if /etc/system-fips exists on the host + _, err := os.Stat("/etc/system-fips") + if err == nil { + if err := addFIPSModeSecret(&secretMounts, containerWorkingDir); err != nil { + logrus.Errorf("error adding FIPS mode secret to container: %v", err) + } + } else if os.IsNotExist(err) { + logrus.Debug("/etc/system-fips does not exist on host, not mounting FIPS mode secret") + } else { + logrus.Errorf("stat /etc/system-fips failed for FIPS mode secret: %v", err) + } + return secretMounts +} + +func rchown(chowndir string, uid, gid int) error { + return filepath.Walk(chowndir, func(filePath string, f os.FileInfo, err error) error { + return os.Lchown(filePath, uid, gid) + }) +} + +// addSecretsFromMountsFile copies the contents of host directory to container directory +// and returns a list of mounts +func addSecretsFromMountsFile(filePath, mountLabel, containerWorkingDir, mountPrefix string, uid, gid int) ([]rspec.Mount, error) { + var mounts []rspec.Mount + defaultMountsPaths := getMounts(filePath) + for _, path := range defaultMountsPaths { + hostDir, ctrDir, err := getMountsMap(path) + if err != nil { + return nil, err + } + // skip if the hostDir path doesn't exist + if _, err = os.Stat(hostDir); err != nil { + if os.IsNotExist(err) { + logrus.Warnf("Path %q from %q doesn't exist, skipping", hostDir, filePath) + continue + } + return nil, errors.Wrapf(err, "failed to stat %q", hostDir) + } + + ctrDirOnHost := filepath.Join(containerWorkingDir, ctrDir) + + // In the event of a restart, don't want to copy secrets over again as they already would exist in ctrDirOnHost + _, err = os.Stat(ctrDirOnHost) + if os.IsNotExist(err) { + if err = os.MkdirAll(ctrDirOnHost, 0755); err != nil { + return nil, errors.Wrapf(err, "making container directory %q failed", ctrDirOnHost) + } + hostDir, err = resolveSymbolicLink(hostDir) + if err != nil { + return nil, err + } + + data, err := getHostSecretData(hostDir) + if err != nil { + return nil, errors.Wrapf(err, "getting host secret data failed") + } + for _, s := range data { + if err := s.saveTo(ctrDirOnHost); err != nil { + return nil, errors.Wrapf(err, "error saving data to container filesystem on host %q", ctrDirOnHost) + } + } + + err = label.Relabel(ctrDirOnHost, mountLabel, false) + if err != nil { + return nil, errors.Wrap(err, "error applying correct labels") + } + if uid != 0 || gid != 0 { + if err := rchown(ctrDirOnHost, uid, gid); err != nil { + return nil, err + } + } + } else if err != nil { + return nil, errors.Wrapf(err, "error getting status of %q", ctrDirOnHost) + } + + m := rspec.Mount{ + Source: filepath.Join(mountPrefix, ctrDir), + Destination: ctrDir, + Type: "bind", + Options: []string{"bind", "rprivate"}, + } + + mounts = append(mounts, m) + } + return mounts, nil +} + +// addFIPSModeSecret creates /run/secrets/system-fips in the container +// root filesystem if /etc/system-fips exists on hosts. +// This enables the container to be FIPS compliant and run openssl in +// FIPS mode as the host is also in FIPS mode. +func addFIPSModeSecret(mounts *[]rspec.Mount, containerWorkingDir string) error { + secretsDir := "/run/secrets" + ctrDirOnHost := filepath.Join(containerWorkingDir, secretsDir) + if _, err := os.Stat(ctrDirOnHost); os.IsNotExist(err) { + if err = os.MkdirAll(ctrDirOnHost, 0755); err != nil { + return errors.Wrapf(err, "making container directory on host failed") + } + } + fipsFile := filepath.Join(ctrDirOnHost, "system-fips") + // In the event of restart, it is possible for the FIPS mode file to already exist + if _, err := os.Stat(fipsFile); os.IsNotExist(err) { + file, err := os.Create(fipsFile) + if err != nil { + return errors.Wrapf(err, "error creating system-fips file in container for FIPS mode") + } + defer file.Close() + } + + if !mountExists(*mounts, secretsDir) { + m := rspec.Mount{ + Source: ctrDirOnHost, + Destination: secretsDir, + Type: "bind", + Options: []string{"bind", "rprivate"}, + } + *mounts = append(*mounts, m) + } + + return nil +} + +// mountExists checks if a mount already exists in the spec +func mountExists(mounts []rspec.Mount, dest string) bool { + for _, mount := range mounts { + if mount.Destination == dest { + return true + } + } + return false +} + +// resolveSymbolicLink resolves a possbile symlink path. If the path is a symlink, returns resolved +// path; if not, returns the original path. +func resolveSymbolicLink(path string) (string, error) { + info, err := os.Lstat(path) + if err != nil { + return "", err + } + if info.Mode()&os.ModeSymlink != os.ModeSymlink { + return path, nil + } + return filepath.EvalSymlinks(path) +} diff --git a/vendor/github.com/containers/buildah/pull.go b/vendor/github.com/containers/buildah/pull.go index d1f33fb01..363cf5ce2 100644 --- a/vendor/github.com/containers/buildah/pull.go +++ b/vendor/github.com/containers/buildah/pull.go @@ -194,12 +194,12 @@ func Pull(ctx context.Context, imageName string, options PullOptions) error { errs = multierror.Append(errs, err) continue } - img, err := is.Transport.GetStoreImage(options.Store, ref) + taggedImg, err := is.Transport.GetStoreImage(options.Store, ref) if err != nil { errs = multierror.Append(errs, err) continue } - fmt.Printf("%s\n", img.ID) + fmt.Printf("%s\n", taggedImg.ID) } } else { fmt.Printf("%s\n", img.ID) diff --git a/vendor/github.com/containers/buildah/run.go b/vendor/github.com/containers/buildah/run.go index 3a248f4f2..4d6d28380 100644 --- a/vendor/github.com/containers/buildah/run.go +++ b/vendor/github.com/containers/buildah/run.go @@ -21,15 +21,15 @@ import ( "github.com/containernetworking/cni/libcni" "github.com/containers/buildah/bind" "github.com/containers/buildah/chroot" + "github.com/containers/buildah/pkg/secrets" "github.com/containers/buildah/util" - "github.com/containers/libpod/pkg/secrets" "github.com/containers/storage/pkg/idtools" "github.com/containers/storage/pkg/ioutils" "github.com/containers/storage/pkg/reexec" "github.com/containers/storage/pkg/stringid" units "github.com/docker/go-units" digest "github.com/opencontainers/go-digest" - "github.com/opencontainers/runtime-spec/specs-go" + specs "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-tools/generate" "github.com/opencontainers/selinux/go-selinux/label" "github.com/pkg/errors" @@ -840,7 +840,7 @@ func setupNamespaces(g *generate.Generator, namespaceOptions NamespaceOptions, i // valid resolution. func runLookupPath(g *generate.Generator, command []string) []string { // Look for the configured $PATH. - spec := g.Spec() + spec := g.Config envPath := "" for i := range spec.Process.Env { if strings.HasPrefix(spec.Process.Env[i], "PATH=") { @@ -953,7 +953,7 @@ func (b *Builder) configureNamespaces(g *generate.Generator, options RunOptions) } found := false - spec := g.Spec() + spec := g.Config for i := range spec.Process.Env { if strings.HasPrefix(spec.Process.Env[i], "HOSTNAME=") { found = true @@ -1054,7 +1054,7 @@ func (b *Builder) Run(command []string, options RunOptions) error { // Now grab the spec from the generator. Set the generator to nil so that future contributors // will quickly be able to tell that they're supposed to be modifying the spec directly from here. - spec := g.Spec() + spec := g.Config g = nil logrus.Debugf("ensuring working directory %q exists", filepath.Join(mountPoint, spec.Process.Cwd)) diff --git a/vendor/github.com/containers/buildah/unshare/unshare_unsupported.go b/vendor/github.com/containers/buildah/unshare/unshare_unsupported.go deleted file mode 100644 index feeceae66..000000000 --- a/vendor/github.com/containers/buildah/unshare/unshare_unsupported.go +++ /dev/null @@ -1 +0,0 @@ -package unshare diff --git a/vendor/github.com/containers/buildah/vendor.conf b/vendor/github.com/containers/buildah/vendor.conf index 7438fc909..27bf45541 100644 --- a/vendor/github.com/containers/buildah/vendor.conf +++ b/vendor/github.com/containers/buildah/vendor.conf @@ -3,7 +3,7 @@ github.com/blang/semver v3.5.0 github.com/BurntSushi/toml v0.2.0 github.com/containerd/continuity 004b46473808b3e7a4a3049c20e4376c91eb966d github.com/containernetworking/cni v0.7.0-alpha1 -github.com/containers/image v1.4 +github.com/containers/image v1.5 github.com/vbauerster/mpb v3.3.4 github.com/mattn/go-isatty v0.0.4 github.com/VividCortex/ewma v1.1.1 diff --git a/version/version.go b/version/version.go index 24daf707c..89b5fbd8b 100644 --- a/version/version.go +++ b/version/version.go @@ -4,7 +4,7 @@ package version // NOTE: remember to bump the version at the top // of the top-level README.md file when this is // bumped. -const Version = "1.0.1-dev" +const Version = "1.2.0-dev" // RemoteAPIVersion is the version for the remote // client API. It is used to determine compatibility |