A small new feature in Terraform 1.12.0 released on May 14 is the ability to import resources using an identity expression instead of an id.
A good first question to ask: isn’t id short for identity? I suppose it is!
There is not a lot of information to read about this feature (yet), so I am basing the content of this blog post on what I can find in the pull-request for the feature.
Importing by ID#
The original method of importing resources into your Terraform state is to use the CLI:
$ terraform import ADDR ID
ADDR
is the resource address in your Terraform configuration, and ID
is the ID string of the resource.
I have written a lot about how this is no longer the preferred method, so I won’t go over it again here. The better approach is to use the import
block:
import {
to = <terraform configuration address>
id = "<resource ID>"
}
A full example of importing an Azure resource group named rg-import-me
located in the swedencentral
region to your Terraform state looks like this:
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 4.28.0"
}
}
}
provider "azurerm" {
features {}
subscription_id = "b8b3c150-9005-499b-971b-28bb85aeb9bb"
}
import {
to = azurerm_resource_group.default
id = "/subscriptions/b8b3c150-9005-499b-971b-28bb85aeb9bb/resourceGroups/rg-import-me"
}
resource "azurerm_resource_group" default" {
name = "rg-import-me"
location = "swedencentral"
}
Importing by identity#
It is a bit annoying that I have to specify the full resource ID in the id
argument of the import
block. This is more of a problem for the Azure provider than for other providers (e.g. AWS). I have already configured the AzureRM provider with my Azure subscription ID, yet I have to repeat this information in the ID of the resource I want to import.
What if there was another way to configure the import
block?
In Terraform 1.12.0 and later there is! And here comes my guesswork based on the code. I have not been able to actually try this out, I will explain why later in this post.
The resource identity is simply how the resource is configured. To explain what I mean, let’s repeat the previous example but importing using the identity instead of the ID:
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 4.28.0"
}
}
}
provider "azurerm" {
features {}
subscription_id = "b8b3c150-9005-499b-971b-28bb85aeb9bb"
}
import {
to = azurerm_resource_group.default
identity = {
name = "rg-import-me"
}
}
resource "azurerm_resource_group" default" {
name = "rg-import-me"
location = "swedencentral"
}
I simply repeat some of the information from the resource
block in the identity
argument of the import
block.
The information in the identity
block must be enough to uniquely identify a resource in the target provider environment. For an Azure resource group, the name is sufficient to identify a unique object. The location does not matter for uniqueness.
Let me reiterate: I do not know for sure this is how the feature works. This is based on what I can see in the pull request for this feature. The official documentation is (at the time of writing) not updated to include this new featre.
This feature seems to be based on the providers exposing identity information for their resoruces in the provider schema. So far I have not been able to find a provider that does this. That is why I have not been able to test the feature for real.
The error I encounter when I try this demo is the following:
azurerm_resource_group.default: Preparing import... [identity=<empty>]
Planning failed. Terraform encountered an error while generating this plan.
│
│ Error: unknown identity type "azurerm_resource_group"
│
In the pull-request you can see tests written for this feature where the test provider includes IdentityTypes
information in the schema (see here):
Conclusions#
I am looking forward to see providers add these identity types to allow for a cleaner import
block.
If you have any additional insights into this feature, let me know on LinkedIn.