GoogleCloudPlatform / terraform-google-nat-gateway

Modular NAT Gateway on Google Compute Engine for Terraform.
Apache License 2.0
156 stars 133 forks source link

How to resolve dependency on newly created custom (sub)network? #90

Open petervandenabeele opened 6 years ago

petervandenabeele commented 6 years ago

I am creating a nat, based on the gke-nat-gateway example, in my own terraform templates. The core code is below. I am (re-)creating the network and subnetwork in the same set of terraform templates and I think I see a race condition.

 module "nat" {
   source          = "github.com/GoogleCloudPlatform/terraform-google-nat-gateway"
   region          = "${var.region}"
   zone            = "${var.zone}"
   tags            = ["${var.gke_node_tag}"]
-  network         = "${var.network}"
-  subnetwork      = "${var.subnetwork}"
+  network         = "${google_compute_network.network.self_link}"
+  subnetwork      = "${google_compute_subnetwork.subnetwork.self_link}"
   dest_range      = "${var.dest_range}"
   ip_address_name = "${var.ip_address_name}"
   name            = "${var.name}"
  1. First I tried with network = "${var.network}" and same for subnetwork, but this fails with:
* module.nat.google_compute_firewall.nat-gateway: 1 error(s) occurred:

* google_compute_firewall.nat-gateway: Error creating Firewall: googleapi: Error 404: The resource 'projects/<hidden>-edge/global/networks/network-v2' was not found, notFound
* module.nat.module.nat-gateway.google_compute_instance_template.default: 1 error(s) occurred:

* google_compute_instance_template.default: Error creating instance template: googleapi: Error 404: The resource 'projects/<hidden>-edge/regions/europe-west1/subnetworks/subnetwork-v2-a' was not found, notFound
* module.nat.module.nat-gateway.google_compute_firewall.default-ssh: 1 error(s) occurred:

* google_compute_firewall.default-ssh: Error creating Firewall: googleapi: Error 404: The resource 'projects/<hidden>-edge/global/networks/network-v2' was not found, notFound

I presume that is because some nat.module resources want to be created before the network and subnetwork are fully created (using the name does not create a terraform dependency on the existance of the (sub)network ?).

  1. Then I tried to use the self_link to force this dependency on the existence of the (sub)network, before starting to create the nat resources. This worked better, but failed on this error where a value with dns compatible regex is required (and not a self_link).
1 error(s) occurred:

* module.nat.data.google_compute_network.network: data.google_compute_network.network: Error reading Network Not Found : https://www.googleapis.com/compute/v1/projects/<hidden>-edge/global/networks/network-v2: googleapi: Error 400: Invalid value 'https://www.googleapis.com/compute/v1/projects/<hidden>-edge/global/networks/network-v2'. Values must match the following regular expression: '[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?', invalidParameter

I presume I can fix this with forcing hard dependencies on the pre-existence of the network and subnetwork in some other way?

Is there a proper fix for this case ? Thanks :-)

petervandenabeele commented 6 years ago

OK, so this work-around does the trick. Maybe this issue is irrelevant then, or should we look for a cleaner solution when the network and/or subnetwork are created in the same terraform apply run as the nat gateway that depends on them?

The reason I am doing this is to have our edge GKE cluster and the egress NAT to our legacy servers (with fixed IP) re-created in full, whenever we want and e.g. every morning.

 module "nat" {
   source          = "github.com/GoogleCloudPlatform/terraform-google-nat-gateway"
   region          = "${var.region}"
   zone            = "${var.zone}"
   tags            = ["${var.gke_node_tag}"]
-  network         = "${var.network}"
-  subnetwork      = "${var.subnetwork}"
+  // dependencies on self_link as a work-around for https://github.com/GoogleCloudPlatform/terraform-google-nat-gateway/issues/90
+  network         = "${true ? var.network : google_compute_network.network.self_link}"
+  subnetwork      = "${true ? var.subnetwork : google_compute_subnetwork.subnetwork.self_link}"
   dest_range      = "${var.dest_range}"
   ip_address_name = "${var.ip_address_name}"
   name            = "${var.name}"
sabrehagen commented 5 years ago

I'm encountering the same issue and have posted my logs here for reference: https://gist.github.com/sabrehagen/74a964e17834c5c87a27125a4069be33

petervandenabeele commented 5 years ago

I commented on your gist with a proposed test to validate the presumption that this is the cause.

sabrehagen commented 5 years ago

I tried your fix and can confirm it works. I believe the dependency tree was lost when referencing "${local.environment_name}" rather than "${google_compute_network.ci-host.self_link}". Thank you for your assistance.

petervandenabeele commented 5 years ago

Great :-)

Yes, one should be able to just point to a self_link (instead of a name with regex '[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?') to keep a clean reference of that dependency when specifying the network of a google_compute_instance.