dd66886de8
Idempotent: does nothing if images/busybox.tar already exists (your own unofficial build, or a previous fetch). Otherwise tries skopeo, then podman, then docker, in that order -- skopeo/podman both reliably produce a genuine OCI Image Layout tar; a plain `docker save` only does if the containerd image store happens to be enabled, so the result is verified (oci-layout/index.json actually present at the tar root) regardless of which tool produced it, falling through to the next option otherwise. Clear instructions + nonzero exit if none of the three are available and no fixture already exists. Verified the no-op (already-present) path and the no-tools-available error path directly (temporarily moved the existing images/busybox.tar aside and back) -- this dev machine has none of skopeo/podman/docker installed, so the actual fetch path itself is unverified here; the format-verification step (looks_like_oci_layout()) is what protects against a `docker save` that produced the legacy Docker tar format on some other machine. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gv3s5jckJKzh6JkMoi2Akz
109 lines
3.7 KiB
Python
Executable File
109 lines
3.7 KiB
Python
Executable File
#!/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())
|