-
Notifications
You must be signed in to change notification settings - Fork 1
/
env.go
140 lines (123 loc) · 5.52 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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package agent
import (
"net/url"
"reflect"
"strconv"
"strings"
"time"
"github.com/sirupsen/logrus"
"github.com/datawire/dlib/derror"
"github.com/datawire/envconfig"
)
type Env struct {
LogLevel logrus.Level `env:"LOG_LEVEL, parser=log-level, default=info"`
AESSnapshotURL *url.URL `env:"AES_SNAPSHOT_URL, parser=absolute-URL, default=http://ambassador-admin:8005/snapshot-external"`
AESDiagnosticsURL *url.URL `env:"AES_DIAGNOSTICS_URL, parser=absolute-URL, default=http://ambassador-admin:8877/ambassador/v0/diag/?json=true"`
AESReportDiagnostics bool `env:"AES_REPORT_DIAGNOSTICS_TO_CLOUD, parser=bool, default=false"`
ScoutID string `env:"AMBASSADOR_SCOUT_ID, parser=string, default="`
ClusterID string `env:"AMBASSADOR_CLUSTER_ID, parser=string, defaultFrom=ScoutID"`
AmbassadorID string `env:"AMBASSADOR_ID, parser=string, default=default"`
AmbassadorAPIKey string `env:"CLOUD_CONNECT_TOKEN, parser=string"`
ConnAddress *ConnInfo `env:"RPC_CONNECTION_ADDRESS, parser=conn-info, default="`
// config map/secret information
// agent namespace is... the namespace the agent is running in.
// but more importantly, it's the namespace that the config resource lives in (which is
// either a ConfigMap or Secret)
AgentNamespace string `env:"AGENT_NAMESPACE, parser=string, default=ambassador"`
// Name of the k8s ConfigMap or Secret the CLOUD_CONNECT_TOKEN exists on. We're supporting
// both Secrets and ConfigMaps here because it is likely in an enterprise cluster, the RBAC
// for secrets is locked down to Ops folks only, and we want to make it easy for regular ol'
// engineers to give this whole service catalog thing a go
AgentConfigResourceName string `env:"AGENT_CONFIG_RESOURCE_NAME, parser=string, default="`
// Field selector for the k8s resources that the agent watches
AgentWatchFieldSelector string `env:"AGENT_WATCH_FIELD_SELECTOR, parser=string, default=metadata.namespace!=kube-system"`
MinReportPeriod time.Duration `env:"AGENT_REPORTING_PERIOD, parser=report-period,default="`
NamespacesToWatch []string `env:"NAMESPACES_TO_WATCH, parser=split-trim, default="`
RpcInterceptHeaderKey string `env:"RPC_INTERCEPT_HEADER_KEY, parser=string, default="`
RpcInterceptHeaderValue string `env:"RPC_INTERCEPT_HEADER_VALUE, parser=string, default="`
// ServerHost is the hostname for the gRPC server. Can be empty, in which case it defaults to localhost.
ServerHost string `env:"SERVER_HOST, parser=string, default="`
// ServerPort is the port tha the gRPC server is listening on.
ServerPort uint16 `env:"SERVER_PORT, parser=port-number"`
}
func fieldTypeHandlers() map[reflect.Type]envconfig.FieldTypeHandler {
fhs := envconfig.DefaultFieldTypeHandlers()
fp := fhs[reflect.TypeOf("")]
fp.Parsers["string"] = fp.Parsers["possibly-empty-string"]
fp = fhs[reflect.TypeOf(true)]
fp.Parsers["bool"] = fp.Parsers["strconv.ParseBool"]
fhs[reflect.TypeOf(logrus.Level(0))] = envconfig.FieldTypeHandler{
Parsers: map[string]func(string) (any, error){
"log-level": func(str string) (any, error) {
if str == "" {
return logrus.InfoLevel, nil
}
return logrus.ParseLevel(str)
},
},
Setter: func(dst reflect.Value, src interface{}) { dst.SetUint(uint64(src.(logrus.Level))) },
}
fhs[reflect.TypeOf(time.Duration(0))] = envconfig.FieldTypeHandler{
Parsers: map[string]func(string) (any, error){
"report-period": func(str string) (any, error) {
if str == "" {
return defaultMinReportPeriod, nil
}
reportPeriod, err := time.ParseDuration(str)
if err != nil {
return 0, err
}
return MaxDuration(defaultMinReportPeriod, reportPeriod), nil
},
},
Setter: func(dst reflect.Value, src interface{}) { dst.SetInt(int64(src.(time.Duration))) },
}
fhs[reflect.TypeOf([]string{})] = envconfig.FieldTypeHandler{
Parsers: map[string]func(string) (any, error){
"split-trim": func(str string) (any, error) { //nolint:unparam // API requirement
if len(str) == 0 {
return nil, nil
}
ss := strings.Split(str, " ")
for i, s := range ss {
ss[i] = strings.TrimSpace(s)
}
return ss, nil
},
},
Setter: func(dst reflect.Value, src interface{}) { dst.Set(reflect.ValueOf(src.([]string))) },
}
fhs[reflect.TypeOf(&ConnInfo{})] = envconfig.FieldTypeHandler{
Parsers: map[string]func(string) (any, error){
"conn-info": func(address string) (any, error) {
return connInfoFromAddress(address)
},
},
Setter: func(dst reflect.Value, src interface{}) { dst.Set(reflect.ValueOf(src.(*ConnInfo))) },
}
fhs[reflect.TypeOf(uint16(0))] = envconfig.FieldTypeHandler{
Parsers: map[string]func(string) (any, error){
"port-number": func(str string) (any, error) {
pn, err := strconv.ParseUint(str, 10, 16)
return uint16(pn), err
},
},
Setter: func(dst reflect.Value, src interface{}) { dst.SetUint(uint64(src.(uint16))) },
}
return fhs
}
func LoadEnv(lookupFunc func(string) (string, bool)) (*Env, error) {
env := Env{}
parser, err := envconfig.GenerateParser(reflect.TypeOf(env), fieldTypeHandlers())
if err != nil {
panic(err)
}
var errs derror.MultiError
warn, fatal := parser.ParseFromEnv(&env, lookupFunc)
errs = append(errs, warn...)
errs = append(errs, fatal...)
if len(errs) > 0 {
return nil, errs
}
return &env, nil
}