AnsiblePilot — Master Ansible Automation

AnsiblePilot is the leading resource for learning Ansible automation, DevOps, and infrastructure as code. Browse over 1,400 tutorials covering Ansible modules, playbooks, roles, collections, and real-world examples. Whether you are a beginner or an experienced engineer, our step-by-step guides help you automate Linux, Windows, cloud, containers, and network infrastructure.

Popular Topics

About Luca Berton

Luca Berton is an Ansible automation expert, author of 8 Ansible books published by Apress and Leanpub including "Ansible for VMware by Examples" and "Ansible for Kubernetes by Example", and creator of the Ansible Pilot YouTube channel. He shares practical automation knowledge through tutorials, books, and video courses to help IT professionals and DevOps engineers master infrastructure automation.

Generate Clean YAML Output from Ansible Facts

By Luca Berton · Published 2024-01-01 · Category: networking

Discover how to generate clean YAML output from Ansible facts using Jinja2 templating, ensuring properly formatted data for easy reporting.

Generate Clean YAML Output from Ansible Facts

Ansible is a powerful tool for automating tasks, but when working with dynamically generated data, such as Ansible facts, it can sometimes be tricky to produce clean, well-formatted output. This article demonstrates how to use Jinja2 templating within an Ansible playbook to transform facts into clean YAML, ensuring proper indentation and formatting.

In this example, we'll look at a different scenario: transforming networking data (like interfaces, IP addresses, and MAC addresses) into a nicely formatted YAML structure. We'll cover how to loop through facts, control whitespace in Jinja2, and generate a neat YAML file.

Scenario: Formatting Network Interfaces

Imagine you are managing a fleet of servers and you need to produce a YAML report that lists each network interface's details, including its name, IP address, MAC address, and the status of the connection.

Here's an Ansible task that gathers network facts and formats them into clean YAML output.

Ansible Playbook Example

---
- name: Generate network interface report
  hosts: localhost
  gather_facts: yes
  tasks:
    - name: Transform network interfaces into YAML
      set_fact:
        network_yaml: |
          interfaces:
            {% for iface_name, iface_data in ansible_facts['ansible_interfaces'].items() %}
            - name: {{ iface_name }}
              mac_address: {{ iface_data.macaddress | default('unknown') }}
              ip_address: {{ iface_data.ipv4.address | default('N/A') }}
              status: {{ iface_data.active | ternary('up', 'down') }}
            {% endfor %}

- name: Save the formatted network interfaces to a file copy: content: "{{ network_yaml }}" dest: /tmp/network_interfaces.yaml

Breaking Down the Example

Gathering Facts: We start by setting gather_facts: yes, which collects information about the target machine. In this case, we focus on the ansible_interfaces fact, which contains data about each network interface on the machine. Looping Through Interfaces: Using Jinja2 templating, we iterate over the ansible_interfaces dictionary. For each interface, we access its name, MAC address, IP address, and status (whether it's active or inactive). Whitespace Control: Proper indentation is crucial in YAML, so we ensure that the loop outputs are correctly aligned by adjusting the placement of the Jinja2 tags within the template. Using Filters: • default: If a MAC address or IP is not present, we use this filter to insert a default value ('unknown' or 'N/A'). • ternary: This filter is used to convert the active boolean value into human-readable statuses ('up' for true, 'down' for false). Saving the Output: The copy module saves the generated YAML content to /tmp/network_interfaces.yaml.

Sample Output

When this playbook is run on a machine, the output YAML file might look like this:

interfaces:
  - name: eth0
    mac_address: 02:42:ac:11:00:02
    ip_address: 192.168.1.100
    status: up
  - name: eth1
    mac_address: 02:42:ac:11:00:03
    ip_address: N/A
    status: down
  - name: wlan0
    mac_address: 3c:22:fb:4e:88:67
    ip_address: 10.0.0.5
    status: up

Understanding YAML Formatting in Ansible

Why Use YAML for Reporting?

YAML (YAML Ain't Markup Language) is highly readable, human-friendly, and widely used in configuration management. With Ansible, generating YAML reports makes it easy for both humans and systems to process structured data. This format is perfect for representing complex data such as server configurations, network interfaces, disk details, etc.

Controlling Indentation with Jinja2

One of the key challenges in formatting YAML using Jinja2 is controlling indentation. If you're unfamiliar with how loops and conditionals work in Jinja2 templates, you might end up with broken YAML due to extra spaces or newlines. Here's how we ensure indentation is handled correctly: • Template Syntax: Make sure your for and endfor statements are placed at the right level of indentation relative to the output. For example:
    {% for item in items %}
    - key: {{ item.key }}
    {% endfor %}
    
Avoid Extra Newlines: Jinja2 can add unwanted newlines. If you need more control, you can use whitespace control operators like {{- and -}} to strip leading and trailing whitespace.

Simplifying the Task with the to_nice_yaml Filter

Ansible also provides the to_nice_yaml filter, which automatically converts a dictionary into well-formatted YAML. If your scenario doesn't require complex transformations or loops, you can use this filter to simplify the process.

Here’s a simplified version of the same task using to_nice_yaml:

- name: Transform network interfaces using to_nice_yaml
  set_fact:
    network_data: |
      {{ ansible_facts['ansible_interfaces'] | to_nice_yaml }}

- name: Save the formatted YAML to a file copy: content: "{{ network_data }}" dest: /tmp/network_interfaces.yaml

In this version, we let Ansible handle the formatting, and we skip the manual template building. This is particularly useful if you don't need to apply custom logic (such as filtering or transforming values).

Conclusion

Generating well-formatted YAML from Ansible facts is a powerful way to extract and report on dynamic data in your infrastructure. By using Jinja2 templates or Ansible's built-in filters like to_nice_yaml, you can output clean and structured YAML files that can be easily read by both humans and machines.

This technique is highly flexible and can be adapted to various scenarios, whether you're reporting on network interfaces, disk usage, or any other aspect of your systems. By understanding how to manage indentation and control whitespace in your templates, you can ensure that your YAML output is always clean and properly formatted.

Related Articles

using ansible.builtin.template effectivelythe Ansible conditionals referencecapturing output with Ansible commandlooping over dictionaries in Ansible

Category: networking

Browse all Ansible tutorials · AnsiblePilot Home