Reorganize the source checkout layout

Separate tracked source from generated artifacts so the repo root stops accumulating helper scripts, manifests, and local runtime outputs.

Move manual shell entrypoints under scripts/, manifests under config/, and the Firecracker API reference under docs/reference/. Make build and runtimebundle now target build/bin, build/runtime, and build/dist as the canonical source-checkout paths.

Update runtime discovery, helper scripts, tests, and docs to follow the new layout while keeping legacy source-checkout runtime fallbacks for existing local bundles during migration.

Validated with bash -n on the moved scripts, make build, and GOCACHE=/tmp/banger-gocache go test ./....
This commit is contained in:
Thales Maciel 2026-03-21 17:22:57 -03:00
parent 2362d0ae39
commit 01c7cb5e65
No known key found for this signature in database
GPG key ID: 33112E6833C34679
23 changed files with 296 additions and 186 deletions

1
.gitignore vendored
View file

@ -1,4 +1,5 @@
state/ state/
/build/
/runtime/ /runtime/
/dist/ /dist/
/banger /banger

View file

@ -4,28 +4,28 @@
- `cmd/banger` and `cmd/bangerd` are the primary user-facing entrypoints. - `cmd/banger` and `cmd/bangerd` are the primary user-facing entrypoints.
- `internal/` contains the daemon, CLI, RPC, storage, Firecracker, and system integration code. - `internal/` contains the daemon, CLI, RPC, storage, Firecracker, and system integration code.
- The VM lifecycle is now organized around daemon capabilities plus a structured guest-config builder. New host-integrated VM features should plug into that Go path instead of adding more one-off branches through `internal/daemon/vm.go`. - The VM lifecycle is now organized around daemon capabilities plus a structured guest-config builder. New host-integrated VM features should plug into that Go path instead of adding more one-off branches through `internal/daemon/vm.go`.
- `customize.sh`, `make-rootfs.sh`, and `interactive.sh` remain as manual rootfs/customization helpers; normal VM lifecycle, NAT, `.vm` DNS, and daemon-driven image builds are handled by the Go control plane. - `scripts/customize.sh`, `scripts/make-rootfs.sh`, and `scripts/interactive.sh` remain as manual rootfs/customization helpers; normal VM lifecycle, NAT, `.vm` DNS, and daemon-driven image builds are handled by the Go control plane.
- Source checkouts use a generated `./runtime/` bundle for Firecracker, kernels, modules, rootfs images, and helper copies. Bundle defaults come from `./runtime/bundle.json` when present. Those runtime artifacts are not meant to be tracked directly in Git. - Source checkouts use a generated `./build/runtime/` bundle for Firecracker, kernels, modules, rootfs images, and helper copies. Bundle defaults come from `./build/runtime/bundle.json` when present. Those runtime artifacts are not meant to be tracked directly in Git.
- The daemon keeps state under XDG directories rather than the old repo-local `state/` layout. - The daemon keeps state under XDG directories rather than the old repo-local `state/` layout.
## Build, Test, and Development Commands ## Build, Test, and Development Commands
- `make build` builds `./banger`, `./bangerd`, and the bundled `./runtime/banger-vsock-agent` guest helper. - `make build` builds `./build/bin/banger`, `./build/bin/bangerd`, and the bundled `./build/runtime/banger-vsock-agent` guest helper.
- `make bench-create` benchmarks `vm create` and first-SSH readiness on the current host. - `make bench-create` benchmarks `vm create` and first-SSH readiness on the current host.
- `make runtime-bundle` bootstraps `./runtime/` from the archive referenced by `RUNTIME_MANIFEST`; the checked-in `runtime-bundle.toml` is only a template. - `make runtime-bundle` bootstraps `./build/runtime/` from the archive referenced by `RUNTIME_MANIFEST`; the checked-in `config/runtime-bundle.toml` is only a template.
- `make void-kernel` downloads and stages a Void `linux6.12` kernel under `./runtime/void-kernel`, including extracted `vmlinux`, raw `vmlinuz`, a matching generated `initramfs`, config, and matching modules. - `make void-kernel` downloads and stages a Void `linux6.12` kernel under `./build/runtime/void-kernel`, including extracted `vmlinux`, raw `vmlinuz`, a matching generated `initramfs`, config, and matching modules.
- `make rootfs-void` builds an experimental local-only `x86_64-glibc` Void rootfs plus work-seed under `./runtime/`; it prefers staged `./runtime/void-kernel` modules when present, but does not replace the default Debian path or teach `banger image build` about Void. - `make rootfs-void` builds an experimental local-only `x86_64-glibc` Void rootfs plus work-seed under `./build/runtime/`; it prefers staged `./build/runtime/void-kernel` modules when present, but does not replace the default Debian path or teach `banger image build` about Void.
- `make verify-void` registers `void-exp` and runs the normal smoke test against that image. - `make verify-void` registers `void-exp` and runs the normal smoke test against that image.
- `banger` validates required host tools per command and reports actionable missing-tool errors; do not assume one workstation's package set. - `banger` validates required host tools per command and reports actionable missing-tool errors; do not assume one workstation's package set.
- `./banger vm create --name testbox` creates and starts a VM. - `./build/bin/banger vm create --name testbox` creates and starts a VM.
- `./banger vm create` now blocks until the guest reaches the daemon's default readiness checks and shows live progress stages on TTY stderr while it waits. - `./build/bin/banger vm create` now blocks until the guest reaches the daemon's default readiness checks and shows live progress stages on TTY stderr while it waits.
- `./banger vm ssh testbox` connects to a running guest using the runtime bundle SSH key and reminds the user if the VM is still running when the session exits. - `./build/bin/banger vm ssh testbox` connects to a running guest using the runtime bundle SSH key and reminds the user if the VM is still running when the session exits.
- `./banger vm stop testbox` stops a VM while preserving its disks. - `./build/bin/banger vm stop testbox` stops a VM while preserving its disks.
- `./banger vm stop vm-a vm-b vm-c` and `./banger vm set --nat web-1 web-2` are supported; multi-VM lifecycle and `set` actions fan out concurrently through the CLI. - `./build/bin/banger vm stop vm-a vm-b vm-c` and `./build/bin/banger vm set --nat web-1 web-2` are supported; multi-VM lifecycle and `set` actions fan out concurrently through the CLI.
- `./banger doctor` reports runtime bundle, host tool, feature, and image-build readiness from the same Go checks used by the daemon. - `./build/bin/banger doctor` reports runtime bundle, host tool, feature, and image-build readiness from the same Go checks used by the daemon.
- `./banger image register --name local --rootfs /abs/path/rootfs.ext4` creates or updates an unmanaged image record without changing the default image config; use it for experimental guest iteration paths such as Void. - `./build/bin/banger image register --name local --rootfs /abs/path/rootfs.ext4` creates or updates an unmanaged image record without changing the default image config; use it for experimental guest iteration paths such as Void.
- `bangerd` now also serves a localhost web UI on `http://127.0.0.1:7777` by default unless `web_listen_addr = ""` disables it; the UI uses server-rendered templates, polls async VM/image operations, and keeps image path selection on the host via a server-side file picker. - `bangerd` now also serves a localhost web UI on `http://127.0.0.1:7777` by default unless `web_listen_addr = ""` disables it; the UI uses server-rendered templates, polls async VM/image operations, and keeps image path selection on the host via a server-side file picker.
- `make test` runs `go test ./...`. - `make test` runs `go test ./...`.
- `./verify.sh` runs the smoke test for the Go VM workflow. - `./scripts/verify.sh` runs the smoke test for the Go VM workflow.
## Coding Style & Naming Conventions ## Coding Style & Naming Conventions
- Go code should stay small, direct, and standard-library-first unless there is a clear reason otherwise. - Go code should stay small, direct, and standard-library-first unless there is a clear reason otherwise.
@ -35,15 +35,15 @@
## Testing Guidelines ## Testing Guidelines
- Primary automated coverage is `go test ./...`. - Primary automated coverage is `go test ./...`.
- Manual verification for VM lifecycle changes: `./banger vm create`, confirm SSH access, then stop/delete the VM. - Manual verification for VM lifecycle changes: `./build/bin/banger vm create`, confirm SSH access, then stop/delete the VM.
- For host-integration changes, run `./banger doctor` as a quick readiness check before the live VM smoke. - For host-integration changes, run `./build/bin/banger doctor` as a quick readiness check before the live VM smoke.
- The web UI follows the same sudo model as the CLI path: bangerd stays unprivileged and privileged writes only work when `sudo -v` is already warm or sudo is passwordless. - The web UI follows the same sudo model as the CLI path: bangerd stays unprivileged and privileged writes only work when `sudo -v` is already warm or sudo is passwordless.
- Rebuilt images now include `mise`, `opencode`, a host-reachable default `opencode` server service on guest TCP port `4096`, `tmux-resurrect`/`tmux-continuum` defaults for `root`, and the `banger-vsock-agent` service used by the SSH reminder and guest health-check path; if you change guest provisioning, document whether users need to rebuild `./runtime/rootfs-docker.ext4` or another base image to pick it up. - Rebuilt images now include `mise`, `opencode`, a host-reachable default `opencode` server service on guest TCP port `4096`, `tmux-resurrect`/`tmux-continuum` defaults for `root`, and the `banger-vsock-agent` service used by the SSH reminder and guest health-check path; if you change guest provisioning, document whether users need to rebuild `./build/runtime/rootfs-docker.ext4` or another base image to pick it up.
- The experimental Void rootfs path now includes the repo's basic dev baseline plus Docker and Compose, alongside boot, SSH, a guest network bootstrap sourced from the kernel `ip=` cmdline, the vsock HTTP health agent, pinned `mise` plus `opencode` for `root`, the default host-reachable `opencode` server service on guest TCP port `4096`, a `bash` root shell while leaving `/bin/sh` alone, and the `/root` work-seed. When `./runtime/void-kernel/` exists, the Void image registration path expects a complete staged Void kernel, initramfs, and modules tree and points `void-exp` at it. Keep further baked-in tooling deliberate and user-driven. - The experimental Void rootfs path now includes the repo's basic dev baseline plus Docker and Compose, alongside boot, SSH, a guest network bootstrap sourced from the kernel `ip=` cmdline, the vsock HTTP health agent, pinned `mise` plus `opencode` for `root`, the default host-reachable `opencode` server service on guest TCP port `4096`, a `bash` root shell while leaving `/bin/sh` alone, and the `/root` work-seed. When `./build/runtime/void-kernel/` exists, the Void image registration path expects a complete staged Void kernel, initramfs, and modules tree and points `void-exp` at it. Keep further baked-in tooling deliberate and user-driven.
- Rebuilt images also emit a `work-seed.ext4` sidecar used to speed up future VM creates. Older managed images may take one slower create to refresh seeded SSH access before they rejoin the fast path. If you touch `/root` provisioning, verify both the rootfs and the work-seed output. - Rebuilt images also emit a `work-seed.ext4` sidecar used to speed up future VM creates. Older managed images may take one slower create to refresh seeded SSH access before they rejoin the fast path. If you touch `/root` provisioning, verify both the rootfs and the work-seed output.
- The daemon may keep idle TAP devices in a pool for faster creates. Smoke tests should treat `tap-pool-*` devices as reusable capacity, not cleanup leaks. - The daemon may keep idle TAP devices in a pool for faster creates. Smoke tests should treat `tap-pool-*` devices as reusable capacity, not cleanup leaks.
- If you add a new operational workflow, document how to exercise it in `README.md`. - If you add a new operational workflow, document how to exercise it in `README.md`.
- For NAT changes, verify both guest outbound access and host rule cleanup, for example with `./verify.sh --nat`. - For NAT changes, verify both guest outbound access and host rule cleanup, for example with `./scripts/verify.sh --nat`.
## Commit & Pull Request Guidelines ## Commit & Pull Request Guidelines
- Git history uses short, imperative subjects. - Git history uses short, imperative subjects.

View file

@ -8,10 +8,14 @@ BINDIR ?= $(PREFIX)/bin
LIBDIR ?= $(PREFIX)/lib LIBDIR ?= $(PREFIX)/lib
RUNTIMEDIR ?= $(LIBDIR)/banger RUNTIMEDIR ?= $(LIBDIR)/banger
DESTDIR ?= DESTDIR ?=
RUNTIME_MANIFEST ?= runtime-bundle.toml BUILD_DIR ?= build
RUNTIME_SOURCE_DIR ?= runtime BUILD_BIN_DIR ?= $(BUILD_DIR)/bin
RUNTIME_ARCHIVE ?= dist/banger-runtime.tar.gz RUNTIME_MANIFEST ?= config/runtime-bundle.toml
BINARIES := banger bangerd RUNTIME_SOURCE_DIR ?= $(BUILD_DIR)/runtime
RUNTIME_ARCHIVE ?= $(BUILD_DIR)/dist/banger-runtime.tar.gz
BANGER_BIN ?= $(BUILD_BIN_DIR)/banger
BANGERD_BIN ?= $(BUILD_BIN_DIR)/bangerd
BINARIES := $(BANGER_BIN) $(BANGERD_BIN)
RUNTIME_HELPERS := $(RUNTIME_SOURCE_DIR)/banger-vsock-agent RUNTIME_HELPERS := $(RUNTIME_SOURCE_DIR)/banger-vsock-agent
GO_SOURCES := $(shell find cmd internal -type f -name '*.go' | sort) GO_SOURCES := $(shell find cmd internal -type f -name '*.go' | sort)
RUNTIME_EXECUTABLES := firecracker customize.sh packages.sh namegen banger-vsock-agent RUNTIME_EXECUTABLES := firecracker customize.sh packages.sh namegen banger-vsock-agent
@ -29,8 +33,8 @@ VOID_VM_NAME ?= void-dev
help: help:
@printf '%s\n' \ @printf '%s\n' \
'Targets:' \ 'Targets:' \
' make build Build ./banger and ./bangerd' \ ' make build Build ./build/bin/banger and ./build/bin/bangerd' \
' make runtime-bundle Fetch and unpack ./runtime from the archive referenced by $(RUNTIME_MANIFEST)' \ ' make runtime-bundle Fetch and unpack ./build/runtime from the archive referenced by $(RUNTIME_MANIFEST)' \
' make runtime-package Package $(RUNTIME_SOURCE_DIR) into $(RUNTIME_ARCHIVE) and print its SHA256' \ ' make runtime-package Package $(RUNTIME_SOURCE_DIR) into $(RUNTIME_ARCHIVE) and print its SHA256' \
' make bench-create Benchmark vm create and SSH readiness with scripts/bench-create.sh' \ ' make bench-create Benchmark vm create and SSH readiness with scripts/bench-create.sh' \
' make install Build and install binaries plus the runtime bundle into $(DESTDIR)$(BINDIR) and $(DESTDIR)$(RUNTIMEDIR)' \ ' make install Build and install binaries plus the runtime bundle into $(DESTDIR)$(BINDIR) and $(DESTDIR)$(RUNTIMEDIR)' \
@ -38,20 +42,22 @@ help:
' make fmt Format Go sources under cmd/ and internal/' \ ' make fmt Format Go sources under cmd/ and internal/' \
' make tidy Run go mod tidy' \ ' make tidy Run go mod tidy' \
' make clean Remove built Go binaries' \ ' make clean Remove built Go binaries' \
' make rootfs Rebuild the source-checkout default Debian rootfs image in ./runtime' \ ' make rootfs Rebuild the source-checkout default Debian rootfs image in ./build/runtime' \
' make void-kernel Download and stage a Void kernel, initramfs, and modules under ./runtime/void-kernel' \ ' make void-kernel Download and stage a Void kernel, initramfs, and modules under ./build/runtime/void-kernel' \
' make rootfs-void Build an experimental Void Linux rootfs and work-seed in ./runtime' \ ' make rootfs-void Build an experimental Void Linux rootfs and work-seed in ./build/runtime' \
' make void-register Register or update the experimental Void image as $(VOID_IMAGE_NAME)' \ ' make void-register Register or update the experimental Void image as $(VOID_IMAGE_NAME)' \
' make void-vm Register the experimental Void image and create a VM named $(VOID_VM_NAME)' \ ' make void-vm Register the experimental Void image and create a VM named $(VOID_VM_NAME)' \
' make verify-void Register the experimental Void image and run verify.sh against it' ' make verify-void Register the experimental Void image and run scripts/verify.sh against it'
build: $(BINARIES) $(RUNTIME_HELPERS) build: $(BINARIES) $(RUNTIME_HELPERS)
banger: $(GO_SOURCES) go.mod go.sum $(BANGER_BIN): $(GO_SOURCES) go.mod go.sum
$(GO) build -o ./banger ./cmd/banger mkdir -p "$(BUILD_BIN_DIR)"
$(GO) build -o "$(BANGER_BIN)" ./cmd/banger
bangerd: $(GO_SOURCES) go.mod go.sum $(BANGERD_BIN): $(GO_SOURCES) go.mod go.sum
$(GO) build -o ./bangerd ./cmd/bangerd mkdir -p "$(BUILD_BIN_DIR)"
$(GO) build -o "$(BANGERD_BIN)" ./cmd/bangerd
$(RUNTIME_SOURCE_DIR)/banger-vsock-agent: $(GO_SOURCES) go.mod go.sum $(RUNTIME_SOURCE_DIR)/banger-vsock-agent: $(GO_SOURCES) go.mod go.sum
mkdir -p "$(RUNTIME_SOURCE_DIR)" mkdir -p "$(RUNTIME_SOURCE_DIR)"
@ -67,7 +73,8 @@ tidy:
$(GO) mod tidy $(GO) mod tidy
clean: clean:
rm -f ./banger ./bangerd rm -rf "$(BUILD_BIN_DIR)"
rm -f "$(RUNTIME_SOURCE_DIR)/banger-vsock-agent"
runtime-bundle: runtime-bundle:
$(GO) run ./cmd/runtimebundle fetch --manifest "$(RUNTIME_MANIFEST)" --out "$(RUNTIME_SOURCE_DIR)" $(GO) run ./cmd/runtimebundle fetch --manifest "$(RUNTIME_MANIFEST)" --out "$(RUNTIME_SOURCE_DIR)"
@ -76,7 +83,7 @@ runtime-package:
$(GO) run ./cmd/runtimebundle package --manifest "$(RUNTIME_MANIFEST)" --runtime-dir "$(RUNTIME_SOURCE_DIR)" --out "$(RUNTIME_ARCHIVE)" $(GO) run ./cmd/runtimebundle package --manifest "$(RUNTIME_MANIFEST)" --runtime-dir "$(RUNTIME_SOURCE_DIR)" --out "$(RUNTIME_ARCHIVE)"
bench-create: build bench-create: build
bash ./scripts/bench-create.sh $(ARGS) BANGER_BIN="$(abspath $(BANGER_BIN))" bash ./scripts/bench-create.sh $(ARGS)
check-runtime: check-runtime:
@test -d "$(RUNTIME_SOURCE_DIR)" || { echo "missing runtime bundle directory: $(RUNTIME_SOURCE_DIR); run 'make runtime-bundle'" >&2; exit 1; } @test -d "$(RUNTIME_SOURCE_DIR)" || { echo "missing runtime bundle directory: $(RUNTIME_SOURCE_DIR); run 'make runtime-bundle'" >&2; exit 1; }
@ -89,8 +96,8 @@ install: build check-runtime
mkdir -p "$(DESTDIR)$(RUNTIMEDIR)" mkdir -p "$(DESTDIR)$(RUNTIMEDIR)"
mkdir -p "$(DESTDIR)$(RUNTIMEDIR)/wtf/root/boot" mkdir -p "$(DESTDIR)$(RUNTIMEDIR)/wtf/root/boot"
mkdir -p "$(DESTDIR)$(RUNTIMEDIR)/wtf/root/lib/modules" mkdir -p "$(DESTDIR)$(RUNTIMEDIR)/wtf/root/lib/modules"
$(INSTALL) -m 0755 ./banger "$(DESTDIR)$(BINDIR)/banger" $(INSTALL) -m 0755 "$(BANGER_BIN)" "$(DESTDIR)$(BINDIR)/banger"
$(INSTALL) -m 0755 ./bangerd "$(DESTDIR)$(BINDIR)/bangerd" $(INSTALL) -m 0755 "$(BANGERD_BIN)" "$(DESTDIR)$(BINDIR)/bangerd"
@for path in $(RUNTIME_EXECUTABLES); do \ @for path in $(RUNTIME_EXECUTABLES); do \
$(INSTALL) -m 0755 "$(RUNTIME_SOURCE_DIR)/$$path" "$(DESTDIR)$(RUNTIMEDIR)/$$path"; \ $(INSTALL) -m 0755 "$(RUNTIME_SOURCE_DIR)/$$path" "$(DESTDIR)$(RUNTIMEDIR)/$$path"; \
done done
@ -106,19 +113,19 @@ install: build check-runtime
cp -a "$(RUNTIME_SOURCE_DIR)/$(RUNTIME_MODULES_DIR)" "$(DESTDIR)$(RUNTIMEDIR)/wtf/root/lib/modules/" cp -a "$(RUNTIME_SOURCE_DIR)/$(RUNTIME_MODULES_DIR)" "$(DESTDIR)$(RUNTIMEDIR)/wtf/root/lib/modules/"
rootfs: rootfs:
BANGER_RUNTIME_DIR="$(abspath $(RUNTIME_SOURCE_DIR))" ./make-rootfs.sh BANGER_RUNTIME_DIR="$(abspath $(RUNTIME_SOURCE_DIR))" ./scripts/make-rootfs.sh
void-kernel: void-kernel:
BANGER_RUNTIME_DIR="$(abspath $(RUNTIME_SOURCE_DIR))" ./make-void-kernel.sh BANGER_RUNTIME_DIR="$(abspath $(RUNTIME_SOURCE_DIR))" ./scripts/make-void-kernel.sh
rootfs-void: rootfs-void:
BANGER_RUNTIME_DIR="$(abspath $(RUNTIME_SOURCE_DIR))" ./make-rootfs-void.sh BANGER_RUNTIME_DIR="$(abspath $(RUNTIME_SOURCE_DIR))" ./scripts/make-rootfs-void.sh
void-register: build void-register: build
BANGER_RUNTIME_DIR="$(abspath $(RUNTIME_SOURCE_DIR))" VOID_IMAGE_NAME="$(VOID_IMAGE_NAME)" BANGER_BIN="$(abspath ./banger)" ./register-void-image.sh BANGER_RUNTIME_DIR="$(abspath $(RUNTIME_SOURCE_DIR))" VOID_IMAGE_NAME="$(VOID_IMAGE_NAME)" BANGER_BIN="$(abspath $(BANGER_BIN))" ./scripts/register-void-image.sh
void-vm: void-register void-vm: void-register
./banger vm create --image "$(VOID_IMAGE_NAME)" --name "$(VOID_VM_NAME)" "$(abspath $(BANGER_BIN))" vm create --image "$(VOID_IMAGE_NAME)" --name "$(VOID_VM_NAME)"
verify-void: void-register verify-void: void-register
./verify.sh --image "$(VOID_IMAGE_NAME)" BANGER_BIN="$(abspath $(BANGER_BIN))" ./scripts/verify.sh --image "$(VOID_IMAGE_NAME)"

102
README.md
View file

@ -17,7 +17,7 @@ assuming one workstation layout.
## Runtime Bundle ## Runtime Bundle
Runtime artifacts are no longer tracked directly in Git. Source checkouts use a Runtime artifacts are no longer tracked directly in Git. Source checkouts use a
generated `./runtime/` bundle, while installed binaries use generated `./build/runtime/` bundle, while installed binaries use
`$(prefix)/lib/banger`. `$(prefix)/lib/banger`.
The bundle contains: The bundle contains:
@ -34,30 +34,30 @@ The bundle contains:
- the helper scripts used by manual customization and installs - the helper scripts used by manual customization and installs
Bootstrap a source checkout from a local or published runtime archive. The Bootstrap a source checkout from a local or published runtime archive. The
checked-in [`runtime-bundle.toml`](/home/thales/projects/personal/banger/runtime-bundle.toml) checked-in [`config/runtime-bundle.toml`](/home/thales/projects/personal/banger/config/runtime-bundle.toml)
is a template and intentionally ships with empty `url` and `sha256`. is a template and intentionally ships with empty `url` and `sha256`.
If you need to create a local archive first, do that from a checkout or machine If you need to create a local archive first, do that from a checkout or machine
that already has a populated `./runtime/` tree: that already has a populated `./build/runtime/` tree:
```bash ```bash
make runtime-package make runtime-package
cp dist/banger-runtime.tar.gz /path/to/fresh-checkout/dist/ cp build/dist/banger-runtime.tar.gz /path/to/fresh-checkout/build/dist/
``` ```
In the fresh checkout: In the fresh checkout:
```bash ```bash
cp runtime-bundle.toml runtime-bundle.local.toml cp config/runtime-bundle.toml config/runtime-bundle.local.toml
``` ```
Edit `runtime-bundle.local.toml` to point at the staged archive and checksum: Edit `config/runtime-bundle.local.toml` to point at the staged archive and checksum:
```toml ```toml
url = "./dist/banger-runtime.tar.gz" url = "./build/dist/banger-runtime.tar.gz"
sha256 = "<sha256 printed by make runtime-package>" sha256 = "<sha256 printed by make runtime-package>"
``` ```
Then bootstrap `./runtime/` with the local manifest copy: Then bootstrap `./build/runtime/` with the local manifest copy:
```bash ```bash
make runtime-bundle RUNTIME_MANIFEST=runtime-bundle.local.toml make runtime-bundle RUNTIME_MANIFEST=config/runtime-bundle.local.toml
``` ```
`url` may be a relative path, absolute path, `file:///...` URL, or HTTP(S) `url` may be a relative path, absolute path, `file:///...` URL, or HTTP(S)
@ -68,8 +68,19 @@ URL. `make install` will not fetch artifacts for you.
make build make build
``` ```
Run `make build` after `./runtime/` has been bootstrapped. It also rebuilds the Run `make build` after `./build/runtime/` has been bootstrapped. It writes
bundled `banger-vsock-agent` guest helper in `./runtime/`. `./build/bin/banger`, `./build/bin/bangerd`, and refreshes the bundled
`banger-vsock-agent` guest helper in `./build/runtime/`.
Older ignored root artifacts such as `./runtime/`, `./banger`, and `./bangerd`
are no longer the canonical source-checkout layout. Leave them alone if you
still need them, or remove them manually after migrating to `build/`.
If you have confirmed your current images and runtime settings no longer point
at the old checkout-local paths, a one-time cleanup looks like:
```bash
rm -rf ./runtime ./banger ./bangerd
```
Install into `~/.local/bin` by default, with the runtime bundle under Install into `~/.local/bin` by default, with the runtime bundle under
`~/.local/lib/banger`: `~/.local/lib/banger`:
@ -178,8 +189,9 @@ State lives under XDG directories:
- runtime socket: `$XDG_RUNTIME_DIR/banger/bangerd.sock` - runtime socket: `$XDG_RUNTIME_DIR/banger/bangerd.sock`
Installed binaries resolve their runtime bundle from `../lib/banger` relative to Installed binaries resolve their runtime bundle from `../lib/banger` relative to
the executable. Source-checkout binaries resolve it from `./runtime` next to the the executable. Source-checkout binaries resolve it from `./build/runtime` next
repo-built `./banger`. You can override either with `runtime_dir` in to `./build/bin/banger`, and still fall back to a legacy `./runtime` checkout
bundle if that exists. You can override either with `runtime_dir` in
`~/.config/banger/config.toml` or `BANGER_RUNTIME_DIR`. `~/.config/banger/config.toml` or `BANGER_RUNTIME_DIR`.
Useful config keys: Useful config keys:
@ -323,32 +335,32 @@ shell helpers treated as manual workflows rather than architecture drivers.
- Stopping a VM preserves its overlay and work disk. - Stopping a VM preserves its overlay and work disk.
## Rebuilding The Repo Default Rootfs ## Rebuilding The Repo Default Rootfs
`packages.apt` controls the base apt packages baked into rebuilt images, `config/packages.apt` controls the base apt packages baked into rebuilt images,
including guest tools such as `ss` used by `banger vm ports`. including guest tools such as `ss` used by `banger vm ports`.
To rebuild the source-checkout default image in `./runtime/rootfs-docker.ext4`: To rebuild the source-checkout default image in `./build/runtime/rootfs-docker.ext4`:
```bash ```bash
make rootfs make rootfs
``` ```
That rebuild also regenerates `./runtime/rootfs-docker.work-seed.ext4`, which That rebuild also regenerates `./build/runtime/rootfs-docker.work-seed.ext4`, which
the daemon uses to speed up future `vm create` calls, and bakes in the default the daemon uses to speed up future `vm create` calls, and bakes in the default
host-reachable `opencode` server service. host-reachable `opencode` server service.
If your runtime bundle does not include `./runtime/rootfs.ext4`, pass an If your runtime bundle does not include `./build/runtime/rootfs.ext4`, pass an
explicit base image instead: explicit base image instead:
```bash ```bash
./make-rootfs.sh --base-rootfs /path/to/base-rootfs.ext4 ./scripts/make-rootfs.sh --base-rootfs /path/to/base-rootfs.ext4
``` ```
If the package manifest changed and you want a fresh source-checkout image: If the package manifest changed and you want a fresh source-checkout image:
```bash ```bash
rm -f ./runtime/rootfs-docker.ext4 ./runtime/rootfs-docker.ext4.packages.sha256 rm -f ./build/runtime/rootfs-docker.ext4 ./build/runtime/rootfs-docker.ext4.packages.sha256
make rootfs make rootfs
``` ```
`make rootfs` expects a bootstrapped runtime bundle. If `./runtime/rootfs.ext4` `make rootfs` expects a bootstrapped runtime bundle. If `./build/runtime/rootfs.ext4`
is not available, pass an explicit `--base-rootfs` to `./make-rootfs.sh`. is not available, pass an explicit `--base-rootfs` to `./scripts/make-rootfs.sh`.
Existing VMs keep using their current image and disks; rebuilds only affect VMs Existing VMs keep using their current image and disks; rebuilds only affect VMs
created from the rebuilt image afterward. Restarting an existing VM is not created from the rebuilt image afterward. Restarting an existing VM is not
enough to pick up guest provisioning changes such as the default `opencode` enough to pick up guest provisioning changes such as the default `opencode`
@ -363,13 +375,13 @@ make rootfs-void
``` ```
That writes: That writes:
- `./runtime/void-kernel/` when `make void-kernel` is used - `./build/runtime/void-kernel/` when `make void-kernel` is used
- `./runtime/rootfs-void.ext4` - `./build/runtime/rootfs-void.ext4`
- `./runtime/rootfs-void.work-seed.ext4` - `./build/runtime/rootfs-void.work-seed.ext4`
This path is intentionally local-only and does not change the default Debian This path is intentionally local-only and does not change the default Debian
image flow. `make void-kernel` stages an actual Void `linux6.12` kernel package image flow. `make void-kernel` stages an actual Void `linux6.12` kernel package
under `./runtime/void-kernel/`, including the raw `vmlinuz`, extracted under `./build/runtime/void-kernel/`, including the raw `vmlinuz`, extracted
Firecracker `vmlinux`, a matching `initramfs`, the matching config, and the Firecracker `vmlinux`, a matching `initramfs`, the matching config, and the
matching modules tree. The initramfs is generated locally with `dracut` matching modules tree. The initramfs is generated locally with `dracut`
against the downloaded Void sysroot so the kernel, initrd, and modules stay against the downloaded Void sysroot so the kernel, initrd, and modules stay
@ -395,11 +407,11 @@ The builder fetches official static XBPS tools and packages from the Void
mirror during the build. The kernel fetcher and rootfs builder currently mirror during the build. The kernel fetcher and rootfs builder currently
support only `x86_64`. support only `x86_64`.
The package set comes from [`packages.void`](/home/thales/projects/personal/banger/packages.void). The package set comes from [`config/packages.void`](/home/thales/projects/personal/banger/config/packages.void).
You can override the mirror, size, output path, or kernel package directly: You can override the mirror, size, output path, or kernel package directly:
```bash ```bash
./make-void-kernel.sh --kernel-package linux6.12 ./scripts/make-void-kernel.sh --kernel-package linux6.12
./make-rootfs-void.sh --mirror https://repo-default.voidlinux.org --size 2G ./scripts/make-rootfs-void.sh --mirror https://repo-default.voidlinux.org --size 2G
``` ```
The fastest local iteration loop does not require changing your default image The fastest local iteration loop does not require changing your default image
@ -408,8 +420,8 @@ config at all:
make void-kernel make void-kernel
make rootfs-void make rootfs-void
make void-register make void-register
./banger vm create --image void-exp --name void-dev ./build/bin/banger vm create --image void-exp --name void-dev
./banger vm ssh void-dev ./build/bin/banger vm ssh void-dev
``` ```
Rebuild the staged Void kernel or Void rootfs, then recreate existing Rebuild the staged Void kernel or Void rootfs, then recreate existing
@ -425,7 +437,7 @@ make verify-void
`make void-register` uses the unmanaged image registration path to create or `make void-register` uses the unmanaged image registration path to create or
update a `void-exp` image record in place, so repeated rebuilds do not require update a `void-exp` image record in place, so repeated rebuilds do not require
editing `~/.config/banger/config.toml`. It expects a complete staged Void editing `~/.config/banger/config.toml`. It expects a complete staged Void
kernel set under `./runtime/void-kernel/` and points the experimental image at kernel set under `./build/runtime/void-kernel/` and points the experimental image at
the staged Void `vmlinux`, `initramfs`, and matching modules tree. the staged Void `vmlinux`, `initramfs`, and matching modules tree.
There is also a one-step helper target: There is also a one-step helper target:
@ -453,12 +465,12 @@ and package manifest:
```bash ```bash
banger image register \ banger image register \
--name void-exp \ --name void-exp \
--rootfs ./runtime/rootfs-void.ext4 \ --rootfs ./build/runtime/rootfs-void.ext4 \
--work-seed ./runtime/rootfs-void.work-seed.ext4 \ --work-seed ./build/runtime/rootfs-void.work-seed.ext4 \
--kernel ./runtime/void-kernel/boot/vmlinux-6.12.77_1 \ --kernel ./build/runtime/void-kernel/boot/vmlinux-6.12.77_1 \
--initrd ./runtime/void-kernel/boot/initramfs-6.12.77_1.img \ --initrd ./build/runtime/void-kernel/boot/initramfs-6.12.77_1.img \
--modules ./runtime/void-kernel/lib/modules/6.12.77_1 \ --modules ./build/runtime/void-kernel/lib/modules/6.12.77_1 \
--packages ./packages.void --packages ./config/packages.void
``` ```
If an unmanaged image with the same name already exists, `image register` If an unmanaged image with the same name already exists, `image register`
@ -466,17 +478,17 @@ updates it in place so future `vm create --image <name>` calls pick up the new
artifacts immediately. artifacts immediately.
## Maintaining The Runtime Bundle ## Maintaining The Runtime Bundle
The checked-in [`runtime-bundle.toml`](/home/thales/projects/personal/banger/runtime-bundle.toml) The checked-in [`config/runtime-bundle.toml`](/home/thales/projects/personal/banger/config/runtime-bundle.toml)
is a template. Keep `bundle_metadata` accurate there, but use a separate local is a template. Keep `bundle_metadata` accurate there, but use a separate local
manifest copy when you need concrete `url` and `sha256` values for bootstrap manifest copy when you need concrete `url` and `sha256` values for bootstrap
testing or publication. testing or publication.
Package a local `./runtime/` tree into an archive: Package a local `./build/runtime/` tree into an archive:
```bash ```bash
make runtime-package make runtime-package
``` ```
That writes `dist/banger-runtime.tar.gz` and prints its SHA256 so you can update That writes `build/dist/banger-runtime.tar.gz` and prints its SHA256 so you can update
a local manifest copy before testing bootstrap changes or publishing the a local manifest copy before testing bootstrap changes or publishing the
archive elsewhere. archive elsewhere.
@ -499,10 +511,10 @@ The benchmark prints JSON with:
## Remaining Shell Helpers ## Remaining Shell Helpers
The runtime VM lifecycle is managed through `banger`. The remaining shell scripts are not the primary user interface: The runtime VM lifecycle is managed through `banger`. The remaining shell scripts are not the primary user interface:
- `customize.sh`: manual reference flow for rootfs customization; `banger image build` is now Go-native, but the script still reads - `scripts/customize.sh`: manual reference flow for rootfs customization; `banger image build` is now Go-native, but the script still reads
assets from `BANGER_RUNTIME_DIR` and stores transient state under assets from `BANGER_RUNTIME_DIR` and stores transient state under
`BANGER_STATE_DIR`/XDG state `BANGER_STATE_DIR`/XDG state
- `make-rootfs.sh`: convenience wrapper for rebuilding `./runtime/rootfs-docker.ext4` - `scripts/make-rootfs.sh`: convenience wrapper for rebuilding `./build/runtime/rootfs-docker.ext4`
- `interactive.sh`: manual one-off rootfs customization over SSH - `scripts/interactive.sh`: manual one-off rootfs customization over SSH
- `packages.sh`: shell helper library - `scripts/lib/packages.sh`: shell helper library
- `verify.sh`: smoke test for the Go workflow (`./verify.sh --nat` adds NAT coverage) - `scripts/verify.sh`: smoke test for the Go workflow (`./scripts/verify.sh --nat` adds NAT coverage)

View file

@ -9,6 +9,12 @@ import (
"banger/internal/runtimebundle" "banger/internal/runtimebundle"
) )
const (
defaultManifestPath = "config/runtime-bundle.toml"
defaultRuntimeDir = "build/runtime"
defaultArchivePath = "build/dist/banger-runtime.tar.gz"
)
func main() { func main() {
if len(os.Args) < 2 { if len(os.Args) < 2 {
usage() usage()
@ -34,8 +40,8 @@ func main() {
func fetch(args []string) error { func fetch(args []string) error {
fs := flag.NewFlagSet("fetch", flag.ContinueOnError) fs := flag.NewFlagSet("fetch", flag.ContinueOnError)
fs.SetOutput(os.Stderr) fs.SetOutput(os.Stderr)
manifestPath := fs.String("manifest", "runtime-bundle.toml", "path to the runtime bundle manifest") manifestPath := fs.String("manifest", defaultManifestPath, "path to the runtime bundle manifest")
outDir := fs.String("out", "runtime", "destination runtime directory") outDir := fs.String("out", defaultRuntimeDir, "destination runtime directory")
if err := fs.Parse(args); err != nil { if err := fs.Parse(args); err != nil {
return err return err
} }
@ -49,9 +55,9 @@ func fetch(args []string) error {
func pkg(args []string) error { func pkg(args []string) error {
fs := flag.NewFlagSet("package", flag.ContinueOnError) fs := flag.NewFlagSet("package", flag.ContinueOnError)
fs.SetOutput(os.Stderr) fs.SetOutput(os.Stderr)
manifestPath := fs.String("manifest", "runtime-bundle.toml", "path to the runtime bundle manifest") manifestPath := fs.String("manifest", defaultManifestPath, "path to the runtime bundle manifest")
runtimeDir := fs.String("runtime-dir", "runtime", "runtime directory to package") runtimeDir := fs.String("runtime-dir", defaultRuntimeDir, "runtime directory to package")
outArchive := fs.String("out", "dist/banger-runtime.tar.gz", "output archive path") outArchive := fs.String("out", defaultArchivePath, "output archive path")
if err := fs.Parse(args); err != nil { if err := fs.Parse(args); err != nil {
return err return err
} }

View file

@ -1,6 +1,6 @@
# Template manifest for local or published runtime bundle archives. # Template manifest for local or published runtime bundle archives.
# Keep this checked-in file empty by default; use a local manifest copy with # Keep this checked-in file empty by default; use a local manifest copy with
# concrete `url` and `sha256` values when bootstrapping `./runtime/`. # concrete `url` and `sha256` values when bootstrapping `./build/runtime/`.
version = "v0" version = "v0"
url = "" url = ""
sha256 = "" sha256 = ""

View file

@ -5,10 +5,10 @@
# to the Void image yet; banger image build still assumes the Debian flow. # to the Void image yet; banger image build still assumes the Debian flow.
# If you run `make void-kernel`, also merge the commented kernel/initrd/modules lines. # If you run `make void-kernel`, also merge the commented kernel/initrd/modules lines.
runtime_dir = "/abs/path/to/banger/runtime" runtime_dir = "/abs/path/to/banger/build/runtime"
default_image_name = "void-exp" default_image_name = "void-exp"
default_rootfs = "/abs/path/to/banger/runtime/rootfs-void.ext4" default_rootfs = "/abs/path/to/banger/build/runtime/rootfs-void.ext4"
default_work_seed = "/abs/path/to/banger/runtime/rootfs-void.work-seed.ext4" default_work_seed = "/abs/path/to/banger/build/runtime/rootfs-void.work-seed.ext4"
# default_kernel = "/abs/path/to/banger/runtime/void-kernel/boot/vmlinux-6.12.77_1" # default_kernel = "/abs/path/to/banger/build/runtime/void-kernel/boot/vmlinux-6.12.77_1"
# default_initrd = "/abs/path/to/banger/runtime/void-kernel/boot/initramfs-6.12.77_1.img" # default_initrd = "/abs/path/to/banger/build/runtime/void-kernel/boot/initramfs-6.12.77_1.img"
# default_modules_dir = "/abs/path/to/banger/runtime/void-kernel/lib/modules/6.12.77_1" # default_modules_dir = "/abs/path/to/banger/build/runtime/void-kernel/lib/modules/6.12.77_1"

View file

@ -427,7 +427,7 @@ func TestAbsolutizeImageRegisterPaths(t *testing.T) {
KernelPath: filepath.Join(".", "runtime", "vmlinux"), KernelPath: filepath.Join(".", "runtime", "vmlinux"),
InitrdPath: filepath.Join(".", "runtime", "initrd.img"), InitrdPath: filepath.Join(".", "runtime", "initrd.img"),
ModulesDir: filepath.Join(".", "runtime", "modules"), ModulesDir: filepath.Join(".", "runtime", "modules"),
PackagesPath: filepath.Join(".", "packages.void"), PackagesPath: filepath.Join(".", "config", "packages.void"),
} }
wd, err := os.Getwd() wd, err := os.Getwd()

View file

@ -111,11 +111,11 @@ func TestEnsureDefaultImageReconcilesStaleUnmanagedDefaultInPlace(t *testing.T)
ID: "default-id", ID: "default-id",
Name: "default", Name: "default",
Managed: false, Managed: false,
RootfsPath: "/home/thales/projects/personal/banger/rootfs-docker.ext4", RootfsPath: "/home/thales/projects/personal/banger/build/runtime/rootfs-docker.ext4",
KernelPath: "/home/thales/projects/personal/banger/wtf/root/boot/vmlinux-6.8.0-94-generic", KernelPath: "/home/thales/projects/personal/banger/build/runtime/wtf/root/boot/vmlinux-6.8.0-94-generic",
InitrdPath: "/home/thales/projects/personal/banger/wtf/root/boot/initrd.img-6.8.0-94-generic", InitrdPath: "/home/thales/projects/personal/banger/build/runtime/wtf/root/boot/initrd.img-6.8.0-94-generic",
ModulesDir: "/home/thales/projects/personal/banger/wtf/root/lib/modules/6.8.0-94-generic", ModulesDir: "/home/thales/projects/personal/banger/build/runtime/wtf/root/lib/modules/6.8.0-94-generic",
PackagesPath: "/home/thales/projects/personal/banger/packages.apt", PackagesPath: "/home/thales/projects/personal/banger/build/runtime/packages.apt",
Docker: true, Docker: true,
CreatedAt: now, CreatedAt: now,
UpdatedAt: now, UpdatedAt: now,

View file

@ -86,14 +86,24 @@ func ResolveRuntimeDir(configuredRuntimeDir, deprecatedRepoRoot string) string {
} }
exeDir := filepath.Dir(exe) exeDir := filepath.Dir(exe)
if filepath.Base(exeDir) == "bin" { if filepath.Base(exeDir) == "bin" {
if filepath.Base(filepath.Dir(exeDir)) == "build" {
buildRuntimeDir := filepath.Clean(filepath.Join(exeDir, "..", "runtime"))
if HasRuntimeBundle(buildRuntimeDir) {
return buildRuntimeDir
}
}
installRuntimeDir := filepath.Clean(filepath.Join(exeDir, "..", "lib", "banger")) installRuntimeDir := filepath.Clean(filepath.Join(exeDir, "..", "lib", "banger"))
if HasRuntimeBundle(installRuntimeDir) { if HasRuntimeBundle(installRuntimeDir) {
return installRuntimeDir return installRuntimeDir
} }
} }
sourceRuntimeDir := filepath.Join(exeDir, "runtime") for _, sourceRuntimeDir := range []string{
if HasRuntimeBundle(sourceRuntimeDir) { filepath.Join(exeDir, "build", "runtime"),
return sourceRuntimeDir filepath.Join(exeDir, "runtime"),
} {
if HasRuntimeBundle(sourceRuntimeDir) {
return sourceRuntimeDir
}
} }
return "" return ""
} }
@ -141,7 +151,7 @@ func BangerdPath() (string, error) {
return candidate, nil return candidate, nil
} }
} }
return "", errors.New("bangerd binary not found next to banger; build ./cmd/bangerd") return "", errors.New("bangerd binary not found next to banger; run `make build`")
} }
func RuntimeBundleHint() string { func RuntimeBundleHint() string {

View file

@ -35,9 +35,9 @@ func TestResolveRuntimeDirUsesInstalledLayout(t *testing.T) {
} }
} }
func TestResolveRuntimeDirUsesSourceCheckoutRuntimeSubdir(t *testing.T) { func TestResolveRuntimeDirUsesBuildRuntimeForSourceCheckoutBinary(t *testing.T) {
root := t.TempDir() root := t.TempDir()
runtimeDir := filepath.Join(root, "runtime") runtimeDir := filepath.Join(root, "build", "runtime")
createRuntimeBundle(t, runtimeDir) createRuntimeBundle(t, runtimeDir)
origExecutablePath := executablePath origExecutablePath := executablePath
@ -53,6 +53,24 @@ func TestResolveRuntimeDirUsesSourceCheckoutRuntimeSubdir(t *testing.T) {
} }
} }
func TestResolveRuntimeDirUsesBuildRuntimeForBuildBinExecutable(t *testing.T) {
root := t.TempDir()
runtimeDir := filepath.Join(root, "build", "runtime")
createRuntimeBundle(t, runtimeDir)
origExecutablePath := executablePath
executablePath = func() (string, error) {
return filepath.Join(root, "build", "bin", "banger"), nil
}
t.Cleanup(func() {
executablePath = origExecutablePath
})
if got := ResolveRuntimeDir("", ""); got != runtimeDir {
t.Fatalf("ResolveRuntimeDir() = %q, want %q", got, runtimeDir)
}
}
func createRuntimeBundle(t *testing.T, runtimeDir string) { func createRuntimeBundle(t *testing.T, runtimeDir string) {
t.Helper() t.Helper()
metadata := runtimebundle.BundleMetadata{ metadata := runtimebundle.BundleMetadata{

View file

@ -52,7 +52,13 @@ fi
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
BANGER_BIN="${BANGER_BIN:-$REPO_ROOT/banger}" if [[ -z "${BANGER_BIN:-}" ]]; then
if [[ -x "$REPO_ROOT/build/bin/banger" ]]; then
BANGER_BIN="$REPO_ROOT/build/bin/banger"
else
BANGER_BIN="$REPO_ROOT/banger"
fi
fi
if [[ ! -x "$BANGER_BIN" ]]; then if [[ ! -x "$BANGER_BIN" ]]; then
log "banger binary not found: $BANGER_BIN" log "banger binary not found: $BANGER_BIN"
log "run 'make build' or set BANGER_BIN" log "run 'make build' or set BANGER_BIN"

View file

@ -7,7 +7,7 @@ log() {
usage() { usage() {
cat <<'EOF' cat <<'EOF'
Usage: ./customize.sh <base-rootfs> [--out <path>] [--size <size>] [--kernel <path>] [--initrd <path>] [--docker] [--modules <dir>] Usage: ./scripts/customize.sh <base-rootfs> [--out <path>] [--size <size>] [--kernel <path>] [--initrd <path>] [--docker] [--modules <dir>]
Creates a copy of rootfs.ext4, optionally resizes it, boots a VM using the Creates a copy of rootfs.ext4, optionally resizes it, boots a VM using the
copy as a writable rootfs, then applies base configuration and packages. copy as a writable rootfs, then applies base configuration and packages.
@ -30,9 +30,10 @@ parse_size() {
} }
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DEFAULT_RUNTIME_DIR="$SCRIPT_DIR" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
if [[ -d "$SCRIPT_DIR/runtime" ]]; then DEFAULT_RUNTIME_DIR="$REPO_ROOT/build/runtime"
DEFAULT_RUNTIME_DIR="$SCRIPT_DIR/runtime" if [[ ! -d "$DEFAULT_RUNTIME_DIR" && -d "$REPO_ROOT/runtime" ]]; then
DEFAULT_RUNTIME_DIR="$REPO_ROOT/runtime"
fi fi
RUNTIME_DIR="${BANGER_RUNTIME_DIR:-$DEFAULT_RUNTIME_DIR}" RUNTIME_DIR="${BANGER_RUNTIME_DIR:-$DEFAULT_RUNTIME_DIR}"
if [[ ! -d "$RUNTIME_DIR" ]]; then if [[ ! -d "$RUNTIME_DIR" ]]; then
@ -40,7 +41,7 @@ if [[ ! -d "$RUNTIME_DIR" ]]; then
log "run 'make runtime-bundle' or set BANGER_RUNTIME_DIR" log "run 'make runtime-bundle' or set BANGER_RUNTIME_DIR"
exit 1 exit 1
fi fi
source "$RUNTIME_DIR/packages.sh" source "$SCRIPT_DIR/lib/packages.sh"
STATE="${BANGER_STATE_DIR:-${XDG_STATE_HOME:-$HOME/.local/state}/banger/image-build}" STATE="${BANGER_STATE_DIR:-${XDG_STATE_HOME:-$HOME/.local/state}/banger/image-build}"
VM_ROOT="$STATE/vms" VM_ROOT="$STATE/vms"
mkdir -p "$VM_ROOT" mkdir -p "$VM_ROOT"
@ -83,8 +84,12 @@ resolve_banger_bin() {
printf '%s\n' "$BANGER_BIN" printf '%s\n' "$BANGER_BIN"
return return
fi fi
if [[ -x "$SCRIPT_DIR/banger" ]]; then if [[ -x "$REPO_ROOT/build/bin/banger" ]]; then
printf '%s\n' "$SCRIPT_DIR/banger" printf '%s\n' "$REPO_ROOT/build/bin/banger"
return
fi
if [[ -x "$REPO_ROOT/banger" ]]; then
printf '%s\n' "$REPO_ROOT/banger"
return return
fi fi
if command -v banger >/dev/null 2>&1; then if command -v banger >/dev/null 2>&1; then

View file

@ -7,7 +7,7 @@ log() {
usage() { usage() {
cat <<'EOF' cat <<'EOF'
Usage: ./interactive.sh <base-rootfs> [--out <path>] [--size <size>] Usage: ./scripts/interactive.sh <base-rootfs> [--out <path>] [--size <size>]
Creates a writable copy of the base rootfs and boots a VM so you can Creates a writable copy of the base rootfs and boots a VM so you can
customize it manually over SSH. No automatic package/config changes customize it manually over SSH. No automatic package/config changes
@ -30,10 +30,11 @@ parse_size() {
return 1 return 1
} }
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DEFAULT_RUNTIME_DIR="$DIR" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
if [[ -d "$DIR/runtime" ]]; then DEFAULT_RUNTIME_DIR="$REPO_ROOT/build/runtime"
DEFAULT_RUNTIME_DIR="$DIR/runtime" if [[ ! -d "$DEFAULT_RUNTIME_DIR" && -d "$REPO_ROOT/runtime" ]]; then
DEFAULT_RUNTIME_DIR="$REPO_ROOT/runtime"
fi fi
RUNTIME_DIR="${BANGER_RUNTIME_DIR:-$DEFAULT_RUNTIME_DIR}" RUNTIME_DIR="${BANGER_RUNTIME_DIR:-$DEFAULT_RUNTIME_DIR}"
if [[ ! -d "$RUNTIME_DIR" ]]; then if [[ ! -d "$RUNTIME_DIR" ]]; then
@ -77,8 +78,12 @@ resolve_banger_bin() {
printf '%s\n' "$BANGER_BIN" printf '%s\n' "$BANGER_BIN"
return return
fi fi
if [[ -x "$DIR/banger" ]]; then if [[ -x "$REPO_ROOT/build/bin/banger" ]]; then
printf '%s\n' "$DIR/banger" printf '%s\n' "$REPO_ROOT/build/bin/banger"
return
fi
if [[ -x "$REPO_ROOT/banger" ]]; then
printf '%s\n' "$REPO_ROOT/banger"
return return
fi fi
if command -v banger >/dev/null 2>&1; then if command -v banger >/dev/null 2>&1; then

View file

@ -1,7 +1,8 @@
#!/usr/bin/env bash #!/usr/bin/env bash
BANGER_PACKAGES_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" readonly BANGER_PACKAGES_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BANGER_APT_PACKAGES_FILE="${BANGER_APT_PACKAGES_FILE:-$BANGER_PACKAGES_DIR/packages.apt}" readonly BANGER_REPO_ROOT="$(cd "$BANGER_PACKAGES_DIR/../.." && pwd)"
BANGER_APT_PACKAGES_FILE="${BANGER_APT_PACKAGES_FILE:-$BANGER_REPO_ROOT/config/packages.apt}"
banger_packages_file() { banger_packages_file() {
printf '%s' "$BANGER_APT_PACKAGES_FILE" printf '%s' "$BANGER_APT_PACKAGES_FILE"

View file

@ -7,21 +7,21 @@ log() {
usage() { usage() {
cat <<'EOF' cat <<'EOF'
Usage: ./make-rootfs-void.sh [--out <path>] [--size <size>] [--mirror <url>] [--arch <arch>] [--packages <path>] Usage: ./scripts/make-rootfs-void.sh [--out <path>] [--size <size>] [--mirror <url>] [--arch <arch>] [--packages <path>]
Build an experimental Void Linux rootfs image plus a matching /root work-seed. Build an experimental Void Linux rootfs image plus a matching /root work-seed.
Defaults: Defaults:
--out ./runtime/rootfs-void.ext4 --out ./build/runtime/rootfs-void.ext4
--size 2G --size 2G
--mirror https://repo-default.voidlinux.org --mirror https://repo-default.voidlinux.org
--arch x86_64 --arch x86_64
--packages ./packages.void --packages ./config/packages.void
This path is experimental and local-only. If ./runtime/void-kernel exists it This path is experimental and local-only. If ./build/runtime/void-kernel exists
uses the staged Void kernel modules from that directory; otherwise it falls back it uses the staged Void kernel modules from that directory; otherwise it falls
to the current runtime bundle modules. It does not change the default Debian back to the current runtime bundle modules. It does not change the default
image flow. Debian image flow.
EOF EOF
} }
@ -53,8 +53,12 @@ resolve_banger_bin() {
printf '%s\n' "$BANGER_BIN" printf '%s\n' "$BANGER_BIN"
return return
fi fi
if [[ -x "$SCRIPT_DIR/banger" ]]; then if [[ -x "$REPO_ROOT/build/bin/banger" ]]; then
printf '%s\n' "$SCRIPT_DIR/banger" printf '%s\n' "$REPO_ROOT/build/bin/banger"
return
fi
if [[ -x "$REPO_ROOT/banger" ]]; then
printf '%s\n' "$REPO_ROOT/banger"
return return
fi fi
if command -v banger >/dev/null 2>&1; then if command -v banger >/dev/null 2>&1; then
@ -377,13 +381,14 @@ cleanup() {
} }
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PACKAGES_FILE="$SCRIPT_DIR/packages.void" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
PACKAGES_FILE="$REPO_ROOT/config/packages.void"
export BANGER_APT_PACKAGES_FILE="$PACKAGES_FILE" export BANGER_APT_PACKAGES_FILE="$PACKAGES_FILE"
source "$SCRIPT_DIR/packages.sh" source "$SCRIPT_DIR/lib/packages.sh"
DEFAULT_RUNTIME_DIR="$SCRIPT_DIR" DEFAULT_RUNTIME_DIR="$REPO_ROOT/build/runtime"
if [[ -d "$SCRIPT_DIR/runtime" ]]; then if [[ ! -d "$DEFAULT_RUNTIME_DIR" && -d "$REPO_ROOT/runtime" ]]; then
DEFAULT_RUNTIME_DIR="$SCRIPT_DIR/runtime" DEFAULT_RUNTIME_DIR="$REPO_ROOT/runtime"
fi fi
RUNTIME_DIR="${BANGER_RUNTIME_DIR:-$DEFAULT_RUNTIME_DIR}" RUNTIME_DIR="${BANGER_RUNTIME_DIR:-$DEFAULT_RUNTIME_DIR}"
if [[ ! -d "$RUNTIME_DIR" ]]; then if [[ ! -d "$RUNTIME_DIR" ]]; then
@ -401,8 +406,8 @@ ARCH="x86_64"
MISE_VERSION="v2025.12.0" MISE_VERSION="v2025.12.0"
MISE_INSTALL_PATH="/usr/local/bin/mise" MISE_INSTALL_PATH="/usr/local/bin/mise"
OPENCODE_TOOL="github:anomalyco/opencode" OPENCODE_TOOL="github:anomalyco/opencode"
GUESTNET_BOOTSTRAP_SCRIPT="$SCRIPT_DIR/internal/guestnet/assets/bootstrap.sh" GUESTNET_BOOTSTRAP_SCRIPT="$REPO_ROOT/internal/guestnet/assets/bootstrap.sh"
GUESTNET_VOID_CORE_SERVICE="$SCRIPT_DIR/internal/guestnet/assets/void-core-service.sh" GUESTNET_VOID_CORE_SERVICE="$REPO_ROOT/internal/guestnet/assets/void-core-service.sh"
MODULES_DIR="$(bundle_path default_modules_dir "$RUNTIME_DIR/wtf/root/lib/modules/6.8.0-94-generic")" MODULES_DIR="$(bundle_path default_modules_dir "$RUNTIME_DIR/wtf/root/lib/modules/6.8.0-94-generic")"
VOID_KERNEL_MODULES_DIR="$(find_latest_module_dir "$RUNTIME_DIR/void-kernel/lib/modules" || true)" VOID_KERNEL_MODULES_DIR="$(find_latest_module_dir "$RUNTIME_DIR/void-kernel/lib/modules" || true)"
VSOCK_AGENT="$(bundle_path vsock_agent_path "$RUNTIME_DIR/banger-vsock-agent")" VSOCK_AGENT="$(bundle_path vsock_agent_path "$RUNTIME_DIR/banger-vsock-agent")"

View file

@ -7,19 +7,25 @@ log() {
usage() { usage() {
cat <<'EOF' cat <<'EOF'
Usage: ./make-rootfs.sh [--size <size>] [--base-rootfs <path>] Usage: ./scripts/make-rootfs.sh [--size <size>] [--base-rootfs <path>]
Builds rootfs-docker.ext4 using customize.sh. If --base-rootfs is omitted, Builds build/runtime/rootfs-docker.ext4 using scripts/customize.sh. If
the first existing file is used: --base-rootfs is omitted, the first existing file is used:
./rootfs.ext4 ./build/runtime/rootfs.ext4
./runtime/rootfs.ext4 (legacy fallback)
./ubuntu-noble-rootfs/rootfs.ext4 ./ubuntu-noble-rootfs/rootfs.ext4
./ubuntu-lts/rootfs.ext4 ./ubuntu-lts/rootfs.ext4
EOF EOF
} }
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$DIR/packages.sh" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
RUNTIME_DIR="${BANGER_RUNTIME_DIR:-$DIR/runtime}" source "$SCRIPT_DIR/lib/packages.sh"
DEFAULT_RUNTIME_DIR="$REPO_ROOT/build/runtime"
if [[ ! -d "$DEFAULT_RUNTIME_DIR" && -d "$REPO_ROOT/runtime" ]]; then
DEFAULT_RUNTIME_DIR="$REPO_ROOT/runtime"
fi
RUNTIME_DIR="${BANGER_RUNTIME_DIR:-$DEFAULT_RUNTIME_DIR}"
if [[ ! -d "$RUNTIME_DIR" ]]; then if [[ ! -d "$RUNTIME_DIR" ]]; then
log "runtime bundle not found: $RUNTIME_DIR" log "runtime bundle not found: $RUNTIME_DIR"
log "run 'make runtime-bundle' or set BANGER_RUNTIME_DIR" log "run 'make runtime-bundle' or set BANGER_RUNTIME_DIR"
@ -63,10 +69,10 @@ fi
if [[ -z "$BASE_ROOTFS" ]]; then if [[ -z "$BASE_ROOTFS" ]]; then
if [[ -f "$RUNTIME_DIR/rootfs.ext4" ]]; then if [[ -f "$RUNTIME_DIR/rootfs.ext4" ]]; then
BASE_ROOTFS="$RUNTIME_DIR/rootfs.ext4" BASE_ROOTFS="$RUNTIME_DIR/rootfs.ext4"
elif [[ -f "$DIR/ubuntu-noble-rootfs/rootfs.ext4" ]]; then elif [[ -f "$REPO_ROOT/ubuntu-noble-rootfs/rootfs.ext4" ]]; then
BASE_ROOTFS="$DIR/ubuntu-noble-rootfs/rootfs.ext4" BASE_ROOTFS="$REPO_ROOT/ubuntu-noble-rootfs/rootfs.ext4"
elif [[ -f "$DIR/ubuntu-lts/rootfs.ext4" ]]; then elif [[ -f "$REPO_ROOT/ubuntu-lts/rootfs.ext4" ]]; then
BASE_ROOTFS="$DIR/ubuntu-lts/rootfs.ext4" BASE_ROOTFS="$REPO_ROOT/ubuntu-lts/rootfs.ext4"
else else
log "no base rootfs found; run 'make runtime-bundle' or pass --base-rootfs" log "no base rootfs found; run 'make runtime-bundle' or pass --base-rootfs"
exit 1 exit 1
@ -76,7 +82,7 @@ fi
mkdir -p "$RUNTIME_DIR" mkdir -p "$RUNTIME_DIR"
log "building $OUT_ROOTFS from $BASE_ROOTFS" log "building $OUT_ROOTFS from $BASE_ROOTFS"
exec env BANGER_RUNTIME_DIR="$RUNTIME_DIR" "$DIR/customize.sh" "$BASE_ROOTFS" \ exec env BANGER_RUNTIME_DIR="$RUNTIME_DIR" "$SCRIPT_DIR/customize.sh" "$BASE_ROOTFS" \
--out "$OUT_ROOTFS" \ --out "$OUT_ROOTFS" \
--size "$SIZE_SPEC" \ --size "$SIZE_SPEC" \
--docker --docker

View file

@ -7,13 +7,14 @@ log() {
usage() { usage() {
cat <<'EOF' cat <<'EOF'
Usage: ./make-void-kernel.sh [--out-dir <path>] [--mirror <url>] [--arch <arch>] [--kernel-package <name>] [--print-register-flags] Usage: ./scripts/make-void-kernel.sh [--out-dir <path>] [--mirror <url>] [--arch <arch>] [--kernel-package <name>] [--print-register-flags]
Download and stage a Void Linux kernel under ./runtime/void-kernel for the Download and stage a Void Linux kernel under ./build/runtime/void-kernel for
the
experimental Void guest flow. experimental Void guest flow.
Defaults: Defaults:
--out-dir ./runtime/void-kernel --out-dir ./build/runtime/void-kernel
--mirror https://repo-default.voidlinux.org --mirror https://repo-default.voidlinux.org
--arch x86_64 --arch x86_64
--kernel-package linux6.12 --kernel-package linux6.12
@ -223,9 +224,10 @@ cleanup() {
} }
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DEFAULT_RUNTIME_DIR="$SCRIPT_DIR" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
if [[ -d "$SCRIPT_DIR/runtime" ]]; then DEFAULT_RUNTIME_DIR="$REPO_ROOT/build/runtime"
DEFAULT_RUNTIME_DIR="$SCRIPT_DIR/runtime" if [[ ! -d "$DEFAULT_RUNTIME_DIR" && -d "$REPO_ROOT/runtime" ]]; then
DEFAULT_RUNTIME_DIR="$REPO_ROOT/runtime"
fi fi
RUNTIME_DIR="${BANGER_RUNTIME_DIR:-$DEFAULT_RUNTIME_DIR}" RUNTIME_DIR="${BANGER_RUNTIME_DIR:-$DEFAULT_RUNTIME_DIR}"
OUT_DIR="$RUNTIME_DIR/void-kernel" OUT_DIR="$RUNTIME_DIR/void-kernel"
@ -282,10 +284,7 @@ if [[ "$ARCH" != "x86_64" ]]; then
log "this experimental downloader currently supports only x86_64" log "this experimental downloader currently supports only x86_64"
exit 1 exit 1
fi fi
if [[ ! -d "$RUNTIME_DIR" ]]; then mkdir -p "$RUNTIME_DIR"
log "runtime bundle not found: $RUNTIME_DIR"
exit 1
fi
if [[ -e "$OUT_DIR" ]]; then if [[ -e "$OUT_DIR" ]]; then
log "output directory already exists: $OUT_DIR" log "output directory already exists: $OUT_DIR"
log "remove it first if you want to re-stage a different Void kernel" log "remove it first if you want to re-stage a different Void kernel"

View file

@ -27,8 +27,12 @@ resolve_banger_bin() {
printf '%s\n' "$BANGER_BIN" printf '%s\n' "$BANGER_BIN"
return return
fi fi
if [[ -x "$SCRIPT_DIR/banger" ]]; then if [[ -x "$REPO_ROOT/build/bin/banger" ]]; then
printf '%s\n' "$SCRIPT_DIR/banger" printf '%s\n' "$REPO_ROOT/build/bin/banger"
return
fi
if [[ -x "$REPO_ROOT/banger" ]]; then
printf '%s\n' "$REPO_ROOT/banger"
return return
fi fi
if command -v banger >/dev/null 2>&1; then if command -v banger >/dev/null 2>&1; then
@ -40,9 +44,10 @@ resolve_banger_bin() {
} }
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DEFAULT_RUNTIME_DIR="$SCRIPT_DIR" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
if [[ -d "$SCRIPT_DIR/runtime" ]]; then DEFAULT_RUNTIME_DIR="$REPO_ROOT/build/runtime"
DEFAULT_RUNTIME_DIR="$SCRIPT_DIR/runtime" if [[ ! -d "$DEFAULT_RUNTIME_DIR" && -d "$REPO_ROOT/runtime" ]]; then
DEFAULT_RUNTIME_DIR="$REPO_ROOT/runtime"
fi fi
RUNTIME_DIR="${BANGER_RUNTIME_DIR:-$DEFAULT_RUNTIME_DIR}" RUNTIME_DIR="${BANGER_RUNTIME_DIR:-$DEFAULT_RUNTIME_DIR}"
@ -50,7 +55,7 @@ IMAGE_NAME="${VOID_IMAGE_NAME:-void-exp}"
BANGER_BIN="$(resolve_banger_bin)" BANGER_BIN="$(resolve_banger_bin)"
ROOTFS="$RUNTIME_DIR/rootfs-void.ext4" ROOTFS="$RUNTIME_DIR/rootfs-void.ext4"
WORK_SEED="$RUNTIME_DIR/rootfs-void.work-seed.ext4" WORK_SEED="$RUNTIME_DIR/rootfs-void.work-seed.ext4"
PACKAGES="$SCRIPT_DIR/packages.void" PACKAGES="$REPO_ROOT/config/packages.void"
if [[ ! -f "$ROOTFS" ]]; then if [[ ! -f "$ROOTFS" ]]; then
log "missing Void rootfs: $ROOTFS" log "missing Void rootfs: $ROOTFS"

View file

@ -5,10 +5,11 @@ log() {
printf '[verify] %s\n' "$*" printf '[verify] %s\n' "$*"
} }
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
DEFAULT_RUNTIME_DIR="$DIR" REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
if [[ -d "$DIR/runtime" ]]; then DEFAULT_RUNTIME_DIR="$REPO_ROOT/build/runtime"
DEFAULT_RUNTIME_DIR="$DIR/runtime" if [[ ! -d "$DEFAULT_RUNTIME_DIR" && -d "$REPO_ROOT/runtime" ]]; then
DEFAULT_RUNTIME_DIR="$REPO_ROOT/runtime"
fi fi
RUNTIME_DIR="${BANGER_RUNTIME_DIR:-$DEFAULT_RUNTIME_DIR}" RUNTIME_DIR="${BANGER_RUNTIME_DIR:-$DEFAULT_RUNTIME_DIR}"
SSH_KEY="$RUNTIME_DIR/id_ed25519" SSH_KEY="$RUNTIME_DIR/id_ed25519"
@ -35,6 +36,29 @@ SSH_COMMON_ARGS=(
) )
OPENCODE_PORT=4096 OPENCODE_PORT=4096
resolve_banger_bin() {
if [[ -n "${BANGER_BIN:-}" ]]; then
printf '%s\n' "$BANGER_BIN"
return
fi
if [[ -x "$REPO_ROOT/build/bin/banger" ]]; then
printf '%s\n' "$REPO_ROOT/build/bin/banger"
return
fi
if [[ -x "$REPO_ROOT/banger" ]]; then
printf '%s\n' "$REPO_ROOT/banger"
return
fi
if command -v banger >/dev/null 2>&1; then
command -v banger
return
fi
log "banger binary not found; run 'make build' or set BANGER_BIN"
exit 1
}
BANGER_BIN="$(resolve_banger_bin)"
firecracker_running() { firecracker_running() {
local pid="$1" local pid="$1"
local api_sock="$2" local api_sock="$2"
@ -85,7 +109,7 @@ wait_for_tcp() {
} }
refresh_vm_metadata() { refresh_vm_metadata() {
if ! VM_JSON="$(./banger vm show "$VM_NAME" 2>/dev/null)"; then if ! VM_JSON="$("$BANGER_BIN" vm show "$VM_NAME" 2>/dev/null)"; then
return 1 return 1
fi fi
TAP="$(printf '%s\n' "$VM_JSON" | jq -r '.runtime.tap_device // empty')" TAP="$(printf '%s\n' "$VM_JSON" | jq -r '.runtime.tap_device // empty')"
@ -125,13 +149,13 @@ wait_for_vm_ready() {
dump_diagnostics() { dump_diagnostics() {
log "diagnostics for $VM_NAME" log "diagnostics for $VM_NAME"
./banger vm show "$VM_NAME" || true "$BANGER_BIN" vm show "$VM_NAME" || true
if [[ "${PID:-0}" -gt 0 ]]; then if [[ "${PID:-0}" -gt 0 ]]; then
log "process state for pid $PID" log "process state for pid $PID"
ps -fp "$PID" || true ps -fp "$PID" || true
fi fi
log "recent firecracker log" log "recent firecracker log"
./banger vm logs "$VM_NAME" 2>/dev/null | tail -n 200 || true "$BANGER_BIN" vm logs "$VM_NAME" 2>/dev/null | tail -n 200 || true
if [[ -f "$DAEMON_LOG" ]]; then if [[ -f "$DAEMON_LOG" ]]; then
log "recent daemon log" log "recent daemon log"
tail -n 200 "$DAEMON_LOG" || true tail -n 200 "$DAEMON_LOG" || true
@ -153,7 +177,7 @@ dump_diagnostics() {
usage() { usage() {
cat <<'EOF' cat <<'EOF'
Usage: ./verify.sh [--nat] [--image <name>] Usage: ./scripts/verify.sh [--nat] [--image <name>]
Run a basic smoke test for the Go VM workflow. Run a basic smoke test for the Go VM workflow.
Use --nat to additionally verify outbound NAT and host rule cleanup. Use --nat to additionally verify outbound NAT and host rule cleanup.
@ -198,20 +222,20 @@ LAST_ERROR=""
delete_vm() { delete_vm() {
if [[ -n "${VM_NAME:-}" ]]; then if [[ -n "${VM_NAME:-}" ]]; then
./banger vm delete "$VM_NAME" "$BANGER_BIN" vm delete "$VM_NAME"
fi fi
} }
cleanup() { cleanup() {
if [[ -n "${VM_NAME:-}" ]]; then if [[ -n "${VM_NAME:-}" ]]; then
./banger vm delete "$VM_NAME" >/dev/null 2>&1 || true "$BANGER_BIN" vm delete "$VM_NAME" >/dev/null 2>&1 || true
fi fi
} }
trap cleanup EXIT trap cleanup EXIT
log "starting VM" log "starting VM"
CREATE_ARGS=(./banger vm create --name "$VM_NAME") CREATE_ARGS=("$BANGER_BIN" vm create --name "$VM_NAME")
if [[ -n "$IMAGE_NAME" ]]; then if [[ -n "$IMAGE_NAME" ]]; then
CREATE_ARGS+=(--image "$IMAGE_NAME") CREATE_ARGS+=(--image "$IMAGE_NAME")
fi fi
@ -267,7 +291,7 @@ if ! wait_for_tcp "$GUEST_IP" "$OPENCODE_PORT" "$BOOT_DEADLINE"; then
fi fi
log "asserting opencode port is reported by banger vm ports" log "asserting opencode port is reported by banger vm ports"
if ! ./banger vm ports "$VM_NAME" | grep -F ":${OPENCODE_PORT}" >/dev/null 2>&1; then if ! "$BANGER_BIN" vm ports "$VM_NAME" | grep -F ":${OPENCODE_PORT}" >/dev/null 2>&1; then
log "banger vm ports did not report ${OPENCODE_PORT}" log "banger vm ports did not report ${OPENCODE_PORT}"
dump_diagnostics dump_diagnostics
exit 1 exit 1
@ -286,7 +310,7 @@ if ! delete_vm; then
fi fi
log "asserting cleanup success" log "asserting cleanup success"
if ./banger vm show "$VM_NAME" >/dev/null 2>&1; then if "$BANGER_BIN" vm show "$VM_NAME" >/dev/null 2>&1; then
log "vm still exists after delete: $VM_NAME" log "vm still exists after delete: $VM_NAME"
exit 1 exit 1
fi fi