format( ) 函数未在 "for" 指令内的 Terraform 模板文件中进行评估

format( ) function not not evaluating in Terraform template file within "for" directive

首先要问一些上下文,所以也许有人可以重定向我来更正 answer/post。我已经学习 Terraform 几天了,现在想在部署我的 tf 文件时生成一个“ansible inventory”。

经过大量初学者搜索后,我发现数据“template_file”对像我这样的初学者来说很重,但我可以 SO-Frankenstein-monster 我的方式:

resource "local_file" "inventory" {
  content = templatefile("${path.module}/templates/hosts.tpl",
    {
      master        = aws_instance.master.*.public_ip
      nodes_ubuntu  = aws_instance.node.*.public_ip
     }
  )
  filename = "./inventory"
}

模板文件格式如下:

[master]
%{ for ip in master ~}
control ansible_host=${ip}
%{ endfor ~}

[nodes_ubuntu]

%{ for ip in nodes_ubuntu ~}

$${format{"withCurly-%02d",index + 1}} ansible_host=${ip}

$${format("WithRound-%02d",index + 1)} ansible_host=${ip}

format("PureFormat-%02s",index+1) ansible_host=${ip}

#These are possible combinations I used and failed for format()

%{ endfor ~}

这导致混淆:

[master]
control ansible_host=ip.add.re.ss

[nodes_ubuntu]

${format{"withCurly-%02d",index + 1}} ansible_host=ip.add.re.ss

${format("WithRound-%02d",index + 1)} ansible_host=ip.add.re.ss

format("PureFormat-%02s",index+1) ansible_host=ip.add.re.ss

${format("WithRound-%02d",index + 1)} ansible_host=${ip}

产生错误 Invalid value for "vars" parameter: vars map does not contain key "index"

我期待它是这样的:

[nodes_ubuntu]
ubuntu-01 ansible_host= ip.add.re.ss

我如何更正代码,或者是 Terraform 错误,因为我看到类似的代码有效但忘记记下参考。

你描述的第一个结果,函数调用保留在输出中,是因为你使用 $${ 来逃避正常的 ${ 模板插值序列,要求 Terraform 插入文字 ${ 代替。如果您正在为另一种使用 ${ 本身表示某种含义的语言生成源代码,那将是一件合适的事情,但是由于您希望 Terraform 评估该插值,因此您必须使用 non-escaped ${ 形式,正如您在第二种情况下尝试的那样。

您在修复不正确的转义时看到的问题是您没有在对 templatefile 的调用中或在本地模板中声明任何符号 index

如果您的目标是使用 nodes_ubuntu 的每个元素的索引,那么您可以通过在 for 指令中声明第二个符号来实现。如果你给出两个符号,那么第一个代表 key/index 而第二个代表值:

%{ for index, ip in nodes_ubuntu ~}
${format("WithRound-%02d", index + 1)} ansible_host=${ip}
%{ endfor ~}

这是处理使用 count 声明的资源对象列表的有效方法,但在采用此策略之前,请务必考虑这在未来的维护中将如何表现:Terraform 正在通过它们的方式跟踪这些对象计数中的索引,因此如果您稍后增加资源 count,则会在末尾添加一个新索引。如果您 减少 count 那么您将始终从此列表的末尾删除条目。如果您更换任何一台主机,则相应索引的 IP 地址将在此模板结果中更改。

如果这些多个虚拟机更像“牛”而不是“宠物”,那么这些限制就好了,也就是说,如果你需要摧毁其中一个,它们都同样可以摧毁。如果它们中的任何一个具有独特的特性,可能会导致您想要专门销毁列表中间的一个,那么这不是一个好的设计。

在你的情况下,这看起来是合适的,因为你已经在不同的资源中区分了“主”和“节点”角色,因此节点都是可替代的。我提到它只是因为它是编写 Terraform 配置的一个相对常见的问题,这意味着实例实际上不是可替代的,这可能会导致以后的维护问题。

(更多信息见 When to Use for_each Instead of count。)