From 6f680653265d2eca84a768e7fd2bd60148daf46b Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Mon, 10 May 2021 09:43:16 -0700 Subject: [PATCH] website: Explicit example of for_each chaining between resources This pattern follows as a natural consequence of how for_each is defined, but I've noticed from community forum Q&A that newcomers often don't immediately notice the connection between what for_each expects as input and what a for_each resource produces as a result, so my aim here is to show a short example of that in the hope of helping folks see the link here and get ideas on how to employ the technique in other situations. --- .../language/meta-arguments/for_each.html.md | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/website/docs/language/meta-arguments/for_each.html.md b/website/docs/language/meta-arguments/for_each.html.md index f382c4769..1a8bfe50b 100644 --- a/website/docs/language/meta-arguments/for_each.html.md +++ b/website/docs/language/meta-arguments/for_each.html.md @@ -147,6 +147,59 @@ For example: collections by [using the `setproduct` function inside a `for` expression](/docs/language/functions/setproduct.html#finding-combinations-for-for_each). +### Chaining `for_each` Between Resources + +Because a resource using `for_each` appears as a map of objects when used in +expressions elsewhere, you can directly use one resource as the `for_each` +of another in situations where there is a one-to-one relationship between +two sets of objects. + +For example, in AWS an `aws_vpc` object is commonly associated with a number +of other objects that provide additional services to that VPC, such as an +"internet gateway". If you are declaring multiple VPC instances using `for_each` +then you can chain that `for_each` into another resource to declare an +internet gateway for each VPC: + +```hcl +variable "vpcs" { + type = map(object({ + cidr_block = string + })) +} + +resource "aws_vpc" "example" { + # One VPC for each element of var.vpcs + for_each = var.vpcs + + # each.value here is a value from var.vpcs + cidr_block = each.value.cidr_block +} + +resource "aws_internet_gateway" "example" { + # One Internet Gateway per VPC + for_each = aws_vpc.example + + # each.value here is a full aws_vpc object + vpc_id = each.value.id +} + +output "vpc_ids" { + value = { + for k, v in aws_vpc.example : k => v.id + } + + # The VPCs aren't fully functional until their + # internet gateways are running. + depends_on = [aws_internet_gateway.example] +} +``` + +This chaining pattern explicitly and concisely declares the relationship +between the internet gateway instances and the VPC instances, which tells +Terraform to expect the instance keys for both to always change together, +and typically also makes the configuration easier to understand for human +maintainers. + ## Referring to Instances When `for_each` is set, Terraform distinguishes between the block itself