IaCでインフラを管理していると、構築手順書が不要になります。構築手順がコードで表現されているからです。では、一切のドキュメントが不要かというと、そんなことはありません。設定値の説明などは必要になるので、使い方のドキュメントは必要になります。
かんたんDevOpsではIaCツールとしてTerraformを使っているんですが、terraform-docsというツールを使うと、そこそこのドキュメントがツールによって生成できることがわかりました。っということで、さっそく使ってみます。
terraform-docs???
Terraformモジュールからドキュメントを生成するツールです。使っているモジュールがどのバージョンに依存しているのか、Input/Outputに渡すべき値なんかはわざわざ手で修正していると面倒ですし、修正漏れの原因になります。コードから自動で収集できる情報は自動化しておきたいですよね。
インストール
パッケージマネージャを使うか、コンテナを使うか、バイナリを直接ダウンロードするか、go install go getするとよさそうです。私の検証環境はMacなのでHomebrewを利用してインストールしました。
使ってみる
今回は対象の環境にplanしたりapplyしたりはしないので、適当なHCLを用意します。
$ tree . . ├── main.tf ├── outputs.tf ├── providers.tf └── variables.tf 1 directory, 4 files
main.tf
resource "random_string" "random" {
length = 4
lower = true
upper = false
numeric = true
special = false
}
locals {
# var.nameがnullだったらインスタンス名を`neko-${random_string}`にする
name = var.name == null ? "neko-${random_string.random.result}" : var.name
}
module "ec2_instance" {
source = "terraform-aws-modules/ec2-instance/aws"
version = "4.3.0"
name = local.name
ami = var.ami_id
instance_type = var.instance_type
monitoring = var.monitoring
subnet_id = var.subnet_id
}
outputs.tf
output "instance_id" {
description = "インスタンスID"
value = module.ec2_instance.id
}
providers.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "4.57.1"
}
}
}
variables.tf
type = string
default = null
description = "インスタンス名"
}
variable "ami_id" {
type = string
description = "AMI ID. AMI IDの取得方法は[こちら](#ami-idを取得)"
}
variable "instance_type" {
type = string
description = "インスタンスタイプ. インスタンスタイプの一覧は[こちら](https://aws.amazon.com/jp/ec2/instance-types/)"
}
variable "monitoring" {
type = bool
default = false
description = "EC2のモニタリングを有効化するか. モニタリングの説明については[こちら](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/monitoring_ec2.html)"
}
variable "subnet_id" {
type = string
description = "EC2を起動するサブネットを指定. サブネットIDの取得方法は[こちら](#subnet-idを取得)"
}
カレントディレクトリのREADME.mdを生成してみます。
terraform-docs markdown table --output-file README.md --output-mode inject .
サブコマンドのmarkdownはMarkdownフォーマットのドキュメントを生成するという意味です。他にもJSONやTOMLなど、様々なフォーマットに対応しています。どんなフォーマットに対応しているかはterraform-docs --helpで確認できます。
markdownサブコマンドの引数にtableを指定しています。テーブルでinput/outputの説明が出力されますtable以外にはdocumentがあります。markdownサブコマンドのヘルプはterraform markdown --helpで確認できます。
--output-fileは文字通り出力先のファイル名です。今回はREADME.mdファイルに出力します。
--output-modeはinjectを指定しています。injectは<!-- BEGIN_TF_DOCS -->から<!-- END_TF_DOCS -->の間を置き換えてくれます。つまり、生成されたドキュメント以外(手書きのものなど)は<!-- {BEGIN,END}_TF_DOCS -->外に置いておけば維持できます。injectの他にはreplaceがありますが、これは全て置き換わってしまいます。ドキュメントに人の手を入れたくない時などに使えばいいでしょうか。
その他のオプションもterraform-docs markdown --helpで確認できますので、ご確認ください。
実際に生成されたREADME.mdは以下
<!-- BEGIN_TF_DOCS --> ## Requirements | Name | Version | |------|---------| | <a name="requirement_aws"></a> [aws](#requirement\_aws) | 4.57.1 | ## Providers | Name | Version | |------|---------| | <a name="provider_random"></a> [random](#provider\_random) | 3.4.3 | ## Modules | Name | Source | Version | |------|--------|---------| | <a name="module_ec2_instance"></a> [ec2\_instance](#module\_ec2\_instance) | terraform-aws-modules/ec2-instance/aws | 4.3.0 | ## Resources | Name | Type | |------|------| | [random_string.random](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/string) | resource | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | <a name="input_ami_id"></a> [ami\_id](#input\_ami\_id) | AMI ID. AMI IDの取得方法は[こちら](#ami-idを取得) | `string` | n/a | yes | | <a name="input_instance_type"></a> [instance\_type](#input\_instance\_type) | インスタンスタイプ. インスタンスタイプの一覧は[こちら](https://aws.amazon.com/jp/ec2/instance-types/) | `string` | n/a | yes | | <a name="input_monitoring"></a> [monitoring](#input\_monitoring) | EC2のモニタリングを有効化するか. モニタリングの説明については[こちら](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/monitoring_ec2.html) | `bool` | `false` | no | | <a name="input_name"></a> [name](#input\_name) | インスタンス名 | `string` | `null` | no | | <a name="input_subnet_id"></a> [subnet\_id](#input\_subnet\_id) | EC2を起動するサブネットを指定. サブネットIDの取得方法は[こちら](#subnet-idを取得) | `string` | n/a | yes | ## Outputs | Name | Description | |------|-------------| | <a name="output_instance_id"></a> [instance\_id](#output\_instance\_id) | インスタンスID | <!-- END_TF_DOCS -->
プレビューしてみるとこんな感じ

今度はterraform.tfvarsを生成してみます。
terraform-docs tfvars hcl --output-file terraform.tfvars --output-template "// BEGIN_TF_DOCS\n{{ .Content }}\n// END_TF_DOCS" .
今回、--output-templateを指定して<!-- BEGIN_TF_DOCS -->を// BEGIN_TF_DOCSに変更しています。tfvarsのコメントフォーマットに合わせた感じですね。いやいや、こうやったらいいんじゃね?っというのがあれば教えて欲しいです。
ちなみに、以下のようにするとコメントはつかなくなりました。初回生成するだけならこれでもいいかもしれないです。
terraform-docs tfvars hcl . > terraform.tfvars
まとめ
細かい設定なんかは割愛しましたが、ドキュメントを生成したいだけならこれで十分です。もし、もう少し凝ったことをやりたい場合はこちらを参考にしてみてください。GitHubの方のドキュメントにはGitのpre-commitで実行する方法や、GitHub Actionsを使って自動で生成する方法も記載されています。
