package config import ( "fmt" "os" "path/filepath" "github.com/spf13/viper" ) type Config struct { NetBox NetBoxConfig `mapstructure:"netbox"` Resolver ResolverConfig `mapstructure:"resolver"` Cache CacheConfig `mapstructure:"cache"` SSH SSHConfig `mapstructure:"ssh"` } type NetBoxConfig struct { URL string `mapstructure:"url"` Token string `mapstructure:"token"` } type ResolverConfig struct { Strategies []string `mapstructure:"strategies"` ManagementSubnets []string `mapstructure:"management_subnets"` InterfaceName string `mapstructure:"interface_name"` } type CacheConfig struct { TTL int `mapstructure:"ttl"` Path string `mapstructure:"path"` } type SSHConfig struct { DefaultUser string `mapstructure:"default_user"` } func Load() (*Config, error) { v := viper.New() v.SetDefault("resolver.strategies", []string{"management_subnet", "primary_ip"}) v.SetDefault("resolver.management_subnets", []string{}) v.SetDefault("cache.ttl", 3600) configDir, err := os.UserConfigDir() if err == nil { v.SetConfigName("netssh") v.SetConfigType("yaml") v.AddConfigPath(filepath.Join(configDir)) v.AddConfigPath(".") } v.SetEnvPrefix("NETSSH") v.AutomaticEnv() if err := v.ReadInConfig(); err != nil { if _, ok := err.(viper.ConfigFileNotFoundError); !ok { return nil, fmt.Errorf("reading config: %w", err) } } var cfg Config if err := v.Unmarshal(&cfg); err != nil { return nil, fmt.Errorf("parsing config: %w", err) } if cfg.Cache.Path == "" { cacheDir, err := os.UserCacheDir() if err != nil { cacheDir = filepath.Join(os.Getenv("HOME"), ".cache") } cfg.Cache.Path = filepath.Join(cacheDir, "netssh", "hosts.json") } return &cfg, nil }