diff --git a/data/containers/bats/skip.yaml b/data/containers/bats/skip.yaml index dbb49350280b..24af553b12f5 100644 --- a/data/containers/bats/skip.yaml +++ b/data/containers/bats/skip.yaml @@ -188,11 +188,13 @@ podman: # https://github.com/containers/podman/pull/26798 is needed for 505-networking-pasta # https://github.com/containers/podman/pull/26920 is needed to drop ncat # https://github.com/containers/podman/pull/26921 is needed to drop socat + # https://github.com/containers/podman/pull/26934 - test/e2e: fix 'block all syscalls' seccomp for runc # https://github.com/containers/podman/pull/27152 is needed for 030-run opensuse-Tumbleweed: GITHUB_PATCHES: - 26017 - 26798 + - 26934 - 27152 BATS_IGNORE: BATS_IGNORE_ROOT_LOCAL: diff --git a/data/containers/patches/podman/26934.patch b/data/containers/patches/podman/26934.patch new file mode 100644 index 000000000000..48d59ca0ca9b --- /dev/null +++ b/data/containers/patches/podman/26934.patch @@ -0,0 +1,84 @@ +From 18b5b2e2d699551dab8fb25c9969d231d5662513 Mon Sep 17 00:00:00 2001 +From: Kir Kolyshkin +Date: Fri, 29 Aug 2025 17:18:44 -0700 +Subject: [PATCH] test/e2e: fix 'block all syscalls' seccomp for runc + +Error messages between runc and crun are not synchronized, and +in some case exit codes can be different, too. + +Commit dd1bcabae9 ("CI: use local registry, part 2 of 3: fix tests") +removed the special case handling for runc from the +"podman run --seccomp-policy image (block all syscalls)" +test case, and so it fails, for example, like this: + + Error: failed to connect to container's attach socket: /tmp/podman-e2e-2877753109/subtest-1698249469/p/root/overlay-containers/62585e98da7dc3fdb32d3b6de0980c762a8a6cde008ed35c68727fb97f5369c7/userdata/attach: no such file or directory + [FAILED] Command exited with status 127 (expected 126) + +or this: + + time="2025-08-29T17:16:52-07:00" level=error msg="cannot start a container that has stopped" + Error: `/usr/bin/runc start 63ce789f7037d9545cde832d29343704cab842e7288046407d0efa347d5ecb77` failed: exit status 1 + [FAILED] Command exited 126 as expected, but did not emit 'OCI runtime error: runc: read from the init process' + +(depending on runc version, phase of the moon etc.) + +We can not reasonably expect a specific error message and exit code in +such an unusual scenario, but let's try. + +With this commit, the above test passes successfully on my machine. + +Tested with: + + make localintegration FOCUS="block all syscalls" OCI_RUNTIME=/usr/local/bin/runc + make remoteintegration FOCUS="block all syscalls" OCI_RUNTIME=/usr/local/bin/runc + +While at it, simplify the error message check for crun (we don't have to +check for the entire message, [the same] substring is fine for both +local and remote cases). + +Fixes: dd1bcabae9 ("CI: use local registry, part 2 of 3: fix tests") +Reported-by: Yiqiao Pu +Signed-off-by: Kir Kolyshkin +--- + test/e2e/run_seccomp_test.go | 20 +++++++++++++++----- + 1 file changed, 15 insertions(+), 5 deletions(-) + +diff --git a/test/e2e/run_seccomp_test.go b/test/e2e/run_seccomp_test.go +index 82a7a42831..ada74b071f 100644 +--- a/test/e2e/run_seccomp_test.go ++++ b/test/e2e/run_seccomp_test.go +@@ -3,7 +3,7 @@ + package integration + + import ( +- "fmt" ++ "path" + + . "github.com/containers/podman/v5/test/utils" + . "github.com/onsi/ginkgo/v2" +@@ -55,11 +55,21 @@ var _ = Describe("Podman run", func() { + session := podmanTest.Podman([]string{"run", "--seccomp-policy", "image", img, "ls"}) + session.WaitWithDefaultTimeout() + +- expect := fmt.Sprintf("OCI runtime error: %s: read from the init process", podmanTest.OCIRuntime) +- if IsRemote() { +- expect = fmt.Sprintf("for attach: %s: read from the init process: OCI runtime error", podmanTest.OCIRuntime) ++ switch path.Base(podmanTest.OCIRuntime) { ++ case "crun": ++ // "crun create" fails with "read from the init process" error. ++ Expect(session).To(ExitWithError(126, "read from the init process")) ++ case "runc": ++ // "runc create" succeeds, then... ++ Expect(session).To(Or( ++ // either "runc start" fails with "cannot start a container that has stopped", ++ ExitWithError(126, "cannot start a container that has stopped"), ++ // or podman itself fails with "failed to connect to container's attach socket". ++ ExitWithError(127, "failed to connect to container's attach socket"), ++ )) ++ default: ++ Expect(session.ExitCode()).To(BeNumerically(">", 0), "Exit status using generic runtime") + } +- Expect(session).To(ExitWithError(126, expect)) + }) + + It("podman run --seccomp-policy image (bogus profile)", func() { diff --git a/tests/containers/README.md b/tests/containers/README.md index 25c2ff3ed869..65dbecc022e8 100644 --- a/tests/containers/README.md +++ b/tests/containers/README.md @@ -7,7 +7,8 @@ In addition to the [BATS](bats/) tests we currently have tests for: | --- | --- | | [docker-compose](docker_compose.pm) | https://github.com/docker/compose/tree/main/pkg/e2e | | [docker-py](python_runtime.pm) | https://github.com/docker/docker-py/tree/main/tests | -| [podman-py](python_runtime.pm) | https://github.com/containers/podman-py | +| [podman-py](python_runtime.pm) | https://github.com/containers/podman-py/tree/main/podman/tests | +| [podman](podman_e2e.pm) | https://github.com/containers/podman/tree/main/test/e2e | Library code is found in [lib/containers/bats.pm](../../../lib/containers/bats.pm) @@ -31,7 +32,7 @@ Note: These jobs are scheduled only for the x86_64 architecture. Notes: - `docker_testsuite` tests `docker-compose` & `docker-py` -- `podman_e2e` tests `podman-py` & the upcoming e2e tests. +- `podman_e2e` tests `podman-py` & `podman` (e2e) [logo]: bats/logo.svg diff --git a/tests/containers/podman_e2e.pm b/tests/containers/podman_e2e.pm new file mode 100644 index 000000000000..1ac469a4051a --- /dev/null +++ b/tests/containers/podman_e2e.pm @@ -0,0 +1,112 @@ +# SUSE's openQA tests +# +# Copyright SUSE LLC +# SPDX-License-Identifier: FSFAP + +# Packages: python3-docker & python3-podman +# Summary: Test podman & docker python packages +# Maintainer: QE-C team + +use Mojo::Base 'containers::basetest', -signatures; +use testapi; +use serial_terminal qw(select_serial_terminal); +use power_action_utils 'power_action'; +use version_utils; +use utils; +use containers::common qw(install_packages); +use containers::bats; + +my $oci_runtime; +my $version; + +sub setup { + my $self = shift; + my @pkgs = qw(aardvark-dns apache2-utils buildah catatonit glibc-devel-static go1.24 gpg2 jq libgpgme-devel + libseccomp-devel make netavark openssl podman podman-remote skopeo socat sudo systemd-container xfsprogs); + push @pkgs, qw(criu libcriu2) unless is_sle; + $oci_runtime = get_var("OCI_RUNTIME", "runc"); + push @pkgs, $oci_runtime; + + $self->setup_pkgs(@pkgs); + select_serial_terminal; + + record_info "info", script_output("podman info -f json"); + record_info("OCI runtime", script_output("$oci_runtime --version")); + + # Workaround for https://bugzilla.opensuse.org/show_bug.cgi?id=1248988 - catatonit missing in /usr/libexec/podman/ + run_command "cp -f /usr/bin/catatonit /usr/libexec/podman/catatonit"; + # rootless user needed for these tests + run_command "useradd -m containers"; + run_command "usermod --add-subuids 100000-165535 containers"; + run_command "usermod --add-subgids 100000-165535 containers"; + # Make /run/secrets directory available on containers + run_command "echo /var/lib/empty:/run/secrets >> /etc/containers/mounts.conf"; + + $version = script_output q(podman --version | awk '{ print $3 }'); + record_info "version", $version; + $version = "v$version"; + + # Download podman sources + patch_sources "podman", $version, "test/e2e"; + # This test fails with: + # Command exited 125 as expected, but did not emit 'failed to connect: dial tcp: lookup ' + run_command "rm -f test/e2e/image_scp_test.go"; + + assert_script_run "curl -o /usr/local/bin/patch_junit " . data_url("containers/patch_junit.py"); + assert_script_run "chmod +x /usr/local/bin/patch_junit"; +} + +sub run { + my ($self, $args) = @_; + select_serial_terminal; + + $self->setup; + select_serial_terminal; + + assert_script_run "cd /var/tmp/podman"; + + my $quadlet = script_output "rpm -ql podman | grep podman/quadlet"; + + my %env = ( + OCI_RUNTIME => $oci_runtime, + PODMAN_BINARY => "/usr/bin/podman", + PODMAN_REMOTE_BINARY => "/usr/bin/podman-remote", + QUADLET_BINARY => "/usr/libexec/podman/quadlet", + TESTFLAGS => "--junit-report=report.xml", + ); + my $env = join " ", map { "$_=$env{$_}" } sort keys %env; + + # mapping of known expected failures + my @xfails = (); + unless (is_tumbleweed) { + # Fixed in podman 5.6.1: + # https://bugzilla.suse.com/show_bug.cgi?id=1249050 - podman passes volume options as bind mount options to runtime + push @xfails, ( + 'localintegration::[It] Podman run with volumes podman run with --mount and named volume with driver-opts', + 'remoteintegration::[It] Podman run with volumes podman run with --mount and named volume with driver-opts', + 'localintegration::[It] Podman run with volumes podman named volume copyup', + 'remoteintegration::[It] Podman run with volumes podman named volume copyup', + ); + } + + my @targets = split('\s+', get_var('PODMAN_TARGETS', 'localintegration remoteintegration')); + foreach my $target (@targets) { + run_command "env $env make $target &> $target.txt || true", timeout => 1800; + script_run "mv report.xml $target.xml"; + my $xfails = join(' ', map { "\"$_\"" } @xfails); + assert_script_run "patch_junit $target.xml $xfails"; + patch_junit "podman", $version, "$target.xml"; + parse_extra_log(XUnit => "$target.xml"); + upload_logs("$target.txt"); + } +} + +sub post_fail_hook { + bats_post_hook; +} + +sub post_run_hook { + bats_post_hook; +} + +1;