Skip to content

Commit 1cc4d84

Browse files
committed
Merge branch 'master' into CLOUDP-352320_autogen_lro_followup
* master: Add support for typed maps in autogen (#3833) Add support for typed nested maps in autogen (#3830) doc: Clarify known limitation associated to creation of duplicate entries in `project_ip_access_list` (#3823)
2 parents 2e3150a + acffdf8 commit 1cc4d84

File tree

24 files changed

+1610
-396
lines changed

24 files changed

+1610
-396
lines changed

docs/resources/project_ip_access_list.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ subcategory: "Projects"
1212
When you remove an entry from the access list, existing connections from the removed address(es) may remain open for a variable amount of time. How much time passes before Atlas closes the connection depends on several factors, including how the connection was established, the particular behavior of the application or driver using the address, and the connection protocol (e.g., TCP or UDP). This is particularly important to consider when changing an existing IP address or CIDR block as they cannot be updated via the Provider (comments can however), hence a change will force the destruction and recreation of entries.
1313

1414

15+
~> **IMPORTANT:** During creation this resource does not validate whether the specified `ip_address`, `cidr_block`, or `aws_security_group` already exists in the project's access list (known limitation). Defining a duplicate entry will result in a successful resource creation associated to the existing entry.
16+
1517
## Example Usage
1618

1719
### Using CIDR Block

internal/common/autogen/customtypes/list.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,14 @@ type ListValueInterface interface {
113113
Elements() []attr.Value
114114
}
115115

116+
func (v ListValue[T]) ToTerraformValue(ctx context.Context) (tftypes.Value, error) {
117+
if v.ListValue.ElementType(ctx) == nil {
118+
// ListValue created as a zero value (not explicitly initialized), initialize now so conversion does not panic.
119+
v.ListValue = NewListValueNull[T](ctx).ListValue
120+
}
121+
return v.ListValue.ToTerraformValue(ctx)
122+
}
123+
116124
func (v ListValue[T]) NewListValue(ctx context.Context, value []attr.Value) ListValueInterface {
117125
return NewListValue[T](ctx, value)
118126
}
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
package customtypes
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/hashicorp/terraform-plugin-framework/attr"
8+
"github.com/hashicorp/terraform-plugin-framework/diag"
9+
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
10+
"github.com/hashicorp/terraform-plugin-go/tftypes"
11+
)
12+
13+
/*
14+
Custom Map type used in auto-generated code to enable the generic marshal/unmarshal operations to access the elements' type during conversion.
15+
Custom types docs: https://developer.hashicorp.com/terraform/plugin/framework/handling-data/types/custom
16+
17+
Usage:
18+
- Schema definition:
19+
"sample_string_map": schema.MapAttribute{
20+
...
21+
CustomType: customtypes.NewMapType[basetypes.StringValue](ctx),
22+
ElementType: types.StringType,
23+
}
24+
25+
- TF Models:
26+
type TFModel struct {
27+
SampleStringMap customtypes.MapValue[basetypes.StringValue] `tfsdk:"sample_string_map"`
28+
...
29+
}
30+
*/
31+
32+
var (
33+
_ basetypes.MapTypable = MapType[basetypes.StringValue]{}
34+
_ basetypes.MapValuable = MapValue[basetypes.StringValue]{}
35+
_ MapValueInterface = MapValue[basetypes.StringValue]{}
36+
)
37+
38+
type MapType[T attr.Value] struct {
39+
basetypes.MapType
40+
}
41+
42+
func NewMapType[T attr.Value](ctx context.Context) MapType[T] {
43+
elemType := getElemType[T](ctx)
44+
return MapType[T]{
45+
MapType: basetypes.MapType{ElemType: elemType},
46+
}
47+
}
48+
49+
func (t MapType[T]) Equal(o attr.Type) bool {
50+
other, ok := o.(MapType[T])
51+
if !ok {
52+
return false
53+
}
54+
55+
return t.MapType.Equal(other.MapType)
56+
}
57+
58+
func (MapType[T]) String() string {
59+
var t T
60+
return fmt.Sprintf("MapType[%T]", t)
61+
}
62+
63+
func (t MapType[T]) ValueFromMap(ctx context.Context, in basetypes.MapValue) (basetypes.MapValuable, diag.Diagnostics) {
64+
if in.IsNull() {
65+
return NewMapValueNull[T](ctx), nil
66+
}
67+
68+
if in.IsUnknown() {
69+
return NewMapValueUnknown[T](ctx), nil
70+
}
71+
72+
elemType := getElemType[T](ctx)
73+
baseMapValue, diags := basetypes.NewMapValue(elemType, in.Elements())
74+
if diags.HasError() {
75+
return nil, diags
76+
}
77+
78+
return MapValue[T]{MapValue: baseMapValue}, nil
79+
}
80+
81+
func (t MapType[T]) ValueFromTerraform(ctx context.Context, in tftypes.Value) (attr.Value, error) {
82+
attrValue, err := t.MapType.ValueFromTerraform(ctx, in)
83+
84+
if err != nil {
85+
return nil, err
86+
}
87+
88+
mapValue, ok := attrValue.(basetypes.MapValue)
89+
if !ok {
90+
return nil, fmt.Errorf("unexpected value type of %T", attrValue)
91+
}
92+
93+
mapValuable, diags := t.ValueFromMap(ctx, mapValue)
94+
if diags.HasError() {
95+
return nil, fmt.Errorf("unexpected error converting MapValue to MapValuable: %v", diags)
96+
}
97+
98+
return mapValuable, nil
99+
}
100+
101+
func (t MapType[T]) ValueType(_ context.Context) attr.Value {
102+
return MapValue[T]{}
103+
}
104+
105+
type MapValue[T attr.Value] struct {
106+
basetypes.MapValue
107+
}
108+
109+
type MapValueInterface interface {
110+
basetypes.MapValuable
111+
NewMapValue(ctx context.Context, value map[string]attr.Value) MapValueInterface
112+
NewMapValueNull(ctx context.Context) MapValueInterface
113+
ElementType(ctx context.Context) attr.Type
114+
Elements() map[string]attr.Value
115+
}
116+
117+
func (v MapValue[T]) ToTerraformValue(ctx context.Context) (tftypes.Value, error) {
118+
if v.MapValue.ElementType(ctx) == nil {
119+
// MapValue created as a zero value (not explicitly initialized), initialize now so conversion does not panic.
120+
v.MapValue = NewMapValueNull[T](ctx).MapValue
121+
}
122+
return v.MapValue.ToTerraformValue(ctx)
123+
}
124+
125+
func (v MapValue[T]) NewMapValue(ctx context.Context, value map[string]attr.Value) MapValueInterface {
126+
return NewMapValue[T](ctx, value)
127+
}
128+
129+
func NewMapValue[T attr.Value](ctx context.Context, value map[string]attr.Value) MapValue[T] {
130+
elemType := getElemType[T](ctx)
131+
132+
mapValue, diags := basetypes.NewMapValue(elemType, value)
133+
if diags.HasError() {
134+
return NewMapValueUnknown[T](ctx)
135+
}
136+
137+
return MapValue[T]{MapValue: mapValue}
138+
}
139+
140+
func (v MapValue[T]) NewMapValueNull(ctx context.Context) MapValueInterface {
141+
return NewMapValueNull[T](ctx)
142+
}
143+
144+
func NewMapValueNull[T attr.Value](ctx context.Context) MapValue[T] {
145+
elemType := getElemType[T](ctx)
146+
return MapValue[T]{MapValue: basetypes.NewMapNull(elemType)}
147+
}
148+
149+
func NewMapValueUnknown[T attr.Value](ctx context.Context) MapValue[T] {
150+
elemType := getElemType[T](ctx)
151+
return MapValue[T]{MapValue: basetypes.NewMapUnknown(elemType)}
152+
}
153+
154+
func (v MapValue[T]) Equal(o attr.Value) bool {
155+
other, ok := o.(MapValue[T])
156+
if !ok {
157+
return false
158+
}
159+
return v.MapValue.Equal(other.MapValue)
160+
}
161+
162+
func (v MapValue[T]) Type(ctx context.Context) attr.Type {
163+
return NewMapType[T](ctx)
164+
}
165+
166+
func (v MapValue[T]) ElementType(ctx context.Context) attr.Type {
167+
return getElemType[T](ctx)
168+
}
169+
170+
func (v MapValue[T]) Elements() map[string]attr.Value {
171+
return v.MapValue.Elements()
172+
}

internal/common/autogen/customtypes/nested_list.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,14 @@ type NestedListValueInterface interface {
133133
Len() int
134134
}
135135

136+
func (v NestedListValue[T]) ToTerraformValue(ctx context.Context) (tftypes.Value, error) {
137+
if v.ElementType(ctx) == nil {
138+
// NestedListValue created as a zero value (not explicitly initialized), initialize now so conversion does not panic.
139+
v.ListValue = NewNestedListValueNull[T](ctx).ListValue
140+
}
141+
return v.ListValue.ToTerraformValue(ctx)
142+
}
143+
136144
func (v NestedListValue[T]) NewNestedListValue(ctx context.Context, value any) NestedListValueInterface {
137145
return NewNestedListValue[T](ctx, value)
138146
}

0 commit comments

Comments
 (0)