-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathhelp_config.go
204 lines (171 loc) · 4.02 KB
/
help_config.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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
package baker
import (
"fmt"
"reflect"
)
type baseDoc struct {
name string // component name
help string // general help string
keys []helpConfigKey // configuration keys
}
type inputDoc struct{ baseDoc }
type filterDoc struct{ baseDoc }
type uploadDoc struct{ baseDoc }
type outputDoc struct {
baseDoc
raw bool // raw output?
}
type metricsDoc struct {
name string // component name
keys []helpConfigKey // configuration keys
}
func newInputDoc(desc InputDesc) (inputDoc, error) {
doc := inputDoc{
baseDoc{
name: desc.Name,
help: desc.Help,
},
}
var err error
doc.keys, err = configKeysFromStruct(desc.Config)
if err != nil {
return doc, fmt.Errorf("input %q: %v", desc.Name, err)
}
return doc, nil
}
func newFilterDoc(desc FilterDesc) (filterDoc, error) {
doc := filterDoc{
baseDoc{
name: desc.Name,
help: desc.Help,
},
}
var err error
doc.keys, err = configKeysFromStruct(desc.Config)
if err != nil {
return doc, fmt.Errorf("filter %q: %v", desc.Name, err)
}
return doc, nil
}
func newOutputDoc(desc OutputDesc) (outputDoc, error) {
doc := outputDoc{
raw: desc.Raw,
baseDoc: baseDoc{
name: desc.Name,
help: desc.Help,
},
}
var err error
doc.keys, err = configKeysFromStruct(desc.Config)
if err != nil {
return doc, fmt.Errorf("output %q: %v", desc.Name, err)
}
return doc, nil
}
func newUploadDoc(desc UploadDesc) (uploadDoc, error) {
doc := uploadDoc{
baseDoc{
name: desc.Name,
help: desc.Help,
},
}
var err error
doc.keys, err = configKeysFromStruct(desc.Config)
if err != nil {
return doc, fmt.Errorf("upload %q: %v", desc.Name, err)
}
return doc, nil
}
func newMetricsDoc(desc MetricsDesc) (metricsDoc, error) {
doc := metricsDoc{
name: desc.Name,
}
var err error
doc.keys, err = configKeysFromStruct(desc.Config)
if err != nil {
return doc, fmt.Errorf("metrics %q: %v", desc.Name, err)
}
return doc, nil
}
type helpConfigKey struct {
name string // config key name
typ string // config key type
def string // default value
required bool
desc string
}
func configKeysFromStruct(cfg interface{}) ([]helpConfigKey, error) {
var keys []helpConfigKey
tf := reflect.TypeOf(cfg).Elem()
for i := 0; i < tf.NumField(); i++ {
f := tf.Field(i)
// skip unexported fields
if f.PkgPath != "" && !f.Anonymous {
continue
}
key, err := newHelpConfigKeyFromField(f)
if err != nil {
return nil, fmt.Errorf("error at exported key %d: %v", i, err)
}
keys = append(keys, key)
}
return keys, nil
}
func newHelpConfigKeyFromField(f reflect.StructField) (helpConfigKey, error) {
h := helpConfigKey{
name: f.Name,
desc: f.Tag.Get("help"),
def: f.Tag.Get("default"),
required: f.Tag.Get("required") == "true",
}
switch f.Type.Kind() {
case reflect.Int:
h.typ = "int"
case reflect.String:
h.typ = "string"
h.def = `"` + h.def + `"`
case reflect.Slice:
switch f.Type.Elem().Kind() {
case reflect.String:
h.typ = "array of strings"
if h.def == "" {
h.def = "[]"
}
case reflect.Int:
h.typ = "array of ints"
default:
return h, fmt.Errorf("config key %q: unsupported type array of %s", f.Name, f.Type.Elem())
}
case reflect.Int64:
if f.Type.Name() == "Duration" {
h.typ = "duration"
} else {
h.typ = "int"
}
case reflect.Bool:
h.typ = "bool"
case reflect.Map:
switch f.Type.Key().Kind() {
case reflect.String:
switch f.Type.Elem().Kind() {
case reflect.String:
h.typ = "map of strings to strings"
case reflect.Int:
h.typ = "map of strings to ints"
default:
return h, fmt.Errorf("config key %q: unsupported type table of %s", f.Name, f.Type.Elem())
}
default:
return h, fmt.Errorf("config key %q: unsupported map with key type %s", f.Name, f.Type.Key())
}
default:
// Handle other accepted types here
switch f.Type.Name() {
case "SizeBytes":
h.typ = "bytes as int or string with SI or IEC unit"
default:
return h, fmt.Errorf("config key %q: unsupported type %s", f.Name, f.Type)
}
}
return h, nil
}