The problem of “shifting all items” in a Terraform array

Photo by Paweł Czerwiński on Unsplash
locals {
roles = [
"roles/viewer",
"roles/storage.admin",
"roles/compute.admin",
"roles/cloudsql.admin"
]
}
resource "google_project_iam_member" "group_access" {
count = length(local.roles)
role = local.roles[count.index]
member = "group:devs@example.com"
}
# google_project_iam_member.group_access[0] will be created
+ resource "google_project_iam_member" "group_access" {
+ etag = (known after apply)
+ id = (known after apply)
+ member = "group:devs@example.com"
+ project = (known after apply)
+ role = "roles/viewer"
}
# google_project_iam_member.group_access[1] will be created
+ resource "google_project_iam_member" "group_access" {
+ etag = (known after apply)
+ id = (known after apply)
+ member = "group:devs@example.com"
+ project = (known after apply)
+ role = "roles/storage.admin"
}
# google_project_iam_member.group_access[2] will be created
+ resource "google_project_iam_member" "group_access" {
+ etag = (known after apply)
+ id = (known after apply)
+ member = "group:devs@example.com"
+ project = (known after apply)
+ role = "roles/compute.admin"
}
# google_project_iam_member.group_access[3] will be created
+ resource "google_project_iam_member" "group_access" {
+ etag = (known after apply)
+ id = (known after apply)
+ member = "group:devs@example.com"
+ project = (known after apply)
+ role = "roles/cloudsql.admin"
}

Adding a new item into the array

locals {
roles = [
"roles/viewer",
"roles/pubsub.admin", # <-- this role is being newly added
"roles/storage.admin",
"roles/compute.admin",
"roles/cloudsql.admin"
]
}
# google_project_iam_member.group_access[1] must be replaced
-/+ resource "google_project_iam_member" "group_access" {
~ etag = "BwWza97zq7A=" -> (known after apply)
~ id = "my-gcp-project/roles/cloudsql.admin/group:devs@example.com" -> (known after apply)
member = "group:devs@example.com"
~ project = "my-gcp-project" -> (known after apply)
~ role = "roles/storage.admin" -> "roles/pubsub.admin" # forces replacement
}
# google_project_iam_member.group_access[2] must be replaced
-/+ resource "google_project_iam_member" "group_access" {
~ etag = "BwWza97zq7A=" -> (known after apply)
~ id = "my-gcp-project/roles/cloudsql.admin/group:devs@example.com" -> (known after apply)
member = "group:devs@example.com"
~ project = "my-gcp-project" -> (known after apply)
~ role = "roles/compute.admin" -> "roles/storage.admin" # forces replacement
}
# google_project_iam_member.group_access[3] must be replaced
-/+ resource "google_project_iam_member" "group_access" {
~ etag = "BwWza97zq7A=" -> (known after apply)
~ id = "my-gcp-project/roles/cloudsql.admin/group:devs@example.com" -> (known after apply)
member = "group:devs@example.com"
~ project = "my-gcp-project" -> (known after apply)
~ role = "roles/cloudsql.admin" -> "roles/compute.admin" # forces replacement
}
# google_project_iam_member.group_access[4] will be created
+ resource "google_project_iam_member" "group_access" {
+ etag = (known after apply)
+ id = (known after apply)
+ member = "group:devs@example.com"
+ project = (known after apply)
+ role = "roles/cloudsql.admin"
}

What’s going on here?

It is shifting all items in the array

How can we improve this?

locals {
roles = [
"roles/viewer",
"roles/storage.admin",
"roles/compute.admin",
"roles/cloudsql.admin"
]
}
resource "google_project_iam_member" "group_access" {
for_each = toset(local.roles) # P.S. for_each can act on sets or hashmaps only
role = each.value
member = "group:devs@example.com"
}
# google_project_iam_member.group_access["roles/viewer"] will be created
+ resource "google_project_iam_member" "group_access" {
+ etag = (known after apply)
+ id = (known after apply)
+ member = "group:devs@example.com"
+ project = (known after apply)
+ role = "roles/viewer"
}
# google_project_iam_member.group_access["roles/storage.admin"] will be created
+ resource "google_project_iam_member" "group_access" {
+ etag = (known after apply)
+ id = (known after apply)
+ member = "group:devs@example.com"
+ project = (known after apply)
+ role = "roles/storage.admin"
}
# google_project_iam_member.group_access["roles/compute.admin"] will be created
+ resource "google_project_iam_member" "group_access" {
+ etag = (known after apply)
+ id = (known after apply)
+ member = "group:devs@example.com"
+ project = (known after apply)
+ role = "roles/compute.admin"
}
# google_project_iam_member.group_access["roles/cloudsql.admin"] will be created
+ resource "google_project_iam_member" "group_access" {
+ etag = (known after apply)
+ id = (known after apply)
+ member = "group:devs@example.com"
+ project = (known after apply)
+ role = "roles/cloudsql.admin"
}

Now, adding a new item in the array

locals {
roles = [
"roles/viewer",
"roles/pubsub.admin", # <-- this role is being newly added
"roles/storage.admin",
"roles/compute.admin",
"roles/cloudsql.admin"
]
}
# google_project_iam_member.group_access["roles/pubsub.admin"] will be created
+ resource "google_project_iam_member" "group_access" {
+ etag = (known after apply)
+ id = (known after apply)
+ member = "group:devs@example.com"
+ project = (known after apply)
+ role = "roles/pubsub.admin"
}

Conclusion

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Syed Rakib Al Hasan

DevOps Engineer, Backend Developer, Cloud Architect, Night time drive-outs & nice hangouts