Skip to content

Commit 78cb442

Browse files
author
Chris Stockton
committed
feat(conf): add JSON config file support
Adds two new replace directives to go.mod which point to the newly created internal/forks directory: github.com/joho/godotenv => ./internal/forks/godotenv github.com/kelseyhightower/envconfig => ./internal/forks/envconfig Each one is clone of the version we use from the public repos with no a dditional changes made. This may be a repeatable pattern we could use to work around some limitations of older packages and allow reaching into internals to ease migrating away from them.
1 parent cda62a9 commit 78cb442

39 files changed

Lines changed: 3731 additions & 0 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,4 @@ www/.DS_Store
2020
www/node_modules
2121
npm-debug.log
2222
.data
23+
tmp

go.mod

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,3 +187,8 @@ require (
187187
)
188188

189189
go 1.25.8
190+
191+
replace (
192+
github.com/joho/godotenv => ./internal/forks/godotenv
193+
github.com/kelseyhightower/envconfig => ./internal/forks/envconfig
194+
)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
language: go
2+
3+
go:
4+
- 1.4.x
5+
- 1.5.x
6+
- 1.6.x
7+
- 1.7.x
8+
- 1.8.x
9+
- 1.9.x
10+
- 1.10.x
11+
- 1.11.x
12+
- 1.12.x
13+
- tip

internal/forks/envconfig/LICENSE

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Copyright (c) 2013 Kelsey Hightower
2+
3+
Permission is hereby granted, free of charge, to any person obtaining a copy of
4+
this software and associated documentation files (the "Software"), to deal in
5+
the Software without restriction, including without limitation the rights to
6+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7+
of the Software, and to permit persons to whom the Software is furnished to do
8+
so, subject to the following conditions:
9+
10+
The above copyright notice and this permission notice shall be included in all
11+
copies or substantial portions of the Software.
12+
13+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19+
SOFTWARE.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Kelsey Hightower kelsey.hightower@gmail.com github.com/kelseyhightower
2+
Travis Parker travis.parker@gmail.com github.com/teepark

internal/forks/envconfig/README.md

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
# envconfig
2+
3+
[![Build Status](https://travis-ci.org/kelseyhightower/envconfig.svg)](https://travis-ci.org/kelseyhightower/envconfig)
4+
5+
```Go
6+
import "github.com/kelseyhightower/envconfig"
7+
```
8+
9+
## Documentation
10+
11+
See [godoc](http://godoc.org/github.com/kelseyhightower/envconfig)
12+
13+
## Usage
14+
15+
Set some environment variables:
16+
17+
```Bash
18+
export MYAPP_DEBUG=false
19+
export MYAPP_PORT=8080
20+
export MYAPP_USER=Kelsey
21+
export MYAPP_RATE="0.5"
22+
export MYAPP_TIMEOUT="3m"
23+
export MYAPP_USERS="rob,ken,robert"
24+
export MYAPP_COLORCODES="red:1,green:2,blue:3"
25+
```
26+
27+
Write some code:
28+
29+
```Go
30+
package main
31+
32+
import (
33+
"fmt"
34+
"log"
35+
"time"
36+
37+
"github.com/kelseyhightower/envconfig"
38+
)
39+
40+
type Specification struct {
41+
Debug bool
42+
Port int
43+
User string
44+
Users []string
45+
Rate float32
46+
Timeout time.Duration
47+
ColorCodes map[string]int
48+
}
49+
50+
func main() {
51+
var s Specification
52+
err := envconfig.Process("myapp", &s)
53+
if err != nil {
54+
log.Fatal(err.Error())
55+
}
56+
format := "Debug: %v\nPort: %d\nUser: %s\nRate: %f\nTimeout: %s\n"
57+
_, err = fmt.Printf(format, s.Debug, s.Port, s.User, s.Rate, s.Timeout)
58+
if err != nil {
59+
log.Fatal(err.Error())
60+
}
61+
62+
fmt.Println("Users:")
63+
for _, u := range s.Users {
64+
fmt.Printf(" %s\n", u)
65+
}
66+
67+
fmt.Println("Color codes:")
68+
for k, v := range s.ColorCodes {
69+
fmt.Printf(" %s: %d\n", k, v)
70+
}
71+
}
72+
```
73+
74+
Results:
75+
76+
```Bash
77+
Debug: false
78+
Port: 8080
79+
User: Kelsey
80+
Rate: 0.500000
81+
Timeout: 3m0s
82+
Users:
83+
rob
84+
ken
85+
robert
86+
Color codes:
87+
red: 1
88+
green: 2
89+
blue: 3
90+
```
91+
92+
## Struct Tag Support
93+
94+
Envconfig supports the use of struct tags to specify alternate, default, and required
95+
environment variables.
96+
97+
For example, consider the following struct:
98+
99+
```Go
100+
type Specification struct {
101+
ManualOverride1 string `envconfig:"manual_override_1"`
102+
DefaultVar string `default:"foobar"`
103+
RequiredVar string `required:"true"`
104+
IgnoredVar string `ignored:"true"`
105+
AutoSplitVar string `split_words:"true"`
106+
RequiredAndAutoSplitVar string `required:"true" split_words:"true"`
107+
}
108+
```
109+
110+
Envconfig has automatic support for CamelCased struct elements when the
111+
`split_words:"true"` tag is supplied. Without this tag, `AutoSplitVar` above
112+
would look for an environment variable called `MYAPP_AUTOSPLITVAR`. With the
113+
setting applied it will look for `MYAPP_AUTO_SPLIT_VAR`. Note that numbers
114+
will get globbed into the previous word. If the setting does not do the
115+
right thing, you may use a manual override.
116+
117+
Envconfig will process value for `ManualOverride1` by populating it with the
118+
value for `MYAPP_MANUAL_OVERRIDE_1`. Without this struct tag, it would have
119+
instead looked up `MYAPP_MANUALOVERRIDE1`. With the `split_words:"true"` tag
120+
it would have looked up `MYAPP_MANUAL_OVERRIDE1`.
121+
122+
```Bash
123+
export MYAPP_MANUAL_OVERRIDE_1="this will be the value"
124+
125+
# export MYAPP_MANUALOVERRIDE1="and this will not"
126+
```
127+
128+
If envconfig can't find an environment variable value for `MYAPP_DEFAULTVAR`,
129+
it will populate it with "foobar" as a default value.
130+
131+
If envconfig can't find an environment variable value for `MYAPP_REQUIREDVAR`,
132+
it will return an error when asked to process the struct. If
133+
`MYAPP_REQUIREDVAR` is present but empty, envconfig will not return an error.
134+
135+
If envconfig can't find an environment variable in the form `PREFIX_MYVAR`, and there
136+
is a struct tag defined, it will try to populate your variable with an environment
137+
variable that directly matches the envconfig tag in your struct definition:
138+
139+
```shell
140+
export SERVICE_HOST=127.0.0.1
141+
export MYAPP_DEBUG=true
142+
```
143+
```Go
144+
type Specification struct {
145+
ServiceHost string `envconfig:"SERVICE_HOST"`
146+
Debug bool
147+
}
148+
```
149+
150+
Envconfig won't process a field with the "ignored" tag set to "true", even if a corresponding
151+
environment variable is set.
152+
153+
## Supported Struct Field Types
154+
155+
envconfig supports these struct field types:
156+
157+
* string
158+
* int8, int16, int32, int64
159+
* bool
160+
* float32, float64
161+
* slices of any supported type
162+
* maps (keys and values of any supported type)
163+
* [encoding.TextUnmarshaler](https://golang.org/pkg/encoding/#TextUnmarshaler)
164+
* [encoding.BinaryUnmarshaler](https://golang.org/pkg/encoding/#BinaryUnmarshaler)
165+
* [time.Duration](https://golang.org/pkg/time/#Duration)
166+
167+
Embedded structs using these fields are also supported.
168+
169+
## Custom Decoders
170+
171+
Any field whose type (or pointer-to-type) implements `envconfig.Decoder` can
172+
control its own deserialization:
173+
174+
```Bash
175+
export DNS_SERVER=8.8.8.8
176+
```
177+
178+
```Go
179+
type IPDecoder net.IP
180+
181+
func (ipd *IPDecoder) Decode(value string) error {
182+
*ipd = IPDecoder(net.ParseIP(value))
183+
return nil
184+
}
185+
186+
type DNSConfig struct {
187+
Address IPDecoder `envconfig:"DNS_SERVER"`
188+
}
189+
```
190+
191+
Also, envconfig will use a `Set(string) error` method like from the
192+
[flag.Value](https://godoc.org/flag#Value) interface if implemented.

internal/forks/envconfig/doc.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Copyright (c) 2013 Kelsey Hightower. All rights reserved.
2+
// Use of this source code is governed by the MIT License that can be found in
3+
// the LICENSE file.
4+
5+
// Package envconfig implements decoding of environment variables based on a user
6+
// defined specification. A typical use is using environment variables for
7+
// configuration settings.
8+
package envconfig

internal/forks/envconfig/env_os.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// +build appengine go1.5
2+
3+
package envconfig
4+
5+
import "os"
6+
7+
var lookupEnv = os.LookupEnv
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// +build !appengine,!go1.5
2+
3+
package envconfig
4+
5+
import "syscall"
6+
7+
var lookupEnv = syscall.Getenv

0 commit comments

Comments
 (0)