One module should wait for another module from a different directory

Module ‘xyz’ should wait 10 mins for module ‘abc’ residing in a diff dir. Here are the details.

root/x/main.tf

module "abc" {
  ...
}
resource "time_sleep" "wait_10_mins" {
  depends_on = [module.abc[0]]

  create_duration = "10m"
}

root/y/main.tf

module "xyz" {
  .....

  depends_on = how to access resource time_sleep.wait_10_mins here?
  
}
1 Like

You need have a .tf at root to pass the reference to time_sleep.wait_10_mins

@gc-ss So there is no other way to achieve this without changing .tf location?

I’m not asking you to change the .tf location but create a new “bridge” .tf file.

Do you have a repo to look at?

Oh okay. Let’s see what I can do. We have a private repo.

Hi @NewToTerraform,

In situations like this it’s useful to know that for Terraform modules each input variable and output value can have its own set of dependencies. In particular, you can use explicit dependencies on your output values to encapsulate implementation details so that calling modules don’t need to know about them.

You didn’t mention here what is the purpose of waiting 10 minutes in your case, so I’m going to assume it’s because there’s some asynchronous process that must complete before some other object you’ve declared will be fully usable. In that case, I would typically suggest to identify another one of your output values which exports the information necessary to use that object, and annotate that output value with the additional dependency.

I’ll invent a situation in order to give an example. If you are deploying an AWS EC2 instance which serves some API which takes several minutes to become available once the EC2 instance is booted, then you’d probably already have an output value exporting the URL of that API, perhaps like this:

resource "aws_instance" "api" {
  # ...
}

output "api_url" {
  value = "https://${aws_instance.api.private_ip}/example/"
}

If you know that API won’t be usable for up to 10 minutes and you have no other way to explicitly detect when it becomes ready, you could represent this to your calling module by adding time_sleep.wait_10_mins as a secondary dependency of that output value:

resource "aws_instance" "api" {
  # ...
}

# Our API server can take up to 10min to become
# ready after launching, and we have no way to
# detect when it's ready explicitly, so we'll
# make the caller wait.
resource "time_sleep" "wait_10_mins" {
  depends_on = [aws_instance.api]

  create_duration = "10m"
}

output "api_url" {
  value      = "https://${aws_instance.api.private_ip}/example/"
  depends_on = [time_sleep.wait_10_mins]
}

The interesting thing about this design is that now your calling module doesn’t need to do anything special to deal with the 10 minute delay. Instead, this api_url output value will itself take 10 minutes to become ready, and thus anything else which uses it will be forced to wait:

module "xyz" {
  api_url = module.other.api_uri
}

Assuming that module.other.api_url is a reference to the output value I showed earlier, anything inside this module which refers to its var.api_url will be transitively blocked on that 10 minute delay, thus allowing the delay to propagate naturally through the dependencies you would’ve written anyway, rather than making all of the intermediate steps all explicitly propagate this extra implementation detail.

If you later change your original module so that it doesn’t need this 10 minute delay anymore then you can remove the delay resource and the explicit dependency in output "api_url" and then all of the callers of this module will immediately benefit from that improvement, without any need for changes outside of the module.

1 Like