这里是 Terraform 新手。 我想使用
for_each
迭代列表,但看起来键和值是相同的:
provider "aws" {
profile = "default"
region = "us-east-1"
}
variable "vpc_cidrs" {
default = ["10.0.0.0/16", "10.1.0.0/16"]
}
resource "aws_vpc" "vpc" {
for_each = toset(var.vpc_cidrs)
cidr_block = each.value
enable_dns_hostnames = true
tags = { Name = "Company0${each.key}" }
}
我希望标签名称为
"Name" = "Company01"
和 "Name" = "Company02"
但根据 terraform apply
,我得到:
"Name" = "Company010.0.0.0/16"
和 "Name" = "Company010.1.0.0/16"
我错过了什么?
使用 index 函数找到了一个简单的解决方案:
tags = { Name = "Company0${index(var.vpc_cidrs, each.value) + 1}" }
还有另一种方法可以在不使用
index()
的情况下实现想要的结果:
更改以下三行:
for_each = { for idx, cidr_block in var.vpc_cidrs: cidr_block => idx}
cidr_block = each.key
tags = { Name = format("Company%02d", each.value + 1) }
for_each
将使用由 cidr_block
返回的
index
到
for
cidr_block
就可以使用 each.key
值tags
中还可以在 format()
上使用 each.value
来获得带有 index
完整示例为:
provider "aws" {
profile = "default"
region = "us-east-1"
}
variable "vpc_cidrs" {
default = ["10.0.0.0/16", "10.1.0.0/16"]
}
resource "aws_vpc" "vpc" {
for_each = { for idx, cidr_block in var.vpc_cidrs: cidr_block => idx}
cidr_block = each.key
enable_dns_hostnames = true
tags = { Name = format("Company%02d", each.value + 1) }
}
for_each
与套装一起使用时,each.key
和each.value
是相同的。
要生成“Company01”、“Company02”等字符串,您需要列表中每个 CIDR 块的索引。一种方法是使用
for
表达式 创建本地地图,例如:
locals {
vpc_cidrs = {for s in var.vpc_cidrs: index(var.vpc_cidrs, s) => s}
}
resource "aws_vpc" "vpc" {
for_each = local.vpc_cidrs
cidr_block = each.value
enable_dns_hostnames = true
tags = { Name = "Company0${each.key}" }
}
作为奖励,您可以使用 format 函数来构建零填充的名称字符串:
resource "aws_vpc" "vpc" {
...
tags = { Name = format("Company%02d", each.key) }
}
您可以使用
count
函数并使用索引来执行此操作:
provider "aws" {
profile = "default"
region = "us-east-1"
}
variable "vpc_cidrs" {
type = list(string)
default = ["10.0.0.0/16", "10.1.0.0/16"]
}
resource "aws_vpc" "vpc" {
count = length(var.vpc_cidrs)
cidr_block = var.vpc_cidrs[count.index]
enable_dns_hostnames = true
tags = { Name = "Company0${count.index}" }
}
在 foreach 中你可以使用这样的东西:
provider "aws" {
profile = "default"
region = "us-east-1"
}
variable "vpc_cidrs" {
default = ["10.0.0.0/16", "10.1.0.0/16"]
}
resource "aws_vpc" "vpc" {
for_each = toset(var.vpc_cidrs)
cidr_block = each.value
enable_dns_hostnames = true
tags = { Name = "Company0${index(keys(var.vpc_cidrs), each.key)}" }
}
您可以通过以下方式获得钥匙:
keys(var.vpc_cidrs)
然后你可以在钥匙中找到钥匙:
index(keys(var.vpc_cidrs), each.key)
其中一条评论询问如何在
动态块中使用
for_each
时使用索引来实现此目的。
可以参考
<name-of-dynamic-block>.key
(key是索引)来完成。
我将采用一个用例,其中我有一个 S3 存储桶,其中包含多个文件夹,并且每个文件夹都有一个指向它的专用 Cloudfront 发行版。
假设我在 s3 存储桶中有 2 个文件夹:name1 和 name2。
所以我必须创建一个如下所示的
aws_s3_bucket_policy
:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": "<arn-of-cloudfront-distribution-1>"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::some-bucket/name1/*"
},
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": "<arn-of-cloudfront-distribution-2>"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::some-bucket/name2/*"
}
]
}
(*) 为了简洁起见,删除了 Cloudfront 发行版的创建。
因此,我有一个需要在 s3 存储桶中创建的文件夹列表:
variable "all_s3_folders" {
type = list(string)
default = []
description = "All folders inside the bucket"
}
对于每个文件夹,我创建了一个 cloudfront 发行版(为简洁起见,已删除)和 cloudfront 原始访问身份(请参阅 oai)资源。
我们将根据文件夹数量的
count
创建这些资源:
resource "aws_cloudfront_origin_access_identity" "oai" {
count = length(var.all_s3_folders)
comment = "some-comment"
}
现在我们需要将每个文件夹(及其相关的 Cloudfront 发行版和 OAI)添加为存储桶策略中的条目。
我想使用其中包含
for_each
的动态块,但不依赖于 count.index
。
但我仍然需要使用索引迭代
aws_cloudfront_origin_access_identity
资源。
那么,
为了在动态块内使用
for_each
时使用索引,您只需引用 <name-of-dynamic-block>.key
- 这里是 statement.key
data "aws_iam_policy_document" "my-doc" {
dynamic "statement" {
for_each = var.folders_array
content {
effect = "Allow"
actions = [
"s3:GetObject"
]
resources = [
"${aws_s3_bucket.my_s3_bucket.arn}/${statement.value}/*" # <--Using statement value
]
principals {
type = "AWS"
identifiers = [some_cloudfront_resource[statement.key].id] # <--Using statement key
}
}
}
}