Terraform Refactoring: Azure VM Example
When working with Terraform configurations, it’s essential to keep them modular and maintainable. One way to achieve this is by using modules. This post demonstrates how to refactor an Azure VM Terraform configuration to use modules, without causing any changes to the existing infrastructure. We will also cover how to use the
terraform state mv
command to update the Terraform state during the refactoring process.
Initial Azure VM Configuration
Here’s the initial Terraform configuration for an Azure VM:
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "example" {
name = "example-resources"
location = "East US"
}
resource "azurerm_virtual_network" "example" {
name = "example-vnet"
address_space = ["10.0.0.0/16"]
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
}
resource "azurerm_subnet" "example" {
name = "example-subnet"
resource_group_name = azurerm_resource_group.example.name
virtual_network_name = azurerm_virtual_network.example.name
address_prefixes = ["10.0.1.0/24"]
}
resource "azurerm_network_interface" "example" {
name = "example-nic"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
ip_configuration {
name = "internal"
subnet_id = azurerm_subnet.example.id
private_ip_address_allocation = "Dynamic"
}
}
resource "azurerm_linux_virtual_machine" "example" {
name = "example-vm"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
network_interface_ids = [
azurerm_network_interface.example.id,
]
size = "Standard_B1s"
admin_username = "adminuser"
admin_password = "P@ssw0rd1234!"
os_disk {
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
}
source_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "18.04-LTS"
version = "latest"
}
}
Refactored Configuration with Modules
Here’s the refactored Terraform configuration that uses a module for the Azure VM:
main.tf
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "example" {
name = "example-resources"
location = "East US"
}
module "vm" {
source = "./vm"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
admin_username = "adminuser"
admin_password = "P@ssw0rd1234!"
}
vm/variables.tf
variable "resource_group_name" {
type = string
}
variable "location" {
type = string
}
variable "admin_username" {
type = string
}
variable "admin_password" {
type = string
}
vm/main.tf
resource "azurerm_virtual_network" "example" {
name = "example-vnet"
address_space = ["10.0.0.0/16"]
location = var.location
resource_group_name = var.resource_group_name
}
resource "azurerm_subnet" "example" {
name = "example-subnet"
resource_group_name = var.resource_group_name
virtual_network_name = azurerm_virtual_network.example.name
address_prefixes = ["10.0.1.0/24"]
}
resource "azurerm_network_interface" "example" {
name = "example-nic"
location = var.location
resource_group_name = var.resource_group_name
ip_configuration {
name = "internal"
subnet_id = azurerm_subnet.example.id
private_ip_address_allocation = "Dynamic"
}
}
resource "azurerm_linux_virtual_machine" "example" {
name = "example-vm"
location = var.location
resource_group_name = var.resource_group_name
network_interface_ids = [
azurerm_network_interface.example.id,
]
size = "Standard_B1s"
admin_username = var.admin_username
admin_password = var.admin_password
os_disk {
caching = "ReadWrite"
storage_account_type = "Standard_LRS"
}
source_image_reference {
publisher = "Canonical"
offer = "UbuntuServer"
sku = "18.04-LTS"
version = "latest"
}
}
Updating Terraform State with terraform state mv
After refactoring, use the terraform state mv
command to update the Terraform state:
- Move the
azurerm_virtual_network
resource:
terraform state mv azurerm_virtual_network.example module.vm.azurerm_virtual_network.example
- Move the
azurerm_subnet
resource:
terraform state mv azurerm_subnet.example module.vm.azurerm_subnet.example
- Move the
azurerm_network_interface
resource:
terraform state mv azurerm_network_interface.example module.vm.azurerm_network_interface.example
- Move the
azurerm_linux_virtual_machine
resource:
terraform state mv azurerm_linux_virtual_machine.example module.vm.azurerm_linux_virtual_machine.example
After running these terraform state mv
commands, your Terraform state should be updated to match the new module structure. Run terraform init
, terraform validate
, and terraform plan
to verify that your refactored configuration does not cause any changes to your existing infrastructure.
In conclusion, refactoring your Terraform configuration to use modules can help improve maintainability and modularity. Using the terraform state mv
command allows you to update your Terraform state during the refactoring process without causing disruptions to your existing infrastructure.