Terraform: Nested for expression with no duplicity - terraform

I am newbie to Terraform, apologies in advance in case inappropriate logic is used.
There is nested map, want to create new map using existing one.
terraform.tfvars
vpcs_info= {
"devops" = {
main = {
cidr = "10.14.0.0/16"
region = "ap-south-1"
peering = {
creator = {
devops = "poc",
uat = "main"
}
}
},
poc = {
cidr = "10.9.0.0/16"
region = "ap-south-1"
peering = {
creator = {
dev = "main"
}
}
}
}
}
locas.tf
locals {
vpcs_info = {
for vpc, properties in var.vpcs_info.devops:
vpc => {for dst_env, dst_vpc in properties.peering.creator : vpc => {"name": "${dst_env}-${dst_vpc}-vpc", "id": "${timestamp()}" }...}
}
}
Actual output:
{
"main" = {
"main" = [
{
"id" = "2023-02-05T21:23:24Z"
"name" = "devops-poc-vpc"
},
{
"id" = "2023-02-05T21:23:24Z"
"name" = "uat-main-vpc"
},
]
}
"poc" = {
"poc" = [
{
"id" = "2023-02-05T21:23:24Z"
"name" = "dev-main-vpc"
},
]
}
}
If we observe, in the output there is duplicity in KEYS. Need to get below desired output using for expression:
Desired output:
{
"main" = {
{
"id" = "2023-02-05T21:23:24Z"
"name" = "devops-poc-vpc"
},
{
"id" = "2023-02-05T21:23:24Z"
"name" = "uat-main-vpc"
}
}
"poc" = {
{
"id" = "2023-02-05T21:23:24Z"
"name" = "dev-main-vpc"
}
}
}
Note: "id" is sensitive information in actual requirement, to avoid security challenges, "${timestamp()}" is being used here.

You can do that with merge:
vpcs_info = merge([
for vpc, properties in var.vpcs_info.devops: {
for dst_env, dst_vpc in properties.peering.creator:
vpc => {
"name" = "${dst_env}-${dst_vpc}-vpc"
"id" = "${timestamp()}"
}...
}
]...)

Related

Extract Maps from List in Terraform

I have a list of complex maps, like so (I've simplified the maps, but really they're made up more maps):
[
{
"hooha" = {
"foo" = { "something" = "this" }
}
},
{
"woot" = {
"bar" = { "other_things" = "that" }
}
},
]
I need to feed this into jsonencode(), but first have it look like this:
{
"hooha" = {
"foo" = { "something" = "this" }
},
"woot" = {
"bar" = { "other_things" = "that" }
}
}
So from a list of maps, to a map of the maps.
This seemed trivial, but for the life of me, I can't figure it out!
You can use the function merge with a combination of with ... operator.
locals {
my_list = [
{
"hooha" = {
"foo" = { "something" = "this" }
},
"www" = {
"aa" = {"x" = "y"}
}
},
{
"woot" = {
"bar" = { "other_things" = "that" }
}
},
]
}
output "prepare" {
value = merge(local.my_list...)
}
The output will be something like this:
prepare = {
"hooha" = {
"foo" = {
"something" = "this"
}
}
"woot" = {
"bar" = {
"other_things" = "that"
}
}
"www" = {
"aa" = {
"x" = "y"
}
}
}

Creating BigQuery Procedure or function in Terraform

I need to create Bigquery user defined function/procedure in Terraform
resource "google_bigquery_routine" "sproc" {
dataset_id = "cssp"
routine_id = "tf_test_routine_id"
routine_type = "TABLE_VALUED_FUNCTION"
language = "SQL"
definition_body = <<-EOS
SELECT 1 + value AS value
EOS
arguments {
name = "value"
argument_kind = "FIXED_TYPE"
data_type = jsonencode({ "typeKind" : "INT64" })
}
return_table_type = jsonencode({"columns" : [
{ "name" : "value", "type" : { "typeKind" : "INT64" } },
] })
}

is there a way to concat tuple in terraform?

variable "query_param" {
type = list(string)
default = [
"hello",
"one",
"two"
]
}
locals {
common_tags = flatten([
for i in var.query_param: {
"method.request.querystring.${i}" = false
}
])
}
output name {
value = local.common_tags
description = "description"
}
I have this code to iterate the variable(list) to locals (map). I got the below output which is not desired.
name = [
{
"method.request.querystring.hello" = false
},
{
"method.request.querystring.one" = false
},
{
"method.request.querystring.two" = false
},
]
The desired output is getting all the values in a single array. As shown below.
name = [
{
"method.request.querystring.hello" = false,
"method.request.querystring.one" = false,
"method.request.querystring.two" = false
}
]
Is there any way to achieve this?
I think you would want something like this:
locals {
common_tags = {
for i in var.query_param :
"method.request.querystring.${i}" => false
}
}
The output of the code above will be as follows:
name = {
"method.request.querystring.hello" = false
"method.request.querystring.one" = false
"method.request.querystring.two" = false
}
Please note, the name itself is not an array in this case. If you want it to be, you can do the following:
locals {
common_tags = [{
for i in var.query_param :
"method.request.querystring.${i}" => false
}]
}
The output will be:
name = [
{
"method.request.querystring.hello" = false
"method.request.querystring.one" = false
"method.request.querystring.two" = false
}
]

How to Recreate Terraform map with duplicate keys?

I'm getting terraform Local variable output as below. I want to reconstruct it to use in deferent argument. I have tried it many way , Still no luck, Appreciate community support on this.
snap_id_list = [
{
"3" = {
"/x01" = "snap-01397a07b574e781f"
}
},
{
"2" = {
"/x04" = "snap-035d6c4165d34041a"
}
},
{
"1" = {
"/x04" = "snap-07bc61be86cb0b3a2"
}
},
{
"3" = {
"/x04" = "snap-0aa3a4d1cbd87531b"
}
},
{
"1" = {
"/x01" = "snap-0e501f7d2798eeb70"
}
},
{
"2" = {
"/x01" = "snap-0fe2fe503e433fdbd"
}
},
]
I want to recreate it as below using common keys.
snap_id_list = [
{
"3" = {
"/x01" = "snap-01397a07b574e781f"
"/x04" = "snap-0aa3a4d1cbd87531b"
},
{
"2" = {
"/x04" = "snap-035d6c4165d34041a"
"/x01" = "snap-0fe2fe503e433fdbd"
},
{
"1" = {
"/x04" = "snap-07bc61be86cb0b3a2"
"/x01" = "snap-0e501f7d2798eeb70"
}
},
]

Split nested map

I want to split the below mapping structure:
stages= {
non_prod = {
"qual" = "token1"
"dev" = "token2"
}
prod = {
"prod" = "token3"
}
testprod = {
"dev" = "token4"
"prod" = "token5"
}
}
Output should be in the below format:
stages= {
"non_prod" = { "qual" = "token1" }
"non_prod" = { "dev" = "token2" }
"prod" = { "prod" = "token3" }
"testprod" = { "dev" = "token4" }
"testprod" = { "prod" = "token5" }
}
So when the output is processed through a for loop, from "non_prod" = { "qual" = "token1" } it will take te values as :
environment = non_prod
stage = qual
token = token1
Witht he below code you can accomplish to create an iterable that allows you to access the information required.
locals {
stages = {
non_prod = {
"qual" = "token1"
"dev" = "token2"
}
prod = {
"prod" = "token3"
}
testprod = {
"dev" = "token4"
"prod" = "token5"
}
}
solution = flatten([
for env, data in local.stages : {
for stage, token in data : join(".", [env, stage]) => tomap({
"env": env,
"stg": stage,
"tok": token
})
}
])
You can use the merge function and the epsilon operator to surround the output of the flatten function to obtain an iterable map in the way you can use it later as required.
> merge(local.solution...)
{
"non_prod.dev" = {
"env" = "non_prod"
"stg" = "dev"
"tok" = "token2"
}
"non_prod.qual" = {
"env" = "non_prod"
"stg" = "qual"
"tok" = "token1"
}
"prod.prod" = {
"env" = "prod"
"stg" = "prod"
"tok" = "token3"
}
"testprod.dev" = {
"env" = "testprod"
"stg" = "dev"
"tok" = "token4"
}
"testprod.prod" = {
"env" = "testprod"
"stg" = "prod"
"tok" = "token5"
}
}
That is an iterable map that you can access the data through by it keys (env, stg, tok).

Resources