PTG2021
PTG2021

Reputation: 19

Converting json to yaml in Terraform

How can we generate an yaml out from a json

{
   "users":[
      {
         "name":"rock",
         "age":33,
         "city":"paris"
      },
      {
         "name":"austin",
         "age":45,
         "city":"greece"
      }
   ]
}

Expected output with a additional field with random password

users:
  - key: 'user[0].name'
    value: rock
  - key: 'user[0].age'
    value: '33'
  - key: 'user[0].city'
    value: paris
  - key: 'user[0].password'
    value: '5]L+J7rA*<7+:PO6'
  - key: 'user[1].name'
    value: austin
  - key: 'user[1].age'
    value: '45'
  - key: 'user[1].city'
    value: greece
  - key: 'user[1].password'
    value: P=x&385YGMI0?!Is

The files are used only on a local machine.

Upvotes: 1

Views: 6157

Answers (3)

Kaushal Soni
Kaushal Soni

Reputation: 1

locals {
  users = jsondecode(file("${path.module}/user.json"))
}

resource "random_string" "password" {
 count =  length(local.users.users)
 length = 16
 special = true
}

output "pass" {
    value = random_string.password
  
}

locals {
  user_flat = yamlencode(flatten([for i,j  in local.users.users:[
   for k,v in j : {
       key = "user.[${i}].${k}"
       "value" = v
        } 
      ]
    ]
  )
)
  out = yamlencode({"users"= local.user_flat}) 
}

output "Desired_output" {
    value = local.out
}

Try this code.

Outputs:

Desired_output = <<EOT
"users": |
  - "key": "user.[0].age"
    "value": 23
  - "key": "user.[0].city"
    "value": "barcelona"
  - "key": "user.[0].name"
    "value": "john"
  - "key": "user.[1].age"
    "value": 29
  - "key": "user.[1].city"
    "value": "london"
  - "key": "user.[1].name"
    "value": "bob"

EOT
pass = [
  {
    "id" = "XEXj*svXm@d&_%Fn"
    "keepers" = tomap(null) /* of string */
    "length" = 16
    "lower" = true
    "min_lower" = 0
    "min_numeric" = 0
    "min_special" = 0
    "min_upper" = 0
    "number" = true
    "override_special" = tostring(null)
    "result" = "XEXj*svXm@d&_%Fn"
    "special" = true
    "upper" = true
  },
  {
    "id" = "Ews%V%Xk[YBd]D_M"
    "keepers" = tomap(null) /* of string */
    "length" = 16
    "lower" = true
    "min_lower" = 0
    "min_numeric" = 0
    "min_special" = 0
    "min_upper" = 0
    "number" = true
    "override_special" = tostring(null)
    "result" = "Ews%V%Xk[YBd]D_M"
    "special" = true
    "upper" = true
  },
]

Upvotes: 0

Martin Atkins
Martin Atkins

Reputation: 74209

A straight conversion from JSON to YAML would involve just passing the result of jsondecode to yamlencode.

However, the meat of your question seems to not be about conversion between serialization formats but rather about transforming from a typical nested data structure into a flattened structure using a compound key syntax.

Transforming from a multi-level structure into a single-level structure is a good job for flatten:

locals {
  users = flatten([
    for idx, u in local.users : [
      for k, v in u : {
        key   = "user[${idx}].${v}"
        value = v
      }
    ]
  ])
}

The result would be a Terraform value corresponding to the data structure you illustrated in YAML:

[
  {
    key   = "user[0].name"
    value = "rock"
  },
  {
    key   = "user[0].age"
    value = 33
  },
  # ...etc...
]

You can then pass the result to yamlencode to produce the YAML serialization of that data structure.

Upvotes: 1

aashitvyas
aashitvyas

Reputation: 1038

You can use file function of terraform to read the content of your json.

You can then use jsondecode to decode/represent the string as json.

The last step is to use , yamlencode function to encode returned json representation in yaml format.

Please see below terraform config.

locals {
  test = yamlencode(jsondecode(file("${path.module}/test.json")))
}

output "test" {
  value = local.test
}

The result from the above tf config is as below

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

test = "users":
- "age": 33
  "city": "paris"
  "name": "rock"
- "age": 45
  "city": "greece"
  "name": "austin"

Upvotes: 1

Related Questions