Advanced vars_files Techniques
In this final step, we'll explore some advanced techniques for working with vars_files in Ansible, including organizing variables hierarchically and implementing role-based variable organization.
Organizing Variables Hierarchically
In complex projects, it's often helpful to organize variables hierarchically. Let's create a structure where we have:
- Common variables that apply to all environments
- Environment-specific variables
- Application-specific variables
First, let's create a common variables file:
Create a new file at ~/project/ansible-vars-demo/vars/common.yml
with the following content:
---
## Common variables for all environments
organization: "Example Corp"
admin_email: "admin@example.com"
timezone: "UTC"
Next, let's create application-specific variables:
Create a new file at ~/project/ansible-vars-demo/vars/database.yml
with the following content:
---
## Database application variables
db_port: 3306
db_user: "dbuser"
db_name: "appdb"
db_max_connections: 100
Creating a Hierarchical Playbook
Now, let's create a playbook that demonstrates using these hierarchical variables. Create a new file at ~/project/ansible-vars-demo/hierarchical_setup.yml
with the following content:
---
- name: Hierarchical Variable Demo
hosts: webservers
vars:
env: dev
app: database
vars_files:
- "vars/common.yml"
- "vars/{{ env }}_environment.yml"
- "vars/{{ app }}.yml"
tasks:
- name: Display hierarchical configuration
debug:
msg: >
Configuration for {{ app }} in {{ environment_name }} environment:
- Organization: {{ organization }}
- Admin Email: {{ admin_email }}
- Timezone: {{ timezone }}
- Debug Mode: {{ debug_mode }}
- Log Level: {{ log_level }}
- DB Port: {{ db_port }}
- DB User: {{ db_user }}
- DB Max Connections: {{ db_max_connections }}
- name: Create hierarchical config file
copy:
content: |
## {{ organization }} Configuration
## {{ environment_name }} Environment
## Common Settings
ADMIN_EMAIL={{ admin_email }}
TIMEZONE={{ timezone }}
## Environment Settings
DEBUG={{ debug_mode }}
LOG_LEVEL={{ log_level }}
BACKUP_FREQUENCY={{ backup_frequency }}
## {{ app | capitalize }} Settings
DB_PORT={{ db_port }}
DB_USER={{ db_user }}
DB_NAME={{ db_name }}
DB_MAX_CONNECTIONS={{ db_max_connections }}
dest: "/tmp/{{ environment_name }}_{{ app }}_config.conf"
mode: "0644"
Understanding Group and Host Variables
In addition to vars_files, Ansible also supports storing variables in special directories called group_vars
and host_vars
. Let's see how these work:
Create a directory structure for group and host variables:
mkdir -p ~/project/ansible-vars-demo/group_vars
mkdir -p ~/project/ansible-vars-demo/host_vars
Now, create a group variables file for the 'webservers' group:
Create a new file at ~/project/ansible-vars-demo/group_vars/webservers.yml
with the following content:
---
## Variables for all webservers
firewall_enabled: true
ssh_port: 22
monitoring_enabled: true
And create a host variables file for 'localhost':
Create a new file at ~/project/ansible-vars-demo/host_vars/localhost.yml
with the following content:
---
## Variables specific to localhost
local_backup_path: "/tmp/backups"
is_development_machine: true
Creating a Playbook with All Variable Types
Let's create a final playbook that demonstrates using all the variable types together. Create a new file at ~/project/ansible-vars-demo/complete_setup.yml
with the following content:
---
- name: Complete Variable Demo
hosts: webservers
vars:
env: prod
app: database
vars_files:
- "vars/common.yml"
- "vars/{{ env }}_environment.yml"
- "vars/{{ app }}.yml"
tasks:
- name: Display complete configuration
debug:
msg: >
Complete configuration for {{ inventory_hostname }}:
- Organization: {{ organization }}
- Environment: {{ environment_name }}
- Debug Mode: {{ debug_mode }}
- Firewall Enabled: {{ firewall_enabled }}
- SSH Port: {{ ssh_port }}
- Monitoring Enabled: {{ monitoring_enabled }}
- Local Backup Path: {{ local_backup_path }}
- Is Development Machine: {{ is_development_machine }}
- name: Create complete config file
copy:
content: |
## {{ organization }} - {{ environment_name }} Environment
## Host: {{ inventory_hostname }}
## Common Settings
ADMIN_EMAIL={{ admin_email }}
TIMEZONE={{ timezone }}
## Environment Settings
DEBUG={{ debug_mode }}
LOG_LEVEL={{ log_level }}
## Server Settings
FIREWALL_ENABLED={{ firewall_enabled }}
SSH_PORT={{ ssh_port }}
MONITORING_ENABLED={{ monitoring_enabled }}
## Host-specific Settings
LOCAL_BACKUP_PATH={{ local_backup_path }}
IS_DEVELOPMENT_MACHINE={{ is_development_machine }}
## {{ app | capitalize }} Settings
DB_PORT={{ db_port }}
DB_USER={{ db_user }}
DB_NAME={{ db_name }}
dest: "/tmp/complete_config.conf"
mode: "0644"
Running the Advanced Playbooks
Let's run our hierarchical playbook:
cd ~/project/ansible-vars-demo
ansible-playbook -i inventory.ini hierarchical_setup.yml
You should see output that includes variables from all three vars_files.
Now, let's run our complete playbook:
ansible-playbook -i inventory.ini complete_setup.yml
This time, you should see output that includes variables from vars_files, group_vars, and host_vars.
Verifying the Configuration Files
Let's check the configuration files created by our advanced playbooks:
cat /tmp/dev_database_config.conf
cat /tmp/complete_config.conf
Understanding Variable Precedence in Ansible
When using multiple variable sources, Ansible follows a specific order of precedence:
- Command line variables (
-e
or --extra-vars
)
- Variables defined in the play
- Variables from included files and roles
- Host facts
- Host vars
- Group vars
- Inventory vars
- Role default vars
This means that variables defined in host_vars will override the same variables defined in group_vars, which will override the same variables defined in vars_files.
This hierarchical structure gives you a powerful way to manage configuration across different environments, hosts, and applications.