aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/README.md2
-rw-r--r--test/apiv2/10-images.at32
-rw-r--r--test/apiv2/12-imagesMore.at10
-rw-r--r--test/apiv2/20-containers.at57
-rw-r--r--test/apiv2/23-containersArchive.at99
-rw-r--r--test/apiv2/26-containersWait.at39
-rw-r--r--test/apiv2/40-pods.at16
-rw-r--r--test/apiv2/45-system.at18
-rw-r--r--test/apiv2/70-short-names.at16
-rw-r--r--test/apiv2/README.md12
-rw-r--r--test/apiv2/python/rest_api/fixtures/api_testcase.py2
-rw-r--r--test/apiv2/python/rest_api/test_v2_0_0_container.py2
-rw-r--r--test/apiv2/python/rest_api/v1_test_rest_v1_0_0.py2
-rwxr-xr-xtest/apiv2/test-apiv296
-rwxr-xr-xtest/buildah-bud/apply-podman-deltas13
-rw-r--r--test/buildah-bud/buildah-tests.diff18
-rw-r--r--test/buildah-bud/make-new-buildah-diffs2
-rwxr-xr-xtest/compose/test-compose6
-rw-r--r--test/e2e/benchmarks_test.go2
-rw-r--r--test/e2e/build/Containerfile.userns-auto2
-rw-r--r--test/e2e/checkpoint_test.go40
-rw-r--r--test/e2e/cleanup_test.go128
-rw-r--r--test/e2e/common_test.go8
-rw-r--r--test/e2e/config/containers.conf2
-rw-r--r--test/e2e/config_amd64.go2
-rw-r--r--test/e2e/config_arm64.go2
-rw-r--r--test/e2e/container_clone_test.go17
-rw-r--r--test/e2e/container_create_volume_test.go2
-rw-r--r--test/e2e/create_staticmac_test.go2
-rw-r--r--test/e2e/create_test.go4
-rw-r--r--test/e2e/diff_test.go10
-rw-r--r--test/e2e/events_test.go22
-rw-r--r--test/e2e/generate_kube_test.go104
-rw-r--r--test/e2e/generate_spec_test.go82
-rw-r--r--test/e2e/generate_systemd_test.go109
-rw-r--r--test/e2e/healthcheck_run_test.go6
-rw-r--r--test/e2e/image_scp_test.go5
-rw-r--r--test/e2e/image_sign_test.go3
-rw-r--r--test/e2e/init_test.go10
-rw-r--r--test/e2e/login_logout_test.go14
-rw-r--r--test/e2e/logs_test.go2
-rw-r--r--test/e2e/manifest_test.go58
-rw-r--r--test/e2e/mount_rootless_test.go22
-rw-r--r--test/e2e/network_connect_disconnect_test.go42
-rw-r--r--test/e2e/network_create_test.go46
-rw-r--r--test/e2e/network_test.go40
-rw-r--r--test/e2e/play_kube_test.go94
-rw-r--r--test/e2e/pod_inspect_test.go17
-rw-r--r--test/e2e/pod_ps_test.go6
-rw-r--r--test/e2e/pod_rm_test.go27
-rw-r--r--test/e2e/ps_test.go6
-rw-r--r--test/e2e/pull_test.go14
-rw-r--r--test/e2e/push_test.go52
-rw-r--r--test/e2e/restart_test.go135
-rw-r--r--test/e2e/rm_test.go65
-rw-r--r--test/e2e/rmi_test.go78
-rw-r--r--test/e2e/run_cleanup_test.go45
-rw-r--r--test/e2e/run_cpu_test.go16
-rw-r--r--test/e2e/run_env_test.go18
-rw-r--r--test/e2e/run_memory_test.go18
-rw-r--r--test/e2e/run_networking_test.go10
-rw-r--r--test/e2e/run_staticip_test.go9
-rw-r--r--test/e2e/run_test.go23
-rw-r--r--test/e2e/run_userns_test.go64
-rw-r--r--test/e2e/run_working_dir_test.go9
-rw-r--r--test/e2e/save_test.go3
-rw-r--r--test/e2e/secret_test.go50
-rw-r--r--test/e2e/sign/key.gpgbin1745 -> 1565 bytes
-rw-r--r--test/e2e/sign/policy.json6
-rw-r--r--test/e2e/sign/secret-key.ascbin3510 -> 2867 bytes
-rw-r--r--test/e2e/start_test.go59
-rw-r--r--test/e2e/stats_test.go3
-rw-r--r--test/e2e/stop_test.go17
-rw-r--r--test/e2e/testdata/sigstore-key.key11
-rw-r--r--test/e2e/testdata/sigstore-key.key.pass1
-rw-r--r--test/e2e/testdata/sigstore-key.pub4
-rw-r--r--test/e2e/testdata/sigstore-registries.d-fragment.yaml3
-rw-r--r--test/e2e/top_test.go11
-rw-r--r--test/e2e/update_test.go200
-rw-r--r--test/e2e/volume_create_test.go15
-rw-r--r--test/e2e/volume_exists_test.go4
-rw-r--r--test/e2e/volume_ls_test.go5
-rw-r--r--test/e2e/volume_plugin_test.go40
-rw-r--r--test/system/001-basic.bats75
-rw-r--r--test/system/010-images.bats6
-rw-r--r--test/system/015-help.bats10
-rw-r--r--test/system/030-run.bats9
-rw-r--r--test/system/035-logs.bats23
-rw-r--r--test/system/045-start.bats18
-rw-r--r--test/system/050-stop.bats16
-rw-r--r--test/system/055-rm.bats1
-rw-r--r--test/system/065-cp.bats4
-rw-r--r--test/system/070-build.bats2
-rw-r--r--test/system/090-events.bats78
-rw-r--r--test/system/150-login.bats2
-rw-r--r--test/system/160-volumes.bats4
-rw-r--r--test/system/200-pod.bats22
-rw-r--r--test/system/220-healthcheck.bats94
-rw-r--r--test/system/250-systemd.bats97
-rw-r--r--test/system/255-auto-update.bats108
-rw-r--r--test/system/260-sdnotify.bats153
-rw-r--r--test/system/272-system-connection.bats4
-rw-r--r--test/system/280-update.bats130
-rw-r--r--test/system/320-system-df.bats2
-rw-r--r--test/system/330-corrupt-images.bats2
-rw-r--r--test/system/400-unprivileged-access.bats4
-rw-r--r--test/system/410-selinux.bats2
-rw-r--r--test/system/420-cgroups.bats5
-rw-r--r--test/system/500-networking.bats14
-rw-r--r--test/system/520-checkpoint.bats19
-rw-r--r--test/system/610-format.bats184
-rw-r--r--test/system/700-play.bats40
-rw-r--r--test/system/710-kube.bats160
-rw-r--r--test/system/900-ssh.bats61
-rw-r--r--test/system/TODO.md2
-rw-r--r--test/system/helpers.bash109
-rw-r--r--test/system/helpers.systemd.bash14
-rw-r--r--test/testvol/main.go8
-rw-r--r--test/testvol/util.go2
-rw-r--r--test/upgrade/test-upgrade.bats4
-rw-r--r--test/utils/utils.go2
121 files changed, 3301 insertions, 555 deletions
diff --git a/test/README.md b/test/README.md
index 769bdbfd7..b44deadaf 100644
--- a/test/README.md
+++ b/test/README.md
@@ -1,4 +1,4 @@
-![PODMAN logo](../logo/podman-logo-source.svg)
+![PODMAN logo](https://raw.githubusercontent.com/containers/common/main/logos/podman-logo-full-vert.png)
# Test utils
Test utils provide common functions and structs for testing. It includes two structs:
* `PodmanTest`: Handle the *podman* command and other global resources like temporary
diff --git a/test/apiv2/10-images.at b/test/apiv2/10-images.at
index f03b95786..3ffc6f738 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
@@ -227,16 +227,36 @@ t GET libpod/images/quay.io/libpod/busybox:latest/exists 204
CONTAINERFILE_WITH_ERR_TAR="${TMPD}/containerfile.tar"
cat > $TMPD/containerfile << EOF
-FROM quay.io/fedora/fedora
+FROM $IMAGE
RUN echo 'some error' >&2
EOF
tar --format=posix -C $TMPD -cvf ${CONTAINERFILE_WITH_ERR_TAR} containerfile &> /dev/null
-t POST "build?q=1&dockerfile=containerfile" $CONTAINERFILE_WITH_ERR_TAR 200
-response_output=$(cat "$WORKDIR/curl.result.out")
-if [[ ${response_output} == *"some error"* ]];then
- _show_ok 0 "compat quiet build" "~ $response_output" "found output from stderr in API"
+t POST "/build?q=1&dockerfile=containerfile" $CONTAINERFILE_WITH_ERR_TAR 200
+if [[ $output == *"some error"* ]];then
+ _show_ok 0 "compat quiet build" "[should not contain 'some error']" "$output"
+else
+ _show_ok 1 "compat quiet build"
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 a8d9baef3..cc238e27e 100644
--- a/test/apiv2/20-containers.at
+++ b/test/apiv2/20-containers.at
@@ -98,6 +98,12 @@ else
fi
fi
+# max_usage is not set for cgroupv2
+if have_cgroupsv2; then
+ t GET libpod/containers/stats?containers='[$cid]' 200 \
+ .memory_stats.max_usage=null
+fi
+
t DELETE libpod/containers/$cid 200 .[0].Id=$cid
# Issue #14676: make sure the stats show the memory limit specified for the container
@@ -111,6 +117,17 @@ if root; then
podman rm -f $CTRNAME
fi
+# Issue #15765: make sure the memory limit is capped
+if root; then
+ CTRNAME=ctr-with-limit
+ podman run --name $CTRNAME -d -m 512m -v /tmp:/tmp $IMAGE top
+
+ t GET libpod/containers/$CTRNAME/stats?stream=false 200 \
+ .memory_stats.limit!=18446744073709552000
+
+ podman rm -f $CTRNAME
+fi
+
# Issue #6799: it should be possible to start a container, even w/o args.
t POST libpod/containers/create?name=test_noargs Image=${IMAGE} 201 \
.Id~[0-9a-f]\\{64\\}
@@ -309,7 +326,9 @@ t POST containers/create Image=${MultiTagName} 201 \
.Id~[0-9a-f]\\{64\\}
cid=$(jq -r '.Id' <<<"$output")
t GET containers/$cid/json 200 \
- .Image=${MultiTagName}
+ .Config.Image=${MultiTagName} \
+ .Image~sha256:[0-9a-f]\\{64\\}
+
t DELETE containers/$cid 204
t DELETE images/${MultiTagName} 200
# vim: filetype=sh
@@ -527,3 +546,39 @@ t GET containers/status-test/json 200 .State.Status="stopping"
sleep 3
t GET containers/status-test/json 200 .State.Status="exited"
+
+# test podman generate spec as input for the api
+cname=specgen$(random_string 10)
+podman create --name=$cname $IMAGE
+
+TMPD=$(mktemp -d podman-apiv2-test.build.XXXXXXXX)
+
+podman generate spec -f ${TMPD}/myspec.json -c $cname
+
+# Create a container based on that spec
+t POST libpod/containers/create ${TMPD}/myspec.json 201 \
+ .Id~[0-9a-f]\\{64\\}
+
+# Verify
+t GET libpod/containers/$cname/json 200 \
+ .ImageName=$IMAGE \
+ .Name=$cname
+
+if root; then
+ podman run -dt --name=updateCtr alpine
+ echo '{"Memory":{"Limit":500000}, "CPU":{"Shares":123}}' >${TMPD}/update.json
+ t POST libpod/containers/updateCtr/update ${TMPD}/update.json 201
+
+ # Verify
+ echo '{ "AttachStdout":true,"Cmd":["cat","/sys/fs/cgroup/cpu.weight"]}' >${TMPD}/exec.json
+ t POST containers/updateCtr/exec ${TMPD}/exec.json 201 .Id~[0-9a-f]\\{64\\}
+ eid=$(jq -r '.Id' <<<"$output")
+ # 002 is the byte length
+ t POST exec/$eid/start 200 $'\001\0025'
+
+ podman rm -f updateCtr
+fi
+
+rm -rf $TMPD
+
+podman container rm -fa
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 80724a8d9..0e0f1cb18 100644
--- a/test/apiv2/40-pods.at
+++ b/test/apiv2/40-pods.at
@@ -134,6 +134,20 @@ 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}/myspec.json -c specgen
+
+t POST libpod/pods/create ${TMPD}/myspec.json 201 \
+ .Id~[0-9a-f]\\{64\\}
+
+rm -rf $TMPD
+
+podman pod rm -fa
# vim: filetype=sh
diff --git a/test/apiv2/45-system.at b/test/apiv2/45-system.at
index 364b87c56..096df5516 100644
--- a/test/apiv2/45-system.at
+++ b/test/apiv2/45-system.at
@@ -25,6 +25,24 @@ t GET system/df 200 '.Volumes[0].Name=foo1'
t GET libpod/system/df 200 '.Volumes[0].VolumeName=foo1'
+# Verify that no containers reference the volume
+t GET system/df 200 '.Volumes[0].UsageData.RefCount=0'
+
+# Make a container using the volume
+podman pull $IMAGE &>/dev/null
+t POST containers/create Image=$IMAGE Volumes='{"/test":{}}' HostConfig='{"Binds":["foo1:/test"]}' 201 \
+ .Id~[0-9a-f]\\{64\\}
+cid=$(jq -r '.Id' <<<"$output")
+
+# Verify that one container references the volume
+t GET system/df 200 '.Volumes[0].UsageData.RefCount=1'
+
+# Remove the container
+t DELETE containers/$cid?v=true 204
+
+# Verify that no containers reference the volume
+t GET system/df 200 '.Volumes[0].UsageData.RefCount=0'
+
# Create two more volumes to test pruneing
t POST libpod/volumes/create \
Name=foo2 \
diff --git a/test/apiv2/70-short-names.at b/test/apiv2/70-short-names.at
index bd7f8e7bd..952dd2ad1 100644
--- a/test/apiv2/70-short-names.at
+++ b/test/apiv2/70-short-names.at
@@ -9,7 +9,7 @@ t POST "images/create?fromImage=quay.io/libpod/alpine:latest" 200 .error~null .s
# 14291 - let a short-name resolve to a *local* non Docker-Hub image.
t POST containers/create Image=alpine 201 .Id~[0-9a-f]\\{64\\}
cid=$(jq -r '.Id' <<<"$output")
-t GET containers/$cid/json 200 .Image="quay.io/libpod/alpine:latest"
+t GET containers/$cid/json 200 .Config.Image="quay.io/libpod/alpine:latest" .Image~sha256:[0-9a-f]\\{64\\}
podman rm -f $cid
########## TAG
@@ -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/test_v2_0_0_container.py b/test/apiv2/python/rest_api/test_v2_0_0_container.py
index a6cd93a1a..25596a9b7 100644
--- a/test/apiv2/python/rest_api/test_v2_0_0_container.py
+++ b/test/apiv2/python/rest_api/test_v2_0_0_container.py
@@ -359,8 +359,6 @@ class ContainerTestCase(APITestCase):
self.assertEqual(2000, out["HostConfig"]["MemorySwap"])
self.assertEqual(1000, out["HostConfig"]["Memory"])
-
-
def execute_process(cmd):
return subprocess.run(
cmd,
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..8132e6432 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
@@ -112,6 +107,22 @@ function is() {
_show_ok 0 "$testname" "$expect" "$actual"
}
+############
+# is_not # Simple disequality
+############
+function is_not() {
+ local actual=$1
+ local expect_not=$2
+ local testname=$3
+
+ if [ "$actual" != "$expect_not" ]; then
+ # On success, include expected value; this helps readers understand
+ _show_ok 1 "$testname!=$expect"
+ return
+ fi
+ _show_ok 0 "$testname" "!= $expect" "$actual"
+}
+
##########
# like # Compare, but allowing patterns
##########
@@ -135,7 +146,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 +232,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 +242,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;;
@@ -270,8 +272,8 @@ function t() {
esac
done
if [[ -z "$curl_args" ]]; then
- curl_args=(-d $(jsonify ${post_args[@]}))
- testname="$testname [${curl_args[@]}]"
+ curl_args=(-d $(jsonify ${post_args[*]}))
+ testname="$testname [${curl_args[*]}]"
fi
fi
@@ -301,6 +303,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,9 +323,20 @@ 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
- die "curl failure ($rc) on $url - cannot continue"
+ if [[ $rc -ne 0 ]]; then
+ die "curl failure ($rc) on $url - cannot continue. args=${curl_args[*]}"
fi
# Show returned headers (without trailing ^M or empty lines) in log file.
@@ -366,7 +384,7 @@ function t() {
# Special case: if response code does not match, dump the response body
# and skip all further subtests.
- if [[ $actual_code != $expected_code ]]; then
+ if [[ "$actual_code" != "$expected_code" ]]; then
echo -e "# response: $output"
for i; do
_show_ok skip "$testname: $i # skip - wrong return code"
@@ -375,7 +393,13 @@ function t() {
fi
for i; do
- if expr "$i" : "[^=~]\+=.*" >/dev/null; then
+ if expr "$i" : '[^\!]\+\!=.\+' >/dev/null; then
+ # Disequality on json field
+ json_field=$(expr "$i" : '\([^!]*\)!')
+ expect_not=$(expr "$i" : '[^\!]*\!=\(.*\)')
+ actual=$(jq -r "$json_field" <<<"$output")
+ is_not "$actual" "$expect_not" "$testname : $json_field"
+ elif expr "$i" : "[^=~]\+=.*" >/dev/null; then
# Exact match on json field
json_field=$(expr "$i" : "\([^=]*\)=")
expect=$(expr "$i" : '[^=]*=\(.*\)')
@@ -647,11 +671,11 @@ echo -e "collected ${#tests_to_run[@]} items\n"
start_service
-for i in ${tests_to_run[@]}; do
+for i in "${tests_to_run[@]}"; do
TEST_CONTEXT="[$(basename $i .at)]"
# Clear output from 'podman' helper
- >| $WORKDIR/output.log
+ truncate --size=0 $WORKDIR/output.log
source $i
done
diff --git a/test/buildah-bud/apply-podman-deltas b/test/buildah-bud/apply-podman-deltas
index 6578afc93..999f36bf9 100755
--- a/test/buildah-bud/apply-podman-deltas
+++ b/test/buildah-bud/apply-podman-deltas
@@ -152,6 +152,10 @@ errmsg "checking authfile: stat /tmp/nonexistent: no such file or directory" \
"Error: checking authfile: stat /tmp/nonexistent: no such file or directory" \
"bud with Containerfile should fail with nonexistent authfile"
+errmsg "cannot find Containerfile or Dockerfile" \
+ "no such file or directory" \
+ "bud-github-context-from-commit"
+
###############################################################################
# BEGIN tests that don't make sense under podman due to fundamental differences
@@ -216,7 +220,10 @@ skip_if_remote "--output option not implemented in podman-remote" \
"build with custom build output and output rootfs to tar" \
"build with custom build output and output rootfs to tar by pipe" \
"build with custom build output must fail for bad input" \
- "build with custom build output and output rootfs to tar with no additional step"
+ "build with custom build output and output rootfs to tar with no additional step" \
+ "build with custom build output for single-stage-cached and output rootfs to directory" \
+ "build with custom build output for multi-stage-cached and output rootfs to directory" \
+ "build with custom build output for multi-stage and output rootfs to directory"
# https://github.com/containers/podman/issues/14544
skip_if_remote "logfile not implemented on remote" "bud-logfile-with-split-logfile-by-platform"
@@ -228,6 +235,10 @@ skip_if_remote "envariables do not automatically work with -remote." \
skip_if_remote "FIXME FIXME FIXME: does this test make sense in remote?" \
"build-test with OCI prestart hook"
+# 2022-08-17 buildah PR 4190
+skip_if_remote "Explicit request in buildah PR 4190 to skip this on remote" \
+ "build: test race in updating image name while performing parallel commits"
+
###############################################################################
# BEGIN tests which are skipped due to actual podman or podman-remote bugs.
diff --git a/test/buildah-bud/buildah-tests.diff b/test/buildah-bud/buildah-tests.diff
index 399042240..bf119421e 100644
--- a/test/buildah-bud/buildah-tests.diff
+++ b/test/buildah-bud/buildah-tests.diff
@@ -1,4 +1,4 @@
-From 6508e3df2a129554fdf8336d8a6f0cdcc6fd4832 Mon Sep 17 00:00:00 2001
+From d22e44c8fb1c87afb90391188733f7ce8fea005d 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
@@ -9,10 +9,10 @@ Signed-off-by: Ed Santiago <santiago@redhat.com>
1 file changed, 67 insertions(+), 3 deletions(-)
diff --git a/tests/helpers.bash b/tests/helpers.bash
-index e3087063..178a486e 100644
+index 8cb93c3a..72c1c797 100644
--- a/tests/helpers.bash
+++ b/tests/helpers.bash
-@@ -51,6 +51,23 @@ EOF
+@@ -52,6 +52,23 @@ EOF
ROOTDIR_OPTS="--root ${TEST_SCRATCH_DIR}/root --runroot ${TEST_SCRATCH_DIR}/runroot --storage-driver ${STORAGE_DRIVER}"
BUILDAH_REGISTRY_OPTS="--registries-conf ${TEST_SOURCES}/registries.conf --registries-conf-dir ${TEST_SCRATCH_DIR}/registries.d --short-name-alias-conf ${TEST_SCRATCH_DIR}/cache/shortnames.conf"
PODMAN_REGISTRY_OPTS="--registries-conf ${TEST_SOURCES}/registries.conf"
@@ -36,7 +36,7 @@ index e3087063..178a486e 100644
}
function starthttpd() {
-@@ -94,6 +111,12 @@ function teardown_tests() {
+@@ -95,6 +112,12 @@ function teardown_tests() {
stop_git_daemon
stop_registry
@@ -49,7 +49,7 @@ index e3087063..178a486e 100644
# Workaround for #1991 - buildah + overlayfs leaks mount points.
# Many tests leave behind /var/tmp/.../root/overlay and sub-mounts;
# let's find those and clean them up, otherwise 'rm -rf' fails.
-@@ -186,6 +209,10 @@ function podman() {
+@@ -187,6 +210,10 @@ function podman() {
command ${PODMAN_BINARY:-podman} ${PODMAN_REGISTRY_OPTS} ${ROOTDIR_OPTS} "$@"
}
@@ -60,7 +60,7 @@ index e3087063..178a486e 100644
# There are various scenarios where we would like to execute `tests` as rootless user, however certain commands like `buildah mount`
# do not work in rootless session since a normal user cannot mount a filesystem unless they're in a user namespace along with its
# own mount namespace. In order to run such specific commands from a rootless session we must perform `buildah unshare`.
-@@ -247,8 +274,36 @@ function run_buildah() {
+@@ -248,8 +275,36 @@ function run_buildah() {
--retry) retry=3; shift;; # retry network flakes
esac
@@ -98,7 +98,7 @@ index e3087063..178a486e 100644
# If session is rootless and `buildah mount` is invoked, perform unshare,
# since normal user cannot mount a filesystem unless they're in a user namespace along with its own mount namespace.
-@@ -262,8 +317,8 @@ function run_buildah() {
+@@ -263,8 +318,8 @@ function run_buildah() {
retry=$(( retry - 1 ))
# stdout is only emitted upon error; this echo is to help a debugger
@@ -109,7 +109,7 @@ index e3087063..178a486e 100644
# without "quotes", multiple lines are glommed together into one
if [ -n "$output" ]; then
echo "$output"
-@@ -595,6 +650,15 @@ function skip_if_no_docker() {
+@@ -596,6 +651,15 @@ function skip_if_no_docker() {
fi
}
@@ -126,5 +126,5 @@ index e3087063..178a486e 100644
daemondir=${TEST_SCRATCH_DIR}/git-daemon
mkdir -p ${daemondir}/repo
--
-2.35.3
+2.36.1
diff --git a/test/buildah-bud/make-new-buildah-diffs b/test/buildah-bud/make-new-buildah-diffs
index 3d0a77008..f6404fa51 100644
--- a/test/buildah-bud/make-new-buildah-diffs
+++ b/test/buildah-bud/make-new-buildah-diffs
@@ -17,7 +17,7 @@ if [[ ! $whereami =~ test-buildah-v ]]; then
fi
# FIXME: check that git repo is buildah
-git remote -v | grep -q [BUILDAHREPO] \
+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
diff --git a/test/compose/test-compose b/test/compose/test-compose
index 99d063c25..fe2da9532 100755
--- a/test/compose/test-compose
+++ b/test/compose/test-compose
@@ -64,7 +64,7 @@ function is() {
local expect=$2
local testname=$3
- if [[ $actual = $expect ]]; then
+ if [[ "$actual" = "$expect" ]]; then
# On success, include expected value; this helps readers understand
_show_ok 1 "$testname=$expect"
return
@@ -303,12 +303,12 @@ n_tests=0
# We aren't really TAP 13; this helps logformatter recognize our output as BATS
echo "TAP version 13"
-for t in ${tests_to_run[@]}; do
+for t in "${tests_to_run[@]}"; do
testdir="$(dirname $t)"
testname="$(basename $testdir)"
if [ -e $test_dir/SKIP ]; then
- local reason="$(<$test_dir/SKIP)"
+ reason="$(<$test_dir/SKIP)"
if [ -n "$reason" ]; then
reason=" - $reason"
fi
diff --git a/test/e2e/benchmarks_test.go b/test/e2e/benchmarks_test.go
index 4be048de2..d1332665a 100644
--- a/test/e2e/benchmarks_test.go
+++ b/test/e2e/benchmarks_test.go
@@ -99,7 +99,7 @@ var _ = Describe("Podman Benchmark Suite", func() {
}
totalMemoryInKb := func() (total uint64) {
- files, err := ioutil.ReadDir(timedir)
+ files, err := os.ReadDir(timedir)
if err != nil {
Fail(fmt.Sprintf("Error reading timing dir: %v", err))
}
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/checkpoint_test.go b/test/e2e/checkpoint_test.go
index 8f5e1a0b6..a33936549 100644
--- a/test/e2e/checkpoint_test.go
+++ b/test/e2e/checkpoint_test.go
@@ -95,13 +95,15 @@ var _ = Describe("Podman checkpoint", func() {
It("podman checkpoint bogus container", func() {
session := podmanTest.Podman([]string{"container", "checkpoint", "foobar"})
session.WaitWithDefaultTimeout()
- Expect(session).To(ExitWithError())
+ Expect(session).Should(Exit(125))
+ Expect(session.ErrorToString()).To(ContainSubstring("no such container"))
})
It("podman restore bogus container", func() {
session := podmanTest.Podman([]string{"container", "restore", "foobar"})
session.WaitWithDefaultTimeout()
- Expect(session).To(ExitWithError())
+ Expect(session).Should(Exit(125))
+ Expect(session.ErrorToString()).To(ContainSubstring("no such container or image"))
})
It("podman checkpoint a running container by id", func() {
@@ -132,6 +134,7 @@ var _ = Describe("Podman checkpoint", func() {
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
+ Expect(result.OutputToString()).To(Equal(cid))
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
@@ -156,6 +159,7 @@ var _ = Describe("Podman checkpoint", func() {
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
+ Expect(result.OutputToString()).To(Equal(cid))
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
@@ -214,6 +218,7 @@ var _ = Describe("Podman checkpoint", func() {
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
+ Expect(result.OutputToString()).To(Equal("test_name"))
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
@@ -221,6 +226,7 @@ var _ = Describe("Podman checkpoint", func() {
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
+ Expect(result.OutputToString()).To(Equal("test_name"))
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
@@ -298,6 +304,7 @@ var _ = Describe("Podman checkpoint", func() {
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
+ Expect(result.OutputToString()).To(Equal("second"))
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
ps := podmanTest.Podman([]string{"ps", "-q", "--no-trunc"})
@@ -310,6 +317,7 @@ var _ = Describe("Podman checkpoint", func() {
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
+ Expect(result.OutputToString()).To(Equal("second"))
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(2))
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
Expect(podmanTest.GetContainerStatus()).To(Not(ContainSubstring("Exited")))
@@ -325,16 +333,20 @@ var _ = Describe("Podman checkpoint", func() {
session1 := podmanTest.Podman(localRunString)
session1.WaitWithDefaultTimeout()
Expect(session1).Should(Exit(0))
+ cid1 := session1.OutputToString()
localRunString = getRunString([]string{"--name", "second", ALPINE, "top"})
session2 := podmanTest.Podman(localRunString)
session2.WaitWithDefaultTimeout()
Expect(session2).Should(Exit(0))
+ cid2 := session2.OutputToString()
result := podmanTest.Podman([]string{"container", "checkpoint", "-a"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
+ Expect(result.OutputToString()).To(ContainSubstring(cid1))
+ Expect(result.OutputToString()).To(ContainSubstring(cid2))
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
ps := podmanTest.Podman([]string{"ps", "-q", "--no-trunc"})
@@ -347,6 +359,8 @@ var _ = Describe("Podman checkpoint", func() {
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
+ Expect(result.OutputToString()).To(ContainSubstring(cid1))
+ Expect(result.OutputToString()).To(ContainSubstring(cid2))
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(2))
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
Expect(podmanTest.GetContainerStatus()).To(Not(ContainSubstring("Exited")))
@@ -573,6 +587,7 @@ var _ = Describe("Podman checkpoint", func() {
// As the container has been started with '--rm' it will be completely
// cleaned up after checkpointing.
Expect(result).Should(Exit(0))
+ Expect(result.OutputToString()).To(ContainSubstring(cid))
fixmeFixme14653(podmanTest, cid)
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
@@ -592,6 +607,7 @@ var _ = Describe("Podman checkpoint", func() {
// As the container has been started with '--rm' it will be completely
// cleaned up after checkpointing.
Expect(result).Should(Exit(0))
+ Expect(result.OutputToString()).To(ContainSubstring(cid))
fixmeFixme14653(podmanTest, cid)
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
@@ -611,6 +627,7 @@ var _ = Describe("Podman checkpoint", func() {
// As the container has been started with '--rm' it will be completely
// cleaned up after checkpointing.
Expect(result).Should(Exit(0))
+ Expect(result.OutputToString()).To(ContainSubstring(cid))
fixmeFixme14653(podmanTest, cid)
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
@@ -630,6 +647,7 @@ var _ = Describe("Podman checkpoint", func() {
// As the container has been started with '--rm' it will be completely
// cleaned up after checkpointing.
Expect(result).Should(Exit(0))
+ Expect(result.OutputToString()).To(ContainSubstring(cid))
fixmeFixme14653(podmanTest, cid)
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
@@ -647,6 +665,7 @@ var _ = Describe("Podman checkpoint", func() {
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(125))
+ Expect(result.ErrorToString()).To(ContainSubstring("not supported"))
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
Expect(podmanTest.NumberOfContainers()).To(Equal(1))
@@ -692,6 +711,7 @@ var _ = Describe("Podman checkpoint", func() {
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
+ Expect(result.OutputToString()).To(ContainSubstring(cid))
fixmeFixme14653(podmanTest, cid)
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
@@ -742,6 +762,7 @@ var _ = Describe("Podman checkpoint", func() {
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
+ Expect(result.OutputToString()).To(ContainSubstring(cid))
fixmeFixme14653(podmanTest, cid)
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
@@ -784,6 +805,7 @@ var _ = Describe("Podman checkpoint", func() {
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
+ Expect(result.OutputToString()).To(ContainSubstring(cid))
fixmeFixme14653(podmanTest, cid)
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
@@ -822,6 +844,7 @@ var _ = Describe("Podman checkpoint", func() {
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
+ Expect(result.OutputToString()).To(ContainSubstring(cid))
fixmeFixme14653(podmanTest, cid)
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
@@ -872,6 +895,7 @@ var _ = Describe("Podman checkpoint", func() {
// As the container has been started with '--rm' it will be completely
// cleaned up after checkpointing.
Expect(result).Should(Exit(0))
+ Expect(result.OutputToString()).To(ContainSubstring(cid))
fixmeFixme14653(podmanTest, cid)
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
@@ -942,6 +966,7 @@ var _ = Describe("Podman checkpoint", func() {
result = podmanTest.Podman([]string{"container", "checkpoint", cid, "-e", checkpointFileName})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
+ Expect(result.OutputToString()).To(ContainSubstring(cid))
fixmeFixme14653(podmanTest, cid)
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
@@ -993,9 +1018,6 @@ var _ = Describe("Podman checkpoint", func() {
if !criu.MemTrack() {
Skip("system (architecture/kernel/CRIU) does not support memory tracking")
}
- if !strings.Contains(podmanTest.OCIRuntime, "runc") {
- Skip("Test only works on runc 1.0-rc3 or higher.")
- }
localRunString := getRunString([]string{ALPINE, "top"})
session := podmanTest.Podman(localRunString)
session.WaitWithDefaultTimeout()
@@ -1029,9 +1051,6 @@ var _ = Describe("Podman checkpoint", func() {
if !criu.MemTrack() {
Skip("system (architecture/kernel/CRIU) does not support memory tracking")
}
- if !strings.Contains(podmanTest.OCIRuntime, "runc") {
- Skip("Test only works on runc 1.0-rc3 or higher.")
- }
localRunString := getRunString([]string{ALPINE, "top"})
session := podmanTest.Podman(localRunString)
session.WaitWithDefaultTimeout()
@@ -1051,6 +1070,7 @@ var _ = Describe("Podman checkpoint", func() {
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
+ Expect(result.OutputToString()).To(ContainSubstring(cid))
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
@@ -1097,6 +1117,7 @@ var _ = Describe("Podman checkpoint", func() {
// As the container has been started with '--rm' it will be completely
// cleaned up after checkpointing.
Expect(result).Should(Exit(0))
+ Expect(result.OutputToString()).To(ContainSubstring(cid))
fixmeFixme14653(podmanTest, cid)
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
@@ -1311,6 +1332,7 @@ var _ = Describe("Podman checkpoint", func() {
// As the container has been started with '--rm' it will be completely
// cleaned up after checkpointing.
Expect(result).Should(Exit(0))
+ Expect(result.OutputToString()).To(ContainSubstring(cid))
fixmeFixme14653(podmanTest, cid)
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
@@ -1642,6 +1664,7 @@ var _ = Describe("Podman checkpoint", func() {
// As the container has been started with '--rm' it will be completely
// cleaned up after checkpointing.
Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).To(ContainSubstring(cid))
fixmeFixme14653(podmanTest, cid)
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
@@ -1796,6 +1819,7 @@ var _ = Describe("Podman checkpoint", func() {
// As the container has been started with '--rm' it will be completely
// cleaned up after checkpointing.
Expect(result).Should(Exit(0))
+ Expect(result.OutputToString()).To(ContainSubstring(cid))
fixmeFixme14653(podmanTest, cid)
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
diff --git a/test/e2e/cleanup_test.go b/test/e2e/cleanup_test.go
new file mode 100644
index 000000000..f15f9bd5a
--- /dev/null
+++ b/test/e2e/cleanup_test.go
@@ -0,0 +1,128 @@
+package integration
+
+import (
+ "os"
+
+ . "github.com/containers/podman/v4/test/utils"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+ . "github.com/onsi/gomega/gexec"
+)
+
+var _ = Describe("Podman container cleanup", func() {
+ var (
+ tempdir string
+ err error
+ podmanTest *PodmanTestIntegration
+ )
+
+ BeforeEach(func() {
+ SkipIfRemote("podman container cleanup is not supported in remote")
+ tempdir, err = CreateTempDirInTempDir()
+ if err != nil {
+ os.Exit(1)
+ }
+ podmanTest = PodmanTestCreate(tempdir)
+ podmanTest.Setup()
+ })
+
+ AfterEach(func() {
+ podmanTest.Cleanup()
+ f := CurrentGinkgoTestDescription()
+ processTestResult(f)
+
+ })
+
+ It("podman cleanup bogus container", func() {
+ session := podmanTest.Podman([]string{"container", "cleanup", "foobar"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(125))
+ Expect(session.ErrorToString()).To(ContainSubstring("no such container"))
+ })
+
+ It("podman cleanup container by id", func() {
+ session := podmanTest.Podman([]string{"create", ALPINE, "ls"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ cid := session.OutputToString()
+ session = podmanTest.Podman([]string{"container", "cleanup", cid})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).To(Equal(cid))
+ })
+
+ It("podman cleanup container by short id", func() {
+ session := podmanTest.Podman([]string{"create", ALPINE, "ls"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ cid := session.OutputToString()
+ shortID := cid[0:10]
+ session = podmanTest.Podman([]string{"container", "cleanup", shortID})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).To(Equal(shortID))
+ })
+
+ It("podman cleanup container by name", func() {
+ session := podmanTest.Podman([]string{"create", "--name", "foo", ALPINE, "ls"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ session = podmanTest.Podman([]string{"container", "cleanup", "foo"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).To(Equal("foo"))
+ })
+
+ It("podman cleanup all containers", func() {
+ session := podmanTest.Podman([]string{"create", ALPINE, "ls"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ cid := session.OutputToString()
+
+ session = podmanTest.Podman([]string{"container", "cleanup", "--all"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).To(Equal(cid))
+ })
+
+ It("podman cleanup latest container", func() {
+ SkipIfRemote("--latest flag n/a")
+ session := podmanTest.Podman([]string{"create", ALPINE, "ls"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ session = podmanTest.Podman([]string{"create", ALPINE, "ls"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ cid := session.OutputToString()
+
+ session = podmanTest.Podman([]string{"container", "cleanup", "--latest"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).To(Equal(cid))
+ })
+
+ It("podman cleanup running container", func() {
+ session := podmanTest.RunTopContainer("running")
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ session = podmanTest.Podman([]string{"container", "cleanup", "running"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(125))
+ Expect(session.ErrorToString()).To(ContainSubstring("container state improper"))
+ })
+
+ It("podman cleanup paused container", func() {
+ SkipIfRootlessCgroupsV1("Pause is not supported in cgroups v1")
+ session := podmanTest.RunTopContainer("paused")
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ session = podmanTest.Podman([]string{"pause", "paused"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ session = podmanTest.Podman([]string{"container", "cleanup", "paused"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(125))
+ Expect(session.ErrorToString()).To(ContainSubstring("container state improper"))
+ })
+})
diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go
index 2d7c47a7f..690e2f22c 100644
--- a/test/e2e/common_test.go
+++ b/test/e2e/common_test.go
@@ -306,7 +306,7 @@ func PodmanTestCreateUtil(tempDir string, remote bool) *PodmanTestIntegration {
// happens. So, use a podman-%s.sock-lock empty file as a marker.
tries := 0
for {
- uuid := stringid.GenerateNonCryptoID()
+ uuid := stringid.GenerateRandomID()
lockPath := fmt.Sprintf("%s-%s.sock-lock", pathPrefix, uuid)
lockFile, err := os.OpenFile(lockPath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0700)
if err == nil {
@@ -571,7 +571,7 @@ func (s *PodmanSessionIntegration) InspectContainerToJSON() []define.InspectCont
func (s *PodmanSessionIntegration) InspectPodToJSON() define.InspectPodData {
var i define.InspectPodData
err := jsoniter.Unmarshal(s.Out.Contents(), &i)
- Expect(err).To(BeNil())
+ Expect(err).ToNot(HaveOccurred())
return i
}
@@ -894,7 +894,7 @@ func generateNetworkConfig(p *PodmanTestIntegration) (string, string) {
conf string
)
// generate a random name to prevent conflicts with other tests
- name := "net" + stringid.GenerateNonCryptoID()
+ name := "net" + stringid.GenerateRandomID()
if p.NetworkBackend != Netavark {
path = filepath.Join(p.NetworkConfigDir, fmt.Sprintf("%s.conflist", name))
conf = fmt.Sprintf(`{
@@ -1030,7 +1030,7 @@ func ncz(port int) bool {
}
func createNetworkName(name string) string {
- return name + stringid.GenerateNonCryptoID()[:10]
+ return name + stringid.GenerateRandomID()[:10]
}
var IPRegex = `(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}`
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/config_amd64.go b/test/e2e/config_amd64.go
index f32542df8..ba7940d57 100644
--- a/test/e2e/config_amd64.go
+++ b/test/e2e/config_amd64.go
@@ -8,7 +8,7 @@ var (
CACHE_IMAGES = []string{ALPINE, BB, fedoraMinimal, NGINX_IMAGE, REDIS_IMAGE, REGISTRY_IMAGE, INFRA_IMAGE, LABELS_IMAGE, HEALTHCHECK_IMAGE, UBI_INIT, UBI_MINIMAL, fedoraToolbox} //nolint:revive,stylecheck
NGINX_IMAGE = "quay.io/libpod/alpine_nginx:latest" //nolint:revive,stylecheck
BB_GLIBC = "docker.io/library/busybox:glibc" //nolint:revive,stylecheck
- REGISTRY_IMAGE = "quay.io/libpod/registry:2.6" //nolint:revive,stylecheck
+ REGISTRY_IMAGE = "quay.io/libpod/registry:2.8" //nolint:revive,stylecheck
LABELS_IMAGE = "quay.io/libpod/alpine_labels:latest" //nolint:revive,stylecheck
UBI_MINIMAL = "registry.access.redhat.com/ubi8-minimal" //nolint:revive,stylecheck
UBI_INIT = "registry.access.redhat.com/ubi8-init" //nolint:revive,stylecheck
diff --git a/test/e2e/config_arm64.go b/test/e2e/config_arm64.go
index c1e0afc47..32ed2f90d 100644
--- a/test/e2e/config_arm64.go
+++ b/test/e2e/config_arm64.go
@@ -8,7 +8,7 @@ var (
CACHE_IMAGES = []string{ALPINE, BB, fedoraMinimal, NGINX_IMAGE, REDIS_IMAGE, REGISTRY_IMAGE, INFRA_IMAGE, LABELS_IMAGE, HEALTHCHECK_IMAGE, UBI_INIT, UBI_MINIMAL, fedoraToolbox} //nolint:revive,stylecheck
NGINX_IMAGE = "quay.io/lsm5/alpine_nginx-aarch64:latest" //nolint:revive,stylecheck
BB_GLIBC = "docker.io/library/busybox:glibc" //nolint:revive,stylecheck
- REGISTRY_IMAGE = "quay.io/libpod/registry:2.6" //nolint:revive,stylecheck
+ REGISTRY_IMAGE = "quay.io/libpod/registry:2.8" //nolint:revive,stylecheck
LABELS_IMAGE = "quay.io/libpod/alpine_labels:latest" //nolint:revive,stylecheck
UBI_MINIMAL = "registry.access.redhat.com/ubi8-minimal" //nolint:revive,stylecheck
UBI_INIT = "registry.access.redhat.com/ubi8-init" //nolint:revive,stylecheck
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/container_create_volume_test.go b/test/e2e/container_create_volume_test.go
index 6d9f13694..3c54691aa 100644
--- a/test/e2e/container_create_volume_test.go
+++ b/test/e2e/container_create_volume_test.go
@@ -58,7 +58,7 @@ func checkDataVolumeContainer(pTest *PodmanTestIntegration, image, cont, dest, d
Expect(volList.OutputToStringArray()[0]).To(Equal(mntName))
// Check the mount source directory
- files, err := ioutil.ReadDir(mntSource)
+ files, err := os.ReadDir(mntSource)
Expect(err).To(BeNil())
if data == "" {
diff --git a/test/e2e/create_staticmac_test.go b/test/e2e/create_staticmac_test.go
index 32deb04a8..f7ddfe50c 100644
--- a/test/e2e/create_staticmac_test.go
+++ b/test/e2e/create_staticmac_test.go
@@ -48,7 +48,7 @@ var _ = Describe("Podman run with --mac-address flag", func() {
})
It("Podman run --mac-address with custom network", func() {
- net := "n1" + stringid.GenerateNonCryptoID()
+ net := "n1" + stringid.GenerateRandomID()
session := podmanTest.Podman([]string{"network", "create", net})
session.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(net)
diff --git a/test/e2e/create_test.go b/test/e2e/create_test.go
index 9679aad24..d5920dc3e 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"
@@ -593,7 +595,7 @@ var _ = Describe("Podman create", func() {
pod.WaitWithDefaultTimeout()
Expect(pod).Should(Exit(0))
- netName := "pod" + stringid.GenerateNonCryptoID()
+ netName := "pod" + stringid.GenerateRandomID()
session := podmanTest.Podman([]string{"network", "create", netName})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
diff --git a/test/e2e/diff_test.go b/test/e2e/diff_test.go
index a1f57f41b..c7f235e29 100644
--- a/test/e2e/diff_test.go
+++ b/test/e2e/diff_test.go
@@ -93,9 +93,9 @@ var _ = Describe("Podman diff", func() {
})
It("podman image diff", func() {
- file1 := "/" + stringid.GenerateNonCryptoID()
- file2 := "/" + stringid.GenerateNonCryptoID()
- file3 := "/" + stringid.GenerateNonCryptoID()
+ file1 := "/" + stringid.GenerateRandomID()
+ file2 := "/" + stringid.GenerateRandomID()
+ file3 := "/" + stringid.GenerateRandomID()
// Create container image with the files
containerfile := fmt.Sprintf(`
@@ -152,8 +152,8 @@ RUN echo test
})
It("podman diff container and image with same name", func() {
- imagefile := "/" + stringid.GenerateNonCryptoID()
- confile := "/" + stringid.GenerateNonCryptoID()
+ imagefile := "/" + stringid.GenerateRandomID()
+ confile := "/" + stringid.GenerateRandomID()
// Create container image with the files
containerfile := fmt.Sprintf(`
diff --git a/test/e2e/events_test.go b/test/e2e/events_test.go
index 528fa143d..bba42c3f4 100644
--- a/test/e2e/events_test.go
+++ b/test/e2e/events_test.go
@@ -42,10 +42,7 @@ var _ = Describe("Podman events", func() {
// Perhaps a future version of this test would put events in a go func and send output back over a channel
// while events occur.
- // These tests are only known to work on Fedora ATM. Other distributions
- // will be skipped.
It("podman events", func() {
- SkipIfNotFedora()
_, ec, _ := podmanTest.RunLsContainer("")
Expect(ec).To(Equal(0))
result := podmanTest.Podman([]string{"events", "--stream=false"})
@@ -54,7 +51,6 @@ var _ = Describe("Podman events", func() {
})
It("podman events with an event filter", func() {
- SkipIfNotFedora()
_, ec, _ := podmanTest.RunLsContainer("")
Expect(ec).To(Equal(0))
result := podmanTest.Podman([]string{"events", "--stream=false", "--filter", "event=start"})
@@ -81,7 +77,6 @@ var _ = Describe("Podman events", func() {
})
It("podman events with a type and filter container=id", func() {
- SkipIfNotFedora()
_, ec, cid := podmanTest.RunLsContainer("")
Expect(ec).To(Equal(0))
result := podmanTest.Podman([]string{"events", "--stream=false", "--filter", "type=pod", "--filter", fmt.Sprintf("container=%s", cid)})
@@ -91,7 +86,6 @@ var _ = Describe("Podman events", func() {
})
It("podman events with a type", func() {
- SkipIfNotFedora()
setup := podmanTest.Podman([]string{"run", "-dt", "--pod", "new:foobarpod", ALPINE, "top"})
setup.WaitWithDefaultTimeout()
stop := podmanTest.Podman([]string{"pod", "stop", "foobarpod"})
@@ -110,7 +104,6 @@ var _ = Describe("Podman events", func() {
})
It("podman events --since", func() {
- SkipIfNotFedora()
_, ec, _ := podmanTest.RunLsContainer("")
Expect(ec).To(Equal(0))
result := podmanTest.Podman([]string{"events", "--stream=false", "--since", "1m"})
@@ -119,7 +112,6 @@ var _ = Describe("Podman events", func() {
})
It("podman events --until", func() {
- SkipIfNotFedora()
_, ec, _ := podmanTest.RunLsContainer("")
Expect(ec).To(Equal(0))
result := podmanTest.Podman([]string{"events", "--stream=false", "--until", "1h"})
@@ -128,7 +120,6 @@ var _ = Describe("Podman events", func() {
})
It("podman events format", func() {
- SkipIfNotFedora()
_, ec, _ := podmanTest.RunLsContainer("")
Expect(ec).To(Equal(0))
@@ -153,12 +144,19 @@ var _ = Describe("Podman events", func() {
event = events.Event{}
err = json.Unmarshal([]byte(jsonArr[0]), &event)
Expect(err).ToNot(HaveOccurred())
+
+ test = podmanTest.Podman([]string{"events", "--stream=false", "--filter=type=container", "--format", "ID: {{.ID}}"})
+ test.WaitWithDefaultTimeout()
+ Expect(test).To(Exit(0))
+ arr := test.OutputToStringArray()
+ Expect(len(arr)).To(BeNumerically(">", 1))
+ Expect(arr[0]).To(MatchRegexp("ID: [a-fA-F0-9]{64}"))
})
It("podman events --until future", func() {
- name1 := stringid.GenerateNonCryptoID()
- name2 := stringid.GenerateNonCryptoID()
- name3 := stringid.GenerateNonCryptoID()
+ name1 := stringid.GenerateRandomID()
+ name2 := stringid.GenerateRandomID()
+ name3 := stringid.GenerateRandomID()
session := podmanTest.Podman([]string{"create", "--name", name1, ALPINE})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
diff --git a/test/e2e/generate_kube_test.go b/test/e2e/generate_kube_test.go
index 845aa60ce..d8308aeea 100644
--- a/test/e2e/generate_kube_test.go
+++ b/test/e2e/generate_kube_test.go
@@ -3,6 +3,7 @@ package integration
import (
"io/ioutil"
"os"
+ "os/user"
"path/filepath"
"strconv"
"strings"
@@ -58,7 +59,7 @@ var _ = Describe("Podman generate kube", func() {
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- kube := podmanTest.Podman([]string{"generate", "kube", "top"})
+ kube := podmanTest.Podman([]string{"kube", "generate", "top"})
kube.WaitWithDefaultTimeout()
Expect(kube).Should(Exit(0))
@@ -71,6 +72,10 @@ var _ = Describe("Podman generate kube", func() {
Expect(pod.Spec.Containers[0]).To(HaveField("WorkingDir", ""))
Expect(pod.Spec.Containers[0].Env).To(BeNil())
Expect(pod).To(HaveField("Name", "top-pod"))
+ enableServiceLinks := false
+ Expect(pod.Spec).To(HaveField("EnableServiceLinks", &enableServiceLinks))
+ automountServiceAccountToken := false
+ Expect(pod.Spec).To(HaveField("AutomountServiceAccountToken", &automountServiceAccountToken))
numContainers := 0
for range pod.Spec.Containers {
@@ -115,7 +120,7 @@ var _ = Describe("Podman generate kube", func() {
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- kube := podmanTest.Podman([]string{"generate", "kube", "test"})
+ kube := podmanTest.Podman([]string{"kube", "generate", "test"})
kube.WaitWithDefaultTimeout()
Expect(kube).Should(Exit(0))
@@ -130,7 +135,7 @@ var _ = Describe("Podman generate kube", func() {
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- kube := podmanTest.Podman([]string{"generate", "kube", "-s", "test-ctr"})
+ kube := podmanTest.Podman([]string{"kube", "generate", "-s", "test-ctr"})
kube.WaitWithDefaultTimeout()
Expect(kube).Should(Exit(0))
@@ -165,6 +170,10 @@ var _ = Describe("Podman generate kube", func() {
err := yaml.Unmarshal(kube.Out.Contents(), pod)
Expect(err).To(BeNil())
Expect(pod.Spec).To(HaveField("HostNetwork", false))
+ enableServiceLinks := false
+ Expect(pod.Spec).To(HaveField("EnableServiceLinks", &enableServiceLinks))
+ automountServiceAccountToken := false
+ Expect(pod.Spec).To(HaveField("AutomountServiceAccountToken", &automountServiceAccountToken))
numContainers := 0
for range pod.Spec.Containers {
@@ -182,7 +191,7 @@ var _ = Describe("Podman generate kube", func() {
pod2.WaitWithDefaultTimeout()
Expect(pod2).Should(Exit(0))
- kube := podmanTest.Podman([]string{"generate", "kube", "pod1", "pod2"})
+ kube := podmanTest.Podman([]string{"kube", "generate", "pod1", "pod2"})
kube.WaitWithDefaultTimeout()
Expect(kube).Should(Exit(0))
@@ -203,7 +212,7 @@ var _ = Describe("Podman generate kube", func() {
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- kube := podmanTest.Podman([]string{"generate", "kube", "toppod"})
+ kube := podmanTest.Podman([]string{"kube", "generate", "toppod"})
kube.WaitWithDefaultTimeout()
Expect(kube).Should(Exit(0))
@@ -262,6 +271,39 @@ var _ = Describe("Podman generate kube", func() {
Expect(numContainers).To(Equal(1))
})
+ It("podman generate kube on pod with user namespace", 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")
+ }
+ podSession := podmanTest.Podman([]string{"pod", "create", "--name", "testPod", "--userns=auto"})
+ podSession.WaitWithDefaultTimeout()
+ Expect(podSession).Should(Exit(0))
+
+ session := podmanTest.Podman([]string{"create", "--name", "topcontainer", "--pod", "testPod", ALPINE, "top"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ kube := podmanTest.Podman([]string{"generate", "kube", "testPod"})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube).Should(Exit(0))
+
+ pod := new(v1.Pod)
+ err = yaml.Unmarshal(kube.Out.Contents(), pod)
+ Expect(err).To(BeNil())
+ expected := false
+ Expect(pod.Spec).To(HaveField("HostUsers", &expected))
+ })
+
It("podman generate kube on pod with host network", func() {
podSession := podmanTest.Podman([]string{"pod", "create", "--name", "testHostNetwork", "--network", "host"})
podSession.WaitWithDefaultTimeout()
@@ -398,7 +440,7 @@ var _ = Describe("Podman generate kube", func() {
ctr2Session.WaitWithDefaultTimeout()
Expect(ctr2Session).Should(Exit(0))
- kube := podmanTest.Podman([]string{"generate", "kube", podName})
+ kube := podmanTest.Podman([]string{"kube", "generate", podName})
kube.WaitWithDefaultTimeout()
Expect(kube).Should(Exit(0))
@@ -490,17 +532,18 @@ 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()
Expect(podSession).Should(Exit(0))
ctr1Name := "ctr1"
- ctr1Session := podmanTest.Podman([]string{"create", "--name", ctr1Name, "--pod", podName, "--memory", "10Mi", ALPINE, "top"})
+ ctr1Session := podmanTest.Podman([]string{"create", "--name", ctr1Name, "--pod", podName, "--memory", "10M", ALPINE, "top"})
ctr1Session.WaitWithDefaultTimeout()
Expect(ctr1Session).Should(Exit(0))
- kube := podmanTest.Podman([]string{"generate", "kube", podName})
+ kube := podmanTest.Podman([]string{"kube", "generate", podName})
kube.WaitWithDefaultTimeout()
Expect(kube).Should(Exit(0))
@@ -515,6 +558,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()
@@ -548,6 +592,11 @@ var _ = Describe("Podman generate kube", func() {
It("podman generate kube on pod with ports", func() {
podName := "test"
+
+ lock4 := GetPortLock("4000")
+ defer lock4.Unlock()
+ lock5 := GetPortLock("5000")
+ defer lock5.Unlock()
podSession := podmanTest.Podman([]string{"pod", "create", "--name", podName, "-p", "4000:4000", "-p", "5000:5000"})
podSession.WaitWithDefaultTimeout()
Expect(podSession).Should(Exit(0))
@@ -562,7 +611,7 @@ var _ = Describe("Podman generate kube", func() {
ctr2Session.WaitWithDefaultTimeout()
Expect(ctr2Session).Should(Exit(0))
- kube := podmanTest.Podman([]string{"generate", "kube", podName})
+ kube := podmanTest.Podman([]string{"kube", "generate", podName})
kube.WaitWithDefaultTimeout()
Expect(kube).Should(Exit(0))
@@ -665,7 +714,7 @@ var _ = Describe("Podman generate kube", func() {
Expect(inspect.OutputToString()).To(ContainSubstring("100:200"))
outputFile := filepath.Join(podmanTest.RunRoot, "pod.yaml")
- kube := podmanTest.Podman([]string{"generate", "kube", "-f", outputFile, podName})
+ kube := podmanTest.Podman([]string{"kube", "generate", "-f", outputFile, podName})
kube.WaitWithDefaultTimeout()
Expect(kube).Should(Exit(0))
@@ -708,7 +757,7 @@ var _ = Describe("Podman generate kube", func() {
pod := new(v1.Pod)
err = yaml.Unmarshal(b, pod)
Expect(err).To(BeNil())
- Expect(pod.Annotations).To(HaveKeyWithValue(define.BindMountPrefix+vol1, HaveSuffix("z")))
+ Expect(pod.Annotations).To(HaveKeyWithValue(define.BindMountPrefix, vol1+":"+"z"))
rm := podmanTest.Podman([]string{"pod", "rm", "-t", "0", "-f", "test1"})
rm.WaitWithDefaultTimeout()
@@ -788,7 +837,7 @@ var _ = Describe("Podman generate kube", func() {
Expect(session).Should(Exit(0))
outputFile := filepath.Join(podmanTest.RunRoot, "pod.yaml")
- kube := podmanTest.Podman([]string{"generate", "kube", podName, "-f", outputFile})
+ kube := podmanTest.Podman([]string{"kube", "generate", podName, "-f", outputFile})
kube.WaitWithDefaultTimeout()
Expect(kube).Should(Exit(0))
@@ -857,7 +906,7 @@ var _ = Describe("Podman generate kube", func() {
pod2.WaitWithDefaultTimeout()
Expect(pod2).Should(Exit(0))
- kube := podmanTest.Podman([]string{"generate", "kube", "top1", "top2"})
+ kube := podmanTest.Podman([]string{"kube", "generate", "top1", "top2"})
kube.WaitWithDefaultTimeout()
Expect(kube).To(ExitWithError())
})
@@ -911,7 +960,7 @@ var _ = Describe("Podman generate kube", func() {
top.WaitWithDefaultTimeout()
Expect(top).Should(Exit(0))
- kube := podmanTest.Podman([]string{"generate", "kube", "pod1"})
+ kube := podmanTest.Podman([]string{"kube", "generate", "pod1"})
kube.WaitWithDefaultTimeout()
Expect(kube).Should(Exit(0))
@@ -973,7 +1022,7 @@ var _ = Describe("Podman generate kube", func() {
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- kube = podmanTest.Podman([]string{"generate", "kube", "test1"})
+ kube = podmanTest.Podman([]string{"kube", "generate", "test1"})
kube.WaitWithDefaultTimeout()
Expect(kube).Should(Exit(0))
@@ -1026,7 +1075,7 @@ ENTRYPOINT ["sleep"]`
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- kube = podmanTest.Podman([]string{"generate", "kube", "testpod-2"})
+ kube = podmanTest.Podman([]string{"kube", "generate", "testpod-2"})
kube.WaitWithDefaultTimeout()
Expect(kube).Should(Exit(0))
@@ -1228,4 +1277,27 @@ USER test1`
Expect(pod.Spec.Containers[0].Env).To(HaveLen(2))
})
+
+ It("podman generate kube omit secret if empty", func() {
+ dir, err := os.MkdirTemp(tempdir, "podman")
+ Expect(err).Should(BeNil())
+
+ defer os.RemoveAll(dir)
+
+ podCreate := podmanTest.Podman([]string{"run", "-d", "--pod", "new:" + "noSecretsPod", "--name", "noSecretsCtr", "--volume", dir + ":/foobar", ALPINE})
+ podCreate.WaitWithDefaultTimeout()
+ Expect(podCreate).Should(Exit(0))
+
+ kube := podmanTest.Podman([]string{"generate", "kube", "noSecretsPod"})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube).Should(Exit(0))
+
+ Expect(kube.OutputToString()).ShouldNot(ContainSubstring("secret"))
+
+ pod := new(v1.Pod)
+ err = yaml.Unmarshal(kube.Out.Contents(), pod)
+ Expect(err).To(BeNil())
+
+ Expect(pod.Spec.Volumes[0].Secret).To(BeNil())
+ })
})
diff --git a/test/e2e/generate_spec_test.go b/test/e2e/generate_spec_test.go
new file mode 100644
index 000000000..9188b5222
--- /dev/null
+++ b/test/e2e/generate_spec_test.go
@@ -0,0 +1,82 @@
+package integration
+
+import (
+ "os"
+ "path/filepath"
+
+ . "github.com/containers/podman/v4/test/utils"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+ . "github.com/onsi/gomega/gexec"
+)
+
+var _ = Describe("Podman generate spec", func() {
+ var (
+ tempdir string
+ err error
+ podmanTest *PodmanTestIntegration
+ )
+
+ BeforeEach(func() {
+ SkipIfRemote("podman generate spec is not supported on the remote client")
+ tempdir, err = CreateTempDirInTempDir()
+ if err != nil {
+ os.Exit(1)
+ }
+ podmanTest = PodmanTestCreate(tempdir)
+ podmanTest.Setup()
+ })
+
+ AfterEach(func() {
+ podmanTest.Cleanup()
+ f := CurrentGinkgoTestDescription()
+ processTestResult(f)
+
+ })
+
+ It("podman generate spec bogus should fail", func() {
+ session := podmanTest.Podman([]string{"generate", "spec", "foobar"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(ExitWithError())
+ })
+
+ 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))
+
+ session = podmanTest.Podman([]string{"generate", "spec", "--compact", "specgen"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ })
+
+ 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))
+
+ session = podmanTest.Podman([]string{"generate", "spec", "--filename", filepath.Join(tempdir, "out.json"), "specgen"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ path := filepath.Join(tempdir, "out.json")
+
+ exec := SystemExec("cat", []string{path})
+ exec.WaitWithDefaultTimeout()
+ Expect(exec.OutputToString()).Should(ContainSubstring("specgen-clone"))
+ Expect(exec.OutputToString()).Should(ContainSubstring("500000"))
+
+ })
+
+ It("generate spec pod", func() {
+ session := podmanTest.Podman([]string{"pod", "create", "--cpus", "5", "--name", "podspecgen"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ session = podmanTest.Podman([]string{"generate", "spec", "--compact", "podspecgen"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ })
+})
diff --git a/test/e2e/generate_systemd_test.go b/test/e2e/generate_systemd_test.go
index 45a2f1f86..347440faf 100644
--- a/test/e2e/generate_systemd_test.go
+++ b/test/e2e/generate_systemd_test.go
@@ -3,6 +3,7 @@ package integration
import (
"io/ioutil"
"os"
+ "strings"
. "github.com/containers/podman/v4/test/utils"
. "github.com/onsi/ginkgo"
@@ -220,19 +221,20 @@ var _ = Describe("Podman generate systemd", func() {
Expect(session).Should(Exit(0))
// Grepping the output (in addition to unit tests)
- Expect(session.OutputToString()).To(ContainSubstring("# pod-foo.service"))
- Expect(session.OutputToString()).To(ContainSubstring("Requires=container-foo-1.service container-foo-2.service"))
- Expect(session.OutputToString()).To(ContainSubstring("# container-foo-1.service"))
- Expect(session.OutputToString()).To(ContainSubstring(" start foo-1"))
- Expect(session.OutputToString()).To(ContainSubstring("-infra")) // infra container
- Expect(session.OutputToString()).To(ContainSubstring("# container-foo-2.service"))
- Expect(session.OutputToString()).To(ContainSubstring(" stop -t 42 foo-2"))
- Expect(session.OutputToString()).To(ContainSubstring("BindsTo=pod-foo.service"))
- Expect(session.OutputToString()).To(ContainSubstring("PIDFile="))
- Expect(session.OutputToString()).To(ContainSubstring("/userdata/conmon.pid"))
-
+ output := session.OutputToString()
+ Expect(output).To(ContainSubstring("# pod-foo.service"))
+ Expect(output).To(ContainSubstring("Wants=container-foo-1.service container-foo-2.service"))
+ Expect(output).To(ContainSubstring("# container-foo-1.service"))
+ Expect(output).To(ContainSubstring(" start foo-1"))
+ Expect(output).To(ContainSubstring("-infra")) // infra container
+ Expect(output).To(ContainSubstring("# container-foo-2.service"))
+ Expect(output).To(ContainSubstring(" stop -t 42 foo-2"))
+ Expect(output).To(ContainSubstring("BindsTo=pod-foo.service"))
+ Expect(output).To(ContainSubstring("PIDFile="))
+ Expect(output).To(ContainSubstring("/userdata/conmon.pid"))
+ Expect(strings.Count(output, "RequiresMountsFor="+podmanTest.RunRoot)).To(Equal(3))
// The podman commands in the unit should not contain the root flags
- Expect(session.OutputToString()).ToNot(ContainSubstring(" --runroot"))
+ Expect(output).ToNot(ContainSubstring(" --runroot"))
})
It("podman generate systemd pod --name --files", func() {
@@ -468,7 +470,7 @@ var _ = Describe("Podman generate systemd", func() {
// Grepping the output (in addition to unit tests)
Expect(session.OutputToString()).To(ContainSubstring("# p-foo.service"))
- Expect(session.OutputToString()).To(ContainSubstring("Requires=container-foo-1.service container-foo-2.service"))
+ Expect(session.OutputToString()).To(ContainSubstring("Wants=container-foo-1.service container-foo-2.service"))
Expect(session.OutputToString()).To(ContainSubstring("# container-foo-1.service"))
Expect(session.OutputToString()).To(ContainSubstring("BindsTo=p-foo.service"))
})
@@ -492,7 +494,7 @@ var _ = Describe("Podman generate systemd", func() {
// Grepping the output (in addition to unit tests)
Expect(session.OutputToString()).To(ContainSubstring("# p_foo.service"))
- Expect(session.OutputToString()).To(ContainSubstring("Requires=con_foo-1.service con_foo-2.service"))
+ Expect(session.OutputToString()).To(ContainSubstring("Wants=con_foo-1.service con_foo-2.service"))
Expect(session.OutputToString()).To(ContainSubstring("# con_foo-1.service"))
Expect(session.OutputToString()).To(ContainSubstring("# con_foo-2.service"))
Expect(session.OutputToString()).To(ContainSubstring("BindsTo=p_foo.service"))
@@ -518,7 +520,7 @@ var _ = Describe("Podman generate systemd", func() {
// Grepping the output (in addition to unit tests)
Expect(session1.OutputToString()).To(ContainSubstring("# foo.service"))
- Expect(session1.OutputToString()).To(ContainSubstring("Requires=container-foo-1.service container-foo-2.service"))
+ Expect(session1.OutputToString()).To(ContainSubstring("Wants=container-foo-1.service container-foo-2.service"))
Expect(session1.OutputToString()).To(ContainSubstring("# container-foo-1.service"))
Expect(session1.OutputToString()).To(ContainSubstring("BindsTo=foo.service"))
@@ -529,7 +531,7 @@ var _ = Describe("Podman generate systemd", func() {
// Grepping the output (in addition to unit tests)
Expect(session2.OutputToString()).To(ContainSubstring("# foo.service"))
- Expect(session2.OutputToString()).To(ContainSubstring("Requires=foo-1.service foo-2.service"))
+ Expect(session2.OutputToString()).To(ContainSubstring("Wants=foo-1.service foo-2.service"))
Expect(session2.OutputToString()).To(ContainSubstring("# foo-1.service"))
Expect(session2.OutputToString()).To(ContainSubstring("# foo-2.service"))
Expect(session2.OutputToString()).To(ContainSubstring("BindsTo=foo.service"))
@@ -560,9 +562,9 @@ var _ = Describe("Podman generate systemd", func() {
// Grepping the output (in addition to unit tests)
Expect(session.OutputToString()).To(ContainSubstring("# pod-foo.service"))
- Expect(session.OutputToString()).To(ContainSubstring("Requires=container-foo-1.service container-foo-2.service"))
+ Expect(session.OutputToString()).To(ContainSubstring("Wants=container-foo-1.service container-foo-2.service"))
Expect(session.OutputToString()).To(ContainSubstring("BindsTo=pod-foo.service"))
- Expect(session.OutputToString()).To(ContainSubstring("pod create --infra-conmon-pidfile %t/pod-foo.pid --pod-id-file %t/pod-foo.pod-id --name foo"))
+ Expect(session.OutputToString()).To(ContainSubstring("pod create --infra-conmon-pidfile %t/pod-foo.pid --pod-id-file %t/pod-foo.pod-id --exit-policy=stop --name foo"))
Expect(session.OutputToString()).To(ContainSubstring("ExecStartPre=/bin/rm -f %t/pod-foo.pid %t/pod-foo.pod-id"))
Expect(session.OutputToString()).To(ContainSubstring("pod stop --ignore --pod-id-file %t/pod-foo.pod-id -t 10"))
Expect(session.OutputToString()).To(ContainSubstring("pod rm --ignore -f --pod-id-file %t/pod-foo.pod-id"))
@@ -600,4 +602,75 @@ var _ = Describe("Podman generate systemd", func() {
Expect(session).Should(Exit(0))
Expect(session.OutputToString()).To(ContainSubstring(" --label key={{someval}}"))
})
+
+ It("podman generate systemd --env", func() {
+ session := podmanTest.RunTopContainer("test")
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ session = podmanTest.Podman([]string{"generate", "systemd", "--env", "foo=bar", "-e", "hoge=fuga", "test"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).To(ContainSubstring("Environment=foo=bar"))
+ Expect(session.OutputToString()).To(ContainSubstring("Environment=hoge=fuga"))
+
+ session = podmanTest.Podman([]string{"generate", "systemd", "--env", "=bar", "-e", "hoge=fuga", "test"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(125))
+ Expect(session.ErrorToString()).To(ContainSubstring("invalid environment variable"))
+
+ // Use -e/--env option with --new option
+ session = podmanTest.Podman([]string{"generate", "systemd", "--env", "foo=bar", "-e", "hoge=fuga", "--new", "test"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).To(ContainSubstring("Environment=foo=bar"))
+ Expect(session.OutputToString()).To(ContainSubstring("Environment=hoge=fuga"))
+
+ session = podmanTest.Podman([]string{"generate", "systemd", "--env", "foo=bar", "-e", "=fuga", "--new", "test"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(125))
+ Expect(session.ErrorToString()).To(ContainSubstring("invalid environment variable"))
+
+ // Escape systemd arguments
+ session = podmanTest.Podman([]string{"generate", "systemd", "--env", "BAR=my test", "-e", "USER=%a", "test"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).To(ContainSubstring("\"BAR=my test\""))
+ Expect(session.OutputToString()).To(ContainSubstring("USER=%%a"))
+
+ session = podmanTest.Podman([]string{"generate", "systemd", "--env", "BAR=my test", "-e", "USER=%a", "--new", "test"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).To(ContainSubstring("\"BAR=my test\""))
+ Expect(session.OutputToString()).To(ContainSubstring("USER=%%a"))
+
+ // Specify the environment variables without a value
+ os.Setenv("FOO1", "BAR1")
+ os.Setenv("FOO2", "BAR2")
+ os.Setenv("FOO3", "BAR3")
+ defer os.Unsetenv("FOO1")
+ defer os.Unsetenv("FOO2")
+ defer os.Unsetenv("FOO3")
+
+ session = podmanTest.Podman([]string{"generate", "systemd", "--env", "FOO1", "test"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).To(ContainSubstring("BAR1"))
+ Expect(session.OutputToString()).NotTo(ContainSubstring("BAR2"))
+ Expect(session.OutputToString()).NotTo(ContainSubstring("BAR3"))
+
+ session = podmanTest.Podman([]string{"generate", "systemd", "--env", "FOO*", "test"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).To(ContainSubstring("BAR1"))
+ Expect(session.OutputToString()).To(ContainSubstring("BAR2"))
+ Expect(session.OutputToString()).To(ContainSubstring("BAR3"))
+
+ session = podmanTest.Podman([]string{"generate", "systemd", "--env", "FOO*", "--new", "test"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).To(ContainSubstring("BAR1"))
+ Expect(session.OutputToString()).To(ContainSubstring("BAR2"))
+ Expect(session.OutputToString()).To(ContainSubstring("BAR3"))
+ })
})
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/image_scp_test.go b/test/e2e/image_scp_test.go
index 77fe810bd..2c275d974 100644
--- a/test/e2e/image_scp_test.go
+++ b/test/e2e/image_scp_test.go
@@ -3,9 +3,11 @@ package integration
import (
"io/ioutil"
"os"
+ "path/filepath"
"github.com/containers/common/pkg/config"
. "github.com/containers/podman/v4/test/utils"
+ "github.com/containers/storage/pkg/homedir"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/gexec"
@@ -56,6 +58,9 @@ var _ = Describe("podman image scp", func() {
})
It("podman image scp with proper connection", func() {
+ if _, err := os.Stat(filepath.Join(homedir.Get(), ".ssh", "known_hosts")); err != nil {
+ Skip("known_hosts does not exist or is not accessible")
+ }
cmd := []string{"system", "connection", "add",
"--default",
"QA",
diff --git a/test/e2e/image_sign_test.go b/test/e2e/image_sign_test.go
index 3c819a7d2..5568acc01 100644
--- a/test/e2e/image_sign_test.go
+++ b/test/e2e/image_sign_test.go
@@ -1,7 +1,6 @@
package integration
import (
- "io/ioutil"
"os"
"os/exec"
"path/filepath"
@@ -69,7 +68,7 @@ var _ = Describe("Podman image sign", func() {
session := podmanTest.Podman([]string{"image", "sign", "--all", "--directory", sigDir, "--sign-by", "foo@bar.com", "docker://library/alpine"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- fInfos, err := ioutil.ReadDir(filepath.Join(sigDir, "library"))
+ fInfos, err := os.ReadDir(filepath.Join(sigDir, "library"))
Expect(err).To(BeNil())
Expect(len(fInfos)).To(BeNumerically(">", 1), "len(fInfos)")
})
diff --git a/test/e2e/init_test.go b/test/e2e/init_test.go
index ccc102fa3..25b9e079a 100644
--- a/test/e2e/init_test.go
+++ b/test/e2e/init_test.go
@@ -52,6 +52,7 @@ var _ = Describe("Podman init", func() {
init := podmanTest.Podman([]string{"init", cid})
init.WaitWithDefaultTimeout()
Expect(init).Should(Exit(0))
+ Expect(init.OutputToString()).To(Equal(cid))
result := podmanTest.Podman([]string{"inspect", cid})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
@@ -67,6 +68,7 @@ var _ = Describe("Podman init", func() {
init := podmanTest.Podman([]string{"init", name})
init.WaitWithDefaultTimeout()
Expect(init).Should(Exit(0))
+ Expect(init.OutputToString()).To(Equal(name))
result := podmanTest.Podman([]string{"inspect", name})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
@@ -79,9 +81,11 @@ var _ = Describe("Podman init", func() {
session := podmanTest.Podman([]string{"create", ALPINE, "ls"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
+ cid := session.OutputToString()
init := podmanTest.Podman([]string{"init", "--latest"})
init.WaitWithDefaultTimeout()
Expect(init).Should(Exit(0))
+ Expect(init.OutputToString()).To(Equal(cid))
result := podmanTest.Podman([]string{"inspect", "--latest"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
@@ -93,15 +97,21 @@ var _ = Describe("Podman init", func() {
session := podmanTest.Podman([]string{"create", "--name", "test1", ALPINE, "ls"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
+ cid := session.OutputToString()
session2 := podmanTest.Podman([]string{"create", "--name", "test2", ALPINE, "ls"})
session2.WaitWithDefaultTimeout()
Expect(session2).Should(Exit(0))
+ cid2 := session2.OutputToString()
session3 := podmanTest.Podman([]string{"run", "--name", "test3", "-d", ALPINE, "top"})
session3.WaitWithDefaultTimeout()
Expect(session3).Should(Exit(0))
+ cid3 := session3.OutputToString()
init := podmanTest.Podman([]string{"init", "--all"})
init.WaitWithDefaultTimeout()
Expect(init).Should(Exit(0))
+ Expect(init.OutputToString()).To(ContainSubstring(cid))
+ Expect(init.OutputToString()).To(ContainSubstring(cid2))
+ Expect(init.OutputToString()).To(ContainSubstring(cid3))
result := podmanTest.Podman([]string{"inspect", "test1"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
diff --git a/test/e2e/login_logout_test.go b/test/e2e/login_logout_test.go
index 3ae130c6d..60c53e27e 100644
--- a/test/e2e/login_logout_test.go
+++ b/test/e2e/login_logout_test.go
@@ -52,15 +52,15 @@ var _ = Describe("Podman login and logout", func() {
}
}
- session := podmanTest.Podman([]string{"run", "--entrypoint", "htpasswd", "registry:2.6", "-Bbn", "podmantest", "test"})
- session.WaitWithDefaultTimeout()
- Expect(session).Should(Exit(0))
+ htpasswd := SystemExec("htpasswd", []string{"-Bbn", "podmantest", "test"})
+ htpasswd.WaitWithDefaultTimeout()
+ Expect(htpasswd).Should(Exit(0))
f, err := os.Create(filepath.Join(authPath, "htpasswd"))
Expect(err).ToNot(HaveOccurred())
defer f.Close()
- _, err = f.WriteString(session.OutputToString())
+ _, err = f.WriteString(htpasswd.OutputToString())
Expect(err).ToNot(HaveOccurred())
err = f.Sync()
Expect(err).ToNot(HaveOccurred())
@@ -80,12 +80,12 @@ var _ = Describe("Podman login and logout", func() {
setup := SystemExec("cp", []string{filepath.Join(certPath, "domain.crt"), filepath.Join(certDirPath, "ca.crt")})
setup.WaitWithDefaultTimeout()
- session = podmanTest.Podman([]string{"run", "-d", "-p", strings.Join([]string{strconv.Itoa(port), strconv.Itoa(port)}, ":"),
+ session := podmanTest.Podman([]string{"run", "-d", "-p", strings.Join([]string{strconv.Itoa(port), strconv.Itoa(port)}, ":"),
"-e", strings.Join([]string{"REGISTRY_HTTP_ADDR=0.0.0.0", strconv.Itoa(port)}, ":"), "--name", "registry", "-v",
strings.Join([]string{authPath, "/auth:Z"}, ":"), "-e", "REGISTRY_AUTH=htpasswd", "-e",
"REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm", "-e", "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd",
"-v", strings.Join([]string{certPath, "/certs:Z"}, ":"), "-e", "REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt",
- "-e", "REGISTRY_HTTP_TLS_KEY=/certs/domain.key", "registry:2.6"})
+ "-e", "REGISTRY_HTTP_TLS_KEY=/certs/domain.key", REGISTRY_IMAGE})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
@@ -249,7 +249,7 @@ var _ = Describe("Podman login and logout", func() {
strings.Join([]string{authPath, "/auth:z"}, ":"), "-e", "REGISTRY_AUTH=htpasswd", "-e",
"REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm", "-e", "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd",
"-v", strings.Join([]string{certPath, "/certs:z"}, ":"), "-e", "REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt",
- "-e", "REGISTRY_HTTP_TLS_KEY=/certs/domain.key", "registry:2.6"})
+ "-e", "REGISTRY_HTTP_TLS_KEY=/certs/domain.key", REGISTRY_IMAGE})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
diff --git a/test/e2e/logs_test.go b/test/e2e/logs_test.go
index 14dd6b6b8..c680cae2a 100644
--- a/test/e2e/logs_test.go
+++ b/test/e2e/logs_test.go
@@ -376,7 +376,7 @@ var _ = Describe("Podman logs", func() {
skipIfJournaldInContainer()
cname := "log-test"
- content := stringid.GenerateNonCryptoID()
+ content := stringid.GenerateRandomID()
// use printf to print no extra newline
logc := podmanTest.Podman([]string{"run", "--log-driver", log, "--name", cname, ALPINE, "printf", content})
logc.WaitWithDefaultTimeout()
diff --git a/test/e2e/manifest_test.go b/test/e2e/manifest_test.go
index 893210a1f..e38499257 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() {
@@ -173,13 +187,15 @@ var _ = Describe("Podman manifest", func() {
session = podmanTest.Podman([]string{"manifest", "add", "foo", imageListInstance})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- session = podmanTest.Podman([]string{"manifest", "annotate", "--arch", "bar", "foo", imageListARM64InstanceDigest})
+ session = podmanTest.Podman([]string{"manifest", "annotate", "--annotation", "hello=world", "--arch", "bar", "foo", imageListARM64InstanceDigest})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
session = podmanTest.Podman([]string{"manifest", "inspect", "foo"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(session.OutputToString()).To(ContainSubstring(`"architecture": "bar"`))
+ // Check added annotation
+ Expect(session.OutputToString()).To(ContainSubstring(`"hello": "world"`))
})
It("remove digest", func() {
@@ -316,7 +332,7 @@ var _ = Describe("Podman manifest", func() {
blobsDir := filepath.Join(dest, "blobs", "sha256")
- blobs, err := ioutil.ReadDir(blobsDir)
+ blobs, err := os.ReadDir(blobsDir)
Expect(err).To(BeNil())
for _, f := range blobs {
@@ -334,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),
@@ -377,6 +420,11 @@ var _ = Describe("Podman manifest", func() {
push = podmanTest.Podman([]string{"manifest", "push", "--tls-verify=false", "--creds=" + registry.User + ":" + registry.Password, "foo", "localhost:" + registry.Port + "/credstest"})
push.WaitWithDefaultTimeout()
Expect(push).Should(Exit(0))
+ output := push.ErrorToString()
+ Expect(output).To(ContainSubstring("Copying blob "))
+ Expect(output).To(ContainSubstring("Copying config "))
+ Expect(output).To(ContainSubstring("Writing manifest to image destination"))
+ Expect(output).To(ContainSubstring("Storing signatures"))
push = podmanTest.Podman([]string{"manifest", "push", "--tls-verify=false", "--creds=podmantest:wrongpasswd", "foo", "localhost:" + registry.Port + "/credstest"})
push.WaitWithDefaultTimeout()
diff --git a/test/e2e/mount_rootless_test.go b/test/e2e/mount_rootless_test.go
index 994a5899b..b0452deda 100644
--- a/test/e2e/mount_rootless_test.go
+++ b/test/e2e/mount_rootless_test.go
@@ -52,9 +52,16 @@ var _ = Describe("Podman mount", func() {
Expect(setup).Should(Exit(0))
cid := setup.OutputToString()
- session := podmanTest.Podman([]string{"unshare", PODMAN_BINARY, "mount", cid})
+ // command: podman <options> unshare podman <options> mount cid
+ args := []string{"unshare", podmanTest.PodmanBinary}
+ opts := podmanTest.PodmanMakeOptions([]string{"mount", cid}, false, false)
+ args = append(args, opts...)
+
+ // container root file system location is /tmp/... because "--root /tmp/..."
+ session := podmanTest.Podman(args)
session.WaitWithDefaultTimeout()
- Expect(setup).Should(Exit(0))
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).To(ContainSubstring("/tmp"))
})
It("podman image mount", func() {
@@ -71,8 +78,15 @@ var _ = Describe("Podman mount", func() {
setup.WaitWithDefaultTimeout()
Expect(setup).Should(Exit(0))
- session := podmanTest.Podman([]string{"unshare", PODMAN_BINARY, "image", "mount", ALPINE})
+ // command: podman <options> unshare podman <options> image mount ALPINE
+ args := []string{"unshare", podmanTest.PodmanBinary}
+ opts := podmanTest.PodmanMakeOptions([]string{"image", "mount", ALPINE}, false, false)
+ args = append(args, opts...)
+
+ // image location is /tmp/... because "--root /tmp/..."
+ session := podmanTest.Podman(args)
session.WaitWithDefaultTimeout()
- Expect(setup).Should(Exit(0))
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).To(ContainSubstring("/tmp"))
})
})
diff --git a/test/e2e/network_connect_disconnect_test.go b/test/e2e/network_connect_disconnect_test.go
index ece1b519d..6e6a7fb39 100644
--- a/test/e2e/network_connect_disconnect_test.go
+++ b/test/e2e/network_connect_disconnect_test.go
@@ -41,7 +41,7 @@ var _ = Describe("Podman network connect and disconnect", func() {
})
It("bad container name in network disconnect should result in error", func() {
- netName := "aliasTest" + stringid.GenerateNonCryptoID()
+ netName := "aliasTest" + stringid.GenerateRandomID()
session := podmanTest.Podman([]string{"network", "create", netName})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
@@ -53,7 +53,7 @@ var _ = Describe("Podman network connect and disconnect", func() {
})
It("network disconnect with net mode slirp4netns should result in error", func() {
- netName := "slirp" + stringid.GenerateNonCryptoID()
+ netName := "slirp" + stringid.GenerateRandomID()
session := podmanTest.Podman([]string{"network", "create", netName})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
@@ -72,7 +72,7 @@ var _ = Describe("Podman network connect and disconnect", func() {
It("podman network disconnect", func() {
SkipIfRootlessCgroupsV1("stats not supported under rootless CgroupsV1")
- netName := "aliasTest" + stringid.GenerateNonCryptoID()
+ netName := "aliasTest" + stringid.GenerateRandomID()
session := podmanTest.Podman([]string{"network", "create", netName})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
@@ -128,7 +128,7 @@ var _ = Describe("Podman network connect and disconnect", func() {
})
It("bad container name in network connect should result in error", func() {
- netName := "aliasTest" + stringid.GenerateNonCryptoID()
+ netName := "aliasTest" + stringid.GenerateRandomID()
session := podmanTest.Podman([]string{"network", "create", netName})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
@@ -140,7 +140,7 @@ var _ = Describe("Podman network connect and disconnect", func() {
})
It("network connect with net mode slirp4netns should result in error", func() {
- netName := "slirp" + stringid.GenerateNonCryptoID()
+ netName := "slirp" + stringid.GenerateRandomID()
session := podmanTest.Podman([]string{"network", "create", netName})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
@@ -157,8 +157,8 @@ 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() {
- netName := "aliasTest" + stringid.GenerateNonCryptoID()
+ It("podman connect on a container that already is connected to the network should error after init", func() {
+ netName := "aliasTest" + stringid.GenerateRandomID()
session := podmanTest.Podman([]string{"network", "create", netName})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
@@ -177,12 +177,20 @@ 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() {
SkipIfRootlessCgroupsV1("stats not supported under rootless CgroupsV1")
- netName := "aliasTest" + stringid.GenerateNonCryptoID()
+ netName := "aliasTest" + stringid.GenerateRandomID()
session := podmanTest.Podman([]string{"network", "create", netName})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
@@ -198,7 +206,7 @@ var _ = Describe("Podman network connect and disconnect", func() {
Expect(exec).Should(Exit(0))
// Create a second network
- newNetName := "aliasTest" + stringid.GenerateNonCryptoID()
+ newNetName := "aliasTest" + stringid.GenerateRandomID()
session = podmanTest.Podman([]string{"network", "create", newNetName, "--subnet", "10.11.100.0/24"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
@@ -256,13 +264,13 @@ var _ = Describe("Podman network connect and disconnect", func() {
})
It("podman network connect when not running", func() {
- netName1 := "connect1" + stringid.GenerateNonCryptoID()
+ netName1 := "connect1" + stringid.GenerateRandomID()
session := podmanTest.Podman([]string{"network", "create", netName1})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
defer podmanTest.removeNetwork(netName1)
- netName2 := "connect2" + stringid.GenerateNonCryptoID()
+ netName2 := "connect2" + stringid.GenerateRandomID()
session = podmanTest.Podman([]string{"network", "create", netName2})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
@@ -295,7 +303,7 @@ var _ = Describe("Podman network connect and disconnect", func() {
})
It("podman network connect and run with network ID", func() {
- netName := "ID" + stringid.GenerateNonCryptoID()
+ netName := "ID" + stringid.GenerateRandomID()
session := podmanTest.Podman([]string{"network", "create", netName})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
@@ -315,7 +323,7 @@ var _ = Describe("Podman network connect and disconnect", func() {
Expect(exec).Should(Exit(0))
// Create a second network
- newNetName := "ID2" + stringid.GenerateNonCryptoID()
+ newNetName := "ID2" + stringid.GenerateRandomID()
session = podmanTest.Podman([]string{"network", "create", newNetName})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
@@ -342,13 +350,13 @@ var _ = Describe("Podman network connect and disconnect", func() {
})
It("podman network disconnect when not running", func() {
- netName1 := "aliasTest" + stringid.GenerateNonCryptoID()
+ netName1 := "aliasTest" + stringid.GenerateRandomID()
session := podmanTest.Podman([]string{"network", "create", netName1})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
defer podmanTest.removeNetwork(netName1)
- netName2 := "aliasTest" + stringid.GenerateNonCryptoID()
+ netName2 := "aliasTest" + stringid.GenerateRandomID()
session2 := podmanTest.Podman([]string{"network", "create", netName2})
session2.WaitWithDefaultTimeout()
Expect(session2).Should(Exit(0))
@@ -387,7 +395,7 @@ var _ = Describe("Podman network connect and disconnect", func() {
})
It("podman network disconnect and run with network ID", func() {
- netName := "aliasTest" + stringid.GenerateNonCryptoID()
+ netName := "aliasTest" + stringid.GenerateRandomID()
session := podmanTest.Podman([]string{"network", "create", netName})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
diff --git a/test/e2e/network_create_test.go b/test/e2e/network_create_test.go
index 69966b07e..f7855581b 100644
--- a/test/e2e/network_create_test.go
+++ b/test/e2e/network_create_test.go
@@ -41,7 +41,7 @@ var _ = Describe("Podman network create", func() {
})
It("podman network create with name and subnet", func() {
- netName := "subnet-" + stringid.GenerateNonCryptoID()
+ netName := "subnet-" + stringid.GenerateRandomID()
nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.12.0/24", "--ip-range", "10.11.12.0/26", netName})
nc.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(netName)
@@ -84,7 +84,7 @@ var _ = Describe("Podman network create", func() {
})
It("podman network create with name and IPv6 subnet", func() {
- netName := "ipv6-" + stringid.GenerateNonCryptoID()
+ netName := "ipv6-" + stringid.GenerateRandomID()
nc := podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:1:2:3:4::/64", netName})
nc.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(netName)
@@ -123,7 +123,7 @@ var _ = Describe("Podman network create", func() {
})
It("podman network create with name and IPv6 flag (dual-stack)", func() {
- netName := "dual-" + stringid.GenerateNonCryptoID()
+ netName := "dual-" + stringid.GenerateRandomID()
nc := podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:4:3:2::/64", "--ipv6", netName})
nc.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(netName)
@@ -156,7 +156,7 @@ var _ = Describe("Podman network create", func() {
// create a second network to check the auto assigned ipv4 subnet does not overlap
// https://github.com/containers/podman/issues/11032
- netName2 := "dual-" + stringid.GenerateNonCryptoID()
+ netName2 := "dual-" + stringid.GenerateRandomID()
nc = podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:10:3:2::/64", "--ipv6", netName2})
nc.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(netName2)
@@ -204,13 +204,13 @@ var _ = Describe("Podman network create", func() {
})
It("podman network create with invalid subnet", func() {
- nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.12.0/17000", stringid.GenerateNonCryptoID()})
+ nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.12.0/17000", stringid.GenerateRandomID()})
nc.WaitWithDefaultTimeout()
Expect(nc).To(ExitWithError())
})
It("podman network create with ipv4 subnet and ipv6 flag", func() {
- name := stringid.GenerateNonCryptoID()
+ name := stringid.GenerateRandomID()
nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.12.0/24", "--ipv6", name})
nc.WaitWithDefaultTimeout()
Expect(nc).To(Exit(0))
@@ -224,7 +224,7 @@ var _ = Describe("Podman network create", func() {
})
It("podman network create with empty subnet and ipv6 flag", func() {
- name := stringid.GenerateNonCryptoID()
+ name := stringid.GenerateRandomID()
nc := podmanTest.Podman([]string{"network", "create", "--ipv6", name})
nc.WaitWithDefaultTimeout()
Expect(nc).To(Exit(0))
@@ -238,19 +238,19 @@ var _ = Describe("Podman network create", func() {
})
It("podman network create with invalid IP", func() {
- nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.0/17000", stringid.GenerateNonCryptoID()})
+ nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.0/17000", stringid.GenerateRandomID()})
nc.WaitWithDefaultTimeout()
Expect(nc).To(ExitWithError())
})
It("podman network create with invalid gateway for subnet", func() {
- nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.12.0/24", "--gateway", "192.168.1.1", stringid.GenerateNonCryptoID()})
+ nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.12.0/24", "--gateway", "192.168.1.1", stringid.GenerateRandomID()})
nc.WaitWithDefaultTimeout()
Expect(nc).To(ExitWithError())
})
It("podman network create two networks with same name should fail", func() {
- netName := "same-" + stringid.GenerateNonCryptoID()
+ netName := "same-" + stringid.GenerateRandomID()
nc := podmanTest.Podman([]string{"network", "create", netName})
nc.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(netName)
@@ -262,13 +262,13 @@ var _ = Describe("Podman network create", func() {
})
It("podman network create two networks with same subnet should fail", func() {
- netName1 := "sub1-" + stringid.GenerateNonCryptoID()
+ netName1 := "sub1-" + stringid.GenerateRandomID()
nc := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.13.0/24", netName1})
nc.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(netName1)
Expect(nc).Should(Exit(0))
- netName2 := "sub2-" + stringid.GenerateNonCryptoID()
+ netName2 := "sub2-" + stringid.GenerateRandomID()
ncFail := podmanTest.Podman([]string{"network", "create", "--subnet", "10.11.13.0/24", netName2})
ncFail.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(netName2)
@@ -276,13 +276,13 @@ var _ = Describe("Podman network create", func() {
})
It("podman network create two IPv6 networks with same subnet should fail", func() {
- netName1 := "subipv61-" + stringid.GenerateNonCryptoID()
+ netName1 := "subipv61-" + stringid.GenerateRandomID()
nc := podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:4:4:4:4::/64", "--ipv6", netName1})
nc.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(netName1)
Expect(nc).Should(Exit(0))
- netName2 := "subipv62-" + stringid.GenerateNonCryptoID()
+ netName2 := "subipv62-" + stringid.GenerateRandomID()
ncFail := podmanTest.Podman([]string{"network", "create", "--subnet", "fd00:4:4:4:4::/64", "--ipv6", netName2})
ncFail.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(netName2)
@@ -296,7 +296,7 @@ var _ = Describe("Podman network create", func() {
})
It("podman network create with mtu option", func() {
- net := "mtu-test" + stringid.GenerateNonCryptoID()
+ net := "mtu-test" + stringid.GenerateRandomID()
nc := podmanTest.Podman([]string{"network", "create", "--opt", "mtu=9000", net})
nc.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(net)
@@ -309,7 +309,7 @@ var _ = Describe("Podman network create", func() {
})
It("podman network create with vlan option", func() {
- net := "vlan-test" + stringid.GenerateNonCryptoID()
+ net := "vlan-test" + stringid.GenerateRandomID()
nc := podmanTest.Podman([]string{"network", "create", "--opt", "vlan=9", net})
nc.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(net)
@@ -322,7 +322,7 @@ var _ = Describe("Podman network create", func() {
})
It("podman network create with invalid option", func() {
- net := "invalid-test" + stringid.GenerateNonCryptoID()
+ net := "invalid-test" + stringid.GenerateRandomID()
nc := podmanTest.Podman([]string{"network", "create", "--opt", "foo=bar", net})
nc.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(net)
@@ -331,7 +331,7 @@ var _ = Describe("Podman network create", func() {
It("podman CNI network create with internal should not have dnsname", func() {
SkipIfNetavark(podmanTest)
- net := "internal-test" + stringid.GenerateNonCryptoID()
+ net := "internal-test" + stringid.GenerateRandomID()
nc := podmanTest.Podman([]string{"network", "create", "--internal", net})
nc.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(net)
@@ -349,7 +349,7 @@ var _ = Describe("Podman network create", func() {
It("podman Netavark network create with internal should have dnsname", func() {
SkipIfCNI(podmanTest)
- net := "internal-test" + stringid.GenerateNonCryptoID()
+ net := "internal-test" + stringid.GenerateRandomID()
nc := podmanTest.Podman([]string{"network", "create", "--internal", net})
nc.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(net)
@@ -375,7 +375,7 @@ var _ = Describe("Podman network create", func() {
})
It("podman network create with multiple subnets", func() {
- name := "subnets-" + stringid.GenerateNonCryptoID()
+ name := "subnets-" + stringid.GenerateRandomID()
subnet1 := "10.10.0.0/24"
subnet2 := "10.10.1.0/24"
nc := podmanTest.Podman([]string{"network", "create", "--subnet", subnet1, "--subnet", subnet2, name})
@@ -393,7 +393,7 @@ var _ = Describe("Podman network create", func() {
})
It("podman network create with multiple subnets dual stack", func() {
- name := "subnets-" + stringid.GenerateNonCryptoID()
+ name := "subnets-" + stringid.GenerateRandomID()
subnet1 := "10.10.2.0/24"
subnet2 := "fd52:2a5a:747e:3acd::/64"
nc := podmanTest.Podman([]string{"network", "create", "--subnet", subnet1, "--subnet", subnet2, name})
@@ -411,7 +411,7 @@ var _ = Describe("Podman network create", func() {
})
It("podman network create with multiple subnets dual stack with gateway and range", func() {
- name := "subnets-" + stringid.GenerateNonCryptoID()
+ name := "subnets-" + stringid.GenerateRandomID()
subnet1 := "10.10.3.0/24"
gw1 := "10.10.3.10"
range1 := "10.10.3.0/26"
@@ -436,7 +436,7 @@ var _ = Describe("Podman network create", func() {
})
It("podman network create invalid options with multiple subnets", func() {
- name := "subnets-" + stringid.GenerateNonCryptoID()
+ name := "subnets-" + stringid.GenerateRandomID()
subnet1 := "10.10.3.0/24"
gw1 := "10.10.3.10"
gw2 := "fd52:2a5a:747e:3acf::10"
diff --git a/test/e2e/network_test.go b/test/e2e/network_test.go
index d4f60d3e4..b2f50ca55 100644
--- a/test/e2e/network_test.go
+++ b/test/e2e/network_test.go
@@ -113,7 +113,7 @@ var _ = Describe("Podman network", func() {
})
It("podman network list --filter labels", func() {
- net1 := "labelnet" + stringid.GenerateNonCryptoID()
+ net1 := "labelnet" + stringid.GenerateRandomID()
label1 := "testlabel1=abc"
label2 := "abcdef"
session := podmanTest.Podman([]string{"network", "create", "--label", label1, net1})
@@ -121,7 +121,7 @@ var _ = Describe("Podman network", func() {
defer podmanTest.removeNetwork(net1)
Expect(session).Should(Exit(0))
- net2 := "labelnet" + stringid.GenerateNonCryptoID()
+ net2 := "labelnet" + stringid.GenerateRandomID()
session = podmanTest.Podman([]string{"network", "create", "--label", label1, "--label", label2, net2})
session.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(net2)
@@ -141,7 +141,7 @@ var _ = Describe("Podman network", func() {
})
It("podman network list --filter invalid value", func() {
- net := "net" + stringid.GenerateNonCryptoID()
+ net := "net" + stringid.GenerateRandomID()
session := podmanTest.Podman([]string{"network", "create", net})
session.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(net)
@@ -294,7 +294,7 @@ var _ = Describe("Podman network", func() {
})
It("podman inspect container single CNI network", func() {
- netName := "net-" + stringid.GenerateNonCryptoID()
+ netName := "net-" + stringid.GenerateRandomID()
network := podmanTest.Podman([]string{"network", "create", "--subnet", "10.50.50.0/24", netName})
network.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(netName)
@@ -324,13 +324,13 @@ var _ = Describe("Podman network", func() {
})
It("podman inspect container two CNI networks (container not running)", func() {
- netName1 := "net1-" + stringid.GenerateNonCryptoID()
+ netName1 := "net1-" + stringid.GenerateRandomID()
network1 := podmanTest.Podman([]string{"network", "create", netName1})
network1.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(netName1)
Expect(network1).Should(Exit(0))
- netName2 := "net2-" + stringid.GenerateNonCryptoID()
+ netName2 := "net2-" + stringid.GenerateRandomID()
network2 := podmanTest.Podman([]string{"network", "create", netName2})
network2.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(netName2)
@@ -361,13 +361,13 @@ var _ = Describe("Podman network", func() {
})
It("podman inspect container two CNI networks", func() {
- netName1 := "net1-" + stringid.GenerateNonCryptoID()
+ netName1 := "net1-" + stringid.GenerateRandomID()
network1 := podmanTest.Podman([]string{"network", "create", "--subnet", "10.50.51.0/25", netName1})
network1.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(netName1)
Expect(network1).Should(Exit(0))
- netName2 := "net2-" + stringid.GenerateNonCryptoID()
+ netName2 := "net2-" + stringid.GenerateRandomID()
network2 := podmanTest.Podman([]string{"network", "create", "--subnet", "10.50.51.128/26", netName2})
network2.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(netName2)
@@ -403,7 +403,7 @@ var _ = Describe("Podman network", func() {
It("podman network remove after disconnect when container initially created with the network", func() {
container := "test"
- network := "foo" + stringid.GenerateNonCryptoID()
+ network := "foo" + stringid.GenerateRandomID()
session := podmanTest.Podman([]string{"network", "create", network})
session.WaitWithDefaultTimeout()
@@ -430,7 +430,7 @@ var _ = Describe("Podman network", func() {
})
It("podman network remove --force with pod", func() {
- netName := "net-" + stringid.GenerateNonCryptoID()
+ netName := "net-" + stringid.GenerateRandomID()
session := podmanTest.Podman([]string{"network", "create", netName})
session.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(netName)
@@ -466,13 +466,13 @@ var _ = Describe("Podman network", func() {
})
It("podman network remove with two networks", func() {
- netName1 := "net1-" + stringid.GenerateNonCryptoID()
+ netName1 := "net1-" + stringid.GenerateRandomID()
session := podmanTest.Podman([]string{"network", "create", netName1})
session.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(netName1)
Expect(session).Should(Exit(0))
- netName2 := "net2-" + stringid.GenerateNonCryptoID()
+ netName2 := "net2-" + stringid.GenerateRandomID()
session = podmanTest.Podman([]string{"network", "create", netName2})
session.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(netName2)
@@ -591,7 +591,7 @@ var _ = Describe("Podman network", func() {
It("podman network create/remove macvlan", func() {
// Netavark currently does not do dhcp so the this test fails
SkipIfNetavark(podmanTest)
- net := "macvlan" + stringid.GenerateNonCryptoID()
+ net := "macvlan" + stringid.GenerateRandomID()
nc := podmanTest.Podman([]string{"network", "create", "--macvlan", "lo", net})
nc.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(net)
@@ -605,7 +605,7 @@ var _ = Describe("Podman network", func() {
It("podman network create/remove macvlan as driver (-d) no device name", func() {
// Netavark currently does not do dhcp so the this test fails
SkipIfNetavark(podmanTest)
- net := "macvlan" + stringid.GenerateNonCryptoID()
+ net := "macvlan" + stringid.GenerateRandomID()
nc := podmanTest.Podman([]string{"network", "create", "-d", "macvlan", net})
nc.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(net)
@@ -632,7 +632,7 @@ var _ = Describe("Podman network", func() {
It("podman network create/remove macvlan as driver (-d) with device name", func() {
// Netavark currently does not do dhcp so the this test fails
SkipIfNetavark(podmanTest)
- net := "macvlan" + stringid.GenerateNonCryptoID()
+ net := "macvlan" + stringid.GenerateRandomID()
nc := podmanTest.Podman([]string{"network", "create", "-d", "macvlan", "-o", "parent=lo", net})
nc.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(net)
@@ -659,7 +659,7 @@ var _ = Describe("Podman network", func() {
})
It("podman network exists", func() {
- net := "net" + stringid.GenerateNonCryptoID()
+ net := "net" + stringid.GenerateRandomID()
session := podmanTest.Podman([]string{"network", "create", net})
session.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(net)
@@ -669,13 +669,13 @@ var _ = Describe("Podman network", func() {
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- session = podmanTest.Podman([]string{"network", "exists", stringid.GenerateNonCryptoID()})
+ session = podmanTest.Podman([]string{"network", "exists", stringid.GenerateRandomID()})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(1))
})
It("podman network create macvlan with network info and options", func() {
- net := "macvlan" + stringid.GenerateNonCryptoID()
+ net := "macvlan" + stringid.GenerateRandomID()
nc := podmanTest.Podman([]string{"network", "create", "-d", "macvlan", "-o", "parent=lo", "-o", "mtu=1500", "--gateway", "192.168.1.254", "--subnet", "192.168.1.0/24", net})
nc.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(net)
@@ -711,7 +711,7 @@ var _ = Describe("Podman network", func() {
if IsRemote() {
podmanTest.RestartRemoteService()
}
- net1 := "macvlan" + stringid.GenerateNonCryptoID() + "net1"
+ net1 := "macvlan" + stringid.GenerateRandomID() + "net1"
nc := podmanTest.Podman([]string{"network", "create", net1})
nc.WaitWithDefaultTimeout()
@@ -764,7 +764,7 @@ var _ = Describe("Podman network", func() {
// Run a container on one of them
// Network Prune
// Check that one has been pruned, other remains
- net := "macvlan" + stringid.GenerateNonCryptoID()
+ net := "macvlan" + stringid.GenerateRandomID()
net1 := net + "1"
net2 := net + "2"
nc := podmanTest.Podman([]string{"network", "create", net1})
diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go
index 1b4eefd45..26460c937 100644
--- a/test/e2e/play_kube_test.go
+++ b/test/e2e/play_kube_test.go
@@ -380,6 +380,9 @@ spec:
restartPolicy: {{ .RestartPolicy }}
hostname: {{ .Hostname }}
hostNetwork: {{ .HostNetwork }}
+{{ if .HostUsers }}
+ hostUsers: {{ .HostUsers }}
+{{ end }}
hostAliases:
{{ range .HostAliases }}
- hostnames:
@@ -509,6 +512,9 @@ spec:
volumes:
{{ range . }}
- name: {{ .Name }}
+ {{- if (eq .VolumeType "EmptyDir") }}
+ emptyDir: {}
+ {{- end }}
{{- if (eq .VolumeType "HostPath") }}
hostPath:
path: {{ .HostPath.Path }}
@@ -841,6 +847,7 @@ type Pod struct {
RestartPolicy string
Hostname string
HostNetwork bool
+ HostUsers *bool
HostAliases []HostAlias
Ctrs []*Ctr
InitCtrs []*Ctr
@@ -965,6 +972,12 @@ func withHostNetwork() podOption {
}
}
+func withHostUsers(val bool) podOption {
+ return func(pod *Pod) {
+ pod.HostUsers = &val
+ }
+}
+
// Deployment describes the options a kube yaml can be configured at deployment level
type Deployment struct {
Name string
@@ -1242,12 +1255,15 @@ type ConfigMap struct {
Optional bool
}
+type EmptyDir struct{}
+
type Volume struct {
VolumeType string
Name string
HostPath
PersistentVolumeClaim
ConfigMap
+ EmptyDir
}
// getHostPathVolume takes a type and a location for a HostPath
@@ -1289,6 +1305,14 @@ func getConfigMapVolume(vName string, items []map[string]string, optional bool)
}
}
+func getEmptyDirVolume() *Volume {
+ return &Volume{
+ VolumeType: "EmptyDir",
+ Name: defaultVolName,
+ EmptyDir: EmptyDir{},
+ }
+}
+
type Env struct {
Name string
Value string
@@ -2409,7 +2433,7 @@ spec:
err := generateKubeYaml("deployment", deployment, kubeYaml)
Expect(err).To(BeNil())
- net := "playkube" + stringid.GenerateNonCryptoID()
+ net := "playkube" + stringid.GenerateRandomID()
session := podmanTest.Podman([]string{"network", "create", "--subnet", "10.25.31.0/24", net})
session.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(net)
@@ -2451,8 +2475,8 @@ spec:
err := generateKubeYaml("pod", pod, kubeYaml)
Expect(err).To(BeNil())
- net1 := "net1" + stringid.GenerateNonCryptoID()
- net2 := "net2" + stringid.GenerateNonCryptoID()
+ net1 := "net1" + stringid.GenerateRandomID()
+ net2 := "net2" + stringid.GenerateRandomID()
net := podmanTest.Podman([]string{"network", "create", "--subnet", "10.0.11.0/24", net1})
net.WaitWithDefaultTimeout()
@@ -2482,7 +2506,7 @@ spec:
It("podman play kube test with network portbindings", func() {
ip := "127.0.0.100"
- port := "5000"
+ port := "8087"
ctr := getCtr(withHostIP(ip, port), withImage(BB))
pod := getPod(withCtr(ctr))
@@ -2496,7 +2520,7 @@ spec:
inspect := podmanTest.Podman([]string{"port", getCtrNameInPod(pod)})
inspect.WaitWithDefaultTimeout()
Expect(inspect).Should(Exit(0))
- Expect(inspect.OutputToString()).To(Equal("5000/tcp -> 127.0.0.100:5000"))
+ Expect(inspect.OutputToString()).To(Equal("8087/tcp -> 127.0.0.100:8087"))
})
It("podman play kube test with nonexistent empty HostPath type volume", func() {
@@ -2762,6 +2786,43 @@ VOLUME %s`, ALPINE, hostPathDir+"/")
Expect(kube).Should(Exit(0))
})
+ It("podman play kube with emptyDir volume", func() {
+ podName := "test-pod"
+ ctrName1 := "vol-test-ctr"
+ ctrName2 := "vol-test-ctr-2"
+ ctr1 := getCtr(withVolumeMount("/test-emptydir", false), withImage(BB), withName(ctrName1))
+ ctr2 := getCtr(withVolumeMount("/test-emptydir-2", false), withImage(BB), withName(ctrName2))
+ pod := getPod(withPodName(podName), withVolume(getEmptyDirVolume()), withCtr(ctr1), withCtr(ctr2))
+ err = generateKubeYaml("pod", pod, kubeYaml)
+ Expect(err).To(BeNil())
+
+ kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube).Should(Exit(0))
+
+ emptyDirCheck1 := podmanTest.Podman([]string{"exec", podName + "-" + ctrName1, "ls", "/test-emptydir"})
+ emptyDirCheck1.WaitWithDefaultTimeout()
+ Expect(emptyDirCheck1).Should(Exit(0))
+
+ emptyDirCheck2 := podmanTest.Podman([]string{"exec", podName + "-" + ctrName2, "ls", "/test-emptydir-2"})
+ emptyDirCheck2.WaitWithDefaultTimeout()
+ Expect(emptyDirCheck2).Should(Exit(0))
+
+ volList1 := podmanTest.Podman([]string{"volume", "ls", "-q"})
+ volList1.WaitWithDefaultTimeout()
+ Expect(volList1).Should(Exit(0))
+ Expect(volList1.OutputToString()).To(Equal(defaultVolName))
+
+ remove := podmanTest.Podman([]string{"pod", "rm", "-f", podName})
+ remove.WaitWithDefaultTimeout()
+ Expect(remove).Should(Exit(0))
+
+ volList2 := podmanTest.Podman([]string{"volume", "ls", "-q"})
+ volList2.WaitWithDefaultTimeout()
+ Expect(volList2).Should(Exit(0))
+ Expect(volList2.OutputToString()).To(Equal(""))
+ })
+
It("podman play kube applies labels to pods", func() {
var numReplicas int32 = 5
expectedLabelKey := "key1"
@@ -3732,8 +3793,7 @@ ENV OPENJ9_JAVA_OPTIONS=%q
Expect((inspect.InspectContainerToJSON()[0]).HostConfig.LogConfig.Tag).To(Equal("{{.ImageName}}"))
})
- // Check that --userns=auto creates a user namespace
- It("podman play kube --userns=auto", func() {
+ It("podman play kube using a user namespace", func() {
u, err := user.Current()
Expect(err).To(BeNil())
name := u.Name
@@ -3780,6 +3840,26 @@ ENV OPENJ9_JAVA_OPTIONS=%q
usernsInCtr.WaitWithDefaultTimeout()
Expect(usernsInCtr).Should(Exit(0))
Expect(string(usernsInCtr.Out.Contents())).To(Not(Equal(string(initialUsernsConfig))))
+
+ // Now try with hostUsers in the pod spec
+ for _, hostUsers := range []bool{true, false} {
+ pod = getPod(withHostUsers(hostUsers))
+ err = generateKubeYaml("pod", pod, kubeYaml)
+ Expect(err).To(BeNil())
+
+ kube = podmanTest.PodmanNoCache([]string{"play", "kube", "--replace", kubeYaml})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube).Should(Exit(0))
+
+ usernsInCtr = podmanTest.Podman([]string{"exec", getCtrNameInPod(pod), "cat", "/proc/self/uid_map"})
+ usernsInCtr.WaitWithDefaultTimeout()
+ Expect(usernsInCtr).Should(Exit(0))
+ if hostUsers {
+ Expect(string(usernsInCtr.Out.Contents())).To(Equal(string(initialUsernsConfig)))
+ } else {
+ Expect(string(usernsInCtr.Out.Contents())).To(Not(Equal(string(initialUsernsConfig))))
+ }
+ }
})
// Check the block devices are exposed inside container
diff --git a/test/e2e/pod_inspect_test.go b/test/e2e/pod_inspect_test.go
index 351317cc5..cefdee40a 100644
--- a/test/e2e/pod_inspect_test.go
+++ b/test/e2e/pod_inspect_test.go
@@ -118,4 +118,21 @@ var _ = Describe("Podman pod inspect", func() {
Expect(inspectOut.OutputToString()).To(ContainSubstring(macAddr))
})
+
+ It("podman inspect two pods", func() {
+ _, ec, podid1 := podmanTest.CreatePod(nil)
+ Expect(ec).To(Equal(0))
+
+ _, ec, podid2 := podmanTest.CreatePod(nil)
+ Expect(ec).To(Equal(0))
+
+ inspect := podmanTest.Podman([]string{"pod", "inspect", podid1, podid2})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect).Should(Exit(0))
+ Expect(inspect.OutputToString()).To(BeValidJSON())
+ podData := inspect.InspectPodArrToJSON()
+ Expect(podData).To(HaveLen(2))
+ Expect(podData[0]).To(HaveField("ID", podid1))
+ Expect(podData[1]).To(HaveField("ID", podid2))
+ })
})
diff --git a/test/e2e/pod_ps_test.go b/test/e2e/pod_ps_test.go
index 97ca5ff94..20335f322 100644
--- a/test/e2e/pod_ps_test.go
+++ b/test/e2e/pod_ps_test.go
@@ -294,7 +294,7 @@ var _ = Describe("Podman ps", func() {
})
It("podman pod ps filter network", func() {
- net := stringid.GenerateNonCryptoID()
+ net := stringid.GenerateRandomID()
session := podmanTest.Podman([]string{"network", "create", net})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
@@ -333,12 +333,12 @@ var _ = Describe("Podman ps", func() {
Expect(session.OutputToString()).To(Equal("podman"))
}
- net1 := stringid.GenerateNonCryptoID()
+ net1 := stringid.GenerateRandomID()
session = podmanTest.Podman([]string{"network", "create", net1})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
defer podmanTest.removeNetwork(net1)
- net2 := stringid.GenerateNonCryptoID()
+ net2 := stringid.GenerateRandomID()
session = podmanTest.Podman([]string{"network", "create", net2})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
diff --git a/test/e2e/pod_rm_test.go b/test/e2e/pod_rm_test.go
index a5eab7eed..364ef54d5 100644
--- a/test/e2e/pod_rm_test.go
+++ b/test/e2e/pod_rm_test.go
@@ -318,4 +318,31 @@ var _ = Describe("Podman pod rm", func() {
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
})
+
+ It("podman pod rm pod with infra container and running container", func() {
+ podName := "testPod"
+ ctrName := "testCtr"
+
+ ctrAndPod := podmanTest.Podman([]string{"run", "-d", "--pod", fmt.Sprintf("new:%s", podName), "--name", ctrName, ALPINE, "top"})
+ ctrAndPod.WaitWithDefaultTimeout()
+ Expect(ctrAndPod).Should(Exit(0))
+
+ removePod := podmanTest.Podman([]string{"pod", "rm", "-a"})
+ removePod.WaitWithDefaultTimeout()
+ Expect(removePod).Should(Not(Exit(0)))
+
+ ps := podmanTest.Podman([]string{"pod", "ps"})
+ ps.WaitWithDefaultTimeout()
+ Expect(ps).Should(Exit(0))
+ Expect(ps.OutputToString()).To(ContainSubstring(podName))
+
+ removePodForce := podmanTest.Podman([]string{"pod", "rm", "-af"})
+ removePodForce.WaitWithDefaultTimeout()
+ Expect(removePodForce).Should(Exit(0))
+
+ ps2 := podmanTest.Podman([]string{"pod", "ps"})
+ ps2.WaitWithDefaultTimeout()
+ Expect(ps2).Should(Exit(0))
+ Expect(ps2.OutputToString()).To(Not(ContainSubstring(podName)))
+ })
})
diff --git a/test/e2e/ps_test.go b/test/e2e/ps_test.go
index 1100a5d90..cc037545c 100644
--- a/test/e2e/ps_test.go
+++ b/test/e2e/ps_test.go
@@ -817,7 +817,7 @@ var _ = Describe("Podman ps", func() {
})
It("podman ps filter network", func() {
- net := stringid.GenerateNonCryptoID()
+ net := stringid.GenerateRandomID()
session := podmanTest.Podman([]string{"network", "create", net})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
@@ -860,12 +860,12 @@ var _ = Describe("Podman ps", func() {
Expect(actual).To(Equal("podman"))
}
- net1 := stringid.GenerateNonCryptoID()
+ net1 := stringid.GenerateRandomID()
session = podmanTest.Podman([]string{"network", "create", net1})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
defer podmanTest.removeNetwork(net1)
- net2 := stringid.GenerateNonCryptoID()
+ net2 := stringid.GenerateRandomID()
session = podmanTest.Podman([]string{"network", "create", net2})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
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/push_test.go b/test/e2e/push_test.go
index f2a103f6b..a73b7c87b 100644
--- a/test/e2e/push_test.go
+++ b/test/e2e/push_test.go
@@ -4,6 +4,7 @@ import (
"fmt"
"io/ioutil"
"os"
+ "os/exec"
"path/filepath"
"strings"
@@ -77,7 +78,7 @@ var _ = Describe("Podman push", func() {
blobsDir := filepath.Join(bbdir, "blobs/sha256")
- blobs, err := ioutil.ReadDir(blobsDir)
+ blobs, err := os.ReadDir(blobsDir)
Expect(err).To(BeNil())
for _, f := range blobs {
@@ -136,6 +137,45 @@ var _ = Describe("Podman push", func() {
Expect(fi.Name()).To(Equal("digestfile.txt"))
Expect(push2).Should(Exit(0))
}
+
+ if !IsRemote() { // Remote does not support signing
+ By("pushing and pulling with sigstore signatures")
+ // Ideally, this should set SystemContext.RegistriesDirPath, but Podman currently doesn’t
+ // expose that as an option. So, for now, modify /etc/directly, and skip testing sigstore if
+ // we don’t have permission to do so.
+ systemRegistriesDAddition := "/etc/containers/registries.d/podman-test-only-temporary-addition.yaml"
+ cmd := exec.Command("cp", "testdata/sigstore-registries.d-fragment.yaml", systemRegistriesDAddition)
+ output, err := cmd.CombinedOutput()
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Skipping sigstore tests because /etc/containers/registries.d isn’t writable: %s", string(output))
+ } else {
+ defer func() {
+ err := os.Remove(systemRegistriesDAddition)
+ Expect(err).ToNot(HaveOccurred())
+ }()
+
+ // Verify that the policy rejects unsigned images
+ push := podmanTest.Podman([]string{"push", "-q", "--tls-verify=false", "--remove-signatures", ALPINE, "localhost:5000/sigstore-signed"})
+ push.WaitWithDefaultTimeout()
+ Expect(push).Should(Exit(0))
+ Expect(len(push.ErrorToString())).To(Equal(0))
+
+ pull := podmanTest.Podman([]string{"pull", "-q", "--tls-verify=false", "--signature-policy", "sign/policy.json", "localhost:5000/sigstore-signed"})
+ pull.WaitWithDefaultTimeout()
+ Expect(pull).To(ExitWithError())
+ Expect(pull.ErrorToString()).To(ContainSubstring("A signature was required, but no signature exists"))
+
+ // Sign an image, and verify it is accepted.
+ push = podmanTest.Podman([]string{"push", "-q", "--tls-verify=false", "--remove-signatures", "--sign-by-sigstore-private-key", "testdata/sigstore-key.key", "--sign-passphrase-file", "testdata/sigstore-key.key.pass", ALPINE, "localhost:5000/sigstore-signed"})
+ push.WaitWithDefaultTimeout()
+ Expect(push).Should(Exit(0))
+ Expect(len(push.ErrorToString())).To(Equal(0))
+
+ pull = podmanTest.Podman([]string{"pull", "-q", "--tls-verify=false", "--signature-policy", "sign/policy.json", "localhost:5000/sigstore-signed"})
+ pull.WaitWithDefaultTimeout()
+ Expect(pull).Should(Exit(0))
+ }
+ }
})
It("podman push to local registry with authorization", func() {
@@ -167,20 +207,20 @@ var _ = Describe("Podman push", func() {
}
lock := GetPortLock("5000")
defer lock.Unlock()
- session := podmanTest.Podman([]string{"run", "--entrypoint", "htpasswd", REGISTRY_IMAGE, "-Bbn", "podmantest", "test"})
- session.WaitWithDefaultTimeout()
- Expect(session).Should(Exit(0))
+ htpasswd := SystemExec("htpasswd", []string{"-Bbn", "podmantest", "test"})
+ htpasswd.WaitWithDefaultTimeout()
+ Expect(htpasswd).Should(Exit(0))
f, err := os.Create(filepath.Join(authPath, "htpasswd"))
Expect(err).ToNot(HaveOccurred())
defer f.Close()
- _, err = f.WriteString(session.OutputToString())
+ _, err = f.WriteString(htpasswd.OutputToString())
Expect(err).ToNot(HaveOccurred())
err = f.Sync()
Expect(err).ToNot(HaveOccurred())
- session = podmanTest.Podman([]string{"run", "-d", "-p", "5000:5000", "--name", "registry", "-v",
+ session := podmanTest.Podman([]string{"run", "-d", "-p", "5000:5000", "--name", "registry", "-v",
strings.Join([]string{authPath, "/auth"}, ":"), "-e", "REGISTRY_AUTH=htpasswd", "-e",
"REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm", "-e", "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd",
"-v", strings.Join([]string{certPath, "/certs"}, ":"), "-e", "REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt",
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/rm_test.go b/test/e2e/rm_test.go
index 7dbe5fed8..e76451824 100644
--- a/test/e2e/rm_test.go
+++ b/test/e2e/rm_test.go
@@ -1,6 +1,7 @@
package integration
import (
+ "fmt"
"io/ioutil"
"os"
@@ -51,6 +52,7 @@ var _ = Describe("Podman rm", func() {
result := podmanTest.Podman([]string{"rm", cid})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(2))
+ Expect(result.ErrorToString()).To(ContainSubstring("containers cannot be removed without force"))
})
It("podman rm created container", func() {
@@ -140,11 +142,9 @@ var _ = Describe("Podman rm", func() {
output := result.OutputToString()
Expect(output).To(ContainSubstring(cid))
Expect(podmanTest.NumberOfContainers()).To(Equal(1))
-
})
It("podman rm --cidfile", func() {
-
tmpDir, err := ioutil.TempDir("", "")
Expect(err).To(BeNil())
tmpFile := tmpDir + "cid"
@@ -166,7 +166,6 @@ var _ = Describe("Podman rm", func() {
})
It("podman rm multiple --cidfile", func() {
-
tmpDir, err := ioutil.TempDir("", "")
Expect(err).To(BeNil())
tmpFile1 := tmpDir + "cid-1"
@@ -201,18 +200,22 @@ var _ = Describe("Podman rm", func() {
result := podmanTest.Podman([]string{"rm", "--cidfile", "foobar", "--latest"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(125))
+ Expect(result.ErrorToString()).To(ContainSubstring("--all, --latest, and --cidfile cannot be used together"))
result = podmanTest.Podman([]string{"rm", "--cidfile", "foobar", "--all"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(125))
+ Expect(result.ErrorToString()).To(ContainSubstring("--all, --latest, and --cidfile cannot be used together"))
result = podmanTest.Podman([]string{"rm", "--cidfile", "foobar", "--all", "--latest"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(125))
+ Expect(result.ErrorToString()).To(ContainSubstring("--all, --latest, and --cidfile cannot be used together"))
result = podmanTest.Podman([]string{"rm", "--latest", "--all"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(125))
+ Expect(result.ErrorToString()).To(ContainSubstring("--all and --latest cannot be used together"))
})
It("podman rm --all", func() {
@@ -242,10 +245,17 @@ var _ = Describe("Podman rm", func() {
session = podmanTest.Podman([]string{"rm", "bogus", cid})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(1))
+ Expect(session.ErrorToString()).To(ContainSubstring("\"bogus\" found: no such container"))
+ if IsRemote() {
+ Expect(session.OutputToString()).To(BeEquivalentTo(cid))
+ }
session = podmanTest.Podman([]string{"rm", "--ignore", "bogus", cid})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
+ if !IsRemote() {
+ Expect(session.OutputToString()).To(BeEquivalentTo(cid))
+ }
Expect(podmanTest.NumberOfContainers()).To(Equal(0))
})
@@ -253,6 +263,7 @@ var _ = Describe("Podman rm", func() {
session := podmanTest.Podman([]string{"rm", "bogus"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(1))
+ Expect(session.ErrorToString()).To(ContainSubstring("\"bogus\" found: no such container"))
})
It("podman rm bogus container and a running container", func() {
@@ -263,10 +274,12 @@ var _ = Describe("Podman rm", func() {
session = podmanTest.Podman([]string{"rm", "bogus", "test1"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(1))
+ Expect(session.ErrorToString()).To(ContainSubstring("\"bogus\" found: no such container"))
session = podmanTest.Podman([]string{"rm", "test1", "bogus"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(1))
+ Expect(session.ErrorToString()).To(ContainSubstring("\"bogus\" found: no such container"))
})
It("podman rm --ignore bogus container and a running container", func() {
@@ -274,12 +287,52 @@ var _ = Describe("Podman rm", func() {
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- session = podmanTest.Podman([]string{"rm", "-t", "0", "--force", "--ignore", "bogus", "test1"})
+ session = podmanTest.Podman([]string{"rm", "--ignore", "test1", "bogus"})
session.WaitWithDefaultTimeout()
- Expect(session).Should(Exit(0))
+ Expect(session).Should(Exit(2))
+ Expect(session.ErrorToString()).To(ContainSubstring("containers cannot be removed without force"))
- session = podmanTest.Podman([]string{"rm", "--ignore", "test1", "bogus"})
+ session = podmanTest.Podman([]string{"rm", "-t", "0", "--force", "--ignore", "bogus", "test1"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).To(BeEquivalentTo("test1"))
+ })
+
+ It("podman rm --filter", func() {
+ session1 := podmanTest.RunTopContainer("test1")
+ session1.WaitWithDefaultTimeout()
+ Expect(session1).Should(Exit(0))
+ cid1 := session1.OutputToString()
+
+ session1 = podmanTest.RunTopContainer("test2")
+ session1.WaitWithDefaultTimeout()
+ Expect(session1).Should(Exit(0))
+ cid2 := session1.OutputToString()
+
+ session1 = podmanTest.RunTopContainer("test3")
+ session1.WaitWithDefaultTimeout()
+ Expect(session1).Should(Exit(0))
+ cid3 := session1.OutputToString()
+ shortCid3 := cid3[0:5]
+
+ session1 = podmanTest.Podman([]string{"rm", cid1, "-f", "--filter", "status=running"})
+ session1.WaitWithDefaultTimeout()
+ Expect(session1).Should(Exit(125))
+ Expect(session1.ErrorToString()).To(ContainSubstring("--filter takes no arguments"))
+
+ session1 = podmanTest.Podman([]string{"rm", "-a", "-f", "--filter", fmt.Sprintf("id=%swrongid", shortCid3)})
+ session1.WaitWithDefaultTimeout()
+ Expect(session1).Should(Exit(0))
+ Expect(session1.OutputToString()).To(HaveLen(0))
+
+ session1 = podmanTest.Podman([]string{"rm", "-a", "-f", "--filter", fmt.Sprintf("id=%s", shortCid3)})
+ session1.WaitWithDefaultTimeout()
+ Expect(session1).Should(Exit(0))
+ Expect(session1.OutputToString()).To(BeEquivalentTo(cid3))
+
+ session1 = podmanTest.Podman([]string{"rm", "-f", "--filter", fmt.Sprintf("id=%s", cid2)})
+ session1.WaitWithDefaultTimeout()
+ Expect(session1).Should(Exit(0))
+ Expect(session1.OutputToString()).To(BeEquivalentTo(cid2))
})
})
diff --git a/test/e2e/rmi_test.go b/test/e2e/rmi_test.go
index d1a0cd6f5..f87f65c34 100644
--- a/test/e2e/rmi_test.go
+++ b/test/e2e/rmi_test.go
@@ -307,4 +307,82 @@ RUN touch %s`, CIRROS_IMAGE, imageName)
}
wg.Wait()
})
+
+ It("podman rmi --no-prune with dangling parents", func() {
+ podmanTest.AddImageToRWStore(ALPINE)
+ session := podmanTest.Podman([]string{"create", "--name", "c_test1", ALPINE, "true"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ session = podmanTest.Podman([]string{"commit", "-q", "c_test1", "test1"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ session = podmanTest.Podman([]string{"create", "--name", "c_test2", "test1", "true"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ session = podmanTest.Podman([]string{"commit", "-q", "c_test2", "test2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ imageID2 := session.OutputToString()
+
+ session = podmanTest.Podman([]string{"create", "--name", "c_test3", "test2", "true"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ session = podmanTest.Podman([]string{"commit", "-q", "c_test3", "test3"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ imageID3 := session.OutputToString()
+
+ session = podmanTest.Podman([]string{"untag", "test2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ session = podmanTest.Podman([]string{"untag", "test1"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ session = podmanTest.Podman([]string{"rmi", "-f", "--no-prune", "test3"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).To(ContainSubstring(imageID3))
+ Expect(session.OutputToString()).NotTo(ContainSubstring(imageID2))
+ })
+
+ It("podman rmi --no-prune with undangling parents", func() {
+ podmanTest.AddImageToRWStore(ALPINE)
+ session := podmanTest.Podman([]string{"create", "--name", "c_test1", ALPINE, "true"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ session = podmanTest.Podman([]string{"commit", "-q", "c_test1", "test1"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ session = podmanTest.Podman([]string{"create", "--name", "c_test2", "test1", "true"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ session = podmanTest.Podman([]string{"commit", "-q", "c_test2", "test2"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ imageID2 := session.OutputToString()
+
+ session = podmanTest.Podman([]string{"create", "--name", "c_test3", "test2", "true"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ session = podmanTest.Podman([]string{"commit", "-q", "c_test3", "test3"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ imageID3 := session.OutputToString()
+
+ session = podmanTest.Podman([]string{"rmi", "-f", "--no-prune", "test3"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).To(ContainSubstring(imageID3))
+ Expect(session.OutputToString()).NotTo(ContainSubstring(imageID2))
+ })
})
diff --git a/test/e2e/run_cleanup_test.go b/test/e2e/run_cleanup_test.go
index ea2caf907..5aa81140d 100644
--- a/test/e2e/run_cleanup_test.go
+++ b/test/e2e/run_cleanup_test.go
@@ -36,7 +36,7 @@ var _ = Describe("Podman run exit", func() {
It("podman run -d mount cleanup test", func() {
SkipIfRemote("podman-remote does not support mount")
- SkipIfRootless("TODO rootless podman mount requires podman unshare first")
+ SkipIfRootless("rootless podman mount requires podman unshare first")
result := podmanTest.Podman([]string{"run", "-dt", ALPINE, "top"})
result.WaitWithDefaultTimeout()
@@ -69,6 +69,49 @@ var _ = Describe("Podman run exit", func() {
pmount.WaitWithDefaultTimeout()
Expect(pmount).Should(Exit(0))
Expect(pmount.OutputToString()).NotTo(ContainSubstring(cid))
+ })
+
+ It("podman run -d mount cleanup rootless test", func() {
+ SkipIfRemote("podman-remote does not support mount")
+ SkipIfNotRootless("Use unshare in rootless only")
+
+ result := podmanTest.Podman([]string{"run", "-dt", ALPINE, "top"})
+ result.WaitWithDefaultTimeout()
+ cid := result.OutputToString()
+ Expect(result).Should(Exit(0))
+
+ mount := podmanTest.Podman([]string{"unshare", "mount"})
+ mount.WaitWithDefaultTimeout()
+ Expect(mount).Should(Exit(0))
+ Expect(mount.OutputToString()).To(ContainSubstring(cid))
+
+ // command: podman <options> unshare podman <options> image mount ALPINE
+ args := []string{"unshare", podmanTest.PodmanBinary}
+ opts := podmanTest.PodmanMakeOptions([]string{"mount", "--no-trunc"}, false, false)
+ args = append(args, opts...)
+
+ pmount := podmanTest.Podman(args)
+ pmount.WaitWithDefaultTimeout()
+ Expect(pmount).Should(Exit(0))
+ Expect(pmount.OutputToString()).To(ContainSubstring(cid))
+ stop := podmanTest.Podman([]string{"stop", cid})
+ stop.WaitWithDefaultTimeout()
+ Expect(stop).Should(Exit(0))
+
+ // We have to force cleanup so the unmount happens
+ podmanCleanupSession := podmanTest.Podman([]string{"container", "cleanup", cid})
+ podmanCleanupSession.WaitWithDefaultTimeout()
+ Expect(podmanCleanupSession).Should(Exit(0))
+
+ mount = podmanTest.Podman([]string{"unshare", "mount"})
+ mount.WaitWithDefaultTimeout()
+ Expect(mount).Should(Exit(0))
+ Expect(mount.OutputToString()).NotTo(ContainSubstring(cid))
+
+ pmount = podmanTest.Podman(args)
+ pmount.WaitWithDefaultTimeout()
+ Expect(pmount).Should(Exit(0))
+ Expect(pmount.OutputToString()).NotTo(ContainSubstring(cid))
})
})
diff --git a/test/e2e/run_cpu_test.go b/test/e2e/run_cpu_test.go
index e57eb3b26..19bb735ff 100644
--- a/test/e2e/run_cpu_test.go
+++ b/test/e2e/run_cpu_test.go
@@ -138,4 +138,20 @@ var _ = Describe("Podman run cpu", func() {
result.WaitWithDefaultTimeout()
Expect(result).To(ExitWithError())
})
+
+ It("podman run invalid cpu-rt-period with cgroupsv2", func() {
+ SkipIfCgroupV1("testing options that only work in cgroup v2")
+ result := podmanTest.Podman([]string{"run", "--rm", "--cpu-rt-period=5000", ALPINE, "ls"})
+ result.WaitWithDefaultTimeout()
+ Expect(result).Should(Exit(0))
+ Expect(result.ErrorToString()).To(ContainSubstring("Realtime period not supported on cgroups V2 systems"))
+ })
+
+ It("podman run invalid cpu-rt-runtime with cgroupsv2", func() {
+ SkipIfCgroupV1("testing options that only work in cgroup v2")
+ result := podmanTest.Podman([]string{"run", "--rm", "--cpu-rt-runtime=5000", ALPINE, "ls"})
+ result.WaitWithDefaultTimeout()
+ Expect(result).Should(Exit(0))
+ Expect(result.ErrorToString()).To(ContainSubstring("Realtime runtime not supported on cgroups V2 systems"))
+ })
})
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_networking_test.go b/test/e2e/run_networking_test.go
index 1ad78c950..78e4a62c0 100644
--- a/test/e2e/run_networking_test.go
+++ b/test/e2e/run_networking_test.go
@@ -869,7 +869,7 @@ EXPOSE 2004-2005/tcp`, ALPINE)
})
It("podman run in custom CNI network with --static-ip", func() {
- netName := stringid.GenerateNonCryptoID()
+ netName := stringid.GenerateRandomID()
ipAddr := "10.25.30.128"
create := podmanTest.Podman([]string{"network", "create", "--subnet", "10.25.30.0/24", netName})
create.WaitWithDefaultTimeout()
@@ -884,7 +884,7 @@ EXPOSE 2004-2005/tcp`, ALPINE)
It("podman CNI network works across user ns", func() {
SkipIfNetavark(podmanTest)
- netName := stringid.GenerateNonCryptoID()
+ netName := stringid.GenerateRandomID()
create := podmanTest.Podman([]string{"network", "create", netName})
create.WaitWithDefaultTimeout()
Expect(create).Should(Exit(0))
@@ -933,7 +933,7 @@ EXPOSE 2004-2005/tcp`, ALPINE)
})
It("podman run with new:pod and static-ip", func() {
- netName := stringid.GenerateNonCryptoID()
+ netName := stringid.GenerateRandomID()
ipAddr := "10.25.40.128"
podname := "testpod"
create := podmanTest.Podman([]string{"network", "create", "--subnet", "10.25.40.0/24", netName})
@@ -1121,7 +1121,7 @@ EXPOSE 2004-2005/tcp`, ALPINE)
// see https://github.com/containers/podman/issues/12972
It("podman run check network-alias works on networks without dns", func() {
- net := "dns" + stringid.GenerateNonCryptoID()
+ net := "dns" + stringid.GenerateRandomID()
session := podmanTest.Podman([]string{"network", "create", "--disable-dns", net})
session.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(net)
@@ -1135,7 +1135,7 @@ EXPOSE 2004-2005/tcp`, ALPINE)
It("podman run with ipam none driver", func() {
// Test fails, issue #13931
SkipIfNetavark(podmanTest)
- net := "ipam" + stringid.GenerateNonCryptoID()
+ net := "ipam" + stringid.GenerateRandomID()
session := podmanTest.Podman([]string{"network", "create", "--ipam-driver=none", net})
session.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(net)
diff --git a/test/e2e/run_staticip_test.go b/test/e2e/run_staticip_test.go
index 8207f6d0b..057fbf775 100644
--- a/test/e2e/run_staticip_test.go
+++ b/test/e2e/run_staticip_test.go
@@ -66,7 +66,7 @@ var _ = Describe("Podman run with --ip flag", func() {
})
It("Podman run with specified static IPv6 has correct IP", func() {
- netName := "ipv6-" + stringid.GenerateNonCryptoID()
+ netName := "ipv6-" + stringid.GenerateRandomID()
ipv6 := "fd46:db93:aa76:ac37::10"
net := podmanTest.Podman([]string{"network", "create", "--subnet", "fd46:db93:aa76:ac37::/64", netName})
net.WaitWithDefaultTimeout()
@@ -105,6 +105,13 @@ var _ = Describe("Podman run with --ip flag", func() {
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
+ // We need to set "no_proxy" in proxy environment
+ if env, found := os.LookupEnv("no_proxy"); found {
+ defer os.Setenv("no_proxy", env)
+ } else {
+ defer os.Unsetenv("no_proxy")
+ }
+ os.Setenv("no_proxy", ip)
for retries := 20; retries > 0; retries-- {
response, err := http.Get(fmt.Sprintf("http://%s", ip))
if err == nil && response.StatusCode == http.StatusOK {
diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go
index c7a0b3f2b..3fbdd4339 100644
--- a/test/e2e/run_test.go
+++ b/test/e2e/run_test.go
@@ -222,7 +222,7 @@ var _ = Describe("Podman run", func() {
It("podman run a container with a --rootfs", func() {
rootfs := filepath.Join(tempdir, "rootfs")
uls := filepath.Join("/", "usr", "local", "share")
- uniqueString := stringid.GenerateNonCryptoID()
+ uniqueString := stringid.GenerateRandomID()
testFilePath := filepath.Join(uls, uniqueString)
tarball := filepath.Join(tempdir, "rootfs.tar")
@@ -848,7 +848,7 @@ USER bin`, BB)
err = ioutil.WriteFile(hookJSONPath, []byte(hookJSON), 0644)
Expect(err).ToNot(HaveOccurred())
- random := stringid.GenerateNonCryptoID()
+ random := stringid.GenerateRandomID()
hookScript := fmt.Sprintf(`#!/bin/sh
echo -n %s >%s
@@ -945,7 +945,7 @@ echo -n %s >%s
session := podmanTest.Podman([]string{"run", "--rm", "--user=1234", ALPINE, "id"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(session.OutputToString()).To(Equal("uid=1234(1234) gid=0(root)"))
+ Expect(session.OutputToString()).To(Equal("uid=1234(1234) gid=0(root) groups=0(root)"))
})
It("podman run with user (integer, in /etc/passwd)", func() {
@@ -966,14 +966,14 @@ echo -n %s >%s
session := podmanTest.Podman([]string{"run", "--rm", "--user=mail:21", ALPINE, "id"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(session.OutputToString()).To(Equal("uid=8(mail) gid=21(ftp)"))
+ Expect(session.OutputToString()).To(Equal("uid=8(mail) gid=21(ftp) groups=21(ftp)"))
})
It("podman run with user:group (integer:groupname)", func() {
session := podmanTest.Podman([]string{"run", "--rm", "--user=8:ftp", ALPINE, "id"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(session.OutputToString()).To(Equal("uid=8(mail) gid=21(ftp)"))
+ Expect(session.OutputToString()).To(Equal("uid=8(mail) gid=21(ftp) groups=21(ftp)"))
})
It("podman run with user, verify caps dropped", func() {
@@ -984,6 +984,14 @@ echo -n %s >%s
Expect("0000000000000000").To(Equal(capEff[1]))
})
+ It("podman run with user, verify group added", func() {
+ session := podmanTest.Podman([]string{"run", "--rm", "--user=1000:1000", ALPINE, "grep", "Groups:", "/proc/self/status"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ groups := strings.Split(session.OutputToString(), " ")[1]
+ Expect("1000").To(Equal(groups))
+ })
+
It("podman run with attach stdin outputs container ID", func() {
session := podmanTest.Podman([]string{"run", "--attach", "stdin", ALPINE, "printenv"})
session.WaitWithDefaultTimeout()
@@ -1235,9 +1243,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 613727118..016f67bf6 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()
@@ -85,6 +113,16 @@ var _ = Describe("Podman UserNS support", func() {
Expect(session).Should(Exit(0))
uid := fmt.Sprintf("%d", os.Geteuid())
Expect(session.OutputToString()).To(ContainSubstring(uid))
+
+ session = podmanTest.Podman([]string{"run", "--userns=keep-id:uid=10,gid=12", "alpine", "sh", "-c", "echo $(id -u):$(id -g)"})
+ session.WaitWithDefaultTimeout()
+ if os.Geteuid() == 0 {
+ Expect(session).Should(Exit(125))
+ return
+ }
+
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).To(ContainSubstring("10:12"))
})
It("podman --userns=keep-id check passwd", func() {
@@ -157,6 +195,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
}
@@ -307,6 +347,30 @@ var _ = Describe("Podman UserNS support", func() {
}
})
+
+ It("podman --userns= conflicts with ui[dg]map and sub[ug]idname", func() {
+ session := podmanTest.Podman([]string{"run", "--userns=host", "--uidmap=0:1:500", "alpine", "true"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(125))
+ Expect(session.ErrorToString()).To(ContainSubstring("--userns and --uidmap/--gidmap/--subuidname/--subgidname are mutually exclusive"))
+
+ session = podmanTest.Podman([]string{"run", "--userns=host", "--gidmap=0:200:5000", "alpine", "true"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(125))
+ Expect(session.ErrorToString()).To(ContainSubstring("--userns and --uidmap/--gidmap/--subuidname/--subgidname are mutually exclusive"))
+
+ // with sub[ug]idname we don't check for the error output since the error message could be different, depending on the
+ // system configuration since the specified user could not be defined and cause a different earlier error.
+ // In any case, make sure the command doesn't succeed.
+ session = podmanTest.Podman([]string{"run", "--userns=private", "--subuidname=containers", "alpine", "true"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Not(Exit(0)))
+
+ session = podmanTest.Podman([]string{"run", "--userns=private", "--subgidname=containers", "alpine", "true"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Not(Exit(0)))
+ })
+
It("podman PODMAN_USERNS", func() {
SkipIfNotRootless("keep-id only works in rootless mode")
diff --git a/test/e2e/run_working_dir_test.go b/test/e2e/run_working_dir_test.go
index ff91a420f..84792481f 100644
--- a/test/e2e/run_working_dir_test.go
+++ b/test/e2e/run_working_dir_test.go
@@ -46,6 +46,15 @@ var _ = Describe("Podman run", func() {
Expect(session).Should(Exit(126))
})
+ It("podman run a container using a --workdir under a bind mount", func() {
+ volume, err := CreateTempDirInTempDir()
+ Expect(err).To(BeNil())
+
+ session := podmanTest.Podman([]string{"run", "--volume", fmt.Sprintf("%s:/var_ovl/:O", volume), "--workdir", "/var_ovl/log", ALPINE, "true"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ })
+
It("podman run a container on an image with a workdir", func() {
dockerfile := fmt.Sprintf(`FROM %s
RUN mkdir -p /home/foobar /etc/foobar; chown bin:bin /etc/foobar
diff --git a/test/e2e/save_test.go b/test/e2e/save_test.go
index 94c363dd4..afb723a63 100644
--- a/test/e2e/save_test.go
+++ b/test/e2e/save_test.go
@@ -153,6 +153,9 @@ var _ = Describe("Podman save", func() {
defer os.Setenv("GNUPGHOME", origGNUPGHOME)
port := 5000
+ portlock := GetPortLock(strconv.Itoa(port))
+ defer portlock.Unlock()
+
session := podmanTest.Podman([]string{"run", "-d", "--name", "registry", "-p", strings.Join([]string{strconv.Itoa(port), strconv.Itoa(port)}, ":"), REGISTRY_IMAGE})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
diff --git a/test/e2e/secret_test.go b/test/e2e/secret_test.go
index ed328d84a..902f422bd 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)
@@ -170,27 +200,33 @@ var _ = Describe("Podman secret", func() {
list := podmanTest.Podman([]string{"secret", "ls", "--filter", fmt.Sprintf("name=%s", secret1)})
list.WaitWithDefaultTimeout()
Expect(list).Should(Exit(0))
- Expect(list.OutputToStringArray()).To(HaveLen(2), ContainSubstring(secret1))
+ Expect(list.OutputToStringArray()).To(HaveLen(2))
+ Expect(list.OutputToStringArray()[1]).To(ContainSubstring(secret1))
list = podmanTest.Podman([]string{"secret", "ls", "--filter", fmt.Sprintf("name=%s", secret2)})
list.WaitWithDefaultTimeout()
Expect(list).Should(Exit(0))
- Expect(list.OutputToStringArray()).To(HaveLen(2), ContainSubstring(secret2))
+ Expect(list.OutputToStringArray()).To(HaveLen(2))
+ Expect(list.OutputToStringArray()[1]).To(ContainSubstring(secret2))
list = podmanTest.Podman([]string{"secret", "ls", "--filter", fmt.Sprintf("id=%s", secrID1)})
list.WaitWithDefaultTimeout()
Expect(list).Should(Exit(0))
- Expect(list.OutputToStringArray()).To(HaveLen(2), ContainSubstring(secrID1))
+ Expect(list.OutputToStringArray()).To(HaveLen(2))
+ Expect(list.OutputToStringArray()[1]).To(ContainSubstring(secrID1))
list = podmanTest.Podman([]string{"secret", "ls", "--filter", fmt.Sprintf("id=%s", secrID2)})
list.WaitWithDefaultTimeout()
Expect(list).Should(Exit(0))
- Expect(list.OutputToStringArray()).To(HaveLen(2), ContainSubstring(secrID2))
+ Expect(list.OutputToStringArray()).To(HaveLen(2))
+ Expect(list.OutputToStringArray()[1]).To(ContainSubstring(secrID2))
list = podmanTest.Podman([]string{"secret", "ls", "--filter", fmt.Sprintf("name=%s,name=%s", secret1, secret2)})
list.WaitWithDefaultTimeout()
Expect(list).Should(Exit(0))
- Expect(list.OutputToStringArray()).To(HaveLen(3), ContainSubstring(secret1), ContainSubstring(secret2))
+ Expect(list.OutputToStringArray()).To(HaveLen(3))
+ Expect(list.OutputToString()).To(ContainSubstring(secret1))
+ Expect(list.OutputToString()).To(ContainSubstring(secret2))
})
It("podman secret ls with Go template", func() {
diff --git a/test/e2e/sign/key.gpg b/test/e2e/sign/key.gpg
index 32968fc04..725bdfb7d 100644
--- a/test/e2e/sign/key.gpg
+++ b/test/e2e/sign/key.gpg
Binary files differ
diff --git a/test/e2e/sign/policy.json b/test/e2e/sign/policy.json
index ab01137bf..812c14989 100644
--- a/test/e2e/sign/policy.json
+++ b/test/e2e/sign/policy.json
@@ -12,6 +12,12 @@
"keyType": "GPGKeys",
"keyPath": "/tmp/key.gpg"
}
+ ],
+ "localhost:5000/sigstore-signed": [
+ {
+ "type": "sigstoreSigned",
+ "keyPath": "testdata/sigstore-key.pub"
+ }
]
}
}
diff --git a/test/e2e/sign/secret-key.asc b/test/e2e/sign/secret-key.asc
index 23c0d05c3..f018a3ce5 100644
--- a/test/e2e/sign/secret-key.asc
+++ b/test/e2e/sign/secret-key.asc
Binary files differ
diff --git a/test/e2e/start_test.go b/test/e2e/start_test.go
index 73af9d12c..f3e8cc015 100644
--- a/test/e2e/start_test.go
+++ b/test/e2e/start_test.go
@@ -1,6 +1,7 @@
package integration
import (
+ "fmt"
"io/ioutil"
"os"
"strconv"
@@ -99,23 +100,6 @@ var _ = Describe("Podman start", func() {
Expect(session.OutputToString()).To(Equal(shortID))
})
- It("podman container start single container by short id", func() {
- session := podmanTest.Podman([]string{"container", "create", ALPINE, "ls"})
- session.WaitWithDefaultTimeout()
- Expect(session).Should(Exit(0))
- cid := session.OutputToString()
- shortID := cid[0:10]
- session = podmanTest.Podman([]string{"container", "start", shortID})
- session.WaitWithDefaultTimeout()
- Expect(session).Should(Exit(0))
- Expect(session.OutputToString()).To(Equal(shortID))
-
- session = podmanTest.Podman([]string{"stop", shortID})
- session.WaitWithDefaultTimeout()
- Expect(session).Should(Exit(0))
- Expect(session.OutputToString()).To(Equal(shortID))
- })
-
It("podman start single container by name", func() {
name := "foobar99"
session := podmanTest.Podman([]string{"create", "--name", name, ALPINE, "ls"})
@@ -124,9 +108,6 @@ var _ = Describe("Podman start", func() {
session = podmanTest.Podman([]string{"start", name})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- if podmanTest.RemoteTest {
- Skip("Container-start name check doesn't work on remote client. It always returns the full ID.")
- }
Expect(session.OutputToString()).To(Equal(name))
})
@@ -231,4 +212,42 @@ var _ = Describe("Podman start", func() {
_, err = strconv.Atoi(containerPID) // Make sure it's a proper integer
Expect(err).To(BeNil())
})
+
+ It("podman start container --filter", func() {
+ session1 := podmanTest.Podman([]string{"container", "create", ALPINE})
+ session1.WaitWithDefaultTimeout()
+ Expect(session1).Should(Exit(0))
+ cid1 := session1.OutputToString()
+
+ session1 = podmanTest.Podman([]string{"container", "create", ALPINE})
+ session1.WaitWithDefaultTimeout()
+ Expect(session1).Should(Exit(0))
+ cid2 := session1.OutputToString()
+
+ session1 = podmanTest.Podman([]string{"container", "create", ALPINE})
+ session1.WaitWithDefaultTimeout()
+ Expect(session1).Should(Exit(0))
+ cid3 := session1.OutputToString()
+ shortCid3 := cid3[0:5]
+
+ session1 = podmanTest.Podman([]string{"start", cid1, "-f", "status=running"})
+ session1.WaitWithDefaultTimeout()
+ Expect(session1).Should(Exit(0))
+ Expect(session1.OutputToString()).To(HaveLen(0))
+
+ session1 = podmanTest.Podman([]string{"start", "--all", "--filter", fmt.Sprintf("id=%swrongid", shortCid3)})
+ session1.WaitWithDefaultTimeout()
+ Expect(session1).Should(Exit(0))
+ Expect(session1.OutputToString()).To(HaveLen(0))
+
+ session1 = podmanTest.Podman([]string{"start", "--all", "--filter", fmt.Sprintf("id=%s", shortCid3)})
+ session1.WaitWithDefaultTimeout()
+ Expect(session1).Should(Exit(0))
+ Expect(session1.OutputToString()).To(BeEquivalentTo(cid3))
+
+ session1 = podmanTest.Podman([]string{"start", "-f", fmt.Sprintf("id=%s", cid2)})
+ session1.WaitWithDefaultTimeout()
+ Expect(session1).Should(Exit(0))
+ Expect(session1.OutputToString()).To(BeEquivalentTo(cid2))
+ })
})
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/stop_test.go b/test/e2e/stop_test.go
index 7a258466a..23abb6d92 100644
--- a/test/e2e/stop_test.go
+++ b/test/e2e/stop_test.go
@@ -69,6 +69,19 @@ var _ = Describe("Podman stop", func() {
Expect(strings.TrimSpace(finalCtrs.OutputToString())).To(Equal(""))
})
+ It("podman stop single container by short id", func() {
+ session := podmanTest.RunTopContainer("test1")
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ cid := session.OutputToString()
+ shortID := cid[0:10]
+
+ session = podmanTest.Podman([]string{"stop", shortID})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).To(Equal(shortID))
+ })
+
It("podman stop container by name", func() {
session := podmanTest.RunTopContainer("test1")
session.WaitWithDefaultTimeout()
@@ -198,9 +211,13 @@ var _ = Describe("Podman stop", func() {
session := podmanTest.RunTopContainer("test1")
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
+ cid := session.OutputToString()
+
session = podmanTest.Podman([]string{"stop", "-l", "-t", "1"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).To(Equal(cid))
+
finalCtrs := podmanTest.Podman([]string{"ps", "-q"})
finalCtrs.WaitWithDefaultTimeout()
Expect(finalCtrs).Should(Exit(0))
diff --git a/test/e2e/testdata/sigstore-key.key b/test/e2e/testdata/sigstore-key.key
new file mode 100644
index 000000000..c4eed76a8
--- /dev/null
+++ b/test/e2e/testdata/sigstore-key.key
@@ -0,0 +1,11 @@
+-----BEGIN ENCRYPTED COSIGN PRIVATE KEY-----
+eyJrZGYiOnsibmFtZSI6InNjcnlwdCIsInBhcmFtcyI6eyJOIjozMjc2OCwiciI6
+OCwicCI6MX0sInNhbHQiOiI2ckxVcEl1M1pTallrY3dua1pNVktuTHNDUjRENTJv
+Y3J5Wmh2anZ4L1VrPSJ9LCJjaXBoZXIiOnsibmFtZSI6Im5hY2wvc2VjcmV0Ym94
+Iiwibm9uY2UiOiJMTVpkeTNBL285NS9SektUZGR3RURhODJTVThVcDdlKyJ9LCJj
+aXBoZXJ0ZXh0IjoiNkkzUlRCc1IwRXpHZWs0SE5LazlVdlpyMEp6Y1Bxemw0ZkEr
+SitJdHlCc0RBSkcyNmhESnFLUDFuQkJTUE5XdHpJRzJUVzQ5Z2hObEJmQy9qYVNk
+eFo2QmhXYk9ldlY0MDB4WjVNZ1oyVHdGSnJxaE9HK0JMdmNvanVkc2tOUFpJTlpE
+LytFZVBIYTRlRVJPTWhnSWlTRC9BYTd3eitlc2trVjkrN216Y3N2RVRiTTJTZGd6
+L3daMUtqV3FlOUc2MWlXSTJPSm1rRlhxQWc9PSJ9
+-----END ENCRYPTED COSIGN PRIVATE KEY-----
diff --git a/test/e2e/testdata/sigstore-key.key.pass b/test/e2e/testdata/sigstore-key.key.pass
new file mode 100644
index 000000000..beb5c7687
--- /dev/null
+++ b/test/e2e/testdata/sigstore-key.key.pass
@@ -0,0 +1 @@
+sigstore pass
diff --git a/test/e2e/testdata/sigstore-key.pub b/test/e2e/testdata/sigstore-key.pub
new file mode 100644
index 000000000..1f470f72b
--- /dev/null
+++ b/test/e2e/testdata/sigstore-key.pub
@@ -0,0 +1,4 @@
+-----BEGIN PUBLIC KEY-----
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEX/AWbBiFPuAU5+ys+Ce8YFPhTr1a
+nM7A8h6NrQi6w8w8/4dJCzlGH4SN+P93nopATs6jDXs4Lpc2/tiA1SBmzA==
+-----END PUBLIC KEY-----
diff --git a/test/e2e/testdata/sigstore-registries.d-fragment.yaml b/test/e2e/testdata/sigstore-registries.d-fragment.yaml
new file mode 100644
index 000000000..d79f4c935
--- /dev/null
+++ b/test/e2e/testdata/sigstore-registries.d-fragment.yaml
@@ -0,0 +1,3 @@
+docker:
+ localhost:5000/sigstore-signed:
+ use-sigstore-attachments: true
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/update_test.go b/test/e2e/update_test.go
new file mode 100644
index 000000000..97dadd04c
--- /dev/null
+++ b/test/e2e/update_test.go
@@ -0,0 +1,200 @@
+package integration
+
+import (
+ "github.com/containers/common/pkg/cgroupv2"
+ . "github.com/containers/podman/v4/test/utils"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+ . "github.com/onsi/gomega/gexec"
+)
+
+var _ = Describe("Podman update", func() {
+ var (
+ tempdir string
+ err error
+ podmanTest *PodmanTestIntegration
+ )
+
+ BeforeEach(func() {
+ tempdir, err = CreateTempDirInTempDir()
+ Expect(err).To(BeNil())
+ podmanTest = PodmanTestCreate(tempdir)
+ podmanTest.Setup()
+ })
+
+ AfterEach(func() {
+ podmanTest.Cleanup()
+ f := CurrentGinkgoTestDescription()
+ processTestResult(f)
+
+ })
+
+ It("podman update container all options v1", func() {
+ SkipIfCgroupV2("testing flags that only work in cgroup v1")
+ SkipIfRootless("many of these handlers are not enabled while rootless in CI")
+ session := podmanTest.Podman([]string{"run", "-dt", ALPINE})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ ctrID := session.OutputToString()
+
+ commonArgs := []string{
+ "update",
+ "--cpus", "5",
+ "--cpuset-cpus", "0",
+ "--cpu-shares", "123",
+ "--cpuset-mems", "0",
+ "--memory", "1G",
+ "--memory-swap", "2G",
+ "--memory-reservation", "2G",
+ "--memory-swappiness", "50", ctrID}
+
+ session = podmanTest.Podman(commonArgs)
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ // checking cpu quota from --cpus
+ session = podmanTest.Podman([]string{"exec", "-it", ctrID, "cat", "/sys/fs/cgroup/cpu/cpu.cfs_quota_us"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).Should(ContainSubstring("500000"))
+
+ // checking cpuset-cpus
+ session = podmanTest.Podman([]string{"exec", "-it", ctrID, "cat", "/sys/fs/cgroup/cpuset/cpuset.cpus"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).Should(Equal("0"))
+
+ // checking cpuset-mems
+ session = podmanTest.Podman([]string{"exec", "-it", ctrID, "cat", "/sys/fs/cgroup/cpuset/cpuset.mems"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).Should(Equal("0"))
+
+ // checking memory limit
+ session = podmanTest.Podman([]string{"exec", "-it", ctrID, "cat", "/sys/fs/cgroup/memory/memory.limit_in_bytes"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).Should(ContainSubstring("1073741824"))
+
+ // checking memory-swap
+ session = podmanTest.Podman([]string{"exec", "-it", ctrID, "cat", "/sys/fs/cgroup/memory/memory.memsw.limit_in_bytes"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).Should(ContainSubstring("2147483648"))
+
+ // checking cpu-shares
+ session = podmanTest.Podman([]string{"exec", "-it", ctrID, "cat", "/sys/fs/cgroup/cpu/cpu.shares"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).Should(ContainSubstring("123"))
+
+ })
+
+ It("podman update container all options v2", func() {
+ SkipIfCgroupV1("testing flags that only work in cgroup v2")
+ SkipIfRootless("many of these handlers are not enabled while rootless in CI")
+ session := podmanTest.Podman([]string{"run", "-dt", ALPINE})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ ctrID := session.OutputToString()
+
+ commonArgs := []string{
+ "update",
+ "--cpus", "5",
+ "--cpuset-cpus", "0",
+ "--cpu-shares", "123",
+ "--cpuset-mems", "0",
+ "--memory", "1G",
+ "--memory-swap", "2G",
+ "--memory-reservation", "2G",
+ "--blkio-weight", "123",
+ "--device-read-bps", "/dev/zero:10mb",
+ "--device-write-bps", "/dev/zero:10mb",
+ "--device-read-iops", "/dev/zero:1000",
+ "--device-write-iops", "/dev/zero:1000",
+ ctrID}
+
+ session = podmanTest.Podman(commonArgs)
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ ctrID = session.OutputToString()
+
+ // checking cpu quota and period
+ session = podmanTest.Podman([]string{"exec", "-it", ctrID, "cat", "/sys/fs/cgroup/cpu.max"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).Should(ContainSubstring("500000"))
+
+ // checking blkio weight
+ session = podmanTest.Podman([]string{"exec", "-it", ctrID, "cat", "/sys/fs/cgroup/io.bfq.weight"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).Should(ContainSubstring("123"))
+
+ // checking device-read/write-bps/iops
+ session = podmanTest.Podman([]string{"exec", "-it", ctrID, "cat", "/sys/fs/cgroup/io.max"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).Should(ContainSubstring("rbps=10485760 wbps=10485760 riops=1000 wiops=1000"))
+
+ // checking cpuset-cpus
+ session = podmanTest.Podman([]string{"exec", "-it", ctrID, "cat", "/sys/fs/cgroup/cpuset.cpus"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).Should(Equal("0"))
+
+ // checking cpuset-mems
+ session = podmanTest.Podman([]string{"exec", "-it", ctrID, "cat", "/sys/fs/cgroup/cpuset.mems"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).Should(Equal("0"))
+
+ // checking memory limit
+ session = podmanTest.Podman([]string{"exec", "-it", ctrID, "cat", "/sys/fs/cgroup/memory.max"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).Should(ContainSubstring("1073741824"))
+
+ // checking memory-swap
+ session = podmanTest.Podman([]string{"exec", "-it", ctrID, "cat", "/sys/fs/cgroup/memory.swap.max"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).Should(ContainSubstring("1073741824"))
+
+ // checking cpu-shares
+ session = podmanTest.Podman([]string{"exec", "-it", ctrID, "cat", "/sys/fs/cgroup/cpu.weight"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).Should(ContainSubstring("5"))
+ })
+
+ It("podman update keep original resources if not overridden", func() {
+ SkipIfRootless("many of these handlers are not enabled while rootless in CI")
+ session := podmanTest.Podman([]string{"run", "-dt", "--cpus", "5", ALPINE})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ session = podmanTest.Podman([]string{
+ "update",
+ "--memory", "1G",
+ session.OutputToString(),
+ })
+
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ ctrID := session.OutputToString()
+
+ if v2, _ := cgroupv2.Enabled(); v2 {
+ session = podmanTest.Podman([]string{"exec", "-it", ctrID, "cat", "/sys/fs/cgroup/cpu.max"})
+ } else {
+ session = podmanTest.Podman([]string{"exec", "-it", ctrID, "cat", "/sys/fs/cgroup/cpu/cpu.cfs_quota_us"})
+ }
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).Should(ContainSubstring("500000"))
+ })
+})
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_exists_test.go b/test/e2e/volume_exists_test.go
index 0de574968..0a550bfcb 100644
--- a/test/e2e/volume_exists_test.go
+++ b/test/e2e/volume_exists_test.go
@@ -34,7 +34,7 @@ var _ = Describe("Podman volume exists", func() {
})
It("podman volume exists", func() {
- vol := "vol" + stringid.GenerateNonCryptoID()
+ vol := "vol" + stringid.GenerateRandomID()
session := podmanTest.Podman([]string{"volume", "create", vol})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
@@ -43,7 +43,7 @@ var _ = Describe("Podman volume exists", func() {
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- session = podmanTest.Podman([]string{"volume", "exists", stringid.GenerateNonCryptoID()})
+ session = podmanTest.Podman([]string{"volume", "exists", stringid.GenerateRandomID()})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(1))
})
diff --git a/test/e2e/volume_ls_test.go b/test/e2e/volume_ls_test.go
index dcfb13f4e..24ea50b26 100644
--- a/test/e2e/volume_ls_test.go
+++ b/test/e2e/volume_ls_test.go
@@ -75,7 +75,10 @@ var _ = Describe("Podman volume ls", func() {
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- Expect(session.OutputToStringArray()).To(HaveLen(1), session.OutputToString())
+ arr := session.OutputToStringArray()
+ Expect(arr).To(HaveLen(2))
+ Expect(arr[0]).To(ContainSubstring("NAME"))
+ Expect(arr[1]).To(ContainSubstring("myvol"))
})
It("podman ls volume with --filter flag", func() {
diff --git a/test/e2e/volume_plugin_test.go b/test/e2e/volume_plugin_test.go
index b585f8dd8..33cdcce5b 100644
--- a/test/e2e/volume_plugin_test.go
+++ b/test/e2e/volume_plugin_test.go
@@ -212,19 +212,19 @@ testvol5 = "/run/docker/plugins/testvol5.sock"`), 0o644)
plugin.WaitWithDefaultTimeout()
Expect(plugin).Should(Exit(0))
- localvol := "local-" + stringid.GenerateNonCryptoID()
+ localvol := "local-" + stringid.GenerateRandomID()
// create local volume
session := podmanTest.Podman([]string{"volume", "create", localvol})
session.WaitWithDefaultTimeout()
Expect(session).To(Exit(0))
- vol1 := "vol1-" + stringid.GenerateNonCryptoID()
+ vol1 := "vol1-" + stringid.GenerateRandomID()
session = podmanTest.Podman([]string{"volume", "create", "--driver", pluginName, vol1})
session.WaitWithDefaultTimeout()
Expect(session).To(Exit(0))
// now create volume in plugin without podman
- vol2 := "vol2-" + stringid.GenerateNonCryptoID()
+ vol2 := "vol2-" + stringid.GenerateRandomID()
plugin = podmanTest.Podman([]string{"exec", ctrName, "/usr/local/bin/testvol", "--sock-name", pluginName, "create", vol2})
plugin.WaitWithDefaultTimeout()
Expect(plugin).Should(Exit(0))
@@ -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/001-basic.bats b/test/system/001-basic.bats
index cf37fc07c..378edc013 100644
--- a/test/system/001-basic.bats
+++ b/test/system/001-basic.bats
@@ -29,6 +29,12 @@ function setup() {
local built=$(expr "$output" : ".*Built: \+\(.*\)" | head -n1)
local built_t=$(date --date="$built" +%s)
assert "$built_t" -gt 1546300800 "Preposterous 'Built' time in podman version"
+
+ run_podman -v
+ is "$output" "podman.*version \+" "'Version line' in output"
+
+ run_podman --config foobar version
+ is "$output" ".*The --config flag is ignored by Podman. Exists for Docker compatibility\+" "verify warning for --config option"
}
@test "podman info" {
@@ -182,14 +188,79 @@ See 'podman version --help'" "podman version --remote"
@test "podman --log-level recognizes log levels" {
run_podman 1 --log-level=telepathic info
is "$output" 'Log Level "telepathic" is not supported.*'
+
run_podman --log-level=trace info
+ if ! is_remote; then
+ # podman-remote does not do any trace logging
+ assert "$output" =~ " level=trace " "log-level=trace"
+ fi
+ assert "$output" =~ " level=debug " "log-level=trace includes debug"
+ assert "$output" =~ " level=info " "log-level=trace includes info"
+ assert "$output" !~ " level=warn" "log-level=trace does not show warn"
+
run_podman --log-level=debug info
+ assert "$output" !~ " level=trace " "log-level=debug does not show trace"
+ assert "$output" =~ " level=debug " "log-level=debug"
+ assert "$output" =~ " level=info " "log-level=debug includes info"
+ assert "$output" !~ " level=warn" "log-level=debug does not show warn"
+
run_podman --log-level=info info
+ assert "$output" !~ " level=trace " "log-level=info does not show trace"
+ assert "$output" !~ " level=debug " "log-level=info does not show debug"
+ assert "$output" =~ " level=info " "log-level=info"
+
run_podman --log-level=warn info
+ assert "$output" !~ " level=" "log-level=warn shows no logs at all"
+
+ # Force a warning (local podman only; podman-remote doesn't check versions)
+ if ! is_remote; then
+ run_podman --log-level=warn --storage-opt=mount_program=/bin/false info
+ assert "$output" =~ " level=warning msg=\"Failed to retrieve " \
+ "log-level=warn"
+
+ # confirm that default level is "warn", by invoking without --log-level
+ run_podman --storage-opt=mount_program=/bin/false info
+ assert "$output" =~ " level=warning msg=\"Failed to retrieve " \
+ "default log level includes warning messages"
+ fi
+
run_podman --log-level=warning info
+ assert "$output" !~ " level=" "log-level=warning shows no logs at all"
+
run_podman --log-level=error info
- run_podman --log-level=fatal info
- run_podman --log-level=panic info
+ assert "$output" !~ " level=" "log-level=error shows no logs at all"
+
+ # error, fatal, panic:
+ if is_remote; then
+ # podman-remote does not grok --runtime; all we can do is test parsing
+ for level in error fatal panic; do
+ run_podman --log-level=$level info
+ assert "$output" !~ " level=" \
+ "log-level=$level shows no logs at all"
+ done
+ else
+ # local podman only
+ run_podman --log-level=error --storage-opt=mount_program=/bin/false --runtime=/bin/false info
+ assert "$output" =~ " level=error msg=\"Getting info on OCI runtime " \
+ "log-level=error shows "
+ assert "$output" !~ " level=warn" \
+ "log-level=error does not show warnings"
+
+ run_podman --log-level=fatal --storage-opt=mount_program=/bin/false --runtime=/bin/false info
+ assert "$output" !~ " level=" "log-level=fatal shows no logs at all"
+
+ run_podman --log-level=panic --storage-opt=mount_program=/bin/false --runtime=/bin/false info
+ assert "$output" !~ " level=" "log-level=panic shows no logs at all"
+ fi
+
+ # docker compat
+ run_podman --debug info
+ assert "$output" =~ " level=debug " "podman --debug gives debug output"
+ run_podman -D info
+ assert "$output" =~ " level=debug " "podman -D gives debug output"
+
+ run_podman 1 --debug --log-level=panic info
+ is "$output" "Setting --log-level and --debug is not allowed"
}
# vim: filetype=sh
diff --git a/test/system/010-images.bats b/test/system/010-images.bats
index aa390f236..16ee681a3 100644
--- a/test/system/010-images.bats
+++ b/test/system/010-images.bats
@@ -259,8 +259,8 @@ Labels.created_at | 20[0-9-]\\\+T[0-9:]\\\+Z
run_podman 2 rmi -a
is "$output" "Error: 2 errors occurred:
-.** image used by .*: image is in use by a container
-.** image used by .*: image is in use by a container"
+.** image used by .*: image is in use by a container: consider listing external containers and force-removing image
+.** image used by .*: image is in use by a container: consider listing external containers and force-removing image"
run_podman rmi -af
is "$output" "Untagged: $IMAGE
@@ -292,7 +292,7 @@ Deleted: $pauseID" "infra images gets removed as well"
pauseID=$output
run_podman 2 rmi $pauseImage
- is "$output" "Error: image used by .* image is in use by a container"
+ is "$output" "Error: image used by .* image is in use by a container: consider listing external containers and force-removing image"
run_podman rmi -f $pauseImage
is "$output" "Untagged: $pauseImage
diff --git a/test/system/015-help.bats b/test/system/015-help.bats
index dd5a7ed44..927645f29 100644
--- a/test/system/015-help.bats
+++ b/test/system/015-help.bats
@@ -121,7 +121,7 @@ function check_help() {
# Exceptions: these commands don't work rootless
if is_rootless; then
# "pause is not supported for rootless containers"
- if [ "$cmd" = "pause" -o "$cmd" = "unpause" ]; then
+ if [[ "$cmd" = "pause" ]] || [[ "$cmd" = "unpause" ]]; then
continue
fi
# "network rm" too
@@ -162,17 +162,17 @@ function check_help() {
# Any command that takes subcommands, prints its help and errors if called
# without one.
- dprint "podman $@"
+ dprint "podman $*"
run_podman '?' "$@"
is "$status" 125 "'podman $*' without any subcommand - exit status"
- is "$output" ".*Usage:.*Error: missing command '.*$@ COMMAND'" \
+ is "$output" ".*Usage:.*Error: missing command '.*$* COMMAND'" \
"'podman $*' without any subcommand - expected error message"
# Assume that 'NoSuchCommand' is not a command
- dprint "podman $@ NoSuchCommand"
+ dprint "podman $* NoSuchCommand"
run_podman '?' "$@" NoSuchCommand
is "$status" 125 "'podman $* NoSuchCommand' - exit status"
- is "$output" "Error: unrecognized command .*$@ NoSuchCommand" \
+ is "$output" "Error: unrecognized command .*$* NoSuchCommand" \
"'podman $* NoSuchCommand' - expected error message"
# This can happen if the output of --help changes, such as between
diff --git a/test/system/030-run.bats b/test/system/030-run.bats
index 908c169ee..b1ce91d14 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
@@ -418,7 +423,7 @@ json-file | f
# Invalid log-driver argument
run_podman 125 run --log-driver=InvalidDriver $IMAGE true
- is "$output" "Error: error running container create option: invalid log driver: invalid argument" \
+ is "$output" "Error: running container create option: invalid log driver: invalid argument" \
"--log-driver InvalidDriver"
}
diff --git a/test/system/035-logs.bats b/test/system/035-logs.bats
index 6b8d5fbc5..6e84e10fc 100644
--- a/test/system/035-logs.bats
+++ b/test/system/035-logs.bats
@@ -36,13 +36,28 @@ function _log_test_tail() {
run_podman run -d --log-driver=$driver $IMAGE sh -c "echo test1; echo test2"
cid="$output"
- run_podman logs --tail 1 $cid
- is "$output" "test2" "logs should only show last line"
+ run_podman wait $cid
+ run_podman logs --tail 1 --timestamps $cid
+ log1="$output"
+ assert "$log1" =~ "^[0-9-]+T[0-9:.]+([\+-][0-9:]+|Z) test2" \
+ "logs should only show last line"
+
+ # Sigh. I hate doing this, but podman-remote --timestamp only has 1-second
+ # resolution (regular podman has sub-second). For the timestamps-differ
+ # check below, we need to force a different second.
+ if is_remote; then
+ sleep 2
+ fi
run_podman restart $cid
+ run_podman wait $cid
+
+ run_podman logs -t --tail 1 $cid
+ log2="$output"
+ assert "$log2" =~ "^[0-9-]+T[0-9:.]+([\+-][0-9:]+|Z) test2" \
+ "logs, after restart, shows only last line"
- run_podman logs --tail 1 $cid
- is "$output" "test2" "logs should only show last line after restart"
+ assert "$log2" != "$log1" "log timestamps should differ"
run_podman rm $cid
}
diff --git a/test/system/045-start.bats b/test/system/045-start.bats
index ad8483bba..773a0acd2 100644
--- a/test/system/045-start.bats
+++ b/test/system/045-start.bats
@@ -40,6 +40,8 @@ load helpers
@test "podman start --filter - start only containers that match the filter" {
run_podman run -d $IMAGE /bin/true
cid="$output"
+ run_podman wait $cid
+
run_podman start --filter restart-policy=always $cid
is "$output" "" "CID of restart-policy=always container"
@@ -66,4 +68,20 @@ load helpers
is "$output" "$cid_exited_0"
}
+@test "podman start print IDs or raw input" {
+ # start --all must print the IDs
+ run_podman create $IMAGE top
+ ctrID="$output"
+ run_podman start --all
+ is "$output" "$ctrID"
+
+ # start $input must print $input
+ cname=$(random_string)
+ run_podman create --name $cname $IMAGE top
+ run_podman start $cname
+ is "$output" $cname
+
+ run_podman rm -t 0 -f $ctrID $cname
+}
+
# vim: filetype=sh
diff --git a/test/system/050-stop.bats b/test/system/050-stop.bats
index 39002512b..a21a036c2 100644
--- a/test/system/050-stop.bats
+++ b/test/system/050-stop.bats
@@ -59,6 +59,22 @@ load helpers
is "${lines[3]}" "c4--Created.*" "ps -a, created container (unaffected)"
}
+@test "podman stop print IDs or raw input" {
+ # stop -a must print the IDs
+ run_podman run -d $IMAGE top
+ ctrID="$output"
+ run_podman stop --all
+ is "$output" "$ctrID"
+
+ # stop $input must print $input
+ cname=$(random_string)
+ run_podman run -d --name $cname $IMAGE top
+ run_podman stop $cname
+ is "$output" $cname
+
+ run_podman rm -t 0 -f $ctrID $cname
+}
+
# #9051 : podman stop --ignore was not working with podman-remote
@test "podman stop --ignore" {
name=thiscontainerdoesnotexist
diff --git a/test/system/055-rm.bats b/test/system/055-rm.bats
index dcd679a1f..613c60c96 100644
--- a/test/system/055-rm.bats
+++ b/test/system/055-rm.bats
@@ -18,6 +18,7 @@ load helpers
# Remove container; now 'inspect' should fail
run_podman rm $rand
+ is "$output" "$rand" "display raw input"
run_podman 125 inspect $rand
}
diff --git a/test/system/065-cp.bats b/test/system/065-cp.bats
index 8f5abd228..c8ad8468c 100644
--- a/test/system/065-cp.bats
+++ b/test/system/065-cp.bats
@@ -436,7 +436,7 @@ load helpers
run_podman cp cpcontainer:$src $destdir$dest
is "$(< $destdir$dest_fullname/containerfile0)" "${randomcontent[0]}" "$description"
is "$(< $destdir$dest_fullname/containerfile1)" "${randomcontent[1]}" "$description"
- rm -rf $destdir/*
+ rm -rf ${destdir:?}/*
done < <(parse_table "$tests")
run_podman kill cpcontainer
run_podman rm -t 0 -f cpcontainer
@@ -456,7 +456,7 @@ load helpers
run_podman cp cpcontainer:$src $destdir$dest
is "$(< $destdir$dest_fullname/containerfile0)" "${randomcontent[0]}" "$description"
is "$(< $destdir$dest_fullname/containerfile1)" "${randomcontent[1]}" "$description"
- rm -rf $destdir/*
+ rm -rf ${destdir:?}/*
done < <(parse_table "$tests")
touch $destdir/testfile
diff --git a/test/system/070-build.bats b/test/system/070-build.bats
index 9fddbaa21..87979483e 100644
--- a/test/system/070-build.bats
+++ b/test/system/070-build.bats
@@ -541,7 +541,7 @@ Labels.$label_name | $label_value
this-file-does-not-match-anything-in-ignore-file
comment
)
- for f in ${files[@]}; do
+ for f in "${files[@]}"; do
# The magic '##-' strips off the '-' prefix
echo "$f" > $tmpdir/${f##-}
done
diff --git a/test/system/090-events.bats b/test/system/090-events.bats
index ceb53ae73..90b9b3b9c 100644
--- a/test/system/090-events.bats
+++ b/test/system/090-events.bats
@@ -22,24 +22,25 @@ load helpers
# Now filter just by container name, no label
run_podman events --filter type=container --filter container=$cname --filter event=start --stream=false
- is "$output" "$expect" "filtering just by label"
+ is "$output" "$expect" "filtering just by container"
}
@test "truncate events" {
cname=test-$(random_string 30 | tr A-Z a-z)
- labelname=$(random_string 10)
- labelvalue=$(random_string 15)
run_podman run -d --name=$cname --rm $IMAGE echo hi
id="$output"
- expect="$id"
run_podman events --filter container=$cname --filter event=start --stream=false
is "$output" ".* $id " "filtering by container name full id"
- truncID=$(expr substr "$id" 1 12)
+ truncID=${id:0:12}
run_podman events --filter container=$cname --filter event=start --stream=false --no-trunc=false
is "$output" ".* $truncID " "filtering by container name trunc id"
+
+ # --no-trunc does not affect --format; we always get the full ID
+ run_podman events --filter container=$cname --filter event=died --stream=false --format='{{.ID}}--{{.Image}}' --no-trunc=false
+ assert "$output" = "${id}--${IMAGE}"
}
@test "image events" {
@@ -64,7 +65,8 @@ load helpers
run_podman --events-backend=file tag $IMAGE $tag
run_podman --events-backend=file untag $IMAGE $tag
run_podman --events-backend=file tag $IMAGE $tag
- run_podman --events-backend=file rmi $tag
+ run_podman --events-backend=file rmi -f $imageID
+ run_podman --events-backend=file load -i $tarball
run_podman --events-backend=file events --stream=false --filter type=image --since $t0
is "$output" ".*image push $imageID dir:$pushedDir
@@ -74,8 +76,29 @@ load helpers
.*image tag $imageID $tag
.*image untag $imageID $tag:latest
.*image tag $imageID $tag
-.*image remove $imageID $tag.*" \
+.*image untag $imageID $IMAGE
+.*image untag $imageID $tag:latest
+.*image remove $imageID $imageID" \
"podman events"
+
+ # With --format we can check the _exact_ output, not just substrings
+ local -a expect=("push--dir:$pushedDir"
+ "save--$tarball"
+ "loadfromarchive--$tarball"
+ "pull--docker-archive:$tarball"
+ "tag--$tag"
+ "untag--$tag:latest"
+ "tag--$tag"
+ "untag--$IMAGE"
+ "untag--$tag:latest"
+ "remove--$imageID"
+ "loadfromarchive--$tarball"
+ )
+ run_podman --events-backend=file events --stream=false --filter type=image --since $t0 --format '{{.Status}}--{{.Name}}'
+ for i in $(seq 0 ${#expect[@]}); do
+ assert "${lines[$i]}" = "${expect[$i]}" "events, line $i"
+ done
+ assert "${#lines[@]}" = "${#expect[@]}" "Total lines of output"
}
function _events_disjunctive_filters() {
@@ -109,7 +132,8 @@ function _events_disjunctive_filters() {
is "$output" "hi" "Should support events-backend=file"
run_podman 125 --events-backend=file logs --follow test
- is "$output" "Error: using --follow with the journald --log-driver but without the journald --events-backend (file) is not supported" "Should fail with reasonable error message when events-backend and events-logger do not match"
+ is "$output" "Error: using --follow with the journald --log-driver but without the journald --events-backend (file) is not supported" \
+ "Should fail with reasonable error message when events-backend and events-logger do not match"
}
@@ -134,7 +158,7 @@ function _populate_events_file() {
local events_file=$1
truncate --size=0 $events_file
for i in {0..99}; do
- printf '{"Name":"busybox","Status":"pull","Time":"2022-04-06T11:26:42.7236679%02d+02:00","Type":"image","Attributes":null}\n' $i >> $events_file
+ printf '{"Name":"busybox","Status":"pull","Time":"2022-04-06T11:26:42.7236679%02d+02:00","Type":"image","Attributes":null}\n' $i >> $events_file
done
}
@@ -146,7 +170,6 @@ function _populate_events_file() {
# Config without a limit
eventsFile=$PODMAN_TMPDIR/events.txt
- _populate_events_file $eventsFile
containersConf=$PODMAN_TMPDIR/containers.conf
cat >$containersConf <<EOF
[engine]
@@ -154,6 +177,11 @@ events_logger="file"
events_logfile_path="$eventsFile"
EOF
+ # Check that a non existing event file does not cause a hang (#15688)
+ CONTAINERS_CONF=$containersConf run_podman events --stream=false
+
+ _populate_events_file $eventsFile
+
# Create events *without* a limit and make sure that it has not been
# rotated/truncated.
contentBefore=$(head -n100 $eventsFile)
@@ -190,6 +218,34 @@ EOF
# Make sure that `podman events` can read the file, and that it returns the
# same amount of events. We checked the contents before.
CONTAINERS_CONF=$containersConf run_podman events --stream=false --since="2022-03-06T11:26:42.723667984+02:00"
- is "$(wc -l <$eventsFile)" "$(wc -l <<<$output)" "all events are returned"
+ assert "${#lines[@]}" = 51 "Number of events returned"
is "${lines[-2]}" ".* log-rotation $eventsFile"
}
+
+# Prior to #15633, container labels would not appear in 'die' log events
+@test "events - labels included in container die" {
+ skip_if_remote "remote does not support --events-backend"
+ local cname=c$(random_string 15)
+ local lname=l$(random_string 10)
+ local lvalue="v$(random_string 10) $(random_string 5)"
+
+ run_podman 17 --events-backend=file run --rm \
+ --name=$cname \
+ --label=$lname="$lvalue" \
+ $IMAGE sh -c 'exit 17'
+ run_podman --events-backend=file events \
+ --filter=container=$cname \
+ --filter=status=died \
+ --stream=false \
+ --format="{{.Attributes.$lname}}"
+ assert "$output" = "$lvalue" "podman-events output includes container label"
+}
+
+@test "events - backend none should error" {
+ skip_if_remote "remote does not support --events-backend"
+
+ run_podman 125 --events-backend none events
+ is "$output" "Error: cannot read events with the \"none\" backend" "correct error message"
+ run_podman 125 --events-backend none events --stream=false
+ is "$output" "Error: cannot read events with the \"none\" backend" "correct error message"
+}
diff --git a/test/system/150-login.bats b/test/system/150-login.bats
index b57bb44ab..b85007f0b 100644
--- a/test/system/150-login.bats
+++ b/test/system/150-login.bats
@@ -122,7 +122,7 @@ function setup() {
--password-stdin \
$registry <<< "x${PODMAN_LOGIN_PASS}"
is "$output" \
- "Error: error logging into \"$registry\": invalid username/password" \
+ "Error: logging into \"$registry\": invalid username/password" \
'output from podman login'
}
diff --git a/test/system/160-volumes.bats b/test/system/160-volumes.bats
index 6829c6a78..08baaf468 100644
--- a/test/system/160-volumes.bats
+++ b/test/system/160-volumes.bats
@@ -315,11 +315,11 @@ EOF
# List available volumes for pruning after using 1,2,3
run_podman volume prune <<< N
- is "$(echo $(sort <<<${lines[@]:1:3}))" "${v[4]} ${v[5]} ${v[6]}" "volume prune, with 1,2,3 in use, lists 4,5,6"
+ is "$(echo $(sort <<<${lines[*]:1:3}))" "${v[4]} ${v[5]} ${v[6]}" "volume prune, with 1,2,3 in use, lists 4,5,6"
# List available volumes for pruning after using 1,2,3 and filtering; see #8913
run_podman volume prune --filter label=mylabel <<< N
- is "$(echo $(sort <<<${lines[@]:1:2}))" "${v[5]} ${v[6]}" "volume prune, with 1,2,3 in use and 4 filtered out, lists 5,6"
+ is "$(echo $(sort <<<${lines[*]:1:2}))" "${v[5]} ${v[6]}" "volume prune, with 1,2,3 in use and 4 filtered out, lists 5,6"
# prune should remove v4
run_podman volume prune --force
diff --git a/test/system/200-pod.bats b/test/system/200-pod.bats
index cbbd62ffb..9bbd56fef 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
@@ -435,7 +435,7 @@ EOF
run_podman pod rm $podID
run_podman 125 pod create --exit-policy invalid
- is "$output" "Error: .*error running pod create option: invalid pod exit policy: \"invalid\"" "invalid exit policy"
+ is "$output" "Error: .*running pod create option: invalid pod exit policy: \"invalid\"" "invalid exit policy"
# Test exit-policy behaviour
run_podman pod create --exit-policy continue
@@ -478,10 +478,10 @@ 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"
+ skip_if_aarch64 "FIXME: #15074 - flakes often on aarch64"
# create loopback device
lofile=${PODMAN_TMPDIR}/disk.img
@@ -492,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/220-healthcheck.bats b/test/system/220-healthcheck.bats
index c502ad669..a1b24d293 100644
--- a/test/system/220-healthcheck.bats
+++ b/test/system/220-healthcheck.bats
@@ -20,44 +20,8 @@ function _check_health {
done
}
-
@test "podman healthcheck" {
- # 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
-#!/bin/sh
-
-if test -e /uh-oh; then
- echo "Uh-oh on stdout!"
- echo "Uh-oh on stderr!" >&2
- exit 1
-else
- echo "Life is Good on stdout"
- echo "Life is Good on stderr" >&2
- exit 0
-fi
-EOF
-
- cat >${PODMAN_TMPDIR}/entrypoint <<EOF
-#!/bin/sh
-
-while :; do
- sleep 1
-done
-EOF
-
- cat >${PODMAN_TMPDIR}/Containerfile <<EOF
-FROM $IMAGE
-
-COPY healthcheck /healthcheck
-COPY entrypoint /entrypoint
-
-RUN chmod 755 /healthcheck /entrypoint
-
-CMD ["/entrypoint"]
-EOF
-
- run_podman build -t healthcheck_i ${PODMAN_TMPDIR}
+ _build_health_check_image healthcheck_i
# Run that healthcheck image.
run_podman run -d --name healthcheck_c \
@@ -66,6 +30,9 @@ EOF
--health-retries 3 \
healthcheck_i
+ run_podman inspect healthcheck_c --format "{{.Config.HealthcheckOnFailureAction}}"
+ is "$output" "none" "default on-failure action is none"
+
# We can't check for 'starting' because a 1-second interval is too
# short; it could run healthcheck before we get to our first check.
#
@@ -109,4 +76,57 @@ Log[-1].Output | \"Uh-oh on stdout!\\\nUh-oh on stderr!\"
run_podman rmi healthcheck_i
}
+@test "podman healthcheck --health-on-failure" {
+ run_podman 125 create --health-on-failure=kill $IMAGE
+ is "$output" "Error: cannot set on-failure action to kill without a health check"
+
+ ctr="healthcheck_c"
+ img="healthcheck_i"
+
+ for policy in none kill restart stop;do
+ if [[ $policy == "none" ]];then
+ # Do not remove the /uh-oh file for `none` as we want to
+ # demonstrate that no action was taken
+ _build_health_check_image $img
+ else
+ _build_health_check_image $img cleanfile
+ fi
+
+ # Run that healthcheck image.
+ run_podman run -d --name $ctr \
+ --health-cmd /healthcheck \
+ --health-on-failure=$policy \
+ $img
+
+ # healthcheck should succeed
+ run_podman healthcheck run $ctr
+
+ # Now cause the healthcheck to fail
+ run_podman exec $ctr touch /uh-oh
+
+ # healthcheck should now fail, with exit status 1 and 'unhealthy' output
+ run_podman 1 healthcheck run $ctr
+ is "$output" "unhealthy" "output from 'podman healthcheck run'"
+
+ run_podman inspect $ctr --format "{{.State.Status}} {{.Config.HealthcheckOnFailureAction}}"
+ if [[ $policy == "restart" ]];then
+ # Container has been restarted and health check works again
+ is "$output" "running $policy" "container has been restarted"
+ run_podman healthcheck run $ctr
+ elif [[ $policy == "none" ]];then
+ # Container is still running and health check still broken
+ is "$output" "running $policy" "container continued running"
+ run_podman 1 healthcheck run $ctr
+ is "$output" "unhealthy" "output from 'podman healthcheck run'"
+ else
+ # kill and stop yield the container into a non-running state
+ is "$output" ".* $policy" "container was stopped/killed"
+ assert "$output" != "running $policy"
+ fi
+
+ run_podman rm -f -t0 $ctr
+ run_podman rmi -f $img
+ done
+}
+
# vim: filetype=sh
diff --git a/test/system/250-systemd.bats b/test/system/250-systemd.bats
index 9a91501dd..ddec3a492 100644
--- a/test/system/250-systemd.bats
+++ b/test/system/250-systemd.bats
@@ -33,7 +33,10 @@ function teardown() {
# Helper to start a systemd service running a container
function service_setup() {
- run_podman generate systemd --new $cname
+ run_podman generate systemd \
+ -e http_proxy -e https_proxy -e no_proxy \
+ -e HTTP_PROXY -e HTTPS_PROXY -e NO_PROXY \
+ --new $cname
echo "$output" > "$UNIT_FILE"
run_podman rm $cname
@@ -73,6 +76,18 @@ function service_cleanup() {
# These tests can fail in dev. environment because of SELinux.
# quick fix: chcon -t container_runtime_exec_t ./bin/podman
@test "podman generate - systemd - basic" {
+ # Flakes with "ActiveState=failed (expected =inactive)"
+ if is_ubuntu; then
+ skip "FIXME: 2022-09-01: requires conmon-2.1.4, ubuntu has 2.1.3"
+ fi
+
+ # Warn when a custom restart policy is used without --new (see #15284)
+ run_podman create --restart=always $IMAGE
+ cid="$output"
+ run_podman generate systemd $cid
+ is "$output" ".*Container $cid has restart policy .*always.* which can lead to issues on shutdown.*" "generate systemd emits warning"
+ run_podman rm -f $cid
+
cname=$(random_string)
# See #7407 for --pull=always.
run_podman create --pull=always --name $cname --label "io.containers.autoupdate=registry" $IMAGE \
@@ -295,25 +310,68 @@ LISTEN_FDNAMES=listen_fdnames" | sort)
run_podman network rm -f $netname
}
-@test "podman-kube@.service template" {
- # If running from a podman source directory, build and use the source
- # version of the play-kube-@ unit file
- unit_name="podman-kube@.service"
- unit_file="contrib/systemd/system/${unit_name}"
- if [[ -e ${unit_file}.in ]]; then
- echo "# [Building & using $unit_name from source]" >&3
- # Force regenerating unit file (existing one may have /usr/bin path)
- rm -f $unit_file
- BINDIR=$(dirname $PODMAN) make $unit_file
- cp $unit_file $UNIT_DIR/$unit_name
- fi
+@test "podman create --health-on-failure=kill" {
+ img="healthcheck_i"
+ _build_health_check_image $img
+
+ cname=$(random_string)
+ run_podman create --name $cname \
+ --health-cmd /healthcheck \
+ --health-on-failure=kill \
+ --restart=on-failure \
+ $img
+
+ # run container in systemd unit
+ service_setup
+
+ run_podman container inspect $cname --format "{{.ID}}"
+ oldID="$output"
+
+ run_podman healthcheck run $cname
+
+ # Now cause the healthcheck to fail
+ run_podman exec $cname touch /uh-oh
+ # healthcheck should now fail, with exit status 1 and 'unhealthy' output
+ run_podman 1 healthcheck run $cname
+ is "$output" "unhealthy" "output from 'podman healthcheck run'"
+
+ # What is expected to happen now:
+ # 1) The container gets killed as the health check has failed
+ # 2) Systemd restarts the service as the restart policy is set to "on-failure"
+ # 3) The /uh-oh file is gone and $cname has another ID
+
+ # Wait at most 10 seconds for the service to be restarted
+ local timeout=10
+ while [[ $timeout -gt 1 ]]; do
+ run_podman '?' container inspect $cname
+ if [[ $status == 0 ]]; then
+ if [[ "$output" != "$oldID" ]]; then
+ break
+ fi
+ fi
+ sleep 1
+ let timeout=$timeout-1
+ done
+
+ run_podman healthcheck run $cname
+
+ # stop systemd container
+ service_cleanup
+ run_podman rmi -f $img
+}
+
+@test "podman-kube@.service template" {
+ install_kube_template
# Create the YAMl file
yaml_source="$PODMAN_TMPDIR/test.yaml"
cat >$yaml_source <<EOF
apiVersion: v1
kind: Pod
metadata:
+ annotations:
+ io.containers.autoupdate: "local"
+ io.containers.autoupdate/b: "registry"
labels:
app: test
name: test_pod
@@ -322,8 +380,11 @@ spec:
- command:
- top
image: $IMAGE
- name: test
- resources: {}
+ name: a
+ - command:
+ - top
+ image: $IMAGE
+ name: b
EOF
# Dispatch the YAML file
@@ -344,6 +405,12 @@ EOF
run_podman 125 container rm $service_container
is "$output" "Error: container .* is the service container of pod(s) .* and cannot be removed without removing the pod(s)"
+ # Add a simple `auto-update --dry-run` test here to avoid too much redundancy
+ # with 255-auto-update.bats
+ run_podman auto-update --dry-run --format "{{.Unit}},{{.Container}},{{.Image}},{{.Updated}},{{.Policy}}"
+ is "$output" ".*$service_name,.* (test_pod-a),$IMAGE,false,local.*" "global auto-update policy gets applied"
+ is "$output" ".*$service_name,.* (test_pod-b),$IMAGE,false,registry.*" "container-specified auto-update policy gets applied"
+
# Kill the pod and make sure the service is not running.
# The restart policy is set to "never" since there is no
# design yet for propagating exit codes up to the service
diff --git a/test/system/255-auto-update.bats b/test/system/255-auto-update.bats
index 6cee939fb..76f6b02e8 100644
--- a/test/system/255-auto-update.bats
+++ b/test/system/255-auto-update.bats
@@ -115,6 +115,7 @@ function _confirm_update() {
# Image has already been pulled, so this shouldn't take too long
local timeout=5
while [[ $timeout -gt 0 ]]; do
+ sleep 1
run_podman '?' inspect --format "{{.Image}}" $cname
if [[ $status != 0 ]]; then
if [[ $output =~ (no such object|does not exist in database): ]]; then
@@ -126,7 +127,7 @@ function _confirm_update() {
elif [[ $output != $old_iid ]]; then
return
fi
- sleep 1
+ timeout=$((timeout - 1))
done
die "Timed out waiting for $cname to update; old IID=$old_iid"
@@ -234,6 +235,8 @@ function _confirm_update() {
_confirm_update $cname $ori_image
}
+# This test can fail in dev. environment because of SELinux.
+# quick fix: chcon -t container_runtime_exec_t ./bin/podman
@test "podman auto-update - label io.containers.autoupdate=local with rollback" {
# sdnotify fails with runc 1.0.0-3-dev2 on Ubuntu. Let's just
# assume that we work only with crun, nothing else.
@@ -264,8 +267,6 @@ EOF
# Generate a healthy image that will run correctly.
run_podman build -t quay.io/libpod/$image -f $dockerfile1
- podman image inspect --format "{{.ID}}" $image
- oldID="$output"
generate_service $image local /runme --sdnotify=container noTag
_wait_service_ready container-$cname.service
@@ -275,7 +276,7 @@ EOF
# Generate an unhealthy image that will fail.
run_podman build -t quay.io/libpod/$image -f $dockerfile2
- podman image inspect --format "{{.ID}}" $image
+ run_podman image inspect --format "{{.ID}}" $image
newID="$output"
run_podman auto-update --dry-run --format "{{.Unit}},{{.Image}},{{.Updated}},{{.Policy}}"
@@ -373,6 +374,12 @@ After=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/bin/podman auto-update
+Environment="http_proxy=${http_proxy}"
+Environment="HTTP_PROXY=${HTTP_PROXY}"
+Environment="https_proxy=${https_proxy}"
+Environment="HTTPS_PROXY=${HTTPS_PROXY}"
+Environment="no_proxy=${no_proxy}"
+Environment="NO_PROXY=${NO_PROXY}"
[Install]
WantedBy=default.target
@@ -407,4 +414,97 @@ EOF
_confirm_update $cname $ori_image
}
+@test "podman-kube@.service template with rollback" {
+ # sdnotify fails with runc 1.0.0-3-dev2 on Ubuntu. Let's just
+ # assume that we work only with crun, nothing else.
+ # [copied from 260-sdnotify.bats]
+ runtime=$(podman_runtime)
+ if [[ "$runtime" != "crun" ]]; then
+ skip "this test only works with crun, not $runtime"
+ fi
+
+ install_kube_template
+
+ dockerfile1=$PODMAN_TMPDIR/Dockerfile.1
+ cat >$dockerfile1 <<EOF
+FROM quay.io/libpod/fedora:31
+RUN echo -e "#!/bin/sh\n\
+printenv NOTIFY_SOCKET; echo READY; systemd-notify --ready;\n\
+trap 'echo Received SIGTERM, finishing; exit' SIGTERM; echo WAITING; while :; do sleep 0.1; done" \
+>> /runme
+RUN chmod +x /runme
+EOF
+
+ dockerfile2=$PODMAN_TMPDIR/Dockerfile.2
+ cat >$dockerfile2 <<EOF
+FROM quay.io/libpod/fedora:31
+RUN echo -e "#!/bin/sh\n\
+exit 1" >> /runme
+RUN chmod +x /runme
+EOF
+ local_image=localhost/image:$(random_string 10)
+
+ # Generate a healthy image that will run correctly.
+ run_podman build -t $local_image -f $dockerfile1
+ run_podman image inspect --format "{{.ID}}" $local_image
+ oldID="$output"
+
+ # Create the YAMl file
+ yaml_source="$PODMAN_TMPDIR/test.yaml"
+ cat >$yaml_source <<EOF
+apiVersion: v1
+kind: Pod
+metadata:
+ annotations:
+ io.containers.autoupdate: "registry"
+ io.containers.autoupdate/b: "local"
+ io.containers.sdnotify/b: "container"
+ labels:
+ app: test
+ name: test_pod
+spec:
+ containers:
+ - command:
+ - top
+ image: $IMAGE
+ name: a
+ - command:
+ - /runme
+ image: $local_image
+ name: b
+EOF
+
+ # Dispatch the YAML file
+ service_name="podman-kube@$(systemd-escape $yaml_source).service"
+ systemctl start $service_name
+ systemctl is-active $service_name
+
+ # Make sure the containers are properly configured
+ run_podman auto-update --dry-run --format "{{.Unit}},{{.Container}},{{.Image}},{{.Updated}},{{.Policy}}"
+ is "$output" ".*$service_name,.* (test_pod-a),$IMAGE,false,registry.*" "global auto-update policy gets applied"
+ is "$output" ".*$service_name,.* (test_pod-b),$local_image,false,local.*" "container-specified auto-update policy gets applied"
+
+ # Generate a broken image that will fail.
+ run_podman build -t $local_image -f $dockerfile2
+ run_podman image inspect --format "{{.ID}}" $local_image
+ newID="$output"
+
+ assert "$oldID" != "$newID" "broken image really is a new one"
+
+ # Make sure container b sees the new image
+ run_podman auto-update --dry-run --format "{{.Unit}},{{.Container}},{{.Image}},{{.Updated}},{{.Policy}}"
+ is "$output" ".*$service_name,.* (test_pod-a),$IMAGE,false,registry.*" "global auto-update policy gets applied"
+ is "$output" ".*$service_name,.* (test_pod-b),$local_image,pending,local.*" "container b sees the new image"
+
+ # Now update and check for the rollback
+ run_podman auto-update --format "{{.Unit}},{{.Container}},{{.Image}},{{.Updated}},{{.Policy}}"
+ is "$output" ".*$service_name,.* (test_pod-a),$IMAGE,rolled back,registry.*" "container a was rolled back as the update of b failed"
+ is "$output" ".*$service_name,.* (test_pod-b),$local_image,rolled back,local.*" "container b was rolled back as its update has failed"
+
+ # Clean up
+ systemctl stop $service_name
+ run_podman rmi -f $(pause_image) $local_image $newID $oldID
+ rm -f $UNIT_DIR/$unit_name
+}
+
# vim: filetype=sh
diff --git a/test/system/260-sdnotify.bats b/test/system/260-sdnotify.bats
index cd7b1262a..6c3ef7f3f 100644
--- a/test/system/260-sdnotify.bats
+++ b/test/system/260-sdnotify.bats
@@ -88,7 +88,13 @@ function _assert_mainpid_is_conmon() {
export NOTIFY_SOCKET=$PODMAN_TMPDIR/ignore.sock
_start_socat
- run_podman 1 run --rm --sdnotify=ignore $IMAGE printenv NOTIFY_SOCKET
+ run_podman create --rm --sdnotify=ignore $IMAGE printenv NOTIFY_SOCKET
+ cid="$output"
+
+ run_podman container inspect $cid --format "{{.Config.SdNotifyMode}} {{.Config.SdNotifySocket}}"
+ is "$output" "ignore " "NOTIFY_SOCKET is not set with 'ignore' mode"
+
+ run_podman 1 start --attach $cid
is "$output" "" "\$NOTIFY_SOCKET in container"
is "$(< $_SOCAT_LOG)" "" "nothing received on socket"
@@ -106,6 +112,9 @@ function _assert_mainpid_is_conmon() {
cid="$output"
wait_for_ready $cid
+ run_podman container inspect $cid --format "{{.Config.SdNotifyMode}} {{.Config.SdNotifySocket}}"
+ is "$output" "conmon $NOTIFY_SOCKET"
+
run_podman container inspect sdnotify_conmon_c --format "{{.State.ConmonPid}}"
mainPID="$output"
@@ -113,6 +122,7 @@ function _assert_mainpid_is_conmon() {
is "$output" "READY" "\$NOTIFY_SOCKET in container"
# The 'echo's help us debug failed runs
+ wait_for_file $_SOCAT_LOG
run cat $_SOCAT_LOG
echo "socat log:"
echo "$output"
@@ -132,7 +142,7 @@ READY=1" "sdnotify sent MAINPID and READY"
# These tests can fail in dev. environment because of SELinux.
# quick fix: chcon -t container_runtime_exec_t ./bin/podman
@test "sdnotify : container" {
- skip_if_aarch64 "FIXME: #15074 - fails on aarch64 non-remote"
+ skip_if_aarch64 "FIXME: #15277 sdnotify doesn't work on aarch64"
# Sigh... we need to pull a humongous image because it has systemd-notify.
# (IMPORTANT: fedora:32 and above silently removed systemd-notify; this
# caused CI to hang. That's why we explicitly require fedora:31)
@@ -147,13 +157,18 @@ READY=1" "sdnotify sent MAINPID and READY"
_start_socat
run_podman run -d --sdnotify=container $_FEDORA \
- sh -c 'printenv NOTIFY_SOCKET;echo READY;systemd-notify --ready;while ! test -f /stop;do sleep 0.1;done'
+ sh -c 'printenv NOTIFY_SOCKET; echo READY; while ! test -f /stop;do sleep 0.1;done;systemd-notify --ready'
cid="$output"
wait_for_ready $cid
+ run_podman container inspect $cid --format "{{.Config.SdNotifyMode}} {{.Config.SdNotifySocket}}"
+ is "$output" "container $NOTIFY_SOCKET"
+
run_podman logs $cid
is "${lines[0]}" "/run/notify/notify.sock" "NOTIFY_SOCKET is passed to container"
+ run_podman container inspect $cid --format "{{.State.ConmonPid}}"
+ mainPID="$output"
# With container, READY=1 isn't necessarily the last message received;
# just look for it anywhere in received messages
run cat $_SOCAT_LOG
@@ -161,19 +176,25 @@ READY=1" "sdnotify sent MAINPID and READY"
echo "socat log:"
echo "$output"
- is "$output" ".*READY=1" "received READY=1 through notify socket"
-
- _assert_mainpid_is_conmon "$output"
+ is "$output" "MAINPID=$mainPID" "Container is not ready yet, so we only know the main PID"
# Done. Stop container, clean up.
run_podman exec $cid touch /stop
run_podman wait $cid
+
+ wait_for_file $_SOCAT_LOG
+ run cat $_SOCAT_LOG
+ echo "socat log:"
+ echo "$output"
+ is "$output" "MAINPID=$mainPID
+READY=1"
+
run_podman rm $cid
run_podman rmi $_FEDORA
_stop_socat
}
-@test "sdnotify : play kube" {
+@test "sdnotify : play kube - no policies" {
# Create the YAMl file
yaml_source="$PODMAN_TMPDIR/test.yaml"
cat >$yaml_source <<EOF
@@ -202,8 +223,15 @@ EOF
_start_socat
run_podman play kube --service-container=true $yaml_source
+
+ # Make sure the containers have the correct policy.
+ run_podman container inspect test_pod-test $service_container --format "{{.Config.SdNotifyMode}}"
+ is "$output" "ignore
+ignore"
+
run_podman container inspect $service_container --format "{{.State.ConmonPid}}"
mainPID="$output"
+ wait_for_file $_SOCAT_LOG
# The 'echo's help us debug failed runs
run cat $_SOCAT_LOG
echo "socat log:"
@@ -216,9 +244,116 @@ READY=1" "sdnotify sent MAINPID and READY"
# Clean up pod and pause image
run_podman play kube --down $PODMAN_TMPDIR/test.yaml
- run_podman version --format "{{.Server.Version}}-{{.Server.Built}}"
- podman rmi -f localhost/podman-pause:$output
+ run_podman rmi $(pause_image)
}
+@test "sdnotify : play kube - with policies" {
+ skip_if_aarch64 "FIXME: #15277 sdnotify doesn't work on aarch64"
+
+ # Sigh... we need to pull a humongous image because it has systemd-notify.
+ # (IMPORTANT: fedora:32 and above silently removed systemd-notify; this
+ # caused CI to hang. That's why we explicitly require fedora:31)
+ # FIXME: is there a smaller image we could use?
+ local _FEDORA="$PODMAN_TEST_IMAGE_REGISTRY/$PODMAN_TEST_IMAGE_USER/fedora:31"
+ # Pull that image. Retry in case of flakes.
+ run_podman pull $_FEDORA || \
+ run_podman pull $_FEDORA || \
+ run_podman pull $_FEDORA
+
+ # Create the YAMl file
+ yaml_source="$PODMAN_TMPDIR/test.yaml"
+ cat >$yaml_source <<EOF
+apiVersion: v1
+kind: Pod
+metadata:
+ labels:
+ app: test
+ name: test_pod
+ annotations:
+ io.containers.sdnotify: "container"
+ io.containers.sdnotify/b: "conmon"
+spec:
+ containers:
+ - command:
+ - /bin/sh
+ - -c
+ - 'printenv NOTIFY_SOCKET; echo READY; while ! test -f /stop;do sleep 0.1;done;systemd-notify --ready'
+ image: $_FEDORA
+ name: a
+ - command:
+ - /bin/sh
+ - -c
+ - 'echo READY; top'
+ image: $IMAGE
+ name: b
+EOF
+ container_a="test_pod-a"
+ container_b="test_pod-b"
+
+ # The name of the service container is predictable: the first 12 characters
+ # of the hash of the YAML file followed by the "-service" suffix
+ yaml_sha=$(sha256sum $yaml_source)
+ service_container="${yaml_sha:0:12}-service"
+
+ export NOTIFY_SOCKET=$PODMAN_TMPDIR/conmon.sock
+ _start_socat
+
+ # Run `play kube` in the background as it will wait for all containers to
+ # send the READY=1 message.
+ timeout --foreground -v --kill=10 60 \
+ $PODMAN play kube --service-container=true $yaml_source &>/dev/null &
+
+ # Wait for both containers to be running
+ for i in $(seq 1 20); do
+ run_podman "?" container wait $container_a $container_b --condition="running"
+ if [[ $status == 0 ]]; then
+ break
+ fi
+ sleep 0.5
+ # Just for debugging
+ run_podman ps -a
+ done
+ if [[ $status != 0 ]]; then
+ die "container $container_a and/or $container_b did not start"
+ fi
+
+ # Make sure the containers have the correct policy
+ run_podman container inspect $container_a $container_b $service_container --format "{{.Config.SdNotifyMode}}"
+ is "$output" "container
+conmon
+ignore"
+
+ is "$(< $_SOCAT_LOG)" "" "nothing received on socket"
+
+ # Make sure the container received a "proxy" socket and is not using the
+ # one of `kube play`
+ run_podman container inspect $container_a --format "{{.Config.SdNotifySocket}}"
+ assert "$output" != $NOTIFY_SOCKET
+
+ run_podman logs $container_a
+ is "${lines[0]}" "/run/notify/notify.sock" "NOTIFY_SOCKET is passed to container"
+
+ # Instruct the container to send the READY
+ run_podman exec $container_a /bin/touch /stop
+
+ run_podman container inspect $service_container --format "{{.State.ConmonPid}}"
+ main_pid="$output"
+
+ run_podman container wait $container_a
+ wait_for_file $_SOCAT_LOG
+ # The 'echo's help us debug failed runs
+ run cat $_SOCAT_LOG
+ echo "socat log:"
+ echo "$output"
+
+ is "$output" "MAINPID=$main_pid
+READY=1" "sdnotify sent MAINPID and READY"
+
+ _stop_socat
+
+ # Clean up pod and pause image
+ run_podman play kube --down $yaml_source
+ run_podman rmi $_FEDORA $(pause_image)
+}
# vim: filetype=sh
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/280-update.bats b/test/system/280-update.bats
new file mode 100644
index 000000000..c7037c286
--- /dev/null
+++ b/test/system/280-update.bats
@@ -0,0 +1,130 @@
+#!/usr/bin/env bats -*- bats -*-
+#
+# Tests for podman update
+#
+
+load helpers
+
+LOOPDEVICE=
+
+function teardown() {
+ if [[ -n "$LOOPDEVICE" ]]; then
+ losetup -d $LOOPDEVICE
+ LOOPDEVICE=
+ fi
+ basic_teardown
+}
+
+
+@test "podman update - test all options" {
+
+ local cgv=1
+ if is_cgroupsv2; then
+ cgv=2;
+ fi
+
+ # Need a block device for blkio-weight-device testing
+ local pass_loop_device=
+ if ! is_rootless; then
+ if is_cgroupsv2; then
+ lofile=${PODMAN_TMPDIR}/disk.img
+ fallocate -l 1k ${lofile}
+ LOOPDEVICE=$(losetup --show -f $lofile)
+ pass_loop_device="--device $LOOPDEVICE"
+
+ # Get maj:min (tr needed because losetup seems to use %2d)
+ lomajmin=$(losetup -l --noheadings --output MAJ:MIN $LOOPDEVICE | tr -d ' ')
+ fi
+ fi
+
+ # Shortcuts to make the table narrower
+ local -a gig=(0 1073741824 2147483648 3221225472)
+ local devicemax="1:5 rbps=10485760 wbps=31457280 riops=2000 wiops=4000"
+ local mm=memory/memory
+
+ # Format:
+ # --<option> = <value> | rootless? | check: cgroups v1 | check: cgroups v2
+ #
+ # Requires very wide window to read. Sorry.
+ #
+ # FIXMEs:
+ # cpu-rt-period (cgv1 only, on cpu/cpu.rt_period_us) works on RHEL8 but not on Ubuntu
+ # cpu-rt-runtime (cgv1 only, on cpu/cpu.rt_runtime_us) fails: error setting cgroup config for procHooks ...
+ tests="
+cpu-shares = 512 | - | cpu/cpu.shares = 512 | cpu.weight = 20
+cpus = 5 | - | cpu/cpu.cfs_quota_us = 500000 | cpu.max = 500000 100000
+cpuset-cpus = 0 | - | cpuset/cpuset.cpus = 0 | cpuset.cpus = 0
+cpuset-mems = 0 | - | cpuset/cpuset.mems = 0 | cpuset.mems = 0
+
+memory = 1G | 2 | $mm.limit_in_bytes = ${gig[1]} | memory.max = ${gig[1]}
+memory-swap = 3G | 2 | $mm.memsw.limit_in_bytes = ${gig[3]} | memory.swap.max = ${gig[2]}
+memory-reservation = 400M | 2 | $mm.soft_limit_in_bytes = 419430400 | memory.low = 419430400
+
+blkio-weight = 321 | - | - | io.bfq.weight = default 321 $lomajmin 98
+blkio-weight-device = $LOOPDEVICE:98 | - | - | io.bfq.weight = default 321 $lomajmin 98
+
+device-read-bps = /dev/zero:10mb | - | - | io.max = $devicemax
+device-read-iops = /dev/zero:2000 | - | - | io.max = $devicemax
+device-write-bps = /dev/zero:30mb | - | - | io.max = $devicemax
+device-write-iops = /dev/zero:4000 | - | - | io.max = $devicemax
+"
+
+ # Run a container
+ run_podman run ${pass_loop_device} -d $IMAGE sleep infinity
+ cid="$output"
+
+ # Pass 1: read the table above, gather up the options applicable
+ # to this test environment (root/rootless, cgroups v1/v2)
+ local -a opts
+ local -A check
+ while read opt works_rootless cgv1 cgv2; do
+ if is_rootless; then
+ local skipping="skipping --$opt : does not work rootless"
+ if [[ $works_rootless = '-' ]]; then
+ echo "[ $skipping ]"
+ continue
+ fi
+ if [[ ! $works_rootless =~ $cgv ]]; then
+ echo "[ $skipping on cgroups v$cgv ]"
+ continue
+ fi
+ fi
+
+ tuple=$cgv1
+ if is_cgroupsv2; then
+ tuple=$cgv2
+ fi
+ if [[ $tuple = '-' ]]; then
+ echo "[ skipping --$opt : N/A on cgroups v$cgv ]"
+ continue
+ fi
+
+ # OK: setting is applicable. Preserve it. (First removing whitespace)
+ opt=${opt// /}
+ opts+=("--$opt")
+ check["--$opt"]=$tuple
+ done < <(parse_table "$tests")
+
+ # Now do the update in one fell swoop
+ run_podman update "${opts[@]}" $cid
+
+ # ...and check one by one
+ for opt in "${opts[@]}"; do
+ read path op expect <<<"${check[$opt]}"
+ run_podman exec $cid cat /sys/fs/cgroup/$path
+
+ # Magic echo of unquoted-output converts newlines to spaces;
+ # important for otherwise multiline blkio file.
+ updated="$(echo $output)"
+ assert "$updated" $op "$expect" "$opt ($path)"
+ done
+
+ # Clean up
+ run_podman rm -f -t0 $cid
+ if [[ -n "$LOOPDEVICE" ]]; then
+ losetup -d $LOOPDEVICE
+ LOOPDEVICE=
+ fi
+}
+
+# vim: filetype=sh
diff --git a/test/system/320-system-df.bats b/test/system/320-system-df.bats
index 217357b37..35e121c62 100644
--- a/test/system/320-system-df.bats
+++ b/test/system/320-system-df.bats
@@ -27,7 +27,7 @@ function teardown() {
run_podman system df --format '{{ .Type }}:{{ .Total }}:{{ .Active }}'
is "${lines[0]}" "Images:1:1" "system df : Images line"
is "${lines[1]}" "Containers:2:1" "system df : Containers line"
- is "${lines[2]}" "Local Volumes:2:1" "system df : Volumes line"
+ is "${lines[2]}" "Local Volumes:2:2" "system df : Volumes line"
# Try -v. (Grrr. No way to specify individual formats)
#
diff --git a/test/system/330-corrupt-images.bats b/test/system/330-corrupt-images.bats
index 7f2b81835..2f0fd753c 100644
--- a/test/system/330-corrupt-images.bats
+++ b/test/system/330-corrupt-images.bats
@@ -74,7 +74,7 @@ function _corrupt_image_test() {
# Corruptify, and confirm that 'podman images' throws an error
rm -v ${PODMAN_CORRUPT_TEST_WORKDIR}/root/*-images/$id/${rm_path}
run_podman 125 images
- is "$output" "Error: error retrieving label for image \"$id\": you may need to remove the image to resolve the error.*"
+ is "$output" "Error: retrieving label for image \"$id\": you may need to remove the image to resolve the error.*"
# Run the requested command. Confirm it succeeds, with suitable warnings
run_podman $*
diff --git a/test/system/400-unprivileged-access.bats b/test/system/400-unprivileged-access.bats
index 0d6be2d60..d70c95973 100644
--- a/test/system/400-unprivileged-access.bats
+++ b/test/system/400-unprivileged-access.bats
@@ -119,7 +119,7 @@ EOF
# Some of the above may not exist on our host. Find only the ones that do.
local -a subset=()
- for mp in ${mps[@]}; do
+ for mp in "${mps[@]}"; do
if [ -e $mp ]; then
subset+=($mp)
fi
@@ -128,7 +128,7 @@ EOF
# Run 'stat' on all the files, plus /dev/null. Get path, file type,
# number of links, major, and minor (see below for why). Do it all
# in one go, to avoid multiple podman-runs
- run_podman '?' run --rm $IMAGE stat -c'%n:%F:%h:%T:%t' /dev/null ${subset[@]}
+ run_podman '?' run --rm $IMAGE stat -c'%n:%F:%h:%T:%t' /dev/null "${subset[@]}"
assert $status -le 1 "stat exit status: expected 0 or 1"
local devnull=
diff --git a/test/system/410-selinux.bats b/test/system/410-selinux.bats
index 082482c7a..cc86f282a 100644
--- a/test/system/410-selinux.bats
+++ b/test/system/410-selinux.bats
@@ -212,7 +212,7 @@ function check_label() {
# https://github.com/opencontainers/selinux/pull/148/commits/a5dc47f74c56922d58ead05d1fdcc5f7f52d5f4e
# from failed to set /proc/self/attr/keycreate on procfs
# to write /proc/self/attr/keycreate: invalid argument
- runc) expect="OCI runtime error: .*: \(failed to set|write\) /proc/self/attr/keycreate" ;;
+ runc) expect="OCI runtime error: .*: \(failed to set\|write\) /proc/self/attr/keycreate.*" ;;
*) skip "Unknown runtime '$runtime'";;
esac
diff --git a/test/system/420-cgroups.bats b/test/system/420-cgroups.bats
index 025a20012..3269f666c 100644
--- a/test/system/420-cgroups.bats
+++ b/test/system/420-cgroups.bats
@@ -19,6 +19,8 @@ load helpers
esac
run_podman --cgroup-manager=$other run --name myc $IMAGE true
+ assert "$output" = "" "run true, with cgroup-manager=$other, is silent"
+
run_podman container inspect --format '{{.HostConfig.CgroupManager}}' myc
is "$output" "$other" "podman preserved .HostConfig.CgroupManager"
@@ -29,7 +31,8 @@ load helpers
# Restart the container, without --cgroup-manager option (ie use default)
# Prior to #7970, this would fail with an OCI runtime error
- run_podman start myc
+ run_podman start -a myc
+ assert "$output" = "" "restarted container emits no output"
run_podman rm myc
}
diff --git a/test/system/500-networking.bats b/test/system/500-networking.bats
index b9a173c2a..862bc285c 100644
--- a/test/system/500-networking.bats
+++ b/test/system/500-networking.bats
@@ -61,9 +61,9 @@ load helpers
is "$output" "$random_2" "curl 127.0.0.1:/index2.txt"
# Verify http contents: wget from a second container
- run_podman run --rm --net=host $IMAGE wget -qO - $SERVER/index.txt
+ run_podman run --rm --net=host --http-proxy=false $IMAGE wget -qO - $SERVER/index.txt
is "$output" "$random_1" "podman wget /index.txt"
- run_podman run --rm --net=host $IMAGE wget -qO - $SERVER/index2.txt
+ run_podman run --rm --net=host --http-proxy=false $IMAGE wget -qO - $SERVER/index2.txt
is "$output" "$random_2" "podman wget /index2.txt"
# Tests #4889 - two-argument form of "podman ports" was broken
@@ -767,4 +767,14 @@ EOF
is "$output" "" "Should print no output"
}
+@test "podman network rm --dns-option " {
+ dns_opt=dns$(random_string)
+ run_podman run --rm --dns-opt=${dns_opt} $IMAGE cat /etc/resolv.conf
+ is "$output" ".*options ${dns_opt}" "--dns-opt was added"
+
+ dns_opt=dns$(random_string)
+ run_podman run --rm --dns-option=${dns_opt} $IMAGE cat /etc/resolv.conf
+ is "$output" ".*options ${dns_opt}" "--dns-option was added"
+}
+
# vim: filetype=sh
diff --git a/test/system/520-checkpoint.bats b/test/system/520-checkpoint.bats
index 7c8fc143a..73fa5d4c4 100644
--- a/test/system/520-checkpoint.bats
+++ b/test/system/520-checkpoint.bats
@@ -101,6 +101,25 @@ function teardown() {
run_podman rm -t 0 -f $cid
}
+@test "podman checkpoint/restore print IDs or raw input" {
+ # checkpoint/restore -a must print the IDs
+ run_podman run -d $IMAGE top
+ ctrID="$output"
+ run_podman container checkpoint -a
+ is "$output" "$ctrID"
+ run_podman container restore -a
+ is "$output" "$ctrID"
+
+ # checkpoint/restore $input must print $input
+ cname=$(random_string)
+ run_podman run -d --name $cname $IMAGE top
+ run_podman container checkpoint $cname
+ is "$output" $cname
+ run_podman container restore $cname
+ is "$output" $cname
+
+ run_podman rm -t 0 -f $ctrID $cname
+}
@test "podman checkpoint --export, with volumes" {
skip_if_remote "Test uses --root/--runroot, which are N/A over remote"
diff --git a/test/system/610-format.bats b/test/system/610-format.bats
new file mode 100644
index 000000000..8f74634d1
--- /dev/null
+++ b/test/system/610-format.bats
@@ -0,0 +1,184 @@
+#!/usr/bin/env bats -*- bats -*-
+#
+# PR #15673: For all commands that accept --format '{{.GoTemplate}}',
+# invoke with --format '{{"\n"}}' and make sure they don't choke.
+#
+
+load helpers
+
+function teardown() {
+ # In case test fails: standard teardown does not wipe machines or secrets
+ run_podman '?' machine rm -f mymachine
+ run_podman '?' secret rm mysecret
+
+ basic_teardown
+}
+
+# Most commands can't just be run with --format; they need an argument or
+# option. This table defines what those are.
+#
+# FIXME: once you've finished fixing them all, remove the SKIPs (just
+# remove the entire lines, except for pod-inspect, just remove the SKIP
+# but leave "mypod")
+extra_args_table="
+history | $IMAGE
+image history | $IMAGE
+image inspect | $IMAGE
+container inspect | mycontainer
+
+volume inspect | -a
+secret inspect | mysecret
+network inspect | podman
+ps | -a
+
+image search | $IMAGE
+search | $IMAGE
+
+pod inspect | mypod
+
+events | --stream=false --events-backend=file
+"
+
+# podman machine is finicky. Assume we can't run it, but see below for more.
+can_run_podman_machine=
+
+# podman stats, too
+can_run_stats=
+
+# Main test loop. Recursively runs 'podman [subcommand] help', looks for:
+# > '[command]', which indicates, recurse; or
+# > '--format', in which case we
+# > check autocompletion, look for Go templates, in which case we
+# > run the command with --format '{{"\n"}}' and make sure it passes
+function check_subcommand() {
+ for cmd in $(_podman_commands "$@"); do
+ # Special case: 'podman machine' can only be run under ideal conditions
+ if [[ "$cmd" = "machine" ]] && [[ -z "$can_run_podman_machine" ]]; then
+ continue
+ fi
+ if [[ "$cmd" = "stats" ]] && [[ -z "$can_run_stats" ]]; then
+ continue
+ fi
+
+ # Human-readable podman command string, with multiple spaces collapsed
+ command_string="podman $* $cmd"
+ command_string=${command_string// / } # 'podman x' -> 'podman x'
+
+ # Run --help, decide if this is a subcommand with subcommands
+ run_podman "$@" $cmd --help
+ local full_help="$output"
+
+ # The line immediately after 'Usage:' gives us a 1-line synopsis
+ usage=$(echo "$full_help" | grep -A1 '^Usage:' | tail -1)
+ assert "$usage" != "" "podman $cmd: no Usage message found"
+
+ # Strip off the leading command string; we no longer need it
+ usage=$(sed -e "s/^ $command_string \?//" <<<"$usage")
+
+ # If usage ends in '[command]', recurse into subcommands
+ if expr "$usage" : '\[command\]' >/dev/null; then
+ # (except for 'podman help', which is a special case)
+ if [[ $cmd != "help" ]]; then
+ check_subcommand "$@" $cmd
+ fi
+ continue
+ fi
+
+ # Not a subcommand-subcommand. Look for --format option
+ if [[ ! "$output" =~ "--format" ]]; then
+ continue
+ fi
+
+ # Have --format. Make sure it's a Go-template option, not like --push
+ run_podman __completeNoDesc "$@" "$cmd" --format '{{.'
+ if [[ ! "$output" =~ \{\{\.[A-Z] ]]; then
+ continue
+ fi
+
+ # Got one.
+ dprint "$command_string has --format"
+
+ # Whatever is needed to make a runnable command
+ local extra=${extra_args[$command_string]}
+ if [[ -n "$extra" ]]; then
+ # Cross off our list
+ unset extra_args["$command_string"]
+ fi
+
+ # This is what does the work. We run with '?' so we can offer
+ # better error messages than just "exited with error status".
+ run_podman '?' "$@" "$cmd" $extra --format '{{"\n"}}'
+
+ # Output must always be empty.
+ #
+ # - If you see "unterminated quoted string" here, there's a
+ # regression, and you need to fix --format (see PR #15673)
+ #
+ # - If you see any other error, it probably means that someone
+ # added a new podman subcommand that supports --format but
+ # needs some sort of option or argument to actually run.
+ # See 'extra_args_table' at the top of this script.
+ #
+ assert "$output" = "" "$command_string --format '{{\"\n\"}}'"
+
+ # *Now* check exit status. This should never, ever, ever trigger!
+ # If it does, it means the podman command failed without an err msg!
+ assert "$status" = "0" \
+ "$command_string --format '{{\"\n\"}}' failed with no output!"
+ done
+}
+
+# Test entry point
+@test "check Go template formatting" {
+ skip_if_remote
+
+ # Setup: some commands need a container, pod, secret, ...
+ run_podman run -d --name mycontainer $IMAGE top
+ run_podman pod create mypod
+ run_podman secret create mysecret /etc/hosts
+
+ # ...or machine. But podman machine is ultra-finicky, it fails as root
+ # or if qemu is missing. Instead of checking for all the possible ways
+ # to skip it, just try running init. If it works, we can test it.
+ run_podman '?' machine init --image-path=/dev/null mymachine
+ if [[ $status -eq 0 ]]; then
+ can_run_podman_machine=true
+ extra_args_table+="
+machine inspect | mymachine
+"
+ fi
+
+ # Similarly, 'stats' cannot run rootless under cgroups v1
+ if ! is_rootless || is_cgroupsv2; then
+ can_run_stats=true
+ extra_args_table+="
+container stats | --no-stream
+pod stats | --no-stream
+stats | --no-stream
+"
+ fi
+
+ # Convert the table at top to an associative array, keyed on subcommand
+ declare -A extra_args
+ while read subcommand extra; do
+ extra_args["podman $subcommand"]=$extra
+ done < <(parse_table "$extra_args_table")
+
+ # Run the test
+ check_subcommand
+
+ # Clean up
+ run_podman pod rm mypod
+ run_podman rmi $(pause_image)
+ run_podman rm -f -t0 mycontainer
+ run_podman secret rm mysecret
+ run_podman '?' machine rm -f mymachine
+
+ # Make sure there are no leftover commands in our table - this would
+ # indicate a typo in the table, or a flaw in our logic such that
+ # we're not actually recursing.
+ local leftovers="${!extra_args[@]}"
+ assert "$leftovers" = "" "Did not find (or test) subcommands:"
+}
+
+# vim: filetype=sh
diff --git a/test/system/700-play.bats b/test/system/700-play.bats
index 72602a9e6..bad9544ff 100644
--- a/test/system/700-play.bats
+++ b/test/system/700-play.bats
@@ -182,8 +182,11 @@ EOF
run_podman container inspect --format "{{.HostConfig.NetworkMode}}" $infraID
is "$output" "none" "network mode none is set for the container"
- run_podman stop -a -t 0
- run_podman pod rm -t 0 -f test_pod
+ run_podman kube down - < $PODMAN_TMPDIR/test.yaml
+ run_podman 125 inspect test_pod-test
+ is "$output" ".*Error: inspecting object: no such object: \"test_pod-test\""
+ run_podman pod rm -a
+ run_podman rm -a
}
@test "podman play with user from image" {
@@ -325,7 +328,6 @@ spec:
- name: TERM
value: xterm
- name: container
-
value: podman
image: quay.io/libpod/userimage
name: test
@@ -353,6 +355,34 @@ status: {}
run_podman inspect --format "{{.HostConfig.LogConfig.Type}}" test_pod-test
is "$output" "$default_driver" "play kube uses default log driver"
- run_podman stop -a -t 0
- run_podman pod rm -t 0 -f test_pod
+ run_podman kube down $PODMAN_TMPDIR/test.yaml
+ run_podman 125 inspect test_pod-test
+ is "$output" ".*Error: inspecting object: no such object: \"test_pod-test\""
+ 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..97a640e3f
--- /dev/null
+++ b/test/system/710-kube.bats
@@ -0,0 +1,160 @@
+#!/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")
+
+ 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: 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")
+
+ 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
new file mode 100644
index 000000000..4f1682d48
--- /dev/null
+++ b/test/system/900-ssh.bats
@@ -0,0 +1,61 @@
+#!/usr/bin/env bats
+#
+# Simplest set of podman tests. If any of these fail, we have serious problems.
+#
+
+load helpers
+
+# Override standard setup! We don't yet trust podman-images or podman-rm
+function setup() {
+ if ! is_remote; then
+ skip "only applicable on podman-remote"
+ fi
+
+ basic_setup
+}
+
+function teardown() {
+ if ! is_remote; then
+ return
+ fi
+
+ # In case test function failed to clean up
+ if [[ -n $_SERVICE_PID ]]; then
+ run kill $_SERVICE_PID
+ fi
+
+ # see test/system/272-system-connection.bats for why this is needed
+ mount \
+ | grep $PODMAN_TMPDIR \
+ | awk '{print $3}' \
+ | xargs -l1 --no-run-if-empty umount
+
+ run_podman system connection rm --all
+
+ basic_teardown
+}
+
+function _run_podman_remote() {
+ PODMAN=${PODMAN%%--url*} run_podman "$@"
+}
+
+@test "podman --ssh test" {
+ skip_if_no_ssh "cannot run these tests without an ssh binary"
+ # Start server
+ _SERVICE_PORT=$(random_free_port 63000-64999)
+
+ ${PODMAN%%-remote*} --root ${PODMAN_TMPDIR}/root \
+ --runroot ${PODMAN_TMPDIR}/runroot \
+ system service -t 99 tcp://localhost:$_SERVICE_PORT &
+ _SERVICE_PID=$!
+ wait_for_port localhost $_SERVICE_PORT
+
+ notme=${PODMAN_ROOTLESS_USER}
+
+ uid=$(id -u $notme)
+
+ run_podman 125 --ssh=native system connection add testing ssh://$notme@localhost:22/run/user/$uid/podman/podman.sock
+ is "$output" "Error: exit status 255"
+
+ # need to figure out how to podman remote test with the new ssh
+}
diff --git a/test/system/TODO.md b/test/system/TODO.md
index e47292f26..55e7601d1 100644
--- a/test/system/TODO.md
+++ b/test/system/TODO.md
@@ -1,4 +1,4 @@
-![PODMAN logo](../../logo/podman-logo-source.svg)
+![PODMAN logo](https://raw.githubusercontent.com/containers/common/main/logos/podman-logo-full-vert.png)
# Overview
diff --git a/test/system/helpers.bash b/test/system/helpers.bash
index 19bc6547c..4bc1ba78c 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
@@ -191,6 +177,15 @@ function run_podman() {
# without "quotes", multiple lines are glommed together into one
if [ -n "$output" ]; then
echo "$output"
+
+ # FIXME FIXME FIXME: instrumenting to track down #15488. Please
+ # remove once that's fixed. We include the args because, remember,
+ # bats only shows output on error; it's possible that the first
+ # instance of the metacopy warning happens in a test that doesn't
+ # check output, hence doesn't fail.
+ if [[ "$output" =~ Ignoring.global.metacopy.option ]]; then
+ echo "# YO! metacopy warning triggered by: podman $*" >&3
+ fi
fi
if [ "$status" -ne 0 ]; then
echo -n "[ rc=$status ";
@@ -342,11 +337,32 @@ function wait_for_port() {
die "Timed out waiting for $host:$port"
}
+###################
+# wait_for_file # Returns once file is available on host
+###################
+function wait_for_file() {
+ local file=$1 # The path to the file
+ local _timeout=${2:-5} # Optional; default 5 seconds
+
+ # Wait
+ while [ $_timeout -gt 0 ]; do
+ test -e $file && return
+ sleep 1
+ _timeout=$(( $_timeout - 1 ))
+ done
+
+ die "Timed out waiting for $file"
+}
+
# END podman helpers
###############################################################################
# BEGIN miscellaneous tools
# Shortcuts for common needs:
+function no_ssh() {
+ [ "$(man ssh)" -ne 0 ]
+}
+
function is_ubuntu() {
grep -qiw ubuntu /etc/os-release
}
@@ -470,6 +486,17 @@ function _add_label_if_missing() {
}
######################
+# skip_if_no_ssh # ...with an optional message
+######################
+function skip_if_no_ssh() {
+ if no_ssh; then
+ local msg=$(_add_label_if_missing "$1" "ssh")
+ skip "${msg:-not applicable with no ssh binary}"
+ fi
+}
+
+
+######################
# skip_if_rootless # ...with an optional message
######################
function skip_if_rootless() {
@@ -876,5 +903,59 @@ function _podman_commands() {
awk '/^Available Commands:/{ok=1;next}/^Options:/{ok=0}ok { print $1 }' <<<"$output" | grep .
}
+###############################
+# _build_health_check_image # Builds a container image with a configured health check
+###############################
+#
+# The health check will fail once the /uh-oh file exists.
+#
+# First argument is the desired name of the image
+# Second argument, if present and non-null, forces removal of the /uh-oh file once the check failed; this way the container can be restarted
+#
+
+function _build_health_check_image {
+ local imagename="$1"
+ local cleanfile=""
+
+ if [[ ! -z "$2" ]]; then
+ cleanfile="rm -f /uh-oh"
+ fi
+ # 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
+#!/bin/sh
+
+if test -e /uh-oh; then
+ echo "Uh-oh on stdout!"
+ echo "Uh-oh on stderr!" >&2
+ ${cleanfile}
+ exit 1
+else
+ echo "Life is Good on stdout"
+ echo "Life is Good on stderr" >&2
+ exit 0
+fi
+EOF
+
+ cat >${PODMAN_TMPDIR}/entrypoint <<EOF
+#!/bin/sh
+
+trap 'echo Received SIGTERM, finishing; exit' SIGTERM; echo WAITING; while :; do sleep 0.1; done
+EOF
+
+ cat >${PODMAN_TMPDIR}/Containerfile <<EOF
+FROM $IMAGE
+
+COPY healthcheck /healthcheck
+COPY entrypoint /entrypoint
+
+RUN chmod 755 /healthcheck /entrypoint
+
+CMD ["/entrypoint"]
+EOF
+
+ run_podman build -t $imagename ${PODMAN_TMPDIR}
+}
+
# END miscellaneous tools
###############################################################################
diff --git a/test/system/helpers.systemd.bash b/test/system/helpers.systemd.bash
index d9abc087d..afbab6e08 100644
--- a/test/system/helpers.systemd.bash
+++ b/test/system/helpers.systemd.bash
@@ -32,3 +32,17 @@ journalctl() {
systemd-run() {
command systemd-run $_DASHUSER "$@";
}
+
+install_kube_template() {
+ # If running from a podman source directory, build and use the source
+ # version of the play-kube-@ unit file
+ unit_name="podman-kube@.service"
+ unit_file="contrib/systemd/system/${unit_name}"
+ if [[ -e ${unit_file}.in ]]; then
+ echo "# [Building & using $unit_name from source]" >&3
+ # Force regenerating unit file (existing one may have /usr/bin path)
+ rm -f $unit_file
+ BINDIR=$(dirname $PODMAN) make $unit_file
+ cp $unit_file $UNIT_DIR/$unit_name
+ fi
+}
diff --git a/test/testvol/main.go b/test/testvol/main.go
index dd4ba642d..ab26e2df0 100644
--- a/test/testvol/main.go
+++ b/test/testvol/main.go
@@ -80,7 +80,7 @@ func startServer(socketPath string) error {
if config.path == "" {
path, err := ioutil.TempDir("", "test_volume_plugin")
if err != nil {
- return fmt.Errorf("error getting directory for plugin: %w", err)
+ return fmt.Errorf("getting directory for plugin: %w", err)
}
config.path = path
} else {
@@ -98,7 +98,7 @@ func startServer(socketPath string) error {
server := volume.NewHandler(handle)
if err := server.ServeUnix(socketPath, 0); err != nil {
- return fmt.Errorf("error starting server: %w", err)
+ return fmt.Errorf("starting server: %w", err)
}
return nil
}
@@ -161,7 +161,7 @@ func (d *DirDriver) Create(opts *volume.CreateRequest) error {
volPath := filepath.Join(d.volumesPath, opts.Name)
if err := os.Mkdir(volPath, 0755); err != nil {
- return fmt.Errorf("error making volume directory: %w", err)
+ return fmt.Errorf("making volume directory: %w", err)
}
newVol.path = volPath
@@ -240,7 +240,7 @@ func (d *DirDriver) Remove(req *volume.RemoveRequest) error {
delete(d.volumes, req.Name)
if err := os.RemoveAll(vol.path); err != nil {
- return fmt.Errorf("error removing mountpoint of volume %s: %w", req.Name, err)
+ return fmt.Errorf("removing mountpoint of volume %s: %w", req.Name, err)
}
logrus.Debugf("Removed volume %s", req.Name)
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)
}
diff --git a/test/upgrade/test-upgrade.bats b/test/upgrade/test-upgrade.bats
index 5efe05d49..dca97e324 100644
--- a/test/upgrade/test-upgrade.bats
+++ b/test/upgrade/test-upgrade.bats
@@ -345,10 +345,10 @@ failed | exited | 17
@test "rm a stopped container" {
run_podman rm myfailedcontainer
- is "$output" "[0-9a-f]\\{64\\}" "podman rm myfailedcontainer"
+ is "$output" "myfailedcontainer" "podman rm myfailedcontainer"
run_podman rm mydonecontainer
- is "$output" "[0-9a-f]\\{64\\}" "podman rm mydonecontainer"
+ is "$output" "mydonecontainer" "podman rm mydonecontainer"
}
diff --git a/test/utils/utils.go b/test/utils/utils.go
index 9c2a63c81..19b287ae1 100644
--- a/test/utils/utils.go
+++ b/test/utils/utils.go
@@ -225,7 +225,7 @@ func (p *PodmanTest) WaitContainerReady(id string, expStr string, timeout int, s
return false
}
- if strings.Contains(s.OutputToString(), expStr) {
+ if strings.Contains(s.OutputToString(), expStr) || strings.Contains(s.ErrorToString(), expStr) {
return true
}
time.Sleep(time.Duration(step) * time.Second)