mediocre-go-lib/mcfg/env.go
Brian Picciano 4b446a0efc mctx: refactor so that contexts no longer carry mutable data
This change required refactoring nearly every package in this project,
but it does a lot to simplify mctx and make other code using it easier
to think about.

Other code, such as mlog and mcfg, had to be slightly modified for this
change to work as well.
2019-02-07 19:42:12 -05:00

75 lines
1.9 KiB
Go

package mcfg
import (
"os"
"strings"
"github.com/mediocregopher/mediocre-go-lib/mctx"
"github.com/mediocregopher/mediocre-go-lib/merr"
)
// SourceEnv is a Source which will parse configuration from the process
// environment.
//
// Possible Env options are generated by joining a Param's Path and Name with
// underscores and making all characters uppercase, as well as changing all
// dashes to underscores.
//
// ctx := mctx.New()
// ctx = mctx.ChildOf(ctx, "foo")
// ctx = mctx.ChildOf(ctx, "bar")
// addr := mcfg.String(ctx, "srv-addr", "", "Some address")
// // the Env option to fill addr will be "FOO_BAR_SRV_ADDR"
//
type SourceEnv struct {
// In the format key=value. Defaults to os.Environ() if nil.
Env []string
// If set then all expected Env options must be prefixed with this string,
// which will be uppercased and have dashes replaced with underscores like
// all the other parts of the option names.
Prefix string
}
func (env SourceEnv) expectedName(path []string, name string) string {
out := strings.Join(append(path, name), "_")
if env.Prefix != "" {
out = env.Prefix + "_" + out
}
out = strings.Replace(out, "-", "_", -1)
out = strings.ToUpper(out)
return out
}
// Parse implements the method for the Source interface
func (env SourceEnv) Parse(params []Param) ([]ParamValue, error) {
kvs := env.Env
if kvs == nil {
kvs = os.Environ()
}
pM := map[string]Param{}
for _, p := range params {
name := env.expectedName(mctx.Path(p.Context), p.Name)
pM[name] = p
}
pvs := make([]ParamValue, 0, len(kvs))
for _, kv := range kvs {
split := strings.SplitN(kv, "=", 2)
if len(split) != 2 {
return nil, merr.New("malformed environment key/value pair", "kv", kv)
}
k, v := split[0], split[1]
if p, ok := pM[k]; ok {
pvs = append(pvs, ParamValue{
Name: p.Name,
Path: mctx.Path(p.Context),
Value: p.fuzzyParse(v),
})
}
}
return pvs, nil
}