MarkK
MarkK

Reputation: 1088

Terraform detects changes when there isn't any

I'm using terraform v1.1.3, whenever I run terraform plan it states I have made changes even when nothing at all has changed locally or remotely. For example, if I run terraform apply then terraform plan immediately after, it states that objects have changed outside of Terraform and forces replacement of my instance.

  # module.database.oci_core_instance.instance[0] has changed
  ~ resource "oci_core_instance" "minstance" {
      + extended_metadata                   = {}
        id                                  = "ocid1.instance.oc1.me-jeddah-1.anvgkljrnghkmsacizo3ubuejydotfi7qz45if32x2e3b55mhirvrvpiw7nq"

Why?

resource "oci_core_instance" "instance" {
  availability_domain                = random_shuffle.compute_ad.result[count.index % length(random_shuffle.compute_ad.result)]
  compartment_id                      = var.compartment_id
  shape                               = var.instance_shape
  freeform_tags                       = var.freeform_tags 
  shape_config {
        memory_in_gbs = 16 
        ocpus         = 1  
    }
  source_details {
    source_type = "image"
    source_id   = lookup(data.oci_core_images.compute_images.images[0], "id") 
   
  }
  metadata = { 
      ssh_authorized_keys = file(var.ssh_public_key) 
      user_data           = data.template_cloudinit_config.nodes.rendered
  }
  count = var.num_nodes

  depends_on = [
    oci_core_volume.volume_1
  ]
}

Upvotes: 0

Views: 2002

Answers (2)

Martin Atkins
Martin Atkins

Reputation: 74269

I think what you see here is a minor bug in the OCI provider. I think that in the underlying remote API there is no difference between this argument being unset or it being set to an empty map, and so when the provider reads the latest state of the object during the refreshing step it doesn't distinguish between those situations and so it overwrites the null (representing it not being set at all) with an empty map.

If that's true then without modifying the provider I think you could avoid this only by writing the configuration in a way that matches what the provider will produce when it refreshes the object, by including an explicit empty map for that argument:

  extended_metadata = {}

The refresh step will then find the same thing that was saved during the initial creation of the object and so won't produce this errant change report.

The "real" fix here would be for the provider to treat null and {} as equivalent values for this argument, and to so not report a change from null to {}, but that may be hard for the provider developers to achieve depending on how this argument is currently implemented.

Upvotes: 2

DarkMukke
DarkMukke

Reputation: 2489

This is probably because the data resources blocks aren't evaluated until the apply, during the plan it does not know what is in

 data.template_cloudinit_config.nodes.rendered

so to be safe, it marks it as changes

If you are 1000% sure that this is not something that will ever change, you could add

lifecycle {
    ignore_changes = [
        extended_metadata
    ]
  }

But be very careful with this, as if the metadata does change in future, it will simply not apply.

Upvotes: 5

Related Questions