メインコンテンツへスキップ

Terraform条件分岐パターン集

·
インフラ Terraform 実践 メモ
目次

今日学んだこと
#

Terraform で条件分岐を実現する3つの手法(count + 三項演算子、for_each + for の if、if 文字列ディレクティブ)について学びました。特に count を使った「作る/作らない」の制御パターンは実践で頻繁に使われます。

学習内容
#

条件分岐に使う手法
#

手法用途
count パラメータ条件付きリソースの作成(作る/作らない)
for_each 式 / for 式条件付きリソース、インラインブロックの条件生成
if 文字列ディレクティブ文字列内での条件分岐

count パラメータを使った条件分岐
#

count を使った if 文
#

三項演算子と組み合わせて、リソースを「作成する/しない」を制御します。

count = var.enable_autoscaling ? 1 : 0
var.enable_autoscalingcount結果
true1リソースを作成する
false0リソースを作成しない

コード例:オートスケーリングスケジュール
#

resource "aws_autoscaling_schedule" "scale_out_during_business_hours" {
  count = var.enable_autoscaling ? 1 : 0

  scheduled_action_name  = "${var.cluster_name}-scale-out-during-business-hours"
  min_size               = 2
  max_size               = 10
  desired_capacity       = 10
  recurrence             = "0 9 * * *"
  autoscaling_group_name = aws_autoscaling_group.example.name
}

本番環境では enable_autoscaling = true、ステージング環境では enable_autoscaling = false のように環境ごとに設定を切り替えられます。

count を使った if-else 文
#

count の値を反転させることで if-else を実現します。

# if 文(true のとき作成)
resource "aws_iam_user_policy_attachment" "user1_cloudwatch_full_access" {
  count = var.give_user1_cloudwatch_full_access ? 1 : 0
  # ...
}

# else 文(false のとき作成)→ 三項演算子の値を反転
resource "aws_iam_user_policy_attachment" "user1_cloudwatch_read_only" {
  count = var.give_user1_cloudwatch_full_access ? 0 : 1
  # ...
}
var.give_user1_cloudwatch_full_accessfull_access の countread_only の count
true10
false01

条件付きリソースの出力値を取得
#

count で作成したリソースは、条件によって存在したりしなかったりします。concatone 関数を組み合わせて出力値を取得します。

output "user1_cloudwatch_policy_arn" {
  value = one(concat(
    aws_iam_user_policy_attachment.user1_cloudwatch_full_access[*].policy_arn,
    aws_iam_user_policy_attachment.user1_cloudwatch_read_only[*].policy_arn
  ))
}

one() 関数は単一要素のリストから値を取り出します。空のリストの場合は null を返します。

for_each と for を使った条件分岐
#

基本的な考え方
#

for_each に渡す集合結果
空の集合 {} / []リソースは作成されない
空ではない集合リソースが作成される

for 式の if でフィルタリングすることで、条件に合う要素のみを処理できます。

dynamic "tag" {
  for_each = {
    for key, value in var.custom_tags:
    key => upper(value)
    if key != "Name"    # ← 条件分岐(フィルタリング)
  }

  content {
    key                 = tag.key
    value               = tag.value
    propagate_at_launch = true
  }
}

この例では key != "Name" の条件により、“Name” キーを除外しています。

count vs for_each の使い分け(条件分岐)
#

ユースケース推奨理由
条件付きでリソース/モジュールを作成(作る or 作らない)count? 1 : 0 がシンプル
リソース/モジュールを複数作成for_each途中要素削除の問題がない
それ以外のループや条件分岐for_each柔軟性が高い

if 文字列ディレクティブを使った条件分岐
#

文字列内で条件分岐を行うための構文です。

基本構文
#

%{ if <CONDITION> }<TRUE_VAL>%{ endif }

コード例:最後の要素だけカンマを付けない
#

output "for_directive_index_if" {
  value = <<EOF
%{~ for i, name in var.names ~}
${name}%{ if i < length(var.names) - 1 }, %{ endif }
%{~ endfor ~}
EOF
}
ループinamei < length - 1出力
1回目0user1trueuser1,
2回目1user2trueuser2,
3回目2user3falseuser3

if-else 構文
#

%{ if <CONDITION> }<TRUE_VAL>%{ else }<FALSE_VAL>%{ endif }
output "for_directive_index_if_else_strip" {
  value = <<EOF
%{~ for i, name in var.names ~}
${name}%{ if i < length(var.names) - 1 }, %{ else }.%{ endif }
%{~ endfor ~}
EOF
}

出力結果は user1, user2, user3. となり、最後の要素にピリオドが付きます。

まとめ
#

手法用途構文例
count + 三項演算子リソースを作る/作らないcount = var.enable ? 1 : 0
count(if-else)排他的なリソース作成? 1 : 0? 0 : 1 を反転
for_each + for の if条件付きフィルタリングfor k, v in map : k => v if condition
if 文字列ディレクティブ文字列内の条件分岐%{ if condition }...%{ endif }
  • 「作る or 作らない」の2択なら count がシンプル
  • 複数作成や複雑な条件なら for_each を使う
  • one()concat() で条件付きリソースの出力値を安全に取得できる

参考
#