在地形代码中连接文件路径前缀和文件名
concatenate filepath prefix and file name in terraform code
我正在尝试使用 terraform 在 aws 中创建策略。
variable "path" {
type = "string"
}
variable "policies" {
type = list(object ({
name = string
plcyfilename = string
asmplcyfilename = string
desc = string
ownner = string}))
default = []
}
resource "aws_iam_policy" "policy" {
count = length(var.policies)
name = lookup(var.policies[count.index], "name")
policy = file(lookup(var.policies[count.index], concat("var.path","plcyfilename")))
description = "Policy for ${lookup(var.policies[count.index], "desc")}"
}
这就是我的 tfvar 的样子:
path = "./../t2/scripts/"
policies = [
{name = "cwpolicy", plcyfilename = "cw.json" , asmplcyfilename ="csasm.json", desc ="vpcflowlogs", ownner ="vpc"},
]
我这样做时抛出的错误是这样的:
Error: Invalid function argument
on main.tf line 13, in resource "aws_iam_policy" "policy":
13: policy = file(lookup(var.policies[count.index], "${concat("${var.path}","plcyfilename")}"))
Invalid value for "seqs" parameter: all arguments must be lists or tuples; got
string.
我正在使用 terraform 0.12。
如果我将变量更改为具有完整的文件路径,它会按预期工作:plcyfilename=./../t2/scripts/cw.json
。
但是我想将文件路径与文件名分开。
谁能指出我哪里出错了。
The concat
function 用于连接列表,而不是用于连接字符串。
为了在 Terraform 中连接字符串,我们使用 template interpolation syntax:
policy = file("${var.path}/${var.policies[count.index].policy_filename}")
由于您的策略集合不是一个顺序很重要的序列,我建议也将其更改为使用 resource for_each
,这将确保 Terraform 使用策略名称字符串而不是跟踪策略使用列表中的位置:
variable "policies" {
type = map(object({
policy_filename = string
assume_policy_filename = string
description = string
owner = string
}))
default = {}
}
resource "aws_iam_policy" "policy" {
for_each = var.policies
name = each.key
policy = file("${var.path}/${each.value.policy_filename}")
description = "Policy for ${each.value.description}"
}
在这种情况下,policies
变量被重新定义为映射,因此您现在将每个策略的名称作为映射中的键而不是属性之一显示:
policies = {
cw = {
policy_filename = "cw.json"
assume_policy_filename = "csasm.json"
description = "vpcflowlogs"
owner = "vpc"
}
# ...
}
因为 for_each
值是策略映射,资源块中的 each.key
是策略名称,而 each.value
是表示该策略的对象,使得结果表达式更容易阅读并理解。
通过使用 for_each
,我们将使 Terraform 创建类似于 aws_iam_policy.policy["cw"]
而不是 aws_iam_policy.policy[1]
的资源实例地址,因此在地图中添加和删除元素将导致 Terraform从资源中添加和删除相应的实例,而不是像您的示例那样尝试就地更新实例以遵守列表顺序。
我正在尝试使用 terraform 在 aws 中创建策略。
variable "path" {
type = "string"
}
variable "policies" {
type = list(object ({
name = string
plcyfilename = string
asmplcyfilename = string
desc = string
ownner = string}))
default = []
}
resource "aws_iam_policy" "policy" {
count = length(var.policies)
name = lookup(var.policies[count.index], "name")
policy = file(lookup(var.policies[count.index], concat("var.path","plcyfilename")))
description = "Policy for ${lookup(var.policies[count.index], "desc")}"
}
这就是我的 tfvar 的样子:
path = "./../t2/scripts/"
policies = [
{name = "cwpolicy", plcyfilename = "cw.json" , asmplcyfilename ="csasm.json", desc ="vpcflowlogs", ownner ="vpc"},
]
我这样做时抛出的错误是这样的:
Error: Invalid function argument
on main.tf line 13, in resource "aws_iam_policy" "policy":
13: policy = file(lookup(var.policies[count.index], "${concat("${var.path}","plcyfilename")}"))
Invalid value for "seqs" parameter: all arguments must be lists or tuples; got
string.
我正在使用 terraform 0.12。
如果我将变量更改为具有完整的文件路径,它会按预期工作:plcyfilename=./../t2/scripts/cw.json
。
但是我想将文件路径与文件名分开。
谁能指出我哪里出错了。
The concat
function 用于连接列表,而不是用于连接字符串。
为了在 Terraform 中连接字符串,我们使用 template interpolation syntax:
policy = file("${var.path}/${var.policies[count.index].policy_filename}")
由于您的策略集合不是一个顺序很重要的序列,我建议也将其更改为使用 resource for_each
,这将确保 Terraform 使用策略名称字符串而不是跟踪策略使用列表中的位置:
variable "policies" {
type = map(object({
policy_filename = string
assume_policy_filename = string
description = string
owner = string
}))
default = {}
}
resource "aws_iam_policy" "policy" {
for_each = var.policies
name = each.key
policy = file("${var.path}/${each.value.policy_filename}")
description = "Policy for ${each.value.description}"
}
在这种情况下,policies
变量被重新定义为映射,因此您现在将每个策略的名称作为映射中的键而不是属性之一显示:
policies = {
cw = {
policy_filename = "cw.json"
assume_policy_filename = "csasm.json"
description = "vpcflowlogs"
owner = "vpc"
}
# ...
}
因为 for_each
值是策略映射,资源块中的 each.key
是策略名称,而 each.value
是表示该策略的对象,使得结果表达式更容易阅读并理解。
通过使用 for_each
,我们将使 Terraform 创建类似于 aws_iam_policy.policy["cw"]
而不是 aws_iam_policy.policy[1]
的资源实例地址,因此在地图中添加和删除元素将导致 Terraform从资源中添加和删除相应的实例,而不是像您的示例那样尝试就地更新实例以遵守列表顺序。