package config import ( "errors" "fmt" "os" "git.wzray.com/homelab/hivemind/internal/types" "github.com/BurntSushi/toml" ) type Configs struct { Master MasterConfig Dns DnsConfig Host HostConfig } type Config struct { Node NodeConfig Configs Configs Roles []types.Role } func FromFile(filename string) (Config, error) { data, err := os.ReadFile(filename) if err != nil { return Config{}, fmt.Errorf("read config file: %w", err) } var temp struct { Node NodeConfig `toml:"node"` Configs struct { Host *HostConfig `toml:"host"` Dns *DnsConfig `toml:"dns"` Master *MasterConfig `toml:"master"` } `toml:"roles"` } if err := toml.Unmarshal(data, &temp); err != nil { return Config{}, fmt.Errorf("parse config file: %w", err) } config := defaultConfig config.Node.Merge(temp.Node) if c := temp.Configs.Master; c != nil { c.set = true config.Roles = append(config.Roles, types.MasterRole) config.Configs.Master.Merge(*c) } if c := temp.Configs.Dns; c != nil { c.set = true config.Roles = append(config.Roles, types.DnsRole) config.Configs.Dns.Merge(*c) } if c := temp.Configs.Host; c != nil { c.set = true config.Roles = append(config.Roles, types.HostRole) config.Configs.Host.Merge(*c) } return config, nil } func (c Config) Validate() error { if err := c.Node.Validate(); err != nil { return fmt.Errorf("node: %w", err) } if c.Configs.Host.set { if err := c.Configs.Host.Validate(); err != nil { return fmt.Errorf("configs.host: %w", err) } } if c.Configs.Dns.set { if err := c.Configs.Dns.Validate(); err != nil { return fmt.Errorf("configs.dns: %w", err) } } if c.Configs.Host.set { if err := c.Configs.Master.Validate(); err != nil { return fmt.Errorf("configs.master: %w", err) } } if len(c.Roles) == 0 { return errors.New("no roles configured") } return nil }