Иногда требуется создать несколько ресурсов, которые будут отличаться незначительными изменениями (например, имя).  
В terraform имеются специальные мета-аргументы, которые позволяют описать данную инфраструктуру максимально быстро, избегая повторений блоков.  
Однако, при таком подходе стоит учитывать то, что созданная при помощи такого подхода инфраструктура является неким "монолитом" и любые изменения будут применятся для всех ресурсов, которые были созданы с помощью мета аргументов.

__ВНИМАНИЕ: СОЗДАННЫЕ ТАКИМ ОБРАЗОМ РЕСУРСЫ, УПРАВЛЯЮТСЯ КАК ОДИН РЕСУРС__

## Создание дисков. Обычный вариант
Предположим, что необходимо создать несколько дисков, которые будут иметь одинаковые поля, а отличаться только именем.  
Тогда, будут использованы несколько блоков resource с описанием данных ресурсов:
```terraform
resource "decort_disk" "disk1" {
  account_id  = 777
  disk_name   = "disk-1"
  size_max    = 10
  gid         = 212
}

resource "decort_disk" "disk2" {
  account_id  = 777
  disk_name   = "disk-2"
  size_max    = 10
  gid         = 212
}
```
Все блоки повторяются и отличаются только именем. Если не планируется изменение каждого ресурса по-отдельности, то можно вынести имена дисков в отдельную переменную, и считывать их из нее.  
## Рефакторинг
Вынесем значения имен дисков в блок locals:
```terraform
locals {
 disk_names = [
   "disk-1",
   "disk-2",
  ]
}

resource "decort_disk" "disk1" {
  account_id  = 777
  disk_name   = "disk-1"
  size_max    = 10
  gid         = 212
}

resource "decort_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, в которую, при каждой итерации будут ключи (если итерация идет по набору строк), либо ключи и соответствующие им значения, если итерация идет по объекту.
Обратиться к ним можно через символ ".", например:
```terraform
each.key
each.value
```
Таким образом, конфигурирование одинаковых ресурсов сократится до одного.
При добавлении в код выше, получится:
```terraform
locals {
  disk_names = [
    "disk-1",
    "disk-2",
  ]
}

#обратите внимание, что ресурс был переименован
resource "decort_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 = decort_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)
          + reason                = null
          + 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)
          + reason                = null
          + 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:
```
decort_disk.disks["disk-2"]
```
Чтобы получить доступ к полям, которые содержит ресурс:
```
<resource_type>.<resource_name>["<key>"].<field_name>
```
Например, для получения account_id для disk-2:
```
decort_disk.disks["disk-2"].account_id
```
### Использование for_each для более сложной конфигурации
Иногда, необходимо объединить несколько ресурсов с разной конфигурацией в один ресурс, с помощью for_each. Для того, чтобы это сделать, необходимо воспользоваться функцией for для перебора информации о каждом ресурсе, в котором так же необходимо указать какое из полей будет указывать на определенный ресурс.
Рассмотрим более сложный пример создания нескольких дисков:
```terraform
#создание массива из объектов, описывающих инфраструктуру
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 "decort_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 принимает на вход либо число, либо выражение, которое возвращает число.  
Число - количество итерацией, которые предстоит произвести.
Например:
```terraform
count = 3
count = length(some_data)
```
Рассмотрим пример:
```terraform
#без изменений
locals {
  disk_names = [
    "disk-1",
    "disk-2",
  ]
}

#без изменений, ресурс так же называется - "disks"
resource "decort_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 = decort_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)
          + reason                = null
          + 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)
          + reason                = null
          + 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:
```
decort_disk.disks[1]
```
Чтобы получить доступ к полям, которые содержит ресурс:
```
<resource_type>.<resource_name>[<index>].<field_name>
```
Например, для получения account_id для disk-2:
```
decort_disk.disks[1].account_id
```
### Использование count для более сложной конфигурации
Иногда, необходимо объединить несколько ресурсов с разной конфигурацией в один ресурс, с помощью count. Для того, чтобы это сделать, необходимо воспользоваться функцией length для установления длины входящих параметров. После чего, обращаться к ним, получая значения, используя индекс.
Рассмотрим более сложный пример создания нескольких дисков:
```terraform
#создание массива из объектов, описывающих инфраструктуру
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 "decort_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
}
```
Таким образом, будут созданы ресурсы, с разной конфигурацией.
