github.com/whiteboxio/flow@v0.0.3-0.20190918184116-508d75d68a2c/pkg/cfg/env_provider.go (about) 1 package cfg 2 3 import ( 4 "os" 5 "strings" 6 7 "github.com/awesome-flow/flow/pkg/types" 8 ) 9 10 // Redefined in tests 11 var envVars = func() []string { 12 return os.Environ() 13 } 14 15 func canonise(key string) string { 16 k := strings.Replace(key, "_", ".", -1) 17 k = strings.Replace(k, "..", "_", -1) 18 return strings.ToLower(k) 19 } 20 21 // EnvProvider reads special FLOW_ preffixed environment variables. 22 // The contract is: 23 // * Underscores are being transformed to dots in key part (before the first =). 24 // * There must be exactly 1 `=` sign. 25 // * Double underscores are converted to singulars and preserved with no dot-conversion. 26 type EnvProvider struct { 27 weight int 28 registry map[string]types.Value 29 ready chan struct{} 30 } 31 32 var _ Provider = (*EnvProvider)(nil) 33 34 // NewEnvProvider returns a new instance of EnvProvider. 35 func NewEnvProvider(repo *Repository, weight int) (*EnvProvider, error) { 36 prov := &EnvProvider{ 37 weight: weight, 38 ready: make(chan struct{}), 39 } 40 repo.RegisterProvider(prov) 41 42 return prov, nil 43 } 44 45 // Name returns provider name: env 46 func (ep *EnvProvider) Name() string { return "env" } 47 48 // Depends returns provider dependencies: default 49 func (ep *EnvProvider) Depends() []string { return []string{"default"} } 50 51 // Weight returns provider weight 52 func (ep *EnvProvider) Weight() int { return ep.weight } 53 54 // SetUp takes the list of env vars and canonizes them before registration in 55 // repo. Env vars are expected to be in form FLOW_<K>=<v>. FLOW_ preffix 56 // would be cleared out. 57 func (ep *EnvProvider) SetUp(repo *Repository) error { 58 defer close(ep.ready) 59 registry := make(map[string]types.Value) 60 var k string 61 var v interface{} 62 63 for _, kv := range envVars() { 64 if !strings.HasPrefix(kv, "FLOW_") { 65 continue 66 } 67 // Clear out "FLOW_" 68 kv = kv[5:] 69 if ix := strings.Index(kv, "="); ix != -1 { 70 k, v = kv[:ix], kv[ix+1:] 71 } else { 72 k, v = kv, true 73 } 74 k = canonise(k) 75 registry[k] = v 76 if repo != nil { 77 if err := repo.RegisterKey(types.NewKey(k), ep); err != nil { 78 return err 79 } 80 } 81 } 82 83 ep.registry = registry 84 85 return nil 86 } 87 88 // TearDown is a no-op operation for CliProvider 89 func (ep *EnvProvider) TearDown(_ *Repository) error { return nil } 90 91 // Get is the primary method to fetch values from the provider registry. 92 func (ep *EnvProvider) Get(key types.Key) (*types.KeyValue, bool) { 93 <-ep.ready 94 if val, ok := ep.registry[key.String()]; ok { 95 return &types.KeyValue{Key: key, Value: val}, ok 96 } 97 return nil, false 98 }