Ansible when statement ใช้กำหนดเงื่อนไขให้ task รันเฉพาะเมื่อตรงตามที่ต้องการ — เช่น รันเฉพาะบน Ubuntu, เฉพาะเมื่อไฟล์ยังไม่มี, หรือเฉพาะเมื่อ variable มีค่าที่กำหนด ทำให้ Playbook ทำงานได้บนหลาย OS หรือหลาย environment โดยใช้ไฟล์เดียว
บทความนี้ครอบคลุม syntax พื้นฐานของ when, การใช้ facts ตรวจ OS, การรวมเงื่อนไขด้วย and/or, การใช้ร่วมกับ register, การตรวจ variable และ pattern สำหรับ multi-OS Playbook
when พื้นฐาน
when รับ Jinja2 expression ที่ประเมินเป็น true หรือ false — ถ้า true task จะรัน ถ้า false task จะ skip โดยแสดงสถานะ skipping แทน changed หรือ ok
---
- name: Basic when examples
hosts: all
vars:
env: production
app_version: "2.5.0"
debug_mode: false
tasks:
# รันเฉพาะเมื่อ env เป็น production
- name: Enable production optimizations
command: /opt/myapp/bin/optimize --production
when: env == "production"
# รันเฉพาะเมื่อ debug_mode เป็น true
- name: Enable debug logging
lineinfile:
path: /etc/myapp/app.conf
line: "LOG_LEVEL=debug"
when: debug_mode
# รันเฉพาะเมื่อ version ไม่ใช่ latest
- name: Notify about version
debug:
msg: "Running non-latest version: {{ app_version }}"
when: app_version != "latest"
# ตรวจ variable มีค่าหรือไม่ (defined และ ไม่ว่าง)
- name: Run only if deploy_target is set
debug:
msg: "Deploying to: {{ deploy_target }}"
when: deploy_target is defined and deploy_target != ""
when กับ Ansible Facts — ตรวจ OS
Ansible facts ที่ใช้บ่อยที่สุดใน when คือ ansible_os_family และ ansible_distribution เพื่อแยก task ตาม OS — ทำให้ Playbook เดียวรองรับได้ทั้ง Debian-based และ RedHat-based systems
---
- name: OS-specific tasks with when
hosts: all
become: true
tasks:
# ติดตั้งด้วย apt เฉพาะ Debian/Ubuntu
- name: Install Nginx on Debian-based systems
apt:
name: nginx
state: present
update_cache: true
when: ansible_os_family == "Debian"
# ติดตั้งด้วย yum/dnf เฉพาะ RedHat/CentOS
- name: Install Nginx on RedHat-based systems
yum:
name: nginx
state: present
when: ansible_os_family == "RedHat"
# ตรวจ distribution เฉพาะเจาะจงมากขึ้น
- name: Ubuntu-only configuration
template:
src: ubuntu-specific.conf.j2
dest: /etc/nginx/conf.d/ubuntu.conf
when: ansible_distribution == "Ubuntu"
# ตรวจ version ด้วย
- name: Ubuntu 22.04+ specific task
command: systemctl enable nginx
when:
- ansible_distribution == "Ubuntu"
- ansible_distribution_version is version("22.04", ">=")
รวมเงื่อนไขด้วย and / or
ใช้ list สำหรับ AND conditions (ทุกเงื่อนไขต้องจริง) และใช้ or operator ภายใน expression สำหรับ OR conditions — ไม่ใช้ and keyword ระหว่าง list items
---
- name: Combined conditions
hosts: all
vars:
env: production
region: asia
tasks:
# AND: ใช้ list — ทุก item ต้องเป็น true
- name: Production Asia deployment
command: /opt/deploy/asia-prod.sh
when:
- env == "production"
- region == "asia"
- ansible_os_family == "Debian"
# OR: ใช้ or keyword ใน expression เดียว
- name: Run on Ubuntu or Debian
apt:
name: curl
state: present
when: ansible_distribution == "Ubuntu" or ansible_distribution == "Debian"
# OR ด้วย in operator (อ่านง่ายกว่า)
- name: Run on Debian family distributions
debug:
msg: "This is a Debian-based system"
when: ansible_distribution in ["Ubuntu", "Debian", "Mint"]
# ผสม AND และ OR
- name: Complex condition
command: /opt/myapp/tune.sh
when:
- env == "production"
- ansible_os_family == "Debian" or ansible_os_family == "RedHat"
when กับ register — ตรวจผลจาก Task ก่อนหน้า
ใช้ register เก็บผลจาก task แล้วใช้ when ตรวจสอบ — pattern นี้เหมาะสำหรับ task ที่ต้องการตรวจสอบก่อนว่า service ทำงานอยู่, ไฟล์มีอยู่, หรือคำสั่งก่อนหน้าสำเร็จหรือไม่
---
- name: when with register
hosts: all
tasks:
# ตรวจว่า service ทำงานอยู่หรือไม่
- name: Check if myapp is running
command: systemctl is-active myapp
register: myapp_status
ignore_errors: true
changed_when: false
# รันเฉพาะเมื่อ service ไม่ได้ทำงาน
- name: Start myapp if not running
service:
name: myapp
state: started
when: myapp_status.rc != 0
# ตรวจไฟล์ด้วย stat แล้วใช้ when
- name: Check if config exists
stat:
path: /etc/myapp/app.conf
register: config_file
- name: Create config if missing
template:
src: app.conf.j2
dest: /etc/myapp/app.conf
when: not config_file.stat.exists
# ตรวจ output ของ command
- name: Get current version
command: /opt/myapp/bin/myapp --version
register: current_version
changed_when: false
- name: Upgrade only if version is outdated
command: /opt/upgrade.sh
when: '"2.5.0" not in current_version.stdout'
ตรวจสอบ Variable — defined, undefined, true, false
Jinja2 มี test ที่ใช้บ่อยสำหรับตรวจสอบ variable ก่อนใช้ — ช่วยป้องกัน error เมื่อ variable อาจไม่ถูก define ใน inventory หรือ vars
---
- name: Variable checking with when
hosts: all
tasks:
# ตรวจว่า variable ถูก define หรือไม่
- name: Run only if custom_port is defined
debug:
msg: "Using custom port: {{ custom_port }}"
when: custom_port is defined
# ตรวจว่าไม่ถูก define
- name: Use default when variable not set
set_fact:
custom_port: 8080
when: custom_port is not defined
# ตรวจว่า variable เป็น truthy/falsy
- name: Enable feature only when flag is true
command: /opt/myapp/enable-feature.sh
when: feature_enabled | bool
# ตรวจ string ว่างหรือไม่
- name: Skip if deploy_key is empty
command: /opt/deploy.sh
when: deploy_key is defined and deploy_key | length > 0
# ใช้ default filter ป้องกัน undefined
- name: Check with default value
debug:
msg: "Environment: {{ env | default('development') }}"
when: (env | default('development')) != "development"
when กับ loop
เมื่อใช้ when ร่วมกับ loop เงื่อนไขจะถูกประเมินสำหรับแต่ละ item ใน loop — ทำให้ skip เฉพาะ item ที่ไม่ตรงเงื่อนไขได้โดยไม่ต้องหยุด loop ทั้งหมด
---
- name: when with loop
hosts: all
vars:
services:
- name: nginx
enabled: true
- name: myapp
enabled: true
- name: legacy-service
enabled: false
tasks:
# รัน task เฉพาะ item ที่ enabled เป็น true
- name: Start enabled services only
service:
name: "{{ item.name }}"
state: started
loop: "{{ services }}"
when: item.enabled
# ติดตั้ง packages เฉพาะ OS ที่ตรงกัน
- name: Install OS-specific packages
package:
name: "{{ item.name }}"
state: present
loop:
- { name: "nginx", os: "Debian" }
- { name: "httpd", os: "RedHat" }
- { name: "curl", os: "all" }
when: item.os == "all" or item.os == ansible_os_family
Pattern: Multi-OS Playbook
ตัวอย่าง Playbook ติดตั้งและ configure web server บน Ubuntu และ CentOS โดยใช้ when แยกส่วนที่ต่างกัน และใช้ tasks ร่วมกันในส่วนที่เหมือนกัน
---
- name: Cross-platform web server setup
hosts: all
become: true
tasks:
# Install — แยกตาม OS
- name: Install Nginx (Debian/Ubuntu)
apt:
name: nginx
state: present
update_cache: true
when: ansible_os_family == "Debian"
- name: Install Nginx (RedHat/CentOS)
yum:
name: nginx
state: present
when: ansible_os_family == "RedHat"
# Set nginx config path ตาม OS
- name: Set nginx config path (Debian)
set_fact:
nginx_conf_dir: /etc/nginx/conf.d
when: ansible_os_family == "Debian"
- name: Set nginx config path (RedHat)
set_fact:
nginx_conf_dir: /etc/nginx/conf.d
when: ansible_os_family == "RedHat"
# Deploy config — เหมือนกันทุก OS
- name: Deploy virtual host config
template:
src: vhost.conf.j2
dest: "{{ nginx_conf_dir }}/mysite.conf"
owner: root
group: root
mode: '0644'
notify: Reload Nginx
# Enable site — เฉพาะ Debian ที่ใช้ sites-available/sites-enabled
- name: Enable site (Debian only)
file:
src: /etc/nginx/sites-available/mysite.conf
dest: /etc/nginx/sites-enabled/mysite.conf
state: link
when: ansible_os_family == "Debian"
# Start service — เหมือนกันทุก OS
- name: Ensure Nginx is started and enabled
service:
name: nginx
state: started
enabled: true
handlers:
- name: Reload Nginx
service:
name: nginx
state: reloaded
สรุป
when statement เป็นกลไกหลักสำหรับสร้าง Playbook ที่ยืดหยุ่น รองรับการตรวจสอบ OS, variable, ผลจาก task ก่อนหน้า และเงื่อนไขซับซ้อนด้วย AND/OR — task ที่ไม่ตรงเงื่อนไขจะถูก skip โดยอัตโนมัติโดยไม่ทำให้ Playbook error
Pattern ที่ควรจำ: ใช้ list สำหรับ AND conditions, ใช้ or ใน expression เดียวสำหรับ OR conditions, ตรวจ is defined ก่อนใช้ variable ที่อาจไม่มีค่า, ใช้ ansible_os_family แทน ansible_distribution เพื่อรองรับ distro หลายรุ่นในคราวเดียว และระวัง when ใน loop ที่จะประเมินเงื่อนไขทีละ item

