From 8e7dfbc92d3c96e013b33ab1c8f18ca25683ebad Mon Sep 17 00:00:00 2001 From: Jules Casteran Date: Thu, 22 Jun 2023 15:09:32 +0200 Subject: [PATCH] feat(tftemplate): add datasource generation to tftemplate --- cmd/tftemplate/datasource.go.tmpl | 77 ++++++++++++++++++++++++++ cmd/tftemplate/datasource_test.go.tmpl | 45 +++++++++++++++ cmd/tftemplate/main.go | 37 ++++++++++++- cmd/tftemplate/resource.go.tmpl | 2 + 4 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 cmd/tftemplate/datasource.go.tmpl create mode 100644 cmd/tftemplate/datasource_test.go.tmpl diff --git a/cmd/tftemplate/datasource.go.tmpl b/cmd/tftemplate/datasource.go.tmpl new file mode 100644 index 0000000000..1ca16e94f0 --- /dev/null +++ b/cmd/tftemplate/datasource.go.tmpl @@ -0,0 +1,77 @@ +{{- /*gotype: tftemplate/models.ResourceTemplate*/ -}} +package scaleway + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func dataSourceScaleway{{.Resource}}() *schema.Resource { + // Generate datasource schema from resource + dsSchema := datasourceSchemaFromResourceSchema(resourceScaleway{{.Resource}}().Schema) + + addOptionalFieldsToSchema(dsSchema, "name", "{{.Locality}}") + + dsSchema["{{.ResourceCleanLow}}_id"] = &schema.Schema{ + Type: schema.TypeString, + Optional: true, + Description: "The ID of the {{.ResourceCleanLow}}", + ConflictsWith: []string{"name"}, + ValidateFunc: validationUUIDorUUIDWithLocality(), + } + + return &schema.Resource{ + ReadContext: dataSourceScaleway{{.Resource}}Read, + Schema: dsSchema, + } +} + +func dataSourceScaleway{{.Resource}}Read(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { + api, {{.Locality}}, err := {{.API}}APIWith{{.LocalityUpper}}(d, meta) + if err != nil { + return diag.FromErr(err) + } + + {{.ResourceCleanLow}}ID, {{.ResourceCleanLow}}IDExists := d.GetOk("{{.ResourceCleanLow}}_id") + if !{{.ResourceCleanLow}}IDExists { + res, err := api.List{{.ResourceClean}}s(&{{.API}}.List{{.ResourceClean}}sRequest{ + {{.LocalityUpper}}: {{.Locality}}, + Name: expandStringPtr(d.Get("name")), + ProjectID: expandStringPtr(d.Get("project_id")), + }) + if err != nil { + return diag.FromErr(err) + } + for _, {{.ResourceCleanLow}} := range res.{{.ResourceClean}}s { + if {{.ResourceCleanLow}}.Name == d.Get("name").(string) { + if {{.ResourceCleanLow}}ID != "" { + return diag.Errorf("more than 1 {{.ResourceCleanLow}} found with the same name %s", d.Get("name")) + } + {{.ResourceCleanLow}}ID = {{.ResourceCleanLow}}.ID + } + } + if {{.ResourceCleanLow}}ID == "" { + return diag.Errorf("no {{.ResourceCleanLow}} found with the name %s", d.Get("name")) + } + } + + {{.Locality}}ID := datasourceNew{{.LocalityAdjectiveUpper}}ID({{.ResourceCleanLow}}ID, {{.Locality}}) + d.SetId({{.Locality}}ID) + err = d.Set("{{.ResourceCleanLow}}_id", {{.Locality}}ID) + if err != nil { + return diag.FromErr(err) + } + + diags := resourceScaleway{{.Resource}}Read(ctx, d, meta) + if diags != nil { + return append(diags, diag.Errorf("failed to read {{.ResourceCleanLow}} state")...) + } + + if d.Id() == "" { + return diag.Errorf("{{.ResourceCleanLow}} (%s) not found", {{.Locality}}ID) + } + + return nil +} diff --git a/cmd/tftemplate/datasource_test.go.tmpl b/cmd/tftemplate/datasource_test.go.tmpl new file mode 100644 index 0000000000..f82848c396 --- /dev/null +++ b/cmd/tftemplate/datasource_test.go.tmpl @@ -0,0 +1,45 @@ +{{- /*gotype: tftemplate/models.ResourceTemplate*/ -}} +package scaleway + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" +) + +func TestAccScalewayDataSource{{.Resource}}_Basic(t *testing.T) { + tt := NewTestTools(t) + defer tt.Cleanup() + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + ProviderFactories: tt.ProviderFactories, + CheckDestroy: resource.ComposeTestCheckFunc( + testAccCheckScaleway{{.Resource}}Destroy(tt), + ), + Steps: []resource.TestStep{ + { + Config: ` + resource scaleway_{{.ResourceHCL}} main { + name = "test-ds-{{.API}}-{{ .ResourceCleanLow}}-basic" + } + + data scaleway_{{.ResourceHCL}} find_by_name { + name = scaleway_{{.ResourceHCL}}.main.name + } + + data scaleway_{{.ResourceHCL}} find_by_id { + {{.ResourceCleanLow}}_id = scaleway_{{.ResourceHCL}}.main.id + } + `, + Check: resource.ComposeTestCheckFunc( + testAccCheckScaleway{{.Resource}}Exists(tt, "scaleway_{{.ResourceHCL}}.main"), + + resource.TestCheckResourceAttrPair("scaleway_{{.ResourceHCL}}.main", "name", "data.scaleway_{{.ResourceHCL}}.find_by_name", "name"), + resource.TestCheckResourceAttrPair("scaleway_{{.ResourceHCL}}.main", "name", "data.scaleway_{{.ResourceHCL}}.find_by_id", "name"), + resource.TestCheckResourceAttrPair("scaleway_{{.ResourceHCL}}.main", "id", "data.scaleway_{{.ResourceHCL}}.find_by_name", "id"), + resource.TestCheckResourceAttrPair("scaleway_{{.ResourceHCL}}.main", "id", "data.scaleway_{{.ResourceHCL}}.find_by_id", "id"), + ), + }, + }, + }) +} diff --git a/cmd/tftemplate/main.go b/cmd/tftemplate/main.go index 7d8b2d87ce..0a3ca68ef1 100644 --- a/cmd/tftemplate/main.go +++ b/cmd/tftemplate/main.go @@ -19,9 +19,21 @@ var ( resourceHelpersTemplateFile string //go:embed waiters.go.tmpl resourceWaitersTemplateFile string + //go:embed datasource.go.tmpl + datasourceTemplateFile string + //go:embed datasource_test.go.tmpl + datasourceTestTemplateFile string ) var resourceQS = []*survey.Question{ + { + Name: "targets", + Prompt: &survey.MultiSelect{ + Message: "Select targets to generate", + Options: []string{"resource", "datasource"}, + Default: []string{"resource"}, + }, + }, { Name: "api", Prompt: &survey.Input{Message: "API name (function, instance, container)"}, @@ -49,14 +61,25 @@ var resourceQS = []*survey.Question{ { Name: "waiters", Prompt: &survey.Confirm{ - Message: "Generate helpers ? Will be added to scaleway/helpers_{api}.go", + Message: "Generate waiters ? Will be added to scaleway/helpers_{api}.go", Default: true, }, }, } +func contains[T comparable](slice []T, expected T) bool { + for _, elem := range slice { + if elem == expected { + return true + } + } + + return false +} + func main() { resourceInput := struct { + Targets []string API string Resource string Locality string @@ -73,10 +96,22 @@ func main() { { FileName: fmt.Sprintf("../../scaleway/resource_%s.go", resourceData.ResourceHCL), TemplateFile: resourceTemplateFile, + Skip: !contains(resourceInput.Targets, "resource"), }, { FileName: fmt.Sprintf("../../scaleway/resource_%s_test.go", resourceData.ResourceHCL), TemplateFile: resourceTestTemplateFile, + Skip: !contains(resourceInput.Targets, "resource"), + }, + { + FileName: fmt.Sprintf("../../scaleway/data_source_%s.go", resourceData.ResourceHCL), + TemplateFile: datasourceTemplateFile, + Skip: !contains(resourceInput.Targets, "datasource"), + }, + { + FileName: fmt.Sprintf("../../scaleway/data_source_%s_test.go", resourceData.ResourceHCL), + TemplateFile: datasourceTestTemplateFile, + Skip: !contains(resourceInput.Targets, "datasource"), }, { FileName: fmt.Sprintf("../../scaleway/helpers_%s.go", resourceData.API), diff --git a/cmd/tftemplate/resource.go.tmpl b/cmd/tftemplate/resource.go.tmpl index 5cc768e62e..8ac78ae528 100644 --- a/cmd/tftemplate/resource.go.tmpl +++ b/cmd/tftemplate/resource.go.tmpl @@ -74,6 +74,8 @@ func resourceScaleway{{ .Resource }}Read(ctx context.Context, d *schema.Resource } _ = d.Set("name", {{ .ResourceCleanLow }}.Name) + _ = d.Set("{{.Locality}}", {{.ResourceCleanLow}}.{{.LocalityUpper}}) + _ = d.Set("project_id", {{.ResourceCleanLow}}.ProjectID) return nil }