Skip to content

Commit dc31133

Browse files
committed
object
1 parent ae39da3 commit dc31133

File tree

4 files changed

+175
-44
lines changed

4 files changed

+175
-44
lines changed

internal/fwserver/attribute_plan_modification_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3421,6 +3421,31 @@ func TestAttributeModifyPlan(t *testing.T) {
34213421
"nested_computed": types.StringType,
34223422
},
34233423
),
3424+
State: tfsdk.State{
3425+
Raw: tftypes.NewValue(
3426+
tftypes.Object{
3427+
AttributeTypes: map[string]tftypes.Type{
3428+
"test": tftypes.Object{
3429+
AttributeTypes: map[string]tftypes.Type{
3430+
"nested_computed": tftypes.String,
3431+
},
3432+
},
3433+
},
3434+
},
3435+
map[string]tftypes.Value{
3436+
"test": tftypes.NewValue(
3437+
tftypes.Object{
3438+
AttributeTypes: map[string]tftypes.Type{
3439+
"nested_computed": tftypes.String,
3440+
},
3441+
},
3442+
map[string]tftypes.Value{
3443+
"nested_computed": tftypes.NewValue(tftypes.String, "statevalue1"),
3444+
},
3445+
),
3446+
},
3447+
),
3448+
},
34243449
AttributeState: types.ObjectValueMust(
34253450
map[string]attr.Type{
34263451
"nested_computed": types.StringType,
@@ -3479,6 +3504,31 @@ func TestAttributeModifyPlan(t *testing.T) {
34793504
},
34803505
),
34813506
},
3507+
State: tfsdk.State{
3508+
Raw: tftypes.NewValue(
3509+
tftypes.Object{
3510+
AttributeTypes: map[string]tftypes.Type{
3511+
"test": tftypes.Object{
3512+
AttributeTypes: map[string]tftypes.Type{
3513+
"nested_computed": tftypes.String,
3514+
},
3515+
},
3516+
},
3517+
},
3518+
map[string]tftypes.Value{
3519+
"test": tftypes.NewValue(
3520+
tftypes.Object{
3521+
AttributeTypes: map[string]tftypes.Type{
3522+
"nested_computed": tftypes.String,
3523+
},
3524+
},
3525+
map[string]tftypes.Value{
3526+
"nested_computed": tftypes.NewValue(tftypes.String, "statevalue1"),
3527+
},
3528+
),
3529+
},
3530+
),
3531+
},
34823532
AttributeState: testtypes.ObjectValueWithSemanticEquals{
34833533
ObjectValue: types.ObjectValueMust(
34843534
map[string]attr.Type{

internal/fwserver/block_plan_modification_test.go

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3772,6 +3772,31 @@ func TestBlockModifyPlan(t *testing.T) {
37723772
"nested_computed": types.StringType,
37733773
},
37743774
),
3775+
State: tfsdk.State{
3776+
Raw: tftypes.NewValue(
3777+
tftypes.Object{
3778+
AttributeTypes: map[string]tftypes.Type{
3779+
"test": tftypes.Object{
3780+
AttributeTypes: map[string]tftypes.Type{
3781+
"nested_computed": tftypes.String,
3782+
},
3783+
},
3784+
},
3785+
},
3786+
map[string]tftypes.Value{
3787+
"test": tftypes.NewValue(
3788+
tftypes.Object{
3789+
AttributeTypes: map[string]tftypes.Type{
3790+
"nested_computed": tftypes.String,
3791+
},
3792+
},
3793+
map[string]tftypes.Value{
3794+
"nested_computed": tftypes.NewValue(tftypes.String, "statevalue1"),
3795+
},
3796+
),
3797+
},
3798+
),
3799+
},
37753800
AttributeState: types.ObjectValueMust(
37763801
map[string]attr.Type{
37773802
"nested_computed": types.StringType,
@@ -3827,6 +3852,31 @@ func TestBlockModifyPlan(t *testing.T) {
38273852
},
38283853
),
38293854
},
3855+
State: tfsdk.State{
3856+
Raw: tftypes.NewValue(
3857+
tftypes.Object{
3858+
AttributeTypes: map[string]tftypes.Type{
3859+
"test": tftypes.Object{
3860+
AttributeTypes: map[string]tftypes.Type{
3861+
"nested_computed": tftypes.String,
3862+
},
3863+
},
3864+
},
3865+
},
3866+
map[string]tftypes.Value{
3867+
"test": tftypes.NewValue(
3868+
tftypes.Object{
3869+
AttributeTypes: map[string]tftypes.Type{
3870+
"nested_computed": tftypes.String,
3871+
},
3872+
},
3873+
map[string]tftypes.Value{
3874+
"nested_computed": tftypes.NewValue(tftypes.String, "statevalue1"),
3875+
},
3876+
),
3877+
},
3878+
),
3879+
},
38303880
AttributeState: testtypes.ObjectValueWithSemanticEquals{
38313881
ObjectValue: types.ObjectValueMust(
38323882
map[string]attr.Type{

resource/schema/objectplanmodifier/use_state_for_unknown.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ func (m useStateForUnknownModifier) MarkdownDescription(_ context.Context) strin
3636

3737
// PlanModifyObject implements the plan modification logic.
3838
func (m useStateForUnknownModifier) PlanModifyObject(_ context.Context, req planmodifier.ObjectRequest, resp *planmodifier.ObjectResponse) {
39-
// Do nothing if there is no state value.
40-
if req.StateValue.IsNull() {
39+
// Do nothing if there is no state (resource is being created).
40+
if req.State.Raw.IsNull() {
4141
return
4242
}
4343

resource/schema/objectplanmodifier/use_state_for_unknown_test.go

Lines changed: 73 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@ import (
99

1010
"github.com/google/go-cmp/cmp"
1111
"github.com/hashicorp/terraform-plugin-framework/attr"
12-
"github.com/hashicorp/terraform-plugin-framework/path"
1312
"github.com/hashicorp/terraform-plugin-framework/resource/schema/objectplanmodifier"
1413
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
14+
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
1515
"github.com/hashicorp/terraform-plugin-framework/types"
16+
"github.com/hashicorp/terraform-plugin-go/tftypes"
1617
)
1718

1819
func TestUseStateForUnknownModifierPlanModifyObject(t *testing.T) {
@@ -26,6 +27,16 @@ func TestUseStateForUnknownModifierPlanModifyObject(t *testing.T) {
2627
// when we first create the resource, use the unknown
2728
// value
2829
request: planmodifier.ObjectRequest{
30+
State: tfsdk.State{
31+
Raw: tftypes.NewValue(
32+
tftypes.Object{
33+
AttributeTypes: map[string]tftypes.Type{
34+
"attr": tftypes.Object{AttributeTypes: map[string]tftypes.Type{"testattr": tftypes.String}},
35+
},
36+
},
37+
nil,
38+
),
39+
},
2940
StateValue: types.ObjectNull(map[string]attr.Type{"testattr": types.StringType}),
3041
PlanValue: types.ObjectUnknown(map[string]attr.Type{"testattr": types.StringType}),
3142
ConfigValue: types.ObjectNull(map[string]attr.Type{"testattr": types.StringType}),
@@ -42,6 +53,23 @@ func TestUseStateForUnknownModifierPlanModifyObject(t *testing.T) {
4253
// but we still want to preserve that value, in this
4354
// case
4455
request: planmodifier.ObjectRequest{
56+
State: tfsdk.State{
57+
Raw: tftypes.NewValue(
58+
tftypes.Object{
59+
AttributeTypes: map[string]tftypes.Type{
60+
"attr": tftypes.Object{AttributeTypes: map[string]tftypes.Type{"testattr": tftypes.String}},
61+
},
62+
},
63+
map[string]tftypes.Value{
64+
"attr": tftypes.NewValue(
65+
tftypes.Object{AttributeTypes: map[string]tftypes.Type{"testattr": tftypes.String}},
66+
map[string]tftypes.Value{
67+
"testattr": tftypes.NewValue(tftypes.String, "other"),
68+
},
69+
),
70+
},
71+
),
72+
},
4573
StateValue: types.ObjectValueMust(map[string]attr.Type{"testattr": types.StringType}, map[string]attr.Value{"testattr": types.StringValue("other")}),
4674
PlanValue: types.ObjectValueMust(map[string]attr.Type{"testattr": types.StringType}, map[string]attr.Value{"testattr": types.StringValue("test")}),
4775
ConfigValue: types.ObjectNull(map[string]attr.Type{"testattr": types.StringType}),
@@ -50,10 +78,27 @@ func TestUseStateForUnknownModifierPlanModifyObject(t *testing.T) {
5078
PlanValue: types.ObjectValueMust(map[string]attr.Type{"testattr": types.StringType}, map[string]attr.Value{"testattr": types.StringValue("test")}),
5179
},
5280
},
53-
"non-null-state-unknown-plan": {
81+
"non-null-state-value-unknown-plan": {
5482
// this is the situation we want to preserve the state
5583
// in
5684
request: planmodifier.ObjectRequest{
85+
State: tfsdk.State{
86+
Raw: tftypes.NewValue(
87+
tftypes.Object{
88+
AttributeTypes: map[string]tftypes.Type{
89+
"attr": tftypes.Object{AttributeTypes: map[string]tftypes.Type{"testattr": tftypes.String}},
90+
},
91+
},
92+
map[string]tftypes.Value{
93+
"attr": tftypes.NewValue(
94+
tftypes.Object{AttributeTypes: map[string]tftypes.Type{"testattr": tftypes.String}},
95+
map[string]tftypes.Value{
96+
"testattr": tftypes.NewValue(tftypes.String, "test"),
97+
},
98+
),
99+
},
100+
),
101+
},
57102
StateValue: types.ObjectValueMust(map[string]attr.Type{"testattr": types.StringType}, map[string]attr.Value{"testattr": types.StringValue("test")}),
58103
PlanValue: types.ObjectUnknown(map[string]attr.Type{"testattr": types.StringType}),
59104
ConfigValue: types.ObjectNull(map[string]attr.Type{"testattr": types.StringType}),
@@ -62,6 +107,32 @@ func TestUseStateForUnknownModifierPlanModifyObject(t *testing.T) {
62107
PlanValue: types.ObjectValueMust(map[string]attr.Type{"testattr": types.StringType}, map[string]attr.Value{"testattr": types.StringValue("test")}),
63108
},
64109
},
110+
"null-state-value-unknown-plan": {
111+
// Null state values are still known, so we should preserve this as well.
112+
request: planmodifier.ObjectRequest{
113+
State: tfsdk.State{
114+
Raw: tftypes.NewValue(
115+
tftypes.Object{
116+
AttributeTypes: map[string]tftypes.Type{
117+
"attr": tftypes.Object{AttributeTypes: map[string]tftypes.Type{"testattr": tftypes.String}},
118+
},
119+
},
120+
map[string]tftypes.Value{
121+
"attr": tftypes.NewValue(
122+
tftypes.Object{AttributeTypes: map[string]tftypes.Type{"testattr": tftypes.String}},
123+
nil,
124+
),
125+
},
126+
),
127+
},
128+
StateValue: types.ObjectNull(map[string]attr.Type{"testattr": types.StringType}),
129+
PlanValue: types.ObjectUnknown(map[string]attr.Type{"testattr": types.StringType}),
130+
ConfigValue: types.ObjectNull(map[string]attr.Type{"testattr": types.StringType}),
131+
},
132+
expected: &planmodifier.ObjectResponse{
133+
PlanValue: types.ObjectNull(map[string]attr.Type{"testattr": types.StringType}),
134+
},
135+
},
65136
"unknown-config": {
66137
// this is the situation in which a user is
67138
// interpolating into a field. We want that to still
@@ -78,46 +149,6 @@ func TestUseStateForUnknownModifierPlanModifyObject(t *testing.T) {
78149
PlanValue: types.ObjectUnknown(map[string]attr.Type{"testattr": types.StringType}),
79150
},
80151
},
81-
"under-list": {
82-
request: planmodifier.ObjectRequest{
83-
ConfigValue: types.ObjectNull(map[string]attr.Type{"testattr": types.StringType}),
84-
Path: path.Root("test").AtListIndex(0).AtName("nested_test"),
85-
PlanValue: types.ObjectUnknown(map[string]attr.Type{"testattr": types.StringType}),
86-
StateValue: types.ObjectNull(map[string]attr.Type{"testattr": types.StringType}),
87-
},
88-
expected: &planmodifier.ObjectResponse{
89-
PlanValue: types.ObjectUnknown(map[string]attr.Type{"testattr": types.StringType}),
90-
},
91-
},
92-
"under-set": {
93-
request: planmodifier.ObjectRequest{
94-
ConfigValue: types.ObjectNull(map[string]attr.Type{"testattr": types.StringType}),
95-
Path: path.Root("test").AtSetValue(
96-
types.SetValueMust(
97-
types.ObjectType{
98-
AttrTypes: map[string]attr.Type{
99-
"nested_test": types.ObjectType{AttrTypes: map[string]attr.Type{"testattr": types.StringType}},
100-
},
101-
},
102-
[]attr.Value{
103-
types.ObjectValueMust(
104-
map[string]attr.Type{
105-
"nested_test": types.ObjectType{AttrTypes: map[string]attr.Type{"testattr": types.StringType}},
106-
},
107-
map[string]attr.Value{
108-
"nested_test": types.ObjectUnknown(map[string]attr.Type{"testattr": types.StringType}),
109-
},
110-
),
111-
},
112-
),
113-
).AtName("nested_test"),
114-
PlanValue: types.ObjectUnknown(map[string]attr.Type{"testattr": types.StringType}),
115-
StateValue: types.ObjectNull(map[string]attr.Type{"testattr": types.StringType}),
116-
},
117-
expected: &planmodifier.ObjectResponse{
118-
PlanValue: types.ObjectUnknown(map[string]attr.Type{"testattr": types.StringType}),
119-
},
120-
},
121152
}
122153

123154
for name, testCase := range testCases {

0 commit comments

Comments
 (0)