首页 > 解决方案 > How to use format for list of strings in terraform 0.12.20?

问题描述

I'm creating data resource to create a policy document for allowing users to access rds, but i'm stuck on how to use format to pass account_id and rds's resource_id,

Code:

   data "aws_iam_policy_document" "iam_authentication_doc" {
      depends_on = [aws_db_instance.name]
      statement {
        effect = "Allow"
        actions = [
          "rds-db:connect"
        ]
        resources = flatten([format("arn:aws:rds-db:us-east-1:${var.account_id}:dbuser:${aws_db_instance.name.resource_id}/%s", var.usernames)])
      }
}

Error:

resources = flatten([format("arn:aws:rds-db:us-east-1:${var.account_id}:dbuser:${aws_db_instance.pgauth.resource_id}/%s", var.usernames)])
    |----------------
    | aws_db_instance.pgauth.resource_id is "db-xxxxxxxxxxxxxxxx"
    | var.account_id is 8.12345678901+11
    | var.usernames is list of string with 12 elements

Call to function "format" failed: unsupported value for "%s" at 75: string
required.

I tried passing

[formatlist("arn:aws:rds-db:us-east-1:%s:dbuser:%s/%s", var.account_id, aws_db_instance.pgauth.resource_id, var.amp_usernames)] got an error

  22:     resources = [formatlist("arn:aws:rds-db:us-east-1:%s:dbuser:%s/%s", var.account_id, aws_db_instance.name.resource_id, var.usernames)]
    |----------------
    | aws_db_instance.name.resource_id is "db-xxxxxxxxxxxxxxx"
    | var.account_id is "123456789012"
    | var.usernames is list of string with 12 elements

Inappropriate value for attribute "resources": element 0: string required.

I want resources like

arn:aws:rds-db:us-east1:1234567890:dbuser:db-xxxxxxxxxxxxxx/foo, 
arn:aws:rds-db:us-east1:1234567890:dbuser:db-xxxxxxxxxxxxxx/bar, 
arn:aws:rds-db:us-east1:1234567890:dbuser:db-xxxxxxxxxxxxxx/tim

标签: terraformamazon-rds

解决方案


第一个示例format不起作用,因为format它期望它的所有参数都是单个值并且它产生单个值。

如您所见,该formatlist函数是解决您的问题的一种方法:它生成一个列表作为其结果,如果它的任何参数是列表,那么它将为具有相同索引的每组元素重复一次格式化过程。列表。

您的第二个示例不起作用,因为您包装了对formatlistin的调用[ ... ],它构造了一个列表。因为formatlist返回一个列表本身,所以结果是一个字符串列表的列表,而不仅仅是一个字符串列表。

我们可以通过删除多余的括号来让它工作:

  resources = formatlist("arn:aws:rds-db:us-east-1:%s:dbuser:%s/%s", var.account_id, aws_db_instance.name.resource_id, var.usernames)

另一种编写方式是使用for表达式,这可能会使您的配置中的重复更加明确:

  resources = [for u in var.usernames : "arn:aws:rds-db:us-east-1:${var.account_id}:dbuser:${aws_db_instance.name.resource_id}/${u}"]

哪个更容易理解当然是主观的:该formatlist方法预先显示了格式字符串,但它暗示我们正在基于var.usernames. 表达式方法将for模板推到行尾,但它使基于var.usernames更明确的重复。


推荐阅读