Skip to content

Commit 0e9b532

Browse files
authored
Merge pull request #257 from ikedam/feature/9431_CaseInsensitiveEnv
Resolve environments case-insensitively on Windows
2 parents bdac2d1 + eeab8f0 commit 0e9b532

File tree

2 files changed

+121
-1
lines changed

2 files changed

+121
-1
lines changed

types/config.go

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,17 @@ package types
1818

1919
import (
2020
"encoding/json"
21+
"runtime"
22+
"strings"
2123

2224
"github.com/mitchellh/mapstructure"
2325
)
2426

27+
var (
28+
// isCaseInsensitiveEnvVars is true on platforms where environment variable names are treated case-insensitively.
29+
isCaseInsensitiveEnvVars = (runtime.GOOS == "windows")
30+
)
31+
2532
// ConfigDetails are the details about a group of ConfigFiles
2633
type ConfigDetails struct {
2734
Version string
@@ -33,7 +40,21 @@ type ConfigDetails struct {
3340
// LookupEnv provides a lookup function for environment variables
3441
func (cd ConfigDetails) LookupEnv(key string) (string, bool) {
3542
v, ok := cd.Environment[key]
36-
return v, ok
43+
if !isCaseInsensitiveEnvVars || ok {
44+
return v, ok
45+
}
46+
// variable names must be treated case-insensitively on some platforms (that is, Windows).
47+
// Resolves in this way:
48+
// * Return the value if its name matches with the passed name case-sensitively.
49+
// * Otherwise, return the value if its lower-cased name matches lower-cased passed name.
50+
// * The value is indefinite if multiple variables match.
51+
lowerKey := strings.ToLower(key)
52+
for k, v := range cd.Environment {
53+
if strings.ToLower(k) == lowerKey {
54+
return v, true
55+
}
56+
}
57+
return "", false
3758
}
3859

3960
// ConfigFile is a filename and the contents of the file as a Dict

types/config_test.go

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,102 @@ func Test_WithServices(t *testing.T) {
5353
assert.NilError(t, err)
5454
assert.DeepEqual(t, order, []string{"service_2", "service_3", "service_1"})
5555
}
56+
57+
func Test_LookupEnv(t *testing.T) {
58+
tests := []struct {
59+
name string
60+
environment map[string]string
61+
caseInsensitive bool
62+
search string
63+
expectedValue string
64+
expectedOk bool
65+
}{
66+
{
67+
name: "case sensitive/case match",
68+
environment: map[string]string{
69+
"Env1": "Value1",
70+
"Env2": "Value2",
71+
},
72+
caseInsensitive: false,
73+
search: "Env1",
74+
expectedValue: "Value1",
75+
expectedOk: true,
76+
},
77+
{
78+
name: "case sensitive/case unmatch",
79+
environment: map[string]string{
80+
"Env1": "Value1",
81+
"Env2": "Value2",
82+
},
83+
caseInsensitive: false,
84+
search: "ENV1",
85+
expectedValue: "",
86+
expectedOk: false,
87+
},
88+
{
89+
name: "case sensitive/nil environment",
90+
environment: nil,
91+
caseInsensitive: false,
92+
search: "Env1",
93+
expectedValue: "",
94+
expectedOk: false,
95+
},
96+
{
97+
name: "case insensitive/case match",
98+
environment: map[string]string{
99+
"Env1": "Value1",
100+
"Env2": "Value2",
101+
},
102+
caseInsensitive: true,
103+
search: "Env1",
104+
expectedValue: "Value1",
105+
expectedOk: true,
106+
},
107+
{
108+
name: "case insensitive/case unmatch",
109+
environment: map[string]string{
110+
"Env1": "Value1",
111+
"Env2": "Value2",
112+
},
113+
caseInsensitive: true,
114+
search: "ENV1",
115+
expectedValue: "Value1",
116+
expectedOk: true,
117+
},
118+
{
119+
name: "case insensitive/unmatch",
120+
environment: map[string]string{
121+
"Env1": "Value1",
122+
"Env2": "Value2",
123+
},
124+
caseInsensitive: true,
125+
search: "Env3",
126+
expectedValue: "",
127+
expectedOk: false,
128+
},
129+
{
130+
name: "case insensitive/nil environment",
131+
environment: nil,
132+
caseInsensitive: true,
133+
search: "Env1",
134+
expectedValue: "",
135+
expectedOk: false,
136+
},
137+
}
138+
139+
for _, test := range tests {
140+
t.Run(test.name, func(t *testing.T) {
141+
origIsCaseInsensitiveEnvVars := isCaseInsensitiveEnvVars
142+
defer func() {
143+
isCaseInsensitiveEnvVars = origIsCaseInsensitiveEnvVars
144+
}()
145+
isCaseInsensitiveEnvVars = test.caseInsensitive
146+
cd := ConfigDetails{
147+
Environment: test.environment,
148+
}
149+
v, ok := cd.LookupEnv(test.search)
150+
assert.Equal(t, v, test.expectedValue)
151+
assert.Equal(t, ok, test.expectedOk)
152+
})
153+
}
154+
}

0 commit comments

Comments
 (0)