From eb111c7306418d68d0772886a89818e425fb3297 Mon Sep 17 00:00:00 2001 From: Service Account - Terraform Provider DevEx <100357958+hc-github-team-tf-provider-devex@users.noreply.github.com> Date: Mon, 16 Sep 2024 09:33:14 -0400 Subject: [PATCH 1/6] [CI] Update lock workflow file From 2b091de742158f02372e8e32ef419e21f8ed2204 Mon Sep 17 00:00:00 2001 From: Service Account - Terraform Provider DevEx <100357958+hc-github-team-tf-provider-devex@users.noreply.github.com> Date: Mon, 16 Sep 2024 09:33:25 -0400 Subject: [PATCH 2/6] [CI] Update issue comment triage workflow file From d8041fea42583d4e3f7d2198057167a4f74e1243 Mon Sep 17 00:00:00 2001 From: Service Account - Terraform Provider DevEx <100357958+hc-github-team-tf-provider-devex@users.noreply.github.com> Date: Mon, 16 Sep 2024 09:34:09 -0400 Subject: [PATCH 3/6] [CI] terraform-devex-repos automation From 2577bef1f1bdfc5bb26737583d130315d43e4d7d Mon Sep 17 00:00:00 2001 From: Service Account - Terraform Provider DevEx <100357958+hc-github-team-tf-provider-devex@users.noreply.github.com> Date: Mon, 16 Sep 2024 09:35:11 -0400 Subject: [PATCH 4/6] [CI] terraform-devex-repos automation From a75e76ad72e4c26d4357a96eda488624e97cfcd0 Mon Sep 17 00:00:00 2001 From: Service Account - Terraform Provider DevEx <100357958+hc-github-team-tf-provider-devex@users.noreply.github.com> Date: Mon, 16 Sep 2024 09:35:36 -0400 Subject: [PATCH 5/6] [CI] terraform-devex-repos automation From c5a3592ca031ed5d202f94ae7dc877190bb3dccd Mon Sep 17 00:00:00 2001 From: Maxim Speshilov <96119389+paaanic@users.noreply.github.com> Date: Tue, 24 Sep 2024 23:18:32 +0300 Subject: [PATCH 6/6] Fix conversion of unknown or null collections to empty in nested objects (#161) * Fix conversion of unknown or null collections to empty in nested objects * Add changelog entry --- .../unreleased/BUG FIXES-20240921-113938.yaml | 5 + .../example_data_source_gen.go | 157 ++++++++++++++++-- .../example_data_source_gen.go | 157 ++++++++++++++++-- .../example_data_source_gen.go | 157 ++++++++++++++++-- .../cmd/testdata/custom_and_external/ir.json | 9 + internal/schema/custom_nested_object_test.go | 152 ++++++++++++++++- ...nested_object_value_to_object_value.gotmpl | 19 ++- 7 files changed, 596 insertions(+), 60 deletions(-) create mode 100644 .changes/unreleased/BUG FIXES-20240921-113938.yaml diff --git a/.changes/unreleased/BUG FIXES-20240921-113938.yaml b/.changes/unreleased/BUG FIXES-20240921-113938.yaml new file mode 100644 index 00000000..ce85acde --- /dev/null +++ b/.changes/unreleased/BUG FIXES-20240921-113938.yaml @@ -0,0 +1,5 @@ +kind: BUG FIXES +body: Fix conversion of unknown or null collections to empty in nested objects +time: 2024-09-21T11:39:38.074042155+03:00 +custom: + Issue: "161" diff --git a/internal/cmd/testdata/custom_and_external/all_output/default_pkg_name/datasource_example/example_data_source_gen.go b/internal/cmd/testdata/custom_and_external/all_output/default_pkg_name/datasource_example/example_data_source_gen.go index bafaf21c..0510769c 100644 --- a/internal/cmd/testdata/custom_and_external/all_output/default_pkg_name/datasource_example/example_data_source_gen.go +++ b/internal/cmd/testdata/custom_and_external/all_output/default_pkg_name/datasource_example/example_data_source_gen.go @@ -90,6 +90,10 @@ func ExampleDataSourceSchema(ctx context.Context) schema.Schema { ElementType: types.StringType, Computed: true, }, + "map_attribute": schema.MapAttribute{ + ElementType: types.Int64Type, + Computed: true, + }, }, CustomType: ListNestedAttributeThreeListNestedAttributeOneType{ ObjectType: types.ObjectType{ @@ -1867,12 +1871,31 @@ func (t ListNestedAttributeThreeListNestedAttributeOneType) ValueFromObject(ctx fmt.Sprintf(`list_attribute expected to be basetypes.ListValue, was: %T`, listAttributeAttribute)) } + mapAttributeAttribute, ok := attributes["map_attribute"] + + if !ok { + diags.AddError( + "Attribute Missing", + `map_attribute is missing from object`) + + return nil, diags + } + + mapAttributeVal, ok := mapAttributeAttribute.(basetypes.MapValue) + + if !ok { + diags.AddError( + "Attribute Wrong Type", + fmt.Sprintf(`map_attribute expected to be basetypes.MapValue, was: %T`, mapAttributeAttribute)) + } + if diags.HasError() { return nil, diags } return ListNestedAttributeThreeListNestedAttributeOneValue{ ListAttribute: listAttributeVal, + MapAttribute: mapAttributeVal, state: attr.ValueStateKnown, }, diags } @@ -1958,12 +1981,31 @@ func NewListNestedAttributeThreeListNestedAttributeOneValue(attributeTypes map[s fmt.Sprintf(`list_attribute expected to be basetypes.ListValue, was: %T`, listAttributeAttribute)) } + mapAttributeAttribute, ok := attributes["map_attribute"] + + if !ok { + diags.AddError( + "Attribute Missing", + `map_attribute is missing from object`) + + return NewListNestedAttributeThreeListNestedAttributeOneValueUnknown(), diags + } + + mapAttributeVal, ok := mapAttributeAttribute.(basetypes.MapValue) + + if !ok { + diags.AddError( + "Attribute Wrong Type", + fmt.Sprintf(`map_attribute expected to be basetypes.MapValue, was: %T`, mapAttributeAttribute)) + } + if diags.HasError() { return NewListNestedAttributeThreeListNestedAttributeOneValueUnknown(), diags } return ListNestedAttributeThreeListNestedAttributeOneValue{ ListAttribute: listAttributeVal, + MapAttribute: mapAttributeVal, state: attr.ValueStateKnown, }, diags } @@ -2037,11 +2079,12 @@ var _ basetypes.ObjectValuable = ListNestedAttributeThreeListNestedAttributeOneV type ListNestedAttributeThreeListNestedAttributeOneValue struct { ListAttribute basetypes.ListValue `tfsdk:"list_attribute"` + MapAttribute basetypes.MapValue `tfsdk:"map_attribute"` state attr.ValueState } func (v ListNestedAttributeThreeListNestedAttributeOneValue) ToTerraformValue(ctx context.Context) (tftypes.Value, error) { - attrTypes := make(map[string]tftypes.Type, 1) + attrTypes := make(map[string]tftypes.Type, 2) var val tftypes.Value var err error @@ -2049,12 +2092,15 @@ func (v ListNestedAttributeThreeListNestedAttributeOneValue) ToTerraformValue(ct attrTypes["list_attribute"] = basetypes.ListType{ ElemType: types.StringType, }.TerraformType(ctx) + attrTypes["map_attribute"] = basetypes.MapType{ + ElemType: types.Int64Type, + }.TerraformType(ctx) objectType := tftypes.Object{AttributeTypes: attrTypes} switch v.state { case attr.ValueStateKnown: - vals := make(map[string]tftypes.Value, 1) + vals := make(map[string]tftypes.Value, 2) val, err = v.ListAttribute.ToTerraformValue(ctx) @@ -2064,6 +2110,14 @@ func (v ListNestedAttributeThreeListNestedAttributeOneValue) ToTerraformValue(ct vals["list_attribute"] = val + val, err = v.MapAttribute.ToTerraformValue(ctx) + + if err != nil { + return tftypes.NewValue(objectType, tftypes.UnknownValue), err + } + + vals["map_attribute"] = val + if err := tftypes.ValidateValue(objectType, vals); err != nil { return tftypes.NewValue(objectType, tftypes.UnknownValue), err } @@ -2093,15 +2147,49 @@ func (v ListNestedAttributeThreeListNestedAttributeOneValue) String() string { func (v ListNestedAttributeThreeListNestedAttributeOneValue) ToObjectValue(ctx context.Context) (basetypes.ObjectValue, diag.Diagnostics) { var diags diag.Diagnostics - listAttributeVal, d := types.ListValue(types.StringType, v.ListAttribute.Elements()) + var listAttributeVal basetypes.ListValue + switch { + case v.ListAttribute.IsUnknown(): + listAttributeVal = types.ListUnknown(types.StringType) + case v.ListAttribute.IsNull(): + listAttributeVal = types.ListNull(types.StringType) + default: + var d diag.Diagnostics + listAttributeVal, d = types.ListValue(types.StringType, v.ListAttribute.Elements()) + diags.Append(d...) + } - diags.Append(d...) + if diags.HasError() { + return types.ObjectUnknown(map[string]attr.Type{ + "list_attribute": basetypes.ListType{ + ElemType: types.StringType, + }, + "map_attribute": basetypes.MapType{ + ElemType: types.Int64Type, + }, + }), diags + } - if d.HasError() { + var mapAttributeVal basetypes.MapValue + switch { + case v.MapAttribute.IsUnknown(): + mapAttributeVal = types.MapUnknown(types.Int64Type) + case v.MapAttribute.IsNull(): + mapAttributeVal = types.MapNull(types.Int64Type) + default: + var d diag.Diagnostics + mapAttributeVal, d = types.MapValue(types.Int64Type, v.MapAttribute.Elements()) + diags.Append(d...) + } + + if diags.HasError() { return types.ObjectUnknown(map[string]attr.Type{ "list_attribute": basetypes.ListType{ ElemType: types.StringType, }, + "map_attribute": basetypes.MapType{ + ElemType: types.Int64Type, + }, }), diags } @@ -2109,6 +2197,9 @@ func (v ListNestedAttributeThreeListNestedAttributeOneValue) ToObjectValue(ctx c "list_attribute": basetypes.ListType{ ElemType: types.StringType, }, + "map_attribute": basetypes.MapType{ + ElemType: types.Int64Type, + }, } if v.IsNull() { @@ -2123,6 +2214,7 @@ func (v ListNestedAttributeThreeListNestedAttributeOneValue) ToObjectValue(ctx c attributeTypes, map[string]attr.Value{ "list_attribute": listAttributeVal, + "map_attribute": mapAttributeVal, }) return objVal, diags @@ -2147,6 +2239,10 @@ func (v ListNestedAttributeThreeListNestedAttributeOneValue) Equal(o attr.Value) return false } + if !v.MapAttribute.Equal(other.MapAttribute) { + return false + } + return true } @@ -2163,6 +2259,9 @@ func (v ListNestedAttributeThreeListNestedAttributeOneValue) AttributeTypes(ctx "list_attribute": basetypes.ListType{ ElemType: types.StringType, }, + "map_attribute": basetypes.MapType{ + ElemType: types.Int64Type, + }, } } @@ -5425,11 +5524,19 @@ func (v SingleNestedAttributeThreeSingleNestedAttributeOneValue) String() string func (v SingleNestedAttributeThreeSingleNestedAttributeOneValue) ToObjectValue(ctx context.Context) (basetypes.ObjectValue, diag.Diagnostics) { var diags diag.Diagnostics - listAttributeVal, d := types.ListValue(types.StringType, v.ListAttribute.Elements()) - - diags.Append(d...) + var listAttributeVal basetypes.ListValue + switch { + case v.ListAttribute.IsUnknown(): + listAttributeVal = types.ListUnknown(types.StringType) + case v.ListAttribute.IsNull(): + listAttributeVal = types.ListNull(types.StringType) + default: + var d diag.Diagnostics + listAttributeVal, d = types.ListValue(types.StringType, v.ListAttribute.Elements()) + diags.Append(d...) + } - if d.HasError() { + if diags.HasError() { return types.ObjectUnknown(map[string]attr.Type{ "list_attribute": basetypes.ListType{ ElemType: types.StringType, @@ -7749,11 +7856,19 @@ func (v ListNestedBlockThreeListNestedBlockOneValue) String() string { func (v ListNestedBlockThreeListNestedBlockOneValue) ToObjectValue(ctx context.Context) (basetypes.ObjectValue, diag.Diagnostics) { var diags diag.Diagnostics - listAttributeVal, d := types.ListValue(types.StringType, v.ListAttribute.Elements()) - - diags.Append(d...) + var listAttributeVal basetypes.ListValue + switch { + case v.ListAttribute.IsUnknown(): + listAttributeVal = types.ListUnknown(types.StringType) + case v.ListAttribute.IsNull(): + listAttributeVal = types.ListNull(types.StringType) + default: + var d diag.Diagnostics + listAttributeVal, d = types.ListValue(types.StringType, v.ListAttribute.Elements()) + diags.Append(d...) + } - if d.HasError() { + if diags.HasError() { return types.ObjectUnknown(map[string]attr.Type{ "list_attribute": basetypes.ListType{ ElemType: types.StringType, @@ -10625,11 +10740,19 @@ func (v SingleNestedBlockThreeListNestedBlockOneValue) String() string { func (v SingleNestedBlockThreeListNestedBlockOneValue) ToObjectValue(ctx context.Context) (basetypes.ObjectValue, diag.Diagnostics) { var diags diag.Diagnostics - listAttributeVal, d := types.ListValue(types.StringType, v.ListAttribute.Elements()) - - diags.Append(d...) + var listAttributeVal basetypes.ListValue + switch { + case v.ListAttribute.IsUnknown(): + listAttributeVal = types.ListUnknown(types.StringType) + case v.ListAttribute.IsNull(): + listAttributeVal = types.ListNull(types.StringType) + default: + var d diag.Diagnostics + listAttributeVal, d = types.ListValue(types.StringType, v.ListAttribute.Elements()) + diags.Append(d...) + } - if d.HasError() { + if diags.HasError() { return types.ObjectUnknown(map[string]attr.Type{ "list_attribute": basetypes.ListType{ ElemType: types.StringType, diff --git a/internal/cmd/testdata/custom_and_external/all_output/specified_pkg_name/example_data_source_gen.go b/internal/cmd/testdata/custom_and_external/all_output/specified_pkg_name/example_data_source_gen.go index faf3303b..e5b873be 100644 --- a/internal/cmd/testdata/custom_and_external/all_output/specified_pkg_name/example_data_source_gen.go +++ b/internal/cmd/testdata/custom_and_external/all_output/specified_pkg_name/example_data_source_gen.go @@ -90,6 +90,10 @@ func ExampleDataSourceSchema(ctx context.Context) schema.Schema { ElementType: types.StringType, Computed: true, }, + "map_attribute": schema.MapAttribute{ + ElementType: types.Int64Type, + Computed: true, + }, }, CustomType: ListNestedAttributeThreeListNestedAttributeOneType{ ObjectType: types.ObjectType{ @@ -1867,12 +1871,31 @@ func (t ListNestedAttributeThreeListNestedAttributeOneType) ValueFromObject(ctx fmt.Sprintf(`list_attribute expected to be basetypes.ListValue, was: %T`, listAttributeAttribute)) } + mapAttributeAttribute, ok := attributes["map_attribute"] + + if !ok { + diags.AddError( + "Attribute Missing", + `map_attribute is missing from object`) + + return nil, diags + } + + mapAttributeVal, ok := mapAttributeAttribute.(basetypes.MapValue) + + if !ok { + diags.AddError( + "Attribute Wrong Type", + fmt.Sprintf(`map_attribute expected to be basetypes.MapValue, was: %T`, mapAttributeAttribute)) + } + if diags.HasError() { return nil, diags } return ListNestedAttributeThreeListNestedAttributeOneValue{ ListAttribute: listAttributeVal, + MapAttribute: mapAttributeVal, state: attr.ValueStateKnown, }, diags } @@ -1958,12 +1981,31 @@ func NewListNestedAttributeThreeListNestedAttributeOneValue(attributeTypes map[s fmt.Sprintf(`list_attribute expected to be basetypes.ListValue, was: %T`, listAttributeAttribute)) } + mapAttributeAttribute, ok := attributes["map_attribute"] + + if !ok { + diags.AddError( + "Attribute Missing", + `map_attribute is missing from object`) + + return NewListNestedAttributeThreeListNestedAttributeOneValueUnknown(), diags + } + + mapAttributeVal, ok := mapAttributeAttribute.(basetypes.MapValue) + + if !ok { + diags.AddError( + "Attribute Wrong Type", + fmt.Sprintf(`map_attribute expected to be basetypes.MapValue, was: %T`, mapAttributeAttribute)) + } + if diags.HasError() { return NewListNestedAttributeThreeListNestedAttributeOneValueUnknown(), diags } return ListNestedAttributeThreeListNestedAttributeOneValue{ ListAttribute: listAttributeVal, + MapAttribute: mapAttributeVal, state: attr.ValueStateKnown, }, diags } @@ -2037,11 +2079,12 @@ var _ basetypes.ObjectValuable = ListNestedAttributeThreeListNestedAttributeOneV type ListNestedAttributeThreeListNestedAttributeOneValue struct { ListAttribute basetypes.ListValue `tfsdk:"list_attribute"` + MapAttribute basetypes.MapValue `tfsdk:"map_attribute"` state attr.ValueState } func (v ListNestedAttributeThreeListNestedAttributeOneValue) ToTerraformValue(ctx context.Context) (tftypes.Value, error) { - attrTypes := make(map[string]tftypes.Type, 1) + attrTypes := make(map[string]tftypes.Type, 2) var val tftypes.Value var err error @@ -2049,12 +2092,15 @@ func (v ListNestedAttributeThreeListNestedAttributeOneValue) ToTerraformValue(ct attrTypes["list_attribute"] = basetypes.ListType{ ElemType: types.StringType, }.TerraformType(ctx) + attrTypes["map_attribute"] = basetypes.MapType{ + ElemType: types.Int64Type, + }.TerraformType(ctx) objectType := tftypes.Object{AttributeTypes: attrTypes} switch v.state { case attr.ValueStateKnown: - vals := make(map[string]tftypes.Value, 1) + vals := make(map[string]tftypes.Value, 2) val, err = v.ListAttribute.ToTerraformValue(ctx) @@ -2064,6 +2110,14 @@ func (v ListNestedAttributeThreeListNestedAttributeOneValue) ToTerraformValue(ct vals["list_attribute"] = val + val, err = v.MapAttribute.ToTerraformValue(ctx) + + if err != nil { + return tftypes.NewValue(objectType, tftypes.UnknownValue), err + } + + vals["map_attribute"] = val + if err := tftypes.ValidateValue(objectType, vals); err != nil { return tftypes.NewValue(objectType, tftypes.UnknownValue), err } @@ -2093,15 +2147,49 @@ func (v ListNestedAttributeThreeListNestedAttributeOneValue) String() string { func (v ListNestedAttributeThreeListNestedAttributeOneValue) ToObjectValue(ctx context.Context) (basetypes.ObjectValue, diag.Diagnostics) { var diags diag.Diagnostics - listAttributeVal, d := types.ListValue(types.StringType, v.ListAttribute.Elements()) + var listAttributeVal basetypes.ListValue + switch { + case v.ListAttribute.IsUnknown(): + listAttributeVal = types.ListUnknown(types.StringType) + case v.ListAttribute.IsNull(): + listAttributeVal = types.ListNull(types.StringType) + default: + var d diag.Diagnostics + listAttributeVal, d = types.ListValue(types.StringType, v.ListAttribute.Elements()) + diags.Append(d...) + } - diags.Append(d...) + if diags.HasError() { + return types.ObjectUnknown(map[string]attr.Type{ + "list_attribute": basetypes.ListType{ + ElemType: types.StringType, + }, + "map_attribute": basetypes.MapType{ + ElemType: types.Int64Type, + }, + }), diags + } - if d.HasError() { + var mapAttributeVal basetypes.MapValue + switch { + case v.MapAttribute.IsUnknown(): + mapAttributeVal = types.MapUnknown(types.Int64Type) + case v.MapAttribute.IsNull(): + mapAttributeVal = types.MapNull(types.Int64Type) + default: + var d diag.Diagnostics + mapAttributeVal, d = types.MapValue(types.Int64Type, v.MapAttribute.Elements()) + diags.Append(d...) + } + + if diags.HasError() { return types.ObjectUnknown(map[string]attr.Type{ "list_attribute": basetypes.ListType{ ElemType: types.StringType, }, + "map_attribute": basetypes.MapType{ + ElemType: types.Int64Type, + }, }), diags } @@ -2109,6 +2197,9 @@ func (v ListNestedAttributeThreeListNestedAttributeOneValue) ToObjectValue(ctx c "list_attribute": basetypes.ListType{ ElemType: types.StringType, }, + "map_attribute": basetypes.MapType{ + ElemType: types.Int64Type, + }, } if v.IsNull() { @@ -2123,6 +2214,7 @@ func (v ListNestedAttributeThreeListNestedAttributeOneValue) ToObjectValue(ctx c attributeTypes, map[string]attr.Value{ "list_attribute": listAttributeVal, + "map_attribute": mapAttributeVal, }) return objVal, diags @@ -2147,6 +2239,10 @@ func (v ListNestedAttributeThreeListNestedAttributeOneValue) Equal(o attr.Value) return false } + if !v.MapAttribute.Equal(other.MapAttribute) { + return false + } + return true } @@ -2163,6 +2259,9 @@ func (v ListNestedAttributeThreeListNestedAttributeOneValue) AttributeTypes(ctx "list_attribute": basetypes.ListType{ ElemType: types.StringType, }, + "map_attribute": basetypes.MapType{ + ElemType: types.Int64Type, + }, } } @@ -5425,11 +5524,19 @@ func (v SingleNestedAttributeThreeSingleNestedAttributeOneValue) String() string func (v SingleNestedAttributeThreeSingleNestedAttributeOneValue) ToObjectValue(ctx context.Context) (basetypes.ObjectValue, diag.Diagnostics) { var diags diag.Diagnostics - listAttributeVal, d := types.ListValue(types.StringType, v.ListAttribute.Elements()) - - diags.Append(d...) + var listAttributeVal basetypes.ListValue + switch { + case v.ListAttribute.IsUnknown(): + listAttributeVal = types.ListUnknown(types.StringType) + case v.ListAttribute.IsNull(): + listAttributeVal = types.ListNull(types.StringType) + default: + var d diag.Diagnostics + listAttributeVal, d = types.ListValue(types.StringType, v.ListAttribute.Elements()) + diags.Append(d...) + } - if d.HasError() { + if diags.HasError() { return types.ObjectUnknown(map[string]attr.Type{ "list_attribute": basetypes.ListType{ ElemType: types.StringType, @@ -7749,11 +7856,19 @@ func (v ListNestedBlockThreeListNestedBlockOneValue) String() string { func (v ListNestedBlockThreeListNestedBlockOneValue) ToObjectValue(ctx context.Context) (basetypes.ObjectValue, diag.Diagnostics) { var diags diag.Diagnostics - listAttributeVal, d := types.ListValue(types.StringType, v.ListAttribute.Elements()) - - diags.Append(d...) + var listAttributeVal basetypes.ListValue + switch { + case v.ListAttribute.IsUnknown(): + listAttributeVal = types.ListUnknown(types.StringType) + case v.ListAttribute.IsNull(): + listAttributeVal = types.ListNull(types.StringType) + default: + var d diag.Diagnostics + listAttributeVal, d = types.ListValue(types.StringType, v.ListAttribute.Elements()) + diags.Append(d...) + } - if d.HasError() { + if diags.HasError() { return types.ObjectUnknown(map[string]attr.Type{ "list_attribute": basetypes.ListType{ ElemType: types.StringType, @@ -10625,11 +10740,19 @@ func (v SingleNestedBlockThreeListNestedBlockOneValue) String() string { func (v SingleNestedBlockThreeListNestedBlockOneValue) ToObjectValue(ctx context.Context) (basetypes.ObjectValue, diag.Diagnostics) { var diags diag.Diagnostics - listAttributeVal, d := types.ListValue(types.StringType, v.ListAttribute.Elements()) - - diags.Append(d...) + var listAttributeVal basetypes.ListValue + switch { + case v.ListAttribute.IsUnknown(): + listAttributeVal = types.ListUnknown(types.StringType) + case v.ListAttribute.IsNull(): + listAttributeVal = types.ListNull(types.StringType) + default: + var d diag.Diagnostics + listAttributeVal, d = types.ListValue(types.StringType, v.ListAttribute.Elements()) + diags.Append(d...) + } - if d.HasError() { + if diags.HasError() { return types.ObjectUnknown(map[string]attr.Type{ "list_attribute": basetypes.ListType{ ElemType: types.StringType, diff --git a/internal/cmd/testdata/custom_and_external/data_sources_output/example_data_source_gen.go b/internal/cmd/testdata/custom_and_external/data_sources_output/example_data_source_gen.go index 18255129..c354325a 100644 --- a/internal/cmd/testdata/custom_and_external/data_sources_output/example_data_source_gen.go +++ b/internal/cmd/testdata/custom_and_external/data_sources_output/example_data_source_gen.go @@ -90,6 +90,10 @@ func ExampleDataSourceSchema(ctx context.Context) schema.Schema { ElementType: types.StringType, Computed: true, }, + "map_attribute": schema.MapAttribute{ + ElementType: types.Int64Type, + Computed: true, + }, }, CustomType: ListNestedAttributeThreeListNestedAttributeOneType{ ObjectType: types.ObjectType{ @@ -1867,12 +1871,31 @@ func (t ListNestedAttributeThreeListNestedAttributeOneType) ValueFromObject(ctx fmt.Sprintf(`list_attribute expected to be basetypes.ListValue, was: %T`, listAttributeAttribute)) } + mapAttributeAttribute, ok := attributes["map_attribute"] + + if !ok { + diags.AddError( + "Attribute Missing", + `map_attribute is missing from object`) + + return nil, diags + } + + mapAttributeVal, ok := mapAttributeAttribute.(basetypes.MapValue) + + if !ok { + diags.AddError( + "Attribute Wrong Type", + fmt.Sprintf(`map_attribute expected to be basetypes.MapValue, was: %T`, mapAttributeAttribute)) + } + if diags.HasError() { return nil, diags } return ListNestedAttributeThreeListNestedAttributeOneValue{ ListAttribute: listAttributeVal, + MapAttribute: mapAttributeVal, state: attr.ValueStateKnown, }, diags } @@ -1958,12 +1981,31 @@ func NewListNestedAttributeThreeListNestedAttributeOneValue(attributeTypes map[s fmt.Sprintf(`list_attribute expected to be basetypes.ListValue, was: %T`, listAttributeAttribute)) } + mapAttributeAttribute, ok := attributes["map_attribute"] + + if !ok { + diags.AddError( + "Attribute Missing", + `map_attribute is missing from object`) + + return NewListNestedAttributeThreeListNestedAttributeOneValueUnknown(), diags + } + + mapAttributeVal, ok := mapAttributeAttribute.(basetypes.MapValue) + + if !ok { + diags.AddError( + "Attribute Wrong Type", + fmt.Sprintf(`map_attribute expected to be basetypes.MapValue, was: %T`, mapAttributeAttribute)) + } + if diags.HasError() { return NewListNestedAttributeThreeListNestedAttributeOneValueUnknown(), diags } return ListNestedAttributeThreeListNestedAttributeOneValue{ ListAttribute: listAttributeVal, + MapAttribute: mapAttributeVal, state: attr.ValueStateKnown, }, diags } @@ -2037,11 +2079,12 @@ var _ basetypes.ObjectValuable = ListNestedAttributeThreeListNestedAttributeOneV type ListNestedAttributeThreeListNestedAttributeOneValue struct { ListAttribute basetypes.ListValue `tfsdk:"list_attribute"` + MapAttribute basetypes.MapValue `tfsdk:"map_attribute"` state attr.ValueState } func (v ListNestedAttributeThreeListNestedAttributeOneValue) ToTerraformValue(ctx context.Context) (tftypes.Value, error) { - attrTypes := make(map[string]tftypes.Type, 1) + attrTypes := make(map[string]tftypes.Type, 2) var val tftypes.Value var err error @@ -2049,12 +2092,15 @@ func (v ListNestedAttributeThreeListNestedAttributeOneValue) ToTerraformValue(ct attrTypes["list_attribute"] = basetypes.ListType{ ElemType: types.StringType, }.TerraformType(ctx) + attrTypes["map_attribute"] = basetypes.MapType{ + ElemType: types.Int64Type, + }.TerraformType(ctx) objectType := tftypes.Object{AttributeTypes: attrTypes} switch v.state { case attr.ValueStateKnown: - vals := make(map[string]tftypes.Value, 1) + vals := make(map[string]tftypes.Value, 2) val, err = v.ListAttribute.ToTerraformValue(ctx) @@ -2064,6 +2110,14 @@ func (v ListNestedAttributeThreeListNestedAttributeOneValue) ToTerraformValue(ct vals["list_attribute"] = val + val, err = v.MapAttribute.ToTerraformValue(ctx) + + if err != nil { + return tftypes.NewValue(objectType, tftypes.UnknownValue), err + } + + vals["map_attribute"] = val + if err := tftypes.ValidateValue(objectType, vals); err != nil { return tftypes.NewValue(objectType, tftypes.UnknownValue), err } @@ -2093,15 +2147,49 @@ func (v ListNestedAttributeThreeListNestedAttributeOneValue) String() string { func (v ListNestedAttributeThreeListNestedAttributeOneValue) ToObjectValue(ctx context.Context) (basetypes.ObjectValue, diag.Diagnostics) { var diags diag.Diagnostics - listAttributeVal, d := types.ListValue(types.StringType, v.ListAttribute.Elements()) + var listAttributeVal basetypes.ListValue + switch { + case v.ListAttribute.IsUnknown(): + listAttributeVal = types.ListUnknown(types.StringType) + case v.ListAttribute.IsNull(): + listAttributeVal = types.ListNull(types.StringType) + default: + var d diag.Diagnostics + listAttributeVal, d = types.ListValue(types.StringType, v.ListAttribute.Elements()) + diags.Append(d...) + } - diags.Append(d...) + if diags.HasError() { + return types.ObjectUnknown(map[string]attr.Type{ + "list_attribute": basetypes.ListType{ + ElemType: types.StringType, + }, + "map_attribute": basetypes.MapType{ + ElemType: types.Int64Type, + }, + }), diags + } - if d.HasError() { + var mapAttributeVal basetypes.MapValue + switch { + case v.MapAttribute.IsUnknown(): + mapAttributeVal = types.MapUnknown(types.Int64Type) + case v.MapAttribute.IsNull(): + mapAttributeVal = types.MapNull(types.Int64Type) + default: + var d diag.Diagnostics + mapAttributeVal, d = types.MapValue(types.Int64Type, v.MapAttribute.Elements()) + diags.Append(d...) + } + + if diags.HasError() { return types.ObjectUnknown(map[string]attr.Type{ "list_attribute": basetypes.ListType{ ElemType: types.StringType, }, + "map_attribute": basetypes.MapType{ + ElemType: types.Int64Type, + }, }), diags } @@ -2109,6 +2197,9 @@ func (v ListNestedAttributeThreeListNestedAttributeOneValue) ToObjectValue(ctx c "list_attribute": basetypes.ListType{ ElemType: types.StringType, }, + "map_attribute": basetypes.MapType{ + ElemType: types.Int64Type, + }, } if v.IsNull() { @@ -2123,6 +2214,7 @@ func (v ListNestedAttributeThreeListNestedAttributeOneValue) ToObjectValue(ctx c attributeTypes, map[string]attr.Value{ "list_attribute": listAttributeVal, + "map_attribute": mapAttributeVal, }) return objVal, diags @@ -2147,6 +2239,10 @@ func (v ListNestedAttributeThreeListNestedAttributeOneValue) Equal(o attr.Value) return false } + if !v.MapAttribute.Equal(other.MapAttribute) { + return false + } + return true } @@ -2163,6 +2259,9 @@ func (v ListNestedAttributeThreeListNestedAttributeOneValue) AttributeTypes(ctx "list_attribute": basetypes.ListType{ ElemType: types.StringType, }, + "map_attribute": basetypes.MapType{ + ElemType: types.Int64Type, + }, } } @@ -5425,11 +5524,19 @@ func (v SingleNestedAttributeThreeSingleNestedAttributeOneValue) String() string func (v SingleNestedAttributeThreeSingleNestedAttributeOneValue) ToObjectValue(ctx context.Context) (basetypes.ObjectValue, diag.Diagnostics) { var diags diag.Diagnostics - listAttributeVal, d := types.ListValue(types.StringType, v.ListAttribute.Elements()) - - diags.Append(d...) + var listAttributeVal basetypes.ListValue + switch { + case v.ListAttribute.IsUnknown(): + listAttributeVal = types.ListUnknown(types.StringType) + case v.ListAttribute.IsNull(): + listAttributeVal = types.ListNull(types.StringType) + default: + var d diag.Diagnostics + listAttributeVal, d = types.ListValue(types.StringType, v.ListAttribute.Elements()) + diags.Append(d...) + } - if d.HasError() { + if diags.HasError() { return types.ObjectUnknown(map[string]attr.Type{ "list_attribute": basetypes.ListType{ ElemType: types.StringType, @@ -7749,11 +7856,19 @@ func (v ListNestedBlockThreeListNestedBlockOneValue) String() string { func (v ListNestedBlockThreeListNestedBlockOneValue) ToObjectValue(ctx context.Context) (basetypes.ObjectValue, diag.Diagnostics) { var diags diag.Diagnostics - listAttributeVal, d := types.ListValue(types.StringType, v.ListAttribute.Elements()) - - diags.Append(d...) + var listAttributeVal basetypes.ListValue + switch { + case v.ListAttribute.IsUnknown(): + listAttributeVal = types.ListUnknown(types.StringType) + case v.ListAttribute.IsNull(): + listAttributeVal = types.ListNull(types.StringType) + default: + var d diag.Diagnostics + listAttributeVal, d = types.ListValue(types.StringType, v.ListAttribute.Elements()) + diags.Append(d...) + } - if d.HasError() { + if diags.HasError() { return types.ObjectUnknown(map[string]attr.Type{ "list_attribute": basetypes.ListType{ ElemType: types.StringType, @@ -10625,11 +10740,19 @@ func (v SingleNestedBlockThreeListNestedBlockOneValue) String() string { func (v SingleNestedBlockThreeListNestedBlockOneValue) ToObjectValue(ctx context.Context) (basetypes.ObjectValue, diag.Diagnostics) { var diags diag.Diagnostics - listAttributeVal, d := types.ListValue(types.StringType, v.ListAttribute.Elements()) - - diags.Append(d...) + var listAttributeVal basetypes.ListValue + switch { + case v.ListAttribute.IsUnknown(): + listAttributeVal = types.ListUnknown(types.StringType) + case v.ListAttribute.IsNull(): + listAttributeVal = types.ListNull(types.StringType) + default: + var d diag.Diagnostics + listAttributeVal, d = types.ListValue(types.StringType, v.ListAttribute.Elements()) + diags.Append(d...) + } - if d.HasError() { + if diags.HasError() { return types.ObjectUnknown(map[string]attr.Type{ "list_attribute": basetypes.ListType{ ElemType: types.StringType, diff --git a/internal/cmd/testdata/custom_and_external/ir.json b/internal/cmd/testdata/custom_and_external/ir.json index bcd16e54..5c381bd4 100644 --- a/internal/cmd/testdata/custom_and_external/ir.json +++ b/internal/cmd/testdata/custom_and_external/ir.json @@ -188,6 +188,15 @@ "string": {} } } + }, + { + "name": "map_attribute", + "map": { + "computed_optional_required": "computed", + "element_type": { + "int64": {} + } + } } ] } diff --git a/internal/schema/custom_nested_object_test.go b/internal/schema/custom_nested_object_test.go index cc1ac108..802d5cc7 100644 --- a/internal/schema/custom_nested_object_test.go +++ b/internal/schema/custom_nested_object_test.go @@ -1325,7 +1325,7 @@ map[string]attr.Value{ return objVal, diags }`), }, - "collection-type": { + "collection-type-list": { name: "Example", attributeTypes: map[string]string{ "list_attribute": "List", @@ -1343,11 +1343,19 @@ return objVal, diags func (v ExampleValue) ToObjectValue(ctx context.Context) (basetypes.ObjectValue, diag.Diagnostics) { var diags diag.Diagnostics -listAttributeVal, d := types.ListValue(types.BoolType, v.ListAttribute.Elements()) - +var listAttributeVal basetypes.ListValue +switch { +case v.ListAttribute.IsUnknown(): +listAttributeVal = types.ListUnknown(types.BoolType) +case v.ListAttribute.IsNull(): +listAttributeVal = types.ListNull(types.BoolType) +default: +var d diag.Diagnostics +listAttributeVal, d = types.ListValue(types.BoolType, v.ListAttribute.Elements()) diags.Append(d...) +} -if d.HasError() { +if diags.HasError() { return types.ObjectUnknown(map[string]attr.Type{ "list_attribute": basetypes.ListType{ ElemType: types.BoolType, @@ -1375,6 +1383,128 @@ map[string]attr.Value{ "list_attribute": listAttributeVal, }) +return objVal, diags +}`), + }, + "collection-type-map": { + name: "Example", + attributeTypes: map[string]string{ + "map_attribute": "Map", + }, + attrTypes: map[string]string{ + "map_attribute": "basetypes.MapType{\nElemType: types.StringType,\n}", + }, + collectionTypes: map[string]map[string]string{ + "map_attribute": { + "ElementType": "types.StringType", + "TypeValueFunc": "types.MapValue", + }, + }, + expected: []byte(` +func (v ExampleValue) ToObjectValue(ctx context.Context) (basetypes.ObjectValue, diag.Diagnostics) { +var diags diag.Diagnostics + +var mapAttributeVal basetypes.MapValue +switch { +case v.MapAttribute.IsUnknown(): +mapAttributeVal = types.MapUnknown(types.StringType) +case v.MapAttribute.IsNull(): +mapAttributeVal = types.MapNull(types.StringType) +default: +var d diag.Diagnostics +mapAttributeVal, d = types.MapValue(types.StringType, v.MapAttribute.Elements()) +diags.Append(d...) +} + +if diags.HasError() { +return types.ObjectUnknown(map[string]attr.Type{ +"map_attribute": basetypes.MapType{ +ElemType: types.StringType, +}, +}), diags +} + +attributeTypes := map[string]attr.Type{ +"map_attribute": basetypes.MapType{ +ElemType: types.StringType, +}, +} + +if v.IsNull() { +return types.ObjectNull(attributeTypes), diags +} + +if v.IsUnknown() { +return types.ObjectUnknown(attributeTypes), diags +} + +objVal, diags := types.ObjectValue( +attributeTypes, +map[string]attr.Value{ +"map_attribute": mapAttributeVal, +}) + +return objVal, diags +}`), + }, + "collection-type-set": { + name: "Example", + attributeTypes: map[string]string{ + "set_attribute": "Set", + }, + attrTypes: map[string]string{ + "set_attribute": "basetypes.SetType{\nElemType: types.Int64Type,\n}", + }, + collectionTypes: map[string]map[string]string{ + "set_attribute": { + "ElementType": "types.Int64Type", + "TypeValueFunc": "types.SetValue", + }, + }, + expected: []byte(` +func (v ExampleValue) ToObjectValue(ctx context.Context) (basetypes.ObjectValue, diag.Diagnostics) { +var diags diag.Diagnostics + +var setAttributeVal basetypes.SetValue +switch { +case v.SetAttribute.IsUnknown(): +setAttributeVal = types.SetUnknown(types.Int64Type) +case v.SetAttribute.IsNull(): +setAttributeVal = types.SetNull(types.Int64Type) +default: +var d diag.Diagnostics +setAttributeVal, d = types.SetValue(types.Int64Type, v.SetAttribute.Elements()) +diags.Append(d...) +} + +if diags.HasError() { +return types.ObjectUnknown(map[string]attr.Type{ +"set_attribute": basetypes.SetType{ +ElemType: types.Int64Type, +}, +}), diags +} + +attributeTypes := map[string]attr.Type{ +"set_attribute": basetypes.SetType{ +ElemType: types.Int64Type, +}, +} + +if v.IsNull() { +return types.ObjectNull(attributeTypes), diags +} + +if v.IsUnknown() { +return types.ObjectUnknown(attributeTypes), diags +} + +objVal, diags := types.ObjectValue( +attributeTypes, +map[string]attr.Value{ +"set_attribute": setAttributeVal, +}) + return objVal, diags }`), }, @@ -1396,11 +1526,19 @@ return objVal, diags func (v ExampleValue) ToObjectValue(ctx context.Context) (basetypes.ObjectValue, diag.Diagnostics) { var diags diag.Diagnostics -typeVal, d := types.ListValue(types.BoolType, v.ExampleType.Elements()) - +var typeVal basetypes.ListValue +switch { +case v.ExampleType.IsUnknown(): +typeVal = types.ListUnknown(types.BoolType) +case v.ExampleType.IsNull(): +typeVal = types.ListNull(types.BoolType) +default: +var d diag.Diagnostics +typeVal, d = types.ListValue(types.BoolType, v.ExampleType.Elements()) diags.Append(d...) +} -if d.HasError() { +if diags.HasError() { return types.ObjectUnknown(map[string]attr.Type{ "type": basetypes.ListType{ ElemType: types.BoolType, diff --git a/internal/schema/templates/nested_object_value_to_object_value.gotmpl b/internal/schema/templates/nested_object_value_to_object_value.gotmpl index 186af9ee..ddf98ccd 100644 --- a/internal/schema/templates/nested_object_value_to_object_value.gotmpl +++ b/internal/schema/templates/nested_object_value_to_object_value.gotmpl @@ -64,11 +64,26 @@ v.{{$key.ToPascalCase}}.Attributes(), {{- end}} {{- range $key, $value := .CollectionTypes }} -{{$key.ToCamelCase}}Val, d := {{$value.TypeValueFunc}}({{$value.ElementType}}, v.{{$key.ToPrefixPascalCase $.Name}}.Elements()) +{{- $typesType := "List"}} +{{- if eq $value.TypeValueFunc "types.MapValue"}} +{{- $typesType = "Map"}} +{{- else if eq $value.TypeValueFunc "types.SetValue"}} +{{- $typesType = "Set"}} +{{- end}} +var {{$key.ToCamelCase}}Val basetypes.{{$typesType}}Value +switch { +case v.{{$key.ToPrefixPascalCase $.Name}}.IsUnknown(): +{{$key.ToCamelCase}}Val = types.{{$typesType}}Unknown({{$value.ElementType}}) +case v.{{$key.ToPrefixPascalCase $.Name}}.IsNull(): +{{$key.ToCamelCase}}Val = types.{{$typesType}}Null({{$value.ElementType}}) +default: +var d diag.Diagnostics +{{$key.ToCamelCase}}Val, d = {{$value.TypeValueFunc}}({{$value.ElementType}}, v.{{$key.ToPrefixPascalCase $.Name}}.Elements()) diags.Append(d...) +} -if d.HasError() { +if diags.HasError() { return types.ObjectUnknown(map[string]attr.Type{ {{- range $attrTypeKey, $attrTypeValue := $.AttrTypes}} "{{$attrTypeKey}}": {{$attrTypeValue}},