# Generate documentation from Terraform modules in various output formats


# terraform-docs

![terraform-docs-teaser](https://github.com/terraform-docs/terraform-docs/raw/master/images/terraform-docs-teaser.png align="center")

## What is terraform-docs

A utility to generate documentation from Terraform modules in various output formats.

## Installation

macOS users can install using [Homebrew](https://brew.sh/):

```less
brew install terraform-docs
```

or

```less
brew install terraform-docs/tap/terraform-docs
```

Windows users can install using [Scoop](https://scoop.sh/):

```less
scoop bucket add terraform-docs https://github.com/terraform-docs/scoop-bucket
scoop install terraform-docs
```

or [Chocolatey](https://www.chocolatey.org/):

```less
choco install terraform-docs
```

Stable binaries are also available on the [releases](https://github.com/terraform-docs/terraform-docs/releases) page. To install, download the binary for your platform from "Assets" and place this into your `$PATH`:

```less
curl -Lo ./terraform-docs.tar.gz https://github.com/terraform-docs/terraform-docs/releases/download/v0.18.0/terraform-docs-v0.18.0-$(uname)-amd64.tar.gz
tar -xzf terraform-docs.tar.gz
chmod +x terraform-docs
mv terraform-docs /usr/local/bin/terraform-docs
```

**NOTE:** Windows releases are in `ZIP` format.

The latest version can be installed using `go install` or `go get`:

```less
# go1.17+
go install github.com/terraform-docs/terraform-docs@v0.18.0
```

```less
# go1.16
GO111MODULE="on" go get github.com/terraform-docs/terraform-docs@v0.18.0
```

**NOTE:** please use the latest Go to do this, minimum `go1.16` is required.

This will put `terraform-docs` in `$(go env GOPATH)/bin`. If you encounter the error `terraform-docs: command not found` after installation then you may need to either add that directory to your `$PATH` as shown [here](https://golang.org/doc/code.html#GOPATH) or do a manual installation by cloning the repo and run `make build` from the repository which will put `terraform-docs` in:

```less
$(go env GOPATH)/src/github.com/terraform-docs/terraform-docs/bin/$(uname | tr '[:upper:]' '[:lower:]')-amd64/terraform-docs
```

## Usage

### Running the binary directly

To run and generate documentation into README within a directory:

```less
terraform-docs markdown table --output-file README.md --output-mode inject /path/to/module
```

Check [`output`](https://terraform-docs.io/user-guide/configuration/output/) configuration for more details and examples.

### Using docker

terraform-docs can be run as a container by mounting a directory with `.tf` files in it and run the following command:

```less
docker run --rm --volume "$(pwd):/terraform-docs" -u $(id -u) quay.io/terraform-docs/terraform-docs:0.18.0 markdown /terraform-docs
```

If `output.file` is not enabled for this module, generated output can be redirected back to a file:

```less
docker run --rm --volume "$(pwd):/terraform-docs" -u $(id -u) quay.io/terraform-docs/terraform-docs:0.18.0 markdown /terraform-docs > doc.md
```

**NOTE:** Docker tag `latest` refers to *latest* stable released version and `edge` refers to HEAD of `master` at any given point in time.

### Using GitHub Actions

To use terraform-docs GitHub Action, configure a YAML workflow file (e.g. `.github/workflows/documentation.yml`) with the following:

```less
name: Generate terraform docs
on:
  - pull_request

jobs:
  docs:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
      with:
        ref: ${{ github.event.pull_request.head.ref }}

    - name: Render terraform docs and push changes back to PR
      uses: terraform-docs/gh-actions@main
      with:
        working-dir: .
        output-file: README.md
        output-method: inject
        git-push: "true"
```

Read more about [terraform-docs GitHub Action](https://github.com/terraform-docs/gh-actions) and its configuration and examples.

### pre-commit hook

With pre-commit, you can ensure your Terraform module documentation is kept up-to-date each time you make a commit.

First [install pre-commit](https://pre-commit.com/#install) and then create or update a `.pre-commit-config.yaml` in the root of your Git repo with at least the following content:

```less
repos:
  - repo: https://github.com/terraform-docs/terraform-docs
    rev: "v0.18.0"
    hooks:
      - id: terraform-docs-go
        args: ["markdown", "table", "--output-file", "README.md", "./mymodule/path"]
```

Then run:

```less
pre-commit install
pre-commit install-hooks
```

Further changes to your module's `.tf` files will cause an update to documentation when you make a commit.

## Configuration

terraform-docs can be configured with a yaml file. The default name of this file is `.terraform-docs.yml` and the path order for locating it is:

1. root of module directory
    
2. `.config/` folder at root of module directory
    
3. current directory
    
4. `.config/` folder at current directory
    
5. `$HOME/.tfdocs.d/`
    

```less
formatter: "" # this is required

version: ""

header-from: main.tf
footer-from: ""

recursive:
  enabled: false
  path: modules
  include-main: true

sections:
  hide: []
  show: []

content: ""

output:
  file: ""
  mode: inject
  template: |-
    <!-- BEGIN_TF_DOCS -->
    {{ .Content }}
    <!-- END_TF_DOCS -->

output-values:
  enabled: false
  from: ""

sort:
  enabled: true
  by: name

settings:
  anchor: true
  color: true
  default: true
  description: false
  escape: true
  hide-empty: false
  html: true
  indent: 2
  lockfile: true
  read-comments: true
  required: true
  sensitive: true
  type: true
```

## Content Template

Generated content can be customized further away with `content` in configuration. If the `content` is empty the default order of sections is used.

Compatible formatters for customized content are `asciidoc` and `markdown`. `content` will be ignored for other formatters.

`content` is a Go template with following additional variables:

* `{{ .Header }}`
    
* `{{ .Footer }}`
    
* `{{ .Inputs }}`
    
* `{{ .Modules }}`
    
* `{{ .Outputs }}`
    
* `{{ .Providers }}`
    
* `{{ .Requirements }}`
    
* `{{ .Resources }}`
    

and following functions:

* `{{ include "relative/path/to/file" }}`
    

These variables are the generated output of individual sections in the selected formatter. For example `{{ .Inputs }}` is Markdown Table representation of *inputs* when formatter is set to `markdown table`.

Note that sections visibility (i.e. `sections.show` and `sections.hide`) takes precedence over the `content`.

Additionally there's also one extra special variable avaialble to the `content`:

* `{{ .Module }}`
    

As opposed to the other variables mentioned above, which are generated sections based on a selected formatter, the `{{ .Module }}` variable is just a `struct` representing a [Terraform module](https://pkg.go.dev/github.com/terraform-docs/terraform-docs/terraform#Module).

```less
content: |-
  Any arbitrary text can be placed anywhere in the content

  {{ .Header }}

  and even in between sections

  {{ .Providers }}

  and they don't even need to be in the default order

  {{ .Outputs }}

  include any relative files

  {{ include "relative/path/to/file" }}

  {{ .Inputs }}

  # Examples

  ```hcl
  {{ include "examples/foo/main.tf" }}
  ```

  ## Resources

  {{ range .Module.Resources }}
  - {{ .GetMode }}.{{ .Spec }} ({{ .Position.Filename }}#{{ .Position.Line }})
  {{- end }}
```

## Build on top of terraform-docs

terraform-docs primary use-case is to be utilized as a standalone binary, but some parts of it is also available publicly and can be imported in your project as a library.

```less
import (
    "github.com/terraform-docs/terraform-docs/format"
    "github.com/terraform-docs/terraform-docs/print"
    "github.com/terraform-docs/terraform-docs/terraform"
)

// buildTerraformDocs for module root `path` and provided content `tmpl`.
func buildTerraformDocs(path string, tmpl string) (string, error) {
    config := print.DefaultConfig()
    config.ModuleRoot = path // module root path (can be relative or absolute)

    module, err := terraform.LoadWithOptions(config)
    if err != nil {
        return "", err
    }

    // Generate in Markdown Table format
    formatter := format.NewMarkdownTable(config)

    if err := formatter.Generate(module); err != nil {
        return "", err
    }

    // // Note: if you don't intend to provide additional template for the generated
    // // content, or the target format doesn't provide templating (e.g. json, yaml,
    // // xml, or toml) you can use `Content()` function instead of `Render()`.
    // // `Content()` returns all the sections combined with predefined order.
    // return formatter.Content(), nil

    return formatter.Render(tmpl)
}
```

## Plugin

Generated output can be heavily customized with [`content`](https://terraform-docs.io/user-guide/configuration/content/), but if using that is not enough for your use-case, you can write your own plugin.

In order to install a plugin the following steps are needed:

* download the plugin and place it in `~/.tfdocs.d/plugins` (or `./.tfdocs.d/plugins`)
    
* make sure the plugin file name is `tfdocs-format-<NAME>`
    
* modify [`formatter`](https://terraform-docs.io/user-guide/configuration/formatter/) of `.terraform-docs.yml` file to be `<NAME>`
    

**Important notes:**

* if the plugin file name is different than the example above, terraform-docs won't be able to to pick it up nor register it properly
    
* you can only use plugin thorough `.terraform-docs.yml` file and it cannot be used with CLI arguments
    

To create a new plugin create a new repository called `tfdocs-format-<NAME>` with following `main.go`:

```less
package main

import (
    _ "embed" //nolint

    "github.com/terraform-docs/terraform-docs/plugin"
    "github.com/terraform-docs/terraform-docs/print"
    "github.com/terraform-docs/terraform-docs/template"
    "github.com/terraform-docs/terraform-docs/terraform"
)

func main() {
    plugin.Serve(&plugin.ServeOpts{
        Name:    "<NAME>",
        Version: "0.1.0",
        Printer: printerFunc,
    })
}

//go:embed sections.tmpl
var tplCustom []byte

// printerFunc the function being executed by the plugin client.
func printerFunc(config *print.Config, module *terraform.Module) (string, error) {
    tpl := template.New(config,
        &template.Item{Name: "custom", Text: string(tplCustom)},
    )

    rendered, err := tpl.Render("custom", module)
    if err != nil {
        return "", err
    }

    return rendered, nil
}
```

Please refer to [tfdocs-format-template](https://github.com/terraform-docs/tfdocs-format-template) for more details. You can create a new repository from it by clicking on `Use this template` button.

## Documentation

* **Users**
    
    * Read the [User Guide](https://terraform-docs.io/user-guide/introduction/) to learn how to use terraform-docs
        
    * Read the [Formats Guide](https://terraform-docs.io/reference/terraform-docs/) to learn about different output formats of terraform-docs
        
    * Refer to [Config File Reference](https://terraform-docs.io/user-guide/configuration/) for all the available configuration options
        
* **Developers**
    
    * Read [Contributing Guide](https://github.com/terraform-docs/terraform-docs/blob/master/CONTRIBUTING.md) before submitting a pull request
        

Visit [our website](https://terraform-docs.io/) for all documentation.

## Community

* Discuss terraform-docs on [Slack](https://slack.terraform-docs.io/)
    

## License

MIT License - Copyright (c) 2021 The terraform-docs Authors.
