Skip to content

Commit

Permalink
Adding ValueFromFramework and ToFrameworkValue interface functions to…
Browse files Browse the repository at this point in the history
… types.MapType and types.Map (value), respectively (#535)
  • Loading branch information
bendbennett committed Nov 11, 2022
1 parent f6c3071 commit 467f056
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 14 deletions.
6 changes: 3 additions & 3 deletions internal/fwserver/attr_value.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,16 @@ func coerceListValue(ctx context.Context, schemaPath path.Path, value attr.Value
return listVal.ToFrameworkValue(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.MapVal)

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

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

func coerceObjectValue(schemaPath path.Path, value attr.Value) (types.Object, diag.Diagnostics) {
Expand Down
6 changes: 3 additions & 3 deletions internal/fwserver/attribute_plan_modification.go
Original file line number Diff line number Diff line change
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 Down
13 changes: 10 additions & 3 deletions internal/fwserver/attribute_validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,19 +207,26 @@ func AttributeValidateNestedAttributes(ctx context.Context, a fwschema.Attribute
}
}
case fwschema.NestingModeMap:
m, ok := req.AttributeConfig.(types.Map)
mapVal, ok := req.AttributeConfig.(types.MapVal)

if !ok {
err := fmt.Errorf("unknown attribute value type (%T) for nesting mode (%T) at path: %s", req.AttributeConfig, nm, req.AttributePath)
resp.Diagnostics.AddAttributeError(
req.AttributePath,
"Attribute Validation Error",
"Attribute validation cannot walk schema. Report this to the provider developer:\n\n"+err.Error(),
"Attribute Validation Error Invalid Value Type",
"A type from which a types.Map can be obtained is expected here. Report this to the provider developer:\n\n"+err.Error(),
)

return
}

m, diags := mapVal.ToFrameworkValue(ctx)

resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}

for key := range m.Elements() {
for nestedName, nestedAttr := range a.GetAttributes().GetAttributes() {
nestedAttrReq := tfsdk.ValidateAttributeRequest{
Expand Down
32 changes: 27 additions & 5 deletions types/map.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,22 @@ import (
)

var (
_ attr.Type = MapType{}
_ attr.Value = &Map{}
_ MapTyp = MapType{}
_ MapVal = &Map{}
)

type MapTyp interface {
attr.Type

ValueFromFramework(context.Context, Map) (attr.Value, diag.Diagnostics)
}

type MapVal interface {
attr.Value

ToFrameworkValue(ctx context.Context) (Map, diag.Diagnostics)
}

// MapType is an AttributeType representing a map of values. All values must
// be of the same type, which the provider must specify as the ElemType
// property. Keys will always be strings.
Expand Down Expand Up @@ -163,12 +175,17 @@ func (m MapType) Validate(ctx context.Context, in tftypes.Value, path path.Path)
}

// ValueType returns the Value type.
func (t MapType) ValueType(_ context.Context) attr.Value {
func (m MapType) ValueType(_ context.Context) attr.Value {
return Map{
elementType: t.ElemType,
elementType: m.ElemType,
}
}

// ValueFromFramework returns an attr.Value given a Map.
func (m MapType) ValueFromFramework(_ context.Context, ma Map) (attr.Value, diag.Diagnostics) {
return ma, nil
}

// MapNull creates a Map with a null value. Determine whether the value is
// null via the Map type IsNull method.
func MapNull(elementType attr.Type) Map {
Expand Down Expand Up @@ -329,7 +346,7 @@ func (m Map) Type(ctx context.Context) attr.Type {
return MapType{ElemType: m.ElementType(ctx)}
}

// ToTerraformValue returns the data contained in the List as a tftypes.Value.
// ToTerraformValue returns the data contained in the Map as a tftypes.Value.
func (m Map) ToTerraformValue(ctx context.Context) (tftypes.Value, error) {
mapType := tftypes.Map{ElementType: m.ElementType(ctx).TerraformType(ctx)}

Expand Down Expand Up @@ -441,3 +458,8 @@ func (m Map) String() string {

return res.String()
}

// ToFrameworkValue returns the Map.
func (m Map) ToFrameworkValue(context.Context) (Map, diag.Diagnostics) {
return m, nil
}

0 comments on commit 467f056

Please sign in to comment.