获取一组子网的CIDR块

时间:2020-04-13 21:43:58

标签: terraform terraform-provider-aws

我正在尝试获取一组提供参数的子网ID的CIDR块。

data "aws_subnet" "target" {
  for_each = "${toset(var.subnet_ids)}"
  id       = "${each.value}"
}

resource "aws_security_group" "registry" {
  vpc_id = "${var.vpc_id}"
  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["${data.aws_subnet.target.*.cidr_block}"]
  }
  tags = {
    Name = "${var.name}"
  }
}

我得到的错误是:

cidr_blocks = "${data.aws_subnet.target.*.cidr_block}"

This object does not have an attribute named "cidr_block".

Terraform配置:

Terraform v0.12.24
+ provider.aws v2.55.0
+ provider.template v2.1.2

感谢任何可以提供帮助的人!

2 个答案:

答案 0 :(得分:0)

您应该对地图的值使用splat表达式。

resource "aws_security_group" "registry" {
  vpc_id = "${var.vpc_id}"
  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = values(data.aws_subnet.target).*.cidr_block
  }
  tags = {
    Name = "${var.name}"
  }
}

答案 1 :(得分:0)

我认为这里的问题在于,for_each参数使data.aws_subnet.target出现为地图值,并且将splat运算符.*定义为无操作(如果应用)除列表或集合以外的任何内容。因此,这里的表达式评估采取以下步骤:

  • 首先求值data.aws_subnet.target,生成对象图,其键是来自var.subnet_ids的字符串,大概看起来像subnet-12345
  • 然后将.*应用于该地图。因为它是一张地图,所以会再次产生相同的结果。
  • 然后将.cidr_block应用于该映射,该映射将失败,因为其键是子网ID,而不是子网对象的属性。

要在此处获得所需的结果,我们可以使用values忽略键,并将地图中的值作为列表:

cidr_blocks = values(data.aws_subnet.target).*.cidr_block

由于values(...)的结果是一个列表,因此.*运算符将按预期方式运行,并尝试在列表的每个元素中找到cidr_block属性。

另一种选择是使用for expression,它是适用于任何集合类型值的splat语法的概括:

cidr_blocks = [for s in data.aws_subnet.target : s.cidr_block]