fix(macos): install passt for podman 5 rootless networking
test / integration-docker (pull_request) Successful in 21s
lint / lint (push) Successful in 56s
test / unit (pull_request) Successful in 1m51s
test / integration-firecracker (pull_request) Successful in 3m30s
test / coverage (pull_request) Successful in 22s
test / publish-infra (pull_request) Has been skipped
tracker-policy-pr / check-pr (pull_request) Failing after 13m15s
test / integration-docker (pull_request) Successful in 21s
lint / lint (push) Successful in 56s
test / unit (pull_request) Successful in 1m51s
test / integration-firecracker (pull_request) Successful in 3m30s
test / coverage (pull_request) Successful in 22s
test / publish-infra (pull_request) Has been skipped
tracker-policy-pr / check-pr (pull_request) Failing after 13m15s
podman 5 uses pasta as the default rootless network helper; podman 4
used slirp4netns. The spike was written against bookworm's podman 4.3.1,
so its package list never included passt — and the trixie bump (#451)
changed the default out from under it. Every nested container failed to
start with "could not find pasta", while image pulls and the service
itself worked, which disguised a missing dependency as a compat-API bug.
The bootstrap now checks for pasta up front so this fails with a clear
message instead of surfacing at the first `docker run`.
Note the sun_path fix in a12d2191 did NOT cause or cure this; that path
was over the 108-byte limit independently and would have bitten as soon
as attach was reached.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -7,7 +7,10 @@ if [ "$uid" -eq 0 ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for command in podman docker fuse-overlayfs slirp4netns; do
|
# pasta is podman 5's default rootless network helper. Checked here so a
|
||||||
|
# missing package fails the bootstrap with a clear message rather than
|
||||||
|
# letting every later `docker run` die with "could not find pasta".
|
||||||
|
for command in podman docker fuse-overlayfs pasta slirp4netns; do
|
||||||
command -v "$command" >/dev/null 2>&1 || {
|
command -v "$command" >/dev/null 2>&1 || {
|
||||||
echo "missing nested-container prerequisite: $command" >&2
|
echo "missing nested-container prerequisite: $command" >&2
|
||||||
exit 1
|
exit 1
|
||||||
|
|||||||
@@ -41,10 +41,9 @@ _INIT = "/usr/local/libexec/bot-bottle/nested-containers-init"
|
|||||||
# Deliberately cryptic and short. podman derives conmon's attach socket as
|
# Deliberately cryptic and short. podman derives conmon's attach socket as
|
||||||
# `$XDG_RUNTIME_DIR/libpod/tmp/socket/<64-hex-id>/attach`, and a Unix socket
|
# `$XDG_RUNTIME_DIR/libpod/tmp/socket/<64-hex-id>/attach`, and a Unix socket
|
||||||
# path may not exceed 108 bytes (`sun_path`). The descriptive
|
# path may not exceed 108 bytes (`sun_path`). The descriptive
|
||||||
# `/tmp/bot-bottle-podman-run` produced a 116-byte path, so every attached
|
# `/tmp/bot-bottle-podman-run` produced a 116-byte path — over the limit, so
|
||||||
# `docker run` failed with "unable to upgrade to tcp, received 500" while
|
# attach would have broken as soon as anything got far enough to attach. Do
|
||||||
# detached runs and image pulls worked fine. Do not lengthen this for
|
# not lengthen this for readability; it buys 8 bytes of headroom.
|
||||||
# readability — it buys 8 bytes of headroom over the limit.
|
|
||||||
_RUNTIME_DIR = "/tmp/bbp"
|
_RUNTIME_DIR = "/tmp/bbp"
|
||||||
_SOCKET = f"{_RUNTIME_DIR}/podman.sock"
|
_SOCKET = f"{_RUNTIME_DIR}/podman.sock"
|
||||||
_LOG = "/tmp/bot-bottle-nested-containers.log"
|
_LOG = "/tmp/bot-bottle-nested-containers.log"
|
||||||
@@ -83,8 +82,12 @@ def build_image(
|
|||||||
"COPY --from=docker_cli /usr/local/libexec/docker/cli-plugins/"
|
"COPY --from=docker_cli /usr/local/libexec/docker/cli-plugins/"
|
||||||
"docker-compose /usr/local/libexec/docker/cli-plugins/docker-compose\n"
|
"docker-compose /usr/local/libexec/docker/cli-plugins/docker-compose\n"
|
||||||
"RUN apt-get update \\\n"
|
"RUN apt-get update \\\n"
|
||||||
|
# passt provides `pasta`, which podman 5 uses by default for
|
||||||
|
# rootless networking (podman 4 defaulted to slirp4netns). Without
|
||||||
|
# it every container fails to start with "could not find pasta".
|
||||||
|
# slirp4netns stays as the documented fallback.
|
||||||
" && apt-get install -y --no-install-recommends "
|
" && apt-get install -y --no-install-recommends "
|
||||||
"fuse-overlayfs slirp4netns uidmap \\\n"
|
"fuse-overlayfs passt slirp4netns uidmap \\\n"
|
||||||
" && rm -rf /var/lib/apt/lists/* \\\n"
|
" && rm -rf /var/lib/apt/lists/* \\\n"
|
||||||
# Deliberate: an empty subordinate range keeps podman on the
|
# Deliberate: an empty subordinate range keeps podman on the
|
||||||
# single-UID mapping that needs no CAP_SYS_ADMIN. Adding ranges
|
# single-UID mapping that needs no CAP_SYS_ADMIN. Adding ranges
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ class TestNestedContainersImage(unittest.TestCase):
|
|||||||
calls.append((image, context, dockerfile))
|
calls.append((image, context, dockerfile))
|
||||||
text = Path(dockerfile).read_text(encoding="utf-8")
|
text = Path(dockerfile).read_text(encoding="utf-8")
|
||||||
self.assertIn("FROM agent:base", text)
|
self.assertIn("FROM agent:base", text)
|
||||||
self.assertIn("fuse-overlayfs slirp4netns uidmap", text)
|
self.assertIn("fuse-overlayfs passt slirp4netns uidmap", text)
|
||||||
self.assertIn("USER node", text)
|
self.assertIn("USER node", text)
|
||||||
self.assertTrue((Path(context) / "nested-containers-init.sh").is_file())
|
self.assertTrue((Path(context) / "nested-containers-init.sh").is_file())
|
||||||
|
|
||||||
@@ -116,6 +116,19 @@ class TestNestedContainersImage(unittest.TestCase):
|
|||||||
self.assertEqual("agent:base-nested-containers", image)
|
self.assertEqual("agent:base-nested-containers", image)
|
||||||
self.assertEqual("agent:base-nested-containers", calls[0][0])
|
self.assertEqual("agent:base-nested-containers", calls[0][0])
|
||||||
|
|
||||||
|
def test_installs_pasta_for_podman_5_rootless_networking(self) -> None:
|
||||||
|
"""podman 5 defaults to pasta where podman 4 used slirp4netns. Without
|
||||||
|
the passt package every nested container fails to start with "could
|
||||||
|
not find pasta" — pulls still work, which makes it look like a
|
||||||
|
compat-API bug rather than a missing dependency."""
|
||||||
|
seen: list[str] = []
|
||||||
|
|
||||||
|
def build(_image: str, _context: str, *, dockerfile: str) -> None:
|
||||||
|
seen.append(Path(dockerfile).read_text(encoding="utf-8"))
|
||||||
|
|
||||||
|
nested_containers.build_image("agent:base", build)
|
||||||
|
self.assertIn("passt", seen[0])
|
||||||
|
|
||||||
def test_strips_subordinate_ranges_so_podman_avoids_newuidmap(self) -> None:
|
def test_strips_subordinate_ranges_so_podman_avoids_newuidmap(self) -> None:
|
||||||
"""The single-UID fallback is the entire reason podman works here.
|
"""The single-UID fallback is the entire reason podman works here.
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user