From 94d03e6d3ef2e61b90e65b13a7d8c4fa87100528 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Fri, 11 Nov 2022 10:28:48 +0000 Subject: [PATCH] Adding ValueFromFramework and ToFrameworkValue interface functions to types.SetType and types.Set (value), respectively (#535) --- internal/fwserver/attr_value.go | 6 ++-- .../fwserver/attribute_plan_modification.go | 6 ++-- internal/fwserver/attribute_validation.go | 13 ++++++-- internal/fwserver/block_plan_modification.go | 6 ++-- internal/fwserver/block_validation.go | 15 +++++++--- types/set.go | 30 ++++++++++++++++--- 6 files changed, 56 insertions(+), 20 deletions(-) diff --git a/internal/fwserver/attr_value.go b/internal/fwserver/attr_value.go index 9bb36f560..3fd9c2ec5 100644 --- a/internal/fwserver/attr_value.go +++ b/internal/fwserver/attr_value.go @@ -48,8 +48,8 @@ func coerceObjectValue(schemaPath path.Path, value attr.Value) (types.Object, di return object, nil } -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.SetVal) if !ok { return types.SetNull(nil), diag.Diagnostics{ @@ -57,7 +57,7 @@ func coerceSetValue(schemaPath path.Path, value attr.Value) (types.Set, diag.Dia } } - return set, nil + return setVal.ToFrameworkValue(ctx) } func listElemObject(ctx context.Context, schemaPath path.Path, list types.List, index int, description fwschemadata.DataDescription) (types.Object, diag.Diagnostics) { diff --git a/internal/fwserver/attribute_plan_modification.go b/internal/fwserver/attribute_plan_modification.go index 26bb49281..6ed801593 100644 --- a/internal/fwserver/attribute_plan_modification.go +++ b/internal/fwserver/attribute_plan_modification.go @@ -220,7 +220,7 @@ 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...) @@ -228,7 +228,7 @@ func AttributeModifyPlan(ctx context.Context, a fwschema.Attribute, req tfsdk.Mo return } - planSet, diags := coerceSetValue(req.AttributePath, req.AttributePlan) + planSet, diags := coerceSetValue(ctx, req.AttributePath, req.AttributePlan) resp.Diagnostics.Append(diags...) @@ -236,7 +236,7 @@ func AttributeModifyPlan(ctx context.Context, a fwschema.Attribute, req tfsdk.Mo return } - stateSet, diags := coerceSetValue(req.AttributePath, req.AttributeState) + stateSet, diags := coerceSetValue(ctx, req.AttributePath, req.AttributeState) resp.Diagnostics.Append(diags...) diff --git a/internal/fwserver/attribute_validation.go b/internal/fwserver/attribute_validation.go index 3cc0a35db..f4b3bbfd3 100644 --- a/internal/fwserver/attribute_validation.go +++ b/internal/fwserver/attribute_validation.go @@ -177,19 +177,26 @@ func AttributeValidateNestedAttributes(ctx context.Context, a fwschema.Attribute } } case fwschema.NestingModeSet: - s, ok := req.AttributeConfig.(types.Set) + setVal, ok := req.AttributeConfig.(types.SetVal) 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.Set can be obtained is expected here. Report this to the provider developer:\n\n"+err.Error(), ) return } + s, diags := setVal.ToFrameworkValue(ctx) + + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + for _, value := range s.Elements() { for nestedName, nestedAttr := range a.GetAttributes().GetAttributes() { nestedAttrReq := tfsdk.ValidateAttributeRequest{ diff --git a/internal/fwserver/block_plan_modification.go b/internal/fwserver/block_plan_modification.go index 6891cb344..db8574f14 100644 --- a/internal/fwserver/block_plan_modification.go +++ b/internal/fwserver/block_plan_modification.go @@ -236,7 +236,7 @@ func BlockModifyPlan(ctx context.Context, b fwschema.Block, req tfsdk.ModifyAttr return } case fwschema.BlockNestingModeSet: - configSet, diags := coerceSetValue(req.AttributePath, req.AttributeConfig) + configSet, diags := coerceSetValue(ctx, req.AttributePath, req.AttributeConfig) resp.Diagnostics.Append(diags...) @@ -244,7 +244,7 @@ func BlockModifyPlan(ctx context.Context, b fwschema.Block, req tfsdk.ModifyAttr return } - planSet, diags := coerceSetValue(req.AttributePath, req.AttributePlan) + planSet, diags := coerceSetValue(ctx, req.AttributePath, req.AttributePlan) resp.Diagnostics.Append(diags...) @@ -252,7 +252,7 @@ func BlockModifyPlan(ctx context.Context, b fwschema.Block, req tfsdk.ModifyAttr return } - stateSet, diags := coerceSetValue(req.AttributePath, req.AttributeState) + stateSet, diags := coerceSetValue(ctx, req.AttributePath, req.AttributeState) resp.Diagnostics.Append(diags...) diff --git a/internal/fwserver/block_validation.go b/internal/fwserver/block_validation.go index 16bd5ae71..3eac5c8d0 100644 --- a/internal/fwserver/block_validation.go +++ b/internal/fwserver/block_validation.go @@ -124,19 +124,26 @@ func BlockValidate(ctx context.Context, b fwschema.Block, req tfsdk.ValidateAttr resp.Diagnostics.Append(blockMinItemsDiagnostic(req.AttributePath, b.GetMinItems(), len(l.Elements()))) } case fwschema.BlockNestingModeSet: - s, ok := req.AttributeConfig.(types.Set) + setVal, ok := req.AttributeConfig.(types.SetVal) if !ok { - err := fmt.Errorf("unknown block value type (%s) for nesting mode (%T) at path: %s", req.AttributeConfig.Type(ctx), nm, req.AttributePath) + err := fmt.Errorf("unknown block value type (%T) for nesting mode (%T) at path: %s", req.AttributeConfig, nm, req.AttributePath) resp.Diagnostics.AddAttributeError( req.AttributePath, - "Block Validation Error", - "Block validation cannot walk schema. Report this to the provider developer:\n\n"+err.Error(), + "Block Validation Error Invalid Value Type", + "A type from which a types.Set can be obtained is expected here. Report this to the provider developer:\n\n"+err.Error(), ) return } + s, diags := setVal.ToFrameworkValue(ctx) + + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + for _, value := range s.Elements() { for name, attr := range b.GetAttributes() { nestedAttrReq := tfsdk.ValidateAttributeRequest{ diff --git a/types/set.go b/types/set.go index 18c386d71..581a12c17 100644 --- a/types/set.go +++ b/types/set.go @@ -15,11 +15,23 @@ import ( ) var ( - _ attr.Type = SetType{} + _ SetTyp = SetType{} _ xattr.TypeWithValidate = SetType{} - _ attr.Value = &Set{} + _ SetVal = &Set{} ) +type SetTyp interface { + attr.Type + + ValueFromFramework(context.Context, Set) (attr.Value, diag.Diagnostics) +} + +type SetVal interface { + attr.Value + + ToFrameworkValue(ctx context.Context) (Set, diag.Diagnostics) +} + // SetType is an AttributeType representing a set of values. All values must // be of the same type, which the provider must specify as the ElemType // property. @@ -191,12 +203,17 @@ func (st SetType) Validate(ctx context.Context, in tftypes.Value, path path.Path } // ValueType returns the Value type. -func (t SetType) ValueType(_ context.Context) attr.Value { +func (st SetType) ValueType(_ context.Context) attr.Value { return Set{ - elementType: t.ElemType, + elementType: st.ElemType, } } +// ValueFromFramework returns an attr.Value given a Set. +func (st SetType) ValueFromFramework(_ context.Context, set Set) (attr.Value, diag.Diagnostics) { + return set, nil +} + // SetNull creates a Set with a null value. Determine whether the value is // null via the Set type IsNull method. func SetNull(elementType attr.Type) Set { @@ -467,3 +484,8 @@ func (s Set) String() string { return res.String() } + +// ToFrameworkValue returns the Set. +func (s Set) ToFrameworkValue(context.Context) (Set, diag.Diagnostics) { + return s, nil +}