Search code examples
dynamicansibleansible-inventory

How to compare variables from a dynamic inventory in ansible


I've been trying to create a playbook that will compare counts of a file from different hosts.

  - shell: << code to count number of lines >> 
    register: record_count

  - debug:
      msg: "The count is {{ record_count.stdout }}"

- hosts: localhost
  tasks:

  - name: Fail if the count doesnt match
    fail:
      msg: "The record count is not matching on both the export files."
    when: "{{ hostvars[groups.apa[0].record_count.stdout }} != {{ hostvars[groups.apa[1].record_count.stdout }}"

But since our inventory is quite dynamic, we can't seem to make use of the host group. I've tried as well saving the inventory hostname on a variable, but as I know, it saves on the managed host and not on the localhost where i will do the comparison, and i can't make the hostvars work

  - name: get current record count in from Latest ldapexport file
    shell: << count code here >>
    register: record_count

  - name: save inventory hostname to variable 1
    set_fact:
        server1: "{{ inventory_hostname }}"
    when: server1 is not defined
    run_once: true

  - debug:
      msg: value of Server 1 is {{ server1 }}

  - name: save inventory hostname to variable 2
    set_fact:
        server2: "{{ inventory_hostname }}"
    when: server1 is defined and server2 is not defined

  - debug:
      msg: value of Server 2 is {{ server2 }}

  - name: compare
    debug:
      msg: they are equal
    when: "{{ hostvars[vars[server1]].record_count.stdout }} == {{ hostvars[vars[server2]].record_count.stdout }}"
    delegate_to: localhost
    run_once: true

any ideas will be very much be appreciated. thanks!


Solution

  • Q: "... it saves on the managed host and not on the localhost ..."

    A: Run the 2nd play with the same hosts and run_once: true delegate_to: localhost the tasks. For example, the inventory and the playbook below

    shell> cat hosts
    [my_group1]
    test_01
    test_02
    
    [my_group2]
    test_03
    
    shell> cat playbook.yml
    - hosts: my_group1, my_group2
      tasks:
        - shell: cat /etc/passwd| wc -l
          register: record_count
        - debug:
            var: record_count.stdout
    
    - hosts: my_group1, my_group2
      vars:
        apa:
          - my_group1
          - my_group2
      tasks:
        - debug:
            msg: "{{ hostvars[item].record_count.stdout|trim }}"
          loop: "{{ groups[apa[0]] }}"
          run_once: true
          delegate_to: localhost
        - debug:
            msg: "{{ hostvars[item].record_count.stdout|trim }}"
          loop: "{{ groups[apa[1]] }}"
          run_once: true
          delegate_to: localhost
    

    give (abridged)

    shell> ansible-playbook -i hosts playbook.yml 
    
    PLAY [my_group1, my_group2] ***************************
    
    ok: [test_01] => 
      record_count.stdout: '      37'
    ok: [test_02] => 
      record_count.stdout: '      31'
    ok: [test_03] => 
      record_count.stdout: '      29'
    
    PLAY [my_group1, my_group2] ***************************
    
    ok: [test_01 -> localhost] => (item=test_01) => 
      msg: '37'
    ok: [test_01 -> localhost] => (item=test_02) => 
      msg: '31'
    
    ok: [test_01 -> localhost] => (item=test_03) => 
      msg: '29'
    

    Notes:

    • The expression hostvars[groups.apa[0]].record_count.stdout is wrong. hostvars[groups.apa[0]] is the list of the hosts in the group apa[0]. The items of the list have got attributes record_count not the list.

    • Use default filter if a (quite dynamic) host might disappear on the fly. For example

    "{{ hostvars[item].record_count.stdout|default(-1)|trim }}"
    
    • Decide how to select the pairs of the hosts if you want to compare their variables.