Variables, facts and registered results

Ansible · Essentials · 10 min

Real playbooks adapt to each host; variables and facts are how they know what to do.

Variables are referenced with Jinja2: "{{ app_port }}". When a value starts with {{, quote the whole string, or YAML will misread it as a mapping.

Where variables come from (the common places): play vars, vars_files, group_vars/ and host_vars/ next to the inventory or playbook, role defaults, -e key=value on the command line (extra vars, the highest precedence), and set_fact during a run.

Facts are variables Ansible discovers about each host at the start of a play (gather_facts: true is the default): OS, IP addresses, CPU, memory, mounts. Access them through ansible_facts, like ansible_facts['distribution'] or ansible_facts['default_ipv4']['address']. The older top-level form (ansible_distribution) still works but is being phased out. Turn gathering off with gather_facts: false when you don't need it; it speeds up runs.

Special variables: inventory_hostname, group_names, groups['web'] (all hosts in a group), hostvars['db1'] (another host's variables and facts).

register saves a task's result: register: result, then use result.stdout, result.rc, result.changed. Use ansible.builtin.debug with var: or msg: to print values while developing.

Example

- name: Variables and facts demo
  hosts: localhost
  connection: local
  vars:
    app_name: shop
    app_port: 8080
  tasks:
    - name: Show OS facts
      ansible.builtin.debug:
        msg: "{{ app_name }} on {{ ansible_facts['distribution'] }} {{ ansible_facts['distribution_version'] }}"

    - name: Check what listens on the port
      ansible.builtin.command: "ss -ltn sport = :{{ app_port }}"
      register: listen
      changed_when: false            # read-only command

    - name: Use the registered result
      ansible.builtin.debug:
        msg: "Port {{ app_port }} busy: {{ listen.stdout_lines | length > 1 }}"
# ansible-playbook vars.yml -e app_port=9090   # extra vars override play vars

Remember

  • Quote values that start with {{
  • Facts live under ansible_facts; turn gathering off when unneeded
  • register captures results; -e has the highest precedence

Watch out for

  • Writing msg: {{ x }} unquoted, which YAML parses as a dictionary and errors.

Check yourself

  1. How do you read the IP address Ansible gathered for host db1 from a play running on web1?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html