Posted on 9 September 2020, updated on 14 February 2022.

This article deals with moving Terraform resources in the Terraform state. First, we will see how we can change a resource name, move a resource between different Terraform objects (“for_each”, “count” and simple resources). Then, we will see a way for migrating a resource from a workspace to another Terraform workspace. In this article, we will work with an AWS S3 bucket but it is just an example, you can do it with any other resource in Terraform.

State manipulation

Before beginning the manipulations of Terraform resources, you have to understand some things about the state and its manipulations. Manipulating the Terraform state is a delicate matter and should not become a habit. It should only be used as a last resort. Fortunately, Terraform makes backup automatically when we manipulate the state.

Moving Terraform objects in a workspace

Change the Terraform simple resource’s name

To change just the Terraform resource’s name, you do not have a magic command to do it. Therefore, we found another way. The simplest way to change it is to use the following command:

This command lets you move an element in a workspace between two different resources (if you want to understand how to create resources in Terraform, check here). So, if you want to change the name of the following resource with the new name “great_s3_bucket”:

Create a duplicate of it with the new name:

And execute the following command to move it:

Now, you can check in your workspace, Terraform follows your new resource (you can check the list of following resources with the command: terraform state list)

After moving it, you can just remove the code of the old Terraform resource and you’re done.

Moving a simple Terraform element to a “for_each” loop

Thanks to the command “terraform state mv”, you can also move objects from a simple resource to a “for_each” loop. Take your great s3 bucket:

So, the objective is to have something like that:

Therefore, create the above object with another name not to have conflicts between our simple resource and this “for_each” and execute the following command:

Of course, you have to change <NEW_NAME> to the right name and <BUCKET_NAME> to the right value in your bucketsList variable. Do not forget the quotes, otherwise, it cannot work.

Change a “count” Terraform object to a “for_each” loop

To move an element from a “count” resource to a “for_each” element, execute the following command:

To execute correctly this command you have to create a map for your new for_each object which will be the equivalent of the list variable for the count loop.

This command moves the first element of a “count” resource to a “for_each” loop with the key “my_beautiful_bucket”. To change all elements from the “count” object, you just have to reiterate the command with every element.

Move a resource to another workspace

Here, I present to you one way to change a resource between 2 workspaces. To migrate it, I propose 2 steps:

  • Deleting the resource in the first workspace
  • Importing the resource in the new workspace

The objective is to make a migration without the unavailability of service. Therefore, first, delete the resource in the workspace with the command:

With this command, the Terraform workspace does not manage the resource anymore but the resource is not deleted.

Second, go to your other workspace and import the resource with:

To know, how can you import a resource, go to the Terraform documentation.

I hope this article helps you to make what you want. Just remember, state manipulation has to be done if you have no other choices and you have to be very careful when you manipulate a Terraform state.