Здесь есть две проблемы: (1) Как интерполировать список через запятую в строке JSON;и (2) Что вызывает ошибку циклической зависимости.
Как интерполировать список, чтобы создать действительный массив JSON
Использовать jsonencode
Самый чистый метод - не использоватьвообще heredoc и просто используйте функцию jsonencode
.
Вы могли бы сделать это:
locals {
arr = ["host1", "host2", "host3"]
}
output "test" {
value = jsonencode(
{
"consul" = {
"servers" = local.arr
}
})
}
И это приводит к выводу:
Outputs:
test = {"consul":{"servers":["host1","host2","host3"]}}
Используйте функцию join и heredoc
Документы поставщика Chef предлагают использовать heredoc для строки JSON, поэтому вы также можете сделать это:
locals {
arr = ["host1", "host2", "host3"]
sep = "\", \""
}
output "test" {
value = <<-EOF
{
"consul": {
"servers": ["${join(local.sep, local.arr)}"]
}
}
EOF
}
Если я подам заявкучто:
Outputs:
test = {
"consul": {
"servers": ["host1", "host2", "host3"]
}
}
Некоторые вещи, на которые следует обратить внимание:
Вы пытаетесь присоединиться к своим хостам, чтобы они стали действительными JSON в контексте JSONмассив.Вам нужно присоединиться к ним с ","
, а не просто запятой.Вот почему я определил локальную переменную sep = "\", \""
.
Вы, кажется, пытаетесь split
там, когда вам, очевидно, нужно join
.
Проблема циклической зависимости
Причина сообщения об ошибке:
Error: Cycle: aws_instance.consul-server[1], aws_instance.consul-server[0]
Это циклическая зависимость.Рассмотрим этот упрощенный пример:
resource "aws_instance" "example" {
count = 3
ami = "ami-08589eca6dcc9b39c"
instance_type = "t2.micro"
user_data = <<-EOF
hosts="${join(",", aws_instance.example[count.index].id)}"
EOF
}
Или вы можете использовать там тоже знак сплат для того же результата, то есть aws_instance.example.*.id
.
План Terraform, тогда вы получите:
▶ terraform012 plan
...
Error: Cycle: aws_instance.example[2], aws_instance.example[1], aws_instance.example[0]
Таким образом, вы получаете ошибку цикла, потому что aws_instance.example.*.id
зависит от создаваемого aws_instance.example
, поэтому ресурс зависит от самого себя.Другими словами, вы не можете использовать экспортируемые в ресурсы значения внутри самого ресурса.
Что делать
Я не знаю много о Консуле, но все же янемного запутался, почему вы хотите идентификаторы экземпляра EC2 в поле servers
.Разве конфиг Консула не будет ожидать там IP-адреса или имена хостов?
В любом случае, вам, вероятно, придется рассчитывать имена хостов самостоятельно вне этого ресурса, либо как статический входной параметр, либо как что-то, что вы можете вычислитькак-то.И я полагаю, у вас получится что-то вроде:
variable "host_names" {
type = list
default = ["myhost1"]
}
resource "aws_instance" "consul_server" {
...
provisioner "chef" {
attributes_json = jsonencode(
{
"consul" = {
"servers" = var.host_names
}
})
}
}