Reputation: 63
I am creating an AWS Stack Set (at org level) which is written in cloud formation. For the cloud formation, it is written in a terraform template file so that variables are passed from terraform. However there one part which I am having issues with.
The for
section needs to look the principals and create Principal
block in the template. However the last index of the loop contains a comma which will makes the stack template invalid.
Is there away in terraform to prevent the last comma in a loop?
main.tf:
variable "cross_account" {
type = list(object({
principals = list(string)
}))
default = [
{
principals = ["ACCOUNT_ID1","ACCOUNT_ID2","ACCOUNT_ID3"]
}
]
}
output "test" {
value = templatefile("./json.tpl", {
principals = var.cross_account[0].principals
})
}
Template file (json.tpl):
"Principal": {
"AWS": [
%{ for princ in principals ~}
{
"Fn::Sub": "arn:aws:iam::${princ}:root"
}
, # <--------------- Need to prevent this line on the last loop index
%{ endfor ~}
]
I have shorten the code down to only the bits needed above. Thanks
Upvotes: 6
Views: 4256
Reputation: 31
I ran into this today, and this was my solution in case it helps anyone.
"Principal": {
"AWS": [
%{ for princ in principals ~}
{
"Fn::Sub": "arn:aws:iam::${princ}:root"
}
%{ if index(principals, princ) == length(principal)-1 }
#do nothing-here if we are on the last iteration
%{ else}
, #add the comma otherwise
%{ endif }
%{ endfor ~}
]
Upvotes: 3
Reputation: 63
After playing around for a while with the help of @Marcin, was able to get a working code:
main.tf:
variable "cross_account" {
type = list(object({
principals = list(string)
}))
default = [
{
principals = ["ACCOUNT_ID1","ACCOUNT_ID2","ACCOUNT_ID3"]
}
]
}
output "test" {
value = templatefile("./json.tpl", {
principals = jsonencode([for i in var.cross_account[0].principals: tomap({"Fn::Sub" = "arn:aws:iam::${i}:root"})])
})
}
Template file (json.tpl):
"Principal": {
"AWS": ${principals}
}
results in the following without the extra comma:
test = <<-EOT
"Principal": {
"AWS": [{"Fn::Sub":"arn:aws:iam::ACCOUNT_ID1:root"},{"Fn::Sub":"arn:aws:iam::ACCOUNT_ID2:root"},{"Fn::Sub":"arn:aws:iam::ACCOUNT_ID3:root"}]
}
EOT
Upvotes: 0
Reputation: 238081
You can use jsonencode:
"Principal": {
"AWS": ${jsonencode([
for princ in principals:
{
"Fn::Sub": "arn:aws:iam::${princ}:root"
}
])}
Or you can use it for all template as shown here depending how exactly your template is defined.
Upvotes: 3