By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.
(For Cloud Engineers, DevOps, and Certification Prep)
Terraform resources are the building blocks of your infrastructure—think EC2 instances, S3 buckets, or IAM roles. Data sources, on the other hand, let you read existing infrastructure (e.g., an AMI ID, a VPC’s CIDR block, or a user’s ARN) without creating it.
Real-world scenario:You’re deploying a new microservice. You need: 1. A resource to create an ECS cluster.2. A data source to fetch the existing VPC’s subnet IDs (so you don’t hardcode them).3. Another data source to grab the latest ECS-optimized AMI.
What breaks if you ignore this?- Hardcoding values (e.g., AMI IDs) → Your Terraform breaks when AWS updates the AMI.- Not using data sources → You duplicate infrastructure (e.g., creating a new VPC when one already exists).- Poor referencing → Circular dependencies (e.g., trying to attach a security group to an instance before the security group exists).
resource
hcl resource "aws_instance" "web" { ami = "ami-0c55b159cbfafe1f0" instance_type = "t3.micro" }
ami
instance_type
lifecycle
prevent_destroy = true
data
hcl data "aws_vpc" "default" { default = true }
data "aws_subnets" "private"
depends_on
hcl resource "aws_db_instance" "app_db" { depends_on = [aws_security_group.db_sg] }
terraform plan
resource_type.name.attribute
hcl resource "aws_instance" "web" { vpc_security_group_ids = [aws_security_group.web_sg.id] }
web_sg
web
A
B
count
for_each
hcl resource "aws_instance" "web" { count = 3 ami = "ami-0c55b159cbfafe1f0" }
hcl resource "aws_iam_user" "developers" { for_each = toset(["alice", "bob", "charlie"]) name = each.key }
hcl resource "aws_instance" "web" { lifecycle { create_before_destroy = true # Replace instance before destroying old one prevent_destroy = true # Block accidental deletion } }
create_before_destroy
prevent_destroy
output
hcl output "instance_ip" { value = aws_instance.web.public_ip }
sensitive = true
terraform import
bash terraform import aws_instance.web i-1234567890abcdef0
.tf
aws configure
terraform --version
Deploy an ECS cluster in an existing VPC (using data sources to fetch subnets and security groups).
mkdir ecs-cluster && cd ecs-cluster terraform init
Create main.tf:
main.tf
# Fetch the default VPC data "aws_vpc" "default" { default = true } # Fetch all subnets in the VPC data "aws_subnets" "all" { filter { name = "vpc-id" values = [data.aws_vpc.default.id] } } # Fetch the default security group data "aws_security_group" "default" { vpc_id = data.aws_vpc.default.id name = "default" }
Add to main.tf:
resource "aws_ecs_cluster" "app" { name = "app-cluster" } resource "aws_ecs_task_definition" "app" { family = "app-task" network_mode = "awsvpc" requires_compatibilities = ["FARGATE"] cpu = 256 memory = 512 execution_role_arn = aws_iam_role.ecs_task_execution.arn container_definitions = jsonencode([{ name = "app" image = "nginx:latest" portMappings = [{ containerPort = 80 hostPort = 80 }] }]) } # IAM role for ECS task execution resource "aws_iam_role" "ecs_task_execution" { name = "ecs-task-execution-role" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [{ Action = "sts:AssumeRole" Effect = "Allow" Principal = { Service = "ecs-tasks.amazonaws.com" } }] }) } resource "aws_iam_role_policy_attachment" "ecs_task_execution" { role = aws_iam_role.ecs_task_execution.name policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy" }
resource "aws_ecs_service" "app" { name = "app-service" cluster = aws_ecs_cluster.app.id task_definition = aws_ecs_task_definition.app.arn desired_count = 1 launch_type = "FARGATE" network_configuration { subnets = data.aws_subnets.all.ids security_groups = [data.aws_security_group.default.id] assign_public_ip = true } }
terraform plan # Verify no hardcoded values terraform apply
app-cluster
app-service
bash curl <TASK_PUBLIC_IP>
hcl data "aws_secretsmanager_secret_version" "db_password" { secret_id = "prod/db/password" }
t3.micro
m5.large
S3 Glacier
Environment = "prod"
Owner = "team-x"
project-environment-resource
app-prod-alb
apply
data "aws_ami" "latest"
aws_instance.web.sg_id
resource "aws_vpc" "main" {...}
✅ data "aws_vpc" "main" {...}
data "aws_vpc" "main" {...}
"How do you reference a security group in an EC2 instance?"
vpc_security_group_ids = [aws_security_group.web.id]
❌ security_groups = ["web_sg"] (wrong attribute)
security_groups = ["web_sg"]
"What happens if you delete a resource from .tf but not from state?"
"You need to deploy an EC2 instance in an existing VPC. How do you avoid hardcoding subnet IDs?"- ✅ Use data "aws_subnets" "private" to fetch subnets dynamically.- ❌ Hardcode subnet_id = "subnet-123456" (breaks if subnets change).
subnet_id = "subnet-123456"
Deploy an S3 bucket with a lifecycle rule that moves objects to S3 Glacier after 30 days. Use a data source to fetch the current AWS account ID (to avoid hardcoding it in the bucket name).
data "aws_caller_identity" "current" {} resource "aws_s3_bucket" "logs" { bucket = "app-logs-${data.aws_caller_identity.current.account_id}" acl = "private" lifecycle_rule { id = "move-to-glacier" enabled = true transition { days = 30 storage_class = "GLACIER" } } }
Why it works:- data.aws_caller_identity.current fetches the AWS account ID dynamically.- The bucket name is globally unique (required for S3).- The lifecycle rule automates cost savings.
data.aws_caller_identity.current
resource "aws_instance" "web" {...}
data "aws_vpc" "default" {...}
aws_instance.web.public_ip
depends_on = [aws_security_group.web_sg]
count = 3
for_each = toset(["alice", "bob"])
lifecycle { create_before_destroy = true }
terraform import aws_instance.web i-1234567890abcdef0
output "instance_ip" { value = aws_instance.web.public_ip }
acl = "private"
private
backup_retention_period = 1
Final Tip:Always run terraform plan before apply. If the plan shows unexpected changes, stop and investigate—it’s cheaper to debug now than fix a broken prod environment later. ?
Join 4M+ learners. Unlock unlimited quizzes, wrong-answer tracking, flashcards + reminders, study guides, and 1-on-1 challenges.