Remove runtime-bundle image dependencies
Hard-cut banger away from source-checkout runtime bundles as an implicit source of\nimage and host defaults. Managed images now own their full boot set,\nimage build starts from an existing registered image, and daemon startup\nno longer synthesizes a default image from host paths.\n\nResolve Firecracker from PATH or firecracker_bin, make SSH keys config-owned\nwith an auto-managed XDG default, replace the external name generator and\npackage manifests with Go code, and keep the vsock helper as a companion\nbinary instead of a user-managed runtime asset.\n\nUpdate the manual scripts, web/CLI forms, config surface, and docs around\nthe new build/manual flow and explicit image registration semantics.\n\nValidation: GOCACHE=/tmp/banger-gocache go test ./..., bash -n scripts/*.sh,\nand make build.
This commit is contained in:
parent
01c7cb5e65
commit
572bf32424
44 changed files with 1194 additions and 3456 deletions
|
|
@ -5,10 +5,7 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"banger/internal/runtimebundle"
|
||||
)
|
||||
|
||||
type Layout struct {
|
||||
|
|
@ -69,71 +66,6 @@ func Ensure(layout Layout) error {
|
|||
|
||||
var executablePath = os.Executable
|
||||
|
||||
func ResolveRuntimeDir(configuredRuntimeDir, deprecatedRepoRoot string) string {
|
||||
for _, candidate := range []string{
|
||||
os.Getenv("BANGER_RUNTIME_DIR"),
|
||||
os.Getenv("BANGER_REPO_ROOT"),
|
||||
configuredRuntimeDir,
|
||||
deprecatedRepoRoot,
|
||||
} {
|
||||
if candidate = strings.TrimSpace(candidate); candidate != "" {
|
||||
return filepath.Clean(candidate)
|
||||
}
|
||||
}
|
||||
exe, err := executablePath()
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
exeDir := filepath.Dir(exe)
|
||||
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"))
|
||||
if HasRuntimeBundle(installRuntimeDir) {
|
||||
return installRuntimeDir
|
||||
}
|
||||
}
|
||||
for _, sourceRuntimeDir := range []string{
|
||||
filepath.Join(exeDir, "build", "runtime"),
|
||||
filepath.Join(exeDir, "runtime"),
|
||||
} {
|
||||
if HasRuntimeBundle(sourceRuntimeDir) {
|
||||
return sourceRuntimeDir
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func HasRuntimeBundle(dir string) bool {
|
||||
if strings.TrimSpace(dir) == "" {
|
||||
return false
|
||||
}
|
||||
if _, err := runtimebundle.LoadBundleMetadata(dir); err == nil {
|
||||
return true
|
||||
}
|
||||
required := []string{
|
||||
"firecracker",
|
||||
"customize.sh",
|
||||
"packages.apt",
|
||||
"wtf/root/boot/vmlinux-6.8.0-94-generic",
|
||||
}
|
||||
for _, name := range required {
|
||||
if _, err := os.Stat(filepath.Join(dir, name)); err != nil {
|
||||
return false
|
||||
}
|
||||
}
|
||||
for _, name := range []string{"rootfs-docker.ext4", "rootfs.ext4"} {
|
||||
if _, err := os.Stat(filepath.Join(dir, name)); err == nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func BangerdPath() (string, error) {
|
||||
if env := os.Getenv("BANGER_DAEMON_BIN"); env != "" {
|
||||
return env, nil
|
||||
|
|
@ -154,8 +86,33 @@ func BangerdPath() (string, error) {
|
|||
return "", errors.New("bangerd binary not found next to banger; run `make build`")
|
||||
}
|
||||
|
||||
func RuntimeBundleHint() string {
|
||||
return "run `make runtime-bundle` or set runtime_dir in ~/.config/banger/config.toml"
|
||||
func CompanionBinaryPath(name string) (string, error) {
|
||||
envNames := []string{
|
||||
"BANGER_" + strings.ToUpper(strings.NewReplacer("-", "_", ".", "_").Replace(name)) + "_BIN",
|
||||
}
|
||||
if trimmed, ok := strings.CutPrefix(name, "banger-"); ok {
|
||||
envNames = append(envNames, "BANGER_"+strings.ToUpper(strings.NewReplacer("-", "_", ".", "_").Replace(trimmed))+"_BIN")
|
||||
}
|
||||
for _, envName := range envNames {
|
||||
if env := strings.TrimSpace(os.Getenv(envName)); env != "" {
|
||||
return env, nil
|
||||
}
|
||||
}
|
||||
exe, err := executablePath()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
exeDir := filepath.Dir(exe)
|
||||
for _, candidate := range []string{
|
||||
filepath.Join(exeDir, name),
|
||||
filepath.Join(exeDir, "..", "lib", "banger", name),
|
||||
filepath.Join(exeDir, "..", "libexec", "banger", name),
|
||||
} {
|
||||
if _, err := os.Stat(candidate); err == nil {
|
||||
return candidate, nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("%s companion binary not found; run `make build` or reinstall banger", name)
|
||||
}
|
||||
|
||||
func getenvDefault(key, fallback string) string {
|
||||
|
|
@ -164,7 +121,3 @@ func getenvDefault(key, fallback string) string {
|
|||
}
|
||||
return fallback
|
||||
}
|
||||
|
||||
func RuntimeFallbackLabel() string {
|
||||
return strconv.Itoa(os.Getuid())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,44 +1,29 @@
|
|||
package paths
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"banger/internal/runtimebundle"
|
||||
)
|
||||
|
||||
func TestResolveRuntimeDirPrefersEnv(t *testing.T) {
|
||||
t.Setenv("BANGER_RUNTIME_DIR", "/env/runtime")
|
||||
func TestCompanionBinaryPathPrefersEnv(t *testing.T) {
|
||||
t.Setenv("BANGER_VSOCK_AGENT_BIN", "/tmp/custom-vsock-agent")
|
||||
|
||||
if got := ResolveRuntimeDir("/config/runtime", "/deprecated/repo"); got != "/env/runtime" {
|
||||
t.Fatalf("ResolveRuntimeDir() = %q, want /env/runtime", got)
|
||||
got, err := CompanionBinaryPath("banger-vsock-agent")
|
||||
if err != nil {
|
||||
t.Fatalf("CompanionBinaryPath: %v", err)
|
||||
}
|
||||
if got != "/tmp/custom-vsock-agent" {
|
||||
t.Fatalf("CompanionBinaryPath() = %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveRuntimeDirUsesInstalledLayout(t *testing.T) {
|
||||
func TestCompanionBinaryPathUsesSiblingBinary(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
runtimeDir := filepath.Join(root, "lib", "banger")
|
||||
createRuntimeBundle(t, runtimeDir)
|
||||
|
||||
origExecutablePath := executablePath
|
||||
executablePath = func() (string, error) {
|
||||
return filepath.Join(root, "bin", "banger"), nil
|
||||
companion := filepath.Join(root, "banger-vsock-agent")
|
||||
if err := os.WriteFile(companion, []byte("test"), 0o755); err != nil {
|
||||
t.Fatalf("write companion: %v", err)
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
executablePath = origExecutablePath
|
||||
})
|
||||
|
||||
if got := ResolveRuntimeDir("", ""); got != runtimeDir {
|
||||
t.Fatalf("ResolveRuntimeDir() = %q, want %q", got, runtimeDir)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveRuntimeDirUsesBuildRuntimeForSourceCheckoutBinary(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
runtimeDir := filepath.Join(root, "build", "runtime")
|
||||
createRuntimeBundle(t, runtimeDir)
|
||||
|
||||
origExecutablePath := executablePath
|
||||
executablePath = func() (string, error) {
|
||||
|
|
@ -48,64 +33,38 @@ func TestResolveRuntimeDirUsesBuildRuntimeForSourceCheckoutBinary(t *testing.T)
|
|||
executablePath = origExecutablePath
|
||||
})
|
||||
|
||||
if got := ResolveRuntimeDir("", ""); got != runtimeDir {
|
||||
t.Fatalf("ResolveRuntimeDir() = %q, want %q", got, runtimeDir)
|
||||
got, err := CompanionBinaryPath("banger-vsock-agent")
|
||||
if err != nil {
|
||||
t.Fatalf("CompanionBinaryPath: %v", err)
|
||||
}
|
||||
if got != companion {
|
||||
t.Fatalf("CompanionBinaryPath() = %q, want %q", got, companion)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolveRuntimeDirUsesBuildRuntimeForBuildBinExecutable(t *testing.T) {
|
||||
func TestCompanionBinaryPathUsesInstalledLibDir(t *testing.T) {
|
||||
root := t.TempDir()
|
||||
runtimeDir := filepath.Join(root, "build", "runtime")
|
||||
createRuntimeBundle(t, runtimeDir)
|
||||
companion := filepath.Join(root, "lib", "banger", "banger-vsock-agent")
|
||||
if err := os.MkdirAll(filepath.Dir(companion), 0o755); err != nil {
|
||||
t.Fatalf("mkdir companion dir: %v", err)
|
||||
}
|
||||
if err := os.WriteFile(companion, []byte("test"), 0o755); err != nil {
|
||||
t.Fatalf("write companion: %v", err)
|
||||
}
|
||||
|
||||
origExecutablePath := executablePath
|
||||
executablePath = func() (string, error) {
|
||||
return filepath.Join(root, "build", "bin", "banger"), nil
|
||||
return filepath.Join(root, "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) {
|
||||
t.Helper()
|
||||
metadata := runtimebundle.BundleMetadata{
|
||||
FirecrackerBin: "bin/firecracker",
|
||||
SSHKeyPath: "keys/id_ed25519",
|
||||
NamegenPath: "bin/namegen",
|
||||
CustomizeScript: "scripts/customize.sh",
|
||||
VSockAgentPath: "bin/banger-vsock-agent",
|
||||
DefaultPackages: "config/packages.apt",
|
||||
DefaultRootfs: "images/rootfs-docker.ext4",
|
||||
DefaultKernel: "kernels/vmlinux",
|
||||
}
|
||||
for _, rel := range []string{
|
||||
metadata.FirecrackerBin,
|
||||
metadata.SSHKeyPath,
|
||||
metadata.NamegenPath,
|
||||
metadata.CustomizeScript,
|
||||
metadata.VSockAgentPath,
|
||||
metadata.DefaultPackages,
|
||||
metadata.DefaultRootfs,
|
||||
metadata.DefaultKernel,
|
||||
} {
|
||||
path := filepath.Join(runtimeDir, rel)
|
||||
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
||||
t.Fatalf("mkdir %s: %v", filepath.Dir(path), err)
|
||||
}
|
||||
if err := os.WriteFile(path, []byte("test"), 0o644); err != nil {
|
||||
t.Fatalf("write %s: %v", path, err)
|
||||
}
|
||||
}
|
||||
data, err := json.Marshal(metadata)
|
||||
got, err := CompanionBinaryPath("banger-vsock-agent")
|
||||
if err != nil {
|
||||
t.Fatalf("Marshal: %v", err)
|
||||
t.Fatalf("CompanionBinaryPath: %v", err)
|
||||
}
|
||||
if err := os.WriteFile(filepath.Join(runtimeDir, runtimebundle.BundleMetadataFile), data, 0o644); err != nil {
|
||||
t.Fatalf("write bundle metadata: %v", err)
|
||||
if got != companion {
|
||||
t.Fatalf("CompanionBinaryPath() = %q, want %q", got, companion)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue