Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

diag: Add WithPath function and remove AttributeErrorDiagnostic and AttributeWarningDiagnostic types #219

Merged
merged 4 commits into from
Nov 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changelog/219.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
```release-note:breaking-change
diag: The `AttributeErrorDiagnostic` and `AttributeWarningDiagnostic` types have been removed. Any usage can be replaced with `DiagnosticWithPath`.
```

```release-note:enhancement
diag: Added `WithPath()` function to wrap or overwrite diagnostic path information.
```
40 changes: 4 additions & 36 deletions diag/attribute_error_diagnostic.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,42 +4,10 @@ import (
"github.com/hashicorp/terraform-plugin-go/tftypes"
)

var _ DiagnosticWithPath = AttributeErrorDiagnostic{}

// AttributeErrorDiagnostic is a generic attribute diagnostic with error severity.
type AttributeErrorDiagnostic struct {
ErrorDiagnostic

path *tftypes.AttributePath
}

// Equal returns true if the other diagnostic is wholly equivalent.
func (d AttributeErrorDiagnostic) Equal(other Diagnostic) bool {
aed, ok := other.(AttributeErrorDiagnostic)

if !ok {
return false
}

if !aed.Path().Equal(d.Path()) {
return false
}

return aed.ErrorDiagnostic.Equal(d.ErrorDiagnostic)
}

// Path returns the diagnostic path.
func (d AttributeErrorDiagnostic) Path() *tftypes.AttributePath {
return d.path
}

// NewAttributeErrorDiagnostic returns a new error severity diagnostic with the given summary, detail, and path.
func NewAttributeErrorDiagnostic(path *tftypes.AttributePath, summary string, detail string) AttributeErrorDiagnostic {
return AttributeErrorDiagnostic{
ErrorDiagnostic: ErrorDiagnostic{
detail: detail,
summary: summary,
},
path: path,
func NewAttributeErrorDiagnostic(path *tftypes.AttributePath, summary string, detail string) DiagnosticWithPath {
return withPath{
Diagnostic: NewErrorDiagnostic(summary, detail),
path: path,
}
}
40 changes: 4 additions & 36 deletions diag/attribute_warning_diagnostic.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,42 +4,10 @@ import (
"github.com/hashicorp/terraform-plugin-go/tftypes"
)

var _ DiagnosticWithPath = AttributeWarningDiagnostic{}

// AttributeErrorDiagnostic is a generic attribute diagnostic with warning severity.
type AttributeWarningDiagnostic struct {
WarningDiagnostic

path *tftypes.AttributePath
}

// Equal returns true if the other diagnostic is wholly equivalent.
func (d AttributeWarningDiagnostic) Equal(other Diagnostic) bool {
awd, ok := other.(AttributeWarningDiagnostic)

if !ok {
return false
}

if !awd.Path().Equal(d.Path()) {
return false
}

return awd.WarningDiagnostic.Equal(d.WarningDiagnostic)
}

// Path returns the diagnostic path.
func (d AttributeWarningDiagnostic) Path() *tftypes.AttributePath {
return d.path
}

// NewAttributeWarningDiagnostic returns a new warning severity diagnostic with the given summary, detail, and path.
func NewAttributeWarningDiagnostic(path *tftypes.AttributePath, summary string, detail string) AttributeWarningDiagnostic {
return AttributeWarningDiagnostic{
WarningDiagnostic: WarningDiagnostic{
detail: detail,
summary: summary,
},
path: path,
func NewAttributeWarningDiagnostic(path *tftypes.AttributePath, summary string, detail string) DiagnosticWithPath {
return withPath{
Diagnostic: NewWarningDiagnostic(summary, detail),
path: path,
}
}
3 changes: 3 additions & 0 deletions diag/diagnostic.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import (
//
// See the ErrorDiagnostic and WarningDiagnostic concrete types for generic
// implementations.
//
// To add path information to an existing diagnostic, see the WithPath()
// function.
type Diagnostic interface {
// Severity returns the desired level of feedback for the diagnostic.
Severity() Severity
Expand Down
54 changes: 54 additions & 0 deletions diag/with_path.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package diag

import (
"github.com/hashicorp/terraform-plugin-go/tftypes"
)

var _ DiagnosticWithPath = withPath{}

// withPath wraps a diagnostic with path information.
type withPath struct {
Diagnostic

path *tftypes.AttributePath
}

// Equal returns true if the other diagnostic is wholly equivalent.
func (d withPath) Equal(other Diagnostic) bool {
o, ok := other.(withPath)

if !ok {
return false
}

if !d.Path().Equal(o.Path()) {
return false
}

if d.Diagnostic == nil {
return d.Diagnostic == o.Diagnostic
}

return d.Diagnostic.Equal(o.Diagnostic)
}

// Path returns the diagnostic path.
func (d withPath) Path() *tftypes.AttributePath {
return d.path
}

// WithPath wraps a diagnostic with path information or overwrites the path.
func WithPath(path *tftypes.AttributePath, d Diagnostic) DiagnosticWithPath {
wp, ok := d.(withPath)

if !ok {
return withPath{
Diagnostic: d,
path: path,
}
}

wp.path = path

return wp
}
24 changes: 4 additions & 20 deletions internal/reflect/diags.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,31 +9,31 @@ import (
"github.com/hashicorp/terraform-plugin-go/tftypes"
)

func toTerraform5ValueErrorDiag(err error, path *tftypes.AttributePath) diag.AttributeErrorDiagnostic {
func toTerraform5ValueErrorDiag(err error, path *tftypes.AttributePath) diag.DiagnosticWithPath {
return diag.NewAttributeErrorDiagnostic(
path,
"Value Conversion Error",
"An unexpected error was encountered trying to convert into a Terraform value. This is always an error in the provider. Please report the following to the provider developer:\n\n"+err.Error(),
)
}

func toTerraformValueErrorDiag(err error, path *tftypes.AttributePath) diag.AttributeErrorDiagnostic {
func toTerraformValueErrorDiag(err error, path *tftypes.AttributePath) diag.DiagnosticWithPath {
return diag.NewAttributeErrorDiagnostic(
path,
"Value Conversion Error",
"An unexpected error was encountered trying to convert the Attribute value into a Terraform value. This is always an error in the provider. Please report the following to the provider developer:\n\n"+err.Error(),
)
}

func validateValueErrorDiag(err error, path *tftypes.AttributePath) diag.AttributeErrorDiagnostic {
func validateValueErrorDiag(err error, path *tftypes.AttributePath) diag.DiagnosticWithPath {
return diag.NewAttributeErrorDiagnostic(
path,
"Value Conversion Error",
"An unexpected error was encountered trying to validate the Terraform value type. This is always an error in the provider. Please report the following to the provider developer:\n\n"+err.Error(),
)
}

func valueFromTerraformErrorDiag(err error, path *tftypes.AttributePath) diag.AttributeErrorDiagnostic {
func valueFromTerraformErrorDiag(err error, path *tftypes.AttributePath) diag.DiagnosticWithPath {
return diag.NewAttributeErrorDiagnostic(
path,
"Value Conversion Error",
Expand All @@ -44,7 +44,6 @@ func valueFromTerraformErrorDiag(err error, path *tftypes.AttributePath) diag.At
type DiagIntoIncompatibleType struct {
Val tftypes.Value
TargetType reflect.Type
AttrPath *tftypes.AttributePath
Err error
}

Expand All @@ -71,24 +70,16 @@ func (d DiagIntoIncompatibleType) Equal(o diag.Diagnostic) bool {
if d.TargetType != od.TargetType {
return false
}
if !d.AttrPath.Equal(od.AttrPath) {
return false
}
if d.Err.Error() != od.Err.Error() {
return false
}
return true
}

func (d DiagIntoIncompatibleType) Path() *tftypes.AttributePath {
return d.AttrPath
}

type DiagNewAttributeValueIntoWrongType struct {
ValType reflect.Type
TargetType reflect.Type
SchemaType attr.Type
AttrPath *tftypes.AttributePath
}

func (d DiagNewAttributeValueIntoWrongType) Severity() diag.Severity {
Expand Down Expand Up @@ -117,12 +108,5 @@ func (d DiagNewAttributeValueIntoWrongType) Equal(o diag.Diagnostic) bool {
if !d.SchemaType.Equal(od.SchemaType) {
return false
}
if !d.AttrPath.Equal(od.AttrPath) {
return false
}
return true
}

func (d DiagNewAttributeValueIntoWrongType) Path() *tftypes.AttributePath {
return d.AttrPath
}
5 changes: 2 additions & 3 deletions internal/reflect/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -291,12 +291,11 @@ func NewAttributeValue(ctx context.Context, typ attr.Type, val tftypes.Value, ta
return target, append(diags, valueFromTerraformErrorDiag(err, path))
}
if reflect.TypeOf(res) != target.Type() {
diags.Append(DiagNewAttributeValueIntoWrongType{
diags.Append(diag.WithPath(path, DiagNewAttributeValueIntoWrongType{
ValType: reflect.TypeOf(res),
TargetType: target.Type(),
SchemaType: typ,
AttrPath: path,
})
}))
return target, diags
}
return reflect.ValueOf(res), diags
Expand Down
20 changes: 8 additions & 12 deletions internal/reflect/map.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,31 +18,28 @@ func Map(ctx context.Context, typ attr.Type, val tftypes.Value, target reflect.V

// this only works with maps, so check that out first
if underlyingValue.Kind() != reflect.Map {
diags.Append(DiagIntoIncompatibleType{
diags.Append(diag.WithPath(path, DiagIntoIncompatibleType{
Val: val,
TargetType: target.Type(),
AttrPath: path,
Err: fmt.Errorf("expected a map type, got %s", target.Type()),
})
}))
return target, diags
}
if !val.Type().Is(tftypes.Map{}) {
diags.Append(DiagIntoIncompatibleType{
diags.Append(diag.WithPath(path, DiagIntoIncompatibleType{
Val: val,
TargetType: target.Type(),
AttrPath: path,
Err: fmt.Errorf("cannot reflect %s into a map, must be a map", val.Type().String()),
})
}))
return target, diags
}
elemTyper, ok := typ.(attr.TypeWithElementType)
if !ok {
diags.Append(DiagIntoIncompatibleType{
diags.Append(diag.WithPath(path, DiagIntoIncompatibleType{
Val: val,
TargetType: target.Type(),
AttrPath: path,
Err: fmt.Errorf("cannot reflect map using type information provided by %T, %T must be an attr.TypeWithElementType", typ, typ),
})
}))
return target, diags
}

Expand All @@ -51,12 +48,11 @@ func Map(ctx context.Context, typ attr.Type, val tftypes.Value, target reflect.V
values := map[string]tftypes.Value{}
err := val.As(&values)
if err != nil {
diags.Append(DiagIntoIncompatibleType{
diags.Append(diag.WithPath(path, DiagIntoIncompatibleType{
Val: val,
TargetType: target.Type(),
AttrPath: path,
Err: err,
})
}))
return target, diags
}

Expand Down
5 changes: 2 additions & 3 deletions internal/reflect/number.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,11 @@ func Number(ctx context.Context, typ attr.Type, val tftypes.Value, target reflec
result := big.NewFloat(0)
err := val.As(&result)
if err != nil {
diags.Append(DiagIntoIncompatibleType{
AttrPath: path,
diags.Append(diag.WithPath(path, DiagIntoIncompatibleType{
Err: err,
TargetType: target.Type(),
Val: val,
})
}))
return target, diags
}
roundingError := fmt.Errorf("cannot store %s in %s", result.String(), target.Type())
Expand Down
5 changes: 2 additions & 3 deletions internal/reflect/pointer.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,11 @@ func Pointer(ctx context.Context, typ attr.Type, val tftypes.Value, target refle
var diags diag.Diagnostics

if target.Kind() != reflect.Ptr {
diags.Append(DiagIntoIncompatibleType{
diags.Append(diag.WithPath(path, DiagIntoIncompatibleType{
Val: val,
TargetType: target.Type(),
AttrPath: path,
Err: fmt.Errorf("cannot dereference pointer, not a pointer, is a %s (%s)", target.Type(), target.Kind()),
})
}))
return target, diags
}
// we may have gotten a nil pointer, so we need to create our own that
Expand Down
5 changes: 2 additions & 3 deletions internal/reflect/pointer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,11 @@ func TestPointer_notAPointer(t *testing.T) {

var s string
expectedDiags := diag.Diagnostics{
refl.DiagIntoIncompatibleType{
diag.WithPath(tftypes.NewAttributePath(), refl.DiagIntoIncompatibleType{
Val: tftypes.NewValue(tftypes.String, "hello"),
TargetType: reflect.TypeOf(s),
AttrPath: tftypes.NewAttributePath(),
Err: fmt.Errorf("cannot dereference pointer, not a pointer, is a %s (%s)", reflect.TypeOf(s), reflect.TypeOf(s).Kind()),
},
}),
}

_, diags := refl.Pointer(context.Background(), types.StringType, tftypes.NewValue(tftypes.String, "hello"), reflect.ValueOf(s), refl.Options{}, tftypes.NewAttributePath())
Expand Down
Loading