Any code pattern which is being repeatedly used, we can create modules for that piece of code. This helps our code to look clean and easy to read. Another major benefit of creating modules is that if any change needs to be made, we just need to make that change at one place (in the module) and then wherever the module is being called, the change will take effect.
Below picture shows that same code was being used in two projects, Alpha and Beta. However, taking advantage of Module, we created a module for that repeatable code and then we did not have to write that big piece of similar code in 2 different projects, on the contrary, we started consuming the code, in both the projects, from a centralized place i.e. module
Let’s do it practically and understand how it works
I have created the below folder structure
Scenario: We have to create EC2 instances in Project Alpha and Project Beta. So we have to write the below code in both the projects in alpha.tf and beta.tf
Now instead of writing the above code at two places, I would prefer to write it at one place. For this reason, I would write this code in modules\ec2\ec2.tf
Now in the alpha.tf and beta.tf, we just have to call the above module by creating module block and provide the source path of module
After we have mentioned the source path, it’s time to execute the code and see what happens.
First step is to run terraform init from Project Alpha path. This will not only download the required provider plugins but also download the modules which has been referenced.
Now lets run terraform plan and we will see that code mentioned in the module gets successfully called
So, we see the success above. I hope by now we understand the benefits of module.
Let’s discuss about few scenarios while working with Modules
Scenario 1: While using Modules, user should be able to change Attribute’s value.
If the Attribute Values are hardcoded in Module then user would not be able to change the values, if required, while referencing a module.
Below screenshot shows that attribute (ami, instance_type) are hardcoded
Now if the user of project alpha would want to change the instance type to t2.large, he would not be able to do that. Let’s see that below
Solution: Create variable and reference that inside the module. Now the user would be able to override the value of attribute that is defined inside the module, if required.
Below screenshot shows that we created variable.tf file under module folder and defined variable instance_type in the variable.tf
Now we will reference the newly created variable in ec2.tf under module directory, as shown below
User would now be able to override the instance_type attribute value
Scenario 2: User should not be able to change value of attribute
Imagine a scenario where we have created a security group via terraform using the same strategy used in Scenario 1 i.e. create a variable for the ports to open. This would allow users to override the setting and open the port of their choice. This would be disastrous for any organization. To handle such scenario, we can make use of locals. Using locals would not let the users override the port values.
Difference between Locals and Variables
- Major advantage of using locals is that it would help us in reducing duplication of the same value and also increases readability of code. Its very much like variable but the difference is that user would not be able to override the value, unlike variable whose value can be overridden/manipulated.
- Another difference is the scope. Locals is accessible within the local module, however, a variable can be scoped global.
Below screenshot shows that we have created locals block and assigned a value, 80, to local name port_to_open
In the below screenshot, user has tried to override the value of port_to_open (local name) to 22 and he gets error when he runs terraform plan command
Now lets try to comment “port_to_open = 22” line and then try to run the terraform plan command. We see success, as shown in the below screenshot.
Referencing Output of Module
In this section, we would learn how to reference an output defined in a module.
In the below screenshot we first created locals, then we are creating aws security group and referencing the local in the ‘from_port’ and ‘to_port’. Then further we would capture the security group id and use the output variable, as shown the below screenshot
Once the above module is created, we would now use the above module and see how we reference the output variable defined in the above module in our project alpha.
We will now run terraform init to download the module and provider plugins
Lets now run terraform plan and terraform apply
Hope you enjoyed reading today.