Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
edwardfeng-db committed Aug 21, 2024
1 parent 6b38834 commit dec205c
Show file tree
Hide file tree
Showing 2 changed files with 162 additions and 0 deletions.
18 changes: 18 additions & 0 deletions pluginframework/tfschema/customizable_schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package tfschema

import (
"fmt"

"github.com/hashicorp/terraform-plugin-framework/schema/validator"
)

type CustomizableSchemaPluginFramework struct {
Expand Down Expand Up @@ -36,6 +38,22 @@ func attributeToMap(attr *AttributeBuilder) map[string]AttributeBuilder {

func (s *CustomizableSchemaPluginFramework) AddValidator(v any, path ...string) *CustomizableSchemaPluginFramework {
cb := func(attr AttributeBuilder) AttributeBuilder {
switch a := attr.(type) {
case BoolAttributeBuilder:

Check failure on line 42 in pluginframework/tfschema/customizable_schema.go

View workflow job for this annotation

GitHub Actions / tests

previous case

Check failure on line 42 in pluginframework/tfschema/customizable_schema.go

View workflow job for this annotation

GitHub Actions / tests

previous case
return a.AddValidator(v.(validator.Bool))
case Float64AttributeBuilder:

Check failure on line 44 in pluginframework/tfschema/customizable_schema.go

View workflow job for this annotation

GitHub Actions / tests

undefined: Float64AttributeBuilder
return a.AddValidator(v.(validator.Float64))
case BoolAttributeBuilder:

Check failure on line 46 in pluginframework/tfschema/customizable_schema.go

View workflow job for this annotation

GitHub Actions / tests

duplicate case BoolAttributeBuilder in type switch
return a.AddValidator(v.(validator.Bool))
case BoolAttributeBuilder:

Check failure on line 48 in pluginframework/tfschema/customizable_schema.go

View workflow job for this annotation

GitHub Actions / tests

duplicate case BoolAttributeBuilder in type switch
return a.AddValidator(v.(validator.Bool))
case BoolAttributeBuilder:
return a.AddValidator(v.(validator.Bool))
case BoolAttributeBuilder:
return a.AddValidator(v.(validator.Bool))
case BoolAttributeBuilder:
return a.AddValidator(v.(validator.Bool))
}
return attr.AddValidators(v)
}

Expand Down
144 changes: 144 additions & 0 deletions pluginframework/tfschema/struct_to_schema.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package tfschema

import (
"fmt"
"reflect"
"strings"
)

func pluginFrameworkTypeToSchema(v reflect.Value) map[string]Attribute {

Check failure on line 9 in pluginframework/tfschema/struct_to_schema.go

View workflow job for this annotation

GitHub Actions / tests

undefined: Attribute
scm := map[string]Attribute{}
rk := v.Kind()
if rk == reflect.Ptr {
v = v.Elem()
rk = v.Kind()
}
if rk != reflect.Struct {
panic(fmt.Errorf("Schema value of Struct is expected, but got %s: %#v", reflectKind(rk), v))
}
fields := listAllFields(v)
for _, field := range fields {
typeField := field.sf
fieldName := typeField.Tag.Get("tfsdk")
if fieldName == "-" {
continue
}
isOptional := fieldIsOptional(typeField)
// For now everything is marked as optional. TODO: add tf annotations for computed, optional, etc.
kind := typeField.Type.Kind()
if kind == reflect.Ptr {
elem := typeField.Type.Elem()
sv := reflect.New(elem).Elem()
nestedScm := pluginFrameworkTypeToSchema(sv)
scm[fieldName] = SingleNestedAttribute{Attributes: nestedScm, Optional: isOptional, Required: !isOptional}
} else if kind == reflect.Slice {
elem := typeField.Type.Elem()
if elem.Kind() == reflect.Ptr {
elem = elem.Elem()
}
if elem.Kind() != reflect.Struct {
panic(fmt.Errorf("unsupported slice value for %s: %s", fieldName, reflectKind(elem.Kind())))
}
switch elem {
case reflect.TypeOf(types.Bool{}):
scm[fieldName] = ListAttribute{ElementType: types.BoolType, Optional: isOptional, Required: !isOptional}
case reflect.TypeOf(types.Int64{}):
scm[fieldName] = ListAttribute{ElementType: types.Int64Type, Optional: isOptional, Required: !isOptional}
case reflect.TypeOf(types.Float64{}):
scm[fieldName] = ListAttribute{ElementType: types.Float64Type, Optional: isOptional, Required: !isOptional}
case reflect.TypeOf(types.String{}):
scm[fieldName] = ListAttribute{ElementType: types.StringType, Optional: isOptional, Required: !isOptional}
default:
// Nested struct
nestedScm := pluginFrameworkTypeToSchema(reflect.New(elem).Elem())
scm[fieldName] = ListNestedAttribute{NestedObject: NestedAttributeObject{Attributes: nestedScm}, Optional: isOptional, Required: !isOptional}
}
} else if kind == reflect.Map {
elem := typeField.Type.Elem()
if elem.Kind() == reflect.Ptr {
elem = elem.Elem()
}
if elem.Kind() != reflect.Struct {
panic(fmt.Errorf("unsupported map value for %s: %s", fieldName, reflectKind(elem.Kind())))
}
switch elem {
case reflect.TypeOf(types.Bool{}):
scm[fieldName] = MapAttribute{ElementType: types.BoolType, Optional: isOptional, Required: !isOptional}
case reflect.TypeOf(types.Int64{}):
scm[fieldName] = MapAttribute{ElementType: types.Int64Type, Optional: isOptional, Required: !isOptional}
case reflect.TypeOf(types.Float64{}):
scm[fieldName] = MapAttribute{ElementType: types.Float64Type, Optional: isOptional, Required: !isOptional}
case reflect.TypeOf(types.String{}):
scm[fieldName] = MapAttribute{ElementType: types.StringType, Optional: isOptional, Required: !isOptional}
default:
// Nested struct
nestedScm := pluginFrameworkTypeToSchema(reflect.New(elem).Elem())
scm[fieldName] = MapNestedAttribute{NestedObject: NestedAttributeObject{Attributes: nestedScm}, Optional: isOptional, Required: !isOptional}
}
} else if kind == reflect.Struct {
switch field.v.Interface().(type) {
case types.Bool:
scm[fieldName] = BoolAttribute{Optional: isOptional, Required: !isOptional}
case types.Int64:
scm[fieldName] = Int64Attribute{Optional: isOptional, Required: !isOptional}
case types.Float64:
scm[fieldName] = Float64Attribute{Optional: isOptional, Required: !isOptional}
case types.String:
scm[fieldName] = StringAttribute{Optional: isOptional, Required: !isOptional}
case types.List:
panic("types.List should never be used in tfsdk structs")
case types.Map:
panic("types.Map should never be used in tfsdk structs")
default:
// If it is a real stuct instead of a tfsdk type, recursively resolve it.
elem := typeField.Type
sv := reflect.New(elem)
nestedScm := pluginFrameworkTypeToSchema(sv)
scm[fieldName] = SingleNestedAttribute{Attributes: nestedScm, Optional: isOptional, Required: !isOptional}
}
} else if kind == reflect.String {
// This case is for Enum types.
scm[fieldName] = StringAttribute{Optional: isOptional, Required: !isOptional}
} else {
panic(fmt.Errorf("unknown type for field: %s", typeField.Name))
}
}
return scm
}

func fieldIsOptional(field reflect.StructField) bool {
tagValue := field.Tag.Get("tf")
return strings.Contains(tagValue, "optional")
}

func PluginFrameworkResourceStructToSchema(v any, customizeSchema func(CustomizableSchemaPluginFramework) CustomizableSchemaPluginFramework) schema.Schema {

Check failure on line 114 in pluginframework/tfschema/struct_to_schema.go

View workflow job for this annotation

GitHub Actions / tests

undefined: schema
attributes := PluginFrameworkResourceStructToSchemaMap(v, customizeSchema)
return schema.Schema{Attributes: attributes}
}

func PluginFrameworkDataSourceStructToSchema(v any, customizeSchema func(CustomizableSchemaPluginFramework) CustomizableSchemaPluginFramework) dataschema.Schema {

Check failure on line 119 in pluginframework/tfschema/struct_to_schema.go

View workflow job for this annotation

GitHub Actions / tests

undefined: dataschema
attributes := PluginFrameworkDataSourceStructToSchemaMap(v, customizeSchema)
return dataschema.Schema{Attributes: attributes}
}

func PluginFrameworkResourceStructToSchemaMap(v any, customizeSchema func(CustomizableSchemaPluginFramework) CustomizableSchemaPluginFramework) map[string]schema.Attribute {

Check failure on line 124 in pluginframework/tfschema/struct_to_schema.go

View workflow job for this annotation

GitHub Actions / tests

undefined: schema
attributes := pluginFrameworkTypeToSchema(reflect.ValueOf(v))

if customizeSchema != nil {
cs := customizeSchema(*ConstructCustomizableSchema(attributes))
return BuildResourceAttributeMap(cs.ToAttributeMap())
} else {
return BuildResourceAttributeMap(attributes)
}
}

func PluginFrameworkDataSourceStructToSchemaMap(v any, customizeSchema func(CustomizableSchemaPluginFramework) CustomizableSchemaPluginFramework) map[string]dataschema.Attribute {

Check failure on line 135 in pluginframework/tfschema/struct_to_schema.go

View workflow job for this annotation

GitHub Actions / tests

undefined: dataschema
attributes := pluginFrameworkTypeToSchema(reflect.ValueOf(v))

if customizeSchema != nil {
cs := customizeSchema(*ConstructCustomizableSchema(attributes))
return BuildDataSourceAttributeMap(cs.ToAttributeMap())
} else {
return BuildDataSourceAttributeMap(attributes)
}
}

0 comments on commit dec205c

Please sign in to comment.