-
-
Notifications
You must be signed in to change notification settings - Fork 8
/
attrmap.go
152 lines (123 loc) · 4.51 KB
/
attrmap.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
145
146
147
148
149
150
151
152
package create
import (
"fmt"
"log"
"strconv"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)
// AttributeMap represents a map of Terraform resource attribute name to AWS API attribute name.
// Useful for SQS Queue or SNS Topic attribute handling.
type attributeInfo struct {
apiAttributeName string
tfType schema.ValueType
tfOptionalComputed bool
}
type AttributeMap map[string]attributeInfo
// AttrMap returns a new AttributeMap from the specified Terraform resource attribute name to AWS API attribute name map and resource schema.
func AttrMap(attrMap map[string]string, schemaMap map[string]*schema.Schema) AttributeMap {
attributeMap := make(AttributeMap)
for tfAttributeName, apiAttributeName := range attrMap {
if s, ok := schemaMap[tfAttributeName]; ok {
attributeInfo := attributeInfo{
apiAttributeName: apiAttributeName,
tfType: s.Type,
}
if s.Optional && s.Computed {
attributeInfo.tfOptionalComputed = true
}
attributeMap[tfAttributeName] = attributeInfo
} else {
log.Printf("[ERROR] Unknown attribute: %s", tfAttributeName)
}
}
return attributeMap
}
// ApiAttributesToResourceData sets Terraform ResourceData from a map of AWS API attributes.
func (m AttributeMap) ApiAttributesToResourceData(apiAttributes map[string]string, d *schema.ResourceData) error {
for tfAttributeName, attributeInfo := range m {
if v, ok := apiAttributes[attributeInfo.apiAttributeName]; ok {
var err error
var tfAttributeValue interface{}
switch t := attributeInfo.tfType; t {
case schema.TypeBool:
tfAttributeValue, err = strconv.ParseBool(v)
if err != nil {
return fmt.Errorf("error parsing %s value (%s) into boolean: %w", tfAttributeName, v, err)
}
case schema.TypeInt:
tfAttributeValue, err = strconv.Atoi(v)
if err != nil {
return fmt.Errorf("error parsing %s value (%s) into integer: %w", tfAttributeName, v, err)
}
case schema.TypeString:
tfAttributeValue = v
default:
return fmt.Errorf("attribute %s is of unsupported type: %d", tfAttributeName, t)
}
if err := d.Set(tfAttributeName, tfAttributeValue); err != nil {
return fmt.Errorf("error setting %s: %w", tfAttributeName, err)
}
} else {
d.Set(tfAttributeName, nil)
}
}
return nil
}
// ResourceDataToApiAttributesCreate returns a map of AWS API attributes from Terraform ResourceData.
// The API attributes map is suitable for resource create.
func (m AttributeMap) ResourceDataToApiAttributesCreate(d *schema.ResourceData) (map[string]string, error) {
apiAttributes := map[string]string{}
for tfAttributeName, attributeInfo := range m {
var apiAttributeValue string
switch v, t := d.Get(tfAttributeName), attributeInfo.tfType; t {
case schema.TypeBool:
if v := v.(bool); v {
apiAttributeValue = strconv.FormatBool(v)
}
case schema.TypeInt:
// On creation don't specify any zero Optional/Computed attribute integer values.
if v := v.(int); !attributeInfo.tfOptionalComputed || v != 0 {
apiAttributeValue = strconv.Itoa(v)
}
case schema.TypeString:
apiAttributeValue = v.(string)
default:
return nil, fmt.Errorf("attribute %s is of unsupported type: %d", tfAttributeName, t)
}
if apiAttributeValue != "" {
apiAttributes[attributeInfo.apiAttributeName] = apiAttributeValue
}
}
return apiAttributes, nil
}
// ResourceDataToApiAttributesUpdate returns a map of AWS API attributes from Terraform ResourceData.
// The API attributes map is suitable for resource update.
func (m AttributeMap) ResourceDataToApiAttributesUpdate(d *schema.ResourceData) (map[string]string, error) {
apiAttributes := map[string]string{}
for tfAttributeName, attributeInfo := range m {
if d.HasChange(tfAttributeName) {
v := d.Get(tfAttributeName)
var apiAttributeValue string
switch t := attributeInfo.tfType; t {
case schema.TypeBool:
apiAttributeValue = strconv.FormatBool(v.(bool))
case schema.TypeInt:
apiAttributeValue = strconv.Itoa(v.(int))
case schema.TypeString:
apiAttributeValue = v.(string)
default:
return nil, fmt.Errorf("attribute %s is of unsupported type: %d", tfAttributeName, t)
}
apiAttributes[attributeInfo.apiAttributeName] = apiAttributeValue
}
}
return apiAttributes, nil
}
// ApiAttributeNames returns the AWS API attribute names.
func (m AttributeMap) ApiAttributeNames() []string {
apiAttributeNames := []string{}
for _, attributeInfo := range m {
apiAttributeNames = append(apiAttributeNames, attributeInfo.apiAttributeName)
}
return apiAttributeNames
}