首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Terraform中构建动态列表?

在Terraform中构建动态列表?
EN

Stack Overflow用户
提问于 2017-06-05 16:09:00
回答 2查看 9.5K关注 0票数 1

我正在尝试使用count在terraform中动态地创建一些aws资源,然后构建一个包含所有创建的资源in的列表的输出变量。

代码语言:javascript
复制
resource "aws_subnet" "subnet-1" {
  // If subnet_id value is supplied then we set count to 1 to create otherwise skip
  count = "${replace(replace(var.primary_subnet_cidr, "/^.+/", "1"), "/^$/", "0")}"
  tags = {
    Name = "subnet-1"
  }
  cidr_block = "${var.primary_subnet_cidr}"
  vpc_id = "${var.vpc_id}"
  availability_zone = "${var.aws_region}a"
}
resource "aws_subnet" "subnet-2" {
  // If subnet_id value is supplied then we set count to 1 to create otherwise skip
  count = "${replace(replace(var.secondary_subnet_cidr, "/^.+/", "1"),"/^$/", "0")}"
  tags = {
    Name = "subnet-2"
  }
  cidr_block = "${var.secondary_subnet_cidr}"
  vpc_id = "${var.vpc_id}"
  availability_zone = "${var.aws_region}b"
}

output "ids" {
      value = ["${aws_subnet.subnet-1.id}","${aws_subnet.subnet-2.id}"]
}

其想法是只通过提供它的变量(primary_subnet_cidr或secondary_subnet_cidr)来创建您想要的子网。

动态创建它们很好,但是我的问题是动态列表。

当试图在类似于接收列表的aws_db_subnet_group.subnet_ids中使用此列表时,只有在创建了两个子网时,它才能工作,否则会引发以下错误

InvalidSubnet: Subnet IDs are required.

我也试过这个

代码语言:javascript
复制
output "ids" {
      value = ["${aws_subnet.*.id}"]
}

但在资源级别上,terraform似乎不支持通配符。

我怀疑这与我生成输出列表的方式有关。是否有更好的方法来生成动态列表,使其只包含所创建的资源?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-06-06 06:14:47

您已经接近了,但是您需要使用正确的RESOURCE-TYPE.RESOURCE-NAME.PROPERTY_NAMERESOURCE-TYPE.RESOURCE-NAME.*.PROPERTY_NAME的Terraform资源语法。因此,在您的示例中,您将输出:

代码语言:javascript
复制
output "ids" {
   value = "${aws_subnet.subnet-1.*.id}"
}

当然,您可能希望使用concat插值函数连接这两个列表

代码语言:javascript
复制
output "ids" {
   value = "${concat(aws_subnet.subnet-1.*.id, aws_subnet.subnet-2.*.id)}"
}

但是,如果在任一资源上将count属性设置为0,则可能会引发错误。为了弥补这一点,您可以使用一些其他插值函数的组合(例如coalescelist()),但我恐怕记不起确切的组合了。

最后,对于您的count属性,这些var定义读起来有点棘手。以下是一些值得尝试的其他想法:

代码语言:javascript
复制
// Count = 1 if var.secondary_subnet_cidr is non-empty
resource "aws_subnet" "subnet-1" {
  count = "${signum(length(var.secondary_subnet_cidr))}"
  ...
}

// Define a separate var altogether. Ideally, you could infer this, but sometimes it's the best you can do.
resource "aws_subnet" "subnet-1" {
  count = "${var.should_create_secondary_subnet)}"
  ...
}

UpdateJun6,2017:感谢@MartinAtkins指出,截至Terraform0.9.x,您不再需要在[]中包装列表输出。我更新了我的答案。

更新2017年6月8日:在两个可能为空的列表中只选择非空列表,使用${element(concat(aws_subnet.subnet-1.*.id, aws_subnet.subnet-2.*.id), 0)}concat()函数将接受一个空列表,element(..., 0)将始终返回第一个元素,在本例中是非空列表。

票数 2
EN

Stack Overflow用户

发布于 2021-07-23 18:27:57

我在尝试创建一个动态列表时发现了这个问题,在这个列表中,我必须创建一个列表,列表中包含可变数量的元素。我在创建一个字符串列表。我用方法解决了这个问题。基本上,这个列表将过滤掉我在列表中生成的空白元素。

例如,假设我有以下列表,

代码语言:javascript
复制
myList = ["foo", barExists ? "bar" : ""]

这将创建["foo", "bar"]["foo", ""]。如果您需要["foo", "bar"]["foo"],那么紧凑型函数就是您的朋友。

代码语言:javascript
复制
myList = compact(["foo", barExists ? "bar" : ""])

在这种情况下,上述项目将有效。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44373102

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档