【问题标题】:how to build up terraform local_file dynamically如何动态构建 terraform local_file
【发布时间】:2020-08-07 18:27:29
【问题描述】:

我想创建几个 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"
}

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

知道如何解决这个问题。

更新:-

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。

【问题讨论】:

标签: amazon-ec2 terraform terraform-provider-aws


【解决方案1】:

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

听起来您的目标是只创建一个包含所有 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 指令拆分为多行来更容易阅读。 &lt;&lt;-EOT 中的 - 导致 Terraform 查看开头 &lt;&lt;-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 部分的中间行,因此结果最终每个条目只有一个换行符,这似乎是这里的意图。

【讨论】:

  • 就是这样!!谢谢马丁
  • 嗨马丁,有没有办法可以从 for 循环中获取索引。我想要一个如下所示的主机文件 [cluster] host0 ansible_host=10.1.0.34 controller=True host1 ansible_host=10.1.0.5 controller=True host2 ansible_host=10.1.0.92 controller=True 所以这里的变量是“主机”跨度>
  • 我通过使用以下代码得到了这个工作:- locals { hosts = { host0 = aws_instance.instance[0].private_ip host1 = aws_instance.instance[1].private_ip host2 = aws_instance.instance[2].private_ip } } resource "local_file" "hosts" { content = &lt;&lt;-EOT [cluster] %{ for host, ip in local.hosts ~} ${host} ansible_host=${ip} controller=True %{ endfor ~} [cluster:vars] EOT filename = "./playbook/roles/ansible_rhel/templates/hosts" }
猜你喜欢
  • 2021-08-28
  • 1970-01-01
  • 1970-01-01
  • 2021-05-09
  • 1970-01-01
  • 1970-01-01
  • 2010-11-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多