Introduction
When managing Terraform configurations, you can organize resources into modules for better structure and maintainability. Moving resources between modules or back to the root configuration requires careful state management to avoid resource recreation and minimize downtime. When you move a resource's configuration code, you must also update its address in the Terraform state file to match.
This guide provides a structured approach for moving Terraform resources using either the terraform state mv command or a moved block, including examples with the count meta-argument.
Prerequisites
This guide assumes you have a Terraform configuration with resources defined in the root module (e.g., main.tf) that you intend to refactor into a child module.
Example initial resource configuration:
resource "null_resource" "resource_null" {}Procedure
Scenario 1: Moving a Resource into a Module
To move a resource into a module, you must first move the resource's configuration block into the module's .tf files. Then, update the state file to reflect the new resource address.
Method A: Using terraform state mv
Use the terraform state mv command to update the resource's address in the state file. This command takes the source address and the destination address as arguments.
Execute the following command:
$ terraform state mv null_resource.resource_null module.terraform_null_module.null_resource.resource_null
After the move, the state reflects the new identifier. You can verify this with terraform state list.
$ terraform state list module.terraform_null_module.null_resource.resource_null
Method B: Using a moved Block
As an alternative to terraform state mv, you can add a moved block to your configuration to instruct Terraform to update the resource address during the next plan and apply cycle.
Add the following blocks to your root configuration:
module "terraform_null_module" {
source = "./modules/terraform_null_module"
}
moved {
from = null_resource.resource_null
to = module.terraform_null_module.null_resource.resource_null
}Scenario 2: Moving a Resource out of a Module
To move a resource from a module back to the root configuration, you must first move its configuration code. Then, update the state to reflect its new, shorter address.
Method A: Using terraform state mv
Execute the terraform state mv command, reversing the source and destination addresses from the previous scenario.
$ terraform state mv module.terraform_null_module.null_resource.resource_null null_resource.resource_null
Method B: Using a moved Block
Add a moved block to your configuration with the module address as the from argument and the root address as the to argument.
moved {
from = module.terraform_null_module.null_resource.resource_null
to = null_resource.resource_null
}Scenario 3: Moving Resources with the count Meta-Argument
When moving resources managed with the count meta-argument, you must update the address for each instance of the resource by specifying its index.
Moving a count Resource into a Module
If the count is defined on the resource block inside the module, use this format:
moved {
from = null_resource.resource_null[0]
to = module.terraform_null_module.null_resource.resource_null[0]
}If the count is defined on the module block in the root configuration, use this format:
moved {
from = null_resource.resource_null[0]
to = module.terraform_null_module[0].null_resource.resource_null
}Moving a count Resource out of a Module
Similarly, moving a resource with count out of a module requires specifying the index for each instance.
moved {
from = module.terraform_null_module[0].null_resource.resource_null
to = null_resource.resource_null[0]
}Note: Ensure you handle count indexing appropriately based on whether count is specified on the resource block or the module block.
Additional Information
For more details on the terraform state mv command, refer to the official documentation.