Tuesday, September 8, 2020

Terraform Module For_Each Subnets

Working with Module For_Loop in Terraform

With 0.13 Terraform is officially supporting Module For_Each Loop. 

Given the below Subnet module

Subnet Module

variable "subnets"{
  default = {
    "public" = {
      "0" = {
        "az" = 0
        "cidr" = "10.1.0.0/18"
      }
      "1" = {
        "az" = 1
        "cidr" = "10.1.64.0/18"
      }
    }
    "private" = {
      "0" = {
        "az" = 0
        "cidr" = "10.1.128.0/19"
      }
      "1" = {
        "az" = 1
        "cidr" = "10.1.160.0/19"
      }
      "2" = {
        "az" = 0
        "cidr" = "10.1.192.0/19"
      }
      "3" = {
        "az" = 1
        "cidr" = "10.1.224.0/19"
      }
    }
  }
}

locals {
  private_subnets = lookup(var.subnet_map,"private",{})
}

resource "aws_subnet" "public_subnets" {
  for_each                = local.public_subnets
  vpc_id                  = var.vpc_id
  cidr_block              = each.value["cidr"]
  availability_zone       = data.aws_availability_zones.az.names[each.value["az"]]
  map_public_ip_on_launch = "false"
}

output "public_subnets" {
  value = aws_subnet.public_subnets
}

  We can call it multiple times via this module call

variable "subnets_map"{
  default = {
    "10.20.0.0/24" = {
      "public" = {
        "0" = {
          "az" = 0
          "cidr" = "10.20.0.0/26"
        }
        "1" = {
          "az" = 1
          "cidr" = "10.20.64.0/26"
        }
      }
      "private" = {
        "0" = {
          "az" = 0
          "cidr" = "10.20.128.0/26"
        }
        "1" = {
          "az" = 1
          "cidr" = "10.20.160.0/26"
        }
      }
    }
  "10.30.0.0/24" = {
      "public" = {
        "0" = {
          "az" = 0
          "cidr" = "10.30.0.0/26"
        }
        "1" = {
          "az" = 1
          "cidr" = "10.30.64.0/26"
        }
      }
      "private" = {
        "0" = {
          "az" = 0
          "cidr" = "10.30.128.0/26"
        }
        "1" = {
          "az" = 1
          "cidr" = "10.30.160.0/26"
        }
      }
    }
  }
}

module "many_subnets" {
  source               = "../subnets"
  for_each             = var.subnets_map
  vpc_id               = var.vpc_id
  subnet_map           = each.value
}

outputs "public_subnets"{
  value = module.many_subnets.public_subnets
}

 The content of module.many_subnets looks like this:

module.many_subnets["10.30.0.0/24"] = 
  private_subnets = {
    0 = {
      arn = "arn:aws:ec2:us-east-1:xxxx:subnet/subnet-xxx"
      assign_ipv6_address_on_creation = false
      availability_zone = "us-east-1a"
      availability_zone_id = "use1-az2"
      cidr_block = "10.30.0.0/26"
      id = "subnet-xxxx"
      ipv6_cidr_block = ""
      ipv6_cidr_block_association_id  = ""
      map_public_ip_on_launch = false
      outpost_arn = ""
      owner_id = "xxxx"
      tags = {}
      timeouts = null
      vpc_id = "vpc-xxx"
      }
    1 = {...}
  }

After everything was done, I only wanted Subnet CIDR and ID, I could have gone back to the original module and updated the output, but I just did this local variable instead:

  private_subnets = {
    for key, value in flatten([
      for item in module.many_subnets : [
        for child in item.private_subnets : {
          "id"   = child.id
          "cidr" = child.cidr_block
        }
      ]
    ]) : (value["cidr"]) => (value["id"])
  }

No comments:

Post a Comment

AWS WAF log4j query

How to query AWS WAF log for log4j attacks 1. Setup your Athena table using this instruction https://docs.aws.amazon.com/athena/latest/ug/wa...