Skip to content

Commit

Permalink
types: Add Typable and Valuable Interfaces (#536)
Browse files Browse the repository at this point in the history
* Adding ValueFromFramework and ToFrameworkValue interface functions to types.ListType and types.List (value), respectively (#535)

* Adding ValueFromFramework and ToFrameworkValue interface functions to types.MapType and types.Map (value), respectively (#535)

* Adding ValueFromFramework and ToFrameworkValue interface functions to types.SetType and types.Set (value), respectively (#535)

* Adding ValueFromFramework and ToFrameworkValue interface functions to types.ObjectType and types.Object (value), respectively (#535)

* Adding ValueFromFramework and ToFrameworkValue interface functions to primitive types and primitive values, respectively (#535)

* Refactoring interface names to use -able suffix (#535)

* Adding Go documentation and refactoring to return type-specific interfaces from ValueFrom<type> functions (#535)

* Adding further Go documentation (#535)

* Apply suggestions from code review

Co-authored-by: Brian Flad <bflad417@gmail.com>

* Amending Go documentation (#535)

* Adding changelog, amending Go documentation and adding unit tests for attribute plan modification and attribute validation for custom nested attribute types (#535)

Co-authored-by: Brian Flad <bflad417@gmail.com>
  • Loading branch information
bendbennett and bflad committed Nov 15, 2022
1 parent 6fea713 commit bf1ce9b
Show file tree
Hide file tree
Showing 23 changed files with 1,482 additions and 105 deletions.
35 changes: 35 additions & 0 deletions .changelog/536.txt
@@ -0,0 +1,35 @@
```release-note:enhancement
types: Added `BoolTypable` and `BoolValuable` interface types, which enable embedding existing boolean types for custom types
```

```release-note:enhancement
types: Added `Float64Typable` and `Float64Valuable` interface types, which enable embedding existing float64 types for custom types
```

```release-note:enhancement
types: Added `Int64Typable` and `Int64Valuable` interface types, which enable embedding existing int64 types for custom types
```

```release-note:enhancement
types: Added `ListTypable` and `ListValuable` interface types, which enable embedding existing list types for custom types
```

```release-note:enhancement
types: Added `MapTypable` and `MapValuable` interface types, which enable embedding existing map types for custom types
```

```release-note:enhancement
types: Added `NumberTypable` and `NumberValuable` interface types, which enable embedding existing number types for custom types
```

```release-note:enhancement
types: Added `ObjectTypable` and `ObjectValuable` interface types, which enable embedding existing object types for custom types
```

```release-note:enhancement
types: Added `SetTypable` and `SetValuable` interface types, which enable embedding existing set types for custom types
```

```release-note:enhancement
types: Added `StringTypable` and `StringValuable` interface types, which enable embedding existing string types for custom types
```
39 changes: 20 additions & 19 deletions internal/fwserver/attr_value.go
Expand Up @@ -3,60 +3,61 @@ package fwserver
import (
"context"

"github.com/hashicorp/terraform-plugin-go/tftypes"

"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/internal/fwschemadata"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-go/tftypes"
)

func coerceListValue(schemaPath path.Path, value attr.Value) (types.List, diag.Diagnostics) {
list, ok := value.(types.List)
func coerceListValue(ctx context.Context, schemaPath path.Path, value attr.Value) (types.List, diag.Diagnostics) {
listVal, ok := value.(types.ListValuable)

if !ok {
return types.ListNull(nil), diag.Diagnostics{
attributePlanModificationWalkError(schemaPath, value),
}
}

return list, nil
return listVal.ToListValue(ctx)
}

func coerceMapValue(schemaPath path.Path, value attr.Value) (types.Map, diag.Diagnostics) {
m, ok := value.(types.Map)
func coerceMapValue(ctx context.Context, schemaPath path.Path, value attr.Value) (types.Map, diag.Diagnostics) {
mapVal, ok := value.(types.MapValuable)

if !ok {
return types.MapNull(nil), diag.Diagnostics{
attributePlanModificationWalkError(schemaPath, value),
}
}

return m, nil
return mapVal.ToMapValue(ctx)
}

func coerceObjectValue(schemaPath path.Path, value attr.Value) (types.Object, diag.Diagnostics) {
object, ok := value.(types.Object)
func coerceObjectValue(ctx context.Context, schemaPath path.Path, value attr.Value) (types.Object, diag.Diagnostics) {
objectVal, ok := value.(types.ObjectValuable)

if !ok {
return types.ObjectNull(nil), diag.Diagnostics{
attributePlanModificationWalkError(schemaPath, value),
}
}

return object, nil
return objectVal.ToObjectValue(ctx)
}

func coerceSetValue(schemaPath path.Path, value attr.Value) (types.Set, diag.Diagnostics) {
set, ok := value.(types.Set)
func coerceSetValue(ctx context.Context, schemaPath path.Path, value attr.Value) (types.Set, diag.Diagnostics) {
setVal, ok := value.(types.SetValuable)

if !ok {
return types.SetNull(nil), diag.Diagnostics{
attributePlanModificationWalkError(schemaPath, value),
}
}

return set, nil
return setVal.ToSetValue(ctx)
}

func listElemObject(ctx context.Context, schemaPath path.Path, list types.List, index int, description fwschemadata.DataDescription) (types.Object, diag.Diagnostics) {
Expand All @@ -72,7 +73,7 @@ func listElemObject(ctx context.Context, schemaPath path.Path, list types.List,
return listElemObjectFromTerraformValue(ctx, schemaPath, list, description, nil)
}

return coerceObjectValue(schemaPath, list.Elements()[index])
return coerceObjectValue(ctx, schemaPath, list.Elements()[index])
}

func listElemObjectFromTerraformValue(ctx context.Context, schemaPath path.Path, list types.List, description fwschemadata.DataDescription, tfValue any) (types.Object, diag.Diagnostics) {
Expand All @@ -85,7 +86,7 @@ func listElemObjectFromTerraformValue(ctx context.Context, schemaPath path.Path,
}
}

return coerceObjectValue(schemaPath, elemValue)
return coerceObjectValue(ctx, schemaPath, elemValue)
}

func mapElemObject(ctx context.Context, schemaPath path.Path, m types.Map, key string, description fwschemadata.DataDescription) (types.Object, diag.Diagnostics) {
Expand All @@ -103,7 +104,7 @@ func mapElemObject(ctx context.Context, schemaPath path.Path, m types.Map, key s
return mapElemObjectFromTerraformValue(ctx, schemaPath, m, description, nil)
}

return coerceObjectValue(schemaPath, elemValue)
return coerceObjectValue(ctx, schemaPath, elemValue)
}

func mapElemObjectFromTerraformValue(ctx context.Context, schemaPath path.Path, m types.Map, description fwschemadata.DataDescription, tfValue any) (types.Object, diag.Diagnostics) {
Expand All @@ -116,7 +117,7 @@ func mapElemObjectFromTerraformValue(ctx context.Context, schemaPath path.Path,
}
}

return coerceObjectValue(schemaPath, elemValue)
return coerceObjectValue(ctx, schemaPath, elemValue)
}

func objectAttributeValue(ctx context.Context, object types.Object, attributeName string, description fwschemadata.DataDescription) (attr.Value, diag.Diagnostics) {
Expand Down Expand Up @@ -162,7 +163,7 @@ func setElemObject(ctx context.Context, schemaPath path.Path, set types.Set, ind
return setElemObjectFromTerraformValue(ctx, schemaPath, set, description, nil)
}

return coerceObjectValue(schemaPath, set.Elements()[index])
return coerceObjectValue(ctx, schemaPath, set.Elements()[index])
}

func setElemObjectFromTerraformValue(ctx context.Context, schemaPath path.Path, set types.Set, description fwschemadata.DataDescription, tfValue any) (types.Object, diag.Diagnostics) {
Expand All @@ -175,5 +176,5 @@ func setElemObjectFromTerraformValue(ctx context.Context, schemaPath path.Path,
}
}

return coerceObjectValue(schemaPath, elemValue)
return coerceObjectValue(ctx, schemaPath, elemValue)
}
30 changes: 15 additions & 15 deletions internal/fwserver/attribute_plan_modification.go
Expand Up @@ -98,23 +98,23 @@ func AttributeModifyPlan(ctx context.Context, a fwschema.Attribute, req tfsdk.Mo
nm := a.GetAttributes().GetNestingMode()
switch nm {
case fwschema.NestingModeList:
configList, diags := coerceListValue(req.AttributePath, req.AttributeConfig)
configList, diags := coerceListValue(ctx, req.AttributePath, req.AttributeConfig)

resp.Diagnostics.Append(diags...)

if resp.Diagnostics.HasError() {
return
}

planList, diags := coerceListValue(req.AttributePath, req.AttributePlan)
planList, diags := coerceListValue(ctx, req.AttributePath, req.AttributePlan)

resp.Diagnostics.Append(diags...)

if resp.Diagnostics.HasError() {
return
}

stateList, diags := coerceListValue(req.AttributePath, req.AttributeState)
stateList, diags := coerceListValue(ctx, req.AttributePath, req.AttributeState)

resp.Diagnostics.Append(diags...)

Expand All @@ -135,7 +135,7 @@ func AttributeModifyPlan(ctx context.Context, a fwschema.Attribute, req tfsdk.Mo
return
}

planObject, diags := coerceObjectValue(attrPath, planElem)
planObject, diags := coerceObjectValue(ctx, attrPath, planElem)

resp.Diagnostics.Append(diags...)

Expand Down Expand Up @@ -220,23 +220,23 @@ func AttributeModifyPlan(ctx context.Context, a fwschema.Attribute, req tfsdk.Mo
return
}
case fwschema.NestingModeSet:
configSet, diags := coerceSetValue(req.AttributePath, req.AttributeConfig)
configSet, diags := coerceSetValue(ctx, req.AttributePath, req.AttributeConfig)

resp.Diagnostics.Append(diags...)

if resp.Diagnostics.HasError() {
return
}

planSet, diags := coerceSetValue(req.AttributePath, req.AttributePlan)
planSet, diags := coerceSetValue(ctx, req.AttributePath, req.AttributePlan)

resp.Diagnostics.Append(diags...)

if resp.Diagnostics.HasError() {
return
}

stateSet, diags := coerceSetValue(req.AttributePath, req.AttributeState)
stateSet, diags := coerceSetValue(ctx, req.AttributePath, req.AttributeState)

resp.Diagnostics.Append(diags...)

Expand All @@ -257,7 +257,7 @@ func AttributeModifyPlan(ctx context.Context, a fwschema.Attribute, req tfsdk.Mo
return
}

planObject, diags := coerceObjectValue(attrPath, planElem)
planObject, diags := coerceObjectValue(ctx, attrPath, planElem)

resp.Diagnostics.Append(diags...)

Expand Down Expand Up @@ -342,23 +342,23 @@ func AttributeModifyPlan(ctx context.Context, a fwschema.Attribute, req tfsdk.Mo
return
}
case fwschema.NestingModeMap:
configMap, diags := coerceMapValue(req.AttributePath, req.AttributeConfig)
configMap, diags := coerceMapValue(ctx, req.AttributePath, req.AttributeConfig)

resp.Diagnostics.Append(diags...)

if resp.Diagnostics.HasError() {
return
}

planMap, diags := coerceMapValue(req.AttributePath, req.AttributePlan)
planMap, diags := coerceMapValue(ctx, req.AttributePath, req.AttributePlan)

resp.Diagnostics.Append(diags...)

if resp.Diagnostics.HasError() {
return
}

stateMap, diags := coerceMapValue(req.AttributePath, req.AttributeState)
stateMap, diags := coerceMapValue(ctx, req.AttributePath, req.AttributeState)

resp.Diagnostics.Append(diags...)

Expand All @@ -379,7 +379,7 @@ func AttributeModifyPlan(ctx context.Context, a fwschema.Attribute, req tfsdk.Mo
return
}

planObject, diags := coerceObjectValue(attrPath, planElem)
planObject, diags := coerceObjectValue(ctx, attrPath, planElem)

resp.Diagnostics.Append(diags...)

Expand Down Expand Up @@ -464,23 +464,23 @@ func AttributeModifyPlan(ctx context.Context, a fwschema.Attribute, req tfsdk.Mo
return
}
case fwschema.NestingModeSingle:
configObject, diags := coerceObjectValue(req.AttributePath, req.AttributeConfig)
configObject, diags := coerceObjectValue(ctx, req.AttributePath, req.AttributeConfig)

resp.Diagnostics.Append(diags...)

if resp.Diagnostics.HasError() {
return
}

planObject, diags := coerceObjectValue(req.AttributePath, req.AttributePlan)
planObject, diags := coerceObjectValue(ctx, req.AttributePath, req.AttributePlan)

resp.Diagnostics.Append(diags...)

if resp.Diagnostics.HasError() {
return
}

stateObject, diags := coerceObjectValue(req.AttributePath, req.AttributeState)
stateObject, diags := coerceObjectValue(ctx, req.AttributePath, req.AttributeState)

resp.Diagnostics.Append(diags...)

Expand Down

0 comments on commit bf1ce9b

Please sign in to comment.