Terraform
Terraform
Core
Init, Plan, Apply
- terraform init
- Set up providers & backend in that directory
 
terraform init
- terraform plan
- Preview changes
 
terraform plan
- terraform apply
- Make changes (add -auto-approve to skip prompt)
 
terraform apply
Core Concept

1. Providers
- Providers is a Terraform Plugin to interact with API
- Best practice: Providers must be located in a separate file ex:terrafrom.tf
- Example of providers which Terraform Support
# terraform.tf
terraform {
    required_providers {
        aws = {
            source = "hashicorp/aws"
            version = "~> 5. 0"
        }
    }
}
provider "aws" {
    region = "us-east-1"
}
- Local provideris used for creating and managing resources on your local machine (no API interaction)
# terraform.tf
terraform {
  required_providers {
    local = {
      source = "hashicorp/local"
      version = "2.5.3"
    }
  }
}
2. Resources + Meta-Arguments
- Actual components that will be define
- Best practice: Resources must be located in main.tf
- Syntax:
resource "type" "resource_name" {}
- Example of local provider (Requirements & Optionals):
# main.tf (local provider)
resource "local_file" "local" {
    # requirement
    filename = "<relative path>/filename.txt"
    # or use a relative path command with ${}
    # filename = "${path.module}/filename.txt"
    #optional
    content  = "This is a local file created by Terraform"
}
- Meta-Arguments:
- Special arguments that can be used with every resource
- They work with every resource type to control how Terraform creates or manages them.
 
depends_on
- Forces an explicit dependency between resources.
- Useful when Terraform can’t automatically detect the dependency.
- Example:
resource "aws_s3_bucket" "example" {
  bucket = "my-bucket"
}
resource "aws_s3_bucket_policy" "example_policy" {
  bucket = aws_s3_bucket.example.id
  policy = data.aws_iam_policy_document.example.json
  depends_on = [aws_s3_bucket.example] # ensures bucket is created first
}
count
- Creates multiple instances of the same resource.
- You can access each instance with an index ([0], [1], etc.).
- Example:
resource "aws_instance" "servers" {
  count = 3
  ami   = "ami-123456"
  instance_type = "t2.micro"
}
- → Creates 3 EC2 instances.
for_each
- Similar to count, but instead of an index, it uses a map or set of strings.
- Gives more control over naming and referencing.
- Example:
resource "aws_s3_bucket" "buckets" {
  for_each = toset(["dev", "staging", "prod"])
  bucket   = "myapp-${each.key}"
}
- → Creates 3 uniquely named buckets.
provider
- Lets you specify which provider configuration a resource should use, especially when multiple providers of the same type exist.
- Example:
provider "aws" {
  region = "us-east-1"
  alias  = "east"
}
provider "aws" {
  region = "us-west-2"
  alias  = "west"
}
resource "aws_instance" "west_server" {
  provider = aws.west
  ami      = "ami-654321"
  instance_type = "t2.micro"
}
lifecycle
- Controls special behaviors for resources during apply/destroy.
- Common options:
- create_before_destroy= true → ensures a new resource is made before deleting the old one.
- prevent_destroy= true → protects critical resources from being destroyed.
- ignore_changes= [field] → tells Terraform to ignore changes to certain fields.
 
- Example:
3. State management
Definitions
- 
What It Is - The state file is like Terraform’s “notebook.”
- It records all resources that Terraform has created, modified, or deleted.
- It acts as Terraform’s database for keeping track of infrastructure.
 
- 
Current vs Desired State - Desired State = what you define in your .tfconfiguration files.
- Current State = what Terraform knows already exists (stored in the state file).
- Terraform compares the two and makes changes to bring the current state in line with the desired state.
 
- Desired State = what you define in your 
- 
How It Works in Practice - At first, the state file is empty because nothing exists.
- When you run terraform apply, Terraform:- Creates the infrastructure.
- Updates the state file with details of the created resources (like IDs, attributes, etc.).
 
- If you later change or delete resources in your config, Terraform compares with the state file and applies only the necessary updates.
 
- 
State File Format - Stored as JSON in terraform.tfstate.
- Contains metadata (Terraform version, provider info).
- Stores details of each resource: type, name, attributes, IDs, and configuration.
 
- Stored as JSON in 
- 
Why It’s Important - Terraform relies on it to know what’s already been provisioned.
- Without it, Terraform would not know whether resources already exist and might recreate or duplicate them.
- It enables Terraform’s declarative approach: always moving the current state toward the desired state.
 
State Sub Command
- Usage: terraform state <subcommand> [options] [args]- List all sub commands: terraform state -h
 
- List all sub commands: 
- terraform state list, List resources in the state
- terraform state mv, Move an item in the state
- terraform state pull, Pull current state and output to stdout
- terraform state push, Update remote state from a local state file
- terraform state replace-provider, Replace provider in the state
- terraform state rm, Remove instances from the state
- terraform state show, Show a resource in the state- terraform state show <specific resources>, gives information of that resource only
 
IMPORTANT: State Drift
- State Drift:
- Occur when someone delete resources manually from the Provider's UI
- Solution:
- terraform initand then- terraform apply(Recommend)- Init helps to compare the actual infra and current state file
- apply create the missing/difference between the two, hence create missing resource(s) + config the state file
 
- terraform refresh(Not Recommend)- If the deletion is intentional
- terraform refresh will not change anything in the infra, but it will changes the current state file
- However, this command doesn't consider the resource file