tasks
This commit is contained in:
@@ -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,80 +27,24 @@
|
|||||||
(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:
|
ansible.windows.win_powershell:
|
||||||
script: |
|
script: |
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
Import-Module ScheduledTasks
|
Import-Module ScheduledTasks
|
||||||
$tp='{{ task_path }}'; $tn='{{ task_name }}'
|
$tp='{{ task_path }}'; $tn='{{ task_name }}'
|
||||||
(Get-ScheduledTaskInfo -TaskPath $tp -TaskName $tn).LastRunTime.ToString('o')
|
$i = Get-ScheduledTaskInfo -TaskPath $tp -TaskName $tn
|
||||||
register: started_info
|
[PSCustomObject]@{ State=$i.State; LastTaskResult=$i.LastTaskResult } | ConvertTo-Json -Compress
|
||||||
retries: "{{ start_retries }}"
|
register: task_info
|
||||||
|
failed_when: false
|
||||||
|
retries: "{{ finish_retries }}"
|
||||||
delay: "{{ poll_delay }}"
|
delay: "{{ poll_delay }}"
|
||||||
until: >
|
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:
|
|
||||||
script: |
|
|
||||||
$ErrorActionPreference = 'Stop'
|
|
||||||
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
|
|
||||||
retries: "{{ finish_retries }}"
|
|
||||||
delay: "{{ poll_delay }}"
|
|
||||||
until: >
|
|
||||||
(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)
|
|
||||||
|
|
||||||
rescue:
|
|
||||||
# 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)
|
(task_info.stdout | default('') | length > 0)
|
||||||
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)
|
||||||
|
|
||||||
- name: Reboot if ready (belt & suspenders)
|
- name: Reboot if needed
|
||||||
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'
|
||||||
|
|||||||
Reference in New Issue
Block a user