Menulis cookbook yang benar: idempotency ketat, desain resource deklaratif, dependency dan versioning lewat metadata, modularity, serta test-driven infrastructure dengan InSpec dan Test Kitchen.

Di episode 14 kalian mengotomasi bootstrap node di cloud dengan Terraform dan cloud-init. Semakin banyak otomasi, semakin besar tuntutan terhadap kualitas cookbook — cookbook yang asal-asalan akan merusak environment dalam sekali run. Di episode 15 ini kita membahas best practice: mendesain cookbook yang idempoten, modular, dan teruji, plus test-driven infrastructure dengan InSpec dan Test Kitchen.
Tujuan episode ini:
Idempotency adalah kemampuan menjalankan ulang tanpa mengubah hasil akhir. Resource seperti package, template, dan service sudah idempoten secara desain — mereka hanya bertindak jika keadaan menyimpang dari desired state. Yang sering bermasalah adalah execute: ia selalu jalan setiap run kecuali kita beri guard.
execute "initialize app database" do
command "myapp-db init --force"
not_if "myapp-db status"
endImportant
Aturan sederhana: setiap execute tanpa guard dianggap bug. Selalu sediakan not_if atau only_if yang mendeteksi apakah pekerjaan sudah selesai.
package, bukan execute apt-get install.template, cookbook_file, atau file — bukan script yang menulis file secara manual.| Tujuan | Resource yang benar | Resource yang salah |
|---|---|---|
| Instal paket | package | execute "apt-get install" |
| Tulis file | template atau file | execute "echo > file" |
| Jalankan layanan | service | execute "systemctl restart" |
Semua ketergantungan cookbook dideklarasikan di metadata.rb dengan batas versi. Ini memungkinkan resolver (Berkshelf atau Policyfile) menghitung grafik dependency secara deterministik.
name "my_app"
version "1.2.0"
depends "apt", ">= 6.0.0"
depends "chef-vault", ">= 3.0.0"Cookbook diberi versi semver di metadata.rb. Rilis menaikkan versi, dipin di lockfile seperti Policyfile.lock.json, dan didistribusikan lewat Supermarket pribadi.
Modularity berarti memecah tanggung jawab:
include_recipe "nginx::default"
node.override["nginx"]["worker_processes"] = 8Prinsip TDD: tulis ekspektasi dulu, lalu bangun konfigurasi agar ekspektasi itu terpenuhi. Di Chef, pasangannya adalah InSpec untuk assertion dan Test Kitchen untuk menjalankan cookbook di environment sementara. Test konvensional diletakkan di test/integration/ dalam cookbook:
control "nginx_is_installed" do
describe package("nginx") do
it { should be_installed }
end
end
control "nginx_is_running" do
describe service("nginx") do
it { should be_running }
it { should be_enabled }
end
endSiklus pengembangan dengan Kitchen:
kitchen converge — terapkan cookbook ke VM atau kontainer.kitchen verify — jalankan test; seharusnya gagal dulu.kitchen destroy — bersihkan environment.Tip
Jalankan kitchen test untuk memicu seluruh siklus create, converge, verify, destroy dalam satu perintah — pasangan yang sempurna untuk pipeline CI.
Pada episode 15 ini kalian mempelajari best practice penulisan cookbook: idempotency ketat dengan guard, desain resource yang deklaratif, dependency dan versioning lewat metadata, modularity lewat pemisahan cookbook, serta siklus test-driven infrastructure dengan InSpec dan Test Kitchen.
Inti yang harus dibawa pulang:
execute wajib ber-guard.Di episode 16 berikutnya kita melampaui resource bawaan: Custom Resources & Libraries — membuat resource sendiri dengan DSL custom resource, memahami LWRP dan HWRP, serta menulis helper dan handler yang meng-hook siklus chef-client run. Sampai jumpa di episode 16!