Terraform v0.13.2
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
}
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.
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.
terraform initI 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.
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_eachcompatible 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 modulefor_eachsyntax.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?
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.