Moving terraform resources from the state file as code

2 min read | by Jordi Prats

Certain operations can cause terraform to try to delete an recreate a resource when we are just trying to move it around within the state, for example renaming a resource

If we try to rename a resource we will end up the a plan that will look similar to this one:

Terraform will perform the following actions:

  # module.eks["pet2cattle-white"].kubernetes_namespace.pet2cattle_namespace will be destroyed
  # (because kubernetes_namespace.pet2cattle_namespace is not in configuration)
  - resource "kubernetes_namespace" "pet2cattle_namespace" {
      - id = "pet2cattle-white" -> null

      - metadata {
          - annotations      = {} -> null
          - generation       = 0 -> null
          - labels           = {} -> null
          - name             = "pet2cattle-white" -> null
          - resource_version = "34561708" -> null
          - uid              = "d03c4dcd-def1-4007-9f4b-18e55c4b65d1" -> null
        }
    }

  # module.eks["pet2cattle-white"].kubernetes_namespace.pet2cattle_namespace_test_rename will be created
  + resource "kubernetes_namespace" "pet2cattle_namespace_test_rename" {
      + id = (known after apply)

      + metadata {
          + generation       = (known after apply)
          + name             = "pet2cattle-white"
          + resource_version = (known after apply)
          + self_link        = (known after apply)
          + uid              = (known after apply)
        }
    }

Plan: 1 to add, 0 to change, 1 to destroy.

To avoid deleting the resource we can always move the resource around using terraform state mv, but that would be an manually perform the operation imperatively. Starting terraform 1.1 we can do this operation as code using the move block. To do so we just need to specify the source and destination as we would to with terraform state mv:

moved {    
  from = kubernetes_namespace.pet2cattle_namespace
  to = kubernetes_namespace.pet2cattle_namespace_test_rename 
}

resource "kubernetes_namespace" "pet2cattle_namespace_test_rename" {
  metadata {
    name = var.namespace
  }

  depends_on = [
    module.redis_instances,
    module.rds_instances,
    module.s3_instances
  ]
}

This is going to be planned as well, so we will be able to check the change before actually applying it:

Terraform will perform the following actions:

  # module.eks["pet2cattle-white"].kubernetes_namespace.pet2cattle_namespace has moved to module.eks["pet2cattle-white"].kubernetes_namespace.pet2cattle_namespace_test_rename
    resource "kubernetes_namespace" "pet2cattle_namespace_test_rename" {
        id = "pet2cattle-white"

        # (1 unchanged block hidden)
    }

Plan: 0 to add, 0 to change, 0 to destroy.

Posted on 02/02/2022

Categories