Terraform — Working With Modules

If you are not familiar with modules in Terraform yet, you should definitely read this post.
A Terraform module is a set of Terraform configuration files in a single directory. Even a simple configuration consisting of a single directory with one or more .tf files is a module. When you run Terraform commands directly from such a directory, it is considered the root module.
In simple words, you can group resources together and call them with a single “module” block, which we will explain in this post. The following image gives us an idea on how to use it:

Instead of creating all these resources separated, we can call the module that already contains everything you need to spin up that specific service. As an example, if you are trying to spin up the app module, instead of creating 03 resources (load balancer, auto scaling and S3 bucket), you just call the module from your root file.
Here is the module we will build in this post to create a virtual machine with a NIC and it will also use a random_string function to concatenate a random string in the name of the resources. This will be useful in the future when we will be using this module for automation. Here’s how it looks like:

The diagram represents the virtual machine module, which contains the resources I’ve mentioned earlier, that will be called from a main.tf file (the root module).
You can find the full code used in this post here:
The Benefit
You will see the benefit of using a module in Terraform when you need to configure many resources from the same type, let’s say, if you want to configure 10 Azure virtual machines, instead of repeating the virtual machine resource block 10 times, you could use a module.
As you may know, an Azure virtual machine also needs a network interface card (NIC) which will require you to repeat 10 times the NIC block (one for each machine), which is not scalable at all.
When Not to Use It
It’s not recommended that you use a module when you have just one resource, let’s say, one block of Azure resource group, this will be more a wrapper than a module, and it will increase deployments complexity without necessity.
The Module Code
This module is intended to deploy an Azure virtual machine with a random name, as well as its network interface card.
If you look at the previous image, you’ll see that we have three resources there, and that’s exactly what we have here, we declare them in a .tf file (mine is main.tf) within the folder that corresponds to that module:

Using the Module
Now that we have created this module, we can call it from the root module. What really points to the folder is this “source” parameter in green, where you can declare the full path to the module:

Here we are calling the module twice, but we could also use the for_Each meta argument to create multiple resources using only one block of this module, but that’s a topic for another post.
Running the Code
It’s time to test our module, as always, run the following:
terraform init #Initialize Terraform modules and dependencies
terraform plan #Plan the resources to make sure everything is there
terraform apply #Create the resources
The result of the apply command will be the following:

As you can see on the image above, 02 of each of the 3 resources that we had in the module were created, it’s also worth noting that the output shows which resource is being created from that module, because you can have many resources in just a single module, and that’s a good thing to track down in a case where the module fails in deploying any of the resources.
Wrap Up
This post presented a simple way to create a module to group resources together and to re-use code instead of repeating the same resources blocks over and over. It was also mentioned when not to use it.
If you have any questions about this topic, feel free to ask them in the comments, I’ll be more than happy to help you. :)
Happy Studying!