diff --git a/3005.1-implement-zypper-removeptf-573.patch b/3005.1-implement-zypper-removeptf-573.patch index f271c04..82e4c9f 100644 --- a/3005.1-implement-zypper-removeptf-573.patch +++ b/3005.1-implement-zypper-removeptf-573.patch @@ -1,4 +1,4 @@ -From a5027f623a0a2e7f49109af9e2fa3ce409a31a64 Mon Sep 17 00:00:00 2001 +From 327a5e5b24c4fa047df44b245abd672e02999cca Mon Sep 17 00:00:00 2001 From: Michael Calmer Date: Mon, 23 Jan 2023 14:33:26 +0100 Subject: [PATCH] 3005.1 implement zypper removeptf (#573) @@ -13,15 +13,13 @@ Subject: [PATCH] 3005.1 implement zypper removeptf (#573) * Update Docs -Co-authored-by: Megan Wilhite - Co-authored-by: Megan Wilhite --- - changelog/63442.added | 1 + - salt/modules/zypperpkg.py | 38 +++++++- - tests/pytests/unit/modules/test_zypperpkg.py | 92 +++++++++++++++++++- - tests/unit/modules/test_zypperpkg.py | 1 + - 4 files changed, 130 insertions(+), 2 deletions(-) + changelog/63442.added | 1 + + salt/modules/zypperpkg.py | 38 +- + tests/pytests/unit/modules/test_zypperpkg.py | 356 ++++++++++++++++++- + tests/unit/modules/test_zypperpkg.py | 1 + + 4 files changed, 394 insertions(+), 2 deletions(-) create mode 100644 changelog/63442.added diff --git a/changelog/63442.added b/changelog/63442.added @@ -32,10 +30,10 @@ index 0000000000..ad81b2f9d5 @@ -0,0 +1 @@ +implement removal of ptf packages in zypper pkg module diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py -index 5d745c432d..2888bb219f 100644 +index 051f8f72c7..44f2cdbd3a 100644 --- a/salt/modules/zypperpkg.py +++ b/salt/modules/zypperpkg.py -@@ -2058,17 +2058,21 @@ def _uninstall(inclusion_detection, name=None, pkgs=None, root=None): +@@ -2073,17 +2073,21 @@ def _uninstall(inclusion_detection, name=None, pkgs=None, root=None): except MinionError as exc: raise CommandExecutionError(exc) @@ -58,7 +56,7 @@ index 5d745c432d..2888bb219f 100644 return {} systemd_scope = _systemd_scope() -@@ -2080,6 +2084,13 @@ def _uninstall(inclusion_detection, name=None, pkgs=None, root=None): +@@ -2095,6 +2099,13 @@ def _uninstall(inclusion_detection, name=None, pkgs=None, root=None): ) targets = targets[500:] @@ -72,7 +70,7 @@ index 5d745c432d..2888bb219f 100644 _clean_cache() new = list_pkgs(root=root, includes=includes) ret = salt.utils.data.compare_dicts(old, new) -@@ -2168,6 +2179,11 @@ def remove( +@@ -2183,6 +2194,11 @@ def remove( salt '*' pkg.remove salt '*' pkg.remove ,, salt '*' pkg.remove pkgs='["foo", "bar"]' @@ -84,7 +82,7 @@ index 5d745c432d..2888bb219f 100644 """ return _uninstall(inclusion_detection, name=name, pkgs=pkgs, root=root) -@@ -2643,6 +2659,26 @@ def _get_visible_patterns(root=None): +@@ -2658,6 +2674,26 @@ def _get_visible_patterns(root=None): return patterns @@ -112,10 +110,10 @@ index 5d745c432d..2888bb219f 100644 """ List all installed patterns. diff --git a/tests/pytests/unit/modules/test_zypperpkg.py b/tests/pytests/unit/modules/test_zypperpkg.py -index 84dc7a10b4..a0d8e0084e 100644 +index 91132b7277..c996662e1c 100644 --- a/tests/pytests/unit/modules/test_zypperpkg.py +++ b/tests/pytests/unit/modules/test_zypperpkg.py -@@ -10,7 +10,7 @@ import pytest +@@ -11,7 +11,7 @@ import pytest import salt.modules.pkg_resource as pkg_resource import salt.modules.zypperpkg as zypper from salt.exceptions import CommandExecutionError, SaltInvocationError @@ -124,10 +122,281 @@ index 84dc7a10b4..a0d8e0084e 100644 @pytest.fixture -@@ -527,3 +527,93 @@ def test_dist_upgrade_failure(): +@@ -27,6 +27,11 @@ def configure_loader_modules(): + } - assert exc.exception.info["changes"] == {} - assert exc.exception.info["result"]["stdout"] == zypper_output + ++@pytest.fixture(autouse=True) ++def fresh_zypper_instance(): ++ zypper.__zypper__ = zypper._Zypper() ++ ++ + def test_list_pkgs_no_context(): + """ + Test packages listing. +@@ -395,3 +400,352 @@ def test_del_repo_key(): + with patch.dict(zypper.__salt__, salt_mock): + assert zypper.del_repo_key(keyid="keyid", root="/mnt") + salt_mock["lowpkg.remove_gpg_key"].assert_called_once_with("keyid", "/mnt") ++ ++@pytest.mark.parametrize( ++ "zypper_version,lowpkg_version_cmp,expected_inst_avc,expected_dup_avc", ++ [ ++ ("0.5", [-1, -1], False, False), ++ ("1.11.34", [0, -1], False, True), ++ ("1.14.8", [0, 0], True, True), ++ ], ++) ++def test_refresh_zypper_flags( ++ zypper_version, lowpkg_version_cmp, expected_inst_avc, expected_dup_avc ++): ++ with patch( ++ "salt.modules.zypperpkg.version", MagicMock(return_value=zypper_version) ++ ), patch.dict( ++ zypper.__salt__, ++ {"lowpkg.version_cmp": MagicMock(side_effect=lowpkg_version_cmp)}, ++ ): ++ _zypper = zypper._Zypper() ++ _zypper.refresh_zypper_flags() ++ assert _zypper.inst_avc == expected_inst_avc ++ assert _zypper.dup_avc == expected_dup_avc ++ ++ ++@pytest.mark.parametrize( ++ "inst_avc,dup_avc,avc,allowvendorchange_param,novendorchange_param,expected", ++ [ ++ # inst_avc = True, dup_avc = True ++ (True, True, False, False, False, True), ++ (True, True, False, True, False, True), ++ (True, True, False, False, True, False), ++ (True, True, False, True, True, True), ++ # inst_avc = False, dup_avc = True ++ (False, True, False, False, False, True), ++ (False, True, False, True, False, True), ++ (False, True, False, False, True, False), ++ (False, True, False, True, True, True), ++ # inst_avc = False, dup_avc = False ++ (False, False, False, False, False, False), ++ (False, False, False, True, False, False), ++ (False, False, False, False, True, False), ++ (False, False, False, True, True, False), ++ ], ++) ++@patch("salt.modules.zypperpkg._Zypper.refresh_zypper_flags", MagicMock()) ++def test_allow_vendor_change( ++ inst_avc, ++ dup_avc, ++ avc, ++ allowvendorchange_param, ++ novendorchange_param, ++ expected, ++): ++ _zypper = zypper._Zypper() ++ _zypper.inst_avc = inst_avc ++ _zypper.dup_avc = dup_avc ++ _zypper.avc = avc ++ _zypper.allow_vendor_change(allowvendorchange_param, novendorchange_param) ++ assert _zypper.avc == expected ++ ++ ++@pytest.mark.parametrize( ++ "package,pre_version,post_version,fromrepo_param,name_param,pkgs_param,diff_attr_param", ++ [ ++ ("vim", "1.1", "1.2", [], "", [], "all"), ++ ("kernel-default", "1.1", "1.1,1.2", ["dummy", "dummy2"], "", [], None), ++ ("vim", "1.1", "1.2", [], "vim", [], None), ++ ], ++) ++@patch.object(zypper, "refresh_db", MagicMock(return_value=True)) ++def test_upgrade( ++ package, ++ pre_version, ++ post_version, ++ fromrepo_param, ++ name_param, ++ pkgs_param, ++ diff_attr_param, ++): ++ with patch( ++ "salt.modules.zypperpkg.__zypper__.noraise.call" ++ ) as zypper_mock, patch.object( ++ zypper, ++ "list_pkgs", ++ MagicMock(side_effect=[{package: pre_version}, {package: post_version}]), ++ ) as list_pkgs_mock: ++ expected_call = ["update", "--auto-agree-with-licenses"] ++ for repo in fromrepo_param: ++ expected_call.extend(["--repo", repo]) ++ ++ if pkgs_param: ++ expected_call.extend(pkgs_param) ++ elif name_param: ++ expected_call.append(name_param) ++ ++ result = zypper.upgrade( ++ name=name_param, ++ pkgs=pkgs_param, ++ fromrepo=fromrepo_param, ++ diff_attr=diff_attr_param, ++ ) ++ zypper_mock.assert_any_call(*expected_call) ++ assert result == {package: {"old": pre_version, "new": post_version}} ++ list_pkgs_mock.assert_any_call(root=None, attr=diff_attr_param) ++ ++ ++@pytest.mark.parametrize( ++ "package,pre_version,post_version,fromrepo_param", ++ [ ++ ("vim", "1.1", "1.2", []), ++ ("emacs", "1.1", "1.2", ["Dummy", "Dummy2"]), ++ ], ++) ++@patch.object(zypper, "refresh_db", MagicMock(return_value=True)) ++def test_dist_upgrade(package, pre_version, post_version, fromrepo_param): ++ with patch( ++ "salt.modules.zypperpkg.__zypper__.noraise.call" ++ ) as zypper_mock, patch.object( ++ zypper, ++ "list_pkgs", ++ MagicMock(side_effect=[{package: pre_version}, {package: post_version}]), ++ ): ++ expected_call = ["dist-upgrade", "--auto-agree-with-licenses"] ++ ++ for repo in fromrepo_param: ++ expected_call.extend(["--from", repo]) ++ ++ result = zypper.upgrade(dist_upgrade=True, fromrepo=fromrepo_param) ++ zypper_mock.assert_any_call(*expected_call) ++ assert result == {package: {"old": pre_version, "new": post_version}} ++ ++ ++@pytest.mark.parametrize( ++ "package,pre_version,post_version,dup_avc,novendorchange_param,allowvendorchange_param,vendor_change", ++ [ ++ # dup_avc = True, both params = default -> no vendor change ++ ("vim", "1.1", "1.2", True, True, False, False), ++ # dup_avc = True, allowvendorchange = True -> vendor change ++ ( ++ "emacs", ++ "1.1", ++ "1.2", ++ True, ++ True, ++ True, ++ True, ++ ), ++ # dup_avc = True, novendorchange = False -> vendor change ++ ("joe", "1.1", "1.2", True, False, False, True), ++ # dup_avc = True, both params = toggled -> vendor change ++ ("kate", "1.1", "1.2", True, False, True, True), ++ # dup_avc = False -> no vendor change ++ ( ++ "gedit", ++ "1.1", ++ "1.2", ++ False, ++ False, ++ True, ++ False ++ ), ++ ], ++) ++@patch.object(zypper, "refresh_db", MagicMock(return_value=True)) ++def test_dist_upgrade_vendorchange( ++ package, ++ pre_version, ++ post_version, ++ dup_avc, ++ novendorchange_param, ++ allowvendorchange_param, ++ vendor_change ++): ++ cmd_run_mock = MagicMock(return_value={"retcode": 0, "stdout": None}) ++ with patch.object( ++ zypper, ++ "list_pkgs", ++ MagicMock(side_effect=[{package: pre_version}, {package: post_version}]), ++ ), patch("salt.modules.zypperpkg.__zypper__.refresh_zypper_flags",), patch.dict( ++ zypper.__salt__, {"cmd.run_all": cmd_run_mock} ++ ): ++ expected_cmd = ["zypper", "--non-interactive", "--no-refresh", "dist-upgrade"] ++ # --allow-vendor-change is injected right after "dist-upgrade" ++ if vendor_change: ++ expected_cmd.append("--allow-vendor-change") ++ expected_cmd.append("--auto-agree-with-licenses") ++ ++ zypper.__zypper__.dup_avc = dup_avc ++ zypper.upgrade( ++ dist_upgrade=True, ++ allowvendorchange=allowvendorchange_param, ++ novendorchange=novendorchange_param, ++ ) ++ cmd_run_mock.assert_any_call( ++ expected_cmd, output_loglevel="trace", python_shell=False, env={} ++ ) ++ ++ ++@pytest.mark.parametrize( ++ "package,pre_version,post_version,fromrepo_param", ++ [ ++ ("vim", "1.1", "1.1", []), ++ ("emacs", "1.1", "1.1", ["Dummy", "Dummy2"]), ++ ], ++) ++@patch.object(zypper, "refresh_db", MagicMock(return_value=True)) ++def test_dist_upgrade_dry_run(package, pre_version, post_version, fromrepo_param): ++ with patch( ++ "salt.modules.zypperpkg.__zypper__.noraise.call" ++ ) as zypper_mock, patch.object( ++ zypper, ++ "list_pkgs", ++ MagicMock(side_effect=[{package: pre_version}, {package: post_version}]), ++ ): ++ expected_call = ["dist-upgrade", "--auto-agree-with-licenses", "--dry-run"] ++ ++ for repo in fromrepo_param: ++ expected_call.extend(["--from", repo]) ++ ++ zypper.upgrade(dist_upgrade=True, dryrun=True, fromrepo=fromrepo_param) ++ zypper_mock.assert_any_call(*expected_call) ++ # dryrun=True causes two calls, one with a trailing --debug-solver flag ++ expected_call.append("--debug-solver") ++ zypper_mock.assert_any_call(*expected_call) ++ ++ ++@patch.object(zypper, "refresh_db", MagicMock(return_value=True)) ++def test_dist_upgrade_failure(): ++ zypper_output = textwrap.dedent( ++ """\ ++ Loading repository data... ++ Reading installed packages... ++ Computing distribution upgrade... ++ Use 'zypper repos' to get the list of defined repositories. ++ Repository 'DUMMY' not found by its alias, number, or URI. ++ """ ++ ) ++ call_spy = MagicMock() ++ zypper_mock = MagicMock() ++ zypper_mock.stdout = zypper_output ++ zypper_mock.stderr = "" ++ zypper_mock.exit_code = 3 ++ zypper_mock.noraise.call = call_spy ++ with patch("salt.modules.zypperpkg.__zypper__", zypper_mock), patch.object( ++ zypper, "list_pkgs", MagicMock(side_effect=[{"vim": 1.1}, {"vim": 1.1}]) ++ ): ++ expected_call = [ ++ "dist-upgrade", ++ "--auto-agree-with-licenses", ++ "--from", ++ "Dummy", ++ ] ++ ++ with pytest.raises(CommandExecutionError) as exc: ++ zypper.upgrade(dist_upgrade=True, fromrepo=["Dummy"]) ++ call_spy.assert_called_with(*expected_call) ++ ++ assert exc.exception.info["changes"] == {} ++ assert exc.exception.info["result"]["stdout"] == zypper_output + + +def test_remove_multiple_pkgs_with_ptf(): @@ -219,10 +488,10 @@ index 84dc7a10b4..a0d8e0084e 100644 + assert result["ptf-12345"]["new"] == "", result + assert result["ptf-12345"]["old"] == "1", result diff --git a/tests/unit/modules/test_zypperpkg.py b/tests/unit/modules/test_zypperpkg.py -index bcd001cd85..db766363ec 100644 +index f5b6d74b6f..6e5ca88895 100644 --- a/tests/unit/modules/test_zypperpkg.py +++ b/tests/unit/modules/test_zypperpkg.py -@@ -1470,6 +1470,7 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): +@@ -1953,6 +1953,7 @@ Repository 'DUMMY' not found by its alias, number, or URI. # If config.get starts being used elsewhere, we'll need to write a # side_effect function. patches = { @@ -231,6 +500,6 @@ index bcd001cd85..db766363ec 100644 "pkg_resource.parse_targets": MagicMock(return_value=parsed_targets), "pkg_resource.stringify": MagicMock(), -- -2.37.3 +2.39.2 diff --git a/_lastrevision b/_lastrevision index c4c75ad..4bb9bbe 100644 --- a/_lastrevision +++ b/_lastrevision @@ -1 +1 @@ -e66649e03c92d249899960aa629533eaeee31fa1 \ No newline at end of file +2c8ae68c3fb161fd84005ed1b58abf7865ba646f \ No newline at end of file diff --git a/_service b/_service index 28c0df2..6b7dd83 100644 --- a/_service +++ b/_service @@ -3,7 +3,7 @@ https://github.com/openSUSE/salt-packaging.git salt package - release/3005.1 + release/3006.0 git @@ -12,8 +12,8 @@ codeload.github.com - openSUSE/salt/tar.gz/v3005.1-suse - v3005.1.tar.gz + openSUSE/salt/tar.gz/v3006.0-suse + v3006.0.tar.gz diff --git a/activate-all-beacons-sources-config-pillar-grains.patch b/activate-all-beacons-sources-config-pillar-grains.patch index e5d34b6..9a02d85 100644 --- a/activate-all-beacons-sources-config-pillar-grains.patch +++ b/activate-all-beacons-sources-config-pillar-grains.patch @@ -1,4 +1,4 @@ -From ae426ff5df3ade9ce16672fb20399634a8b777d5 Mon Sep 17 00:00:00 2001 +From f2938966bd1fcb46df0f202f5a86729ab190565a Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Tue, 17 Oct 2017 16:52:33 +0200 Subject: [PATCH] Activate all beacons sources: config/pillar/grains @@ -8,7 +8,7 @@ Subject: [PATCH] Activate all beacons sources: config/pillar/grains 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/salt/minion.py b/salt/minion.py -index 544805fc62..16452facf4 100644 +index 6237fcc4b7..2f905e4a4f 100644 --- a/salt/minion.py +++ b/salt/minion.py @@ -503,9 +503,7 @@ class MinionBase: @@ -23,6 +23,6 @@ index 544805fc62..16452facf4 100644 return self.beacons.process( b_conf, self.opts["grains"] -- -2.37.3 +2.39.2 diff --git a/add-amazon-ec2-detection-for-virtual-grains-bsc-1195.patch b/add-amazon-ec2-detection-for-virtual-grains-bsc-1195.patch deleted file mode 100644 index b599881..0000000 --- a/add-amazon-ec2-detection-for-virtual-grains-bsc-1195.patch +++ /dev/null @@ -1,224 +0,0 @@ -From 1434a128559df8183c032af722dc3d187bda148a Mon Sep 17 00:00:00 2001 -From: Victor Zhestkov -Date: Thu, 1 Sep 2022 14:46:24 +0300 -Subject: [PATCH] Add Amazon EC2 detection for virtual grains - (bsc#1195624) - -* Add ignore_retcode to quiet run functions - -* Implement Amazon EC2 detection for virtual grains - -* Add test for virtual grain detection of Amazon EC2 - -* Also detect the product of Amazon EC2 instance - -* Add changelog entry ---- - changelog/62539.added | 1 + - salt/grains/core.py | 18 ++++ - salt/modules/cmdmod.py | 4 + - tests/pytests/unit/grains/test_core.py | 117 +++++++++++++++++++++++++ - 4 files changed, 140 insertions(+) - create mode 100644 changelog/62539.added - -diff --git a/changelog/62539.added b/changelog/62539.added -new file mode 100644 -index 0000000000..5f402d61c2 ---- /dev/null -+++ b/changelog/62539.added -@@ -0,0 +1 @@ -+Implementation of Amazon EC2 instance detection and setting `virtual_subtype` grain accordingly including the product if possible to identify. -diff --git a/salt/grains/core.py b/salt/grains/core.py -index 23d8b8ea42..047c33ffd3 100644 ---- a/salt/grains/core.py -+++ b/salt/grains/core.py -@@ -1171,6 +1171,24 @@ def _virtual(osdata): - if grains.get("virtual_subtype") and grains["virtual"] == "physical": - grains["virtual"] = "virtual" - -+ # Try to detect if the instance is running on Amazon EC2 -+ if grains["virtual"] in ("qemu", "kvm", "xen"): -+ dmidecode = salt.utils.path.which("dmidecode") -+ if dmidecode: -+ ret = __salt__["cmd.run_all"]( -+ [dmidecode, "-t", "system"], ignore_retcode=True -+ ) -+ output = ret["stdout"] -+ if "Manufacturer: Amazon EC2" in output: -+ grains["virtual_subtype"] = "Amazon EC2" -+ product = re.match( -+ r".*Product Name: ([^\r\n]*).*", output, flags=re.DOTALL -+ ) -+ if product: -+ grains["virtual_subtype"] = "Amazon EC2 ({})".format(product[1]) -+ elif re.match(r".*Version: [^\r\n]+\.amazon.*", output, flags=re.DOTALL): -+ grains["virtual_subtype"] = "Amazon EC2" -+ - for command in failed_commands: - log.info( - "Although '%s' was found in path, the current user " -diff --git a/salt/modules/cmdmod.py b/salt/modules/cmdmod.py -index a26220718a..07b6e100d2 100644 ---- a/salt/modules/cmdmod.py -+++ b/salt/modules/cmdmod.py -@@ -932,6 +932,7 @@ def _run_quiet( - success_retcodes=None, - success_stdout=None, - success_stderr=None, -+ ignore_retcode=None, - ): - """ - Helper for running commands quietly for minion startup -@@ -958,6 +959,7 @@ def _run_quiet( - success_retcodes=success_retcodes, - success_stdout=success_stdout, - success_stderr=success_stderr, -+ ignore_retcode=ignore_retcode, - )["stdout"] - - -@@ -980,6 +982,7 @@ def _run_all_quiet( - success_retcodes=None, - success_stdout=None, - success_stderr=None, -+ ignore_retcode=None, - ): - - """ -@@ -1012,6 +1015,7 @@ def _run_all_quiet( - success_retcodes=success_retcodes, - success_stdout=success_stdout, - success_stderr=success_stderr, -+ ignore_retcode=ignore_retcode, - ) - - -diff --git a/tests/pytests/unit/grains/test_core.py b/tests/pytests/unit/grains/test_core.py -index 5c43dbdb09..7c4ea1f17f 100644 ---- a/tests/pytests/unit/grains/test_core.py -+++ b/tests/pytests/unit/grains/test_core.py -@@ -2823,3 +2823,120 @@ def test_get_server_id(): - - with patch.dict(core.__opts__, {"id": "otherid"}): - assert core.get_server_id() != expected -+ -+ -+@pytest.mark.skip_unless_on_linux -+def test_virtual_set_virtual_ec2(): -+ osdata = {} -+ -+ ( -+ osdata["kernel"], -+ osdata["nodename"], -+ osdata["kernelrelease"], -+ osdata["kernelversion"], -+ osdata["cpuarch"], -+ _, -+ ) = platform.uname() -+ -+ which_mock = MagicMock( -+ side_effect=[ -+ # Check with virt-what -+ "/usr/sbin/virt-what", -+ "/usr/sbin/virt-what", -+ None, -+ "/usr/sbin/dmidecode", -+ # Check with systemd-detect-virt -+ None, -+ "/usr/bin/systemd-detect-virt", -+ None, -+ "/usr/sbin/dmidecode", -+ # Check with systemd-detect-virt when no dmidecode available -+ None, -+ "/usr/bin/systemd-detect-virt", -+ None, -+ None, -+ ] -+ ) -+ cmd_run_all_mock = MagicMock( -+ side_effect=[ -+ # Check with virt-what -+ {"retcode": 0, "stderr": "", "stdout": "xen"}, -+ { -+ "retcode": 0, -+ "stderr": "", -+ "stdout": "\n".join( -+ [ -+ "dmidecode 3.2", -+ "Getting SMBIOS data from sysfs.", -+ "SMBIOS 2.7 present.", -+ "", -+ "Handle 0x0100, DMI type 1, 27 bytes", -+ "System Information", -+ " Manufacturer: Xen", -+ " Product Name: HVM domU", -+ " Version: 4.11.amazon", -+ " Serial Number: 12345678-abcd-4321-dcba-0123456789ab", -+ " UUID: 01234567-dcba-1234-abcd-abcdef012345", -+ " Wake-up Type: Power Switch", -+ " SKU Number: Not Specified", -+ " Family: Not Specified", -+ "", -+ "Handle 0x2000, DMI type 32, 11 bytes", -+ "System Boot Information", -+ " Status: No errors detected", -+ ] -+ ), -+ }, -+ # Check with systemd-detect-virt -+ {"retcode": 0, "stderr": "", "stdout": "kvm"}, -+ { -+ "retcode": 0, -+ "stderr": "", -+ "stdout": "\n".join( -+ [ -+ "dmidecode 3.2", -+ "Getting SMBIOS data from sysfs.", -+ "SMBIOS 2.7 present.", -+ "", -+ "Handle 0x0001, DMI type 1, 27 bytes", -+ "System Information", -+ " Manufacturer: Amazon EC2", -+ " Product Name: m5.large", -+ " Version: Not Specified", -+ " Serial Number: 01234567-dcba-1234-abcd-abcdef012345", -+ " UUID: 12345678-abcd-4321-dcba-0123456789ab", -+ " Wake-up Type: Power Switch", -+ " SKU Number: Not Specified", -+ " Family: Not Specified", -+ ] -+ ), -+ }, -+ # Check with systemd-detect-virt when no dmidecode available -+ {"retcode": 0, "stderr": "", "stdout": "kvm"}, -+ ] -+ ) -+ -+ with patch("salt.utils.path.which", which_mock), patch.dict( -+ core.__salt__, -+ { -+ "cmd.run": salt.modules.cmdmod.run, -+ "cmd.run_all": cmd_run_all_mock, -+ "cmd.retcode": salt.modules.cmdmod.retcode, -+ "smbios.get": salt.modules.smbios.get, -+ }, -+ ): -+ -+ virtual_grains = core._virtual(osdata.copy()) -+ -+ assert virtual_grains["virtual"] == "xen" -+ assert virtual_grains["virtual_subtype"] == "Amazon EC2" -+ -+ virtual_grains = core._virtual(osdata.copy()) -+ -+ assert virtual_grains["virtual"] == "kvm" -+ assert virtual_grains["virtual_subtype"] == "Amazon EC2 (m5.large)" -+ -+ virtual_grains = core._virtual(osdata.copy()) -+ -+ assert virtual_grains["virtual"] == "kvm" -+ assert "virtual_subtype" not in virtual_grains --- -2.37.3 - - diff --git a/add-custom-suse-capabilities-as-grains.patch b/add-custom-suse-capabilities-as-grains.patch index 418b5aa..690c44e 100644 --- a/add-custom-suse-capabilities-as-grains.patch +++ b/add-custom-suse-capabilities-as-grains.patch @@ -1,4 +1,4 @@ -From cb31b475c2ac02e06b167f30fc36fe49f7f5d4f6 Mon Sep 17 00:00:00 2001 +From 311d4e320527158b6ff88604b45e15f0dc2bfa62 Mon Sep 17 00:00:00 2001 From: Alexander Graul Date: Tue, 18 Jan 2022 12:59:43 +0100 Subject: [PATCH] Add custom SUSE capabilities as Grains @@ -25,6 +25,6 @@ index 300052f1ee..f2504dbf19 100644 + '__suse_reserved_saltutil_states_support': True + } -- -2.37.3 +2.39.2 diff --git a/add-environment-variable-to-know-if-yum-is-invoked-f.patch b/add-environment-variable-to-know-if-yum-is-invoked-f.patch index da79922..1235df4 100644 --- a/add-environment-variable-to-know-if-yum-is-invoked-f.patch +++ b/add-environment-variable-to-know-if-yum-is-invoked-f.patch @@ -1,4 +1,4 @@ -From 0cbc4e8f8ed5c8366ed6864216d70d58f5ae0a82 Mon Sep 17 00:00:00 2001 +From d7682d1bc67ccdd63022c63b2d3229f8ab40d52b Mon Sep 17 00:00:00 2001 From: Alexander Graul Date: Tue, 18 Jan 2022 12:57:21 +0100 Subject: [PATCH] Add environment variable to know if yum is invoked from @@ -9,13 +9,13 @@ Subject: [PATCH] Add environment variable to know if yum is invoked from 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/salt/modules/yumpkg.py b/salt/modules/yumpkg.py -index 3f855d255f..08dccafceb 100644 +index 4d0070f21a..b362d30bf4 100644 --- a/salt/modules/yumpkg.py +++ b/salt/modules/yumpkg.py -@@ -965,7 +965,9 @@ def list_repo_pkgs(*args, **kwargs): +@@ -964,7 +964,9 @@ def list_repo_pkgs(*args, **kwargs): None if _yum() != "yum" - else _LooseVersion( + else LooseVersion( - __salt__["cmd.run"](["yum", "--version"], python_shell=False) + __salt__["cmd.run"]( + ["yum", "--version"], python_shell=False, env={"SALT_RUNNING": "1"} @@ -23,7 +23,7 @@ index 3f855d255f..08dccafceb 100644 .splitlines()[0] .strip() ) -@@ -2433,7 +2435,9 @@ def list_holds(pattern=__HOLD_PATTERN, full=True): +@@ -2474,7 +2476,9 @@ def list_holds(pattern=__HOLD_PATTERN, full=True): """ _check_versionlock() @@ -34,7 +34,7 @@ index 3f855d255f..08dccafceb 100644 ret = [] for line in salt.utils.itertools.split(out, "\n"): match = _get_hold(line, pattern=pattern, full=full) -@@ -2501,7 +2505,10 @@ def group_list(): +@@ -2542,7 +2546,10 @@ def group_list(): } out = __salt__["cmd.run_stdout"]( @@ -46,7 +46,7 @@ index 3f855d255f..08dccafceb 100644 ) key = None for line in salt.utils.itertools.split(out, "\n"): -@@ -2572,7 +2579,9 @@ def group_info(name, expand=False, ignore_groups=None): +@@ -2613,7 +2620,9 @@ def group_info(name, expand=False, ignore_groups=None): ret[pkgtype] = set() cmd = [_yum(), "--quiet", "groupinfo", name] @@ -57,7 +57,7 @@ index 3f855d255f..08dccafceb 100644 g_info = {} for line in salt.utils.itertools.split(out, "\n"): -@@ -3301,7 +3310,9 @@ def download(*packages, **kwargs): +@@ -3342,7 +3351,9 @@ def download(*packages, **kwargs): cmd = ["yumdownloader", "-q", "--destdir={}".format(CACHE_DIR)] cmd.extend(packages) @@ -68,7 +68,7 @@ index 3f855d255f..08dccafceb 100644 ret = {} for dld_result in os.listdir(CACHE_DIR): if not dld_result.endswith(".rpm"): -@@ -3377,7 +3388,7 @@ def _get_patches(installed_only=False): +@@ -3418,7 +3429,7 @@ def _get_patches(installed_only=False): patches = {} cmd = [_yum(), "--quiet", "updateinfo", "list", "all"] @@ -78,6 +78,6 @@ index 3f855d255f..08dccafceb 100644 for line in salt.utils.itertools.split(ret, os.linesep): -- -2.37.3 +2.39.2 diff --git a/add-migrated-state-and-gpg-key-management-functions-.patch b/add-migrated-state-and-gpg-key-management-functions-.patch index 10ea5e3..beffeaa 100644 --- a/add-migrated-state-and-gpg-key-management-functions-.patch +++ b/add-migrated-state-and-gpg-key-management-functions-.patch @@ -1,4 +1,4 @@ -From 97753443c2d782b61fd51457d13309405e8f12d8 Mon Sep 17 00:00:00 2001 +From c5236dadcffc24c00181c10ac4cf56020371c538 Mon Sep 17 00:00:00 2001 From: Alexander Graul Date: Tue, 18 Jan 2022 18:40:40 +0100 Subject: [PATCH] Add "migrated" state and GPG key management functions @@ -28,13 +28,13 @@ Convert test to pytests tests/pytests/unit/modules/test_yumpkg.py | 44 +- tests/pytests/unit/modules/test_zypperpkg.py | 45 +- tests/pytests/unit/states/test_pkgrepo.py | 448 +++++++++++++++++++ - 8 files changed, 1071 insertions(+), 4 deletions(-) + 8 files changed, 1070 insertions(+), 5 deletions(-) diff --git a/salt/modules/aptpkg.py b/salt/modules/aptpkg.py -index 544143d286..21ccc2a73c 100644 +index 3289f6604d..9885e9fb60 100644 --- a/salt/modules/aptpkg.py +++ b/salt/modules/aptpkg.py -@@ -2211,7 +2211,7 @@ def _parse_repo_keys_output(cmd_ret): +@@ -2197,7 +2197,7 @@ def _parse_repo_keys_output(cmd_ret): return ret @@ -43,7 +43,7 @@ index 544143d286..21ccc2a73c 100644 """ .. versionadded:: 2017.7.0 -@@ -2319,6 +2319,7 @@ def add_repo_key( +@@ -2305,6 +2305,7 @@ def add_repo_key( aptkey=True, keydir=None, keyfile=None, @@ -51,7 +51,7 @@ index 544143d286..21ccc2a73c 100644 ): """ .. versionadded:: 2017.7.0 -@@ -2372,7 +2373,6 @@ def add_repo_key( +@@ -2358,7 +2359,6 @@ def add_repo_key( if not salt.utils.path.which("apt-key"): aptkey = False cmd = ["apt-key"] @@ -60,10 +60,10 @@ index 544143d286..21ccc2a73c 100644 # If the keyid is provided or determined, check it against the existing # repo key ids to determine whether it needs to be imported. diff --git a/salt/modules/rpm_lowpkg.py b/salt/modules/rpm_lowpkg.py -index d65a46a703..c8e984c021 100644 +index 4cd137c258..b360ec8df3 100644 --- a/salt/modules/rpm_lowpkg.py +++ b/salt/modules/rpm_lowpkg.py -@@ -859,3 +859,154 @@ def checksum(*paths, **kwargs): +@@ -865,3 +865,154 @@ def checksum(*paths, **kwargs): ) return ret @@ -219,10 +219,10 @@ index d65a46a703..c8e984c021 100644 + cmd.extend(["-e", key]) + return __salt__["cmd.retcode"](cmd) == 0 diff --git a/salt/modules/yumpkg.py b/salt/modules/yumpkg.py -index 08dccafceb..46f0b1f613 100644 +index b362d30bf4..b2be251a40 100644 --- a/salt/modules/yumpkg.py +++ b/salt/modules/yumpkg.py -@@ -3494,3 +3494,91 @@ def services_need_restart(**kwargs): +@@ -3535,3 +3535,91 @@ def services_need_restart(**kwargs): services.add(service) return list(services) @@ -315,10 +315,10 @@ index 08dccafceb..46f0b1f613 100644 + """ + return __salt__["lowpkg.remove_gpg_key"](keyid, root) diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py -index c2452d6dec..4e3006a8cd 100644 +index 2da470bea3..318c871b37 100644 --- a/salt/modules/zypperpkg.py +++ b/salt/modules/zypperpkg.py -@@ -3142,3 +3142,91 @@ def services_need_restart(root=None, **kwargs): +@@ -3261,3 +3261,91 @@ def services_need_restart(root=None, **kwargs): services = zypper_output.split() return services @@ -411,7 +411,7 @@ index c2452d6dec..4e3006a8cd 100644 + """ + return __salt__["lowpkg.remove_gpg_key"](keyid, root) diff --git a/salt/states/pkgrepo.py b/salt/states/pkgrepo.py -index 358c927695..a777fe4a96 100644 +index 67a50c3ca0..c2d23f95bb 100644 --- a/salt/states/pkgrepo.py +++ b/salt/states/pkgrepo.py @@ -118,6 +118,7 @@ Using ``aptkey: False`` with ``keyserver`` and ``keyid``: @@ -422,7 +422,7 @@ index 358c927695..a777fe4a96 100644 import sys import salt.utils.data -@@ -714,3 +715,209 @@ def absent(name, **kwargs): +@@ -745,3 +746,209 @@ def absent(name, **kwargs): ret["comment"] = "Failed to remove repo {}".format(name) return ret @@ -633,19 +633,19 @@ index 358c927695..a777fe4a96 100644 + + return ret diff --git a/tests/pytests/unit/modules/test_yumpkg.py b/tests/pytests/unit/modules/test_yumpkg.py -index 99ec05b990..a495569c5d 100644 +index 1354ee5d2d..45c62d793d 100644 --- a/tests/pytests/unit/modules/test_yumpkg.py +++ b/tests/pytests/unit/modules/test_yumpkg.py -@@ -7,7 +7,7 @@ import salt.modules.rpm_lowpkg as rpm +@@ -9,7 +9,7 @@ import salt.modules.rpm_lowpkg as rpm import salt.modules.yumpkg as yumpkg import salt.utils.platform from salt.exceptions import CommandExecutionError, SaltInvocationError -from tests.support.mock import MagicMock, Mock, call, patch +from tests.support.mock import MagicMock, Mock, call, mock_open, patch - try: - import pytest -@@ -1911,6 +1911,48 @@ def test_get_repo_with_non_existent_repo(list_repos_var): + log = logging.getLogger(__name__) + +@@ -1908,6 +1908,48 @@ def test_get_repo_with_non_existent_repo(list_repos_var): assert ret == expected, ret @@ -695,24 +695,24 @@ index 99ec05b990..a495569c5d 100644 """ Tests that the proper CLI options are added when obsoletes=False diff --git a/tests/pytests/unit/modules/test_zypperpkg.py b/tests/pytests/unit/modules/test_zypperpkg.py -index 70bd837c5f..351a173b81 100644 +index 1e2d6ea443..91132b7277 100644 --- a/tests/pytests/unit/modules/test_zypperpkg.py +++ b/tests/pytests/unit/modules/test_zypperpkg.py -@@ -8,7 +8,8 @@ import os - import pytest +@@ -10,8 +10,8 @@ import pytest + import salt.modules.pkg_resource as pkg_resource import salt.modules.zypperpkg as zypper +-from salt.exceptions import CommandExecutionError -from tests.support.mock import MagicMock, patch -+from salt.exceptions import SaltInvocationError ++from salt.exceptions import CommandExecutionError, SaltInvocationError +from tests.support.mock import MagicMock, mock_open, patch @pytest.fixture -@@ -211,3 +212,45 @@ def test_pkg_list_holds(): - ret = zypper.list_holds() - assert len(ret) == 1 - assert "bar-2:2.3.4-2.1.*" in ret -+ +@@ -354,3 +354,44 @@ def test_dist_upgrade_failure(): + + assert exc.exception.info["changes"] == {} + assert exc.exception.info["result"]["stdout"] == zypper_output + +def test_get_repo_keys(): + salt_mock = {"lowpkg.list_gpg_keys": MagicMock(return_value=True)} @@ -755,13 +755,13 @@ index 70bd837c5f..351a173b81 100644 + assert zypper.del_repo_key(keyid="keyid", root="/mnt") + salt_mock["lowpkg.remove_gpg_key"].assert_called_once_with("keyid", "/mnt") diff --git a/tests/pytests/unit/states/test_pkgrepo.py b/tests/pytests/unit/states/test_pkgrepo.py -index daa913bcc2..cbb12cfb9b 100644 +index c572583d19..5f540bd245 100644 --- a/tests/pytests/unit/states/test_pkgrepo.py +++ b/tests/pytests/unit/states/test_pkgrepo.py -@@ -51,3 +51,451 @@ def test_update_key_url(): - assert ret["changes"] == { - "key_url": {"old": kwargs["key_url"], "new": changed_kwargs["key_url"]} - } +@@ -72,3 +72,451 @@ def test_managed_insecure_key(): + ret["comment"] + == "Cannot have 'key_url' using http with 'allow_insecure_key' set to True" + ) + + +def test__normalize_repo_suse(): @@ -1211,6 +1211,6 @@ index daa913bcc2..cbb12cfb9b 100644 + "comment": "There are keys or repositories to migrate or drop", + } -- -2.37.3 +2.39.2 diff --git a/add-publish_batch-to-clearfuncs-exposed-methods.patch b/add-publish_batch-to-clearfuncs-exposed-methods.patch index c4e22cc..9effdce 100644 --- a/add-publish_batch-to-clearfuncs-exposed-methods.patch +++ b/add-publish_batch-to-clearfuncs-exposed-methods.patch @@ -1,4 +1,4 @@ -From e6f6b011849536c5ff9a9bdef56e900ed5a7fb1d Mon Sep 17 00:00:00 2001 +From 3ef2071daf7a415f2c43e1339affe2b7cad93b3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?= Date: Thu, 28 May 2020 09:37:08 +0100 @@ -9,10 +9,10 @@ Subject: [PATCH] Add publish_batch to ClearFuncs exposed methods 1 file changed, 1 insertion(+) diff --git a/salt/master.py b/salt/master.py -index 705a1bc2fb..7f41ffe77b 100644 +index 2a526b4f21..a0552fa232 100644 --- a/salt/master.py +++ b/salt/master.py -@@ -1952,6 +1952,7 @@ class ClearFuncs(TransportMethods): +@@ -1960,6 +1960,7 @@ class ClearFuncs(TransportMethods): expose_methods = ( "ping", "publish", @@ -21,6 +21,6 @@ index 705a1bc2fb..7f41ffe77b 100644 "mk_token", "wheel", -- -2.37.3 +2.39.2 diff --git a/add-salt-ssh-support-with-venv-salt-minion-3004-493.patch b/add-salt-ssh-support-with-venv-salt-minion-3004-493.patch index 58dd071..dc38bd4 100644 --- a/add-salt-ssh-support-with-venv-salt-minion-3004-493.patch +++ b/add-salt-ssh-support-with-venv-salt-minion-3004-493.patch @@ -1,4 +1,4 @@ -From c683ceaf9321a646d32e3b2b5fca705563fe8e73 Mon Sep 17 00:00:00 2001 +From 3fd6c0c6793632c819fb5f8fb3b3538463eaaccc Mon Sep 17 00:00:00 2001 From: Victor Zhestkov Date: Thu, 24 Feb 2022 16:52:24 +0300 Subject: [PATCH] Add salt-ssh support with venv-salt-minion - 3004 @@ -146,7 +146,7 @@ index cc18f49a9e..e050f43caf 100644 def makeRecord( self, diff --git a/salt/client/ssh/__init__.py b/salt/client/ssh/__init__.py -index ad2796bc87..6db2dfcbb0 100644 +index 19089ce8ad..e6837df4e5 100644 --- a/salt/client/ssh/__init__.py +++ b/salt/client/ssh/__init__.py @@ -6,11 +6,13 @@ import base64 @@ -732,7 +732,7 @@ index 72a5e54401..32f8a7702c 100644 ): err = ( diff --git a/salt/netapi/__init__.py b/salt/netapi/__init__.py -index 7127dc2b3c..4a80697648 100644 +index a89c1a19af..8a28c48460 100644 --- a/salt/netapi/__init__.py +++ b/salt/netapi/__init__.py @@ -79,6 +79,7 @@ class NetapiClient: @@ -743,7 +743,7 @@ index 7127dc2b3c..4a80697648 100644 def _is_master_running(self): """ -@@ -238,7 +239,7 @@ class NetapiClient: +@@ -245,7 +246,7 @@ class NetapiClient: with salt.client.ssh.client.SSHClient( mopts=self.opts, disable_custom_roster=True ) as client: @@ -777,10 +777,10 @@ index fc7339d785..ea23d550d7 100644 def _gen_back(self): """ diff --git a/tests/unit/test_loader.py b/tests/unit/test_loader.py -index 66ba3d4e05..412d412398 100644 +index cf33903320..1b616375b3 100644 --- a/tests/unit/test_loader.py +++ b/tests/unit/test_loader.py -@@ -1696,7 +1696,7 @@ class LazyLoaderRefreshFileMappingTest(TestCase): +@@ -1697,7 +1697,7 @@ class LazyLoaderRefreshFileMappingTest(TestCase): cls.funcs = salt.loader.minion_mods(cls.opts, utils=cls.utils, proxy=cls.proxy) def setUp(self): @@ -790,6 +790,6 @@ index 66ba3d4e05..412d412398 100644 self.LOADER_CLASS = LazyLoaderMock -- -2.37.3 +2.39.2 diff --git a/add-sleep-on-exception-handling-on-minion-connection.patch b/add-sleep-on-exception-handling-on-minion-connection.patch index 83a3ca8..edda8d7 100644 --- a/add-sleep-on-exception-handling-on-minion-connection.patch +++ b/add-sleep-on-exception-handling-on-minion-connection.patch @@ -1,4 +1,4 @@ -From b772fc7540cea4088ecac0bdc0e24d2be84bfcad Mon Sep 17 00:00:00 2001 +From bad9e783e1a6923d85bdb1477a2e9766887a511e Mon Sep 17 00:00:00 2001 From: Victor Zhestkov <35733135+vzhestkov@users.noreply.github.com> Date: Thu, 18 Feb 2021 14:49:38 +0300 Subject: [PATCH] Add sleep on exception handling on minion connection @@ -12,7 +12,7 @@ Subject: [PATCH] Add sleep on exception handling on minion connection 1 file changed, 6 insertions(+) diff --git a/salt/minion.py b/salt/minion.py -index 16452facf4..780b397e83 100644 +index 2f905e4a4f..c3b65f16c3 100644 --- a/salt/minion.py +++ b/salt/minion.py @@ -1123,6 +1123,9 @@ class MinionManager(MinionBase): @@ -36,6 +36,6 @@ index 16452facf4..780b397e83 100644 # Multi Master Tune In def tune_in(self): -- -2.37.3 +2.39.2 diff --git a/add-standalone-configuration-file-for-enabling-packa.patch b/add-standalone-configuration-file-for-enabling-packa.patch index 8cf92a5..7000574 100644 --- a/add-standalone-configuration-file-for-enabling-packa.patch +++ b/add-standalone-configuration-file-for-enabling-packa.patch @@ -1,4 +1,4 @@ -From 875fb95ae468042005cd0db463f13a9315c1e756 Mon Sep 17 00:00:00 2001 +From 94e702e83c05814296ea8987a722b71e99117360 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?= Date: Wed, 22 May 2019 13:00:46 +0100 @@ -21,6 +21,6 @@ index 0000000000..94d05fb2ee + - /usr/share/salt-formulas/states + - /srv/salt -- -2.37.3 +2.39.2 diff --git a/add-support-for-gpgautoimport-539.patch b/add-support-for-gpgautoimport-539.patch index 804c62c..d1176dc 100644 --- a/add-support-for-gpgautoimport-539.patch +++ b/add-support-for-gpgautoimport-539.patch @@ -1,4 +1,4 @@ -From f92891c007ee55d9ccc2d7b3da53e4e0a6fc94c3 Mon Sep 17 00:00:00 2001 +From 2e103365c50fe42a72de3e9d57c3fdbee47454aa Mon Sep 17 00:00:00 2001 From: Michael Calmer Date: Fri, 8 Jul 2022 10:15:37 +0200 Subject: [PATCH] add support for gpgautoimport (#539) @@ -18,10 +18,10 @@ Subject: [PATCH] add support for gpgautoimport (#539) 2 files changed, 140 insertions(+), 31 deletions(-) diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py -index cbfbc4b78d..2c36e2968a 100644 +index 318c871b37..051f8f72c7 100644 --- a/salt/modules/zypperpkg.py +++ b/salt/modules/zypperpkg.py -@@ -589,7 +589,7 @@ def list_upgrades(refresh=True, root=None, **kwargs): +@@ -623,7 +623,7 @@ def list_upgrades(refresh=True, root=None, **kwargs): salt '*' pkg.list_upgrades """ if refresh: @@ -30,7 +30,7 @@ index cbfbc4b78d..2c36e2968a 100644 ret = dict() cmd = ["list-updates"] -@@ -703,7 +703,7 @@ def info_available(*names, **kwargs): +@@ -737,7 +737,7 @@ def info_available(*names, **kwargs): # Refresh db before extracting the latest package if kwargs.get("refresh", True): @@ -39,15 +39,15 @@ index cbfbc4b78d..2c36e2968a 100644 pkg_info = [] batch = names[:] -@@ -1393,7 +1393,6 @@ def mod_repo(repo, **kwargs): - cmd_opt.append("--name='{}'".format(kwargs.get("humanname"))) +@@ -1439,7 +1439,6 @@ def mod_repo(repo, **kwargs): + cmd_opt.append(kwargs.get("name")) if kwargs.get("gpgautoimport") is True: - global_cmd_opt.append("--gpg-auto-import-keys") call_refresh = True if cmd_opt: -@@ -1405,8 +1404,8 @@ def mod_repo(repo, **kwargs): +@@ -1451,8 +1450,8 @@ def mod_repo(repo, **kwargs): # when used with "zypper ar --refresh" or "zypper mr --refresh" # --gpg-auto-import-keys is not doing anything # so we need to specifically refresh here with --gpg-auto-import-keys @@ -58,7 +58,7 @@ index cbfbc4b78d..2c36e2968a 100644 elif not added and not cmd_opt: comment = "Specified arguments did not result in modification of repo" -@@ -1417,7 +1416,7 @@ def mod_repo(repo, **kwargs): +@@ -1463,7 +1462,7 @@ def mod_repo(repo, **kwargs): return repo @@ -67,7 +67,7 @@ index cbfbc4b78d..2c36e2968a 100644 """ Trigger a repository refresh by calling ``zypper refresh``. Refresh will run with ``--force`` if the "force=True" flag is passed on the CLI or -@@ -1428,6 +1427,17 @@ def refresh_db(force=None, root=None): +@@ -1474,6 +1473,17 @@ def refresh_db(force=None, root=None): {'': Bool} @@ -85,7 +85,7 @@ index cbfbc4b78d..2c36e2968a 100644 root operate on a different root directory. -@@ -1448,11 +1458,22 @@ def refresh_db(force=None, root=None): +@@ -1494,11 +1504,22 @@ def refresh_db(force=None, root=None): salt.utils.pkg.clear_rtag(__opts__) ret = {} refresh_opts = ["refresh"] @@ -109,7 +109,7 @@ index cbfbc4b78d..2c36e2968a 100644 for line in out.splitlines(): if not line: -@@ -1637,7 +1658,7 @@ def install( +@@ -1683,7 +1704,7 @@ def install( 'arch': ''}}} """ if refresh: @@ -118,7 +118,7 @@ index cbfbc4b78d..2c36e2968a 100644 try: pkg_params, pkg_type = __salt__["pkg_resource.parse_targets"]( -@@ -1932,7 +1953,7 @@ def upgrade( +@@ -1980,7 +2001,7 @@ def upgrade( cmd_update.insert(0, "--no-gpg-checks") if refresh: @@ -127,7 +127,7 @@ index cbfbc4b78d..2c36e2968a 100644 if dryrun: cmd_update.append("--dry-run") -@@ -2759,7 +2780,7 @@ def search(criteria, refresh=False, **kwargs): +@@ -2808,7 +2829,7 @@ def search(criteria, refresh=False, **kwargs): root = kwargs.get("root", None) if refresh: @@ -136,7 +136,7 @@ index cbfbc4b78d..2c36e2968a 100644 cmd = ["search"] if kwargs.get("match") == "exact": -@@ -2910,7 +2931,7 @@ def download(*packages, **kwargs): +@@ -2959,7 +2980,7 @@ def download(*packages, **kwargs): refresh = kwargs.get("refresh", False) if refresh: @@ -145,7 +145,7 @@ index cbfbc4b78d..2c36e2968a 100644 pkg_ret = {} for dld_result in ( -@@ -3062,7 +3083,7 @@ def list_patches(refresh=False, root=None, **kwargs): +@@ -3111,7 +3132,7 @@ def list_patches(refresh=False, root=None, **kwargs): salt '*' pkg.list_patches """ if refresh: @@ -154,7 +154,7 @@ index cbfbc4b78d..2c36e2968a 100644 return _get_patches(root=root) -@@ -3156,7 +3177,7 @@ def resolve_capabilities(pkgs, refresh=False, root=None, **kwargs): +@@ -3205,7 +3226,7 @@ def resolve_capabilities(pkgs, refresh=False, root=None, **kwargs): salt '*' pkg.resolve_capabilities resolve_capabilities=True w3m_ssl """ if refresh: @@ -164,10 +164,10 @@ index cbfbc4b78d..2c36e2968a 100644 ret = list() for pkg in pkgs: diff --git a/tests/unit/modules/test_zypperpkg.py b/tests/unit/modules/test_zypperpkg.py -index fea6eeb004..3f1560a385 100644 +index e85c93da3b..f5b6d74b6f 100644 --- a/tests/unit/modules/test_zypperpkg.py +++ b/tests/unit/modules/test_zypperpkg.py -@@ -358,7 +358,12 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): +@@ -377,7 +377,12 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): run_out = {"stderr": "", "stdout": "\n".join(ref_out), "retcode": 0} zypper_mock = MagicMock(return_value=run_out) @@ -181,7 +181,7 @@ index fea6eeb004..3f1560a385 100644 with patch.dict(zypper.__salt__, {"cmd.run_all": zypper_mock}): with patch.object(salt.utils.pkg, "clear_rtag", Mock()): result = zypper.refresh_db() -@@ -376,6 +381,73 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): +@@ -395,6 +400,73 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): zypper_mock.assert_called_with( ["zypper", "--non-interactive", "refresh", "--force"], **call_kwargs ) @@ -255,7 +255,7 @@ index fea6eeb004..3f1560a385 100644 def test_info_installed(self): """ -@@ -1555,18 +1627,23 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): +@@ -2082,18 +2154,23 @@ Repository 'DUMMY' not found by its alias, number, or URI. url = self.new_repo_config["url"] name = self.new_repo_config["name"] @@ -281,7 +281,7 @@ index fea6eeb004..3f1560a385 100644 def test_repo_noadd_nomod_ref(self): """ -@@ -1585,15 +1662,17 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): +@@ -2112,15 +2189,17 @@ Repository 'DUMMY' not found by its alias, number, or URI. "salt.modules.zypperpkg", **self.zypper_patcher_config ) @@ -304,7 +304,7 @@ index fea6eeb004..3f1560a385 100644 def test_repo_add_mod_ref(self): """ -@@ -1606,10 +1685,10 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): +@@ -2133,10 +2212,10 @@ Repository 'DUMMY' not found by its alias, number, or URI. zypper_patcher = patch.multiple( "salt.modules.zypperpkg", **self.zypper_patcher_config ) @@ -317,7 +317,7 @@ index fea6eeb004..3f1560a385 100644 zypper.mod_repo( name, **{"url": url, "refresh": True, "gpgautoimport": True} ) -@@ -1617,11 +1696,17 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): +@@ -2144,11 +2223,17 @@ Repository 'DUMMY' not found by its alias, number, or URI. zypper.__zypper__(root=None).xml.call.call_args_list, [ call("ar", url, name), @@ -337,7 +337,7 @@ index fea6eeb004..3f1560a385 100644 ) def test_repo_noadd_mod_ref(self): -@@ -1641,16 +1726,19 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): +@@ -2168,16 +2253,19 @@ Repository 'DUMMY' not found by its alias, number, or URI. "salt.modules.zypperpkg", **self.zypper_patcher_config ) @@ -364,6 +364,6 @@ index fea6eeb004..3f1560a385 100644 def test_wildcard_to_query_match_all(self): -- -2.37.3 +2.39.2 diff --git a/add-support-for-name-pkgs-and-diff_attr-parameters-t.patch b/add-support-for-name-pkgs-and-diff_attr-parameters-t.patch deleted file mode 100644 index f6d9d17..0000000 --- a/add-support-for-name-pkgs-and-diff_attr-parameters-t.patch +++ /dev/null @@ -1,1056 +0,0 @@ -From 0165c300ec0f7ac70b274b81a8857c2e6d71552d Mon Sep 17 00:00:00 2001 -From: Alexander Graul -Date: Thu, 7 Jul 2022 11:26:34 +0200 -Subject: [PATCH] Add support for name, pkgs and diff_attr parameters to - zypperpkg.upgrade()/yumpkg.upgrade() - backport 3004 (#538) - -* Migrate zypper.upgrade tests to pytest - -(cherry picked from commit ecce005b543f66198c7ac118966254dd3d60682f) - -* Add names and pkgs parameters to zypper.upgrade - -Fixes https://github.com/saltstack/salt/issues/62030 - -(cherry picked from commit 19ebb40dc4538c983721a8746a201b7f1300c2f7) - -* Don't turn attr="all" into a list - -pkg_resource.format_pkg_list expects its `attr` argument to be either a -list of attributes or the string "all" to indicate all available -attributes should be used for formatting. - -Fixes: https://github.com/saltstack/salt/issues/62032 -(cherry picked from commit 05482da89b91442235d3cc2889e59ac3722a7fae) - -* Add diff_attr parameter to zypper/yum upgrade - -diff_attr works just like it does for pkg.install. Having the -option to return additional attributes can remove the need for a -follow-up list_pkgs call. - -Fixes: https://github.com/saltstack/salt/issues/62031 -(cherry picked from commit 20ffffe3be6c7d94e9cc3338a57bbf5014f33d93) ---- - changelog/62030.fixed | 1 + - changelog/62031.added | 1 + - changelog/62032.fixed | 1 + - salt/modules/yumpkg.py | 7 +- - salt/modules/zypperpkg.py | 76 ++- - tests/pytests/unit/modules/test_zypperpkg.py | 277 ++++++++++- - tests/unit/modules/test_zypperpkg.py | 482 ------------------- - 7 files changed, 355 insertions(+), 490 deletions(-) - create mode 100644 changelog/62030.fixed - create mode 100644 changelog/62031.added - create mode 100644 changelog/62032.fixed - -diff --git a/changelog/62030.fixed b/changelog/62030.fixed -new file mode 100644 -index 0000000000..bd60463606 ---- /dev/null -+++ b/changelog/62030.fixed -@@ -0,0 +1 @@ -+Fix inconsitency regarding name and pkgs parameters between zypperpkg.upgrade() and yumpkg.upgrade() -diff --git a/changelog/62031.added b/changelog/62031.added -new file mode 100644 -index 0000000000..f0b66ff96f ---- /dev/null -+++ b/changelog/62031.added -@@ -0,0 +1 @@ -+Add `diff_attr` parameter to pkg.upgrade() (zypper/yum). -diff --git a/changelog/62032.fixed b/changelog/62032.fixed -new file mode 100644 -index 0000000000..ceb3cc89b9 ---- /dev/null -+++ b/changelog/62032.fixed -@@ -0,0 +1 @@ -+Fix attr=all handling in pkg.list_pkgs() (yum/zypper). -diff --git a/salt/modules/yumpkg.py b/salt/modules/yumpkg.py -index f52e084346..fcfc5d4045 100644 ---- a/salt/modules/yumpkg.py -+++ b/salt/modules/yumpkg.py -@@ -735,7 +735,7 @@ def list_pkgs(versions_as_list=False, **kwargs): - return {} - - attr = kwargs.get("attr") -- if attr is not None: -+ if attr is not None and attr != "all": - attr = salt.utils.args.split_input(attr) - - contextkey = "pkg.list_pkgs" -@@ -1844,6 +1844,7 @@ def upgrade( - normalize=True, - minimal=False, - obsoletes=True, -+ diff_attr=None, - **kwargs - ): - """ -@@ -2000,7 +2001,7 @@ def upgrade( - if salt.utils.data.is_true(refresh): - refresh_db(**kwargs) - -- old = list_pkgs() -+ old = list_pkgs(attr=diff_attr) - - targets = [] - if name or pkgs: -@@ -2032,7 +2033,7 @@ def upgrade( - cmd.extend(targets) - result = _call_yum(cmd) - __context__.pop("pkg.list_pkgs", None) -- new = list_pkgs() -+ new = list_pkgs(attr=diff_attr) - ret = salt.utils.data.compare_dicts(old, new) - - if result["retcode"] != 0: -diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py -index 4e3006a8cd..cbfbc4b78d 100644 ---- a/salt/modules/zypperpkg.py -+++ b/salt/modules/zypperpkg.py -@@ -939,7 +939,7 @@ def list_pkgs(versions_as_list=False, root=None, includes=None, **kwargs): - return {} - - attr = kwargs.get("attr") -- if attr is not None: -+ if attr is not None and attr != "all": - attr = salt.utils.args.split_input(attr) - - includes = includes if includes else [] -@@ -1791,6 +1791,8 @@ def install( - - - def upgrade( -+ name=None, -+ pkgs=None, - refresh=True, - dryrun=False, - dist_upgrade=False, -@@ -1800,6 +1802,7 @@ def upgrade( - skip_verify=False, - no_recommends=False, - root=None, -+ diff_attr=None, - **kwargs - ): # pylint: disable=unused-argument - """ -@@ -1819,6 +1822,27 @@ def upgrade( - - Run a full system upgrade, a zypper upgrade - -+ name -+ The name of the package to be installed. Note that this parameter is -+ ignored if ``pkgs`` is passed or if ``dryrun`` is set to True. -+ -+ CLI Example: -+ -+ .. code-block:: bash -+ -+ salt '*' pkg.install name= -+ -+ pkgs -+ A list of packages to install from a software repository. Must be -+ passed as a python list. Note that this parameter is ignored if -+ ``dryrun`` is set to True. -+ -+ CLI Examples: -+ -+ .. code-block:: bash -+ -+ salt '*' pkg.install pkgs='["foo", "bar"]' -+ - refresh - force a refresh if set to True (default). - If set to False it depends on zypper if a refresh is -@@ -1850,6 +1874,24 @@ def upgrade( - root - Operate on a different root directory. - -+ diff_attr: -+ If a list of package attributes is specified, returned value will -+ contain them, eg.:: -+ -+ {'': { -+ 'old': { -+ 'version': '', -+ 'arch': ''}, -+ -+ 'new': { -+ 'version': '', -+ 'arch': ''}}} -+ -+ Valid attributes are: ``epoch``, ``version``, ``release``, ``arch``, -+ ``install_date``, ``install_date_time_t``. -+ -+ If ``all`` is specified, all valid attributes will be returned. -+ - Returns a dictionary containing the changes: - - .. code-block:: python -@@ -1857,11 +1899,27 @@ def upgrade( - {'': {'old': '', - 'new': ''}} - -+ If an attribute list is specified in ``diff_attr``, the dict will also contain -+ any specified attribute, eg.:: -+ -+ .. code-block:: python -+ -+ {'': { -+ 'old': { -+ 'version': '', -+ 'arch': ''}, -+ -+ 'new': { -+ 'version': '', -+ 'arch': ''}}} -+ - CLI Example: - - .. code-block:: bash - - salt '*' pkg.upgrade -+ salt '*' pkg.upgrade name=mypackage -+ salt '*' pkg.upgrade pkgs='["package1", "package2"]' - salt '*' pkg.upgrade dist_upgrade=True fromrepo='["MyRepoName"]' novendorchange=True - salt '*' pkg.upgrade dist_upgrade=True dryrun=True - """ -@@ -1897,12 +1955,24 @@ def upgrade( - allowvendorchange, novendorchange - ).noraise.call(*cmd_update + ["--debug-solver"]) - -- old = list_pkgs(root=root) -+ if not dist_upgrade: -+ if name or pkgs: -+ try: -+ (pkg_params, _) = __salt__["pkg_resource.parse_targets"]( -+ name=name, pkgs=pkgs, sources=None, **kwargs -+ ) -+ if pkg_params: -+ cmd_update.extend(pkg_params.keys()) -+ -+ except MinionError as exc: -+ raise CommandExecutionError(exc) -+ -+ old = list_pkgs(root=root, attr=diff_attr) - __zypper__(systemd_scope=_systemd_scope(), root=root).allow_vendor_change( - allowvendorchange, novendorchange - ).noraise.call(*cmd_update) - _clean_cache() -- new = list_pkgs(root=root) -+ new = list_pkgs(root=root, attr=diff_attr) - ret = salt.utils.data.compare_dicts(old, new) - - if __zypper__.exit_code not in __zypper__.SUCCESS_EXIT_CODES: -diff --git a/tests/pytests/unit/modules/test_zypperpkg.py b/tests/pytests/unit/modules/test_zypperpkg.py -index 351a173b81..84dc7a10b4 100644 ---- a/tests/pytests/unit/modules/test_zypperpkg.py -+++ b/tests/pytests/unit/modules/test_zypperpkg.py -@@ -4,17 +4,31 @@ - - - import os -+import textwrap - - import pytest - import salt.modules.pkg_resource as pkg_resource - import salt.modules.zypperpkg as zypper --from salt.exceptions import SaltInvocationError -+from salt.exceptions import CommandExecutionError, SaltInvocationError - from tests.support.mock import MagicMock, mock_open, patch - - - @pytest.fixture - def configure_loader_modules(): -- return {zypper: {"rpm": None}, pkg_resource: {}} -+ return { -+ zypper: { -+ "rpm": None, -+ "_systemd_scope": MagicMock(return_value=False), -+ "osrelease_info": [15, 3], -+ "__salt__": {"pkg_resource.parse_targets": pkg_resource.parse_targets}, -+ }, -+ pkg_resource: {"__grains__": {"os": "SUSE"}}, -+ } -+ -+ -+@pytest.fixture(autouse=True) -+def fresh_zypper_instance(): -+ zypper.__zypper__ = zypper._Zypper() - - - def test_list_pkgs_no_context(): -@@ -254,3 +268,262 @@ def test_del_repo_key(): - with patch.dict(zypper.__salt__, salt_mock): - assert zypper.del_repo_key(keyid="keyid", root="/mnt") - salt_mock["lowpkg.remove_gpg_key"].assert_called_once_with("keyid", "/mnt") -+ -+@pytest.mark.parametrize( -+ "zypper_version,lowpkg_version_cmp,expected_inst_avc,expected_dup_avc", -+ [ -+ ("0.5", [-1, -1], False, False), -+ ("1.11.34", [0, -1], False, True), -+ ("1.14.8", [0, 0], True, True), -+ ], -+) -+def test_refresh_zypper_flags( -+ zypper_version, lowpkg_version_cmp, expected_inst_avc, expected_dup_avc -+): -+ with patch( -+ "salt.modules.zypperpkg.version", MagicMock(return_value=zypper_version) -+ ), patch.dict( -+ zypper.__salt__, -+ {"lowpkg.version_cmp": MagicMock(side_effect=lowpkg_version_cmp)}, -+ ): -+ _zypper = zypper._Zypper() -+ _zypper.refresh_zypper_flags() -+ assert _zypper.inst_avc == expected_inst_avc -+ assert _zypper.dup_avc == expected_dup_avc -+ -+ -+@pytest.mark.parametrize( -+ "inst_avc,dup_avc,avc,allowvendorchange_param,novendorchange_param,expected", -+ [ -+ # inst_avc = True, dup_avc = True -+ (True, True, False, False, False, True), -+ (True, True, False, True, False, True), -+ (True, True, False, False, True, False), -+ (True, True, False, True, True, True), -+ # inst_avc = False, dup_avc = True -+ (False, True, False, False, False, True), -+ (False, True, False, True, False, True), -+ (False, True, False, False, True, False), -+ (False, True, False, True, True, True), -+ # inst_avc = False, dup_avc = False -+ (False, False, False, False, False, False), -+ (False, False, False, True, False, False), -+ (False, False, False, False, True, False), -+ (False, False, False, True, True, False), -+ ], -+) -+@patch("salt.modules.zypperpkg._Zypper.refresh_zypper_flags", MagicMock()) -+def test_allow_vendor_change( -+ inst_avc, -+ dup_avc, -+ avc, -+ allowvendorchange_param, -+ novendorchange_param, -+ expected, -+): -+ _zypper = zypper._Zypper() -+ _zypper.inst_avc = inst_avc -+ _zypper.dup_avc = dup_avc -+ _zypper.avc = avc -+ _zypper.allow_vendor_change(allowvendorchange_param, novendorchange_param) -+ assert _zypper.avc == expected -+ -+ -+@pytest.mark.parametrize( -+ "package,pre_version,post_version,fromrepo_param,name_param,pkgs_param,diff_attr_param", -+ [ -+ ("vim", "1.1", "1.2", [], "", [], "all"), -+ ("kernel-default", "1.1", "1.1,1.2", ["dummy", "dummy2"], "", [], None), -+ ("vim", "1.1", "1.2", [], "vim", [], None), -+ ], -+) -+@patch.object(zypper, "refresh_db", MagicMock(return_value=True)) -+def test_upgrade( -+ package, -+ pre_version, -+ post_version, -+ fromrepo_param, -+ name_param, -+ pkgs_param, -+ diff_attr_param, -+): -+ with patch( -+ "salt.modules.zypperpkg.__zypper__.noraise.call" -+ ) as zypper_mock, patch.object( -+ zypper, -+ "list_pkgs", -+ MagicMock(side_effect=[{package: pre_version}, {package: post_version}]), -+ ) as list_pkgs_mock: -+ expected_call = ["update", "--auto-agree-with-licenses"] -+ for repo in fromrepo_param: -+ expected_call.extend(["--repo", repo]) -+ -+ if pkgs_param: -+ expected_call.extend(pkgs_param) -+ elif name_param: -+ expected_call.append(name_param) -+ -+ result = zypper.upgrade( -+ name=name_param, -+ pkgs=pkgs_param, -+ fromrepo=fromrepo_param, -+ diff_attr=diff_attr_param, -+ ) -+ zypper_mock.assert_any_call(*expected_call) -+ assert result == {package: {"old": pre_version, "new": post_version}} -+ list_pkgs_mock.assert_any_call(root=None, attr=diff_attr_param) -+ -+ -+@pytest.mark.parametrize( -+ "package,pre_version,post_version,fromrepo_param", -+ [ -+ ("vim", "1.1", "1.2", []), -+ ("emacs", "1.1", "1.2", ["Dummy", "Dummy2"]), -+ ], -+) -+@patch.object(zypper, "refresh_db", MagicMock(return_value=True)) -+def test_dist_upgrade(package, pre_version, post_version, fromrepo_param): -+ with patch( -+ "salt.modules.zypperpkg.__zypper__.noraise.call" -+ ) as zypper_mock, patch.object( -+ zypper, -+ "list_pkgs", -+ MagicMock(side_effect=[{package: pre_version}, {package: post_version}]), -+ ): -+ expected_call = ["dist-upgrade", "--auto-agree-with-licenses"] -+ -+ for repo in fromrepo_param: -+ expected_call.extend(["--from", repo]) -+ -+ result = zypper.upgrade(dist_upgrade=True, fromrepo=fromrepo_param) -+ zypper_mock.assert_any_call(*expected_call) -+ assert result == {package: {"old": pre_version, "new": post_version}} -+ -+ -+@pytest.mark.parametrize( -+ "package,pre_version,post_version,dup_avc,novendorchange_param,allowvendorchange_param,vendor_change", -+ [ -+ # dup_avc = True, both params = default -> no vendor change -+ ("vim", "1.1", "1.2", True, True, False, False), -+ # dup_avc = True, allowvendorchange = True -> vendor change -+ ( -+ "emacs", -+ "1.1", -+ "1.2", -+ True, -+ True, -+ True, -+ True, -+ ), -+ # dup_avc = True, novendorchange = False -> vendor change -+ ("joe", "1.1", "1.2", True, False, False, True), -+ # dup_avc = True, both params = toggled -> vendor change -+ ("kate", "1.1", "1.2", True, False, True, True), -+ # dup_avc = False -> no vendor change -+ ( -+ "gedit", -+ "1.1", -+ "1.2", -+ False, -+ False, -+ True, -+ False -+ ), -+ ], -+) -+@patch.object(zypper, "refresh_db", MagicMock(return_value=True)) -+def test_dist_upgrade_vendorchange( -+ package, -+ pre_version, -+ post_version, -+ dup_avc, -+ novendorchange_param, -+ allowvendorchange_param, -+ vendor_change -+): -+ cmd_run_mock = MagicMock(return_value={"retcode": 0, "stdout": None}) -+ with patch.object( -+ zypper, -+ "list_pkgs", -+ MagicMock(side_effect=[{package: pre_version}, {package: post_version}]), -+ ), patch("salt.modules.zypperpkg.__zypper__.refresh_zypper_flags",), patch.dict( -+ zypper.__salt__, {"cmd.run_all": cmd_run_mock} -+ ): -+ expected_cmd = ["zypper", "--non-interactive", "--no-refresh", "dist-upgrade"] -+ # --allow-vendor-change is injected right after "dist-upgrade" -+ if vendor_change: -+ expected_cmd.append("--allow-vendor-change") -+ expected_cmd.append("--auto-agree-with-licenses") -+ -+ zypper.__zypper__.dup_avc = dup_avc -+ zypper.upgrade( -+ dist_upgrade=True, -+ allowvendorchange=allowvendorchange_param, -+ novendorchange=novendorchange_param, -+ ) -+ cmd_run_mock.assert_any_call( -+ expected_cmd, output_loglevel="trace", python_shell=False, env={} -+ ) -+ -+ -+@pytest.mark.parametrize( -+ "package,pre_version,post_version,fromrepo_param", -+ [ -+ ("vim", "1.1", "1.1", []), -+ ("emacs", "1.1", "1.1", ["Dummy", "Dummy2"]), -+ ], -+) -+@patch.object(zypper, "refresh_db", MagicMock(return_value=True)) -+def test_dist_upgrade_dry_run(package, pre_version, post_version, fromrepo_param): -+ with patch( -+ "salt.modules.zypperpkg.__zypper__.noraise.call" -+ ) as zypper_mock, patch.object( -+ zypper, -+ "list_pkgs", -+ MagicMock(side_effect=[{package: pre_version}, {package: post_version}]), -+ ): -+ expected_call = ["dist-upgrade", "--auto-agree-with-licenses", "--dry-run"] -+ -+ for repo in fromrepo_param: -+ expected_call.extend(["--from", repo]) -+ -+ zypper.upgrade(dist_upgrade=True, dryrun=True, fromrepo=fromrepo_param) -+ zypper_mock.assert_any_call(*expected_call) -+ # dryrun=True causes two calls, one with a trailing --debug-solver flag -+ expected_call.append("--debug-solver") -+ zypper_mock.assert_any_call(*expected_call) -+ -+ -+@patch.object(zypper, "refresh_db", MagicMock(return_value=True)) -+def test_dist_upgrade_failure(): -+ zypper_output = textwrap.dedent( -+ """\ -+ Loading repository data... -+ Reading installed packages... -+ Computing distribution upgrade... -+ Use 'zypper repos' to get the list of defined repositories. -+ Repository 'DUMMY' not found by its alias, number, or URI. -+ """ -+ ) -+ call_spy = MagicMock() -+ zypper_mock = MagicMock() -+ zypper_mock.stdout = zypper_output -+ zypper_mock.stderr = "" -+ zypper_mock.exit_code = 3 -+ zypper_mock.noraise.call = call_spy -+ with patch("salt.modules.zypperpkg.__zypper__", zypper_mock), patch.object( -+ zypper, "list_pkgs", MagicMock(side_effect=[{"vim": 1.1}, {"vim": 1.1}]) -+ ): -+ expected_call = [ -+ "dist-upgrade", -+ "--auto-agree-with-licenses", -+ "--from", -+ "Dummy", -+ ] -+ -+ with pytest.raises(CommandExecutionError) as exc: -+ zypper.upgrade(dist_upgrade=True, fromrepo=["Dummy"]) -+ call_spy.assert_called_with(*expected_call) -+ -+ assert exc.exception.info["changes"] == {} -+ assert exc.exception.info["result"]["stdout"] == zypper_output -diff --git a/tests/unit/modules/test_zypperpkg.py b/tests/unit/modules/test_zypperpkg.py -index 39f28f2198..fea6eeb004 100644 ---- a/tests/unit/modules/test_zypperpkg.py -+++ b/tests/unit/modules/test_zypperpkg.py -@@ -610,151 +610,6 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): - {"vim": "7.4.326-2.62", "fakepkg": ""}, - ) - -- def test_upgrade_without_vendor_change(self): -- """ -- Dist-upgrade without vendor change option. -- """ -- with patch( -- "salt.modules.zypperpkg.refresh_db", MagicMock(return_value=True) -- ), patch( -- "salt.modules.zypperpkg._systemd_scope", MagicMock(return_value=False) -- ): -- with patch( -- "salt.modules.zypperpkg.__zypper__.noraise.call", MagicMock() -- ) as zypper_mock: -- with patch( -- "salt.modules.zypperpkg.list_pkgs", -- MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.2"}]), -- ): -- ret = zypper.upgrade(dist_upgrade=True) -- self.assertDictEqual(ret, {"vim": {"old": "1.1", "new": "1.2"}}) -- zypper_mock.assert_any_call( -- "dist-upgrade", "--auto-agree-with-licenses", -- ) -- -- def test_refresh_zypper_flags(self): -- zypper.__zypper__._reset() -- with patch( -- "salt.modules.zypperpkg.version", MagicMock(return_value="0.5") -- ), patch.dict( -- zypper.__salt__, {"lowpkg.version_cmp": MagicMock(side_effect=[-1, -1])} -- ): -- zypper.__zypper__.refresh_zypper_flags() -- assert zypper.__zypper__.inst_avc == False -- assert zypper.__zypper__.dup_avc == False -- with patch( -- "salt.modules.zypperpkg.version", MagicMock(return_value="1.11.34") -- ), patch.dict( -- zypper.__salt__, {"lowpkg.version_cmp": MagicMock(side_effect=[0, -1])} -- ): -- zypper.__zypper__.refresh_zypper_flags() -- assert zypper.__zypper__.inst_avc == False -- assert zypper.__zypper__.dup_avc == True -- with patch( -- "salt.modules.zypperpkg.version", MagicMock(return_value="1.14.8") -- ), patch.dict( -- zypper.__salt__, {"lowpkg.version_cmp": MagicMock(side_effect=[0, 0])} -- ): -- zypper.__zypper__.refresh_zypper_flags() -- assert zypper.__zypper__.inst_avc == True -- assert zypper.__zypper__.dup_avc == True -- -- @patch("salt.modules.zypperpkg.__zypper__.refresh_zypper_flags", MagicMock()) -- def test_allow_vendor_change_function(self): -- zypper.__zypper__._reset() -- zypper.__zypper__.inst_avc = True -- zypper.__zypper__.dup_avc = True -- zypper.__zypper__.avc = False -- zypper.__zypper__.allow_vendor_change(False, False) -- assert zypper.__zypper__.avc == True -- zypper.__zypper__.avc = False -- zypper.__zypper__.allow_vendor_change(True, False) -- assert zypper.__zypper__.avc == True -- zypper.__zypper__.avc = False -- zypper.__zypper__.allow_vendor_change(False, True) -- assert zypper.__zypper__.avc == False -- zypper.__zypper__.avc = False -- zypper.__zypper__.allow_vendor_change(True, True) -- assert zypper.__zypper__.avc == True -- -- zypper.__zypper__._reset() -- zypper.__zypper__.inst_avc = False -- zypper.__zypper__.dup_avc = True -- zypper.__zypper__.avc = False -- zypper.__zypper__.allow_vendor_change(False, False) -- assert zypper.__zypper__.avc == True -- zypper.__zypper__.avc = False -- zypper.__zypper__.allow_vendor_change(True, False) -- assert zypper.__zypper__.avc == True -- zypper.__zypper__.avc = False -- zypper.__zypper__.allow_vendor_change(False, True) -- assert zypper.__zypper__.avc == False -- zypper.__zypper__.avc = False -- zypper.__zypper__.allow_vendor_change(True, True) -- assert zypper.__zypper__.avc == True -- -- zypper.__zypper__._reset() -- zypper.__zypper__.inst_avc = False -- zypper.__zypper__.dup_avc = False -- zypper.__zypper__.avc = False -- zypper.__zypper__.allow_vendor_change(False, False) -- assert zypper.__zypper__.avc == False -- zypper.__zypper__.avc = False -- zypper.__zypper__.allow_vendor_change(True, False) -- assert zypper.__zypper__.avc == False -- zypper.__zypper__.avc = False -- zypper.__zypper__.allow_vendor_change(False, True) -- assert zypper.__zypper__.avc == False -- zypper.__zypper__.avc = False -- zypper.__zypper__.allow_vendor_change(True, True) -- assert zypper.__zypper__.avc == False -- -- @patch( -- "salt.utils.environment.get_module_environment", -- MagicMock(return_value={"SALT_RUNNING": "1"}), -- ) -- def test_zypper_call_dist_upgrade_with_avc_true(self): -- cmd_run_mock = MagicMock(return_value={"retcode": 0, "stdout": None}) -- zypper.__zypper__._reset() -- with patch.dict(zypper.__salt__, {"cmd.run_all": cmd_run_mock}), patch( -- "salt.modules.zypperpkg.__zypper__.refresh_zypper_flags", MagicMock() -- ), patch("salt.modules.zypperpkg.__zypper__._reset", MagicMock()): -- zypper.__zypper__.dup_avc = True -- zypper.__zypper__.avc = True -- zypper.__zypper__.call("dist-upgrade") -- cmd_run_mock.assert_any_call( -- [ -- "zypper", -- "--non-interactive", -- "--no-refresh", -- "dist-upgrade", -- "--allow-vendor-change", -- ], -- output_loglevel="trace", -- python_shell=False, -- env={"SALT_RUNNING": "1"}, -- ) -- -- @patch( -- "salt.utils.environment.get_module_environment", -- MagicMock(return_value={"SALT_RUNNING": "1"}), -- ) -- def test_zypper_call_dist_upgrade_with_avc_false(self): -- cmd_run_mock = MagicMock(return_value={"retcode": 0, "stdout": None}) -- zypper.__zypper__._reset() -- with patch.dict(zypper.__salt__, {"cmd.run_all": cmd_run_mock}), patch( -- "salt.modules.zypperpkg.__zypper__.refresh_zypper_flags", MagicMock() -- ), patch("salt.modules.zypperpkg.__zypper__._reset", MagicMock()): -- zypper.__zypper__.dup_avc = False -- zypper.__zypper__.avc = False -- zypper.__zypper__.call("dist-upgrade") -- cmd_run_mock.assert_any_call( -- ["zypper", "--non-interactive", "--no-refresh", "dist-upgrade",], -- output_loglevel="trace", -- python_shell=False, -- env={"SALT_RUNNING": "1"}, -- ) -- - @patch( - "salt.utils.environment.get_module_environment", - MagicMock(return_value={"SALT_RUNNING": "1"}), -@@ -802,296 +657,6 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): - env={"SALT_RUNNING": "1"}, - ) - -- def test_upgrade_with_novendorchange_true(self): -- """ -- Dist-upgrade without vendor change option. -- """ -- zypper.__zypper__._reset() -- with patch( -- "salt.modules.zypperpkg.refresh_db", MagicMock(return_value=True) -- ), patch( -- "salt.modules.zypperpkg.__zypper__.refresh_zypper_flags", MagicMock() -- ) as refresh_flags_mock, patch( -- "salt.modules.zypperpkg._systemd_scope", MagicMock(return_value=False) -- ): -- with patch( -- "salt.modules.zypperpkg.__zypper__.noraise.call", MagicMock() -- ) as zypper_mock: -- with patch( -- "salt.modules.zypperpkg.list_pkgs", -- MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.2"}]), -- ): -- ret = zypper.upgrade(dist_upgrade=True, novendorchange=True) -- refresh_flags_mock.assert_not_called() -- zypper_mock.assert_any_call( -- "dist-upgrade", "--auto-agree-with-licenses", -- ) -- -- def test_upgrade_with_novendorchange_false(self): -- """ -- Perform dist-upgrade with novendorchange set to False. -- """ -- zypper.__zypper__._reset() -- with patch( -- "salt.modules.zypperpkg.refresh_db", MagicMock(return_value=True) -- ), patch( -- "salt.modules.zypperpkg.__zypper__.refresh_zypper_flags", MagicMock() -- ), patch( -- "salt.modules.zypperpkg._systemd_scope", MagicMock(return_value=False) -- ): -- with patch( -- "salt.modules.zypperpkg.__zypper__.noraise.call", MagicMock() -- ) as zypper_mock: -- with patch( -- "salt.modules.zypperpkg.list_pkgs", -- MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.1"}]), -- ): -- zypper.__zypper__.inst_avc = True -- zypper.__zypper__.dup_avc = True -- with patch.dict( -- zypper.__salt__, -- { -- "pkg_resource.version": MagicMock(return_value="1.15"), -- "lowpkg.version_cmp": MagicMock(return_value=1), -- }, -- ): -- ret = zypper.upgrade( -- dist_upgrade=True, -- dryrun=True, -- fromrepo=["Dummy", "Dummy2"], -- novendorchange=False, -- ) -- assert zypper.__zypper__.avc == True -- -- def test_upgrade_with_allowvendorchange_true(self): -- """ -- Perform dist-upgrade with allowvendorchange set to True. -- """ -- zypper.__zypper__._reset() -- with patch( -- "salt.modules.zypperpkg.refresh_db", MagicMock(return_value=True) -- ), patch( -- "salt.modules.zypperpkg.__zypper__.refresh_zypper_flags", MagicMock() -- ), patch( -- "salt.modules.zypperpkg._systemd_scope", MagicMock(return_value=False) -- ): -- with patch( -- "salt.modules.zypperpkg.__zypper__.noraise.call", MagicMock() -- ) as zypper_mock: -- with patch( -- "salt.modules.zypperpkg.list_pkgs", -- MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.1"}]), -- ): -- with patch.dict( -- zypper.__salt__, -- { -- "pkg_resource.version": MagicMock(return_value="1.15"), -- "lowpkg.version_cmp": MagicMock(return_value=1), -- }, -- ): -- -- zypper.__zypper__.inst_avc = True -- zypper.__zypper__.dup_avc = True -- ret = zypper.upgrade( -- dist_upgrade=True, -- dryrun=True, -- fromrepo=["Dummy", "Dummy2"], -- allowvendorchange=True, -- ) -- assert zypper.__zypper__.avc == True -- -- def test_upgrade_with_allowvendorchange_false(self): -- """ -- Perform dist-upgrade with allowvendorchange set to False. -- """ -- zypper.__zypper__._reset() -- with patch( -- "salt.modules.zypperpkg.refresh_db", MagicMock(return_value=True) -- ), patch( -- "salt.modules.zypperpkg.__zypper__.refresh_zypper_flags", MagicMock() -- ), patch( -- "salt.modules.zypperpkg._systemd_scope", MagicMock(return_value=False) -- ): -- with patch( -- "salt.modules.zypperpkg.__zypper__.noraise.call", MagicMock() -- ) as zypper_mock: -- with patch( -- "salt.modules.zypperpkg.list_pkgs", -- MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.1"}]), -- ): -- with patch.dict( -- zypper.__salt__, -- { -- "pkg_resource.version": MagicMock(return_value="1.15"), -- "lowpkg.version_cmp": MagicMock(return_value=1), -- }, -- ): -- -- zypper.__zypper__.inst_avc = True -- zypper.__zypper__.dup_avc = True -- ret = zypper.upgrade( -- dist_upgrade=True, -- dryrun=True, -- fromrepo=["Dummy", "Dummy2"], -- allowvendorchange=False, -- ) -- assert zypper.__zypper__.avc == False -- -- def test_upgrade_old_zypper(self): -- zypper.__zypper__._reset() -- with patch( -- "salt.modules.zypperpkg.refresh_db", MagicMock(return_value=True) -- ), patch( -- "salt.modules.zypperpkg.__zypper__.refresh_zypper_flags", MagicMock() -- ) as refresh_flags_mock, patch( -- "salt.modules.zypperpkg._systemd_scope", MagicMock(return_value=False) -- ): -- with patch( -- "salt.modules.zypperpkg.__zypper__.noraise.call", MagicMock() -- ) as zypper_mock: -- with patch( -- "salt.modules.zypperpkg.list_pkgs", -- MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.1"}]), -- ): -- with patch.dict( -- zypper.__salt__, -- { -- "pkg_resource.version": MagicMock(return_value="1.11"), -- "lowpkg.version_cmp": MagicMock(return_value=-1), -- }, -- ): -- zypper.__zypper__.inst_avc = False -- zypper.__zypper__.dup_avc = False -- ret = zypper.upgrade( -- dist_upgrade=True, -- dryrun=True, -- fromrepo=["Dummy", "Dummy2"], -- novendorchange=False, -- ) -- zypper.__zypper__.avc = False -- -- def test_upgrade_success(self): -- """ -- Test system upgrade and dist-upgrade success. -- -- :return: -- """ -- with patch( -- "salt.modules.zypperpkg.refresh_db", MagicMock(return_value=True) -- ), patch( -- "salt.modules.zypperpkg._systemd_scope", MagicMock(return_value=False) -- ): -- with patch( -- "salt.modules.zypperpkg.__zypper__.noraise.call", MagicMock() -- ) as zypper_mock: -- with patch( -- "salt.modules.zypperpkg.list_pkgs", -- MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.2"}]), -- ): -- ret = zypper.upgrade() -- self.assertDictEqual(ret, {"vim": {"old": "1.1", "new": "1.2"}}) -- zypper_mock.assert_any_call("update", "--auto-agree-with-licenses") -- -- with patch( -- "salt.modules.zypperpkg.list_pkgs", -- MagicMock( -- side_effect=[ -- {"kernel-default": "1.1"}, -- {"kernel-default": "1.1,1.2"}, -- ] -- ), -- ): -- ret = zypper.upgrade() -- self.assertDictEqual( -- ret, {"kernel-default": {"old": "1.1", "new": "1.1,1.2"}} -- ) -- zypper_mock.assert_any_call("update", "--auto-agree-with-licenses") -- -- with patch( -- "salt.modules.zypperpkg.list_pkgs", -- MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.1,1.2"}]), -- ): -- ret = zypper.upgrade() -- self.assertDictEqual(ret, {"vim": {"old": "1.1", "new": "1.1,1.2"}}) -- zypper_mock.assert_any_call("update", "--auto-agree-with-licenses") -- -- with patch( -- "salt.modules.zypperpkg.list_pkgs", -- MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.1"}]), -- ): -- ret = zypper.upgrade(dist_upgrade=True, dryrun=True) -- zypper_mock.assert_any_call( -- "dist-upgrade", "--auto-agree-with-licenses", "--dry-run" -- ) -- zypper_mock.assert_any_call( -- "dist-upgrade", -- "--auto-agree-with-licenses", -- "--dry-run", -- "--debug-solver", -- ) -- -- with patch( -- "salt.modules.zypperpkg.list_pkgs", -- MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.1"}]), -- ): -- ret = zypper.upgrade( -- dist_upgrade=False, fromrepo=["Dummy", "Dummy2"], dryrun=False -- ) -- zypper_mock.assert_any_call( -- "update", -- "--auto-agree-with-licenses", -- "--repo", -- "Dummy", -- "--repo", -- "Dummy2", -- ) -- -- with patch( -- "salt.modules.zypperpkg.list_pkgs", -- MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.1"}]), -- ): -- ret = zypper.upgrade( -- dist_upgrade=True, -- dryrun=True, -- fromrepo=["Dummy", "Dummy2"], -- novendorchange=True, -- ) -- zypper_mock.assert_any_call( -- "dist-upgrade", -- "--auto-agree-with-licenses", -- "--dry-run", -- "--from", -- "Dummy", -- "--from", -- "Dummy2", -- ) -- zypper_mock.assert_any_call( -- "dist-upgrade", -- "--auto-agree-with-licenses", -- "--dry-run", -- "--from", -- "Dummy", -- "--from", -- "Dummy2", -- "--debug-solver", -- ) -- -- with patch( -- "salt.modules.zypperpkg.list_pkgs", -- MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.1"}]), -- ): -- ret = zypper.upgrade( -- dist_upgrade=False, fromrepo=["Dummy", "Dummy2"], dryrun=False -- ) -- zypper_mock.assert_any_call( -- "update", -- "--auto-agree-with-licenses", -- "--repo", -- "Dummy", -- "--repo", -- "Dummy2", -- ) -- - def test_upgrade_kernel(self): - """ - Test kernel package upgrade success. -@@ -1136,53 +701,6 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): - }, - ) - -- def test_upgrade_failure(self): -- """ -- Test system upgrade failure. -- -- :return: -- """ -- zypper_out = """ --Loading repository data... --Reading installed packages... --Computing distribution upgrade... --Use 'zypper repos' to get the list of defined repositories. --Repository 'DUMMY' not found by its alias, number, or URI. --""" -- -- class FailingZypperDummy: -- def __init__(self): -- self.stdout = zypper_out -- self.stderr = "" -- self.pid = 1234 -- self.exit_code = 555 -- self.noraise = MagicMock() -- self.allow_vendor_change = self -- self.SUCCESS_EXIT_CODES = [0] -- -- def __call__(self, *args, **kwargs): -- return self -- -- with patch( -- "salt.modules.zypperpkg.__zypper__", FailingZypperDummy() -- ) as zypper_mock, patch( -- "salt.modules.zypperpkg.refresh_db", MagicMock(return_value=True) -- ), patch( -- "salt.modules.zypperpkg._systemd_scope", MagicMock(return_value=False) -- ): -- zypper_mock.noraise.call = MagicMock() -- with patch( -- "salt.modules.zypperpkg.list_pkgs", -- MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.1"}]), -- ): -- with self.assertRaises(CommandExecutionError) as cmd_exc: -- ret = zypper.upgrade(dist_upgrade=True, fromrepo=["DUMMY"]) -- self.assertEqual(cmd_exc.exception.info["changes"], {}) -- self.assertEqual(cmd_exc.exception.info["result"]["stdout"], zypper_out) -- zypper_mock.noraise.call.assert_called_with( -- "dist-upgrade", "--auto-agree-with-licenses", "--from", "DUMMY", -- ) -- - def test_upgrade_available(self): - """ - Test whether or not an upgrade is available for a given package. --- -2.37.3 - - diff --git a/align-amazon-ec2-nitro-grains-with-upstream-pr-bsc-1.patch b/align-amazon-ec2-nitro-grains-with-upstream-pr-bsc-1.patch deleted file mode 100644 index a56ff4e..0000000 --- a/align-amazon-ec2-nitro-grains-with-upstream-pr-bsc-1.patch +++ /dev/null @@ -1,124 +0,0 @@ -From d1e9af256fa67cd792ce11e6e9c1e24a1fe2054f Mon Sep 17 00:00:00 2001 -From: Victor Zhestkov -Date: Fri, 28 Oct 2022 13:19:46 +0300 -Subject: [PATCH] Align Amazon EC2 (Nitro) grains with upstream PR - (bsc#1203685) - -* Set virtual to Nitro for Amazon EC2 kvm instances - -* Add few mocks to prevent false failing - -possible in some specific environments - -* Add one more possible test case returning Nitro ---- - salt/grains/core.py | 8 +++++++- - tests/pytests/unit/grains/test_core.py | 27 +++++++++++++++++++++++++- - 2 files changed, 33 insertions(+), 2 deletions(-) - -diff --git a/salt/grains/core.py b/salt/grains/core.py -index 76f3767ddf..f359c07432 100644 ---- a/salt/grains/core.py -+++ b/salt/grains/core.py -@@ -860,6 +860,10 @@ def _virtual(osdata): - grains["virtual"] = "container" - grains["virtual_subtype"] = "LXC" - break -+ elif "amazon" in output: -+ grains["virtual"] = "Nitro" -+ grains["virtual_subtype"] = "Amazon EC2" -+ break - elif command == "virt-what": - for line in output.splitlines(): - if line in ("kvm", "qemu", "uml", "xen"): -@@ -1174,7 +1178,7 @@ def _virtual(osdata): - grains["virtual"] = "virtual" - - # Try to detect if the instance is running on Amazon EC2 -- if grains["virtual"] in ("qemu", "kvm", "xen"): -+ if grains["virtual"] in ("qemu", "kvm", "xen", "amazon"): - dmidecode = salt.utils.path.which("dmidecode") - if dmidecode: - ret = __salt__["cmd.run_all"]( -@@ -1182,6 +1186,8 @@ def _virtual(osdata): - ) - output = ret["stdout"] - if "Manufacturer: Amazon EC2" in output: -+ if grains["virtual"] != "xen": -+ grains["virtual"] = "Nitro" - grains["virtual_subtype"] = "Amazon EC2" - product = re.match( - r".*Product Name: ([^\r\n]*).*", output, flags=re.DOTALL -diff --git a/tests/pytests/unit/grains/test_core.py b/tests/pytests/unit/grains/test_core.py -index c06cdb2db0..6f3bef69f2 100644 ---- a/tests/pytests/unit/grains/test_core.py -+++ b/tests/pytests/unit/grains/test_core.py -@@ -2888,6 +2888,11 @@ def test_virtual_set_virtual_ec2(): - "/usr/bin/systemd-detect-virt", - None, - None, -+ # Check with systemd-detect-virt returning amazon and no dmidecode available -+ None, -+ "/usr/bin/systemd-detect-virt", -+ None, -+ None, - ] - ) - cmd_run_all_mock = MagicMock( -@@ -2946,9 +2951,22 @@ def test_virtual_set_virtual_ec2(): - }, - # Check with systemd-detect-virt when no dmidecode available - {"retcode": 0, "stderr": "", "stdout": "kvm"}, -+ # Check with systemd-detect-virt returning amazon and no dmidecode available -+ {"retcode": 0, "stderr": "", "stdout": "amazon"}, - ] - ) - -+ def _mock_is_file(filename): -+ if filename in ( -+ "/proc/1/cgroup", -+ "/proc/cpuinfo", -+ "/sys/devices/virtual/dmi/id/product_name", -+ "/proc/xen/xsd_kva", -+ "/proc/xen/capabilities", -+ ): -+ return False -+ return True -+ - with patch("salt.utils.path.which", which_mock), patch.dict( - core.__salt__, - { -@@ -2957,6 +2975,8 @@ def test_virtual_set_virtual_ec2(): - "cmd.retcode": salt.modules.cmdmod.retcode, - "smbios.get": salt.modules.smbios.get, - }, -+ ), patch("os.path.isfile", _mock_is_file), patch( -+ "os.path.isdir", return_value=False - ): - - virtual_grains = core._virtual(osdata.copy()) -@@ -2966,7 +2986,7 @@ def test_virtual_set_virtual_ec2(): - - virtual_grains = core._virtual(osdata.copy()) - -- assert virtual_grains["virtual"] == "kvm" -+ assert virtual_grains["virtual"] == "Nitro" - assert virtual_grains["virtual_subtype"] == "Amazon EC2 (m5.large)" - - virtual_grains = core._virtual(osdata.copy()) -@@ -2974,6 +2994,11 @@ def test_virtual_set_virtual_ec2(): - assert virtual_grains["virtual"] == "kvm" - assert "virtual_subtype" not in virtual_grains - -+ virtual_grains = core._virtual(osdata.copy()) -+ -+ assert virtual_grains["virtual"] == "Nitro" -+ assert virtual_grains["virtual_subtype"] == "Amazon EC2" -+ - - @pytest.mark.skip_on_windows - def test_linux_proc_files_with_non_utf8_chars(): --- -2.37.3 - - diff --git a/allow-entrypoint-compatibility-for-importlib-metadat.patch b/allow-entrypoint-compatibility-for-importlib-metadat.patch deleted file mode 100644 index b4546de..0000000 --- a/allow-entrypoint-compatibility-for-importlib-metadat.patch +++ /dev/null @@ -1,151 +0,0 @@ -From 6dc653b0cf8e6e043e13bea7009ded604ceb7b71 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?= - -Date: Thu, 12 Jan 2023 15:43:56 +0000 -Subject: [PATCH] Allow entrypoint compatibility for - importlib-metadata>=5.0.0 (#572) - -add tests and make sure the compat code is in an else :) - -changelog - -switch to try/except - -Co-authored-by: MKLeb ---- - changelog/62854.fixed | 1 + - salt/utils/entrypoints.py | 15 +++-- - .../pytests/functional/loader/test_loader.py | 67 +++++++++++++++++-- - 3 files changed, 74 insertions(+), 9 deletions(-) - create mode 100644 changelog/62854.fixed - -diff --git a/changelog/62854.fixed b/changelog/62854.fixed -new file mode 100644 -index 0000000000..13e6df4fe3 ---- /dev/null -+++ b/changelog/62854.fixed -@@ -0,0 +1 @@ -+Use select instead of iterating over entrypoints as a dictionary for importlib_metadata>=5.0.0 -diff --git a/salt/utils/entrypoints.py b/salt/utils/entrypoints.py -index 3effa0b494..9452878ade 100644 ---- a/salt/utils/entrypoints.py -+++ b/salt/utils/entrypoints.py -@@ -38,13 +38,20 @@ def iter_entry_points(group, name=None): - entry_points_listing = [] - entry_points = importlib_metadata.entry_points() - -- for entry_point_group, entry_points_list in entry_points.items(): -- if entry_point_group != group: -- continue -- for entry_point in entry_points_list: -+ try: -+ for entry_point in entry_points.select(group=group): - if name is not None and entry_point.name != name: - continue - entry_points_listing.append(entry_point) -+ except AttributeError: -+ # importlib-metadata<5.0.0 -+ for entry_point_group, entry_points_list in entry_points.items(): -+ if entry_point_group != group: -+ continue -+ for entry_point in entry_points_list: -+ if name is not None and entry_point.name != name: -+ continue -+ entry_points_listing.append(entry_point) - - return entry_points_listing - -diff --git a/tests/pytests/functional/loader/test_loader.py b/tests/pytests/functional/loader/test_loader.py -index 6dfd97b0e6..a13d90d5eb 100644 ---- a/tests/pytests/functional/loader/test_loader.py -+++ b/tests/pytests/functional/loader/test_loader.py -@@ -1,5 +1,4 @@ - import json --import sys - - import pytest - import salt.utils.versions -@@ -143,10 +142,6 @@ def test_utils_loader_does_not_load_extensions( - assert "foobar.echo" not in loader_functions - - --@pytest.mark.skipif( -- sys.version_info < (3, 6), -- reason="importlib-metadata>=3.3.0 does not exist for Py3.5", --) - def test_extension_discovery_without_reload_with_importlib_metadata_installed( - venv, salt_extension, salt_minion_factory - ): -@@ -209,6 +204,68 @@ def test_extension_discovery_without_reload_with_importlib_metadata_installed( - assert "foobar.echo2" in loader_functions - - -+def test_extension_discovery_without_reload_with_importlib_metadata_5_installed( -+ venv, salt_extension, salt_minion_factory -+): -+ # Install our extension into the virtualenv -+ installed_packages = venv.get_installed_packages() -+ assert salt_extension.name not in installed_packages -+ venv.install("importlib-metadata>=3.3.0") -+ code = """ -+ import sys -+ import json -+ import subprocess -+ import salt._logging -+ import salt.loader -+ -+ extension_path = "{}" -+ -+ minion_config = json.loads(sys.stdin.read()) -+ salt._logging.set_logging_options_dict(minion_config) -+ salt._logging.setup_logging() -+ loader = salt.loader.minion_mods(minion_config) -+ -+ if "foobar.echo1" in loader: -+ sys.exit(1) -+ -+ # Install the extension -+ proc = subprocess.run( -+ [sys.executable, "-m", "pip", "install", extension_path], -+ check=False, -+ shell=False, -+ stdout=subprocess.PIPE, -+ ) -+ if proc.returncode != 0: -+ sys.exit(2) -+ -+ loader = salt.loader.minion_mods(minion_config) -+ if "foobar.echo1" not in loader: -+ sys.exit(3) -+ -+ print(json.dumps(list(loader))) -+ """.format( -+ salt_extension.srcdir -+ ) -+ ret = venv.run_code( -+ code, input=json.dumps(salt_minion_factory.config.copy()), check=False -+ ) -+ # Exitcode 1 - Extension was already installed -+ # Exitcode 2 - Failed to install the extension -+ # Exitcode 3 - Extension was not found within the same python process after being installed -+ assert ret.returncode == 0 -+ installed_packages = venv.get_installed_packages() -+ assert salt_extension.name in installed_packages -+ -+ loader_functions = json.loads(ret.stdout) -+ -+ # A non existing module should not appear in the loader -+ assert "monty.python" not in loader_functions -+ -+ # But our extension's modules should appear on the loader -+ assert "foobar.echo1" in loader_functions -+ assert "foobar.echo2" in loader_functions -+ -+ - def test_extension_discovery_without_reload_with_bundled_importlib_metadata( - venv, salt_extension, salt_minion_factory - ): --- -2.37.3 - - diff --git a/allow-vendor-change-option-with-zypper.patch b/allow-vendor-change-option-with-zypper.patch index 58ac76b..5d33a98 100644 --- a/allow-vendor-change-option-with-zypper.patch +++ b/allow-vendor-change-option-with-zypper.patch @@ -1,4 +1,4 @@ -From 51836a4c37f05262e708f058f323c1fbc2123ade Mon Sep 17 00:00:00 2001 +From a36d6524e530eca32966f46597c88dbfd4b90e78 Mon Sep 17 00:00:00 2001 From: Martin Seidl Date: Tue, 27 Oct 2020 16:12:29 +0100 Subject: [PATCH] Allow vendor change option with zypper @@ -59,15 +59,15 @@ Co-authored-by: Pablo Suárez Hernández Co-authored-by: Jochen Breuer Co-authored-by: Pablo Suárez Hernández --- - salt/modules/zypperpkg.py | 105 +++++-- - tests/unit/modules/test_zypperpkg.py | 418 ++++++++++++++++++++++++--- - 2 files changed, 462 insertions(+), 61 deletions(-) + salt/modules/zypperpkg.py | 105 ++++-- + tests/unit/modules/test_zypperpkg.py | 532 ++++++++++++++++++++++++++- + 2 files changed, 612 insertions(+), 25 deletions(-) diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py -index 6b19c65db3..c2452d6dec 100644 +index 4bb10f445a..2da470bea3 100644 --- a/salt/modules/zypperpkg.py +++ b/salt/modules/zypperpkg.py -@@ -35,6 +35,8 @@ import salt.utils.stringutils +@@ -36,6 +36,8 @@ import salt.utils.stringutils import salt.utils.systemd import salt.utils.versions from salt.exceptions import CommandExecutionError, MinionError, SaltInvocationError @@ -75,8 +75,8 @@ index 6b19c65db3..c2452d6dec 100644 +# pylint: disable=import-error,redefined-builtin,no-name-in-module from salt.utils.versions import LooseVersion - log = logging.getLogger(__name__) -@@ -135,6 +137,13 @@ class _Zypper: + if salt.utils.files.is_fcntl_available(): +@@ -140,6 +142,13 @@ class _Zypper: self.__systemd_scope = False self.__root = None @@ -90,7 +90,7 @@ index 6b19c65db3..c2452d6dec 100644 # Call status self.__called = False -@@ -179,6 +188,8 @@ class _Zypper: +@@ -184,6 +193,8 @@ class _Zypper: self.__no_raise = True elif item == "refreshable": self.__refresh = True @@ -99,7 +99,7 @@ index 6b19c65db3..c2452d6dec 100644 elif item == "call": return self.__call else: -@@ -219,6 +230,33 @@ class _Zypper: +@@ -224,6 +235,33 @@ class _Zypper: def pid(self): return self.__call_result.get("pid", "") @@ -133,7 +133,7 @@ index 6b19c65db3..c2452d6dec 100644 def _is_error(self): """ Is this is an error code? -@@ -335,6 +373,15 @@ class _Zypper: +@@ -362,6 +400,15 @@ class _Zypper: if self.__systemd_scope: cmd.extend(["systemd-run", "--scope"]) cmd.extend(self.__cmd) @@ -149,7 +149,7 @@ index 6b19c65db3..c2452d6dec 100644 log.debug("Calling Zypper: %s", " ".join(cmd)) self.__call_result = __salt__["cmd.run_all"](cmd, **kwargs) if self._check_result(): -@@ -1444,6 +1491,8 @@ def install( +@@ -1490,6 +1537,8 @@ def install( no_recommends=False, root=None, inclusion_detection=False, @@ -158,7 +158,7 @@ index 6b19c65db3..c2452d6dec 100644 **kwargs ): """ -@@ -1491,6 +1540,13 @@ def install( +@@ -1537,6 +1586,13 @@ def install( skip_verify Skip the GPG verification check (e.g., ``--no-gpg-checks``) @@ -172,7 +172,7 @@ index 6b19c65db3..c2452d6dec 100644 version Can be either a version number, or the combination of a comparison operator (<, >, <=, >=, =) and a version number (ex. '>1.2.3-4'). -@@ -1656,6 +1712,7 @@ def install( +@@ -1702,6 +1758,7 @@ def install( cmd_install.append( kwargs.get("resolve_capabilities") and "--capability" or "--name" ) @@ -180,7 +180,7 @@ index 6b19c65db3..c2452d6dec 100644 if not refresh: cmd_install.insert(0, "--no-refresh") -@@ -1692,6 +1749,7 @@ def install( +@@ -1738,6 +1795,7 @@ def install( systemd_scope=systemd_scope, root=root, ) @@ -188,7 +188,7 @@ index 6b19c65db3..c2452d6dec 100644 .call(*cmd) .splitlines() ): -@@ -1704,7 +1762,9 @@ def install( +@@ -1750,7 +1808,9 @@ def install( while downgrades: cmd = cmd_install + ["--force"] + downgrades[:500] downgrades = downgrades[500:] @@ -199,7 +199,7 @@ index 6b19c65db3..c2452d6dec 100644 _clean_cache() new = ( -@@ -1735,7 +1795,8 @@ def upgrade( +@@ -1783,7 +1843,8 @@ def upgrade( dryrun=False, dist_upgrade=False, fromrepo=None, @@ -209,7 +209,7 @@ index 6b19c65db3..c2452d6dec 100644 skip_verify=False, no_recommends=False, root=None, -@@ -1774,7 +1835,11 @@ def upgrade( +@@ -1844,7 +1905,11 @@ def upgrade( Specify a list of package repositories to upgrade from. Default: None novendorchange @@ -222,7 +222,7 @@ index 6b19c65db3..c2452d6dec 100644 skip_verify Skip the GPG verification check (e.g., ``--no-gpg-checks``) -@@ -1821,31 +1886,21 @@ def upgrade( +@@ -1927,28 +1992,18 @@ def upgrade( cmd_update.extend(["--from" if dist_upgrade else "--repo", repo]) log.info("Targeting repos: %s", fromrepo) @@ -236,20 +236,13 @@ index 6b19c65db3..c2452d6dec 100644 - log.warning( - "Disabling vendor changes is not supported on this Zypper version" - ) -- -- if no_recommends: -- cmd_update.append("--no-recommends") -- log.info("Disabling recommendations") + if no_recommends: + cmd_update.append("--no-recommends") + log.info("Disabling recommendations") -- if dryrun: -- # Creates a solver test case for debugging. -- log.info("Executing debugsolver and performing a dry-run dist-upgrade") -- __zypper__(systemd_scope=_systemd_scope(), root=root).noraise.call( -- *cmd_update + ["--debug-solver"] -- ) +- if no_recommends: +- cmd_update.append("--no-recommends") +- log.info("Disabling recommendations") + if dryrun: + # Creates a solver test case for debugging. + log.info("Executing debugsolver and performing a dry-run dist-upgrade") @@ -257,20 +250,33 @@ index 6b19c65db3..c2452d6dec 100644 + allowvendorchange, novendorchange + ).noraise.call(*cmd_update + ["--debug-solver"]) - old = list_pkgs(root=root) -- +- if dryrun: +- # Creates a solver test case for debugging. +- log.info("Executing debugsolver and performing a dry-run dist-upgrade") +- __zypper__(systemd_scope=_systemd_scope(), root=root).noraise.call( +- *cmd_update + ["--debug-solver"] +- ) +- else: ++ if not dist_upgrade: + if name or pkgs: + try: + (pkg_params, _) = __salt__["pkg_resource.parse_targets"]( +@@ -1962,7 +2017,9 @@ def upgrade( + + old = list_pkgs(root=root, attr=diff_attr) + - __zypper__(systemd_scope=_systemd_scope(), root=root).noraise.call(*cmd_update) + __zypper__(systemd_scope=_systemd_scope(), root=root).allow_vendor_change( + allowvendorchange, novendorchange + ).noraise.call(*cmd_update) _clean_cache() - new = list_pkgs(root=root) + new = list_pkgs(root=root, attr=diff_attr) ret = salt.utils.data.compare_dicts(old, new) diff --git a/tests/unit/modules/test_zypperpkg.py b/tests/unit/modules/test_zypperpkg.py -index 671adc2779..39f28f2198 100644 +index 5e4c967520..e85c93da3b 100644 --- a/tests/unit/modules/test_zypperpkg.py +++ b/tests/unit/modules/test_zypperpkg.py -@@ -135,6 +135,7 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): +@@ -137,6 +137,7 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): stdout_xml_snippet = '' sniffer = RunSniffer(stdout=stdout_xml_snippet) @@ -278,7 +284,7 @@ index 671adc2779..39f28f2198 100644 with patch.dict("salt.modules.zypperpkg.__salt__", {"cmd.run_all": sniffer}): self.assertEqual(zypper.__zypper__.call("foo"), stdout_xml_snippet) self.assertEqual(len(sniffer.calls), 1) -@@ -609,13 +610,373 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): +@@ -628,13 +629,495 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): {"vim": "7.4.326-2.62", "fakepkg": ""}, ) @@ -642,38 +648,112 @@ index 671adc2779..39f28f2198 100644 + ) + zypper.__zypper__.avc = False + - def test_upgrade_success(self): - """ - Test system upgrade and dist-upgrade success. - - :return: - """ -- with patch.dict(zypper.__grains__, {"osrelease_info": [12, 1]}), patch( ++ def test_upgrade_success(self): ++ """ ++ Test system upgrade and dist-upgrade success. ++ ++ :return: ++ """ + with patch( - "salt.modules.zypperpkg.refresh_db", MagicMock(return_value=True) - ), patch( - "salt.modules.zypperpkg._systemd_scope", MagicMock(return_value=False) -@@ -654,16 +1015,6 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): - self.assertDictEqual(ret, {"vim": {"old": "1.1", "new": "1.1,1.2"}}) - zypper_mock.assert_any_call("update", "--auto-agree-with-licenses") - -- with patch( -- "salt.modules.zypperpkg.list_pkgs", -- MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.2"}]), -- ): -- ret = zypper.upgrade(dist_upgrade=True) -- self.assertDictEqual(ret, {"vim": {"old": "1.1", "new": "1.2"}}) -- zypper_mock.assert_any_call( -- "dist-upgrade", "--auto-agree-with-licenses" -- ) -- - with patch( - "salt.modules.zypperpkg.list_pkgs", - MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.1"}]), -@@ -679,6 +1030,22 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): - "--debug-solver", - ) - ++ "salt.modules.zypperpkg.refresh_db", MagicMock(return_value=True) ++ ), patch( ++ "salt.modules.zypperpkg._systemd_scope", MagicMock(return_value=False) ++ ): ++ with patch( ++ "salt.modules.zypperpkg.__zypper__.noraise.call", MagicMock() ++ ) as zypper_mock: ++ with patch( ++ "salt.modules.zypperpkg.list_pkgs", ++ MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.2"}]), ++ ): ++ ret = zypper.upgrade() ++ self.assertDictEqual(ret, {"vim": {"old": "1.1", "new": "1.2"}}) ++ zypper_mock.assert_any_call("update", "--auto-agree-with-licenses") ++ ++ with patch( ++ "salt.modules.zypperpkg.list_pkgs", ++ MagicMock( ++ side_effect=[ ++ {"kernel-default": "1.1"}, ++ {"kernel-default": "1.1,1.2"}, ++ ] ++ ), ++ ): ++ ret = zypper.upgrade() ++ self.assertDictEqual( ++ ret, {"kernel-default": {"old": "1.1", "new": "1.1,1.2"}} ++ ) ++ zypper_mock.assert_any_call("update", "--auto-agree-with-licenses") ++ ++ with patch( ++ "salt.modules.zypperpkg.list_pkgs", ++ MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.1,1.2"}]), ++ ): ++ ret = zypper.upgrade() ++ self.assertDictEqual(ret, {"vim": {"old": "1.1", "new": "1.1,1.2"}}) ++ zypper_mock.assert_any_call("update", "--auto-agree-with-licenses") ++ ++ with patch( ++ "salt.modules.zypperpkg.list_pkgs", ++ MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.1"}]), ++ ): ++ ret = zypper.upgrade(dist_upgrade=True, dryrun=True) ++ zypper_mock.assert_any_call( ++ "dist-upgrade", "--auto-agree-with-licenses", "--dry-run" ++ ) ++ zypper_mock.assert_any_call( ++ "dist-upgrade", ++ "--auto-agree-with-licenses", ++ "--dry-run", ++ "--debug-solver", ++ ) ++ ++ with patch( ++ "salt.modules.zypperpkg.list_pkgs", ++ MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.1"}]), ++ ): ++ ret = zypper.upgrade( ++ dist_upgrade=False, fromrepo=["Dummy", "Dummy2"], dryrun=False ++ ) ++ zypper_mock.assert_any_call( ++ "update", ++ "--auto-agree-with-licenses", ++ "--repo", ++ "Dummy", ++ "--repo", ++ "Dummy2", ++ ) ++ ++ with patch( ++ "salt.modules.zypperpkg.list_pkgs", ++ MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.1"}]), ++ ): ++ ret = zypper.upgrade( ++ dist_upgrade=True, ++ dryrun=True, ++ fromrepo=["Dummy", "Dummy2"], ++ novendorchange=True, ++ ) ++ zypper_mock.assert_any_call( ++ "dist-upgrade", ++ "--auto-agree-with-licenses", ++ "--dry-run", ++ "--from", ++ "Dummy", ++ "--from", ++ "Dummy2", ++ ) ++ zypper_mock.assert_any_call( ++ "dist-upgrade", ++ "--auto-agree-with-licenses", ++ "--dry-run", ++ "--from", ++ "Dummy", ++ "--from", ++ "Dummy2", ++ "--debug-solver", ++ ) ++ + with patch( + "salt.modules.zypperpkg.list_pkgs", + MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.1"}]), @@ -690,49 +770,6 @@ index 671adc2779..39f28f2198 100644 + "Dummy2", + ) + - with patch( - "salt.modules.zypperpkg.list_pkgs", - MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.1"}]), -@@ -697,7 +1064,6 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): - "Dummy", - "--from", - "Dummy2", -- "--no-allow-vendor-change", - ) - zypper_mock.assert_any_call( - "dist-upgrade", -@@ -707,7 +1073,6 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): - "Dummy", - "--from", - "Dummy2", -- "--no-allow-vendor-change", - "--debug-solver", - ) - -@@ -727,33 +1092,13 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): - "Dummy2", - ) - -- with patch( -- "salt.modules.zypperpkg.list_pkgs", -- MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.2"}]), -- ): -- ret = zypper.upgrade( -- dist_upgrade=True, -- fromrepo=["Dummy", "Dummy2"], -- novendorchange=True, -- ) -- self.assertDictEqual(ret, {"vim": {"old": "1.1", "new": "1.2"}}) -- zypper_mock.assert_any_call( -- "dist-upgrade", -- "--auto-agree-with-licenses", -- "--from", -- "Dummy", -- "--from", -- "Dummy2", -- "--no-allow-vendor-change", -- ) -- def test_upgrade_kernel(self): """ Test kernel package upgrade success. @@ -744,31 +781,61 @@ index 671adc2779..39f28f2198 100644 "salt.modules.zypperpkg.refresh_db", MagicMock(return_value=True) ), patch( "salt.modules.zypperpkg._systemd_scope", MagicMock(return_value=False) -@@ -812,12 +1157,13 @@ Repository 'DUMMY' not found by its alias, number, or URI. - self.pid = 1234 - self.exit_code = 555 - self.noraise = MagicMock() +@@ -672,6 +1155,53 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): + }, + ) + ++ def test_upgrade_failure(self): ++ """ ++ Test system upgrade failure. ++ ++ :return: ++ """ ++ zypper_out = """ ++Loading repository data... ++Reading installed packages... ++Computing distribution upgrade... ++Use 'zypper repos' to get the list of defined repositories. ++Repository 'DUMMY' not found by its alias, number, or URI. ++""" ++ ++ class FailingZypperDummy: ++ def __init__(self): ++ self.stdout = zypper_out ++ self.stderr = "" ++ self.pid = 1234 ++ self.exit_code = 555 ++ self.noraise = MagicMock() + self.allow_vendor_change = self - self.SUCCESS_EXIT_CODES = [0] - - def __call__(self, *args, **kwargs): - return self - -- with patch.dict(zypper.__grains__, {"osrelease_info": [12, 1]}), patch( ++ self.SUCCESS_EXIT_CODES = [0] ++ ++ def __call__(self, *args, **kwargs): ++ return self ++ + with patch( - "salt.modules.zypperpkg.__zypper__", FailingZypperDummy() - ) as zypper_mock, patch( - "salt.modules.zypperpkg.refresh_db", MagicMock(return_value=True) -@@ -834,7 +1180,7 @@ Repository 'DUMMY' not found by its alias, number, or URI. - self.assertEqual(cmd_exc.exception.info["changes"], {}) - self.assertEqual(cmd_exc.exception.info["result"]["stdout"], zypper_out) - zypper_mock.noraise.call.assert_called_with( -- "dist-upgrade", "--auto-agree-with-licenses", "--from", "DUMMY" ++ "salt.modules.zypperpkg.__zypper__", FailingZypperDummy() ++ ) as zypper_mock, patch( ++ "salt.modules.zypperpkg.refresh_db", MagicMock(return_value=True) ++ ), patch( ++ "salt.modules.zypperpkg._systemd_scope", MagicMock(return_value=False) ++ ): ++ zypper_mock.noraise.call = MagicMock() ++ with patch( ++ "salt.modules.zypperpkg.list_pkgs", ++ MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.1"}]), ++ ): ++ with self.assertRaises(CommandExecutionError) as cmd_exc: ++ ret = zypper.upgrade(dist_upgrade=True, fromrepo=["DUMMY"]) ++ self.assertEqual(cmd_exc.exception.info["changes"], {}) ++ self.assertEqual(cmd_exc.exception.info["result"]["stdout"], zypper_out) ++ zypper_mock.noraise.call.assert_called_with( + "dist-upgrade", "--auto-agree-with-licenses", "--from", "DUMMY", - ) - ++ ) ++ def test_upgrade_available(self): + """ + Test whether or not an upgrade is available for a given package. -- -2.37.3 +2.39.2 diff --git a/async-batch-implementation.patch b/async-batch-implementation.patch index 434ef94..303127a 100644 --- a/async-batch-implementation.patch +++ b/async-batch-implementation.patch @@ -1,4 +1,4 @@ -From f16fb8885eeddad179be9e2290d1523cb8f82641 Mon Sep 17 00:00:00 2001 +From 76e69d9ef729365db1b0f1798f5f8a038d2065fc Mon Sep 17 00:00:00 2001 From: Mihai Dinca Date: Fri, 16 Nov 2018 17:05:29 +0100 Subject: [PATCH] Async batch implementation @@ -71,21 +71,21 @@ Async batch implementation fix (#320) Remove deprecated usage of NO_MOCK and NO_MOCK_REASON --- - salt/auth/__init__.py | 2 + - salt/cli/batch.py | 109 ++++++-- - salt/cli/batch_async.py | 315 +++++++++++++++++++++ - salt/cli/support/profiles/__init__.py | 5 +- - salt/client/__init__.py | 51 +--- - salt/master.py | 20 ++ - salt/transport/ipc.py | 9 +- - salt/utils/event.py | 8 +- - tests/unit/cli/test_batch_async.py | 386 ++++++++++++++++++++++++++ - 9 files changed, 841 insertions(+), 64 deletions(-) + salt/auth/__init__.py | 2 + + salt/cli/batch.py | 109 ++++-- + salt/cli/batch_async.py | 315 +++++++++++++++++ + salt/cli/support/profiles/__init__.py | 5 +- + salt/client/__init__.py | 45 +-- + salt/master.py | 20 ++ + salt/transport/ipc.py | 9 +- + salt/utils/event.py | 8 +- + tests/pytests/unit/cli/test_batch_async.py | 386 +++++++++++++++++++++ + 9 files changed, 841 insertions(+), 58 deletions(-) create mode 100644 salt/cli/batch_async.py - create mode 100644 tests/unit/cli/test_batch_async.py + create mode 100644 tests/pytests/unit/cli/test_batch_async.py diff --git a/salt/auth/__init__.py b/salt/auth/__init__.py -index 0c64755235..8dc096d9c5 100644 +index 331baab211..b0f0c0ac6c 100644 --- a/salt/auth/__init__.py +++ b/salt/auth/__init__.py @@ -49,6 +49,8 @@ AUTH_INTERNAL_KEYWORDS = frozenset( @@ -581,21 +581,12 @@ index b86aef30b8..4ae6d07b13 100644 -''' +""" diff --git a/salt/client/__init__.py b/salt/client/__init__.py -index eaf156e060..2427516ca1 100644 +index 7ce8963b8f..bcda56c9b4 100644 --- a/salt/client/__init__.py +++ b/salt/client/__init__.py -@@ -586,47 +586,23 @@ class LocalClient: - {'dave': {...}} - {'stewart': {...}} - """ -- # We need to re-import salt.utils.args here -- # even though it has already been imported. -- # when cmd_batch is called via the NetAPI -- # the module is unavailable. -- import salt.utils.args -- - # Late import - not used anywhere else in this file +@@ -594,38 +594,20 @@ class LocalClient: import salt.cli.batch + import salt.utils.args - arg = salt.utils.args.condition_input(arg, kwarg) - opts = { @@ -645,7 +636,7 @@ index eaf156e060..2427516ca1 100644 batch = salt.cli.batch.Batch(opts, eauth=eauth, quiet=True) for ret, _ in batch.run(): yield ret -@@ -1819,6 +1795,7 @@ class LocalClient: +@@ -1826,6 +1808,7 @@ class LocalClient: "key": self.key, "tgt_type": tgt_type, "ret": ret, @@ -654,7 +645,7 @@ index eaf156e060..2427516ca1 100644 } diff --git a/salt/master.py b/salt/master.py -index 9c06a52c1c..705a1bc2fb 100644 +index 9d2239bffb..2a526b4f21 100644 --- a/salt/master.py +++ b/salt/master.py @@ -19,6 +19,7 @@ import time @@ -665,7 +656,7 @@ index 9c06a52c1c..705a1bc2fb 100644 import salt.client import salt.client.ssh.client import salt.crypt -@@ -2145,6 +2146,22 @@ class ClearFuncs(TransportMethods): +@@ -2153,6 +2154,22 @@ class ClearFuncs(TransportMethods): return False return self.loadauth.get_tok(clear_load["token"]) @@ -688,7 +679,7 @@ index 9c06a52c1c..705a1bc2fb 100644 def publish(self, clear_load): """ This method sends out publications to the minions, it can only be used -@@ -2264,6 +2281,9 @@ class ClearFuncs(TransportMethods): +@@ -2297,6 +2314,9 @@ class ClearFuncs(TransportMethods): ), }, } @@ -734,10 +725,10 @@ index ca13a498e3..3a3f0c7a5f 100644 def close(self): """ diff --git a/salt/utils/event.py b/salt/utils/event.py -index d14b9ada40..e8d1aaa5f5 100644 +index a07ad513b1..869e12a140 100644 --- a/salt/utils/event.py +++ b/salt/utils/event.py -@@ -944,6 +944,10 @@ class SaltEvent: +@@ -946,6 +946,10 @@ class SaltEvent: # Minion fired a bad retcode, fire an event self._fire_ret_load_specific_fun(load) @@ -748,7 +739,7 @@ index d14b9ada40..e8d1aaa5f5 100644 def set_event_handler(self, event_handler): """ Invoke the event_handler callback each time an event arrives. -@@ -952,8 +956,10 @@ class SaltEvent: +@@ -954,8 +958,10 @@ class SaltEvent: if not self.cpub: self.connect_pub() @@ -760,11 +751,11 @@ index d14b9ada40..e8d1aaa5f5 100644 # pylint: disable=W1701 def __del__(self): -diff --git a/tests/unit/cli/test_batch_async.py b/tests/unit/cli/test_batch_async.py +diff --git a/tests/pytests/unit/cli/test_batch_async.py b/tests/pytests/unit/cli/test_batch_async.py new file mode 100644 index 0000000000..c0b708de76 --- /dev/null -+++ b/tests/unit/cli/test_batch_async.py ++++ b/tests/pytests/unit/cli/test_batch_async.py @@ -0,0 +1,386 @@ +import salt.ext.tornado +from salt.cli.batch_async import BatchAsync @@ -1153,6 +1144,6 @@ index 0000000000..c0b708de76 + self.batch.schedule_next() + self.assertEqual(len(self.batch.event.io_loop.spawn_callback.mock_calls), 0) -- -2.37.3 +2.39.2 diff --git a/avoid-excessive-syslogging-by-watchdog-cronjob-58.patch b/avoid-excessive-syslogging-by-watchdog-cronjob-58.patch index 9284c2f..7536fad 100644 --- a/avoid-excessive-syslogging-by-watchdog-cronjob-58.patch +++ b/avoid-excessive-syslogging-by-watchdog-cronjob-58.patch @@ -1,16 +1,16 @@ -From 100bf2d977c15fda21de7d1d5da2f2c61bed2afd Mon Sep 17 00:00:00 2001 +From 4d8c88d6e467c22ea74738743de5be6577f81085 Mon Sep 17 00:00:00 2001 From: Hubert Mantel Date: Mon, 27 Nov 2017 13:55:13 +0100 Subject: [PATCH] avoid excessive syslogging by watchdog cronjob (#58) --- - pkg/suse/salt-minion | 2 +- + pkg/old/suse/salt-minion | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) -diff --git a/pkg/suse/salt-minion b/pkg/suse/salt-minion +diff --git a/pkg/old/suse/salt-minion b/pkg/old/suse/salt-minion index 2e418094ed..73a91ebd62 100755 ---- a/pkg/suse/salt-minion -+++ b/pkg/suse/salt-minion +--- a/pkg/old/suse/salt-minion ++++ b/pkg/old/suse/salt-minion @@ -55,7 +55,7 @@ WATCHDOG_CRON="/etc/cron.d/salt-minion" set_watchdog() { @@ -21,6 +21,6 @@ index 2e418094ed..73a91ebd62 100755 /usr/bin/salt-daemon-watcher --with-init & disown fi -- -2.37.3 +2.39.2 diff --git a/bsc-1176024-fix-file-directory-user-and-group-owners.patch b/bsc-1176024-fix-file-directory-user-and-group-owners.patch index e2fad68..edd8e9e 100644 --- a/bsc-1176024-fix-file-directory-user-and-group-owners.patch +++ b/bsc-1176024-fix-file-directory-user-and-group-owners.patch @@ -1,4 +1,4 @@ -From 58329533d8b3239d978c15ecb76934987880897f Mon Sep 17 00:00:00 2001 +From 2ca37fe7d2a03ad86ed738f2636fe240b9f4467e Mon Sep 17 00:00:00 2001 From: Victor Zhestkov <35733135+vzhestkov@users.noreply.github.com> Date: Tue, 6 Oct 2020 12:36:41 +0300 Subject: [PATCH] bsc#1176024: Fix file/directory user and group @@ -12,15 +12,15 @@ Subject: [PATCH] bsc#1176024: Fix file/directory user and group Co-authored-by: Victor Zhestkov --- - salt/modules/file.py | 26 +++++++++++++++++--------- + salt/modules/file.py | 20 ++++++++++---------- salt/states/file.py | 12 ++++++++++-- - 2 files changed, 27 insertions(+), 11 deletions(-) + 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/salt/modules/file.py b/salt/modules/file.py -index 95bd69a588..d475e3c2e3 100644 +index 69d7992f5a..4612d65511 100644 --- a/salt/modules/file.py +++ b/salt/modules/file.py -@@ -247,7 +247,7 @@ def group_to_gid(group): +@@ -245,7 +245,7 @@ def group_to_gid(group): try: if isinstance(group, int): return group @@ -29,7 +29,7 @@ index 95bd69a588..d475e3c2e3 100644 except KeyError: return "" -@@ -338,7 +338,7 @@ def user_to_uid(user): +@@ -336,7 +336,7 @@ def user_to_uid(user): try: if isinstance(user, int): return user @@ -38,69 +38,55 @@ index 95bd69a588..d475e3c2e3 100644 except KeyError: return "" -@@ -5043,7 +5043,10 @@ def check_perms( - if ( - salt.utils.platform.is_windows() - and user_to_uid(user) != user_to_uid(perms["luser"]) -- ) or (not salt.utils.platform.is_windows() and user != perms["luser"]): -+ ) or ( -+ not salt.utils.platform.is_windows() -+ and salt.utils.stringutils.to_str(user) != perms["luser"] -+ ): +@@ -5133,8 +5133,8 @@ def check_perms( + salt.utils.platform.is_windows() and not user_to_uid(user) == cur["uid"] + ) or ( + not salt.utils.platform.is_windows() +- and not user == cur["user"] +- and not user == cur["uid"] ++ and not salt.utils.stringutils.to_str(user) == cur["user"] ++ and not salt.utils.stringutils.to_str(user) == cur["uid"] + ): perms["cuser"] = user - if group: -@@ -5052,7 +5055,10 @@ def check_perms( - if ( - salt.utils.platform.is_windows() - and group_to_gid(group) != group_to_gid(perms["lgroup"]) -- ) or (not salt.utils.platform.is_windows() and group != perms["lgroup"]): -+ ) or ( -+ not salt.utils.platform.is_windows() -+ and salt.utils.stringutils.to_str(group) != perms["lgroup"] -+ ): +@@ -5143,8 +5143,8 @@ def check_perms( + salt.utils.platform.is_windows() and not group_to_gid(group) == cur["gid"] + ) or ( + not salt.utils.platform.is_windows() +- and not group == cur["group"] +- and not group == cur["gid"] ++ and not salt.utils.stringutils.to_str(group) == cur["group"] ++ and not salt.utils.stringutils.to_str(group) == cur["gid"] + ): perms["cgroup"] = group - if "cuser" in perms or "cgroup" in perms: -@@ -5083,7 +5089,8 @@ def check_perms( - and user != "" +@@ -5188,8 +5188,8 @@ def check_perms( + salt.utils.platform.is_windows() and not user_to_uid(user) == post["uid"] ) or ( not salt.utils.platform.is_windows() -- and user != get_user(name, follow_symlinks=follow_symlinks) -+ and salt.utils.stringutils.to_str(user) -+ != get_user(name, follow_symlinks=follow_symlinks) - and user != "" +- and not user == post["user"] +- and not user == post["uid"] ++ and not salt.utils.stringutils.to_str(user) == post["user"] ++ and not salt.utils.stringutils.to_str(user) == post["uid"] ): if __opts__["test"] is True: -@@ -5101,18 +5108,19 @@ def check_perms( - salt.utils.platform.is_windows() - and group_to_gid(group) - != group_to_gid(get_group(name, follow_symlinks=follow_symlinks)) -- and user != "" -+ and group != "" + ret["changes"]["user"] = user +@@ -5204,8 +5204,8 @@ def check_perms( + salt.utils.platform.is_windows() and not group_to_gid(group) == post["gid"] ) or ( not salt.utils.platform.is_windows() -- and group != get_group(name, follow_symlinks=follow_symlinks) -- and user != "" -+ and salt.utils.stringutils.to_str(group) -+ != get_group(name, follow_symlinks=follow_symlinks) -+ and group != "" +- and not group == post["group"] +- and not group == post["gid"] ++ and not salt.utils.stringutils.to_str(group) == post["group"] ++ and not salt.utils.stringutils.to_str(group) == post["gid"] ): if __opts__["test"] is True: ret["changes"]["group"] = group - else: - ret["result"] = False - ret["comment"].append("Failed to change group to {}".format(group)) -- elif "cgroup" in perms and user != "": -+ elif "cgroup" in perms and group != "": - ret["changes"]["group"] = group - - # Mode changes if needed diff --git a/salt/states/file.py b/salt/states/file.py -index 9f33a8de23..50ceef1158 100644 +index 9f32151b8b..024e5e34ce 100644 --- a/salt/states/file.py +++ b/salt/states/file.py -@@ -863,9 +863,17 @@ def _check_dir_meta(name, user, group, mode, follow_symlinks=False): +@@ -864,9 +864,17 @@ def _check_dir_meta(name, user, group, mode, follow_symlinks=False): if not stats: changes["directory"] = "new" return changes @@ -121,6 +107,6 @@ index 9f33a8de23..50ceef1158 100644 # Normalize the dir mode smode = salt.utils.files.normalize_mode(stats["mode"]) -- -2.37.3 +2.39.2 diff --git a/change-the-delimeters-to-prevent-possible-tracebacks.patch b/change-the-delimeters-to-prevent-possible-tracebacks.patch index 72ab82a..4e50b2b 100644 --- a/change-the-delimeters-to-prevent-possible-tracebacks.patch +++ b/change-the-delimeters-to-prevent-possible-tracebacks.patch @@ -1,4 +1,4 @@ -From e011015f0eaa8e6453b57c208ab2a43a15824e36 Mon Sep 17 00:00:00 2001 +From b7a554e2dec3351c91c237497fe37cbc30d664bd Mon Sep 17 00:00:00 2001 From: Victor Zhestkov Date: Thu, 1 Sep 2022 14:42:24 +0300 Subject: [PATCH] Change the delimeters to prevent possible tracebacks on @@ -8,42 +8,14 @@ Subject: [PATCH] Change the delimeters to prevent possible tracebacks on * Fix the test test_dpkg_lowpkg::test_info --- - salt/modules/dpkg_lowpkg.py | 13 ++++++++----- - tests/unit/modules/test_dpkg_lowpkg.py | 4 ++-- - 2 files changed, 10 insertions(+), 7 deletions(-) + salt/modules/dpkg_lowpkg.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/modules/dpkg_lowpkg.py b/salt/modules/dpkg_lowpkg.py -index 2c25b1fb2a..fc93d99549 100644 +index 4d716c8772..78990492cf 100644 --- a/salt/modules/dpkg_lowpkg.py +++ b/salt/modules/dpkg_lowpkg.py -@@ -309,9 +309,8 @@ def _get_pkg_info(*packages, **kwargs): - "origin:${Origin}\\n" - "homepage:${Homepage}\\n" - "status:${db:Status-Abbrev}\\n" -- "======\\n" - "description:${Description}\\n" -- "------\\n'" -+ "\\n*/~^\\\\*\\n'" - ) - cmd += " {}".format(" ".join(packages)) - cmd = cmd.strip() -@@ -325,9 +324,13 @@ def _get_pkg_info(*packages, **kwargs): - else: - return ret - -- for pkg_info in [elm for elm in re.split(r"------", call["stdout"]) if elm.strip()]: -+ for pkg_info in [ -+ elm -+ for elm in re.split(r"\r?\n\*/~\^\\\*(\r?\n|)", call["stdout"]) -+ if elm.strip() -+ ]: - pkg_data = {} -- pkg_info, pkg_descr = re.split(r"======", pkg_info) -+ pkg_info, pkg_descr = pkg_info.split("\ndescription:", 1) - for pkg_info_line in [ - el.strip() for el in pkg_info.split(os.linesep) if el.strip() - ]: -@@ -344,7 +347,7 @@ def _get_pkg_info(*packages, **kwargs): +@@ -347,7 +347,7 @@ def _get_pkg_info(*packages, **kwargs): if build_date: pkg_data["build_date"] = build_date pkg_data["build_date_time_t"] = build_date_t @@ -52,29 +24,7 @@ index 2c25b1fb2a..fc93d99549 100644 ret.append(pkg_data) return ret -diff --git a/tests/unit/modules/test_dpkg_lowpkg.py b/tests/unit/modules/test_dpkg_lowpkg.py -index d00fc46c66..a97519f489 100644 ---- a/tests/unit/modules/test_dpkg_lowpkg.py -+++ b/tests/unit/modules/test_dpkg_lowpkg.py -@@ -290,7 +290,6 @@ class DpkgTestCase(TestCase, LoaderModuleMockMixin): - "origin:", - "homepage:http://tiswww.case.edu/php/chet/bash/bashtop.html", - "status:ii ", -- "======", - "description:GNU Bourne Again SHell", - " Bash is an sh-compatible command language interpreter that" - " executes", -@@ -307,7 +306,8 @@ class DpkgTestCase(TestCase, LoaderModuleMockMixin): - " The Programmable Completion Code, by Ian Macdonald, is now" - " found in", - " the bash-completion package.", -- "------", -+ "", -+ "*/~^\\*", # pylint: disable=W1401 - ] - ), - } -- -2.37.3 +2.39.2 diff --git a/clarify-pkg.installed-pkg_verify-documentation.patch b/clarify-pkg.installed-pkg_verify-documentation.patch deleted file mode 100644 index 90f9a24..0000000 --- a/clarify-pkg.installed-pkg_verify-documentation.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 5ed2295489fc13e48b981c323c846bde927cb800 Mon Sep 17 00:00:00 2001 -From: Alexander Graul -Date: Fri, 21 Oct 2022 14:39:21 +0200 -Subject: [PATCH] Clarify pkg.installed pkg_verify documentation - -There have been misunderstandings what the pkg_verify parameter does and -bug reports that it does not work, based on the wrong assumption that -this parameter changes the installation of new packages. The docstring -also stated that it was only provided by `yum`, but `zypper` also -provides this feature (actually it is `rpm` itself in both cases that -does the verification check) - -Related issue: https://github.com/saltstack/salt/issues/44878 - -(cherry picked from commit 2ed5f3c29d3b4313d904b7c081e5a29bf5e309c7) ---- - salt/states/pkg.py | 17 +++++++++-------- - 1 file changed, 9 insertions(+), 8 deletions(-) - -diff --git a/salt/states/pkg.py b/salt/states/pkg.py -index cda966a1e8..13532521d5 100644 ---- a/salt/states/pkg.py -+++ b/salt/states/pkg.py -@@ -1277,14 +1277,15 @@ def installed( - - .. versionadded:: 2014.7.0 - -- For requested packages that are already installed and would not be -- targeted for upgrade or downgrade, use pkg.verify to determine if any -- of the files installed by the package have been altered. If files have -- been altered, the reinstall option of pkg.install is used to force a -- reinstall. Types to ignore can be passed to pkg.verify. Additionally, -- ``verify_options`` can be used to modify further the behavior of -- pkg.verify. See examples below. Currently, this option is supported -- for the following pkg providers: :mod:`yumpkg `. -+ Use pkg.verify to check if already installed packages require -+ reinstallion. Requested packages that are already installed and not -+ targeted for up- or downgrade are verified with pkg.verify to determine -+ if any file installed by the package have been modified or if package -+ dependencies are not fulfilled. ``ignore_types`` and ``verify_options`` -+ can be passed to pkg.verify. See examples below. Currently, this option -+ is supported for the following pkg providers: -+ :mod:`yum `, -+ :mod:`zypperpkg `. - - Examples: - --- -2.37.3 - - diff --git a/control-the-collection-of-lvm-grains-via-config.patch b/control-the-collection-of-lvm-grains-via-config.patch index 2926237..b767488 100644 --- a/control-the-collection-of-lvm-grains-via-config.patch +++ b/control-the-collection-of-lvm-grains-via-config.patch @@ -1,4 +1,4 @@ -From 0df204fb1ea7135ce0196f99a864d3f94bd6f92e Mon Sep 17 00:00:00 2001 +From fcb43735942ca1b796f656d5647e49a93f770bb2 Mon Sep 17 00:00:00 2001 From: Alexander Graul Date: Tue, 10 Jan 2023 15:04:01 +0100 Subject: [PATCH] Control the collection of lvm grains via config @@ -32,6 +32,6 @@ index 586b187ddb..f5c406cb44 100644 """ Return list of LVM devices -- -2.37.3 +2.39.2 diff --git a/debian-info_installed-compatibility-50453.patch b/debian-info_installed-compatibility-50453.patch index 7486718..0703083 100644 --- a/debian-info_installed-compatibility-50453.patch +++ b/debian-info_installed-compatibility-50453.patch @@ -1,4 +1,4 @@ -From 8cd50907edeb4a1128681c30e52b2b30cf7f937d Mon Sep 17 00:00:00 2001 +From 2fbc5b580661b094cf79cc5da0860745b72088e4 Mon Sep 17 00:00:00 2001 From: Alexander Graul Date: Tue, 25 Jan 2022 17:08:57 +0100 Subject: [PATCH] Debian info_installed compatibility (#50453) @@ -56,15 +56,15 @@ that got partially reverted by this commit: https://github.com/openSUSE/salt/commit/d0ef24d113bdaaa29f180031b5da384cffe08c64#diff-820e6ce667fe3afddbc1b9cf1682fdef --- salt/modules/aptpkg.py | 24 ++++- - salt/modules/dpkg_lowpkg.py | 108 ++++++++++++++++++---- - tests/pytests/unit/modules/test_aptpkg.py | 52 +++++++++++ - 3 files changed, 166 insertions(+), 18 deletions(-) + salt/modules/dpkg_lowpkg.py | 110 ++++++++++++++++++---- + tests/pytests/unit/modules/test_aptpkg.py | 52 ++++++++++ + 3 files changed, 167 insertions(+), 19 deletions(-) diff --git a/salt/modules/aptpkg.py b/salt/modules/aptpkg.py -index 0cbd611b71..4a2281c47f 100644 +index 8e89744b5e..938e37cc9e 100644 --- a/salt/modules/aptpkg.py +++ b/salt/modules/aptpkg.py -@@ -3458,6 +3458,15 @@ def info_installed(*names, **kwargs): +@@ -3440,6 +3440,15 @@ def info_installed(*names, **kwargs): .. versionadded:: 2016.11.3 @@ -80,7 +80,7 @@ index 0cbd611b71..4a2281c47f 100644 CLI Example: .. code-block:: bash -@@ -3468,11 +3477,19 @@ def info_installed(*names, **kwargs): +@@ -3450,11 +3459,19 @@ def info_installed(*names, **kwargs): """ kwargs = salt.utils.args.clean_kwargs(**kwargs) failhard = kwargs.pop("failhard", True) @@ -101,7 +101,7 @@ index 0cbd611b71..4a2281c47f 100644 t_nfo = dict() if pkg_nfo.get("status", "ii")[1] != "i": continue # return only packages that are really installed -@@ -3493,7 +3510,10 @@ def info_installed(*names, **kwargs): +@@ -3475,7 +3492,10 @@ def info_installed(*names, **kwargs): else: t_nfo[key] = value @@ -114,7 +114,7 @@ index 0cbd611b71..4a2281c47f 100644 return ret diff --git a/salt/modules/dpkg_lowpkg.py b/salt/modules/dpkg_lowpkg.py -index 6a88573a8f..afbd619490 100644 +index eefd852c51..4d716c8772 100644 --- a/salt/modules/dpkg_lowpkg.py +++ b/salt/modules/dpkg_lowpkg.py @@ -234,6 +234,44 @@ def file_dict(*packages, **kwargs): @@ -171,13 +171,14 @@ index 6a88573a8f..afbd619490 100644 "maintainer:${Maintainer}\\n" "summary:${Summary}\\n" "source:${source:Package}\\n" -@@ -296,9 +334,16 @@ def _get_pkg_info(*packages, **kwargs): +@@ -299,10 +337,17 @@ def _get_pkg_info(*packages, **kwargs): key, value = pkg_info_line.split(":", 1) if value: pkg_data[key] = value - install_date = _get_pkg_install_time(pkg_data.get("package")) - if install_date: - pkg_data["install_date"] = install_date +- pkg_data["description"] = pkg_descr + install_date, install_date_t = _get_pkg_install_time( + pkg_data.get("package"), pkg_data.get("arch") + ) @@ -188,10 +189,11 @@ index 6a88573a8f..afbd619490 100644 + if build_date: + pkg_data["build_date"] = build_date + pkg_data["build_date_time_t"] = build_date_t - pkg_data["description"] = pkg_descr.split(":", 1)[-1] ++ pkg_data["description"] = pkg_descr.split(":", 1)[-1] ret.append(pkg_data) -@@ -324,24 +369,34 @@ def _get_pkg_license(pkg): + return ret +@@ -327,24 +372,34 @@ def _get_pkg_license(pkg): return ", ".join(sorted(licenses)) @@ -237,7 +239,7 @@ index 6a88573a8f..afbd619490 100644 def _get_pkg_ds_avail(): -@@ -391,6 +446,15 @@ def info(*packages, **kwargs): +@@ -394,6 +449,15 @@ def info(*packages, **kwargs): .. versionadded:: 2016.11.3 @@ -253,7 +255,7 @@ index 6a88573a8f..afbd619490 100644 CLI Example: .. code-block:: bash -@@ -405,6 +469,10 @@ def info(*packages, **kwargs): +@@ -408,6 +472,10 @@ def info(*packages, **kwargs): kwargs = salt.utils.args.clean_kwargs(**kwargs) failhard = kwargs.pop("failhard", True) @@ -264,7 +266,7 @@ index 6a88573a8f..afbd619490 100644 if kwargs: salt.utils.args.invalid_kwargs(kwargs) -@@ -432,6 +500,14 @@ def info(*packages, **kwargs): +@@ -435,6 +503,14 @@ def info(*packages, **kwargs): lic = _get_pkg_license(pkg["package"]) if lic: pkg["license"] = lic @@ -281,10 +283,10 @@ index 6a88573a8f..afbd619490 100644 return ret diff --git a/tests/pytests/unit/modules/test_aptpkg.py b/tests/pytests/unit/modules/test_aptpkg.py -index 6ef27e2d29..8e404a673c 100644 +index b69402578a..4226957eeb 100644 --- a/tests/pytests/unit/modules/test_aptpkg.py +++ b/tests/pytests/unit/modules/test_aptpkg.py -@@ -359,6 +359,58 @@ def test_info_installed(lowpkg_info_var): +@@ -360,6 +360,58 @@ def test_info_installed(lowpkg_info_var): assert len(aptpkg.info_installed()) == 1 @@ -344,6 +346,6 @@ index 6ef27e2d29..8e404a673c 100644 """ Test - Return the name of the package that owns the file. -- -2.37.3 +2.39.2 diff --git a/detect-module.run-syntax.patch b/detect-module.run-syntax.patch deleted file mode 100644 index e7f58ae..0000000 --- a/detect-module.run-syntax.patch +++ /dev/null @@ -1,28 +0,0 @@ -From dd147ab110e71ea0f1091923c9230ade01f226d4 Mon Sep 17 00:00:00 2001 -From: Victor Zhestkov -Date: Fri, 28 Oct 2022 13:19:23 +0300 -Subject: [PATCH] Detect module.run syntax - -* Detect module run syntax version - -* Update module.run docs and add changelog - -* Add test for module.run without any args - -Co-authored-by: Daniel A. Wozniak ---- - changelog/58763.fixed | 1 + - 1 file changed, 1 insertion(+) - create mode 100644 changelog/58763.fixed - -diff --git a/changelog/58763.fixed b/changelog/58763.fixed -new file mode 100644 -index 0000000000..53ee8304c0 ---- /dev/null -+++ b/changelog/58763.fixed -@@ -0,0 +1 @@ -+Detect new and legacy styles of calling module.run and support them both. --- -2.37.3 - - diff --git a/dnfnotify-pkgset-plugin-implementation-3002.2-450.patch b/dnfnotify-pkgset-plugin-implementation-3002.2-450.patch index 44dcdc4..388222d 100644 --- a/dnfnotify-pkgset-plugin-implementation-3002.2-450.patch +++ b/dnfnotify-pkgset-plugin-implementation-3002.2-450.patch @@ -1,4 +1,4 @@ -From e7bc5c7fc89877e9cbf203d8fb70855df0b626e1 Mon Sep 17 00:00:00 2001 +From c2a35c0c0aac093d0cc35181c1fda0162e22ac4c Mon Sep 17 00:00:00 2001 From: Victor Zhestkov <35733135+vzhestkov@users.noreply.github.com> Date: Mon, 8 Nov 2021 18:09:53 +0300 Subject: [PATCH] dnfnotify pkgset plugin implementation - 3002.2 (#450) @@ -125,6 +125,6 @@ index 0000000000..6e9df85f71 + digest.update(buff) + return digest.hexdigest() -- -2.37.3 +2.39.2 diff --git a/do-not-load-pip-state-if-there-is-no-3rd-party-depen.patch b/do-not-load-pip-state-if-there-is-no-3rd-party-depen.patch index 5a6592f..74ff65f 100644 --- a/do-not-load-pip-state-if-there-is-no-3rd-party-depen.patch +++ b/do-not-load-pip-state-if-there-is-no-3rd-party-depen.patch @@ -1,4 +1,4 @@ -From d97cbae7eb3cb0030d355a4ae3fb35745fed5da0 Mon Sep 17 00:00:00 2001 +From 4060d4cd24ac0fbcf83c1521553921d76c070a57 Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Fri, 21 Sep 2018 17:31:39 +0200 Subject: [PATCH] Do not load pip state if there is no 3rd party @@ -10,7 +10,7 @@ Safe import 3rd party dependency 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/salt/modules/pip.py b/salt/modules/pip.py -index 7135a9145f..da26416662 100644 +index c4de0c2984..a60bdca0bb 100644 --- a/salt/modules/pip.py +++ b/salt/modules/pip.py @@ -96,6 +96,12 @@ import salt.utils.url @@ -41,6 +41,6 @@ index 7135a9145f..da26416662 100644 def _pip_bin_env(cwd, bin_env): -- -2.37.3 +2.39.2 diff --git a/don-t-use-shell-sbin-nologin-in-requisites.patch b/don-t-use-shell-sbin-nologin-in-requisites.patch index 2d734f0..481d356 100644 --- a/don-t-use-shell-sbin-nologin-in-requisites.patch +++ b/don-t-use-shell-sbin-nologin-in-requisites.patch @@ -1,4 +1,4 @@ -From 009f51315366827653011d2e9b80aa88416a8bf0 Mon Sep 17 00:00:00 2001 +From da6adc6984f21c0d93afff0b0ff55d0eb0ee3e9f Mon Sep 17 00:00:00 2001 From: Alexander Graul Date: Tue, 17 Aug 2021 11:52:00 +0200 Subject: [PATCH] Don't use shell="/sbin/nologin" in requisites @@ -13,13 +13,13 @@ Fixes: bsc#1188259 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/salt/state.py b/salt/state.py -index 2385975b42..db228228a7 100644 +index cb434a91e7..cda84a0fcb 100644 --- a/salt/state.py +++ b/salt/state.py -@@ -921,9 +921,14 @@ class State: - cmd_opts[run_cmd_arg] = low_data.get(run_cmd_arg) +@@ -986,9 +986,14 @@ class State: + cmd_opts[run_cmd_arg] = low_data.get(run_cmd_arg) - if "shell" in low_data: + if "shell" in low_data and "shell" not in cmd_opts_exclude: - cmd_opts["shell"] = low_data["shell"] + shell = low_data["shell"] elif "shell" in self.opts["grains"]: @@ -34,6 +34,6 @@ index 2385975b42..db228228a7 100644 if "onlyif" in low_data: _ret = self._run_check_onlyif(low_data, cmd_opts) -- -2.37.3 +2.39.2 diff --git a/drop-serial-from-event.unpack-in-cli.batch_async.patch b/drop-serial-from-event.unpack-in-cli.batch_async.patch index d92ab44..a550031 100644 --- a/drop-serial-from-event.unpack-in-cli.batch_async.patch +++ b/drop-serial-from-event.unpack-in-cli.batch_async.patch @@ -1,4 +1,4 @@ -From d4c70bdcb8d871bf3a7e15299b69b9687b7d0d94 Mon Sep 17 00:00:00 2001 +From e7ef0b5a46cc69a9237033d8dc4dbc60c0802a20 Mon Sep 17 00:00:00 2001 From: Alexander Graul Date: Mon, 31 Jan 2022 10:24:26 +0100 Subject: [PATCH] Drop serial from event.unpack in cli.batch_async @@ -29,6 +29,6 @@ index 09aa85258b..1012ce37cc 100644 if mtag.startswith(pattern[:-1]): minion = data["id"] -- -2.37.3 +2.39.2 diff --git a/early-feature-support-config.patch b/early-feature-support-config.patch index b7f509f..8e66230 100644 --- a/early-feature-support-config.patch +++ b/early-feature-support-config.patch @@ -1,4 +1,4 @@ -From 3ccce128163f6cd9a9360d3b28729702a5d260c1 Mon Sep 17 00:00:00 2001 +From 7b47e6f19b38d773a6ec744209753f3d29b094ea Mon Sep 17 00:00:00 2001 From: Alexander Graul Date: Tue, 18 Jan 2022 16:40:45 +0100 Subject: [PATCH] early feature: support-config @@ -537,7 +537,7 @@ Check last function by full name salt/utils/parsers.py | 114 +++++ scripts/salt-support | 11 + setup.py | 2 + - tests/unit/cli/test_support.py | 553 +++++++++++++++++++++ + tests/pytests/unit/cli/test_support.py | 553 +++++++++++++++++++++ tests/unit/modules/test_saltsupport.py | 496 +++++++++++++++++++ 28 files changed, 2958 insertions(+), 7 deletions(-) create mode 100644 salt/cli/support/__init__.py @@ -557,11 +557,11 @@ Check last function by full name create mode 100644 salt/modules/saltsupport.py create mode 100644 salt/states/saltsupport.py create mode 100755 scripts/salt-support - create mode 100644 tests/unit/cli/test_support.py + create mode 100644 tests/pytests/unit/cli/test_support.py create mode 100644 tests/unit/modules/test_saltsupport.py diff --git a/doc/ref/modules/all/index.rst b/doc/ref/modules/all/index.rst -index fef851215a..a36ab6b2e9 100644 +index cbd8b0cdc5..abd40e0bc7 100644 --- a/doc/ref/modules/all/index.rst +++ b/doc/ref/modules/all/index.rst @@ -416,6 +416,7 @@ execution modules @@ -573,10 +573,10 @@ index fef851215a..a36ab6b2e9 100644 schedule scp_mod diff --git a/doc/ref/states/all/index.rst b/doc/ref/states/all/index.rst -index da7be43039..c968315970 100644 +index 13ff645b59..7a062c227b 100644 --- a/doc/ref/states/all/index.rst +++ b/doc/ref/states/all/index.rst -@@ -282,6 +282,7 @@ state modules +@@ -283,6 +283,7 @@ state modules rvm salt_proxy saltmod @@ -1740,10 +1740,10 @@ index 0000000000..391acdb606 + info: List of all available groups + output: table diff --git a/salt/loader/lazy.py b/salt/loader/lazy.py -index 8a5d0dd267..e7d692859c 100644 +index d319fe54b4..5de995d446 100644 --- a/salt/loader/lazy.py +++ b/salt/loader/lazy.py -@@ -968,8 +968,10 @@ class LazyLoader(salt.utils.lazy.LazyDict): +@@ -972,8 +972,10 @@ class LazyLoader(salt.utils.lazy.LazyDict): mod_names = [module_name] + list(virtual_aliases) for attr in funcs_to_load: @@ -2168,13 +2168,13 @@ index 0000000000..e800e3bf1f + + return __virtualname__ diff --git a/salt/scripts.py b/salt/scripts.py -index 7f6d80de59..1276d2c8b2 100644 +index 07393373c9..16b032af2e 100644 --- a/salt/scripts.py +++ b/salt/scripts.py -@@ -583,3 +583,18 @@ def salt_unity(): - sys.argv.pop(1) - s_fun = getattr(sys.modules[__name__], "salt_{}".format(cmd)) - s_fun() +@@ -622,3 +622,18 @@ def salt_pip(): + ] + _pip_args(sys.argv[1:], extras) + ret = subprocess.run(command, shell=False, check=False, env=env) + sys.exit(ret.returncode) + + +def salt_support(): @@ -2191,10 +2191,10 @@ index 7f6d80de59..1276d2c8b2 100644 + _install_signal_handlers(client) + client.run() diff --git a/salt/state.py b/salt/state.py -index d6d2c90168..3196f3c635 100644 +index 868be2749e..8352a8defc 100644 --- a/salt/state.py +++ b/salt/state.py -@@ -1592,7 +1592,9 @@ class State: +@@ -1671,7 +1671,9 @@ class State: names = [] if state.startswith("__"): continue @@ -2205,27 +2205,27 @@ index d6d2c90168..3196f3c635 100644 if orchestration_jid is not None: chunk["__orchestration_jid__"] = orchestration_jid if "__sls__" in body: -@@ -2273,9 +2275,16 @@ class State: - ret = self.call_parallel(cdata, low) +@@ -2382,9 +2384,16 @@ class State: else: self.format_slots(cdata) -- ret = self.states[cdata["full"]]( -- *cdata["args"], **cdata["kwargs"] -- ) -+ if cdata["full"].split(".")[-1] == "__call__": -+ # __call__ requires OrderedDict to preserve state order -+ # kwargs are also invalid overall -+ ret = self.states[cdata["full"]]( -+ cdata["args"], module=None, state=cdata["kwargs"] -+ ) -+ else: -+ ret = self.states[cdata["full"]]( -+ *cdata["args"], **cdata["kwargs"] -+ ) + with salt.utils.files.set_umask(low.get("__umask__")): +- ret = self.states[cdata["full"]]( +- *cdata["args"], **cdata["kwargs"] +- ) ++ if cdata["full"].split(".")[-1] == "__call__": ++ # __call__ requires OrderedDict to preserve state order ++ # kwargs are also invalid overall ++ ret = self.states[cdata["full"]]( ++ cdata["args"], module=None, state=cdata["kwargs"] ++ ) ++ else: ++ ret = self.states[cdata["full"]]( ++ *cdata["args"], **cdata["kwargs"] ++ ) self.states.inject_globals = {} - if ( - "check_cmd" in low -@@ -3362,10 +3371,31 @@ class State: + if "check_cmd" in low: + state_check_cmd = "{0[state]}.mod_run_check_cmd".format(low) +@@ -3489,10 +3498,31 @@ class State: running.update(errors) return running @@ -2698,30 +2698,30 @@ index 0000000000..4e0e79f3ea +if __name__ == "__main__": + salt_support() diff --git a/setup.py b/setup.py -index bd11ff95f7..d633af35ec 100755 +index 931ed40a51..e60f1b7085 100755 --- a/setup.py +++ b/setup.py -@@ -1165,6 +1165,7 @@ class SaltDistribution(distutils.dist.Distribution): - "scripts/salt-master", +@@ -1061,6 +1061,7 @@ class SaltDistribution(distutils.dist.Distribution): "scripts/salt-minion", "scripts/salt-proxy", + "scripts/salt-run", + "scripts/salt-support", "scripts/salt-ssh", "scripts/salt-syndic", "scripts/spm", -@@ -1216,6 +1217,7 @@ class SaltDistribution(distutils.dist.Distribution): - "salt-key = salt.scripts:salt_key", +@@ -1109,6 +1110,7 @@ class SaltDistribution(distutils.dist.Distribution): "salt-master = salt.scripts:salt_master", "salt-minion = salt.scripts:salt_minion", + "salt-run = salt.scripts:salt_run", + "salt-support = salt.scripts:salt_support", "salt-ssh = salt.scripts:salt_ssh", "salt-syndic = salt.scripts:salt_syndic", "spm = salt.scripts:salt_spm", -diff --git a/tests/unit/cli/test_support.py b/tests/unit/cli/test_support.py +diff --git a/tests/pytests/unit/cli/test_support.py b/tests/pytests/unit/cli/test_support.py new file mode 100644 index 0000000000..dc0e99bb3d --- /dev/null -+++ b/tests/unit/cli/test_support.py ++++ b/tests/pytests/unit/cli/test_support.py @@ -0,0 +1,553 @@ +""" + :codeauthor: Bo Maryniuk @@ -3779,6 +3779,6 @@ index 0000000000..f9ce7be29a + "00:00:00.000 - The real TTYs became " "pseudo TTYs and vice versa" + ] -- -2.37.3 +2.39.2 diff --git a/enable-passing-a-unix_socket-for-mysql-returners-bsc.patch b/enable-passing-a-unix_socket-for-mysql-returners-bsc.patch index c81b44d..c978774 100644 --- a/enable-passing-a-unix_socket-for-mysql-returners-bsc.patch +++ b/enable-passing-a-unix_socket-for-mysql-returners-bsc.patch @@ -1,4 +1,4 @@ -From 465ea094039e771ea2b4ccda012d0dc12f7aa022 Mon Sep 17 00:00:00 2001 +From e9d52cb97d619a76355c5aa1d03b733c125c0f22 Mon Sep 17 00:00:00 2001 From: Maximilian Meister Date: Thu, 3 May 2018 15:52:23 +0200 Subject: [PATCH] enable passing a unix_socket for mysql returners @@ -19,7 +19,7 @@ Signed-off-by: Maximilian Meister 1 file changed, 5 insertions(+) diff --git a/salt/returners/mysql.py b/salt/returners/mysql.py -index 6fd4fdef2c..7a7e9a3284 100644 +index 67b44004ac..a220f11465 100644 --- a/salt/returners/mysql.py +++ b/salt/returners/mysql.py @@ -17,6 +17,7 @@ config. These are the defaults: @@ -37,8 +37,8 @@ index 6fd4fdef2c..7a7e9a3284 100644 + alternative.mysql.unix_socket: '/tmp/mysql.sock' Should you wish the returner data to be cleaned out every so often, set - `keep_jobs` to the number of hours for the jobs to live in the tables. -@@ -196,6 +198,7 @@ def _get_options(ret=None): + `keep_jobs_seconds` to the number of hours for the jobs to live in the +@@ -197,6 +199,7 @@ def _get_options(ret=None): "ssl_ca": None, "ssl_cert": None, "ssl_key": None, @@ -46,7 +46,7 @@ index 6fd4fdef2c..7a7e9a3284 100644 } attrs = { -@@ -207,6 +210,7 @@ def _get_options(ret=None): +@@ -208,6 +211,7 @@ def _get_options(ret=None): "ssl_ca": "ssl_ca", "ssl_cert": "ssl_cert", "ssl_key": "ssl_key", @@ -54,7 +54,7 @@ index 6fd4fdef2c..7a7e9a3284 100644 } _options = salt.returners.get_returner_options( -@@ -265,6 +269,7 @@ def _get_serv(ret=None, commit=False): +@@ -266,6 +270,7 @@ def _get_serv(ret=None, commit=False): db=_options.get("db"), port=_options.get("port"), ssl=ssl_options, @@ -63,6 +63,6 @@ index 6fd4fdef2c..7a7e9a3284 100644 try: -- -2.37.3 +2.39.2 diff --git a/enhance-openscap-module-add-xccdf_eval-call-386.patch b/enhance-openscap-module-add-xccdf_eval-call-386.patch index def9667..32e8cf2 100644 --- a/enhance-openscap-module-add-xccdf_eval-call-386.patch +++ b/enhance-openscap-module-add-xccdf_eval-call-386.patch @@ -1,4 +1,4 @@ -From 93d7bdab18bdc657c8103a7b5f569458a97c8ca0 Mon Sep 17 00:00:00 2001 +From 17452801e950b3f49a9ec7ef444e3d57862cd9bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?= Date: Wed, 7 Jul 2021 15:41:48 +0100 @@ -420,6 +420,6 @@ index 045c37f7c9..301c1869ec 100644 + }, + ) -- -2.37.3 +2.39.2 diff --git a/fix-bsc-1065792.patch b/fix-bsc-1065792.patch index 7d3d817..283b400 100644 --- a/fix-bsc-1065792.patch +++ b/fix-bsc-1065792.patch @@ -1,4 +1,4 @@ -From 559920223a010b70a4e469143b3390d8d3a7a4e2 Mon Sep 17 00:00:00 2001 +From 42a5e5d1a898d7b8bdb56a94decf525204ebccb8 Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Thu, 14 Dec 2017 16:21:40 +0100 Subject: [PATCH] Fix bsc#1065792 @@ -20,6 +20,6 @@ index 93c7c4fb07..0d8a4efa03 100644 return __virtualname__ else: -- -2.37.3 +2.39.2 diff --git a/fix-for-suse-expanded-support-detection.patch b/fix-for-suse-expanded-support-detection.patch index 21a1690..acbfc28 100644 --- a/fix-for-suse-expanded-support-detection.patch +++ b/fix-for-suse-expanded-support-detection.patch @@ -1,4 +1,4 @@ -From 51bcdcfdec73368d1517150eafda21e4af51dd7a Mon Sep 17 00:00:00 2001 +From 7be26299bc7b6ec2065ab13857f088dc500ee882 Mon Sep 17 00:00:00 2001 From: Jochen Breuer Date: Thu, 6 Sep 2018 17:15:18 +0200 Subject: [PATCH] Fix for SUSE Expanded Support detection @@ -14,26 +14,26 @@ This change also adds a check for redhat-release and then marks the 1 file changed, 9 insertions(+) diff --git a/salt/grains/core.py b/salt/grains/core.py -index debbeb257d..b55ab4e472 100644 +index 710c57f28f..1199ad274f 100644 --- a/salt/grains/core.py +++ b/salt/grains/core.py -@@ -2058,6 +2058,15 @@ def os_data(): - log.trace("Parsing distrib info from /etc/centos-release") - # CentOS Linux - grains["lsb_distrib_id"] = "CentOS" -+ # Maybe CentOS Linux; could also be SUSE Expanded Support. -+ # SUSE ES has both, centos-release and redhat-release. -+ if os.path.isfile("/etc/redhat-release"): -+ with salt.utils.files.fopen("/etc/redhat-release") as ifile: -+ for line in ifile: -+ if "red hat enterprise linux server" in line.lower(): -+ # This is a SUSE Expanded Support Rhel installation -+ grains["lsb_distrib_id"] = "RedHat" -+ break - with salt.utils.files.fopen("/etc/centos-release") as ifile: - for line in ifile: - # Need to pull out the version and codename +@@ -2279,6 +2279,15 @@ def _legacy_linux_distribution_data(grains, os_release, lsb_has_error): + log.trace("Parsing distrib info from /etc/centos-release") + # CentOS Linux + grains["lsb_distrib_id"] = "CentOS" ++ # Maybe CentOS Linux; could also be SUSE Expanded Support. ++ # SUSE ES has both, centos-release and redhat-release. ++ if os.path.isfile("/etc/redhat-release"): ++ with salt.utils.files.fopen("/etc/redhat-release") as ifile: ++ for line in ifile: ++ if "red hat enterprise linux server" in line.lower(): ++ # This is a SUSE Expanded Support Rhel installation ++ grains["lsb_distrib_id"] = "RedHat" ++ break + with salt.utils.files.fopen("/etc/centos-release") as ifile: + for line in ifile: + # Need to pull out the version and codename -- -2.37.3 +2.39.2 diff --git a/fix-issue-2068-test.patch b/fix-issue-2068-test.patch index 2a45430..701457a 100644 --- a/fix-issue-2068-test.patch +++ b/fix-issue-2068-test.patch @@ -1,4 +1,4 @@ -From f87d92122cb141e8f6f4d1c5a6ed5685e1b3900c Mon Sep 17 00:00:00 2001 +From b0e713d6946526b894837406c0760c262e4312a1 Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Wed, 9 Jan 2019 16:08:19 +0100 Subject: [PATCH] Fix issue #2068 test @@ -13,7 +13,7 @@ Minor update: more correct is-dict check. 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/salt/state.py b/salt/state.py -index 3196f3c635..2385975b42 100644 +index 8352a8defc..cb434a91e7 100644 --- a/salt/state.py +++ b/salt/state.py @@ -12,6 +12,7 @@ The data sent to the state calls is as follows: @@ -24,7 +24,7 @@ index 3196f3c635..2385975b42 100644 import copy import datetime import fnmatch -@@ -3380,16 +3381,18 @@ class State: +@@ -3507,16 +3508,18 @@ class State: """ for chunk in high: state = high[chunk] @@ -47,6 +47,6 @@ index 3196f3c635..2385975b42 100644 def call_high(self, high, orchestration_jid=None): """ -- -2.37.3 +2.39.2 diff --git a/fix-missing-minion-returns-in-batch-mode-360.patch b/fix-missing-minion-returns-in-batch-mode-360.patch index e14ac15..1566eb6 100644 --- a/fix-missing-minion-returns-in-batch-mode-360.patch +++ b/fix-missing-minion-returns-in-batch-mode-360.patch @@ -1,4 +1,4 @@ -From 3ed9869ee6847472846072d62cbc57dcb9104c90 Mon Sep 17 00:00:00 2001 +From 5158ebce305d961a2d2e3cb3f889b0cde593c4a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hole=C4=8Dek?= Date: Mon, 10 May 2021 16:23:19 +0200 Subject: [PATCH] Fix missing minion returns in batch mode (#360) @@ -12,10 +12,10 @@ Co-authored-by: Denis V. Meltsaykin 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/client/__init__.py b/salt/client/__init__.py -index 2427516ca1..86888adc19 100644 +index bcda56c9b4..b2617e4554 100644 --- a/salt/client/__init__.py +++ b/salt/client/__init__.py -@@ -972,7 +972,7 @@ class LocalClient: +@@ -976,7 +976,7 @@ class LocalClient: self._clean_up_subscriptions(pub_data["jid"]) finally: @@ -25,6 +25,6 @@ index 2427516ca1..86888adc19 100644 def cmd_full_return( -- -2.37.3 +2.39.2 diff --git a/fix-ownership-of-salt-thin-directory-when-using-the-.patch b/fix-ownership-of-salt-thin-directory-when-using-the-.patch index ec3293c..2b9fdf5 100644 --- a/fix-ownership-of-salt-thin-directory-when-using-the-.patch +++ b/fix-ownership-of-salt-thin-directory-when-using-the-.patch @@ -1,4 +1,4 @@ -From 7ac8c79f38960c787f6b5324e347707325c65e79 Mon Sep 17 00:00:00 2001 +From 5f6488ab9211927c421e3d87a4ee84fe659ceb8b Mon Sep 17 00:00:00 2001 From: Victor Zhestkov Date: Mon, 27 Jun 2022 18:03:49 +0300 Subject: [PATCH] Fix ownership of salt thin directory when using the @@ -45,6 +45,6 @@ index 293ea1b7fa..95171f7aea 100644 if venv_salt_call is None: # Use Salt thin only if Salt Bundle (venv-salt-minion) is not available -- -2.37.3 +2.39.2 diff --git a/fix-regression-with-depending-client.ssh-on-psutil-b.patch b/fix-regression-with-depending-client.ssh-on-psutil-b.patch index 8909b36..3e465e1 100644 --- a/fix-regression-with-depending-client.ssh-on-psutil-b.patch +++ b/fix-regression-with-depending-client.ssh-on-psutil-b.patch @@ -1,4 +1,4 @@ -From 6e0e6c26f4ec0955b55937ae3b58ca485b99facd Mon Sep 17 00:00:00 2001 +From 42cfb51fa01e13fe043a62536ba37fd472bc2688 Mon Sep 17 00:00:00 2001 From: Victor Zhestkov Date: Tue, 12 Apr 2022 10:08:17 +0300 Subject: [PATCH] Fix regression with depending client.ssh on psutil @@ -9,7 +9,7 @@ Subject: [PATCH] Fix regression with depending client.ssh on psutil 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/salt/client/ssh/__init__.py b/salt/client/ssh/__init__.py -index fe1213b723..1b76a38e0b 100644 +index d5a679821e..b120e0002e 100644 --- a/salt/client/ssh/__init__.py +++ b/salt/client/ssh/__init__.py @@ -12,7 +12,6 @@ import hashlib @@ -48,6 +48,6 @@ index fe1213b723..1b76a38e0b 100644 if ( pid_running and prev_session_running < self.max_pid_wait -- -2.37.3 +2.39.2 diff --git a/fix-salt-ssh-opts-poisoning-bsc-1197637-3004-501.patch b/fix-salt-ssh-opts-poisoning-bsc-1197637-3004-501.patch index 9403f28..11c07c1 100644 --- a/fix-salt-ssh-opts-poisoning-bsc-1197637-3004-501.patch +++ b/fix-salt-ssh-opts-poisoning-bsc-1197637-3004-501.patch @@ -1,4 +1,4 @@ -From 59200b4a4578c96dcffc0584725d8cba40c20ff7 Mon Sep 17 00:00:00 2001 +From 4dbd5534a39fbfaebad32a00d0e6c512d840b0fd Mon Sep 17 00:00:00 2001 From: Victor Zhestkov Date: Thu, 31 Mar 2022 13:39:57 +0300 Subject: [PATCH] Fix salt-ssh opts poisoning (bsc#1197637) - 3004 (#501) @@ -14,7 +14,7 @@ Subject: [PATCH] Fix salt-ssh opts poisoning (bsc#1197637) - 3004 (#501) 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/salt/client/ssh/__init__.py b/salt/client/ssh/__init__.py -index 6db2dfcbb0..8ae417f575 100644 +index e6837df4e5..a527c03de6 100644 --- a/salt/client/ssh/__init__.py +++ b/salt/client/ssh/__init__.py @@ -338,7 +338,7 @@ class SSH(MultiprocessingStateMixin): @@ -123,6 +123,6 @@ index 32f8a7702c..bbe4269839 100644 loaded_base_name=loaded_base_name, ) -- -2.37.3 +2.39.2 diff --git a/fix-salt.states.file.managed-for-follow_symlinks-tru.patch b/fix-salt.states.file.managed-for-follow_symlinks-tru.patch deleted file mode 100644 index 661c70c..0000000 --- a/fix-salt.states.file.managed-for-follow_symlinks-tru.patch +++ /dev/null @@ -1,50 +0,0 @@ -From e328d2029c93153c519e10e9596c635f6f3febcf Mon Sep 17 00:00:00 2001 -From: Petr Pavlu <31453820+petrpavlu@users.noreply.github.com> -Date: Fri, 8 Jul 2022 10:11:52 +0200 -Subject: [PATCH] Fix salt.states.file.managed() for follow_symlinks=True - and test=True (bsc#1199372) (#535) - -When managing file /etc/test as follows: -> file /etc/test: -> file.managed: -> - name: /etc/test -> - source: salt://config/test -> - mode: 644 -> - follow_symlinks: True - -and with /etc/test being a symlink to a different file, an invocation of -"salt-call '*' state.apply test=True" can report that the file should be -updated even when a subsequent run of the same command without the test -parameter makes no changes. - -The problem is that the test code path doesn't take correctly into -account the follow_symlinks=True setting and ends up comparing -permissions of the symlink instead of its target file. - -The patch addresses the problem by extending functions -salt.modules.file.check_managed(), check_managed_changes() and -check_file_meta() to have the follow_symlinks parameter which gets -propagated to the salt.modules.file.stats() call and by updating -salt.states.file.managed() to forward the same parameter to -salt.modules.file.check_managed_changes(). - -Fixes #62066. - -[Cherry-picked from upstream commit -95bfbe31a2dc54723af3f1783d40de152760fe1a.] ---- - changelog/62066.fixed | 1 + - 1 file changed, 1 insertion(+) - create mode 100644 changelog/62066.fixed - -diff --git a/changelog/62066.fixed b/changelog/62066.fixed -new file mode 100644 -index 0000000000..68216a03c1 ---- /dev/null -+++ b/changelog/62066.fixed -@@ -0,0 +1 @@ -+Fixed salt.states.file.managed() for follow_symlinks=True and test=True --- -2.37.3 - - diff --git a/fix-salt.utils.stringutils.to_str-calls-to-make-it-w.patch b/fix-salt.utils.stringutils.to_str-calls-to-make-it-w.patch index b40e9bb..ea63d91 100644 --- a/fix-salt.utils.stringutils.to_str-calls-to-make-it-w.patch +++ b/fix-salt.utils.stringutils.to_str-calls-to-make-it-w.patch @@ -1,19 +1,21 @@ -From f348f291093ea3f7c841b03a975ae81b40963842 Mon Sep 17 00:00:00 2001 +From b4b2c59bfd479d59faeaf0e4d26d672828a519c8 Mon Sep 17 00:00:00 2001 From: Victor Zhestkov Date: Wed, 25 Nov 2020 15:09:41 +0300 Subject: [PATCH] Fix salt.utils.stringutils.to_str calls to make it working with numeric uid/gid +Fix upstream tests to work with 3006. --- - salt/modules/file.py | 16 ++++++++++------ - salt/states/file.py | 11 +++++++++-- - 2 files changed, 19 insertions(+), 8 deletions(-) + salt/modules/file.py | 22 ++++++++++++------- + salt/states/file.py | 11 ++++++++-- + .../unit/modules/file/test_file_check.py | 10 ++++----- + 3 files changed, 28 insertions(+), 15 deletions(-) diff --git a/salt/modules/file.py b/salt/modules/file.py -index d475e3c2e3..d3de4da467 100644 +index 4612d65511..55b236fe41 100644 --- a/salt/modules/file.py +++ b/salt/modules/file.py -@@ -5036,6 +5036,12 @@ def check_perms( +@@ -5127,14 +5127,20 @@ def check_perms( is_dir = os.path.isdir(name) is_link = os.path.islink(name) @@ -23,52 +25,57 @@ index d475e3c2e3..d3de4da467 100644 + except: + return salt.utils.stringutils.to_str(str(s)) + - # user/group changes if needed, then check if it worked + # Check and make user/group/mode changes, then verify they were successful if user: - if isinstance(user, int): -@@ -5045,7 +5051,7 @@ def check_perms( - and user_to_uid(user) != user_to_uid(perms["luser"]) + if ( + salt.utils.platform.is_windows() and not user_to_uid(user) == cur["uid"] ) or ( not salt.utils.platform.is_windows() -- and salt.utils.stringutils.to_str(user) != perms["luser"] -+ and __safe_to_str(user) != perms["luser"] +- and not salt.utils.stringutils.to_str(user) == cur["user"] +- and not salt.utils.stringutils.to_str(user) == cur["uid"] ++ and not __safe_to_str(user) == cur["user"] ++ and not user == cur["uid"] ): perms["cuser"] = user -@@ -5057,7 +5063,7 @@ def check_perms( - and group_to_gid(group) != group_to_gid(perms["lgroup"]) +@@ -5143,8 +5149,8 @@ def check_perms( + salt.utils.platform.is_windows() and not group_to_gid(group) == cur["gid"] ) or ( not salt.utils.platform.is_windows() -- and salt.utils.stringutils.to_str(group) != perms["lgroup"] -+ and __safe_to_str(group) != perms["lgroup"] +- and not salt.utils.stringutils.to_str(group) == cur["group"] +- and not salt.utils.stringutils.to_str(group) == cur["gid"] ++ and not __safe_to_str(group) == cur["group"] ++ and not group == cur["gid"] ): perms["cgroup"] = group -@@ -5089,8 +5095,7 @@ def check_perms( - and user != "" +@@ -5188,8 +5194,8 @@ def check_perms( + salt.utils.platform.is_windows() and not user_to_uid(user) == post["uid"] ) or ( not salt.utils.platform.is_windows() -- and salt.utils.stringutils.to_str(user) -- != get_user(name, follow_symlinks=follow_symlinks) -+ and __safe_to_str(user) != get_user(name, follow_symlinks=follow_symlinks) - and user != "" +- and not salt.utils.stringutils.to_str(user) == post["user"] +- and not salt.utils.stringutils.to_str(user) == post["uid"] ++ and not __safe_to_str(user) == post["user"] ++ and not user == post["uid"] ): if __opts__["test"] is True: -@@ -5111,8 +5116,7 @@ def check_perms( - and group != "" + ret["changes"]["user"] = user +@@ -5204,8 +5210,8 @@ def check_perms( + salt.utils.platform.is_windows() and not group_to_gid(group) == post["gid"] ) or ( not salt.utils.platform.is_windows() -- and salt.utils.stringutils.to_str(group) -- != get_group(name, follow_symlinks=follow_symlinks) -+ and __safe_to_str(group) != get_group(name, follow_symlinks=follow_symlinks) - and group != "" +- and not salt.utils.stringutils.to_str(group) == post["group"] +- and not salt.utils.stringutils.to_str(group) == post["gid"] ++ and not __safe_to_str(group) == post["group"] ++ and not group == post["gid"] ): if __opts__["test"] is True: + ret["changes"]["group"] = group diff --git a/salt/states/file.py b/salt/states/file.py -index 50ceef1158..1083bb46d6 100644 +index 024e5e34ce..9630ff7096 100644 --- a/salt/states/file.py +++ b/salt/states/file.py -@@ -863,15 +863,22 @@ def _check_dir_meta(name, user, group, mode, follow_symlinks=False): +@@ -864,15 +864,22 @@ def _check_dir_meta(name, user, group, mode, follow_symlinks=False): if not stats: changes["directory"] = "new" return changes @@ -93,7 +100,42 @@ index 50ceef1158..1083bb46d6 100644 and group != stats.get("gid") ): changes["group"] = group +diff --git a/tests/pytests/unit/modules/file/test_file_check.py b/tests/pytests/unit/modules/file/test_file_check.py +index ce86acd7fc..2294e6760b 100644 +--- a/tests/pytests/unit/modules/file/test_file_check.py ++++ b/tests/pytests/unit/modules/file/test_file_check.py +@@ -17,7 +17,7 @@ def configure_loader_modules(): + return { + filemod: { + "__context__": {}, +- "__opts__": {"test": False}, ++ "__opts__": {"test": True}, + } + } + +@@ -172,7 +172,7 @@ def test_check_managed_changes_follow_symlinks(a_link, tfile): + ), + # no user/group changes needed by id + ( +- {"user": 3001, "group": 4001}, ++ {"user": 2001, "group": 1001}, + {}, + ), + ], +@@ -184,9 +184,9 @@ def test_check_perms_user_group_name_and_id(input, expected): + stat_out = { + "user": "luser", + "group": "lgroup", +- "uid": 3001, +- "gid": 4001, +- "mode": "123", ++ "uid": 2001, ++ "gid": 1001, ++ "mode": "0123", + } + + patch_stats = patch( -- -2.37.3 +2.39.2 diff --git a/fix-state.apply-in-test-mode-with-file-state-module-.patch b/fix-state.apply-in-test-mode-with-file-state-module-.patch deleted file mode 100644 index 85a7e84..0000000 --- a/fix-state.apply-in-test-mode-with-file-state-module-.patch +++ /dev/null @@ -1,183 +0,0 @@ -From 58317cda7a347581b495ab7fd71ce75f0740d8d6 Mon Sep 17 00:00:00 2001 -From: Victor Zhestkov -Date: Thu, 1 Sep 2022 14:44:26 +0300 -Subject: [PATCH] Fix state.apply in test mode with file state module on - user/group checking (bsc#1202167) - -* Do not fail on checking user/group in test mode - -* fixes saltstack/salt#61846 reporting of errors in test mode - -Co-authored-by: nicholasmhughes - -* Add tests for _check_user usage - -Co-authored-by: nicholasmhughes ---- - changelog/61846.fixed | 1 + - salt/states/file.py | 5 +++ - tests/pytests/unit/states/file/test_copy.py | 35 ++++++++++++++++ - .../unit/states/file/test_filestate.py | 42 +++++++++++++++++++ - .../pytests/unit/states/file/test_managed.py | 31 ++++++++++++++ - 5 files changed, 114 insertions(+) - create mode 100644 changelog/61846.fixed - -diff --git a/changelog/61846.fixed b/changelog/61846.fixed -new file mode 100644 -index 0000000000..c4024efe9f ---- /dev/null -+++ b/changelog/61846.fixed -@@ -0,0 +1 @@ -+Fix the reporting of errors for file.directory in test mode -diff --git a/salt/states/file.py b/salt/states/file.py -index 1083bb46d6..5cb58f5454 100644 ---- a/salt/states/file.py -+++ b/salt/states/file.py -@@ -379,6 +379,11 @@ def _check_user(user, group): - gid = __salt__["file.group_to_gid"](group) - if gid == "": - err += "Group {} is not available".format(group) -+ if err and __opts__["test"]: -+ # Write the warning with error message, but prevent failing, -+ # in case of applying the state in test mode. -+ log.warning(err) -+ return "" - return err - - -diff --git a/tests/pytests/unit/states/file/test_copy.py b/tests/pytests/unit/states/file/test_copy.py -index ce7161f02d..a11adf5ae0 100644 ---- a/tests/pytests/unit/states/file/test_copy.py -+++ b/tests/pytests/unit/states/file/test_copy.py -@@ -205,3 +205,38 @@ def test_copy(tmp_path): - ) - res = filestate.copy_(name, source, group=group, preserve=False) - assert res == ret -+ -+ -+def test_copy_test_mode_user_group_not_present(): -+ """ -+ Test file copy in test mode with no user or group existing -+ """ -+ source = "/tmp/src_copy_no_user_group_test_mode" -+ filename = "/tmp/copy_no_user_group_test_mode" -+ with patch.dict( -+ filestate.__salt__, -+ { -+ "file.group_to_gid": MagicMock(side_effect=["1234", "", ""]), -+ "file.user_to_uid": MagicMock(side_effect=["", "4321", ""]), -+ "file.get_mode": MagicMock(return_value="0644"), -+ }, -+ ), patch.dict(filestate.__opts__, {"test": True}), patch.object( -+ os.path, "exists", return_value=True -+ ): -+ ret = filestate.copy_( -+ source, filename, group="nonexistinggroup", user="nonexistinguser" -+ ) -+ assert ret["result"] is not False -+ assert "is not available" not in ret["comment"] -+ -+ ret = filestate.copy_( -+ source, filename, group="nonexistinggroup", user="nonexistinguser" -+ ) -+ assert ret["result"] is not False -+ assert "is not available" not in ret["comment"] -+ -+ ret = filestate.copy_( -+ source, filename, group="nonexistinggroup", user="nonexistinguser" -+ ) -+ assert ret["result"] is not False -+ assert "is not available" not in ret["comment"] -diff --git a/tests/pytests/unit/states/file/test_filestate.py b/tests/pytests/unit/states/file/test_filestate.py -index 2f9f369fb2..c373cb3449 100644 ---- a/tests/pytests/unit/states/file/test_filestate.py -+++ b/tests/pytests/unit/states/file/test_filestate.py -@@ -577,3 +577,45 @@ def test_mod_run_check_cmd(): - assert filestate.mod_run_check_cmd(cmd, filename) == ret - - assert filestate.mod_run_check_cmd(cmd, filename) -+ -+ -+def test_recurse_test_mode_user_group_not_present(): -+ """ -+ Test file recurse in test mode with no user or group existing -+ """ -+ filename = "/tmp/recurse_no_user_group_test_mode" -+ source = "salt://tmp/src_recurse_no_user_group_test_mode" -+ mock_l = MagicMock(return_value=[]) -+ mock_emt = MagicMock(return_value=["tmp/src_recurse_no_user_group_test_mode"]) -+ with patch.dict( -+ filestate.__salt__, -+ { -+ "file.group_to_gid": MagicMock(side_effect=["1234", "", ""]), -+ "file.user_to_uid": MagicMock(side_effect=["", "4321", ""]), -+ "file.get_mode": MagicMock(return_value="0644"), -+ "file.source_list": MagicMock(return_value=[source, ""]), -+ "cp.list_master_dirs": mock_emt, -+ "cp.list_master": mock_l, -+ }, -+ ), patch.dict(filestate.__opts__, {"test": True}), patch.object( -+ os.path, "exists", return_value=True -+ ), patch.object( -+ os.path, "isdir", return_value=True -+ ): -+ ret = filestate.recurse( -+ filename, source, group="nonexistinggroup", user="nonexistinguser" -+ ) -+ assert ret["result"] is not False -+ assert "is not available" not in ret["comment"] -+ -+ ret = filestate.recurse( -+ filename, source, group="nonexistinggroup", user="nonexistinguser" -+ ) -+ assert ret["result"] is not False -+ assert "is not available" not in ret["comment"] -+ -+ ret = filestate.recurse( -+ filename, source, group="nonexistinggroup", user="nonexistinguser" -+ ) -+ assert ret["result"] is not False -+ assert "is not available" not in ret["comment"] -diff --git a/tests/pytests/unit/states/file/test_managed.py b/tests/pytests/unit/states/file/test_managed.py -index 9d9fb17717..0b341e09a9 100644 ---- a/tests/pytests/unit/states/file/test_managed.py -+++ b/tests/pytests/unit/states/file/test_managed.py -@@ -373,3 +373,34 @@ def test_managed(): - filestate.managed(name, user=user, group=group) - == ret - ) -+ -+ -+def test_managed_test_mode_user_group_not_present(): -+ """ -+ Test file managed in test mode with no user or group existing -+ """ -+ filename = "/tmp/managed_no_user_group_test_mode" -+ with patch.dict( -+ filestate.__salt__, -+ { -+ "file.group_to_gid": MagicMock(side_effect=["1234", "", ""]), -+ "file.user_to_uid": MagicMock(side_effect=["", "4321", ""]), -+ }, -+ ), patch.dict(filestate.__opts__, {"test": True}): -+ ret = filestate.managed( -+ filename, group="nonexistinggroup", user="nonexistinguser" -+ ) -+ assert ret["result"] is not False -+ assert "is not available" not in ret["comment"] -+ -+ ret = filestate.managed( -+ filename, group="nonexistinggroup", user="nonexistinguser" -+ ) -+ assert ret["result"] is not False -+ assert "is not available" not in ret["comment"] -+ -+ ret = filestate.managed( -+ filename, group="nonexistinggroup", user="nonexistinguser" -+ ) -+ assert ret["result"] is not False -+ assert "is not available" not in ret["comment"] --- -2.37.3 - - diff --git a/fix-test_ipc-unit-tests.patch b/fix-test_ipc-unit-tests.patch deleted file mode 100644 index 5a24a11..0000000 --- a/fix-test_ipc-unit-tests.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 4cc528dadfbffdeb90df41bbd848d0c2c7efec78 Mon Sep 17 00:00:00 2001 -From: Alexander Graul -Date: Tue, 12 Jul 2022 14:02:58 +0200 -Subject: [PATCH] Fix test_ipc unit tests - ---- - tests/unit/transport/test_ipc.py | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/tests/unit/transport/test_ipc.py b/tests/unit/transport/test_ipc.py -index 4a0a7c29e2..af001d9650 100644 ---- a/tests/unit/transport/test_ipc.py -+++ b/tests/unit/transport/test_ipc.py -@@ -105,8 +105,8 @@ class IPCMessagePubSubCase(salt.ext.tornado.testing.AsyncTestCase): - self.stop() - - # Now let both waiting data at once -- client1.read_async(handler) -- client2.read_async(handler) -+ client1.read_async() -+ client2.read_async() - self.pub_channel.publish("TEST") - self.wait() - self.assertEqual(len(call_cnt), 2) -@@ -148,7 +148,7 @@ class IPCMessagePubSubCase(salt.ext.tornado.testing.AsyncTestCase): - pass - - try: -- ret1 = yield client1.read_async(handler) -+ ret1 = yield client1.read_async() - self.wait() - except StreamClosedError as ex: - assert False, "StreamClosedError was raised inside the Future" --- -2.37.3 - - diff --git a/fix-the-regression-for-yumnotify-plugin-456.patch b/fix-the-regression-for-yumnotify-plugin-456.patch index e8532c8..c12e2e3 100644 --- a/fix-the-regression-for-yumnotify-plugin-456.patch +++ b/fix-the-regression-for-yumnotify-plugin-456.patch @@ -1,4 +1,4 @@ -From 48a924bfad537f236593395a9d4cf108d6e9a03f Mon Sep 17 00:00:00 2001 +From b80c0d515e8715c160f94124dff8b5b90e773cd0 Mon Sep 17 00:00:00 2001 From: Victor Zhestkov <35733135+vzhestkov@users.noreply.github.com> Date: Tue, 9 Nov 2021 16:19:56 +0300 Subject: [PATCH] Fix the regression for yumnotify plugin (#456) @@ -18,6 +18,6 @@ index 0d117e8946..cec5256d20 100644 - print("Unable to save the cookie file: %s" % (e), file=sys.stderr) + sys.stderr.write("Unable to save the cookie file: %s\n" % (e)) -- -2.37.3 +2.39.2 diff --git a/fix-traceback.print_exc-calls-for-test_pip_state-432.patch b/fix-traceback.print_exc-calls-for-test_pip_state-432.patch index 822521f..a063edf 100644 --- a/fix-traceback.print_exc-calls-for-test_pip_state-432.patch +++ b/fix-traceback.print_exc-calls-for-test_pip_state-432.patch @@ -1,4 +1,4 @@ -From 8b07b529458e1fc007c8ee848d66035b3403a22d Mon Sep 17 00:00:00 2001 +From c37992e305978e95da1ac0a40a8142f578271320 Mon Sep 17 00:00:00 2001 From: Victor Zhestkov <35733135+vzhestkov@users.noreply.github.com> Date: Mon, 8 Nov 2021 17:43:02 +0300 Subject: [PATCH] Fix traceback.print_exc calls for test_pip_state (#432) @@ -8,10 +8,10 @@ Subject: [PATCH] Fix traceback.print_exc calls for test_pip_state (#432) 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/states/test_pip_state.py b/tests/unit/states/test_pip_state.py -index 93b8b3bd71..9531b6d2be 100644 +index 5e4b6e0af1..981ad46a13 100644 --- a/tests/unit/states/test_pip_state.py +++ b/tests/unit/states/test_pip_state.py -@@ -441,7 +441,7 @@ class PipStateInstallationErrorTest(TestCase): +@@ -442,7 +442,7 @@ class PipStateInstallationErrorTest(TestCase): sys.stdout.flush() sys.exit(2) except Exception as exc: @@ -21,6 +21,6 @@ index 93b8b3bd71..9531b6d2be 100644 sys.exit(3) sys.exit(0) -- -2.37.3 +2.39.2 diff --git a/fix-version-detection-and-avoid-building-and-testing.patch b/fix-version-detection-and-avoid-building-and-testing.patch new file mode 100644 index 0000000..0b18663 --- /dev/null +++ b/fix-version-detection-and-avoid-building-and-testing.patch @@ -0,0 +1,58 @@ +From c0fae09e5a4f6997a60007d970c7c6a5614d9102 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?= + +Date: Wed, 19 Apr 2023 10:41:28 +0100 +Subject: [PATCH] Fix version detection and avoid building and testing + failures + +--- + salt/version.py | 20 ++------------------ + 1 file changed, 2 insertions(+), 18 deletions(-) + +diff --git a/salt/version.py b/salt/version.py +index 43cb5f86f7..67719bd020 100644 +--- a/salt/version.py ++++ b/salt/version.py +@@ -1,7 +1,6 @@ + """ + Set up the version of Salt + """ +-import argparse + import operator + import os + import platform +@@ -78,7 +77,7 @@ class SaltVersionsInfo(type): + ALUMINIUM = SaltVersion("Aluminium" , info=3003, released=True) + SILICON = SaltVersion("Silicon" , info=3004, released=True) + PHOSPHORUS = SaltVersion("Phosphorus" , info=3005, released=True) +- SULFUR = SaltVersion("Sulfur" , info=(3006, 0), released=True) ++ SULFUR = SaltVersion("Sulfur" , info=(3006, 0)) + CHLORINE = SaltVersion("Chlorine" , info=(3007, 0)) + ARGON = SaltVersion("Argon" , info=(3008, 0)) + POTASSIUM = SaltVersion("Potassium" , info=(3009, 0)) +@@ -922,20 +921,5 @@ def versions_report(include_salt_cloud=False, include_extensions=True): + yield from info + + +-def _parser(): +- parser = argparse.ArgumentParser() +- parser.add_argument( +- "--next-release", help="Return the next release", action="store_true" +- ) +- # When pip installing we pass in other args to this script. +- # This allows us to catch those args but not use them +- parser.add_argument("unknown", nargs=argparse.REMAINDER) +- return parser.parse_args() +- +- + if __name__ == "__main__": +- args = _parser() +- if args.next_release: +- print(__saltstack_version__.next_release()) +- else: +- print(__version__) ++ print(__version__) +-- +2.39.2 + + diff --git a/fixes-for-python-3.10-502.patch b/fixes-for-python-3.10-502.patch index 053ed45..890d439 100644 --- a/fixes-for-python-3.10-502.patch +++ b/fixes-for-python-3.10-502.patch @@ -1,4 +1,4 @@ -From d5fae6bd4a4f243115ee220393e05440f0d48b5a Mon Sep 17 00:00:00 2001 +From 4996f423f14369fad14a9e6d2d3b8bd750c77fc7 Mon Sep 17 00:00:00 2001 From: Victor Zhestkov Date: Tue, 5 Apr 2022 12:04:46 +0300 Subject: [PATCH] Fixes for Python 3.10 (#502) @@ -9,7 +9,7 @@ Subject: [PATCH] Fixes for Python 3.10 (#502) 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/salt/state.py b/salt/state.py -index f5579fbb69..61519d5042 100644 +index ab84cb8b4d..489424a083 100644 --- a/salt/state.py +++ b/salt/state.py @@ -12,7 +12,6 @@ The data sent to the state calls is as follows: @@ -20,7 +20,7 @@ index f5579fbb69..61519d5042 100644 import copy import datetime import fnmatch -@@ -26,6 +25,8 @@ import sys +@@ -27,6 +26,8 @@ import sys import time import traceback @@ -29,7 +29,7 @@ index f5579fbb69..61519d5042 100644 import salt.channel.client import salt.fileclient import salt.loader -@@ -3405,7 +3406,7 @@ class State: +@@ -3513,7 +3514,7 @@ class State: """ for chunk in high: state = high[chunk] @@ -39,6 +39,6 @@ index f5579fbb69..61519d5042 100644 for state_ref in state: needs_default = True -- -2.37.3 +2.39.2 diff --git a/fixes-pkg.version_cmp-on-openeuler-systems-and-a-few.patch b/fixes-pkg.version_cmp-on-openeuler-systems-and-a-few.patch deleted file mode 100644 index 3d66c74..0000000 --- a/fixes-pkg.version_cmp-on-openeuler-systems-and-a-few.patch +++ /dev/null @@ -1,103 +0,0 @@ -From 62b3e3491f283a5b5ac243e1f5904ad17e0353bc Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Ra=C3=BAl=20Osuna?= - <17827278+raulillo82@users.noreply.github.com> -Date: Tue, 31 Jan 2023 13:13:32 +0100 -Subject: [PATCH] Fixes pkg.version_cmp on openEuler systems and a few - other OS flavors (#576) - -* Fix bug/issue #540 - -* Fix bug/issue #540 - -* Add tests for __virtual__ function - -* Minor changes to align with upstream ---- - changelog/540.fixed | 1 + - salt/modules/rpm_lowpkg.py | 12 +++++-- - tests/pytests/unit/modules/test_rpm_lowpkg.py | 31 +++++++++++++++++++ - 3 files changed, 42 insertions(+), 2 deletions(-) - create mode 100644 changelog/540.fixed - -diff --git a/changelog/540.fixed b/changelog/540.fixed -new file mode 100644 -index 0000000000..50cb42bf40 ---- /dev/null -+++ b/changelog/540.fixed -@@ -0,0 +1 @@ -+Fix pkg.version_cmp on openEuler and a few other os flavors. -diff --git a/salt/modules/rpm_lowpkg.py b/salt/modules/rpm_lowpkg.py -index c8e984c021..01cd575bc7 100644 ---- a/salt/modules/rpm_lowpkg.py -+++ b/salt/modules/rpm_lowpkg.py -@@ -62,14 +62,22 @@ def __virtual__(): - " grains.", - ) - -- enabled = ("amazon", "xcp", "xenserver", "virtuozzolinux") -+ enabled = ( -+ "amazon", -+ "xcp", -+ "xenserver", -+ "virtuozzolinux", -+ "virtuozzo", -+ "issabel pbx", -+ "openeuler", -+ ) - - if os_family in ["redhat", "suse"] or os_grain in enabled: - return __virtualname__ - return ( - False, - "The rpm execution module failed to load: only available on redhat/suse type" -- " systems or amazon, xcp or xenserver.", -+ " systems or amazon, xcp, xenserver, virtuozzolinux, virtuozzo, issabel pbx or openeuler.", - ) - - -diff --git a/tests/pytests/unit/modules/test_rpm_lowpkg.py b/tests/pytests/unit/modules/test_rpm_lowpkg.py -index f19afa854e..e07f71eb61 100644 ---- a/tests/pytests/unit/modules/test_rpm_lowpkg.py -+++ b/tests/pytests/unit/modules/test_rpm_lowpkg.py -@@ -35,6 +35,37 @@ def _called_with_root(mock): - def configure_loader_modules(): - return {rpm: {"rpm": MagicMock(return_value=MagicMock)}} - -+def test___virtual___openeuler(): -+ patch_which = patch("salt.utils.path.which", return_value=True) -+ with patch.dict( -+ rpm.__grains__, {"os": "openEuler", "os_family": "openEuler"} -+ ), patch_which: -+ assert rpm.__virtual__() == "lowpkg" -+ -+ -+def test___virtual___issabel_pbx(): -+ patch_which = patch("salt.utils.path.which", return_value=True) -+ with patch.dict( -+ rpm.__grains__, {"os": "Issabel Pbx", "os_family": "IssabeL PBX"} -+ ), patch_which: -+ assert rpm.__virtual__() == "lowpkg" -+ -+ -+def test___virtual___virtuozzo(): -+ patch_which = patch("salt.utils.path.which", return_value=True) -+ with patch.dict( -+ rpm.__grains__, {"os": "virtuozzo", "os_family": "VirtuoZZO"} -+ ), patch_which: -+ assert rpm.__virtual__() == "lowpkg" -+ -+ -+def test___virtual___with_no_rpm(): -+ patch_which = patch("salt.utils.path.which", return_value=False) -+ ret = rpm.__virtual__() -+ assert isinstance(ret, tuple) -+ assert ret[0] is False -+ -+ - - # 'list_pkgs' function tests: 2 - --- -2.37.3 - - diff --git a/fopen-workaround-bad-buffering-for-binary-mode-563.patch b/fopen-workaround-bad-buffering-for-binary-mode-563.patch deleted file mode 100644 index e68ddd2..0000000 --- a/fopen-workaround-bad-buffering-for-binary-mode-563.patch +++ /dev/null @@ -1,105 +0,0 @@ -From 7d5b1d2178d0573f137b9481ded85419a36998ff Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?= - -Date: Thu, 6 Oct 2022 10:55:50 +0100 -Subject: [PATCH] fopen: Workaround bad buffering for binary mode (#563) -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -A lot of code assumes Python 2.x behavior for buffering, in which 1 is a -special value meaning line buffered. - -Python 3 makes this value unusable, so fallback to the default buffering -size, and report these calls to be fixed. - -Fixes: https://github.com/saltstack/salt/issues/57584 - -Do not drop buffering from kwargs to avoid errors - -Add unit test around linebuffering in binary mode - -Add changelog file - -Co-authored-by: Pablo Suárez Hernández - -Co-authored-by: Ismael Luceno ---- - changelog/62817.fixed | 1 + - salt/utils/files.py | 8 ++++++++ - tests/pytests/unit/utils/test_files.py | 13 ++++++++++++- - 3 files changed, 21 insertions(+), 1 deletion(-) - create mode 100644 changelog/62817.fixed - -diff --git a/changelog/62817.fixed b/changelog/62817.fixed -new file mode 100644 -index 0000000000..ff335f2916 ---- /dev/null -+++ b/changelog/62817.fixed -@@ -0,0 +1 @@ -+Prevent annoying RuntimeWarning message about line buffering (buffering=1) not being supported in binary mode -diff --git a/salt/utils/files.py b/salt/utils/files.py -index 1cf636a753..3c57cce713 100644 ---- a/salt/utils/files.py -+++ b/salt/utils/files.py -@@ -6,6 +6,7 @@ Functions for working with files - import codecs - import contextlib - import errno -+import io - import logging - import os - import re -@@ -382,6 +383,13 @@ def fopen(*args, **kwargs): - if not binary and not kwargs.get("newline", None): - kwargs["newline"] = "" - -+ # Workaround callers with bad buffering setting for binary files -+ if kwargs.get("buffering") == 1 and "b" in kwargs.get("mode", ""): -+ log.debug( -+ "Line buffering (buffering=1) isn't supported in binary mode, the default buffer size will be used" -+ ) -+ kwargs["buffering"] = io.DEFAULT_BUFFER_SIZE -+ - f_handle = open(*args, **kwargs) # pylint: disable=resource-leakage - - if is_fcntl_available(): -diff --git a/tests/pytests/unit/utils/test_files.py b/tests/pytests/unit/utils/test_files.py -index fd88167b16..bd18bc5750 100644 ---- a/tests/pytests/unit/utils/test_files.py -+++ b/tests/pytests/unit/utils/test_files.py -@@ -4,11 +4,12 @@ Unit Tests for functions located in salt/utils/files.py - - - import copy -+import io - import os - - import pytest - import salt.utils.files --from tests.support.mock import patch -+from tests.support.mock import MagicMock, patch - - - def test_safe_rm(): -@@ -74,6 +75,16 @@ def test_fopen_with_disallowed_fds(): - ) - - -+def test_fopen_binary_line_buffering(tmp_path): -+ tmp_file = os.path.join(tmp_path, "foobar") -+ with patch("builtins.open") as open_mock, patch( -+ "salt.utils.files.is_fcntl_available", MagicMock(return_value=False) -+ ): -+ salt.utils.files.fopen(os.path.join(tmp_path, "foobar"), mode="b", buffering=1) -+ assert open_mock.called -+ assert open_mock.call_args[1]["buffering"] == io.DEFAULT_BUFFER_SIZE -+ -+ - def _create_temp_structure(temp_directory, structure): - for folder, files in structure.items(): - current_directory = os.path.join(temp_directory, folder) --- -2.37.3 - - diff --git a/html.tar.bz2 b/html.tar.bz2 index 4eabcb6..88d8461 100644 --- a/html.tar.bz2 +++ b/html.tar.bz2 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:82795a90cebe98e39a7fc513144a45686bcbe13806c1ad233cb371c120af2bc7 -size 10525087 +oid sha256:f6fba74e3093218b099e917e5ae52eb3ecdea2a7611b7b46b91dfca518e2a022 +size 10804131 diff --git a/ignore-erros-on-reading-license-files-with-dpkg_lowp.patch b/ignore-erros-on-reading-license-files-with-dpkg_lowp.patch deleted file mode 100644 index 3b9c808..0000000 --- a/ignore-erros-on-reading-license-files-with-dpkg_lowp.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 7cac5f67eb0d586314f9e7c987b8a620e28eeac3 Mon Sep 17 00:00:00 2001 -From: Victor Zhestkov -Date: Mon, 27 Jun 2022 17:55:49 +0300 -Subject: [PATCH] Ignore erros on reading license files with dpkg_lowpkg - (bsc#1197288) - -* Ignore erros on reading license files with dpkg_lowpkg (bsc#1197288) - -* Add test for license reading with dpkg_lowpkg ---- - salt/modules/dpkg_lowpkg.py | 2 +- - tests/pytests/unit/modules/test_dpkg_lowpkg.py | 18 ++++++++++++++++++ - 2 files changed, 19 insertions(+), 1 deletion(-) - create mode 100644 tests/pytests/unit/modules/test_dpkg_lowpkg.py - -diff --git a/salt/modules/dpkg_lowpkg.py b/salt/modules/dpkg_lowpkg.py -index afbd619490..2c25b1fb2a 100644 ---- a/salt/modules/dpkg_lowpkg.py -+++ b/salt/modules/dpkg_lowpkg.py -@@ -361,7 +361,7 @@ def _get_pkg_license(pkg): - licenses = set() - cpr = "/usr/share/doc/{}/copyright".format(pkg) - if os.path.exists(cpr): -- with salt.utils.files.fopen(cpr) as fp_: -+ with salt.utils.files.fopen(cpr, errors="ignore") as fp_: - for line in salt.utils.stringutils.to_unicode(fp_.read()).split(os.linesep): - if line.startswith("License:"): - licenses.add(line.split(":", 1)[1].strip()) -diff --git a/tests/pytests/unit/modules/test_dpkg_lowpkg.py b/tests/pytests/unit/modules/test_dpkg_lowpkg.py -new file mode 100644 -index 0000000000..1a89660c02 ---- /dev/null -+++ b/tests/pytests/unit/modules/test_dpkg_lowpkg.py -@@ -0,0 +1,18 @@ -+import os -+ -+import salt.modules.dpkg_lowpkg as dpkg -+from tests.support.mock import MagicMock, mock_open, patch -+ -+ -+def test_get_pkg_license(): -+ """ -+ Test _get_pkg_license for ignore errors on reading license from copyright files -+ """ -+ license_read_mock = mock_open(read_data="") -+ with patch.object(os.path, "exists", MagicMock(return_value=True)), patch( -+ "salt.utils.files.fopen", license_read_mock -+ ): -+ dpkg._get_pkg_license("bash") -+ -+ assert license_read_mock.calls[0].args[0] == "/usr/share/doc/bash/copyright" -+ assert license_read_mock.calls[0].kwargs["errors"] == "ignore" --- -2.37.3 - - diff --git a/ignore-extend-declarations-from-excluded-sls-files.patch b/ignore-extend-declarations-from-excluded-sls-files.patch deleted file mode 100644 index 619ac0a..0000000 --- a/ignore-extend-declarations-from-excluded-sls-files.patch +++ /dev/null @@ -1,250 +0,0 @@ -From e4aff9ca68ce142c87ec875846d8916b9df8e6c5 Mon Sep 17 00:00:00 2001 -From: Alexander Graul -Date: Fri, 21 Oct 2022 14:39:52 +0200 -Subject: [PATCH] Ignore extend declarations from excluded sls files - -* Use both test sls files - -(cherry picked from commit 3cb5f5a14ff68d0bd809a4adba7d820534d0f7c7) - -* Test that excluded sls files can't extend others - -(cherry picked from commit e91c1a608b3c016b2c30bf324e969cd097ddf776) - -* Ignore extend declarations from excluded sls files - -sls files that are excluded should not affect other sls files by -extending their states. Exclude statements are processed very late in -the state processing pipeline to ensure they are not overridden. By that -time, extend declarations are already processed. - -Luckily, it's not necessary to change much, during the extend -declarations processing it is easy to check if the sls file that -contains a given extend declaration is excluded. - -(cherry picked from commit 856b23c45dd3be78d8879a0b0c4aa6356afea3cf) ---- - changelog/62082.fixed | 1 + - salt/state.py | 19 +++ - .../unit/state/test_state_highstate.py | 152 +++++++++++++++++- - 3 files changed, 171 insertions(+), 1 deletion(-) - create mode 100644 changelog/62082.fixed - -diff --git a/changelog/62082.fixed b/changelog/62082.fixed -new file mode 100644 -index 0000000000..02e5f5ff40 ---- /dev/null -+++ b/changelog/62082.fixed -@@ -0,0 +1 @@ -+Ignore extend declarations in sls files that are excluded. -diff --git a/salt/state.py b/salt/state.py -index 316dcdec63..f5579fbb69 100644 ---- a/salt/state.py -+++ b/salt/state.py -@@ -1680,6 +1680,25 @@ class State: - else: - name = ids[0][0] - -+ sls_excludes = [] -+ # excluded sls are plain list items or dicts with an "sls" key -+ for exclude in high.get("__exclude__", []): -+ if isinstance(exclude, str): -+ sls_excludes.append(exclude) -+ elif exclude.get("sls"): -+ sls_excludes.append(exclude["sls"]) -+ -+ if body.get("__sls__") in sls_excludes: -+ log.debug( -+ "Cannot extend ID '%s' in '%s:%s' because '%s:%s' is excluded.", -+ name, -+ body.get("__env__", "base"), -+ body.get("__sls__", "base"), -+ body.get("__env__", "base"), -+ body.get("__sls__", "base"), -+ ) -+ continue -+ - for state, run in body.items(): - if state.startswith("__"): - continue -diff --git a/tests/pytests/unit/state/test_state_highstate.py b/tests/pytests/unit/state/test_state_highstate.py -index 059f83fd9f..7c72cc8e09 100644 ---- a/tests/pytests/unit/state/test_state_highstate.py -+++ b/tests/pytests/unit/state/test_state_highstate.py -@@ -3,9 +3,11 @@ - """ - - import logging -+import textwrap - - import pytest # pylint: disable=unused-import - import salt.state -+from salt.utils.odict import OrderedDict - - log = logging.getLogger(__name__) - -@@ -180,7 +182,7 @@ def test_find_sls_ids_with_exclude(highstate, state_tree_dir): - with pytest.helpers.temp_file( - "slsfile1.sls", slsfile1, sls_dir - ), pytest.helpers.temp_file( -- "slsfile1.sls", slsfile1, sls_dir -+ "slsfile2.sls", slsfile2, sls_dir - ), pytest.helpers.temp_file( - "stateB.sls", stateB, sls_dir - ), pytest.helpers.temp_file( -@@ -196,3 +198,151 @@ def test_find_sls_ids_with_exclude(highstate, state_tree_dir): - high, _ = highstate.render_highstate(matches) - ret = salt.state.find_sls_ids("issue-47182.stateA.newer", high) - assert ret == [("somestuff", "cmd")] -+ -+ -+def test_dont_extend_in_excluded_sls_file(highstate, state_tree_dir): -+ """ -+ See https://github.com/saltstack/salt/issues/62082#issuecomment-1245461333 -+ """ -+ top_sls = textwrap.dedent( -+ """\ -+ base: -+ '*': -+ - test1 -+ - exclude -+ """ -+ ) -+ exclude_sls = textwrap.dedent( -+ """\ -+ exclude: -+ - sls: test2 -+ """ -+ ) -+ test1_sls = textwrap.dedent( -+ """\ -+ include: -+ - test2 -+ -+ test1: -+ cmd.run: -+ - name: echo test1 -+ """ -+ ) -+ test2_sls = textwrap.dedent( -+ """\ -+ extend: -+ test1: -+ cmd.run: -+ - name: echo "override test1 in test2" -+ -+ test2-id: -+ cmd.run: -+ - name: echo test2 -+ """ -+ ) -+ sls_dir = str(state_tree_dir) -+ with pytest.helpers.temp_file( -+ "top.sls", top_sls, sls_dir -+ ), pytest.helpers.temp_file( -+ "test1.sls", test1_sls, sls_dir -+ ), pytest.helpers.temp_file( -+ "test2.sls", test2_sls, sls_dir -+ ), pytest.helpers.temp_file( -+ "exclude.sls", exclude_sls, sls_dir -+ ): -+ # manually compile the high data, error checking is not needed in this -+ # test case. -+ top = highstate.get_top() -+ matches = highstate.top_matches(top) -+ high, _ = highstate.render_highstate(matches) -+ -+ # high is mutated by call_high and the different "pipeline steps" -+ assert high == OrderedDict( -+ [ -+ ( -+ "__extend__", -+ [ -+ { -+ "test1": OrderedDict( -+ [ -+ ("__sls__", "test2"), -+ ("__env__", "base"), -+ ( -+ "cmd", -+ [ -+ OrderedDict( -+ [ -+ ( -+ "name", -+ 'echo "override test1 in test2"', -+ ) -+ ] -+ ), -+ "run", -+ ], -+ ), -+ ] -+ ) -+ } -+ ], -+ ), -+ ( -+ "test1", -+ OrderedDict( -+ [ -+ ( -+ "cmd", -+ [ -+ OrderedDict([("name", "echo test1")]), -+ "run", -+ {"order": 10001}, -+ ], -+ ), -+ ("__sls__", "test1"), -+ ("__env__", "base"), -+ ] -+ ), -+ ), -+ ( -+ "test2-id", -+ OrderedDict( -+ [ -+ ( -+ "cmd", -+ [ -+ OrderedDict([("name", "echo test2")]), -+ "run", -+ {"order": 10000}, -+ ], -+ ), -+ ("__sls__", "test2"), -+ ("__env__", "base"), -+ ] -+ ), -+ ), -+ ("__exclude__", [OrderedDict([("sls", "test2")])]), -+ ] -+ ) -+ highstate.state.call_high(high) -+ # assert that the extend declaration was not applied -+ assert high == OrderedDict( -+ [ -+ ( -+ "test1", -+ OrderedDict( -+ [ -+ ( -+ "cmd", -+ [ -+ OrderedDict([("name", "echo test1")]), -+ "run", -+ {"order": 10001}, -+ ], -+ ), -+ ("__sls__", "test1"), -+ ("__env__", "base"), -+ ] -+ ), -+ ) -+ ] -+ ) --- -2.37.3 - - diff --git a/ignore-non-utf8-characters-while-reading-files-with-.patch b/ignore-non-utf8-characters-while-reading-files-with-.patch deleted file mode 100644 index 4fb2242..0000000 --- a/ignore-non-utf8-characters-while-reading-files-with-.patch +++ /dev/null @@ -1,214 +0,0 @@ -From 3f1b1180ba34e9ab3a4453248c733f11aa193f1b Mon Sep 17 00:00:00 2001 -From: Victor Zhestkov -Date: Wed, 14 Sep 2022 14:57:29 +0300 -Subject: [PATCH] Ignore non utf8 characters while reading files with - core grains module (bsc#1202165) - -* Ignore UnicodeDecodeError on reading files with core grains - -* Add tests for non utf8 chars in cmdline - -* Blacken modified lines - -* Fix the tests - -* Add changelog entry - -* Change ignore to surrogateescape for kernelparameters - -* Turn static test files to dynamic ---- - changelog/62633.fixed | 1 + - salt/grains/core.py | 12 ++- - tests/pytests/unit/grains/test_core.py | 118 +++++++++++++++++++++++++ - 3 files changed, 128 insertions(+), 3 deletions(-) - create mode 100644 changelog/62633.fixed - -diff --git a/changelog/62633.fixed b/changelog/62633.fixed -new file mode 100644 -index 0000000000..1ab74f9122 ---- /dev/null -+++ b/changelog/62633.fixed -@@ -0,0 +1 @@ -+Prevent possible tracebacks in core grains module by ignoring non utf8 characters in /proc/1/environ, /proc/1/cmdline, /proc/cmdline -diff --git a/salt/grains/core.py b/salt/grains/core.py -index 047c33ffd3..76f3767ddf 100644 ---- a/salt/grains/core.py -+++ b/salt/grains/core.py -@@ -1089,7 +1089,9 @@ def _virtual(osdata): - if ("virtual_subtype" not in grains) or (grains["virtual_subtype"] != "LXC"): - if os.path.isfile("/proc/1/environ"): - try: -- with salt.utils.files.fopen("/proc/1/environ", "r") as fhr: -+ with salt.utils.files.fopen( -+ "/proc/1/environ", "r", errors="ignore" -+ ) as fhr: - fhr_contents = fhr.read() - if "container=lxc" in fhr_contents: - grains["virtual"] = "container" -@@ -1909,7 +1911,9 @@ def os_data(): - grains["init"] = "systemd" - except OSError: - try: -- with salt.utils.files.fopen("/proc/1/cmdline") as fhr: -+ with salt.utils.files.fopen( -+ "/proc/1/cmdline", "r", errors="ignore" -+ ) as fhr: - init_cmdline = fhr.read().replace("\x00", " ").split() - except OSError: - pass -@@ -3154,7 +3158,9 @@ def kernelparams(): - return {} - else: - try: -- with salt.utils.files.fopen("/proc/cmdline", "r") as fhr: -+ with salt.utils.files.fopen( -+ "/proc/cmdline", "r", errors="surrogateescape" -+ ) as fhr: - cmdline = fhr.read() - grains = {"kernelparams": []} - for data in [ -diff --git a/tests/pytests/unit/grains/test_core.py b/tests/pytests/unit/grains/test_core.py -index 7c4ea1f17f..c06cdb2db0 100644 ---- a/tests/pytests/unit/grains/test_core.py -+++ b/tests/pytests/unit/grains/test_core.py -@@ -11,6 +11,7 @@ import os - import pathlib - import platform - import socket -+import tempfile - import textwrap - from collections import namedtuple - -@@ -2738,6 +2739,38 @@ def test_kernelparams_return_linux(cmdline, expectation): - assert core.kernelparams() == expectation - - -+@pytest.mark.skip_unless_on_linux -+def test_kernelparams_return_linux_non_utf8(): -+ _salt_utils_files_fopen = salt.utils.files.fopen -+ -+ expected = { -+ "kernelparams": [ -+ ("TEST_KEY1", "VAL1"), -+ ("TEST_KEY2", "VAL2"), -+ ("BOOTABLE_FLAG", "\udc80"), -+ ("TEST_KEY_NOVAL", None), -+ ("TEST_KEY3", "3"), -+ ] -+ } -+ -+ with tempfile.TemporaryDirectory() as tempdir: -+ -+ def _open_mock(file_name, *args, **kwargs): -+ return _salt_utils_files_fopen( -+ os.path.join(tempdir, "cmdline"), *args, **kwargs -+ ) -+ -+ with salt.utils.files.fopen( -+ os.path.join(tempdir, "cmdline"), -+ "wb", -+ ) as cmdline_fh, patch("salt.utils.files.fopen", _open_mock): -+ cmdline_fh.write( -+ b'TEST_KEY1=VAL1 TEST_KEY2=VAL2 BOOTABLE_FLAG="\x80" TEST_KEY_NOVAL TEST_KEY3=3\n' -+ ) -+ cmdline_fh.close() -+ assert core.kernelparams() == expected -+ -+ - def test_linux_gpus(): - """ - Test GPU detection on Linux systems -@@ -2940,3 +2973,88 @@ def test_virtual_set_virtual_ec2(): - - assert virtual_grains["virtual"] == "kvm" - assert "virtual_subtype" not in virtual_grains -+ -+ -+@pytest.mark.skip_on_windows -+def test_linux_proc_files_with_non_utf8_chars(): -+ _salt_utils_files_fopen = salt.utils.files.fopen -+ -+ empty_mock = MagicMock(return_value={}) -+ -+ with tempfile.TemporaryDirectory() as tempdir: -+ -+ def _mock_open(filename, *args, **kwargs): -+ return _salt_utils_files_fopen( -+ os.path.join(tempdir, "cmdline-1"), *args, **kwargs -+ ) -+ -+ with salt.utils.files.fopen( -+ os.path.join(tempdir, "cmdline-1"), -+ "wb", -+ ) as cmdline_fh, patch("os.path.isfile", return_value=False), patch( -+ "salt.utils.files.fopen", _mock_open -+ ), patch.dict( -+ core.__salt__, -+ { -+ "cmd.retcode": salt.modules.cmdmod.retcode, -+ "cmd.run": MagicMock(return_value=""), -+ }, -+ ), patch.object( -+ core, "_linux_bin_exists", return_value=False -+ ), patch.object( -+ core, "_parse_lsb_release", return_value=empty_mock -+ ), patch.object( -+ core, "_parse_os_release", return_value=empty_mock -+ ), patch.object( -+ core, "_hw_data", return_value=empty_mock -+ ), patch.object( -+ core, "_virtual", return_value=empty_mock -+ ), patch.object( -+ core, "_bsd_cpudata", return_value=empty_mock -+ ), patch.object( -+ os, "stat", side_effect=OSError() -+ ): -+ cmdline_fh.write( -+ b"/usr/lib/systemd/systemd\x00--switched-root\x00--system\x00--deserialize\x0028\x80\x00" -+ ) -+ cmdline_fh.close() -+ os_grains = core.os_data() -+ assert os_grains != {} -+ -+ -+@pytest.mark.skip_on_windows -+def test_virtual_linux_proc_files_with_non_utf8_chars(): -+ _salt_utils_files_fopen = salt.utils.files.fopen -+ -+ def _is_file_mock(filename): -+ if filename == "/proc/1/environ": -+ return True -+ return False -+ -+ with tempfile.TemporaryDirectory() as tempdir: -+ -+ def _mock_open(filename, *args, **kwargs): -+ return _salt_utils_files_fopen( -+ os.path.join(tempdir, "environ"), *args, **kwargs -+ ) -+ -+ with salt.utils.files.fopen( -+ os.path.join(tempdir, "environ"), -+ "wb", -+ ) as environ_fh, patch("os.path.isfile", _is_file_mock), patch( -+ "salt.utils.files.fopen", _mock_open -+ ), patch.object( -+ salt.utils.path, "which", MagicMock(return_value=None) -+ ), patch.dict( -+ core.__salt__, -+ { -+ "cmd.run_all": MagicMock( -+ return_value={"retcode": 1, "stderr": "", "stdout": ""} -+ ), -+ "cmd.run": MagicMock(return_value=""), -+ }, -+ ): -+ environ_fh.write(b"KEY1=VAL1 KEY2=VAL2\x80 KEY2=VAL2") -+ environ_fh.close() -+ virt_grains = core._virtual({"kernel": "Linux"}) -+ assert virt_grains == {"virtual": "physical"} --- -2.37.3 - - diff --git a/include-aliases-in-the-fqdns-grains.patch b/include-aliases-in-the-fqdns-grains.patch index 602e78d..ab65d0b 100644 --- a/include-aliases-in-the-fqdns-grains.patch +++ b/include-aliases-in-the-fqdns-grains.patch @@ -1,4 +1,4 @@ -From 797b256548cbcda0f3828c6d182c44a3815dd313 Mon Sep 17 00:00:00 2001 +From 4f459d670886a8f4a410fdbd1ec595477d45e4e2 Mon Sep 17 00:00:00 2001 From: Alexander Graul Date: Tue, 18 Jan 2022 17:10:37 +0100 Subject: [PATCH] Include aliases in the fqdns grains @@ -31,10 +31,10 @@ Co-authored-by: Eric Siebigteroth 4 files changed, 54 insertions(+), 3 deletions(-) diff --git a/salt/modules/network.py b/salt/modules/network.py -index 1149c96097..8c2d188903 100644 +index 524b1b74fa..f959dbf97b 100644 --- a/salt/modules/network.py +++ b/salt/modules/network.py -@@ -2100,7 +2100,10 @@ def fqdns(): +@@ -2096,7 +2096,10 @@ def fqdns(): # https://sourceware.org/bugzilla/show_bug.cgi?id=19329 time.sleep(random.randint(5, 25) / 1000) try: @@ -47,13 +47,13 @@ index 1149c96097..8c2d188903 100644 if err.errno in (0, HOST_NOT_FOUND, NO_DATA): # No FQDN for this IP address, so we don't need to know this all the time. diff --git a/salt/utils/network.py b/salt/utils/network.py -index d042cd177d..bccda01556 100644 +index 2bea2cf129..6ec993a678 100644 --- a/salt/utils/network.py +++ b/salt/utils/network.py -@@ -2332,3 +2332,19 @@ def filter_by_networks(values, networks): - raise ValueError("Do not know how to filter a {}".format(type(values))) - else: - return values +@@ -2372,3 +2372,19 @@ def ip_bracket(addr, strip=False): + addr = addr.rstrip("]") + addr = ipaddress.ip_address(addr) + return ("[{}]" if addr.version == 6 and not strip else "{}").format(addr) + + +def is_fqdn(hostname): @@ -71,10 +71,10 @@ index d042cd177d..bccda01556 100644 + and all(compliant.match(x) for x in hostname.rstrip(".").split(".")) + ) diff --git a/tests/pytests/unit/modules/test_network.py b/tests/pytests/unit/modules/test_network.py -index 15fd5545a0..b948e578bb 100644 +index 81035434b6..3f31391f44 100644 --- a/tests/pytests/unit/modules/test_network.py +++ b/tests/pytests/unit/modules/test_network.py -@@ -28,7 +28,7 @@ def fake_fqdn(): +@@ -29,7 +29,7 @@ def fake_fqdn(): with patch("socket.getfqdn", autospec=True, return_value=fqdn), patch( "socket.gethostbyaddr", autospec=True, @@ -83,7 +83,7 @@ index 15fd5545a0..b948e578bb 100644 ): yield fqdn -@@ -88,7 +88,7 @@ def test_fqdns_should_return_sorted_unique_domains(fake_ips): +@@ -89,7 +89,7 @@ def test_fqdns_should_return_sorted_unique_domains(fake_ips): with patch("socket.getfqdn", autospec=True, side_effect=fake_domains), patch( "socket.gethostbyaddr", autospec=True, @@ -93,13 +93,13 @@ index 15fd5545a0..b948e578bb 100644 actual_fqdns = networkmod.fqdns() assert actual_fqdns == { diff --git a/tests/unit/utils/test_network.py b/tests/unit/utils/test_network.py -index 422f85d68c..3060aba0aa 100644 +index f7d3972930..cdb1ca19ca 100644 --- a/tests/unit/utils/test_network.py +++ b/tests/unit/utils/test_network.py -@@ -1269,3 +1269,35 @@ class NetworkTestCase(TestCase): - ), - ): - self.assertEqual(network.get_fqhostname(), host) +@@ -1311,3 +1311,35 @@ class NetworkTestCase(TestCase): + + ip_addr_obj = ipaddress.ip_address(test_ipv4) + self.assertEqual(test_ipv4, network.ip_bracket(ip_addr_obj)) + + def test_is_fqdn(self): + """ @@ -133,6 +133,6 @@ index 422f85d68c..3060aba0aa 100644 + ]: + assert not network.is_fqdn(fqdn) -- -2.37.3 +2.39.2 diff --git a/include-stdout-in-error-message-for-zypperpkg-559.patch b/include-stdout-in-error-message-for-zypperpkg-559.patch deleted file mode 100644 index 79615fe..0000000 --- a/include-stdout-in-error-message-for-zypperpkg-559.patch +++ /dev/null @@ -1,63 +0,0 @@ -From f9fe9ea009915478ea8f7896dff2c281e68b5d36 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Yeray=20Guti=C3=A9rrez=20Cedr=C3=A9s?= - -Date: Fri, 14 Oct 2022 08:41:40 +0100 -Subject: [PATCH] Include stdout in error message for zypperpkg (#559) - ---- - salt/modules/zypperpkg.py | 5 +++++ - tests/unit/modules/test_zypperpkg.py | 17 ++++++++++++++++- - 2 files changed, 21 insertions(+), 1 deletion(-) - -diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py -index c787d4009d..5d745c432d 100644 ---- a/salt/modules/zypperpkg.py -+++ b/salt/modules/zypperpkg.py -@@ -339,6 +339,11 @@ class _Zypper: - and self.__call_result["stderr"].strip() - or "" - ) -+ msg += ( -+ self.__call_result["stdout"] -+ and self.__call_result["stdout"].strip() -+ or "" -+ ) - if msg: - _error_msg.append(msg) - else: -diff --git a/tests/unit/modules/test_zypperpkg.py b/tests/unit/modules/test_zypperpkg.py -index 37d555844c..bcd001cd85 100644 ---- a/tests/unit/modules/test_zypperpkg.py -+++ b/tests/unit/modules/test_zypperpkg.py -@@ -207,11 +207,26 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): - ): - zypper.__zypper__.xml.call("crashme") - -+ output_to_user_stdout = "Output to user to stdout" -+ output_to_user_stderr = "Output to user to stderr" -+ sniffer = RunSniffer( -+ stdout=output_to_user_stdout, stderr=output_to_user_stderr, retcode=1 -+ ) -+ with patch.dict( -+ "salt.modules.zypperpkg.__salt__", {"cmd.run_all": sniffer} -+ ), patch.object(zypper.__zypper__, "_is_rpm_lock", return_value=False): - with self.assertRaisesRegex( -- CommandExecutionError, "^Zypper command failure: Check Zypper's logs.$" -+ CommandExecutionError, -+ "^Zypper command failure: {}$".format( -+ output_to_user_stderr + output_to_user_stdout -+ ), - ): - zypper.__zypper__.call("crashme again") - -+ sniffer = RunSniffer(retcode=1) -+ with patch.dict( -+ "salt.modules.zypperpkg.__salt__", {"cmd.run_all": sniffer} -+ ), patch.object(zypper.__zypper__, "_is_rpm_lock", return_value=False): - zypper.__zypper__.noraise.call("stay quiet") - self.assertEqual(zypper.__zypper__.error_msg, "Check Zypper's logs.") - --- -2.37.3 - - diff --git a/info_installed-works-without-status-attr-now.patch b/info_installed-works-without-status-attr-now.patch index 45581d7..0ffd8e1 100644 --- a/info_installed-works-without-status-attr-now.patch +++ b/info_installed-works-without-status-attr-now.patch @@ -1,4 +1,4 @@ -From 55fc248aabd486f8ae4ff2bc755d653cdc39a4bb Mon Sep 17 00:00:00 2001 +From 01a670dad69e03bd8bf2da76a6a81e847af20aab Mon Sep 17 00:00:00 2001 From: Alexander Graul Date: Tue, 25 Jan 2022 17:12:47 +0100 Subject: [PATCH] info_installed works without status attr now @@ -12,10 +12,10 @@ detect if a package was installed or not. Now info_installed adds the 2 files changed, 27 insertions(+) diff --git a/salt/modules/aptpkg.py b/salt/modules/aptpkg.py -index 4a2281c47f..544143d286 100644 +index 938e37cc9e..3289f6604d 100644 --- a/salt/modules/aptpkg.py +++ b/salt/modules/aptpkg.py -@@ -3479,6 +3479,15 @@ def info_installed(*names, **kwargs): +@@ -3461,6 +3461,15 @@ def info_installed(*names, **kwargs): failhard = kwargs.pop("failhard", True) kwargs.pop("errors", None) # Only for compatibility with RPM attr = kwargs.pop("attr", None) # Package attributes to return @@ -32,10 +32,10 @@ index 4a2281c47f..544143d286 100644 "all_versions", False ) # This is for backward compatible structure only diff --git a/tests/pytests/unit/modules/test_aptpkg.py b/tests/pytests/unit/modules/test_aptpkg.py -index 8e404a673c..76b59d8604 100644 +index 4226957eeb..eb72447c3a 100644 --- a/tests/pytests/unit/modules/test_aptpkg.py +++ b/tests/pytests/unit/modules/test_aptpkg.py -@@ -384,6 +384,24 @@ def test_info_installed_attr(lowpkg_info_var): +@@ -385,6 +385,24 @@ def test_info_installed_attr(lowpkg_info_var): assert ret["wget"] == expected_pkg @@ -61,6 +61,6 @@ index 8e404a673c..76b59d8604 100644 """ Test info_installed 'all_versions'. -- -2.37.3 +2.39.2 diff --git a/let-salt-ssh-use-platform-python-binary-in-rhel8-191.patch b/let-salt-ssh-use-platform-python-binary-in-rhel8-191.patch index 94b669b..5a5cdc2 100644 --- a/let-salt-ssh-use-platform-python-binary-in-rhel8-191.patch +++ b/let-salt-ssh-use-platform-python-binary-in-rhel8-191.patch @@ -1,4 +1,4 @@ -From c68a988ebcc7bae06231c9a9ebc3d654a7d6ffbc Mon Sep 17 00:00:00 2001 +From 1de8313e55317a62c36a1a6262e7b9463544d69c Mon Sep 17 00:00:00 2001 From: Can Bulut Bayburt <1103552+cbbayburt@users.noreply.github.com> Date: Wed, 4 Dec 2019 15:59:46 +0100 Subject: [PATCH] Let salt-ssh use 'platform-python' binary in RHEL8 @@ -14,19 +14,19 @@ creating the sh shim. 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/client/ssh/__init__.py b/salt/client/ssh/__init__.py -index 5e557c51da..ef162d2270 100644 +index 88365a6099..049baff51a 100644 --- a/salt/client/ssh/__init__.py +++ b/salt/client/ssh/__init__.py @@ -146,7 +146,7 @@ if [ "$SUDO" ] && [ "$SUDO_USER" ] then SUDO="$SUDO -u $SUDO_USER" fi EX_PYTHON_INVALID={EX_THIN_PYTHON_INVALID} --PYTHON_CMDS="python3 python27 python2.7 python26 python2.6 python2 python" +-PYTHON_CMDS="python3 python27 python2.7 python26 python2.6 python2 python /usr/libexec/platform-python" +PYTHON_CMDS="python3 /usr/libexec/platform-python python27 python2.7 python26 python2.6 python2 python" for py_cmd in $PYTHON_CMDS do if command -v "$py_cmd" >/dev/null 2>&1 && "$py_cmd" -c "import sys; sys.exit(not (sys.version_info >= (2, 6)));" -- -2.37.3 +2.39.2 diff --git a/make-aptpkg.list_repos-compatible-on-enabled-disable.patch b/make-aptpkg.list_repos-compatible-on-enabled-disable.patch index 8b51dcb..0fafcc8 100644 --- a/make-aptpkg.list_repos-compatible-on-enabled-disable.patch +++ b/make-aptpkg.list_repos-compatible-on-enabled-disable.patch @@ -1,4 +1,4 @@ -From f113f94d40ee37919aa974a4fab95e482c5a0631 Mon Sep 17 00:00:00 2001 +From f9731227e7af0b1bf0a54993e0cac890225517f6 Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Fri, 16 Nov 2018 10:54:12 +0100 Subject: [PATCH] Make aptpkg.list_repos compatible on enabled/disabled @@ -9,10 +9,10 @@ Subject: [PATCH] Make aptpkg.list_repos compatible on enabled/disabled 1 file changed, 3 insertions(+) diff --git a/salt/modules/aptpkg.py b/salt/modules/aptpkg.py -index 94e97a0b5b..0cbd611b71 100644 +index f68b1907e8..8e89744b5e 100644 --- a/salt/modules/aptpkg.py +++ b/salt/modules/aptpkg.py -@@ -1933,6 +1933,9 @@ def list_repos(**kwargs): +@@ -1919,6 +1919,9 @@ def list_repos(**kwargs): repo["file"] = source.file repo["comps"] = getattr(source, "comps", []) repo["disabled"] = source.disabled @@ -23,6 +23,6 @@ index 94e97a0b5b..0cbd611b71 100644 repo["type"] = source.type repo["uri"] = source.uri -- -2.37.3 +2.39.2 diff --git a/make-pass-renderer-configurable-other-fixes-532.patch b/make-pass-renderer-configurable-other-fixes-532.patch deleted file mode 100644 index a99c412..0000000 --- a/make-pass-renderer-configurable-other-fixes-532.patch +++ /dev/null @@ -1,414 +0,0 @@ -From 030e2cb20af09673d5f38d68bcb257c6c839a2f3 Mon Sep 17 00:00:00 2001 -From: Daniel Mach -Date: Thu, 6 Oct 2022 11:58:23 +0200 -Subject: [PATCH] Make pass renderer configurable & other fixes (#532) -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -* pass: Use a secure way of handling pass arguments - -The original code would fail on pass paths with spaces, -because they would be split into multiple arguments. - -* pass: Strip only trailing newline characters from the secret - -* pass: Do not modify $HOME env globally - -Just set $HOME for calling the pass binary -to avoid affecting anything outside the pass renderer. - -* pass: Use pass executable path from _get_pass_exec() - -* Make the pass renderer more configurable - -1. Allow us to make the pass renderer fail during pillar rendering - when a secret corresponding with a pass path cannot be fetched. - For this we add a master config variable pass_strict_fetch. - -2. Allow to have prefix for variables that should be processed - with the pass renderer. - For this we add a master config variable pass_variable_prefix. - -3. Allow us to configure pass' GNUPGHOME and PASSWORD_STORE_DIR - environmental variables. - For this we add master config variables pass_gnupghome and pass_dir. - -* Add tests for the pass renderer - -* pass: Handle FileNotFoundError when pass binary is not available - -Co-authored-by: Marcus Rückert ---- - changelog/62120.added | 4 + - changelog/62120.fixed | 4 + - salt/config/__init__.py | 12 ++ - salt/renderers/pass.py | 104 ++++++++++++-- - tests/pytests/unit/renderers/test_pass.py | 164 ++++++++++++++++++++++ - 5 files changed, 274 insertions(+), 14 deletions(-) - create mode 100644 changelog/62120.added - create mode 100644 changelog/62120.fixed - create mode 100644 tests/pytests/unit/renderers/test_pass.py - -diff --git a/changelog/62120.added b/changelog/62120.added -new file mode 100644 -index 0000000000..4303d124f0 ---- /dev/null -+++ b/changelog/62120.added -@@ -0,0 +1,4 @@ -+Config option pass_variable_prefix allows to distinguish variables that contain paths to pass secrets. -+Config option pass_strict_fetch allows to error out when a secret cannot be fetched from pass. -+Config option pass_dir allows setting the PASSWORD_STORE_DIR env for pass. -+Config option pass_gnupghome allows setting the $GNUPGHOME env for pass. -diff --git a/changelog/62120.fixed b/changelog/62120.fixed -new file mode 100644 -index 0000000000..22a9711383 ---- /dev/null -+++ b/changelog/62120.fixed -@@ -0,0 +1,4 @@ -+Pass executable path from _get_path_exec() is used when calling the program. -+The $HOME env is no longer modified globally. -+Only trailing newlines are stripped from the fetched secret. -+Pass process arguments are handled in a secure way. -diff --git a/salt/config/__init__.py b/salt/config/__init__.py -index 7cdee12c4d..0cc0deb874 100644 ---- a/salt/config/__init__.py -+++ b/salt/config/__init__.py -@@ -967,6 +967,14 @@ VALID_OPTS = immutabletypes.freeze( - # Use Adler32 hashing algorithm for server_id (default False until Sodium, "adler32" after) - # Possible values are: False, adler32, crc32 - "server_id_use_crc": (bool, str), -+ # pass renderer: Fetch secrets only for the template variables matching the prefix -+ "pass_variable_prefix": str, -+ # pass renderer: Whether to error out when unable to fetch a secret -+ "pass_strict_fetch": bool, -+ # pass renderer: Set GNUPGHOME env for Pass -+ "pass_gnupghome": str, -+ # pass renderer: Set PASSWORD_STORE_DIR env for Pass -+ "pass_dir": str, - } - ) - -@@ -1608,6 +1616,10 @@ DEFAULT_MASTER_OPTS = immutabletypes.freeze( - "fips_mode": False, - "detect_remote_minions": False, - "remote_minions_port": 22, -+ "pass_variable_prefix": "", -+ "pass_strict_fetch": False, -+ "pass_gnupghome": "", -+ "pass_dir": "", - } - ) - -diff --git a/salt/renderers/pass.py b/salt/renderers/pass.py -index 71b1021b96..ba0f152c23 100644 ---- a/salt/renderers/pass.py -+++ b/salt/renderers/pass.py -@@ -45,6 +45,34 @@ Install pass binary - - pass: - pkg.installed -+ -+Salt master configuration options -+ -+.. code-block:: yaml -+ -+ # If the prefix is *not* set (default behavior), all template variables are -+ # considered for fetching secrets from Pass. Those that cannot be resolved -+ # to a secret are passed through. -+ # -+ # If the prefix is set, only the template variables with matching prefix are -+ # considered for fetching the secrets, other variables are passed through. -+ # -+ # For ease of use it is recommended to set the following options as well: -+ # renderer: 'jinja|yaml|pass' -+ # pass_strict_fetch: true -+ # -+ pass_variable_prefix: 'pass:' -+ -+ # If set to 'true', error out when unable to fetch a secret for a template variable. -+ pass_strict_fetch: true -+ -+ # Set GNUPGHOME env for Pass. -+ # Defaults to: ~/.gnupg -+ pass_gnupghome: -+ -+ # Set PASSWORD_STORE_DIR env for Pass. -+ # Defaults to: ~/.password-store -+ pass_dir: - """ - - -@@ -54,7 +82,7 @@ from os.path import expanduser - from subprocess import PIPE, Popen - - import salt.utils.path --from salt.exceptions import SaltRenderError -+from salt.exceptions import SaltConfigurationError, SaltRenderError - - log = logging.getLogger(__name__) - -@@ -75,18 +103,71 @@ def _fetch_secret(pass_path): - Fetch secret from pass based on pass_path. If there is - any error, return back the original pass_path value - """ -- cmd = "pass show {}".format(pass_path.strip()) -- log.debug("Fetching secret: %s", cmd) -+ pass_exec = _get_pass_exec() -+ -+ # Make a backup in case we want to return the original value without stripped whitespaces -+ original_pass_path = pass_path -+ -+ # Remove the optional prefix from pass path -+ pass_prefix = __opts__["pass_variable_prefix"] -+ if pass_prefix: -+ # If we do not see our prefix we do not want to process this variable -+ # and we return the unmodified pass path -+ if not pass_path.startswith(pass_prefix): -+ return pass_path -+ -+ # strip the prefix from the start of the string -+ pass_path = pass_path[len(pass_prefix) :] -+ -+ # The pass_strict_fetch option must be used with pass_variable_prefix -+ pass_strict_fetch = __opts__["pass_strict_fetch"] -+ if pass_strict_fetch and not pass_prefix: -+ msg = "The 'pass_strict_fetch' option requires 'pass_variable_prefix' option enabled" -+ raise SaltConfigurationError(msg) -+ -+ # Remove whitespaces from the pass_path -+ pass_path = pass_path.strip() - -- proc = Popen(cmd.split(" "), stdout=PIPE, stderr=PIPE) -- pass_data, pass_error = proc.communicate() -+ cmd = [pass_exec, "show", pass_path] -+ log.debug("Fetching secret: %s", " ".join(cmd)) -+ -+ # Make sure environment variable HOME is set, since Pass looks for the -+ # password-store under ~/.password-store. -+ env = os.environ.copy() -+ env["HOME"] = expanduser("~") -+ -+ pass_dir = __opts__["pass_dir"] -+ if pass_dir: -+ env["PASSWORD_STORE_DIR"] = pass_dir -+ -+ pass_gnupghome = __opts__["pass_gnupghome"] -+ if pass_gnupghome: -+ env["GNUPGHOME"] = pass_gnupghome -+ -+ try: -+ proc = Popen(cmd, stdout=PIPE, stderr=PIPE, env=env) -+ pass_data, pass_error = proc.communicate() -+ pass_returncode = proc.returncode -+ except OSError as e: -+ pass_data, pass_error = "", str(e) -+ pass_returncode = 1 - - # The version of pass used during development sent output to - # stdout instead of stderr even though its returncode was non zero. -- if proc.returncode or not pass_data: -- log.warning("Could not fetch secret: %s %s", pass_data, pass_error) -- pass_data = pass_path -- return pass_data.strip() -+ if pass_returncode or not pass_data: -+ try: -+ pass_error = pass_error.decode("utf-8") -+ except (AttributeError, ValueError): -+ pass -+ msg = "Could not fetch secret '{}' from the password store: {}".format( -+ pass_path, pass_error -+ ) -+ if pass_strict_fetch: -+ raise SaltRenderError(msg) -+ else: -+ log.warning(msg) -+ return original_pass_path -+ return pass_data.rstrip("\r\n") - - - def _decrypt_object(obj): -@@ -108,9 +189,4 @@ def render(pass_info, saltenv="base", sls="", argline="", **kwargs): - """ - Fetch secret from pass based on pass_path - """ -- _get_pass_exec() -- -- # Make sure environment variable HOME is set, since Pass looks for the -- # password-store under ~/.password-store. -- os.environ["HOME"] = expanduser("~") - return _decrypt_object(pass_info) -diff --git a/tests/pytests/unit/renderers/test_pass.py b/tests/pytests/unit/renderers/test_pass.py -new file mode 100644 -index 0000000000..74e822c7ec ---- /dev/null -+++ b/tests/pytests/unit/renderers/test_pass.py -@@ -0,0 +1,164 @@ -+import importlib -+ -+import pytest -+ -+import salt.config -+import salt.exceptions -+from tests.support.mock import MagicMock, patch -+ -+# "pass" is a reserved keyword, we need to import it differently -+pass_ = importlib.import_module("salt.renderers.pass") -+ -+ -+@pytest.fixture -+def configure_loader_modules(): -+ return { -+ pass_: { -+ "__opts__": salt.config.DEFAULT_MASTER_OPTS.copy(), -+ "_get_pass_exec": MagicMock(return_value="/usr/bin/pass"), -+ } -+ } -+ -+ -+# The default behavior is that if fetching a secret from pass fails, -+# the value is passed through. Even the trailing newlines are preserved. -+def test_passthrough(): -+ pass_path = "secret\n" -+ expected = pass_path -+ result = pass_.render(pass_path) -+ -+ assert result == expected -+ -+ -+# Fetch a secret in the strict mode. -+def test_strict_fetch(): -+ config = { -+ "pass_variable_prefix": "pass:", -+ "pass_strict_fetch": True, -+ } -+ -+ popen_mock = MagicMock(spec=pass_.Popen) -+ popen_mock.return_value.communicate.return_value = ("password123456\n", "") -+ popen_mock.return_value.returncode = 0 -+ -+ mocks = { -+ "Popen": popen_mock, -+ } -+ -+ pass_path = "pass:secret" -+ expected = "password123456" -+ with patch.dict(pass_.__opts__, config), patch.dict(pass_.__dict__, mocks): -+ result = pass_.render(pass_path) -+ -+ assert result == expected -+ -+ -+# Fail to fetch a secret in the strict mode. -+def test_strict_fetch_fail(): -+ config = { -+ "pass_variable_prefix": "pass:", -+ "pass_strict_fetch": True, -+ } -+ -+ popen_mock = MagicMock(spec=pass_.Popen) -+ popen_mock.return_value.communicate.return_value = ("", "Secret not found") -+ popen_mock.return_value.returncode = 1 -+ -+ mocks = { -+ "Popen": popen_mock, -+ } -+ -+ pass_path = "pass:secret" -+ with patch.dict(pass_.__opts__, config), patch.dict(pass_.__dict__, mocks): -+ with pytest.raises(salt.exceptions.SaltRenderError): -+ pass_.render(pass_path) -+ -+ -+# Passthrough a value that doesn't have a pass prefix. -+def test_strict_fetch_passthrough(): -+ config = { -+ "pass_variable_prefix": "pass:", -+ "pass_strict_fetch": True, -+ } -+ -+ pass_path = "variable-without-pass-prefix\n" -+ expected = pass_path -+ with patch.dict(pass_.__opts__, config): -+ result = pass_.render(pass_path) -+ -+ assert result == expected -+ -+ -+# Fetch a secret in the strict mode. The pass path contains spaces. -+def test_strict_fetch_pass_path_with_spaces(): -+ config = { -+ "pass_variable_prefix": "pass:", -+ "pass_strict_fetch": True, -+ } -+ -+ popen_mock = MagicMock(spec=pass_.Popen) -+ popen_mock.return_value.communicate.return_value = ("password123456\n", "") -+ popen_mock.return_value.returncode = 0 -+ -+ mocks = { -+ "Popen": popen_mock, -+ } -+ -+ pass_path = "pass:se cr et" -+ with patch.dict(pass_.__opts__, config), patch.dict(pass_.__dict__, mocks): -+ pass_.render(pass_path) -+ -+ call_args, call_kwargs = popen_mock.call_args_list[0] -+ assert call_args[0] == ["/usr/bin/pass", "show", "se cr et"] -+ -+ -+# Fetch a secret in the strict mode. The secret contains leading and trailing whitespaces. -+def test_strict_fetch_secret_with_whitespaces(): -+ config = { -+ "pass_variable_prefix": "pass:", -+ "pass_strict_fetch": True, -+ } -+ -+ popen_mock = MagicMock(spec=pass_.Popen) -+ popen_mock.return_value.communicate.return_value = (" \tpassword123456\t \r\n", "") -+ popen_mock.return_value.returncode = 0 -+ -+ mocks = { -+ "Popen": popen_mock, -+ } -+ -+ pass_path = "pass:secret" -+ expected = " \tpassword123456\t " # only the trailing newlines get striped -+ with patch.dict(pass_.__opts__, config), patch.dict(pass_.__dict__, mocks): -+ result = pass_.render(pass_path) -+ -+ assert result == expected -+ -+ -+# Test setting env variables based on config values: -+# - pass_gnupghome -> GNUPGHOME -+# - pass_dir -> PASSWORD_STORE_DIR -+def test_env(): -+ config = { -+ "pass_variable_prefix": "pass:", -+ "pass_strict_fetch": True, -+ "pass_gnupghome": "/path/to/gnupghome", -+ "pass_dir": "/path/to/secretstore", -+ } -+ -+ popen_mock = MagicMock(spec=pass_.Popen) -+ popen_mock.return_value.communicate.return_value = ("password123456\n", "") -+ popen_mock.return_value.returncode = 0 -+ -+ mocks = { -+ "Popen": popen_mock, -+ } -+ -+ pass_path = "pass:secret" -+ expected = " \tpassword123456\t " # only the trailing newlines get striped -+ with patch.dict(pass_.__opts__, config), patch.dict(pass_.__dict__, mocks): -+ result = pass_.render(pass_path) -+ -+ call_args, call_kwargs = popen_mock.call_args_list[0] -+ assert call_kwargs["env"]["GNUPGHOME"] == config["pass_gnupghome"] -+ assert call_kwargs["env"]["PASSWORD_STORE_DIR"] == config["pass_dir"] --- -2.37.3 - - diff --git a/make-setup.py-script-to-not-require-setuptools-9.1.patch b/make-setup.py-script-to-not-require-setuptools-9.1.patch index eda211e..ea91881 100644 --- a/make-setup.py-script-to-not-require-setuptools-9.1.patch +++ b/make-setup.py-script-to-not-require-setuptools-9.1.patch @@ -1,4 +1,4 @@ -From 33e45a7ced8a3cfc0a8c37cdc5d7a29d6f6833c3 Mon Sep 17 00:00:00 2001 +From d2b4c8170d7ff30bf33623fcbbb6ebb6d7af934e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?= Date: Wed, 25 Mar 2020 13:09:52 +0000 @@ -9,10 +9,10 @@ Subject: [PATCH] Make setup.py script to not require setuptools > 9.1 1 file changed, 8 deletions(-) diff --git a/setup.py b/setup.py -index d633af35ec..586842972d 100755 +index e60f1b7085..8ca8a66d45 100755 --- a/setup.py +++ b/setup.py -@@ -718,14 +718,6 @@ class Install(install): +@@ -632,14 +632,6 @@ class Install(install): install.finalize_options(self) def run(self): @@ -25,9 +25,9 @@ index d633af35ec..586842972d 100755 - sys.exit(1) - # Let's set the running_salt_install attribute so we can add - # _version.py in the build command + # _version.txt in the build command self.distribution.running_salt_install = True -- -2.37.3 +2.39.2 diff --git a/make-sure-saltcacheloader-use-correct-fileclient-519.patch b/make-sure-saltcacheloader-use-correct-fileclient-519.patch deleted file mode 100644 index 51b8686..0000000 --- a/make-sure-saltcacheloader-use-correct-fileclient-519.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 03ce925098fb96ad2f2f4b7d4c151ef63aede75f Mon Sep 17 00:00:00 2001 -From: Witek Bedyk -Date: Thu, 19 May 2022 12:52:12 +0200 -Subject: [PATCH] Make sure SaltCacheLoader use correct fileclient (#519) - -Backported from https://github.com/saltstack/salt/pull/61895 - -Signed-off-by: Witek Bedyk ---- - salt/state.py | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/salt/state.py b/salt/state.py -index db228228a7..316dcdec63 100644 ---- a/salt/state.py -+++ b/salt/state.py -@@ -4170,6 +4170,9 @@ class BaseHighState: - ) - else: - try: -+ # Make sure SaltCacheLoader use correct fileclient -+ if context is None: -+ context = {"fileclient": self.client} - state = compile_template( - fn_, - self.state.rend, --- -2.37.3 - - diff --git a/make-sure-the-file-client-is-destroyed-upon-used.patch b/make-sure-the-file-client-is-destroyed-upon-used.patch new file mode 100644 index 0000000..db8d41f --- /dev/null +++ b/make-sure-the-file-client-is-destroyed-upon-used.patch @@ -0,0 +1,850 @@ +From a1fc5287d501a1ecdbd259e5bbdd4f7d5d06dd13 Mon Sep 17 00:00:00 2001 +From: Alexander Graul +Date: Fri, 28 Apr 2023 09:41:28 +0200 +Subject: [PATCH] Make sure the file client is destroyed upon used + +Backport of https://github.com/saltstack/salt/pull/64113 +--- + salt/client/ssh/wrapper/saltcheck.py | 108 +++---- + salt/fileclient.py | 11 - + salt/modules/dockermod.py | 17 +- + salt/pillar/__init__.py | 6 +- + salt/states/ansiblegate.py | 11 +- + salt/utils/asynchronous.py | 2 +- + salt/utils/jinja.py | 53 ++- + salt/utils/mako.py | 7 + + salt/utils/templates.py | 303 +++++++++--------- + .../integration/states/test_include.py | 40 +++ + .../utils/jinja/test_salt_cache_loader.py | 47 ++- + 11 files changed, 330 insertions(+), 275 deletions(-) + create mode 100644 tests/pytests/integration/states/test_include.py + +diff --git a/salt/client/ssh/wrapper/saltcheck.py b/salt/client/ssh/wrapper/saltcheck.py +index d47b5cf6883..b0b94593809 100644 +--- a/salt/client/ssh/wrapper/saltcheck.py ++++ b/salt/client/ssh/wrapper/saltcheck.py +@@ -9,6 +9,7 @@ import tarfile + import tempfile + from contextlib import closing + ++import salt.fileclient + import salt.utils.files + import salt.utils.json + import salt.utils.url +@@ -28,65 +29,62 @@ def update_master_cache(states, saltenv="base"): + # Setup for copying states to gendir + gendir = tempfile.mkdtemp() + trans_tar = salt.utils.files.mkstemp() +- if "cp.fileclient_{}".format(id(__opts__)) not in __context__: +- __context__[ +- "cp.fileclient_{}".format(id(__opts__)) +- ] = salt.fileclient.get_file_client(__opts__) +- +- # generate cp.list_states output and save to gendir +- cp_output = salt.utils.json.dumps(__salt__["cp.list_states"]()) +- cp_output_file = os.path.join(gendir, "cp_output.txt") +- with salt.utils.files.fopen(cp_output_file, "w") as fp: +- fp.write(cp_output) +- +- # cp state directories to gendir +- already_processed = [] +- sls_list = salt.utils.args.split_input(states) +- for state_name in sls_list: +- # generate low data for each state and save to gendir +- state_low_file = os.path.join(gendir, state_name + ".low") +- state_low_output = salt.utils.json.dumps( +- __salt__["state.show_low_sls"](state_name) +- ) +- with salt.utils.files.fopen(state_low_file, "w") as fp: +- fp.write(state_low_output) +- +- state_name = state_name.replace(".", os.sep) +- if state_name in already_processed: +- log.debug("Already cached state for %s", state_name) +- else: +- file_copy_file = os.path.join(gendir, state_name + ".copy") +- log.debug("copying %s to %s", state_name, gendir) +- qualified_name = salt.utils.url.create(state_name, saltenv) +- # Duplicate cp.get_dir to gendir +- copy_result = __context__["cp.fileclient_{}".format(id(__opts__))].get_dir( +- qualified_name, gendir, saltenv ++ with salt.fileclient.get_file_client(__opts__) as cp_fileclient: ++ ++ # generate cp.list_states output and save to gendir ++ cp_output = salt.utils.json.dumps(__salt__["cp.list_states"]()) ++ cp_output_file = os.path.join(gendir, "cp_output.txt") ++ with salt.utils.files.fopen(cp_output_file, "w") as fp: ++ fp.write(cp_output) ++ ++ # cp state directories to gendir ++ already_processed = [] ++ sls_list = salt.utils.args.split_input(states) ++ for state_name in sls_list: ++ # generate low data for each state and save to gendir ++ state_low_file = os.path.join(gendir, state_name + ".low") ++ state_low_output = salt.utils.json.dumps( ++ __salt__["state.show_low_sls"](state_name) + ) +- if copy_result: +- copy_result = [dir.replace(gendir, state_cache) for dir in copy_result] +- copy_result_output = salt.utils.json.dumps(copy_result) +- with salt.utils.files.fopen(file_copy_file, "w") as fp: +- fp.write(copy_result_output) +- already_processed.append(state_name) ++ with salt.utils.files.fopen(state_low_file, "w") as fp: ++ fp.write(state_low_output) ++ ++ state_name = state_name.replace(".", os.sep) ++ if state_name in already_processed: ++ log.debug("Already cached state for %s", state_name) + else: +- # If files were not copied, assume state.file.sls was given and just copy state +- state_name = os.path.dirname(state_name) + file_copy_file = os.path.join(gendir, state_name + ".copy") +- if state_name in already_processed: +- log.debug("Already cached state for %s", state_name) ++ log.debug("copying %s to %s", state_name, gendir) ++ qualified_name = salt.utils.url.create(state_name, saltenv) ++ # Duplicate cp.get_dir to gendir ++ copy_result = cp_fileclient.get_dir(qualified_name, gendir, saltenv) ++ if copy_result: ++ copy_result = [ ++ dir.replace(gendir, state_cache) for dir in copy_result ++ ] ++ copy_result_output = salt.utils.json.dumps(copy_result) ++ with salt.utils.files.fopen(file_copy_file, "w") as fp: ++ fp.write(copy_result_output) ++ already_processed.append(state_name) + else: +- qualified_name = salt.utils.url.create(state_name, saltenv) +- copy_result = __context__[ +- "cp.fileclient_{}".format(id(__opts__)) +- ].get_dir(qualified_name, gendir, saltenv) +- if copy_result: +- copy_result = [ +- dir.replace(gendir, state_cache) for dir in copy_result +- ] +- copy_result_output = salt.utils.json.dumps(copy_result) +- with salt.utils.files.fopen(file_copy_file, "w") as fp: +- fp.write(copy_result_output) +- already_processed.append(state_name) ++ # If files were not copied, assume state.file.sls was given and just copy state ++ state_name = os.path.dirname(state_name) ++ file_copy_file = os.path.join(gendir, state_name + ".copy") ++ if state_name in already_processed: ++ log.debug("Already cached state for %s", state_name) ++ else: ++ qualified_name = salt.utils.url.create(state_name, saltenv) ++ copy_result = cp_fileclient.get_dir( ++ qualified_name, gendir, saltenv ++ ) ++ if copy_result: ++ copy_result = [ ++ dir.replace(gendir, state_cache) for dir in copy_result ++ ] ++ copy_result_output = salt.utils.json.dumps(copy_result) ++ with salt.utils.files.fopen(file_copy_file, "w") as fp: ++ fp.write(copy_result_output) ++ already_processed.append(state_name) + + # turn gendir into tarball and remove gendir + try: +diff --git a/salt/fileclient.py b/salt/fileclient.py +index fef5154a0be..f01a86dd0d4 100644 +--- a/salt/fileclient.py ++++ b/salt/fileclient.py +@@ -849,7 +849,6 @@ class Client: + kwargs.pop("env") + + kwargs["saltenv"] = saltenv +- url_data = urllib.parse.urlparse(url) + sfn = self.cache_file(url, saltenv, cachedir=cachedir) + if not sfn or not os.path.exists(sfn): + return "" +@@ -1165,13 +1164,8 @@ class RemoteClient(Client): + + if not salt.utils.platform.is_windows(): + hash_server, stat_server = self.hash_and_stat_file(path, saltenv) +- try: +- mode_server = stat_server[0] +- except (IndexError, TypeError): +- mode_server = None + else: + hash_server = self.hash_file(path, saltenv) +- mode_server = None + + # Check if file exists on server, before creating files and + # directories +@@ -1214,13 +1208,8 @@ class RemoteClient(Client): + if dest2check and os.path.isfile(dest2check): + if not salt.utils.platform.is_windows(): + hash_local, stat_local = self.hash_and_stat_file(dest2check, saltenv) +- try: +- mode_local = stat_local[0] +- except (IndexError, TypeError): +- mode_local = None + else: + hash_local = self.hash_file(dest2check, saltenv) +- mode_local = None + + if hash_local == hash_server: + return dest2check +diff --git a/salt/modules/dockermod.py b/salt/modules/dockermod.py +index f7344b66ac6..69b722f0c95 100644 +--- a/salt/modules/dockermod.py ++++ b/salt/modules/dockermod.py +@@ -6667,14 +6667,6 @@ def script_retcode( + )["retcode"] + + +-def _mk_fileclient(): +- """ +- Create a file client and add it to the context. +- """ +- if "cp.fileclient" not in __context__: +- __context__["cp.fileclient"] = salt.fileclient.get_file_client(__opts__) +- +- + def _generate_tmp_path(): + return os.path.join("/tmp", "salt.docker.{}".format(uuid.uuid4().hex[:6])) + +@@ -6688,11 +6680,10 @@ def _prepare_trans_tar(name, sls_opts, mods=None, pillar=None, extra_filerefs="" + # reuse it from salt.ssh, however this function should + # be somewhere else + refs = salt.client.ssh.state.lowstate_file_refs(chunks, extra_filerefs) +- _mk_fileclient() +- trans_tar = salt.client.ssh.state.prep_trans_tar( +- __context__["cp.fileclient"], chunks, refs, pillar, name +- ) +- return trans_tar ++ with salt.fileclient.get_file_client(__opts__) as fileclient: ++ return salt.client.ssh.state.prep_trans_tar( ++ fileclient, chunks, refs, pillar, name ++ ) + + + def _compile_state(sls_opts, mods=None): +diff --git a/salt/pillar/__init__.py b/salt/pillar/__init__.py +index 0dfab4cc579..26312b3bd53 100644 +--- a/salt/pillar/__init__.py ++++ b/salt/pillar/__init__.py +@@ -9,7 +9,6 @@ import logging + import os + import sys + import traceback +-import uuid + + import salt.channel.client + import salt.ext.tornado.gen +@@ -1351,6 +1350,11 @@ class Pillar: + if hasattr(self, "_closing") and self._closing: + return + self._closing = True ++ if self.client: ++ try: ++ self.client.destroy() ++ except AttributeError: ++ pass + + # pylint: disable=W1701 + def __del__(self): +diff --git a/salt/states/ansiblegate.py b/salt/states/ansiblegate.py +index 7fd4deb6c2a..9abd418c42c 100644 +--- a/salt/states/ansiblegate.py ++++ b/salt/states/ansiblegate.py +@@ -32,12 +32,10 @@ state: + - state: installed + + """ +- + import logging + import os + import sys + +-# Import salt modules + import salt.fileclient + import salt.utils.decorators.path + from salt.utils.decorators import depends +@@ -108,13 +106,6 @@ def __virtual__(): + return __virtualname__ + + +-def _client(): +- """ +- Get a fileclient +- """ +- return salt.fileclient.get_file_client(__opts__) +- +- + def _changes(plays): + """ + Find changes in ansible return data +@@ -171,7 +162,7 @@ def playbooks(name, rundir=None, git_repo=None, git_kwargs=None, ansible_kwargs= + } + if git_repo: + if not isinstance(rundir, str) or not os.path.isdir(rundir): +- with _client() as client: ++ with salt.fileclient.get_file_client(__opts__) as client: + rundir = client._extrn_path(git_repo, "base") + log.trace("rundir set to %s", rundir) + if not isinstance(git_kwargs, dict): +diff --git a/salt/utils/asynchronous.py b/salt/utils/asynchronous.py +index 2a858feee98..0c645bbc3bb 100644 +--- a/salt/utils/asynchronous.py ++++ b/salt/utils/asynchronous.py +@@ -131,7 +131,7 @@ class SyncWrapper: + result = io_loop.run_sync(lambda: getattr(self.obj, key)(*args, **kwargs)) + results.append(True) + results.append(result) +- except Exception as exc: # pylint: disable=broad-except ++ except Exception: # pylint: disable=broad-except + results.append(False) + results.append(sys.exc_info()) + +diff --git a/salt/utils/jinja.py b/salt/utils/jinja.py +index fcc5aec497e..a6a8a279605 100644 +--- a/salt/utils/jinja.py ++++ b/salt/utils/jinja.py +@@ -58,19 +58,6 @@ class SaltCacheLoader(BaseLoader): + and only loaded once per loader instance. + """ + +- _cached_pillar_client = None +- _cached_client = None +- +- @classmethod +- def shutdown(cls): +- for attr in ("_cached_client", "_cached_pillar_client"): +- client = getattr(cls, attr, None) +- if client is not None: +- # PillarClient and LocalClient objects do not have a destroy method +- if hasattr(client, "destroy"): +- client.destroy() +- setattr(cls, attr, None) +- + def __init__( + self, + opts, +@@ -93,8 +80,7 @@ class SaltCacheLoader(BaseLoader): + log.debug("Jinja search path: %s", self.searchpath) + self.cached = [] + self._file_client = _file_client +- # Instantiate the fileclient +- self.file_client() ++ self._close_file_client = _file_client is None + + def file_client(self): + """ +@@ -108,18 +94,10 @@ class SaltCacheLoader(BaseLoader): + or not hasattr(self._file_client, "opts") + or self._file_client.opts["file_roots"] != self.opts["file_roots"] + ): +- attr = "_cached_pillar_client" if self.pillar_rend else "_cached_client" +- cached_client = getattr(self, attr, None) +- if ( +- cached_client is None +- or not hasattr(cached_client, "opts") +- or cached_client.opts["file_roots"] != self.opts["file_roots"] +- ): +- cached_client = salt.fileclient.get_file_client( +- self.opts, self.pillar_rend +- ) +- setattr(SaltCacheLoader, attr, cached_client) +- self._file_client = cached_client ++ self._file_client = salt.fileclient.get_file_client( ++ self.opts, self.pillar_rend ++ ) ++ self._close_file_client = True + return self._file_client + + def cache_file(self, template): +@@ -221,6 +199,27 @@ class SaltCacheLoader(BaseLoader): + # there is no template file within searchpaths + raise TemplateNotFound(template) + ++ def destroy(self): ++ if self._close_file_client is False: ++ return ++ if self._file_client is None: ++ return ++ file_client = self._file_client ++ self._file_client = None ++ ++ try: ++ file_client.destroy() ++ except AttributeError: ++ # PillarClient and LocalClient objects do not have a destroy method ++ pass ++ ++ def __enter__(self): ++ self.file_client() ++ return self ++ ++ def __exit__(self, *args): ++ self.destroy() ++ + + class PrintableDict(OrderedDict): + """ +diff --git a/salt/utils/mako.py b/salt/utils/mako.py +index 69618de9837..037d5d86deb 100644 +--- a/salt/utils/mako.py ++++ b/salt/utils/mako.py +@@ -97,3 +97,10 @@ if HAS_MAKO: + self.cache[fpath] = self.file_client().get_file( + fpath, "", True, self.saltenv + ) ++ ++ def destroy(self): ++ if self.client: ++ try: ++ self.client.destroy() ++ except AttributeError: ++ pass +diff --git a/salt/utils/templates.py b/salt/utils/templates.py +index 4947b820a36..4a8adf2a14f 100644 +--- a/salt/utils/templates.py ++++ b/salt/utils/templates.py +@@ -362,163 +362,169 @@ def render_jinja_tmpl(tmplstr, context, tmplpath=None): + elif tmplstr.endswith("\n"): + newline = "\n" + +- if not saltenv: +- if tmplpath: +- loader = jinja2.FileSystemLoader(os.path.dirname(tmplpath)) +- else: +- loader = salt.utils.jinja.SaltCacheLoader( +- opts, +- saltenv, +- pillar_rend=context.get("_pillar_rend", False), +- _file_client=file_client, +- ) ++ try: ++ if not saltenv: ++ if tmplpath: ++ loader = jinja2.FileSystemLoader(os.path.dirname(tmplpath)) ++ else: ++ loader = salt.utils.jinja.SaltCacheLoader( ++ opts, ++ saltenv, ++ pillar_rend=context.get("_pillar_rend", False), ++ _file_client=file_client, ++ ) + +- env_args = {"extensions": [], "loader": loader} +- +- if hasattr(jinja2.ext, "with_"): +- env_args["extensions"].append("jinja2.ext.with_") +- if hasattr(jinja2.ext, "do"): +- env_args["extensions"].append("jinja2.ext.do") +- if hasattr(jinja2.ext, "loopcontrols"): +- env_args["extensions"].append("jinja2.ext.loopcontrols") +- env_args["extensions"].append(salt.utils.jinja.SerializerExtension) +- +- opt_jinja_env = opts.get("jinja_env", {}) +- opt_jinja_sls_env = opts.get("jinja_sls_env", {}) +- +- opt_jinja_env = opt_jinja_env if isinstance(opt_jinja_env, dict) else {} +- opt_jinja_sls_env = opt_jinja_sls_env if isinstance(opt_jinja_sls_env, dict) else {} +- +- # Pass through trim_blocks and lstrip_blocks Jinja parameters +- # trim_blocks removes newlines around Jinja blocks +- # lstrip_blocks strips tabs and spaces from the beginning of +- # line to the start of a block. +- if opts.get("jinja_trim_blocks", False): +- log.debug("Jinja2 trim_blocks is enabled") +- log.warning( +- "jinja_trim_blocks is deprecated and will be removed in a future release," +- " please use jinja_env and/or jinja_sls_env instead" +- ) +- opt_jinja_env["trim_blocks"] = True +- opt_jinja_sls_env["trim_blocks"] = True +- if opts.get("jinja_lstrip_blocks", False): +- log.debug("Jinja2 lstrip_blocks is enabled") +- log.warning( +- "jinja_lstrip_blocks is deprecated and will be removed in a future release," +- " please use jinja_env and/or jinja_sls_env instead" +- ) +- opt_jinja_env["lstrip_blocks"] = True +- opt_jinja_sls_env["lstrip_blocks"] = True +- +- def opt_jinja_env_helper(opts, optname): +- for k, v in opts.items(): +- k = k.lower() +- if hasattr(jinja2.defaults, k.upper()): +- log.debug("Jinja2 environment %s was set to %s by %s", k, v, optname) +- env_args[k] = v +- else: +- log.warning("Jinja2 environment %s is not recognized", k) ++ env_args = {"extensions": [], "loader": loader} + +- if "sls" in context and context["sls"] != "": +- opt_jinja_env_helper(opt_jinja_sls_env, "jinja_sls_env") +- else: +- opt_jinja_env_helper(opt_jinja_env, "jinja_env") ++ if hasattr(jinja2.ext, "with_"): ++ env_args["extensions"].append("jinja2.ext.with_") ++ if hasattr(jinja2.ext, "do"): ++ env_args["extensions"].append("jinja2.ext.do") ++ if hasattr(jinja2.ext, "loopcontrols"): ++ env_args["extensions"].append("jinja2.ext.loopcontrols") ++ env_args["extensions"].append(salt.utils.jinja.SerializerExtension) + +- if opts.get("allow_undefined", False): +- jinja_env = jinja2.sandbox.SandboxedEnvironment(**env_args) +- else: +- jinja_env = jinja2.sandbox.SandboxedEnvironment( +- undefined=jinja2.StrictUndefined, **env_args +- ) ++ opt_jinja_env = opts.get("jinja_env", {}) ++ opt_jinja_sls_env = opts.get("jinja_sls_env", {}) + +- indent_filter = jinja_env.filters.get("indent") +- jinja_env.tests.update(JinjaTest.salt_jinja_tests) +- jinja_env.filters.update(JinjaFilter.salt_jinja_filters) +- if salt.utils.jinja.JINJA_VERSION >= Version("2.11"): +- # Use the existing indent filter on Jinja versions where it's not broken +- jinja_env.filters["indent"] = indent_filter +- jinja_env.globals.update(JinjaGlobal.salt_jinja_globals) +- +- # globals +- jinja_env.globals["odict"] = OrderedDict +- jinja_env.globals["show_full_context"] = salt.utils.jinja.show_full_context +- +- jinja_env.tests["list"] = salt.utils.data.is_list +- +- decoded_context = {} +- for key, value in context.items(): +- if not isinstance(value, str): +- if isinstance(value, NamedLoaderContext): +- decoded_context[key] = value.value() +- else: +- decoded_context[key] = value +- continue ++ opt_jinja_env = opt_jinja_env if isinstance(opt_jinja_env, dict) else {} ++ opt_jinja_sls_env = ( ++ opt_jinja_sls_env if isinstance(opt_jinja_sls_env, dict) else {} ++ ) + +- try: +- decoded_context[key] = salt.utils.stringutils.to_unicode( +- value, encoding=SLS_ENCODING ++ # Pass through trim_blocks and lstrip_blocks Jinja parameters ++ # trim_blocks removes newlines around Jinja blocks ++ # lstrip_blocks strips tabs and spaces from the beginning of ++ # line to the start of a block. ++ if opts.get("jinja_trim_blocks", False): ++ log.debug("Jinja2 trim_blocks is enabled") ++ log.warning( ++ "jinja_trim_blocks is deprecated and will be removed in a future release," ++ " please use jinja_env and/or jinja_sls_env instead" + ) +- except UnicodeDecodeError as ex: +- log.debug( +- "Failed to decode using default encoding (%s), trying system encoding", +- SLS_ENCODING, ++ opt_jinja_env["trim_blocks"] = True ++ opt_jinja_sls_env["trim_blocks"] = True ++ if opts.get("jinja_lstrip_blocks", False): ++ log.debug("Jinja2 lstrip_blocks is enabled") ++ log.warning( ++ "jinja_lstrip_blocks is deprecated and will be removed in a future release," ++ " please use jinja_env and/or jinja_sls_env instead" + ) +- decoded_context[key] = salt.utils.data.decode(value) ++ opt_jinja_env["lstrip_blocks"] = True ++ opt_jinja_sls_env["lstrip_blocks"] = True ++ ++ def opt_jinja_env_helper(opts, optname): ++ for k, v in opts.items(): ++ k = k.lower() ++ if hasattr(jinja2.defaults, k.upper()): ++ log.debug( ++ "Jinja2 environment %s was set to %s by %s", k, v, optname ++ ) ++ env_args[k] = v ++ else: ++ log.warning("Jinja2 environment %s is not recognized", k) + +- jinja_env.globals.update(decoded_context) +- try: +- template = jinja_env.from_string(tmplstr) +- output = template.render(**decoded_context) +- except jinja2.exceptions.UndefinedError as exc: +- trace = traceback.extract_tb(sys.exc_info()[2]) +- line, out = _get_jinja_error(trace, context=decoded_context) +- if not line: +- tmplstr = "" +- raise SaltRenderError("Jinja variable {}{}".format(exc, out), line, tmplstr) +- except ( +- jinja2.exceptions.TemplateRuntimeError, +- jinja2.exceptions.TemplateSyntaxError, +- jinja2.exceptions.SecurityError, +- ) as exc: +- trace = traceback.extract_tb(sys.exc_info()[2]) +- line, out = _get_jinja_error(trace, context=decoded_context) +- if not line: +- tmplstr = "" +- raise SaltRenderError( +- "Jinja syntax error: {}{}".format(exc, out), line, tmplstr +- ) +- except (SaltInvocationError, CommandExecutionError) as exc: +- trace = traceback.extract_tb(sys.exc_info()[2]) +- line, out = _get_jinja_error(trace, context=decoded_context) +- if not line: +- tmplstr = "" +- raise SaltRenderError( +- "Problem running salt function in Jinja template: {}{}".format(exc, out), +- line, +- tmplstr, +- ) +- except Exception as exc: # pylint: disable=broad-except +- tracestr = traceback.format_exc() +- trace = traceback.extract_tb(sys.exc_info()[2]) +- line, out = _get_jinja_error(trace, context=decoded_context) +- if not line: +- tmplstr = "" ++ if "sls" in context and context["sls"] != "": ++ opt_jinja_env_helper(opt_jinja_sls_env, "jinja_sls_env") + else: +- tmplstr += "\n{}".format(tracestr) +- log.debug("Jinja Error") +- log.debug("Exception:", exc_info=True) +- log.debug("Out: %s", out) +- log.debug("Line: %s", line) +- log.debug("TmplStr: %s", tmplstr) +- log.debug("TraceStr: %s", tracestr) ++ opt_jinja_env_helper(opt_jinja_env, "jinja_env") + +- raise SaltRenderError( +- "Jinja error: {}{}".format(exc, out), line, tmplstr, trace=tracestr +- ) ++ if opts.get("allow_undefined", False): ++ jinja_env = jinja2.sandbox.SandboxedEnvironment(**env_args) ++ else: ++ jinja_env = jinja2.sandbox.SandboxedEnvironment( ++ undefined=jinja2.StrictUndefined, **env_args ++ ) ++ ++ indent_filter = jinja_env.filters.get("indent") ++ jinja_env.tests.update(JinjaTest.salt_jinja_tests) ++ jinja_env.filters.update(JinjaFilter.salt_jinja_filters) ++ if salt.utils.jinja.JINJA_VERSION >= Version("2.11"): ++ # Use the existing indent filter on Jinja versions where it's not broken ++ jinja_env.filters["indent"] = indent_filter ++ jinja_env.globals.update(JinjaGlobal.salt_jinja_globals) ++ ++ # globals ++ jinja_env.globals["odict"] = OrderedDict ++ jinja_env.globals["show_full_context"] = salt.utils.jinja.show_full_context ++ ++ jinja_env.tests["list"] = salt.utils.data.is_list ++ ++ decoded_context = {} ++ for key, value in context.items(): ++ if not isinstance(value, str): ++ if isinstance(value, NamedLoaderContext): ++ decoded_context[key] = value.value() ++ else: ++ decoded_context[key] = value ++ continue ++ ++ try: ++ decoded_context[key] = salt.utils.stringutils.to_unicode( ++ value, encoding=SLS_ENCODING ++ ) ++ except UnicodeDecodeError: ++ log.debug( ++ "Failed to decode using default encoding (%s), trying system encoding", ++ SLS_ENCODING, ++ ) ++ decoded_context[key] = salt.utils.data.decode(value) ++ ++ jinja_env.globals.update(decoded_context) ++ try: ++ template = jinja_env.from_string(tmplstr) ++ output = template.render(**decoded_context) ++ except jinja2.exceptions.UndefinedError as exc: ++ trace = traceback.extract_tb(sys.exc_info()[2]) ++ line, out = _get_jinja_error(trace, context=decoded_context) ++ if not line: ++ tmplstr = "" ++ raise SaltRenderError("Jinja variable {}{}".format(exc, out), line, tmplstr) ++ except ( ++ jinja2.exceptions.TemplateRuntimeError, ++ jinja2.exceptions.TemplateSyntaxError, ++ jinja2.exceptions.SecurityError, ++ ) as exc: ++ trace = traceback.extract_tb(sys.exc_info()[2]) ++ line, out = _get_jinja_error(trace, context=decoded_context) ++ if not line: ++ tmplstr = "" ++ raise SaltRenderError( ++ "Jinja syntax error: {}{}".format(exc, out), line, tmplstr ++ ) ++ except (SaltInvocationError, CommandExecutionError) as exc: ++ trace = traceback.extract_tb(sys.exc_info()[2]) ++ line, out = _get_jinja_error(trace, context=decoded_context) ++ if not line: ++ tmplstr = "" ++ raise SaltRenderError( ++ "Problem running salt function in Jinja template: {}{}".format( ++ exc, out ++ ), ++ line, ++ tmplstr, ++ ) ++ except Exception as exc: # pylint: disable=broad-except ++ tracestr = traceback.format_exc() ++ trace = traceback.extract_tb(sys.exc_info()[2]) ++ line, out = _get_jinja_error(trace, context=decoded_context) ++ if not line: ++ tmplstr = "" ++ else: ++ tmplstr += "\n{}".format(tracestr) ++ log.debug("Jinja Error") ++ log.debug("Exception:", exc_info=True) ++ log.debug("Out: %s", out) ++ log.debug("Line: %s", line) ++ log.debug("TmplStr: %s", tmplstr) ++ log.debug("TraceStr: %s", tracestr) ++ ++ raise SaltRenderError( ++ "Jinja error: {}{}".format(exc, out), line, tmplstr, trace=tracestr ++ ) + finally: +- if loader and hasattr(loader, "_file_client"): +- if hasattr(loader._file_client, "destroy"): +- loader._file_client.destroy() ++ if loader and isinstance(loader, salt.utils.jinja.SaltCacheLoader): ++ loader.destroy() + + # Workaround a bug in Jinja that removes the final newline + # (https://github.com/mitsuhiko/jinja2/issues/75) +@@ -569,9 +575,8 @@ def render_mako_tmpl(tmplstr, context, tmplpath=None): + except Exception: # pylint: disable=broad-except + raise SaltRenderError(mako.exceptions.text_error_template().render()) + finally: +- if lookup and hasattr(lookup, "_file_client"): +- if hasattr(lookup._file_client, "destroy"): +- lookup._file_client.destroy() ++ if lookup and isinstance(lookup, SaltMakoTemplateLookup): ++ lookup.destroy() + + + def render_wempy_tmpl(tmplstr, context, tmplpath=None): +diff --git a/tests/pytests/integration/states/test_include.py b/tests/pytests/integration/states/test_include.py +new file mode 100644 +index 00000000000..f814328c5e4 +--- /dev/null ++++ b/tests/pytests/integration/states/test_include.py +@@ -0,0 +1,40 @@ ++""" ++Integration tests for the jinja includes in states ++""" ++import logging ++ ++import pytest ++ ++log = logging.getLogger(__name__) ++ ++ ++@pytest.mark.slow_test ++def test_issue_64111(salt_master, salt_minion, salt_call_cli): ++ # This needs to be an integration test. A functional test does not trigger ++ # the issue fixed. ++ ++ macros_jinja = """ ++ {% macro a_jinja_macro(arg) -%} ++ {{ arg }} ++ {%- endmacro %} ++ """ ++ ++ init_sls = """ ++ include: ++ - common.file1 ++ """ ++ ++ file1_sls = """ ++ {% from 'common/macros.jinja' import a_jinja_macro with context %} ++ ++ a state id: ++ cmd.run: ++ - name: echo {{ a_jinja_macro("hello world") }} ++ """ ++ tf = salt_master.state_tree.base.temp_file ++ ++ with tf("common/macros.jinja", macros_jinja): ++ with tf("common/init.sls", init_sls): ++ with tf("common/file1.sls", file1_sls): ++ ret = salt_call_cli.run("state.apply", "common") ++ assert ret.returncode == 0 +diff --git a/tests/pytests/unit/utils/jinja/test_salt_cache_loader.py b/tests/pytests/unit/utils/jinja/test_salt_cache_loader.py +index 38c5ce5b724..e0f5fa158ff 100644 +--- a/tests/pytests/unit/utils/jinja/test_salt_cache_loader.py ++++ b/tests/pytests/unit/utils/jinja/test_salt_cache_loader.py +@@ -15,7 +15,7 @@ import salt.utils.json # pylint: disable=unused-import + import salt.utils.stringutils # pylint: disable=unused-import + import salt.utils.yaml # pylint: disable=unused-import + from salt.utils.jinja import SaltCacheLoader +-from tests.support.mock import Mock, patch ++from tests.support.mock import Mock, call, patch + + + @pytest.fixture +@@ -224,14 +224,45 @@ def test_file_client_kwarg(minion_opts, mock_file_client): + assert loader._file_client is mock_file_client + + +-def test_cache_loader_shutdown(minion_opts, mock_file_client): ++def test_cache_loader_passed_file_client(minion_opts, mock_file_client): + """ + The shudown method can be called without raising an exception when the + file_client does not have a destroy method + """ +- assert not hasattr(mock_file_client, "destroy") +- mock_file_client.opts = minion_opts +- loader = SaltCacheLoader(minion_opts, _file_client=mock_file_client) +- assert loader._file_client is mock_file_client +- # Shutdown method should not raise any exceptions +- loader.shutdown() ++ # Test SaltCacheLoader creating and destroying the file client created ++ file_client = Mock() ++ with patch("salt.fileclient.get_file_client", return_value=file_client): ++ loader = SaltCacheLoader(minion_opts) ++ assert loader._file_client is None ++ with loader: ++ assert loader._file_client is file_client ++ assert loader._file_client is None ++ assert file_client.mock_calls == [call.destroy()] ++ ++ # Test SaltCacheLoader reusing the file client passed ++ file_client = Mock() ++ file_client.opts = {"file_roots": minion_opts["file_roots"]} ++ with patch("salt.fileclient.get_file_client", return_value=Mock()): ++ loader = SaltCacheLoader(minion_opts, _file_client=file_client) ++ assert loader._file_client is file_client ++ with loader: ++ assert loader._file_client is file_client ++ assert loader._file_client is file_client ++ assert file_client.mock_calls == [] ++ ++ # Test SaltCacheLoader creating a client even though a file client was ++ # passed because the "file_roots" option is different, and, as such, ++ # the destroy method on the new file client is called, but not on the ++ # file client passed in. ++ file_client = Mock() ++ file_client.opts = {"file_roots": ""} ++ new_file_client = Mock() ++ with patch("salt.fileclient.get_file_client", return_value=new_file_client): ++ loader = SaltCacheLoader(minion_opts, _file_client=file_client) ++ assert loader._file_client is file_client ++ with loader: ++ assert loader._file_client is not file_client ++ assert loader._file_client is new_file_client ++ assert loader._file_client is None ++ assert file_client.mock_calls == [] ++ assert new_file_client.mock_calls == [call.destroy()] +-- +2.40.0 + diff --git a/normalize-package-names-once-with-pkg.installed-remo.patch b/normalize-package-names-once-with-pkg.installed-remo.patch deleted file mode 100644 index 76fd684..0000000 --- a/normalize-package-names-once-with-pkg.installed-remo.patch +++ /dev/null @@ -1,296 +0,0 @@ -From f2dc43cf1db3fee41e328c68545ccac2576021ca Mon Sep 17 00:00:00 2001 -From: Victor Zhestkov -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 46f0b1f613..f52e084346 100644 ---- a/salt/modules/yumpkg.py -+++ b/salt/modules/yumpkg.py -@@ -1460,7 +1460,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) -@@ -1612,7 +1617,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 - -@@ -2143,11 +2151,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 ef4e062145..cda966a1e8 100644 ---- a/salt/states/pkg.py -+++ b/salt/states/pkg.py -@@ -1873,6 +1873,7 @@ def installed( - normalize=normalize, - update_holds=update_holds, - ignore_epoch=ignore_epoch, -+ split_arch=False, - **kwargs - ) - except CommandExecutionError as exc: -@@ -2940,7 +2941,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 cba8201bda..ecb841e8ec 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__": {}, -+ }, - } - - -@@ -726,3 +737,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.37.3 - - diff --git a/pass-the-context-to-pillar-ext-modules.patch b/pass-the-context-to-pillar-ext-modules.patch index 91d82da..c3e4ac4 100644 --- a/pass-the-context-to-pillar-ext-modules.patch +++ b/pass-the-context-to-pillar-ext-modules.patch @@ -1,4 +1,4 @@ -From 8a584a8546667ab5390e9a2003a8ce3cb3add25c Mon Sep 17 00:00:00 2001 +From bd671b53de8933732e2108624d7dfb6f9b183f38 Mon Sep 17 00:00:00 2001 From: Victor Zhestkov Date: Fri, 28 Oct 2022 13:20:13 +0300 Subject: [PATCH] Pass the context to pillar ext modules @@ -15,10 +15,10 @@ Subject: [PATCH] Pass the context to pillar ext modules 3 files changed, 108 insertions(+), 6 deletions(-) diff --git a/salt/master.py b/salt/master.py -index 7f41ffe77b..0110082626 100644 +index a0552fa232..da1eb8cef5 100644 --- a/salt/master.py +++ b/salt/master.py -@@ -951,6 +951,7 @@ class MWorker(salt.utils.process.SignalHandlingProcess): +@@ -964,6 +964,7 @@ class MWorker(salt.utils.process.SignalHandlingProcess): self.k_mtime = 0 self.stats = collections.defaultdict(lambda: {"mean": 0, "runs": 0}) self.stat_clock = time.time() @@ -26,7 +26,7 @@ index 7f41ffe77b..0110082626 100644 # We need __setstate__ and __getstate__ to also pickle 'SMaster.secrets'. # Otherwise, 'SMaster.secrets' won't be copied over to the spawned process -@@ -1138,7 +1139,7 @@ class MWorker(salt.utils.process.SignalHandlingProcess): +@@ -1151,7 +1152,7 @@ class MWorker(salt.utils.process.SignalHandlingProcess): self.key, ) self.clear_funcs.connect() @@ -35,8 +35,8 @@ index 7f41ffe77b..0110082626 100644 salt.utils.crypt.reinit_crypto() self.__bind() -@@ -1202,7 +1203,7 @@ class AESFuncs(TransportMethods): - "_ext_nodes", # To be removed in 3006 (Sulfur) #60980 +@@ -1214,7 +1215,7 @@ class AESFuncs(TransportMethods): + "_file_envs", ) - def __init__(self, opts): @@ -44,7 +44,7 @@ index 7f41ffe77b..0110082626 100644 """ Create a new AESFuncs -@@ -1212,6 +1213,7 @@ class AESFuncs(TransportMethods): +@@ -1224,6 +1225,7 @@ class AESFuncs(TransportMethods): :returns: Instance for handling AES operations """ self.opts = opts @@ -52,7 +52,7 @@ index 7f41ffe77b..0110082626 100644 self.event = salt.utils.event.get_master_event( self.opts, self.opts["sock_dir"], listen=False ) -@@ -1603,6 +1605,7 @@ class AESFuncs(TransportMethods): +@@ -1611,6 +1613,7 @@ class AESFuncs(TransportMethods): pillarenv=load.get("pillarenv"), extra_minion_data=load.get("extra_minion_data"), clean_cache=load.get("clean_cache"), @@ -61,7 +61,7 @@ index 7f41ffe77b..0110082626 100644 data = pillar.compile_pillar() self.fs_.update_opts() diff --git a/salt/pillar/__init__.py b/salt/pillar/__init__.py -index 7be963566a..906bdfe55d 100644 +index 5a3f5388b4..0dfab4cc57 100644 --- a/salt/pillar/__init__.py +++ b/salt/pillar/__init__.py @@ -46,6 +46,7 @@ def get_pillar( @@ -72,15 +72,15 @@ index 7be963566a..906bdfe55d 100644 ): """ Return the correct pillar driver based on the file_client option -@@ -81,6 +82,7 @@ def get_pillar( - pillar_override=pillar_override, +@@ -82,6 +83,7 @@ def get_pillar( pillarenv=pillarenv, clean_cache=clean_cache, + extra_minion_data=extra_minion_data, + context=context, ) return ptype( opts, -@@ -92,6 +94,7 @@ def get_pillar( +@@ -93,6 +95,7 @@ def get_pillar( pillar_override=pillar_override, pillarenv=pillarenv, extra_minion_data=extra_minion_data, @@ -88,7 +88,7 @@ index 7be963566a..906bdfe55d 100644 ) -@@ -280,7 +283,7 @@ class AsyncRemotePillar(RemotePillarMixin): +@@ -281,7 +284,7 @@ class AsyncRemotePillar(RemotePillarMixin): raise salt.ext.tornado.gen.Return(ret_pillar) def destroy(self): @@ -97,7 +97,7 @@ index 7be963566a..906bdfe55d 100644 return self._closing = True -@@ -309,6 +312,7 @@ class RemotePillar(RemotePillarMixin): +@@ -310,6 +313,7 @@ class RemotePillar(RemotePillarMixin): pillar_override=None, pillarenv=None, extra_minion_data=None, @@ -105,7 +105,7 @@ index 7be963566a..906bdfe55d 100644 ): self.opts = opts self.opts["saltenv"] = saltenv -@@ -333,6 +337,7 @@ class RemotePillar(RemotePillarMixin): +@@ -334,6 +338,7 @@ class RemotePillar(RemotePillarMixin): merge_lists=True, ) self._closing = False @@ -113,7 +113,7 @@ index 7be963566a..906bdfe55d 100644 def compile_pillar(self): """ -@@ -406,6 +411,7 @@ class PillarCache: +@@ -407,6 +412,7 @@ class PillarCache: pillarenv=None, extra_minion_data=None, clean_cache=False, @@ -121,7 +121,7 @@ index 7be963566a..906bdfe55d 100644 ): # Yes, we need all of these because we need to route to the Pillar object # if we have no cache. This is another refactor target. -@@ -432,6 +438,8 @@ class PillarCache: +@@ -434,6 +440,8 @@ class PillarCache: minion_cache_path=self._minion_cache_path(minion_id), ) @@ -130,15 +130,15 @@ index 7be963566a..906bdfe55d 100644 def _minion_cache_path(self, minion_id): """ Return the path to the cache file for the minion. -@@ -455,6 +463,7 @@ class PillarCache: - functions=self.functions, +@@ -458,6 +466,7 @@ class PillarCache: pillar_override=self.pillar_override, pillarenv=self.pillarenv, + extra_minion_data=self.extra_minion_data, + context=self.context, ) return fresh_pillar.compile_pillar() -@@ -530,6 +539,7 @@ class Pillar: +@@ -533,6 +542,7 @@ class Pillar: pillar_override=None, pillarenv=None, extra_minion_data=None, @@ -146,7 +146,7 @@ index 7be963566a..906bdfe55d 100644 ): self.minion_id = minion_id self.ext = ext -@@ -568,7 +578,7 @@ class Pillar: +@@ -571,7 +581,7 @@ class Pillar: if opts.get("pillar_source_merging_strategy"): self.merge_strategy = opts["pillar_source_merging_strategy"] @@ -155,7 +155,7 @@ index 7be963566a..906bdfe55d 100644 self.ignored_pillars = {} self.pillar_override = pillar_override or {} if not isinstance(self.pillar_override, dict): -@@ -1335,7 +1345,7 @@ class Pillar: +@@ -1338,7 +1348,7 @@ class Pillar: """ This method exist in order to be API compatible with RemotePillar """ @@ -165,22 +165,22 @@ index 7be963566a..906bdfe55d 100644 self._closing = True diff --git a/tests/pytests/unit/test_master.py b/tests/pytests/unit/test_master.py -index a49ecfec3b..ca02c7788d 100644 +index cd11d217c7..98c796912a 100644 --- a/tests/pytests/unit/test_master.py +++ b/tests/pytests/unit/test_master.py -@@ -1,7 +1,7 @@ - import time +@@ -4,7 +4,7 @@ import pytest import salt.master + import salt.utils.platform -from tests.support.mock import patch +from tests.support.mock import MagicMock, patch - def test_fileserver_duration(): -@@ -14,3 +14,92 @@ def test_fileserver_duration(): - update.called_once() - # Timeout is 1 second - assert 2 > end - start > 1 + @pytest.fixture +@@ -160,3 +160,92 @@ def test_when_syndic_return_processes_load_then_correct_values_should_be_returne + with patch.object(encrypted_requests, "_return", autospec=True) as fake_return: + encrypted_requests._syndic_return(payload) + fake_return.assert_called_with(expected_return) + + +def test_mworker_pass_context(): @@ -271,6 +271,6 @@ index a49ecfec3b..ca02c7788d 100644 + == test_context + ) -- -2.37.3 +2.39.2 diff --git a/prevent-affection-of-ssh.opts-with-lazyloader-bsc-11.patch b/prevent-affection-of-ssh.opts-with-lazyloader-bsc-11.patch index 7197ff9..a88c3e7 100644 --- a/prevent-affection-of-ssh.opts-with-lazyloader-bsc-11.patch +++ b/prevent-affection-of-ssh.opts-with-lazyloader-bsc-11.patch @@ -1,4 +1,4 @@ -From ad3735581379e5d4bbc7baef3eaa4a1b8387ccbf Mon Sep 17 00:00:00 2001 +From 90236c844cfce7da8beb7a570be19a8677c60820 Mon Sep 17 00:00:00 2001 From: Victor Zhestkov Date: Tue, 12 Apr 2022 10:06:43 +0300 Subject: [PATCH] Prevent affection of SSH.opts with LazyLoader @@ -9,13 +9,17 @@ Subject: [PATCH] Prevent affection of SSH.opts with LazyLoader * Restore parsed targets * Fix test_ssh unit tests + +Adjust unit tests --- - salt/client/ssh/__init__.py | 19 +++++++++++-------- - tests/unit/client/test_ssh.py | 18 +++++++++--------- - 2 files changed, 20 insertions(+), 17 deletions(-) + salt/client/ssh/__init__.py | 19 +++++++++------- + .../pytests/unit/client/ssh/test_password.py | 4 +++- + .../unit/client/ssh/test_return_events.py | 2 +- + tests/pytests/unit/client/ssh/test_ssh.py | 22 +++++++++---------- + 4 files changed, 26 insertions(+), 21 deletions(-) diff --git a/salt/client/ssh/__init__.py b/salt/client/ssh/__init__.py -index 8ae417f575..fe1213b723 100644 +index a527c03de6..d5a679821e 100644 --- a/salt/client/ssh/__init__.py +++ b/salt/client/ssh/__init__.py @@ -224,15 +224,16 @@ class SSH(MultiprocessingStateMixin): @@ -92,92 +96,145 @@ index 8ae417f575..fe1213b723 100644 self.targets ) >= len(running): time.sleep(0.1) -diff --git a/tests/unit/client/test_ssh.py b/tests/unit/client/test_ssh.py -index 00313ed55f..92a9314149 100644 ---- a/tests/unit/client/test_ssh.py -+++ b/tests/unit/client/test_ssh.py -@@ -95,7 +95,7 @@ class SSHReturnEventTests(ShellCase): - assert "localhost" in ret - assert "fun" in ret["localhost"] - client.run() -- display_output.assert_called_once_with(expected, "nested", opts) -+ display_output.assert_called_once_with(expected, "nested", client.opts) - self.assertIs(ret, handle_ssh_ret[0]) - assert len(client.event.fire_event.call_args_list) == 2 - assert "fun" in client.event.fire_event.call_args_list[0][0][0] -@@ -539,7 +539,7 @@ class SSHTests(ShellCase): - MagicMock(return_value=salt.utils.yaml.safe_load(self.roster)), - ): - client._expand_target() -- assert opts["tgt"] == host -+ assert client.opts["tgt"] == host +diff --git a/tests/pytests/unit/client/ssh/test_password.py b/tests/pytests/unit/client/ssh/test_password.py +index 8a7794d2f4..0ca28d022e 100644 +--- a/tests/pytests/unit/client/ssh/test_password.py ++++ b/tests/pytests/unit/client/ssh/test_password.py +@@ -27,6 +27,8 @@ def test_password_failure(temp_salt_master, tmp_path): + opts["argv"] = ["test.ping"] + opts["selected_target_option"] = "glob" + opts["tgt"] = "localhost" ++ opts["ssh_cli_tgt"] = "localhost" ++ opts["_ssh_version"] = "foobar" + opts["arg"] = [] + roster = str(tmp_path / "roster") + handle_ssh_ret = [ +@@ -44,7 +46,7 @@ def test_password_failure(temp_salt_master, tmp_path): + "salt.client.ssh.SSH.handle_ssh", MagicMock(return_value=handle_ssh_ret) + ), patch("salt.client.ssh.SSH.key_deploy", MagicMock(return_value=expected)), patch( + "salt.output.display_output", display_output +- ): ++ ), patch("salt.client.ssh.ssh_version", MagicMock(return_value="foobar")): + client = ssh.SSH(opts) + ret = next(client.run_iter()) + with pytest.raises(SystemExit): +diff --git a/tests/pytests/unit/client/ssh/test_return_events.py b/tests/pytests/unit/client/ssh/test_return_events.py +index 1f0b0dbf33..18714741b9 100644 +--- a/tests/pytests/unit/client/ssh/test_return_events.py ++++ b/tests/pytests/unit/client/ssh/test_return_events.py +@@ -43,7 +43,7 @@ def test_not_missing_fun_calling_wfuncs(temp_salt_master, tmp_path): + assert "localhost" in ret + assert "fun" in ret["localhost"] + client.run() +- display_output.assert_called_once_with(expected, "nested", opts) ++ display_output.assert_called_once_with(expected, "nested", client.opts) + assert ret is handle_ssh_ret[0] + assert len(client.event.fire_event.call_args_list) == 2 + assert "fun" in client.event.fire_event.call_args_list[0][0][0] +diff --git a/tests/pytests/unit/client/ssh/test_ssh.py b/tests/pytests/unit/client/ssh/test_ssh.py +index 2be96ab195..377aad9998 100644 +--- a/tests/pytests/unit/client/ssh/test_ssh.py ++++ b/tests/pytests/unit/client/ssh/test_ssh.py +@@ -148,7 +148,7 @@ def test_expand_target_ip_address(opts, roster): + MagicMock(return_value=salt.utils.yaml.safe_load(roster)), + ): + client._expand_target() +- assert opts["tgt"] == host ++ assert client.opts["tgt"] == host - def test_expand_target_no_host(self): - """ -@@ -564,7 +564,7 @@ class SSHTests(ShellCase): - assert opts["tgt"] == user + host - with patch("salt.roster.get_roster_file", MagicMock(return_value=roster_file)): - client._expand_target() -- assert opts["tgt"] == host -+ assert client.opts["tgt"] == host - def test_expand_target_dns(self): - """ -@@ -587,7 +587,7 @@ class SSHTests(ShellCase): - MagicMock(return_value=salt.utils.yaml.safe_load(self.roster)), - ): - client._expand_target() -- assert opts["tgt"] == host -+ assert client.opts["tgt"] == host + def test_expand_target_no_host(opts, tmp_path): +@@ -171,7 +171,7 @@ def test_expand_target_no_host(opts, tmp_path): + assert opts["tgt"] == user + host + with patch("salt.roster.get_roster_file", MagicMock(return_value=roster_file)): + client._expand_target() +- assert opts["tgt"] == host ++ assert client.opts["tgt"] == host - def test_expand_target_no_user(self): - """ -@@ -627,7 +627,7 @@ class SSHTests(ShellCase): - client = ssh.SSH(opts) - assert opts["tgt"] == user + host - client._update_targets() -- assert opts["tgt"] == host -+ assert client.opts["tgt"] == host - assert client.targets[host]["user"] == user.split("@")[0] - def test_update_targets_dns(self): -@@ -645,7 +645,7 @@ class SSHTests(ShellCase): - client = ssh.SSH(opts) - assert opts["tgt"] == user + host - client._update_targets() -- assert opts["tgt"] == host -+ assert client.opts["tgt"] == host - assert client.targets[host]["user"] == user.split("@")[0] + def test_expand_target_dns(opts, roster): +@@ -192,7 +192,7 @@ def test_expand_target_dns(opts, roster): + MagicMock(return_value=salt.utils.yaml.safe_load(roster)), + ): + client._expand_target() +- assert opts["tgt"] == host ++ assert client.opts["tgt"] == host - def test_update_targets_no_user(self): -@@ -686,7 +686,7 @@ class SSHTests(ShellCase): - ): - client._expand_target() - client._update_targets() -- assert opts["tgt"] == host -+ assert client.opts["tgt"] == host - assert client.targets[host]["user"] == user.split("@")[0] - def test_parse_tgt(self): -@@ -706,7 +706,7 @@ class SSHTests(ShellCase): - client = ssh.SSH(opts) - assert client.parse_tgt["hostname"] == host - assert client.parse_tgt["user"] == user.split("@")[0] -- assert self.opts.get("ssh_cli_tgt") == user + host -+ assert client.opts.get("ssh_cli_tgt") == user + host + def test_expand_target_no_user(opts, roster): +@@ -204,7 +204,7 @@ def test_expand_target_no_user(opts, roster): - def test_parse_tgt_no_user(self): - """ -@@ -725,7 +725,7 @@ class SSHTests(ShellCase): - client = ssh.SSH(opts) - assert client.parse_tgt["hostname"] == host - assert client.parse_tgt["user"] == opts["ssh_user"] -- assert self.opts.get("ssh_cli_tgt") == host -+ assert client.opts.get("ssh_cli_tgt") == host + with patch("salt.utils.network.is_reachable_host", MagicMock(return_value=False)): + client = ssh.SSH(opts) +- assert opts["tgt"] == host ++ assert client.opts["tgt"] == host - def test_extra_filerefs(self): - """ + with patch( + "salt.roster.get_roster_file", MagicMock(return_value="/etc/salt/roster") +@@ -213,7 +213,7 @@ def test_expand_target_no_user(opts, roster): + MagicMock(return_value=salt.utils.yaml.safe_load(roster)), + ): + client._expand_target() +- assert opts["tgt"] == host ++ assert client.opts["tgt"] == host + + + def test_update_targets_ip_address(opts): +@@ -228,7 +228,7 @@ def test_update_targets_ip_address(opts): + client = ssh.SSH(opts) + assert opts["tgt"] == user + host + client._update_targets() +- assert opts["tgt"] == host ++ assert client.opts["tgt"] == host + assert client.targets[host]["user"] == user.split("@")[0] + + +@@ -244,7 +244,7 @@ def test_update_targets_dns(opts): + client = ssh.SSH(opts) + assert opts["tgt"] == user + host + client._update_targets() +- assert opts["tgt"] == host ++ assert client.opts["tgt"] == host + assert client.targets[host]["user"] == user.split("@")[0] + + +@@ -259,7 +259,7 @@ def test_update_targets_no_user(opts): + client = ssh.SSH(opts) + assert opts["tgt"] == host + client._update_targets() +- assert opts["tgt"] == host ++ assert client.opts["tgt"] == host + + + def test_update_expand_target_dns(opts, roster): +@@ -281,7 +281,7 @@ def test_update_expand_target_dns(opts, roster): + ): + client._expand_target() + client._update_targets() +- assert opts["tgt"] == host ++ assert client.opts["tgt"] == host + assert client.targets[host]["user"] == user.split("@")[0] + + +@@ -299,7 +299,7 @@ def test_parse_tgt(opts): + client = ssh.SSH(opts) + assert client.parse_tgt["hostname"] == host + assert client.parse_tgt["user"] == user.split("@")[0] +- assert opts.get("ssh_cli_tgt") == user + host ++ assert client.opts.get("ssh_cli_tgt") == user + host + + + def test_parse_tgt_no_user(opts): +@@ -316,7 +316,7 @@ def test_parse_tgt_no_user(opts): + client = ssh.SSH(opts) + assert client.parse_tgt["hostname"] == host + assert client.parse_tgt["user"] == opts["ssh_user"] +- assert opts.get("ssh_cli_tgt") == host ++ assert client.opts.get("ssh_cli_tgt") == host + + + def test_extra_filerefs(tmp_path, opts): -- -2.37.3 +2.39.2 diff --git a/prevent-pkg-plugins-errors-on-missing-cookie-path-bs.patch b/prevent-pkg-plugins-errors-on-missing-cookie-path-bs.patch index 4ac11f9..a0a8f35 100644 --- a/prevent-pkg-plugins-errors-on-missing-cookie-path-bs.patch +++ b/prevent-pkg-plugins-errors-on-missing-cookie-path-bs.patch @@ -1,4 +1,4 @@ -From 6c1878310bf75be467b5ce15e8c89134a6f770cb Mon Sep 17 00:00:00 2001 +From 4240f0d5ffbc46c557885c5a28d1f2fd0b4c5e48 Mon Sep 17 00:00:00 2001 From: Victor Zhestkov <35733135+vzhestkov@users.noreply.github.com> Date: Mon, 8 Nov 2021 17:42:36 +0300 Subject: [PATCH] Prevent pkg plugins errors on missing cookie path @@ -97,6 +97,6 @@ index bacbc8b97e..e3528e87a9 100755 self.ack() -- -2.37.3 +2.39.2 diff --git a/prevent-shell-injection-via-pre_flight_script_args-4.patch b/prevent-shell-injection-via-pre_flight_script_args-4.patch index 76bf003..14376a5 100644 --- a/prevent-shell-injection-via-pre_flight_script_args-4.patch +++ b/prevent-shell-injection-via-pre_flight_script_args-4.patch @@ -1,4 +1,4 @@ -From 57f2400bfce206e16e7f282cd3b93cd4d7e99dd7 Mon Sep 17 00:00:00 2001 +From 1b4e382856e1d5d8ef95890aec5a8e5e07254708 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?= Date: Mon, 28 Feb 2022 14:25:43 +0000 @@ -28,6 +28,6 @@ index e050f43caf..2d1a276cb8 100644 class SaltLogRecord(logging.LogRecord): -- -2.37.3 +2.39.2 diff --git a/read-repo-info-without-using-interpolation-bsc-11356.patch b/read-repo-info-without-using-interpolation-bsc-11356.patch index 4ec0781..29cfec7 100644 --- a/read-repo-info-without-using-interpolation-bsc-11356.patch +++ b/read-repo-info-without-using-interpolation-bsc-11356.patch @@ -1,4 +1,4 @@ -From c27ac9afb6bd13fc26fc440e0a097bbb82cbb640 Mon Sep 17 00:00:00 2001 +From ce0fedf25dea7eb63ccff8f9b90a9a35571a5f9d Mon Sep 17 00:00:00 2001 From: Mihai Dinca Date: Thu, 7 Nov 2019 15:11:49 +0100 Subject: [PATCH] Read repo info without using interpolation @@ -9,10 +9,10 @@ Subject: [PATCH] Read repo info without using interpolation 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py -index dd836b7ad0..32e22ce9a8 100644 +index 6adf5f9aa3..d8220a1fdd 100644 --- a/salt/modules/zypperpkg.py +++ b/salt/modules/zypperpkg.py -@@ -1121,7 +1121,9 @@ def _get_repo_info(alias, repos_cfg=None, root=None): +@@ -1155,7 +1155,9 @@ def _get_repo_info(alias, repos_cfg=None, root=None): Get one repo meta-data. """ try: @@ -24,6 +24,6 @@ index dd836b7ad0..32e22ce9a8 100644 for key, val in meta.items(): if val in ["0", "1"]: -- -2.37.3 +2.39.2 diff --git a/restore-default-behaviour-of-pkg-list-return.patch b/restore-default-behaviour-of-pkg-list-return.patch index a598703..dd1c0aa 100644 --- a/restore-default-behaviour-of-pkg-list-return.patch +++ b/restore-default-behaviour-of-pkg-list-return.patch @@ -1,4 +1,4 @@ -From 2de635bd9c2f9571092d5904ac8fa971c0140235 Mon Sep 17 00:00:00 2001 +From a1a8b5a886705e5f005cb7ab067e42095066ef80 Mon Sep 17 00:00:00 2001 From: Jochen Breuer Date: Fri, 30 Aug 2019 14:20:06 +0200 Subject: [PATCH] Restore default behaviour of pkg list return @@ -13,10 +13,10 @@ Co-authored-by: Mihai Dinca 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py -index e52535d428..dd836b7ad0 100644 +index 9d16fcb0b1..6adf5f9aa3 100644 --- a/salt/modules/zypperpkg.py +++ b/salt/modules/zypperpkg.py -@@ -1410,8 +1410,10 @@ def refresh_db(force=None, root=None): +@@ -1456,8 +1456,10 @@ def refresh_db(force=None, root=None): return ret @@ -28,7 +28,7 @@ index e52535d428..dd836b7ad0 100644 return sorted({pkg.split(":", 1)[0] for pkg in pkgs if len(pkg.split(":", 1)) == 2}) -@@ -1427,6 +1429,7 @@ def install( +@@ -1473,6 +1475,7 @@ def install( ignore_repo_failure=False, no_recommends=False, root=None, @@ -36,7 +36,7 @@ index e52535d428..dd836b7ad0 100644 **kwargs ): """ -@@ -1542,6 +1545,9 @@ def install( +@@ -1588,6 +1591,9 @@ def install( .. versionadded:: 2018.3.0 @@ -46,7 +46,7 @@ index e52535d428..dd836b7ad0 100644 Returns a dict containing the new package names and versions:: -@@ -1617,7 +1623,8 @@ def install( +@@ -1663,7 +1669,8 @@ def install( diff_attr = kwargs.get("diff_attr") @@ -56,7 +56,7 @@ index e52535d428..dd836b7ad0 100644 old = ( list_pkgs(attr=diff_attr, root=root, includes=includes) if not downloadonly -@@ -1847,7 +1854,7 @@ def upgrade( +@@ -1964,7 +1971,7 @@ def upgrade( return ret @@ -65,7 +65,7 @@ index e52535d428..dd836b7ad0 100644 """ Remove and purge do identical things but with different Zypper commands, this function performs the common logic. -@@ -1857,7 +1864,7 @@ def _uninstall(name=None, pkgs=None, root=None): +@@ -1974,7 +1981,7 @@ def _uninstall(name=None, pkgs=None, root=None): except MinionError as exc: raise CommandExecutionError(exc) @@ -74,7 +74,7 @@ index e52535d428..dd836b7ad0 100644 old = list_pkgs(root=root, includes=includes) targets = [] for target in pkg_params: -@@ -1920,7 +1927,7 @@ def normalize_name(name): +@@ -2037,7 +2044,7 @@ def normalize_name(name): def remove( @@ -83,7 +83,7 @@ index e52535d428..dd836b7ad0 100644 ): # pylint: disable=unused-argument """ .. versionchanged:: 2015.8.12,2016.3.3,2016.11.0 -@@ -1952,8 +1959,11 @@ def remove( +@@ -2069,8 +2076,11 @@ def remove( root Operate on a different root directory. @@ -96,7 +96,7 @@ index e52535d428..dd836b7ad0 100644 Returns a dict containing the changes. -@@ -1965,10 +1975,12 @@ def remove( +@@ -2082,10 +2092,12 @@ def remove( salt '*' pkg.remove ,, salt '*' pkg.remove pkgs='["foo", "bar"]' """ @@ -111,7 +111,7 @@ index e52535d428..dd836b7ad0 100644 """ .. versionchanged:: 2015.8.12,2016.3.3,2016.11.0 On minions running systemd>=205, `systemd-run(1)`_ is now used to -@@ -2000,6 +2012,10 @@ def purge(name=None, pkgs=None, root=None, **kwargs): # pylint: disable=unused- +@@ -2117,6 +2129,10 @@ def purge(name=None, pkgs=None, root=None, **kwargs): # pylint: disable=unused- root Operate on a different root directory. @@ -122,7 +122,7 @@ index e52535d428..dd836b7ad0 100644 .. versionadded:: 0.16.0 -@@ -2013,7 +2029,7 @@ def purge(name=None, pkgs=None, root=None, **kwargs): # pylint: disable=unused- +@@ -2130,7 +2146,7 @@ def purge(name=None, pkgs=None, root=None, **kwargs): # pylint: disable=unused- salt '*' pkg.purge ,, salt '*' pkg.purge pkgs='["foo", "bar"]' """ @@ -132,6 +132,6 @@ index e52535d428..dd836b7ad0 100644 def list_holds(pattern=None, full=True, root=None, **kwargs): -- -2.37.3 +2.39.2 diff --git a/retry-if-rpm-lock-is-temporarily-unavailable-547.patch b/retry-if-rpm-lock-is-temporarily-unavailable-547.patch deleted file mode 100644 index 46cb60b..0000000 --- a/retry-if-rpm-lock-is-temporarily-unavailable-547.patch +++ /dev/null @@ -1,297 +0,0 @@ -From 4a9ec335e7da2f0e3314580e43075bb69fe90c38 Mon Sep 17 00:00:00 2001 -From: Witek Bedyk -Date: Mon, 29 Aug 2022 14:16:00 +0200 -Subject: [PATCH] Retry if RPM lock is temporarily unavailable (#547) - -* Retry if RPM lock is temporarily unavailable - -Backported from saltstack/salt#62204 - -Signed-off-by: Witek Bedyk - -* Sync formating fixes from upstream - -Signed-off-by: Witek Bedyk ---- - changelog/62204.fixed | 1 + - salt/modules/zypperpkg.py | 117 +++++++++++++++++---------- - tests/unit/modules/test_zypperpkg.py | 45 ++++++++++- - 3 files changed, 115 insertions(+), 48 deletions(-) - create mode 100644 changelog/62204.fixed - -diff --git a/changelog/62204.fixed b/changelog/62204.fixed -new file mode 100644 -index 0000000000..59f1914593 ---- /dev/null -+++ b/changelog/62204.fixed -@@ -0,0 +1 @@ -+Fixed Zypper module failing on RPM lock file being temporarily unavailable. -diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py -index 2c36e2968a..c787d4009d 100644 ---- a/salt/modules/zypperpkg.py -+++ b/salt/modules/zypperpkg.py -@@ -14,6 +14,7 @@ Package support for openSUSE via the zypper package manager - - import configparser - import datetime -+import errno - import fnmatch - import logging - import os -@@ -39,6 +40,9 @@ from salt.exceptions import CommandExecutionError, MinionError, SaltInvocationEr - # pylint: disable=import-error,redefined-builtin,no-name-in-module - from salt.utils.versions import LooseVersion - -+if salt.utils.files.is_fcntl_available(): -+ import fcntl -+ - log = logging.getLogger(__name__) - - HAS_ZYPP = False -@@ -106,6 +110,7 @@ class _Zypper: - XML_DIRECTIVES = ["-x", "--xmlout"] - # ZYPPER_LOCK is not affected by --root - ZYPPER_LOCK = "/var/run/zypp.pid" -+ RPM_LOCK = "/var/lib/rpm/.rpm.lock" - TAG_RELEASED = "zypper/released" - TAG_BLOCKED = "zypper/blocked" - -@@ -276,7 +281,7 @@ class _Zypper: - and self.exit_code not in self.WARNING_EXIT_CODES - ) - -- def _is_lock(self): -+ def _is_zypper_lock(self): - """ - Is this is a lock error code? - -@@ -284,6 +289,23 @@ class _Zypper: - """ - return self.exit_code == self.LOCK_EXIT_CODE - -+ def _is_rpm_lock(self): -+ """ -+ Is this an RPM lock error? -+ """ -+ if salt.utils.files.is_fcntl_available(): -+ if self.exit_code > 0 and os.path.exists(self.RPM_LOCK): -+ with salt.utils.files.fopen(self.RPM_LOCK, mode="w+") as rfh: -+ try: -+ fcntl.lockf(rfh, fcntl.LOCK_EX | fcntl.LOCK_NB) -+ except OSError as err: -+ if err.errno == errno.EAGAIN: -+ return True -+ else: -+ fcntl.lockf(rfh, fcntl.LOCK_UN) -+ -+ return False -+ - def _is_xml_mode(self): - """ - Is Zypper's output is in XML format? -@@ -306,7 +328,7 @@ class _Zypper: - raise CommandExecutionError("No output result from Zypper?") - - self.exit_code = self.__call_result["retcode"] -- if self._is_lock(): -+ if self._is_zypper_lock() or self._is_rpm_lock(): - return False - - if self._is_error(): -@@ -387,48 +409,11 @@ class _Zypper: - if self._check_result(): - break - -- if os.path.exists(self.ZYPPER_LOCK): -- try: -- with salt.utils.files.fopen(self.ZYPPER_LOCK) as rfh: -- data = __salt__["ps.proc_info"]( -- int(rfh.readline()), -- attrs=["pid", "name", "cmdline", "create_time"], -- ) -- data["cmdline"] = " ".join(data["cmdline"]) -- data["info"] = "Blocking process created at {}.".format( -- datetime.datetime.utcfromtimestamp( -- data["create_time"] -- ).isoformat() -- ) -- data["success"] = True -- except Exception as err: # pylint: disable=broad-except -- data = { -- "info": ( -- "Unable to retrieve information about blocking process: {}".format( -- err.message -- ) -- ), -- "success": False, -- } -- else: -- data = { -- "info": "Zypper is locked, but no Zypper lock has been found.", -- "success": False, -- } -- -- if not data["success"]: -- log.debug("Unable to collect data about blocking process.") -- else: -- log.debug("Collected data about blocking process.") -- -- __salt__["event.fire_master"](data, self.TAG_BLOCKED) -- log.debug( -- "Fired a Zypper blocked event to the master with the data: %s", data -- ) -- log.debug("Waiting 5 seconds for Zypper gets released...") -- time.sleep(5) -- if not was_blocked: -- was_blocked = True -+ if self._is_zypper_lock(): -+ self._handle_zypper_lock_file() -+ if self._is_rpm_lock(): -+ self._handle_rpm_lock_file() -+ was_blocked = True - - if was_blocked: - __salt__["event.fire_master"]( -@@ -451,6 +436,50 @@ class _Zypper: - or self.__call_result["stdout"] - ) - -+ def _handle_zypper_lock_file(self): -+ if os.path.exists(self.ZYPPER_LOCK): -+ try: -+ with salt.utils.files.fopen(self.ZYPPER_LOCK) as rfh: -+ data = __salt__["ps.proc_info"]( -+ int(rfh.readline()), -+ attrs=["pid", "name", "cmdline", "create_time"], -+ ) -+ data["cmdline"] = " ".join(data["cmdline"]) -+ data["info"] = "Blocking process created at {}.".format( -+ datetime.datetime.utcfromtimestamp( -+ data["create_time"] -+ ).isoformat() -+ ) -+ data["success"] = True -+ except Exception as err: # pylint: disable=broad-except -+ data = { -+ "info": ( -+ "Unable to retrieve information about " -+ "blocking process: {}".format(err) -+ ), -+ "success": False, -+ } -+ else: -+ data = { -+ "info": "Zypper is locked, but no Zypper lock has been found.", -+ "success": False, -+ } -+ if not data["success"]: -+ log.debug("Unable to collect data about blocking process.") -+ else: -+ log.debug("Collected data about blocking process.") -+ __salt__["event.fire_master"](data, self.TAG_BLOCKED) -+ log.debug("Fired a Zypper blocked event to the master with the data: %s", data) -+ log.debug("Waiting 5 seconds for Zypper gets released...") -+ time.sleep(5) -+ -+ def _handle_rpm_lock_file(self): -+ data = {"info": "RPM is temporarily locked.", "success": True} -+ __salt__["event.fire_master"](data, self.TAG_BLOCKED) -+ log.debug("Fired an RPM blocked event to the master with the data: %s", data) -+ log.debug("Waiting 5 seconds for RPM to get released...") -+ time.sleep(5) -+ - - __zypper__ = _Zypper() - -diff --git a/tests/unit/modules/test_zypperpkg.py b/tests/unit/modules/test_zypperpkg.py -index 3f1560a385..37d555844c 100644 ---- a/tests/unit/modules/test_zypperpkg.py -+++ b/tests/unit/modules/test_zypperpkg.py -@@ -4,6 +4,7 @@ - - - import configparser -+import errno - import io - import os - from xml.dom import minidom -@@ -97,7 +98,7 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): - } - with patch.dict( - zypper.__salt__, {"cmd.run_all": MagicMock(return_value=ref_out)} -- ): -+ ), patch.object(zypper.__zypper__, "_is_rpm_lock", return_value=False): - upgrades = zypper.list_upgrades(refresh=False) - self.assertEqual(len(upgrades), 3) - for pkg, version in { -@@ -198,7 +199,9 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): - ' type="error">Booya!' - ) - sniffer = RunSniffer(stdout=stdout_xml_snippet, retcode=1) -- with patch.dict("salt.modules.zypperpkg.__salt__", {"cmd.run_all": sniffer}): -+ with patch.dict( -+ "salt.modules.zypperpkg.__salt__", {"cmd.run_all": sniffer} -+ ), patch.object(zypper.__zypper__, "_is_rpm_lock", return_value=False): - with self.assertRaisesRegex( - CommandExecutionError, "^Zypper command failure: Booya!$" - ): -@@ -232,7 +235,7 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): - with patch.dict( - "salt.modules.zypperpkg.__salt__", - {"cmd.run_all": MagicMock(return_value=ref_out)}, -- ): -+ ), patch.object(zypper.__zypper__, "_is_rpm_lock", return_value=False): - with self.assertRaisesRegex( - CommandExecutionError, - "^Zypper command failure: Some handled zypper internal error{}Another" -@@ -245,7 +248,7 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): - with patch.dict( - "salt.modules.zypperpkg.__salt__", - {"cmd.run_all": MagicMock(return_value=ref_out)}, -- ): -+ ), patch.object(zypper.__zypper__, "_is_rpm_lock", return_value=False): - with self.assertRaisesRegex( - CommandExecutionError, "^Zypper command failure: Check Zypper's logs.$" - ): -@@ -2064,3 +2067,37 @@ pattern() = package-c""" - python_shell=False, - env={"ZYPP_READONLY_HACK": "1"}, - ) -+ -+ def test_is_rpm_lock_no_error(self): -+ with patch.object(os.path, "exists", return_value=True): -+ self.assertFalse(zypper.__zypper__._is_rpm_lock()) -+ -+ def test_rpm_lock_does_not_exist(self): -+ if salt.utils.files.is_fcntl_available(): -+ zypper.__zypper__.exit_code = 1 -+ with patch.object( -+ os.path, "exists", return_value=False -+ ) as mock_path_exists: -+ self.assertFalse(zypper.__zypper__._is_rpm_lock()) -+ mock_path_exists.assert_called_with(zypper.__zypper__.RPM_LOCK) -+ zypper.__zypper__._reset() -+ -+ def test_rpm_lock_acquirable(self): -+ if salt.utils.files.is_fcntl_available(): -+ zypper.__zypper__.exit_code = 1 -+ with patch.object(os.path, "exists", return_value=True), patch( -+ "fcntl.lockf", side_effect=OSError(errno.EAGAIN, "") -+ ) as lockf_mock, patch("salt.utils.files.fopen", mock_open()): -+ self.assertTrue(zypper.__zypper__._is_rpm_lock()) -+ lockf_mock.assert_called() -+ zypper.__zypper__._reset() -+ -+ def test_rpm_lock_not_acquirable(self): -+ if salt.utils.files.is_fcntl_available(): -+ zypper.__zypper__.exit_code = 1 -+ with patch.object(os.path, "exists", return_value=True), patch( -+ "fcntl.lockf" -+ ) as lockf_mock, patch("salt.utils.files.fopen", mock_open()): -+ self.assertFalse(zypper.__zypper__._is_rpm_lock()) -+ self.assertEqual(lockf_mock.call_count, 2) -+ zypper.__zypper__._reset() --- -2.37.3 - - diff --git a/return-the-expected-powerpc-os-arch-bsc-1117995.patch b/return-the-expected-powerpc-os-arch-bsc-1117995.patch index d653643..b25ae08 100644 --- a/return-the-expected-powerpc-os-arch-bsc-1117995.patch +++ b/return-the-expected-powerpc-os-arch-bsc-1117995.patch @@ -1,4 +1,4 @@ -From 3ce70f43376dbf62edf2ca2aa8c9f28aa733b3d8 Mon Sep 17 00:00:00 2001 +From ceaf42a67d21cb6fa723339559c85be969e67308 Mon Sep 17 00:00:00 2001 From: Mihai Dinca Date: Thu, 13 Dec 2018 12:17:35 +0100 Subject: [PATCH] Return the expected powerpc os arch (bsc#1117995) @@ -8,10 +8,10 @@ Subject: [PATCH] Return the expected powerpc os arch (bsc#1117995) 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/salt/utils/pkg/rpm.py b/salt/utils/pkg/rpm.py -index e80a01f92f..8203d2f989 100644 +index f9975f8dff..147447ba75 100644 --- a/salt/utils/pkg/rpm.py +++ b/salt/utils/pkg/rpm.py -@@ -59,9 +59,10 @@ def get_osarch(): +@@ -69,9 +69,10 @@ def get_osarch(): stderr=subprocess.PIPE, ).communicate()[0] else: @@ -26,6 +26,6 @@ index e80a01f92f..8203d2f989 100644 def check_32(arch, osarch=None): -- -2.37.3 +2.39.2 diff --git a/revert-fixing-a-use-case-when-multiple-inotify-beaco.patch b/revert-fixing-a-use-case-when-multiple-inotify-beaco.patch index e8b6485..824e34a 100644 --- a/revert-fixing-a-use-case-when-multiple-inotify-beaco.patch +++ b/revert-fixing-a-use-case-when-multiple-inotify-beaco.patch @@ -1,4 +1,4 @@ -From dc849a15ea214170d4de9f54615caa8b3136dc10 Mon Sep 17 00:00:00 2001 +From 76f2b98a3a9b9a49903a4d3b47dca0f2311bd7af Mon Sep 17 00:00:00 2001 From: Alexander Graul Date: Tue, 18 Jan 2022 19:07:34 +0100 Subject: [PATCH] Revert "Fixing a use case when multiple inotify beacons @@ -17,8 +17,8 @@ This reverts commit 66c58dedf8c364eaeb35c5adce8bcc8fe5c1219a. salt/beacons/napalm_beacon.py | 6 ++---- salt/beacons/status.py | 4 ---- tests/pytests/unit/beacons/test_inotify.py | 5 +---- - tests/pytests/unit/test_beacons.py | 16 --------------- - 7 files changed, 11 insertions(+), 48 deletions(-) + tests/pytests/unit/test_beacons.py | 17 --------------- + 7 files changed, 11 insertions(+), 49 deletions(-) diff --git a/salt/beacons/__init__.py b/salt/beacons/__init__.py index b346c2a648..90918cba5b 100644 @@ -162,10 +162,10 @@ index aa5aa13b47..e2c3177ea8 100644 config = [ { diff --git a/tests/pytests/unit/beacons/test_inotify.py b/tests/pytests/unit/beacons/test_inotify.py -index f5befb2756..dfaf1d499a 100644 +index 30a9a91db4..678a528529 100644 --- a/tests/pytests/unit/beacons/test_inotify.py +++ b/tests/pytests/unit/beacons/test_inotify.py -@@ -273,7 +273,6 @@ def test_multi_files_exclude(tmp_path): +@@ -263,7 +263,6 @@ def test_multi_files_exclude(tmp_path): # Check __get_notifier and ensure that the right bits are in __context__ @@ -173,7 +173,7 @@ index f5befb2756..dfaf1d499a 100644 def test__get_notifier(): config = { "files": { -@@ -303,10 +302,8 @@ def test__get_notifier(): +@@ -293,10 +292,8 @@ def test__get_notifier(): }, }, "coalesce": True, @@ -186,13 +186,14 @@ index f5befb2756..dfaf1d499a 100644 - assert "httpd.inotify.notifier" in inotify.__context__ + assert "inotify.notifier" in inotify.__context__ diff --git a/tests/pytests/unit/test_beacons.py b/tests/pytests/unit/test_beacons.py -index 2ca0b30ea2..841a3b8140 100644 +index 217cd5c6a4..855e271d7d 100644 --- a/tests/pytests/unit/test_beacons.py +++ b/tests/pytests/unit/test_beacons.py -@@ -108,19 +108,3 @@ def test_beacon_module(): +@@ -104,20 +104,3 @@ def test_beacon_module(minion_opts): + } ] assert ret == _expected - +- - # Ensure that "beacon_name" is available in the call to the beacon function - name = "ps.beacon" - mocked = {name: MagicMock(return_value=_expected)} @@ -207,9 +208,9 @@ index 2ca0b30ea2..841a3b8140 100644 - ) - ] - with patch.object(beacon, "beacons", mocked) as patched: -- beacon.process(mock_opts["beacons"], mock_opts["grains"]) +- beacon.process(minion_opts["beacons"], minion_opts["grains"]) - patched[name].assert_has_calls(calls) -- -2.37.3 +2.39.2 diff --git a/run-salt-api-as-user-salt-bsc-1064520.patch b/run-salt-api-as-user-salt-bsc-1064520.patch index c639975..bd9adba 100644 --- a/run-salt-api-as-user-salt-bsc-1064520.patch +++ b/run-salt-api-as-user-salt-bsc-1064520.patch @@ -1,16 +1,16 @@ -From 0dc36f5d2e8ba94e2a527323b698fd49a98f5246 Mon Sep 17 00:00:00 2001 +From a94cfd5dea05c2c4a9d6b8b243048a2ceeb3f208 Mon Sep 17 00:00:00 2001 From: Christian Lanig Date: Mon, 27 Nov 2017 13:10:26 +0100 Subject: [PATCH] Run salt-api as user salt (bsc#1064520) --- - pkg/salt-api.service | 1 + + pkg/common/salt-api.service | 1 + 1 file changed, 1 insertion(+) -diff --git a/pkg/salt-api.service b/pkg/salt-api.service +diff --git a/pkg/common/salt-api.service b/pkg/common/salt-api.service index d0b6d74120..9cdc9c582b 100644 ---- a/pkg/salt-api.service -+++ b/pkg/salt-api.service +--- a/pkg/common/salt-api.service ++++ b/pkg/common/salt-api.service @@ -6,6 +6,7 @@ After=network.target [Service] Type=notify @@ -20,6 +20,6 @@ index d0b6d74120..9cdc9c582b 100644 ExecStart=/usr/bin/salt-api TimeoutStopSec=3 -- -2.37.3 +2.39.2 diff --git a/run-salt-master-as-dedicated-salt-user.patch b/run-salt-master-as-dedicated-salt-user.patch index 0835259..1a28b73 100644 --- a/run-salt-master-as-dedicated-salt-user.patch +++ b/run-salt-master-as-dedicated-salt-user.patch @@ -1,16 +1,16 @@ -From 34d047fa0e2733359501e15ecc282159ddbd29f9 Mon Sep 17 00:00:00 2001 +From 6ffbf7fcc178f32c670b177b25ed64658c59f1bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Klaus=20K=C3=A4mpf?= Date: Wed, 20 Jan 2016 11:01:06 +0100 Subject: [PATCH] Run salt master as dedicated salt user * Minion runs always as a root --- - conf/master | 3 ++- - pkg/salt-common.logrotate | 2 ++ + conf/master | 3 ++- + pkg/common/salt-common.logrotate | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/conf/master b/conf/master -index 17b3768267..95aed0066f 100644 +index f542051d76..acff94abec 100644 --- a/conf/master +++ b/conf/master @@ -25,7 +25,8 @@ @@ -23,10 +23,10 @@ index 17b3768267..95aed0066f 100644 # Tell the master to also use salt-ssh when running commands against minions. #enable_ssh_minions: False -diff --git a/pkg/salt-common.logrotate b/pkg/salt-common.logrotate +diff --git a/pkg/common/salt-common.logrotate b/pkg/common/salt-common.logrotate index a0306ff370..97d158db18 100644 ---- a/pkg/salt-common.logrotate -+++ b/pkg/salt-common.logrotate +--- a/pkg/common/salt-common.logrotate ++++ b/pkg/common/salt-common.logrotate @@ -1,4 +1,5 @@ /var/log/salt/master { + su salt salt @@ -42,6 +42,6 @@ index a0306ff370..97d158db18 100644 missingok rotate 7 -- -2.37.3 +2.39.2 diff --git a/salt.changes b/salt.changes index 17309c1..40688b2 100644 --- a/salt.changes +++ b/salt.changes @@ -1,3 +1,105 @@ +------------------------------------------------------------------- +Fri May 5 08:29:26 UTC 2023 - Alexander Graul + +- Update to Salt release version 3006.0 (jsc#PED-3139) + * See release notes: https://docs.saltproject.io/en/latest/topics/releases/3006.0.html + +- Add python3-looseversion as new dependency for salt +- Add python3-packaging as new dependency for salt +- Drop conflictive patch dicarded from upstream +- Fix SLS rendering error when Jinja macros are used +- Fix version detection and avoid building and testing failures + +- Added: + * fix-version-detection-and-avoid-building-and-testing.patch + * make-sure-the-file-client-is-destroyed-upon-used.patch + +- Modified: + * 3005.1-implement-zypper-removeptf-573.patch + * activate-all-beacons-sources-config-pillar-grains.patch + * add-custom-suse-capabilities-as-grains.patch + * add-environment-variable-to-know-if-yum-is-invoked-f.patch + * add-migrated-state-and-gpg-key-management-functions-.patch + * add-publish_batch-to-clearfuncs-exposed-methods.patch + * add-salt-ssh-support-with-venv-salt-minion-3004-493.patch + * add-sleep-on-exception-handling-on-minion-connection.patch + * add-standalone-configuration-file-for-enabling-packa.patch + * add-support-for-gpgautoimport-539.patch + * allow-vendor-change-option-with-zypper.patch + * async-batch-implementation.patch + * avoid-excessive-syslogging-by-watchdog-cronjob-58.patch + * bsc-1176024-fix-file-directory-user-and-group-owners.patch + * change-the-delimeters-to-prevent-possible-tracebacks.patch + * control-the-collection-of-lvm-grains-via-config.patch + * debian-info_installed-compatibility-50453.patch + * dnfnotify-pkgset-plugin-implementation-3002.2-450.patch + * do-not-load-pip-state-if-there-is-no-3rd-party-depen.patch + * don-t-use-shell-sbin-nologin-in-requisites.patch + * drop-serial-from-event.unpack-in-cli.batch_async.patch + * early-feature-support-config.patch + * enable-passing-a-unix_socket-for-mysql-returners-bsc.patch + * enhance-openscap-module-add-xccdf_eval-call-386.patch + * fix-bsc-1065792.patch + * fix-for-suse-expanded-support-detection.patch + * fix-issue-2068-test.patch + * fix-missing-minion-returns-in-batch-mode-360.patch + * fix-ownership-of-salt-thin-directory-when-using-the-.patch + * fix-regression-with-depending-client.ssh-on-psutil-b.patch + * fix-salt-ssh-opts-poisoning-bsc-1197637-3004-501.patch + * fix-salt.utils.stringutils.to_str-calls-to-make-it-w.patch + * fix-the-regression-for-yumnotify-plugin-456.patch + * fix-traceback.print_exc-calls-for-test_pip_state-432.patch + * fixes-for-python-3.10-502.patch + * include-aliases-in-the-fqdns-grains.patch + * info_installed-works-without-status-attr-now.patch + * let-salt-ssh-use-platform-python-binary-in-rhel8-191.patch + * make-aptpkg.list_repos-compatible-on-enabled-disable.patch + * make-setup.py-script-to-not-require-setuptools-9.1.patch + * pass-the-context-to-pillar-ext-modules.patch + * prevent-affection-of-ssh.opts-with-lazyloader-bsc-11.patch + * prevent-pkg-plugins-errors-on-missing-cookie-path-bs.patch + * prevent-shell-injection-via-pre_flight_script_args-4.patch + * read-repo-info-without-using-interpolation-bsc-11356.patch + * restore-default-behaviour-of-pkg-list-return.patch + * return-the-expected-powerpc-os-arch-bsc-1117995.patch + * revert-fixing-a-use-case-when-multiple-inotify-beaco.patch + * run-salt-api-as-user-salt-bsc-1064520.patch + * run-salt-master-as-dedicated-salt-user.patch + * save-log-to-logfile-with-docker.build.patch + * skip-package-names-without-colon-bsc-1208691-578.patch + * switch-firewalld-state-to-use-change_interface.patch + * temporary-fix-extend-the-whitelist-of-allowed-comman.patch + * update-target-fix-for-salt-ssh-to-process-targets-li.patch + * use-adler32-algorithm-to-compute-string-checksums.patch + * use-rlock-to-avoid-deadlocks-in-salt-ssh.patch + * use-salt-bundle-in-dockermod.patch + * x509-fixes-111.patch + * zypperpkg-ignore-retcode-104-for-search-bsc-1176697-.patch + +- Removed: + * add-amazon-ec2-detection-for-virtual-grains-bsc-1195.patch + * add-support-for-name-pkgs-and-diff_attr-parameters-t.patch + * align-amazon-ec2-nitro-grains-with-upstream-pr-bsc-1.patch + * allow-entrypoint-compatibility-for-importlib-metadat.patch + * clarify-pkg.installed-pkg_verify-documentation.patch + * detect-module.run-syntax.patch + * fix-salt.states.file.managed-for-follow_symlinks-tru.patch + * fix-state.apply-in-test-mode-with-file-state-module-.patch + * fix-test_ipc-unit-tests.patch + * fixes-pkg.version_cmp-on-openeuler-systems-and-a-few.patch + * fopen-workaround-bad-buffering-for-binary-mode-563.patch + * ignore-erros-on-reading-license-files-with-dpkg_lowp.patch + * ignore-extend-declarations-from-excluded-sls-files.patch + * ignore-non-utf8-characters-while-reading-files-with-.patch + * include-stdout-in-error-message-for-zypperpkg-559.patch + * make-pass-renderer-configurable-other-fixes-532.patch + * make-sure-saltcacheloader-use-correct-fileclient-519.patch + * normalize-package-names-once-with-pkg.installed-remo.patch + * retry-if-rpm-lock-is-temporarily-unavailable-547.patch + * set-default-target-for-pip-from-venv_pip_target-envi.patch + * state.apply-don-t-check-for-cached-pillar-errors.patch + * state.orchestrate_single-does-not-pass-pillar-none-4.patch + ------------------------------------------------------------------- Fri Mar 17 12:05:55 UTC 2023 - Alexander Graul diff --git a/salt.spec b/salt.spec index 4bd9926..184e180 100644 --- a/salt.spec +++ b/salt.spec @@ -36,12 +36,12 @@ %bcond_with builddocs Name: salt -Version: 3005.1 +Version: 3006.0 Release: 0 Summary: A parallel remote execution system License: Apache-2.0 Group: System/Management -Url: http://saltstack.org/ +Url: https://saltproject.io/ Source: v%{version}.tar.gz Source1: README.SUSE Source2: salt-tmpfiles.d @@ -219,97 +219,54 @@ Patch41: prevent-pkg-plugins-errors-on-missing-cookie-path-bs.patch Patch42: dnfnotify-pkgset-plugin-implementation-3002.2-450.patch # PATCH-FIX_OPENSUSE https://github.com/openSUSE/salt/pull/456 (missing upstream PR) Patch43: fix-the-regression-for-yumnotify-plugin-456.patch -# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/61189 -Patch44: state.apply-don-t-check-for-cached-pillar-errors.patch # PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/482 -Patch45: drop-serial-from-event.unpack-in-cli.batch_async.patch -# PATCH-FIX_UPSTREAM https://github.com/saltstack/salt/pull/61093 -Patch46: state.orchestrate_single-does-not-pass-pillar-none-4.patch +Patch44: drop-serial-from-event.unpack-in-cli.batch_async.patch ### SALT-SSH WITH SALT BUNDLE ### # PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/61715 (ssh_pre_flight_args) # PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/493 # PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/497 -Patch47: add-salt-ssh-support-with-venv-salt-minion-3004-493.patch -Patch48: prevent-shell-injection-via-pre_flight_script_args-4.patch +Patch45: add-salt-ssh-support-with-venv-salt-minion-3004-493.patch +Patch46: prevent-shell-injection-via-pre_flight_script_args-4.patch ############### # PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/501 -Patch49: fix-salt-ssh-opts-poisoning-bsc-1197637-3004-501.patch +Patch47: fix-salt-ssh-opts-poisoning-bsc-1197637-3004-501.patch # PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/505 -Patch50: prevent-affection-of-ssh.opts-with-lazyloader-bsc-11.patch +Patch48: prevent-affection-of-ssh.opts-with-lazyloader-bsc-11.patch # PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/506 -Patch51: fix-regression-with-depending-client.ssh-on-psutil-b.patch -# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/61895 -Patch52: make-sure-saltcacheloader-use-correct-fileclient-519.patch -# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/61827 -Patch53: ignore-erros-on-reading-license-files-with-dpkg_lowp.patch +Patch49: fix-regression-with-depending-client.ssh-on-psutil-b.patch # PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/62109 -Patch54: use-salt-bundle-in-dockermod.patch +Patch50: use-salt-bundle-in-dockermod.patch # PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/61984 -Patch55: save-log-to-logfile-with-docker.build.patch -# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/62029 -Patch56: normalize-package-names-once-with-pkg.installed-remo.patch -# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/62089 -Patch57: set-default-target-for-pip-from-venv_pip_target-envi.patch +Patch51: save-log-to-logfile-with-docker.build.patch # PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/534 -Patch58: fix-ownership-of-salt-thin-directory-when-using-the-.patch -# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/62033 -Patch59: add-support-for-name-pkgs-and-diff_attr-parameters-t.patch -# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/62067 -Patch60: fix-salt.states.file.managed-for-follow_symlinks-tru.patch +Patch52: fix-ownership-of-salt-thin-directory-when-using-the-.patch # PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/62209 -Patch61: add-support-for-gpgautoimport-539.patch -# PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/commit/2b486d0484c51509e9972e581d97655f4f87852e -Patch62: fix-test_ipc-unit-tests.patch -# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/62204 -Patch63: retry-if-rpm-lock-is-temporarily-unavailable-547.patch +Patch53: add-support-for-gpgautoimport-539.patch # PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/62519 -Patch64: change-the-delimeters-to-prevent-possible-tracebacks.patch -# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/61847 -Patch65: fix-state.apply-in-test-mode-with-file-state-module-.patch -# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/62539 -Patch66: add-amazon-ec2-detection-for-virtual-grains-bsc-1195.patch -# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/62633 -Patch67: ignore-non-utf8-characters-while-reading-files-with-.patch -# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/62817 -Patch68: fopen-workaround-bad-buffering-for-binary-mode-563.patch -# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/62120 -Patch69: make-pass-renderer-configurable-other-fixes-532.patch -### ENHANCE ZYPPERPKG ERROR MESSAGES ### -# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/62750 -# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/62346 -Patch70: include-stdout-in-error-message-for-zypperpkg-559.patch -############### -# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/57426 -Patch71: clarify-pkg.installed-pkg_verify-documentation.patch -# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/62862 -Patch72: ignore-extend-declarations-from-excluded-sls-files.patch -# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/61772 -Patch73: detect-module.run-syntax.patch -# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/62539 -Patch74: align-amazon-ec2-nitro-grains-with-upstream-pr-bsc-1.patch +Patch54: change-the-delimeters-to-prevent-possible-tracebacks.patch # PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/62898 -Patch75: pass-the-context-to-pillar-ext-modules.patch +Patch55: pass-the-context-to-pillar-ext-modules.patch # PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/commit/c6be36eeea49ee0d0641da272087305f79c32c99 (not yet upstream) # Fix problem caused by: https://github.com/openSUSE/salt/pull/493 (Patch47) affecting only 3005.1. -Patch76: use-rlock-to-avoid-deadlocks-in-salt-ssh.patch +Patch56: use-rlock-to-avoid-deadlocks-in-salt-ssh.patch # PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/61064 # PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/commit/5e3ff4d662321c237ddd5b2c5c83f35a84af594c (not PR to master yet) -Patch77: fixes-for-python-3.10-502.patch -# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/62854 -Patch78: allow-entrypoint-compatibility-for-importlib-metadat.patch +Patch57: fixes-for-python-3.10-502.patch # PATCH-FIX-OPENSUSE: https://github.com/openSUSE/salt/pull/571 -Patch79: control-the-collection-of-lvm-grains-via-config.patch +Patch58: control-the-collection-of-lvm-grains-via-config.patch # PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/63460 -Patch80: 3005.1-implement-zypper-removeptf-573.patch -# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/62249 -Patch81: fixes-pkg.version_cmp-on-openeuler-systems-and-a-few.patch +Patch59: 3005.1-implement-zypper-removeptf-573.patch # PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/63460 # PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/pull/578 -Patch82: skip-package-names-without-colon-bsc-1208691-578.patch +Patch60: skip-package-names-without-colon-bsc-1208691-578.patch +# PATCH-FIX_OPENSUSE: https://github.com/openSUSE/salt/commit/c0fae09e5a4f6997a60007d970c7c6a5614d9102 +Patch61: fix-version-detection-and-avoid-building-and-testing.patch +# PATCH-FIX_UPSTREAM: https://github.com/saltstack/salt/pull/64113 +Patch62: make-sure-the-file-client-is-destroyed-upon-used.patch ### IMPORTANT: The line below is used as a snippet marker. Do not touch it. ### SALT PATCHES LIST END @@ -422,6 +379,8 @@ BuildRequires: python3-PyYAML BuildRequires: python3-psutil BuildRequires: python3-requests >= 1.0.0 BuildRequires: python3-distro +BuildRequires: python3-looseversion +BuildRequires: python3-packaging # requirements/zeromq.txt %if %{with test} @@ -472,6 +431,8 @@ Requires: python3-PyYAML Requires: python3-psutil Requires: python3-requests >= 1.0.0 Requires: python3-distro +Requires: python3-looseversion +Requires: python3-packaging Requires: python3-contextvars %if 0%{?suse_version} # required for zypper.py @@ -750,7 +711,6 @@ cp %{S:6} . export PATH=/usr/bin:$PATH %endif python3 setup.py --with-salt-version=%{version} --salt-transport=both build -cp ./build/lib/salt/_version.py ./salt mv build _build.python3 %if %{with docs} && %{without builddocs} @@ -849,15 +809,15 @@ install -Dd %{buildroot}%{_sysconfdir}/yum/pluginconf.d ## install init and systemd scripts %if %{with systemd} -install -Dpm 0644 pkg/suse/salt-master.service %{buildroot}%{_unitdir}/salt-master.service +install -Dpm 0644 pkg/old/suse/salt-master.service %{buildroot}%{_unitdir}/salt-master.service %if 0%{?suse_version} -install -Dpm 0644 pkg/suse/salt-minion.service %{buildroot}%{_unitdir}/salt-minion.service +install -Dpm 0644 pkg/old/suse/salt-minion.service %{buildroot}%{_unitdir}/salt-minion.service %else -install -Dpm 0644 pkg/suse/salt-minion.service.rhel7 %{buildroot}%{_unitdir}/salt-minion.service +install -Dpm 0644 pkg/old/suse/salt-minion.service.rhel7 %{buildroot}%{_unitdir}/salt-minion.service %endif -install -Dpm 0644 pkg/salt-syndic.service %{buildroot}%{_unitdir}/salt-syndic.service -install -Dpm 0644 pkg/suse/salt-api.service %{buildroot}%{_unitdir}/salt-api.service -install -Dpm 0644 pkg/salt-proxy@.service %{buildroot}%{_unitdir}/salt-proxy@.service +install -Dpm 0644 pkg/common/salt-syndic.service %{buildroot}%{_unitdir}/salt-syndic.service +install -Dpm 0644 pkg/old/suse/salt-api.service %{buildroot}%{_unitdir}/salt-api.service +install -Dpm 0644 pkg/common/salt-proxy@.service %{buildroot}%{_unitdir}/salt-proxy@.service ln -s service %{buildroot}%{_sbindir}/rcsalt-master ln -s service %{buildroot}%{_sbindir}/rcsalt-syndic ln -s service %{buildroot}%{_sbindir}/rcsalt-minion @@ -866,10 +826,10 @@ install -Dpm 644 %{S:2} %{buildroot}/usr/lib/tmpfiles.d/salt.c %else mkdir -p %{buildroot}%{_initddir} ## install init scripts -install -Dpm 0755 pkg/suse/salt-master %{buildroot}%{_initddir}/salt-master -install -Dpm 0755 pkg/suse/salt-syndic %{buildroot}%{_initddir}/salt-syndic -install -Dpm 0755 pkg/suse/salt-minion %{buildroot}%{_initddir}/salt-minion -install -Dpm 0755 pkg/suse/salt-api %{buildroot}%{_initddir}/salt-api +install -Dpm 0755 pkg/old/suse/salt-master %{buildroot}%{_initddir}/salt-master +install -Dpm 0755 pkg/old/suse/salt-syndic %{buildroot}%{_initddir}/salt-syndic +install -Dpm 0755 pkg/old/suse/salt-minion %{buildroot}%{_initddir}/salt-minion +install -Dpm 0755 pkg/old/suse/salt-api %{buildroot}%{_initddir}/salt-api ln -sf %{_initddir}/salt-master %{buildroot}%{_sbindir}/rcsalt-master ln -sf %{_initddir}/salt-syndic %{buildroot}%{_sbindir}/rcsalt-syndic ln -sf %{_initddir}/salt-minion %{buildroot}%{_sbindir}/rcsalt-minion @@ -894,27 +854,27 @@ install -Dpm 0640 transactional_update.conf %{buildroot}%{_sysconfdir}/salt/mini # ## install logrotate file (for RHEL6 we use without sudo) %if 0%{?rhel} > 6 || 0%{?suse_version} -install -Dpm 0644 pkg/suse/salt-common.logrotate %{buildroot}%{_sysconfdir}/logrotate.d/salt +install -Dpm 0644 pkg/old/suse/salt-common.logrotate %{buildroot}%{_sysconfdir}/logrotate.d/salt %else -install -Dpm 0644 pkg/salt-common.logrotate %{buildroot}%{_sysconfdir}/logrotate.d/salt +install -Dpm 0644 pkg/common/salt-common.logrotate %{buildroot}%{_sysconfdir}/logrotate.d/salt %endif # %if 0%{?suse_version} <= 1500 ## install SuSEfirewall2 rules -install -Dpm 0644 pkg/suse/salt.SuSEfirewall2 %{buildroot}%{_sysconfdir}/sysconfig/SuSEfirewall2.d/services/salt +install -Dpm 0644 pkg/old/suse/salt.SuSEfirewall2 %{buildroot}%{_sysconfdir}/sysconfig/SuSEfirewall2.d/services/salt %endif # ## install completion scripts %if %{with bash_completion} -install -Dpm 0644 pkg/salt.bash %{buildroot}%{_sysconfdir}/bash_completion.d/salt +install -Dpm 0644 pkg/common/salt.bash %{buildroot}%{_sysconfdir}/bash_completion.d/salt %endif %if %{with zsh_completion} -install -Dpm 0644 pkg/salt.zsh %{buildroot}%{_sysconfdir}/zsh_completion.d/salt +install -Dpm 0644 pkg/common/salt.zsh %{buildroot}%{_sysconfdir}/zsh_completion.d/salt %endif %if %{with fish_completion} mkdir -p %{buildroot}%{fish_completions_dir} -install -Dpm 0644 pkg/fish-completions/* %{buildroot}%{fish_completions_dir} +install -Dpm 0644 pkg/common/fish-completions/* %{buildroot}%{fish_completions_dir} %endif # Standalone Salt formulas configuration diff --git a/save-log-to-logfile-with-docker.build.patch b/save-log-to-logfile-with-docker.build.patch index 41fd9d8..d94bb4c 100644 --- a/save-log-to-logfile-with-docker.build.patch +++ b/save-log-to-logfile-with-docker.build.patch @@ -1,4 +1,4 @@ -From af5eb3f436fa405b76851c6ba0d491559b020974 Mon Sep 17 00:00:00 2001 +From 88adb2f59137213119f1da2b6dbf6fce859fc12f Mon Sep 17 00:00:00 2001 From: Vladimir Nadvornik Date: Mon, 27 Jun 2022 17:00:58 +0200 Subject: [PATCH] Save log to logfile with docker.build @@ -8,10 +8,10 @@ Subject: [PATCH] Save log to logfile with docker.build 1 file changed, 18 insertions(+) diff --git a/salt/modules/dockermod.py b/salt/modules/dockermod.py -index ab5c2ac609..461c89431f 100644 +index 8b6ab8058e..f7344b66ac 100644 --- a/salt/modules/dockermod.py +++ b/salt/modules/dockermod.py -@@ -4001,6 +4001,7 @@ def build( +@@ -4006,6 +4006,7 @@ def build( fileobj=None, dockerfile=None, buildargs=None, @@ -19,7 +19,7 @@ index ab5c2ac609..461c89431f 100644 ): """ .. versionchanged:: 2018.3.0 -@@ -4054,6 +4055,9 @@ def build( +@@ -4059,6 +4060,9 @@ def build( buildargs A dictionary of build arguments provided to the docker build process. @@ -29,7 +29,7 @@ index ab5c2ac609..461c89431f 100644 **RETURN DATA** -@@ -4128,6 +4132,20 @@ def build( +@@ -4133,6 +4137,20 @@ def build( stream_data = [] for line in response: stream_data.extend(salt.utils.json.loads(line, cls=DockerJSONDecoder)) @@ -51,6 +51,6 @@ index ab5c2ac609..461c89431f 100644 # Iterate through API response and collect information for item in stream_data: -- -2.37.3 +2.39.2 diff --git a/set-default-target-for-pip-from-venv_pip_target-envi.patch b/set-default-target-for-pip-from-venv_pip_target-envi.patch deleted file mode 100644 index c3a6934..0000000 --- a/set-default-target-for-pip-from-venv_pip_target-envi.patch +++ /dev/null @@ -1,87 +0,0 @@ -From d561491c48ee30472e0d4699ba389648ef0d863a Mon Sep 17 00:00:00 2001 -From: Victor Zhestkov -Date: Mon, 27 Jun 2022 18:02:31 +0300 -Subject: [PATCH] Set default target for pip from VENV_PIP_TARGET - environment variable - -* Use VENV_PIP_TARGET as a target for pkg.install - -if set and no target specified on the call - -* Add test for VENV_PIP_TARGET environment variable - -* Changelog entry ---- - changelog/62089.changed | 1 + - salt/modules/pip.py | 6 +++++ - tests/pytests/unit/modules/test_pip.py | 31 ++++++++++++++++++++++++++ - 3 files changed, 38 insertions(+) - create mode 100644 changelog/62089.changed - -diff --git a/changelog/62089.changed b/changelog/62089.changed -new file mode 100644 -index 0000000000..09feb2e922 ---- /dev/null -+++ b/changelog/62089.changed -@@ -0,0 +1 @@ -+Use VENV_PIP_TARGET environment variable as a default target for pip if present. -diff --git a/salt/modules/pip.py b/salt/modules/pip.py -index da26416662..9410024fd5 100644 ---- a/salt/modules/pip.py -+++ b/salt/modules/pip.py -@@ -858,6 +858,12 @@ def install( - if build: - cmd.extend(["--build", build]) - -+ # Use VENV_PIP_TARGET environment variable value as target -+ # if set and no target specified on the function call -+ target_env = os.environ.get("VENV_PIP_TARGET", None) -+ if target is None and target_env is not None: -+ target = target_env -+ - if target: - cmd.extend(["--target", target]) - -diff --git a/tests/pytests/unit/modules/test_pip.py b/tests/pytests/unit/modules/test_pip.py -index 405ec6c82e..ae9005d806 100644 ---- a/tests/pytests/unit/modules/test_pip.py -+++ b/tests/pytests/unit/modules/test_pip.py -@@ -1773,3 +1773,34 @@ def test_when_version_is_called_with_a_user_it_should_be_passed_to_undelying_run - cwd=None, - python_shell=False, - ) -+ -+ -+def test_install_target_from_VENV_PIP_TARGET_in_resulting_command(): -+ pkg = "pep8" -+ target = "/tmp/foo" -+ target_env = "/tmp/bar" -+ mock = MagicMock(return_value={"retcode": 0, "stdout": ""}) -+ environment = os.environ.copy() -+ environment["VENV_PIP_TARGET"] = target_env -+ with patch.dict(pip.__salt__, {"cmd.run_all": mock}), patch.object( -+ os, "environ", environment -+ ): -+ pip.install(pkg) -+ expected = [sys.executable, "-m", "pip", "install", "--target", target_env, pkg] -+ mock.assert_called_with( -+ expected, -+ saltenv="base", -+ runas=None, -+ use_vt=False, -+ python_shell=False, -+ ) -+ mock.reset_mock() -+ pip.install(pkg, target=target) -+ expected = [sys.executable, "-m", "pip", "install", "--target", target, pkg] -+ mock.assert_called_with( -+ expected, -+ saltenv="base", -+ runas=None, -+ use_vt=False, -+ python_shell=False, -+ ) --- -2.37.3 - - diff --git a/skip-package-names-without-colon-bsc-1208691-578.patch b/skip-package-names-without-colon-bsc-1208691-578.patch index ab6ed8d..d1fc699 100644 --- a/skip-package-names-without-colon-bsc-1208691-578.patch +++ b/skip-package-names-without-colon-bsc-1208691-578.patch @@ -1,4 +1,4 @@ -From 6d122245f15a206dbfa92703b954d535c5c34dd4 Mon Sep 17 00:00:00 2001 +From c61da0bef8d4d8394592db2f9995cdf4820c02af Mon Sep 17 00:00:00 2001 From: Alexander Graul Date: Mon, 27 Feb 2023 11:35:41 +0100 Subject: [PATCH] Skip package names without colon (bsc#1208691) (#578) @@ -9,10 +9,10 @@ Fixes a problem in `_find_ptf_packages()` when passing multiple packages to `zyp 1 file changed, 2 insertions(+) diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py -index cd057ec637..64373e59fb 100644 +index 44f2cdbd3a..cdec397d69 100644 --- a/salt/modules/zypperpkg.py +++ b/salt/modules/zypperpkg.py -@@ -2758,6 +2758,8 @@ def _find_ptf_packages(pkgs, root=None): +@@ -2688,6 +2688,8 @@ def _find_ptf_packages(pkgs, root=None): for line in output.splitlines(): if not line.strip(): continue @@ -24,3 +24,4 @@ index cd057ec637..64373e59fb 100644 -- 2.39.2 + diff --git a/state.apply-don-t-check-for-cached-pillar-errors.patch b/state.apply-don-t-check-for-cached-pillar-errors.patch deleted file mode 100644 index a724ea5..0000000 --- a/state.apply-don-t-check-for-cached-pillar-errors.patch +++ /dev/null @@ -1,362 +0,0 @@ -From cba6455bd0480bfb80c466a2b34a702a9afb5bd5 Mon Sep 17 00:00:00 2001 -From: Alexander Graul -Date: Tue, 25 Jan 2022 17:20:55 +0100 -Subject: [PATCH] state.apply: don't check for cached pillar errors - -state.apply request new pillar data from the server. This done to always -have the most up-to-date pillar to work with. Previously, checking for -pillar errors looked at both the new pillar and the in-memory pillar. -The latter might contain pillar rendering errors even if the former does -not. - -For this reason, only the new pillar should be checked, not both. ---- - changelog/52354.fixed | 1 + - changelog/57180.fixed | 1 + - changelog/59339.fixed | 1 + - salt/modules/state.py | 17 ++- - .../modules/state/test_state_pillar_errors.py | 131 ++++++++++++++++++ - .../pytests/unit/modules/state/test_state.py | 115 +++++---------- - 6 files changed, 177 insertions(+), 89 deletions(-) - create mode 100644 changelog/52354.fixed - create mode 100644 changelog/57180.fixed - create mode 100644 changelog/59339.fixed - create mode 100644 tests/pytests/integration/modules/state/test_state_pillar_errors.py - -diff --git a/changelog/52354.fixed b/changelog/52354.fixed -new file mode 100644 -index 0000000000..af885d77fa ---- /dev/null -+++ b/changelog/52354.fixed -@@ -0,0 +1 @@ -+Don't check for cached pillar errors on state.apply -diff --git a/changelog/57180.fixed b/changelog/57180.fixed -new file mode 100644 -index 0000000000..af885d77fa ---- /dev/null -+++ b/changelog/57180.fixed -@@ -0,0 +1 @@ -+Don't check for cached pillar errors on state.apply -diff --git a/changelog/59339.fixed b/changelog/59339.fixed -new file mode 100644 -index 0000000000..af885d77fa ---- /dev/null -+++ b/changelog/59339.fixed -@@ -0,0 +1 @@ -+Don't check for cached pillar errors on state.apply -diff --git a/salt/modules/state.py b/salt/modules/state.py -index f214291328..c0feabe842 100644 ---- a/salt/modules/state.py -+++ b/salt/modules/state.py -@@ -106,18 +106,17 @@ def _set_retcode(ret, highstate=None): - - def _get_pillar_errors(kwargs, pillar=None): - """ -- Checks all pillars (external and internal) for errors. -- Return an error message, if anywhere or None. -+ Check pillar for errors. -+ -+ If a pillar is passed, it will be checked. Otherwise, the in-memory pillar -+ will checked instead. Passing kwargs['force'] = True short cuts the check -+ and always returns None, indicating no errors. - - :param kwargs: dictionary of options -- :param pillar: external pillar -- :return: None or an error message -+ :param pillar: pillar -+ :return: None or a list of error messages - """ -- return ( -- None -- if kwargs.get("force") -- else (pillar or {}).get("_errors", __pillar__.get("_errors")) or None -- ) -+ return None if kwargs.get("force") else (pillar or __pillar__).get("_errors") - - - def _wait(jid): -diff --git a/tests/pytests/integration/modules/state/test_state_pillar_errors.py b/tests/pytests/integration/modules/state/test_state_pillar_errors.py -new file mode 100644 -index 0000000000..af65a05945 ---- /dev/null -+++ b/tests/pytests/integration/modules/state/test_state_pillar_errors.py -@@ -0,0 +1,131 @@ -+#!/usr/bin/python3 -+ -+import textwrap -+ -+import pytest -+from saltfactories.utils.functional import StateResult -+ -+pytestmark = [ -+ pytest.mark.slow_test, -+] -+ -+ -+@pytest.fixture(scope="module") -+def reset_pillar(salt_call_cli): -+ try: -+ # Run tests -+ yield -+ finally: -+ # Refresh pillar once all tests are done. -+ ret = salt_call_cli.run("saltutil.refresh_pillar", wait=True) -+ assert ret.exitcode == 0 -+ assert ret.json is True -+ -+ -+@pytest.fixture -+def testfile_path(tmp_path, base_env_state_tree_root_dir): -+ testfile = tmp_path / "testfile" -+ sls_contents = textwrap.dedent( -+ """ -+ {}: -+ file: -+ - managed -+ - source: salt://testfile -+ - makedirs: true -+ """.format(testfile) -+ ) -+ with pytest.helpers.temp_file( -+ "sls-id-test.sls", sls_contents, base_env_state_tree_root_dir -+ ): -+ yield testfile -+ -+ -+@pytest.mark.usefixtures("testfile_path", "reset_pillar") -+def test_state_apply_aborts_on_pillar_error( -+ salt_cli, -+ salt_minion, -+ base_env_pillar_tree_root_dir, -+): -+ """ -+ Test state.apply with error in pillar. -+ """ -+ pillar_top_file = textwrap.dedent( -+ """ -+ base: -+ '{}': -+ - basic -+ """ -+ ).format(salt_minion.id) -+ basic_pillar_file = textwrap.dedent( -+ """ -+ syntax_error -+ """ -+ ) -+ -+ with pytest.helpers.temp_file( -+ "top.sls", pillar_top_file, base_env_pillar_tree_root_dir -+ ), pytest.helpers.temp_file( -+ "basic.sls", basic_pillar_file, base_env_pillar_tree_root_dir -+ ): -+ expected_comment = [ -+ "Pillar failed to render with the following messages:", -+ "SLS 'basic' does not render to a dictionary", -+ ] -+ shell_result = salt_cli.run( -+ "state.apply", "sls-id-test", minion_tgt=salt_minion.id -+ ) -+ assert shell_result.exitcode == 1 -+ assert shell_result.json == expected_comment -+ -+ -+@pytest.mark.usefixtures("testfile_path", "reset_pillar") -+def test_state_apply_continues_after_pillar_error_is_fixed( -+ salt_cli, -+ salt_minion, -+ base_env_pillar_tree_root_dir, -+): -+ """ -+ Test state.apply with error in pillar. -+ """ -+ pillar_top_file = textwrap.dedent( -+ """ -+ base: -+ '{}': -+ - basic -+ """.format(salt_minion.id) -+ ) -+ basic_pillar_file_error = textwrap.dedent( -+ """ -+ syntax_error -+ """ -+ ) -+ basic_pillar_file = textwrap.dedent( -+ """ -+ syntax_error: Fixed! -+ """ -+ ) -+ -+ # save pillar render error in minion's in-memory pillar -+ with pytest.helpers.temp_file( -+ "top.sls", pillar_top_file, base_env_pillar_tree_root_dir -+ ), pytest.helpers.temp_file( -+ "basic.sls", basic_pillar_file_error, base_env_pillar_tree_root_dir -+ ): -+ shell_result = salt_cli.run( -+ "saltutil.refresh_pillar", minion_tgt=salt_minion.id -+ ) -+ assert shell_result.exitcode == 0 -+ -+ # run state.apply with fixed pillar render error -+ with pytest.helpers.temp_file( -+ "top.sls", pillar_top_file, base_env_pillar_tree_root_dir -+ ), pytest.helpers.temp_file( -+ "basic.sls", basic_pillar_file, base_env_pillar_tree_root_dir -+ ): -+ shell_result = salt_cli.run( -+ "state.apply", "sls-id-test", minion_tgt=salt_minion.id -+ ) -+ assert shell_result.exitcode == 0 -+ state_result = StateResult(shell_result.json) -+ assert state_result.result is True -+ assert state_result.changes == {"diff": "New file", "mode": "0644"} -diff --git a/tests/pytests/unit/modules/state/test_state.py b/tests/pytests/unit/modules/state/test_state.py -index 02fd2dd307..30cda303cc 100644 ---- a/tests/pytests/unit/modules/state/test_state.py -+++ b/tests/pytests/unit/modules/state/test_state.py -@@ -1,14 +1,16 @@ - """ - :codeauthor: Rahul Handay - """ -- - import datetime - import logging - import os -+from collections import namedtuple - - import pytest -+ - import salt.config - import salt.loader -+import salt.loader.context - import salt.modules.config as config - import salt.modules.state as state - import salt.state -@@ -1200,85 +1202,6 @@ def test_lock_saltenv(): - ) - - --def test_get_pillar_errors_CC(): -- """ -- Test _get_pillar_errors function. -- CC: External clean, Internal clean -- :return: -- """ -- for int_pillar, ext_pillar in [ -- ({"foo": "bar"}, {"fred": "baz"}), -- ({"foo": "bar"}, None), -- ({}, {"fred": "baz"}), -- ]: -- with patch("salt.modules.state.__pillar__", int_pillar): -- for opts, res in [ -- ({"force": True}, None), -- ({"force": False}, None), -- ({}, None), -- ]: -- assert res == state._get_pillar_errors(kwargs=opts, pillar=ext_pillar) -- -- --def test_get_pillar_errors_EC(): -- """ -- Test _get_pillar_errors function. -- EC: External erroneous, Internal clean -- :return: -- """ -- errors = ["failure", "everywhere"] -- for int_pillar, ext_pillar in [ -- ({"foo": "bar"}, {"fred": "baz", "_errors": errors}), -- ({}, {"fred": "baz", "_errors": errors}), -- ]: -- with patch("salt.modules.state.__pillar__", int_pillar): -- for opts, res in [ -- ({"force": True}, None), -- ({"force": False}, errors), -- ({}, errors), -- ]: -- assert res == state._get_pillar_errors(kwargs=opts, pillar=ext_pillar) -- -- --def test_get_pillar_errors_EE(): -- """ -- Test _get_pillar_errors function. -- CC: External erroneous, Internal erroneous -- :return: -- """ -- errors = ["failure", "everywhere"] -- for int_pillar, ext_pillar in [ -- ({"foo": "bar", "_errors": errors}, {"fred": "baz", "_errors": errors}) -- ]: -- with patch("salt.modules.state.__pillar__", int_pillar): -- for opts, res in [ -- ({"force": True}, None), -- ({"force": False}, errors), -- ({}, errors), -- ]: -- assert res == state._get_pillar_errors(kwargs=opts, pillar=ext_pillar) -- -- --def test_get_pillar_errors_CE(): -- """ -- Test _get_pillar_errors function. -- CC: External clean, Internal erroneous -- :return: -- """ -- errors = ["failure", "everywhere"] -- for int_pillar, ext_pillar in [ -- ({"foo": "bar", "_errors": errors}, {"fred": "baz"}), -- ({"foo": "bar", "_errors": errors}, None), -- ]: -- with patch("salt.modules.state.__pillar__", int_pillar): -- for opts, res in [ -- ({"force": True}, None), -- ({"force": False}, errors), -- ({}, errors), -- ]: -- assert res == state._get_pillar_errors(kwargs=opts, pillar=ext_pillar) -- -- - def test_event(): - """ - test state.event runner -@@ -1318,3 +1241,35 @@ def test_event(): - if _expected in x.args[0]: - found = True - assert found is True -+ -+ -+PillarPair = namedtuple("PillarPair", ["in_memory", "fresh"]) -+pillar_combinations = [ -+ (PillarPair({"foo": "bar"}, {"fred": "baz"}), None), -+ (PillarPair({"foo": "bar"}, {"fred": "baz", "_errors": ["Failure"]}), ["Failure"]), -+ (PillarPair({"foo": "bar"}, None), None), -+ (PillarPair({"foo": "bar", "_errors": ["Failure"]}, None), ["Failure"]), -+ (PillarPair({"foo": "bar", "_errors": ["Failure"]}, {"fred": "baz"}), None), -+] -+ -+ -+@pytest.mark.parametrize("pillar,expected_errors", pillar_combinations) -+def test_get_pillar_errors(pillar: PillarPair, expected_errors): -+ """ -+ test _get_pillar_errors function -+ -+ There are three cases to consider: -+ 1. kwargs['force'] is True -> None, no matter what's in pillar/__pillar__ -+ 2. pillar kwarg is available -> only check pillar, no matter what's in __pillar__ -+ 3. pillar kwarg is not available -> check __pillar__ -+ """ -+ ctx = salt.loader.context.LoaderContext() -+ named_ctx = ctx.named_context("__pillar__", pillar.in_memory) -+ with patch("salt.modules.state.__pillar__", named_ctx, create=True): -+ assert ( -+ state._get_pillar_errors(kwargs={"force": True}, pillar=pillar.fresh) -+ is None -+ ) -+ assert ( -+ state._get_pillar_errors(kwargs={}, pillar=pillar.fresh) == expected_errors -+ ) --- -2.37.3 - - diff --git a/state.orchestrate_single-does-not-pass-pillar-none-4.patch b/state.orchestrate_single-does-not-pass-pillar-none-4.patch deleted file mode 100644 index 511ee81..0000000 --- a/state.orchestrate_single-does-not-pass-pillar-none-4.patch +++ /dev/null @@ -1,105 +0,0 @@ -From 634e82874b17c38bd4d27c0c07a53c9e39e49968 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?= - -Date: Wed, 9 Feb 2022 09:01:08 +0000 -Subject: [PATCH] state.orchestrate_single does not pass pillar=None - (#488) - -Passing a pillar to state.single can results in state functions not -working when they don't accept a pillar keyword argument. One example -where this is the case is salt.wait_for_event. When no pillar is -provided, it does not need to be passed. - -Co-authored-by: Alexander Graul ---- - changelog/61092.fixed | 3 ++ - salt/runners/state.py | 10 ++++-- - tests/pytests/unit/runners/test_state.py | 41 ++++++++++++++++++++++++ - 3 files changed, 51 insertions(+), 3 deletions(-) - create mode 100644 changelog/61092.fixed - create mode 100644 tests/pytests/unit/runners/test_state.py - -diff --git a/changelog/61092.fixed b/changelog/61092.fixed -new file mode 100644 -index 0000000000..6ca66839c9 ---- /dev/null -+++ b/changelog/61092.fixed -@@ -0,0 +1,3 @@ -+state.orchestrate_single only passes a pillar if it is set to the state -+function. This allows it to be used with state functions that don't accept a -+pillar keyword argument. -diff --git a/salt/runners/state.py b/salt/runners/state.py -index f8fc1b0944..5642204ce9 100644 ---- a/salt/runners/state.py -+++ b/salt/runners/state.py -@@ -150,12 +150,16 @@ def orchestrate_single(fun, name, test=None, queue=False, pillar=None, **kwargs) - - salt-run state.orchestrate_single fun=salt.wheel name=key.list_all - """ -- if pillar is not None and not isinstance(pillar, dict): -- raise SaltInvocationError("Pillar data must be formatted as a dictionary") -+ if pillar is not None: -+ if isinstance(pillar, dict): -+ kwargs["pillar"] = pillar -+ else: -+ raise SaltInvocationError("Pillar data must be formatted as a dictionary") -+ - __opts__["file_client"] = "local" - minion = salt.minion.MasterMinion(__opts__) - running = minion.functions["state.single"]( -- fun, name, test=None, queue=False, pillar=pillar, **kwargs -+ fun, name, test=None, queue=False, **kwargs - ) - ret = {minion.opts["id"]: running} - __jid_event__.fire_event({"data": ret, "outputter": "highstate"}, "progress") -diff --git a/tests/pytests/unit/runners/test_state.py b/tests/pytests/unit/runners/test_state.py -new file mode 100644 -index 0000000000..df0a718a41 ---- /dev/null -+++ b/tests/pytests/unit/runners/test_state.py -@@ -0,0 +1,41 @@ -+#!/usr/bin/python3 -+ -+import pytest -+from salt.runners import state as state_runner -+from tests.support.mock import Mock, patch -+ -+ -+@pytest.fixture -+def configure_loader_modules(): -+ return {state_runner: {"__opts__": {}, "__jid_event__": Mock()}} -+ -+ -+def test_orchestrate_single_passes_pillar(): -+ """ -+ test state.orchestrate_single passes given pillar to state.single -+ """ -+ mock_master_minion = Mock() -+ mock_state_single = Mock() -+ mock_master_minion.functions = {"state.single": mock_state_single} -+ mock_master_minion.opts = {"id": "dummy"} -+ test_pillar = {"test_entry": "exists"} -+ with patch("salt.minion.MasterMinion", Mock(return_value=mock_master_minion)): -+ state_runner.orchestrate_single( -+ fun="pillar.get", name="test_entry", pillar=test_pillar -+ ) -+ assert mock_state_single.call_args.kwargs["pillar"] == test_pillar -+ -+ -+def test_orchestrate_single_does_not_pass_none_pillar(): -+ """ -+ test state.orchestrate_single does not pass pillar=None to state.single -+ """ -+ mock_master_minion = Mock() -+ mock_state_single = Mock() -+ mock_master_minion.functions = {"state.single": mock_state_single} -+ mock_master_minion.opts = {"id": "dummy"} -+ with patch("salt.minion.MasterMinion", Mock(return_value=mock_master_minion)): -+ state_runner.orchestrate_single( -+ fun="pillar.get", name="test_entry", pillar=None -+ ) -+ assert "pillar" not in mock_state_single.call_args.kwargs --- -2.37.3 - - diff --git a/switch-firewalld-state-to-use-change_interface.patch b/switch-firewalld-state-to-use-change_interface.patch index d76ff18..95d55bc 100644 --- a/switch-firewalld-state-to-use-change_interface.patch +++ b/switch-firewalld-state-to-use-change_interface.patch @@ -1,4 +1,4 @@ -From 995f67741e591b60fcecff87d4d97099ca82bafc Mon Sep 17 00:00:00 2001 +From 57626d8eb77d2c559365d1df974100e474671fef Mon Sep 17 00:00:00 2001 From: Alexander Graul Date: Tue, 18 Jan 2022 17:12:04 +0100 Subject: [PATCH] Switch firewalld state to use change_interface @@ -67,6 +67,6 @@ index cc6eaba5c3..534b9dd62d 100644 ret["comment"] = "Error: {}".format(err) return ret -- -2.37.3 +2.39.2 diff --git a/temporary-fix-extend-the-whitelist-of-allowed-comman.patch b/temporary-fix-extend-the-whitelist-of-allowed-comman.patch index f817e6b..a91c728 100644 --- a/temporary-fix-extend-the-whitelist-of-allowed-comman.patch +++ b/temporary-fix-extend-the-whitelist-of-allowed-comman.patch @@ -1,4 +1,4 @@ -From e4374250234ab74bce0ef86d95cb30e873f0af3c Mon Sep 17 00:00:00 2001 +From 2575e64ee21f774a1efb6960972e9d476a8d5927 Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Thu, 24 Jan 2019 18:12:35 +0100 Subject: [PATCH] temporary fix: extend the whitelist of allowed commands @@ -8,7 +8,7 @@ Subject: [PATCH] temporary fix: extend the whitelist of allowed commands 1 file changed, 3 insertions(+) diff --git a/salt/auth/__init__.py b/salt/auth/__init__.py -index afd7ad65fa..0c64755235 100644 +index b87e2aff0d..331baab211 100644 --- a/salt/auth/__init__.py +++ b/salt/auth/__init__.py @@ -12,6 +12,7 @@ so that any external authentication system can be used inside of Salt @@ -29,6 +29,6 @@ index afd7ad65fa..0c64755235 100644 "print_event", "raw", -- -2.37.3 +2.39.2 diff --git a/update-target-fix-for-salt-ssh-to-process-targets-li.patch b/update-target-fix-for-salt-ssh-to-process-targets-li.patch index aa57dd8..0dfd119 100644 --- a/update-target-fix-for-salt-ssh-to-process-targets-li.patch +++ b/update-target-fix-for-salt-ssh-to-process-targets-li.patch @@ -1,4 +1,4 @@ -From 9e527322ee0f5c7e1f9b7c16f14be9c349cf8e55 Mon Sep 17 00:00:00 2001 +From b6bf7e1cb3efedbb651b7d6c5f36b73d88cfa1c0 Mon Sep 17 00:00:00 2001 From: Victor Zhestkov <35733135+vzhestkov@users.noreply.github.com> Date: Fri, 9 Apr 2021 16:01:32 +0300 Subject: [PATCH] Update target fix for salt-ssh to process targets list @@ -14,7 +14,7 @@ Regression fix of salt-ssh on processing targets (#353) 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/salt/client/ssh/__init__.py b/salt/client/ssh/__init__.py -index ef162d2270..ad2796bc87 100644 +index 049baff51a..19089ce8ad 100644 --- a/salt/client/ssh/__init__.py +++ b/salt/client/ssh/__init__.py @@ -338,7 +338,7 @@ class SSH(MultiprocessingStateMixin): @@ -93,6 +93,6 @@ index ef162d2270..ad2796bc87 100644 def get_pubkey(self): """ -- -2.37.3 +2.39.2 diff --git a/use-adler32-algorithm-to-compute-string-checksums.patch b/use-adler32-algorithm-to-compute-string-checksums.patch index a0e57a5..cb5ae44 100644 --- a/use-adler32-algorithm-to-compute-string-checksums.patch +++ b/use-adler32-algorithm-to-compute-string-checksums.patch @@ -1,4 +1,4 @@ -From a2f8b54cd56eb83552eccf87afd9b67f6a4a6f4c Mon Sep 17 00:00:00 2001 +From ef6da7d43fcf51a7d705422624c1e7a94b1297f2 Mon Sep 17 00:00:00 2001 From: Alexander Graul Date: Tue, 18 Jan 2022 16:36:57 +0100 Subject: [PATCH] Use Adler32 algorithm to compute string checksums @@ -24,21 +24,21 @@ Remove deprecated warning that breaks miniion execution when "server_id_use_crc" 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/salt/config/__init__.py b/salt/config/__init__.py -index a37f7eebcc..7cdee12c4d 100644 +index 1632663474..43182f3f92 100644 --- a/salt/config/__init__.py +++ b/salt/config/__init__.py -@@ -964,6 +964,9 @@ VALID_OPTS = immutabletypes.freeze( - # The port to be used when checking if a master is connected to a - # minion - "remote_minions_port": int, +@@ -991,6 +991,9 @@ VALID_OPTS = immutabletypes.freeze( + "maintenance_interval": int, + # Fileserver process restart interval + "fileserver_interval": int, + # Use Adler32 hashing algorithm for server_id (default False until Sodium, "adler32" after) + # Possible values are: False, adler32, crc32 + "server_id_use_crc": (bool, str), } ) -@@ -1267,6 +1270,7 @@ DEFAULT_MINION_OPTS = immutabletypes.freeze( - "disabled_requisites": [], +@@ -1296,6 +1299,7 @@ DEFAULT_MINION_OPTS = immutabletypes.freeze( + "global_state_conditions": None, "reactor_niceness": None, "fips_mode": False, + "server_id_use_crc": False, @@ -46,7 +46,7 @@ index a37f7eebcc..7cdee12c4d 100644 ) diff --git a/salt/grains/core.py b/salt/grains/core.py -index b55ab4e472..23d8b8ea42 100644 +index 1199ad274f..5c12556346 100644 --- a/salt/grains/core.py +++ b/salt/grains/core.py @@ -21,6 +21,7 @@ import subprocess @@ -56,8 +56,8 @@ index b55ab4e472..23d8b8ea42 100644 +import zlib from errno import EACCES, EPERM - import distro -@@ -3015,6 +3016,36 @@ def _hw_data(osdata): + import salt.exceptions +@@ -3382,6 +3383,36 @@ def _hw_data(osdata): return grains @@ -94,14 +94,14 @@ index b55ab4e472..23d8b8ea42 100644 def get_server_id(): """ Provides an integer based on the FQDN of a machine. -@@ -3025,10 +3056,19 @@ def get_server_id(): +@@ -3392,10 +3423,19 @@ def get_server_id(): # server_id if salt.utils.platform.is_proxy(): - return {} - id_ = __opts__.get("id", "") - hash_ = int(hashlib.sha256(id_.encode()).hexdigest(), 16) -- return {"server_id": abs(hash_ % (2 ** 31))} +- return {"server_id": abs(hash_ % (2**31))} + server_id = {} + else: + use_crc = __opts__.get("server_id_use_crc") @@ -119,6 +119,6 @@ index b55ab4e472..23d8b8ea42 100644 def get_master(): -- -2.37.3 +2.39.2 diff --git a/use-rlock-to-avoid-deadlocks-in-salt-ssh.patch b/use-rlock-to-avoid-deadlocks-in-salt-ssh.patch index fe104ae..1b9df2c 100644 --- a/use-rlock-to-avoid-deadlocks-in-salt-ssh.patch +++ b/use-rlock-to-avoid-deadlocks-in-salt-ssh.patch @@ -1,4 +1,4 @@ -From c6be36eeea49ee0d0641da272087305f79c32c99 Mon Sep 17 00:00:00 2001 +From 578932e56be4b4151aa33bd25997c916b0e00a04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?= Date: Wed, 4 Jan 2023 13:11:50 +0000 @@ -22,6 +22,6 @@ index bbe4269839..b41cc64b8e 100644 def LazyLoader(*args, **kwargs): -- -2.37.3 +2.39.2 diff --git a/use-salt-bundle-in-dockermod.patch b/use-salt-bundle-in-dockermod.patch index a5547e2..15909b0 100644 --- a/use-salt-bundle-in-dockermod.patch +++ b/use-salt-bundle-in-dockermod.patch @@ -1,4 +1,4 @@ -From cd03f33b3ba1ebf267825d29b68d4e88e6a0021a Mon Sep 17 00:00:00 2001 +From b0891f83afa354c4b1f803af8a679ecf5a7fb63c Mon Sep 17 00:00:00 2001 From: Victor Zhestkov Date: Mon, 27 Jun 2022 17:59:24 +0300 Subject: [PATCH] Use Salt Bundle in dockermod @@ -12,7 +12,7 @@ Subject: [PATCH] Use Salt Bundle in dockermod 2 files changed, 241 insertions(+), 34 deletions(-) diff --git a/salt/modules/dockermod.py b/salt/modules/dockermod.py -index d8581586ca..ab5c2ac609 100644 +index 6870c26b0e..8b6ab8058e 100644 --- a/salt/modules/dockermod.py +++ b/salt/modules/dockermod.py @@ -201,14 +201,19 @@ import copy @@ -35,7 +35,7 @@ index d8581586ca..ab5c2ac609 100644 import time import uuid -@@ -6693,6 +6698,111 @@ def _compile_state(sls_opts, mods=None): +@@ -6698,6 +6703,111 @@ def _compile_state(sls_opts, mods=None): return st_.state.compile_high_data(high_data) @@ -147,7 +147,7 @@ index d8581586ca..ab5c2ac609 100644 def call(name, function, *args, **kwargs): """ Executes a Salt function inside a running container -@@ -6728,47 +6838,68 @@ def call(name, function, *args, **kwargs): +@@ -6733,47 +6843,68 @@ def call(name, function, *args, **kwargs): if function is None: raise CommandExecutionError("Missing function parameter") @@ -250,7 +250,7 @@ index d8581586ca..ab5c2ac609 100644 "--local", "--log-file", diff --git a/tests/pytests/unit/modules/dockermod/test_module.py b/tests/pytests/unit/modules/dockermod/test_module.py -index 47fe5d55e6..19c7f450d7 100644 +index 8fb7806497..1ac7dff52a 100644 --- a/tests/pytests/unit/modules/dockermod/test_module.py +++ b/tests/pytests/unit/modules/dockermod/test_module.py @@ -3,6 +3,7 @@ Unit tests for the docker module @@ -260,8 +260,8 @@ index 47fe5d55e6..19c7f450d7 100644 +import sys import pytest - import salt.config -@@ -26,6 +27,7 @@ def configure_loader_modules(): + +@@ -26,6 +27,7 @@ def configure_loader_modules(minion_opts): whitelist=[ "args", "docker", @@ -370,6 +370,6 @@ index 47fe5d55e6..19c7f450d7 100644 + + assert {"retcode": 0, "comment": "container cmd"} == ret -- -2.37.3 +2.39.2 diff --git a/v3005.1.tar.gz b/v3005.1.tar.gz deleted file mode 100644 index 3242028..0000000 --- a/v3005.1.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:344032370bda5edd6242732587111b0a2fee378fcda2d9a1cfff7e191f9ac89e -size 18016427 diff --git a/v3006.0.tar.gz b/v3006.0.tar.gz new file mode 100644 index 0000000..067fac0 --- /dev/null +++ b/v3006.0.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:09703cff7142ae5e86c958ccff342e7800df7465031f95accdbfc4274059e4d1 +size 20816042 diff --git a/x509-fixes-111.patch b/x509-fixes-111.patch index 0a6a0c9..7e4c2e8 100644 --- a/x509-fixes-111.patch +++ b/x509-fixes-111.patch @@ -1,4 +1,4 @@ -From 1b78ceabaf3885e7d90d13a041685e7dda960ac9 Mon Sep 17 00:00:00 2001 +From 094b34760a85c3ee27bf64783624b17bd3bbca0a Mon Sep 17 00:00:00 2001 From: Alexander Graul Date: Tue, 18 Jan 2022 16:38:17 +0100 Subject: [PATCH] X509 fixes (#111) @@ -41,10 +41,10 @@ We are logging in debug and not in trace mode here. salt/modules/x509.py | 93 ++++++++++++++++----------------- salt/states/x509.py | 74 ++++++++++++++++++++++++-- tests/unit/modules/test_x509.py | 6 +-- - 4 files changed, 121 insertions(+), 54 deletions(-) + 4 files changed, 120 insertions(+), 55 deletions(-) diff --git a/salt/modules/publish.py b/salt/modules/publish.py -index c2dd62b913..45ee41ef19 100644 +index cc424cc383..a82cb3ac98 100644 --- a/salt/modules/publish.py +++ b/salt/modules/publish.py @@ -199,6 +199,8 @@ def _publish( @@ -57,10 +57,10 @@ index c2dd62b913..45ee41ef19 100644 def publish( tgt, fun, arg=None, tgt_type="glob", returner="", timeout=5, via_master=None diff --git a/salt/modules/x509.py b/salt/modules/x509.py -index 2f9cc5cc44..194116a85c 100644 +index 57c381ea38..6699a5d363 100644 --- a/salt/modules/x509.py +++ b/salt/modules/x509.py -@@ -30,16 +30,13 @@ from salt.utils.odict import OrderedDict +@@ -42,16 +42,13 @@ from salt.utils.odict import OrderedDict try: import M2Crypto @@ -80,11 +80,16 @@ index 2f9cc5cc44..194116a85c 100644 __virtualname__ = "x509" -@@ -79,10 +76,10 @@ def __virtual__(): - """ - only load this module if m2crypto is available - """ +@@ -94,15 +91,10 @@ def __virtual__(): + # salt.features appears to not be setup when invoked via peer publishing + if __opts__.get("features", {}).get("x509_v2"): + return (False, "Superseded, using x509_v2") - if HAS_M2: +- salt.utils.versions.warn_until( +- "Potassium", +- "The x509 modules are deprecated. Please migrate to the replacement " +- "modules (x509_v2). They are the default from Salt 3008 (Argon) onwards.", +- ) - return __virtualname__ - else: - return (False, "Could not load x509 module, m2crypto unavailable") @@ -95,7 +100,7 @@ index 2f9cc5cc44..194116a85c 100644 class _Ctx(ctypes.Structure): -@@ -140,8 +137,8 @@ def _new_extension(name, value, critical=0, issuer=None, _pyfree=1): +@@ -160,8 +152,8 @@ def _new_extension(name, value, critical=0, issuer=None, _pyfree=1): x509_ext_ptr = M2Crypto.m2.x509v3_ext_conf(None, ctx, name, value) lhash = None except AttributeError: @@ -106,7 +111,7 @@ index 2f9cc5cc44..194116a85c 100644 # ctx not zeroed _fix_ctx(ctx, issuer) x509_ext_ptr = M2Crypto.m2.x509v3_ext_conf(lhash, ctx, name, value) -@@ -280,7 +277,7 @@ def _get_signing_policy(name): +@@ -300,7 +292,7 @@ def _get_signing_policy(name): signing_policy = policies.get(name) if signing_policy: return signing_policy @@ -115,7 +120,7 @@ index 2f9cc5cc44..194116a85c 100644 def _pretty_hex(hex_str): -@@ -318,9 +315,11 @@ def _text_or_file(input_): +@@ -338,9 +330,11 @@ def _text_or_file(input_): """ if _isfile(input_): with salt.utils.files.fopen(input_) as fp_: @@ -129,7 +134,7 @@ index 2f9cc5cc44..194116a85c 100644 def _parse_subject(subject): -@@ -339,7 +338,7 @@ def _parse_subject(subject): +@@ -359,7 +353,7 @@ def _parse_subject(subject): ret_list.append((nid_num, nid_name, val)) nids.append(nid_num) except TypeError as err: @@ -138,7 +143,7 @@ index 2f9cc5cc44..194116a85c 100644 for nid_num, nid_name, val in sorted(ret_list): ret[nid_name] = val return ret -@@ -537,8 +536,8 @@ def get_pem_entries(glob_path): +@@ -557,8 +551,8 @@ def get_pem_entries(glob_path): if os.path.isfile(path): try: ret[path] = get_pem_entry(text=path) @@ -149,7 +154,7 @@ index 2f9cc5cc44..194116a85c 100644 return ret -@@ -616,8 +615,8 @@ def read_certificates(glob_path): +@@ -636,8 +630,8 @@ def read_certificates(glob_path): if os.path.isfile(path): try: ret[path] = read_certificate(certificate=path) @@ -160,7 +165,7 @@ index 2f9cc5cc44..194116a85c 100644 return ret -@@ -647,10 +646,9 @@ def read_csr(csr): +@@ -667,10 +661,9 @@ def read_csr(csr): "Subject": _parse_subject(csr.get_subject()), "Subject Hash": _dec2hex(csr.get_subject().as_hash()), "Public Key Hash": hashlib.sha1(csr.get_pubkey().get_modulus()).hexdigest(), @@ -172,7 +177,7 @@ index 2f9cc5cc44..194116a85c 100644 return ret -@@ -960,7 +958,7 @@ def create_crl( +@@ -980,7 +973,7 @@ def create_crl( # pyOpenSSL Note due to current limitations in pyOpenSSL it is impossible # to specify a digest For signing the CRL. This will hopefully be fixed # soon: https://github.com/pyca/pyopenssl/pull/161 @@ -181,7 +186,7 @@ index 2f9cc5cc44..194116a85c 100644 raise salt.exceptions.SaltInvocationError( "Could not load OpenSSL module, OpenSSL unavailable" ) -@@ -1111,6 +1109,7 @@ def get_signing_policy(signing_policy_name): +@@ -1131,6 +1124,7 @@ def get_signing_policy(signing_policy_name): signing_policy = _get_signing_policy(signing_policy_name) if not signing_policy: return "Signing policy {} does not exist.".format(signing_policy_name) @@ -189,7 +194,7 @@ index 2f9cc5cc44..194116a85c 100644 if isinstance(signing_policy, list): dict_ = {} for item in signing_policy: -@@ -1127,7 +1126,7 @@ def get_signing_policy(signing_policy_name): +@@ -1147,7 +1141,7 @@ def get_signing_policy(signing_policy_name): signing_policy["signing_cert"], "CERTIFICATE" ) except KeyError: @@ -198,7 +203,7 @@ index 2f9cc5cc44..194116a85c 100644 return signing_policy -@@ -1762,7 +1761,8 @@ def create_csr(path=None, text=False, **kwargs): +@@ -1782,7 +1776,8 @@ def create_csr(path=None, text=False, **kwargs): ) ) @@ -208,7 +213,7 @@ index 2f9cc5cc44..194116a85c 100644 if entry in kwargs: setattr(subject, entry, kwargs[entry]) -@@ -1798,7 +1798,6 @@ def create_csr(path=None, text=False, **kwargs): +@@ -1818,7 +1813,6 @@ def create_csr(path=None, text=False, **kwargs): extstack.push(ext) csr.add_extensions(extstack) @@ -216,7 +221,7 @@ index 2f9cc5cc44..194116a85c 100644 csr.sign( _get_private_key_obj( kwargs["private_key"], passphrase=kwargs["private_key_passphrase"] -@@ -1806,10 +1805,11 @@ def create_csr(path=None, text=False, **kwargs): +@@ -1826,10 +1820,11 @@ def create_csr(path=None, text=False, **kwargs): kwargs["algorithm"], ) @@ -232,7 +237,7 @@ index 2f9cc5cc44..194116a85c 100644 def verify_private_key(private_key, public_key, passphrase=None): -@@ -1834,7 +1834,7 @@ def verify_private_key(private_key, public_key, passphrase=None): +@@ -1854,7 +1849,7 @@ def verify_private_key(private_key, public_key, passphrase=None): salt '*' x509.verify_private_key private_key=/etc/pki/myca.key \\ public_key=/etc/pki/myca.crt """ @@ -241,7 +246,7 @@ index 2f9cc5cc44..194116a85c 100644 def verify_signature( -@@ -1890,7 +1890,10 @@ def verify_crl(crl, cert): +@@ -1910,7 +1905,10 @@ def verify_crl(crl, cert): salt '*' x509.verify_crl crl=/etc/pki/myca.crl cert=/etc/pki/myca.crt """ if not salt.utils.path.which("openssl"): @@ -253,19 +258,7 @@ index 2f9cc5cc44..194116a85c 100644 crltext = _text_or_file(crl) crltext = get_pem_entry(crltext, pem_type="X509 CRL") crltempfile = tempfile.NamedTemporaryFile(delete=True) -@@ -1912,10 +1915,7 @@ def verify_crl(crl, cert): - crltempfile.close() - certtempfile.close() - -- if "verify OK" in output: -- return True -- else: -- return False -+ return "verify OK" in output - - - def expired(certificate): -@@ -1953,8 +1953,9 @@ def expired(certificate): +@@ -1970,8 +1968,9 @@ def expired(certificate): ret["expired"] = True else: ret["expired"] = False @@ -277,7 +270,7 @@ index 2f9cc5cc44..194116a85c 100644 return ret -@@ -1977,6 +1978,7 @@ def will_expire(certificate, days): +@@ -1994,6 +1993,7 @@ def will_expire(certificate, days): salt '*' x509.will_expire "/etc/pki/mycert.crt" days=30 """ @@ -285,7 +278,7 @@ index 2f9cc5cc44..194116a85c 100644 ret = {} if os.path.isfile(certificate): -@@ -1990,14 +1992,11 @@ def will_expire(certificate, days): +@@ -2007,14 +2007,11 @@ def will_expire(certificate, days): _expiration_date = cert.get_not_after().get_datetime() ret["cn"] = _parse_subject(cert.get_subject())["CN"] @@ -307,13 +300,13 @@ index 2f9cc5cc44..194116a85c 100644 return ret diff --git a/salt/states/x509.py b/salt/states/x509.py -index b3d2f978bd..16811bcfb8 100644 +index aebbc4cc82..f9cbec87f9 100644 --- a/salt/states/x509.py +++ b/salt/states/x509.py -@@ -177,11 +177,12 @@ import os - import re - +@@ -192,11 +192,12 @@ import re import salt.exceptions + import salt.utils.versions + from salt.features import features +import salt.utils.stringutils try: @@ -324,8 +317,8 @@ index b3d2f978bd..16811bcfb8 100644 log = logging.getLogger(__name__) -@@ -193,7 +194,7 @@ def __virtual__(): - if "x509.get_pem_entry" in __salt__: +@@ -215,7 +216,7 @@ def __virtual__(): + ) return "x509" else: - return (False, "Could not load x509 state: m2crypto unavailable") @@ -333,7 +326,7 @@ index b3d2f978bd..16811bcfb8 100644 def _revoked_to_list(revs): -@@ -682,7 +683,70 @@ def certificate_managed(name, days_remaining=90, append_certs=None, **kwargs): +@@ -704,7 +705,70 @@ def certificate_managed(name, days_remaining=90, append_certs=None, **kwargs): "Old": invalid_reason, "New": "Certificate will be valid and up to date", } @@ -405,7 +398,7 @@ index b3d2f978bd..16811bcfb8 100644 contents = __salt__["x509.create_certificate"](text=True, **kwargs) # Check the module actually returned a cert and not an error message as a string -@@ -878,6 +942,8 @@ def pem_managed(name, text, backup=False, **kwargs): +@@ -900,6 +964,8 @@ def pem_managed(name, text, backup=False, **kwargs): Any arguments supported by :py:func:`file.managed ` are supported. """ file_args, kwargs = _get_file_args(name, **kwargs) @@ -416,10 +409,10 @@ index b3d2f978bd..16811bcfb8 100644 return __states__["file.managed"](**file_args) diff --git a/tests/unit/modules/test_x509.py b/tests/unit/modules/test_x509.py -index 8f4c433b1a..3105290a2c 100644 +index f1ca5bb45a..a5c44f0ed2 100644 --- a/tests/unit/modules/test_x509.py +++ b/tests/unit/modules/test_x509.py -@@ -118,9 +118,9 @@ class X509TestCase(TestCase, LoaderModuleMockMixin): +@@ -119,9 +119,9 @@ class X509TestCase(TestCase, LoaderModuleMockMixin): subj = FakeSubject() x509._parse_subject(subj) @@ -430,9 +423,9 @@ index 8f4c433b1a..3105290a2c 100644 + assert x509.log.debug.call_args[0][1] == list(subj.nid.keys())[0] + assert isinstance(x509.log.debug.call_args[0][2], TypeError) - @skipIf(not HAS_M2CRYPTO, "Skipping, M2Crypto is unavailable") - def test_get_pem_entry(self): + @pytest.mark.skipif( + not HAS_M2CRYPTO, reason="Skipping, reason=M2Crypto is unavailable" -- -2.37.3 +2.39.2 diff --git a/zypperpkg-ignore-retcode-104-for-search-bsc-1176697-.patch b/zypperpkg-ignore-retcode-104-for-search-bsc-1176697-.patch index a8c344a..ff4bcb0 100644 --- a/zypperpkg-ignore-retcode-104-for-search-bsc-1176697-.patch +++ b/zypperpkg-ignore-retcode-104-for-search-bsc-1176697-.patch @@ -1,4 +1,4 @@ -From 41e53ad0b03511d65c5d7e6a12e7c460d83b6737 Mon Sep 17 00:00:00 2001 +From deaee93b2f83f1524ec136afc1a5198b33d293d2 Mon Sep 17 00:00:00 2001 From: Alberto Planas Date: Mon, 5 Oct 2020 16:24:16 +0200 Subject: [PATCH] zypperpkg: ignore retcode 104 for search() @@ -6,14 +6,14 @@ Subject: [PATCH] zypperpkg: ignore retcode 104 for search() --- salt/modules/zypperpkg.py | 28 ++++++--- - tests/unit/modules/test_zypperpkg.py | 89 +++++++++++++++++++++------- - 2 files changed, 90 insertions(+), 27 deletions(-) + tests/unit/modules/test_zypperpkg.py | 87 ++++++++++++++++++++++------ + 2 files changed, 89 insertions(+), 26 deletions(-) diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py -index 32e22ce9a8..6b19c65db3 100644 +index d8220a1fdd..4bb10f445a 100644 --- a/salt/modules/zypperpkg.py +++ b/salt/modules/zypperpkg.py -@@ -99,6 +99,8 @@ class _Zypper: +@@ -103,6 +103,8 @@ class _Zypper: } LOCK_EXIT_CODE = 7 @@ -22,7 +22,7 @@ index 32e22ce9a8..6b19c65db3 100644 XML_DIRECTIVES = ["-x", "--xmlout"] # ZYPPER_LOCK is not affected by --root ZYPPER_LOCK = "/var/run/zypp.pid" -@@ -129,6 +131,7 @@ class _Zypper: +@@ -134,6 +136,7 @@ class _Zypper: self.__no_raise = False self.__refresh = False self.__ignore_repo_failure = False @@ -30,7 +30,7 @@ index 32e22ce9a8..6b19c65db3 100644 self.__systemd_scope = False self.__root = None -@@ -148,6 +151,9 @@ class _Zypper: +@@ -153,6 +156,9 @@ class _Zypper: # Ignore exit code for 106 (repo is not available) if "no_repo_failure" in kwargs: self.__ignore_repo_failure = kwargs["no_repo_failure"] @@ -40,7 +40,7 @@ index 32e22ce9a8..6b19c65db3 100644 if "systemd_scope" in kwargs: self.__systemd_scope = kwargs["systemd_scope"] if "root" in kwargs: -@@ -306,6 +312,10 @@ class _Zypper: +@@ -333,6 +339,10 @@ class _Zypper: if self.__root: self.__cmd.extend(["--root", self.__root]) @@ -51,7 +51,7 @@ index 32e22ce9a8..6b19c65db3 100644 self.__cmd.extend(args) kwargs["output_loglevel"] = "trace" kwargs["python_shell"] = False -@@ -445,9 +455,11 @@ class Wildcard: +@@ -479,9 +489,11 @@ class Wildcard: Get available versions of the package. :return: """ @@ -66,7 +66,7 @@ index 32e22ce9a8..6b19c65db3 100644 if not solvables: raise CommandExecutionError( "No packages found matching '{}'".format(self.name) -@@ -1052,7 +1064,7 @@ def list_repo_pkgs(*args, **kwargs): +@@ -1086,7 +1098,7 @@ def list_repo_pkgs(*args, **kwargs): root = kwargs.get("root") or None for node in ( @@ -75,7 +75,7 @@ index 32e22ce9a8..6b19c65db3 100644 .xml.call("se", "-s", *targets) .getElementsByTagName("solvable") ): -@@ -2439,7 +2451,9 @@ def owner(*paths, **kwargs): +@@ -2556,7 +2568,9 @@ def owner(*paths, **kwargs): def _get_visible_patterns(root=None): """Get all available patterns in the repo that are visible.""" patterns = {} @@ -86,7 +86,7 @@ index 32e22ce9a8..6b19c65db3 100644 for element in search_patterns.getElementsByTagName("solvable"): installed = element.getAttribute("status") == "installed" patterns[element.getAttribute("name")] = { -@@ -2636,7 +2650,7 @@ def search(criteria, refresh=False, **kwargs): +@@ -2753,7 +2767,7 @@ def search(criteria, refresh=False, **kwargs): cmd.append(criteria) solvables = ( @@ -95,7 +95,7 @@ index 32e22ce9a8..6b19c65db3 100644 .nolock.noraise.xml.call(*cmd) .getElementsByTagName("solvable") ) -@@ -2888,7 +2902,7 @@ def _get_patches(installed_only=False, root=None): +@@ -3005,7 +3019,7 @@ def _get_patches(installed_only=False, root=None): """ patches = {} for element in ( @@ -105,19 +105,10 @@ index 32e22ce9a8..6b19c65db3 100644 .getElementsByTagName("solvable") ): diff --git a/tests/unit/modules/test_zypperpkg.py b/tests/unit/modules/test_zypperpkg.py -index 47fca906a7..671adc2779 100644 +index 22137a2544..5e4c967520 100644 --- a/tests/unit/modules/test_zypperpkg.py +++ b/tests/unit/modules/test_zypperpkg.py -@@ -14,7 +14,7 @@ import salt.utils.files - import salt.utils.pkg - from salt.exceptions import CommandExecutionError - from tests.support.mixins import LoaderModuleMockMixin --from tests.support.mock import MagicMock, Mock, call, patch -+from tests.support.mock import MagicMock, Mock, call, mock_open, patch - from tests.support.unit import TestCase - - -@@ -27,7 +27,10 @@ class ZyppCallMock: +@@ -28,7 +28,10 @@ class ZyppCallMock: def __call__(self, *args, **kwargs): # If the call is for a configuration modifier, we return self @@ -129,7 +120,7 @@ index 47fca906a7..671adc2779 100644 return self return MagicMock(return_value=self.__return_value)() -@@ -1801,8 +1804,9 @@ Repository 'DUMMY' not found by its alias, number, or URI. +@@ -1662,8 +1665,9 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): """ @@ -141,7 +132,7 @@ index 47fca906a7..671adc2779 100644 wcard = zypper.Wildcard(_zpr) wcard.name, wcard.version = "libzypp", "*" assert wcard._get_scope_versions(wcard._get_available_versions()) == [ -@@ -1824,8 +1828,9 @@ Repository 'DUMMY' not found by its alias, number, or URI. +@@ -1685,8 +1689,9 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): """ @@ -153,7 +144,7 @@ index 47fca906a7..671adc2779 100644 wcard = zypper.Wildcard(_zpr) wcard.name, wcard.version = "libzypp", "16.2.*-2*" assert wcard._get_scope_versions(wcard._get_available_versions()) == [ -@@ -1846,8 +1851,9 @@ Repository 'DUMMY' not found by its alias, number, or URI. +@@ -1707,8 +1712,9 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): """ @@ -165,7 +156,7 @@ index 47fca906a7..671adc2779 100644 wcard = zypper.Wildcard(_zpr) wcard.name, wcard.version = "libzypp", "16.2.5*" assert wcard._get_scope_versions(wcard._get_available_versions()) == [ -@@ -1867,8 +1873,9 @@ Repository 'DUMMY' not found by its alias, number, or URI. +@@ -1728,8 +1734,9 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): """ @@ -177,7 +168,7 @@ index 47fca906a7..671adc2779 100644 wcard = zypper.Wildcard(_zpr) wcard.name, wcard.version = "libzypp", "*.1" assert wcard._get_scope_versions(wcard._get_available_versions()) == [ -@@ -1889,8 +1896,9 @@ Repository 'DUMMY' not found by its alias, number, or URI. +@@ -1750,8 +1757,9 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): """ @@ -189,7 +180,7 @@ index 47fca906a7..671adc2779 100644 assert zypper.Wildcard(_zpr)("libzypp", "16.2.4*") == "16.2.4-19.5" assert zypper.Wildcard(_zpr)("libzypp", "16.2*") == "16.2.5-25.1" assert zypper.Wildcard(_zpr)("libzypp", "*6-*") == "17.2.6-27.9.1" -@@ -1909,8 +1917,10 @@ Repository 'DUMMY' not found by its alias, number, or URI. +@@ -1770,8 +1778,10 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): """ @@ -202,7 +193,7 @@ index 47fca906a7..671adc2779 100644 assert zypper.Wildcard(_zpr)("libzypp", None) is None def test_wildcard_to_query_typecheck(self): -@@ -1926,8 +1936,9 @@ Repository 'DUMMY' not found by its alias, number, or URI. +@@ -1787,8 +1797,9 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): """ @@ -214,7 +205,7 @@ index 47fca906a7..671adc2779 100644 assert isinstance(zypper.Wildcard(_zpr)("libzypp", "*.1"), str) def test_wildcard_to_query_condition_preservation(self): -@@ -1943,8 +1954,9 @@ Repository 'DUMMY' not found by its alias, number, or URI. +@@ -1804,8 +1815,9 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): """ @@ -226,7 +217,7 @@ index 47fca906a7..671adc2779 100644 for op in zypper.Wildcard.Z_OP: assert zypper.Wildcard(_zpr)( -@@ -1970,8 +1982,10 @@ Repository 'DUMMY' not found by its alias, number, or URI. +@@ -1831,8 +1843,10 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin): """ @@ -239,10 +230,10 @@ index 47fca906a7..671adc2779 100644 with self.assertRaises(CommandExecutionError): for op in [">>", "==", "<<", "+"]: zypper.Wildcard(_zpr)("libzypp", "{}*.1".format(op)) -@@ -2063,3 +2077,38 @@ pattern() = package-c""" - with patch("salt.modules.zypperpkg.__zypper__", zypper_mock): - assert zypper.services_need_restart() == expected - zypper_mock(root=None).nolock.call.assert_called_with("ps", "-sss") +@@ -1958,3 +1972,38 @@ pattern() = package-c""" + self.assertFalse(zypper.__zypper__._is_rpm_lock()) + self.assertEqual(lockf_mock.call_count, 2) + zypper.__zypper__._reset() + + def test_search(self): + """Test zypperpkg.search()""" @@ -279,6 +270,6 @@ index 47fca906a7..671adc2779 100644 + env={"ZYPP_READONLY_HACK": "1"}, + ) -- -2.37.3 +2.39.2