Top Terraform Functions | Use Cases, Categories, & Examples

Blog Featured image for a blog with a title - Terraform Functions

Top Terraform Functions | Use Cases, Categories, & Examples

Blog Featured image for a blog with a title - Terraform Functions
Categories

Introduction

Terraform functions are powerful tools that make your infrastructure code smarter, cleaner, and more dynamic. They help manipulate data, simplify configurations, and reduce repetition by handling strings, numbers, and collections within your Terraform scripts. This blog explores various built-in functions across categories like string, numeric, date and time, encoding, and more. You will also learn how to use these functions in real-world use cases with AWS resources, tags, and variables. key concepts covered in any comprehensive Ansible and Terraform course. Plus, we will explore looping mechanisms like for, for_each, and count, and dive into OpenTofu’s provider-specific functions to help you write scalable, efficient, and production-ready Terraform code.

Let us move on to our main section where we will discuss about functions in Terraform.

What are Terraform Functions

Terraform functions are built-in tools that let you handle and change data inside your terraform infrastructure code. You can use them in string formatting, numerical operations, date translations, and more. This makes your code dynamic, reusable, and manageable.

Functions in Terraform will enable you to concatenate strings, count objects in a map, or generate a timestamp. Functions also ensure that it is easy to avoid hardcoding in values, and when your input variables change or resource outputs are updated, changes can be made to your code. In simple terms, functions maintain your Terraform code free and effective.

Use Cases for Terraform Functions

Terraform functions are useful for many tasks: variable interpolation, generating resource names, and applying conditional logic. Here are a few examples.

  • Concatenating Strings: You can make unique resource names by adding environment names (such as “dev” or “prod”) to base names (such as “app-server”). The result is names like “app-server-dev” and “app-server-prod.
  • Splitting Strings: The split function name allows you to break a comma-separated variable such as: key1, value1, key2, value2 into a series of individual items: key1, value1, key2, and value2.
  • Converting Data Types: You can turn IP addresses list into a set to eliminate duplications and have each IP address unique. Terraform’s built-in functions support such data-type transformations.
  • Merging Tags: You can merge tags of multiple resources into one set. This helps manage and apply consistent tagging across resources.
  • Implementing Conditional Logic: You are able to define varying kinds of instances depending on a variable like micro and large instances t2.
  • Generating Timestamps: You are able to store the time when resources were created, so it can be audited or tracked.

Let us now move on to our next section where we will discuss different categories of Terraform functions.

Terraform Functions Categories

Below, we have discussed different categories of Terraform functions along with their description and examples.

CategoryDescriptionExamples
StringManipulate and transform stringsjoin(separator, list), split(separator, string), replace(string, search, replace), trimspace(string)
NumericPerform arithmetic operationsabs(number), ceil(number), floor(number)
CollectionWork with lists, maps, and setslength(list or map), element(list, index), flatten(list), merge(map1, map2, …)
Date and TimeWork with date and time valuestimestamp(), timeadd(timestamp, duration), formatdate(format, timestamp), uuid()
EncodingEncode and decode values, and transform data formatsbase64encode(string), base64decode(string), jsondecode(string)
Type ConversionConvert between different typestostring(value), tonumber(value), toset(value)
FilesystemRead files from the filesystemfile(path), filebase64(path), dirname(path)
IP NetworkWork with IP addresses and networkscidrnetmask(prefix), cidrrange(prefix)

String

The category of strings provides you with functions that can assist you in assembling and operating strings within your code. It can be conveniently used when it is required to assign names to resources, construct tags, or format the output values.

For instance, we can define var.instance_base_name to set the base name of the instance, and var.env to specify the environment name in variables.tf.

variable "instance_base_name" { 

  description = "Base name for instances" 

  type        = string 

  default     = "webapp" 

} 

  

variable "env" { 

  description = "Environment name" 

  type        = string 

  default     = "production" 

} 

join(separator, list)

(join) The method converts a collection of strings to a single string containing a delimeter. It can be used like this:

locals { 

joined_name= join("-", [var.instance_base_name, var.env]) 

} 

To generate the name for an aws_instance resource, it uses the join function to merge the instance_base_name and env variables with a hyphen, producing a name such as “webapp-production”.

split(separator, string)

The (split) function takes a string and a separator. It would separate the string into a list of shorter strings, with the separator at the end of each of the new strings.

locals { 

 split_name = split("-", local.joined_name) 

} 

To split the name, we use the split function, which breaks local.joined_name (e.g., “webapp-production”) into a list of substrings: [“webapp”, “production”].

Replace(string, substr, replacement)

The (replace) function substitutes all occurrences of substr within a string with replacement.

locals { 

  replaced_name = replace(local.joined_name, "webapp", "service") 

} 

As illustrated in this case using the replace option, the string given as webapp-production is altered by switching webapp by service to acquire service-production.

Trimspace(string)

The (trimspace) operation is used to eliminate the leading and the trailing white spaces in a string.

locals { 

  trimmed_description = trimspace("   This is a description with leading and trailing spaces   ") 

} 

The trimspace command strips both the beginning and end spaces in the description which leaves it with the values that produce the text, this is a description with leading and trailing spaces.

resource "aws_instance" "env0" { 

  ami           = "ami-09040d770ffe2224f" 

  instance_type = "t2.micro" 

  tags = { 

    Name          = local.joined_name 

    Splitted_Name = local.split_name 

    Description   = local.trimmed_description 

    Replaced_Name = local.replaced_name 

  } 

} 

Numeric

Numeric (number-related) functions let you carry out math on numbers. You may take them to round off figures or take the absolute values of numbers. They come in handy when you have to scale resources in accordance with the numbers, like the case of scaling up a server or computing derived values.

For example: define var.desired_cpu for CPU allocation and var.desired_disk_size for disk size in variables.tf.

variable "desired_cpu" { 

  description = "Desired CPU allocation" 

  type        = number 

  default     = 3.7 

} 

  

variable "desired_disk_size" { 

  description = "Desired Disk Size" 

  type        = number 

  default     = 100 

} 

Abs(number)

The (abs) function returns the absolute value of a given number.

locals { 

  disk_abs_size = tostring(abs(var.desired_disk_size)) 

}

Here, the (abs) function converts the desired_disk_size from -100 to its absolute value, 100.

Ceil(number)

The (ceil) function rounds a number up to the nearest whole number.

locals { 

  cpu_ceiled = tostring(ceil(var.desired_cpu)) 

} 

Here, the (ceil) function rounds the desired_cpu from 3.7 up to 4.

Floor(number)

The (floor) function rounds a number down to the nearest whole number.

locals { 

  cpu_floored = tostring(floor(var.desired_cpu)) 

} 

Here, the (floor) function rounds down the  desired_cpu from 3.7 to 3.

These calculated values are used to define tags and configure an AWS instance’s root block device.

resource "aws_instance" "env0" { 

  ami           = "ami-09040d770ffe2224f" 

  instance_type = "t2.micro" 

  tags = { 

    Name          = "env0-numeric" 

    CPU_Ceiled    = tostring(ceil(var.desired_cpu)) 

    CPU_Floored   = tostring(floor(var.desired_cpu)) 

    Disk_AbsSize  = tostring(abs(var.desired_disk_size)) 

  } 

} 

Collection

This category is about working with lists and maps. They (can be) used to count, retrieve a specific item, flatten nested lists, and merge maps.

As an example, use var.security_groups to specify all security groups, and var.additional_tags to include extra tags for the resources in variables.tf.

variable "security_groups" { 

  description = "List of security groups" 

  type        = list(string) 

  default     = ["sg-0bda1e9d218590d2b", "sg-084be08f8f8f1ad64e"] 

} 

  

variable "additional_tags" { 

  description = "Additional tags for resources" 

  type        = map(string) 

  default = { 

    "Team"  = "DevOps" 

    "Owner" = "admin" 

  } 

} 

Length(list)

The (length) function returns the number of elements in a list. 

locals { 

  sg_length = length(var.security_groups) 

} 

Here, the (length) function counts the number of items within the security_groups variable, defining the total number of security groups.

Element(list, index)

The (element) function retrieves a single element from a list by its index.

locals { 

  sg_element = element(var.security_groups, 0) 

} 

The (element) function retrieves the first item from the security_groups list, returning the first defined security group.

Flatten(list)

The (flatten) function collapses a multi-dimensional list into a single-dimensional list.

locals { 

  flat_list = flatten([ 

    ["env:production", "app:web"], 

    ["tier:frontend", "region:us-east-2"] 

  ]) 

} 

The (flatten) function combines nested lists into a single list, resulting in [“env:production”, “app:web”, “tier:frontend”, “region:us-east-2”]

Merge(map1, map2)

The (merge) function combines multiple maps into a single map.

locals { 

  merged_tags = merge( 

    { 

      "Environment" = "production" 

      "Project"     = "env0" 

    }, 

    var.additional_tags 

  ) 

} 

Example:

resource "aws_instance" "env0" { 

  ami           = "ami-09040d770ffe2224f" 

  instance_type = "t2.micro" 

   

  tags = merge( 

    { 

      "environment" = "production" 

      "project"     = "example" 

    }, 

    var.additional_tags 

  ) 

  

  vpc_security_group_ids = [element(var.security_groups, 0)] 

} 

Date And Time

It will enable you to work with timestamps, schedule events. You may use it to track the creation date or to schedule backups or keep expiration dates.

Timestamp() 

The timestamp function name returns UTC’s current date and time. 

locals { 

  created_At = timestamp() 

} 

output "current_time" { 

  value = local.created_At 

} 

The timestamp function captures the current date and time when the configuration is applied and makes this timestamp available as both a local variable created_At and an output current_time. 

Timeadd(timestamp, duration) 

The timeadd function adds a duration to a timestamp, returning a new timestamp. 

locals { 

  new_timestamp = timeadd(timestamp(), "168h") 

} 

The timeadd function adds 168 hours (7 days) to the current timestamp to set the Backup_Schedule tag and the backup_time output.: 

resource "aws_instance" "env0" { 

  ami           = "ami-09040d770ffe2224f" 

  instance_type = "t2.micro" 

   

  tags = { 

    Name            = "DateAndTimeInstance" 

    Created_At      = local.created_At 

    Backup_Schedule = local.new_timestamp 

  } 

} 

Encoding 

There are the functions that convert one type of data into the data of another type. As an example a function may Base64-encode a string, or decoding Base64-encoded string. Use of data using APIs and other applications is easy since it is in form of such functions. 

For example: define var.config_json for the configurations in JSON format in variables.tf. 

variable "config_json" { 

  description = "Configuration in JSON format" 

  type        = string 

  default     = "{\"key\":\"value\"}" 

} 

Base64encode(string) 

The base64encode function encodes a string to Base64 format. 

locals { 

encoded_string = base64encode(local.original_string) 

} 

The base64encode function encodes the original_string “This is a sample string.” into Base64 format, resulting in encoded_string. 

Jsondecode(string) 

The jsondecode function decodes a JSON string into a map or list. 

locals { 

 decoded_config = jsondecode(var.config_json) 

} 

The jsondecode function decodes the JSON string stored in config_json into a map, resulting in decoded_config. 

resource "aws_instance" "env1" { 

  ami           = "ami-09040d770ffe2224f" 

  instance_type = "t2.micro" 

   

  tags = { 

    Name            = "EncodingInstance" 

    Encoded_Message = local.encoded_string 

    Decoded_Key     = local.decoded_config["key"] 

  } 

} 

Looping in Terraform 

So far, we have learned the built-in functions in Terraform. However, there will be times when you’ll need to iterate over functions to solve slightly more complex problems by making use of looping mechanisms. 

Functions like count, for_each, and for letting developers create and manage resources automatically. 

For Loop 

The for loop in terraform allows you to iterate through collections to modify their data. 

Consider this example. The for loop runs through every key in the tags and converts it to uppercase and runs through every value in tags and converts it to lowercase. Through this, the two sets of changes appear in the map altogether. 

Here is the configuration: 

map for_each = { “key1” : “value1”, “key2” : “value2” } 

  

for each_key, each_value in for_each { 

each_key = upper(each_key) 

each_value = lower(each_value) 

} 


output show = { Key1 : value1, Key2 : value2 } 

  
tags = { for key, value in var.tags : upper(key) => lower(value) } 

For_each 

The for_each construct lets you create multiple resources using items from a map or set. You could employ this when you wish to handle a set of resources whose properties are nearly identical, but whose values differ. 

In this example, for_each starts multiple AWS instances, using the server types in the servers variable. 

variable "servers" { 

  type = map(string) 

  default = { 

    server1 = "t2.micro", 

    server2 = "t3.small", 

    server3 = "t3.medium" 

  } 

} 

  

resource "aws_instance" "server" { 

  for_each = var.servers 

  

  ami           = "ami-04b70fa74e45c3917" 

  instance_type = each.value 

  

  tags = { 

    Name = each.key 

  } 

} 

Count 

Count meta- argument allows you to generate resources when a boolean expression is non-zero. This allows you to deal with resources that must exist only under certain conditions, say provisioning additional infrastructure to support a staging environment. 

count = var.create_extra_instance ? 1 : 0 

For the full code, refer to GitHub repository. 

OpenTofu provider functions with env0 

Terraform works with OpenTofu providers to build modules. OpenTofu providers are able to introduce additional capabilities which Terraform cannot process. To run these functions, Terraform checks the required_providers block, and OpenTofu asks each provider if they have custom functions. 

These can be called like this in a module: 

provider::<provider_name>::<function_name> 

And you can also use aliases for providers.  

Provider functions can be used only within the same module where a provider is declared. They are not shared with any child modules. 

An illustration of provider functions working with OpenTofu code as follows: 

terraform { 

  required_providers { 

    corefunc = { 

      source = "northwood-labs/corefunc" 

      version = "1.4.0" 

    } 

  } 

} 

provider "corefunc" { 

} 

output "test_with_number" { 

  value = provider::corefunc::str_camel("test with number -123.456") 

} 

The corefunc provider is filled with their name and it is pinned at version 1.4.0. The provider is then initialized without any additional configuration. The str_camel function from the corefunc provider converts a string to kebab-case, removing any non-alphanumeric characters.  

You can use various functions from the corefunc provider, which you can find in corefunc functions documentation. 

Frequently Asked Questions

Q1. What is the key function in Terraform? 

The function “keys()” takes a map and returns a list. The list has all the keys of the map in lexicographical order. In other words, the outcome will remain constant as long as keys in the map are constant. 

Q2.  How many date type functions are in Terraform? 

Input variables support several data types. These types fall into two groups: simple and complex. Basic ones are string , number and bool . The list , map , tuple , object and set are complex types. 

Q3. What is the path function in Terraform functions? 

Terraform has a path module that you may invoke within your Terraform code to handle file paths. 

Q4. What is the limit of Terraform? 

By default, Terraform runs with 512 MB of memory. You can set a different limit if needed. Note that this limit is a recommendation only; and the system will not check to see that you have sufficient physical memory left. 

Conclusion 

Using Terraform functions can make your infrastructure automation work faster and more reliable. Native methods allow you to manipulate characters, perform arithmetic, and manipulate values. With looping structures like for, for_each, and count, you can manage multiple resources at once. To add to that, the functions of a provider allow OpenTofu to provide you with additional customization opportunities.  

Get in touch

Blog
Looking For Networking Training- PyNetLabs

Popular Courses

Automation

(FRESHERS / EXPERIENCED)

Network Expert

Automation

(FRESHERS / EXPERIENCED)

Network Expert

Automation

(FRESHERS / EXPERIENCED)

Network Expert

Automation

(FRESHERS / EXPERIENCED)

Network Expert

Automation

(FRESHERS / EXPERIENCED)

Network Expert

Leave a Reply

Your email address will not be published. Required fields are marked *