diff --git a/ocis-pkg/config/config.go b/ocis-pkg/config/config.go index 7cec4f664d..5e97e79c96 100644 --- a/ocis-pkg/config/config.go +++ b/ocis-pkg/config/config.go @@ -4,6 +4,8 @@ import ( "fmt" "reflect" + "github.com/owncloud/ocis/ocis-pkg/shared" + gofig "github.com/gookit/config/v2" accounts "github.com/owncloud/ocis/accounts/pkg/config" glauth "github.com/owncloud/ocis/glauth/pkg/config" @@ -130,11 +132,6 @@ func New() *Config { } } -type mapping struct { - EnvVars []string // name of the EnvVars var. - Destination interface{} // memory address of the original config value to modify. -} - // GetEnv fetches a list of known env variables for this extension. It is to be used by gookit, as it provides a list // with all the environment variables an extension supports. func GetEnv() []string { @@ -182,8 +179,8 @@ func (c *Config) UnmapEnv(gooconf *gofig.Config) error { } // structMappings binds a set of environment variables to a destination on cfg. -func structMappings(cfg *Config) []mapping { - return []mapping{ +func structMappings(cfg *Config) []shared.EnvBinding { + return []shared.EnvBinding{ { EnvVars: []string{"OCIS_LOG_FILE"}, Destination: &cfg.Log.Level, diff --git a/ocis-pkg/config/environment.go b/ocis-pkg/config/environment.go new file mode 100644 index 0000000000..14d62609c1 --- /dev/null +++ b/ocis-pkg/config/environment.go @@ -0,0 +1,48 @@ +package config + +import ( + "fmt" + "reflect" + + "github.com/owncloud/ocis/ocis-pkg/shared" + + gofig "github.com/gookit/config/v2" +) + +// UnbindEnv takes a config `c` and a EnvBinding +func UnbindEnv(c *gofig.Config, bindings []shared.EnvBinding) error { + return unbindEnv(c, bindings) +} + +func unbindEnv(c *gofig.Config, bindings []shared.EnvBinding) error { + for i := range bindings { + for j := range bindings[i].EnvVars { + // we need to guard against v != "" because this is the condition that checks that the value is set from the environment. + // the `ok` guard is not enough, apparently. + if v, ok := c.GetValue(bindings[i].EnvVars[j]); ok && v != "" { + + // get the destination type from destination + switch reflect.ValueOf(bindings[i].Destination).Type().String() { + case "*bool": + r := c.Bool(bindings[i].EnvVars[j]) + *bindings[i].Destination.(*bool) = r + case "*string": + r := c.String(bindings[i].EnvVars[j]) + *bindings[i].Destination.(*string) = r + case "*int": + r := c.Int(bindings[i].EnvVars[j]) + *bindings[i].Destination.(*int) = r + case "*float64": + // defaults to float64 + r := c.Float(bindings[i].EnvVars[j]) + *bindings[i].Destination.(*float64) = r + default: + // it is unlikely we will ever get here. Let this serve more as a runtime check for when debugging. + return fmt.Errorf("invalid type for env var: `%v`", bindings[i].EnvVars[j]) + } + } + } + } + + return nil +} diff --git a/ocis-pkg/shared/shared_types.go b/ocis-pkg/shared/shared_types.go new file mode 100644 index 0000000000..4897dc3cb0 --- /dev/null +++ b/ocis-pkg/shared/shared_types.go @@ -0,0 +1,9 @@ +package shared + +// EnvBinding represents a direct binding from an env variable to a go kind. Along with gookit/config, its primal goal +// is to unpack environment variables into a Go value. We do so with reflection, and this data structure is just a step +// in between. +type EnvBinding struct { + EnvVars []string // name of the environment var. + Destination interface{} // pointer to the original config value to modify. +} diff --git a/proxy/pkg/command/root.go b/proxy/pkg/command/root.go index 1753992842..9b1430df13 100644 --- a/proxy/pkg/command/root.go +++ b/proxy/pkg/command/root.go @@ -72,12 +72,8 @@ func ParseConfig(c *cli.Context, cfg *config.Config) error { // load all env variables relevant to the config in the current context. conf.LoadOSEnv(config.GetEnv(), false) - - if err = cfg.UnmapEnv(conf); err != nil { - return err - } - - return nil + bindings := config.StructMappings(cfg) + return ociscfg.UnbindEnv(conf, bindings) } // SutureService allows for the proxy command to be embedded and supervised by a suture supervisor tree. diff --git a/proxy/pkg/config/env.go b/proxy/pkg/config/env.go index e8afc953d8..0662983e3a 100644 --- a/proxy/pkg/config/env.go +++ b/proxy/pkg/config/env.go @@ -1,12 +1,5 @@ package config -import ( - "fmt" - "reflect" - - gofig "github.com/gookit/config/v2" -) - type mapping struct { EnvVars []string // name of the EnvVars var. Destination interface{} // memory address of the original config value to modify. @@ -22,38 +15,3 @@ func GetEnv() []string { return r } - -// UnmapEnv loads values from the gooconf.Config argument and sets them in the expected destination. -func (c *Config) UnmapEnv(gooconf *gofig.Config) error { - vals := structMappings(c) - for i := range vals { - for j := range vals[i].EnvVars { - // we need to guard against v != "" because this is the condition that checks that the value is set from the environment. - // the `ok` guard is not enough, apparently. - if v, ok := gooconf.GetValue(vals[i].EnvVars[j]); ok && v != "" { - - // get the destination type from destination - switch reflect.ValueOf(vals[i].Destination).Type().String() { - case "*bool": - r := gooconf.Bool(vals[i].EnvVars[j]) - *vals[i].Destination.(*bool) = r - case "*string": - r := gooconf.String(vals[i].EnvVars[j]) - *vals[i].Destination.(*string) = r - case "*int": - r := gooconf.Int(vals[i].EnvVars[j]) - *vals[i].Destination.(*int) = r - case "*float64": - // defaults to float64 - r := gooconf.Float(vals[i].EnvVars[j]) - *vals[i].Destination.(*float64) = r - default: - // it is unlikely we will ever get here. Let this serve more as a runtime check for when debugging. - return fmt.Errorf("invalid type for env var: `%v`", vals[i].EnvVars[j]) - } - } - } - } - - return nil -} diff --git a/proxy/pkg/config/mappings.go b/proxy/pkg/config/mappings.go index d5ed4bb3d8..5119ff5712 100644 --- a/proxy/pkg/config/mappings.go +++ b/proxy/pkg/config/mappings.go @@ -1,8 +1,14 @@ package config -// structMappings binds a set of environment variables to a destination on cfg. -func structMappings(cfg *Config) []mapping { - return []mapping{ +import "github.com/owncloud/ocis/ocis-pkg/shared" + +// StructMappings binds a set of environment variables to a destination on cfg. +func StructMappings(cfg *Config) []shared.EnvBinding { + return structMappings(cfg) +} + +func structMappings(cfg *Config) []shared.EnvBinding { + return []shared.EnvBinding{ // Logging { EnvVars: []string{"PROXY_LOG_LEVEL", "OCIS_LOG_LEVEL"},