/
nested_attributes.go
215 lines (178 loc) · 6.55 KB
/
nested_attributes.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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
package fwschema
import (
"fmt"
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-go/tftypes"
)
// NestingMode is an enum type of the ways nested attributes can be nested in
// an attribute. They can be a list, a set, a map (with string
// keys), or they can be nested directly, like an object.
type NestingMode uint8
const (
// NestingModeUnknown is an invalid nesting mode, used to catch when a
// nesting mode is expected and not set.
NestingModeUnknown NestingMode = 0
// NestingModeSingle is for attributes that represent a struct or
// object, a single instance of those attributes directly nested under
// another attribute.
NestingModeSingle NestingMode = 1
// NestingModeList is for attributes that represent a list of objects,
// with multiple instances of those attributes nested inside a list
// under another attribute.
NestingModeList NestingMode = 2
// NestingModeSet is for attributes that represent a set of objects,
// with multiple, unique instances of those attributes nested inside a
// set under another attribute.
NestingModeSet NestingMode = 3
// NestingModeMap is for attributes that represent a map of objects,
// with multiple instances of those attributes, each associated with a
// unique string key, nested inside a map under another attribute.
NestingModeMap NestingMode = 4
)
// NestedAttributes surfaces a group of attributes to nest beneath another
// attribute, and how that nesting should behave. Nesting can have the
// following modes:
//
// * SingleNestedAttributes are nested attributes that represent a struct or
// object; there should only be one instance of them nested beneath that
// specific attribute.
//
// * ListNestedAttributes are nested attributes that represent a list of
// structs or objects; there can be multiple instances of them beneath that
// specific attribute.
//
// * SetNestedAttributes are nested attributes that represent a set of structs
// or objects; there can be multiple instances of them beneath that specific
// attribute. Unlike ListNestedAttributes, these nested attributes must have
// unique values.
//
// * MapNestedAttributes are nested attributes that represent a string-indexed
// map of structs or objects; there can be multiple instances of them beneath
// that specific attribute. Unlike ListNestedAttributes, these nested
// attributes must be associated with a unique key. Unlike SetNestedAttributes,
// the key must be explicitly set by the user.
type NestedAttributes interface {
// Implementations should include the tftypes.AttributePathStepper
// interface methods for proper path and data handling.
tftypes.AttributePathStepper
// Equal should return true if the other NestedAttributes is equivalent.
Equal(NestedAttributes) bool
// GetNestingMode should return the nesting mode (list, map, set, or
// single) of the nested attributes.
GetNestingMode() NestingMode
// GetAttributes() should return the mapping of names to nested attributes.
GetAttributes() map[string]Attribute
// Type should return the framework type of the nested attributes.
Type() attr.Type
}
type SingleNestedAttributes struct {
UnderlyingAttributes
}
func (s SingleNestedAttributes) ApplyTerraform5AttributePathStep(step tftypes.AttributePathStep) (interface{}, error) {
return s.UnderlyingAttributes.ApplyTerraform5AttributePathStep(step)
}
func (s SingleNestedAttributes) GetAttributes() map[string]Attribute {
return s.UnderlyingAttributes
}
func (s SingleNestedAttributes) GetNestingMode() NestingMode {
return NestingModeSingle
}
func (s SingleNestedAttributes) Equal(o NestedAttributes) bool {
other, ok := o.(SingleNestedAttributes)
if !ok {
return false
}
return s.UnderlyingAttributes.Equal(other.UnderlyingAttributes)
}
// Type returns the framework type of the nested attributes.
func (s SingleNestedAttributes) Type() attr.Type {
return s.UnderlyingAttributes.Type()
}
type ListNestedAttributes struct {
UnderlyingAttributes
}
func (l ListNestedAttributes) GetAttributes() map[string]Attribute {
return l.UnderlyingAttributes
}
func (l ListNestedAttributes) GetNestingMode() NestingMode {
return NestingModeList
}
func (l ListNestedAttributes) ApplyTerraform5AttributePathStep(step tftypes.AttributePathStep) (interface{}, error) {
_, ok := step.(tftypes.ElementKeyInt)
if !ok {
return nil, fmt.Errorf("can't apply %T to ListNestedAttributes", step)
}
return l.UnderlyingAttributes, nil
}
func (l ListNestedAttributes) Equal(o NestedAttributes) bool {
other, ok := o.(ListNestedAttributes)
if !ok {
return false
}
return l.UnderlyingAttributes.Equal(other.UnderlyingAttributes)
}
// Type returns the framework type of the nested attributes.
func (l ListNestedAttributes) Type() attr.Type {
return types.ListType{
ElemType: l.UnderlyingAttributes.Type(),
}
}
type SetNestedAttributes struct {
UnderlyingAttributes
}
func (s SetNestedAttributes) GetAttributes() map[string]Attribute {
return s.UnderlyingAttributes
}
func (s SetNestedAttributes) GetNestingMode() NestingMode {
return NestingModeSet
}
func (s SetNestedAttributes) ApplyTerraform5AttributePathStep(step tftypes.AttributePathStep) (interface{}, error) {
_, ok := step.(tftypes.ElementKeyValue)
if !ok {
return nil, fmt.Errorf("can't use %T on sets", step)
}
return s.UnderlyingAttributes, nil
}
func (s SetNestedAttributes) Equal(o NestedAttributes) bool {
other, ok := o.(SetNestedAttributes)
if !ok {
return false
}
return s.UnderlyingAttributes.Equal(other.UnderlyingAttributes)
}
// Type returns the framework type of the nested attributes.
func (s SetNestedAttributes) Type() attr.Type {
return types.SetType{
ElemType: s.UnderlyingAttributes.Type(),
}
}
type MapNestedAttributes struct {
UnderlyingAttributes
}
func (m MapNestedAttributes) GetAttributes() map[string]Attribute {
return m.UnderlyingAttributes
}
func (m MapNestedAttributes) GetNestingMode() NestingMode {
return NestingModeMap
}
func (m MapNestedAttributes) ApplyTerraform5AttributePathStep(step tftypes.AttributePathStep) (interface{}, error) {
_, ok := step.(tftypes.ElementKeyString)
if !ok {
return nil, fmt.Errorf("can't use %T on maps", step)
}
return m.UnderlyingAttributes, nil
}
func (m MapNestedAttributes) Equal(o NestedAttributes) bool {
other, ok := o.(MapNestedAttributes)
if !ok {
return false
}
return m.UnderlyingAttributes.Equal(other.UnderlyingAttributes)
}
// Type returns the framework type of the nested attributes.
func (m MapNestedAttributes) Type() attr.Type {
return types.MapType{
ElemType: m.UnderlyingAttributes.Type(),
}
}