TerraformPilot

Terraform

How to Use Terraform Data Sources - Query Existing Resources

Learn to use Terraform data sources to query existing infrastructure. Covers AWS AMI lookup, VPC discovery, AZ listing, and cross-state data access patterns.

LLuca Berton1 min read

Quick Answer

#

Data sources let you read information from your cloud provider or other Terraform state without creating resources. Use them to look up AMIs, discover VPCs, list availability zones, and reference resources managed outside your current configuration.

data "aws_ami" "ubuntu" {
  most_recent = true
  owners      = ["099720109477"]
  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
  }
}
 
resource "aws_instance" "web" {
  ami           = data.aws_ami.ubuntu.id  # Dynamic AMI lookup
  instance_type = "t3.micro"
}

What Are Data Sources?

#
ConceptResourcesData Sources
PurposeCreate/manage infrastructureRead existing infrastructure
Keywordresourcedata
StateStored in state fileRefreshed every plan/apply
Referenceaws_instance.web.iddata.aws_ami.ubuntu.id

Common Data Source Patterns

#

Look Up the Latest AMI

#
data "aws_ami" "amazon_linux" {
  most_recent = true
  owners      = ["amazon"]
 
  filter {
    name   = "name"
    values = ["al2023-ami-*-x86_64"]
  }
 
  filter {
    name   = "virtualization-type"
    values = ["hvm"]
  }
}
 
output "ami_id" {
  value = data.aws_ami.amazon_linux.id
}

Discover Available AZs

#
data "aws_availability_zones" "available" {
  state = "available"
}
 
resource "aws_subnet" "private" {
  count             = 3
  vpc_id            = aws_vpc.main.id
  cidr_block        = cidrsubnet(aws_vpc.main.cidr_block, 8, count.index)
  availability_zone = data.aws_availability_zones.available.names[count.index]
}

Reference an Existing VPC

#
# Look up VPC by tag
data "aws_vpc" "main" {
  filter {
    name   = "tag:Name"
    values = ["production-vpc"]
  }
}
 
# Look up subnets in that VPC
data "aws_subnets" "private" {
  filter {
    name   = "vpc-id"
    values = [data.aws_vpc.main.id]
  }
  filter {
    name   = "tag:Tier"
    values = ["private"]
  }
}
 
resource "aws_lb" "main" {
  name               = "app-lb"
  internal           = true
  load_balancer_type = "application"
  subnets            = data.aws_subnets.private.ids
}

Get Current AWS Account Info

#
data "aws_caller_identity" "current" {}
data "aws_region" "current" {}
 
output "account_id" {
  value = data.aws_caller_identity.current.account_id
}
 
output "region" {
  value = data.aws_region.current.name
}

Read Remote State

#
# Reference outputs from another Terraform configuration
data "terraform_remote_state" "network" {
  backend = "s3"
  config = {
    bucket = "my-terraform-state"
    key    = "network/terraform.tfstate"
    region = "us-east-1"
  }
}
 
resource "aws_instance" "app" {
  ami           = data.aws_ami.amazon_linux.id
  instance_type = "t3.micro"
  subnet_id     = data.terraform_remote_state.network.outputs.private_subnet_ids[0]
}

Build IAM Policies

#
data "aws_iam_policy_document" "s3_read" {
  statement {
    effect    = "Allow"
    actions   = ["s3:GetObject", "s3:ListBucket"]
    resources = [
      aws_s3_bucket.data.arn,
      "${aws_s3_bucket.data.arn}/*",
    ]
  }
}
 
resource "aws_iam_policy" "s3_read" {
  name   = "s3-read-policy"
  policy = data.aws_iam_policy_document.s3_read.json
}

Data Sources Across Cloud Providers

#

Azure

#
data "azurerm_resource_group" "existing" {
  name = "my-rg"
}
 
data "azurerm_virtual_network" "main" {
  name                = "production-vnet"
  resource_group_name = data.azurerm_resource_group.existing.name
}

GCP

#
data "google_compute_network" "main" {
  name    = "default"
  project = var.project_id
}

When to Use Data Sources

#
  • AMI/image lookups — always use data sources, never hardcode
  • Cross-team resources — reference VPCs, subnets managed by another team
  • Account/region info — dynamic configuration based on where you're running
  • Remote state — compose infrastructure from multiple Terraform configs
  • IAM policies — use aws_iam_policy_document over raw JSON

Troubleshooting

#
ErrorFix
"no matching data source found"Check filters — too restrictive
"multiple results returned"Add most_recent = true or more filters
"insufficient permissions"IAM role needs describe/list permissions
#

Conclusion

#

Data sources are the read-only counterpart to resources. Use them to dynamically look up AMIs, discover infrastructure, reference remote state, and build IAM policies. They keep your configs portable across regions and accounts — never hardcode what you can look up.

#Terraform#AWS#Infrastructure as Code#DevOps

Share this article