Condition & Loop #
Playbook yang hanya berjalan secara linear dari atas ke bawah tanpa variasi hanya berguna untuk skenario yang sangat sederhana. Di dunia nyata, kamu perlu task yang berjalan hanya dalam kondisi tertentu — install package A hanya di Ubuntu, skip task tertentu jika service sudah berjalan — dan task yang mengulang aksi untuk banyak item. when dan loop adalah dua mekanisme Ansible untuk menangani kebutuhan ini.
Kondisi dengan when #
when adalah kondisi yang menentukan apakah sebuah task akan dieksekusi. Task hanya dijalankan jika kondisi when bernilai true:
- name: Install paket khusus Ubuntu
apt:
name: ubuntu-advantage-tools
state: present
when: ansible_distribution == "Ubuntu" # Hanya jalan di Ubuntu
- name: Install paket khusus RHEL
dnf:
name: rhel-system-roles
state: present
when: ansible_distribution == "RedHat" # Hanya jalan di RHEL
Kondisi dalam when adalah ekspresi Jinja2 yang dievaluasi menjadi true atau false. Kamu bisa menggunakan semua variabel Ansible yang tersedia — facts, variabel inventory, variabel yang di-register dari task sebelumnya.
Kondisi Berbasis Facts #
Facts yang dikumpulkan Ansible menyediakan informasi lengkap tentang managed node — sistem operasi, versi kernel, arsitektur, jumlah memori, dan banyak lagi:
# Kondisi berdasarkan OS
- name: Install nginx (Debian-based)
apt:
name: nginx
state: present
when: ansible_os_family == "Debian"
- name: Install nginx (RedHat-based)
dnf:
name: nginx
state: present
when: ansible_os_family == "RedHat"
# Kondisi berdasarkan versi OS
- name: Aktifkan fitur yang hanya ada di Ubuntu 22.04+
command: /opt/app/enable-new-feature
when:
- ansible_distribution == "Ubuntu"
- ansible_distribution_major_version | int >= 22
# Kondisi berdasarkan memori
- name: Aktifkan swap (hanya untuk server dengan RAM < 2GB)
command: /usr/local/bin/setup-swap.sh
when: ansible_memtotal_mb < 2048
Kondisi Kompleks: AND, OR, NOT #
Kondisi when mendukung operator logika untuk ekspresi yang lebih kompleks:
# AND — semua kondisi harus terpenuhi (gunakan list)
- name: Deploy konfigurasi khusus
template:
src: special.conf.j2
dest: /etc/app/special.conf
when:
- env == "production" # Kondisi 1
- ansible_distribution == "Ubuntu" # Kondisi 2
- app_version | version_compare('2.0', '>=') # Kondisi 3
# Semua tiga kondisi harus true
# OR — salah satu kondisi terpenuhi
- name: Restart service untuk distro tertentu
systemd:
name: myapp
state: restarted
when: ansible_distribution == "Ubuntu" or ansible_distribution == "Debian"
# NOT — kondisi kebalikan
- name: Skip setup monitoring di environment dev
include_tasks: setup-monitoring.yml
when: env != "development"
# Kombinasi AND dan OR
- name: Task khusus untuk production Ubuntu atau staging RedHat
command: /opt/app/special-setup
when: >
(env == "production" and ansible_os_family == "Debian") or
(env == "staging" and ansible_os_family == "RedHat")
Kondisi Berbasis Hasil Task Sebelumnya #
Hasil task yang disimpan dengan register sangat sering digunakan sebagai kondisi:
- name: Cek apakah file konfigurasi lama ada
stat:
path: /etc/app/old-config.conf
register: old_config
- name: Backup konfigurasi lama jika ada
copy:
src: /etc/app/old-config.conf
dest: /etc/app/old-config.conf.bak
remote_src: true
when: old_config.stat.exists # Jalankan hanya jika file ada
- name: Cek apakah database sudah diinisialisasi
command: psql -U postgres -c "SELECT tablename FROM pg_tables WHERE schemaname='public'"
register: db_tables
changed_when: false
- name: Inisialisasi database jika kosong
command: python manage.py migrate
when: db_tables.stdout_lines | length == 0
Loop Dasar #
Saat kamu perlu menjalankan task yang sama untuk beberapa item, gunakan loop:
# Tanpa loop — repetitif dan sulit di-maintain
- name: Install nginx
apt:
name: nginx
state: present
- name: Install postgresql
apt:
name: postgresql
state: present
- name: Install redis
apt:
name: redis-server
state: present
# Dengan loop — lebih bersih
- name: Install semua package yang diperlukan
apt:
name: "{{ item }}"
state: present
loop:
- nginx
- postgresql
- redis-server
Loop dengan Dictionary #
Loop bisa mengiterasi atas list of dictionaries untuk task yang membutuhkan beberapa parameter per item:
- name: Buat beberapa user sistem
user:
name: "{{ item.name }}"
groups: "{{ item.groups }}"
shell: "{{ item.shell | default('/bin/bash') }}"
state: present
loop:
- name: deployer
groups: sudo
shell: /bin/bash
- name: monitor
groups: monitoring
shell: /bin/false
- name: backup
groups: backup
- name: Buat beberapa direktori dengan permission berbeda
file:
path: "{{ item.path }}"
state: directory
owner: "{{ item.owner }}"
mode: "{{ item.mode }}"
loop:
- path: /opt/app
owner: deployer
mode: "0755"
- path: /var/log/app
owner: deployer
mode: "0755"
- path: /etc/app/secrets
owner: root
mode: "0700"
loop_control: Label yang Lebih Informatif #
Secara default, output loop menampilkan seluruh nilai item yang bisa panjang dan sulit dibaca. Gunakan loop_control untuk menampilkan label yang lebih bersih:
- name: Deploy konfigurasi per virtual host
template:
src: "templates/vhost.conf.j2"
dest: "/etc/nginx/sites-available/{{ item.domain }}.conf"
loop:
- domain: app.example.com
port: 8080
upstream: app-backend
- domain: api.example.com
port: 8081
upstream: api-backend
loop_control:
label: "{{ item.domain }}" # Tampilkan hanya domain, bukan seluruh dict
# Output dengan loop_control:
# TASK [Deploy konfigurasi per virtual host] *****
# changed: [web-01] => (item=app.example.com)
# changed: [web-01] => (item=api.example.com)
# Output tanpa loop_control (lebih berantakan):
# changed: [web-01] => (item={'domain': 'app.example.com', 'port': 8080, ...})
Kombinasi Loop dan when #
Loop dan when bisa dikombinasikan — kondisi dievaluasi untuk setiap iterasi:
- name: Install optional features berdasarkan konfigurasi
apt:
name: "{{ item.package }}"
state: present
loop:
- package: nginx
enabled: true
- package: varnish
enabled: false # Package ini akan di-skip
- package: redis-server
enabled: true
when: item.enabled # Jalankan hanya untuk item dengan enabled: true
Ringkasan #
whenmenentukan apakah task dieksekusi — kondisi dievaluasi sebagai ekspresi Jinja2.- Gunakan list untuk kondisi AND (semua harus terpenuhi), operator
oruntuk kondisi OR, dannotuntuk negasi.- Facts (
ansible_distribution,ansible_os_family, dll.) adalah sumber kondisi yang paling umum — tersedia di semua managed node.- Hasil task yang disimpan dengan
registerbisa digunakan sebagai kondisi untuk task berikutnya.loopuntuk mengulang task terhadap banyak item — lebih bersih dari task yang diulang secara manual.- Loop bisa mengiterasi list of dictionaries untuk task yang membutuhkan beberapa parameter per item.
loop_control.labeluntuk menampilkan output yang lebih bersih saat menggunakan loop dengan dictionary kompleks.whendi dalam loop dievaluasi per item — kamu bisa skip item tertentu berdasarkan nilai propertinya.
← Sebelumnya: Notify & Listen Berikutnya: Scope & Precedence →