Terraform-遍历合并的地图和列表

时间:2020-09-21 11:50:03

标签: amazon-web-services terraform terraform-provider-aws

我想使用Terraform将列表和映射合并到AWS安全组的一组资源参数中。对于端口列表中的每个端口,以及人员图中的每个键,我希望在安全组中具有一个Ingress规则。例如,我有一个(简化的).tf像这样(我不知道的问号):

variable "IP_Mapping" {
  type = "map"
  default = {
    "bob"          = "1.1.1.1/32"
    "alice"        = "2.2.2.2/32"
  }
}

variable "ingress_ports" {
  type        = list(number)
  description = "list of ingress ports"
  default     = [80, 443]
}

resource "aws_security_group" "sg-vpc" {
  name        = "sd-ocp-vpc_sg"
  description = "Default security group"
  vpc_id      = "${aws_vpc.vpc.id}"

    ingress {
      from_port   = ?
      to_port     = ?
      protocol    = "tcp"
      cidr_blocks = ?
      description = ?
    }
}

我想要一个这样的结果静态资源:

resource "aws_security_group" "sg-vpc" {
  name        = "sd-ocp-vpc_sg"
  description = "Default security group"
  vpc_id      = "${aws_vpc.vpc.id}"

  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["1.1.1.1/32"]
    description = "bob"
  }
  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["1.1.1.1/32"]
    description = "bob"
  }
  ingress {
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = ["2.2.2.2/32"]
    description = "alice"
  }
  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["2.2.2.2/32"]
    description = "alice"
  }
}

我意识到入口块的顺序无关紧要。如果没有更好的方法,我也不会过于依赖地图/列表数据结构,只要我不必为每个用户列出每个端口即可(可能有很多端口,但是它们对于所有用户而言,始终是相同的。)

我已经为入口规则使用了动态块,并且可以弄清楚如何在动态块中遍历地图,但是无法弄清楚如何获得嵌套的for循环在动态资源参数中起作用。

1 个答案:

答案 0 :(得分:1)

在构造动态块之前,您可以先使用setproduct并创建一个helper_list


locals {

  helper_list = setproduct(
                  var.ingress_ports,
                  [for name, cidr in var.IP_Mapping: [name, cidr]])           
}

local.helper_list的格式应为:

[
  [
    80,
    [
      "alice",
      "2.2.2.2/32",
    ],
  ],
  [
    80,
    [
      "bob",
      "1.1.1.1/32",
    ],
  ],
  [
    443,
    [
      "alice",
      "2.2.2.2/32",
    ],
  ],
  [
    443,
    [
      "bob",
      "1.1.1.1/32",
    ],
  ],
]

然后输入动态块:

resource "aws_security_group" "sg-vpc" {
  name        = "sd-ocp-vpc_sg"
  description = "Default security group"
  vpc_id      = "${aws_vpc.vpc.id}"

  dynamic "ingress" {

      for_each = {for idx, item in local.helper_list: idx=>item}

      content {
        from_port   = ingress.value[0]
        to_port     = ingress.value[0]
        protocol    = "tcp"
        cidr_blocks = [ingress.value[1][1]]
        description = ingress.value[1][0]
      }    
   }
}