File normalize-package-names-once-with-pkg.installed-remo.patch of Package salt

From 09afcd0d04788ec4351c1c0b73a0c6eb3b0fd8c9 Mon Sep 17 00:00:00 2001
From: Victor Zhestkov <vzhestkov@suse.com>
Date: Mon, 27 Jun 2022 18:01:21 +0300
Subject: [PATCH] Normalize package names once with pkg.installed/removed
 using yum (bsc#1195895)

* Normalize the package names only once on install/remove

* Add test for checking pkg.installed/removed with only normalisation

* Fix split_arch conditions

* Fix test_pkg
---
 salt/modules/yumpkg.py                |  18 ++-
 salt/states/pkg.py                    |   3 +-
 tests/pytests/unit/states/test_pkg.py | 177 +++++++++++++++++++++++++-
 3 files changed, 192 insertions(+), 6 deletions(-)

diff --git a/salt/modules/yumpkg.py b/salt/modules/yumpkg.py
index 9f8f548e5f..3138ac2e59 100644
--- a/salt/modules/yumpkg.py
+++ b/salt/modules/yumpkg.py
@@ -1449,7 +1449,12 @@ def install(
 
     try:
         pkg_params, pkg_type = __salt__["pkg_resource.parse_targets"](
-            name, pkgs, sources, saltenv=saltenv, normalize=normalize, **kwargs
+            name,
+            pkgs,
+            sources,
+            saltenv=saltenv,
+            normalize=normalize and kwargs.get("split_arch", True),
+            **kwargs
         )
     except MinionError as exc:
         raise CommandExecutionError(exc)
@@ -1603,7 +1608,10 @@ def install(
                 except ValueError:
                     pass
                 else:
-                    if archpart in salt.utils.pkg.rpm.ARCHES:
+                    if archpart in salt.utils.pkg.rpm.ARCHES and (
+                        archpart != __grains__["osarch"]
+                        or kwargs.get("split_arch", True)
+                    ):
                         arch = "." + archpart
                         pkgname = namepart
 
@@ -2134,11 +2142,13 @@ def remove(name=None, pkgs=None, **kwargs):  # pylint: disable=W0613
             arch = ""
             pkgname = target
             try:
-                namepart, archpart = target.rsplit(".", 1)
+                namepart, archpart = pkgname.rsplit(".", 1)
             except ValueError:
                 pass
             else:
-                if archpart in salt.utils.pkg.rpm.ARCHES:
+                if archpart in salt.utils.pkg.rpm.ARCHES and (
+                    archpart != __grains__["osarch"] or kwargs.get("split_arch", True)
+                ):
                     arch = "." + archpart
                     pkgname = namepart
             # Since we don't always have the arch info, epoch information has to parsed out. But
diff --git a/salt/states/pkg.py b/salt/states/pkg.py
index 0d601e1aaf..71298e6c7a 100644
--- a/salt/states/pkg.py
+++ b/salt/states/pkg.py
@@ -1901,6 +1901,7 @@ def installed(
                 normalize=normalize,
                 update_holds=update_holds,
                 ignore_epoch=ignore_epoch,
+                split_arch=False,
                 **kwargs
             )
         except CommandExecutionError as exc:
@@ -2973,7 +2974,7 @@ def _uninstall(
         }
 
     changes = __salt__["pkg.{}".format(action)](
-        name, pkgs=pkgs, version=version, **kwargs
+        name, pkgs=pkgs, version=version, split_arch=False, **kwargs
     )
     new = __salt__["pkg.list_pkgs"](versions_as_list=True, **kwargs)
     failed = []
diff --git a/tests/pytests/unit/states/test_pkg.py b/tests/pytests/unit/states/test_pkg.py
index 17b91bcb39..10acae9f88 100644
--- a/tests/pytests/unit/states/test_pkg.py
+++ b/tests/pytests/unit/states/test_pkg.py
@@ -2,6 +2,8 @@ import logging
 
 import pytest
 import salt.modules.beacons as beaconmod
+import salt.modules.pkg_resource as pkg_resource
+import salt.modules.yumpkg as yumpkg
 import salt.states.beacon as beaconstate
 import salt.states.pkg as pkg
 import salt.utils.state as state_utils
@@ -17,7 +19,7 @@ def configure_loader_modules():
         pkg: {
             "__env__": "base",
             "__salt__": {},
-            "__grains__": {"os": "CentOS"},
+            "__grains__": {"os": "CentOS", "os_family": "RedHat"},
             "__opts__": {"test": False, "cachedir": ""},
             "__instance_id__": "",
             "__low__": {},
@@ -25,6 +27,15 @@ def configure_loader_modules():
         },
         beaconstate: {"__salt__": {}, "__opts__": {}},
         beaconmod: {"__salt__": {}, "__opts__": {}},
+        pkg_resource: {
+            "__salt__": {},
+            "__grains__": {"os": "CentOS", "os_family": "RedHat"},
+        },
+        yumpkg: {
+            "__salt__": {},
+            "__grains__": {"osarch": "x86_64", "osmajorrelease": 7},
+            "__opts__": {},
+        },
     }
 
 
@@ -715,3 +726,167 @@ def test_held_unheld(package_manager):
         hold_mock.assert_not_called()
         unhold_mock.assert_any_call(name="held-test", pkgs=["baz"])
         unhold_mock.assert_any_call(name="held-test", pkgs=["bar"])
+
+
+def test_installed_with_single_normalize():
+    """
+    Test pkg.installed with preventing multiple package name normalisation
+    """
+
+    list_no_weird_installed = {
+        "pkga": "1.0.1",
+        "pkgb": "1.0.2",
+        "pkgc": "1.0.3",
+    }
+    list_no_weird_installed_ver_list = {
+        "pkga": ["1.0.1"],
+        "pkgb": ["1.0.2"],
+        "pkgc": ["1.0.3"],
+    }
+    list_with_weird_installed = {
+        "pkga": "1.0.1",
+        "pkgb": "1.0.2",
+        "pkgc": "1.0.3",
+        "weird-name-1.2.3-1234.5.6.test7tst.x86_64": "20220214-2.1",
+    }
+    list_with_weird_installed_ver_list = {
+        "pkga": ["1.0.1"],
+        "pkgb": ["1.0.2"],
+        "pkgc": ["1.0.3"],
+        "weird-name-1.2.3-1234.5.6.test7tst.x86_64": ["20220214-2.1"],
+    }
+    list_pkgs = MagicMock(
+        side_effect=[
+            # For the package with version specified
+            list_no_weird_installed_ver_list,
+            {},
+            list_no_weird_installed,
+            list_no_weird_installed_ver_list,
+            list_with_weird_installed,
+            list_with_weird_installed_ver_list,
+            # For the package with no version specified
+            list_no_weird_installed_ver_list,
+            {},
+            list_no_weird_installed,
+            list_no_weird_installed_ver_list,
+            list_with_weird_installed,
+            list_with_weird_installed_ver_list,
+        ]
+    )
+
+    salt_dict = {
+        "pkg.install": yumpkg.install,
+        "pkg.list_pkgs": list_pkgs,
+        "pkg.normalize_name": yumpkg.normalize_name,
+        "pkg_resource.version_clean": pkg_resource.version_clean,
+        "pkg_resource.parse_targets": pkg_resource.parse_targets,
+    }
+
+    with patch("salt.modules.yumpkg.list_pkgs", list_pkgs), patch(
+        "salt.modules.yumpkg.version_cmp", MagicMock(return_value=0)
+    ), patch(
+        "salt.modules.yumpkg._call_yum", MagicMock(return_value={"retcode": 0})
+    ) as call_yum_mock, patch.dict(
+        pkg.__salt__, salt_dict
+    ), patch.dict(
+        pkg_resource.__salt__, salt_dict
+    ), patch.dict(
+        yumpkg.__salt__, salt_dict
+    ), patch.dict(
+        yumpkg.__grains__, {"os": "CentOS", "osarch": "x86_64", "osmajorrelease": 7}
+    ), patch.object(
+        yumpkg, "list_holds", MagicMock()
+    ):
+
+        expected = {
+            "weird-name-1.2.3-1234.5.6.test7tst.x86_64": {
+                "old": "",
+                "new": "20220214-2.1",
+            }
+        }
+        ret = pkg.installed(
+            "test_install",
+            pkgs=[{"weird-name-1.2.3-1234.5.6.test7tst.x86_64.noarch": "20220214-2.1"}],
+        )
+        call_yum_mock.assert_called_once()
+        assert (
+            call_yum_mock.mock_calls[0].args[0][2]
+            == "weird-name-1.2.3-1234.5.6.test7tst.x86_64-20220214-2.1"
+        )
+        assert ret["result"]
+        assert ret["changes"] == expected
+
+
+def test_removed_with_single_normalize():
+    """
+    Test pkg.removed with preventing multiple package name normalisation
+    """
+
+    list_no_weird_installed = {
+        "pkga": "1.0.1",
+        "pkgb": "1.0.2",
+        "pkgc": "1.0.3",
+    }
+    list_no_weird_installed_ver_list = {
+        "pkga": ["1.0.1"],
+        "pkgb": ["1.0.2"],
+        "pkgc": ["1.0.3"],
+    }
+    list_with_weird_installed = {
+        "pkga": "1.0.1",
+        "pkgb": "1.0.2",
+        "pkgc": "1.0.3",
+        "weird-name-1.2.3-1234.5.6.test7tst.x86_64": "20220214-2.1",
+    }
+    list_with_weird_installed_ver_list = {
+        "pkga": ["1.0.1"],
+        "pkgb": ["1.0.2"],
+        "pkgc": ["1.0.3"],
+        "weird-name-1.2.3-1234.5.6.test7tst.x86_64": ["20220214-2.1"],
+    }
+    list_pkgs = MagicMock(
+        side_effect=[
+            list_with_weird_installed_ver_list,
+            list_with_weird_installed,
+            list_no_weird_installed,
+            list_no_weird_installed_ver_list,
+        ]
+    )
+
+    salt_dict = {
+        "pkg.remove": yumpkg.remove,
+        "pkg.list_pkgs": list_pkgs,
+        "pkg.normalize_name": yumpkg.normalize_name,
+        "pkg_resource.parse_targets": pkg_resource.parse_targets,
+        "pkg_resource.version_clean": pkg_resource.version_clean,
+    }
+
+    with patch("salt.modules.yumpkg.list_pkgs", list_pkgs), patch(
+        "salt.modules.yumpkg.version_cmp", MagicMock(return_value=0)
+    ), patch(
+        "salt.modules.yumpkg._call_yum", MagicMock(return_value={"retcode": 0})
+    ) as call_yum_mock, patch.dict(
+        pkg.__salt__, salt_dict
+    ), patch.dict(
+        pkg_resource.__salt__, salt_dict
+    ), patch.dict(
+        yumpkg.__salt__, salt_dict
+    ):
+
+        expected = {
+            "weird-name-1.2.3-1234.5.6.test7tst.x86_64": {
+                "old": "20220214-2.1",
+                "new": "",
+            }
+        }
+        ret = pkg.removed(
+            "test_remove",
+            pkgs=[{"weird-name-1.2.3-1234.5.6.test7tst.x86_64.noarch": "20220214-2.1"}],
+        )
+        call_yum_mock.assert_called_once()
+        assert (
+            call_yum_mock.mock_calls[0].args[0][2]
+            == "weird-name-1.2.3-1234.5.6.test7tst.x86_64-20220214-2.1"
+        )
+        assert ret["result"]
+        assert ret["changes"] == expected
-- 
2.36.1


openSUSE Build Service is sponsored by