02. 基本構文
HCL の文法は驚くほどシンプルで、覚えるのは 2 種類だけ です。引数 (argument) と ブロック (block)。すべてはこの組み合わせ。
HCL は 2 種類の構造しかない
# これが「引数」(argument)
image_id = "ami-abc123"
# これが「ブロック」(block)
resource "aws_instance" "web" {
ami = "ami-abc123"
instance_type = "t3.micro"
}
引数は NAME = VALUE の代入。ブロックは TYPE [LABEL] [LABEL] { ... } の波カッコ構造。これだけで Terraform の設定全体が表現されます。
引数(argument)
引数は 名前 = 値 の形。値は文字列・数値・真偽値・リスト・マップ・オブジェクト・null など、第 4 章で詳しく扱う 型 に従います。
name = "my-app" # 文字列
count = 3 # 数値
enabled = true # 真偽値
zones = ["a", "b", "c"] # リスト
tags = { # マップ/オブジェクト
Env = "prod"
Team = "platform"
}
description = null # 値なし
ブロック(block)
ブロックは「何かのまとまり」を表します。以下、典型的なブロックの形を読み解きます。
resource "aws_instance" "web" {
ami = "ami-abc123"
instance_type = "t3.micro"
}
| 位置 | 意味 | 例 |
|---|---|---|
| ブロックタイプ | このブロックの種類 | resource |
| ラベル 1 | リソースタイプ(プロバイダが定義) | "aws_instance" |
| ラベル 2 | このリソースの呼び名(自分で決める) | "web" |
{ ... } | ボディ(中身は引数や入れ子ブロック) | ― |
ラベルの数や種類はブロックタイプによって決まっています。resource はラベル 2 つ、locals はラベル 0、provider はラベル 1。それぞれの章で出てきたら確認すれば OK。
入れ子ブロック
ブロックは中にさらにブロックを置けます。たとえば EC2 のルートディスク設定:
resource "aws_instance" "web" {
ami = "ami-abc123"
instance_type = "t3.micro"
root_block_device { # ← 入れ子ブロック
volume_size = 30
volume_type = "gp3"
encrypted = true
}
tags = {
Name = "web"
}
}
識別子の規則
引数名・ブロックラベル・変数名などに使える「識別子」のルール:
- 使える文字: 英数字・アンダースコア(
_)・ハイフン(-) - 先頭は数字以外
- 大文字小文字を区別する
- 慣習: snake_case(
web_server、db_password)
コメント
# これが推奨スタイル(シェル風)
// これも書ける(C++ 風、ただし慣習的には # を使う)
/*
複数行は
/* */ で囲む
*/
文字列とヒアドキュメント
普通の文字列
name = "production"
path = "C:\\Users\\me" # バックスラッシュは \\
note = "line1\nline2" # \n で改行
ヒアドキュメント(複数行文字列)
user_data = <<EOT
#!/bin/bash
yum update -y
yum install -y nginx
systemctl enable nginx
systemctl start nginx
EOT
インデントを揃えたければ <<-EOT(ハイフン付き)。閉じタグの位置までの共通インデントが自動で除去されます。
user_data = <<-EOT
#!/bin/bash
yum update -y
yum install -y nginx
EOT
${} 補間
文字列の中に変数や式の結果を埋め込む構文。Terraform で もっとも使う書き方の 1 つ。
name = "${var.project}-web" # 文字列の中に変数
arn = "arn:aws:s3:::${var.bucket}/*" # 任意の式を ${} で囲む
# 文字列が ${} 1 つだけの時は、生のまま書ける(こちらが推奨)
arn = aws_s3_bucket.this.arn # ${aws_s3_bucket.this.arn} と同じ
スタイル
Terraform 0.12 以降は 「文字列の合成が必要な時だけ
${} を使う」 のが推奨です。name = "${var.x}" のように単独で使うのは冗長で、警告も出ます。
ファイル分割は機能でなく役割で
Terraform は同じディレクトリの .tf をすべてマージして 1 つの構成として読みます。なので分割は完全に 読みやすさのため。慣習的なファイル名:
| ファイル | 中身 |
|---|---|
terraform.tf | terraform { required_version, required_providers, backend } |
providers.tf | provider "..." { ... } |
variables.tf | variable "..." { ... } |
locals.tf | locals { ... } |
main.tf | 主要な resource / data / module |
outputs.tf | output "..." { ... } |