Terraform — Import Blocks
A quick article showcasing the new import block capability recently released in HashiCorp Terraform v1.5 beta 1.
Current situation — import command
Most of you will be familiar with the terraform import command already but as a quick refresher, it's essentially a quick way to as it says “import” objects outside of terraform into your terraform state. Let's look at an example of this in action.
Let’s suppose I have a GCP Bucket called `this-is-my-bucket-name` in GCP (which I do). To import that into my terraform state I would do the following:
- Download my Terraform state file from its external host, in my case my backend bucket (assuming you don’t store it locally which you never should!).
- Have Terraform installed locally.
- Have a way of authenticating or have the rights already as my own user to run Terraform commands against my GCP project (commonly this is a service account key; would you need to grab a new key? Or perhaps grab an 0auth token? Is that a quick process for you?).
- The Google provider saves its state file as “default.tfstate” whereas the import command looks for a “terraform.tftstate” file so I usually rename the file for ease of use.
- Comment out the backend configuration and make sure you can connect correctly to any private registries you may have.
- Finally, run the Terraform init and Terraform import command.
terraform init
terraform import module.gcs.google_storage_bucket.this["this-is-my-bucket-name"] this-is-my-bucket-name
## my terraform main.tf file:
module "gcs" {
source = "drandell/cloud-storage/google"
version = "1.0.1"
buckets = {
"this-is-my-bucket-name": {
project = "billing-budgets"
location = "us-central1"
uniform_bucket_level_access = true
}
}
}
You can see above it took 6 steps for me to finally be able to import a resource. This doesn’t include uploading my new terraform state file back into my GCP Backend bucket, nor re-running whatever CI/CD process I have to check the import is looking okay in my plan with nothing unexpected occurring (at this point I would usually run the terraform plan locally first anyway before re-uploading since I’ve undertaken the effort to get to this point). The time investment here could be quite significant.
It could be that you’re working with an engineering team new to this or perhaps that team doesn’t have the necessary permissions to undertake some of these actions and you are the person “coming to the rescue”.
Introducing Terraform Import Blocks
The terraform import block is simply:
import {
to =
id =
}
- to ~ The reference which you will import into your terraform state (in the import command this is the first argument)
- id ~ The id of the resource you are attempting to import (the second argument in the import command)
My main.tf file now looks like this:
import {
to = module.gcs.google_storage_bucket.this["this-is-my-bucket-name"]
id = "this-is-my-bucket-name"
}
module "gcs" {
source = "drandell/cloud-storage/google"
version = "1.0.1"
buckets = {
"this-is-my-bucket-name": {
project = "billing-budgets"
location = "us-central1"
uniform_bucket_level_access = true
}
}
}
In comparison to running the import command:
- I’ve not had to change my existing codebase apart from adding our new import block in
- I’ve not had to go ahead and retrieve the state file from my external source
- I can simply re-use my existing workflow to run a terraform plan command to produce the following (I’m doing this locally below but imagine if this was a real CI/CD workflow 😆):
Running a terraform apply:
And voila!
After the import statement is complete, the import block is ignored for future runs and can be deleted.
One small caveat to the import blocks for the moment would be that the id
field cannot be interpolated but there’s already a future feature request for this!
And that’s a quick overview of the new terraform import blocks feature 😊.
Disclaimer: This is an early release of the import block and could be subject to changes in the future although it shouldn’t include any breaking changes until Terraform v2 as per the compatibility promise.
Another Disclaimer: I am the author of the GCS module used in the examples above, and that module can be found in the Terraform registry.