Day 11 — Terraform Functions Part 1

Terraform Functions
Welcome to Day 11! Today marks an exciting milestone in our Terraform journey. We're diving into Terraform functions—powerful built-in tools that make your infrastructure code cleaner, smarter, and more maintainable.
This topic is extensive, so I've split it into two parts. Today, we'll cover the most commonly used functions that you'll work with daily. Tomorrow, we'll explore the remaining functions to complete your toolkit.
If you've been following this series from Day 1, you already have a solid foundation. If you're just joining, I recommend starting from Day 0, which explains how to participate in this challenge and be eligible for the end-of-series rewards.
Let's make our Terraform code work smarter, not harder! 💪
What Exactly is a Function?
Before we jump into Terraform functions, let's understand what a function is in simple terms—especially if you're not from a programming background.
The Simple Explanation
A function makes your life easier by letting you reuse code instead of writing it repeatedly.
Imagine you need to add two numbers and print the result. You write:
a = 2
b = 3
c = a + b
print(c)
Simple enough for once. But what if you need to do this 10 times with different numbers? You could copy-paste this code 10 times, but that's:
Repetitive and boring
Prone to errors
Hard to maintain
Inefficient
Instead, you wrap this logic inside a function:
function sum(a, b) {
c = a + b
return c
}
Now you can call sum(2, 3), sum(5, 7), or sum(100, 200) anytime you need it. Write once, use everywhere!
That's the power of functions.
Functions in Terraform: A Key Difference
Terraform uses HCL (HashiCorp Configuration Language), which is a configuration language, not a full programming language like Python or JavaScript.
This means:
✅ What Terraform CAN do:
Use powerful built-in functions
Manipulate data (strings, numbers, collections)
Perform calculations and transformations
Infrastructure provisioning
❌ What Terraform CANNOT do:
Create custom functions (unlike programming languages)
Use classes or objects
Full OOP (Object-Oriented Programming) support
Key Takeaway: In Terraform, you cannot create your own functions. You can only use the built-in functions provided by Terraform.
But don't worry—Terraform provides a rich library of built-in functions that cover almost everything you need!
Categories of Terraform Functions
Terraform functions are organized into these categories:
String Functions - Manipulating text
Numeric Functions - Working with numbers
Collection Functions - Lists, maps, sets operations
Type Conversion Functions - Converting between types
Date and Time Functions - Working with timestamps
Validation Functions - Checking conditions
Lookup Functions - Finding values in maps
File Functions - Reading files
Today, we'll cover the first five categories with practical AWS examples.
Using Terraform Console
Before we dive into examples, let's learn about terraform console—an interactive shell for testing functions.
Open Terraform Console:
terraform console
This opens an interactive prompt where you can test functions directly without writing Terraform files.
To exit:
exit
or press Ctrl+D
Let's start exploring functions!
1. String Functions 📝
String functions help you manipulate text—essential for naming resources, formatting outputs, and data processing.
upper() - Convert to Uppercase
> upper("hello 30 days of aws terraform")
"HELLO 30 DAYS OF AWS TERRAFORM"
Real-world use: Standardizing environment names or tags.
lower() - Convert to Lowercase
> lower("HELLO 30 DAYS OF AWS TERRAFORM")
"hello 30 days of aws terraform"
Real-world use: S3 bucket names (which must be lowercase).
trim() - Remove Characters
The trim() function removes specified characters from the beginning and end of a string.
Syntax:
trim(string, character_set)
Example - Remove spaces:
> trim(" AWSTF ", " ")
"AWSTF"
Example - Remove specific characters:
> trim("AWSTF", "F")
"AWST"
What it does: Removes all occurrences of "F" from the beginning and end of the string.
replace() - Replace Characters
Replace occurrences of a substring with another substring.
Syntax:
replace(string, search_string, replacement_string)
Example:
> replace("hello world", " ", "-")
"hello-world"
Real-world use: Converting spaces to hyphens for resource names.
substr() - Extract Substring
Extract a portion of a string based on position and length.
Syntax:
substr(string, start_index, length)
Example:
> substr("hello world", 0, 5)
"hello"
What it does: Starts at index 0, extracts 5 characters.
Real-world use: Truncating long strings to meet naming constraints.
2. Numeric Functions 🔢
Functions for mathematical operations on numbers.
max() - Find Maximum
> max(5, 12, 1)
12
Real-world use: Determining the maximum instance count across environments.
min() - Find Minimum
> min(5, 12, 1)
1
Real-world use: Setting minimum resource limits.
abs() - Absolute Value
> abs(-42)
42
Real-world use: Calculating differences or distances.
3. Collection Functions 📦
Functions for working with lists, maps, and sets.
length() - Count Elements
> length([1, 2, 3, 4])
4
Real-world use: Counting availability zones or subnet IDs.
concat() - Concatenate Lists
> concat([1, 2], [3, 4])
[1, 2, 3, 4]
Real-world use: Combining multiple lists of CIDR blocks or security group rules.
merge() - Merge Maps
> merge({a = 1, b = 2}, {c = 3, d = 4})
{
"a" = 1
"b" = 2
"c" = 3
"d" = 4
}
Real-world use: Combining default tags with environment-specific tags.
4. Type Conversion Functions 🔄
Convert values from one type to another.
toset() - Convert List to Set
> toset(["a", "b", "a"])
toset([
"a",
"b",
])
What happened? The duplicate "a" was removed because sets don't allow duplicates.
tonumber() - Convert to Number
> tonumber("23")
23
What changed? "23" (string) became 23 (number).
tostring() - Convert to String
> tostring(23)
"23"
What changed? 23 (number) became "23" (string).
5. Date and Time Functions ⏰
timestamp() - Current Time
> timestamp()
"2024-12-05T10:30:45Z"
Real-world use: Adding creation timestamps to resources.
formatdate() - Format Timestamp
> formatdate("DD-MM-YYYY", timestamp())
"05-12-2024"
Custom formats:
"YYYY-MM-DD"→ "2024-12-05""DD/MM/YY"→ "05/12/24""MMM DD, YYYY"→ "Dec 05, 2024"
Real-World Terraform Examples
Now let's use these functions in actual Terraform configurations with AWS resources.
Example 1: Formatting Project Names
Scenario: You have a project name with uppercase letters and spaces. You need to convert it to lowercase and replace spaces with hyphens for S3 bucket naming.
variables.tf
variable "project_name" {
description = "Name of the project"
type = string
default = "Project Alpha Resource"
}
main.tf
locals {
# Convert to lowercase and replace spaces with hyphens
formatted_project_name = lower(replace(var.project_name, " ", "-"))
}
outputs.tf
output "formatted_project_name" {
description = "Formatted project name"
value = local.formatted_project_name
}
Run Terraform:
terraform init
terraform plan
Output:
formatted_project_name = "project-alpha-resource"
What happened:
replace(var.project_name, " ", "-")→ "Project-Alpha-Resource"lower(...)→ "project-alpha-resource"
Example 2: Merging Tags
Scenario: You have default tags for all resources and environment-specific tags. You need to merge them.
variables.tf
variable "default_tags" {
description = "Default tags for all resources"
type = map(string)
default = {
Company = "TechCorp"
ManagedBy = "Terraform"
}
}
variable "environment_tags" {
description = "Environment-specific tags"
type = map(string)
default = {
Environment = "Development"
CostCenter = "Engineering"
}
}
main.tf
locals {
# Merge both tag maps
merged_tags = merge(var.default_tags, var.environment_tags)
}
resource "aws_s3_bucket" "example" {
bucket = "my-terraform-bucket"
tags = local.merged_tags
}
Result:
tags = {
Company = "TechCorp"
ManagedBy = "Terraform"
Environment = "Development"
CostCenter = "Engineering"
}
Example 3: Validating S3 Bucket Names
Scenario: S3 bucket names have strict requirements:
Maximum 63 characters
Lowercase only
No spaces or special characters
Let's auto-format any bucket name to meet these requirements.
variables.tf
variable "bucket_name" {
description = "S3 bucket name"
type = string
default = "Project Alpha Storage!"
}
main.tf
locals {
# Format bucket name to meet S3 requirements
formatted_bucket_name = lower(
replace(
substr(var.bucket_name, 0, 63), # Max 63 chars
" ",
"-"
)
)
# Remove special characters
clean_bucket_name = replace(local.formatted_bucket_name, "!", "")
}
resource "aws_s3_bucket" "data" {
bucket = local.clean_bucket_name
tags = {
Name = "Data Bucket"
}
}
Input: "Project Alpha Storage!"
Steps:
substr(..., 0, 63)→ Limit to 63 charactersreplace(..., " ", "-")→ "Project-Alpha-Storage!"lower(...)→ "project-alpha-storage!"replace(..., "!", "")→ "project-alpha-storage"
Final bucket name: project-alpha-storage ✅
Example 4: Using split() and For Expression
Scenario: You have a comma-separated string of ports that you need to convert into a list and create security group rules.
variables.tf
variable "allowed_ports" {
description = "Comma-separated list of allowed ports"
type = string
default = "80,443,8080,3306"
}
main.tf
locals {
# Split the string into a list
port_list = split(",", var.allowed_ports)
# Create security group rule objects using for expression
sg_rules = [
for port in local.port_list : {
name = "port-${port}"
port = port
description = "Allow traffic on port ${port}"
}
]
}
outputs.tf
output "port_list" {
description = "List of ports"
value = local.port_list
}
output "sg_rules" {
description = "Security group rules"
value = local.sg_rules
}
Run Terraform:
terraform refresh
terraform output
Output:
port_list = [
"80",
"443",
"8080",
"3306",
]
sg_rules = [
{
"name" = "port-80"
"port" = "80"
"description" = "Allow traffic on port 80"
},
{
"name" = "port-443"
"port" = "443"
"description" = "Allow traffic on port 443"
},
# ... and so on
]
What happened:
split(",", var.allowed_ports)→["80", "443", "8080", "3306"]for port in local.port_list→ Iterates through each portCreates a map for each port with name, port, and description
Understanding String Interpolation
When you need to combine variables with strings, use string interpolation.
Syntax:
"${variable_name}"
Example:
variable "environment" {
default = "production"
}
resource "aws_instance" "web" {
ami = "ami-12345"
instance_type = "t3.micro"
tags = {
Name = "${var.environment}-web-server"
}
}
Result: Tag Name = "production-web-server"
Why use ${}?
When you're inside a string and want to insert a variable's value, you must use ${}. This tells Terraform: "Evaluate this variable and insert its value here."
Example 5: lookup() Function
Scenario: You want different instance types for different environments (dev, staging, prod).
variables.tf
variable "environment" {
description = "Deployment environment"
type = string
default = "dev"
}
variable "instance_sizes" {
description = "Instance sizes per environment"
type = map(string)
default = {
dev = "t2.micro"
staging = "t3.small"
prod = "t3.large"
}
}
main.tf
locals {
# Look up instance size based on environment
# If environment not found, use t2.micro as default
instance_size = lookup(
var.instance_sizes,
var.environment,
"t2.micro" # Default fallback
)
}
outputs.tf
output "instance_size" {
description = "Selected instance size"
value = local.instance_size
}
Test different environments:
Environment: dev
terraform plan
Output: instance_size = "t2.micro"
Environment: prod (in terraform.tfvars)
environment = "prod"
terraform plan
Output: instance_size = "t3.large"
Environment: unknown
environment = "production" # Not in map
terraform plan
Output: instance_size = "t2.micro" (fallback default)
How Functions Work Together
You can chain multiple functions to create powerful transformations:
locals {
formatted_name = lower(replace(substr(var.name, 0, 20), " ", "-"))
}
Execution order (inside to outside):
substr(var.name, 0, 20)→ Limit to 20 charactersreplace(..., " ", "-")→ Replace spaces with hyphenslower(...)→ Convert to lowercase
Example flow:
Input: "Project Alpha Storage Bucket"
↓
substr(..., 0, 20) → "Project Alpha Storag"
↓
replace(..., " ", "-") → "Project-Alpha-Storag"
↓
lower(...) → "project-alpha-storag"
Quick Reference Table 📋
| Function | Category | Purpose | Example |
upper() | String | Convert to uppercase | upper("hello") → "HELLO" |
lower() | String | Convert to lowercase | lower("HELLO") → "hello" |
trim() | String | Remove characters | trim(" hi ", " ") → "hi" |
replace() | String | Replace substring | replace("a-b", "-", "_") → "a_b" |
substr() | String | Extract substring | substr("hello", 0, 3) → "hel" |
split() | String | Split into list | split(",", "a,b") → ["a", "b"] |
max() | Numeric | Maximum value | max(1, 5, 3) → 5 |
min() | Numeric | Minimum value | min(1, 5, 3) → 1 |
abs() | Numeric | Absolute value | abs(-5) → 5 |
length() | Collection | Count elements | length([1, 2, 3]) → 3 |
concat() | Collection | Merge lists | concat([1], [2]) → [1, 2] |
merge() | Collection | Merge maps | merge({a=1}, {b=2}) |
toset() | Type Conv | To set | toset(["a", "a"]) → ["a"] |
tonumber() | Type Conv | To number | tonumber("5") → 5 |
tostring() | Type Conv | To string | tostring(5) → "5" |
timestamp() | Date/Time | Current time | Returns current timestamp |
formatdate() | Date/Time | Format date | formatdate("DD-MM-YYYY", ...) |
lookup() | Lookup | Find in map | lookup(map, key, default) |
Wrapping Up
Today we covered the essential Terraform functions you'll use daily:
String Functions:
upper(),lower()- Case conversiontrim(),replace()- String manipulationsubstr(),split()- String extraction
Numeric Functions:
max(),min(),abs()- Calculations
Collection Functions:
length(),concat(),merge()- Working with lists/maps
Type Conversion:
toset(),tonumber(),tostring()- Type changes
Date/Time:
timestamp(),formatdate()- Time handling
Lookup:
lookup()- Dynamic value selection
Key Takeaways:
Functions make code reusable and maintainable
Terraform has built-in functions only (no custom functions)
Chain functions for powerful transformations
Use
terraform consoleto test functionsAlways provide fallback values
Remember: The best way to learn is by doing. Open terraform console and experiment with these functions yourself!
Reference Video :
What's Next?
Tomorrow on Day 12, we'll continue with:
File Functions - Reading and processing files
Encoding Functions - Base64, JSON, YAML
IP Network Functions - CIDR calculations
Crypto Functions - Hashing and encryption
And more advanced function patterns!
Keep practicing, keep building, and see you tomorrow! 🚀
Practice makes perfect! Don't just read—try these functions in your own Terraform code.
Happy Terraforming! 🚀




