Apa itu Resource? #

Di section Concept, kamu sudah berkenalan dengan resource sebagai unit dasar konfigurasi Terraform. Di section ini, kita masuk lebih dalam — bagaimana resource berinteraksi satu sama lain, bagaimana Terraform mengelola lifecycle-nya, dan bagaimana menulis resource yang robust untuk infrastruktur production. Artikel ini membangun fondasi untuk topik-topik yang lebih dalam di section ini: lifecycle, dependency, dan operation.

Resource vs Data Source #

Salah satu kebingungan paling umum di Terraform adalah perbedaan antara resource dan data. Keduanya adalah blok konfigurasi, tapi perannya sangat berbeda.

# resource — Terraform MEMBUAT dan MENGELOLA ini
# Terraform bertanggung jawab atas lifecycle-nya: create, update, destroy
resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"

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

# data — Terraform MEMBACA ini, tidak membuatnya
# Resource sudah ada di luar Terraform, kamu hanya ingin referensikan
data "aws_ami" "ubuntu" {
  most_recent = true
  owners      = ["099720109477"]  # Canonical

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

# Menggunakan keduanya bersama
resource "aws_instance" "web" {
  ami           = data.aws_ami.ubuntu.id  # AMI dari data source
  instance_type = "t3.micro"
  vpc_id        = aws_vpc.main.id         # VPC dari resource
}

Anatomi Lengkap Blok Resource #

# Struktur lengkap blok resource dengan semua bagiannya

resource "<PROVIDER>_<TYPE>" "<NAME>" {
  # ─────────────────────────────────────────
  # ARGUMEN — konfigurasi spesifik resource ini
  # ─────────────────────────────────────────
  ami           = "ami-0abcdef1234567890"
  instance_type = "t3.micro"

  # Blok bersarang (nested block)
  tags = {
    Name        = "web-server"
    Environment = var.environment
  }

  # ─────────────────────────────────────────
  # META-ARGUMENTS — berlaku untuk semua resource
  # ─────────────────────────────────────────

  # Dependency eksplisit
  depends_on = [aws_iam_role_policy_attachment.node]

  # Buat beberapa instance
  count = 3
  # atau: for_each = var.instance_map

  # Gunakan provider non-default
  provider = aws.us_east

  # Kustomisasi lifecycle
  lifecycle {
    create_before_destroy = true
    prevent_destroy       = false
    ignore_changes        = [tags["LastModified"]]
  }
}

Meta-arguments (depends_on, count, for_each, provider, lifecycle) adalah argumen khusus yang dikenali Terraform sendiri — bukan argumen dari provider. Mereka berlaku untuk semua resource, apapun tipe dan providernya.


Bagaimana Resource Direpresentasikan di State #

Setiap resource yang dibuat Terraform disimpan di state dengan identitas uniknya. Memahami struktur ini membantu saat kamu perlu berinteraksi dengan state secara langsung.

# Lihat semua resource di state
terraform state list

# Output:
# aws_instance.web
# aws_instance.workers[0]
# aws_instance.workers[1]
# aws_instance.workers[2]
# module.vpc.aws_vpc.main
# module.vpc.aws_subnet.public["ap-southeast-1a"]
# Lihat detail satu resource di state
terraform state show aws_instance.web

# Output:
# # aws_instance.web:
# resource "aws_instance" "web" {
#     ami                    = "ami-0abcdef1234567890"
#     id                     = "i-0abcdef1234567890"
#     instance_type          = "t3.micro"
#     private_ip             = "10.0.1.42"
#     public_ip              = "54.123.45.67"
#     ... (semua atribut, termasuk yang digenerate AWS)
# }

Address resource di state mengikuti format: <type>.<name> untuk resource biasa, <type>.<name>[index] untuk resource dengan count, dan <type>.<name>["key"] untuk resource dengan for_each.


Resource Address dan Cara Mereferensikannya #

Setiap resource memiliki address yang bisa direferensikan dari tempat lain dalam konfigurasi.

# Format referensi: <TYPE>.<NAME>.<ATTRIBUTE>

resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"
}

resource "aws_subnet" "public" {
  vpc_id = aws_vpc.main.id  # Referensi ke atribut "id" dari aws_vpc.main
}

# Untuk resource dengan count:
resource "aws_subnet" "private" {
  count  = 3
  vpc_id = aws_vpc.main.id
  cidr_block = "10.0.${count.index + 10}.0/24"
}

resource "aws_route_table_association" "private" {
  count          = 3
  subnet_id      = aws_subnet.private[count.index].id  # Akses per index
  route_table_id = aws_route_table.private.id
}

# Semua subnet sekaligus menggunakan splat expression:
output "private_subnet_ids" {
  value = aws_subnet.private[*].id  # ["subnet-001", "subnet-002", "subnet-003"]
}

Pola Penulisan yang Konsisten #

Konsistensi dalam cara menulis resource membuat konfigurasi lebih mudah dibaca dan di-review.

# POLA YANG DIREKOMENDASIKAN:

resource "aws_instance" "web" {
  # 1. Argumen required (wajib) di atas
  ami           = var.ami_id
  instance_type = var.instance_type

  # 2. Argumen optional yang penting
  subnet_id              = aws_subnet.public.id
  vpc_security_group_ids = [aws_security_group.web.id]
  iam_instance_profile   = aws_iam_instance_profile.web.name

  # 3. Blok bersarang
  root_block_device {
    volume_size = 20
    volume_type = "gp3"
    encrypted   = true
  }

  # 4. Tags selalu di akhir
  tags = merge(
    var.common_tags,
    {
      Name = "web-server"
      Role = "web"
    }
  )

  # 5. Lifecycle di paling akhir (jika ada)
  lifecycle {
    create_before_destroy = true
  }
}

Ringkasan #

  • resource untuk membuat, data untuk membaca — resource dikelola Terraform, data source hanya dibaca dari yang sudah ada.
  • Meta-arguments (depends_on, count, for_each, provider, lifecycle) berlaku untuk semua resource, bukan argumen dari provider.
  • Address resource di state mengikuti format <type>.<name> — penting diketahui untuk operasi terraform state dan referensi antar resource.
  • Referensi menggunakan format <type>.<name>.<attribute> — ini yang membentuk dependency graph otomatis Terraform.
  • Splat expression ([*]) untuk mengakses semua instance sekaligus dari resource dengan count.
  • Konsistensi penulisan — required args dulu, optional, nested blocks, tags, lifecycle — membuat review lebih mudah.

← Sebelumnya: Idempotency   Berikutnya: Lifecycle →

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