diff --git a/config/config.go b/config/config.go index 8a1c942..30fbbef 100644 --- a/config/config.go +++ b/config/config.go @@ -1,6 +1,7 @@ package config import ( + "strconv" "strings" "git.defalsify.org/vise.git/logging" @@ -23,6 +24,7 @@ var ( userDbConn string userDbConnMode storage.DbMode Languages []string + configManager *Config ) type Override struct { @@ -134,6 +136,17 @@ func GetConns() (storage.Conns, error) { // LoadConfig initializes the configuration values after environment variables are loaded. func LoadConfig() error { + configManager = NewConfig(logg) + + // Add configuration keys with validation + configManager.AddKey("HOST", "127.0.0.1", false, nil) + configManager.AddKey("PORT", "7123", false, func(v string) error { + _, err := strconv.Atoi(v) + return err + }) + configManager.AddKey("DB_CONN", "", true, nil) + // ... add other keys ? or is enough :/ ... + err := setConn() if err != nil { return err @@ -145,5 +158,7 @@ func LoadConfig() error { DefaultLanguage = defaultLanguage Languages = languages + // Report configuration + configManager.Report("INFO") return nil } diff --git a/config/config_test.go b/config/config_test.go new file mode 100644 index 0000000..503fcb3 --- /dev/null +++ b/config/config_test.go @@ -0,0 +1,61 @@ +package config + +import ( + "fmt" + "os" + "testing" + + "git.defalsify.org/vise.git/logging" +) + +// go test -tags configreport ./config/... ---> run with tag +func TestConfig(t *testing.T) { + logger := logging.NewVanilla().WithDomain("test") + cfg := NewConfig(logger) + + t.Run("Default Values", func(t *testing.T) { + cfg.AddKey("TEST_KEY", "default", false, nil) + value, err := cfg.GetValue("TEST_KEY") + t.Logf("Got value: %q, error: %v", value, err) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if value != "default" { + t.Errorf("expected 'default', got '%s'", value) + } + }) + + t.Run("Environment Override", func(t *testing.T) { + os.Setenv("TEST_ENV_KEY", "override") + defer os.Unsetenv("TEST_ENV_KEY") + + cfg.AddKey("TEST_ENV_KEY", "default", false, nil) + value, err := cfg.GetValue("TEST_ENV_KEY") + t.Logf("Got value: %q, error: %v", value, err) + if err != nil { + t.Errorf("unexpected error: %v", err) + } + if value != "override" { + t.Errorf("expected 'override', got '%s'", value) + } + }) + + t.Run("Validation", func(t *testing.T) { + validator := func(v string) error { + if v != "valid" { + return fmt.Errorf("invalid value") + } + return nil + } + + cfg.AddKey("VALIDATED_KEY", "valid", false, validator) + os.Setenv("VALIDATED_KEY", "invalid") + defer os.Unsetenv("VALIDATED_KEY") + + value, err := cfg.GetValue("VALIDATED_KEY") + t.Logf("Got value: %q, error: %v", value, err) + if err == nil { + t.Error("expected validation error, got nil") + } + }) +} diff --git a/config/reporter.go b/config/reporter.go new file mode 100644 index 0000000..34d823b --- /dev/null +++ b/config/reporter.go @@ -0,0 +1,96 @@ +//go:build configreport + +package config + +import ( + "fmt" + + "git.defalsify.org/vise.git/logging" + "git.grassecon.net/grassrootseconomics/visedriver/env" +) + +// ConfigValue represents a configuration key-value pair +type ConfigValue struct { + Key string + Default string + Validator func(string) error + Sensitive bool +} + +// Config handles configuration management and reporting +type Config struct { + values map[string]ConfigValue + logger logging.Vanilla +} + +func NewConfig(logger logging.Vanilla) *Config { + return &Config{ + values: make(map[string]ConfigValue), + logger: logger, + } +} + +// AddKey registers a new configuration key with optional validation +func (c *Config) AddKey(key string, defaultValue string, sensitive bool, validator func(string) error) { + c.values[key] = ConfigValue{ + Key: key, + Default: defaultValue, + Validator: validator, + Sensitive: sensitive, + } +} + +// GetValue returns the value for a given key, applying environment override if present +func (c *Config) GetValue(key string) (string, error) { + // Find config value by key + var cv ConfigValue + for _, v := range c.values { + if v.Key == key { + cv = v + break + } + } + + if cv.Key == "" { + return "", fmt.Errorf("configuration key not found: %s", key) + } + + // Get value from environment or default + value := env.GetEnv(key, cv.Default) + + // Validate if validator exists + if cv.Validator != nil && cv.Validator(value) != nil { + return "", fmt.Errorf("invalid value for key %s", key) + } + + return value, nil +} + +// Report outputs all configuration values at the specified log level +func (c *Config) Report(level string) { + c.logger.Debugf("Configuration Report:") + for _, cv := range c.values { + value, err := c.GetValue(cv.Key) + if err != nil { + c.logger.Errorf("Error getting value for %s: %v", cv.Key, err) + continue + } + + if cv.Sensitive { + value = "****" + } + + switch level { + case "DEBUG": + c.logger.Debugf("%s: %s", cv.Key, value) + case "INFO": + c.logger.Infof("%s: %s", cv.Key, value) + case "WARN": + c.logger.Warnf("%s: %s", cv.Key, value) + case "ERROR": + c.logger.Errorf("%s: %s", cv.Key, value) + default: + c.logger.Infof("%s: %s", cv.Key, value) + } + } +} diff --git a/config/reporter_noop.go b/config/reporter_noop.go new file mode 100644 index 0000000..67e4d71 --- /dev/null +++ b/config/reporter_noop.go @@ -0,0 +1,21 @@ +//go:build !configreport + +package config + +import ( + "git.defalsify.org/vise.git/logging" +) + +type Config struct{} + +func NewConfig(logger logging.Vanilla) *Config { + return &Config{} +} + +func (c *Config) AddKey(key string, defaultValue string, sensitive bool, validator func(string) error) {} + +func (c *Config) GetValue(key string) (string, error) { + return "", nil +} + +func (c *Config) Report(level string) {} \ No newline at end of file