-
Notifications
You must be signed in to change notification settings - Fork 1
/
jsonencode.go
138 lines (118 loc) · 3.85 KB
/
jsonencode.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
package tfplanparse
import (
"fmt"
"strings"
)
type JSONEncodeAttributeChange struct {
Name string
AttributeChanges []attributeChange
UpdateType UpdateType
}
var _ attributeChange = &JSONEncodeAttributeChange{}
// IsJSONEncodeAttributeChangeLine returns true if the line is a valid attribute change
// This requires the line to start with "+", "-" or "~", delimited with a space, and the value to start with "jsonencode(".
func IsJSONEncodeAttributeChangeLine(line string) bool {
line = strings.TrimSpace(line)
attribute := strings.SplitN(line, ATTRIBUTE_DEFINITON_DELIMITER, 2)
if len(attribute) != 2 {
return false
}
validPrefix := strings.HasPrefix(line, "+") || strings.HasPrefix(line, "-") || strings.HasPrefix(line, "~")
isJSONEncode := strings.HasPrefix(attribute[1], "jsonencode(")
return validPrefix && isJSONEncode && !IsResourceChangeLine(line)
}
// IsJSONEncodeAttributeTerminator returns true if the line is ")"
// TODO: verify this
func IsJSONEncodeAttributeTerminator(line string) bool {
return strings.TrimSuffix(strings.TrimSpace(line), " -> null") == ")"
}
// NewJSONEncodeAttributeChangeFromLine initializes a JSONEncodeAttributeChange from a line containing a JSONEncode change
// It expects a line that passes the IsJSONEncodeAttributeChangeLine check
func NewJSONEncodeAttributeChangeFromLine(line string) (*JSONEncodeAttributeChange, error) {
line = strings.TrimSpace(line)
if !IsJSONEncodeAttributeChangeLine(line) {
return nil, fmt.Errorf("%s is not a valid line to initialize a JSONEncodeAttributeChange", line)
}
attribute := strings.SplitN(removeChangeTypeCharacters(line), ATTRIBUTE_DEFINITON_DELIMITER, 2)
if strings.HasPrefix(line, "+") {
// add
return &JSONEncodeAttributeChange{
Name: dequote(strings.TrimSpace(attribute[0])),
UpdateType: NewResource,
}, nil
} else if strings.HasPrefix(line, "-") {
// destroy
return &JSONEncodeAttributeChange{
Name: dequote(strings.TrimSpace(attribute[0])),
UpdateType: DestroyResource,
}, nil
} else if strings.HasPrefix(line, "~") {
// replace
updateType := UpdateInPlaceResource
if strings.HasSuffix(attribute[1], " # forces replacement") {
updateType = ForceReplaceResource
}
return &JSONEncodeAttributeChange{
Name: dequote(strings.TrimSpace(attribute[0])),
UpdateType: updateType,
}, nil
} else {
return nil, fmt.Errorf("unrecognized line pattern")
}
}
// GetName returns the name of the attribute
func (j *JSONEncodeAttributeChange) GetName() string {
return j.Name
}
// GetUpdateType returns the UpdateType of the attribute
func (j *JSONEncodeAttributeChange) GetUpdateType() UpdateType {
return j.UpdateType
}
// IsSensitive returns true if the attribute contains a sensitive value
func (j *JSONEncodeAttributeChange) IsSensitive() bool {
for _, ac := range j.AttributeChanges {
if ac.IsSensitive() {
return true
}
}
return false
}
// IsComputed returns true if the attribute contains a computed value
func (j *JSONEncodeAttributeChange) IsComputed() bool {
for _, ac := range j.AttributeChanges {
if ac.IsComputed() {
return true
}
}
return false
}
// IsNoOp returns true if the attribute has not changed
func (j *JSONEncodeAttributeChange) IsNoOp() bool {
return j.UpdateType == NoOpResource
}
func (j *JSONEncodeAttributeChange) GetBefore(opts ...GetBeforeAfterOptions) interface{} {
result := map[string]interface{}{}
attrs:
for _, a := range j.AttributeChanges {
for _, opt := range opts {
if opt(a) {
continue attrs
}
}
result[a.GetName()] = a.GetBefore(opts...)
}
return result
}
func (j *JSONEncodeAttributeChange) GetAfter(opts ...GetBeforeAfterOptions) interface{} {
result := map[string]interface{}{}
attrs:
for _, a := range j.AttributeChanges {
for _, opt := range opts {
if opt(a) {
continue attrs
}
}
result[a.GetName()] = a.GetAfter(opts...)
}
return result
}