--- - name: Validate patch window when: enforce_patch_window | bool block: - name: Check current time against patch window ansible.builtin.assert: that: - ansible_date_time.hour | int >= patch_window_start.split(':')[0] | int - ansible_date_time.hour | int < patch_window_end.split(':')[0] | int fail_msg: | Current time {{ ansible_date_time.hour }}:{{ ansible_date_time.minute }} is outside patch window {{ patch_window_start }}-{{ patch_window_end }} - name: Create pre-patch backup when: backup_before_patch | bool block: - name: Create backup directory ansible.builtin.file: path: "/var/backups/pre-patch-{{ ansible_date_time.iso8601 }}" state: directory mode: '0755' - name: Capture current package list ansible.builtin.shell: | set -o pipefail dpkg --get-selections > /var/backups/pre-patch-{{ ansible_date_time.iso8601 }}/packages.list changed_when: false - name: Check for available updates ansible.builtin.shell: | set -o pipefail apt list --upgradable 2>/dev/null | grep -v "Listing..." | wc -l register: updates_available_count changed_when: false failed_when: false - name: Update package cache ansible.builtin.apt: update_cache: true cache_valid_time: 300 changed_when: false - name: Check if reboot required before patching ansible.builtin.stat: path: /var/run/reboot-required register: reboot_required_before changed_when: false - name: Apply security updates ansible.builtin.apt: upgrade: dist update_cache: true when: patch_security_only | bool register: apt_update_result notify: restart patching services - name: Apply all available updates ansible.builtin.apt: upgrade: full update_cache: true when: not (patch_security_only | bool) register: apt_update_result notify: restart patching services - name: Check if reboot required after patching ansible.builtin.stat: path: /var/run/reboot-required register: reboot_required_after changed_when: false - name: Verify critical services are running ansible.builtin.service: name: "{{ item }}" state: started enabled: true loop: "{{ critical_services }}" failed_when: false - name: Run post-patch health checks ansible.builtin.uri: url: http://localhost/health method: GET status_code: 200 register: health_check failed_when: false ignore_errors: true when: "'webservers' in group_names" - name: Set reboot required flag ansible.builtin.set_fact: reboot_required: "{{ reboot_required_after.stat.exists | default(false) }}" - name: Perform system reboot if required ansible.builtin.reboot: msg: "Rebooting after security patches" timeout: "{{ reboot_timeout }}" when: reboot_required and reboot_if_required | bool - name: Generate patching report ansible.builtin.template: src: patch_report.j2 dest: /var/log/patch_report_{{ ansible_date_time.iso8601 }}.log mode: '0644' vars: updates_applied_count: "{{ apt_update_result.changed | ternary('Yes', 'No') }}" reboot_required_flag: "{{ reboot_required }}"