如何在 Terraform 中引用备用资源? [英] How to refer to alternate resources in Terraform?

查看:10
本文介绍了如何在 Terraform 中引用备用资源?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Terraform(截至今天)有一些令人不安的限制,即您无法创建具有内插(计算)lifecycle 属性 prevent_destroy 的资源.

Terraform (as of today) has the somewhat disturbing limitation, that you cannot create a resource with an interpolated (calcuted) lifecycle attribute prevent_destroy.

解决方法的代码非常简单,只需创建 2 个具有交替"计数的资源.当您有 1 个不允许销毁的生产"资源时,您有 0 个可以销毁的测试"资源.或者反过来.(请参阅链接的stackoverflow问题的答案详情见上面.)

The work-around is pretty simple to code, just create 2 resources with "alternating" counts. When you have 1 "production" resource which does not allow destroying you have 0 "testing" resources which can be destroyed. Or the other way round. (See the answer to the stackoverflow question linked above for details.)

但是,这带来了一个新问题.当我想引用为此执行而存在的备用资源之一"时,我该怎么做?

However, this brings up a new question. When I want to refer to "the one of the alternate resources that exists for this execution", how do I do that?

类似的伪代码

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

这个伪代码不能工作有几个原因:

This pseudo code cannot work for a couple of reasons:

  • aws_eip.commander_production 不再是单个资源,它是一个列表,因此您需要 * 语法
  • 其中一个列表始终为空,Terraform 很容易抱怨它无法确定空列表的类型.(我猜是因为三元运算符要求替代项具有相同的类型)
  • 当你访问一个空列表时,你会得到一个错误(使用 C 语义,未使用的替代将不会被评估,但 Terraform 似乎工作方式不同,我在尝试编写代码时出错)
  • aws_eip.commander_production is no longer a single resource, it is a list, so you need the * syntax
  • one of the lists is always empty and Terraform easily complains that it cannot determine the type of an empty list. (I guess because the ternary operator requires that the alternates have the same type)
  • when you access into an empty list you will get an error (With C semantics the unused alternate would not be evaluated, but Terraform seems to work differently and I got errors when trying to code this)

为了解决这些问题,我想出了以下 hacky 解决方案:最后用一个虚拟元素扩展列表,然后参考扩展列表的第一个元素.这个代码很漂亮打字很糟糕,但它似乎有效

To work around those I came up with the following hacky solution: Extend the lists with a dummy element in the end and then refer to the first element of the extended list. The code for this is pretty horrible to type, but it seems to work

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)}" }")}"

}

问题:什么是更短/更优雅的编码方式?

Question: What is a shorter / more elegant way to code this?

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

Note: I have found one answer myself, but feel welcome to contribute even better ones.

推荐答案

代码短一点

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

}

纯文本:连接列表并获取结果的第一个元素.一个列表有一个元素,另一个为零,因此无论该元素是在第一个列表还是第二个列表中,结果都是我们想要的.

In plain text: Concatenate the lists and take the first element of the the result. One list has one element and the other one zero, so the result will be what we want, regardless whether the element is in the first or second list.

这篇关于如何在 Terraform 中引用备用资源?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆