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 28, 2022
1 parent fad0233 commit 897a02f
Show file tree
Hide file tree
Showing 7 changed files with 2,441 additions and 256 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
60 changes: 24 additions & 36 deletions internal/fwserver/attribute_plan_modification.go
Expand Up @@ -151,7 +151,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 @@ -197,19 +201,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
}

planElements[idx], diags = types.ObjectValue(planObject.AttributeTypes(ctx), planAttributes)

resp.Diagnostics.Append(diags...)

if resp.Diagnostics.HasError() {
return
}
planList.Elems[idx] = planObject.(attr.ValueWithAttrs).SetAttrs(planObjectAttrs)
}

resp.AttributePlan, diags = types.ListValue(planList.ElementType(ctx), planElements)
Expand Down Expand Up @@ -273,7 +271,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 @@ -319,19 +321,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
}

planElements[idx], diags = types.ObjectValue(planObject.AttributeTypes(ctx), planAttributes)

resp.Diagnostics.Append(diags...)

if resp.Diagnostics.HasError() {
return
}
planSet.Elems[idx] = planObject.(attr.ValueWithAttrs).SetAttrs(planObjectAttrs)
}

resp.AttributePlan, diags = types.SetValue(planSet.ElementType(ctx), planElements)
Expand Down Expand Up @@ -395,7 +391,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 @@ -441,19 +441,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
}

planElements[key], diags = types.ObjectValue(planObject.AttributeTypes(ctx), planAttributes)

resp.Diagnostics.Append(diags...)

if resp.Diagnostics.HasError() {
return
}
planMap.Elems[key] = planObject.(attr.ValueWithAttrs).SetAttrs(planObjectAttrs)
}

resp.AttributePlan, diags = types.MapValue(planMap.ElementType(ctx), planElements)
Expand Down Expand Up @@ -488,7 +482,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 @@ -540,19 +534,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, diags = types.ObjectValue(planObject.AttributeTypes(ctx), planAttributes)

resp.Diagnostics.Append(diags...)

if resp.Diagnostics.HasError() {
return
}
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
56 changes: 23 additions & 33 deletions internal/fwserver/block_plan_modification.go
Expand Up @@ -117,7 +117,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 @@ -163,7 +167,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 @@ -213,19 +217,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
}

planElements[idx], diags = types.ObjectValue(planObject.AttributeTypes(ctx), planAttributes)

resp.Diagnostics.Append(diags...)

if resp.Diagnostics.HasError() {
return
}
planList.Elems[idx] = planObject.(attr.ValueWithAttrs).SetAttrs(planObjectAttrs)
}

resp.AttributePlan, diags = types.ListValue(planList.ElementType(ctx), planElements)
Expand Down Expand Up @@ -289,7 +287,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 @@ -335,7 +337,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 @@ -385,19 +387,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
}

planElements[idx], diags = types.ObjectValue(planObject.AttributeTypes(ctx), planAttributes)

resp.Diagnostics.Append(diags...)

if resp.Diagnostics.HasError() {
return
}
planSet.Elems[idx] = planObject.(attr.ValueWithAttrs).SetAttrs(planObjectAttrs)
}

resp.AttributePlan, diags = types.SetValue(planSet.ElementType(ctx), planElements)
Expand Down Expand Up @@ -432,11 +428,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 @@ -482,7 +478,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 @@ -532,19 +528,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, diags = types.ObjectValue(planObject.AttributeTypes(ctx), planAttributes)

resp.Diagnostics.Append(diags...)

if resp.Diagnostics.HasError() {
return
}
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 897a02f

Please sign in to comment.