I am seeking to create a two json objects for each Terraform templatefile iteration.
Template
${jsonencode({
rules = flatten([
[ for index, value in schemas : {
"rule-type": "selection",
"rule-id": "${index + 1}",
"object-locator": {
"schema-name": "${value}",
"table-name": "%"
},
}
],
])
})}
Invoke
variable "schemas" {
default = ["xxx", "yyy", "zzz"]
}
output "json_rules" {
value = templatefile("${path.module}/rules.json.tpl", {
schemas = var.schemas
})
}
Output
{
"rules": [
{
"object-locator": {
"schema-name": "xxx",
"table-name": "%"
},
"rule-id": 1,
"rule-type": "selection"
},
{
"object-locator": {
"schema-name": "yyy",
"table-name": "%"
},
"rule-id": 2,
"rule-type": "selection"
},
{
"object-locator": {
"schema-name": "zzz",
"table-name": "%"
},
"rule-id": 3,
"rule-type": "selection"
}
]
}
Required Output
{
"rules": [
{
"object-locator": {
"schema-name": "xxx",
"table-name": "%"
},
"rule-id": 1,
"rule-type": "selection"
},
{
"rule-type": "transformation",
"rule-id": "2",
"rule-action": "rename",
"rule-target": "schema",
"object-locator": {
"schema-name": "xxx"
},
"value": "xxx"
},
{
"object-locator": {
"schema-name": "yyy",
"table-name": "%"
},
"rule-id": 3,
"rule-type": "selection"
},
{
"rule-type": "transformation",
"rule-id": "4",
"rule-action": "rename",
"rule-target": "schema",
"object-locator": {
"schema-name": "yyy"
},
"value": "yyy"
},
{
"object-locator": {
"schema-name": "zzz",
"table-name": "%"
},
"rule-id": 5,
"rule-type": "selection"
},
{
"rule-type": "transformation",
"rule-id": "6",
"rule-action": "rename",
"rule-target": "schema",
"object-locator": {
"schema-name": "zzz"
},
"value": "zzz"
},
]
}
Any tips or ideas on how this can be achieved would be appreciated.
#Edit 1
By updating the templatefile as seen below it creates the required output, but the index is not working correctly
${jsonencode({
rules = flatten([
[ for index, value in schemas : [
{
"rule-type": "selection",
"rule-id": index + 1,
"object-locator": {
"schema-name": "${value}",
"table-name": "%"
}
},
{
"rule-type": "transformation",
"rule-id": index + 2
"rule-action": "rename",
"rule-target": "schema",
"object-locator": {
"schema-name": "${value}"
}
}]
],
])
})}
Revised Output
{
"rules": [
{
"object-locator": {
"schema-name": "xxx",
"table-name": "%"
},
"rule-id": 1,
"rule-type": "selection"
},
{
"object-locator": {
"schema-name": "xxx"
},
"rule-action": "rename",
"rule-id": 2,
"rule-target": "schema",
"rule-type": "transformation"
},
{
"object-locator": {
"schema-name": "yyy",
"table-name": "%"
},
"rule-id": 2,
"rule-type": "selection"
},
{
"object-locator": {
"schema-name": "yyy"
},
"rule-action": "rename",
"rule-id": 3,
"rule-target": "schema",
"rule-type": "transformation"
},
{
"object-locator": {
"schema-name": "zzz",
"table-name": "%"
},
"rule-id": 3,
"rule-type": "selection"
},
{
"object-locator": {
"schema-name": "zzz"
},
"rule-action": "rename",
"rule-id": 4,
"rule-target": "schema",
"rule-type": "transformation"
}
]
}
I am seeking to create a two json objects for each Terraform templatefile iteration.
Template
${jsonencode({
rules = flatten([
[ for index, value in schemas : {
"rule-type": "selection",
"rule-id": "${index + 1}",
"object-locator": {
"schema-name": "${value}",
"table-name": "%"
},
}
],
])
})}
Invoke
variable "schemas" {
default = ["xxx", "yyy", "zzz"]
}
output "json_rules" {
value = templatefile("${path.module}/rules.json.tpl", {
schemas = var.schemas
})
}
Output
{
"rules": [
{
"object-locator": {
"schema-name": "xxx",
"table-name": "%"
},
"rule-id": 1,
"rule-type": "selection"
},
{
"object-locator": {
"schema-name": "yyy",
"table-name": "%"
},
"rule-id": 2,
"rule-type": "selection"
},
{
"object-locator": {
"schema-name": "zzz",
"table-name": "%"
},
"rule-id": 3,
"rule-type": "selection"
}
]
}
Required Output
{
"rules": [
{
"object-locator": {
"schema-name": "xxx",
"table-name": "%"
},
"rule-id": 1,
"rule-type": "selection"
},
{
"rule-type": "transformation",
"rule-id": "2",
"rule-action": "rename",
"rule-target": "schema",
"object-locator": {
"schema-name": "xxx"
},
"value": "xxx"
},
{
"object-locator": {
"schema-name": "yyy",
"table-name": "%"
},
"rule-id": 3,
"rule-type": "selection"
},
{
"rule-type": "transformation",
"rule-id": "4",
"rule-action": "rename",
"rule-target": "schema",
"object-locator": {
"schema-name": "yyy"
},
"value": "yyy"
},
{
"object-locator": {
"schema-name": "zzz",
"table-name": "%"
},
"rule-id": 5,
"rule-type": "selection"
},
{
"rule-type": "transformation",
"rule-id": "6",
"rule-action": "rename",
"rule-target": "schema",
"object-locator": {
"schema-name": "zzz"
},
"value": "zzz"
},
]
}
Any tips or ideas on how this can be achieved would be appreciated.
#Edit 1
By updating the templatefile as seen below it creates the required output, but the index is not working correctly
${jsonencode({
rules = flatten([
[ for index, value in schemas : [
{
"rule-type": "selection",
"rule-id": index + 1,
"object-locator": {
"schema-name": "${value}",
"table-name": "%"
}
},
{
"rule-type": "transformation",
"rule-id": index + 2
"rule-action": "rename",
"rule-target": "schema",
"object-locator": {
"schema-name": "${value}"
}
}]
],
])
})}
Revised Output
{
"rules": [
{
"object-locator": {
"schema-name": "xxx",
"table-name": "%"
},
"rule-id": 1,
"rule-type": "selection"
},
{
"object-locator": {
"schema-name": "xxx"
},
"rule-action": "rename",
"rule-id": 2,
"rule-target": "schema",
"rule-type": "transformation"
},
{
"object-locator": {
"schema-name": "yyy",
"table-name": "%"
},
"rule-id": 2,
"rule-type": "selection"
},
{
"object-locator": {
"schema-name": "yyy"
},
"rule-action": "rename",
"rule-id": 3,
"rule-target": "schema",
"rule-type": "transformation"
},
{
"object-locator": {
"schema-name": "zzz",
"table-name": "%"
},
"rule-id": 3,
"rule-type": "selection"
},
{
"object-locator": {
"schema-name": "zzz"
},
"rule-action": "rename",
"rule-id": 4,
"rule-target": "schema",
"rule-type": "transformation"
}
]
}
The main problem is that you're trying to create the rule numbers based off of just the index. Since var.schemas
is a tuple, you can use the index()
function to adjust your rule ID calculation.
To make things simpler within the answer, I've added a rules
output and removed the templatefile
call so everything exists in a single file but you can apply the same logic within the template if needed.
$ terraform --version
Terraform v1.10.3
on linux_amd64
variable "schemas" {
default = ["xxx", "yyy", "zzz"]
}
locals {
rules = flatten([for i, value in var.schemas : [
{
rule-type : "selection",
rule-id : index(var.schemas, value) + i + 1,
object-locator : {
schema-name : "${value}",
table-name : "%"
}
},
{
rule-type : "transformation",
rule-id : index(var.schemas, value) + i + 2
rule-action : "rename",
rule-target : "schema",
object-locator : {
schema-name : "${value}"
}
}]
])
json_rules = jsonencode({
rules = local.rules
})
}
output "rules" {
value = local.rules
}
output "json_rules" {
value = local.json_rules
}
Running terraform apply
gives us
Changes to Outputs:
+ json_rules = jsonencode(
{
+ rules = [
+ {
+ object-locator = {
+ schema-name = "xxx"
+ table-name = "%"
}
+ rule-id = 1
+ rule-type = "selection"
},
+ {
+ object-locator = {
+ schema-name = "xxx"
}
+ rule-action = "rename"
+ rule-id = 2
+ rule-target = "schema"
+ rule-type = "transformation"
},
+ {
+ object-locator = {
+ schema-name = "yyy"
+ table-name = "%"
}
+ rule-id = 3
+ rule-type = "selection"
},
+ {
+ object-locator = {
+ schema-name = "yyy"
}
+ rule-action = "rename"
+ rule-id = 4
+ rule-target = "schema"
+ rule-type = "transformation"
},
+ {
+ object-locator = {
+ schema-name = "zzz"
+ table-name = "%"
}
+ rule-id = 5
+ rule-type = "selection"
},
+ {
+ object-locator = {
+ schema-name = "zzz"
}
+ rule-action = "rename"
+ rule-id = 6
+ rule-target = "schema"
+ rule-type = "transformation"
},
]
}
)
+ rules = [
+ {
+ object-locator = {
+ schema-name = "xxx"
+ table-name = "%"
}
+ rule-id = 1
+ rule-type = "selection"
},
+ {
+ object-locator = {
+ schema-name = "xxx"
}
+ rule-action = "rename"
+ rule-id = 2
+ rule-target = "schema"
+ rule-type = "transformation"
},
+ {
+ object-locator = {
+ schema-name = "yyy"
+ table-name = "%"
}
+ rule-id = 3
+ rule-type = "selection"
},
+ {
+ object-locator = {
+ schema-name = "yyy"
}
+ rule-action = "rename"
+ rule-id = 4
+ rule-target = "schema"
+ rule-type = "transformation"
},
+ {
+ object-locator = {
+ schema-name = "zzz"
+ table-name = "%"
}
+ rule-id = 5
+ rule-type = "selection"
},
+ {
+ object-locator = {
+ schema-name = "zzz"
}
+ rule-action = "rename"
+ rule-id = 6
+ rule-target = "schema"
+ rule-type = "transformation"
},
]
You can apply this plan to save these new output values to the Terraform state, without changing any real infrastructure.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
Outputs:
json_rules = "{\"rules\":[{\"object-locator\":{\"schema-name\":\"xxx\",\"table-name\":\"%\"},\"rule-id\":1,\"rule-type\":\"selection\"},{\"object-locator\":{\"schema-name\":\"xxx\"},\"rule-action\":\"rename\",\"rule-id\":2,\"rule-target\":\"schema\",\"rule-type\":\"transformation\"},{\"object-locator\":{\"schema-name\":\"yyy\",\"table-name\":\"%\"},\"rule-id\":3,\"rule-type\":\"selection\"},{\"object-locator\":{\"schema-name\":\"yyy\"},\"rule-action\":\"rename\",\"rule-id\":4,\"rule-target\":\"schema\",\"rule-type\":\"transformation\"},{\"object-locator\":{\"schema-name\":\"zzz\",\"table-name\":\"%\"},\"rule-id\":5,\"rule-type\":\"selection\"},{\"object-locator\":{\"schema-name\":\"zzz\"},\"rule-action\":\"rename\",\"rule-id\":6,\"rule-target\":\"schema\",\"rule-type\":\"transformation\"}]}"
rules = [
{
"object-locator" = {
"schema-name" = "xxx"
"table-name" = "%"
}
"rule-id" = 1
"rule-type" = "selection"
},
{
"object-locator" = {
"schema-name" = "xxx"
}
"rule-action" = "rename"
"rule-id" = 2
"rule-target" = "schema"
"rule-type" = "transformation"
},
{
"object-locator" = {
"schema-name" = "yyy"
"table-name" = "%"
}
"rule-id" = 3
"rule-type" = "selection"
},
{
"object-locator" = {
"schema-name" = "yyy"
}
"rule-action" = "rename"
"rule-id" = 4
"rule-target" = "schema"
"rule-type" = "transformation"
},
{
"object-locator" = {
"schema-name" = "zzz"
"table-name" = "%"
}
"rule-id" = 5
"rule-type" = "selection"
},
{
"object-locator" = {
"schema-name" = "zzz"
}
"rule-action" = "rename"
"rule-id" = 6
"rule-target" = "schema"
"rule-type" = "transformation"
},
]
Thank you user202311 and Ngenator, both approaches work very well.
rule-id : index(var.schemas, value) + i + 1
or
rule-id : i * 2 + 1
index + 1
toindex * 2 + 1
andindex + 2
toindex * 2 + 2
. – Man made of meat Commented Jan 2 at 18:35