Loops 在地形代码中连接文件路径前缀和文件名

Loops 在地形代码中连接文件路径前缀和文件名,loops,terraform,concat,terraform-provider-aws,Loops,Terraform,Concat,Terraform Provider Aws,我正在尝试使用terraform在aws中创建策略 variable "path" { type = "string" } variable "policies" { type = list(object ({ name = string plcyfilename = string asmplcyfilename = string desc = string ownner = string})) default = []

我正在尝试使用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.
我用的是地形0.12

如果我将变量更改为具有完整的文件路径:
plcyfilename=./../t2/scripts/cw.json
,它将按预期工作

但是,我想将文件路径与文件名隔离开来

有人能告诉我哪里出了问题。

用于连接列表,而不是连接字符串

要在Terraform中连接字符串,我们使用:


由于您的策略集合不是顺序重要的序列,因此我建议您也将其更改为使用,这将确保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[“cw”]
,而不是
aws_iam_policy.policy[1]
,因此从地图中添加和删除元素将导致Terraform从资源中添加和删除相应的实例,而不是像您的示例那样尝试就地更新实例以尊重列表顺序。

非常感谢Martin。。这比我的整洁多了
  policies = {
    cw = {
      policy_filename        = "cw.json"
      assume_policy_filename = "csasm.json"
      description            = "vpcflowlogs"
      owner                  = "vpc"
    }
    # ...
  }