mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-01-05 19:59:37 -06:00
use reflection to set config values from environment
This commit is contained in:
@@ -68,7 +68,12 @@ func NewLogger(cfg *config.Config) log.Logger {
|
||||
|
||||
// ParseConfig loads accounts configuration from known paths.
|
||||
func ParseConfig(c *cli.Context, cfg *config.Config) error {
|
||||
return ociscfg.BindSourcesToStructs("accounts", cfg)
|
||||
_, err := ociscfg.BindSourcesToStructs("accounts", cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SutureService allows for the accounts command to be embedded and supervised by a suture supervisor tree.
|
||||
|
||||
@@ -65,7 +65,7 @@ func sanitizeExtensions(set []string, ext []string, f func(a, b string) bool) []
|
||||
|
||||
// BindSourcesToStructs assigns any config value from a config file / env variable to struct `dst`. Its only purpose
|
||||
// is to solely modify `dst`, not dealing with the config structs; and do so in a thread safe manner.
|
||||
func BindSourcesToStructs(extension string, dst interface{}) error {
|
||||
func BindSourcesToStructs(extension string, dst interface{}) (*gofig.Config, error) {
|
||||
sources := DefaultConfigSources(extension, supportedExtensions)
|
||||
cnf := gofig.NewWithOptions("proxy", gofig.ParseEnv)
|
||||
cnf.AddDriver(gooyaml.Driver)
|
||||
@@ -73,8 +73,8 @@ func BindSourcesToStructs(extension string, dst interface{}) error {
|
||||
|
||||
err := cnf.BindStruct("", &dst)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil
|
||||
return cnf, nil
|
||||
}
|
||||
|
||||
@@ -67,7 +67,19 @@ func NewLogger(cfg *config.Config) log.Logger {
|
||||
|
||||
// ParseConfig loads proxy configuration from known paths.
|
||||
func ParseConfig(c *cli.Context, cfg *config.Config) error {
|
||||
return ociscfg.BindSourcesToStructs("proxy", cfg)
|
||||
conf, err := ociscfg.BindSourcesToStructs("proxy", cfg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// load all env variables relevant to the config in the current context.
|
||||
conf.LoadOSEnv(config.GetEnv(), false)
|
||||
|
||||
if err = config.UnmapEnv(conf, cfg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SutureService allows for the proxy command to be embedded and supervised by a suture supervisor tree.
|
||||
|
||||
82
proxy/pkg/config/env_mapping.go
Normal file
82
proxy/pkg/config/env_mapping.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
gofig "github.com/gookit/config/v2"
|
||||
)
|
||||
|
||||
var mappings = []struct {
|
||||
gType string // expected type, used for decoding. It is the type expected from gookit.
|
||||
envName string // name of the env var
|
||||
tagName string // name of the tag to select the value from. Tag names are to be unique.
|
||||
}{
|
||||
{
|
||||
gType: "bool",
|
||||
envName: "PROXY_ENABLE_BASIC_AUTH",
|
||||
tagName: "enable_basic_auth",
|
||||
},
|
||||
}
|
||||
|
||||
// GetEnv fetches a list of known env variables for this extension.
|
||||
func GetEnv() []string {
|
||||
var r []string
|
||||
for i := range mappings {
|
||||
r = append(r, mappings[i].envName)
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func UnmapEnv(gooconf *gofig.Config, cfg *Config) error {
|
||||
for i := range mappings {
|
||||
switch mappings[i].gType {
|
||||
case "bool":
|
||||
v := gooconf.Bool(mappings[i].envName)
|
||||
if err := setField(cfg, mappings[i].tagName, v); err != nil {
|
||||
return err
|
||||
}
|
||||
case "string":
|
||||
v := gooconf.String(mappings[i].envName)
|
||||
if err := setField(cfg, mappings[i].tagName, v); err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("invalid type for env var: `%v`", mappings[i].envName)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// setField allows us to set a value on a struct selecting by its `mapstructure` tag.
|
||||
func setField(item interface{}, fieldName string, value interface{}) error {
|
||||
v := reflect.ValueOf(item).Elem()
|
||||
if !v.CanAddr() {
|
||||
return fmt.Errorf("cannot assign to the item passed, item must be a pointer in order to assign")
|
||||
}
|
||||
fName := func(t reflect.StructTag) (string, error) {
|
||||
if jt, ok := t.Lookup("mapstructure"); ok {
|
||||
return strings.Split(jt, ",")[0], nil
|
||||
}
|
||||
return "", fmt.Errorf("tag %s provided does not define a json tag", fieldName)
|
||||
}
|
||||
|
||||
fieldNames := map[string]int{}
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
typeField := v.Type().Field(i)
|
||||
tag := typeField.Tag
|
||||
jName, _ := fName(tag)
|
||||
fieldNames[jName] = i
|
||||
}
|
||||
|
||||
fieldNum, ok := fieldNames[fieldName]
|
||||
if !ok {
|
||||
return fmt.Errorf("field does not exist within the provided item")
|
||||
}
|
||||
fieldVal := v.Field(fieldNum)
|
||||
fieldVal.Set(reflect.ValueOf(value))
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user