Coder Social home page Coder Social logo

hashicorp / terraform-plugin-docs Goto Github PK

View Code? Open in Web Editor NEW
211.0 17.0 67.0 667 KB

Generate and validate Terraform plugin/provider documentation.

License: Mozilla Public License 2.0

Go 99.49% Makefile 0.15% HCL 0.36%
terraform terraform-providers

terraform-plugin-docs's Introduction

terraform-plugin-docs

This repository contains tools and packages for creating Terraform plugin docs (currently only provider plugins). The primary way users will interact with this is the tfplugindocs CLI tool to generate and validate plugin documentation.

tfplugindocs

The tfplugindocs CLI has three main commands, migrate, validate and generate (generate is the default). This tool will let you generate documentation for your provider from live example .tf files and markdown templates. It will also export schema information from the provider (using terraform providers schema -json), and sync the schema with the reference documents.

If your documentation only consists of simple examples and schema information, the tool can also generate missing template files to make website creation extremely simple for most providers.

Installation

You can install a copy of the binary manually from the releases, or you can optionally use the tools.go model for tool installation.

Note

Here is a brief ./tools/tools.go example from https://github.com/hashicorp/terraform-provider-scaffolding-framework:

//go:build tools

package tools

import (
  // Documentation generation
  _ "github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs"
)

Then run the following to install and verify tfplugindocs:

export GOBIN=$PWD/bin
export PATH=$GOBIN:$PATH
go install github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs
which tfplugindocs

Usage

$ tfplugindocs --help
Usage: tfplugindocs [--version] [--help] <command> [<args>]

Available commands are:
                the generate command is run by default
    generate    generates a plugin website from code, templates, and examples
    migrate     migrates website files from either the legacy rendered website directory (`website/docs/r`) or the docs rendered website directory (`docs/resources`) to the tfplugindocs supported structure (`templates/`).
    validate    validates a plugin website
       

generate command:

$ tfplugindocs generate --help

Usage: tfplugindocs generate [<args>]

    --examples-dir <ARG>             examples directory based on provider-dir                                                                                           (default: "examples")
    --ignore-deprecated <ARG>        don't generate documentation for deprecated resources and data-sources                                                             (default: "false")
    --provider-dir <ARG>             relative or absolute path to the root provider code directory when running the command outside the root provider code directory  
    --provider-name <ARG>            provider name, as used in Terraform configurations                                                                               
    --providers-schema <ARG>         path to the providers schema JSON file, which contains the output of the terraform providers schema -json command. Setting this flag will skip building the provider and calling Terraform CLI                                                                               
    --rendered-provider-name <ARG>   provider name, as generated in documentation (ex. page titles, ...)                                                              
    --rendered-website-dir <ARG>     output directory based on provider-dir                                                                                             (default: "docs")
    --tf-version <ARG>               terraform binary version to download. If not provided, will look for a terraform binary in the local environment. If not found in the environment, will download the latest version of Terraform                                                                                             
    --website-source-dir <ARG>       templates directory based on provider-dir                                                                                          (default: "templates")
    --website-temp-dir <ARG>         temporary directory (used during generation)  

validate command:

$ tfplugindocs validate --help

Usage: tfplugindocs validate [<args>]

    --provider-dir <ARG>       relative or absolute path to the root provider code directory; this will default to the current working directory if not set                                                              
    --provider-name <ARG>      provider name, as used in Terraform configurations                                                                                                                                                
    --providers-schema <ARG>   path to the providers schema JSON file, which contains the output of the terraform providers schema -json command. Setting this flag will skip building the provider and calling Terraform CLI    
    --tf-version <ARG>         terraform binary version to download. If not provided, will look for a terraform binary in the local environment. If not found in the environment, will download the latest version of Terraform  

migrate command:

$ tfplugindocs migrate --help

Usage: tfplugindocs migrate [<args>]

    --examples-dir <ARG>             examples directory based on provider-dir                                                                                           (default: "examples")
    --provider-dir <ARG>             relative or absolute path to the root provider code directory when running the command outside the root provider code directory
    --templates-dir <ARG>            new website templates directory based on provider-dir; files will be migrated to this directory                                    (default: "templates")
    --provider-name <ARG>            provider name, as used in Terraform configurations; this will default to provider-dir basename if not set                                                                                                                                            

How it Works

When you run tfplugindocs, by default from the root directory of a provider codebase, the tool takes the following actions:

  • Copy all the templates and static files to a temporary directory
  • Build (go build) a temporary binary of the provider source code
  • Collect schema information using terraform providers schema -json
  • Generate a default provider template file, if missing (index.md)
  • Generate resource template files, if missing
  • Generate data source template files, if missing
  • Generate function template files, if missing (Requires Terraform v1.8.0+)
  • Copy all non-template files to the output website directory
  • Process all the remaining templates to generate files for the output website directory

For inspiration, you can look at the templates and output of the terraform-provider-random and terraform-provider-tls. You can browse their respective docs on the Terraform Registry, here and here.

Usage of Terraform binary

If the --providers-schema flag is not provided, tfplugindocs will use the Terraform binary to generate the provider schema with the commands:

We recommend using the latest version of Terraform when using tfplugindocs, however, the version can be specified with the --tf-version flag if needed.

About the id attribute

If the provider schema didn't set id for the given resource/data-source, the documentation generated will place it under the "Read Only" section and provide a simple description.

Otherwise, the provider developer can set an arbitrary description like this:

    // ...
    Schema: map[string]*schema.Schema{
        // ...
        "id": {
            Type:     schema.TypeString,
            Computed: true,
            Description: "Unique identifier for this resource",
		},
        // ...
    }
    // ...

Validate subcommand

The validate subcommand can be used to validate the provider website documentation against the Terraform Registry's provider documentation guidelines and provider documentation best practices. The current checks in the validate command are:

Check Description
InvalidDirectoriesCheck Checks for valid subdirectory structure and throws an error if an invalid Terraform Provider documentation subdirectory is found.
MixedDirectoriesCheck Throws an error if both legacy documentation (/website/docs) and registry documentation (/docs) are found.
NumberOfFilesCheck Throws an error if the number of files in a directory is larger than the registry limit.
FileSizeCheck Throws an error if the documentation file is above the registry storage limit.
FileExtensionCheck Throws an error if the extension of the given file is not a valid registry documentation extension.
FrontMatterCheck Checks the YAML frontmatter of documentation for missing required fields or invalid fields.
FileMismatchCheck Throws an error if the names/number of resources/datasources/functions in the provider schema does not match the names/number of files in the corresponding documentation directory

All check errors are wrapped and returned as a single error message to stderr.

Migrate subcommand

The migrate subcommand can be used to migrate website files from either the legacy rendered website directory (website/docs/r) or the docs rendered website directory (docs/resources) to the tfplugindocs supported structure (templates/). Markdown files in the rendered website directory will be converted to tfplugindocs templates. The legacy website/ directory will be removed after migration to avoid Terraform Registry ingress issues.

The migrate subcommand takes the following actions:

  1. Determines the rendered website directory based on the --provider-dir argument
  2. Determines the provider name based on the --provider-name argument
  3. Copies the contents of the rendered website directory to the --templates-dir folder (will create this folder if it doesn't exist)
  4. (if the rendered website is using legacy format) Renames docs/d/ and docs/r/ subdirectories to data-sources/ and resources/ respectively
  5. Renames files in the --templates-dir folder to remove the provider shortname prefix from the file name
  6. Change file suffixes for Markdown files to .md.tmpl to create website templates
  7. Extracts code blocks from website docs to create individual example files in --examples-dir (will create this folder if it doesn't exist)
  8. Replace extracted example code in website templates with codefile/tffile template functions referencing the example files.
  9. Copies non-template files to --templates-dir folder
  10. Removes the website/ directory

Conventional Paths

The generation of missing documentation is based on a number of assumptions / conventional paths.

For templates:

NOTE: In the following conventional paths for templates, <data source name>, <resource name>, and <function name> do not include the provider prefix.

Path Description
templates/ Root of templated docs
templates/index.md[.tmpl] Docs index page (or template)
templates/data-sources.md[.tmpl] Generic data source page (or template)
templates/data-sources/<data source name>.md[.tmpl] Data source page (or template)
templates/functions.md[.tmpl] Generic function page (or template)
templates/functions/<function name>.md[.tmpl] Function page (or template)
templates/resources.md[.tmpl] Generic resource page (or template)
templates/resources/<resource name>.md[.tmpl] Resource page (or template)

Note: the .tmpl extension is necessary, for the file to be correctly handled as a template.

For examples:

NOTE: In the following conventional paths for examples, <data source name> and <resource name> include the provider prefix as well, but the provider prefix is NOT included in<function name>. For example, the data source caller_identity in the aws provider would have an "example" conventional path of: examples/data-sources/aws_caller_identity/data-source.tf

Path Description
examples/ Root of examples
examples/provider/provider.tf Provider example config
examples/data-sources/<data source name>/data-source.tf Data source example config
examples/functions/<function name>/function.tf Function example config
examples/resources/<resource name>/resource.tf Resource example config
examples/resources/<resource name>/import.sh Resource example import command

Migration

The migrate subcommand assumes the following conventional paths for the rendered website directory:

NOTE: In the following conventional paths for templates, <data source name>, <resource name>, and <function name> do not include the provider prefix. if the --provider-name argument is set, the provider prefix will be removed from the file names during migration.

Legacy website directory structure:

Path Description
website/ Root of website docs
website/docs/guides Root of guides subdirectory
website/docs/index.html.markdown Docs index page
website/docs/d/<data source name>.html.markdown Data source page
website/docs/functons/<function name>.html.markdown Functions page
website/docs/r/<resource name>.html.markdown Resource page

Docs website directory structure:

Path Description
docs/ Root of website docs
docs/guides Root of guides subdirectory
docs/index.html.markdown Docs index page
docs/data-sources/<data source name>.html.markdown Data source page
docs/functions/<function name>.html.markdown Function page
docs/resources/<resource name>.html.markdown Resource page

Files named index (before the first .) in the website docs root directory and files in the website/docs/d/, website/docs/r/, docs/data-sources/, and docs/resources/ subdirectories will be converted to tfplugindocs templates.

The website/docs/guides/ and docs/guides/ subdirectories will be copied as-is to the --templates-dir folder.

All other files in the conventional paths will be ignored.

Templates

The templates are implemented with Go text/template using the following data fields and functions:

Data fields

Provider Fields
Field Type Description
.Description string Provider description
.HasExample bool Is there an example file?
.ExampleFile string Path to the file with the terraform configuration example
.ProviderName string Canonical provider name (ex. terraform-provider-random)
.ProviderShortName string Short version of the provider name (ex. random)
.RenderedProviderName string Value provided via argument --rendered-provider-name, otherwise same as .ProviderName
.SchemaMarkdown string a Markdown formatted Provider Schema definition
Resources / Data Source Fields
Field Type Description
.Name string Name of the resource/data-source (ex. tls_certificate)
.Type string Either Resource or Data Source
.Description string Resource / Data Source description
.HasExample bool Is there an example file?
.ExampleFile string Path to the file with the terraform configuration example
.HasImport bool Is there an import file?
.ImportFile string Path to the file with the command for importing the resource
.ProviderName string Canonical provider name (ex. terraform-provider-random)
.ProviderShortName string Short version of the provider name (ex. random)
.RenderedProviderName string Value provided via argument --rendered-provider-name, otherwise same as .ProviderName
.SchemaMarkdown string a Markdown formatted Resource / Data Source Schema definition
Provider-defined Function Fields
Field Type Description
.Name string Name of the function (ex. echo)
.Type string Returns Function
.Description string Function description
.Summary string Function summary
.HasExample bool Is there an example file?
.ExampleFile string Path to the file with the terraform configuration example
.ProviderName string Canonical provider name (ex. terraform-provider-random)
.ProviderShortName string Short version of the provider name (ex. random)
.RenderedProviderName string Value provided via argument --rendered-provider-name, otherwise same as .ProviderName
.FunctionSignatureMarkdown string a Markdown formatted Function signature
.FunctionArgumentsMarkdown string a Markdown formatted Function arguments definition
.HasVariadic bool Does this function have a variadic argument?
.FunctionVariadicArgumentMarkdown string a Markdown formatted Function variadic argument definition

Template Functions

Function Description
codefile Create a Markdown code block with the content of a file. Path is relative to the repository root.
lower Equivalent to strings.ToLower.
plainmarkdown Render Markdown content as plaintext.
prefixlines Add a prefix to all (newline-separated) lines in a string.
printf Equivalent to fmt.Printf.
split Split string into sub-strings, by a given separator (ex. split .Name "_").
title Equivalent to cases.Title.
tffile A special case of the codefile function, designed for Terraform files (i.e. .tf).
trimspace Equivalent to strings.TrimSpace.
upper Equivalent to strings.ToUpper.

Disclaimer

This is still under development: while it's being used for production-ready providers, you might still find bugs and limitations. In those cases, please report issues or, if you can, submit a pull-request.

Your help and patience is truly appreciated.

Contributing

License Headers

All source code files in this repository (excluding autogenerated files like go.mod, prose, and files excluded in .copywrite.hcl) must have a license header at the top.

This can be autogenerated by running make generate or running go generate ./... in the /tools directory.

Acceptance Tests

This repo uses the testscript package for acceptance testing.

There are two types of acceptance tests: full provider build tests in tfplugindocs/testdata/scripts/provider-build and provider schema json tests in tfplugindocs/testdata/scripts/schema-json.

Provider build tests run the default tfplugindocs command which builds the provider source code and runs Terraform to retrieve the schema. These tests require the full provider source code to build a valid provider binary.

Schema json tests run the tfplugindocs command with the --providers-schema=<arg> flag to specify a provider schemas json file. This allows the test to skip the provider build and Terraform CLI call, instead using the specified file to generate docs.

You can run make testacc to run the full suite of acceptance tests. By default, the provider build acceptance tests will create a temporary directory in /tmp/tftmp for testing, but you can change this location in cmd/tfplugindocs/main_test.go. The schema json tests uses the testscript package's default work directory.

The test scripts are defined in the tfplugindocs/testdata/scripts directory. Each script includes the test, golden files, and the provider source code or schema JSON file needed to run the test.

Each script is a text archive. You can install the txtar CLI locally by running go install golang.org/x/exp/cmd/txtar@latest to extract the files in the test script for debugging. You can also use txtar CLI archive files into the .txtar format to create new tests or modify existing ones.

terraform-plugin-docs's People

Contributors

alessiodionisi avatar anmoel avatar austinvalle avatar bendbennett avatar bflad avatar bookshelfdave avatar dependabot[bot] avatar detro avatar eamonnotoole avatar ewbankkit avatar gdavison avatar gennadyspb avatar hashicorp-copywrite[bot] avatar hashicorp-tsccr[bot] avatar hc-github-team-tf-provider-devex avatar jacobbednarz avatar k-yomo avatar koikonom avatar nayyara-cropsey avatar ojford avatar ovandriyanov avatar paddycarver avatar paultyng avatar remilapeyre avatar sbgoods avatar sebhoss avatar smacfarlane avatar thiskevinwang avatar yannihu1996 avatar zippolyte avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

terraform-plugin-docs's Issues

Terraform Plugin Protocol Version 6 / Providers Schema JSON Version 0.2 Support

Description

As part of the upcoming Terraform CLI version 0.15 release, a newer version 6 of the Terraform Plugin Protocol is now available. This protocol bump includes goodies such as NestedType that will benefit the future of plugin development and documentation. The changes to the output of terraform providers schema -json are denoted with a bump in that format version from 0.1 to 0.2.

References

Allow skipping docs for resources

Related to the issue around deprecation in #10, if a resource is renamed, then it would be helpful to skip generating documentation for that resource.

One approach might be to take a command line flag for resources or filenames to skip in generation.

No Schema Discovery when using Resource/Data-Source specific templates

Not sure if I have the wrong expectation or if something is broken with resource and data-source templates. The template line:

{{ .SchemaMarkdown | trimspace }} seems to break/not-function when I create these specific templates.

I have my internal/provider/resource_plugin.go and internal/provider/datasource_plugin.go files defined. I create templates:

templates/resource/plugin.md.tmpl and templates/data-sources/plugin.md.tmpl

run tfplugindocs in the root of my plugin repo and get an error:

Error executing command: unable to generate website: unable to render template "data-sources/plugin.md.tmpl": unable to execute template: template: docTemplate:11:21: executing "docTemplate" at <trimspace>: invalid value; expected string

This trimspace error is related to .SchemaMarkdown return "". Seems that .SchemaMarkdown can't find the

func resourcePlugin() *schema.Resource in resource_plugin.go (nor datasource_plugin.go).

If I don't create specific templates, tfplugindocs runs to completion and all the files are generated. Although without the custom content I'd like to include.

I'm expecting my specific templates to allow me to create custom md-headers and other content, while .SchemaMarkdown does it's thing.

Creating the specific template index.md.tmpl works as I expect.

Is this how templates/resource/plugin.md.tmpl and templates/datasources/plugin.md.tmpl are suposed to work?

Thank you.

Support flag for providing the name of the provider

For slightly silly/cautious reasons, I'm developing my provider in a folder that is different from the repo & providers name, which means that the docs are generated with the wrong name.

It would be good if we could pass in the name with via a -name flag.

tfplugindocs does not handle tags

I have a Terraform Provider which needs special tags to build.
These tags I can pass to:

go run -tags containers_image_openpgp github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs

The problem is though, that tfplugindocs does not pass along the tags.
As a result tflugindocs fails building Go files.

Error: /home/runner/go/pkg/mod/github.com/containers/image/[email protected]/signature/mechanism_gpgme.go:17:16: undefined: gpgme.Context
Error: /home/runner/go/pkg/mod/github.com/containers/image/[email protected]/signature/mechanism_gpgme.go:67:44: undefined: gpgme.Context
Error: /home/runner/go/pkg/mod/github.com/containers/image/[email protected]/signature/mechanism_gpgme.go:68:14: undefined: gpgme.New
Error: /home/runner/go/pkg/mod/github.com/containers/image/[email protected]/signature/mechanism_gpgme.go:72:27: undefined: gpgme.ProtocolOpenPGP
Error: /home/runner/go/pkg/mod/github.com/containers/image/[email protected]/signature/mechanism_gpgme.go:76:28: undefined: gpgme.ProtocolOpenPGP
Error: /home/runner/go/pkg/mod/github.com/containers/image/[email protected]/signature/mechanism_gpgme.go:98:20: undefined: gpgme.NewDataBytes
Error: /home/runner/go/pkg/mod/github.com/containers/image/[email protected]/signature/mechanism_gpgme.go:127:20: undefined: gpgme.NewDataBytes
Error: /home/runner/go/pkg/mod/github.com/containers/image/[email protected]/signature/mechanism_gpgme.go:132:18: undefined: gpgme.NewDataWriter
Error: /home/runner/go/pkg/mod/github.com/containers/image/[email protected]/signature/mechanism_gpgme.go:136:25: undefined: gpgme.Key
Error: /home/runner/go/pkg/mod/github.com/containers/image/[email protected]/signature/mechanism_gpgme.go:136:61: undefined: gpgme.SigModeNormal
Error: /home/runner/go/pkg/mod/github.com/containers/image/[email protected]/signature/mechanism_gpgme.go:136:61: too many errors

Thus I would need a way for tfplugindocs to handle tags when generating code.

"Block List" confusing to user reading docs, perhaps "repeatable Block"?

(Block List) as a type rendered in documentation makes sense to the maintainer of a provider, but IMO it's confusing or even misleading to the end user.

Concrete example here:
OJFord/terraform-provider-wireguard@58ef3d8#diff-60a95e399cf5c94cb98075600ad42997cdae1a9839f293569766d66acdaa0bcfR59

peer in:

data "wireguard_config_document" "peer1" {
  private_key = wireguard_asymmetric_key.peer1.private_key
  listen_port = 1234
  dns = [
    "1.1.1.1",
    "1.0.0.1",
    "2606:4700:4700:0:0:0:0:64",
    "2606:4700:4700:0:0:0:0:6400",
  ]

  peer {
    public_key = wireguard_asymmetric_key.peer2.public_key
    allowed_ips = [
      "0.0.0.0/0",
    ]
    persistent_keepalive = 25
  }

  peer {
    public_key = wireguard_asymmetric_key.peer3.public_key
    endpoint   = "example.com:51820"
    allowed_ips = [
      "::/0",
    ]
  }
}

to a user isn't a 'list', it's just a block. One that can be specified multiple times, sure, and maybe that's represented as a list behind the scenes, but as someone using the resource or data source it isn't a list.

It's rendered in docs (by tfplugindocs v0.4.0) as:

but I think better would be:

or 'multiple allowed', or similar.

Anchor links for nested blocks broken on registry docs

When generating sections for documenting nested blocks, the generator creates a <a id="nestedblock--something"></a> just above the markdown title level 3 that is generated ### Nested schema for something and generates links that point to the former anchor instead of the one generated by the markdown title.
Issue is the id="nestedblock--something" part of the HTML link is removed in the final docs on the registry (on the preview too), leaving only <a></a>, so the anchor links are effectively broken.

See for example this page https://registry.terraform.io/providers/DataDog/datadog/latest/docs/resources/monitor
Generated from https://github.com/DataDog/terraform-provider-datadog/blob/master/docs/resources/monitor.md
Using the tfplugindocs v0.3.1

Now the question is: should this be fixed in the registry site where the markdown files are rendered to HTML, so that the id attribute doesn't disappear, or should it be fixed in this generator so that it directly uses the id that the markdown titles will get after rendering.

Thanks for having a look !
And thanks for this docs generator !

Cheers

bug: attribute descriptions are not rendered in read-only nested block

Current behavior

Given the schema entry with the surrounding type is and all attributes are Computed: true,:

"network_data": {
	Type:        schema.TypeList,
	Description: "The data of the networks the container is connected to",
        Computed:    true,
	Elem: &schema.Resource{
		Schema: map[string]*schema.Schema{
			"network_name": {
				Type:        schema.TypeString,
				Description: "The name of the network",
				Computed:    true,
			},
			"ip_address": {
				Type:        schema.TypeString,
				Description: "The IP address of the container.",
				Computed:    true,
				Deprecated:  "Use `network_data` instead. The IP address of the container's first network it.",
			},
			"ip_prefix_length": {
				Type:        schema.TypeInt,
				Description: "The IP prefix length of the container.",
				Computed:    true,
				Deprecated:  "Use `network_data` instead. The IP prefix length of the container as read from its NetworkSettings.",
			},
			"gateway": {
				Type:        schema.TypeString,
				Description: "The network gateway of the container.",
				Computed:    true,
				Deprecated:  "Use `network_data` instead. The network gateway of the container as read from its NetworkSettings.",
			},
			"global_ipv6_address": {
				Type:        schema.TypeString,
				Description: "The IPV6 address of the container",
				Computed:    true,
			},
			"global_ipv6_prefix_length": {
				Type:        schema.TypeInt,
				Description: "The IPV6 prefix length address of the container",
				Computed:    true,
			},
			"ipv6_gateway": {
				Type:        schema.TypeString,
				Description: "The IPV6 gateway of the container",
				Computed:    true,
			},
		},
	},
},

the rendered output is

<a id="nestedatt--network_data"></a>
### Nested Schema for `network_data`

Read-Only:

- **gateway** (String)
- **global_ipv6_address** (String)
- **global_ipv6_prefix_length** (Number)
- **ip_address** (String)
- **ip_prefix_length** (Number)
- **ipv6_gateway** (String)
- **network_name** (String)

Desired behavior

Where I like to see this output:

<a id="nestedblock--network_data"></a>
### Nested Schema for `network_data`

Read-Only:

- **gateway** (String, Deprecated) The network gateway of the container.
- **global_ipv6_address** (String) The IPV6 address of the container
- **global_ipv6_prefix_length** (Number) The IPV6 prefix length address of the container
- **ip_address** (String, Deprecated) The IP address of the container.
- **ip_prefix_length** (Number, Deprecated) The IP prefix length of the container.
- **ipv6_gateway** (String) The IPV6 gateway of the container
- **network_name** (String) The name of the network

For the surrounding type with Optional: true, the rendering works as expected.

Versions

  • terraform-plugin-docs: v0.4.0
  • terraform-plugin-sdk/v2 v2.6.1

ID attribute marked as Optional in generated documentation

Each terraform schema has an implicit ID that needs to be set for the terraform lifecycle to work properly.
We don't set this "ID" explicitly in the schema, but the generated documentation seems to mark it as Optional

I think this should be marked as "Read Only" if the "ID" isn't explicitly in the schema by the provider developer.

Example Dashboard Resource Schema - https://github.com/DataDog/terraform-provider-datadog/blob/master/datadog/resource_datadog_dashboard.go#L44
Generated Documentation - https://registry.terraform.io/providers/DataDog/datadog/latest/docs/resources/dashboard#optional

Question: Is showing a Required field as Optional when setting DefaultFunc the best approach?

Hello ๐Ÿ‘‹๐Ÿป

I'm opening this more for a general discussion regarding the use of DefaultFunc with a required field.

I've noticed that when adding DefaultFunc to an otherwise required field it's rendered in the documentation as 'optional'.

Now this make sense because if the value isn't provided by the user in their configuration, then we'll use schema.EnvDefaultFunc to get a value (otherwise we return an empty string), but it's also a little bit confusing when you look at the code and see Required: true compared to the documentation saying it's 'optional'.

"user": {
  Type:        schema.TypeString,
  Required:    true,
  DefaultFunc: schema.EnvDefaultFunc("SOME_ENV_VAR", ""),
}

I'm not sure if it's better to still have this field be shown as 'required' in the documentation because ultimately if the user doesn't provide a value (not in config, nor in the environment var) then we'll end up setting an empty string which will (in our case definitely) cause errors. I'd personally still prefer to see this field under "Required" to be explicit that regardless of the use of DefaultFunc the user should pay special attention to it.

Thoughts?

Stronger emphasis on `Deprecated` schema fields

Currently, when a field in a schema is deprecated, it shows up in parenthesis next to whether it's required or not.

Live example here under thresholds - https://registry.terraform.io/providers/DataDog/datadog/latest/docs/resources/monitor#optional

thresholds (Map of String, Deprecated) Alert thresholds of the monitor.

Could the fact that a field is deprecated be more strongly represented?
A few ideas for this may be -

  • Make the word Deprecated bold to stand out more
  • Maybe have a new section Required, Optional, Deprecated

Thanks for this project ๐Ÿ™‚

bug with required provider attributes w/ env variables

I have been trying to make use of this project with terraform-provider-snowflake and am very excited for it, since it means I could delete my half-baked code that did similar work.

We have run into one limitation โ€“ required provider configuration which accepts environment variables.

When using this configuration, running terraform providers schema -json will vary its configuration for these inputs based on whether or not the environment variables are present. For the linked example, if the SNOWFLAKE_USER environment variable is set, then username will be marked as "optional". If the env variable is not preset, it will be set as "required".

For purposes of documentation, it seems like it should always be marked as "required".

Document how to emit attribute defaults (and other customizations) via the SDK

Assume the following schema segment:

"quantity": {
  Default:  30,
  Description: "The quantity of this resource.",
  Optional: true,
  Type:     schema.TypeInt,
}

When documentation is generated, fields are emitted with their type and a requirement "indicator":

quantity (Number, Optional) The quantity of this resource.

A default value should be emitted to the generated Markdown if specified in the underlying schema:

quantity (Number, Optional, Default: 30) The quantity of this resource.

please tell me default templates

Background

I have created some terraform provider,
and it is need to create document so using this and modify but I have a hard time reproducing default.

I have copy and paste from template.go but something wrong...for example, not output Example Usage on index.md.
(What is {{ if .HasExample -}} ...?)

I need...

  • how to reproduce default
  • default templates on (this repo)/templates/*
  • documentation special variables/functions

Thank you.

Self Hosting Terraform Provider docs

hi!

Is there any way to self host provider docs? We wrote some providers that are internal to our company.

We would like to generate docs for them using tfplugindocs. I used this tool, but i just got MD files in the format expected by the registry.

Is there a way to convert these files to normal markdown files so that they can be hosted in Github pages, for eg?

Error while running

Hello!

I'm trying to run tfplugindocs for the provider-terraform-hashicups provider.

I am receiving the following error, can you point me in the right direction?

$ go run github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs
rendering website for provider "terraform-provider-hashicups"
exporting schema from Terraform
compiling provider "hashicups"
2022/04/26 23:07:27 error executing "/usr/local/bin/go", [go build -o /var/folders/s6/m22_k3p11z104k2vx1jkqr2c0000gp/T/tfws2963541216/plugins/registry.terraform.io/hashicorp/hashicups/0.0.1/darwin_amd64/terraform-provider-hashicups]
2022/04/26 23:07:27 ../../../../pkg/mod/github.com/zclconf/[email protected]/cty/function/stdlib/format.go:9:2: missing go.sum entry for module providing package github.com/apparentlymart/go-textseg/v13/textseg (imported by github.com/zclconf/go-cty/cty/function/stdlib); to add:
        go get github.com/zclconf/go-cty/cty/function/[email protected]
../../../../pkg/mod/github.com/hashicorp/[email protected]/internal/plugin/grpc_broker.pb.go:11:2: missing go.sum entry for module providing package golang.org/x/net/context (imported by github.com/hashicorp/go-plugin); to add:
        go get github.com/hashicorp/[email protected]
../../../../pkg/mod/google.golang.org/[email protected]/internal/transport/controlbuf.go:28:2: missing go.sum entry for module providing package golang.org/x/net/http2 (imported by google.golang.org/grpc/internal/transport); to add:
        go get google.golang.org/grpc/internal/[email protected]
../../../../pkg/mod/google.golang.org/[email protected]/internal/transport/controlbuf.go:29:2: missing go.sum entry for module providing package golang.org/x/net/http2/hpack (imported by google.golang.org/grpc/internal/transport); to add:
        go get google.golang.org/grpc/internal/[email protected]
../../../../pkg/mod/google.golang.org/[email protected]/server.go:36:2: missing go.sum entry for module providing package golang.org/x/net/trace (imported by google.golang.org/grpc); to add:
        go get google.golang.org/[email protected]
Error executing command: unable to generate website: error executing "/usr/local/bin/go": exit status 1

exit status 1

feat: add default values to attributes to documentation

Current behavior

Given the schema entry:

"rm": {
	Type:        schema.TypeBool,
	Description: "If true, then the container will be automatically removed after his execution.",
	Default:     false,
	Optional:    true,
},

the rendered output is

- **rm** (Boolean) If true, then the container will be automatically removed after his execution.

Desired behavior

I'd like to have Defaults to abc in the generation as well as follows:

- **rm** (Boolean) If true, then the container will be automatically removed after his execution. Defaults to `false`

Versions

  • terraform-plugin-docs: v0.4.0
  • terraform-plugin-sdk/v2 v2.6.1

Log/Output Provider Binary Path When Used

example:

// service_account resource schema
func (r serviceAccountResourceType) GetSchema(_ context.Context) (tfsdk.Schema, diag.Diagnostics) {
	return tfsdk.Schema{

		MarkdownDescription: "Service account resource",

		Attributes: map[string]tfsdk.Attribute{
			"id": {
				Type:     types.StringType,
				Computed: true,
				MarkdownDescription: "Server generated UUID",
			},
			"name": {
				Type:     types.StringType,
				Required: true,
				Validators: []tfsdk.AttributeValidator{
					validate.StringNotNull(),
				},
			},
			"role": {
				Type:     types.StringType,
				Required: true,
				Validators: []tfsdk.AttributeValidator{
					validate.RoleIsValid(),
				},
			},
			"membership_id": {
				Type:     types.StringType,
				Computed: true,
				MarkdownDescription: "Server generated UUID",
			},
		},
	}, nil
}

Both Description and MarkdownDescription are ignored.

github.com/hashicorp/terraform-plugin-docs v0.5.1

Resource / Data source examples not detected when a template is provided

The readme describes using resource examples in examples/resources/<name>/resource.tf, but if I template {{ printf "%s" .ExampleFile }} it seems just to be "" for resources.

After a quick look at the code, I think it's just not implemented rather than a bug. I'm sure you know this - a note here just might help anyone else confused by it.

To workaround, you can of course just change the template to remove the if .HasExample and .ExampleFile and replace with a tffile "examples/resources/wherever.tf". That is:

{{/* templates/resources/name.md.tmpl */}}

 ## Example Usage

{{ tffile "examples/resources/name/resource.tf" }}

cannot find module providing package github.com/hashicorp/terraform-exec/tfinstall

go mod init demo
go get github.com/hashicorp/terraform-plugin-framework
go get github.com/hashicorp/terraform-plugin-go
go get github.com/hashicorp/terraform-plugin-sdk/v2
cat go.mod
module demo

go 1.17

require (
	github.com/hashicorp/terraform-plugin-framework v0.6.0 // indirect
	github.com/hashicorp/terraform-plugin-go v0.8.0 // indirect
	github.com/hashicorp/terraform-plugin-sdk/v2 v2.11.0 // indirect
)
go get github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs
github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs imports
	github.com/hashicorp/terraform-plugin-docs/internal/cmd imports
	github.com/hashicorp/terraform-plugin-docs/internal/provider imports
	github.com/hashicorp/terraform-exec/tfinstall: cannot find module providing package github.com/hashicorp/terraform-exec/tfinstall

Add means to provide a generic resource and data source template

It seems like resource and data source templates have to be name specific. This request is providing the caller the ability to replace the const defaultResourceTemplate. Then the provider developer does not have to provide a template per unique resource.

Have a go run compatible workflow

Currently, if I try to run the main.go directly with go I get the following errors. Could you have defaults such as undefined commit and devel version?

$ go run ./cmd/tfplugindocs/main.go
# command-line-arguments
cmd/tfplugindocs/main.go:13:34: undefined: version
cmd/tfplugindocs/main.go:14:5: undefined: commit
cmd/tfplugindocs/main.go:15:32: undefined: commit

configuration is invalid

Hello,

When running tfplugindocs inside my terraform plugin I have this error:

tfplugindocs.exe generate 
rendering website for provider "terraform_ccc_provider"
exporting schema from Terraform
compiling provider "terraform_ccc_provider"
using Terraform CLI binary from PATH if available, otherwise downloading latest Terraform CLI binary
running terraform init
Error executing command: unable to generate website: configuration is invalid

I cannot get any information on what is invalid and what this tool is expecting. Would be nice to have more informations on this kind of errors.

Can you help me?

Regards

Add validation to links

The AWS provider uses a GitHub action to do this, may be able to use similar functionality or the command its wrapping.

Potentially related to #5

Bring your own terraform binary

It looks like tfpluginfocs downloads the terraform binary each time it is run. We could work a lot quicker if we could tell tfplugindocs the location of a terraform binary to use instead.

I'd like to propose a new argument --terraform-binary [path] for this purpose. When specified, tfplugindocs would use that terraform binary instead of downloading it. (This is analogous to Helmfile's --helm-binary argument.)

Running v0.7.0 in Actions, with terraform on PATH, gives invalid character 'c' looking for beginning of value

Only running in GH Actions CI (vs. my also-amd64 machine) and only if terraform is already on $PATH, v0.7.0 (which began to use it from PATH) errors:

using Terraform CLI binary from PATH if available, otherwise downloading latest Terraform CLI binary
running terraform init
getting provider schema
Error executing command: unable to generate website: invalid character 'c' looking for beginning of value

(For example: https://github.com/OJFord/terraform-provider-wireguard/runs/5590511618)

I haven't been able to reproduce this outside of Actions, even using act, which makes it quite difficult to debug.

I've worked around it by letting it acquire terraform itself instead.

Unable to render schema without a 'required' attribute.

I'm trying to generate docs for a custom provider, however the tool produces an error when it tries to render the following schema:

func manualTriggerSchema() map[string]*schema.Schema {
	return map[string]*schema.Schema{
		"trigger": {
			Type:     schema.TypeString,
			Computed: true,
		},
	}
}

Which produces the following error:

Error executing command: unable to generate website: unable to render doc "gorillastack_rule": unable to render template for "gorillastack_rule": unable to render schema: unable to render schema: no match for "manual"

Adding a dummy 'required' attribute fixes this issue:

func manualTriggerSchema() map[string]*schema.Schema {
	return map[string]*schema.Schema{
		"trigger": {
			Type:     schema.TypeString,
			Computed: true,
		},
		"dummy": {
			Type:     schema.TypeString,
			Required: true,
		},
	}
}

Is it a requirement that a 'Required' attribute must be present in a schema or is this a bug within the tool?

Thanks.

Preview rendered site

Just a feature idea - I realise it'll at best be a 'nice-to-have', far more to be done first sort of thing - but I think it'd be really helpful for working on provider docs; making sure the flow makes sense and everything renders correctly, to be able to serve a local preview roughly as it will render on the registry.

i.e. something like:

$tfplugindocs serve
Serving myprovider docs on http://localhost:8123

(And just to say - even without that, I'm already extremely glad to find this generator, early days as it may be. Beats the copy-pasting-renaming between projects I have been doing. ๐Ÿ˜Š Great stuff!)

Use code block for attribute name

It's more readable to use code block for attribute names instead of bold and also it makes attributes linkable.
It's also aligned with the docs of major terraform providers.

Screen Shot 2021-04-26 at 13 30 23

Descriptions for nested schemas are missing (inconsistent behaviour)

There are two issues:

  1. A Description field set on the parent Schema isn't displayed any where.
  2. In some cases a nested Schema type(s) will not have its Description value pulled into the documentation.

Here's an example schema that shows a Description field has been set on the top-level Schema:

s.Schema[h.GetKey()] = &schema.Schema{
	Type:        schema.TypeSet,
	Required:    true,
	Description: "A set of Domain names to serve as entry points for your Service",
	Elem: &schema.Resource{
		Schema: map[string]*schema.Schema{
			"name": {
				Type:        schema.TypeString,
				Required:    true,
				Description: "The domain that this Service will respond to",
			},
			"comment": {
				Type:        schema.TypeString,
				Optional:    true,
				Description: "An optional comment about the Domain.",
			},
		},
	},
}

Yet when generating the documentation for this resource I discovered that description value is not present anywhere:

Screenshot 2021-01-27 at 13 40 39

Screenshot 2021-01-27 at 13 40 46

Here's an example schema definition with a nested schema under the 'rules' field:

Schema: map[string]*schema.Schema{
	"publishers": {
		Type:        schema.TypeList,
		Optional:    true,
		Description: "A list of publishers to be used as filters for the data set.",
		Elem:        &schema.Schema{Type: schema.TypeString},
	},
	"tags": {
		Type:        schema.TypeList,
		Optional:    true,
		Description: "A list of tags to be used as filters for the data set.",
		Elem:        &schema.Schema{Type: schema.TypeString},
	},
	"exclude_modsec_rule_ids": {
		Type:        schema.TypeList,
		Optional:    true,
		Description: "A list of modsecurity rules IDs to be excluded from the data set.",
		Elem:        &schema.Schema{Type: schema.TypeInt},
	},
	"rules": {
		Type:        schema.TypeList,
		Computed:    true,
		Description: "The list of rules that results from any given combination of filters.",
		Elem: &schema.Resource{
			Schema: map[string]*schema.Schema{
				"modsec_rule_id": {
					Type:        schema.TypeInt,
					Required:    true,
					Description: "The modsecurity rule ID.",
				},
				"latest_revision_number": {
					Type:        schema.TypeInt,
					Required:    true,
					Description: "The modsecurity rule's latest revision.",
				},
				"type": {
					Type:        schema.TypeString,
					Computed:    true,
					Description: "The modsecurity rule's type.",
				},
			},
		},
	},
},

In the generated schema output (see below example, from running tfplugindocs generate) we can see the Description fields from the top-level Schema types are included in the output, but the nested Schema Description fields are not included (see <MISSING DESCRIPTION>)...

<!-- schema generated by tfplugindocs -->
## Schema

### Optional

- **exclude_modsec_rule_ids** (List of Number) A list of modsecurity rules IDs to be excluded from the data set.
- **id** (String) The ID of this resource.
- **publishers** (List of String) A list of publishers to be used as filters for the data set.
- **tags** (List of String) A list of tags to be used as filters for the data set.

### Read-only

- **rules** (List of Object) The list of rules that results from any given combination of filters. (see [below for nested schema](#nestedatt--rules))

<a id="nestedatt--rules"></a>
### Nested Schema for `rules`

Read-only:

- **latest_revision_number** (Number) <MISSING DESCRIPTION>
- **modsec_rule_id** (Number) <MISSING DESCRIPTION>
- **type** (String) <MISSING DESCRIPTION>

Empty objects in schema fail the doc generation

Terraform allows providers to have empty objects in their schema, but currently terraform-plugin-docs does not recognize such empty fields neither as required, nor optional, nor read-only, and thus cannot generate docs for such providers and raises an error like the following:

no match for empty_block_field, this can happen if you have incompatible schema
defined, for example an optional block where all the child attributes are
computed, in which case the block itself should also be marked computed

I tried to fix it with this patch: #99

cannot find module providing package google.golang.org/grpc/naming

As per Generating Documentation:

$ go get github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs
github.com/hashicorp/terraform-plugin-docs/cmd/tfplugindocs imports
        github.com/hashicorp/terraform-plugin-docs/internal/cmd imports
        github.com/hashicorp/terraform-plugin-docs/internal/provider imports
        github.com/hashicorp/terraform-exec/tfinstall imports
        github.com/hashicorp/go-getter imports
        cloud.google.com/go/storage imports
        google.golang.org/api/option imports
        google.golang.org/api/internal imports
        google.golang.org/grpc/naming: cannot find module providing package google.golang.org/grpc/naming
$ go version 
go version go1.17.8 darwin/amd64        

Error executing command: unable to generate website: unexpected error: invalid checksum: no checksum found in: https://releases.hashicorp.com/terraform/0.13.2/terraform_0.13.2_SHA256SUMS

Running the tfplugindocs from the root of any provider repo generates the following error:

โฏ tfplugindocs
rendering website for provider "terraform-provider-scaffolding"
exporting schema from Terraform
compiling provider "scaffolding"
Error executing command: unable to generate website: unexpected error: invalid checksum: no checksum found in: https://releases.hashicorp.com/terraform/0.13.2/terraform_0.13.2_SHA256SUMS

> ~/g/s/g/h/terraform-provider-scaffolding

Not sure what i'm doing incorrectly. I have tried on other repos terraform-provider-unifi and same results

Add IsDeprecated for Template Rendering

As mentioned in #10:

deprecation messages are not included in the schema exported from Terraform, only a bool indicating its deprecated

I propose making this bool available in the template rendering (as a workaround to this limitation). That way, it may be used in custom templates for documentation generation.

bug: TypeSet/TypeList Elements are not rendered in data-sources

Current behavior

The descriptions of the nested elements are only rendered in the markdown of the resources, but not the datasources.

  • The schema:
"ipam_config": {
	Type:        schema.TypeSet,
	Description: "The IPAM configuration options",
	Computed:    true,
	Elem: &schema.Resource{
		Schema: map[string]*schema.Schema{
			"subnet": {
				Type:        schema.TypeString,
				Description: "The subnet in CIDR form",
				Optional:    true,
				ForceNew:    true,
			},

			"ip_range": {
				Type:        schema.TypeString,
				Description: "The ip range in CIDR form",
				Optional:    true,
				ForceNew:    true,
			},

			"gateway": {
				Type:        schema.TypeString,
				Description: "The IP address of the gateway",
				Optional:    true,
				ForceNew:    true,
			},

			"aux_address": {
				Type:        schema.TypeMap,
				Description: "Auxiliary IPv4 or IPv6 addresses used by Network driver",
				Optional:    true,
				ForceNew:    true,
			},
		},
	},
},

See the rendered markdowns:

Expected behavior

The descriptions of the nested elements in datasources are also rendered in the markdown.

Versions

  • terraform-plugin-docs: v0.4.0
  • terraform-plugin-sdk/v2 v2.6.1

Still being worked on?

Hi, I'm just curious if tfplugindocs is still being worked on?

Just slightly worried to notice no commits for several months when quite active previously, except moving an Action from @paultyng's repo to Hashicorp's; that not authored or committed by him (instead @smacfarlane), who was previously the committer on almost all and authored most.

Thanks! ๐Ÿคž๐Ÿป it's nothing, just a priority shift ๐Ÿ™‚

template vars .Type & .Name are back to front?

For the resource template excerpt:

# {{.Type}} `{{.Name}}`

v0.4.0 generates (for an AWS VPC resource, say):

# aws_vpc `Resource`

which is certainly backwards from the perspective of the rendered page, but surely it's right to expect that .Type would be "Resource" and .Name "aws_vpc", rather than vice versa?

I initially got that template from the Unifi provider linked in the readme here, but I note now that it doesn't use resource templates, and there's a sensible default if you don't need to add something to the template. So I've actually done that myself too now, and as a result this isn't really an issue for me, just thought I'd mention it ๐Ÿ™‚.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.