
Some checks failed
CI/CD Pipeline / Run Tests (push) Has been cancelled
CI/CD Pipeline / Build Application (push) Has been cancelled
CI/CD Pipeline / Build Docker Image (push) Has been cancelled
CI/CD Pipeline / Security Scan (push) Has been cancelled
CI/CD Pipeline / Create Release (push) Has been cancelled
206 lines
5.2 KiB
Go
206 lines
5.2 KiB
Go
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
// Config represents the application configuration
|
|
type Config struct {
|
|
Server ServerConfig `yaml:"server"`
|
|
Proxy ProxyConfig `yaml:"proxy"`
|
|
NAT NATConfig `yaml:"nat"`
|
|
Logging LoggingConfig `yaml:"logging"`
|
|
Monitor MonitorConfig `yaml:"monitor"`
|
|
}
|
|
|
|
// ServerConfig represents server configuration
|
|
type ServerConfig struct {
|
|
Port int `yaml:"port"`
|
|
ReadTimeout int `yaml:"read_timeout"`
|
|
WriteTimeout int `yaml:"write_timeout"`
|
|
IdleTimeout int `yaml:"idle_timeout"`
|
|
TLSCertFile string `yaml:"tls_cert_file,omitempty"`
|
|
TLSKeyFile string `yaml:"tls_key_file,omitempty"`
|
|
}
|
|
|
|
// ProxyConfig represents reverse proxy configuration
|
|
type ProxyConfig struct {
|
|
Targets []TargetConfig `yaml:"targets"`
|
|
LoadBalancer string `yaml:"load_balancer"` // "roundrobin", "leastconn", "random"
|
|
HealthCheckPath string `yaml:"health_check_path"`
|
|
HealthCheckInterval int `yaml:"health_check_interval"`
|
|
}
|
|
|
|
// TargetConfig represents a proxy target
|
|
type TargetConfig struct {
|
|
Name string `yaml:"name"`
|
|
Address string `yaml:"address"`
|
|
Protocol string `yaml:"protocol"` // "http", "https"
|
|
Weight int `yaml:"weight"` // for weighted load balancing
|
|
Healthy bool `yaml:"-"` // health status
|
|
}
|
|
|
|
// NATConfig represents NAT traversal configuration
|
|
type NATConfig struct {
|
|
Enabled bool `yaml:"enabled"`
|
|
STUNServer string `yaml:"stun_server,omitempty"`
|
|
TURNServer string `yaml:"turn_server,omitempty"`
|
|
TURNUsername string `yaml:"turn_username,omitempty"`
|
|
TURNPassword string `yaml:"turn_password,omitempty"`
|
|
}
|
|
|
|
// LoggingConfig represents logging configuration
|
|
type LoggingConfig struct {
|
|
Level string `yaml:"level"` // "debug", "info", "warn", "error"
|
|
Format string `yaml:"format"` // "json", "text"
|
|
Output string `yaml:"output"` // "stdout", "file"
|
|
File string `yaml:"file,omitempty"`
|
|
}
|
|
|
|
// MonitorConfig represents monitoring configuration
|
|
type MonitorConfig struct {
|
|
Enabled bool `yaml:"enabled"`
|
|
Port int `yaml:"port"`
|
|
Path string `yaml:"path"`
|
|
Auth bool `yaml:"auth"`
|
|
Username string `yaml:"username,omitempty"`
|
|
Password string `yaml:"password,omitempty"`
|
|
}
|
|
|
|
// Load loads configuration from file
|
|
func Load(path string) (*Config, error) {
|
|
// Check if file exists
|
|
if _, err := os.Stat(path); os.IsNotExist(err) {
|
|
return nil, fmt.Errorf("configuration file not found: %s", path)
|
|
}
|
|
|
|
// Read file
|
|
data, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to read configuration file: %w", err)
|
|
}
|
|
|
|
// Parse YAML
|
|
var config Config
|
|
if err := yaml.Unmarshal(data, &config); err != nil {
|
|
return nil, fmt.Errorf("failed to parse configuration: %w", err)
|
|
}
|
|
|
|
// Set defaults
|
|
setDefaults(&config)
|
|
|
|
return &config, nil
|
|
}
|
|
|
|
// setDefaults sets default values for configuration
|
|
func setDefaults(c *Config) {
|
|
// Server defaults
|
|
if c.Server.Port == 0 {
|
|
c.Server.Port = 8080
|
|
}
|
|
if c.Server.ReadTimeout == 0 {
|
|
c.Server.ReadTimeout = 30
|
|
}
|
|
if c.Server.WriteTimeout == 0 {
|
|
c.Server.WriteTimeout = 30
|
|
}
|
|
if c.Server.IdleTimeout == 0 {
|
|
c.Server.IdleTimeout = 60
|
|
}
|
|
|
|
// Proxy defaults
|
|
if c.Proxy.LoadBalancer == "" {
|
|
c.Proxy.LoadBalancer = "roundrobin"
|
|
}
|
|
if c.Proxy.HealthCheckPath == "" {
|
|
c.Proxy.HealthCheckPath = "/health"
|
|
}
|
|
if c.Proxy.HealthCheckInterval == 0 {
|
|
c.Proxy.HealthCheckInterval = 30
|
|
}
|
|
|
|
// NAT defaults
|
|
if c.NAT.Enabled && c.NAT.STUNServer == "" {
|
|
c.NAT.STUNServer = "stun:stun.l.google.com:19302"
|
|
}
|
|
|
|
// Logging defaults
|
|
if c.Logging.Level == "" {
|
|
c.Logging.Level = "info"
|
|
}
|
|
if c.Logging.Format == "" {
|
|
c.Logging.Format = "json"
|
|
}
|
|
if c.Logging.Output == "" {
|
|
c.Logging.Output = "stdout"
|
|
}
|
|
|
|
// Monitor defaults
|
|
if c.Monitor.Enabled && c.Monitor.Port == 0 {
|
|
c.Monitor.Port = 9090
|
|
}
|
|
if c.Monitor.Enabled && c.Monitor.Path == "" {
|
|
c.Monitor.Path = "/metrics"
|
|
}
|
|
}
|
|
|
|
// CreateDefaultConfig creates a default configuration file
|
|
func CreateDefaultConfig(path string) error {
|
|
config := Config{
|
|
Server: ServerConfig{
|
|
Port: 8080,
|
|
ReadTimeout: 30,
|
|
WriteTimeout: 30,
|
|
IdleTimeout: 60,
|
|
},
|
|
Proxy: ProxyConfig{
|
|
LoadBalancer: "roundrobin",
|
|
HealthCheckPath: "/health",
|
|
HealthCheckInterval: 30,
|
|
Targets: []TargetConfig{
|
|
{
|
|
Name: "example",
|
|
Address: "http://localhost:3000",
|
|
Protocol: "http",
|
|
Weight: 1,
|
|
},
|
|
},
|
|
},
|
|
NAT: NATConfig{
|
|
Enabled: false,
|
|
STUNServer: "stun:stun.l.google.com:19302",
|
|
},
|
|
Logging: LoggingConfig{
|
|
Level: "info",
|
|
Format: "json",
|
|
Output: "stdout",
|
|
},
|
|
Monitor: MonitorConfig{
|
|
Enabled: true,
|
|
Port: 9090,
|
|
Path: "/metrics",
|
|
Auth: false,
|
|
},
|
|
}
|
|
|
|
data, err := yaml.Marshal(config)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to marshal default configuration: %w", err)
|
|
}
|
|
|
|
// Create directory if it doesn't exist
|
|
if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
|
|
return fmt.Errorf("failed to create configuration directory: %w", err)
|
|
}
|
|
|
|
// Write configuration file
|
|
if err := os.WriteFile(path, data, 0644); err != nil {
|
|
return fmt.Errorf("failed to write configuration file: %w", err)
|
|
}
|
|
|
|
return nil
|
|
} |