summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorEgor Tensin <egor@tensin.name>2025-11-23 17:32:30 +0100
committerEgor Tensin <egor@tensin.name>2025-11-23 18:47:43 +0100
commit15bdc3b966c7e1dc11d00e6ea7c216b09d4b837a (patch)
tree0b90bc64aaa9b8078649527d6818341150aa8c12
parentmy_dotfiles: prettier repo URL (diff)
downloadinfra-ansible-15bdc3b966c7e1dc11d00e6ea7c216b09d4b837a.tar.gz
infra-ansible-15bdc3b966c7e1dc11d00e6ea7c216b09d4b837a.zip
plugins: add apt_wrapper
-rwxr-xr-xplugins/action/apt_wrapper.py67
-rw-r--r--roles/apt/tasks/main.yml74
-rw-r--r--roles/apt_install/tasks/main.yml41
3 files changed, 88 insertions, 94 deletions
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