feat: complete API-driven projects with infrastructure and business acceptance
This commit is contained in:
35
database/configOverlay_test.go
Normal file
35
database/configOverlay_test.go
Normal file
@@ -0,0 +1,35 @@
|
||||
package database
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestApplyEnvPreservesFilePoolAndHidesDSN(t *testing.T) {
|
||||
cfg := DefaultConfig()
|
||||
cfg.MaxOpenConns = 3
|
||||
cfg.MaxIdleConns = 1
|
||||
cfg.PingTimeout = time.Second
|
||||
t.Setenv("OMNI_TEST_DSN", "user:secret@tcp(localhost:3306)/test")
|
||||
t.Setenv("OMNI_TEST_MAX_IDLE_CONNS", "0")
|
||||
got, err := ApplyEnv(cfg, "OMNI_TEST_")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got.MaxOpenConns != 3 || got.MaxIdleConns != 0 || got.PingTimeout != time.Second {
|
||||
t.Fatalf("lost file defaults: %+v", got)
|
||||
}
|
||||
data, err := json.Marshal(got)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if strings.Contains(string(data), "secret") || !strings.Contains(string(data), "maxOpenConns") {
|
||||
t.Fatalf("unsafe config encoding: %s", data)
|
||||
}
|
||||
t.Setenv("OMNI_TEST_MAX_OPEN_CONNS", "bad")
|
||||
if _, err = ApplyEnv(cfg, "OMNI_TEST_"); err == nil {
|
||||
t.Fatal("invalid override accepted")
|
||||
}
|
||||
}
|
||||
@@ -14,13 +14,13 @@ import (
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Driver string
|
||||
DSN string
|
||||
MaxOpenConns int
|
||||
MaxIdleConns int
|
||||
ConnMaxLifetime time.Duration
|
||||
ConnMaxIdleTime time.Duration
|
||||
PingTimeout time.Duration
|
||||
Driver string `json:"driver"`
|
||||
DSN string `json:"-"`
|
||||
MaxOpenConns int `json:"maxOpenConns"`
|
||||
MaxIdleConns int `json:"maxIdleConns"`
|
||||
ConnMaxLifetime time.Duration `json:"connMaxLifetime"`
|
||||
ConnMaxIdleTime time.Duration `json:"connMaxIdleTime"`
|
||||
PingTimeout time.Duration `json:"pingTimeout"`
|
||||
}
|
||||
|
||||
func DefaultConfig() Config {
|
||||
@@ -35,16 +35,25 @@ func DefaultConfig() Config {
|
||||
|
||||
// ConfigFromEnv reads GO_OMNI_DB_* style settings. DSN is required.
|
||||
func ConfigFromEnv(prefix string) (Config, error) {
|
||||
return ApplyEnv(DefaultConfig(), prefix)
|
||||
}
|
||||
|
||||
// ApplyEnv overlays nonempty environment settings on file/default configuration.
|
||||
// DSN is environment-only when Config is decoded from JSON or YAML.
|
||||
func ApplyEnv(cfg Config, prefix string) (Config, error) {
|
||||
prefix = strings.TrimSpace(prefix)
|
||||
if prefix == "" {
|
||||
prefix = "GO_OMNI_DB_"
|
||||
}
|
||||
cfg := DefaultConfig()
|
||||
cfg.Driver = strings.TrimSpace(os.Getenv(prefix + "DRIVER"))
|
||||
if value := strings.TrimSpace(os.Getenv(prefix + "DRIVER")); value != "" {
|
||||
cfg.Driver = value
|
||||
}
|
||||
if cfg.Driver == "" {
|
||||
cfg.Driver = "mysql"
|
||||
}
|
||||
cfg.DSN = strings.TrimSpace(os.Getenv(prefix + "DSN"))
|
||||
if value := strings.TrimSpace(os.Getenv(prefix + "DSN")); value != "" {
|
||||
cfg.DSN = value
|
||||
}
|
||||
if cfg.DSN == "" {
|
||||
return Config{}, fmt.Errorf("%sDSN is required", prefix)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user