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を使って自動で生成する方法も記載されています。