Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revive fine master #68

Merged
merged 3 commits into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 81 additions & 1 deletion pleskdistup/actions/distupgrade.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
# Copyright 2023-2024. WebPros International GmbH. All rights reserved.
import os
import subprocess
import typing
import urllib.request
import xml.etree.ElementTree as ElementTree

from pleskdistup.common import action, dpkg, files, log, packages, util
from pleskdistup.common import action, dist, dpkg, files, log, packages, plesk, util


class InstallUbuntuUpdateManager(action.ActiveAction):
Expand Down Expand Up @@ -65,6 +68,83 @@ def estimate_revert_time(self) -> int:
return 0


class UpdateLegacyPhpRepositories(action.ActiveAction):
legacy_php_versions_inf3_urls: typing.List[str]
from_os: dist.Distro
to_os: dist.Distro
sources_list_d_path: str

def __init__(
self,
from_os: dist.Distro,
to_os: dist.Distro,
sources_list_d_path: str = "/etc/apt/sources.list.d/",
):
self.name = "update legacy PHP repositories"
self.legacy_php_versions_inf3_urls = [
"https://autoinstall.plesk.com/php{}.inf3".format(version) for version in [71, 72, 73]
]
self.from_os = from_os
self.to_os = to_os
self.sources_list_d_path = sources_list_d_path

def _retrieve_php_version_repositories_mapping(self, url: str, from_os: dist.Distro, to_os: dist.Distro) -> typing.Dict[str, str]:
try:
response = urllib.request.urlopen(url)
xml_content = response.read().decode('utf-8')
log.debug(f"Retrieved PHP version repositories mapping from {url!r}. Content: {xml_content}")
root = ElementTree.fromstring(xml_content)

to_repo = plesk.get_repository_by_os_from_inf3(root, to_os)
from_repo = plesk.get_repository_by_os_from_inf3(root, from_os)
if to_repo and from_repo:
return {from_repo: to_repo}
except urllib.error.URLError as ex:
log.warn(f"Unable to download {url!r}: {ex}")
except ElementTree.ParseError as ex:
log.warn(f"Unable to parse inf3 file from {url!r}: {ex}")
except Exception as ex:
log.warn(f"Unable to retrieve PHP version repositories mapping from {url!r}: {ex}")

return {}

def _prepare_action(self) -> action.ActionResult:
mappings = {}
for url in self.legacy_php_versions_inf3_urls:
mappings.update(self._retrieve_php_version_repositories_mapping(url, self.from_os, self.to_os))

for list_file in files.find_files_case_insensitive(self.sources_list_d_path, "*.list", True):
if not files.backup_exists(list_file):
files.backup_file(list_file)

for from_repo, target_repo in mappings.items():
log.debug(f"Replacing {from_repo!r} with {target_repo!r} in {list_file!r}")
files.replace_string(list_file, from_repo, target_repo)

return action.ActionResult()

def _post_action(self) -> action.ActionResult:
# Source lists backups are not relevant after the upgrade, so we can remove them from any
# action that uses them.
for list_file in files.find_files_case_insensitive(self.sources_list_d_path, "*.list", True):
files.remove_backup(list_file)

return action.ActionResult()

def _revert_action(self) -> action.ActionResult:
for list_file in files.find_files_case_insensitive(self.sources_list_d_path, "*.list", True):
files.restore_file_from_backup(list_file)

packages.update_package_list()
return action.ActionResult()

def estimate_prepare_time(self) -> int:
return 20

def estimate_revert_time(self) -> int:
return 20


class SetupAptRepositories(action.ActiveAction):
from_codename: str
to_codename: str
Expand Down
4 changes: 4 additions & 0 deletions pleskdistup/common/src/files.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ def backup_file(filename: str) -> None:
shutil.copy(filename, filename + ".bak")


def backup_exists(filename: str) -> bool:
return os.path.exists(filename + ".bak")


def restore_file_from_backup(filename: str, remove_if_no_backup: bool = False) -> None:
if os.path.exists(filename + ".bak"):
shutil.move(filename + ".bak", filename)
Expand Down
22 changes: 21 additions & 1 deletion pleskdistup/common/src/plesk.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import urllib.request
import xml.etree.ElementTree as ElementTree

from . import log, mariadb, systemd, version, util
from . import dist, log, mariadb, systemd, version, util

# http://autoinstall.plesk.com/products.inf3 is an xml file with available products,
# including all versions of Plesk.
Expand Down Expand Up @@ -237,3 +237,23 @@ def get_from_plesk_database(query: str) -> typing.Optional[typing.List[str]]:
)
log.debug(f"Command {cmd} returned {proc.returncode}, stdout: '{proc.stdout}', stderr: '{proc.stderr}'")
return proc.stdout.splitlines()


def get_repository_by_os_from_inf3(inf3_content: typing.Union[ElementTree.Element, str], os: dist.Distro) -> typing.Optional[str]:
if isinstance(inf3_content, str):
if not inf3_content:
return None
inf3_content = ElementTree.fromstring(inf3_content)

for build in inf3_content.findall(".//build"):
entry_os_vendor = build.get("os_vendor")
entry_os_version = build.get("os_version")
if not entry_os_vendor or not entry_os_version:
continue

if entry_os_vendor == os.name and entry_os_version.split('.')[0] == os.version:
entry_config_attr = build.get("config")
if entry_config_attr:
return entry_config_attr.rsplit("/", 1)[0]
return None
return None
42 changes: 41 additions & 1 deletion pleskdistup/common/tests/plesktests.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Copyright 2023-2024. WebPros International GmbH. All rights reserved.
import unittest

from src import plesk, version
from src import dist, plesk, version


class TestProductsFileParser(unittest.TestCase):
Expand Down Expand Up @@ -88,3 +88,43 @@ def test_only_plesk_without_release_key(self):
"""

self.assertEqual([], plesk.extract_plesk_versions(data))


class TestGetRepositoryByOsFromInf3(unittest.TestCase):
DEFAULT_TEST_DATA = """
<addon id="php73" name="PHP v 7.3">
<release id="PHP_7_3" name="PHP v 7.3" version="7.3.33">
<compatibility_info>
<compatible product_id="plesk" from_version="17.8.11" to_version="18.0.99"/>
</compatibility_info>
<build os_name="Linux" os_vendor="Debian" os_version="11.0" os_arch="x86_64" config="pool/PHP_7.3.33_13/php73-deb11.0-x86_64.inf3"/>
<build os_name="Linux" os_vendor="Ubuntu" os_version="22.04" os_arch="x86_64" config="pool/PHP_7.3.33_13/php73-ubt22.04-x86_64.inf3"/>
</release>
<release id="PHP73_17" name="PHP v 7.3" version="7.3">
<compatibility_info>
<compatible product_id="plesk" from_version="17.8.11" to_version="18.0.99"/>
</compatibility_info>
<build os_name="Linux" os_vendor="AlmaLinux" os_version="8" os_arch="x86_64" config="pool/PHP_7.3.33_248/php73-cos8-x86_64.inf3"/>
<build os_name="Linux" os_vendor="CentOS" os_version="7" os_arch="x86_64" config="pool/PHP_7.3.33_248/php73-cos7-x86_64.inf3"/>
<build os_name="Linux" os_vendor="CentOS" os_version="8" os_arch="x86_64" config="pool/PHP_7.3.33_248/php73-cos8-x86_64.inf3"/>
<build os_name="Linux" os_vendor="Ubuntu" os_version="20.04" os_arch="x86_64" config="pool/PHP_7.3.33_248/php73-ubt20.04-x86_64.inf3"/>
</release>
</addon>
"""

def test_first_release_parsing(self):
self.assertEqual("pool/PHP_7.3.33_13", plesk.get_repository_by_os_from_inf3(self.DEFAULT_TEST_DATA, dist.Ubuntu("22")))

def test_second_release_parsing(self):
self.assertEqual("pool/PHP_7.3.33_248", plesk.get_repository_by_os_from_inf3(self.DEFAULT_TEST_DATA, dist.Ubuntu("20")))

def test_first_release_from_xml_object(self):
import xml.etree.ElementTree as ElementTree
root = ElementTree.fromstring(self.DEFAULT_TEST_DATA)
self.assertEqual("pool/PHP_7.3.33_13", plesk.get_repository_by_os_from_inf3(root, dist.Ubuntu("22")))

def test_no_such_release(self):
self.assertEqual(None, plesk.get_repository_by_os_from_inf3(self.DEFAULT_TEST_DATA, dist.Ubuntu("21")))

def test_empty_xml(self):
self.assertEqual(None, plesk.get_repository_by_os_from_inf3("", dist.Ubuntu("22")))
Loading