I would be appreciated for help or any idea on this task.
As you may see in locals.var Application
and Environment
keys have different values.
But as the result JSON file, these values are similar for both keys.
How to set correct corresponding values?
I guess value_tag
should be set dynamically. for_each
- creates a lot of files. Dynamically block
looks don't work for this. Also, I need it all in one JSON file.
Incorrect result
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "ec2:*",
"Resource": "*",
"Condition": {
"ForAllValues:StringEquals": {
"aws:TagKeys": [
"Application",
"Environment"
]
},
"StringEqualsIfExists": {
"aws:RequestTag/Application": [
"development",
"production"
],
"aws:RequestTag/Environment": [
"development",
"production"
]
}
}
}
]
}
Correct result should be like this
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "ec2:*",
"Resource": "*",
"Condition": {
"ForAllValues:StringEquals": {
"aws:TagKeys": [
"Application",
"Environment"
]
},
"StringEqualsIfExists": {
"aws:RequestTag/Application": [
"app-01",
"app-02"
],
"aws:RequestTag/Environment": [
"development",
"production"
]
}
}
}
]
}
locals {
enforce_tag = {
Environment = {
env01 = "development"
env02 = "production"
}
Application = {
app01 = "app-01"
app02 = "app-02"
}
}
}
data "template_file" "enforcetags" {
template = templatefile("${path.module}/enforcetags.tpl",
{
key_tag = [for key, value in local.enforce_tag : key]
value_tag = local.enforce_tag.Environment
}
)
}
Template file:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": "ec2:*",
"Resource": "*",
"Condition": {
"ForAllValues:StringEquals": {
"aws:TagKeys": ${jsonencode([for key in key_tag : "${key}"
])
}
},
"StringEqualsIfExists": ${jsonencode(
{for key in key_tag: "aws:RequestTag/${key}" => value_tag
})
}
}
}
]
}
CodePudding user response:
You are close, but a few things are missing. First comes some explanation, below you can find what I believe is the solution to your problem.
With this:
value_tag = local.enforce_tag.Environment
you only ever touch the Environment
map, there's no reference to the Application
map. Instead you can use this to pass both these maps (a map of 2 maps):
value_tag = local.enforce_tag
To avoid confusion let's call them:
- the big map called
enforce_tag
consisting of the following: - the first small map (for environments)
- the second small map (for applications)
Then in order to use it properly in the template, when iterating over your tags (Application
, Environment
) you need to take respective small map for relevant tag:
value_tag[key]
And the last thing is that you don't seem to ever use the keys in the small maps (i.e. nowhere in your desired output I can see env01
or app02
). Nevertheless, maybe you need it this way for other reasons. If so, you are interested only in the values of the small maps. Not the whole maps, i.e.
values(value_tag[key])
In short, the following should work:
Terraform
data "template_file" "enforcetags" {
template = templatefile("${path.module}/enforcetags.tpl",
{
key_tag = [for key, value in local.enforce_tag : key]
value_tag = local.enforce_tag
}
)
}
Template fragment
"StringEqualsIfExists": ${jsonencode(
{for key in key_tag: "aws:RequestTag/${key}" => values(value_tag[key])}
)
}