79 lines
5.1 KiB
Terraform
79 lines
5.1 KiB
Terraform
# =============================================================================
|
||
# Пример: доменные зоны компании и записи 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
|
||
}
|
||
|