Ansible Hostvars

AnsibleAnsibleBeginner
今すぐ練習

💡 このチュートリアルは英語版からAIによって翻訳されています。原文を確認するには、 ここをクリックしてください

Introduction

Ansible hostvars are essential variables that store information about each managed host in your infrastructure. These variables enable you to create dynamic, flexible automation workflows that adapt to different servers and environments.

In this hands-on lab, you will learn how to work with Ansible hostvars from the ground up. You will set up a simple inventory, access hostvars in playbooks, use them in templates, and explore practical use cases. By the end of this lab, you will understand how to leverage hostvars to make your Ansible automation more powerful and adaptable.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL ansible(("Ansible")) -.-> ansible/ModuleOperationsGroup(["Module Operations"]) ansible(("Ansible")) -.-> ansible/InventoryManagementGroup(["Inventory Management"]) ansible(("Ansible")) -.-> ansible/PlaybookEssentialsGroup(["Playbook Essentials"]) ansible/ModuleOperationsGroup -.-> ansible/apt("Package Manager") ansible/ModuleOperationsGroup -.-> ansible/command("Execute Commands") ansible/ModuleOperationsGroup -.-> ansible/debug("Test Output") ansible/ModuleOperationsGroup -.-> ansible/file("Manage Files/Directories") ansible/ModuleOperationsGroup -.-> ansible/template("Generate Files from Templates") ansible/InventoryManagementGroup -.-> ansible/group_variables("Set Group Variables") ansible/InventoryManagementGroup -.-> ansible/host_variables("Set Host Variables") ansible/PlaybookEssentialsGroup -.-> ansible/loop("Iteration") subgraph Lab Skills ansible/apt -.-> lab-391846{{"Ansible Hostvars"}} ansible/command -.-> lab-391846{{"Ansible Hostvars"}} ansible/debug -.-> lab-391846{{"Ansible Hostvars"}} ansible/file -.-> lab-391846{{"Ansible Hostvars"}} ansible/template -.-> lab-391846{{"Ansible Hostvars"}} ansible/group_variables -.-> lab-391846{{"Ansible Hostvars"}} ansible/host_variables -.-> lab-391846{{"Ansible Hostvars"}} ansible/loop -.-> lab-391846{{"Ansible Hostvars"}} end

Setting Up the Lab Environment

Before diving into Ansible hostvars, we need to set up our working environment. In this step, we will install Ansible, create a project directory structure, and prepare our inventory file.

Installing Ansible

Let's start by installing Ansible on our system:

sudo apt update
sudo apt install -y ansible

After installation, verify that Ansible is installed correctly:

ansible --version

You should see output similar to this:

ansible [core 2.12.x]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/labex/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3/dist-packages/ansible
  ansible collection location = /home/labex/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.10.x (default, Mar 15 2023, 11:42:32) [GCC 11.3.0]
  jinja version = 3.0.3
  libyaml = True

Creating the Project Structure

Now, let's create a proper directory structure for our Ansible project:

mkdir -p ~/project/ansible_hostvars/inventory
mkdir -p ~/project/ansible_hostvars/group_vars
mkdir -p ~/project/ansible_hostvars/playbooks
mkdir -p ~/project/ansible_hostvars/templates
cd ~/project/ansible_hostvars

Creating an Inventory File

Ansible uses inventory files to define the hosts and groups it will manage. Let's create a simple inventory file with some example hosts:

cat > ~/project/ansible_hostvars/inventory/hosts << 'EOF'
[webservers]
web01 ansible_host=192.168.1.10 http_port=80 max_connections=100
web02 ansible_host=192.168.1.11 http_port=8080 max_connections=200

[dbservers]
db01 ansible_host=192.168.1.20 db_port=3306 backup_dir=/var/backups
db02 ansible_host=192.168.1.21 db_port=5432 backup_dir=/opt/backups

[all:vars]
ansible_connection=local
ansible_user=labex
environment=development
EOF

In this inventory file:

  • We've defined two groups: webservers and dbservers
  • Each host has specific variables like http_port or db_port
  • We've set global variables for all hosts under [all:vars]
  • We're using ansible_connection=local since this is a lab environment

Let's also create a simple ansible.cfg file in our project directory:

cat > ~/project/ansible_hostvars/ansible.cfg << 'EOF'
[defaults]
inventory = ./inventory/hosts
host_key_checking = False
EOF

Now, let's verify our inventory:

cd ~/project/ansible_hostvars
ansible-inventory --list

You should see a JSON output displaying all the hosts and their variables in your inventory.

Congratulations! You've successfully set up your Ansible environment and created an inventory with host variables. In the next step, we'll explore how to access these variables using hostvars.

Exploring Ansible Hostvars

Now that we have our environment set up, let's explore Ansible hostvars and learn how to access them in playbooks.

Understanding Hostvars

In Ansible, hostvars is a special variable that contains information about all hosts in your inventory. It's a dictionary where the keys are hostnames and the values are dictionaries containing all variables defined for each host.

Let's create a simple playbook to explore hostvars:

cat > ~/project/ansible_hostvars/playbooks/explore_hostvars.yml << 'EOF'
---
- name: Explore hostvars
  hosts: all
  gather_facts: no
  tasks:
    - name: Display host variables for the current host
      debug:
        msg: "Host: {{ inventory_hostname }} has the following variables: {{ hostvars[inventory_hostname] }}"
      
    - name: Display a specific variable for the current host
      debug:
        msg: "Host {{ inventory_hostname }} has environment: {{ hostvars[inventory_hostname]['environment'] }}"
EOF

Now, let's run this playbook:

cd ~/project/ansible_hostvars
ansible-playbook playbooks/explore_hostvars.yml

You should see output with each host's variables. The first task shows all variables for each host, while the second task shows a specific variable.

Creating a Host-Specific Variables Playbook

Let's create another playbook that demonstrates how to access different types of host variables:

cat > ~/project/ansible_hostvars/playbooks/host_specific_vars.yml << 'EOF'
---
- name: Working with host-specific variables
  hosts: all
  gather_facts: no
  tasks:
    - name: Display web server information
      debug:
        msg: "Web server {{ inventory_hostname }} running on port {{ hostvars[inventory_hostname]['http_port'] | default('N/A') }}"
      when: inventory_hostname in groups['webservers']
    
    - name: Display database server information
      debug:
        msg: "Database server {{ inventory_hostname }} running on port {{ hostvars[inventory_hostname]['db_port'] | default('N/A') }}"
      when: inventory_hostname in groups['dbservers']
EOF

Run this playbook:

cd ~/project/ansible_hostvars
ansible-playbook playbooks/host_specific_vars.yml

You should see output that shows different information for web servers and database servers, based on their respective variables.

Accessing Variables from Other Hosts

One of the powerful features of hostvars is that you can access variables from any host in your inventory. Let's create a playbook that demonstrates this:

cat > ~/project/ansible_hostvars/playbooks/cross_host_vars.yml << 'EOF'
---
- name: Access variables from other hosts
  hosts: web01
  gather_facts: no
  tasks:
    - name: Display information about web01 and db01
      debug:
        msg: |
          Web server: {{ inventory_hostname }}
          Web server port: {{ hostvars[inventory_hostname]['http_port'] }}
          
          Database server: db01
          Database port: {{ hostvars['db01']['db_port'] }}
          Backup directory: {{ hostvars['db01']['backup_dir'] }}
EOF

Run this playbook:

cd ~/project/ansible_hostvars
ansible-playbook playbooks/cross_host_vars.yml

You should see output that shows information from both web01 and db01, even though the playbook is only running on web01.

This demonstrates how hostvars give you access to variables from all hosts in your inventory, enabling you to create complex relationships and dependencies between hosts in your automation.

Using Hostvars in Templates

Templates are one of the most powerful features in Ansible, and they become even more powerful when combined with hostvars. In this step, we'll learn how to use hostvars within Jinja2 templates to create dynamic configuration files.

Introduction to Jinja2 Templates

Ansible uses the Jinja2 templating engine to generate dynamic content. Templates allow you to create configuration files that adapt to different hosts and scenarios.

Let's create a simple web server configuration template:

mkdir -p ~/project/ansible_hostvars/templates
cat > ~/project/ansible_hostvars/templates/nginx.conf.j2 << 'EOF'
## Server configuration for {{ inventory_hostname }}
## Generated by Ansible

server {
    listen {{ hostvars[inventory_hostname]['http_port'] | default(80) }};
    server_name {{ inventory_hostname }};
    
    root /var/www/html;
    
    ## Environment: {{ hostvars[inventory_hostname]['environment'] }}
    
    ## Max connections: {{ hostvars[inventory_hostname]['max_connections'] | default(50) }}
    
    location / {
        index index.html index.htm;
    }
}
EOF

Now, let's create a database configuration template:

cat > ~/project/ansible_hostvars/templates/db.conf.j2 << 'EOF'
## Database configuration for {{ inventory_hostname }}
## Generated by Ansible

port = {{ hostvars[inventory_hostname]['db_port'] }}
backup_directory = {{ hostvars[inventory_hostname]['backup_dir'] }}
environment = {{ hostvars[inventory_hostname]['environment'] }}

## Database hosts in environment:
{% for host in groups['dbservers'] %}
## - {{ host }} ({{ hostvars[host]['ansible_host'] }})
{% endfor %}
EOF

Creating a Playbook to Apply Templates

Let's create a playbook that applies these templates:

cat > ~/project/ansible_hostvars/playbooks/apply_templates.yml << 'EOF'
---
- name: Apply configuration templates
  hosts: all
  gather_facts: no
  tasks:
    - name: Create output directory
      file:
        path: ~/project/ansible_hostvars/output
        state: directory
      run_once: true
    
    - name: Apply web server configuration template
      template:
        src: ../templates/nginx.conf.j2
        dest: ~/project/ansible_hostvars/output/{{ inventory_hostname }}-nginx.conf
      when: inventory_hostname in groups['webservers']
    
    - name: Apply database configuration template
      template:
        src: ../templates/db.conf.j2
        dest: ~/project/ansible_hostvars/output/{{ inventory_hostname }}-db.conf
      when: inventory_hostname in groups['dbservers']
EOF

Now, let's run this playbook:

cd ~/project/ansible_hostvars
ansible-playbook playbooks/apply_templates.yml

After running the playbook, check the generated configuration files:

ls -l ~/project/ansible_hostvars/output/

You should see configuration files generated for each host. Let's examine one of the web server configurations:

cat ~/project/ansible_hostvars/output/web01-nginx.conf

And one of the database configurations:

cat ~/project/ansible_hostvars/output/db01-db.conf

Notice how the templates use hostvars to dynamically generate configurations tailored to each host.

Using Loops and Conditionals in Templates

Templates can use loops and conditionals to create even more dynamic content. Let's create a comprehensive hosts file template:

cat > ~/project/ansible_hostvars/templates/hosts.j2 << 'EOF'
## Hosts file generated by Ansible
127.0.0.1 localhost

## Web servers
{% for host in groups['webservers'] %}
{{ hostvars[host]['ansible_host'] }} {{ host }}
{% endfor %}

## Database servers
{% for host in groups['dbservers'] %}
{{ hostvars[host]['ansible_host'] }} {{ host }}
{% endfor %}
EOF

Let's add a task to our playbook to apply this template:

cat > ~/project/ansible_hostvars/playbooks/hosts_template.yml << 'EOF'
---
- name: Create hosts file from template
  hosts: localhost
  gather_facts: no
  tasks:
    - name: Create output directory
      file:
        path: ~/project/ansible_hostvars/output
        state: directory
    
    - name: Generate hosts file
      template:
        src: ../templates/hosts.j2
        dest: ~/project/ansible_hostvars/output/hosts
EOF

Run this playbook:

cd ~/project/ansible_hostvars
ansible-playbook playbooks/hosts_template.yml

Check the generated hosts file:

cat ~/project/ansible_hostvars/output/hosts

You should see a hosts file with all your webservers and dbservers, generated dynamically from your inventory.

Advanced Hostvars Techniques

Now that you've mastered the basics of hostvars, let's explore some advanced techniques for working with them in Ansible.

Using Group Variables with Hostvars

Group variables allow you to define variables that apply to entire groups of hosts. Let's create a group variables file:

cat > ~/project/ansible_hostvars/group_vars/webservers.yml << 'EOF'
---
web_server_type: nginx
default_document_root: /var/www/html
enable_ssl: true
ssl_cert_path: /etc/ssl/certs
EOF

And another for the database servers:

cat > ~/project/ansible_hostvars/group_vars/dbservers.yml << 'EOF'
---
backup_frequency: daily
backup_retention: 7
monitoring_enabled: true
alert_email: admin@example.com
EOF

Now, let's create a playbook that accesses these group variables through hostvars:

cat > ~/project/ansible_hostvars/playbooks/group_vars_demo.yml << 'EOF'
---
- name: Demonstrate group variables with hostvars
  hosts: all
  gather_facts: no
  tasks:
    - name: Display web server group variables
      debug:
        msg: |
          Host: {{ inventory_hostname }}
          Web Server Type: {{ hostvars[inventory_hostname]['web_server_type'] | default('N/A') }}
          Document Root: {{ hostvars[inventory_hostname]['default_document_root'] | default('N/A') }}
          SSL Enabled: {{ hostvars[inventory_hostname]['enable_ssl'] | default('N/A') }}
      when: inventory_hostname in groups['webservers']
    
    - name: Display database server group variables
      debug:
        msg: |
          Host: {{ inventory_hostname }}
          Backup Frequency: {{ hostvars[inventory_hostname]['backup_frequency'] | default('N/A') }}
          Backup Retention: {{ hostvars[inventory_hostname]['backup_retention'] | default('N/A') }}
          Monitoring Enabled: {{ hostvars[inventory_hostname]['monitoring_enabled'] | default('N/A') }}
      when: inventory_hostname in groups['dbservers']
EOF

Run this playbook:

cd ~/project/ansible_hostvars
ansible-playbook playbooks/group_vars_demo.yml

You should see output showing how group variables are available through hostvars.

Creating Dynamic Inventory Reports

Let's create a playbook that generates reports based on inventory data:

cat > ~/project/ansible_hostvars/playbooks/inventory_report.yml << 'EOF'
---
- name: Generate inventory reports
  hosts: localhost
  gather_facts: no
  tasks:
    - name: Create output directory
      file:
        path: ~/project/ansible_hostvars/output
        state: directory
    
    - name: Generate web servers report
      template:
        src: ../templates/web_report.j2
        dest: ~/project/ansible_hostvars/output/web_servers_report.txt
    
    - name: Generate database servers report
      template:
        src: ../templates/db_report.j2
        dest: ~/project/ansible_hostvars/output/db_servers_report.txt
EOF

Now, let's create the templates for these reports:

cat > ~/project/ansible_hostvars/templates/web_report.j2 << 'EOF'
========================================
WEB SERVERS INVENTORY REPORT
========================================
Generated: {{ ansible_date_time.date }}

{% for host in groups['webservers'] %}
HOST: {{ host }}
  IP Address: {{ hostvars[host]['ansible_host'] }}
  HTTP Port: {{ hostvars[host]['http_port'] }}
  Max Connections: {{ hostvars[host]['max_connections'] | default('Not specified') }}
  Web Server Type: {{ hostvars[host]['web_server_type'] | default('Not specified') }}
  Environment: {{ hostvars[host]['environment'] }}

{% endfor %}
EOF
cat > ~/project/ansible_hostvars/templates/db_report.j2 << 'EOF'
========================================
DATABASE SERVERS INVENTORY REPORT
========================================
Generated: {{ ansible_date_time.date }}

{% for host in groups['dbservers'] %}
HOST: {{ host }}
  IP Address: {{ hostvars[host]['ansible_host'] }}
  DB Port: {{ hostvars[host]['db_port'] }}
  Backup Directory: {{ hostvars[host]['backup_dir'] }}
  Backup Frequency: {{ hostvars[host]['backup_frequency'] | default('Not specified') }}
  Backup Retention: {{ hostvars[host]['backup_retention'] | default('Not specified') }}
  Environment: {{ hostvars[host]['environment'] }}

{% endfor %}
EOF

Before running this playbook, we need to gather some facts for the date:

cat > ~/project/ansible_hostvars/playbooks/setup.yml << 'EOF'
---
- name: Setup for other playbooks
  hosts: localhost
  gather_facts: yes
  tasks:
    - name: Create timestamp file
      copy:
        content: "{{ ansible_date_time.date }}"
        dest: ~/project/ansible_hostvars/output/timestamp.txt
EOF

Run the setup playbook:

cd ~/project/ansible_hostvars
ansible-playbook playbooks/setup.yml

Now, run the inventory report playbook:

cd ~/project/ansible_hostvars
ansible-playbook playbooks/inventory_report.yml

Check the generated reports:

cat ~/project/ansible_hostvars/output/web_servers_report.txt
cat ~/project/ansible_hostvars/output/db_servers_report.txt

These reports demonstrate how hostvars can be used to create comprehensive reports of your infrastructure.

Handling Missing Variables

When working with hostvars, it's important to handle cases where variables might be missing. Let's create a playbook that demonstrates safe variable access:

cat > ~/project/ansible_hostvars/playbooks/safe_variable_access.yml << 'EOF'
---
- name: Demonstrate safe variable access
  hosts: all
  gather_facts: no
  tasks:
    - name: Using default filter
      debug:
        msg: "The value is: {{ hostvars[inventory_hostname]['nonexistent_variable'] | default('Not defined') }}"
    
    - name: Using conditional checks
      debug:
        msg: >
          {% if 'special_variable' in hostvars[inventory_hostname] %}
          The special variable is: {{ hostvars[inventory_hostname]['special_variable'] }}
          {% else %}
          The special variable is not defined for this host.
          {% endif %}
EOF

Run this playbook:

cd ~/project/ansible_hostvars
ansible-playbook playbooks/safe_variable_access.yml

The output shows how to safely handle missing variables using the default filter and conditional checks.

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

Creating a Host Documentation Tool

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.

Summary

In this lab, you explored the power and versatility of Ansible hostvars. Here's what you learned:

  1. Setting Up the Environment: You configured an Ansible environment with an inventory structure that included hosts, groups, and variables.

  2. Exploring Hostvars: You learned how to access hostvars in playbooks, including accessing variables from the current host and from other hosts in the inventory.

  3. Using Hostvars in Templates: You created Jinja2 templates that leverage hostvars to generate dynamic configuration files tailored to each host.

  4. Advanced Hostvars Techniques: You explored group variables, dynamic inventory reports, and techniques for handling missing variables safely.

  5. Best Practices and Real-World Applications: You implemented structured variable organization and created practical applications, including a configuration generator and a host documentation tool.

Ansible hostvars are a powerful feature that allows you to create dynamic, adaptable automation workflows. By understanding how to effectively work with hostvars, you can create more flexible and maintainable automation solutions for your infrastructure.

As you continue your Ansible journey, remember that hostvars are just one part of Ansible's rich ecosystem of features. Consider exploring other features like roles, collections, and dynamic inventories to further enhance your automation capabilities.