Merge branch 'main' into cloud

This commit is contained in:
willtome
2022-06-10 10:26:26 -04:00
committed by GitHub
40 changed files with 1027 additions and 28 deletions

View File

@@ -22,7 +22,7 @@
- name: AWS| CREATE VM | save ami
set_fact:
aws_instance_ami: >
{{ amis.images | selectattr('name', 'defined') | sort(attribute='creation_date') | last }}
{{ (amis.images | selectattr('name', 'defined') | sort(attribute='creation_date'))[-2] }}
- name: AWS| CREATE VM | create instance
amazon.aws.ec2_instance:

View File

@@ -0,0 +1,14 @@
---
win_update_categories:
- Application
- Connectors
- CriticalUpdates
- DefinitionUpdates
- DeveloperKits
- FeaturePacks Guidance
- SecurityUpdates
- ServicePacks
- Tools
- UpdateRollups
- Updates
allow_reboot: true

View File

@@ -0,0 +1,15 @@
---
- name: Scan packages
demo.patching.win_scan_packages:
check_mode: no
- name: Scan Services
demo.patching.win_scan_services:
check_mode: no
- name: Install Windows Updates
ansible.windows.win_updates:
category_names: "{{ win_update_categories | default(omit) }}"
reboot: "{{ allow_reboot }}"
state: installed
register: patchingresult

View File

@@ -24,4 +24,4 @@
- name: display link to inventory report
ansible.builtin.debug:
msg: "Please go to http://{{ ansible_host }}/reports/linux.html"
msg: "Please go to http://{{ hostvars[report_server]['ansible_host'] }}/reports/linux.html"

View File

@@ -20,7 +20,8 @@
- name: Display link to Linux patch report
ansible.builtin.debug:
msg: "Please go to http://{{ ansible_host }}/reports/linuxpatch.html"
msg: "Please go to http://{{ hostvars[report_server]['ansible_host'] }}/reports/linuxpatch.html"
#- name: Send Report via E-mail
# community.general.mail:

View File

@@ -0,0 +1,20 @@
---
- yum:
name: httpd
state: latest
check_mode: no
- file:
path: /var/www/html/reports/
state: directory
check_mode: no
- copy:
dest: /var/www/html/reports/.htaccess
content: Options +Indexes
check_mode: no
- service:
name: httpd
state: started
check_mode: no

View File

@@ -0,0 +1,23 @@
---
- name: Install IIS
ansible.windows.win_feature:
name: Web-Server
state: present
check_mode: no
- name: Start IIS service
ansible.windows.win_service:
name: W3Svc
state: started
check_mode: no
- name: Create Directory
ansible.windows.win_file:
path: C:\Inetpub\wwwroot\reports
state: directory
check_mode: no
- name: Enable Directory Browsing
ansible.windows.win_powershell:
script: |
"Set-WebConfigurationProperty -filter /system.webServer/directoryBrowse -name enabled -value true -PSPath 'IIS:\Sites\Default Web Site\reports'"

View File

@@ -0,0 +1,36 @@
build_report_windows
========
Installs Apache and creates a report based on facts from Windows services and packages modules
Requirements
------------
Must run on Apache server
Role Variables / Configuration
--------------
N/A
Dependencies
------------
N/A
Example Playbook
----------------
The role can be used to create an html report on any number of Linux hosts using any number of Windows servers about their services and packages installed
```
---
- hosts: all
tasks:
- name: Run Windows Report
import_role:
name: shadowman.reports.build_report_windows
```

View File

@@ -0,0 +1,2 @@
---
detailedreport: True

View File

@@ -0,0 +1,202 @@
p.hostname {
color: #000000;
font-weight: bolder;
font-size: large;
margin: auto;
width: 50%;
}
#subtable {
background: #ebebeb;
margin: 0px;
width: 100%;
}
#subtable tbody tr td {
padding: 5px 5px 5px 5px;
}
#subtable thead th {
padding: 5px;
}
* {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
font-family: "Open Sans", "Helvetica";
}
a {
color: #ffffff;
}
p {
color: #ffffff;
}
h1 {
text-align: center;
color: #ffffff;
}
body {
background:#353a40;
padding: 0px;
margin: 0px;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
table {
border-collapse: separate;
background:#fff;
@include border-radius(5px);
@include box-shadow(0px 0px 5px rgba(0,0,0,0.3));
}
.main_net_table {
margin:50px auto;
}
thead {
@include border-radius(5px);
}
thead th {
font-size:16px;
font-weight:400;
color:#fff;
@include text-shadow(1px 1px 0px rgba(0,0,0,0.5));
text-align:left;
padding:20px;
border-top:1px solid #858d99;
background: #353a40;
&:first-child {
@include border-top-left-radius(5px);
}
&:last-child {
@include border-top-right-radius(5px);
}
}
tbody tr td {
font-weight:400;
color:#5f6062;
font-size:13px;
padding:20px 20px 20px 20px;
border-bottom:1px solid #e0e0e0;
}
tbody tr:nth-child(2n) {
background:#f0f3f5;
}
tbody tr:last-child td {
border-bottom:none;
&:first-child {
@include border-bottom-left-radius(5px);
}
&:last-child {
@include border-bottom-right-radius(5px);
}
}
td {
vertical-align: top;
}
span.highlight {
background-color: yellow;
}
.expandclass {
color: #5f6062;
}
.content{
display:none;
margin: 10px;
}
header {
width: 100%;
position: initial;
float: initial;
padding: 0;
margin: 0;
border-radius: 0;
height: 88px;
background-color: #171717;
}
.header-container {
margin: 0 auto;
width: 100%;
height: 100%;
max-width: 1170px;
padding: 0;
float: initial;
display: flex;
align-items: center;
}
.header-logo {
width: 137px;
border: 0;
margin: 0;
margin-left: 15px;
}
.header-link {
margin-left: 40px;
text-decoration: none;
cursor: pointer;
text-transform: uppercase;
font-size: 15px;
font-family: 'Red Hat Text';
font-weight: 500;
}
.header-link:hover {
text-shadow: 0 0 0.02px white;
text-decoration: none;
}
table.net_info td {
padding: 5px;
}
p.expandclass:hover {
text-decoration: underline;
color: #EE0000;
cursor: pointer;
}
.summary_info {
}
.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active, a.ui-button:active, .ui-button:active, .ui-button.ui-state-active:hover {
border: 1px solid #5F0000;
background: #EE0000;
}
div#net_content {
padding: 0px;
height: auto !important;
}
img.router_image {
vertical-align: middle;
padding: 0px 10px 10px 10px;
width: 50px;
}
table.net_info {
width: 100%;
}
p.internal_label {
color: #000000;
}

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Logos" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="930.2px" height="350px" viewBox="0 0 930.2 350" style="enable-background:new 0 0 930.2 350;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
.st1{fill:#EE0000;}
</style>
<title>Logo-Red_Hat-Ansible_Automation_Platform-A-Reverse-RGB</title>
<path class="st0" d="M383.3,228.5h18.8L446,335.7h-17.5l-12.4-31.4h-48l-12.6,31.4h-16.7L383.3,228.5z M410.9,291l-18.7-47l-18.7,47
H410.9z"/>
<path class="st0" d="M455.2,257.7h15.3v7.8c6.2-6.2,14.7-9.6,23.5-9.3c17.9,0,30.5,12.4,30.5,30.5v49h-15.3v-46.5
c0-12.3-7.5-19.8-19.3-19.8c-7.8-0.3-15.1,3.6-19.3,10.1v56.1h-15.3V257.7z"/>
<path class="st0" d="M543,315.5c8.1,6.4,16.7,9.8,25.4,9.8c11,0,18.7-4.8,18.7-11.7c0-5.5-4-8.7-12.6-10l-14.1-2
c-15.5-2.3-23.3-9.5-23.3-21.6c0-14.1,12.3-23.6,30.5-23.6c11.3-0.1,22.3,3.4,31.5,9.9l-7.8,10.1c-8.6-5.7-16.4-8.1-24.7-8.1
c-9.3,0-15.6,4.3-15.6,10.6c0,5.7,3.7,8.4,12.9,9.8l14.1,2c15.5,2.3,23.6,9.7,23.6,21.7c0,14-14.1,24.5-32.6,24.5
c-13.5,0-25.6-4-34.2-11.5L543,315.5z"/>
<path class="st0" d="M611.6,235.6c0-5.2,4.1-9.4,9.3-9.5c0,0,0,0,0,0c5.2-0.2,9.7,3.9,9.9,9.1c0.2,5.2-3.9,9.7-9.1,9.9
c-0.2,0-0.5,0-0.7,0C615.8,245.1,611.6,240.9,611.6,235.6C611.6,235.7,611.6,235.7,611.6,235.6z M628.6,335.7h-15.3v-78h15.3V335.7z
"/>
<path class="st0" d="M685.5,336.9c-8.5,0-16.8-2.7-23.6-7.8v6.6h-15.2V228.5l15.3-3.4v40c6.6-5.6,15.1-8.7,23.7-8.6
c22.1,0,39.4,17.7,39.4,40.1C725.2,319.1,707.9,336.9,685.5,336.9z M662,279.2v35.2c4.9,5.7,13,9.2,21.8,9.2
c15,0,26.4-11.5,26.4-26.8c0-15.3-11.5-27-26.4-27C674.9,269.8,667.1,273.2,662,279.2z"/>
<path class="st0" d="M755,335.7h-15.3V228.5l15.3-3.4V335.7z"/>
<path class="st0" d="M810.5,337.1c-23,0-40.9-17.7-40.9-40.4c0-22.5,17.2-40.1,39.1-40.1c21.5,0,37.7,17.8,37.7,40.8v4.4h-61.6
c2,13,13.2,22.5,26.4,22.4c7.2,0.2,14.2-2.3,19.8-6.8l9.8,9.7C832.1,333.7,821.5,337.4,810.5,337.1z M784.9,290.2h46.3
c-2.3-11.9-11.5-20.8-22.8-20.8C796.5,269.4,787.2,277.8,784.9,290.2z"/>
<path class="st1" d="M202.8,137.5c18.4,0,45.1-3.8,45.1-25.7c0.1-1.7-0.1-3.4-0.5-5l-11-47.7c-2.5-10.5-4.8-15.2-23.2-24.5
c-14.3-7.3-45.5-19.4-54.7-19.4c-8.6,0-11.1,11.1-21.3,11.1c-9.8,0-17.1-8.3-26.4-8.3c-8.8,0-14.6,6-19,18.4c0,0-12.4,34.9-14,40
c-0.3,0.9-0.4,1.9-0.4,2.9C77.6,92.9,131.1,137.5,202.8,137.5 M250.8,120.7c2.5,12.1,2.5,13.3,2.5,14.9c0,20.6-23.2,32.1-53.7,32.1
c-69,0-129.3-40.3-129.3-67c0-3.7,0.8-7.4,2.2-10.8c-24.8,1.3-56.9,5.7-56.9,34c0,46.4,109.9,103.5,196.9,103.5
c66.7,0,83.5-30.2,83.5-54C296.1,154.6,279.9,133.4,250.8,120.7"/>
<path d="M250.7,120.7c2.5,12.1,2.5,13.3,2.5,14.9c0,20.6-23.2,32.1-53.7,32.1c-69,0-129.3-40.3-129.3-67c0-3.7,0.8-7.4,2.2-10.8
l5.4-13.3c-0.3,0.9-0.4,1.9-0.4,2.8c0,13.6,53.5,58.1,125.2,58.1c18.4,0,45.1-3.8,45.1-25.7c0.1-1.7-0.1-3.4-0.5-5L250.7,120.7z"/>
<path class="st0" d="M869.1,151.2c0,17.5,10.5,26,29.7,26c5.9-0.1,11.8-1,17.5-2.5v-20.3c-3.7,1.2-7.5,1.7-11.3,1.7
c-7.9,0-10.8-2.5-10.8-9.9v-31.1h22.9V94.2h-22.9V67.7l-25,5.4v21.1h-16.6v20.9h16.6L869.1,151.2z M791,151.7
c0-5.4,5.4-8.1,13.6-8.1c5,0,10,0.7,14.9,1.9V156c-4.8,2.6-10.2,3.9-15.6,3.9C795.9,159.9,791.1,156.8,791,151.7 M798.7,177.5
c8.8,0,16-1.9,22.6-6.3v5h24.8v-52.5c0-20-13.5-30.9-35.9-30.9c-12.6,0-25,2.9-38.3,9l9,18.4c9.6-4,17.7-6.5,24.8-6.5
c10.3,0,15.6,4,15.6,12.2v4c-6.1-1.6-12.3-2.4-18.6-2.3c-21.1,0-33.8,8.8-33.8,24.6C768.9,166.6,780.4,177.6,798.7,177.5
M662.5,176.2h26.7v-42.5h44.6v42.5h26.7V67.7h-26.6v41.7h-44.6V67.7h-26.7L662.5,176.2z M561,135.1c0-11.8,9.3-20.8,21.5-20.8
c6.4-0.1,12.6,2.1,17.4,6.4v28.6c-4.7,4.4-10.9,6.7-17.4,6.5C570.5,155.8,561,146.8,561,135.1 M600.2,176.1H625V62.3l-25,5.4v30.8
c-6.4-3.6-13.6-5.5-20.9-5.4c-23.9,0-42.6,18.4-42.6,42c-0.3,23,18.1,41.9,41.1,42.2c0.2,0,0.5,0,0.7,0c7.9,0,15.6-2.5,22-7.1V176.1
z M486.5,113.2c7.9,0,14.6,5.1,17.2,13h-34.2C471.9,118,478.2,113.2,486.5,113.2 M444.2,135.2c0,23.9,19.5,42.5,44.6,42.5
c13.8,0,23.9-3.7,34.3-12.4l-16.6-14.7c-3.9,4-9.6,6.2-16.4,6.2c-8.8,0.2-16.8-4.9-20.2-13h58.4v-6.2c0-26-17.5-44.8-41.4-44.8
c-23.2-0.4-42.4,18.2-42.7,41.5C444.2,134.6,444.2,134.9,444.2,135.2 M400.9,90.5c8.8,0,13.8,5.6,13.8,12.2s-5,12.2-13.8,12.2h-26.3
V90.5H400.9z M347.9,176.2h26.7v-39.5h20.3l20.5,39.5h29.7l-23.9-43.4c12.4-5,20.5-17.1,20.4-30.5c0-19.5-15.3-34.5-38.3-34.5H348
L347.9,176.2z"/>
</svg>

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View File

@@ -0,0 +1,28 @@
---
- name: create HTML report
ansible.windows.win_template:
src: report.j2
dest: "{{ file_path }}/windows.html"
check_mode: no
- name: copy CSS over
ansible.windows.win_copy:
src: "css"
dest: "{{ file_path }}"
directory_mode: true
check_mode: no
- name: copy logos over
ansible.windows.win_copy:
src: "{{ item }}"
dest: "{{ file_path }}"
directory_mode: true
loop:
- "webpage_logo.png"
- "redhat-ansible-logo.svg"
- "server.png"
check_mode: no
#- name: display link to inventory report
# ansible.builtin.debug:
# msg: "Please go to http://{{ host_vars[report_server]['ansible_host'] }}/reports/windows.html"

View File

@@ -0,0 +1,15 @@
<div class="wrapper">
<header>
<div class="header-container">
<a href="https://ansible.com">
<img
class="header-logo"
src="redhat-ansible-logo.svg"
title="Red Hat Ansible"
alt="Red Hat Ansible"
/>
</a>
</div>
</header>

View File

@@ -0,0 +1,29 @@
<! INTERNAL TABLE FOR PACKAGES --!>
<div id="accordion">
<div class="ui-accordion ui-widget ui-helper-reset" role="tablist">
<h3 class="ui-accordion-header ui-corner-top ui-state-default ui-accordion-icons ui-accordion-header-collapsed ui-corner-all" role="tab" id="ui-id-3" aria-controls="ui-id-4" aria-selected="false" aria-expanded="false" tabindex="0">Package Facts</h3>
<div class="net_content ui-accordion-content ui-corner-bottom ui-helper-reset ui-widget-content" id="ui-id-4" aria-labelledby="ui-id-3" role="tabpanel" aria-hidden="true" style="display: none; height: 194px;">
<table id="subtable" class="sortable">
<thead>
<tr>
<th>Package Name</th>
<th>Version</th>
<th>Publisher</th>
</tr>
</thead>
<tbody>
{% if hostvars[windows_host]['packages'] is defined %}
{% for package in hostvars[windows_host]['packages'] %}
<tr>
<td>{{package['name']}}</td>
<td>{{package['version']}}</td>
<td>{{package['publisher']}}</td>
</tr>
{% endfor %}
{% endif %}
</tbody>
</table>
</div>
</div>
</div>
<! END INTERNAL TABLE FOR PACKAGES --!>

View File

@@ -0,0 +1,101 @@
<!DOCTYPE html>
<html>
<head>
<title> Ansible Windows Automation Report </title>
<link rel="stylesheet" type="text/css" href="//fonts.googleapis.com/css?family=Open+Sans" />
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link rel="stylesheet" href="css/new.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script src="https://www.kryogenix.org/code/browser/sorttable/sorttable.js"></script>
<script>
$(function() {
$( "#accordion > div" ).accordion({
header: "h3",
active: false,
collapsible: true
});
});
</script>
<script>
(function(document) {
'use strict';
var TableFilter = (function(myArray) {
var search_input;
function _onInputSearch(e) {
search_input = e.target;
var tables = document.getElementsByClassName(search_input.getAttribute('data-table'));
myArray.forEach.call(tables, function(table) {
myArray.forEach.call(table.tBodies, function(tbody) {
myArray.forEach.call(tbody.rows, function(row) {
var text_content = row.textContent.toLowerCase();
var search_val = search_input.value.toLowerCase();
row.style.display = text_content.indexOf(search_val) > -1 ? '' : 'none';
});
});
});
}
return {
init: function() {
var inputs = document.getElementsByClassName('search-input');
myArray.forEach.call(inputs, function(input) {
input.oninput = _onInputSearch;
});
}
};
})(Array.prototype);
document.addEventListener('readystatechange', function() {
if (document.readyState === 'complete') {
TableFilter.init();
}
});
})(document);
</script>
</head>
<body>
<div class="wrapper">
{% include 'header.j2' %}
<section>
<center>
<h1>Ansible Windows Automation Report</h1>
<h3><input type="search" placeholder="Search..." class="form-control search-input" data-table="main_net_table"/>
</center>
<table class="table table-striped mt32 main_net_table">
<thead>
<tr>
<th>Windows Device</th>
<th>Operating System</th>
<th>Operating System Kernel Version</th>
</tr>
</thead>
<tbody>
{% for windows_host in ansible_play_hosts |sort %}
<tr>
<td class="summary_info">
<div id="hostname">
<p class="hostname">
<img class="router_image" src="server.png"> {{ hostvars[windows_host]['inventory_hostname'].split('.')[0] }}</p>
</div>
{% if detailedreport == 'True' %}
{% include 'packages.j2' %}
{% include 'services.j2' %}
{% endif %}
</td>
<td>{{hostvars[windows_host]['ansible_os_family']|default("none")}}</td>
<td>{{hostvars[windows_host]['ansible_distribution']|default("none")}}</td>
</tr>
{% endfor %}
</tbody>
</table>
<center><p>Created with</p><br><img src="webpage_logo.png" width="300">
</center>
</section>
</div>
</body>
</html>

View File

@@ -0,0 +1,29 @@
<! INTERNAL TABLE FOR SERVICES --!>
<div id="accordion">
<div class="ui-accordion ui-widget ui-helper-reset" role="tablist">
<h3 class="ui-accordion-header ui-corner-top ui-state-default ui-accordion-icons ui-accordion-header-collapsed ui-corner-all" role="tab" id="ui-id-3" aria-controls="ui-id-4" aria-selected="false" aria-expanded="false" tabindex="0">Services Facts</h3>
<div class="net_content ui-accordion-content ui-corner-bottom ui-helper-reset ui-widget-content" id="ui-id-4" aria-labelledby="ui-id-3" role="tabpanel" aria-hidden="true" style="display: none; height: 194px;">
<table id="subtable" class="sortable">
<thead>
<tr>
<th>Display Name</th>
<th>Windows Services Name</th>
<th>State</th>
</tr>
</thead>
<tbody>
{% if hostvars[windows_host]['services'] is defined %}
{% for service in hostvars[windows_host]['services'] %}
<tr>
<td>{{service['name']}}</td>
<td>{{service['win_svc_name']}}</td>
<td>{{service['state']}}</td>
</tr>
{% endfor %}
{% endif %}
</tbody>
</table>
</div>
</div>
</div>
<! END INTERNAL TABLE FOR SERVICES --!>

View File

@@ -0,0 +1 @@
file_path: C:\Inetpub\wwwroot\reports

View File

@@ -0,0 +1,36 @@
build_report_windows_patch
========
Installs Apache and creates a report based on facts from Windows update job
Requirements
------------
Must run on Apache server
Role Variables / Configuration
--------------
N/A
Dependencies
------------
N/A
Example Playbook
----------------
The role can be used to create an html patching report on any number of Linux hosts using any number of Windows servers
```
---
- hosts: all
tasks:
- name: Run Windows Patch Report
import_role:
name: shadowman.reports.build_report_windows_patch
```

View File

@@ -0,0 +1,3 @@
EMAIL_FROM: tower@shadowman.dev
to_emails: alex@shadowman.dev,tower@shadowman.dev
EMAIL_TO: "{{ to_emails.split(',') }}"

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

View File

@@ -0,0 +1,111 @@
p.hostname {
color: #000000;
font-weight: bolder;
font-size: large;
}
#subtable {
background: #ebebeb;
margin: 0px;
}
#subtable tbody tr td {
padding: 5px 5px 5px 5px;
}
#subtable thead th {
padding: 5px;
}
* {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
font-family: "Open Sans", "Helvetica";
}
a {
color: #ffffff;
}
p {
color: #ffffff;
}
h1 {
text-align: center;
color: #ffffff;
}
body {
background:#353a40;
}
table {
border-collapse: separate;
background:#fff;
@include border-radius(5px);
margin:50px auto;
@include box-shadow(0px 0px 5px rgba(0,0,0,0.3));
}
thead {
@include border-radius(5px);
}
thead th {
font-family: 'Patua One', monospace;
font-size:16px;
font-weight:400;
color:#fff;
@include text-shadow(1px 1px 0px rgba(0,0,0,0.5));
text-align:left;
padding:20px;
border-top:1px solid #858d99;
background: #353a40;
&:first-child {
@include border-top-left-radius(5px);
}
&:last-child {
@include border-top-right-radius(5px);
}
}
tbody tr td {
font-family: 'Open Sans', sans-serif;
font-weight:400;
color:#5f6062;
font-size:13px;
padding:20px 20px 20px 20px;
border-bottom:1px solid #e0e0e0;
}
tbody tr:nth-child(2n) {
background:#f0f3f5;
}
tbody tr:last-child td {
border-bottom:none;
&:first-child {
@include border-bottom-left-radius(5px);
}
&:last-child {
@include border-bottom-right-radius(5px);
}
}
span.highlight {
background-color: yellow;
}
.expandclass {
color: #5f6062;
}
.content{
display:none;
margin: 10px;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

View File

@@ -0,0 +1,23 @@
- name: Create HTML report
ansible.windows.win_template:
src: report.j2
dest: "{{ file_path }}/windowspatch.html"
check_mode: no
- name: Copy CSS over
ansible.windows.win_copy:
src: "css"
dest: "{{ file_path }}"
directory_mode: true
check_mode: no
- name: Copy logo over
ansible.windows.win_copy:
src: "webpage_logo.png"
dest: "{{ file_path }}"
directory_mode: true
check_mode: no
- name: Display link to Patch report
ansible.builtin.debug:
msg: "Please go to http://{{ hostvars[report_server]['ansible_host'] }}/reports/windowspatch.html"

View File

@@ -0,0 +1,113 @@
<!DOCTYPE html>
<html>
<head>
<title> Windows Patch Report </title>
</head>
<body>
<center>
<h1>Ansible Windows Patching Report</h1>
<style>
@media print {
.noprint {
display: none !important;
}
}
</style>
<div class="noprint">
<button type="button" onclick="tableToCSV()">Download CSV</button>
<input type="button" value="Print" onClick="window.print()">
</div>
</center>
<table border = "1" cellpadding = "5" cellspacing = "5">
<thead>
<tr>
<th>Hostname</th>
<th>Operating System</th>
<th>Required Updates</th>
</tr>
</thead>
<tbody>
{% for windows_host in ansible_play_hosts |sort %}
<tr>
<td>{{hostvars[windows_host]['inventory_hostname']}}</td>
<td>{{hostvars[windows_host]['ansible_distribution']|default("none")}}</td>
<td>
<ul>
{% if hostvars[windows_host].patchingresult.updates is defined and hostvars[windows_host].patchingresult.found_update_count|int > 0 %}
{% for update in hostvars[windows_host].patchingresult.updates %}
{% set updatenum = hostvars[windows_host].patchingresult.updates[update] %}
<li>{{updatenum.title}}</li>
{% endfor %}
{% else %}
<li>Compliant</li>
{% endif %}
</ul>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<center><p>Created with Ansible on {{hostvars[inventory_hostname].ansible_date_time.iso8601}}</p></center>
<script type="text/javascript">
function tableToCSV() {
// Variable to store the final csv data
var csv_data = [];
// Get each row data
var rows = document.getElementsByTagName('tr');
for (var i = 0; i < rows.length; i++) {
// Get each column data
var cols = rows[i].querySelectorAll('td,th');
// Stores each csv row data
var csvrow = [];
for (var j = 0; j < (cols.length); j++) {
// Get the text data of each cell of
// a row and push it to csvrow
if ( j == cols.length-1 && i==0){}
else{
csvrow.push(cols[j].textContent.replace(/,/g, " "));
}
}
csv_data.push(csvrow.join(","));
}
// combine each row data with new line character
csv_data = csv_data.join('\n');
// Call this function to download csv file
downloadCSVFile(csv_data);
}
function downloadCSVFile(csv_data) {
// Create CSV file object and feed our
// csv_data into it
CSVFile = new Blob([csv_data], { type: "text/csv" });
// Create to temporary link to initiate
// download process
var temp_link = document.createElement('a');
var todayDate = new Date().toISOString().slice(0, 10);
// Download csv file
temp_link.download = "windowspatching-" + todayDate + ".csv";
var url = window.URL.createObjectURL(CSVFile);
temp_link.href = url;
// This link should not be displayed
temp_link.style.display = "none";
document.body.appendChild(temp_link);
// Automatically click the link to trigger download
temp_link.click();
document.body.removeChild(temp_link);
}
</script>
</body>
</html>

View File

@@ -0,0 +1 @@
file_path: C:\Inetpub\wwwroot\reports