如何动态构建 terraform local_file

how to build up terraform local_file dynamically

我想创建几个 EC2 实例并将它们的 private_ips 抓取到 ec2.ini 样式文件中,以便进一步与 Ansible 一起使用。

resource "local_file" "ec2_id" {
  count = var.instance_count
  content  = "${aws_instance.instance[count.index].private_ip} ansible_ssh_user=ec2-user\n"
  filename = "ec2.ini"
}

这总是打印 private_ip 最新创建的 EC2 实例。

知道如何解决这个问题。

更新:-

data "template_file" "hehe" {
  count = var.instance_count
  template = "${element(aws_instance.instance.*.private_ip, count.index)} ansible_ssh_user=ec2-user subnetmask=${element(split("/", data.aws_subnet.selected-subnet-id.cidr_block),1)}\n"
}


resource "local_file" "ec2_id" {
  count = var.instance_count
  content  = "${element(data.template_file.hehe.*.rendered, count.index)}"
  filename = "ec2.ini"
}

不起作用。给我最后创建的实例 private_ip.

当您在资源中使用 count 时,您要求 Terraform 创建该资源的多个实例。但是,在您的情况下,您没有在 filename 参数中包含 count.index,因此您的所有实例都在竞争覆盖相同的文件名 ec2.ini,因此只有其中一个可以 "win".

听起来您的目标是只创建一个包含所有 IP 地址的文件。这与我撰写本文时 Terraform String Templates 文档中的示例之一非常接近,我们可以像这样适应您的目标:

resource "local_file" "ec2_iini" {
  filename = "ec2.ini"
  content = <<-EOT
    %{ for ip in aws_instance.instance.*.private_ip ~}
    ${ip} ansible_ssh_user=ec2-user
    %{ endfor ~}
  EOT
}

在上面的示例中,local_file 资源本身 而不是 设置了 count,因为我们的目标是只创建一个文件。相反,我们使用 Terraform 的 template for directive 为每个实例重复一次字符串模板,将结果收集为单个字符串,然后 local_file 可以将其用作其 content 参数。

我在这里使用了 string literal 的 "heredoc" 样式,因为我认为它通过将 for 指令分成多行来使它更易于阅读。 <<-EOT 中的 - 导致 Terraform 查看开始 <<-EOT 和结束 EOT 之间的所有行,并找到这些行共有的前导空格的最小数量,然后在渲染时将其剥离。这意味着您可以在配置中缩进模板,但避免在呈现的字符串中出现这些缩进,它应该看起来像这样:

10.1.0.34 ansible_ssh_user=ec2-user
10.1.0.5 ansible_ssh_user=ec2-user
10.1.0.92 ansible_ssh_user=ec2-user

两个 %{ ... } 指令末尾的 ~ 标记指示 Terraform 的模板引擎忽略它们之后的换行符和空格,因此我们可以将模板包装在多行上而无需引入额外的换行符进入结果。此处生成尾随换行符的模板的唯一一行是包含 IP 地址插值和 ansible_ssh_user 部分的中间行,因此结果最终每个条目只有一个换行符,这似乎是此处的意图。