Add linux_patch role — package facts before/after, apt/dnf, version diff tracking
This commit is contained in:
@@ -1,6 +1,131 @@
|
||||
---
|
||||
# linux_patch tasks
|
||||
# Implementation to follow
|
||||
- name: Placeholder
|
||||
- name: Gather package facts before patching
|
||||
ansible.builtin.package_facts:
|
||||
manager: auto
|
||||
register: packages_before
|
||||
|
||||
- name: Store pre-patch package versions
|
||||
ansible.builtin.set_fact:
|
||||
packages_pre_patch: "{{ ansible_facts.packages }}"
|
||||
|
||||
- name: Check for available updates (Debian/Ubuntu)
|
||||
ansible.builtin.apt:
|
||||
update_cache: true
|
||||
cache_valid_time: 3600
|
||||
when: ansible_os_family == "Debian"
|
||||
changed_when: false
|
||||
|
||||
- name: Get list of upgradable packages (Debian/Ubuntu)
|
||||
ansible.builtin.shell: |
|
||||
apt list --upgradable 2>/dev/null | grep -v "Listing..." | awk -F'/' '{print $1}'
|
||||
register: upgradable_packages
|
||||
changed_when: false
|
||||
when: ansible_os_family == "Debian"
|
||||
|
||||
- name: Get list of upgradable packages (RHEL/CentOS)
|
||||
ansible.builtin.shell: |
|
||||
dnf check-update --quiet | awk '{print $1}' | grep -v "^$"
|
||||
register: upgradable_packages
|
||||
changed_when: false
|
||||
failed_when: upgradable_packages.rc not in [0, 100]
|
||||
when: ansible_os_family == "RedHat"
|
||||
|
||||
- name: Log packages to be updated
|
||||
ansible.builtin.debug:
|
||||
msg: "linux_patch role - tasks to be implemented"
|
||||
msg: "Packages to be updated on {{ inventory_hostname }}: {{ upgradable_packages.stdout_lines | length }} packages"
|
||||
|
||||
- name: Perform full upgrade (Debian/Ubuntu)
|
||||
ansible.builtin.apt:
|
||||
upgrade: dist
|
||||
autoremove: true
|
||||
autoclean: true
|
||||
register: apt_upgrade_result
|
||||
when:
|
||||
- ansible_os_family == "Debian"
|
||||
- patch_mode == "full" or patch_mode == "security"
|
||||
|
||||
- name: Perform security-only upgrade (RHEL/CentOS)
|
||||
ansible.builtin.dnf:
|
||||
name: "*"
|
||||
state: latest
|
||||
security: "{{ patch_mode == 'security' }}"
|
||||
update_cache: true
|
||||
register: dnf_upgrade_result
|
||||
when: ansible_os_family == "RedHat"
|
||||
|
||||
- name: Gather package facts after patching
|
||||
ansible.builtin.package_facts:
|
||||
manager: auto
|
||||
|
||||
- name: Store post-patch package versions
|
||||
ansible.builtin.set_fact:
|
||||
packages_post_patch: "{{ ansible_facts.packages }}"
|
||||
|
||||
- name: Calculate changed packages
|
||||
ansible.builtin.set_fact:
|
||||
packages_updated: >-
|
||||
{{
|
||||
packages_post_patch | dict2items
|
||||
| selectattr('key', 'in', packages_pre_patch)
|
||||
| selectattr('value', '!=', packages_pre_patch[item.key] | default([]))
|
||||
| list
|
||||
| map(attribute='key')
|
||||
| list
|
||||
}}
|
||||
loop: "{{ packages_post_patch | dict2items }}"
|
||||
when: false
|
||||
|
||||
- name: Build packages updated list
|
||||
ansible.builtin.set_fact:
|
||||
packages_updated: >-
|
||||
{%- set updated = [] -%}
|
||||
{%- for pkg, details in packages_post_patch.items() -%}
|
||||
{%- if pkg in packages_pre_patch -%}
|
||||
{%- if details[0].version != packages_pre_patch[pkg][0].version -%}
|
||||
{%- set _ = updated.append({
|
||||
'name': pkg,
|
||||
'version_before': packages_pre_patch[pkg][0].version,
|
||||
'version_after': details[0].version,
|
||||
'type': 'updated'
|
||||
}) -%}
|
||||
{%- endif -%}
|
||||
{%- else -%}
|
||||
{%- set _ = updated.append({
|
||||
'name': pkg,
|
||||
'version_before': 'not installed',
|
||||
'version_after': details[0].version,
|
||||
'type': 'new'
|
||||
}) -%}
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{{ updated }}
|
||||
|
||||
- name: Log updated packages
|
||||
ansible.builtin.debug:
|
||||
msg: "Updated: {{ item.name }} {{ item.version_before }} -> {{ item.version_after }}"
|
||||
loop: "{{ packages_updated }}"
|
||||
|
||||
- name: Check if reboot is required after patching (Debian/Ubuntu)
|
||||
ansible.builtin.stat:
|
||||
path: /var/run/reboot-required
|
||||
register: reboot_required_post
|
||||
when: ansible_os_family == "Debian"
|
||||
|
||||
- name: Update reboot required fact
|
||||
ansible.builtin.set_fact:
|
||||
host_reboot_required: "{{ reboot_required_post.stat.exists | default(false) }}"
|
||||
when: ansible_os_family == "Debian"
|
||||
|
||||
- name: Reboot if required and auto_reboot is enabled
|
||||
ansible.builtin.reboot:
|
||||
reboot_timeout: 300
|
||||
pre_reboot_delay: 10
|
||||
post_reboot_delay: 30
|
||||
msg: "Rebooting after patch run — initiated by Ansible"
|
||||
when:
|
||||
- host_reboot_required | bool
|
||||
- auto_reboot | bool
|
||||
|
||||
- name: Patching complete
|
||||
ansible.builtin.debug:
|
||||
msg: "Patching complete on {{ inventory_hostname }} — {{ packages_updated | length }} packages updated"
|
||||
|
||||
Reference in New Issue
Block a user