fbpx

Terraform is a powerful infrastructure as code (IaC) tool, but even experienced users sometimes encounter challenges with what seems like basic operations. One such operation is simple string concatenation, which can be perplexing if you’re not familiar with the specific syntax and functions available in Terraform. In this article, we’ll address a common issue that many Terraform users encounter and provide a clear solution to it.

The Problem

Consider the scenario where you need to create a string that varies based on the value of a Terraform variable. Specifically, you want to create a URL that should have a dot (".") separator between two parts of the string, but only when a certain condition is met. Let’s say you have a variable env_name, and you want to create a URL like app.api.mydomain.com when env_name is set to "prod" and app.api.staging.mydomain.com for any other value of env_name.

An extremely simple string concatenation would work using the following code, but wont work for this more complex scenario:

main_api_gw = "app.api.${var.env_name}"

For this more complex scenario though, including an if/then evaluation, you might initially try to achieve this string concatenation using the following code:

data "null_data_source" "api_gw_url" {
  inputs = {
    main_api_gw = "app.api.${var.env_name == "prod" ? "" : var.env_name}mydomain.com"
  }
}

However, there’s a problem with this approach. When env_name is not "prod", the code results in app.api.stagingmydomain.com instead of the desired app.api.staging.mydomain.com because the dot separator is missing.

To address this issue, you might attempt to concatenate the dot when env_name is not "prod" using the + operator:

data "null_data_source" "api_gw_url" {
  inputs = {
    main_api_gw = "app.api.${var.env_name == "prod" ? "" : var.env_name + "."}mydomain.com"
  }
}

However, this approach will lead to an error: __builtin_StringToInt: strconv.ParseInt: parsing "".

The problem here is that Terraform tries to convert the result of the conditional expression into an integer, leading to an error since it’s attempting to convert an empty string "" to an integer.

The Solution

In Terraform, more complex string concatenation scenarios can be achieved using the join function. This function is quite flexible and allows you to concatenate a list of strings using a separator. To use it in this case, you can convert the string parts you want to concatenate into a list and then use join with a dot separator.

Here’s how you can do it:

data "null_data_source" "api_gw_url" {
  inputs = {
    main_api_gw = join(".", ["app.api", var.env_name == "prod" ? "" : var.env_name, "mydomain.com"])
  }
}

In this code, we create a list containing three elements: "app.api", var.env_name, and "mydomain.com". The join function concatenates these elements with a dot separator, producing the desired URL.

Practical Example: Using join function

Here’s a complete practical example of how you can use the solution in a Terraform configuration file:

variable "env_name" {
  description = "Environment name"
  type        = string
  default     = "staging"
}

data "null_data_source" "api_gw_url" {
  inputs = {
    main_api_gw = join(".", ["app.api", var.env_name == "prod" ? "" : var.env_name, "mydomain.com"])
  }
}

output "api_gateway_url" {
  value = data.null_data_source.api_gw_url.inputs.main_api_gw
}

In this example, we define a variable env_name with a default value of “staging.” The null_data_source block then uses the join function to concatenate the parts of the URL, and we output the resulting API gateway URL.

Now, Terraform will correctly handle the string concatenation, and you will get the expected output depending on the value of env_name. If env_name is “prod,” you’ll get app.api.mydomain.com, and for any other value of env_name, you’ll get the appropriate URL with the dot separator.

Practical Example: Using locals

Here’s another practical example of how you can use a local varable in addition to use simple string concatenation to get the job done without the need for the join function at all:

variable "env_name" {
  description = "Environment name"
  type        = string
  default     = "staging"
}

local {
  gateway_environment = var.env_name == "prod" ? "" : "${var.env_name}."
}

data "null_data_source" "api_gw_url" {
  inputs = {
    main_api_gw = "app.api.${local.gateway_environment}mydomain.com"
  }
}

output "api_gateway_url" {
  value = data.null_data_source.api_gw_url.inputs.main_api_gw
}

Conclusion

While string concatenation in Terraform may seem straightforward, it’s essential to be aware of the available functions like join to handle various scenarios effectively. The join function provides a flexible way to concatenate strings and is especially useful when dealing with conditional concatenation, as shown in this article.

Microsoft MVP

Chris Pietschmann is a Microsoft MVP, HashiCorp Ambassador, and Microsoft Certified Trainer (MCT) with 20+ years of experience designing and building Cloud & Enterprise systems. He has worked with companies of all sizes from startups to large enterprises. He has a passion for technology and sharing what he learns with others to help enable them to learn faster and be more productive.
HashiCorp Ambassador Microsoft Certified Trainer (MCT) Microsoft Certified: Azure Solutions Architect

Discover more from Build5Nines

Subscribe now to keep reading and get access to the full archive.

Continue reading