Blog

Ansible Windows Updates Status Query

5/14/2025 2 min read

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