precondition / postcondition — ライフサイクル中の条件検証

1. 概要

  • preconditionpostconditionとは何か
  • lifecycleブロック内での定義方法
  • precondition(apply前チェック)の使い方
  • postcondition(apply後チェック)の使い方
  • checkブロックとの使い分け

preconditionはリソースの作成・更新前に、postcondition作成・更新後に条件を検証します。条件が満たされない場合はapplyをエラーで中断します。


2. precondition / postcondition vs check ブロック

比較precondition/postconditioncheckブロック
配置場所resource/dataのlifecycleブロック内トップレベル
失敗時の挙動エラーでapplyを中断警告のみ(続行)
参照できる値親リソース・dataの属性のみ独自dataを持てる
用途必須条件の強制外部依存・状態確認

3. 基本構文

resource "リソース" "名前" {
  # ...

  lifecycle {
    precondition {
      condition     = <apply前に検証する式>
      error_message = "<エラーメッセージ>"
    }

    postcondition {
      condition     = <apply後に検証する式>
      error_message = "<エラーメッセージ>"
    }
  }
}

4. precondition — apply前の条件チェック

terraform {
  required_version = ">= 1.9"
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = "ap-northeast-1"
}

variable "environment" {
  description = "環境名(dev/stg/prd)"
  type        = string
  default     = "dev"
}

variable "instance_type" {
  description = "EC2インスタンスタイプ"
  type        = string
  default     = "t3.micro"
}

data "aws_ami" "amazon_linux_2023" {
  most_recent = true
  owners      = ["amazon"]
  filter {
    name   = "name"
    values = ["al2023-ami-*-x86_64"]
  }
}

resource "aws_instance" "web" {
  ami           = data.aws_ami.amazon_linux_2023.id
  instance_type = var.instance_type

  root_block_device {
    volume_size = 20
    volume_type = "gp3"
    encrypted   = true
  }

  tags = {
    Name        = "${var.environment}-web"
    Environment = var.environment
    ManagedBy   = "terraform"
  }

  lifecycle {
    # 本番環境では小さすぎるインスタンスタイプを禁止
    precondition {
      condition     = !(var.environment == "prd" && var.instance_type == "t3.micro")
      error_message = "本番環境ではt3.micro以上のインスタンスタイプを使用してください。現在: ${var.instance_type}"
    }
  }
}

5. postcondition — apply後の状態確認

selfキーワードで作成されたリソース自身の属性を参照できます。

resource "aws_instance" "app" {
  ami           = data.aws_ami.amazon_linux_2023.id
  instance_type = var.instance_type

  root_block_device {
    volume_size = 20
    volume_type = "gp3"
    encrypted   = true
  }

  tags = {
    Name        = "${var.environment}-app"
    Environment = var.environment
    ManagedBy   = "terraform"
  }

  lifecycle {
    # apply後: インスタンスが実際に起動しているか確認
    postcondition {
      condition     = self.instance_state == "running"
      error_message = "インスタンスが起動状態ではありません。現在の状態: ${self.instance_state}"
    }
  }
}

6. outputブロックにpreconditionを使う

outputブロックにもpreconditionを設定できます。モジュールが外部に公開する値が要件を満たしているかを確認する用途に使います。

output "instance_public_ip" {
  value = aws_instance.web.public_ip

  precondition {
    condition     = aws_instance.web.public_ip != ""
    error_message = "インスタンスにパブリックIPが割り当てられていません。VPC設定を確認してください。"
  }
}

7. dataブロックにpreconditionを使う

dataブロックにもprecondition/postconditionを設定できます。

data "aws_vpc" "selected" {
  filter {
    name   = "tag:Environment"
    values = [var.environment]
  }

  lifecycle {
    postcondition {
      # 取得したVPCのCIDRが期待通りか確認
      condition     = self.cidr_block == "10.0.0.0/16"
      error_message = "VPCのCIDRが期待値と異なります。取得値: ${self.cidr_block}"
    }
  }
}

8. 複数条件を組み合わせる

variable "volume_size" {
  description = "EBSボリュームサイズ(GB)"
  type        = number
  default     = 20
}

resource "aws_instance" "db" {
  ami           = data.aws_ami.amazon_linux_2023.id
  instance_type = var.instance_type

  root_block_device {
    volume_size = var.volume_size
    volume_type = "gp3"
    encrypted   = true
  }

  tags = {
    Name        = "${var.environment}-db"
    Environment = var.environment
    ManagedBy   = "terraform"
  }

  lifecycle {
    precondition {
      condition     = var.volume_size >= 20
      error_message = "EBSボリュームは最低20GB必要です。指定値: ${var.volume_size}GB"
    }

    precondition {
      condition     = contains(["dev", "stg", "prd"], var.environment)
      error_message = "environmentはdev/stg/prdのいずれかを指定してください。"
    }
  }
}

9. 関連記事


10. まとめ

  • preconditionはapply前の条件チェック、postconditionはapply後の確認
  • 条件が満たされない場合はapplyをエラーで中断する(checkは警告のみ)
  • lifecycleブロック内に複数設定できる
  • postconditionではselfで作成されたリソース自身の属性を参照できる
  • dataブロックにも設定可能

動作確認バージョン: Terraform >= 1.2 公式ドキュメント: https://developer.hashicorp.com/terraform/language/expressions/custom-conditions