Skip to content

Commit

Permalink
internal/fwserver: Fix framework setting nested blocks within nested …
Browse files Browse the repository at this point in the history
…lists to nil during plan modification (#480)

Reference: #479
  • Loading branch information
liamcervante committed Sep 14, 2022
1 parent d974925 commit 9696464
Show file tree
Hide file tree
Showing 3 changed files with 287 additions and 6 deletions.
3 changes: 3 additions & 0 deletions .changelog/479.txt
@@ -0,0 +1,3 @@
```release-note:bug
internal/fwserver: Ensured nested block plan modifiers correctly set their request `AttributeConfig`, `AttributePlan`, and `AttributeState` values
```
39 changes: 33 additions & 6 deletions internal/fwserver/block_plan_modification.go
Expand Up @@ -160,13 +160,40 @@ func BlockModifyPlan(ctx context.Context, b fwschema.Block, req tfsdk.ModifyAttr
}

for name, block := range b.GetBlocks() {
attrConfig, diags := objectAttributeValue(ctx, configObject, name, fwschemadata.DataDescriptionConfiguration)

resp.Diagnostics.Append(diags...)

if resp.Diagnostics.HasError() {
return
}

attrPlan, diags := objectAttributeValue(ctx, planObject, name, fwschemadata.DataDescriptionPlan)

resp.Diagnostics.Append(diags...)

if resp.Diagnostics.HasError() {
return
}

attrState, diags := objectAttributeValue(ctx, stateObject, name, fwschemadata.DataDescriptionState)

resp.Diagnostics.Append(diags...)

if resp.Diagnostics.HasError() {
return
}

blockReq := tfsdk.ModifyAttributePlanRequest{
AttributePath: req.AttributePath.AtListIndex(idx).AtName(name),
Config: req.Config,
Plan: req.Plan,
ProviderMeta: req.ProviderMeta,
State: req.State,
Private: resp.Private,
AttributeConfig: attrConfig,
AttributePath: req.AttributePath.AtListIndex(idx).AtName(name),
AttributePlan: attrPlan,
AttributeState: attrState,
Config: req.Config,
Plan: req.Plan,
ProviderMeta: req.ProviderMeta,
State: req.State,
Private: resp.Private,
}
blockResp := ModifyAttributePlanResponse{
AttributePlan: blockReq.AttributePlan,
Expand Down
251 changes: 251 additions & 0 deletions internal/fwserver/block_plan_modification_test.go
Expand Up @@ -836,6 +836,257 @@ func TestBlockModifyPlan(t *testing.T) {
Private: testProviderData,
},
},
"block-list-nested-block-list": {
block: tfsdk.Block{
Attributes: map[string]tfsdk.Attribute{
"id": {
Type: types.StringType,
Computed: true,
Optional: true,
PlanModifiers: []tfsdk.AttributePlanModifier{
resource.UseStateForUnknown(),
},
},
},
Blocks: map[string]tfsdk.Block{
"list": {
Attributes: map[string]tfsdk.Attribute{
"nested_computed": {
Type: types.StringType,
Computed: true,
PlanModifiers: []tfsdk.AttributePlanModifier{
resource.UseStateForUnknown(),
},
},
"nested_required": {
Type: types.StringType,
Required: true,
},
},
NestingMode: tfsdk.BlockNestingModeList,
},
},
NestingMode: tfsdk.BlockNestingModeList,
},
req: tfsdk.ModifyAttributePlanRequest{
AttributeConfig: types.List{
ElemType: types.ObjectType{
AttrTypes: map[string]attr.Type{
"id": types.StringType,
"list": types.ListType{
ElemType: types.ObjectType{
AttrTypes: map[string]attr.Type{
"nested_computed": types.StringType,
"nested_required": types.StringType,
},
},
},
},
},
Elems: []attr.Value{
types.Object{
AttrTypes: map[string]attr.Type{
"id": types.StringType,
"list": types.ListType{
ElemType: types.ObjectType{
AttrTypes: map[string]attr.Type{
"nested_computed": types.StringType,
"nested_required": types.StringType,
},
},
},
},
Attrs: map[string]attr.Value{
"id": types.String{Value: "configvalue"},
"list": types.List{
ElemType: types.ObjectType{
AttrTypes: map[string]attr.Type{
"nested_computed": types.StringType,
"nested_required": types.StringType,
},
},
Elems: []attr.Value{
types.Object{
AttrTypes: map[string]attr.Type{
"nested_computed": types.StringType,
"nested_required": types.StringType,
},
Attrs: map[string]attr.Value{
"nested_computed": types.String{Null: true},
"nested_required": types.String{Value: "configvalue"},
},
},
},
},
},
},
},
},
AttributePath: path.Root("test"),
AttributePlan: types.List{
ElemType: types.ObjectType{
AttrTypes: map[string]attr.Type{
"id": types.StringType,
"list": types.ListType{
ElemType: types.ObjectType{
AttrTypes: map[string]attr.Type{
"nested_computed": types.StringType,
"nested_required": types.StringType,
},
},
},
},
},
Elems: []attr.Value{
types.Object{
AttrTypes: map[string]attr.Type{
"id": types.StringType,
"list": types.ListType{
ElemType: types.ObjectType{
AttrTypes: map[string]attr.Type{
"nested_computed": types.StringType,
"nested_required": types.StringType,
},
},
},
},
Attrs: map[string]attr.Value{
"id": types.String{Value: "one"},
"list": types.List{
ElemType: types.ObjectType{
AttrTypes: map[string]attr.Type{
"nested_computed": types.StringType,
"nested_required": types.StringType,
},
},
Elems: []attr.Value{
types.Object{
AttrTypes: map[string]attr.Type{
"nested_computed": types.StringType,
"nested_required": types.StringType,
},
Attrs: map[string]attr.Value{
"nested_computed": types.String{Unknown: true},
"nested_required": types.String{Value: "configvalue"},
},
},
},
},
},
},
},
},
AttributeState: types.List{
ElemType: types.ObjectType{
AttrTypes: map[string]attr.Type{
"id": types.StringType,
"list": types.ListType{
ElemType: types.ObjectType{
AttrTypes: map[string]attr.Type{
"nested_computed": types.StringType,
"nested_required": types.StringType,
},
},
},
},
},
Elems: []attr.Value{
types.Object{
AttrTypes: map[string]attr.Type{
"id": types.StringType,
"list": types.ListType{
ElemType: types.ObjectType{
AttrTypes: map[string]attr.Type{
"nested_computed": types.StringType,
"nested_required": types.StringType,
},
},
},
},
Attrs: map[string]attr.Value{
"id": types.String{Value: "one"},
"list": types.List{
ElemType: types.ObjectType{
AttrTypes: map[string]attr.Type{
"nested_computed": types.StringType,
"nested_required": types.StringType,
},
},
Elems: []attr.Value{
types.Object{
AttrTypes: map[string]attr.Type{
"nested_computed": types.StringType,
"nested_required": types.StringType,
},
Attrs: map[string]attr.Value{
"nested_computed": types.String{Value: "statevalue"},
"nested_required": types.String{Value: "configvalue"},
},
},
},
},
},
},
},
},
},
expectedResp: ModifyAttributePlanResponse{
AttributePlan: types.List{
ElemType: types.ObjectType{
AttrTypes: map[string]attr.Type{
"id": types.StringType,
"list": types.ListType{
ElemType: types.ObjectType{
AttrTypes: map[string]attr.Type{
"nested_computed": types.StringType,
"nested_required": types.StringType,
},
},
},
},
},
Elems: []attr.Value{
types.Object{
AttrTypes: map[string]attr.Type{
"id": types.StringType,
"list": types.ListType{
ElemType: types.ObjectType{
AttrTypes: map[string]attr.Type{
"nested_computed": types.StringType,
"nested_required": types.StringType,
},
},
},
},
Attrs: map[string]attr.Value{
"id": types.String{Value: "one"},
"list": types.List{
ElemType: types.ObjectType{
AttrTypes: map[string]attr.Type{
"nested_computed": types.StringType,
"nested_required": types.StringType,
},
},
Elems: []attr.Value{
types.Object{
AttrTypes: map[string]attr.Type{
"nested_computed": types.StringType,
"nested_required": types.StringType,
},
Attrs: map[string]attr.Value{
"nested_computed": types.String{Value: "statevalue"},
"nested_required": types.String{Value: "configvalue"},
},
},
},
},
},
},
},
},
Private: testEmptyProviderData,
},
},
"block-set-nested-usestateforunknown": {
block: tfsdk.Block{
Attributes: map[string]tfsdk.Attribute{
Expand Down

0 comments on commit 9696464

Please sign in to comment.