I'm trying to concatenate a declared variable within the Terraform data assignation to build a dynamic call.
Having the following code:
# 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
}
It's failing with error:
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.
Is there a way to concatenate a variable within terraform data call?
CodePudding user response:
Normally you would do this as follows:
iam_policy_document = data.aws_iam_policy_document[var.s3_bucket_names[count.index]].json
Exact details would depend on how data.aws_iam_policy_document
is defined. But sadly such information is not given in your question.
CodePudding user response:
Terraform cannot dynamically look up a resource in the way you are attempting because that would mean that the resource dependency would not be decided until evaluation time, but Terraform needs to know the correct dependency order before evaluating any expressions.
However, you can meet your use-case of dynamically selecting a resource with the extra step of creating a mapping using the keys that you'll then use to select each one:
locals {
bucket_policies = {
s3_access_policy_1 = data.aws_iam_policy.s3_access_policy_1
s3_access_policy_2 = data.aws_iam_policy.s3_access_policy_2
s3_access_policy_3 = data.aws_iam_policy.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
}
I have changed the names of your data resources to be like s3_access_policy_1
instead of 1_s3_access_policy
because Terraform does not allow resource names to start with digits. Terraform isn't reporting that error message yet because you have a syntax error, but resolving the syntax error would've then exposed the naming error.
Notice that now module.platform-cloud
's iam_policy_document
refers to the whole of local.bucket_policies
, which in turn depends on all three of the data resources. Terraform therefore understands that it must evaluate all three of those data resources before evaluating that module argument, which produces a correct evaluation order.
Although not directly related to your question, I'd recommend reading When to use for_each
instead of count
to decide whether it might be better to use for_each
in your module "platform-cloud"
block, instead of count
.