terraform, foreach and a module - wait after action on one of element from the list

263 Views Asked by At

Terraform is not waiting for the full module creation within foreach. Instead of finishing entire module creation in one iteration it is creating first resource from the module for every list element, then iterates over the list and creates second module, and so on.

Also I use parallelism=1 option when running the apply: terraform apply -parallelism=1

#templates/iam.tf
variable "project_id2" {}
variable "project_id" {}
variable "user" {}
variable "role" {}

resource "google_project_iam_member" "first_me" {
  project = var.project_id2
  role    = var.role
  member  = "user:${var.user}"
}

resource "google_project_iam_member" "then_me" {
  project = var.project_id
  role    = var.role
  member  = "user:${var.user}"
  depends_on = [
    google_project_iam_member.first_me
  ]
}

resource "time_sleep" "wait_seconds" {
  create_duration = "11s"

  depends_on = [google_project_iam_member.then_me]
}

resource "null_resource" "sleep_after_project_import" {
  depends_on = [
    time_sleep.wait_seconds,
    google_project_iam_member.then_me
  ]
}

# ---

# ./main.tf 
locals {
  roles_for_bindings = [
    "roles/accessapproval.invalidator",
    "roles/actions.Viewer",
    "roles/serviceconsumermanagement.tenancyUnitsAdmin",
  ]
}

module "role_binding_sleep_test" {
  source     = "./templates/iam"
  for_each   = toset(local.test)
  project_id = "some_project_id"
  project_id2 = "some_project_id2"
  role       = each.key
  user       = "[email protected]"
}

Logs

module.role_binding_sleep_test["roles/accessapproval.invalidator"].google_project_iam_member.first_me: Creation complete after 9s [id=some_project_id2/roles/accessapproval.invalidator/user:[email protected]]
module.role_binding_sleep_test["roles/actions.Viewer"].google_project_iam_member.first_me: Creating...
module.role_binding_sleep_test["roles/actions.Viewer"].google_project_iam_member.first_me: Creation complete after 9s [id=some_project_id2/roles/actions.Viewer/user:[email protected]]
module.role_binding_sleep_test["roles/serviceconsumermanagement.tenancyUnitsAdmin"].google_project_iam_member.first_me: Creating...
module.role_binding_sleep_test["roles/serviceconsumermanagement.tenancyUnitsAdmin"].google_project_iam_member.first_me: Creation complete after 9s [id=some_project_id2/roles/serviceconsumermanagement.tenancyUnitsAdmin/user:[email protected]]
module.role_binding_sleep_test["roles/accessapproval.invalidator"].google_project_iam_member.then_me: Creating...
module.role_binding_sleep_test["roles/accessapproval.invalidator"].google_project_iam_member.then_me: Creation complete after 9s [id=some_project_id1/roles/accessapproval.invalidator/user:[email protected]]
module.role_binding_sleep_test["roles/actions.Viewer"].google_project_iam_member.then_me: Creating...
module.role_binding_sleep_test["roles/actions.Viewer"].google_project_iam_member.then_me: Creation complete after 9s [id=some_project_id1/roles/actions.Viewer/user:[email protected]]
module.role_binding_sleep_test["roles/serviceconsumermanagement.tenancyUnitsAdmin"].google_project_iam_member.then_me: Creating...
module.role_binding_sleep_test["roles/serviceconsumermanagement.tenancyUnitsAdmin"].google_project_iam_member.then_me: Creation complete after 10s [id=some_project_id1/roles/serviceconsumermanagement.tenancyUnitsAdmin/user:[email protected]]
module.role_binding_sleep_test["roles/accessapproval.invalidator"].time_sleep.wait_seconds: Creating...
module.role_binding_sleep_test["roles/accessapproval.invalidator"].time_sleep.wait_seconds: Still creating... [10s elapsed]
module.role_binding_sleep_test["roles/accessapproval.invalidator"].time_sleep.wait_seconds: Creation complete after 11s [id=2023-12-04T13:22:47Z]
module.role_binding_sleep_test["roles/actions.Viewer"].time_sleep.wait_seconds: Creating...
module.role_binding_sleep_test["roles/actions.Viewer"].time_sleep.wait_seconds: Still creating... [10s elapsed]
module.role_binding_sleep_test["roles/actions.Viewer"].time_sleep.wait_seconds: Creation complete after 11s [id=2023-12-04T13:22:59Z]
module.role_binding_sleep_test["roles/serviceconsumermanagement.tenancyUnitsAdmin"].time_sleep.wait_seconds: Creating...
module.role_binding_sleep_test["roles/serviceconsumermanagement.tenancyUnitsAdmin"].time_sleep.wait_seconds: Still creating... [10s elapsed]
module.role_binding_sleep_test["roles/serviceconsumermanagement.tenancyUnitsAdmin"].time_sleep.wait_seconds: Creation complete after 11s [id=2023-12-04T13:23:10Z]
module.role_binding_sleep_test["roles/actions.Viewer"].null_resource.sleep_after_project_import: Creating...
module.role_binding_sleep_test["roles/actions.Viewer"].null_resource.sleep_after_project_import: Creation complete after 0s [id=111111]
module.role_binding_sleep_test["roles/accessapproval.invalidator"].null_resource.sleep_after_project_import: Creating...
module.role_binding_sleep_test["roles/accessapproval.invalidator"].null_resource.sleep_after_project_import: Creation complete after 0s [id=111112]
module.role_binding_sleep_test["roles/serviceconsumermanagement.tenancyUnitsAdmin"].null_resource.sleep_after_project_import: Creating...
module.role_binding_sleep_test["roles/serviceconsumermanagement.tenancyUnitsAdmin"].null_resource.sleep_after_project_import: Creation complete after 0s [id=111113]

Logs I was expecting:

module.role_binding_sleep_test["roles/accessapproval.invalidator"].google_project_iam_member.first_me: Creating...
module.role_binding_sleep_test["roles/accessapproval.invalidator"].google_project_iam_member.first_me: Creation complete after 9s [id=some_project_id2/roles/accessapproval.invalidator/user:[email protected]]
module.role_binding_sleep_test["roles/accessapproval.invalidator"].google_project_iam_member.then_me: Creating...
module.role_binding_sleep_test["roles/accessapproval.invalidator"].google_project_iam_member.then_me: Creation complete after 9s [id=some_project_id1/roles/accessapproval.invalidator/user:[email protected]]
module.role_binding_sleep_test["roles/accessapproval.invalidator"].time_sleep.wait_seconds: Creating...
module.role_binding_sleep_test["roles/accessapproval.invalidator"].time_sleep.wait_seconds: Still creating... [10s elapsed]
module.role_binding_sleep_test["roles/accessapproval.invalidator"].time_sleep.wait_seconds: Creation complete after 11s [id=2023-12-04T13:22:47Z]
module.role_binding_sleep_test["roles/accessapproval.invalidator"].null_resource.sleep_after_project_import: Creating...
module.role_binding_sleep_test["roles/accessapproval.invalidator"].null_resource.sleep_after_project_import: Creation complete after 0s [id=111111]
# now 1st foreach iteration for role should end and next start
module.role_binding_sleep_test["roles/serviceconsumermanagement.tenancyUnitsAdmin"].google_project_iam_member.first_me: Creating...
module.role_binding_sleep_test["roles/serviceconsumermanagement.tenancyUnitsAdmin"].google_project_iam_member.first_me: Creation complete after 9s [id=some_project_id2/roles/serviceconsumermanagement.tenancyUnitsAdmin/user:[email protected]]
module.role_binding_sleep_test["roles/serviceconsumermanagement.tenancyUnitsAdmin"].google_project_iam_member.then_me: Creating...
module.role_binding_sleep_test["roles/serviceconsumermanagement.tenancyUnitsAdmin"].google_project_iam_member.then_me: Creation complete after 10s [id=some_project_id1/roles/serviceconsumermanagement.tenancyUnitsAdmin/user:[email protected]]
module.role_binding_sleep_test["roles/serviceconsumermanagement.tenancyUnitsAdmin"].time_sleep.wait_seconds: Creating...
module.role_binding_sleep_test["roles/serviceconsumermanagement.tenancyUnitsAdmin"].time_sleep.wait_seconds: Still creating... [10s elapsed]
module.role_binding_sleep_test["roles/serviceconsumermanagement.tenancyUnitsAdmin"].time_sleep.wait_seconds: Creation complete after 11s [id=2023-12-04T13:23:10Z]
module.role_binding_sleep_test["roles/serviceconsumermanagement.tenancyUnitsAdmin"].null_resource.sleep_after_project_import: Creating...
module.role_binding_sleep_test["roles/serviceconsumermanagement.tenancyUnitsAdmin"].null_resource.sleep_after_project_import: Creation complete after 0s [id=111112]
# now 2nd foreach iteration for role should end and next start
module.role_binding_sleep_test["roles/actions.Viewer"].google_project_iam_member.then_me: Creating...
module.role_binding_sleep_test["roles/actions.Viewer"].google_project_iam_member.then_me: Creation complete after 9s [id=some_project_id1/roles/actions.Viewer/user:[email protected]]
module.role_binding_sleep_test["roles/actions.Viewer"].time_sleep.wait_seconds: Creating...
module.role_binding_sleep_test["roles/actions.Viewer"].time_sleep.wait_seconds: Still creating... [10s elapsed]
module.role_binding_sleep_test["roles/actions.Viewer"].time_sleep.wait_seconds: Creation complete after 11s [id=2023-12-04T13:22:59Z]
module.role_binding_sleep_test["roles/actions.Viewer"].null_resource.sleep_after_project_import: Creating...
module.role_binding_sleep_test["roles/actions.Viewer"].null_resource.sleep_after_project_import: Creation complete after 0s [id=111113]
1

There are 1 best solutions below

3
Martin Atkins On

When you use count or for_each in Terraform, the meaning is to declare zero or more independent instances of the same module or resource. Terraform therefore assumes it can perform operations on those independent instances concurrently, or in any sequential order.

If your instances are not actually independent of one another -- that is, if any one of them must be acted on before another for the result to be correct -- then for_each is not a suitable tool to use. Instead, you'll need to declare multiple module blocks and explain the relationships between them by having the arguments in one block refer to the output values from the other.

Dependencies in Terraform are between configuration blocks, not the multiple instances that they can potentially declare. Any time you need to describe a dependency between two objects, they will need to be declared as two separate configuration blocks.