Accepting request 1085020 from systemsmanagement:saltstack
- 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 OBS-URL: https://build.opensuse.org/request/show/1085020 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/salt?expand=0&rev=137
This commit is contained in:
commit
21a97bca4b
@ -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 <Michael.Calmer@suse.de>
|
||||
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 <mwilhite@vmware.com>
|
||||
|
||||
Co-authored-by: Megan Wilhite <mwilhite@vmware.com>
|
||||
---
|
||||
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 <package name>
|
||||
salt '*' pkg.remove <package1>,<package2>,<package3>
|
||||
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
|
||||
|
||||
|
||||
|
@ -1 +1 @@
|
||||
e66649e03c92d249899960aa629533eaeee31fa1
|
||||
2c8ae68c3fb161fd84005ed1b58abf7865ba646f
|
6
_service
6
_service
@ -3,7 +3,7 @@
|
||||
<param name="url">https://github.com/openSUSE/salt-packaging.git</param>
|
||||
<param name="subdir">salt</param>
|
||||
<param name="filename">package</param>
|
||||
<param name="revision">release/3005.1</param>
|
||||
<param name="revision">release/3006.0</param>
|
||||
<param name="scm">git</param>
|
||||
</service>
|
||||
<service name="extract_file" mode="disabled">
|
||||
@ -12,8 +12,8 @@
|
||||
</service>
|
||||
<service name="download_url" mode="disabled">
|
||||
<param name="host">codeload.github.com</param>
|
||||
<param name="path">openSUSE/salt/tar.gz/v3005.1-suse</param>
|
||||
<param name="filename">v3005.1.tar.gz</param>
|
||||
<param name="path">openSUSE/salt/tar.gz/v3006.0-suse</param>
|
||||
<param name="filename">v3006.0.tar.gz</param>
|
||||
</service>
|
||||
<service name="update_changelog" mode="disabled"></service>
|
||||
</services>
|
||||
|
@ -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 <bo@suse.de>
|
||||
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
|
||||
|
||||
|
||||
|
@ -1,224 +0,0 @@
|
||||
From 1434a128559df8183c032af722dc3d187bda148a Mon Sep 17 00:00:00 2001
|
||||
From: Victor Zhestkov <Victor.Zhestkov@suse.com>
|
||||
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
|
||||
|
||||
|
@ -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 <agraul@suse.com>
|
||||
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
|
||||
|
||||
|
||||
|
@ -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 <agraul@suse.com>
|
||||
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
|
||||
|
||||
|
||||
|
@ -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 <agraul@suse.com>
|
||||
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
|
||||
|
||||
|
||||
|
@ -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?=
|
||||
<psuarezhernandez@suse.com>
|
||||
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
|
||||
|
||||
|
||||
|
@ -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 <vzhestkov@suse.com>
|
||||
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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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?=
|
||||
<psuarezhernandez@suse.com>
|
||||
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
|
||||
|
||||
|
||||
|
@ -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 <mc@suse.de>
|
||||
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):
|
||||
|
||||
{'<database name>': 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': '<new-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
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,124 +0,0 @@
|
||||
From d1e9af256fa67cd792ce11e6e9c1e24a1fe2054f Mon Sep 17 00:00:00 2001
|
||||
From: Victor Zhestkov <Victor.Zhestkov@suse.com>
|
||||
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
|
||||
|
||||
|
@ -1,151 +0,0 @@
|
||||
From 6dc653b0cf8e6e043e13bea7009ded604ceb7b71 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||
<psuarezhernandez@suse.com>
|
||||
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 <calebb@vmware.com>
|
||||
---
|
||||
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
|
||||
|
||||
|
@ -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 <mseidl@suse.de>
|
||||
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 <psuarezhernandez@suse.com>
|
||||
Co-authored-by: Jochen Breuer <jbreuer@suse.de>
|
||||
Co-authored-by: Pablo Suárez Hernández <psuarezhernandez@suse.com>
|
||||
---
|
||||
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 = '<?xml version="1.0"?><test foo="bar"/>'
|
||||
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
|
||||
|
||||
|
||||
|
@ -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 <mdinca@suse.de>
|
||||
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
|
||||
|
||||
|
||||
|
@ -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 <mantel@suse.de>
|
||||
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
|
||||
|
||||
|
||||
|
@ -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 <vzhestkov@vz-thinkpad.vzhestkov.net>
|
||||
---
|
||||
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
|
||||
|
||||
|
||||
|
@ -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 <Victor.Zhestkov@suse.com>
|
||||
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
|
||||
|
||||
|
||||
|
@ -1,51 +0,0 @@
|
||||
From 5ed2295489fc13e48b981c323c846bde927cb800 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Graul <agraul@suse.com>
|
||||
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 <salt.modules.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 <salt.modules.yumpkg>`,
|
||||
+ :mod:`zypperpkg <salt.modules.zypperpkg>`.
|
||||
|
||||
Examples:
|
||||
|
||||
--
|
||||
2.37.3
|
||||
|
||||
|
@ -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 <agraul@suse.com>
|
||||
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
|
||||
|
||||
|
||||
|
@ -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 <agraul@suse.com>
|
||||
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
|
||||
|
||||
|
||||
|
@ -1,28 +0,0 @@
|
||||
From dd147ab110e71ea0f1091923c9230ade01f226d4 Mon Sep 17 00:00:00 2001
|
||||
From: Victor Zhestkov <Victor.Zhestkov@suse.com>
|
||||
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 <dwozniak@saltstack.com>
|
||||
---
|
||||
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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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 <bo@suse.de>
|
||||
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
|
||||
|
||||
|
||||
|
@ -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 <agraul@suse.com>
|
||||
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
|
||||
|
||||
|
||||
|
@ -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 <agraul@suse.com>
|
||||
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
|
||||
|
||||
|
||||
|
@ -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 <agraul@suse.com>
|
||||
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 <bo@suse.de>
|
||||
@ -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
|
||||
|
||||
|
||||
|
@ -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 <mmeister@suse.de>
|
||||
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 <mmeister@suse.de>
|
||||
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
|
||||
|
||||
|
||||
|
@ -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?=
|
||||
<psuarezhernandez@suse.com>
|
||||
Date: Wed, 7 Jul 2021 15:41:48 +0100
|
||||
@ -420,6 +420,6 @@ index 045c37f7c9..301c1869ec 100644
|
||||
+ },
|
||||
+ )
|
||||
--
|
||||
2.37.3
|
||||
2.39.2
|
||||
|
||||
|
||||
|
@ -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 <bo@suse.de>
|
||||
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
|
||||
|
||||
|
||||
|
@ -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 <jbreuer@suse.de>
|
||||
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
|
||||
|
||||
|
||||
|
@ -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 <bo@suse.de>
|
||||
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
|
||||
|
||||
|
||||
|
@ -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?= <oholecek@aaannz.eu>
|
||||
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 <dmeltsaykin@mirantis.com>
|
||||
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
|
||||
|
||||
|
||||
|
@ -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 <vzhestkov@suse.com>
|
||||
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
|
||||
|
||||
|
||||
|
@ -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 <vzhestkov@suse.com>
|
||||
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
|
||||
|
||||
|
||||
|
@ -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 <vzhestkov@suse.com>
|
||||
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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 <vzhestkov@suse.com>
|
||||
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
|
||||
|
||||
|
||||
|
@ -1,183 +0,0 @@
|
||||
From 58317cda7a347581b495ab7fd71ce75f0740d8d6 Mon Sep 17 00:00:00 2001
|
||||
From: Victor Zhestkov <Victor.Zhestkov@suse.com>
|
||||
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 <nicholasmhughes@gmail.com>
|
||||
|
||||
* Add tests for _check_user usage
|
||||
|
||||
Co-authored-by: nicholasmhughes <nicholasmhughes@gmail.com>
|
||||
---
|
||||
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
|
||||
|
||||
|
@ -1,37 +0,0 @@
|
||||
From 4cc528dadfbffdeb90df41bbd848d0c2c7efec78 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Graul <agraul@suse.com>
|
||||
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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
58
fix-version-detection-and-avoid-building-and-testing.patch
Normal file
58
fix-version-detection-and-avoid-building-and-testing.patch
Normal file
@ -0,0 +1,58 @@
|
||||
From c0fae09e5a4f6997a60007d970c7c6a5614d9102 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||
<psuarezhernandez@suse.com>
|
||||
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
|
||||
|
||||
|
@ -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 <vzhestkov@suse.com>
|
||||
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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -1,105 +0,0 @@
|
||||
From 7d5b1d2178d0573f137b9481ded85419a36998ff Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||
<psuarezhernandez@suse.com>
|
||||
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 <psuarezhernandez@suse.com>
|
||||
|
||||
Co-authored-by: Ismael Luceno <iluceno@suse.de>
|
||||
---
|
||||
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
|
||||
|
||||
|
BIN
html.tar.bz2
(Stored with Git LFS)
BIN
html.tar.bz2
(Stored with Git LFS)
Binary file not shown.
@ -1,56 +0,0 @@
|
||||
From 7cac5f67eb0d586314f9e7c987b8a620e28eeac3 Mon Sep 17 00:00:00 2001
|
||||
From: Victor Zhestkov <vzhestkov@suse.com>
|
||||
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
|
||||
|
||||
|
@ -1,250 +0,0 @@
|
||||
From e4aff9ca68ce142c87ec875846d8916b9df8e6c5 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Graul <agraul@suse.com>
|
||||
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
|
||||
|
||||
|
@ -1,214 +0,0 @@
|
||||
From 3f1b1180ba34e9ab3a4453248c733f11aa193f1b Mon Sep 17 00:00:00 2001
|
||||
From: Victor Zhestkov <Victor.Zhestkov@suse.com>
|
||||
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
|
||||
|
||||
|
@ -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 <agraul@suse.com>
|
||||
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 <eric.siebigteroth@suse.de>
|
||||
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
|
||||
|
||||
|
||||
|
@ -1,63 +0,0 @@
|
||||
From f9fe9ea009915478ea8f7896dff2c281e68b5d36 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Yeray=20Guti=C3=A9rrez=20Cedr=C3=A9s?=
|
||||
<yeray.gutierrez@suse.com>
|
||||
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
|
||||
|
||||
|
@ -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 <agraul@suse.com>
|
||||
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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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 <bo@suse.de>
|
||||
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
|
||||
|
||||
|
||||
|
@ -1,414 +0,0 @@
|
||||
From 030e2cb20af09673d5f38d68bcb257c6c839a2f3 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Mach <daniel.mach@gmail.com>
|
||||
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 <darix@nordisch.org>
|
||||
---
|
||||
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: <path>
|
||||
+
|
||||
+ # Set PASSWORD_STORE_DIR env for Pass.
|
||||
+ # Defaults to: ~/.password-store
|
||||
+ pass_dir: <path>
|
||||
"""
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
@ -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?=
|
||||
<psuarezhernandez@suse.com>
|
||||
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
|
||||
|
||||
|
||||
|
@ -1,30 +0,0 @@
|
||||
From 03ce925098fb96ad2f2f4b7d4c151ef63aede75f Mon Sep 17 00:00:00 2001
|
||||
From: Witek Bedyk <wbedyk@suse.com>
|
||||
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 <witold.bedyk@suse.com>
|
||||
---
|
||||
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
|
||||
|
||||
|
850
make-sure-the-file-client-is-destroyed-upon-used.patch
Normal file
850
make-sure-the-file-client-is-destroyed-upon-used.patch
Normal file
@ -0,0 +1,850 @@
|
||||
From a1fc5287d501a1ecdbd259e5bbdd4f7d5d06dd13 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Graul <agraul@suse.com>
|
||||
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
|
||||
|
@ -1,296 +0,0 @@
|
||||
From f2dc43cf1db3fee41e328c68545ccac2576021ca Mon Sep 17 00:00:00 2001
|
||||
From: Victor Zhestkov <vzhestkov@suse.com>
|
||||
Date: Mon, 27 Jun 2022 18:01:21 +0300
|
||||
Subject: [PATCH] Normalize package names once with pkg.installed/removed
|
||||
using yum (bsc#1195895)
|
||||
|
||||
* Normalize the package names only once on install/remove
|
||||
|
||||
* Add test for checking pkg.installed/removed with only normalisation
|
||||
|
||||
* Fix split_arch conditions
|
||||
|
||||
* Fix test_pkg
|
||||
---
|
||||
salt/modules/yumpkg.py | 18 ++-
|
||||
salt/states/pkg.py | 3 +-
|
||||
tests/pytests/unit/states/test_pkg.py | 177 +++++++++++++++++++++++++-
|
||||
3 files changed, 192 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/salt/modules/yumpkg.py b/salt/modules/yumpkg.py
|
||||
index 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
|
||||
|
||||
|
@ -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 <Victor.Zhestkov@suse.com>
|
||||
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
|
||||
|
||||
|
||||
|
@ -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 <vzhestkov@suse.com>
|
||||
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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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?=
|
||||
<psuarezhernandez@suse.com>
|
||||
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
|
||||
|
||||
|
||||
|
@ -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 <mdinca@suse.de>
|
||||
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
|
||||
|
||||
|
||||
|
@ -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 <jbreuer@suse.de>
|
||||
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 <mdinca@suse.de>
|
||||
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 <package1>,<package2>,<package3>
|
||||
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 <package1>,<package2>,<package3>
|
||||
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
|
||||
|
||||
|
||||
|
@ -1,297 +0,0 @@
|
||||
From 4a9ec335e7da2f0e3314580e43075bb69fe90c38 Mon Sep 17 00:00:00 2001
|
||||
From: Witek Bedyk <witold.bedyk@suse.com>
|
||||
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 <witold.bedyk@suse.com>
|
||||
|
||||
* Sync formating fixes from upstream
|
||||
|
||||
Signed-off-by: Witek Bedyk <witold.bedyk@suse.com>
|
||||
---
|
||||
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!</message></stream>'
|
||||
)
|
||||
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
|
||||
|
||||
|
@ -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 <mdinca@suse.de>
|
||||
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
|
||||
|
||||
|
||||
|
@ -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 <agraul@suse.com>
|
||||
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
|
||||
|
||||
|
||||
|
@ -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 <clanig@suse.com>
|
||||
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
|
||||
|
||||
|
||||
|
@ -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?= <kkaempf@suse.de>
|
||||
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
|
||||
|
||||
|
||||
|
102
salt.changes
102
salt.changes
@ -1,3 +1,105 @@
|
||||
-------------------------------------------------------------------
|
||||
Fri May 5 08:29:26 UTC 2023 - Alexander Graul <alexander.graul@suse.com>
|
||||
|
||||
- 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 <alexander.graul@suse.com>
|
||||
|
||||
|
126
salt.spec
126
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
|
||||
|
@ -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 <nadvornik@suse.cz>
|
||||
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
|
||||
|
||||
|
||||
|
@ -1,87 +0,0 @@
|
||||
From d561491c48ee30472e0d4699ba389648ef0d863a Mon Sep 17 00:00:00 2001
|
||||
From: Victor Zhestkov <vzhestkov@suse.com>
|
||||
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
|
||||
|
||||
|
@ -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 <agraul@suse.com>
|
||||
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
|
||||
|
||||
|
||||
|
@ -1,362 +0,0 @@
|
||||
From cba6455bd0480bfb80c466a2b34a702a9afb5bd5 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Graul <agraul@suse.com>
|
||||
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 <rahulha@saltstack.com>
|
||||
"""
|
||||
-
|
||||
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
|
||||
|
||||
|
@ -1,105 +0,0 @@
|
||||
From 634e82874b17c38bd4d27c0c07a53c9e39e49968 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||
<psuarezhernandez@suse.com>
|
||||
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 <agraul@suse.com>
|
||||
---
|
||||
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
|
||||
|
||||
|
@ -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 <agraul@suse.com>
|
||||
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
|
||||
|
||||
|
||||
|
@ -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 <bo@suse.de>
|
||||
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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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 <agraul@suse.com>
|
||||
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
|
||||
|
||||
|
||||
|
@ -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?=
|
||||
<psuarezhernandez@suse.com>
|
||||
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
|
||||
|
||||
|
||||
|
@ -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 <vzhestkov@suse.com>
|
||||
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
|
||||
|
||||
|
||||
|
@ -1,3 +0,0 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:344032370bda5edd6242732587111b0a2fee378fcda2d9a1cfff7e191f9ac89e
|
||||
size 18016427
|
BIN
v3006.0.tar.gz
(Stored with Git LFS)
Normal file
BIN
v3006.0.tar.gz
(Stored with Git LFS)
Normal file
Binary file not shown.
@ -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 <agraul@suse.com>
|
||||
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 <salt.states.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
|
||||
|
||||
|
||||
|
@ -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 <aplanas@suse.com>
|
||||
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):
|
||||
<solvable status="installed" name="libzypp" kind="package" edition="16.2.4-19.5" arch="x86_64" repository="(System Packages)"/>
|
||||
</solvable-list></search-result></stream>
|
||||
"""
|
||||
@ -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):
|
||||
</solvable-list></search-result></stream>
|
||||
"""
|
||||
|
||||
@ -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):
|
||||
</solvable-list></search-result></stream>
|
||||
"""
|
||||
|
||||
@ -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):
|
||||
</solvable-list></search-result></stream>
|
||||
"""
|
||||
|
||||
@ -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):
|
||||
<solvable status="other-version" name="libzypp" kind="package" edition="17.2.6-27.9.1" arch="x86_64" repository="foo"/>
|
||||
</solvable-list></search-result></stream>
|
||||
"""
|
||||
@ -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):
|
||||
<solvable status="other-version" name="libzypp" kind="package" edition="17.2.6-27.9.1" arch="x86_64" repository="foo"/>
|
||||
</solvable-list></search-result></stream>
|
||||
"""
|
||||
@ -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):
|
||||
<solvable status="other-version" name="libzypp" kind="package" edition="17.2.6-27.9.1" arch="x86_64" repository="foo"/>
|
||||
</solvable-list></search-result></stream>
|
||||
"""
|
||||
@ -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):
|
||||
<solvable status="other-version" name="libzypp" kind="package" edition="17.2.6-27.9.1" arch="x86_64" repository="foo"/>
|
||||
</solvable-list></search-result></stream>
|
||||
"""
|
||||
@ -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):
|
||||
<solvable status="other-version" name="libzypp" kind="package" edition="17.2.6-27.9.1" arch="x86_64" repository="foo"/>
|
||||
</solvable-list></search-result></stream>
|
||||
"""
|
||||
@ -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
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user