@@ -15,6 +15,7 @@ import (
1515 "github.com/mitchellh/mapstructure"
1616 "github.com/shirou/gopsutil/v4/cpu"
1717 "github.com/spf13/viper"
18+ "gopkg.in/yaml.v3"
1819)
1920
2021const (
@@ -439,14 +440,19 @@ func Load(paths ...string) (*Config, error) {
439440
440441 v .SetConfigType ("yaml" )
441442
442- // Load and merge configs in order.
443+ // Load and merge configs in order, collecting expanded YAML for
444+ // post-processing (Viper lowercases map keys, so we re-parse to
445+ // restore original casing for environment variables).
446+ rawYAMLs := make ([]string , 0 , len (paths ))
447+
443448 for i , path := range paths {
444449 content , err := os .ReadFile (path )
445450 if err != nil {
446451 return nil , fmt .Errorf ("reading config file %q: %w" , path , err )
447452 }
448453
449454 expanded := os .ExpandEnv (string (content ))
455+ rawYAMLs = append (rawYAMLs , expanded )
450456
451457 if i == 0 {
452458 if err := v .ReadConfig (strings .NewReader (expanded )); err != nil {
@@ -474,6 +480,8 @@ func Load(paths ...string) (*Config, error) {
474480 return nil , fmt .Errorf ("parsing config: %w" , err )
475481 }
476482
483+ restoreEnvironmentKeyCasing (& cfg , rawYAMLs )
484+
477485 cfg .applyDefaults ()
478486
479487 return & cfg , nil
@@ -1183,3 +1191,39 @@ func bootstrapFCUDecodeHook() mapstructure.DecodeHookFuncType {
11831191 return data , nil
11841192 }
11851193}
1194+
1195+ // rawClientConfig is a minimal struct used to re-parse environment map keys
1196+ // with their original casing, since Viper lowercases all map keys internally.
1197+ type rawClientConfig struct {
1198+ Client struct {
1199+ Instances []struct {
1200+ ID string `yaml:"id"`
1201+ Environment map [string ]string `yaml:"environment"`
1202+ } `yaml:"instances"`
1203+ } `yaml:"client"`
1204+ }
1205+
1206+ // restoreEnvironmentKeyCasing re-parses the raw YAML to recover the original
1207+ // casing of environment variable keys that Viper lowercased.
1208+ func restoreEnvironmentKeyCasing (cfg * Config , rawYAMLs []string ) {
1209+ envByID := make (map [string ]map [string ]string , len (cfg .Client .Instances ))
1210+
1211+ for _ , raw := range rawYAMLs {
1212+ var parsed rawClientConfig
1213+ if err := yaml .Unmarshal ([]byte (raw ), & parsed ); err != nil {
1214+ continue
1215+ }
1216+
1217+ for _ , inst := range parsed .Client .Instances {
1218+ if inst .Environment != nil {
1219+ envByID [inst .ID ] = inst .Environment
1220+ }
1221+ }
1222+ }
1223+
1224+ for i := range cfg .Client .Instances {
1225+ if orig , ok := envByID [cfg .Client .Instances [i ].ID ]; ok {
1226+ cfg .Client .Instances [i ].Environment = orig
1227+ }
1228+ }
1229+ }
0 commit comments