amazon web services - Terraform Templatefile List Of Json Objects - Stack Overflow

admin2025-05-01  1

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"
    }
  ]
}
Share Improve this question edited Jan 2 at 15:59 Theo Sweeny asked Jan 2 at 14:46 Theo SweenyTheo Sweeny 1,1473 gold badges15 silver badges31 bronze badges 1
  • Try changing index + 1 to index * 2 + 1 and index + 2 to index * 2 + 2. – Man made of meat Commented Jan 2 at 18:35
Add a comment  | 

2 Answers 2

Reset to default 1

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

main.tf

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
转载请注明原文地址:http://www.anycun.com/QandA/1746112992a91848.html