Thanks for sharing this tip, @bernardmaltais!
The key insight here is that variables are nodes in the dependency graph too, and so you can use them as a “hub” for passing dependencies across the module boundary.
If using Terraform 0.12, this pattern is more straightforward because depends_on
can refer directly to variables in Terraform 0.12 and later:
variable "vm_depends_on" {
type = any
default = null
}
resource "azure_virtual_machine" "example" {
depends_on = [var.vm_depends_on]
# ...
}
Since this variable is being used only for its dependencies and not for its value, I defined it as having type any
to get the most flexibility. The caller of this module can then use vm_depends_on
in the same way as the first-class depends_on
meta-argument:
module "example" {
source = "..."
vm_depends_on = [module.fw_core01.firewall]
}
One nice side-benefit of this approach is that you can potentially offer multiple different depends_on
-like variables so that different parts of the module can have different dependencies. Keeping the dependencies tightly scoped will improve the performance of terraform apply
because it will allow more actions to potentially run concurrently, but of course that comes at the expense of some usability for the caller of having to think about the dependencies of different parts of the module separately.