Skip to content

Commit d4b2237

Browse files
authored
feat(tftemplate): generate helpers with resource (#1986)
1 parent 5100cfe commit d4b2237

File tree

5 files changed

+172
-35
lines changed

5 files changed

+172
-35
lines changed

cmd/tftemplate/helpers.go.tmpl

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{{- /*gotype: tftemplate/models.ResourceTemplate*/ -}}
2+
package scaleway
3+
4+
import (
5+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
6+
"github.com/scaleway/scaleway-sdk-go/scw"
7+
)
8+
9+
// {{.API}}APIWith{{.LocalityUpper}} returns a new {{.API}} API and the {{.Locality}} for a Create request
10+
func {{.API}}APIWith{{.LocalityUpper}}(d *schema.ResourceData, m interface{}) (*{{.API}}.API, scw.{{.LocalityUpper}}, error) {
11+
meta := m.(*Meta)
12+
{{.API}}API := {{.API}}.NewAPI(meta.scwClient)
13+
14+
{{.Locality}}, err := extract{{.LocalityUpper}}(d, meta)
15+
if err != nil {
16+
return nil, "", err
17+
}
18+
19+
return {{.API}}API, {{.Locality}}, nil
20+
}
21+
22+
// {{.API}}APIWith{{.LocalityAdjectiveUpper}}AndID returns a new {{.API }} API with {{.Locality}} and ID extracted from the state
23+
func {{.API}}APIWith{{.LocalityUpper}}AndID(m interface{}, {{.LocalityAdjective}}ID string) (*{{.API}}.API, scw.{{.LocalityUpper}}, string, error) {
24+
meta := m.(*Meta)
25+
{{.API}}API := {{.API}}.NewAPI(meta.scwClient)
26+
27+
{{.Locality}}, ID, err := parse{{.LocalityAdjectiveUpper}}ID({{.LocalityAdjective}}ID)
28+
if err != nil {
29+
return nil, "", "", err
30+
}
31+
32+
return {{.API}}API, {{.Locality}}, ID, nil
33+
}
34+

cmd/tftemplate/main.go

+63-33
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,23 @@ package main
33
import (
44
_ "embed"
55
"fmt"
6-
"html/template"
76
"log"
8-
"os"
7+
"text/template"
98
"tftemplate/models"
109

1110
"github.com/AlecAivazis/survey/v2"
1211
)
1312

14-
//go:embed resource.go.tmpl
15-
var resourceTemplateFile string
16-
17-
//go:embed resource_test.go.tmpl
18-
var resourceTestTemplateFile string
13+
var (
14+
//go:embed resource.go.tmpl
15+
resourceTemplateFile string
16+
//go:embed resource_test.go.tmpl
17+
resourceTestTemplateFile string
18+
//go:embed helpers.go.tmpl
19+
resourceHelpersTemplateFile string
20+
//go:embed waiters.go.tmpl
21+
resourceWaitersTemplateFile string
22+
)
1923

2024
var resourceQS = []*survey.Question{
2125
{
@@ -35,48 +39,74 @@ var resourceQS = []*survey.Question{
3539
Default: "zone",
3640
},
3741
},
42+
{
43+
Name: "helpers",
44+
Prompt: &survey.Confirm{
45+
Message: "Generate helpers ? Will override scaleway/helpers_{api}.go",
46+
Default: false,
47+
},
48+
},
49+
{
50+
Name: "waiters",
51+
Prompt: &survey.Confirm{
52+
Message: "Generate helpers ? Will be added to scaleway/helpers_{api}.go",
53+
Default: true,
54+
},
55+
},
3856
}
3957

4058
func main() {
4159
resourceInput := struct {
4260
API string
4361
Resource string
4462
Locality string
63+
Helpers bool
64+
Waiters bool
4565
}{}
4666
err := survey.Ask(resourceQS, &resourceInput)
4767
if err != nil {
4868
log.Fatalln(err)
4969
}
5070
resourceData := models.NewResourceTemplate(resourceInput.API, resourceInput.Resource, resourceInput.Locality)
5171

52-
resourceTemplate, err := template.New("resource").Parse(resourceTemplateFile)
53-
if err != nil {
54-
log.Fatalln(err)
55-
}
56-
resourceTestTemplate, err := template.New("resource").Parse(resourceTestTemplateFile)
57-
if err != nil {
58-
log.Fatalln(err)
59-
}
60-
resourceFile, err := os.Create(fmt.Sprintf("../../scaleway/resource_%s.go", resourceData.ResourceHCL))
61-
if err != nil {
62-
log.Fatalln(err)
63-
}
64-
defer resourceFile.Close()
65-
err = resourceTemplate.Execute(resourceFile, resourceData)
66-
if err != nil {
67-
log.Println(err)
68-
return
72+
templates := []*TerraformTemplate{
73+
{
74+
FileName: fmt.Sprintf("../../scaleway/resource_%s.go", resourceData.ResourceHCL),
75+
TemplateFile: resourceTemplateFile,
76+
},
77+
{
78+
FileName: fmt.Sprintf("../../scaleway/resource_%s_test.go", resourceData.ResourceHCL),
79+
TemplateFile: resourceTestTemplateFile,
80+
},
81+
{
82+
FileName: fmt.Sprintf("../../scaleway/helpers_%s.go", resourceData.API),
83+
TemplateFile: resourceHelpersTemplateFile,
84+
Skip: !resourceInput.Helpers,
85+
},
86+
{
87+
FileName: fmt.Sprintf("../../scaleway/helpers_%s.go", resourceData.API),
88+
TemplateFile: resourceWaitersTemplateFile,
89+
Skip: !resourceInput.Waiters,
90+
Append: true,
91+
},
6992
}
7093

71-
resourceTestFile, err := os.Create(fmt.Sprintf("../../scaleway/resource_%s_test.go", resourceData.ResourceHCL))
72-
if err != nil {
73-
log.Println(err)
74-
return
94+
for _, tmpl := range templates {
95+
if tmpl.Template == nil {
96+
tmpl.Template, err = template.New(tmpl.FileName).Parse(tmpl.TemplateFile)
97+
if err != nil {
98+
log.Fatalln("failed to template " + tmpl.FileName + ":" + err.Error())
99+
}
100+
}
75101
}
76-
defer resourceTestFile.Close()
77-
err = resourceTestTemplate.Execute(resourceTestFile, resourceData)
78-
if err != nil {
79-
log.Println(err)
80-
return
102+
103+
for _, tmpl := range templates {
104+
if tmpl.Skip {
105+
continue
106+
}
107+
err := executeTemplate(tmpl, resourceData)
108+
if err != nil {
109+
log.Println(err)
110+
}
81111
}
82112
}

cmd/tftemplate/models/resource.go

+15-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import (
66
)
77

88
type ResourceTemplate struct {
9-
LocalityAdjectiveUpper string // Regional
9+
LocalityAdjectiveUpper string // Regional/Zoned
10+
LocalityAdjective string // regional/zoned
1011
LocalityUpper string // Region
1112
Locality string // region
1213
Resource string // FunctionNamespace
@@ -75,12 +76,24 @@ func resourceWordsLower(resource string) []string {
7576
return words
7677
}
7778

79+
func adjectiveLocality(locality string) string {
80+
switch locality {
81+
case "zone":
82+
return "zoned"
83+
case "region":
84+
return "regional"
85+
}
86+
87+
return locality
88+
}
89+
7890
// api: function, container, instance
7991
// resource: FunctionNamespace, InstanceServer, ContainerDomain
8092
// locality: region, zone
8193
func NewResourceTemplate(api string, resource string, locality string) ResourceTemplate {
8294
return ResourceTemplate{
83-
LocalityAdjectiveUpper: strings.Title(locality) + "al",
95+
LocalityAdjectiveUpper: strings.Title(adjectiveLocality(locality)),
96+
LocalityAdjective: adjectiveLocality(locality),
8497
LocalityUpper: strings.Title(locality),
8598
Locality: locality,
8699
Resource: resource,

cmd/tftemplate/templates.go

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package main
2+
3+
import (
4+
"log"
5+
"os"
6+
"text/template"
7+
"tftemplate/models"
8+
)
9+
10+
type TerraformTemplate struct {
11+
// Target file for output
12+
FileName string
13+
// TemplateFile is a Go template as string
14+
TemplateFile string
15+
// Template is a Go template, will be created from TemplateFile if nil
16+
Template *template.Template
17+
// Skip template generation if true
18+
Skip bool
19+
// Append template output to target if true
20+
Append bool
21+
}
22+
23+
func executeTemplate(tmpl *TerraformTemplate, data models.ResourceTemplate) error {
24+
var outputFile *os.File
25+
var err error
26+
27+
if tmpl.Append {
28+
outputFile, err = os.OpenFile(tmpl.FileName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
29+
} else {
30+
outputFile, err = os.Create(tmpl.FileName)
31+
}
32+
if err != nil {
33+
log.Fatalln(err)
34+
}
35+
defer outputFile.Close()
36+
37+
err = tmpl.Template.Execute(outputFile, data)
38+
if err != nil {
39+
return err
40+
}
41+
42+
return nil
43+
}

cmd/tftemplate/waiters.go.tmpl

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{{- /*gotype: tftemplate/models.ResourceTemplate*/ -}}
2+
3+
func waitFor{{.Resource}}(ctx context.Context, {{.API}}API *{{.API}}.API, {{.Locality}} scw.{{.LocalityUpper}}, id string, timeout time.Duration) (*{{.API}}.{{.ResourceClean}}, error) {
4+
retryInterval := defaultFunctionRetryInterval
5+
if DefaultWaitRetryInterval != nil {
6+
retryInterval = *DefaultWaitRetryInterval
7+
}
8+
9+
{{.ResourceCleanLow}}, err := {{.API}}API.WaitFor{{.ResourceClean}}(&{{.API}}.WaitFor{{.ResourceClean}}Request{
10+
{{.LocalityUpper}}: {{.Locality}},
11+
{{.ResourceClean}}ID: id,
12+
RetryInterval: &retryInterval,
13+
Timeout: scw.TimeDurationPtr(timeout),
14+
}, scw.WithContext(ctx))
15+
16+
return {{.ResourceCleanLow}}, err
17+
}

0 commit comments

Comments
 (0)