hashicorp / terraform

Terraform enables you to safely and predictably create, change, and improve infrastructure. It is a source-available tool that codifies APIs into declarative configuration files that can be shared amongst team members, treated as code, edited, reviewed, and versioned.
https://www.terraform.io/
Other
42.52k stars 9.52k forks source link

moved block does not trigger if using `locals` as input #35840

Open fritz-net opened 3 days ago

fritz-net commented 3 days ago

Terraform Version

Terraform v1.9.6
on windows_amd64
+ provider registry.terraform.io/hashicorp/random v3.6.3

I also tested it with 1.7

Terraform Configuration Files

terraform {
    required_providers {
        random = {
        source = "hashicorp/random"
        }
    }
}

resource "random_password" "token" { # first run `terraform apply` with this named `token_old`
  length  = 32
  special = false
}

# this works
#moved {
#    from = random_password.token_old
#    to = random_password.token
#}

# this is the bug and causes a destroy and create
locals {
    old_token = "random_password.token_old"
}
moved {
    from = locals.old_token
    to = random_password.token
}

# this is not valid:
# A single static variable reference is required: only attribute access and
# │ indexing with constant keys. No calculations, function calls, template
# │ expressions, etc are allowed here.
# 
# moved {
#     from = "random_password.token_old"
#     to = "random_password.token"
# }

Debug Output

terraform plan
random_password.token_old: Refreshing state... [id=none]

Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
  + create
  - destroy

Terraform will perform the following actions:

  # random_password.token will be created
  + resource "random_password" "token" {
      + bcrypt_hash = (sensitive value)
      + id          = (known after apply)
      + length      = 32
      + lower       = true
      + min_lower   = 0
      + min_numeric = 0
      + min_special = 0
      + min_upper   = 0
      + number      = true
      + numeric     = true
      + result      = (sensitive value)
      + special     = false
      + upper       = true
    }

  # random_password.token_old will be destroyed
  # (because random_password.token_old is not in configuration)
  - resource "random_password" "token_old" {
      - bcrypt_hash = (sensitive value) -> null
      - id          = "none" -> null
      - length      = 32 -> null
      - lower       = true -> null
      - min_lower   = 0 -> null
      - min_numeric = 0 -> null
      - min_special = 0 -> null
      - min_upper   = 0 -> null
      - number      = true -> null
      - numeric     = true -> null
      - result      = (sensitive value) -> null
      - special     = false -> null
      - upper       = true -> null
    }

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

Expected Behavior

it should also move the resource like in the first, commented out, example:

moved {
    from = random_password.token_old
    to = random_password.token
}
terraform plan
random_password.token: Refreshing state... [id=none]

Terraform will perform the following actions:

  # random_password.token_old has moved to random_password.token
    resource "random_password" "token" {
        id          = "none"
        # (12 unchanged attributes hidden)
    }

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

Actual Behavior

the resource is not moved but destroyed and created

when using:

locals {
    old_token = "random_password.token_old"
}
moved {
    from = locals.old_token
    to = random_password.token
}

Steps to Reproduce

Additional Context

tested in CI/CD with version 1.7 tested on windows with 1.9

The Idea behind using locals is that I can use variables inside the names of the resources. I needed this since I'm migrating away from a lib which dynamically created tf.json files and used env vars to name the resources.

References

No response

jbardin commented 2 days ago

Hi @fritz-net,

Thanks for filing the issue! Terraform should return an error there, since locals.old_token is not a valid from address.

fritz-net commented 7 hours ago

Hey @jbardin,

thanks for confirming. I was hoping that it is a valid option and the comparison is just somehow "buggy" :( I solved it by doing some bash pre processing on relevant .tf files.

Could the docs then be updated? Currently they allow strings: https://developer.hashicorp.com/terraform/language/moved