155 lines
4.8 KiB
Go
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
|
|
}
|