Hi,
I am just removing a resource (myvm) from a module (Azure), no changes in module definition, but my plan is showing it needs to recreate other VMs(myvm1) also. Why it is so? I have no change in version and other dependencies.
Unfortunately what you’ve shared isn’t really enough information to determine what’s happening here. I’d like to see the definition of this resource "azurerm_virtual_machine" "vm-windows" you showed in your plan output, since I think the way you’ve defined location is likely to be a clue here. I also assume there must be something else changing in this plan alongside this VM which would then lead to that location changing, so if there were other changes described in the plan output then it would help to share those too, so it’s possible to see how planned changes are flowing between your multiple resources.
When you use depends_on like this you force Terraform to be quite pessimistic in how it resolves dependencies, because now everything inside that module must depend on these two objects, and one of them is itself a module and so implies depending on many other objects too.
It doesn’t seem like either of these depends_on in your module are actually needed, because all of the necessary dependencies seem to already be described by the references in other arguments. For that reason, I’d suggest trying to remove depends_on from both of your module blocks to see if that makes the situation better. It should be very rare to use depends_on in a module block because in most cases either Terraform can infer the dependencies automatically itself (as I think is the case here) or there are better ways to describe the dependencies more precisely inside your module’s output blocks.
This also seems like a situation where we’ve made Terraform’s dependency resolver more precise in later versions of Terraform and so if you are not on the latest release then upgrading may cause Terraform to handle the depends_on arguments better, although I would still suggest removing them unless there is a specific reason why you included them.
Hi @apparentlymart ,
This actually solved my issue here thanks a lot. I remember that I might was facing some dependency issue while calling VM module where it was searching ASG information first to bind with NIC before ASG was actually created etc. That’s why I had put all depends_on. But I need to read now and come up with more accurate strategy to handle that part. Thanks a lot again.
As a starting point for learning about other options for managing dependencies between modules, I’d suggest looking at the depends_on argument for Output Values.
I’m not familiar enough with the VM/ASG/NIC situation to show a real example of that, but another typical situation where this sort of problem can arise is assigning policies to objects in order to make them usable. In many cloud systems, including Azure I believe, there is a distinction between declaring an object, declaring a policy, and attaching the policy to the object, and so with Terraform’s default dependency inference the policy attachment ends up being dependent on the object rather than the other way around, and so any other component referring to the object wouldn’t naturally also depend on the policy attachment.
If you’re writing a module that returns an object with a policy attached to it then, you can properly encapsulate that module’s behavior by adding a depends_on argument to the output value to document those additional dependencies that Terraform can’t automatically see:
resource "azurerm_resource_group" "example" {
name = "example"
location = "West Europe"
}
resource "azurerm_policy_definition" "example" {
name = "example"
# etc...
}
resource "azurerm_policy_assignment" "example" {
name = "example"
# These references mean that the policy assignment
# depends on the resource group and the policy.
scope = azurerm_resource_group.example.id
policy_definition_id = azurerm_policy_definition.example.id
# etc...
}
output "resource_group_name" {
# This value expression means that the output
# automatically depends on the resource group.
value = azurerm_resource_group.example.name
# ...but the resource group isn't really complete
# until the policy is assigned to it, so we can use
# depends_on to let Terraform know that.
depends_on = [azurerm_policy_assignment.example]
}
The important advantage of placing the depends_on on the output value rather than on the calling module blocks is that this extra dependency is now encapsulated within the module. If another module calls this module and refers to the resource_group_name attribute then that reference will automatically depend on both the resource group and the policy assignment, without the module user needing to know the details of how the objects are connected together.
This is what I meant by “there are better ways to describe the dependencies more precisely inside your module’s output blocks” in my previous comment.