Skip to content

Commit

Permalink
support url.URL setting type, handle error if unknown type
Browse files Browse the repository at this point in the history
  • Loading branch information
JamesReate committed Aug 29, 2024
1 parent 2de0b64 commit 2539973
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 10 deletions.
23 changes: 15 additions & 8 deletions config_loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,12 @@ func loadFromEnvVars[S any](settings S) error {
for i := 0; i < valueOfConfig.NumField(); i++ {
field := valueOfConfig.Field(i)
fieldYamlName := typeOfT.Field(i).Tag.Get("yaml")
if fieldYamlName == "-" {
if fieldYamlName == "-" { // ignore property
continue
}
if field.Kind() == reflect.Struct {
if typeOfT.Field(i).Type == reflect.TypeOf(url.URL{}) {
err = matchEnvVarToField(fieldYamlName, field)
} else if field.Kind() == reflect.Struct {
// iterate through the fields - like above, prepend fieldYamlName
for i := 0; i < field.NumField(); i++ {
subField := field.Field(i)
Expand All @@ -83,19 +85,24 @@ func matchEnvVarToField(envVarName string, field reflect.Value) error { // other
var val any
switch field.Kind() {
case reflect.String:
if strings.HasPrefix(env, "http") {
if urlParsed, err := url.Parse(env); err == nil {
val = urlParsed
break
}
}
val = env
case reflect.Bool:
val, err = strconv.ParseBool(env)
case reflect.Int:
val, err = strconv.Atoi(env)
case reflect.Int64:
val, err = strconv.ParseInt(env, 10, 64)
default:
// want to check for actual type, not just Kind, which are like the standard types
if field.Type() == reflect.TypeOf(url.URL{}) {
if urlParsed, err := url.Parse(env); err == nil {
val = *urlParsed
} else {
return err
}
} else {
return fmt.Errorf("unknown setting Type: %s", field.Type().Name())
}
}
// now set the field with the val
if val != nil {
Expand Down
32 changes: 30 additions & 2 deletions config_loader_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package shared

import (
"github.com/stretchr/testify/require"
"net/url"
"reflect"
"testing"

Expand All @@ -16,6 +18,7 @@ REDIS:
URL: redis.bobby
INLINE_URL: inline.bobby
IGNORE: ignoreme
ACTUAL_URL_OBJECT: https://identity-api.dimo.zone/query
`
settings, err := loadFromYaml[TestSettings]([]byte(data))
assert.NoError(t, err, "no error expected")

Check failure on line 24 in config_loader_test.go

View workflow job for this annotation

GitHub Actions / tests

config_loader_test.go:24: Error Trace: /home/runner/work/shared/shared/config_loader_test.go:24 Error: Received unexpected error: yaml: unmarshal errors: line 9: cannot unmarshal !!str `https:/...` into url.URL could not unmarshall yaml file to settings github.com/DIMO-Network/shared.loadFromYaml[...] /home/runner/work/shared/shared/config_loader.go:38 github.com/DIMO-Network/shared.Test_loadFromYaml /home/runner/work/shared/shared/config_loader_test.go:23 testing.tRunner /opt/hostedtoolcache/go/1.21.13/x64/src/testing/testing.go:1595 runtime.goexit /opt/hostedtoolcache/go/1.21.13/x64/src/runtime/asm_amd64.s:1650 Test: Test_loadFromYaml
Expand All @@ -26,6 +29,9 @@ IGNORE: ignoreme
assert.Equal(t, "redis.bobby", settings.Redis.URL)
assert.Equal(t, "inline.bobby", settings.Inline.URL)
assert.Equal(t, "", settings.IGNORE)
assert.Equal(t, "https://identity-api.dimo.zone/query", settings.ActualURLObject.String())

Check failure on line 32 in config_loader_test.go

View workflow job for this annotation

GitHub Actions / tests

config_loader_test.go:32: Error Trace: /home/runner/work/shared/shared/config_loader_test.go:32 Error: Not equal: expected: "https://identity-api.dimo.zone/query" actual : "" Diff: --- Expected +++ Actual @@ -1 +1 @@ -https://identity-api.dimo.zone/query + Test: Test_loadFromYaml
assert.Equal(t, "/query", settings.ActualURLObject.Path)

Check failure on line 33 in config_loader_test.go

View workflow job for this annotation

GitHub Actions / tests

config_loader_test.go:33: Error Trace: /home/runner/work/shared/shared/config_loader_test.go:33 Error: Not equal: expected: "/query" actual : "" Diff: --- Expected +++ Actual @@ -1 +1 @@ -/query + Test: Test_loadFromYaml
assert.Equal(t, "identity-api.dimo.zone", settings.ActualURLObject.Host)

Check failure on line 34 in config_loader_test.go

View workflow job for this annotation

GitHub Actions / tests

config_loader_test.go:34: Error Trace: /home/runner/work/shared/shared/config_loader_test.go:34 Error: Not equal: expected: "identity-api.dimo.zone" actual : "" Diff: --- Expected +++ Actual @@ -1 +1 @@ -identity-api.dimo.zone + Test: Test_loadFromYaml ---
}

func Test_loadFromEnvVars(t *testing.T) {
Expand All @@ -40,16 +46,20 @@ func Test_loadFromEnvVars(t *testing.T) {
t.Setenv("REDIS_URL", "redis.bobby")
t.Setenv("INLINE_URL", "inline.bobby")
t.Setenv("IGNORE", "ignoreme")
t.Setenv("ACTUAL_URL_OBJECT", "https://identity-api.dimo.zone/query")

err := loadFromEnvVars(&settings) // b/c of type inference we don't need to specify the type
assert.NoError(t, err)
require.NoError(t, err)
assert.NotNilf(t, settings, "expected not nil")
assert.Equal(t, "test", settings.Env)
assert.Equal(t, 5000, settings.Port)
assert.Equal(t, "mydb.aws.net", settings.DbConnectString)
assert.Equal(t, "redis.bobby", settings.Redis.URL)
assert.Equal(t, "inline.bobby", settings.Inline.URL)
assert.Equal(t, "", settings.IGNORE)
assert.Equal(t, "https://identity-api.dimo.zone/query", settings.ActualURLObject.String())
assert.Equal(t, "/query", settings.ActualURLObject.Path)
assert.Equal(t, "identity-api.dimo.zone", settings.ActualURLObject.Host)
}

func Test_loadFromEnvVars_errIfNotPointer(t *testing.T) {
Expand All @@ -58,9 +68,10 @@ func Test_loadFromEnvVars_errIfNotPointer(t *testing.T) {
assert.Error(t, err, "expected error if settings not a pointer")
}

func Test_matchEnvVarToField(t *testing.T) {
func Test_matchEnvVarToField_PortInt(t *testing.T) {
settings := &TestSettings{}
t.Setenv("PORT", "5000")
t.Setenv("ACTUAL_URL_OBJECT", "https://identity-api.dimo.zone/query")

valueOfConfig := reflect.ValueOf(settings).Elem()
field := valueOfConfig.Field(0)
Expand All @@ -72,13 +83,30 @@ func Test_matchEnvVarToField(t *testing.T) {
assert.Equal(t, 5000, settings.Port)
}

func Test_matchEnvVarToField_Url(t *testing.T) {
settings := &TestSettings{}
t.Setenv("ACTUAL_URL_OBJECT", "https://identity-api.dimo.zone/query")

valueOfConfig := reflect.ValueOf(settings).Elem()
field := valueOfConfig.Field(6)

err := matchEnvVarToField("ACTUAL_URL_OBJECT", field)
assert.NoError(t, err)

//assert.Equal(t, "https://identity-api.dimo.zone/query", field.String())
assert.Equal(t, "https://identity-api.dimo.zone/query", settings.ActualURLObject.String())
assert.Equal(t, "/query", settings.ActualURLObject.Path)
assert.Equal(t, "identity-api.dimo.zone", settings.ActualURLObject.Host)
}

type TestSettings struct {
Port int `yaml:"PORT"`
DbConnectString string `yaml:"DB_CONNECT_STRING"`
Env string `yaml:"ENV"`
Redis RedisSubProp `yaml:"REDIS"`
Inline InlineSubProp `yaml:",inline"`
IGNORE string `yaml:"-"`
ActualURLObject url.URL `yaml:"ACTUAL_URL_OBJECT"`
}

type RedisSubProp struct {
Expand Down

0 comments on commit 2539973

Please sign in to comment.