Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the iterator feature for in Terraform's for_each?

Tags:

terraform

I am trying to understand the iterator feature of the for_each in Terraform 0.12. The docs say:

Iterator:

The iterator argument (optional) sets the name of a temporary variable that represents the current element of the complex value. If omitted, the name of the variable defaults to the label of the dynamic block ...

But I can't find any code examples that uses this feature and I can't get my head around what it is for. I have read the Terraform 0.12 preview but it is not mentioned there, and I found some GitHub issues (e.g. this one) but can't find clues there either.

Is it just for improving readability? I would really appreciate a code example and explanation that goes beyond what I can find in the docs.

like image 790
Alex Harvey Avatar asked Jun 04 '19 11:06

Alex Harvey


1 Answers

Basically in various languages like Python, Ruby, C++, Javascript, Groovy, etc. you can establish a temporary variable within a lambda (especially if it is iterative) that stores the temporary value per iteration within the lambda. In some languages (e.g. Groovy), there is a default name for this variable, or you can set one yourself (i.e. default variable name in Groovy is it). For example, in Groovy we have:

strings.each() {
  print it
}

would print the content of the string variable assignment (assuming it can be cast to String). The following code has the exact same functionality:

strings.each() { a_string ->
  print a_string
}

where we have explicitly named the temporary variable as a_string. This is analogous to the iterator argument in your question. So in Terraform, we see an example in the documentation:

resource "aws_security_group" "example" {
  name = "example" # can use expressions here

  dynamic "ingress" {
    for_each = var.service_ports
    content {
      from_port = ingress.value
      to_port   = ingress.value
      protocol  = "tcp"
    }
  }
}

According to the documentation:

If omitted, the name of the variable defaults to the label of the dynamic block

and the name above is ingress (notice it is the label specified adjacent to the dynamic block). Sure enough, we see the name of the temporary variable above is ingress and it is being accessed via ingress.value. To utilize the functionality of iterator to rename this temporary variable, we can do something like the below.

resource "aws_security_group" "example" {
  name = "example" # can use expressions here

  dynamic "ingress" {
    for_each = var.service_ports
    iterator = "service_port"
    content {
      from_port = service_port.value
      to_port   = service_port.value
      protocol  = "tcp"
    }
  }
}

thus renaming the temporary variable storing the element of var.service_ports in each iteration within the lambda from default name ingress to service_port. The primary added value I see in this (and likewise when I use it in Groovy for Jenkins Pipeline libraries) is to provide a more clear name for the temporary variable storing the value to improve readability.

like image 187
Matt Schuchard Avatar answered Oct 10 '22 20:10

Matt Schuchard