diff --git a/.github/scripts/tests/test_oci_pve_version_gate.py b/.github/scripts/tests/test_oci_pve_version_gate.py index 80703fd6..b012197e 100644 --- a/.github/scripts/tests/test_oci_pve_version_gate.py +++ b/.github/scripts/tests/test_oci_pve_version_gate.py @@ -14,15 +14,16 @@ class OciPveVersionGateTests(unittest.TestCase): @classmethod def setUpClass(cls): text = LAUNCHER.read_text(encoding='utf-8') - cls.function = re.search(r'^pve_supports_oci\(\) \{\n.*?^\}\n', text, re.M | re.S).group(0) + cls.function = ''.join(re.search(rf'^{name}\(\) \{{\n.*?^\}}\n', text, re.M | re.S).group(0) + for name in ('pve_manager_version', 'pve_supports_oci')) cls.text = text def supported(self, version): with tempfile.TemporaryDirectory() as folder: - fake = Path(folder, 'pveversion') - # Without Proxmox the command is missing: a stand-in that fails hides the host's own. - fake.write_text('#!/bin/sh\nexit 127\n' if version is None else - f'#!/bin/sh\necho "pve-manager/{version}/b9984c6d90a4bd80 (running kernel: 6.17)"\n') + fake = Path(folder, 'dpkg-query') + # Without Proxmox the package is not installed: dpkg-query fails. + fake.write_text('#!/bin/sh\nexit 1\n' if version is None else + f'#!/bin/sh\nprintf %s "{version}"\n') fake.chmod(0o755) result = subprocess.run(['bash', '-c', f'PATH={folder}:/usr/bin:/bin\n{self.function}pve_supports_oci'], capture_output=True, text=True) @@ -38,6 +39,9 @@ class OciPveVersionGateTests(unittest.TestCase): with self.subTest(version=version): self.assertFalse(self.supported(version)) + def test_the_version_is_read_without_the_slow_pveversion(self): + self.assertNotIn('pveversion', self.function) + def test_it_is_checked_before_anything_is_installed(self): self.assertLess(self.text.index('if ! pve_supports_oci; then'), self.text.index('ensure_oci_dependencies || exit 1')) diff --git a/scripts/oci/oci_manager_apps.sh b/scripts/oci/oci_manager_apps.sh index 67546cb9..6e6b2143 100755 --- a/scripts/oci/oci_manager_apps.sh +++ b/scripts/oci/oci_manager_apps.sh @@ -32,8 +32,11 @@ initialize_cache ensure_oci_dependencies() { local -a missing=() - python3 -c 'import yaml' >/dev/null 2>&1 || missing+=("python3-yaml") - python3 -c 'import jsonschema' >/dev/null 2>&1 || missing+=("python3-jsonschema") + # One Python start when both are present; each is checked only if not. + if ! python3 -c 'import yaml, jsonschema' >/dev/null 2>&1; then + python3 -c 'import yaml' >/dev/null 2>&1 || missing+=("python3-yaml") + python3 -c 'import jsonschema' >/dev/null 2>&1 || missing+=("python3-jsonschema") + fi command -v skopeo >/dev/null 2>&1 || missing+=("skopeo") [[ ${#missing[@]} -eq 0 ]] && return 0 @@ -57,12 +60,15 @@ ensure_oci_dependencies() { stop_spinner } -# Proxmox VE runs OCI images as LXC containers from 9.1 on. +# Proxmox VE runs OCI images as LXC containers from 9.1 on. The package +# database answers at once; pveversion takes about half a second. +pve_manager_version() { + dpkg-query -W -f='${Version}' pve-manager 2>/dev/null | grep -oE '^[0-9]+(\.[0-9]+)+' | head -1 +} + pve_supports_oci() { - local version major minor - version=$(pveversion 2>/dev/null | grep -oP 'pve-manager/\K[0-9]+\.[0-9]+' | head -1) - major=${version%%.*} - minor=${version#*.} + local major minor + IFS=. read -r major minor _ <<< "$(pve_manager_version)" [[ $major =~ ^[0-9]+$ && $minor =~ ^[0-9]+$ ]] || return 1 (( major > 9 || (major == 9 && minor >= 1) )) } @@ -71,7 +77,7 @@ if ! pve_supports_oci; then show_proxmenux_logo msg_title "$(translate "OCI manager Apps (Technology Preview)")" msg_error "$(translate "OCI containers require Proxmox VE 9.1 or later.")" - PVE_VERSION=$(pveversion 2>/dev/null | grep -oP 'pve-manager/\K[0-9.]+' | head -1) + PVE_VERSION=$(pve_manager_version) [[ -n $PVE_VERSION ]] && msg_info2 "$(translate "Current version:") $PVE_VERSION" if [[ -t 0 ]]; then echo