Parameterized #
Ada kalanya kamu perlu menjalankan role yang sama lebih dari sekali dalam satu playbook, tapi dengan konfigurasi yang berbeda. Misalnya: mendeploy dua virtual host nginx dengan domain berbeda, atau menginisialisasi tiga database PostgreSQL dengan nama berbeda, atau menjalankan beberapa instance aplikasi di port yang berbeda. Ini adalah parameterized role — menggunakan satu role dengan berbagai set parameter.
Masalah: Role Bawaan Hanya Jalan Sekali #
Secara default, Ansible menjalankan role yang sama hanya sekali per play karena deduplication. Jika kamu memanggil role yang sama dua kali dengan variabel berbeda, hanya yang pertama yang dieksekusi:
# ANTI-PATTERN: role yang sama dua kali — hanya yang pertama berjalan
- hosts: webservers
roles:
- role: nginx_vhost
vars:
vhost_domain: app.example.com # Ini dijalankan
vhost_port: 8080
- role: nginx_vhost # Ini DIABAIKAN karena deduplication
vars:
vhost_domain: api.example.com
vhost_port: 8081
Solusi 1: allow_duplicates di meta/main.yml #
Cara pertama adalah mengizinkan role dijalankan berkali-kali dari meta-nya:
# roles/nginx_vhost/meta/main.yml
---
allow_duplicates: true # Izinkan role ini dijalankan lebih dari sekali
dependencies: []
# playbook.yml — sekarang kedua pemanggilan dieksekusi
- hosts: webservers
roles:
- role: nginx_vhost
vars:
vhost_domain: app.example.com
vhost_port: 8080
- role: nginx_vhost
vars:
vhost_domain: api.example.com
vhost_port: 8081
Solusi 2: include_role dalam Loop #
Cara yang lebih elegan untuk multi-instance adalah menggunakan include_role di dalam loop:
- hosts: webservers
vars:
virtual_hosts:
- domain: app.example.com
port: 8080
upstream: app-backend
ssl: true
- domain: api.example.com
port: 8081
upstream: api-backend
ssl: true
- domain: admin.example.com
port: 8082
upstream: admin-backend
ssl: false
tasks:
- name: Setup virtual host untuk setiap aplikasi
include_role:
name: nginx_vhost
vars:
vhost_domain: "{{ item.domain }}"
vhost_port: "{{ item.port }}"
vhost_upstream: "{{ item.upstream }}"
vhost_ssl_enabled: "{{ item.ssl }}"
loop: "{{ virtual_hosts }}"
loop_control:
label: "{{ item.domain }}"
Pola ini jauh lebih scalable — untuk menambah virtual host baru, cukup tambahkan item ke list virtual_hosts.
Pola Multi-Instance Database #
Contoh lain yang sangat umum: menginisialisasi beberapa database untuk aplikasi yang berbeda:
- hosts: dbservers
vars:
databases:
- name: app_production
user: app_user
password: "{{ vault_app_db_password }}"
encoding: UTF8
- name: analytics_production
user: analytics_user
password: "{{ vault_analytics_db_password }}"
encoding: UTF8
- name: queue_production
user: queue_user
password: "{{ vault_queue_db_password }}"
encoding: UTF8
tasks:
- name: Inisialisasi setiap database
include_role:
name: postgresql_database
vars:
db_name: "{{ item.name }}"
db_user: "{{ item.user }}"
db_password: "{{ item.password }}"
db_encoding: "{{ item.encoding }}"
loop: "{{ databases }}"
loop_control:
label: "{{ item.name }}"
Validasi Parameter di dalam Role #
Role yang diparameterisasi harus memvalidasi bahwa semua parameter yang diperlukan telah disediakan dengan nilai yang valid:
# roles/nginx_vhost/tasks/main.yml
---
- name: Validasi parameter yang wajib ada
assert:
that:
- vhost_domain is defined
- vhost_domain | length > 0
- vhost_port is defined
- vhost_port | int > 0
- vhost_port | int < 65536
fail_msg: >
Parameter tidak valid untuk role nginx_vhost!
Pastikan vhost_domain dan vhost_port sudah di-set.
Contoh: vhost_domain=app.example.com, vhost_port=8080
- name: Import task konfigurasi virtual host
import_tasks: configure.yml
- name: Import task setup SSL (jika diaktifkan)
import_tasks: ssl.yml
when: vhost_ssl_enabled | default(false)
Menyimpan State antar Iterasi #
Saat menggunakan include_role dalam loop, kadang kamu perlu mengakses hasil dari iterasi sebelumnya. Gunakan set_fact dengan nama yang unik per iterasi:
- name: Setup virtual host dan simpan status
include_role:
name: nginx_vhost
vars:
vhost_domain: "{{ item.domain }}"
vhost_port: "{{ item.port }}"
loop: "{{ virtual_hosts }}"
register: vhost_results
- name: Tampilkan ringkasan semua virtual host yang di-setup
debug:
msg: >
Virtual host setup selesai:
{% for result in vhost_results.results %}
- {{ result.item.domain }}:{{ result.item.port }}
{% endfor %}
Ringkasan #
- Secara default, Ansible hanya menjalankan role yang sama sekali per play karena deduplication — gunakan
allow_duplicates: trueatauinclude_roleuntuk menjalankannya berkali-kali.include_roledalam loop adalah pola paling scalable untuk multi-instance — tambahkan item ke list untuk menambah instance baru.- Definisikan semua konfigurasi instance sebagai list of dictionaries di variabel — membuat playbook mudah dibaca dan dikelola.
- Validasi parameter di awal role dengan
assert— lebih baik gagal cepat dengan pesan yang jelas daripada gagal di tengah eksekusi.include_rolebersifat dinamis (diproses saat eksekusi), berbeda dariroles:di play level yang bersifat statis — ini membuatinclude_rolemendukung loop dan kondisi.