From 2e65441bb70b9a3e95c2b7fa1c156177e8024f95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Tosser?= Date: Fri, 11 Apr 2025 23:42:37 +0400 Subject: [PATCH] refactor: enhance DebPackages and DebPackage facts to include detailed package information - Updated the DebPackages class to return a structured dictionary for each package, including desired action, status, version, architecture, and description. - Modified the regex pattern to capture additional package details. - Adjusted related test cases to reflect the new data structure for package facts. --- pyinfra/facts/deb.py | 58 ++++++++++++++++--- tests/facts/deb.DebPackage/whitespace.json | 4 +- .../facts/deb.DebPackages/hold_packages.json | 24 +++++++- tests/facts/deb.DebPackages/packages.json | 40 +++++++++++-- 4 files changed, 109 insertions(+), 17 deletions(-) diff --git a/pyinfra/facts/deb.py b/pyinfra/facts/deb.py index c01961d99..5bb4958d4 100644 --- a/pyinfra/facts/deb.py +++ b/pyinfra/facts/deb.py @@ -7,8 +7,6 @@ from pyinfra.api import FactBase -from .util.packaging import parse_packages - DEB_PACKAGE_NAME_REGEX = r"[a-zA-Z0-9\+\-\.]+" DEB_PACKAGE_VERSION_REGEX = r"[a-zA-Z0-9:~\.\-\+]+" @@ -34,7 +32,13 @@ class DebPackages(FactBase): .. code:: python { - "package_name": ["version"], + "package_name": { + "desired": "Install", + "status": "Installed", + "version": "version", + "architecture": "architecture", + "description": "description", + } } """ @@ -48,14 +52,49 @@ def requires_command(self) -> str: default = dict - regex = r"^[i|h]i\s+({0}):?[a-zA-Z0-9]*\s+({1}).+$".format( - DEB_PACKAGE_NAME_REGEX, - DEB_PACKAGE_VERSION_REGEX, - ) + regex = r"^([uirph]{1})([nicuhwt]{1})\s+([\w\-\.]+)\s+([\w\-\+\.:~]+)\s+(\w+)\s+(.+)$" @override def process(self, output): - return parse_packages(self.regex, output) + packages = {} + + # Mapping of single-letter codes to their full meanings + desired_map = { + "u": "Unknown", + "i": "Install", + "r": "Remove", + "p": "Purge", + "h": "Hold", + } + + status_map = { + "n": "Not-installed", + "i": "Installed", + "c": "Config-files", + "u": "Unpacked", + "h": "Half-installed", + "w": "Trigger-awaited", + "t": "Trigger-pending", + } + + for line in output: + matches = re.match(self.regex, line) + if matches: + desired_code = matches.group(1) # Desired action (u,i,r,p,h) + status_code = matches.group(2) # Current status (n,i,c,u,h,w,t) + name = matches.group(3) # Package name + version = matches.group(4) # Version + arch = matches.group(5) # Architecture + description = matches.group(6).strip() # Description + + packages[name] = { + "desired": desired_map.get(desired_code, "Unknown"), + "status": status_map.get(status_code, "Unknown"), + "version": version, + "architecture": arch, + "description": description, + } + return packages class DebPackage(FactBase): @@ -66,6 +105,9 @@ class DebPackage(FactBase): _regexes = { "name": r"^Package:\s+({0})$".format(DEB_PACKAGE_NAME_REGEX), "version": r"^Version:\s+({0})$".format(DEB_PACKAGE_VERSION_REGEX), + "architecture": r"^Architecture:\s+(.*)$", + "description": r"^Description:\s+(.*)$", + "status": r"^Status:\s+(.*)$", } @override diff --git a/tests/facts/deb.DebPackage/whitespace.json b/tests/facts/deb.DebPackage/whitespace.json index e0456e838..51a757a2d 100644 --- a/tests/facts/deb.DebPackage/whitespace.json +++ b/tests/facts/deb.DebPackage/whitespace.json @@ -24,7 +24,9 @@ " gskssl64 (>= 8.0-55.31)" ], "fact": { + "version": "8.1.21-0", "name": "tivsm-api64", - "version": "8.1.21-0" + "architecture": "amd64", + "description": "This is the IBM Storage Protect Linux API" } } diff --git a/tests/facts/deb.DebPackages/hold_packages.json b/tests/facts/deb.DebPackages/hold_packages.json index 7d521af38..dbfbfa92a 100644 --- a/tests/facts/deb.DebPackages/hold_packages.json +++ b/tests/facts/deb.DebPackages/hold_packages.json @@ -7,8 +7,26 @@ "hi wireguard 1.0.20200513-1~18.04.2 all fast, modern, secure kernel VPN tunnel (metapackage)" ], "fact": { - "matrix-synapse-py3": ["1.37.1+bionic1"], - "miniflux": ["2.0.31"], - "wireguard": ["1.0.20200513-1~18.04.2"] + "matrix-synapse-py3": { + "desired": "Hold", + "status": "Installed", + "version": "1.37.1+bionic1", + "architecture": "amd64", + "description": "Open federated Instant Messaging and VoIP server" + }, + "miniflux": { + "desired": "Hold", + "status": "Installed", + "version": "2.0.31", + "architecture": "amd64", + "description": "Minimalist Feed Reader" + }, + "wireguard": { + "desired": "Hold", + "status": "Installed", + "version": "1.0.20200513-1~18.04.2", + "architecture": "all", + "description": "fast, modern, secure kernel VPN tunnel (metapackage)" + } } } diff --git a/tests/facts/deb.DebPackages/packages.json b/tests/facts/deb.DebPackages/packages.json index 96711ddb1..05cbd359f 100644 --- a/tests/facts/deb.DebPackages/packages.json +++ b/tests/facts/deb.DebPackages/packages.json @@ -9,10 +9,40 @@ "ii x11-xkb-utils 7.7+1 amd64 X11 XKB utilitie" ], "fact": { - "w3m": ["0.5.3-15"], - "wget": ["1.15-1ubuntu1.14.04."], - "whiptail": ["0.52.15-2ubuntu5"], - "x11-common": ["1:7.7+1ubuntu8.1"], - "x11-xkb-utils": ["7.7+1"] + "w3m": { + "desired": "Install", + "status": "Installed", + "version": "0.5.3-15", + "architecture": "amd64", + "description": "WWW browsable pager with excellent tables/frames support" + }, + "wget": { + "desired": "Install", + "status": "Installed", + "version": "1.15-1ubuntu1.14.04.", + "architecture": "amd64", + "description": "retrieves files from the web" + }, + "whiptail": { + "desired": "Install", + "status": "Installed", + "version": "0.52.15-2ubuntu5", + "architecture": "amd64", + "description": "Displays user-friendly dialog oxes from shell scripts" + }, + "x11-common": { + "desired": "Install", + "status": "Installed", + "version": "1:7.7+1ubuntu8.1", + "architecture": "all", + "description": "X Window System (X.Org) infrastructure" + }, + "x11-xkb-utils": { + "desired": "Install", + "status": "Installed", + "version": "7.7+1", + "architecture": "amd64", + "description": "X11 XKB utilitie" + } } }