package config import ( "fmt" "os" "time" "git.benadis.ru/gitops/benadis-rac/internal/constants" "gopkg.in/yaml.v3" ) // Config представляет основную конфигурацию приложения type Config struct { RACPath string `yaml:"rac_path"` ConnectionTimeout string `yaml:"connection_timeout"` CommandTimeout string `yaml:"command_timeout"` RetryCount int `yaml:"retry_count"` RetryDelay string `yaml:"retry_delay"` } // GetConnectionTimeout возвращает ConnectionTimeout как time.Duration func (c *Config) GetConnectionTimeout() (time.Duration, error) { return time.ParseDuration(c.ConnectionTimeout) } // GetCommandTimeout возвращает CommandTimeout как time.Duration func (c *Config) GetCommandTimeout() (time.Duration, error) { return time.ParseDuration(c.CommandTimeout) } // GetRetryDelay возвращает RetryDelay как time.Duration func (c *Config) GetRetryDelay() (time.Duration, error) { return time.ParseDuration(c.RetryDelay) } // ProjectCredentials представляет учетные данные для конкретного проекта type ProjectCredentials struct { ClusterAdmin string `yaml:"cluster_admin,omitempty"` ClusterAdminPassword string `yaml:"cluster_admin_password,omitempty"` DBAdmin string `yaml:"db_admin,omitempty"` DBAdminPassword string `yaml:"db_admin_password,omitempty"` } // Secret представляет секретную конфигурацию type Secret struct { ClusterAdmin string `yaml:"cluster_admin"` ClusterAdminPassword string `yaml:"cluster_admin_password"` DBAdmin string `yaml:"db_admin"` DBAdminPassword string `yaml:"db_admin_password"` Projects map[string]*ProjectCredentials `yaml:"projects,omitempty"` } // ServiceModeConfig представляет конфигурацию service-mode из project.yaml type ServiceModeConfig struct { ServerHost string `yaml:"server_host"` ServerPort int `yaml:"server_port"` RACPort int `yaml:"rac_port"` LogLevel string `yaml:"log_level"` ServerName string `yaml:"server_name"` BaseName string `yaml:"base_name"` Command string `yaml:"command"` } // ProjectConfig представляет конфигурацию проекта type ProjectConfig struct { ServiceMode *ServiceModeConfig `yaml:"service-mode"` } // AppConfig объединяет все конфигурации type AppConfig struct { Config *Config Secret *Secret Project *ProjectConfig } // LoadConfig загружает конфигурацию из файлов func LoadConfig(configPath, secretPath, projectPath string) (*AppConfig, error) { config, err := loadConfigFile(configPath) if err != nil { return nil, fmt.Errorf(constants.ErrLoadConfig, err) } secret, err := loadSecretFile(secretPath) if err != nil { return nil, fmt.Errorf(constants.ErrLoadSecret, err) } project, err := loadProjectFile(projectPath) if err != nil { return nil, fmt.Errorf("failed to load project config: %w", err) } return &AppConfig{ Config: config, Secret: secret, Project: project, }, nil } // loadConfigFile загружает основной конфигурационный файл func loadConfigFile(path string) (*Config, error) { data, err := os.ReadFile(path) if err != nil { return nil, fmt.Errorf("failed to read config file: %w", err) } var config Config if err := yaml.Unmarshal(data, &config); err != nil { return nil, fmt.Errorf("failed to unmarshal config: %w", err) } return &config, nil } // loadSecretFile загружает файл с секретами func loadSecretFile(path string) (*Secret, error) { data, err := os.ReadFile(path) if err != nil { return nil, fmt.Errorf("failed to read secret file: %w", err) } var secret Secret if err := yaml.Unmarshal(data, &secret); err != nil { return nil, fmt.Errorf("failed to unmarshal secret: %w", err) } return &secret, nil } // loadProjectFile загружает файл с настройками проекта func loadProjectFile(path string) (*ProjectConfig, error) { data, err := os.ReadFile(path) if err != nil { return nil, fmt.Errorf("failed to read project file: %w", err) } var project ProjectConfig if err := yaml.Unmarshal(data, &project); err != nil { return nil, fmt.Errorf("failed to unmarshal project: %w", err) } return &project, nil } // Validate проверяет корректность конфигурации func (ac *AppConfig) Validate() error { if ac.Config.RACPath == "" { return fmt.Errorf(constants.ErrRACPathRequired) } if ac.Project == nil || ac.Project.ServiceMode == nil { return fmt.Errorf("project service-mode configuration is required") } if ac.Project.ServiceMode.ServerHost == "" { return fmt.Errorf(constants.ErrServerHostRequired) } if ac.Project.ServiceMode.BaseName == "" { return fmt.Errorf(constants.ErrBaseNameRequired) } if ac.Secret.ClusterAdmin == "" { return fmt.Errorf(constants.ErrClusterAdminRequired) } if ac.Secret.DBAdmin == "" { return fmt.Errorf(constants.ErrDBAdminRequired) } return nil } // GetRACAddress возвращает адрес для подключения к RAC func (ac *AppConfig) GetRACAddress() string { return fmt.Sprintf("%s:%d", ac.Project.ServiceMode.ServerHost, ac.Project.ServiceMode.RACPort) } // GetClusterCredentials возвращает учетные данные кластера с учетом приоритета проекта func (ac *AppConfig) GetClusterCredentials(projectName string) (string, string) { // Проверяем настройки для конкретного проекта if ac.Secret.Projects != nil { if projectCreds, exists := ac.Secret.Projects[projectName]; exists { if projectCreds.ClusterAdmin != "" { return projectCreds.ClusterAdmin, projectCreds.ClusterAdminPassword } } } // Возвращаем глобальные настройки return ac.Secret.ClusterAdmin, ac.Secret.ClusterAdminPassword } // GetDBCredentials возвращает учетные данные базы данных с учетом приоритета проекта func (ac *AppConfig) GetDBCredentials(projectName string) (string, string) { // Проверяем настройки для конкретного проекта if ac.Secret.Projects != nil { if projectCreds, exists := ac.Secret.Projects[projectName]; exists { if projectCreds.DBAdmin != "" { return projectCreds.DBAdmin, projectCreds.DBAdminPassword } } } // Возвращаем глобальные настройки return ac.Secret.DBAdmin, ac.Secret.DBAdminPassword }