From a46d26314466807df59409087dd33e443739238f Mon Sep 17 00:00:00 2001 From: Brian Flad Date: Wed, 12 Jul 2023 12:35:54 -0400 Subject: [PATCH] internal/fwserver: Prevent PlanResourceChange panic during changed path logging (#797) Reference: https://github.com/hashicorp/terraform-plugin-framework/issues/783 Prior to the logic update: ``` --- FAIL: TestServerPlanResourceChange (0.01s) --- FAIL: TestServerPlanResourceChange/update-set-default-values (0.00s) panic: runtime error: invalid memory address or nil pointer dereference [recovered] panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x2 addr=0x18 pc=0x1043b0484] goroutine 32 [running]: testing.tRunner.func1.2({0x1048d4e60, 0x104c08f90}) /opt/homebrew/Cellar/go/1.20.5/libexec/src/testing/testing.go:1526 +0x1c8 testing.tRunner.func1() /opt/homebrew/Cellar/go/1.20.5/libexec/src/testing/testing.go:1529 +0x384 panic({0x1048d4e60, 0x104c08f90}) /opt/homebrew/Cellar/go/1.20.5/libexec/src/runtime/panic.go:884 +0x204 github.com/hashicorp/terraform-plugin-framework/internal/fwserver.(*Server).PlanResourceChange(0x140001f4a00, {0x10494ddb0, 0x14000098008}, 0x140001eeeb0, 0x14000592540) /Users/bflad/src/github.com/hashicorp/terraform-plugin-framework/internal/fwserver/server_planresourcechange.go:219 +0x19e4 github.com/hashicorp/terraform-plugin-framework/internal/fwserver_test.TestServerPlanResourceChange.func37(0x14000231860) /Users/bflad/src/github.com/hashicorp/terraform-plugin-framework/internal/fwserver/server_planresourcechange_test.go:5849 +0x70 testing.tRunner(0x14000231860, 0x140000ccde0) /opt/homebrew/Cellar/go/1.20.5/libexec/src/testing/testing.go:1576 +0x10c created by testing.(*T).Run /opt/homebrew/Cellar/go/1.20.5/libexec/src/testing/testing.go:1629 +0x368 FAIL github.com/hashicorp/terraform-plugin-framework/internal/fwserver 0.457s ``` This change verifies and handles the more critical bug fix of the panic report. The handling of defaults for set nested attributes will require further logic updates, which will be handled in a future change. --- .../unreleased/BUG FIXES-20230711-161747.yaml | 6 + .../fwschemadata/data_get_at_path_test.go | 57 + .../fwserver/server_planresourcechange.go | 8 + .../server_planresourcechange_test.go | 3045 ++++++++++++++--- 4 files changed, 2634 insertions(+), 482 deletions(-) create mode 100644 .changes/unreleased/BUG FIXES-20230711-161747.yaml diff --git a/.changes/unreleased/BUG FIXES-20230711-161747.yaml b/.changes/unreleased/BUG FIXES-20230711-161747.yaml new file mode 100644 index 000000000..29eeb5999 --- /dev/null +++ b/.changes/unreleased/BUG FIXES-20230711-161747.yaml @@ -0,0 +1,6 @@ +kind: BUG FIXES +body: 'resource: Prevented panic during planning caused by `SetNestedAttribute` with + nested attribute `Default` and multiple configured elements' +time: 2023-07-11T16:17:47.990142-04:00 +custom: + Issue: "783" diff --git a/internal/fwschemadata/data_get_at_path_test.go b/internal/fwschemadata/data_get_at_path_test.go index 30caed912..eaaa75872 100644 --- a/internal/fwschemadata/data_get_at_path_test.go +++ b/internal/fwschemadata/data_get_at_path_test.go @@ -34,6 +34,40 @@ func TestDataGetAtPath(t *testing.T) { expected any expectedDiags diag.Diagnostics }{ + "invalid-path": { + data: fwschemadata.Data{ + Schema: testschema.Schema{ + Attributes: map[string]fwschema.Attribute{ + "test": testschema.Attribute{ + Optional: true, + Type: types.StringType, + }, + }, + }, + TerraformValue: tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "test": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "test": tftypes.NewValue(tftypes.String, "test-value"), + }, + ), + }, + path: path.Root("not-test"), + target: new(string), + expected: new(string), + expectedDiags: diag.Diagnostics{ + diag.NewAttributeErrorDiagnostic( + path.Root("not-test"), + "Data Read Error", + "An unexpected error was encountered trying to retrieve type information at a given path. "+ + "This is always an error in the provider. Please report the following to the provider developer:\n\n"+ + "Error: AttributeName(\"not-test\") still remains in the path: could not find attribute or block \"not-test\" in schema", + ), + }, + }, "invalid-target": { data: fwschemadata.Data{ Schema: testschema.Schema{ @@ -104,6 +138,29 @@ func TestDataGetAtPath(t *testing.T) { ), }, }, + "TerraformValue-null": { + data: fwschemadata.Data{ + Schema: testschema.Schema{ + Attributes: map[string]fwschema.Attribute{ + "test": testschema.Attribute{ + Optional: true, + Type: types.StringType, + }, + }, + }, + TerraformValue: tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "test": tftypes.String, + }, + }, + nil, + ), + }, + path: path.Root("test"), + target: new(types.String), + expected: pointer(types.StringNull()), + }, "AttrTypeWithValidateError": { data: fwschemadata.Data{ Schema: testschema.Schema{ diff --git a/internal/fwserver/server_planresourcechange.go b/internal/fwserver/server_planresourcechange.go index fdc198eae..5d72f2301 100644 --- a/internal/fwserver/server_planresourcechange.go +++ b/internal/fwserver/server_planresourcechange.go @@ -207,6 +207,14 @@ func (s *Server) PlanResourceChange(ctx context.Context, req *PlanResourceChange _ = resp.PlannedState.GetAttribute(ctx, p, &plannedState) _ = req.PriorState.GetAttribute(ctx, p, &priorState) + // Due to ignoring diagnostics, the value may not be populated. + // Prevent the panic and show the path as changed. + if plannedState == nil { + changedPaths.Append(p) + + continue + } + if plannedState.Equal(priorState) { continue } diff --git a/internal/fwserver/server_planresourcechange_test.go b/internal/fwserver/server_planresourcechange_test.go index 8841f1d79..7fc0588a4 100644 --- a/internal/fwserver/server_planresourcechange_test.go +++ b/internal/fwserver/server_planresourcechange_test.go @@ -384,6 +384,76 @@ func TestServerPlanResourceChange(t *testing.T) { "test_computed_nested_set_attribute": tftypes.Set{ElementType: tftypes.Object{AttributeTypes: map[string]tftypes.Type{"string_attribute": tftypes.String}}}, "test_computed_nested_single": tftypes.Object{AttributeTypes: map[string]tftypes.Type{"string_attribute": tftypes.String}}, "test_computed_nested_single_attribute": tftypes.Object{AttributeTypes: map[string]tftypes.Type{"string_attribute": tftypes.String}}, + "test_configured_bool": tftypes.Bool, + "test_configured_float64": tftypes.Number, + "test_configured_int64": tftypes.Number, + "test_configured_list": tftypes.List{ElementType: tftypes.String}, + "test_configured_map": tftypes.Map{ElementType: tftypes.String}, + "test_configured_number": tftypes.Number, + "test_configured_object": tftypes.Object{AttributeTypes: map[string]tftypes.Type{"a": tftypes.String}}, + "test_configured_set": tftypes.Set{ElementType: tftypes.String}, + "test_configured_string": tftypes.String, + "test_configured_string_custom_type": tftypes.String, + "test_configured_nested_list": tftypes.List{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + }, + "test_configured_nested_list_attribute": tftypes.List{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + }, + "test_configured_nested_map": tftypes.Map{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + }, + "test_configured_nested_map_attribute": tftypes.Map{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + }, + "test_configured_nested_set": tftypes.Set{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + }, + "test_configured_nested_set_attribute": tftypes.Set{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + }, + "test_configured_nested_single": tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + "test_configured_nested_single_attribute": tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, }, } @@ -601,6 +671,265 @@ func TestServerPlanResourceChange(t *testing.T) { }, }, }, + "test_configured_bool": schema.BoolAttribute{ + Optional: true, + Default: booldefault.StaticBool(true), + }, + "test_configured_float64": schema.Float64Attribute{ + Optional: true, + Computed: true, + Default: float64default.StaticFloat64(1.2345), + }, + "test_configured_int64": schema.Int64Attribute{ + Optional: true, + Computed: true, + Default: int64default.StaticInt64(12345), + }, + "test_configured_list": schema.ListAttribute{ + Optional: true, + Computed: true, + ElementType: types.StringType, + Default: listdefault.StaticValue(types.ListValueMust(types.StringType, []attr.Value{types.StringValue("default")})), + }, + "test_configured_map": schema.MapAttribute{ + Optional: true, + Computed: true, + ElementType: types.StringType, + Default: mapdefault.StaticValue(types.MapValueMust(types.StringType, map[string]attr.Value{"a": types.StringValue("default")})), + }, + "test_configured_number": schema.NumberAttribute{ + Optional: true, + Computed: true, + Default: numberdefault.StaticBigFloat(big.NewFloat(1.2345)), + }, + "test_configured_object": schema.ObjectAttribute{ + Optional: true, + Computed: true, + AttributeTypes: map[string]attr.Type{"a": types.StringType}, + Default: objectdefault.StaticValue(types.ObjectValueMust(map[string]attr.Type{"a": types.StringType}, map[string]attr.Value{"a": types.StringValue("default")})), + }, + "test_configured_set": schema.SetAttribute{ + Optional: true, + Computed: true, + ElementType: types.StringType, + Default: setdefault.StaticValue(types.SetValueMust(types.StringType, []attr.Value{types.StringValue("default")})), + }, + "test_configured_string": schema.StringAttribute{ + Optional: true, + Computed: true, + Default: stringdefault.StaticString("one"), + }, + "test_configured_string_custom_type": schema.StringAttribute{ + Optional: true, + Computed: true, + CustomType: testtypes.StringTypeWithSemanticEquals{}, + Default: stringdefault.StaticString("one"), + }, + "test_configured_nested_list": schema.ListNestedAttribute{ + Optional: true, + Computed: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "computed_attribute": schema.StringAttribute{ + Computed: true, + Default: stringdefault.StaticString("attribute-default-value"), + }, + "configurable_attribute": schema.StringAttribute{ + Optional: true, + Computed: true, + Default: stringdefault.StaticString("attribute-default-value"), + }, + }, + }, + Default: listdefault.StaticValue( + types.ListValueMust( + types.ObjectType{ + AttrTypes: map[string]attr.Type{ + "computed_attribute": types.StringType, + "configurable_attribute": types.StringType, + }, + }, + []attr.Value{ + types.ObjectValueMust( + map[string]attr.Type{ + "computed_attribute": types.StringType, + "configurable_attribute": types.StringType, + }, + map[string]attr.Value{ + "computed_attribute": types.StringValue("list-default-value"), + "configurable_attribute": types.StringValue("list-default-value"), + }), + }, + ), + ), + }, + "test_configured_nested_list_attribute": schema.ListNestedAttribute{ + Optional: true, + Computed: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "computed_attribute": schema.StringAttribute{ + Computed: true, + Default: stringdefault.StaticString("attribute-default-value"), + }, + "configurable_attribute": schema.StringAttribute{ + Optional: true, + Computed: true, + Default: stringdefault.StaticString("attribute-default-value"), + }, + }, + }, + }, + "test_configured_nested_map": schema.MapNestedAttribute{ + Optional: true, + Computed: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "computed_attribute": schema.StringAttribute{ + Computed: true, + Default: stringdefault.StaticString("attribute-default-value"), + }, + "configurable_attribute": schema.StringAttribute{ + Optional: true, + Computed: true, + Default: stringdefault.StaticString("attribute-default-value"), + }, + }, + }, + Default: mapdefault.StaticValue( + types.MapValueMust( + types.ObjectType{ + AttrTypes: map[string]attr.Type{ + "computed_attribute": types.StringType, + "configurable_attribute": types.StringType, + }, + }, + map[string]attr.Value{ + "test-key": types.ObjectValueMust( + map[string]attr.Type{ + "computed_attribute": types.StringType, + "configurable_attribute": types.StringType, + }, + map[string]attr.Value{ + "computed_attribute": types.StringValue("map-default-value"), + "configurable_attribute": types.StringValue("map-default-value"), + }), + }, + ), + ), + }, + "test_configured_nested_map_attribute": schema.MapNestedAttribute{ + Optional: true, + Computed: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "computed_attribute": schema.StringAttribute{ + Computed: true, + Default: stringdefault.StaticString("attribute-default-value"), + }, + "configurable_attribute": schema.StringAttribute{ + Optional: true, + Computed: true, + Default: stringdefault.StaticString("attribute-default-value"), + }, + }, + }, + }, + "test_configured_nested_set": schema.SetNestedAttribute{ + Optional: true, + Computed: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "computed_attribute": schema.StringAttribute{ + Computed: true, + Default: stringdefault.StaticString("attribute-default-value"), + }, + "configurable_attribute": schema.StringAttribute{ + Optional: true, + Computed: true, + Default: stringdefault.StaticString("attribute-default-value"), + }, + }, + }, + Default: setdefault.StaticValue( + types.SetValueMust( + types.ObjectType{ + AttrTypes: map[string]attr.Type{ + "computed_attribute": types.StringType, + "configurable_attribute": types.StringType, + }, + }, + []attr.Value{ + types.ObjectValueMust( + map[string]attr.Type{ + "computed_attribute": types.StringType, + "configurable_attribute": types.StringType, + }, + map[string]attr.Value{ + "computed_attribute": types.StringValue("set-default-value"), + "configurable_attribute": types.StringValue("set-default-value"), + }), + }, + ), + ), + }, + "test_configured_nested_set_attribute": schema.SetNestedAttribute{ + Optional: true, + Computed: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "computed_attribute": schema.StringAttribute{ + Computed: true, + Default: stringdefault.StaticString("attribute-default-value"), + }, + "configurable_attribute": schema.StringAttribute{ + Optional: true, + Computed: true, + Default: stringdefault.StaticString("attribute-default-value"), + }, + }, + }, + }, + "test_configured_nested_single": schema.SingleNestedAttribute{ + Optional: true, + Computed: true, + Attributes: map[string]schema.Attribute{ + "computed_attribute": schema.StringAttribute{ + Computed: true, + Default: stringdefault.StaticString("attribute-default-value"), + }, + "configurable_attribute": schema.StringAttribute{ + Optional: true, + Computed: true, + Default: stringdefault.StaticString("attribute-default-value"), + }, + }, + Default: objectdefault.StaticValue( + types.ObjectValueMust( + map[string]attr.Type{ + "computed_attribute": types.StringType, + "configurable_attribute": types.StringType, + }, + map[string]attr.Value{ + "computed_attribute": types.StringValue("object-default-value"), + "configurable_attribute": types.StringValue("object-default-value"), + }), + ), + }, + "test_configured_nested_single_attribute": schema.SingleNestedAttribute{ + Optional: true, + Attributes: map[string]schema.Attribute{ + "computed_attribute": schema.StringAttribute{ + Computed: true, + Default: stringdefault.StaticString("attribute-default-value"), + }, + "configurable_attribute": schema.StringAttribute{ + Optional: true, + Computed: true, + Default: stringdefault.StaticString("attribute-default-value"), + }, + }, + }, }, } @@ -1055,36 +1384,42 @@ func TestServerPlanResourceChange(t *testing.T) { "string_attribute": tftypes.NewValue(tftypes.String, nil), }, ), - }), - Schema: testSchemaDefault, - }, - ProposedNewState: &tfsdk.Plan{ - Raw: tftypes.NewValue(testSchemaTypeDefault, map[string]tftypes.Value{ - "test_computed_bool": tftypes.NewValue(tftypes.Bool, nil), - "test_computed_float64": tftypes.NewValue(tftypes.Number, nil), - "test_computed_int64": tftypes.NewValue(tftypes.Number, nil), - "test_computed_list": tftypes.NewValue(tftypes.List{ElementType: tftypes.String}, nil), - "test_computed_map": tftypes.NewValue(tftypes.Map{ElementType: tftypes.String}, nil), - "test_computed_number": tftypes.NewValue(tftypes.Number, nil), - "test_computed_object": tftypes.NewValue(tftypes.Object{AttributeTypes: map[string]tftypes.Type{"a": tftypes.String}}, nil), - "test_computed_set": tftypes.NewValue(tftypes.Set{ElementType: tftypes.String}, nil), - "test_computed_string": tftypes.NewValue(tftypes.String, nil), - "test_computed_string_custom_type": tftypes.NewValue(tftypes.String, nil), - "test_computed_nested_list": tftypes.NewValue( - tftypes.List{ - ElementType: tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, - }, - }, + "test_configured_bool": tftypes.NewValue(tftypes.Bool, true), + "test_configured_float64": tftypes.NewValue(tftypes.Number, 1.2), + "test_configured_int64": tftypes.NewValue(tftypes.Number, 123), + "test_configured_list": tftypes.NewValue( + tftypes.List{ElementType: tftypes.String}, + []tftypes.Value{ + tftypes.NewValue(tftypes.String, "config-value"), }, - nil, ), - "test_computed_nested_list_attribute": tftypes.NewValue( + "test_configured_map": tftypes.NewValue( + tftypes.Map{ElementType: tftypes.String}, + map[string]tftypes.Value{ + "test-key": tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + "test_configured_number": tftypes.NewValue(tftypes.Number, 1.2), + "test_configured_object": tftypes.NewValue( + tftypes.Object{AttributeTypes: map[string]tftypes.Type{"a": tftypes.String}}, + map[string]tftypes.Value{ + "a": tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + "test_configured_set": tftypes.NewValue( + tftypes.Set{ElementType: tftypes.String}, + []tftypes.Value{ + tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + "test_configured_string": tftypes.NewValue(tftypes.String, "config-value"), + "test_configured_string_custom_type": tftypes.NewValue(tftypes.String, "config-value"), + "test_configured_nested_list": tftypes.NewValue( tftypes.List{ ElementType: tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, }, @@ -1092,24 +1427,264 @@ func TestServerPlanResourceChange(t *testing.T) { tftypes.NewValue( tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, map[string]tftypes.Value{ - "string_attribute": tftypes.NewValue(tftypes.String, nil), + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-1"), + }, + ), + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-2"), }, ), }, ), - "test_computed_nested_map": tftypes.NewValue( - tftypes.Map{ + "test_configured_nested_list_attribute": tftypes.NewValue( + tftypes.List{ ElementType: tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, }, - nil, + []tftypes.Value{ + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-1"), + }, + ), + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-2"), + }, + ), + }, + ), + "test_configured_nested_map": tftypes.NewValue( + tftypes.Map{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + }, + map[string]tftypes.Value{ + "test-key": tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + }, + ), + "test_configured_nested_map_attribute": tftypes.NewValue( + tftypes.Map{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + }, + map[string]tftypes.Value{ + "test-key": tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + }, + ), + "test_configured_nested_set": tftypes.NewValue( + tftypes.Set{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + }, + []tftypes.Value{ + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-1"), + }, + ), + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-2"), + }, + ), + }, + ), + "test_configured_nested_set_attribute": tftypes.NewValue( + tftypes.Set{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + }, + []tftypes.Value{ + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-1"), + }, + ), + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-2"), + }, + ), + }, + ), + "test_configured_nested_single": tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + "test_configured_nested_single_attribute": tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + }), + Schema: testSchemaDefault, + }, + ProposedNewState: &tfsdk.Plan{ + Raw: tftypes.NewValue(testSchemaTypeDefault, map[string]tftypes.Value{ + "test_computed_bool": tftypes.NewValue(tftypes.Bool, nil), + "test_computed_float64": tftypes.NewValue(tftypes.Number, nil), + "test_computed_int64": tftypes.NewValue(tftypes.Number, nil), + "test_computed_list": tftypes.NewValue(tftypes.List{ElementType: tftypes.String}, nil), + "test_computed_map": tftypes.NewValue(tftypes.Map{ElementType: tftypes.String}, nil), + "test_computed_number": tftypes.NewValue(tftypes.Number, nil), + "test_computed_object": tftypes.NewValue(tftypes.Object{AttributeTypes: map[string]tftypes.Type{"a": tftypes.String}}, nil), + "test_computed_set": tftypes.NewValue(tftypes.Set{ElementType: tftypes.String}, nil), + "test_computed_string": tftypes.NewValue(tftypes.String, nil), + "test_computed_string_custom_type": tftypes.NewValue(tftypes.String, nil), + "test_computed_nested_list": tftypes.NewValue( + tftypes.List{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + }, + nil, + ), + "test_computed_nested_list_attribute": tftypes.NewValue( + tftypes.List{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + }, + []tftypes.Value{ + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "string_attribute": tftypes.NewValue(tftypes.String, nil), + }, + ), + }, + ), + "test_computed_nested_map": tftypes.NewValue( + tftypes.Map{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + }, + nil, ), "test_computed_nested_map_attribute": tftypes.NewValue( tftypes.Map{ @@ -1181,31 +1756,42 @@ func TestServerPlanResourceChange(t *testing.T) { "string_attribute": tftypes.NewValue(tftypes.String, nil), }, ), - }), - Schema: testSchemaDefault, - }, - PriorState: testEmptyStateDefault, - ResourceSchema: testSchemaDefault, - Resource: &testprovider.Resource{}, - }, - expectedResponse: &fwserver.PlanResourceChangeResponse{ - PlannedState: &tfsdk.State{ - Raw: tftypes.NewValue(testSchemaTypeDefault, map[string]tftypes.Value{ - "test_computed_bool": tftypes.NewValue(tftypes.Bool, true), - "test_computed_float64": tftypes.NewValue(tftypes.Number, 1.2345), - "test_computed_int64": tftypes.NewValue(tftypes.Number, 12345), - "test_computed_list": tftypes.NewValue(tftypes.List{ElementType: tftypes.String}, []tftypes.Value{tftypes.NewValue(tftypes.String, "default")}), - "test_computed_map": tftypes.NewValue(tftypes.Map{ElementType: tftypes.String}, map[string]tftypes.Value{"a": tftypes.NewValue(tftypes.String, "default")}), - "test_computed_number": tftypes.NewValue(tftypes.Number, big.NewFloat(1.2345)), - "test_computed_object": tftypes.NewValue(tftypes.Object{AttributeTypes: map[string]tftypes.Type{"a": tftypes.String}}, map[string]tftypes.Value{"a": tftypes.NewValue(tftypes.String, "default")}), - "test_computed_set": tftypes.NewValue(tftypes.Set{ElementType: tftypes.String}, []tftypes.Value{tftypes.NewValue(tftypes.String, "default")}), - "test_computed_string": tftypes.NewValue(tftypes.String, "one"), - "test_computed_string_custom_type": tftypes.NewValue(tftypes.String, "one"), - "test_computed_nested_list": tftypes.NewValue( + "test_configured_bool": tftypes.NewValue(tftypes.Bool, true), + "test_configured_float64": tftypes.NewValue(tftypes.Number, 1.2), + "test_configured_int64": tftypes.NewValue(tftypes.Number, 123), + "test_configured_list": tftypes.NewValue( + tftypes.List{ElementType: tftypes.String}, + []tftypes.Value{ + tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + "test_configured_map": tftypes.NewValue( + tftypes.Map{ElementType: tftypes.String}, + map[string]tftypes.Value{ + "test-key": tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + "test_configured_number": tftypes.NewValue(tftypes.Number, 1.2), + "test_configured_object": tftypes.NewValue( + tftypes.Object{AttributeTypes: map[string]tftypes.Type{"a": tftypes.String}}, + map[string]tftypes.Value{ + "a": tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + "test_configured_set": tftypes.NewValue( + tftypes.Set{ElementType: tftypes.String}, + []tftypes.Value{ + tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + "test_configured_string": tftypes.NewValue(tftypes.String, "config-value"), + "test_configured_string_custom_type": tftypes.NewValue(tftypes.String, "config-value"), + "test_configured_nested_list": tftypes.NewValue( tftypes.List{ ElementType: tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, }, @@ -1213,20 +1799,35 @@ func TestServerPlanResourceChange(t *testing.T) { tftypes.NewValue( tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, map[string]tftypes.Value{ - "string_attribute": tftypes.NewValue(tftypes.String, "default"), + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-1"), + }, + ), + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-2"), }, ), }, ), - "test_computed_nested_list_attribute": tftypes.NewValue( + "test_configured_nested_list_attribute": tftypes.NewValue( tftypes.List{ ElementType: tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, }, @@ -1234,20 +1835,35 @@ func TestServerPlanResourceChange(t *testing.T) { tftypes.NewValue( tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, map[string]tftypes.Value{ - "string_attribute": tftypes.NewValue(tftypes.String, "default-attribute"), + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-1"), + }, + ), + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-2"), }, ), }, ), - "test_computed_nested_map": tftypes.NewValue( + "test_configured_nested_map": tftypes.NewValue( tftypes.Map{ ElementType: tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, }, @@ -1255,20 +1871,23 @@ func TestServerPlanResourceChange(t *testing.T) { "test-key": tftypes.NewValue( tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, map[string]tftypes.Value{ - "string_attribute": tftypes.NewValue(tftypes.String, "default"), + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value"), }, ), }, ), - "test_computed_nested_map_attribute": tftypes.NewValue( + "test_configured_nested_map_attribute": tftypes.NewValue( tftypes.Map{ ElementType: tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, }, @@ -1276,20 +1895,23 @@ func TestServerPlanResourceChange(t *testing.T) { "test-key": tftypes.NewValue( tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, map[string]tftypes.Value{ - "string_attribute": tftypes.NewValue(tftypes.String, "default-attribute"), + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value"), }, ), }, ), - "test_computed_nested_set": tftypes.NewValue( + "test_configured_nested_set": tftypes.NewValue( tftypes.Set{ ElementType: tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, }, @@ -1297,20 +1919,35 @@ func TestServerPlanResourceChange(t *testing.T) { tftypes.NewValue( tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, map[string]tftypes.Value{ - "string_attribute": tftypes.NewValue(tftypes.String, "default"), + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-1"), + }, + ), + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-2"), }, ), }, ), - "test_computed_nested_set_attribute": tftypes.NewValue( + "test_configured_nested_set_attribute": tftypes.NewValue( tftypes.Set{ ElementType: tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, }, @@ -1318,280 +1955,710 @@ func TestServerPlanResourceChange(t *testing.T) { tftypes.NewValue( tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, map[string]tftypes.Value{ - "string_attribute": tftypes.NewValue(tftypes.String, "default-attribute"), + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-1"), }, ), - }, - ), - "test_computed_nested_single": tftypes.NewValue( - tftypes.Object{ + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-2"), + }, + ), + }, + ), + "test_configured_nested_single": tftypes.NewValue( + tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, map[string]tftypes.Value{ - "string_attribute": tftypes.NewValue(tftypes.String, "default"), + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value"), }, ), - "test_computed_nested_single_attribute": tftypes.NewValue( + "test_configured_nested_single_attribute": tftypes.NewValue( tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, map[string]tftypes.Value{ - "string_attribute": tftypes.NewValue(tftypes.String, "default-attribute"), + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value"), }, ), }), Schema: testSchemaDefault, }, - PlannedPrivate: testEmptyPrivate, - }, - }, - "create-attributeplanmodifier-request-privateplan": { - server: &fwserver.Server{ - Provider: &testprovider.Provider{}, - }, - request: &fwserver.PlanResourceChangeRequest{ - Config: &tfsdk.Config{ - Raw: tftypes.NewValue(testSchemaType, map[string]tftypes.Value{ - "test_computed": tftypes.NewValue(tftypes.String, nil), - "test_required": tftypes.NewValue(tftypes.String, "test-config-value"), - }), - Schema: testSchemaAttributePlanModifierPrivatePlanRequest, - }, - ProposedNewState: &tfsdk.Plan{ - Raw: tftypes.NewValue(testSchemaType, map[string]tftypes.Value{ - "test_computed": tftypes.NewValue(tftypes.String, nil), - "test_required": tftypes.NewValue(tftypes.String, "test-config-value"), - }), - Schema: testSchemaAttributePlanModifierPrivatePlanRequest, - }, - PriorState: testEmptyState, - ResourceSchema: testSchemaAttributePlanModifierPrivatePlanRequest, - Resource: &testprovider.Resource{}, - PriorPrivate: testPrivate, - }, - expectedResponse: &fwserver.PlanResourceChangeResponse{ - PlannedState: &tfsdk.State{ - Raw: tftypes.NewValue(testSchemaType, map[string]tftypes.Value{ - "test_computed": tftypes.NewValue(tftypes.String, tftypes.UnknownValue), - "test_required": tftypes.NewValue(tftypes.String, "test-config-value"), - }), - Schema: testSchemaAttributePlanModifierPrivatePlanRequest, - }, - PlannedPrivate: testPrivate, - }, - }, - "create-attributeplanmodifier-response-attributeplan": { - server: &fwserver.Server{ - Provider: &testprovider.Provider{}, - }, - request: &fwserver.PlanResourceChangeRequest{ - Config: &tfsdk.Config{ - Raw: tftypes.NewValue(tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "test_computed": tftypes.String, - "test_other_computed": tftypes.String, - "test_required": tftypes.String, - }, - }, map[string]tftypes.Value{ - "test_computed": tftypes.NewValue(tftypes.String, nil), - "test_other_computed": tftypes.NewValue(tftypes.String, nil), - "test_required": tftypes.NewValue(tftypes.String, "test-config-value"), - }), - Schema: testSchemaAttributePlanModifierAttributePlan, - }, - ProposedNewState: &tfsdk.Plan{ - Raw: tftypes.NewValue(tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "test_computed": tftypes.String, - "test_other_computed": tftypes.String, - "test_required": tftypes.String, - }, - }, map[string]tftypes.Value{ - "test_computed": tftypes.NewValue(tftypes.String, nil), - "test_other_computed": tftypes.NewValue(tftypes.String, nil), - "test_required": tftypes.NewValue(tftypes.String, "test-config-value"), - }), - Schema: testSchemaAttributePlanModifierAttributePlan, - }, - PriorState: &tfsdk.State{ - Raw: tftypes.NewValue(tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "test_computed": tftypes.String, - "test_other_computed": tftypes.String, - "test_required": tftypes.String, - }, - }, nil), - Schema: testSchemaAttributePlanModifierAttributePlan, - }, - ResourceSchema: testSchemaAttributePlanModifierAttributePlan, - Resource: &testprovider.Resource{}, - }, - expectedResponse: &fwserver.PlanResourceChangeResponse{ - PlannedState: &tfsdk.State{ - Raw: tftypes.NewValue(tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "test_computed": tftypes.String, - "test_other_computed": tftypes.String, - "test_required": tftypes.String, - }, - }, map[string]tftypes.Value{ - "test_computed": tftypes.NewValue(tftypes.String, "test-attributeplanmodifier-value"), - "test_other_computed": tftypes.NewValue(tftypes.String, tftypes.UnknownValue), - "test_required": tftypes.NewValue(tftypes.String, "test-config-value"), - }), - Schema: testSchemaAttributePlanModifierAttributePlan, - }, - PlannedPrivate: testEmptyPrivate, - }, - }, - "create-attributeplanmodifier-response-attributeplan-custom-type": { - server: &fwserver.Server{ - Provider: &testprovider.Provider{}, - }, - request: &fwserver.PlanResourceChangeRequest{ - Config: &tfsdk.Config{ - Raw: tftypes.NewValue(tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "test_computed": tftypes.String, - "test_other_computed": tftypes.String, - "test_required": tftypes.String, - }, - }, map[string]tftypes.Value{ - "test_computed": tftypes.NewValue(tftypes.String, nil), - "test_other_computed": tftypes.NewValue(tftypes.String, nil), - "test_required": tftypes.NewValue(tftypes.String, "test-config-value"), - }), - Schema: testSchemaAttributePlanModifierAttributePlanCustomType, - }, - ProposedNewState: &tfsdk.Plan{ - Raw: tftypes.NewValue(tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "test_computed": tftypes.String, - "test_other_computed": tftypes.String, - "test_required": tftypes.String, - }, - }, map[string]tftypes.Value{ - "test_computed": tftypes.NewValue(tftypes.String, nil), - "test_other_computed": tftypes.NewValue(tftypes.String, nil), - "test_required": tftypes.NewValue(tftypes.String, "test-config-value"), - }), - Schema: testSchemaAttributePlanModifierAttributePlanCustomType, - }, - PriorState: &tfsdk.State{ - Raw: tftypes.NewValue(tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "test_computed": tftypes.String, - "test_other_computed": tftypes.String, - "test_required": tftypes.String, - }, - }, nil), - Schema: testSchemaAttributePlanModifierAttributePlanCustomType, - }, - ResourceSchema: testSchemaAttributePlanModifierAttributePlanCustomType, - Resource: &testprovider.Resource{}, - }, - expectedResponse: &fwserver.PlanResourceChangeResponse{ - PlannedState: &tfsdk.State{ - Raw: tftypes.NewValue(tftypes.Object{ - AttributeTypes: map[string]tftypes.Type{ - "test_computed": tftypes.String, - "test_other_computed": tftypes.String, - "test_required": tftypes.String, - }, - }, map[string]tftypes.Value{ - "test_computed": tftypes.NewValue(tftypes.String, "test-attributeplanmodifier-value"), - "test_other_computed": tftypes.NewValue(tftypes.String, tftypes.UnknownValue), - "test_required": tftypes.NewValue(tftypes.String, "test-config-value"), - }), - Schema: testSchemaAttributePlanModifierAttributePlanCustomType, - }, - PlannedPrivate: testEmptyPrivate, - }, - }, - "create-attributeplanmodifier-response-privateplan": { - server: &fwserver.Server{ - Provider: &testprovider.Provider{}, - }, - request: &fwserver.PlanResourceChangeRequest{ - Config: &tfsdk.Config{ - Raw: tftypes.NewValue(testSchemaType, map[string]tftypes.Value{ - "test_computed": tftypes.NewValue(tftypes.String, nil), - "test_required": tftypes.NewValue(tftypes.String, "test-config-value"), - }), - Schema: testSchemaAttributePlanModifierPrivatePlanResponse, - }, - ProposedNewState: &tfsdk.Plan{ - Raw: tftypes.NewValue(testSchemaType, map[string]tftypes.Value{ - "test_computed": tftypes.NewValue(tftypes.String, nil), - "test_required": tftypes.NewValue(tftypes.String, "test-config-value"), - }), - Schema: testSchemaAttributePlanModifierPrivatePlanResponse, - }, - PriorState: testEmptyState, - ResourceSchema: testSchemaAttributePlanModifierPrivatePlanResponse, - Resource: &testprovider.Resource{}, - }, - expectedResponse: &fwserver.PlanResourceChangeResponse{ - PlannedState: &tfsdk.State{ - Raw: tftypes.NewValue(testSchemaType, map[string]tftypes.Value{ - "test_computed": tftypes.NewValue(tftypes.String, tftypes.UnknownValue), - "test_required": tftypes.NewValue(tftypes.String, "test-config-value"), - }), - Schema: testSchemaAttributePlanModifierPrivatePlanResponse, - }, - PlannedPrivate: testPrivateProvider, - }, - }, - "create-attributeplanmodifier-response-diagnostics": { - server: &fwserver.Server{ - Provider: &testprovider.Provider{}, - }, - request: &fwserver.PlanResourceChangeRequest{ - Config: &tfsdk.Config{ - Raw: tftypes.NewValue(testSchemaType, map[string]tftypes.Value{ - "test_computed": tftypes.NewValue(tftypes.String, nil), - "test_required": tftypes.NewValue(tftypes.String, "test-config-value"), - }), - Schema: testSchemaAttributePlanModifierDiagnosticsError, - }, - ProposedNewState: &tfsdk.Plan{ - Raw: tftypes.NewValue(testSchemaType, map[string]tftypes.Value{ - "test_computed": tftypes.NewValue(tftypes.String, nil), - "test_required": tftypes.NewValue(tftypes.String, "test-config-value"), - }), - Schema: testSchemaAttributePlanModifierDiagnosticsError, - }, - PriorState: testEmptyState, - ResourceSchema: testSchemaAttributePlanModifierDiagnosticsError, + PriorState: testEmptyStateDefault, + ResourceSchema: testSchemaDefault, Resource: &testprovider.Resource{}, }, expectedResponse: &fwserver.PlanResourceChangeResponse{ - Diagnostics: diag.Diagnostics{ - diag.WithPath( - path.Root("test_required"), - diag.NewErrorDiagnostic("error summary", "error detail"), - ), - }, PlannedState: &tfsdk.State{ - Raw: tftypes.NewValue(testSchemaType, map[string]tftypes.Value{ - "test_computed": tftypes.NewValue(tftypes.String, tftypes.UnknownValue), - "test_required": tftypes.NewValue(tftypes.String, "test-config-value"), - }), - Schema: testSchemaAttributePlanModifierDiagnosticsError, - }, - PlannedPrivate: testEmptyPrivate, - }, - }, - "create-attributeplanmodifier-response-requiresreplace": { - server: &fwserver.Server{ + Raw: tftypes.NewValue(testSchemaTypeDefault, map[string]tftypes.Value{ + "test_computed_bool": tftypes.NewValue(tftypes.Bool, true), + "test_computed_float64": tftypes.NewValue(tftypes.Number, 1.2345), + "test_computed_int64": tftypes.NewValue(tftypes.Number, 12345), + "test_computed_list": tftypes.NewValue(tftypes.List{ElementType: tftypes.String}, []tftypes.Value{tftypes.NewValue(tftypes.String, "default")}), + "test_computed_map": tftypes.NewValue(tftypes.Map{ElementType: tftypes.String}, map[string]tftypes.Value{"a": tftypes.NewValue(tftypes.String, "default")}), + "test_computed_number": tftypes.NewValue(tftypes.Number, big.NewFloat(1.2345)), + "test_computed_object": tftypes.NewValue(tftypes.Object{AttributeTypes: map[string]tftypes.Type{"a": tftypes.String}}, map[string]tftypes.Value{"a": tftypes.NewValue(tftypes.String, "default")}), + "test_computed_set": tftypes.NewValue(tftypes.Set{ElementType: tftypes.String}, []tftypes.Value{tftypes.NewValue(tftypes.String, "default")}), + "test_computed_string": tftypes.NewValue(tftypes.String, "one"), + "test_computed_string_custom_type": tftypes.NewValue(tftypes.String, "one"), + "test_computed_nested_list": tftypes.NewValue( + tftypes.List{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + }, + []tftypes.Value{ + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "string_attribute": tftypes.NewValue(tftypes.String, "default"), + }, + ), + }, + ), + "test_computed_nested_list_attribute": tftypes.NewValue( + tftypes.List{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + }, + []tftypes.Value{ + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "string_attribute": tftypes.NewValue(tftypes.String, "default-attribute"), + }, + ), + }, + ), + "test_computed_nested_map": tftypes.NewValue( + tftypes.Map{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + }, + map[string]tftypes.Value{ + "test-key": tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "string_attribute": tftypes.NewValue(tftypes.String, "default"), + }, + ), + }, + ), + "test_computed_nested_map_attribute": tftypes.NewValue( + tftypes.Map{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + }, + map[string]tftypes.Value{ + "test-key": tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "string_attribute": tftypes.NewValue(tftypes.String, "default-attribute"), + }, + ), + }, + ), + "test_computed_nested_set": tftypes.NewValue( + tftypes.Set{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + }, + []tftypes.Value{ + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "string_attribute": tftypes.NewValue(tftypes.String, "default"), + }, + ), + }, + ), + "test_computed_nested_set_attribute": tftypes.NewValue( + tftypes.Set{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + }, + []tftypes.Value{ + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "string_attribute": tftypes.NewValue(tftypes.String, "default-attribute"), + }, + ), + }, + ), + "test_computed_nested_single": tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "string_attribute": tftypes.NewValue(tftypes.String, "default"), + }, + ), + "test_computed_nested_single_attribute": tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "string_attribute": tftypes.NewValue(tftypes.String, "default-attribute"), + }, + ), + "test_configured_bool": tftypes.NewValue(tftypes.Bool, true), + "test_configured_float64": tftypes.NewValue(tftypes.Number, 1.2), + "test_configured_int64": tftypes.NewValue(tftypes.Number, 123), + "test_configured_list": tftypes.NewValue( + tftypes.List{ElementType: tftypes.String}, + []tftypes.Value{ + tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + "test_configured_map": tftypes.NewValue( + tftypes.Map{ElementType: tftypes.String}, + map[string]tftypes.Value{ + "test-key": tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + "test_configured_number": tftypes.NewValue(tftypes.Number, 1.2), + "test_configured_object": tftypes.NewValue( + tftypes.Object{AttributeTypes: map[string]tftypes.Type{"a": tftypes.String}}, + map[string]tftypes.Value{ + "a": tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + "test_configured_set": tftypes.NewValue( + tftypes.Set{ElementType: tftypes.String}, + []tftypes.Value{ + tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + "test_configured_string": tftypes.NewValue(tftypes.String, "config-value"), + "test_configured_string_custom_type": tftypes.NewValue(tftypes.String, "config-value"), + "test_configured_nested_list": tftypes.NewValue( + tftypes.List{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + }, + []tftypes.Value{ + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, "attribute-default-value"), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-1"), + }, + ), + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, "attribute-default-value"), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-2"), + }, + ), + }, + ), + "test_configured_nested_list_attribute": tftypes.NewValue( + tftypes.List{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + }, + []tftypes.Value{ + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, "attribute-default-value"), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-1"), + }, + ), + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, "attribute-default-value"), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-2"), + }, + ), + }, + ), + "test_configured_nested_map": tftypes.NewValue( + tftypes.Map{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + }, + map[string]tftypes.Value{ + "test-key": tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, "attribute-default-value"), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + }, + ), + "test_configured_nested_map_attribute": tftypes.NewValue( + tftypes.Map{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + }, + map[string]tftypes.Value{ + "test-key": tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, "attribute-default-value"), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + }, + ), + "test_configured_nested_set": tftypes.NewValue( + tftypes.Set{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + }, + []tftypes.Value{ + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, "attribute-default-value"), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-1"), + }, + ), + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, "attribute-default-value"), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-2"), + }, + ), + }, + ), + "test_configured_nested_set_attribute": tftypes.NewValue( + tftypes.Set{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + }, + []tftypes.Value{ + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, "attribute-default-value"), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-1"), + }, + ), + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, "attribute-default-value"), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-2"), + }, + ), + }, + ), + "test_configured_nested_single": tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, "attribute-default-value"), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + "test_configured_nested_single_attribute": tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, "attribute-default-value"), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + }), + Schema: testSchemaDefault, + }, + PlannedPrivate: testEmptyPrivate, + }, + }, + "create-attributeplanmodifier-request-privateplan": { + server: &fwserver.Server{ + Provider: &testprovider.Provider{}, + }, + request: &fwserver.PlanResourceChangeRequest{ + Config: &tfsdk.Config{ + Raw: tftypes.NewValue(testSchemaType, map[string]tftypes.Value{ + "test_computed": tftypes.NewValue(tftypes.String, nil), + "test_required": tftypes.NewValue(tftypes.String, "test-config-value"), + }), + Schema: testSchemaAttributePlanModifierPrivatePlanRequest, + }, + ProposedNewState: &tfsdk.Plan{ + Raw: tftypes.NewValue(testSchemaType, map[string]tftypes.Value{ + "test_computed": tftypes.NewValue(tftypes.String, nil), + "test_required": tftypes.NewValue(tftypes.String, "test-config-value"), + }), + Schema: testSchemaAttributePlanModifierPrivatePlanRequest, + }, + PriorState: testEmptyState, + ResourceSchema: testSchemaAttributePlanModifierPrivatePlanRequest, + Resource: &testprovider.Resource{}, + PriorPrivate: testPrivate, + }, + expectedResponse: &fwserver.PlanResourceChangeResponse{ + PlannedState: &tfsdk.State{ + Raw: tftypes.NewValue(testSchemaType, map[string]tftypes.Value{ + "test_computed": tftypes.NewValue(tftypes.String, tftypes.UnknownValue), + "test_required": tftypes.NewValue(tftypes.String, "test-config-value"), + }), + Schema: testSchemaAttributePlanModifierPrivatePlanRequest, + }, + PlannedPrivate: testPrivate, + }, + }, + "create-attributeplanmodifier-response-attributeplan": { + server: &fwserver.Server{ + Provider: &testprovider.Provider{}, + }, + request: &fwserver.PlanResourceChangeRequest{ + Config: &tfsdk.Config{ + Raw: tftypes.NewValue(tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "test_computed": tftypes.String, + "test_other_computed": tftypes.String, + "test_required": tftypes.String, + }, + }, map[string]tftypes.Value{ + "test_computed": tftypes.NewValue(tftypes.String, nil), + "test_other_computed": tftypes.NewValue(tftypes.String, nil), + "test_required": tftypes.NewValue(tftypes.String, "test-config-value"), + }), + Schema: testSchemaAttributePlanModifierAttributePlan, + }, + ProposedNewState: &tfsdk.Plan{ + Raw: tftypes.NewValue(tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "test_computed": tftypes.String, + "test_other_computed": tftypes.String, + "test_required": tftypes.String, + }, + }, map[string]tftypes.Value{ + "test_computed": tftypes.NewValue(tftypes.String, nil), + "test_other_computed": tftypes.NewValue(tftypes.String, nil), + "test_required": tftypes.NewValue(tftypes.String, "test-config-value"), + }), + Schema: testSchemaAttributePlanModifierAttributePlan, + }, + PriorState: &tfsdk.State{ + Raw: tftypes.NewValue(tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "test_computed": tftypes.String, + "test_other_computed": tftypes.String, + "test_required": tftypes.String, + }, + }, nil), + Schema: testSchemaAttributePlanModifierAttributePlan, + }, + ResourceSchema: testSchemaAttributePlanModifierAttributePlan, + Resource: &testprovider.Resource{}, + }, + expectedResponse: &fwserver.PlanResourceChangeResponse{ + PlannedState: &tfsdk.State{ + Raw: tftypes.NewValue(tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "test_computed": tftypes.String, + "test_other_computed": tftypes.String, + "test_required": tftypes.String, + }, + }, map[string]tftypes.Value{ + "test_computed": tftypes.NewValue(tftypes.String, "test-attributeplanmodifier-value"), + "test_other_computed": tftypes.NewValue(tftypes.String, tftypes.UnknownValue), + "test_required": tftypes.NewValue(tftypes.String, "test-config-value"), + }), + Schema: testSchemaAttributePlanModifierAttributePlan, + }, + PlannedPrivate: testEmptyPrivate, + }, + }, + "create-attributeplanmodifier-response-attributeplan-custom-type": { + server: &fwserver.Server{ + Provider: &testprovider.Provider{}, + }, + request: &fwserver.PlanResourceChangeRequest{ + Config: &tfsdk.Config{ + Raw: tftypes.NewValue(tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "test_computed": tftypes.String, + "test_other_computed": tftypes.String, + "test_required": tftypes.String, + }, + }, map[string]tftypes.Value{ + "test_computed": tftypes.NewValue(tftypes.String, nil), + "test_other_computed": tftypes.NewValue(tftypes.String, nil), + "test_required": tftypes.NewValue(tftypes.String, "test-config-value"), + }), + Schema: testSchemaAttributePlanModifierAttributePlanCustomType, + }, + ProposedNewState: &tfsdk.Plan{ + Raw: tftypes.NewValue(tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "test_computed": tftypes.String, + "test_other_computed": tftypes.String, + "test_required": tftypes.String, + }, + }, map[string]tftypes.Value{ + "test_computed": tftypes.NewValue(tftypes.String, nil), + "test_other_computed": tftypes.NewValue(tftypes.String, nil), + "test_required": tftypes.NewValue(tftypes.String, "test-config-value"), + }), + Schema: testSchemaAttributePlanModifierAttributePlanCustomType, + }, + PriorState: &tfsdk.State{ + Raw: tftypes.NewValue(tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "test_computed": tftypes.String, + "test_other_computed": tftypes.String, + "test_required": tftypes.String, + }, + }, nil), + Schema: testSchemaAttributePlanModifierAttributePlanCustomType, + }, + ResourceSchema: testSchemaAttributePlanModifierAttributePlanCustomType, + Resource: &testprovider.Resource{}, + }, + expectedResponse: &fwserver.PlanResourceChangeResponse{ + PlannedState: &tfsdk.State{ + Raw: tftypes.NewValue(tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "test_computed": tftypes.String, + "test_other_computed": tftypes.String, + "test_required": tftypes.String, + }, + }, map[string]tftypes.Value{ + "test_computed": tftypes.NewValue(tftypes.String, "test-attributeplanmodifier-value"), + "test_other_computed": tftypes.NewValue(tftypes.String, tftypes.UnknownValue), + "test_required": tftypes.NewValue(tftypes.String, "test-config-value"), + }), + Schema: testSchemaAttributePlanModifierAttributePlanCustomType, + }, + PlannedPrivate: testEmptyPrivate, + }, + }, + "create-attributeplanmodifier-response-privateplan": { + server: &fwserver.Server{ + Provider: &testprovider.Provider{}, + }, + request: &fwserver.PlanResourceChangeRequest{ + Config: &tfsdk.Config{ + Raw: tftypes.NewValue(testSchemaType, map[string]tftypes.Value{ + "test_computed": tftypes.NewValue(tftypes.String, nil), + "test_required": tftypes.NewValue(tftypes.String, "test-config-value"), + }), + Schema: testSchemaAttributePlanModifierPrivatePlanResponse, + }, + ProposedNewState: &tfsdk.Plan{ + Raw: tftypes.NewValue(testSchemaType, map[string]tftypes.Value{ + "test_computed": tftypes.NewValue(tftypes.String, nil), + "test_required": tftypes.NewValue(tftypes.String, "test-config-value"), + }), + Schema: testSchemaAttributePlanModifierPrivatePlanResponse, + }, + PriorState: testEmptyState, + ResourceSchema: testSchemaAttributePlanModifierPrivatePlanResponse, + Resource: &testprovider.Resource{}, + }, + expectedResponse: &fwserver.PlanResourceChangeResponse{ + PlannedState: &tfsdk.State{ + Raw: tftypes.NewValue(testSchemaType, map[string]tftypes.Value{ + "test_computed": tftypes.NewValue(tftypes.String, tftypes.UnknownValue), + "test_required": tftypes.NewValue(tftypes.String, "test-config-value"), + }), + Schema: testSchemaAttributePlanModifierPrivatePlanResponse, + }, + PlannedPrivate: testPrivateProvider, + }, + }, + "create-attributeplanmodifier-response-diagnostics": { + server: &fwserver.Server{ + Provider: &testprovider.Provider{}, + }, + request: &fwserver.PlanResourceChangeRequest{ + Config: &tfsdk.Config{ + Raw: tftypes.NewValue(testSchemaType, map[string]tftypes.Value{ + "test_computed": tftypes.NewValue(tftypes.String, nil), + "test_required": tftypes.NewValue(tftypes.String, "test-config-value"), + }), + Schema: testSchemaAttributePlanModifierDiagnosticsError, + }, + ProposedNewState: &tfsdk.Plan{ + Raw: tftypes.NewValue(testSchemaType, map[string]tftypes.Value{ + "test_computed": tftypes.NewValue(tftypes.String, nil), + "test_required": tftypes.NewValue(tftypes.String, "test-config-value"), + }), + Schema: testSchemaAttributePlanModifierDiagnosticsError, + }, + PriorState: testEmptyState, + ResourceSchema: testSchemaAttributePlanModifierDiagnosticsError, + Resource: &testprovider.Resource{}, + }, + expectedResponse: &fwserver.PlanResourceChangeResponse{ + Diagnostics: diag.Diagnostics{ + diag.WithPath( + path.Root("test_required"), + diag.NewErrorDiagnostic("error summary", "error detail"), + ), + }, + PlannedState: &tfsdk.State{ + Raw: tftypes.NewValue(testSchemaType, map[string]tftypes.Value{ + "test_computed": tftypes.NewValue(tftypes.String, tftypes.UnknownValue), + "test_required": tftypes.NewValue(tftypes.String, "test-config-value"), + }), + Schema: testSchemaAttributePlanModifierDiagnosticsError, + }, + PlannedPrivate: testEmptyPrivate, + }, + }, + "create-attributeplanmodifier-response-requiresreplace": { + server: &fwserver.Server{ Provider: &testprovider.Provider{}, }, request: &fwserver.PlanResourceChangeRequest{ @@ -2398,53 +3465,801 @@ func TestServerPlanResourceChange(t *testing.T) { "test_computed": tftypes.NewValue(tftypes.String, nil), "test_required": tftypes.NewValue(tftypes.String, "test-new-value"), }), - Schema: testSchema, + Schema: testSchema, + }, + ProposedNewState: &tfsdk.Plan{ + Raw: tftypes.NewValue(testSchemaType, map[string]tftypes.Value{ + "test_computed": tftypes.NewValue(tftypes.String, nil), + "test_required": tftypes.NewValue(tftypes.String, "test-new-value"), + }), + Schema: testSchema, + }, + PriorState: &tfsdk.State{ + Raw: tftypes.NewValue(testSchemaType, map[string]tftypes.Value{ + "test_computed": tftypes.NewValue(tftypes.String, nil), + "test_required": tftypes.NewValue(tftypes.String, "test-old-value"), + }), + Schema: testSchema, + }, + ResourceSchema: testSchema, + Resource: &testprovider.Resource{}, + }, + expectedResponse: &fwserver.PlanResourceChangeResponse{ + PlannedState: &tfsdk.State{ + Raw: tftypes.NewValue(testSchemaType, map[string]tftypes.Value{ + "test_computed": tftypes.NewValue(tftypes.String, tftypes.UnknownValue), + "test_required": tftypes.NewValue(tftypes.String, "test-new-value"), + }), + Schema: testSchema, + }, + PlannedPrivate: testEmptyPrivate, + }, + }, + "update-set-default-values": { + server: &fwserver.Server{ + Provider: &testprovider.Provider{}, + }, + request: &fwserver.PlanResourceChangeRequest{ + Config: &tfsdk.Config{ + Raw: tftypes.NewValue(testSchemaTypeDefault, map[string]tftypes.Value{ + "test_computed_bool": tftypes.NewValue(tftypes.Bool, nil), + "test_computed_float64": tftypes.NewValue(tftypes.Number, nil), + "test_computed_int64": tftypes.NewValue(tftypes.Number, nil), + "test_computed_list": tftypes.NewValue(tftypes.List{ElementType: tftypes.String}, nil), + "test_computed_map": tftypes.NewValue(tftypes.Map{ElementType: tftypes.String}, nil), + "test_computed_number": tftypes.NewValue(tftypes.Number, nil), + "test_computed_object": tftypes.NewValue(tftypes.Object{AttributeTypes: map[string]tftypes.Type{"a": tftypes.String}}, nil), + "test_computed_set": tftypes.NewValue(tftypes.Set{ElementType: tftypes.String}, nil), + "test_computed_string": tftypes.NewValue(tftypes.String, nil), + "test_computed_string_custom_type": tftypes.NewValue(tftypes.String, nil), + "test_computed_nested_list": tftypes.NewValue( + tftypes.List{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + }, + nil, + ), + "test_computed_nested_list_attribute": tftypes.NewValue( + tftypes.List{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + }, + []tftypes.Value{ + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "string_attribute": tftypes.NewValue(tftypes.String, nil), + }, + ), + }, + ), + "test_computed_nested_map": tftypes.NewValue( + tftypes.Map{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + }, + nil, + ), + "test_computed_nested_map_attribute": tftypes.NewValue( + tftypes.Map{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + }, + map[string]tftypes.Value{ + "test-key": tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "string_attribute": tftypes.NewValue(tftypes.String, nil), + }, + ), + }, + ), + "test_computed_nested_set": tftypes.NewValue( + tftypes.Set{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + }, + nil, + ), + "test_computed_nested_set_attribute": tftypes.NewValue( + tftypes.Set{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + }, + []tftypes.Value{ + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "string_attribute": tftypes.NewValue(tftypes.String, nil), + }, + ), + }, + ), + "test_computed_nested_single": tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + nil, + ), + "test_computed_nested_single_attribute": tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "string_attribute": tftypes.NewValue(tftypes.String, nil), + }, + ), + "test_configured_bool": tftypes.NewValue(tftypes.Bool, true), + "test_configured_float64": tftypes.NewValue(tftypes.Number, 1.2), + "test_configured_int64": tftypes.NewValue(tftypes.Number, 123), + "test_configured_list": tftypes.NewValue( + tftypes.List{ElementType: tftypes.String}, + []tftypes.Value{ + tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + "test_configured_map": tftypes.NewValue( + tftypes.Map{ElementType: tftypes.String}, + map[string]tftypes.Value{ + "test-key": tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + "test_configured_number": tftypes.NewValue(tftypes.Number, 1.2), + "test_configured_object": tftypes.NewValue( + tftypes.Object{AttributeTypes: map[string]tftypes.Type{"a": tftypes.String}}, + map[string]tftypes.Value{ + "a": tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + "test_configured_set": tftypes.NewValue( + tftypes.Set{ElementType: tftypes.String}, + []tftypes.Value{ + tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + "test_configured_string": tftypes.NewValue(tftypes.String, "config-value"), + "test_configured_string_custom_type": tftypes.NewValue(tftypes.String, "config-value"), + "test_configured_nested_list": tftypes.NewValue( + tftypes.List{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + }, + []tftypes.Value{ + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-1"), + }, + ), + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-2"), + }, + ), + }, + ), + "test_configured_nested_list_attribute": tftypes.NewValue( + tftypes.List{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + }, + []tftypes.Value{ + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-1"), + }, + ), + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-2"), + }, + ), + }, + ), + "test_configured_nested_map": tftypes.NewValue( + tftypes.Map{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + }, + map[string]tftypes.Value{ + "test-key": tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + }, + ), + "test_configured_nested_map_attribute": tftypes.NewValue( + tftypes.Map{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + }, + map[string]tftypes.Value{ + "test-key": tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + }, + ), + "test_configured_nested_set": tftypes.NewValue( + tftypes.Set{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + }, + []tftypes.Value{ + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-1"), + }, + ), + // TODO: Prevent random attributes map access from causing flaky test + // Reference: https://github.com/hashicorp/terraform-plugin-framework/issues/783 + // tftypes.NewValue( + // tftypes.Object{ + // AttributeTypes: map[string]tftypes.Type{ + // "computed_attribute": tftypes.String, + // "configurable_attribute": tftypes.String, + // }, + // }, + // map[string]tftypes.Value{ + // "computed_attribute": tftypes.NewValue(tftypes.String, nil), + // "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-2"), + // }, + // ), + }, + ), + "test_configured_nested_set_attribute": tftypes.NewValue( + tftypes.Set{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + }, + []tftypes.Value{ + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-1"), + }, + ), + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-2"), + }, + ), + }, + ), + "test_configured_nested_single": tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + "test_configured_nested_single_attribute": tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, nil), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + }), + Schema: testSchemaDefault, }, ProposedNewState: &tfsdk.Plan{ - Raw: tftypes.NewValue(testSchemaType, map[string]tftypes.Value{ - "test_computed": tftypes.NewValue(tftypes.String, nil), - "test_required": tftypes.NewValue(tftypes.String, "test-new-value"), + Raw: tftypes.NewValue(testSchemaTypeDefault, map[string]tftypes.Value{ + "test_computed_bool": tftypes.NewValue(tftypes.Bool, nil), + "test_computed_float64": tftypes.NewValue(tftypes.Number, nil), + "test_computed_int64": tftypes.NewValue(tftypes.Number, nil), + "test_computed_list": tftypes.NewValue(tftypes.List{ElementType: tftypes.String}, nil), + "test_computed_map": tftypes.NewValue(tftypes.Map{ElementType: tftypes.String}, nil), + "test_computed_number": tftypes.NewValue(tftypes.Number, nil), + "test_computed_object": tftypes.NewValue(tftypes.Object{AttributeTypes: map[string]tftypes.Type{"a": tftypes.String}}, nil), + "test_computed_set": tftypes.NewValue(tftypes.Set{ElementType: tftypes.String}, nil), + "test_computed_string": tftypes.NewValue(tftypes.String, nil), + "test_computed_string_custom_type": tftypes.NewValue(tftypes.String, nil), + "test_computed_nested_list": tftypes.NewValue( + tftypes.List{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + }, + nil, + ), + "test_computed_nested_list_attribute": tftypes.NewValue( + tftypes.List{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + }, + []tftypes.Value{ + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "string_attribute": tftypes.NewValue(tftypes.String, nil), + }, + ), + }, + ), + "test_computed_nested_map": tftypes.NewValue( + tftypes.Map{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + }, + nil, + ), + "test_computed_nested_map_attribute": tftypes.NewValue( + tftypes.Map{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + }, + map[string]tftypes.Value{ + "test-key": tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "string_attribute": tftypes.NewValue(tftypes.String, nil), + }, + ), + }, + ), + "test_computed_nested_set": tftypes.NewValue( + tftypes.Set{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + }, + nil, + ), + "test_computed_nested_set_attribute": tftypes.NewValue( + tftypes.Set{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + }, + []tftypes.Value{ + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "string_attribute": tftypes.NewValue(tftypes.String, nil), + }, + ), + }, + ), + "test_computed_nested_single": tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + nil, + ), + "test_computed_nested_single_attribute": tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "string_attribute": tftypes.NewValue(tftypes.String, nil), + }, + ), + "test_configured_bool": tftypes.NewValue(tftypes.Bool, true), + "test_configured_float64": tftypes.NewValue(tftypes.Number, 1.2), + "test_configured_int64": tftypes.NewValue(tftypes.Number, 123), + "test_configured_list": tftypes.NewValue( + tftypes.List{ElementType: tftypes.String}, + []tftypes.Value{ + tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + "test_configured_map": tftypes.NewValue( + tftypes.Map{ElementType: tftypes.String}, + map[string]tftypes.Value{ + "test-key": tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + "test_configured_number": tftypes.NewValue(tftypes.Number, 1.2), + "test_configured_object": tftypes.NewValue( + tftypes.Object{AttributeTypes: map[string]tftypes.Type{"a": tftypes.String}}, + map[string]tftypes.Value{ + "a": tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + "test_configured_set": tftypes.NewValue( + tftypes.Set{ElementType: tftypes.String}, + []tftypes.Value{ + tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + "test_configured_string": tftypes.NewValue(tftypes.String, "config-value"), + "test_configured_string_custom_type": tftypes.NewValue(tftypes.String, "config-value"), + "test_configured_nested_list": tftypes.NewValue( + tftypes.List{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + }, + []tftypes.Value{ + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, "state-value-element-1"), // Terraform core behavior + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-1"), + }, + ), + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, "state-value-element-2"), // Terraform core behavior + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-2"), + }, + ), + }, + ), + "test_configured_nested_list_attribute": tftypes.NewValue( + tftypes.List{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + }, + []tftypes.Value{ + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, "state-value-element-1"), // Terraform core behavior + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-1"), + }, + ), + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, "state-value-element-2"), // Terraform core behavior + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-2"), + }, + ), + }, + ), + "test_configured_nested_map": tftypes.NewValue( + tftypes.Map{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + }, + map[string]tftypes.Value{ + "test-key": tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, "state-value"), // Terraform core behavior + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + }, + ), + "test_configured_nested_map_attribute": tftypes.NewValue( + tftypes.Map{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + }, + map[string]tftypes.Value{ + "test-key": tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, "state-value"), // Terraform core behavior + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + }, + ), + "test_configured_nested_set": tftypes.NewValue( + tftypes.Set{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + }, + []tftypes.Value{ + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, "state-value-element-1"), // Terraform core behavior + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-1"), + }, + ), + // TODO: Prevent random attributes map access from causing flaky test + // Reference: https://github.com/hashicorp/terraform-plugin-framework/issues/783 + // tftypes.NewValue( + // tftypes.Object{ + // AttributeTypes: map[string]tftypes.Type{ + // "computed_attribute": tftypes.String, + // "configurable_attribute": tftypes.String, + // }, + // }, + // map[string]tftypes.Value{ + // "computed_attribute": tftypes.NewValue(tftypes.String, "state-value-element-2"), // Terraform core behavior + // "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-2"), + // }, + // ), + }, + ), + "test_configured_nested_set_attribute": tftypes.NewValue( + tftypes.Set{ + ElementType: tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + }, + []tftypes.Value{ + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, "state-value-element-1"), // Terraform core behavior + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-1"), + }, + ), + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, "state-value-element-2"), // Terraform core behavior + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-2"), + }, + ), + }, + ), + "test_configured_nested_single": tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, "state-value"), // Terraform core behavior + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + "test_configured_nested_single_attribute": tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, "state-value"), // Terraform core behavior + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value"), + }, + ), }), - Schema: testSchema, + Schema: testSchemaDefault, }, PriorState: &tfsdk.State{ - Raw: tftypes.NewValue(testSchemaType, map[string]tftypes.Value{ - "test_computed": tftypes.NewValue(tftypes.String, nil), - "test_required": tftypes.NewValue(tftypes.String, "test-old-value"), - }), - Schema: testSchema, - }, - ResourceSchema: testSchema, - Resource: &testprovider.Resource{}, - }, - expectedResponse: &fwserver.PlanResourceChangeResponse{ - PlannedState: &tfsdk.State{ - Raw: tftypes.NewValue(testSchemaType, map[string]tftypes.Value{ - "test_computed": tftypes.NewValue(tftypes.String, tftypes.UnknownValue), - "test_required": tftypes.NewValue(tftypes.String, "test-new-value"), - }), - Schema: testSchema, - }, - PlannedPrivate: testEmptyPrivate, - }, - }, - "update-set-default-values": { - server: &fwserver.Server{ - Provider: &testprovider.Provider{}, - }, - request: &fwserver.PlanResourceChangeRequest{ - Config: &tfsdk.Config{ Raw: tftypes.NewValue(testSchemaTypeDefault, map[string]tftypes.Value{ - "test_computed_bool": tftypes.NewValue(tftypes.Bool, nil), - "test_computed_float64": tftypes.NewValue(tftypes.Number, nil), - "test_computed_int64": tftypes.NewValue(tftypes.Number, nil), - "test_computed_list": tftypes.NewValue(tftypes.List{ElementType: tftypes.String}, nil), - "test_computed_map": tftypes.NewValue(tftypes.Map{ElementType: tftypes.String}, nil), - "test_computed_number": tftypes.NewValue(tftypes.Number, nil), - "test_computed_object": tftypes.NewValue(tftypes.Object{AttributeTypes: map[string]tftypes.Type{"a": tftypes.String}}, nil), - "test_computed_set": tftypes.NewValue(tftypes.Set{ElementType: tftypes.String}, nil), - "test_computed_string": tftypes.NewValue(tftypes.String, nil), - "test_computed_string_custom_type": tftypes.NewValue(tftypes.String, nil), + "test_computed_bool": tftypes.NewValue(tftypes.Bool, false), + "test_computed_float64": tftypes.NewValue(tftypes.Number, 5.4321), + "test_computed_int64": tftypes.NewValue(tftypes.Number, 54321), + "test_computed_list": tftypes.NewValue(tftypes.List{ElementType: tftypes.String}, []tftypes.Value{tftypes.NewValue(tftypes.String, "prior-state")}), + "test_computed_map": tftypes.NewValue(tftypes.Map{ElementType: tftypes.String}, map[string]tftypes.Value{"a": tftypes.NewValue(tftypes.String, "prior-state")}), + "test_computed_number": tftypes.NewValue(tftypes.Number, big.NewFloat(5.4321)), + "test_computed_object": tftypes.NewValue(tftypes.Object{AttributeTypes: map[string]tftypes.Type{"a": tftypes.String}}, map[string]tftypes.Value{"a": tftypes.NewValue(tftypes.String, "prior-state")}), + "test_computed_set": tftypes.NewValue(tftypes.Set{ElementType: tftypes.String}, []tftypes.Value{tftypes.NewValue(tftypes.String, "prior-state")}), + "test_computed_string": tftypes.NewValue(tftypes.String, "two"), + "test_computed_string_custom_type": tftypes.NewValue(tftypes.String, "two"), "test_computed_nested_list": tftypes.NewValue( tftypes.List{ ElementType: tftypes.Object{ @@ -2453,7 +4268,18 @@ func TestServerPlanResourceChange(t *testing.T) { }, }, }, - nil, + []tftypes.Value{ + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "string_attribute": tftypes.NewValue(tftypes.String, "prior-state"), + }, + ), + }, ), "test_computed_nested_list_attribute": tftypes.NewValue( tftypes.List{ @@ -2471,7 +4297,7 @@ func TestServerPlanResourceChange(t *testing.T) { }, }, map[string]tftypes.Value{ - "string_attribute": tftypes.NewValue(tftypes.String, nil), + "string_attribute": tftypes.NewValue(tftypes.String, "prior-state-attribute"), }, ), }, @@ -2484,7 +4310,18 @@ func TestServerPlanResourceChange(t *testing.T) { }, }, }, - nil, + map[string]tftypes.Value{ + "test-key": tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "string_attribute": tftypes.NewValue(tftypes.String, "prior-state"), + }, + ), + }, ), "test_computed_nested_map_attribute": tftypes.NewValue( tftypes.Map{ @@ -2502,7 +4339,7 @@ func TestServerPlanResourceChange(t *testing.T) { }, }, map[string]tftypes.Value{ - "string_attribute": tftypes.NewValue(tftypes.String, nil), + "string_attribute": tftypes.NewValue(tftypes.String, "prior-state-attribute"), }, ), }, @@ -2513,9 +4350,20 @@ func TestServerPlanResourceChange(t *testing.T) { AttributeTypes: map[string]tftypes.Type{ "string_attribute": tftypes.String, }, - }, + }, + }, + []tftypes.Value{ + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "string_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "string_attribute": tftypes.NewValue(tftypes.String, "prior-state"), + }, + ), }, - nil, ), "test_computed_nested_set_attribute": tftypes.NewValue( tftypes.Set{ @@ -2533,7 +4381,7 @@ func TestServerPlanResourceChange(t *testing.T) { }, }, map[string]tftypes.Value{ - "string_attribute": tftypes.NewValue(tftypes.String, nil), + "string_attribute": tftypes.NewValue(tftypes.String, "prior-state-attribute"), }, ), }, @@ -2544,7 +4392,9 @@ func TestServerPlanResourceChange(t *testing.T) { "string_attribute": tftypes.String, }, }, - nil, + map[string]tftypes.Value{ + "string_attribute": tftypes.NewValue(tftypes.String, "prior-state"), + }, ), "test_computed_nested_single_attribute": tftypes.NewValue( tftypes.Object{ @@ -2553,39 +4403,81 @@ func TestServerPlanResourceChange(t *testing.T) { }, }, map[string]tftypes.Value{ - "string_attribute": tftypes.NewValue(tftypes.String, nil), + "string_attribute": tftypes.NewValue(tftypes.String, "prior-state-attribute"), }, ), - }), - Schema: testSchemaDefault, - }, - ProposedNewState: &tfsdk.Plan{ - Raw: tftypes.NewValue(testSchemaTypeDefault, map[string]tftypes.Value{ - "test_computed_bool": tftypes.NewValue(tftypes.Bool, nil), - "test_computed_float64": tftypes.NewValue(tftypes.Number, nil), - "test_computed_int64": tftypes.NewValue(tftypes.Number, nil), - "test_computed_list": tftypes.NewValue(tftypes.List{ElementType: tftypes.String}, nil), - "test_computed_map": tftypes.NewValue(tftypes.Map{ElementType: tftypes.String}, nil), - "test_computed_number": tftypes.NewValue(tftypes.Number, nil), - "test_computed_object": tftypes.NewValue(tftypes.Object{AttributeTypes: map[string]tftypes.Type{"a": tftypes.String}}, nil), - "test_computed_set": tftypes.NewValue(tftypes.Set{ElementType: tftypes.String}, nil), - "test_computed_string": tftypes.NewValue(tftypes.String, nil), - "test_computed_string_custom_type": tftypes.NewValue(tftypes.String, nil), - "test_computed_nested_list": tftypes.NewValue( + "test_configured_bool": tftypes.NewValue(tftypes.Bool, false), + "test_configured_float64": tftypes.NewValue(tftypes.Number, 2.4), + "test_configured_int64": tftypes.NewValue(tftypes.Number, 456), + "test_configured_list": tftypes.NewValue( + tftypes.List{ElementType: tftypes.String}, + []tftypes.Value{ + tftypes.NewValue(tftypes.String, "state-value"), + }, + ), + "test_configured_map": tftypes.NewValue( + tftypes.Map{ElementType: tftypes.String}, + map[string]tftypes.Value{ + "test-key": tftypes.NewValue(tftypes.String, "state-value"), + }, + ), + "test_configured_number": tftypes.NewValue(tftypes.Number, 2.4), + "test_configured_object": tftypes.NewValue( + tftypes.Object{AttributeTypes: map[string]tftypes.Type{"a": tftypes.String}}, + map[string]tftypes.Value{ + "a": tftypes.NewValue(tftypes.String, "state-value"), + }, + ), + "test_configured_set": tftypes.NewValue( + tftypes.Set{ElementType: tftypes.String}, + []tftypes.Value{ + tftypes.NewValue(tftypes.String, "state-value"), + }, + ), + "test_configured_string": tftypes.NewValue(tftypes.String, "state-value"), + "test_configured_string_custom_type": tftypes.NewValue(tftypes.String, "state-value"), + "test_configured_nested_list": tftypes.NewValue( tftypes.List{ ElementType: tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, }, - nil, + []tftypes.Value{ + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, "state-value-element-1"), + "configurable_attribute": tftypes.NewValue(tftypes.String, "state-value-element-1"), + }, + ), + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, "state-value-element-2"), + "configurable_attribute": tftypes.NewValue(tftypes.String, "state-value-element-2"), + }, + ), + }, ), - "test_computed_nested_list_attribute": tftypes.NewValue( + "test_configured_nested_list_attribute": tftypes.NewValue( tftypes.List{ ElementType: tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, }, @@ -2593,30 +4485,59 @@ func TestServerPlanResourceChange(t *testing.T) { tftypes.NewValue( tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, map[string]tftypes.Value{ - "string_attribute": tftypes.NewValue(tftypes.String, nil), + "computed_attribute": tftypes.NewValue(tftypes.String, "state-value-element-1"), + "configurable_attribute": tftypes.NewValue(tftypes.String, "state-value-element-1"), + }, + ), + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, "state-value-element-2"), + "configurable_attribute": tftypes.NewValue(tftypes.String, "state-value-element-2"), }, ), }, ), - "test_computed_nested_map": tftypes.NewValue( + "test_configured_nested_map": tftypes.NewValue( tftypes.Map{ ElementType: tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, }, - nil, + map[string]tftypes.Value{ + "test-key": tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, "state-value"), + "configurable_attribute": tftypes.NewValue(tftypes.String, "state-value"), + }, + ), + }, ), - "test_computed_nested_map_attribute": tftypes.NewValue( + "test_configured_nested_map_attribute": tftypes.NewValue( tftypes.Map{ ElementType: tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, }, @@ -2624,30 +4545,61 @@ func TestServerPlanResourceChange(t *testing.T) { "test-key": tftypes.NewValue( tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, map[string]tftypes.Value{ - "string_attribute": tftypes.NewValue(tftypes.String, nil), + "computed_attribute": tftypes.NewValue(tftypes.String, "state-value"), + "configurable_attribute": tftypes.NewValue(tftypes.String, "state-value"), }, ), }, ), - "test_computed_nested_set": tftypes.NewValue( + "test_configured_nested_set": tftypes.NewValue( tftypes.Set{ ElementType: tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, }, - nil, + []tftypes.Value{ + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, "state-value-element-1"), + "configurable_attribute": tftypes.NewValue(tftypes.String, "state-value-element-1"), + }, + ), + // TODO: Prevent random attributes map access from causing flaky test + // Reference: https://github.com/hashicorp/terraform-plugin-framework/issues/783 + // tftypes.NewValue( + // tftypes.Object{ + // AttributeTypes: map[string]tftypes.Type{ + // "computed_attribute": tftypes.String, + // "configurable_attribute": tftypes.String, + // }, + // }, + // map[string]tftypes.Value{ + // "computed_attribute": tftypes.NewValue(tftypes.String, "state-value-element-2"), + // "configurable_attribute": tftypes.NewValue(tftypes.String, "state-value-element-2"), + // }, + // ), + }, ), - "test_computed_nested_set_attribute": tftypes.NewValue( + "test_configured_nested_set_attribute": tftypes.NewValue( tftypes.Set{ ElementType: tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, }, @@ -2655,48 +4607,86 @@ func TestServerPlanResourceChange(t *testing.T) { tftypes.NewValue( tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, map[string]tftypes.Value{ - "string_attribute": tftypes.NewValue(tftypes.String, nil), + "computed_attribute": tftypes.NewValue(tftypes.String, "state-value-element-1"), + "configurable_attribute": tftypes.NewValue(tftypes.String, "state-value-element-1"), + }, + ), + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, "state-value-element-2"), + "configurable_attribute": tftypes.NewValue(tftypes.String, "state-value-element-2"), }, ), }, ), - "test_computed_nested_single": tftypes.NewValue( + "test_configured_nested_single": tftypes.NewValue( tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, - nil, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, "state-value"), + "configurable_attribute": tftypes.NewValue(tftypes.String, "state-value"), + }, ), - "test_computed_nested_single_attribute": tftypes.NewValue( + "test_configured_nested_single_attribute": tftypes.NewValue( tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, map[string]tftypes.Value{ - "string_attribute": tftypes.NewValue(tftypes.String, nil), + "computed_attribute": tftypes.NewValue(tftypes.String, "state-value"), + "configurable_attribute": tftypes.NewValue(tftypes.String, "state-value"), }, ), }), Schema: testSchemaDefault, }, - PriorState: &tfsdk.State{ + ResourceSchema: testSchemaDefault, + Resource: &testprovider.Resource{}, + }, + expectedResponse: &fwserver.PlanResourceChangeResponse{ + // TODO: https://github.com/hashicorp/terraform-plugin-framework/issues/783 + Diagnostics: diag.Diagnostics{ + diag.NewAttributeErrorDiagnostic( + path.Root("test_configured_nested_set_attribute"), + "Duplicate Set Element", + "This attribute contains duplicate values of: tftypes.Object["+ + "\"computed_attribute\":tftypes.String, "+ + "\"configurable_attribute\":tftypes.String"+ + "]<"+ + "\"computed_attribute\":tftypes.String<\"attribute-default-value\">, "+ + "\"configurable_attribute\":tftypes.String<\"attribute-default-value\">"+ + ">", + ), + }, + PlannedState: &tfsdk.State{ Raw: tftypes.NewValue(testSchemaTypeDefault, map[string]tftypes.Value{ - "test_computed_bool": tftypes.NewValue(tftypes.Bool, false), - "test_computed_float64": tftypes.NewValue(tftypes.Number, 5.4321), - "test_computed_int64": tftypes.NewValue(tftypes.Number, 54321), - "test_computed_list": tftypes.NewValue(tftypes.List{ElementType: tftypes.String}, []tftypes.Value{tftypes.NewValue(tftypes.String, "prior-state")}), - "test_computed_map": tftypes.NewValue(tftypes.Map{ElementType: tftypes.String}, map[string]tftypes.Value{"a": tftypes.NewValue(tftypes.String, "prior-state")}), - "test_computed_number": tftypes.NewValue(tftypes.Number, big.NewFloat(5.4321)), - "test_computed_object": tftypes.NewValue(tftypes.Object{AttributeTypes: map[string]tftypes.Type{"a": tftypes.String}}, map[string]tftypes.Value{"a": tftypes.NewValue(tftypes.String, "prior-state")}), - "test_computed_set": tftypes.NewValue(tftypes.Set{ElementType: tftypes.String}, []tftypes.Value{tftypes.NewValue(tftypes.String, "prior-state")}), - "test_computed_string": tftypes.NewValue(tftypes.String, "two"), - "test_computed_string_custom_type": tftypes.NewValue(tftypes.String, "two"), + "test_computed_bool": tftypes.NewValue(tftypes.Bool, true), + "test_computed_float64": tftypes.NewValue(tftypes.Number, 1.2345), + "test_computed_int64": tftypes.NewValue(tftypes.Number, 12345), + "test_computed_list": tftypes.NewValue(tftypes.List{ElementType: tftypes.String}, []tftypes.Value{tftypes.NewValue(tftypes.String, "default")}), + "test_computed_map": tftypes.NewValue(tftypes.Map{ElementType: tftypes.String}, map[string]tftypes.Value{"a": tftypes.NewValue(tftypes.String, "default")}), + "test_computed_number": tftypes.NewValue(tftypes.Number, big.NewFloat(1.2345)), + "test_computed_object": tftypes.NewValue(tftypes.Object{AttributeTypes: map[string]tftypes.Type{"a": tftypes.String}}, map[string]tftypes.Value{"a": tftypes.NewValue(tftypes.String, "default")}), + "test_computed_set": tftypes.NewValue(tftypes.Set{ElementType: tftypes.String}, []tftypes.Value{tftypes.NewValue(tftypes.String, "default")}), + "test_computed_string": tftypes.NewValue(tftypes.String, "one"), + "test_computed_string_custom_type": tftypes.NewValue(tftypes.String, "one"), "test_computed_nested_list": tftypes.NewValue( tftypes.List{ ElementType: tftypes.Object{ @@ -2713,7 +4703,7 @@ func TestServerPlanResourceChange(t *testing.T) { }, }, map[string]tftypes.Value{ - "string_attribute": tftypes.NewValue(tftypes.String, "prior-state"), + "string_attribute": tftypes.NewValue(tftypes.String, "default"), }, ), }, @@ -2734,7 +4724,7 @@ func TestServerPlanResourceChange(t *testing.T) { }, }, map[string]tftypes.Value{ - "string_attribute": tftypes.NewValue(tftypes.String, "prior-state-attribute"), + "string_attribute": tftypes.NewValue(tftypes.String, "default-attribute"), }, ), }, @@ -2755,7 +4745,7 @@ func TestServerPlanResourceChange(t *testing.T) { }, }, map[string]tftypes.Value{ - "string_attribute": tftypes.NewValue(tftypes.String, "prior-state"), + "string_attribute": tftypes.NewValue(tftypes.String, "default"), }, ), }, @@ -2776,7 +4766,7 @@ func TestServerPlanResourceChange(t *testing.T) { }, }, map[string]tftypes.Value{ - "string_attribute": tftypes.NewValue(tftypes.String, "prior-state-attribute"), + "string_attribute": tftypes.NewValue(tftypes.String, "default-attribute"), }, ), }, @@ -2797,7 +4787,7 @@ func TestServerPlanResourceChange(t *testing.T) { }, }, map[string]tftypes.Value{ - "string_attribute": tftypes.NewValue(tftypes.String, "prior-state"), + "string_attribute": tftypes.NewValue(tftypes.String, "default"), }, ), }, @@ -2818,7 +4808,7 @@ func TestServerPlanResourceChange(t *testing.T) { }, }, map[string]tftypes.Value{ - "string_attribute": tftypes.NewValue(tftypes.String, "prior-state-attribute"), + "string_attribute": tftypes.NewValue(tftypes.String, "default-attribute"), }, ), }, @@ -2830,7 +4820,7 @@ func TestServerPlanResourceChange(t *testing.T) { }, }, map[string]tftypes.Value{ - "string_attribute": tftypes.NewValue(tftypes.String, "prior-state"), + "string_attribute": tftypes.NewValue(tftypes.String, "default"), }, ), "test_computed_nested_single_attribute": tftypes.NewValue( @@ -2840,33 +4830,45 @@ func TestServerPlanResourceChange(t *testing.T) { }, }, map[string]tftypes.Value{ - "string_attribute": tftypes.NewValue(tftypes.String, "prior-state-attribute"), + "string_attribute": tftypes.NewValue(tftypes.String, "default-attribute"), }, ), - }), - Schema: testSchemaDefault, - }, - ResourceSchema: testSchemaDefault, - Resource: &testprovider.Resource{}, - }, - expectedResponse: &fwserver.PlanResourceChangeResponse{ - PlannedState: &tfsdk.State{ - Raw: tftypes.NewValue(testSchemaTypeDefault, map[string]tftypes.Value{ - "test_computed_bool": tftypes.NewValue(tftypes.Bool, true), - "test_computed_float64": tftypes.NewValue(tftypes.Number, 1.2345), - "test_computed_int64": tftypes.NewValue(tftypes.Number, 12345), - "test_computed_list": tftypes.NewValue(tftypes.List{ElementType: tftypes.String}, []tftypes.Value{tftypes.NewValue(tftypes.String, "default")}), - "test_computed_map": tftypes.NewValue(tftypes.Map{ElementType: tftypes.String}, map[string]tftypes.Value{"a": tftypes.NewValue(tftypes.String, "default")}), - "test_computed_number": tftypes.NewValue(tftypes.Number, big.NewFloat(1.2345)), - "test_computed_object": tftypes.NewValue(tftypes.Object{AttributeTypes: map[string]tftypes.Type{"a": tftypes.String}}, map[string]tftypes.Value{"a": tftypes.NewValue(tftypes.String, "default")}), - "test_computed_set": tftypes.NewValue(tftypes.Set{ElementType: tftypes.String}, []tftypes.Value{tftypes.NewValue(tftypes.String, "default")}), - "test_computed_string": tftypes.NewValue(tftypes.String, "one"), - "test_computed_string_custom_type": tftypes.NewValue(tftypes.String, "one"), - "test_computed_nested_list": tftypes.NewValue( + "test_configured_bool": tftypes.NewValue(tftypes.Bool, true), + "test_configured_float64": tftypes.NewValue(tftypes.Number, 1.2), + "test_configured_int64": tftypes.NewValue(tftypes.Number, 123), + "test_configured_list": tftypes.NewValue( + tftypes.List{ElementType: tftypes.String}, + []tftypes.Value{ + tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + "test_configured_map": tftypes.NewValue( + tftypes.Map{ElementType: tftypes.String}, + map[string]tftypes.Value{ + "test-key": tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + "test_configured_number": tftypes.NewValue(tftypes.Number, 1.2), + "test_configured_object": tftypes.NewValue( + tftypes.Object{AttributeTypes: map[string]tftypes.Type{"a": tftypes.String}}, + map[string]tftypes.Value{ + "a": tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + "test_configured_set": tftypes.NewValue( + tftypes.Set{ElementType: tftypes.String}, + []tftypes.Value{ + tftypes.NewValue(tftypes.String, "config-value"), + }, + ), + "test_configured_string": tftypes.NewValue(tftypes.String, "config-value"), + "test_configured_string_custom_type": tftypes.NewValue(tftypes.String, "config-value"), + "test_configured_nested_list": tftypes.NewValue( tftypes.List{ ElementType: tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, }, @@ -2874,20 +4876,35 @@ func TestServerPlanResourceChange(t *testing.T) { tftypes.NewValue( tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, map[string]tftypes.Value{ - "string_attribute": tftypes.NewValue(tftypes.String, "default"), + "computed_attribute": tftypes.NewValue(tftypes.String, "attribute-default-value"), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-1"), + }, + ), + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, "attribute-default-value"), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-2"), }, ), }, ), - "test_computed_nested_list_attribute": tftypes.NewValue( + "test_configured_nested_list_attribute": tftypes.NewValue( tftypes.List{ ElementType: tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, }, @@ -2895,20 +4912,35 @@ func TestServerPlanResourceChange(t *testing.T) { tftypes.NewValue( tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, map[string]tftypes.Value{ - "string_attribute": tftypes.NewValue(tftypes.String, "default-attribute"), + "computed_attribute": tftypes.NewValue(tftypes.String, "attribute-default-value"), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-1"), + }, + ), + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, "attribute-default-value"), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-2"), }, ), }, ), - "test_computed_nested_map": tftypes.NewValue( + "test_configured_nested_map": tftypes.NewValue( tftypes.Map{ ElementType: tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, }, @@ -2916,20 +4948,23 @@ func TestServerPlanResourceChange(t *testing.T) { "test-key": tftypes.NewValue( tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, map[string]tftypes.Value{ - "string_attribute": tftypes.NewValue(tftypes.String, "default"), + "computed_attribute": tftypes.NewValue(tftypes.String, "attribute-default-value"), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value"), }, ), }, ), - "test_computed_nested_map_attribute": tftypes.NewValue( + "test_configured_nested_map_attribute": tftypes.NewValue( tftypes.Map{ ElementType: tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, }, @@ -2937,20 +4972,23 @@ func TestServerPlanResourceChange(t *testing.T) { "test-key": tftypes.NewValue( tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, map[string]tftypes.Value{ - "string_attribute": tftypes.NewValue(tftypes.String, "default-attribute"), + "computed_attribute": tftypes.NewValue(tftypes.String, "attribute-default-value"), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value"), }, ), }, ), - "test_computed_nested_set": tftypes.NewValue( + "test_configured_nested_set": tftypes.NewValue( tftypes.Set{ ElementType: tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, }, @@ -2958,20 +4996,41 @@ func TestServerPlanResourceChange(t *testing.T) { tftypes.NewValue( tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, map[string]tftypes.Value{ - "string_attribute": tftypes.NewValue(tftypes.String, "default"), + "computed_attribute": tftypes.NewValue(tftypes.String, "attribute-default-value"), + // TODO: https://github.com/hashicorp/terraform-plugin-framework/issues/783 + // "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-1"), + "configurable_attribute": tftypes.NewValue(tftypes.String, "attribute-default-value"), }, ), + // TODO: Prevent random attributes map access from causing flaky test (also fix above data) + // Reference: https://github.com/hashicorp/terraform-plugin-framework/issues/783 + // tftypes.NewValue( + // tftypes.Object{ + // AttributeTypes: map[string]tftypes.Type{ + // "computed_attribute": tftypes.String, + // "configurable_attribute": tftypes.String, + // }, + // }, + // map[string]tftypes.Value{ + // "computed_attribute": tftypes.NewValue(tftypes.String, "attribute-default-value"), + // // TODO: https://github.com/hashicorp/terraform-plugin-framework/issues/783 + // // "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-2"), + // "configurable_attribute": tftypes.NewValue(tftypes.String, "attribute-default-value"), + // }, + // ), }, ), - "test_computed_nested_set_attribute": tftypes.NewValue( + "test_configured_nested_set_attribute": tftypes.NewValue( tftypes.Set{ ElementType: tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, }, @@ -2979,33 +5038,55 @@ func TestServerPlanResourceChange(t *testing.T) { tftypes.NewValue( tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, map[string]tftypes.Value{ - "string_attribute": tftypes.NewValue(tftypes.String, "default-attribute"), + "computed_attribute": tftypes.NewValue(tftypes.String, "attribute-default-value"), + // TODO: https://github.com/hashicorp/terraform-plugin-framework/issues/783 + // "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-1"), + "configurable_attribute": tftypes.NewValue(tftypes.String, "attribute-default-value"), + }, + ), + tftypes.NewValue( + tftypes.Object{ + AttributeTypes: map[string]tftypes.Type{ + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, + }, + }, + map[string]tftypes.Value{ + "computed_attribute": tftypes.NewValue(tftypes.String, "attribute-default-value"), + // TODO: https://github.com/hashicorp/terraform-plugin-framework/issues/783 + // "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value-element-2"), + "configurable_attribute": tftypes.NewValue(tftypes.String, "attribute-default-value"), }, ), }, ), - "test_computed_nested_single": tftypes.NewValue( + "test_configured_nested_single": tftypes.NewValue( tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, map[string]tftypes.Value{ - "string_attribute": tftypes.NewValue(tftypes.String, "default"), + "computed_attribute": tftypes.NewValue(tftypes.String, "attribute-default-value"), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value"), }, ), - "test_computed_nested_single_attribute": tftypes.NewValue( + "test_configured_nested_single_attribute": tftypes.NewValue( tftypes.Object{ AttributeTypes: map[string]tftypes.Type{ - "string_attribute": tftypes.String, + "computed_attribute": tftypes.String, + "configurable_attribute": tftypes.String, }, }, map[string]tftypes.Value{ - "string_attribute": tftypes.NewValue(tftypes.String, "default-attribute"), + "computed_attribute": tftypes.NewValue(tftypes.String, "attribute-default-value"), + "configurable_attribute": tftypes.NewValue(tftypes.String, "config-value"), }, ), }),