v0.0.89
This commit is contained in:
parent
ec4dba173f
commit
dba0cd229e
@ -70,103 +70,114 @@ func processEnvOverrides(rval reflect.Value, delim string, prefix string) error
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if rvfield.Type() == reflect.TypeOf("") {
|
if rvfield.Type().Kind() == reflect.Pointer {
|
||||||
|
|
||||||
rvfield.Set(reflect.ValueOf(envval))
|
newval, err := parseEnvToValue(envval, fullEnvKey, rvfield.Type().Elem())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// converts reflect.Value to pointer
|
||||||
|
ptrval := reflect.New(rvfield.Type().Elem())
|
||||||
|
ptrval.Elem().Set(newval)
|
||||||
|
|
||||||
|
rvfield.Set(ptrval)
|
||||||
|
|
||||||
fmt.Printf("[CONF] Overwrite config '%s' with '%s'\n", fullEnvKey, envval)
|
fmt.Printf("[CONF] Overwrite config '%s' with '%s'\n", fullEnvKey, envval)
|
||||||
|
|
||||||
} else if rvfield.Type() == reflect.TypeOf(int(0)) {
|
|
||||||
|
|
||||||
envint, err := strconv.ParseInt(envval, 10, bits.UintSize)
|
|
||||||
if err != nil {
|
|
||||||
return errors.New(fmt.Sprintf("Failed to parse env-config variable '%s' to int (value := '%s')", fullEnvKey, envval))
|
|
||||||
}
|
|
||||||
|
|
||||||
rvfield.Set(reflect.ValueOf(int(envint)))
|
|
||||||
|
|
||||||
fmt.Printf("[CONF] Overwrite config '%s' with '%s'\n", fullEnvKey, envval)
|
|
||||||
|
|
||||||
} else if rvfield.Type() == reflect.TypeOf(int64(0)) {
|
|
||||||
|
|
||||||
envint, err := strconv.ParseInt(envval, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return errors.New(fmt.Sprintf("Failed to parse env-config variable '%s' to int64 (value := '%s')", fullEnvKey, envval))
|
|
||||||
}
|
|
||||||
|
|
||||||
rvfield.Set(reflect.ValueOf(int64(envint)))
|
|
||||||
|
|
||||||
fmt.Printf("[CONF] Overwrite config '%s' with '%s'\n", fullEnvKey, envval)
|
|
||||||
|
|
||||||
} else if rvfield.Type() == reflect.TypeOf(int32(0)) {
|
|
||||||
|
|
||||||
envint, err := strconv.ParseInt(envval, 10, 32)
|
|
||||||
if err != nil {
|
|
||||||
return errors.New(fmt.Sprintf("Failed to parse env-config variable '%s' to int32 (value := '%s')", fullEnvKey, envval))
|
|
||||||
}
|
|
||||||
|
|
||||||
rvfield.Set(reflect.ValueOf(int32(envint)))
|
|
||||||
|
|
||||||
fmt.Printf("[CONF] Overwrite config '%s' with '%s'\n", fullEnvKey, envval)
|
|
||||||
|
|
||||||
} else if rvfield.Type() == reflect.TypeOf(int8(0)) {
|
|
||||||
|
|
||||||
envint, err := strconv.ParseInt(envval, 10, 8)
|
|
||||||
if err != nil {
|
|
||||||
return errors.New(fmt.Sprintf("Failed to parse env-config variable '%s' to int32 (value := '%s')", fullEnvKey, envval))
|
|
||||||
}
|
|
||||||
|
|
||||||
rvfield.Set(reflect.ValueOf(int8(envint)))
|
|
||||||
|
|
||||||
fmt.Printf("[CONF] Overwrite config '%s' with '%s'\n", fullEnvKey, envval)
|
|
||||||
|
|
||||||
} else if rvfield.Type() == reflect.TypeOf(time.Duration(0)) {
|
|
||||||
|
|
||||||
dur, err := timeext.ParseDurationShortString(envval)
|
|
||||||
if err != nil {
|
|
||||||
return errors.New(fmt.Sprintf("Failed to parse env-config variable '%s' to duration (value := '%s')", fullEnvKey, envval))
|
|
||||||
}
|
|
||||||
|
|
||||||
rvfield.Set(reflect.ValueOf(dur))
|
|
||||||
|
|
||||||
fmt.Printf("[CONF] Overwrite config '%s' with '%s'\n", fullEnvKey, dur.String())
|
|
||||||
|
|
||||||
} else if rvfield.Type() == reflect.TypeOf(time.UnixMilli(0)) {
|
|
||||||
|
|
||||||
tim, err := time.Parse(time.RFC3339Nano, envval)
|
|
||||||
if err != nil {
|
|
||||||
return errors.New(fmt.Sprintf("Failed to parse env-config variable '%s' to time.time (value := '%s')", fullEnvKey, envval))
|
|
||||||
}
|
|
||||||
|
|
||||||
rvfield.Set(reflect.ValueOf(tim))
|
|
||||||
|
|
||||||
fmt.Printf("[CONF] Overwrite config '%s' with '%s'\n", fullEnvKey, tim.String())
|
|
||||||
|
|
||||||
} else if rvfield.Type().ConvertibleTo(reflect.TypeOf(int(0))) {
|
|
||||||
|
|
||||||
envint, err := strconv.ParseInt(envval, 10, 8)
|
|
||||||
if err != nil {
|
|
||||||
return errors.New(fmt.Sprintf("Failed to parse env-config variable '%s' to <%s, ,int> (value := '%s')", rvfield.Type().Name(), fullEnvKey, envval))
|
|
||||||
}
|
|
||||||
|
|
||||||
envcvl := reflect.ValueOf(envint).Convert(rvfield.Type())
|
|
||||||
|
|
||||||
rvfield.Set(envcvl)
|
|
||||||
|
|
||||||
fmt.Printf("[CONF] Overwrite config '%s' with '%v'\n", fullEnvKey, envcvl.Interface())
|
|
||||||
|
|
||||||
} else if rvfield.Type().ConvertibleTo(reflect.TypeOf("")) {
|
|
||||||
|
|
||||||
envcvl := reflect.ValueOf(envval).Convert(rvfield.Type())
|
|
||||||
|
|
||||||
rvfield.Set(envcvl)
|
|
||||||
|
|
||||||
fmt.Printf("[CONF] Overwrite config '%s' with '%v'\n", fullEnvKey, envcvl.Interface())
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return errors.New(fmt.Sprintf("Unknown kind/type in config: [ %s | %s ]", rvfield.Kind().String(), rvfield.Type().String()))
|
|
||||||
|
newval, err := parseEnvToValue(envval, fullEnvKey, rvfield.Type())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
rvfield.Set(newval)
|
||||||
|
fmt.Printf("[CONF] Overwrite config '%s' with '%s'\n", fullEnvKey, envval)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseEnvToValue(envval string, fullEnvKey string, rvtype reflect.Type) (reflect.Value, error) {
|
||||||
|
if rvtype == reflect.TypeOf("") {
|
||||||
|
|
||||||
|
return reflect.ValueOf(envval), nil
|
||||||
|
|
||||||
|
} else if rvtype == reflect.TypeOf(int(0)) {
|
||||||
|
|
||||||
|
envint, err := strconv.ParseInt(envval, 10, bits.UintSize)
|
||||||
|
if err != nil {
|
||||||
|
return reflect.Value{}, errors.New(fmt.Sprintf("Failed to parse env-config variable '%s' to int (value := '%s')", fullEnvKey, envval))
|
||||||
|
}
|
||||||
|
|
||||||
|
return reflect.ValueOf(int(envint)), nil
|
||||||
|
|
||||||
|
} else if rvtype == reflect.TypeOf(int64(0)) {
|
||||||
|
|
||||||
|
envint, err := strconv.ParseInt(envval, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return reflect.Value{}, errors.New(fmt.Sprintf("Failed to parse env-config variable '%s' to int64 (value := '%s')", fullEnvKey, envval))
|
||||||
|
}
|
||||||
|
|
||||||
|
return reflect.ValueOf(int64(envint)), nil
|
||||||
|
|
||||||
|
} else if rvtype == reflect.TypeOf(int32(0)) {
|
||||||
|
|
||||||
|
envint, err := strconv.ParseInt(envval, 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
return reflect.Value{}, errors.New(fmt.Sprintf("Failed to parse env-config variable '%s' to int32 (value := '%s')", fullEnvKey, envval))
|
||||||
|
}
|
||||||
|
|
||||||
|
return reflect.ValueOf(int32(envint)), nil
|
||||||
|
|
||||||
|
} else if rvtype == reflect.TypeOf(int8(0)) {
|
||||||
|
|
||||||
|
envint, err := strconv.ParseInt(envval, 10, 8)
|
||||||
|
if err != nil {
|
||||||
|
return reflect.Value{}, errors.New(fmt.Sprintf("Failed to parse env-config variable '%s' to int32 (value := '%s')", fullEnvKey, envval))
|
||||||
|
}
|
||||||
|
|
||||||
|
return reflect.ValueOf(int8(envint)), nil
|
||||||
|
|
||||||
|
} else if rvtype == reflect.TypeOf(time.Duration(0)) {
|
||||||
|
|
||||||
|
dur, err := timeext.ParseDurationShortString(envval)
|
||||||
|
if err != nil {
|
||||||
|
return reflect.Value{}, errors.New(fmt.Sprintf("Failed to parse env-config variable '%s' to duration (value := '%s')", fullEnvKey, envval))
|
||||||
|
}
|
||||||
|
|
||||||
|
return reflect.ValueOf(dur), nil
|
||||||
|
|
||||||
|
} else if rvtype == reflect.TypeOf(time.UnixMilli(0)) {
|
||||||
|
|
||||||
|
tim, err := time.Parse(time.RFC3339Nano, envval)
|
||||||
|
if err != nil {
|
||||||
|
return reflect.Value{}, errors.New(fmt.Sprintf("Failed to parse env-config variable '%s' to time.time (value := '%s')", fullEnvKey, envval))
|
||||||
|
}
|
||||||
|
|
||||||
|
return reflect.ValueOf(tim), nil
|
||||||
|
|
||||||
|
} else if rvtype.ConvertibleTo(reflect.TypeOf(int(0))) {
|
||||||
|
|
||||||
|
envint, err := strconv.ParseInt(envval, 10, 8)
|
||||||
|
if err != nil {
|
||||||
|
return reflect.Value{}, errors.New(fmt.Sprintf("Failed to parse env-config variable '%s' to <%s, ,int> (value := '%s')", rvtype.Name(), fullEnvKey, envval))
|
||||||
|
}
|
||||||
|
|
||||||
|
envcvl := reflect.ValueOf(envint).Convert(rvtype)
|
||||||
|
|
||||||
|
return envcvl, nil
|
||||||
|
|
||||||
|
} else if rvtype.ConvertibleTo(reflect.TypeOf("")) {
|
||||||
|
|
||||||
|
envcvl := reflect.ValueOf(envval).Convert(rvtype)
|
||||||
|
return envcvl, nil
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return reflect.Value{}, errors.New(fmt.Sprintf("Unknown kind/type in config: [ %s | %s ]", rvtype.Kind().String(), rvtype.String()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -213,8 +213,65 @@ func TestApplyEnvOverridesRecursive(t *testing.T) {
|
|||||||
assertEqual(t, data.Sub4.V9, time.Unix(2335219200, 0).UTC())
|
assertEqual(t, data.Sub4.V9, time.Unix(2335219200, 0).UTC())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestApplyEnvOverridesPointer(t *testing.T) {
|
||||||
|
|
||||||
|
type aliasint int
|
||||||
|
type aliasstring string
|
||||||
|
|
||||||
|
type testdata struct {
|
||||||
|
V1 *int `env:"TEST_V1"`
|
||||||
|
VX *string ``
|
||||||
|
V2 *string `env:"TEST_V2"`
|
||||||
|
V3 *int8 `env:"TEST_V3"`
|
||||||
|
V4 *int32 `env:"TEST_V4"`
|
||||||
|
V5 *int64 `env:"TEST_V5"`
|
||||||
|
V6 *aliasint `env:"TEST_V6"`
|
||||||
|
VY *aliasint ``
|
||||||
|
V7 *aliasstring `env:"TEST_V7"`
|
||||||
|
V8 *time.Duration `env:"TEST_V8"`
|
||||||
|
V9 *time.Time `env:"TEST_V9"`
|
||||||
|
}
|
||||||
|
|
||||||
|
data := testdata{}
|
||||||
|
|
||||||
|
t.Setenv("TEST_V1", "846")
|
||||||
|
t.Setenv("TEST_V2", "hello_world")
|
||||||
|
t.Setenv("TEST_V3", "6")
|
||||||
|
t.Setenv("TEST_V4", "333")
|
||||||
|
t.Setenv("TEST_V5", "-937")
|
||||||
|
t.Setenv("TEST_V6", "070")
|
||||||
|
t.Setenv("TEST_V7", "AAAAAA")
|
||||||
|
t.Setenv("TEST_V8", "1min4s")
|
||||||
|
t.Setenv("TEST_V9", "2009-11-10T23:00:00Z")
|
||||||
|
|
||||||
|
err := ApplyEnvOverrides(&data, ".")
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("%v", err)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
|
||||||
|
assertPtrEqual(t, data.V1, 846)
|
||||||
|
assertPtrEqual(t, data.V2, "hello_world")
|
||||||
|
assertPtrEqual(t, data.V3, 6)
|
||||||
|
assertPtrEqual(t, data.V4, 333)
|
||||||
|
assertPtrEqual(t, data.V5, -937)
|
||||||
|
assertPtrEqual(t, data.V6, 70)
|
||||||
|
assertPtrEqual(t, data.V7, "AAAAAA")
|
||||||
|
assertPtrEqual(t, data.V8, time.Second*64)
|
||||||
|
assertPtrEqual(t, data.V9, time.Unix(1257894000, 0).UTC())
|
||||||
|
}
|
||||||
|
|
||||||
func assertEqual[T comparable](t *testing.T, actual T, expected T) {
|
func assertEqual[T comparable](t *testing.T, actual T, expected T) {
|
||||||
if actual != expected {
|
if actual != expected {
|
||||||
t.Errorf("values differ: Actual: '%v', Expected: '%v'", actual, expected)
|
t.Errorf("values differ: Actual: '%v', Expected: '%v'", actual, expected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func assertPtrEqual[T comparable](t *testing.T, actual *T, expected T) {
|
||||||
|
if actual == nil {
|
||||||
|
t.Errorf("values differ: Actual: NIL, Expected: '%v'", expected)
|
||||||
|
}
|
||||||
|
if *actual != expected {
|
||||||
|
t.Errorf("values differ: Actual: '%v', Expected: '%v'", actual, expected)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user