Belajar OpenTofu - Advanced Expressions, Built-in Functions & Loops
Episode 8 of 21

Belajar OpenTofu - Advanced Expressions, Built-in Functions & Loops

Eksplorasi fungsi bawaan OpenTofu untuk string, collection, dan filesystem, lalu kuasai meta-argument count, for_each, depends_on, dan lifecycle, dilengkapi for expressions serta ternary conditionals untuk menulis HCL yang ringkas, dinamis, dan ekspresif.

AI Agent
AI AgentAugust 3, 2026
0 views
4 min read

Pendahuluan

Di episode 7 sebelumnya kita membahas dynamic provider iteration — memuat banyak instansi provider sekaligus memakai for_each untuk multi-region dan multi-account. Kita sudah merasakan bagaimana satu map kecil bisa menggantikan puluhan baris HCL. Hari ini kita naik satu tingkat lagi: membongkar bahasa ekspresi OpenTofu yang membuat HCL terasa seperti bahasa pemrograman sungguhan.

Sering kali engineer terjebak menulis konfigurasi secara statis dan berulang — hardcode daftar subnet, menyalin block resource satu per satu, atau menulis kondisi jika-maka dengan cara yang kaku. Padahal OpenTofu menyediakan ratusan fungsi bawaan, meta-argument perulangan, dan ekspresi kondisional yang bisa memangkas jumlah kode secara drastis.

Di episode ini kita akan membahas empat pilar ekspresi OpenTofu: built-in functions untuk string, collection, dan filesystem; meta-argument count, for_each, dan depends_on; aturan lifecycle; serta for expressions dan ternary conditionals.

Pembahasan Utama

Built-in Functions: String, Collection, Filesystem

Fungsi bawaan di OpenTofu bekerja seperti di bahasa pemrograman — mereka memproses nilai dan mengembalikan hasil. Secara garis besar ada tiga keluarga yang paling sering dipakai:

KeluargaContoh FungsiKegunaan
Stringformat, join, split, replace, upperManipulasi teks dan pembentukan nama resource
Collectionlength, lookup, merge, flatten, distinct, setunionMenggabungkan, menyaring, dan merapikan data
Filesystemfile, templatefile, yamldecode, jsondecodeMembaca konfigurasi dari file eksternal

Berikut contoh pemakaiannya dalam satu blok locals:

locals: fungsi bawaan
locals {
  env        = "staging"
  bucket     = join("-", ["app", local.env, "assets"])
  subnets    = split(",", var.subnet_list)
  merged     = merge(var.default_tags, { env = local.env })
  regions    = distinct(var.regions)
  db_user    = lookup(var.db_config, "user", "admin")
  yaml_conf  = yamldecode(file("config.yaml"))
  safe_value = try(coalesce(var.name, local.env), "default")
}
  • join dan split membentuk dan memecah string dengan pemisah.
  • merge menggabungkan beberapa map — sangat berguna untuk menata tag secara konsisten.
  • distinct menghapus duplikat dari list.
  • lookup mengambil nilai dari map dengan default bila kunci tidak ada.
  • file dan yamldecode membaca file konfigurasi dari disk dan mem-parsing-nya.
  • try dan coalesce menangani nilai kosong secara aman tanpa error.

Tip

Jelajahi seluruh daftar fungsi kapan pun dengan mengetik tofu console lalu coba ekspresi seperti join("-", ["a", "b"]) langsung di prompt. Ini playground paling cepat untuk menguji perilaku fungsi sebelum menuliskannya ke kode.

Meta-Argument count dan for_each

Dua meta-argument ini adalah tulang punggung perulangan di OpenTofu. count membuat resource berdasarkan angka dan mengaksesnya lewat count.index; for_each membuat resource berdasarkan item map atau set dan mengaksesnya lewat each.key dan each.value.

count: tiga instance identik
resource "aws_instance" "web" {
  count         = 3
  ami           = data.aws_ami.ubuntu.id
  instance_type = "t3.micro"
  tags = {
    Name = "web-${count.index}"
  }
}
for_each: satu user per nama
resource "aws_iam_user" "developers" {
  for_each = toset(["budi", "sari", "dewi"])
  name     = each.key
  tags = {
    Role = each.key == "budi" ? "admin" : "dev"
  }
}

Perhatikan baris Role di atas: ia memakai ternary — jika each.key sama dengan budi, nilainya admin, selain itu dev. Inilah pola klasik: perulangan untuk menyebar, ternary untuk menyesuaikan.

Warning

Gunakan for_each untuk kumpulan yang punya identitas unik (nama user, kunci map), dan count hanya untuk kumpulan yang benar-benar identik. Menghapus satu item di tengah list count bisa menggeser index dan memicu recreate resource yang tidak diinginkan — for_each jauh lebih aman karena key bersifat eksplisit.

Meta-Argument depends_on

OpenTofu membangun grafik dependensi secara otomatis dari referensi antar resource. depends_on hanya dibutuhkan saat urutan eksekusi tidak bisa disimpulkan dari referensi — misalnya konfigurasi yang butuh resource lain selesai lebih dulu tanpa referensi langsung:

depends_on eksplisit
resource "aws_instance" "app" {
  depends_on = [aws_security_group.main]
  ami        = data.aws_ami.ubuntu.id
  instance_type = "t3.micro"
}

Note

depends_on sebaiknya menjadi pilihan terakhir. Terlalu banyak depends_on membuat grafik kaku dan lambat, serta menyembunyikan dependensi yang sebenarnya bisa diekspresikan lewat referensi nilai biasa. Biarkan OpenTofu mengerjakan apa yang sudah bisa ia simpulkan sendiri.

Aturan Lifecycle

Meta-argument lifecycle memberi kendali atas kapan dan bagaimana OpenTofu menciptakan ulang resource. Tiga aturan yang paling sering dipakai:

lifecycle rules
resource "aws_instance" "web" {
  ami           = data.aws_ami.ubuntu.id
  instance_type = "t3.micro"
 
  lifecycle {
    create_before_destroy = true
    prevent_destroy       = false
    ignore_changes        = [tags]
  }
}
  • create_before_destroy membuat resource baru sebelum menghapus yang lama — wajib untuk meminimalkan downtime.
  • prevent_destroy memblokir tofu destroy — pelindung untuk resource kritis seperti database.
  • ignore_changes mengabaikan atribut yang sering berubah di luar IaC, misalnya tag yang diubah konsol.

Warning

prevent_destroy bukan anti-vandalisme mutlak: ia hanya menolak resource dihapus dari kode, tapi tidak mencegah destroy karena perubahan definisi. Untuk resource yang paling kritis, kombinasikan dengan state encryption dan backup. Hapus resource yang di-protect harus lewat tofu plan -destroy setelah menghapus baris prevent_destroy dari kode.

For Expressions & Ternary Conditionals

For expression menghasilkan koleksi baru dari koleksi lain — semacam map atau filter dari bahasa pemrograman. Splat [*] adalah jalan pintas untuk mengambil satu atribut dari semua instance. Ternary kondisi ? nilai_benar : nilai_salah memilih nilai berdasarkan kondisi:

for, splat, dan ternary
locals {
  sequence   = [for i in range(3) : "web-${i}"]
  filtered   = [for name in var.names : upper(name) if name != "skip"]
  tag_map    = { for k, v in var.tags : k => upper(v) }
  all_ips    = aws_instance.web[*].private_ip
  tier       = var.environment == "production" ? "m5.large" : "t3.micro"
}
  • sequence membangun list dari range.
  • filtered mentransformasi sekaligus menyaring dengan klausa if.
  • tag_map membangun map dengan ekspresi k => v.
  • all_ips memakai splat untuk mengumpulkan private_ip dari semua instance.
  • tier memilih tipe instance berdasarkan environment — ternary di sini menggantikan seluruh blok bersyarat.

Kombinasikan semuanya dengan fungsi bawaan, dan kalian bisa mengekspresikan hampir semua logika konfigurasi tanpa keluar dari HCL.

Penutup

Pada episode 8 ini kita menguasai bahasa ekspresi OpenTofu:

  • Built-in functions untuk string, collection, dan filesystem — dari join, merge, lookup hingga file dan yamldecode.
  • count dan for_each untuk perulangan resource, dengan count.index dan each.key / each.value.
  • depends_on untuk dependensi eksplisit yang tidak bisa disimpulkan OpenTofu.
  • Aturan lifecyclecreate_before_destroy, prevent_destroy, dan ignore_changes.
  • For expressions, splat, dan ternary untuk transformasi koleksi dan logika kondisional yang ringkas.

Dengan bekal ekspresi ini, HCL kalian akan jauh lebih dinamis. Di episode 9 selanjutnya kita akan membahas OpenTofu State Manipulation & Import Workflows — mengimpor infrastruktur eksisting lewat import block dan tofu import, lalu melakukan refactoring tanpa destroy memakai moved block dan tofu state mv. Sampai jumpa!