c0bef0d989
-r/--run mounts an image, runs a command under bwrap in the foreground (default /bin/sh, overridable via -- <command> [args...]), then unmounts and cleans up when it exits. -c/--cleanup deletes a layer and its ancestor chain from local storage (containers-storage delete-layer, walking parents via `layer --json`), since -u only ever unmounted. bwrap needs to see the merged mount from inside the private namespace containers-storage mount creates when running rootless; run_bwrap() locates the live fuse-overlayfs process and runs bwrap via nsenter into its namespaces. When running as root no such namespace exists (containers-storage doesn't need to reexec for privilege), so nsenter fails with EINVAL; detect geteuid() == 0 and skip it automatically there. -n/--no-nsenter forces it off manually for any other case. process.cpp gains run_process_foreground() (inherited stdio, for the interactive bwrap run) and the relocated find_in_path(), now shared with bwrap.cpp's nsenter lookup. Also: meson test only ran -m, leaking a layer on every run; it now runs tests/run_test.py, which drives mount -> umount -> cleanup and fails if any step does. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
40 lines
1.1 KiB
Python
40 lines
1.1 KiB
Python
#!/usr/bin/env python3
|
|
"""Runs the mount -> umount -> cleanup cycle against the fixture image and checks
|
|
that every step succeeds, so `meson test` doesn't leak a layer on every run.
|
|
"""
|
|
|
|
import re
|
|
import subprocess
|
|
import sys
|
|
|
|
|
|
def run(slocker_lite: str, *args: str) -> subprocess.CompletedProcess:
|
|
return subprocess.run([slocker_lite, *args], capture_output=True, text=True)
|
|
|
|
|
|
def main() -> int:
|
|
slocker_lite, fixture_tar = sys.argv[1], sys.argv[2]
|
|
|
|
mount = run(slocker_lite, "-m", fixture_tar)
|
|
if mount.returncode != 0:
|
|
print(mount.stderr, file=sys.stderr)
|
|
return mount.returncode
|
|
|
|
match = re.search(r"\(layer (\S+)\)", mount.stdout)
|
|
if not match:
|
|
print(f"could not find layer ID in mount output: {mount.stdout!r}", file=sys.stderr)
|
|
return 1
|
|
layer_id = match.group(1)
|
|
|
|
for args in (("-u", layer_id), ("-c", layer_id)):
|
|
result = run(slocker_lite, *args)
|
|
if result.returncode != 0:
|
|
print(result.stderr, file=sys.stderr)
|
|
return result.returncode
|
|
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|