variable validationは、型制約では表しきれないビジネスルールをTerraform言語で宣言的に検査する機能です。エラーメッセージを明示でき、モジュールの再利用性と安全性を高めます。
Associateでは基本構文・評価タイミング、Proではコレクション/条件付き/unknownの扱いが頻出。実務でもmoduleの入口で落とせる設計が保守コストを下げます。
variableブロック内のvalidationは、conditionがtrueであることを要求し、falseの場合にerror_messageの内容で失敗させます。conditionはTerraform言語の式で、var.<name>を参照します。
評価タイミングは「その変数の最終値が既知になった時点」。通常はplan時に既知で評価され、結果が偽ならplan自体がエラーで停止します。値がunknown(例: data source依存)で条件結果が不定な場合は、明確にfalseと判定できない限り適用時まで猶予されます。
| 項目 | 役割 | 例 |
|---|---|---|
| type制約 | 型・簡易制約を強制 | string, number, list(string), object({...}) |
| default | 入力欠如時の既定値 | default = 443 |
| validation | 型では表せないルールを宣言 | AMIは"ami-"で開始、ポート1..65535 など |
評価パイプライン(概念図)
最小構成の例
variable "image_id" {
type = string
validation {
condition = can(regex("^ami-[0-9a-f]+
NicheeLab を読み込み中…
quot;, var.image_id)) error_message = "image_id は 'ami-' で始まる有効なAMI IDを指定してください。例: ami-0123abcd"; } }
validationブロックはcondition(必須)とerror_message(必須)から構成されます。conditionは純粋式であり、関数・演算子・for式を使って書けます。エラーメッセージは利用者が即修正できる粒度で短く具体的に。
正規表現や数値範囲など失敗しやすい判定はcan()でガードし、不正形式でregexがエラーになるのを防ぎます。重い計算や大きなコレクション走査は最小限に保ち、読みやすく維持しやすい表現を心がけます。
| 関数 | 用途 | 注意点 |
|---|---|---|
| regex, can | 書式・パターン検証 | regexは不一致時にfalse、パターン不正時はエラー→canで防御 |
| startswith, endswith | 接頭/接尾の簡易検証 | 単純なときはregexより可読 |
| contains | 要素/値の包含判定 | セット許容値の検査と相性が良い |
| alltrue, anytrue | ブール配列の総合判定 | for式と組み合わせると強力 |
| length, distinct | 長さ・一意性の検査 | 重複禁止の表現によく使う |
エラーメッセージ設計の観点
よくあるガードの書き方
variable "account_id" {
type = string
validation {
condition = can(regex("^[0-9]{12}
NicheeLab を読み込み中…
quot;, var.account_id))
error_message = "account_id は12桁の数字で指定してください。";
}
}
variable "port" {
type = number
validation {
condition = var.port >= 1 && var.port <= 65535
error_message = "port は1〜65535の範囲で指定してください。";
}
}シンプルなパターンは可読性を重視します。接頭辞検査はstartswith、厳密な形式はregex、レンジは単純な比較で表現します。
regexはメンテナンス性を損ねやすいので、必要十分に留め、代替があればなるべくstartswithやlengthで置き換えます。
| 目的 | 条件式の例 | エラーメッセージ例 |
|---|---|---|
| AMI形式 | can(regex("^ami-[0-9a-f]+
NicheeLab を読み込み中…
| ami は 'ami-'で始まる16進IDを指定してください。 |
| 名前の最小長 | length(var.name) >= 3 | name は3文字以上で指定してください。 |
| 副本数の範囲 | var.replicas >= 2 && var.replicas <= 10 | replicas は2〜10の範囲で指定してください。 |
| 環境の列挙 | contains(["dev","stg","prod"], var.env) | env は dev/stg/prod のいずれかです。 |
パターン選択の目安
サンプル: ポートとAMI
variable "port" {
type = number
validation {
condition = var.port >= 1 && var.port <= 65535
error_message = "port は1〜65535です。";
}
}
variable "ami" {
type = string
validation {
condition = can(regex("^ami-[0-9a-f]+
NicheeLab を読み込み中…
quot;, var.ami))
error_message = "ami は 'ami-'で始まる有効なIDを指定してください。";
}
}listやmap/objectではfor式とalltrue/anytrueで各要素をまとめて検査します。重複禁止はdistinctで実現できます。
タグやキーの長さ・文字種制約などは読みやすい単位に分解して条件式を構成すると保守しやすくなります。
| パターン | 条件式(抜粋) | 補足 |
|---|---|---|
| 要素の書式検査 | alltrue([for s in var.subnets : startswith(s, "subnet-")]) | 単純書式はregexより可読 |
| 重複禁止 | length(distinct(var.ids)) == length(var.ids) | distinctで一意性を検査 |
| 必須キー含有 | alltrue([for k in ["Name","Owner"] : contains(keys(var.tags), k)]) | keys(map)とcontainsの組合せ |
for式で要素を検査する流れ
サンプル: サブネットIDとタグ
variable "subnets" {
type = list(string)
validation {
condition = length(var.subnets) > 0 && alltrue([for s in var.subnets : startswith(s, "subnet-")])
error_message = "subnets は1件以上、各要素は 'subnet-'で始まるIDで指定してください。";
}
}
variable "tags" {
type = map(string)
validation {
condition = alltrue([for k, v in var.tags : length(k) <= 128 && length(v) <= 256])
error_message = "tags のキーは128文字以内、値は256文字以内で指定してください。";
}
}
variable "names" {
type = list(string)
validation {
condition = length(distinct(var.names)) == length(var.names)
error_message = "names は重複のない値で指定してください。";
}
}条件付き検証は「含意」で表現すると読みやすくなります。例えばprodのときだけ強い制約を課すなら、env != "prod" || 厳格条件 の形にします。
unknown値(計画時に未確定の値)が関係する場合、Terraformは条件が明確にfalseと断定できない限りエラーにしません。regexなど不正形式で式自体が評価エラーになる恐れがある箇所はcan()で包んで安全に。
| 状況 | Terraformの挙動 | 対策/書き方 |
|---|---|---|
| prodのみ厳格 | 条件結果がtrue/falseで確定し評価 | env != "prod" || 厳格条件 |
| unknownが混入 | 結果が不明なら計画は続行、適用時に再評価 | can()や安全な関数でガード |
| 不正パターン | 式の評価自体がエラーで停止 | regexなどはcan()を併用 |
unknownの評価イメージ
prodのときだけ強い制約をかける
variable "env" {
type = string
validation {
condition = contains(["dev","stg","prod"], var.env)
error_message = "env は dev/stg/prod のいずれかです。";
}
}
variable "az_count" {
type = number
validation {
condition = var.env != "prod" || var.az_count >= 2
error_message = "env=prod の場合、az_count は2以上である必要があります。";
}
}試験では、type制約とvalidationの役割差、precondition/postconditionとの違い、評価タイミング、unknownの扱いが問われがちです。validationは入力値に対する静的な検査であり、リソース属性やデータソース結果を参照できません。
アンチパターンは、複雑な正規表現で可読性を損なう、外部状態に依存させる、エラーメッセージが抽象的すぎる、など。まず型で絞り、シンプルな関数で十分な安全性を確保しましょう。
| 機能 | 定義場所 | 実行タイミング | 主な用途 |
|---|---|---|---|
| type制約 | variable | 値決定時(plan前段) | 型・スキーマの基本制約 |
| validation | variable | 値が既知になった時(主にplan時) | ビジネスルールの宣言的検査 |
| pre/postcondition | resourceやmodule呼び出し | plan/applyでの状態検査 | リソース属性・モジュール出力の検査 |
Do/Don'tメモ
[OK] typeで大枠 → validationで細則
[OK] envに応じた含意で条件分岐
[NG] resource属性やdataをvalidationで参照
[NG] 複雑すぎるregexで可読性を損なうアンチパターン修正例
# 悪い例(resource属性参照は不可)
# variable "size" {
# validation {
# condition = var.size <= aws_instance.example.cpu_core_count # 参照不可
# error_message = "...";
# }
# }
# 良い例: 入力間の関係をvalidationで、リソース状態はpreconditionで
variable "size" {
type = number
validation {
condition = var.size >= 1 && var.size <= 64
error_message = "size は1〜64で指定してください。";
}
}
# (参考)resource側での状態検査はprecondition/postconditionを使用
# resource "aws_instance" "example" {
# # ...
# lifecycle {
# precondition {
# condition = self.cpu_core_count >= var.size
# error_message = "インスタンスタイプが size を満たしていません。";
# }
# }
# }Associate / Pro
問題 1
モジュールに env と instance_count の2つの変数があります。env=prod のときだけ instance_count を3以上に制限し、それ以外は制限しないようにしたい。最も適切なvalidationはどれか。
正解: A
envに応じた条件付き制約は含意で表現するのが定石。env != "prod" || var.instance_count >= 3 はprod以外を無条件に許し、prod時のみ下限を課す。Bは常に3以上で不適切、Cはdev/stgに制限がかかる誤り、Dは入力値の整合はvariable側で落とすのが適切(状態検査はpre/postcondition)。
validationはいつ評価されますか? planとapplyのどちらですか?
値が既知であればplanの時点で評価され、falseならplanがエラーで止まります。値がunknownで結果が不定な場合は、apply段階で再評価されます。
複数のvalidationブロックを1つの変数に定義できますか?
可能です。ただし条件が増えるほど可読性が落ちるため、関連する検査は1つの読みやすい式にまとめるか、論理的に分けた少数のブロックに留めるのが実務的です。
リソース属性やデータソースの値をvalidationで参照できますか?
いいえ。validationは入力変数の検査であり、resourceやdataの属性は参照できません。入力間の関係はvalidationで、リソース状態の整合はpre/postconditionで検査します。
NicheeLab編集部
データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。
Terraform HCL 構文の基礎:Block / Attribute / Expression を正しく使い分ける
Terraform Associate で頻出の HCL 構文を、ブロック・属性・式の3視点で整理。実務で迷いがちな書き...
Terraform Authoring & Ops Pro: 上位資格の範囲と対策
上位レベルを想定したTerraformの設計・運用ドメインを整理し、実務で通用する対策を提示。モジュール設計、ステート運...
Terraform Providers の基本: プラグイン型アーキテクチャを正しく使いこなす
Associate レベルで押さえるべき Provider の基礎、インストール、バージョニング、認証、エイリアス運用を...
Terraform Resourceブロック徹底ガイド: 最小単位のリソース定義
Associateレベルで押さえるべきResourceブロックの構造、依存関係、メタ引数、ライフサイクル制御を実務目線で...
Terraform Data Source徹底理解:既存リソースの参照で壊さず足す
Terraform Associate向けに、Data Sourceを用いた既存リソース参照の基本、選択基準、評価順序、...