Closed floflock closed 3 months ago
what was the fix here?
Unfortunately, I have to reopen the issue. This error appears again on following version:
➜ cloud git:(feature/BB-864-production-infrastructure) ✗ terraform version
Terraform v1.0.4
on darwin_amd64
+ provider registry.terraform.io/hashicorp/external v2.1.0
+ provider registry.terraform.io/hashicorp/google v3.78.0
+ provider registry.terraform.io/hashicorp/google-beta v3.79.0
+ provider registry.terraform.io/hashicorp/kubernetes v2.4.1
+ provider registry.terraform.io/hashicorp/null v3.1.0
+ provider registry.terraform.io/hashicorp/random v3.1.0
+ provider registry.terraform.io/hashicorp/time v0.7.2
Just to summarize, this is the issue thrown in the console:
╷
│ Error: Invalid for_each argument
│
│ on .terraform/modules/gke_service_account/main.tf line 38, in resource "google_service_account" "service_accounts":
│ 38: for_each = local.names
│ ├────────────────
│ │ local.names is set of string with 2 elements
│
│ The "for_each" value depends on resource attributes that cannot be determined until apply, so Terraform cannot predict how many instances will be created. To work around this, use the -target argument to first apply only the resources that the for_each depends
│ on.
╵
The module source code is:
module "gke_service_account" {
source = "terraform-google-modules/service-accounts/google"
version = "~> 4.0"
project_id = var.project_prefix
description = "Service Account for Cluster ${var.cluster_name}-${var.environment} (managed by Terraform)"
prefix = "gke"
names = [
"${var.cluster_name}-${var.environment}-${random_id.gke_suffix.hex}"]
project_roles = [
"${var.project_prefix}=>roles/monitoring.viewer",
"${var.project_prefix}=>roles/monitoring.metricWriter",
"${var.project_prefix}=>roles/logging.logWriter",
"${var.project_prefix}=>roles/stackdriver.resourceMetadata.writer",
"${var.project_prefix}=>roles/artifactregistry.reader",
]
}
The module cannot handle creating a single service account since "name" list has only one element...? @jmymy were you able to fix that somehow?
@floflock The problem is not with the length of your list. It's that you are using random_id.gke_suffix.hex
in the names of the Service Accounts. Terraform does not allow you to use dynamically-computed values in the key of for_each
resources.
You could instead inject the random ID as a prefix using the existing prefix
variable. Alternatively, I'd be happy to review a PR adding a suffix variable as well.
As a workaround, you can also apply your random ID resource terraform apply -target=random_id.gke_suffix
separately before applying your full Terraform config.
@morgante, thanks for the quick response! Will give a try and will also try to fork in order to prepare the PR.
So I had a similar error and am looking for a way to workaround this limitation.
I am using the terraform-google-modules/project-factory/google
module to create a VPC and then create an additional service account at the same time.
module "project" {
source = "terraform-google-modules/project-factory/google"
version = "11.1.1"
name = lower(var.project_name)
random_project_id = true
org_id = var.org_id
folder_id = var.folder_id
billing_account = var.billing_account
activate_apis = concat(var.activate_apis, var.additional_apis)
default_service_account = "disable"
disable_services_on_destroy = false
}
module "terraform_cloud_sa" {
source = "terraform-google-modules/service-accounts/google"
version = "4.0.2"
project_id = module.project.project_id
prefix = "tfc"
names = ["generated-sa"]
project_roles = ["${module.project.project_id}=>roles/owner", "${module.project.project_id}=>roles/serviceusage.serviceUsageAdmin"]
generate_keys = true
}
I can confirm it is the random_project_id
var in the project module as it appends a 2-byte hex to the end of the project name to get the project_id.
I really like this naming/ID feature and would like to keep it. I am also trying to limit the number of things I have to rename every time I want a copy of these 2 blocks. For example, these 2 blocks are part of a standard "module" we use when spinning up new VPCs. Everything used to work fine, and now on version 1.0+ it seems we hit this issue.
I can manually make up a 4 digit ending for the project_id and provide that but seems pointless if I could just use a random_id
automatically.
Outside of basically using a template and generating a new block and committing that, is there any other way I could do this?
the apply -target=
is not feasible as we are using terraform cloud and only allow remote runs via git workflows
ultimately I would just like to instantiate both of those modules like so:
module "new_vpc" {
source = "../modules/vpc"
name = "new-vpc-name
}
I think there's a decent case to be made for us to refactor this module so you don't need to provide the project ID in project_roles
and therefore don't run into that issue.
I think there's a decent case to be made for us to refactor this module so you don't need to provide the project ID in project_roles
I think that would be super helpful
My example is:
provider "google" {
project = var.project_id
region = var.region
}
module "service_accounts" {
for_each = { for sa in var.service_accounts : sa.name => sa }
source = "terraform-google-modules/service-accounts/google"
version = "~> 4.0.3"
project_id = var.project_id
names = [each.key]
description = each.value.description
project_roles = each.value.roles
}
Where var.service_accounts looks like:
service_accounts = [
{ "name": "ci-deploy-user",
"description": "Service account with enough roles to perform deployment operation",
"roles": ["roles/pubsub.editor", "roles/run.invoker", "roles/storage.objectAdmin"]
},
{ "name": "monitoring-example",
"description": "Service account to do some fancy stuff",
"roles": ["roles/monitoring.viewer"]
}
]
My problem here is that I now need to somehow inject project_id mapping into each element of the roles list dynamically and my tiny brain cant compute that :)
This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 7 days
I happen to have the same issue, for the exact reason that I am using a random suffix for the project ID, as @morgante explained.
To make this refactor happen would be awesome. We currently have to use -target
for each run, which is not recommended by Terraform and is slow.
I think there's a decent case to be made for us to refactor this module so you don't need to provide the project ID in
project_roles
and therefore don't run into that issue.
We would be happy to accept a PR with that refactor.
just hit this issue 2 Apr 2022
We tried to setup a project with terraform and using random project_id so that we can recreate this at any given time. We also ran into this issue. From my point of view, this is a design error in this module. I really hope this could be refactored to not use "names" or "project_roles" in any for_each. "names" should also allow dynamic names like suffixes.
See also this stack overflow question / answer: https://stackoverflow.com/questions/70144554/how-to-solve-for-each-terraform-cannot-predict-how-many-instances-will-be-cre
Hit this issue today, as well.
Uggg.... 🤢 Hitting this issue today and banging my head as there is no good way my boss will approve my PR if I'm hardcoding the project id into the module.
If you want to create a single service account with the module, a error appears about a for_each:
The error output is:
I think it worked with v0.15.x but I am not sure.
My Terraform Version is now: