banger/docs/oci-import-internals.md
Thales Maciel d0997fd3b5
model,cli,docs: medium-effort polish for v0.1.0
* model.ParseSize / FormatSizeBytes: pinned with table tests in
    internal/model/types_test.go (TestParseSize 22 cases,
    TestFormatSizeBytes 11 cases, TestParseSizeFormatRoundTrip 7
    boundaries). Fixed the long-suffix regression: "4GiB", "512MiB",
    "4KiB" now parse correctly (parser strips trailing IB before
    inspecting the unit byte). Pinned current behaviour for
    no-suffix input ("1024" treated as MiB) and FormatSizeBytes(0).
    commands_image.go --size flag-help updated to show 4GiB now
    that the parser accepts it.
  * vm ports --json: matches the JSON-vs-table inconsistency between
    vm stats (always JSON) and vm ports (always table). --json on
    vm ports flips to the same printJSON path as vm stats. Default
    table output unchanged. Other vm subcommands (show, stats,
    logs, health, ping) didn't fit the identical pattern; left
    alone.
  * docs/oci-import.md architecture section moved to a new
    docs/oci-import-internals.md (precedent: internal/daemon/
    ARCHITECTURE.md). User-facing oci-import.md keeps a one-line
    pointer for advanced reading.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 17:36:03 -03:00

2.1 KiB

OCI import — internals

Advanced reading. This document describes implementation details of the OCI import pipeline. It is not needed for day-to-day use of banger image pull. User-facing documentation is in docs/oci-import.md.

Architecture

internal/imagepull/ owns the mechanics:

  • Pull wraps go-containerregistry's remote.Image with the linux/amd64 platform pinned. Layer blobs cache under ~/.cache/banger/oci/blobs/ and populate lazily during flatten.
  • Flatten replays layers oldest-first into a staging directory, applies whiteouts, rejects unsafe paths plus filenames that banger's debugfs ownership fixup cannot encode safely. Returns a Metadata map of per-file uid/gid/mode from tar headers.
  • BuildExt4 runs mkfs.ext4 -F -d <staging> -E root_owner=0:0 at the size of the pre-truncated file — no mount, no sudo, no loopback. Requires e2fsprogs ≥ 1.43.
  • ApplyOwnership streams a batched set_inode_field script to debugfs -w to rewrite per-file uid/gid/mode to the captured tar- header values.
  • InjectGuestAgents uses the same debugfs scripting to drop banger's guest assets into the ext4 with root ownership: vsock agent binary, network bootstrap + unit, first-boot script + unit, multi-user.target.wants symlinks, vsock modules-load config, /var/lib/banger/first-boot-pending marker.

internal/daemon/images_pull.go orchestrates pullFromOCI:

  1. Parse + validate the OCI ref, derive a default name when --name is omitted (debian-bookworm from docker.io/library/debian:bookworm).
  2. Resolve kernel info via resolveKernelInputs (auto-pulls from kernelcat if --kernel-ref names a catalog entry that isn't yet local).
  3. Stage at <ImagesDir>/<id>.staging; extract layers to a temp tree under $TMPDIR.
  4. BuildExt4ApplyOwnershipInjectGuestAgents.
  5. imagemgr.StageBootArtifacts stages the kernel triple alongside.
  6. Atomic os.Rename publishes the artifact dir.
  7. Persist a model.Image{Managed: true, …} record.