Invalid for_each argument on initial deployment caused by `module.uptime_monitoring` & `local.monitor_hosts`
What is the problem?
When deploying this module for the first time, and with disable_monitoring
set to false
(its default), this module fails with the following error.
╷
│ Error: Invalid for_each argument
│
│ on /terraform_data/modules/webapp/main.tf line 236, in module "uptime_monitoring":
│ 236: for_each = local.monitor_hosts
│ ├────────────────
│ │ local.monitor_hosts will be known only after apply
│
│ The "for_each" map includes keys derived from resource attributes that cannot be determined until apply, and so Terraform cannot determine the full set of keys that will identify the instances of this
│ resource.
│
│ When working with unknown values in for_each, it's better to define the map keys statically in your configuration and place apply-time results only in the map values.
│
│ Alternatively, you could use the -target planning option to first apply only the resources that the for_each value depends on, and then apply a second time to fully converge.
Potential cause
This is because the monitor_hosts
local references the google_cloud_run_service.webapp
resource which is also being created by this module but cannot exist until after the first run. The monitor_hosts
local is defined as follows.
# Map containing the hosts to monitor and whether an auth proxy and egress connector
# should be configured.
monitor_hosts = var.disable_monitoring ? {} : merge(
{
trimsuffix(trimprefix(google_cloud_run_service.webapp.status[0].url, "https://"), "/") = {
"enable_auth_proxy" = !var.allow_unauthenticated_invocations || local.webapp_allowed_ingress != "all",
"enable_egress_connector" = local.webapp_allowed_ingress != "all"
},
},
local.can_monitor_custom_dns ? {
for dns_name in local.dns_names :
(dns_name) => {
"enable_auth_proxy" = local.webapp_allowed_ingress == "internal",
"enable_egress_connector" = local.webapp_allowed_ingress == "internal"
}
} : {}
)
Workarounds
There are two workarounds available.
- Set the
disable_monitoring
argument totrue
for the first run of the module and then run a second apply withdisable_monitoring
set tofalse
again. - Run a targeted apply of the
google_cloud_run_service.webapp
resource first and then a full apply as a second task.
Both of these options are not ideal and require multiple apply operations.
Actions
Need to investigate options to remove the dependency on the google_cloud_run_service.webapp
resource in the monitor_hosts
local.
This issue ties in with a couple of other open issues for this repo (#26 (closed) & #7 (closed)). Ideally we refactor all of these at the same time and ensure that the module can be deployed with a single apply
operation, regardless of which arguments are provided etc.