我想创建几个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-usern"
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。
当您在资源中使用count
时,您要求Terraform创建该资源的多个实例。但是,在您的案例中,filename
参数中没有包含count.index
,因此所有实例都在竞争覆盖相同的文件名ec2.ini
,因此只有其中一个实例可以"获胜"。
听起来您的目标是只创建一个包含所有IP地址的文件。这与我写这篇文章时Terraform字符串模板文档中的一个例子非常接近,我们可以根据您的目标进行调整,如下所示:
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的templatefor
指令为每个实例重复一次字符串模板,将结果收集为单个字符串,然后local_file
可以将其用作content
参数。
我在这里使用了字符串文字的"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
部分的中间行,因此结果是每个条目只有一个换行符,这似乎是这里想要的。