Skip to main content
๐Ÿ“ฌ Get weekly Production AI insights Practical notes on Kubernetes, AI infrastructure and platform engineering. No spam. Subscribe free
Ansible assert module guide for production validation
Automation

Ansible Assert Module: Validate Variables and Facts

The Ansible assert module catches misconfigurations before they reach production. Learn how to validate variables, facts, network reachability, disk.

LB
Luca Berton
ยท 1 min read

Why Assert Before You Deploy

The ansible.builtin.assert module is your last line of defense before a playbook makes changes to production systems. It evaluates conditions and fails the play immediately if any condition is false โ€” before any damage is done.

Think of it as a pre-flight checklist: verify the target host meets all requirements before applying configuration changes.

Basic Syntax

- name: Ensure minimum Ansible version
  ansible.builtin.assert:
    that:
      - "ansible_version.full is version('2.14', '>=')"
    fail_msg: "Ansible 2.14+ required. Found {{ ansible_version.full }}"
    success_msg: "Ansible version {{ ansible_version.full }} meets requirements"

Key parameters:

  • that โ€” list of conditions (all must be true)
  • fail_msg โ€” custom error message on failure
  • success_msg โ€” optional message on success
  • quiet โ€” suppress success output (boolean, default false)

Validate Required Variables

The most common use case โ€” ensure variables are defined and non-empty before using them:

- name: Validate deployment variables
  ansible.builtin.assert:
    that:
      - app_version is defined
      - app_version | length > 0
      - deploy_env is defined
      - deploy_env in ['staging', 'production']
      - db_host is defined
      - db_port | int > 0
    fail_msg: >
      Missing or invalid deployment variables.
      app_version={{ app_version | default('UNDEFINED') }},
      deploy_env={{ deploy_env | default('UNDEFINED') }},
      db_host={{ db_host | default('UNDEFINED') }}

Validate Host Facts

Check that the target system meets hardware and OS requirements:

- name: Gather facts
  ansible.builtin.setup:

- name: Validate target system
  ansible.builtin.assert:
    that:
      - ansible_os_family == "RedHat"
      - ansible_distribution_major_version | int >= 9
      - ansible_memtotal_mb >= 4096
      - ansible_processor_vcpus >= 2
      - ansible_mounts | selectattr('mount', 'equalto', '/') | map(attribute='size_available') | first | int > 5368709120
    fail_msg: >
      Host does not meet requirements:
      OS={{ ansible_distribution }} {{ ansible_distribution_version }},
      RAM={{ ansible_memtotal_mb }}MB (need 4096MB),
      CPUs={{ ansible_processor_vcpus }} (need 2),
      Root disk free={{ (ansible_mounts | selectattr('mount', 'equalto', '/') | map(attribute='size_available') | first | int / 1073741824) | round(1) }}GB (need 5GB)

Validate Network Connectivity

Check that required services are reachable before configuring clients:

- name: Check database connectivity
  ansible.builtin.wait_for:
    host: "{{ db_host }}"
    port: "{{ db_port }}"
    timeout: 5
  register: db_check
  ignore_errors: true

- name: Assert database is reachable
  ansible.builtin.assert:
    that:
      - db_check is success
    fail_msg: "Cannot reach database at {{ db_host }}:{{ db_port }}"

- name: Check API endpoint
  ansible.builtin.uri:
    url: "https://{{ api_host }}/healthz"
    method: GET
    status_code: 200
    timeout: 10
  register: api_check
  ignore_errors: true

- name: Assert API is healthy
  ansible.builtin.assert:
    that:
      - api_check.status == 200
    fail_msg: "API health check failed: {{ api_check.msg | default('unreachable') }}"

Validate Kubernetes Prerequisites

Before deploying to Kubernetes, verify the cluster is ready:

- name: Get cluster info
  kubernetes.core.k8s_cluster_info:
  register: cluster_info

- name: Assert Kubernetes version
  ansible.builtin.assert:
    that:
      - cluster_info.version.server.kubernetes.major | int >= 1
      - cluster_info.version.server.kubernetes.minor | int >= 28
    fail_msg: "Kubernetes 1.28+ required. Found {{ cluster_info.version.server.kubernetes.gitVersion }}"

- name: Check namespace exists
  kubernetes.core.k8s_info:
    api_version: v1
    kind: Namespace
    name: "{{ deploy_namespace }}"
  register: ns_check

- name: Assert namespace exists
  ansible.builtin.assert:
    that:
      - ns_check.resources | length > 0
    fail_msg: "Namespace {{ deploy_namespace }} does not exist"

Validate File and Directory State

- name: Check SSL certificate exists
  ansible.builtin.stat:
    path: /etc/ssl/certs/app.crt
  register: cert_file

- name: Assert certificate is present and not expired soon
  ansible.builtin.assert:
    that:
      - cert_file.stat.exists
      - cert_file.stat.size > 0
    fail_msg: "SSL certificate missing at /etc/ssl/certs/app.crt"

- name: Get certificate expiry
  ansible.builtin.command: >
    openssl x509 -enddate -noout -in /etc/ssl/certs/app.crt
  register: cert_expiry
  changed_when: false

- name: Assert certificate not expiring within 30 days
  ansible.builtin.assert:
    that:
      - "'notAfter' in cert_expiry.stdout"
    fail_msg: "Certificate expiry check failed: {{ cert_expiry.stdout }}"

Using Assert in Roles

Create a validate.yml task file that runs before the main role tasks:

# roles/webserver/tasks/validate.yml
- name: Validate webserver role variables
  ansible.builtin.assert:
    that:
      - webserver_port | int > 0
      - webserver_port | int < 65536
      - webserver_document_root is defined
      - webserver_ssl_enabled is defined
      - webserver_ssl_enabled | bool or not webserver_force_https | default(false) | bool
    fail_msg: "Invalid webserver configuration. Check role variables."
    quiet: true
# roles/webserver/tasks/main.yml
- name: Run validation
  ansible.builtin.include_tasks: validate.yml

- name: Install web server
  ansible.builtin.dnf:
    name: nginx
    state: present
# ... rest of role

Assert with Loops

Validate multiple items:

- name: Validate all required services are running
  ansible.builtin.assert:
    that:
      - "item in ansible_facts.services"
      - "ansible_facts.services[item].state == 'running'"
    fail_msg: "Service {{ item }} is not running"
    quiet: true
  loop:
    - sshd.service
    - firewalld.service
    - chronyd.service

Assert vs Fail + When

These are equivalent:

# Using assert
- ansible.builtin.assert:
    that:
      - disk_free_gb | int > 10
    fail_msg: "Not enough disk space"

# Using fail + when
- ansible.builtin.fail:
    msg: "Not enough disk space"
  when: disk_free_gb | int <= 10

Use assert when you have multiple conditions to check โ€” it is cleaner than nested when clauses. Use fail + when for simple single-condition checks.

Production Validation Playbook Template

---
- name: Pre-deployment validation
  hosts: "{{ target_hosts }}"
  gather_facts: true
  tasks:
    - name: OS validation
      ansible.builtin.assert:
        that:
          - ansible_os_family in ['RedHat', 'Debian']
          - ansible_distribution_major_version | int >= 9 or ansible_distribution == 'Ubuntu'
        fail_msg: "Unsupported OS: {{ ansible_distribution }} {{ ansible_distribution_version }}"

    - name: Resource validation
      ansible.builtin.assert:
        that:
          - ansible_memtotal_mb >= min_memory_mb | default(2048)
          - ansible_processor_vcpus >= min_cpus | default(2)
        fail_msg: "Insufficient resources: {{ ansible_memtotal_mb }}MB RAM, {{ ansible_processor_vcpus }} CPUs"

    - name: Variable validation
      ansible.builtin.assert:
        that:
          - app_version is defined and app_version | length > 0
          - deploy_env is defined and deploy_env in allowed_environments
        fail_msg: "Invalid deployment variables"

    - name: Connectivity validation
      ansible.builtin.wait_for:
        host: "{{ item.host }}"
        port: "{{ item.port }}"
        timeout: 5
      loop: "{{ required_endpoints }}"
      loop_control:
        label: "{{ item.host }}:{{ item.port }}"

  post_tasks:
    - name: All validations passed
      ansible.builtin.debug:
        msg: "Pre-deployment validation complete. Safe to proceed."

Building reliable automation pipelines? I help teams design Ansible automation with proper validation, testing, and production safeguards.

Book a Consultation โ†’

Free 30-min Production AI consultation

Book Now