Skip to main content
BlogDevOps

OpenTofu 1.13: Fungsi convert, assume dan Breaking Changes

Catatan upgrade OpenTofu 1.13: perubahan output base64gzip, WinRM dihapus, fungsi convert dan assume, linting experimental, Windows ARM64, akhir build 32-bit.

Matthews Wong

Software Engineer

Oktober 202611 menit baca
OpenTofu 1.13: Fungsi convert, assume dan Breaking Changes

Ringkasan Utama

OpenTofu 1.13, diumumkan pada 29 September 2026, sengaja dibuat ringan: fungsi convert dan assume baru, linting dan Symbol Libraries yang masih experimental, serta paket Windows ARM64. Risiko upgrade-nya adalah output base64gzip berubah, koneksi provisioner WinRM dihapus, macOS 13 jadi minimum, dan ini series terakhir dengan build 32-bit.

Kebanyakan post rilis dibaca untuk daftar fitur. Untuk 1.13 daftar fiturnya pendek, dan upgrade notes-lah yang bisa menghabiskan satu sore Anda, jadi post ini membacanya berdasarkan urutan tingkat bahayanya.

Saya membaca pengumuman resmi 1.13.0, halaman referensi fungsi convert, keluarga assume dan base64gzip, dua post tentang experiment, serta halaman release di GitHub. Saya belum menjalankan 1.13 terhadap state production, jadi kode di bawah dibentuk dari dokumen-dokumen itu dan bukan hasil pengukuran. Apa pun yang tidak saya temukan di sana sengaja dibuang.

Rilis ringan, dengan sengaja

Pengumuman menyebut masa pengembangan dipersingkat agar OpenTofu selaras dengan siklus rilis Go, dan menyebut 1.13 relatif ringan soal fitur baru. Series 1.13 mendapat security support sampai Agustus 2027.

Ringan bukan berarti tanpa kejadian. Upgrade Go di bawah binary-lah yang mengubah output base64gzip, dan penghapusan fitur mengikuti jalur biasa: deprecate dulu, baru remove. Berikut semua perubahan yang bisa saya konfirmasi, diurutkan menurut apakah bisa merugikan Anda.

PerubahanJenisSiapa yang kenaYang perlu dilakukan
Output base64gzipBreakingSiapa pun yang punya argumen resource dari base64gzip; plan berikutnya mengusulkan perubahanReview diff; pakai ignore_changes sementara kalau belum bisa apply
WinRM untuk provisionerBreaking (dihapus)Setiap connection block dengan type winrm pada provisioner remote-exec atau filePindah ke OpenSSH for Windows sebelum upgrade
Build 32-bit (386, arm)Series terakhirRunner dan laptop dengan CPU 32-bit; tofu init menampilkan warning selama series 1.13Rencanakan pindah ke amd64 atau arm64 sebelum 1.14
Minimum macOS 13 VenturaBatas platformmacOS yang lebih lama bisa crash atau berperilaku salahUpgrade OS atau pertahankan CLI lama di mesin itu
Fungsi convert dan assumeBaru, tambahanTidak ada; opt in per expressionPakai hanya jika provider menjamin propertinya
Linting dan Symbol LibrariesExperimentalTidak ada secara default; keduanya opt-in dan bisa berubahCoba di branch, beri feedback, jangan jadikan dependency

Windows di ARM64 juga baru menjadi platform yang didukung resmi. Ini kabar baik, tetapi seperti dijelaskan di bagian enam, ada catatan soal provider.

base64gzip: output setara, byte berbeda

Fungsi base64gzip meng-gzip sebuah string lalu meng-encode hasilnya dengan Base64. Pengumuman menyebut perubahan di standard library Go membuat hasilnya setara dengan versi lama tetapi tidak identik byte per byte, dan halaman referensi fungsinya mengulang hal itu. Karena OpenTofu membandingkan nilai konfigurasi dengan state sebagai string persis, argumen resource apa pun yang dibangun dari fungsi ini akan tampak berubah.

Jalan keluar yang didokumentasikan adalah meta-argument ignore_changes: pertahankan nilai lama untuk sementara dan hapus block-nya saat siap memakai encoding baru. Pengumuman juga menyebut provider pihak ketiga yang dibuild dengan Go 1.26 atau lebih lama bisa menyediakan perilaku lama, OpenTofu tidak menyediakan provider resmi untuk itu, dan Anda bisa mencarinya di OpenTofu Registry. Saya anggap itu pilihan terakhir.

resource "aws_s3_object" "index" {
  bucket           = aws_s3_bucket.site.id
  key              = "index.html.gz"
  content_base64   = base64gzip(file("${path.module}/index.html"))
  content_encoding = "gzip"

  # Temporary: the 1.13 encoding is equivalent but not byte-for-byte identical,
  # so the first plan after upgrading proposes an in-place update. Pin the old
  # value, upgrade, then delete this block in its own reviewed change.
  lifecycle {
    ignore_changes = [content_base64]
  }
}

Kegagalan yang perlu diwaspadai: reviewer melihat deretan in-place update pada objek yang isinya tidak berubah lalu menyetujuinya begitu saja. Jalankan upgrade di pull request tersendiri agar satu-satunya diff adalah ini, dan jadikan penghapusan ignore_changes perubahan terpisah yang diberi label.

WinRM hilang dari provisioner

WinRM sudah deprecated sejak 1.12.0 dan kini dihapus untuk provisioner remote-exec dan file; connection block dengan type winrm menjadi error. Pengumuman menyarankan migrasi ke OpenSSH for Windows sebelum upgrade. Connection type ssh di bawah adalah alternatif standarnya, tetapi pekerjaan sebenarnya adalah memastikan sshd terpasang dan bisa dijangkau di host Windows Anda.

# Wrong: errors in 1.13 (deprecated in 1.12, removed for remote-exec and file).
resource "null_resource" "bootstrap" {
  connection {
    type     = "winrm"
    host     = var.windows_host
    user     = "Administrator"
    password = var.admin_password
  }
  provisioner "remote-exec" {
    inline = ["powershell -File C:\\bootstrap.ps1"]
  }
}

# Right: the same connection over OpenSSH for Windows, once sshd is running on the host.
resource "null_resource" "bootstrap" {
  connection {
    type        = "ssh"
    host        = var.windows_host
    user        = "Administrator"
    private_key = file(var.ssh_key_path)
  }
  provisioner "remote-exec" {
    inline = ["powershell -File C:\\bootstrap.ps1"]
  }
}

Jika image Windows berasal dari golden template, aktifkan OpenSSH di sana, bukan di provisioner yang butuh WinRM untuk melakukannya. Anda akan membangun jalur baru memakai jalur yang sudah tidak ada.

convert dan assume: lebih sedikit unknown saat plan

Nilai yang baru diketahui setelah apply tampil sebagai known after apply di plan, dan beberapa fitur menolaknya saat planning, termasuk enabled, for_each, dan count. Fungsi baru ini memungkinkan module author memberi tahu OpenTofu apa yang tidak bisa ia simpulkan sendiri.

convert mendeklarasikan tipe, sehingga hasil yang unknown tetap punya bentuk yang diketahui. Keluarga assume mendeklarasikan properti nilai, sehingga perbandingan dan pengecekan bisa berjalan saat plan. Halaman referensi mencantumkan signature ini dan menyatakan hint tercakup dalam compatibility promise, dengan deteksi lebih awal bersifat best effort.

FungsiYang dijanjikanYang terbuka saat plan
assumenotnull(value)Nilai bukan null; error jika sebaliknyaPerbandingan dengan null menghasilkan boolean yang known, jika tipenya sudah known (pasangkan dengan convert jika belum)
assumestringprefix(string, expected_prefix)String diawali prefix tersebut; error jika sebaliknyaPerbandingan dengan string kosong dan pemanggilan startswith menghasilkan hasil yang known
assumeequal(actual_value, expected_value)Mengonversi ke tipe argumen kedua, mengecek kesamaan, mengembalikan argumen keduaModule bisa memprediksi nilai yang tidak bisa diprediksi provider, misalnya ARN dari input yang known
assumelistlength, assumesetlength, assumemaplengthPanjang berada dalam batas min dan max (inklusif)Pengecekan panjang menghasilkan hasil yang known; varian min dan max mengecek satu batas
convert(value, type)Nilai sesuai type constraintNilai unknown tetap punya bentuk yang known, sehingga akses atribut punya tipe yang known
# 1. convert: tell OpenTofu the SHAPE of a value it cannot see until apply.
locals {
  vendor = convert(
    jsondecode(something_dynamic.example.output_json),
    object({ id = string, tags = map(string) })
  )
  # local.vendor is still unknown, but local.vendor.id is known to be a string.
}

# 2. assume...: promise a property of the value, so downstream checks run at plan.
variable "vpc_id" {
  type = string

  validation {
    # Without the hint, an unknown vpc_id makes this rule wait for apply.
    condition     = startswith(var.vpc_id, "vpc-")
    error_message = "vpc_id must look like vpc-..."
  }
}

module "network_checks" {
  source = "./modules/network-checks"

  # Only safe because the provider documentation guarantees the prefix.
  vpc_id = assumenotnull(assumestringprefix(aws_vpc.example.id, "vpc-"))
}

Perhatikan urutan di contoh: assumenotnull membungkus assumestringprefix karena validation rule biasanya mengecek null lebih dulu. Referensi menyatakan assumenotnull hanya bekerja jika tipenya sudah known, dan itulah kasus yang ditutup oleh convert.

Dua experiment, dan cara menyalakannya

Linting dinyalakan per command dengan opsi lint. Post tentang linting mencantumkan empat rule bawaan di 1.13: core:no-type-variable, core:count-instead-enabled, core:unused-variable, dan core:unused-local. Post itu juga menyebut pendekatan lewat file konfigurasi direncanakan tetapi belum didefinisikan, jadi flag adalah satu-satunya jalur yang terdokumentasi saat ini.

# Every built-in rule, as warnings, on any of the three commands.
tofu validate -lint=all
tofu plan -lint=all

# Or pick rules by ID. These four are the ones the linting post says 1.13 ships.
tofu plan -lint=core:no-type-variable,core:count-instead-enabled,core:unused-variable,core:unused-local

Symbol Libraries adalah kumpulan function, type, dan constant yang bisa dipakai ulang dalam file berekstensi sym.hcl, diimpor dengan block symbols, dan diaktifkan lewat daftar experiments di konfigurasi project. Post pengantarnya menyebut library tidak bisa membaca state resource atau data maupun memakai provider function, meskipun nilai resource bisa dikirim sebagai argumen.

# project configuration: opt in to the experiment explicitly
language {
  experiments = [symbol_libraries]
}

# Import a directory of *.sym.hcl files under the label "lib".
symbols "lib" {
  source = "./example-lib"
}

# Functions and types: symbols::lib::<name>()    Constants: symbols.lib.<name>

Post Symbol Libraries menyebut tujuannya adalah stabil di 1.14 dan meminta feedback lewat GitHub discussion. Itu niat, bukan janji, jadi jauhkan library dari apa pun yang tidak bisa Anda tulis ulang.

Platform: Windows ARM64 masuk, 32-bit dan macOS lama keluar

Windows di ARM64 mendapat paket resmi, dan pengumuman menyebut sebagian besar build OpenTofu untuk provider cloud besar sudah punya paket windows_arm64. Maintainer provider pihak ketiga menentukan kebijakan platform sendiri, jadi satu provider yang belum ada bisa menghalangi runner Windows ARM64.

PlatformStatus di series 1.13Yang perlu dilakukan
Windows ARM64Paket resmi baruCek tiap provider menyediakan windows_arm64 sebelum memindahkan runner
386 dan arm (32-bit)Series terakhir; tofu init menampilkan warningMigrasi ke amd64 atau arm64; 1.14 tidak punya paket resmi untuk keduanya
macOS 13 Ventura atau lebih baruBatas minimum yang didukungVerifikasi laptop developer dan self-hosted Mac runner
macOS sebelum 13Bisa crash atau berperilaku salahJangan upgrade CLI di sana; ganti mesin atau OS

Warning 32-bit adalah yang diam-diam penting: runner ARM ala Raspberry Pi bisa tetap jalan sepanjang 1.13 lalu tidak punya jalur upgrade resmi.

Di mana ia bisa salah: hint yang berbohong dan experiment yang bergeser

Fungsi assume adalah janji, dan pengumuman eksplisit soal biaya melanggarnya. Jika Anda menjanjikan prefix vpc- lalu nilainya ternyata subnet-, pemanggilan gagal saat apply, yang lebih telat dan lebih menyakitkan daripada unknown yang digantikannya.

Pakai fungsi assume hanya jika dokumentasi provider atau vendor menjamin propertinya. Hint yang salah mengubah unknown saat plan menjadi kegagalan saat apply, bahkan mungkin di tengah sebuah perubahan.

  • Waktu deteksi bisa berbeda antar versi: masalah yang tertangkap saat plan di satu rilis bisa baru muncul saat apply di rilis lain, dan sebaliknya. Jangan membangun jaminan di atasnya.
  • Elemen bahasa Symbol Libraries digambarkan sebagai titik awal yang bisa berubah berdasarkan feedback.
  • Linting masih infrastruktur awal dengan empat rule; hasil bersih belum membuktikan banyak hal.
  • ignore_changes untuk base64gzip adalah utang. Jika dibiarkan, resource diam-diam berhenti melacak perubahan konten yang nyata.

Aturan saya: ambil fitur tambahan pelan-pelan dan penghapusan dengan serius. Kelompok pertama bisa menunggu satu rilis; kelompok kedua akan menggagalkan pipeline pada run pertama.

Yang dilakukan hari Senin

Semua ini tidak butuh proyek migrasi. Cukup satu sore dan satu branch.

  1. Cari di repository koneksi type winrm dan pemakaian base64gzip.
  2. Cek platform setiap runner dan laptop terhadap tabel di bagian enam.
  3. Upgrade di branch khusus dengan tofu init -upgrade dan simpan plan-nya.
  4. Pastikan satu-satunya perubahan berasal dari base64gzip; apply, atau pakai ignore_changes untuk satu rilis dan catat penghapusannya.
  5. Jalankan tofu validate dengan opsi lint pada satu module dan beri tahu project apa yang Anda temukan.
# 1. Find the three things that break before you touch the binary.
grep -rn 'type *= *"winrm"' --include='*.tf' .
grep -rn 'base64gzip' --include='*.tf' .
tofu version            # note the platform line: windows_386 / linux_arm / darwin on macOS < 13

# 2. Upgrade in a branch, then read the plan before anything else.
tofu init -upgrade
tofu plan -out=tfplan-1.13

# 3. Only base64gzip arguments should show as changes. Anything else is a real diff.
tofu show tfplan-1.13 | grep -B2 -A6 'base64gzip\|content_base64'

# 4. Try the linter on the module you know best.
tofu validate -lint=all

Perintah di bawah adalah jam pertama dari sore itu. Langkah tiga menjalankan grep pada plan tersimpan, itu kemudahan dan bukan jaminan, jadi tetap baca diff-nya.

Aturan yang dibawa: pada rilis OpenTofu yang ringan, catatan di bawah breaking changes adalah seluruh rilisnya. Perbaiki WinRM dan base64gzip dalam perubahan tersendiri, cek platform Anda, dan perlakukan convert, assume, linting, serta Symbol Libraries sebagai hal untuk dicoba di branch, bukan untuk dijadikan fondasi.

FAQ

Pertanyaan Umum

Jawaban singkat untuk pertanyaan yang paling sering diajukan pembaca tentang topik ini.

Apa yang baru di OpenTofu 1.13?

OpenTofu 1.13 menambah paket resmi Windows ARM64, fungsi convert dan assume yang mengurangi nilai unknown saat planning, opsi linting experimental, dan fitur Symbol Libraries experimental. Pengumuman menyebutnya rilis yang relatif ringan dan selaras dengan siklus rilis Go.

Apa yang rusak saat upgrade ke OpenTofu 1.13?

Empat hal: output base64gzip setara tetapi tidak identik byte per byte sehingga plan bisa menampilkan perubahan, WinRM dihapus untuk provisioner remote-exec dan file, macOS 13 atau lebih baru diwajibkan, dan ini series terakhir dengan build 32-bit. Cek masing-masing terhadap repository dan runner Anda sebelum upgrade.

Bagaimana menghentikan perubahan base64gzip muncul di plan setelah upgrade?

Review dulu perubahan yang diusulkan karena kontennya setara. Jika belum bisa di-apply, dokumentasi menyebut Anda bisa sementara memakai meta-argument ignore_changes untuk mempertahankan nilai lama, lalu menghapusnya saat siap memakai encoding baru.

Apa fungsi assume di OpenTofu?

Fungsi ini memungkinkan module author menjanjikan properti sebuah nilai yang baru diketahui setelah apply, misalnya tidak null atau punya prefix string tertentu. OpenTofu lalu bisa mengevaluasi pengecekan saat plan, tetapi jika janji itu salah pemanggilan gagal saat apply, jadi pakai hanya jika dokumentasi menjamin propertinya.

Sampai kapan OpenTofu 1.13 didukung?

Pengumuman menyebut series v1.13 mendapat security support sampai Agustus 2027. Ini juga series terakhir dengan paket 32-bit resmi, jadi rencanakan migrasi 386 atau arm jauh sebelum 1.14.