22 KiB
Иногда требуется создать несколько ресурсов, которые будут отличаться незначительными изменениями (например, имя).
В terraform имеются специальные мета-аргументы, которые позволяют описать данную инфраструктуру максимально быстро, избегая повторений блоков.
Однако, при таком подходе стоит учитывать то, что созданная при помощи такого подхода инфраструктура является неким "монолитом" и любые изменения будут применятся для всех ресурсов, которые были созданы с помощью мета аргументов.
ВНИМАНИЕ: СОЗДАННЫЕ ТАКИМ ОБРАЗОМ РЕСУРСЫ, УПРАВЛЯЮТСЯ КАК ОДИН РЕСУРС
Создание дисков. Обычный вариант
Предположим, что необходимо создать несколько дисков, которые будут иметь одинаковые поля, а отличаться только именем.
Тогда, будут использованы несколько блоков resource с описанием данных ресурсов:
resource "dynamix_disk" "disk1" {
account_id = 777
disk_name = "disk-1"
size_max = 10
gid = 212
}
resource "dynamix_disk" "disk2" {
account_id = 777
disk_name = "disk-2"
size_max = 10
gid = 212
}
Все блоки повторяются и отличаются только именем. Если не планируется изменение каждого ресурса по-отдельности, то можно вынести имена дисков в отдельную переменную, и считывать их из нее.
Рефакторинг
Вынесем значения имен дисков в блок locals:
locals {
disk_names = [
"disk-1",
"disk-2",
]
}
resource "dynamix_disk" "disk1" {
account_id = 777
disk_name = "disk-1"
size_max = 10
gid = 212
}
resource "dynamix_disk" "disk2" {
account_id = 777
disk_name = "disk-2"
size_max = 10
gid = 212
}
Оставшиеся блоки resource идентичны друг другу, за исключением наименования ресурса, поэтому, их создание и работу с ними можно объединить.
Мета аргумент for_each
Мета аргумент for_each служит для итерации по набору (set) строки, либо по мапе (map, object). Результатом работы этого мета аргумента станет так же объект, ключами которого будут либо строки, входящие в набор, либо параметры, указанные при итерировании объекта. Мета аргумент for_each предоставляет переменную each, в которую, при каждой итерации будут ключи (если итерация идет по набору строк), либо ключи и соответствующие им значения, если итерация идет по объекту. Обратиться к ним можно через символ ".", например:
each.key
each.value
Таким образом, конфигурирование одинаковых ресурсов сократится до одного. При добавлении в код выше, получится:
locals {
disk_names = [
"disk-1",
"disk-2",
]
}
#обратите внимание, что ресурс был переименован
resource "dynamix_disk" "disks" {
#преобразование массива к набору строк для успешной работы for_each
for_each = toset(local.disk_names)
account_id = 777
#получение имени диска из переменной each
disk_name = each.key
size_max = 10
gid = 212
}
#блок output демонстрирует вывод работы на экран
output "test" {
value = dynamix_disk.disks
}
При выполнении данной конфигурации в terraform output будет следующее:
Changes to Outputs:
+ test = {
+ disk-1 = {
+ account_id = 777
+ account_name = (known after apply)
+ acl = (known after apply)
+ boot_partition = (known after apply)
+ compute_id = (known after apply)
+ compute_name = (known after apply)
+ created_time = (known after apply)
+ deleted_time = (known after apply)
+ desc = (known after apply)
+ destruction_time = (known after apply)
+ detach = false
+ devicename = (known after apply)
+ disk_id = (known after apply)
+ disk_name = "disk-1"
+ disk_path = (known after apply)
+ gid = 212
+ guid = (known after apply)
+ id = (known after apply)
+ image_id = (known after apply)
+ images = (known after apply)
+ iotune = (known after apply)
+ iqn = (known after apply)
+ login = (known after apply)
+ milestones = (known after apply)
+ order = (known after apply)
+ params = (known after apply)
+ parent_id = (known after apply)
+ passwd = (known after apply)
+ pci_slot = (known after apply)
+ permanently = false
+ pool = (known after apply)
+ purge_attempts = (known after apply)
+ purge_time = (known after apply)
+ reality_device_number = (known after apply)
+ reference_id = (known after apply)
+ res_id = (known after apply)
+ res_name = (known after apply)
+ restore = false
+ role = (known after apply)
+ sep_id = (known after apply)
+ sep_type = (known after apply)
+ size_max = 10
+ size_used = (known after apply)
+ snapshots = (known after apply)
+ status = (known after apply)
+ tech_status = (known after apply)
+ timeouts = null
+ type = (known after apply)
+ vmid = (known after apply)
}
+ disk-2 = {
+ account_id = 777
+ account_name = (known after apply)
+ acl = (known after apply)
+ boot_partition = (known after apply)
+ compute_id = (known after apply)
+ compute_name = (known after apply)
+ created_time = (known after apply)
+ deleted_time = (known after apply)
+ desc = (known after apply)
+ destruction_time = (known after apply)
+ detach = false
+ devicename = (known after apply)
+ disk_id = (known after apply)
+ disk_name = "disk-2"
+ disk_path = (known after apply)
+ gid = 212
+ guid = (known after apply)
+ id = (known after apply)
+ image_id = (known after apply)
+ images = (known after apply)
+ iotune = (known after apply)
+ iqn = (known after apply)
+ login = (known after apply)
+ milestones = (known after apply)
+ order = (known after apply)
+ params = (known after apply)
+ parent_id = (known after apply)
+ passwd = (known after apply)
+ pci_slot = (known after apply)
+ permanently = false
+ pool = (known after apply)
+ purge_attempts = (known after apply)
+ purge_time = (known after apply)
+ reality_device_number = (known after apply)
+ reference_id = (known after apply)
+ res_id = (known after apply)
+ res_name = (known after apply)
+ restore = false
+ role = (known after apply)
+ sep_id = (known after apply)
+ sep_type = (known after apply)
+ size_max = 10
+ size_used = (known after apply)
+ snapshots = (known after apply)
+ status = (known after apply)
+ tech_status = (known after apply)
+ timeouts = null
+ type = (known after apply)
+ vmid = (known after apply)
}
}
После подтверждения команды, будет создан файл состояния инфраструктуры, в который запишутся данные.
Обращение к конфигурации, созданной с помощью for_each
Получить доступ к ресурсам, созданным с помощью for_each можно по сл. схеме:
<resource_type>.<resource_name>["<key>"]
Пример получения доступа к ресурсу disk-2:
dynamix_disk.disks["disk-2"]
Чтобы получить доступ к полям, которые содержит ресурс:
<resource_type>.<resource_name>["<key>"].<field_name>
Например, для получения account_id для disk-2:
dynamix_disk.disks["disk-2"].account_id
Использование for_each для более сложной конфигурации
Иногда, необходимо объединить несколько ресурсов с разной конфигурацией в один ресурс, с помощью for_each. Для того, чтобы это сделать, необходимо воспользоваться функцией for для перебора информации о каждом ресурсе, в котором так же необходимо указать какое из полей будет указывать на определенный ресурс. Рассмотрим более сложный пример создания нескольких дисков:
#создание массива из объектов, описывающих инфраструктуру
locals {
disks = [
{
account_id = 777
diskname = "test-disk"
disk2_gb = 100
gid = 212
},
{
account_id = 778
diskname = "test-disk-1"
disk2_gb = 200
gid = 213
}
]
}
resource "dynamix_disk" "disks" {
#цикл for проходит по каждому элементы списка, превращая его в объект, где
#ключом будет - имя диска
#знаяением - сам диск
for_each = { for disk in local.disks : disk.diskname => disk }
#получение account_id каждого диска
account_id = each.value.account_id
#шаблон задания имени диска
#так же, если не надо вносить изменения, можно использовать:
#disk_name = each.value.diskname
disk_name = "${each.value.diskname}-data"
#получение размера диска
size_max = each.value.disk2_gb
#получение gid диска
gid = each.value.gid
}
Таким образом, будут созданы ресурсы с разной конфигурацией.
Мета аргумент count
Мета аргумент count так же служит для множественного создания ресурсов, объединяя их в один, с тем лишь исключением, что это будет массив, а не объект.
Аргумент count принимает на вход либо число, либо выражение, которое возвращает число.
Число - количество итерацией, которые предстоит произвести.
Например:
count = 3
count = length(some_data)
Рассмотрим пример:
#без изменений
locals {
disk_names = [
"disk-1",
"disk-2",
]
}
#без изменений, ресурс так же называется - "disks"
resource "dynamix_disk" "disks" {
#Используется функция length для подсчета длины списка имен дисков
count = length(local.disk_names)
account_id = 777
#аргумент count имеет поле index, которое возвращает индекс(счетчик) текущей итерации
disk_name = local.disk_names[count.index]
size_max = 10
gid = 212
}
output "test" {
value = dynamix_disk.disks
}
При выполнении данной конфигурации в terraform output будет следующее:
Changes to Outputs:
+ test = [
+ {
+ account_id = 777
+ account_name = (known after apply)
+ acl = (known after apply)
+ boot_partition = (known after apply)
+ compute_id = (known after apply)
+ compute_name = (known after apply)
+ created_time = (known after apply)
+ deleted_time = (known after apply)
+ desc = (known after apply)
+ destruction_time = (known after apply)
+ detach = false
+ devicename = (known after apply)
+ disk_id = (known after apply)
+ disk_name = "disk-1"
+ disk_path = (known after apply)
+ gid = 212
+ guid = (known after apply)
+ id = (known after apply)
+ image_id = (known after apply)
+ images = (known after apply)
+ iotune = (known after apply)
+ iqn = (known after apply)
+ login = (known after apply)
+ milestones = (known after apply)
+ order = (known after apply)
+ params = (known after apply)
+ parent_id = (known after apply)
+ passwd = (known after apply)
+ pci_slot = (known after apply)
+ permanently = false
+ pool = (known after apply)
+ purge_attempts = (known after apply)
+ purge_time = (known after apply)
+ reality_device_number = (known after apply)
+ reference_id = (known after apply)
+ res_id = (known after apply)
+ res_name = (known after apply)
+ restore = false
+ role = (known after apply)
+ sep_id = (known after apply)
+ sep_type = (known after apply)
+ size_max = 10
+ size_used = (known after apply)
+ snapshots = (known after apply)
+ status = (known after apply)
+ tech_status = (known after apply)
+ timeouts = null
+ type = (known after apply)
+ vmid = (known after apply)
},
+ {
+ account_id = 777
+ account_name = (known after apply)
+ acl = (known after apply)
+ boot_partition = (known after apply)
+ compute_id = (known after apply)
+ compute_name = (known after apply)
+ created_time = (known after apply)
+ deleted_time = (known after apply)
+ desc = (known after apply)
+ destruction_time = (known after apply)
+ detach = false
+ devicename = (known after apply)
+ disk_id = (known after apply)
+ disk_name = "disk-2"
+ disk_path = (known after apply)
+ gid = 212
+ guid = (known after apply)
+ id = (known after apply)
+ image_id = (known after apply)
+ images = (known after apply)
+ iotune = (known after apply)
+ iqn = (known after apply)
+ login = (known after apply)
+ milestones = (known after apply)
+ order = (known after apply)
+ params = (known after apply)
+ parent_id = (known after apply)
+ passwd = (known after apply)
+ pci_slot = (known after apply)
+ permanently = false
+ pool = (known after apply)
+ purge_attempts = (known after apply)
+ purge_time = (known after apply)
+ reality_device_number = (known after apply)
+ reference_id = (known after apply)
+ res_id = (known after apply)
+ res_name = (known after apply)
+ restore = false
+ role = (known after apply)
+ sep_id = (known after apply)
+ sep_type = (known after apply)
+ size_max = 10
+ size_used = (known after apply)
+ snapshots = (known after apply)
+ status = (known after apply)
+ tech_status = (known after apply)
+ timeouts = null
+ type = (known after apply)
+ vmid = (known after apply)
},
]
Обращение к конфигурации, созданной с помощью сount
Получить доступ к ресурсам, созданным с помощью count можно по сл. схеме:
<resource_type>.<resource_name>[<index>]
Пример получения доступа к ресурсу disk-2:
dynamix_disk.disks[1]
Чтобы получить доступ к полям, которые содержит ресурс:
<resource_type>.<resource_name>[<index>].<field_name>
Например, для получения account_id для disk-2:
dynamix_disk.disks[1].account_id
Использование count для более сложной конфигурации
Иногда, необходимо объединить несколько ресурсов с разной конфигурацией в один ресурс, с помощью count. Для того, чтобы это сделать, необходимо воспользоваться функцией length для установления длины входящих параметров. После чего, обращаться к ним, получая значения, используя индекс. Рассмотрим более сложный пример создания нескольких дисков:
#создание массива из объектов, описывающих инфраструктуру
locals {
disks = [
{
account_id = 777
diskname = "test-disk"
disk2_gb = 100
gid = 212
},
{
account_id = 778
diskname = "test-disk-1"
disk2_gb = 200
gid = 213
}
]
}
resource "dynamix_disk" "disks" {
#получение значения длины входящих параметров
count = length(local.disks)
#получение идентификатора аккаунта
account_id = local.disks[count.index].account_id
#получение имени диска
disk_name = "${local.disks[count.index].diskname}-data"
#получение размера диска
size_max = local.disks[count.index].disk2_gb
#получение gid
gid = local.disks[count.index].gid
}
Таким образом, будут созданы ресурсы, с разной конфигурацией.