Ansible - how to compare two dictionaries with same keys

Viewed 5396

I have two dictionaries:

source_list:
  myFlag1: true
  MyFlag2: false

And second dict:

target_list:
  MyFlag1: false
  MyFlag2: false

Keys are identical always, but the order is not strict yet. How can i highlight the difference between them? I can use dict2items to convert lists to

source_list:
  - key: MyFlag1
    value: true
  - key: MyFlag2
    value: false

But again i'm confused, how can i compare them... Of course, i can loop ov er two dicts and compare it one by one, but it doesn't look really effective. Any help will be highly appreciated!

1 Answers

Q: "How to compare two dictionaries with the same keys?"

A: Given the simplified data for testing

    s:
      flag1: true
      Flag3: true
      flag2: false
    t:
      flag3: true
      flag1: false
      flag2: false
  • Compare the variables to briefly find out whether there are any differences or not, e.g.
    - debug:
        msg: The dictionaries are identical
      when: s == t
    - debug:
        msg: The dictionaries are different
      when: s != t

gives

  msg: The dictionaries are different
  • Next, compare the keys, e.g. declare the variables
    s_keys: "{{ s.keys()|list }}"
    t_keys: "{{ t.keys()|list }}"
    diff_keys: "{{ s_keys|symmetric_difference(t_keys) }}"

and test the length of the symmetric_difference

    - debug:
        msg: "The difference in the keys: {{ diff_keys }}"
      when:  diff_keys|length != 0

gives

  msg: 'The difference in the keys: [''Flag3'', ''flag3'']'
  • Let's assume dictionaries with identical keys to finding different values, e.g.
    s:
      flag1: true
      flag3: true
      flag2: false
    t:
      flag3: true
      flag1: false
      flag2: false
  • Iterate the list of keys and compare the dictionaries item by item, e.g.
    - debug:
        msg: "{{ item }} is {{ (s[item] == t[item])|ternary('OK', 'KO') }}"
      loop: "{{ s.keys()|sort }}"
      when:  diff_keys|length == 0

gives

  msg: flag1 is KO
  msg: flag2 is OK
  msg: flag3 is OK

Q: "How can I highlight the difference between them?"

A: Create a dictionary with the different values only, e.g.

    - set_fact:
        diff_vals: "{{ diff_vals|d({})|combine({item: s[item]}) }}"
      loop: "{{ s.keys()|sort }}"
      when:
        - diff_keys|length == 0
        - s[item] != t[item]
    - debug:
        var: diff_vals

gives

  diff_vals:
    flag1: true

Example of a complete playbook

- hosts: localhost
  gather_facts: false

  vars:
    s:
      flag1: true
      flag3: true
      flag2: false
    t:
      flag3: true
      flag1: false
      flag2: false
    
    s_keys: "{{ s.keys()|list }}"
    t_keys: "{{ t.keys()|list }}"
    diff_keys: "{{ s_keys|symmetric_difference(t_keys) }}"

  tasks:

    - debug:
        msg: The dictionaries are identical
      when: s == t
    - debug:
        msg: The dictionaries are different
      when: s != t

    - debug:
        msg: "The difference in the keys: {{ diff_keys }}"
      when:  diff_keys|length != 0

    - debug:
        msg: "{{ item }} is {{ (s[item] == t[item])|ternary('OK', 'KO') }}"
      loop: "{{ s.keys()|sort }}"
      when:  diff_keys|length == 0

    - set_fact:
        diff_vals: "{{ diff_vals|d({})|combine({item: s[item]}) }}"
      loop: "{{ s.keys()|sort }}"
      when:
        - diff_keys|length == 0
        - s[item] != t[item]
    - debug:
        var: diff_vals
Related