GoogleCloudPlatform / terraform-google-managed-instance-group

Modular Google Compute Engine managed instance group for Terraform.
Apache License 2.0
63 stars 139 forks source link

`project` parameter forcing `google_compute_instance_template.default` recreation #12

Closed hawksight closed 6 years ago

hawksight commented 6 years ago

Issue

I have been using the module via the nat module with the configuration as such:

module "nat" {
  source     = "git@github.com:GoogleCloudPlatform/terraform-google-nat-gateway.git?ref=1.1.8"

  project         = "${module.project.PROJECT_ID}"
  region          = "${var.G_REGION}"
  zone            = "${module.cluster.K8S_ZONE}"
  tags            = ["${module.cluster.K8S_TAG}"]
  network         = "${module.network.VPC_NAME}"
  subnetwork      = "${module.network.SUB_NAME[0]}"
  ip_address_name = "${google_compute_address.nat-ip.name}"
}

Calling the module specifically with project being an output from a prior module, forces the module.nat.module.nat-gateway.google_compute_instance_template.default to be recreated.

Specifically the following two fields in terraform plan:

-/+ module.nat.module.nat-gateway.google_compute_instance_template.default (new resource required)
id:                                     "default-20180529094950180000000001" => <computed> (forces new resource)
network_interface.0.access_config.#:    "1" => <computed> (forces new resource)

After investigating between two almost identical configurations, I have found the solution to be passing the project explicitly from a variable set in my inputs.tfvars:

module "nat" {
  source     = "git@github.com:GoogleCloudPlatform/terraform-google-nat-gateway.git?ref=1.1.8"

  project         = "${var.G_PROJECT}"
  region          = "${var.G_REGION}"
  zone            = "${module.cluster.K8S_ZONE}"
  tags            = ["${module.cluster.K8S_TAG}"]
  network         = "${module.network.VPC_NAME}"
  subnetwork      = "${module.network.SUB_NAME[0]}"
  ip_address_name = "${google_compute_address.nat-ip.name}"
}

I'm not entirely sure on the specifics of how terraform calculates the resource attributes, but the actual value of the project field is identical. One is calculated, one is fixed. I think its got something to do with this line here.

The ideal scenario would be for the resource not to be recreated when the project comes from another module's output. I use the project output as a sort of flow control through the infrastructure build. However I suspect in this situation that its just how terraform works perhaps.

Raised this issue incase anyone else sees this, and that there is a 'solution' of sorts that might help others.

hawksight commented 6 years ago

Actually I should also add that the same field impacts on module.nat.google_compute_route.nat-gateway but that is not specific to this module. More relevant here but mentioned as I think the issue is similar.

danisla commented 6 years ago

@hawksight is this still a problem? It might have been a provider issuer. I wasn't able to reproduce it with the latest provider.

$ terraform version
Terraform v0.11.7
+ provider.google v1.16.2
hawksight commented 6 years ago

I have just checked over and one of my configs and found that I seen the issue in one configuration but I think I can see why (hence some details of how I figured it out).

❯ terraform --version

Terraform v0.11.8
+ provider.google v1.16.2
+ provider.null v1.0.0
+ provider.random v1.3.1
+ provider.template v1.0.0

I did not see the issue with the following NAT config:

module "nat" {
  source     = "git@github.com:GoogleCloudPlatform/terraform-google-nat-gateway.git?ref=1.1.9"

  project         = "${var.G_PROJECT}"
  region          = "${var.G_REGION}"
  zone            = "${module.cluster.K8S_ZONE}"
  tags            = ["${module.cluster.K8S_TAG}"]
  network         = "${module.network.VPC_NAME}"
  subnetwork      = "${module.network.SUB_NAME[0]}"
  ip_address_name = "${google_compute_address.nat-ip.name}"
}

I did see the issue in this NAT config, when I changes the project input to an output from another module:

module "nat" {
  source     = "git@github.com:GoogleCloudPlatform/terraform-google-nat-gateway.git?ref=1.1.9"

  project         = "${module.cluster.PROJECT}"
  region          = "${var.G_REGION}"
  zone            = "${module.cluster.K8S_ZONE}"
  tags            = ["${module.cluster.K8S_TAG}"]
  network         = "${module.network.VPC_NAME}"
  subnetwork      = "${module.network.SUB_NAME[0]}"
  ip_address_name = "${google_compute_address.nat-ip.name}"
}

The resulting output wanted to recreate:

And update in place:

However I did try then changing the project var to be: project = "${google_compute_address.nat-ip.project}"

I did not see the problem with that, so I have looked up where the output was coming from (my cluster module):

output "PROJECT" {
  value       = "${data.google_container_cluster.information.project}"
  description = "Project output used for execution flow control - pass in, pass out"
}

I think the issue was more that the parameter I was passing in was based on a data lookup resource. I guess because terraform could not compute that value during the plan stage, it made the assumption that the value would change, hence came up with the result or recreating a couple resources.

When the value was from a known state or hard-coded value, then terraform could plan correctly.

Apologies, this is a configuration issue on my side so happy to close this issue.