Skip to content

Commit 0f32f5d

Browse files
committed
Add subcategory support to the generate command
This patch adds a --subcategory flag that let users give a mapping that will use to set the `subcategory` field in the documentation: tfplugindocs generate --subcategory consul_acl=ACL --subcategory consul_admin="Admin Partition" The format for the flag is `prefix="Sub Category"` so all resources and datasources starting with `consul_acl` like `consul_acl_policy`, `consul_acl_token`, etc. will have the `subcategory: "ACL"` in the generated documentation. This is not very elegant but should work in most cases as needed. Closes hashicorp#156
1 parent edb4eab commit 0f32f5d

File tree

5 files changed

+79
-18
lines changed

5 files changed

+79
-18
lines changed

README.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Available commands are:
2929
the generate command is run by default
3030
generate generates a plugin website from code, templates, and examples for the current directory
3131
validate validates a plugin website for the current directory
32-
32+
3333
```
3434

3535
`generate` command:
@@ -39,14 +39,15 @@ $ tfplugindocs generate --help
3939

4040
Usage: tfplugindocs generate [<args>]
4141

42-
--examples-dir <ARG> examples directory (default: "examples")
43-
--ignore-deprecated <ARG> don't generate documentation for deprecated resources and data-sources (default: "false")
44-
--legacy-sidebar <ARG> generate the legacy .erb sidebar file (default: "false")
42+
--examples-dir <ARG> examples directory (default: "examples")
43+
--ignore-deprecated <ARG> don't generate documentation for deprecated resources and data-sources (default: "false")
44+
--legacy-sidebar <ARG> generate the legacy .erb sidebar file (default: "false")
4545
--provider-name <ARG> provider name, as used in Terraform configurations
4646
--rendered-provider-name <ARG> provider name, as generated in documentation (ex. page titles, ...)
47-
--rendered-website-dir <ARG> output directory (default: "docs")
47+
--rendered-website-dir <ARG> output directory (default: "docs")
48+
--subcategory <ARG> an optional subcategory mapping to group resources, can be specified multiple time e.g. --subcategory consul_acl=ACL --subcategory consul_admin="Admin Partition"
4849
--tf-version <ARG> terraform binary version to download
49-
--website-source-dir <ARG> templates directory (default: "templates")
50+
--website-source-dir <ARG> templates directory (default: "templates")
5051
--website-temp-dir <ARG> temporary directory (used during generation)
5152
```
5253
@@ -150,6 +151,7 @@ using the following data fields and functions:
150151
|------------------------:|:------:|-------------------------------------------------------------------------------------------|
151152
| `.Name` | string | Name of the resource/data-source (ex. `tls_certificate`) |
152153
| `.Type` | string | Either `Resource` or `Data Source` |
154+
| `.SubCategory` | string | The subcategory for this resource or an empty string if unset |
153155
| `.Description` | string | Resource / Data Source description |
154156
| `.HasExample` | bool | Is there an example file? |
155157
| `.ExampleFile` | string | Path to the file with the terraform configuration example |

internal/cmd/generate.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ type generateCmd struct {
2222
flagWebsiteTmpDir string
2323
flagWebsiteSourceDir string
2424
tfVersion string
25+
flagSubcategory provider.SubCategories
2526
}
2627

2728
func (cmd *generateCmd) Synopsis() string {
@@ -42,7 +43,7 @@ func (cmd *generateCmd) Help() string {
4243
}
4344
})
4445

45-
strBuilder.WriteString(fmt.Sprintf("\nUsage: tfplugindocs generate [<args>]\n\n"))
46+
strBuilder.WriteString("\nUsage: tfplugindocs generate [<args>]\n\n")
4647
cmd.Flags().VisitAll(func(f *flag.Flag) {
4748
if f.DefValue != "" {
4849
strBuilder.WriteString(fmt.Sprintf(" --%s <ARG> %s%s%s (default: %q)\n",
@@ -67,6 +68,8 @@ func (cmd *generateCmd) Help() string {
6768
}
6869

6970
func (cmd *generateCmd) Flags() *flag.FlagSet {
71+
cmd.flagSubcategory = provider.SubCategories{}
72+
7073
fs := flag.NewFlagSet("generate", flag.ExitOnError)
7174
fs.BoolVar(&cmd.flagLegacySidebar, "legacy-sidebar", false, "generate the legacy .erb sidebar file")
7275
fs.StringVar(&cmd.flagProviderName, "provider-name", "", "provider name, as used in Terraform configurations")
@@ -77,6 +80,7 @@ func (cmd *generateCmd) Flags() *flag.FlagSet {
7780
fs.StringVar(&cmd.flagWebsiteSourceDir, "website-source-dir", "templates", "templates directory")
7881
fs.StringVar(&cmd.tfVersion, "tf-version", "", "terraform binary version to download")
7982
fs.BoolVar(&cmd.flagIgnoreDeprecated, "ignore-deprecated", false, "don't generate documentation for deprecated resources and data-sources")
83+
fs.Var(&cmd.flagSubcategory, "subcategory", "an optional subcategory mapping to group resources, can be specified multiple time e.g. --subcategory consul_acl=ACL --subcategory consul_admin=\"Admin Partition\"")
8084
return fs
8185
}
8286

@@ -103,6 +107,7 @@ func (cmd *generateCmd) runInternal() error {
103107
cmd.flagWebsiteSourceDir,
104108
cmd.tfVersion,
105109
cmd.flagIgnoreDeprecated,
110+
cmd.flagSubcategory,
106111
)
107112
if err != nil {
108113
return fmt.Errorf("unable to generate website: %w", err)

internal/cmd/validate.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func (cmd *validateCmd) Help() string {
3030
}
3131
})
3232

33-
strBuilder.WriteString(fmt.Sprintf("\nUsage: tfplugindocs validate [<args>]\n\n"))
33+
strBuilder.WriteString("\nUsage: tfplugindocs validate [<args>]\n\n")
3434
cmd.Flags().VisitAll(func(f *flag.Flag) {
3535
if f.DefValue != "" {
3636
strBuilder.WriteString(fmt.Sprintf(" --%s <ARG> %s%s%s (default: %q)\n",

internal/provider/generate.go

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,51 @@ type generator struct {
7575
websiteTmpDir string
7676
websiteSourceDir string
7777

78+
subcategories SubCategories
79+
7880
ui cli.Ui
7981
}
8082

83+
type SubCategories map[string]string
84+
85+
func (s *SubCategories) String() string {
86+
if s == nil {
87+
return ""
88+
}
89+
90+
var subcategories []string
91+
for k, v := range *s {
92+
subcategories = append(subcategories, fmt.Sprintf("%s=%q", k, v))
93+
}
94+
95+
return strings.Join(subcategories, ", ")
96+
}
97+
98+
func (s *SubCategories) Set(v string) error {
99+
parts := strings.SplitN(v, "=", 2)
100+
if len(parts) != 2 {
101+
return fmt.Errorf("wrong format for %q, expected prefix=\"SubCategory Name\"", v)
102+
}
103+
104+
prefix := parts[0]
105+
if sc, found := (*s)[prefix]; found {
106+
return fmt.Errorf("%s is already registered with subcategory %q", prefix, sc)
107+
}
108+
109+
(*s)[prefix] = parts[1]
110+
return nil
111+
}
112+
113+
func (s *SubCategories) Get(name string) string {
114+
for k, v := range *s {
115+
if strings.HasPrefix(name, k) {
116+
return v
117+
}
118+
}
119+
120+
return ""
121+
}
122+
81123
func (g *generator) infof(format string, a ...interface{}) {
82124
g.ui.Info(fmt.Sprintf(format, a...))
83125
}
@@ -86,7 +128,7 @@ func (g *generator) warnf(format string, a ...interface{}) {
86128
g.ui.Warn(fmt.Sprintf(format, a...))
87129
}
88130

89-
func Generate(ui cli.Ui, legacySidebar bool, providerName, renderedProviderName, renderedWebsiteDir, examplesDir, websiteTmpDir, websiteSourceDir, tfVersion string, ignoreDeprecated bool) error {
131+
func Generate(ui cli.Ui, legacySidebar bool, providerName, renderedProviderName, renderedWebsiteDir, examplesDir, websiteTmpDir, websiteSourceDir, tfVersion string, ignoreDeprecated bool, subcategories SubCategories) error {
90132
g := &generator{
91133
ignoreDeprecated: ignoreDeprecated,
92134
legacySidebar: legacySidebar,
@@ -99,6 +141,8 @@ func Generate(ui cli.Ui, legacySidebar bool, providerName, renderedProviderName,
99141
websiteTmpDir: websiteTmpDir,
100142
websiteSourceDir: websiteSourceDir,
101143

144+
subcategories: subcategories,
145+
102146
ui: ui,
103147
}
104148

@@ -192,7 +236,7 @@ func (g *generator) Generate(ctx context.Context) error {
192236
return nil
193237
}
194238

195-
func (g *generator) renderMissingResourceDoc(providerName, name, typeName string, schema *tfjson.Schema, websiteFileTemplate resourceFileTemplate, fallbackWebsiteFileTemplate resourceFileTemplate, websiteStaticCandidateTemplates []resourceFileTemplate, examplesFileTemplate resourceFileTemplate, examplesImportTemplate *resourceFileTemplate) error {
239+
func (g *generator) renderMissingResourceDoc(providerName, name, typeName, subCategory string, schema *tfjson.Schema, websiteFileTemplate resourceFileTemplate, fallbackWebsiteFileTemplate resourceFileTemplate, websiteStaticCandidateTemplates []resourceFileTemplate, examplesFileTemplate resourceFileTemplate, examplesImportTemplate *resourceFileTemplate) error {
196240
tmplPath, err := websiteFileTemplate.Render(name, providerName)
197241
if err != nil {
198242
return fmt.Errorf("unable to render path for resource %q: %w", name, err)
@@ -257,7 +301,7 @@ func (g *generator) renderMissingResourceDoc(providerName, name, typeName string
257301
}
258302

259303
g.infof("generating template for %q", name)
260-
md, err := targetResourceTemplate.Render(name, providerName, g.renderedProviderName, typeName, examplePath, importPath, schema)
304+
md, err := targetResourceTemplate.Render(name, providerName, g.renderedProviderName, typeName, subCategory, examplePath, importPath, schema)
261305
if err != nil {
262306
return fmt.Errorf("unable to render template for %q: %w", name, err)
263307
}
@@ -325,7 +369,10 @@ func (g *generator) renderMissingDocs(providerName string, providerSchema *tfjso
325369
continue
326370
}
327371

328-
err := g.renderMissingResourceDoc(providerName, name, "Resource", schema,
372+
subCategory := g.subcategories.Get(name)
373+
374+
err := g.renderMissingResourceDoc(providerName, name, "Resource", subCategory,
375+
schema,
329376
websiteResourceFileTemplate,
330377
websiteResourceFallbackFileTemplate,
331378
websiteResourceFileStatic,
@@ -342,7 +389,10 @@ func (g *generator) renderMissingDocs(providerName string, providerSchema *tfjso
342389
continue
343390
}
344391

345-
err := g.renderMissingResourceDoc(providerName, name, "Data Source", schema,
392+
subCategory := g.subcategories.Get(name)
393+
394+
err := g.renderMissingResourceDoc(providerName, name, "Data Source", subCategory,
395+
schema,
346396
websiteDataSourceFileTemplate,
347397
websiteDataSourceFallbackFileTemplate,
348398
websiteDataSourceFileStatic,
@@ -425,10 +475,11 @@ func (g *generator) renderStaticWebsite(providerName string, providerSchema *tfj
425475
switch relDir {
426476
case "data-sources/":
427477
resSchema, resName := resourceSchema(providerSchema.DataSourceSchemas, shortName, relFile)
478+
subCategory := g.subcategories.Get(resName)
428479
exampleFilePath := filepath.Join(g.examplesDir, "data-sources", resName, "data-source.tf")
429480
if resSchema != nil {
430481
tmpl := resourceTemplate(tmplData)
431-
render, err := tmpl.Render(resName, providerName, g.renderedProviderName, "Data Source", exampleFilePath, "", resSchema)
482+
render, err := tmpl.Render(resName, providerName, g.renderedProviderName, "Data Source", subCategory, exampleFilePath, "", resSchema)
432483
if err != nil {
433484
return fmt.Errorf("unable to render data source template %q: %w", rel, err)
434485
}
@@ -441,12 +492,13 @@ func (g *generator) renderStaticWebsite(providerName string, providerSchema *tfj
441492
g.warnf("data source entitled %q, or %q does not exist", shortName, resName)
442493
case "resources/":
443494
resSchema, resName := resourceSchema(providerSchema.ResourceSchemas, shortName, relFile)
495+
subCategory := g.subcategories.Get(resName)
444496
exampleFilePath := filepath.Join(g.examplesDir, "resources", resName, "resource.tf")
445497
importFilePath := filepath.Join(g.examplesDir, "resources", resName, "import.sh")
446498

447499
if resSchema != nil {
448500
tmpl := resourceTemplate(tmplData)
449-
render, err := tmpl.Render(resName, providerName, g.renderedProviderName, "Resource", exampleFilePath, importFilePath, resSchema)
501+
render, err := tmpl.Render(resName, providerName, g.renderedProviderName, "Resource", subCategory, exampleFilePath, importFilePath, resSchema)
450502
if err != nil {
451503
return fmt.Errorf("unable to render resource template %q: %w", rel, err)
452504
}

internal/provider/template.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ func (t providerTemplate) Render(providerName, renderedProviderName, exampleFile
165165
})
166166
}
167167

168-
func (t resourceTemplate) Render(name, providerName, renderedProviderName, typeName, exampleFile, importFile string, schema *tfjson.Schema) (string, error) {
168+
func (t resourceTemplate) Render(name, providerName, renderedProviderName, typeName, subCategory, exampleFile, importFile string, schema *tfjson.Schema) (string, error) {
169169
schemaBuffer := bytes.NewBuffer(nil)
170170
err := schemamd.Render(schema, schemaBuffer)
171171
if err != nil {
@@ -181,6 +181,7 @@ func (t resourceTemplate) Render(name, providerName, renderedProviderName, typeN
181181
Type string
182182
Name string
183183
Description string
184+
SubCategory string
184185

185186
HasExample bool
186187
ExampleFile string
@@ -198,6 +199,7 @@ func (t resourceTemplate) Render(name, providerName, renderedProviderName, typeN
198199
Type: typeName,
199200
Name: name,
200201
Description: schema.Block.Description,
202+
SubCategory: subCategory,
201203

202204
HasExample: exampleFile != "" && fileExists(exampleFile),
203205
ExampleFile: exampleFile,
@@ -217,7 +219,7 @@ func (t resourceTemplate) Render(name, providerName, renderedProviderName, typeN
217219
const defaultResourceTemplate resourceTemplate = `---
218220
` + frontmatterComment + `
219221
page_title: "{{.Name}} {{.Type}} - {{.ProviderName}}"
220-
subcategory: ""
222+
subcategory: "{{.SubCategory}}"
221223
description: |-
222224
{{ .Description | plainmarkdown | trimspace | prefixlines " " }}
223225
---
@@ -246,7 +248,7 @@ Import is supported using the following syntax:
246248
const defaultProviderTemplate providerTemplate = `---
247249
` + frontmatterComment + `
248250
page_title: "{{.ProviderShortName}} Provider"
249-
subcategory: ""
251+
subcategory: "{{.SubCategory}}"
250252
description: |-
251253
{{ .Description | plainmarkdown | trimspace | prefixlines " " }}
252254
---

0 commit comments

Comments
 (0)