From 7c82f37f448fffbc0adee7b1a340b75c850f37a0 Mon Sep 17 00:00:00 2001 From: Tyler Levy Conde Date: Thu, 21 Mar 2024 12:05:02 -0600 Subject: [PATCH] Fix: Prevent full system upgrade in pkg.installed for Arch Linux This change modifies the logic in the pacman module to only append the '-u' flag to the pacman command if sysupgrade is explicitly set to True. This prevents the pkg.installed state from triggering a full system upgrade by default on Arch Linux systems. --- changelog/65200.fixed.md | 1 + salt/modules/pacmanpkg.py | 2 +- tests/pytests/unit/modules/test_pacmanpkg.py | 118 ++++--------------- 3 files changed, 24 insertions(+), 97 deletions(-) create mode 100644 changelog/65200.fixed.md diff --git a/changelog/65200.fixed.md b/changelog/65200.fixed.md new file mode 100644 index 000000000000..9da348e5e4e7 --- /dev/null +++ b/changelog/65200.fixed.md @@ -0,0 +1 @@ +Prevent full system upgrade on single package install for Arch Linux diff --git a/salt/modules/pacmanpkg.py b/salt/modules/pacmanpkg.py index 57df5f72cb80..40e56f937338 100644 --- a/salt/modules/pacmanpkg.py +++ b/salt/modules/pacmanpkg.py @@ -552,7 +552,7 @@ def install( cmd.append("-S") if refresh is True: cmd.append("-y") - if sysupgrade is True or (sysupgrade is None and refresh is True): + if sysupgrade is True: cmd.append("-u") cmd.extend(["--noprogressbar", "--noconfirm", "--needed"]) wildcards = [] diff --git a/tests/pytests/unit/modules/test_pacmanpkg.py b/tests/pytests/unit/modules/test_pacmanpkg.py index 796624dbeb7a..0b4d457f4d85 100644 --- a/tests/pytests/unit/modules/test_pacmanpkg.py +++ b/tests/pytests/unit/modules/test_pacmanpkg.py @@ -6,11 +6,14 @@ import salt.modules.pacmanpkg as pacman from tests.support.mock import MagicMock, patch +import salt.utils.systemd @pytest.fixture def configure_loader_modules(): - return {pacman: {}} + return { + pacman: {}, + } def test_list_pkgs(): @@ -63,106 +66,29 @@ def test_list_pkgs_as_list(): assert stringifymock.call_count == 0 -def test_list_pkgs_no_context(): +def test_pacman_install_sysupgrade_flag(): """ - Test if it list the packages currently installed in a dict + Test if the pacman.install function appends the '-u' flag only when sysupgrade is True """ - cmdmock = MagicMock(return_value="A 1.0\nB 2.0") - sortmock = MagicMock() - stringifymock = MagicMock() - mock_ret = {"A": ["1.0"], "B": ["2.0"]} + mock_parse_targets = MagicMock(return_value=({"somepkg": None}, "repository")) + mock_has_scope = MagicMock(return_value=False) + mock_list_pkgs = MagicMock(return_value={"somepkg": "1.0"}) + mock_run_all = MagicMock(return_value={"retcode": 0, "stderr": ""}) + with patch.dict( pacman.__salt__, { - "cmd.run": cmdmock, - "pkg_resource.add_pkg": lambda pkgs, name, version: pkgs.setdefault( - name, [] - ).append(version), - "pkg_resource.sort_pkglist": sortmock, - "pkg_resource.stringify": stringifymock, + "cmd.run_all": mock_run_all, + "pkg_resource.parse_targets": mock_parse_targets, + "config.get": MagicMock(return_value=True), }, - ), patch.object(pacman, "_list_pkgs_from_context") as list_pkgs_context_mock: - assert pacman.list_pkgs() == mock_ret - - pkgs = pacman.list_pkgs(versions_as_list=True, use_context=False) - list_pkgs_context_mock.assert_not_called() - list_pkgs_context_mock.reset_mock() - - pkgs = pacman.list_pkgs(versions_as_list=True, use_context=False) - list_pkgs_context_mock.assert_not_called() - list_pkgs_context_mock.reset_mock() - - -def test_group_list(): - """ - Test if it lists the available groups - """ - - def cmdlist(cmd, **kwargs): - """ - Handle several different commands being run - """ - if cmd == ["pacman", "-Sgg"]: - return ( - "group-a pkg1\ngroup-a pkg2\ngroup-f pkg9\ngroup-c pkg3\ngroup-b pkg4" - ) - elif cmd == ["pacman", "-Qg"]: - return "group-a pkg1\ngroup-b pkg4" - else: - return f"Untested command ({cmd}, {kwargs})!" - - cmdmock = MagicMock(side_effect=cmdlist) - - sortmock = MagicMock() - with patch.dict( - pacman.__salt__, {"cmd.run": cmdmock, "pkg_resource.sort_pkglist": sortmock} - ): - assert pacman.group_list() == { - "available": ["group-c", "group-f"], - "installed": ["group-b"], - "partially_installed": ["group-a"], - } - - -def test_group_info(): - """ - Test if it shows the packages in a group - """ - - def cmdlist(cmd, **kwargs): - """ - Handle several different commands being run - """ - if cmd == ["pacman", "-Sgg", "testgroup"]: - return "testgroup pkg1\ntestgroup pkg2" - else: - return f"Untested command ({cmd}, {kwargs})!" - - cmdmock = MagicMock(side_effect=cmdlist) - - sortmock = MagicMock() - with patch.dict( - pacman.__salt__, {"cmd.run": cmdmock, "pkg_resource.sort_pkglist": sortmock} + ), patch.object(salt.utils.systemd, "has_scope", mock_has_scope), patch.object( + pacman, "list_pkgs", mock_list_pkgs ): - assert pacman.group_info("testgroup")["default"] == ["pkg1", "pkg2"] - + pacman.install(name="somepkg", sysupgrade=True) + args, _ = pacman.__salt__["cmd.run_all"].call_args + assert "-u" in args[0] -def test_group_diff(): - """ - Test if it shows the difference between installed and target group contents - """ - - listmock = MagicMock(return_value={"A": ["1.0"], "B": ["2.0"]}) - groupmock = MagicMock( - return_value={ - "mandatory": [], - "optional": [], - "default": ["A", "C"], - "conditional": [], - } - ) - with patch.dict( - pacman.__salt__, {"pkg.list_pkgs": listmock, "pkg.group_info": groupmock} - ): - results = pacman.group_diff("testgroup") - assert results["default"] == {"installed": ["A"], "not installed": ["C"]} + pacman.install(name="somepkg", sysupgrade=None, refresh=True) + args, _ = pacman.__salt__["cmd.run_all"].call_args + assert "-u" not in args[0]