Rename resources from the terraform state

When handling Infrastructure as Code (IaC) with terraform, refactoring the code might cause terraform to try to delete the existing resources an recreate them using a different name:

  # module.jenkins.module.worker.module.kms-parameter-store.aws_iam_policy.kms_read_policy will be destroyed
  # module.jenkins.module.worker.module.kms-parameter-store.aws_iam_policy.ssm_read_policy will be destroyed
  # module.jenkins.module.worker.module.kms-parameter-store.aws_iam_role_policy_attachment.kms_read_policy_attachment will be destroyed
  # module.jenkins.module.worker.module.kms-parameter-store.aws_iam_role_policy_attachment.ssm_role_policy_attachment will be destroyed
  # module.jenkins.module.worker.module.kms-parameter-store.aws_kms_alias.kms_key_alias will be destroyed
  # module.jenkins.module.worker.module.kms-parameter-store.aws_kms_key.kms_key will be destroyed

  # module.jenkins.module.worker[0].module.kms-parameter-store.aws_iam_policy.kms_read_policy will be created
  # module.jenkins.module.worker[0].module.kms-parameter-store.aws_iam_policy.ssm_read_policy will be created
  # module.jenkins.module.worker[0].module.kms-parameter-store.aws_iam_role_policy_attachment.kms_read_policy_attachment will be created
  # module.jenkins.module.worker[0].module.kms-parameter-store.aws_iam_role_policy_attachment.ssm_role_policy_attachment will be created
  # module.jenkins.module.worker[0].module.kms-parameter-store.aws_kms_alias.kms_key_alias will be created
  # module.jenkins.module.worker[0].module.kms-parameter-store.aws_kms_key.kms_key will be created

While in some cases it's just fine to destroy the resources and recreate them back, in other cases it can cause a undesired service interruption just for deleting all the resources and recreate them back exactly with the same settings using slightly different name on the terraform state.

We can avoid it by renaming the resources in the terraform state to the name terraform is expecting

To have a list of the current resources we have on the terraform state we can use terraform state show. Using this list we can them rename the resources using terraform state mv:

$ terraform state mv --help
Usage: terraform state mv [options] SOURCE DESTINATION

Let's take as an example a plan that would recreate 126 resources:

$ terraform plan
Plan: 126 to add, 0 to change, 126 to destroy.

We can use terraform state mv on one of the resources to move it to the path where it would be recreated:

$ terraform state mv "module.jenkins.module.worker.module.kms-parameter-store.aws_iam_policy.kms_read_policy" "module.jenkins.module.worker[0].module.kms-parameter-store.aws_iam_policy.kms_read_policy"
Acquiring state lock. This may take a few moments...
Move "module.jenkins.module.worker.module.kms-parameter-store.aws_iam_policy.kms_read_policy" to "module.jenkins.module.worker[0].module.kms-parameter-store.aws_iam_policy.kms_read_policy"
Successfully moved 1 object(s).
Releasing state lock. This may take a few moments...

Running again the terraform plan we will notice we have one less resource to be recreated:

$ terraform plan
Plan: 125 to add, 0 to change, 125 to destroy.

Bear in mind that by moving the parent resource all the nested resources are also moved. Depending on the refactor we made we can take this into account to move more efficiently the resources:

terraform state mv module.jenkins.module.worker module.jenkins.module.worker[0]

Posted on 23/04/2021