Files
pixa/internal/config/config.go

135 lines
2.9 KiB
Go

// Package config provides application configuration using smartconfig.
package config
import (
"fmt"
"os"
"path/filepath"
"git.eeqj.de/sneak/smartconfig"
"go.uber.org/fx"
"sneak.berlin/go/pixa/internal/globals"
"sneak.berlin/go/pixa/internal/logger"
)
// Default configuration values.
const (
DefaultPort = 8080
DefaultStateDir = "./data"
)
// ConfigParams defines dependencies for Config.
type ConfigParams struct {
fx.In
Globals *globals.Globals
Logger *logger.Logger
}
// Config holds application configuration values.
type Config struct {
Debug bool
MaintenanceMode bool
MetricsPassword string
MetricsUsername string
Port int
SentryDSN string
StateDir string
DBURL string
}
// New creates a new Config instance by loading configuration from file.
func New(lc fx.Lifecycle, params ConfigParams) (*Config, error) {
log := params.Logger.Get()
name := params.Globals.Appname
var sc *smartconfig.Config
var err error
// Try loading config from standard locations
configPaths := []string{
fmt.Sprintf("/etc/%s/config.yml", name),
fmt.Sprintf("/etc/%s/config.yaml", name),
filepath.Join(os.Getenv("HOME"), ".config", name, "config.yml"),
filepath.Join(os.Getenv("HOME"), ".config", name, "config.yaml"),
"config.yml",
"config.yaml",
}
for _, path := range configPaths {
if _, statErr := os.Stat(path); statErr == nil {
sc, err = smartconfig.NewFromConfigPath(path)
if err == nil {
log.Info("loaded config file", "path", path)
break
}
log.Warn("failed to parse config file", "path", path, "error", err)
}
}
if sc == nil {
log.Info("no config file found, using defaults")
}
c := &Config{
Debug: getBool(sc, "debug", false),
MaintenanceMode: getBool(sc, "maintenance_mode", false),
Port: getInt(sc, "port", DefaultPort),
StateDir: getString(sc, "state_dir", DefaultStateDir),
SentryDSN: getString(sc, "sentry_dsn", ""),
MetricsUsername: getString(sc, "metrics.username", ""),
MetricsPassword: getString(sc, "metrics.password", ""),
}
// Build DBURL from StateDir if not explicitly set
c.DBURL = getString(sc, "db_url", "")
if c.DBURL == "" {
c.DBURL = fmt.Sprintf("file:%s/state.sqlite3?_journal_mode=WAL", c.StateDir)
}
if c.Debug {
params.Logger.EnableDebugLogging()
}
return c, nil
}
func getString(sc *smartconfig.Config, key, defaultVal string) string {
if sc == nil {
return defaultVal
}
val, err := sc.GetString(key)
if err != nil {
return defaultVal
}
return val
}
func getInt(sc *smartconfig.Config, key string, defaultVal int) int {
if sc == nil {
return defaultVal
}
val, err := sc.GetInt(key)
if err != nil {
return defaultVal
}
return val
}
func getBool(sc *smartconfig.Config, key string, defaultVal bool) bool {
if sc == nil {
return defaultVal
}
val, err := sc.GetBool(key)
if err != nil {
return defaultVal
}
return val
}