Substitute environment variables when loading yaml config to fix #840 (#880)

This commit is contained in:
James Read 2026-06-20 01:45:29 +01:00 committed by GitHub
commit e61c8b036d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 15 additions and 27 deletions

View File

@ -8,6 +8,7 @@ import (
"sort" "sort"
"strings" "strings"
"github.com/go-viper/mapstructure/v2"
"github.com/knadh/koanf/parsers/yaml" "github.com/knadh/koanf/parsers/yaml"
"github.com/knadh/koanf/providers/file" "github.com/knadh/koanf/providers/file"
"github.com/knadh/koanf/v2" "github.com/knadh/koanf/v2"
@ -51,6 +52,14 @@ func AppendSource(cfg *Config, k *koanf.Koanf, configPath string) {
func unmarshalRoot(k *koanf.Koanf, cfg *Config) bool { func unmarshalRoot(k *koanf.Koanf, cfg *Config) bool {
err := k.UnmarshalWithConf("", cfg, koanf.UnmarshalConf{ err := k.UnmarshalWithConf("", cfg, koanf.UnmarshalConf{
Tag: "koanf", Tag: "koanf",
DecoderConfig: &mapstructure.DecoderConfig{
DecodeHook: mapstructure.ComposeDecodeHookFunc(
envDecodeHookFunc,
mapstructure.StringToTimeDurationHookFunc(),
mapstructure.TextUnmarshallerHookFunc(),
),
WeaklyTypedInput: true,
},
}) })
if err != nil { if err != nil {

View File

@ -90,26 +90,22 @@ var envConfigTests = []struct {
} }
func TestEnvInConfig(t *testing.T) { func TestEnvInConfig(t *testing.T) {
t.Skip("Skipping test in 3k")
for _, tt := range envConfigTests { for _, tt := range envConfigTests {
cfg := DefaultConfig() cfg := DefaultConfig()
setIfNotEmpty("INPUT", tt.input) setIfNotEmpty("INPUT", tt.input)
processed := processYamlWithEnv(tt.yaml) k := koanf.New(".")
k, err := loadKoanf(processed) err := k.Load(rawbytes.Provider([]byte(tt.yaml)), yaml.Parser())
if err != nil { if err != nil {
t.Errorf("Error loading YAML: %v", err) t.Errorf("Error loading YAML: %v", err)
continue continue
} }
if !unmarshalRoot(k, cfg) {
if err := k.UnmarshalWithConf("", cfg, koanf.UnmarshalConf{ t.Errorf("Error unmarshalling config for env=%q", tt.input)
Tag: "koanf",
}); err != nil {
t.Errorf("Error unmarshalling config: %v", err)
continue continue
} }
field := tt.selector(cfg) field := tt.selector(cfg)
assert.Equal(t, tt.output, field, "Unmarshaled config field doesn't match expected value: env=\"%s\"", tt.input) assert.Equal(t, tt.output, field,
"Unmarshaled config field doesn't match expected value: env=%q", tt.input)
os.Unsetenv("INPUT") os.Unsetenv("INPUT")
} }
} }
@ -119,20 +115,3 @@ func setIfNotEmpty(key, val string) {
os.Setenv(key, val) os.Setenv(key, val)
} }
} }
func processYamlWithEnv(content string) string {
return envRegex.ReplaceAllStringFunc(content, func(match string) string {
submatches := envRegex.FindStringSubmatch(match)
key := submatches[1]
val, _ := os.LookupEnv(key)
return val
})
}
func loadKoanf(processed string) (*koanf.Koanf, error) {
k := koanf.New(".")
if err := k.Load(rawbytes.Provider([]byte(processed)), yaml.Parser()); err != nil {
return nil, err
}
return k, nil
}