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.
123 lines
3.3 KiB
Go
123 lines
3.3 KiB
Go
package paths
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
type Layout struct {
|
|
ConfigHome string
|
|
StateHome string
|
|
CacheHome string
|
|
RuntimeHome string
|
|
ConfigDir string
|
|
StateDir string
|
|
CacheDir string
|
|
RuntimeDir string
|
|
SocketPath string
|
|
DBPath string
|
|
DaemonLog string
|
|
VMsDir string
|
|
ImagesDir string
|
|
}
|
|
|
|
func Resolve() (Layout, error) {
|
|
home, err := os.UserHomeDir()
|
|
if err != nil {
|
|
return Layout{}, err
|
|
}
|
|
configHome := getenvDefault("XDG_CONFIG_HOME", filepath.Join(home, ".config"))
|
|
stateHome := getenvDefault("XDG_STATE_HOME", filepath.Join(home, ".local", "state"))
|
|
cacheHome := getenvDefault("XDG_CACHE_HOME", filepath.Join(home, ".cache"))
|
|
runtimeHome := os.Getenv("XDG_RUNTIME_DIR")
|
|
if runtimeHome == "" {
|
|
runtimeHome = filepath.Join(os.TempDir(), fmt.Sprintf("banger-runtime-%d", os.Getuid()))
|
|
}
|
|
|
|
layout := Layout{
|
|
ConfigHome: configHome,
|
|
StateHome: stateHome,
|
|
CacheHome: cacheHome,
|
|
RuntimeHome: runtimeHome,
|
|
ConfigDir: filepath.Join(configHome, "banger"),
|
|
StateDir: filepath.Join(stateHome, "banger"),
|
|
CacheDir: filepath.Join(cacheHome, "banger"),
|
|
RuntimeDir: filepath.Join(runtimeHome, "banger"),
|
|
}
|
|
layout.SocketPath = filepath.Join(layout.RuntimeDir, "bangerd.sock")
|
|
layout.DBPath = filepath.Join(layout.StateDir, "state.db")
|
|
layout.DaemonLog = filepath.Join(layout.StateDir, "bangerd.log")
|
|
layout.VMsDir = filepath.Join(layout.StateDir, "vms")
|
|
layout.ImagesDir = filepath.Join(layout.StateDir, "images")
|
|
return layout, nil
|
|
}
|
|
|
|
func Ensure(layout Layout) error {
|
|
for _, dir := range []string{layout.ConfigDir, layout.StateDir, layout.CacheDir, layout.RuntimeDir, layout.VMsDir, layout.ImagesDir} {
|
|
if err := os.MkdirAll(dir, 0o755); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
var executablePath = os.Executable
|
|
|
|
func BangerdPath() (string, error) {
|
|
if env := os.Getenv("BANGER_DAEMON_BIN"); env != "" {
|
|
return env, nil
|
|
}
|
|
exe, err := executablePath()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
dir := filepath.Dir(exe)
|
|
for _, candidate := range []string{
|
|
filepath.Join(dir, "bangerd"),
|
|
filepath.Join(dir, "bangerd.exe"),
|
|
} {
|
|
if _, err := os.Stat(candidate); err == nil {
|
|
return candidate, nil
|
|
}
|
|
}
|
|
return "", errors.New("bangerd binary not found next to banger; run `make build`")
|
|
}
|
|
|
|
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 {
|
|
if value := strings.TrimSpace(os.Getenv(key)); value != "" {
|
|
return value
|
|
}
|
|
return fallback
|
|
}
|