package config import ( "fmt" "os" "gopkg.in/yaml.v3" ) type Config struct { Server ServerConfig `yaml:"server"` Database DatabaseConfig `yaml:"database"` JWT JWTConfig `yaml:"jwt"` Controller ControllerConfig `yaml:"controller"` Agent AgentConfig `yaml:"agent"` Relay RelayConfig `yaml:"relay"` CORS CORSConfig `yaml:"cors"` RateLimit RateLimitConfig `yaml:"rate_limit"` Logging LoggingConfig `yaml:"logging"` Env EnvConfig `yaml:"env"` } type ServerConfig struct { Port int `yaml:"port"` } func (s *ServerConfig) Addr() string { return fmt.Sprintf(":%d", s.Port) } type DatabaseConfig struct { Driver string `yaml:"driver"` AutoMigrate bool `yaml:"auto_migrate"` InitData bool `yaml:"init_data"` SQLite SQLiteConfig `yaml:"sqlite"` MySQL MySQLConfig `yaml:"mysql"` } type SQLiteConfig struct { Path string `yaml:"path"` } type MySQLConfig struct { Host string `yaml:"host"` Port int `yaml:"port"` Username string `yaml:"username"` Password string `yaml:"password"` Database string `yaml:"database"` Charset string `yaml:"charset"` MaxIdleConns int `yaml:"max_idle_conns"` MaxOpenConns int `yaml:"max_open_conns"` } type JWTConfig struct { Secret string `yaml:"secret"` ExpireHours int `yaml:"expire_hours"` } type ControllerConfig struct { ListenPort int `yaml:"listen_port"` PublicEndpoint string `yaml:"public_endpoint"` PlanetID string `yaml:"planet_id"` } type AgentConfig struct { ControllerURL string `yaml:"controller_url"` ListenPort int `yaml:"listen_port"` TAPName string `yaml:"tap_name"` TAPMTU int `yaml:"tap_mtu"` NetworkID uint32 `yaml:"network_id"` PSK string `yaml:"psk"` StaticPeers []string `yaml:"static_peers"` } type RelayConfig struct { ListenPort int `yaml:"listen_port"` Realm string `yaml:"realm"` } type CORSConfig struct { AllowedOrigins []string `yaml:"allowed_origins"` } type RateLimitConfig struct { Enabled bool `yaml:"enabled"` RequestsPerSecond int `yaml:"requests_per_second"` BurstSize int `yaml:"burst_size"` } type LoggingConfig struct { Level string `yaml:"level"` Format string `yaml:"format"` } type EnvConfig struct { Name string `yaml:"name"` } func Load(path string) (*Config, error) { data, err := os.ReadFile(path) if err != nil { return nil, fmt.Errorf("read config: %w", err) } var cfg Config if err := yaml.Unmarshal(data, &cfg); err != nil { return nil, fmt.Errorf("parse config: %w", err) } setDefaults(&cfg) return &cfg, nil } func setDefaults(cfg *Config) { if cfg.Server.Port == 0 { cfg.Server.Port = 10001 } if cfg.Controller.ListenPort == 0 { cfg.Controller.ListenPort = 9993 } if cfg.Agent.TAPName == "" { cfg.Agent.TAPName = "zeromesh0" } if cfg.Agent.TAPMTU == 0 { cfg.Agent.TAPMTU = 2800 } if cfg.JWT.ExpireHours == 0 { cfg.JWT.ExpireHours = 720 } if cfg.Logging.Level == "" { cfg.Logging.Level = "info" } if cfg.Env.Name == "" { cfg.Env.Name = "dev" } } func (d *DatabaseConfig) BuildDSN() string { if d.Driver == "mysql" { return fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=%s&parseTime=True&loc=Local", d.MySQL.Username, d.MySQL.Password, d.MySQL.Host, d.MySQL.Port, d.MySQL.Database, d.MySQL.Charset) } return "" }