summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/apiv2/30-volumes.at16
-rw-r--r--test/apiv2/rest_api/test_rest_v2_0_0.py8
-rw-r--r--test/buildah-bud/README.md70
-rwxr-xr-xtest/buildah-bud/apply-podman-deltas157
-rw-r--r--test/buildah-bud/buildah-tests.diff146
-rw-r--r--test/buildah-bud/make-new-buildah-diffs6
-rwxr-xr-xtest/buildah-bud/run-buildah-bud-tests71
-rwxr-xr-xtest/compose/test-compose32
-rw-r--r--test/e2e/build_test.go38
-rw-r--r--test/e2e/config_amd64.go2
-rw-r--r--test/e2e/generate_kube_test.go58
-rw-r--r--test/e2e/images_test.go6
-rw-r--r--test/e2e/play_kube_test.go264
-rw-r--r--test/e2e/rmi_test.go4
-rw-r--r--test/e2e/run_test.go25
-rw-r--r--test/e2e/save_test.go22
-rw-r--r--test/e2e/toolbox_test.go5
-rw-r--r--test/e2e/unshare_test.go7
-rw-r--r--test/system/001-basic.bats13
-rw-r--r--test/system/005-info.bats21
-rw-r--r--test/system/037-runlabel.bats32
-rw-r--r--test/system/050-stop.bats1
-rw-r--r--test/system/070-build.bats12
-rw-r--r--test/system/420-cgroups.bats5
-rw-r--r--test/system/500-networking.bats15
-rw-r--r--test/system/helpers.bash15
26 files changed, 848 insertions, 203 deletions
diff --git a/test/apiv2/30-volumes.at b/test/apiv2/30-volumes.at
index 18ff31100..623e691e3 100644
--- a/test/apiv2/30-volumes.at
+++ b/test/apiv2/30-volumes.at
@@ -123,4 +123,20 @@ t POST libpod/volumes/prune 200
#After prune volumes, there should be no volume existing
t GET libpod/volumes/json 200 length=0
+# libpod api: do not use list filters for prune
+t POST libpod/volumes/prune?filters='{"name":["anyname"]}' 500 \
+ .cause="\"name\" is an invalid volume filter"
+t POST libpod/volumes/prune?filters='{"driver":["anydriver"]}' 500 \
+ .cause="\"driver\" is an invalid volume filter"
+t POST libpod/volumes/prune?filters='{"scope":["anyscope"]}' 500 \
+ .cause="\"scope\" is an invalid volume filter"
+
+# compat api: do not use list filters for prune
+t POST volumes/prune?filters='{"name":["anyname"]}' 500 \
+ .cause="\"name\" is an invalid volume filter"
+t POST volumes/prune?filters='{"driver":["anydriver"]}' 500 \
+ .cause="\"driver\" is an invalid volume filter"
+t POST volumes/prune?filters='{"scope":["anyscope"]}' 500 \
+ .cause="\"scope\" is an invalid volume filter"
+
# vim: filetype=sh
diff --git a/test/apiv2/rest_api/test_rest_v2_0_0.py b/test/apiv2/rest_api/test_rest_v2_0_0.py
index d7910f555..bf0ee0603 100644
--- a/test/apiv2/rest_api/test_rest_v2_0_0.py
+++ b/test/apiv2/rest_api/test_rest_v2_0_0.py
@@ -727,6 +727,14 @@ class TestApi(unittest.TestCase):
start = json.loads(r.text)
self.assertGreater(len(start["Errs"]), 0, r.text)
+ def test_manifest_409(self):
+ r = requests.post(_url("/manifests/create"), params={"name": "ThisIsAnInvalidImage"})
+ self.assertEqual(r.status_code, 400, r.text)
+
+ def test_df(self):
+ r = requests.get(_url("/system/df"))
+ self.assertEqual(r.status_code, 200, r.text)
+
if __name__ == "__main__":
unittest.main()
diff --git a/test/buildah-bud/README.md b/test/buildah-bud/README.md
index 88e4bbc3c..ba776c4d9 100644
--- a/test/buildah-bud/README.md
+++ b/test/buildah-bud/README.md
@@ -1,5 +1,4 @@
-buildah-bud tests under podman
-==============================
+# buildah-bud tests under podman
This directory contains tools for running 'buildah bud' tests
under podman. The key concept of the workflow is:
@@ -13,8 +12,7 @@ It's a teeny bit more complicated than that, but that's really most of
what you need to know for most purposes. The tests run in podman CI,
and for the most part are expected to just pass.
-Troubleshooting
----------------
+## Troubleshooting
If you're reading this, it's probably because something went wrong.
At the time of this writing (March 2021, initial commit) it is
@@ -26,8 +24,7 @@ my prediction is that they will fit one of two categories:
Let's examine those in reverse order:
-Failure when not vendoring
---------------------------
+## Failure when not vendoring
Aside from flakes, my only guess here is that you broke 'podman build'.
If this is the case, it is very likely that you are aware of what you
@@ -41,13 +38,12 @@ If neither of those is the case, then I'm sorry, you're on your own.
When you figure it out, please remember to update these instructions.
-Failure when vendoring new buildah
-----------------------------------
+## Failure when vendoring new buildah
This is what I predict will be the usual case; and I predict that
failures will fall into one of two bins:
-* failure to apply the patch
+* failure to apply the patches; and/or
* failure because there are new buildah tests for functionality not in podman
In either case, the process for solving is the same:
@@ -59,24 +55,52 @@ Presumably, something will fail here. Whatever the failure, your next step is:
* `cd test-buildah-v<TAB>` (this is a new directory created by the script)
-If the failure was in `git am`, solve it (left as exercise for the reader).
+Now there are three possible failures:
-If the failure was in tests run, solve it (either by adding `skip`s to
-failing tests in bud.bats, or less preferably, by making other tweaks
-to the test code).
+### Failure in `git am`
-You now have modified files. THOSE SHOULD ONLY BE test/bud.bats or
-test/helpers.bash! If you changed any other file, that is a sign that
-something is very wrong!
+If the failure was in `git am`, it probably means that buildah
+`tests/helpers.bash` got updated in such a way as to cause a conflict
+with the patches we apply. Your best bet is to:
-Commit your changes: `git commit --all --amend`
+* Look at `tests/*.rej`
+* For each rejected patch, try to figure out where it should go and how to apply it. Do so.
+* `git add tests/helpers.bash` - this is for `git am`, next
+* `git am --continue` - this continues the failed patch. Make sure it succeeds.
+* `./make-new-buildah-diffs` - this updates your podman working directory
+* `cd ..; git diff test/buildah-bud`. This will show you a diff of a .diff file, which is really painful to read. I'm sorry. Just try to confirm that the changes look like what you expect.
-Push those changes to the podman repo: `./make-new-buildah-diffs`
+Proceed with 'In all cases' below.
-cd back up to the podman repo
+### Failure when applying podman-custom deltas
-As necessary, rerun `run-buildah-bud-tests`. You can use `--no-checkout`
-to run tests immediately, without rerunning the git checkout.
+Failure in the `apply-podman-deltas` script means that one of the
+hand-crafted exceptions was not found, e.g., there's a `skip` or
+`errmsg` looking for a specific `@test` in `bud.bats` that is
+no longer there.
-If you're happy with the diffs, `git add` the modified `.diff` file
-and submit it as part of your PR.
+Solution:
+* Inspect the error message(s) from `apply-podman-deltas`. Each message will list a specific `@test` name.
+* Look at the diffs in `tests/bud.bats` between master and your PR. (I'm really sorry; there's no quick easy command-line way to do that. You will need a checked-out buildah tree, and you will need to know the old and new buildah tags).
+ * In those diffs, look for changes related to each `@test` listed as an error. For example, a test being renamed or even removed.
+ * Update `test/buildah-bud/apply-podman-deltas` accordingly.
+
+Proceed with 'In all cases' below.
+
+### Failure when running tests
+
+If the failure was in tests run, and you're vendoring, your only real choice is to add a new `skip`:
+
+* Identify the failing test(s)
+* File a new podman issue, e.g. "podman build fails buildah XYZ test"
+* Edit `test/buildah/bud/apply-podman-deltas`. Search for "actual podman bugs" near the bottom, and add a new `skip` line with the reason (INCLUDE THE ISSUE NUMBER!) and the test name.
+
+### In all cases
+
+You will probably want to rerun `run-buildah-bud-tests` to save yourself
+the hassle of having it fail in CI. (`rm -rf test-buildah-v<TAB>` first).
+If you're debugging problems that run on a specific test, you can
+use `--filter="pattern"` to run only tests that match "pattern".
+
+If everything passes, `git commit --amend` your PR, adding the
+files you changed under `test/buildah-bud`, then `git push --force`.
diff --git a/test/buildah-bud/apply-podman-deltas b/test/buildah-bud/apply-podman-deltas
new file mode 100755
index 000000000..9f6f38190
--- /dev/null
+++ b/test/buildah-bud/apply-podman-deltas
@@ -0,0 +1,157 @@
+#!/bin/bash
+#
+# *** NOTE TO READER: Please skip down to "user-customizable section" below!
+#
+# Not all tests in buildah/tests/bud.bats work under podman.
+# Some work, but emit different error messages.
+#
+# This script is used to skip the former, and munge expect_output messages
+# for the latter.
+#
+ME=$(basename $0)
+
+BUD=tests/bud.bats
+
+if [[ ! -e $BUD ]]; then
+ echo "$ME: $BUD not found: please run me from buildah subdir" >&2
+ exit 1
+fi
+
+###############################################################################
+# BEGIN handlers
+#
+# *** NOTE TO READER (again): Please skip down to "user-customizable section"
+#
+# You almost certainly don't care about anything in this section.
+#
+set -e
+
+RC=0
+
+ECHO=':'
+if [[ -n $DEBUG_PODMAN_DELTAS ]]; then
+ ECHO='echo'
+fi
+
+# Issue a warning, and set exit status (but do not exit now)
+function warn() {
+ echo "$ME: ERROR: $*" >&2
+ RC=1
+}
+
+# errmsg: used to change the text of a message, probably in expect_output()
+function errmsg() {
+ local msg_orig=${1//\//\\/}; shift
+ local msg_new=${1//\//\\/}; shift
+
+ for t in "$@"; do
+ if fgrep -qx "@test \"$t\" {" $BUD; then
+ $ECHO "@test \"$t\" : updating to \"$msg_new\""
+ t=${t//\//\\/}
+ # FIXME: emit error if msg_orig not found
+ sed -i -e "/^\@test \"$t\" {/,/^}/s/\"$msg_orig\"/\"$msg_new\"/" $BUD
+ else
+ warn "[errmsg] Did not find test \"$t\" in $BUD"
+ fi
+ done
+}
+
+# skip: used to add a 'skip' to one specific test
+function skip() {
+ local reason=$1; shift
+
+ # All further arguments are test names
+ for t in "$@"; do
+ if fgrep -qx "@test \"$t\" {" $BUD; then
+ $ECHO "@test \"$t\" : skip \"$reason\""
+ t=${t//\//\\/}
+ sed -i -e "/^\@test \"$t\" {/ a \ \ skip \"$reason\"" $BUD
+ else
+ warn "[skip] Did not find test \"$t\" in $BUD"
+ fi
+ done
+}
+
+# END handlers
+###############################################################################
+# BEGIN user-customizable section
+#
+# These are the hand-maintained exceptions. This is what you want to edit
+# or update as needed.
+#
+# There are two directives you can use below:
+#
+# errmsg "old-message" "new-message" "test name" ["test name"...]
+#
+# This replaced "old-message" with "new-message" in @test "test name".
+# It is used when a podman error message differs from buildah's.
+#
+# skip "reason" "test name" ["test name"...]
+#
+# This adds a 'skip' statement as the first line of @test "test name".
+# It is used when a test does not work in podman, either for permanent
+# design-related reasons or for hopefully-temporary bug-in-podman reasons.
+# (If the latter, please file an issue before adding the skip, and include
+# the issue number in your skip message. This makes it possible to remove
+# the skip once the issue is fixed).
+#
+# For both cases, you can list multiple "test names" at the end. This
+# is not used much right now, but will be once I file my podman-remote PR
+# because there are some cases where the same issue affects up to fifty
+# different bud.bats tests.
+#
+
+###############################################################################
+# BEGIN differences in error messages between buildah and podman
+errmsg "non-directory/Dockerfile: not a directory" \
+ "Error: context must be a directory:" \
+ "bud with a path to a Dockerfile (-f) containing a non-directory entry"
+
+errmsg "no such file or directory" \
+ "Error: context must be a directory:" \
+ "bud with dir for file but no Dockerfile in dir" \
+ "bud with bad dir Dockerfile"
+
+errmsg "no such file or directory" \
+ "Error: no context directory and no Containerfile specified" \
+ "bud without any arguments should fail when no Dockerfile exist"
+
+errmsg "is not a file" \
+ "Error: open .*: no such file or directory" \
+ "bud with specified context should fail if assumed Dockerfile is a directory"
+
+errmsg "no such file or directory" \
+ "context must be a directory" \
+ "bud with specified context should fail if context contains not-existing Dockerfile"
+
+###############################################################################
+# BEGIN tests that don't make sense under podman due to fundamental differences
+skip "N/A under podman" \
+ "bud-flags-order-verification"
+
+skip "does not work under podman" \
+ "bud without any arguments should succeed"
+
+skip "podman requires a directory, not a Dockerfile" \
+ "bud with specified context should succeed if context contains existing Dockerfile"
+
+# ...or due to Ed's laziness
+skip "Too much effort to spin up a local registry" \
+ "bud with encrypted FROM image"
+
+# ...or due to a fundamental arg-parsing difference between buildah and podman
+# which we could and perhaps should fix in the buildah repo via:
+# - ... ${TESTSDIR}/bud/layers-squash/Dockerfile.hardlinks
+# + ... -f Dockerfile.hardlinks ${TESTSDIR}/bud/layers-squash
+skip "FIXME FIXME FIXME: argument-order incompatible with podman" \
+ "bud-squash-hardlinks"
+
+###############################################################################
+# BEGIN tests which are skipped due to actual podman bugs.
+skip "FIXME: podman #9915" \
+ "bud with --arch flag"
+
+###############################################################################
+# Done.
+
+exit $RC
diff --git a/test/buildah-bud/buildah-tests.diff b/test/buildah-bud/buildah-tests.diff
index ad35e5926..bba737848 100644
--- a/test/buildah-bud/buildah-tests.diff
+++ b/test/buildah-bud/buildah-tests.diff
@@ -1,154 +1,26 @@
-From a49a2e48421c6f3bb1a56ae372de1f3d1a45d1f1 Mon Sep 17 00:00:00 2001
+From b948e99cb6cb4765987711e8d8948841f6d3f7e2 Mon Sep 17 00:00:00 2001
From: Ed Santiago <santiago@redhat.com>
Date: Tue, 9 Feb 2021 17:28:05 -0700
Subject: [PATCH] tweaks for running buildah tests under podman
Signed-off-by: Ed Santiago <santiago@redhat.com>
---
- tests/bud.bats | 26 ++++++++++++++++----------
tests/helpers.bash | 28 ++++++++++++++++++++++++----
- 2 files changed, 40 insertions(+), 14 deletions(-)
+ 1 file changed, 24 insertions(+), 4 deletions(-)
-diff --git a/tests/bud.bats b/tests/bud.bats
-index cf55d9a4..60cb6f96 100644
---- a/tests/bud.bats
-+++ b/tests/bud.bats
-@@ -4,7 +4,7 @@ load helpers
-
- @test "bud with a path to a Dockerfile (-f) containing a non-directory entry" {
- run_buildah 125 bud -f ${TESTSDIR}/bud/non-directory-in-path/non-directory/Dockerfile
-- expect_output --substring "non-directory/Dockerfile: not a directory"
-+ expect_output --substring "Error: context must be a directory:"
- }
-
- @test "bud with --dns* flags" {
-@@ -117,6 +117,7 @@ symlink(subdir)"
- }
-
- @test "bud-flags-order-verification" {
-+ skip "N/A under podman"
- run_buildah 125 bud /tmp/tmpdockerfile/ -t blabla
- check_options_flag_err "-t"
-
-@@ -1416,13 +1417,13 @@ function _test_http() {
- @test "bud with dir for file but no Dockerfile in dir" {
- target=alpine-image
- run_buildah 125 bud --signature-policy ${TESTSDIR}/policy.json -t ${target} -f ${TESTSDIR}/bud/empty-dir ${TESTSDIR}/bud/empty-dir
-- expect_output --substring "no such file or directory"
-+ expect_output --substring "Error: context must be a directory:"
- }
-
- @test "bud with bad dir Dockerfile" {
- target=alpine-image
- run_buildah 125 bud --signature-policy ${TESTSDIR}/policy.json -t ${target} -f ${TESTSDIR}/baddirname ${TESTSDIR}/baddirname
-- expect_output --substring "no such file or directory"
-+ expect_output --substring "Error: context must be a directory:"
- }
-
- @test "bud with ARG before FROM default value" {
-@@ -1834,7 +1835,9 @@ _EOF
- run_buildah bud --signature-policy ${TESTSDIR}/policy.json --layers -t test-img-2 --build-arg TEST=foo -f Dockerfile4 ${TESTSDIR}/bud/build-arg
- run_buildah inspect -f '{{.FromImageID}}' test-img-2
- argsid="$output"
-- [[ "$argsid" != "$initialid" ]]
-+ if [[ "$argsid" == "$initialid" ]]; then
-+ die ".FromImageID of test-img-2 ($argsid) == same as test-img, it should be different"
-+ fi
-
- # Set the build-arg via an ENV in the local environment and verify that the cached layers are not used
- export TEST=bar
-@@ -1887,6 +1890,7 @@ _EOF
- }
-
- @test "bud without any arguments should succeed" {
-+ skip "does not work under podman"
- cd ${TESTSDIR}/bud/from-scratch
- run_buildah bud --signature-policy ${TESTSDIR}/policy.json
- }
-@@ -1894,7 +1898,7 @@ _EOF
- @test "bud without any arguments should fail when no Dockerfile exist" {
- cd $(mktemp -d)
- run_buildah 125 bud --signature-policy ${TESTSDIR}/policy.json
-- expect_output --substring "no such file or directory"
-+ expect_output "Error: no context directory and no Containerfile specified"
- }
-
- @test "bud with specified context should fail if directory contains no Dockerfile" {
-@@ -1907,16 +1911,17 @@ _EOF
- DIR=$(mktemp -d)
- mkdir -p "$DIR"/Dockerfile
- run_buildah 125 bud --signature-policy ${TESTSDIR}/policy.json "$DIR"
-- expect_output --substring "is not a file"
-+ expect_output --substring "Error: open .*: no such file or directory"
- }
-
- @test "bud with specified context should fail if context contains not-existing Dockerfile" {
- DIR=$(mktemp -d)
- run_buildah 125 bud --signature-policy ${TESTSDIR}/policy.json "$DIR"/Dockerfile
-- expect_output --substring "no such file or directory"
-+ expect_output --substring "context must be a directory"
- }
-
- @test "bud with specified context should succeed if context contains existing Dockerfile" {
-+ skip "podman requires a directory, not a Dockerfile"
- DIR=$(mktemp -d)
- echo "FROM alpine" > "$DIR"/Dockerfile
- run_buildah 0 bud --signature-policy ${TESTSDIR}/policy.json "$DIR"/Dockerfile
-@@ -1968,7 +1973,7 @@ _EOF
-
- @test "bud-squash-hardlinks" {
- _prefetch busybox
-- run_buildah bud --signature-policy ${TESTSDIR}/policy.json --squash ${TESTSDIR}/bud/layers-squash/Dockerfile.hardlinks
-+ run_buildah bud --signature-policy ${TESTSDIR}/policy.json --squash -f Dockerfile.hardlinks ${TESTSDIR}/bud/layers-squash
- }
-
- @test "bud with additional directory of devices" {
-@@ -2134,6 +2139,7 @@ _EOF
- }
-
- @test "bud with Containerfile should fail with nonexistent authfile" {
-+ skip "FIXME: podman issue #9572"
- target=alpine-image
- run_buildah 125 bud --authfile /tmp/nonexistent --signature-policy ${TESTSDIR}/policy.json -t ${target} ${TESTSDIR}/bud/containerfile
- }
-@@ -2261,6 +2267,7 @@ EOM
- }
-
- @test "bud with encrypted FROM image" {
-+ skip "Too much effort to spin up a local registry"
- _prefetch busybox
- mkdir ${TESTDIR}/tmp
- openssl genrsa -out ${TESTDIR}/tmp/mykey.pem 1024
-@@ -2333,8 +2340,6 @@ EOM
- _prefetch alpine
- run_buildah bud --timestamp=0 --quiet --pull=false --signature-policy ${TESTSDIR}/policy.json -t timestamp -f Dockerfile.1 ${TESTSDIR}/bud/cache-stages
- cid=$output
-- run_buildah inspect --format '{{ .Docker.Created }}' timestamp
-- expect_output --substring "1970-01-01"
- run_buildah inspect --format '{{ .OCIv1.Created }}' timestamp
- expect_output --substring "1970-01-01"
- run_buildah inspect --format '{{ .History }}' timestamp
-@@ -2594,6 +2599,7 @@ _EOF
- }
-
- @test "bud with --arch flag" {
-+ skip "FIXME: for podman, emergency skip to get CI going"
- _prefetch alpine
- mytmpdir=${TESTDIR}/my-dir
- mkdir -p ${mytmpdir}
diff --git a/tests/helpers.bash b/tests/helpers.bash
-index b28fd2c3..d42a6b82 100644
+index 99c290af..c5572840 100644
--- a/tests/helpers.bash
+++ b/tests/helpers.bash
@@ -70,7 +70,7 @@ function _prefetch() {
- mkdir -p ${_BUILDAH_IMAGE_CACHEDIR}
- fi
+ mkdir -p ${_BUILDAH_IMAGE_CACHEDIR}
+ fi
-- local _podman_opts="--root ${TESTDIR}/root --storage-driver ${STORAGE_DRIVER}"
-+ local _podman_opts="--root ${TESTDIR}/root --runroot ${TESTDIR}/runroot --storage-driver ${STORAGE_DRIVER}"
+- local _podman_opts="--root ${TESTDIR}/root --storage-driver ${STORAGE_DRIVER}"
++ local _podman_opts="--root ${TESTDIR}/root --runroot ${TESTDIR}/runroot --storage-driver ${STORAGE_DRIVER}"
- for img in "$@"; do
- echo "# [checking for: $img]" >&2
+ for img in "$@"; do
+ echo "# [checking for: $img]" >&2
@@ -138,15 +138,35 @@ function run_buildah() {
--retry) retry=3; shift;; # retry network flakes
esac
diff --git a/test/buildah-bud/make-new-buildah-diffs b/test/buildah-bud/make-new-buildah-diffs
index 1191f4597..11987e376 100644
--- a/test/buildah-bud/make-new-buildah-diffs
+++ b/test/buildah-bud/make-new-buildah-diffs
@@ -37,11 +37,11 @@ if [[ $n_commits -gt 1 ]]; then
die "Please squash your commits"
fi
-# Scope check: make sure the only files changed are under tests/
-changes=$(git diff --name-status [BASETAG]..HEAD | egrep -v '\stests/')
+# Scope check: make sure the only files changed is helpers.bash
+changes=$(git diff --name-status [BASETAG]..HEAD | egrep -v '\stests/helpers.bash')
if [[ -n "$changes" ]]; then
echo $changes
- die "Found modified files other than under 'tests/'"
+ die "Found modified files other than 'tests/helpers.bash'"
fi
###############################################################################
diff --git a/test/buildah-bud/run-buildah-bud-tests b/test/buildah-bud/run-buildah-bud-tests
index 67c8fdfa4..b08b854ee 100755
--- a/test/buildah-bud/run-buildah-bud-tests
+++ b/test/buildah-bud/run-buildah-bud-tests
@@ -14,16 +14,25 @@ BASE_TAG=buildah-bud-in-podman
# END user-customizable section
###############################################################################
-usage="Usage: $ME [--help] [--no-checkout] [--no-test]
+usage="Usage: $ME [--help] [--no-checkout] [--no-test] [--filter=TESTNAME]
+
+Flags, useful for manual debugging:
+
+ --no-checkout Skip checkout step, go directly to running tests
+ --no-test Do checkout only, but do not run tests
+ --filter=NAME Passed on to bats; runs only tests that match NAME
"
# Parse command-line options (used in development only, not in CI)
do_checkout=y
do_test=y
+declare -a bats_filter=()
for i; do
+ value=$(expr "$i" : '[^=]*=\(.*\)')
case "$i" in
--no-checkout) do_checkout= ; shift;;
--no-test) do_test= ; shift;;
+ --filter=*) bats_filter=("--filter" "$value"); shift;;
-h|--help) echo "$usage"; exit 0;;
*) echo "$ME: Unrecognized option '$i'" >&2; exit 1;;
esac
@@ -72,7 +81,7 @@ function die() {
# From here on out, any unexpected abort will try to offer helpful hints
failhint=
-trap 'if [[ $? != 0 ]]; then if [[ -n $failhint ]]; then echo;echo "***************************************";echo $failhint;echo;echo "Please see $BUD_TEST_DIR_REL/README.md for advice";fi;fi' 0
+trap 'if [[ $? != 0 ]]; then if [[ -n $failhint ]]; then echo;echo "***************************************";echo "$failhint";echo;echo "Please see $BUD_TEST_DIR_REL/README.md for advice";fi;fi' 0
# Find the version of buildah we've vendored in, so we can run the right tests
buildah_version=$(awk "\$1 == \"$BUILDAH_REPO\" { print \$2 }" <go.mod)
@@ -110,10 +119,27 @@ if [[ -n $do_checkout ]]; then
die "Directory already exists: $buildah_dir"
fi
+ # buildah_version should usually be vX.Y, but sometimes a PR under test
+ # will need a special unreleased version (go calls then "pseudoversions").
+ # In the usual case, we can do a shallow git clone:
+ shallow_checkout="--branch $buildah_version"
+ if [[ $buildah_version =~ .*-.*\.[0-9]{14}-.* ]]; then
+ # ...but with a pseudoversion, we must git-clone the entire repo,
+ # then do a git checkout within it
+ shallow_checkout=
+ fi
+
failhint="'git clone' failed - this should never happen!"
- (set -x;git clone -q --branch $buildah_version https://$BUILDAH_REPO $buildah_dir)
+ (set -x;git clone -q $shallow_checkout https://$BUILDAH_REPO $buildah_dir)
cd $buildah_dir
+ if [[ -z $shallow_checkout ]]; then
+ # extract the SHA (rightmost field) from, e.g., v1.2-YYYMMDD-<sha>
+ sha=${buildah_version##*-}
+
+ failhint="'git checkout $sha' failed - this should never happen!"
+ (set -x;git checkout -q $sha)
+ fi
# Give it a recognizable tag; this will be useful if we need to update
# the set of patches
@@ -123,18 +149,43 @@ if [[ -n $do_checkout ]]; then
failhint="error building buildah. This should never happen."
(set -x;make bin/buildah)
- # Apply custom patches. We do this _after_ building, although it shouldn't
- # matter because these patches should only apply to test scripts.
- failhint="
-Error applying patch file. This can happen when you vendor in a new buildah."
- (set -x;git am <$PATCHES)
-
+ # The upcoming patch may fail. Before we try it, create a helper script
+ # for a developer to push a new set of diffs to podman-land.
failhint=
sed -e "s,\[BASETAG\],${BASE_TAG},g" \
-e "s,\[BUILDAHREPO\],${BUILDAH_REPO},g" \
< ${BUD_TEST_DIR}/make-new-buildah-diffs \
> make-new-buildah-diffs
chmod 755 make-new-buildah-diffs
+
+ # Apply custom patches. We do this _after_ building, although it shouldn't
+ # matter because these patches should only apply to test scripts and not
+ # to any buildah sources.
+ failhint="
+Error applying patch file. This can happen when you vendor in a new buildah.
+You will want to:
+
+ - look for 'test/*.rej'
+ - resolve conflicts manually
+ - git add test/helpers.bash
+ - git am --continue
+ - ./make-new-buildah-diffs
+"
+ (set -x;git am --reject <$PATCHES)
+
+ # Now apply our custom skips and error-message changes. This is maintained
+ # in a custom script, not a .diff file, because diffs are WAY too hard for
+ # humans to read and update.
+ APPLY=apply-podman-deltas
+ failhint="
+Error applying podman-specific deltas. This sometimes happens when you
+vendor in a new buildah. You will want to:
+
+ - inspect the errors shown above
+ - find the corresponding lines in $BUD_TEST_DIR_REL/$APPLY
+ - edit/delete them as necessary
+"
+ (set -x;$BUD_TEST_DIR/$APPLY)
else
# Called with --no-checkout
test -d $buildah_dir || die "Called with --no-checkout, but $buildah_dir does not exist"
@@ -162,5 +213,5 @@ review the test failure and double-check your changes.
(set -x;sudo env TMPDIR=/var/tmp \
PODMAN_BINARY=$PODMAN_BINARY \
BUILDAH_BINARY=$(pwd)/bin/buildah \
- bats tests/bud.bats)
+ bats "${bats_filter[@]}" tests/bud.bats)
fi
diff --git a/test/compose/test-compose b/test/compose/test-compose
index 704c71a9f..46ca80321 100755
--- a/test/compose/test-compose
+++ b/test/compose/test-compose
@@ -136,8 +136,11 @@ function _show_ok() {
local expect=$3
local actual=$4
printf "${red}not ok $count $testname${reset}\n"
- printf "${red}# expected: %s${reset}\n" "$expect"
- printf "${red}# actual: ${bold}%s${reset}\n" "$actual"
+ # Not all errors include actual/expect
+ if [[ -n "$expect" || -n "$actual" ]]; then
+ printf "${red}# expected: %s${reset}\n" "$expect"
+ printf "${red}# actual: ${bold}%s${reset}\n" "$actual"
+ fi
echo "not ok $count $testname" >>$LOG
echo " expected: $expect" >>$LOG
@@ -163,12 +166,24 @@ function test_port() {
local op="$2" # '=' or '~'
local expect="$3" # what to expect from curl output
- local actual=$(curl --retry 10 --retry-all-errors -s http://127.0.0.1:$port/)
+ # -s -S means "silent, but show errors"
+ local actual
+ actual=$(curl --retry 3 --retry-all-errors -s -S http://127.0.0.1:$port/)
local curl_rc=$?
+
if [ $curl_rc -ne 0 ]; then
- _show_ok 0 "$testname - curl failed with status $curl_rc"
-### docker-compose down >>$logfile 2>&1
-### exit 1
+ _show_ok 0 "$testname - curl (port $port) failed with status $curl_rc"
+ echo "# podman ps -a:"
+ $PODMAN_BIN --root $WORKDIR/root --runroot $WORKDIR/runroot ps -a
+ if type -p ss; then
+ echo "# ss -tulpn:"
+ ss -tulpn
+ echo "# podman unshare --rootless-cni ss -tulpn:"
+ $PODMAN_BIN --root $WORKDIR/root --runroot $WORKDIR/runroot unshare --rootless-cni ss -tulpn
+ fi
+ echo "# cat $WORKDIR/server.log:"
+ cat $WORKDIR/server.log
+ return
fi
case "$op" in
@@ -198,6 +213,7 @@ function start_service() {
cp /etc/cni/net.d/*podman*conflist $WORKDIR/cni/
$PODMAN_BIN \
+ --log-level debug \
--root $WORKDIR/root \
--runroot $WORKDIR/runroot \
--cgroup-manager=systemd \
@@ -279,6 +295,10 @@ fi
# Too hard to precompute the number of tests; just spit it out at the end.
n_tests=0
+
+# We aren't really TAP 13; this helps logformatter recognize our output as BATS
+echo "TAP version 13"
+
for t in ${tests_to_run[@]}; do
testdir="$(dirname $t)"
testname="$(basename $testdir)"
diff --git a/test/e2e/build_test.go b/test/e2e/build_test.go
index 4f337116e..6255690b1 100644
--- a/test/e2e/build_test.go
+++ b/test/e2e/build_test.go
@@ -566,4 +566,42 @@ RUN echo hello`, ALPINE)
Expect(session.OutputToString()).To(ContainSubstring("(user)"))
Expect(session.OutputToString()).To(ContainSubstring("(elapsed)"))
})
+
+ It("podman build --arch --os flag", func() {
+ containerfile := `FROM scratch`
+ containerfilePath := filepath.Join(podmanTest.TempDir, "Containerfile")
+ err := ioutil.WriteFile(containerfilePath, []byte(containerfile), 0755)
+ Expect(err).To(BeNil())
+ session := podmanTest.Podman([]string{"build", "--pull-never", "-t", "test", "--arch", "foo", "--os", "bar", "--file", containerfilePath, podmanTest.TempDir})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ inspect := podmanTest.Podman([]string{"image", "inspect", "--format", "{{ .Architecture }}", "test"})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect.OutputToString()).To(Equal("foo"))
+
+ inspect = podmanTest.Podman([]string{"image", "inspect", "--format", "{{ .Os }}", "test"})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect.OutputToString()).To(Equal("bar"))
+
+ })
+
+ It("podman build --os windows flag", func() {
+ containerfile := `FROM scratch`
+ containerfilePath := filepath.Join(podmanTest.TempDir, "Containerfile")
+ err := ioutil.WriteFile(containerfilePath, []byte(containerfile), 0755)
+ Expect(err).To(BeNil())
+ session := podmanTest.Podman([]string{"build", "--pull-never", "-t", "test", "--os", "windows", "--file", containerfilePath, podmanTest.TempDir})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ inspect := podmanTest.Podman([]string{"image", "inspect", "--format", "{{ .Architecture }}", "test"})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect.OutputToString()).To(Equal(runtime.GOARCH))
+
+ inspect = podmanTest.Podman([]string{"image", "inspect", "--format", "{{ .Os }}", "test"})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect.OutputToString()).To(Equal("windows"))
+
+ })
})
diff --git a/test/e2e/config_amd64.go b/test/e2e/config_amd64.go
index 25e50a541..3607bdc30 100644
--- a/test/e2e/config_amd64.go
+++ b/test/e2e/config_amd64.go
@@ -5,7 +5,7 @@ var (
STORAGE_OPTIONS = "--storage-driver vfs"
ROOTLESS_STORAGE_FS = "vfs"
ROOTLESS_STORAGE_OPTIONS = "--storage-driver vfs"
- CACHE_IMAGES = []string{ALPINE, BB, fedoraMinimal, nginx, redis, registry, infra, labels, healthcheck, ubi_init, ubi_minimal}
+ CACHE_IMAGES = []string{ALPINE, BB, fedoraMinimal, nginx, redis, registry, infra, labels, healthcheck, ubi_init, ubi_minimal, fedoraToolbox}
nginx = "quay.io/libpod/alpine_nginx:latest"
BB_GLIBC = "docker.io/library/busybox:glibc"
registry = "quay.io/libpod/registry:2.6"
diff --git a/test/e2e/generate_kube_test.go b/test/e2e/generate_kube_test.go
index 1c53307bd..c3586d9b6 100644
--- a/test/e2e/generate_kube_test.go
+++ b/test/e2e/generate_kube_test.go
@@ -6,6 +6,7 @@ import (
"path/filepath"
"strconv"
+ "github.com/containers/podman/v3/pkg/util"
. "github.com/containers/podman/v3/test/utils"
"github.com/ghodss/yaml"
. "github.com/onsi/ginkgo"
@@ -554,7 +555,7 @@ var _ = Describe("Podman generate kube", func() {
Expect(inspect.OutputToString()).To(ContainSubstring(`"pid"`))
})
- It("podman generate kube with pods and containers should fail", func() {
+ It("podman generate kube with pods and containers", func() {
pod1 := podmanTest.Podman([]string{"run", "-dt", "--pod", "new:pod1", ALPINE, "top"})
pod1.WaitWithDefaultTimeout()
Expect(pod1.ExitCode()).To(Equal(0))
@@ -565,7 +566,7 @@ var _ = Describe("Podman generate kube", func() {
kube := podmanTest.Podman([]string{"generate", "kube", "pod1", "top"})
kube.WaitWithDefaultTimeout()
- Expect(kube.ExitCode()).ToNot(Equal(0))
+ Expect(kube.ExitCode()).To(Equal(0))
})
It("podman generate kube with containers in a pod should fail", func() {
@@ -630,7 +631,7 @@ var _ = Describe("Podman generate kube", func() {
Expect(*pod.Spec.DNSConfig.Options[0].Value).To(Equal("blue"))
})
- It("podman generate kube multiple contianer dns servers and options are cumulative", func() {
+ It("podman generate kube multiple container dns servers and options are cumulative", func() {
top1 := podmanTest.Podman([]string{"run", "-dt", "--name", "top1", "--dns", "8.8.8.8", "--dns-search", "foobar.com", ALPINE, "top"})
top1.WaitWithDefaultTimeout()
Expect(top1.ExitCode()).To(BeZero())
@@ -798,4 +799,55 @@ USER test1`
Expect(*pod.Spec.Containers[0].SecurityContext.RunAsUser).To(Equal(int64(10001)))
})
+ It("podman generate kube on named volume", func() {
+ vol := "simple-named-volume"
+
+ session := podmanTest.Podman([]string{"volume", "create", vol})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ kube := podmanTest.Podman([]string{"generate", "kube", vol})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube.ExitCode()).To(Equal(0))
+
+ pvc := new(v1.PersistentVolumeClaim)
+ err := yaml.Unmarshal(kube.Out.Contents(), pvc)
+ Expect(err).To(BeNil())
+ Expect(pvc.GetName()).To(Equal(vol))
+ Expect(pvc.Spec.AccessModes[0]).To(Equal(v1.ReadWriteOnce))
+ Expect(pvc.Spec.Resources.Requests.Storage().String()).To(Equal("1Gi"))
+ })
+
+ It("podman generate kube on named volume with options", func() {
+ vol := "complex-named-volume"
+ volDevice := "tmpfs"
+ volType := "tmpfs"
+ volOpts := "nodev,noexec"
+
+ session := podmanTest.Podman([]string{"volume", "create", "--opt", "device=" + volDevice, "--opt", "type=" + volType, "--opt", "o=" + volOpts, vol})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ kube := podmanTest.Podman([]string{"generate", "kube", vol})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube.ExitCode()).To(Equal(0))
+
+ pvc := new(v1.PersistentVolumeClaim)
+ err := yaml.Unmarshal(kube.Out.Contents(), pvc)
+ Expect(err).To(BeNil())
+ Expect(pvc.GetName()).To(Equal(vol))
+ Expect(pvc.Spec.AccessModes[0]).To(Equal(v1.ReadWriteOnce))
+ Expect(pvc.Spec.Resources.Requests.Storage().String()).To(Equal("1Gi"))
+
+ for k, v := range pvc.GetAnnotations() {
+ switch k {
+ case util.VolumeDeviceAnnotation:
+ Expect(v).To(Equal(volDevice))
+ case util.VolumeTypeAnnotation:
+ Expect(v).To(Equal(volType))
+ case util.VolumeMountOptsAnnotation:
+ Expect(v).To(Equal(volOpts))
+ }
+ }
+ })
})
diff --git a/test/e2e/images_test.go b/test/e2e/images_test.go
index 29be505b7..098d58033 100644
--- a/test/e2e/images_test.go
+++ b/test/e2e/images_test.go
@@ -78,7 +78,7 @@ var _ = Describe("Podman images", func() {
session = podmanTest.Podman([]string{"images", "-qn"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(BeNumerically("==", 11))
+ Expect(len(session.OutputToStringArray())).To(BeNumerically("==", len(CACHE_IMAGES)))
})
It("podman images with digests", func() {
@@ -194,7 +194,7 @@ WORKDIR /test
result := podmanTest.Podman([]string{"images", "-q", "-f", "since=quay.io/libpod/alpine:latest"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
- Expect(len(result.OutputToStringArray())).To(Equal(8))
+ Expect(len(result.OutputToStringArray())).To(Equal(9))
})
It("podman image list filter after image", func() {
@@ -204,7 +204,7 @@ WORKDIR /test
result := podmanTest.Podman([]string{"image", "list", "-q", "-f", "after=quay.io/libpod/alpine:latest"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
- Expect(result.OutputToStringArray()).Should(HaveLen(8), "list filter output: %q", result.OutputToString())
+ Expect(result.OutputToStringArray()).Should(HaveLen(9), "list filter output: %q", result.OutputToString())
})
It("podman images filter dangling", func() {
diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go
index 93c8426a7..f89da4c05 100644
--- a/test/e2e/play_kube_test.go
+++ b/test/e2e/play_kube_test.go
@@ -10,7 +10,9 @@ import (
"strings"
"text/template"
+ "github.com/containers/podman/v3/pkg/util"
. "github.com/containers/podman/v3/test/utils"
+ "github.com/containers/storage/pkg/stringid"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/opencontainers/selinux/go-selinux"
@@ -83,6 +85,26 @@ data:
{{ end }}
`
+var persistentVolumeClaimYamlTemplate = `
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+ name: {{ .Name }}
+{{ with .Annotations }}
+ annotations:
+ {{ range $key, $value := . }}
+ {{ $key }}: {{ $value }}
+ {{ end }}
+{{ end }}
+spec:
+ accessModes:
+ - "ReadWriteOnce"
+ resources:
+ requests:
+ storage: "1Gi"
+ storageClassName: default
+`
+
var podYamlTemplate = `
apiVersion: v1
kind: Pod
@@ -337,10 +359,31 @@ spec:
privileged: false
readOnlyRootFilesystem: false
workingDir: /
+ volumeMounts:
+ {{ if .VolumeMount }}
+ - name: {{.VolumeName}}
+ mountPath: {{ .VolumeMountPath }}
+ readonly: {{.VolumeReadOnly}}
+ {{ end }}
{{ end }}
{{ end }}
{{ end }}
- {{ end }}
+ {{ with .Volumes }}
+ volumes:
+ {{ range . }}
+ - name: {{ .Name }}
+ {{- if (eq .VolumeType "HostPath") }}
+ hostPath:
+ path: {{ .HostPath.Path }}
+ type: {{ .HostPath.Type }}
+ {{- end }}
+ {{- if (eq .VolumeType "PersistentVolumeClaim") }}
+ persistentVolumeClaim:
+ claimName: {{ .PersistentVolumeClaim.ClaimName }}
+ {{- end }}
+ {{ end }}
+ {{ end }}
+{{ end }}
`
var (
@@ -352,6 +395,7 @@ var (
defaultVolName = "testVol"
defaultDeploymentName = "testDeployment"
defaultConfigMapName = "testConfigMap"
+ defaultPVCName = "testPVC"
seccompPwdEPERM = []byte(`{"defaultAction":"SCMP_ACT_ALLOW","syscalls":[{"name":"getcwd","action":"SCMP_ACT_ERRNO"}]}`)
// CPU Period in ms
defaultCPUPeriod = 100
@@ -386,6 +430,8 @@ func getKubeYaml(kind string, object interface{}) (string, error) {
yamlTemplate = podYamlTemplate
case "deployment":
yamlTemplate = deploymentYamlTemplate
+ case "persistentVolumeClaim":
+ yamlTemplate = persistentVolumeClaimYamlTemplate
default:
return "", fmt.Errorf("unsupported kubernetes kind")
}
@@ -467,6 +513,39 @@ func withConfigMapData(k, v string) configMapOption {
}
}
+// PVC describes the options a kube yaml can be configured at persistent volume claim level
+type PVC struct {
+ Name string
+ Annotations map[string]string
+}
+
+func getPVC(options ...pvcOption) *PVC {
+ pvc := PVC{
+ Name: defaultPVCName,
+ Annotations: map[string]string{},
+ }
+
+ for _, option := range options {
+ option(&pvc)
+ }
+
+ return &pvc
+}
+
+type pvcOption func(*PVC)
+
+func withPVCName(name string) pvcOption {
+ return func(pvc *PVC) {
+ pvc.Name = name
+ }
+}
+
+func withPVCAnnotations(k, v string) pvcOption {
+ return func(pvc *PVC) {
+ pvc.Annotations[k] = v
+ }
+}
+
// Pod describes the options a kube yaml can be configured at pod level
type Pod struct {
Name string
@@ -1638,6 +1717,38 @@ spec:
}
})
+ It("podman play kube --ip", func() {
+ var i, numReplicas int32
+ numReplicas = 3
+ deployment := getDeployment(withReplicas(numReplicas))
+ err := generateKubeYaml("deployment", deployment, kubeYaml)
+ Expect(err).To(BeNil())
+
+ net := "playkube" + stringid.GenerateNonCryptoID()
+ session := podmanTest.Podman([]string{"network", "create", "--subnet", "10.25.31.0/24", net})
+ session.WaitWithDefaultTimeout()
+ defer podmanTest.removeCNINetwork(net)
+ Expect(session.ExitCode()).To(BeZero())
+
+ ips := []string{"10.25.31.5", "10.25.31.10", "10.25.31.15"}
+ playArgs := []string{"play", "kube", "--network", net}
+ for _, ip := range ips {
+ playArgs = append(playArgs, "--ip", ip)
+ }
+
+ kube := podmanTest.Podman(append(playArgs, kubeYaml))
+ kube.WaitWithDefaultTimeout()
+ Expect(kube.ExitCode()).To(Equal(0))
+
+ podNames := getPodNamesInDeployment(deployment)
+ for i = 0; i < numReplicas; i++ {
+ inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(&podNames[i]), "--format", "{{ .NetworkSettings.Networks." + net + ".IPAddress }}"})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect.ExitCode()).To(Equal(0))
+ Expect(inspect.OutputToString()).To(Equal(ips[i]))
+ }
+ })
+
It("podman play kube test with network portbindings", func() {
ip := "127.0.0.100"
port := "5000"
@@ -1783,6 +1894,54 @@ spec:
Expect(inspect.OutputToString()).To(ContainSubstring(correct))
})
+ It("podman play kube test duplicate volume destination between host path and image volumes", func() {
+ // Create host test directory and file
+ testdir := "testdir"
+ testfile := "testfile"
+
+ hostPathDir := filepath.Join(tempdir, testdir)
+ err := os.Mkdir(hostPathDir, 0755)
+ Expect(err).To(BeNil())
+
+ hostPathDirFile := filepath.Join(hostPathDir, testfile)
+ f, err := os.Create(hostPathDirFile)
+ Expect(err).To(BeNil())
+ f.Close()
+
+ // Create container image with named volume
+ containerfile := fmt.Sprintf(`
+FROM %s
+VOLUME %s`, ALPINE, hostPathDir+"/")
+
+ image := "podman-kube-test:podman"
+ podmanTest.BuildImage(containerfile, image, "false")
+
+ // Create and play kube pod
+ ctr := getCtr(withVolumeMount(hostPathDir+"/", false), withImage(image))
+ pod := getPod(withCtr(ctr), withVolume(getHostPathVolume("Directory", hostPathDir+"/")))
+ err = generateKubeYaml("pod", pod, kubeYaml)
+ Expect(err).To(BeNil())
+
+ kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube.ExitCode()).To(Equal(0))
+
+ result := podmanTest.Podman([]string{"exec", getCtrNameInPod(pod), "ls", hostPathDir + "/" + testfile})
+ result.WaitWithDefaultTimeout()
+ Expect(result.ExitCode()).To(Equal(0))
+
+ inspect := podmanTest.Podman([]string{"inspect", getCtrNameInPod(pod)})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect.ExitCode()).To(Equal(0))
+
+ // If two volumes are specified and share the same destination,
+ // only one will be mounted. Host path volumes take precedence.
+ ctrJSON := inspect.InspectContainerToJSON()
+ Expect(len(ctrJSON[0].Mounts)).To(Equal(1))
+ Expect(ctrJSON[0].Mounts[0].Type).To(Equal("bind"))
+
+ })
+
It("podman play kube test with PersistentVolumeClaim volume", func() {
volumeName := "namedVolume"
@@ -1892,7 +2051,6 @@ MemoryReservation: {{ .HostConfig.MemoryReservation }}`})
})
It("podman play kube applies log driver to containers", func() {
- Skip("need to verify images have correct packages for journald")
pod := getPod()
err := generateKubeYaml("pod", pod, kubeYaml)
Expect(err).To(BeNil())
@@ -1941,8 +2099,106 @@ MemoryReservation: {{ .HostConfig.MemoryReservation }}`})
Expect(inspect.OutputToString()).To(Equal("true"))
})
+ It("podman play kube persistentVolumeClaim", func() {
+ volName := "myvol"
+ volDevice := "tmpfs"
+ volType := "tmpfs"
+ volOpts := "nodev,noexec"
+
+ pvc := getPVC(withPVCName(volName),
+ withPVCAnnotations(util.VolumeDeviceAnnotation, volDevice),
+ withPVCAnnotations(util.VolumeTypeAnnotation, volType),
+ withPVCAnnotations(util.VolumeMountOptsAnnotation, volOpts))
+ err = generateKubeYaml("persistentVolumeClaim", pvc, kubeYaml)
+ Expect(err).To(BeNil())
+
+ kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube.ExitCode()).To(Equal(0))
+
+ inspect := podmanTest.Podman([]string{"inspect", volName, "--format", `
+Name: {{ .Name }}
+Device: {{ .Options.device }}
+Type: {{ .Options.type }}
+o: {{ .Options.o }}`})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect.ExitCode()).To(Equal(0))
+ Expect(inspect.OutputToString()).To(ContainSubstring("Name: " + volName))
+ Expect(inspect.OutputToString()).To(ContainSubstring("Device: " + volDevice))
+ Expect(inspect.OutputToString()).To(ContainSubstring("Type: " + volType))
+ Expect(inspect.OutputToString()).To(ContainSubstring("o: " + volOpts))
+ })
+
// Multi doc related tests
- It("podman play kube multi doc yaml", func() {
+ It("podman play kube multi doc yaml with persistentVolumeClaim, service and deployment", func() {
+ yamlDocs := []string{}
+
+ serviceTemplate := `apiVersion: v1
+kind: Service
+metadata:
+ name: %s
+spec:
+ ports:
+ - port: 80
+ protocol: TCP
+ targetPort: 9376
+ selector:
+ app: %s
+`
+ // generate persistentVolumeClaim
+ volName := "multiFoo"
+ pvc := getPVC(withPVCName(volName))
+
+ // generate deployment
+ deploymentName := "multiFoo"
+ podName := "multiFoo"
+ ctrName := "ctr-01"
+ ctr := getCtr(withVolumeMount("/test", false))
+ ctr.Name = ctrName
+ pod := getPod(withPodName(podName), withVolume(getPersistentVolumeClaimVolume(volName)), withCtr(ctr))
+ deployment := getDeployment(withPod(pod))
+ deployment.Name = deploymentName
+
+ // add pvc
+ k, err := getKubeYaml("persistentVolumeClaim", pvc)
+ Expect(err).To(BeNil())
+ yamlDocs = append(yamlDocs, k)
+
+ // add service
+ yamlDocs = append(yamlDocs, fmt.Sprintf(serviceTemplate, deploymentName, deploymentName))
+
+ // add deployment
+ k, err = getKubeYaml("deployment", deployment)
+ Expect(err).To(BeNil())
+ yamlDocs = append(yamlDocs, k)
+
+ // generate multi doc yaml
+ err = generateMultiDocKubeYaml(yamlDocs, kubeYaml)
+ Expect(err).To(BeNil())
+
+ kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube.ExitCode()).To(Equal(0))
+
+ inspectVolume := podmanTest.Podman([]string{"inspect", volName, "--format", "'{{ .Name }}'"})
+ inspectVolume.WaitWithDefaultTimeout()
+ Expect(inspectVolume.ExitCode()).To(Equal(0))
+ Expect(inspectVolume.OutputToString()).To(ContainSubstring(volName))
+
+ inspectPod := podmanTest.Podman([]string{"inspect", podName + "-pod-0", "--format", "'{{ .State }}'"})
+ inspectPod.WaitWithDefaultTimeout()
+ Expect(inspectPod.ExitCode()).To(Equal(0))
+ Expect(inspectPod.OutputToString()).To(ContainSubstring(`Running`))
+
+ inspectMounts := podmanTest.Podman([]string{"inspect", podName + "-pod-0-" + ctrName, "--format", "{{ (index .Mounts 0).Type }}:{{ (index .Mounts 0).Name }}"})
+ inspectMounts.WaitWithDefaultTimeout()
+ Expect(inspectMounts.ExitCode()).To(Equal(0))
+
+ correct := fmt.Sprintf("volume:%s", volName)
+ Expect(inspectMounts.OutputToString()).To(Equal(correct))
+ })
+
+ It("podman play kube multi doc yaml with multiple services, pods and deployments", func() {
yamlDocs := []string{}
podNames := []string{}
@@ -1958,7 +2214,7 @@ spec:
selector:
app: %s
`
- // generate servies, pods and deployments
+ // generate services, pods and deployments
for i := 0; i < 2; i++ {
podName := fmt.Sprintf("testPod%d", i)
deploymentName := fmt.Sprintf("testDeploy%d", i)
diff --git a/test/e2e/rmi_test.go b/test/e2e/rmi_test.go
index 5e6d66d53..03a347a6f 100644
--- a/test/e2e/rmi_test.go
+++ b/test/e2e/rmi_test.go
@@ -221,7 +221,7 @@ var _ = Describe("Podman rmi", func() {
session = podmanTest.Podman([]string{"images", "-q", "-a"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToStringArray())).To(Equal(12))
+ Expect(len(session.OutputToStringArray())).To(Equal(len(CACHE_IMAGES) + 1))
podmanTest.BuildImage(dockerfile, "test3", "true")
@@ -236,7 +236,7 @@ var _ = Describe("Podman rmi", func() {
session = podmanTest.Podman([]string{"images", "-q", "-a"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(len(session.OutputToString())).To(Equal(142))
+ Expect(len(session.OutputToString())).To(Equal(155))
})
It("podman rmi -a with no images should be exit 0", func() {
diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go
index 23930b4f7..cefe00655 100644
--- a/test/e2e/run_test.go
+++ b/test/e2e/run_test.go
@@ -1588,4 +1588,29 @@ WORKDIR /madethis`, BB)
Expect(session.OutputToString()).To(ContainSubstring("mysecret"))
})
+
+ It("podman run --requires", func() {
+ depName := "ctr1"
+ depContainer := podmanTest.Podman([]string{"create", "--name", depName, ALPINE, "top"})
+ depContainer.WaitWithDefaultTimeout()
+ Expect(depContainer.ExitCode()).To(Equal(0))
+
+ mainName := "ctr2"
+ mainContainer := podmanTest.Podman([]string{"run", "--name", mainName, "--requires", depName, "-d", ALPINE, "top"})
+ mainContainer.WaitWithDefaultTimeout()
+ Expect(mainContainer.ExitCode()).To(Equal(0))
+
+ stop := podmanTest.Podman([]string{"stop", "--all"})
+ stop.WaitWithDefaultTimeout()
+ Expect(stop.ExitCode()).To(Equal(0))
+
+ start := podmanTest.Podman([]string{"start", mainName})
+ start.WaitWithDefaultTimeout()
+ Expect(start.ExitCode()).To(Equal(0))
+
+ running := podmanTest.Podman([]string{"ps", "-q"})
+ running.WaitWithDefaultTimeout()
+ Expect(running.ExitCode()).To(Equal(0))
+ Expect(len(running.OutputToStringArray())).To(Equal(2))
+ })
})
diff --git a/test/e2e/save_test.go b/test/e2e/save_test.go
index 5ddd5efc8..69184649f 100644
--- a/test/e2e/save_test.go
+++ b/test/e2e/save_test.go
@@ -79,7 +79,7 @@ var _ = Describe("Podman save", func() {
})
It("podman save to directory with oci format", func() {
- if rootless.IsRootless() && podmanTest.RemoteTest {
+ if rootless.IsRootless() {
Skip("Requires a fix in containers image for chown/lchown")
}
outdir := filepath.Join(podmanTest.TempDir, "save")
@@ -90,7 +90,7 @@ var _ = Describe("Podman save", func() {
})
It("podman save to directory with v2s2 docker format", func() {
- if rootless.IsRootless() && podmanTest.RemoteTest {
+ if rootless.IsRootless() {
Skip("Requires a fix in containers image for chown/lchown")
}
outdir := filepath.Join(podmanTest.TempDir, "save")
@@ -111,6 +111,24 @@ var _ = Describe("Podman save", func() {
Expect(save.ExitCode()).To(Equal(0))
})
+ It("podman save to directory with --compress but not use docker-dir and oci-dir", func() {
+ if rootless.IsRootless() && podmanTest.RemoteTest {
+ Skip("Requires a fix in containers image for chown/lchown")
+ }
+ outdir := filepath.Join(podmanTest.TempDir, "save")
+
+ save := podmanTest.Podman([]string{"save", "--compress", "--format", "docker-archive", "-o", outdir, ALPINE})
+ save.WaitWithDefaultTimeout()
+ // should not be 0
+ Expect(save.ExitCode()).ToNot(Equal(0))
+
+ save = podmanTest.Podman([]string{"save", "--compress", "--format", "oci-archive", "-o", outdir, ALPINE})
+ save.WaitWithDefaultTimeout()
+ // should not be 0
+ Expect(save.ExitCode()).ToNot(Equal(0))
+
+ })
+
It("podman save bad filename", func() {
outdir := filepath.Join(podmanTest.TempDir, "save:colon")
diff --git a/test/e2e/toolbox_test.go b/test/e2e/toolbox_test.go
index d605b59f9..986f856bf 100644
--- a/test/e2e/toolbox_test.go
+++ b/test/e2e/toolbox_test.go
@@ -215,7 +215,6 @@ var _ = Describe("Toolbox-specific testing", func() {
useradd := fmt.Sprintf("useradd --home-dir %s --shell %s --uid %s %s",
homeDir, shell, uid, username)
passwd := fmt.Sprintf("passwd --delete %s", username)
- podmanTest.AddImageToRWStore(fedoraToolbox)
session = podmanTest.Podman([]string{"create", "--name", "test", "--userns=keep-id", "--user", "root:root", fedoraToolbox, "sh", "-c",
fmt.Sprintf("%s; %s; echo READY; sleep 1000", useradd, passwd)})
session.WaitWithDefaultTimeout()
@@ -251,7 +250,6 @@ var _ = Describe("Toolbox-specific testing", func() {
groupadd := fmt.Sprintf("groupadd --gid %s %s", gid, groupName)
- podmanTest.AddImageToRWStore(fedoraToolbox)
session = podmanTest.Podman([]string{"create", "--name", "test", "--userns=keep-id", "--user", "root:root", fedoraToolbox, "sh", "-c",
fmt.Sprintf("%s; echo READY; sleep 1000", groupadd)})
session.WaitWithDefaultTimeout()
@@ -296,7 +294,6 @@ var _ = Describe("Toolbox-specific testing", func() {
usermod := fmt.Sprintf("usermod --append --groups wheel --home %s --shell %s --uid %s --gid %s %s",
homeDir, shell, uid, gid, username)
- podmanTest.AddImageToRWStore(fedoraToolbox)
session = podmanTest.Podman([]string{"create", "--name", "test", "--userns=keep-id", "--user", "root:root", fedoraToolbox, "sh", "-c",
fmt.Sprintf("%s; %s; %s; echo READY; sleep 1000", useradd, groupadd, usermod)})
session.WaitWithDefaultTimeout()
@@ -341,7 +338,6 @@ var _ = Describe("Toolbox-specific testing", func() {
// These should be most of the switches that Toolbox uses to create a "toolbox" container
// https://github.com/containers/toolbox/blob/master/src/cmd/create.go
- podmanTest.AddImageToRWStore(fedoraToolbox)
session = podmanTest.Podman([]string{"create",
"--dns", "none",
"--hostname", "toolbox",
@@ -378,7 +374,6 @@ var _ = Describe("Toolbox-specific testing", func() {
currentUser, err := user.Current()
Expect(err).To(BeNil())
- podmanTest.AddImageToRWStore(fedoraToolbox)
session = podmanTest.Podman([]string{"run", "-v", fmt.Sprintf("%s:%s", currentUser.HomeDir, currentUser.HomeDir), "--userns=keep-id", fedoraToolbox, "sh", "-c", "echo $HOME"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
diff --git a/test/e2e/unshare_test.go b/test/e2e/unshare_test.go
index 515b3a42e..24ab98916 100644
--- a/test/e2e/unshare_test.go
+++ b/test/e2e/unshare_test.go
@@ -49,4 +49,11 @@ var _ = Describe("Podman unshare", func() {
ok, _ := session.GrepString(userNS)
Expect(ok).To(BeFalse())
})
+
+ It("podman unshare --rootles-cni", func() {
+ session := podmanTest.Podman([]string{"unshare", "--rootless-cni", "ip", "addr"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+ Expect(session.OutputToString()).To(ContainSubstring("tap0"))
+ })
})
diff --git a/test/system/001-basic.bats b/test/system/001-basic.bats
index 081bb1171..35107f0a0 100644
--- a/test/system/001-basic.bats
+++ b/test/system/001-basic.bats
@@ -111,4 +111,17 @@ function setup() {
is "$output" "you found me" "sample invocation of 'jq'"
}
+@test "podman --log-level recognizes log levels" {
+ run_podman 1 --log-level=telepathic info
+ is "$output" 'Log Level "telepathic" is not supported.*'
+ run_podman --log-level=trace info
+ run_podman --log-level=debug info
+ run_podman --log-level=info info
+ run_podman --log-level=warn info
+ run_podman --log-level=warning info
+ run_podman --log-level=error info
+ run_podman --log-level=fatal info
+ run_podman --log-level=panic info
+}
+
# vim: filetype=sh
diff --git a/test/system/005-info.bats b/test/system/005-info.bats
index c0af2e937..ed341dd17 100644
--- a/test/system/005-info.bats
+++ b/test/system/005-info.bats
@@ -53,6 +53,27 @@ store.imageStore.number | 1
}
+# 2021-04-06 discussed in watercooler: RHEL must never use crun, even if
+# using cgroups v2.
+@test "podman info - RHEL8 must use runc" {
+ local osrelease=/etc/os-release
+ test -e $osrelease || skip "Not a RHEL system (no $osrelease)"
+
+ local osname=$(source $osrelease; echo $NAME)
+ if [[ $osname =~ Red.Hat || $osname =~ CentOS ]]; then
+ # Version can include minor; strip off first dot an all beyond it
+ local osver=$(source $osrelease; echo $VERSION_ID)
+ test ${osver%%.*} -le 8 || skip "$osname $osver > RHEL8"
+
+ # RHEL or CentOS 8.
+ # FIXME: what does 'CentOS 8' even mean? What is $VERSION_ID in CentOS?
+ run_podman info --format '{{.Host.OCIRuntime.Name}}'
+ is "$output" "runc" "$osname only supports OCI Runtime = runc"
+ else
+ skip "only applicable on RHEL, this is $osname"
+ fi
+}
+
@test "podman info --storage-opt='' " {
skip_if_remote "--storage-opt flag is not supported for remote"
skip_if_rootless "storage opts are required for rootless running"
diff --git a/test/system/037-runlabel.bats b/test/system/037-runlabel.bats
new file mode 100644
index 000000000..8e18f40d3
--- /dev/null
+++ b/test/system/037-runlabel.bats
@@ -0,0 +1,32 @@
+#!/usr/bin/env bats
+
+load helpers
+
+@test "podman container runlabel test" {
+ skip_if_remote "container runlabel is not supported for remote"
+ tmpdir=$PODMAN_TMPDIR/runlabel-test
+ mkdir -p $tmpdir
+ containerfile=$tmpdir/Containerfile
+ rand1=$(random_string 30)
+ rand2=$(random_string 30)
+ rand3=$(random_string 30)
+ cat >$containerfile <<EOF
+FROM $IMAGE
+LABEL INSTALL /usr/bin/podman run -t -i --rm \\\${OPT1} --privileged -v /:/host --net=host --ipc=host --pid=host -e HOST=/host -e NAME=\\\${NAME} -e IMAGE=\\\${IMAGE} -e CONFDIR=/etc/\\\${NAME} -e LOGDIR=/var/log/\\\${NAME} -e DATADIR=/var/lib/\\\${NAME} \\\${IMAGE} \\\${OPT2} /bin/install.sh \\\${OPT3}
+EOF
+
+ run_podman build -t runlabel_image $tmpdir
+
+ run_podman container runlabel --opt1=${rand1} --opt2=${rand2} --opt3=${rand3} --name test1 --display install runlabel_image
+ is "$output" "command: ${PODMAN} run -t -i --rm ${rand1} --privileged -v /:/host --net=host --ipc=host --pid=host -e HOST=/host -e NAME=test1 -e IMAGE=localhost/runlabel_image:latest -e CONFDIR=/etc/test1 -e LOGDIR=/var/log/test1 -e DATADIR=/var/lib/test1 localhost/runlabel_image:latest ${rand2} /bin/install.sh ${rand3}" "generating runlabel install command"
+
+ run_podman container runlabel --opt3=${rand3} --display install runlabel_image
+ is "$output" "command: ${PODMAN} run -t -i --rm --privileged -v /:/host --net=host --ipc=host --pid=host -e HOST=/host -e NAME=runlabel_image -e IMAGE=localhost/runlabel_image:latest -e CONFDIR=/etc/runlabel_image -e LOGDIR=/var/log/runlabel_image -e DATADIR=/var/lib/runlabel_image localhost/runlabel_image:latest /bin/install.sh ${rand3}" "generating runlabel without name and --opt1, --opt2"
+
+ run_podman 125 container runlabel --opt1=${rand1} --opt2=${rand2} --opt3=${rand3} --name test1 --display run runlabel_image
+ is "$output" "Error: cannot find the value of label: run in image: runlabel_image" "generating runlabel run command"
+
+ run_podman rmi -f runlabel_image
+}
+
+# vim: filetype=sh
diff --git a/test/system/050-stop.bats b/test/system/050-stop.bats
index 0652a97e4..a9495e350 100644
--- a/test/system/050-stop.bats
+++ b/test/system/050-stop.bats
@@ -132,6 +132,7 @@ load helpers
is "$output" "stopping" "Status of container should be 'stopping'"
run_podman kill stopme
+ run_podman wait stopme
# Exit code should be 137 as it was killed
run_podman inspect --format '{{.State.ExitCode}}' stopme
diff --git a/test/system/070-build.bats b/test/system/070-build.bats
index 5a887c71e..d4017ae01 100644
--- a/test/system/070-build.bats
+++ b/test/system/070-build.bats
@@ -691,8 +691,16 @@ RUN echo $random_string
EOF
run_podman 125 build -t build_test --pull-never $tmpdir
- is "$output" ".* pull policy is .never. but .* could not be found locally" \
- "--pull-never fails with expected error message"
+ # FIXME: this is just ridiculous. Even after #10030 and #10034, Ubuntu
+ # remote *STILL* flakes this test! It fails with the correct exit status,
+ # but the error output is 'Error: stream dropped, unexpected failure'
+ # Let's just stop checking on podman-remote. As long as it exits 125,
+ # we're happy.
+ if ! is_remote; then
+ is "$output" \
+ ".* pull policy is .never. but .* could not be found locally" \
+ "--pull-never fails with expected error message"
+ fi
}
@test "podman build --logfile test" {
diff --git a/test/system/420-cgroups.bats b/test/system/420-cgroups.bats
index 615e43e6c..89c81a742 100644
--- a/test/system/420-cgroups.bats
+++ b/test/system/420-cgroups.bats
@@ -24,6 +24,11 @@ load helpers
run_podman container inspect --format '{{.HostConfig.CgroupManager}}' myc
is "$output" "$other" "podman preserved .HostConfig.CgroupManager"
+ if is_rootless && test $other = cgroupfs ; then
+ run_podman container inspect --format '{{.HostConfig.CgroupParent}}' myc
+ is "$output" "" "podman didn't set .HostConfig.CgroupParent for cgroupfs and rootless"
+ fi
+
# Restart the container, without --cgroup-manager option (ie use default)
# Prior to #7970, this would fail with an OCI runtime error
run_podman start myc
diff --git a/test/system/500-networking.bats b/test/system/500-networking.bats
index 804dd46b1..cda054b15 100644
--- a/test/system/500-networking.bats
+++ b/test/system/500-networking.bats
@@ -209,4 +209,19 @@ load helpers
run_podman rm -f $cid
}
+@test "podman rootless cni adds /usr/sbin to PATH" {
+ is_rootless || skip "only meaningful for rootless"
+
+ local mynetname=testnet-$(random_string 10)
+ run_podman network create $mynetname
+
+ # Test that rootless cni adds /usr/sbin to $PATH
+ # iptables is located under /usr/sbin and is needed for the CNI plugins.
+ # Debian doesn't add /usr/sbin to $PATH for rootless users so we have to add it.
+ PATH=/usr/local/bin:/usr/bin run_podman run --rm --network $mynetname $IMAGE ip addr
+ is "$output" ".*eth0.*" "Interface eth0 not found in ip addr output"
+
+ run_podman network rm -f $mynetname
+}
+
# vim: filetype=sh
diff --git a/test/system/helpers.bash b/test/system/helpers.bash
index 823dc3376..b9eacfd0b 100644
--- a/test/system/helpers.bash
+++ b/test/system/helpers.bash
@@ -9,6 +9,7 @@ PODMAN_TEST_IMAGE_USER=${PODMAN_TEST_IMAGE_USER:-"libpod"}
PODMAN_TEST_IMAGE_NAME=${PODMAN_TEST_IMAGE_NAME:-"testimage"}
PODMAN_TEST_IMAGE_TAG=${PODMAN_TEST_IMAGE_TAG:-"20210223"}
PODMAN_TEST_IMAGE_FQN="$PODMAN_TEST_IMAGE_REGISTRY/$PODMAN_TEST_IMAGE_USER/$PODMAN_TEST_IMAGE_NAME:$PODMAN_TEST_IMAGE_TAG"
+PODMAN_TEST_IMAGE_ID=
# Remote image that we *DO NOT* fetch or keep by default; used for testing pull
# This changed from 0 to 1 on 2021-02-24 due to multiarch considerations; it
@@ -53,11 +54,21 @@ function basic_setup() {
for line in "${lines[@]}"; do
set $line
if [ "$1" == "$PODMAN_TEST_IMAGE_FQN" ]; then
+ if [[ -z "$PODMAN_TEST_IMAGE_ID" ]]; then
+ # This will probably only trigger the 2nd time through setup
+ PODMAN_TEST_IMAGE_ID=$2
+ fi
found_needed_image=1
else
- echo "# setup(): removing stray images $1 $2" >&3
+ # Always remove image that doesn't match by name
+ echo "# setup(): removing stray image $1" >&3
run_podman rmi --force "$1" >/dev/null 2>&1 || true
- run_podman rmi --force "$2" >/dev/null 2>&1 || true
+
+ # Tagged image will have same IID as our test image; don't rmi it.
+ if [[ $2 != "$PODMAN_TEST_IMAGE_ID" ]]; then
+ echo "# setup(): removing stray image $2" >&3
+ run_podman rmi --force "$2" >/dev/null 2>&1 || true
+ fi
fi
done