TalesMGodois
TalesMGodois

Reputation: 316

How to keep terraform resource after refactoring to use for_each?

Currently I am doing a small refactor in our infrastructure. My current version of my project is similar to the following: And I am trying to use for_each to reuse variables.

resource "google_cloud_scheduler_job" "job" {
  name             = "Create_All_Dossier_Summary"
  description      = "desc1"
  schedule         = "0 19 * * 1"
  time_zone        = "America/Sao_Paulo"
  attempt_deadline = "320s"

  retry_config {
    retry_count = 1
  }

  http_target {
    http_method = "POST"
    uri         = "<some-url>"
  }
}

And I am trying to upgrade it to something like the following:

variable "description" {
  default = ["desc1", "desc 2"]
}

resource "google_cloud_scheduler_job" "job" {
  for_each = toset(var.description)
  name             = "Create_All_Dossier_Summary"
  description      = each.value
  schedule         = "0 19 * * 1"
  time_zone        = "America/Sao_Paulo"
  attempt_deadline = "320s"

  retry_config {
    retry_count = 1
  }

  http_target {
    http_method = "POST"
    uri         = "<some-url>"
  }
}

So, the configuration is ok, but after running terraform plan, terraform is destroying my old one, and that is not what I'd like terraform to do, I was aiming that it just created the second one since the first is already there and the configuration is the same.

Is there a way to tell terraform to not recreate that first resource after doing this refactor?

Plan: 2 to add, 0 to change, 1 to destroy.
# google_cloud_scheduler_job.job will be destroyed
# google_cloud_scheduler_job.job["desc 2"] will be created
# google_cloud_scheduler_job.job["desc1"] will be created

BTW: I am trying to use a list of objects, I have used a list of strings here because it's easier to demonstrate.

Upvotes: 6

Views: 2907

Answers (2)

Ruslan Kovalov
Ruslan Kovalov

Reputation: 141

I think in terms of terraform code that exeecutes inside of CI it is better to use 'moved' block which is described here https://developer.hashicorp.com/terraform/language/modules/develop/refactoring this is the way not to do any manual terminal commands and have everything done by 'terraform apply' Your block should look something like this.

    moved {
      from = google_cloud_scheduler_job.job
      to = google_cloud_scheduler_job.job["desc 2"]
    }

I usually put it right after block with for_each, but not sure that this is the best place for it

Upvotes: 4

Matthew Schuchard
Matthew Schuchard

Reputation: 28739

When the namespace/address of the resource changes in the Terraform config, then you must rename its corresponding id in the state with the state mv subcommand:

terraform state mv google_cloud_scheduler_job.job 'google_cloud_scheduler_job.job["desc 2"]'

Note that the second resource address must be entirely cast as a literal string for the shell to interpret it correctly as an argument due to the use of " in the syntax.

Upvotes: 12

Related Questions