Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CI: make systemd tests parallel-safe (*) #24048

Merged
merged 1 commit into from
Sep 24, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 72 additions & 50 deletions test/system/250-systemd.bats
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,29 @@
# Tests generated configurations for systemd.
#

# bats file_tags=ci:parallel

load helpers
load helpers.systemd
load helpers.network

SERVICE_NAME="podman_test_$(random_string)"
SERVICE_NAME=

UNIT_FILE="$UNIT_DIR/$SERVICE_NAME.service"
TEMPLATE_FILE="$UNIT_DIR/[email protected]"
UNIT_FILE=
TEMPLATE_FILE=

function setup() {
skip_if_remote "systemd tests are meaningless over remote"

SERVICE_NAME="podman-test-$(safename)"
UNIT_FILE="$UNIT_DIR/$SERVICE_NAME.service"
TEMPLATE_FILE="$UNIT_DIR/[email protected]"

basic_setup
}

function teardown() {
if [[ -e "$UNIT_FILE" ]]; then
if [[ -n "$UNIT_FILE" ]] && [[ -e "$UNIT_FILE" ]]; then
run systemctl stop "$SERVICE_NAME"
if [ $status -ne 0 ]; then
echo "# WARNING: systemctl stop failed in teardown: $output" >&3
Expand All @@ -32,6 +38,20 @@ function teardown() {
basic_teardown
}

# Helper to atomically create a systemd unit file from a tmpfile
#
# Context:
# $1 - file created by podman generate systemd; presumed to be in a tmpdir
# $2 - desired service file path, presumed to be in /run
#
# We can't just mv one to the other, because mv is not atomic across
# filesystems. (We need atomic, to guarantee that there will never
# be an incomplete .service file). Hence the tmp extension.
# -Z is because /run and $TMPDIR have different SELinux contexts.
function mv-safely() {
mv -Z "$1" "$2.tmp.$$" && mv -Z "$2.tmp.$$" "$2"
}

# Helper to start a systemd service running a container
function service_setup() {
# January 2024: we can no longer do "run_podman generate systemd" followed
Expand All @@ -40,12 +60,12 @@ function service_setup() {
# stdout + stderr, that warning goes to the unit file. (Today's systemd
# is forgiving about that, but RHEL8 systemd chokes with EINVAL)
(
cd $UNIT_DIR
cd $PODMAN_TMPDIR
run_podman generate systemd --files --name \
-e http_proxy -e https_proxy -e no_proxy \
-e HTTP_PROXY -e HTTPS_PROXY -e NO_PROXY \
--new $cname
mv "container-$cname.service" $UNIT_FILE
mv-safely "container-$cname.service" $UNIT_FILE
)
run_podman rm $cname

Expand Down Expand Up @@ -92,7 +112,7 @@ function service_cleanup() {
"generate systemd emits warning"
run_podman rm -f $cid

cname=$(random_string)
cname=c-$(safename)
# See #7407 for --pull=always.
run_podman create --pull=always --name $cname --label "io.containers.autoupdate=registry" $IMAGE \
sh -c "trap 'echo Received SIGTERM, finishing; exit' SIGTERM; echo WAITING; while :; do sleep 0.1; done"
Expand All @@ -112,10 +132,10 @@ function service_cleanup() {

@test "podman autoupdate local" {
# Note that the entrypoint may be a JSON string which requires preserving the quotes (see #12477)
cname=$(random_string)
cname=c-$(safename)

# Create a scratch image (copy of our regular one)
image_copy=base$(random_string | tr A-Z a-z)
image_copy=base-$(safename)
run_podman tag $IMAGE $image_copy

# Create a container based on that
Expand All @@ -140,7 +160,7 @@ function service_cleanup() {
# These tests can fail in dev. environment because of SELinux.
# quick fix: chcon -t container_runtime_exec_t ./bin/podman
@test "podman generate systemd - envar" {
cname=$(random_string)
cname=c-$(safename)
FOO=value BAR=%s run_podman create --name $cname --env FOO -e BAR --env MYVAR=myval \
$IMAGE sh -c 'printenv && echo READY; trap 'exit' SIGTERM; while :; do sleep 0.1; done'

Expand All @@ -162,19 +182,19 @@ function service_cleanup() {

# Regression test for #11438
@test "podman generate systemd - restart policy & timeouts" {
cname=$(random_string)
cname=c1-$(safename)
run_podman create --restart=always --name $cname $IMAGE
run_podman generate systemd --new $cname
is "$output" ".*Restart=always.*" "Use container's restart policy if set"
run_podman generate systemd --new --restart-policy=on-failure $cname
is "$output" ".*Restart=on-failure.*" "Override container's restart policy"

cname2=$(random_string)
cname2=c2-$(safename)
run_podman create --restart=unless-stopped --name $cname2 $IMAGE
run_podman generate systemd --new $cname2
is "$output" ".*Restart=always.*" "unless-stopped translated to always"

cname3=$(random_string)
cname3=c3-$(safename)
run_podman create --restart=on-failure:42 --name $cname3 $IMAGE
run_podman generate systemd --new $cname3
is "$output" ".*Restart=on-failure.*" "on-failure:xx is parsed correctly"
Expand Down Expand Up @@ -230,14 +250,14 @@ LISTEN_FDNAMES=listen_fdnames" | sort)
}

@test "podman generate - systemd template" {
cname=$(random_string)
cname=c-$(safename)
run_podman create --name $cname $IMAGE top

# See note in service_setup() above re: using --files
(
cd $UNIT_DIR
cd $PODMAN_TMPDIR
run_podman generate systemd --template --files -n $cname
mv "container-$cname.service" $TEMPLATE_FILE
mv-safely "container-$cname.service" $TEMPLATE_FILE
)
run_podman rm -f $cname

Expand All @@ -257,8 +277,8 @@ LISTEN_FDNAMES=listen_fdnames" | sort)
}

@test "podman generate - systemd template no support for pod" {
cname=$(random_string)
podname=$(random_string)
cname=c-$(safename)
podname=p-$(safename)
run_podman pod create --name $podname
run_podman run --pod $podname -dt --name $cname $IMAGE top

Expand All @@ -267,11 +287,10 @@ LISTEN_FDNAMES=listen_fdnames" | sort)

run_podman rm -f $cname
run_podman pod rm -f $podname
run_podman rmi $(pause_image)
}

@test "podman generate - systemd template only used on --new" {
cname=$(random_string)
cname=c-$(safename)
run_podman create --name $cname $IMAGE top
run_podman 125 generate systemd --new=false --template -n $cname
is "$output" ".*--template cannot be set" "Error message should be '--template requires --new'"
Expand All @@ -284,11 +303,12 @@ LISTEN_FDNAMES=listen_fdnames" | sort)
}

@test "podman --systemd sets container_uuid" {
run_podman run --systemd=always --name test $IMAGE printenv container_uuid
cname=c-$(safename)
run_podman run --systemd=always --name $cname $IMAGE printenv container_uuid
container_uuid=$output
run_podman inspect test --format '{{ .ID }}'
run_podman inspect $cname --format '{{ .ID }}'
is "${container_uuid}" "${output:0:32}" "UUID should be first 32 chars of Container id"
run_podman rm test
run_podman rm $cname
}

@test "podman --systemd fails on cgroup v1 with a private cgroupns" {
Expand All @@ -302,8 +322,8 @@ LISTEN_FDNAMES=listen_fdnames" | sort)
@test "podman rootless-netns processes should be in different cgroup" {
is_rootless || skip "only meaningful for rootless"

cname=$(random_string)
local netname=testnet-$(random_string 10)
cname=c-$(safename)
local netname=testnet-$(safename)

# create network and container with network
run_podman network create $netname
Expand All @@ -313,7 +333,7 @@ LISTEN_FDNAMES=listen_fdnames" | sort)
service_setup

# run second container with network
cname2=$(random_string)
cname2=c2-$(safename)
run_podman run -d --name $cname2 --network $netname $IMAGE top

# stop systemd container
Expand All @@ -332,7 +352,7 @@ LISTEN_FDNAMES=listen_fdnames" | sort)
}

@test "podman create --health-on-failure=kill" {
cname=c_$(random_string)
cname=c-$(safename)
run_podman create --name $cname \
--health-cmd /home/podman/healthcheck \
--health-on-failure=kill \
Expand Down Expand Up @@ -387,30 +407,33 @@ LISTEN_FDNAMES=listen_fdnames" | sort)
install_kube_template
# Create the YAMl file
yaml_source="$PODMAN_TMPDIR/test.yaml"
podname=p-$(safename)
c1=c1-$(safename)
c2=c2-$(safename)
cat >$yaml_source <<EOF
apiVersion: v1
kind: Pod
metadata:
annotations:
io.containers.autoupdate: "local"
io.containers.autoupdate/b: "registry"
io.containers.autoupdate/$c2: "registry"
labels:
app: test
name: test_pod
name: $podname
spec:
containers:
- command:
- sh
- -c
- echo a stdout; echo a stderr 1>&2; trap 'exit' SIGTERM; while :; do sleep 0.1; done
- echo c1 stdout; echo c1 stderr 1>&2; trap 'exit' SIGTERM; while :; do sleep 0.1; done
image: $IMAGE
name: a
name: $c1
- command:
- sh
- -c
- echo b stdout; echo b stderr 1>&2; trap 'exit' SIGTERM; while :; do sleep 0.1; done
- echo c2 stdout; echo c2 stderr 1>&2; trap 'exit' SIGTERM; while :; do sleep 0.1; done
image: $IMAGE
name: b
name: $c2
EOF

# Dispatch the YAML file
Expand All @@ -436,29 +459,29 @@ EOF
is "$output" "Error: container .* is the service container of pod(s) .* and cannot be removed without removing the pod(s)"

# containers/podman/issues/17482: verify that the log-driver for the Pod's containers is NOT passthrough
for name in "a" "b"; do
run_podman container inspect test_pod-${name} --format "{{.HostConfig.LogConfig.Type}}"
for name in "c1" "c2"; do
run_podman container inspect ${podname}-${!name} --format "{{.HostConfig.LogConfig.Type}}"
assert $output != "passthrough"
# check that we can get the logs with passthrough when we run in a systemd unit
run_podman logs test_pod-$name
run_podman logs ${podname}-${!name}
assert "$output" == "$name stdout
$name stderr" "logs work with passthrough"
done

# we cannot assume the ordering between a b, this depends on timing and would flake in CI
# use --names so we do not have to get the ID
run_podman pod logs --names test_pod
assert "$output" =~ ".*^test_pod-a a stdout.*" "logs from container a shown"
assert "$output" =~ ".*^test_pod-b b stdout.*" "logs from container b shown"
run_podman pod logs --names $podname
assert "$output" =~ ".*^${podname}-${c1} c1 stdout.*" "logs from container 1 shown"
assert "$output" =~ ".*^${podname}-${c2} c2 stdout.*" "logs from container 2 shown"

# Add a simple `auto-update --dry-run` test here to avoid too much redundancy
# with 255-auto-update.bats
run_podman auto-update --dry-run --format "{{.Unit}},{{.Container}},{{.Image}},{{.Updated}},{{.Policy}}"
is "$output" ".*$service_name,.* (test_pod-a),$IMAGE,false,local.*" "global auto-update policy gets applied"
is "$output" ".*$service_name,.* (test_pod-b),$IMAGE,false,registry.*" "container-specified auto-update policy gets applied"
is "$output" ".*$service_name,.* (${podname}-${c1}),$IMAGE,false,local.*" "global auto-update policy gets applied"
is "$output" ".*$service_name,.* (${podname}-${c2}),$IMAGE,false,registry.*" "container-specified auto-update policy gets applied"

# Kill the pod and make sure the service is not running.
run_podman pod kill test_pod
run_podman pod kill $podname
for i in {0..20}; do
# echos are for debugging test flakes
echo "$_LOG_PROMPT systemctl is-active $service_name"
Expand All @@ -481,26 +504,25 @@ $name stderr" "logs work with passthrough"
# Clean up
systemctl stop $service_name
run_podman 1 container exists $service_container
run_podman 1 pod exists test_pod
run_podman rmi $(pause_image)
run_podman network rm podman-default-kube-network
rm -f $UNIT_DIR/$unit_name
run_podman 1 pod exists $podname
}

@test "podman generate - systemd - DEPRECATED" {
run_podman generate systemd --help
is "$output" ".*[DEPRECATED] command:"
is "$output" ".*\[DEPRECATED\] Generate systemd units.*"
run_podman create --name test $IMAGE
run_podman generate systemd test >/dev/null

cname=c-$(safename)
run_podman create --name $cname $IMAGE
run_podman generate systemd $cname >/dev/null
is "$output" ".*[DEPRECATED] command:"
run_podman generate --help
is "$output" ".*\[DEPRECATED\] Generate systemd units"
run_podman rm test
run_podman rm $cname
}

@test "podman passes down the KillSignal and StopTimeout setting" {
ctr=systemd_test_$(random_string 5)
ctr=systemd_test_$(safename)

run_podman run -d --name $ctr --stop-signal 5 --stop-timeout 7 --rm $IMAGE top
run_podman inspect $ctr --format '{{ .Id }}'
Expand Down