#!/usr/bin/env python3 """Fetches a real, runnable busybox OCI Image Layout tar for the [integration][net] test categories (tests/support/fixtures.h's find_busybox_fixture() looks for it at images/busybox.tar, relative to the repo root -- the same directory this project's own manual testing has always used, see CLAUDE.md). Idempotent: if images/busybox.tar already exists (your own unofficial build, or a previously-fetched one), does nothing. Otherwise looks for skopeo, then podman, then docker, in that preference order -- skopeo and podman both reliably produce a genuine OCI Image Layout tar (what oci_image.cpp actually parses: oci-layout + index.json + blobs/sha256/*); a plain `docker save` only does if Docker's containerd image store happens to be enabled, so the result is verified either way before being accepted. """ import shutil import subprocess import sys import tarfile from pathlib import Path REPO_ROOT = Path(__file__).resolve().parent.parent TARGET = REPO_ROOT / "images" / "busybox.tar" IMAGE = "docker.io/library/busybox:latest" def looks_like_oci_layout(path: Path) -> bool: try: with tarfile.open(path) as tar: names = set(tar.getnames()) except tarfile.TarError: return False return "oci-layout" in names and "index.json" in names def fetch_with_skopeo() -> bool: print("fetching busybox via skopeo...") result = subprocess.run( ["skopeo", "copy", f"docker://{IMAGE.removeprefix('docker.io/')}", f"oci-archive:{TARGET}:latest"] ) return result.returncode == 0 def fetch_with_podman() -> bool: print("fetching busybox via podman...") if subprocess.run(["podman", "pull", IMAGE]).returncode != 0: return False result = subprocess.run(["podman", "save", "--format", "oci-archive", "-o", str(TARGET), IMAGE]) return result.returncode == 0 def fetch_with_docker() -> bool: print("fetching busybox via docker (only works if the containerd image store is enabled)...") if subprocess.run(["docker", "pull", IMAGE]).returncode != 0: return False result = subprocess.run(["docker", "save", "-o", str(TARGET), IMAGE]) return result.returncode == 0 def main() -> int: if TARGET.exists(): print(f"already present: {TARGET}") return 0 TARGET.parent.mkdir(parents=True, exist_ok=True) fetchers = [ ("skopeo", fetch_with_skopeo), ("podman", fetch_with_podman), ("docker", fetch_with_docker), ] for tool, fetch in fetchers: if not shutil.which(tool): continue try: ok = fetch() except OSError as exc: print(f"{tool} failed to run: {exc}", file=sys.stderr) ok = False if not ok: TARGET.unlink(missing_ok=True) print(f"{tool} was found but fetching busybox with it failed; trying the next option", file=sys.stderr) continue if not looks_like_oci_layout(TARGET): TARGET.unlink(missing_ok=True) print( f"{tool} produced {TARGET.name}, but it isn't a genuine OCI Image Layout tar " "(no oci-layout/index.json at its root) -- if that was docker, this usually means " "the containerd image store isn't enabled; trying the next option", file=sys.stderr, ) continue print(f"fetched: {TARGET}") return 0 print( "no usable image tool found (checked skopeo, podman, docker) and " f"{TARGET} doesn't already exist.\n" "Install one of skopeo/podman/docker, or supply your own busybox-like " f"OCI Image Layout tar at {TARGET} directly.", file=sys.stderr, ) return 1 if __name__ == "__main__": sys.exit(main())