【问题标题】:Dynamically refer to a Terraform data resource by variable containing its name通过包含名称的变量动态引用 Terraform 数据资源
【发布时间】:2021-12-03 06:59:23
【问题描述】:

我正在尝试连接 Terraform 数据分配中声明的变量以构建动态调用。

有以下代码:

# Policy 1
data "aws_iam_policy_document" "1_s3_access_policy" {
   statement {
     effect = "Allow"
     actions = [
      "s3:GetObject",
      "s3:PutObject",
      "s3:DeleteObject",
     ]
     resources = [
      "arn:aws:s3:::1_s3_access_policy/*",
      "arn:aws:s3:::1_s3_access_policy",
     ]
     principals {
      type        = "AWS"
      identifiers = ["arn:aws:iam::67435677645:user/d2c-user-us-west-1"]
     }
   }
 }
# policy 2
data "aws_iam_policy_document" "2_s3_access_policy" {
    statement {
     effect = "Allow"
     actions = [
      "s3:GetObject",
      "s3:PutObject",
      "s3:DeleteObject",
     ]
     resources = [
      "arn:aws:s3:::2_s3_access_policy/*",
      "arn:aws:s3:::2_s3_access_policy",
     ]
     principals {
      type        = "AWS"
      identifiers = ["arn:aws:iam::67435677645:user/d2c-user-us-west-1"]
     }
   }
 }
# Policy 3
...
variable "s3_bucket_names" {
      type    = list(any)
      default = ["1_s3_access_policy", "2_s3_access_policy", "3_s3_access_policy"]
}

module "platform-cloud" {
      source              = "./module"
      count               = length(var.s3_bucket_names) //count will be 3
      bucket_name         = var.s3_bucket_names[count.index]
      sse_algorithm       = "aws:kms"
      iam_policy_document =  data.aws_iam_policy_document.${var.s3_bucket_names[count.index]}.json
}

失败并出现错误:

Error: Invalid character

on main.tf line 10, in module "platform-cloud":

iam_policy_document = data.aws_iam_policy_document.${var.s3_bucket_names[count.index]}.json

This character is not used within the language.

有没有办法在 terraform data 调用中连接变量?

【问题讨论】:

    标签: amazon-web-services terraform terraform-provider-aws


    【解决方案1】:

    Terraform 无法以您尝试的方式动态查找资源,因为这意味着在评估时间之前不会决定资源依赖关系,但 Terraform 需要在评估任何表达式之前知道正确的依赖关系顺序。

    但是,您可以满足您的用例动态选择资源的额外步骤,即使用键创建映射,然后您将使用这些键来选择每个资源:

    locals {
      bucket_policies = {
        s3_access_policy_1 = data.aws_iam_policy_document.s3_access_policy_1
        s3_access_policy_2 = data.aws_iam_policy_document.s3_access_policy_2
        s3_access_policy_3 = data.aws_iam_policy_document.s3_access_policy_3
      }
    }
    
    module "platform-cloud" {
      source = "./module"
      count  = length(var.s3_bucket_names) //count will be 3
    
      bucket_name         = var.s3_bucket_names[count.index]
      sse_algorithm       = "aws:kms"
      iam_policy_document = local.bucket_policies[var.s3_bucket_names[count.index]].json
    }
    

    我已将您的数据资源的名称更改为 s3_access_policy_1 而不是 1_s3_access_policy,因为 Terraform 不允许资源名称以数字开头。 Terraform 尚未报告该错误消息,因为您有语法错误,但解决语法错误会暴露命名错误。

    请注意,现在module.platform-cloudiam_policy_document 指的是整个local.bucket_policies,而这又依赖于所有三个数据资源。因此,Terraform 明白它必须在评估模块参数之前评估所有这三个数据资源,这会产生正确的评估顺序。


    虽然与您的问题没有直接关系,但我建议您阅读When to use for_each instead of count 以决定在您的module "platform-cloud" 块中使用for_each 是否会更好,而不是count

    【讨论】:

    • 好方法!!只需要修改data.aws_iam_policy_document 而不是data.aws_iam_policy 就可以了。可能我用数字命名我的存储桶和策略代码示例有点混乱,但在实际情况下存储桶名称不同,因此只需要在 本地存储桶策略变量中分配正确的名称>。谢谢老哥!
    【解决方案2】:

    通常你会这样做:

    iam_policy_document =  data.aws_iam_policy_document[var.s3_bucket_names[count.index]].json
    

    具体细节取决于data.aws_iam_policy_document 的定义方式。但遗憾的是,您的问题中没有提供此类信息。

    【讨论】:

    • 语法是正确的,但是count在这里会失效。同意信息不足以提供“完整”答案。
    • 我已经编辑并添加了包含数据内容的代码。我已经尝试过上面的@Marcin 评论,但仍然失败。
    • iam_policy_document = data.aws_iam_policy_document[var.s3_bucket_names[count.index]].json The "data" object must be followed by two attribute names: the data source type and the resource name.
    • @Sallyerik 你不能做你想做的事。您必须完全重构您的 data.aws_iam_policy_document 定义。我建议针对这个新问题提出新问题。
    • count 工作正常,var 只是想指出数据对象的 资源名称。我认为data 对象的内容应该不会增加太多价值,是吗?
    猜你喜欢
    • 2022-10-13
    • 2016-12-01
    • 2018-03-03
    • 2021-01-03
    • 1970-01-01
    • 2020-01-13
    • 2017-08-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多