-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathenv.go
112 lines (104 loc) · 2.86 KB
/
env.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package xconf
import (
"flag"
"fmt"
"regexp"
"strings"
)
const defaultEnvKeyForFiles = "sys_config_center_service_files"
// LookupEnv Env value provider func.
// 默认提供不缺分大小写的env绑定模式
var LookupEnv = LookupEnvCaseInsensitive
// envBindToFlags 将environ绑定到FlagSet格式,字段映射由mapping指定
// mapping : env key upper => flag name,默认提供的是不区分env key 大小写的匹配方式
func envBindToFlags(environ []string, mapping map[string]string) []string {
var flags []string
env := make(map[string]string)
for _, s := range environ {
i := strings.Index(s, "=")
if i < 1 {
continue
}
env[s[0:i]] = s[i+1:]
}
for k, v := range env {
flagName := mapping[strings.ToUpper(k)]
if flagName == "" {
continue
}
flags = append(flags, fmt.Sprintf("-%s=%s", flagName, v))
}
return flags
}
var _ = flagBindEnv
func flagBindEnv(fs *flag.FlagSet, environ []string, mapping map[string]string) error {
env := make(map[string]string)
for _, s := range environ {
i := strings.Index(s, "=")
if i < 1 {
continue
}
env[s[0:i]] = s[i+1:]
}
for k, v := range env {
flagName := mapping[strings.ToUpper(k)]
if flagName == "" {
continue
}
flagInst := fs.Lookup(flagName)
if flagInst == nil {
continue
}
err := flagInst.Value.Set(v)
if err != nil {
return fmt.Errorf("got error while bind env:%s val:%s to flag,err :%w", k, v, err)
}
}
return nil
}
// parse env value, allow:
//
// only key - "${SHELL}"
// with default - "${NotExist|defValue}"
// multi key - "${GOPATH}/${APP_ENV | prod}/dir"
//
// Notice:
//
// must add "?" - To ensure that there is no greedy match
// var envRegex = regexp.MustCompile(`\${[\w-| ]+}`)
var envRegex = regexp.MustCompile(`\${.+?}`)
// ParseEnvValue parse ENV var value from input string, support default value.
func ParseEnvValue(val string) (newVal string, err error) {
if !strings.Contains(val, "${") {
return val, nil
}
var name, def string
var nameNoDefaultNoFound []string
newVal = envRegex.ReplaceAllStringFunc(val, func(eVar string) string {
// eVar like "${NotExist|defValue}", first remove "${" and "}", then split it
ss := strings.SplitN(eVar[2:len(eVar)-1], "|", 2)
// with default value. ${NotExist|defValue}
hasDefault := false
if len(ss) == 2 {
name, def = strings.TrimSpace(ss[0]), strings.TrimSpace(ss[1])
hasDefault = true
} else {
def = eVar // use raw value
name = strings.TrimSpace(ss[0])
}
// get ENV value by name
eVal, ok := LookupEnv(name)
if eVal == "" {
if !ok && !hasDefault {
// 指定的key不存在且没有显示提供默认值
nameNoDefaultNoFound = append(nameNoDefaultNoFound, name)
}
eVal = def
}
return eVal
})
if len(nameNoDefaultNoFound) == 0 {
return newVal, nil
}
return newVal, fmt.Errorf("EnvBind lost env and default for key:%s", strings.Join(nameNoDefaultNoFound, ","))
}