summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/apiv2/12-imagesMore.at5
-rw-r--r--test/apiv2/20-containers.at5
-rw-r--r--test/apiv2/python/conftest.py8
-rw-r--r--test/apiv2/python/requirements.txt5
-rwxr-xr-xtest/apiv2/test-apiv263
-rwxr-xr-xtest/buildah-bud/apply-podman-deltas12
-rw-r--r--test/buildah-bud/buildah-tests.diff21
-rw-r--r--test/checkseccomp/checkseccomp.go1
-rw-r--r--test/compose/ipam_set_ip/tests.sh6
-rw-r--r--test/compose/slirp4netns_opts/tests.sh14
-rw-r--r--test/compose/two_networks/tests.sh8
-rw-r--r--test/e2e/attach_test.go8
-rw-r--r--test/e2e/build/Containerfile.with-multiple-secret (renamed from test/e2e/build/Dockerfile.with-multiple-secret)0
-rw-r--r--test/e2e/build/Containerfile.with-secret (renamed from test/e2e/build/Dockerfile.with-secret)0
-rw-r--r--test/e2e/build/Dockerfile.test-cp-root-dir2
-rw-r--r--test/e2e/build/secret-verify-leak/Containerfile.with-secret-verify-leak (renamed from test/e2e/build/Dockerfile.with-secret-verify-leak)0
-rw-r--r--test/e2e/build/workdir-symlink/Dockerfile5
-rw-r--r--test/e2e/build_test.go19
-rw-r--r--test/e2e/checkpoint_test.go8
-rw-r--r--test/e2e/commit_test.go7
-rw-r--r--test/e2e/common_test.go29
-rw-r--r--test/e2e/containers_conf_test.go5
-rw-r--r--test/e2e/create_test.go37
-rw-r--r--test/e2e/generate_kube_test.go14
-rw-r--r--test/e2e/generate_systemd_test.go52
-rw-r--r--test/e2e/healthcheck_run_test.go10
-rw-r--r--test/e2e/inspect_test.go8
-rw-r--r--test/e2e/libpod_suite_test.go1
-rw-r--r--test/e2e/login_logout_test.go6
-rw-r--r--test/e2e/network_create_test.go6
-rw-r--r--test/e2e/play_build_test.go1
-rw-r--r--test/e2e/play_kube_test.go55
-rw-r--r--test/e2e/run_aardvark_test.go314
-rw-r--r--test/e2e/run_apparmor_test.go1
-rw-r--r--test/e2e/run_device_test.go5
-rw-r--r--test/e2e/run_networking_test.go155
-rw-r--r--test/e2e/system_df_test.go17
-rw-r--r--test/e2e/system_service_test.go2
-rw-r--r--test/e2e/systemd_activate_test.go107
-rw-r--r--test/system/010-images.bats12
-rw-r--r--test/system/070-build.bats35
-rw-r--r--test/system/200-pod.bats15
-rw-r--r--test/system/700-play.bats65
-rw-r--r--test/system/helpers.bash9
-rw-r--r--test/utils/common_function_test.go11
-rw-r--r--test/utils/matchers.go8
-rw-r--r--test/utils/utils.go7
47 files changed, 1081 insertions, 103 deletions
diff --git a/test/apiv2/12-imagesMore.at b/test/apiv2/12-imagesMore.at
index 96eba1db5..67b4f1c79 100644
--- a/test/apiv2/12-imagesMore.at
+++ b/test/apiv2/12-imagesMore.at
@@ -26,7 +26,8 @@ t GET libpod/images/$IMAGE/json 200 \
.RepoTags[1]=localhost:5000/myrepo:mytag
# Run registry container
-podman run -d --name registry -p 5000:5000 quay.io/libpod/registry:2.6 /entrypoint.sh /etc/docker/registry/config.yml
+# FIXME this fails if python tests have been run first...
+podman run -d --name registry -p 5000:5000 quay.io/libpod/registry:2.7 /entrypoint.sh /etc/docker/registry/config.yml
wait_for_port localhost 5000
# Push to local registry and check output
@@ -58,7 +59,7 @@ t DELETE libpod/containers/registry?force=true 200
# Remove images
t DELETE libpod/images/$IMAGE 200 \
.ExitCode=0
-t DELETE libpod/images/quay.io/libpod/registry:2.6 200 \
+t DELETE libpod/images/quay.io/libpod/registry:2.7 200 \
.ExitCode=0
if [ -z "${GOT_DIGEST}" ] ; then
diff --git a/test/apiv2/20-containers.at b/test/apiv2/20-containers.at
index cc5eda88e..94de2cf24 100644
--- a/test/apiv2/20-containers.at
+++ b/test/apiv2/20-containers.at
@@ -280,7 +280,7 @@ t DELETE containers/$cid_top 204
t POST containers/create \
Image=$ENV_WORKDIR_IMG \
WorkingDir=/dataDir \
- StopSignal=9 \
+ StopSignal=\"9\" \
201 \
.Id~[0-9a-f]\\{64\\}
cid=$(jq -r '.Id' <<<"$output")
@@ -394,7 +394,8 @@ t GET containers/$cid/json 200 \
.Config.Healthcheck.Retries=3
# compat api: Test for mount options support
-payload='{"Mounts":[{"Type":"tmpfs","Target":"/mnt/scratch","TmpfsOptions":{"SizeBytes":1024,"Mode":755}}]}'
+# Sigh, JSON can't handle octal. 0755(octal) = 493(decimal)
+payload='{"Mounts":[{"Type":"tmpfs","Target":"/mnt/scratch","TmpfsOptions":{"SizeBytes":1024,"Mode":493}}]}'
t POST containers/create Image=$IMAGE HostConfig="$payload" 201 .Id~[0-9a-f]\\{64\\}
cid=$(jq -r '.Id' <<<"$output")
t GET containers/$cid/json 200 \
diff --git a/test/apiv2/python/conftest.py b/test/apiv2/python/conftest.py
new file mode 100644
index 000000000..54a267049
--- /dev/null
+++ b/test/apiv2/python/conftest.py
@@ -0,0 +1,8 @@
+"""
+Configure pytest
+"""
+
+
+def pytest_report_header(config):
+ """Add header to report."""
+ return "python client -- requests library"
diff --git a/test/apiv2/python/requirements.txt b/test/apiv2/python/requirements.txt
new file mode 100644
index 000000000..d9cfc687a
--- /dev/null
+++ b/test/apiv2/python/requirements.txt
@@ -0,0 +1,5 @@
+requests-mock~=1.9.3
+requests~=2.20.0
+setuptools~=50.3.2
+python-dateutil~=2.8.1
+PyYAML~=5.4.1
diff --git a/test/apiv2/test-apiv2 b/test/apiv2/test-apiv2
index bd728e130..c3545522e 100755
--- a/test/apiv2/test-apiv2
+++ b/test/apiv2/test-apiv2
@@ -194,8 +194,16 @@ function jsonify() {
local rhs
IFS='=' read lhs rhs <<<"$i"
- # If right-hand side already includes double quotes, do nothing
- if [[ ! $rhs =~ \" ]]; then
+ if [[ $rhs =~ \" || $rhs == true || $rhs == false || $rhs =~ ^-?[0-9]+$ ]]; then
+ # rhs has been pre-formatted for JSON or a non-string, do not change it
+ :
+ elif [[ $rhs == False ]]; then
+ # JSON boolean is lowercase only
+ rhs=false
+ elif [[ $rhs == True ]]; then
+ # JSON boolean is lowercase only
+ rhs=true
+ else
rhs="\"${rhs}\""
fi
settings_out+=("\"${lhs}\":${rhs}")
@@ -241,26 +249,30 @@ function t() {
# entrypoint path can include a descriptive comment; strip it off
path=${path%% *}
- # path may include JSONish params that curl will barf on; url-encode them
- path="${path//'['/%5B}"
- path="${path//']'/%5D}"
- path="${path//'{'/%7B}"
- path="${path//'}'/%7D}"
- path="${path//':'/%3A}"
+ local url=$path
+ if ! [[ $path =~ ^'http://' ]]; then
+ # path may include JSONish params that curl will barf on; url-encode them
+ path="${path//'['/%5B}"
+ path="${path//']'/%5D}"
+ path="${path//'{'/%7B}"
+ path="${path//'}'/%7D}"
+ path="${path//':'/%3A}"
+
+ # If given path begins with /, use it as-is; otherwise prepend /version/
+ url=http://$HOST:$PORT
+ case "$path" in
+ /*) url="$url$path" ;;
+ libpod/*) url="$url/v4.0.0/$path" ;;
+ *) url="$url/v1.41/$path" ;;
+ esac
+ fi
# curl -X HEAD but without --head seems to wait for output anyway
if [[ $method == "HEAD" ]]; then
curl_args="--head"
fi
- local expected_code=$1; shift
- # If given path begins with /, use it as-is; otherwise prepend /version/
- local url=http://$HOST:$PORT
- case "$path" in
- /*) url="$url$path" ;;
- libpod/*) url="$url/v4.0.0/$path" ;;
- *) url="$url/v1.41/$path" ;;
- esac
+ local expected_code=$1; shift
# Log every action we do
echo "-------------------------------------------------------------" >>$LOG
@@ -368,7 +380,7 @@ function start_service() {
die "Cannot start service on non-localhost ($HOST)"
fi
- echo $WORKDIR
+ echo "rootdir: "$WORKDIR
# Some tests use shortnames; force registry override to work around
# docker.io throttling.
# FIXME esm revisit pulling expected images re: shortnames caused tests to fail
@@ -376,7 +388,7 @@ function start_service() {
$PODMAN_BIN \
--root $WORKDIR/server_root --syslog=true \
system service \
- --time 15 \
+ --time 0 \
tcp:127.0.0.1:$PORT \
&> $WORKDIR/server.log &
service_pid=$!
@@ -443,7 +455,7 @@ function start_registry() {
-e REGISTRY_HTTP_TLS_KEY=/auth/domain.key \
${REGISTRY_IMAGE}
- wait_for_port localhost $REGISTRY_PORT
+ wait_for_port localhost $REGISTRY_PORT 10
}
function stop_registry() {
@@ -492,13 +504,16 @@ function wait_for_port() {
local port=$2 # Numeric port
local _timeout=${3:-5} # Optional; default to 5 seconds
+ local path=/dev/tcp/$host/$port
+
# Wait
- while [ $_timeout -gt 0 ]; do
+ local i=$_timeout
+ while [ $i -gt 0 ]; do
{ exec 3<> /dev/tcp/$host/$port; } &>/dev/null && return
sleep 1
- _timeout=$(( $_timeout - 1 ))
+ i=$(( $i - 1 ))
done
- die "Timed out waiting for service"
+ die "Timed out (${_timeout}s) waiting for service ($path)"
}
############
@@ -543,6 +558,9 @@ done
###############################################################################
# BEGIN entry handler (subtest invoker)
+echo '============================= test session starts =============================='
+echo "podman client -- $(curl --version)"
+
# Identify the tests to run. If called with args, use those as globs.
tests_to_run=()
if [ -n "$*" ]; then
@@ -558,6 +576,7 @@ if [ -n "$*" ]; then
else
tests_to_run=($TESTS_DIR/*.at)
fi
+echo -e "collected ${#tests_to_run[@]} items\n"
start_service
diff --git a/test/buildah-bud/apply-podman-deltas b/test/buildah-bud/apply-podman-deltas
index dd5331091..26d7fc075 100755
--- a/test/buildah-bud/apply-podman-deltas
+++ b/test/buildah-bud/apply-podman-deltas
@@ -140,6 +140,18 @@ errmsg "no such file or directory" \
skip "N/A under podman" \
"bud-flags-order-verification"
+# TODO
+# Some of the podman tests in CI expects exit code 125, which might not be true
+# since exit code from runtime is relayed as it is without any modification both
+# in `buildah` and `podman`. Following behviour is seen when PR https://github.com/containers/buildah/pull/3809
+# added a test here https://github.com/containers/buildah/blob/main/tests/bud.bats#L3183
+# which relays exit code from runtime as it is, in case of both `podman` and `buildah`.
+# However apart from this test case no other test case was able to trigger this behavior
+# hence marking this test as an anomaly. Since its debatable if we should override this
+# returned error number or not hence adding a note here.
+skip "podman CI expects all exit code to be 125 this test has anomaly behaviour" \
+ "bud with --add-host"
+
skip "does not work under podman" \
"bud without any arguments should succeed"
diff --git a/test/buildah-bud/buildah-tests.diff b/test/buildah-bud/buildah-tests.diff
index b1a19a522..ca38b5a10 100644
--- a/test/buildah-bud/buildah-tests.diff
+++ b/test/buildah-bud/buildah-tests.diff
@@ -1,15 +1,15 @@
-From c18638abfbc1066442cf6ff0b3f012a5c25a918e Mon Sep 17 00:00:00 2001
+From 1a5562929a85074a7498165191558f434bb30bf1 Mon Sep 17 00:00:00 2001
From: Ed Santiago <santiago@redhat.com>
Date: Tue, 9 Feb 2021 17:28:05 -0700
Subject: [PATCH] tweaks for running buildah tests under podman
Signed-off-by: Ed Santiago <santiago@redhat.com>
---
- tests/helpers.bash | 72 +++++++++++++++++++++++++++++++++++++++++++---
- 1 file changed, 68 insertions(+), 4 deletions(-)
+ tests/helpers.bash | 73 +++++++++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 69 insertions(+), 4 deletions(-)
diff --git a/tests/helpers.bash b/tests/helpers.bash
-index bd2794c9..ecf6ed7d 100644
+index 2bb6b429..0dc98a85 100644
--- a/tests/helpers.bash
+++ b/tests/helpers.bash
@@ -43,6 +43,23 @@ EOF
@@ -63,8 +63,8 @@ index bd2794c9..ecf6ed7d 100644
+ ${PODMAN_BINARY} ${ROOTDIR_OPTS} "$@"
}
- #################
-@@ -192,15 +221,41 @@ function run_buildah() {
+ # There are various scenarios where we would like to execute `tests` as rootless user, however certain commands like `buildah mount`
+@@ -221,8 +250,35 @@ function run_buildah() {
--retry) retry=3; shift;; # retry network flakes
esac
@@ -94,11 +94,14 @@ index bd2794c9..ecf6ed7d 100644
+ fi
+ local cmd_basename=$(basename ${podman_or_buildah})
+
++
# Remember command args, for possible use in later diagnostic messages
- MOST_RECENT_BUILDAH_COMMAND="buildah $*"
+ MOST_RECENT_BUILDAH_COMMAND="$cmd_basename $*"
- while [ $retry -gt 0 ]; do
+ # 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.
+@@ -236,8 +292,8 @@ function run_buildah() {
retry=$(( retry - 1 ))
# stdout is only emitted upon error; this echo is to help a debugger
@@ -109,7 +112,7 @@ index bd2794c9..ecf6ed7d 100644
# without "quotes", multiple lines are glommed together into one
if [ -n "$output" ]; then
echo "$output"
-@@ -499,6 +554,15 @@ function skip_if_no_docker() {
+@@ -545,6 +601,15 @@ function skip_if_no_docker() {
fi
}
@@ -126,5 +129,5 @@ index bd2794c9..ecf6ed7d 100644
daemondir=${TESTDIR}/git-daemon
mkdir -p ${daemondir}/repo
--
-2.34.1
+2.31.1
diff --git a/test/checkseccomp/checkseccomp.go b/test/checkseccomp/checkseccomp.go
index 9046e0955..6c188ec0d 100644
--- a/test/checkseccomp/checkseccomp.go
+++ b/test/checkseccomp/checkseccomp.go
@@ -1,3 +1,4 @@
+//go:build seccomp
// +build seccomp
package main
diff --git a/test/compose/ipam_set_ip/tests.sh b/test/compose/ipam_set_ip/tests.sh
index ecaf3167e..b9e761ea2 100644
--- a/test/compose/ipam_set_ip/tests.sh
+++ b/test/compose/ipam_set_ip/tests.sh
@@ -1,4 +1,8 @@
# -*- bash -*-
-podman container inspect ipam_set_ip_test_1 --format '{{ .NetworkSettings.Networks.ipam_set_ip_net1.IPAddress }}'
+ctr_name="ipam_set_ip_test_1"
+if [ "$TEST_FLAVOR" = "compose_v2" ]; then
+ ctr_name="ipam_set_ip-test-1"
+fi
+podman container inspect "$ctr_name" --format '{{ .NetworkSettings.Networks.ipam_set_ip_net1.IPAddress }}'
like "$output" "10.123.0.253" "$testname : ip address is set"
diff --git a/test/compose/slirp4netns_opts/tests.sh b/test/compose/slirp4netns_opts/tests.sh
index 1efce45c4..cfa84e1e4 100644
--- a/test/compose/slirp4netns_opts/tests.sh
+++ b/test/compose/slirp4netns_opts/tests.sh
@@ -3,4 +3,18 @@
output="$(cat $OUTFILE)"
expected="teststring"
+# Reading from the nc socket is flaky because docker-compose only starts
+# the containers. We cannot know at this point if the container did already
+# send the message. Give the container 5 seconds time to send the message
+# to prevent flakes.
+local _timeout=5
+while [ $_timeout -gt 0 ]; do
+ if [ -n "$output" ]; then
+ break
+ fi
+ sleep 1
+ _timeout=$(($_timeout - 1))
+ output="$(cat $OUTFILE)"
+done
+
is "$output" "$expected" "$testname : nc received teststring"
diff --git a/test/compose/two_networks/tests.sh b/test/compose/two_networks/tests.sh
index 1cc88aa5f..af0d1fbe3 100644
--- a/test/compose/two_networks/tests.sh
+++ b/test/compose/two_networks/tests.sh
@@ -1,7 +1,11 @@
# -*- bash -*-
-podman container inspect two_networks_con1_1 --format '{{len .NetworkSettings.Networks}}'
+ctr_name="two_networks_con1_1"
+if [ "$TEST_FLAVOR" = "compose_v2" ]; then
+ ctr_name="two_networks-con1-1"
+fi
+podman container inspect "$ctr_name" --format '{{len .NetworkSettings.Networks}}'
is "$output" "2" "$testname : Container is connected to both networks"
-podman container inspect two_networks_con1_1 --format '{{.NetworkSettings.Networks}}'
+podman container inspect "$ctr_name" --format '{{.NetworkSettings.Networks}}'
like "$output" "two_networks_net1" "$testname : First network name exists"
like "$output" "two_networks_net2" "$testname : Second network name exists"
diff --git a/test/e2e/attach_test.go b/test/e2e/attach_test.go
index a7af76529..74e3a619a 100644
--- a/test/e2e/attach_test.go
+++ b/test/e2e/attach_test.go
@@ -1,7 +1,6 @@
package integration
import (
- "os"
"syscall"
"time"
@@ -20,12 +19,11 @@ var _ = Describe("Podman attach", func() {
BeforeEach(func() {
tempdir, err = CreateTempDirInTempDir()
- if err != nil {
- os.Exit(1)
- }
+ Expect(err).To(BeNil())
podmanTest = PodmanTestCreate(tempdir)
podmanTest.Setup()
- podmanTest.SeedImages()
+ err = podmanTest.SeedImages()
+ Expect(err).To(BeNil())
})
AfterEach(func() {
diff --git a/test/e2e/build/Dockerfile.with-multiple-secret b/test/e2e/build/Containerfile.with-multiple-secret
index f3478914f..f3478914f 100644
--- a/test/e2e/build/Dockerfile.with-multiple-secret
+++ b/test/e2e/build/Containerfile.with-multiple-secret
diff --git a/test/e2e/build/Dockerfile.with-secret b/test/e2e/build/Containerfile.with-secret
index 920663a92..920663a92 100644
--- a/test/e2e/build/Dockerfile.with-secret
+++ b/test/e2e/build/Containerfile.with-secret
diff --git a/test/e2e/build/Dockerfile.test-cp-root-dir b/test/e2e/build/Dockerfile.test-cp-root-dir
deleted file mode 100644
index 9f7de7c32..000000000
--- a/test/e2e/build/Dockerfile.test-cp-root-dir
+++ /dev/null
@@ -1,2 +0,0 @@
-FROM scratch
-COPY Dockerfile.test-cp-root-dir /
diff --git a/test/e2e/build/Dockerfile.with-secret-verify-leak b/test/e2e/build/secret-verify-leak/Containerfile.with-secret-verify-leak
index 0957ac6a6..0957ac6a6 100644
--- a/test/e2e/build/Dockerfile.with-secret-verify-leak
+++ b/test/e2e/build/secret-verify-leak/Containerfile.with-secret-verify-leak
diff --git a/test/e2e/build/workdir-symlink/Dockerfile b/test/e2e/build/workdir-symlink/Dockerfile
new file mode 100644
index 000000000..abc9b47ee
--- /dev/null
+++ b/test/e2e/build/workdir-symlink/Dockerfile
@@ -0,0 +1,5 @@
+FROM alpine
+RUN mkdir /tmp/destination
+RUN ln -s /tmp/destination /tmp/link
+WORKDIR /tmp/link
+CMD ["echo", "hello"]
diff --git a/test/e2e/build_test.go b/test/e2e/build_test.go
index a1c2f5e54..c5903f037 100644
--- a/test/e2e/build_test.go
+++ b/test/e2e/build_test.go
@@ -60,7 +60,7 @@ var _ = Describe("Podman build", func() {
})
It("podman build with a secret from file", func() {
- session := podmanTest.Podman([]string{"build", "-f", "build/Dockerfile.with-secret", "-t", "secret-test", "--secret", "id=mysecret,src=build/secret.txt", "build/"})
+ session := podmanTest.Podman([]string{"build", "-f", "build/Containerfile.with-secret", "-t", "secret-test", "--secret", "id=mysecret,src=build/secret.txt", "build/"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(session.OutputToString()).To(ContainSubstring("somesecret"))
@@ -71,7 +71,7 @@ var _ = Describe("Podman build", func() {
})
It("podman build with multiple secrets from files", func() {
- session := podmanTest.Podman([]string{"build", "-f", "build/Dockerfile.with-multiple-secret", "-t", "multiple-secret-test", "--secret", "id=mysecret,src=build/secret.txt", "--secret", "id=mysecret2,src=build/anothersecret.txt", "build/"})
+ session := podmanTest.Podman([]string{"build", "-f", "build/Containerfile.with-multiple-secret", "-t", "multiple-secret-test", "--secret", "id=mysecret,src=build/secret.txt", "--secret", "id=mysecret2,src=build/anothersecret.txt", "build/"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(session.OutputToString()).To(ContainSubstring("somesecret"))
@@ -83,7 +83,7 @@ var _ = Describe("Podman build", func() {
})
It("podman build with a secret from file and verify if secret file is not leaked into image", func() {
- session := podmanTest.Podman([]string{"build", "-f", "build/Dockerfile.with-secret-verify-leak", "-t", "secret-test-leak", "--secret", "id=mysecret,src=build/secret.txt", "build/"})
+ session := podmanTest.Podman([]string{"build", "-f", "build/secret-verify-leak/Containerfile.with-secret-verify-leak", "-t", "secret-test-leak", "--secret", "id=mysecret,src=build/secret.txt", "build/"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(session.OutputToString()).To(ContainSubstring("somesecret"))
@@ -259,6 +259,19 @@ var _ = Describe("Podman build", func() {
Expect(session.OutputToString()).NotTo(ContainSubstring("io.podman.annotations.seccomp"))
})
+ It("podman build where workdir is a symlink and run without creating new workdir", func() {
+ session := podmanTest.Podman([]string{
+ "build", "-f", "build/workdir-symlink/Dockerfile", "-t", "test-symlink",
+ })
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ session = podmanTest.Podman([]string{"run", "--workdir", "/tmp/link", "test-symlink"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).To(ContainSubstring("hello"))
+ })
+
It("podman build --http_proxy flag", func() {
os.Setenv("http_proxy", "1.2.3.4")
if IsRemote() {
diff --git a/test/e2e/checkpoint_test.go b/test/e2e/checkpoint_test.go
index 5abc672e9..7b2dd89c9 100644
--- a/test/e2e/checkpoint_test.go
+++ b/test/e2e/checkpoint_test.go
@@ -37,12 +37,12 @@ var _ = Describe("Podman checkpoint", func() {
BeforeEach(func() {
SkipIfRootless("checkpoint not supported in rootless mode")
tempdir, err = CreateTempDirInTempDir()
- if err != nil {
- os.Exit(1)
- }
+ Expect(err).To(BeNil())
+
podmanTest = PodmanTestCreate(tempdir)
podmanTest.Setup()
- podmanTest.SeedImages()
+ err = podmanTest.SeedImages()
+ Expect(err).To(BeNil())
// Check if the runtime implements checkpointing. Currently only
// runc's checkpoint/restore implementation is supported.
cmd := exec.Command(podmanTest.OCIRuntime, "checkpoint", "--help")
diff --git a/test/e2e/commit_test.go b/test/e2e/commit_test.go
index 6bcf17bfe..78b607f1e 100644
--- a/test/e2e/commit_test.go
+++ b/test/e2e/commit_test.go
@@ -21,12 +21,11 @@ var _ = Describe("Podman commit", func() {
BeforeEach(func() {
tempdir, err = CreateTempDirInTempDir()
- if err != nil {
- os.Exit(1)
- }
+ Expect(err).To(BeNil())
podmanTest = PodmanTestCreate(tempdir)
podmanTest.Setup()
- podmanTest.SeedImages()
+ err = podmanTest.SeedImages()
+ Expect(err).To(BeNil())
})
AfterEach(func() {
diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go
index b1cd76d27..cb6574f23 100644
--- a/test/e2e/common_test.go
+++ b/test/e2e/common_test.go
@@ -809,7 +809,8 @@ func (p *PodmanTestIntegration) RestoreArtifactToCache(image string) error {
func populateCache(podman *PodmanTestIntegration) {
for _, image := range CACHE_IMAGES {
- podman.RestoreArtifactToCache(image)
+ err := podman.RestoreArtifactToCache(image)
+ Expect(err).To(BeNil())
}
// logformatter uses this to recognize the first test
fmt.Printf("-----------------------------\n")
@@ -896,7 +897,7 @@ func removeConf(confPath string) {
}
}
-// generateNetworkConfig generates a cni config with a random name
+// generateNetworkConfig generates a CNI or Netavark config with a random name
// it returns the network name and the filepath
func generateNetworkConfig(p *PodmanTestIntegration) (string, string) {
var (
@@ -1042,3 +1043,27 @@ func ncz(port int) bool {
func createNetworkName(name string) string {
return name + stringid.GenerateNonCryptoID()[: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}`
+
+// digShort execs into the given container and does a dig lookup with a timeout
+// backoff. If it gets a response, it ensures that the output is in the correct
+// format and iterates a string array for match
+func digShort(container, lookupName string, matchNames []string, p *PodmanTestIntegration) string {
+ digInterval := time.Millisecond * 250
+ for i := 0; i < 6; i++ {
+ time.Sleep(digInterval * time.Duration(i))
+ dig := p.Podman([]string{"exec", container, "dig", "+short", lookupName})
+ dig.WaitWithDefaultTimeout()
+ if dig.ExitCode() == 0 {
+ output := dig.OutputToString()
+ Expect(output).To(MatchRegexp(IPRegex))
+ for _, name := range matchNames {
+ Expect(output).To(Equal(name))
+ }
+ return output
+ }
+ }
+ Fail("dns is not responding")
+ return ""
+}
diff --git a/test/e2e/containers_conf_test.go b/test/e2e/containers_conf_test.go
index bfed01854..09cd68042 100644
--- a/test/e2e/containers_conf_test.go
+++ b/test/e2e/containers_conf_test.go
@@ -562,6 +562,11 @@ var _ = Describe("Verify podman containers.conf usage", func() {
inspect = podmanTest.Podman([]string{"inspect", "--format", "{{ .HostConfig.Cgroups }}", result.OutputToString()})
inspect.WaitWithDefaultTimeout()
Expect(inspect.OutputToString()).To(Equal("disabled"))
+
+ // Check we can also create a pod when cgroups=disabled
+ result = podmanTest.Podman([]string{"pod", "create"})
+ result.WaitWithDefaultTimeout()
+ Expect(result).Should(Exit(0))
})
It("podman containers.conf runtime", func() {
diff --git a/test/e2e/create_test.go b/test/e2e/create_test.go
index 6a4a394ef..4c3b5604a 100644
--- a/test/e2e/create_test.go
+++ b/test/e2e/create_test.go
@@ -24,12 +24,11 @@ var _ = Describe("Podman create", func() {
BeforeEach(func() {
tempdir, err = CreateTempDirInTempDir()
- if err != nil {
- os.Exit(1)
- }
+ Expect(err).To(BeNil())
podmanTest = PodmanTestCreate(tempdir)
podmanTest.Setup()
- podmanTest.SeedImages()
+ err = podmanTest.SeedImages()
+ Expect(err).To(BeNil())
})
AfterEach(func() {
@@ -706,4 +705,34 @@ var _ = Describe("Podman create", func() {
Expect(create.ErrorToString()).To(ContainSubstring("cannot specify a new uid/gid map when entering a pod with an infra container"))
})
+
+ It("podman create --chrootdirs inspection test", func() {
+ session := podmanTest.Podman([]string{"create", "--chrootdirs", "/var/local/qwerty", ALPINE})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ setup := podmanTest.Podman([]string{"container", "inspect", session.OutputToString()})
+ setup.WaitWithDefaultTimeout()
+ Expect(setup).Should(Exit(0))
+
+ data := setup.InspectContainerToJSON()
+ Expect(data).To(HaveLen(1))
+ Expect(data[0].Config.ChrootDirs).To(HaveLen(1))
+ Expect(data[0].Config.ChrootDirs[0]).To(Equal("/var/local/qwerty"))
+ })
+
+ It("podman create --chrootdirs functionality test", func() {
+ session := podmanTest.Podman([]string{"create", "-t", "--chrootdirs", "/var/local/qwerty", ALPINE, "/bin/cat"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ ctrID := session.OutputToString()
+
+ setup := podmanTest.Podman([]string{"start", ctrID})
+ setup.WaitWithDefaultTimeout()
+ Expect(setup).Should(Exit(0))
+
+ setup = podmanTest.Podman([]string{"exec", ctrID, "cmp", "/etc/resolv.conf", "/var/local/qwerty/etc/resolv.conf"})
+ setup.WaitWithDefaultTimeout()
+ Expect(setup).Should(Exit(0))
+ })
})
diff --git a/test/e2e/generate_kube_test.go b/test/e2e/generate_kube_test.go
index 53829e89b..44c906eed 100644
--- a/test/e2e/generate_kube_test.go
+++ b/test/e2e/generate_kube_test.go
@@ -9,13 +9,13 @@ import (
"github.com/containers/podman/v4/libpod/define"
+ v1 "github.com/containers/podman/v4/pkg/k8s.io/api/core/v1"
"github.com/containers/podman/v4/pkg/util"
. "github.com/containers/podman/v4/test/utils"
"github.com/ghodss/yaml"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/gexec"
- v1 "k8s.io/api/core/v1"
)
var _ = Describe("Podman generate kube", func() {
@@ -1018,7 +1018,7 @@ USER test1`
pvc := new(v1.PersistentVolumeClaim)
err := yaml.Unmarshal(kube.Out.Contents(), pvc)
Expect(err).To(BeNil())
- Expect(pvc.GetName()).To(Equal(vol))
+ Expect(pvc.Name).To(Equal(vol))
Expect(pvc.Spec.AccessModes[0]).To(Equal(v1.ReadWriteOnce))
Expect(pvc.Spec.Resources.Requests.Storage().String()).To(Equal("1Gi"))
})
@@ -1040,11 +1040,11 @@ USER test1`
pvc := new(v1.PersistentVolumeClaim)
err := yaml.Unmarshal(kube.Out.Contents(), pvc)
Expect(err).To(BeNil())
- Expect(pvc.GetName()).To(Equal(vol))
+ Expect(pvc.Name).To(Equal(vol))
Expect(pvc.Spec.AccessModes[0]).To(Equal(v1.ReadWriteOnce))
Expect(pvc.Spec.Resources.Requests.Storage().String()).To(Equal("1Gi"))
- for k, v := range pvc.GetAnnotations() {
+ for k, v := range pvc.Annotations {
switch k {
case util.VolumeDeviceAnnotation:
Expect(v).To(Equal(volDevice))
@@ -1069,7 +1069,7 @@ USER test1`
err := yaml.Unmarshal(kube.Out.Contents(), pod)
Expect(err).To(BeNil())
- Expect(pod.GetAnnotations()).To(HaveKeyWithValue("io.containers.autoupdate/top", "local"))
+ Expect(pod.Annotations).To(HaveKeyWithValue("io.containers.autoupdate/top", "local"))
})
It("podman generate kube on pod with auto update labels in all containers", func() {
@@ -1096,8 +1096,8 @@ USER test1`
Expect(pod.Spec.Containers[1].WorkingDir).To(Equal("/root"))
for _, ctr := range []string{"top1", "top2"} {
- Expect(pod.GetAnnotations()).To(HaveKeyWithValue("io.containers.autoupdate/"+ctr, "registry"))
- Expect(pod.GetAnnotations()).To(HaveKeyWithValue("io.containers.autoupdate.authfile/"+ctr, "/some/authfile.json"))
+ Expect(pod.Annotations).To(HaveKeyWithValue("io.containers.autoupdate/"+ctr, "registry"))
+ Expect(pod.Annotations).To(HaveKeyWithValue("io.containers.autoupdate.authfile/"+ctr, "/some/authfile.json"))
}
})
diff --git a/test/e2e/generate_systemd_test.go b/test/e2e/generate_systemd_test.go
index 55b9a8037..e4b854332 100644
--- a/test/e2e/generate_systemd_test.go
+++ b/test/e2e/generate_systemd_test.go
@@ -423,6 +423,20 @@ var _ = Describe("Podman generate systemd", func() {
})
+ It("podman generate systemd --container-prefix ''", func() {
+ n := podmanTest.Podman([]string{"create", "--name", "foo", "alpine", "top"})
+ n.WaitWithDefaultTimeout()
+ Expect(n).Should(Exit(0))
+
+ session := podmanTest.Podman([]string{"generate", "systemd", "--name", "--container-prefix", "", "foo"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ // Grepping the output (in addition to unit tests)
+ Expect(session.OutputToString()).To(ContainSubstring("# foo.service"))
+
+ })
+
It("podman generate systemd --separator _", func() {
n := podmanTest.Podman([]string{"create", "--name", "foo", "alpine", "top"})
n.WaitWithDefaultTimeout()
@@ -485,6 +499,44 @@ var _ = Describe("Podman generate systemd", func() {
Expect(session.OutputToString()).To(ContainSubstring("BindsTo=p_foo.service"))
})
+ It("podman generate systemd pod --pod-prefix '' --container-prefix '' --separator _ change all prefixes/separator", func() {
+ n := podmanTest.Podman([]string{"pod", "create", "--name", "foo"})
+ n.WaitWithDefaultTimeout()
+ Expect(n).Should(Exit(0))
+
+ n = podmanTest.Podman([]string{"create", "--pod", "foo", "--name", "foo-1", "alpine", "top"})
+ n.WaitWithDefaultTimeout()
+ Expect(n).Should(Exit(0))
+
+ n = podmanTest.Podman([]string{"create", "--pod", "foo", "--name", "foo-2", "alpine", "top"})
+ n.WaitWithDefaultTimeout()
+ Expect(n).Should(Exit(0))
+
+ // test systemd generate with empty pod prefix
+ session1 := podmanTest.Podman([]string{"generate", "systemd", "--pod-prefix", "", "--name", "foo"})
+ session1.WaitWithDefaultTimeout()
+ Expect(session1).Should(Exit(0))
+
+ // 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("# container-foo-1.service"))
+ Expect(session1.OutputToString()).To(ContainSubstring("BindsTo=foo.service"))
+
+ // test systemd generate with empty container and pod prefix
+ session2 := podmanTest.Podman([]string{"generate", "systemd", "--container-prefix", "", "--pod-prefix", "", "--separator", "_", "--name", "foo"})
+ session2.WaitWithDefaultTimeout()
+ Expect(session2).Should(Exit(0))
+
+ // 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("# foo-1.service"))
+ Expect(session2.OutputToString()).To(ContainSubstring("# foo-2.service"))
+ Expect(session2.OutputToString()).To(ContainSubstring("BindsTo=foo.service"))
+
+ })
+
It("podman generate systemd pod with containers --new", func() {
tmpDir, err := ioutil.TempDir("", "")
Expect(err).To(BeNil())
diff --git a/test/e2e/healthcheck_run_test.go b/test/e2e/healthcheck_run_test.go
index 866edbf0e..757eaed20 100644
--- a/test/e2e/healthcheck_run_test.go
+++ b/test/e2e/healthcheck_run_test.go
@@ -54,6 +54,16 @@ var _ = Describe("Podman healthcheck run", func() {
Expect(hc).Should(Exit(125))
})
+ It("podman disable healthcheck with --no-healthcheck must not show starting on status", func() {
+ session := podmanTest.Podman([]string{"run", "-dt", "--no-healthcheck", "--name", "hc", healthcheck})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ hc := podmanTest.Podman([]string{"container", "inspect", "--format", "{{.State.Health.Status}}", "hc"})
+ hc.WaitWithDefaultTimeout()
+ Expect(hc).Should(Exit(0))
+ Expect(hc.OutputToString()).To(Not(ContainSubstring("starting")))
+ })
+
It("podman run healthcheck and logs should contain healthcheck output", func() {
session := podmanTest.Podman([]string{"run", "--name", "test-logs", "-dt", "--health-interval", "1s", "--health-cmd", "echo working", "busybox", "sleep", "3600"})
session.WaitWithDefaultTimeout()
diff --git a/test/e2e/inspect_test.go b/test/e2e/inspect_test.go
index 3943a5e87..bb5a3a6ad 100644
--- a/test/e2e/inspect_test.go
+++ b/test/e2e/inspect_test.go
@@ -86,6 +86,7 @@ var _ = Describe("Podman inspect", func() {
It("podman inspect container with GO format for ConmonPidFile", func() {
session, ec, _ := podmanTest.RunLsContainer("test1")
+ session.WaitWithDefaultTimeout()
Expect(ec).To(Equal(0))
session = podmanTest.Podman([]string{"inspect", "--format", "{{.ConmonPidFile}}", "test1"})
@@ -94,7 +95,8 @@ var _ = Describe("Podman inspect", func() {
})
It("podman inspect container with size", func() {
- _, ec, _ := podmanTest.RunLsContainer("sizetest")
+ session, ec, _ := podmanTest.RunLsContainer("sizetest")
+ session.WaitWithDefaultTimeout()
Expect(ec).To(Equal(0))
result := podmanTest.Podman([]string{"inspect", "--size", "sizetest"})
@@ -107,6 +109,7 @@ var _ = Describe("Podman inspect", func() {
It("podman inspect container and image", func() {
ls, ec, _ := podmanTest.RunLsContainer("")
+ ls.WaitWithDefaultTimeout()
Expect(ec).To(Equal(0))
cid := ls.OutputToString()
@@ -118,6 +121,7 @@ var _ = Describe("Podman inspect", func() {
It("podman inspect container and filter for Image{ID}", func() {
ls, ec, _ := podmanTest.RunLsContainer("")
+ ls.WaitWithDefaultTimeout()
Expect(ec).To(Equal(0))
cid := ls.OutputToString()
@@ -134,6 +138,7 @@ var _ = Describe("Podman inspect", func() {
It("podman inspect container and filter for CreateCommand", func() {
ls, ec, _ := podmanTest.RunLsContainer("")
+ ls.WaitWithDefaultTimeout()
Expect(ec).To(Equal(0))
cid := ls.OutputToString()
@@ -529,6 +534,7 @@ var _ = Describe("Podman inspect", func() {
It("podman inspect container with GO format for PidFile", func() {
SkipIfRemote("pidfile not handled by remote")
session, ec, _ := podmanTest.RunLsContainer("test1")
+ session.WaitWithDefaultTimeout()
Expect(ec).To(Equal(0))
session = podmanTest.Podman([]string{"inspect", "--format", "{{.PidFile}}", "test1"})
diff --git a/test/e2e/libpod_suite_test.go b/test/e2e/libpod_suite_test.go
index ccd7c771e..cf81a0348 100644
--- a/test/e2e/libpod_suite_test.go
+++ b/test/e2e/libpod_suite_test.go
@@ -1,3 +1,4 @@
+//go:build !remote
// +build !remote
package integration
diff --git a/test/e2e/login_logout_test.go b/test/e2e/login_logout_test.go
index 1280b3e83..77549a9a8 100644
--- a/test/e2e/login_logout_test.go
+++ b/test/e2e/login_logout_test.go
@@ -417,12 +417,12 @@ var _ = Describe("Podman login and logout", func() {
Expect(authInfo).NotTo(HaveKey(testRepos[1]))
})
- It("podman login with repository invalid arguments", func() {
+ It("podman login with http{s} prefix", func() {
authFile := filepath.Join(podmanTest.TempDir, "auth.json")
for _, invalidArg := range []string{
"https://" + server + "/podmantest",
- server + "/podmantest/image:latest",
+ "http://" + server + "/podmantest/image:latest",
} {
session := podmanTest.Podman([]string{
"login",
@@ -432,7 +432,7 @@ var _ = Describe("Podman login and logout", func() {
invalidArg,
})
session.WaitWithDefaultTimeout()
- Expect(session).Should(ExitWithError())
+ Expect(session).To(Exit(0))
}
})
diff --git a/test/e2e/network_create_test.go b/test/e2e/network_create_test.go
index 395759ee6..82b99bd68 100644
--- a/test/e2e/network_create_test.go
+++ b/test/e2e/network_create_test.go
@@ -416,8 +416,8 @@ var _ = Describe("Podman network create", func() {
subnet1 := "10.10.3.0/24"
gw1 := "10.10.3.10"
range1 := "10.10.3.0/26"
- subnet2 := "fd52:2a5a:747e:3acd::/64"
- gw2 := "fd52:2a5a:747e:3acd::10"
+ subnet2 := "fd52:2a5a:747e:3ace::/64"
+ gw2 := "fd52:2a5a:747e:3ace::10"
nc := podmanTest.Podman([]string{"network", "create", "--subnet", subnet1, "--gateway", gw1, "--ip-range", range1, "--subnet", subnet2, "--gateway", gw2, name})
nc.WaitWithDefaultTimeout()
defer podmanTest.removeNetwork(name)
@@ -440,7 +440,7 @@ var _ = Describe("Podman network create", func() {
name := "subnets-" + stringid.GenerateNonCryptoID()
subnet1 := "10.10.3.0/24"
gw1 := "10.10.3.10"
- gw2 := "fd52:2a5a:747e:3acd::10"
+ gw2 := "fd52:2a5a:747e:3acf::10"
nc := podmanTest.Podman([]string{"network", "create", "--subnet", subnet1, "--gateway", gw1, "--gateway", gw2, name})
nc.WaitWithDefaultTimeout()
Expect(nc).To(Exit(125))
diff --git a/test/e2e/play_build_test.go b/test/e2e/play_build_test.go
index 849ba7162..96785c569 100644
--- a/test/e2e/play_build_test.go
+++ b/test/e2e/play_build_test.go
@@ -1,3 +1,4 @@
+//go:build !remote
// +build !remote
// build for play kube is not supported on remote yet.
diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go
index c0c71652e..6a4083565 100644
--- a/test/e2e/play_kube_test.go
+++ b/test/e2e/play_kube_test.go
@@ -38,6 +38,21 @@ spec:
hostname: unknown
`
+var workdirSymlinkPodYaml = `
+apiVersion: v1
+kind: Pod
+metadata:
+ labels:
+ app: test-symlink
+ name: test-symlink
+spec:
+ containers:
+ - image: test-symlink
+ name: test-symlink
+ resources: {}
+ restartPolicy: Never
+`
+
var podnameEqualsContainerNameYaml = `
apiVersion: v1
kind: Pod
@@ -1332,6 +1347,26 @@ var _ = Describe("Podman play kube", func() {
Expect(sharednamespaces).To(ContainSubstring("pid"))
})
+ It("podman play kube should be able to run image where workdir is a symlink", func() {
+ session := podmanTest.Podman([]string{
+ "build", "-f", "build/workdir-symlink/Dockerfile", "-t", "test-symlink",
+ })
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ err := writeYaml(workdirSymlinkPodYaml, kubeYaml)
+ Expect(err).To(BeNil())
+
+ kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube).Should(Exit(0))
+
+ logs := podmanTest.Podman([]string{"pod", "logs", "-c", "test-symlink-test-symlink", "test-symlink"})
+ logs.WaitWithDefaultTimeout()
+ Expect(logs).Should(Exit(0))
+ Expect(logs.OutputToString()).To(ContainSubstring("hello"))
+ })
+
It("podman play kube should not rename pod if container in pod has same name", func() {
err := writeYaml(podnameEqualsContainerNameYaml, kubeYaml)
Expect(err).To(BeNil())
@@ -1853,6 +1888,26 @@ var _ = Describe("Podman play kube", func() {
Expect(kube).Should(Exit(0))
})
+ It("podman play kube test duplicate container name", func() {
+ p := getPod(withCtr(getCtr(withName("testctr"), withCmd([]string{"echo", "hello"}))), withCtr(getCtr(withName("testctr"), withCmd([]string{"echo", "world"}))))
+
+ err := generateKubeYaml("pod", p, kubeYaml)
+ Expect(err).To(BeNil())
+
+ kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube).To(ExitWithError())
+
+ p = getPod(withPodInitCtr(getCtr(withImage(ALPINE), withCmd([]string{"echo", "hello"}), withInitCtr(), withName("initctr"))), withCtr(getCtr(withImage(ALPINE), withName("initctr"), withCmd([]string{"top"}))))
+
+ err = generateKubeYaml("pod", p, kubeYaml)
+ Expect(err).To(BeNil())
+
+ kube = podmanTest.Podman([]string{"play", "kube", kubeYaml})
+ kube.WaitWithDefaultTimeout()
+ Expect(kube).To(ExitWithError())
+ })
+
It("podman play kube test hostname", func() {
pod := getPod()
err := generateKubeYaml("pod", pod, kubeYaml)
diff --git a/test/e2e/run_aardvark_test.go b/test/e2e/run_aardvark_test.go
new file mode 100644
index 000000000..c82f614a6
--- /dev/null
+++ b/test/e2e/run_aardvark_test.go
@@ -0,0 +1,314 @@
+package integration
+
+import (
+ "fmt"
+ "os"
+ "strings"
+
+ . "github.com/containers/podman/v4/test/utils"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+ . "github.com/onsi/gomega/gexec"
+)
+
+var _ = Describe("Podman run networking", func() {
+ var (
+ tempdir string
+ err error
+ podmanTest *PodmanTestIntegration
+ )
+
+ BeforeEach(func() {
+ tempdir, err = CreateTempDirInTempDir()
+ if err != nil {
+ os.Exit(1)
+ }
+ podmanTest = PodmanTestCreate(tempdir)
+ podmanTest.Setup()
+ podmanTest.SeedImages()
+ SkipIfCNI(podmanTest)
+ })
+
+ AfterEach(func() {
+ podmanTest.Cleanup()
+ f := CurrentGinkgoTestDescription()
+ processTestResult(f)
+
+ })
+
+ It("Aardvark Test 1: One container", func() {
+ netName := createNetworkName("Test")
+ session := podmanTest.Podman([]string{"network", "create", netName})
+ session.WaitWithDefaultTimeout()
+ defer podmanTest.removeNetwork(netName)
+ Expect(session).Should(Exit(0))
+
+ ctrID := podmanTest.Podman([]string{"run", "-dt", "--name", "aone", "--network", netName, nginx})
+ ctrID.WaitWithDefaultTimeout()
+ Expect(ctrID).Should(Exit(0))
+ cid := ctrID.OutputToString()
+
+ ctrIP := podmanTest.Podman([]string{"inspect", "--format", fmt.Sprintf(`{{.NetworkSettings.Networks.%s.IPAddress}}`, netName), cid})
+ ctrIP.WaitWithDefaultTimeout()
+ Expect(ctrIP).Should(Exit(0))
+ cip := ctrIP.OutputToString()
+ Expect(cip).To(MatchRegexp(IPRegex))
+
+ _ = digShort(cid, "aone", []string{cip}, podmanTest)
+
+ reverseLookup := podmanTest.Podman([]string{"exec", cid, "dig", "+short", "-x", cip})
+ reverseLookup.WaitWithDefaultTimeout()
+ Expect(reverseLookup).Should(Exit(0))
+ revListArray := reverseLookup.OutputToStringArray()
+ Expect(revListArray).Should(HaveLen(2))
+ Expect(strings.TrimRight(revListArray[0], ".")).To(Equal("aone"))
+ Expect(strings.TrimRight(revListArray[1], ".")).To(Equal(cid[:12]))
+
+ })
+
+ It("Aardvark Test 2: Two containers, same subnet", func() {
+ netName := createNetworkName("Test")
+ session := podmanTest.Podman([]string{"network", "create", netName})
+ session.WaitWithDefaultTimeout()
+ defer podmanTest.removeNetwork(netName)
+ Expect(session).Should(Exit(0))
+
+ ctr1 := podmanTest.Podman([]string{"run", "-dt", "--name", "aone", "--network", netName, nginx})
+ ctr1.WaitWithDefaultTimeout()
+ Expect(ctr1).Should(Exit(0))
+ cid1 := ctr1.OutputToString()
+
+ ctrIP1 := podmanTest.Podman([]string{"inspect", "--format", fmt.Sprintf(`{{.NetworkSettings.Networks.%s.IPAddress}}`, netName), cid1})
+ ctrIP1.WaitWithDefaultTimeout()
+ Expect(ctrIP1).Should(Exit(0))
+ cip1 := ctrIP1.OutputToString()
+ Expect(cip1).To(MatchRegexp(IPRegex))
+
+ ctr2 := podmanTest.Podman([]string{"run", "-dt", "--name", "atwo", "--network", netName, nginx})
+ ctr2.WaitWithDefaultTimeout()
+ Expect(ctr2).Should(Exit(0))
+ cid2 := ctr2.OutputToString()
+
+ ctrIP2 := podmanTest.Podman([]string{"inspect", "--format", fmt.Sprintf(`{{.NetworkSettings.Networks.%s.IPAddress}}`, netName), cid2})
+ ctrIP2.WaitWithDefaultTimeout()
+ Expect(ctrIP2).Should(Exit(0))
+ cip2 := ctrIP2.OutputToString()
+ Expect(cip2).To(MatchRegexp(IPRegex))
+
+ _ = digShort("aone", "atwo", []string{cip2}, podmanTest)
+
+ _ = digShort("atwo", "aone", []string{cip1}, podmanTest)
+
+ reverseLookup12 := podmanTest.Podman([]string{"exec", cid1, "dig", "+short", "-x", cip2})
+ reverseLookup12.WaitWithDefaultTimeout()
+ Expect(reverseLookup12).Should(Exit(0))
+ revListArray12 := reverseLookup12.OutputToStringArray()
+ Expect(revListArray12).Should(HaveLen(2))
+ Expect(strings.TrimRight(revListArray12[0], ".")).To(Equal("atwo"))
+ Expect(strings.TrimRight(revListArray12[1], ".")).To(Equal(cid2[:12]))
+
+ reverseLookup21 := podmanTest.Podman([]string{"exec", cid2, "dig", "+short", "-x", cip1})
+ reverseLookup21.WaitWithDefaultTimeout()
+ Expect(reverseLookup21).Should(Exit(0))
+ revListArray21 := reverseLookup21.OutputToStringArray()
+ Expect(revListArray21).Should(HaveLen(2))
+ Expect(strings.TrimRight(revListArray21[0], ".")).To(Equal("aone"))
+ Expect(strings.TrimRight(revListArray21[1], ".")).To(Equal(cid1[:12]))
+
+ })
+
+ It("Aardvark Test 3: Two containers, same subnet w/aliases", func() {
+ netName := createNetworkName("Test")
+ session := podmanTest.Podman([]string{"network", "create", netName})
+ session.WaitWithDefaultTimeout()
+ defer podmanTest.removeNetwork(netName)
+ Expect(session).Should(Exit(0))
+
+ ctr1 := podmanTest.Podman([]string{"run", "-dt", "--name", "aone", "--network", netName, "--network-alias", "alias_a1,alias_1a", nginx})
+ ctr1.WaitWithDefaultTimeout()
+ Expect(ctr1).Should(Exit(0))
+
+ ctrIP1 := podmanTest.Podman([]string{"inspect", "--format", fmt.Sprintf(`{{.NetworkSettings.Networks.%s.IPAddress}}`, netName), "aone"})
+ ctrIP1.WaitWithDefaultTimeout()
+ Expect(ctrIP1).Should(Exit(0))
+ cip1 := ctrIP1.OutputToString()
+ Expect(cip1).To(MatchRegexp(IPRegex))
+
+ ctr2 := podmanTest.Podman([]string{"run", "-dt", "--name", "atwo", "--network", netName, "--network-alias", "alias_a2,alias_2a", nginx})
+ ctr2.WaitWithDefaultTimeout()
+ Expect(ctr2).Should(Exit(0))
+
+ ctrIP2 := podmanTest.Podman([]string{"inspect", "--format", fmt.Sprintf(`{{.NetworkSettings.Networks.%s.IPAddress}}`, netName), "atwo"})
+ ctrIP2.WaitWithDefaultTimeout()
+ Expect(ctrIP2).Should(Exit(0))
+ cip2 := ctrIP2.OutputToString()
+ Expect(cip2).To(MatchRegexp(IPRegex))
+
+ _ = digShort("aone", "atwo", []string{cip2}, podmanTest)
+
+ _ = digShort("aone", "alias_a2", []string{cip2}, podmanTest)
+
+ _ = digShort("aone", "alias_2a", []string{cip2}, podmanTest)
+
+ _ = digShort("atwo", "aone", []string{cip1}, podmanTest)
+
+ _ = digShort("atwo", "alias_a1", []string{cip1}, podmanTest)
+
+ _ = digShort("atwo", "alias_1a", []string{cip1}, podmanTest)
+
+ })
+
+ It("Aardvark Test 4: Two containers, different subnets", func() {
+ netNameA := createNetworkName("TestA")
+ sessionA := podmanTest.Podman([]string{"network", "create", netNameA})
+ sessionA.WaitWithDefaultTimeout()
+ defer podmanTest.removeNetwork(netNameA)
+ Expect(sessionA).Should(Exit(0))
+
+ netNameB := createNetworkName("TestB")
+ sessionB := podmanTest.Podman([]string{"network", "create", netNameB})
+ sessionB.WaitWithDefaultTimeout()
+ defer podmanTest.removeNetwork(netNameB)
+ Expect(sessionB).Should(Exit(0))
+
+ ctrA1 := podmanTest.Podman([]string{"run", "-dt", "--name", "aone", "--network", netNameA, nginx})
+ ctrA1.WaitWithDefaultTimeout()
+ cidA1 := ctrA1.OutputToString()
+
+ ctrB1 := podmanTest.Podman([]string{"run", "-dt", "--name", "bone", "--network", netNameB, nginx})
+ ctrB1.WaitWithDefaultTimeout()
+ cidB1 := ctrB1.OutputToString()
+
+ ctrIPA1 := podmanTest.Podman([]string{"inspect", "--format", fmt.Sprintf(`{{.NetworkSettings.Networks.%s.IPAddress}}`, netNameA), cidA1})
+ ctrIPA1.WaitWithDefaultTimeout()
+ Expect(ctrIPA1).Should(Exit(0))
+ cipA1 := ctrIPA1.OutputToString()
+ Expect(cipA1).To(MatchRegexp(IPRegex))
+
+ ctrIPB1 := podmanTest.Podman([]string{"inspect", "--format", fmt.Sprintf(`{{.NetworkSettings.Networks.%s.IPAddress}}`, netNameB), cidB1})
+ ctrIPB1.WaitWithDefaultTimeout()
+ Expect(ctrIPB1).Should(Exit(0))
+ cipB1 := ctrIPB1.OutputToString()
+ Expect(cipB1).To(MatchRegexp(IPRegex))
+
+ resA1B1 := podmanTest.Podman([]string{"exec", "aone", "dig", "+short", "bone"})
+ resA1B1.WaitWithDefaultTimeout()
+ Expect(resA1B1).Should(Exit(0))
+ Expect(resA1B1.OutputToString()).To(Equal(""))
+
+ resB1A1 := podmanTest.Podman([]string{"exec", "bone", "dig", "+short", "aone"})
+ resB1A1.WaitWithDefaultTimeout()
+ Expect(resB1A1).Should(Exit(0))
+ Expect(resB1A1.OutputToString()).To(Equal(""))
+ })
+
+ It("Aardvark Test 5: Two containers on their own subnets, one container on both", func() {
+ netNameA := createNetworkName("TestA")
+ sessionA := podmanTest.Podman([]string{"network", "create", netNameA})
+ sessionA.WaitWithDefaultTimeout()
+ defer podmanTest.removeNetwork(netNameA)
+ Expect(sessionA).Should(Exit(0))
+
+ netNameB := createNetworkName("TestB")
+ sessionB := podmanTest.Podman([]string{"network", "create", netNameB})
+ sessionB.WaitWithDefaultTimeout()
+ defer podmanTest.removeNetwork(netNameB)
+ Expect(sessionB).Should(Exit(0))
+
+ ctrA1 := podmanTest.Podman([]string{"run", "-dt", "--name", "aone", "--network", netNameA, nginx})
+ ctrA1.WaitWithDefaultTimeout()
+ cidA1 := ctrA1.OutputToString()
+
+ ctrIPA1 := podmanTest.Podman([]string{"inspect", "--format", fmt.Sprintf(`{{.NetworkSettings.Networks.%s.IPAddress}}`, netNameA), cidA1})
+ ctrIPA1.WaitWithDefaultTimeout()
+ Expect(ctrIPA1).Should(Exit(0))
+ cipA1 := ctrIPA1.OutputToString()
+ Expect(cipA1).To(MatchRegexp(IPRegex))
+
+ ctrB1 := podmanTest.Podman([]string{"run", "-dt", "--name", "bone", "--network", netNameB, nginx})
+ ctrB1.WaitWithDefaultTimeout()
+ cidB1 := ctrB1.OutputToString()
+
+ ctrIPB1 := podmanTest.Podman([]string{"inspect", "--format", fmt.Sprintf(`{{.NetworkSettings.Networks.%s.IPAddress}}`, netNameB), cidB1})
+ ctrIPB1.WaitWithDefaultTimeout()
+ Expect(ctrIPB1).Should(Exit(0))
+ cipB1 := ctrIPB1.OutputToString()
+ Expect(cipB1).To(MatchRegexp(IPRegex))
+
+ ctrA2B2 := podmanTest.Podman([]string{"run", "-dt", "--name", "atwobtwo", "--network", netNameA, "--network", netNameB, nginx})
+ ctrA2B2.WaitWithDefaultTimeout()
+ cidA2B2 := ctrA2B2.OutputToString()
+
+ ctrIPA2B21 := podmanTest.Podman([]string{"inspect", "--format", fmt.Sprintf(`{{.NetworkSettings.Networks.%s.IPAddress}}`, netNameA), cidA2B2})
+ ctrIPA2B21.WaitWithDefaultTimeout()
+ Expect(ctrIPA2B21).Should(Exit(0))
+ cipA2B21 := ctrIPA2B21.OutputToString()
+ Expect(cipA2B21).To(MatchRegexp(IPRegex))
+
+ ctrIPA2B22 := podmanTest.Podman([]string{"inspect", "--format", fmt.Sprintf(`{{.NetworkSettings.Networks.%s.IPAddress}}`, netNameB), cidA2B2})
+ ctrIPA2B22.WaitWithDefaultTimeout()
+ Expect(ctrIPA2B22).Should(Exit(0))
+ cipA2B22 := ctrIPA2B22.OutputToString()
+ Expect(cipA2B22).To(MatchRegexp(IPRegex))
+
+ _ = digShort("aone", "atwobtwo", []string{cipA2B21}, podmanTest)
+
+ _ = digShort("bone", "atwobtwo", []string{cipA2B22}, podmanTest)
+
+ _ = digShort("atwobtwo", "aone", []string{cipA1}, podmanTest)
+
+ _ = digShort("atwobtwo", "bone", []string{cipB1}, podmanTest)
+ })
+
+ It("Aardvark Test 6: Three subnets, first container on 1/2 and second on 2/3, w/ network aliases", func() {
+ netNameA := createNetworkName("TestA")
+ sessionA := podmanTest.Podman([]string{"network", "create", netNameA})
+ sessionA.WaitWithDefaultTimeout()
+ defer podmanTest.removeNetwork(netNameA)
+ Expect(sessionA).Should(Exit(0))
+
+ netNameB := createNetworkName("TestB")
+ sessionB := podmanTest.Podman([]string{"network", "create", netNameB})
+ sessionB.WaitWithDefaultTimeout()
+ defer podmanTest.removeNetwork(netNameB)
+ Expect(sessionB).Should(Exit(0))
+
+ netNameC := createNetworkName("TestC")
+ sessionC := podmanTest.Podman([]string{"network", "create", netNameC})
+ sessionC.WaitWithDefaultTimeout()
+ defer podmanTest.removeNetwork(netNameC)
+ Expect(sessionC).Should(Exit(0))
+
+ ctrA := podmanTest.Podman([]string{"run", "-dt", "--name", "aone", "--network", netNameA, nginx})
+ ctrA.WaitWithDefaultTimeout()
+ Expect(ctrA).Should(Exit(0))
+
+ ctrC := podmanTest.Podman([]string{"run", "-dt", "--name", "cone", "--network", netNameC, nginx})
+ ctrC.WaitWithDefaultTimeout()
+ Expect(ctrC).Should(Exit(0))
+
+ ctrnetAB1 := podmanTest.Podman([]string{"network", "connect", "--alias", "testB1_nw", netNameB, "aone"})
+ ctrnetAB1.WaitWithDefaultTimeout()
+ Expect(ctrnetAB1).Should(Exit(0))
+
+ ctrIPAB1 := podmanTest.Podman([]string{"inspect", "--format", fmt.Sprintf(`{{.NetworkSettings.Networks.%s.IPAddress}}`, netNameB), "aone"})
+ ctrIPAB1.WaitWithDefaultTimeout()
+ Expect(ctrIPAB1).Should(Exit(0))
+ cipAB1 := ctrIPAB1.OutputToString()
+
+ ctrnetCB2 := podmanTest.Podman([]string{"network", "connect", "--alias", "testB2_nw", netNameB, "cone"})
+ ctrnetCB2.WaitWithDefaultTimeout()
+ Expect(ctrnetCB2).Should(Exit(0))
+
+ ctrIPCB2 := podmanTest.Podman([]string{"inspect", "--format", fmt.Sprintf(`{{.NetworkSettings.Networks.%s.IPAddress}}`, netNameB), "cone"})
+ ctrIPCB2.WaitWithDefaultTimeout()
+ Expect(ctrIPCB2).Should(Exit(0))
+ cipCB2 := ctrIPCB2.OutputToString()
+
+ _ = digShort("aone", "testB2_nw", []string{cipCB2}, podmanTest)
+
+ _ = digShort("cone", "testB1_nw", []string{cipAB1}, podmanTest)
+
+ })
+
+})
diff --git a/test/e2e/run_apparmor_test.go b/test/e2e/run_apparmor_test.go
index e6526217a..64a01deb7 100644
--- a/test/e2e/run_apparmor_test.go
+++ b/test/e2e/run_apparmor_test.go
@@ -1,3 +1,4 @@
+//go:build !remote
// +build !remote
package integration
diff --git a/test/e2e/run_device_test.go b/test/e2e/run_device_test.go
index b8bdc84f8..479837dda 100644
--- a/test/e2e/run_device_test.go
+++ b/test/e2e/run_device_test.go
@@ -44,6 +44,11 @@ var _ = Describe("Podman run device", func() {
session := podmanTest.Podman([]string{"run", "-q", "--security-opt", "label=disable", "--device", "/dev/kmsg", ALPINE, "test", "-c", "/dev/kmsg"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
+ if !isRootless() {
+ session = podmanTest.Podman([]string{"run", "-q", "--security-opt", "label=disable", "--device", "/dev/kmsg", "--cap-add", "SYS_ADMIN", ALPINE, "head", "-n", "1", "/dev/kmsg"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ }
})
It("podman run device rename test", func() {
diff --git a/test/e2e/run_networking_test.go b/test/e2e/run_networking_test.go
index aa1887f84..2202cadd8 100644
--- a/test/e2e/run_networking_test.go
+++ b/test/e2e/run_networking_test.go
@@ -2,15 +2,19 @@ package integration
import (
"fmt"
+ "net"
"os"
"strings"
+ "syscall"
+ "github.com/containernetworking/plugins/pkg/ns"
. "github.com/containers/podman/v4/test/utils"
"github.com/containers/storage/pkg/stringid"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/gexec"
"github.com/uber/jaeger-client-go/utils"
+ "github.com/vishvananda/netlink"
)
var _ = Describe("Podman run networking", func() {
@@ -694,6 +698,157 @@ EXPOSE 2004-2005/tcp`, ALPINE)
Expect(session.OutputToString()).To(ContainSubstring("11.11.11.11"))
})
+ addAddr := func(cidr string, containerInterface netlink.Link) error {
+ _, ipnet, err := net.ParseCIDR(cidr)
+ Expect(err).To(BeNil())
+ addr := &netlink.Addr{IPNet: ipnet, Label: ""}
+ if err := netlink.AddrAdd(containerInterface, addr); err != nil && err != syscall.EEXIST {
+ return err
+ }
+ return nil
+ }
+
+ loopbackup := func() {
+ lo, err := netlink.LinkByName("lo")
+ Expect(err).To(BeNil())
+ err = netlink.LinkSetUp(lo)
+ Expect(err).To(BeNil())
+ }
+
+ linkup := func(name string, mac string, addresses []string) {
+ linkAttr := netlink.NewLinkAttrs()
+ linkAttr.Name = name
+ m, err := net.ParseMAC(mac)
+ Expect(err).To(BeNil())
+ linkAttr.HardwareAddr = net.HardwareAddr(m)
+ eth := &netlink.Dummy{LinkAttrs: linkAttr}
+ err = netlink.LinkAdd(eth)
+ Expect(err).To(BeNil())
+ err = netlink.LinkSetUp(eth)
+ Expect(err).To(BeNil())
+ for _, address := range addresses {
+ err := addAddr(address, eth)
+ Expect(err).To(BeNil())
+ }
+ }
+
+ routeAdd := func(gateway string) {
+ gw := net.ParseIP(gateway)
+ route := &netlink.Route{Dst: nil, Gw: gw}
+ netlink.RouteAdd(route)
+ }
+
+ setupNetworkNs := func(networkNSName string) {
+ ns.WithNetNSPath("/run/netns/"+networkNSName, func(_ ns.NetNS) error {
+ loopbackup()
+ linkup("eth0", "46:7f:45:6e:4f:c8", []string{"10.25.40.0/24", "fd04:3e42:4a4e:3381::/64"})
+ linkup("eth1", "56:6e:35:5d:3e:a8", []string{"10.88.0.0/16"})
+
+ routeAdd("10.25.40.0")
+ return nil
+ })
+ }
+
+ checkNetworkNsInspect := func(name string) {
+ inspectOut := podmanTest.InspectContainer(name)
+ Expect(inspectOut[0].NetworkSettings.IPAddress).To(Equal("10.25.40.0"))
+ Expect(inspectOut[0].NetworkSettings.IPPrefixLen).To(Equal(24))
+ Expect(len(inspectOut[0].NetworkSettings.SecondaryIPAddresses)).To(Equal(1))
+ Expect(inspectOut[0].NetworkSettings.SecondaryIPAddresses[0].Addr).To(Equal("10.88.0.0"))
+ Expect(inspectOut[0].NetworkSettings.SecondaryIPAddresses[0].PrefixLength).To(Equal(16))
+ Expect(inspectOut[0].NetworkSettings.GlobalIPv6Address).To(Equal("fd04:3e42:4a4e:3381::"))
+ Expect(inspectOut[0].NetworkSettings.GlobalIPv6PrefixLen).To(Equal(64))
+ Expect(len(inspectOut[0].NetworkSettings.SecondaryIPv6Addresses)).To(Equal(0))
+ Expect(inspectOut[0].NetworkSettings.MacAddress).To(Equal("46:7f:45:6e:4f:c8"))
+ Expect(len(inspectOut[0].NetworkSettings.AdditionalMacAddresses)).To(Equal(1))
+ Expect(inspectOut[0].NetworkSettings.AdditionalMacAddresses[0]).To(Equal("56:6e:35:5d:3e:a8"))
+ Expect(inspectOut[0].NetworkSettings.Gateway).To(Equal("10.25.40.0"))
+
+ }
+
+ It("podman run newtork inspect fails gracefully on non-reachable network ns", func() {
+ SkipIfRootless("ip netns is not supported for rootless users")
+
+ networkNSName := RandomString(12)
+ addNamedNetwork := SystemExec("ip", []string{"netns", "add", networkNSName})
+ Expect(addNamedNetwork).Should(Exit(0))
+
+ setupNetworkNs(networkNSName)
+
+ name := RandomString(12)
+ session := podmanTest.Podman([]string{"run", "-d", "--name", name, "--net", "ns:/run/netns/" + networkNSName, ALPINE, "top"})
+ session.WaitWithDefaultTimeout()
+
+ // delete the named network ns before inspect
+ delNetworkNamespace := SystemExec("ip", []string{"netns", "delete", networkNSName})
+ Expect(delNetworkNamespace).Should(Exit(0))
+
+ inspectOut := podmanTest.InspectContainer(name)
+ Expect(inspectOut[0].NetworkSettings.IPAddress).To(Equal(""))
+ Expect(len(inspectOut[0].NetworkSettings.Networks)).To(Equal(0))
+ })
+
+ It("podman inspect can handle joined network ns with multiple interfaces", func() {
+ SkipIfRootless("ip netns is not supported for rootless users")
+
+ networkNSName := RandomString(12)
+ addNamedNetwork := SystemExec("ip", []string{"netns", "add", networkNSName})
+ Expect(addNamedNetwork).Should(Exit(0))
+ defer func() {
+ delNetworkNamespace := SystemExec("ip", []string{"netns", "delete", networkNSName})
+ Expect(delNetworkNamespace).Should(Exit(0))
+ }()
+ setupNetworkNs(networkNSName)
+
+ name := RandomString(12)
+ session := podmanTest.Podman([]string{"run", "--name", name, "--net", "ns:/run/netns/" + networkNSName, ALPINE})
+ session.WaitWithDefaultTimeout()
+
+ session = podmanTest.Podman([]string{"container", "rm", name})
+ session.WaitWithDefaultTimeout()
+
+ // no network teardown should touch joined network ns interfaces
+ session = podmanTest.Podman([]string{"run", "-d", "--replace", "--name", name, "--net", "ns:/run/netns/" + networkNSName, ALPINE, "top"})
+ session.WaitWithDefaultTimeout()
+
+ checkNetworkNsInspect(name)
+ })
+
+ It("podman do not tamper with joined network ns interfaces", func() {
+ SkipIfRootless("ip netns is not supported for rootless users")
+
+ networkNSName := RandomString(12)
+ addNamedNetwork := SystemExec("ip", []string{"netns", "add", networkNSName})
+ Expect(addNamedNetwork).Should(Exit(0))
+ defer func() {
+ delNetworkNamespace := SystemExec("ip", []string{"netns", "delete", networkNSName})
+ Expect(delNetworkNamespace).Should(Exit(0))
+ }()
+
+ setupNetworkNs(networkNSName)
+
+ name := RandomString(12)
+ session := podmanTest.Podman([]string{"run", "--name", name, "--net", "ns:/run/netns/" + networkNSName, ALPINE})
+ session.WaitWithDefaultTimeout()
+
+ checkNetworkNsInspect(name)
+
+ name = RandomString(12)
+ session = podmanTest.Podman([]string{"run", "--name", name, "--net", "ns:/run/netns/" + networkNSName, ALPINE})
+ session.WaitWithDefaultTimeout()
+
+ checkNetworkNsInspect(name)
+
+ // delete container, the network inspect should not change
+ session = podmanTest.Podman([]string{"container", "rm", name})
+ session.WaitWithDefaultTimeout()
+
+ session = podmanTest.Podman([]string{"run", "-d", "--replace", "--name", name, "--net", "ns:/run/netns/" + networkNSName, ALPINE, "top"})
+ session.WaitWithDefaultTimeout()
+
+ checkNetworkNsInspect(name)
+ })
+
It("podman run network in bogus user created network namespace", func() {
session := podmanTest.Podman([]string{"run", "-dt", "--net", "ns:/run/netns/xxy", ALPINE, "wget", "www.podman.io"})
session.Wait(90)
diff --git a/test/e2e/system_df_test.go b/test/e2e/system_df_test.go
index 2d75316ad..a9fa5f4ac 100644
--- a/test/e2e/system_df_test.go
+++ b/test/e2e/system_df_test.go
@@ -41,11 +41,17 @@ var _ = Describe("podman system df", func() {
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- session = podmanTest.Podman([]string{"volume", "create", "data"})
+ // run two containers with volumes to create something in the volume
+ session = podmanTest.Podman([]string{"run", "-v", "data1:/data", "--name", "container1", BB, "sh", "-c", "echo test > /data/1"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
- session = podmanTest.Podman([]string{"create", "-v", "data:/data", "--name", "container1", BB})
+ session = podmanTest.Podman([]string{"run", "-v", "data2:/data", "--name", "container2", BB, "sh", "-c", "echo test > /data/1"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ // remove one container, we keep the volume
+ session = podmanTest.Podman([]string{"rm", "container2"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
@@ -61,9 +67,10 @@ var _ = Describe("podman system df", func() {
images := strings.Fields(session.OutputToStringArray()[1])
containers := strings.Fields(session.OutputToStringArray()[2])
volumes := strings.Fields(session.OutputToStringArray()[3])
- Expect(images[1]).To(Equal(string(totImages)))
- Expect(containers[1]).To(Equal("2"))
- Expect(volumes[2]).To(Equal("1"))
+ Expect(images[1]).To(Equal(string(totImages)), "total images expected")
+ Expect(containers[1]).To(Equal("2"), "total containers expected")
+ Expect(volumes[2]).To(Equal("2"), "total volumes expected")
+ Expect(volumes[6]).To(Equal("(50%)"), "percentage usage expected")
})
It("podman system df image with no tag", func() {
diff --git a/test/e2e/system_service_test.go b/test/e2e/system_service_test.go
index dcf5e03b2..2bc7756d6 100644
--- a/test/e2e/system_service_test.go
+++ b/test/e2e/system_service_test.go
@@ -58,6 +58,7 @@ var _ = Describe("podman system service", func() {
const magicComment = "pprof service listening on"
It("are available", func() {
+ Skip("FIXME: Test is too flaky (#12624)")
SkipIfRemote("service subcommand not supported remotely")
address := url.URL{
@@ -97,6 +98,7 @@ var _ = Describe("podman system service", func() {
})
It("are not available", func() {
+ Skip("FIXME: Test is too flaky (#12624)")
SkipIfRemote("service subcommand not supported remotely")
address := url.URL{
diff --git a/test/e2e/systemd_activate_test.go b/test/e2e/systemd_activate_test.go
new file mode 100644
index 000000000..d5434868d
--- /dev/null
+++ b/test/e2e/systemd_activate_test.go
@@ -0,0 +1,107 @@
+package integration
+
+import (
+ "errors"
+ "fmt"
+ "io/fs"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "syscall"
+ "time"
+
+ testUtils "github.com/containers/podman/v4/test/utils"
+ podmanUtils "github.com/containers/podman/v4/utils"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+ . "github.com/onsi/gomega/gexec"
+)
+
+var _ = Describe("Systemd activate", func() {
+ var tempDir string
+ var err error
+ var podmanTest *PodmanTestIntegration
+
+ BeforeEach(func() {
+ tempDir, err = testUtils.CreateTempDirInTempDir()
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "%v\n", err)
+ os.Exit(1)
+ }
+
+ podmanTest = PodmanTestCreate(tempDir)
+ podmanTest.Setup()
+ podmanTest.SeedImages()
+ })
+
+ AfterEach(func() {
+ podmanTest.Cleanup()
+ processTestResult(CurrentGinkgoTestDescription())
+ })
+
+ It("stop podman.service", func() {
+ SkipIfRemote("Testing stopped service requires both podman and podman-remote binaries")
+
+ activate, err := exec.LookPath("systemd-socket-activate")
+ if err != nil {
+ activate = "/usr/bin/systemd-socket-activate"
+ }
+ stat, err := os.Stat(activate)
+ switch {
+ case errors.Is(err, fs.ErrNotExist):
+ Skip(activate + " required for systemd activation tests")
+ case stat.Mode()&0111 == 0:
+ Skip("Unable to execute " + activate)
+ case err != nil:
+ Skip(err.Error())
+ }
+
+ // systemd-socket-activate does not support DNS lookups
+ host := "127.0.0.1"
+ port, err := podmanUtils.GetRandomPort()
+ Expect(err).ToNot(HaveOccurred())
+
+ activateSession := testUtils.StartSystemExec(activate, []string{
+ fmt.Sprintf("--listen=%s:%d", host, port),
+ podmanTest.PodmanBinary,
+ "--root=" + filepath.Join(tempDir, "server_root"),
+ "system", "service",
+ "--time=0",
+ })
+ Expect(activateSession.Exited).ShouldNot(Receive(), "Failed to start podman service")
+
+ // Curried functions for specialized podman calls
+ podmanRemote := func(args ...string) *testUtils.PodmanSession {
+ args = append([]string{"--url", fmt.Sprintf("tcp://%s:%d", host, port)}, args...)
+ return testUtils.SystemExec(podmanTest.RemotePodmanBinary, args)
+ }
+
+ podman := func(args ...string) *testUtils.PodmanSession {
+ args = append([]string{"--root", filepath.Join(tempDir, "server_root")}, args...)
+ return testUtils.SystemExec(podmanTest.PodmanBinary, args)
+ }
+
+ containerName := "top_" + testUtils.RandomString(8)
+ apiSession := podmanRemote(
+ "create", "--tty", "--name", containerName, "--entrypoint", "top",
+ "quay.io/libpod/alpine_labels:latest",
+ )
+ Expect(apiSession).Should(Exit(0))
+
+ apiSession = podmanRemote("start", containerName)
+ Expect(apiSession).Should(Exit(0))
+
+ apiSession = podmanRemote("inspect", "--format={{.State.Running}}", containerName)
+ Expect(apiSession).Should(Exit(0))
+ Expect(apiSession.OutputToString()).To(Equal("true"))
+
+ // Emulate 'systemd stop podman.service'
+ activateSession.Signal(syscall.SIGTERM)
+ time.Sleep(2)
+ Eventually(activateSession).Should(Exit(0))
+
+ abiSession := podman("inspect", "--format={{.State.Running}}", containerName)
+ Expect(abiSession).To(Exit(0))
+ Expect(abiSession.OutputToString()).To(Equal("true"))
+ })
+})
diff --git a/test/system/010-images.bats b/test/system/010-images.bats
index ebd71450f..257508418 100644
--- a/test/system/010-images.bats
+++ b/test/system/010-images.bats
@@ -248,8 +248,7 @@ Labels.created_at | 20[0-9-]\\\+T[0-9:]\\\+Z
run_podman inspect --format '{{.ID}}' $IMAGE
imageID=$output
- run_podman version --format "{{.Server.Version}}-{{.Server.Built}}"
- pauseImage=localhost/podman-pause:$output
+ pauseImage=$(pause_image)
run_podman inspect --format '{{.ID}}' $pauseImage
pauseID=$output
@@ -304,4 +303,13 @@ Deleted: $pauseID"
run_podman image exists $IMAGE
}
+@test "podman rmi --ignore" {
+ random_image_name=$(random_string)
+ random_image_name=${random_image_name,,} # name must be lowercase
+ run_podman 1 rmi $random_image_name
+ is "$output" "Error: $random_image_name: image not known.*"
+ run_podman rmi --ignore $random_image_name
+ is "$output" ""
+}
+
# vim: filetype=sh
diff --git a/test/system/070-build.bats b/test/system/070-build.bats
index c963d8325..7466c3b74 100644
--- a/test/system/070-build.bats
+++ b/test/system/070-build.bats
@@ -210,6 +210,30 @@ EOF
run_podman rmi -f build_test
}
+@test "podman parallel build should not race" {
+ skip_if_remote "following test is not supported for remote clients"
+
+ # Run thirty parallel builds using the same Containerfile
+ cat >$PODMAN_TMPDIR/Containerfile <<EOF
+FROM $IMAGE
+RUN echo hi
+EOF
+
+ local count=30
+ for i in $(seq --format '%02g' 1 $count); do
+ timeout --foreground -v --kill=10 60 \
+ $PODMAN build -t i$i $PODMAN_TMPDIR &>/dev/null &
+ done
+
+ # Wait for all background builds to complete. Note that this succeeds
+ # even if some of the individual builds fail! Our actual test is below.
+ wait
+
+ # Now delete all built images. If any image wasn't built, rmi will fail
+ # and test will fail.
+ run_podman rmi $(seq --format 'i%02g' 1 $count)
+}
+
@test "podman build - URLs" {
tmpdir=$PODMAN_TMPDIR/build-test
mkdir -p $tmpdir
@@ -581,7 +605,7 @@ EOF
done
}
-# Regression test for #9867
+# Regression test for #9867 and #13529
# Make sure that if you exclude everything in context dir, that
# the Containerfile/Dockerfile in the context dir are used
@test "podman build with ignore '*'" {
@@ -596,6 +620,15 @@ cat >$tmpdir/.dockerignore <<EOF
*
EOF
+ # Prior to the fix for #13529, pod-create would fail with 'error building
+ # at STEP COPY .../catatonit' because of the local .dockerignore file was
+ # used.
+ pushd "${tmpdir}"
+ run_podman pod create
+ run_podman pod rm $output
+ run_podman rmi $(pause_image)
+ popd
+
run_podman build -t build_test $tmpdir
# Rename Containerfile to Dockerfile
diff --git a/test/system/200-pod.bats b/test/system/200-pod.bats
index 34dfaa8f6..f5fe41924 100644
--- a/test/system/200-pod.bats
+++ b/test/system/200-pod.bats
@@ -6,13 +6,7 @@ load helpers
function teardown() {
run_podman pod rm -f -t 0 -a
run_podman rm -f -t 0 -a
- run_podman image list --format '{{.ID}} {{.Repository}}'
- while read id name; do
- if [[ "$name" =~ /podman-pause ]]; then
- run_podman rmi $id
- fi
- done <<<"$output"
-
+ run_podman rmi --ignore $(pause_image)
basic_teardown
}
@@ -323,16 +317,17 @@ EOF
@test "podman pod create should fail when infra-name is already in use" {
local infra_name="infra_container_$(random_string 10 | tr A-Z a-z)"
+ local infra_image="k8s.gcr.io/pause:3.5"
local pod_name="$(random_string 10 | tr A-Z a-z)"
- run_podman --noout pod create --name $pod_name --infra-name "$infra_name" --infra-image "k8s.gcr.io/pause:3.5"
- is "$output" "" "output should be empty"
+ run_podman --noout pod create --name $pod_name --infra-name "$infra_name" --infra-image "$infra_image"
+ is "$output" "" "output from pod create should be empty"
run_podman '?' pod create --infra-name "$infra_name"
if [ $status -eq 0 ]; then
die "Podman should fail when user try to create two pods with the same infra-name value"
fi
run_podman pod rm -f $pod_name
- run_podman images -a
+ run_podman rmi $infra_image
}
@test "podman pod create --share" {
diff --git a/test/system/700-play.bats b/test/system/700-play.bats
index 88c7cad87..8af4cd25b 100644
--- a/test/system/700-play.bats
+++ b/test/system/700-play.bats
@@ -168,3 +168,68 @@ _EOF
run_podman pod rm -t 0 -f test_pod
run_podman rmi -f userimage:latest
}
+
+@test "podman play --build --context-dir" {
+ skip_if_remote "--build is not supported in context remote"
+ testUserYaml="
+apiVersion: v1
+kind: Pod
+metadata:
+ labels:
+ app: test
+ name: test_pod
+spec:
+ containers:
+ - command:
+ - id
+ env:
+ - name: PATH
+ value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
+ - name: TERM
+ value: xterm
+ - name: container
+ value: podman
+ image: quay.io/libpod/userimage
+ name: test
+ resources: {}
+status: {}
+"
+
+mkdir -p $PODMAN_TMPDIR/userimage
+cat > $PODMAN_TMPDIR/userimage/Containerfile << _EOF
+from $IMAGE
+USER bin
+_EOF
+
+ echo "$testUserYaml" > $PODMAN_TMPDIR/test.yaml
+ run_podman 125 play kube --build --start=false $PODMAN_TMPDIR/test.yaml
+ run_podman play kube --replace --context-dir=$PODMAN_TMPDIR --build --start=false $PODMAN_TMPDIR/test.yaml
+ run_podman inspect --format "{{ .Config.User }}" test_pod-test
+ is "$output" bin "expect container within pod to run as the bin user"
+
+ run_podman stop -a -t 0
+ run_podman pod rm -t 0 -f test_pod
+ run_podman rmi -f userimage:latest
+
+ cd $PODMAN_TMPDIR
+ run_podman play kube --replace --build --start=false $PODMAN_TMPDIR/test.yaml
+ run_podman inspect --format "{{ .Config.User }}" test_pod-test
+ is "$output" bin "expect container within pod to run as the bin user"
+
+ run_podman stop -a -t 0
+ run_podman pod rm -t 0 -f test_pod
+ run_podman rmi -f userimage:latest
+}
+
+@test "podman play --annotation" {
+ TESTDIR=$PODMAN_TMPDIR/testdir
+ RANDOMSTRING=$(random_string 15)
+ mkdir -p $TESTDIR
+ echo "$testYaml" | sed "s|TESTDIR|${TESTDIR}|g" > $PODMAN_TMPDIR/test.yaml
+ run_podman play kube --annotation "name=$RANDOMSTRING" $PODMAN_TMPDIR/test.yaml
+ run_podman inspect --format "{{ .Config.Annotations }}" test_pod-test
+ is "$output" ".*name:$RANDOMSTRING" "Annotation should be added to pod"
+
+ run_podman stop -a -t 0
+ run_podman pod rm -t 0 -f test_pod
+}
diff --git a/test/system/helpers.bash b/test/system/helpers.bash
index 221315b97..0d336592f 100644
--- a/test/system/helpers.bash
+++ b/test/system/helpers.bash
@@ -383,6 +383,15 @@ function journald_unavailable() {
return 1
}
+# Returns the name of the local pause image.
+function pause_image() {
+ # This function is intended to be used as '$(pause_image)', i.e.
+ # our caller wants our output. run_podman() messes with output because
+ # it emits the command invocation to stdout, hence the redirection.
+ run_podman version --format "{{.Server.Version}}-{{.Server.Built}}" >/dev/null
+ echo "localhost/podman-pause:$output"
+}
+
###########################
# _add_label_if_missing # make sure skip messages include rootless/remote
###########################
diff --git a/test/utils/common_function_test.go b/test/utils/common_function_test.go
index 810d9f2a5..6323b44eb 100644
--- a/test/utils/common_function_test.go
+++ b/test/utils/common_function_test.go
@@ -51,7 +51,8 @@ var _ = Describe("Common functions test", func() {
txt := fmt.Sprintf("ID=%s\nVERSION_ID=%s", id, ver)
if !empty {
f, _ := os.Create(path)
- f.WriteString(txt)
+ _, err := f.WriteString(txt)
+ Expect(err).To(BeNil(), "Failed to write data.")
f.Close()
}
@@ -102,9 +103,10 @@ var _ = Describe("Common functions test", func() {
Item2: []string{"test"},
}
- testByte, _ := json.Marshal(testData)
- err := WriteJSONFile(testByte, "/tmp/testJSON")
+ testByte, err := json.Marshal(testData)
+ Expect(err).To(BeNil(), "Failed to marshal data.")
+ err = WriteJSONFile(testByte, "/tmp/testJSON")
Expect(err).To(BeNil(), "Failed to write JSON to file.")
read, err := os.Open("/tmp/testJSON")
@@ -135,7 +137,8 @@ var _ = Describe("Common functions test", func() {
}
if createFile {
f, _ := os.Create(path)
- f.WriteString(txt)
+ _, err := f.WriteString(txt)
+ Expect(err).To(BeNil(), "Failed to write data.")
f.Close()
}
ProcessOneCgroupPath = path
diff --git a/test/utils/matchers.go b/test/utils/matchers.go
index 288779b63..0c0948e4b 100644
--- a/test/utils/matchers.go
+++ b/test/utils/matchers.go
@@ -13,7 +13,7 @@ import (
"github.com/onsi/gomega/types"
)
-// HaveActiveService verifies the given service is the active service
+// HaveActiveService verifies the given service is the active service.
func HaveActiveService(name interface{}) OmegaMatcher {
return WithTransform(
func(cfg *config.Config) string {
@@ -86,7 +86,7 @@ type URLMatcher struct {
matchers.EqualMatcher
}
-// VerifyURL matches when actual is a valid URL and matches expected
+// VerifyURL matches when actual is a valid URL and matches expected.
func VerifyURL(uri interface{}) OmegaMatcher {
return &URLMatcher{matchers.EqualMatcher{Expected: uri}}
}
@@ -129,7 +129,7 @@ func ExitWithError(optionalExitCode ...int) *ExitMatcher {
return &ExitMatcher{Expected: exitCode}
}
-// Match follows gexec.Matcher interface
+// Match follows gexec.Matcher interface.
func (matcher *ExitMatcher) Match(actual interface{}) (success bool, err error) {
exiter, ok := actual.(gexec.Exiter)
if !ok {
@@ -184,7 +184,7 @@ func (matcher *ValidJSONMatcher) Match(actual interface{}) (success bool, err er
var i interface{}
if err := json.Unmarshal([]byte(s), &i); err != nil {
- return false, nil
+ return false, err
}
return true, nil
}
diff --git a/test/utils/utils.go b/test/utils/utils.go
index 14092a2a5..a6295cd19 100644
--- a/test/utils/utils.go
+++ b/test/utils/utils.go
@@ -368,6 +368,7 @@ func CreateTempDirInTempDir() (string, error) {
// SystemExec is used to exec a system command to check its exit code or output
func SystemExec(command string, args []string) *PodmanSession {
c := exec.Command(command, args...)
+ fmt.Println("Execing " + c.String() + "\n")
session, err := Start(c, GinkgoWriter, GinkgoWriter)
if err != nil {
Fail(fmt.Sprintf("unable to run command: %s %s", command, strings.Join(args, " ")))
@@ -379,6 +380,7 @@ func SystemExec(command string, args []string) *PodmanSession {
// StartSystemExec is used to start exec a system command
func StartSystemExec(command string, args []string) *PodmanSession {
c := exec.Command(command, args...)
+ fmt.Println("Execing " + c.String() + "\n")
session, err := Start(c, GinkgoWriter, GinkgoWriter)
if err != nil {
Fail(fmt.Sprintf("unable to run command: %s %s", command, strings.Join(args, " ")))
@@ -477,7 +479,10 @@ func IsCommandAvailable(command string) bool {
func WriteJSONFile(data []byte, filePath string) error {
var jsonData map[string]interface{}
json.Unmarshal(data, &jsonData)
- formatJSON, _ := json.MarshalIndent(jsonData, "", " ")
+ formatJSON, err := json.MarshalIndent(jsonData, "", " ")
+ if err != nil {
+ return err
+ }
return ioutil.WriteFile(filePath, formatJSON, 0644)
}