Variable Precedence in Ansible
Ansible is a powerful tool for managing infrastructure and automating tasks. It allows you to define variables that can be used throughout your playbooks and roles, making it easy to reuse configuration and logic across multiple tasks and systems. However, when using variables in Ansible, it is important to understand the order in which they are defined, as this determines which value will be used when a variable is defined multiple times. This is known as "variable precedence".
The variable precedence order in Ansible is as follows:
- command line values (for example,
-u my_user
, these are not variables) - role defaults (defined in role/defaults/main.yml)
- inventory file or script group vars
- inventory group_vars/all
- playbook group_vars/all
- inventory group_vars/*
- playbook group_vars/*
- inventory file or script host vars
- inventory host_vars/*
- playbook host_vars/*
- host facts / cached set_facts
- play vars
- play vars_prompt
- play vars_files
- role vars (defined in role/vars/main.yml)
- block vars (only for tasks in block)
- task vars (only for the task)
- include_vars
- set_facts / registered vars
- role (and include_role) params
- include params
- extra vars (for example,
-e "user=my_user"
)(always win precedence)
Variables with higher precedence will override variables with lower precedence. For example, if a variable is defined in both the inventory file and the playbook file, the value defined in the inventory file will take precedence.
Examples
Example 1: Using Extra Vars
Suppose you have a playbook that defines a variable called my_var
. You can override this variable using the -e
or --extra-vars
option when running the playbook, like this:
ansible-playbook my_playbook.yml -e "my_var=foo"
In this case, the value of my_var
will be set to foo
, regardless of any other variable definitions in the playbook or role files.
Example 2: Using Role Defaults
Suppose you have a role that defines a variable called my_var
in the defaults/main.yml
file:
# roles/my_role/defaults/main.yml
my_var: default_value
If you use this role in a playbook and don't define my_var
anywhere else in the playbook, the value of my_var
will be set to default_value
.
Example 3: Using Inventory Variables
Suppose you have an inventory file that defines a variable called my_var
for a specific host:
# inventory/my_inventory.yml
my_host:
my_var: host_value
If you run a playbook that uses my_host
as the target, the value of my_var
will be set to host_value
for that host.
Example 4: Using Block Variables
Suppose you have a playbook that defines a variable called my_var
within a block:
- name: My Playbook
hosts: all
tasks:
- block:
- name: Task 1
set_fact:
my_var: block_value
- name: Task 2
debug:
var: my_var
become: yes
In this case, the value of my_var
will be set to block_value
within the block, and will be available only to Task 2.
Example 5: Using Registered Variables
Suppose you have a playbook that uses the yum
module to install a package, and registers the output using the register
keyword:
- name: Install Package
hosts: all
tasks:
- name: Install Package
yum:
name: my_package
state: present
register: install_result
- name: Display Output
debug:
var: install_result
In this case, the output of the yum
module is registered as install_result
, and can be used in subsequent tasks in the playbook. The value of install_result
will be available only to subsequent tasks in the playbook.
These examples illustrate how variable precedence works in Ansible, and how different types of variables are defined and used. By understanding the order in which variables are defined and the context in which they are used, you can ensure that your playbooks and roles are using the correct values for each variable, and avoid unexpected behaviour.