Practical Example: Reading Ansible Inventory YAMLs

🏷️ Structured Data Formats: JSON, YAML, and CSV / YAML Processing


🧠 Context Introduction

Ansible is a widely used automation tool, and its inventory filesβ€”which define the hosts and groups you manageβ€”are typically written in YAML. For engineers working with automation pipelines, being able to read, parse, and manipulate these YAML inventory files programmatically is a valuable skill. This allows you to dynamically generate inventories, validate configurations, or extract specific host information for reporting or monitoring purposes.

In this guide, we'll walk through a practical example of reading an Ansible inventory YAML file using Python's PyYAML library, breaking down each step in a simple, clear manner.


βš™οΈ What is an Ansible Inventory YAML?

An Ansible inventory file written in YAML defines:

  • Hosts: Individual machines (e.g., web servers, database servers).
  • Groups: Logical collections of hosts (e.g., webservers, databases).
  • Variables: Key-value pairs that apply to hosts or groups (e.g., ansible_user, http_port).

A typical inventory YAML looks like this:

  • all: The root group containing all hosts.
  • children: Sub-groups under all.
  • hosts: Individual machines listed under a group.
  • vars: Variables specific to a group or host.

πŸ› οΈ Step 1: Install the Required Library

Before we can read YAML files in Python, we need the PyYAML library.

  • Install it using pip: pip install pyyaml
  • This library provides functions to parse YAML content into Python dictionaries and lists.

πŸ•΅οΈ Step 2: Reading the YAML File

We'll use a sample inventory file named inventory.yml with the following structure:

  • all group contains:
  • children:
    • webservers group with hosts: web1.example.com and web2.example.com
    • databases group with hosts: db1.example.com and db2.example.com
  • vars:
    • ansible_user: admin
    • ansible_port: 22

To read this file in Python:

  • Import the yaml module.
  • Open the file using Python's built-in open() function.
  • Use yaml.safe_load() to parse the file content into a Python dictionary.

Example code flow:

  • import yaml
  • with open('inventory.yml', 'r') as file:
  • data = yaml.safe_load(file)
  • The variable data now holds the entire inventory as a nested Python dictionary.

πŸ“Š Step 3: Exploring the Parsed Data

Once the YAML is loaded, we can explore its structure using Python dictionary methods.

  • To see all top-level keys: data.keys() returns dict_keys(['all'])
  • To access the children section: data['all']['children'] returns a dictionary of groups.
  • To list all groups: data['all']['children'].keys() returns dict_keys(['webservers', 'databases'])
  • To get hosts under webservers: data['all']['children']['webservers']['hosts'] returns a dictionary of host names.
  • To access global variables: data['all']['vars'] returns {'ansible_user': 'admin', 'ansible_port': 22}

🧩 Step 4: Extracting Specific Information

Let's say we want to extract all hostnames from the inventory for reporting.

We can loop through each group and collect the hostnames:

  • Initialize an empty list: all_hosts = []
  • Loop through each group in data['all']['children']:
  • For each group, access its hosts key.
  • Loop through the hosts and append each hostname to all_hosts.
  • The final list all_hosts will contain: ['web1.example.com', 'web2.example.com', 'db1.example.com', 'db2.example.com']

πŸ§ͺ Step 5: Handling Nested Variables

Sometimes variables are defined at the group level or even at the host level. To retrieve all variables for a specific host:

  • Access the host's group first.
  • Check if the host has its own vars section.
  • Merge group-level variables with host-level variables if needed.

For example, if web1.example.com has a custom variable http_port: 8080, we can access it as:

  • data['all']['children']['webservers']['hosts']['web1.example.com']['http_port']

πŸ“‹ Comparison: YAML vs Python Dictionary

YAML Structure Python Equivalent
all: Dictionary key 'all'
children: Dictionary key 'children'
webservers: Dictionary key 'webservers'
hosts: Dictionary key 'hosts'
web1.example.com: Dictionary key 'web1.example.com'
vars: Dictionary key 'vars'
ansible_user: admin Key-value pair 'ansible_user': 'admin'

🧹 Step 6: Validating the Inventory Structure

Before processing, it's good practice to validate that the inventory has the expected structure.

  • Check if the 'all' key exists: if 'all' in data:
  • Check if 'children' exists under 'all': if 'children' in data['all']:
  • Check if a specific group exists: if 'webservers' in data['all']['children']:
  • This prevents KeyError exceptions when accessing nested data.

πŸš€ Practical Use Case: Generating a Host List for Monitoring

Imagine you need to generate a simple text file listing all hosts for a monitoring tool.

Steps:

  1. Read the inventory YAML as shown above.
  2. Extract all hostnames into a list.
  3. Write each hostname to a new file, one per line.

The output file would contain:

  • web1.example.com
  • web2.example.com
  • db1.example.com
  • db2.example.com

βœ… Summary

  • Ansible inventory YAML files are structured as nested dictionaries in Python.
  • The PyYAML library's yaml.safe_load() function converts YAML to Python data structures.
  • Access hosts, groups, and variables using standard dictionary key lookups.
  • Always validate the structure before accessing nested keys to avoid errors.
  • This approach allows you to dynamically process inventories for automation, reporting, or integration with other tools.

πŸ“š Next Steps

  • Experiment with more complex inventory files that include nested groups or host-specific variables.
  • Learn to write or modify YAML files using yaml.dump().
  • Explore error handling with try-except blocks when reading files or parsing YAML.

Happy automating!


This example shows how to read and work with Ansible inventory files in YAML format using Python's yaml library.

🐍 Example 1: Reading a simple Ansible inventory file

This example loads a basic inventory with one host group and prints the group name.

import yaml

inventory_yaml = """
all:
  hosts:
    webserver01:
      ansible_host: 192.168.1.10
"""

inventory = yaml.safe_load(inventory_yaml)
print(inventory["all"]["hosts"].keys())

πŸ“€ Output: dict_keys(['webserver01'])


🐍 Example 2: Accessing host variables from an inventory

This example reads host-specific variables like IP addresses from the inventory.

import yaml

inventory_yaml = """
all:
  hosts:
    webserver01:
      ansible_host: 192.168.1.10
      ansible_user: admin
    dbserver01:
      ansible_host: 192.168.1.20
      ansible_user: dbadmin
"""

inventory = yaml.safe_load(inventory_yaml)
for host, vars in inventory["all"]["hosts"].items():
    print(f"{host}: {vars['ansible_host']}")

πŸ“€ Output: webserver01: 192.168.1.10
dbserver01: 192.168.1.20


🐍 Example 3: Working with host groups and children

This example reads a multi-group inventory and lists all hosts in each group.

import yaml

inventory_yaml = """
all:
  children:
    webservers:
      hosts:
        web01:
          ansible_host: 10.0.0.1
        web02:
          ansible_host: 10.0.0.2
    databases:
      hosts:
        db01:
          ansible_host: 10.0.1.1
"""

inventory = yaml.safe_load(inventory_yaml)
for group, data in inventory["all"]["children"].items():
    hosts = list(data["hosts"].keys())
    print(f"Group '{group}': {hosts}")

πŸ“€ Output: Group 'webservers': ['web01', 'web02']
Group 'databases': ['db01']


🐍 Example 4: Extracting all host IPs from a nested inventory

This example flattens a multi-group inventory into a simple list of all host IP addresses.

import yaml

inventory_yaml = """
all:
  children:
    webservers:
      hosts:
        web01:
          ansible_host: 10.0.0.1
        web02:
          ansible_host: 10.0.0.2
    databases:
      hosts:
        db01:
          ansible_host: 10.0.1.1
        db02:
          ansible_host: 10.0.1.2
"""

inventory = yaml.safe_load(inventory_yaml)
all_ips = []
for group in inventory["all"]["children"].values():
    for host_vars in group["hosts"].values():
        all_ips.append(host_vars["ansible_host"])
print(all_ips)

πŸ“€ Output: ['10.0.0.1', '10.0.0.2', '10.0.1.1', '10.0.1.2']


🐍 Example 5: Reading an inventory from a file and filtering by group

This example loads an actual YAML file and prints only hosts in the "webservers" group.

import yaml

with open("inventory.yml", "r") as file:
    inventory = yaml.safe_load(file)

webserver_hosts = inventory["all"]["children"]["webservers"]["hosts"]
for host, vars in webserver_hosts.items():
    print(f"{host} -> {vars['ansible_host']}")

πŸ“€ Output: web01 -> 10.0.0.1
web02 -> 10.0.0.2


Comparison Table

Feature Example 1 Example 2 Example 3 Example 4 Example 5
Reads from string βœ… βœ… βœ… βœ… ❌ (file)
Accesses host variables ❌ βœ… βœ… βœ… βœ…
Handles multiple groups ❌ ❌ βœ… βœ… βœ…
Flattens nested data ❌ ❌ ❌ βœ… ❌
Uses file input ❌ ❌ ❌ ❌ βœ…

🧠 Context Introduction

Ansible is a widely used automation tool, and its inventory filesβ€”which define the hosts and groups you manageβ€”are typically written in YAML. For engineers working with automation pipelines, being able to read, parse, and manipulate these YAML inventory files programmatically is a valuable skill. This allows you to dynamically generate inventories, validate configurations, or extract specific host information for reporting or monitoring purposes.

In this guide, we'll walk through a practical example of reading an Ansible inventory YAML file using Python's PyYAML library, breaking down each step in a simple, clear manner.


βš™οΈ What is an Ansible Inventory YAML?

An Ansible inventory file written in YAML defines:

  • Hosts: Individual machines (e.g., web servers, database servers).
  • Groups: Logical collections of hosts (e.g., webservers, databases).
  • Variables: Key-value pairs that apply to hosts or groups (e.g., ansible_user, http_port).

A typical inventory YAML looks like this:

  • all: The root group containing all hosts.
  • children: Sub-groups under all.
  • hosts: Individual machines listed under a group.
  • vars: Variables specific to a group or host.

πŸ› οΈ Step 1: Install the Required Library

Before we can read YAML files in Python, we need the PyYAML library.

  • Install it using pip: pip install pyyaml
  • This library provides functions to parse YAML content into Python dictionaries and lists.

πŸ•΅οΈ Step 2: Reading the YAML File

We'll use a sample inventory file named inventory.yml with the following structure:

  • all group contains:
  • children:
    • webservers group with hosts: web1.example.com and web2.example.com
    • databases group with hosts: db1.example.com and db2.example.com
  • vars:
    • ansible_user: admin
    • ansible_port: 22

To read this file in Python:

  • Import the yaml module.
  • Open the file using Python's built-in open() function.
  • Use yaml.safe_load() to parse the file content into a Python dictionary.

Example code flow:

  • import yaml
  • with open('inventory.yml', 'r') as file:
  • data = yaml.safe_load(file)
  • The variable data now holds the entire inventory as a nested Python dictionary.

πŸ“Š Step 3: Exploring the Parsed Data

Once the YAML is loaded, we can explore its structure using Python dictionary methods.

  • To see all top-level keys: data.keys() returns dict_keys(['all'])
  • To access the children section: data['all']['children'] returns a dictionary of groups.
  • To list all groups: data['all']['children'].keys() returns dict_keys(['webservers', 'databases'])
  • To get hosts under webservers: data['all']['children']['webservers']['hosts'] returns a dictionary of host names.
  • To access global variables: data['all']['vars'] returns {'ansible_user': 'admin', 'ansible_port': 22}

🧩 Step 4: Extracting Specific Information

Let's say we want to extract all hostnames from the inventory for reporting.

We can loop through each group and collect the hostnames:

  • Initialize an empty list: all_hosts = []
  • Loop through each group in data['all']['children']:
  • For each group, access its hosts key.
  • Loop through the hosts and append each hostname to all_hosts.
  • The final list all_hosts will contain: ['web1.example.com', 'web2.example.com', 'db1.example.com', 'db2.example.com']

πŸ§ͺ Step 5: Handling Nested Variables

Sometimes variables are defined at the group level or even at the host level. To retrieve all variables for a specific host:

  • Access the host's group first.
  • Check if the host has its own vars section.
  • Merge group-level variables with host-level variables if needed.

For example, if web1.example.com has a custom variable http_port: 8080, we can access it as:

  • data['all']['children']['webservers']['hosts']['web1.example.com']['http_port']

πŸ“‹ Comparison: YAML vs Python Dictionary

YAML Structure Python Equivalent
all: Dictionary key 'all'
children: Dictionary key 'children'
webservers: Dictionary key 'webservers'
hosts: Dictionary key 'hosts'
web1.example.com: Dictionary key 'web1.example.com'
vars: Dictionary key 'vars'
ansible_user: admin Key-value pair 'ansible_user': 'admin'

🧹 Step 6: Validating the Inventory Structure

Before processing, it's good practice to validate that the inventory has the expected structure.

  • Check if the 'all' key exists: if 'all' in data:
  • Check if 'children' exists under 'all': if 'children' in data['all']:
  • Check if a specific group exists: if 'webservers' in data['all']['children']:
  • This prevents KeyError exceptions when accessing nested data.

πŸš€ Practical Use Case: Generating a Host List for Monitoring

Imagine you need to generate a simple text file listing all hosts for a monitoring tool.

Steps:

  1. Read the inventory YAML as shown above.
  2. Extract all hostnames into a list.
  3. Write each hostname to a new file, one per line.

The output file would contain:

  • web1.example.com
  • web2.example.com
  • db1.example.com
  • db2.example.com

βœ… Summary

  • Ansible inventory YAML files are structured as nested dictionaries in Python.
  • The PyYAML library's yaml.safe_load() function converts YAML to Python data structures.
  • Access hosts, groups, and variables using standard dictionary key lookups.
  • Always validate the structure before accessing nested keys to avoid errors.
  • This approach allows you to dynamically process inventories for automation, reporting, or integration with other tools.

πŸ“š Next Steps

  • Experiment with more complex inventory files that include nested groups or host-specific variables.
  • Learn to write or modify YAML files using yaml.dump().
  • Explore error handling with try-except blocks when reading files or parsing YAML.

Happy automating!

Interactive Views

You are currently in πŸ“š All-in-One mode. Use the tabs at the top to switch to πŸ“– Theory Only or πŸ’» Code Only views.

This example shows how to read and work with Ansible inventory files in YAML format using Python's yaml library.

🐍 Example 1: Reading a simple Ansible inventory file

This example loads a basic inventory with one host group and prints the group name.

import yaml

inventory_yaml = """
all:
  hosts:
    webserver01:
      ansible_host: 192.168.1.10
"""

inventory = yaml.safe_load(inventory_yaml)
print(inventory["all"]["hosts"].keys())

πŸ“€ Output: dict_keys(['webserver01'])


🐍 Example 2: Accessing host variables from an inventory

This example reads host-specific variables like IP addresses from the inventory.

import yaml

inventory_yaml = """
all:
  hosts:
    webserver01:
      ansible_host: 192.168.1.10
      ansible_user: admin
    dbserver01:
      ansible_host: 192.168.1.20
      ansible_user: dbadmin
"""

inventory = yaml.safe_load(inventory_yaml)
for host, vars in inventory["all"]["hosts"].items():
    print(f"{host}: {vars['ansible_host']}")

πŸ“€ Output: webserver01: 192.168.1.10
dbserver01: 192.168.1.20


🐍 Example 3: Working with host groups and children

This example reads a multi-group inventory and lists all hosts in each group.

import yaml

inventory_yaml = """
all:
  children:
    webservers:
      hosts:
        web01:
          ansible_host: 10.0.0.1
        web02:
          ansible_host: 10.0.0.2
    databases:
      hosts:
        db01:
          ansible_host: 10.0.1.1
"""

inventory = yaml.safe_load(inventory_yaml)
for group, data in inventory["all"]["children"].items():
    hosts = list(data["hosts"].keys())
    print(f"Group '{group}': {hosts}")

πŸ“€ Output: Group 'webservers': ['web01', 'web02']
Group 'databases': ['db01']


🐍 Example 4: Extracting all host IPs from a nested inventory

This example flattens a multi-group inventory into a simple list of all host IP addresses.

import yaml

inventory_yaml = """
all:
  children:
    webservers:
      hosts:
        web01:
          ansible_host: 10.0.0.1
        web02:
          ansible_host: 10.0.0.2
    databases:
      hosts:
        db01:
          ansible_host: 10.0.1.1
        db02:
          ansible_host: 10.0.1.2
"""

inventory = yaml.safe_load(inventory_yaml)
all_ips = []
for group in inventory["all"]["children"].values():
    for host_vars in group["hosts"].values():
        all_ips.append(host_vars["ansible_host"])
print(all_ips)

πŸ“€ Output: ['10.0.0.1', '10.0.0.2', '10.0.1.1', '10.0.1.2']


🐍 Example 5: Reading an inventory from a file and filtering by group

This example loads an actual YAML file and prints only hosts in the "webservers" group.

import yaml

with open("inventory.yml", "r") as file:
    inventory = yaml.safe_load(file)

webserver_hosts = inventory["all"]["children"]["webservers"]["hosts"]
for host, vars in webserver_hosts.items():
    print(f"{host} -> {vars['ansible_host']}")

πŸ“€ Output: web01 -> 10.0.0.1
web02 -> 10.0.0.2


Comparison Table

Feature Example 1 Example 2 Example 3 Example 4 Example 5
Reads from string βœ… βœ… βœ… βœ… ❌ (file)
Accesses host variables ❌ βœ… βœ… βœ… βœ…
Handles multiple groups ❌ ❌ βœ… βœ… βœ…
Flattens nested data ❌ ❌ ❌ βœ… ❌
Uses file input ❌ ❌ ❌ ❌ βœ