Apa itu Datasource? #
Resource dan data source sama-sama menggunakan informasi dari provider, tapi perannya berlawanan. Resource membuat infrastruktur dan Terraform bertanggung jawab atas lifecycle-nya. Data source membaca informasi dari infrastruktur yang sudah ada — yang mungkin dibuat oleh Terraform workspace lain, oleh tim lain, atau bahkan secara manual. Data source adalah cara Terraform menjangkau keluar dari konfigurasinya sendiri untuk mendapat informasi yang dibutuhkan.
flowchart TD
A["data source block\ndi Terraform config"] -->|"Read"| B["☁️ Cloud Provider\nAPI"]
B -->|"Return"| C["📋 Existing\nResource Data"]
C --> D["🔗 Referenced di\nresource lain"]
style A fill:#3b82f6,stroke:#1e40af,color:#fff
style B fill:#f59e0b,stroke:#d97706,color:#fff
style C fill:#10b981,stroke:#059669,color:#fff
style D fill:#8b5cf6,stroke:#6d28d9,color:#fffResource vs Data Source: Perbedaan Mendasar #
# resource — Terraform MEMILIKI ini
# Dibuat, diupdate, dan dihapus oleh Terraform
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
# VPC ini ada karena Terraform membuatnya
# Jika blok ini dihapus dari konfigurasi → VPC dihapus
}
# data — Terraform MEMBACA ini
# Sudah ada di luar, Terraform hanya query
data "aws_vpc" "existing" {
id = "vpc-0abcdef1234567890"
# VPC ini sudah ada sebelum Terraform — dibuat secara manual atau oleh tim lain
# Terraform hanya membacanya, tidak pernah mengubah atau menghapusnya
}
LIFECYCLE PERBANDINGAN:
resource:
terraform apply → resource DIBUAT
ubah konfigurasi → resource DIUPDATE
hapus dari .tf → resource DIHAPUS
data:
terraform plan/apply → data DIBACA
ubah filter → data yang BERBEDA DIBACA
hapus dari .tf → tidak ada yang berubah di infrastruktur
Cara Data Source Bekerja dalam Execution Plan #
Data source di-evaluate saat terraform plan — sebelum operasi create/update/destroy resource manapun.
URUTAN EVALUASI:
terraform plan dimulai
│
▼
1. Evaluasi semua data source
(query ke provider API sekarang juga)
│
▼
2. Gunakan nilai dari data source
untuk menghitung resource plan
│
▼
3. Tampilkan execution plan
# Data source dievaluasi dulu, baru resource yang menggunakannya diplan
data "aws_ami" "ubuntu" {
most_recent = true
owners = ["099720109477"] # Canonical
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-*-22.04-amd64-server-*"]
}
}
resource "aws_instance" "web" {
# Saat plan, data.aws_ami.ubuntu.id sudah diketahui nilainya
# (bukan "known after apply" seperti resource)
ami = data.aws_ami.ubuntu.id
instance_type = "t3.micro"
}
Data Source yang Paling Sering Digunakan #
# 1. AMI terbaru
data "aws_ami" "ubuntu_22_04" {
most_recent = true
owners = ["099720109477"]
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
}
# 2. Informasi akun AWS saat ini
data "aws_caller_identity" "current" {}
data "aws_region" "current" {}
# Gunakan dalam konfigurasi:
resource "aws_s3_bucket" "logs" {
bucket = "logs-${data.aws_caller_identity.current.account_id}-${data.aws_region.current.name}"
}
# 3. Availability Zones yang tersedia
data "aws_availability_zones" "available" {
state = "available"
}
resource "aws_subnet" "public" {
count = 3
availability_zone = data.aws_availability_zones.available.names[count.index]
vpc_id = aws_vpc.main.id
cidr_block = "10.0.${count.index}.0/24"
}
# 4. VPC atau resource yang dikelola Terraform lain
data "aws_vpc" "shared_services" {
tags = {
Name = "shared-services-vpc"
Environment = "production"
}
}
# 5. Secret dari AWS Secrets Manager
data "aws_secretsmanager_secret_version" "api_key" {
secret_id = "production/myapp/api-key"
}
# 6. IAM policy document
data "aws_iam_policy_document" "assume_role" {
statement {
effect = "Allow"
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["ec2.amazonaws.com"]
}
}
}
resource "aws_iam_role" "instance" {
assume_role_policy = data.aws_iam_policy_document.assume_role.json
}
flowchart LR
A["🏗️ Manually\nCreated VPC"] -->|"Existing"| B["data.aws_vpc\nLookup"]
B -->|"vpc_id, cidr_block"| C["🔗 Used by\nNew Subnet"]
D["🏗️ Manually\nCreated AMI"] -->|"Existing"| E["data.aws_ami\nLookup"]
E -->|"image_id"| F["🔗 Used by\nNew Instance"]
style A fill:#6b7280,stroke:#4b5563,color:#fff
style B fill:#3b82f6,stroke:#1e40af,color:#fff
style C fill:#10b981,stroke:#059669,color:#fff
style D fill:#6b7280,stroke:#4b5563,color:#fff
style E fill:#3b82f6,stroke:#1e40af,color:#fff
style F fill:#10b981,stroke:#059669,color:#fffKapan Menggunakan Data Source #
GUNAKAN DATA SOURCE UNTUK:
✓ Membaca resource yang dikelola workspace Terraform lain
(VPC dari tim networking, IAM role dari tim security)
✓ Mendapatkan informasi dinamis yang berubah
(AMI terbaru, AZ yang tersedia, latest RDS engine version)
✓ Membaca secret dari AWS Secrets Manager atau Vault
✓ Mendapatkan informasi tentang akun atau region aktif
✓ Membaca resource yang dibuat secara manual dan tidak akan di-Terraform-kan
✓ Membuat IAM policy document secara programatik
JANGAN GUNAKAN DATA SOURCE UNTUK:
✗ Resource yang ingin kamu kelola lifecycle-nya dengan Terraform
→ Gunakan resource block, bukan data block
✗ Menyiasati dependency antar workspace secara implicit coupling
→ Pertimbangkan mengoper nilai via variable secara eksplisit
Data Source dengan Filter yang Salah #
Salah satu kesalahan paling umum dengan data source adalah filter yang mengembalikan lebih dari satu hasil atau tidak ada hasil sama sekali.
# ANTI-PATTERN: Filter yang terlalu lebar — mungkin mengembalikan >1 hasil
data "aws_instance" "web" {
filter {
name = "instance-state-name"
values = ["running"] # Ada banyak instance yang running!
}
# Error: Your query returned more than one result. Please try a more specific search criteria.
}
# BENAR: Filter yang cukup spesifik untuk mengembalikan tepat 1 hasil
data "aws_instance" "web" {
filter {
name = "tag:Name"
values = ["web-server-production"]
}
filter {
name = "instance-state-name"
values = ["running"]
}
}
Data Source vs Variable: Kapan Menggunakan yang Mana #
Pemilihan antara data source dan variable tergantung pada sumber nilai dan fleksibilitas yang dibutuhkan.
flowchart TD
A["Butuh nilai
resource yang sudah ada?"] --> B{"Sumber nilai?"}
B -->|"Dari Terraform
lain"| C["terraform_remote_state
data source"]
B -->|"Dari cloud
provider"| D["data.aws_ami
data.aws_vpc
DLL"]
B -->|"Dari user
di CLI"| E["variable
dengan default"]
B -->|"Dari file
.env/.tfvars"| F["variable
dengan validation"]
style A fill:#e3f2fd,stroke:#1565c0
style C fill:#e8f5e9,stroke:#2e7d32
style D fill:#fff3e0,stroke:#e65100
style E fill:#f3e5f5,stroke:#6a1b9a
style F fill:#fce4ec,stroke:#c62828# DATA SOURCE: Ambil dari API cloud
data "aws_ami" "latest" {
most_recent = true
owners = ["amazon"]
filter {
name = "name"
values = ["amzn2-ami-hvm-*"]
}
}
# VARIABLE: Diberikan oleh user atau tfvars
variable "ami_id" {
type = string
default = "ami-12345"
}
# Kapan data source lebih baik:
# - Nilai berubah seiring waktu (AMI terbaru, zone availability)
# - Nilai bergantung pada resource yang sudah ada di cloud
# - Butuh informasi yang tidak diketahui user
# Kapan variable lebih baik:
# - Nilai sudah diketahui dan spesifik
# - Butuh validasi custom
# - Nilai berbeda per environment
Menghindari Over-Fetching dengan Data Source #
# ANTI-PATTERN: Mengambil terlalu banyak data
data "aws_instances" "all" {
# Mengambil SEMUA instance di account → API call mahal
# Tidak ada filter → response sangat besar
}
# BENAR: Filter sedini mungkin
data "aws_instances" "running" {
filter {
name = "instance-state-name"
values = ["running"]
}
filter {
name = "tag:Environment"
values = [var.environment]
}
}
Data Source Patterns untuk Multi-Environment #
Pola umum: menggunakan data source untuk menyesuaikan konfigurasi dengan environment yang sedang aktif.
# Ambil info VPC yang sudah ada (shared infra)
data "aws_vpc" "main" {
filter {
name = "tag:Environment"
values = [var.environment]
}
}
data "aws_subnets" "private" {
filter {
name = "vpc-id"
values = [data.aws_vpc.main.id]
}
filter {
name = "tag:Tier"
values = ["private"]
}
}
# Gunakan data source untuk conditional resource
resource "aws_instance" "web" {
count = var.environment == "production" ? 3 : 1
ami = data.aws_ami.latest.id
instance_type = var.environment == "production" ? "m5.large" : "t3.micro"
subnet_id = data.aws_subnets.private.ids[0]
}
flowchart LR
A["terraform workspace
select production"] --> B["data.aws_vpc
(tag:Environment=prod)"]
B --> C["data.aws_subnets
(vpc-id=xxx)"]
C --> D["resource.aws_instance
(count=3)"]
style A fill:#e3f2fd,stroke:#1565c0
style D fill:#e8f5e9,stroke:#2e7d32Data Source Error Handling #
Data source bisa gagal karena berbagai alasan. Penting untuk menangani error dengan benar.
# Error umum:
# 1. Resource tidak ditemukan
# Error: no matching AMI found
# → Periksa filter, pastikan resource benar-benar ada
# 2. Multiple matches
# Error: multiple VPCs matched; use additional constraints
# → Tambahkan filter lebih spesifik
# 3. Permission denied
# Error: UnauthorizedOperation
# → Pastikan IAM policy punya izin read untuk resource type
# 4. API rate limit
# Error: Throttling
# → Kurangi data source, gunakan caching, atau retry
# Tips: gunakan try() untuk graceful degradation
locals {
# Jika data source gagal, gunakan default
vpc_cidr = try(data.aws_vpc.main.cidr_block, "10.0.0.0/16")
# Jika data source mengembalikan kosong
subnet_ids = length(data.aws_subnets.private.ids) > 0 ? data.aws_subnets.private.ids : [aws_subnet.fallback.id]
}
Data Source Lifecycle #
DATA SOURCE LIFECYCLE:
terraform init
└── Download providers
terraform plan
├── Read data source (API call)
├── Store result in state
├── Use result untuk compute resource arguments
└── Plan resource changes
terraform apply
├── Read data source lagi (refresh)
├── Apply resource changes
└── Update state
terraform destroy
└── Hapus managed resources (data source TIDAK dihapus)
# Data source SELALU di-refresh saat plan/apply
# Ini bisa lambat jika banyak data source
# Percepat: gunakan -refresh=false (tidak recommended)
terraform plan -refresh=false
# Lebih baik: kurangi jumlah data source
# atau gunakan caching mechanism
Ringkasan #
- Data source membaca, resource membuat — data source tidak pernah mengubah infrastruktur, hanya membaca informasi dari yang sudah ada.
- Data source di-evaluate saat plan — nilainya sudah diketahui sebelum resource apapun dibuat atau diubah.
- Gunakan untuk informasi dinamis — AMI terbaru, AZ yang tersedia, informasi akun saat ini — nilai yang berubah dan tidak bisa di-hardcode.
- Gunakan untuk membaca lintas batas — resource dari workspace lain, resource yang dikelola tim lain, resource yang dibuat manual.
- Filter harus cukup spesifik untuk mengembalikan tepat satu hasil — filter yang terlalu lebar menyebabkan error saat plan.
- Data source tidak menciptakan coupling ownership — Terraform tidak bisa menghapus atau mengubah resource yang hanya dibaca via data source.