how to generate html report for multiple hosts using ansible and jinja2

6k Views Asked by At

my playbook

    - name: create HTML report
      template:
        src: report.j2
        dest: /cktreport.html
      delegate_to: localhost
      run_once: true

report.j2

<!DOCTYPE html>
<html>
<body>
<table>
    <thead>
        <tr>
            <th>HOSTNAME</th>
            <th>PORT</th>
            <th>CKTID</th>
        </tr>
    </thead>
    <tbody>      
    {% for item in output.parsed %}
        <tr>
        {% if 'CID' in item.DESCRIP %}
            <td>{{inventory_hostname}}</td>
            <td>{{item.PORT}}</td>
            <td>{{item.DESCRIP}}</td>  
        {%elif 'ckid' in item.DESCRIP %}
            <td>{{inventory_hostname}}</td>
            <td>{{item.PORT}}</td>
            <td>{{item.DESCRIP}}</td>               
        {% endif %}    
     {% endfor %}   
        </tr>      
{% endfor %}
    </tbody>
</table>

</body>
</html>

'output.parsed' has below info

TASK [debug] *******************************************************************
ok: [host-1] => {
    "msg": [
        {
            "DESCRIP": "CID: xxxx",
            "PORT": "Gi0/0/0",
            "PROTOCOL": "up",
            "STATUS": "up"
        },
        {
            "DESCRIP": "",
            "PORT": "Gi0/0/1",
            "PROTOCOL": "up",
            "STATUS": "up"
        },
        {
            "DESCRIP": "",
            "PORT": "Gi0/0/2",
            "PROTOCOL": "down",
            "STATUS": "down"
        },
        {
            "DESCRIP": "ckid: XXXX",
            "PORT": "Gi0/0/3",
            "PROTOCOL": "up",
            "STATUS": "up"
        }
    ]
}
ok: [host-2] => {
    "msg": [
        {
            "DESCRIP": "CID: xxxx",
            "PORT": "Gi0/0/1",
            "PROTOCOL": "up",
            "STATUS": "up"
        },
        {
            "DESCRIP": "",
            "PORT": "Gi0/0/6",
            "PROTOCOL": "up",
            "STATUS": "up"
        },
        {
            "DESCRIP": "",
            "PORT": "Gi0/0/7",
            "PROTOCOL": "down",
            "STATUS": "down"
        },
        {
            "DESCRIP": "ckid: XXXX",
            "PORT": "Gi0/0/8",
            "PROTOCOL": "up",
            "STATUS": "up"
        }
    ]
}

issue i have is - when i run playbook , cktreport.html is generated for just host-1, i have multiple hosts, how to generate single/one cktreport.html such a way that it has all hosts info in it.

i know i need to modify jinja2 template but not sure what logic to use.

1

There are 1 best solutions below

0
On BEST ANSWER

I'll take for granted your playbook targets the magic group all. Just replace in the template below with the correct group if this is not the case.

If you are doing something more complex (targeting several groups, using an advance host pattern, using limits on the command line...) have a look at special variables like ansible_play_hosts which will be more adapted.

It is in most cases a bad practice to loop directly on host lists outside of the natural play host loop... except when there is a good reason and this one. In your template, you need to go over all hosts to include in the report then loop on the parsed info you previously gathered. I believe the following template should meet your requirements (untested).

Notes:

  • since h actually contains the inventory_hostname, I used it directly for conciseness. But you can replace with hostvars[h].inventory_hostname if you prefer. The result will be absolutely identical.
  • your example template was not valid (closing endfor hanging arround with no opennig for). I fixed that below.
  • I left your if stanza as they were but you have several options to DRY here and check both conditions at once (with the match test or other regexp solutions...) to output the same piece of html afterwards. I'll let you explore that on your own if you wish.
<!DOCTYPE html>
<html>
<body>
<table>
    <thead>
        <tr>
            <th>HOSTNAME</th>
            <th>PORT</th>
            <th>CKTID</th>
        </tr>
    </thead>
    <tbody>
    {% for h in groups['all'] %}     
    {% for item in hostvars[h].output.parsed %}
        <tr>
        {% if 'CID' in item.DESCRIP %}
            <td>{{ h }}</td>
            <td>{{ item.PORT }}</td>
            <td>{{ item.DESCRIP }}</td>  
        {%elif 'ckid' in item.DESCRIP %}
            <td>{{ h }}</td>
            <td>{{ item.PORT }}</td>
            <td>{{ item.DESCRIP }}</td>               
        {% endif %}      
        </tr>      
    {% endfor %}
    {% endfor %}
    </tbody>
</table>

</body>
</html>