package config import ( "fmt" "maps" "net/url" "github.com/ilyakaznacheev/cleanenv" log "github.com/sirupsen/logrus" ) type AzureStorageConfig struct { AccountName string `env:"AZ_ACCOUNT_NAME"` Container string `env:"AZ_CONTAINER"` AccountKey string `env:"AZ_ACCOUNT_KEY"` UseHTTPS bool `env:"AZ_USE_HTTPS" env-default:"true"` ServiceURL string `env:"AZ_SERVICE_URL"` Prefix string `env:"AZ_PREFIX"` Enabled bool `env:"AZ_STORAGE_ENABLED"` } type appConfig struct { SourceDbUrl string `env:"SOURCE_DB_URL"` SourceDbHost string `env:"SOURCE_DB_HOST"` SourceDbPort string `env:"SOURCE_DB_PORT"` SourceDbName string `env:"SOURCE_DB_NAME"` SourceDbUser string `env:"SOURCE_DB_USER"` SourceDbPwd string `env:"SOURCE_DB_PWD"` SourceDbOptions string `env:"SOURCE_DB_OPTIONS"` TargetDbUrl string `env:"TARGET_DB_URL"` TargetDbHost string `env:"TARGET_DB_HOST"` TargetDbPort string `env:"TARGET_DB_PORT"` TargetDbName string `env:"TARGET_DB_NAME"` TargetDbUser string `env:"TARGET_DB_USER"` TargetDbPwd string `env:"TARGET_DB_PWD"` TargetDbOptions string `env:"TARGET_DB_OPTIONS"` LogLevel string `env:"LOG_LEVEL" env-default:"INFO"` AzureStorage AzureStorageConfig } func (c *appConfig) ResolveSourceDbUrl(dbType string) (string, error) { if c.SourceDbUrl != "" { return c.SourceDbUrl, nil } u, err := buildDbUrl(dbType, c.SourceDbHost, c.SourceDbPort, c.SourceDbName, c.SourceDbUser, c.SourceDbPwd, c.SourceDbOptions) if err != nil { return "", fmt.Errorf("source DB: %w", err) } return u, nil } func (c *appConfig) ResolveTargetDbUrl(dbType string) (string, error) { if c.TargetDbUrl != "" { return c.TargetDbUrl, nil } u, err := buildDbUrl(dbType, c.TargetDbHost, c.TargetDbPort, c.TargetDbName, c.TargetDbUser, c.TargetDbPwd, c.TargetDbOptions) if err != nil { return "", fmt.Errorf("target DB: %w", err) } return u, nil } func buildDbUrl(dbType, host, port, name, user, pwd, options string) (string, error) { if host == "" { return "", fmt.Errorf("DB_HOST is required when DB_URL is not set") } if name == "" { return "", fmt.Errorf("DB_NAME is required when DB_URL is not set") } if user == "" { return "", fmt.Errorf("DB_USER is required when DB_URL is not set") } switch dbType { case "sqlserver": if port == "" { port = "1433" } q := url.Values{} if options != "" { extra, err := url.ParseQuery(options) if err != nil { return "", fmt.Errorf("invalid DB_OPTIONS: %w", err) } maps.Copy(q, extra) } q.Set("database", name) u := &url.URL{ Scheme: "sqlserver", Host: host + ":" + port, User: url.UserPassword(user, pwd), RawQuery: q.Encode(), } return u.String(), nil case "postgres": if port == "" { port = "5432" } u := &url.URL{ Scheme: "postgres", Host: host + ":" + port, User: url.UserPassword(user, pwd), Path: "/" + name, RawQuery: options, } return u.String(), nil default: return "", fmt.Errorf("unknown db type %q — cannot build URL from individual components", dbType) } } func getAppConfig() appConfig { var cfg appConfig err := cleanenv.ReadConfig(".env", &cfg) if err != nil { log.Warn("Could not load .env file") } err = cleanenv.ReadEnv(&cfg) if err != nil { log.Fatalf("Error al cargar variables: %v", err) } return cfg } var App appConfig = getAppConfig()