From b0cb3e47c6f41d5065b479c58e4e8f210fb19709 Mon Sep 17 00:00:00 2001 From: Liam Cervante Date: Fri, 2 Sep 2022 12:12:05 +0100 Subject: [PATCH 1/8] Reproducing a bug with nested sets, lists and computed values --- .../provider1/nested_resource.go | 136 ++++++++++++++++++ .../provider1/nested_resource_test.go | 41 ++++++ internal/tf6muxprovider/provider1/provider.go | 3 +- 3 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 internal/tf6muxprovider/provider1/nested_resource.go create mode 100644 internal/tf6muxprovider/provider1/nested_resource_test.go diff --git a/internal/tf6muxprovider/provider1/nested_resource.go b/internal/tf6muxprovider/provider1/nested_resource.go new file mode 100644 index 0000000..a6cb27d --- /dev/null +++ b/internal/tf6muxprovider/provider1/nested_resource.go @@ -0,0 +1,136 @@ +package provider1 + +import ( + "context" + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/provider" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/tfsdk" + "github.com/hashicorp/terraform-plugin-framework/types" + "math/rand" +) + +type resourceNestedType struct{} + +func (r resourceNestedType) NewResource(_ context.Context, p provider.Provider) (resource.Resource, diag.Diagnostics) { + return resourceNested{ + p: *(p.(*testProvider)), + }, nil +} + +func (r resourceNestedType) GetSchema(_ context.Context) (tfsdk.Schema, diag.Diagnostics) { + return tfsdk.Schema{ + Attributes: map[string]tfsdk.Attribute{ + "id": { + Type: types.StringType, + Computed: true, + PlanModifiers: []tfsdk.AttributePlanModifier{ + resource.UseStateForUnknown(), + }, + }, + }, + Blocks: map[string]tfsdk.Block{ + "set": { + Attributes: map[string]tfsdk.Attribute{ + "id": { + Type: types.StringType, + Computed: true, + Optional: true, + PlanModifiers: []tfsdk.AttributePlanModifier{ + resource.UseStateForUnknown(), + }, + }, + }, + Blocks: map[string]tfsdk.Block{ + "list": { + Attributes: map[string]tfsdk.Attribute{ + "id": { + Type: types.StringType, + Computed: true, + PlanModifiers: []tfsdk.AttributePlanModifier{ + resource.UseStateForUnknown(), + }, + }, + }, + NestingMode: tfsdk.BlockNestingModeList, + }, + }, + NestingMode: tfsdk.BlockNestingModeSet, + }, + }, + }, nil +} + +type resourceNested struct { + p testProvider +} + +var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") + +func id(n int) string { + b := make([]rune, n) + for i := range b { + b[i] = letters[rand.Intn(len(letters))] + } + return string(b) +} + +type nested struct { + Id types.String `tfsdk:"id"` + NestedItem []*NestedItem `tfsdk:"set"` +} + +type NestedItem struct { + Id types.String `tfsdk:"id"` + NestedNestedItem []*NestedNestedItem `tfsdk:"list"` +} + +type NestedNestedItem struct { + Id types.String `tfsdk:"id"` +} + +func (r resourceNested) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + nested := nested{} + diags := req.Plan.Get(ctx, &nested) + resp.Diagnostics.Append(diags...) + if diags.HasError() { + return + } + + if nested.Id.IsUnknown() { + nested.Id = types.String{Value: id(8)} + } + + for _, nst := range nested.NestedItem { + if nst.Id.IsUnknown() { + nst.Id = types.String{Value: id(8)} + } + + for _, nstnst := range nst.NestedNestedItem { + nstnst.Id = types.String{Value: id(8)} + } + } + + diags = resp.State.Set(ctx, nested) + resp.Diagnostics.Append(diags...) + if diags.HasError() { + return + } +} + +func (r resourceNested) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + resp.State.Set(ctx, req.State.Raw) +} + +func (r resourceNested) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + resp.State.Set(ctx, req.Plan.Raw) +} + +func (r resourceNested) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + resp.State.RemoveResource(ctx) +} + +func (r resourceNested) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) +} diff --git a/internal/tf6muxprovider/provider1/nested_resource_test.go b/internal/tf6muxprovider/provider1/nested_resource_test.go new file mode 100644 index 0000000..26838ca --- /dev/null +++ b/internal/tf6muxprovider/provider1/nested_resource_test.go @@ -0,0 +1,41 @@ +package provider1 + +import ( + "github.com/hashicorp/terraform-plugin-framework/providerserver" + "github.com/hashicorp/terraform-plugin-go/tfprotov6" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "testing" +) + +func TestAccResourceNested(t *testing.T) { + resource.UnitTest(t, resource.TestCase{ + ProtoV6ProviderFactories: map[string]func() (tfprotov6.ProviderServer, error){ + "tf6muxprovider": providerserver.NewProtocol6WithError(New()), + }, + Steps: []resource.TestStep{ + { + Config: configResourceNestedBasic, + }, + }, + }) +} + +const configResourceNestedBasic = ` +resource "tf6muxprovider_nested" "example" { + set { + id = "one" + + list { + + } + + list { + + } + } + + set { + id = "two" + } +} +` diff --git a/internal/tf6muxprovider/provider1/provider.go b/internal/tf6muxprovider/provider1/provider.go index 256358c..6f76771 100644 --- a/internal/tf6muxprovider/provider1/provider.go +++ b/internal/tf6muxprovider/provider1/provider.go @@ -39,7 +39,8 @@ func (p *testProvider) Configure(ctx context.Context, req provider.ConfigureRequ func (p *testProvider) GetResources(_ context.Context) (map[string]provider.ResourceType, diag.Diagnostics) { return map[string]provider.ResourceType{ - "tf6muxprovider_user1": resourceUserType{}, + "tf6muxprovider_user1": resourceUserType{}, + "tf6muxprovider_nested": resourceNestedType{}, }, nil } From 848eb1bf1cb4320527a5a8fad391188f6f7ca708 Mon Sep 17 00:00:00 2001 From: Liam Cervante Date: Fri, 2 Sep 2022 13:00:15 +0100 Subject: [PATCH 2/8] tabs vs spaces --- internal/tf6muxprovider/provider1/nested_resource_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/tf6muxprovider/provider1/nested_resource_test.go b/internal/tf6muxprovider/provider1/nested_resource_test.go index 26838ca..a5a2c82 100644 --- a/internal/tf6muxprovider/provider1/nested_resource_test.go +++ b/internal/tf6muxprovider/provider1/nested_resource_test.go @@ -27,11 +27,11 @@ resource "tf6muxprovider_nested" "example" { list { - } + } list { - } + } } set { From 7f30d7a18587de6cc4627df8df8d0654dedc008e Mon Sep 17 00:00:00 2001 From: Brian Flad Date: Tue, 13 Sep 2022 08:42:27 -0400 Subject: [PATCH 3/8] Updates for terraform-plugin-framework@v0.12.0 --- .../provider1/nested_resource.go | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/internal/tf6muxprovider/provider1/nested_resource.go b/internal/tf6muxprovider/provider1/nested_resource.go index a6cb27d..71d546c 100644 --- a/internal/tf6muxprovider/provider1/nested_resource.go +++ b/internal/tf6muxprovider/provider1/nested_resource.go @@ -2,24 +2,30 @@ package provider1 import ( "context" + "math/rand" + "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/path" - "github.com/hashicorp/terraform-plugin-framework/provider" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/tfsdk" "github.com/hashicorp/terraform-plugin-framework/types" - "math/rand" ) -type resourceNestedType struct{} +var ( + _ resource.Resource = &resourceNested{} +) -func (r resourceNestedType) NewResource(_ context.Context, p provider.Provider) (resource.Resource, diag.Diagnostics) { - return resourceNested{ - p: *(p.(*testProvider)), - }, nil +func NewNestedResource() resource.Resource { + return &resourceNested{} } -func (r resourceNestedType) GetSchema(_ context.Context) (tfsdk.Schema, diag.Diagnostics) { +type resourceNested struct{} + +func (r resourceNested) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_nested" +} + +func (r resourceNested) GetSchema(_ context.Context) (tfsdk.Schema, diag.Diagnostics) { return tfsdk.Schema{ Attributes: map[string]tfsdk.Attribute{ "id": { @@ -62,10 +68,6 @@ func (r resourceNestedType) GetSchema(_ context.Context) (tfsdk.Schema, diag.Dia }, nil } -type resourceNested struct { - p testProvider -} - var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") func id(n int) string { From f6f20375f5295ddf9f4d52e95ae6ae5e9cb9683c Mon Sep 17 00:00:00 2001 From: Liam Cervante Date: Tue, 13 Sep 2022 15:25:17 +0200 Subject: [PATCH 4/8] update to other bug --- internal/tf6muxprovider/provider1/nested_resource.go | 2 +- internal/tf6muxprovider/provider1/nested_resource_test.go | 8 -------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/internal/tf6muxprovider/provider1/nested_resource.go b/internal/tf6muxprovider/provider1/nested_resource.go index 71d546c..a7e36fa 100644 --- a/internal/tf6muxprovider/provider1/nested_resource.go +++ b/internal/tf6muxprovider/provider1/nested_resource.go @@ -62,7 +62,7 @@ func (r resourceNested) GetSchema(_ context.Context) (tfsdk.Schema, diag.Diagnos NestingMode: tfsdk.BlockNestingModeList, }, }, - NestingMode: tfsdk.BlockNestingModeSet, + NestingMode: tfsdk.BlockNestingModeList, }, }, }, nil diff --git a/internal/tf6muxprovider/provider1/nested_resource_test.go b/internal/tf6muxprovider/provider1/nested_resource_test.go index a5a2c82..20b0303 100644 --- a/internal/tf6muxprovider/provider1/nested_resource_test.go +++ b/internal/tf6muxprovider/provider1/nested_resource_test.go @@ -24,14 +24,6 @@ const configResourceNestedBasic = ` resource "tf6muxprovider_nested" "example" { set { id = "one" - - list { - - } - - list { - - } } set { From 8bfaea66de1314b16e801ea2255176f90a19fae6 Mon Sep 17 00:00:00 2001 From: Liam Cervante Date: Wed, 14 Sep 2022 10:31:53 +0200 Subject: [PATCH 5/8] second bug --- go.mod | 2 ++ internal/tf6muxprovider/provider1/nested_resource.go | 2 +- .../tf6muxprovider/provider1/nested_resource_test.go | 10 +++++++++- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index bad4407..f226479 100644 --- a/go.mod +++ b/go.mod @@ -2,6 +2,8 @@ module github.com/hashicorp/terraform-provider-corner go 1.18 +replace github.com/hashicorp/terraform-plugin-framework => ../terraform-plugin-framework + require ( github.com/hashicorp/go-memdb v1.3.3 github.com/hashicorp/terraform-plugin-framework v0.12.0 diff --git a/internal/tf6muxprovider/provider1/nested_resource.go b/internal/tf6muxprovider/provider1/nested_resource.go index a7e36fa..71d546c 100644 --- a/internal/tf6muxprovider/provider1/nested_resource.go +++ b/internal/tf6muxprovider/provider1/nested_resource.go @@ -62,7 +62,7 @@ func (r resourceNested) GetSchema(_ context.Context) (tfsdk.Schema, diag.Diagnos NestingMode: tfsdk.BlockNestingModeList, }, }, - NestingMode: tfsdk.BlockNestingModeList, + NestingMode: tfsdk.BlockNestingModeSet, }, }, }, nil diff --git a/internal/tf6muxprovider/provider1/nested_resource_test.go b/internal/tf6muxprovider/provider1/nested_resource_test.go index 20b0303..0369c98 100644 --- a/internal/tf6muxprovider/provider1/nested_resource_test.go +++ b/internal/tf6muxprovider/provider1/nested_resource_test.go @@ -24,10 +24,18 @@ const configResourceNestedBasic = ` resource "tf6muxprovider_nested" "example" { set { id = "one" + + list { + + } + + list { + + } } set { - id = "two" + } } ` From 10a2ed14c7821de46289dbcc1bee165fd10899f2 Mon Sep 17 00:00:00 2001 From: Liam Cervante Date: Wed, 14 Sep 2022 12:04:15 +0200 Subject: [PATCH 6/8] remove override --- go.mod | 2 -- 1 file changed, 2 deletions(-) diff --git a/go.mod b/go.mod index f226479..bad4407 100644 --- a/go.mod +++ b/go.mod @@ -2,8 +2,6 @@ module github.com/hashicorp/terraform-provider-corner go 1.18 -replace github.com/hashicorp/terraform-plugin-framework => ../terraform-plugin-framework - require ( github.com/hashicorp/go-memdb v1.3.3 github.com/hashicorp/terraform-plugin-framework v0.12.0 From 859a1624bd59bd70de06bea7466ae7ff5dde6260 Mon Sep 17 00:00:00 2001 From: Liam Cervante Date: Wed, 14 Sep 2022 12:05:12 +0200 Subject: [PATCH 7/8] fix indentation --- internal/tf6muxprovider/provider1/nested_resource_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/tf6muxprovider/provider1/nested_resource_test.go b/internal/tf6muxprovider/provider1/nested_resource_test.go index 0369c98..7bc9326 100644 --- a/internal/tf6muxprovider/provider1/nested_resource_test.go +++ b/internal/tf6muxprovider/provider1/nested_resource_test.go @@ -23,9 +23,9 @@ func TestAccResourceNested(t *testing.T) { const configResourceNestedBasic = ` resource "tf6muxprovider_nested" "example" { set { - id = "one" + id = "one" - list { + list { } From 9247987f0367fd7479e7757d9a0f30cadf8c6429 Mon Sep 17 00:00:00 2001 From: Liam Cervante Date: Wed, 14 Sep 2022 12:05:48 +0200 Subject: [PATCH 8/8] fix indentation --- internal/tf6muxprovider/provider1/provider.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/tf6muxprovider/provider1/provider.go b/internal/tf6muxprovider/provider1/provider.go index 73f158e..658c417 100644 --- a/internal/tf6muxprovider/provider1/provider.go +++ b/internal/tf6muxprovider/provider1/provider.go @@ -43,8 +43,8 @@ func (p *testProvider) Configure(ctx context.Context, req provider.ConfigureRequ func (p *testProvider) Resources(_ context.Context) []func() resource.Resource { return []func() resource.Resource{ - NewNestedResource, - NewUserResource, + NewNestedResource, + NewUserResource, } }