条件式(三項演算子) — if文の代わりに使う条件分岐

1. 概要

  • Terraformの三項演算子(条件式)の基本構文
  • if文がない代わりに条件式を使うパターン
  • countfor_eachとの組み合わせ(オプションリソース)
  • よく使う実用パターン集
  • ネストした条件式(注意点)

Terraformにはif文がなく、代わりに条件式(三項演算子)を使います。条件 ? 真の値 : 偽の値という構文で、環境やフラグに応じて設定値やリソース数を切り替えられます。


2. 基本構文

condition ? true_val : false_val
# condition: boolを返す式
# true_val:  conditionがtrueのときに返す値
# false_val: conditionがfalseのときに返す値

⚠️ 型の制約(Result Types): true_valfalse_val同じ型でなければなりません。異なる型が指定された場合、Terraformは自動型変換を試みます(例:数値は文字列に変換可能)が、変換できない場合はエラーになります。明示的に型変換関数(tostring()等)を使うことを推奨します。

# 数値→文字列への自動変換は動作する(ただし明示的な変換を推奨)
var.example ? 12 : "hello"   # → "12"(数値が文字列に変換)

# 明示的に変換する推奨パターン
var.example ? tostring(12) : "hello"
# terraform consoleで確認
> var.environment == "prd" ? "t3.medium" : "t3.micro"
# var.environment = "prd" の場合: "t3.medium"
# var.environment = "dev" の場合: "t3.micro"

> true ? "yes" : "no"
"yes"

> 1 > 2 ? "big" : "small"
"small"

3. 基本的な使い方

環境によってインスタンスタイプを切り替える

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 "enable_deletion_protection" {
  description = "削除保護を有効にするか"
  type        = bool
  default     = false
}

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

resource "aws_instance" "app" {
  ami           = data.aws_ami.amazon_linux_2023.id
  # 本番はt3.medium、それ以外はt3.micro
  instance_type = var.environment == "prd" ? "t3.medium" : "t3.micro"

  root_block_device {
    volume_size = var.environment == "prd" ? 100 : 20
    volume_type = "gp3"
    encrypted   = true
  }

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

4. countと組み合わせてオプションリソースを作る

count = condition ? 1 : 0パターンは、フラグでリソースの作成有無を制御する定番手法です。

variable "create_bastion" {
  description = "踏み台サーバーを作成するか"
  type        = bool
  default     = false
}

# create_bastionがtrueのときだけEC2を作成
resource "aws_instance" "bastion" {
  count = var.create_bastion ? 1 : 0

  ami           = data.aws_ami.amazon_linux_2023.id
  instance_type = "t3.micro"

  tags = {
    Name        = "bastion"
    Environment = var.environment
    ManagedBy   = "terraform"
  }
}

# 条件付き作成したリソースの参照方法
output "bastion_ip" {
  # count = 0の場合はnullを返す
  value = var.create_bastion ? aws_instance.bastion[0].public_ip : null
}

5. for_eachと組み合わせる

locals {
  environments = ["dev", "stg", "prd"]

  # 本番環境のみencryption設定を変える
  bucket_config = {
    for env in local.environments :
    env => {
      versioning = env == "prd" ? true : false
      lifecycle   = env == "prd" ? 90 : 30
    }
  }
}

resource "aws_s3_bucket" "env" {
  for_each = local.bucket_config
  bucket   = "myapp-${each.key}"

  tags = {
    Name        = "myapp-${each.key}"
    Environment = each.key
    ManagedBy   = "terraform"
  }
}

resource "aws_s3_bucket_versioning" "env" {
  for_each = local.bucket_config
  bucket   = aws_s3_bucket.env[each.key].id

  versioning_configuration {
    status = each.value.versioning ? "Enabled" : "Suspended"
  }
}

6. 文字列内での条件式

locals {
  # 文字列の一部に条件式を埋め込む
  bucket_name = "myapp-${var.environment == "prd" ? "production" : var.environment}"

  # CIDR範囲を環境で切り替える
  vpc_cidr = var.environment == "prd" ? "10.1.0.0/16" : "10.0.0.0/16"
}

7. ネストした条件式(注意点)

複数の条件を組み合わせるとネストになりますが、可読性が下がるため注意が必要です。

# ❌ 3段ネストは読みにくい
instance_type = var.env == "prd" ? "t3.medium" : var.env == "stg" ? "t3.small" : "t3.micro"

# ✅ localsかlookupに切り出す
locals {
  instance_type_map = {
    dev = "t3.micro"
    stg = "t3.small"
    prd = "t3.medium"
  }
  instance_type = lookup(local.instance_type_map, var.environment, "t3.micro")
}

3種類以上の分岐が必要な場合は、lookup関数でmapから取り出す方が読みやすくなります。


8. よく使うパターン一覧

パターンコード
値を切り替えるvar.env == "prd" ? "t3.medium" : "t3.micro"
リソースを作る/作らないcount = var.create_resource ? 1 : 0
null を使うvar.optional_value != null ? var.optional_value : "default"
bool → stringvar.enabled ? "enabled" : "disabled"
文字列に埋め込む"prefix-${var.env == "prd" ? "prod" : var.env}"

9. 関連記事


10. まとめ

  • 構文: condition ? true_val : false_val
  • TerraformにはIf文がない。代わりに条件式(三項演算子)を使う
  • count = var.flag ? 1 : 0でリソースの作成有無を制御する定番パターン
  • 3種類以上の分岐はネストが深くなるため、lookup関数やmapで代替する
  • localsに条件式を集めると、リソースブロックがシンプルになる

動作確認バージョン: Terraform >= 1.9 / AWS Provider ~> 5.0 公式ドキュメント: https://developer.hashicorp.com/terraform/language/expressions/conditionals