package backup import ( "log" "github.com/joho/godotenv" "github.com/spf13/viper" ) // Configuration holds the complete application configuration type Configuration struct { Defaults DefaultsConfig `mapstructure:"defaults"` Services map[string]ServiceGroup `mapstructure:"services"` } // DefaultsConfig holds the default settings for all services type DefaultsConfig struct { Retention RetentionConfig `mapstructure:"retention"` } // ServiceGroup represents a service group with a common directory and multiple backup configurations type ServiceGroup struct { Directory string `mapstructure:"directory,omitempty"` Source SourceConfig `mapstructure:"source"` Hooks HooksConfig `mapstructure:"hooks"` BackupConfigs map[string]BackupConfig `mapstructure:"backup_configs"` } // SourceConfig represents source configuration for backups type SourceConfig struct { Host string `mapstructure:"host"` Path string `mapstructure:"path"` SSHKey string `mapstructure:"ssh_key"` } // HooksConfig contains the hooks to run before and after the backup type HooksConfig struct { BeforeHook string `mapstructure:"before_hook"` AfterHook string `mapstructure:"after_hook"` } // BackupConfig represents a specific backup configuration type BackupConfig struct { BackupStrategy StrategyConfig `mapstructure:"backup_strategy"` } // StrategyConfig represents a backup strategy configuration type StrategyConfig struct { Type string `mapstructure:"type"` Provider string `mapstructure:"provider"` Options string `mapstructure:"options,omitempty"` Retention RetentionConfig `mapstructure:"retention,omitempty"` Destination DestConfig `mapstructure:"destination"` } // RetentionConfig represents retention policy configuration type RetentionConfig struct { KeepLatest int `mapstructure:"keep_latest"` KeepHourly int `mapstructure:"keep_hourly"` KeepDaily int `mapstructure:"keep_daily"` KeepWeekly int `mapstructure:"keep_weekly"` KeepMonthly int `mapstructure:"keep_monthly"` KeepYearly int `mapstructure:"keep_yearly"` } // DestConfig represents destination configuration for remote backups type DestConfig struct { Host string `mapstructure:"host,omitempty"` Path string `mapstructure:"path"` SSHKey string `mapstructure:"ssh_key,omitempty"` } // LoadConfig loads the application configuration from a file func LoadConfig(configPath string) (*Configuration, error) { if err := godotenv.Load(); err != nil { log.Printf("Warning: Error loading .env file: %v", err) } viper.SetConfigFile(configPath) if err := viper.ReadInConfig(); err != nil { return nil, err } var config Configuration if err := viper.Unmarshal(&config); err != nil { return nil, err } // Apply default retention settings where needed for serviceName, service := range config.Services { for configID, backupConfig := range service.BackupConfigs { // If retention is not set, use defaults if isRetentionEmpty(backupConfig.BackupStrategy.Retention) { backupConfig.BackupStrategy.Retention = config.Defaults.Retention service.BackupConfigs[configID] = backupConfig } } config.Services[serviceName] = service } return &config, nil } // isRetentionEmpty checks if a retention config is empty (all zeros) func isRetentionEmpty(retention RetentionConfig) bool { return retention.KeepLatest == 0 && retention.KeepHourly == 0 && retention.KeepDaily == 0 && retention.KeepWeekly == 0 && retention.KeepMonthly == 0 && retention.KeepYearly == 0 }