Files
Ansible/roles/maintenance_patch_os/tasks/windows.yml
T
2026-09-22 19:23:17 +02:00

163 lines
6.3 KiB
YAML

---
- name: Patching | Initialize Windows report state
ansible.builtin.set_fact:
_aim_patch_action_failed: false
_aim_patch_pre_reboot_performed: false
_aim_patch_any_reboot_performed: false
_aim_patch_preexisting_reboot_required: false
_aim_patch_preexisting_reboot_reasons: []
_aim_patch_reboot_deferred: false
_aim_patch_reboot_required_after: false
_aim_patch_blocked_reason: null
_aim_patch_continuation_required: false
_aim_patch_remaining_updates_known: false
_aim_patch_done: false
_aim_patch_cycles: 0
_aim_windows_update_runs: []
_aim_windows_searches: []
- name: Patching | Detect pending Windows reboot before patching
ansible.windows.win_reboot_info:
register: _aim_patch_pre_reboot_probe
- name: Patching | Record pre-existing Windows reboot state
ansible.builtin.set_fact:
_aim_patch_preexisting_reboot_required: '{{ _aim_patch_pre_reboot_probe.reboot_required | default(false) | bool }}'
_aim_patch_preexisting_reboot_reasons: '{{ _aim_patch_pre_reboot_probe.reboot_required_reasons | default([]) }}'
- name: Patching | Publish blocked Windows result when reboot is deferred
when:
- _aim_patch_preexisting_reboot_required | bool
- not (os_patching_reboot | bool)
block:
- name: Patching | Build blocked Windows patch report
ansible.builtin.set_fact:
_aim_patch_report: >-
{{ 'windows' | aim_report_patch_blocked(ansible_check_mode,
os_patching_reboot_delay_minutes | int,
os_patching_rescan_after_reboot | bool,
_aim_patch_preexisting_reboot_reasons) }}
- name: AIM | Publish blocked operation result
ansible.builtin.set_stats:
per_host: true
aggregate: false
data:
aim_output:
protocol: aim_output_v1
schema: patch_summary_v1
data: '{{ _aim_patch_report }}'
- name: Patching | Require reboot before continuing Windows patching
ansible.builtin.fail:
msg: >-
A reboot is already pending from a previous update or installation. Reboot the host first,
or rerun with "Reboot when required" enabled. No new Windows updates were started by this run.
- name: Patching | Clear pre-existing Windows reboot before patching
ansible.windows.win_reboot:
msg: '{{ os_patching_reboot_message }}'
pre_reboot_delay: '{{ [2, (os_patching_reboot_delay_minutes | int) * 60] | max }}'
reboot_timeout: '{{ os_patching_reboot_timeout | int }}'
register: _aim_patch_pre_reboot
when:
- _aim_patch_preexisting_reboot_required | bool
- os_patching_reboot | bool
- not ansible_check_mode
- name: Patching | Record pre-patch Windows reboot
ansible.builtin.set_fact:
_aim_patch_pre_reboot_performed: '{{ _aim_patch_pre_reboot.rebooted | default(false) | bool }}'
_aim_patch_any_reboot_performed: '{{ _aim_patch_pre_reboot.rebooted | default(false) | bool }}'
_aim_patch_done: >-
{{ (_aim_patch_pre_reboot.rebooted | default(false) | bool) and
not (os_patching_rescan_after_reboot | bool) }}
_aim_patch_continuation_required: >-
{{ (_aim_patch_pre_reboot.rebooted | default(false) | bool) and
not (os_patching_rescan_after_reboot | bool) }}
_aim_patch_remaining_updates_known: false
- name: Patching | Search Windows updates in check mode
ansible.windows.win_updates:
category_names: '{{ os_patching_windows_categories }}'
state: searched
reboot: false
register: _aim_windows_check_search
when:
- ansible_check_mode
- not (_aim_patch_done | bool)
- name: Patching | Record Windows check-mode search
ansible.builtin.set_fact:
_aim_windows_searches: '{{ [_aim_windows_check_search] }}'
_aim_patch_remaining_updates_known: true
_aim_patch_continuation_required: '{{ (_aim_windows_check_search.found_update_count | default(0) | int) > 0 }}'
_aim_patch_done: true
when:
- ansible_check_mode
- _aim_windows_check_search is defined
- not (_aim_windows_check_search.skipped | default(false) | bool)
- name: Patching | Process Windows patch waves
ansible.builtin.include_tasks: windows_wave.yml
loop: >-
{{ (range(1, 13) | list) if (os_patching_rescan_after_reboot | bool) else [1] }}
loop_control:
loop_var: _aim_patch_wave_number
label: 'Windows patch wave {{ _aim_patch_wave_number }}'
when:
- not ansible_check_mode
- not (_aim_patch_done | bool)
- name: Patching | Guard automatic continuation wave limit
ansible.builtin.set_fact:
_aim_patch_action_failed: true
_aim_patch_blocked_reason: cycle_limit_reached
_aim_patch_continuation_required: true
when:
- not ansible_check_mode
- os_patching_rescan_after_reboot | bool
- not (_aim_patch_done | bool)
- name: Patching | Normalize Windows update results
ansible.builtin.set_fact:
_aim_patch_report: >-
{{ _aim_windows_update_runs |
aim_report_patch_windows_runs(
_aim_windows_searches,
ansible_check_mode,
_aim_patch_preexisting_reboot_required | bool,
_aim_patch_any_reboot_performed | bool,
os_patching_reboot | bool,
os_patching_reboot_delay_minutes | int,
os_patching_rescan_after_reboot | bool,
_aim_patch_cycles | int,
_aim_patch_continuation_required | bool,
_aim_patch_remaining_updates_known | bool,
_aim_patch_reboot_deferred | bool,
_aim_patch_reboot_required_after,
_aim_patch_blocked_reason,
not (_aim_patch_action_failed | bool),
_aim_patch_preexisting_reboot_reasons
) }}
- name: Patching | Update summary
ansible.builtin.debug:
msg: '{{ _aim_patch_report }}'
- name: AIM | Publish operation result
ansible.builtin.set_stats:
per_host: true
aggregate: false
data:
aim_output:
protocol: aim_output_v1
schema: patch_summary_v1
data: '{{ _aim_patch_report }}'
- name: Patching | Preserve Windows update failure
ansible.builtin.fail:
msg: >-
Windows patching stopped before the approved patch wave completed. The structured result contains
successfully installed updates, bounded failed-update reasons when available, and whether another
operator-approved run is required. AIM did not replay the patch job automatically.
when: _aim_patch_action_failed | bool