Это связано не с aws, а с методом извлечения данных из коллекции ресурсов; поэтому контент, скорее всего, неверен относительно провайдера aws. Я просто использовал несколько слов от этого провайдера, чтобы доказать свою идею.
Учитывая, что ресурсы aws_instance.web
создаются как коллекция с использованием цикла for_each
, как описано ниже:
resource "aws_instance" "web" {
for_each = {for k,v in var.input_var: k => v if v.enabled}
name = each.key
ami = each.value.ami
instance_type = each.value.instance_type
}
resource "aws_db_instance" "db" {
for_each = var.another_map
aws_instance_id = aws_instance.web[index(aws_instance.web[*].name, each.value.name)].id
}
При создании первой коллекции ресурсов каждому элементу назначается уникальный доступный только для чтения id
terraform/provider. Учитывая, что var.input_var.key
всегда уникален, результаты, которые также aws_instance.web.name
, всегда будут уникальными для каждого созданного элемента.
Во втором блоке ресурсов я также использую цикл for_each
для циклического перебора всех элементов var.another_map
. Я хочу отнести к aws_instance_id
сгенерированный id
из первой коллекции ресурсов. Поэтому мне нужно сначала найти элемент из aws_instance.web
, где его имя равно each.value.name
, при создании aws_db_instance.db
, а затем извлечь его из id
.
Я пробовал несколько способов добиться этого. Ближайший из них представлен выше: aws_instance.web[index(aws_instance.web[*].name, each.value.name)].id
.
Отсюда два вопроса:
Какой тип aws_instance.web
(список объектов, карта объектов, объект, который содержит карту)?
Как будет выглядеть правильный синтаксис для сопоставления элемента и извлечения из него id
?
Изучая ответ Мэтта Шухарда и расширяя его, результат создания первого ресурса таков: object(map(object))
где ключи сгенерированной карты — это те же ключи входной переменной var.input_var
.
например: учитывая входную переменную
input_var = {
"website1" = {
ami = "ami-a1b2c3d4"
instance_type = "t2.micro"
other_var = "some value"
},
"webst2" = {
ami = "ami-a1b2c3d4"
instance_type = "t2.micro"
other_var = "some other value"
}
}
Блок resource "aws_instance" "web"
создаст переменную aws_instance.web
с таким содержимым:
aws_instance.web = {
"website1" = {
id = 43262 # (read-only) generated by `aws_instance` resource block
name = "website1"
ami = "ami-a1b2c3d4"
instance_type = "t2.micro"
# other entries generated by `aws_instance` resource block
},
"webst2" = {
id = 43263 # (read-only) generated by `aws_instance` resource block
name = "webst2"
ami = "ami-a1b2c3d4"
instance_type = "t2.micro"
# other entries generated by `aws_instance` resource block
}
}
Таким образом, при попытке получить доступ к определенному элементу из aws_instance.web
во втором блоке ресурсов (aws_db_instance.db
) можно получить к нему доступ по его ключу, а не пытаться сопоставить его атрибут name
.
Следовательно, строку aws_instance_id = aws_instance.web[index(aws_instance.web[*].name, each.value.name)].id
следует заменить на aws_instance_id = aws_instance.web[each.value.name].id
тогда и только тогда, когда набор name
s является подмножеством ключей aws_instance.web
(я буду представлять это как each.value.name[*]
⊆ aws_instance.web.keys[*]
)