This commit is contained in:
2025-08-19 17:00:44 +02:00
parent 6a1a25c85c
commit 5a1b3343c1

View File

@@ -4,47 +4,21 @@
gather_facts: no gather_facts: no
vars: vars:
task_path: '\' # or e.g. '\\Microsoft\\Windows\\WindowsUpdate\\' task_path: '\\' # root folder
task_name: 'Patching-windows-task' task_name: 'Patching-windows-task'
poll_delay: 60 # seconds poll_delay: 60
start_retries: 30 # up to 30 minutes to confirm it started finish_retries: 3 # up to 6h
finish_retries: 3 # up to 6 hours to finish
winrm_port: 5986
tasks: tasks:
- name: Verify task exists and capture pre-start info - name: Ensure the task is enabled
ansible.windows.win_powershell:
script: |
$ErrorActionPreference = 'Stop'
Import-Module ScheduledTasks
$tp='{{ task_path }}'; $tn='{{ task_name }}'
$t = Get-ScheduledTask -TaskPath $tp -TaskName $tn
$i = Get-ScheduledTaskInfo -TaskPath $tp -TaskName $tn
[PSCustomObject]@{
Exists = $true
State = $i.State
LastRunTime = $i.LastRunTime
LastTaskResult= $i.LastTaskResult
Enabled = $t.Settings.Enabled
} | ConvertTo-Json -Compress
register: pre_info
- name: Fail if task not found
ansible.builtin.fail:
msg: "Task '{{ task_path }}{{ task_name }}' not found."
when: pre_info.stdout | default('') == ''
- name: Ensure task is enabled
ansible.windows.win_powershell: ansible.windows.win_powershell:
script: | script: |
Import-Module ScheduledTasks Import-Module ScheduledTasks
$tp='{{ task_path }}'; $tn='{{ task_name }}' $tp='{{ task_path }}'; $tn='{{ task_name }}'
$t = Get-ScheduledTask -TaskPath $tp -TaskName $tn $t = Get-ScheduledTask -TaskPath $tp -TaskName $tn
if (-not $t.Settings.Enabled) { Enable-ScheduledTask -TaskPath $tp -TaskName $tn | Out-Null } if (-not $t.Settings.Enabled) { Enable-ScheduledTask -TaskPath $tp -TaskName $tn | Out-Null }
register: enable_task
failed_when: false
- name: Start the SYSTEM patch task (schtasks) - name: Start the SYSTEM patch task
ansible.windows.win_command: > ansible.windows.win_command: >
schtasks /Run /TN "{{ task_path }}{{ task_name }}" schtasks /Run /TN "{{ task_path }}{{ task_name }}"
register: start_task register: start_task
@@ -53,35 +27,14 @@
(start_task.rc | default(1)) == 0 (start_task.rc | default(1)) == 0
or ('SUCCESS' in (start_task.stdout | default(''))) or ('SUCCESS' in (start_task.stdout | default('')))
# Confirm the task actually started (LastRunTime advanced) - name: Poll until Ready/Disabled with success
- name: Wait until LastRunTime changes (task actually started)
ansible.windows.win_powershell:
script: |
Import-Module ScheduledTasks
$tp='{{ task_path }}'; $tn='{{ task_name }}'
(Get-ScheduledTaskInfo -TaskPath $tp -TaskName $tn).LastRunTime.ToString('o')
register: started_info
retries: "{{ start_retries }}"
delay: "{{ poll_delay }}"
until: >
(started_info.stdout | default('') | length > 0) and
(started_info.stdout != (pre_info.stdout | from_json).LastRunTime)
# Long poll until the task finishes successfully
- name: Poll until task is Ready/Disabled with LastTaskResult 0
block:
- name: Get current task state/result
ansible.windows.win_powershell: ansible.windows.win_powershell:
script: | script: |
$ErrorActionPreference = 'Stop' $ErrorActionPreference = 'Stop'
Import-Module ScheduledTasks Import-Module ScheduledTasks
$tp='{{ task_path }}'; $tn='{{ task_name }}' $tp='{{ task_path }}'; $tn='{{ task_name }}'
$i = Get-ScheduledTaskInfo -TaskPath $tp -TaskName $tn $i = Get-ScheduledTaskInfo -TaskPath $tp -TaskName $tn
[PSCustomObject]@{ [PSCustomObject]@{ State=$i.State; LastTaskResult=$i.LastTaskResult } | ConvertTo-Json -Compress
State = $i.State
LastTaskResult = $i.LastTaskResult
LastRunTime = $i.LastRunTime
} | ConvertTo-Json -Compress
register: task_info register: task_info
failed_when: false failed_when: false
retries: "{{ finish_retries }}" retries: "{{ finish_retries }}"
@@ -91,42 +44,7 @@
and ((task_info.stdout | from_json).State in ['Ready','Disabled']) and ((task_info.stdout | from_json).State in ['Ready','Disabled'])
and (((task_info.stdout | from_json).LastTaskResult | int) == 0) and (((task_info.stdout | from_json).LastTaskResult | int) == 0)
rescue: - name: Reboot if needed
# If the node rebooted and PSRP dropped, wait for WinRM then check once more
- name: Wait for WinRM after possible reboot
ansible.windows.win_wait_for:
port: "{{ winrm_port }}"
timeout: 1800
- name: Final check after reconnect
ansible.windows.win_powershell:
script: |
Import-Module ScheduledTasks
$tp='{{ task_path }}'; $tn='{{ task_name }}'
$i = Get-ScheduledTaskInfo -TaskPath $tp -TaskName $tn
[PSCustomObject]@{ State=$i.State; LastTaskResult=$i.LastTaskResult; LastRunTime=$i.LastRunTime } |
ConvertTo-Json -Compress
register: task_info
failed_when: false
- name: Show final task state/result
ansible.builtin.debug:
msg:
- "Final State: {{ (task_info.stdout | default('{}') | from_json).State | default('n/a') }}"
- "LastTaskResult: {{ (task_info.stdout | default('{}') | from_json).LastTaskResult | default('n/a') }}"
- "LastRunTime: {{ (task_info.stdout | default('{}') | from_json).LastRunTime | default('n/a') }}"
- name: Fail if task ended but did not return 0
ansible.builtin.fail:
msg: >
Task finished in state {{ (task_info.stdout | from_json).State }}
with LastTaskResult {{ (task_info.stdout | from_json).LastTaskResult }} (non-zero).
when: >
(task_info.stdout | default('') | length > 0)
and ((task_info.stdout | from_json).State in ['Ready','Disabled'])
and (((task_info.stdout | from_json).LastTaskResult | int) != 0)
- name: Reboot if ready (belt & suspenders)
ansible.windows.win_reboot: ansible.windows.win_reboot:
reboot_timeout: 5400 reboot_timeout: 5400
when: (task_info.stdout | from_json).State == 'Ready' when: (task_info.stdout | from_json).State == 'Ready'