-
Notifications
You must be signed in to change notification settings - Fork 18
/
docs.go
107 lines (97 loc) · 2.99 KB
/
docs.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
package helmchart
import (
"fmt"
"reflect"
"strings"
)
type HelmValue struct {
Key string
Type string
DefaultValue string
Description string
}
type HelmValues []HelmValue
func (v HelmValues) ToMarkdown() string {
result := new(strings.Builder)
fmt.Fprintln(result, "|Option|Type|Default Value|Description|")
fmt.Fprintln(result, "|------|----|-----------|-------------|")
for _, value := range v {
fmt.Fprintf(result, "|%s|%s|%s|%s|\n", value.Key, value.Type, value.DefaultValue, value.Description)
}
return result.String()
}
type addValue func(HelmValue)
func Doc(s interface{}) HelmValues {
var values []HelmValue
cfgT := reflect.ValueOf(s)
addValue := func(v HelmValue) { values = append(values, v) }
docReflect(addValue, nil, "", cfgT.Type(), cfgT)
return HelmValues(values)
}
func docReflect(addValue addValue, path []string, desc string, typ reflect.Type, val reflect.Value) {
switch typ.Kind() {
case reflect.Ptr:
var elemVal reflect.Value
if elemVal != val {
elemVal = val.Elem()
}
docReflect(addValue, path, desc, typ.Elem(), elemVal)
case reflect.Map:
if typ.Key().Kind() == reflect.String {
docReflect(addValue, append(path, "NAME"), desc, typ.Elem(), reflect.Value{})
if (val != reflect.Value{}) {
for _, k := range val.MapKeys() {
path = append(path, k.String())
defaultVal := val.MapIndex(k)
if typ.Elem().Kind() <= reflect.Float64 || typ.Elem().Kind() == reflect.String {
// primitve type, print it as default value
valStr := valToString(defaultVal)
addValue(HelmValue{Key: strings.Join(path, "."), Type: typ.Elem().Kind().String(), DefaultValue: valStr, Description: desc})
} else {
// non primitive type, decend
docReflect(addValue, path, desc, typ.Elem(), val.MapIndex(k))
}
}
}
}
case reflect.Slice:
lst := len(path) - 1
path[lst] = path[lst] + "[]"
docReflect(addValue, path, desc, typ.Elem(), reflect.Value{})
case reflect.Struct:
for i := 0; i < typ.NumField(); i++ {
field := typ.Field(i)
jsonTag := field.Tag.Get("json")
parts := strings.Split(jsonTag, ",")
jsonName := parts[0]
desc := field.Tag.Get("desc")
fieldPath := path
if jsonName != "" {
fieldPath = append(fieldPath, jsonName)
}
var fieldVal reflect.Value
if val != fieldVal {
fieldVal = val.Field(i)
}
docReflect(addValue, fieldPath, desc, field.Type, fieldVal)
}
default:
addValue(HelmValue{Key: strings.Join(path, "."), Type: typ.Kind().String(), DefaultValue: valToString(val), Description: desc})
}
}
func valToString(val reflect.Value) string {
valStr := ""
if val.IsValid() {
switch val.Kind() {
case reflect.Bool:
valStr = fmt.Sprint(val.Bool())
case reflect.String:
valStr = fmt.Sprint(val.String())
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
valStr = fmt.Sprint(val.Int())
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
valStr = fmt.Sprint(val.Uint())
}
}
return valStr
}