0
votes

I am facing a dependency problem between terraform module and resource. My module is dependent on a resource but I have not been able to find out how to explicitly imply this in Terraform. At the moment the module code is ran before the resource it is dependent on is created, this is naturally resulting in an error.

I have looked across the internet and found few discussions around modules having dependencies on other modules including some suggestions on how to work around the lack of "depends_on" in modules. However I have not been able to find any suggestion/ workarounds for when modules have a dependency on resource.

I have tried suggestion made on following but to no avail

https://github.com/hashicorp/terraform/issues/16983

https://devops.stackexchange.com/questions/6163/how-to-make-terraform-modules-wait-for-resources-to-be-created-in-place-of-using

Below is the code for my module for standard azure nic and vm

     resource "azurerm_network_interface" "nic" {
      name                = "${var.nicName}"
      resource_group_name = "${var.rgName}"
      location            = "${var.rgLocation}"

      ip_configuration {
        name                          = "vm-nic-configuration"
        subnet_id                     = "${var.subnetId}"
        private_ip_address_allocation = "dynamic"
      }
    }


    resource "azurerm_virtual_machine" "vms" {
      name                  = "${var.vmHostName}"
      location              = "${var.rgLocation}"
      resource_group_name   = "${var.rgName}"
      network_interface_ids = ["${azurerm_network_interface.nic.id}"]

      vm_size                          = "${var.vmSize}"
      delete_os_disk_on_termination    = true
      delete_data_disks_on_termination = true

      storage_image_reference {
        publisher = "MicrosoftWindowsServer"
        offer     = "WindowsServer"
        sku       = "2016-Datacenter"
        version   = "latest"
      }

      storage_os_disk {
        name              = "${var.diskVol01Name}"
        caching           = "ReadWrite"
        create_option     = "FromImage"
        managed_disk_type = "Standard_LRS"
      }

      os_profile {
        computer_name  = "${var.vmHostName}"
        admin_username = "${var.vmUserName}"
        admin_password = "${var.vmAdminPwd}"
      }

      os_profile_windows_config {
        provision_vm_agent        = true
        enable_automatic_upgrades = true
      }

      depends_on = ["azurerm_network_interface.nic"]  
    }

This is how I am using the module in my main template file

module "WinWeb01" {
  source = "../modules/vmsetup"

  nicName    = "${var.prefix}-web-nic01"
  rgName     = "${azurerm_resource_group.rg.name}"
  rgLocation = "${azurerm_resource_group.rg.location}"
  vmHostName = "${var.prefix}-web01"
  vmUserName = "vmAdmin"

  vmAdminPwd           = "${data.azurerm_key_vault_secret.vmPassword.0.value}"
  availabilitySetId    = "${azurerm_availability_set.webvmavailset.id}"
  vmSize               = "${var.vmSize}"
  diskVol01Name        = "${var.prefix}-web01-disk01"
  availabilitySetCount = "${var.availabilitySetCount}"
  subnetId             = "${azurerm_subnet.subnets.1.id}"
}

I have a requirement to spin up VMs in different subnets so I thought it will be beneficial if I add Network Interface template to my module as well and provide the appropriate subnet ids when calling the module.

However the problem is when I run terraform plan I get following error

module.WinWeb01.var.subnetId: Resource 'azurerm_subnet.subnets' not found for variable 'azurerm_subnet.subnets.1.id'

The module is looking for a subnet id before the subnet has actually been created (subnet code is in main template file). I have seen few posts suggesting using depends_on variable but that has not worked in my case.

https://medium.com/@bonya/terraform-adding-depends-on-to-your-custom-modules-453754a8043e

Will appreciate if you anyone can guide my in a right direction here.

2
The error message states the resource azurerm_subnet.subnets does not exist, which is true according to the posted code.Matt Schuchard

2 Answers

1
votes

Resolved the issue by upgrading Terraform to latest v 0.12.2. I was previously using v0.11.2.

0
votes

This actually works fine in the earlier version of Terraform (I'm running v0.11.13).

The workaround for module and resource dependency is to use a list variable called depends_on and pass that to the different modules from the root level, as long as you include the same variable also in the module folders:

variable "depends_on" {
    default = []
    type = "list"
}

For example if you have a resource like the resource group that needs to be created before you can create the CosmosDB account, then you can do something like this:

rg.tf

resource "azurerm_resource_group" "resource_group_name" {
  name     = "rg-${var.environment}-${var.project_name}"
  location = "${var.resource_location}"
}

main.tf

module "cosmosdb" {
  source            = "./modules/cosmosdb"
  resource_group    = "${azurerm_resource_group.resource_group_name.name}"
  project_name      = "${var.project_name}"
  depends_on = ["azurerm_resource_group.resource_group_name"]

You can also do the same with resources that exist in separate modules as long as the depends_on variable is located inside the module.