Skip to content

Commit

Permalink
Adding support for using ValueWithAttrs interface (#508)
Browse files Browse the repository at this point in the history
  • Loading branch information
bendbennett committed Oct 7, 2022
1 parent aa0723e commit 5b8a4b5
Show file tree
Hide file tree
Showing 7 changed files with 2,486 additions and 259 deletions.
8 changes: 8 additions & 0 deletions attr/value.go
Expand Up @@ -46,3 +46,11 @@ type Value interface {
// compatibility guarantees within the framework.
String() string
}

type ValueWithAttrs interface {
Value

GetAttrs() map[string]Value

SetAttrs(map[string]Value) ValueWithAttrs
}
15 changes: 9 additions & 6 deletions internal/fwserver/attr_value.go
Expand Up @@ -36,16 +36,20 @@ func coerceMapValue(schemaPath path.Path, value attr.Value) (types.Map, diag.Dia
return m, nil
}

// coerceObjectValue no longer coerces value to types.Object, but performs a type assertion to verify that value fills
// attr.ValueWithAttrs interface.
func coerceObjectValue(schemaPath path.Path, value attr.Value) (attr.Value, diag.Diagnostics) {
object, ok := value.Type(context.Background()).(attr.TypeWithAttributeTypes)
object, ok := value.(attr.ValueWithAttrs)

if !ok {
return object.ValueType(context.Background()), diag.Diagnostics{
// TODO: Verify whether returning value rather than the equivalent of types.Object{Null: true} for value is acceptable.
// https://github.com/hashicorp/terraform-plugin-framework/blob/main/internal/fwserver/attr_value.go#L42
return value, diag.Diagnostics{
attributePlanModificationWalkError(schemaPath, value),
}
}

return value, nil
return object, nil
}

func coerceSetValue(schemaPath path.Path, value attr.Value) (types.Set, diag.Diagnostics) {
Expand Down Expand Up @@ -127,12 +131,11 @@ func objectAttributeValue(ctx context.Context, object attr.Value, attributeName
return objectAttributeValueFromTerraformValue(ctx, object, attributeName, description, tftypes.UnknownValue)
}

attrTypes := object.Type(ctx).(attr.TypeWithAttributeTypes).AttributeTypes()
attrType := attrTypes[attributeName]
attrValues := object.(attr.ValueWithAttrs).GetAttrs()

// A panic here indicates a bug somewhere else in the framework or an
// invalid test case.
return attrType.ValueType(ctx), nil
return attrValues[attributeName], nil
}

func objectAttributeValueFromTerraformValue(ctx context.Context, object attr.Value, attributeName string, description fwschemadata.DataDescription, tfValue any) (attr.Value, diag.Diagnostics) {
Expand Down
36 changes: 24 additions & 12 deletions internal/fwserver/attribute_plan_modification.go
Expand Up @@ -143,7 +143,11 @@ func AttributeModifyPlan(ctx context.Context, a fwschema.Attribute, req tfsdk.Mo
return
}

planObjectAttrs := planObject.Type(ctx).(attr.TypeWithAttributeTypes).AttributeTypes()
planObjectAttrs := planObject.(attr.ValueWithAttrs).GetAttrs()

if planObjectAttrs == nil {
planObjectAttrs = make(map[string]attr.Value)
}

for name, attr := range a.GetAttributes().GetAttributes() {
attrConfig, diags := objectAttributeValue(ctx, configObject, name, fwschemadata.DataDescriptionConfiguration)
Expand Down Expand Up @@ -189,13 +193,13 @@ func AttributeModifyPlan(ctx context.Context, a fwschema.Attribute, req tfsdk.Mo

AttributeModifyPlan(ctx, attr, attrReq, &attrResp)

planObjectAttrs[name] = attrResp.AttributePlan.Type(ctx)
planObjectAttrs[name] = attrResp.AttributePlan
resp.Diagnostics.Append(attrResp.Diagnostics...)
resp.RequiresReplace = attrResp.RequiresReplace
resp.Private = attrResp.Private
}

planList.Elems[idx] = planObject
planList.Elems[idx] = planObject.(attr.ValueWithAttrs).SetAttrs(planObjectAttrs)
}

resp.AttributePlan = planList
Expand Down Expand Up @@ -251,7 +255,11 @@ func AttributeModifyPlan(ctx context.Context, a fwschema.Attribute, req tfsdk.Mo
return
}

planObjectAttrs := planObject.Type(ctx).(attr.TypeWithAttributeTypes).AttributeTypes()
planObjectAttrs := planObject.(attr.ValueWithAttrs).GetAttrs()

if planObjectAttrs == nil {
planObjectAttrs = make(map[string]attr.Value)
}

for name, attr := range a.GetAttributes().GetAttributes() {
attrConfig, diags := objectAttributeValue(ctx, configObject, name, fwschemadata.DataDescriptionConfiguration)
Expand Down Expand Up @@ -297,13 +305,13 @@ func AttributeModifyPlan(ctx context.Context, a fwschema.Attribute, req tfsdk.Mo

AttributeModifyPlan(ctx, attr, attrReq, &attrResp)

planObjectAttrs[name] = attrResp.AttributePlan.Type(ctx)
planObjectAttrs[name] = attrResp.AttributePlan
resp.Diagnostics.Append(attrResp.Diagnostics...)
resp.RequiresReplace = attrResp.RequiresReplace
resp.Private = attrResp.Private
}

planSet.Elems[idx] = planObject
planSet.Elems[idx] = planObject.(attr.ValueWithAttrs).SetAttrs(planObjectAttrs)
}

resp.AttributePlan = planSet
Expand Down Expand Up @@ -359,7 +367,11 @@ func AttributeModifyPlan(ctx context.Context, a fwschema.Attribute, req tfsdk.Mo
return
}

planObjectAttrs := planObject.Type(ctx).(attr.TypeWithAttributeTypes).AttributeTypes()
planObjectAttrs := planObject.(attr.ValueWithAttrs).GetAttrs()

if planObjectAttrs == nil {
planObjectAttrs = make(map[string]attr.Value)
}

for name, attr := range a.GetAttributes().GetAttributes() {
attrConfig, diags := objectAttributeValue(ctx, configObject, name, fwschemadata.DataDescriptionConfiguration)
Expand Down Expand Up @@ -405,13 +417,13 @@ func AttributeModifyPlan(ctx context.Context, a fwschema.Attribute, req tfsdk.Mo

AttributeModifyPlan(ctx, attr, attrReq, &attrResp)

planObjectAttrs[name] = attrResp.AttributePlan.Type(ctx)
planObjectAttrs[name] = attrResp.AttributePlan
resp.Diagnostics.Append(attrResp.Diagnostics...)
resp.RequiresReplace = attrResp.RequiresReplace
resp.Private = attrResp.Private
}

planMap.Elems[key] = planObject
planMap.Elems[key] = planObject.(attr.ValueWithAttrs).SetAttrs(planObjectAttrs)
}

resp.AttributePlan = planMap
Expand Down Expand Up @@ -440,7 +452,7 @@ func AttributeModifyPlan(ctx context.Context, a fwschema.Attribute, req tfsdk.Mo
return
}

planObjectAttrs := planObject.Type(ctx).(attr.TypeWithAttributeTypes).AttributeTypes()
planObjectAttrs := planObject.(attr.ValueWithAttrs).GetAttrs()

if len(planObjectAttrs) == 0 {
return
Expand Down Expand Up @@ -490,13 +502,13 @@ func AttributeModifyPlan(ctx context.Context, a fwschema.Attribute, req tfsdk.Mo

AttributeModifyPlan(ctx, attr, attrReq, &attrResp)

planObjectAttrs[name] = attrResp.AttributePlan.Type(ctx)
planObjectAttrs[name] = attrResp.AttributePlan
resp.Diagnostics.Append(attrResp.Diagnostics...)
resp.RequiresReplace = attrResp.RequiresReplace
resp.Private = attrResp.Private
}

resp.AttributePlan = planObject
resp.AttributePlan = planObject.(attr.ValueWithAttrs).SetAttrs(planObjectAttrs)
default:
err := fmt.Errorf("unknown attribute nesting mode (%T: %v) at path: %s", nm, nm, req.AttributePath)
resp.Diagnostics.AddAttributeError(
Expand Down
38 changes: 23 additions & 15 deletions internal/fwserver/block_plan_modification.go
Expand Up @@ -109,7 +109,11 @@ func BlockModifyPlan(ctx context.Context, b fwschema.Block, req tfsdk.ModifyAttr
return
}

planObjectAttrs := planObject.Type(ctx).(attr.TypeWithAttributeTypes).AttributeTypes()
planObjectAttrs := planObject.(attr.ValueWithAttrs).GetAttrs()

if planObjectAttrs == nil {
planObjectAttrs = make(map[string]attr.Value)
}

for name, attr := range b.GetAttributes() {
attrConfig, diags := objectAttributeValue(ctx, configObject, name, fwschemadata.DataDescriptionConfiguration)
Expand Down Expand Up @@ -155,7 +159,7 @@ func BlockModifyPlan(ctx context.Context, b fwschema.Block, req tfsdk.ModifyAttr

AttributeModifyPlan(ctx, attr, attrReq, &attrResp)

planObjectAttrs[name] = attrResp.AttributePlan.Type(ctx)
planObjectAttrs[name] = attrResp.AttributePlan
resp.Diagnostics.Append(attrResp.Diagnostics...)
resp.RequiresReplace = attrResp.RequiresReplace
resp.Private = attrResp.Private
Expand Down Expand Up @@ -205,13 +209,13 @@ func BlockModifyPlan(ctx context.Context, b fwschema.Block, req tfsdk.ModifyAttr

BlockModifyPlan(ctx, block, blockReq, &blockResp)

planObjectAttrs[name] = blockResp.AttributePlan.Type(ctx)
planObjectAttrs[name] = blockResp.AttributePlan
resp.Diagnostics.Append(blockResp.Diagnostics...)
resp.RequiresReplace = blockResp.RequiresReplace
resp.Private = blockResp.Private
}

planList.Elems[idx] = planObject
planList.Elems[idx] = planObject.(attr.ValueWithAttrs).SetAttrs(planObjectAttrs)
}

resp.AttributePlan = planList
Expand Down Expand Up @@ -267,7 +271,11 @@ func BlockModifyPlan(ctx context.Context, b fwschema.Block, req tfsdk.ModifyAttr
return
}

planObjectAttrs := planObject.Type(ctx).(attr.TypeWithAttributeTypes).AttributeTypes()
planObjectAttrs := planObject.(attr.ValueWithAttrs).GetAttrs()

if planObjectAttrs == nil {
planObjectAttrs = make(map[string]attr.Value)
}

for name, attr := range b.GetAttributes() {
attrConfig, diags := objectAttributeValue(ctx, configObject, name, fwschemadata.DataDescriptionConfiguration)
Expand Down Expand Up @@ -313,7 +321,7 @@ func BlockModifyPlan(ctx context.Context, b fwschema.Block, req tfsdk.ModifyAttr

AttributeModifyPlan(ctx, attr, attrReq, &attrResp)

planObjectAttrs[name] = attrResp.AttributePlan.Type(ctx)
planObjectAttrs[name] = attrResp.AttributePlan
resp.Diagnostics.Append(attrResp.Diagnostics...)
resp.RequiresReplace = attrResp.RequiresReplace
resp.Private = attrResp.Private
Expand Down Expand Up @@ -363,13 +371,13 @@ func BlockModifyPlan(ctx context.Context, b fwschema.Block, req tfsdk.ModifyAttr

BlockModifyPlan(ctx, block, blockReq, &blockResp)

planObjectAttrs[name] = blockResp.AttributePlan.Type(ctx)
planObjectAttrs[name] = blockResp.AttributePlan
resp.Diagnostics.Append(blockResp.Diagnostics...)
resp.RequiresReplace = blockResp.RequiresReplace
resp.Private = blockResp.Private
}

planSet.Elems[idx] = planObject
planSet.Elems[idx] = planObject.(attr.ValueWithAttrs).SetAttrs(planObjectAttrs)
}

resp.AttributePlan = planSet
Expand Down Expand Up @@ -398,11 +406,11 @@ func BlockModifyPlan(ctx context.Context, b fwschema.Block, req tfsdk.ModifyAttr
return
}

if planObject.Type(ctx).(attr.TypeWithAttributeTypes).AttributeTypes() == nil {
planObject.Type(ctx).(attr.TypeWithAttributeTypes).WithAttributeTypes(make(map[string]attr.Type))
}
planObjectAttrs := planObject.(attr.ValueWithAttrs).GetAttrs()

planObjectAttrs := planObject.Type(ctx).(attr.TypeWithAttributeTypes).AttributeTypes()
if planObjectAttrs == nil {
planObjectAttrs = make(map[string]attr.Value)
}

for name, attr := range b.GetAttributes() {
attrConfig, diags := objectAttributeValue(ctx, configObject, name, fwschemadata.DataDescriptionConfiguration)
Expand Down Expand Up @@ -448,7 +456,7 @@ func BlockModifyPlan(ctx context.Context, b fwschema.Block, req tfsdk.ModifyAttr

AttributeModifyPlan(ctx, attr, attrReq, &attrResp)

planObjectAttrs[name] = attrResp.AttributePlan.Type(ctx)
planObjectAttrs[name] = attrResp.AttributePlan
resp.Diagnostics.Append(attrResp.Diagnostics...)
resp.RequiresReplace = attrResp.RequiresReplace
resp.Private = attrResp.Private
Expand Down Expand Up @@ -498,13 +506,13 @@ func BlockModifyPlan(ctx context.Context, b fwschema.Block, req tfsdk.ModifyAttr

BlockModifyPlan(ctx, block, blockReq, &blockResp)

planObjectAttrs[name] = blockResp.AttributePlan.Type(ctx)
planObjectAttrs[name] = blockResp.AttributePlan
resp.Diagnostics.Append(blockResp.Diagnostics...)
resp.RequiresReplace = blockResp.RequiresReplace
resp.Private = blockResp.Private
}

resp.AttributePlan = planObject
resp.AttributePlan = planObject.(attr.ValueWithAttrs).SetAttrs(planObjectAttrs)
default:
err := fmt.Errorf("unknown block plan modification nesting mode (%T: %v) at path: %s", nm, nm, req.AttributePath)
resp.Diagnostics.AddAttributeError(
Expand Down

0 comments on commit 5b8a4b5

Please sign in to comment.