1

I am a novice to Ansible. I am trying to print all the inventory hosts with serial number (sl.no) using a Jinja template which would be transformed to a .csv file. I have this playbook to ping all the hosts and get the status.

- hosts: '{{ host }}'
  gather_facts: true
  become: true      

  tasks:
    - name: Pinging Host {{ host }}
      action: ping
      register: var_ping

I want to print all hostnames and its ping status with serial order number.

How to achieve this?

Expected output: enter image description here

U880D
  • 8,601
  • 6
  • 24
  • 40

1 Answers1

1

Use Special Variables ansible_play_hosts and ansible_play_hosts_all. Quoting:

ansible_play_hosts: List of hosts in the current play run, not limited by the serial. Failed/Unreachable hosts are excluded from this list.

ansible_play_hosts_all: List of all the hosts that were targeted by the play

  1. Create the serial numbers

For example, given the inventory

shell> cat hosts
test_11
test_12
test_13
test_14

and the abridged result of the ping module. The hosts test_12 and test_14 failed.

TASK [ping] ****************************************************************
fatal: [test_12]: FAILED! => changed=false 
ok: [test_11]
ok: [test_13]
fatal: [test_14]: UNREACHABLE! => changed=false

gives

ansible_play_hosts_all: ['test_11', 'test_12', 'test_13', 'test_14']
ansible_play_hosts: ['test_11', 'test_13']

Declare the variables

failed_hosts: "{{ ansible_play_hosts_all|difference(ansible_play_hosts) }}"
failed_hosts_dict: "{{ dict(failed_hosts|product(['fail'])) }}"
passed_hosts_dict: "{{ dict(ansible_play_hosts|product(['success'])) }}"
hosts_dict: "{{ passed_hosts_dict|combine(failed_hosts_dict) }}"

gives

failed_hosts: ['test_12', 'test_14']
failed_hosts_dict: {'test_12': 'fail', 'test_14': 'fail'}
passed_hosts_dict: {'test_11': 'success', 'test_13': 'success'}
hosts_dict: {'test_11': 'success', 'test_13': 'success', 'test_12': 'fail', 'test_14': 'fail'}

Create and test a template. Fit the sorting to you needs

    - debug:
        msg: |
          Serial Number, Hostname, Ping Status
          {% for k,v in hosts_dict.items()|sort() %}
          {{ loop.index }},{{ k }},{{ v }}
          {% endfor %}

gives

  msg: |-
    Serial Number, Hostname, Ping Status
    1,test_11,success
    2,test_12,fail
    3,test_13,success
    4,test_14,fail

If this is what you want write the file

    - copy:
        dest: /tmp/status.csv
        content: |
          Serial Number, Hostname, Ping Status
          {% for k,v in hosts_dict.items()|sort() %}
          {{ loop.index }},{{ k }},{{ v }}
          {% endfor %}
      delegate_to: localhost

gives

shell> cat /tmp/status.csv 
Serial Number, Hostname, Ping Status
1,test_11,success
2,test_12,fail
3,test_13,success
4,test_14,fail

Example of a complete playbook for testing

- hosts: all
  gather_facts: false

  vars:

    failed_hosts: "{{ ansible_play_hosts_all|difference(ansible_play_hosts) }}"
    failed_hosts_dict: "{{ dict(failed_hosts|product(['fail'])) }}"
    passed_hosts_dict: "{{ dict(ansible_play_hosts|product(['success'])) }}"
    hosts_dict: "{{ passed_hosts_dict|combine(failed_hosts_dict) }}"

  tasks:

    - ping:

    - debug:
        msg: |
          ansible_play_hosts_all: {{ ansible_play_hosts_all }}
          ansible_play_hosts: {{ ansible_play_hosts }}
          failed_hosts: {{ failed_hosts }}
          failed_hosts_dict: {{ failed_hosts_dict }}
          passed_hosts_dict: {{ passed_hosts_dict }}
          hosts_dict: {{ hosts_dict }}
      run_once: true

    - debug:
        msg: |
          Serial Number, Hostname, Ping Status
          {% for k,v in hosts_dict.items()|sort() %}
          {{ loop.index }},{{ k }},{{ v }}
          {% endfor %}
      run_once: true

    - copy:
        dest: /tmp/status.csv
        content: |
          Serial Number, Hostname, Ping Status
          {% for k,v in hosts_dict.items()|sort() %}
          {{ loop.index }},{{ k }},{{ v }}
          {% endfor %}
      delegate_to: localhost
      run_once: true

  1. Serial numbers are assigned in the inventory

For example, given the inventory

shell> cat hosts
test_11 sn=1
test_12 sn=2
test_13 sn=3
test_14 sn=4

Declare the variables

failed_hosts: "{{ ansible_play_hosts_all|difference(ansible_play_hosts) }}"
failed_hosts_dict: |
  {% for host in failed_hosts %}
  {{ host }}:
    status: fail
    sn: {{ hostvars[host]['sn'] }}
  {% endfor %}
passed_hosts_dict: |
  {% for host in ansible_play_hosts %}
  {{ host }}:
    status: success
    sn: {{ hostvars[host]['sn'] }}
  {% endfor %}
hosts_list: "{{ passed_hosts_dict|from_yaml|
                combine(failed_hosts_dict|from_yaml)|
                dict2items|
                sort(attribute='value.sn')}}"

gives

hosts_list:
  - key: test_11
    value:
      sn: 1
      status: success
  - key: test_12
    value:
      sn: 2
      status: fail
  - key: test_13
    value:
      sn: 3
      status: success
  - key: test_14
    value:
      sn: 4
      status: fail

Write the file

    - copy:
        dest: /tmp/status.csv
        content: |
          Serial Number, Hostname, Ping Status
          {% for i in hosts_list %}
          {{ i.value.sn }},{{ i.key }},{{ i.value.status }}
          {% endfor %}
      delegate_to: localhost
      run_once: true

gives the same result

shell> cat /tmp/status.csv 
Serial Number, Hostname, Ping Status
1,test_11,success
2,test_12,fail
3,test_13,success
4,test_14,fail

Example of a complete playbook for testing

- hosts: all
  gather_facts: false

  vars:

    failed_hosts: "{{ ansible_play_hosts_all|difference(ansible_play_hosts) }}"
    failed_hosts_dict: |
      {% for host in failed_hosts %}
      {{ host }}:
        status: fail
        sn: {{ hostvars[host]['sn'] }}
      {% endfor %}
    passed_hosts_dict: |
      {% for host in ansible_play_hosts %}
      {{ host }}:
        status: success
        sn: {{ hostvars[host]['sn'] }}
      {% endfor %}
    hosts_list: "{{ passed_hosts_dict|from_yaml|
                    combine(failed_hosts_dict|from_yaml)|
                    dict2items|
                    sort(attribute='value.sn')}}"

  tasks:

    - ping:

    - debug:
        var: hosts_list
      run_once: true

    - debug:
        msg: |
          ansible_play_hosts_all: {{ ansible_play_hosts_all }}
          ansible_play_hosts: {{ ansible_play_hosts }}
          failed_hosts: {{ failed_hosts }}
          failed_hosts_dict: {{ failed_hosts_dict|from_yaml }}
          passed_hosts_dict: {{ passed_hosts_dict|from_yaml }}
          hosts_list: {{ hosts_list }}
      run_once: true

    - debug:
        msg: |
          Serial Number, Hostname, Ping Status
          {% for i in hosts_list %}
          {{ i.value.sn }},{{ i.key }},{{ i.value.status }}
          {% endfor %}
      run_once: true

    - copy:
        dest: /tmp/status.csv
        content: |
          Serial Number, Hostname, Ping Status
          {% for i in hosts_list %}
          {{ i.value.sn }},{{ i.key }},{{ i.value.status }}
          {% endfor %}
      delegate_to: localhost
      run_once: true
Vladimir Botka
  • 58,131
  • 4
  • 32
  • 63