git.iko.soy/typeable/oauth2-proxy
on master help sign in
Allow embedded structs in env_options
2da89f8Joel Speed
env_options.go+15−2
@@ -15,14 +15,27 @@ type EnvOptions map[string]interface{}
15// Fields in the options struct must have an `env` and `cfg` tag to be read
15// Fields in the options struct must have an `env` and `cfg` tag to be read
16// from the environment
16// from the environment
17func (cfg EnvOptions) LoadEnvForStruct(options interface{}) {
17func (cfg EnvOptions) LoadEnvForStruct(options interface{}) {
18− val := reflect.ValueOf(options).Elem()
18+ val := reflect.ValueOf(options)
19+ var typ reflect.Type
20+ if val.Kind() == reflect.Ptr {
21+ typ = val.Elem().Type()
22+ } else {
19− typ := val.Type()
23+ typ = val.Type()
24+ }
25+
20 for i := 0; i < typ.NumField(); i++ {
26 for i := 0; i < typ.NumField(); i++ {
21 // pull out the struct tags:
27 // pull out the struct tags:
22 // flag - the name of the command line flag
28 // flag - the name of the command line flag
23 // deprecated - (optional) the name of the deprecated command line flag
29 // deprecated - (optional) the name of the deprecated command line flag
24 // cfg - (optional, defaults to underscored flag) the name of the config file option
30 // cfg - (optional, defaults to underscored flag) the name of the config file option
25 field := typ.Field(i)
31 field := typ.Field(i)
32+ fieldV := reflect.Indirect(val).Field(i)
33+
34+ if field.Type.Kind() == reflect.Struct && field.Anonymous {
35+ cfg.LoadEnvForStruct(fieldV.Interface())
36+ continue
37+ }
38+
26 flagName := field.Tag.Get("flag")
39 flagName := field.Tag.Get("flag")
27 envName := field.Tag.Get("env")
40 envName := field.Tag.Get("env")
28 cfgName := field.Tag.Get("cfg")
41 cfgName := field.Tag.Get("cfg")
env_options_test.go+26−6
@@ -1,26 +1,46 @@
1−package main
1+package main_test
2
2
3import (
3import (
4 "os"
4 "os"
5 "testing"
5 "testing"
6
6
7+ proxy "github.com/pusher/oauth2_proxy"
7 "github.com/stretchr/testify/assert"
8 "github.com/stretchr/testify/assert"
8)
9)
9
10
10−type envTest struct {
11+type EnvTest struct {
11− testField string `cfg:"target_field" env:"TEST_ENV_FIELD"`
12+ TestField string `cfg:"target_field" env:"TEST_ENV_FIELD"`
13+ EnvTestEmbed
14+}
15+
16+type EnvTestEmbed struct {
17+ TestFieldEmbed string `cfg:"target_field_embed" env:"TEST_ENV_FIELD_EMBED"`
12}
18}
13
19
14func TestLoadEnvForStruct(t *testing.T) {
20func TestLoadEnvForStruct(t *testing.T) {
15
21
16− cfg := make(EnvOptions)
22+ cfg := make(proxy.EnvOptions)
17− cfg.LoadEnvForStruct(&envTest{})
23+ cfg.LoadEnvForStruct(&EnvTest{})
18
24
19 _, ok := cfg["target_field"]
25 _, ok := cfg["target_field"]
20 assert.Equal(t, ok, false)
26 assert.Equal(t, ok, false)
21
27
22 os.Setenv("TEST_ENV_FIELD", "1234abcd")
28 os.Setenv("TEST_ENV_FIELD", "1234abcd")
23− cfg.LoadEnvForStruct(&envTest{})
29+ cfg.LoadEnvForStruct(&EnvTest{})
24 v := cfg["target_field"]
30 v := cfg["target_field"]
25 assert.Equal(t, v, "1234abcd")
31 assert.Equal(t, v, "1234abcd")
26}
32}
33+
34+func TestLoadEnvForStructWithEmbeddedFields(t *testing.T) {
35+
36+ cfg := make(proxy.EnvOptions)
37+ cfg.LoadEnvForStruct(&EnvTest{})
38+
39+ _, ok := cfg["target_field_embed"]
40+ assert.Equal(t, ok, false)
41+
42+ os.Setenv("TEST_ENV_FIELD_EMBED", "1234abcd")
43+ cfg.LoadEnvForStruct(&EnvTest{})
44+ v := cfg["target_field_embed"]
45+ assert.Equal(t, v, "1234abcd")
46+}