Now that we have gained an understanding about what Terraform State is how do we manipulate it, and when should we? In most scenarios it is actually not recommended to manipulate our state in any way as that is the responsibility of our Terraform code. However, in some situations we don’t have a choice, or perhaps we want to test a particular scenario that’s when state manipulation comes into play.
First lets check out the terraform state
CLI command, it comes with 7 subcommands:
list
- list all resources within the state file
mv
- move an item within the state file
pull
- pull the current state file and output it to our terminal
push
- update remote state from a local state file
replace-provider
- replace a provider within the state file
rm
- remove a resource from our state file
show
- show a single resource within the state file
Generally I use list
and show
fairly frequently to interrogate what’s in the state file, especially if it is a new codebase that I am looking at.
The rm
subcommand can also be very useful if someone has been unkind enough to remove a resource (e.g. from the Azure portal). This allows us to remove that reference in state so that Terraform won’t complain, although if we don’t also remove it from the code Terraform will try to create on next apply
.
Let’s dive into some scenarios and then how we would resolve them:
Force replacement/recreation of a single resource within state
This is actually pretty common during the development phase with larger projects. Let’s say you’ve built an entire cloud environment but you want to recreate a network. taint
allows us to do this, otherwise we might need to delete the resource manually or comment the code out, neither are good solutions.
# Find the resource in state
terraform state list
# Inspect the resource
terraform state show azurerm_virtual_network.this
# Taint the resource
terraform taint azurerm_virtual_network.this
On the next terraform apply
the azurerm_virtual_network.this
will be recreated. If you change your mind and no longer require the resource to be tainted then you can use the aptly named untaint
command.
terraform untaint azurerm_virtual_network.this
Import an existing resource into our state file
Sometimes we define all of our resources in our Terraform code but for some reason the resource is manually created. This leaves us in a state where Terraform can see the resource on the remote end and in its code but not in state. In order to fix that we need to import the resource into state this is where the import
command comes into play.
As an example we are going to import the above virtual network into our state file.
terraform import azurerm_virtual_network.this /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/Resource_Group/providers/Microsoft.Network/virtualNetworks/Virtual Network
As you can see from the above the import process is pretty simple, we simply need to pass in the address in Terraform state and the ID that is used for the resource. This will be different between providers.
Move a resource from a single resource into and set of resources, or into a module
This happens as our Terraform code grows, we might start with a single instance of something and then move to multiple instance through the use of the for
expression or through creation of a module. To tell Terraform that we want to move our currently existing resource into one of those constructs we can either use the moved
block or the Terraform mv
command. Let’s take a look at an example.
# `for` expression
terraform mv azurerm_virtual_network.this azurerm_virtual_network.this["primary"]
# Module
terraform mv azurerm_virtual_network.this module.virtual_networks.azurerm_virtual_network.this
Update your state with the latest from your live resources
In this instance we want to force our state to go and check what the real state of our resources are and update state with any changes. This can be done with a very simple command.
Closing out
In this post we went through the basics of working with Terraform state. How to taint and untaint a resource, how to move a resource to a new address within state, importing existing resources into state and refreshing state from the resource APIs. This really just touches the surface of working with state but in reality it is also about as much as you should be doing in state for 95% of cases. As a general rule of thumb if you’re modifying a state file by hand you’re doing something wrong.