Skip to content

Commit 9180419

Browse files
authored
feat: allow fetching env from a prefix (#8)
* feat: allow fetching env from a prefix * add a quick test
1 parent a8fbf8d commit 9180419

File tree

2 files changed

+22
-4
lines changed

2 files changed

+22
-4
lines changed

env.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ type Setter interface {
2424
// If a field is unexported or required configuration is not
2525
// found, an error will be returned.
2626
func Set(i interface{}) (err error) {
27+
return SetPrefix(i, "")
28+
}
29+
30+
// SetPrefix sets the fields of a struct from environment config
31+
// with a given prefix. If a field is unexported or required
32+
// configuration is not found, an error will be returned.
33+
func SetPrefix(i interface{}, prefix string) (err error) {
2734
v := reflect.ValueOf(i)
2835

2936
// Don't try to process a non-pointer value.
@@ -35,7 +42,7 @@ func Set(i interface{}) (err error) {
3542
t := reflect.TypeOf(i).Elem()
3643

3744
for i := 0; i < t.NumField(); i++ {
38-
if err = processField(t.Field(i), v.Field(i)); err != nil {
45+
if err = processField(prefix, t.Field(i), v.Field(i)); err != nil {
3946
return
4047
}
4148
}
@@ -47,7 +54,7 @@ func Set(i interface{}) (err error) {
4754
// and attempt to set it. If not found, another check for the
4855
// "required" tag will be performed to decided whether an error
4956
// needs to be returned.
50-
func processField(t reflect.StructField, v reflect.Value) (err error) {
57+
func processField(prefix string, t reflect.StructField, v reflect.Value) (err error) {
5158
envTag, ok := t.Tag.Lookup("env")
5259
if !ok {
5360
return
@@ -61,7 +68,7 @@ func processField(t reflect.StructField, v reflect.Value) (err error) {
6168

6269
// Lookup the environment variable and if found, set and
6370
// return
64-
env, ok := os.LookupEnv(envTag)
71+
env, ok := os.LookupEnv(prefix + envTag)
6572
if ok {
6673
return setField(t, v, env)
6774
}

env_test.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -614,7 +614,7 @@ func TestInvalidConfigurationForDuration(t *testing.T) {
614614

615615
err := Set(&config)
616616
ErrorNotNil(t, err)
617-
Equals(t, `error setting "Prop": time: unknown unit hh in duration 1hh`, err.Error())
617+
Equals(t, `error setting "Prop": time: unknown unit "hh" in duration "1hh"`, err.Error())
618618
}
619619

620620
func TestEnvNonPointer(t *testing.T) {
@@ -664,6 +664,17 @@ func TestEnvCustomTypeStructWithError(t *testing.T) {
664664
Assert(t, strings.Contains(err.Error(), errConfigDurationError.Error()))
665665
}
666666

667+
func TestEnvPrefixed(t *testing.T) {
668+
os.Setenv("PROP_PROP", "hello")
669+
670+
config := struct {
671+
Prop string `env:"PROP"`
672+
}{}
673+
674+
ErrorNil(t, SetPrefix(&config, "PROP_"))
675+
Equals(t, "hello", config.Prop)
676+
}
677+
667678
type configDuration struct {
668679
Duration time.Duration
669680
}

0 commit comments

Comments
 (0)