From cbd432b6cbaeb8830d7a2f692b2082ed23cf3247 Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Fri, 10 Jun 2022 13:27:01 +0100 Subject: [PATCH] Allowing single word resources to use templates (#147) * Allowing single word resources to use templates * Updating CHANGELOG.md * Add unit test for resourceName * Returning error if resource not found * Adding field names to test structs --- CHANGELOG.md | 10 ++++- internal/provider/generate.go | 54 +++++++++++------------ internal/provider/template.go | 1 + internal/provider/util.go | 19 +++++++++ internal/provider/util_test.go | 78 ++++++++++++++++++++++++++++++++++ 5 files changed, 134 insertions(+), 28 deletions(-) create mode 100644 internal/provider/util_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f3acae8..98c9bb6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,18 @@ +# 0.9.1 (Unreleased) + +BUG FIXES: + +* cmd/tfplugindocs: Allow single word resources to use templates ([147](https://github.com/hashicorp/terraform-plugin-docs/pull/147)). + # 0.9.0 (June 1, 2022) NEW FEATURES: -* cmd/tflugindocs: Additional CLI arguments `provider-name`, `rendered-provider-name`, `rendered-website-dir`, `examples-dir`, `website-temp-dir`, and `website-source-dir`. These allow to further customise generated doc ([#95](https://github.com/hashicorp/terraform-plugin-docs/pull/95)). +* cmd/tfplugindocs: Additional CLI arguments `provider-name`, `rendered-provider-name`, `rendered-website-dir`, `examples-dir`, `website-temp-dir`, and `website-source-dir`. These allow to further customise generated doc ([#95](https://github.com/hashicorp/terraform-plugin-docs/pull/95)). ENHANCEMENTS: -* cmd/tflugindocs: Implemented usage output (i.e. `--help`) for `generate` and `validate` commands ([#95](https://github.com/hashicorp/terraform-plugin-docs/pull/95)). +* cmd/tfplugindocs: Implemented usage output (i.e. `--help`) for `generate` and `validate` commands ([#95](https://github.com/hashicorp/terraform-plugin-docs/pull/95)). # 0.8.1 (May 10, 2022) diff --git a/internal/provider/generate.go b/internal/provider/generate.go index c0841bfc..9b83dd24 100644 --- a/internal/provider/generate.go +++ b/internal/provider/generate.go @@ -414,35 +414,37 @@ func (g *generator) renderStaticWebsite(providerName string, providerSchema *tfj g.infof("rendering %q", rel) switch relDir { case "data-sources/": - resName := shortName + "_" + removeAllExt(relFile) - resSchema, ok := providerSchema.DataSourceSchemas[resName] - if ok { - tmpl := resourceTemplate(tmplData) - render, err := tmpl.Render(resName, providerName, "Data Source", "", "", resSchema) - if err != nil { - return fmt.Errorf("unable to render data source template %q: %w", rel, err) - } - _, err = out.WriteString(render) - if err != nil { - return fmt.Errorf("unable to write rendered string: %w", err) - } - return nil + resSchema, resName := resourceSchema(providerSchema.DataSourceSchemas, shortName, relFile) + if resSchema == nil { + return fmt.Errorf("unable to find resource for provider (%s) and template (%s)", shortName, relFile) + } + + tmpl := resourceTemplate(tmplData) + render, err := tmpl.Render(resName, providerName, "Data Source", "", "", resSchema) + if err != nil { + return fmt.Errorf("unable to render data source template %q: %w", rel, err) } + _, err = out.WriteString(render) + if err != nil { + return fmt.Errorf("unable to write rendered string: %w", err) + } + return nil case "resources/": - resName := shortName + "_" + removeAllExt(relFile) - resSchema, ok := providerSchema.ResourceSchemas[resName] - if ok { - tmpl := resourceTemplate(tmplData) - render, err := tmpl.Render(resName, providerName, "Resource", "", "", resSchema) - if err != nil { - return fmt.Errorf("unable to render resource template %q: %w", rel, err) - } - _, err = out.WriteString(render) - if err != nil { - return fmt.Errorf("unable to write regindered string: %w", err) - } - return nil + resSchema, resName := resourceSchema(providerSchema.ResourceSchemas, shortName, relFile) + if resSchema == nil { + return fmt.Errorf("unable to find resource for provider (%s) and template (%s)", shortName, relFile) + } + + tmpl := resourceTemplate(tmplData) + render, err := tmpl.Render(resName, providerName, "Resource", "", "", resSchema) + if err != nil { + return fmt.Errorf("unable to render resource template %q: %w", rel, err) } + _, err = out.WriteString(render) + if err != nil { + return fmt.Errorf("unable to write regindered string: %w", err) + } + return nil case "": // provider if relFile == "index.md.tmpl" { tmpl := providerTemplate(tmplData) diff --git a/internal/provider/template.go b/internal/provider/template.go index 2d02e69c..4612627b 100644 --- a/internal/provider/template.go +++ b/internal/provider/template.go @@ -8,6 +8,7 @@ import ( "text/template" tfjson "github.com/hashicorp/terraform-json" + "github.com/hashicorp/terraform-plugin-docs/internal/mdplain" "github.com/hashicorp/terraform-plugin-docs/internal/tmplfuncs" "github.com/hashicorp/terraform-plugin-docs/schemamd" diff --git a/internal/provider/util.go b/internal/provider/util.go index 052ddd84..6410bbdd 100644 --- a/internal/provider/util.go +++ b/internal/provider/util.go @@ -9,6 +9,8 @@ import ( "os/exec" "path/filepath" "strings" + + tfjson "github.com/hashicorp/terraform-json" ) func providerShortName(n string) string { @@ -52,6 +54,23 @@ func removeAllExt(file string) string { } } +// resourceSchema determines whether there is a schema in the supplied schemas map which +// has either the providerShortName or the providerShortName concatenated with the +// templateFileName (stripped of file extension. +func resourceSchema(schemas map[string]*tfjson.Schema, providerShortName, templateFileName string) (*tfjson.Schema, string) { + if schema, ok := schemas[providerShortName]; ok { + return schema, providerShortName + } + + resName := providerShortName + "_" + removeAllExt(templateFileName) + + if schema, ok := schemas[resName]; ok { + return schema, resName + } + + return nil, "" +} + func writeFile(path string, data string) error { dir, _ := filepath.Split(path) err := os.MkdirAll(dir, 0755) diff --git a/internal/provider/util_test.go b/internal/provider/util_test.go new file mode 100644 index 00000000..3e94549c --- /dev/null +++ b/internal/provider/util_test.go @@ -0,0 +1,78 @@ +package provider + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + tfjson "github.com/hashicorp/terraform-json" +) + +func Test_resourceSchema(t *testing.T) { + cases := map[string]struct { + schemas map[string]*tfjson.Schema + providerShortName string + templateFileName string + expectedSchema *tfjson.Schema + expectedResourceName string + }{ + "provider short name matches schema name": { + schemas: map[string]*tfjson.Schema{ + "http": {}, + }, + providerShortName: "http", + templateFileName: "http.md.tmpl", + expectedSchema: &tfjson.Schema{}, + expectedResourceName: "http", + }, + "provider short name does not match schema name": { + schemas: map[string]*tfjson.Schema{ + "http": {}, + }, + providerShortName: "tls", + templateFileName: "http.md.tmpl", + expectedSchema: nil, + expectedResourceName: "", + }, + "provider short name concatenated with template file name matches schema name": { + schemas: map[string]*tfjson.Schema{ + "tls_cert_request": {}, + }, + providerShortName: "tls", + templateFileName: "cert_request.md.tmpl", + expectedSchema: &tfjson.Schema{}, + expectedResourceName: "tls_cert_request", + }, + "provider short name concatenated with template file name does not match schema name": { + schemas: map[string]*tfjson.Schema{ + "tls_cert_request": {}, + }, + providerShortName: "tls", + templateFileName: "not_found.md.tmpl", + expectedSchema: nil, + expectedResourceName: "", + }, + "provider short name concatenated with same template file name matches schema name": { + schemas: map[string]*tfjson.Schema{ + "tls_tls": {}, + }, + providerShortName: "tls", + templateFileName: "tls.md.tmpl", + expectedSchema: &tfjson.Schema{}, + expectedResourceName: "tls_tls", + }, + } + + for name, c := range cases { + t.Run(name, func(t *testing.T) { + actualSchema, actualResourceName := resourceSchema(c.schemas, c.providerShortName, c.templateFileName) + + if !cmp.Equal(c.expectedSchema, actualSchema) { + t.Errorf("expected: %+v, got: %+v", c.expectedSchema, actualSchema) + } + + if !cmp.Equal(c.expectedResourceName, actualResourceName) { + t.Errorf("expected: %s, got: %s", c.expectedResourceName, actualResourceName) + } + }) + } +}