Terraform For each iteration
This is to explain Terraform for each looping technique. In this example, 3 buckets are created to demonstrate the looping idea.
In the first step, we will create the above 3 buckets starting from 0.
Simple Example
This is a simple example1 where you have only string interpolations in the local variables. In the main.tf file:
terraform {
required_version = ">=0.12.0"
}
provider "aws" {
version = "~> 2.0"
region = "ap-southeast-2"
profile = "dev"
}
variable "bucket_owner" {
type = string
default = "oj"
}
locals {
bucket_prefix= "${data.aws_caller_identity.current.account_id}-${var.bucket_owner}-${local.bucket_resource}"
bucket_resource = "bucket"
}
resource "aws_s3_bucket" "bucket0" {
bucket = "${local.bucket_prefix}0"
}
resource "aws_s3_bucket" "bucket1" {
bucket = "${local.bucket_prefix}1"
tags = {
"dependency" = aws_s3_bucket.bucket0.arn
}
}
resource "aws_s3_bucket" "bucket2" {
bucket = "${local.bucket_prefix}2"
#Explicit
depends_on = [aws_s3_bucket.bucket1]
}
data "aws_caller_identity" "current" {
}
data "aws_availability_zones" "available" {
state = "available"
}
output "bucket1_info" {
value = aws_s3_bucket.bucket1
}
output "bucket2_info" {
value = aws_s3_bucket.bucket1
}
output "aws_caller_info" {
value = data.aws_caller_identity.current
}
output "aws_availability_zones" {
value = data.aws_availability_zones.available
}
output "aws_caller_identity_account_id" {
value = data.aws_caller_identity.current
}
The bucket name is composed in line #19 under the local variables.
Count
You can use the count.index
to start the base number. For example, if the count value is 3, the bucket is 1 to 2, not starting from zero.
terraform {
required_version = ">=0.12.0"
}
provider "aws" {
version = "~> 2.0"
region = "ap-southeast-2"
profile = "dev"
}
variable "bucket_owner" {
type = string
default = "oj"
}
locals {
bucket_prefix= "${data.aws_caller_identity.current.account_id}-${var.bucket_owner}-${local.bucket_resource}"
bucket_resource = "bucket"
}
resource "aws_s3_bucket" "bucket" {
count = 3
bucket = "${local.bucket_prefix}${count.index}"
}
# resource "aws_s3_bucket" "bucket1" {
# bucket = "${local.bucket_prefix}1"
# tags = {
# "dependency" = aws_s3_bucket.bucket0.arn
# }
# }
# resource "aws_s3_bucket" "bucket2" {
# bucket = "${local.bucket_prefix}2"
# #Explicit
# depends_on = [aws_s3_bucket.bucket1]
# }
data "aws_caller_identity" "current" {
}
data "aws_availability_zones" "available" {
state = "available"
}
output "bucket_info" {
value = aws_s3_bucket.bucket
}
# output "bucket2_info" {
# value = aws_s3_bucket.bucket2
# }
output "aws_caller_info" {
value = data.aws_caller_identity.current
}
output "aws_availability_zones" {
value = data.aws_availability_zones.available
}
output "aws_caller_identity_account_id" {
value = data.aws_caller_identity.current
}
The above provision script is simplified as follows:
The magic count has been used in lines #24-25.
For each
Here,
terraform {
required_version = ">=0.12.0"
}
provider "aws" {
version = "~> 2.0"
region = "ap-southeast-2"
profile = "dev"
}
variable "bucket_owner" {
type = string
default = "oj"
}
locals {
bucket_prefix= "${data.aws_caller_identity.current.account_id}-${var.bucket_owner}-${local.bucket_resource}"
bucket_resource = "bucket"
}
locals {
buckets = {
bucket0 = "0"
bucket1 = "1"
bucket2 = "2"
}
}
resource "aws_s3_bucket" "bucket" {
for_each = local.buckets
bucket = "${local.bucket_prefix}${each.value}"
}
# resource "aws_s3_bucket" "bucket1" {
# bucket = "${local.bucket_prefix}1"
# tags = {
# "dependency" = aws_s3_bucket.bucket0.arn
# }
# }
# resource "aws_s3_bucket" "bucket2" {
# bucket = "${local.bucket_prefix}2"
# #Explicit
# depends_on = [aws_s3_bucket.bucket1]
# }
data "aws_caller_identity" "current" {
}
data "aws_availability_zones" "available" {
state = "available"
}
output "bucket_info" {
value = aws_s3_bucket.bucket
}
# output "bucket2_info" {
# value = aws_s3_bucket.bucket2
# }
output "aws_caller_info" {
value = data.aws_caller_identity.current
}
output "aws_availability_zones" {
value = data.aws_availability_zones.available
}
output "aws_caller_identity_account_id" {
value = data.aws_caller_identity.current
}
In the above code, the count
has been replaced by the foreach
lines 23-34 as follows:
You can change the above code’s map to list as follows:
locals {
buckets = ["0","1","2"]
}
resource "aws_s3_bucket" "bucket" {
for_each = toset(local.buckets)
bucket = "${local.bucket_prefix}${each.key}"
}
As shown in lines #1-3, only the list elements are created as buckets. Please note how line #6 has been changed to return set. In line #7 instead of each.value
now we are using each.key
.