-
Notifications
You must be signed in to change notification settings - Fork 1
/
heredoc_attribute.go
128 lines (111 loc) · 4.09 KB
/
heredoc_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
package tfplanparse
import (
"fmt"
"strings"
)
type HeredocAttributeChange struct {
Name string
Before []string
After []string
UpdateType UpdateType
}
var _ attributeChange = &HeredocAttributeChange{}
// IsHeredocAttributeChangeLine 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 "<<".
func IsHeredocAttributeChangeLine(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, "~")
// The only permitted heredoc string is <<~EOT
// Ref: https://github.com/hashicorp/terraform/blob/6a126df0c601ab23689171506bfc1386fea4c96c/command/format/diff.go#L838
isHeredoc := strings.HasPrefix(attribute[1], "<<~EOT")
return validPrefix && isHeredoc && !IsResourceChangeLine(line)
}
// IsHeredocAttributeTerminator returns true if the line is "EOT"
// EOT is the only possible terminator for the heredoc
// Ref: https://github.com/hashicorp/terraform/blob/6a126df0c601ab23689171506bfc1386fea4c96c/command/format/diff.go#L880
func IsHeredocAttributeTerminator(line string) bool {
return strings.TrimSuffix(strings.TrimSpace(line), " -> null") == "EOT"
}
// NewHeredocAttributeChangeFromLine initializes a HeredocAttributeChange from a line containing a heredoc change
// It expects a line that passes the IsHeredocAttributeChangeLine check
func NewHeredocAttributeChangeFromLine(line string) (*HeredocAttributeChange, error) {
line = strings.TrimSpace(line)
if !IsHeredocAttributeChangeLine(line) {
return nil, fmt.Errorf("%s is not a valid line to initialize a HeredocAttributeChange", line)
}
attribute := strings.SplitN(removeChangeTypeCharacters(line), ATTRIBUTE_DEFINITON_DELIMITER, 2)
if strings.HasPrefix(line, "+") {
// add
return &HeredocAttributeChange{
Name: dequote(strings.TrimSpace(attribute[0])),
Before: []string{},
After: []string{},
UpdateType: NewResource,
}, nil
} else if strings.HasPrefix(line, "-") {
// destroy
return &HeredocAttributeChange{
Name: dequote(strings.TrimSpace(attribute[0])),
Before: []string{},
After: []string{},
UpdateType: DestroyResource,
}, nil
} else if strings.HasPrefix(line, "~") {
// replace
updateType := UpdateInPlaceResource
if strings.HasSuffix(attribute[1], " # forces replacement") {
updateType = ForceReplaceResource
}
return &HeredocAttributeChange{
Name: dequote(strings.TrimSpace(attribute[0])),
Before: []string{},
After: []string{},
UpdateType: updateType,
}, nil
} else {
return nil, fmt.Errorf("unrecognized line pattern")
}
}
func (h *HeredocAttributeChange) AddLineToContent(line string) {
switch h.UpdateType {
case NewResource:
h.After = append(h.After, strings.TrimPrefix(line, "+ "))
case DestroyResource:
h.Before = append(h.Before, strings.TrimPrefix(line, "- "))
default:
// replace
// TODO: remove ANSI coded - or + only
h.Before = append(h.Before, line)
h.After = append(h.After, line)
}
}
// GetName returns the name of the attribute
func (h *HeredocAttributeChange) GetName() string {
return h.Name
}
// GetUpdateType returns the UpdateType of the attribute
func (h *HeredocAttributeChange) GetUpdateType() UpdateType {
return h.UpdateType
}
// IsSensitive returns true if the attribute contains a sensitive value
func (h *HeredocAttributeChange) IsSensitive() bool {
return false
}
// IsComputed returns true if the attribute contains a computed value
func (h *HeredocAttributeChange) IsComputed() bool {
return false
}
// IsNoOp returns true if the attribute has not changed
func (h *HeredocAttributeChange) IsNoOp() bool {
return h.UpdateType == NoOpResource
}
func (h *HeredocAttributeChange) GetBefore(opts ...GetBeforeAfterOptions) interface{} {
return strings.Join(h.Before, "\n")
}
func (h *HeredocAttributeChange) GetAfter(opts ...GetBeforeAfterOptions) interface{} {
return strings.Join(h.After, "\n")
}