How to create a custom string using map value - Terraform - string

I struggle to create a custom string in Terraform when I loop through a list of map which contains a map.
The problem isn't the looping itself but creation of a custom string.
E.g
locals {
for var1 ... : [
for var2 ... : {
myString = "${var2.map["key1"]_${var2.map["key2"]}" <-- This does NOT work as im using '"'
}]
}
Aware that the example does not work as I need to use double quote " to access the map value, but also because I need to use " for the creation of the string.

You are missing } and it should be var, not var2:
myString = "${var2.map["key1"]}_${var2.map["key2"]}"

Related

retrieve values from a list based on criterea using terraform syntax HCL

I am looking for a terraform expression to retrieve values from a list, i have a list of values
namespaces = [blue,red,green,ns-blue,ns-green,ns-grey]
I would like to retrieve in list format just the values contains "ns", as a result i must get:
namepsace-filtred = [ns-blue,ns-green,ns-grey]
thanks in advance.
Assuming you have a list of strings for a variable namespace:
variable "namespaces" {
default = ["blue", "red", "green", "ns-blue", "ns-green", "ns-grey"]
}
You can use a for with the regex function to check if a string contains a substring. Also, you have to use the can function to transform the result of the regex to a boolean:
locals {
namepsace_filtred = [for ns in var.namespaces : ns if can(regex("ns", ns))]
}
The result of this should be something like this:
namepsace_filtred = [
"ns-blue",
"ns-green",
"ns-grey",
]

Extract a string in terraform

I have the following string value that comes from a YAML file. I want to extract the first two parts of the string within the terraform file. Let me know how it can be done. I tried the split function.
String: "sg:dev:crm"
Expected value: "sg:dev"
Tried: split(":","sg:dev:crm")[1,2] // This doesn't work
You would have to split it into two separate values and concatenate them. For example:
locals {
sg = "sg:dev:crm"
split_sg = split(":","sg:dev:crm")
wanted_str = "${local.split_sg[0]}:${local.split_sg[1]}"
}
Also, you tried referencing wrong indexes after you split the string because indexes start from 0, and sg is at index 0 while dev is at index 1.

Terraform, convert user input variable to type list

In Terraform, I want a user to enter values for a variable (type list) without having to worry too much about the syntax for a list variable. For example, Terraform requires the following syntax for lists:
Enter value: ["value1", "value2", "value3"]
It would be nice if the user just needed to enter a comma separated list without having to worry about adding quotations and the brackets. For example:
Enter value: value1, value2, value3
From the comma separated string, I would like to convert it to type list with the correct syntax.
My current code looks like this, I don't think I am even close to figuring it out. Any help is appreciated!
variable "subnetNames" {
description = "Enter value:"
default = "value1, value2, value3"
}
output "test" {
value = "${join(",", list("[", var.subnetNames, "]"))}"
}
You want to use the split function.
variable "subnetNames" {
default = "value1,value2,value3"
}
output "test" {
value = "${split(",", var.subnetNames)}"
}
$ terraform init && terraform apply
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
Outputs:
test = [
value1,
value2,
value3
]

Mongodb text search not working with string Flask

I am trying to make text search with Flask.
For one word it works, but when I pass a string with multiple words it doesn't work.
But when I pass that string as hardcoded it works:
Suppose that string is this:
str = "SOME TEXT HERE"
if I pass it as variable like this:
newText= ' '.join(r'\"'+word+r'\"' for word in str.split())
result = app.data.driver.db[endpoint].find({"$text":{"$search":newText }}, {"score": {"$meta":"textScore"}}).sort([("score", {"$meta": "textScore"})])
it doesn't work.
But if I pass it as hardcoded like this:
result = app.data.driver.db[endpoint].find({"$text":{"$search":" \"SOME\" \"TEXT\" \"HERE\" " }}, {"score": {"$meta":"textScore"}}).sort([("score", {"$meta": "textScore"})])
It works.
The contents of variable newText are different from the contents in your hardcoded string.
Try removing 'r' during creation of newText to generate a string similar to the hardcoded string, as follows:
newText= ' '.join('\"'+word+'\"' for word in str.split())

How to check if string contains a substring in terraform interpolation?

How do you check if a terraform string contains another string?
For example, I want to treat terraform workspaces with "tmp" in the name specially (e.g. allowing rds instances to be deleted without a snapshot), so something like this:
locals
{
is_tmp = "${"tmp" in terraform.workspace}"
}
As far as I can tell, the substr interpolation function doesn't accomplish this.
For terraform 0.12.xx apparently you are suppose to use regexall to do this.
From the manual for terraform 0.12.XX:
regexall() documentation
regexall can also be used to test whether a particular string matches a given pattern, by testing whether the length of the resulting list of matches is greater than zero.
Example from the manual:
> length(regexall("[a-z]+", "1234abcd5678efgh9"))
2
> length(regexall("[a-z]+", "123456789")) > 0
false
Example applied to your case in terraform 0.12.xx syntax should be something like:
locals
{
is_tmp = length(regexall(".*tmp.*", terraform.workspace)) > 0
}
It also specifically says in the manual not to use "regex" but instead use regexall.
If the given pattern does not match at all, the regex raises an error. To test whether a given pattern matches a string, use regexall and test that the result has length greater than zero.
As stated above this is because you will actually get an exception error when you try to use it in the later versions of 0.12.xx that are out now when you run plan. This is how I found this out and why I posted the new answer back here.
You can indirectly check for substrings using replace, e.g.
locals
{
is_tmp = "${replace(terraform.workspace, "tmp", "") != terraform.workspace}"
}
Like #MechaStorm, with Terrafor 0.12.7+ you can use regex to return a Boolean value if your string contains a particular substring
locals {
is_tmp = contains(regex("^(?:.*(tmp))?.*$",terraform.workspace),"tmp")
}
The regex query returns a list of capture groups for any characters before tmp, tmp if found, any characters after tmp. Then contains looks for "tmp" in the list and returns true or false. I am using this type of logic in my own terraform.
Length of the list produced by split function is greater than one when separtor is a substring.
locals {
is_tmp = length(split("tmp", terraform.workspace)) > 1
}
Use replace( string, search, replace ) as in the snippet:
// string contains ABBA = result is ABBA
output "match" {
value = "${ replace("xxxABBAyyy", "/(?:.*)(ABBA)(?:.*)/", "$1") }"
}
// string doesn't contain ABBA = result is original string
output "no_match" {
value = "${ replace("xxxBABAyyy", "/(?:.*)(ABBA)(?:.*)/", "$1")}"
}
// string contains ABBA (ingorecase) = result is AbBA
output "equals_ignorecase" {
value = "${ replace("xxxAbBAyyy", "/(?:.*)((?i)ABBA)(?:.*)/", "$1")}"
}
An output of terraform apply is:
Outputs:
equals_ignorecase = AbBA
match = ABBA
no_match = xxxBABAyyy
In terraform 0.12.7, we now have regex . This may help simplify some code and make it readable to some (perhaps?)
> regex("[a-z]+", "53453453.345345aaabbbccc23454")
aaabbbccc
I use this way to check if bucket name start with test-tmp
eg. test-tmp, test-tmp-app1, test-tmp-db1 etc..
is_test_bucket = can(regex("^(test-tmp){1}($|-{1}.*$)", var.bucket_name))
Something that makes sense reading, IMHO:
locals {
is_tmp = can(regex("tmp", terraform.workspace))
}
This works because the regex function will raise an error if no matches are found.
Bonus: since Terraform 1.3.x, there are the new startswith and endswith functions that can be handy in a good amount of cases.

Resources