terraform

Conditional statement in locals


I've removed the initial question to simplify.

Is there a way to print the value of tolist(local.port_mappings) to see what the issue is?

Thanks to @DharaniDharGolladasari - just use an output!

locals = {
     host_ports = [for port in local.all_ports: {"containerPort": tonumber(port), "hostPort": tonumber(port), "protocol": "tcp"}]
 
     port_mappings = var.ecs_task_definition_network_mode == "host" ? [for port in local.all_ports: {"containerPort": tonumber(port), "hostPort": tonumber(port), "protocol": "tcp"}] : [for port in local.all_ports: {"containerPort": tonumber(port), "protocol": "tcp"}]
}

Outputs:

Changes to Outputs:
  + host_ports                  = [
      + {
          + containerPort = 8080
          + protocol      = "tcp"
        },
    ]
  + port_mappings               = [
      + {
          + containerPort = "8080"
          + hostPort      = "8080"
          + protocol      = "tcp"
        },
    ]

So it looks like the conditional statement is removing the tonumber() and treating the number as a string.

Is this intentional? Anything I can do to make it respect the tonumber?


Solution

  • looks like I find out what happened here - terraform handles the type conversion properly, but local.port_mappings have additional tomap function inside, and because of this, terraform convert all variables to the same type (string in our case), as described in the documentation. You can check this by using terraform console:

    $ terraform console
    > local.port_mappings
    [
      tomap({
        "containerPort" = "8080"
        "hostPort" = "8080"
        "protocol" = "tcp"
      }),
    ]
    

    I can't say why this happens and couldn't find a way for disable this behaviour, but if you move this [for ...] to the upper layer, all start to works as expected:

    locals {
         all_ports = ["8080"]
    
         host_ports = [for port in local.all_ports: {"containerPort": tonumber(port), "hostPort": tonumber(port), "protocol": "tcp"}]
    
         container_ports = [for port in local.all_ports: {"containerPort": tonumber(port), "protocol": "tcp"}]
    
         port_mappings = var.ecs_task_definition_network_mode == "host" ? local.host_ports : local.container_ports
    
    }
    
    $ terraform console
    > local.port_mappings
    [
      {
        "containerPort" = 8080
        "hostPort" = 8080
        "protocol" = "tcp"
      },
    ]
    

    Look at the second output - we don't have additional tomap() function, and I believe because of this we have a numbers instead of strings.