Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

google_compute_url_map: cannot delete google_compute_backend_service #4543

Open
JanMa opened this issue Sep 25, 2019 · 16 comments
Open

google_compute_url_map: cannot delete google_compute_backend_service #4543

JanMa opened this issue Sep 25, 2019 · 16 comments

Comments

@JanMa
Copy link

JanMa commented Sep 25, 2019

Community Note

  • Please vote on this issue by adding a 馃憤 reaction to the original issue to help the community and maintainers prioritize this request
  • Please do not leave "+1" or "me too" comments, they generate extra noise for issue followers and do not help prioritize the request
  • If you are interested in working on this issue or have submitted a pull request, please leave a comment
  • If an issue is assigned to the "modular-magician" user, it is either in the process of being autogenerated, or is planned to be autogenerated soon. If an issue is assigned to a user, that user is claiming responsibility for the issue. If an issue is assigned to "hashibot", a community member has claimed the issue already.

Terraform Version

Terraform v0.12.9

  • provider.google v2.16.0

Affected Resource(s)

  • google_compute_url_map
  • google_compute_backend_service

Terraform Configuration Files

provider "google" {
  project = var.project
  region  = var.region
}

locals {
  instances = {
    # name: zone
    "a-vm" : "europe-west1-b",
    "b-vm" : "europe-west1-c",
    "c-vm" : "europe-west1-d",
    "d-vm" : "europe-west1-b",
    "e-vm" : "europe-west1-c",
  }
}

resource "google_compute_instance" "default" {
  for_each     = local.instances
  name         = each.key
  machine_type = "f1-micro"
  zone         = each.value

  boot_disk {
    initialize_params {
      image = "debian-cloud/debian-10"
    }
  }

  network_interface {
    network    = var.network
    subnetwork = var.subnetwork
  }
  metadata_startup_script = <<EOF
#! /bin/bash
apt-get update
apt-get install apache2 -y
a2ensite default-ssl
a2enmod ssl
vm_hostname="$(curl -H "Metadata-Flavor:Google" \
http://169.254.169.254/computeMetadata/v1/instance/name)"
echo "Page served from: $vm_hostname" | \
tee /var/www/html/index.html
systemctl restart apache2
EOF

}

resource "google_compute_instance_group" "default" {
  for_each = local.instances
  name     = each.key
  zone     = each.value

  instances = [google_compute_instance.default[each.key].self_link]

  named_port {
    name = "http"
    port = "80"
  }
}

resource "google_compute_backend_service" "default" {
  for_each = local.instances
  name     = each.key

  backend {
    group = google_compute_instance_group.default[each.key].self_link
  }

  health_checks = [google_compute_http_health_check.default[each.key].self_link]
  port_name     = "http"
}

resource "google_compute_http_health_check" "default" {
  for_each           = local.instances
  name               = "${each.key}-hc"
  request_path       = "/"
  check_interval_sec = 1
  timeout_sec        = 1
}


resource "google_compute_url_map" "default" {
  name            = "default"
  default_service = google_compute_backend_service.default["a-vm"].self_link

  dynamic "host_rule" {
    for_each = keys(local.instances)
    content {
      hosts        = ["${host_rule.value}.example.com"]
      path_matcher = host_rule.value
    }
  }

  dynamic "path_matcher" {
    for_each = keys(local.instances)
    content {
      name            = path_matcher.value
      default_service = google_compute_backend_service.default[path_matcher.value].self_link
    }
  }
}

Expected Behavior

When an element from the local.instances group gets removed, Terraform should remove all
corresponding resources and update the google_compute_url_map resource accordingly.

Actual Behavior

Instead of first updating the google_compute_url_map, Terraform tries to delete the google_compute_backend_service which causes the following error:

Error: Error reading BackendService: googleapi: Error 400: The backend_service resource 'projects/<project>/global/backendServices/d-vm' is already being used by 'projects/<project>/global/urlMaps/default', resourceInUse
ByAnotherResource                                                                                                                                                                                                                            

I tried various combinations of lifecycle { create_before_destroy = true } and explicit depends_on blocks but i can cannot get this working.

Note: Adding further entries to the local.instances list works just fine.

Steps to Reproduce

  1. terraform apply
  • make sure to pass all required variables for project, region, network and subnetwork
  1. delete line "d-vm": "europe-west1-b"
  2. terraform apply again

b/308569900

@ghost ghost added the bug label Sep 25, 2019
@tysen tysen self-assigned this Sep 30, 2019
@JanMa
Copy link
Author

JanMa commented Oct 7, 2019

So I have found a way around the issue by using the random provider that comes with Terraform.
You can do something like this

resource "random_id" "url_map" {
  keepers = {
    # Generate a new id each time the instance list changes
    instances = base64encode(jsonencode(local.instances))
  }

  byte_length = 1
}

resource "google_compute_url_map" "default" {
  name            = "default-${random_id.url_map.hex}"
  default_service = google_compute_backend_service.default["a-vm"].self_link

  dynamic "host_rule" {
    for_each = keys(jsondecode(base64decode(random_id.url_map.keepers.instances)))
    content {
      hosts        = ["${host_rule.value}.example.com"]
      path_matcher = host_rule.value
    }
  }

  dynamic "path_matcher" {
    for_each = keys(jsondecode(base64decode(random_id.url_map.keepers.instances)))
    content {
      name            = path_matcher.value
      default_service = google_compute_backend_service.default[path_matcher.value].self_link
    }
  }

  lifecycle {
    create_before_destroy = true
  }
}

This will cause the url-map to be recreated every time the local.instances map changes because the random_id resource will change and therefore the name of the url-map will also change.

It is not really solving the underlying issue of the wrong order of deletion of resources though.

@tysen tysen removed their assignment Nov 20, 2019
@edwardmedia edwardmedia self-assigned this Jan 8, 2020
@edwardmedia
Copy link
Contributor

@JanMa your provider's version is old. Can you upgrade it and then try to see if you can repro the issue? If you still see the issue, please attach the full debug log and plan for both tf apply and tf delete. Thanks

@JanMa
Copy link
Author

JanMa commented Jan 9, 2020

Hello @edwardmedia , the described issue still occurs with the latest provider version. After creating all resources with the attached config file and then trying to remove the line "b-vm" : "europe-west1-c", from the local.instances variable, I still get the following error:

Error: Error reading BackendService: googleapi: Error 400: The backend_service resource 'projects/<my-project>/global/backendServices/b-vm' is already being used by 'projects/<my-project>/global/urlMaps/default', resourceInUseByAnotherResource

If I have some more time I will add the full debug output of all commands.

@ghost ghost removed the waiting-response label Jan 9, 2020
@edwardmedia
Copy link
Contributor

@JanMa waiting for your debug logs. Thanks

@edwardmedia
Copy link
Contributor

@ndmckinley I can repro this issue on v3.20.0.

@nat-henderson
Copy link
Contributor

Unfortunately this issue is a combination between a core terraform issue and a GCP issue, and is not resolvable. :(

The two issues are:

  • Terraform does not allow a resource to reorder itself in the plan, which means it will always decide to act on the url map after the backend service.
  • GCP does not provide a way to know which url maps are using backend services, so the url map cannot be updated in the backend service resource.

modular-magician added a commit to modular-magician/terraform-provider-google that referenced this issue Mar 8, 2021
* Mark BQ's materialized view query as ForceNew

* add acctest to update BigQuery Materialized View

Signed-off-by: Modular Magician <magic-modules@google.com>
modular-magician added a commit that referenced this issue Mar 8, 2021
* Mark BQ's materialized view query as ForceNew

* add acctest to update BigQuery Materialized View

Signed-off-by: Modular Magician <magic-modules@google.com>
@zymotik
Copy link

zymotik commented Jan 16, 2023

Unfortunately this issue is a combination between a core terraform issue and a GCP issue, and is not resolvable. :(

The two issues are:

  • Terraform does not allow a resource to reorder itself in the plan, which means it will always decide to act on the url map after the backend service.
  • GCP does not provide a way to know which url maps are using backend services, so the url map cannot be updated in the backend service resource.

Hi @nat-henderson, do these two issues you mention still exist in 2023?

@nat-henderson
Copy link
Contributor

@zymotik Hi there - unfortunately so; the former is unlikely to change, in my view.

For the latter, you can check https://cloud.google.com/compute/docs/reference/rest/v1/backendServices and see that there is no reference to url maps, and no listUsers or similar method on the left hand side of the page.

@45413
Copy link

45413 commented Feb 23, 2023

There is an open feature request to get the required 'in use by' information added to the backendServices.get API request: https://issuetracker.google.com/issues/257459514. If you are interest please +1 or add a note to the ticket to hopefully motivate Google Product Team to get this implemented.

@x-yuri
Copy link

x-yuri commented Jun 14, 2023

So unless I want to use the random trick and want to change e.g. load_balancing_scheme I need to comment out the following resources:

google_compute_global_forwarding_rule
google_compute_target_http_proxy
google_compute_url_map
google_compute_backend_service

terraform apply, then uncomment them, change the load balancing scheme and terraform apply again?

@github-actions github-actions bot added forward/review In review; remove label to forward service/compute-l7-load-balancer labels Oct 25, 2023
@edwardmedia edwardmedia removed the forward/review In review; remove label to forward label Oct 30, 2023
@btkelly
Copy link

btkelly commented Mar 12, 2024

The random id solution didn't change the error I receive as it's not allowing the deletion at all due to a backend service using it. In my use case, I am replacing a backend serverless NEG with a different one but for the same path via the URL map. I receive the same error as linked above seemingly caused by the same issue of order of operations. I'm not sure what a solution here is except manually going in and deleting items in GCP and then running Terraform to recreate them which is not ideal.

@derhally
Copy link

derhally commented May 5, 2024

still happens with terraform 1.5.1 and TGP 5.26.0

@45413
Copy link

45413 commented May 5, 2024

Unfortunately it is unlikely this will ever get resolved in the terraform provided until the API feature request is completed https://issuetracker.google.com/issues/257459514.

Our best option is to get as many people and companies to post on this feature request issue, and /or reach out to Google reps until it gets implemented.

@seils
Copy link

seils commented May 6, 2024

The response body for the backendServices.get method contains a list of URL maps that reference the backend service in usedBy[].

@jacobshirley
Copy link

With their latest update, I believe this could now be fixed

@brianwarsing
Copy link

Checked v5.29.1 and it's still an issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests