Understanding Implicit Dependencies between Resources in Terraform
Tags: terraform, cloud9, cli, ec2
Published: 2023-01-17 00:05:59

In this article, I am going to show you how the ***`implicit dependencies`*** affect the behavior and order of different resources created and destroyed based on their configurations. However, Terraform cannot always deduce/give reasons on implicit dependencies between different parts of your infrastructure.

Please visit my **[GitHub Repository for Terraform articles](https://github.com/awsmine/Terraform_projects)** on various topics being updated on constant basis.

_**Let’s get started!**_


# Objectives:

**1.** Create infrastructure for ***`Implicit`*** dependencies

**2.** Delete (Destroy) your infrastructure



# Pre-requisites:
- AWS user account with admin access, not a root account.
- Cloud9 IDE with AWS CLI.



# Resources Used:

I have used a data source for pulling in an AMI ID instead of a hard-coded value for creating an EC2 Instance. I have used Terraform documentation for this purpose.

***[Terraform documentation for AMI](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami).***

***[data source for pulling in an AMI ID](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance).***



# Steps for implementation to this project:

## 1. Create infrastructure for Implicit dependencies

- Let’s create the following organizational structure as shown below.




![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u36spe8e01u7m39dmg6v.png)






- Create a ***`main.tf`*** file. This will deploy 2 Linux EC2 instances ***`"ec2_1"`*** and ***`"ec2_2"`***, with the security group ***`"ec2_sg"`***. 


```
# PROVIDERS BLOCK
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.23"
    }
  }
  required_version = ">= 1.2.0"
}


provider "aws" {
  region  = var.aws_region
}


# EC2 BLOCK
data "aws_ami" "linux" {
   most_recent = true
   owners      = ["amazon"]

  filter {
    name   = "name"
    values = ["amzn2-ami-hvm-*-x86_64-gp2"]
  }

  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }
}



resource "aws_instance" "ec2_1" {
  ami                = data.aws_ami.linux.id
  instance_type      = "t2.micro"
  vpc_security_group_ids = [aws_security_group.ec2_sg.id]

  tags = {
    Name = "ec2_1"
  }
}

resource "aws_instance" "ec2_2" {
  ami                = data.aws_ami.linux.id
  instance_type      = "t2.micro"
  vpc_security_group_ids = [aws_security_group.ec2_sg.id]

  tags = {
    Name = "ec2_2"
  }
}

resource "aws_eip" "ip" {
  vpc      = true
  instance = aws_instance.ec2_1.id

  tags = {
    Name = "ip"
  }
}



# SECURITY BLOCK 
resource "aws_security_group" "ec2_sg" {
   name        = "ec2_sg"
   description = "allow inbound HTTP traffic"

   # HTTP from vpc
   ingress {
      from_port   = 80
      to_port     = 80
      protocol    = "tcp"
      cidr_blocks = ["0.0.0.0/0"]     
   }

  # outbound rules
  # internet access to anywhere
  egress {
     from_port   = 0
     to_port     = 0
     protocol    = "-1"
     cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
     name = "ec2_sg"
  }
}



# VARIABLES BLOCK
variable "aws_region" {
  description = "AWS region for all resources."
  type        = string
  default     = "us-east-1"
}



# OUTPUTS BLOCK
output "instance_id_1" {
  value = aws_instance.ec2_1.id
}

output "instance_id_2" {
  value = aws_instance.ec2_2.id
}

output "ec2_elastic_ip" {
  description = "Elastic IP address for ec2_1 instance."
  value       = aws_eip.ip.id
}

```

- Run **`terraform init`** to initialize Terraform. 


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gwi0h3znd5grjl2a84wf.png)


- The ***`aws_eip`*** resource type allocates and associates an Elastic IP to an ***`ec2_1`*** instance.

- Hence, ***`aws_instance.ec2_1`*** should be created before ***`aws_eip`*** can be created and attached, because it is dependent on ***`aws_instance.ec2_1`*** creation.

- However, ***`aws_instance.ec2_2`*** can be created parallelly to other resources as there is no dependency attached.

- Run **`terraform apply`** to apply the configuration and type **`yes`** when prompted. 


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/amjeacq81fc1e8sm01nr.png)


- See how Terraform creates your resources in order, and reports on its progress as it deploys your resources. The output will be similar to the following.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9x66o4gtf2xxd3r7rh33.png)


- As shown above, Terraform waited until the creation of EC2 instance - ***`ec2_1`*** was complete before creating the Elastic IP address - ***`aws_eip`***.

- It automatically infers when one resource depends on another by studying the resource attributes used in interpolation expressions. 

***Terraform knows that the EC2 Instance must be created before the Elastic IP.***

***The reference to*** ***`aws_instance.ec2_1.id`*** ***in the definition of the*** ***`aws_eip.ip`*** ***block creates an implicit dependency.***

- It uses this dependency information to determine the correct order in which to create the different resources. 


## 2. Delete (Destroy) your infrastructure

- Implicit dependencies affect the order in which resources are destroyed as well as created.

- Run **`terraform destroy`** to destroy your infrastructure. Accept the changes by typing **`yes`** when prompted.

- Wait for 4-5 minutes to destroy your resources.

- See how Elastic IP address - ***`eip_ip`*** is destroyed before EC2 instance - ***`ec2_1`***.  


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c5t0vya2415bjlixs0if.png)


# What we have done so far

- We have successfully demonstrated how the ***`implicit dependencies`*** affect the behavior and order of different resources created and destroyed based on their configurations.