Skip to content

Commit 73b6882

Browse files
authored
Update Test Generation: resource test (#15556)
1 parent fd1258f commit 73b6882

File tree

9 files changed

+327
-14
lines changed

9 files changed

+327
-14
lines changed

mmv1/api/resource.go

Lines changed: 73 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,9 @@ type Resource struct {
220220
// corresponding OiCS walkthroughs.
221221
Examples []*resource.Examples
222222

223+
// Samples for generating tests and documentation
224+
Samples []*resource.Sample
225+
223226
// If true, generates product operation handling logic.
224227
AutogenAsync bool `yaml:"autogen_async,omitempty"`
225228

@@ -531,6 +534,10 @@ func (r *Resource) Validate() {
531534
example.Validate(r.Name)
532535
}
533536

537+
for _, sample := range r.Samples {
538+
sample.Validate(r.Name)
539+
}
540+
534541
if r.Async != nil {
535542
r.Async.Validate()
536543
}
@@ -1301,9 +1308,10 @@ func ImportIdFormats(importFormat, identity []string, baseUrl string) []string {
13011308
return uniq
13021309
}
13031310

1311+
// IgnoreReadPropertiesLegacy is the legacy version of IgnoreReadProperties for Examples
13041312
// IgnoreReadProperties returns a sorted slice of property names (snake_case) that should be ignored when reading.
13051313
// This is useful for downstream code that needs to iterate over these properties.
1306-
func (r Resource) IgnoreReadProperties(e *resource.Examples) []string {
1314+
func (r Resource) IgnoreReadPropertiesLegacy(e *resource.Examples) []string {
13071315
var props []string
13081316
for _, tp := range r.AllUserProperties() {
13091317
if tp.UrlParamOnly || tp.IsA("ResourceRef") {
@@ -1318,10 +1326,38 @@ func (r Resource) IgnoreReadProperties(e *resource.Examples) []string {
13181326
return props
13191327
}
13201328

1329+
// IgnoreReadPropertiesToStringLegacy is the legacy version of IgnoreReadPropertiesToString for Examples
1330+
// IgnoreReadPropertiesToString returns the ignore read properties as a Go-syntax string slice.
1331+
// This is a wrapper around IgnoreReadProperties for backwards compatibility.
1332+
func (r Resource) IgnoreReadPropertiesToStringLegacy(e *resource.Examples) string {
1333+
props := r.IgnoreReadPropertiesLegacy(e)
1334+
if len(props) > 0 {
1335+
return fmt.Sprintf("[]string{%s}", strings.Join(quoteStrings(props), ", "))
1336+
}
1337+
return ""
1338+
}
1339+
1340+
// IgnoreReadProperties returns a sorted slice of property names (snake_case) that should be ignored when reading.
1341+
// This is useful for downstream code that needs to iterate over these properties.
1342+
func (r Resource) IgnoreReadProperties(s *resource.Step) []string {
1343+
var props []string
1344+
for _, tp := range r.AllUserProperties() {
1345+
if tp.UrlParamOnly || tp.IsA("ResourceRef") {
1346+
props = append(props, google.Underscore(tp.Name))
1347+
}
1348+
}
1349+
props = append(props, s.IgnoreReadExtra...)
1350+
props = append(props, r.IgnoreReadLabelsFields(r.PropertiesWithExcluded())...)
1351+
props = append(props, ignoreReadFields(r.AllUserProperties())...)
1352+
1353+
slices.Sort(props)
1354+
return props
1355+
}
1356+
13211357
// IgnoreReadPropertiesToString returns the ignore read properties as a Go-syntax string slice.
13221358
// This is a wrapper around IgnoreReadProperties for backwards compatibility.
1323-
func (r Resource) IgnoreReadPropertiesToString(e *resource.Examples) string {
1324-
props := r.IgnoreReadProperties(e)
1359+
func (r Resource) IgnoreReadPropertiesToString(s *resource.Step) string {
1360+
props := r.IgnoreReadProperties(s)
13251361
if len(props) > 0 {
13261362
return fmt.Sprintf("[]string{%s}", strings.Join(quoteStrings(props), ", "))
13271363
}
@@ -1933,6 +1969,40 @@ func (r Resource) TestExamples() []*resource.Examples {
19331969
})
19341970
}
19351971

1972+
func (r Resource) TestSamples() []*resource.Sample {
1973+
return google.Reject(google.Reject(r.Samples, func(s *resource.Sample) bool {
1974+
return s.ExcludeTest
1975+
}), func(s *resource.Sample) bool {
1976+
return s.MinVersion != "" && slices.Index(product.ORDER, r.TargetVersionName) < slices.Index(product.ORDER, s.MinVersion)
1977+
})
1978+
}
1979+
1980+
func (r Resource) TestSampleSetUp() {
1981+
res := make(map[string]string)
1982+
for _, sample := range r.Samples {
1983+
sample.TargetVersionName = r.TargetVersionName
1984+
if sample.MinVersion != "" && slices.Index(product.ORDER, r.TargetVersionName) < slices.Index(product.ORDER, sample.MinVersion) {
1985+
continue
1986+
}
1987+
for _, step := range sample.Steps {
1988+
if step.MinVersion != "" && slices.Index(product.ORDER, r.TargetVersionName) < slices.Index(product.ORDER, step.MinVersion) {
1989+
continue
1990+
}
1991+
step.PrimaryResourceId = sample.PrimaryResourceId
1992+
packageName := filepath.Base(filepath.Dir(r.SourceYamlFile))
1993+
if step.ConfigPath == "" {
1994+
step.ConfigPath = fmt.Sprintf("templates/terraform/samples/services/%s/%s.tf.tmpl", packageName, step.Name)
1995+
}
1996+
step.SetHCLText()
1997+
configName := step.Name
1998+
if _, ok := res[step.Name]; !ok {
1999+
res[configName] = sample.Name
2000+
sample.NewConfigFuncs = append(sample.NewConfigFuncs, step)
2001+
}
2002+
}
2003+
}
2004+
}
2005+
19362006
func (r Resource) VersionedProvider(exampleVersion string) bool {
19372007
var vp string
19382008
if exampleVersion != "" {

mmv1/api/resource/sample.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,13 @@ type Sample struct {
7676
PrimaryResourceName string `yaml:"primary_resource_name,omitempty"`
7777

7878
// Steps
79-
Steps []Step
79+
Steps []*Step
8080

8181
// The version name provided by the user through CI
8282
TargetVersionName string `yaml:"-"`
8383

8484
// Step configs that first appears
85-
NewConfigFuncs []Step `yaml:"-"`
85+
NewConfigFuncs []*Step `yaml:"-"`
8686

8787
// The name of the location/region override for use in IAM tests. IAM
8888
// tests may need this if the location is not inherited on the resource
@@ -115,8 +115,8 @@ func (s *Sample) TestSampleSlug(productName, resourceName string) string {
115115
return ret
116116
}
117117

118-
func (s *Sample) TestSteps() []Step {
119-
return google.Reject(s.Steps, func(st Step) bool {
118+
func (s *Sample) TestSteps() []*Step {
119+
return google.Reject(s.Steps, func(st *Step) bool {
120120
return st.MinVersion != "" && slices.Index(product.ORDER, s.TargetVersionName) < slices.Index(product.ORDER, st.MinVersion)
121121
})
122122
}

mmv1/api/resource/step.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,6 @@ type Step struct {
111111
TestHCLText string `yaml:"-"`
112112
OicsHCLText string `yaml:"-"`
113113
PrimaryResourceId string `yaml:"-"`
114-
ProductName string `yaml:"-"`
115114
}
116115

117116
func (s *Step) UnmarshalYAML(unmarshal func(any) error) error {

mmv1/loader/loader.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,7 @@ func (l *Loader) loadResource(product *api.Product, baseResourcePath string, ove
307307
// SetDefault after AddExtraFields to ensure relevant metadata is available for the newly generated fields
308308
resource.SetDefault(product)
309309
resource.Validate()
310+
resource.TestSampleSetUp()
310311

311312
for _, e := range resource.Examples {
312313
e.LoadHCLText(l.BaseDirectory)

mmv1/provider/template_data.go

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ func (td *TemplateData) GenerateDocumentationFile(filePath string, resource api.
121121
td.GenerateFile(filePath, templatePath, resource, false, templates...)
122122
}
123123

124-
func (td *TemplateData) GenerateTestFile(filePath string, resource api.Resource) {
124+
func (td *TemplateData) GenerateTestFileLegacy(filePath string, resource api.Resource) {
125125
templatePath := "templates/terraform/examples/base_configs/test_file.go.tmpl"
126126
templates := []string{
127127
"templates/terraform/env_var_context.go.tmpl",
@@ -150,6 +150,35 @@ func (td *TemplateData) GenerateTestFile(filePath string, resource api.Resource)
150150
td.GenerateFile(filePath, templatePath, tmplInput, true, templates...)
151151
}
152152

153+
func (td *TemplateData) GenerateTestFile(filePath string, resource api.Resource) {
154+
templatePath := "templates/terraform/samples/base_configs/test_file.go.tmpl"
155+
templates := []string{
156+
"templates/terraform/env_var_context.go.tmpl",
157+
templatePath,
158+
}
159+
tmplInput := TestInput{
160+
Res: resource,
161+
ImportPath: resource.ImportPath,
162+
PROJECT_NAME: "my-project-name",
163+
CREDENTIALS: "my/credentials/filename.json",
164+
REGION: "us-west1",
165+
ORG_ID: "123456789",
166+
ORG_DOMAIN: "example.com",
167+
ORG_TARGET: "123456789",
168+
PROJECT_NUMBER: "1111111111111",
169+
BILLING_ACCT: "000000-0000000-0000000-000000",
170+
MASTER_BILLING_ACCT: "000000-0000000-0000000-000000",
171+
SERVICE_ACCT: "[email protected]",
172+
CUST_ID: "A01b123xz",
173+
IDENTITY_USER: "cloud_identity_user",
174+
PAP_DESCRIPTION: "description",
175+
CHRONICLE_ID: "00000000-0000-0000-0000-000000000000",
176+
VMWAREENGINE_PROJECT: "my-vmwareengine-project",
177+
}
178+
179+
td.GenerateFile(filePath, templatePath, tmplInput, true, templates...)
180+
}
181+
153182
func (td *TemplateData) GenerateDataSourceTestFile(filePath string, resource api.Resource) {
154183
templatePath := "templates/terraform/examples/base_configs/datasource_test_file.go.tmpl"
155184
templates := []string{

mmv1/provider/terraform.go

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ func (t *Terraform) GenerateResourceMetadata(object api.Resource, templateData T
158158
templateData.GenerateMetadataFile(targetFilePath, object)
159159
}
160160

161-
func (t *Terraform) GenerateResourceTests(object api.Resource, templateData TemplateData, outputFolder string) {
161+
func (t *Terraform) GenerateResourceTestsLegacy(object api.Resource, templateData TemplateData, outputFolder string) {
162162
eligibleExample := false
163163
for _, example := range object.Examples {
164164
if !example.ExcludeTest {
@@ -172,6 +172,36 @@ func (t *Terraform) GenerateResourceTests(object api.Resource, templateData Temp
172172
return
173173
}
174174

175+
productName := t.Product.ApiName
176+
targetFolder := path.Join(outputFolder, t.FolderName(), "services", productName)
177+
if err := os.MkdirAll(targetFolder, os.ModePerm); err != nil {
178+
log.Println(fmt.Errorf("error creating parent directory %v: %v", targetFolder, err))
179+
}
180+
targetFilePath := path.Join(targetFolder, fmt.Sprintf("resource_%s_generated_test.go", t.ResourceGoFilename(object)))
181+
templateData.GenerateTestFileLegacy(targetFilePath, object)
182+
}
183+
184+
func (t *Terraform) GenerateResourceTests(object api.Resource, templateData TemplateData, outputFolder string) {
185+
if object.Samples != nil && object.Examples != nil {
186+
log.Fatalf("Both Samples and Examples block exist in %v", object.Name)
187+
}
188+
if object.Examples != nil {
189+
t.GenerateResourceTestsLegacy(object, templateData, outputFolder)
190+
}
191+
192+
eligibleSample := false
193+
for _, sample := range object.Samples {
194+
if !sample.ExcludeTest {
195+
if object.ProductMetadata.VersionObjOrClosest(t.Version.Name).CompareTo(object.ProductMetadata.VersionObjOrClosest(sample.MinVersion)) >= 0 {
196+
eligibleSample = true
197+
break
198+
}
199+
}
200+
}
201+
if !eligibleSample {
202+
return
203+
}
204+
175205
productName := t.Product.ApiName
176206
targetFolder := path.Join(outputFolder, t.FolderName(), "services", productName)
177207
if err := os.MkdirAll(targetFolder, os.ModePerm); err != nil {

mmv1/templates/terraform/examples/base_configs/datasource_test_file.go.tmpl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,12 @@ func TestAccDataSource{{ $.Res.ResourceName }}_basic(t *testing.T) {
6868
{
6969
Config: testAcc{{ $e.TestSlug $.Res.ProductMetadata.Name $.Res.Name }}DataSource(context),
7070
Check: resource.ComposeTestCheckFunc(
71-
{{- if gt (len ($.Res.IgnoreReadProperties $e)) 0 }}
71+
{{- if gt (len ($.Res.IgnoreReadPropertiesLegacy $e)) 0 }}
7272
acctest.CheckDataSourceStateMatchesResourceStateWithIgnores(
7373
"data.{{ $e.ResourceType $.Res.TerraformName }}.default",
7474
"{{ $e.ResourceType $.Res.TerraformName }}.{{ $e.PrimaryResourceId }}",
7575
[]string{
76-
{{- range $prop := $.Res.IgnoreReadProperties $e }}
76+
{{- range $prop := $.Res.IgnoreReadPropertiesLegacy $e }}
7777
"{{ $prop }}",
7878
{{- end }}
7979
},

mmv1/templates/terraform/examples/base_configs/test_file.go.tmpl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ func TestAcc{{ $e.TestSlug $.Res.ProductMetadata.Name $.Res.Name }}(t *testing.T
106106
ResourceName: "{{ $e.ResourceType $.Res.TerraformName }}.{{ $e.PrimaryResourceId }}",
107107
ImportState: true,
108108
ImportStateVerify: true,
109-
{{- if $.Res.IgnoreReadPropertiesToString $e }}
110-
ImportStateVerifyIgnore: {{ $.Res.IgnoreReadPropertiesToString $e }},
109+
{{- if $.Res.IgnoreReadPropertiesToStringLegacy $e }}
110+
ImportStateVerifyIgnore: {{ $.Res.IgnoreReadPropertiesToStringLegacy $e }},
111111
{{- end }}
112112
},
113113
{{- end }}

0 commit comments

Comments
 (0)