mediamtx/confenv/confenv.go

125 lines
2.4 KiB
Go
Raw Normal View History

package confenv
import (
"fmt"
"os"
"reflect"
"strconv"
"strings"
"time"
)
func process(env map[string]string, envKey string, rv reflect.Value) error {
rt := rv.Type()
switch rt {
case reflect.TypeOf(time.Duration(0)):
if ev, ok := env[envKey]; ok {
d, err := time.ParseDuration(ev)
if err != nil {
return fmt.Errorf("%s: %s", envKey, err)
}
rv.Set(reflect.ValueOf(d))
}
return nil
}
switch rt.Kind() {
case reflect.String:
if ev, ok := env[envKey]; ok {
rv.SetString(ev)
}
return nil
case reflect.Int:
if ev, ok := env[envKey]; ok {
iv, err := strconv.ParseInt(ev, 10, 64)
if err != nil {
return fmt.Errorf("%s: %s", envKey, err)
}
rv.SetInt(iv)
}
return nil
case reflect.Bool:
if ev, ok := env[envKey]; ok {
switch strings.ToLower(ev) {
case "yes", "true":
rv.SetBool(true)
case "no", "false":
rv.SetBool(false)
default:
return fmt.Errorf("%s: invalid value '%s'", envKey, ev)
}
}
return nil
case reflect.Slice:
if rt.Elem().Kind() == reflect.String {
if ev, ok := env[envKey]; ok {
nv := reflect.Zero(rt)
for _, sv := range strings.Split(ev, ",") {
nv = reflect.Append(nv, reflect.ValueOf(sv))
}
rv.Set(nv)
}
return nil
}
case reflect.Map:
for k := range env {
if !strings.HasPrefix(k, envKey) {
continue
}
tmp := strings.Split(strings.TrimPrefix(k[len(envKey):], "_"), "_")
mapKey := strings.ToLower(tmp[0])
nv := rv.MapIndex(reflect.ValueOf(mapKey))
zero := reflect.Value{}
if nv == zero {
nv = reflect.New(rt.Elem().Elem())
rv.SetMapIndex(reflect.ValueOf(mapKey), nv)
}
err := process(env, envKey+"_"+strings.ToUpper(mapKey), nv.Elem())
if err != nil {
return err
}
}
return nil
case reflect.Struct:
flen := rt.NumField()
for i := 0; i < flen; i++ {
2020-10-13 22:50:08 +00:00
f := rt.Field(i)
// process only public fields
2020-10-13 22:50:08 +00:00
if f.Tag.Get("yaml") == "-" {
continue
}
2020-10-13 22:50:08 +00:00
fieldEnvKey := envKey + "_" + strings.ToUpper(f.Name)
err := process(env, fieldEnvKey, rv.Field(i))
if err != nil {
return err
}
}
return nil
}
return fmt.Errorf("unsupported type: %v", rt)
}
func Process(envKey string, v interface{}) error {
env := make(map[string]string)
for _, kv := range os.Environ() {
tmp := strings.Split(kv, "=")
env[tmp[0]] = tmp[1]
}
return process(env, envKey, reflect.ValueOf(v).Elem())
}