简体   繁体   English

Terraform - 迭代组合 map 和列表

[英]Terraform - iterate over combined map and list

I would like to use Terraform to combine a list and a map into a set of resource arguments for an AWS security group.我想使用 Terraform 将列表和 map 组合成 AWS 安全组的一组资源 arguments。 For each port in the list of ports, and for each key in the map of people I would like to have an Ingress rule in the security group.对于端口列表中的每个端口,以及 map 人中的每个密钥,我希望在安全组中有一个 Ingress 规则。 So for example I have a (simplified).tf like this (question marks where I don't know):因此,例如我有一个 (simplified).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 = ?
    }
}

And I would like a resulting static resource like this:我想要这样的 static 资源:

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

I realize that the order of the ingress blocks doesn't matter.我意识到入口块的顺序并不重要。 I'm also not overly attached to the map/list data structure if there's a better way I'm not seeing, as long as I don't have to list each port for each user (there may be many ports, but they'll always be the same for all users).如果我没有看到更好的方法,我也不会过度依赖地图/列表数据结构,只要我不必为每个用户列出每个端口(可能有很多端口,但它们'对所有用户来说总是一样的)。

I have gotten as far as using dynamic blocks for the ingress rule, and can figure out how to iterate over the map in the dynamic block, but can't for the life of my figure out how to get a nested for loop in a dynamic resource argument to work.我已经为入口规则使用动态块,并且可以弄清楚如何在动态块中迭代 map,但是我终生无法弄清楚如何在动态中获得嵌套的 for 循环工作的资源参数。

You can use setproduct and create a helper_list first, before you construct your dynamic block.在构建动态块之前,您可以先使用setproduct并创建一个helper_list


locals {

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

local.helper_list should be in the for form of: 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",
    ],
  ],
]

Then for your dynamic block:然后为您的动态块:

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]
      }    
   }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM