package monitoring import ( "encoding/json" "fmt" "os" "time" ) // OperationsConfigManager handles loading and saving operations configuration type OperationsConfigManager struct { configPath string config *OperationsConfig } // LoadOperationsConfig loads operations configuration from file func LoadOperationsConfig(configPath string) (*OperationsConfig, error) { manager := &OperationsConfigManager{ configPath: configPath, } return manager.Load() } // Load loads configuration from file func (ocm *OperationsConfigManager) Load() (*OperationsConfig, error) { // Check if config file exists if _, err := os.Stat(ocm.configPath); os.IsNotExist(err) { // Create default configuration ocm.config = ocm.createDefaultConfig() return ocm.config, ocm.Save() } // Read existing configuration data, err := os.ReadFile(ocm.configPath) if err != nil { return nil, fmt.Errorf("failed to read config file: %w", err) } // Parse configuration ocm.config = &OperationsConfig{} if err := json.Unmarshal(data, ocm.config); err != nil { return nil, fmt.Errorf("failed to parse config file: %w", err) } return ocm.config, nil } // Save saves configuration to file func (ocm *OperationsConfigManager) Save() error { if ocm.config == nil { return fmt.Errorf("no configuration to save") } // Create directory if it doesn't exist configDir := os.DirEntry(ocm.configPath) if configDir != nil { if err := os.MkdirAll(ocm.configPath, 0755); err != nil { return fmt.Errorf("failed to create config directory: %w", err) } } // Marshal configuration data, err := json.MarshalIndent(ocm.config, "", " ") if err != nil { return fmt.Errorf("failed to marshal config: %w", err) } // Write to file if err := os.WriteFile(ocm.configPath, data, 0644); err != nil { return fmt.Errorf("failed to write config file: %w", err) } return nil } // UpdateConfig updates configuration and saves to file func (ocm *OperationsConfigManager) UpdateConfig(updates map[string]interface{}) error { if ocm.config == nil { return fmt.Errorf("no configuration loaded") } // Apply updates for key, value := range updates { switch key { case "enabled": if boolVal, ok := value.(bool); ok { ocm.config.Enabled = boolVal } case "backup_path": if strVal, ok := value.(string); ok { ocm.config.BackupPath = strVal } case "recovery_path": if strVal, ok := value.(string); ok { ocm.config.RecoveryPath = strVal } case "retention_days": if intVal, ok := value.(int); ok { ocm.config.RetentionDays = intVal } case "compression": if boolVal, ok := value.(bool); ok { ocm.config.Compression = boolVal } case "encryption": if boolVal, ok := value.(bool); ok { ocm.config.Encryption = boolVal } case "metadata": if mapVal, ok := value.(map[string]string); ok { ocm.config.Metadata = mapVal } } } // Save updated configuration return ocm.Save() } // createDefaultConfig creates a default operations configuration func (ocm *OperationsConfigManager) createDefaultConfig() *OperationsConfig { return &OperationsConfig{ Enabled: true, BackupPath: "/var/lib/debian-forge/backups", RecoveryPath: "/var/lib/debian-forge/recovery", RetentionDays: 30, Compression: true, Encryption: false, Metadata: map[string]string{ "version": "1.0.0", "created": time.Now().Format(time.RFC3339), "description": "Default operations configuration for Debian Forge", }, } } // ValidateConfig validates the configuration func (ocm *OperationsConfigManager) ValidateConfig() error { if ocm.config == nil { return fmt.Errorf("no configuration loaded") } // Validate backup path if ocm.config.BackupPath == "" { return fmt.Errorf("backup path is required") } // Validate recovery path if ocm.config.RecoveryPath == "" { return fmt.Errorf("recovery path is required") } // Validate retention days if ocm.config.RetentionDays <= 0 { return fmt.Errorf("retention days must be positive") } // Validate paths are absolute if !isAbsolutePath(ocm.config.BackupPath) { return fmt.Errorf("backup path must be absolute") } if !isAbsolutePath(ocm.config.RecoveryPath) { return fmt.Errorf("recovery path must be absolute") } return nil } // isAbsolutePath checks if a path is absolute func isAbsolutePath(path string) bool { return len(path) > 0 && path[0] == '/' } // GetBackupConfig returns backup-specific configuration func (ocm *OperationsConfigManager) GetBackupConfig() *BackupConfig { if ocm.config == nil { return nil } return &BackupConfig{ Enabled: ocm.config.Enabled, AutoBackup: true, BackupPath: ocm.config.BackupPath, RetentionDays: ocm.config.RetentionDays, Compression: ocm.config.Compression, Encryption: ocm.config.Encryption, Metadata: ocm.config.Metadata, } } // GetRecoveryConfig returns recovery-specific configuration func (ocm *OperationsConfigManager) GetRecoveryConfig() *RecoveryConfig { if ocm.config == nil { return nil } return &RecoveryConfig{ Enabled: ocm.config.Enabled, AutoRecovery: false, RecoveryPath: ocm.config.RecoveryPath, Testing: true, Metadata: ocm.config.Metadata, } } // GetPersistenceConfig returns persistence-specific configuration func (ocm *OperationsConfigManager) GetPersistenceConfig() *PersistenceConfig { if ocm.config == nil { return nil } return &PersistenceConfig{ Enabled: ocm.config.Enabled, Replication: true, ReplicaCount: 3, SyncMode: "async", Metadata: ocm.config.Metadata, } } // GetTestingConfig returns testing-specific configuration func (ocm *OperationsConfigManager) GetTestingConfig() *TestingConfig { if ocm.config == nil { return nil } return &TestingConfig{ Enabled: ocm.config.Enabled, AutoTesting: false, TestInterval: 7 * 24 * time.Hour, // Weekly Metadata: ocm.config.Metadata, } }