Skip to content

Commit

Permalink
Fix: Prevent full system upgrade in pkg.installed for Arch Linux
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Akm0d committed Mar 22, 2024
1 parent b2fe6c4 commit 7c82f37
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 97 deletions.
1 change: 1 addition & 0 deletions changelog/65200.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Prevent full system upgrade on single package install for Arch Linux
2 changes: 1 addition & 1 deletion salt/modules/pacmanpkg.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = []
Expand Down
118 changes: 22 additions & 96 deletions tests/pytests/unit/modules/test_pacmanpkg.py
Original file line number Diff line number Diff line change
Expand Up @@ -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():
Expand Down Expand Up @@ -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]

0 comments on commit 7c82f37

Please sign in to comment.