Reference #

Mendeklarasikan data source adalah langkah pertama. Langkah berikutnya adalah menggunakan nilainya secara efektif — mereferensikan atribut yang tepat, memahami kapan nilai tersedia, dan menghindari jebakan yang muncul ketika data source bergantung pada resource yang belum tentu ada saat plan dijalankan.

flowchart TD
    A["data source\ndideklarasikan"] --> B["Terraform\nRead API"]
    B --> C["Attribute\ntersedia"]
    C --> D["Referenced\ndengan data.X.Y.Z"]

    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:#fff

Cara Mereferensikan Atribut Data Source #

Referensi ke atribut data source menggunakan format data.<TYPE>.<NAME>.<ATTRIBUTE>.

data "aws_ami" "ubuntu" {
  most_recent = true
  owners      = ["099720109477"]

  filter {
    name   = "name"
    values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"]
  }
}

# Referensi atribut data source:
resource "aws_instance" "web" {
  ami           = data.aws_ami.ubuntu.id           # String — AMI ID
  instance_type = "t3.micro"
}

resource "aws_launch_template" "web" {
  image_id      = data.aws_ami.ubuntu.id
  instance_type = "t3.micro"

  # Referensi atribut lain dari data source yang sama
  description = "Template menggunakan ${data.aws_ami.ubuntu.name} (${data.aws_ami.ubuntu.creation_date})"
}

Data Source untuk Membaca State Workspace Lain #

terraform_remote_state adalah data source khusus yang membaca output dari workspace Terraform lain. Ini memungkinkan arsitektur multi-workspace yang terpisah tapi terhubung.

# Workspace "networking" menyediakan VPC dan subnet
# Workspace "compute" membaca output dari workspace "networking"

data "terraform_remote_state" "networking" {
  backend = "s3"

  config = {
    bucket = "my-terraform-state"
    key    = "production/networking/terraform.tfstate"
    region = "ap-southeast-1"
  }
}

# Gunakan output dari workspace networking
resource "aws_instance" "app" {
  ami       = data.aws_ami.ubuntu.id
  subnet_id = data.terraform_remote_state.networking.outputs.private_subnet_ids[0]

  vpc_security_group_ids = [
    data.terraform_remote_state.networking.outputs.app_security_group_id
  ]
}

# Atau baca semua subnet sekaligus
resource "aws_autoscaling_group" "app" {
  vpc_zone_identifier = data.terraform_remote_state.networking.outputs.private_subnet_ids
  # ...
}

Data Source yang Bergantung pada Resource #

Ada kasus di mana data source perlu membaca resource yang baru saja dibuat dalam konfigurasi yang sama. Ini membutuhkan depends_on.

# SKENARIO: Membaca policy yang baru dibuat untuk menggabungkannya

resource "aws_iam_policy" "s3_read" {
  name   = "s3-read-policy"
  policy = data.aws_iam_policy_document.s3_read.json
}

resource "aws_iam_policy" "cloudwatch_write" {
  name   = "cloudwatch-write-policy"
  policy = data.aws_iam_policy_document.cloudwatch_write.json
}

# Data source ini membaca policy yang baru dibuat di atas
data "aws_iam_policy" "s3_read" {
  name = "s3-read-policy"

  # Tanpa depends_on, data source mungkin di-evaluate sebelum
  # resource aws_iam_policy.s3_read selesai dibuat
  depends_on = [aws_iam_policy.s3_read]
}
# Pola yang lebih umum: hindari situasi ini dengan referensi langsung
# Daripada baca via data source, referensikan resource langsung

resource "aws_iam_role_policy_attachment" "app_s3" {
  role       = aws_iam_role.app.name
  policy_arn = aws_iam_policy.s3_read.arn  # Referensi langsung — lebih bersih
  # Bukan: data.aws_iam_policy.s3_read.arn
}
flowchart LR
    subgraph DATASOURCE["data source"]
        DS["data.aws_vpc.selected"]
    end
    subgraph RESOURCES["Resources"]
        SG["aws_security_group"]
        SUB["aws_subnet"]
    end

    DS -->|"vpc_id"| SG
    DS -->|"cidr_block"| SUB

    style DATASOURCE fill:#e3f2fd,stroke:#1565c0
    style RESOURCES fill:#e8f5e9,stroke:#2e7d32

Pola Data Source di Arsitektur Production #

# POLA 1: Dynamic AMI — selalu gunakan AMI terbaru yang sudah di-test

data "aws_ami" "app" {
  most_recent = true
  owners      = ["self"]  # AMI yang dibuat oleh akun ini sendiri (golden AMI)

  filter {
    name   = "name"
    values = ["app-server-*"]
  }

  filter {
    name   = "tag:Status"
    values = ["tested"]  # Hanya AMI yang sudah lulus testing
  }
}
# POLA 2: Lookup resource yang dikelola tim lain

# Tim networking mengelola VPC dan menandainya dengan tag
data "aws_vpc" "main" {
  tags = {
    Name        = "main-vpc"
    Environment = var.environment
    ManagedBy   = "networking-team"
  }
}

data "aws_subnets" "private" {
  filter {
    name   = "vpc-id"
    values = [data.aws_vpc.main.id]
  }

  tags = {
    Tier = "private"
  }
}
# POLA 3: Lookup berdasarkan naming convention yang konsisten

locals {
  # Naming convention yang disepakati tim: <project>-<env>-<component>
  vpc_name = "${var.project}-${var.environment}-vpc"
}

data "aws_vpc" "main" {
  filter {
    name   = "tag:Name"
    values = [local.vpc_name]
  }
}
# POLA 4: Conditional data source — hanya query jika diperlukan

variable "use_existing_vpc" {
  type    = bool
  default = false
}

data "aws_vpc" "existing" {
  count = var.use_existing_vpc ? 1 : 0

  tags = {
    Name = "existing-vpc"
  }
}

resource "aws_subnet" "app" {
  vpc_id = var.use_existing_vpc ? data.aws_vpc.existing[0].id : aws_vpc.new.id
  # ...
}

Membaca Atribut Akun dan Region #

Data source untuk informasi akun dan region sangat berguna untuk membuat konfigurasi yang portable — tidak perlu hardcode account ID atau region.

data "aws_caller_identity" "current" {}
data "aws_region" "current" {}
data "aws_partition" "current" {}

# Gunakan untuk ARN yang portable
resource "aws_iam_role_policy" "app" {
  role = aws_iam_role.app.id

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect   = "Allow"
      Action   = ["s3:GetObject"]
      Resource = [
        # Portable — tidak hardcode account ID atau region
        "arn:${data.aws_partition.current.partition}:s3:::${var.bucket_name}/*"
      ]
    }]
  })
}

# Tag standar yang menyertakan informasi akun
locals {
  standard_tags = {
    AccountId  = data.aws_caller_identity.current.account_id
    Region     = data.aws_region.current.name
    ManagedBy  = "terraform"
  }
}


Data Source Lifecycle dan Refresh Behavior #

Data source di-refresh saat terraform plan dan terraform apply. Memahami kapan dan bagaimana data source di-refresh penting untuk konsistensi.

# Data source di-refresh SETIAP kali plan/apply dijalankan
# Ini berbeda dengan managed resource yang hanya di-refresh
# jika -refresh=true (default)

# Contoh: data.aws_ami.latest akan selalu mencari AMI terbaru
# Jika AMI baru dibuat antara plan dan apply, apply bisa menggunakan
# AMI yang berbeda dari yang direncanakan

# Untuk mem-pinning data source ke nilai tertentu:
# Gunakan filter yang spesifik atau simpan nilai di variable
flowchart TD
    A["terraform plan"] --> B["Refresh data sources"]
    B --> C["Read dari API
(ami-12345)"]
    C --> D["Plan menggunakan
ami-12345"]
    D --> E["Waktu berlalu...
AMI baru dibuat"]
    E --> F["terraform apply"]
    F --> G["Refresh data sources
lagi!"]
    G --> H["Read dari API
(ami-67890) ⚠️"]
    H --> I["Apply menggunakan
ami-67890 ≠ plan"]

    style A fill:#e3f2fd,stroke:#1565c0
    style H fill:#fff3e0,stroke:#e65100
    style I fill:#ffebee,stroke:#c62828

Performance Optimization untuk Data Source #

# Data source yang memanggil API bisa memperlambat plan
# jika ada banyak data source atau API lambat

# Tips: Gunakan filter yang spesifik untuk mengurangi API call
# BURUK: Mengambil semua AMI, lalu filter di Terraform
data "aws_ami" "all" {
  most_recent = true
  owners      = ["self"]
  # Mengembalikan SEMUA AMI milik kita → API response besar
}

# BAIK: Filter sedini mungkin di level API
data "aws_ami" "filtered" {
  most_recent = true
  owners      = ["self"]

  filter {
    name   = "name"
    values = ["my-app-*"]  # Filter di level API → response kecil
  }

  filter {
    name   = "state"
    values = ["available"]  # Hanya AMI yang available
  }
}

Caching Data Source Results #

Data source dipanggil setiap kali terraform plan atau terraform apply. Untuk data yang jarang berubah, ini bisa memperlambat eksekusi.

# Solusi: Simpan hasil data source di local values
# Data source dipanggil sekali, tapi bisa dipakai berkali-kali

data "aws_region" "current" {}

data "aws_caller_identity" "current" {}

locals {
  # Simpan di locals untuk referensi mudah
  region     = data.aws_region.current.name
  account_id = data.aws_caller_identity.current.account_id
  
  # Build ARN pattern yang bisa dipakai di banyak tempat
  arn_prefix = "arn:aws:${local.region}:${local.account_id}"
  
  # Common tags yang include info dari data source
  common_tags = {
    Region    = local.region
    AccountId = local.account_id
    ManagedBy = "terraform"
  }
}
# Jika data source terlalu lambat karena API rate limit:
# 1. Kurangi jumlah data source (gabungkan filter)
# 2. Gunakan -refresh=false untuk skip refresh saat plan
terraform plan -refresh=false
# Hati-hati: state tidak di-refresh, bisa tidak akurat

# 3. Targeted refresh untuk resource tertentu
terraform plan -refresh-only -target=data.aws_ami.latest


---

## Data Source Authentication Context

Data source menggunakan credentials yang dikonfigurasi di provider block. Jika provider tidak terkonfigurasi, data source akan gagal.

```bash
# Data source menggunakan credentials dari:
# 1. Provider block (explicit configuration)
# 2. Environment variables (AWS_ACCESS_KEY_ID, etc.)
# 3. Shared credentials file (~/.aws/credentials)
# 4. IAM role (EC2 instance profile, ECS task role)
# 5. OIDC token (GitHub Actions, GitLab CI)

# Urutan prioritas:
# Explicit config > Env vars > Shared creds > IAM role > OIDC
# Data source dengan explicit provider
provider "aws" {
  region = "ap-southeast-1"
  profile = "production"  # Menggunakan shared credentials
}

# Data source ini menggunakan provider di atas
data "aws_ami" "latest" {
  most_recent = true
  owners      = ["amazon"]
  filter {
    name   = "name"
    values = ["amzn2-ami-hvm-*"]
  }
}

# Data source dengan different provider
provider "aws" {
  alias   = "us_east"
  region  = "us-east-1"
}

data "aws_ami" "latest_us" {
  provider    = aws.us_east
  most_recent = true
  owners      = ["amazon"]
}

Ringkasan #

  • Format referensi: data.<TYPE>.<NAME>.<ATTRIBUTE> — konsisten dengan format referensi resource tapi dengan prefix data..
  • terraform_remote_state untuk membaca output workspace lain — berguna untuk arsitektur multi-workspace tapi menciptakan coupling yang perlu dipertimbangkan.
  • depends_on untuk data source yang membaca resource dalam konfigurasi yang sama — pastikan resource selesai dibuat sebelum data source di-evaluate.
  • Lebih baik referensi langsung ke resource daripada membaca via data source jika resource ada di konfigurasi yang sama.
  • Pola golden AMI: gunakan filter tag:Status = tested untuk memastikan hanya AMI yang sudah divalidasi yang digunakan.
  • aws_caller_identity dan aws_region untuk membuat konfigurasi yang portable — tidak perlu hardcode account ID atau region name di konfigurasi.

← Sebelumnya: Apa itu Datasource?   Berikutnya: Anti-Pattern Datasource →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact