Files
tf_examples/dns_zones/main.tf
T

79 lines
5.1 KiB
Terraform
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# =============================================================================
# Пример: доменные зоны компании и записи DNS — целиком через Terraform.
#
# Задача: держать доменные зоны и их записи в коде (IaC), а не руками в ЛК.
#
# Ресурсы провайдера Nubes:
# - nubes_zones_v2 (сервис 109) — DNS-зона;
# - nubes_zones_v2_record (подресурс зоны, record) — запись внутри зоны
# (A / CNAME / …). Записи — ОТДЕЛЬНЫЕ ресурсы, поэтому ими можно управлять
# адресно: добавить/изменить/удалить одну запись, не трогая зону целиком.
#
# ⚠️ В HCL пишется `name` поля из схемы (snake_case): `zone_name`, `record_name`,
# `record_type`, `record_input`, `record_ttl`. `code` (camelCase) — внутреннее
# имя в API, в HCL НЕ используется.
#
# КАК РАСШИРЯТЬ: чтобы добавить/убрать зону или запись — правьте `var.zones`
# (в variables.tf или terraform.tfvars) и делайте `terraform apply`.
# Ключи карт (`a`, `b`, `www`, …) — это АДРЕСА объектов в state. Меняйте их
# осознанно: смена ключа = «удалить старый объект + создать новый», а не
# «переименовать». Само значение `zone_name`/`record_input` меняется обычным
# `apply`.
# =============================================================================
# ── locals.records: «уплощаем» вложенную структуру «зоны → записи» ────────────
#
# var.zones — карта «зона → { zone_name, records }», где records — ещё одна
# карта «имя записи → { type, values }».
#
# Ресурсу записи нужен ОДИН плоский набор, где у каждого элемента УНИКАЛЬНЫЙ
# ключ: тогда `for_each` создаст ровно по одному ресурсу на запись и даст
# стабильные адреса вида `nubes_zones_v2_record.record["a:www"]`.
#
# `merge([ ... ]...)` — разворот (`...`) списка карт в один вызов merge —
# склеивает карты из каждой зоны в общую. Ключ собираем как "<зона>:<запись>",
# чтобы записи с одинаковыми именами в разных зонах не столкнулись.
locals {
records = merge([
for zk, z in var.zones : {
for rk, r in z.records :
"${zk}:${rk}" => {
zone = zk # какая зона (ключ карты var.zones)
name = rk # имя записи
type = r.type # тип записи (A / CNAME / …)
values = r.values # список значений записи
}
}
]...)
}
# ── Зоны ─────────────────────────────────────────────────────────────────────
# `for_each = var.zones` — по одному ресурсу на каждый КЛЮЧ карты зон.
# `each.key` — короткое имя зоны (a, b, …), `each.value` — её параметры.
# `resource_name` — человекочитаемое имя ресурса в Nubes; `zone_name` — сам
# домен (FQDN зоны).
resource "nubes_zones_v2" "zone" {
for_each = var.zones
resource_name = "dns-zone-${each.key}"
zone_name = each.value.zone_name
}
# ── Записи ───────────────────────────────────────────────────────────────────
# `for_each = local.records` — по одному ресурсу на запись (плоская карта выше).
# `zones_v2_id` — ссылка на id СВОЕЙ зоны (через for_each зоны): Terraform сам
# построит зависимость «зона создаётся раньше своих записей».
#
# `record_input` — платформа ждёт JSON-массив объектов `[{ record = "<значение>" },
# …]`, поэтому собираем его из плоского списка `values` через `jsonencode`.
# Одна запись может иметь НЕСКОЛЬКО значений (напр. два A-адреса) — это одна
# запись с массивом, а не две отдельные.
resource "nubes_zones_v2_record" "record" {
for_each = local.records
zones_v2_id = nubes_zones_v2.zone[each.value.zone].id
record_name = each.value.name
record_type = each.value.type
record_input = jsonencode([for v in each.value.values : { record = v }])
record_ttl = 3600
}