When to Use Iterators
Use iterators when you need to reference dynamic data that is not known until after Terraform (or OpenTofu) applies a configuration. For example, instance IDs that cloud providers assign on creation. When data is static or you know the values before synthesizing your code, we recommend using loops in your preferred programming language.Define Iterators
Import theTerraformIterator class and call the .fromList() or .fromMap() static method. Then use the forEach property to pass the iterator to a resource, data source, or module. This lets you use the iterator in attributes.
The following example uses an iterator to create a unique name for each new S3 bucket.
count.index property.
Using Iterators on Complex Types
The iterator also exposes methods to access nested attributes. The following example uses thegetString and getStringMap methods to access the name and tags attributes of each list item.
Using Iterators on Complex Lists
There are resources with attributes which are lists of objects whose properties are not all known at plan time. When trying to iterate over these directly, Terraform will error and complain about an invalidfor_each argument. To workaround this problem, you can use the TerraformIterator.fromComplexList() method to create an iterator that transforms the list of objects into a map first, which has a key that is known at plan time and whose name is passed to that method. This is common for the aws_acm_certificate resource, whose domain_validation_options attribute is a list of objects with a domain_name property that is known at plan time.
The following example validates an ACM certificate through DNS validation:
Using Iterators for List Attributes
You can also use iterators to create a list of objects based on each item in a list and assign the result as a value to a property of a resource. This is equivalent to usingArray.map in TypeScript and using dynamic blocks in a Terraform HCL configuration.
Use iterators for list attributes if the length of the list is not known before deploying. Otherwise, use native functions that are available in your language (e.g., Array.map in TypeScript).
The following examples use an iterator to create a team containing each member of an organization.
Chaining Iterators
Sometimes the need arises to loop over resources created through an iterator; commonly referred to as chaining. To chain iterators you can use theTerraformIterator.fromResources or TerraformIterator.fromDataSources methods with the resource or data source you want to chain as an argument.
Using for expressions
To use the values of an iterator for example in a list attribute for a resource you can use one of the following methods (given thatiterator got created through one of the static methods on TerraformIterator):
iterator.keys(): Results in equivalent of[for k, v in var.iteratorSource : k].iterator.values(): Results in equivalent of[for k, v in var.iteratorSource : v].iterator.pluckProperty("foo"): Results in equivalent of[for k, v in var.iteratorSource : v.foo].iterator.forExpressionForList('uppercase(val.owner) if val.owner != ""'): Results in equivalent of[ for key, val in toset(var.list): uppercase(val.owner) if val.owner != "" ].iterator.forExpressionForMap("val.teamName",join(”,”, val.teamMembers) if length(val.teamMembers) > 0): Results in equivalent of{ for key, val in toset(var.list): val.teamName => join(",", val.teamMembers) if length(val.teamMembers) > 0 }.
Using Count
You can also use theTerraformCount class to achieve the equivalent of setting count on resources in HCL Terraform. Refer to the Terraform docs for more information on the count meta argument.
This is useful when there’s a numeric value that is only known at runtime that affects the amount of resources that should be created and those resources are almost identical. For most cases, however, Iterators are preferred over count. Refer to the Terraform docs for the underlying reasons.
The following examples use TerraformCount to create a specific amount of instances that is defined via a Terraform variable.