Terraform depends_on with modules

54,142

Solution 1

In most cases, the necessary dependencies just occur automatically as a result of your references. If the configuration for one resource refers directly or indirectly to another, Terraform automatically infers the dependency between them without the need for explicit depends_on.

This works because module variables and outputs are also nodes in the dependency graph: if a child module resource refers to var.foo then it indirectly depends on anything that the value of that variable depends on.

For the rare situation where automatic dependency detection is insufficient, you can still exploit the fact that module variables and outputs are nodes in the dependency graph to create indirect explicit dependencies, like this:

variable "storage_account_depends_on" {
  # the value doesn't matter; we're just using this variable
  # to propagate dependencies.
  type    = any
  default = []
}

resource "azurerm_storage_account" "test" {
  name                     = "diagnostics${azurerm_resource_group.management.name}"
  resource_group_name      = "${azurerm_resource_group.management.name}"
  location                 = "${azurerm_resource_group.management.location}"
  account_tier             = "Standard"
  account_replication_type = "LRS"

  tags = {
    environment = "diagnostics"
  }

  # This resource depends on whatever the variable
  # depends on, indirectly. This is the same
  # as using var.storage_account_depends_on in
  # an expression above, but for situations where
  # we don't actually need the value.
  depends_on = [var.storage_account_depends_on]
}

When you call this module, you can set storage_account_depends_on to any expression that includes the objects you want to ensure are created before the storage account:

module "diagnostic_logs" {
  source = "./modules/diagnostic_logs"
}

module "storage_account" {
  source = "./modules/storage_account"

  storage_account_depends_on = [module.diagnostic_logs.logging]
}

Then in your diagnostic_logs module you can configure indirect dependencies for the logging output to complete the dependency links between the modules:

output "logging" {
  # Again, the value is not important because we're just
  # using this for its dependencies.
  value = {}

  # Anything that refers to this output must wait until
  # the actions for azurerm_monitor_diagnostic_setting.example
  # to have completed first.
  depends_on = [azurerm_monitor_diagnostic_setting.example]
}

If your relationships can be expressed by passing actual values around, such as by having an output that includes the id, I'd recommend preferring that approach because it leads to a configuration that is easier to follow. But in rare situations where there are relationships between resources that cannot be modeled as data flow, you can use outputs and variables to propagate explicit dependencies between modules too.

Solution 2

module dependencies are now supported in Terraform 13, this is currently at the release candidate stage.

resource "aws_iam_policy_attachment" "example" {
  name       = "example"
  roles      = [aws_iam_role.example.name]
  policy_arn = aws_iam_policy.example.arn
}

module "uses-role" {
  # ...

  depends_on = [aws_iam_policy_attachment.example]
}
Share:
54,142

Related videos on Youtube

El so
Author by

El so

Updated on July 09, 2022

Comments

  • El so
    El so almost 2 years

    I'm new at terraform and I created a custom azure policies on module structure. each policy represents a custom module. One of the modules that I have created is enabling diagnostics logs for any new azure resource created. but, I need a storage account for that. (before enabling the diagnostics settings how can I implement "depends_on"? or any other methods? I want to create first the storage account and then the module of diagnostics settings. on the main.tf (where calling all the other modules) or inside the resource (module)?

    Thanks for the help!! :)

    this below code represents the main.tf file:

    //calling the create storage account name
    
    module "createstorageaccount" {
    
    source = "./modules/module_create_storage_account"
        depends_on = [
        "module_enable_diagnostics_logs"
      ]
    
    }
    

    this one represents the create storage account module

    resource "azurerm_resource_group" "management" {
    
    
      name     = "management-rg"
      location = "West Europe"
    }
    
    resource "azurerm_storage_account" "test" {
      name                     = "diagnostics${azurerm_resource_group.management.name}"
      resource_group_name      = "${azurerm_resource_group.management.name}"
      location                 = "${azurerm_resource_group.management.location}"
      account_tier             = "Standard"
      account_replication_type = "LRS"
    
      tags = {
        environment = "diagnostics"
      }
    }
    
        depends_on = [
        "module_enable_diagnostics_logs"
      ]
    
    
    • Alex
      Alex over 4 years
      As far as I know, the depends_on works with resources, not modules
    • mariux
      mariux about 4 years
      see medium.com/mineiros/… on how to implement a more generic module_depends_on ..
    • LoganMzz
      LoganMzz over 3 years
      Since 0.13 it's now possible to have depend_on on modules
  • El so
    El so over 4 years
    Thank you very much for the detailed answer!!
  • Nightt
    Nightt almost 4 years
    The above code will create the diagnostic_logs before storage_account. Please pay attention!
  • LoganMzz
    LoganMzz over 3 years
    Just note that using per resource dependancy is still prefered to have fine grained parallel resource handling instead of blocking entire module processing while not all your module resources depend on some external resources