/
template.go
88 lines (74 loc) · 1.91 KB
/
template.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
package plugin
import (
"encoding/json"
"reflect"
"strings"
"github.com/iancoleman/strcase"
"github.com/mitchellh/mapstructure"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"github.com/hashicorp/waypoint-plugin-sdk/component"
)
// templateData returns the template data for a result object. If v
// implements component.Template that value is used. Otherwise, we automatically
// infer the fields based on the exported fields of the struct.
func templateData(v interface{}) ([]byte, error) {
// Determine our data
var data map[string]interface{}
if tpl, ok := v.(component.Template); ok {
data = tpl.TemplateData()
} else {
data = templateDataFromConfig(v)
}
// If empty we don't do anything
if len(data) == 0 {
return nil, nil
}
// Encode as JSON
encoded, err := json.Marshal(data)
if err != nil {
return nil, status.Errorf(codes.Aborted,
"failed to JSON encode result template data: %s", err)
}
return encoded, nil
}
func templateDataFromConfig(v interface{}) map[string]interface{} {
var result map[string]interface{}
dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
Result: &result,
DecodeHook: func(srcT, dstT reflect.Type, raw interface{}) (interface{}, error) {
for srcT.Kind() == reflect.Ptr {
srcT = srcT.Elem()
}
if srcT.Kind() != reflect.Struct {
return raw, nil
}
val := reflect.ValueOf(raw)
for val.Kind() == reflect.Ptr {
val = val.Elem()
}
m := map[string]interface{}{}
for i := 0; i < srcT.NumField(); i++ {
sf := srcT.Field(i)
if sf.PkgPath != "" {
// ignore unexported fields
continue
}
if strings.HasPrefix(sf.Name, "XXX_") {
// ignore proto internals
continue
}
name := strcase.ToSnake(sf.Name)
m[name] = val.Field(i).Interface()
}
return m, nil
},
})
if err != nil {
panic(err)
}
if err := dec.Decode(v); err != nil {
panic(err)
}
return result
}