summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/apiv2/10-images.at2
-rw-r--r--test/apiv2/12-imagesMore.at56
-rw-r--r--test/apiv2/15-manifest.at24
-rw-r--r--test/apiv2/20-containers.at10
-rw-r--r--test/apiv2/60-auth.at4
-rw-r--r--test/apiv2/70-short-names.at2
-rwxr-xr-xtest/apiv2/test-apiv282
-rwxr-xr-xtest/buildah-bud/apply-podman-deltas13
-rw-r--r--test/e2e/build_test.go2
-rw-r--r--test/e2e/logs_test.go21
-rw-r--r--test/e2e/network_connect_disconnect_test.go9
-rw-r--r--test/e2e/play_kube_test.go8
-rw-r--r--test/e2e/pod_create_test.go22
-rw-r--r--test/e2e/run_privileged_test.go24
-rw-r--r--test/e2e/run_volume_test.go45
-rw-r--r--test/system/170-run-userns.bats35
-rw-r--r--test/system/500-networking.bats4
-rw-r--r--test/system/520-checkpoint.bats30
-rw-r--r--test/system/600-completion.bats18
19 files changed, 302 insertions, 109 deletions
diff --git a/test/apiv2/10-images.at b/test/apiv2/10-images.at
index 13aaea317..f03b95786 100644
--- a/test/apiv2/10-images.at
+++ b/test/apiv2/10-images.at
@@ -53,7 +53,7 @@ t POST "images/create?fromImage=alpine" 200 .error~null .status~".*Download comp
t POST "images/create?fromImage=alpine&tag=latest" 200
# 10977 - handle platform parameter correctly
-t POST "images/create?fromImage=testimage:20210610&platform=linux/arm64" 200
+t POST "images/create?fromImage=quay.io/libpod/testimage:20210610&platform=linux/arm64" 200
t GET "images/testimage:20210610/json" 200 \
.Architecture=arm64
diff --git a/test/apiv2/12-imagesMore.at b/test/apiv2/12-imagesMore.at
index 67b4f1c79..57d5e114d 100644
--- a/test/apiv2/12-imagesMore.at
+++ b/test/apiv2/12-imagesMore.at
@@ -6,6 +6,8 @@
red='\e[31m'
nc='\e[0m'
+start_registry
+
podman pull -q $IMAGE
t GET libpod/images/json 200 \
@@ -20,48 +22,38 @@ t GET libpod/images/$IMAGE/tree 200 \
t POST "libpod/images/nonesuch/tag?repo=myrepo&tag=mytag" 404
# Tag the image
-t POST "libpod/images/$IMAGE/tag?repo=localhost:5000/myrepo&tag=mytag" 201
+t POST "libpod/images/$IMAGE/tag?repo=localhost:$REGISTRY_PORT/myrepo&tag=mytag" 201
t GET libpod/images/$IMAGE/json 200 \
- .RepoTags[1]=localhost:5000/myrepo:mytag
-
-# Run registry container
-# 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
-while read -r LINE
-do
- if echo "${LINE}" | jq --exit-status 'select( .status != null) | select ( .status | contains("digest: sha256:"))' &>/dev/null; then
- GOT_DIGEST="1"
- fi
-done < <(curl -sL "http://$HOST:$PORT/images/localhost:5000/myrepo/push?tlsVerify=false&tag=mytag" -XPOST)
-if [ -z "${GOT_DIGEST}" ] ; then
- echo -e "${red}not ok: did not found digest in output${nc}" 1>&2;
-fi
-
-# Push to local registry
-t POST "images/localhost:5000/myrepo/push?tlsVerify=false&tag=mytag" 200
+ .RepoTags[1]=localhost:$REGISTRY_PORT/myrepo:mytag
+
+# Push to local registry...
+t POST "images/localhost:$REGISTRY_PORT/myrepo/push?tlsVerify=false&tag=mytag" 200
+
+# ...and check output. We can't use our built-in checks because this output
+# is a sequence of JSON objects, i.e., individual ones, not in a JSON array.
+# The lines themselves are valid JSON, but taken together they are not.
+readarray lines <<<"$output"
+s0=$(jq -r .status <<<"${lines[0]}")
+is "$s0" "The push refers to repository [localhost:$REGISTRY_PORT/myrepo:mytag]" \
+ "Push to local registry: first status line"
+
+# FIXME: is there a way to test the actual digest?
+s1=$(jq -r .status <<<"${lines[1]}")
+like "$s1" "mytag: digest: sha256:[0-9a-f]\{64\} size: [0-9]\+" \
+ "Push to local registry: second status line"
# Untag the image
-t POST "libpod/images/$iid/untag?repo=localhost:5000/myrepo&tag=mytag" 201
+t POST "libpod/images/$iid/untag?repo=localhost:$REGISTRY_PORT/myrepo&tag=mytag" 201
# Try to push non-existing image
-t POST "images/localhost:5000/idonotexist/push?tlsVerify=false" 404
+t POST "images/localhost:$REGISTRY_PORT/idonotexist/push?tlsVerify=false" 404
t GET libpod/images/$IMAGE/json 200 \
.RepoTags[-1]=$IMAGE
-# Remove the registry container
-t DELETE libpod/containers/registry?force=true 200
-
-# Remove images
+# Remove image
t DELETE libpod/images/$IMAGE 200 \
.ExitCode=0
-t DELETE libpod/images/quay.io/libpod/registry:2.7 200 \
- .ExitCode=0
-if [ -z "${GOT_DIGEST}" ] ; then
- exit 1;
-fi
+stop_registry
diff --git a/test/apiv2/15-manifest.at b/test/apiv2/15-manifest.at
index 0dd7026fa..970bed5a8 100644
--- a/test/apiv2/15-manifest.at
+++ b/test/apiv2/15-manifest.at
@@ -2,18 +2,40 @@
#
# Tests for manifest list endpoints
+start_registry
+
t POST /v3.4.0/libpod/manifests/create?name=abc 200 \
.Id~[0-9a-f]\\{64\\}
id_abc=$(jq -r '.Id' <<<"$output")
t POST /v4.0.0/libpod/manifests/xyz 201 \
.Id~[0-9a-f]\\{64\\}
-echo xyz $output
id_xyz=$(jq -r '.Id' <<<"$output")
t GET /v3.4.0/libpod/manifests/$id_abc/exists 204
t GET /v4.0.0/libpod/manifests/$id_xyz/exists 204
+id_abc_image=$($PODMAN_BIN --root $WORKDIR/server_root image build -q --format=docker -<<EOF
+FROM alpine
+RUN >file1
+EOF
+)
+
+id_xyz_image=$($PODMAN_BIN --root $WORKDIR/server_root image build -q --format=docker -<<EOF
+FROM alpine
+RUN >file2
+EOF
+)
+
+t POST /v3.4.0/libpod/manifests/$id_abc/add images="[\"containers-storage:$id_abc_image\"]" 200
+t PUT /v4.0.0/libpod/manifests/$id_xyz operation='update' images="[\"containers-storage:$id_xyz_image\"]" 200
+
+t POST "/v3.4.0/libpod/manifests/abc:latest/push?destination=localhost:$REGISTRY_PORT%2Fabc:latest&tlsVerify=false&all=true" 200
+t POST "/v4.0.0/libpod/manifests/xyz:latest/registry/localhost:$REGISTRY_PORT%2Fxyz:latest?tlsVerify=false&all=true" 200
+
# /v3.x cannot delete a manifest list
t DELETE /v4.0.0/libpod/manifests/$id_abc 200
t DELETE /v4.0.0/libpod/manifests/$id_xyz 200
+
+podman rmi -a
+stop_registry
diff --git a/test/apiv2/20-containers.at b/test/apiv2/20-containers.at
index 4d32a1031..383c527b4 100644
--- a/test/apiv2/20-containers.at
+++ b/test/apiv2/20-containers.at
@@ -45,16 +45,16 @@ t GET libpod/containers/json?all=true 200 \
.[0].IsInfra=false
# Test compat API for Network Settings (.Network is N/A when rootless)
-network_expect=
+network_expect="Networks=null"
if root; then
- network_expect='.[0].NetworkSettings.Networks.podman.NetworkID=podman'
+ network_expect="Networks.podman.NetworkID=podman"
fi
t GET /containers/json?all=true 200 \
length=1 \
.[0].Id~[0-9a-f]\\{64\\} \
.[0].Image=$IMAGE \
.[0].Mounts~.*/tmp \
- $network_expect
+ .[0].NetworkSettings.$network_expect
# compat API imageid with sha256: prefix
t GET containers/json?limit=1 200 \
@@ -239,6 +239,7 @@ t GET containers/$cid/json 200 \
t POST containers/create Image=$IMAGE Entrypoint='["top"]' 201 \
.Id~[0-9a-f]\\{64\\}
cid_top=$(jq -r '.Id' <<<"$output")
+
t GET containers/${cid_top}/json 200 \
.Config.Entrypoint[0]="top" \
.Config.Cmd='[]' \
@@ -477,7 +478,8 @@ for endpoint in containers/create libpod/containers/create; do
t POST libpod/containers/$cid/init 204
- t GET libpod/containers/$cid/json 200
+ t GET libpod/containers/$cid/json 200 \
+ .HostsPath=""
t DELETE containers/$cid 204
done
diff --git a/test/apiv2/60-auth.at b/test/apiv2/60-auth.at
index 1e087d12b..465b0a96d 100644
--- a/test/apiv2/60-auth.at
+++ b/test/apiv2/60-auth.at
@@ -3,7 +3,7 @@
# registry-related tests
#
-start_registry
+start_registry htpasswd
# Test unreachable
t POST /v1.40/auth username=$REGISTRY_USERNAME password=WrOnGPassWord serveraddress=does.not.exist.io:1234/ \
@@ -26,3 +26,5 @@ t POST /v1.40/auth username=$REGISTRY_USERNAME password=$REGISTRY_PASSWORD serve
200 \
.Status="Login Succeeded" \
.IdentityToken=""
+
+stop_registry
diff --git a/test/apiv2/70-short-names.at b/test/apiv2/70-short-names.at
index dbf816f55..bd7f8e7bd 100644
--- a/test/apiv2/70-short-names.at
+++ b/test/apiv2/70-short-names.at
@@ -128,7 +128,7 @@ t DELETE "containers/$cid"
# disable the docker.io enforcement.
stop_service
-CONTAINERS_CONF=$(pwd)/test/apiv2/containers.conf start_service
+CONTAINERS_CONF=$TESTS_DIR/containers.conf start_service
t POST "images/create?fromImage=quay.io/libpod/alpine:latest" 200 .error~null .status~".*Download complete.*"
t POST "images/alpine/tag?repo=foo" 201
diff --git a/test/apiv2/test-apiv2 b/test/apiv2/test-apiv2
index c3545522e..6151b7672 100755
--- a/test/apiv2/test-apiv2
+++ b/test/apiv2/test-apiv2
@@ -62,7 +62,7 @@ clean_up_server() {
podman rm -a
podman rmi -af
- stop_registry
+ stop_registry --cleanup
stop_service
fi
}
@@ -87,6 +87,7 @@ trap err_handler ERR
#########
function die() {
echo "$ME: $*" >&2
+ clean_up_server
exit 1
}
@@ -219,19 +220,19 @@ function jsonify() {
function t() {
local method=$1; shift
local path=$1; shift
- local curl_args
+ local -a curl_args
local content_type="application/json"
local testname="$method $path"
- # POST requests may be followed by one or more key=value pairs.
+ # 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" ]]; then
+ if [[ $method = "POST" || $method == "PUT" ]]; then
local -a post_args
for arg; do
case "$arg" in
*=*) post_args+=("$arg");
shift;;
- *.tar) curl_args="--data-binary @$arg" ;
+ *.tar) curl_args+=(--data-binary @$arg);
content_type="application/x-tar";
shift;;
application/*) content_type="$arg";
@@ -241,8 +242,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
@@ -269,7 +270,7 @@ function t() {
# curl -X HEAD but without --head seems to wait for output anyway
if [[ $method == "HEAD" ]]; then
- curl_args="--head"
+ curl_args+=("--head")
fi
local expected_code=$1; shift
@@ -281,7 +282,7 @@ function t() {
# -s = silent, but --write-out 'format' gives us important response data
# The hairy "{ ...;rc=$?; } || :" lets us capture curl's exit code and
# give a helpful diagnostic if it fails.
- { response=$(curl -s -X $method ${curl_args} \
+ { response=$(curl -s -X $method "${curl_args[@]}" \
-H "Content-type: $content_type" \
--dump-header $WORKDIR/curl.headers.out \
--write-out '%{http_code}^%{content_type}^%{time_total}' \
@@ -289,8 +290,7 @@ function t() {
# Any error from curl is instant bad news, from which we can't recover
if [[ $rc -ne 0 ]]; then
- echo "FATAL: curl failure ($rc) on $url - cannot continue" >&2
- exit 1
+ die "curl failure ($rc) on $url - cannot continue"
fi
# Show returned headers (without trailing ^M or empty lines) in log file.
@@ -380,11 +380,6 @@ function start_service() {
die "Cannot start service on non-localhost ($HOST)"
fi
- 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
-# env CONTAINERS_REGISTRIES_CONF=$TESTS_DIR/../registries.conf
$PODMAN_BIN \
--root $WORKDIR/server_root --syslog=true \
system service \
@@ -411,15 +406,17 @@ REGISTRY_PORT=
REGISTRY_USERNAME=
REGISTRY_PASSWORD=
function start_registry() {
- # We can be invoked multiple times, e.g. from different subtests, but
- # let's assume that once started we only kill it at the end of tests.
+ # We can be called multiple times, but each time should start a new
+ # registry container with (possibly) different configuration. That
+ # means that all callers must be responsible for invoking stop_registry.
if [[ -n "$REGISTRY_PORT" ]]; then
- return
+ die "start_registry invoked twice in succession, without stop_registry"
fi
+ # First arg is auth type (default: "none", but can also be "htpasswd")
+ local auth="${1:-none}"
+
REGISTRY_PORT=$(random_port)
- REGISTRY_USERNAME=u$(random_string 7)
- REGISTRY_PASSWORD=p$(random_string 7)
local REGDIR=$WORKDIR/registry
local AUTHDIR=$REGDIR/auth
@@ -433,22 +430,33 @@ function start_registry() {
podman ${PODMAN_REGISTRY_ARGS} pull $REGISTRY_IMAGE ||
podman ${PODMAN_REGISTRY_ARGS} pull $REGISTRY_IMAGE
- # Create a local cert and credentials
- # FIXME: is there a hidden "--quiet" flag? This is too noisy.
- openssl req -newkey rsa:4096 -nodes -sha256 \
- -keyout $AUTHDIR/domain.key -x509 -days 2 \
- -out $AUTHDIR/domain.crt \
- -subj "/C=US/ST=Foo/L=Bar/O=Red Hat, Inc./CN=registry host certificate" \
- -addext subjectAltName=DNS:localhost
- htpasswd -Bbn ${REGISTRY_USERNAME} ${REGISTRY_PASSWORD} \
- > $AUTHDIR/htpasswd
+ # Create a local cert (no need to do this more than once)
+ if [[ ! -e $AUTHDIR/domain.key ]]; then
+ # FIXME: is there a hidden "--quiet" flag? This is too noisy.
+ openssl req -newkey rsa:4096 -nodes -sha256 \
+ -keyout $AUTHDIR/domain.key -x509 -days 2 \
+ -out $AUTHDIR/domain.crt \
+ -subj "/C=US/ST=Foo/L=Bar/O=Red Hat, Inc./CN=registry host certificate" \
+ -addext subjectAltName=DNS:localhost
+ fi
+
+ # If invoked with auth=htpasswd, create credentials
+ REGISTRY_USERNAME=
+ REGISTRY_PASSWORD=
+ if [[ "$auth" = "htpasswd" ]]; then
+ REGISTRY_USERNAME=u$(random_string 7)
+ REGISTRY_PASSWORD=p$(random_string 7)
+
+ htpasswd -Bbn ${REGISTRY_USERNAME} ${REGISTRY_PASSWORD} \
+ > $AUTHDIR/htpasswd
+ fi
# Run the registry, and wait for it to come up
podman ${PODMAN_REGISTRY_ARGS} run -d \
-p ${REGISTRY_PORT}:5000 \
--name registry \
-v $AUTHDIR:/auth:Z \
- -e "REGISTRY_AUTH=htpasswd" \
+ -e "REGISTRY_AUTH=$auth" \
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/auth/domain.crt \
@@ -462,13 +470,19 @@ function stop_registry() {
local REGDIR=${WORKDIR}/registry
if [[ -d $REGDIR ]]; then
local OPTS="--root ${REGDIR}/root --runroot ${REGDIR}/runroot"
- podman $OPTS stop -f -t 0 -a
+ podman $OPTS stop -i -t 0 registry
# rm/rmi are important when running rootless: without them we
# get EPERMS in tmpdir cleanup because files are owned by subuids.
- podman $OPTS rm -f -a
- podman $OPTS rmi -f -a
+ podman $OPTS rm -f -i registry
+ if [[ "$1" = "--cleanup" ]]; then
+ podman $OPTS rmi -f -a
+ fi
fi
+
+ REGISTRY_PORT=
+ REGISTRY_USERNAME=
+ REGISTRY_PASSWORD=
}
#################
diff --git a/test/buildah-bud/apply-podman-deltas b/test/buildah-bud/apply-podman-deltas
index e2ca45728..6ff564aaa 100755
--- a/test/buildah-bud/apply-podman-deltas
+++ b/test/buildah-bud/apply-podman-deltas
@@ -193,21 +193,12 @@ skip_if_remote "volumes don't work with podman-remote" \
"buildah bud --volume" \
"buildah-bud-policy"
-# Most of this should work in podman remote after API implementation other than where context is host.
skip_if_remote "--build-context option not implemented in podman-remote" \
- "build-with-additional-build-context and COPY, test pinning image" \
- "build-with-additional-build-context and COPY, stagename and additional-context conflict" \
- "build-with-additional-build-context and COPY, additionalContext and numeric value of stage" \
- "build-with-additional-build-context and COPY, additionalContext and numeric value of stage" \
"build-with-additional-build-context and COPY, additional context from host" \
- "build-with-additional-build-context and COPY, additional context from external URL" \
- "build-with-additional-build-context and RUN --mount=from=, additional-context is URL and mounted from subdir" \
"build-with-additional-build-context and RUN --mount=from=, additional-context not image and also test conflict with stagename" \
- "build-with-additional-build-context and RUN --mount=from=, additional-context and also test conflict with stagename" \
- "bud-multiple-platform for --all-platform with additional-build-context" \
- "build-with-additional-build-context and FROM, stagename and additional-context conflict" \
+
+skip_if_remote "env-variable for Containerfile.in pre-processing is not propogated on remote" \
"bud with Containerfile.in, via envariable" \
- "build-with-additional-build-context and FROM, pin busybox to alpine"
# Requires a local file outside context dir
skip_if_remote "local keyfile not sent to podman-remote" \
diff --git a/test/e2e/build_test.go b/test/e2e/build_test.go
index 86dc76116..0b766dcc8 100644
--- a/test/e2e/build_test.go
+++ b/test/e2e/build_test.go
@@ -85,7 +85,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/secret-verify-leak/Containerfile.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/secret-verify-leak"})
session.WaitWithDefaultTimeout()
Expect(session).Should(Exit(0))
Expect(session.OutputToString()).To(ContainSubstring("somesecret"))
diff --git a/test/e2e/logs_test.go b/test/e2e/logs_test.go
index 0d24a7e17..14dd6b6b8 100644
--- a/test/e2e/logs_test.go
+++ b/test/e2e/logs_test.go
@@ -8,6 +8,7 @@ import (
"time"
. "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"
@@ -370,6 +371,26 @@ var _ = Describe("Podman logs", func() {
Expect(results.OutputToString()).To(Equal("stdout"))
Expect(results.ErrorToString()).To(Equal("stderr"))
})
+
+ It("podman logs partial log lines: "+log, func() {
+ skipIfJournaldInContainer()
+
+ cname := "log-test"
+ content := stringid.GenerateNonCryptoID()
+ // use printf to print no extra newline
+ logc := podmanTest.Podman([]string{"run", "--log-driver", log, "--name", cname, ALPINE, "printf", content})
+ logc.WaitWithDefaultTimeout()
+ Expect(logc).To(Exit(0))
+ // Important: do not use OutputToString(), this will remove the trailing newline from the output.
+ // However this test must make sure that there is no such extra newline.
+ Expect(string(logc.Out.Contents())).To(Equal(content))
+
+ logs := podmanTest.Podman([]string{"logs", cname})
+ logs.WaitWithDefaultTimeout()
+ Expect(logs).To(Exit(0))
+ // see comment above
+ Expect(string(logs.Out.Contents())).To(Equal(content))
+ })
}
It("using journald for container with container tag", func() {
diff --git a/test/e2e/network_connect_disconnect_test.go b/test/e2e/network_connect_disconnect_test.go
index 019bb4617..c9ffe6a8d 100644
--- a/test/e2e/network_connect_disconnect_test.go
+++ b/test/e2e/network_connect_disconnect_test.go
@@ -2,7 +2,6 @@ package integration
import (
"os"
- "strings"
. "github.com/containers/podman/v4/test/utils"
"github.com/containers/storage/pkg/stringid"
@@ -94,7 +93,7 @@ var _ = Describe("Podman network connect and disconnect", func() {
exec2 := podmanTest.Podman([]string{"exec", "-it", "test", "cat", "/etc/resolv.conf"})
exec2.WaitWithDefaultTimeout()
Expect(exec2).Should(Exit(0))
- Expect(strings.Contains(exec2.OutputToString(), ns)).To(BeTrue())
+ Expect(exec2.OutputToString()).To(ContainSubstring(ns))
dis := podmanTest.Podman([]string{"network", "disconnect", netName, "test"})
dis.WaitWithDefaultTimeout()
@@ -113,7 +112,7 @@ var _ = Describe("Podman network connect and disconnect", func() {
exec3 := podmanTest.Podman([]string{"exec", "-it", "test", "cat", "/etc/resolv.conf"})
exec3.WaitWithDefaultTimeout()
Expect(exec3).Should(Exit(0))
- Expect(strings.Contains(exec3.OutputToString(), ns)).To(BeFalse())
+ Expect(exec3.OutputToString()).ToNot(ContainSubstring(ns))
// make sure stats still works https://github.com/containers/podman/issues/13824
stats := podmanTest.Podman([]string{"stats", "test", "--no-stream"})
@@ -211,7 +210,7 @@ var _ = Describe("Podman network connect and disconnect", func() {
exec2 := podmanTest.Podman([]string{"exec", "-it", "test", "cat", "/etc/resolv.conf"})
exec2.WaitWithDefaultTimeout()
Expect(exec2).Should(Exit(0))
- Expect(strings.Contains(exec2.OutputToString(), ns)).To(BeFalse())
+ Expect(exec2.OutputToString()).ToNot(ContainSubstring(ns))
ip := "10.11.100.99"
mac := "44:11:44:11:44:11"
@@ -240,7 +239,7 @@ var _ = Describe("Podman network connect and disconnect", func() {
exec3 := podmanTest.Podman([]string{"exec", "-it", "test", "cat", "/etc/resolv.conf"})
exec3.WaitWithDefaultTimeout()
Expect(exec3).Should(Exit(0))
- Expect(strings.Contains(exec3.OutputToString(), ns)).To(BeTrue())
+ Expect(exec3.OutputToString()).To(ContainSubstring(ns))
// make sure stats works https://github.com/containers/podman/issues/13824
stats := podmanTest.Podman([]string{"stats", "test", "--no-stream"})
diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go
index 31044f68b..61f2b3a1c 100644
--- a/test/e2e/play_kube_test.go
+++ b/test/e2e/play_kube_test.go
@@ -3688,7 +3688,7 @@ ENV OPENJ9_JAVA_OPTIONS=%q
})
// Check the block devices are exposed inside container
- It("ddpodman play kube expose block device inside container", func() {
+ It("podman play kube expose block device inside container", func() {
SkipIfRootless("It needs root access to create devices")
// randomize the folder name to avoid error when running tests with multiple nodes
@@ -3727,7 +3727,7 @@ ENV OPENJ9_JAVA_OPTIONS=%q
})
// Check the char devices are exposed inside container
- It("ddpodman play kube expose character device inside container", func() {
+ It("podman play kube expose character device inside container", func() {
SkipIfRootless("It needs root access to create devices")
// randomize the folder name to avoid error when running tests with multiple nodes
@@ -3781,7 +3781,7 @@ ENV OPENJ9_JAVA_OPTIONS=%q
Expect(kube).Should(Exit(125))
})
- It("ddpodman play kube reports error when we try to expose char device as block device", func() {
+ It("podman play kube reports error when we try to expose char device as block device", func() {
SkipIfRootless("It needs root access to create devices")
// randomize the folder name to avoid error when running tests with multiple nodes
@@ -3807,7 +3807,7 @@ ENV OPENJ9_JAVA_OPTIONS=%q
Expect(kube).Should(Exit(125))
})
- It("ddpodman play kube reports error when we try to expose block device as char device", func() {
+ It("podman play kube reports error when we try to expose block device as char device", func() {
SkipIfRootless("It needs root access to create devices")
// randomize the folder name to avoid error when running tests with multiple nodes
diff --git a/test/e2e/pod_create_test.go b/test/e2e/pod_create_test.go
index dedb1caeb..4919cc670 100644
--- a/test/e2e/pod_create_test.go
+++ b/test/e2e/pod_create_test.go
@@ -1112,4 +1112,26 @@ ENTRYPOINT ["sleep","99999"]
})
+ It("podman pod create infra inheritance test", func() {
+ volName := "testVol1"
+ volCreate := podmanTest.Podman([]string{"volume", "create", volName})
+ volCreate.WaitWithDefaultTimeout()
+ Expect(volCreate).Should(Exit(0))
+
+ session := podmanTest.Podman([]string{"pod", "create", "-v", volName + ":/vol1"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ volName2 := "testVol2"
+ volCreate = podmanTest.Podman([]string{"volume", "create", volName2})
+ volCreate.WaitWithDefaultTimeout()
+ Expect(volCreate).Should(Exit(0))
+
+ session = podmanTest.Podman([]string{"run", "--pod", session.OutputToString(), "-v", volName2 + ":/vol2", ALPINE, "mount"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.OutputToString()).Should(ContainSubstring("/vol1"))
+ Expect(session.OutputToString()).Should(ContainSubstring("/vol2"))
+ })
+
})
diff --git a/test/e2e/run_privileged_test.go b/test/e2e/run_privileged_test.go
index 4f0b512c6..dfaff7e67 100644
--- a/test/e2e/run_privileged_test.go
+++ b/test/e2e/run_privileged_test.go
@@ -131,6 +131,30 @@ var _ = Describe("Podman privileged container tests", func() {
Expect(len(session.OutputToStringArray())).To(BeNumerically(">", 20))
})
+ It("podman privileged should restart after host devices change", func() {
+ containerName := "privileged-restart-test"
+ SkipIfRootless("Cannot create devices in /dev in rootless mode")
+ Expect(os.MkdirAll("/dev/foodevdir", os.ModePerm)).To(BeNil())
+
+ mknod := SystemExec("mknod", []string{"/dev/foodevdir/null", "c", "1", "3"})
+ mknod.WaitWithDefaultTimeout()
+ Expect(mknod).Should(Exit(0))
+
+ session := podmanTest.Podman([]string{"run", "--name=" + containerName, "--privileged", "-it", fedoraMinimal, "ls", "/dev"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ deviceFiles := session.OutputToStringArray()
+
+ os.RemoveAll("/dev/foodevdir")
+ session = podmanTest.Podman([]string{"start", "--attach", containerName})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ deviceFilesAfterRemoval := session.OutputToStringArray()
+ Expect(deviceFiles).To(Not(Equal(deviceFilesAfterRemoval)))
+ })
+
It("run no-new-privileges test", func() {
// Check if our kernel is new enough
k, err := IsKernelNewerThan("4.14")
diff --git a/test/e2e/run_volume_test.go b/test/e2e/run_volume_test.go
index 3bef889b7..1c0480407 100644
--- a/test/e2e/run_volume_test.go
+++ b/test/e2e/run_volume_test.go
@@ -325,6 +325,51 @@ var _ = Describe("Podman run with volumes", func() {
})
+ It("podman support overlay volume with custom upperdir and workdir", func() {
+ SkipIfRemote("Overlay volumes only work locally")
+ if os.Getenv("container") != "" {
+ Skip("Overlay mounts not supported when running in a container")
+ }
+ if rootless.IsRootless() {
+ if _, err := exec.LookPath("fuse-overlayfs"); err != nil {
+ Skip("Fuse-Overlayfs required for rootless overlay mount test")
+ }
+ }
+
+ // Use bindsource instead of named volume
+ bindSource := filepath.Join(tempdir, "bindsource")
+ err := os.Mkdir(bindSource, 0755)
+ Expect(err).To(BeNil(), "mkdir "+bindSource)
+
+ // create persistent upperdir on host
+ upperDir := filepath.Join(tempdir, "upper")
+ err = os.Mkdir(upperDir, 0755)
+ Expect(err).To(BeNil(), "mkdir "+upperDir)
+
+ // create persistent workdir on host
+ workDir := filepath.Join(tempdir, "work")
+ err = os.Mkdir(workDir, 0755)
+ Expect(err).To(BeNil(), "mkdir "+workDir)
+
+ overlayOpts := fmt.Sprintf("upperdir=%s,workdir=%s", upperDir, workDir)
+
+ // create file on overlay volume
+ session := podmanTest.Podman([]string{"run", "--volume", bindSource + ":/data:O," + overlayOpts, ALPINE, "sh", "-c", "echo hello >> " + "/data/overlay"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+
+ session = podmanTest.Podman([]string{"run", "--volume", bindSource + ":/data:O," + overlayOpts, ALPINE, "sh", "-c", "ls /data"})
+ session.WaitWithDefaultTimeout()
+ // must contain `overlay` file since it should be persistent on specified upper and workdir
+ Expect(session.OutputToString()).To(ContainSubstring("overlay"))
+
+ session = podmanTest.Podman([]string{"run", "--volume", bindSource + ":/data:O", ALPINE, "sh", "-c", "ls /data"})
+ session.WaitWithDefaultTimeout()
+ // must not contain `overlay` file which was on custom upper and workdir since we have not specified any upper or workdir
+ Expect(session.OutputToString()).To(Not(ContainSubstring("overlay")))
+
+ })
+
It("podman run with noexec can't exec", func() {
session := podmanTest.Podman([]string{"run", "--rm", "-v", "/bin:/hostbin:noexec", ALPINE, "/hostbin/ls", "/"})
session.WaitWithDefaultTimeout()
diff --git a/test/system/170-run-userns.bats b/test/system/170-run-userns.bats
index 46cb37b9d..84788a7f4 100644
--- a/test/system/170-run-userns.bats
+++ b/test/system/170-run-userns.bats
@@ -111,15 +111,30 @@ EOF
}
@test "podman userns=nomap" {
- skip_if_not_rootless "--userns=nomap only works in rootless mode"
- ns_user=$(id -un)
- baseuid=$(egrep "${ns_user}:" /etc/subuid | cut -f2 -d:)
- test ! -z ${baseuid} || skip "no IDs allocated for user ${ns_user}"
+ if is_rootless; then
+ ns_user=$(id -un)
+ baseuid=$(egrep "${ns_user}:" /etc/subuid | cut -f2 -d:)
+ test ! -z ${baseuid} || skip "no IDs allocated for user ${ns_user}"
+
+ test_name="test_$(random_string 12)"
+ run_podman run -d --userns=nomap $IMAGE sleep 100
+ cid=${output}
+ run_podman top ${cid} huser
+ is "${output}" "HUSER.*${baseuid}" "Container should start with baseuid from /etc/subuid not user UID"
+ run_podman rm -t 0 --force ${cid}
+ else
+ run_podman 125 run -d --userns=nomap $IMAGE sleep 100
+ is "${output}" "Error: nomap is only supported in rootless mode" "Container should fail to start since nomap is not suppored in rootful mode"
+ fi
+}
- test_name="test_$(random_string 12)"
- run_podman run -d --userns=nomap $IMAGE sleep 100
- cid=${output}
- run_podman top ${cid} huser
- is "${output}" "HUSER.*${baseuid}" "Container should start with baseuid from /etc/subuid not user UID"
- run_podman rm -t 0 --force ${cid}
+@test "podman userns=keep-id" {
+ if is_rootless; then
+ user=$(id -u)
+ run_podman run --rm --userns=keep-id $IMAGE id -u
+ is "${output}" "$user" "Container should run as the current user"
+ else
+ run_podman 125 run --rm --userns=keep-id $IMAGE id -u
+ is "${output}" "Error: keep-id is only supported in rootless mode" "Container should fail to start since keep-id is not suppored in rootful mode"
+ fi
}
diff --git a/test/system/500-networking.bats b/test/system/500-networking.bats
index 3db0804d1..92aabae32 100644
--- a/test/system/500-networking.bats
+++ b/test/system/500-networking.bats
@@ -111,6 +111,10 @@ load helpers
$IMAGE nc -l -n -v -p $myport
cid="$output"
+ # check that podman stores the network info correctly when a userns is used (#14465)
+ run_podman container inspect --format "{{.NetworkSettings.SandboxKey}}" $cid
+ assert "$output" =~ ".*/netns/netns-.*" "Netns path should be set"
+
wait_for_output "listening on .*:$myport .*" $cid
# emit random string, and check it
diff --git a/test/system/520-checkpoint.bats b/test/system/520-checkpoint.bats
index c16a8c35d..7f60f01b3 100644
--- a/test/system/520-checkpoint.bats
+++ b/test/system/520-checkpoint.bats
@@ -170,4 +170,34 @@ function teardown() {
# FIXME: test --leave-running
+@test "podman checkpoint --file-locks" {
+ action='flock test.lock sh -c "while [ -e /wait ];do sleep 0.5;done;for i in 1 2 3;do echo \$i;sleep 0.5;done"'
+ run_podman run -d $IMAGE sh -c "touch /wait; touch test.lock; echo READY; $action & $action & wait"
+ local cid="$output"
+
+ # Wait for container to start emitting output
+ wait_for_ready $cid
+
+ # Checkpoint, and confirm via inspect
+ run_podman container checkpoint --file-locks $cid
+ is "$output" "$cid" "podman container checkpoint"
+
+ run_podman container inspect \
+ --format '{{.State.Status}}:{{.State.Running}}:{{.State.Paused}}:{{.State.Checkpointed}}' $cid
+ is "$output" "exited:false:false:true" "State. Status:Running:Pause:Checkpointed"
+
+ # Restart immediately and confirm state
+ run_podman container restore --file-locks $cid
+ is "$output" "$cid" "podman container restore"
+
+ # Signal the container to continue; this is where the 1-2-3s will come from
+ run_podman exec $cid rm /wait
+
+ # Wait for the container to stop
+ run_podman wait $cid
+
+ run_podman logs $cid
+ trim=$(sed -z -e 's/[\r\n]\+//g' <<<"$output")
+ is "$trim" "READY123123" "File lock restored"
+}
# vim: filetype=sh
diff --git a/test/system/600-completion.bats b/test/system/600-completion.bats
index 2de9b1ae1..cb4a2c5f8 100644
--- a/test/system/600-completion.bats
+++ b/test/system/600-completion.bats
@@ -341,7 +341,9 @@ function _check_no_suggestions() {
skip_if_remote "mounting via remote does not work"
for cmd in create run; do
run_completion $cmd $IMAGE ""
- assert "$output" =~ ".*^/etc\$.*^/home\$.*^/root\$.*" "root directories suggested (cmd: podman $cmd)"
+ assert "$output" =~ ".*^/etc/\$.*" "etc directory suggested (cmd: podman $cmd)"
+ assert "$output" =~ ".*^/home/\$.*" "home directory suggested (cmd: podman $cmd)"
+ assert "$output" =~ ".*^/root/\$.*" "root directory suggested (cmd: podman $cmd)"
# check completion for subdirectory
run_completion $cmd $IMAGE "/etc"
@@ -354,23 +356,31 @@ function _check_no_suggestions() {
# check completion with relative path components
# It is important the we will still use the image root and not escape to the host
run_completion $cmd $IMAGE "../../"
- assert "$output" =~ ".*^../../etc\$.*^../../home\$.*" "relative root directories suggested (cmd: podman $cmd ../../)"
+ assert "$output" =~ ".*^../../etc/\$.*" "relative etc directory suggested (cmd: podman $cmd ../../)"
+ assert "$output" =~ ".*^../../home/\$.*" "relative home directory suggested (cmd: podman $cmd ../../)"
done
random_name=$(random_string 30)
random_file=$(random_string 30)
- run_podman run --name $random_name $IMAGE touch /tmp/$random_file
+ run_podman run --name $random_name $IMAGE sh -c "touch /tmp/$random_file && touch /tmp/${random_file}2 && mkdir /emptydir"
# check completion for podman cp
run_completion cp ""
assert "$output" =~ ".*^$random_name\:\$.*" "podman cp suggest container names"
run_completion cp "$random_name:"
- assert "$output" =~ ".*^$random_name\:/etc\$.*" "podman cp suggest paths in container"
+ assert "$output" =~ ".*^$random_name\:/etc/\$.*" "podman cp suggest paths in container"
run_completion cp "$random_name:/tmp"
assert "$output" =~ ".*^$random_name\:/tmp/$random_file\$.*" "podman cp suggest custom file in container"
+ run_completion cp "$random_name:/tmp/$random_file"
+ assert "$output" =~ ".*^$random_name\:/tmp/$random_file\$.*" "podman cp suggest /tmp/$random_file file in container"
+ assert "$output" =~ ".*^$random_name\:/tmp/${random_file}2\$.*" "podman cp suggest /tmp/${random_file}2 file in container"
+
+ run_completion cp "$random_name:/emptydir"
+ assert "$output" =~ ".*^$random_name\:/emptydir/\$.*ShellCompDirectiveNoSpace" "podman cp suggest empty dir with no space directive (:2)"
+
# cleanup container
run_podman rm $random_name
}