はじめに
業務の中でterraformを触る機会がありこの書き方いいなと思ったので備忘録です。
背景&課題
今回はdatadogでprd, pilot以外の環境で、hogehoge-api-web, hogehoge-api-appのような末尾のprefixだけが異なるサービスに対してダウンタイムを作成したいタイミングがありました。
それぞれ冗長にダウンタイムを作成してもいいですが、冗長になってしまうため、1つの定義で2つのマイクロサービスに対してのダウンタイムを作成したいという課題がありました。
いつもは、countで作成する環境を限定。for_eachで末尾のprefixが異なるサービスのモニターを作成しており、countとfor_eachは併用できるものと考えていました。
しかし、以下のようにcountとfor_eachは併用することができません
resource "datadog_downtime_schedule" "downtime-template" {
// count と for_eachは併用できない
count = "${local.env}" == "prd" || "${local.env}" == "pilot" ? 0 : 1
for_each = local.application_name
// 以下省略
}
エラー
併用した場合以下のようなエラーが発生してしまいます。
│ Error: Invalid combination of "count" and "for_each"
│
│ on downtime.tf line 4, in resource "datadog_downtime_schedule" "downtime_template":
│ 4: for_each = local.application_name
│
│ The "count" and "for_each" meta-arguments are mutually-exclusive, only one should be used to be explicit about the number of
│ resources to be created.
解決策
先輩社員からアドバイスをいただき、以下のような感じで、環境に該当する場合は空配列を返すようにしました。(こういう書き方もできるんですね〜)
for_each = "${local.env}" == "prd" || "${local.env}" == "pilot" ? {} : local.application_name
完成系
locals {
service_name = "hogehoge-api"
application_name = {
web = {
fugahoge = xxx
},
app = {
fugahoge = xxx
}
}
}
resource "datadog_downtime_schedule" "downtime-template" {
for_each = "${local.env}" == "prd" || "${local.env}" == "pilot" ? {} : local.application_name
scope = "*"
message = "[${local.env}] ${local.service_name}-${each.key} scheduled downtime"
mute_first_recovery_notification = false
notify_end_states = ["no data", "alert", "warn"]
notify_end_types = ["expired"]
recurring_schedule {
recurrence {
duration = "450m" # Everyday 0:00 - 7:30 JST (specified in UTC)
rrule = "FREQ=DAILY;INTERVAL=1"
start = "2024-09-16T15:00:00" # JST 2024-09-17 00:00
}
recurrence {
duration = "3330m" # SAT 0:00 - MON 7:30 JST (specified in UTC)
rrule = "FREQ=WEEKLY;INTERVAL=1"
start = "2024-09-13T15:00:00" # JST 2024-09-14 00:00
}
}
monitor_identifier {
monitor_tags = [
"env:${local.env}",
"service:${local.service_name}-${each.key}",
"downtime-for-cost:true"
]
}
}