Search code examples
for-loopterraformkubernetes-ingress

Dynamic block with "for each" in a variable with a list - Terraform


I have this resource and this dynamic block with this variables:

variable "services" {
  description = "Map of the Services"
  type = map(object({
    port                           = number
    uri                            = optional(string)
  }))
}
services = {

  "auth-service" = {
    port              = 3050
    uri               = "example1"
   }

"clone-service" = {
    port              = 3040
   }

}

resource "kubernetes_ingress_v1" "eks_global_ingress" {

[...]

dynamic "rule" {
     # I make this expression to bypass the services that doesn't have URI.
      for_each = { for k, v in var.services : k => v if v["uri"] != null }
      content {
        http {
          path {
            path = "/${rule.value["uri"]}/*"
            backend {
              service {
                name = "${rule.key}-i-svc"
                port {
                  number = rule.value["port"]
                }
              }
            }
          }
        }
      }
    }

At this point everything is ok, but now i want to add another URI to the same service. So i make a list in the URI like below:

services = {
  "auth-service" = {
    port              = 3050
    uri               = ["example1","example2]
  "clone-service" = {
    port              = 3040

But with this i cant include another for_each in the Dynamic Block. How can i filter null URI and at the same time, loop the code with 2 or more URI as a list?

I expect that the rule is duplicated "x" times over the number of URI present on the list, and if a URI value is not present on the map (null) the "for_each" bypass this rule.


Solution

    1. It is completely possible to use more dynamic blocks inside another dynamic block
    2. The parameter http.path is a list too of blocks so you should be able to do something like this:
          dynamic "rule" {
         # I make this expression to bypass the services that doesn't have URI.
          for_each = { for k, v in var.services : k => v if length(v["uri"]) > 0 }
          content {
            http {
              dynamic "path" {
                for_each = toset(rule.value["uri"])
                content {
                  path = "/${path.key}/*"
                  backend {
                    service {
                      name = "${rule.key}-i-svc"
                      port {
                        number = rule.value["port"]
                      }
                    }
                  }
                }
              }
            }
          }
        }
    

    Note: don't forget change the uri type from string to list(string)