2025-03-28 19:57:44 +01:00

155 lines
4.8 KiB
Go

package models
import (
"backea/internal/logging"
"github.com/joho/godotenv"
"github.com/spf13/viper"
)
// Configuration holds the complete application configuration
type Configuration struct {
Logging LoggingConfig `mapstructure:"logging"`
Defaults DefaultsConfig `mapstructure:"defaults"`
Services map[string]ServiceGroup `mapstructure:"services"`
}
// LoggingConfig holds logging configuration
type LoggingConfig struct {
LogLevel string `mapstructure:"log_level"`
LogFile string `mapstructure:"log_file"`
}
// 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"`
Username string `mapstructure:"username"`
}
// parseLogLevel converts string log level to LogLevel
func parseLogLevel(level string) logging.LogLevel {
switch level {
case "debug":
return logging.DEBUG
case "info":
return logging.INFO
case "warn":
return logging.WARN
case "error":
return logging.ERROR
case "fatal":
return logging.FATAL
default:
return logging.INFO // Default to INFO if not specified or invalid
}
}
// LoadConfig loads the application configuration from a file
func LoadConfig(configPath string) (*Configuration, error) {
// Create a logger first with default settings
logger := logging.GetLogger()
if err := godotenv.Load(); err != nil {
logger.Warn("Error loading .env file: %v", err)
}
viper.SetConfigFile(configPath)
if err := viper.ReadInConfig(); err != nil {
logger.Error("Failed to read config file: %v", err)
return nil, err
}
var config Configuration
if err := viper.Unmarshal(&config); err != nil {
logger.Error("Failed to unmarshal config: %v", err)
return nil, err
}
// Initialize logger with config settings
logLevel := parseLogLevel(config.Logging.LogLevel)
logging.InitLogger(logLevel, config.Logging.LogFile)
// Get the potentially reconfigured logger
logger = logging.GetLogger()
logger.Info("Initialized logger with level %v and output file %s",
config.Logging.LogLevel, config.Logging.LogFile)
// 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) {
logger.Debug("Applying default retention settings for service %s, config %s",
serviceName, configID)
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
}