When running multiple Ansible roles sequentially, variables can persist between role executions unless explicitly cleared. This behavior becomes problematic when:
- Roles share common variable names (like
version
) - Some roles should use default values
- Previous role assignments might interfere with subsequent roles
Consider this playbook structure:
roles:
- { role: mysql, version: "5.7" }
- { role: rabbitmq } # Should use default version
The version
value from mysql (5.7) will persist when rabbitmq runs, potentially causing incorrect installations.
1. Explicit Variable Unsetting
Add this task at the end of each role:
- name: Reset version variable
set_fact:
version: ""
2. Role-Specific Variable Scoping
Prefix variables with role names:
roles:
- { role: mysql, mysql_version: "5.7" }
- { role: rabbitmq, rabbitmq_version: "" }
3. Using Default Filters
Modify your role templates to explicitly handle undefined cases:
version: "{{ version | default(omit) }}"
Create a custom role for variable management:
- name: Clean variables between roles
hosts: localhost
tasks:
- name: Flush all temporary facts
set_fact:
version: null
delegate_to: localhost
run_once: true
For production environments, I recommend combining solutions:
- Use role-specific variable names (
mysql_version
,rabbitmq_version
) - Implement default filters in templates
- Add explicit cleanup tasks for shared variables
This approach provides both immediate resolution and long-term maintainability.
When working with multiple Ansible roles that use the same variable names, you might encounter situations where variable values persist unexpectedly between role executions. This commonly occurs with frequently-used variable names like version
, port
, or config_path
.
# Problem scenario example
roles:
- { role: mysql, version: "8.0" }
- { role: rabbitmq } # Accidentally inherits mysql's version
1. Explicitly Undefining Variables
The most straightforward method is using the set_fact
module to nullify the variable:
- name: Reset version variable
set_fact:
version: ~
when: version is defined
2. Role-Specific Variable Scoping
Ansible 2.8+ provides better namespace control with vars
:
roles:
- role: mysql
vars:
version: "8.0"
- role: rabbitmq
vars:
version: "" # Explicit empty value
3. Using Blocks for Isolation
Block-level variable scoping can create clean separation:
- block:
- include_role:
name: mysql
vars:
version: "5.7"
rescue:
- debug:
msg: "MySQL installation failed"
- block:
- include_role:
name: rabbitmq
vars:
version: "" # Reset between blocks
For complex scenarios, consider pre-task cleanup:
- name: Clean environment variables
hosts: all
pre_tasks:
- name: Reset common variables
set_fact:
version: ""
port: ""
config_path: ""
run_once: true
Always use role-specific variable prefixes in your roles:
# Instead of:
vars:
version: "2.3"
# Use:
vars:
rabbitmq_version: "3.8"
mysql_version: "8.0"
To troubleshoot variable leakage, add this debug task between roles:
- name: Show current variable state
debug:
var: hostvars[inventory_hostname]