Parameterized

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: true atau include_role untuk menjalankannya berkali-kali.
  • include_role dalam 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_role bersifat dinamis (diproses saat eksekusi), berbeda dari roles: di play level yang bersifat statis — ini membuat include_role mendukung loop dan kondisi.

← Sebelumnya: Reusability   Berikutnya: Versioning →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact