Moving a Resource from One Project to Another
Learn why and how to move resources from one Terraform project to another.
Moving a resource
When Terraform projects become large or you want to refactor them, you may need to move a resource from one Terraform project to another. To do this, you cannot simply delete the resource from the Terraform project and add it to the other. If you do, then Terraform will physically delete the resource and recreate it again in the other project. This is often not desirable as it will cause a loss of availability and/or data.
First project example
To solve this problem, we will learn how you can manipulate the Terraform state to move resources between projects:
provider "aws" {region = "us-east-2"}resource "aws_vpc" "my_vpc" {cidr_block = "10.1.0.0/16"tags = {Name = "vpc"}}
Second project example
Next, we’ll create another project. This will be our second Terraform project where we are going to move the resource to:
provider "aws" {region = "us-east-2"}resource "aws_vpc" "main" {cidr_block = "10.1.0.0/16"tags = {Name = "vpc"}}
Both of the projects are pretty similar. They both set up the AWS provider in the same way both define an AWS VPC with the same CIDR range (10.1.0.0/16
), and both have a single name tag, vpc
. The VPCs do have a different identifier though. In the first project, we use the identifier my_vpc
while in the second project the identifier is main
.
We have now created our VPC. In this example, we want to move this VPC to the second Terraform project, but we do not want to destroy it. If you remove the block my_vpc
from the project and run
terraform apply
, Terraform will want to destroy the VPC. This is not what we want. To make
Terraform stop managing the resource, we have to remove it from Terraform’s state.
Removing the VPC from Terraform’s state
To remove the VPC from the Terraform’s state, we need to use the terraform state rm
command.
This command needs to be handled with care. To remove the VPC from the state, run
terraform state rm aws_vpc.my_vpc
You will see Terraform say Removed aws_vpc.my_vpc
.
This means that the VPC will not be in Terraform’s state anymore so, as far as Terraform is concerned, it did not create the VPC and is not managing it. Note the VPC still exists in AWS (which is what we wanted). The format of the terraform state rm
command is
terraform state rm <resource_name>.<resource_idenitifier>
Deleting AWS VPC block
Now that the VPC is removed from our first project, go ahead and delete the aws_vpc.my_vpc
block
from the project and run terraform apply
. Terraform will report that there is nothing to do. The reason for this is that Terraform does not know about the VPC anymore. This is the effect the state
removal had. We have now successfully removed the VPC from this project but, crucially, it still exists in AWS.
Running the second project
Next, we want to make the second project own the VPC:
-
Run
terraform init
to initialise Terraform. -
Open the AWS console in a web browser and go to the VPC section.
-
Find the ID of the VPC that we created using the first Terraform project and copy it to your clipboard.
-
Now run
terraform import aws_vpc.main <VPC_ID>
.This will import the VPC into the state of Terraform.
-
Now run
terraform apply
and Terraform should report that there is nothing to do.This is because Terraform in the second project is now managing the VPC and it matches our HCL code.
Another interesting aside is that we changed the identifier of the VPC in our HCL code from
my_vpc
tomain
.
We have now successfully moved the VPC from one Terraform project to another. Although this was a bit of a trivial example, the technique can be used to break up larger Terraform projects when they become cumbersome to manage.
Another way to move resources
There is another way to move a resource from one project to another, which is to use the terraform state mv
command.
Let’s use the terraform state mv
command to move the AWS VPC from the second project back to the first project.
Before starting this exercise, paste the VPC block back into the first project with the identifier my_vpc
.
Run the command:
terraform state mv -state-out=../state_example_02a/terraform.tfstate aws_vpc.main aws_vpc.my_vpc
What does the command do
This command directs the system to move an item from the Terraform state into the file specified by the flag -state-out
.
We are pointing that flag to the Terraform state of our first project. The next two arguments are the source resource and the destination resources. Remember, we are using the identifier main
in the second project and my_vpc
in the first project. Run this command then go into the folder of the first project. If you run terraform apply
, you will see Terraform report that there is nothing to do.
This command has slightly different semantics from the remove and then import flow that we first covered. This command removes the resource from the first project’s Terraform state but, rather than importing the resource, puts it directly into the state file.
An import works a bit differently on the back end. Terraform queries the API of the infrastructure to read the resource and uses that to build the state. On the other hand, the move command copies the state across directly.
The advantage of the state mv
command is that it works on any resource, even if it does not support an import.
Listing Terraform state
One last thing to cover in this section is listing the Terraform state. In the first project with the VPC, run the command terraform state list
. This command lists all of the resources that exist in Terraform’s state file. You should see the following output:
aws_vpc.my_vpc
The terraform state list
command is handy if you want to interrogate Terraform to find out
which resources are in its state file.
Get hands-on with 1300+ tech skills courses.