smoKeyY
smoKeyY

Reputation: 3

terraform for_each for security groups

variable "ingress_ports_cidr_blocks" {
  type = any
   default = {
     1111 = {description = "test" , protocol = "TCP" , cidr_blocks = ["0.0.0.0/0"]}
     2222 = {description = "test" , protocol = "TCP" , cidr_blocks = ["0.0.0.0/0"]}
   }
}

resource "aws_security_group" "sg_ec2" {
      name        = "ec2-sg"
      vpc_id      = data.aws_vpc.env_vpc.id
      description = var.sgDescription
   
      dynamic ingress {
        for_each = var.single_ingress_port_cidr_blocks
        content {
        description = ingress.value.description
        from_port   = ingress.key
        to_port     = ingress.key
        protocol    = ingress.value.protocol
        cidr_blocks = ingress.value.cidr_blocks
        }
       }

The above code will create 1 SG with 2 rules

I would like to loop in something like this :

variable "ingress_ports_cidr_blocks" {
  type = any
   default = {
     1111 = {description = "test" , protocol = "TCP" , cidr_blocks = ["0.0.0.0/0"]}
     1111 = {description = "test" , protocol = "TCP" , cidr_blocks = ["10.10.10.0/0"]}
     2222 = {description = "test" , protocol = "TCP" , cidr_blocks = ["0.0.0.0/0"]}
   }
}

the problem is that Terraform will ignore the 1st line and skip the 1st rule creation... I am fairly new with for_each, var type and terraform so bare with me... from what I have gathered using type "any" for the variable will choose its type on its own.

Upvotes: 0

Views: 2515

Answers (1)

Mark B
Mark B

Reputation: 200486

Your question is a bit confusing as you seem to be focusing on the type part of the variable declaration, which really has nothing to do with the issue you are encountering. Specifying type = any is the same as just leaving the type definition out all together, it isn't really doing anything.

Your problem is you are defining a map, and two of the keys are the same value:

   default = {
     1111 = {description = "test" , protocol = "TCP" , cidr_blocks = ["0.0.0.0/0"]}
     1111 = {description = "test" , protocol = "TCP" , cidr_blocks = ["10.10.10.0/0"]}
     2222 = {description = "test" , protocol = "TCP" , cidr_blocks = ["0.0.0.0/0"]}
   }

All the keys in a map have to be unique. You are defining two entries in the map with a key of 1111.

It looks like you probably want to use a list instead:

   type = list(map)
   default = [
     {port = 1111, description = "test" , protocol = "TCP" , cidr_blocks = ["0.0.0.0/0"]}
     {port = 1111, description = "test" , protocol = "TCP" , cidr_blocks = ["10.10.10.0/0"]}}
     {port = 2222, description = "test" , protocol = "TCP" , cidr_blocks = ["0.0.0.0/0"]}}
   ]

You'll need to change your dynamic ingress definition to the following:

      dynamic ingress {
        for_each = toset(var.single_ingress_port_cidr_blocks)
        content {
        description = ingress.value.description
        from_port   = ingress.value.port
        to_port     = ingress.value.port
        protocol    = ingress.value.protocol
        cidr_blocks = ingress.value.cidr_blocks
        }
       }

Upvotes: 1

Related Questions