Terraform modules are reusable, repeatable templates. They allow abstraction in provisioning infrastructure, which is much needed if your usage grows beyond just some proof of concept. HashiCorp visualizes modules as designed by experts who know the enterprise standard and used by developers who want to apply the enterprise standard infrastructure in their projects. That way, things are standard across the organization. It saves developers time and avoids duplication of efforts. Modules can be versioned and distributed using a module repository or through your version control. That provides infrastructure admins with an ample amount of power and control at the same time.
As we created a resource group in the last section, let’s modularize that in the next exercise. To access the resources for this section, cd into the following:
$ cd ~/modern-devops/ch8/terraform-modules/
Within this directory, we have the following directory structure:
├── main.tf
├── modules
└── resource_group
├── main.tf
└── vars.tf
├── terraform.tfvars
└── vars.tf
As we can see, we have the main.tf, terraform.tfvars, and vars.tf files in the root directory like before. However, we have included an additional modules directory, which contains a resource_group subdirectory that contains a main.tf file and a vars.tf file. Let’s look at both.
modules/resource_group/main.tf looks like the following:
resource “azurerm_resource_group” “rg” {
name = var.name
location = var.location
}
It only contains an azurerm_resource_group resource with a name and location sourced from the name and location variables defined in the following modules/resource_group/ vars.tf file:
variable “name” {
type = string
description = “The resource group name”
}
variable “location” {
type = string
description = “The resource group location”
}
In the root module, which is the current directory, we’ve modified the main.tf file to look like the following:
terraform {
required_providers {
…
}
}
provider “azurerm” {
…
}
module “rg” {
source = “./modules/resource_group”
name = var.rg_name
location = var.rg_location
}
As we can see, instead of defining the resource directly in this file, we have defined a module called rg, whose source is ./modules/resource_group. Note that we pass the value for the variables defined for the module, that is, name, and location, from the variables defined at the root level, that is, var.rg_name and var.rg_location.
Now, let’s go ahead and see what happens when we initialize and apply this configuration.
Run the following command to initialize the Terraform workspace:
$ terraform init
Initializing the backend…
Initializing modules…
rg in modules/resource_group
Initializing provider plugins…
Terraform has been successfully initialized!
As we can see, Terraform has detected the new module and initialized it during init.
Tip
Whenever you define a new module, you must always reinitialize Terraform.
Now, let’s go ahead and run a plan using the following command:
$ terraform plan
Terraform will perform the following actions:
module.rg.azurerm_resource_group.rg will be created + resource “azurerm_resource_group” “rg” {
- id = (known after apply)
- location = “westeurope”
- name = “terraform-exercise”
}
Plan: 1 to add, 0 to change, 0 to destroy.
As we can see, it will create the resource group. However, this is now a part of the module addressed module.rg.azurerm_resource_group.rg. To apply the plan, let’s run the following command:
$ terraform apply
module.rg.azurerm_resource_group.rg: Creating…
module.rg.azurerm_resource_group.rg: Creation complete after 4s [id=/subscriptions/id/ resourceGroups/terraform-exercise]
And the resource group has been created! To destroy the resource group, let’s run the following command:
$ terraform destroy
By using modules, you can simplify infrastructure creation and management, enhance collaboration among teams, and establish a consistent approach to deploying resources in a scalable and maintainable manner.
Tip
Use Terraform modules to encapsulate and reuse infrastructure configurations, promoting modularity and reusability.
Until now, we’ve seen Terraform creating and destroying resources, but how does Terraform know what it had created before and what it needs to destroy? Well, it uses a state file for that. Let’s have a look.
Leave a Reply