top of page
  • Writer's pictureChristoffer Windahl Madsen

Terraform weekly tips (4)

Updated: May 27, 2023

I believe in the principle of "learning by doing" to this extend, do you know how easy you can get started with compiling and debugging Terraform? As an experienced coder I know the hurdle of having to create a lot of "boilerplate" codes to just simply getting started with executing my scripts. In Terraform especially you might think that you ALWAYS need to define the following:


1 - Terraform block with required providers

2 - Provider block with all the required service connections

3 - All 3 Terraform base files (main, variables and outputs)


But the truth is, you don´t always have to define them. What if you just want to play around with some functions? Or try to understand how complex objects work? Whatever it might be, as long as you want to play without actually using a provider, a very very simple setup can be created. You do not even need an active internet connection.


Create a main.tf file in a directory of your own choosing. Inside this simple main.tf the following can be used to play around with Terraform:


1. Define normal variables as you would in the variables.tf file (the reason you can do this is because Terraform will merge all 3 base files together at runtime)


2. Define "Dynamic" variables inside the locals block. This area is fun as it allows us to play with data, functions, loops and logic.


3. Outputs, which is a type that allows us to "return" values to the screen to see the behavior of what Terraform does.


So all in all, even with a very very simple Terraform main.tf file one can still do loops, logic and so much more manipulation simply by playing with ones imagination!


Lets see some examples:

locals {
  simple_string = "hi world"
}

output "string" {
  value = local.simple_string
}

Run terraform terraform apply --auto-approve=true

Notice how we didnt even need to start with Terraform init - Why? Because Terraform can actually execute code as long as there are no defined codes that will require dependencies to work.


Lets expand on our example - Lets play around with the string:

locals {
  simple_string = "hi world"
  complex_string = replace(local.simple_string, " ", " and welcome to the new terraform ")
}

output "simple_string" {
  value = local.simple_string
}

output "complex_string" {
  value = local.complex_string
}

Above, we have defined a complex string where using the replace function on the other local variable 'simple_string' (must be prefixed local). For local variables to be referrenced, even if referrenced within the locals block itself to create a new string which we also have output.


Now lets make it a little more fun and build a more complex scenario. Let's say that we have the following comple object:

locals {
  ip_configuration = {
        "loadbalancer-prod" = {
            host_address = ["10.0.0.100", "10.0.0.101"]
            subnet_prefix = "/24"
        },
        "loadbalancer-test" = {
            host_address = ["10.0.1.100", "10.0.0.101"]
            subnet_prefix = "/24"
        }
    }
  list_of_ips = flatten(values(local.ip_configuration).*.host_address)
}

output "list_of_ips" {
  value = local.list_of_ips
}

With the configuration above we have defined a map consisting of 2 objects. These objects then consists 2 attributes. The 'host_address' attribute consists of a tupple which then contains the 2 strings. The attribute 'subnet_prefix' is simply just a string.


Now - Lets say that we want to generate a new tupple only consisting of an ip address accross both objects: To do so, we need to play with some Terraform functions:

list_of_ips = flatten(values(local.ip_configuration).*.host_address)

This seems a little overwhelming at first but its not when we define exactly what has to be done step-by-step:


We want to go from a map that contains 2 unique keys which each identifies an object, which consists of 2 attributes to only having a simple tupple consisting of both objects host_address

list_of_ips = local.ip_configuration

If we then simply put this to the output:


Now we use the values function from terraform to remove the two present keys:

list_of_ips = values(local.ip_configuration)

Notice how the keys are gone from each of the objects. Now, this allows us to go through each object in a for-loop and only retrieve the 'host_address' attribute from each

list_of_ips = values(local.ip_configuration).*.host_address

The output now:

Now it is instead a tupple containing 2 nested tupples. We are getting close to the end result that we want also the expression '.*.' is the Terraform 'splat' expression and is basically a short cut for using a for-loop. We can write the actual for-loop and get the same result as well:

list_of_ips = [for ip in values(local.ip_configuration) : ip.host_address]

Which gives the exact same result.


Now one might think that we are done and have the list that we aimed for, well not quite. Remember that right now, we are having a tupple with 2 tupples inside of that. We need to 'flatten' our nested list so that all 4 ip addresses gets on the same level. We will acheive this with the Terraform function 'flatten()' which we will use on the entire expression:

list_of_ips = flatten(values(local.ip_configuration).*.host_address)

Which gives us the final output of:

If we then want to only retrieve a specific IP, we simply use the index:

output "list_of_ips" {
  value = local.list_of_ips[1]
}

And we will get:


That was all for now, thank you for reading this weeks edition of the 'Terraform weekly tips'. We will continue to advance ourselves as we move forward through more tips!


Want to learn more about Terraform? Click here -> terraform (codeterraform.com)

Want to learn more about other cool stuff like Automation or Powershell -> powershell (codeterraform.com) / automation (codeterraform.com)


18 views0 comments

Comments

Rated 0 out of 5 stars.
No ratings yet

Add a rating
bottom of page