From 62a64922c93ff1d48cfda879e2bfb316523d2b54 Mon Sep 17 00:00:00 2001 From: Rodolfo Olivieri Date: Thu, 25 May 2023 13:37:16 -0300 Subject: [PATCH] [RHELC-899] Prevent packages marked for update to reinstall (#833) * Prevent packages marked for update to reinstall During our transaction handler, some packages were trying to be reinstalled/downgraded on the system without necessity, as they were already marked for update. This patch prevents those packages marked for update to be reinstalled or downgraded in further cases. Signed-off-by: Rodolfo Olivieri * Add integration tests Signed-off-by: Rodolfo Olivieri * Modify the test * change the test to be able to install tracked packages Signed-off-by: Daniel Diblik * Try yum check-update * try yum check update to verify if package lands on latest version * add list of packages relevant for Oracle Linux 7 Signed-off-by: Daniel Diblik * Override releasever for CentOS 8.5 * we need to point the yum check-update to the correct minor Signed-off-by: Daniel Diblik * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Signed-off-by: Rodolfo Olivieri Signed-off-by: Daniel Diblik Co-authored-by: Daniel Diblik Co-authored-by: Daniel Diblik <8378124+danmyway@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .../pkgmanager/handlers/dnf/__init__.py | 15 +- .../pkgmanager/handlers/yum/__init__.py | 10 +- .../pkgmanager/handlers/dnf/dnf_test.py | 247 +++++++----------- .../pkgmanager/handlers/yum/yum_test.py | 243 ++++++----------- plans/tier1.fmf | 11 + pytest.ini | 1 + .../tier1/single-yum-transaction/main.fmf | 8 +- .../test_check_for_latest_packages.py | 62 +++++ .../tier1/system-up-to-date/main.fmf | 1 - 9 files changed, 274 insertions(+), 324 deletions(-) create mode 100644 tests/integration/tier1/single-yum-transaction/test_check_for_latest_packages.py diff --git a/convert2rhel/pkgmanager/handlers/dnf/__init__.py b/convert2rhel/pkgmanager/handlers/dnf/__init__.py index cab2a39f0..88ce37b4c 100644 --- a/convert2rhel/pkgmanager/handlers/dnf/__init__.py +++ b/convert2rhel/pkgmanager/handlers/dnf/__init__.py @@ -113,11 +113,24 @@ def _perform_operations(self): `PackagesNotAvailableError`. """ original_os_pkgs = get_system_packages_for_replacement() + upgrades = self._base.sack.query().upgrades().latest() loggerinst.info("Adding %s packages to the dnf transaction set.", system_info.name) for pkg in original_os_pkgs: - self._base.upgrade(pkg_spec=pkg) + # Splitting the name and arch so we can filter it out in the list + # of packages to upgrade. + name, arch = tuple(pkg.rsplit(".")) + upgrade_pkg = next(iter(upgrades.filter(name=name, arch=arch)), None) + + # If a package is marked for update, then we don't need to + # proceed with reinstall, and possibly, the downgrade of this + # package. This is an inconsistency that could lead to packages + # being outdated in the system after the conversion. + if upgrade_pkg: + self._base.upgrade(pkg_spec=pkg) + continue + try: self._base.reinstall(pkg_spec=pkg) except pkgmanager.exceptions.PackagesNotAvailableError: diff --git a/convert2rhel/pkgmanager/handlers/yum/__init__.py b/convert2rhel/pkgmanager/handlers/yum/__init__.py index 82c8ebf7a..82eab2dcd 100644 --- a/convert2rhel/pkgmanager/handlers/yum/__init__.py +++ b/convert2rhel/pkgmanager/handlers/yum/__init__.py @@ -173,7 +173,15 @@ def _perform_operations(self): try: for pkg in original_os_pkgs: - self._base.update(pattern=pkg) + can_update = self._base.update(pattern=pkg) + + # If a package is marked for update, then we don't need to + # proceed with reinstall, and possibly, the downgrade of this + # package. This is an inconsistency that could lead to packages + # being outdated in the system after the conversion. + if can_update: + continue + try: self._base.reinstall(pattern=pkg) except (pkgmanager.Errors.ReinstallInstallError, pkgmanager.Errors.ReinstallRemoveError): diff --git a/convert2rhel/unit_tests/pkgmanager/handlers/dnf/dnf_test.py b/convert2rhel/unit_tests/pkgmanager/handlers/dnf/dnf_test.py index 252bf9812..c3565d6aa 100644 --- a/convert2rhel/unit_tests/pkgmanager/handlers/dnf/dnf_test.py +++ b/convert2rhel/unit_tests/pkgmanager/handlers/dnf/dnf_test.py @@ -14,11 +14,10 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - import pytest import six -from convert2rhel import pkgmanager +from convert2rhel import pkghandler, pkgmanager from convert2rhel.pkgmanager.handlers.dnf import DnfTransactionHandler from convert2rhel.pkgmanager.handlers.dnf.callback import DependencySolverProgressIndicatorCallback from convert2rhel.systeminfo import system_info @@ -45,6 +44,66 @@ def enable(self): self.disabled = False +class SackMock: + def __init__(self, packages=None): + if not packages: + packages = [] + + self.packages = packages + + def __call__(self, *args, **kwds): + return self + + def query(self): + return self + + def upgrades(self): + return self + + def latest(self): + return self + + def filter(self, *args, **kwargs): + return self.packages + + +SYSTEM_PACKAGES = [ + create_pkg_information( + packager="test", + vendor="test", + name="pkg-1", + epoch="0", + version="1.0.0", + release="1", + arch="x86_64", + fingerprint="05b555b38483c65d", + signature="test", + ), + create_pkg_information( + packager="test", + vendor="test", + name="pkg-2", + epoch="0", + version="1.0.0", + release="1", + arch="x86_64", + fingerprint="05b555b38483c65d", + signature="test", + ), + create_pkg_information( + packager="test", + vendor="test", + name="pkg-3", + epoch="0", + version="1.0.0", + release="1", + arch="x86_64", + fingerprint="05b555b38483c65d", + signature="test", + ), +] + + @pytest.mark.skipif( pkgmanager.TYPE != "dnf", reason="No dnf module detected on the system, skipping it.", @@ -63,6 +122,7 @@ def _mock_dnf_api_calls(self, monkeypatch): monkeypatch.setattr(pkgmanager.Base, "download_packages", value=mock.Mock()) monkeypatch.setattr(pkgmanager.Base, "do_transaction", value=mock.Mock()) monkeypatch.setattr(pkgmanager.Base, "transaction", value=mock.Mock()) + monkeypatch.setattr(pkgmanager.Base, "sack", value=SackMock()) @centos8 def test_set_up_base(self, pretend_os): @@ -154,172 +214,59 @@ def test_enable_repos_repo_error_exception( assert "Failed to populate repository metadata." in caplog.records[-1].message @centos8 - @pytest.mark.parametrize( - ("system_packages"), - ( - ( - [ - create_pkg_information( - packager="test", - vendor="test", - name="pkg-1", - epoch="0", - version="1.0.0", - release="1", - arch="x86_64", - fingerprint="test", - signature="test", - ), - create_pkg_information( - packager="test", - vendor="test", - name="pkg-2", - epoch="0", - version="1.0.0", - release="1", - arch="x86_64", - fingerprint="test", - signature="test", - ), - create_pkg_information( - packager="test", - vendor="test", - name="pkg-3", - epoch="0", - version="1.0.0", - release="1", - arch="x86_64", - fingerprint="test", - signature="test", - ), - ] - ), - ), - ) - def test_perform_operations(self, pretend_os, system_packages, _mock_dnf_api_calls, caplog, monkeypatch): + def test_perform_operations(self, pretend_os, _mock_dnf_api_calls, caplog, monkeypatch): monkeypatch.setattr( - pkgmanager.handlers.dnf, - "get_system_packages_for_replacement", - value=lambda: system_packages, + pkghandler, + "get_installed_pkg_information", + value=lambda: SYSTEM_PACKAGES, ) instance = DnfTransactionHandler() instance._set_up_base() instance._perform_operations() - assert pkgmanager.Base.upgrade.call_count == len(system_packages) - assert pkgmanager.Base.reinstall.call_count == len(system_packages) + assert pkgmanager.Base.reinstall.call_count == len(SYSTEM_PACKAGES) assert pkgmanager.Base.downgrade.call_count == 0 @centos8 - @pytest.mark.parametrize( - ("system_packages"), - ( - ( - [ - create_pkg_information( - packager="test", - vendor="test", - name="pkg-1", - epoch="0", - version="1.0.0", - release="1", - arch="x86_64", - fingerprint="test", - signature="test", - ), - create_pkg_information( - packager="test", - vendor="test", - name="pkg-2", - epoch="0", - version="1.0.0", - release="1", - arch="x86_64", - fingerprint="test", - signature="test", - ), - create_pkg_information( - packager="test", - vendor="test", - name="pkg-3", - epoch="0", - version="1.0.0", - release="1", - arch="x86_64", - fingerprint="test", - signature="test", - ), - ] - ), - ), - ) - def test_perform_operations_reinstall_exception( - self, pretend_os, system_packages, _mock_dnf_api_calls, caplog, monkeypatch - ): + def test_package_marked_for_update(self, pretend_os, _mock_dnf_api_calls, monkeypatch): + """ + Test that if a package is marked for update, we won't call reinstall or + downgrade after that. + + This comes from: https://issues.redhat.com/browse/RHELC-899 + """ + monkeypatch.setattr(pkghandler, "get_installed_pkg_information", value=lambda: SYSTEM_PACKAGES) + monkeypatch.setattr(pkgmanager.Base, "sack", value=SackMock(packages=SYSTEM_PACKAGES)) + instance = DnfTransactionHandler() + instance._set_up_base() + instance._perform_operations() + + assert pkgmanager.Base.upgrade.call_count == len(SYSTEM_PACKAGES) + assert pkgmanager.Base.reinstall.call_count == 0 + assert pkgmanager.Base.downgrade.call_count == 0 + + @centos8 + def test_perform_operations_reinstall_exception(self, pretend_os, _mock_dnf_api_calls, caplog, monkeypatch): monkeypatch.setattr( - pkgmanager.handlers.dnf, - "get_system_packages_for_replacement", - value=lambda: system_packages, + pkghandler, + "get_installed_pkg_information", + value=lambda: SYSTEM_PACKAGES, ) pkgmanager.Base.reinstall.side_effect = pkgmanager.exceptions.PackagesNotAvailableError instance = DnfTransactionHandler() instance._set_up_base() instance._perform_operations() - assert pkgmanager.Base.reinstall.call_count == len(system_packages) - assert pkgmanager.Base.downgrade.call_count == len(system_packages) + assert pkgmanager.Base.reinstall.call_count == len(SYSTEM_PACKAGES) + assert pkgmanager.Base.downgrade.call_count == len(SYSTEM_PACKAGES) assert "not available in RHEL repositories" not in caplog.records[-1].message @centos8 - @pytest.mark.parametrize( - ("system_packages"), - ( - ( - [ - create_pkg_information( - packager="test", - vendor="test", - name="pkg-1", - epoch="0", - version="1.0.0", - release="1", - arch="x86_64", - fingerprint="test", - signature="test", - ), - create_pkg_information( - packager="test", - vendor="test", - name="pkg-2", - epoch="0", - version="1.0.0", - release="1", - arch="x86_64", - fingerprint="test", - signature="test", - ), - create_pkg_information( - packager="test", - vendor="test", - name="pkg-3", - epoch="0", - version="1.0.0", - release="1", - arch="x86_64", - fingerprint="test", - signature="test", - ), - ] - ), - ), - ) - def test_perform_operations_downgrade_exception( - self, pretend_os, system_packages, _mock_dnf_api_calls, caplog, monkeypatch - ): + def test_perform_operations_downgrade_exception(self, pretend_os, _mock_dnf_api_calls, caplog, monkeypatch): monkeypatch.setattr( - pkgmanager.handlers.dnf, - "get_system_packages_for_replacement", - value=lambda: system_packages, + pkghandler, + "get_installed_pkg_information", + value=lambda: SYSTEM_PACKAGES, ) pkgmanager.Base.reinstall.side_effect = pkgmanager.exceptions.PackagesNotAvailableError pkgmanager.Base.downgrade.side_effect = pkgmanager.exceptions.PackagesNotInstalledError @@ -328,8 +275,8 @@ def test_perform_operations_downgrade_exception( instance._set_up_base() instance._perform_operations() - assert pkgmanager.Base.reinstall.call_count == len(system_packages) - assert pkgmanager.Base.downgrade.call_count == len(system_packages) + assert pkgmanager.Base.reinstall.call_count == len(SYSTEM_PACKAGES) + assert pkgmanager.Base.downgrade.call_count == len(SYSTEM_PACKAGES) assert "not available in RHEL repositories" in caplog.records[-1].message @centos8 diff --git a/convert2rhel/unit_tests/pkgmanager/handlers/yum/yum_test.py b/convert2rhel/unit_tests/pkgmanager/handlers/yum/yum_test.py index 4fca3facb..3902c8370 100644 --- a/convert2rhel/unit_tests/pkgmanager/handlers/yum/yum_test.py +++ b/convert2rhel/unit_tests/pkgmanager/handlers/yum/yum_test.py @@ -14,9 +14,6 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . - -import functools - import six @@ -30,7 +27,7 @@ six.add_move(six.MovedModule("mock", "mock", "unittest.mock")) from six.moves import mock -from convert2rhel import pkgmanager, unit_tests, utils +from convert2rhel import pkghandler, pkgmanager, unit_tests, utils from convert2rhel.pkgmanager.handlers.yum import YumTransactionHandler from convert2rhel.systeminfo import system_info from convert2rhel.unit_tests import create_pkg_information, mock_decorator @@ -50,6 +47,43 @@ def __call__(self, *args, **kwargs): return False +SYSTEM_PACKAGES = [ + create_pkg_information( + packager="test", + vendor="test", + name="pkg-1", + epoch="0", + version="1.0.0", + release="1", + arch="x86_64", + fingerprint="24c6a8a7f4a80eb5", + signature="test", + ), + create_pkg_information( + packager="test", + vendor="test", + name="pkg-2", + epoch="0", + version="1.0.0", + release="1", + arch="x86_64", + fingerprint="24c6a8a7f4a80eb5", + signature="test", + ), + create_pkg_information( + packager="test", + vendor="test", + name="pkg-3", + epoch="0", + version="1.0.0", + release="1", + arch="x86_64", + fingerprint="24c6a8a7f4a80eb5", + signature="test", + ), +] + + @pytest.mark.skipif( pkgmanager.TYPE != "yum", reason="No yum module detected on the system, skipping it.", @@ -60,7 +94,7 @@ def _mock_yum_api_calls(self, monkeypatch): """ """ monkeypatch.setattr(pkgmanager.RepoStorage, "enableRepo", value=mock.Mock()) monkeypatch.setattr(pkgmanager.RepoStorage, "disableRepo", value=mock.Mock()) - monkeypatch.setattr(pkgmanager.YumBase, "update", value=mock.Mock()) + monkeypatch.setattr(pkgmanager.YumBase, "update", value=mock.Mock(return_value=[])) monkeypatch.setattr(pkgmanager.YumBase, "reinstall", value=mock.Mock()) monkeypatch.setattr(pkgmanager.YumBase, "downgrade", value=mock.Mock()) monkeypatch.setattr(pkgmanager.YumBase, "resolveDeps", value=mock.Mock(return_value=(0, "Success."))) @@ -101,187 +135,44 @@ def test_enable_repos_repo_error(self, pretend_os, enabled_rhel_repos, _mock_yum assert pkgmanager.RepoStorage.disableRepo.called_once() @centos7 - @pytest.mark.parametrize( - ("system_packages"), - ( - ( - [ - create_pkg_information( - packager="test", - vendor="test", - name="pkg-1", - epoch="0", - version="1.0.0", - release="1", - arch="x86_64", - fingerprint="test", - signature="test", - ), - create_pkg_information( - packager="test", - vendor="test", - name="pkg-2", - epoch="0", - version="1.0.0", - release="1", - arch="x86_64", - fingerprint="test", - signature="test", - ), - create_pkg_information( - packager="test", - vendor="test", - name="pkg-3", - epoch="0", - version="1.0.0", - release="1", - arch="x86_64", - fingerprint="test", - signature="test", - ), - ], - ) - ), - ) - def test_perform_operations(self, pretend_os, system_packages, _mock_yum_api_calls, caplog, monkeypatch): - monkeypatch.setattr(pkgmanager.handlers.yum, "get_system_packages_for_replacement", lambda: system_packages) + def test_perform_operations(self, pretend_os, _mock_yum_api_calls, caplog, monkeypatch): + monkeypatch.setattr(pkghandler, "get_installed_pkg_information", lambda: SYSTEM_PACKAGES) instance = YumTransactionHandler() instance._perform_operations() - assert pkgmanager.YumBase.update.call_count == len(system_packages) - assert pkgmanager.YumBase.reinstall.call_count == len(system_packages) + assert pkgmanager.YumBase.update.call_count == len(SYSTEM_PACKAGES) + assert pkgmanager.YumBase.reinstall.call_count == len(SYSTEM_PACKAGES) assert pkgmanager.YumBase.downgrade.call_count == 0 @centos7 - @pytest.mark.parametrize( - ("system_packages"), - ( - ( - [ - create_pkg_information( - packager="test", - vendor="test", - name="pkg-1", - epoch="0", - version="1.0.0", - release="1", - arch="x86_64", - fingerprint="test", - signature="test", - ), - create_pkg_information( - packager="test", - vendor="test", - name="pkg-2", - epoch="0", - version="1.0.0", - release="1", - arch="x86_64", - fingerprint="test", - signature="test", - ), - create_pkg_information( - packager="test", - vendor="test", - name="pkg-3", - epoch="0", - version="1.0.0", - release="1", - arch="x86_64", - fingerprint="test", - signature="test", - ), - ], - ) - ), - ) - def test_perform_operations_reinstall_exception( - self, pretend_os, system_packages, _mock_yum_api_calls, caplog, monkeypatch - ): - monkeypatch.setattr(pkgmanager.handlers.yum, "get_system_packages_for_replacement", lambda: system_packages) + def test_perform_operations_reinstall_exception(self, pretend_os, _mock_yum_api_calls, caplog, monkeypatch): + monkeypatch.setattr(pkghandler, "get_installed_pkg_information", lambda: SYSTEM_PACKAGES) pkgmanager.YumBase.reinstall.side_effect = pkgmanager.Errors.ReinstallInstallError instance = YumTransactionHandler() instance._perform_operations() - assert pkgmanager.YumBase.reinstall.call_count == len(system_packages) - assert pkgmanager.YumBase.downgrade.call_count == len(system_packages) + assert pkgmanager.YumBase.reinstall.call_count == len(SYSTEM_PACKAGES) + assert pkgmanager.YumBase.downgrade.call_count == len(SYSTEM_PACKAGES) assert "not available in RHEL repositories" not in caplog.records[-1].message @centos7 - @pytest.mark.parametrize( - ("system_packages"), - ( - ( - [ - create_pkg_information( - packager="test", - vendor="test", - name="pkg-1", - epoch="0", - version="1.0.0", - release="1", - arch="x86_64", - fingerprint="test", - signature="test", - ), - create_pkg_information( - packager="test", - vendor="test", - name="pkg-2", - epoch="0", - version="1.0.0", - release="1", - arch="x86_64", - fingerprint="test", - signature="test", - ), - create_pkg_information( - packager="test", - vendor="test", - name="pkg-3", - epoch="0", - version="1.0.0", - release="1", - arch="x86_64", - fingerprint="test", - signature="test", - ), - ], - ) - ), - ) - def test_perform_operations_downgrade_exception( - self, pretend_os, system_packages, _mock_yum_api_calls, caplog, monkeypatch - ): - monkeypatch.setattr(pkgmanager.handlers.yum, "get_system_packages_for_replacement", lambda: system_packages) + def test_perform_operations_downgrade_exception(self, pretend_os, _mock_yum_api_calls, caplog, monkeypatch): + monkeypatch.setattr(pkghandler, "get_installed_pkg_information", lambda: SYSTEM_PACKAGES) pkgmanager.YumBase.reinstall.side_effect = pkgmanager.Errors.ReinstallInstallError pkgmanager.YumBase.downgrade.side_effect = pkgmanager.Errors.ReinstallRemoveError instance = YumTransactionHandler() instance._perform_operations() - assert pkgmanager.YumBase.reinstall.call_count == len(system_packages) - assert pkgmanager.YumBase.downgrade.call_count == len(system_packages) + assert pkgmanager.YumBase.reinstall.call_count == len(SYSTEM_PACKAGES) + assert pkgmanager.YumBase.downgrade.call_count == len(SYSTEM_PACKAGES) assert "not available in RHEL repositories." in caplog.records[-1].message @centos7 def test_perform_operations_no_more_mirrors_repo_exception(self, pretend_os, _mock_yum_api_calls, monkeypatch): - package = [ - create_pkg_information( - packager="test", - vendor="test", - name="pkg-1", - epoch="0", - version="1.0.0", - release="1", - arch="x86_64", - fingerprint="test", - signature="test", - ), - ] - monkeypatch.setattr(pkgmanager.handlers.yum, "get_system_packages_for_replacement", lambda: package) + monkeypatch.setattr(pkghandler, "get_installed_pkg_information", lambda: SYSTEM_PACKAGES) pkgmanager.YumBase.update.side_effect = pkgmanager.Errors.NoMoreMirrorsRepoError instance = YumTransactionHandler() @@ -299,15 +190,7 @@ def test_perform_operations_no_more_mirrors_repo_exception(self, pretend_os, _mo ), ) def test_resolve_dependencies( - self, - pretend_os, - ret_code, - message, - validate_transaction, - expected, - _mock_yum_api_calls, - caplog, - monkeypatch, + self, pretend_os, ret_code, message, validate_transaction, expected, _mock_yum_api_calls, caplog, monkeypatch ): monkeypatch.setattr( pkgmanager.YumBase, @@ -411,6 +294,26 @@ def test_run_transaction_resolve_dependencies_loop( assert pkgmanager.handlers.yum.YumTransactionHandler._perform_operations.call_count == perform_operations_count assert pkgmanager.handlers.yum.YumTransactionHandler._resolve_dependencies.called == resolve_dependencies_count + @centos7 + def test_package_marked_for_update(self, pretend_os, _mock_yum_api_calls, monkeypatch): + """ + Test that if a package is marked for update, we won't call reinstall or + downgrade after that. + + This comes from: https://issues.redhat.com/browse/RHELC-899 + """ + monkeypatch.setattr(pkghandler, "get_installed_pkg_information", lambda: SYSTEM_PACKAGES) + pkgmanager.YumBase.update.return_value = [ + "something" + ] # We don't care about the value, only that if has something. + + instance = YumTransactionHandler() + instance._perform_operations() + + assert pkgmanager.YumBase.update.call_count == len(SYSTEM_PACKAGES) + assert pkgmanager.YumBase.reinstall.call_count == 0 + assert pkgmanager.YumBase.downgrade.call_count == 0 + @centos7 @pytest.mark.parametrize( diff --git a/plans/tier1.fmf b/plans/tier1.fmf index 482e08e38..6302a1058 100644 --- a/plans/tier1.fmf +++ b/plans/tier1.fmf @@ -399,6 +399,17 @@ how: ansible playbook: tests/ansible_collections/roles/reboot/main.yml +/single_yum_transaction_check_for_latest_packages: + discover+: + filter: tag:checks-after-conversion + prepare+: + - name: main conversion preparation + how: shell + script: pytest -svv tests/integration/tier1/single-yum-transaction/test_check_for_latest_packages.py + - name: reboot after conversion + how: ansible + playbook: tests/ansible_collections/roles/reboot/main.yml + /detect_correct_boot_partition: adjust+: - enabled: false diff --git a/pytest.ini b/pytest.ini index 0f3981a1e..1d8995378 100644 --- a/pytest.ini +++ b/pytest.ini @@ -58,4 +58,5 @@ markers = test_failures_and_skips_in_report test_successful_report test_failed_to_parse_package_info_empty_arch_not_present + test_packages_upgraded_after_conversion test_analyze_incomplete_rollback diff --git a/tests/integration/tier1/single-yum-transaction/main.fmf b/tests/integration/tier1/single-yum-transaction/main.fmf index 55f918d31..ea9a8044e 100644 --- a/tests/integration/tier1/single-yum-transaction/main.fmf +++ b/tests/integration/tier1/single-yum-transaction/main.fmf @@ -5,7 +5,13 @@ description: | error. Previous iterations used a lot of different steps, whereas now it is one transaction that can be rolled back more easily. -link: https://issues.redhat.com/browse/RHELC-576 + Verify that packages got upgraded by the end of conversion instead of + reinstalled/downgraded. + + +link: + - https://issues.redhat.com/browse/RHELC-576 + - https://issues.redhat.com/browse/RHELC-899 tier: 1 diff --git a/tests/integration/tier1/single-yum-transaction/test_check_for_latest_packages.py b/tests/integration/tier1/single-yum-transaction/test_check_for_latest_packages.py new file mode 100644 index 000000000..ee70cb782 --- /dev/null +++ b/tests/integration/tier1/single-yum-transaction/test_check_for_latest_packages.py @@ -0,0 +1,62 @@ +import pytest + +from conftest import SYSTEM_RELEASE_ENV +from envparse import env + + +@pytest.mark.test_packages_upgraded_after_conversion +def test_packages_upgraded_after_conversion(convert2rhel, shell): + """ + Verify that packages get correctly reinstalled and not + downgraded during the conversion. + """ + + checked_packages = ["shim-x64"] + + if "oracle-7" in SYSTEM_RELEASE_ENV: + checked_packages = [ + "krb5-libs.x86_64", + "nss-softokn-freebl.x86_64", + "nss-softokn.x86_64", + "expat.x86_64", + "krb5-libs.x86_64", + ] + + packages_to_verify = {} + + for package in checked_packages: + latest_version = shell(f"repoquery --quiet --latest-limit=1 {package}").output.strip("\n") + is_installed = shell(f"rpm -q {package}").output + if "is not installed" in is_installed: + shell(f"yum install -y {package}") + # although not really used, keep the assembled dictionary if needed for version comparison + # also the dictionary gets appended only when there is the package available to install + # (repoquery yields a value) + if latest_version: + packages_to_verify[package] = latest_version + + # Run utility until the reboot + with convert2rhel( + "-y --no-rpm-va --serverurl {} --username {} --password {} --pool {} --debug".format( + env.str("RHSM_SERVER_URL"), + env.str("RHSM_USERNAME"), + env.str("RHSM_PASSWORD"), + env.str("RHSM_POOL"), + ) + ) as c2r: + c2r.expect("Conversion successful!") + assert c2r.exitstatus == 0 + + cmd = "yum check-update --quiet %s" + # We need to point the releasever to 8.5 with CentOS latest + # otherwise the yum check-update looks at releasever 8 + # discovering package versions not available for 8.5 + # Doing that, we also need to disable the epel-modular repo + # as it raises an 404 error + if "centos-8.5" in SYSTEM_RELEASE_ENV: + cmd = "yum check-update --quiet --releasever=8.5 --disablerepo epel-modular %s" + for package in packages_to_verify: + # If tha package lands on latest version after conversion + # `yum check-update` will return 0 + # If it is possible to update the package, the yum returncode yields 100 + assert shell(cmd % package).returncode == 0 diff --git a/tests/integration/tier1/system-up-to-date/main.fmf b/tests/integration/tier1/system-up-to-date/main.fmf index 5fe9ac8ec..9e5e03d04 100644 --- a/tests/integration/tier1/system-up-to-date/main.fmf +++ b/tests/integration/tier1/system-up-to-date/main.fmf @@ -7,5 +7,4 @@ description: | Verify that the conversion emits a warning if the yum versionlock plugin is being used. tier: 1 - test: pytest -svv