From 34d55f08499d36dd250f1989ea7d818d18125858 Mon Sep 17 00:00:00 2001 From: cronekorkn Date: Mon, 31 Jul 2023 18:41:52 +0200 Subject: [PATCH] apt conf in metadata --- bundles/apt/files/00disable-package-cache | 21 ---- bundles/apt/files/20auto-upgrades | 2 - bundles/apt/files/50unattended-upgrades | 3 - bundles/apt/items.py | 16 +-- bundles/apt/metadata.py | 116 +++++++++++++++++++--- libs/apt.py | 24 +++++ 6 files changed, 135 insertions(+), 47 deletions(-) delete mode 100644 bundles/apt/files/00disable-package-cache delete mode 100644 bundles/apt/files/20auto-upgrades delete mode 100644 bundles/apt/files/50unattended-upgrades diff --git a/bundles/apt/files/00disable-package-cache b/bundles/apt/files/00disable-package-cache deleted file mode 100644 index e1f351d..0000000 --- a/bundles/apt/files/00disable-package-cache +++ /dev/null @@ -1,21 +0,0 @@ -# ACHTUNG! -# KATASTROPHALER BUG IN APT! -# UNBEDINGT GENAU LESEN! -# -# Der offizielle Weg zum abschalten des Caches hat einen katastrophalen Bug, welcher in jedem Fall zum Verlust des -# gesamten Servers führt. Und zwar deaktivieren folgende Direktiven den Cache nicht, sondern legen ihn ins Root- -# Verzeichnis ("/"): -# -# Dir::Cache ""; -# Dir::Cache::archives ""; -# -# Führt man danach "apt clean" aus, wird des Cache-Verzeichnis gelöscht. Es wird also der gesamte Verzeichnisbaum -# gelöscht! -# -# siehe auch: -# https://askubuntu.com/questions/81179/how-to-prevent-apt-get-aptitude-keeping-a-cache -# https://superuser.com/questions/1405001/why-does-apt-do-not-store-downloaded-packages-anymore -# -# Als Alternative löschen wir also lieber alle "*.deb" im Standard-Cache-Verzeichnis: - -DPkg::Post-Invoke {"/bin/rm -f /var/cache/apt/archives/*.deb || true";}; diff --git a/bundles/apt/files/20auto-upgrades b/bundles/apt/files/20auto-upgrades deleted file mode 100644 index 8d6d7c8..0000000 --- a/bundles/apt/files/20auto-upgrades +++ /dev/null @@ -1,2 +0,0 @@ -APT::Periodic::Update-Package-Lists "1"; -APT::Periodic::Unattended-Upgrade "1"; diff --git a/bundles/apt/files/50unattended-upgrades b/bundles/apt/files/50unattended-upgrades deleted file mode 100644 index 16156c7..0000000 --- a/bundles/apt/files/50unattended-upgrades +++ /dev/null @@ -1,3 +0,0 @@ -Unattended-Upgrade::Origins-Pattern { - "origin=*"; -}; diff --git a/bundles/apt/items.py b/bundles/apt/items.py index 241c4b8..3a46369 100644 --- a/bundles/apt/items.py +++ b/bundles/apt/items.py @@ -12,6 +12,8 @@ directories = { }, }, '/etc/apt/apt.conf.d': { + # existance is expected + 'purge': True, 'triggers': { 'action:apt_update', }, @@ -44,11 +46,14 @@ directories = { } files = { - '/etc/apt/listchanges.conf.d/managed.conf': { - 'content': repo.libs.ini.dumps(node.metadata.get('apt/list_changes')), + '/etc/apt/apt.conf': { + 'content': repo.libs.apt.render_apt_conf(node.metadata.get('apt/config')), + 'triggers': { + 'action:apt_update', + }, }, - '/etc/apt/trusted.gpg.d': { - 'delete': True, + '/etc/apt/listchanges.conf': { + 'content': repo.libs.ini.dumps(node.metadata.get('apt/list_changes')), }, '/usr/lib/nagios/plugins/check_apt_upgradable': { 'mode': '0755', @@ -134,9 +139,6 @@ for package, options in node.metadata.get('apt/packages', {}).items(): # apt-daily.timer: performs apt update # apt-daily-upgrade.timer: performs apt upgrade -files['/etc/apt/apt.conf.d/00disable-package-cache'] = {} -files['/etc/apt/apt.conf.d/20auto-upgrades'] = {} -files['/etc/apt/apt.conf.d/50unattended-upgrades'] = {} svc_systemd['unattended-upgrades.service'] = { 'needs': [ 'pkg_apt:unattended-upgrades', diff --git a/bundles/apt/metadata.py b/bundles/apt/metadata.py index 8e44df4..dc3a0cd 100644 --- a/bundles/apt/metadata.py +++ b/bundles/apt/metadata.py @@ -1,21 +1,38 @@ defaults = { 'apt': { - 'packages': { - 'unattended-upgrades': {}, - }, - 'sources': set(), - 'list_changes': { - 'apt': { - 'frontend': 'pager', - 'which': 'news', - 'email_address': 'root', - 'email_format': 'text', - 'confirm': 'false', - 'headers': 'false', - 'reverse': 'false', - 'save_seen': '/var/lib/apt/listchanges.db', + 'config': { + 'DPkg': { + 'Pre-Install-Pkgs': { + '/usr/sbin/dpkg-preconfigure --apt || true', + }, + 'Post-Invoke': { + '/bin/rm -f /var/cache/apt/archives/*.deb || true', + }, + }, + 'APT': { + 'NeverAutoRemove': { + '^firmware-linux.*', + '^linux-firmware$', + '^linux-image-[a-z0-9]*$', + '^linux-image-[a-z0-9]*-[a-z0-9]*$', + }, + 'VersionedKernelPackages': { + # kernels + 'linux-.*', + 'kfreebsd-.*', + 'gnumach-.*', + # (out-of-tree) modules + '.*-modules', + '.*-kernel', + }, + 'Never-MarkAuto-Sections': { + 'metapackages', + 'tasks', + }, + 'Move-Autobit-Sections': 'oldlibs', }, }, + 'sources': set(), }, 'monitoring': { 'services': { @@ -35,3 +52,74 @@ defaults = { }, }, } + + +@metadata_reactor.provides( + 'apt/config', + 'apt/packages', +) +def unattended_upgrades(metadata): + return { + 'apt': { + 'config': { + 'APT': { + 'Periodic': { + 'Update-Package-Lists': '1', + 'Unattended-Upgrade': '1', + }, + }, + 'Unattended-Upgrade': { + 'Origins-Pattern': { + "origin=*", + }, + }, + }, + 'packages': { + 'unattended-upgrades': {}, + }, + }, + } + + +@metadata_reactor.provides( + 'apt/config', + 'apt/list_changes', +) +def listchanges(metadata): + return { + 'apt': { + 'config': { + 'DPkg': { + 'Pre-Install-Pkgs': { + '/usr/bin/apt-listchanges --apt || test $? -lt 10', + }, + }, + 'Tools': { + 'Options': { + '/usr/bin/apt-listchanges': { + 'Version': '2', + 'InfoFD': '20', + }, + }, + }, + 'Dir': { + 'Etc': { + 'apt-listchanges-main': 'listchanges.conf', + 'apt-listchanges-parts': 'listchanges.conf.d', + }, + }, + }, + 'list_changes': { + 'apt': { + 'frontend': 'pager', + 'which': 'news', + 'email_address': 'root', + 'email_format': 'text', + 'confirm': 'false', + 'headers': 'false', + 'reverse': 'false', + 'save_seen': '/var/lib/apt/listchanges.db', + }, + }, + }, + } diff --git a/libs/apt.py b/libs/apt.py index b10a094..8af983a 100644 --- a/libs/apt.py +++ b/libs/apt.py @@ -3,6 +3,30 @@ from urllib.parse import urlparse from re import search, sub from functools import total_ordering +from re import match + + +def render_apt_conf(section, depth=0): + buffer = "" + + for k,v in sorted(section.items()): + if isinstance(v, dict): + # element is a sub section + assert match(r'^[a-zA-Z/\-\:\.\_\+]*$', k) and not match(r'::', k) + buffer += ' '*4*depth + k + ' {\n' + buffer += render_apt_conf(v, depth=depth+1) + buffer += ' '*4*depth + '}\n' + elif isinstance(v, (set, list)): + # element is a value list + buffer += ' '*4*depth + k + ' {\n' + for e in sorted(v): + buffer += ' '*4*(depth+1) + '"' + e + '";\n' + buffer += ' '*4*depth + '}\n' + else: + # element is a single value + buffer += ' '*4*depth + k + ' "' + v + '";\n' + + return buffer @total_ordering