Skip to content

Commit

Permalink
Adding processing for bool with associated external type (#31)
Browse files Browse the repository at this point in the history
  • Loading branch information
bendbennett committed Aug 7, 2023
1 parent cd665dd commit 2894156
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 30 deletions.
5 changes: 3 additions & 2 deletions internal/datasource_convert/bool_attribute.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ func convertBoolAttribute(a *datasource.BoolAttribute) (datasource_generate.Gene
DeprecationMessage: deprecationMessage(a.DeprecationMessage),
},

CustomType: a.CustomType,
Validators: a.Validators,
AssociatedExternalType: a.AssociatedExternalType,
CustomType: a.CustomType,
Validators: a.Validators,
}, nil
}
12 changes: 10 additions & 2 deletions internal/datasource_generate/bool_attribute.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,13 @@ type GeneratorBoolAttribute struct {

// The "specschema" types are used instead of the types within the attribute
// because support for extracting custom import information is required.
CustomType *specschema.CustomType
Validators []specschema.BoolValidator
AssociatedExternalType *specschema.AssociatedExternalType
CustomType *specschema.CustomType
Validators []specschema.BoolValidator
}

func (g GeneratorBoolAttribute) AssocExtType() *generatorschema.AssocExtType {
return generatorschema.NewAssocExtType(g.AssociatedExternalType)
}

func (g GeneratorBoolAttribute) AttrType() attr.Type {
Expand All @@ -40,6 +45,9 @@ func (g GeneratorBoolAttribute) Imports() *generatorschema.Imports {
imports.Append(customValidatorImports)
}

assocExtTypeImports := generatorschema.AssociatedExternalTypeImports(g.AssociatedExternalType)
imports.Append(assocExtTypeImports)

return imports
}

Expand Down
123 changes: 97 additions & 26 deletions internal/schema/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,8 @@ func (g GeneratorSchema) ModelObjectHelpersTemplate(name string) ([]byte, error)
return buf.Bytes(), nil
}

// TODO: Call recursively to generate "expand" and "flatten" functions for all nested blocks and attributes
// which may have an associated external type.
func (g GeneratorSchema) ModelsToFromBytes() ([]byte, error) {
var buf bytes.Buffer

Expand All @@ -532,23 +534,55 @@ func (g GeneratorSchema) ModelsToFromBytes() ([]byte, error) {
continue
}

//fmt.Println(g.Attributes[k].AttrType())
//
//if g.Attributes[k].AttrType() == types.Object {
//}
//
//if a, ok := g.Attributes[k].(Attributes); ok {
// ng := GeneratorSchema{
// Attributes: a.GetAttributes(),
// }
//
// modelObjectHelpers, err := ng.ModelObjectHelpersTemplate(k)
// if err != nil {
// return nil, err
// }
//
// buf.Write(modelObjectHelpers)
//}
// TODO: Type check is only required until all blocks and attributes
// implement AssocExtType().
var attributeAssocExtType GeneratorAttributeAssocExtType
var ok bool

if attributeAssocExtType, ok = g.Attributes[k].(GeneratorAttributeAssocExtType); !ok {
continue
}

assocExtType := attributeAssocExtType.AssocExtType()

if assocExtType == nil {
continue
}

if _, ok := attributeAssocExtType.(Attributes); ok {
// TODO: Handle objects - object itself and list, map, set, single nested object
} else {
switch attributeAssocExtType.AttrType() {
case types.BoolType:
t, err := template.New("model_bool_to_from").Parse(templates.ModelBoolToFromTemplate)
if err != nil {
return nil, err
}

var boolBuf bytes.Buffer

templateData := struct {
Name string
Type string
TypeReference string
}{
Name: model.SnakeCaseToCamelCase(k),
Type: assocExtType.Type(),
TypeReference: assocExtType.TypeReference(),
}

err = t.Execute(&boolBuf, templateData)
if err != nil {
return nil, err
}

if boolBuf.Len() > 0 {
buf.WriteString("\n")
buf.Write(boolBuf.Bytes())
}
}
}

}

// Using sorted blockKeys to guarantee block order as maps are unordered in Go.
Expand All @@ -567,14 +601,14 @@ func (g GeneratorSchema) ModelsToFromBytes() ([]byte, error) {

// TODO: Type check is only required until all blocks and attributes
// implement AssocExtType().
var b GeneratorBlockAssocExtType
var blockAssocExtType GeneratorBlockAssocExtType
var ok bool

if b, ok = g.Blocks[k].(GeneratorBlockAssocExtType); !ok {
if blockAssocExtType, ok = g.Blocks[k].(GeneratorBlockAssocExtType); !ok {
continue
}

assocExtType := b.AssocExtType()
assocExtType := blockAssocExtType.AssocExtType()

if assocExtType == nil {
continue
Expand All @@ -586,18 +620,40 @@ func (g GeneratorSchema) ModelsToFromBytes() ([]byte, error) {
return nil, fmt.Errorf("all block types must implement Attributes, %s does not", k)
}

// TODO: Need to process blocks in the template
b, ok := g.Blocks[k].(Blocks)

if !ok {
return nil, fmt.Errorf("all block types must implement Blocks, %s does not", k)
}

attributes := make(map[string]map[string]string)

// TODO: Check whether v implements AssocExtType, and use that in preference to "default".
for k, v := range a.GetAttributes() {
for x, v := range a.GetAttributes() {
switch v.AttrType() {
case types.BoolType:
attributes[model.SnakeCaseToCamelCase(k)] = map[string]string{
"to": "ValueBoolPointer",
"from": "BoolPointerValue",
// TODO: Remove type assertion once all attributes and blocks implement AssocExtType()
if y, ok := v.(GeneratorAttributeAssocExtType); ok {
if y.AssocExtType() != nil {

attributes[model.SnakeCaseToCamelCase(x)] = map[string]string{
"toAssocExtType": fmt.Sprintf("To%s(ctx, tfModel.%s)", model.SnakeCaseToCamelCase(x), model.SnakeCaseToCamelCase(x)),
"toAssocExtTypeVar": fmt.Sprintf("to%s", model.SnakeCaseToCamelCase(x)),
"fromAssocExtType": fmt.Sprintf("From%s(ctx, apiObject.%s)", model.SnakeCaseToCamelCase(x), model.SnakeCaseToCamelCase(x)),
"fromAssocExtTypeVar": fmt.Sprintf("from%s", model.SnakeCaseToCamelCase(x)),
}

continue
}

attributes[model.SnakeCaseToCamelCase(x)] = map[string]string{
"to": "ValueBoolPointer",
"from": "BoolPointerValue",
}
}
case types.Int64Type:
attributes[model.SnakeCaseToCamelCase(k)] = map[string]string{
attributes[model.SnakeCaseToCamelCase(x)] = map[string]string{
"to": "ValueInt64Pointer",
"from": "Int64PointerValue",
}
Expand All @@ -609,7 +665,7 @@ func (g GeneratorSchema) ModelsToFromBytes() ([]byte, error) {
// "flatten" or a slice of objects (list, set) in "expand" and "flatten".
// This can be determined by using the attr.Type and a case.

switch b.AttrType().(type) {
switch blockAssocExtType.AttrType().(type) {
case basetypes.ObjectTypable:
t, err := template.New("model_object_to_from").Parse(templates.ModelObjectToFromTemplate)
if err != nil {
Expand Down Expand Up @@ -638,6 +694,21 @@ func (g GeneratorSchema) ModelsToFromBytes() ([]byte, error) {
buf.WriteString("\n")
buf.Write(objBuf.Bytes())
}

s := GeneratorSchema{
Attributes: a.GetAttributes(),
Blocks: b.GetBlocks(),
}

toFromBytes, err := s.ModelsToFromBytes()
if err != nil {
return nil, err
}

if len(toFromBytes) > 0 {
buf.WriteString("\n")
buf.Write(toFromBytes)
}
}

if buf.Len() > 0 {
Expand Down
8 changes: 8 additions & 0 deletions internal/schema/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ type GeneratorBlock interface {
ToString(string) (string, error)
}

// TODO: AssocExtType() can be added to GeneratorAttribute,
// and GeneratorBlock once all attributes and blocks
// implement the function.
type GeneratorAttributeAssocExtType interface {
GeneratorAttribute
AssocExtType() *AssocExtType
}

// TODO: AssocExtType() can be added to GeneratorAttribute,
// and GeneratorBlock once all attributes and blocks
// implement the function.
Expand Down
3 changes: 3 additions & 0 deletions internal/templates/embed.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import (
//go:embed model_object_helpers.gotmpl
var ModelObjectHelpersTemplate string

//go:embed model_bool_to_from.gotmpl
var ModelBoolToFromTemplate string

//go:embed model_object_to_from.gotmpl
var ModelObjectToFromTemplate string

Expand Down
23 changes: 23 additions & 0 deletions internal/templates/model_bool_to_from.gotmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
func To{{.Name}}(ctx context.Context, tfBool types.Bool) ({{.Type}}, diag.Diagnostics) {
var diags diag.Diagnostics

if tfBool.IsNull() || tfBool.IsUnknown() {
return nil, diags
}

apiObject := &{{.TypeReference}}{
{{.Name}}: tfBool.ValueBoolPointer(),
}

return apiObject, diags
}

func From{{.Name}}(ctx context.Context, apiObject {{.Type}}) (types.Bool, diag.Diagnostics) {
var diags diag.Diagnostics

if apiObject == nil {
return types.BoolNull(), diags
}

return types.BoolPointerValue(apiObject.{{.Name}}), diags
}
32 changes: 32 additions & 0 deletions internal/templates/model_object_to_from.gotmpl
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,26 @@ if diags.HasError() {
return nil, diags
}

{{range $key, $value := .Attributes }}
{{- if $value.toAssocExtType}}
{{$value.toAssocExtTypeVar}}, d := {{$value.toAssocExtType}}

diags.Append(d...)

if diags.HasError() {
return nil, diags
}
{{- end}}
{{- end}}

apiObject := &{{.TypeReference}}{
{{- range $key, $value := .Attributes }}
{{- if $value.toAssocExtType}}
{{$key}}: {{$value.toAssocExtTypeVar}},
{{- else}}
{{$key}}: tfModel.{{$key}}.{{$value.to}}(),
{{- end}}
{{- end}}
}

return apiObject, diags
Expand All @@ -31,8 +47,24 @@ return tfModel.ObjectNull(ctx), diags
}

{{range $key, $value := .Attributes }}
{{- if $value.fromAssocExtType}}
{{$value.fromAssocExtTypeVar}}, d := {{$value.fromAssocExtType}}

diags.Append(d...)

if diags.HasError() {
return tfModel.ObjectNull(ctx), diags
}
{{- end}}
{{- end}}

{{range $key, $value := .Attributes }}
{{- if $value.fromAssocExtType}}
tfModel.{{$key}} = {{$value.fromAssocExtTypeVar}}
{{- else}}
tfModel.{{$key}} = types.{{$value.from}}(apiObject.{{$key}})
{{- end}}
{{- end}}

return tfModel.ObjectValueFrom(ctx, tfModel)
}

0 comments on commit 2894156

Please sign in to comment.