Terraform

Terraformのprecondition / postconditionで実現する宣言的アサーション

2026-04-19
NicheeLab編集部

precondition / postconditionは、リソースやデータソースなどに対して「満たすべき条件」を宣言的に埋め込む仕組みです。手続き的な検査ではなく、計画と適用のライフサイクルに沿って自動評価されます。

資格試験(上位レベルを想定)では、評価タイミングの違い、unknown値の扱い、variableのvalidationやcheckブロックとの使い分けが頻出です。実務でも「壊れないIaC」を作るための守りの仕掛けとして有効です。

precondition / postconditionの基本とねらい

preconditionは実行前(plan〜apply前段)に検証し、構成や入力が前提条件を満たしているかを保証します。postconditionは実行後(apply後段やread後)に検証し、作成・更新・取得された結果が期待と一致するかを保証します。

これらは宣言的アサーションであり、状態を変更する副作用はありません。条件に違反するとTerraformは計画もしくは適用を失敗として扱い、明示的なerror_messageをユーザーに返します。

  • 利用可能な場所: resource、data、module呼び出し、output(いずれもHCL内の該当ブロックにネストして宣言)
  • 条件式は真偽値を返す必要がある(can()やlength()などの式・関数を活用)
  • 違反時はエラー終了。警告やスキップにはできない
  • 宣言はコードに近接して保存され、ドキュメント兼ガードレールとして機能

最小例(概念)

resource "some_resource" "app" {
  # ... 引数の宣言など

  precondition {
    condition     = contains(["dev", "stg", "prod"], var.env)
    error_message = "env は dev/stg/prod のいずれかである必要があります"
  }

  postcondition {
    condition     = self.id != null
    error_message = "作成後にIDが返りませんでした(providerの応答を確認してください)"
  }
}

評価タイミングとunknown値の扱い

preconditionはplan時点で評価され、式がtrueであること(またはunknownでapply時に再評価されること)が必要です。式がfalseと確定すればplanは失敗します。unknown(計画時に未確定)の場合、計画には「apply時に検証する」旨が含まれ、applyで再評価されます。

postconditionは対象のcreate/update/readの直後に評価されます。plan時に最終値が既知でfalseと判定できる場合はplanで失敗しますが、多くの場合はapply時の実値に対して評価されます。違反してもTerraformはロールバックしません。必要に応じて構成や環境を直し、再適用します。

  • dataブロックはread後にpostconditionで検証できる(入力の妥当性はpreconditionで)
  • resourceブロックは作成/更新後にpostconditionで実測値を検証できる
  • unknownの可能性がある式はcan()やtry()で安全に包むと計画時の評価が安定する

Plan/Applyにおけるpre/postの評価位置

terraform planevaluate preconditions (true/false/unk)PLAN FAILif any falseterraform applyre-evaluate preconditions (if unk)Provider create/update/readproceed if all trueevaluate postconditions(true/false)APPLY failureif any false (no rollback)Plan/Applyにおけるpre/postの評価位置

unknownに強い書き方(can/tryの活用)

resource "some_resource" "svc" {
  name = var.name

  precondition {
    # var.labels may be null/unknown。missing key参照をcan()で保護
    condition     = can(var.labels["team"]) && length(try(var.labels["team"], "")) > 0
    error_message = "labels.team を必須にしてください"
  }
}

構文と参照ルール(self・式・エラーメッセージ)

各ブロックでprecondition/postconditionをネストし、conditionとerror_messageを指定します。conditionは真偽値に評価される必要があります。error_messageは違反時にそのままユーザーに表示されるため、改善アクションが分かる具体的な文言にしましょう。

resourceやdataのpostcondition内ではselfがそのオブジェクトの最終値を指します。precondition内のselfは計画中の値(unknownを含む)です。module呼び出しやoutputでも条件を宣言できますが、参照できるものや評価タイミングは対象ブロックに従います。

  • 式は副作用を持たない(外部API呼び出し等は不可)
  • 正規表現や型チェックにはregex()/can()/try()が便利
  • 長文の条件はlocalsで分解して可読性を確保

resource・outputでの宣言例

# resourceの例(概念)
resource "some_resource" "db" {
  name    = var.name
  version = var.version

  precondition {
    condition     = length(var.name) <= 20 && can(regex("^[a-z0-9-]+
NicheeLab を読み込み中…
quot;, var.name)) error_message = "name は20文字以内の小文字英数字とハイフンのみ許可" } postcondition { condition = self.id != null && length(tostring(self.id)) > 0 error_message = "作成後にIDが返らないのは不正です(provider・権限を確認)" } } # outputの例(URL形式の前提を宣言) output "service_url" { value = var.base_url precondition { condition = can(regex("^https?://", var.base_url)) error_message = "base_url は http(s) スキームである必要があります" } }

実務パターン集(ガードレールとしての活用)

環境ポリシーの強制: 本番は必ず暗号化やタグ付けを有効にする、といった前提をpreconditionで早期に弾きます。入力の組み合わせ(例: prodなら冗長化必須)もここで表現可能です。

結果検証: providerや外部システムの最終状態が必須条件を満たすかをpostconditionで検証します。たとえば実際に割り当てられたCIDRが許容範囲か、得られたエンドポイントが期待する形式かなどです。

  • ポリシー化できるものはmodule内に閉じ込め、呼び出し側の自由度を保ちつつ安全性を担保
  • unknownが多い属性はpostcondition側で検証し、計画を不安定にしない
  • 広域な整合性(複数リソース横断)はcheckブロックで表現するのが適切

環境ポリシーと結果検証の例(概念)

# 環境ポリシー(本番は冗長化必須)
resource "some_resource" "api" {
  replicas = var.replicas
  env      = var.env

  precondition {
    condition     = var.env != "prod" || (var.env == "prod" && var.replicas >= 2)
    error_message = "prod 環境では replicas >= 2 が必須です"
  }

  # 例: 割り当てられた識別子が所定の接頭辞を持つことを検証
  postcondition {
    condition     = can(regex("^api-", tostring(self.id)))
    error_message = "作成結果のIDがポリシーに反する(prefix 'api-' 必須)"
  }
}

pre/post と他機能の使い分け(比較表)

似た目的の仕組みとしてvariableのvalidationやcheckブロックがあり、適用範囲と評価タイミングが異なります。試験では「どこで、いつ、何を検証するか」を軸に選択肢を切り分けます。

特にpostconditionは「実際にできあがったもの」を検証できる点でuniqueです。入力だけで保証できない不変条件に適しています。

  • 入力の妥当性は validation / precondition
  • 最終結果の妥当性は postcondition
  • リソース横断の整合性は check
機能宣言先評価タイミングself等の参照
variable validationvariable ブロックplan時(入力評価時)selfなし(var.*)
preconditionresource/data/module/outputplan時(unknownはapplyで再評価)resource/dataでself可
postconditionresource/data/module/outputapply直後(read直後)resource/dataでself可
check ブロックルートモジュールplan時(unknownはapplyで再評価)selfなし(任意の式)

checkブロック(横断アサーションの例)

check "naming_convention" {
  assert {
    condition     = can(regex("^proj-[a-z0-9-]+
NicheeLab を読み込み中…
quot;, var.project_id)) error_message = "project_id は 'proj-' から始まる必要があります" } }

落とし穴と試験対策(ベストプラクティス)

postcondition違反時にTerraformは自動ロールバックしません。状態や実リソースが中途半端になり得る点を理解し、エラーメッセージに対処法(再適用、設定修正)を含めると実務で役立ちます。

unknownの取り扱いに注意。計画時に確定できない式はcan()/try()で守る、もしくはpostcondition側で検証して計画差分を安定化させます。

  • 長大・複雑な条件はlocalsで分解し、テストしやすくする
  • モジュール作者は内側で不変条件を宣言し、呼び出し側は環境前提(組織ルール)を宣言する、の分担が有効
  • error_messageは改善行動を含める(例: 具体的な許容値、関連ドキュメントへの参照)

localsで条件を分割して可読性向上

locals {
  is_valid_env     = contains(["dev", "stg", "prod"], var.env)
  is_replica_valid = var.env != "prod" || var.replicas >= 2
}

resource "some_resource" "svc" {
  replicas = var.replicas
  env      = var.env

  precondition {
    condition     = local.is_valid_env && local.is_replica_valid
    error_message = "env/replicas の組み合わせがポリシーに違反"
  }
}

問題で確認

Pro

問題 1

あるチームは、本番環境のserviceリソースについて「適用後に実際の結果として冗長化が有効であること」を必ず検証したい。入力値のチェックだけでは不十分で、providerの最終応答に対して評価したい。Terraformのどの仕組みをどこに書くのが最も適切か?

  1. 対象resourceブロック内のpostconditionで、selfの最終値を使って冗長化が有効であることを検証する
  2. variableブロックのvalidationで、replicas >= 2 を強制する
  3. checkブロックで任意の式を評価し、横断的に検証する
  4. resourceのlifecycle設定でprevent_destroyを有効化する

正解: A

実際の結果(providerが返す最終値)に基づく検証はpostconditionが適任。resource内postconditionでselfの実測値を評価できる。variableのvalidationは入力値しか見えず、checkは横断アサーション向け。prevent_destroyは削除抑止であり要件に合致しない。

よくある質問

precondition/postconditionはどのブロックで使えますか?

resource、data、module呼び出し、outputの各ブロック内で宣言できます。条件式はtrue/falseを返し、違反時はerror_messageとともに処理が失敗します。

plan時にunknownな値が含まれる条件はどうなりますか?

plan時に評価不能(unknown)の場合、計画には「apply時に検証する」旨が表示され、applyで再評価されます。不安定さを避けるにはcan()/try()で守るか、postcondition側で最終値を検証します。

postconditionが失敗したらロールバックされますか?

自動ロールバックは行われません。エラーでapplyは終了します。必要に応じて設定や環境を修正し、再適用します(providerや外部システム側の状態は手動で調整が必要な場合があります)。

この記事で学んだ内容を問題で確認しましょう

16,000問以上の問題で実力チェック

無料で問題を解いてみる
この記事の著者

NicheeLab編集部

データエンジニアリング・クラウド資格の専門家。Databricks・Snowflake等の認定資格を保有し、実務経験に基づいた問題作成・解説を行っています。NicheeLab運営。


関連記事
Terraform

Terraform HCL 構文の基礎:Block / Attribute / Expression を正しく使い分ける

Terraform Associate で頻出の HCL 構文を、ブロック・属性・式の3視点で整理。実務で迷いがちな書き...

Terraform

Terraform Authoring & Ops Pro: 上位資格の範囲と対策

上位レベルを想定したTerraformの設計・運用ドメインを整理し、実務で通用する対策を提示。モジュール設計、ステート運...

Terraform

Terraform Providers の基本: プラグイン型アーキテクチャを正しく使いこなす

Associate レベルで押さえるべき Provider の基礎、インストール、バージョニング、認証、エイリアス運用を...

Terraform

Terraform Resourceブロック徹底ガイド: 最小単位のリソース定義

Associateレベルで押さえるべきResourceブロックの構造、依存関係、メタ引数、ライフサイクル制御を実務目線で...

Terraform

Terraform Data Source徹底理解:既存リソースの参照で壊さず足す

Terraform Associate向けに、Data Sourceを用いた既存リソース参照の基本、選択基準、評価順序、...

Terraformの記事一覧 (101件)
© 2026 NicheeLab All rights reserved.