Published on

Azure Export for Terraform: A Comprehensive How-To Guide

Authors
  • avatar
    Name
    Saif Segni
    Twitter

Introduction

Azure Export for Terraform is a tool designed to help reduce friction in translation between Azure and Terraform concepts.

Azure Export for Terraform exports supported resources into Terraform state and generate the corresponding Terraform configuration.It is possible to import into Terraform (or export from Azure, hence the name) a single resource, resources from a resource group, or a set of customizable resources.

In this demo , I will show you how to install Microsoft Azure Export for Terraform, and important existing Azure resources and discuss some best practices and limitations of the tool.

azexportf

Prerequisites

  • An Azure account and subscription .
  • Terraform installed on your machine with version >= v0.12.
  • Azure CLI installed on your machine .
  • Azure profile configured within Azure CLI to read resources in your Azure subscription .

Install Microsoft Azure Export for Terraform

For an installation with apt , you must carry out the following steps:

  1. Import the Microsoft repository key:
$ curl -sSL https://packages.microsoft.com/keys/microsoft.asc > /etc/apt/trusted.gpg.d/microsoft.asc
  1. Add packages-microsoft-com-prod repository:
ver=20.04 # or 22.04
$ apt-add-repository https://packages.microsoft.com/ubuntu/${ver}/prod
  1. Install:
$ apt-get install aztfexport
  1. Verify the installation :
aztfexport -v
aztfexport version v0.14.0(fb772ba)
  1. Check the help
$ aztfexport -h

NAME:
   aztfexport - A tool to bring existing Azure resources under Terraform's management

USAGE:
   aztfexport <command> [option] <scope>

VERSION:
   v0.14.0(fb772ba)

COMMANDS:
   config              Configuring the tool
   resource, res       Exporting a single resource
   resource-group, rg  Exporting a resource group and the nested resources resides within it
   query               Exporting a customized scope of resources determined by an Azure Resource Graph where predicate
   mapping-file, map   Exporting a customized scope of resources determined by the resource mapping file
   help, h             Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --help, -h     show help
   --version, -v  print the version

Import Existing Resources

For this demo , I will use an azure resource group called “my-rg-test01”

$ az group show --name my-rg-test01
{
  "id": "/subscriptions/***************/resourceGroups/my-rg-test01",
  "location": "francecentral",
  "managedBy": null,
  "name": "my-rg-test01",
  "properties": {
    "provisioningState": "Succeeded"
  },
  "tags": {
    "env": "test"
  },
  "type": "Microsoft.Resources/resourceGroups"
}

Inside this resource group , I have create a virtual netwok “my-vnet-test01” with two subnets : default and my-subnet-test01

rg-resources

Now let’s use the aztfexport command to import this resource and manage it with teraform :

$ aztfexport resource-group my-rg-test01

After the tool initializes, a list of the resources to be exported is displayed. Each line has an Azure resourceID matched to the corresponding AzureRM resource type.

resource-import

The list of available commands displays at the bottom of the display.Press w to run the export.

Verify the results

If we check our directory , We will find files that have been created

$ tree
.
├── aztfexportResourceMapping.json
├── main.tf
├── provider.tf
├── terraform.tf
└── terraform.tfstate

0 directories, 5 files

In the main.tf we find the imported resources in the Terraform state . main-file

We can see the terraform configruation block for our resource group , vnet and the two subnets

  • In the provider.tf file, we have the bare minimum, as our authentication method is az cli ,even for the terraform.tf file which automatically selects a provider version.
  • The terraform.tfstate file which clearly shows that our state is, at this stage, still local
  • The aztfexportResourceMapping.json file that mapp your azure resource id with the terraform id

Terraform workflow

Finally let’s run the Terraform workflow :

$ terraform init 
$ terraform plan
azurerm_virtual_network.res-1: Refreshing state... [id=/subscriptions/********************/resourceGroups/my-rg-test01/providers/Microsoft.Network/virtualNetworks/my-vnet-test01]
azurerm_resource_group.res-0: Refreshing state... [id=/subscriptions/********************/resourceGroups/my-rg-test01]
azurerm_subnet.res-3: Refreshing state... [id=/subscriptions/********************/resourceGroups/my-rg-test01/providers/Microsoft.Network/virtualNetworks/my-vnet-test01/subnets/my-subnet-test]
azurerm_subnet.res-2: Refreshing state... [id=/subscriptions/********************/resourceGroups/my-rg-test01/providers/Microsoft.Network/virtualNetworks/my-vnet-test01/subnets/default]

No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.

The terminal outputs No changes needed !The infrastructure and its corresponding state have been successfully exported to Terraform.

Funny GIF

Tips

  • In case of remote tfstate , use the — backend-type & — backend-config value options to define your backend configuration
  • In case of importing one azure resource , you need to specify the resource id (aztfexport resource [option] resource-id )
  • For a non-interactive resource, add the — non-interactive flag: aztfexport rg — non-interactive myResourceGroup.
  • Save the mapping file and import resources based in this mapping file (aztfexport mapping-file [option] resource-mapping-file )
  • To import and add resource to an existant state file , use — append option
  • Use the — hcl-only to generates HCL code (and mapping file), but not the files for resource management (e.g. the state file).

Limitations

  • Microsoft Azure Export for Terraform doesn’t generate variable files, everything is defined in a static way.
  • The tool currently declares dependencies explicitly. You must know the mapping of the relationships between resources to refactor the code to include any implicit dependencies.
  • Certain properties within AzureRM are write-only and aren’t included in the generated code that Azure Export for Terraform creates. The issue is addressed by defining the property after exporting to HCL code.
  • Certain resources in Azure can be defined as either a property in a parent Terraform resource or an individual Terraform resource. One example is a subnet. Azure Export for Terraform defines the resource as an individual resource,but it’s best practice to match your existing coding configuration.

that’s all folks 👏 thanks for reading 🙏