diff --git a/go.mod b/go.mod index c26aba8..12af97b 100644 --- a/go.mod +++ b/go.mod @@ -5,9 +5,11 @@ go 1.22.7 require ( github.com/hashicorp/go-memdb v1.3.4 github.com/hashicorp/terraform-json v0.24.0 - github.com/hashicorp/terraform-plugin-framework v1.13.0 + github.com/hashicorp/terraform-plugin-framework v1.13.1-0.20250117160114-74bb9aebdf2b + github.com/hashicorp/terraform-plugin-framework-nettypes v0.2.0 github.com/hashicorp/terraform-plugin-framework-timeouts v0.5.0 github.com/hashicorp/terraform-plugin-framework-timetypes v0.5.0 + github.com/hashicorp/terraform-plugin-framework-validators v0.16.0 github.com/hashicorp/terraform-plugin-go v0.25.0 github.com/hashicorp/terraform-plugin-mux v0.17.0 github.com/hashicorp/terraform-plugin-sdk/v2 v2.35.0 diff --git a/go.sum b/go.sum index 3376b91..41dfb02 100644 --- a/go.sum +++ b/go.sum @@ -81,12 +81,16 @@ github.com/hashicorp/terraform-exec v0.21.0 h1:uNkLAe95ey5Uux6KJdua6+cv8asgILFVW github.com/hashicorp/terraform-exec v0.21.0/go.mod h1:1PPeMYou+KDUSSeRE9szMZ/oHf4fYUmB923Wzbq1ICg= github.com/hashicorp/terraform-json v0.24.0 h1:rUiyF+x1kYawXeRth6fKFm/MdfBS6+lW4NbeATsYz8Q= github.com/hashicorp/terraform-json v0.24.0/go.mod h1:Nfj5ubo9xbu9uiAoZVBsNOjvNKB66Oyrvtit74kC7ow= -github.com/hashicorp/terraform-plugin-framework v1.13.0 h1:8OTG4+oZUfKgnfTdPTJwZ532Bh2BobF4H+yBiYJ/scw= -github.com/hashicorp/terraform-plugin-framework v1.13.0/go.mod h1:j64rwMGpgM3NYXTKuxrCnyubQb/4VKldEKlcG8cvmjU= +github.com/hashicorp/terraform-plugin-framework v1.13.1-0.20250117160114-74bb9aebdf2b h1:0QhaC0IR4fwVXuQWNZATh2B+8RURGOhDAOhdgqDyDvo= +github.com/hashicorp/terraform-plugin-framework v1.13.1-0.20250117160114-74bb9aebdf2b/go.mod h1:j64rwMGpgM3NYXTKuxrCnyubQb/4VKldEKlcG8cvmjU= +github.com/hashicorp/terraform-plugin-framework-nettypes v0.2.0 h1:Zap24rkky7SvNGGNYHMKFhAriP6+6riI21BMYOYgLRE= +github.com/hashicorp/terraform-plugin-framework-nettypes v0.2.0/go.mod h1:CYPq+I5bWsmI8021VJY85hAyOeiEEQpdGW+NapdQn7A= github.com/hashicorp/terraform-plugin-framework-timeouts v0.5.0 h1:I/N0g/eLZ1ZkLZXUQ0oRSXa8YG/EF0CEuQP1wXdrzKw= github.com/hashicorp/terraform-plugin-framework-timeouts v0.5.0/go.mod h1:t339KhmxnaF4SzdpxmqW8HnQBHVGYazwtfxU0qCs4eE= github.com/hashicorp/terraform-plugin-framework-timetypes v0.5.0 h1:v3DapR8gsp3EM8fKMh6up9cJUFQ2iRaFsYLP8UJnCco= github.com/hashicorp/terraform-plugin-framework-timetypes v0.5.0/go.mod h1:c3PnGE9pHBDfdEVG9t1S1C9ia5LW+gkFR0CygXlM8ak= +github.com/hashicorp/terraform-plugin-framework-validators v0.16.0 h1:O9QqGoYDzQT7lwTXUsZEtgabeWW96zUBh47Smn2lkFA= +github.com/hashicorp/terraform-plugin-framework-validators v0.16.0/go.mod h1:Bh89/hNmqsEWug4/XWKYBwtnw3tbz5BAy1L1OgvbIaY= github.com/hashicorp/terraform-plugin-go v0.25.0 h1:oi13cx7xXA6QciMcpcFi/rwA974rdTxjqEhXJjbAyks= github.com/hashicorp/terraform-plugin-go v0.25.0/go.mod h1:+SYagMYadJP86Kvn+TGeV+ofr/R3g4/If0O5sO96MVw= github.com/hashicorp/terraform-plugin-log v0.9.0 h1:i7hOA+vdAItN1/7UrfBqBwvYPQ9TFvymaRGZED3FCV0= diff --git a/internal/framework5provider/provider.go b/internal/framework5provider/provider.go index 76aa407..49cff44 100644 --- a/internal/framework5provider/provider.go +++ b/internal/framework5provider/provider.go @@ -91,6 +91,7 @@ func (p *testProvider) Resources(_ context.Context) []func() resource.Resource { NewTFSDKReflectionResource, NewMoveStateResource, NewSetNestedBlockWithDefaultsResource, + NewSetSemanticEqualityResource, } } diff --git a/internal/framework5provider/set_semantic_equality_resource.go b/internal/framework5provider/set_semantic_equality_resource.go new file mode 100644 index 0000000..ba6bade --- /dev/null +++ b/internal/framework5provider/set_semantic_equality_resource.go @@ -0,0 +1,137 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package framework + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-framework-nettypes/iptypes" + "github.com/hashicorp/terraform-plugin-framework-validators/setvalidator" + "github.com/hashicorp/terraform-plugin-framework/attr" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +var _ resource.Resource = SetSemanticEqualityResource{} + +func NewSetSemanticEqualityResource() resource.Resource { + return &SetSemanticEqualityResource{} +} + +// This resource tests that semantic equality for elements inside of a set are correctly executed +// Original bug: https://github.com/hashicorp/terraform-plugin-framework/issues/1061 +type SetSemanticEqualityResource struct{} + +func (r SetSemanticEqualityResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_set_semantic_equality" +} + +func (r SetSemanticEqualityResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "set_of_ipv6": schema.SetAttribute{ + ElementType: iptypes.IPv6AddressType{}, + Required: true, + }, + }, + Blocks: map[string]schema.Block{ + "set_nested_block": schema.SetNestedBlock{ + Validators: []validator.Set{ + setvalidator.IsRequired(), + }, + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "ipv6": schema.StringAttribute{ + CustomType: iptypes.IPv6AddressType{}, + Required: true, + }, + }, + }, + }, + }, + } +} + +func (r SetSemanticEqualityResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var data SetSemanticEqualityResourceModel + + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + + if resp.Diagnostics.HasError() { + return + } + + // Simulate remote API returning semantically equivalent IPv6 addresses + data.shiftAndShorten() + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (r SetSemanticEqualityResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var data SetSemanticEqualityResourceModel + + resp.Diagnostics.Append(req.State.Get(ctx, &data)...) + + if resp.Diagnostics.HasError() { + return + } + + // Simulate remote API returning semantically equivalent IPv6 addresses + data.shiftAndShorten() + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (r SetSemanticEqualityResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var data SetSemanticEqualityResourceModel + + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + + if resp.Diagnostics.HasError() { + return + } + + // Simulate remote API returning semantically equivalent IPv6 addresses + data.shiftAndShorten() + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (r SetSemanticEqualityResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { +} + +type SetSemanticEqualityResourceModel struct { + SetOfIPv6 types.Set `tfsdk:"set_of_ipv6"` + SetNestedBlock types.Set `tfsdk:"set_nested_block"` +} + +var setObjectWithIPv6 = types.ObjectType{ + AttrTypes: map[string]attr.Type{ + "ipv6": iptypes.IPv6AddressType{}, + }, +} + +// Shifts + switches data to shortened IPv6 addresses, but is semantically equal to test config +func (m *SetSemanticEqualityResourceModel) shiftAndShorten() { + m.SetOfIPv6 = types.SetValueMust(iptypes.IPv6AddressType{}, []attr.Value{ + iptypes.NewIPv6AddressValue("2001:DB8::8:800:200C:417A"), + iptypes.NewIPv6AddressValue("::FFFF:192.168.255.255"), + iptypes.NewIPv6AddressValue("::"), + iptypes.NewIPv6AddressValue("::101"), + }) + + m.SetNestedBlock = types.SetValueMust(setObjectWithIPv6, []attr.Value{ + types.ObjectValueMust(setObjectWithIPv6.AttributeTypes(), map[string]attr.Value{ + "ipv6": iptypes.NewIPv6AddressValue("::FFFF:192.168.255.255"), + }), + types.ObjectValueMust(setObjectWithIPv6.AttributeTypes(), map[string]attr.Value{ + "ipv6": iptypes.NewIPv6AddressValue("FF01::"), + }), + types.ObjectValueMust(setObjectWithIPv6.AttributeTypes(), map[string]attr.Value{ + "ipv6": iptypes.NewIPv6AddressValue("2001:DB8::8:800:200C:417A"), + }), + }) +} diff --git a/internal/framework5provider/set_semantic_equality_resource_test.go b/internal/framework5provider/set_semantic_equality_resource_test.go new file mode 100644 index 0000000..2388002 --- /dev/null +++ b/internal/framework5provider/set_semantic_equality_resource_test.go @@ -0,0 +1,99 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package framework + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-framework/providerserver" + "github.com/hashicorp/terraform-plugin-go/tfprotov5" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/plancheck" +) + +// This resource tests that semantic equality for elements inside of a set are correctly executed +// Original bug: https://github.com/hashicorp/terraform-plugin-framework/issues/1061 +func TestSetSemanticEqualityResource(t *testing.T) { + resource.UnitTest(t, resource.TestCase{ + ProtoV5ProviderFactories: map[string]func() (tfprotov5.ProviderServer, error){ + "framework": providerserver.NewProtocol5WithError(New()), + }, + Steps: []resource.TestStep{ + { + // The resource Create/Read will return semantically equal data that will cause a diff if returned to Terraform. + // The semantic equality logic in iptypes.IPv6Address allows this configuration to successfully apply. + Config: `resource "framework_set_semantic_equality" "test" { + set_of_ipv6 = [ + "0:0:0:0:0:0:0:0", + "2001:0DB8:0000:0000:0008:0800:200C:417A", + "0:0:0:0:0:0:0:101", + "0:0:0:0:0:FFFF:192.168.255.255", + ] + + set_nested_block { + ipv6 = "FF01:0:0:0:0:0:0:0" + } + set_nested_block { + ipv6 = "2001:db8::8:800:200c:417a" + } + set_nested_block { + ipv6 = "0:0:0:0:0:FFFF:192.168.255.255" + } + }`, + }, + { + // Re-ordering the set doesn't produce a diff with semantically equal hardcoded data + Config: `resource "framework_set_semantic_equality" "test" { + set_of_ipv6 = [ + "0:0:0:0:0:FFFF:192.168.255.255", + "0:0:0:0:0:0:0:0", + "2001:0DB8:0000:0000:0008:0800:200C:417A", + "0:0:0:0:0:0:0:101", + ] + + set_nested_block { + ipv6 = "0:0:0:0:0:FFFF:192.168.255.255" + } + set_nested_block { + ipv6 = "FF01:0:0:0:0:0:0:0" + } + set_nested_block { + ipv6 = "2001:db8::8:800:200c:417a" + } + }`, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction("framework_set_semantic_equality.test", plancheck.ResourceActionNoop), + }, + }, + }, + { + // User config changes will still produce a diff, but the apply will be successful with semantically equal data + Config: `resource "framework_set_semantic_equality" "test" { + set_of_ipv6 = [ + "0:0:0:0:0:FFFF:192.168.255.255", + "::", # <----------- This update will cause a diff + "2001:0DB8:0000:0000:0008:0800:200C:417A", + "0:0:0:0:0:0:0:101", + ] + + set_nested_block { + ipv6 = "0:0:0:0:0:FFFF:192.168.255.255" + } + set_nested_block { + ipv6 = "FF01::" # <----------- This update will cause a diff + } + set_nested_block { + ipv6 = "2001:db8::8:800:200c:417a" + } + }`, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction("framework_set_semantic_equality.test", plancheck.ResourceActionUpdate), + }, + }, + }, + }, + }) +} diff --git a/internal/framework6provider/provider.go b/internal/framework6provider/provider.go index e5a3df3..b405856 100644 --- a/internal/framework6provider/provider.go +++ b/internal/framework6provider/provider.go @@ -91,6 +91,7 @@ func (p *testProvider) Resources(_ context.Context) []func() resource.Resource { NewMoveStateResource, NewSetNestedBlockWithDefaultsResource, NewSetNestedAttributeWithDefaultsResource, + NewSetSemanticEqualityResource, } } diff --git a/internal/framework6provider/set_semantic_equality_resource.go b/internal/framework6provider/set_semantic_equality_resource.go new file mode 100644 index 0000000..eb7ab2b --- /dev/null +++ b/internal/framework6provider/set_semantic_equality_resource.go @@ -0,0 +1,158 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package framework + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-framework-nettypes/iptypes" + "github.com/hashicorp/terraform-plugin-framework-validators/setvalidator" + "github.com/hashicorp/terraform-plugin-framework/attr" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +var _ resource.Resource = SetSemanticEqualityResource{} + +func NewSetSemanticEqualityResource() resource.Resource { + return &SetSemanticEqualityResource{} +} + +// This resource tests that semantic equality for elements inside of a set are correctly executed +// Original bug: https://github.com/hashicorp/terraform-plugin-framework/issues/1061 +type SetSemanticEqualityResource struct{} + +func (r SetSemanticEqualityResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_set_semantic_equality" +} + +func (r SetSemanticEqualityResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "set_of_ipv6": schema.SetAttribute{ + ElementType: iptypes.IPv6AddressType{}, + Required: true, + }, + "set_nested_attribute": schema.SetNestedAttribute{ + Required: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "ipv6": schema.StringAttribute{ + CustomType: iptypes.IPv6AddressType{}, + Required: true, + }, + }, + }, + }, + }, + Blocks: map[string]schema.Block{ + "set_nested_block": schema.SetNestedBlock{ + Validators: []validator.Set{ + setvalidator.IsRequired(), + }, + NestedObject: schema.NestedBlockObject{ + Attributes: map[string]schema.Attribute{ + "ipv6": schema.StringAttribute{ + CustomType: iptypes.IPv6AddressType{}, + Required: true, + }, + }, + }, + }, + }, + } +} + +func (r SetSemanticEqualityResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var data SetSemanticEqualityResourceModel + + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + + if resp.Diagnostics.HasError() { + return + } + + // Simulate remote API returning semantically equivalent IPv6 addresses + data.shiftAndShorten() + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (r SetSemanticEqualityResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var data SetSemanticEqualityResourceModel + + resp.Diagnostics.Append(req.State.Get(ctx, &data)...) + + if resp.Diagnostics.HasError() { + return + } + + // Simulate remote API returning semantically equivalent IPv6 addresses + data.shiftAndShorten() + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (r SetSemanticEqualityResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + var data SetSemanticEqualityResourceModel + + resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...) + + if resp.Diagnostics.HasError() { + return + } + + // Simulate remote API returning semantically equivalent IPv6 addresses + data.shiftAndShorten() + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (r SetSemanticEqualityResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { +} + +type SetSemanticEqualityResourceModel struct { + SetOfIPv6 types.Set `tfsdk:"set_of_ipv6"` + SetNestedAttribute types.Set `tfsdk:"set_nested_attribute"` + SetNestedBlock types.Set `tfsdk:"set_nested_block"` +} + +var setObjectWithIPv6 = types.ObjectType{ + AttrTypes: map[string]attr.Type{ + "ipv6": iptypes.IPv6AddressType{}, + }, +} + +// Shifts + switches data to shortened IPv6 addresses, but is semantically equal to test config +func (m *SetSemanticEqualityResourceModel) shiftAndShorten() { + m.SetOfIPv6 = types.SetValueMust(iptypes.IPv6AddressType{}, []attr.Value{ + iptypes.NewIPv6AddressValue("2001:DB8::8:800:200C:417A"), + iptypes.NewIPv6AddressValue("::FFFF:192.168.255.255"), + iptypes.NewIPv6AddressValue("::"), + iptypes.NewIPv6AddressValue("::101"), + }) + + m.SetNestedBlock = types.SetValueMust(setObjectWithIPv6, []attr.Value{ + types.ObjectValueMust(setObjectWithIPv6.AttributeTypes(), map[string]attr.Value{ + "ipv6": iptypes.NewIPv6AddressValue("::FFFF:192.168.255.255"), + }), + types.ObjectValueMust(setObjectWithIPv6.AttributeTypes(), map[string]attr.Value{ + "ipv6": iptypes.NewIPv6AddressValue("FF01::"), + }), + types.ObjectValueMust(setObjectWithIPv6.AttributeTypes(), map[string]attr.Value{ + "ipv6": iptypes.NewIPv6AddressValue("2001:DB8::8:800:200C:417A"), + }), + }) + + m.SetNestedAttribute = types.SetValueMust(setObjectWithIPv6, []attr.Value{ + types.ObjectValueMust(setObjectWithIPv6.AttributeTypes(), map[string]attr.Value{ + "ipv6": iptypes.NewIPv6AddressValue("2001:1:2:3:4:5:6:7"), + }), + types.ObjectValueMust(setObjectWithIPv6.AttributeTypes(), map[string]attr.Value{ + "ipv6": iptypes.NewIPv6AddressValue("2041:0000:140F::875B:131B"), + }), + }) +} diff --git a/internal/framework6provider/set_semantic_equality_resource_test.go b/internal/framework6provider/set_semantic_equality_resource_test.go new file mode 100644 index 0000000..6d6978a --- /dev/null +++ b/internal/framework6provider/set_semantic_equality_resource_test.go @@ -0,0 +1,126 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package framework + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-framework/providerserver" + "github.com/hashicorp/terraform-plugin-go/tfprotov6" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/plancheck" +) + +// This resource tests that semantic equality for elements inside of a set are correctly executed +// Original bug: https://github.com/hashicorp/terraform-plugin-framework/issues/1061 +func TestSetSemanticEqualityResource(t *testing.T) { + resource.UnitTest(t, resource.TestCase{ + ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){ + "framework": providerserver.NewProtocol6WithError(New()), + }, + Steps: []resource.TestStep{ + { + // The resource Create/Read will return semantically equal data that will cause a diff if returned to Terraform. + // The semantic equality logic in iptypes.IPv6Address allows this configuration to successfully apply. + Config: `resource "framework_set_semantic_equality" "test" { + set_of_ipv6 = [ + "0:0:0:0:0:0:0:0", + "2001:0DB8:0000:0000:0008:0800:200C:417A", + "0:0:0:0:0:0:0:101", + "0:0:0:0:0:FFFF:192.168.255.255", + ] + + set_nested_attribute = [ + { + ipv6 = "2041:0000:140F:0000:0000:0000:875B:131B" + }, + { + ipv6 = "2001:0001:0002:0003:0004:0005:0006:0007" + }, + ] + + set_nested_block { + ipv6 = "FF01:0:0:0:0:0:0:0" + } + set_nested_block { + ipv6 = "2001:db8::8:800:200c:417a" + } + set_nested_block { + ipv6 = "0:0:0:0:0:FFFF:192.168.255.255" + } + }`, + }, + { + // Re-ordering the set doesn't produce a diff with semantically equal hardcoded data + Config: `resource "framework_set_semantic_equality" "test" { + set_of_ipv6 = [ + "0:0:0:0:0:FFFF:192.168.255.255", + "0:0:0:0:0:0:0:0", + "2001:0DB8:0000:0000:0008:0800:200C:417A", + "0:0:0:0:0:0:0:101", + ] + + set_nested_attribute = [ + { + ipv6 = "2001:0001:0002:0003:0004:0005:0006:0007" + }, + { + ipv6 = "2041:0000:140F:0000:0000:0000:875B:131B" + }, + ] + + set_nested_block { + ipv6 = "0:0:0:0:0:FFFF:192.168.255.255" + } + set_nested_block { + ipv6 = "FF01:0:0:0:0:0:0:0" + } + set_nested_block { + ipv6 = "2001:db8::8:800:200c:417a" + } + }`, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction("framework_set_semantic_equality.test", plancheck.ResourceActionNoop), + }, + }, + }, + { + // User config changes will still produce a diff, but the apply will be successful with semantically equal data + Config: `resource "framework_set_semantic_equality" "test" { + set_of_ipv6 = [ + "0:0:0:0:0:FFFF:192.168.255.255", + "::", # <----------- This update will cause a diff + "2001:0DB8:0000:0000:0008:0800:200C:417A", + "0:0:0:0:0:0:0:101", + ] + + set_nested_attribute = [ + { + ipv6 = "2001:1:2:3:4:5:6:7" # <----------- This update will cause a diff + }, + { + ipv6 = "2041:0000:140F:0000:0000:0000:875B:131B" + }, + ] + + set_nested_block { + ipv6 = "0:0:0:0:0:FFFF:192.168.255.255" + } + set_nested_block { + ipv6 = "FF01::" # <----------- This update will cause a diff + } + set_nested_block { + ipv6 = "2001:db8::8:800:200c:417a" + } + }`, + ConfigPlanChecks: resource.ConfigPlanChecks{ + PreApply: []plancheck.PlanCheck{ + plancheck.ExpectResourceAction("framework_set_semantic_equality.test", plancheck.ResourceActionUpdate), + }, + }, + }, + }, + }) +}