Skip to content

Ansible Conditionals

Overview

Conditionals in Ansible allow you to execute tasks based on specific conditions, making your playbooks more dynamic and adaptable.

Basic Conditionals

When Statement

# Simple condition
- name: Install Apache on Debian-based systems
  ansible.builtin.apt:
    name: apache2
    state: present
  when: ansible_facts['os_family'] == "Debian"

# Multiple conditions
- name: Configure production settings
  ansible.builtin.template:
    src: prod-settings.j2
    dest: /etc/app/settings.conf
  when:
    - environment == "production"
    - ansible_facts['memory_mb']['real']['total'] >= 4096

Boolean Operations

# AND condition
- name: Execute with multiple conditions
  debug:
    msg: "All conditions met"
  when:
    - condition1 | bool
    - condition2 | bool
    - condition3 | bool

# OR condition
- name: Execute with any condition
  debug:
    msg: "One condition met"
  when: condition1 | bool or condition2 | bool

# NOT condition
- name: Skip when condition is true
  debug:
    msg: "Condition not met"
  when: not condition1

Advanced Conditionals

Conditional Imports

# Conditional include
- name: Include OS-specific tasks
  ansible.builtin.include_tasks:
    file: "{{ ansible_facts['os_family'] | lower }}.yml"
  when: ansible_facts['os_family'] in ['Debian', 'RedHat']

# Conditional roles
- name: Include role based on environment
  ansible.builtin.include_role:
    name: "{{ item }}"
  loop:
    - common
    - "{{ environment }}_specific"
  when: environment in ['dev', 'prod']

Variable Existence

# Check if variable exists
- name: Configure when variable exists
  debug:
    msg: "Variable exists and equals {{ myvar }}"
  when: myvar is defined

# Check variable type
- name: Process list variable
  debug:
    msg: "Processing list items"
  when: myvar is sequence

File and Path Conditions

# Check file status
- name: Check file conditions
  debug:
    msg: "File exists and is not empty"
  when:
    - path_to_file is exists
    - path_to_file is file
    - path_to_file is not directory
    - path_to_file.stat.size > 0
  vars:
    path_to_file: "/path/to/file"

Complex Conditionals

Nested Conditions

# Multiple level conditions
- name: Complex conditional execution
  debug:
    msg: "All conditions met"
  when:
    - environment == "production"
    - ansible_facts['os_family'] == "Debian"
    - ansible_facts['distribution_version'] is version('18.04', '>=')
    - ansible_facts['memory_mb']['real']['total'] >= 4096

Register and Conditions

# Use registered variables
- name: Check process status
  ansible.builtin.command: systemctl status nginx
  register: nginx_status
  ignore_errors: yes

- name: Restart if not running
  ansible.builtin.service:
    name: nginx
    state: restarted
  when: nginx_status.rc != 0

Custom Conditions

# Define custom conditions
- name: Set custom facts
  ansible.builtin.set_fact:
    is_valid_env: "{{ environment in ['dev', 'staging', 'prod'] }}"
    has_enough_memory: "{{ ansible_facts['memory_mb']['real']['total'] >= min_memory }}"
    is_supported_os: "{{ ansible_facts['os_family'] in supported_os }}"

- name: Execute with custom conditions
  debug:
    msg: "System meets all requirements"
  when:
    - is_valid_env
    - has_enough_memory
    ### Pattern Matching
```yaml
# String pattern matching
- name: Match hostname pattern
  debug:
    msg: "Webserver detected"
  when: inventory_hostname is match("web-*")

# Regular expressions
- name: Match using regex
  debug:
    msg: "Development server detected"
  when: inventory_hostname is regex("^dev-\d+")

Version Comparisons

# Compare versions
- name: Check minimum version
  debug:
    msg: "Version meets requirement"
  when: app_version is version('2.0.0', '>=')

# Version ranges
- name: Check version compatibility
  debug:
    msg: "Version in supported range"
  when:
    - app_version is version('1.5.0', '>=')
    - app_version is version('3.0.0', '<')

Error Handling with Conditionals

Failed Status Handling

# Check task failure
- name: Attempt primary action
  ansible.builtin.command: /usr/local/bin/primary-action
  register: primary_result
  ignore_errors: yes

- name: Attempt fallback action
  ansible.builtin.command: /usr/local/bin/fallback-action
  when: primary_result is failed

# Multiple failure checks
- name: Complex error handling
  block:
    - name: Primary database connection
      ansible.builtin.command: check_db_connection.sh primary
      register: primary_db

    - name: Failover database connection
      ansible.builtin.command: check_db_connection.sh failover
      register: failover_db
      when: primary_db is failed

    - name: Emergency backup connection
      ansible.builtin.command: check_db_connection.sh backup
      when: 
        - primary_db is failed
        - failover_db is failed
  rescue:
    - name: Notify on complete failure
      ansible.builtin.mail:
        to: [email protected]
        subject: "Database connection failure"
        body: "All database connections failed"
      when: primary_db is failed and failover_db is failed

Conditional Tasks Based on Environment

Environment-Specific Configuration

# Multi-environment handling
- name: Configure environment settings
  ansible.builtin.template:
    src: "{{ item }}"
    dest: "/etc/app/config.yml"
  with_first_found:
    - files:
        - "config-{{ environment }}.yml.j2"
        - "config-default.yml.j2"
      paths:
        - templates/configs
  when: environment is defined

# Resource allocation by environment
- name: Set resource limits
  ansible.builtin.template:
    src: limits.conf.j2
    dest: /etc/security/limits.conf
  vars:
    max_memory: "{{ '512MB' if environment == 'dev' else '2GB' if environment == 'staging' else '8GB' }}"
  when: environment in ['dev', 'staging', 'prod']

Conditional Role Execution

Role-Based Logic

# Conditional role inclusion
- name: Include monitoring role
  ansible.builtin.include_role:
    name: monitoring
  when: 
    - enable_monitoring | bool
    - monitoring_type in ['basic', 'advanced']

# Dynamic role parameters
- name: Configure backup role
  ansible.builtin.include_role:
    name: backup
    tasks_from: "{{ backup_type }}"
  vars:
    backup_params:
      retention: "{{ '7d' if environment == 'dev' else '30d' }}"
      compression: "{{ 'low' if environment == 'dev' else 'high' }}"
  when: enable_backups | default(true) | bool

Best Practices

Readable Conditions

# Use descriptive variables
- name: Set condition variables
  ansible.builtin.set_fact:
    is_production: "{{ environment == 'production' }}"
    is_high_capacity: "{{ ansible_facts['memory_mb']['real']['total'] >= 16384 }}"
    is_backup_day: "{{ ansible_date_time.weekday in ['Saturday', 'Sunday'] }}"

- name: Execute weekend backup
  ansible.builtin.include_role:
    name: backup
    tasks_from: full
  when: 
    - is_production
    - is_high_capacity
    - is_backup_day

Conditional Documentation

# Document complex conditions
- name: Document conditional logic
  ansible.builtin.set_fact:
    deployment_conditions: |
      Deployment requires:
      1. Production environment
      2. Minimum 16GB RAM
      3. Supported OS version
      4. All health checks passing

- name: Deploy application
  ansible.builtin.include_role:
    name: app_deploy
  vars:
    conditions_met: "{{
      environment == 'production' and
      ansible_facts['memory_mb']['real']['total'] >= 16384 and
      ansible_distribution_version is version('20.04', '>=') and
      health_checks.status == 'passing'
    }}"
  when: conditions_met

Testing Conditions

# Debug conditional logic
- name: Debug condition evaluation
  ansible.builtin.debug:
    msg: |
      Condition evaluation:
      - Environment: {{ environment }}
      - Memory: {{ ansible_facts['memory_mb']['real']['total'] }}
      - OS Version: {{ ansible_distribution_version }}
      - Health Status: {{ health_checks.status }}
  when: debug_mode | default(false) | bool

Performance Optimization

# Optimize condition checking
- name: Cache frequent condition results
  ansible.builtin.set_fact:
    cache_time: 3600  # Cache for 1 hour
    system_conditions: "{{
      {
        'meets_memory': ansible_facts['memory_mb']['real']['total'] >= min_memory,
        'meets_version': ansible_distribution_version is version(min_version, '>='),
        'meets_disk': ansible_facts['mounts'][0]['size_available'] >= min_disk_space
      }
    }}"
  when: system_conditions is not defined

- name: Use cached conditions
  debug:
    msg: "System meets requirements"
  when: 
    - system_conditions.meets_memory
    - system_conditions.meets_version
    - system_conditions.meets_disk