Best Practices and Real-World Applications
In this final step, we'll explore best practices for working with hostvars and look at some real-world applications.
Best Practices for Organizing Variables
Organizing your variables properly is crucial for maintaining clean, maintainable Ansible code. Let's create a more structured inventory setup to demonstrate best practices:
mkdir -p ~/project/ansible_hostvars/inventory/group_vars/all
mkdir -p ~/project/ansible_hostvars/inventory/group_vars/webservers
mkdir -p ~/project/ansible_hostvars/inventory/group_vars/dbservers
mkdir -p ~/project/ansible_hostvars/inventory/host_vars
Now, let's create some organized variable files:
cat > ~/project/ansible_hostvars/inventory/group_vars/all/common.yml << 'EOF'
---
## Common variables for all hosts
ntp_servers:
- ntp1.example.com
- ntp2.example.com
timezone: UTC
monitoring_enabled: true
monitoring_server: monitor.example.com
EOF
cat > ~/project/ansible_hostvars/inventory/group_vars/webservers/web.yml << 'EOF'
---
## Web server specific variables
http_protocol: https
default_vhost: default.example.com
web_user: www-data
web_group: www-data
firewall_ports:
- 80
- 443
EOF
cat > ~/project/ansible_hostvars/inventory/host_vars/web01.yml << 'EOF'
---
## Host-specific variables for web01
server_role: primary
backup_server: web02
custom_vhosts:
- name: site1.example.com
docroot: /var/www/site1
- name: site2.example.com
docroot: /var/www/site2
EOF
Let's create a playbook that demonstrates accessing these structured variables:
cat > ~/project/ansible_hostvars/playbooks/structured_vars.yml << 'EOF'
---
- name: Demonstrate structured variables
hosts: localhost
gather_facts: no
tasks:
- name: Display structured variables
debug:
msg: |
Common variables:
- NTP Servers: {{ hostvars['web01']['ntp_servers'] | default([]) }}
- Timezone: {{ hostvars['web01']['timezone'] | default('Not set') }}
Web server variables:
- HTTP Protocol: {{ hostvars['web01']['http_protocol'] | default('Not set') }}
- Default VHost: {{ hostvars['web01']['default_vhost'] | default('Not set') }}
Host-specific variables for web01:
- Server Role: {{ hostvars['web01']['server_role'] | default('Not set') }}
- Backup Server: {{ hostvars['web01']['backup_server'] | default('Not set') }}
- Custom VHosts: {{ hostvars['web01']['custom_vhosts'] | default([]) }}
EOF
Run this playbook:
cd ~/project/ansible_hostvars
ANSIBLE_INVENTORY=~/project/ansible_hostvars/inventory ansible-playbook playbooks/structured_vars.yml
Note: We're using the ANSIBLE_INVENTORY
environment variable to specify a different inventory path for this example.
Creating a Configuration Generator
Let's create a practical application that generates configuration files for multiple services:
mkdir -p ~/project/ansible_hostvars/templates/configs
Create template files for different services:
cat > ~/project/ansible_hostvars/templates/configs/apache.conf.j2 << 'EOF'
## Apache configuration for {{ inventory_hostname }}
Listen {{ hostvars[inventory_hostname]['http_port'] | default(80) }}
ServerName {{ inventory_hostname }}
DocumentRoot {{ hostvars[inventory_hostname]['default_document_root'] | default('/var/www/html') }}
MaxClients {{ hostvars[inventory_hostname]['max_connections'] | default(100) }}
## Environment: {{ hostvars[inventory_hostname]['environment'] }}
EOF
cat > ~/project/ansible_hostvars/templates/configs/mysql.conf.j2 << 'EOF'
## MySQL configuration for {{ inventory_hostname }}
[mysqld]
port = {{ hostvars[inventory_hostname]['db_port'] | default(3306) }}
datadir = /var/lib/mysql
socket = /var/lib/mysql/mysql.sock
max_connections = {{ hostvars[inventory_hostname]['max_connections'] | default(100) }}
## Backup directory: {{ hostvars[inventory_hostname]['backup_dir'] | default('/var/backups') }}
## Environment: {{ hostvars[inventory_hostname]['environment'] }}
EOF
cat > ~/project/ansible_hostvars/templates/configs/postgresql.conf.j2 << 'EOF'
## PostgreSQL configuration for {{ inventory_hostname }}
listen_addresses = '*'
port = {{ hostvars[inventory_hostname]['db_port'] | default(5432) }}
max_connections = {{ hostvars[inventory_hostname]['max_connections'] | default(100) }}
## Backup directory: {{ hostvars[inventory_hostname]['backup_dir'] | default('/var/backups') }}
## Environment: {{ hostvars[inventory_hostname]['environment'] }}
EOF
Now, create a playbook to apply these templates:
cat > ~/project/ansible_hostvars/playbooks/config_generator.yml << 'EOF'
---
- name: Generate service configurations
hosts: all
gather_facts: no
tasks:
- name: Create output directory
file:
path: ~/project/ansible_hostvars/output/configs/{{ inventory_hostname }}
state: directory
- name: Generate Apache configuration for web servers
template:
src: ../templates/configs/apache.conf.j2
dest: ~/project/ansible_hostvars/output/configs/{{ inventory_hostname }}/apache.conf
when: inventory_hostname in groups['webservers']
- name: Generate MySQL configuration for database servers with MySQL
template:
src: ../templates/configs/mysql.conf.j2
dest: ~/project/ansible_hostvars/output/configs/{{ inventory_hostname }}/mysql.conf
when: inventory_hostname in groups['dbservers'] and hostvars[inventory_hostname]['db_port'] | string == '3306'
- name: Generate PostgreSQL configuration for database servers with PostgreSQL
template:
src: ../templates/configs/postgresql.conf.j2
dest: ~/project/ansible_hostvars/output/configs/{{ inventory_hostname }}/postgresql.conf
when: inventory_hostname in groups['dbservers'] and hostvars[inventory_hostname]['db_port'] | string == '5432'
EOF
Run the config generator playbook:
cd ~/project/ansible_hostvars
ansible-playbook playbooks/config_generator.yml
Explore the generated configuration files:
find ~/project/ansible_hostvars/output/configs -type f | sort
View some of the generated configurations:
cat ~/project/ansible_hostvars/output/configs/web01/apache.conf
cat ~/project/ansible_hostvars/output/configs/db01/mysql.conf
cat ~/project/ansible_hostvars/output/configs/db02/postgresql.conf
Finally, let's create a tool that generates comprehensive documentation for each host in our inventory:
cat > ~/project/ansible_hostvars/templates/host_doc.j2 << 'EOF'
## Host Documentation for {{ inventory_hostname }}
==============================================
### Basic Information
- Hostname: {{ inventory_hostname }}
- IP Address: {{ hostvars[inventory_hostname]['ansible_host'] }}
- Environment: {{ hostvars[inventory_hostname]['environment'] | default('Not specified') }}
### Role Information
{% if inventory_hostname in groups['webservers'] %}
- Role: Web Server
- HTTP Port: {{ hostvars[inventory_hostname]['http_port'] | default('Not specified') }}
- Max Connections: {{ hostvars[inventory_hostname]['max_connections'] | default('Not specified') }}
{% if 'web_server_type' in hostvars[inventory_hostname] %}
- Web Server Type: {{ hostvars[inventory_hostname]['web_server_type'] }}
{% endif %}
{% endif %}
{% if inventory_hostname in groups['dbservers'] %}
- Role: Database Server
- DB Port: {{ hostvars[inventory_hostname]['db_port'] | default('Not specified') }}
- Backup Directory: {{ hostvars[inventory_hostname]['backup_dir'] | default('Not specified') }}
{% if 'backup_frequency' in hostvars[inventory_hostname] %}
- Backup Frequency: {{ hostvars[inventory_hostname]['backup_frequency'] }}
- Backup Retention: {{ hostvars[inventory_hostname]['backup_retention'] }} days
{% endif %}
{% endif %}
### Related Hosts
{% if inventory_hostname in groups['webservers'] %}
#### Database Servers:
{% for db_host in groups['dbservers'] %}
- {{ db_host }} ({{ hostvars[db_host]['ansible_host'] }})
{% endfor %}
{% endif %}
{% if inventory_hostname in groups['dbservers'] %}
#### Web Servers:
{% for web_host in groups['webservers'] %}
- {{ web_host }} ({{ hostvars[web_host]['ansible_host'] }})
{% endfor %}
{% endif %}
EOF
Create a playbook to generate the documentation:
cat > ~/project/ansible_hostvars/playbooks/host_documentation.yml << 'EOF'
---
- name: Generate host documentation
hosts: all
gather_facts: no
tasks:
- name: Create output directory
file:
path: ~/project/ansible_hostvars/output/docs
state: directory
- name: Generate host documentation
template:
src: ../templates/host_doc.j2
dest: ~/project/ansible_hostvars/output/docs/{{ inventory_hostname }}.md
EOF
Run the documentation playbook:
cd ~/project/ansible_hostvars
ansible-playbook playbooks/host_documentation.yml
View the generated documentation:
ls -l ~/project/ansible_hostvars/output/docs/
cat ~/project/ansible_hostvars/output/docs/web01.md
cat ~/project/ansible_hostvars/output/docs/db01.md
Congratulations! You've now completed a comprehensive exploration of Ansible hostvars, from basic usage to advanced applications. You've learned how to access host variables, use them in templates, and create practical tools for managing your infrastructure.