Add registry, ingest, timeline, tickets features
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
@@ -33,14 +35,22 @@ func Load() (Config, error) {
|
||||
return Config{}, err
|
||||
}
|
||||
|
||||
return Config{
|
||||
cfg := Config{
|
||||
HTTPAddr: envOrDefault("HTTP_ADDR", ":9999"),
|
||||
ReadTimeout: readTimeout,
|
||||
WriteTimeout: writeTimeout,
|
||||
ShutdownGrace: shutdownGrace,
|
||||
DatabaseDSN: os.Getenv("DATABASE_DSN"),
|
||||
MigrationsDir: envOrDefault("MIGRATIONS_DIR", "migrations"),
|
||||
}, nil
|
||||
}
|
||||
|
||||
fileCfg, err := loadFileConfig()
|
||||
if err != nil {
|
||||
return Config{}, err
|
||||
}
|
||||
applyFileConfig(&cfg, fileCfg)
|
||||
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func envOrDefault(key, fallback string) string {
|
||||
@@ -66,3 +76,111 @@ func envDuration(key string, fallback time.Duration) (time.Duration, error) {
|
||||
|
||||
return time.Duration(seconds) * time.Second, nil
|
||||
}
|
||||
|
||||
type fileConfig struct {
|
||||
HTTPAddr *string `json:"http_addr"`
|
||||
ReadTimeoutSeconds *int `json:"read_timeout_seconds"`
|
||||
WriteTimeoutSeconds *int `json:"write_timeout_seconds"`
|
||||
ShutdownGraceSeconds *int `json:"shutdown_grace_seconds"`
|
||||
DatabaseDSN *string `json:"database_dsn"`
|
||||
Database *dbFileConfig `json:"database"`
|
||||
MigrationsDir *string `json:"migrations_dir"`
|
||||
}
|
||||
|
||||
type dbFileConfig struct {
|
||||
User *string `json:"user"`
|
||||
Password *string `json:"password"`
|
||||
Host *string `json:"host"`
|
||||
Port *int `json:"port"`
|
||||
Name *string `json:"name"`
|
||||
Params *string `json:"params"`
|
||||
}
|
||||
|
||||
func loadFileConfig() (fileConfig, error) {
|
||||
path := os.Getenv("CONFIG_FILE")
|
||||
if path == "" {
|
||||
path = "config.json"
|
||||
if _, err := os.Stat(path); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return fileConfig{}, nil
|
||||
}
|
||||
return fileConfig{}, err
|
||||
}
|
||||
} else {
|
||||
if _, err := os.Stat(path); err != nil {
|
||||
return fileConfig{}, fmt.Errorf("config file %s: %w", path, err)
|
||||
}
|
||||
}
|
||||
|
||||
raw, err := os.ReadFile(filepath.Clean(path))
|
||||
if err != nil {
|
||||
return fileConfig{}, err
|
||||
}
|
||||
|
||||
var cfg fileConfig
|
||||
if err := json.Unmarshal(raw, &cfg); err != nil {
|
||||
return fileConfig{}, fmt.Errorf("parse config file %s: %w", path, err)
|
||||
}
|
||||
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func applyFileConfig(cfg *Config, fileCfg fileConfig) {
|
||||
if fileCfg.HTTPAddr != nil && os.Getenv("HTTP_ADDR") == "" {
|
||||
cfg.HTTPAddr = *fileCfg.HTTPAddr
|
||||
}
|
||||
if fileCfg.ReadTimeoutSeconds != nil && os.Getenv("READ_TIMEOUT") == "" {
|
||||
if *fileCfg.ReadTimeoutSeconds > 0 {
|
||||
cfg.ReadTimeout = time.Duration(*fileCfg.ReadTimeoutSeconds) * time.Second
|
||||
}
|
||||
}
|
||||
if fileCfg.WriteTimeoutSeconds != nil && os.Getenv("WRITE_TIMEOUT") == "" {
|
||||
if *fileCfg.WriteTimeoutSeconds > 0 {
|
||||
cfg.WriteTimeout = time.Duration(*fileCfg.WriteTimeoutSeconds) * time.Second
|
||||
}
|
||||
}
|
||||
if fileCfg.ShutdownGraceSeconds != nil && os.Getenv("SHUTDOWN_GRACE") == "" {
|
||||
if *fileCfg.ShutdownGraceSeconds > 0 {
|
||||
cfg.ShutdownGrace = time.Duration(*fileCfg.ShutdownGraceSeconds) * time.Second
|
||||
}
|
||||
}
|
||||
if fileCfg.DatabaseDSN != nil && os.Getenv("DATABASE_DSN") == "" {
|
||||
cfg.DatabaseDSN = *fileCfg.DatabaseDSN
|
||||
}
|
||||
if cfg.DatabaseDSN == "" && os.Getenv("DATABASE_DSN") == "" {
|
||||
if dsn := buildDSN(fileCfg.Database); dsn != "" {
|
||||
cfg.DatabaseDSN = dsn
|
||||
}
|
||||
}
|
||||
if fileCfg.MigrationsDir != nil && os.Getenv("MIGRATIONS_DIR") == "" {
|
||||
cfg.MigrationsDir = *fileCfg.MigrationsDir
|
||||
}
|
||||
}
|
||||
|
||||
func buildDSN(db *dbFileConfig) string {
|
||||
if db == nil || db.Name == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
user := valueOrDefault(db.User, "reanimator")
|
||||
password := valueOrDefault(db.Password, "reanimator")
|
||||
host := valueOrDefault(db.Host, "127.0.0.1")
|
||||
port := intValueOrDefault(db.Port, 3306)
|
||||
params := valueOrDefault(db.Params, "parseTime=true")
|
||||
|
||||
return fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?%s", user, password, host, port, *db.Name, params)
|
||||
}
|
||||
|
||||
func valueOrDefault(value *string, fallback string) string {
|
||||
if value == nil || *value == "" {
|
||||
return fallback
|
||||
}
|
||||
return *value
|
||||
}
|
||||
|
||||
func intValueOrDefault(value *int, fallback int) int {
|
||||
if value == nil || *value <= 0 {
|
||||
return fallback
|
||||
}
|
||||
return *value
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user