From e13e80f1d90a12d4714ec0a0a0b5aa14a6858dc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20S=C3=B6llvander?= Date: Thu, 24 Sep 2026 13:57:50 +0200 Subject: [PATCH 1/2] Add list_repo_pkgs to modules/pkgng.py Fixes: https://github.com/saltstack/salt/discussions/70317 --- changelog/70317.fixed.md | 1 + salt/modules/pkgng.py | 58 ++++++++++++++++++++++++ tests/pytests/unit/modules/test_pkgng.py | 32 +++++++++++++ 3 files changed, 91 insertions(+) create mode 100644 changelog/70317.fixed.md diff --git a/changelog/70317.fixed.md b/changelog/70317.fixed.md new file mode 100644 index 000000000000..f26f0423fba5 --- /dev/null +++ b/changelog/70317.fixed.md @@ -0,0 +1 @@ +Add list_repo_pkgs to modules/pkgng.py diff --git a/salt/modules/pkgng.py b/salt/modules/pkgng.py index c69c19360963..01704fd3aa10 100644 --- a/salt/modules/pkgng.py +++ b/salt/modules/pkgng.py @@ -2326,6 +2326,64 @@ def list_upgrades(refresh=True, **kwargs): } +def list_repo_pkgs(*args, **kwargs): + """ + Returns all available packages. Optionally, package names (and name globs) + can be passed and the results will be filtered to packages matching those + names. + + This function can be helpful in discovering the version or repo to specify + in a :mod:`pkg.installed ` state. + + .. code-block:: python + + { + 'bash': ['4.3-14ubuntu1.1', + '4.3-14ubuntu1'], + 'nginx': ['1.10.0-0ubuntu0.16.04.4', + '1.9.15-0ubuntu1'] + } + + CLI Examples: + + .. code-block:: bash + + salt '*' pkg.list_repo_pkgs + salt '*' pkg.list_repo_pkgs foo bar baz + salt '*' pkg.list_repo_pkgs jail= + salt '*' pkg.list_repo_pkgs jail= foo bar baz + """ + jail = kwargs.get("jail") + chroot = kwargs.get("chroot") + root = kwargs.get("root") + + cmds = [] + if args: + # Get only information about packages in args + for arg in args: + cmd = ["search", "-q", "-S", "name", arg] + cmds.append(cmd) + + else: + cmd = ["search", "-q", "-g", "*"] + cmds.append(cmd) + + ret = {} + + for cmd in cmds: + out = __salt__["cmd.run_stdout"]( + _pkg(jail=jail, chroot=chroot, root=root) + cmd, + output_loglevel="trace", + python_shell=False + ) + + for line in salt.utils.itertools.split(out, "\n"): + pkg, version = line.strip().rsplit("-", 1) + ret.setdefault(pkg, []).append(version) + + return ret + + def _parse_upgrade(stdout): """ Parse the output from the ``pkg upgrade --dry-run`` command diff --git a/tests/pytests/unit/modules/test_pkgng.py b/tests/pytests/unit/modules/test_pkgng.py index 7dda62002e69..e2b537dcafa7 100644 --- a/tests/pytests/unit/modules/test_pkgng.py +++ b/tests/pytests/unit/modules/test_pkgng.py @@ -994,3 +994,35 @@ def test_which_with_origin_flag(): output_loglevel="trace", python_shell=False, ) + + +def test_list_repo_pkgs(): + """ + Test pkgng.list_repo_pkgs with argument + """ + list_repo_pkgs_cmd = MagicMock(return_value="vim-9.2.0738") + with patch.dict(pkgng.__salt__, {"cmd.run_stdout": list_repo_pkgs_cmd}): + + result = pkgng.list_repo_pkgs("vim") + assert result + list_repo_pkgs_cmd.assert_called_with( + ["pkg", "search", "-q", "-S", "name", "vim"], + output_loglevel="trace", + python_shell=False, + ) + + +def test_list_repo_pkgs_unavailable(): + """ + Test pkgng.list_repo_pkgs when nothing is returned + """ + list_repo_pkgs_cmd = MagicMock(return_value="") + with patch.dict(pkgng.__salt__, {"cmd.run_stdout": list_repo_pkgs_cmd}): + + result = pkgng.list_repo_pkgs("vim") + assert not result + list_repo_pkgs_cmd.assert_called_with( + ["pkg", "search", "-q", "-S", "name", "vim"], + output_loglevel="trace", + python_shell=False, + ) From 847dcd26b9db12eab4e0ed34aeba942f056da5be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20S=C3=B6llvander?= Date: Fri, 25 Sep 2026 14:30:20 +0200 Subject: [PATCH 2/2] Fix feedback Make docstring more accurateg. Handle empty lines better and check for "-" before rsplit(). Add two more tests, one with multiple args and one for globs. --- salt/modules/pkgng.py | 17 +++++---- tests/pytests/unit/modules/test_pkgng.py | 46 ++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 6 deletions(-) diff --git a/salt/modules/pkgng.py b/salt/modules/pkgng.py index 01704fd3aa10..b7c1c5c36466 100644 --- a/salt/modules/pkgng.py +++ b/salt/modules/pkgng.py @@ -2338,10 +2338,9 @@ def list_repo_pkgs(*args, **kwargs): .. code-block:: python { - 'bash': ['4.3-14ubuntu1.1', - '4.3-14ubuntu1'], - 'nginx': ['1.10.0-0ubuntu0.16.04.4', - '1.9.15-0ubuntu1'] + 'bash': ['5.3.20', + '5.3.20'] + 'nginx': ['1.30.5,3'] } CLI Examples: @@ -2361,7 +2360,10 @@ def list_repo_pkgs(*args, **kwargs): if args: # Get only information about packages in args for arg in args: - cmd = ["search", "-q", "-S", "name", arg] + cmd = ["search", "-q", "-S", "name"] + if "*" in arg: + cmd = cmd + ["-g"] + cmd = cmd + [arg] cmds.append(cmd) else: @@ -2378,7 +2380,10 @@ def list_repo_pkgs(*args, **kwargs): ) for line in salt.utils.itertools.split(out, "\n"): - pkg, version = line.strip().rsplit("-", 1) + line = line.strip() + if not line or "-" not in line: + continue + pkg, version = line.rsplit("-", 1) ret.setdefault(pkg, []).append(version) return ret diff --git a/tests/pytests/unit/modules/test_pkgng.py b/tests/pytests/unit/modules/test_pkgng.py index e2b537dcafa7..d3ef86163cf3 100644 --- a/tests/pytests/unit/modules/test_pkgng.py +++ b/tests/pytests/unit/modules/test_pkgng.py @@ -1010,6 +1010,52 @@ def test_list_repo_pkgs(): output_loglevel="trace", python_shell=False, ) + assert isinstance(result, dict) + + +def test_list_repo_pkgs_multiple_args(): + """ + Test pkgng.list_repo_pkgs with multiple arguments + """ + list_repo_pkgs_cmd = MagicMock( + side_effect=[ + "vim-9.2.0738", + "nginx-1.30.5,3" + ] + ) + with patch.dict(pkgng.__salt__, {"cmd.run_stdout": list_repo_pkgs_cmd}): + + result = pkgng.list_repo_pkgs("nginx", "vim") + list_repo_pkgs_cmd.assert_called_with( + ["pkg", "search", "-q", "-S", "name", "vim"], + output_loglevel="trace", + python_shell=False, + ) + assert {'vim': ['9.2.0738'], 'nginx': ['1.30.5,3']} == result + + +def test_list_repo_pkgs_arg_glob(): + """ + Test pkgng.list_repo_pkgs with glob argument + """ + + list_repo_pkgs_cmd = MagicMock( + side_effect=[ + "bash-5.3.20", + "bash-completion-zfs-2.4.1", + ] + ) + with patch.dict(pkgng.__salt__, {"cmd.run_stdout": list_repo_pkgs_cmd}): + + result = pkgng.list_repo_pkgs("bash*") + list_repo_pkgs_cmd.assert_called_with( + ["pkg", "search", "-q", "-S", "name", "-g", "bash*"], + output_loglevel="trace", + python_shell=False, + ) + assert {'bash': ['5.3.20']} == result + result = pkgng.list_repo_pkgs("bash*") + assert {'bash-completion-zfs': ['2.4.1']} == result def test_list_repo_pkgs_unavailable():