diff options
author | Josh Patterson <josh.patterson@securityonionsolutions.com> | 2022-08-29 15:48:02 -0400 |
---|---|---|
committer | Josh Patterson <josh.patterson@securityonionsolutions.com> | 2022-08-29 15:48:02 -0400 |
commit | 0e53c8c73509e666bbb5ff4ba0ec2a8fa5c8c1b8 (patch) | |
tree | 139b60bd14d06eaf9c6c0a40d78c1e3c08404037 /test | |
parent | 08af95f63576af0c443fdef9d3ba6ba12a0c0dbc (diff) | |
parent | 468aa6478c73e4acd8708ce8bb0bb5a056f329c2 (diff) | |
download | podman-0e53c8c73509e666bbb5ff4ba0ec2a8fa5c8c1b8.tar.gz podman-0e53c8c73509e666bbb5ff4ba0ec2a8fa5c8c1b8.tar.bz2 podman-0e53c8c73509e666bbb5ff4ba0ec2a8fa5c8c1b8.zip |
Merge remote-tracking branch 'upstream/main' into api_compat_containers
Diffstat (limited to 'test')
39 files changed, 733 insertions, 215 deletions
diff --git a/test/apiv2/10-images.at b/test/apiv2/10-images.at index f03b95786..86ee2a1f5 100644 --- a/test/apiv2/10-images.at +++ b/test/apiv2/10-images.at @@ -203,7 +203,7 @@ t POST "build?dockerfile=containerfile" $CONTAINERFILE_TAR application/json 200 # Libpod: allow building from url: https://github.com/alpinelinux/docker-alpine.git and must ignore any provided tar t POST "libpod/build?remote=https%3A%2F%2Fgithub.com%2Falpinelinux%2Fdocker-alpine.git" $CONTAINERFILE_TAR 200 \ - .stream~"STEP 1/5: FROM alpine:3.14" + .stream~"STEP 1/5: FROM alpine:" # Build api response header must contain Content-type: application/json t POST "build?dockerfile=containerfile" $CONTAINERFILE_TAR application/json 200 @@ -239,4 +239,23 @@ fi cleanBuildTest +# compat API vs libpod API event differences: +# on image removal, libpod produces 'remove' events. +# compat produces 'delete' events. +podman image build -t test:test -<<EOF +from $IMAGE +EOF + +START=$(date +%s) + +t DELETE libpod/images/test:test 200 +# HACK HACK HACK There is a race around events being added to the journal +# This sleep seems to avoid the race. +# If it fails and begins to flake, investigate a retry loop. +sleep 1 +t GET "libpod/events?stream=false&since=$START" 200 \ + 'select(.status | contains("remove")).Action=remove' +t GET "events?stream=false&since=$START" 200 \ + 'select(.status | contains("delete")).Action=delete' + # vim: filetype=sh diff --git a/test/apiv2/12-imagesMore.at b/test/apiv2/12-imagesMore.at index 498d67569..eb58b8377 100644 --- a/test/apiv2/12-imagesMore.at +++ b/test/apiv2/12-imagesMore.at @@ -3,9 +3,6 @@ # Tests for more image-related endpoints # -red='\e[31m' -nc='\e[0m' - start_registry podman pull -q $IMAGE @@ -63,7 +60,9 @@ podman pull -q $IMAGE # test podman image SCP # ssh needs to work so we can validate that the failure is past argument parsing -podman system connection add --default test ssh://$USER@localhost/run/user/$UID/podman/podman.sock +conn=apiv2test-temp-connection +podman system connection add --default $conn \ + ssh://$USER@localhost/run/user/$UID/podman/podman.sock # should fail but need to check the output... # status 125 here means that the save/load fails due to # cirrus weirdness with exec.Command. All of the args have been parsed successfully. @@ -72,4 +71,7 @@ t POST "libpod/images/scp/$IMAGE?destination=QA::" 500 \ t DELETE libpod/images/$IMAGE 200 \ .ExitCode=0 +# Clean up +podman system connection rm $conn + stop_registry diff --git a/test/apiv2/20-containers.at b/test/apiv2/20-containers.at index 29b641853..253bb2e45 100644 --- a/test/apiv2/20-containers.at +++ b/test/apiv2/20-containers.at @@ -531,21 +531,21 @@ sleep 3 t GET containers/status-test/json 200 .State.Status="exited" # test podman generate spec as input for the api -podman create --name=specgen alpine_labels +cname=specgen$(random_string 10) +podman create --name=$cname $IMAGE TMPD=$(mktemp -d podman-apiv2-test.build.XXXXXXXX) -podman generate spec -f ${TMPD}/input.txt -c specgen +podman generate spec -f ${TMPD}/myspec.json -c $cname -curl -XPOST -o ${TMPD}/response.txt --dump-header ${TMPD}/headers.txt -H content-type:application/json http://$HOST:$PORT/v4.0.0/libpod/containers/create -d "@${TMPD}/input.txt" +# Create a container based on that spec +t POST libpod/containers/create ${TMPD}/myspec.json 201 \ + .Id~[0-9a-f]\\{64\\} -if ! grep -q '201 Created' "${TMPD}/headers.txt"; then - cat "${TMPD}/headers.txt" - cat "${TMPD}/response.txt" - echo -e "${red}NOK: container create failed" - rm -rf $TMPD - exit 1 -fi +# Verify +t GET libpod/containers/$cname/json 200 \ + .ImageName=$IMAGE \ + .Name=$cname rm -rf $TMPD diff --git a/test/apiv2/23-containersArchive.at b/test/apiv2/23-containersArchive.at index c55164780..c1b936e3a 100644 --- a/test/apiv2/23-containersArchive.at +++ b/test/apiv2/23-containersArchive.at @@ -3,22 +3,31 @@ # test more container-related endpoints # -red='\e[31m' -nc='\e[0m' - podman pull $IMAGE &>/dev/null # Ensure clean slate podman rm -a -f &>/dev/null -CTR="ArchiveTestingCtr" +CTR="ArchiveTestingCtr$(random_string 5)" TMPD=$(mktemp -d podman-apiv2-test.archive.XXXXXXXX) HELLO_TAR="${TMPD}/hello.tar" -echo "Hello" > $TMPD/hello.txt +HELLO_S="Hello_$(random_string 8)" +echo "$HELLO_S" > $TMPD/hello.txt tar --owner=1042 --group=1043 --format=posix -C $TMPD -cvf ${HELLO_TAR} hello.txt &> /dev/null +# Start a container, and wait for it. (I know we don't actually do anything +# if we time out. If we do, subsequent tests will fail. I just want to avoid +# a race between container-start and tests-start) podman run -d --name "${CTR}" "${IMAGE}" top +timeout=10 +while [[ $timeout -gt 0 ]]; do + if podman container exists "${CTR}"; then + break + fi + timeout=$((timeout - 1)) + sleep 1 +done function cleanUpArchiveTest() { podman container stop "${CTR}" &> /dev/null @@ -30,63 +39,47 @@ t HEAD "containers/nonExistentCtr/archive?path=%2F" 404 t HEAD "containers/${CTR}/archive?path=%2Fnon%2Fexistent%2Fpath" 404 t HEAD "containers/${CTR}/archive?path=%2Fetc%2Fpasswd" 200 -curl "http://$HOST:$PORT/containers/${CTR}/archive?path=%2Ftmp%2F" \ - -X PUT \ - -H "Content-Type: application/x-tar" \ - --upload-file "${HELLO_TAR}" &> /dev/null +# Send tarfile to container... +t PUT "/containers/${CTR}/archive?path=%2Ftmp%2F" ${HELLO_TAR} 200 '' -if ! podman exec -it "${CTR}" "grep" "Hello" "/tmp/hello.txt" &> /dev/null ; then - echo -e "${red}NOK: The hello.txt file has not been uploaded.${nc}" 1>&2; - cleanUpArchiveTest - exit 1 -fi +# ...and 'exec cat file' to confirm that it got extracted into place. +cat >$TMPD/exec.json <<EOF +{ "AttachStdout":true,"Cmd":["cat","/tmp/hello.txt"]} +EOF +t POST containers/${CTR}/exec $TMPD/exec.json 201 .Id~[0-9a-f]\\{64\\} +eid=$(jq -r '.Id' <<<"$output") +# The 017 is the byte length +t POST exec/$eid/start 200 $'\001\017'$HELLO_S +# Now fetch hello.txt back as a tarfile t HEAD "containers/${CTR}/archive?path=%2Ftmp%2Fhello.txt" 200 +t GET "containers/${CTR}/archive?path=%2Ftmp%2Fhello.txt" 200 -curl "http://$HOST:$PORT/containers/${CTR}/archive?path=%2Ftmp%2Fhello.txt" \ - --dump-header "${TMPD}/headers.txt" \ - -o "${TMPD}/body.tar" \ - -X GET &> /dev/null - -PATH_STAT="$(grep X-Docker-Container-Path-Stat "${TMPD}/headers.txt" | cut -d " " -f 2 | base64 -d --ignore-garbage)" - -ARCHIVE_TEST_ERROR="" +# Check important-looking header +PATH_STAT="$(grep X-Docker-Container-Path-Stat "$WORKDIR/curl.headers.out" | cut -d " " -f 2 | base64 -d --ignore-garbage)" -if [ "$(echo "${PATH_STAT}" | jq ".name")" != '"hello.txt"' ]; then - echo -e "${red}NOK: Wrong name in X-Docker-Container-Path-Stat header.${nc}" 1>&2; - ARCHIVE_TEST_ERROR="1" -fi +is "$(jq -r .name <<<$PATH_STAT)" "hello.txt" "Docker-Path-Stat .name" +is "$(jq -r .size <<<$PATH_STAT)" "15" "Docker-Path-Stat .size" -if [ "$(echo "${PATH_STAT}" | jq ".size")" != "6" ]; then - echo -e "${red}NOK: Wrong size in X-Docker-Container-Path-Stat header.${nc}" 1>&2; - ARCHIVE_TEST_ERROR="1" -fi +# Check filename and its contents +tar_tf=$(tar tf $WORKDIR/curl.result.out) +is "$tar_tf" "hello.txt" "fetched tarball: file name" -if ! tar -tf "${TMPD}/body.tar" | grep "hello.txt" &> /dev/null; then - echo -e "${red}NOK: Body doesn't contain expected file.${nc}" 1>&2; - ARCHIVE_TEST_ERROR="1" -fi +tar_contents=$(tar xf $WORKDIR/curl.result.out --to-stdout) +is "$tar_contents" "$HELLO_S" "fetched tarball: file contents" -if [ "$(tar -xf "${TMPD}/body.tar" hello.txt --to-stdout)" != "Hello" ]; then - echo -e "${red}NOK: Content of file doesn't match.${nc}" 1>&2; - ARCHIVE_TEST_ERROR="1" -fi +# TODO: uid/gid should be also preserved on way back (GET request) +# right now it ends up as 0/0 instead of 1042/1043 +tar_uidgid=$(tar tvf $WORKDIR/curl.result.out | awk '{print $2}') +is "$tar_uidgid" "0/0" "fetched tarball: file uid/gid" -# test if uid/gid was set correctly in the server -uidngid=$($PODMAN_BIN --root $WORKDIR/server_root exec "${CTR}" stat -c "%u:%g" "/tmp/hello.txt") -if [[ "${uidngid}" != "1042:1043" ]]; then - echo -e "${red}NOK: UID/GID of the file doesn't match.${nc}" 1>&2; - ARCHIVE_TEST_ERROR="1" -fi +# test if uid/gid was set correctly in the server. Again, via exec. +cat >$TMPD/exec.json <<EOF +{ "AttachStdout":true,"Cmd":["stat","-c","%u:%g","/tmp/hello.txt"]} +EOF -# TODO: uid/gid should be also preserved on way back (GET request) -# right now it ends up as root:root instead of 1042:1043 -#if [[ "$(tar -tvf "${TMPD}/body.tar")" != *"1042/1043"* ]]; then -# echo -e "${red}NOK: UID/GID of the file doesn't match.${nc}" 1>&2; -# ARCHIVE_TEST_ERROR="1" -#fi +t POST containers/${CTR}/exec $TMPD/exec.json 201 .Id~[0-9a-f]\\{64\\} +eid=$(jq -r '.Id' <<<"$output") +t POST exec/$eid/start 200 $'\001\012'1042:1043 cleanUpArchiveTest -if [[ "${ARCHIVE_TEST_ERROR}" ]] ; then - exit 1; -fi diff --git a/test/apiv2/26-containersWait.at b/test/apiv2/26-containersWait.at index 55bcd4592..41938d567 100644 --- a/test/apiv2/26-containersWait.at +++ b/test/apiv2/26-containersWait.at @@ -3,9 +3,6 @@ # test more container-related endpoints # -red='\e[31m' -nc='\e[0m' - podman pull "${IMAGE}" &>/dev/null # Ensure clean slate @@ -21,29 +18,29 @@ t POST "containers/${CTR}/wait?condition=non-existent-cond" 400 t POST "containers/${CTR}/wait?condition=not-running" 200 +# Test waiting for EXIT (need to start a background trigger first) +(sleep 2;podman start "${CTR}") & +child_pid=$! + +# This will block until the background job completes t POST "containers/${CTR}/wait?condition=next-exit" 200 \ .StatusCode=0 \ - .Error=null & -child_pid=$! -podman start "${CTR}" + .Error=null wait "${child_pid}" - -# check if headers are sent in advance before body -WAIT_TEST_ERROR="" -curl -I -X POST "http://$HOST:$PORT/containers/${CTR}/wait?condition=next-exit" &> "/dev/null" & -child_pid=$! -sleep 0.5 -if kill -2 "${child_pid}" 2> "/dev/null"; then - echo -e "${red}NOK: Failed to get response headers immediately.${nc}" 1>&2; - WAIT_TEST_ERROR="1" +# Test that headers are sent before body. (We should actually never get a body) +APIV2_TEST_EXPECT_TIMEOUT=2 t POST "containers/${CTR}/wait?condition=next-exit" 999 +like "$(<$WORKDIR/curl.headers.out)" ".*HTTP.* 200 OK.*" \ + "Received headers from /wait" +if [[ -e $WORKDIR/curl.result.out ]]; then + _show_ok 0 "UNEXPECTED: curl on /wait returned results" fi -t POST "containers/${CTR}/wait?condition=removed" 200 & +# Test waiting for REMOVE. Like above, start a background trigger. +(sleep 2;podman container rm "${CTR}") & child_pid=$! -podman container rm "${CTR}" -wait "${child_pid}" -if [[ "${WAIT_TEST_ERROR}" ]] ; then - exit 1; -fi +t POST "containers/${CTR}/wait?condition=removed" 200 \ + .StatusCode=0 \ + .Error=null +wait "${child_pid}" diff --git a/test/apiv2/40-pods.at b/test/apiv2/40-pods.at index d21b3d1a9..0e0f1cb18 100644 --- a/test/apiv2/40-pods.at +++ b/test/apiv2/40-pods.at @@ -134,23 +134,17 @@ t GET libpod/pods/json?filters='{"label":["testl' 400 \ t DELETE libpod/pods/foo 200 t DELETE "libpod/pods/foo (pod has already been deleted)" 404 -t_timeout 5 GET "libpod/pods/stats?stream=true&delay=1" 200 +# Expect this to time out +APIV2_TEST_EXPECT_TIMEOUT=5 t GET "libpod/pods/stats?stream=true&delay=1" 999 podman pod create --name=specgen TMPD=$(mktemp -d podman-apiv2-test.build.XXXXXXXX) -podman generate spec -f ${TMPD}/input.txt -c specgen +podman generate spec -f ${TMPD}/myspec.json -c specgen -curl -XPOST -o ${TMPD}/response.txt --dump-header ${TMPD}/headers.txt -H content-type:application/json http://$HOST:$PORT/v4.0.0/libpod/pods/create -d "@${TMPD}/input.txt" - -if ! grep -q '201 Created' "${TMPD}/headers.txt"; then - cat "${TMPD}/headers.txt" - cat "${TMPD}/response.txt" - echo -e "${red}NOK: pod create failed" - rm -rf $TMPD - exit 1 -fi +t POST libpod/pods/create ${TMPD}/myspec.json 201 \ + .Id~[0-9a-f]\\{64\\} rm -rf $TMPD diff --git a/test/apiv2/70-short-names.at b/test/apiv2/70-short-names.at index 643cbc25b..952dd2ad1 100644 --- a/test/apiv2/70-short-names.at +++ b/test/apiv2/70-short-names.at @@ -33,18 +33,8 @@ RUN touch /foo EOF tar --format=posix -C $TMPD -cvf ${CONTAINERFILE_TAR} containerfile &> /dev/null - curl -XPOST --data-binary @<(cat $CONTAINERFILE_TAR) \ - -H "content-type: application/x-tar" \ - --dump-header "${TMPD}/headers.txt" \ - -o "${TMPD}/response.txt" \ - "http://$HOST:$PORT/build?dockerfile=containerfile&t=$tag" &> /dev/null - - if ! grep -q '200 OK' "${TMPD}/headers.txt"; then - cat "${TMPD}/headers.txt" - cat "${TMPD}/response.txt" - echo -e "${red}NOK: Image build from tar failed response was not 200 OK (application/x-tar)" - exit 1 - fi + t POST "/build?dockerfile=containerfile&t=$tag" $CONTAINERFILE_TAR 200 \ + .stream~".*Successfully tagged .*" rm -rf $TMPD t DELETE "images/$fqn" 200 diff --git a/test/apiv2/README.md b/test/apiv2/README.md index 63d1f5b13..712124d1b 100644 --- a/test/apiv2/README.md +++ b/test/apiv2/README.md @@ -46,6 +46,9 @@ with POST parameters if present, and compares return status and | +----------- POST params +--------------------------------- note the missing slash +Never, ever, ever, seriously _EVER_ `exit` from a test. Just don't. +That skips cleanup, and leaves the system in a broken state. + Notes: * If the endpoint has a leading slash (`/_ping`), `t` leaves it unchanged. @@ -61,14 +64,19 @@ of POST parameters in the form 'key=value', separated by spaces: `t` will convert the param list to JSON form for passing to the server. A numeric status code terminates processing of POST parameters. ** As a special case, when one POST argument is a string ending in `.tar`, -`t` will invoke `curl` with `--data-binary @PATH` and -set `Content-type: application/x-tar`. This is useful for `build` endpoints. +`.yaml`, or `.json`, `t` will invoke `curl` with `--data-binary @PATH` and +set `Content-type` as appropriate. This is useful for `build` endpoints. (To override `Content-type`, simply pass along an extra string argument matching `application/*`): t POST myentrypoint /mytmpdir/myfile.tar application/foo 400 +** Like above, when using PUT, `t` does `--upload-time` instead of +`--data-binary` * The final arguments are one or more expected string results. If an argument starts with a dot, `t` will invoke `jq` on the output to fetch that field, and will compare it to the right-hand side of the argument. If the separator is `=` (equals), `t` will require an exact match; if `~` (tilde), `t` will use `expr` to compare. + +* If your test expects `curl` to time out: + APIV2_TEST_EXPECT_TIMEOUT=5 t POST /foo 999 diff --git a/test/apiv2/python/rest_api/fixtures/api_testcase.py b/test/apiv2/python/rest_api/fixtures/api_testcase.py index f47136555..edb34b31e 100644 --- a/test/apiv2/python/rest_api/fixtures/api_testcase.py +++ b/test/apiv2/python/rest_api/fixtures/api_testcase.py @@ -20,7 +20,7 @@ class APITestCase(unittest.TestCase): APITestCase.podman = Podman() APITestCase.service = APITestCase.podman.open( - "system", "service", "tcp:localhost:8080", "--time=0" + "system", "service", "tcp://localhost:8080", "--time=0" ) # give the service some time to be ready... time.sleep(2) diff --git a/test/apiv2/python/rest_api/v1_test_rest_v1_0_0.py b/test/apiv2/python/rest_api/v1_test_rest_v1_0_0.py index 905c29683..2274f25bf 100644 --- a/test/apiv2/python/rest_api/v1_test_rest_v1_0_0.py +++ b/test/apiv2/python/rest_api/v1_test_rest_v1_0_0.py @@ -63,7 +63,7 @@ class TestApi(unittest.TestCase): podman(), "system", "service", - "tcp:localhost:8080", + "tcp://localhost:8080", "--log-level=debug", "--time=0", ], diff --git a/test/apiv2/test-apiv2 b/test/apiv2/test-apiv2 index 0c3c6e672..aca7db0dd 100755 --- a/test/apiv2/test-apiv2 +++ b/test/apiv2/test-apiv2 @@ -23,8 +23,6 @@ REGISTRY_IMAGE="${PODMAN_TEST_IMAGE_REGISTRY}/${PODMAN_TEST_IMAGE_USER}/registry ############################################################################### # BEGIN setup -USER=$PODMAN_ROOTLESS_USER -UID=$PODMAN_ROOTLESS_UID TMPDIR=${TMPDIR:-/tmp} WORKDIR=$(mktemp --tmpdir -d $ME.tmp.XXXXXX) @@ -56,9 +54,6 @@ fi # Path to podman binary PODMAN_BIN=${PODMAN:-${CONTAINERS_HELPER_BINARY_DIR}/podman} -# Timeout for streamed responses -CURL_TIMEOUT=0 - # Cleanup handlers clean_up_server() { if [ -n "$service_pid" ]; then @@ -135,7 +130,8 @@ function like() { ############## function _show_ok() { local ok=$1 - local testname=$2 + # Exec tests include control characters; filter them out + local testname=$(tr -d \\012 <<<"$2"|cat -vT) # If output is a tty, colorize pass/fail local red= @@ -220,21 +216,6 @@ function jsonify() { } ####### -# t_timeout # Timeout wrapper for test helper -####### -function t_timeout() { - CURL_TIMEOUT=$1; shift - local min_runtime=$((CURL_TIMEOUT - 1)) - start=`date +%s` - t $@ - local end=`date +%s` - local runtime=$((end-start)) - if ! [[ "$runtime" -ge "$min_runtime" ]]; then - die "Error: Streaming time should be greater or equal to '$min_runtime'" - fi -} - -####### # t # Main test helper ####### function t() { @@ -245,23 +226,28 @@ function t() { local testname="$method $path" - if [[ $CURL_TIMEOUT != 0 ]]; then - local c_timeout=$CURL_TIMEOUT - curl_args+=("-m $CURL_TIMEOUT") - CURL_TIMEOUT=0 # 'consume' timeout - fi # POST and PUT requests may be followed by one or more key=value pairs. # Slurp the command line until we see a 3-digit status code. if [[ $method = "POST" || $method == "PUT" || $method = "DELETE" ]]; then local -a post_args + + if [[ $method = "POST" ]]; then + function _add_curl_args() { curl_args+=(--data-binary @$1); } + else + function _add_curl_args() { curl_args+=(--upload-file $1); } + fi + for arg; do case "$arg" in *=*) post_args+=("$arg"); shift;; - *.tar) curl_args+=(--data-binary @$arg); + *.json) _add_curl_args $arg; + content_type="application/json"; + shift;; + *.tar) _add_curl_args $arg; content_type="application/x-tar"; shift;; - *.yaml) curl_args+=(--data-binary @$arg); + *.yaml) _add_curl_args $arg; shift;; application/*) content_type="$arg"; shift;; @@ -301,6 +287,11 @@ function t() { curl_args+=("--head") fi + # If this is set, we're *expecting* curl to time out + if [[ -n "$APIV2_TEST_EXPECT_TIMEOUT" ]]; then + curl_args+=("-m" $APIV2_TEST_EXPECT_TIMEOUT) + fi + local expected_code=$1; shift # Log every action we do @@ -316,8 +307,19 @@ function t() { --write-out '%{http_code}^%{content_type}^%{time_total}' \ -o $WORKDIR/curl.result.out "$url"); rc=$?; } || : + # Special case: this means we *expect and want* a timeout + if [[ -n "$APIV2_TEST_EXPECT_TIMEOUT" ]]; then + # Hardcoded. See curl(1) for list of exit codes + if [[ $rc -eq 28 ]]; then + _show_ok 1 "$testname: curl timed out (expected)" + else + _show_ok 0 "$testname: expected curl to time out; it did not" + fi + return + fi + # Any error from curl is instant bad news, from which we can't recover - if [[ $rc -ne 0 ]] && [[ $c_timeout -eq 0 ]]; then + if [[ $rc -ne 0 ]]; then die "curl failure ($rc) on $url - cannot continue" fi diff --git a/test/e2e/build/Containerfile.userns-auto b/test/e2e/build/Containerfile.userns-auto new file mode 100644 index 000000000..921610982 --- /dev/null +++ b/test/e2e/build/Containerfile.userns-auto @@ -0,0 +1,2 @@ +FROM alpine +RUN cat /proc/self/uid_map diff --git a/test/e2e/config/containers.conf b/test/e2e/config/containers.conf index c33f32ab4..94bb316b1 100644 --- a/test/e2e/config/containers.conf +++ b/test/e2e/config/containers.conf @@ -61,6 +61,8 @@ no_hosts=true network_cmd_options=["allow_host_loopback=true"] service_timeout=1234 +volume_plugin_timeout = 15 + # We need to ensure each test runs on a separate plugin instance... # For now, let's just make a bunch of plugin paths and have each test use one. [engine.volume_plugins] diff --git a/test/e2e/container_clone_test.go b/test/e2e/container_clone_test.go index 94ccd6ffe..1ba5de1a3 100644 --- a/test/e2e/container_clone_test.go +++ b/test/e2e/container_clone_test.go @@ -87,6 +87,7 @@ var _ = Describe("Podman container clone", func() { }) It("podman container clone resource limits override", func() { + SkipIfRootlessCgroupsV1("Not supported for rootless + CgroupsV1") create := podmanTest.Podman([]string{"create", "--cpus=5", ALPINE}) create.WaitWithDefaultTimeout() Expect(create).To(Exit(0)) @@ -292,4 +293,20 @@ var _ = Describe("Podman container clone", func() { Expect(ok).To(BeTrue()) }) + + It("podman container clone env test", func() { + session := podmanTest.Podman([]string{"run", "--name", "env_ctr", "-e", "ENV_TEST=123", ALPINE, "printenv", "ENV_TEST"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + session = podmanTest.Podman([]string{"container", "clone", "env_ctr"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + session = podmanTest.Podman([]string{"start", "-a", "env_ctr-clone"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).Should(ContainSubstring("123")) + + }) }) diff --git a/test/e2e/create_test.go b/test/e2e/create_test.go index 9679aad24..b35d0f3c5 100644 --- a/test/e2e/create_test.go +++ b/test/e2e/create_test.go @@ -438,6 +438,7 @@ var _ = Describe("Podman create", func() { }) It("podman create with -m 1000000 sets swap to 2000000", func() { + SkipIfRootlessCgroupsV1("Not supported for rootless + CgroupsV1") numMem := 1000000 ctrName := "testCtr" session := podmanTest.Podman([]string{"create", "-t", "-m", fmt.Sprintf("%db", numMem), "--name", ctrName, ALPINE, "/bin/sh"}) @@ -452,6 +453,7 @@ var _ = Describe("Podman create", func() { }) It("podman create --cpus 5 sets nanocpus", func() { + SkipIfRootlessCgroupsV1("Not supported for rootless + CgroupsV1") numCpus := 5 nanoCPUs := numCpus * 1000000000 ctrName := "testCtr" diff --git a/test/e2e/generate_kube_test.go b/test/e2e/generate_kube_test.go index 142f32d19..e7ceaf2d2 100644 --- a/test/e2e/generate_kube_test.go +++ b/test/e2e/generate_kube_test.go @@ -490,6 +490,7 @@ var _ = Describe("Podman generate kube", func() { }) It("podman generate kube on pod with memory limit", func() { + SkipIfRootlessCgroupsV1("Not supported for rootless + CgroupsV1") podName := "testMemoryLimit" podSession := podmanTest.Podman([]string{"pod", "create", "--name", podName}) podSession.WaitWithDefaultTimeout() @@ -515,6 +516,7 @@ var _ = Describe("Podman generate kube", func() { }) It("podman generate kube on pod with cpu limit", func() { + SkipIfRootlessCgroupsV1("Not supported for rootless + CgroupsV1") podName := "testCpuLimit" podSession := podmanTest.Podman([]string{"pod", "create", "--name", podName}) podSession.WaitWithDefaultTimeout() diff --git a/test/e2e/generate_spec_test.go b/test/e2e/generate_spec_test.go index 57cd9546b..9188b5222 100644 --- a/test/e2e/generate_spec_test.go +++ b/test/e2e/generate_spec_test.go @@ -41,6 +41,7 @@ var _ = Describe("Podman generate spec", func() { }) It("podman generate spec basic usage", func() { + SkipIfRootlessCgroupsV1("Not supported for rootless + CgroupsV1") session := podmanTest.Podman([]string{"create", "--cpus", "5", "--name", "specgen", ALPINE}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) @@ -51,6 +52,7 @@ var _ = Describe("Podman generate spec", func() { }) It("podman generate spec file", func() { + SkipIfRootlessCgroupsV1("Not supported for rootless + CgroupsV1") session := podmanTest.Podman([]string{"create", "--cpus", "5", "--name", "specgen", ALPINE}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) diff --git a/test/e2e/healthcheck_run_test.go b/test/e2e/healthcheck_run_test.go index fd4e763f9..969f83b19 100644 --- a/test/e2e/healthcheck_run_test.go +++ b/test/e2e/healthcheck_run_test.go @@ -317,6 +317,12 @@ HEALTHCHECK CMD ls -l / 2>&1`, ALPINE) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) + // Check if image inspect contains CMD-SHELL generated by healthcheck. + session = podmanTest.Podman([]string{"image", "inspect", "--format", "{{.Config.Healthcheck}}", "test"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(ContainSubstring("CMD-SHELL")) + run := podmanTest.Podman([]string{"run", "-dt", "--name", "hctest", "test", "ls"}) run.WaitWithDefaultTimeout() Expect(run).Should(Exit(0)) diff --git a/test/e2e/manifest_test.go b/test/e2e/manifest_test.go index ee954a1a4..60b72dcaa 100644 --- a/test/e2e/manifest_test.go +++ b/test/e2e/manifest_test.go @@ -46,9 +46,23 @@ var _ = Describe("Podman manifest", func() { processTestResult(f) }) It("create w/o image", func() { - session := podmanTest.Podman([]string{"manifest", "create", "foo"}) - session.WaitWithDefaultTimeout() - Expect(session).Should(Exit(0)) + for _, amend := range []string{"--amend", "-a"} { + session := podmanTest.Podman([]string{"manifest", "create", "foo"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + session = podmanTest.Podman([]string{"manifest", "create", "foo"}) + session.WaitWithDefaultTimeout() + Expect(session).To(ExitWithError()) + + session = podmanTest.Podman([]string{"manifest", "create", amend, "foo"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + session = podmanTest.Podman([]string{"manifest", "rm", "foo"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + } }) It("create w/ image", func() { @@ -336,6 +350,33 @@ var _ = Describe("Podman manifest", func() { Expect(foundZstdFile).To(BeTrue()) }) + It("push progress", func() { + SkipIfRemote("manifest push to dir not supported in remote mode") + + session := podmanTest.Podman([]string{"manifest", "create", "foo", imageList}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + dest := filepath.Join(podmanTest.TempDir, "pushed") + err := os.MkdirAll(dest, os.ModePerm) + Expect(err).To(BeNil()) + defer func() { + os.RemoveAll(dest) + }() + + session = podmanTest.Podman([]string{"push", "foo", "-q", "dir:" + dest}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.ErrorToString()).To(BeEmpty()) + + session = podmanTest.Podman([]string{"push", "foo", "dir:" + dest}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + output := session.ErrorToString() + Expect(output).To(ContainSubstring("Writing manifest list to image destination")) + Expect(output).To(ContainSubstring("Storing list signatures")) + }) + It("authenticated push", func() { registryOptions := &podmanRegistry.Options{ Image: "docker-archive:" + imageTarPath(REGISTRY_IMAGE), diff --git a/test/e2e/network_connect_disconnect_test.go b/test/e2e/network_connect_disconnect_test.go index ece1b519d..30a5c6482 100644 --- a/test/e2e/network_connect_disconnect_test.go +++ b/test/e2e/network_connect_disconnect_test.go @@ -157,7 +157,7 @@ var _ = Describe("Podman network connect and disconnect", func() { Expect(con.ErrorToString()).To(ContainSubstring(`"slirp4netns" is not supported: invalid network mode`)) }) - It("podman connect on a container that already is connected to the network should error", func() { + It("podman connect on a container that already is connected to the network should error after init", func() { netName := "aliasTest" + stringid.GenerateNonCryptoID() session := podmanTest.Podman([]string{"network", "create", netName}) session.WaitWithDefaultTimeout() @@ -177,7 +177,15 @@ var _ = Describe("Podman network connect and disconnect", func() { con := podmanTest.Podman([]string{"network", "connect", netName, "test"}) con.WaitWithDefaultTimeout() - Expect(con).Should(ExitWithError()) + Expect(con).Should(Exit(0)) + + init := podmanTest.Podman([]string{"init", "test"}) + init.WaitWithDefaultTimeout() + Expect(init).Should(Exit(0)) + + con2 := podmanTest.Podman([]string{"network", "connect", netName, "test"}) + con2.WaitWithDefaultTimeout() + Expect(con2).Should(ExitWithError()) }) It("podman network connect", func() { diff --git a/test/e2e/pull_test.go b/test/e2e/pull_test.go index 12f14fdc8..ba717f393 100644 --- a/test/e2e/pull_test.go +++ b/test/e2e/pull_test.go @@ -545,4 +545,18 @@ var _ = Describe("Podman pull", func() { Expect(data[0]).To(HaveField("Os", runtime.GOOS)) Expect(data[0]).To(HaveField("Architecture", "arm64")) }) + + It("podman pull progress", func() { + session := podmanTest.Podman([]string{"pull", ALPINE}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + output := session.ErrorToString() + Expect(output).To(ContainSubstring("Getting image source signatures")) + Expect(output).To(ContainSubstring("Copying blob ")) + + session = podmanTest.Podman([]string{"pull", "-q", ALPINE}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.ErrorToString()).To(BeEmpty()) + }) }) diff --git a/test/e2e/restart_test.go b/test/e2e/restart_test.go index b3052623b..9df884292 100644 --- a/test/e2e/restart_test.go +++ b/test/e2e/restart_test.go @@ -1,6 +1,8 @@ package integration import ( + "fmt" + "io/ioutil" "os" "time" @@ -33,13 +35,13 @@ var _ = Describe("Podman restart", func() { }) - It("Podman restart bogus container", func() { + It("podman restart bogus container", func() { session := podmanTest.Podman([]string{"start", "123"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(125)) }) - It("Podman restart stopped container by name", func() { + It("podman restart stopped container by name", func() { _, exitCode, _ := podmanTest.RunLsContainer("test1") Expect(exitCode).To(Equal(0)) startTime := podmanTest.Podman([]string{"inspect", "--format='{{.State.StartedAt}}'", "test1"}) @@ -53,7 +55,7 @@ var _ = Describe("Podman restart", func() { Expect(restartTime.OutputToString()).To(Not(Equal(startTime.OutputToString()))) }) - It("Podman restart stopped container by ID", func() { + It("podman restart stopped container by ID", func() { session := podmanTest.Podman([]string{"create", ALPINE, "ls"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) @@ -73,7 +75,7 @@ var _ = Describe("Podman restart", func() { Expect(restartTime.OutputToString()).To(Not(Equal(startTime.OutputToString()))) }) - It("Podman restart running container", func() { + It("podman restart running container", func() { _ = podmanTest.RunTopContainer("test1") ok := WaitForContainer(podmanTest) Expect(ok).To(BeTrue()) @@ -88,7 +90,7 @@ var _ = Describe("Podman restart", func() { Expect(restartTime.OutputToString()).To(Not(Equal(startTime.OutputToString()))) }) - It("Podman container restart running container", func() { + It("podman container restart running container", func() { _ = podmanTest.RunTopContainer("test1") ok := WaitForContainer(podmanTest) Expect(ok).To(BeTrue()) @@ -103,7 +105,7 @@ var _ = Describe("Podman restart", func() { Expect(restartTime.OutputToString()).To(Not(Equal(startTime.OutputToString()))) }) - It("Podman restart multiple containers", func() { + It("podman restart multiple containers", func() { _, exitCode, _ := podmanTest.RunLsContainer("test1") Expect(exitCode).To(Equal(0)) @@ -121,7 +123,7 @@ var _ = Describe("Podman restart", func() { Expect(restartTime.OutputToStringArray()[1]).To(Not(Equal(startTime.OutputToStringArray()[1]))) }) - It("Podman restart the latest container", func() { + It("podman restart the latest container", func() { _, exitCode, _ := podmanTest.RunLsContainer("test1") Expect(exitCode).To(Equal(0)) @@ -144,7 +146,7 @@ var _ = Describe("Podman restart", func() { Expect(restartTime.OutputToStringArray()[1]).To(Not(Equal(startTime.OutputToStringArray()[1]))) }) - It("Podman restart non-stop container with short timeout", func() { + It("podman restart non-stop container with short timeout", func() { session := podmanTest.Podman([]string{"run", "-d", "--name", "test1", "--env", "STOPSIGNAL=SIGKILL", ALPINE, "sleep", "999"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) @@ -157,7 +159,7 @@ var _ = Describe("Podman restart", func() { Expect(timeSince).To(BeNumerically(">", 2*time.Second)) }) - It("Podman restart --all", func() { + It("podman restart --all", func() { _, exitCode, _ := podmanTest.RunLsContainer("test1") Expect(exitCode).To(Equal(0)) @@ -177,7 +179,7 @@ var _ = Describe("Podman restart", func() { Expect(restartTime.OutputToStringArray()[1]).To(Not(Equal(startTime.OutputToStringArray()[1]))) }) - It("Podman restart --all --running", func() { + It("podman restart --all --running", func() { _, exitCode, _ := podmanTest.RunLsContainer("test1") Expect(exitCode).To(Equal(0)) @@ -197,7 +199,7 @@ var _ = Describe("Podman restart", func() { Expect(restartTime.OutputToStringArray()[1]).To(Not(Equal(startTime.OutputToStringArray()[1]))) }) - It("Podman restart a container in a pod and hosts should not duplicated", func() { + It("podman restart a container in a pod and hosts should not duplicated", func() { // Fixes: https://github.com/containers/podman/issues/8921 _, ec, _ := podmanTest.CreatePod(map[string][]string{"--name": {"foobar99"}}) @@ -226,7 +228,7 @@ var _ = Describe("Podman restart", func() { Expect(beforeRestart.OutputToString()).To(Equal(afterRestart.OutputToString())) }) - It("podman restart --all", func() { + It("podman restart all stopped containers with --all", func() { session := podmanTest.RunTopContainer("") session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) @@ -247,4 +249,113 @@ var _ = Describe("Podman restart", func() { Expect(session).Should(Exit(0)) Expect(podmanTest.NumberOfContainersRunning()).To(Equal(2)) }) + + It("podman restart --cidfile", func() { + tmpDir, err := ioutil.TempDir("", "") + Expect(err).To(BeNil()) + tmpFile := tmpDir + "cid" + + defer os.RemoveAll(tmpDir) + + session := podmanTest.Podman([]string{"create", "--cidfile", tmpFile, ALPINE, "top"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + cid := session.OutputToStringArray()[0] + + session = podmanTest.Podman([]string{"start", cid}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + result := podmanTest.Podman([]string{"restart", "--cidfile", tmpFile}) + result.WaitWithDefaultTimeout() + Expect(result).Should(Exit(0)) + output := result.OutputToString() + Expect(output).To(ContainSubstring(cid)) + }) + + It("podman restart multiple --cidfile", func() { + tmpDir, err := ioutil.TempDir("", "") + Expect(err).To(BeNil()) + tmpFile1 := tmpDir + "cid-1" + tmpFile2 := tmpDir + "cid-2" + + defer os.RemoveAll(tmpDir) + + session := podmanTest.Podman([]string{"run", "--cidfile", tmpFile1, "-d", ALPINE, "top"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + cid1 := session.OutputToStringArray()[0] + Expect(podmanTest.NumberOfContainers()).To(Equal(1)) + + session = podmanTest.Podman([]string{"run", "--cidfile", tmpFile2, "-d", ALPINE, "top"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + cid2 := session.OutputToStringArray()[0] + Expect(podmanTest.NumberOfContainers()).To(Equal(2)) + + result := podmanTest.Podman([]string{"restart", "--cidfile", tmpFile1, "--cidfile", tmpFile2}) + result.WaitWithDefaultTimeout() + Expect(result).Should(Exit(0)) + output := result.OutputToString() + Expect(output).To(ContainSubstring(cid1)) + Expect(output).To(ContainSubstring(cid2)) + Expect(podmanTest.NumberOfContainers()).To(Equal(2)) + }) + + It("podman restart invalid --latest and --cidfile and --all", func() { + SkipIfRemote("--latest flag n/a") + result := podmanTest.Podman([]string{"restart", "--cidfile", "foobar", "--latest"}) + result.WaitWithDefaultTimeout() + Expect(result).Should(Exit(125)) + Expect(result.ErrorToString()).To(ContainSubstring("cannot be used together")) + result = podmanTest.Podman([]string{"restart", "--cidfile", "foobar", "--all"}) + result.WaitWithDefaultTimeout() + Expect(result).Should(Exit(125)) + Expect(result.ErrorToString()).To(ContainSubstring("cannot be used together")) + result = podmanTest.Podman([]string{"restart", "--cidfile", "foobar", "--all", "--latest"}) + result.WaitWithDefaultTimeout() + Expect(result).Should(Exit(125)) + Expect(result.ErrorToString()).To(ContainSubstring("cannot be used together")) + result = podmanTest.Podman([]string{"restart", "--latest", "--all"}) + result.WaitWithDefaultTimeout() + Expect(result).Should(Exit(125)) + Expect(result.ErrorToString()).To(ContainSubstring("cannot be used together")) + }) + + It("podman pause --filter", func() { + session1 := podmanTest.RunTopContainer("") + session1.WaitWithDefaultTimeout() + Expect(session1).Should(Exit(0)) + cid1 := session1.OutputToString() + + session1 = podmanTest.RunTopContainer("") + session1.WaitWithDefaultTimeout() + Expect(session1).Should(Exit(0)) + cid2 := session1.OutputToString() + + session1 = podmanTest.RunTopContainer("") + session1.WaitWithDefaultTimeout() + Expect(session1).Should(Exit(0)) + cid3 := session1.OutputToString() + shortCid3 := cid3[0:5] + + session1 = podmanTest.Podman([]string{"restart", cid1, "-f", "status=test"}) + session1.WaitWithDefaultTimeout() + Expect(session1).Should(Exit(125)) + + session1 = podmanTest.Podman([]string{"restart", "-a", "--filter", fmt.Sprintf("id=%swrongid", shortCid3)}) + session1.WaitWithDefaultTimeout() + Expect(session1).Should(Exit(0)) + Expect(session1.OutputToString()).To(HaveLen(0)) + + session1 = podmanTest.Podman([]string{"restart", "-a", "--filter", fmt.Sprintf("id=%s", shortCid3)}) + session1.WaitWithDefaultTimeout() + Expect(session1).Should(Exit(0)) + Expect(session1.OutputToString()).To(BeEquivalentTo(cid3)) + + session1 = podmanTest.Podman([]string{"restart", "-f", fmt.Sprintf("id=%s", cid2)}) + session1.WaitWithDefaultTimeout() + Expect(session1).Should(Exit(0)) + Expect(session1.OutputToString()).To(BeEquivalentTo(cid2)) + }) }) diff --git a/test/e2e/run_env_test.go b/test/e2e/run_env_test.go index bab52efc5..2b2d67f57 100644 --- a/test/e2e/run_env_test.go +++ b/test/e2e/run_env_test.go @@ -58,6 +58,13 @@ var _ = Describe("Podman run", func() { Expect(session).Should(Exit(0)) Expect(session.OutputToString()).To(ContainSubstring("/bin")) + // Verify environ keys with spaces do not blow up podman command + os.Setenv("FOO BAR", "BAZ") + session = podmanTest.Podman([]string{"run", "--rm", ALPINE, "true"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + os.Unsetenv("FOO BAR") + os.Setenv("FOO", "BAR") session = podmanTest.Podman([]string{"run", "--rm", "--env", "FOO", ALPINE, "printenv", "FOO"}) session.WaitWithDefaultTimeout() @@ -82,6 +89,17 @@ var _ = Describe("Podman run", func() { Expect(session.OutputToString()).To(ContainSubstring("HOSTNAME")) }) + It("podman run with --env-merge", func() { + dockerfile := `FROM quay.io/libpod/alpine:latest +ENV hello=world +` + podmanTest.BuildImage(dockerfile, "test", "false") + session := podmanTest.Podman([]string{"run", "--rm", "--env-merge", "hello=${hello}-earth", "test", "env"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(ContainSubstring("world-earth")) + }) + It("podman run --env-host environment test", func() { env := append(os.Environ(), "FOO=BAR") session := podmanTest.PodmanAsUser([]string{"run", "--rm", "--env-host", ALPINE, "/bin/printenv", "FOO"}, 0, 0, "", env) diff --git a/test/e2e/run_memory_test.go b/test/e2e/run_memory_test.go index 083020f08..3f611040b 100644 --- a/test/e2e/run_memory_test.go +++ b/test/e2e/run_memory_test.go @@ -66,6 +66,24 @@ var _ = Describe("Podman run memory", func() { Expect(session.OutputToString()).To(Equal("41943040")) }) + It("podman run memory-swap test", func() { + var ( + session *PodmanSessionIntegration + expect string + ) + + if CGROUPSV2 { + session = podmanTest.Podman([]string{"run", "--memory=20m", "--memory-swap=30M", "--net=none", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/memory.swap.max"}) + expect = "10485760" + } else { + session = podmanTest.Podman([]string{"run", "--memory=20m", "--memory-swap=30M", ALPINE, "cat", "/sys/fs/cgroup/memory/memory.memsw.limit_in_bytes"}) + expect = "31457280" + } + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(Equal(expect)) + }) + for _, limit := range []string{"0", "15", "100"} { limit := limit // Keep this value in a proper scope testName := fmt.Sprintf("podman run memory-swappiness test(%s)", limit) diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index c7a0b3f2b..1f6b6fa3d 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -1235,9 +1235,8 @@ USER mail`, BB) }) It("podman run --mount type=bind,bind-nonrecursive", func() { - // crun: mount `/` to `/host`: Invalid argument - SkipIfRootless("FIXME: rootless users are not allowed to mount bind-nonrecursive (Could this be a Kernel bug?") - session := podmanTest.Podman([]string{"run", "--mount", "type=bind,bind-nonrecursive,slave,src=/,target=/host", fedoraMinimal, "findmnt", "-nR", "/host"}) + SkipIfRootless("FIXME: rootless users are not allowed to mount bind-nonrecursive") + session := podmanTest.Podman([]string{"run", "--mount", "type=bind,bind-nonrecursive,private,src=/sys,target=/host-sys", fedoraMinimal, "findmnt", "-nR", "/host-sys"}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) Expect(session.OutputToStringArray()).To(HaveLen(1)) diff --git a/test/e2e/run_userns_test.go b/test/e2e/run_userns_test.go index f247b2dac..62e512d3a 100644 --- a/test/e2e/run_userns_test.go +++ b/test/e2e/run_userns_test.go @@ -8,6 +8,7 @@ import ( "strings" . "github.com/containers/podman/v4/test/utils" + "github.com/containers/storage" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" . "github.com/onsi/gomega/gexec" @@ -42,6 +43,33 @@ var _ = Describe("Podman UserNS support", func() { }) + // Note: Lot of tests for build with --userns=auto are already there in buildah + // but they are skipped in podman CI because bud tests are executed in rootfull + // environment ( where mappings for the `containers` user is not present in /etc/subuid ) + // causing them to skip hence this is a redundant test for sanity to make sure + // we don't break this feature for podman-remote. + It("podman build with --userns=auto", func() { + u, err := user.Current() + Expect(err).To(BeNil()) + name := u.Name + if name == "root" { + name = "containers" + } + content, err := ioutil.ReadFile("/etc/subuid") + if err != nil { + Skip("cannot read /etc/subuid") + } + if !strings.Contains(string(content), name) { + Skip("cannot find mappings for the current user") + } + session := podmanTest.Podman([]string{"build", "-f", "build/Containerfile.userns-auto", "-t", "test", "--userns=auto"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + // `1024` is the default size or length of the range of user IDs + // that is mapped between the two user namespaces by --userns=auto. + Expect(session.OutputToString()).To(ContainSubstring(fmt.Sprintf("%d", storage.AutoUserNsMinSize))) + }) + It("podman uidmapping and gidmapping", func() { session := podmanTest.Podman([]string{"run", "--uidmap=0:100:5000", "--gidmap=0:200:5000", "alpine", "echo", "hello"}) session.WaitWithDefaultTimeout() @@ -157,6 +185,8 @@ var _ = Describe("Podman UserNS support", func() { session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) l := session.OutputToString() + // `1024` is the default size or length of the range of user IDs + // that is mapped between the two user namespaces by --userns=auto. Expect(l).To(ContainSubstring("1024")) m[l] = l } diff --git a/test/e2e/secret_test.go b/test/e2e/secret_test.go index ed328d84a..c6d5e6391 100644 --- a/test/e2e/secret_test.go +++ b/test/e2e/secret_test.go @@ -40,7 +40,7 @@ var _ = Describe("Podman secret", func() { err := ioutil.WriteFile(secretFilePath, []byte("mysecret"), 0755) Expect(err).To(BeNil()) - session := podmanTest.Podman([]string{"secret", "create", "--driver-opts", "opt1=val", "a", secretFilePath}) + session := podmanTest.Podman([]string{"secret", "create", "-d", "file", "--driver-opts", "opt1=val", "a", secretFilePath}) session.WaitWithDefaultTimeout() secrID := session.OutputToString() Expect(session).Should(Exit(0)) @@ -49,7 +49,7 @@ var _ = Describe("Podman secret", func() { inspect.WaitWithDefaultTimeout() Expect(inspect).Should(Exit(0)) Expect(inspect.OutputToString()).To(Equal(secrID)) - inspect = podmanTest.Podman([]string{"secret", "inspect", "--format", "{{.Spec.Driver.Options}}", secrID}) + inspect = podmanTest.Podman([]string{"secret", "inspect", "-f", "{{.Spec.Driver.Options}}", secrID}) inspect.WaitWithDefaultTimeout() Expect(inspect).Should(Exit(0)) Expect(inspect.OutputToString()).To(ContainSubstring("opt1:val")) @@ -145,6 +145,36 @@ var _ = Describe("Podman secret", func() { }) + It("podman secret ls --quiet", func() { + secretFilePath := filepath.Join(podmanTest.TempDir, "secret") + err := ioutil.WriteFile(secretFilePath, []byte("mysecret"), 0755) + Expect(err).To(BeNil()) + + secretName := "a" + + session := podmanTest.Podman([]string{"secret", "create", secretName, secretFilePath}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + secretID := session.OutputToString() + + list := podmanTest.Podman([]string{"secret", "ls", "-q"}) + list.WaitWithDefaultTimeout() + Expect(list).Should(Exit(0)) + Expect(list.OutputToString()).To(Equal(secretID)) + + list = podmanTest.Podman([]string{"secret", "ls", "--quiet"}) + list.WaitWithDefaultTimeout() + Expect(list).Should(Exit(0)) + Expect(list.OutputToString()).To(Equal(secretID)) + + // Prefer format over quiet + list = podmanTest.Podman([]string{"secret", "ls", "-q", "--format", "{{.Name}}"}) + list.WaitWithDefaultTimeout() + Expect(list).Should(Exit(0)) + Expect(list.OutputToString()).To(Equal(secretName)) + + }) + It("podman secret ls with filters", func() { secretFilePath := filepath.Join(podmanTest.TempDir, "secret") err := ioutil.WriteFile(secretFilePath, []byte("mysecret"), 0755) diff --git a/test/e2e/stats_test.go b/test/e2e/stats_test.go index 3000a819f..981c00316 100644 --- a/test/e2e/stats_test.go +++ b/test/e2e/stats_test.go @@ -79,9 +79,10 @@ var _ = Describe("Podman stats", func() { session := podmanTest.RunTopContainer("") session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) - session = podmanTest.Podman([]string{"stats", "--all", "--no-stream", "--format", "\"{{.ID}}\""}) + session = podmanTest.Podman([]string{"stats", "--all", "--no-trunc", "--no-stream", "--format", "\"{{.ID}}\""}) session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) + Expect(len(session.OutputToStringArray()[0])).Should(BeEquivalentTo(66)) }) It("podman stats with GO template", func() { diff --git a/test/e2e/top_test.go b/test/e2e/top_test.go index 66bb887dc..5f51742d1 100644 --- a/test/e2e/top_test.go +++ b/test/e2e/top_test.go @@ -133,4 +133,15 @@ var _ = Describe("Podman top", func() { Expect(result).Should(Exit(125)) }) + It("podman top on privileged container", func() { + session := podmanTest.Podman([]string{"run", "--privileged", "-d", ALPINE, "top"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + cid := session.OutputToString() + + result := podmanTest.Podman([]string{"top", cid, "capeff"}) + result.WaitWithDefaultTimeout() + Expect(result).Should(Exit(0)) + Expect(result.OutputToStringArray()).To(Equal([]string{"EFFECTIVE CAPS", "full"})) + }) }) diff --git a/test/e2e/volume_create_test.go b/test/e2e/volume_create_test.go index 7a975f6a5..499283cab 100644 --- a/test/e2e/volume_create_test.go +++ b/test/e2e/volume_create_test.go @@ -162,19 +162,4 @@ var _ = Describe("Podman volume create", func() { Expect(inspectOpts).Should(Exit(0)) Expect(inspectOpts.OutputToString()).To(Equal(optionStrFormatExpect)) }) - - It("podman create volume with o=timeout", func() { - volName := "testVol" - timeout := 10 - timeoutStr := "10" - session := podmanTest.Podman([]string{"volume", "create", "--opt", fmt.Sprintf("o=timeout=%d", timeout), volName}) - session.WaitWithDefaultTimeout() - Expect(session).Should(Exit(0)) - - inspectTimeout := podmanTest.Podman([]string{"volume", "inspect", "--format", "{{ .Timeout }}", volName}) - inspectTimeout.WaitWithDefaultTimeout() - Expect(inspectTimeout).Should(Exit(0)) - Expect(inspectTimeout.OutputToString()).To(Equal(timeoutStr)) - - }) }) diff --git a/test/e2e/volume_plugin_test.go b/test/e2e/volume_plugin_test.go index b585f8dd8..a44e75a54 100644 --- a/test/e2e/volume_plugin_test.go +++ b/test/e2e/volume_plugin_test.go @@ -256,4 +256,38 @@ Removed: Expect(session.OutputToStringArray()).To(ContainElements(localvol, vol2)) Expect(session.ErrorToString()).To(Equal("")) // make no errors are shown }) + + It("volume driver timeouts test", func() { + podmanTest.AddImageToRWStore(volumeTest) + + pluginStatePath := filepath.Join(podmanTest.TempDir, "volumes") + err := os.Mkdir(pluginStatePath, 0755) + Expect(err).ToNot(HaveOccurred()) + + // Keep this distinct within tests to avoid multiple tests using the same plugin. + pluginName := "testvol6" + plugin := podmanTest.Podman([]string{"run", "--security-opt", "label=disable", "-v", "/run/docker/plugins:/run/docker/plugins", "-v", fmt.Sprintf("%v:%v", pluginStatePath, pluginStatePath), "-d", volumeTest, "--sock-name", pluginName, "--path", pluginStatePath}) + plugin.WaitWithDefaultTimeout() + Expect(plugin).Should(Exit(0)) + + volName := "testVolume1" + create := podmanTest.Podman([]string{"volume", "create", "--driver", pluginName, volName}) + create.WaitWithDefaultTimeout() + Expect(create).Should(Exit(0)) + + volInspect := podmanTest.Podman([]string{"volume", "inspect", "--format", "{{ .Timeout }}", volName}) + volInspect.WaitWithDefaultTimeout() + Expect(volInspect).Should(Exit(0)) + Expect(volInspect.OutputToString()).To(ContainSubstring("15")) + + volName2 := "testVolume2" + create2 := podmanTest.Podman([]string{"volume", "create", "--driver", pluginName, "--opt", "o=timeout=3", volName2}) + create2.WaitWithDefaultTimeout() + Expect(create2).Should(Exit(0)) + + volInspect2 := podmanTest.Podman([]string{"volume", "inspect", "--format", "{{ .Timeout }}", volName2}) + volInspect2.WaitWithDefaultTimeout() + Expect(volInspect2).Should(Exit(0)) + Expect(volInspect2.OutputToString()).To(ContainSubstring("3")) + }) }) diff --git a/test/system/030-run.bats b/test/system/030-run.bats index 908c169ee..a3bfe5780 100644 --- a/test/system/030-run.bats +++ b/test/system/030-run.bats @@ -56,7 +56,12 @@ echo $rand | 0 | $rand @test "podman run --memory=0 runtime option" { run_podman run --memory=0 --rm $IMAGE echo hello - is "$output" "hello" "failed to run when --memory is set to 0" + if is_rootless && ! is_cgroupsv2; then + is "${lines[0]}" "Resource limits are not supported and ignored on cgroups V1 rootless systems" "--memory is not supported" + is "${lines[1]}" "hello" "--memory is ignored" + else + is "$output" "hello" "failed to run when --memory is set to 0" + fi } # 'run --preserve-fds' passes a number of additional file descriptors into the container diff --git a/test/system/200-pod.bats b/test/system/200-pod.bats index b1b9ee5e1..e3a9ec4c3 100644 --- a/test/system/200-pod.bats +++ b/test/system/200-pod.bats @@ -61,7 +61,7 @@ function teardown() { @test "podman pod create - custom infra image" { - skip_if_remote "CONTAINERS_CONF only effects server side" + skip_if_remote "CONTAINERS_CONF only affects server side" image="i.do/not/exist:image" tmpdir=$PODMAN_TMPDIR/pod-test mkdir -p $tmpdir @@ -478,7 +478,6 @@ spec: } @test "pod resource limits" { - # FIXME: #15074 - possible flake on aarch64 skip_if_remote "resource limits only implemented on non-remote" skip_if_rootless "resource limits only work with root" skip_if_cgroupsv1 "resource limits only meaningful on cgroups V2" @@ -493,30 +492,24 @@ spec: lomajmin=$(losetup -l --noheadings --output MAJ:MIN $LOOPDEVICE | tr -d ' ') run grep -w bfq /sys/block/$(basename ${LOOPDEVICE})/queue/scheduler if [ $status -ne 0 ]; then + losetup -d $LOOPDEVICE + LOOPDEVICE= skip "BFQ scheduler is not supported on the system" - if [ -f ${lofile} ]; then - run_podman '?' rm -t 0 --all --force --ignore - - while read path dev; do - if [[ "$path" == "$lofile" ]]; then - losetup -d $dev - fi - done < <(losetup -l --noheadings --output BACK-FILE,NAME) - rm ${lofile} - fi fi echo bfq > /sys/block/$(basename ${LOOPDEVICE})/queue/scheduler + # FIXME: #15464: blkio-weight-device not working expected_limits=" cpu.max | 500000 100000 memory.max | 5242880 memory.swap.max | 1068498944 +io.bfq.weight | default 50 io.max | $lomajmin rbps=1048576 wbps=1048576 riops=max wiops=max " for cgm in systemd cgroupfs; do local name=resources-$cgm - run_podman --cgroup-manager=$cgm pod create --name=$name --cpus=5 --memory=5m --memory-swap=1g --cpu-shares=1000 --cpuset-cpus=0 --cpuset-mems=0 --device-read-bps=${LOOPDEVICE}:1mb --device-write-bps=${LOOPDEVICE}:1mb --blkio-weight-device=${LOOPDEVICE}:123 --blkio-weight=50 + run_podman --cgroup-manager=$cgm pod create --name=$name --cpus=5 --memory=5m --memory-swap=1g --cpu-shares=1000 --cpuset-cpus=0 --cpuset-mems=0 --device-read-bps=${LOOPDEVICE}:1mb --device-write-bps=${LOOPDEVICE}:1mb --blkio-weight=50 run_podman --cgroup-manager=$cgm pod start $name run_podman pod inspect --format '{{.CgroupPath}}' $name local cgroup_path="$output" diff --git a/test/system/272-system-connection.bats b/test/system/272-system-connection.bats index e9e9a01ea..e937a7273 100644 --- a/test/system/272-system-connection.bats +++ b/test/system/272-system-connection.bats @@ -95,12 +95,12 @@ $c2[ ]\+tcp://localhost:54321[ ]\+true" \ # we need for the server. ${PODMAN%%-remote*} --root ${PODMAN_TMPDIR}/root \ --runroot ${PODMAN_TMPDIR}/runroot \ - system service -t 99 tcp:localhost:$_SERVICE_PORT & + system service -t 99 tcp://localhost:$_SERVICE_PORT & _SERVICE_PID=$! wait_for_port localhost $_SERVICE_PORT _run_podman_remote info --format '{{.Host.RemoteSocket.Path}}' - is "$output" "tcp:localhost:$_SERVICE_PORT" \ + is "$output" "tcp://localhost:$_SERVICE_PORT" \ "podman info works, and talks to the correct server" _run_podman_remote info --format '{{.Store.GraphRoot}}' diff --git a/test/system/700-play.bats b/test/system/700-play.bats index e1955cfd1..bad9544ff 100644 --- a/test/system/700-play.bats +++ b/test/system/700-play.bats @@ -361,3 +361,28 @@ status: {} run_podman pod rm -a run_podman rm -a } + +@test "podman kube play - URL" { + TESTDIR=$PODMAN_TMPDIR/testdir + mkdir -p $TESTDIR + echo "$testYaml" | sed "s|TESTDIR|${TESTDIR}|g" > $PODMAN_TMPDIR/test.yaml + + HOST_PORT=$(random_free_port) + SERVER=http://127.0.0.1:$HOST_PORT + + run_podman run -d --name myyaml -p "$HOST_PORT:80" \ + -v $PODMAN_TMPDIR/test.yaml:/var/www/testpod.yaml:Z \ + -w /var/www \ + $IMAGE /bin/busybox-extras httpd -f -p 80 + + run_podman kube play $SERVER/testpod.yaml + run_podman inspect test_pod-test --format "{{.State.Running}}" + is "$output" "true" + run_podman kube down $SERVER/testpod.yaml + run_podman 125 inspect test_pod-test + is "$output" ".*Error: inspecting object: no such object: \"test_pod-test\"" + + run_podman pod rm -a -f + run_podman rm -a -f + run_podman rm -f -t0 myyaml +} diff --git a/test/system/710-kube.bats b/test/system/710-kube.bats new file mode 100644 index 000000000..58e42148a --- /dev/null +++ b/test/system/710-kube.bats @@ -0,0 +1,171 @@ +#!/usr/bin/env bats -*- bats -*- +# +# Test podman kube generate +# + +load helpers + +# standard capability drop list +capabilities='{"drop":["CAP_MKNOD","CAP_NET_RAW","CAP_AUDIT_WRITE"]}' + +# Warning that is emitted once on containers, multiple times on pods +kubernetes_63='Truncation Annotation: .* Kubernetes only allows 63 characters' + +# filter: convert yaml to json, because bash+yaml=madness +function yaml2json() { + egrep -v "$kubernetes_63" | python3 -c 'import yaml +import json +import sys +json.dump(yaml.safe_load(sys.stdin), sys.stdout)' +} + +############################################################################### +# BEGIN tests + +@test "podman kube generate - usage message" { + run_podman kube generate --help + is "$output" ".*podman.* kube generate \[options\] {CONTAINER...|POD...|VOLUME...}" + run_podman generate kube --help + is "$output" ".*podman.* generate kube \[options\] {CONTAINER...|POD...|VOLUME...}" +} + +@test "podman kube generate - container" { + cname=c$(random_string 15) + run_podman container create --name $cname $IMAGE top + run_podman kube generate $cname + + # Convert yaml to json, and dump to stdout (to help in case of errors) + json=$(yaml2json <<<"$output") + jq . <<<"$json" + + # What we expect to see. This is by necessity an incomplete list. + # For instance, it does not include org.opencontainers.image.base.* + # because sometimes we get that, sometimes we don't. No clue why. + # + # And, unfortunately, if new fields are added to the YAML, we won't + # test those unless a developer remembers to add them here. + # + # Reasons for doing it this way, instead of straight-comparing yaml: + # 1) the arbitrariness of the org.opencontainers.image.base annotations + # 2) YAML order is nondeterministic, so on a pod with two containers + # (as in the pod test below) we cannot rely on cname1/cname2. + expect=" +apiVersion | = | v1 +kind | = | Pod + +metadata.annotations.\"io.kubernetes.cri-o.TTY/$cname\" | = | false +metadata.annotations.\"io.podman.annotations.autoremove/$cname\" | = | FALSE +metadata.annotations.\"io.podman.annotations.init/$cname\" | = | FALSE +metadata.annotations.\"io.podman.annotations.privileged/$cname\" | = | FALSE +metadata.annotations.\"io.podman.annotations.publish-all/$cname\" | = | FALSE + +metadata.creationTimestamp | =~ | [0-9T:-]\\+Z +metadata.labels.app | = | ${cname}-pod +metadata.name | = | ${cname}-pod + +spec.containers[0].command | = | [\"top\"] +spec.containers[0].image | = | $IMAGE +spec.containers[0].name | = | $cname + +spec.containers[0].securityContext.capabilities | = | $capabilities + +status | = | null +" + + # Parse and check all those + while read key op expect; do + actual=$(jq -r -c ".$key" <<<"$json") + assert "$actual" $op "$expect" ".$key" + done < <(parse_table "$expect") + + if ! is_remote; then + count=$(egrep -c "$kubernetes_63" <<<"$output") + assert "$count" = 1 "1 instance of the Kubernetes-63-char warning" + fi + + run_podman rm $cname +} + +@test "podman kube generate - pod" { + local pname=p$(random_string 15) + local cname1=c1$(random_string 15) + local cname2=c2$(random_string 15) + + run_podman pod create --name $pname --publish 9999:8888 + + # Needs at least one container. Error is slightly different between + # regular and remote podman: + # regular: Error: pod ... only has... + # remote: Error: error generating YAML: pod ... only has... + run_podman 125 kube generate $pname + assert "$output" =~ "Error: .* only has an infra container" + + run_podman container create --name $cname1 --pod $pname $IMAGE top + run_podman container create --name $cname2 --pod $pname $IMAGE bottom + run_podman kube generate $pname + + json=$(yaml2json <<<"$output") + jq . <<<"$json" + + # See container test above for description of this table + expect=" +apiVersion | = | v1 +kind | = | Pod + +metadata.annotations.\"io.kubernetes.cri-o.ContainerType/$cname1\" | = | container +metadata.annotations.\"io.kubernetes.cri-o.ContainerType/$cname2\" | = | container +metadata.annotations.\"io.kubernetes.cri-o.SandboxID/$cname1\" | =~ | [0-9a-f]\\{56\\} +metadata.annotations.\"io.kubernetes.cri-o.SandboxID/$cname2\" | =~ | [0-9a-f]\\{56\\} +metadata.annotations.\"io.kubernetes.cri-o.TTY/$cname1\" | = | false +metadata.annotations.\"io.kubernetes.cri-o.TTY/$cname2\" | = | false +metadata.annotations.\"io.podman.annotations.autoremove/$cname1\" | = | FALSE +metadata.annotations.\"io.podman.annotations.autoremove/$cname2\" | = | FALSE +metadata.annotations.\"io.podman.annotations.init/$cname1\" | = | FALSE +metadata.annotations.\"io.podman.annotations.init/$cname2\" | = | FALSE +metadata.annotations.\"io.podman.annotations.privileged/$cname1\" | = | FALSE +metadata.annotations.\"io.podman.annotations.privileged/$cname2\" | = | FALSE +metadata.annotations.\"io.podman.annotations.publish-all/$cname1\" | = | FALSE +metadata.annotations.\"io.podman.annotations.publish-all/$cname2\" | = | FALSE + +metadata.creationTimestamp | =~ | [0-9T:-]\\+Z +metadata.labels.app | = | ${pname} +metadata.name | = | ${pname} + +spec.hostname | = | $pname +spec.restartPolicy | = | Never + +spec.containers[0].command | = | [\"top\"] +spec.containers[0].image | = | $IMAGE +spec.containers[0].name | = | $cname1 +spec.containers[0].ports[0].containerPort | = | 8888 +spec.containers[0].ports[0].hostPort | = | 9999 +spec.containers[0].resources | = | {} + +spec.containers[1].command | = | [\"bottom\"] +spec.containers[1].image | = | $IMAGE +spec.containers[1].name | = | $cname2 +spec.containers[1].ports | = | null +spec.containers[1].resources | = | {} + +spec.containers[0].securityContext.capabilities | = | $capabilities + +status | = | {} +" + + while read key op expect; do + actual=$(jq -r -c ".$key" <<<"$json") + assert "$actual" $op "$expect" ".$key" + done < <(parse_table "$expect") + + # Why 4? Maybe two for each container? + if ! is_remote; then + count=$(egrep -c "$kubernetes_63" <<<"$output") + assert "$count" = 4 "instances of the Kubernetes-63-char warning" + fi + + run_podman rm $cname1 $cname2 + run_podman pod rm $pname + run_podman rmi $(pause_image) +} + +# vim: filetype=sh diff --git a/test/system/900-ssh.bats b/test/system/900-ssh.bats index 0757f5838..4f1682d48 100644 --- a/test/system/900-ssh.bats +++ b/test/system/900-ssh.bats @@ -46,7 +46,7 @@ function _run_podman_remote() { ${PODMAN%%-remote*} --root ${PODMAN_TMPDIR}/root \ --runroot ${PODMAN_TMPDIR}/runroot \ - system service -t 99 tcp:localhost:$_SERVICE_PORT & + system service -t 99 tcp://localhost:$_SERVICE_PORT & _SERVICE_PID=$! wait_for_port localhost $_SERVICE_PORT diff --git a/test/system/helpers.bash b/test/system/helpers.bash index 5ff3fae6d..f2eb3016c 100644 --- a/test/system/helpers.bash +++ b/test/system/helpers.bash @@ -36,20 +36,6 @@ fi # That way individual tests can override with their own setup/teardown, # while retaining the ability to include these if they so desire. -# Some CI systems set this to runc, overriding the default crun. -if [[ -n $OCI_RUNTIME ]]; then - if [[ -z $CONTAINERS_CONF ]]; then - # FIXME: BATS provides no mechanism for end-of-run cleanup[1]; how - # can we avoid leaving this file behind when we finish? - # [1] https://github.com/bats-core/bats-core/issues/39 - export CONTAINERS_CONF=$(mktemp --tmpdir=${BATS_TMPDIR:-/tmp} podman-bats-XXXXXXX.containers.conf) - cat >$CONTAINERS_CONF <<EOF -[engine] -runtime="$OCI_RUNTIME" -EOF - fi -fi - # Setup helper: establish a test environment with exactly the images needed function basic_setup() { # Clean up all containers diff --git a/test/testvol/util.go b/test/testvol/util.go index b50bb3afb..b4961e097 100644 --- a/test/testvol/util.go +++ b/test/testvol/util.go @@ -25,5 +25,5 @@ func getPluginName(pathOrName string) string { func getPlugin(sockNameOrPath string) (*plugin.VolumePlugin, error) { path := getSocketPath(sockNameOrPath) name := getPluginName(sockNameOrPath) - return plugin.GetVolumePlugin(name, path, 0) + return plugin.GetVolumePlugin(name, path, nil, nil) } |