Home

Awesome

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; defaults to the --provider-dir short name (after removing `terraform-provider-` prefix)                                                                            
    --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; defaults to the --provider-dir short name (after removing `terraform-provider-` prefix) 
    --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; defaults to the --provider-dir short name (after removing `terraform-provider-` prefix)     

How it Works

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

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:

CheckDescription
InvalidDirectoriesCheckChecks for valid subdirectory structure and throws an error if an invalid Terraform Provider documentation subdirectory is found.
MixedDirectoriesCheckThrows an error if both legacy documentation (/website/docs) and registry documentation (/docs) are found.
FileSizeCheckThrows an error if the documentation file is above the registry storage limit.
FileExtensionCheckThrows an error if the extension of the given file is not a valid registry documentation extension.
FrontMatterCheckChecks the YAML frontmatter of documentation for missing required fields or invalid fields.
FileMismatchCheckThrows 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.

PathDescription
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/ephemeral-resources.md[.tmpl]Generic ephemeral resource page (or template)
templates/ephemeral-resources/<ephemeral resource name>.md[.tmpl]Ephemeral resource 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

PathDescription
examples/Root of examples
examples/provider/provider.tfProvider example config
examples/data-sources/<data source name>/data-source.tfData source example config
examples/ephemeral-resources/<ephemeral resource>/ephemeral-resource.tfEphemeral resource example config
examples/functions/<function name>/function.tfFunction example config
examples/resources/<resource name>/resource.tfResource example config
examples/resources/<resource name>/import.shResource 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:

PathDescription
website/Root of website docs
website/docs/guidesRoot of guides subdirectory
website/docs/index.html.markdownDocs index page
website/docs/d/<data source name>.html.markdownData source page
website/docs/ephemeral-resources/<ephemeral resource name>.html.markdownEphemeral resource page
website/docs/functons/<function name>.html.markdownFunctions page
website/docs/r/<resource name>.html.markdownResource page

Docs website directory structure:

PathDescription
docs/Root of website docs
docs/guidesRoot of guides subdirectory
docs/index.html.markdownDocs index page
docs/data-sources/<data source name>.html.markdownData source page
docs/ephemeral-resources/<ephemeral resource name>.html.markdownEphemeral resource page
docs/functions/<function name>.html.markdownFunction page
docs/resources/<resource name>.html.markdownResource 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
FieldTypeDescription
.DescriptionstringProvider description
.HasExampleboolIs there an example file?
.ExampleFilestringPath to the file with the terraform configuration example
.ProviderNamestringCanonical provider name (ex. terraform-provider-random)
.ProviderShortNamestringShort version of the provider name (ex. random)
.RenderedProviderNamestringValue provided via argument --rendered-provider-name, otherwise same as .ProviderName
.SchemaMarkdownstringa Markdown formatted Provider Schema definition
Managed Resource / Ephemeral Resource / Data Source Fields
FieldTypeDescription
.NamestringName of the resource/data-source (ex. tls_certificate)
.TypestringEither Resource or Data Source
.DescriptionstringResource / Data Source description
.HasExampleboolIs there an example file?
.ExampleFilestringPath to the file with the terraform configuration example
.HasImportboolIs there an import file?
.ImportFilestringPath to the file with the command for importing the resource
.ProviderNamestringCanonical provider name (ex. terraform-provider-random)
.ProviderShortNamestringShort version of the provider name (ex. random)
.RenderedProviderNamestringValue provided via argument --rendered-provider-name, otherwise same as .ProviderName
.SchemaMarkdownstringa Markdown formatted Resource / Data Source Schema definition
Provider-defined Function Fields
FieldTypeDescription
.NamestringName of the function (ex. echo)
.TypestringReturns Function
.DescriptionstringFunction description
.SummarystringFunction summary
.HasExampleboolIs there an example file?
.ExampleFilestringPath to the file with the terraform configuration example
.ProviderNamestringCanonical provider name (ex. terraform-provider-random)
.ProviderShortNamestringShort version of the provider name (ex. random)
.RenderedProviderNamestringValue provided via argument --rendered-provider-name, otherwise same as .ProviderName
.FunctionSignatureMarkdownstringa Markdown formatted Function signature
.FunctionArgumentsMarkdownstringa Markdown formatted Function arguments definition
.HasVariadicboolDoes this function have a variadic argument?
.FunctionVariadicArgumentMarkdownstringa Markdown formatted Function variadic argument definition

Template Functions

FunctionDescription
codefileCreate a Markdown code block with the content of a file. Path is relative to the repository root.
lowerEquivalent to strings.ToLower.
plainmarkdownRender Markdown content as plaintext.
prefixlinesAdd a prefix to all (newline-separated) lines in a string.
printfEquivalent to fmt.Printf.
splitSplit string into sub-strings, by a given separator (ex. split .Name "_").
titleEquivalent to cases.Title.
tffileA special case of the codefile function, designed for Terraform files (i.e. .tf).
trimspaceEquivalent to strings.TrimSpace.
upperEquivalent 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.