Introduction
Variable scoping can be quite complicated on Ansible and it’s important to know what variable your playbook is going to be using. But sometimes it’s not as easy as it may appear. The documentation on Ansible’s website explains this but I’d like to run you through a scenario we found where this is not what you would expect it to be.
Recently whilst working on a deployment where we had the same role applied to a group of servers twice with different configurations we found it wasn’t working for us. We did a bit of investigation and we found that some of the variable precedence was not behaving as we were expecting it to be.
The scenarios below demonstrate the problem on tests 4 and 5.
Test framework
I’m going to use a simple playbook with a single role which prints a variable content to the screen.
.
├── main.yml
└── roles
└── my-role
├── defaults
│ └── main.yml
└── tasks
└── main.yml
4 directories, 3 files
---
- debug:
var: day_of_the_week
---
day_of_the_week: Thursday
Test 1: Load the role
Playbook
- hosts: all
roles:
- name: my-role
Explanation: It simply takes the default value from the role
Test 2: Override the default with a new value
- hosts: all
vars:
day_of_the_week: Monday
roles:
- name: my-role
Explanation: New value displayed as expected
Test 3: Override variable from within the role
- hosts: all
roles:
- name: my-role
vars:
day_of_the_week: Monday
Explanation: New value displayed as expected
Test 4: Load the role twice and change the default value for one of them
- hosts: all
roles:
- name: my-role
vars:
day_of_the_week: Monday
- name: my-role
Explanation: This is an unexpected result. You would have thought it the result would be Thursday for the first time the role loads and Monday for the second attempt but Ansible seems to override the value.
Test 5: Change the order of loading from Test 4
- hosts: all
roles:
- name: my-role
- name: my-role
vars:
day_of_the_week: Monday
Explanation: This is another unexpected result. Logic would dictate that the first one should be Thursday and Monday for the second attempt. The order in which the roles are defined does not affect the result.
Test 6: Override value for both roles
- hosts: all
roles:
- name: my-role
vars:
day_of_the_week: Monday
- name: my-role
vars:
day_of_the_week: Tuesday
Explanation: This is exactly what you would expect as you’re changing the default value.
Test 7: Set global variable and override on role
- hosts: all
vars:
day_of_the_week: Friday
roles:
- name: my-role
- name: my-role
vars:
day_of_the_week: Tuesday
Explanation: This is yet another unexpected result similar to tests 4 and 5. The local variable set for a single role seems to override the whole playbook.
Test 8: Override variable from command line
- hosts: all
vars:
day_of_the_week: Friday
roles:
- name: my-role
- name: my-role
vars:
day_of_the_week: Tuesday
and we’re running the playbook using
ansible-playbook -i localhost,
--connection=local
-v main.yml
-e day_of_the_week=Yesterday
Explanation: Ansible documentation states that the command line has the highest precedence and it stands to reason that all the other variables are ignored.
Test 9: Change variable with set_fact
- hosts: all
vars:
day_of_the_week: Friday
pre_tasks:
- set_fact:
day_of_the_week: Wednesday
roles:
- name: my-role
vars:
day_of_the_week: Monday
- name: my-role
vars:
day_of_the_week: Tuesday
Explanation: This is expected as set_fact has precedence over roles.
Test 10: Import variable from files
The day_of_the_week variable is move into two files, one defines Wednesday and loaded first and the other one sets the value of Friday and it’s loaded last
- hosts: all
vars_files:
- wed.yml
- fri.yml
roles:
- name: my-role
Explanation: This is expected. The last value overrides the first one.
Summary
Some of the results where surprising to me.
Sergio Rua
DevOps Engineer
Sergio has many years experience working on various development projects before joining Digitalis. He worked for large companies with complex networks and infrastructure. ‘This has helped Sergio gain lots of experience in multiple areas from programming to networks. He especial excels is in DevOps: automation is his day-to-day and Kubernetes his passion.
Related Articles
Getting started with Kafka Cassandra Connector
If you want to understand how to easily ingest data from Kafka topics into Cassandra than this blog can show you how with the DataStax Kafka Connector.
K3s – lightweight kubernetes made ready for production – Part 3
Do you want to know securely deploy k3s kubernetes for production? Have a read of this blog and accompanying Ansible project for you to run.
K3s – lightweight kubernetes made ready for production – Part 2
Do you want to know securely deploy k3s kubernetes for production? Have a read of this blog and accompanying Ansible project for you to run.