Automating vSphere VM Deployment with Terraform and Variable Maps

Using Terraform Variable Maps to Deploy VMs from Different Pre-existing VM Templates

As a virtualization enthusiast, I’ve been working on a project over the last couple of weeks that has enabled me to sharpen my Terraform skills. One of the challenges I faced was deploying VMs based on specific vSphere templates, and I wanted to find a way to make it even more “singularly declarative.” Here’s how I used Terraform variable maps to optimize the deployment of VMs based on different pre-existing VM templates.

Background and Challenge

—————————

When deploying VMs using Terraform, I wanted to avoid code duplication and make the process more managed and easily controlled. Instead of having one set of Terraform declarations per template (resulting in a lot of code duplication), or having the declaration variables tied to specific operating systems changing (resulting in more manual change) depending on what was being deployed, I looked for a way to make it even more “singularly declarative.”

Solution: Using Terraform Variable Maps

——————————————

I discovered that Terraform variable maps could be used to group like variables in one block declaration. These map values are then fed through to the rest of the Terraform code. By separating the maps into a separate file (maps.tf), I could logically separate what was being configured and make it easier to manage.

Here’s an example of how I used variable maps:

In the maps.tf file, I have a standard variable that is the only variable that changes and needs setting:

“`yaml

variable “vsphere_linux_distro” {

type = string

}

“`

Then, I define the map values for each Linux distro (Ubuntu and CentOS) in the same file:

“`yaml

map(“ubuntu”, {

template = “template-ubuntu”

password = “ubuntu-password”

})

map(“centos”, {

template = “template-centos”

password = “centos-password”

})

“`

In the terraform.tfvars file, I set the vsphere_linux_distro variable to either “ubuntu” or “centos”:

“`yaml

vsphere_linux_distro = “ubuntu”

“`

When I run Terraform, it looks up the linux_template variable and maps it with the appropriate map value based on the vsphere_linux_distro setting. Here’s an example of how the data source that dictates what template is used builds the name from the lookup function of the base variable and the map value:

“`yaml

data “vsphere_template” “template” {

depends_on = [

null_resource.prepare_template,

]

name = “template-${var.vsphere_linux_distro}”

}

“`

The above data source that dictates what template is used builds the name from the lookup function of the base variable and the map value. The values we set in the maps are being used to execute the right command depending if it is Ubuntu or CentOS and also to use the correct password depending on the linux_distro set.

Advantages and Conclusion

————————-

Using Terraform variable maps has several advantages:

1. **Code Reusability**: By grouping like variables in one block declaration, I can reuse the same code for different operating systems, reducing code duplication.

2. **Easier Management**: The maps file is a separate file that can be logically separated from the rest of the Terraform code, making it easier to manage and maintain.

3. **Improved Readability**: The use of maps makes the code more readable, as the grouped variables are clearly visible and easy to understand.

In conclusion, using Terraform variable maps is an excellent way to optimize the deployment of VMs based on different pre-existing VM templates. It allows for easier management, improved readability, and reusability of code, making it a valuable tool for any virtualization enthusiast.