hashicorp / terraform-provider-google

Terraform Provider for Google Cloud Platform
https://registry.terraform.io/providers/hashicorp/google/latest/docs
Mozilla Public License 2.0
2.33k stars 1.73k forks source link

secondary_ip_range block not being removed when empty list is passed #14878

Open jeheyer opened 1 year ago

jeheyer commented 1 year ago

Community Note

Terraform Version

1.4.5

Affected Resource(s)

Terraform Configuration Files

Note: var.subnets.secondary_ranges is defined a a list of objects with 'name' and 'range' attributes.

locals {
  subnets = [for i, v in var.subnets : merge(v,
    {
      key           = "${v.project_id}-${v.region}-${v.name}"
      secondary_ranges = [for i, v in coalesce(v.secondary_ranges, []) : {
        name  = coalesce(v.name, "secondary-range-${i}")
        range = v.range
      }]
    }
  )]
}
resource "google_compute_subnetwork" "default" {
  for_each                 = { for k, v in local.subnets : v.key => v }
  project                  = var.project_id
  dynamic "secondary_ip_range" {
    for_each = each.value.secondary_ranges
    content {
      range_name    = secondary_ip_range.value.name
      ip_cidr_range = secondary_ip_range.value.range
    }
  }
}

Debug Output

Panic Output

Expected Behavior

Since the block is an empty list, the dynamic block should be removed, and any values associated with it deleted.

Actual Behavior

Secondary ranges remain in place unchanged

Steps to Reproduce

Create secondary ranges on a subnet via a list. Then make the list empty.

  1. terraform apply

Important Factoids

I do see several reports of this going back a few years, and the suggested workaround is pass an empty list ([]):

https://github.com/hashicorp/terraform-provider-google/issues/10433 https://github.com/hashicorp/terraform-provider-google/issues/11654 https://github.com/hashicorp/terraform-provider-google/issues/2570 https://github.com/hashicorp/terraform-provider-google/issues/5568

That's exactly what I'm doing, but the secondary ranges never get removed when that is passed.

I did try working around by passing a single object with dummy values to force a change rather than delete:

for_each = length(each.value.secondary_ranges) > 0 ? each.value.secondary_ranges : [{ name = "null", range = "192.0.2.0/24" }]

But this results in error message:

Error: Error updating Subnetwork "": googleapi: Error 400: Invalid value for field 'resource.secondaryIpRanges': ''. Cannot add and remove secondary IP ranges in the same request.

Also, commenting out the secondary_ip_range block entirely does result in the ranges being removed either. So I'm suspecting this is ultimately some type of API limitation.

References

jeheyer commented 1 year ago

Seems the fix for this is just remove the dynamic block entirely and just write secondary_ip_range as if it were an attribute:

resource "google_compute_subnetwork" "default" {
  secondary_ip_range = [for secondary_range in var.subnet.secondary_ranges : {
    range_name    = secondary_range.name
    ip_cidr_range = secondary_range.ip_cidr
  }]
}

I think the problem is more the documentation isn't clear

edwardmedia commented 1 year ago

@jeheyer it works for me after I update the config with secondary_ip_range =[]. Does it work for you?


resource "google_compute_subnetwork" "default" {
...
  secondary_ip_range = []
}
edwardmedia commented 1 year ago

@jeheyer is this still an issue?

jeheyer commented 1 year ago

Depends on what you mean by 'issue'

edwardmedia commented 1 year ago

@jeheyer does this work for you? From what I can see, it is not a problem at the provider level. This is what I mean by issue. You may need to code like this to make it work.

jeheyer commented 1 year ago

You're linking to a work-around, not the issue itself.

edwardmedia commented 1 year ago

@slevenick what do you think about this?

ScottSuarez commented 10 months ago

This is a Computed field. This means if you don't assign a value it will accept the server defined value for this. This is a limitation of terraform.

Similar to the suggestion given you can assign an empty block in case of empty secondary_ranges.

https://github.com/hashicorp/terraform-provider-google-beta/blob/5a2b54ce9458771716576665a31d118350618540/google-beta/services/compute/resource_compute_subnetwork.go#L253

ScottSuarez commented 10 months ago

Not workable, setting for retriage.. Recommendation to close issue.