-
Notifications
You must be signed in to change notification settings - Fork 523
/
resource_data.go
144 lines (118 loc) 路 4.12 KB
/
resource_data.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
package schema
import (
"encoding/json"
"strings"
"github.com/awslabs/goformation/v7/cloudformation"
"github.com/tidwall/gjson"
)
type ResourceData struct {
Type string
ProviderName string
Address string
Tags *map[string]string
RawValues gjson.Result
ReferencesMap map[string][]*ResourceData
CFResource cloudformation.Resource
UsageData *UsageData
Metadata map[string]gjson.Result
}
func NewResourceData(resourceType string, providerName string, address string, tags *map[string]string, rawValues gjson.Result) *ResourceData {
return &ResourceData{
Type: resourceType,
ProviderName: providerName,
Address: address,
Tags: tags,
RawValues: rawValues,
ReferencesMap: make(map[string][]*ResourceData),
CFResource: nil,
}
}
func NewCFResourceData(resourceType string, providerName string, address string, tags *map[string]string, cfResource cloudformation.Resource) *ResourceData {
return &ResourceData{
Type: resourceType,
ProviderName: providerName,
Address: address,
Tags: tags,
RawValues: gjson.Result{},
ReferencesMap: make(map[string][]*ResourceData),
CFResource: cfResource,
}
}
func (d *ResourceData) Get(key string) gjson.Result {
return gjson.Parse(strings.Clone(d.RawValues.Get(key).Raw))
}
// GetStringOrDefault returns the value of key within ResourceData as a string.
// If the retrieved value is not set GetStringOrDefault will return def.
func (d *ResourceData) GetStringOrDefault(key, def string) string {
if !d.IsEmpty(key) {
return strings.Clone(d.RawValues.Get(key).String())
}
return def
}
// GetInt64OrDefault returns the value of key within ResourceData as an int64.
// If the retrieved value is not set GetInt64OrDefault will return def.
func (d *ResourceData) GetInt64OrDefault(key string, def int64) int64 {
if !d.IsEmpty(key) {
return d.RawValues.Get(key).Int()
}
return def
}
// GetFloat64OrDefault returns the value of key within ResourceData as a float64.
// If the retrieved value is not set GetFloat64OrDefault will return def.
func (d *ResourceData) GetFloat64OrDefault(key string, def float64) float64 {
if !d.IsEmpty(key) {
return d.RawValues.Get(key).Float()
}
return def
}
func (d *ResourceData) GetBoolOrDefault(key string, def bool) bool {
if !d.IsEmpty(key) {
return d.RawValues.Get(key).Bool()
}
return def
}
// Return true if the key doesn't exist, is null, or is an empty string.
// Needed because gjson.Exists returns true as long as a key exists, even if it's empty or null.
func (d *ResourceData) IsEmpty(key string) bool {
g := d.RawValues.Get(key)
return g.Type == gjson.Null || len(g.Raw) == 0 || g.Raw == "\"\"" || emptyObjectOrArray(g)
}
func (d *ResourceData) References(keys ...string) []*ResourceData {
var data []*ResourceData
for _, key := range keys {
data = append(data, d.ReferencesMap[key]...)
}
return data
}
func (d *ResourceData) AddReference(k string, reference *ResourceData, reverseRefAttrs []string) {
// Perf/memory leak: Copy gjson string slices that may be returned so we don't prevent
// the entire underlying parsed json from being garbage collected.
key := strings.Clone(k)
if _, ok := d.ReferencesMap[key]; !ok {
d.ReferencesMap[key] = make([]*ResourceData, 0)
}
d.ReferencesMap[key] = append(d.ReferencesMap[key], reference)
// add any reverse references
reverseRefKey := d.Type + "." + key
for _, attr := range reverseRefAttrs {
if attr == reverseRefKey {
if _, ok := reference.ReferencesMap[reverseRefKey]; !ok {
reference.ReferencesMap[reverseRefKey] = make([]*ResourceData, 0)
}
reference.ReferencesMap[reverseRefKey] = append(reference.ReferencesMap[reverseRefKey], d)
}
}
}
func (d *ResourceData) Set(key string, value interface{}) {
d.RawValues = AddRawValue(d.RawValues, key, value)
}
func AddRawValue(r gjson.Result, key string, v interface{}) gjson.Result {
j := make(map[string]interface{})
_ = json.Unmarshal([]byte(r.Raw), &j) // TODO: unhandled error
if j == nil {
j = make(map[string]interface{})
}
j[key] = v
mj, _ := json.Marshal(j) // TODO: unhandled error
return gjson.ParseBytes(mj)
}