A WSUS server can be useful, but it can consume considerable resources, often respond slowly, and also requires significant maintenance effort or additional software for upkeep.
A more efficient solution is to use Ansible to query updates. With this playbook, you can search for updates on any host and list them in a structured status email.
Prerequisites
Before you use this playbook, make sure the following prerequisites are met:
- Working Ansible installation
- Reachable Windows hosts via WinRM
- Permissions to install PowerShell modules
- Mail server to send the report
Ansible Playbook
# Ansible playbook to ensure that the PSWindowsUpdate module is installed on Windows hosts,
# check for pending updates, log the update status, and send a consolidated report by email.
- hosts: all
vars:
# Defines the path for the email report file
email_report_file: "/tmp/linux_email_report.txt"
tasks:
- name: Initialize email report file
copy:
# Creates or overwrites the email report file with empty content
content: ""
dest: "{{ email_report_file }}"
delegate_to: localhost
run_once: true
- name: Ensure the PSWindowsUpdate module is installed
win_shell: |
# Checks if the PSWindowsUpdate module is installed, installs it if not
if (-not (Get-Module -ListAvailable -Name PSWindowsUpdate)) {
Install-Module -Name PSWindowsUpdate -Force -AllowClobber
}
register: module_update
ignore_errors: true
- name: Import PSWindowsUpdate module and search for updates
win_shell: |
# Imports the PSWindowsUpdate module and retrieves a list of pending updates
Import-Module PSWindowsUpdate
$Updates = Get-WindowsUpdate -MicrosoftUpdate -AcceptAll -IgnoreReboot
$UpdateTitles = $Updates | ForEach-Object { $_.Title }
$UpdateTitles -join "`n"
register: update_titles
ignore_errors: true
- name: Log update titles with proper formatting
lineinfile:
# Logs the hostname and list of pending updates in HTML format
path: "{{ email_report_file }}"
line: |
**{{ inventory_hostname }}** | Pending updates:
{{ update_titles.stdout | regex_replace('`n', '\n') }}
delegate_to: localhost
# Task to read the consolidated email report and send it by email
- hosts: localhost
gather_facts: no
vars:
# Defines the path to the email report file
email_report_file: "/tmp/linux_email_report.txt"
tasks:
- name: Read email report from file
slurp:
# Reads the content of the email report file
src: "{{ email_report_file }}"
register: email_content
- name: Decode email content and prepare HTML email body
set_fact:
# Decodes the content from Base64 and formats it as HTML
email_body: "Here is the status report for the server updates:\n\n{{ (email_content.content | b64decode).splitlines() | join('\n') }}\n\n"
- name: Send status email after all hosts have been updated
mail:
# Sends the email with the consolidated report
host: dein-mail-server.com
port: 25
from: ansible@example.com
to: dein-email@example.com
subject: "Server Update Status"
subtype: html
body: "{{ email_body }}"
charset: utf8
Troubleshooting
WinRM can often be picky and is not the same across all Windows versions. If individual servers report errors, the easiest way is to manually run the commands Ansible executes on the affected host and check where it fails.
Check if the PSWindowsUpdate module is installed
Get-Module -ListAvailable -Name PSWindowsUpdate
Install the PSWindowsUpdate module
Install-Module -Name PSWindowsUpdate -Force -AllowClobber
Import the module and search for updates
Import-Module PSWindowsUpdate
Get-WindowsUpdate -MicrosoftUpdate -AcceptAll -IgnoreReboot