The for_each Meta-Argument
The for_each
meta-argument accepts a map or a set of strings, and creates an instance for each item in that map or set. Each instance has a distinct infrastructure object associated with it, and each is separately created, updated, or destroyed when the configuration is applied.
Example
In this case, the for_each meta-argument is used to create multiple DNS records based on a map of DNS records defined in the dns_records variable.
variable "dns_records" {
default = {
"record1" = {
recordType = "A"
ttl = 60
target = "172.233.190.92"
name = "origin.example.com"
},
"record2" = {
recordType = "MX"
ttl = 60
target = "10 email.example.com"
name = "example.com"
}
}
}
The above is a map of objects, in other words a list of "JSON-like" objects. This structure allows to add more information for each DNS record such as the recordType
, ttl
, target
and name
. With the help of for_each
all thees values can be used of each resource instance.
resource "akamai_dns_record" "tf_demo_dns_records" {
for_each = var.dns_records
zone = "example.com"
recordtype = each.value.recordType
ttl = each.value.ttl
target = [each.value.target]
name = each.value.name
}
for_each = var.additional_records
tells Terraform to create one akamai_dns_record
resource per element in the dns_records
map.
Inside the resource block, you can access the current map element's key using each.key
(e.g., "record1") and the value using each.value
(which is another map with recordType, ttl, target, and name properties).
Using each.key
to refer to the instances created by for_each
:
akamai_dns_record.my_dns_hostnames["record1"]
akamai_dns_record.my_dns_hostnames["record2"]
Using each.value
to populate the resource attributes
recordtype = each.value.recordType
ttl = each.value.ttl
target = [each.value.target]
name = each.value.name
So, in this example, the for_each
will create a single akamai_dns_record
resource with the values from the "record1" and "record2" elements of the dns_records
map.
The key benefit of using for_each in this case is the ability to easily add or remove DNS records by updating the dns_records
variable, without having to modify the resource configuration itself.
for_each
vs. count
The main difference between count
and for_each
in Terraform is the way they handle iteration and resource identification.
count
- Allows you to create multiple instances of a resource based on a numerical value.
- The resources are identified by their numerical index, e.g.
akamai_dns_record.my_dns_hostnames[0]
,akamai_dns_record.my_dns_hostnames[1]
. - You cannot use
count
andfor_each
on the same resource block.
for_each
- Allows you to create multiple instances of a resource based on a map or set of strings.
- The resources are identified by the map keys or set elements, e.g.
akamai_dns_record.my_dns_hostnames["record1"]
,akamai_dns_record.my_dns_hostnames["record2"]
. - You cannot use a numerical list with for_each.
Exercise
Update
Create the following variable in your variables.tf:
variable "dns_records" {
default = {
"orgigin1" = {
zone = "example.com"
recordType = "A"
ttl = 60
target = "172.233.190.92"
name = "origin-www.example.com"
},
"origin2" = {
zone = "example.com"
recordType = "A"
ttl = 100
target = "173.233.190.93"
name = "origin-api.example.com"
},
"origin3" = {
zone = "example.com"
recordType = "A"
ttl = 600
target = "174.233.190.94"
name = "origin-blog.example.com"
}
}
}
Configure
In your dns.tf with the use of the for_each
meta-argument and a single akamai_dns_record
resource block create all 3 DNS records from the dns_records
variable above. The values for all the arguments must be Terraform expressions.
Plan/Apply
Run terraform
Commit
Commit your change and push it to GitHub.