Skip to content

Commit

Permalink
Modifying handling of blocks during plan resource change to allow opt…
Browse files Browse the repository at this point in the history
…ional blocks to be present within configuration (#551)
  • Loading branch information
bendbennett committed Nov 28, 2022
1 parent 488e688 commit f738135
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 0 deletions.
6 changes: 6 additions & 0 deletions internal/fwserver/server_planresourcechange.go
Expand Up @@ -291,6 +291,12 @@ func MarkComputedNilsAsUnknown(ctx context.Context, config tftypes.Value, resour
return val, nil
}

if errors.Is(err, tfsdk.ErrPathIsBlock) {
// ignore blocks, they do not have a computed field
logging.FrameworkTrace(ctx, "attribute is a block, not marking unknown")
return val, nil
}

logging.FrameworkError(ctx, "couldn't find attribute in resource schema")

return tftypes.Value{}, fmt.Errorf("couldn't find attribute in resource schema: %w", err)
Expand Down
111 changes: 111 additions & 0 deletions internal/fwserver/server_planresourcechange_test.go
Expand Up @@ -274,6 +274,18 @@ func TestServerPlanResourceChange(t *testing.T) {
},
}

testSchemaBlockType := tftypes.Object{
AttributeTypes: map[string]tftypes.Type{
"test_required": tftypes.String,
"test_optional_block": tftypes.Object{
AttributeTypes: map[string]tftypes.Type{
"test_optional_one": tftypes.String,
"test_optional_two": tftypes.String,
},
},
},
}

testSchemaTypeComputed := tftypes.Object{
AttributeTypes: map[string]tftypes.Type{
"test_computed": tftypes.String,
Expand All @@ -293,6 +305,30 @@ func TestServerPlanResourceChange(t *testing.T) {
},
}

testSchemaBlock := tfsdk.Schema{
Attributes: map[string]tfsdk.Attribute{
"test_required": {
Required: true,
Type: types.StringType,
},
},
Blocks: map[string]tfsdk.Block{
"test_optional_block": {
Attributes: map[string]tfsdk.Attribute{
"test_optional_one": {
Type: types.StringType,
Optional: true,
},
"test_optional_two": {
Type: types.StringType,
Optional: true,
},
},
NestingMode: tfsdk.BlockNestingModeSingle,
},
},
}

testEmptyPlan := &tfsdk.Plan{
Raw: tftypes.NewValue(testSchemaType, nil),
Schema: testSchema,
Expand All @@ -308,6 +344,11 @@ func TestServerPlanResourceChange(t *testing.T) {
TestRequired types.String `tfsdk:"test_required"`
}

type testSchemaDataBlock struct {
TestRequired types.String `tfsdk:"test_required"`
TestOptionalBlock types.Object `tfsdk:"test_optional_block"`
}

testSchemaAttributePlanModifierAttributePlan := tfsdk.Schema{
Attributes: map[string]tfsdk.Attribute{
"test_computed": {
Expand Down Expand Up @@ -1935,6 +1976,76 @@ func TestServerPlanResourceChange(t *testing.T) {
PlannedPrivate: testEmptyPrivate,
},
},
"update-resourcewithmodifyplan-request-config-nil-block": {
server: &fwserver.Server{
Provider: &testprovider.Provider{},
},
request: &fwserver.PlanResourceChangeRequest{
Config: &tfsdk.Config{
Raw: tftypes.NewValue(testSchemaBlockType, map[string]tftypes.Value{
"test_required": tftypes.NewValue(tftypes.String, "test-new-value"),
"test_optional_block": tftypes.NewValue(tftypes.Object{
AttributeTypes: map[string]tftypes.Type{
"test_optional_one": tftypes.String,
"test_optional_two": tftypes.String,
},
}, nil),
}),
Schema: testSchemaBlock,
},
ProposedNewState: &tfsdk.Plan{
Raw: tftypes.NewValue(testSchemaBlockType, map[string]tftypes.Value{
"test_required": tftypes.NewValue(tftypes.String, "test-new-value"),
"test_optional_block": tftypes.NewValue(tftypes.Object{
AttributeTypes: map[string]tftypes.Type{
"test_optional_one": tftypes.String,
"test_optional_two": tftypes.String,
},
}, nil),
}),
Schema: testSchemaBlock,
},
PriorState: &tfsdk.State{
Raw: tftypes.NewValue(testSchemaBlockType, map[string]tftypes.Value{
"test_required": tftypes.NewValue(tftypes.String, "test-new-value"),
"test_optional_block": tftypes.NewValue(tftypes.Object{
AttributeTypes: map[string]tftypes.Type{
"test_optional_one": tftypes.String,
"test_optional_two": tftypes.String,
},
}, nil),
}),
Schema: testSchemaBlock,
},
ResourceSchema: testSchemaBlock,
Resource: &testprovider.ResourceWithModifyPlan{
ModifyPlanMethod: func(ctx context.Context, req resource.ModifyPlanRequest, resp *resource.ModifyPlanResponse) {
var data testSchemaDataBlock

resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)

if data.TestRequired.ValueString() != "test-new-value" {
resp.Diagnostics.AddError("Unexpected req.Config Value", "Got: "+data.TestRequired.ValueString())
}
},
},
},
expectedResponse: &fwserver.PlanResourceChangeResponse{
PlannedState: &tfsdk.State{
Raw: tftypes.NewValue(testSchemaBlockType, map[string]tftypes.Value{
"test_required": tftypes.NewValue(tftypes.String, "test-new-value"),
"test_optional_block": tftypes.NewValue(tftypes.Object{
AttributeTypes: map[string]tftypes.Type{
"test_optional_one": tftypes.String,
"test_optional_two": tftypes.String,
},
}, nil),
}),
Schema: testSchemaBlock,
},
PlannedPrivate: testEmptyPrivate,
},
},
"update-resourcewithmodifyplan-request-proposednewstate": {
server: &fwserver.Server{
Provider: &testprovider.Provider{},
Expand Down

0 comments on commit f738135

Please sign in to comment.