release prep: opt-in web UI, make uninstall, fix stale kernel-catalog docs

- WebListenAddr default is now "" (empty). The experimental web UI was
  running on 127.0.0.1:7777 by default, which surprises users who never
  opted in. Users who want it set `web_listen_addr = "127.0.0.1:7777"`
  in config.toml.
- `make uninstall` stops the daemon (if any) and removes the installed
  binaries. Preserves user data on disk but prints the paths so `rm -rf`
  can follow for a full purge. Documented in README next to install.
- docs/kernel-catalog.md: replace the `void-6.12` and `alpine-3.23`
  examples (never published) with `generic-6.12` (the only cataloged
  kernel today). Updates the versioning-convention example too.
This commit is contained in:
Thales Maciel 2026-04-19 12:43:58 -03:00
parent 221fb03d68
commit 78ff482bfa
No known key found for this signature in database
GPG key ID: 33112E6833C34679
6 changed files with 52 additions and 19 deletions

View file

@ -28,13 +28,14 @@ GO_LDFLAGS := -X banger/internal/buildinfo.Version=$(VERSION) -X banger/internal
.DEFAULT_GOAL := help
.PHONY: help build banger bangerd test fmt tidy clean install bench-create lint lint-go lint-shell coverage coverage-html coverage-total
.PHONY: help build banger bangerd test fmt tidy clean install uninstall bench-create lint lint-go lint-shell coverage coverage-html coverage-total
help:
@printf '%s\n' \
'Targets:' \
' make build Build ./build/bin/banger, ./build/bin/bangerd, and ./build/bin/banger-vsock-agent' \
' make install Build and install banger, bangerd, and the companion vsock helper' \
' make uninstall Stop the daemon and remove installed binaries (leaves user state by default)' \
' make test Run go test ./...' \
' make coverage Run tests with coverage; print per-package + total' \
' make coverage-html Open a browsable per-line HTML report (writes coverage.html)' \
@ -110,3 +111,19 @@ install: build
$(INSTALL) -m 0755 "$(BANGER_BIN)" "$(DESTDIR)$(BINDIR)/banger"
$(INSTALL) -m 0755 "$(BANGERD_BIN)" "$(DESTDIR)$(BINDIR)/bangerd"
$(INSTALL) -m 0755 "$(VSOCK_AGENT_BIN)" "$(DESTDIR)$(LIBDIR)/banger/banger-vsock-agent"
# uninstall stops a running daemon (if any) and removes the installed
# binaries. It does NOT touch user data (config, SSH keys, VM state,
# image/kernel caches) — rm -rf those paths manually if wanted; they
# are printed for convenience.
uninstall:
@if [ -x "$(DESTDIR)$(BINDIR)/banger" ]; then \
"$(DESTDIR)$(BINDIR)/banger" daemon stop >/dev/null 2>&1 || true; \
fi
rm -f "$(DESTDIR)$(BINDIR)/banger" "$(DESTDIR)$(BINDIR)/bangerd"
rm -rf "$(DESTDIR)$(LIBDIR)/banger"
@printf '\nRemoved binaries. User data is preserved at:\n'
@printf ' ~/.config/banger/ (config, ssh keys)\n'
@printf ' ~/.local/state/banger/ (VMs, images, kernels, db, logs)\n'
@printf ' ~/.cache/banger/ (OCI layer cache)\n'
@printf '\nDelete those paths manually if you want a full purge.\n'

View file

@ -32,6 +32,19 @@ Installs `banger` (CLI), `bangerd` (daemon, auto-starts on first
CLI call), and `banger-vsock-agent` (companion, under
`$PREFIX/lib/banger/`).
To remove the binaries (and stop the daemon):
```bash
make uninstall
```
User data stays in place — the target prints the paths so you can
`rm -rf` them if you want a full purge:
- `~/.config/banger/` — config, managed SSH keys
- `~/.local/state/banger/` — VM records, rootfs images, kernels, daemon DB/log
- `~/.cache/banger/` — OCI layer cache
### Shell completion
`banger` ships completion scripts for bash, zsh, fish, and
@ -116,8 +129,8 @@ Most commonly set:
- `ssh_key_path` — host SSH key. If unset, banger creates
`~/.config/banger/ssh/id_ed25519`.
- `firecracker_bin` — override the auto-resolved `PATH` lookup.
- `web_listen_addr` — experimental web UI (default `127.0.0.1:7777`;
set to `""` to disable).
- `web_listen_addr` — experimental web UI; disabled by default. Set
e.g. `"127.0.0.1:7777"` to enable.
Full key list in `internal/config/config.go`.

View file

@ -7,9 +7,9 @@ binary and updated each release.
End-user flow:
```bash
banger kernel list --available # browse the catalog
banger kernel pull void-6.12 # download a bundle (no sudo, no make)
banger image register --name void --rootfs … --kernel-ref void-6.12
banger kernel list --available # browse the catalog
banger kernel pull generic-6.12 # download a bundle (no sudo, no make)
banger image register --name myimg --rootfs … --kernel-ref generic-6.12
```
## Architecture
@ -88,10 +88,10 @@ the middle of a workflow.
## Versioning conventions
- **Entry names**: `<distro>-<major.minor>` (e.g. `void-6.12`,
`alpine-3.23`). The major.minor is the kernel line, not the distro
release. Patch-level bumps reuse the entry name and replace the
tarball; minor bumps create a new entry (`void-6.13`).
- **Entry names**: `<family>-<major.minor>` (e.g. `generic-6.12`).
The major.minor is the kernel line. Patch-level bumps reuse the
entry name and replace the tarball; minor bumps create a new entry
(`generic-6.13`).
- **Architecture**: only `x86_64` is published today. The `arch` field in
the catalog schema is additive — adding `arm64` later is a config
change, not a schema change.

View file

@ -1985,8 +1985,9 @@ func TestDaemonStatusIncludesLogPathWhenStopped(t *testing.T) {
if !strings.Contains(output, "dns: 127.0.0.1:42069") {
t.Fatalf("output = %q, want dns listener", output)
}
if !strings.Contains(output, "web: http://127.0.0.1:7777") {
t.Fatalf("output = %q, want default web listener", output)
// Web UI is opt-in; with no config it should be omitted entirely.
if strings.Contains(output, "web:") {
t.Fatalf("output = %q, should not list web (disabled by default)", output)
}
}

View file

@ -44,8 +44,10 @@ type fileSyncEntryFile struct {
func Load(layout paths.Layout) (model.DaemonConfig, error) {
cfg := model.DaemonConfig{
LogLevel: "info",
WebListenAddr: "127.0.0.1:7777",
LogLevel: "info",
// Experimental web UI is opt-in: users set web_listen_addr in
// config.toml (e.g. "127.0.0.1:7777") to enable it.
WebListenAddr: "",
AutoStopStaleAfter: 0,
StatsPollInterval: model.DefaultStatsPollInterval,
MetricsPollInterval: model.DefaultMetricsPollInterval,

View file

@ -39,8 +39,8 @@ func TestLoadDefaultsResolveFirecrackerAndGenerateSSHKey(t *testing.T) {
if cfg.DefaultImageName != "debian-bookworm" {
t.Fatalf("DefaultImageName = %q, want debian-bookworm", cfg.DefaultImageName)
}
if cfg.WebListenAddr != "127.0.0.1:7777" {
t.Fatalf("WebListenAddr = %q", cfg.WebListenAddr)
if cfg.WebListenAddr != "" {
t.Fatalf("WebListenAddr default = %q, want empty (experimental web UI is opt-in)", cfg.WebListenAddr)
}
}
@ -48,7 +48,7 @@ func TestLoadAppliesConfigOverrides(t *testing.T) {
configDir := t.TempDir()
data := []byte(`
log_level = "debug"
web_listen_addr = ""
web_listen_addr = "127.0.0.1:8080"
firecracker_bin = "/opt/firecracker"
ssh_key_path = "/tmp/custom-key"
default_image_name = "void"
@ -73,8 +73,8 @@ default_dns = "9.9.9.9"
if cfg.LogLevel != "debug" {
t.Fatalf("LogLevel = %q", cfg.LogLevel)
}
if cfg.WebListenAddr != "" {
t.Fatalf("WebListenAddr = %q, want empty", cfg.WebListenAddr)
if cfg.WebListenAddr != "127.0.0.1:8080" {
t.Fatalf("WebListenAddr = %q, want 127.0.0.1:8080", cfg.WebListenAddr)
}
if cfg.FirecrackerBin != "/opt/firecracker" {
t.Fatalf("FirecrackerBin = %q", cfg.FirecrackerBin)