# ============================================================================= # Пример: N DNS-зон генерируются ПРОГРАММНО (в цикле) — целиком через Terraform. # # Отличие от ../dns_zones/: там зоны заданы ЯВНОЙ картой `var.zones`, а здесь — # генерируются из числа `var.zone_count` через `range(1, N+1)`. Удобно, когда # зон много и они ОДНОТИПНЫ (tfzone-1 … tfzone-N), и задавать каждую руками # не хочется. # # Ресурсы провайдера Nubes: # - nubes_zones_v2 (сервис 109) — DNS-зона; # - nubes_zones_v2_record (подресурс зоны, record) — запись внутри зоны. # # ⚠️ В HCL пишется `name` поля из схемы (snake_case): `zone_name`, `record_name`, # `record_type`, `record_input`, `record_ttl`. `code` (camelCase) — имя в API. # # КАК РАСШИРЯТЬ: измените `var.zone_count` (и `zone_prefix`/`zone_domain`) и # сделайте `apply` — зоны добавятся/уберутся. Состав записей в шаблоне зоны # правится в `locals.zones` ниже. # ============================================================================= # ── locals.zones: ГЕНЕРИРУЕМ N однотипных зон ──────────────────────────────── # `range(1, var.zone_count + 1)` даёт последовательность 1..N. Для каждого числа # строим элемент карты: ключ "-", значение — { zone_name, records }. # Ключ карты = адрес зоны в state (стабильное имя объекта), поэтому нумерация # зон детерминирована: tfzone-1 … tfzone-N. locals { zones = { for i in range(1, var.zone_count + 1) : "${var.zone_prefix}-${i}" => { zone_name = "${var.zone_prefix}-${i}.${var.zone_domain}" # Однотипный набор записей для каждой зоны (пример). Здесь — www и api # с адресами, зависящими от номера зоны (10.0..1 / .2). records = { www = { type = "A", values = ["10.0.${i}.1"] } api = { type = "A", values = ["10.0.${i}.2"] } } } } # ── locals.records: «уплощаем» карту зон в плоский набор записей ─────────── # Записи — отдельные ресурсы, каждой нужен уникальный ключ в for_each. Собираем # карту «<зона>:<запись>» (разворот `...` в merge склеивает карты всех зон). records = merge([ for zk, z in local.zones : { for rk, r in z.records : "${zk}:${rk}" => { zone = zk # какая зона name = rk # имя записи type = r.type # тип (A / CNAME / …) values = r.values # список значений } } ]...) } # ── Зоны ───────────────────────────────────────────────────────────────────── # `for_each = local.zones` — по одному ресурсу на сгенерированную зону. # `each.key` = "-", `each.value.zone_name` = FQDN. resource "nubes_zones_v2" "zone" { for_each = local.zones resource_name = "dns-zone-${each.key}" zone_name = each.value.zone_name } # ── Записи ─────────────────────────────────────────────────────────────────── # `zones_v2_id` ссылается на id СВОЕЙ зоны → Terraform строит зависимость. # `record_input` — JSON-массив `[{ record = "<значение>" }, …]` (jsonencode), # одна запись может иметь несколько значений. 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 }