From 23bcbac24d55d45b7cf9788d703b550b9d73b39e Mon Sep 17 00:00:00 2001 From: Brian Flad Date: Fri, 3 Sep 2021 10:13:55 -0400 Subject: [PATCH] attr: Add attribute path parameter to (TypeWithValidate).Validate() method Reference: https://github.com/hashicorp/terraform-plugin-framework/issues/127 --- attr/type.go | 2 +- internal/reflect/interfaces.go | 14 ++++++------- internal/reflect/map.go | 6 +++--- internal/reflect/number.go | 10 ++++----- internal/reflect/number_test.go | 20 +++++++++--------- internal/reflect/pointer.go | 2 +- internal/reflect/pointer_test.go | 4 ++-- internal/reflect/primitive.go | 4 ++-- internal/reflect/primitive_test.go | 8 +++---- internal/reflect/slice.go | 6 +++--- internal/reflect/struct.go | 4 ++-- internal/testing/types/boolwithvalidate.go | 8 +++---- internal/testing/types/diags.go | 14 +++++++++---- internal/testing/types/numberwithvalidate.go | 8 +++---- internal/testing/types/stringwithvalidate.go | 8 +++---- tfsdk/attribute_test.go | 4 ++-- tfsdk/config.go | 2 +- tfsdk/config_test.go | 8 +++---- tfsdk/plan.go | 4 ++-- tfsdk/plan_test.go | 22 +++++++++++++------- tfsdk/state.go | 4 ++-- tfsdk/state_test.go | 22 +++++++++++++------- 22 files changed, 101 insertions(+), 83 deletions(-) diff --git a/attr/type.go b/attr/type.go index db1e6c339..5a74c4962 100644 --- a/attr/type.go +++ b/attr/type.go @@ -80,7 +80,7 @@ type TypeWithValidate interface { // being used to populate the Type. It is generally used to check the // data format and ensure that it complies with the requirements of the // Type. - Validate(context.Context, tftypes.Value) diag.Diagnostics + Validate(context.Context, tftypes.Value, *tftypes.AttributePath) diag.Diagnostics } // TypeWithPlaintextDescription extends the Type interface to include a diff --git a/internal/reflect/interfaces.go b/internal/reflect/interfaces.go index b13762789..6783c5b1b 100644 --- a/internal/reflect/interfaces.go +++ b/internal/reflect/interfaces.go @@ -70,7 +70,7 @@ func FromUnknownable(ctx context.Context, typ attr.Type, val Unknownable, path * tfVal := tftypes.NewValue(typ.TerraformType(ctx), tftypes.UnknownValue) if typeWithValidate, ok := typ.(attr.TypeWithValidate); ok { - diags.Append(typeWithValidate.Validate(ctx, tfVal)...) + diags.Append(typeWithValidate.Validate(ctx, tfVal, path)...) if diags.HasError() { return nil, diags @@ -91,7 +91,7 @@ func FromUnknownable(ctx context.Context, typ attr.Type, val Unknownable, path * tfVal := tftypes.NewValue(typ.TerraformType(ctx), val.GetValue(ctx)) if typeWithValidate, ok := typ.(attr.TypeWithValidate); ok { - diags.Append(typeWithValidate.Validate(ctx, tfVal)...) + diags.Append(typeWithValidate.Validate(ctx, tfVal, path)...) if diags.HasError() { return nil, diags @@ -164,7 +164,7 @@ func FromNullable(ctx context.Context, typ attr.Type, val Nullable, path *tftype tfVal := tftypes.NewValue(typ.TerraformType(ctx), nil) if typeWithValidate, ok := typ.(attr.TypeWithValidate); ok { - diags.Append(typeWithValidate.Validate(ctx, tfVal)...) + diags.Append(typeWithValidate.Validate(ctx, tfVal, path)...) if diags.HasError() { return nil, diags @@ -185,7 +185,7 @@ func FromNullable(ctx context.Context, typ attr.Type, val Nullable, path *tftype tfVal := tftypes.NewValue(typ.TerraformType(ctx), val.GetValue(ctx)) if typeWithValidate, ok := typ.(attr.TypeWithValidate); ok { - diags.Append(typeWithValidate.Validate(ctx, tfVal)...) + diags.Append(typeWithValidate.Validate(ctx, tfVal, path)...) if diags.HasError() { return nil, diags @@ -256,7 +256,7 @@ func FromValueCreator(ctx context.Context, typ attr.Type, val tftypes.ValueCreat tfVal := tftypes.NewValue(typ.TerraformType(ctx), raw) if typeWithValidate, ok := typ.(attr.TypeWithValidate); ok { - diags.Append(typeWithValidate.Validate(ctx, tfVal)...) + diags.Append(typeWithValidate.Validate(ctx, tfVal, path)...) if diags.HasError() { return nil, diags @@ -279,7 +279,7 @@ func NewAttributeValue(ctx context.Context, typ attr.Type, val tftypes.Value, ta var diags diag.Diagnostics if typeWithValidate, ok := typ.(attr.TypeWithValidate); ok { - diags.Append(typeWithValidate.Validate(ctx, val)...) + diags.Append(typeWithValidate.Validate(ctx, val, path)...) if diags.HasError() { return target, diags @@ -319,7 +319,7 @@ func FromAttributeValue(ctx context.Context, typ attr.Type, val attr.Value, path return val, append(diags, toTerraformValueErrorDiag(err, path)) } - diags.Append(typeWithValidate.Validate(ctx, tftypes.NewValue(tfType, tfVal))...) + diags.Append(typeWithValidate.Validate(ctx, tftypes.NewValue(tfType, tfVal), path)...) if diags.HasError() { return val, diags diff --git a/internal/reflect/map.go b/internal/reflect/map.go index b3616ac81..8ae46bff2 100644 --- a/internal/reflect/map.go +++ b/internal/reflect/map.go @@ -102,7 +102,7 @@ func FromMap(ctx context.Context, typ attr.TypeWithElementType, val reflect.Valu tfVal := tftypes.NewValue(tfType, nil) if typeWithValidate, ok := typ.(attr.TypeWithValidate); ok { - diags.Append(typeWithValidate.Validate(ctx, tfVal)...) + diags.Append(typeWithValidate.Validate(ctx, tfVal, path)...) if diags.HasError() { return nil, diags @@ -156,7 +156,7 @@ func FromMap(ctx context.Context, typ attr.TypeWithElementType, val reflect.Valu tfElemVal := tftypes.NewValue(tfElemType, tfVal) if typeWithValidate, ok := typ.(attr.TypeWithValidate); ok { - diags.Append(typeWithValidate.Validate(ctx, tfElemVal)...) + diags.Append(typeWithValidate.Validate(ctx, tfElemVal, path.WithElementKeyString(key.String()))...) if diags.HasError() { return nil, diags @@ -174,7 +174,7 @@ func FromMap(ctx context.Context, typ attr.TypeWithElementType, val reflect.Valu tfVal := tftypes.NewValue(tfType, tfElems) if typeWithValidate, ok := typ.(attr.TypeWithValidate); ok { - diags.Append(typeWithValidate.Validate(ctx, tfVal)...) + diags.Append(typeWithValidate.Validate(ctx, tfVal, path)...) if diags.HasError() { return nil, diags diff --git a/internal/reflect/number.go b/internal/reflect/number.go index 520febe31..643f725b4 100644 --- a/internal/reflect/number.go +++ b/internal/reflect/number.go @@ -245,7 +245,7 @@ func FromInt(ctx context.Context, typ attr.Type, val int64, path *tftypes.Attrib tfNum := tftypes.NewValue(tftypes.Number, val) if typeWithValidate, ok := typ.(attr.TypeWithValidate); ok { - diags.Append(typeWithValidate.Validate(ctx, tfNum)...) + diags.Append(typeWithValidate.Validate(ctx, tfNum, path)...) if diags.HasError() { return nil, diags @@ -272,7 +272,7 @@ func FromUint(ctx context.Context, typ attr.Type, val uint64, path *tftypes.Attr tfNum := tftypes.NewValue(tftypes.Number, val) if typeWithValidate, ok := typ.(attr.TypeWithValidate); ok { - diags.Append(typeWithValidate.Validate(ctx, tfNum)...) + diags.Append(typeWithValidate.Validate(ctx, tfNum, path)...) if diags.HasError() { return nil, diags @@ -299,7 +299,7 @@ func FromFloat(ctx context.Context, typ attr.Type, val float64, path *tftypes.At tfNum := tftypes.NewValue(tftypes.Number, val) if typeWithValidate, ok := typ.(attr.TypeWithValidate); ok { - diags.Append(typeWithValidate.Validate(ctx, tfNum)...) + diags.Append(typeWithValidate.Validate(ctx, tfNum, path)...) if diags.HasError() { return nil, diags @@ -326,7 +326,7 @@ func FromBigFloat(ctx context.Context, typ attr.Type, val *big.Float, path *tfty tfNum := tftypes.NewValue(tftypes.Number, val) if typeWithValidate, ok := typ.(attr.TypeWithValidate); ok { - diags.Append(typeWithValidate.Validate(ctx, tfNum)...) + diags.Append(typeWithValidate.Validate(ctx, tfNum, path)...) if diags.HasError() { return nil, diags @@ -354,7 +354,7 @@ func FromBigInt(ctx context.Context, typ attr.Type, val *big.Int, path *tftypes. tfNum := tftypes.NewValue(tftypes.Number, fl) if typeWithValidate, ok := typ.(attr.TypeWithValidate); ok { - diags.Append(typeWithValidate.Validate(ctx, tfNum)...) + diags.Append(typeWithValidate.Validate(ctx, tfNum, path)...) if diags.HasError() { return nil, diags diff --git a/internal/reflect/number_test.go b/internal/reflect/number_test.go index 6ce6019c9..54510db77 100644 --- a/internal/reflect/number_test.go +++ b/internal/reflect/number_test.go @@ -1202,14 +1202,14 @@ func TestFromInt(t *testing.T) { Value: big.NewFloat(1), }, expectedDiags: diag.Diagnostics{ - testtypes.TestWarningDiagnostic, + testtypes.TestWarningDiagnostic(tftypes.NewAttributePath()), }, }, "WithValidateError": { val: 1, typ: testtypes.NumberTypeWithValidateError{}, expectedDiags: diag.Diagnostics{ - testtypes.TestErrorDiagnostic, + testtypes.TestErrorDiagnostic(tftypes.NewAttributePath()), }, }, } @@ -1261,14 +1261,14 @@ func TestFromUint(t *testing.T) { Value: big.NewFloat(1), }, expectedDiags: diag.Diagnostics{ - testtypes.TestWarningDiagnostic, + testtypes.TestWarningDiagnostic(tftypes.NewAttributePath()), }, }, "WithValidateError": { val: 1, typ: testtypes.NumberTypeWithValidateError{}, expectedDiags: diag.Diagnostics{ - testtypes.TestErrorDiagnostic, + testtypes.TestErrorDiagnostic(tftypes.NewAttributePath()), }, }, } @@ -1327,14 +1327,14 @@ func TestFromFloat(t *testing.T) { Value: big.NewFloat(1), }, expectedDiags: diag.Diagnostics{ - testtypes.TestWarningDiagnostic, + testtypes.TestWarningDiagnostic(tftypes.NewAttributePath()), }, }, "WithValidateError": { val: 1, typ: testtypes.NumberTypeWithValidateError{}, expectedDiags: diag.Diagnostics{ - testtypes.TestErrorDiagnostic, + testtypes.TestErrorDiagnostic(tftypes.NewAttributePath()), }, }, } @@ -1393,14 +1393,14 @@ func TestFromBigFloat(t *testing.T) { Value: big.NewFloat(1), }, expectedDiags: diag.Diagnostics{ - testtypes.TestWarningDiagnostic, + testtypes.TestWarningDiagnostic(tftypes.NewAttributePath()), }, }, "WithValidateError": { val: big.NewFloat(1), typ: testtypes.NumberTypeWithValidateError{}, expectedDiags: diag.Diagnostics{ - testtypes.TestErrorDiagnostic, + testtypes.TestErrorDiagnostic(tftypes.NewAttributePath()), }, }, } @@ -1452,14 +1452,14 @@ func TestFromBigInt(t *testing.T) { Value: big.NewFloat(1), }, expectedDiags: diag.Diagnostics{ - testtypes.TestWarningDiagnostic, + testtypes.TestWarningDiagnostic(tftypes.NewAttributePath()), }, }, "WithValidateError": { val: big.NewInt(1), typ: testtypes.NumberTypeWithValidateError{}, expectedDiags: diag.Diagnostics{ - testtypes.TestErrorDiagnostic, + testtypes.TestErrorDiagnostic(tftypes.NewAttributePath()), }, }, } diff --git a/internal/reflect/pointer.go b/internal/reflect/pointer.go index bb1795ee5..e4262f25a 100644 --- a/internal/reflect/pointer.go +++ b/internal/reflect/pointer.go @@ -90,7 +90,7 @@ func FromPointer(ctx context.Context, typ attr.Type, value reflect.Value, path * tfVal := tftypes.NewValue(typ.TerraformType(ctx), nil) if typeWithValidate, ok := typ.(attr.TypeWithValidate); ok { - diags.Append(typeWithValidate.Validate(ctx, tfVal)...) + diags.Append(typeWithValidate.Validate(ctx, tfVal, path)...) if diags.HasError() { return nil, diags diff --git a/internal/reflect/pointer_test.go b/internal/reflect/pointer_test.go index d8fdd4961..1df3b5df7 100644 --- a/internal/reflect/pointer_test.go +++ b/internal/reflect/pointer_test.go @@ -109,7 +109,7 @@ func TestFromPointer(t *testing.T) { typ: testtypes.StringTypeWithValidateError{}, val: reflect.ValueOf(strPtr("hello, world")), expectedDiags: diag.Diagnostics{ - testtypes.TestErrorDiagnostic, + testtypes.TestErrorDiagnostic(tftypes.NewAttributePath()), }, }, "WithValidateWarning": { @@ -119,7 +119,7 @@ func TestFromPointer(t *testing.T) { Value: "hello, world", }, expectedDiags: diag.Diagnostics{ - testtypes.TestWarningDiagnostic, + testtypes.TestWarningDiagnostic(tftypes.NewAttributePath()), }, }, } diff --git a/internal/reflect/primitive.go b/internal/reflect/primitive.go index 2e387bdee..983d94e23 100644 --- a/internal/reflect/primitive.go +++ b/internal/reflect/primitive.go @@ -65,7 +65,7 @@ func FromString(ctx context.Context, typ attr.Type, val string, path *tftypes.At tfStr := tftypes.NewValue(tftypes.String, val) if typeWithValidate, ok := typ.(attr.TypeWithValidate); ok { - diags.Append(typeWithValidate.Validate(ctx, tfStr)...) + diags.Append(typeWithValidate.Validate(ctx, tfStr, path)...) if diags.HasError() { return nil, diags @@ -92,7 +92,7 @@ func FromBool(ctx context.Context, typ attr.Type, val bool, path *tftypes.Attrib tfBool := tftypes.NewValue(tftypes.Bool, val) if typeWithValidate, ok := typ.(attr.TypeWithValidate); ok { - diags.Append(typeWithValidate.Validate(ctx, tfBool)...) + diags.Append(typeWithValidate.Validate(ctx, tfBool, path)...) if diags.HasError() { return nil, diags diff --git a/internal/reflect/primitive_test.go b/internal/reflect/primitive_test.go index bb831fb06..36c79e420 100644 --- a/internal/reflect/primitive_test.go +++ b/internal/reflect/primitive_test.go @@ -99,14 +99,14 @@ func TestFromString(t *testing.T) { Value: "mystring", }, expectedDiags: diag.Diagnostics{ - testtypes.TestWarningDiagnostic, + testtypes.TestWarningDiagnostic(tftypes.NewAttributePath()), }, }, "WithValidateError": { val: "mystring", typ: testtypes.StringTypeWithValidateError{}, expectedDiags: diag.Diagnostics{ - testtypes.TestErrorDiagnostic, + testtypes.TestErrorDiagnostic(tftypes.NewAttributePath()), }, }, } @@ -159,14 +159,14 @@ func TestFromBool(t *testing.T) { Value: true, }, expectedDiags: diag.Diagnostics{ - testtypes.TestWarningDiagnostic, + testtypes.TestWarningDiagnostic(tftypes.NewAttributePath()), }, }, "WithValidateError": { val: true, typ: testtypes.BoolTypeWithValidateError{}, expectedDiags: diag.Diagnostics{ - testtypes.TestErrorDiagnostic, + testtypes.TestErrorDiagnostic(tftypes.NewAttributePath()), }, }, } diff --git a/internal/reflect/slice.go b/internal/reflect/slice.go index 0be5e4641..bf0520b03 100644 --- a/internal/reflect/slice.go +++ b/internal/reflect/slice.go @@ -99,7 +99,7 @@ func FromSlice(ctx context.Context, typ attr.Type, val reflect.Value, path *tfty tfVal := tftypes.NewValue(tfType, nil) if typeWithValidate, ok := typ.(attr.TypeWithValidate); ok { - diags.Append(typeWithValidate.Validate(ctx, tfVal)...) + diags.Append(typeWithValidate.Validate(ctx, tfVal, path)...) if diags.HasError() { return nil, diags @@ -152,7 +152,7 @@ func FromSlice(ctx context.Context, typ attr.Type, val reflect.Value, path *tfty tfElemVal := tftypes.NewValue(elemType.TerraformType(ctx), tfVal) if typeWithValidate, ok := typ.(attr.TypeWithValidate); ok { - diags.Append(typeWithValidate.Validate(ctx, tfElemVal)...) + diags.Append(typeWithValidate.Validate(ctx, tfElemVal, path.WithElementKeyInt(int64(i)))...) if diags.HasError() { return nil, diags @@ -170,7 +170,7 @@ func FromSlice(ctx context.Context, typ attr.Type, val reflect.Value, path *tfty tfVal := tftypes.NewValue(tfType, tfElems) if typeWithValidate, ok := typ.(attr.TypeWithValidate); ok { - diags.Append(typeWithValidate.Validate(ctx, tfVal)...) + diags.Append(typeWithValidate.Validate(ctx, tfVal, path)...) if diags.HasError() { return nil, diags diff --git a/internal/reflect/struct.go b/internal/reflect/struct.go index b0b486b14..0819c6a62 100644 --- a/internal/reflect/struct.go +++ b/internal/reflect/struct.go @@ -204,7 +204,7 @@ func FromStruct(ctx context.Context, typ attr.TypeWithAttributeTypes, val reflec tfObjVal := tftypes.NewValue(objTypes[name], tfVal) if typeWithValidate, ok := typ.(attr.TypeWithValidate); ok { - diags.Append(typeWithValidate.Validate(ctx, tfObjVal)...) + diags.Append(typeWithValidate.Validate(ctx, tfObjVal, path)...) if diags.HasError() { return nil, diags @@ -219,7 +219,7 @@ func FromStruct(ctx context.Context, typ attr.TypeWithAttributeTypes, val reflec }, objValues) if typeWithValidate, ok := typ.(attr.TypeWithValidate); ok { - diags.Append(typeWithValidate.Validate(ctx, tfVal)...) + diags.Append(typeWithValidate.Validate(ctx, tfVal, path)...) if diags.HasError() { return nil, diags diff --git a/internal/testing/types/boolwithvalidate.go b/internal/testing/types/boolwithvalidate.go index bbc7d5d84..7b57a75a0 100644 --- a/internal/testing/types/boolwithvalidate.go +++ b/internal/testing/types/boolwithvalidate.go @@ -21,10 +21,10 @@ type BoolTypeWithValidateWarning struct { BoolType } -func (t BoolTypeWithValidateError) Validate(ctx context.Context, in tftypes.Value) diag.Diagnostics { - return diag.Diagnostics{TestErrorDiagnostic} +func (t BoolTypeWithValidateError) Validate(ctx context.Context, in tftypes.Value, path *tftypes.AttributePath) diag.Diagnostics { + return diag.Diagnostics{TestErrorDiagnostic(path)} } -func (t BoolTypeWithValidateWarning) Validate(ctx context.Context, in tftypes.Value) diag.Diagnostics { - return diag.Diagnostics{TestWarningDiagnostic} +func (t BoolTypeWithValidateWarning) Validate(ctx context.Context, in tftypes.Value, path *tftypes.AttributePath) diag.Diagnostics { + return diag.Diagnostics{TestWarningDiagnostic(path)} } diff --git a/internal/testing/types/diags.go b/internal/testing/types/diags.go index 3564b36a9..a9a28b0a0 100644 --- a/internal/testing/types/diags.go +++ b/internal/testing/types/diags.go @@ -2,15 +2,21 @@ package types import ( "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-go/tftypes" ) -var ( - TestErrorDiagnostic = diag.NewErrorDiagnostic( +func TestErrorDiagnostic(path *tftypes.AttributePath) diag.AttributeErrorDiagnostic { + return diag.NewAttributeErrorDiagnostic( + path, "Error Diagnostic", "This is an error.", ) - TestWarningDiagnostic = diag.NewWarningDiagnostic( +} + +func TestWarningDiagnostic(path *tftypes.AttributePath) diag.AttributeWarningDiagnostic { + return diag.NewAttributeWarningDiagnostic( + path, "Warning Diagnostic", "This is a warning.", ) -) +} diff --git a/internal/testing/types/numberwithvalidate.go b/internal/testing/types/numberwithvalidate.go index 40719dc62..67c042100 100644 --- a/internal/testing/types/numberwithvalidate.go +++ b/internal/testing/types/numberwithvalidate.go @@ -21,10 +21,10 @@ type NumberTypeWithValidateWarning struct { NumberType } -func (t NumberTypeWithValidateError) Validate(ctx context.Context, in tftypes.Value) diag.Diagnostics { - return diag.Diagnostics{TestErrorDiagnostic} +func (t NumberTypeWithValidateError) Validate(ctx context.Context, in tftypes.Value, path *tftypes.AttributePath) diag.Diagnostics { + return diag.Diagnostics{TestErrorDiagnostic(path)} } -func (t NumberTypeWithValidateWarning) Validate(ctx context.Context, in tftypes.Value) diag.Diagnostics { - return diag.Diagnostics{TestWarningDiagnostic} +func (t NumberTypeWithValidateWarning) Validate(ctx context.Context, in tftypes.Value, path *tftypes.AttributePath) diag.Diagnostics { + return diag.Diagnostics{TestWarningDiagnostic(path)} } diff --git a/internal/testing/types/stringwithvalidate.go b/internal/testing/types/stringwithvalidate.go index 2b9b3c5ab..6c37b50ff 100644 --- a/internal/testing/types/stringwithvalidate.go +++ b/internal/testing/types/stringwithvalidate.go @@ -21,10 +21,10 @@ type StringTypeWithValidateWarning struct { StringType } -func (t StringTypeWithValidateError) Validate(ctx context.Context, in tftypes.Value) diag.Diagnostics { - return diag.Diagnostics{TestErrorDiagnostic} +func (t StringTypeWithValidateError) Validate(ctx context.Context, in tftypes.Value, path *tftypes.AttributePath) diag.Diagnostics { + return diag.Diagnostics{TestErrorDiagnostic(path)} } -func (t StringTypeWithValidateWarning) Validate(ctx context.Context, in tftypes.Value) diag.Diagnostics { - return diag.Diagnostics{TestWarningDiagnostic} +func (t StringTypeWithValidateWarning) Validate(ctx context.Context, in tftypes.Value, path *tftypes.AttributePath) diag.Diagnostics { + return diag.Diagnostics{TestWarningDiagnostic(path)} } diff --git a/tfsdk/attribute_test.go b/tfsdk/attribute_test.go index 489210b5d..7e2d20788 100644 --- a/tfsdk/attribute_test.go +++ b/tfsdk/attribute_test.go @@ -1015,7 +1015,7 @@ func TestAttributeValidate(t *testing.T) { }, resp: ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ - testtypes.TestErrorDiagnostic, + testtypes.TestErrorDiagnostic(tftypes.NewAttributePath().WithAttributeName("test")), }, }, }, @@ -1042,7 +1042,7 @@ func TestAttributeValidate(t *testing.T) { }, resp: ValidateAttributeResponse{ Diagnostics: diag.Diagnostics{ - testtypes.TestWarningDiagnostic, + testtypes.TestWarningDiagnostic(tftypes.NewAttributePath().WithAttributeName("test")), }, }, }, diff --git a/tfsdk/config.go b/tfsdk/config.go index e0fc52a59..40ea23061 100644 --- a/tfsdk/config.go +++ b/tfsdk/config.go @@ -54,7 +54,7 @@ func (c Config) GetAttribute(ctx context.Context, path *tftypes.AttributePath) ( } if attrTypeWithValidate, ok := attrType.(attr.TypeWithValidate); ok { - diags.Append(attrTypeWithValidate.Validate(ctx, tfValue)...) + diags.Append(attrTypeWithValidate.Validate(ctx, tfValue, path)...) if diags.HasError() { return nil, diags diff --git a/tfsdk/config_test.go b/tfsdk/config_test.go index 8ed77fe8a..6d6e81532 100644 --- a/tfsdk/config_test.go +++ b/tfsdk/config_test.go @@ -69,7 +69,7 @@ func TestConfigGet(t *testing.T) { expected: testConfigGetData{ Name: types.String{Value: ""}, }, - expectedDiags: diag.Diagnostics{testtypes.TestErrorDiagnostic}, + expectedDiags: diag.Diagnostics{testtypes.TestErrorDiagnostic(tftypes.NewAttributePath().WithAttributeName("name"))}, }, "AttrTypeWithValidateWarning": { config: Config{ @@ -92,7 +92,7 @@ func TestConfigGet(t *testing.T) { expected: testConfigGetData{ Name: types.String{Value: "namevalue"}, }, - expectedDiags: diag.Diagnostics{testtypes.TestWarningDiagnostic}, + expectedDiags: diag.Diagnostics{testtypes.TestWarningDiagnostic(tftypes.NewAttributePath().WithAttributeName("name"))}, }, } @@ -165,7 +165,7 @@ func TestConfigGetAttribute(t *testing.T) { }, }, expected: nil, - expectedDiags: diag.Diagnostics{testtypes.TestErrorDiagnostic}, + expectedDiags: diag.Diagnostics{testtypes.TestErrorDiagnostic(tftypes.NewAttributePath().WithAttributeName("name"))}, }, "AttrTypeWithValidateWarning": { config: Config{ @@ -186,7 +186,7 @@ func TestConfigGetAttribute(t *testing.T) { }, }, expected: types.String{Value: "namevalue"}, - expectedDiags: diag.Diagnostics{testtypes.TestWarningDiagnostic}, + expectedDiags: diag.Diagnostics{testtypes.TestWarningDiagnostic(tftypes.NewAttributePath().WithAttributeName("name"))}, }, } diff --git a/tfsdk/plan.go b/tfsdk/plan.go index 38c0a0795..cc85c3d19 100644 --- a/tfsdk/plan.go +++ b/tfsdk/plan.go @@ -54,7 +54,7 @@ func (p Plan) GetAttribute(ctx context.Context, path *tftypes.AttributePath) (at } if attrTypeWithValidate, ok := attrType.(attr.TypeWithValidate); ok { - diags.Append(attrTypeWithValidate.Validate(ctx, tfValue)...) + diags.Append(attrTypeWithValidate.Validate(ctx, tfValue, path)...) if diags.HasError() { return nil, diags @@ -138,7 +138,7 @@ func (p *Plan) SetAttribute(ctx context.Context, path *tftypes.AttributePath, va tfVal := tftypes.NewValue(attrType.TerraformType(ctx), newTfVal) if attrTypeWithValidate, ok := attrType.(attr.TypeWithValidate); ok { - diags.Append(attrTypeWithValidate.Validate(ctx, tfVal)...) + diags.Append(attrTypeWithValidate.Validate(ctx, tfVal, path)...) if diags.HasError() { return v, nil diff --git a/tfsdk/plan_test.go b/tfsdk/plan_test.go index d08a555a7..d325b608e 100644 --- a/tfsdk/plan_test.go +++ b/tfsdk/plan_test.go @@ -69,7 +69,7 @@ func TestPlanGet(t *testing.T) { expected: testPlanGetData{ Name: types.String{Value: ""}, }, - expectedDiags: diag.Diagnostics{testtypes.TestErrorDiagnostic}, + expectedDiags: diag.Diagnostics{testtypes.TestErrorDiagnostic(tftypes.NewAttributePath().WithAttributeName("name"))}, }, "AttrTypeWithValidateWarning": { plan: Plan{ @@ -92,7 +92,7 @@ func TestPlanGet(t *testing.T) { expected: testPlanGetData{ Name: types.String{Value: "namevalue"}, }, - expectedDiags: diag.Diagnostics{testtypes.TestWarningDiagnostic}, + expectedDiags: diag.Diagnostics{testtypes.TestWarningDiagnostic(tftypes.NewAttributePath().WithAttributeName("name"))}, }, } @@ -165,7 +165,7 @@ func TestPlanGetAttribute(t *testing.T) { }, }, expected: nil, - expectedDiags: diag.Diagnostics{testtypes.TestErrorDiagnostic}, + expectedDiags: diag.Diagnostics{testtypes.TestErrorDiagnostic(tftypes.NewAttributePath().WithAttributeName("name"))}, }, "AttrTypeWithValidateWarning": { plan: Plan{ @@ -186,7 +186,7 @@ func TestPlanGetAttribute(t *testing.T) { }, }, expected: types.String{Value: "namevalue"}, - expectedDiags: diag.Diagnostics{testtypes.TestWarningDiagnostic}, + expectedDiags: diag.Diagnostics{testtypes.TestWarningDiagnostic(tftypes.NewAttributePath().WithAttributeName("name"))}, }, } @@ -293,7 +293,7 @@ func TestPlanSet(t *testing.T) { Name: "newvalue", }, expected: tftypes.Value{}, - expectedDiags: diag.Diagnostics{testtypes.TestErrorDiagnostic}, + expectedDiags: diag.Diagnostics{testtypes.TestErrorDiagnostic(tftypes.NewAttributePath().WithAttributeName("name"))}, }, "AttrTypeWithValidateWarning": { plan: Plan{ @@ -319,7 +319,7 @@ func TestPlanSet(t *testing.T) { }, map[string]tftypes.Value{ "name": tftypes.NewValue(tftypes.String, "newvalue"), }), - expectedDiags: diag.Diagnostics{testtypes.TestWarningDiagnostic}, + expectedDiags: diag.Diagnostics{testtypes.TestWarningDiagnostic(tftypes.NewAttributePath().WithAttributeName("name"))}, }, } @@ -408,7 +408,9 @@ func TestPlanSetAttribute(t *testing.T) { }, map[string]tftypes.Value{ "name": tftypes.NewValue(tftypes.String, "originalname"), }), - expectedDiags: diag.Diagnostics{testtypes.TestErrorDiagnostic}, + // TODO: Diagnostic should include WithAttributeName("name") + // Reference: https://github.com/hashicorp/terraform-plugin-framework/issues/128 + expectedDiags: diag.Diagnostics{testtypes.TestErrorDiagnostic(tftypes.NewAttributePath())}, }, "AttrTypeWithValidateWarning": { plan: Plan{ @@ -438,7 +440,11 @@ func TestPlanSetAttribute(t *testing.T) { "name": tftypes.NewValue(tftypes.String, "newname"), }), expectedDiags: diag.Diagnostics{ - testtypes.TestWarningDiagnostic, + // TODO: Diagnostic should include WithAttributeName("name") + // Reference: https://github.com/hashicorp/terraform-plugin-framework/issues/128 + testtypes.TestWarningDiagnostic(tftypes.NewAttributePath()), + // This duplicate should go away with the above fix. + testtypes.TestWarningDiagnostic(tftypes.NewAttributePath().WithAttributeName("name")), }, }, } diff --git a/tfsdk/state.go b/tfsdk/state.go index 0598ebe2e..e80a2ca40 100644 --- a/tfsdk/state.go +++ b/tfsdk/state.go @@ -54,7 +54,7 @@ func (s State) GetAttribute(ctx context.Context, path *tftypes.AttributePath) (a } if attrTypeWithValidate, ok := attrType.(attr.TypeWithValidate); ok { - diags.Append(attrTypeWithValidate.Validate(ctx, tfValue)...) + diags.Append(attrTypeWithValidate.Validate(ctx, tfValue, path)...) if diags.HasError() { return nil, diags @@ -147,7 +147,7 @@ func (s *State) SetAttribute(ctx context.Context, path *tftypes.AttributePath, v tfVal := tftypes.NewValue(attrType.TerraformType(ctx), newTfVal) if attrTypeWithValidate, ok := attrType.(attr.TypeWithValidate); ok { - diags.Append(attrTypeWithValidate.Validate(ctx, tfVal)...) + diags.Append(attrTypeWithValidate.Validate(ctx, tfVal, path)...) if diags.HasError() { return v, nil diff --git a/tfsdk/state_test.go b/tfsdk/state_test.go index 7fdfd28e8..0bff0c079 100644 --- a/tfsdk/state_test.go +++ b/tfsdk/state_test.go @@ -359,7 +359,7 @@ func TestStateGet(t *testing.T) { Interface: "", }, }, - expectedDiags: diag.Diagnostics{testtypes.TestErrorDiagnostic}, + expectedDiags: diag.Diagnostics{testtypes.TestErrorDiagnostic(tftypes.NewAttributePath().WithAttributeName("name"))}, }, "AttrTypeWithValidateWarning": { state: State{ @@ -530,7 +530,7 @@ func TestStateGet(t *testing.T) { Interface: "SCSI", }, }, - expectedDiags: diag.Diagnostics{testtypes.TestWarningDiagnostic}, + expectedDiags: diag.Diagnostics{testtypes.TestWarningDiagnostic(tftypes.NewAttributePath().WithAttributeName("name"))}, }, } @@ -827,7 +827,7 @@ func TestStateGetAttribute(t *testing.T) { }, path: tftypes.NewAttributePath().WithAttributeName("name"), expected: nil, - expectedDiags: diag.Diagnostics{testtypes.TestErrorDiagnostic}, + expectedDiags: diag.Diagnostics{testtypes.TestErrorDiagnostic(tftypes.NewAttributePath().WithAttributeName("name"))}, }, "AttrTypeWithValidateWarning": { state: State{ @@ -849,7 +849,7 @@ func TestStateGetAttribute(t *testing.T) { }, path: tftypes.NewAttributePath().WithAttributeName("name"), expected: types.String{Value: "namevalue"}, - expectedDiags: diag.Diagnostics{testtypes.TestWarningDiagnostic}, + expectedDiags: diag.Diagnostics{testtypes.TestWarningDiagnostic(tftypes.NewAttributePath().WithAttributeName("name"))}, }, } @@ -1189,7 +1189,7 @@ func TestStateSet(t *testing.T) { Name: "newvalue", }, expected: tftypes.Value{}, - expectedDiags: diag.Diagnostics{testtypes.TestErrorDiagnostic}, + expectedDiags: diag.Diagnostics{testtypes.TestErrorDiagnostic(tftypes.NewAttributePath().WithAttributeName("name"))}, }, "AttrTypeWithValidateWarning": { state: State{ @@ -1215,7 +1215,7 @@ func TestStateSet(t *testing.T) { }, map[string]tftypes.Value{ "name": tftypes.NewValue(tftypes.String, "newvalue"), }), - expectedDiags: diag.Diagnostics{testtypes.TestWarningDiagnostic}, + expectedDiags: diag.Diagnostics{testtypes.TestWarningDiagnostic(tftypes.NewAttributePath().WithAttributeName("name"))}, }, } @@ -1539,7 +1539,9 @@ func TestStateSetAttribute(t *testing.T) { }, map[string]tftypes.Value{ "name": tftypes.NewValue(tftypes.String, "originalname"), }), - expectedDiags: diag.Diagnostics{testtypes.TestErrorDiagnostic}, + // TODO: Diagnostic should include WithAttributeName("name") + // Reference: https://github.com/hashicorp/terraform-plugin-framework/issues/128 + expectedDiags: diag.Diagnostics{testtypes.TestErrorDiagnostic(tftypes.NewAttributePath())}, }, "AttrTypeWithValidateWarning": { state: State{ @@ -1569,7 +1571,11 @@ func TestStateSetAttribute(t *testing.T) { "name": tftypes.NewValue(tftypes.String, "newname"), }), expectedDiags: diag.Diagnostics{ - testtypes.TestWarningDiagnostic, + // TODO: Diagnostic should include WithAttributeName("name") + // Reference: https://github.com/hashicorp/terraform-plugin-framework/issues/128 + testtypes.TestWarningDiagnostic(tftypes.NewAttributePath()), + // This duplicate should go away with the above fix. + testtypes.TestWarningDiagnostic(tftypes.NewAttributePath().WithAttributeName("name")), }, }, }