Skip to main content
Importing Infrastructure With Azure Terrafy
  1. Posts/

Importing Infrastructure With Azure Terrafy

William Collins
Author
William Collins
Building at the intersection of cloud, automation, and AI. Host of The Cloud Gambit podcast.
Table of Contents

Anyone that has worked in tech knows that building greenfield is much easier than dragging along brownfield environments through a roller-coaster they aren’t ready for. Tools like Terraform make infrastructure-as-code a breeze, but what about all that infrastructure you already have provisioned? April Edwards, Cloud Advocate at Microsoft, recently posted a blog about Azure Terrafy, a new tool in preview which aims to simplify the process. You can find the original blog here. Let’s take it for a spin!

Intro
Intro
Can’t you already import resources into Terraform state?

Terraform Import enables the importing of infrastructure today, but this only imports one resource at a time, and it’s on you to build the configuration files. Sounds time-consuming, right? When you are in the process of learning Terraform, having a tool that can import brownfield environments into state while also generating the HCL files, is extremely useful.

Installing Terrafy
#

I installed it via go install github.com/Azure/aztfy@latest.

Install Terrafy
Install Terrafy

Building some Infra
#

To kick off this little experiment, I will build some infrastructure in Azure using Terraform and then create a different project directory to test Terrafy in. If things go south, I don’t have to remove everything manually.

main.tf

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
locals {
  subnet_names    = ["eeny", "meeny", "miny", "moe"]
  vm_names        = ["catch", "tiger", "by", "toe"]
  subnet_prefixes = ["10.5.1.0/24", "10.5.2.0/24", "10.5.3.0/24", "10.5.4.0/24"]
}

resource "azurerm_resource_group" "rg" {
  name     = "rg-terrafy-test"
  location = "eastus"
}

resource "azurerm_virtual_network" "vnet" {
  name                = "vn-terrafy-test"
  address_space       = ["10.5.0.0/20"]
  resource_group_name = azurerm_resource_group.rg.name
  location            = azurerm_resource_group.rg.location
}

resource "azurerm_subnet" "subnet" {
  count                = length(local.subnet_names)
  name                 = local.subnet_names[count.index]
  resource_group_name  = azurerm_resource_group.rg.name
  virtual_network_name = azurerm_virtual_network.vnet.name
  address_prefixes     = [local.subnet_prefixes[count.index]]
}

resource "azurerm_network_interface" "interface" {
    count                             = length(local.subnet_names)
    name                              = "vnic-${local.subnet_names[count.index]}"
    location                          = azurerm_resource_group.rg.location
    resource_group_name               = azurerm_resource_group.rg.name

    ip_configuration {
        name                          = "vnic-config"
        private_ip_address_allocation = "Dynamic"
        subnet_id                     = azurerm_subnet.subnet.*.id[count.index]
    }
}

resource "random_id" "id" {

  keepers = {
    resource_group = azurerm_resource_group.rg.name
  }

  byte_length = 8
}

resource "random_string" "str" {
  length           = 16
  special          = true
  override_special = "/@£$"
}

resource "azurerm_storage_account" "storage" {
  name                     = random_id.id.hex
  account_tier             = "Standard"
  account_replication_type = "GRS"
  resource_group_name      = azurerm_resource_group.rg.name
  location                 = azurerm_resource_group.rg.location
}

resource "azurerm_linux_virtual_machine" "vm" {
    count                 = length(local.vm_names)
    name                  = local.vm_names[count.index]
    admin_username        = "ubuntu"
    admin_password        = random_string.str.result
    resource_group_name   = azurerm_resource_group.rg.name
    location              = azurerm_resource_group.rg.location
    network_interface_ids = [azurerm_network_interface.interface.*.id[count.index]]
    size                  = "Standard_B1s"

    os_disk {
        caching              = "ReadWrite"
        storage_account_type = "Standard_LRS"
    }

    source_image_reference {
        publisher = "Canonical"
        offer     = "UbuntuServer"
        sku       = "18.04-LTS"
        version   = "latest"
    }

    disable_password_authentication = false

    boot_diagnostics {
        storage_account_uri = azurerm_storage_account.storage.primary_blob_endpoint
    }
}

Running Terrafy
#

I created an empty directory called terrafy-test for this exercise. Before running Terrafy, make sure azure-cli is installed and authenticated. If your running on macOS and use Homebrew, you can run brew update && brew install azure-cli and then az login.

Run Terrafy
Run Terrafy
Missing Resources

Like a boss, I ran with defaults and didn’t bother reading any of the well-crafted README. Most of the resources were translated fine, but I noticed the virtual machines and storage accounts didn’t make it. When going through the setup, you will be able to cycle through and view all the resources available to import. If you see (Skip), that resource will indeed get skipped unless you update the resource type accordingly.

Was it Successful?
#

Let’s test a few things before we ride off into the sunset. I did a terraform plan -refresh only, and also updated some resources, and everything looks good!

Plan Refresh
Refresh

Some Thoughts
#

This is a great tool, especially in learning and adoption of infrastructure-as-code. The import process is scoped at the resource group level, which makes a lot of sense. Subscriptions would be the next level up, and that might get too messy. When Terrafy generates the infra-as-code files, it builds a provider.tf to source the azurerm details, and all the other configuration is generated in a monolithic main.tf file. This is the layout here:

Configuration Output
Output

More Organization
#

With infra-as-code, there is no easy button. To make things work at scale, things have to be organized. As a starting point, it would be neat to see Terrafy do more organization. Even something simple like breaking down infra into separate categories would be helpful.

An example of this would be taking resources like localNetworkGateways, networkSecurityGroups, and virtualNetworks and putting them into a separate file called network.tf as they all fall under Microsoft.Network when drilling down through azurerm.

Virtual Machines and all compute-related components would fall under Microsoft.Compute and would be in a different file called compute.tf. Organizing things in categories like this would make it easy to sift through larger imports.

Summary
#

Terrafy is a great way to bring existing infrastructure into Terraform state. Installation and usage are simple, and the documentation is good. I think this tool will gain enough momentum that new features will come quickly, hopefully on the organization side. To learn more, visit the GitHub page. Happy building!

Related

Getting Started With Alkira And Terraform (Part 2)

In Part 1, we started with a scalable foundation that can adapt over time as the business grows and adjusts to changing markets. With Alkira’s Network Cloud, we take a cloud native approach in enabling our customer’s transformation. No appliances need to be provisioned in remote VPCs or VNets, and no agents need to be installed on workloads. Getting started is as easy as kicking off a build pipeline. For Part 2, let’s connect some networks from AWS, Azure, and GCP.

Getting Started With Alkira And Terraform - (Part 1)

HashiCorp’s Terraform needs no introduction. It is all but the de facto vehicle for delivering cloud infrastructure, and for a good reason. What Terraform did for Multi-Cloud Infrastructure as Code, is precisely what Alkira does for the network. What happens when you use these two platforms together to deliver networking in and across clouds? If providing network services in code faster than ever before sounds interesting, this multi-part series is for you. Need a quick primer on Alkira? You can read up here.

Intro To Terraform Modules With AWS

Effectively automating infrastructure is no longer a luxury but a staple in the enterprise move through future transformation. I wrote a blog recently about using Terraform with Packer together, and wanted to take this thought further with breaking down Terraform Modules and getting well connected with Terraform Cloud. I recently put together a simple module for building base infrastructure in AWS for the purpose of testing Alkira Network Cloud. Let’s dive in!