diff --git a/www-install-win-updates.yaml b/www-install-win-updates.yaml deleted file mode 100644 index d8ebe4c..0000000 --- a/www-install-win-updates.yaml +++ /dev/null @@ -1,258 +0,0 @@ ---- -- name: Windows Update Installation from Assessment Report - hosts: windows - gather_facts: no - - tasks: - - name: Get current timestamp - set_fact: - current_timestamp: "{{ lookup('pipe', 'date +%Y-%m-%dT%H:%M:%S') }}" - - - name: Check if KB updates report file exists - win_stat: - path: 'C:\Temp\windows_updates_with_kb.txt' - register: kb_updates_file - - - name: Fail if updates report file is missing - fail: - msg: 'KB updates report file not found at C:\Temp\windows_updates_with_kb.txt. Please run the assessment playbook first.' - when: not kb_updates_file.stat.exists - - - name: Read KB updates report content - win_shell: Get-Content -Path 'C:\Temp\windows_updates_with_kb.txt' - register: updates_content - when: kb_updates_file.stat.exists - - - name: Extract KB numbers from report file - set_fact: - kb_numbers: "{{ updates_content.stdout_lines - | select('match', '.*KB: .*') - | map('regex_replace', '.*KB: ([0-9,\\s]+).*', '\\1') - | map('split', ',') | flatten | map('trim') - | select('match', '^[0-9]+$') | list | unique }}" - when: - - kb_updates_file.stat.exists - - updates_content.stdout_lines is defined - - - name: Display KB numbers to be installed - debug: - msg: - - "Found {{ kb_numbers | length }} unique KB numbers to install:" - - "{{ kb_numbers | join(', ') }}" - when: - - kb_updates_file.stat.exists - - kb_numbers is defined - - kb_numbers | length > 0 - - # ---- Patch with failure capture (block/rescue) ---- - - name: Install Windows updates by KB numbers (with failure capture) - block: - - name: Install Windows updates by KB numbers - win_updates: - category_names: '*' - state: installed - accept_list: "{{ kb_numbers }}" - log_path: 'C:\Temp\windows_update_installation.log' - register: installation_result - when: - - kb_updates_file.stat.exists - - kb_numbers is defined - - kb_numbers | length > 0 - - - name: Mark host failed if any KB installs failed (module reported partial failures) - set_fact: - patch_failed_host: "{{ (installation_result.failed_update_count | default(0) | int) > 0 }}" - patch_failed_count: "{{ installation_result.failed_update_count | default(0) | int }}" - when: installation_result is defined - - rescue: - - name: Mark host failed because win_updates task error/exception - set_fact: - patch_failed_host: true - patch_failed_count: "{{ (patch_failed_count | default(0) | int) + 1 }}" - - always: - - name: Ensure failure flags exist (default to false/0) - set_fact: - patch_failed_host: "{{ patch_failed_host | default(false) }}" - patch_failed_count: "{{ patch_failed_count | default(0) | int }}" - - - name: Display installation summary - debug: - msg: - - "=== WINDOWS UPDATE INSTALLATION COMPLETE ===" - - "Host: {{ inventory_hostname }}" - - "Updates Found: {{ installation_result.found_update_count | default(0) }}" - - "Updates Installed: {{ installation_result.installed_update_count | default(0) }}" - - "Updates Failed: {{ installation_result.failed_update_count | default(0) }}" - - "Reboot Required: {{ 'Yes' if installation_result.reboot_required | default(false) else 'No' }}" - - "Patch failed flag: {{ patch_failed_host | default(false) }}" - when: - - kb_updates_file.stat.exists - - kb_numbers is defined - - kb_numbers | length > 0 - - - name: Reboot if required - win_reboot: - reboot_timeout: 1800 - when: installation_result is defined and (installation_result.reboot_required | default(false)) - - - name: Create installation report - set_fact: - installation_summary: | - Windows Update Installation Report - ================================= - Host: {{ inventory_hostname }} - Date: {{ current_timestamp }} - - Summary: - -------- - Total Updates Found: {{ installation_result.found_update_count | default(0) }} - Successfully Installed: {{ installation_result.installed_update_count | default(0) }} - Failed Installations: {{ installation_result.failed_update_count | default(0) }} - Reboot Required: {{ installation_result.reboot_required | default('No') }} - - Requested KB Numbers: {{ kb_numbers | default([]) | join(', ') }} - - {% if installation_result is defined and installation_result.updates is defined %} - Installed Updates: - ----------------- - {% for update_id, update_info in installation_result.updates.items() %} - - {{ update_info.title }} - KB: {{ update_info.kb | join(', ') if update_info.kb else 'None' }} - {% endfor %} - {% endif %} - when: - - kb_updates_file.stat.exists - - - name: Save installation report to file - win_copy: - content: "{{ installation_summary }}" - dest: 'C:\Temp\windows_update_installation_report.txt' - when: installation_summary is defined - - - name: Give a report when no KB numbers were found on updates - debug: - msg: "No valid KB numbers found in the updates report file. Please verify the assessment report." - when: - - kb_updates_file.stat.exists - - (kb_numbers is not defined or kb_numbers | length == 0) - -# ------------------------------------------------------------------------------ - -- name: Post patching results to SharePoint (Graph) - hosts: windows - gather_facts: false - - vars: - tenant_id: "{{ lookup('env', 'SP_TENANT_ID') }}" - client_id: "{{ lookup('env', 'SP_CLIENT_ID') }}" - client_secret: "{{ lookup('env', 'SP_CLIENT_SECRET') }}" - site_id: "{{ lookup('env', 'SP_SITE_ID') }}" - list_id: "{{ lookup('env', 'SP_LIST_ID') }}" - - job_id: "{{ tower_job_id | default('n/a') }}" - job_name: "{{ tower_job_template_name | default('Patch run') }}" - job_url: "{{ tower_job_url | default('') }}" - - run_start: "{{ lookup('pipe','date -u +%Y-%m-%dT%H:%M:%SZ') }}" - run_end: "{{ lookup('pipe','date -u +%Y-%m-%dT%H:%M:%SZ') }}" - - summary_text: >- - Job {{ job_id }}. - Template={{ job_name }}. - URL={{ job_url }}. - - tasks: - - name: Aggregate per-host patch failures (from first play) - run_once: true - delegate_to: localhost - set_fact: - failed_hosts_list: [] - - - name: Collect failed hosts (no extract filter) - run_once: true - delegate_to: localhost - set_fact: - failed_hosts_list: "{{ failed_hosts_list + [item] }}" - loop: "{{ ansible_play_hosts_all }}" - when: hostvars[item].patch_failed_host | default(false) - - - name: Build flags from failed hosts list - run_once: true - delegate_to: localhost - set_fact: - any_patch_failed: "{{ (failed_hosts_list | length) > 0 }}" - failed_hosts_csv: "{{ failed_hosts_list | join(', ') if failed_hosts_list | length > 0 else 'None' }}" - - - name: Build final status (only from per-host flags) - run_once: true - set_fact: - status_final: "{{ 'failed' if (any_patch_failed | default(false)) else 'successful' }}" - - - name: Acquire Graph token (client credentials) - delegate_to: localhost - run_once: true - uri: - url: "https://login.microsoftonline.com/{{ tenant_id }}/oauth2/v2.0/token" - method: POST - headers: - Content-Type: "application/x-www-form-urlencoded" - body: > - client_id={{ client_id }} - &client_secret={{ client_secret | urlencode }} - &scope=https%3A%2F%2Fgraph.microsoft.com%2F.default - &grant_type=client_credentials - register: graph_token - no_log: true - failed_when: graph_token.status not in [200] - - - name: Create SharePoint list item (Graph) - delegate_to: localhost - run_once: true - uri: - url: "https://graph.microsoft.com/v1.0/sites/{{ site_id }}/lists/{{ list_id }}/items" - method: POST - headers: - Authorization: "Bearer {{ graph_token.json.access_token }}" - Content-Type: "application/json" - body_format: json - return_content: true - status_code: [200, 201] - body: - fields: - Title: "{{ job_name }} ({{ job_id }})" - Status: "{{ status_final }}" - RunStart: "{{ run_start }}" - RunEnd: "{{ run_end }}" - Notes: |- - {{ summary_text }} - Failed hosts: {{ failed_hosts_csv }} - register: sp_create - ignore_errors: true - no_log: true - - - name: Show sanitized Graph error (if any) - run_once: true - when: sp_create is failed - vars: - _json: "{{ sp_create.json | default({}) }}" - debug: - msg: - status: "{{ sp_create.status | default('n/a') }}" - graph_error: >- - {{ _json.error.message - | default(_json.message - | default(sp_create.msg | default('Unknown error'))) }} - - - name: Fail if SharePoint item was not created - run_once: true - when: sp_create is failed - fail: - msg: "Failed to create SharePoint item (see previous message)." - - - name: Show created list item id - run_once: true - when: sp_create is succeeded - debug: - var: sp_create.json.id