Terraform moduleのdoc出力にはTerraform-docsを使おう

# tl;dr 
- Terraformのmoduleのdocumentを書くのにTerraform-docsが便利だった。

## はじめに
Terraformを書いていくうちに複数のresourceを<a hred="https://www.terraform.io/docs/modules/usage.html">module</a>機能でまとめて再利用出来るようにすることはよくあると思います。　ただmoduleはユーザーがまとめたものなので、完全に一人で作業するのならば良いと思いますが、チームでの作業ではparameterがどのように使えるかというのはdocumentなどに残すことになると思います。ただその際にparameterやoutputなどの機械的な情報の説明を書くのは非常に手間です。doc化するときにTerraform-docsを利用すると非常に便利だったので紹介します。

## Terraform-docs
- Terraform-docsはアクセス分析サービスを提供している<a href="https://segment.com/">Segment</a>社がOSSとして公開している(ただ現在メンテしているのは<a hred="https://getcloudnative.io/">getcloudnative</a>という団体っぽい？)Go製のツールです。
- repo
    - https://github.com/segmentio/terraform-docs
 
### Install
- Go製のツールなので `go get` をするか Macならば `brew` でinstallが出来ます。
- Go get
    - `go get github.com/segmentio/terraform-docs`
- brew
    - `brew install terraform-docs`

### 使い方
- 公式の<a href="https://github.com/segmentio/terraform-docs/tree/master/examples">example<a/>があるのでこれを参考に説明します。
- main.tf,output.tf,variables.tfの3つのファイルがあります。

```shell-session

├── main.tf
├── outputs.tf
└── variables.tf
```
- コマンド
    - `terraform-docs {documentの形式} {出力したいdocがあるmodule}`
    - e.g `terraform-docs markdown ./examples`

#### 出力結果

```markdown
$ terraform-docs markdown ./examples
Usage:

module "foo" {
  source = "github.com/foo/bar"

  id   = "1234567890"
  name = "baz"

  zones = ["us-east-1", "us-west-1"]

  tags = {
    Name         = "baz"
    Created-By   = "first.last@email.com"
    Date-Created = "20180101"
  }
}

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|:----:|:-----:|:-----:|
| input\_with\_underscores | A variable with underscores. | string | - | yes |
| list-1 | It's list number one. | list | `<list>` | no |
| list-2 | It's list number two. | list | - | yes |
| list-3 | - | list | `<list>` | no |
| map-1 | It's map number one. | map | `<map>` | no |
| map-2 | It's map number two. | map | - | yes |
| map-3 | - | map | `<map>` | no |
| string-1 | It's string number one. | string | `bar` | no |
| string-2 | It's string number two. | string | - | yes |
| string-3 | - | string | `` | no |
| unquoted | - | string | - | yes |

## Outputs

| Name | Description |
|------|-------------|
| output-1 | It's output number one. |
| output-2 | It's output number two. |
| unquoted | It's unquoted output. |
```

### Markdown
Usage:

module "foo" {
  source = "github.com/foo/bar"

  id   = "1234567890"
  name = "baz"

  zones = ["us-east-1", "us-west-1"]

  tags = {
    Name         = "baz"
    Created-By   = "first.last@email.com"
    Date-Created = "20180101"
  }
}

## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|:----:|:-----:|:-----:|
| input\_with\_underscores | A variable with underscores. | string | - | yes |
| list-1 | It's list number one. | list | `<list>` | no |
| list-2 | It's list number two. | list | - | yes |
| list-3 | - | list | `<list>` | no |
| map-1 | It's map number one. | map | `<map>` | no |
| map-2 | It's map number two. | map | - | yes |
| map-3 | - | map | `<map>` | no |
| string-1 | It's string number one. | string | `bar` | no |
| string-2 | It's string number two. | string | - | yes |
| string-3 | - | string | `` | no |
| unquoted | - | string | - | yes |

## Outputs

| Name | Description |
|------|-------------|
| output-1 | It's output number one. |
| output-2 | It's output number two. |
| unquoted | It's unquoted output. |


### 説明
- module内にあるoutputとinputの `Name`, `Description`, `Default`,`Type`, `Value` の値をMarkdownやJsonの形式に変換して吐き出すことが出来ます。
- 使い方のtext書く場合はmain.tfをという名前のファイルを用意して、コメントで使い方を記入するとgenerateされます。


#### main.tf

```hcl
/**
 * Usage:
 *
 * module "foo" {
 *   source = "github.com/foo/bar"
 *   
 *   id   = "1234567890"
 *   name = "baz"
 *   
 *   zones = ["us-east-1", "us-west-1"]
 *   
 *   tags = {
 *     Name         = "baz"
 *     Created-By   = "first.last@email.com"
 *     Date-Created = "20180101"
 *   }
 * }
 */
```

#### variables.tf

```hcl
variable unquoted {}

variable "string-3" {
  default = ""
}

variable "string-2" {
  description = "It's string number two."
  type        = "string"
}

// It's string number one.
variable "string-1" {
  default = "bar"
}

variable "map-3" {
  default = {}
}

variable "map-2" {
  description = "It's map number two."
  type        = "map"
}

// It's map number one.
variable "map-1" {
  default = {
    a = 1
    b = 2
    c = 3
  }

  type = "map"
}

variable "list-3" {
  default = []
}

variable "list-2" {
  description = "It's list number two."
  type        = "list"
}

// It's list number one.
variable "list-1" {
  default = ["a", "b", "c"]
  type    = "list"
}

// A variable with underscores.
variable "input_with_underscores" {}
```

#### output.tf

```hcl
output unquoted {
  description = "It's unquoted output."
  value       = ""
}

output "output-2" {
  description = "It's output number two."
  value       = "2"
}

// It's output number one.
output "output-1" {
  value = "1"
}
```

## おわりに
- Terraform-docsを知った理由は<a href="https://registry.terraform.io/">Terraform module registry</a>で公開されているmoduleのdocの出力によく使われていることでした。Terraformはエコシステムやコミュニティが非常に拡大し始めていています。このような便利なツールがもっと増えてくるといいですね！