Skip to content

Commit d6166b5

Browse files
autogeneration of tests for singular datasources (#14872)
Co-authored-by: Stephen Lewis (Burrows) <[email protected]>
1 parent 6bb6bdc commit d6166b5

File tree

10 files changed

+177
-82
lines changed

10 files changed

+177
-82
lines changed

mmv1/api/resource.go

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,31 +1203,42 @@ func ImportIdFormats(importFormat, identity []string, baseUrl string) []string {
12031203
return uniq
12041204
}
12051205

1206-
func (r Resource) IgnoreReadPropertiesToString(e resource.Examples) string {
1206+
// IgnoreReadProperties returns a sorted slice of property names (snake_case) that should be ignored when reading.
1207+
// This is useful for downstream code that needs to iterate over these properties.
1208+
func (r Resource) IgnoreReadProperties(e resource.Examples) []string {
12071209
var props []string
12081210
for _, tp := range r.AllUserProperties() {
12091211
if tp.UrlParamOnly || tp.IsA("ResourceRef") {
1210-
props = append(props, fmt.Sprintf("\"%s\"", google.Underscore(tp.Name)))
1212+
props = append(props, google.Underscore(tp.Name))
12111213
}
12121214
}
1213-
for _, tp := range e.IgnoreReadExtra {
1214-
props = append(props, fmt.Sprintf("\"%s\"", tp))
1215-
}
1216-
for _, tp := range r.IgnoreReadLabelsFields(r.PropertiesWithExcluded()) {
1217-
props = append(props, fmt.Sprintf("\"%s\"", tp))
1218-
}
1219-
for _, tp := range ignoreReadFields(r.AllUserProperties()) {
1220-
props = append(props, fmt.Sprintf("\"%s\"", tp))
1221-
}
1215+
props = append(props, e.IgnoreReadExtra...)
1216+
props = append(props, r.IgnoreReadLabelsFields(r.PropertiesWithExcluded())...)
1217+
props = append(props, ignoreReadFields(r.AllUserProperties())...)
12221218

12231219
slices.Sort(props)
1220+
return props
1221+
}
12241222

1223+
// IgnoreReadPropertiesToString returns the ignore read properties as a Go-syntax string slice.
1224+
// This is a wrapper around IgnoreReadProperties for backwards compatibility.
1225+
func (r Resource) IgnoreReadPropertiesToString(e resource.Examples) string {
1226+
props := r.IgnoreReadProperties(e)
12251227
if len(props) > 0 {
1226-
return fmt.Sprintf("[]string{%s}", strings.Join(props, ", "))
1228+
return fmt.Sprintf("[]string{%s}", strings.Join(quoteStrings(props), ", "))
12271229
}
12281230
return ""
12291231
}
12301232

1233+
// quoteStrings returns a new slice with each string quoted.
1234+
func quoteStrings(strs []string) []string {
1235+
quoted := make([]string, len(strs))
1236+
for i, s := range strs {
1237+
quoted[i] = fmt.Sprintf("\"%s\"", s)
1238+
}
1239+
return quoted
1240+
}
1241+
12311242
func ignoreReadFields(props []*Type) []string {
12321243
var fields []string
12331244
for _, tp := range props {
@@ -2021,6 +2032,13 @@ func (r *Resource) ShouldGenerateSingularDataSource() bool {
20212032
return r.Datasource.Generate
20222033
}
20232034

2035+
func (r *Resource) ShouldGenerateSingularDataSourceTests() bool {
2036+
if r.Datasource == nil {
2037+
return false
2038+
}
2039+
return !r.Datasource.ExcludeTest
2040+
}
2041+
20242042
func (r Resource) ShouldDatasourceSetLabels() bool {
20252043
for _, p := range r.Properties {
20262044
if p.Name == "labels" && p.Type == "KeyValueLabels" {

mmv1/api/resource/datasource.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,6 @@ package resource
1616
type Datasource struct {
1717
// boolean to determine whether the datasource file should be generated
1818
Generate bool `yaml:"generate"`
19+
// boolean to determine whether tests should be generated for a datasource
20+
ExcludeTest bool `yaml:"exclude_test"`
1921
}

mmv1/products/cloudrun/Service.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import_format:
3131
- 'locations/{{location}}/namespaces/{{project}}/services/{{name}}'
3232
datasource:
3333
generate: true
34+
exclude_test: true
3435
timeouts:
3536
insert_minutes: 20
3637
update_minutes: 20

mmv1/products/storagecontrol/FolderIntelligenceConfig.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ autogen_async: false
5151

5252
datasource:
5353
generate: true
54+
exclude_test: true
5455

5556
examples:
5657
- name: storage_control_folder_intelligence_config_basic

mmv1/products/storagecontrol/OrganizationIntelligenceConfig.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ autogen_async: false
5151

5252
datasource:
5353
generate: true
54+
exclude_test: true
5455

5556
examples:
5657
- name: storage_control_organization_intelligence_config_basic

mmv1/products/storagecontrol/ProjectIntelligenceConfig.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ autogen_async: false
5252

5353
datasource:
5454
generate: true
55+
exclude_test: true
5556

5657
examples:
5758
- name: storage_control_project_intelligence_config_basic

mmv1/provider/template_data.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,35 @@ func (td *TemplateData) GenerateTestFile(filePath string, resource api.Resource)
165165
td.GenerateFile(filePath, templatePath, tmplInput, true, templates...)
166166
}
167167

168+
func (td *TemplateData) GenerateDataSourceTestFile(filePath string, resource api.Resource) {
169+
templatePath := "templates/terraform/examples/base_configs/datasource_test_file.go.tmpl"
170+
templates := []string{
171+
"templates/terraform/env_var_context.go.tmpl",
172+
templatePath,
173+
}
174+
tmplInput := TestInput{
175+
Res: resource,
176+
ImportPath: resource.ImportPath,
177+
PROJECT_NAME: "my-project-name",
178+
CREDENTIALS: "my/credentials/filename.json",
179+
REGION: "us-west1",
180+
ORG_ID: "123456789",
181+
ORG_DOMAIN: "example.com",
182+
ORG_TARGET: "123456789",
183+
PROJECT_NUMBER: "1111111111111",
184+
BILLING_ACCT: "000000-0000000-0000000-000000",
185+
MASTER_BILLING_ACCT: "000000-0000000-0000000-000000",
186+
SERVICE_ACCT: "[email protected]",
187+
CUST_ID: "A01b123xz",
188+
IDENTITY_USER: "cloud_identity_user",
189+
PAP_DESCRIPTION: "description",
190+
CHRONICLE_ID: "00000000-0000-0000-0000-000000000000",
191+
VMWAREENGINE_PROJECT: "my-vmwareengine-project",
192+
}
193+
194+
td.GenerateFile(filePath, templatePath, tmplInput, true, templates...)
195+
}
196+
168197
func (td *TemplateData) GenerateIamPolicyFile(filePath string, resource api.Resource) {
169198
templatePath := "templates/terraform/iam_policy.go.tmpl"
170199
templates := []string{

mmv1/provider/terraform.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ func (t *Terraform) GenerateObject(object api.Resource, outputFolder, productPat
108108
t.GenerateResourceTests(object, *templateData, outputFolder)
109109
t.GenerateResourceSweeper(object, *templateData, outputFolder)
110110
t.GenerateSingularDataSource(object, *templateData, outputFolder)
111+
t.GenerateSingularDataSourceTests(object, *templateData, outputFolder)
111112
// log.Printf("Generating %s metadata", object.Name)
112113
t.GenerateResourceMetadata(object, *templateData, outputFolder)
113114
}
@@ -208,6 +209,21 @@ func (t *Terraform) GenerateSingularDataSource(object api.Resource, templateData
208209
templateData.GenerateDataSourceFile(targetFilePath, object)
209210
}
210211

212+
func (t *Terraform) GenerateSingularDataSourceTests(object api.Resource, templateData TemplateData, outputFolder string) {
213+
if !object.ShouldGenerateSingularDataSourceTests() {
214+
return
215+
}
216+
217+
productName := t.Product.ApiName
218+
targetFolder := path.Join(outputFolder, t.FolderName(), "services", productName)
219+
if err := os.MkdirAll(targetFolder, os.ModePerm); err != nil {
220+
log.Println(fmt.Errorf("error creating parent directory %v: %v", targetFolder, err))
221+
}
222+
targetFilePath := path.Join(targetFolder, fmt.Sprintf("data_source_%s_test.go", t.ResourceGoFilename(object)))
223+
templateData.GenerateDataSourceTestFile(targetFilePath, object)
224+
225+
}
226+
211227
// GenerateProduct creates the product.go file for a given service directory.
212228
// This will be used to seed the directory and add a package-level comment
213229
// specific to the product.
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
// ----------------------------------------------------------------------------
5+
//
6+
// *** AUTO GENERATED CODE *** Type: MMv1 ***
7+
//
8+
// ----------------------------------------------------------------------------
9+
//
10+
// This file is automatically generated by Magic Modules and manual
11+
// changes will be clobbered when the file is regenerated.
12+
//
13+
// Please read more about how to change this file in
14+
// .github/CONTRIBUTING.md.
15+
//
16+
// ----------------------------------------------------------------------------
17+
18+
package {{ $.Res.PackageName }}_test
19+
20+
import (
21+
"fmt"
22+
"testing"
23+
24+
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
25+
26+
"{{ $.ImportPath }}/acctest"
27+
"{{ $.ImportPath }}/envvar"
28+
"{{ $.ImportPath }}/tpgresource"
29+
)
30+
31+
{{ if $.Res.TestExamples }}
32+
{{ $e := index $.Res.TestExamples 0 }}
33+
func TestAccDataSource{{ $.Res.ResourceName }}_basic(t *testing.T) {
34+
t.Parallel()
35+
36+
context := map[string]interface{}{
37+
{{- template "EnvVarContext" dict "TestEnvVars" $e.TestEnvVars "HasNewLine" false}}
38+
{{- range $varKey, $varVal := $e.TestVarsOverrides }}
39+
"{{$varKey}}": {{$varVal}},
40+
{{- end }}
41+
"random_suffix": acctest.RandString(t, 10),
42+
}
43+
44+
acctest.VcrTest(t, resource.TestCase{
45+
PreCheck: func() { acctest.AccTestPreCheck(t) },
46+
{{- if $.Res.VersionedProvider $e.MinVersion }}
47+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t),
48+
{{- else }}
49+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
50+
{{- end }}
51+
{{- if $e.ExternalProviders }}
52+
ExternalProviders: map[string]resource.ExternalProvider{
53+
{{- range $provider := $e.ExternalProviders }}
54+
"{{$provider}}": {},
55+
{{- end }}
56+
},
57+
{{- end }}
58+
{{- if not $.Res.ExcludeDelete }}
59+
CheckDestroy: testAccCheck{{ $.Res.ResourceName }}DestroyProducer(t),
60+
{{- end }}
61+
Steps: []resource.TestStep{
62+
{
63+
Config: testAcc{{ $e.TestSlug $.Res.ProductMetadata.Name $.Res.Name }}DataSource(context),
64+
Check: resource.ComposeTestCheckFunc(
65+
{{- if gt (len ($.Res.IgnoreReadProperties $e)) 0 }}
66+
acctest.CheckDataSourceStateMatchesResourceStateWithIgnores(
67+
"data.{{ $e.ResourceType $.Res.TerraformName }}.default",
68+
"{{ $e.ResourceType $.Res.TerraformName }}.{{ $e.PrimaryResourceId }}",
69+
map[string]struct{}{
70+
{{- range $prop := $.Res.IgnoreReadProperties $e }}
71+
"{{ $prop }}": {},
72+
{{- end }}
73+
},
74+
),
75+
{{- else }}
76+
acctest.CheckDataSourceStateMatchesResourceState("data.{{ $e.ResourceType $.Res.TerraformName }}.default", "{{ $e.ResourceType $.Res.TerraformName }}.{{ $e.PrimaryResourceId }}"),
77+
{{- end }}
78+
),
79+
},
80+
},
81+
})
82+
}
83+
84+
func testAcc{{ $e.TestSlug $.Res.ProductMetadata.Name $.Res.Name }}DataSource(context map[string]interface{}) string {
85+
return acctest.Nprintf(`
86+
{{ $e.TestHCLText }}
87+
88+
data "{{ $.Res.TerraformName }}" "default" {
89+
{{- range $fieldName := $.Res.DatasourceRequiredFields }}
90+
{{ $fieldName }} = {{ $e.ResourceType $.Res.TerraformName }}.{{ $e.PrimaryResourceId }}.{{ $fieldName }}
91+
{{- end }}
92+
}`,
93+
context,
94+
)
95+
}
96+
{{ end }}

mmv1/third_party/terraform/services/iap/data_source_iap_client_test.go

Lines changed: 0 additions & 70 deletions
This file was deleted.

0 commit comments

Comments
 (0)