summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/apiv2/10-images.at49
-rw-r--r--test/apiv2/20-containers.at26
-rw-r--r--test/apiv2/30-volumes.at20
-rw-r--r--test/apiv2/35-networks.at48
-rw-r--r--test/buildah-bud/README.md82
-rw-r--r--test/buildah-bud/buildah-tests.diff192
-rw-r--r--test/buildah-bud/make-new-buildah-diffs63
-rwxr-xr-xtest/buildah-bud/run-buildah-bud-tests166
-rw-r--r--test/e2e/build_test.go42
-rw-r--r--test/e2e/common_test.go2
-rw-r--r--test/e2e/generate_kube_test.go70
-rw-r--r--test/e2e/play_kube_test.go129
-rw-r--r--test/e2e/run_test.go47
-rw-r--r--test/e2e/run_volume_test.go26
-rw-r--r--test/python/docker/compat/test_images.py17
-rw-r--r--test/system/120-load.bats14
-rw-r--r--test/system/200-pod.bats16
-rw-r--r--test/system/220-healthcheck.bats2
-rw-r--r--test/system/410-selinux.bats3
-rw-r--r--test/system/450-interactive.bats90
-rw-r--r--test/system/500-networking.bats1
21 files changed, 1010 insertions, 95 deletions
diff --git a/test/apiv2/10-images.at b/test/apiv2/10-images.at
index 4ebaeff45..f854d38ab 100644
--- a/test/apiv2/10-images.at
+++ b/test/apiv2/10-images.at
@@ -77,6 +77,55 @@ for i in $iid ${iid:0:12} $PODMAN_TEST_IMAGE_NAME; do
t GET "libpod/images/$i/get?compress=false" 200 '[POSIX tar archive]'
done
+#compat api list images sanity checks
+t GET images/json?filters='garb1age}' 500 \
+ .cause="invalid character 'g' looking for beginning of value"
+t GET images/json?filters='{"label":["testl' 500 \
+ .cause="unexpected end of JSON input"
+
+#libpod api list images sanity checks
+t GET libpod/images/json?filters='garb1age}' 500 \
+ .cause="invalid character 'g' looking for beginning of value"
+t GET libpod/images/json?filters='{"label":["testl' 500 \
+ .cause="unexpected end of JSON input"
+
+# Prune images - bad filter input
+t POST images/prune?filters='garb1age}' 500 \
+ .cause="invalid character 'g' looking for beginning of value"
+t POST libpod/images/prune?filters='garb1age}' 500 \
+ .cause="invalid character 'g' looking for beginning of value"
+
+## Prune images with illformed label
+t POST images/prune?filters='{"label":["tes' 500 \
+ .cause="unexpected end of JSON input"
+t POST libpod/images/prune?filters='{"label":["tes' 500 \
+ .cause="unexpected end of JSON input"
+
+
+#create, list and remove dangling image
+podman image build -t test:test -<<EOF
+from alpine
+RUN >file1
+EOF
+
+podman image build -t test:test --label xyz -<<EOF
+from alpine
+RUN >file2
+EOF
+
+t GET images/json?filters='{"dangling":["true"]}' 200 length=1
+t POST images/prune?filters='{"dangling":["true"]}' 200
+t GET images/json?filters='{"dangling":["true"]}' 200 length=0
+
+#label filter check in libpod and compat
+t GET images/json?filters='{"label":["xyz"]}' 200 length=1
+t GET libpod/images/json?filters='{"label":["xyz"]}' 200 length=1
+
+t DELETE libpod/images/test:test 200
+
+t GET images/json?filters='{"label":["xyz"]}' 200 length=0
+t GET libpod/images/json?filters='{"label":["xyz"]}' 200 length=0
+
# Export more than one image
# FIXME FIXME FIXME, this doesn't work:
# not ok 64 [10-images] GET images/get?names=alpine,busybox : status
diff --git a/test/apiv2/20-containers.at b/test/apiv2/20-containers.at
index 478717700..9030f0095 100644
--- a/test/apiv2/20-containers.at
+++ b/test/apiv2/20-containers.at
@@ -280,6 +280,32 @@ t GET containers/json 200 \
podman stop bar
+#compat api list containers sanity checks
+t GET containers/json?filters='garb1age}' 500 \
+ .cause="invalid character 'g' looking for beginning of value"
+t GET containers/json?filters='{"label":["testl' 500 \
+ .cause="unexpected end of JSON input"
+
+#libpod api list containers sanity checks
+t GET libpod/containers/json?filters='garb1age}' 500 \
+ .cause="invalid character 'g' looking for beginning of value"
+t GET libpod/containers/json?filters='{"label":["testl' 500 \
+ .cause="unexpected end of JSON input"
+
+# Prune containers - bad filter input
+t POST containers/prune?filters='garb1age}' 500 \
+ .cause="invalid character 'g' looking for beginning of value"
+t POST libpod/containers/prune?filters='garb1age}' 500 \
+ .cause="invalid character 'g' looking for beginning of value"
+
+## Prune containers with illformed label
+t POST containers/prune?filters='{"label":["tes' 500 \
+ .cause="unexpected end of JSON input"
+t POST libpod/containers/prune?filters='{"label":["tes' 500 \
+ .cause="unexpected end of JSON input"
+
+t GET libpod/containers/json?filters='{"label":["testlabel"]}' 200 length=0
+
# Test CPU limit (NanoCPUs)
t POST containers/create Image=$IMAGE HostConfig='{"NanoCpus":500000}' 201 \
.Id~[0-9a-f]\\{64\\}
diff --git a/test/apiv2/30-volumes.at b/test/apiv2/30-volumes.at
index 1a40b3cdf..18ff31100 100644
--- a/test/apiv2/30-volumes.at
+++ b/test/apiv2/30-volumes.at
@@ -86,14 +86,34 @@ t DELETE libpod/volumes/foo1 404 \
.message~.* \
.response=404
+#compat api list volumes sanity checks
+t GET volumes?filters='garb1age}' 500 \
+ .cause="invalid character 'g' looking for beginning of value"
+t GET volumes?filters='{"label":["testl' 500 \
+ .cause="unexpected end of JSON input"
+
+#libpod api list volumes sanity checks
+t GET libpod/volumes/json?filters='garb1age}' 500 \
+ .cause="invalid character 'g' looking for beginning of value"
+t GET libpod/volumes/json?filters='{"label":["testl' 500 \
+ .cause="unexpected end of JSON input"
+
# Prune volumes - bad filter input
t POST volumes/prune?filters='garb1age}' 500 \
.cause="invalid character 'g' looking for beginning of value"
+t POST libpod/volumes/prune?filters='garb1age}' 500 \
+ .cause="invalid character 'g' looking for beginning of value"
## Prune volumes with label matching 'testlabel1=testonly'
t POST libpod/volumes/prune?filters='{"label":["testlabel1=testonly"]}' 200
t GET libpod/volumes/json?filters='{"label":["testlabel1=testonly"]}' 200 length=0
+## Prune volumes with label illformed label
+t POST volumes/prune?filters='{"label":["tes' 500 \
+ .cause="unexpected end of JSON input"
+t POST libpod/volumes/prune?filters='{"label":["tes' 500 \
+ .cause="unexpected end of JSON input"
+
## Prune volumes with label matching 'testlabel'
t POST libpod/volumes/prune?filters='{"label":["testlabel"]}' 200
t GET libpod/volumes/json?filters='{"label":["testlabel"]}' 200 length=0
diff --git a/test/apiv2/35-networks.at b/test/apiv2/35-networks.at
index ce7ca628a..21840a42d 100644
--- a/test/apiv2/35-networks.at
+++ b/test/apiv2/35-networks.at
@@ -16,6 +16,20 @@ t POST libpod/networks/create?name=network2 \
200 \
.Filename~.*/network2\\.conflist
+# --data '{"Subnet":{"IP":"10.10.133.0","Mask":[255,255,255,0]},"Labels":{"xyz":"val"}}'
+t POST libpod/networks/create?name=network3 \
+ Subnet='{"IP":"10.10.133.0","Mask":[255,255,255,0]}' \
+ Labels='{"xyz":"val"}' \
+ 200 \
+ .Filename~.*/network3\\.conflist
+
+# --data '{"Subnet":{"IP":"10.10.134.0","Mask":[255,255,255,0]},"Labels":{"zaq":"val"}}'
+t POST libpod/networks/create?name=network4 \
+ Subnet='{"IP":"10.10.134.0","Mask":[255,255,255,0]}' \
+ Labels='{"zaq":"val"}' \
+ 200 \
+ .Filename~.*/network4\\.conflist
+
# test for empty mask
t POST libpod/networks/create Subnet='{"IP":"10.10.1.0","Mask":[]}' 500 \
.cause~'.*cannot be empty'
@@ -38,7 +52,7 @@ t GET libpod/networks/network1/json 200 \
t GET networks?filters='{"name":["network1","network2"]}' 200 \
length=2
t GET networks?filters='{"name":["network"]}' 200 \
- length=2
+ length=4
t GET networks?filters='{"label":["abc"]}' 200 \
length=1
# old docker filter type see #9526
@@ -66,6 +80,38 @@ t POST networks/create Name=net3\ IPAM='{"Config":[]}' 201
# network delete docker
t DELETE networks/net3 204
+#compat api list networks sanity checks
+t GET networks?filters='garb1age}' 500 \
+ .cause="invalid character 'g' looking for beginning of value"
+t GET networks?filters='{"label":["testl' 500 \
+ .cause="unexpected end of JSON input"
+
+#libpod api list networks sanity checks
+t GET libpod/networks/json?filters='garb1age}' 500 \
+ .cause="invalid character 'g' looking for beginning of value"
+t GET libpod/networks/json?filters='{"label":["testl' 500 \
+ .cause="unexpected end of JSON input"
+
+# Prune networks compat api
+t POST networks/prune?filters='garb1age}' 500 \
+ .cause="invalid character 'g' looking for beginning of value"
+t POST networks/prune?filters='{"label":["tes' 500 \
+ .cause="unexpected end of JSON input"
+
+# Prune networks libpod api
+t POST libpod/networks/prune?filters='garb1age}' 500 \
+ .cause="invalid character 'g' looking for beginning of value"
+t POST libpod/networks/prune?filters='{"label":["tes' 500 \
+ .cause="unexpected end of JSON input"
+
+# prune networks using filter - compat api
+t POST networks/prune?filters='{"label":["xyz"]}' 200
+t GET networks/json?filters='{"label":["xyz"]}' 404
+
+# prune networks using filter - libpod api
+t POST libpod/networks/prune?filters='{"label":["zaq=val"]}' 200
+t GET libpod/networks/json?filters='{"label":["zaq=val"]}' 200 length=0
+
# clean the network
t DELETE libpod/networks/network1 200 \
.[0].Name~network1 \
diff --git a/test/buildah-bud/README.md b/test/buildah-bud/README.md
new file mode 100644
index 000000000..88e4bbc3c
--- /dev/null
+++ b/test/buildah-bud/README.md
@@ -0,0 +1,82 @@
+buildah-bud tests under podman
+==============================
+
+This directory contains tools for running 'buildah bud' tests
+under podman. The key concept of the workflow is:
+
+* Pull buildah @ version specified in go.mod
+* Apply a small set of patches to buildah's tests directory, such that
+ * BATS will use 'podman build' instead of 'buildah bud'; and
+ * some not-applicable-under-podman tests are skipped
+
+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
+---------------
+
+If you're reading this, it's probably because something went wrong.
+At the time of this writing (March 2021, initial commit) it is
+impossible to foresee what typical failures will look like, but
+my prediction is that they will fit one of two categories:
+
+* Failure when vendoring new buildah (e.g., by dependabot)
+* Other failure
+
+Let's examine those in reverse order:
+
+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
+did; and if this is the case, your change likely falls into one of
+these two categories:
+
+* "OOPS! I didn't mean to break that". Solution: fix it!
+* "Uh, yeah, this is deliberate, and we choose to be incompatible with buildah". In this case, you'll need to skip or edit the failing test(s); see below.
+
+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
+----------------------------------
+
+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 because there are new buildah tests for functionality not in podman
+
+In either case, the process for solving is the same:
+
+* Start with a checked-out podman tree with the failing PR applied
+* run `./test/buildah-bud/run-buildah-bud-tests`
+
+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).
+
+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).
+
+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!
+
+Commit your changes: `git commit --all --amend`
+
+Push those changes to the podman repo: `./make-new-buildah-diffs`
+
+cd back up to the podman repo
+
+As necessary, rerun `run-buildah-bud-tests`. You can use `--no-checkout`
+to run tests immediately, without rerunning the git checkout.
+
+If you're happy with the diffs, `git add` the modified `.diff` file
+and submit it as part of your PR.
diff --git a/test/buildah-bud/buildah-tests.diff b/test/buildah-bud/buildah-tests.diff
new file mode 100644
index 000000000..92adabcac
--- /dev/null
+++ b/test/buildah-bud/buildah-tests.diff
@@ -0,0 +1,192 @@
+From c85882a8f7fb6efbf4d59dfe8340bfbef57ccd48 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(-)
+
+diff --git a/tests/bud.bats b/tests/bud.bats
+index 1efc3c58..9a39d594 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" {
+@@ -95,6 +95,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"
+
+@@ -1324,13 +1325,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" {
+@@ -1742,7 +1743,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
+@@ -1795,6 +1798,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
+ }
+@@ -1802,7 +1806,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" {
+@@ -1815,16 +1819,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
+@@ -1876,7 +1881,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" {
+@@ -2023,6 +2028,7 @@ _EOF
+ }
+
+ @test "bud pull never" {
++ skip "FIXME: podman issue #9573"
+ target=pull
+ run_buildah 125 bud --signature-policy ${TESTSDIR}/policy.json -t ${target} --pull-never ${TESTSDIR}/bud/pull
+ expect_output --substring "pull policy is \"never\" but \""
+@@ -2042,6 +2048,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
+ }
+@@ -2169,6 +2176,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
+@@ -2241,8 +2249,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
+diff --git a/tests/helpers.bash b/tests/helpers.bash
+index 5623a0e7..9683360f 100644
+--- a/tests/helpers.bash
++++ b/tests/helpers.bash
+@@ -70,7 +70,7 @@ function _prefetch() {
+ 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}"
+
+ for img in "$@"; do
+ echo "# [checking for: $img]" >&2
+@@ -138,15 +138,35 @@ function run_buildah() {
+ --retry) retry=3; shift;; # retry network flakes
+ esac
+
++ local podman_or_buildah=${BUILDAH_BINARY}
++ if [[ $1 == "bud" || $1 == "build-using-dockerfile" ]]; then
++ shift
++ # podman defaults to --layers=true; buildah to --false.
++ # If command line includes explicit --layers, leave it untouched,
++ # but otherwise update command line so podman mimics buildah default.
++ if [[ "$*" =~ --layers || "$*" =~ --squash ]]; then
++ set "build" "--force-rm=false" "$@"
++ else
++ set "build" "--force-rm=false" "--layers=false" "$@"
++ fi
++ podman_or_buildah=${PODMAN_BINARY}
++
++ # podman always exits 125 where buildah exits 1 or 2
++ case $expected_rc in
++ 1|2) expected_rc=125 ;;
++ esac
++ fi
++ local cmd_basename=$(basename ${podman_or_buildah})
++
+ # Remember command args, for possible use in later diagnostic messages
+- MOST_RECENT_BUILDAH_COMMAND="buildah $*"
++ MOST_RECENT_BUILDAH_COMMAND="$cmd_basename $*"
+
+ while [ $retry -gt 0 ]; do
+ retry=$(( retry - 1 ))
+
+ # stdout is only emitted upon error; this echo is to help a debugger
+- echo "\$ $BUILDAH_BINARY $*"
+- run timeout --foreground --kill=10 $BUILDAH_TIMEOUT ${BUILDAH_BINARY} --registries-conf ${TESTSDIR}/registries.conf --root ${TESTDIR}/root --runroot ${TESTDIR}/runroot --storage-driver ${STORAGE_DRIVER} "$@"
++ echo "\$ $cmd_basename $*"
++ run timeout --foreground --kill=10 $BUILDAH_TIMEOUT ${podman_or_buildah} --registries-conf ${TESTSDIR}/registries.conf --root ${TESTDIR}/root --runroot ${TESTDIR}/runroot --storage-driver ${STORAGE_DRIVER} "$@"
+ # without "quotes", multiple lines are glommed together into one
+ if [ -n "$output" ]; then
+ echo "$output"
+--
+2.30.2
diff --git a/test/buildah-bud/make-new-buildah-diffs b/test/buildah-bud/make-new-buildah-diffs
new file mode 100644
index 000000000..1191f4597
--- /dev/null
+++ b/test/buildah-bud/make-new-buildah-diffs
@@ -0,0 +1,63 @@
+#!/bin/bash
+#
+# This script is intended to help developers get buildah-tests-under-podman
+# working again in case of failure.
+#
+ME=$(basename $0)
+
+die() {
+ echo "$ME: $*" >&2
+ exit 1
+}
+
+# Confirm that we're in a test-buildah* subdir of podman
+whereami=$(basename $(pwd))
+if [[ ! $whereami =~ test-buildah-v ]]; then
+ die "Please run me while cd'ed to a test-buildah-vN.M directory"
+fi
+
+# FIXME: check that git repo is buildah
+git remote -v | grep -q [BUILDAHREPO] \
+ || die "This does not look like a buildah repo (git remote -v)"
+
+# We could do the commit automatically, but it's prudent to require human
+# involvement.
+modified=$(git status --untracked=no --porcelain)
+if [[ -n "$modified" ]]; then
+ echo $modified
+ die "Please commit your changes: git commit --amend --all"
+fi
+
+# Remove any 00??-*.patch files
+rm -f 0001-*.patch
+
+# Check count of commits, barf if need to squash
+n_commits=$(git log --pretty=format:%h [BASETAG]..HEAD | wc -l)
+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/')
+if [[ -n "$changes" ]]; then
+ echo $changes
+ die "Found modified files other than under 'tests/'"
+fi
+
+###############################################################################
+# All right - things look good. Generate the patch, and copy it into place.
+
+git format-patch [BASETAG]
+
+# Once again, make sure there's exactly one and only one commit
+shopt -s nullglob
+patch2=$(echo 0002-*.patch)
+if [[ -n "$patch2" ]]; then
+ die "Internal error: I thought I checked for squashed commits, but still see $patch2"
+fi
+
+# All looks good. Now write that patch into its proper place in the
+# podman repo. The sed and tac mess strips trailing whitespace and
+# empty lines; we need to do this to pass github CI checks.
+sed -e 's/ \+$//' <0001-*.patch |\
+ tac | sed -e '/./,$!d' | tac >| ../test/buildah-bud/buildah-tests.diff
diff --git a/test/buildah-bud/run-buildah-bud-tests b/test/buildah-bud/run-buildah-bud-tests
new file mode 100755
index 000000000..67c8fdfa4
--- /dev/null
+++ b/test/buildah-bud/run-buildah-bud-tests
@@ -0,0 +1,166 @@
+#!/bin/bash
+
+ME=$(basename $0)
+
+###############################################################################
+# BEGIN user-customizable section
+
+# Buildah main repository; unlikely to change often
+BUILDAH_REPO=github.com/containers/buildah
+
+# Tag name used to identify the base checkout
+BASE_TAG=buildah-bud-in-podman
+
+# END user-customizable section
+###############################################################################
+
+usage="Usage: $ME [--help] [--no-checkout] [--no-test]
+"
+
+# Parse command-line options (used in development only, not in CI)
+do_checkout=y
+do_test=y
+for i; do
+ case "$i" in
+ --no-checkout) do_checkout= ; shift;;
+ --no-test) do_test= ; shift;;
+ -h|--help) echo "$usage"; exit 0;;
+ *) echo "$ME: Unrecognized option '$i'" >&2; exit 1;;
+ esac
+done
+
+# Patches helpers.bash and potentially other files (bud.bats? Dockerfiles?)
+#
+# The patch file is horrible to generate:
+# 1) cd to the checked-out buildah/tests directory
+# 2) make your edits
+# 3) git commit -asm 'blah blah blah'
+# 3a) if checked-out directory already includes earlier patches,
+# you may need to 'git commit --amend' instead
+# 4) git format-patch HEAD^
+# 5) sed -e 's/ \+$//' 0001* >../PATCH-FILE-PATH
+# 6) vim that file, remove trailing empty newlines
+# 7) cd back out of buildah directory, and git-commit this new patch file
+#
+# FIXME: this makes me nervous. The diff will probably need tweaking
+# over time. I don't think we need to version it, because we
+# *have* to be in lockstep with a specific buildah version,
+# so problems should only arise when we re-vendor.
+# But I'm still nervous and can't put my finger on the reason.
+#
+# Complicated invocation needed because we 'cd' down below.
+BUD_TEST_DIR=$(realpath $(dirname ${BASH_SOURCE[0]}))
+PATCHES=${BUD_TEST_DIR}/buildah-tests.diff
+
+# Friendlier relative path to our buildah-tests dir
+BUD_TEST_DIR_REL=$(dirname $(git ls-files --full-name ${BASH_SOURCE[0]}))
+# Path to podman binary; again, do it before we cd
+PODMAN_BINARY=$(pwd)/bin/podman
+REMOTE=
+# If remote, start server & change path
+if [[ "${PODBIN_NAME:-}" = "remote" ]]; then
+ REMOTE=1
+ echo "$ME: remote tests are not working yet" >&2
+ exit 1
+fi
+
+function die() {
+ failhint=
+ echo "$ME: $*" >&2
+ exit 1
+}
+
+# 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
+
+# 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)
+
+if [[ -z "$buildah_version" ]]; then
+ # This should not happen
+ die "Did not find '$BUILDAH_REPO' in go.mod"
+fi
+
+# From here on out, any error is fatal
+set -e
+
+# Before pulling buildah (while still cd'ed to podman repo), try to determine
+# if this is a PR, and if so if it's a revendoring of buildah. We use this to
+# try to offer a helpful hint on failure.
+is_revendor=
+if [[ -n $CIRRUS_CHANGE_IN_REPO ]]; then
+ if [[ -n $DEST_BRANCH ]]; then
+ head=${CIRRUS_CHANGE_IN_REPO}
+ # Base of this PR.
+ base=$(set -x;git merge-base ${DEST_BRANCH} $head)
+ changes=$(set -x;git diff --name-status $base $head)
+ if [[ -n $changes ]]; then
+ if [[ $changes =~ vendor/$BUILDAH_REPO ]]; then
+ is_revendor=y
+ fi
+ fi
+ fi
+fi
+
+# Pull buildah, including tests
+buildah_dir=test-buildah-$buildah_version
+if [[ -n $do_checkout ]]; then
+ if [[ -d $buildah_dir ]]; then
+ die "Directory already exists: $buildah_dir"
+ fi
+
+ failhint="'git clone' failed - this should never happen!"
+ (set -x;git clone -q --branch $buildah_version https://$BUILDAH_REPO $buildah_dir)
+
+ cd $buildah_dir
+
+ # Give it a recognizable tag; this will be useful if we need to update
+ # the set of patches
+ (set -x;git tag $BASE_TAG)
+
+ # Build buildah
+ 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)
+
+ 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
+else
+ # Called with --no-checkout
+ test -d $buildah_dir || die "Called with --no-checkout, but $buildah_dir does not exist"
+
+ cd $buildah_dir
+fi
+
+if [[ -n $do_test ]]; then
+ failhint="Error running buildah bud tests under podman."
+ if [[ -n $is_revendor ]]; then
+ failhint+="
+
+It looks like you're vendoring in a new buildah. The likely failure
+here is that there's a new test in bud.bats that uses functionality
+not (yet) in podman build. You will likely need to 'skip' that test.
+"
+ else
+ failhint+="
+
+Is it possible that your PR breaks podman build in some way? Please
+review the test failure and double-check your changes.
+"
+ fi
+
+ (set -x;sudo env TMPDIR=/var/tmp \
+ PODMAN_BINARY=$PODMAN_BINARY \
+ BUILDAH_BINARY=$(pwd)/bin/buildah \
+ bats tests/bud.bats)
+fi
diff --git a/test/e2e/build_test.go b/test/e2e/build_test.go
index 4839d66ec..e061a2154 100644
--- a/test/e2e/build_test.go
+++ b/test/e2e/build_test.go
@@ -39,7 +39,7 @@ var _ = Describe("Podman build", func() {
// happy and then clean up after ourselves to make sure that works too.
It("podman build and remove basic alpine", func() {
podmanTest.AddImageToRWStore(ALPINE)
- session := podmanTest.Podman([]string{"build", "build/basicalpine"})
+ session := podmanTest.Podman([]string{"build", "--pull-never", "build/basicalpine"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
@@ -59,7 +59,7 @@ var _ = Describe("Podman build", func() {
It("podman build with logfile", func() {
logfile := filepath.Join(podmanTest.TempDir, "logfile")
- session := podmanTest.Podman([]string{"build", "--tag", "test", "--logfile", logfile, "build/basicalpine"})
+ session := podmanTest.Podman([]string{"build", "--pull-never", "--tag", "test", "--logfile", logfile, "build/basicalpine"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
@@ -82,7 +82,7 @@ var _ = Describe("Podman build", func() {
// If the context directory is pointing at a file and not a directory,
// that's a no no, fail out.
It("podman build context directory a file", func() {
- session := podmanTest.Podman([]string{"build", "build/context_dir_a_file"})
+ session := podmanTest.Podman([]string{"build", "--pull-never", "build/context_dir_a_file"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(125))
})
@@ -90,7 +90,7 @@ var _ = Describe("Podman build", func() {
// Check that builds with different values for the squash options
// create the appropriate number of layers, then clean up after.
It("podman build basic alpine with squash", func() {
- session := podmanTest.Podman([]string{"build", "-f", "build/squash/Dockerfile.squash-a", "-t", "test-squash-a:latest", "build/squash"})
+ session := podmanTest.Podman([]string{"build", "--pull-never", "-f", "build/squash/Dockerfile.squash-a", "-t", "test-squash-a:latest", "build/squash"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
@@ -100,7 +100,7 @@ var _ = Describe("Podman build", func() {
// Check for two layers
Expect(len(strings.Fields(session.OutputToString()))).To(Equal(2))
- session = podmanTest.Podman([]string{"build", "-f", "build/squash/Dockerfile.squash-b", "--squash", "-t", "test-squash-b:latest", "build/squash"})
+ session = podmanTest.Podman([]string{"build", "--pull-never", "-f", "build/squash/Dockerfile.squash-b", "--squash", "-t", "test-squash-b:latest", "build/squash"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
@@ -110,7 +110,7 @@ var _ = Describe("Podman build", func() {
// Check for three layers
Expect(len(strings.Fields(session.OutputToString()))).To(Equal(3))
- session = podmanTest.Podman([]string{"build", "-f", "build/squash/Dockerfile.squash-c", "--squash", "-t", "test-squash-c:latest", "build/squash"})
+ session = podmanTest.Podman([]string{"build", "--pull-never", "-f", "build/squash/Dockerfile.squash-c", "--squash", "-t", "test-squash-c:latest", "build/squash"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
@@ -120,7 +120,7 @@ var _ = Describe("Podman build", func() {
// Check for two layers
Expect(len(strings.Fields(session.OutputToString()))).To(Equal(2))
- session = podmanTest.Podman([]string{"build", "-f", "build/squash/Dockerfile.squash-c", "--squash-all", "-t", "test-squash-d:latest", "build/squash"})
+ session = podmanTest.Podman([]string{"build", "--pull-never", "-f", "build/squash/Dockerfile.squash-c", "--squash-all", "-t", "test-squash-d:latest", "build/squash"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
@@ -162,7 +162,7 @@ var _ = Describe("Podman build", func() {
// When
session := podmanTest.Podman([]string{
- "build", "-f", targetFile, "-t", "test-locations",
+ "build", "--pull-never", "-f", targetFile, "-t", "test-locations",
})
session.WaitWithDefaultTimeout()
@@ -185,7 +185,7 @@ var _ = Describe("Podman build", func() {
}
targetFile := filepath.Join(targetPath, "idFile")
- session := podmanTest.Podman([]string{"build", "build/basicalpine", "--iidfile", targetFile})
+ session := podmanTest.Podman([]string{"build", "--pull-never", "build/basicalpine", "--iidfile", targetFile})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
id, _ := ioutil.ReadFile(targetFile)
@@ -200,7 +200,7 @@ var _ = Describe("Podman build", func() {
It("podman Test PATH in built image", func() {
path := "/tmp:/bin:/usr/bin:/usr/sbin"
session := podmanTest.Podman([]string{
- "build", "-f", "build/basicalpine/Containerfile.path", "-t", "test-path",
+ "build", "--pull-never", "-f", "build/basicalpine/Containerfile.path", "-t", "test-path",
})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
@@ -225,7 +225,7 @@ RUN printenv http_proxy`
dockerfilePath := filepath.Join(podmanTest.TempDir, "Dockerfile")
err := ioutil.WriteFile(dockerfilePath, []byte(dockerfile), 0755)
Expect(err).To(BeNil())
- session := podmanTest.Podman([]string{"build", "--http-proxy", "--file", dockerfilePath, podmanTest.TempDir})
+ session := podmanTest.Podman([]string{"build", "--pull-never", "--http-proxy", "--file", dockerfilePath, podmanTest.TempDir})
session.Wait(120)
Expect(session.ExitCode()).To(Equal(0))
ok, _ := session.GrepString("1.2.3.4")
@@ -234,7 +234,7 @@ RUN printenv http_proxy`
})
It("podman build and check identity", func() {
- session := podmanTest.Podman([]string{"build", "-f", "build/basicalpine/Containerfile.path", "--no-cache", "-t", "test", "build/basicalpine"})
+ session := podmanTest.Podman([]string{"build", "--pull-never", "-f", "build/basicalpine/Containerfile.path", "--no-cache", "-t", "test", "build/basicalpine"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
@@ -279,7 +279,7 @@ RUN find /test`
// make cwd as context root path
Expect(os.Chdir(targetPath)).To(BeNil())
- session := podmanTest.Podman([]string{"build", "-t", "test", "-f", "Containerfile", targetSubPath})
+ session := podmanTest.Podman([]string{"build", "--pull-never", "-t", "test", "-f", "Containerfile", targetSubPath})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
ok, _ := session.GrepString("/test/dummy")
@@ -321,7 +321,7 @@ RUN find /test`
// make cwd as context root path
Expect(os.Chdir(targetPath)).To(BeNil())
- session := podmanTest.Podman([]string{"build", "-t", "test", "-f", "subdir/Containerfile", "."})
+ session := podmanTest.Podman([]string{"build", "--pull-never", "-t", "test", "-f", "subdir/Containerfile", "."})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
})
@@ -445,7 +445,7 @@ RUN [[ -L /test/dummy-symlink ]] && echo SYMLNKOK || echo SYMLNKERR`
// make cwd as context root path
Expect(os.Chdir(targetPath)).To(BeNil())
- session := podmanTest.Podman([]string{"build", "-t", "test", targetSubPath})
+ session := podmanTest.Podman([]string{"build", "--pull-never", "-t", "test", targetSubPath})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
ok, _ := session.GrepString("/test/dummy")
@@ -475,7 +475,7 @@ RUN grep CapEff /proc/self/status`
// When
session := podmanTest.Podman([]string{
- "build", "--cap-drop=all", "--cap-add=net_bind_service", "--add-host", "testhost:1.2.3.4", "--from", "alpine", targetPath,
+ "build", "--pull-never", "--cap-drop=all", "--cap-add=net_bind_service", "--add-host", "testhost:1.2.3.4", "--from", "alpine", targetPath,
})
session.WaitWithDefaultTimeout()
@@ -502,7 +502,7 @@ RUN grep CapEff /proc/self/status`
// When
session := podmanTest.Podman([]string{
- "build", "--isolation", "oci", "--arch", "arm64", targetPath,
+ "build", "--pull-never", "--isolation", "oci", "--arch", "arm64", targetPath,
})
session.WaitWithDefaultTimeout()
// Then
@@ -510,7 +510,7 @@ RUN grep CapEff /proc/self/status`
// When
session = podmanTest.Podman([]string{
- "build", "--isolation", "chroot", "--arch", "arm64", targetPath,
+ "build", "--pull-never", "--isolation", "chroot", "--arch", "arm64", targetPath,
})
session.WaitWithDefaultTimeout()
// Then
@@ -518,7 +518,7 @@ RUN grep CapEff /proc/self/status`
// When
session = podmanTest.Podman([]string{
- "build", "--isolation", "rootless", "--arch", "arm64", targetPath,
+ "build", "--pull-never", "--isolation", "rootless", "--arch", "arm64", targetPath,
})
session.WaitWithDefaultTimeout()
// Then
@@ -526,7 +526,7 @@ RUN grep CapEff /proc/self/status`
// When
session = podmanTest.Podman([]string{
- "build", "--isolation", "bogus", "--arch", "arm64", targetPath,
+ "build", "--pull-never", "--isolation", "bogus", "--arch", "arm64", targetPath,
})
session.WaitWithDefaultTimeout()
// Then
@@ -540,7 +540,7 @@ RUN echo hello`
containerfilePath := filepath.Join(podmanTest.TempDir, "Containerfile")
err := ioutil.WriteFile(containerfilePath, []byte(containerfile), 0755)
Expect(err).To(BeNil())
- session := podmanTest.Podman([]string{"build", "-t", "test", "--timestamp", "0", "--file", containerfilePath, podmanTest.TempDir})
+ session := podmanTest.Podman([]string{"build", "--pull-never", "-t", "test", "--timestamp", "0", "--file", containerfilePath, podmanTest.TempDir})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go
index 70ffdebea..9ae56d7ce 100644
--- a/test/e2e/common_test.go
+++ b/test/e2e/common_test.go
@@ -440,7 +440,7 @@ func (p *PodmanTestIntegration) BuildImage(dockerfile, imageName string, layers
dockerfilePath := filepath.Join(p.TempDir, "Dockerfile")
err := ioutil.WriteFile(dockerfilePath, []byte(dockerfile), 0755)
Expect(err).To(BeNil())
- cmd := []string{"build", "--layers=" + layers, "--file", dockerfilePath}
+ cmd := []string{"build", "--pull-never", "--layers=" + layers, "--file", dockerfilePath}
if len(imageName) > 0 {
cmd = append(cmd, []string{"-t", imageName}...)
}
diff --git a/test/e2e/generate_kube_test.go b/test/e2e/generate_kube_test.go
index 21e006c20..1c53307bd 100644
--- a/test/e2e/generate_kube_test.go
+++ b/test/e2e/generate_kube_test.go
@@ -155,6 +155,23 @@ var _ = Describe("Podman generate kube", func() {
Expect(numContainers).To(Equal(1))
})
+ It("podman generate kube multiple pods", func() {
+ pod1 := podmanTest.Podman([]string{"run", "-dt", "--pod", "new:pod1", ALPINE, "top"})
+ pod1.WaitWithDefaultTimeout()
+ Expect(pod1.ExitCode()).To(Equal(0))
+
+ pod2 := podmanTest.Podman([]string{"run", "-dt", "--pod", "new:pod2", ALPINE, "top"})
+ pod2.WaitWithDefaultTimeout()
+ Expect(pod2.ExitCode()).To(Equal(0))
+
+ kube := podmanTest.Podman([]string{"generate", "kube", "pod1", "pod2"})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube.ExitCode()).To(Equal(0))
+
+ Expect(string(kube.Out.Contents())).To(ContainSubstring(`name: pod1`))
+ Expect(string(kube.Out.Contents())).To(ContainSubstring(`name: pod2`))
+ })
+
It("podman generate kube on pod with host network", func() {
podSession := podmanTest.Podman([]string{"pod", "create", "--name", "testHostNetwork", "--network", "host"})
podSession.WaitWithDefaultTimeout()
@@ -478,6 +495,36 @@ var _ = Describe("Podman generate kube", func() {
Expect(inspect.OutputToString()).To(ContainSubstring(vol1))
})
+ It("podman generate kube with persistent volume claim", func() {
+ vol := "vol-test-persistent-volume-claim"
+
+ // we need a container name because IDs don't persist after rm/play
+ ctrName := "test-persistent-volume-claim"
+ ctrNameInKubePod := "test1-test-persistent-volume-claim"
+
+ session := podmanTest.Podman([]string{"run", "-d", "--pod", "new:test1", "--name", ctrName, "-v", vol + ":/volume/:z", "alpine", "top"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Equal(0))
+
+ outputFile := filepath.Join(podmanTest.RunRoot, "pod.yaml")
+ kube := podmanTest.Podman([]string{"generate", "kube", "test1", "-f", outputFile})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube.ExitCode()).To(Equal(0))
+
+ rm := podmanTest.Podman([]string{"pod", "rm", "-f", "test1"})
+ rm.WaitWithDefaultTimeout()
+ Expect(rm.ExitCode()).To(Equal(0))
+
+ play := podmanTest.Podman([]string{"play", "kube", outputFile})
+ play.WaitWithDefaultTimeout()
+ Expect(play.ExitCode()).To(Equal(0))
+
+ inspect := podmanTest.Podman([]string{"inspect", ctrNameInKubePod})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect.ExitCode()).To(Equal(0))
+ Expect(inspect.OutputToString()).To(ContainSubstring(vol))
+ })
+
It("podman generate kube sharing pid namespace", func() {
podName := "test"
podSession := podmanTest.Podman([]string{"pod", "create", "--name", podName, "--share", "pid"})
@@ -507,21 +554,6 @@ var _ = Describe("Podman generate kube", func() {
Expect(inspect.OutputToString()).To(ContainSubstring(`"pid"`))
})
- It("podman generate kube multiple pods should fail", func() {
- SkipIfRootlessCgroupsV1("Not supported for rootless + CGroupsV1")
- pod1 := podmanTest.Podman([]string{"run", "-dt", "--pod", "new:pod1", ALPINE, "top"})
- pod1.WaitWithDefaultTimeout()
- Expect(pod1.ExitCode()).To(Equal(0))
-
- pod2 := podmanTest.Podman([]string{"run", "-dt", "--pod", "new:pod2", ALPINE, "top"})
- pod2.WaitWithDefaultTimeout()
- Expect(pod2.ExitCode()).To(Equal(0))
-
- kube := podmanTest.Podman([]string{"generate", "kube", "pod1", "pod2"})
- kube.WaitWithDefaultTimeout()
- Expect(kube.ExitCode()).ToNot(Equal(0))
- })
-
It("podman generate kube with pods and containers should fail", func() {
pod1 := podmanTest.Podman([]string{"run", "-dt", "--pod", "new:pod1", ALPINE, "top"})
pod1.WaitWithDefaultTimeout()
@@ -564,7 +596,7 @@ var _ = Describe("Podman generate kube", func() {
Expect(kube.ExitCode()).To(Equal(0))
})
- It("podman generate kube with containers in a pod should fail", func() {
+ It("podman generate kube with containers in pods should fail", func() {
pod1 := podmanTest.Podman([]string{"run", "-dt", "--pod", "new:pod1", "--name", "top1", ALPINE, "top"})
pod1.WaitWithDefaultTimeout()
Expect(pod1.ExitCode()).To(Equal(0))
@@ -573,7 +605,7 @@ var _ = Describe("Podman generate kube", func() {
pod2.WaitWithDefaultTimeout()
Expect(pod2.ExitCode()).To(Equal(0))
- kube := podmanTest.Podman([]string{"generate", "kube", "pod1", "pod2"})
+ kube := podmanTest.Podman([]string{"generate", "kube", "top1", "top2"})
kube.WaitWithDefaultTimeout()
Expect(kube.ExitCode()).ToNot(Equal(0))
})
@@ -675,7 +707,7 @@ ENTRYPOINT /bin/sleep`
Expect(err).To(BeNil())
image := "generatekube:test"
- session := podmanTest.Podman([]string{"build", "-f", containerfilePath, "-t", image})
+ session := podmanTest.Podman([]string{"build", "--pull-never", "-f", containerfilePath, "-t", image})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
@@ -748,7 +780,7 @@ USER test1`
Expect(err).To(BeNil())
image := "generatekube:test"
- session := podmanTest.Podman([]string{"build", "-f", containerfilePath, "-t", image})
+ session := podmanTest.Podman([]string{"build", "--pull-never", "-f", containerfilePath, "-t", image})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go
index 9260d6cd2..cc4450379 100644
--- a/test/e2e/play_kube_test.go
+++ b/test/e2e/play_kube_test.go
@@ -357,7 +357,8 @@ func writeYaml(content string, fileName string) error {
return nil
}
-func generateKubeYaml(kind string, object interface{}, pathname string) error {
+// getKubeYaml returns a kubernetes YAML document.
+func getKubeYaml(kind string, object interface{}) (string, error) {
var yamlTemplate string
templateBytes := &bytes.Buffer{}
@@ -369,19 +370,41 @@ func generateKubeYaml(kind string, object interface{}, pathname string) error {
case "deployment":
yamlTemplate = deploymentYamlTemplate
default:
- return fmt.Errorf("unsupported kubernetes kind")
+ return "", fmt.Errorf("unsupported kubernetes kind")
}
t, err := template.New(kind).Parse(yamlTemplate)
if err != nil {
- return err
+ return "", err
}
if err := t.Execute(templateBytes, object); err != nil {
+ return "", err
+ }
+
+ return templateBytes.String(), nil
+}
+
+// generateKubeYaml writes a kubernetes YAML document.
+func generateKubeYaml(kind string, object interface{}, pathname string) error {
+ k, err := getKubeYaml(kind, object)
+ if err != nil {
return err
}
- return writeYaml(templateBytes.String(), pathname)
+ return writeYaml(k, pathname)
+}
+
+// generateMultiDocKubeYaml writes multiple kube objects in one Yaml document.
+func generateMultiDocKubeYaml(kubeObjects []string, pathname string) error {
+ var multiKube string
+
+ for _, k := range kubeObjects {
+ multiKube += "---\n"
+ multiKube += k
+ }
+
+ return writeYaml(multiKube, pathname)
}
// ConfigMap describes the options a kube yaml can be configured at configmap level
@@ -1698,4 +1721,102 @@ MemoryReservation: {{ .HostConfig.MemoryReservation }}`})
Expect(inspect.ExitCode()).To(Equal(0))
Expect(inspect.OutputToString()).To(Equal("true"))
})
+
+ // Multi doc related tests
+ It("podman play kube multi doc yaml", func() {
+ yamlDocs := []string{}
+ podNames := []string{}
+
+ serviceTemplate := `apiVersion: v1
+kind: Service
+metadata:
+ name: %s
+spec:
+ ports:
+ - port: 80
+ protocol: TCP
+ targetPort: 9376
+ selector:
+ app: %s
+`
+ // generate servies, pods and deployments
+ for i := 0; i < 2; i++ {
+ podName := fmt.Sprintf("testPod%d", i)
+ deploymentName := fmt.Sprintf("testDeploy%d", i)
+ deploymentPodName := fmt.Sprintf("%s-pod-0", deploymentName)
+
+ podNames = append(podNames, podName)
+ podNames = append(podNames, deploymentPodName)
+
+ pod := getPod(withPodName(podName))
+ podDeployment := getPod(withPodName(deploymentName))
+ deployment := getDeployment(withPod(podDeployment))
+ deployment.Name = deploymentName
+
+ // add services
+ yamlDocs = append([]string{
+ fmt.Sprintf(serviceTemplate, podName, podName),
+ fmt.Sprintf(serviceTemplate, deploymentPodName, deploymentPodName)}, yamlDocs...)
+
+ // add pods
+ k, err := getKubeYaml("pod", pod)
+ Expect(err).To(BeNil())
+ yamlDocs = append(yamlDocs, k)
+
+ // add deployments
+ 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))
+
+ for _, n := range podNames {
+ inspect := podmanTest.Podman([]string{"inspect", n, "--format", "'{{ .State }}'"})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect.ExitCode()).To(Equal(0))
+ Expect(inspect.OutputToString()).To(ContainSubstring(`Running`))
+ }
+ })
+
+ It("podman play kube invalid multi doc yaml", func() {
+ yamlDocs := []string{}
+
+ serviceTemplate := `apiVersion: v1
+kind: Service
+metadata:
+ name: %s
+spec:
+ ports:
+ - port: 80
+ protocol: TCP
+ targetPort: 9376
+ selector:
+ app: %s
+---
+invalid kube kind
+`
+ // add invalid multi doc yaml
+ yamlDocs = append(yamlDocs, fmt.Sprintf(serviceTemplate, "foo", "foo"))
+
+ // add pod
+ pod := getPod()
+ k, err := getKubeYaml("pod", pod)
+ 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(Not(Equal(0)))
+ })
})
diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go
index 490d05699..bb1f9590d 100644
--- a/test/e2e/run_test.go
+++ b/test/e2e/run_test.go
@@ -576,23 +576,23 @@ USER bin`
})
It("podman run blkio-weight test", func() {
- SkipIfRootless("FIXME: This is blowing up because of no /sys/fs/cgroup/user.slice/user-14467.slice/user@14467.service/cgroup.subtree_control file")
SkipIfRootlessCgroupsV1("Setting blkio-weight not supported on cgroupv1 for rootless users")
- if !CGROUPSV2 {
- if _, err := os.Stat("/sys/fs/cgroup/blkio/blkio.weight"); os.IsNotExist(err) {
- Skip("Kernel does not support blkio.weight")
- }
- }
- if podmanTest.Host.Distribution == "ubuntu" {
- Skip("Ubuntu <= 20.10 lacks BFQ scheduler")
- }
+ SkipIfRootless("By default systemd doesn't delegate io to rootless users")
if CGROUPSV2 {
- // convert linearly from [10-1000] to [1-10000]
- session := podmanTest.Podman([]string{"run", "--rm", "--blkio-weight=15", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/io.bfq.weight"})
+ if _, err := os.Stat("/sys/fs/cgroup/io.stat"); os.IsNotExist(err) {
+ Skip("Kernel does not have io.stat")
+ }
+ session := podmanTest.Podman([]string{"run", "--rm", "--blkio-weight=15", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/io.bfq.weight"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
- Expect(session.OutputToString()).To(ContainSubstring("51"))
+ // there was a documentation issue in the kernel that reported a different range [1-10000] for the io controller.
+ // older versions of crun/runc used it. For the time being allow both versions to pass the test.
+ // FIXME: drop "|51" once all the runtimes we test have the fix in place.
+ Expect(strings.Replace(session.OutputToString(), "default ", "", 1)).To(MatchRegexp("15|51"))
} else {
+ if _, err := os.Stat("/sys/fs/cgroup/blkio/blkio.weight"); os.IsNotExist(err) {
+ Skip("Kernel does not support blkio.weight")
+ }
session := podmanTest.Podman([]string{"run", "--rm", "--blkio-weight=15", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.weight"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
@@ -1412,7 +1412,28 @@ USER mail`
})
It("podman run --tz", func() {
- session := podmanTest.Podman([]string{"run", "--tz", "foo", "--rm", ALPINE, "date"})
+ testDir := filepath.Join(podmanTest.RunRoot, "tz-test")
+ err := os.MkdirAll(testDir, 0755)
+ Expect(err).To(BeNil())
+
+ tzFile := filepath.Join(testDir, "tzfile.txt")
+ file, err := os.Create(tzFile)
+ Expect(err).To(BeNil())
+
+ _, err = file.WriteString("Hello")
+ Expect(err).To(BeNil())
+ file.Close()
+
+ badTZFile := fmt.Sprintf("../../../%s", tzFile)
+ session := podmanTest.Podman([]string{"run", "--tz", badTZFile, "--rm", ALPINE, "date"})
+ session.WaitWithDefaultTimeout()
+ Expect(session.ExitCode()).To(Not(Equal(0)))
+ Expect(session.ErrorToString()).To(ContainSubstring("error finding timezone for container"))
+
+ err = os.Remove(tzFile)
+ Expect(err).To(BeNil())
+
+ session = podmanTest.Podman([]string{"run", "--tz", "foo", "--rm", ALPINE, "date"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Not(Equal(0)))
diff --git a/test/e2e/run_volume_test.go b/test/e2e/run_volume_test.go
index 454dfdc83..85a4d6d52 100644
--- a/test/e2e/run_volume_test.go
+++ b/test/e2e/run_volume_test.go
@@ -643,4 +643,30 @@ VOLUME /test/`
found, _ = session.GrepString("888:888")
Expect(found).Should(BeTrue())
})
+
+ It("volume permissions after run", func() {
+ imgName := "testimg"
+ dockerfile := `FROM fedora-minimal
+RUN useradd -m testuser -u 1005
+USER testuser`
+ podmanTest.BuildImage(dockerfile, imgName, "false")
+
+ testString := "testuser testuser"
+
+ test1 := podmanTest.Podman([]string{"run", "-v", "testvol1:/test", imgName, "bash", "-c", "ls -al /test | grep -v root | grep -v total"})
+ test1.WaitWithDefaultTimeout()
+ Expect(test1.ExitCode()).To(Equal(0))
+ Expect(strings.Contains(test1.OutputToString(), testString)).To(BeTrue())
+
+ volName := "testvol2"
+ vol := podmanTest.Podman([]string{"volume", "create", volName})
+ vol.WaitWithDefaultTimeout()
+ Expect(vol.ExitCode()).To(Equal(0))
+
+ test2 := podmanTest.Podman([]string{"run", "-v", fmt.Sprintf("%s:/test", volName), imgName, "bash", "-c", "ls -al /test | grep -v root | grep -v total"})
+ test2.WaitWithDefaultTimeout()
+ Expect(test2.ExitCode()).To(Equal(0))
+ Expect(strings.Contains(test2.OutputToString(), testString)).To(BeTrue())
+
+ })
})
diff --git a/test/python/docker/compat/test_images.py b/test/python/docker/compat/test_images.py
index 4a90069a9..1e2b531b7 100644
--- a/test/python/docker/compat/test_images.py
+++ b/test/python/docker/compat/test_images.py
@@ -1,4 +1,5 @@
import collections
+import io
import os
import subprocess
import sys
@@ -6,6 +7,7 @@ import time
import unittest
from docker import DockerClient, errors
+from docker.errors import APIError
from test.python.docker import Podman
from test.python.docker.compat import common, constant
@@ -79,9 +81,7 @@ class TestImages(unittest.TestCase):
self.assertEqual(len(self.client.images.list()), 2)
# List images with filter
- self.assertEqual(
- len(self.client.images.list(filters={"reference": "alpine"})), 1
- )
+ self.assertEqual(len(self.client.images.list(filters={"reference": "alpine"})), 1)
def test_search_image(self):
"""Search for image"""
@@ -149,15 +149,22 @@ class TestImages(unittest.TestCase):
self.assertEqual(len(self.client.images.list()), 2)
+ def test_load_corrupt_image(self):
+ """Import|Load Image failure"""
+ tarball = io.BytesIO("This is a corrupt tarball".encode("utf-8"))
+ with self.assertRaises(APIError):
+ self.client.images.load(tarball)
+
def test_build_image(self):
labels = {"apple": "red", "grape": "green"}
- _ = self.client.images.build(path="test/python/docker/build_labels", labels=labels, tag="labels")
+ _ = self.client.images.build(
+ path="test/python/docker/build_labels", labels=labels, tag="labels", isolation="default"
+ )
image = self.client.images.get("labels")
self.assertEqual(image.labels["apple"], labels["apple"])
self.assertEqual(image.labels["grape"], labels["grape"])
-
if __name__ == "__main__":
# Setup temporary space
unittest.main()
diff --git a/test/system/120-load.bats b/test/system/120-load.bats
index 95113c4a6..67687a5b0 100644
--- a/test/system/120-load.bats
+++ b/test/system/120-load.bats
@@ -32,7 +32,7 @@ verify_iid_and_name() {
echo "I am an invalid file and should cause a podman-load error" > $invalid
run_podman 125 load -i $invalid
# podman and podman-remote emit different messages; this is a common string
- is "$output" ".*error pulling image: unable to pull .*" \
+ is "$output" ".*payload does not match any of the supported image formats .*" \
"load -i INVALID fails with expected diagnostic"
}
@@ -126,15 +126,11 @@ verify_iid_and_name() {
verify_iid_and_name $img_name
}
-@test "podman load - will not read from tty" {
- if [ ! -t 0 ]; then
- skip "STDIN is not a tty"
- fi
-
- run_podman 125 load
+@test "podman load - redirect corrupt payload" {
+ run_podman 125 load <<< "Danger, Will Robinson!! This is a corrupt tarball!"
is "$output" \
- "Error: cannot read from terminal. Use command-line redirection" \
- "Diagnostic from 'podman load' without redirection or -i"
+ ".*payload does not match any of the supported image formats .*" \
+ "Diagnostic from 'podman load' unknown/corrupt payload"
}
@test "podman load - multi-image archive" {
diff --git a/test/system/200-pod.bats b/test/system/200-pod.bats
index 51835e4a3..c65449212 100644
--- a/test/system/200-pod.bats
+++ b/test/system/200-pod.bats
@@ -18,10 +18,6 @@ function teardown() {
@test "podman pod top - containers in different PID namespaces" {
- if is_remote && is_rootless; then
- skip "FIXME: pending #7139"
- fi
-
# With infra=false, we don't get a /pause container (we also
# don't pull k8s.gcr.io/pause )
no_infra='--infra=false'
@@ -55,10 +51,6 @@ function teardown() {
@test "podman pod - communicating between pods" {
- if is_remote && is_rootless; then
- skip "FIXME: pending #7139"
- fi
-
podname=pod$(random_string)
run_podman 1 pod exists $podname
run_podman pod create --infra=true --name=$podname
@@ -117,10 +109,6 @@ function teardown() {
}
@test "podman pod - communicating via /dev/shm " {
- if is_remote && is_rootless; then
- skip "FIXME: pending #7139"
- fi
-
podname=pod$(random_string)
run_podman 1 pod exists $podname
run_podman pod create --infra=true --name=$podname
@@ -168,10 +156,6 @@ function random_ip() {
}
@test "podman pod create - hashtag AllTheOptions" {
- if is_remote && is_rootless; then
- skip "FIXME: pending #7139"
- fi
-
mac=$(random_mac)
add_host_ip=$(random_ip)
add_host_n=$(random_string | tr A-Z a-z).$(random_string | tr A-Z a-z).xyz
diff --git a/test/system/220-healthcheck.bats b/test/system/220-healthcheck.bats
index 3405029c1..f929c6770 100644
--- a/test/system/220-healthcheck.bats
+++ b/test/system/220-healthcheck.bats
@@ -25,8 +25,6 @@ function _check_health {
@test "podman healthcheck" {
- skip_if_remote "FIXME: pending #7137"
-
# Create an image with a healthcheck script; said script will
# pass until the file /uh-oh gets created (by us, via exec)
cat >${PODMAN_TMPDIR}/healthcheck <<EOF
diff --git a/test/system/410-selinux.bats b/test/system/410-selinux.bats
index 49743ff33..4a2c7b7a4 100644
--- a/test/system/410-selinux.bats
+++ b/test/system/410-selinux.bats
@@ -61,9 +61,6 @@ function check_label() {
# SELinux not enabled on Ubuntu, so we should never get here
die "WHOA! SELinux enabled, but no /usr/bin/rpm!"
fi
- if [[ "$cs_version" < "2.146" ]]; then
- skip "FIXME: #7939: requires container-selinux-2.146.0 (currently installed: $cs_version)"
- fi
fi
# FIXME FIXME FIXME: delete up to here, leaving just check_label
diff --git a/test/system/450-interactive.bats b/test/system/450-interactive.bats
new file mode 100644
index 000000000..d047b9f25
--- /dev/null
+++ b/test/system/450-interactive.bats
@@ -0,0 +1,90 @@
+# -*- bats -*-
+#
+# tests of podman commands that require an interactive pty
+#
+
+load helpers
+
+###############################################################################
+# BEGIN setup/teardown
+
+# Each test runs with its own PTY, managed by socat.
+PODMAN_TEST_PTY=$(mktemp -u --tmpdir=${BATS_TMPDIR:-/tmp} podman_pty.XXXXXX)
+PODMAN_DUMMY=$(mktemp -u --tmpdir=${BATS_TMPDIR:-/tmp} podman_dummy.XXXXXX)
+PODMAN_SOCAT_PID=
+
+function setup() {
+ basic_setup
+
+ # Create a pty. Run under 'timeout' because BATS reaps child processes
+ # and if we exit before killing socat, bats will hang forever.
+ timeout 10 socat \
+ PTY,link=$PODMAN_TEST_PTY,raw,echo=0 \
+ PTY,link=$PODMAN_DUMMY,raw,echo=0 &
+ PODMAN_SOCAT_PID=$!
+
+ # Wait for pty
+ retries=5
+ while [[ ! -e $PODMAN_TEST_PTY ]]; do
+ retries=$(( retries - 1 ))
+ if [[ $retries -eq 0 ]]; then
+ die "Timed out waiting for $PODMAN_TEST_PTY"
+ fi
+ sleep 0.5
+ done
+}
+
+function teardown() {
+ if [[ -n $PODMAN_SOCAT_PID ]]; then
+ kill $PODMAN_SOCAT_PID
+ PODMAN_SOCAT_PID=
+ fi
+ rm -f $PODMAN_TEST_PTY $PODMAN_DUMMY_PTY
+
+ basic_teardown
+}
+
+# END setup/teardown
+###############################################################################
+# BEGIN tests
+
+@test "podman detects correct tty size" {
+ # Set the pty to a random size. Make rows/columns odd/even, to guarantee
+ # that they can never be the same
+ rows=$(( 15 + RANDOM % 60 | 1 ))
+ cols=$(( 15 + RANDOM % 60 & 126 ))
+ stty rows $rows cols $cols <$PODMAN_TEST_PTY
+
+ # ...and make sure stty under podman reads that.
+ # FIXME: 'sleep 1' is needed for podman-remote; without it, there's
+ # a race condition resulting in the following warning:
+ # WARN[0000] failed to resize TTY: container "xx" in wrong state "stopped"
+ # (also "created")
+ run_podman run -it --name mystty $IMAGE sh -c 'sleep 1;stty size' <$PODMAN_TEST_PTY
+ is "$output" "$rows $cols" "stty under podman reads the correct dimensions"
+}
+
+
+@test "podman load - will not read from tty" {
+ run_podman 125 load <$PODMAN_TEST_PTY
+ is "$output" \
+ "Error: cannot read from terminal. Use command-line redirection" \
+ "Diagnostic from 'podman load' without redirection or -i"
+}
+
+
+@test "podman run --tty -i failure with no tty" {
+ run_podman run --tty -i --rm $IMAGE echo hello < /dev/null
+ is "$output" ".*The input device is not a TTY.*" "-it _without_ a tty"
+
+ run_podman run --tty -i --rm $IMAGE echo hello <$PODMAN_TEST_PTY
+ is "$output" "hello" "-it _with_ a pty"
+
+ run_podman run --tty=false -i --rm $IMAGE echo hello < /dev/null
+ is "$output" "hello" "-tty=false: no warning"
+
+ run_podman run --tty -i=false --rm $IMAGE echo hello < /dev/null
+ is "$output" "hello" "-i=false: no warning"
+}
+
+# vim: filetype=sh
diff --git a/test/system/500-networking.bats b/test/system/500-networking.bats
index 0d976a6af..4868ad6a0 100644
--- a/test/system/500-networking.bats
+++ b/test/system/500-networking.bats
@@ -97,7 +97,6 @@ load helpers
# "network create" now works rootless, with the help of a special container
@test "podman network create" {
- skip_if_remote "FIXME: pending #7808"
myport=54322
local mynetname=testnet-$(random_string 10)