1
votes

How to get the sum of two hosts with Jinja2 filtering ansible host1 and host 2

---
- name: Count Check
  hosts: MYGROUP
  gather_facts: true
  user: sv_admin
  tasks:
    - name: count check
      shell: cat /etc/hosts | wc -l
      register: command_result
    - debug:
        var: command_result.stdout
    - set_fact:
        total_result: "{{ command_result.stdout | map('int') | sum(start=0) }}"
    - debug:
        msg: "Total count: {{ total_result }}" 

Playbook Output

TASK [debug] *****************************************************************
ok: [Host-01] => {
  "msg": "Total count:      134"
}
ok: [Host-02] => {
  "msg": "Total count:      133"
}
2

2 Answers

2
votes

Use extract and sum. For example, the playbook below

shell> cat playbook.yml
- hosts: test_01:test_03
  gather_facts: false
  tasks:
    - shell: cat /etc/hosts | wc -l
      register: command_result
    - debug:
        var: command_result.stdout
    - set_fact:
        total_result: "{{ ansible_play_hosts_all|
                          map('extract', hostvars, ['command_result', 'stdout'])|
                          map('int')|
                          sum }}"
      run_once: true
    - debug:
        var: total_result

gives (abridged)

shell> ansible-playbook playbook.yml 

PLAY [test_01:test_03] ****

TASK [shell] ****
changed: [test_01]
changed: [test_03]

TASK [debug] ****
ok: [test_01] => {
    "command_result.stdout": "      62"
}
ok: [test_03] => {
    "command_result.stdout": "      31"
}

TASK [set_fact] ****
ok: [test_01]

TASK [debug] ****
ok: [test_03] => {
    "total_result": "93"
}
ok: [test_01] => {
    "total_result": "93"
}

1
votes

You can use custom stats to do that: https://docs.ansible.com/ansible/latest/modules/set_stats_module.html

So for your case it would look like

---
- name: Count Check
  hosts: MYGROUP
  gather_facts: true
  user: sv_admin
  tasks:
    - name: count check
      shell: cat /etc/hosts | wc -l
      register: command_result
    - debug:
        var: command_result.stdout
    - set_fact:
        host_result: "{{ command_result.stdout }}"
    - debug:
        msg: "Count for this host: {{ host_result }}"
    - set_stats:
        data: "{{ { 'total_count': host_result | int } }}"

Then if you run it with ANSIBLE_SHOW_CUSTOM_STATS=yes it will show you the result at the end:

$ ANSIBLE_SHOW_CUSTOM_STATS=yes ansible-playbook -i inventory pb.yml
... (usual output)

CUSTOM STATS: *************************************************************

    RUN: { "total_count": 267}

The set_stats task adds results together from all the hosts by default, which is what you are looking for. You need to make sure the values are integers though, because if they are strings it will just concatenate them and you will end up with something like RUN: { "total_count": "134133"}. That's why I have put the data: bit the way I have - if you try to create the dictionary in regular yaml, like

  data:
    total_count: "{{ host_result | int }}"

you will see that the value is still a string (due to the way yaml/jinja works) and it won't work properly.