Skip to content

Commit ccf9ac2

Browse files
authored
feat: Generate Terraform DataSource structures (#120)
1 parent 11eb059 commit ccf9ac2

File tree

3 files changed

+142
-13
lines changed

3 files changed

+142
-13
lines changed

pkg/translate/terraform_provider/funcs.go

Lines changed: 134 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ type spec struct {
3030
OneOf map[string]*properties.SpecParam
3131
}
3232

33-
func getReturnPangoTypeForProperty(pkgName string, parent string, prop *properties.SpecParam) string {
33+
func returnPangoTypeForProperty(pkgName string, parent string, prop *properties.SpecParam) string {
3434
if prop.Type == "" {
3535
return fmt.Sprintf("%s.%s", pkgName, parent)
3636
} else if prop.Type == "list" {
@@ -675,6 +675,139 @@ func RenderLocationsStateToPango(names *NameProvider, spec *properties.Normaliza
675675
return processTemplate(locationsStateToPango, "render-locations-state-to-pango", data, commonFuncMap)
676676
}
677677

678+
const dataSourceStructs = `
679+
{{- range .Structs }}
680+
type {{ .StructName }}{{ .ModelOrObject }} struct {
681+
{{- range .Fields }}
682+
{{ .Name }} {{ .Type }} {{ range .Tags }}{{ . }} {{ end }}
683+
{{- end }}
684+
}
685+
{{- end }}
686+
`
687+
688+
type datasourceStructFieldSpec struct {
689+
Name string
690+
Type string
691+
Tags []string
692+
}
693+
694+
type datasourceStructSpec struct {
695+
StructName string
696+
ModelOrObject string
697+
Fields []datasourceStructFieldSpec
698+
}
699+
700+
func terraformTypeForProperty(structPrefix string, prop *properties.SpecParam) string {
701+
if prop.Type == "" {
702+
return fmt.Sprintf("*%s%sObject", structPrefix, prop.Name.CamelCase)
703+
}
704+
705+
if prop.Type == "list" && prop.Items.Type == "entry" {
706+
return fmt.Sprintf("[]%s%sObject", structPrefix, prop.Name.CamelCase)
707+
}
708+
709+
if prop.Type == "list" {
710+
return fmt.Sprintf("[]types.%s", pascalCase(prop.Items.Type))
711+
}
712+
713+
return fmt.Sprintf("types.%s", pascalCase(prop.Type))
714+
}
715+
716+
func structFieldSpec(param *properties.SpecParam, structPrefix string) datasourceStructFieldSpec {
717+
tfTag := fmt.Sprintf("`tfsdk:\"%s\"`", param.Name.Underscore)
718+
return datasourceStructFieldSpec{
719+
Name: param.Name.CamelCase,
720+
Type: terraformTypeForProperty(structPrefix, param),
721+
Tags: []string{tfTag},
722+
}
723+
}
724+
725+
func dataSourceStructContextForParam(structPrefix string, param *properties.SpecParam) []datasourceStructSpec {
726+
var structs []datasourceStructSpec
727+
728+
structName := fmt.Sprintf("%s%s", structPrefix, param.Name.CamelCase)
729+
730+
var params []datasourceStructFieldSpec
731+
if param.Spec != nil {
732+
for _, elt := range param.Spec.Params {
733+
params = append(params, structFieldSpec(elt, structName))
734+
}
735+
736+
for _, elt := range param.Spec.OneOf {
737+
params = append(params, structFieldSpec(elt, structName))
738+
}
739+
}
740+
741+
structs = append(structs, datasourceStructSpec{
742+
StructName: structName,
743+
ModelOrObject: "Object",
744+
Fields: params,
745+
})
746+
747+
if param.Spec == nil {
748+
return structs
749+
}
750+
751+
for _, elt := range param.Spec.Params {
752+
if elt.Type == "" || (elt.Type == "list" && elt.Items.Type == "entry") {
753+
structs = append(structs, dataSourceStructContextForParam(structName, elt)...)
754+
}
755+
}
756+
757+
for _, elt := range param.Spec.OneOf {
758+
if elt.Type == "" || (elt.Type == "list" && elt.Items.Type == "entry") {
759+
structs = append(structs, dataSourceStructContextForParam(structName, elt)...)
760+
}
761+
}
762+
763+
return structs
764+
}
765+
766+
func dataSourceStructContext(spec *properties.Normalization) []datasourceStructSpec {
767+
var structs []datasourceStructSpec
768+
769+
if spec.Spec == nil {
770+
return nil
771+
}
772+
773+
names := NewNameProvider(spec)
774+
775+
var fields []datasourceStructFieldSpec
776+
777+
for _, elt := range spec.Spec.Params {
778+
fields = append(fields, structFieldSpec(elt, names.DataSourceStructName))
779+
if elt.Type == "" || (elt.Type == "list" && elt.Items.Type == "entry") {
780+
structs = append(structs, dataSourceStructContextForParam(names.DataSourceStructName, elt)...)
781+
}
782+
}
783+
784+
for _, elt := range spec.Spec.OneOf {
785+
fields = append(fields, structFieldSpec(elt, names.DataSourceStructName))
786+
if elt.Type == "" || (elt.Type == "list" && elt.Items.Type == "entry") {
787+
structs = append(structs, dataSourceStructContextForParam(names.DataSourceStructName, elt)...)
788+
}
789+
}
790+
791+
structs = append(structs, datasourceStructSpec{
792+
StructName: names.DataSourceStructName,
793+
ModelOrObject: "Model",
794+
Fields: fields,
795+
})
796+
return structs
797+
}
798+
799+
func RenderDataSourceStructs(names *NameProvider, spec *properties.Normalization) (string, error) {
800+
type context struct {
801+
Structs []datasourceStructSpec
802+
}
803+
804+
data := context{
805+
Structs: dataSourceStructContext(spec),
806+
}
807+
808+
return processTemplate(dataSourceStructs, "render-locations-state-to-pango", data, commonFuncMap)
809+
}
810+
678811
func ResourceCreateFunction(names *NameProvider, serviceName string, paramSpec *properties.Normalization, terraformProvider *properties.TerraformProviderFile, resourceSDKName string) (string, error) {
679812
funcMap := template.FuncMap{
680813
"ConfigToEntry": ConfigEntry,

pkg/translate/terraform_provider/template.go

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -498,17 +498,11 @@ type {{ structName }} struct {
498498
client *pango.Client
499499
}
500500
501-
type {{ structName }}Model struct {
502-
//TODO: Generate Data Source model via function
503-
}
504-
505501
type {{ structName }}Filter struct {
506502
//TODO: Generate Data Source filter via function
507503
}
508504
509-
type {{ structName }}Entry struct {
510-
// TODO: Entry model struct via function
511-
}
505+
{{ RenderDataSourceStructs }}
512506
513507
// Metadata returns the data source type name.
514508
func (d *{{ structName }}) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {

pkg/translate/terraform_provider/terraform_provider_file.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ type NameProvider struct {
2222
}
2323

2424
// NewNameProvider creates a new NameProvider based on given specifications.
25-
func NewNameProvider(spec *properties.Normalization, resourceName string) *NameProvider {
25+
func NewNameProvider(spec *properties.Normalization) *NameProvider {
2626
var objectName string
2727

2828
tfName := spec.Name
@@ -100,7 +100,7 @@ func (g *GenerateTerraformProvider) generateTerraformEntityTemplate(resourceType
100100
// GenerateTerraformResource generates a Terraform resource template.
101101
func (g *GenerateTerraformProvider) GenerateTerraformResource(spec *properties.Normalization, terraformProvider *properties.TerraformProviderFile) error {
102102
resourceType := "Resource"
103-
names := NewNameProvider(spec, resourceType)
103+
names := NewNameProvider(spec)
104104
funcMap := template.FuncMap{
105105
"metaName": func() string { return names.MetaName },
106106
"structName": func() string { return names.StructName },
@@ -235,13 +235,15 @@ func (g *GenerateTerraformProvider) GenerateTerraformDataSource(spec *properties
235235

236236
if !spec.TerraformProviderConfig.SkipDatasource {
237237
terraformProvider.ImportManager.AddHashicorpImport("github.com/hashicorp/terraform-plugin-framework/datasource/schema", "dsschema")
238+
terraformProvider.ImportManager.AddHashicorpImport("github.com/hashicorp/terraform-plugin-framework/types", "")
238239
terraformProvider.ImportManager.AddHashicorpImport("github.com/hashicorp/terraform-plugin-framework/datasource", "")
239240

240241
resourceType := "DataSource"
241-
names := NewNameProvider(spec, resourceType)
242+
names := NewNameProvider(spec)
242243
funcMap := template.FuncMap{
243-
"metaName": func() string { return names.MetaName },
244-
"structName": func() string { return names.DataSourceStructName },
244+
"metaName": func() string { return names.MetaName },
245+
"structName": func() string { return names.DataSourceStructName },
246+
"RenderDataSourceStructs": func() (string, error) { return RenderDataSourceStructs(names, spec) },
245247
}
246248
err := g.generateTerraformEntityTemplate(resourceType, names, spec, terraformProvider, dataSourceSingletonObj, funcMap)
247249
if err != nil {

0 commit comments

Comments
 (0)