equinix/terraform-provider-metal

Uppercase `metro` attribute causes resource destruction

flokli opened this issue · 1 comments

Hi there,

Terraform Version

Terraform v0.15.5
on linux_amd64

Affected Resource(s)

Please list the resources as a list, for example:

  • metal_device

If this issue appears to affect multiple resources, it may be an issue with Terraform's core, so please mention this.

Terraform Configuration Files

resource "metal_device" "node1" {
  hostname         = "node1"
  plan             = "c3.medium.x86"
  metro            = "FR"
  operating_system = "custom_ipxe"
  ipxe_script_url  = "http://example.com/foo.ipxe"
  always_pxe       = true

  project_id    = local.metal_project_id
  billing_cycle = "hourly"
}

Expected Behavior

On a subsequent apply, the resource shouldn't change.

Actual Behavior

Terraform proposed replacing the metal_device resource entirely (which would have caused a destroy of the server, and creation of the new one.

It seems the metro name (FR) got downcased during the first apply, but while comparing on the next terraform apply, this was considered to be a change requiring replacement:

  # metal_device.node1 must be replaced
-/+ resource "metal_device" "node1" {
      ~ access_private_ipv4              = "10.25.19.131" -> (known after apply)
      ~ access_public_ipv4               = "145.40.93.171" -> (known after apply)
      ~ access_public_ipv6               = "2604:xxxx:xxxx:xxxx::3" -> (known after apply)
      ~ created                          = "2021-06-05T10:00:15Z" -> (known after apply)
      ~ deployed_facility                = "fr2" -> (known after apply)
      + deployed_hardware_reservation_id = (known after apply)
      - facilities                       = [
          - "fr2",
        ] -> null
      ~ id                               = "c554b60b-9ca6-xxxx-xxxx-8137f8d0eff6" -> (known after apply)
      ~ ipxe_script_url                  = "http://example.com/foo.ipxe" -> "http://example.com/foo.ipxe"
      ~ locked                           = false -> (known after apply)
      ~ metro                            = "fr" -> "FR" # forces replacement
      ~ network                          = [
          - {

Changing the metro to be downcased in the .hcl helped to workaround - but it's very confusing.

In your docs, metro codes are shown in uppercase most of the time. If the terraform provider accepts both downcased and upcased variants, a subsequent apply should be a no-op.

Steps to Reproduce

Please list the steps required to reproduce the issue, for example:

  1. terraform apply
t0mk commented

Hi @flokli thanks for letting us know. You're right that if the doc shows the metro in uppercase, the TF provider should accept it and ignore the case of the metro string. I will need to check if the API accepts uppercase, and if yes, I will make the provider to always cast the metro string to lowercase for storing in the state.

The way to go is probably a statefunc:
https://www.terraform.io/docs/extend/schemas/schema-behaviors.html#statefunc

We'll need to do this in more than metal_device:

(base) tomk@xps ~/tpm/metal ±metro_case » grep '"metro": {' * | cut -f 1 -d":"
datasource_metal_connection.go
datasource_metal_device.go
datasource_metal_facility.go
datasource_metal_ip_block_ranges.go
datasource_metal_reserved_ip_block.go
datasource_metal_spot_market_price.go
datasource_metal_spot_market_request.go
datasource_metal_vlan.go
resource_metal_connection.go
resource_metal_device.go
resource_metal_spot_market_request.go
resource_metal_vlan.go