如何在Terraform中引用备用资源?

时间:2018-12-12 13:45:37

标签: terraform

Terraform(截至今天)具有某种令人不安的局限性,即您无法使用插值(计算出的)lifecycle属性prevent_destroy创建资源。

解决方法非常简单,只需创建2个具有“交替”计数的资源即可。当您有1个“生产”资源不允许销毁时,您就有0个“测试”资源可以销毁。或反过来。 (请参阅链接的stackoverflow问题的答案 有关详细信息,请参见上文。)

但是,这提出了一个新问题。当我要引用“执行此操作时存在的备用资源之一”时,该怎么做?

用伪代码类似

"${local.production ? "${aws_eip.commander_production.public_ip}" : "${aws_eip.commander_testing.public_ip}" }" 

此伪代码由于以下几个原因而无法工作:

  • aws_eip.commander_production不再是单个资源,而是一个列表,因此您需要*语法
  • 其中一个列表始终为空,Terraform很容易抱怨它无法确定空列表的类型。 (我想这是因为三元运算符要求备用字符具有相同的类型)
  • 当您访问一个空列表时,您将得到一个错误(使用C语义将不会评估未使用的替代项,但是Terraform的工作方式似乎有所不同,并且在尝试对此进行编码时出现错误)

要解决这些问题,我想出了以下hacky解决方案: 在列表的末尾添加一个虚拟元素,然后参考 扩展列表的第一个元素。这个代码很漂亮 太可怕了,但似乎可以用

locals  {
  dummy = [ "foo" ]
}


output "0101: address" {
  value = "${format("Public IP is %s", "${local.production ? "${element("${concat("${aws_eip.commander_production.*.public_ip}", "${local.dummy}")}", 0)}" : "${element("${concat("${aws_eip.commander_testing.*.public_ip}", "${local.dummy}")}", 0)}" }")}"

}

问题:什么是对此进行编码的更简短/更优雅的方法?

注意:我自己找到了一个答案,但欢迎为更好的答案做出贡献。

1 个答案:

答案 0 :(得分:0)

较短的代码是

output "0101: address" {
   value = "${format("Public IP is %s", "${element("${concat("${aws_eip.commander_production.*.public_ip}", "${aws_eip.commander_testing.*.public_ip}")}", 0)}")}"

}

以纯文本格式:连接列表并采用结果的第一个元素。一个列表具有一个元素,而另一个列表为零,因此结果将是我们想要的结果,而不管元素是在第一列表还是第二列表中。