Terraform: Official documentation example for terraform v0.13 module for_each with regions is invalid

Created on 3 Sep 2020  路  7Comments  路  Source: hashicorp/terraform

Terraform Version

Terraform v0.13.2

Terraform Configuration Files

variable "project_id" {
  type = string
}

variable "regions" {
  type = map(object({
    region            = string
    network           = string
    subnetwork        = string
    ip_range_pods     = string
    ip_range_services = string
  }))
}

module "kubernetes_cluster" {
  source   = "terraform-google-modules/kubernetes-engine/google"
  for_each = var.regions

  project_id        = var.project_id
  name              = each.key
  region            = each.value.region
  network           = each.value.network
  subnetwork        = each.value.subnetwork
  ip_range_pods     = each.value.ip_range_pods
  ip_range_services = each.value.ip_range_services
}

Expected Behavior

Given the above code is copied verbatim from the official Terraform v0.13 release announcement page I would have expected running a simple terraform init or terraform validate (along with plan, apply, etc.) would work fine.

Actual Behavior

Terraform fails to initialize, validate, plan, apply, etc. without encountering this error:

Error: Module does not support for_each

  on main.tf line 17, in module "kubernetes_cluster":
  17:   for_each = var.regions

Module "kubernetes_cluster" cannot be used with for_each because it contains a
nested provider configuration for "kubernetes", at
.terraform/modules/kubernetes_cluster/auth.tf:29,10-22.

This module can be made compatible with for_each by changing it to receive all
of its provider configurations from the calling module, by using the
"providers" argument in the calling module block.

Steps to Reproduce

  1. terraform init

Additional Context

I would assume this issue was some sort of bug in Terraform given the fact that this example is from the official release page, but based on the following issues/notes, I think this is a "by design" behavior...
https://github.com/hashicorp/terraform/issues/25120#issuecomment-638496075
https://github.com/hashicorp/terraform/tree/guide-v0.13-beta/module-repetition#associating-provider-configurations-with-modules.

Enabling for_each on providers would solve this issue by using the same for_each definition on the provider block as the module block and the providers = meta-parameter in the module block to map them.

References

  • #25120
  • #24476
bug documentation

Most helpful comment

@ryno75 Seconding @apparentlymart's thanks. The egg is on my face there and I absolutely should have double checked the code I was using.

I'll update immediately.

All 7 comments

Thanks for reporting this, @ryno75!

Indeed, it seems that it is the documentation that is incorrect, rather than Terraform's behavior. My guess is that this example was originally written with a different module and changed later in the editorial process without first checking if the listed module is actually for_each-compatible. Hopefully that module will _become_ for_each compatible in a later release, by accepting a Kubernetes provider configuration from outside rather than declaring one itself, but until then hopefully there is another module that can replace it to illustrate the general point, since the exact module used there is less important than showing the overall module for_each syntax.

The team that maintains the code in this repository isn't directly involved in publishing these articles, but I'll ask internally about who can help get that article updated to use a different example. Thanks again for reporting this!

@ryno75 Seconding @apparentlymart's thanks. The egg is on my face there and I absolutely should have double checked the code I was using.

I'll update immediately.

@ryno75 Seconding @apparentlymart's thanks. The egg is on my face there and I absolutely should have double checked the code I was using.

I'll update immediately.

Thanks!
I recall seeing it somewhere during the beta announcements too. Don't recall now exactly where though.

Thanks for reporting this, @ryno75!

Indeed, it seems that it is the documentation that is incorrect, rather than Terraform's behavior. My guess is that this example was originally written with a different module and changed later in the editorial process without first checking if the listed module is actually for_each-compatible. Hopefully that module will _become_ for_each compatible in a later release, by accepting a Kubernetes provider configuration from outside rather than declaring one itself, but until then hopefully there is another module that can replace it to illustrate the general point, since the exact module used there is less important than showing the overall module for_each syntax.

The team that maintains the code in this repository isn't directly involved in publishing these articles, but I'll ask internally about who can help get that article updated to use a different example. Thanks again for reporting this!

Thanks @apparentlymart! I agree that the examples are mainly for demonstrating syntax and possible use cases. What was specifically problematic about this one is that it uses the multi-region use case (which is one I've been clamoring over for quite a while). Since the region is really an API client specific value... a 1-to-1 mapping of number of regions to number of providers is very much the most common use-case. Case in point... If I were to use a for_each in a module to deploy a particular AWS Config or Insights service configuration across a number of regions, I would need a declared provider for each region. I think the hope of course was to let the sub-module in that scenario manage the provider but I understand the reasons why that is not allowed. Anyway... the example as is (without doing some digging) led me to believe that a nested provider was indeed supported with for_each.

Is there any issue to track or roadmap for adding for_each to providers definitions?

@ryno75 https://github.com/hashicorp/terraform/issues/19932 might be what you're looking for 馃憤

@ryno75 #19932 might be what you're looking for 馃憤

Ah! very much so. Thanks @bflad !

Hi @pkolyvas @apparentlymart
I help maintain the terraform-google-modules/kubernetes-engine/google and we were discussing how to make this compatible for for_each https://github.com/terraform-google-modules/terraform-google-kubernetes-engine/issues/673 . IIUC the only way would be remove the nested provider config?

Was this page helpful?
0 / 5 - 0 ratings