metis/pkg/service/settings.go

90 lines
2.6 KiB
Go

package service
import (
"os"
"path/filepath"
"strconv"
"strings"
)
// Settings configures the Metis service runtime.
type Settings struct {
BindAddr string
InventoryPath string
CacheDir string
ArtifactDir string
HistoryPath string
SnapshotsPath string
TargetsPath string
DefaultFlashHost string
FlashHosts []string
LocalHost string
AllowedGroups []string
MaxDeviceBytes int64
}
// FromEnv builds service settings with sensible defaults for local dev and in-cluster use.
func FromEnv() Settings {
dataDir := getenvDefault("METIS_DATA_DIR", "/var/lib/metis")
localHost := getenvDefault("METIS_LOCAL_HOST", hostnameOr("unknown"))
defaultFlashHost := getenvDefault("METIS_DEFAULT_FLASH_HOST", localHost)
flashHosts := splitList(getenvDefault("METIS_FLASH_HOSTS", defaultFlashHost))
return Settings{
BindAddr: getenvDefault("METIS_BIND_ADDR", ":8080"),
InventoryPath: getenvDefault("METIS_INVENTORY_PATH", "inventory.titan-rpi4.yaml"),
CacheDir: getenvDefault("METIS_CACHE_DIR", filepath.Join(dataDir, "cache")),
ArtifactDir: getenvDefault("METIS_ARTIFACT_DIR", filepath.Join(dataDir, "artifacts")),
HistoryPath: getenvDefault("METIS_HISTORY_PATH", filepath.Join(dataDir, "history.jsonl")),
SnapshotsPath: getenvDefault("METIS_SNAPSHOTS_PATH", filepath.Join(dataDir, "snapshots.json")),
TargetsPath: getenvDefault("METIS_TARGETS_PATH", filepath.Join(dataDir, "targets.json")),
DefaultFlashHost: defaultFlashHost,
FlashHosts: flashHosts,
LocalHost: localHost,
AllowedGroups: splitList(getenvDefault("METIS_ALLOWED_GROUPS", "admin,maintainer")),
MaxDeviceBytes: getenvInt64("METIS_MAX_DEVICE_BYTES", 300000000000),
}
}
func getenvDefault(key, fallback string) string {
if value := strings.TrimSpace(os.Getenv(key)); value != "" {
return value
}
return fallback
}
func getenvInt64(key string, fallback int64) int64 {
raw := strings.TrimSpace(os.Getenv(key))
if raw == "" {
return fallback
}
value, err := strconv.ParseInt(raw, 10, 64)
if err != nil {
return fallback
}
return value
}
func splitList(raw string) []string {
if strings.TrimSpace(raw) == "" {
return nil
}
parts := strings.Split(raw, ",")
result := make([]string, 0, len(parts))
for _, part := range parts {
part = strings.TrimSpace(part)
if part == "" {
continue
}
result = append(result, part)
}
return result
}
func hostnameOr(fallback string) string {
name, err := os.Hostname()
if err != nil || strings.TrimSpace(name) == "" {
return fallback
}
return strings.TrimSpace(name)
}