Operation #
Setiap resource dalam konfigurasi Terraform akan mengalami salah satu dari lima operasi: create, read, update, delete, atau replace. Terraform memutuskan operasi mana yang tepat berdasarkan perbandingan antara konfigurasi, state, dan kondisi aktual di cloud. Memahami logika di balik keputusan ini — termasuk mengapa kadang update bisa berubah jadi replace — membantumu menulis konfigurasi yang lebih terprediksi dan menghindari kejutan saat apply.
Lima Operasi Resource #
CREATE (+)
Kondisi: Resource ada di konfigurasi, tidak ada di state
Tindakan: Terraform memanggil API provider untuk membuat resource baru
Simbol di plan: +
READ (<=)
Kondisi: Data source dibaca
Tindakan: Terraform query data dari provider, tidak ada perubahan infrastruktur
Simbol di plan: <=
UPDATE IN-PLACE (~)
Kondisi: Resource ada di konfigurasi dan state, tapi konfigurasi berbeda
DAN provider mendukung update in-place untuk atribut yang berubah
Tindakan: Terraform memanggil API update — resource tetap running
Simbol di plan: ~
DELETE (-)
Kondisi: Resource ada di state, tidak ada di konfigurasi
Tindakan: Terraform memanggil API provider untuk menghapus resource
Simbol di plan: -
REPLACE (-/+)
Kondisi: Resource perlu diupdate TAPI perubahan tersebut
tidak bisa dilakukan in-place (provider tidak mendukung)
Tindakan: Delete resource lama, create resource baru
Simbol di plan: -/+ (atau +/- jika create_before_destroy aktif)
Bagaimana Terraform Memilih Operasi #
Keputusan apakah suatu perubahan bisa dilakukan in-place atau harus replace ditentukan oleh provider, bukan Terraform core.
# Setiap argumen resource punya sifat yang didefinisikan provider:
# - "updatable" → perubahan memicu UPDATE in-place
# - "forces new resource" → perubahan memicu REPLACE
resource "aws_instance" "web" {
ami = var.ami_id # forces new resource — tidak bisa diganti in-place
instance_type = var.type # updatable — bisa diganti in-place (dengan stop/start)
tags = {
Name = "web" # updatable — bisa diubah tanpa restart instance
}
root_block_device {
volume_size = 30 # forces new resource di beberapa kondisi
}
}
# Plan output memberitahu kamu atribut mana yang forces replacement:
# -/+ resource "aws_instance" "web" {
# ~ ami = "ami-OLD" -> "ami-NEW" # forces replacement
# id = "i-0abcdef1234567890"
# }
#
# Tanda "# forces replacement" atau "forces new resource"
# muncul di samping atribut yang menyebabkan replace
Import: Mengambil Alih Resource yang Sudah Ada #
Salah satu operasi penting yang sering dibutuhkan saat migrasi ke Terraform adalah import — mengambil alih pengelolaan resource yang sudah ada di cloud tanpa harus menghapus dan membuat ulang.
# Format: terraform import <resource_address> <resource_id>
# Import EC2 instance yang sudah ada
terraform import aws_instance.web i-0abcdef1234567890
# Import VPC yang sudah ada
terraform import aws_vpc.main vpc-0abcdef1234567890
# Import S3 bucket
terraform import aws_s3_bucket.assets my-existing-bucket
# Import resource di dalam module
terraform import module.vpc.aws_vpc.main vpc-0abcdef1234567890
# Sebelum import, kamu harus sudah punya blok resource yang kosong
# (atau dengan konfigurasi yang kamu inginkan)
# Langkah 1: Buat blok resource (bisa kosong dulu)
resource "aws_instance" "web" {
# Isi ini setelah import, berdasarkan output terraform state show
}
# Langkah 2: Import
# terraform import aws_instance.web i-0abcdef1234567890
# Langkah 3: Lihat kondisi aktual di state
# terraform state show aws_instance.web
# Langkah 4: Lengkapi konfigurasi berdasarkan kondisi aktual
resource "aws_instance" "web" {
ami = "ami-0abcdef1234567890" # dari state show
instance_type = "t3.micro" # dari state show
subnet_id = "subnet-0abcdef" # dari state show
}
# Langkah 5: Jalankan plan — seharusnya "No changes"
# terraform plan
Import dengan Blok import (Terraform 1.5+) #
Sejak Terraform 1.5, ada cara yang lebih deklaratif untuk melakukan import menggunakan blok import dalam konfigurasi.
# Blok import bisa di-commit ke version control
# dan dieksekusi sebagai bagian dari terraform apply
import {
to = aws_instance.web
id = "i-0abcdef1234567890"
}
resource "aws_instance" "web" {
ami = "ami-0abcdef1234567890"
instance_type = "t3.micro"
subnet_id = aws_subnet.public.id
}
# Terraform 1.5+ juga bisa generate konfigurasi otomatis:
# terraform plan -generate-config-out=generated.tf
# Menghasilkan file .tf dengan konfigurasi berdasarkan kondisi aktual
Moved Block: Rename Resource Tanpa Destroy #
Saat kamu ingin mengganti nama resource di konfigurasi, Terraform secara default akan menghapus yang lama dan membuat yang baru. Blok moved mencegah ini.
# MASALAH: Rename resource menyebabkan destroy + create
# Sebelum:
resource "aws_instance" "web" { ... }
# Sesudah rename:
resource "aws_instance" "web_server" { ... }
# Plan: -aws_instance.web + aws_instance.web_server → DESTROY + CREATE!
# SOLUSI: Gunakan blok moved
moved {
from = aws_instance.web
to = aws_instance.web_server
}
resource "aws_instance" "web_server" {
ami = var.ami_id
instance_type = "t3.micro"
}
# Plan: aws_instance.web moved to aws_instance.web_server
# → TIDAK ada destroy, tidak ada create
# moved juga berguna saat refactoring ke module
moved {
from = aws_vpc.main
to = module.networking.aws_vpc.main
}
Tainted Resource #
Resource yang ditandai “tainted” oleh Terraform berarti resource tersebut dianggap rusak dan perlu di-replace pada apply berikutnya.
# Tandai resource sebagai tainted (akan di-replace saat apply)
terraform taint aws_instance.web
# Hapus taint jika kamu berubah pikiran
terraform untaint aws_instance.web
# Cek resource yang tainted di state
terraform state list # Resource tainted ditandai dengan (tainted)
# Kasus di mana resource otomatis tainted:
# - Provisioner gagal saat create
# - Resource dibuat tapi berada dalam kondisi error
resource "aws_instance" "web" {
ami = var.ami_id
instance_type = "t3.micro"
provisioner "remote-exec" {
inline = ["sudo apt update && sudo apt install -y nginx"]
connection {
type = "ssh"
user = "ubuntu"
host = self.public_ip
}
}
# Jika provisioner gagal, instance ini otomatis tainted
# terraform apply berikutnya akan destroy + recreate instance ini
}
Ringkasan #
- Lima operasi: create
+, read<=, update in-place~, delete-, replace-/+— Terraform memilih berdasarkan perbandingan konfigurasi, state, dan kondisi aktual.- Apakah update atau replace ditentukan oleh provider, bukan Terraform core — cek dokumentasi provider untuk tahu atribut mana yang “forces new resource”.
terraform importuntuk mengambil alih resource existing tanpa destroy — wajib ada blok resource dulu sebelum import dilakukan.- Blok
importdeklaratif (Terraform 1.5+) lebih clean dari perintah CLI dan bisa di-commit ke version control.- Blok
moveduntuk rename resource atau refactoring ke module tanpa menyebabkan destroy + create.- Tainted resource adalah resource yang dianggap rusak dan akan di-replace pada apply berikutnya — bisa ditandai manual atau otomatis saat provisioner gagal.