-
Notifications
You must be signed in to change notification settings - Fork 1
/
array_attribute.go
140 lines (121 loc) · 4.07 KB
/
array_attribute.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
package tfplanparse
import (
"fmt"
"strings"
)
// TODO: array attributes can be any attribute change, an array of arrays, or array of maps
// Type of the attribute can vary, but they're all the same
// Should use an interface
type ArrayAttributeChange struct {
Name string
AttributeChanges []attributeChange
UpdateType UpdateType
}
var _ attributeChange = &ArrayAttributeChange{}
// IsArrayAttributeChangeLine returns true if the line is a valid attribute change
// This requires the line to start with "+", "-" or "~", not be followed with "resource" or "data", and ends with "[".
func IsArrayAttributeChangeLine(line string) bool {
line = strings.TrimSpace(line)
// validPrefix := strings.HasPrefix(line, "+") || strings.HasPrefix(line, "-") || strings.HasPrefix(line, "~")
validSuffix := strings.HasSuffix(line, "[") || IsOneLineEmptyArrayAttribute(line)
return validSuffix && !IsResourceChangeLine(line)
}
// IsArrayAttributeTerminator returns true if the line is "]" or "] -> null"
func IsArrayAttributeTerminator(line string) bool {
return strings.TrimSuffix(strings.TrimSpace(line), " -> null") == "]"
}
// IsOneLineEmptyArrayAttribute returns true if the line ends with a "[]"
func IsOneLineEmptyArrayAttribute(line string) bool {
return strings.HasSuffix(line, "[]")
}
// NewArrayAttributeChangeFromLine initializes an ArrayAttributeChange from a line containing an array attribute change
// It expects a line that passes the IsArrayAttributeChangeLine check
func NewArrayAttributeChangeFromLine(line string) (*ArrayAttributeChange, error) {
line = strings.TrimSpace(line)
if !IsArrayAttributeChangeLine(line) {
return nil, fmt.Errorf("%s is not a valid line to initialize a ArrayAttributeChange", line)
}
attributeName := getMultiLineAttributeName(line)
if strings.HasPrefix(line, "+") {
// add
return &ArrayAttributeChange{
Name: attributeName,
UpdateType: NewResource,
}, nil
} else if strings.HasPrefix(line, "-") {
// destroy
return &ArrayAttributeChange{
Name: attributeName,
UpdateType: DestroyResource,
}, nil
} else if strings.HasPrefix(line, "~") {
// replace
return &ArrayAttributeChange{
Name: attributeName,
UpdateType: UpdateInPlaceResource,
}, nil
} else {
return &ArrayAttributeChange{
Name: attributeName,
UpdateType: NoOpResource,
}, nil
}
}
// GetName returns the name of the attribute
func (a *ArrayAttributeChange) GetName() string {
return a.Name
}
// GetUpdateType returns the UpdateType of the attribute
func (a *ArrayAttributeChange) GetUpdateType() UpdateType {
return a.UpdateType
}
// IsSensitive returns true if the attribute contains a sensitive value
func (a *ArrayAttributeChange) IsSensitive() bool {
// return m.OldValue == SENSITIVE_VALUE || m.NewValue == SENSITIVE_VALUE
return false
}
// IsComputed returns true if the attribute contains a computed value
func (a *ArrayAttributeChange) IsComputed() bool {
// return m.OldValue == COMPUTED_VALUE || m.NewValue == COMPUTED_VALUE
return false
}
// IsNoOp returns true if the attribute has not changed
func (a *ArrayAttributeChange) IsNoOp() bool {
return a.UpdateType == NoOpResource
}
func (a *ArrayAttributeChange) GetBefore(opts ...GetBeforeAfterOptions) interface{} {
// TODO: ensure the result types are all the same
// Currently it is assumed that all changes added are the same type...
// This is handled correctly in parse, but we should handle it here
result := []interface{}{}
attrs:
for _, ac := range a.AttributeChanges {
if ac.GetUpdateType() == NewResource {
continue attrs
}
for _, opt := range opts {
if opt(ac) {
continue attrs
}
}
result = append(result, ac.GetBefore(opts...))
}
return result
}
func (a *ArrayAttributeChange) GetAfter(opts ...GetBeforeAfterOptions) interface{} {
// TODO: same as above
result := []interface{}{}
attrs:
for _, ac := range a.AttributeChanges {
if ac.GetUpdateType() == DestroyResource {
continue attrs
}
for _, opt := range opts {
if opt(ac) {
continue attrs
}
}
result = append(result, ac.GetAfter(opts...))
}
return result
}