Repository navigation
Expand file tree
/
Copy pathresource_builder.go
More file actions
129 lines (110 loc) · 3.3 KB
/
Copy pathresource_builder.go
File metadata and controls
129 lines (110 loc) · 3.3 KB
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
package diff
import (
"strings"
"github.com/hashicorp/terraform/flatmap"
"github.com/hashicorp/terraform/terraform"
)
// AttrType is an enum that tells the ResourceBuilder what type of attribute
// an attribute is, affecting the overall diff output.
//
// The valid values are:
//
// * AttrTypeCreate - This attribute can only be set or updated on create.
// This means that if this attribute is changed, it will require a new
// resource to be created if it is already created.
//
// * AttrTypeUpdate - This attribute can be set at create time or updated
// in-place. Changing this attribute does not require a new resource.
//
type AttrType byte
const (
AttrTypeUnknown AttrType = iota
AttrTypeCreate
AttrTypeUpdate
)
// ResourceBuilder is a helper that knows about how a single resource
// changes and how those changes affect the diff.
type ResourceBuilder struct {
// Attrs are the mapping of attributes that can be set from the
// configuration, and the affect they have. See the documentation for
// AttrType for more info.
Attrs map[string]AttrType
// ComputedAttrs are the attributes that are computed at
// resource creation time.
ComputedAttrs []string
}
// Diff returns the ResourceDiff for a resource given its state and
// configuration.
func (b *ResourceBuilder) Diff(
s *terraform.ResourceState,
c *terraform.ResourceConfig) (*terraform.ResourceDiff, error) {
attrs := make(map[string]*terraform.ResourceAttrDiff)
// We require a new resource if the ID is empty. Or, later, we set
// this to true if any configuration changed that triggers a new resource.
requiresNew := s.ID == ""
// Flatten the raw and processed configuration
flatRaw := flatmap.Flatten(c.Raw)
flatConfig := flatmap.Flatten(c.Config)
for k, v := range flatRaw {
// Make sure this is an attribute that actually affects
// the diff in some way.
var attr AttrType
for ak, at := range b.Attrs {
if strings.HasPrefix(k, ak) {
attr = at
break
}
}
if attr == AttrTypeUnknown {
continue
}
// If this key is in the cleaned config, then use that value
// because it'll have its variables properly interpolated
if cleanV, ok := flatConfig[k]; ok {
v = cleanV
}
oldV, ok := s.Attributes[k]
// If there is an old value and they're the same, no change
if ok && oldV == v {
continue
}
// Record the change
attrs[k] = &terraform.ResourceAttrDiff{
Old: oldV,
New: v,
Type: terraform.DiffAttrInput,
}
// If this requires a new resource, record that and flag our
// boolean.
if attr == AttrTypeCreate {
attrs[k].RequiresNew = true
requiresNew = true
}
}
// If we require a new resource, then process all the attributes
// that will be changing due to the creation of the resource.
if requiresNew {
for _, k := range b.ComputedAttrs {
old := s.Attributes[k]
attrs[k] = &terraform.ResourceAttrDiff{
Old: old,
NewComputed: true,
Type: terraform.DiffAttrOutput,
}
}
// The ID will change
attrs["id"] = &terraform.ResourceAttrDiff{
Old: s.ID,
NewComputed: true,
Type: terraform.DiffAttrOutput,
}
}
// Build our resulting diff if we had attributes change
var result *terraform.ResourceDiff
if len(attrs) > 0 {
result = &terraform.ResourceDiff{
Attributes: attrs,
}
}
return result, nil
}