@@ -14,24 +14,46 @@ type EnvVar struct {
14
14
EnvKey string
15
15
Required bool
16
16
DefaultVal string
17
- IsDir bool
18
17
}
19
18
20
19
type Environment map [string ]string
21
20
22
- // GetEnvironment tries to read environment variables from various sources. In
23
- // order of precedence:
24
- // * OS environment variables.
25
- // * Values from any .env file that may exist.
26
- // * Default values specified by the caller.
27
- // It returns an error if one or more expected variables are not present in any
28
- // of the sources.
29
- func GetEnvironment (vars []EnvVar ) (Environment , error ) {
30
- env := map [string ]string {}
21
+ // EnvironmentProvider is an interface used to retrieve a string-based,
22
+ // key-value set of configuration options.
23
+ type EnvironmentProvider interface {
24
+ // Read attempts to read the values of the provided variables from the
25
+ // underlying source. If a value for a variable is found, it's written into
26
+ // the provided Environment.
27
+ Read (vars []EnvVar , env Environment )
28
+ }
29
+
30
+ // GetEnvironmentOrPrintUsage reads the requested variables from an environment
31
+ // provider. If a required variable is not found, usage information is printed
32
+ // to stdout and an error is returned; otherwise, a populated Environment
33
+ // containing the values of the requested variables is returned.
34
+ func GetEnvironmentOrPrintUsage (
35
+ provider EnvironmentProvider ,
36
+ vars []EnvVar ,
37
+ ) (Environment , error ) {
38
+ env := Environment {}
31
39
setupDefaultValues (vars , env )
32
- readDotEnv (vars , env )
33
- readEnvironment (vars , env )
34
- return env , checkEnvironment (vars , env )
40
+ provider .Read (vars , env )
41
+
42
+ if err := checkEnvironment (vars , env ); err != nil {
43
+ printEnvUsage (vars , env )
44
+ return nil , err
45
+ }
46
+
47
+ return env , nil
48
+ }
49
+
50
+ func setupDefaultValues (vars []EnvVar , env Environment ) {
51
+ for _ , variable := range vars {
52
+ if variable .DefaultVal == "" {
53
+ continue
54
+ }
55
+ env [variable .EnvKey ] = variable .DefaultVal
56
+ }
35
57
}
36
58
37
59
func checkEnvironment (vars []EnvVar , env Environment ) error {
@@ -44,17 +66,12 @@ func checkEnvironment(vars []EnvVar, env Environment) error {
44
66
if found == false || len (envVal ) == 0 {
45
67
return errors .New ("Required environment variable is missing: " + variable .EnvKey )
46
68
}
47
-
48
- if variable .IsDir && checkDir (envVal ) != nil {
49
- logger .Println ("Could not read " + variable .EnvKey + " directory: " + envVal )
50
- return errors .New ("Invalid directory: " + envVal )
51
- }
52
69
}
53
70
54
71
return nil
55
72
}
56
73
57
- func PrintEnvUsage (vars []EnvVar , env Environment ) {
74
+ func printEnvUsage (vars []EnvVar , env Environment ) {
58
75
logger .Println ("Required configuration variables via .env or environment:" )
59
76
for _ , variable := range vars {
60
77
if variable .Required == false {
@@ -83,21 +100,26 @@ func PrintEnvUsage(vars []EnvVar, env Environment) {
83
100
}
84
101
}
85
102
86
- func checkDir (dirPath string ) error {
87
- pathInfo , err := os .Stat (dirPath )
88
- if err != nil {
89
- return err
90
- }
91
- if pathInfo .IsDir () == false {
92
- return errors .New ("Not a directory" )
93
- }
94
- return nil
103
+ // DefaultEnvironmentProvider tries to read environment variables from various
104
+ // external sources. In order of precedence:
105
+ // * OS environment variables.
106
+ // * Values from any .env file that may exist.
107
+ type DefaultEnvironmentProvider struct {
108
+ }
109
+
110
+ func NewDefaultEnvironmentProvider () EnvironmentProvider {
111
+ return & DefaultEnvironmentProvider {}
112
+ }
113
+
114
+ func (provider * DefaultEnvironmentProvider ) Read (vars []EnvVar , env Environment ) {
115
+ provider .readDotEnv (vars , env )
116
+ provider .readEnvironment (vars , env )
95
117
}
96
118
97
119
// readDotEnv reads environment variables from a .env file, if one is present,
98
120
// and adds their values to env. Returns an error if reading from .env fails.
99
- func readDotEnv (vars []EnvVar , env Environment ) error {
100
- dotEnvVals , err := parseDotEnv (".env" )
121
+ func ( provider * DefaultEnvironmentProvider ) readDotEnv (vars []EnvVar , env Environment ) error {
122
+ dotEnvVals , err := provider . parseDotEnv (".env" )
101
123
if err != nil {
102
124
return err
103
125
}
@@ -107,7 +129,7 @@ func readDotEnv(vars []EnvVar, env Environment) error {
107
129
return nil
108
130
}
109
131
110
- func readEnvironment (vars []EnvVar , env Environment ) {
132
+ func ( provider * DefaultEnvironmentProvider ) readEnvironment (vars []EnvVar , env Environment ) {
111
133
for _ , variable := range vars {
112
134
envVal , found := os .LookupEnv (variable .EnvKey )
113
135
if found && len (envVal ) > 0 {
@@ -116,7 +138,7 @@ func readEnvironment(vars []EnvVar, env Environment) {
116
138
}
117
139
}
118
140
119
- func parseDotEnv (filePath string ) (Environment , error ) {
141
+ func ( provider * DefaultEnvironmentProvider ) parseDotEnv (filePath string ) (Environment , error ) {
120
142
results := Environment {}
121
143
122
144
file , err := os .Open (filePath )
@@ -153,11 +175,22 @@ func parseDotEnv(filePath string) (Environment, error) {
153
175
return results , nil
154
176
}
155
177
156
- func setupDefaultValues (vars []EnvVar , env Environment ) {
178
+ // TestEnvironmentProvider reads environment variables from a hard-coded list.
179
+ type TestEnvironmentProvider struct {
180
+ env Environment
181
+ }
182
+
183
+ func NewTestEnvironmentProvider (env Environment ) EnvironmentProvider {
184
+ return & TestEnvironmentProvider {
185
+ env : env ,
186
+ }
187
+ }
188
+
189
+ func (provider * TestEnvironmentProvider ) Read (vars []EnvVar , env Environment ) {
157
190
for _ , variable := range vars {
158
- if variable .DefaultVal == "" {
159
- continue
191
+ envVal , found := provider .env [variable .EnvKey ]
192
+ if found {
193
+ env [variable .EnvKey ] = envVal
160
194
}
161
- env [variable .EnvKey ] = variable .DefaultVal
162
195
}
163
196
}
0 commit comments