diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 00000000..eb6a4406 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,19 @@ +run: + tests: False + timeout: 3m + +severity: + default-severity: error + rules: + - linters: + - errcheck + - gocritic + severity: warning + +linters: + enable: + - asciicheck + - exportloopref + - gci + - gofmt + - misspell diff --git a/cmd/tfplugindocs/main.go b/cmd/tfplugindocs/main.go index 1bf63bf1..13e1cd75 100644 --- a/cmd/tfplugindocs/main.go +++ b/cmd/tfplugindocs/main.go @@ -3,9 +3,8 @@ package main import ( "os" - "github.com/mattn/go-colorable" - "github.com/hashicorp/terraform-plugin-docs/internal/cmd" + "github.com/mattn/go-colorable" ) func main() { diff --git a/internal/cmd/generate.go b/internal/cmd/generate.go index 54e4d201..e41780b2 100644 --- a/internal/cmd/generate.go +++ b/internal/cmd/generate.go @@ -42,7 +42,7 @@ func (cmd *generateCmd) Help() string { } }) - strBuilder.WriteString(fmt.Sprintf("\nUsage: tfplugindocs generate []\n\n")) + strBuilder.WriteString("\nUsage: tfplugindocs generate []\n\n") cmd.Flags().VisitAll(func(f *flag.Flag) { if f.DefValue != "" { strBuilder.WriteString(fmt.Sprintf(" --%s %s%s%s (default: %q)\n", diff --git a/internal/cmd/run.go b/internal/cmd/run.go index 9438288e..e83842b5 100644 --- a/internal/cmd/run.go +++ b/internal/cmd/run.go @@ -23,7 +23,6 @@ func (cmd *commonCmd) run(r func() error) int { } func initCommands(ui cli.Ui) map[string]cli.CommandFactory { - generateFactory := func() (cli.Command, error) { return &generateCmd{ commonCmd: commonCmd{ @@ -55,7 +54,7 @@ func initCommands(ui cli.Ui) map[string]cli.CommandFactory { "": defaultFactory, "generate": generateFactory, "validate": validateFactory, - //"serve": serveFactory, + // "serve": serveFactory, } } @@ -82,7 +81,7 @@ func Run(name, version string, args []string, stdin io.Reader, stdout, stderr io commands := initCommands(ui) - cli := cli.CLI{ + cmd := cli.CLI{ Name: name, Args: args, Commands: commands, @@ -91,7 +90,7 @@ func Run(name, version string, args []string, stdin io.Reader, stdout, stderr io Version: version, } - exitCode, err := cli.Run() + exitCode, err := cmd.Run() if err != nil { return 1 } diff --git a/internal/cmd/validate.go b/internal/cmd/validate.go index 0f54c566..890ef8d1 100644 --- a/internal/cmd/validate.go +++ b/internal/cmd/validate.go @@ -30,7 +30,7 @@ func (cmd *validateCmd) Help() string { } }) - strBuilder.WriteString(fmt.Sprintf("\nUsage: tfplugindocs validate []\n\n")) + strBuilder.WriteString("\nUsage: tfplugindocs validate []\n\n") cmd.Flags().VisitAll(func(f *flag.Flag) { if f.DefValue != "" { strBuilder.WriteString(fmt.Sprintf(" --%s %s%s%s (default: %q)\n", diff --git a/internal/mdplain/renderer.go b/internal/mdplain/renderer.go index 6dd958e6..03589705 100644 --- a/internal/mdplain/renderer.go +++ b/internal/mdplain/renderer.go @@ -18,7 +18,7 @@ func (options *Text) GetFlags() int { func (options *Text) TitleBlock(out *bytes.Buffer, text []byte) { text = bytes.TrimPrefix(text, []byte("% ")) - text = bytes.Replace(text, []byte("\n% "), []byte("\n"), -1) + text = bytes.ReplaceAll(text, []byte("\n% "), []byte("\n")) out.Write(text) out.WriteString("\n") } @@ -29,7 +29,6 @@ func (options *Text) Header(out *bytes.Buffer, text func() bool, level int, id s if !text() { out.Truncate(marker) - return } } @@ -57,7 +56,7 @@ func (options *Text) BlockQuote(out *bytes.Buffer, text []byte) { out.Write(text) } -func (options *Text) Table(out *bytes.Buffer, header []byte, body []byte, columnData []int) { +func (options *Text) Table(out *bytes.Buffer, header, body []byte, columnData []int) { doubleSpace(out) out.Write(header) out.Write(body) @@ -93,7 +92,6 @@ func (options *Text) List(out *bytes.Buffer, text func() bool, flags int) { if !text() { out.Truncate(marker) - return } } @@ -107,7 +105,6 @@ func (options *Text) Paragraph(out *bytes.Buffer, text func() bool) { if !text() { out.Truncate(marker) - return } } @@ -130,26 +127,19 @@ func (options *Text) Emphasis(out *bytes.Buffer, text []byte) { out.Write(text) } -func (options *Text) Image(out *bytes.Buffer, link []byte, title []byte, alt []byte) { - return -} +func (options *Text) Image(out *bytes.Buffer, link, title, alt []byte) {} -func (options *Text) LineBreak(out *bytes.Buffer) { - return -} +func (options *Text) LineBreak(out *bytes.Buffer) {} -func (options *Text) Link(out *bytes.Buffer, link []byte, title []byte, content []byte) { +func (options *Text) Link(out *bytes.Buffer, link, title, content []byte) { out.Write(content) if !isRelativeLink(link) { out.WriteString(" ") out.Write(link) } - return } -func (options *Text) RawHtmlTag(out *bytes.Buffer, text []byte) { - return -} +func (options *Text) RawHtmlTag(out *bytes.Buffer, text []byte) {} func (options *Text) TripleEmphasis(out *bytes.Buffer, text []byte) { out.Write(text) @@ -159,9 +149,7 @@ func (options *Text) StrikeThrough(out *bytes.Buffer, text []byte) { out.Write(text) } -func (options *Text) FootnoteRef(out *bytes.Buffer, ref []byte, id int) { - return -} +func (options *Text) FootnoteRef(out *bytes.Buffer, ref []byte, id int) {} func (options *Text) Entity(out *bytes.Buffer, entity []byte) { out.Write(entity) @@ -171,25 +159,15 @@ func (options *Text) NormalText(out *bytes.Buffer, text []byte) { out.Write(text) } -func (options *Text) Smartypants(out *bytes.Buffer, text []byte) { - return -} +func (options *Text) Smartypants(out *bytes.Buffer, text []byte) {} -func (options *Text) DocumentHeader(out *bytes.Buffer) { - return -} +func (options *Text) DocumentHeader(out *bytes.Buffer) {} -func (options *Text) DocumentFooter(out *bytes.Buffer) { - return -} +func (options *Text) DocumentFooter(out *bytes.Buffer) {} -func (options *Text) TocHeader(text []byte, level int) { - return -} +func (options *Text) TocHeader(text []byte, level int) {} -func (options *Text) TocFinalize() { - return -} +func (options *Text) TocFinalize() {} func doubleSpace(out *bytes.Buffer) { if out.Len() > 0 { @@ -214,5 +192,5 @@ func isRelativeLink(link []byte) (yes bool) { if len(link) == 1 && link[0] == '/' { yes = true } - return + return yes } diff --git a/internal/provider/generate.go b/internal/provider/generate.go index ce5a4b13..8f085435 100644 --- a/internal/provider/generate.go +++ b/internal/provider/generate.go @@ -3,7 +3,6 @@ package provider import ( "context" "fmt" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -112,7 +111,7 @@ func (g *generator) Generate(ctx context.Context) error { wd, err := os.Getwd() if err != nil { - return err + return fmt.Errorf("unable to get working directory: %w", err) } providerName := g.providerName @@ -128,22 +127,20 @@ func (g *generator) Generate(ctx context.Context) error { switch { case g.websiteTmpDir == "": - g.websiteTmpDir, err = ioutil.TempDir("", "tfws") + g.websiteTmpDir, err = os.MkdirTemp("", "tfws") if err != nil { - return err + return fmt.Errorf("unable to create temporary directory: %w", err) } defer os.RemoveAll(g.websiteTmpDir) default: g.infof("cleaning tmp dir %q", g.websiteTmpDir) - err = os.RemoveAll(g.websiteTmpDir) - if err != nil { - return err + if err = os.RemoveAll(g.websiteTmpDir); err != nil { + return fmt.Errorf("unable to clean temporary directory: %w", err) } g.infof("creating tmp dir %q", g.websiteTmpDir) - err = os.MkdirAll(g.websiteTmpDir, 0755) - if err != nil { - return err + if err = os.MkdirAll(g.websiteTmpDir, 0o755); err != nil { + return fmt.Errorf("unable to create temporary directory: %w", err) } } @@ -161,26 +158,26 @@ func (g *generator) Generate(ctx context.Context) error { g.infof("copying any existing content to tmp dir") err = cp(g.websiteSourceDir, filepath.Join(g.websiteTmpDir, "templates")) if err != nil { - return err + return fmt.Errorf("unable to copy content to temporary directory: %w", err) } } g.infof("exporting schema from Terraform") providerSchema, err := g.terraformProviderSchema(ctx, providerName) if err != nil { - return err + return fmt.Errorf("unable to export schema: %w", err) } g.infof("rendering missing docs") err = g.renderMissingDocs(providerName, providerSchema) if err != nil { - return err + return fmt.Errorf("unable to render missing docs: %w", err) } g.infof("rendering static website") err = g.renderStaticWebsite(providerName, providerSchema) if err != nil { - return err + return fmt.Errorf("unable to render static website: %w", err) } // TODO: may not ever need this, unsure on when this will go live @@ -192,7 +189,14 @@ func (g *generator) Generate(ctx context.Context) error { return nil } -func (g *generator) renderMissingResourceDoc(providerName, name, typeName string, schema *tfjson.Schema, websiteFileTemplate resourceFileTemplate, fallbackWebsiteFileTemplate resourceFileTemplate, websiteStaticCandidateTemplates []resourceFileTemplate, examplesFileTemplate resourceFileTemplate, examplesImportTemplate *resourceFileTemplate) error { +func (g *generator) renderMissingResourceDoc( + providerName, name, typeName string, + schema *tfjson.Schema, + websiteFileTemplate, fallbackWebsiteFileTemplate resourceFileTemplate, + websiteStaticCandidateTemplates []resourceFileTemplate, + examplesFileTemplate resourceFileTemplate, + examplesImportTemplate *resourceFileTemplate, +) error { tmplPath, err := websiteFileTemplate.Render(name, providerName) if err != nil { return fmt.Errorf("unable to render path for resource %q: %w", name, err) @@ -249,7 +253,7 @@ func (g *generator) renderMissingResourceDoc(providerName, name, typeName string fallbackTmplPath = filepath.Join(g.websiteTmpDir, g.websiteSourceDir, fallbackTmplPath) if fileExists(fallbackTmplPath) { g.infof("resource %q fallback template exists", name) - tmplData, err := ioutil.ReadFile(fallbackTmplPath) + tmplData, err := os.ReadFile(fallbackTmplPath) if err != nil { return fmt.Errorf("unable to read file %q: %w", fallbackTmplPath, err) } @@ -370,7 +374,7 @@ func (g *generator) renderStaticWebsite(providerName string, providerSchema *tfj g.infof("cleaning rendered website dir") err := os.RemoveAll(g.renderedWebsiteDir) if err != nil { - return err + return fmt.Errorf("unable to clean rendered website dir: %w", err) } shortName := providerShortName(providerName) @@ -378,6 +382,10 @@ func (g *generator) renderStaticWebsite(providerName string, providerSchema *tfj g.infof("rendering templated website to static markdown") err = filepath.Walk(g.websiteTmpDir, func(path string, info os.FileInfo, err error) error { + if err != nil { + return fmt.Errorf("unable to walk dir %q: %w", g.websiteTmpDir, err) + } + if info.IsDir() { // skip directories return nil @@ -385,7 +393,7 @@ func (g *generator) renderStaticWebsite(providerName string, providerSchema *tfj rel, err := filepath.Rel(filepath.Join(g.websiteTmpDir, g.websiteSourceDir), path) if err != nil { - return err + return fmt.Errorf("unable to get relative path for %q: %w", path, err) } relDir, relFile := filepath.Split(rel) @@ -397,27 +405,30 @@ func (g *generator) renderStaticWebsite(providerName string, providerSchema *tfj } renderedPath := filepath.Join(g.renderedWebsiteDir, rel) - err = os.MkdirAll(filepath.Dir(renderedPath), 0755) + err = os.MkdirAll(filepath.Dir(renderedPath), 0o755) if err != nil { - return err + return fmt.Errorf("unable to create dir %q: %w", filepath.Dir(renderedPath), err) } ext := filepath.Ext(path) if ext != ".tmpl" { g.infof("copying non-template file: %q", rel) - return cp(path, renderedPath) + if err = cp(path, renderedPath); err != nil { + return fmt.Errorf("unable to copy %q to %q: %w", path, renderedPath, err) + } + return nil } renderedPath = strings.TrimSuffix(renderedPath, ext) - tmplData, err := ioutil.ReadFile(path) + tmplData, err := os.ReadFile(path) if err != nil { return fmt.Errorf("unable to read file %q: %w", rel, err) } out, err := os.Create(renderedPath) if err != nil { - return err + return fmt.Errorf("unable to create file %q: %w", renderedPath, err) } defer out.Close() @@ -481,7 +492,7 @@ func (g *generator) renderStaticWebsite(providerName string, providerSchema *tfj return nil }) if err != nil { - return err + return fmt.Errorf("unable to render website: %w", err) } return nil @@ -492,9 +503,9 @@ func (g *generator) terraformProviderSchema(ctx context.Context, providerName st shortName := providerShortName(providerName) - tmpDir, err := ioutil.TempDir("", "tfws") + tmpDir, err := os.MkdirTemp("", "tfws") if err != nil { - return nil, err + return nil, fmt.Errorf("unable to create temp dir: %w", err) } defer os.RemoveAll(tmpDir) @@ -506,15 +517,14 @@ func (g *generator) terraformProviderSchema(ctx context.Context, providerName st g.infof("compiling provider %q", shortName) providerPath := fmt.Sprintf("plugins/registry.terraform.io/hashicorp/%s/0.0.1/%s_%s", shortName, runtime.GOOS, runtime.GOARCH) outFile := filepath.Join(tmpDir, providerPath, fmt.Sprintf("terraform-provider-%s", shortName)) - switch runtime.GOOS { - case "windows": - outFile = outFile + ".exe" + if runtime.GOOS == "windows" { + outFile += ".exe" } buildCmd := exec.Command("go", "build", "-o", outFile) // TODO: constrain env here to make it a little safer? _, err = runCmd(buildCmd) if err != nil { - return nil, err + return nil, fmt.Errorf("unable to build provider %q: %w", shortName, err) } err = writeFile(filepath.Join(tmpDir, "provider.tf"), fmt.Sprintf(` @@ -522,7 +532,7 @@ provider %[1]q { } `, shortName)) if err != nil { - return nil, err + return nil, fmt.Errorf("unable to write provider.tf: %w", err) } i := install.NewInstaller() @@ -551,24 +561,28 @@ provider %[1]q { tfBin, err := i.Ensure(context.Background(), sources) if err != nil { - return nil, err + return nil, fmt.Errorf("unable to ensure Terraform CLI binary: %w", err) } tf, err := tfexec.NewTerraform(tmpDir, tfBin) if err != nil { - return nil, err + return nil, fmt.Errorf("unable to create Terraform CLI: %w", err) } + // Pass stderr through to the end user, as if there is an error, the output from + // terraform will help troubleshoot. + tf.SetStderr(os.Stderr) + g.infof("running terraform init") err = tf.Init(ctx, tfexec.Get(false), tfexec.PluginDir("./plugins")) if err != nil { - return nil, err + return nil, fmt.Errorf("unable to init Terraform: %w", err) } g.infof("getting provider schema") schemas, err := tf.ProvidersSchema(ctx) if err != nil { - return nil, err + return nil, fmt.Errorf("unable to get provider schema: %w", err) } if ps, ok := schemas.Schemas[shortName]; ok { diff --git a/internal/provider/template.go b/internal/provider/template.go index dcc1e541..665023fa 100644 --- a/internal/provider/template.go +++ b/internal/provider/template.go @@ -7,14 +7,12 @@ import ( "strings" "text/template" - "golang.org/x/text/cases" - "golang.org/x/text/language" - 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" + "golang.org/x/text/cases" + "golang.org/x/text/language" ) const ( @@ -62,10 +60,10 @@ func terraformCodeFile(file string) (string, error) { return tmplfuncs.CodeFile("terraform", file) } -func renderTemplate(name string, text string, out io.Writer, data interface{}) error { +func renderTemplate(name, text string, out io.Writer, data interface{}) error { tmpl, err := newTemplate(name, text) if err != nil { - return err + return fmt.Errorf("unable to parse template %q: %w", text, err) } err = tmpl.Execute(out, data) @@ -81,7 +79,7 @@ func renderStringTemplate(name, text string, data interface{}) (string, error) { err := renderTemplate(name, text, &buf, data) if err != nil { - return "", err + return "", fmt.Errorf("unable to render template: %w", err) } return buf.String(), nil diff --git a/internal/provider/util.go b/internal/provider/util.go index 1de2ed46..3c361bd2 100644 --- a/internal/provider/util.go +++ b/internal/provider/util.go @@ -3,7 +3,6 @@ package provider import ( "fmt" "io" - "io/ioutil" "log" "os" "os/exec" @@ -71,14 +70,14 @@ func resourceSchema(schemas map[string]*tfjson.Schema, providerShortName, templa return nil, resName } -func writeFile(path string, data string) error { +func writeFile(path, data string) error { dir, _ := filepath.Split(path) - err := os.MkdirAll(dir, 0755) + err := os.MkdirAll(dir, 0o755) if err != nil { return fmt.Errorf("unable to make dir %q: %w", dir, err) } - err = ioutil.WriteFile(path, []byte(data), 0644) + err = os.WriteFile(path, []byte(data), 0o644) if err != nil { return fmt.Errorf("unable to write file %q: %w", path, err) } @@ -90,7 +89,7 @@ func runCmd(cmd *exec.Cmd) ([]byte, error) { output, err := cmd.CombinedOutput() if err != nil { log.Printf("error executing %q, %v", cmd.Path, cmd.Args) - log.Printf(string(output)) + log.Println(string(output)) return nil, fmt.Errorf("error executing %q: %w", cmd.Path, err) } return output, nil @@ -99,12 +98,12 @@ func runCmd(cmd *exec.Cmd) ([]byte, error) { func cp(srcDir, dstDir string) error { err := filepath.Walk(srcDir, func(srcPath string, f os.FileInfo, err error) error { if err != nil { - return err + return fmt.Errorf("unable to walk %q: %w", srcPath, err) } relPath, err := filepath.Rel(srcDir, srcPath) if err != nil { - return err + return fmt.Errorf("unable to get relative path for %q: %w", srcPath, err) } dstPath := filepath.Join(dstDir, relPath) @@ -112,11 +111,11 @@ func cp(srcDir, dstDir string) error { switch mode := f.Mode(); { case mode.IsDir(): if err := os.Mkdir(dstPath, f.Mode()); err != nil && !os.IsExist(err) { - return err + return fmt.Errorf("unable to create dir %q: %w", dstPath, err) } case mode.IsRegular(): if err := copyFile(srcPath, dstPath, mode); err != nil { - return err + return fmt.Errorf("unable to copy file %q to %q: %w", srcPath, dstPath, err) } default: return fmt.Errorf("unknown file type (%d / %s) for %s", f.Mode(), f.Mode().String(), srcPath) diff --git a/internal/provider/validate.go b/internal/provider/validate.go index 5bc53656..c4620a65 100644 --- a/internal/provider/validate.go +++ b/internal/provider/validate.go @@ -25,13 +25,13 @@ func Validate(ui cli.Ui) error { ui.Info("detected templates directory, running checks...") err := validateTemplates(ui, "templates") if err != nil { - return err + return fmt.Errorf("invalid templates directory: %w", err) } if dirExists("examples") { ui.Info("detected examples directory for templates, running checks...") err = validateExamples(ui, "examples") if err != nil { - return err + return fmt.Errorf("invalid examples directory: %w", err) } } return err @@ -73,7 +73,7 @@ func validateTemplates(ui cli.Ui, dir string) error { for _, c := range checks { checkIssues, err := c(dir) if err != nil { - return err + return fmt.Errorf("invalid templates directory: %w", err) } issues = append(issues, checkIssues...) } @@ -109,7 +109,7 @@ func validateStaticDocs(ui cli.Ui, dir string) error { for _, c := range checks { checkIssues, err := c(dir) if err != nil { - return err + return fmt.Errorf("invalid static docs directory: %w", err) } issues = append(issues, checkIssues...) } @@ -138,7 +138,7 @@ func checkBlockedExtensions(exts ...string) check { issues := []issue{} err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { if err != nil { - return err + return fmt.Errorf("error checking for blocked extensions: %w", err) } if info.IsDir() { return nil @@ -156,7 +156,7 @@ func checkBlockedExtensions(exts ...string) check { return nil }) if err != nil { - return nil, err + return nil, fmt.Errorf("error checking for blocked extensions: %w", err) } return issues, nil } @@ -167,7 +167,7 @@ func checkAllowedExtensions(exts ...string) check { issues := []issue{} err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { if err != nil { - return err + return fmt.Errorf("error checking for allowed extensions: %w", err) } if info.IsDir() { return nil @@ -189,7 +189,7 @@ func checkAllowedExtensions(exts ...string) check { return nil }) if err != nil { - return nil, err + return nil, fmt.Errorf("error checking for allowed extensions: %w", err) } return issues, nil } @@ -210,7 +210,7 @@ func checkAllowedDirs(dirs ...string) check { } infos, err := f.Readdir(-1) if err != nil { - return nil, err + return nil, fmt.Errorf("error reading directory: %w", err) } for _, fi := range infos { @@ -241,11 +241,11 @@ func checkAllowedFiles(dirs ...string) check { f, err := os.Open(dir) if err != nil { - return nil, err + return nil, fmt.Errorf("error opening directory: %w", err) } infos, err := f.Readdir(-1) if err != nil { - return nil, err + return nil, fmt.Errorf("error reading directory: %w", err) } for _, fi := range infos { diff --git a/internal/tmplfuncs/tmplfuncs.go b/internal/tmplfuncs/tmplfuncs.go index 67ffa8f3..0d17640b 100644 --- a/internal/tmplfuncs/tmplfuncs.go +++ b/internal/tmplfuncs/tmplfuncs.go @@ -2,7 +2,6 @@ package tmplfuncs import ( "fmt" - "io/ioutil" "os" "path/filepath" "strings" @@ -17,11 +16,11 @@ func CodeFile(format, file string) (string, error) { // may be undesirable, probably need to think about it wd, err := os.Getwd() if err != nil { - return "", err + return "", fmt.Errorf("error getting working dir: %w", err) } fullPath := filepath.Join(wd, file) - content, err := ioutil.ReadFile(fullPath) + content, err := os.ReadFile(fullPath) if err != nil { return "", fmt.Errorf("unable to read content from %q: %w", file, err) } diff --git a/schemamd/render.go b/schemamd/render.go index df46a76d..170b5672 100644 --- a/schemamd/render.go +++ b/schemamd/render.go @@ -12,11 +12,12 @@ import ( // Render writes a Markdown formatted Schema definition to the specified writer. // A Schema contains a Version and the root Block, for example: -// "aws_accessanalyzer_analyzer": { -// "block": { -// }, -// "version": 0 -// }, +// +// "aws_accessanalyzer_analyzer": { +// "block": { +// }, +// "version": 0 +// }, func Render(schema *tfjson.Schema, w io.Writer) error { _, err := io.WriteString(w, "## Schema\n\n") if err != nil { @@ -178,26 +179,27 @@ func writeRootBlock(w io.Writer, block *tfjson.SchemaBlock) error { // * Description(Kind) // * Deprecated flag // For example: -// "block": { -// "attributes": { -// "certificate_arn": { -// "description_kind": "plain", -// "required": true, -// "type": "string" -// } -// }, -// "block_types": { -// "timeouts": { -// "block": { -// "attributes": { -// }, -// "description_kind": "plain" -// }, -// "nesting_mode": "single" -// } -// }, -// "description_kind": "plain" -// }, +// +// "block": { +// "attributes": { +// "certificate_arn": { +// "description_kind": "plain", +// "required": true, +// "type": "string" +// } +// }, +// "block_types": { +// "timeouts": { +// "block": { +// "attributes": { +// }, +// "description_kind": "plain" +// }, +// "nesting_mode": "single" +// } +// }, +// "description_kind": "plain" +// }, func writeBlockChildren(w io.Writer, parents []string, block *tfjson.SchemaBlock, root bool) error { names := []string{} for n := range block.Attributes { @@ -226,7 +228,7 @@ nameLoop: // // If a `.Description` is provided instead, the behaviour will be the // same as for every other attribute. - if strings.ToLower(n) == "id" && childAtt.Description == "" { + if strings.EqualFold(n, "id") && childAtt.Description == "" { if strings.Contains(gf.topLevelTitle, "Read-Only") { childAtt.Description = "The ID of this resource." groups[i] = append(groups[i], n) diff --git a/schemamd/write_block_type_description.go b/schemamd/write_block_type_description.go index 14a18153..e1bcf8fd 100644 --- a/schemamd/write_block_type_description.go +++ b/schemamd/write_block_type_description.go @@ -56,17 +56,15 @@ func WriteBlockTypeDescription(w io.Writer, block *tfjson.SchemaBlockType) error default: return fmt.Errorf("block does not match any filter states") } - } else { - if block.MinItems > 0 { - _, err = io.WriteString(w, fmt.Sprintf(", Min: %d", block.MinItems)) - if err != nil { - return err - } + } else if block.MinItems > 0 { + _, err = fmt.Fprintf(w, ", Min: %d", block.MinItems) + if err != nil { + return err } } if block.MaxItems > 0 { - _, err = io.WriteString(w, fmt.Sprintf(", Max: %d", block.MaxItems)) + _, err = fmt.Fprintf(w, ", Max: %d", block.MaxItems) if err != nil { return err } diff --git a/schemamd/write_nested_attribute_type_description.go b/schemamd/write_nested_attribute_type_description.go index f9e90a57..19024bd5 100644 --- a/schemamd/write_nested_attribute_type_description.go +++ b/schemamd/write_nested_attribute_type_description.go @@ -66,7 +66,7 @@ func WriteNestedAttributeTypeDescription(w io.Writer, att *tfjson.SchemaAttribut } } else { if nestedAttributeType.MinItems > 0 { - _, err = io.WriteString(w, fmt.Sprintf(", Min: %d", nestedAttributeType.MinItems)) + _, err = fmt.Fprintf(w, ", Min: %d", nestedAttributeType.MinItems) if err != nil { return err } @@ -74,7 +74,7 @@ func WriteNestedAttributeTypeDescription(w io.Writer, att *tfjson.SchemaAttribut } if nestedAttributeType.MaxItems > 0 { - _, err = io.WriteString(w, fmt.Sprintf(", Max: %d", nestedAttributeType.MaxItems)) + _, err = fmt.Fprintf(w, ", Max: %d", nestedAttributeType.MaxItems) if err != nil { return err }