4
votes

I'm about to create a small VM with terraform in azure and have come across a curious problem. Terraform creates my resource group but immediately fails when creating the next object (a VNet) that is part of the resource group:

resource "azurerm_resource_group" "simple_vm" {
  name     = "simple_vm"
  location = "westeurope"
}

resource "azurerm_virtual_network" "main" {
  name                = "main"
  address_space       = ["10.0.0.0/16"]
  location            = "westeurope"
  resource_group_name = "simple_vm"
}

Calling terraform apply results in:

* azurerm_virtual_network.main: 1 error(s) occurred:

* azurerm_virtual_network.main: Error Creating/Updating Virtual Network "main" (Resource Group "simple_vm"): network.VirtualNetworksClient#CreateOrUpdate: Failure sending request: StatusCode=0 -- Original Error: autorest/azure: Service returned an error. Status=404 Code="ResourceGroupNotFound" Message="Resource group 'simple_vm' could not be found."

Looking at the web interface shows, the resource group has been created. Calling terraform apply a second time correctly finds it and creates the VNet inside the resource group.

To me this looks like terraform tries to create objects in the resource group while it is not yet fully instantiated in azure. I've observed a similar behavior with public IPs: I've created a VM with a public IP and included an output ... to print the public ip of the VM. On the first run, the output is empty (no error message though). After terraform refresh the output is filled with the IP.

Am I doing something wrong? Is this a bug in terraform?

3
This is just a generic dependency ordering issue as with stackoverflow.com/questions/51932165/…. Use depends on or interpolate the result of the resource group into the virtual network resource so that Terraform knows what order to do things in. We should probably create a generic, canonical question/answer combo for this I guess. - ydaetskcoR
Here is an interpolation example. As ydestskorR states, this will set up the dependency for you. resource_group_name = "${azurerm_resource_group.simple_vm.name}" - Neil Peterson

3 Answers

11
votes

You need to create an implicit dependency like this:

resource "azurerm_virtual_network" "main" {
  name                = "main"
  address_space       = ["10.0.0.0/16"]
  location            = "westeurope"
  resource_group_name = "${azurerm_resource_group.simple_vm.name}"
}

In this way, Terraform knows that it will need to create the Resource Group first before it can create the vNet.

From Terraform's perspective, your original code simply has 2 independent resources.

Terraform's documentation on this is useful. In general, you don't want to set up explicit (depends_on) dependencies unless you absolutely have to.

1
votes

Make sure you have your "provider" values exported properly before running plan and apply. Sometimes terraform might not know which subscription/resource group it needs to associate and hence, resource not found(404 error) might occur.

1
votes

You are trying to use the resource group created using the code at the top (azurerm_resource_group.simple_vm.name)

I can also see that you are using the same location so you can set in the vnet module the location like follow: azurerm_resource_group.simple_location

So your code should look like this

resource "azurerm_resource_group" "simple_vm" {
  name     = "simple_vm"
  location = "westeurope"
}

resource "azurerm_virtual_network" "main" {
  name                = "main"
  address_space       = ["10.0.0.0/16"]
  location            = azurerm_resource_group.simple_vm.location
  resource_group_name = azurerm_resource_group.simple_vm.name
}