TL;DR
Release v12.3.0 (#442) introduced a breaking change and an anti-pattern that doesn't follow current best practices for keying resources using for_each. The new change creates the same issues that count did, where the resource names are tied to the order of the input set, causing recreation on changes to the set contents or order.
This causes all existing permissions to need to be recreated on upgrade as well.
Expected behavior
Minor versions not introduce breaking changes, especially without documentation.
Observed behavior
# module.bucket.google_storage_bucket_iam_member.members["0"] will be created
+ resource "google_storage_bucket_iam_member" "members" {
+ bucket = "bucket-aaaaaaaa-0000-bbbb-1111-cccccccccccc"
+ etag = (known after apply)
+ id = (known after apply)
+ member = "serviceAccount:sa@project.iam.gserviceaccount.com"
+ role = "roles/storage.objectViewer"
}
# module.bucket.google_storage_bucket_iam_member.members["1"] will be created
+ resource "google_storage_bucket_iam_member" "members" {
+ bucket = "bucket-aaaaaaaa-0000-bbbb-1111-cccccccccccc"
+ etag = (known after apply)
+ id = (known after apply)
+ member = "serviceAccount:sa@project.iam.gserviceaccount.com"
+ role = "roles/storage.objectAdmin"
}
# module.bucket.google_storage_bucket_iam_member.members["2"] will be created
+ resource "google_storage_bucket_iam_member" "members" {
+ bucket = "bucket-aaaaaaaa-0000-bbbb-1111-cccccccccccc"
+ etag = (known after apply)
+ id = (known after apply)
+ member = "group:group1@example.com"
+ role = "roles/storage.objectAdmin"
}
# module.bucket.google_storage_bucket_iam_member.members["3"] will be created
+ resource "google_storage_bucket_iam_member" "members" {
+ bucket = "bucket-aaaaaaaa-0000-bbbb-1111-cccccccccccc"
+ etag = (known after apply)
+ id = (known after apply)
+ member = "group:group0@example.com"
+ role = "roles/storage.objectAdmin"
}
# module.bucket.google_storage_bucket_iam_member.members["roles/storage.objectAdmin group:group0@example.com"] will be destroyed
# (because key ["roles/storage.objectAdmin group:group0@example.com"] is not in for_each map)
- resource "google_storage_bucket_iam_member" "members" {
- bucket = "b/bucket-aaaaaaaa-0000-bbbb-1111-cccccccccccc" -> null
- etag = "CAg=" -> null
- id = "b/bucket-aaaaaaaa-0000-bbbb-1111-cccccccccccc/roles/storage.objectAdmin/group:group0@example.com" -> null
- member = "group:group0@example.com" -> null
- role = "roles/storage.objectAdmin" -> null
}
# module.bucket.google_storage_bucket_iam_member.members["roles/storage.objectAdmin group:group1@example.com"] will be destroyed
# (because key ["roles/storage.objectAdmin group:group1@example.com"] is not in for_each map)
- resource "google_storage_bucket_iam_member" "members" {
- bucket = "b/bucket-aaaaaaaa-0000-bbbb-1111-cccccccccccc" -> null
- etag = "CAg=" -> null
- id = "b/bucket-aaaaaaaa-0000-bbbb-1111-cccccccccccc/roles/storage.objectAdmin/group:group1@example.com" -> null
- member = "group:group1@example.com" -> null
- role = "roles/storage.objectAdmin" -> null
}
# module.bucket.google_storage_bucket_iam_member.members["roles/storage.objectAdmin serviceAccount:sa@project.iam.gserviceaccount.com"] will be destroyed
# (because key ["roles/storage.objectAdmin serviceAccount:sa@project.iam.gserviceaccount.com"] is not in for_each map)
- resource "google_storage_bucket_iam_member" "members" {
- bucket = "b/bucket-aaaaaaaa-0000-bbbb-1111-cccccccccccc" -> null
- etag = "CAg=" -> null
- id = "b/bucket-aaaaaaaa-0000-bbbb-1111-cccccccccccc/roles/storage.objectAdmin/serviceAccount:sa@project.iam.gserviceaccount.com" -> null
- member = "serviceAccount:sa@project.iam.gserviceaccount.com" -> null
- role = "roles/storage.objectAdmin" -> null
}
# module.bucket.google_storage_bucket_iam_member.members["roles/storage.objectViewer serviceAccount:sa@project.iam.gserviceaccount.com"] will be destroyed
# (because key ["roles/storage.objectViewer serviceAccount:sa@project.iam.gserviceaccount.com"] is not in for_each map)
- resource "google_storage_bucket_iam_member" "members" {
- bucket = "b/bucket-aaaaaaaa-0000-bbbb-1111-cccccccccccc" -> null
- etag = "CAg=" -> null
- id = "b/bucket-aaaaaaaa-0000-bbbb-1111-cccccccccccc/roles/storage.objectViewer/serviceAccount:sa@project.iam.gserviceaccount.com" -> null
- member = "serviceAccount:sa@project.iam.gserviceaccount.com" -> null
- role = "roles/storage.objectViewer" -> null
}
Terraform Configuration
resource "random_uuid" "bucket" {
keepers = {
env = local.env
}
}
module "bucket" {
source = "terraform-google-modules/cloud-storage/google//modules/simple_bucket"
version = "~> 12.0.0"
name = "bucket-${random_uuid.bucket.result}"
project_id = var.gcp_project_id
location = "us-east1"
bucket_policy_only = true
public_access_prevention = "enforced"
versioning = false
autoclass = true
iam_members = [
{
role = "roles/storage.objectViewer"
member = "serviceAccount:sa@project.iam.gserviceaccount.com"
},
{
role = "roles/storage.objectAdmin"
member = "serviceAccount:sa@project.iam.gserviceaccount.com"
},
{
role = "roles/storage.objectAdmin"
member = "group:group0@example.com"
},
{
role = "roles/storage.objectAdmin"
member = "group:group1@example.com"
},
]
}
Terraform Version
$ terraform version
Terraform v1.14.8
on darwin_arm64
Terraform Provider Versions
$ terraform providers
Providers required by configuration:
.
├── provider[registry.terraform.io/hashicorp/google] ~> 7.30
├── provider[registry.terraform.io/hashicorp/random] ~> 3.6
├── provider[terraform.io/builtin/terraform]
└── module.bucket
├── provider[registry.terraform.io/hashicorp/google] >= 6.37.0, < 8.0.0
└── module.encryption_key
└── provider[registry.terraform.io/hashicorp/google] >= 5.31.0, < 8.0.0
Providers required by state:
provider[registry.terraform.io/hashicorp/random]
provider[terraform.io/builtin/terraform]
provider[registry.terraform.io/hashicorp/google]
Additional information
No response
TL;DR
Release v12.3.0 (#442) introduced a breaking change and an anti-pattern that doesn't follow current best practices for keying resources using
for_each. The new change creates the same issues thatcountdid, where the resource names are tied to the order of the input set, causing recreation on changes to the set contents or order.This causes all existing permissions to need to be recreated on upgrade as well.
Expected behavior
Minor versions not introduce breaking changes, especially without documentation.
Observed behavior
Terraform Configuration
Terraform Version
Terraform Provider Versions
Additional information
No response