Search code examples
loopsvariablesansiblehostvars

How can I check how many Play Hosts have variable value X in Ansible?


I have the following Ansible problem.

Each host a variable, let's call it is_master, which can either be "0" or "1".

I now want to check if the number of hosts having is_master == "1" is grather than 1.

So I want to do something like

- set_fact: master_counter = "0"
- set_fact: {{ master_counter + 1 }}
  when: {{ hostvars['{{ item }}']['is_master'] }} == "1"
  loop: "{{ ansible_play_hosts_all }}"
  delegate_to: localhost
  run_once: true
- debug: msg="There is more than one master!"
  when: master_counter > 1

Solution

  • For example, given the inventory for testing

    test:
      hosts:
        host_A:
          is_master: '1'
        host_B:
          is_master: '1'
        host_C:
          is_master: '0'
    

    count the masters

      master_counter: "{{ ansible_play_hosts_all|
                          map('extract', hostvars, 'is_master')|
                          select('eq', '1')|length }}"
    

    and display the result

        - debug:
            msg: "master_counter={{ master_counter }}. There is more than one master!"
          when: master_counter|int > 1
          run_once: true
    

    gives

      msg: master_counter=2. There is more than one master!
    

    • Example of a complete playbook for testing
    - hosts: all
    
      vars:
    
        master_counter: "{{ ansible_play_hosts_all|
                            map('extract', hostvars, 'is_master')|
                            select('eq', '1')|length }}"
    
      tasks:
    
        - debug:
            var: is_master
    
        - debug:
            msg: "master_counter={{ master_counter }}. There is more than one master!"
          when: master_counter|int > 1
          run_once: true
    

    • It's more practical to use boolean instead of stings
    test:
      hosts:
        host_A:
          is_master: true
        host_B:
          is_master: true
        host_C:
          is_master: false
    

    The counting is a bit simpler

      master_counter: "{{ ansible_play_hosts_all|
                          map('extract', hostvars, 'is_master')|
                          select()|length }}"
    

    • The above options count hosts limited by the play ansible_play_hosts_all. You can count all hosts in the inventory if you want to
      master_counter: "{{ hostvars|
                          json_query('*.is_master')|
                          select()|length }}"