Skip to content

Commit

Permalink
internal/fwserver: Ensure computed dynamic values are marked as dynam…
Browse files Browse the repository at this point in the history
…ic type during plan modification (#970)

* internal/fwserver: Ensure computed dynamic values are marked as dynamic type during plan modification

* Update .changes/unreleased/BUG FIXES-20240325-101108.yaml

Co-authored-by: Brian Flad <bflad417@gmail.com>

---------

Co-authored-by: Brian Flad <bflad417@gmail.com>
  • Loading branch information
austinvalle and bflad committed Mar 26, 2024
1 parent 332d5d1 commit 484f311
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 3 deletions.
6 changes: 6 additions & 0 deletions .changes/unreleased/BUG FIXES-20240325-101108.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
kind: BUG FIXES
body: 'resource: Ensured computed-only dynamic attributes will not cause `wrong final
value type` errors during planning'
time: 2024-03-25T10:11:08.813527-04:00
custom:
Issue: "969"
13 changes: 12 additions & 1 deletion internal/fwserver/server_planresourcechange.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
)

// PlanResourceChangeRequest is the framework server request for the
Expand Down Expand Up @@ -406,9 +407,19 @@ func MarkComputedNilsAsUnknown(ctx context.Context, config tftypes.Value, resour
}
}

// Value type from planned state to create unknown with
newValueType := val.Type()

// If the attribute is dynamic then we can't use the planned state value to create an unknown, as it may be a concrete type.
// This logic explicitly sets the unknown value type to dynamic so the type can be determined during apply.
_, isDynamic := attribute.GetType().(basetypes.DynamicTypable)
if isDynamic {
newValueType = tftypes.DynamicPseudoType
}

logging.FrameworkDebug(ctx, "marking computed attribute that is null in the config as unknown")

return tftypes.NewValue(val.Type(), tftypes.UnknownValue), nil
return tftypes.NewValue(newValueType, tftypes.UnknownValue), nil
}
}

Expand Down
4 changes: 2 additions & 2 deletions internal/fwserver/server_planresourcechange_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func TestMarkComputedNilsAsUnknown(t *testing.T) {
"dynamic-nil-computed": schema.DynamicAttribute{
Computed: true,
},
// underlying nil computed values should be turned into unknown, preserving the original type
// underlying nil computed values should be turned into unknown, this should not preserve the original type
"dynamic-underlying-string-nil-computed": schema.DynamicAttribute{
Computed: true,
},
Expand Down Expand Up @@ -274,7 +274,7 @@ func TestMarkComputedNilsAsUnknown(t *testing.T) {
"dynamic-value": tftypes.NewValue(tftypes.String, "hello, world"),
"dynamic-nil": tftypes.NewValue(tftypes.DynamicPseudoType, nil),
"dynamic-nil-computed": tftypes.NewValue(tftypes.DynamicPseudoType, tftypes.UnknownValue),
"dynamic-underlying-string-nil-computed": tftypes.NewValue(tftypes.String, tftypes.UnknownValue), // Preserves the underlying string type
"dynamic-underlying-string-nil-computed": tftypes.NewValue(tftypes.DynamicPseudoType, tftypes.UnknownValue), // doesn't preserve original type
"dynamic-nil-optional-computed": tftypes.NewValue(tftypes.DynamicPseudoType, tftypes.UnknownValue),
"dynamic-value-optional-computed": tftypes.NewValue(tftypes.String, "hello, world"),
"dynamic-value-with-underlying-list-optional-computed": tftypes.NewValue(
Expand Down

0 comments on commit 484f311

Please sign in to comment.