how do I convert a Terraform map variable into a string? - terraform

I'm working on an tf plan what builds a json template and out of a map variable and I'm not quite sure how to use the existing looping, type, list functions to do the work. I know that I cannot pass lists or map to a data "template_file" so my thought was to build the string in a locals or null resource block and then pass that to the template
Variable
variable "boostrap_servers" {
type = map
default = {
"env01" : [
"k01.env01",
"k02.env01"
],
"env02" : [
"k01.env02"
]
}
Desired text
"connections": {
"env01": {
"properties": {
"bootstrap.servers": "k01.env01,k02.env01"
}
},
"env02": {
"properties": {
"bootstrap.servers": "k01.env02"
}
},

You may simply use the jsonencode function and list comprehension for this:
locals {
connections = jsonencode({
for cluster, servers in local.bootstrap_servers :
cluster => {
properties = {
"bootstrap.servers" = join(",", servers)
}
}
})
}

Ok, so the following works but there's a better question: why not just use the jsonencode function to build the json
locals {
clusters = [
for cluster, servers in var.boostrap_servers :
"{\"${cluster}\":{\"properties\":{\"bootstrap.servers\":\"${join(" ,", servers)}\"}}"]
connections = join(",", local.clusters)
}

Related

Fetch key value from json data using terraform

I have a json data file from which I need to fetch only the id attribute value into a separate list variable. I tried for loop but not able to get the required data using terraform. Can someone tell how to fetch the id part ? your help is much appreacited.
code:
locals {
data = jsondecode(file("./data.json"))[*]
sections = [ for item in local.data : item ]
}
output "ids" {
value = [for a in local.sections[0]: a]
}
json file:
{
"c":[
{
"id":"6",
"key":"c",
"name":"s01"
}
],
"l":{
"id":"7",
"key":"l",
"name":"s02"
},
"m":{
"id":"8",
"key":"mp",
"name":"s03"
},
"n":{
"id":"5",
"key":"cn",
"name":"s04"
},
"od":"odk",
"s":{
"id":"9",
"key":"cs",
"name":"s05"
},
"ss":{
"id":"1",
"key":"ss",
"name":"s06"
},
"in":{
"id":"65",
"key":"cn",
"name":"s07"
},
"b":{
"id":"2",
"key":"cb",
"name":"s08"
}
}
Not sure if "od":"odk", is mistake or not, but you can do the following:
locals {
data = jsondecode(file("./data.json"))
}
output "ids" {
value = [for v in values(local.data): v.id if can(v.id)]
}

Terraform change nested maps values

I have this local map variable
(some AWS ECS tasks definition configurations I read from .JSON files)
tasks = {
"service1" = {
task_definition = {
"cpu": 128,
"environment": [
{
"name": "DB_HOST",
"value": "X"
}
],
"essential": true,
"healthCheck": {}
}
}
"service2" = {
"task_definition" = ...
}
}
I want to change DB_HOST value based on other module output :
worth noting DB_HOST won’t appear on each service - should be changed/added
Something like that :
tasks.x.task_definition.environment[x].value = module.example.db_host
-> DB_HOST = module.example.db_host
didn’t manage to do it when looping through the map keys…
Thanks in advance !

Appending values to a JSON key with terraform?

I am quite new to terraform. I have a provider that will accept JSON as input.
I have stored JSON config files in my project folder, eg:
{
"id": 58187729,
"name": "My dashboard",
"tags": ["mytag1", "mytag2"]
}
and load them into the resource with the below code:
resource "datadog_monitor_json" "monitor_json" {
for_each = fileset(path.module, "/monitors/*.json")
monitor = file("${path.module}/${each.key}")
}
Is there anyway I can easily append to the "tags" key or will the entire JSON need parsing somehow?
Thanks.
Here is an example on how to add extra tags:
locals {
example = jsondecode(file("${path.module}/myfile.json"))
with_extra_tags = merge(local.example,
{tags = concat(
local.example["tags"],["mytag4", "mytag3"])})
}
gives:
test = {
"id" = 58187729
"name" = "My dashboard"
"tags" = [
"mytag1",
"mytag2",
"mytag4",
"mytag3",
]
}

Is it possible to perform nested iterations in HCL resulting in a flat list without calling flatten?

Is it possible with HCL to have nested iterations returning a flat list(map) without resorting to flatten?
I have this:
locals {
mappings = flatten([
for record_type in var.record_types : [
for host in var.hosts : {
type = record_type,
host = host
}
]
])
}
I would like to remove the need for flatten like this:
locals {
mappings = [
for record_type in var.record_types :
for host in var.hosts : {
type = record_type,
host = host
}
]
}
But it seems like each for .. in must return data.
One alternative I could think of to only have a single for-loop is using setproduct():
variable "record_types" {
default = ["type1", "type2"]
}
variable "hosts" {
default = ["host1", "host2"]
}
locals {
mappings = [
for i in setproduct(var.record_types, var.hosts) : {
type = i[0],
host = i[1],
}
]
}
output "mappings" {
value = local.mappings
}
after terraform apply resulting in:
Outputs:
mappings = [
{
"host" = "host1"
"type" = "type1"
},
{
"host" = "host2"
"type" = "type1"
},
{
"host" = "host1"
"type" = "type2"
},
{
"host" = "host2"
"type" = "type2"
},
]
Of course, the two variables need to be independent sets here.
If you want to support duplicates or have dependent inputs, flatten() with two loops is the way.

Terraform For Loop To Generate JSON From Map

Looking for the easiest way in terraform to create a JSON string (preferably using jsonencode) or something similar i've looked at the few examples on the terraform docs but still struggling to nail the exact formatting to get this output right. This should make it pretty easy to keep the dev.env file we use in our docker-compose to transfer nicely into this large array that's used in several of our containers.
locals {
container_envs = {
ENV = "dev"
CONTAINER_TAG = "dev"
}
}
To the following type of output
[{
"name": "ENV",
"value": "dev"
},
{
"name": "CONTAINER_TAG",
"value": "dev"
}
]
I think the following should work (not sure if the order is important or not):
locals {
container_envs = {
ENV = "dev"
CONTAINER_TAG = "dev"
}
}
output "test" {
value = [for k,v in local.container_envs: { name = k, value = v }]
}
which gives:
test = [
{
"name" = "CONTAINER_TAG"
"value" = "dev"
},
{
"name" = "ENV"
"value" = "dev"
},
]

Resources