Skip to content

Commit

Permalink
Add util/validate folder
Browse files Browse the repository at this point in the history
  • Loading branch information
cjgajard committed May 23, 2024
1 parent 99eb75a commit 6e08b1e
Show file tree
Hide file tree
Showing 13 changed files with 681 additions and 6 deletions.
23 changes: 23 additions & 0 deletions util/build.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package util

import (
"fmt"
"strconv"

"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/types"
)

func StringToUintPointer(p path.Path, s types.String, diags *diag.Diagnostics) *uint {
if s.IsNull() || s.IsUnknown() || s.ValueString() == "" || s.ValueString() == "null" {
return nil
}
if val, err := strconv.Atoi(s.ValueString()); err == nil {
uintvalue := uint(val)
return &uintvalue
} else {
diags.AddError(fmt.Sprintf("Value for %q is not a valid number", p), err.Error())
}
return nil
}
105 changes: 105 additions & 0 deletions util/enumtypes/int64.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package enumtypes

import (
"context"
"fmt"
"math/big"
"slices"

"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
"github.com/hashicorp/terraform-plugin-go/tftypes"
)

type Int64Value struct {
basetypes.Int64Value
EnumType Int64Type
}

func NewInt64Null(t Int64Type) Int64Value {
return Int64Value{Int64Value: basetypes.NewInt64Null(), EnumType: t}
}

func NewInt64Value(v int64, t Int64Type) Int64Value {
return Int64Value{Int64Value: basetypes.NewInt64Value(v), EnumType: t}
}

func (s Int64Value) Type(_ context.Context) attr.Type {
return s.EnumType
}

type Int64Type struct {
basetypes.Int64Type
OneOf []int64
}

func (t Int64Type) Int64() string {
return "enumtypes.Int64Type"
}

func (t Int64Type) Equal(o attr.Type) bool {
if t2, ok := o.(Int64Type); ok {
return slices.Equal(t.OneOf, t2.OneOf)
}
return t.Int64Type.Equal(o)
}

func (t Int64Type) Validate(ctx context.Context, in tftypes.Value, path path.Path) (diags diag.Diagnostics) {
if in.Type() == nil {
return
}

if !in.Type().Is(tftypes.Number) {
err := fmt.Errorf("expected Int64 value, received %T with value: %v", in, in)
diags.AddAttributeError(
path,
"Type Validation Error",
"An unexpected error was encountered trying to validate an attribute value. This is always an error in the provider. "+
"Please report the following to the provider developer:\n\n"+err.Error(),
)
return diags
}

if !in.IsKnown() || in.IsNull() {
return diags
}

var valueFloat big.Float
if err := in.As(&valueFloat); err != nil {
diags.AddAttributeError(
path,
"Type Validation Error",
"An unexpected error was encountered trying to validate an attribute value. This is always an error in the provider. "+
"Please report the following to the provider developer:\n\n"+err.Error(),
)
return
}
valueInt64, _ := valueFloat.Int64()

found := false
for _, v := range t.OneOf {
if v == valueInt64 {
found = true
break
}
}

if !found {
diags.AddAttributeError(
path,
"Invalid Int64 Value",
fmt.Sprintf(
"A string value was provided that is not valid.\n"+
"Given Value: %v\n"+
"Expecting One Of: %v",
valueInt64,
t.OneOf,
),
)
return
}

return
}
100 changes: 100 additions & 0 deletions util/enumtypes/string.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package enumtypes

import (
"context"
"fmt"
"slices"
"strings"

"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
"github.com/hashicorp/terraform-plugin-go/tftypes"
)

type StringValue struct {
basetypes.StringValue
EnumType StringType
}

func NewStringNull(t StringType) StringValue {
return StringValue{StringValue: basetypes.NewStringNull(), EnumType: t}
}

func NewStringValue(v string, t StringType) StringValue {
return StringValue{StringValue: basetypes.NewStringValue(v), EnumType: t}
}

func (s StringValue) Type(_ context.Context) attr.Type {
return s.EnumType
}

type StringType struct {
basetypes.StringType
OneOf []string
}

func (t StringType) String() string {
return "enumtypes.StringType"
}

func (t StringType) Equal(o attr.Type) bool {
if t2, ok := o.(StringType); ok {
return slices.Equal(t.OneOf, t2.OneOf)
}
return t.StringType.Equal(o)
}

func (t StringType) Validate(ctx context.Context, in tftypes.Value, path path.Path) (diags diag.Diagnostics) {
if in.Type() == nil {
return
}

if !in.Type().Is(tftypes.String) {
err := fmt.Errorf("expected String value, received %T with value: %v", in, in)
diags.AddAttributeError(
path,
"Type Validation Error",
"An unexpected error was encountered trying to validate an attribute value. This is always an error in the provider. "+
"Please report the following to the provider developer:\n\n"+err.Error(),
)
return diags
}

if !in.IsKnown() || in.IsNull() {
return diags
}

var valueString string
if err := in.As(&valueString); err != nil {
diags.AddAttributeError(
path,
"Type Validation Error",
"An unexpected error was encountered trying to validate an attribute value. This is always an error in the provider. "+
"Please report the following to the provider developer:\n\n"+err.Error(),
)
return
}

found := false
for _, v := range t.OneOf {
if v == valueString {
found = true
break
}
}

if !found {
diags.AddAttributeError(
path,
"Invalid String Value",
"A string value was provided that is not valid.\n"+
"Given Value: "+valueString+"\n"+
"Expecting One Of: "+strings.Join(t.OneOf, ", "),
)
return
}

return
}
91 changes: 91 additions & 0 deletions util/rangetypes/int64.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package rangetypes

import (
"context"
"fmt"
"math/big"

"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
"github.com/hashicorp/terraform-plugin-go/tftypes"
)

type Int64Value struct {
basetypes.Int64Value
RangeType Int64Type
}

func NewInt64Null(t Int64Type) Int64Value {
return Int64Value{Int64Value: basetypes.NewInt64Null(), RangeType: t}
}

func NewInt64Value(v int64, t Int64Type) Int64Value {
return Int64Value{Int64Value: basetypes.NewInt64Value(v), RangeType: t}
}

func (s Int64Value) Type(_ context.Context) attr.Type {
return s.RangeType
}

type Int64Type struct {
basetypes.Int64Type
Start int64
End int64
}

func (t Int64Type) String() string {
return "rangetypes.Int64Type"
}

func (t Int64Type) Equal(o attr.Type) bool {
if t2, ok := o.(Int64Type); ok {
return t.Start == t2.Start && t.End == t2.End
}
return t.Int64Type.Equal(o)
}

func (t Int64Type) addTypeValidationError(err error, path path.Path, diags *diag.Diagnostics) {
diags.AddAttributeError(
path,
"Type Validation Error",
"An unexpected error was encountered trying to validate an attribute value. This is always an error in the provider. "+
"Please report the following to the provider developer:\n\n"+err.Error(),
)
}

func (t Int64Type) Validate(ctx context.Context, in tftypes.Value, path path.Path) (diags diag.Diagnostics) {
if in.Type() == nil {
return
}

if !in.Type().Is(tftypes.Number) {
err := fmt.Errorf("expected Int64 value, received %T with value: %v", in, in)
t.addTypeValidationError(err, path, &diags)
return
}

if !in.IsKnown() || in.IsNull() {
return
}

var valueFloat big.Float
if err := in.As(&valueFloat); err != nil {
t.addTypeValidationError(err, path, &diags)
return
}
valueInt64, _ := valueFloat.Int64()

if valueInt64 < t.Start || valueInt64 > int64(t.End) {
diags.AddAttributeError(
path,
"Invalid Int64 Value",
fmt.Sprintf("A value was provided that is not inside valid range (%v, %v).\n"+
"Given Value: %v", t.Start, t.End, valueInt64),
)
return
}

return
}
13 changes: 13 additions & 0 deletions util/string_describer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package util

import "context"

type StringDescriber struct{ Value string }

func (d StringDescriber) MarkdownDescription(context.Context) string {
return d.Value
}

func (d StringDescriber) Description(ctx context.Context) string {
return d.MarkdownDescription(ctx)
}
Loading

0 comments on commit 6e08b1e

Please sign in to comment.