Hello Guys,
I am recently working for a client in which he has a ask that can i export the report what he can see in the AAP/AWX dashboard in html or PDF format for compliance so i started researching a bit on it and shared so report which are available on internet bit he did not like it.
He wanted a tailer made report showing job name start and finish time and how much time it took and final status also if i can show the logs of that execution that will be great.
So i use the API which are available with AAP or AWX to fetch the report of last 30 days with these field
below is the job template report.yml
--- - name: Generate Last 1 Month Job Report hosts: aux_server
##can be replace with any server name you want localhost will not work as it will destroy the report once the job is finish execution become: true gather_facts: true vars: controller_url: "https://<FQDN_AAP or AWX server>" tower_username: "admin" tower_password: "primod123" # Calculate date 30 days ago in ISO format (YYYY-MM-DD) last_month: "{{ lookup('pipe', 'date -d \"30 days ago\" +%Y-%m-%d') }}" page_size: 200 is_pdf: false ##Remove the word controller from api call if you are using awx tasks: - name: Fetch first page of jobs ansible.builtin.uri: url: "{{ controller_url }}/api/controller/v2/jobs/?finished__gte={{ last_month }}&order_by=-finished&page_size={{ page_size }}" method: GET user: "{{ tower_username }}" password: "{{ tower_password }}" force_basic_auth: yes validate_certs: false register: first_page - name: Calculate total pages ansible.builtin.set_fact: total_pages: "{{ (first_page.json.count / page_size) | round(0, 'ceil') | int }}" - name: Fetch remaining pages ansible.builtin.uri: url: "{{ controller_url }}/api/controller/v2/jobs/?finished__gte={{ last_month }}&order_by=-finished&page_size={{ page_size }}&page={{ item }}" method: GET user: "{{ tower_username }}" password: "{{ tower_password }}" force_basic_auth: yes validate_certs: false # Loop from page 2 to the end loop: "{{ range(2, total_pages | int + 1) | list }}" register: remaining_pages when: total_pages | int > 1 - name: Consolidate all results ansible.builtin.set_fact: all_jobs: >- {{ first_page.json.results + (remaining_pages.results | default([]) | map(attribute='json.results') | flatten) }} - name: Generate HTML Report ansible.builtin.template: src: report_template.j2 dest: "/usr/share/nginx/html/job_report_{{ ansible_date_time.date }}.html" vars: jobs: "{{ all_jobs }}" report_title: "Monthly Automation Summary" report_range: "Last 30 Days (Since {{ last_month }})"
and jinja template : report_template.j2<!DOCTYPE html> <html> <head> <style> body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 40px; color: #333; } .header { border-bottom: 2px solid #005596; padding-bottom: 10px; margin-bottom: 20px; } .logo {height: 40px; /* Fixed height for a cleaner look */ width: auto; /* Maintains aspect ratio */ margin-right: 20px; } table { width: 100%; border-collapse: collapse; margin-top: 20px; } th, td { padding: 12px; border: 1px solid #ddd; text-align: left; } th { background-color: #f8f9fa; font-weight: bold; } .status-successful { color: #28a745; font-weight: bold; } .status-failed { color: #dc3545; font-weight: bold; } .status-canceled { color: #f5f503fc; font-weight: bold; } .summary-box { background: #e9ecef; padding: 15px; border-radius: 5px; margin-bottom: 30px; } </style> </head> <body> <div class="header"> <h1>{{ report_title }}</h1> <img src="https://raw.githubusercontent.com/benc-uk/icon-collection/refs/heads/master/logos/ansible.svg" alt="Ansible" class="logo"> <p><strong>Report Genrated on and using ansible automation platform 2.6</strong></p> <p><strong>Period:</strong> {{ report_range }}</p> <p><strong>Generated On:</strong> {{ ansible_date_time.date }}</p> </div> <div class="summary-box"> <strong>Total Jobs Executed:</strong> {{ jobs | length }} </div> <table> <thead> <tr> <th>Job ID</th> <th>Template Name</th> <th>Status</th> <th>Started At</th> <th>Finished At</th> <th>Duration</th> </tr> </thead> <tbody> {% for job in jobs %} <tr> <td>{{ job.id }}</td> <td>{{ job.name }}</td> <td class="status-{{ job.status }}">{{ job.status | capitalize }}</td> <td>{{ job.started | default(job.created) }}</td> <td>{{ job.finished }}</td> <td>{{'%M:%S' |ansible.builtin.strftime(job.elapsed)}}</td> </tr>{% endfor %} </tbody> </table> </body> </html>
sample outputLet me know you feedback in comments

No comments:
Post a Comment