Explaining Dependency handling and depends_on keyword in Terraform
This page 📝 aims to provide a high-level explanation of how Terraform handles dependencies, specifically the introduction of the depends_on
meta-argument. This argument is required in situations where an explicit dependency declaration is necessary.
2 min readNov 2, 2023
- When preparing for deployment, Terraform goes through a planning process.
- As part of this process, the order of actions must be determined.
- To facilitate this:
- Load local state (files) data into memory.
- Refresh the attributes of resources and data sources from the remote environment.
- Parse local config (files).
- Construct a dependency graph based on the data sources and resources defined in the code.
- Perform a diff, generating a list of additions, updates, and deletions.
- Terraform, ideally, seeks to execute changes in parallel.
- Therefore, it works out which changes are dependent on others.
- Changes that are not dependent on others are executed in parallel.
- Other changes are done one after the other, in a serial fashion.
The dependency graph is based on references in configuration files
- In the VPC resource, there is no reference:
resource "aws_vpc" "app" {
cidr_block = var.vpc_cidr_block
enable_dns_hostnames = true
tags = local.common_tags
}
- However, in the subnet resource
aws_subnet.public_subnet1
, there is a dependency on the value ofaws_vpc.app.id
:
resource "aws_subnet" "public_subnet1" {
cidr_block = var.vpc_public_subnets[0]
vpc_id = aws_vpc.app.id
map_public_ip_on_launch = var.map_public_ip_on_launch
availability_zone = data.aws_availability_zones.available.names[0]
tags = local.common_tags
}
- Consequently, Terraform will wait until the VPC is created before it retrieves its
id
and creates a subnet in that VPC. - Then, the
aws_instance
has a reference toaws_subnet.public_subnet1.id
and therefore it waits for the subnet to be created, etc. - Terraform can manage these dependencies implicitly.
- But sometimes, the dependency is non-obvious and Terraform needs to be explicitly informed about it.
Non-obvious/explicit dependencies are managed with the depends_on
meta-argument
- When creating
aws_iam_role
, bothaws_iam_instance_profile
andaws_iam_role_policy
depend on it. - The
aws_instance
depends onaws_iam_instance_profile
. - However, for the EC2 instances to access the S3 bucket, the
aws_iam_role_policy
needs to be created. - The solution is to add a meta-argument to the configuration — this is the
depends_on
keyword. - A meta-argument is an argument in a configuration file that instructs Terraform on how to manage the object but is not used by the provider to configure the target object.
- The
depends_on
meta-argument expects a<list>
of other resources/data sources that the resource depends on.
- In the following code, the
depends_on
meta-argument contains a single item in a<list>
:
resource "aws_instance" "nginx1" {
ami = nonsensitive(data.aws_ssm_parameter.amzn2_linux.value)
instance_type = "t2.micro"
subnet_id = aws_subnet.public_subnet1.id
vpc_security_group_ids = [aws_security_group.alb_sg.id]
iam_instance_profile = aws_iam_instance_profile.nginx_profile.name
depends_on = [aws_iam_role_policy.allow_s3_all]
tags = local.common_tags
user_data = <<EOF
#! /bin/bash
sudo amazon-linux-extras install -y nginx1
sudo service nginx start
sudo rm /usr/share/nginx/html/index.html
echo '<html><head><title>Hello World</title></head><body>Hello World;</span></span></p></body></html>' | sudo tee /usr/share/nginx/html/index.html
EOF
}