This repository has been archived by the owner on Dec 30, 2024. It is now read-only.
generated from FrangipaneTeam/template-repository
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
22 changed files
with
1,786 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package supertypes | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"reflect" | ||
|
||
"github.com/hashicorp/terraform-plugin-framework/attr" | ||
) | ||
|
||
// AttributeTypes returns a map of attribute types for the specified type T. | ||
// T must be a struct and reflection is used to find exported fields of T with the `tfsdk` tag. | ||
func AttributeTypes[T any](ctx context.Context) (map[string]attr.Type, error) { | ||
var t T | ||
val := reflect.ValueOf(t) | ||
typ := val.Type() | ||
|
||
if typ.Kind() != reflect.Struct { | ||
return nil, fmt.Errorf("%T has unsupported type: %s", t, typ) | ||
} | ||
|
||
attributeTypes := make(map[string]attr.Type) | ||
for i := 0; i < typ.NumField(); i++ { | ||
field := typ.Field(i) | ||
if field.PkgPath != "" { | ||
continue // Skip unexported fields. | ||
} | ||
tag := field.Tag.Get(`tfsdk`) | ||
if tag == "-" { | ||
continue // Skip explicitly excluded fields. | ||
} | ||
if tag == "" { | ||
return nil, fmt.Errorf(`%T needs a struct tag for "tfsdk" on %s`, t, field.Name) | ||
} | ||
|
||
if v, ok := val.Field(i).Interface().(attr.Value); ok { | ||
attributeTypes[tag] = v.Type(ctx) | ||
} | ||
} | ||
|
||
return attributeTypes, nil | ||
} | ||
|
||
func AttributeTypesMust[T any](ctx context.Context) map[string]attr.Type { | ||
return Must(AttributeTypes[T](ctx)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package supertypes_test | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
|
||
"github.com/google/go-cmp/cmp" | ||
"github.com/hashicorp/terraform-plugin-framework/attr" | ||
"github.com/hashicorp/terraform-plugin-framework/types" | ||
|
||
supertypes "github.com/FrangipaneTeam/terraform-plugin-framework-supertypes" | ||
) | ||
|
||
func TestAttributeTypes(t *testing.T) { | ||
t.Parallel() | ||
|
||
type struct1 struct{} | ||
type struct2 struct { | ||
Name types.String `tfsdk:"name"` | ||
ID types.Int64 `tfsdk:"id"` | ||
IncludeProperty types.Bool `tfsdk:"include_property"` | ||
} | ||
|
||
ctx := context.Background() | ||
got := supertypes.AttributeTypesMust[struct1](ctx) | ||
wanted := map[string]attr.Type{} | ||
|
||
if diff := cmp.Diff(got, wanted); diff != "" { | ||
t.Errorf("unexpected diff (+wanted, -got): %s", diff) | ||
} | ||
|
||
_, err := supertypes.AttributeTypes[int](ctx) | ||
|
||
if err == nil { | ||
t.Fatalf("expected error") | ||
} | ||
|
||
got, err = supertypes.AttributeTypes[struct2](ctx) | ||
|
||
if err != nil { | ||
t.Fatalf("unexpected error") | ||
} | ||
|
||
wanted = map[string]attr.Type{ | ||
"name": types.StringType, | ||
"id": types.Int64Type, | ||
"include_property": types.BoolType, | ||
} | ||
|
||
if diff := cmp.Diff(got, wanted); diff != "" { | ||
t.Errorf("unexpected diff (+wanted, -got): %s", diff) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package supertypes | ||
|
||
import ( | ||
"errors" | ||
"fmt" | ||
|
||
"github.com/hashicorp/terraform-plugin-framework/diag" | ||
) | ||
|
||
// Must is a generic implementation of the Go Must idiom [1, 2]. It panics if | ||
// the provided error is non-nil and returns x otherwise. | ||
// | ||
// [1]: https://pkg.go.dev/text/template#Must | ||
// [2]: https://pkg.go.dev/regexp#MustCompile | ||
func Must[T any](x T, err error) T { | ||
if err != nil { | ||
panic(err) | ||
} | ||
return x | ||
} | ||
|
||
// MustDiag is a generic implementation of the Go Must idiom [1, 2]. It panics if | ||
// the provided Diagnostics has errors and returns x otherwise. | ||
// | ||
// [1]: https://pkg.go.dev/text/template#Must | ||
// [2]: https://pkg.go.dev/regexp#MustCompile | ||
func MustDiag[T any](x T, diags diag.Diagnostics) T { | ||
return Must(x, DiagnosticsError(diags)) | ||
} | ||
|
||
// DiagnosticsError returns an error containing all Diagnostic with SeverityError | ||
func DiagnosticsError(diags diag.Diagnostics) error { | ||
var errs []error | ||
|
||
for _, d := range diags.Errors() { | ||
errs = append(errs, errors.New(DiagnosticString(d))) | ||
} | ||
|
||
return errors.Join(errs...) | ||
} | ||
|
||
// DiagnosticString formats a Diagnostic | ||
// If there is no `Detail`, only prints summary, otherwise prints both | ||
func DiagnosticString(d diag.Diagnostic) string { | ||
if d.Detail() == "" { | ||
return d.Summary() | ||
} | ||
return fmt.Sprintf("%s\n\n%s", d.Summary(), d.Detail()) | ||
} |
Oops, something went wrong.