Introduction

When working with Ansible playbooks, comparing two lists is a common task, especially for validating data consistency in automation workflows. However, users often encounter issues with filters like length, particularly in older Ansible versions or due to syntax ambiguities. This guide demonstrates how to effectively compare lists, ensuring they match in both size and content.


The Scenario: Comparing Two Lists

Consider the following two lists:

list_one:
  - { name: "foo" }
  - { name: "bar" }
  - { name: "baz" }
  - { name: "qux" }
  - { name: "quux" }

list_two:
  - { name: "foo" }
  - { name: "bar" }
  - { name: "baz" }
  - { name: "quux" }

The goal is to:

  1. Verify that both lists are of equal length.
  2. Check that all elements in list_one are present in list_two, and vice versa.
  3. Fail gracefully if there are mismatches.

Playbook: Comparing Two Lists

Here’s the complete playbook to achieve this:

Example Playbook

---
- name: Compare two lists
  hosts: localhost
  vars:
    list_one:
      - { name: "foo" }
      - { name: "bar" }
      - { name: "baz" }
      - { name: "qux" }
      - { name: "quux" }
    list_two:
      - { name: "foo" }
      - { name: "bar" }
      - { name: "baz" }
      - { name: "quux" }
  tasks:
    - name: Verify if lengths of both lists are equal
      debug:
        msg: "The lists are of equal length."
      when: 
        - "{{ list_one | length == list_two | length }}"

    - name: Verify if all names in list_one are in list_two
      debug:
        msg: "All names in list_one are present in list_two."
      when: 
        - "{{ list_one | map(attribute='name') | difference(list_two | map(attribute='name')) | length  == 0 }}"

    - name: Verify if all names in list_two are in list_one
      debug:
        msg: "All names in list_two are present in list_one."
      when: 
        - "{{ list_two | map(attribute='name') | difference(list_one | map(attribute='name')) | length == 0 }}"

    - name: Fail if lists are not of equal length or contain different elements
      fail:
        msg: "The lists do not match in length or elements."
      when: 
        - "{{ list_one | length !=  list_two | length }}"
        - "{{ list_one | map(attribute='name') | difference(list_two | map(attribute='name')) | length != 0 }}"
        - "{{ list_two | map(attribute='name') | difference(list_one | map(attribute='name')) | length != 0 }}"

Key Features of the Playbook

Length Comparison

  • Ensures both lists are of the same size using the length filter.

Element Comparison

  • Extracts name attributes with map(attribute='name').
  • Uses the difference filter to identify mismatched elements between the lists.

Fail Gracefully

  • The fail module provides clear error feedback when the lists differ in length or content.

Why It Works

  1. Explicit Template Syntax:

    • Wrapping conditions in {{ ... }} ensures clear, unambiguous Jinja2 evaluation.
  2. Robust Filters:

    • Filters like length, map, and difference are reliable tools for list manipulation.
  3. Error Handling:

    • By using the fail module, you can terminate playbook execution with descriptive errors when conditions are not met.

Conclusion

Comparing lists in Ansible is straightforward with the right tools and syntax. By addressing common pitfalls, like ambiguous filter usage, you can create reliable playbooks that validate data effectively. Use this approach to ensure data integrity in your automation workflows.

Subscribe to the YouTube channel, Medium, and Website, X (formerly Twitter) to not miss the next episode of the Ansible Pilot.

Academy

Learn the Ansible automation technology with real-life examples in my Udemy 300+ Lessons Video Course.

BUY the Complete Udemy 300+ Lessons Video Course

Explore my book Ansible By Examples: 200+ Automation Examples for Linux and Windows System Administrators and DevOps:

BUY the Complete PDF BOOK to easily Copy and Paste the 250+ Ansible code

Support this project and keep learning resources alive: Patreon Buy me a Pizza