Files
plexterraform/internal/provider/reflect/interfaces.go

354 lines
12 KiB
Go

// Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.
package reflect
import (
"context"
"fmt"
"reflect"
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/attr/xattr"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-go/tftypes"
)
// Unknownable is an interface for types that can be explicitly set to known or
// unknown.
type Unknownable interface {
SetUnknown(context.Context, bool) error
SetValue(context.Context, interface{}) error
GetUnknown(context.Context) bool
GetValue(context.Context) interface{}
}
// NewUnknownable creates a zero value of `target` (or the concrete type it's
// referencing, if it's a pointer) and calls its SetUnknown method.
//
// It is meant to be called through Into, not directly.
func NewUnknownable(ctx context.Context, typ attr.Type, val tftypes.Value, target reflect.Value, opts Options, path path.Path) (reflect.Value, diag.Diagnostics) {
var diags diag.Diagnostics
receiver := pointerSafeZeroValue(ctx, target)
method := receiver.MethodByName("SetUnknown")
if !method.IsValid() {
err := fmt.Errorf("cannot find SetUnknown method on type %s", receiver.Type().String())
diags.AddAttributeError(
path,
"Value Conversion Error",
"An unexpected error was encountered trying to convert value. This is always an error in the provider. Please report the following to the provider developer:\n\n"+err.Error(),
)
return target, diags
}
results := method.Call([]reflect.Value{
reflect.ValueOf(ctx),
reflect.ValueOf(!val.IsKnown()),
})
err := results[0].Interface()
if err != nil {
var underlyingErr error
switch e := err.(type) {
case error:
underlyingErr = e
default:
underlyingErr = fmt.Errorf("unknown error type %T: %v", e, e)
}
underlyingErr = fmt.Errorf("reflection error: %w", underlyingErr)
diags.AddAttributeError(
path,
"Value Conversion Error",
"An unexpected error was encountered trying to convert into a value. This is always an error in the provider. Please report the following to the provider developer:\n\n"+underlyingErr.Error(),
)
return target, diags
}
return receiver, diags
}
// FromUnknownable creates an attr.Value from the data in an Unknownable.
//
// It is meant to be called through FromValue, not directly.
func FromUnknownable(ctx context.Context, typ attr.Type, val Unknownable, path path.Path) (attr.Value, diag.Diagnostics) {
var diags diag.Diagnostics
if val.GetUnknown(ctx) {
tfVal := tftypes.NewValue(typ.TerraformType(ctx), tftypes.UnknownValue)
if typeWithValidate, ok := typ.(xattr.TypeWithValidate); ok {
diags.Append(typeWithValidate.Validate(ctx, tfVal, path)...)
if diags.HasError() {
return nil, diags
}
}
res, err := typ.ValueFromTerraform(ctx, tfVal)
if err != nil {
return nil, append(diags, valueFromTerraformErrorDiag(err, path))
}
return res, nil
}
err := tftypes.ValidateValue(typ.TerraformType(ctx), val.GetValue(ctx))
if err != nil {
return nil, append(diags, validateValueErrorDiag(err, path))
}
tfVal := tftypes.NewValue(typ.TerraformType(ctx), val.GetValue(ctx))
if typeWithValidate, ok := typ.(xattr.TypeWithValidate); ok {
diags.Append(typeWithValidate.Validate(ctx, tfVal, path)...)
if diags.HasError() {
return nil, diags
}
}
res, err := typ.ValueFromTerraform(ctx, tfVal)
if err != nil {
return nil, append(diags, valueFromTerraformErrorDiag(err, path))
}
return res, nil
}
// Nullable is an interface for types that can be explicitly set to null.
type Nullable interface {
SetNull(context.Context, bool) error
SetValue(context.Context, interface{}) error
GetNull(context.Context) bool
GetValue(context.Context) interface{}
}
// NewNullable creates a zero value of `target` (or the concrete type it's
// referencing, if it's a pointer) and calls its SetNull method.
//
// It is meant to be called through Into, not directly.
func NewNullable(ctx context.Context, typ attr.Type, val tftypes.Value, target reflect.Value, opts Options, path path.Path) (reflect.Value, diag.Diagnostics) {
var diags diag.Diagnostics
receiver := pointerSafeZeroValue(ctx, target)
method := receiver.MethodByName("SetNull")
if !method.IsValid() {
err := fmt.Errorf("cannot find SetNull method on type %s", receiver.Type().String())
diags.AddAttributeError(
path,
"Value Conversion Error",
"An unexpected error was encountered trying to convert value. This is always an error in the provider. Please report the following to the provider developer:\n\n"+err.Error(),
)
return target, diags
}
results := method.Call([]reflect.Value{
reflect.ValueOf(ctx),
reflect.ValueOf(val.IsNull()),
})
err := results[0].Interface()
if err != nil {
var underlyingErr error
switch e := err.(type) {
case error:
underlyingErr = e
default:
underlyingErr = fmt.Errorf("unknown error type: %T", e)
}
underlyingErr = fmt.Errorf("reflection error: %w", underlyingErr)
diags.AddAttributeError(
path,
"Value Conversion Error",
"An unexpected error was encountered trying to convert into a value. This is always an error in the provider. Please report the following to the provider developer:\n\n"+underlyingErr.Error(),
)
return target, diags
}
return receiver, diags
}
// FromNullable creates an attr.Value from the data in a Nullable.
//
// It is meant to be called through FromValue, not directly.
func FromNullable(ctx context.Context, typ attr.Type, val Nullable, path path.Path) (attr.Value, diag.Diagnostics) {
var diags diag.Diagnostics
if val.GetNull(ctx) {
tfVal := tftypes.NewValue(typ.TerraformType(ctx), nil)
if typeWithValidate, ok := typ.(xattr.TypeWithValidate); ok {
diags.Append(typeWithValidate.Validate(ctx, tfVal, path)...)
if diags.HasError() {
return nil, diags
}
}
res, err := typ.ValueFromTerraform(ctx, tfVal)
if err != nil {
return nil, append(diags, valueFromTerraformErrorDiag(err, path))
}
return res, nil
}
err := tftypes.ValidateValue(typ.TerraformType(ctx), val.GetValue(ctx))
if err != nil {
return nil, append(diags, validateValueErrorDiag(err, path))
}
tfVal := tftypes.NewValue(typ.TerraformType(ctx), val.GetValue(ctx))
if typeWithValidate, ok := typ.(xattr.TypeWithValidate); ok {
diags.Append(typeWithValidate.Validate(ctx, tfVal, path)...)
if diags.HasError() {
return nil, diags
}
}
res, err := typ.ValueFromTerraform(ctx, tfVal)
if err != nil {
return nil, append(diags, valueFromTerraformErrorDiag(err, path))
}
return res, diags
}
// NewValueConverter creates a zero value of `target` (or the concrete type
// it's referencing, if it's a pointer) and calls its FromTerraform5Value
// method.
//
// It is meant to be called through Into, not directly.
func NewValueConverter(ctx context.Context, typ attr.Type, val tftypes.Value, target reflect.Value, opts Options, path path.Path) (reflect.Value, diag.Diagnostics) {
var diags diag.Diagnostics
receiver := pointerSafeZeroValue(ctx, target)
method := receiver.MethodByName("FromTerraform5Value")
if !method.IsValid() {
err := fmt.Errorf("could not find FromTerraform5Type method on type %s", receiver.Type().String())
diags.AddAttributeError(
path,
"Value Conversion Error",
"An unexpected error was encountered trying to convert into a value. This is always an error in the provider. Please report the following to the provider developer:\n\n"+err.Error(),
)
return target, diags
}
results := method.Call([]reflect.Value{reflect.ValueOf(val)})
err := results[0].Interface()
if err != nil {
var underlyingErr error
switch e := err.(type) {
case error:
underlyingErr = e
default:
underlyingErr = fmt.Errorf("unknown error type: %T", e)
}
underlyingErr = fmt.Errorf("reflection error: %w", underlyingErr)
diags.AddAttributeError(
path,
"Value Conversion Error",
"An unexpected error was encountered trying to convert into a value. This is always an error in the provider. Please report the following to the provider developer:\n\n"+underlyingErr.Error(),
)
return target, diags
}
return receiver, diags
}
// FromValueCreator creates an attr.Value from the data in a
// tftypes.ValueCreator, calling its ToTerraform5Value method and converting
// the result to an attr.Value using `typ`.
//
// It is meant to be called from FromValue, not directly.
func FromValueCreator(ctx context.Context, typ attr.Type, val tftypes.ValueCreator, path path.Path) (attr.Value, diag.Diagnostics) {
var diags diag.Diagnostics
raw, err := val.ToTerraform5Value()
if err != nil {
return nil, append(diags, toTerraform5ValueErrorDiag(err, path))
}
err = tftypes.ValidateValue(typ.TerraformType(ctx), raw)
if err != nil {
return nil, append(diags, validateValueErrorDiag(err, path))
}
tfVal := tftypes.NewValue(typ.TerraformType(ctx), raw)
if typeWithValidate, ok := typ.(xattr.TypeWithValidate); ok {
diags.Append(typeWithValidate.Validate(ctx, tfVal, path)...)
if diags.HasError() {
return nil, diags
}
}
res, err := typ.ValueFromTerraform(ctx, tfVal)
if err != nil {
return nil, append(diags, valueFromTerraformErrorDiag(err, path))
}
return res, diags
}
// NewAttributeValue creates a new reflect.Value by calling the
// ValueFromTerraform method on `typ`. It will return an error if the returned
// `attr.Value` is not the same type as `target`.
//
// It is meant to be called through Into, not directly.
func NewAttributeValue(ctx context.Context, typ attr.Type, val tftypes.Value, target reflect.Value, opts Options, path path.Path) (reflect.Value, diag.Diagnostics) {
var diags diag.Diagnostics
if typeWithValidate, ok := typ.(xattr.TypeWithValidate); ok {
diags.Append(typeWithValidate.Validate(ctx, val, path)...)
if diags.HasError() {
return target, diags
}
}
res, err := typ.ValueFromTerraform(ctx, val)
if err != nil {
return target, append(diags, valueFromTerraformErrorDiag(err, path))
}
if reflect.TypeOf(res) != target.Type() {
diags.Append(diag.WithPath(path, DiagNewAttributeValueIntoWrongType{
ValType: reflect.TypeOf(res),
TargetType: target.Type(),
SchemaType: typ,
}))
return target, diags
}
return reflect.ValueOf(res), diags
}
// FromAttributeValue creates an attr.Value from an attr.Value. It just returns
// the attr.Value it is passed or an error if there is an unexpected mismatch
// between the attr.Type and attr.Value.
//
// It is meant to be called through FromValue, not directly.
func FromAttributeValue(ctx context.Context, typ attr.Type, val attr.Value, path path.Path) (attr.Value, diag.Diagnostics) {
var diags diag.Diagnostics
// Since the reflection logic is a generic Go type implementation with
// user input, it is possible to get into awkward situations where
// the logic is expecting a certain type while a value may not be
// compatible. This check will ensure the framework raises its own
// error is there is a mismatch, rather than a terraform-plugin-go
// error or worse a panic.
//
// If this validation causes major issues, another option is to
// validate via tftypes.Type for both the type and value type.
if !typ.Equal(val.Type(ctx)) {
diags.AddAttributeError(
path,
"Value Conversion Error",
"An unexpected error was encountered while verifying an attribute value matched its expected type to prevent unexpected behavior or panics. "+
"This is always an error in the provider. Please report the following to the provider developer:\n\n"+
fmt.Sprintf("Expected type: %s\n", typ)+
fmt.Sprintf("Value type: %s\n", val.Type(ctx))+
fmt.Sprintf("Path: %s", path),
)
return nil, diags
}
if typeWithValidate, ok := typ.(xattr.TypeWithValidate); ok {
tfVal, err := val.ToTerraformValue(ctx)
if err != nil {
return val, append(diags, toTerraformValueErrorDiag(err, path))
}
diags.Append(typeWithValidate.Validate(ctx, tfVal, path)...)
if diags.HasError() {
return val, diags
}
}
return val, diags
}