Skip to content

Commit

Permalink
feat(viperx): Add support for parsing config passed through env vars …
Browse files Browse the repository at this point in the history
…as json (#232)
  • Loading branch information
bmonkman authored Nov 16, 2020
1 parent 25720ec commit 5b71f1e
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 10 deletions.
18 changes: 17 additions & 1 deletion viperx/vars.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,24 @@ func UnmarshalKey(key string, destination interface{}) error {
}

var b bytes.Buffer
if err := json.NewEncoder(&b).Encode(mapx.ToJSONMap(viper.Get(key))); err != nil {

// This may be a string in the case where a value was provided via an env var.
// If it's a string, try to decode it as json.
if v, ok := value.(string); ok {
if _, err := b.WriteString(v); err != nil {
return errors.WithStack(err)
}

// Try decoding the json directly. If it decodes successfully, return immediately.
if err := json.NewDecoder(&b).Decode(destination); err == nil {
return nil
}
}

// If it's not a string or not valid json, use the value as it was originally provided.
if err := json.NewEncoder(&b).Encode(mapx.ToJSONMap(value)); err != nil {
return errors.WithStack(err)
}

return errors.WithStack(json.NewDecoder(&b).Decode(destination))
}
59 changes: 50 additions & 9 deletions viperx/vars_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,56 @@ import (
)

func TestUnmarshalKey(t *testing.T) {
viper.SetConfigFile("./stub/.unmarshal-key.yml")
require.NoError(t, viper.ReadInConfig())
t.Run("case=Unmarshal a map from viper", func(t *testing.T) {
viper.SetConfigFile("./stub/.unmarshal-key.yml")
require.NoError(t, viper.ReadInConfig())

var config struct {
Enabled bool `json:"enabled"`
Config json.RawMessage `json:"config"`
}
require.NoError(t, UnmarshalKey("selfservice.strategies.oidc", &config))
var config struct {
Enabled bool `json:"enabled"`
Config json.RawMessage `json:"config"`
}
require.NoError(t, UnmarshalKey("selfservice.strategies.oidc", &config))

assert.EqualValues(t, true, config.Enabled)
assert.EqualValues(t, `{"providers":[{"client_id":"kratos-client","client_secret":"kratos-secret","id":"hydra","issuer_url":"http://127.0.0.1:4444/","mapper_url":"file://test/e2e/profiles/oidc/hydra.jsonnet","provider":"generic","scope":["offline"]},{"client_id":"google-client","client_secret":"kratos-secret","id":"google","issuer_url":"http://127.0.0.1:4444/","mapper_url":"file://test/e2e/profiles/oidc/hydra.jsonnet","provider":"generic","scope":["offline"]},{"client_id":"github-client","client_secret":"kratos-secret","id":"github","issuer_url":"http://127.0.0.1:4444/","mapper_url":"file://test/e2e/profiles/oidc/hydra.jsonnet","provider":"generic","scope":["offline"]}]}`, string(config.Config))
})

t.Run("case=Unmarshal a string containing a JSON object", func(t *testing.T) {
viper.SetConfigFile("./stub/.unmarshal-key.yml")
viper.Set("selfservice.strategies.oidc", `{"enabled":true, "config":{"providers": [{"client_id":"a-different-client","client_secret":"a-different-secret","issuer_url":"http://127.0.0.1:4444/","mapper_url":"file://test/e2e/profiles/oidc/a-different-file.jsonnet","provider":"github","scope":["user:email"]}]}}`)
require.NoError(t, viper.ReadInConfig())

var config struct {
Enabled bool `json:"enabled"`
Config json.RawMessage `json:"config"`
}
require.NoError(t, UnmarshalKey("selfservice.strategies.oidc", &config))

assert.EqualValues(t, true, config.Enabled)
assert.EqualValues(t, `{"providers": [{"client_id":"a-different-client","client_secret":"a-different-secret","issuer_url":"http://127.0.0.1:4444/","mapper_url":"file://test/e2e/profiles/oidc/a-different-file.jsonnet","provider":"github","scope":["user:email"]}]}`, string(config.Config))
})

t.Run("case=Unmarshal a string containing invalid JSON", func(t *testing.T) {
viper.SetConfigFile("./stub/.unmarshal-key.yml")
viper.Set("selfservice.strategies.oidc", `{"enabled":true, "config":{"providers": [{"client_id":"a-different-client",`)
require.NoError(t, viper.ReadInConfig())

var config struct {
Enabled bool `json:"enabled"`
Config json.RawMessage `json:"config"`
}
require.Error(t, UnmarshalKey("selfservice.strategies.oidc", &config))
})

t.Run("case=Unmarshal a regular string", func(t *testing.T) {
viper.SetConfigFile("./stub/.unmarshal-key.yml")
viper.Set("identity.default_schema_url", `https://ory.sh`)
require.NoError(t, viper.ReadInConfig())

var defaultSchemaURL string
require.NoError(t, UnmarshalKey("identity.default_schema_url", &defaultSchemaURL))

assert.EqualValues(t, `https://ory.sh`, defaultSchemaURL)
})

assert.EqualValues(t, true, config.Enabled)
assert.EqualValues(t, `{"providers":[{"client_id":"kratos-client","client_secret":"kratos-secret","id":"hydra","issuer_url":"http://127.0.0.1:4444/","mapper_url":"file://test/e2e/profiles/oidc/hydra.jsonnet","provider":"generic","scope":["offline"]},{"client_id":"google-client","client_secret":"kratos-secret","id":"google","issuer_url":"http://127.0.0.1:4444/","mapper_url":"file://test/e2e/profiles/oidc/hydra.jsonnet","provider":"generic","scope":["offline"]},{"client_id":"github-client","client_secret":"kratos-secret","id":"github","issuer_url":"http://127.0.0.1:4444/","mapper_url":"file://test/e2e/profiles/oidc/hydra.jsonnet","provider":"generic","scope":["offline"]}]}`, string(config.Config))
}

0 comments on commit 5b71f1e

Please sign in to comment.