diff --git a/env_options.go b/env_options.go index d54f5af..9db2d89 100644 --- a/env_options.go +++ b/env_options.go @@ -15,14 +15,27 @@ type EnvOptions map[string]interface{} // Fields in the options struct must have an `env` and `cfg` tag to be read // from the environment func (cfg EnvOptions) LoadEnvForStruct(options interface{}) { - val := reflect.ValueOf(options).Elem() - typ := val.Type() + val := reflect.ValueOf(options) + var typ reflect.Type + if val.Kind() == reflect.Ptr { + typ = val.Elem().Type() + } else { + typ = val.Type() + } + for i := 0; i < typ.NumField(); i++ { // pull out the struct tags: // flag - the name of the command line flag // deprecated - (optional) the name of the deprecated command line flag // cfg - (optional, defaults to underscored flag) the name of the config file option field := typ.Field(i) + fieldV := reflect.Indirect(val).Field(i) + + if field.Type.Kind() == reflect.Struct && field.Anonymous { + cfg.LoadEnvForStruct(fieldV.Interface()) + continue + } + flagName := field.Tag.Get("flag") envName := field.Tag.Get("env") cfgName := field.Tag.Get("cfg") diff --git a/env_options_test.go b/env_options_test.go index e9277f7..c1937e6 100644 --- a/env_options_test.go +++ b/env_options_test.go @@ -1,26 +1,46 @@ -package main +package main_test import ( "os" "testing" + proxy "github.com/pusher/oauth2_proxy" "github.com/stretchr/testify/assert" ) -type envTest struct { - testField string `cfg:"target_field" env:"TEST_ENV_FIELD"` +type EnvTest struct { + TestField string `cfg:"target_field" env:"TEST_ENV_FIELD"` + EnvTestEmbed +} + +type EnvTestEmbed struct { + TestFieldEmbed string `cfg:"target_field_embed" env:"TEST_ENV_FIELD_EMBED"` } func TestLoadEnvForStruct(t *testing.T) { - cfg := make(EnvOptions) - cfg.LoadEnvForStruct(&envTest{}) + cfg := make(proxy.EnvOptions) + cfg.LoadEnvForStruct(&EnvTest{}) _, ok := cfg["target_field"] assert.Equal(t, ok, false) os.Setenv("TEST_ENV_FIELD", "1234abcd") - cfg.LoadEnvForStruct(&envTest{}) + cfg.LoadEnvForStruct(&EnvTest{}) v := cfg["target_field"] assert.Equal(t, v, "1234abcd") } + +func TestLoadEnvForStructWithEmbeddedFields(t *testing.T) { + + cfg := make(proxy.EnvOptions) + cfg.LoadEnvForStruct(&EnvTest{}) + + _, ok := cfg["target_field_embed"] + assert.Equal(t, ok, false) + + os.Setenv("TEST_ENV_FIELD_EMBED", "1234abcd") + cfg.LoadEnvForStruct(&EnvTest{}) + v := cfg["target_field_embed"] + assert.Equal(t, v, "1234abcd") +}