-
Notifications
You must be signed in to change notification settings - Fork 255
/
attributes.go
65 lines (54 loc) · 1.67 KB
/
attributes.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
package modconfig
import (
"log"
"reflect"
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/turbot/go-kit/helpers"
"github.com/turbot/terraform-components/configs/configschema"
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/gocty"
)
// GetCtyTypes builds a map of cty types for all tagged properties.
// It is used to convert the struct to a cty value
func GetCtyTypes(item interface{}) map[string]cty.Type {
defer func() {
if r := recover(); r != nil {
log.Printf("[WARN] GetCtyTypes failed with panic: %v", r)
}
}()
var res = make(map[string]cty.Type)
t := reflect.TypeOf(helpers.DereferencePointer(item))
val := reflect.ValueOf(item)
if val.Type().Kind() == reflect.Ptr {
val = val.Elem()
}
for i := 0; i < val.NumField(); i++ {
structField := t.Field(i)
attribute, ok := structField.Tag.Lookup("cty")
if ok && attribute != "-" {
valField := val.Field(i)
// get cty type
ctyType, err := gocty.ImpliedType(valField.Interface())
if err != nil {
panic(err)
}
res[attribute] = ctyType
}
}
return res
}
// GetCtyValue converts the item into a cty value
func GetCtyValue(item interface{}) (cty.Value, error) {
// TODO [node_reuse] look at merging base struct schemas
// build the block schema
var block = configschema.Block{Attributes: make(map[string]*configschema.Attribute)}
// get the hcl attributes - these include the cty type
for attribute, ctyType := range GetCtyTypes(item) {
// TODO how to determine optional?
block.Attributes[attribute] = &configschema.Attribute{Optional: true, Type: ctyType}
}
// get cty spec
spec := block.DecoderSpec()
ty := hcldec.ImpliedType(spec)
return gocty.ToCtyValue(item, ty)
}