Data Sources: Reading Existing Infrastructure
Scenario
Your configuration needs to reference infrastructure that already exists — the current AWS account ID, the current region, the default VPC ID. You shouldn't hardcode these values because they change between accounts and regions. Instead, you need to query them at plan time using data sources.
Data sources read existing infrastructure without creating or modifying anything. They are the read-only counterpart to resource blocks.
- Use data "aws_caller_identity" to get the current account ID.
- Use data "aws_region" to get the current region name.
- Use data "aws_vpc" with a filter to find the default VPC.
- Reference data source attributes in a resource using data.TYPE.NAME.attribute syntax.
- Output all queried values to confirm they were fetched correctly.
Additional Context
Data sources execute during terraform plan. Terraform calls the cloud provider's API to read the current state of the referenced resource. The result is available as attributes you can reference anywhere in your config.
Key difference: resource = Terraform manages the lifecycle (create, update, delete). data = Terraform only reads; the resource is managed by someone else (another team, the AWS console, another Terraform config).
main.tf
# main.tf
terraform {
required_version = ">= 1.5.0"
required_providers {
aws = { source = "hashicorp/aws", version = "~> 5.0" }
}
}
provider "aws" { region = "us-east-1" }
# ─── DATA SOURCES ─── Read existing infrastructure without modifying it
# Get the current AWS account ID and user/role info
data "aws_caller_identity" "current" {}
# Get the current region (reads from provider config)
data "aws_region" "current" {}
# Find the default VPC using a filter
# Every AWS account has a default VPC — this finds it without hardcoding the ID
data "aws_vpc" "default" {
default = true # simple flag — returns the default VPC
}
# ─── RESOURCE ─── Uses data source values (no hardcoding)
resource "aws_s3_bucket" "datasource_demo" {
# Bucket name includes account ID and region from data sources
bucket = "datasource-demo-${data.aws_caller_identity.current.account_id}-${data.aws_region.current.name}"
tags = {
AccountID = data.aws_caller_identity.current.account_id
Region = data.aws_region.current.name
DefaultVPC = data.aws_vpc.default.id
ManagedBy = "terraform"
}
}outputs.tf
# outputs.tf
output "account_id" { value = data.aws_caller_identity.current.account_id }
output "caller_arn" { value = data.aws_caller_identity.current.arn }
output "current_region" { value = data.aws_region.current.name }
output "default_vpc_id" { value = data.aws_vpc.default.id }
output "vpc_cidr" { value = data.aws_vpc.default.cidr_block }
output "bucket_name" { value = aws_s3_bucket.datasource_demo.id }Workflow Commands
terraform init && terraform apply
# All queried values are available as outputs
terraform output account_id
terraform output default_vpc_id
terraform output vpc_cidr
terraform destroyApply complete! Resources: 1 added, 0 changed, 0 destroyed. Outputs: account_id = "123456789012" caller_arn = "arn:aws:iam::123456789012:user/terraform-user" current_region = "us-east-1" default_vpc_id = "vpc-0abc1234def56789" vpc_cidr = "172.31.0.0/16" bucket_name = "datasource-demo-123456789012-us-east-1"

