package config import ( "errors" "io" "os" "strings" "gopkg.in/yaml.v3" ) // Config captures node-agent runtime configuration. type Config struct { ListenAddr string `json:"listen_addr" yaml:"listen_addr"` LibvirtURI string `json:"libvirt_uri" yaml:"libvirt_uri"` LXCPath string `json:"lxc_path" yaml:"lxc_path"` PodmanSocket string `json:"podman_socket" yaml:"podman_socket"` VMPath string `json:"vm_path" yaml:"vm_path"` CTPath string `json:"ct_path" yaml:"ct_path"` AuthToken string `json:"auth_token" yaml:"auth_token"` StoragePools []StoragePool `json:"storage_pools" yaml:"storage_pools"` Bridges []Bridge `json:"bridges" yaml:"bridges"` } type StoragePool struct { Name string `json:"name" yaml:"name"` Type string `json:"type" yaml:"type"` Path string `json:"path" yaml:"path"` } type Bridge struct { Name string `json:"name" yaml:"name"` VlanAware bool `json:"vlan_aware" yaml:"vlan_aware"` MTU int `json:"mtu" yaml:"mtu"` } // LoadOrExit loads YAML/JSON config and applies defaults. It panics on fatal errors // to keep the agent simple for now. func LoadOrExit(path string) Config { cfg := Config{ ListenAddr: ":8000", LibvirtURI: "qemu:///system", LXCPath: "/etc/jagacloud/lxc", VMPath: "/etc/jagacloud/vm", CTPath: "/etc/jagacloud/ct", } f, err := os.Open(path) if err != nil { if errors.Is(err, os.ErrNotExist) { // File missing is allowed; defaults stay in place. return cfg } panic(err) } defer f.Close() raw, err := io.ReadAll(f) if err != nil { panic(err) } if err := yaml.Unmarshal(raw, &cfg); err != nil { panic(err) } cfg.ListenAddr = strings.TrimSpace(cfg.ListenAddr) if cfg.ListenAddr == "" { cfg.ListenAddr = ":8000" } if cfg.LibvirtURI == "" { cfg.LibvirtURI = "qemu:///system" } if cfg.LXCPath == "" { cfg.LXCPath = "/etc/jagacloud/lxc" } if cfg.VMPath == "" { cfg.VMPath = "/etc/jagacloud/vm" } if cfg.CTPath == "" { cfg.CTPath = "/etc/jagacloud/ct" } return cfg }