From 15bdc3b966c7e1dc11d00e6ea7c216b09d4b837a Mon Sep 17 00:00:00 2001 From: Egor Tensin Date: Sun, 23 Nov 2025 17:32:30 +0100 Subject: plugins: add apt_wrapper --- plugins/action/apt_wrapper.py | 67 ++++++++++++++++++++++++++++++++++++ roles/apt/tasks/main.yml | 74 ++++++++-------------------------------- roles/apt_install/tasks/main.yml | 41 ++++------------------ 3 files changed, 88 insertions(+), 94 deletions(-) create mode 100755 plugins/action/apt_wrapper.py diff --git a/plugins/action/apt_wrapper.py b/plugins/action/apt_wrapper.py new file mode 100755 index 0000000..00decc2 --- /dev/null +++ b/plugins/action/apt_wrapper.py @@ -0,0 +1,67 @@ +#!/usr/bin/python + +import base64 +import re + +from ansible.errors import AnsibleActionFail +from ansible.module_utils.common.text.converters import to_text +from ansible.plugins.action import ActionBase + +LOG_PATH = '/var/log/dpkg.log' + + +class ActionModule(ActionBase): + def run(self, tmp=None, task_vars=None): + super().run(tmp, task_vars) + + if self._check_dpkg_log(task_vars): + before = self._parse_dpkg_log(task_vars) + else: + before = [] + + apt_result = self._execute_module( + module_name='ansible.builtin.apt', + module_args=self._task.args.get('apt_args', {}), + task_vars=task_vars, + ) + + after = self._parse_dpkg_log(task_vars) + + apt_result['packages'] = after[len(before):] + return apt_result + + def _check_dpkg_log(self, task_vars): + return self._is_file_readable(LOG_PATH, task_vars) + + def _parse_dpkg_log(self, task_vars): + contents = self._read_file(LOG_PATH, task_vars) + lines = contents.splitlines() + regex = re.compile(' install | upgrade | remove | purge ') + lines = [line for line in lines if regex.search(line)] + lines = [' '.join(line.split(' ')[2:]) for line in lines] + return lines + + def _is_file_readable(self, path, task_vars): + stat_result = self._execute_module( + module_name='ansible.builtin.stat', + module_args=dict( + path=path, + get_attributes=False, + get_checksum=False, + get_mime=False, + ), + task_vars=task_vars, + ) + if stat_result.get('failed'): + raise AnsibleActionFail(f"Couldn't stat file {path}", result=stat_result) + return stat_result['stat']['readable'] + + def _read_file(self, path, task_vars): + read_result = self._execute_module( + module_name='ansible.builtin.slurp', + module_args=dict(src=path), + task_vars=task_vars, + ) + if read_result.get('failed'): + raise AnsibleActionFail(f"Couldn't read file {path}", result=read_result) + return base64.b64decode(to_text(read_result['content'])).decode('utf-8') diff --git a/roles/apt/tasks/main.yml b/roles/apt/tasks/main.yml index 2e4fc3b..dd5db7b 100644 --- a/roles/apt/tasks/main.yml +++ b/roles/apt/tasks/main.yml @@ -1,20 +1,9 @@ -- name: Get dpkg.log - ansible.builtin.shell: | - set -o pipefail && \ - if [ -s /var/log/dpkg.log ]; then \ - grep ' install \| upgrade \| remove \| purge ' /var/log/dpkg.log \ - | cut -d ' ' -f 3-5 ; \ - fi - vars: - ansible_shell_executable: /bin/bash - register: dpkg_log1 - changed_when: false - - name: Upgrade packages become: true - ansible.builtin.apt: - update_cache: true - upgrade: dist + tensin.infra.apt_wrapper: + apt_args: + update_cache: true + upgrade: dist register: apt_result - name: Reboot @@ -24,58 +13,23 @@ reboot_timeout: 180 when: apt_result is changed -- name: Get dpkg.log - ansible.builtin.shell: | - set -o pipefail && \ - if [ -s /var/log/dpkg.log ]; then \ - grep ' install \| upgrade \| remove \| purge ' /var/log/dpkg.log \ - | cut -d ' ' -f 3-5 ; \ - fi - vars: - ansible_shell_executable: /bin/bash - register: dpkg_log2 - changed_when: false - - name: Show upgraded packages ansible.builtin.debug: - var: dpkg_log_diff - when: dpkg_len_diff > 0 - vars: - dpkg_log1_len: '{{ dpkg_log1.stdout_lines | length }}' - dpkg_log2_len: '{{ dpkg_log2.stdout_lines | length }}' - dpkg_len_diff: '{{ dpkg_log2_len - dpkg_log1_len }}' - dpkg_log_diff: '{{ dpkg_log2.stdout_lines[-dpkg_len_diff:] }}' - -- name: Reboot if necessary - ansible.builtin.meta: flush_handlers + var: apt_result.packages + when: apt_result is changed - name: Clean up dependencies become: true - ansible.builtin.apt: - autoremove: true - purge: true - -- name: Get dpkg.log - ansible.builtin.shell: | - set -o pipefail && \ - if [ -s /var/log/dpkg.log ]; then \ - grep ' install \| upgrade \| remove \| purge ' /var/log/dpkg.log \ - | cut -d ' ' -f 3-5 ; \ - fi - vars: - ansible_shell_executable: /bin/bash - register: dpkg_log3 - changed_when: false + tensin.infra.apt_wrapper: + apt_args: + autoremove: true + purge: true + register: apt_result -- name: Show upgraded packages +- name: Show removed dependencies ansible.builtin.debug: - var: dpkg_log_diff - when: dpkg_len_diff > 0 - vars: - dpkg_log2_len: '{{ dpkg_log2.stdout_lines | length }}' - dpkg_log3_len: '{{ dpkg_log3.stdout_lines | length }}' - dpkg_len_diff: '{{ dpkg_log3_len - dpkg_log2_len }}' - dpkg_log_diff: '{{ dpkg_log3.stdout_lines[-dpkg_len_diff:] }}' + var: apt_result.packages + when: apt_result is changed - name: Configure unattended-upgrades ansible.builtin.include_tasks: unattended_upgrades.yml diff --git a/roles/apt_install/tasks/main.yml b/roles/apt_install/tasks/main.yml index 19204e1..022d9d2 100644 --- a/roles/apt_install/tasks/main.yml +++ b/roles/apt_install/tasks/main.yml @@ -1,39 +1,12 @@ -- name: Get dpkg.log - ansible.builtin.shell: | - set -o pipefail && \ - if [ -s /var/log/dpkg.log ]; then \ - grep ' install \| upgrade \| remove \| purge ' /var/log/dpkg.log \ - | cut -d ' ' -f 3-5 ; \ - fi - vars: - ansible_shell_executable: /bin/bash - register: dpkg_log1 - changed_when: false - - name: Install packages become: true - ansible.builtin.package: - name: '{{ apt_install_packages }}' - state: present - -- name: Get dpkg.log - ansible.builtin.shell: | - set -o pipefail && \ - if [ -s /var/log/dpkg.log ]; then \ - grep ' install \| upgrade \| remove \| purge ' /var/log/dpkg.log \ - | cut -d ' ' -f 3-5 ; \ - fi - vars: - ansible_shell_executable: /bin/bash - register: dpkg_log2 - changed_when: false + tensin.infra.apt_wrapper: + apt_args: + name: '{{ apt_install_packages }}' + state: present + register: apt_result - name: Show installed packages ansible.builtin.debug: - var: dpkg_log_diff - when: dpkg_len_diff > 0 - vars: - dpkg_log1_len: '{{ dpkg_log1.stdout_lines | length }}' - dpkg_log2_len: '{{ dpkg_log2.stdout_lines | length }}' - dpkg_len_diff: '{{ dpkg_log2_len - dpkg_log1_len }}' - dpkg_log_diff: '{{ dpkg_log2.stdout_lines[-dpkg_len_diff:] }}' + var: apt_result.packages + when: apt_result is changed -- cgit v1.3