# Impor Infrastruktur yang Sudah Ada ke Terraform Tanpa Menulis HCL Manual

> Bagaimana import block Terraform dan flag -generate-config-out mengubah pekerjaan manual yang menyakitkan menjadi alur kerja config-driven yang bisa direview — plus batasan yang masih menggigit.

URL: https://www.matthewswong.com/id/blog/terraform-import-blocks-existing-infra/

- Author: Matthews Wong (https://www.matthewswong.com/id/about/)
- Published: 2026-07-11
- Updated: 2026-07-11
- Category: DevOps

> **Key takeaway:** Terraform 1.5 menambahkan import block: impor deklaratif yang Anda tulis di konfigurasi, lihat di terraform plan, dan review seperti perubahan kode lainnya. Pasangkan dengan flag -generate-config-out dan Terraform menulis HCL tebakan-terbaik untuk tiap resource yang diimpor, sehingga Anda memperbaiki draf alih-alih menulis tiap argumen manual dari nol.

Hampir setiap pekerjaan infrastruktur yang saya ambil dimulai dengan masalah yang sama: sesuatu sudah ada. Load balancer yang dibuat lewat konsol dua tahun lalu, database yang dibuat saat insiden, zona DNS yang tidak ada yang ingat pernah menyentuhnya. Terraform paling senang dengan greenfield, tapi kenyataan hidup adalah brownfield. Pertanyaannya bukan apakah harus membawa infrastruktur yang sudah ada ke Terraform — tapi berapa banyak rasa sakit yang dibebankan migrasi itu.

Selama bertahun-tahun jawabannya adalah: banyak. Perintah CLI terraform import lama hanya menulis resource ke dalam state — tidak pernah menghasilkan konfigurasi yang cocok. Anda mengimpor resource, lalu menulis HCL manual, lalu menjalankan plan dan berdoa diff kembali kosong. Untuk apa pun yang lebih dari segelintir resource, loop itu melelahkan dan rawan kesalahan. Sejak Terraform 1.5, import block plus flag -generate-config-out mengubah bentuk pekerjaan itu sepenuhnya.

## Cara lama dan mengapa itu menyakitkan

Impor CLI klasik bersifat imperatif: Anda menjalankan perintah, ia langsung memutasi state, dan tidak meninggalkan jejak di konfigurasi atau pull request Anda. Dua masalah muncul dari situ. Pertama, tidak ada yang bisa direview — rekan tim tidak bisa melihat di diff apa yang Anda impor. Kedua, Anda tetap harus menulis sendiri setiap argumen resource, mencocokkan apa pun yang sebenarnya dimiliki penyedia cloud, atau plan berikutnya menampilkan perubahan destruktif.

## Import block: impor yang config-driven

Import block adalah blok Terraform biasa yang Anda commit ke file .tf. Ia menamai alamat resource tempat objek yang diimpor akan berada (argumen to) dan ID spesifik-penyedia dari objek yang sudah ada (argumen id). Karena ia berada di konfigurasi Anda, ia muncul di terraform plan, melewati code review, dan tidak ada yang menyentuh state sampai terraform apply. Itulah keseluruhan pergeserannya: impor menjadi deklaratif dan bisa direview alih-alih perintah konsol sekali pakai.

> Simpan import block di file khusus seperti imports.tf. Mereka adalah scaffolding sekali pakai — begitu apply mendarat dan resource masuk ke state, blok tersebut tidak melakukan apa pun pada plan berikutnya dan Anda bisa menghapusnya di PR lanjutan. Mengelompokkannya membuat pembersihan itu menjadi perubahan satu file.

## -generate-config-out: berhenti menulis HCL manual

Import block sendirian masih mengasumsikan blok resource yang cocok sudah ada. Keajaibannya adalah flag -generate-config-out, diperkenalkan bersama import block di Terraform 1.5 dan masih berlabel eksperimental. Arahkan terraform plan ke path file baru dan Terraform membaca objek live untuk setiap import block yang belum punya resource cocok, lalu menulis HCL dengan tebakan terbaiknya untuk tiap argumen. Anda mendapat scaffold, bukan modul jadi — tapi scaffold lebih baik daripada file kosong.

1. Tulis import block untuk resource yang Anda inginkan, dengan alamat to dan id yang benar.
2. Jalankan terraform plan -generate-config-out=generated.tf terhadap path file yang baru.
3. Baca HCL yang dihasilkan, hapus argumen read-only dan default, lalu refactor nama.
4. Jalankan terraform plan lagi sampai diff kosong — tanpa create, tanpa destroy.
5. terraform apply untuk meng-commit objek ke state, lalu hapus import block.

## HCL yang dihasilkan adalah draf, bukan hasil akhir

Jangan commit output -generate-config-out tanpa disentuh. Terraform cenderung ke arah kelengkapan, jadi ia memancarkan atribut read-only, nilai computed, dan default yang mengacaukan file atau justru merusak plan. Dokumentasinya menyebut contoh konkret: ia bisa menghasilkan baik ipv6_address_count maupun ipv6_addresses pada sebuah instance meski kedua argumen itu berkonflik, menghasilkan HCL yang tidak akan lolos validasi. Perlakukan file itu sebagai draf pertama yang Anda bersihkan.

- Hapus argumen yang ditandai penyedia sebagai read-only atau computed (ID, ARN, timestamp).
- Hapus default yang menambah kebisingan, agar konfigurasi menyatakan maksud, bukan tiap tombol.
- Ganti ID hard-coded dengan referensi ke resource lain atau variabel jika memungkinkan.
- Ganti label resource ke konvensi Anda — nama yang dihasilkan hanyalah alamat to.

> -generate-config-out punya batasan nyata. Ia tidak bisa menghasilkan config untuk import block yang menggunakan for_each, atau untuk resource yang menggunakan for_each atau count, dan ia tidak bekerja dengan remote backend atau HCP Terraform karena harus menulis ke filesystem lokal. Terraform 1.7 menambahkan dukungan for_each pada import block itu sendiri, tapi generasi config untuk instance tersebut masih belum tercakup — generate terhadap alamat top-level biasa dulu, lalu refactor ke koleksi Anda secara manual.

## Alur kerja yang menskala melampaui segelintir resource

Pada migrasi baru-baru ini saya punya beberapa lusin objek untuk dibawa masuk lintas satu penyedia. Pola yang berhasil: enumerasi ID nyata dengan CLI penyedia, buat template satu import block per ID ke imports.tf, lalu jalankan satu pass generate. Anda mereview file yang dihasilkan dalam satu duduk, membersihkannya, dan mendaratkannya sebagai satu PR yang bisa direview — jauh lebih baik daripada loop shell dari perintah terraform import yang tidak bisa diaudit siapa pun setelahnya.

| Aspek | terraform import (CLI) | import block + generate-config-out |
| --- | --- | --- |
| Gaya | Imperatif, langsung berjalan | Deklaratif, diterapkan saat apply |
| Bisa direview di PR | Tidak — tak meninggalkan jejak config | Ya — muncul di plan dan diff |
| Menghasilkan config | Tidak pernah — hanya state | Ya — draf HCL tebakan terbaik |
| Impor massal | Satu perintah per resource | Banyak blok, satu pass plan |
| for_each / count | Manual, per instance | Blok dukung for_each (1.7+); gen tidak |
| Remote backend / HCP | Berfungsi | generate-config-out perlu FS lokal |

## Jebakan yang terus saya temui

- Path output harus baru. Terraform error alih-alih menimpa file yang ada — hapus generated.tf antar-run.
- Mendapatkan id yang benar bersifat spesifik-penyedia. Bucket S3 pakai namanya, instance EC2 pakai instance ID-nya, record route53 pakai string komposit — cek dokumen impor resource tersebut.
- Generasi config masih eksperimental; format HCL persisnya bisa berubah antar-versi minor, jadi review ulang setelah upgrade.
- Impor ke modul atau instance for_each? Generate terhadap alamat top-level dulu, lalu pindahkan HCL yang sudah dibersihkan ke modul secara manual.

> Kemenangan sejatinya bukan hemat ketikan — tapi auditabilitas. Impor menjadi pull request yang bisa direview, disetujui, dan di-rollback tim Anda, dengan config yang dihasilkan sebagai titik awal. Perubahan tunggal itu memindahkan impor infrastruktur brownfield dari pekerjaan konsol menakutkan menjadi bagian normal dan membosankan dari alur kerja IaC saya.

## Sources

- Terraform Docs — Import: Generating Configuration
- Terraform Docs — Import resources overview
- HashiCorp Blog — Terraform 1.5 brings config-driven import and checks

## Source links

- https://developer.hashicorp.com/terraform/language/import/generating-configuration
- https://developer.hashicorp.com/terraform/language/import
- https://www.hashicorp.com/en/blog/terraform-1-5-brings-config-driven-import-and-checks

## FAQ

### Apa perbedaan antara perintah terraform import dan import block?

Perintah CLI terraform import bersifat imperatif: ia langsung menulis resource ke dalam state dan tidak menghasilkan konfigurasi, tanpa meninggalkan jejak di kode Anda. Import block bersifat deklaratif — Anda commit ke file .tf, ia muncul di terraform plan, melewati code review, dan tidak ada yang berubah di state sampai terraform apply. Import block ditambahkan di Terraform 1.5.

### Apa fungsi flag -generate-config-out di Terraform?

Saat Anda menjalankan terraform plan -generate-config-out=file.tf, Terraform membaca setiap objek yang sudah ada yang dirujuk oleh import block tanpa resource cocok, lalu menulis HCL dengan tebakan terbaiknya untuk tiap argumen ke file itu. Ia memberi Anda scaffold konfigurasi resource alih-alih file kosong, sehingga Anda memperbaiki draf daripada menulis semuanya manual. Diperkenalkan di Terraform 1.5 dan masih eksperimental.

### Bisakah saya memakai -generate-config-out dengan for_each atau count?

Tidak. Generasi config tidak bisa dipakai dengan import block yang menggunakan for_each, atau dengan resource yang menggunakan for_each atau count, dan tidak berfungsi untuk resource di dalam modul yang belum ada. Terraform 1.7 menambahkan dukungan for_each pada import block itu sendiri, tapi generasi config untuk instance tersebut masih belum tercakup. Generate terhadap alamat resource top-level biasa dulu, lalu refactor HCL yang sudah dibersihkan ke koleksi atau modul Anda secara manual.

### Mengapa terraform plan error saat saya memakai -generate-config-out?

Penyebab paling umum adalah mengarahkan flag ke file yang sudah ada — Terraform menolak menimpanya dan error, jadi hapus file yang dihasilkan antar-run. Ia juga gagal dengan remote backend atau HCP Terraform karena flag harus menulis ke filesystem lokal. Terakhir, config yang dihasilkan bisa memuat argumen berkonflik (misalnya ipv6_address_count dan ipv6_addresses bersamaan) yang gagal validasi sampai Anda menyuntingnya.

### Apakah saya harus menyimpan import block di konfigurasi Terraform selamanya?

Tidak. Import block adalah scaffolding sekali pakai. Begitu terraform apply meng-commit objek ke state, blok tersebut tidak melakukan apa pun pada plan berikutnya, jadi Anda bisa menghapusnya dengan aman di pull request lanjutan. Menyimpannya di file khusus seperti imports.tf membuat pembersihan itu menjadi perubahan satu file.

---

- HTML version: https://www.matthewswong.com/id/blog/terraform-import-blocks-existing-infra/
- English: https://www.matthewswong.com/en/blog/terraform-import-blocks-existing-infra/
- Site index for agents: https://www.matthewswong.com/llms.txt
- Sitemap: https://www.matthewswong.com/sitemap.xml
- API description (OpenAPI): https://www.matthewswong.com/openapi.json
