简体   繁体   中英

Terraform iterate nested objects and lists

I am using Terraform to setup some infrastructure on AWS. The input is a Map of objects and has stages. The code looks like this:

variables.tf

variable "aws_api_gw_instances" {
 description = "Maps of objects representing API GW instances with id and stages"
 type = map(object({
    stages  = list(string)
  }))
  default = {
    apiId = {
        stages = ["stage1"]
    }
  }
}

Then I basically need to iterate all the objects in the map and their list of stages, effectively creating a nested loops. However I fail to understand how to achive this with Terraform. I have the following code but using this for syntax does not seem to work at all.

resource "aws_api_gateway_deployment" "deploy_api" {
  for apiGw in var.aws_api_gw_instances
    for stage in toset(apiGw.value["stages"])
      rest_api_id = apiGw.key
      stage_name = stage
      variables = {
        tf_force_redeployment_id = local.current_time
      }
      lifecycle {
        create_before_destroy = true
      }
}

I have previously been using the for_each syntax to iterate the map, but I do not understand how to write a nestled loop here:

for_each = (var.aws_api_gw_instances)  
  rest_api_id = each.key

You can flatten your var.aws_api_gw_instances into local.helper_map (uniqueness of api_id - stage name pairs is assumed, as its not stated otherwise in your question):


variable "aws_api_gw_instances" {
 description = "Maps of objects representing API GW instances with id and stages"
 type = map(object({
    stages  = list(string)
  }))
  default = {
    apiId1 = {
        stages = ["stage1", "stage2"]
    }
    apiId2 = {
        stages = ["stage11", "stage22", "stage33"]
    }    
  }
}


locals {

  helper_map = merge([
      for api_id, values in var.aws_api_gw_instances:
      {
        for stage in values.stages:
          "${api_id}-${stage}" => {api_id = api_id, stage = stage}
      }
    ]...) # <-- dont forget about three dots!
}

which results in ``local.helper_map` being:

{
  "apiId1-stage1" = {
    "api_id" = "apiId1"
    "stage" = "stage1"
  }
  "apiId1-stage2" = {
    "api_id" = "apiId1"
    "stage" = "stage2"
  }
  "apiId2-stage11" = {
    "api_id" = "apiId2"
    "stage" = "stage11"
  }
  "apiId2-stage22" = {
    "api_id" = "apiId2"
    "stage" = "stage22"
  }
  "apiId2-stage33" = {
    "api_id" = "apiId2"
    "stage" = "stage33"
  }
}

Then, you use the helper_map as follows:

resource "aws_api_gateway_deployment" "deploy_api" {

      for_each = local.helper_map

      rest_api_id = each.value.api_id
      stage_name = each.value.stage

      variables = {
        tf_force_redeployment_id = local.current_time
      }
      lifecycle {
        create_before_destroy = true
      }
}

I haven't verified the validity of your aws_api_gateway_deployment in itself as it depends on many other things not shown and not considered in the question. But the local.helper_map should work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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