Skip to main content

Command Palette

Search for a command to run...

DAY #37: [DAY-12] AWS Terraform Functions (Part-2)

Let’s Learn How Built-In Terraform Functions Make Configuration Flexible and Error-Free

Updated
12 min read
DAY #37: [DAY-12] AWS Terraform Functions (Part-2)
A
Sharing real-time progress, roadblocks, and open source lessons. Hoping my notes help someone else feel less stuck. "Stop waiting to feel ready, stop waiting for the perfect moment, start messy, start scared and start before you feel qualified"

Introduction

Hello and welcome back, it’s good to see you here again.

We’re now on Day 12 of our 30-day AWS Terraform journey, and it really does feel like we’re continuing a conversation we paused only yesterday. That steady, day-by-day progress is what makes this whole thing manageable and, honestly, kind of enjoyable.

If you remember, on Day 11 we opened the door to Terraform functions: we saw what they are, ran a few demos, and began to get a feel for how Terraform “thinks.” That day was about getting comfortable with the ideas and seeing how small functions fit into a larger workflow. Today we pick up right where we left off, carrying the same slow, steady pace.

So settle in, make yourself comfortable, and let’s explore this next chapter together.

I am so ready for learning terraform - MeMes Generator

Personal tidbit time:

Fact #12: I’m not a big fan of mathematics, as a kid I used to dread it. And I think a big part of that was because I never really tried to understand it. Looking back, I actually feel a little sad for my younger self, if only I could explain things to that version of me in a simpler way, maybe it wouldn’t have felt so overwhelming.

Understanding Validation Functions

Before we jump into the Terraform code, let’s take a moment to understand why validation functions matter.

Imagine we’re asking someone to fill out a small form maybe choosing an instance type or providing a backup name. Now, people make mistakes. They might type something too short, too long, or in a completely different format. If Terraform went ahead without checking anything, we’d only discover the mistake much later, often after the infrastructure has already been created incorrectly.

That’s where validation functions step in.

And the best part? These validations happen before Terraform even starts planning anything.

Why validation goes inside the variable block

Unlike other checks we’ve done before, validation has to live inside the variable declaration itself.
That’s because we’re telling Terraform:

“Whenever someone provides a value for this variable, please check these rules first.”

Here’s the example:

Let’s break this down.

1. First validation: checking the length

Terraform first checks whether the instance type is at least 2 characters long and at most 20.

Why?
Because sometimes someone may type something extremely short like t or something very long accidentally. This rule keeps things sensible.

The validation says:

  • if the length is 2–20, we’re good

  • if not, Terraform stops you with the message:
    “instance type must be between 2 and 20 characters”

Simple and helpful.

2. Second validation: checking if it starts with t2 or t3

This one is more interesting.

Here’s the condition again:

Let’s break it into very easy language:

  • regex()
    → checks whether a value matches a specific pattern

  • the pattern ^t[2-3]\. means:
    “The value should start with t2. or t3.

  • can()
    → used so Terraform can safely test the regex without crashing

Think of the regex like a rulebook:

  • ^ = start of the string

  • t = must start with the letter "t"

  • [2-3] = followed by either 2 or 3

  • \. = then there must be a dot (.)

So valid examples are:

  • t2.micro

  • t2.small

  • t3.large

Invalid ones would be:

  • m5.large

  • t4.micro

  • t2micro (missing dot)

And if the input doesn’t follow the pattern, Terraform returns our custom error:

“Instance type must start with T2 or T3.”

This makes the error more human-friendly and less confusing.

Why can() is needed

If we used only regex(), Terraform might throw a harsh technical error if the pattern didn’t match.
But with can(), Terraform simply checks:

  • If regex works → return true

  • If regex fails → return false, but gracefully (no crashes)

An example to relate

Imagine we're checking someone’s ID:

  • First, check if the ID length is reasonable (not too short, not too long).

  • Then check if it starts with a certain prefix like "AB" or "BC".

If both checks pass, great, let them in.
If not, we politely say, “Sorry, this ID doesn’t look right.”

Terraform is doing exactly that for our variables.

A Practical Validation: Ensuring a Backup Name Ends With -backup

Now that we understand how validations work with instance_type, let’s look at another everyday example, something even simpler.

Imagine we’re creating a variable called backup name.
We want every backup to follow a proper naming pattern so it’s easy to identify later.

Let’s say the rule is:

“Every backup name must end with -backup.”

Why is this useful?
Because when our systems grow, naming patterns save us from chaos.
Backups become easy to filter, group, search, and automate around, all because they follow a familiar ending.

The Terraform validation

Here’s how it might look:

Let’s unpack this.

1. endswith() function

endswith(string, substring) simply checks whether a value ends with a specific text.

So:

  • "mydata-backup" → valid ✔

  • "backup-mydata" → invalid ❌

  • "mydata-backup123" → invalid ❌

Terraform evaluates the condition, and if it fails, it shows you the custom message we provided.

We can enforce structure before Terraform even plans anything.

Understanding Sensitive Variables (Why Some Values Stay Hidden)

Some Terraform variables hold harmless information, like names or flags.
But others may contain things that should never appear in logs or screens i.e. things like passwords, tokens, keys, or database connection strings.

Terraform gives us a simple way to protect such values:

Mark the variable as sensitive = true.

This doesn’t encrypt the value, but it does hide it from output, logs, and accidental exposure during terraform plan or terraform apply.

Terraform example

Now, even if someone tries to print it:

Terraform will hide it.
You’ll see something like:

Why this matters

Sensitive variables protect us from:

  • accidental screen-sharing leaks

  • logs exposing secrets

  • commit mistakes when values accidentally get echoed

  • teammates seeing secrets they don’t need to

It’s not encryption, but it’s a safety layer that prevents embarrassment and accidents.

Validations Using Regex

So far, our validations checked simple conditions like:

  • Does this value belong to a list?

  • Does this value end with “-backup”?

But sometimes we need more powerful rules, rules that check patterns, formats, or structures.

This is where regex (regular expressions) comes in.

Regex sounds scary, but in Terraform, we’ll mostly use it for simple checks like:

  • Does the value contain only letters and numbers?

  • Does the name follow a specific pattern?

  • Does it start with something specific?

  • Does it avoid special characters?

A simple explanation of regex

Think of regex as a pattern detective.

Instead of checking a single condition, it looks for a shape in the text.

Example in plain English:

“The name must start with a letter and can only contain letters, numbers, and hyphens.”

Regex lets Terraform enforce that in one line.

Terraform regex example

Let’s say we want our environment names to follow this rule:

“Must start with a letter, and can contain letters, numbers, and hyphens.”

The regex for that (very common pattern) is:

We’ll understand what the above gibbersh means in a while.

Here’s how we apply it in Terraform:

Breaking this down in simple terms

1. ^ and $

These mean “start” and “end”.

Terraform checks the whole string, not just a part.

2. [a-zA-Z]

The name must start with a letter.

3. [a-zA-Z0-9-]*

After the first letter, we can have:

  • letters

  • numbers

  • hyphens

  • repeated any number of times (*)

Why regex matters in Terraform

When our project grows, naming mistakes create chaos:

  • S3 buckets with weird characters

  • IAM roles with spaces

  • Environment names with typos

  • Random uppercase/lowercase mixtures

Regex is our gatekeeper.

It stops wrong values before they spread through our infrastructure.

If this section is good, we’ll move to the next one:

Validation Rules for Lists

So far, we’ve seen validations for single values: an instance type, a backup name, or an environment name.
But what if our variable is a list of values? For example, a list of regions, instance types, or users.

Terraform lets us apply validations to every item in the list, ensuring consistency across the board.

Why this matters

Imagine we have a list of regions:

We want all regions to:

  • Follow the proper format

  • Only contain letters, numbers, and hyphens

  • Avoid typos or accidental spaces

Without validation, Terraform would happily accept a wrong entry, and our deployments could fail later.

With validations, Terraform stops mistakes upfront.

Terraform example

Suppose we have a variable for allowed regions:

Breaking it down

  • for r in var.allowed_regions
    Iterates over every region in the list.

  • regex("^[a-z]{2}-[a-z]+-[0-9]$", r)
    Ensures each region follows AWS naming conventions i.e.

    • Accepted values: us-east-1

    • Rejected values: USEAST1, us-east

  • can()
    Handles errors gracefully if the regex fails.

  • alltrue([...])
    Ensures that every single item passes the condition. If even one fails, Terraform stops and shows our custom error.

Why list validation is useful

  • Prevents subtle mistakes across multiple entries

  • Makes infrastructure predictable

  • Saves time debugging deployment errors

  • Ensures human-friendly, consistent standards

Type Conversion Functions (Lists, Sets, and Unique Values)

In Terraform, sometimes we need to change the type of a variable to make it easier to work with.
This is especially common when dealing with lists and sets, or when we want to remove duplicate values.

Why this matters

Imagine we have a list of regions:

Notice how “us-east-1” appears twice.

  • A list allows duplicates

  • A set only keeps unique values

Converting a list to a set is a simple way to automatically remove duplicates, making our infrastructure cleaner and more predictable.

Terraform example: Converting a list to a set

Suppose we have two variables:

We can combine them with concat:

This produces:

Now, to get only unique locations, use toset:

Result:

Duplicates are automatically removed, no extra effort needed.

Why type conversion is useful

  • Cleans up data automatically

  • Makes further operations easier

  • Prevents mistakes when working with lists that shouldn’t have duplicates

  • Bridges differences between Terraform’s list and set types

Number Functions: Sum, Max, Min, Absolute, and Average

Terraform provides several handy number functions that help us perform calculations on variables, especially lists of numbers.'

These functions are useful for things like monthly costs, resource counts, or any scenario where we need math on our infrastructure data.

The scenario

Suppose we have a list of monthly costs (some are credits, so negative):

We want to:

  1. Convert everything to positive numbers

  2. Find the maximum cost

  3. Find the minimum cost

  4. Calculate the total cost

  5. Calculate the average cost

Step 1: Convert to positive values

Terraform’s abs() function returns the absolute value of a number.
But because abs() doesn’t work on a list directly, we use a for loop:

Result:

Step 2: Find max and min

Terraform provides max() and min() functions.
Apply them on our positive list:

Result:

Step 3: Calculate total and average

To sum all costs:

Result:

Average is simply total divided by the number of elements:

Result:

Why this matters

  • Handles negative/credit values easily

  • Calculates statistics across any list of numbers

  • Helps in budgeting, reporting, or monitoring infrastructure costs

  • Makes our Terraform configurations smarter and more automated

Timestamp Functions: Current Time and Formatting

Terraform also provides timestamp functions to help us capture and format the current time.
This can be useful for logging, backups, or creating time-stamped resources automatically.

An example

Terraform’s timestamp() function doesn’t need any input:

This produces a value like:

This is the current UTC timestamp in ISO 8601 format.

Formatting the timestamp

Sometimes, we may want a more human-friendly format.
Terraform provides formatdate():

Result:

Now we can use this formatted timestamp in backup names, logs, or resource tags.

Why timestamp functions matter

  • Helps with automation that relies on dates

  • Makes logs and outputs easier to interpret

  • Supports versioning and auditing in our Terraform deployments

File Handling Functions

Terraform provides file handling functions that let us read, decode, and use data from files directly in our configurations.

This is especially useful when working with JSON configuration files or other structured data.

The scenario

Suppose we have a JSON file config.json:

We want Terraform to:

  • Check if the file exists

  • Read its contents

  • Decode the JSON into a usable map

Terraform example

Breaking it down

  1. fileexists("config.json")
    Checks if the file exists. Returns true or false.

  2. file("config.json")
    Reads the contents of the file.

  3. jsondecode(...)
    Converts the JSON text into a Terraform map or object.

  4. Conditional operator (? :)
    If the file exists → decode it
    If not → return an empty map {}

Output example

Now Terraform can use the database host, API endpoint, or any other value from the JSON file in our infrastructure resources.

Additional notes

  • Terraform also provides jsonencode() to convert data structures back into JSON

  • File handling functions let us reuse external data safely and efficiently

  • Great for keeping secrets, configurations, or templates outside our main .tf files

Why this matters

  • Makes our Terraform configurations more dynamic and flexible

  • Keeps sensitive or large configuration data outside our main code

  • Supports automation, templating, and scaling your deployments

Conclusion

And with this, we’ve reached the end of Day 12 in our 30-day Terraform journey.
Today we closed the loop on the remaining Terraform functions, everything we couldn’t finish in Part 1 finally found its place here in Part 2.

We explored validations, sensitive values, type conversions, numeric functions, timestamps, and even dipped our toes into file handling.
Each of these shape the kind of Terraform code that behaves reliably, predictably, and in a way that protects us from surprises.

And I just want to say this: if you’ve been following along till Day 12, that’s not a small thing.
Learning something every day, especially something as deep and layered as Terraform, is not easy.

We’ve come this far, and there’s still a long, exciting road ahead. We’ll tackle it together!

And hey, if you still have doubts or something felt a bit fuzzy, here’s a helpful video by Piyush Sachdeva that might clear things up.

Never hesitate to revisit, rewatch, or relearn.

With that thought, I’ll leave you for today. We’ll catch up again tomorrow with a new topic tomorrow.

Peace!