You've already forked ionscale
mirror of
https://github.com/jsiebens/ionscale.git
synced 2026-04-05 12:32:58 +01:00
fix: change precedence order, env variables overrule file config
This commit is contained in:
@@ -5,6 +5,7 @@ go 1.19
|
||||
require (
|
||||
github.com/apparentlymart/go-cidr v1.1.0
|
||||
github.com/bufbuild/connect-go v0.4.0
|
||||
github.com/caarlos0/env/v6 v6.10.1
|
||||
github.com/caddyserver/certmagic v0.17.1
|
||||
github.com/coreos/go-oidc/v3 v3.3.0
|
||||
github.com/glebarez/sqlite v1.4.6
|
||||
@@ -13,6 +14,7 @@ require (
|
||||
github.com/hashicorp/go-bexpr v0.1.11
|
||||
github.com/hashicorp/go-hclog v1.3.0
|
||||
github.com/hashicorp/go-multierror v1.1.1
|
||||
github.com/imdario/mergo v0.3.12
|
||||
github.com/klauspost/compress v1.15.9
|
||||
github.com/labstack/echo-contrib v0.13.0
|
||||
github.com/labstack/echo/v4 v4.9.0
|
||||
|
||||
@@ -81,6 +81,8 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bufbuild/connect-go v0.4.0 h1:fIMyUYG8mXSTH+nnlOx9KmRUf3mBF0R2uKK+BQBoOHE=
|
||||
github.com/bufbuild/connect-go v0.4.0/go.mod h1:ZEtBnQ7J/m7bvWOW+H8T/+hKQCzPVfhhhICuvtcnjlI=
|
||||
github.com/caarlos0/env/v6 v6.10.1 h1:t1mPSxNpei6M5yAeu1qtRdPAK29Nbcf/n3G7x+b3/II=
|
||||
github.com/caarlos0/env/v6 v6.10.1/go.mod h1:hvp/ryKXKipEkcuYjs9mI4bBCg+UI0Yhgm5Zu0ddvwc=
|
||||
github.com/caddyserver/certmagic v0.17.1 h1:VrWANhQAj3brK7jAUKyN6XBHg56WsyorI/84Ilq1tCQ=
|
||||
github.com/caddyserver/certmagic v0.17.1/go.mod h1:pSS2aZcdKlrTZrb2DKuRafckx20o5Fz1EdDKEB8KOQM=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
@@ -276,6 +278,8 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
|
||||
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
|
||||
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
|
||||
+59
-106
@@ -2,7 +2,9 @@ package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/caarlos0/env/v6"
|
||||
"github.com/caddyserver/certmagic"
|
||||
"github.com/imdario/mergo"
|
||||
"github.com/jsiebens/ionscale/internal/key"
|
||||
"github.com/jsiebens/ionscale/internal/util"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
@@ -19,11 +21,7 @@ var (
|
||||
)
|
||||
|
||||
func LoadConfig(path string) (*Config, error) {
|
||||
config, err := defaultConfig()
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfg := defaultConfig()
|
||||
|
||||
if len(path) != 0 {
|
||||
expandedPath, err := homedir.Expand(path)
|
||||
@@ -41,88 +39,43 @@ func LoadConfig(path string) (*Config, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := yaml.Unmarshal(b, config); err != nil {
|
||||
if err := yaml.Unmarshal(b, cfg); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
KeepAliveInterval = config.PollNet.KeepAliveInterval
|
||||
|
||||
return config, nil
|
||||
}
|
||||
|
||||
const (
|
||||
httpListenAddrKey = "IONSCALE_HTTP_LISTEN_ADDR"
|
||||
httpsListenAddrKey = "IONSCALE_HTTPS_LISTEN_ADDR"
|
||||
serverUrlKey = "IONSCALE_SERVER_URL"
|
||||
keysSystemAdminKeyKey = "IONSCALE_SYSTEM_ADMIN_KEY"
|
||||
keysControlKeyKey = "IONSCALE_CONTROL_KEY"
|
||||
keysLegacyControlKeyKey = "IONSCALE_LEGACY_CONTROL_KEY"
|
||||
databaseUrlKey = "IONSCALE_DB_URL"
|
||||
tlsDisableKey = "IONSCALE_TLS_DISABLE"
|
||||
tlsForceHttpsKey = "IONSCALE_TLS_FORCE_HTTPS"
|
||||
tlsCertFileKey = "IONSCALE_TLS_CERT_FILE"
|
||||
tlsKeyFileKey = "IONSCALE_TLS_KEY_FILE"
|
||||
tlsAcmeKey = "IONSCALE_TLS_ACME"
|
||||
tlsAcmeCAKey = "IONSCALE_TLS_ACME_CA"
|
||||
tlsAcmeEmailKey = "IONSCALE_TLS_ACME_EMAIL"
|
||||
tlsAcmePath = "IONSCALE_TLS_ACME_PATH"
|
||||
pollNetKeepAliveInterval = "IONSCALE_POLL_NET_KEEP_ALIVE_INTERVAL"
|
||||
metricsListenAddrKey = "IONSCALE_METRICS_LISTEN_ADDR"
|
||||
loggingLevelKey = "IONSCALE_LOGGING_LEVEL"
|
||||
loggingFormatKey = "IONSCALE_LOGGING_FORMAT"
|
||||
loggingFileKey = "IONSCALE_LOGGING_FILE"
|
||||
authProviderIssuerKey = "IONSCALE_AUTH_PROVIDER_ISSUER"
|
||||
authProviderClientIdKey = "IONSCALE_AUTH_PROVIDER_CLIENT_ID"
|
||||
authProviderClientSecretKey = "IONSCALE_AUTH_PROVIDER_CLIENT_SECRET"
|
||||
authProviderScopesKey = "IONSCALE_AUTH_PROVIDER_SCOPES"
|
||||
)
|
||||
|
||||
func defaultConfig() (*Config, error) {
|
||||
defaultKeepAliveInterval, err := GetDuration(pollNetKeepAliveInterval, 1*time.Minute)
|
||||
if err != nil {
|
||||
envCfg := &Config{}
|
||||
if err := env.Parse(envCfg, env.Options{Prefix: "IONSCALE_"}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c := &Config{
|
||||
HttpListenAddr: GetString(httpListenAddrKey, ":8080"),
|
||||
HttpsListenAddr: GetString(httpsListenAddrKey, ":8443"),
|
||||
MetricsListenAddr: GetString(metricsListenAddrKey, ":9091"),
|
||||
ServerUrl: GetString(serverUrlKey, "https://localhost:8443"),
|
||||
Keys: Keys{
|
||||
SystemAdminKey: GetString(keysSystemAdminKeyKey, ""),
|
||||
ControlKey: GetString(keysControlKeyKey, ""),
|
||||
LegacyControlKey: GetString(keysLegacyControlKeyKey, ""),
|
||||
},
|
||||
// merge env configuration on top of the default/file configuration
|
||||
if err := mergo.Merge(cfg, envCfg, mergo.WithOverride); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return cfg, nil
|
||||
}
|
||||
|
||||
func defaultConfig() *Config {
|
||||
return &Config{
|
||||
HttpListenAddr: ":8080",
|
||||
HttpsListenAddr: ":8443",
|
||||
MetricsListenAddr: ":9091",
|
||||
ServerUrl: "https://localhost:8843",
|
||||
Database: Database{
|
||||
Url: GetString(databaseUrlKey, "ionscale.db"),
|
||||
Type: "sqlite",
|
||||
Url: "ionscale.db",
|
||||
},
|
||||
Tls: Tls{
|
||||
Disable: GetBool(tlsDisableKey, false),
|
||||
ForceHttps: GetBool(tlsForceHttpsKey, true),
|
||||
CertFile: GetString(tlsCertFileKey, ""),
|
||||
KeyFile: GetString(tlsKeyFileKey, ""),
|
||||
AcmeEnabled: GetBool(tlsAcmeKey, false),
|
||||
AcmeCA: GetString(tlsAcmeCAKey, certmagic.LetsEncryptProductionCA),
|
||||
AcmeEmail: GetString(tlsAcmeEmailKey, ""),
|
||||
AcmePath: GetString(tlsAcmePath, ""),
|
||||
},
|
||||
PollNet: PollNet{
|
||||
KeepAliveInterval: defaultKeepAliveInterval,
|
||||
},
|
||||
AuthProvider: AuthProvider{
|
||||
Issuer: GetString(authProviderIssuerKey, ""),
|
||||
ClientID: GetString(authProviderClientIdKey, ""),
|
||||
ClientSecret: GetString(authProviderClientSecretKey, ""),
|
||||
Scopes: GetStrings(authProviderScopesKey, nil),
|
||||
},
|
||||
Logging: Logging{
|
||||
Level: GetString(loggingLevelKey, "info"),
|
||||
Format: GetString(loggingFormatKey, ""),
|
||||
File: GetString(loggingFileKey, ""),
|
||||
Disable: false,
|
||||
ForceHttps: true,
|
||||
AcmeEnabled: false,
|
||||
AcmeCA: certmagic.LetsEncryptProductionCA,
|
||||
},
|
||||
PollNet: PollNet{KeepAliveInterval: 1 * time.Minute},
|
||||
Logging: Logging{Level: "info"},
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
type ServerKeys struct {
|
||||
@@ -132,55 +85,55 @@ type ServerKeys struct {
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
HttpListenAddr string `yaml:"http_listen_addr,omitempty"`
|
||||
HttpsListenAddr string `yaml:"https_listen_addr,omitempty"`
|
||||
MetricsListenAddr string `yaml:"metrics_listen_addr,omitempty"`
|
||||
ServerUrl string `yaml:"server_url,omitempty"`
|
||||
Tls Tls `yaml:"tls,omitempty"`
|
||||
PollNet PollNet `yaml:"poll_net,omitempty"`
|
||||
Keys Keys `yaml:"keys,omitempty"`
|
||||
Database Database `yaml:"database,omitempty"`
|
||||
AuthProvider AuthProvider `yaml:"auth_provider,omitempty"`
|
||||
Logging Logging `yaml:"logging,omitempty"`
|
||||
HttpListenAddr string `yaml:"http_listen_addr,omitempty" env:"HTTP_LISTEN_ADDR"`
|
||||
HttpsListenAddr string `yaml:"https_listen_addr,omitempty" env:"HTTPS_LISTEN_ADDR"`
|
||||
MetricsListenAddr string `yaml:"metrics_listen_addr,omitempty" env:"METRICS_LISTEN_ADDR"`
|
||||
ServerUrl string `yaml:"server_url,omitempty" env:"SERVER_URL"`
|
||||
Tls Tls `yaml:"tls,omitempty" envPrefix:"TLS_"`
|
||||
PollNet PollNet `yaml:"poll_net,omitempty" envPrefix:"POLL_NET_"`
|
||||
Keys Keys `yaml:"keys,omitempty" envPrefix:"KEYS_"`
|
||||
Database Database `yaml:"database,omitempty" envPrefix:"DB_"`
|
||||
AuthProvider AuthProvider `yaml:"auth_provider,omitempty" envPrefix:"AUTH_PROVIDER_"`
|
||||
Logging Logging `yaml:"logging,omitempty" envPrefix:"LOGGING_"`
|
||||
}
|
||||
|
||||
type Tls struct {
|
||||
Disable bool `yaml:"disable"`
|
||||
ForceHttps bool `yaml:"force_https"`
|
||||
CertFile string `yaml:"cert_file,omitempty"`
|
||||
KeyFile string `yaml:"key_file,omitempty"`
|
||||
AcmeEnabled bool `yaml:"acme,omitempty"`
|
||||
AcmeEmail string `yaml:"acme_email,omitempty"`
|
||||
AcmeCA string `yaml:"acme_ca,omitempty"`
|
||||
AcmePath string `yaml:"acme_path,omitempty"`
|
||||
Disable bool `yaml:"disable" env:"DISABLE"`
|
||||
ForceHttps bool `yaml:"force_https" env:"FORCE_HTTPS"`
|
||||
CertFile string `yaml:"cert_file,omitempty" env:"CERT_FILE"`
|
||||
KeyFile string `yaml:"key_file,omitempty" env:"KEY_FILE"`
|
||||
AcmeEnabled bool `yaml:"acme,omitempty" env:"ACME_ENABLED"`
|
||||
AcmeEmail string `yaml:"acme_email,omitempty" env:"ACME_EMAIL"`
|
||||
AcmeCA string `yaml:"acme_ca,omitempty" env:"ACME_CA"`
|
||||
AcmePath string `yaml:"acme_path,omitempty" env:"ACME_PATH"`
|
||||
}
|
||||
|
||||
type PollNet struct {
|
||||
KeepAliveInterval time.Duration `yaml:"keep_alive_interval"`
|
||||
KeepAliveInterval time.Duration `yaml:"keep_alive_interval" env:"KEEP_ALIVE_INTERVAL"`
|
||||
}
|
||||
|
||||
type Logging struct {
|
||||
Level string `yaml:"level,omitempty"`
|
||||
Format string `yaml:"format,omitempty"`
|
||||
File string `yaml:"file,omitempty"`
|
||||
Level string `yaml:"level,omitempty" env:"LEVEL"`
|
||||
Format string `yaml:"format,omitempty" env:"FORMAT"`
|
||||
File string `yaml:"file,omitempty" env:"FILE"`
|
||||
}
|
||||
|
||||
type Database struct {
|
||||
Type string `yaml:"type,omitempty"`
|
||||
Url string `yaml:"url,omitempty"`
|
||||
Type string `yaml:"type,omitempty" env:"TYPE"`
|
||||
Url string `yaml:"url,omitempty" env:"URL"`
|
||||
}
|
||||
|
||||
type Keys struct {
|
||||
ControlKey string `yaml:"control_key,omitempty"`
|
||||
LegacyControlKey string `yaml:"legacy_control_key,omitempty"`
|
||||
SystemAdminKey string `yaml:"system_admin_key,omitempty"`
|
||||
ControlKey string `yaml:"control_key,omitempty" env:"CONTROL_KEY"`
|
||||
LegacyControlKey string `yaml:"legacy_control_key,omitempty" env:"LEGACY_CONTROL_KEY"`
|
||||
SystemAdminKey string `yaml:"system_admin_key,omitempty" env:"SYSTEM_ADMIN_KEY"`
|
||||
}
|
||||
|
||||
type AuthProvider struct {
|
||||
Issuer string `yaml:"issuer"`
|
||||
ClientID string `yaml:"client_id"`
|
||||
ClientSecret string `yaml:"client_secret"`
|
||||
Scopes []string `yaml:"additional_scopes"`
|
||||
Issuer string `yaml:"issuer" env:"ISSUER"`
|
||||
ClientID string `yaml:"client_id" env:"CLIENT_ID"`
|
||||
ClientSecret string `yaml:"client_secret" env:"CLIENT_SECRET"`
|
||||
Scopes []string `yaml:"additional_scopes" env:"ADDITIONAL_SCOPES"`
|
||||
SystemAdminPolicy SystemAdminPolicy `yaml:"system_admins"`
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ package config
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func GetBool(key string, defaultValue bool) bool {
|
||||
@@ -21,23 +20,3 @@ func GetString(key, defaultValue string) string {
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
func GetStrings(key string, defaultValue []string) []string {
|
||||
v := os.Getenv(key)
|
||||
if v != "" {
|
||||
return strings.Split(v, ",")
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
func GetDuration(key string, defaultValue time.Duration) (time.Duration, error) {
|
||||
v := os.Getenv(key)
|
||||
if len(v) > 0 {
|
||||
duration, err := time.ParseDuration(v)
|
||||
if err != nil {
|
||||
return defaultValue, err
|
||||
}
|
||||
return duration, nil
|
||||
}
|
||||
return defaultValue, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user