Accepting request 862930 from systemsmanagement:saltstack
- Remove deprecated warning that breaks minion execution when "server_id_use_crc" opts is missing - Added: * remove-deprecated-warning-that-breaks-miniion-execut.patch - Revert wrong zypper patch to support vendorchanges flags on pkg.install - Added: * revert-add-patch-support-for-allow-vendor-change-opt.patch - Force zyppnotify to prefer Packages.db than Packages if it exists - Allow vendor change option with zypper - Add pkg.services_need_restart - Fix for file.check_perms to work with numeric uid/gid - Added: * force-zyppnotify-to-prefer-packages.db-than-packages.patch * fix-salt.utils.stringutils.to_str-calls-to-make-it-w.patch * add-patch-support-for-allow-vendor-change-option-wit.patch * add-pkg.services_need_restart-302.patch - virt: more network support Add more network and PCI/USB host devices passthrough support to virt module and states - Added: * open-suse-3002.2-virt-network-311.patch - Bigvm backports virt consoles, CPU tuning and topology, and memory tuning. - Added: * open-suse-3002.2-bigvm-310.patch - Fix pkg states when DEB package has "all" arch OBS-URL: https://build.opensuse.org/request/show/862930 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/salt?expand=0&rev=113
This commit is contained in:
commit
e6e8c978db
@ -1 +1 @@
|
|||||||
1a73678e768b896323b9d2d1f903a400e48e51e1
|
73673e4ab1d13c4393183b8ad6066dfab39c7e63
|
6
_service
6
_service
@ -3,7 +3,7 @@
|
|||||||
<param name="url">https://github.com/openSUSE/salt-packaging.git</param>
|
<param name="url">https://github.com/openSUSE/salt-packaging.git</param>
|
||||||
<param name="subdir">salt</param>
|
<param name="subdir">salt</param>
|
||||||
<param name="filename">package</param>
|
<param name="filename">package</param>
|
||||||
<param name="revision">3000.3</param>
|
<param name="revision">3002.2</param>
|
||||||
<param name="scm">git</param>
|
<param name="scm">git</param>
|
||||||
</service>
|
</service>
|
||||||
<service name="extract_file" mode="disabled">
|
<service name="extract_file" mode="disabled">
|
||||||
@ -12,8 +12,8 @@
|
|||||||
</service>
|
</service>
|
||||||
<service name="download_url" mode="disabled">
|
<service name="download_url" mode="disabled">
|
||||||
<param name="host">codeload.github.com</param>
|
<param name="host">codeload.github.com</param>
|
||||||
<param name="path">openSUSE/salt/tar.gz/v3000.3-suse</param>
|
<param name="path">openSUSE/salt/tar.gz/v3002.2-suse</param>
|
||||||
<param name="filename">v3000.3.tar.gz</param>
|
<param name="filename">v3002.2.tar.gz</param>
|
||||||
</service>
|
</service>
|
||||||
<service name="update_changelog" mode="disabled"></service>
|
<service name="update_changelog" mode="disabled"></service>
|
||||||
</services>
|
</services>
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From 951d2a385a40c5322155f952e08430e8402bfbde Mon Sep 17 00:00:00 2001
|
From 828650500159fd7040d2fa76b2fc4d2b627f7065 Mon Sep 17 00:00:00 2001
|
||||||
From: Alberto Planas <aplanas@gmail.com>
|
From: Alberto Planas <aplanas@gmail.com>
|
||||||
Date: Tue, 22 Oct 2019 11:02:33 +0200
|
Date: Tue, 22 Oct 2019 11:02:33 +0200
|
||||||
Subject: [PATCH] Accumulated changes from Yomi (#167)
|
Subject: [PATCH] Accumulated changes from Yomi (#167)
|
||||||
@ -17,190 +17,207 @@ This patch ignore this kind of issue during the grains creation.
|
|||||||
|
|
||||||
(cherry picked from commit b865491b74679140f7a71c5ba50d482db47b600f)
|
(cherry picked from commit b865491b74679140f7a71c5ba50d482db47b600f)
|
||||||
---
|
---
|
||||||
salt/grains/core.py | 4 +++
|
salt/grains/core.py | 6 +--
|
||||||
salt/modules/zypperpkg.py | 30 +++++++++++-----
|
salt/modules/zypperpkg.py | 22 ----------
|
||||||
tests/unit/grains/test_core.py | 68 ++++++++++++++++++++++++++++++++++++
|
tests/unit/grains/test_core.py | 64 +++++++++++++++++++++++++++-
|
||||||
tests/unit/modules/test_zypperpkg.py | 26 ++++++++++++++
|
tests/unit/modules/test_zypperpkg.py | 38 +++++++++++++++++
|
||||||
4 files changed, 119 insertions(+), 9 deletions(-)
|
4 files changed, 103 insertions(+), 27 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/grains/core.py b/salt/grains/core.py
|
diff --git a/salt/grains/core.py b/salt/grains/core.py
|
||||||
index 77ae99590f..68c43482d3 100644
|
index 0dc1d97f97..a2983e388b 100644
|
||||||
--- a/salt/grains/core.py
|
--- a/salt/grains/core.py
|
||||||
+++ b/salt/grains/core.py
|
+++ b/salt/grains/core.py
|
||||||
@@ -997,6 +997,10 @@ def _virtual(osdata):
|
@@ -1046,7 +1046,7 @@ def _virtual(osdata):
|
||||||
grains['virtual'] = 'gce'
|
if os.path.isfile("/sys/devices/virtual/dmi/id/product_name"):
|
||||||
elif 'BHYVE' in output:
|
try:
|
||||||
grains['virtual'] = 'bhyve'
|
with salt.utils.files.fopen(
|
||||||
+ except UnicodeDecodeError:
|
- "/sys/devices/virtual/dmi/id/product_name", "rb"
|
||||||
+ # Some firmwares provide non-valid 'product_name'
|
+ "/sys/devices/virtual/dmi/id/product_name", "r"
|
||||||
+ # files, ignore them
|
) as fhr:
|
||||||
|
output = salt.utils.stringutils.to_unicode(
|
||||||
|
fhr.read(), errors="replace"
|
||||||
|
@@ -1066,9 +1066,7 @@ def _virtual(osdata):
|
||||||
|
except UnicodeDecodeError:
|
||||||
|
# Some firmwares provide non-valid 'product_name'
|
||||||
|
# files, ignore them
|
||||||
|
- log.debug(
|
||||||
|
- "The content in /sys/devices/virtual/dmi/id/product_name is not valid"
|
||||||
|
- )
|
||||||
+ pass
|
+ pass
|
||||||
except IOError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
elif osdata['kernel'] == 'FreeBSD':
|
elif osdata["kernel"] == "FreeBSD":
|
||||||
diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py
|
diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py
|
||||||
index f7158e0810..5f3b6d6855 100644
|
index 2daec0f380..b5621174a4 100644
|
||||||
--- a/salt/modules/zypperpkg.py
|
--- a/salt/modules/zypperpkg.py
|
||||||
+++ b/salt/modules/zypperpkg.py
|
+++ b/salt/modules/zypperpkg.py
|
||||||
@@ -863,23 +863,35 @@ def list_pkgs(versions_as_list=False, root=None, includes=None, **kwargs):
|
@@ -958,28 +958,6 @@ def list_pkgs(versions_as_list=False, root=None, includes=None, **kwargs):
|
||||||
_ret[pkgname] = sorted(ret[pkgname], key=lambda d: d['version'])
|
}
|
||||||
|
]
|
||||||
|
|
||||||
for include in includes:
|
- for include in includes:
|
||||||
+ if include == 'product':
|
- if include in ("pattern", "patch"):
|
||||||
+ products = list_products(all=False, root=root)
|
- if include == "pattern":
|
||||||
+ for product in products:
|
|
||||||
+ extended_name = '{}:{}'.format(include, product['name'])
|
|
||||||
+ _ret[extended_name] = [{
|
|
||||||
+ 'epoch': product['epoch'],
|
|
||||||
+ 'version': product['version'],
|
|
||||||
+ 'release': product['release'],
|
|
||||||
+ 'arch': product['arch'],
|
|
||||||
+ 'install_date': None,
|
|
||||||
+ 'install_date_time_t': None,
|
|
||||||
+ }]
|
|
||||||
if include in ('pattern', 'patch'):
|
|
||||||
if include == 'pattern':
|
|
||||||
- pkgs = list_installed_patterns(root=root)
|
- pkgs = list_installed_patterns(root=root)
|
||||||
+ elements = list_installed_patterns(root=root)
|
- elif include == "patch":
|
||||||
elif include == 'patch':
|
|
||||||
- pkgs = list_installed_patches(root=root)
|
- pkgs = list_installed_patches(root=root)
|
||||||
+ elements = list_installed_patches(root=root)
|
- else:
|
||||||
else:
|
|
||||||
- pkgs = []
|
- pkgs = []
|
||||||
- for pkg in pkgs:
|
- for pkg in pkgs:
|
||||||
- pkg_extended_name = '{}:{}'.format(include, pkg)
|
- pkg_extended_name = "{}:{}".format(include, pkg)
|
||||||
- info = info_available(pkg_extended_name,
|
- info = info_available(pkg_extended_name, refresh=False, root=root)
|
||||||
+ elements = []
|
- _ret[pkg_extended_name] = [
|
||||||
+ for element in elements:
|
- {
|
||||||
+ extended_name = '{}:{}'.format(include, element)
|
- "epoch": None,
|
||||||
+ info = info_available(extended_name,
|
- "version": info[pkg]["version"],
|
||||||
refresh=False,
|
- "release": None,
|
||||||
root=root)
|
- "arch": info[pkg]["arch"],
|
||||||
- _ret[pkg_extended_name] = [{
|
- "install_date": None,
|
||||||
+ _ret[extended_name] = [{
|
- "install_date_time_t": None,
|
||||||
'epoch': None,
|
- }
|
||||||
- 'version': info[pkg]['version'],
|
- ]
|
||||||
+ 'version': info[element]['version'],
|
-
|
||||||
'release': None,
|
__context__[contextkey] = _ret
|
||||||
- 'arch': info[pkg]['arch'],
|
|
||||||
+ 'arch': info[element]['arch'],
|
return __salt__["pkg_resource.format_pkg_list"](
|
||||||
'install_date': None,
|
|
||||||
'install_date_time_t': None,
|
|
||||||
}]
|
|
||||||
diff --git a/tests/unit/grains/test_core.py b/tests/unit/grains/test_core.py
|
diff --git a/tests/unit/grains/test_core.py b/tests/unit/grains/test_core.py
|
||||||
index e722bfab5b..33d6a9507f 100644
|
index a5ceeb8317..0dc3423646 100644
|
||||||
--- a/tests/unit/grains/test_core.py
|
--- a/tests/unit/grains/test_core.py
|
||||||
+++ b/tests/unit/grains/test_core.py
|
+++ b/tests/unit/grains/test_core.py
|
||||||
@@ -1559,3 +1559,71 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -2047,13 +2047,74 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
assert len(info) == 2
|
result = core.path()
|
||||||
assert all([x is not None for x in info])
|
assert result == {"path": path, "systempath": comps}, result
|
||||||
assert all([isinstance(x, int) for x in info])
|
|
||||||
+
|
+ @skipIf(not salt.utils.platform.is_linux(), "System is not Linux")
|
||||||
+ @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
|
+ @patch("os.path.exists")
|
||||||
|
+ @patch("salt.utils.platform.is_proxy")
|
||||||
+ def test_kernelparams_return(self):
|
+ def test_kernelparams_return(self):
|
||||||
+ expectations = [
|
+ expectations = [
|
||||||
+ ('BOOT_IMAGE=/vmlinuz-3.10.0-693.2.2.el7.x86_64',
|
+ (
|
||||||
+ {'kernelparams': [('BOOT_IMAGE', '/vmlinuz-3.10.0-693.2.2.el7.x86_64')]}),
|
+ "BOOT_IMAGE=/vmlinuz-3.10.0-693.2.2.el7.x86_64",
|
||||||
+ ('root=/dev/mapper/centos_daemon-root',
|
+ {
|
||||||
+ {'kernelparams': [('root', '/dev/mapper/centos_daemon-root')]}),
|
+ "kernelparams": [
|
||||||
+ ('rhgb quiet ro',
|
+ ("BOOT_IMAGE", "/vmlinuz-3.10.0-693.2.2.el7.x86_64")
|
||||||
+ {'kernelparams': [('rhgb', None), ('quiet', None), ('ro', None)]}),
|
+ ]
|
||||||
+ ('param="value1"',
|
+ },
|
||||||
+ {'kernelparams': [('param', 'value1')]}),
|
+ ),
|
||||||
+ ('param="value1 value2 value3"',
|
+ (
|
||||||
+ {'kernelparams': [('param', 'value1 value2 value3')]}),
|
+ "root=/dev/mapper/centos_daemon-root",
|
||||||
+ ('param="value1 value2 value3" LANG="pl" ro',
|
+ {"kernelparams": [("root", "/dev/mapper/centos_daemon-root")]},
|
||||||
+ {'kernelparams': [('param', 'value1 value2 value3'), ('LANG', 'pl'), ('ro', None)]}),
|
+ ),
|
||||||
+ ('ipv6.disable=1',
|
+ (
|
||||||
+ {'kernelparams': [('ipv6.disable', '1')]}),
|
+ "rhgb quiet ro",
|
||||||
+ ('param="value1:value2:value3"',
|
+ {"kernelparams": [("rhgb", None), ("quiet", None), ("ro", None)]},
|
||||||
+ {'kernelparams': [('param', 'value1:value2:value3')]}),
|
+ ),
|
||||||
+ ('param="value1,value2,value3"',
|
+ ('param="value1"', {"kernelparams": [("param", "value1")]}),
|
||||||
+ {'kernelparams': [('param', 'value1,value2,value3')]}),
|
+ (
|
||||||
+ ('param="value1" param="value2" param="value3"',
|
+ 'param="value1 value2 value3"',
|
||||||
+ {'kernelparams': [('param', 'value1'), ('param', 'value2'), ('param', 'value3')]}),
|
+ {"kernelparams": [("param", "value1 value2 value3")]},
|
||||||
|
+ ),
|
||||||
|
+ (
|
||||||
|
+ 'param="value1 value2 value3" LANG="pl" ro',
|
||||||
|
+ {
|
||||||
|
+ "kernelparams": [
|
||||||
|
+ ("param", "value1 value2 value3"),
|
||||||
|
+ ("LANG", "pl"),
|
||||||
|
+ ("ro", None),
|
||||||
|
+ ]
|
||||||
|
+ },
|
||||||
|
+ ),
|
||||||
|
+ ("ipv6.disable=1", {"kernelparams": [("ipv6.disable", "1")]}),
|
||||||
|
+ (
|
||||||
|
+ 'param="value1:value2:value3"',
|
||||||
|
+ {"kernelparams": [("param", "value1:value2:value3")]},
|
||||||
|
+ ),
|
||||||
|
+ (
|
||||||
|
+ 'param="value1,value2,value3"',
|
||||||
|
+ {"kernelparams": [("param", "value1,value2,value3")]},
|
||||||
|
+ ),
|
||||||
|
+ (
|
||||||
|
+ 'param="value1" param="value2" param="value3"',
|
||||||
|
+ {
|
||||||
|
+ "kernelparams": [
|
||||||
|
+ ("param", "value1"),
|
||||||
|
+ ("param", "value2"),
|
||||||
|
+ ("param", "value3"),
|
||||||
|
+ ]
|
||||||
|
+ },
|
||||||
|
+ ),
|
||||||
+ ]
|
+ ]
|
||||||
+
|
+
|
||||||
+ for cmdline, expectation in expectations:
|
+ for cmdline, expectation in expectations:
|
||||||
+ with patch('salt.utils.files.fopen', mock_open(read_data=cmdline)):
|
+ with patch("salt.utils.files.fopen", mock_open(read_data=cmdline)):
|
||||||
+ self.assertEqual(core.kernelparams(), expectation)
|
+ self.assertEqual(core.kernelparams(), expectation)
|
||||||
+
|
+
|
||||||
+ @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
|
@skipIf(not salt.utils.platform.is_linux(), "System is not Linux")
|
||||||
+ @patch('os.path.exists')
|
@patch("os.path.exists")
|
||||||
+ @patch('salt.utils.platform.is_proxy')
|
@patch("salt.utils.platform.is_proxy")
|
||||||
+ def test__hw_data_linux_empty(self, is_proxy, exists):
|
def test__hw_data_linux_empty(self, is_proxy, exists):
|
||||||
+ is_proxy.return_value = False
|
is_proxy.return_value = False
|
||||||
+ exists.return_value = True
|
exists.return_value = True
|
||||||
+ with patch('salt.utils.files.fopen', mock_open(read_data='')):
|
- with patch("salt.utils.files.fopen", mock_open(read_data=b"")):
|
||||||
+ self.assertEqual(core._hw_data({'kernel': 'Linux'}), {
|
+ with patch("salt.utils.files.fopen", mock_open(read_data="")):
|
||||||
+ 'biosreleasedate': '',
|
self.assertEqual(
|
||||||
+ 'biosversion': '',
|
core._hw_data({"kernel": "Linux"}),
|
||||||
+ 'manufacturer': '',
|
{
|
||||||
+ 'productname': '',
|
@@ -2067,6 +2128,7 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
+ 'serialnumber': '',
|
)
|
||||||
+ 'uuid': ''
|
|
||||||
+ })
|
@skipIf(not salt.utils.platform.is_linux(), "System is not Linux")
|
||||||
+
|
+ @skipIf(six.PY2, "UnicodeDecodeError is throw in Python 3")
|
||||||
+ @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
|
@patch("os.path.exists")
|
||||||
+ @skipIf(six.PY2, 'UnicodeDecodeError is throw in Python 3')
|
@patch("salt.utils.platform.is_proxy")
|
||||||
+ @patch('os.path.exists')
|
def test__hw_data_linux_unicode_error(self, is_proxy, exists):
|
||||||
+ @patch('salt.utils.platform.is_proxy')
|
|
||||||
+ def test__hw_data_linux_unicode_error(self, is_proxy, exists):
|
|
||||||
+ def _fopen(*args):
|
|
||||||
+ class _File(object):
|
|
||||||
+ def __enter__(self):
|
|
||||||
+ return self
|
|
||||||
+
|
|
||||||
+ def __exit__(self, *args):
|
|
||||||
+ pass
|
|
||||||
+
|
|
||||||
+ def read(self):
|
|
||||||
+ raise UnicodeDecodeError('enconding', b'', 1, 2, 'reason')
|
|
||||||
+
|
|
||||||
+ return _File()
|
|
||||||
+
|
|
||||||
+ is_proxy.return_value = False
|
|
||||||
+ exists.return_value = True
|
|
||||||
+ with patch('salt.utils.files.fopen', _fopen):
|
|
||||||
+ self.assertEqual(core._hw_data({'kernel': 'Linux'}), {})
|
|
||||||
diff --git a/tests/unit/modules/test_zypperpkg.py b/tests/unit/modules/test_zypperpkg.py
|
diff --git a/tests/unit/modules/test_zypperpkg.py b/tests/unit/modules/test_zypperpkg.py
|
||||||
index 6102043384..76937cc358 100644
|
index 5d4e7766b6..1b62122e0e 100644
|
||||||
--- a/tests/unit/modules/test_zypperpkg.py
|
--- a/tests/unit/modules/test_zypperpkg.py
|
||||||
+++ b/tests/unit/modules/test_zypperpkg.py
|
+++ b/tests/unit/modules/test_zypperpkg.py
|
||||||
@@ -944,6 +944,32 @@ Repository 'DUMMY' not found by its alias, number, or URI.
|
@@ -1424,6 +1424,44 @@ Repository 'DUMMY' not found by its alias, number, or URI.
|
||||||
with self.assertRaisesRegex(CommandExecutionError, '^Advisory id "SUSE-PATCH-XXX" not found$'):
|
ret, {"product:openSUSE": {"old": "15.2", "new": "15.3"}}
|
||||||
zypper.install(advisory_ids=['SUSE-PATCH-XXX'])
|
)
|
||||||
|
|
||||||
+ @patch('salt.modules.zypperpkg._systemd_scope',
|
+ @patch("salt.modules.zypperpkg._systemd_scope", MagicMock(return_value=False))
|
||||||
+ MagicMock(return_value=False))
|
+ @patch(
|
||||||
+ @patch('salt.modules.zypperpkg.list_products',
|
+ "salt.modules.zypperpkg.list_products",
|
||||||
+ MagicMock(return_value={'openSUSE': {'installed': False, 'summary': 'test'}}))
|
+ MagicMock(return_value={"openSUSE": {"installed": False, "summary": "test"}}),
|
||||||
+ @patch('salt.modules.zypperpkg.list_pkgs', MagicMock(side_effect=[{"product:openSUSE": "15.2"},
|
+ )
|
||||||
+ {"product:openSUSE": "15.3"}]))
|
+ @patch(
|
||||||
+ def test_install_product_ok(self):
|
+ "salt.modules.zypperpkg.list_pkgs",
|
||||||
+ '''
|
+ MagicMock(
|
||||||
+ Test successfully product installation.
|
+ side_effect=[{"product:openSUSE": "15.2"}, {"product:openSUSE": "15.3"}]
|
||||||
+ '''
|
+ ),
|
||||||
+ with patch.dict(zypper.__salt__,
|
+ )
|
||||||
+ {
|
+ def test_install_product_ok(self):
|
||||||
+ 'pkg_resource.parse_targets': MagicMock(
|
+ """
|
||||||
+ return_value=(['product:openSUSE'], None))
|
+ Test successfully product installation.
|
||||||
+ }):
|
+ """
|
||||||
+ with patch('salt.modules.zypperpkg.__zypper__.noraise.call', MagicMock()) as zypper_mock:
|
+ with patch.dict(
|
||||||
+ ret = zypper.install('product:openSUSE', includes=['product'])
|
+ zypper.__salt__,
|
||||||
+ zypper_mock.assert_called_once_with(
|
+ {
|
||||||
+ '--no-refresh',
|
+ "pkg_resource.parse_targets": MagicMock(
|
||||||
+ 'install',
|
+ return_value=(["product:openSUSE"], None)
|
||||||
+ '--auto-agree-with-licenses',
|
+ )
|
||||||
+ '--name',
|
+ },
|
||||||
+ 'product:openSUSE'
|
+ ):
|
||||||
|
+ with patch(
|
||||||
|
+ "salt.modules.zypperpkg.__zypper__.noraise.call", MagicMock()
|
||||||
|
+ ) as zypper_mock:
|
||||||
|
+ ret = zypper.install("product:openSUSE", includes=["product"])
|
||||||
|
+ zypper_mock.assert_called_once_with(
|
||||||
|
+ "--no-refresh",
|
||||||
|
+ "install",
|
||||||
|
+ "--auto-agree-with-licenses",
|
||||||
|
+ "--name",
|
||||||
|
+ "product:openSUSE",
|
||||||
|
+ )
|
||||||
|
+ self.assertDictEqual(
|
||||||
|
+ ret, {"product:openSUSE": {"old": "15.2", "new": "15.3"}}
|
||||||
+ )
|
+ )
|
||||||
+ self.assertDictEqual(ret, {"product:openSUSE": {"old": "15.2", "new": "15.3"}})
|
|
||||||
+
|
+
|
||||||
def test_remove_purge(self):
|
def test_remove_purge(self):
|
||||||
'''
|
"""
|
||||||
Test package removal
|
Test package removal
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From 9f29577b75cac1e79ec7c30a5dff0dff0ab9da3a Mon Sep 17 00:00:00 2001
|
From 7d35fdba84b6e1b62a3abc71e518366a35efb662 Mon Sep 17 00:00:00 2001
|
||||||
From: Alberto Planas <aplanas@gmail.com>
|
From: Alberto Planas <aplanas@gmail.com>
|
||||||
Date: Tue, 30 Jul 2019 11:23:12 +0200
|
Date: Tue, 30 Jul 2019 11:23:12 +0200
|
||||||
Subject: [PATCH] Accumulated changes required for Yomi (#165)
|
Subject: [PATCH] Accumulated changes required for Yomi (#165)
|
||||||
@ -58,143 +58,60 @@ so the cached data will be separated too.
|
|||||||
|
|
||||||
(cherry picked from commit 9c54bb3e8c93ba21fc583bdefbcadbe53cbcd7b5)
|
(cherry picked from commit 9c54bb3e8c93ba21fc583bdefbcadbe53cbcd7b5)
|
||||||
---
|
---
|
||||||
salt/modules/cmdmod.py | 12 +++++++++---
|
salt/modules/zypperpkg.py | 1 -
|
||||||
salt/modules/zypperpkg.py | 13 ++++++++++---
|
tests/unit/modules/test_zypperpkg.py | 22 +++++++++++++++++++++-
|
||||||
tests/unit/modules/test_cmdmod.py | 16 ++++++++++++++++
|
2 files changed, 21 insertions(+), 2 deletions(-)
|
||||||
tests/unit/modules/test_zypperpkg.py | 21 +++++++++++++++++++++
|
|
||||||
4 files changed, 56 insertions(+), 6 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/salt/modules/cmdmod.py b/salt/modules/cmdmod.py
|
|
||||||
index eed7656a6d..0d2f720bbb 100644
|
|
||||||
--- a/salt/modules/cmdmod.py
|
|
||||||
+++ b/salt/modules/cmdmod.py
|
|
||||||
@@ -3094,13 +3094,19 @@ def run_chroot(root,
|
|
||||||
|
|
||||||
if isinstance(cmd, (list, tuple)):
|
|
||||||
cmd = ' '.join([six.text_type(i) for i in cmd])
|
|
||||||
- cmd = 'chroot {0} {1} -c {2}'.format(root, sh_, _cmd_quote(cmd))
|
|
||||||
+
|
|
||||||
+ # If runas and group are provided, we expect that the user lives
|
|
||||||
+ # inside the chroot, not outside.
|
|
||||||
+ if runas:
|
|
||||||
+ userspec = '--userspec {}:{}'.format(runas, group if group else '')
|
|
||||||
+ else:
|
|
||||||
+ userspec = ''
|
|
||||||
+
|
|
||||||
+ cmd = 'chroot {} {} {} -c {}'.format(userspec, root, sh_, _cmd_quote(cmd))
|
|
||||||
|
|
||||||
run_func = __context__.pop('cmd.run_chroot.func', run_all)
|
|
||||||
|
|
||||||
ret = run_func(cmd,
|
|
||||||
- runas=runas,
|
|
||||||
- group=group,
|
|
||||||
cwd=cwd,
|
|
||||||
stdin=stdin,
|
|
||||||
shell=shell,
|
|
||||||
diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py
|
diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py
|
||||||
index 3760b525e7..8179cd8c1d 100644
|
index c996935bff..b099f3e5d7 100644
|
||||||
--- a/salt/modules/zypperpkg.py
|
--- a/salt/modules/zypperpkg.py
|
||||||
+++ b/salt/modules/zypperpkg.py
|
+++ b/salt/modules/zypperpkg.py
|
||||||
@@ -449,8 +449,14 @@ def _clean_cache():
|
@@ -879,7 +879,6 @@ def list_pkgs(versions_as_list=False, root=None, includes=None, **kwargs):
|
||||||
'''
|
# inclusion types are passed
|
||||||
Clean cached results
|
contextkey = "pkg.list_pkgs_{}_{}".format(root, includes)
|
||||||
'''
|
|
||||||
+ keys = []
|
|
||||||
for cache_name in ['pkg.list_pkgs', 'pkg.list_provides']:
|
|
||||||
- __context__.pop(cache_name, None)
|
|
||||||
+ for contextkey in __context__:
|
|
||||||
+ if contextkey.startswith(cache_name):
|
|
||||||
+ keys.append(contextkey)
|
|
||||||
+
|
|
||||||
+ for key in keys:
|
|
||||||
+ __context__.pop(key, None)
|
|
||||||
|
|
||||||
|
|
||||||
def list_upgrades(refresh=True, root=None, **kwargs):
|
|
||||||
@@ -811,9 +817,10 @@ def list_pkgs(versions_as_list=False, root=None, includes=None, **kwargs):
|
|
||||||
|
|
||||||
includes = includes if includes else []
|
|
||||||
|
|
||||||
- contextkey = 'pkg.list_pkgs'
|
|
||||||
+ # Results can be different if a different root or a different
|
|
||||||
+ # inclusion types are passed
|
|
||||||
+ contextkey = 'pkg.list_pkgs_{}_{}'.format(root, includes)
|
|
||||||
|
|
||||||
- # TODO(aplanas): this cached value depends on the parameters
|
- # TODO(aplanas): this cached value depends on the parameters
|
||||||
if contextkey not in __context__:
|
if contextkey not in __context__:
|
||||||
ret = {}
|
ret = {}
|
||||||
cmd = ['rpm']
|
cmd = ["rpm"]
|
||||||
diff --git a/tests/unit/modules/test_cmdmod.py b/tests/unit/modules/test_cmdmod.py
|
|
||||||
index f8fba59294..8d763435f8 100644
|
|
||||||
--- a/tests/unit/modules/test_cmdmod.py
|
|
||||||
+++ b/tests/unit/modules/test_cmdmod.py
|
|
||||||
@@ -371,6 +371,22 @@ class CMDMODTestCase(TestCase, LoaderModuleMockMixin):
|
|
||||||
else:
|
|
||||||
raise RuntimeError
|
|
||||||
|
|
||||||
+ @skipIf(salt.utils.platform.is_windows(), 'Do not run on Windows')
|
|
||||||
+ @skipIf(salt.utils.platform.is_darwin(), 'Do not run on MacOS')
|
|
||||||
+ def test_run_cwd_in_combination_with_runas(self):
|
|
||||||
+ '''
|
|
||||||
+ cmd.run executes command in the cwd directory
|
|
||||||
+ when the runas parameter is specified
|
|
||||||
+ '''
|
|
||||||
+ cmd = 'pwd'
|
|
||||||
+ cwd = '/tmp'
|
|
||||||
+ runas = os.getlogin()
|
|
||||||
+
|
|
||||||
+ with patch.dict(cmdmod.__grains__, {'os': 'Darwin',
|
|
||||||
+ 'os_family': 'Solaris'}):
|
|
||||||
+ stdout = cmdmod._run(cmd, cwd=cwd, runas=runas).get('stdout')
|
|
||||||
+ self.assertEqual(stdout, cwd)
|
|
||||||
+
|
|
||||||
def test_run_all_binary_replace(self):
|
|
||||||
'''
|
|
||||||
Test for failed decoding of binary data, for instance when doing
|
|
||||||
diff --git a/tests/unit/modules/test_zypperpkg.py b/tests/unit/modules/test_zypperpkg.py
|
diff --git a/tests/unit/modules/test_zypperpkg.py b/tests/unit/modules/test_zypperpkg.py
|
||||||
index 12c22bfcb2..6102043384 100644
|
index 032785395e..5d4e7766b6 100644
|
||||||
--- a/tests/unit/modules/test_zypperpkg.py
|
--- a/tests/unit/modules/test_zypperpkg.py
|
||||||
+++ b/tests/unit/modules/test_zypperpkg.py
|
+++ b/tests/unit/modules/test_zypperpkg.py
|
||||||
@@ -571,6 +571,7 @@ Repository 'DUMMY' not found by its alias, number, or URI.
|
@@ -912,7 +912,8 @@ Repository 'DUMMY' not found by its alias, number, or URI.
|
||||||
patch.dict(zypper.__salt__, {'pkg_resource.stringify': MagicMock()}):
|
), patch.dict(
|
||||||
pkgs = zypper.list_pkgs(versions_as_list=True)
|
zypper.__salt__, {"pkg_resource.stringify": MagicMock()}
|
||||||
self.assertFalse(pkgs.get('gpg-pubkey', False))
|
), patch.dict(
|
||||||
+ self.assertTrue('pkg.list_pkgs_None_[]' in zypper.__context__)
|
- pkg_resource.__salt__, {"pkg.parse_arch": zypper.parse_arch}
|
||||||
for pkg_name, pkg_version in {
|
+ pkg_resource.__salt__,
|
||||||
'jakarta-commons-discovery': ['0.4-129.686'],
|
+ {"pkg.parse_arch_from_name": zypper.parse_arch_from_name},
|
||||||
'yast2-ftp-server': ['3.1.8-8.1'],
|
):
|
||||||
@@ -613,6 +614,7 @@ Repository 'DUMMY' not found by its alias, number, or URI.
|
pkgs = zypper.list_pkgs(
|
||||||
patch.dict(pkg_resource.__salt__, {'pkg.parse_arch_from_name': zypper.parse_arch_from_name}):
|
attr=["epoch", "release", "arch", "install_date_time_t"]
|
||||||
pkgs = zypper.list_pkgs(attr=['epoch', 'release', 'arch', 'install_date_time_t'])
|
@@ -1950,3 +1951,22 @@ pattern() = package-c"""
|
||||||
self.assertFalse(pkgs.get('gpg-pubkey', False))
|
"package-a": {"installed": True, "summary": "description a",},
|
||||||
+ self.assertTrue('pkg.list_pkgs_None_[]' in zypper.__context__)
|
"package-b": {"installed": False, "summary": "description b",},
|
||||||
for pkg_name, pkg_attr in {
|
|
||||||
'jakarta-commons-discovery': [{
|
|
||||||
'version': '0.4',
|
|
||||||
@@ -1456,3 +1458,22 @@ pattern() = package-c'''),
|
|
||||||
'summary': 'description b',
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
+
|
+
|
||||||
+ def test__clean_cache_empty(self):
|
+ def test__clean_cache_empty(self):
|
||||||
+ '''Test that an empty cached can be cleaned'''
|
+ """Test that an empty cached can be cleaned"""
|
||||||
+ context = {}
|
+ context = {}
|
||||||
+ with patch.dict(zypper.__context__, context):
|
+ with patch.dict(zypper.__context__, context):
|
||||||
+ zypper._clean_cache()
|
+ zypper._clean_cache()
|
||||||
+ assert context == {}
|
+ assert context == {}
|
||||||
+
|
+
|
||||||
+ def test__clean_cache_filled(self):
|
+ def test__clean_cache_filled(self):
|
||||||
+ '''Test that a filled cached can be cleaned'''
|
+ """Test that a filled cached can be cleaned"""
|
||||||
+ context = {
|
+ context = {
|
||||||
+ 'pkg.list_pkgs_/mnt_[]': None,
|
+ "pkg.list_pkgs_/mnt_[]": None,
|
||||||
+ 'pkg.list_pkgs_/mnt_[patterns]': None,
|
+ "pkg.list_pkgs_/mnt_[patterns]": None,
|
||||||
+ 'pkg.list_provides': None,
|
+ "pkg.list_provides": None,
|
||||||
+ 'pkg.other_data': None,
|
+ "pkg.other_data": None,
|
||||||
+ }
|
+ }
|
||||||
+ with patch.dict(zypper.__context__, context):
|
+ with patch.dict(zypper.__context__, context):
|
||||||
+ zypper._clean_cache()
|
+ zypper._clean_cache()
|
||||||
+ self.assertEqual(zypper.__context__, {'pkg.other_data': None})
|
+ self.assertEqual(zypper.__context__, {"pkg.other_data": None})
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,26 +1,28 @@
|
|||||||
From 6df4cef549665aad5b9e2af50eb06124a2bb0997 Mon Sep 17 00:00:00 2001
|
From c44b897eb1305c6b9c341fc16f729d2293ab24e4 Mon Sep 17 00:00:00 2001
|
||||||
From: Bo Maryniuk <bo@suse.de>
|
From: Bo Maryniuk <bo@suse.de>
|
||||||
Date: Tue, 17 Oct 2017 16:52:33 +0200
|
Date: Tue, 17 Oct 2017 16:52:33 +0200
|
||||||
Subject: [PATCH] Activate all beacons sources: config/pillar/grains
|
Subject: [PATCH] Activate all beacons sources: config/pillar/grains
|
||||||
|
|
||||||
---
|
---
|
||||||
salt/minion.py | 2 +-
|
salt/minion.py | 4 +---
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
1 file changed, 1 insertion(+), 3 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/minion.py b/salt/minion.py
|
diff --git a/salt/minion.py b/salt/minion.py
|
||||||
index 6a77d90185..457f485b0a 100644
|
index c255f37c26..4da665a130 100644
|
||||||
--- a/salt/minion.py
|
--- a/salt/minion.py
|
||||||
+++ b/salt/minion.py
|
+++ b/salt/minion.py
|
||||||
@@ -483,7 +483,7 @@ class MinionBase(object):
|
@@ -508,9 +508,7 @@ class MinionBase:
|
||||||
the pillar or grains changed
|
the pillar or grains changed
|
||||||
'''
|
"""
|
||||||
if 'config.merge' in functions:
|
if "config.merge" in functions:
|
||||||
- b_conf = functions['config.merge']('beacons', self.opts['beacons'], omit_opts=True)
|
- b_conf = functions["config.merge"](
|
||||||
+ b_conf = functions['config.merge']('beacons', self.opts['beacons'])
|
- "beacons", self.opts["beacons"], omit_opts=True
|
||||||
|
- )
|
||||||
|
+ b_conf = functions["config.merge"]("beacons", self.opts["beacons"])
|
||||||
if b_conf:
|
if b_conf:
|
||||||
return self.beacons.process(b_conf, self.opts['grains']) # pylint: disable=no-member
|
return self.beacons.process(
|
||||||
return []
|
b_conf, self.opts["grains"]
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From cd66b1e6636013440577a38a5a68729fec2f3f99 Mon Sep 17 00:00:00 2001
|
From 2e300c770c227cf394929b7d5d025d5c52f1ae2c Mon Sep 17 00:00:00 2001
|
||||||
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||||
<psuarezhernandez@suse.com>
|
<psuarezhernandez@suse.com>
|
||||||
Date: Mon, 14 May 2018 11:33:13 +0100
|
Date: Mon, 14 May 2018 11:33:13 +0100
|
||||||
@ -19,21 +19,119 @@ Refactor: use dict.setdefault instead if-else statement
|
|||||||
|
|
||||||
Allow removing only specific package versions with zypper and yum
|
Allow removing only specific package versions with zypper and yum
|
||||||
---
|
---
|
||||||
salt/states/pkg.py | 21 +++++++++++++++++++++
|
salt/states/pkg.py | 285 +++++++++++++++++++++++----------------------
|
||||||
1 file changed, 21 insertions(+)
|
1 file changed, 146 insertions(+), 139 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/states/pkg.py b/salt/states/pkg.py
|
diff --git a/salt/states/pkg.py b/salt/states/pkg.py
|
||||||
index a13d418400..c0fa2f6b69 100644
|
index 51b5a06e8f..a1b2a122bb 100644
|
||||||
--- a/salt/states/pkg.py
|
--- a/salt/states/pkg.py
|
||||||
+++ b/salt/states/pkg.py
|
+++ b/salt/states/pkg.py
|
||||||
@@ -450,6 +450,16 @@ def _find_remove_targets(name=None,
|
@@ -1,4 +1,3 @@
|
||||||
|
-# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Installation of packages using OS package managers such as yum or apt-get
|
||||||
|
=========================================================================
|
||||||
|
@@ -71,21 +70,16 @@ state module
|
||||||
|
used. This will be addressed in a future release of Salt.
|
||||||
|
"""
|
||||||
|
|
||||||
if __grains__['os'] == 'FreeBSD' and origin:
|
-# Import python libs
|
||||||
cver = [k for k, v in six.iteritems(cur_pkgs) if v['origin'] == pkgname]
|
-from __future__ import absolute_import, print_function, unicode_literals
|
||||||
+ elif __grains__['os_family'] == 'Suse':
|
|
||||||
|
import fnmatch
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
-# Import Salt libs
|
||||||
|
import salt.utils.pkg
|
||||||
|
import salt.utils.platform
|
||||||
|
import salt.utils.versions
|
||||||
|
from salt.exceptions import CommandExecutionError, MinionError, SaltInvocationError
|
||||||
|
-
|
||||||
|
-# Import 3rd-party libs
|
||||||
|
from salt.ext import six
|
||||||
|
from salt.modules.pkg_resource import _repack_pkgs
|
||||||
|
from salt.output import nested
|
||||||
|
@@ -323,7 +317,7 @@ def _find_download_targets(
|
||||||
|
"name": name,
|
||||||
|
"changes": {},
|
||||||
|
"result": True,
|
||||||
|
- "comment": "Version {0} of package '{1}' is already "
|
||||||
|
+ "comment": "Version {} of package '{}' is already "
|
||||||
|
"downloaded".format(version, name),
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -334,7 +328,7 @@ def _find_download_targets(
|
||||||
|
"name": name,
|
||||||
|
"changes": {},
|
||||||
|
"result": True,
|
||||||
|
- "comment": "Package {0} is already " "downloaded".format(name),
|
||||||
|
+ "comment": "Package {} is already " "downloaded".format(name),
|
||||||
|
}
|
||||||
|
|
||||||
|
version_spec = False
|
||||||
|
@@ -349,13 +343,13 @@ def _find_download_targets(
|
||||||
|
comments.append(
|
||||||
|
"The following package(s) were not found, and no "
|
||||||
|
"possible matches were found in the package db: "
|
||||||
|
- "{0}".format(", ".join(sorted(problems["no_suggest"])))
|
||||||
|
+ "{}".format(", ".join(sorted(problems["no_suggest"])))
|
||||||
|
)
|
||||||
|
if problems.get("suggest"):
|
||||||
|
- for pkgname, suggestions in six.iteritems(problems["suggest"]):
|
||||||
|
+ for pkgname, suggestions in problems["suggest"].items():
|
||||||
|
comments.append(
|
||||||
|
- "Package '{0}' not found (possible matches: "
|
||||||
|
- "{1})".format(pkgname, ", ".join(suggestions))
|
||||||
|
+ "Package '{}' not found (possible matches: "
|
||||||
|
+ "{})".format(pkgname, ", ".join(suggestions))
|
||||||
|
)
|
||||||
|
if comments:
|
||||||
|
if len(comments) > 1:
|
||||||
|
@@ -371,7 +365,7 @@ def _find_download_targets(
|
||||||
|
# Check current downloaded versions against specified versions
|
||||||
|
targets = {}
|
||||||
|
problems = []
|
||||||
|
- for pkgname, pkgver in six.iteritems(to_download):
|
||||||
|
+ for pkgname, pkgver in to_download.items():
|
||||||
|
cver = cur_pkgs.get(pkgname, {})
|
||||||
|
# Package not yet downloaded, so add to targets
|
||||||
|
if not cver:
|
||||||
|
@@ -401,7 +395,7 @@ def _find_download_targets(
|
||||||
|
|
||||||
|
if not targets:
|
||||||
|
# All specified packages are already downloaded
|
||||||
|
- msg = "All specified packages{0} are already downloaded".format(
|
||||||
|
+ msg = "All specified packages{} are already downloaded".format(
|
||||||
|
" (matching specified versions)" if version_spec else ""
|
||||||
|
)
|
||||||
|
return {"name": name, "changes": {}, "result": True, "comment": msg}
|
||||||
|
@@ -425,7 +419,7 @@ def _find_advisory_targets(name=None, advisory_ids=None, **kwargs):
|
||||||
|
"name": name,
|
||||||
|
"changes": {},
|
||||||
|
"result": True,
|
||||||
|
- "comment": "Advisory patch {0} is already " "installed".format(name),
|
||||||
|
+ "comment": "Advisory patch {} is already " "installed".format(name),
|
||||||
|
}
|
||||||
|
|
||||||
|
# Find out which advisory patches will be targeted in the call to pkg.install
|
||||||
|
@@ -477,12 +471,22 @@ def _find_remove_targets(
|
||||||
|
# Check current versions against specified versions
|
||||||
|
targets = []
|
||||||
|
problems = []
|
||||||
|
- for pkgname, pkgver in six.iteritems(to_remove):
|
||||||
|
+ for pkgname, pkgver in to_remove.items():
|
||||||
|
# FreeBSD pkg supports `openjdk` and `java/openjdk7` package names
|
||||||
|
origin = bool(re.search("/", pkgname))
|
||||||
|
|
||||||
|
if __grains__["os"] == "FreeBSD" and origin:
|
||||||
|
- cver = [k for k, v in six.iteritems(cur_pkgs) if v["origin"] == pkgname]
|
||||||
|
+ cver = [k for k, v in cur_pkgs.items() if v["origin"] == pkgname]
|
||||||
|
+ elif __grains__["os_family"] == "Suse":
|
||||||
+ # On SUSE systems. Zypper returns packages without "arch" in name
|
+ # On SUSE systems. Zypper returns packages without "arch" in name
|
||||||
+ try:
|
+ try:
|
||||||
+ namepart, archpart = pkgname.rsplit('.', 1)
|
+ namepart, archpart = pkgname.rsplit(".", 1)
|
||||||
+ except ValueError:
|
+ except ValueError:
|
||||||
+ cver = cur_pkgs.get(pkgname, [])
|
+ cver = cur_pkgs.get(pkgname, [])
|
||||||
+ else:
|
+ else:
|
||||||
@ -43,14 +141,162 @@ index a13d418400..c0fa2f6b69 100644
|
|||||||
else:
|
else:
|
||||||
cver = cur_pkgs.get(pkgname, [])
|
cver = cur_pkgs.get(pkgname, [])
|
||||||
|
|
||||||
@@ -856,6 +866,17 @@ def _verify_install(desired, new_pkgs, ignore_epoch=False, new_caps=None):
|
@@ -518,7 +522,7 @@ def _find_remove_targets(
|
||||||
cver = new_pkgs.get(pkgname.split('%')[0])
|
|
||||||
elif __grains__['os_family'] == 'Debian':
|
if not targets:
|
||||||
cver = new_pkgs.get(pkgname.split('=')[0])
|
# All specified packages are already absent
|
||||||
+ elif __grains__['os_family'] == 'Suse':
|
- msg = "All specified packages{0} are already absent".format(
|
||||||
|
+ msg = "All specified packages{} are already absent".format(
|
||||||
|
" (matching specified versions)" if version_spec else ""
|
||||||
|
)
|
||||||
|
return {"name": name, "changes": {}, "result": True, "comment": msg}
|
||||||
|
@@ -619,7 +623,7 @@ def _find_install_targets(
|
||||||
|
"name": name,
|
||||||
|
"changes": {},
|
||||||
|
"result": False,
|
||||||
|
- "comment": "Invalidly formatted '{0}' parameter. See "
|
||||||
|
+ "comment": "Invalidly formatted '{}' parameter. See "
|
||||||
|
"minion log.".format("pkgs" if pkgs else "sources"),
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -634,7 +638,7 @@ def _find_install_targets(
|
||||||
|
"name": name,
|
||||||
|
"changes": {},
|
||||||
|
"result": False,
|
||||||
|
- "comment": "Package {0} not found in the "
|
||||||
|
+ "comment": "Package {} not found in the "
|
||||||
|
"repository.".format(name),
|
||||||
|
}
|
||||||
|
if version is None:
|
||||||
|
@@ -656,7 +660,7 @@ def _find_install_targets(
|
||||||
|
origin = bool(re.search("/", name))
|
||||||
|
|
||||||
|
if __grains__["os"] == "FreeBSD" and origin:
|
||||||
|
- cver = [k for k, v in six.iteritems(cur_pkgs) if v["origin"] == name]
|
||||||
|
+ cver = [k for k, v in cur_pkgs.items() if v["origin"] == name]
|
||||||
|
else:
|
||||||
|
cver = cur_pkgs.get(name, [])
|
||||||
|
|
||||||
|
@@ -667,7 +671,7 @@ def _find_install_targets(
|
||||||
|
"name": name,
|
||||||
|
"changes": {},
|
||||||
|
"result": True,
|
||||||
|
- "comment": "Version {0} of package '{1}' is already "
|
||||||
|
+ "comment": "Version {} of package '{}' is already "
|
||||||
|
"installed".format(version, name),
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -678,7 +682,7 @@ def _find_install_targets(
|
||||||
|
"name": name,
|
||||||
|
"changes": {},
|
||||||
|
"result": True,
|
||||||
|
- "comment": "Package {0} is already " "installed".format(name),
|
||||||
|
+ "comment": "Package {} is already " "installed".format(name),
|
||||||
|
}
|
||||||
|
|
||||||
|
version_spec = False
|
||||||
|
@@ -687,21 +691,19 @@ def _find_install_targets(
|
||||||
|
# enforced. Takes extra time. Disable for improved performance
|
||||||
|
if not skip_suggestions:
|
||||||
|
# Perform platform-specific pre-flight checks
|
||||||
|
- not_installed = dict(
|
||||||
|
- [
|
||||||
|
- (name, version)
|
||||||
|
- for name, version in desired.items()
|
||||||
|
- if not (
|
||||||
|
- name in cur_pkgs
|
||||||
|
- and (
|
||||||
|
- version is None
|
||||||
|
- or _fulfills_version_string(
|
||||||
|
- cur_pkgs[name], version, ignore_epoch=ignore_epoch
|
||||||
|
- )
|
||||||
|
+ not_installed = {
|
||||||
|
+ name: version
|
||||||
|
+ for name, version in desired.items()
|
||||||
|
+ if not (
|
||||||
|
+ name in cur_pkgs
|
||||||
|
+ and (
|
||||||
|
+ version is None
|
||||||
|
+ or _fulfills_version_string(
|
||||||
|
+ cur_pkgs[name], version, ignore_epoch=ignore_epoch
|
||||||
|
)
|
||||||
|
)
|
||||||
|
- ]
|
||||||
|
- )
|
||||||
|
+ )
|
||||||
|
+ }
|
||||||
|
if not_installed:
|
||||||
|
try:
|
||||||
|
problems = _preflight_check(not_installed, **kwargs)
|
||||||
|
@@ -713,13 +715,13 @@ def _find_install_targets(
|
||||||
|
comments.append(
|
||||||
|
"The following package(s) were not found, and no "
|
||||||
|
"possible matches were found in the package db: "
|
||||||
|
- "{0}".format(", ".join(sorted(problems["no_suggest"])))
|
||||||
|
+ "{}".format(", ".join(sorted(problems["no_suggest"])))
|
||||||
|
)
|
||||||
|
if problems.get("suggest"):
|
||||||
|
- for pkgname, suggestions in six.iteritems(problems["suggest"]):
|
||||||
|
+ for pkgname, suggestions in problems["suggest"].items():
|
||||||
|
comments.append(
|
||||||
|
- "Package '{0}' not found (possible matches: "
|
||||||
|
- "{1})".format(pkgname, ", ".join(suggestions))
|
||||||
|
+ "Package '{}' not found (possible matches: "
|
||||||
|
+ "{})".format(pkgname, ", ".join(suggestions))
|
||||||
|
)
|
||||||
|
if comments:
|
||||||
|
if len(comments) > 1:
|
||||||
|
@@ -733,9 +735,7 @@ def _find_install_targets(
|
||||||
|
|
||||||
|
# Resolve the latest package version for any packages with "latest" in the
|
||||||
|
# package version
|
||||||
|
- wants_latest = (
|
||||||
|
- [] if sources else [x for x, y in six.iteritems(desired) if y == "latest"]
|
||||||
|
- )
|
||||||
|
+ wants_latest = [] if sources else [x for x, y in desired.items() if y == "latest"]
|
||||||
|
if wants_latest:
|
||||||
|
resolved_latest = __salt__["pkg.latest_version"](
|
||||||
|
*wants_latest, refresh=refresh, **kwargs
|
||||||
|
@@ -766,7 +766,7 @@ def _find_install_targets(
|
||||||
|
problems = []
|
||||||
|
warnings = []
|
||||||
|
failed_verify = False
|
||||||
|
- for package_name, version_string in six.iteritems(desired):
|
||||||
|
+ for package_name, version_string in desired.items():
|
||||||
|
cver = cur_pkgs.get(package_name, [])
|
||||||
|
if resolve_capabilities and not cver and package_name in cur_prov:
|
||||||
|
cver = cur_pkgs.get(cur_prov.get(package_name)[0], [])
|
||||||
|
@@ -795,12 +795,12 @@ def _find_install_targets(
|
||||||
|
problems.append(err.format(version_string, "file not found"))
|
||||||
|
continue
|
||||||
|
elif not os.path.exists(cached_path):
|
||||||
|
- problems.append("{0} does not exist on minion".format(version_string))
|
||||||
|
+ problems.append("{} does not exist on minion".format(version_string))
|
||||||
|
continue
|
||||||
|
source_info = __salt__["lowpkg.bin_pkg_info"](cached_path)
|
||||||
|
if source_info is None:
|
||||||
|
warnings.append(
|
||||||
|
- "Failed to parse metadata for {0}".format(version_string)
|
||||||
|
+ "Failed to parse metadata for {}".format(version_string)
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
@@ -923,13 +923,24 @@ def _verify_install(desired, new_pkgs, ignore_epoch=None, new_caps=None):
|
||||||
|
has_origin = "/" in pkgname
|
||||||
|
|
||||||
|
if __grains__["os"] == "FreeBSD" and has_origin:
|
||||||
|
- cver = [k for k, v in six.iteritems(new_pkgs) if v["origin"] == pkgname]
|
||||||
|
+ cver = [k for k, v in new_pkgs.items() if v["origin"] == pkgname]
|
||||||
|
elif __grains__["os"] == "MacOS" and has_origin:
|
||||||
|
cver = new_pkgs.get(pkgname, new_pkgs.get(pkgname.split("/")[-1]))
|
||||||
|
elif __grains__["os"] == "OpenBSD":
|
||||||
|
cver = new_pkgs.get(pkgname.split("%")[0])
|
||||||
|
elif __grains__["os_family"] == "Debian":
|
||||||
|
cver = new_pkgs.get(pkgname.split("=")[0])
|
||||||
|
+ elif __grains__["os_family"] == "Suse":
|
||||||
+ # On SUSE systems. Zypper returns packages without "arch" in name
|
+ # On SUSE systems. Zypper returns packages without "arch" in name
|
||||||
+ try:
|
+ try:
|
||||||
+ namepart, archpart = pkgname.rsplit('.', 1)
|
+ namepart, archpart = pkgname.rsplit(".", 1)
|
||||||
+ except ValueError:
|
+ except ValueError:
|
||||||
+ cver = new_pkgs.get(pkgname)
|
+ cver = new_pkgs.get(pkgname)
|
||||||
+ else:
|
+ else:
|
||||||
@ -61,7 +307,653 @@ index a13d418400..c0fa2f6b69 100644
|
|||||||
else:
|
else:
|
||||||
cver = new_pkgs.get(pkgname)
|
cver = new_pkgs.get(pkgname)
|
||||||
if not cver and pkgname in new_caps:
|
if not cver and pkgname in new_caps:
|
||||||
|
@@ -964,7 +975,7 @@ def _get_desired_pkg(name, desired):
|
||||||
|
oper = ""
|
||||||
|
else:
|
||||||
|
oper = "="
|
||||||
|
- return "{0}{1}{2}".format(name, oper, "" if not desired[name] else desired[name])
|
||||||
|
+ return "{}{}{}".format(name, oper, "" if not desired[name] else desired[name])
|
||||||
|
|
||||||
|
|
||||||
|
def _preflight_check(desired, fromrepo, **kwargs):
|
||||||
|
@@ -1709,8 +1720,8 @@ def installed(
|
||||||
|
"comment": "pkg.verify not implemented",
|
||||||
|
}
|
||||||
|
|
||||||
|
- if not isinstance(version, six.string_types) and version is not None:
|
||||||
|
- version = six.text_type(version)
|
||||||
|
+ if not isinstance(version, str) and version is not None:
|
||||||
|
+ version = str(version)
|
||||||
|
|
||||||
|
kwargs["allow_updates"] = allow_updates
|
||||||
|
|
||||||
|
@@ -1754,7 +1765,7 @@ def installed(
|
||||||
|
"name": name,
|
||||||
|
"changes": {},
|
||||||
|
"result": False,
|
||||||
|
- "comment": six.text_type(exc),
|
||||||
|
+ "comment": str(exc),
|
||||||
|
}
|
||||||
|
|
||||||
|
if "result" in hold_ret and not hold_ret["result"]:
|
||||||
|
@@ -1763,7 +1774,7 @@ def installed(
|
||||||
|
"changes": {},
|
||||||
|
"result": False,
|
||||||
|
"comment": "An error was encountered while "
|
||||||
|
- "holding/unholding package(s): {0}".format(hold_ret["comment"]),
|
||||||
|
+ "holding/unholding package(s): {}".format(hold_ret["comment"]),
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
modified_hold = [
|
||||||
|
@@ -1779,16 +1790,16 @@ def installed(
|
||||||
|
]
|
||||||
|
|
||||||
|
for i in modified_hold:
|
||||||
|
- result["comment"] += ".\n{0}".format(i["comment"])
|
||||||
|
+ result["comment"] += ".\n{}".format(i["comment"])
|
||||||
|
result["result"] = i["result"]
|
||||||
|
result["changes"][i["name"]] = i["changes"]
|
||||||
|
|
||||||
|
for i in not_modified_hold:
|
||||||
|
- result["comment"] += ".\n{0}".format(i["comment"])
|
||||||
|
+ result["comment"] += ".\n{}".format(i["comment"])
|
||||||
|
result["result"] = i["result"]
|
||||||
|
|
||||||
|
for i in failed_hold:
|
||||||
|
- result["comment"] += ".\n{0}".format(i["comment"])
|
||||||
|
+ result["comment"] += ".\n{}".format(i["comment"])
|
||||||
|
result["result"] = i["result"]
|
||||||
|
return result
|
||||||
|
|
||||||
|
@@ -1805,8 +1816,8 @@ def installed(
|
||||||
|
|
||||||
|
# Remove any targets not returned by _find_install_targets
|
||||||
|
if pkgs:
|
||||||
|
- pkgs = [dict([(x, y)]) for x, y in six.iteritems(targets)]
|
||||||
|
- pkgs.extend([dict([(x, y)]) for x, y in six.iteritems(to_reinstall)])
|
||||||
|
+ pkgs = [dict([(x, y)]) for x, y in targets.items()]
|
||||||
|
+ pkgs.extend([dict([(x, y)]) for x, y in to_reinstall.items()])
|
||||||
|
elif sources:
|
||||||
|
oldsources = sources
|
||||||
|
sources = [x for x in oldsources if next(iter(list(x.keys()))) in targets]
|
||||||
|
@@ -1823,12 +1834,12 @@ def installed(
|
||||||
|
summary = ", ".join([_get_desired_pkg(x, targets) for x in targets])
|
||||||
|
comment.append(
|
||||||
|
"The following packages would be "
|
||||||
|
- "installed/updated: {0}".format(summary)
|
||||||
|
+ "installed/updated: {}".format(summary)
|
||||||
|
)
|
||||||
|
if to_unpurge:
|
||||||
|
comment.append(
|
||||||
|
"The following packages would have their selection status "
|
||||||
|
- "changed from 'purge' to 'install': {0}".format(", ".join(to_unpurge))
|
||||||
|
+ "changed from 'purge' to 'install': {}".format(", ".join(to_unpurge))
|
||||||
|
)
|
||||||
|
if to_reinstall:
|
||||||
|
# Add a comment for each package in to_reinstall with its
|
||||||
|
@@ -1852,7 +1863,7 @@ def installed(
|
||||||
|
else:
|
||||||
|
pkgstr = _get_desired_pkg(reinstall_pkg, to_reinstall)
|
||||||
|
comment.append(
|
||||||
|
- "Package '{0}' would be reinstalled because the "
|
||||||
|
+ "Package '{}' would be reinstalled because the "
|
||||||
|
"following files have been altered:".format(pkgstr)
|
||||||
|
)
|
||||||
|
comment.append(_nested_output(altered_files[reinstall_pkg]))
|
||||||
|
@@ -1896,7 +1907,7 @@ def installed(
|
||||||
|
ret["changes"] = {}
|
||||||
|
ret["comment"] = (
|
||||||
|
"An error was encountered while installing "
|
||||||
|
- "package(s): {0}".format(exc)
|
||||||
|
+ "package(s): {}".format(exc)
|
||||||
|
)
|
||||||
|
if warnings:
|
||||||
|
ret.setdefault("warnings", []).extend(warnings)
|
||||||
|
@@ -1907,7 +1918,7 @@ def installed(
|
||||||
|
|
||||||
|
if isinstance(pkg_ret, dict):
|
||||||
|
changes["installed"].update(pkg_ret)
|
||||||
|
- elif isinstance(pkg_ret, six.string_types):
|
||||||
|
+ elif isinstance(pkg_ret, str):
|
||||||
|
comment.append(pkg_ret)
|
||||||
|
# Code below will be looking for a dictionary. If this is a string
|
||||||
|
# it means that there was an exception raised and that no packages
|
||||||
|
@@ -1921,7 +1932,7 @@ def installed(
|
||||||
|
action = "pkg.hold" if kwargs["hold"] else "pkg.unhold"
|
||||||
|
hold_ret = __salt__[action](name=name, pkgs=desired)
|
||||||
|
except (CommandExecutionError, SaltInvocationError) as exc:
|
||||||
|
- comment.append(six.text_type(exc))
|
||||||
|
+ comment.append(str(exc))
|
||||||
|
ret = {
|
||||||
|
"name": name,
|
||||||
|
"changes": changes,
|
||||||
|
@@ -1938,7 +1949,7 @@ def installed(
|
||||||
|
"changes": {},
|
||||||
|
"result": False,
|
||||||
|
"comment": "An error was encountered while "
|
||||||
|
- "holding/unholding package(s): {0}".format(hold_ret["comment"]),
|
||||||
|
+ "holding/unholding package(s): {}".format(hold_ret["comment"]),
|
||||||
|
}
|
||||||
|
if warnings:
|
||||||
|
ret.setdefault("warnings", []).extend(warnings)
|
||||||
|
@@ -1996,11 +2007,11 @@ def installed(
|
||||||
|
summary = ", ".join([_get_desired_pkg(x, desired) for x in modified])
|
||||||
|
if len(summary) < 20:
|
||||||
|
comment.append(
|
||||||
|
- "The following packages were installed/updated: " "{0}".format(summary)
|
||||||
|
+ "The following packages were installed/updated: " "{}".format(summary)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
comment.append(
|
||||||
|
- "{0} targeted package{1} {2} installed/updated.".format(
|
||||||
|
+ "{} targeted package{} {} installed/updated.".format(
|
||||||
|
len(modified),
|
||||||
|
"s" if len(modified) > 1 else "",
|
||||||
|
"were" if len(modified) > 1 else "was",
|
||||||
|
@@ -2014,14 +2025,14 @@ def installed(
|
||||||
|
comment.append(i["comment"])
|
||||||
|
if len(changes[change_name]["new"]) > 0:
|
||||||
|
changes[change_name]["new"] += "\n"
|
||||||
|
- changes[change_name]["new"] += "{0}".format(i["changes"]["new"])
|
||||||
|
+ changes[change_name]["new"] += "{}".format(i["changes"]["new"])
|
||||||
|
if len(changes[change_name]["old"]) > 0:
|
||||||
|
changes[change_name]["old"] += "\n"
|
||||||
|
- changes[change_name]["old"] += "{0}".format(i["changes"]["old"])
|
||||||
|
+ changes[change_name]["old"] += "{}".format(i["changes"]["old"])
|
||||||
|
else:
|
||||||
|
comment.append(i["comment"])
|
||||||
|
changes[change_name] = {}
|
||||||
|
- changes[change_name]["new"] = "{0}".format(i["changes"]["new"])
|
||||||
|
+ changes[change_name]["new"] = "{}".format(i["changes"]["new"])
|
||||||
|
|
||||||
|
# Any requested packages that were not targeted for install or reinstall
|
||||||
|
if not_modified:
|
||||||
|
@@ -2031,11 +2042,11 @@ def installed(
|
||||||
|
summary = ", ".join([_get_desired_pkg(x, desired) for x in not_modified])
|
||||||
|
if len(not_modified) <= 20:
|
||||||
|
comment.append(
|
||||||
|
- "The following packages were already installed: " "{0}".format(summary)
|
||||||
|
+ "The following packages were already installed: " "{}".format(summary)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
comment.append(
|
||||||
|
- "{0} targeted package{1} {2} already installed".format(
|
||||||
|
+ "{} targeted package{} {} already installed".format(
|
||||||
|
len(not_modified),
|
||||||
|
"s" if len(not_modified) > 1 else "",
|
||||||
|
"were" if len(not_modified) > 1 else "was",
|
||||||
|
@@ -2054,7 +2065,7 @@ def installed(
|
||||||
|
else:
|
||||||
|
summary = ", ".join([_get_desired_pkg(x, desired) for x in failed])
|
||||||
|
comment.insert(
|
||||||
|
- 0, "The following packages failed to " "install/update: {0}".format(summary)
|
||||||
|
+ 0, "The following packages failed to " "install/update: {}".format(summary)
|
||||||
|
)
|
||||||
|
result = False
|
||||||
|
|
||||||
|
@@ -2118,7 +2129,7 @@ def installed(
|
||||||
|
pkgstr = modified_pkg
|
||||||
|
else:
|
||||||
|
pkgstr = _get_desired_pkg(modified_pkg, desired)
|
||||||
|
- msg = "Package {0} was reinstalled.".format(pkgstr)
|
||||||
|
+ msg = "Package {} was reinstalled.".format(pkgstr)
|
||||||
|
if modified_pkg in altered_files:
|
||||||
|
msg += " The following files were remediated:"
|
||||||
|
comment.append(msg)
|
||||||
|
@@ -2133,7 +2144,7 @@ def installed(
|
||||||
|
pkgstr = failed_pkg
|
||||||
|
else:
|
||||||
|
pkgstr = _get_desired_pkg(failed_pkg, desired)
|
||||||
|
- msg = "Reinstall was not successful for package {0}.".format(pkgstr)
|
||||||
|
+ msg = "Reinstall was not successful for package {}.".format(pkgstr)
|
||||||
|
if failed_pkg in altered_files:
|
||||||
|
msg += " The following files could not be remediated:"
|
||||||
|
comment.append(msg)
|
||||||
|
@@ -2274,12 +2285,12 @@ def downloaded(
|
||||||
|
ret["result"] = False
|
||||||
|
ret[
|
||||||
|
"comment"
|
||||||
|
- ] = "An error was encountered while checking targets: " "{0}".format(targets)
|
||||||
|
+ ] = "An error was encountered while checking targets: " "{}".format(targets)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
if __opts__["test"]:
|
||||||
|
summary = ", ".join(targets)
|
||||||
|
- ret["comment"] = "The following packages would be " "downloaded: {0}".format(
|
||||||
|
+ ret["comment"] = "The following packages would be " "downloaded: {}".format(
|
||||||
|
summary
|
||||||
|
)
|
||||||
|
return ret
|
||||||
|
@@ -2306,7 +2317,7 @@ def downloaded(
|
||||||
|
ret["changes"] = {}
|
||||||
|
ret["comment"] = (
|
||||||
|
"An error was encountered while downloading "
|
||||||
|
- "package(s): {0}".format(exc)
|
||||||
|
+ "package(s): {}".format(exc)
|
||||||
|
)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
@@ -2316,13 +2327,13 @@ def downloaded(
|
||||||
|
if failed:
|
||||||
|
summary = ", ".join([_get_desired_pkg(x, targets) for x in failed])
|
||||||
|
ret["result"] = False
|
||||||
|
- ret["comment"] = "The following packages failed to " "download: {0}".format(
|
||||||
|
+ ret["comment"] = "The following packages failed to " "download: {}".format(
|
||||||
|
summary
|
||||||
|
)
|
||||||
|
|
||||||
|
if not ret["changes"] and not ret["comment"]:
|
||||||
|
ret["result"] = True
|
||||||
|
- ret["comment"] = "Packages downloaded: " "{0}".format(", ".join(targets))
|
||||||
|
+ ret["comment"] = "Packages downloaded: " "{}".format(", ".join(targets))
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
@@ -2382,14 +2393,14 @@ def patch_installed(name, advisory_ids=None, downloadonly=None, **kwargs):
|
||||||
|
ret["result"] = False
|
||||||
|
ret[
|
||||||
|
"comment"
|
||||||
|
- ] = "An error was encountered while checking targets: " "{0}".format(targets)
|
||||||
|
+ ] = "An error was encountered while checking targets: " "{}".format(targets)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
if __opts__["test"]:
|
||||||
|
summary = ", ".join(targets)
|
||||||
|
ret[
|
||||||
|
"comment"
|
||||||
|
- ] = "The following advisory patches would be " "downloaded: {0}".format(summary)
|
||||||
|
+ ] = "The following advisory patches would be " "downloaded: {}".format(summary)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
try:
|
||||||
|
@@ -2408,7 +2419,7 @@ def patch_installed(name, advisory_ids=None, downloadonly=None, **kwargs):
|
||||||
|
ret["changes"] = {}
|
||||||
|
ret["comment"] = (
|
||||||
|
"An error was encountered while downloading "
|
||||||
|
- "package(s): {0}".format(exc)
|
||||||
|
+ "package(s): {}".format(exc)
|
||||||
|
)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
@@ -2417,7 +2428,7 @@ def patch_installed(name, advisory_ids=None, downloadonly=None, **kwargs):
|
||||||
|
ret["result"] = True
|
||||||
|
ret["comment"] = (
|
||||||
|
"Advisory patch is not needed or related packages "
|
||||||
|
- "are already {0}".format(status)
|
||||||
|
+ "are already {}".format(status)
|
||||||
|
)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
@@ -2674,7 +2685,7 @@ def latest(
|
||||||
|
"changes": {},
|
||||||
|
"result": False,
|
||||||
|
"comment": "An error was encountered while checking the "
|
||||||
|
- "newest available version of package(s): {0}".format(exc),
|
||||||
|
+ "newest available version of package(s): {}".format(exc),
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
@@ -2683,9 +2694,9 @@ def latest(
|
||||||
|
return {"name": name, "changes": {}, "result": False, "comment": exc.strerror}
|
||||||
|
|
||||||
|
# Repack the cur/avail data if only a single package is being checked
|
||||||
|
- if isinstance(cur, six.string_types):
|
||||||
|
+ if isinstance(cur, str):
|
||||||
|
cur = {desired_pkgs[0]: cur}
|
||||||
|
- if isinstance(avail, six.string_types):
|
||||||
|
+ if isinstance(avail, str):
|
||||||
|
avail = {desired_pkgs[0]: avail}
|
||||||
|
|
||||||
|
targets = {}
|
||||||
|
@@ -2695,7 +2706,7 @@ def latest(
|
||||||
|
# Package either a) is up-to-date, or b) does not exist
|
||||||
|
if not cur.get(pkg):
|
||||||
|
# Package does not exist
|
||||||
|
- msg = "No information found for '{0}'.".format(pkg)
|
||||||
|
+ msg = "No information found for '{}'.".format(pkg)
|
||||||
|
log.error(msg)
|
||||||
|
problems.append(msg)
|
||||||
|
elif (
|
||||||
|
@@ -2741,12 +2752,12 @@ def latest(
|
||||||
|
comments.append(
|
||||||
|
"The following packages are already up-to-date: "
|
||||||
|
+ ", ".join(
|
||||||
|
- ["{0} ({1})".format(x, cur[x]) for x in sorted(up_to_date)]
|
||||||
|
+ ["{} ({})".format(x, cur[x]) for x in sorted(up_to_date)]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
comments.append(
|
||||||
|
- "{0} packages are already up-to-date".format(up_to_date_count)
|
||||||
|
+ "{} packages are already up-to-date".format(up_to_date_count)
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
@@ -2784,7 +2795,7 @@ def latest(
|
||||||
|
"changes": {},
|
||||||
|
"result": False,
|
||||||
|
"comment": "An error was encountered while installing "
|
||||||
|
- "package(s): {0}".format(exc),
|
||||||
|
+ "package(s): {}".format(exc),
|
||||||
|
}
|
||||||
|
|
||||||
|
if changes:
|
||||||
|
@@ -2800,7 +2811,7 @@ def latest(
|
||||||
|
|
||||||
|
comments = []
|
||||||
|
if failed:
|
||||||
|
- msg = "The following packages failed to update: " "{0}".format(
|
||||||
|
+ msg = "The following packages failed to update: " "{}".format(
|
||||||
|
", ".join(sorted(failed))
|
||||||
|
)
|
||||||
|
comments.append(msg)
|
||||||
|
@@ -2808,19 +2819,17 @@ def latest(
|
||||||
|
msg = (
|
||||||
|
"The following packages were successfully "
|
||||||
|
"installed/upgraded: "
|
||||||
|
- "{0}".format(", ".join(sorted(successful)))
|
||||||
|
+ "{}".format(", ".join(sorted(successful)))
|
||||||
|
)
|
||||||
|
comments.append(msg)
|
||||||
|
if up_to_date:
|
||||||
|
if len(up_to_date) <= 10:
|
||||||
|
msg = (
|
||||||
|
"The following packages were already up-to-date: "
|
||||||
|
- "{0}".format(", ".join(sorted(up_to_date)))
|
||||||
|
+ "{}".format(", ".join(sorted(up_to_date)))
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
- msg = "{0} packages were already up-to-date ".format(
|
||||||
|
- len(up_to_date)
|
||||||
|
- )
|
||||||
|
+ msg = "{} packages were already up-to-date ".format(len(up_to_date))
|
||||||
|
comments.append(msg)
|
||||||
|
|
||||||
|
return {
|
||||||
|
@@ -2832,18 +2841,18 @@ def latest(
|
||||||
|
else:
|
||||||
|
if len(targets) > 10:
|
||||||
|
comment = (
|
||||||
|
- "{0} targeted packages failed to update. "
|
||||||
|
+ "{} targeted packages failed to update. "
|
||||||
|
"See debug log for details.".format(len(targets))
|
||||||
|
)
|
||||||
|
elif len(targets) > 1:
|
||||||
|
comment = (
|
||||||
|
"The following targeted packages failed to update. "
|
||||||
|
- "See debug log for details: ({0}).".format(
|
||||||
|
+ "See debug log for details: ({}).".format(
|
||||||
|
", ".join(sorted(targets))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
- comment = "Package {0} failed to " "update.".format(
|
||||||
|
+ comment = "Package {} failed to " "update.".format(
|
||||||
|
next(iter(list(targets.keys())))
|
||||||
|
)
|
||||||
|
if up_to_date:
|
||||||
|
@@ -2851,10 +2860,10 @@ def latest(
|
||||||
|
comment += (
|
||||||
|
" The following packages were already "
|
||||||
|
"up-to-date: "
|
||||||
|
- "{0}".format(", ".join(sorted(up_to_date)))
|
||||||
|
+ "{}".format(", ".join(sorted(up_to_date)))
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
- comment += "{0} packages were already " "up-to-date".format(
|
||||||
|
+ comment += "{} packages were already " "up-to-date".format(
|
||||||
|
len(up_to_date)
|
||||||
|
)
|
||||||
|
|
||||||
|
@@ -2866,13 +2875,13 @@ def latest(
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
if len(desired_pkgs) > 10:
|
||||||
|
- comment = "All {0} packages are up-to-date.".format(len(desired_pkgs))
|
||||||
|
+ comment = "All {} packages are up-to-date.".format(len(desired_pkgs))
|
||||||
|
elif len(desired_pkgs) > 1:
|
||||||
|
- comment = "All packages are up-to-date " "({0}).".format(
|
||||||
|
+ comment = "All packages are up-to-date " "({}).".format(
|
||||||
|
", ".join(sorted(desired_pkgs))
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
- comment = "Package {0} is already " "up-to-date".format(desired_pkgs[0])
|
||||||
|
+ comment = "Package {} is already " "up-to-date".format(desired_pkgs[0])
|
||||||
|
|
||||||
|
return {"name": name, "changes": {}, "result": True, "comment": comment}
|
||||||
|
|
||||||
|
@@ -2894,8 +2903,7 @@ def _uninstall(
|
||||||
|
"name": name,
|
||||||
|
"changes": {},
|
||||||
|
"result": False,
|
||||||
|
- "comment": "Invalid action '{0}'. "
|
||||||
|
- "This is probably a bug.".format(action),
|
||||||
|
+ "comment": "Invalid action '{}'. " "This is probably a bug.".format(action),
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
@@ -2908,7 +2916,7 @@ def _uninstall(
|
||||||
|
"changes": {},
|
||||||
|
"result": False,
|
||||||
|
"comment": "An error was encountered while parsing targets: "
|
||||||
|
- "{0}".format(exc),
|
||||||
|
+ "{}".format(exc),
|
||||||
|
}
|
||||||
|
targets = _find_remove_targets(
|
||||||
|
name, version, pkgs, normalize, ignore_epoch=ignore_epoch, **kwargs
|
||||||
|
@@ -2921,7 +2929,7 @@ def _uninstall(
|
||||||
|
"changes": {},
|
||||||
|
"result": False,
|
||||||
|
"comment": "An error was encountered while checking targets: "
|
||||||
|
- "{0}".format(targets),
|
||||||
|
+ "{}".format(targets),
|
||||||
|
}
|
||||||
|
if action == "purge":
|
||||||
|
old_removed = __salt__["pkg.list_pkgs"](
|
||||||
|
@@ -2936,7 +2944,7 @@ def _uninstall(
|
||||||
|
"changes": {},
|
||||||
|
"result": True,
|
||||||
|
"comment": "None of the targeted packages are installed"
|
||||||
|
- "{0}".format(" or partially installed" if action == "purge" else ""),
|
||||||
|
+ "{}".format(" or partially installed" if action == "purge" else ""),
|
||||||
|
}
|
||||||
|
|
||||||
|
if __opts__["test"]:
|
||||||
|
@@ -2944,11 +2952,11 @@ def _uninstall(
|
||||||
|
"name": name,
|
||||||
|
"changes": {},
|
||||||
|
"result": None,
|
||||||
|
- "comment": "The following packages will be {0}d: "
|
||||||
|
- "{1}.".format(action, ", ".join(targets)),
|
||||||
|
+ "comment": "The following packages will be {}d: "
|
||||||
|
+ "{}.".format(action, ", ".join(targets)),
|
||||||
|
}
|
||||||
|
|
||||||
|
- changes = __salt__["pkg.{0}".format(action)](
|
||||||
|
+ changes = __salt__["pkg.{}".format(action)](
|
||||||
|
name, pkgs=pkgs, version=version, **kwargs
|
||||||
|
)
|
||||||
|
new = __salt__["pkg.list_pkgs"](versions_as_list=True, **kwargs)
|
||||||
|
@@ -2975,8 +2983,8 @@ def _uninstall(
|
||||||
|
"name": name,
|
||||||
|
"changes": changes,
|
||||||
|
"result": False,
|
||||||
|
- "comment": "The following packages failed to {0}: "
|
||||||
|
- "{1}.".format(action, ", ".join(failed)),
|
||||||
|
+ "comment": "The following packages failed to {}: "
|
||||||
|
+ "{}.".format(action, ", ".join(failed)),
|
||||||
|
}
|
||||||
|
|
||||||
|
comments = []
|
||||||
|
@@ -2984,14 +2992,13 @@ def _uninstall(
|
||||||
|
if not_installed:
|
||||||
|
comments.append(
|
||||||
|
"The following packages were not installed: "
|
||||||
|
- "{0}".format(", ".join(not_installed))
|
||||||
|
+ "{}".format(", ".join(not_installed))
|
||||||
|
)
|
||||||
|
comments.append(
|
||||||
|
- "The following packages were {0}d: "
|
||||||
|
- "{1}.".format(action, ", ".join(targets))
|
||||||
|
+ "The following packages were {}d: " "{}.".format(action, ", ".join(targets))
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
- comments.append("All targeted packages were {0}d.".format(action))
|
||||||
|
+ comments.append("All targeted packages were {}d.".format(action))
|
||||||
|
|
||||||
|
return {
|
||||||
|
"name": name,
|
||||||
|
@@ -3089,7 +3096,7 @@ def removed(name, version=None, pkgs=None, normalize=True, ignore_epoch=None, **
|
||||||
|
ret["changes"] = {}
|
||||||
|
ret[
|
||||||
|
"comment"
|
||||||
|
- ] = "An error was encountered while removing " "package(s): {0}".format(exc)
|
||||||
|
+ ] = "An error was encountered while removing " "package(s): {}".format(exc)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
@@ -3181,7 +3188,7 @@ def purged(name, version=None, pkgs=None, normalize=True, ignore_epoch=None, **k
|
||||||
|
ret["changes"] = {}
|
||||||
|
ret[
|
||||||
|
"comment"
|
||||||
|
- ] = "An error was encountered while purging " "package(s): {0}".format(exc)
|
||||||
|
+ ] = "An error was encountered while purging " "package(s): {}".format(exc)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
@@ -3247,17 +3254,17 @@ def uptodate(name, refresh=False, pkgs=None, **kwargs):
|
||||||
|
"new": pkgver,
|
||||||
|
"old": __salt__["pkg.version"](pkgname, **kwargs),
|
||||||
|
}
|
||||||
|
- for pkgname, pkgver in six.iteritems(packages)
|
||||||
|
+ for pkgname, pkgver in packages.items()
|
||||||
|
}
|
||||||
|
if isinstance(pkgs, list):
|
||||||
|
packages = [pkg for pkg in packages if pkg in pkgs]
|
||||||
|
expected = {
|
||||||
|
pkgname: pkgver
|
||||||
|
- for pkgname, pkgver in six.iteritems(expected)
|
||||||
|
+ for pkgname, pkgver in expected.items()
|
||||||
|
if pkgname in pkgs
|
||||||
|
}
|
||||||
|
except Exception as exc: # pylint: disable=broad-except
|
||||||
|
- ret["comment"] = six.text_type(exc)
|
||||||
|
+ ret["comment"] = str(exc)
|
||||||
|
return ret
|
||||||
|
else:
|
||||||
|
ret["comment"] = "refresh must be either True or False"
|
||||||
|
@@ -3284,16 +3291,16 @@ def uptodate(name, refresh=False, pkgs=None, **kwargs):
|
||||||
|
ret["changes"] = {}
|
||||||
|
ret[
|
||||||
|
"comment"
|
||||||
|
- ] = "An error was encountered while updating " "packages: {0}".format(exc)
|
||||||
|
+ ] = "An error was encountered while updating " "packages: {}".format(exc)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
# If a package list was provided, ensure those packages were updated
|
||||||
|
missing = []
|
||||||
|
if isinstance(pkgs, list):
|
||||||
|
- missing = [pkg for pkg in six.iterkeys(expected) if pkg not in ret["changes"]]
|
||||||
|
+ missing = [pkg for pkg in expected.keys() if pkg not in ret["changes"]]
|
||||||
|
|
||||||
|
if missing:
|
||||||
|
- ret["comment"] = "The following package(s) failed to update: {0}".format(
|
||||||
|
+ ret["comment"] = "The following package(s) failed to update: {}".format(
|
||||||
|
", ".join(missing)
|
||||||
|
)
|
||||||
|
ret["result"] = False
|
||||||
|
@@ -3362,8 +3369,8 @@ def group_installed(name, skip=None, include=None, **kwargs):
|
||||||
|
ret["comment"] = "skip must be formatted as a list"
|
||||||
|
return ret
|
||||||
|
for idx, item in enumerate(skip):
|
||||||
|
- if not isinstance(item, six.string_types):
|
||||||
|
- skip[idx] = six.text_type(item)
|
||||||
|
+ if not isinstance(item, str):
|
||||||
|
+ skip[idx] = str(item)
|
||||||
|
|
||||||
|
if include is None:
|
||||||
|
include = []
|
||||||
|
@@ -3372,15 +3379,15 @@ def group_installed(name, skip=None, include=None, **kwargs):
|
||||||
|
ret["comment"] = "include must be formatted as a list"
|
||||||
|
return ret
|
||||||
|
for idx, item in enumerate(include):
|
||||||
|
- if not isinstance(item, six.string_types):
|
||||||
|
- include[idx] = six.text_type(item)
|
||||||
|
+ if not isinstance(item, str):
|
||||||
|
+ include[idx] = str(item)
|
||||||
|
|
||||||
|
try:
|
||||||
|
diff = __salt__["pkg.group_diff"](name)
|
||||||
|
except CommandExecutionError as err:
|
||||||
|
ret["comment"] = (
|
||||||
|
"An error was encountered while installing/updating "
|
||||||
|
- "group '{0}': {1}.".format(name, err)
|
||||||
|
+ "group '{}': {}.".format(name, err)
|
||||||
|
)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
@@ -3390,7 +3397,7 @@ def group_installed(name, skip=None, include=None, **kwargs):
|
||||||
|
if invalid_skip:
|
||||||
|
ret[
|
||||||
|
"comment"
|
||||||
|
- ] = "The following mandatory packages cannot be skipped: {0}".format(
|
||||||
|
+ ] = "The following mandatory packages cannot be skipped: {}".format(
|
||||||
|
", ".join(invalid_skip)
|
||||||
|
)
|
||||||
|
return ret
|
||||||
|
@@ -3401,7 +3408,7 @@ def group_installed(name, skip=None, include=None, **kwargs):
|
||||||
|
|
||||||
|
if not targets:
|
||||||
|
ret["result"] = True
|
||||||
|
- ret["comment"] = "Group '{0}' is already installed".format(name)
|
||||||
|
+ ret["comment"] = "Group '{}' is already installed".format(name)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
partially_installed = (
|
||||||
|
@@ -3415,9 +3422,9 @@ def group_installed(name, skip=None, include=None, **kwargs):
|
||||||
|
if partially_installed:
|
||||||
|
ret[
|
||||||
|
"comment"
|
||||||
|
- ] = "Group '{0}' is partially installed and will be updated".format(name)
|
||||||
|
+ ] = "Group '{}' is partially installed and will be updated".format(name)
|
||||||
|
else:
|
||||||
|
- ret["comment"] = "Group '{0}' will be installed".format(name)
|
||||||
|
+ ret["comment"] = "Group '{}' will be installed".format(name)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
try:
|
||||||
|
@@ -3432,19 +3439,19 @@ def group_installed(name, skip=None, include=None, **kwargs):
|
||||||
|
ret["changes"] = {}
|
||||||
|
ret["comment"] = (
|
||||||
|
"An error was encountered while "
|
||||||
|
- "installing/updating group '{0}': {1}".format(name, exc)
|
||||||
|
+ "installing/updating group '{}': {}".format(name, exc)
|
||||||
|
)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
failed = [x for x in targets if x not in __salt__["pkg.list_pkgs"](**kwargs)]
|
||||||
|
if failed:
|
||||||
|
- ret["comment"] = "Failed to install the following packages: {0}".format(
|
||||||
|
+ ret["comment"] = "Failed to install the following packages: {}".format(
|
||||||
|
", ".join(failed)
|
||||||
|
)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
ret["result"] = True
|
||||||
|
- ret["comment"] = "Group '{0}' was {1}".format(
|
||||||
|
+ ret["comment"] = "Group '{}' was {}".format(
|
||||||
|
name, "updated" if partially_installed else "installed"
|
||||||
|
)
|
||||||
|
return ret
|
||||||
|
@@ -3561,6 +3568,6 @@ def mod_watch(name, **kwargs):
|
||||||
|
return {
|
||||||
|
"name": name,
|
||||||
|
"changes": {},
|
||||||
|
- "comment": "pkg.{0} does not work with the watch requisite".format(sfun),
|
||||||
|
+ "comment": "pkg.{} does not work with the watch requisite".format(sfun),
|
||||||
|
"result": False,
|
||||||
|
}
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From acf0b24353d831dcc2c5b292f99480938f5ecd93 Mon Sep 17 00:00:00 2001
|
From d5569023c64a3fcec57a7aa6823ee94e8be91b3d Mon Sep 17 00:00:00 2001
|
||||||
From: =?UTF-8?q?Julio=20Gonz=C3=A1lez=20Gil?=
|
From: =?UTF-8?q?Julio=20Gonz=C3=A1lez=20Gil?=
|
||||||
<juliogonzalez@users.noreply.github.com>
|
<juliogonzalez@users.noreply.github.com>
|
||||||
Date: Wed, 12 Feb 2020 10:05:45 +0100
|
Date: Wed, 12 Feb 2020 10:05:45 +0100
|
||||||
@ -11,49 +11,49 @@ Subject: [PATCH] Add Astra Linux Common Edition to the OS Family list
|
|||||||
2 files changed, 21 insertions(+)
|
2 files changed, 21 insertions(+)
|
||||||
|
|
||||||
diff --git a/salt/grains/core.py b/salt/grains/core.py
|
diff --git a/salt/grains/core.py b/salt/grains/core.py
|
||||||
index 20950988d9..f410985198 100644
|
index 5dff6ecfd4..5634327623 100644
|
||||||
--- a/salt/grains/core.py
|
--- a/salt/grains/core.py
|
||||||
+++ b/salt/grains/core.py
|
+++ b/salt/grains/core.py
|
||||||
@@ -1523,6 +1523,7 @@ _OS_FAMILY_MAP = {
|
@@ -1618,6 +1618,7 @@ _OS_FAMILY_MAP = {
|
||||||
'Funtoo': 'Gentoo',
|
"Funtoo": "Gentoo",
|
||||||
'AIX': 'AIX',
|
"AIX": "AIX",
|
||||||
'TurnKey': 'Debian',
|
"TurnKey": "Debian",
|
||||||
+ 'AstraLinuxCE': 'Debian',
|
+ "AstraLinuxCE": "Debian",
|
||||||
}
|
}
|
||||||
|
|
||||||
# Matches any possible format:
|
# Matches any possible format:
|
||||||
diff --git a/tests/unit/grains/test_core.py b/tests/unit/grains/test_core.py
|
diff --git a/tests/unit/grains/test_core.py b/tests/unit/grains/test_core.py
|
||||||
index b4ed9379e5..c276dee9f3 100644
|
index 85d434dd9d..196dbcf83d 100644
|
||||||
--- a/tests/unit/grains/test_core.py
|
--- a/tests/unit/grains/test_core.py
|
||||||
+++ b/tests/unit/grains/test_core.py
|
+++ b/tests/unit/grains/test_core.py
|
||||||
@@ -605,6 +605,26 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -728,6 +728,26 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
}
|
}
|
||||||
self._run_os_grains_tests("ubuntu-17.10", _os_release_map, expectation)
|
self._run_os_grains_tests("ubuntu-17.10", _os_release_map, expectation)
|
||||||
|
|
||||||
+ @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
|
+ @skipIf(not salt.utils.platform.is_linux(), "System is not Linux")
|
||||||
+ def test_astralinuxce_2_os_grains(self):
|
+ def test_astralinuxce_2_os_grains(self):
|
||||||
+ '''
|
+ """
|
||||||
+ Test if OS grains are parsed correctly in Astra Linux CE 2.12.22 "orel"
|
+ Test if OS grains are parsed correctly in Astra Linux CE 2.12.22 "orel"
|
||||||
+ '''
|
+ """
|
||||||
+ _os_release_map = {
|
+ _os_release_map = {
|
||||||
+ 'linux_distribution': ('AstraLinuxCE', '2.12.22', 'orel'),
|
+ "linux_distribution": ("AstraLinuxCE", "2.12.22", "orel"),
|
||||||
+ }
|
+ }
|
||||||
+ expectation = {
|
+ expectation = {
|
||||||
+ 'os': 'AstraLinuxCE',
|
+ "os": "AstraLinuxCE",
|
||||||
+ 'os_family': 'Debian',
|
+ "os_family": "Debian",
|
||||||
+ 'oscodename': 'orel',
|
+ "oscodename": "orel",
|
||||||
+ 'osfullname': 'AstraLinuxCE',
|
+ "osfullname": "AstraLinuxCE",
|
||||||
+ 'osrelease': '2.12.22',
|
+ "osrelease": "2.12.22",
|
||||||
+ 'osrelease_info': (2, 12, 22),
|
+ "osrelease_info": (2, 12, 22),
|
||||||
+ 'osmajorrelease': 2,
|
+ "osmajorrelease": 2,
|
||||||
+ 'osfinger': 'AstraLinuxCE-2',
|
+ "osfinger": "AstraLinuxCE-2",
|
||||||
+ }
|
+ }
|
||||||
+ self._run_os_grains_tests("astralinuxce-2.12.22", _os_release_map, expectation)
|
+ self._run_os_grains_tests("astralinuxce-2.12.22", _os_release_map, expectation)
|
||||||
+
|
+
|
||||||
@skipIf(not salt.utils.platform.is_windows(), 'System is not Windows')
|
@skipIf(not salt.utils.platform.is_windows(), "System is not Windows")
|
||||||
def test_windows_platform_data(self):
|
def test_windows_platform_data(self):
|
||||||
'''
|
"""
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,46 +1,55 @@
|
|||||||
From 376a7d2eeb6b3b215fac9322f1baee4497bdb339 Mon Sep 17 00:00:00 2001
|
From 66f6c2540a151487b26c89a2bb66199d6c65c18d Mon Sep 17 00:00:00 2001
|
||||||
From: Marcelo Chiaradia <mchiaradia@suse.com>
|
From: Marcelo Chiaradia <mchiaradia@suse.com>
|
||||||
Date: Thu, 4 Apr 2019 13:57:38 +0200
|
Date: Thu, 4 Apr 2019 13:57:38 +0200
|
||||||
Subject: [PATCH] Add 'batch_presence_ping_timeout' and
|
Subject: [PATCH] Add 'batch_presence_ping_timeout' and
|
||||||
'batch_presence_ping_gather_job_timeout' parameters for synchronous batching
|
'batch_presence_ping_gather_job_timeout' parameters for synchronous batching
|
||||||
|
|
||||||
---
|
---
|
||||||
salt/cli/batch.py | 7 +++++--
|
salt/cli/batch.py | 16 ++++++++++++++--
|
||||||
1 file changed, 5 insertions(+), 2 deletions(-)
|
1 file changed, 14 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/cli/batch.py b/salt/cli/batch.py
|
diff --git a/salt/cli/batch.py b/salt/cli/batch.py
|
||||||
index 36e66da1af..67f03c8a45 100644
|
index 527cffdeb7..2bc5444aef 100644
|
||||||
--- a/salt/cli/batch.py
|
--- a/salt/cli/batch.py
|
||||||
+++ b/salt/cli/batch.py
|
+++ b/salt/cli/batch.py
|
||||||
@@ -83,6 +83,9 @@ def batch_get_opts(
|
@@ -77,6 +77,13 @@ def batch_get_opts(
|
||||||
if key not in opts:
|
if key not in opts:
|
||||||
opts[key] = val
|
opts[key] = val
|
||||||
|
|
||||||
+ opts['batch_presence_ping_timeout'] = kwargs.get('batch_presence_ping_timeout', opts['timeout'])
|
+ opts["batch_presence_ping_timeout"] = kwargs.get(
|
||||||
+ opts['batch_presence_ping_gather_job_timeout'] = kwargs.get('batch_presence_ping_gather_job_timeout', opts['gather_job_timeout'])
|
+ "batch_presence_ping_timeout", opts["timeout"]
|
||||||
|
+ )
|
||||||
|
+ opts["batch_presence_ping_gather_job_timeout"] = kwargs.get(
|
||||||
|
+ "batch_presence_ping_gather_job_timeout", opts["gather_job_timeout"]
|
||||||
|
+ )
|
||||||
+
|
+
|
||||||
return opts
|
return opts
|
||||||
|
|
||||||
|
|
||||||
@@ -119,7 +122,7 @@ class Batch(object):
|
@@ -115,7 +122,7 @@ class Batch:
|
||||||
args = [self.opts['tgt'],
|
self.opts["tgt"],
|
||||||
'test.ping',
|
"test.ping",
|
||||||
[],
|
[],
|
||||||
- self.opts['timeout'],
|
- self.opts["timeout"],
|
||||||
+ self.opts.get('batch_presence_ping_timeout', self.opts['timeout']),
|
+ self.opts.get("batch_presence_ping_timeout", self.opts["timeout"]),
|
||||||
]
|
]
|
||||||
|
|
||||||
selected_target_option = self.opts.get('selected_target_option', None)
|
selected_target_option = self.opts.get("selected_target_option", None)
|
||||||
@@ -130,7 +133,7 @@ class Batch(object):
|
@@ -126,7 +133,12 @@ class Batch:
|
||||||
|
|
||||||
self.pub_kwargs['yield_pub_data'] = True
|
self.pub_kwargs["yield_pub_data"] = True
|
||||||
ping_gen = self.local.cmd_iter(*args,
|
ping_gen = self.local.cmd_iter(
|
||||||
- gather_job_timeout=self.opts['gather_job_timeout'],
|
- *args, gather_job_timeout=self.opts["gather_job_timeout"], **self.pub_kwargs
|
||||||
+ gather_job_timeout=self.opts.get('batch_presence_ping_gather_job_timeout', self.opts['gather_job_timeout']),
|
+ *args,
|
||||||
**self.pub_kwargs)
|
+ gather_job_timeout=self.opts.get(
|
||||||
|
+ "batch_presence_ping_gather_job_timeout",
|
||||||
|
+ self.opts["gather_job_timeout"],
|
||||||
|
+ ),
|
||||||
|
+ **self.pub_kwargs
|
||||||
|
)
|
||||||
|
|
||||||
# Broadcast to targets
|
# Broadcast to targets
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From a90f35bc03b477a63aae20c58f8957c075569465 Mon Sep 17 00:00:00 2001
|
From c845d56fdf1762586b1f210b1eb49193893d4312 Mon Sep 17 00:00:00 2001
|
||||||
From: Bo Maryniuk <bo@suse.de>
|
From: Bo Maryniuk <bo@suse.de>
|
||||||
Date: Tue, 9 Oct 2018 14:08:50 +0200
|
Date: Tue, 9 Oct 2018 14:08:50 +0200
|
||||||
Subject: [PATCH] Add CPE_NAME for osversion* grain parsing (U#49946)
|
Subject: [PATCH] Add CPE_NAME for osversion* grain parsing (U#49946)
|
||||||
@ -29,10 +29,10 @@ Fix proper part name in the string-bound CPE
|
|||||||
1 file changed, 28 insertions(+)
|
1 file changed, 28 insertions(+)
|
||||||
|
|
||||||
diff --git a/salt/grains/core.py b/salt/grains/core.py
|
diff --git a/salt/grains/core.py b/salt/grains/core.py
|
||||||
index 9c1b5d930e..7b7e328520 100644
|
index 5535584d1b..bc3cf129cd 100644
|
||||||
--- a/salt/grains/core.py
|
--- a/salt/grains/core.py
|
||||||
+++ b/salt/grains/core.py
|
+++ b/salt/grains/core.py
|
||||||
@@ -1642,6 +1642,34 @@ def _parse_cpe_name(cpe):
|
@@ -1732,6 +1732,34 @@ def _parse_cpe_name(cpe):
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
@ -65,9 +65,9 @@ index 9c1b5d930e..7b7e328520 100644
|
|||||||
+
|
+
|
||||||
+
|
+
|
||||||
def os_data():
|
def os_data():
|
||||||
'''
|
"""
|
||||||
Return grains pertaining to the operating system
|
Return grains pertaining to the operating system
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From e57dd3c2ae655422f0f6939825154ce5827d43c4 Mon Sep 17 00:00:00 2001
|
From 713ccfdc5c6733495d3ce7f26a8cfeddb8e9e9c4 Mon Sep 17 00:00:00 2001
|
||||||
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||||
<psuarezhernandez@suse.com>
|
<psuarezhernandez@suse.com>
|
||||||
Date: Thu, 21 Jun 2018 11:57:57 +0100
|
Date: Thu, 21 Jun 2018 11:57:57 +0100
|
||||||
@ -9,10 +9,10 @@ Subject: [PATCH] Add custom SUSE capabilities as Grains
|
|||||||
1 file changed, 7 insertions(+)
|
1 file changed, 7 insertions(+)
|
||||||
|
|
||||||
diff --git a/salt/grains/extra.py b/salt/grains/extra.py
|
diff --git a/salt/grains/extra.py b/salt/grains/extra.py
|
||||||
index 9ce644b766..1082b05dba 100644
|
index 2fdbe6526a..ddc22293ea 100644
|
||||||
--- a/salt/grains/extra.py
|
--- a/salt/grains/extra.py
|
||||||
+++ b/salt/grains/extra.py
|
+++ b/salt/grains/extra.py
|
||||||
@@ -75,3 +75,10 @@ def config():
|
@@ -66,3 +66,10 @@ def config():
|
||||||
log.warning("Bad syntax in grains file! Skipping.")
|
log.warning("Bad syntax in grains file! Skipping.")
|
||||||
return {}
|
return {}
|
||||||
return {}
|
return {}
|
||||||
@ -24,6 +24,6 @@ index 9ce644b766..1082b05dba 100644
|
|||||||
+ '__suse_reserved_pkg_patches_support': True
|
+ '__suse_reserved_pkg_patches_support': True
|
||||||
+ }
|
+ }
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From 9e6bd24b07cd2424c3805777b07b9ea84adff416 Mon Sep 17 00:00:00 2001
|
From 355e1e29e8f3286eeb13bc2d05089c096c9e01e3 Mon Sep 17 00:00:00 2001
|
||||||
From: Alexander Graul <agraul@suse.com>
|
From: Alexander Graul <agraul@suse.com>
|
||||||
Date: Mon, 18 May 2020 16:39:27 +0200
|
Date: Mon, 18 May 2020 16:39:27 +0200
|
||||||
Subject: [PATCH] Add docker logout (#237)
|
Subject: [PATCH] Add docker logout (#237)
|
||||||
@ -13,10 +13,10 @@ interpreted as a list of docker registries to log out of.
|
|||||||
2 files changed, 139 insertions(+)
|
2 files changed, 139 insertions(+)
|
||||||
|
|
||||||
diff --git a/salt/modules/dockermod.py b/salt/modules/dockermod.py
|
diff --git a/salt/modules/dockermod.py b/salt/modules/dockermod.py
|
||||||
index 28a2107cec..119e9eb170 100644
|
index 934038c927..176b4db926 100644
|
||||||
--- a/salt/modules/dockermod.py
|
--- a/salt/modules/dockermod.py
|
||||||
+++ b/salt/modules/dockermod.py
|
+++ b/salt/modules/dockermod.py
|
||||||
@@ -1481,6 +1481,86 @@ def login(*registries):
|
@@ -1586,6 +1586,86 @@ def logout(*registries):
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
@ -102,44 +102,15 @@ index 28a2107cec..119e9eb170 100644
|
|||||||
+
|
+
|
||||||
# Functions for information gathering
|
# Functions for information gathering
|
||||||
def depends(name):
|
def depends(name):
|
||||||
'''
|
"""
|
||||||
diff --git a/tests/unit/modules/test_dockermod.py b/tests/unit/modules/test_dockermod.py
|
diff --git a/tests/unit/modules/test_dockermod.py b/tests/unit/modules/test_dockermod.py
|
||||||
index 191bfc123f..8f4ead2867 100644
|
index 34e2e9c610..48526acb71 100644
|
||||||
--- a/tests/unit/modules/test_dockermod.py
|
--- a/tests/unit/modules/test_dockermod.py
|
||||||
+++ b/tests/unit/modules/test_dockermod.py
|
+++ b/tests/unit/modules/test_dockermod.py
|
||||||
@@ -164,6 +164,65 @@ class DockerTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -199,6 +199,65 @@ class DockerTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
self.assertIn('retcode', ret)
|
output_loglevel="quiet",
|
||||||
self.assertNotEqual(ret['retcode'], 0)
|
)
|
||||||
|
|
||||||
+ def test_logout_calls_docker_cli_logout_single(self):
|
|
||||||
+ client = Mock()
|
|
||||||
+ get_client_mock = MagicMock(return_value=client)
|
|
||||||
+ ref_out = {"stdout": "", "stderr": "", "retcode": 0}
|
|
||||||
+ registry_auth_data = {
|
|
||||||
+ "portus.example.com:5000": {
|
|
||||||
+ "username": "admin",
|
|
||||||
+ "password": "linux12345",
|
|
||||||
+ "email": "tux@example.com",
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ docker_mock = MagicMock(return_value=ref_out)
|
|
||||||
+ with patch.object(docker_mod, "_get_client", get_client_mock):
|
|
||||||
+ dunder_salt = {
|
|
||||||
+ "config.get": MagicMock(return_value=registry_auth_data),
|
|
||||||
+ "cmd.run_all": docker_mock,
|
|
||||||
+ "config.option": MagicMock(return_value={}),
|
|
||||||
+ }
|
|
||||||
+ with patch.dict(docker_mod.__salt__, dunder_salt):
|
|
||||||
+ ret = docker_mod.logout("portus.example.com:5000")
|
|
||||||
+ assert "retcode" in ret
|
|
||||||
+ assert ret["retcode"] == 0
|
|
||||||
+ docker_mock.assert_called_with(
|
|
||||||
+ ["docker", "logout", "portus.example.com:5000"],
|
|
||||||
+ python_shell=False,
|
|
||||||
+ output_loglevel="quiet",
|
|
||||||
+ )
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+ def test_logout_calls_docker_cli_logout_all(self):
|
+ def test_logout_calls_docker_cli_logout_all(self):
|
||||||
+ client = Mock()
|
+ client = Mock()
|
||||||
+ get_client_mock = MagicMock(return_value=client)
|
+ get_client_mock = MagicMock(return_value=client)
|
||||||
@ -170,10 +141,39 @@ index 191bfc123f..8f4ead2867 100644
|
|||||||
+ assert ret["retcode"] == 0
|
+ assert ret["retcode"] == 0
|
||||||
+ assert docker_mock.call_count == 2
|
+ assert docker_mock.call_count == 2
|
||||||
+
|
+
|
||||||
def test_ps_with_host_true(self):
|
+ def test_logout_calls_docker_cli_logout_single(self):
|
||||||
'''
|
+ client = Mock()
|
||||||
Check that docker.ps called with host is ``True``,
|
+ get_client_mock = MagicMock(return_value=client)
|
||||||
|
+ ref_out = {"stdout": "", "stderr": "", "retcode": 0}
|
||||||
|
+ registry_auth_data = {
|
||||||
|
+ "portus.example.com:5000": {
|
||||||
|
+ "username": "admin",
|
||||||
|
+ "password": "linux12345",
|
||||||
|
+ "email": "tux@example.com",
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ docker_mock = MagicMock(return_value=ref_out)
|
||||||
|
+ with patch.object(docker_mod, "_get_client", get_client_mock):
|
||||||
|
+ dunder_salt = {
|
||||||
|
+ "config.get": MagicMock(return_value=registry_auth_data),
|
||||||
|
+ "cmd.run_all": docker_mock,
|
||||||
|
+ "config.option": MagicMock(return_value={}),
|
||||||
|
+ }
|
||||||
|
+ with patch.dict(docker_mod.__salt__, dunder_salt):
|
||||||
|
+ ret = docker_mod.logout("portus.example.com:5000")
|
||||||
|
+ assert "retcode" in ret
|
||||||
|
+ assert ret["retcode"] == 0
|
||||||
|
+ docker_mock.assert_called_with(
|
||||||
|
+ ["docker", "logout", "portus.example.com:5000"],
|
||||||
|
+ python_shell=False,
|
||||||
|
+ output_loglevel="quiet",
|
||||||
|
+ )
|
||||||
|
+
|
||||||
|
+
|
||||||
|
def test_logout_calls_docker_cli_logout_all(self):
|
||||||
|
client = Mock()
|
||||||
|
get_client_mock = MagicMock(return_value=client)
|
||||||
--
|
--
|
||||||
2.26.2
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,78 +1,83 @@
|
|||||||
From 874b1229babf5244debac141cd260f695ccc1e9d Mon Sep 17 00:00:00 2001
|
From 7b2b5fc53d30397b8f7a11e59f5c7a57bcb63058 Mon Sep 17 00:00:00 2001
|
||||||
From: Marcelo Chiaradia <mchiaradia@suse.com>
|
From: Marcelo Chiaradia <mchiaradia@suse.com>
|
||||||
Date: Thu, 7 Jun 2018 10:29:41 +0200
|
Date: Thu, 7 Jun 2018 10:29:41 +0200
|
||||||
Subject: [PATCH] Add environment variable to know if yum is invoked from
|
Subject: [PATCH] Add environment variable to know if yum is invoked
|
||||||
Salt(bsc#1057635)
|
from Salt(bsc#1057635)
|
||||||
|
|
||||||
---
|
---
|
||||||
salt/modules/yumpkg.py | 18 ++++++++++++------
|
salt/modules/yumpkg.py | 23 +++++++++++++++++------
|
||||||
1 file changed, 12 insertions(+), 6 deletions(-)
|
1 file changed, 17 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/modules/yumpkg.py b/salt/modules/yumpkg.py
|
diff --git a/salt/modules/yumpkg.py b/salt/modules/yumpkg.py
|
||||||
index f7e4ac9753..c89d321a1b 100644
|
index b547fe6be7..c58b3e4c70 100644
|
||||||
--- a/salt/modules/yumpkg.py
|
--- a/salt/modules/yumpkg.py
|
||||||
+++ b/salt/modules/yumpkg.py
|
+++ b/salt/modules/yumpkg.py
|
||||||
@@ -913,7 +913,8 @@ def list_repo_pkgs(*args, **kwargs):
|
@@ -917,7 +917,9 @@ def list_repo_pkgs(*args, **kwargs):
|
||||||
yum_version = None if _yum() != 'yum' else _LooseVersion(
|
None
|
||||||
__salt__['cmd.run'](
|
if _yum() != "yum"
|
||||||
['yum', '--version'],
|
else _LooseVersion(
|
||||||
- python_shell=False
|
- __salt__["cmd.run"](["yum", "--version"], python_shell=False)
|
||||||
+ python_shell=False,
|
+ __salt__["cmd.run"](
|
||||||
+ env={"SALT_RUNNING": '1'}
|
+ ["yum", "--version"], python_shell=False, env={"SALT_RUNNING": "1"}
|
||||||
).splitlines()[0].strip()
|
+ )
|
||||||
|
.splitlines()[0]
|
||||||
|
.strip()
|
||||||
)
|
)
|
||||||
# Really old version of yum; does not even have --showduplicates option
|
@@ -2347,7 +2349,9 @@ def list_holds(pattern=__HOLD_PATTERN, full=True):
|
||||||
@@ -2324,7 +2325,8 @@ def list_holds(pattern=__HOLD_PATTERN, full=True):
|
"""
|
||||||
_check_versionlock()
|
_check_versionlock()
|
||||||
|
|
||||||
out = __salt__['cmd.run']([_yum(), 'versionlock', 'list'],
|
- out = __salt__["cmd.run"]([_yum(), "versionlock", "list"], python_shell=False)
|
||||||
- python_shell=False)
|
+ out = __salt__["cmd.run"](
|
||||||
+ python_shell=False,
|
+ [_yum(), "versionlock", "list"], python_shell=False, env={"SALT_RUNNING": "1"}
|
||||||
+ env={"SALT_RUNNING": '1'})
|
+ )
|
||||||
ret = []
|
ret = []
|
||||||
for line in salt.utils.itertools.split(out, '\n'):
|
for line in salt.utils.itertools.split(out, "\n"):
|
||||||
match = _get_hold(line, pattern=pattern, full=full)
|
match = _get_hold(line, pattern=pattern, full=full)
|
||||||
@@ -2390,7 +2392,8 @@ def group_list():
|
@@ -2415,7 +2419,10 @@ def group_list():
|
||||||
out = __salt__['cmd.run_stdout'](
|
}
|
||||||
[_yum(), 'grouplist', 'hidden'],
|
|
||||||
output_loglevel='trace',
|
out = __salt__["cmd.run_stdout"](
|
||||||
- python_shell=False
|
- [_yum(), "grouplist", "hidden"], output_loglevel="trace", python_shell=False
|
||||||
|
+ [_yum(), "grouplist", "hidden"],
|
||||||
|
+ output_loglevel="trace",
|
||||||
+ python_shell=False,
|
+ python_shell=False,
|
||||||
+ env={"SALT_RUNNING": '1'}
|
+ env={"SALT_RUNNING": "1"},
|
||||||
)
|
)
|
||||||
key = None
|
key = None
|
||||||
for line in salt.utils.itertools.split(out, '\n'):
|
for line in salt.utils.itertools.split(out, "\n"):
|
||||||
@@ -2457,7 +2460,8 @@ def group_info(name, expand=False):
|
@@ -2486,7 +2493,9 @@ def group_info(name, expand=False, ignore_groups=None):
|
||||||
out = __salt__['cmd.run_stdout'](
|
ret[pkgtype] = set()
|
||||||
cmd,
|
|
||||||
output_loglevel='trace',
|
cmd = [_yum(), "--quiet", "groupinfo", name]
|
||||||
- python_shell=False
|
- out = __salt__["cmd.run_stdout"](cmd, output_loglevel="trace", python_shell=False)
|
||||||
+ python_shell=False,
|
+ out = __salt__["cmd.run_stdout"](
|
||||||
+ env={"SALT_RUNNING": '1'}
|
+ cmd, output_loglevel="trace", python_shell=False, env={"SALT_RUNNING": "1"}
|
||||||
)
|
+ )
|
||||||
|
|
||||||
g_info = {}
|
g_info = {}
|
||||||
@@ -3134,7 +3138,8 @@ def download(*packages):
|
for line in salt.utils.itertools.split(out, "\n"):
|
||||||
__salt__['cmd.run'](
|
@@ -3203,7 +3212,9 @@ def download(*packages, **kwargs):
|
||||||
cmd,
|
|
||||||
output_loglevel='trace',
|
cmd = ["yumdownloader", "-q", "--destdir={}".format(CACHE_DIR)]
|
||||||
- python_shell=False
|
cmd.extend(packages)
|
||||||
+ python_shell=False,
|
- __salt__["cmd.run"](cmd, output_loglevel="trace", python_shell=False)
|
||||||
+ env={"SALT_RUNNING": '1'}
|
+ __salt__["cmd.run"](
|
||||||
)
|
+ cmd, output_loglevel="trace", python_shell=False, env={"SALT_RUNNING": "1"}
|
||||||
|
+ )
|
||||||
ret = {}
|
ret = {}
|
||||||
for dld_result in os.listdir(CACHE_DIR):
|
for dld_result in os.listdir(CACHE_DIR):
|
||||||
@@ -3209,7 +3214,8 @@ def _get_patches(installed_only=False):
|
if not dld_result.endswith(".rpm"):
|
||||||
cmd = [_yum(), '--quiet', 'updateinfo', 'list', 'all']
|
@@ -3279,7 +3290,7 @@ def _get_patches(installed_only=False):
|
||||||
ret = __salt__['cmd.run_stdout'](
|
patches = {}
|
||||||
cmd,
|
|
||||||
- python_shell=False
|
cmd = [_yum(), "--quiet", "updateinfo", "list", "all"]
|
||||||
+ python_shell=False,
|
- ret = __salt__["cmd.run_stdout"](cmd, python_shell=False)
|
||||||
+ env={"SALT_RUNNING": '1'}
|
+ ret = __salt__["cmd.run_stdout"](cmd, python_shell=False, env={"SALT_RUNNING": "1"})
|
||||||
)
|
|
||||||
for line in salt.utils.itertools.split(ret, os.linesep):
|
for line in salt.utils.itertools.split(ret, os.linesep):
|
||||||
inst, advisory_id, sev, pkg = re.match(r'([i|\s]) ([^\s]+) +([^\s]+) +([^\s]+)',
|
inst, advisory_id, sev, pkg = re.match(
|
||||||
|
r"([i|\s]) ([^\s]+) +([^\s]+) +([^\s]+)", line
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From 666f62917bbc48cbee2ed0aa319a61afd1b1fcb2 Mon Sep 17 00:00:00 2001
|
From 6176ef8aa39626dcb450a1665231a796e9544342 Mon Sep 17 00:00:00 2001
|
||||||
From: Bo Maryniuk <bo@suse.de>
|
From: Bo Maryniuk <bo@suse.de>
|
||||||
Date: Thu, 6 Dec 2018 16:26:23 +0100
|
Date: Thu, 6 Dec 2018 16:26:23 +0100
|
||||||
Subject: [PATCH] Add hold/unhold functions
|
Subject: [PATCH] Add hold/unhold functions
|
||||||
@ -7,43 +7,324 @@ Add unhold function
|
|||||||
|
|
||||||
Add warnings
|
Add warnings
|
||||||
---
|
---
|
||||||
salt/modules/zypperpkg.py | 88 ++++++++++++++++++++++++++++++++++++++++++++++-
|
salt/modules/zypperpkg.py | 186 +++++++++++++++++++++++++++-----------
|
||||||
1 file changed, 87 insertions(+), 1 deletion(-)
|
1 file changed, 131 insertions(+), 55 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py
|
diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py
|
||||||
index 50279ccbd1..08a9c2ed4d 100644
|
index 44bcbbf2f2..6fa6e3e0a1 100644
|
||||||
--- a/salt/modules/zypperpkg.py
|
--- a/salt/modules/zypperpkg.py
|
||||||
+++ b/salt/modules/zypperpkg.py
|
+++ b/salt/modules/zypperpkg.py
|
||||||
@@ -41,6 +41,7 @@ import salt.utils.pkg
|
@@ -1,4 +1,3 @@
|
||||||
|
-# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Package support for openSUSE via the zypper package manager
|
||||||
|
|
||||||
|
@@ -12,8 +11,6 @@ Package support for openSUSE via the zypper package manager
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
-# Import python libs
|
||||||
|
-from __future__ import absolute_import, print_function, unicode_literals
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
import fnmatch
|
||||||
|
@@ -24,7 +21,6 @@ import time
|
||||||
|
from xml.dom import minidom as dom
|
||||||
|
from xml.parsers.expat import ExpatError
|
||||||
|
|
||||||
|
-# Import salt libs
|
||||||
|
import salt.utils.data
|
||||||
|
import salt.utils.environment
|
||||||
|
import salt.utils.event
|
||||||
|
@@ -35,9 +31,9 @@ import salt.utils.pkg
|
||||||
import salt.utils.pkg.rpm
|
import salt.utils.pkg.rpm
|
||||||
import salt.utils.stringutils
|
import salt.utils.stringutils
|
||||||
import salt.utils.systemd
|
import salt.utils.systemd
|
||||||
+import salt.utils.versions
|
+import salt.utils.versions
|
||||||
from salt.utils.versions import LooseVersion
|
|
||||||
import salt.utils.environment
|
|
||||||
from salt.exceptions import CommandExecutionError, MinionError, SaltInvocationError
|
from salt.exceptions import CommandExecutionError, MinionError, SaltInvocationError
|
||||||
@@ -1771,7 +1772,7 @@ def clean_locks():
|
|
||||||
|
-# Import 3rd-party libs
|
||||||
|
# pylint: disable=import-error,redefined-builtin,no-name-in-module
|
||||||
|
from salt.ext import six
|
||||||
|
from salt.ext.six.moves import configparser
|
||||||
|
@@ -51,8 +47,8 @@ log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
HAS_ZYPP = False
|
||||||
|
ZYPP_HOME = "/etc/zypp"
|
||||||
|
-LOCKS = "{0}/locks".format(ZYPP_HOME)
|
||||||
|
-REPOS = "{0}/repos.d".format(ZYPP_HOME)
|
||||||
|
+LOCKS = "{}/locks".format(ZYPP_HOME)
|
||||||
|
+REPOS = "{}/repos.d".format(ZYPP_HOME)
|
||||||
|
DEFAULT_PRIORITY = 99
|
||||||
|
PKG_ARCH_SEPARATOR = "."
|
||||||
|
|
||||||
|
@@ -75,7 +71,7 @@ def __virtual__():
|
||||||
|
return __virtualname__
|
||||||
|
|
||||||
|
|
||||||
|
-class _Zypper(object):
|
||||||
|
+class _Zypper:
|
||||||
|
"""
|
||||||
|
Zypper parallel caller.
|
||||||
|
Validates the result and either raises an exception or reports an error.
|
||||||
|
@@ -339,7 +335,7 @@ class _Zypper(object):
|
||||||
|
attrs=["pid", "name", "cmdline", "create_time"],
|
||||||
|
)
|
||||||
|
data["cmdline"] = " ".join(data["cmdline"])
|
||||||
|
- data["info"] = "Blocking process created at {0}.".format(
|
||||||
|
+ data["info"] = "Blocking process created at {}.".format(
|
||||||
|
datetime.datetime.utcfromtimestamp(
|
||||||
|
data["create_time"]
|
||||||
|
).isoformat()
|
||||||
|
@@ -347,7 +343,7 @@ class _Zypper(object):
|
||||||
|
data["success"] = True
|
||||||
|
except Exception as err: # pylint: disable=broad-except
|
||||||
|
data = {
|
||||||
|
- "info": "Unable to retrieve information about blocking process: {0}".format(
|
||||||
|
+ "info": "Unable to retrieve information about blocking process: {}".format(
|
||||||
|
err.message
|
||||||
|
),
|
||||||
|
"success": False,
|
||||||
|
@@ -382,7 +378,7 @@ class _Zypper(object):
|
||||||
|
)
|
||||||
|
if self.error_msg and not self.__no_raise and not self.__ignore_repo_failure:
|
||||||
|
raise CommandExecutionError(
|
||||||
|
- "Zypper command failure: {0}".format(self.error_msg)
|
||||||
|
+ "Zypper command failure: {}".format(self.error_msg)
|
||||||
|
)
|
||||||
|
|
||||||
|
return (
|
||||||
|
@@ -397,7 +393,7 @@ class _Zypper(object):
|
||||||
|
__zypper__ = _Zypper()
|
||||||
|
|
||||||
|
|
||||||
|
-class Wildcard(object):
|
||||||
|
+class Wildcard:
|
||||||
|
"""
|
||||||
|
.. versionadded:: 2017.7.0
|
||||||
|
|
||||||
|
@@ -439,7 +435,7 @@ class Wildcard(object):
|
||||||
|
for vrs in self._get_scope_versions(self._get_available_versions())
|
||||||
|
]
|
||||||
|
)
|
||||||
|
- return versions and "{0}{1}".format(self._op or "", versions[-1]) or None
|
||||||
|
+ return versions and "{}{}".format(self._op or "", versions[-1]) or None
|
||||||
|
|
||||||
|
def _get_available_versions(self):
|
||||||
|
"""
|
||||||
|
@@ -451,17 +447,15 @@ class Wildcard(object):
|
||||||
|
).getElementsByTagName("solvable")
|
||||||
|
if not solvables:
|
||||||
|
raise CommandExecutionError(
|
||||||
|
- "No packages found matching '{0}'".format(self.name)
|
||||||
|
+ "No packages found matching '{}'".format(self.name)
|
||||||
|
)
|
||||||
|
|
||||||
|
return sorted(
|
||||||
|
- set(
|
||||||
|
- [
|
||||||
|
- slv.getAttribute(self._attr_solvable_version)
|
||||||
|
- for slv in solvables
|
||||||
|
- if slv.getAttribute(self._attr_solvable_version)
|
||||||
|
- ]
|
||||||
|
- )
|
||||||
|
+ {
|
||||||
|
+ slv.getAttribute(self._attr_solvable_version)
|
||||||
|
+ for slv in solvables
|
||||||
|
+ if slv.getAttribute(self._attr_solvable_version)
|
||||||
|
+ }
|
||||||
|
)
|
||||||
|
|
||||||
|
def _get_scope_versions(self, pkg_versions):
|
||||||
|
@@ -489,7 +483,7 @@ class Wildcard(object):
|
||||||
|
self._op = version.replace(exact_version, "") or None
|
||||||
|
if self._op and self._op not in self.Z_OP:
|
||||||
|
raise CommandExecutionError(
|
||||||
|
- 'Zypper do not supports operator "{0}".'.format(self._op)
|
||||||
|
+ 'Zypper do not supports operator "{}".'.format(self._op)
|
||||||
|
)
|
||||||
|
self.version = exact_version
|
||||||
|
|
||||||
|
@@ -539,14 +533,11 @@ def list_upgrades(refresh=True, root=None, **kwargs):
|
||||||
|
cmd = ["list-updates"]
|
||||||
|
if "fromrepo" in kwargs:
|
||||||
|
repos = kwargs["fromrepo"]
|
||||||
|
- if isinstance(repos, six.string_types):
|
||||||
|
+ if isinstance(repos, str):
|
||||||
|
repos = [repos]
|
||||||
|
for repo in repos:
|
||||||
|
cmd.extend(
|
||||||
|
- [
|
||||||
|
- "--repo",
|
||||||
|
- repo if isinstance(repo, six.string_types) else six.text_type(repo),
|
||||||
|
- ]
|
||||||
|
+ ["--repo", repo if isinstance(repo, str) else str(repo),]
|
||||||
|
)
|
||||||
|
log.debug("Targeting repos: %s", repos)
|
||||||
|
for update_node in (
|
||||||
|
@@ -610,7 +601,7 @@ def info_installed(*names, **kwargs):
|
||||||
|
for _nfo in pkg_nfo:
|
||||||
|
t_nfo = dict()
|
||||||
|
# Translate dpkg-specific keys to a common structure
|
||||||
|
- for key, value in six.iteritems(_nfo):
|
||||||
|
+ for key, value in _nfo.items():
|
||||||
|
if key == "source_rpm":
|
||||||
|
t_nfo["source"] = value
|
||||||
|
else:
|
||||||
|
@@ -1033,9 +1024,7 @@ def list_repo_pkgs(*args, **kwargs):
|
||||||
|
fromrepo = kwargs.pop("fromrepo", "") or ""
|
||||||
|
ret = {}
|
||||||
|
|
||||||
|
- targets = [
|
||||||
|
- arg if isinstance(arg, six.string_types) else six.text_type(arg) for arg in args
|
||||||
|
- ]
|
||||||
|
+ targets = [arg if isinstance(arg, str) else str(arg) for arg in args]
|
||||||
|
|
||||||
|
def _is_match(pkgname):
|
||||||
|
"""
|
||||||
|
@@ -1124,7 +1113,7 @@ def _get_repo_info(alias, repos_cfg=None, root=None):
|
||||||
|
try:
|
||||||
|
meta = dict((repos_cfg or _get_configured_repos(root=root)).items(alias))
|
||||||
|
meta["alias"] = alias
|
||||||
|
- for key, val in six.iteritems(meta):
|
||||||
|
+ for key, val in meta.items():
|
||||||
|
if val in ["0", "1"]:
|
||||||
|
meta[key] = int(meta[key]) == 1
|
||||||
|
elif val == "NONE":
|
||||||
|
@@ -1197,7 +1186,7 @@ def del_repo(repo, root=None):
|
||||||
|
"message": msg[0].childNodes[0].nodeValue,
|
||||||
|
}
|
||||||
|
|
||||||
|
- raise CommandExecutionError("Repository '{0}' not found.".format(repo))
|
||||||
|
+ raise CommandExecutionError("Repository '{}' not found.".format(repo))
|
||||||
|
|
||||||
|
|
||||||
|
def mod_repo(repo, **kwargs):
|
||||||
|
@@ -1252,13 +1241,13 @@ def mod_repo(repo, **kwargs):
|
||||||
|
url = kwargs.get("url", kwargs.get("mirrorlist", kwargs.get("baseurl")))
|
||||||
|
if not url:
|
||||||
|
raise CommandExecutionError(
|
||||||
|
- "Repository '{0}' not found, and neither 'baseurl' nor "
|
||||||
|
+ "Repository '{}' not found, and neither 'baseurl' nor "
|
||||||
|
"'mirrorlist' was specified".format(repo)
|
||||||
|
)
|
||||||
|
|
||||||
|
if not _urlparse(url).scheme:
|
||||||
|
raise CommandExecutionError(
|
||||||
|
- "Repository '{0}' not found and URL for baseurl/mirrorlist "
|
||||||
|
+ "Repository '{}' not found and URL for baseurl/mirrorlist "
|
||||||
|
"is malformed".format(repo)
|
||||||
|
)
|
||||||
|
|
||||||
|
@@ -1281,7 +1270,7 @@ def mod_repo(repo, **kwargs):
|
||||||
|
|
||||||
|
if new_url == base_url:
|
||||||
|
raise CommandExecutionError(
|
||||||
|
- "Repository '{0}' already exists as '{1}'.".format(repo, alias)
|
||||||
|
+ "Repository '{}' already exists as '{}'.".format(repo, alias)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add new repo
|
||||||
|
@@ -1291,7 +1280,7 @@ def mod_repo(repo, **kwargs):
|
||||||
|
repos_cfg = _get_configured_repos(root=root)
|
||||||
|
if repo not in repos_cfg.sections():
|
||||||
|
raise CommandExecutionError(
|
||||||
|
- "Failed add new repository '{0}' for unspecified reason. "
|
||||||
|
+ "Failed add new repository '{}' for unspecified reason. "
|
||||||
|
"Please check zypper logs.".format(repo)
|
||||||
|
)
|
||||||
|
added = True
|
||||||
|
@@ -1327,12 +1316,10 @@ def mod_repo(repo, **kwargs):
|
||||||
|
cmd_opt.append(kwargs["gpgcheck"] and "--gpgcheck" or "--no-gpgcheck")
|
||||||
|
|
||||||
|
if "priority" in kwargs:
|
||||||
|
- cmd_opt.append(
|
||||||
|
- "--priority={0}".format(kwargs.get("priority", DEFAULT_PRIORITY))
|
||||||
|
- )
|
||||||
|
+ cmd_opt.append("--priority={}".format(kwargs.get("priority", DEFAULT_PRIORITY)))
|
||||||
|
|
||||||
|
if "humanname" in kwargs:
|
||||||
|
- cmd_opt.append("--name='{0}'".format(kwargs.get("humanname")))
|
||||||
|
+ cmd_opt.append("--name='{}'".format(kwargs.get("humanname")))
|
||||||
|
|
||||||
|
if kwargs.get("gpgautoimport") is True:
|
||||||
|
global_cmd_opt.append("--gpg-auto-import-keys")
|
||||||
|
@@ -1589,7 +1576,7 @@ def install(
|
||||||
|
|
||||||
|
if pkg_type == "repository":
|
||||||
|
targets = []
|
||||||
|
- for param, version_num in six.iteritems(pkg_params):
|
||||||
|
+ for param, version_num in pkg_params.items():
|
||||||
|
if version_num is None:
|
||||||
|
log.debug("targeting package: %s", param)
|
||||||
|
targets.append(param)
|
||||||
|
@@ -1597,7 +1584,7 @@ def install(
|
||||||
|
prefix, verstr = salt.utils.pkg.split_comparison(version_num)
|
||||||
|
if not prefix:
|
||||||
|
prefix = "="
|
||||||
|
- target = "{0}{1}{2}".format(param, prefix, verstr)
|
||||||
|
+ target = "{}{}{}".format(param, prefix, verstr)
|
||||||
|
log.debug("targeting package: %s", target)
|
||||||
|
targets.append(target)
|
||||||
|
elif pkg_type == "advisory":
|
||||||
|
@@ -1606,7 +1593,7 @@ def install(
|
||||||
|
for advisory_id in pkg_params:
|
||||||
|
if advisory_id not in cur_patches:
|
||||||
|
raise CommandExecutionError(
|
||||||
|
- 'Advisory id "{0}" not found'.format(advisory_id)
|
||||||
|
+ 'Advisory id "{}" not found'.format(advisory_id)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# If we add here the `patch:` prefix, the
|
||||||
|
@@ -1703,7 +1690,7 @@ def install(
|
||||||
|
|
||||||
|
if errors:
|
||||||
|
raise CommandExecutionError(
|
||||||
|
- "Problem encountered {0} package(s)".format(
|
||||||
|
+ "Problem encountered {} package(s)".format(
|
||||||
|
"downloading" if downloadonly else "installing"
|
||||||
|
),
|
||||||
|
info={"errors": errors, "changes": ret},
|
||||||
|
@@ -1797,7 +1784,7 @@ def upgrade(
|
||||||
|
cmd_update.append("--dry-run")
|
||||||
|
|
||||||
|
if fromrepo:
|
||||||
|
- if isinstance(fromrepo, six.string_types):
|
||||||
|
+ if isinstance(fromrepo, str):
|
||||||
|
fromrepo = [fromrepo]
|
||||||
|
for repo in fromrepo:
|
||||||
|
cmd_update.extend(["--from" if dist_upgrade else "--repo", repo])
|
||||||
|
@@ -2052,7 +2039,7 @@ def list_locks(root=None):
|
||||||
|
)
|
||||||
|
if lock.get("solvable_name"):
|
||||||
|
locks[lock.pop("solvable_name")] = lock
|
||||||
|
- except IOError:
|
||||||
|
+ except OSError:
|
||||||
|
pass
|
||||||
|
except Exception: # pylint: disable=broad-except
|
||||||
|
log.warning("Detected a problem when accessing {}".format(_locks))
|
||||||
|
@@ -2089,7 +2076,7 @@ def clean_locks(root=None):
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
-def remove_lock(packages, **kwargs): # pylint: disable=unused-argument
|
-def remove_lock(packages, root=None, **kwargs): # pylint: disable=unused-argument
|
||||||
+def unhold(name=None, pkgs=None, **kwargs):
|
+def unhold(name=None, pkgs=None, **kwargs):
|
||||||
'''
|
"""
|
||||||
Remove specified package lock.
|
Remove specified package lock.
|
||||||
|
|
||||||
@@ -1783,7 +1784,47 @@ def remove_lock(packages, **kwargs): # pylint: disable=unused-argument
|
@@ -2104,8 +2091,50 @@ def remove_lock(packages, root=None, **kwargs): # pylint: disable=unused-argume
|
||||||
salt '*' pkg.remove_lock <package1>,<package2>,<package3>
|
salt '*' pkg.remove_lock <package1>,<package2>,<package3>
|
||||||
salt '*' pkg.remove_lock pkgs='["foo", "bar"]'
|
salt '*' pkg.remove_lock pkgs='["foo", "bar"]'
|
||||||
'''
|
"""
|
||||||
+ ret = {}
|
+ ret = {}
|
||||||
+ if (not name and not pkgs) or (name and pkgs):
|
+ if (not name and not pkgs) or (name and pkgs):
|
||||||
+ raise CommandExecutionError('Name or packages must be specified.')
|
+ raise CommandExecutionError("Name or packages must be specified.")
|
||||||
+ elif name:
|
+ elif name:
|
||||||
+ pkgs = [name]
|
+ pkgs = [name]
|
||||||
+
|
+
|
||||||
+ locks = list_locks()
|
+ locks = list_locks()
|
||||||
+ try:
|
+ try:
|
||||||
+ pkgs = list(__salt__['pkg_resource.parse_targets'](pkgs)[0].keys())
|
+ pkgs = list(__salt__["pkg_resource.parse_targets"](pkgs)[0].keys())
|
||||||
+ except MinionError as exc:
|
+ except MinionError as exc:
|
||||||
+ raise CommandExecutionError(exc)
|
+ raise CommandExecutionError(exc)
|
||||||
+
|
+
|
||||||
@ -52,39 +333,44 @@ index 50279ccbd1..08a9c2ed4d 100644
|
|||||||
+ for pkg in pkgs:
|
+ for pkg in pkgs:
|
||||||
+ if locks.get(pkg):
|
+ if locks.get(pkg):
|
||||||
+ removed.append(pkg)
|
+ removed.append(pkg)
|
||||||
+ ret[pkg]['comment'] = 'Package {0} is no longer held.'.format(pkg)
|
+ ret[pkg]["comment"] = "Package {} is no longer held.".format(pkg)
|
||||||
+ else:
|
+ else:
|
||||||
+ missing.append(pkg)
|
+ missing.append(pkg)
|
||||||
+ ret[pkg]['comment'] = 'Package {0} unable to be unheld.'.format(pkg)
|
+ ret[pkg]["comment"] = "Package {} unable to be unheld.".format(pkg)
|
||||||
+
|
+
|
||||||
+ if removed:
|
+ if removed:
|
||||||
+ __zypper__.call('rl', *removed)
|
+ __zypper__.call("rl", *removed)
|
||||||
+
|
+
|
||||||
+ return ret
|
+ return ret
|
||||||
+
|
+
|
||||||
+
|
+
|
||||||
+def remove_lock(packages, **kwargs): # pylint: disable=unused-argument
|
+def remove_lock(packages, **kwargs): # pylint: disable=unused-argument
|
||||||
+ '''
|
+ """
|
||||||
+ Remove specified package lock.
|
+ Remove specified package lock.
|
||||||
+
|
+
|
||||||
+ CLI Example:
|
+ CLI Example:
|
||||||
+
|
+
|
||||||
+ .. code-block:: bash
|
+ .. code-block:: bash
|
||||||
|
|
||||||
|
- locks = list_locks(root)
|
||||||
+ salt '*' pkg.remove_lock <package name>
|
+ salt '*' pkg.remove_lock <package name>
|
||||||
+ salt '*' pkg.remove_lock <package1>,<package2>,<package3>
|
+ salt '*' pkg.remove_lock <package1>,<package2>,<package3>
|
||||||
+ salt '*' pkg.remove_lock pkgs='["foo", "bar"]'
|
+ salt '*' pkg.remove_lock pkgs='["foo", "bar"]'
|
||||||
+ '''
|
+ """
|
||||||
+ salt.utils.versions.warn_until('Sodium', 'This function is deprecated. Please use unhold() instead.')
|
+ salt.utils.versions.warn_until(
|
||||||
locks = list_locks()
|
+ "Sodium", "This function is deprecated. Please use unhold() instead."
|
||||||
|
+ )
|
||||||
|
+ locks = list_locks()
|
||||||
try:
|
try:
|
||||||
packages = list(__salt__['pkg_resource.parse_targets'](packages)[0].keys())
|
packages = list(__salt__["pkg_resource.parse_targets"](packages)[0].keys())
|
||||||
@@ -1804,6 +1845,50 @@ def remove_lock(packages, **kwargs): # pylint: disable=unused-argument
|
except MinionError as exc:
|
||||||
return {'removed': len(removed), 'not_found': missing}
|
@@ -2125,7 +2154,51 @@ def remove_lock(packages, root=None, **kwargs): # pylint: disable=unused-argume
|
||||||
|
return {"removed": len(removed), "not_found": missing}
|
||||||
|
|
||||||
|
|
||||||
|
-def add_lock(packages, root=None, **kwargs): # pylint: disable=unused-argument
|
||||||
+def hold(name=None, pkgs=None, **kwargs):
|
+def hold(name=None, pkgs=None, **kwargs):
|
||||||
+ '''
|
+ """
|
||||||
+ Add a package lock. Specify packages to lock by exact name.
|
+ Add a package lock. Specify packages to lock by exact name.
|
||||||
+
|
+
|
||||||
+ CLI Example:
|
+ CLI Example:
|
||||||
@ -99,46 +385,85 @@ index 50279ccbd1..08a9c2ed4d 100644
|
|||||||
+ :param pkgs:
|
+ :param pkgs:
|
||||||
+ :param kwargs:
|
+ :param kwargs:
|
||||||
+ :return:
|
+ :return:
|
||||||
+ '''
|
+ """
|
||||||
+ ret = {}
|
+ ret = {}
|
||||||
+ if (not name and not pkgs) or (name and pkgs):
|
+ if (not name and not pkgs) or (name and pkgs):
|
||||||
+ raise CommandExecutionError('Name or packages must be specified.')
|
+ raise CommandExecutionError("Name or packages must be specified.")
|
||||||
+ elif name:
|
+ elif name:
|
||||||
+ pkgs = [name]
|
+ pkgs = [name]
|
||||||
+
|
+
|
||||||
+ locks = list_locks()
|
+ locks = list_locks()
|
||||||
+ added = []
|
+ added = []
|
||||||
+ try:
|
+ try:
|
||||||
+ pkgs = list(__salt__['pkg_resource.parse_targets'](pkgs)[0].keys())
|
+ pkgs = list(__salt__["pkg_resource.parse_targets"](pkgs)[0].keys())
|
||||||
+ except MinionError as exc:
|
+ except MinionError as exc:
|
||||||
+ raise CommandExecutionError(exc)
|
+ raise CommandExecutionError(exc)
|
||||||
+
|
+
|
||||||
+ for pkg in pkgs:
|
+ for pkg in pkgs:
|
||||||
+ ret[pkg] = {'name': pkg, 'changes': {}, 'result': False, 'comment': ''}
|
+ ret[pkg] = {"name": pkg, "changes": {}, "result": False, "comment": ""}
|
||||||
+ if not locks.get(pkg):
|
+ if not locks.get(pkg):
|
||||||
+ added.append(pkg)
|
+ added.append(pkg)
|
||||||
+ ret[pkg]['comment'] = 'Package {0} is now being held.'.format(pkg)
|
+ ret[pkg]["comment"] = "Package {} is now being held.".format(pkg)
|
||||||
+ else:
|
+ else:
|
||||||
+ ret[pkg]['comment'] = 'Package {0} is already set to be held.'.format(pkg)
|
+ ret[pkg]["comment"] = "Package {} is already set to be held.".format(pkg)
|
||||||
+
|
+
|
||||||
+ if added:
|
+ if added:
|
||||||
+ __zypper__.call('al', *added)
|
+ __zypper__.call("al", *added)
|
||||||
+
|
+
|
||||||
+ return ret
|
+ return ret
|
||||||
+
|
+
|
||||||
+
|
+
|
||||||
def add_lock(packages, **kwargs): # pylint: disable=unused-argument
|
+def add_lock(packages, **kwargs): # pylint: disable=unused-argument
|
||||||
'''
|
"""
|
||||||
Add a package lock. Specify packages to lock by exact name.
|
Add a package lock. Specify packages to lock by exact name.
|
||||||
@@ -1816,6 +1901,7 @@ def add_lock(packages, **kwargs): # pylint: disable=unused-argument
|
|
||||||
|
@@ -2140,7 +2213,10 @@ def add_lock(packages, root=None, **kwargs): # pylint: disable=unused-argument
|
||||||
salt '*' pkg.add_lock <package1>,<package2>,<package3>
|
salt '*' pkg.add_lock <package1>,<package2>,<package3>
|
||||||
salt '*' pkg.add_lock pkgs='["foo", "bar"]'
|
salt '*' pkg.add_lock pkgs='["foo", "bar"]'
|
||||||
'''
|
"""
|
||||||
+ salt.utils.versions.warn_until('Sodium', 'This function is deprecated. Please use hold() instead.')
|
- locks = list_locks(root)
|
||||||
locks = list_locks()
|
+ salt.utils.versions.warn_until(
|
||||||
|
+ "Sodium", "This function is deprecated. Please use hold() instead."
|
||||||
|
+ )
|
||||||
|
+ locks = list_locks()
|
||||||
added = []
|
added = []
|
||||||
try:
|
try:
|
||||||
|
packages = list(__salt__["pkg_resource.parse_targets"](packages)[0].keys())
|
||||||
|
@@ -2495,7 +2571,7 @@ def search(criteria, refresh=False, **kwargs):
|
||||||
|
.getElementsByTagName("solvable")
|
||||||
|
)
|
||||||
|
if not solvables:
|
||||||
|
- raise CommandExecutionError("No packages found matching '{0}'".format(criteria))
|
||||||
|
+ raise CommandExecutionError("No packages found matching '{}'".format(criteria))
|
||||||
|
|
||||||
|
out = {}
|
||||||
|
for solvable in solvables:
|
||||||
|
@@ -2649,13 +2725,13 @@ def download(*packages, **kwargs):
|
||||||
|
if failed:
|
||||||
|
pkg_ret[
|
||||||
|
"_error"
|
||||||
|
- ] = "The following package(s) failed to download: {0}".format(
|
||||||
|
+ ] = "The following package(s) failed to download: {}".format(
|
||||||
|
", ".join(failed)
|
||||||
|
)
|
||||||
|
return pkg_ret
|
||||||
|
|
||||||
|
raise CommandExecutionError(
|
||||||
|
- "Unable to download packages: {0}".format(", ".join(packages))
|
||||||
|
+ "Unable to download packages: {}".format(", ".join(packages))
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@@ -2726,7 +2802,7 @@ def diff(*paths, **kwargs):
|
||||||
|
|
||||||
|
if pkg_to_paths:
|
||||||
|
local_pkgs = __salt__["pkg.download"](*pkg_to_paths.keys(), **kwargs)
|
||||||
|
- for pkg, files in six.iteritems(pkg_to_paths):
|
||||||
|
+ for pkg, files in pkg_to_paths.items():
|
||||||
|
for path in files:
|
||||||
|
ret[path] = (
|
||||||
|
__salt__["lowpkg.diff"](local_pkgs[pkg]["path"], path)
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From 5254ec34316a0924edb4856f84e6092fafe479fa Mon Sep 17 00:00:00 2001
|
From 57cab2d4e282f8b1d17610e6b4a0e772494bfcb1 Mon Sep 17 00:00:00 2001
|
||||||
From: Alberto Planas <aplanas@suse.com>
|
From: Alberto Planas <aplanas@suse.com>
|
||||||
Date: Tue, 20 Oct 2020 11:43:09 +0200
|
Date: Tue, 20 Oct 2020 11:43:09 +0200
|
||||||
Subject: [PATCH] Add "migrated" state and GPG key management functions
|
Subject: [PATCH] Add "migrated" state and GPG key management functions
|
||||||
@ -20,17 +20,16 @@ same virtual package, based on the counterpart from rpm_lowpkg API.
|
|||||||
---
|
---
|
||||||
changelog/58782.added | 1 +
|
changelog/58782.added | 1 +
|
||||||
salt/modules/aptpkg.py | 7 +-
|
salt/modules/aptpkg.py | 7 +-
|
||||||
salt/modules/rpm_lowpkg.py | 151 ++++++++
|
salt/modules/rpm_lowpkg.py | 151 +++++++++
|
||||||
salt/modules/yumpkg.py | 88 +++++
|
salt/modules/yumpkg.py | 88 +++++
|
||||||
salt/modules/zypperpkg.py | 90 ++++-
|
salt/modules/zypperpkg.py | 88 +++++
|
||||||
salt/states/pkgrepo.py | 208 ++++++++++
|
salt/states/pkgrepo.py | 207 ++++++++++++
|
||||||
tests/unit/modules/test_rpm_lowpkg.py | 215 +++++++++++
|
tests/unit/modules/test_rpm_lowpkg.py | 236 ++++++++++++-
|
||||||
tests/unit/modules/test_yumpkg.py | 43 ++-
|
tests/unit/modules/test_yumpkg.py | 41 ++-
|
||||||
tests/unit/modules/test_zypperpkg.py | 40 +-
|
tests/unit/modules/test_zypperpkg.py | 40 ++-
|
||||||
tests/unit/states/test_pkgrepo.py | 527 ++++++++++++++++++++++++++
|
tests/unit/states/test_pkgrepo.py | 468 +++++++++++++++++++++++++-
|
||||||
10 files changed, 1363 insertions(+), 7 deletions(-)
|
10 files changed, 1301 insertions(+), 26 deletions(-)
|
||||||
create mode 100644 changelog/58782.added
|
create mode 100644 changelog/58782.added
|
||||||
create mode 100644 tests/unit/states/test_pkgrepo.py
|
|
||||||
|
|
||||||
diff --git a/changelog/58782.added b/changelog/58782.added
|
diff --git a/changelog/58782.added b/changelog/58782.added
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
@ -41,43 +40,43 @@ index 0000000000..f9e69f64f2
|
|||||||
+Add GPG key functions in "lowpkg" and a "migrated" function in the "pkgrepo" state for repository and GPG key migration.
|
+Add GPG key functions in "lowpkg" and a "migrated" function in the "pkgrepo" state for repository and GPG key migration.
|
||||||
\ No newline at end of file
|
\ No newline at end of file
|
||||||
diff --git a/salt/modules/aptpkg.py b/salt/modules/aptpkg.py
|
diff --git a/salt/modules/aptpkg.py b/salt/modules/aptpkg.py
|
||||||
index 765d69aff2..28b8597ef5 100644
|
index e4a9872aad..e001d2f11c 100644
|
||||||
--- a/salt/modules/aptpkg.py
|
--- a/salt/modules/aptpkg.py
|
||||||
+++ b/salt/modules/aptpkg.py
|
+++ b/salt/modules/aptpkg.py
|
||||||
@@ -1878,7 +1878,7 @@ def _convert_if_int(value):
|
@@ -1908,7 +1908,7 @@ def _convert_if_int(value):
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
-def get_repo_keys():
|
-def get_repo_keys():
|
||||||
+def get_repo_keys(**kwargs):
|
+def get_repo_keys(**kwargs):
|
||||||
'''
|
"""
|
||||||
.. versionadded:: 2017.7.0
|
.. versionadded:: 2017.7.0
|
||||||
|
|
||||||
@@ -1950,7 +1950,9 @@ def get_repo_keys():
|
@@ -1990,7 +1990,9 @@ def get_repo_keys():
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
-def add_repo_key(path=None, text=None, keyserver=None, keyid=None, saltenv='base'):
|
-def add_repo_key(path=None, text=None, keyserver=None, keyid=None, saltenv="base"):
|
||||||
+def add_repo_key(
|
+def add_repo_key(
|
||||||
+ path=None, text=None, keyserver=None, keyid=None, saltenv='base', **kwargs
|
+ path=None, text=None, keyserver=None, keyid=None, saltenv="base", **kwargs
|
||||||
+):
|
+):
|
||||||
'''
|
"""
|
||||||
.. versionadded:: 2017.7.0
|
.. versionadded:: 2017.7.0
|
||||||
|
|
||||||
@@ -1976,7 +1978,6 @@ def add_repo_key(path=None, text=None, keyserver=None, keyid=None, saltenv='base
|
@@ -2016,7 +2018,6 @@ def add_repo_key(path=None, text=None, keyserver=None, keyid=None, saltenv="base
|
||||||
salt '*' pkg.add_repo_key keyserver='keyserver.example' keyid='0000AAAA'
|
salt '*' pkg.add_repo_key keyserver='keyserver.example' keyid='0000AAAA'
|
||||||
'''
|
"""
|
||||||
cmd = ['apt-key']
|
cmd = ["apt-key"]
|
||||||
- kwargs = {}
|
- kwargs = {}
|
||||||
|
|
||||||
current_repo_keys = get_repo_keys()
|
current_repo_keys = get_repo_keys()
|
||||||
|
|
||||||
diff --git a/salt/modules/rpm_lowpkg.py b/salt/modules/rpm_lowpkg.py
|
diff --git a/salt/modules/rpm_lowpkg.py b/salt/modules/rpm_lowpkg.py
|
||||||
index c8a87276b2..fee0221a7c 100644
|
index 393b0f453a..57f336bacf 100644
|
||||||
--- a/salt/modules/rpm_lowpkg.py
|
--- a/salt/modules/rpm_lowpkg.py
|
||||||
+++ b/salt/modules/rpm_lowpkg.py
|
+++ b/salt/modules/rpm_lowpkg.py
|
||||||
@@ -823,3 +823,154 @@ def checksum(*paths, **kwargs):
|
@@ -835,3 +835,154 @@ def checksum(*paths, **kwargs):
|
||||||
python_shell=False))
|
)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
+
|
+
|
||||||
@ -232,12 +231,12 @@ index c8a87276b2..fee0221a7c 100644
|
|||||||
+ cmd.extend(["-e", key])
|
+ cmd.extend(["-e", key])
|
||||||
+ return __salt__["cmd.retcode"](cmd) == 0
|
+ return __salt__["cmd.retcode"](cmd) == 0
|
||||||
diff --git a/salt/modules/yumpkg.py b/salt/modules/yumpkg.py
|
diff --git a/salt/modules/yumpkg.py b/salt/modules/yumpkg.py
|
||||||
index 04ab240cd4..85a2dbd857 100644
|
index c58b3e4c70..dd843f985b 100644
|
||||||
--- a/salt/modules/yumpkg.py
|
--- a/salt/modules/yumpkg.py
|
||||||
+++ b/salt/modules/yumpkg.py
|
+++ b/salt/modules/yumpkg.py
|
||||||
@@ -3271,3 +3271,91 @@ def list_installed_patches(**kwargs):
|
@@ -3346,3 +3346,91 @@ def list_installed_patches(**kwargs):
|
||||||
salt '*' pkg.list_installed_patches
|
salt '*' pkg.list_installed_patches
|
||||||
'''
|
"""
|
||||||
return _get_patches(installed_only=True)
|
return _get_patches(installed_only=True)
|
||||||
+
|
+
|
||||||
+
|
+
|
||||||
@ -328,19 +327,10 @@ index 04ab240cd4..85a2dbd857 100644
|
|||||||
+ """
|
+ """
|
||||||
+ return __salt__["lowpkg.remove_gpg_key"](keyid, root)
|
+ return __salt__["lowpkg.remove_gpg_key"](keyid, root)
|
||||||
diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py
|
diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py
|
||||||
index d84a6af6e0..fab7736701 100644
|
index d06c265202..5e13c68708 100644
|
||||||
--- a/salt/modules/zypperpkg.py
|
--- a/salt/modules/zypperpkg.py
|
||||||
+++ b/salt/modules/zypperpkg.py
|
+++ b/salt/modules/zypperpkg.py
|
||||||
@@ -1270,7 +1270,7 @@ def mod_repo(repo, **kwargs):
|
@@ -3004,3 +3004,91 @@ def resolve_capabilities(pkgs, refresh=False, root=None, **kwargs):
|
||||||
cmd_opt.append("--priority={0}".format(kwargs.get('priority', DEFAULT_PRIORITY)))
|
|
||||||
|
|
||||||
if 'humanname' in kwargs:
|
|
||||||
- cmd_opt.append("--name='{0}'".format(kwargs.get('humanname')))
|
|
||||||
+ cmd_opt.extend(["--name", kwargs.get("humanname")])
|
|
||||||
|
|
||||||
if kwargs.get('gpgautoimport') is True:
|
|
||||||
global_cmd_opt.append('--gpg-auto-import-keys')
|
|
||||||
@@ -2879,3 +2879,91 @@ def resolve_capabilities(pkgs, refresh=False, root=None, **kwargs):
|
|
||||||
else:
|
else:
|
||||||
ret.append(name)
|
ret.append(name)
|
||||||
return ret
|
return ret
|
||||||
@ -433,27 +423,19 @@ index d84a6af6e0..fab7736701 100644
|
|||||||
+ """
|
+ """
|
||||||
+ return __salt__["lowpkg.remove_gpg_key"](keyid, root)
|
+ return __salt__["lowpkg.remove_gpg_key"](keyid, root)
|
||||||
diff --git a/salt/states/pkgrepo.py b/salt/states/pkgrepo.py
|
diff --git a/salt/states/pkgrepo.py b/salt/states/pkgrepo.py
|
||||||
index c39e857580..6c42d17d32 100644
|
index 70cb7a1c7e..d734bb9de9 100644
|
||||||
--- a/salt/states/pkgrepo.py
|
--- a/salt/states/pkgrepo.py
|
||||||
+++ b/salt/states/pkgrepo.py
|
+++ b/salt/states/pkgrepo.py
|
||||||
@@ -84,6 +84,7 @@ package managers are APT, DNF, YUM and Zypper. Here is some example SLS:
|
@@ -93,6 +93,7 @@ package managers are APT, DNF, YUM and Zypper. Here is some example SLS:
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
# Import Python libs
|
|
||||||
from __future__ import absolute_import, print_function, unicode_literals
|
|
||||||
+import os
|
+import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
# Import salt libs
|
import salt.utils.data
|
||||||
@@ -96,6 +97,7 @@ import salt.utils.pkg.rpm
|
@@ -679,3 +680,209 @@ def absent(name, **kwargs):
|
||||||
|
ret["comment"] = "Failed to remove repo {}".format(name)
|
||||||
# Import 3rd-party libs
|
|
||||||
from salt.ext import six
|
|
||||||
+import salt.utils.versions
|
|
||||||
|
|
||||||
|
|
||||||
def __virtual__():
|
|
||||||
@@ -643,3 +645,209 @@ def absent(name, **kwargs):
|
|
||||||
ret['comment'] = 'Failed to remove repo {0}'.format(name)
|
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
+
|
+
|
||||||
@ -663,21 +645,49 @@ index c39e857580..6c42d17d32 100644
|
|||||||
+
|
+
|
||||||
+ return ret
|
+ return ret
|
||||||
diff --git a/tests/unit/modules/test_rpm_lowpkg.py b/tests/unit/modules/test_rpm_lowpkg.py
|
diff --git a/tests/unit/modules/test_rpm_lowpkg.py b/tests/unit/modules/test_rpm_lowpkg.py
|
||||||
index b6cbd9e5cb..ff3678fde5 100644
|
index ec9ecd40cb..84020263ea 100644
|
||||||
--- a/tests/unit/modules/test_rpm_lowpkg.py
|
--- a/tests/unit/modules/test_rpm_lowpkg.py
|
||||||
+++ b/tests/unit/modules/test_rpm_lowpkg.py
|
+++ b/tests/unit/modules/test_rpm_lowpkg.py
|
||||||
@@ -5,6 +5,7 @@
|
@@ -2,6 +2,7 @@
|
||||||
|
:codeauthor: Jayesh Kariya <jayeshk@saltstack.com>
|
||||||
|
"""
|
||||||
|
|
||||||
# Import Python Libs
|
|
||||||
from __future__ import absolute_import
|
|
||||||
+import datetime
|
+import datetime
|
||||||
|
|
||||||
# Import Salt Testing Libs
|
import salt.modules.rpm_lowpkg as rpm
|
||||||
from tests.support.mixins import LoaderModuleMockMixin
|
from tests.support.mixins import LoaderModuleMockMixin
|
||||||
@@ -205,3 +206,217 @@ class RpmTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -15,8 +16,8 @@ def _called_with_root(mock):
|
||||||
with patch('salt.modules.rpm_lowpkg.rpm.labelCompare', MagicMock(return_value=0)), \
|
|
||||||
patch('salt.modules.rpm_lowpkg.HAS_RPM', False):
|
|
||||||
self.assertEqual(-1, rpm.version_cmp('1', '2')) # mock returns -1, a python implementation was called
|
def _called_with_root(mock):
|
||||||
|
- cmd = ' '.join(mock.call_args[0][0])
|
||||||
|
- return cmd.startswith('rpm --root /')
|
||||||
|
+ cmd = " ".join(mock.call_args[0][0])
|
||||||
|
+ return cmd.startswith("rpm --root /")
|
||||||
|
|
||||||
|
|
||||||
|
class RpmTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
|
@@ -263,14 +264,223 @@ class RpmTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
|
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
- self.assertEqual(-1, rpm.version_cmp("1", "2"))
|
||||||
|
- self.assertEqual(mock_version_cmp.called, True)
|
||||||
|
- self.assertEqual(mock_log.warning.called, True)
|
||||||
|
- self.assertEqual(
|
||||||
|
- mock_log.warning.mock_calls[0][1][0],
|
||||||
|
- "Please install a package that provides rpm.labelCompare for more accurate version comparisons.",
|
||||||
|
- )
|
||||||
|
- self.assertEqual(
|
||||||
|
- mock_log.warning.mock_calls[1][1][0],
|
||||||
|
- "Falling back on salt.utils.versions.version_cmp() for version comparisons",
|
||||||
|
- )
|
||||||
|
+ with patch(
|
||||||
|
+ "salt.modules.rpm_lowpkg.rpm.labelCompare", MagicMock(return_value=0)
|
||||||
|
+ ), patch("salt.modules.rpm_lowpkg.HAS_RPM", False):
|
||||||
|
+ self.assertEqual(
|
||||||
|
+ -1, rpm.version_cmp("1", "2")
|
||||||
|
+ ) # mock returns -1, a python implementation was called
|
||||||
+
|
+
|
||||||
+ def test_list_gpg_keys_no_info(self):
|
+ def test_list_gpg_keys_no_info(self):
|
||||||
+ """
|
+ """
|
||||||
@ -893,39 +903,31 @@ index b6cbd9e5cb..ff3678fde5 100644
|
|||||||
+ self.assertTrue(rpm.remove_gpg_key("gpg-pubkey-1"))
|
+ self.assertTrue(rpm.remove_gpg_key("gpg-pubkey-1"))
|
||||||
+ self.assertFalse(_called_with_root(mock))
|
+ self.assertFalse(_called_with_root(mock))
|
||||||
diff --git a/tests/unit/modules/test_yumpkg.py b/tests/unit/modules/test_yumpkg.py
|
diff --git a/tests/unit/modules/test_yumpkg.py b/tests/unit/modules/test_yumpkg.py
|
||||||
index 9fbe3d051e..dfe00a7181 100644
|
index 4784160d25..e65a1f8b8b 100644
|
||||||
--- a/tests/unit/modules/test_yumpkg.py
|
--- a/tests/unit/modules/test_yumpkg.py
|
||||||
+++ b/tests/unit/modules/test_yumpkg.py
|
+++ b/tests/unit/modules/test_yumpkg.py
|
||||||
@@ -10,15 +10,17 @@ from tests.support.unit import TestCase, skipIf
|
@@ -5,9 +5,9 @@ import salt.modules.pkg_resource as pkg_resource
|
||||||
from tests.support.mock import (
|
import salt.modules.rpm_lowpkg as rpm
|
||||||
Mock,
|
import salt.modules.yumpkg as yumpkg
|
||||||
MagicMock,
|
import salt.utils.platform
|
||||||
+ mock_open,
|
|
||||||
patch,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Import Salt libs
|
|
||||||
-from salt.exceptions import CommandExecutionError
|
-from salt.exceptions import CommandExecutionError
|
||||||
+from salt.exceptions import CommandExecutionError, SaltInvocationError
|
+from salt.exceptions import CommandExecutionError, SaltInvocationError
|
||||||
import salt.modules.rpm_lowpkg as rpm
|
from tests.support.mixins import LoaderModuleMockMixin
|
||||||
from salt.ext import six
|
-from tests.support.mock import MagicMock, Mock, patch
|
||||||
import salt.modules.yumpkg as yumpkg
|
+from tests.support.mock import MagicMock, Mock, mock_open, patch
|
||||||
import salt.modules.pkg_resource as pkg_resource
|
from tests.support.unit import TestCase, skipIf
|
||||||
+import salt.utils.platform
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import pytest
|
@@ -1630,6 +1630,43 @@ class YumTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
@@ -799,8 +801,45 @@ class YumTestCase(TestCase, LoaderModuleMockMixin):
|
ret = yumpkg.get_repo(repo, **kwargs)
|
||||||
with pytest.raises(CommandExecutionError):
|
assert ret == expected, ret
|
||||||
yumpkg._get_yum_config()
|
|
||||||
|
|
||||||
+ def test_get_repo_keys(self):
|
+ def test_get_repo_keys(self):
|
||||||
+ salt_mock = {"lowpkg.list_gpg_keys": MagicMock(return_value=True)}
|
+ salt_mock = {"lowpkg.list_gpg_keys": MagicMock(return_value=True)}
|
||||||
+ with patch.dict(yumpkg.__salt__, salt_mock):
|
+ with patch.dict(yumpkg.__salt__, salt_mock):
|
||||||
+ self.assertTrue(yumpkg.get_repo_keys(info=True, root="/mnt"))
|
+ self.assertTrue(yumpkg.get_repo_keys(info=True, root="/mnt"))
|
||||||
+ salt_mock["lowpkg.list_gpg_keys"].assert_called_once_with(True, "/mnt")
|
+ salt_mock["lowpkg.list_gpg_keys"].assert_called_once_with(True, "/mnt")
|
||||||
|
+
|
||||||
-@skipIf(pytest is None, 'PyTest is missing')
|
|
||||||
+ def test_add_repo_key_fail(self):
|
+ def test_add_repo_key_fail(self):
|
||||||
+ with self.assertRaises(SaltInvocationError):
|
+ with self.assertRaises(SaltInvocationError):
|
||||||
+ yumpkg.add_repo_key()
|
+ yumpkg.add_repo_key()
|
||||||
@ -957,25 +959,23 @@ index 9fbe3d051e..dfe00a7181 100644
|
|||||||
+ self.assertTrue(yumpkg.del_repo_key(keyid="keyid", root="/mnt"))
|
+ self.assertTrue(yumpkg.del_repo_key(keyid="keyid", root="/mnt"))
|
||||||
+ salt_mock["lowpkg.remove_gpg_key"].assert_called_once_with("keyid", "/mnt")
|
+ salt_mock["lowpkg.remove_gpg_key"].assert_called_once_with("keyid", "/mnt")
|
||||||
+
|
+
|
||||||
+
|
|
||||||
+@skipIf(pytest is None, "PyTest is missing")
|
@skipIf(pytest is None, "PyTest is missing")
|
||||||
class YumUtilsTestCase(TestCase, LoaderModuleMockMixin):
|
class YumUtilsTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
'''
|
|
||||||
Yum/Dnf utils tests.
|
|
||||||
diff --git a/tests/unit/modules/test_zypperpkg.py b/tests/unit/modules/test_zypperpkg.py
|
diff --git a/tests/unit/modules/test_zypperpkg.py b/tests/unit/modules/test_zypperpkg.py
|
||||||
index 8cc84485b5..1f2a7dc4b2 100644
|
index eaa4d9a76a..018c1ffbca 100644
|
||||||
--- a/tests/unit/modules/test_zypperpkg.py
|
--- a/tests/unit/modules/test_zypperpkg.py
|
||||||
+++ b/tests/unit/modules/test_zypperpkg.py
|
+++ b/tests/unit/modules/test_zypperpkg.py
|
||||||
@@ -22,7 +22,7 @@ from tests.support.mock import (
|
@@ -10,7 +10,7 @@ import salt.modules.pkg_resource as pkg_resource
|
||||||
import salt.utils.files
|
|
||||||
import salt.modules.zypperpkg as zypper
|
import salt.modules.zypperpkg as zypper
|
||||||
import salt.modules.pkg_resource as pkg_resource
|
import salt.utils.files
|
||||||
|
import salt.utils.pkg
|
||||||
-from salt.exceptions import CommandExecutionError
|
-from salt.exceptions import CommandExecutionError
|
||||||
+from salt.exceptions import CommandExecutionError, SaltInvocationError
|
+from salt.exceptions import CommandExecutionError, SaltInvocationError
|
||||||
|
from salt.ext import six
|
||||||
# Import 3rd-party libs
|
|
||||||
from salt.ext.six.moves import configparser
|
from salt.ext.six.moves import configparser
|
||||||
@@ -1728,3 +1728,41 @@ pattern() = package-c"""
|
from tests.support.mixins import LoaderModuleMockMixin
|
||||||
|
@@ -2175,3 +2175,41 @@ pattern() = package-c"""
|
||||||
python_shell=False,
|
python_shell=False,
|
||||||
env={"ZYPP_READONLY_HACK": "1"},
|
env={"ZYPP_READONLY_HACK": "1"},
|
||||||
)
|
)
|
||||||
@ -1018,79 +1018,33 @@ index 8cc84485b5..1f2a7dc4b2 100644
|
|||||||
+ self.assertTrue(zypper.del_repo_key(keyid="keyid", root="/mnt"))
|
+ self.assertTrue(zypper.del_repo_key(keyid="keyid", root="/mnt"))
|
||||||
+ salt_mock["lowpkg.remove_gpg_key"].assert_called_once_with("keyid", "/mnt")
|
+ salt_mock["lowpkg.remove_gpg_key"].assert_called_once_with("keyid", "/mnt")
|
||||||
diff --git a/tests/unit/states/test_pkgrepo.py b/tests/unit/states/test_pkgrepo.py
|
diff --git a/tests/unit/states/test_pkgrepo.py b/tests/unit/states/test_pkgrepo.py
|
||||||
new file mode 100644
|
index b2be5b4da1..135e545220 100644
|
||||||
index 0000000000..9d8d88abd9
|
--- a/tests/unit/states/test_pkgrepo.py
|
||||||
--- /dev/null
|
|
||||||
+++ b/tests/unit/states/test_pkgrepo.py
|
+++ b/tests/unit/states/test_pkgrepo.py
|
||||||
@@ -0,0 +1,527 @@
|
@@ -1,17 +1,12 @@
|
||||||
+"""
|
-# -*- coding: utf-8 -*-
|
||||||
+ :codeauthor: Tyler Johnson <tjohnson@saltstack.com>
|
"""
|
||||||
+"""
|
:codeauthor: Tyler Johnson <tjohnson@saltstack.com>
|
||||||
+import salt.states.pkgrepo as pkgrepo
|
"""
|
||||||
|
-# Import Python libs
|
||||||
|
-from __future__ import absolute_import
|
||||||
|
|
||||||
|
-# Import Salt Libs
|
||||||
|
import salt.states.pkgrepo as pkgrepo
|
||||||
|
-
|
||||||
|
-# Import Salt Testing Libs
|
||||||
+import salt.utils.platform
|
+import salt.utils.platform
|
||||||
+from tests.support.mixins import LoaderModuleMockMixin
|
from tests.support.mixins import LoaderModuleMockMixin
|
||||||
+from tests.support.mock import MagicMock, patch
|
from tests.support.mock import MagicMock, patch
|
||||||
|
-from tests.support.unit import TestCase
|
||||||
+from tests.support.unit import TestCase, skipIf
|
+from tests.support.unit import TestCase, skipIf
|
||||||
+
|
|
||||||
+
|
|
||||||
+class PkgrepoTestCase(TestCase, LoaderModuleMockMixin):
|
class PkgrepoTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
+ """
|
@@ -72,3 +67,462 @@ class PkgrepoTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
+ Test cases for salt.states.pkgrepo
|
},
|
||||||
+ """
|
ret["changes"],
|
||||||
+
|
)
|
||||||
+ def setup_loader_modules(self):
|
|
||||||
+ return {
|
|
||||||
+ pkgrepo: {
|
|
||||||
+ "__opts__": {"test": True},
|
|
||||||
+ "__grains__": {"os": "", "os_family": ""},
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ def test_new_key_url(self):
|
|
||||||
+ """
|
|
||||||
+ Test when only the key_url is changed that a change is triggered
|
|
||||||
+ """
|
|
||||||
+ kwargs = {
|
|
||||||
+ "name": "deb http://mock/ sid main",
|
|
||||||
+ "disabled": False,
|
|
||||||
+ }
|
|
||||||
+ key_url = "http://mock/changed_gpg.key"
|
|
||||||
+
|
|
||||||
+ with patch.dict(
|
|
||||||
+ pkgrepo.__salt__, {"pkg.get_repo": MagicMock(return_value=kwargs)}
|
|
||||||
+ ):
|
|
||||||
+ ret = pkgrepo.managed(key_url=key_url, **kwargs)
|
|
||||||
+ self.assertDictEqual(
|
|
||||||
+ {"key_url": {"old": None, "new": key_url}}, ret["changes"]
|
|
||||||
+ )
|
|
||||||
+
|
|
||||||
+ def test_update_key_url(self):
|
|
||||||
+ """
|
|
||||||
+ Test when only the key_url is changed that a change is triggered
|
|
||||||
+ """
|
|
||||||
+ kwargs = {
|
|
||||||
+ "name": "deb http://mock/ sid main",
|
|
||||||
+ "gpgcheck": 1,
|
|
||||||
+ "disabled": False,
|
|
||||||
+ "key_url": "http://mock/gpg.key",
|
|
||||||
+ }
|
|
||||||
+ changed_kwargs = kwargs.copy()
|
|
||||||
+ changed_kwargs["key_url"] = "http://mock/gpg2.key"
|
|
||||||
+
|
|
||||||
+ with patch.dict(
|
|
||||||
+ pkgrepo.__salt__, {"pkg.get_repo": MagicMock(return_value=kwargs)}
|
|
||||||
+ ):
|
|
||||||
+ ret = pkgrepo.managed(**changed_kwargs)
|
|
||||||
+ self.assertIn("key_url", ret["changes"], "Expected a change to key_url")
|
|
||||||
+ self.assertDictEqual(
|
|
||||||
+ {
|
|
||||||
+ "key_url": {
|
|
||||||
+ "old": kwargs["key_url"],
|
|
||||||
+ "new": changed_kwargs["key_url"],
|
|
||||||
+ }
|
|
||||||
+ },
|
|
||||||
+ ret["changes"],
|
|
||||||
+ )
|
|
||||||
+
|
+
|
||||||
+ def test__normalize_repo_suse(self):
|
+ def test__normalize_repo_suse(self):
|
||||||
+ repo = {
|
+ repo = {
|
||||||
@ -1551,6 +1505,6 @@ index 0000000000..9d8d88abd9
|
|||||||
+ },
|
+ },
|
||||||
+ )
|
+ )
|
||||||
--
|
--
|
||||||
2.29.1
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
From 082fa07e5301414b5b834b731aaa96bd5d966de7 Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
|
||||||
<psuarezhernandez@suse.com>
|
|
||||||
Date: Tue, 10 Mar 2020 13:16:05 +0000
|
|
||||||
Subject: [PATCH] Add missing _utils at loader grains_func
|
|
||||||
|
|
||||||
---
|
|
||||||
salt/loader.py | 1 +
|
|
||||||
1 file changed, 1 insertion(+)
|
|
||||||
|
|
||||||
diff --git a/salt/loader.py b/salt/loader.py
|
|
||||||
index c68562988d..742b2f8e22 100644
|
|
||||||
--- a/salt/loader.py
|
|
||||||
+++ b/salt/loader.py
|
|
||||||
@@ -683,6 +683,7 @@ def grain_funcs(opts, proxy=None):
|
|
||||||
__opts__ = salt.config.minion_config('/etc/salt/minion')
|
|
||||||
grainfuncs = salt.loader.grain_funcs(__opts__)
|
|
||||||
'''
|
|
||||||
+ _utils = utils(opts)
|
|
||||||
ret = LazyLoader(
|
|
||||||
_module_dirs(
|
|
||||||
opts,
|
|
||||||
--
|
|
||||||
2.23.0
|
|
||||||
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
|||||||
From 5c25babafd4e4bbe55626713851ea5d6345c43d1 Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
|
||||||
<psuarezhernandez@suse.com>
|
|
||||||
Date: Wed, 9 Oct 2019 13:03:33 +0100
|
|
||||||
Subject: [PATCH] Add missing 'fun' for returns from wfunc executions
|
|
||||||
|
|
||||||
---
|
|
||||||
salt/client/ssh/__init__.py | 4 ++++
|
|
||||||
1 file changed, 4 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/salt/client/ssh/__init__.py b/salt/client/ssh/__init__.py
|
|
||||||
index 4881540837..1373274739 100644
|
|
||||||
--- a/salt/client/ssh/__init__.py
|
|
||||||
+++ b/salt/client/ssh/__init__.py
|
|
||||||
@@ -682,6 +682,8 @@ class SSH(object):
|
|
||||||
data = {'return': data}
|
|
||||||
if 'id' not in data:
|
|
||||||
data['id'] = id_
|
|
||||||
+ if 'fun' not in data:
|
|
||||||
+ data['fun'] = fun
|
|
||||||
data['jid'] = jid # make the jid in the payload the same as the jid in the tag
|
|
||||||
self.event.fire_event(
|
|
||||||
data,
|
|
||||||
@@ -797,6 +799,8 @@ class SSH(object):
|
|
||||||
data = {'return': data}
|
|
||||||
if 'id' not in data:
|
|
||||||
data['id'] = id_
|
|
||||||
+ if 'fun' not in data:
|
|
||||||
+ data['fun'] = fun
|
|
||||||
data['jid'] = jid # make the jid in the payload the same as the jid in the tag
|
|
||||||
self.event.fire_event(
|
|
||||||
data,
|
|
||||||
--
|
|
||||||
2.16.4
|
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
From 0a6b5e92a4a74dee94eb33a939600f8c2e429c01 Mon Sep 17 00:00:00 2001
|
From c5e5dc304e897f8c1664cce29fe9ee63d84f3ae6 Mon Sep 17 00:00:00 2001
|
||||||
From: Bo Maryniuk <bo@suse.de>
|
From: Bo Maryniuk <bo@suse.de>
|
||||||
Date: Fri, 12 Oct 2018 16:20:40 +0200
|
Date: Fri, 12 Oct 2018 16:20:40 +0200
|
||||||
Subject: [PATCH] Add multi-file support and globbing to the filetree
|
Subject: [PATCH] Add multi-file support and globbing to the filetree
|
||||||
@ -12,37 +12,37 @@ Collect system logs and boot logs
|
|||||||
|
|
||||||
Support globbing in filetree
|
Support globbing in filetree
|
||||||
---
|
---
|
||||||
salt/cli/support/intfunc.py | 49 +++++++++++++++++++++--------------
|
salt/cli/support/intfunc.py | 49 ++++++++++++++++-----------
|
||||||
salt/cli/support/profiles/default.yml | 7 +++++
|
salt/cli/support/profiles/default.yml | 7 ++++
|
||||||
2 files changed, 37 insertions(+), 19 deletions(-)
|
2 files changed, 37 insertions(+), 19 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/cli/support/intfunc.py b/salt/cli/support/intfunc.py
|
diff --git a/salt/cli/support/intfunc.py b/salt/cli/support/intfunc.py
|
||||||
index 2727cd6394..f15f4d4097 100644
|
index d3d8f83cb8..a9f76a6003 100644
|
||||||
--- a/salt/cli/support/intfunc.py
|
--- a/salt/cli/support/intfunc.py
|
||||||
+++ b/salt/cli/support/intfunc.py
|
+++ b/salt/cli/support/intfunc.py
|
||||||
@@ -6,6 +6,7 @@ Internal functions.
|
@@ -3,6 +3,7 @@ Internal functions.
|
||||||
|
"""
|
||||||
|
# Maybe this needs to be a modules in a future?
|
||||||
|
|
||||||
from __future__ import absolute_import, print_function, unicode_literals
|
|
||||||
import os
|
|
||||||
+import glob
|
+import glob
|
||||||
from salt.cli.support.console import MessagesOutput
|
import os
|
||||||
import salt.utils.files
|
|
||||||
|
|
||||||
@@ -13,7 +14,7 @@ import salt.utils.files
|
import salt.utils.files
|
||||||
|
@@ -11,7 +12,7 @@ from salt.cli.support.console import MessagesOutput
|
||||||
out = MessagesOutput()
|
out = MessagesOutput()
|
||||||
|
|
||||||
|
|
||||||
-def filetree(collector, path):
|
-def filetree(collector, path):
|
||||||
+def filetree(collector, *paths):
|
+def filetree(collector, *paths):
|
||||||
'''
|
"""
|
||||||
Add all files in the tree. If the "path" is a file,
|
Add all files in the tree. If the "path" is a file,
|
||||||
only that file will be added.
|
only that file will be added.
|
||||||
@@ -21,22 +22,32 @@ def filetree(collector, path):
|
@@ -19,22 +20,32 @@ def filetree(collector, path):
|
||||||
:param path: File or directory
|
:param path: File or directory
|
||||||
:return:
|
:return:
|
||||||
'''
|
"""
|
||||||
- if not path:
|
- if not path:
|
||||||
- out.error('Path not defined', ident=2)
|
- out.error("Path not defined", ident=2)
|
||||||
- else:
|
- else:
|
||||||
- # The filehandler needs to be explicitly passed here, so PyLint needs to accept that.
|
- # The filehandler needs to be explicitly passed here, so PyLint needs to accept that.
|
||||||
- # pylint: disable=W8470
|
- # pylint: disable=W8470
|
||||||
@ -50,7 +50,7 @@ index 2727cd6394..f15f4d4097 100644
|
|||||||
- filename = os.path.basename(path)
|
- filename = os.path.basename(path)
|
||||||
- try:
|
- try:
|
||||||
- file_ref = salt.utils.files.fopen(path) # pylint: disable=W
|
- file_ref = salt.utils.files.fopen(path) # pylint: disable=W
|
||||||
- out.put('Add {}'.format(filename), indent=2)
|
- out.put("Add {}".format(filename), indent=2)
|
||||||
- collector.add(filename)
|
- collector.add(filename)
|
||||||
- collector.link(title=path, path=file_ref)
|
- collector.link(title=path, path=file_ref)
|
||||||
- except Exception as err:
|
- except Exception as err:
|
||||||
@ -62,9 +62,9 @@ index 2727cd6394..f15f4d4097 100644
|
|||||||
+ _paths += glob.glob(path)
|
+ _paths += glob.glob(path)
|
||||||
+ for path in set(_paths):
|
+ for path in set(_paths):
|
||||||
+ if not path:
|
+ if not path:
|
||||||
+ out.error('Path not defined', ident=2)
|
+ out.error("Path not defined", ident=2)
|
||||||
+ elif not os.path.exists(path):
|
+ elif not os.path.exists(path):
|
||||||
+ out.warning('Path {} does not exists'.format(path))
|
+ out.warning("Path {} does not exists".format(path))
|
||||||
else:
|
else:
|
||||||
- for fname in os.listdir(path):
|
- for fname in os.listdir(path):
|
||||||
- fname = os.path.join(path, fname)
|
- fname = os.path.join(path, fname)
|
||||||
@ -75,7 +75,7 @@ index 2727cd6394..f15f4d4097 100644
|
|||||||
+ filename = os.path.basename(path)
|
+ filename = os.path.basename(path)
|
||||||
+ try:
|
+ try:
|
||||||
+ file_ref = salt.utils.files.fopen(path) # pylint: disable=W
|
+ file_ref = salt.utils.files.fopen(path) # pylint: disable=W
|
||||||
+ out.put('Add {}'.format(filename), indent=2)
|
+ out.put("Add {}".format(filename), indent=2)
|
||||||
+ collector.add(filename)
|
+ collector.add(filename)
|
||||||
+ collector.link(title=path, path=file_ref)
|
+ collector.link(title=path, path=file_ref)
|
||||||
+ except Exception as err:
|
+ except Exception as err:
|
||||||
@ -111,6 +111,6 @@ index 01d9a26193..3defb5eef3 100644
|
|||||||
+ - /var/log/messages
|
+ - /var/log/messages
|
||||||
|
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From ad1323b4f83fa8f2954c0a965f4acaf91575a59b Mon Sep 17 00:00:00 2001
|
From 70d13dcc62286d5195bbf28b53aae61616cc0f8f Mon Sep 17 00:00:00 2001
|
||||||
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||||
<psuarezhernandez@suse.com>
|
<psuarezhernandez@suse.com>
|
||||||
Date: Thu, 26 Mar 2020 13:08:16 +0000
|
Date: Thu, 26 Mar 2020 13:08:16 +0000
|
||||||
@ -10,10 +10,10 @@ Subject: [PATCH] Add new custom SUSE capability for saltutil state
|
|||||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
diff --git a/salt/grains/extra.py b/salt/grains/extra.py
|
diff --git a/salt/grains/extra.py b/salt/grains/extra.py
|
||||||
index 1082b05dba7830ee53078cff86b5183b5eea2829..b30ab0091fee7cda8f74b861e9e9f95f8ad85b39 100644
|
index ddc22293ea..0eec27e628 100644
|
||||||
--- a/salt/grains/extra.py
|
--- a/salt/grains/extra.py
|
||||||
+++ b/salt/grains/extra.py
|
+++ b/salt/grains/extra.py
|
||||||
@@ -80,5 +80,6 @@ def config():
|
@@ -71,5 +71,6 @@ def config():
|
||||||
def suse_backported_capabilities():
|
def suse_backported_capabilities():
|
||||||
return {
|
return {
|
||||||
'__suse_reserved_pkg_all_versions_support': True,
|
'__suse_reserved_pkg_all_versions_support': True,
|
||||||
@ -22,6 +22,6 @@ index 1082b05dba7830ee53078cff86b5183b5eea2829..b30ab0091fee7cda8f74b861e9e9f95f
|
|||||||
+ '__suse_reserved_saltutil_states_support': True
|
+ '__suse_reserved_saltutil_states_support': True
|
||||||
}
|
}
|
||||||
--
|
--
|
||||||
2.23.0
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
107
add-patch-support-for-allow-vendor-change-option-wit.patch
Normal file
107
add-patch-support-for-allow-vendor-change-option-wit.patch
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
From cee4cc182b4740c912861c712dea7bc44eb70ffb Mon Sep 17 00:00:00 2001
|
||||||
|
From: Martin Seidl <mseidl@suse.de>
|
||||||
|
Date: Mon, 7 Dec 2020 01:10:51 +0100
|
||||||
|
Subject: [PATCH] add patch support for allow vendor change option with
|
||||||
|
zypper
|
||||||
|
|
||||||
|
---
|
||||||
|
salt/modules/zypperpkg.py | 46 +++++++++++++++++++++++++++------------
|
||||||
|
1 file changed, 32 insertions(+), 14 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py
|
||||||
|
index 6f22994bf0..4a5cb85e7c 100644
|
||||||
|
--- a/salt/modules/zypperpkg.py
|
||||||
|
+++ b/salt/modules/zypperpkg.py
|
||||||
|
@@ -35,7 +35,6 @@ import salt.utils.versions
|
||||||
|
from salt.exceptions import CommandExecutionError, MinionError, SaltInvocationError
|
||||||
|
|
||||||
|
# pylint: disable=import-error,redefined-builtin,no-name-in-module
|
||||||
|
-from salt.ext import six
|
||||||
|
from salt.ext.six.moves import configparser
|
||||||
|
from salt.ext.six.moves.urllib.parse import urlparse as _urlparse
|
||||||
|
from salt.utils.versions import LooseVersion
|
||||||
|
@@ -1431,6 +1430,7 @@ def install(
|
||||||
|
no_recommends=False,
|
||||||
|
root=None,
|
||||||
|
inclusion_detection=False,
|
||||||
|
+ novendorchange=True,
|
||||||
|
**kwargs
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
@@ -1478,6 +1478,10 @@ def install(
|
||||||
|
skip_verify
|
||||||
|
Skip the GPG verification check (e.g., ``--no-gpg-checks``)
|
||||||
|
|
||||||
|
+
|
||||||
|
+ novendorchange
|
||||||
|
+ Disallow vendor change
|
||||||
|
+
|
||||||
|
version
|
||||||
|
Can be either a version number, or the combination of a comparison
|
||||||
|
operator (<, >, <=, >=, =) and a version number (ex. '>1.2.3-4').
|
||||||
|
@@ -1638,6 +1642,22 @@ def install(
|
||||||
|
cmd_install.append(
|
||||||
|
kwargs.get("resolve_capabilities") and "--capability" or "--name"
|
||||||
|
)
|
||||||
|
+ if novendorchange:
|
||||||
|
+ if __grains__["osrelease_info"][0] > 11:
|
||||||
|
+ cmd_install.append("--no-allow-vendor-change")
|
||||||
|
+ log.info("Disabling vendor changes")
|
||||||
|
+ else:
|
||||||
|
+ log.warning(
|
||||||
|
+ "Enabling/Disabling vendor changes is not supported on this Zypper version"
|
||||||
|
+ )
|
||||||
|
+ else:
|
||||||
|
+ if __grains__["osrelease_info"][0] > 11:
|
||||||
|
+ cmd_install.append("--allow-vendor-change")
|
||||||
|
+ log.info("Enabling vendor changes")
|
||||||
|
+ else:
|
||||||
|
+ log.warning(
|
||||||
|
+ "Enabling/Disabling vendor changes is not supported on this Zypper version"
|
||||||
|
+ )
|
||||||
|
|
||||||
|
if not refresh:
|
||||||
|
cmd_install.insert(0, "--no-refresh")
|
||||||
|
@@ -1649,7 +1669,6 @@ def install(
|
||||||
|
cmd_install.extend(fromrepoopt)
|
||||||
|
if no_recommends:
|
||||||
|
cmd_install.append("--no-recommends")
|
||||||
|
-
|
||||||
|
errors = []
|
||||||
|
|
||||||
|
# Split the targets into batches of 500 packages each, so that
|
||||||
|
@@ -1793,19 +1812,18 @@ def upgrade(
|
||||||
|
cmd_update.extend(["--from" if dist_upgrade else "--repo", repo])
|
||||||
|
log.info("Targeting repos: %s", fromrepo)
|
||||||
|
|
||||||
|
- if dist_upgrade:
|
||||||
|
- # TODO: Grains validation should be moved to Zypper class
|
||||||
|
- if __grains__["osrelease_info"][0] > 11:
|
||||||
|
- if novendorchange:
|
||||||
|
- cmd_update.append("--no-allow-vendor-change")
|
||||||
|
- log.info("Disabling vendor changes")
|
||||||
|
- else:
|
||||||
|
- cmd_update.append("--allow-vendor-change")
|
||||||
|
- log.info("Enabling vendor changes")
|
||||||
|
+ # TODO: Grains validation should be moved to Zypper class
|
||||||
|
+ if __grains__["osrelease_info"][0] > 11:
|
||||||
|
+ if novendorchange:
|
||||||
|
+ cmd_update.append("--no-allow-vendor-change")
|
||||||
|
+ log.info("Disabling vendor changes")
|
||||||
|
else:
|
||||||
|
- log.warning(
|
||||||
|
- "Enabling/Disabling vendor changes is not supported on this Zypper version"
|
||||||
|
- )
|
||||||
|
+ cmd_update.append("--allow-vendor-change")
|
||||||
|
+ log.info("Enabling vendor changes")
|
||||||
|
+ else:
|
||||||
|
+ log.warning(
|
||||||
|
+ "Enabling/Disabling vendor changes is not supported on this Zypper version"
|
||||||
|
+ )
|
||||||
|
|
||||||
|
if no_recommends:
|
||||||
|
cmd_update.append("--no-recommends")
|
||||||
|
--
|
||||||
|
2.29.2
|
||||||
|
|
||||||
|
|
404
add-pkg.services_need_restart-302.patch
Normal file
404
add-pkg.services_need_restart-302.patch
Normal file
@ -0,0 +1,404 @@
|
|||||||
|
From c79f4a8619ff1275b2ec4400c1fb27d24c22a7eb Mon Sep 17 00:00:00 2001
|
||||||
|
From: Alexander Graul <mail@agraul.de>
|
||||||
|
Date: Tue, 8 Dec 2020 15:35:49 +0100
|
||||||
|
Subject: [PATCH] Add pkg.services_need_restart (#302)
|
||||||
|
|
||||||
|
* Add utils.systemd.pid_to_service function
|
||||||
|
|
||||||
|
This function translates a given PID to the systemd service name in case
|
||||||
|
the process belongs to a running service. It uses DBUS for the
|
||||||
|
translation if DBUS is available, falling back to parsing
|
||||||
|
``systemctl status -o json'' output.
|
||||||
|
|
||||||
|
* Add zypperpkg.services_need_restart
|
||||||
|
|
||||||
|
pkg.services_need_restart returns a list of system services that were
|
||||||
|
affected by package manager operations such as updates, downgrades or
|
||||||
|
reinstallations without having been restarted. This might cause issues,
|
||||||
|
e.g. in the case a shared object was loaded by a process and then
|
||||||
|
replaced by the package manager.
|
||||||
|
|
||||||
|
(cherry picked from commit b950fcdbd6cc8cb08e1413a0ed05e0ae21717cea)
|
||||||
|
|
||||||
|
* Add aptpkg.services_need_restart
|
||||||
|
|
||||||
|
pkg.services_need_restart returns a list of system services that were
|
||||||
|
affected by package manager operations such as updates, downgrades or
|
||||||
|
reinstallations without having been restarted. This might cause issues,
|
||||||
|
e.g. in the case a shared object was loaded by a process and then
|
||||||
|
replaced by the package manager.
|
||||||
|
|
||||||
|
Requires checkrestart, which is part of the debian-goodies package and
|
||||||
|
available from official Ubuntu and Debian repositories.
|
||||||
|
|
||||||
|
(cherry picked from commit b981f6ecb1a551b98c5cebab4975fc09c6a55a22)
|
||||||
|
|
||||||
|
* Add yumpkg.services_need_restart
|
||||||
|
|
||||||
|
pkg.services_need_restart returns a list of system services that were
|
||||||
|
affected by package manager operations such as updates, downgrades or
|
||||||
|
reinstallations without having been restarted. This might cause issues,
|
||||||
|
e.g. in the case a shared object was loaded by a process and then
|
||||||
|
replaced by the package manager.
|
||||||
|
|
||||||
|
Requires dnf with the needs-restarting plugin, which is part of
|
||||||
|
dnf-plugins-core and installed by default on RHEL/CentOS/Fedora.
|
||||||
|
Also requires systemd for the mapping between PIDs and systemd services.
|
||||||
|
|
||||||
|
(cherry picked from commit 5e2be1095729c9f73394e852b82749950957e6fb)
|
||||||
|
|
||||||
|
* Add changelog entry for issue #58261
|
||||||
|
|
||||||
|
(cherry picked from commit 148877ed8ff7a47132c1186274739e648f7acf1c)
|
||||||
|
|
||||||
|
* Simplify dnf needs-restarting output parsing
|
||||||
|
|
||||||
|
Co-authored-by: Wayne Werner <waynejwerner@gmail.com>
|
||||||
|
(cherry picked from commit beb5d60f3cc64b880ec25ca188f8a73f6ec493dd)
|
||||||
|
---
|
||||||
|
changelog/58261.added | 1 +
|
||||||
|
salt/modules/aptpkg.py | 42 ++++++++++++++++-
|
||||||
|
salt/modules/yumpkg.py | 36 +++++++++++++++
|
||||||
|
salt/modules/zypperpkg.py | 25 ++++++++++
|
||||||
|
salt/utils/systemd.py | 69 ++++++++++++++++++++++++++++
|
||||||
|
tests/unit/modules/test_aptpkg.py | 22 ++++++++-
|
||||||
|
tests/unit/modules/test_yumpkg.py | 32 ++++++++++++-
|
||||||
|
tests/unit/modules/test_zypperpkg.py | 14 ++++++
|
||||||
|
8 files changed, 238 insertions(+), 3 deletions(-)
|
||||||
|
create mode 100644 changelog/58261.added
|
||||||
|
|
||||||
|
diff --git a/changelog/58261.added b/changelog/58261.added
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000000..537a43e80d
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/changelog/58261.added
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+Added ``pkg.services_need_restart`` which lists system services that should be restarted after package management operations.
|
||||||
|
diff --git a/salt/modules/aptpkg.py b/salt/modules/aptpkg.py
|
||||||
|
index 03e99af733..a0e0cc30c1 100644
|
||||||
|
--- a/salt/modules/aptpkg.py
|
||||||
|
+++ b/salt/modules/aptpkg.py
|
||||||
|
@@ -38,7 +38,12 @@ import salt.utils.stringutils
|
||||||
|
import salt.utils.systemd
|
||||||
|
import salt.utils.versions
|
||||||
|
import salt.utils.yaml
|
||||||
|
-from salt.exceptions import CommandExecutionError, MinionError, SaltInvocationError
|
||||||
|
+from salt.exceptions import (
|
||||||
|
+ CommandExecutionError,
|
||||||
|
+ CommandNotFoundError,
|
||||||
|
+ MinionError,
|
||||||
|
+ SaltInvocationError,
|
||||||
|
+)
|
||||||
|
from salt.modules.cmdmod import _parse_env
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
@@ -3029,3 +3034,38 @@ def list_downloaded(root=None, **kwargs):
|
||||||
|
).isoformat(),
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def services_need_restart(**kwargs):
|
||||||
|
+ """
|
||||||
|
+ .. versionadded:: NEXT
|
||||||
|
+
|
||||||
|
+ List services that use files which have been changed by the
|
||||||
|
+ package manager. It might be needed to restart them.
|
||||||
|
+
|
||||||
|
+ Requires checkrestart from the debian-goodies package.
|
||||||
|
+
|
||||||
|
+ CLI Examples:
|
||||||
|
+
|
||||||
|
+ .. code-block:: bash
|
||||||
|
+
|
||||||
|
+ salt '*' pkg.services_need_restart
|
||||||
|
+ """
|
||||||
|
+ if not salt.utils.path.which_bin(["checkrestart"]):
|
||||||
|
+ raise CommandNotFoundError(
|
||||||
|
+ "'checkrestart' is needed. It is part of the 'debian-goodies' "
|
||||||
|
+ "package which can be installed from official repositories."
|
||||||
|
+ )
|
||||||
|
+
|
||||||
|
+ cmd = ["checkrestart", "--machine"]
|
||||||
|
+ services = set()
|
||||||
|
+
|
||||||
|
+ cr_output = __salt__["cmd.run_stdout"](cmd, python_shell=False)
|
||||||
|
+ for line in cr_output.split("\n"):
|
||||||
|
+ if not line.startswith("SERVICE:"):
|
||||||
|
+ continue
|
||||||
|
+ end_of_name = line.find(",")
|
||||||
|
+ service = line[8:end_of_name] # skip "SERVICE:"
|
||||||
|
+ services.add(service)
|
||||||
|
+
|
||||||
|
+ return list(services)
|
||||||
|
diff --git a/salt/modules/yumpkg.py b/salt/modules/yumpkg.py
|
||||||
|
index dd843f985b..df174e737d 100644
|
||||||
|
--- a/salt/modules/yumpkg.py
|
||||||
|
+++ b/salt/modules/yumpkg.py
|
||||||
|
@@ -3434,3 +3434,39 @@ def del_repo_key(keyid, root=None, **kwargs):
|
||||||
|
|
||||||
|
"""
|
||||||
|
return __salt__["lowpkg.remove_gpg_key"](keyid, root)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def services_need_restart(**kwargs):
|
||||||
|
+ """
|
||||||
|
+ .. versionadded:: NEXT
|
||||||
|
+
|
||||||
|
+ List services that use files which have been changed by the
|
||||||
|
+ package manager. It might be needed to restart them.
|
||||||
|
+
|
||||||
|
+ Requires systemd.
|
||||||
|
+
|
||||||
|
+ CLI Examples:
|
||||||
|
+
|
||||||
|
+ .. code-block:: bash
|
||||||
|
+
|
||||||
|
+ salt '*' pkg.services_need_restart
|
||||||
|
+ """
|
||||||
|
+ if _yum() != "dnf":
|
||||||
|
+ raise CommandExecutionError("dnf is required to list outdated services.")
|
||||||
|
+ if not salt.utils.systemd.booted(__context__):
|
||||||
|
+ raise CommandExecutionError("systemd is required to list outdated services.")
|
||||||
|
+
|
||||||
|
+ cmd = ["dnf", "--quiet", "needs-restarting"]
|
||||||
|
+ dnf_output = __salt__["cmd.run_stdout"](cmd, python_shell=False)
|
||||||
|
+ if not dnf_output:
|
||||||
|
+ return []
|
||||||
|
+
|
||||||
|
+ services = set()
|
||||||
|
+ for line in dnf_output.split("\n"):
|
||||||
|
+ pid, has_delim, _ = line.partition(":")
|
||||||
|
+ if has_delim:
|
||||||
|
+ service = salt.utils.systemd.pid_to_service(pid.strip())
|
||||||
|
+ if service:
|
||||||
|
+ services.add(service)
|
||||||
|
+
|
||||||
|
+ return list(services)
|
||||||
|
diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py
|
||||||
|
index 5e13c68708..6f22994bf0 100644
|
||||||
|
--- a/salt/modules/zypperpkg.py
|
||||||
|
+++ b/salt/modules/zypperpkg.py
|
||||||
|
@@ -3092,3 +3092,28 @@ def del_repo_key(keyid, root=None, **kwargs):
|
||||||
|
|
||||||
|
"""
|
||||||
|
return __salt__["lowpkg.remove_gpg_key"](keyid, root)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def services_need_restart(root=None, **kwargs):
|
||||||
|
+ """
|
||||||
|
+ .. versionadded:: NEXT
|
||||||
|
+
|
||||||
|
+ List services that use files which have been changed by the
|
||||||
|
+ package manager. It might be needed to restart them.
|
||||||
|
+
|
||||||
|
+ root
|
||||||
|
+ operate on a different root directory.
|
||||||
|
+
|
||||||
|
+ CLI Examples:
|
||||||
|
+
|
||||||
|
+ .. code-block:: bash
|
||||||
|
+
|
||||||
|
+ salt '*' pkg.services_need_restart
|
||||||
|
+
|
||||||
|
+ """
|
||||||
|
+ cmd = ["ps", "-sss"]
|
||||||
|
+
|
||||||
|
+ zypper_output = __zypper__(root=root).nolock.call(*cmd)
|
||||||
|
+ services = zypper_output.split()
|
||||||
|
+
|
||||||
|
+ return services
|
||||||
|
diff --git a/salt/utils/systemd.py b/salt/utils/systemd.py
|
||||||
|
index 4d902bc920..f42d0421f8 100644
|
||||||
|
--- a/salt/utils/systemd.py
|
||||||
|
+++ b/salt/utils/systemd.py
|
||||||
|
@@ -11,6 +11,12 @@ import salt.utils.path
|
||||||
|
import salt.utils.stringutils
|
||||||
|
from salt.exceptions import SaltInvocationError
|
||||||
|
|
||||||
|
+try:
|
||||||
|
+ import dbus
|
||||||
|
+except ImportError:
|
||||||
|
+ dbus = None
|
||||||
|
+
|
||||||
|
+
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@@ -114,3 +120,66 @@ def has_scope(context=None):
|
||||||
|
if _sd_version is None:
|
||||||
|
return False
|
||||||
|
return _sd_version >= 205
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def pid_to_service(pid):
|
||||||
|
+ """
|
||||||
|
+ Check if a PID belongs to a systemd service and return its name.
|
||||||
|
+ Return None if the PID does not belong to a service.
|
||||||
|
+
|
||||||
|
+ Uses DBUS if available.
|
||||||
|
+ """
|
||||||
|
+ if dbus:
|
||||||
|
+ return _pid_to_service_dbus(pid)
|
||||||
|
+ else:
|
||||||
|
+ return _pid_to_service_systemctl(pid)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def _pid_to_service_systemctl(pid):
|
||||||
|
+ systemd_cmd = ["systemctl", "--output", "json", "status", str(pid)]
|
||||||
|
+ try:
|
||||||
|
+ systemd_output = subprocess.run(
|
||||||
|
+ systemd_cmd, check=True, text=True, capture_output=True
|
||||||
|
+ )
|
||||||
|
+ status_json = salt.utils.json.find_json(systemd_output.stdout)
|
||||||
|
+ except (ValueError, subprocess.CalledProcessError):
|
||||||
|
+ return None
|
||||||
|
+
|
||||||
|
+ name = status_json.get("_SYSTEMD_UNIT")
|
||||||
|
+ if name and name.endswith(".service"):
|
||||||
|
+ return _strip_suffix(name)
|
||||||
|
+ else:
|
||||||
|
+ return None
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def _pid_to_service_dbus(pid):
|
||||||
|
+ """
|
||||||
|
+ Use DBUS to check if a PID belongs to a running systemd service and return the service name if it does.
|
||||||
|
+ """
|
||||||
|
+ bus = dbus.SystemBus()
|
||||||
|
+ systemd_object = bus.get_object(
|
||||||
|
+ "org.freedesktop.systemd1", "/org/freedesktop/systemd1"
|
||||||
|
+ )
|
||||||
|
+ systemd = dbus.Interface(systemd_object, "org.freedesktop.systemd1.Manager")
|
||||||
|
+ try:
|
||||||
|
+ service_path = systemd.GetUnitByPID(pid)
|
||||||
|
+ service_object = bus.get_object("org.freedesktop.systemd1", service_path)
|
||||||
|
+ service_props = dbus.Interface(
|
||||||
|
+ service_object, "org.freedesktop.DBus.Properties"
|
||||||
|
+ )
|
||||||
|
+ service_name = service_props.Get("org.freedesktop.systemd1.Unit", "Id")
|
||||||
|
+ name = str(service_name)
|
||||||
|
+
|
||||||
|
+ if name and name.endswith(".service"):
|
||||||
|
+ return _strip_suffix(name)
|
||||||
|
+ else:
|
||||||
|
+ return None
|
||||||
|
+ except dbus.DBusException:
|
||||||
|
+ return None
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+def _strip_suffix(service_name):
|
||||||
|
+ """
|
||||||
|
+ Strip ".service" suffix from a given service name.
|
||||||
|
+ """
|
||||||
|
+ return service_name[:-8]
|
||||||
|
diff --git a/tests/unit/modules/test_aptpkg.py b/tests/unit/modules/test_aptpkg.py
|
||||||
|
index eb3f9e2da7..1d4d2f7fdc 100644
|
||||||
|
--- a/tests/unit/modules/test_aptpkg.py
|
||||||
|
+++ b/tests/unit/modules/test_aptpkg.py
|
||||||
|
@@ -13,7 +13,6 @@ import textwrap
|
||||||
|
import pytest
|
||||||
|
import salt.modules.aptpkg as aptpkg
|
||||||
|
from salt.exceptions import CommandExecutionError, SaltInvocationError
|
||||||
|
-from salt.ext import six
|
||||||
|
from tests.support.mixins import LoaderModuleMockMixin
|
||||||
|
from tests.support.mock import MagicMock, Mock, call, patch
|
||||||
|
from tests.support.unit import TestCase, skipIf
|
||||||
|
@@ -1001,3 +1000,24 @@ class AptUtilsTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
|
# We should attempt to call the cmd 5 times
|
||||||
|
self.assertEqual(cmd_mock.call_count, 5)
|
||||||
|
cmd_mock.has_calls(expected_calls)
|
||||||
|
+
|
||||||
|
+ @patch("salt.utils.path.which_bin", Mock(return_value="/usr/sbin/checkrestart"))
|
||||||
|
+ def test_services_need_restart(self):
|
||||||
|
+ """
|
||||||
|
+ Test that checkrestart output is parsed correctly
|
||||||
|
+ """
|
||||||
|
+ cr_output = """
|
||||||
|
+PROCESSES: 24
|
||||||
|
+PROGRAMS: 17
|
||||||
|
+PACKAGES: 8
|
||||||
|
+SERVICE:rsyslog,385,/usr/sbin/rsyslogd
|
||||||
|
+SERVICE:cups-daemon,390,/usr/sbin/cupsd
|
||||||
|
+ """
|
||||||
|
+
|
||||||
|
+ with patch.dict(
|
||||||
|
+ aptpkg.__salt__, {"cmd.run_stdout": Mock(return_value=cr_output)}
|
||||||
|
+ ):
|
||||||
|
+ assert sorted(aptpkg.services_need_restart()) == [
|
||||||
|
+ "cups-daemon",
|
||||||
|
+ "rsyslog",
|
||||||
|
+ ]
|
||||||
|
diff --git a/tests/unit/modules/test_yumpkg.py b/tests/unit/modules/test_yumpkg.py
|
||||||
|
index e65a1f8b8b..b97e82d307 100644
|
||||||
|
--- a/tests/unit/modules/test_yumpkg.py
|
||||||
|
+++ b/tests/unit/modules/test_yumpkg.py
|
||||||
|
@@ -7,7 +7,7 @@ import salt.modules.yumpkg as yumpkg
|
||||||
|
import salt.utils.platform
|
||||||
|
from salt.exceptions import CommandExecutionError, SaltInvocationError
|
||||||
|
from tests.support.mixins import LoaderModuleMockMixin
|
||||||
|
-from tests.support.mock import MagicMock, Mock, mock_open, patch
|
||||||
|
+from tests.support.mock import MagicMock, Mock, call, mock_open, patch
|
||||||
|
from tests.support.unit import TestCase, skipIf
|
||||||
|
|
||||||
|
try:
|
||||||
|
@@ -1745,3 +1745,33 @@ class YumUtilsTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
|
python_shell=True,
|
||||||
|
username="Darth Vader",
|
||||||
|
)
|
||||||
|
+
|
||||||
|
+ @skipIf(not salt.utils.systemd.booted(), "Requires systemd")
|
||||||
|
+ @patch("salt.modules.yumpkg._yum", Mock(return_value="dnf"))
|
||||||
|
+ def test_services_need_restart(self):
|
||||||
|
+ """
|
||||||
|
+ Test that dnf needs-restarting output is parsed and
|
||||||
|
+ salt.utils.systemd.pid_to_service is called as expected.
|
||||||
|
+ """
|
||||||
|
+ expected = ["firewalld", "salt-minion"]
|
||||||
|
+
|
||||||
|
+ dnf_mock = Mock(
|
||||||
|
+ return_value="123 : /usr/bin/firewalld\n456 : /usr/bin/salt-minion\n"
|
||||||
|
+ )
|
||||||
|
+ systemd_mock = Mock(side_effect=["firewalld", "salt-minion"])
|
||||||
|
+ with patch.dict(yumpkg.__salt__, {"cmd.run_stdout": dnf_mock}), patch(
|
||||||
|
+ "salt.utils.systemd.pid_to_service", systemd_mock
|
||||||
|
+ ):
|
||||||
|
+ assert sorted(yumpkg.services_need_restart()) == expected
|
||||||
|
+ systemd_mock.assert_has_calls([call("123"), call("456")])
|
||||||
|
+
|
||||||
|
+ @patch("salt.modules.yumpkg._yum", Mock(return_value="dnf"))
|
||||||
|
+ def test_services_need_restart_requires_systemd(self):
|
||||||
|
+ """Test that yumpkg.services_need_restart raises an error if systemd is unavailable."""
|
||||||
|
+ with patch("salt.utils.systemd.booted", Mock(return_value=False)):
|
||||||
|
+ pytest.raises(CommandExecutionError, yumpkg.services_need_restart)
|
||||||
|
+
|
||||||
|
+ @patch("salt.modules.yumpkg._yum", Mock(return_value="yum"))
|
||||||
|
+ def test_services_need_restart_requires_dnf(self):
|
||||||
|
+ """Test that yumpkg.services_need_restart raises an error if DNF is unavailable."""
|
||||||
|
+ pytest.raises(CommandExecutionError, yumpkg.services_need_restart)
|
||||||
|
diff --git a/tests/unit/modules/test_zypperpkg.py b/tests/unit/modules/test_zypperpkg.py
|
||||||
|
index 018c1ffbca..9c4a224c55 100644
|
||||||
|
--- a/tests/unit/modules/test_zypperpkg.py
|
||||||
|
+++ b/tests/unit/modules/test_zypperpkg.py
|
||||||
|
@@ -2213,3 +2213,17 @@ pattern() = package-c"""
|
||||||
|
with patch.dict(zypper.__salt__, salt_mock):
|
||||||
|
self.assertTrue(zypper.del_repo_key(keyid="keyid", root="/mnt"))
|
||||||
|
salt_mock["lowpkg.remove_gpg_key"].assert_called_once_with("keyid", "/mnt")
|
||||||
|
+
|
||||||
|
+ def test_services_need_restart(self):
|
||||||
|
+ """
|
||||||
|
+ Test that zypper ps is used correctly to list services that need to
|
||||||
|
+ be restarted.
|
||||||
|
+ """
|
||||||
|
+ expected = ["salt-minion", "firewalld"]
|
||||||
|
+ zypper_output = "salt-minion\nfirewalld"
|
||||||
|
+ zypper_mock = Mock()
|
||||||
|
+ zypper_mock(root=None).nolock.call = Mock(return_value=zypper_output)
|
||||||
|
+
|
||||||
|
+ 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")
|
||||||
|
--
|
||||||
|
2.29.2
|
||||||
|
|
||||||
|
|
@ -1,27 +1,26 @@
|
|||||||
From da936daeebd701e147707ad814c07bfc259d4be4 Mon Sep 17 00:00:00 2001
|
From 2422d30358bcd0f96e399e623136f7984d136b38 Mon Sep 17 00:00:00 2001
|
||||||
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||||
<psuarezhernandez@suse.com>
|
<psuarezhernandez@suse.com>
|
||||||
Date: Thu, 28 May 2020 09:37:08 +0100
|
Date: Thu, 28 May 2020 09:37:08 +0100
|
||||||
Subject: [PATCH] Add publish_batch to ClearFuncs exposed methods
|
Subject: [PATCH] Add publish_batch to ClearFuncs exposed methods
|
||||||
|
|
||||||
---
|
---
|
||||||
salt/master.py | 2 +-
|
salt/master.py | 1 +
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
1 file changed, 1 insertion(+)
|
||||||
|
|
||||||
diff --git a/salt/master.py b/salt/master.py
|
diff --git a/salt/master.py b/salt/master.py
|
||||||
index 485c16029b12fc38fc88b54aba95f03aa95d14ee..7d7a094a1a212180bfb294df3ad8b38477981450 100644
|
index ab85c7f5c6..59bb19ce75 100644
|
||||||
--- a/salt/master.py
|
--- a/salt/master.py
|
||||||
+++ b/salt/master.py
|
+++ b/salt/master.py
|
||||||
@@ -1906,7 +1906,7 @@ class ClearFuncs(TransportMethods):
|
@@ -2042,6 +2042,7 @@ class ClearFuncs(TransportMethods):
|
||||||
# These methods will be exposed to the transport layer by
|
|
||||||
# MWorker._handle_clear
|
|
||||||
expose_methods = (
|
expose_methods = (
|
||||||
- 'ping', 'publish', 'get_token', 'mk_token', 'wheel', 'runner',
|
"ping",
|
||||||
+ 'ping', 'publish', 'publish_batch', 'get_token', 'mk_token', 'wheel', 'runner',
|
"publish",
|
||||||
)
|
+ "publish_batch",
|
||||||
|
"get_token",
|
||||||
# The ClearFuncs object encapsulates the functions that can be executed in
|
"mk_token",
|
||||||
|
"wheel",
|
||||||
--
|
--
|
||||||
2.23.0
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From 369567107fa18187f8cbc5040728037d0774287b Mon Sep 17 00:00:00 2001
|
From 99aa26e7ab4840cf38f54e7692d7d1eede3adeb4 Mon Sep 17 00:00:00 2001
|
||||||
From: Bo Maryniuk <bo@suse.de>
|
From: Bo Maryniuk <bo@suse.de>
|
||||||
Date: Mon, 12 Mar 2018 12:01:39 +0100
|
Date: Mon, 12 Mar 2018 12:01:39 +0100
|
||||||
Subject: [PATCH] Add SaltSSH multi-version support across Python
|
Subject: [PATCH] Add SaltSSH multi-version support across Python
|
||||||
@ -254,10 +254,9 @@ Lintfix
|
|||||||
|
|
||||||
Set master_top_first to False by default
|
Set master_top_first to False by default
|
||||||
---
|
---
|
||||||
doc/topics/releases/fluorine.rst | 178 +++++++++++++++++++++++++++++++++++++++
|
doc/topics/releases/fluorine.rst | 178 +++++++++++++++++++++++++++++++
|
||||||
salt/client/ssh/ssh_py_shim.py | 4 +
|
salt/client/ssh/ssh_py_shim.py | 3 +
|
||||||
salt/utils/thin.py | 1 +
|
2 files changed, 181 insertions(+)
|
||||||
3 files changed, 183 insertions(+)
|
|
||||||
create mode 100644 doc/topics/releases/fluorine.rst
|
create mode 100644 doc/topics/releases/fluorine.rst
|
||||||
|
|
||||||
diff --git a/doc/topics/releases/fluorine.rst b/doc/topics/releases/fluorine.rst
|
diff --git a/doc/topics/releases/fluorine.rst b/doc/topics/releases/fluorine.rst
|
||||||
@ -445,39 +444,20 @@ index 0000000000..40c69e25cc
|
|||||||
+Salt version is also available on the Master machine, although does not need to be directly
|
+Salt version is also available on the Master machine, although does not need to be directly
|
||||||
+installed together with the older Python interpreter.
|
+installed together with the older Python interpreter.
|
||||||
diff --git a/salt/client/ssh/ssh_py_shim.py b/salt/client/ssh/ssh_py_shim.py
|
diff --git a/salt/client/ssh/ssh_py_shim.py b/salt/client/ssh/ssh_py_shim.py
|
||||||
index cd7549a178..95b3931a32 100644
|
index c0ce0fd7de..5ddd282ed0 100644
|
||||||
--- a/salt/client/ssh/ssh_py_shim.py
|
--- a/salt/client/ssh/ssh_py_shim.py
|
||||||
+++ b/salt/client/ssh/ssh_py_shim.py
|
+++ b/salt/client/ssh/ssh_py_shim.py
|
||||||
@@ -165,6 +165,9 @@ def unpack_thin(thin_path):
|
@@ -171,6 +171,9 @@ def unpack_thin(thin_path):
|
||||||
old_umask = os.umask(0o077) # pylint: disable=blacklisted-function
|
old_umask = os.umask(0o077) # pylint: disable=blacklisted-function
|
||||||
tfile.extractall(path=OPTIONS.saltdir)
|
tfile.extractall(path=OPTIONS.saltdir)
|
||||||
tfile.close()
|
tfile.close()
|
||||||
+ checksum_path = os.path.normpath(os.path.join(OPTIONS.saltdir, "thin_checksum"))
|
+ checksum_path = os.path.normpath(os.path.join(OPTIONS.saltdir, "thin_checksum"))
|
||||||
+ with open(checksum_path, 'w') as chk:
|
+ with open(checksum_path, "w") as chk:
|
||||||
+ chk.write(OPTIONS.checksum + '\n')
|
+ chk.write(OPTIONS.checksum + "\n")
|
||||||
os.umask(old_umask) # pylint: disable=blacklisted-function
|
os.umask(old_umask) # pylint: disable=blacklisted-function
|
||||||
try:
|
try:
|
||||||
os.unlink(thin_path)
|
os.unlink(thin_path)
|
||||||
@@ -358,5 +361,6 @@ def main(argv): # pylint: disable=W0613
|
|
||||||
return retcode
|
|
||||||
|
|
||||||
|
|
||||||
+
|
|
||||||
if __name__ == '__main__':
|
|
||||||
sys.exit(main(sys.argv))
|
|
||||||
diff --git a/salt/utils/thin.py b/salt/utils/thin.py
|
|
||||||
index 8496db9569..0ff31cef39 100644
|
|
||||||
--- a/salt/utils/thin.py
|
|
||||||
+++ b/salt/utils/thin.py
|
|
||||||
@@ -9,6 +9,7 @@ from __future__ import absolute_import, print_function, unicode_literals
|
|
||||||
import copy
|
|
||||||
import logging
|
|
||||||
import os
|
|
||||||
+import copy
|
|
||||||
import shutil
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
From 717c9bc6cb81994c5f23de87cfa91112fa7bf89c Mon Sep 17 00:00:00 2001
|
From 8ad65d6fa39edc7fc1967e2df1f3db0aa7df4d11 Mon Sep 17 00:00:00 2001
|
||||||
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||||
<psuarezhernandez@suse.com>
|
<psuarezhernandez@suse.com>
|
||||||
Date: Wed, 22 May 2019 13:00:46 +0100
|
Date: Wed, 22 May 2019 13:00:46 +0100
|
||||||
Subject: [PATCH] Add standalone configuration file for enabling package
|
Subject: [PATCH] Add standalone configuration file for enabling
|
||||||
formulas
|
package formulas
|
||||||
|
|
||||||
---
|
---
|
||||||
conf/suse/standalone-formulas-configuration.conf | 4 ++++
|
conf/suse/standalone-formulas-configuration.conf | 4 ++++
|
||||||
@ -21,6 +21,6 @@ index 0000000000..94d05fb2ee
|
|||||||
+ - /usr/share/salt-formulas/states
|
+ - /usr/share/salt-formulas/states
|
||||||
+ - /srv/salt
|
+ - /srv/salt
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
|||||||
From 82ddc9d93f6c0d6bc1e8dc6ebd30d6809d9f4d8f Mon Sep 17 00:00:00 2001
|
From ca2ad86438293af6715a9890b168f159ff4d9b9b Mon Sep 17 00:00:00 2001
|
||||||
From: =?UTF-8?q?C=C3=A9dric=20Bosdonnat?= <cbosdonnat@suse.com>
|
From: =?UTF-8?q?C=C3=A9dric=20Bosdonnat?= <cbosdonnat@suse.com>
|
||||||
Date: Thu, 18 Oct 2018 13:32:59 +0200
|
Date: Thu, 18 Oct 2018 13:32:59 +0200
|
||||||
Subject: [PATCH] Add virt.all_capabilities
|
Subject: [PATCH] Add virt.all_capabilities
|
||||||
@ -10,100 +10,37 @@ before calling virt.domain_capabilities for each of them.
|
|||||||
This commit embeds all this logic to get them all in a single
|
This commit embeds all this logic to get them all in a single
|
||||||
virt.all_capabilities call.
|
virt.all_capabilities call.
|
||||||
---
|
---
|
||||||
salt/modules/virt.py | 107 +++++++++++++++++++++++++++++-----------
|
salt/modules/virt.py | 73 +++++++++++++++++++++++++++++++--
|
||||||
tests/unit/modules/test_virt.py | 56 +++++++++++++++++++++
|
tests/unit/modules/test_virt.py | 2 +-
|
||||||
2 files changed, 134 insertions(+), 29 deletions(-)
|
2 files changed, 71 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/modules/virt.py b/salt/modules/virt.py
|
diff --git a/salt/modules/virt.py b/salt/modules/virt.py
|
||||||
index a2412bb745..3889238ecd 100644
|
index 313181c49e..362c2a68b5 100644
|
||||||
--- a/salt/modules/virt.py
|
--- a/salt/modules/virt.py
|
||||||
+++ b/salt/modules/virt.py
|
+++ b/salt/modules/virt.py
|
||||||
@@ -4254,37 +4254,10 @@ def _parse_caps_loader(node):
|
@@ -5568,11 +5568,76 @@ def _parse_domain_caps(caps):
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
-def domain_capabilities(emulator=None, arch=None, machine=None, domain=None, **kwargs):
|
|
||||||
+def _parse_domain_caps(caps):
|
+def _parse_domain_caps(caps):
|
||||||
'''
|
+ """
|
||||||
- Return the domain capabilities given an emulator, architecture, machine or virtualization type.
|
|
||||||
-
|
|
||||||
- .. versionadded:: 2019.2.0
|
|
||||||
-
|
|
||||||
- :param emulator: return the capabilities for the given emulator binary
|
|
||||||
- :param arch: return the capabilities for the given CPU architecture
|
|
||||||
- :param machine: return the capabilities for the given emulated machine type
|
|
||||||
- :param domain: return the capabilities for the given virtualization type.
|
|
||||||
- :param connection: libvirt connection URI, overriding defaults
|
|
||||||
- :param username: username to connect with, overriding defaults
|
|
||||||
- :param password: password to connect with, overriding defaults
|
|
||||||
-
|
|
||||||
- The list of the possible emulator, arch, machine and domain can be found in
|
|
||||||
- the host capabilities output.
|
|
||||||
-
|
|
||||||
- If none of the parameters is provided the libvirt default domain capabilities
|
|
||||||
- will be returned.
|
|
||||||
-
|
|
||||||
- CLI Example:
|
|
||||||
-
|
|
||||||
- .. code-block:: bash
|
|
||||||
-
|
|
||||||
- salt '*' virt.domain_capabilities arch='x86_64' domain='kvm'
|
|
||||||
-
|
|
||||||
+ Parse the XML document of domain capabilities into a structure.
|
+ Parse the XML document of domain capabilities into a structure.
|
||||||
'''
|
+ """
|
||||||
- conn = __get_conn(**kwargs)
|
+ result = {
|
||||||
- caps = ElementTree.fromstring(conn.getDomainCapabilities(emulator, arch, machine, domain, 0))
|
+ "emulator": caps.find("path").text if caps.find("path") is not None else None,
|
||||||
- conn.close()
|
+ "domain": caps.find("domain").text if caps.find("domain") is not None else None,
|
||||||
-
|
+ "machine": caps.find("machine").text
|
||||||
result = {
|
+ if caps.find("machine") is not None
|
||||||
'emulator': caps.find('path').text if caps.find('path') is not None else None,
|
+ else None,
|
||||||
'domain': caps.find('domain').text if caps.find('domain') is not None else None,
|
+ "arch": caps.find("arch").text if caps.find("arch") is not None else None,
|
||||||
@@ -4324,6 +4297,82 @@ def domain_capabilities(emulator=None, arch=None, machine=None, domain=None, **k
|
+ }
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
+def domain_capabilities(emulator=None, arch=None, machine=None, domain=None, **kwargs):
|
|
||||||
+ '''
|
|
||||||
+ Return the domain capabilities given an emulator, architecture, machine or virtualization type.
|
|
||||||
+
|
|
||||||
+ .. versionadded:: Fluorine
|
|
||||||
+
|
|
||||||
+ :param emulator: return the capabilities for the given emulator binary
|
|
||||||
+ :param arch: return the capabilities for the given CPU architecture
|
|
||||||
+ :param machine: return the capabilities for the given emulated machine type
|
|
||||||
+ :param domain: return the capabilities for the given virtualization type.
|
|
||||||
+ :param connection: libvirt connection URI, overriding defaults
|
|
||||||
+ :param username: username to connect with, overriding defaults
|
|
||||||
+ :param password: password to connect with, overriding defaults
|
|
||||||
+
|
|
||||||
+ The list of the possible emulator, arch, machine and domain can be found in
|
|
||||||
+ the host capabilities output.
|
|
||||||
+
|
|
||||||
+ If none of the parameters is provided, the libvirt default one is returned.
|
|
||||||
+
|
|
||||||
+ CLI Example:
|
|
||||||
+
|
|
||||||
+ .. code-block:: bash
|
|
||||||
+
|
|
||||||
+ salt '*' virt.domain_capabilities arch='x86_64' domain='kvm'
|
|
||||||
+
|
|
||||||
+ '''
|
|
||||||
+ conn = __get_conn(**kwargs)
|
|
||||||
+ result = []
|
|
||||||
+ try:
|
|
||||||
+ caps = ElementTree.fromstring(conn.getDomainCapabilities(emulator, arch, machine, domain, 0))
|
|
||||||
+ result = _parse_domain_caps(caps)
|
|
||||||
+ finally:
|
|
||||||
+ conn.close()
|
|
||||||
+
|
|
||||||
+ return result
|
|
||||||
+
|
+
|
||||||
+
|
+
|
||||||
+def all_capabilities(**kwargs):
|
+def all_capabilities(**kwargs):
|
||||||
+ '''
|
+ """
|
||||||
+ Return the host and domain capabilities in a single call.
|
+ Return the host and domain capabilities in a single call.
|
||||||
+
|
+
|
||||||
+ .. versionadded:: Neon
|
+ .. versionadded:: 3001
|
||||||
+
|
+
|
||||||
+ :param connection: libvirt connection URI, overriding defaults
|
+ :param connection: libvirt connection URI, overriding defaults
|
||||||
+ :param username: username to connect with, overriding defaults
|
+ :param username: username to connect with, overriding defaults
|
||||||
@ -115,100 +52,94 @@ index a2412bb745..3889238ecd 100644
|
|||||||
+
|
+
|
||||||
+ salt '*' virt.all_capabilities
|
+ salt '*' virt.all_capabilities
|
||||||
+
|
+
|
||||||
+ '''
|
+ """
|
||||||
+ conn = __get_conn(**kwargs)
|
+ conn = __get_conn(**kwargs)
|
||||||
+ result = {}
|
|
||||||
+ try:
|
+ try:
|
||||||
+ host_caps = ElementTree.fromstring(conn.getCapabilities())
|
+ host_caps = ElementTree.fromstring(conn.getCapabilities())
|
||||||
+ domains = [[(guest.get('arch', {}).get('name', None), key)
|
+ domains = [
|
||||||
+ for key in guest.get('arch', {}).get('domains', {}).keys()]
|
+ [
|
||||||
+ for guest in [_parse_caps_guest(guest) for guest in host_caps.findall('guest')]]
|
+ (guest.get("arch", {}).get("name", None), key)
|
||||||
|
+ for key in guest.get("arch", {}).get("domains", {}).keys()
|
||||||
|
+ ]
|
||||||
|
+ for guest in [
|
||||||
|
+ _parse_caps_guest(guest) for guest in host_caps.findall("guest")
|
||||||
|
+ ]
|
||||||
|
+ ]
|
||||||
+ flattened = [pair for item in (x for x in domains) for pair in item]
|
+ flattened = [pair for item in (x for x in domains) for pair in item]
|
||||||
+ result = {
|
+ result = {
|
||||||
+ 'host': {
|
+ "host": {
|
||||||
+ 'host': _parse_caps_host(host_caps.find('host')),
|
+ "host": _parse_caps_host(host_caps.find("host")),
|
||||||
+ 'guests': [_parse_caps_guest(guest) for guest in host_caps.findall('guest')]
|
+ "guests": [
|
||||||
|
+ _parse_caps_guest(guest) for guest in host_caps.findall("guest")
|
||||||
|
+ ],
|
||||||
+ },
|
+ },
|
||||||
+ 'domains': [_parse_domain_caps(ElementTree.fromstring(
|
+ "domains": [
|
||||||
+ conn.getDomainCapabilities(None, arch, None, domain)))
|
+ _parse_domain_caps(
|
||||||
+ for (arch, domain) in flattened]}
|
+ ElementTree.fromstring(
|
||||||
|
+ conn.getDomainCapabilities(None, arch, None, domain)
|
||||||
|
+ )
|
||||||
|
+ )
|
||||||
|
+ for (arch, domain) in flattened
|
||||||
|
+ ],
|
||||||
|
+ }
|
||||||
|
+ return result
|
||||||
+ finally:
|
+ finally:
|
||||||
+ conn.close()
|
+ conn.close()
|
||||||
+
|
+
|
||||||
|
+
|
||||||
|
def domain_capabilities(emulator=None, arch=None, machine=None, domain=None, **kwargs):
|
||||||
|
"""
|
||||||
|
Return the domain capabilities given an emulator, architecture, machine or virtualization type.
|
||||||
|
|
||||||
|
- .. versionadded:: 2019.2.0
|
||||||
|
+ .. versionadded:: Fluorine
|
||||||
|
|
||||||
|
:param emulator: return the capabilities for the given emulator binary
|
||||||
|
:param arch: return the capabilities for the given CPU architecture
|
||||||
|
@@ -5611,7 +5676,7 @@ def all_capabilities(**kwargs):
|
||||||
|
"""
|
||||||
|
Return the host and domain capabilities in a single call.
|
||||||
|
|
||||||
|
- .. versionadded:: 3001
|
||||||
|
+ .. versionadded:: Neon
|
||||||
|
|
||||||
|
:param connection: libvirt connection URI, overriding defaults
|
||||||
|
:param username: username to connect with, overriding defaults
|
||||||
|
@@ -5625,6 +5690,7 @@ def all_capabilities(**kwargs):
|
||||||
|
|
||||||
|
"""
|
||||||
|
conn = __get_conn(**kwargs)
|
||||||
|
+ result = {}
|
||||||
|
try:
|
||||||
|
host_caps = ElementTree.fromstring(conn.getCapabilities())
|
||||||
|
domains = [
|
||||||
|
@@ -5653,10 +5719,11 @@ def all_capabilities(**kwargs):
|
||||||
|
for (arch, domain) in flattened
|
||||||
|
],
|
||||||
|
}
|
||||||
|
- return result
|
||||||
|
finally:
|
||||||
|
conn.close()
|
||||||
|
|
||||||
+ return result
|
+ return result
|
||||||
+
|
+
|
||||||
+
|
|
||||||
def cpu_baseline(full=False, migratable=False, out='libvirt', **kwargs):
|
def cpu_baseline(full=False, migratable=False, out="libvirt", **kwargs):
|
||||||
'''
|
"""
|
||||||
Return the optimal 'custom' CPU baseline config for VM's on this minion
|
|
||||||
diff --git a/tests/unit/modules/test_virt.py b/tests/unit/modules/test_virt.py
|
diff --git a/tests/unit/modules/test_virt.py b/tests/unit/modules/test_virt.py
|
||||||
index 32f4302e5f..94372c6d72 100644
|
index cce107c9e4..e9e73d7b5d 100644
|
||||||
--- a/tests/unit/modules/test_virt.py
|
--- a/tests/unit/modules/test_virt.py
|
||||||
+++ b/tests/unit/modules/test_virt.py
|
+++ b/tests/unit/modules/test_virt.py
|
||||||
@@ -2216,6 +2216,62 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -4063,7 +4063,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
|
"44454c4c-3400-105a-8033-b3c04f4b344a", caps["host"]["host"]["uuid"]
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
- {"qemu", "kvm"}, {domainCaps["domain"] for domainCaps in caps["domains"]},
|
||||||
|
+ {"qemu", "kvm"}, {domainCaps["domain"] for domainCaps in caps["domains"]}
|
||||||
|
)
|
||||||
|
|
||||||
self.assertEqual(expected, caps)
|
|
||||||
|
|
||||||
+ def test_all_capabilities(self):
|
|
||||||
+ '''
|
|
||||||
+ Test the virt.domain_capabilities default output
|
|
||||||
+ '''
|
|
||||||
+ domainXml = '''
|
|
||||||
+<domainCapabilities>
|
|
||||||
+ <path>/usr/bin/qemu-system-x86_64</path>
|
|
||||||
+ <domain>kvm</domain>
|
|
||||||
+ <machine>virt-2.12</machine>
|
|
||||||
+ <arch>x86_64</arch>
|
|
||||||
+ <vcpu max='255'/>
|
|
||||||
+ <iothreads supported='yes'/>
|
|
||||||
+</domainCapabilities>
|
|
||||||
+ '''
|
|
||||||
+ hostXml = '''
|
|
||||||
+<capabilities>
|
|
||||||
+ <host>
|
|
||||||
+ <uuid>44454c4c-3400-105a-8033-b3c04f4b344a</uuid>
|
|
||||||
+ <cpu>
|
|
||||||
+ <arch>x86_64</arch>
|
|
||||||
+ <model>Nehalem</model>
|
|
||||||
+ <vendor>Intel</vendor>
|
|
||||||
+ <microcode version='25'/>
|
|
||||||
+ <topology sockets='1' cores='4' threads='2'/>
|
|
||||||
+ </cpu>
|
|
||||||
+ </host>
|
|
||||||
+ <guest>
|
|
||||||
+ <os_type>hvm</os_type>
|
|
||||||
+ <arch name='x86_64'>
|
|
||||||
+ <wordsize>64</wordsize>
|
|
||||||
+ <emulator>/usr/bin/qemu-system-x86_64</emulator>
|
|
||||||
+ <machine maxCpus='255'>pc-i440fx-2.6</machine>
|
|
||||||
+ <machine canonical='pc-i440fx-2.6' maxCpus='255'>pc</machine>
|
|
||||||
+ <machine maxCpus='255'>pc-0.12</machine>
|
|
||||||
+ <domain type='qemu'/>
|
|
||||||
+ <domain type='kvm'>
|
|
||||||
+ <emulator>/usr/bin/qemu-kvm</emulator>
|
|
||||||
+ <machine maxCpus='255'>pc-i440fx-2.6</machine>
|
|
||||||
+ <machine canonical='pc-i440fx-2.6' maxCpus='255'>pc</machine>
|
|
||||||
+ <machine maxCpus='255'>pc-0.12</machine>
|
|
||||||
+ </domain>
|
|
||||||
+ </arch>
|
|
||||||
+ </guest>
|
|
||||||
+</capabilities>
|
|
||||||
+ '''
|
|
||||||
+
|
|
||||||
+ # pylint: disable=no-member
|
|
||||||
+ self.mock_conn.getCapabilities.return_value = hostXml
|
|
||||||
+ self.mock_conn.getDomainCapabilities.side_effect = [
|
|
||||||
+ domainXml, domainXml.replace('<domain>kvm', '<domain>qemu')]
|
|
||||||
+ # pylint: enable=no-member
|
|
||||||
+
|
|
||||||
+ caps = virt.all_capabilities()
|
|
||||||
+ self.assertEqual('44454c4c-3400-105a-8033-b3c04f4b344a', caps['host']['host']['uuid'])
|
|
||||||
+ self.assertEqual(set(['qemu', 'kvm']), set([domainCaps['domain'] for domainCaps in caps['domains']]))
|
|
||||||
+
|
|
||||||
def test_network_tag(self):
|
def test_network_tag(self):
|
||||||
'''
|
|
||||||
Test virt._get_net_xml() with VLAN tag
|
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From 2182f2cbc835fee8a95101ce0c722d582b7456aa Mon Sep 17 00:00:00 2001
|
From 12d67e0cfa54399f3a0b6ae0d4faa09793fa2b0f Mon Sep 17 00:00:00 2001
|
||||||
From: Jochen Breuer <jbreuer@suse.de>
|
From: Jochen Breuer <jbreuer@suse.de>
|
||||||
Date: Wed, 1 Apr 2020 16:13:23 +0200
|
Date: Wed, 1 Apr 2020 16:13:23 +0200
|
||||||
Subject: [PATCH] Adds explicit type cast for port
|
Subject: [PATCH] Adds explicit type cast for port
|
||||||
@ -12,22 +12,22 @@ The type casting to int solves this issue.
|
|||||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/utils/network.py b/salt/utils/network.py
|
diff --git a/salt/utils/network.py b/salt/utils/network.py
|
||||||
index d6543ff160..def997f3dc 100644
|
index 25b2d06758..1705a5809d 100644
|
||||||
--- a/salt/utils/network.py
|
--- a/salt/utils/network.py
|
||||||
+++ b/salt/utils/network.py
|
+++ b/salt/utils/network.py
|
||||||
@@ -1457,9 +1457,9 @@ def _netlink_tool_remote_on(port, which_end):
|
@@ -1626,9 +1626,9 @@ def _netlink_tool_remote_on(port, which_end):
|
||||||
local_host, local_port = chunks[3].rsplit(':', 1)
|
local_host, local_port = chunks[3].rsplit(":", 1)
|
||||||
remote_host, remote_port = chunks[4].rsplit(':', 1)
|
remote_host, remote_port = chunks[4].rsplit(":", 1)
|
||||||
|
|
||||||
- if which_end == 'remote_port' and int(remote_port) != port:
|
- if which_end == "remote_port" and int(remote_port) != port:
|
||||||
+ if which_end == 'remote_port' and int(remote_port) != int(port):
|
+ if which_end == "remote_port" and int(remote_port) != int(port):
|
||||||
continue
|
continue
|
||||||
- if which_end == 'local_port' and int(local_port) != port:
|
- if which_end == "local_port" and int(local_port) != port:
|
||||||
+ if which_end == 'local_port' and int(local_port) != int(port):
|
+ if which_end == "local_port" and int(local_port) != int(port):
|
||||||
continue
|
continue
|
||||||
remotes.add(remote_host.strip("[]"))
|
remotes.add(remote_host.strip("[]"))
|
||||||
|
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From 206a2f7c4c1104f2f35dfa2c0b775bef4adc5b91 Mon Sep 17 00:00:00 2001
|
From 125f973014b8d5ffa13ae7dd231043e39af75ea0 Mon Sep 17 00:00:00 2001
|
||||||
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||||
<psuarezhernandez@suse.com>
|
<psuarezhernandez@suse.com>
|
||||||
Date: Wed, 3 Jul 2019 09:34:50 +0100
|
Date: Wed, 3 Jul 2019 09:34:50 +0100
|
||||||
@ -8,61 +8,22 @@ Subject: [PATCH] Allow passing kwargs to pkg.list_downloaded
|
|||||||
Add unit test for pkg.list_downloaded with kwargs
|
Add unit test for pkg.list_downloaded with kwargs
|
||||||
---
|
---
|
||||||
salt/modules/zypperpkg.py | 2 +-
|
salt/modules/zypperpkg.py | 2 +-
|
||||||
tests/unit/modules/test_zypperpkg.py | 27 +++++++++++++++++++++++++++
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
2 files changed, 28 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py
|
diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py
|
||||||
index 582caffb59..3760b525e7 100644
|
index 75cb5ce4a8..c996935bff 100644
|
||||||
--- a/salt/modules/zypperpkg.py
|
--- a/salt/modules/zypperpkg.py
|
||||||
+++ b/salt/modules/zypperpkg.py
|
+++ b/salt/modules/zypperpkg.py
|
||||||
@@ -2557,7 +2557,7 @@ def download(*packages, **kwargs):
|
@@ -2754,7 +2754,7 @@ def download(*packages, **kwargs):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
-def list_downloaded(root=None):
|
-def list_downloaded(root=None):
|
||||||
+def list_downloaded(root=None, **kwargs):
|
+def list_downloaded(root=None, **kwargs):
|
||||||
'''
|
"""
|
||||||
.. versionadded:: 2017.7.0
|
.. versionadded:: 2017.7.0
|
||||||
|
|
||||||
diff --git a/tests/unit/modules/test_zypperpkg.py b/tests/unit/modules/test_zypperpkg.py
|
|
||||||
index 3a6466f061..12c22bfcb2 100644
|
|
||||||
--- a/tests/unit/modules/test_zypperpkg.py
|
|
||||||
+++ b/tests/unit/modules/test_zypperpkg.py
|
|
||||||
@@ -767,6 +767,33 @@ Repository 'DUMMY' not found by its alias, number, or URI.
|
|
||||||
self.assertEqual(len(list_patches), 3)
|
|
||||||
self.assertDictEqual(list_patches, PATCHES_RET)
|
|
||||||
|
|
||||||
+ @patch('salt.utils.path.os_walk', MagicMock(return_value=[('test', 'test', 'test')]))
|
|
||||||
+ @patch('os.path.getsize', MagicMock(return_value=123456))
|
|
||||||
+ @patch('os.path.getctime', MagicMock(return_value=1234567890.123456))
|
|
||||||
+ @patch('fnmatch.filter', MagicMock(return_value=['/var/cache/zypper/packages/foo/bar/test_package.rpm']))
|
|
||||||
+ def test_list_downloaded_with_kwargs(self):
|
|
||||||
+ '''
|
|
||||||
+ Test downloaded packages listing.
|
|
||||||
+
|
|
||||||
+ :return:
|
|
||||||
+ '''
|
|
||||||
+ DOWNLOADED_RET = {
|
|
||||||
+ 'test-package': {
|
|
||||||
+ '1.0': {
|
|
||||||
+ 'path': '/var/cache/zypper/packages/foo/bar/test_package.rpm',
|
|
||||||
+ 'size': 123456,
|
|
||||||
+ 'creation_date_time_t': 1234567890,
|
|
||||||
+ 'creation_date_time': '2009-02-13T23:31:30',
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ with patch.dict(zypper.__salt__, {'lowpkg.bin_pkg_info': MagicMock(return_value={'name': 'test-package',
|
|
||||||
+ 'version': '1.0'})}):
|
|
||||||
+ list_downloaded = zypper.list_downloaded(kw1=True, kw2=False)
|
|
||||||
+ self.assertEqual(len(list_downloaded), 1)
|
|
||||||
+ self.assertDictEqual(list_downloaded, DOWNLOADED_RET)
|
|
||||||
+
|
|
||||||
@patch('salt.utils.path.os_walk', MagicMock(return_value=[('test', 'test', 'test')]))
|
|
||||||
@patch('os.path.getsize', MagicMock(return_value=123456))
|
|
||||||
@patch('os.path.getctime', MagicMock(return_value=1234567890.123456))
|
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
|||||||
From b8226467e665650a0587b8fd64242faefb805e13 Mon Sep 17 00:00:00 2001
|
From 85464ec6c34fceee3379d268745c3294d27e7fb4 Mon Sep 17 00:00:00 2001
|
||||||
From: Steve Kowalik <steven@wedontsleep.org>
|
From: Steve Kowalik <steven@wedontsleep.org>
|
||||||
Date: Mon, 17 Feb 2020 15:34:00 +1100
|
Date: Mon, 17 Feb 2020 15:34:00 +1100
|
||||||
Subject: [PATCH] Apply patch from upstream to support Python 3.8
|
Subject: [PATCH] Apply patch from upstream to support Python 3.8
|
||||||
@ -8,14 +8,11 @@ deprecated module and changed some behaviour. Add a {Build,}Requires on
|
|||||||
python-distro, since it is now required.
|
python-distro, since it is now required.
|
||||||
---
|
---
|
||||||
pkg/suse/salt.spec | 2 ++
|
pkg/suse/salt.spec | 2 ++
|
||||||
salt/config/__init__.py | 4 +++-
|
salt/renderers/stateconf.py | 49 ++++++++++++++++---------------------
|
||||||
salt/grains/core.py | 16 ++++++++--------
|
2 files changed, 23 insertions(+), 28 deletions(-)
|
||||||
salt/renderers/stateconf.py | 8 ++++----
|
|
||||||
tests/unit/modules/test_virt.py | 2 +-
|
|
||||||
5 files changed, 18 insertions(+), 14 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/pkg/suse/salt.spec b/pkg/suse/salt.spec
|
diff --git a/pkg/suse/salt.spec b/pkg/suse/salt.spec
|
||||||
index e3e678af3b..0f6a9bc012 100644
|
index a17d2381ce..0df9d6c283 100644
|
||||||
--- a/pkg/suse/salt.spec
|
--- a/pkg/suse/salt.spec
|
||||||
+++ b/pkg/suse/salt.spec
|
+++ b/pkg/suse/salt.spec
|
||||||
@@ -62,6 +62,7 @@ BuildRequires: python-psutil
|
@@ -62,6 +62,7 @@ BuildRequires: python-psutil
|
||||||
@ -34,95 +31,205 @@ index e3e678af3b..0f6a9bc012 100644
|
|||||||
%if 0%{?suse_version}
|
%if 0%{?suse_version}
|
||||||
# requirements/opt.txt (not all)
|
# requirements/opt.txt (not all)
|
||||||
Recommends: python-MySQL-python
|
Recommends: python-MySQL-python
|
||||||
diff --git a/salt/config/__init__.py b/salt/config/__init__.py
|
|
||||||
index 0ebe1181dd..f484d94e7e 100644
|
|
||||||
--- a/salt/config/__init__.py
|
|
||||||
+++ b/salt/config/__init__.py
|
|
||||||
@@ -3196,7 +3196,9 @@ def apply_cloud_providers_config(overrides, defaults=None):
|
|
||||||
# Merge provided extends
|
|
||||||
keep_looping = False
|
|
||||||
for alias, entries in six.iteritems(providers.copy()):
|
|
||||||
- for driver, details in six.iteritems(entries):
|
|
||||||
+ for driver in list(six.iterkeys(entries)):
|
|
||||||
+ # Don't use iteritems, because the values of the dictionary will be changed
|
|
||||||
+ details = entries[driver]
|
|
||||||
|
|
||||||
if 'extends' not in details:
|
|
||||||
# Extends resolved or non existing, continue!
|
|
||||||
diff --git a/salt/grains/core.py b/salt/grains/core.py
|
|
||||||
index f410985198..358b66fdb0 100644
|
|
||||||
--- a/salt/grains/core.py
|
|
||||||
+++ b/salt/grains/core.py
|
|
||||||
@@ -40,20 +40,20 @@ except ImportError:
|
|
||||||
__proxyenabled__ = ['*']
|
|
||||||
__FQDN__ = None
|
|
||||||
|
|
||||||
-# Extend the default list of supported distros. This will be used for the
|
|
||||||
-# /etc/DISTRO-release checking that is part of linux_distribution()
|
|
||||||
-from platform import _supported_dists
|
|
||||||
-_supported_dists += ('arch', 'mageia', 'meego', 'vmware', 'bluewhite64',
|
|
||||||
- 'slamd64', 'ovs', 'system', 'mint', 'oracle', 'void')
|
|
||||||
-
|
|
||||||
# linux_distribution deprecated in py3.7
|
|
||||||
try:
|
|
||||||
from platform import linux_distribution as _deprecated_linux_distribution
|
|
||||||
|
|
||||||
+ # Extend the default list of supported distros. This will be used for the
|
|
||||||
+ # /etc/DISTRO-release checking that is part of linux_distribution()
|
|
||||||
+ from platform import _supported_dists
|
|
||||||
+ _supported_dists += ('arch', 'mageia', 'meego', 'vmware', 'bluewhite64',
|
|
||||||
+ 'slamd64', 'ovs', 'system', 'mint', 'oracle', 'void')
|
|
||||||
+
|
|
||||||
def linux_distribution(**kwargs):
|
|
||||||
with warnings.catch_warnings():
|
|
||||||
warnings.simplefilter("ignore")
|
|
||||||
- return _deprecated_linux_distribution(**kwargs)
|
|
||||||
+ return _deprecated_linux_distribution(supported_dists=_supported_dists, **kwargs)
|
|
||||||
except ImportError:
|
|
||||||
from distro import linux_distribution
|
|
||||||
|
|
||||||
@@ -1976,7 +1976,7 @@ def os_data():
|
|
||||||
)
|
|
||||||
(osname, osrelease, oscodename) = \
|
|
||||||
[x.strip('"').strip("'") for x in
|
|
||||||
- linux_distribution(supported_dists=_supported_dists)]
|
|
||||||
+ linux_distribution()]
|
|
||||||
# Try to assign these three names based on the lsb info, they tend to
|
|
||||||
# be more accurate than what python gets from /etc/DISTRO-release.
|
|
||||||
# It's worth noting that Ubuntu has patched their Python distribution
|
|
||||||
diff --git a/salt/renderers/stateconf.py b/salt/renderers/stateconf.py
|
diff --git a/salt/renderers/stateconf.py b/salt/renderers/stateconf.py
|
||||||
index cfce9e6926..5c8a8322ed 100644
|
index 298ae28338..f0527d51d7 100644
|
||||||
--- a/salt/renderers/stateconf.py
|
--- a/salt/renderers/stateconf.py
|
||||||
+++ b/salt/renderers/stateconf.py
|
+++ b/salt/renderers/stateconf.py
|
||||||
@@ -224,10 +224,10 @@ def render(input, saltenv='base', sls='', argline='', **kws):
|
@@ -1,4 +1,3 @@
|
||||||
tmplctx = STATE_CONF.copy()
|
-# -*- coding: utf-8 -*-
|
||||||
if tmplctx:
|
"""
|
||||||
prefix = sls + '::'
|
A flexible renderer that takes a templating engine and a data format
|
||||||
- for k in six.iterkeys(tmplctx): # iterate over a copy of keys
|
|
||||||
- if k.startswith(prefix):
|
@@ -26,8 +25,6 @@ A flexible renderer that takes a templating engine and a data format
|
||||||
- tmplctx[k[len(prefix):]] = tmplctx[k]
|
# - apache: >= 0.1.0
|
||||||
- del tmplctx[k]
|
#
|
||||||
+ tmplctx = {
|
|
||||||
+ k[len(prefix):] if k.startswith(prefix) else k: v
|
-# Import python libs
|
||||||
+ for k, v in six.iteritems(tmplctx)
|
-from __future__ import absolute_import, print_function, unicode_literals
|
||||||
+ }
|
|
||||||
|
import copy
|
||||||
|
import getopt
|
||||||
|
@@ -36,12 +33,9 @@ import os
|
||||||
|
import re
|
||||||
|
from itertools import chain
|
||||||
|
|
||||||
|
-# Import salt libs
|
||||||
|
import salt.utils.files
|
||||||
|
import salt.utils.stringutils
|
||||||
|
from salt.exceptions import SaltRenderError
|
||||||
|
-
|
||||||
|
-# Import 3rd-party libs
|
||||||
|
from salt.ext import six
|
||||||
|
from salt.ext.six.moves import StringIO # pylint: disable=import-error
|
||||||
|
|
||||||
|
@@ -135,7 +129,7 @@ def render(input, saltenv="base", sls="", argline="", **kws):
|
||||||
|
sid = has_names_decls(data)
|
||||||
|
if sid:
|
||||||
|
raise SaltRenderError(
|
||||||
|
- "'names' declaration(found in state id: {0}) is "
|
||||||
|
+ "'names' declaration(found in state id: {}) is "
|
||||||
|
"not supported with implicitly ordered states! You "
|
||||||
|
"should generate the states in a template for-loop "
|
||||||
|
"instead.".format(sid)
|
||||||
|
@@ -203,11 +197,11 @@ def render(input, saltenv="base", sls="", argline="", **kws):
|
||||||
|
name, rt_argline = (args[1] + " ").split(" ", 1)
|
||||||
|
render_template = renderers[name] # e.g., the mako renderer
|
||||||
|
except KeyError as err:
|
||||||
|
- raise SaltRenderError("Renderer: {0} is not available!".format(err))
|
||||||
|
+ raise SaltRenderError("Renderer: {} is not available!".format(err))
|
||||||
|
except IndexError:
|
||||||
|
raise INVALID_USAGE_ERROR
|
||||||
|
|
||||||
|
- if isinstance(input, six.string_types):
|
||||||
|
+ if isinstance(input, str):
|
||||||
|
with salt.utils.files.fopen(input, "r") as ifile:
|
||||||
|
sls_templ = salt.utils.stringutils.to_unicode(ifile.read())
|
||||||
|
else: # assume file-like
|
||||||
|
@@ -227,7 +221,7 @@ def render(input, saltenv="base", sls="", argline="", **kws):
|
||||||
|
prefix = sls + "::"
|
||||||
|
tmplctx = {
|
||||||
|
k[len(prefix) :] if k.startswith(prefix) else k: v
|
||||||
|
- for k, v in six.iteritems(tmplctx)
|
||||||
|
+ for k, v in tmplctx.items()
|
||||||
|
}
|
||||||
else:
|
else:
|
||||||
tmplctx = {}
|
tmplctx = {}
|
||||||
|
@@ -262,8 +256,8 @@ def rewrite_single_shorthand_state_decl(data): # pylint: disable=C0103
|
||||||
|
state_id_decl:
|
||||||
|
state.func: []
|
||||||
|
"""
|
||||||
|
- for sid, states in six.iteritems(data):
|
||||||
|
- if isinstance(states, six.string_types):
|
||||||
|
+ for sid, states in data.items():
|
||||||
|
+ if isinstance(states, str):
|
||||||
|
data[sid] = {states: []}
|
||||||
|
|
||||||
diff --git a/tests/unit/modules/test_virt.py b/tests/unit/modules/test_virt.py
|
|
||||||
index 94372c6d72..d762dcc479 100644
|
@@ -328,7 +322,7 @@ def nvlist(thelist, names=None):
|
||||||
--- a/tests/unit/modules/test_virt.py
|
for nvitem in thelist:
|
||||||
+++ b/tests/unit/modules/test_virt.py
|
if isinstance(nvitem, dict):
|
||||||
@@ -1256,7 +1256,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
# then nvitem is a name-value item(a dict) of the list.
|
||||||
<alias name='net1'/>
|
- name, value = next(six.iteritems(nvitem))
|
||||||
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x1'/>
|
+ name, value = next(iter(nvitem.items()))
|
||||||
</interface>
|
if names is None or name in names:
|
||||||
- <graphics type='spice' port='5900' autoport='yes' listen='127.0.0.1'>
|
yield nvitem, name, value
|
||||||
+ <graphics type='spice' listen='127.0.0.1' autoport='yes'>
|
|
||||||
<listen type='address' address='127.0.0.1'/>
|
@@ -349,17 +343,16 @@ def nvlist2(thelist, names=None):
|
||||||
</graphics>
|
|
||||||
<video>
|
"""
|
||||||
|
for _, _, value in nvlist(thelist, names):
|
||||||
|
- for each in nvlist(value):
|
||||||
|
- yield each
|
||||||
|
+ yield from nvlist(value)
|
||||||
|
|
||||||
|
|
||||||
|
def statelist(states_dict, sid_excludes=frozenset(["include", "exclude"])):
|
||||||
|
- for sid, states in six.iteritems(states_dict):
|
||||||
|
+ for sid, states in states_dict.items():
|
||||||
|
if sid.startswith("__"):
|
||||||
|
continue
|
||||||
|
if sid in sid_excludes:
|
||||||
|
continue
|
||||||
|
- for sname, args in six.iteritems(states):
|
||||||
|
+ for sname, args in states.items():
|
||||||
|
if sname.startswith("__"):
|
||||||
|
continue
|
||||||
|
yield sid, states, sname, args
|
||||||
|
@@ -401,11 +394,11 @@ def rename_state_ids(data, sls, is_extend=False):
|
||||||
|
newsid = _local_to_abs_sid(sid, sls)
|
||||||
|
if newsid in data:
|
||||||
|
raise SaltRenderError(
|
||||||
|
- "Can't rename state id({0}) into {1} because the later "
|
||||||
|
+ "Can't rename state id({}) into {} because the later "
|
||||||
|
"already exists!".format(sid, newsid)
|
||||||
|
)
|
||||||
|
# add a '- name: sid' to those states without '- name'.
|
||||||
|
- for sname, args in six.iteritems(data[sid]):
|
||||||
|
+ for sname, args in data[sid].items():
|
||||||
|
if state_name(sname) == STATE_NAME:
|
||||||
|
continue
|
||||||
|
for arg in args:
|
||||||
|
@@ -430,7 +423,7 @@ EXTENDED_REQUIRE_IN = {}
|
||||||
|
# explicit require_in/watch_in/listen_in/onchanges_in/onfail_in can only contain states after it
|
||||||
|
def add_implicit_requires(data):
|
||||||
|
def T(sid, state): # pylint: disable=C0103
|
||||||
|
- return "{0}:{1}".format(sid, state_name(state))
|
||||||
|
+ return "{}:{}".format(sid, state_name(state))
|
||||||
|
|
||||||
|
states_before = set()
|
||||||
|
states_after = set()
|
||||||
|
@@ -462,7 +455,7 @@ def add_implicit_requires(data):
|
||||||
|
for _, rstate, rsid in reqs:
|
||||||
|
if T(rsid, rstate) in states_after:
|
||||||
|
raise SaltRenderError(
|
||||||
|
- "State({0}) can't require/watch/listen/onchanges/onfail a state({1}) defined "
|
||||||
|
+ "State({}) can't require/watch/listen/onchanges/onfail a state({}) defined "
|
||||||
|
"after it!".format(tag, T(rsid, rstate))
|
||||||
|
)
|
||||||
|
|
||||||
|
@@ -472,7 +465,7 @@ def add_implicit_requires(data):
|
||||||
|
for _, rstate, rsid in reqs:
|
||||||
|
if T(rsid, rstate) in states_before:
|
||||||
|
raise SaltRenderError(
|
||||||
|
- "State({0}) can't require_in/watch_in/listen_in/onchanges_in/onfail_in a state({1}) "
|
||||||
|
+ "State({}) can't require_in/watch_in/listen_in/onchanges_in/onfail_in a state({}) "
|
||||||
|
"defined before it!".format(tag, T(rsid, rstate))
|
||||||
|
)
|
||||||
|
|
||||||
|
@@ -492,7 +485,7 @@ def add_start_state(data, sls):
|
||||||
|
start_sid = __opts__["stateconf_start_state"]
|
||||||
|
if start_sid in data:
|
||||||
|
raise SaltRenderError(
|
||||||
|
- "Can't generate start state({0})! The same state id already "
|
||||||
|
+ "Can't generate start state({})! The same state id already "
|
||||||
|
"exists!".format(start_sid)
|
||||||
|
)
|
||||||
|
if not data:
|
||||||
|
@@ -502,14 +495,14 @@ def add_start_state(data, sls):
|
||||||
|
# no __sls__, or it's the first state whose id declaration has a
|
||||||
|
# __sls__ == sls.
|
||||||
|
non_sids = ("include", "exclude", "extend")
|
||||||
|
- for sid, states in six.iteritems(data):
|
||||||
|
+ for sid, states in data.items():
|
||||||
|
if sid in non_sids or sid.startswith("__"):
|
||||||
|
continue
|
||||||
|
if "__sls__" not in states or states["__sls__"] == sls:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
raise SaltRenderError("Can't determine the first state in the sls file!")
|
||||||
|
- reqin = {state_name(next(six.iterkeys(data[sid]))): sid}
|
||||||
|
+ reqin = {state_name(next(iter(data[sid].keys()))): sid}
|
||||||
|
data[start_sid] = {STATE_FUNC: [{"require_in": [reqin]}]}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -517,7 +510,7 @@ def add_goal_state(data):
|
||||||
|
goal_sid = __opts__["stateconf_goal_state"]
|
||||||
|
if goal_sid in data:
|
||||||
|
raise SaltRenderError(
|
||||||
|
- "Can't generate goal state({0})! The same state id already "
|
||||||
|
+ "Can't generate goal state({})! The same state id already "
|
||||||
|
"exists!".format(goal_sid)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
@@ -561,7 +554,7 @@ STATE_CONF_EXT = {} # stateconf.set under extend: ...
|
||||||
|
|
||||||
|
|
||||||
|
def extract_state_confs(data, is_extend=False):
|
||||||
|
- for state_id, state_dict in six.iteritems(data):
|
||||||
|
+ for state_id, state_dict in data.items():
|
||||||
|
if state_id == "extend" and not is_extend:
|
||||||
|
extract_state_confs(state_dict, True)
|
||||||
|
continue
|
||||||
|
@@ -578,7 +571,7 @@ def extract_state_confs(data, is_extend=False):
|
||||||
|
for sdk in state_dict[key]:
|
||||||
|
if not isinstance(sdk, dict):
|
||||||
|
continue
|
||||||
|
- key, val = next(six.iteritems(sdk))
|
||||||
|
+ key, val = next(iter(sdk.items()))
|
||||||
|
conf[key] = val
|
||||||
|
|
||||||
|
if not is_extend and state_id in STATE_CONF_EXT:
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
|||||||
From 638ad2baa04e96f744f97c97f3840151937e8aac Mon Sep 17 00:00:00 2001
|
From 3c83bab3da101223c99af1f9ee2f3bf5e97be3f8 Mon Sep 17 00:00:00 2001
|
||||||
From: Hubert Mantel <mantel@suse.de>
|
From: Hubert Mantel <mantel@suse.de>
|
||||||
Date: Mon, 27 Nov 2017 13:55:13 +0100
|
Date: Mon, 27 Nov 2017 13:55:13 +0100
|
||||||
Subject: [PATCH] avoid excessive syslogging by watchdog cronjob (#58)
|
Subject: [PATCH] avoid excessive syslogging by watchdog cronjob (#58)
|
||||||
@ -21,6 +21,6 @@ index 2e418094ed..73a91ebd62 100755
|
|||||||
/usr/bin/salt-daemon-watcher --with-init & disown
|
/usr/bin/salt-daemon-watcher --with-init & disown
|
||||||
fi
|
fi
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
From f942aeb3eb64b99cd9432bebf021835ade46df74 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 16:38:04 +0100
|
|
||||||
Subject: [PATCH] Avoid HAS_DOCKER true if import messes with
|
|
||||||
salt.utils.docker (bsc#1172075)
|
|
||||||
|
|
||||||
---
|
|
||||||
salt/modules/swarm.py | 6 +++++-
|
|
||||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/salt/modules/swarm.py b/salt/modules/swarm.py
|
|
||||||
index ea327ce640040bdbd7e7077bc6bbb59a9f0ade4a..6f16f41ece01738f3a04d11211fa5e96cd8155b4 100644
|
|
||||||
--- a/salt/modules/swarm.py
|
|
||||||
+++ b/salt/modules/swarm.py
|
|
||||||
@@ -30,9 +30,13 @@ from __future__ import absolute_import, unicode_literals, print_function
|
|
||||||
# Import Salt libs
|
|
||||||
import salt.utils.json
|
|
||||||
|
|
||||||
+HAS_DOCKER = False
|
|
||||||
+
|
|
||||||
try:
|
|
||||||
import docker
|
|
||||||
- HAS_DOCKER = True
|
|
||||||
+
|
|
||||||
+ if hasattr(docker, "from_env"):
|
|
||||||
+ HAS_DOCKER = True
|
|
||||||
except ImportError:
|
|
||||||
HAS_DOCKER = False
|
|
||||||
|
|
||||||
--
|
|
||||||
2.23.0
|
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
From e45658e074fbf8c038816dc56b86c3daf33d6ebc Mon Sep 17 00:00:00 2001
|
From 2fecfe18cf17389714ab5bed0ff59bec2d1e1c36 Mon Sep 17 00:00:00 2001
|
||||||
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||||
<psuarezhernandez@suse.com>
|
<psuarezhernandez@suse.com>
|
||||||
Date: Mon, 29 Jul 2019 11:17:53 +0100
|
Date: Mon, 29 Jul 2019 11:17:53 +0100
|
||||||
@ -7,29 +7,33 @@ Subject: [PATCH] Avoid traceback when http.query request cannot be
|
|||||||
|
|
||||||
Improve error logging when http.query cannot be performed
|
Improve error logging when http.query cannot be performed
|
||||||
---
|
---
|
||||||
salt/utils/http.py | 4 +++-
|
salt/utils/http.py | 7 ++++++-
|
||||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
1 file changed, 6 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
diff --git a/salt/utils/http.py b/salt/utils/http.py
|
diff --git a/salt/utils/http.py b/salt/utils/http.py
|
||||||
index dee0563679..c2fdffb266 100644
|
index 5ab4503f61..9522bd6ee4 100644
|
||||||
--- a/salt/utils/http.py
|
--- a/salt/utils/http.py
|
||||||
+++ b/salt/utils/http.py
|
+++ b/salt/utils/http.py
|
||||||
@@ -580,11 +580,13 @@ def query(url,
|
@@ -628,12 +628,17 @@ def query(
|
||||||
except salt.ext.tornado.httpclient.HTTPError as exc:
|
except salt.ext.tornado.httpclient.HTTPError as exc:
|
||||||
ret['status'] = exc.code
|
ret["status"] = exc.code
|
||||||
ret['error'] = six.text_type(exc)
|
ret["error"] = str(exc)
|
||||||
+ log.error("Cannot perform 'http.query': {0} - {1}".format(url_full, ret['error']))
|
+ log.error(
|
||||||
|
+ "Cannot perform 'http.query': {} - {}".format(url_full, ret["error"])
|
||||||
|
+ )
|
||||||
return ret
|
return ret
|
||||||
- except socket.gaierror as exc:
|
except (socket.herror, OSError, socket.timeout, socket.gaierror) as exc:
|
||||||
+ except (socket.herror, socket.error, socket.timeout, socket.gaierror) as exc:
|
|
||||||
if status is True:
|
if status is True:
|
||||||
ret['status'] = 0
|
ret["status"] = 0
|
||||||
ret['error'] = six.text_type(exc)
|
ret["error"] = str(exc)
|
||||||
+ log.error("Cannot perform 'http.query': {0} - {1}".format(url_full, ret['error']))
|
- log.debug("Cannot perform 'http.query': %s - %s", url_full, ret["error"])
|
||||||
|
+ log.error(
|
||||||
|
+ "Cannot perform 'http.query': {} - {}".format(url_full, ret["error"])
|
||||||
|
+ )
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
if stream is True or handle is True:
|
if stream is True or handle is True:
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From f45df684fe68a93a7003aca2189479b0d0240305 Mon Sep 17 00:00:00 2001
|
From acee2074e9fe4da2731e61a554639e773c04e43a Mon Sep 17 00:00:00 2001
|
||||||
From: Cedric Bosdonnat <cbosdonnat@suse.com>
|
From: Cedric Bosdonnat <cbosdonnat@suse.com>
|
||||||
Date: Mon, 5 Oct 2020 16:49:59 +0200
|
Date: Mon, 5 Oct 2020 16:49:59 +0200
|
||||||
Subject: [PATCH] Backport a few virt PRs (#272)
|
Subject: [PATCH] Backport a few virt PRs (#272)
|
||||||
@ -39,13 +39,13 @@ Co-authored-by: gqlo <escita@pm.me>
|
|||||||
---
|
---
|
||||||
changelog/57639.added | 1 +
|
changelog/57639.added | 1 +
|
||||||
changelog/58589.added | 1 +
|
changelog/58589.added | 1 +
|
||||||
salt/modules/virt.py | 303 +++++++++++++++++++--
|
salt/modules/virt.py | 284 ++++++++++++++++++--
|
||||||
salt/states/virt.py | 73 +++++-
|
salt/states/virt.py | 71 ++++-
|
||||||
salt/templates/virt/libvirt_domain.jinja | 30 ++-
|
salt/templates/virt/libvirt_domain.jinja | 30 ++-
|
||||||
salt/utils/xmlutil.py | 4 +-
|
salt/utils/xmlutil.py | 2 +-
|
||||||
tests/unit/modules/test_virt.py | 320 ++++++++++++++++++++++-
|
tests/unit/modules/test_virt.py | 318 ++++++++++++++++++++++-
|
||||||
tests/unit/states/test_virt.py | 19 +-
|
tests/unit/states/test_virt.py | 14 +-
|
||||||
8 files changed, 704 insertions(+), 47 deletions(-)
|
8 files changed, 687 insertions(+), 34 deletions(-)
|
||||||
create mode 100644 changelog/57639.added
|
create mode 100644 changelog/57639.added
|
||||||
create mode 100644 changelog/58589.added
|
create mode 100644 changelog/58589.added
|
||||||
|
|
||||||
@ -64,10 +64,10 @@ index 0000000000..5960555ec6
|
|||||||
@@ -0,0 +1 @@
|
@@ -0,0 +1 @@
|
||||||
+Allow handling special first boot definition on virtual machine
|
+Allow handling special first boot definition on virtual machine
|
||||||
diff --git a/salt/modules/virt.py b/salt/modules/virt.py
|
diff --git a/salt/modules/virt.py b/salt/modules/virt.py
|
||||||
index 34643787f9..87ab7ca12d 100644
|
index e306bc0679..8e2180608a 100644
|
||||||
--- a/salt/modules/virt.py
|
--- a/salt/modules/virt.py
|
||||||
+++ b/salt/modules/virt.py
|
+++ b/salt/modules/virt.py
|
||||||
@@ -71,13 +71,57 @@ The calls not using the libvirt connection setup are:
|
@@ -71,6 +71,50 @@ The calls not using the libvirt connection setup are:
|
||||||
- `libvirt URI format <http://libvirt.org/uri.html#URI_config>`_
|
- `libvirt URI format <http://libvirt.org/uri.html#URI_config>`_
|
||||||
- `libvirt authentication configuration <http://libvirt.org/auth.html#Auth_client_config>`_
|
- `libvirt authentication configuration <http://libvirt.org/auth.html#Auth_client_config>`_
|
||||||
|
|
||||||
@ -118,26 +118,7 @@ index 34643787f9..87ab7ca12d 100644
|
|||||||
"""
|
"""
|
||||||
# Special Thanks to Michael Dehann, many of the concepts, and a few structures
|
# Special Thanks to Michael Dehann, many of the concepts, and a few structures
|
||||||
# of his in the virt func module have been used
|
# of his in the virt func module have been used
|
||||||
|
@@ -719,6 +763,39 @@ def _disk_from_pool(conn, pool, pool_xml, volume_name):
|
||||||
-# Import python libs
|
|
||||||
|
|
||||||
import base64
|
|
||||||
+import collections
|
|
||||||
import copy
|
|
||||||
import datetime
|
|
||||||
import logging
|
|
||||||
@@ -89,10 +133,8 @@ import subprocess
|
|
||||||
import sys
|
|
||||||
import time
|
|
||||||
|
|
||||||
-# Import third party libs
|
|
||||||
import jinja2.exceptions
|
|
||||||
|
|
||||||
-# Import salt libs
|
|
||||||
import salt.utils.data
|
|
||||||
import salt.utils.files
|
|
||||||
import salt.utils.json
|
|
||||||
@@ -725,6 +767,39 @@ def _disk_from_pool(conn, pool, pool_xml, volume_name):
|
|
||||||
return disk_context
|
return disk_context
|
||||||
|
|
||||||
|
|
||||||
@ -145,7 +126,7 @@ index 34643787f9..87ab7ca12d 100644
|
|||||||
+ """
|
+ """
|
||||||
+ Handle the unit conversion, return the value in bytes
|
+ Handle the unit conversion, return the value in bytes
|
||||||
+ """
|
+ """
|
||||||
+ m = re.match(r"(?P<value>[0-9.]*)\s*(?P<unit>.*)$", six.text_type(s).strip())
|
+ m = re.match(r"(?P<value>[0-9.]*)\s*(?P<unit>.*)$", str(s).strip())
|
||||||
+ value = m.group("value")
|
+ value = m.group("value")
|
||||||
+ # default unit
|
+ # default unit
|
||||||
+ unit = m.group("unit").lower() or def_unit
|
+ unit = m.group("unit").lower() or def_unit
|
||||||
@ -177,7 +158,7 @@ index 34643787f9..87ab7ca12d 100644
|
|||||||
def _gen_xml(
|
def _gen_xml(
|
||||||
conn,
|
conn,
|
||||||
name,
|
name,
|
||||||
@@ -738,18 +813,32 @@ def _gen_xml(
|
@@ -732,18 +809,32 @@ def _gen_xml(
|
||||||
graphics=None,
|
graphics=None,
|
||||||
boot=None,
|
boot=None,
|
||||||
boot_dev=None,
|
boot_dev=None,
|
||||||
@ -191,28 +172,28 @@ index 34643787f9..87ab7ca12d 100644
|
|||||||
context = {
|
context = {
|
||||||
"hypervisor": hypervisor,
|
"hypervisor": hypervisor,
|
||||||
"name": name,
|
"name": name,
|
||||||
"cpu": six.text_type(cpu),
|
"cpu": str(cpu),
|
||||||
- "mem": six.text_type(mem),
|
- "mem": str(mem),
|
||||||
+ "on_reboot": "destroy" if stop_on_reboot else "restart",
|
+ "on_reboot": "destroy" if stop_on_reboot else "restart",
|
||||||
}
|
}
|
||||||
+
|
+
|
||||||
+ context["mem"] = nesthash()
|
+ context["mem"] = nesthash()
|
||||||
+ if isinstance(mem, int):
|
+ if isinstance(mem, int):
|
||||||
+ mem = int(mem) * 1024 # MB
|
+ mem = int(mem) * 1024 # MB
|
||||||
+ context["mem"]["boot"] = six.text_type(mem)
|
+ context["mem"]["boot"] = str(mem)
|
||||||
+ context["mem"]["current"] = six.text_type(mem)
|
+ context["mem"]["current"] = str(mem)
|
||||||
+ elif isinstance(mem, dict):
|
+ elif isinstance(mem, dict):
|
||||||
+ for tag, val in six.iteritems(mem):
|
+ for tag, val in mem.items():
|
||||||
+ if val:
|
+ if val:
|
||||||
+ if tag == "slots":
|
+ if tag == "slots":
|
||||||
+ context["mem"]["slots"] = "{}='{}'".format(tag, val)
|
+ context["mem"]["slots"] = "{}='{}'".format(tag, val)
|
||||||
+ else:
|
+ else:
|
||||||
+ context["mem"][tag] = six.text_type(int(_handle_unit(val) / 1024))
|
+ context["mem"][tag] = str(int(_handle_unit(val) / 1024))
|
||||||
+
|
+
|
||||||
if hypervisor in ["qemu", "kvm"]:
|
if hypervisor in ["qemu", "kvm"]:
|
||||||
context["controller_model"] = False
|
context["controller_model"] = False
|
||||||
elif hypervisor == "vmware":
|
elif hypervisor == "vmware":
|
||||||
@@ -869,7 +958,6 @@ def _gen_xml(
|
@@ -863,7 +954,6 @@ def _gen_xml(
|
||||||
except jinja2.exceptions.TemplateNotFound:
|
except jinja2.exceptions.TemplateNotFound:
|
||||||
log.error("Could not load template %s", fn_)
|
log.error("Could not load template %s", fn_)
|
||||||
return ""
|
return ""
|
||||||
@ -220,7 +201,7 @@ index 34643787f9..87ab7ca12d 100644
|
|||||||
return template.render(**context)
|
return template.render(**context)
|
||||||
|
|
||||||
|
|
||||||
@@ -1668,6 +1756,7 @@ def init(
|
@@ -1662,6 +1752,7 @@ def init(
|
||||||
arch=None,
|
arch=None,
|
||||||
boot=None,
|
boot=None,
|
||||||
boot_dev=None,
|
boot_dev=None,
|
||||||
@ -228,7 +209,7 @@ index 34643787f9..87ab7ca12d 100644
|
|||||||
**kwargs
|
**kwargs
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
@@ -1675,7 +1764,28 @@ def init(
|
@@ -1669,7 +1760,28 @@ def init(
|
||||||
|
|
||||||
:param name: name of the virtual machine to create
|
:param name: name of the virtual machine to create
|
||||||
:param cpu: Number of virtual CPUs to assign to the virtual machine
|
:param cpu: Number of virtual CPUs to assign to the virtual machine
|
||||||
@ -258,7 +239,7 @@ index 34643787f9..87ab7ca12d 100644
|
|||||||
:param nic: NIC profile to use (Default: ``'default'``).
|
:param nic: NIC profile to use (Default: ``'default'``).
|
||||||
The profile interfaces can be customized / extended with the interfaces parameter.
|
The profile interfaces can be customized / extended with the interfaces parameter.
|
||||||
If set to ``None``, no profile will be used.
|
If set to ``None``, no profile will be used.
|
||||||
@@ -1732,6 +1842,15 @@ def init(
|
@@ -1726,6 +1838,15 @@ def init(
|
||||||
:param password: password to connect with, overriding defaults
|
:param password: password to connect with, overriding defaults
|
||||||
|
|
||||||
.. versionadded:: 2019.2.0
|
.. versionadded:: 2019.2.0
|
||||||
@ -274,7 +255,7 @@ index 34643787f9..87ab7ca12d 100644
|
|||||||
:param boot:
|
:param boot:
|
||||||
Specifies kernel, initial ramdisk and kernel command line parameters for the virtual machine.
|
Specifies kernel, initial ramdisk and kernel command line parameters for the virtual machine.
|
||||||
This is an optional parameter, all of the keys are optional within the dictionary. The structure of
|
This is an optional parameter, all of the keys are optional within the dictionary. The structure of
|
||||||
@@ -1788,6 +1907,36 @@ def init(
|
@@ -1782,6 +1903,36 @@ def init(
|
||||||
|
|
||||||
.. versionadded:: sodium
|
.. versionadded:: sodium
|
||||||
|
|
||||||
@ -311,7 +292,7 @@ index 34643787f9..87ab7ca12d 100644
|
|||||||
.. _init-nic-def:
|
.. _init-nic-def:
|
||||||
|
|
||||||
.. rubric:: Network Interfaces Definitions
|
.. rubric:: Network Interfaces Definitions
|
||||||
@@ -2082,6 +2231,7 @@ def init(
|
@@ -2076,6 +2227,7 @@ def init(
|
||||||
graphics,
|
graphics,
|
||||||
boot,
|
boot,
|
||||||
boot_dev,
|
boot_dev,
|
||||||
@ -319,7 +300,7 @@ index 34643787f9..87ab7ca12d 100644
|
|||||||
**kwargs
|
**kwargs
|
||||||
)
|
)
|
||||||
log.debug("New virtual machine definition: %s", vm_xml)
|
log.debug("New virtual machine definition: %s", vm_xml)
|
||||||
@@ -2311,6 +2461,7 @@ def update(
|
@@ -2305,6 +2457,7 @@ def update(
|
||||||
boot=None,
|
boot=None,
|
||||||
test=False,
|
test=False,
|
||||||
boot_dev=None,
|
boot_dev=None,
|
||||||
@ -327,33 +308,25 @@ index 34643787f9..87ab7ca12d 100644
|
|||||||
**kwargs
|
**kwargs
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
@@ -2318,7 +2469,24 @@ def update(
|
@@ -2312,7 +2465,7 @@ def update(
|
||||||
|
|
||||||
:param name: Name of the domain to update
|
:param name: Name of the domain to update
|
||||||
:param cpu: Number of virtual CPUs to assign to the virtual machine
|
:param cpu: Number of virtual CPUs to assign to the virtual machine
|
||||||
- :param mem: Amount of memory to allocate to the virtual machine in MiB.
|
- :param mem: Amount of memory to allocate to the virtual machine in MiB. Since 3002, a dictionary can be used to
|
||||||
+ :param mem: Amount of memory to allocate to the virtual machine in MiB. Since Magnesium, a dictionary can be used to
|
+ :param mem: Amount of memory to allocate to the virtual machine in MiB. Since Magnesium, a dictionary can be used to
|
||||||
+ contain detailed configuration which support memory allocation or tuning. Supported parameters are ``boot``,
|
contain detailed configuration which support memory allocation or tuning. Supported parameters are ``boot``,
|
||||||
+ ``current``, ``max``, ``slots``, ``hard_limit``, ``soft_limit``, ``swap_hard_limit`` and ``min_guarantee``. The
|
``current``, ``max``, ``slots``, ``hard_limit``, ``soft_limit``, ``swap_hard_limit`` and ``min_guarantee``. The
|
||||||
+ structure of the dictionary is documented in :ref:`init-mem-def`. Both decimal and binary base are supported.
|
structure of the dictionary is documented in :ref:`init-mem-def`. Both decimal and binary base are supported.
|
||||||
+ Detail unit specification is documented in :ref:`virt-units`. Please note that the value for ``slots`` must be
|
@@ -2328,7 +2481,7 @@ def update(
|
||||||
+ an integer.
|
hard_limit: null
|
||||||
+
|
soft_limit: null
|
||||||
+ To remove any parameters, pass a None object, for instance: 'soft_limit': ``None``. Please note that ``None``
|
|
||||||
+ is mapped to ``null`` in sls file, pass ``null`` in sls file instead.
|
- .. versionchanged:: 3002
|
||||||
+
|
|
||||||
+ .. code-block:: yaml
|
|
||||||
+
|
|
||||||
+ - mem:
|
|
||||||
+ hard_limit: null
|
|
||||||
+ soft_limit: null
|
|
||||||
+
|
|
||||||
+ .. versionchanged:: Magnesium
|
+ .. versionchanged:: Magnesium
|
||||||
+
|
|
||||||
:param disk_profile: disk profile to use
|
:param disk_profile: disk profile to use
|
||||||
:param disks:
|
:param disks:
|
||||||
Disk definitions as documented in the :func:`init` function.
|
@@ -2386,6 +2539,14 @@ def update(
|
||||||
@@ -2375,6 +2543,14 @@ def update(
|
|
||||||
|
|
||||||
.. versionadded:: Magnesium
|
.. versionadded:: Magnesium
|
||||||
|
|
||||||
@ -368,7 +341,7 @@ index 34643787f9..87ab7ca12d 100644
|
|||||||
:param test: run in dry-run mode if set to True
|
:param test: run in dry-run mode if set to True
|
||||||
|
|
||||||
.. versionadded:: sodium
|
.. versionadded:: sodium
|
||||||
@@ -2438,6 +2614,8 @@ def update(
|
@@ -2449,6 +2610,8 @@ def update(
|
||||||
desc.find(".//os/type").get("arch"),
|
desc.find(".//os/type").get("arch"),
|
||||||
graphics,
|
graphics,
|
||||||
boot,
|
boot,
|
||||||
@ -377,13 +350,13 @@ index 34643787f9..87ab7ca12d 100644
|
|||||||
**kwargs
|
**kwargs
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -2458,12 +2636,26 @@ def update(
|
@@ -2469,12 +2632,26 @@ def update(
|
||||||
def _set_nvram(node, value):
|
def _set_nvram(node, value):
|
||||||
node.set("template", value)
|
node.set("template", value)
|
||||||
|
|
||||||
- def _set_with_mib_unit(node, value):
|
- def _set_with_mib_unit(node, value):
|
||||||
+ def _set_with_byte_unit(node, value):
|
+ def _set_with_byte_unit(node, value):
|
||||||
node.text = six.text_type(value)
|
node.text = str(value)
|
||||||
- node.set("unit", "MiB")
|
- node.set("unit", "MiB")
|
||||||
+ node.set("unit", "bytes")
|
+ node.set("unit", "bytes")
|
||||||
+
|
+
|
||||||
@ -406,7 +379,7 @@ index 34643787f9..87ab7ca12d 100644
|
|||||||
{"path": "boot:kernel", "xpath": "os/kernel"},
|
{"path": "boot:kernel", "xpath": "os/kernel"},
|
||||||
{"path": "boot:initrd", "xpath": "os/initrd"},
|
{"path": "boot:initrd", "xpath": "os/initrd"},
|
||||||
{"path": "boot:cmdline", "xpath": "os/cmdline"},
|
{"path": "boot:cmdline", "xpath": "os/cmdline"},
|
||||||
@@ -2473,14 +2665,72 @@ def update(
|
@@ -2484,14 +2661,72 @@ def update(
|
||||||
{
|
{
|
||||||
"path": "mem",
|
"path": "mem",
|
||||||
"xpath": "memory",
|
"xpath": "memory",
|
||||||
@ -483,7 +456,7 @@ index 34643787f9..87ab7ca12d 100644
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "boot_dev:{dev}",
|
"path": "boot_dev:{dev}",
|
||||||
@@ -2566,13 +2816,24 @@ def update(
|
@@ -2577,13 +2812,24 @@ def update(
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
if mem:
|
if mem:
|
||||||
@ -516,24 +489,10 @@ index 34643787f9..87ab7ca12d 100644
|
|||||||
# Look for removable device source changes
|
# Look for removable device source changes
|
||||||
new_disks = []
|
new_disks = []
|
||||||
diff --git a/salt/states/virt.py b/salt/states/virt.py
|
diff --git a/salt/states/virt.py b/salt/states/virt.py
|
||||||
index 1a0c889d58..740f6c5746 100644
|
index df7ebb63e6..20ea1c25f1 100644
|
||||||
--- a/salt/states/virt.py
|
--- a/salt/states/virt.py
|
||||||
+++ b/salt/states/virt.py
|
+++ b/salt/states/virt.py
|
||||||
@@ -11,13 +11,11 @@ for the generation and signing of certificates for systems running libvirt:
|
@@ -289,6 +289,8 @@ def defined(
|
||||||
virt.keys
|
|
||||||
"""
|
|
||||||
|
|
||||||
-# Import Python libs
|
|
||||||
|
|
||||||
import fnmatch
|
|
||||||
import logging
|
|
||||||
import os
|
|
||||||
|
|
||||||
-# Import Salt libs
|
|
||||||
import salt.utils.args
|
|
||||||
import salt.utils.files
|
|
||||||
import salt.utils.stringutils
|
|
||||||
@@ -290,6 +288,8 @@ def defined(
|
|
||||||
boot=None,
|
boot=None,
|
||||||
update=True,
|
update=True,
|
||||||
boot_dev=None,
|
boot_dev=None,
|
||||||
@ -542,7 +501,7 @@ index 1a0c889d58..740f6c5746 100644
|
|||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Starts an existing guest, or defines and starts a new VM with specified arguments.
|
Starts an existing guest, or defines and starts a new VM with specified arguments.
|
||||||
@@ -298,7 +298,28 @@ def defined(
|
@@ -297,7 +299,28 @@ def defined(
|
||||||
|
|
||||||
:param name: name of the virtual machine to run
|
:param name: name of the virtual machine to run
|
||||||
:param cpu: number of CPUs for the virtual machine to create
|
:param cpu: number of CPUs for the virtual machine to create
|
||||||
@ -572,7 +531,7 @@ index 1a0c889d58..740f6c5746 100644
|
|||||||
:param vm_type: force virtual machine type for the new VM. The default value is taken from
|
:param vm_type: force virtual machine type for the new VM. The default value is taken from
|
||||||
the host capabilities. This could be useful for example to use ``'qemu'`` type instead
|
the host capabilities. This could be useful for example to use ``'qemu'`` type instead
|
||||||
of the ``'kvm'`` one.
|
of the ``'kvm'`` one.
|
||||||
@@ -358,6 +379,20 @@ def defined(
|
@@ -357,6 +380,20 @@ def defined(
|
||||||
|
|
||||||
.. versionadded:: Magnesium
|
.. versionadded:: Magnesium
|
||||||
|
|
||||||
@ -593,7 +552,7 @@ index 1a0c889d58..740f6c5746 100644
|
|||||||
.. rubric:: Example States
|
.. rubric:: Example States
|
||||||
|
|
||||||
Make sure a virtual machine called ``domain_name`` is defined:
|
Make sure a virtual machine called ``domain_name`` is defined:
|
||||||
@@ -415,13 +450,14 @@ def defined(
|
@@ -414,13 +451,14 @@ def defined(
|
||||||
nic_profile=nic_profile,
|
nic_profile=nic_profile,
|
||||||
interfaces=interfaces,
|
interfaces=interfaces,
|
||||||
graphics=graphics,
|
graphics=graphics,
|
||||||
@ -609,7 +568,7 @@ index 1a0c889d58..740f6c5746 100644
|
|||||||
)
|
)
|
||||||
ret["changes"][name] = status
|
ret["changes"][name] = status
|
||||||
if not status.get("definition"):
|
if not status.get("definition"):
|
||||||
@@ -457,6 +493,7 @@ def defined(
|
@@ -456,6 +494,7 @@ def defined(
|
||||||
boot=boot,
|
boot=boot,
|
||||||
start=False,
|
start=False,
|
||||||
boot_dev=boot_dev,
|
boot_dev=boot_dev,
|
||||||
@ -617,7 +576,7 @@ index 1a0c889d58..740f6c5746 100644
|
|||||||
)
|
)
|
||||||
ret["changes"][name] = {"definition": True}
|
ret["changes"][name] = {"definition": True}
|
||||||
ret["comment"] = "Domain {} defined".format(name)
|
ret["comment"] = "Domain {} defined".format(name)
|
||||||
@@ -490,6 +527,7 @@ def running(
|
@@ -489,6 +528,7 @@ def running(
|
||||||
arch=None,
|
arch=None,
|
||||||
boot=None,
|
boot=None,
|
||||||
boot_dev=None,
|
boot_dev=None,
|
||||||
@ -625,7 +584,7 @@ index 1a0c889d58..740f6c5746 100644
|
|||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Starts an existing guest, or defines and starts a new VM with specified arguments.
|
Starts an existing guest, or defines and starts a new VM with specified arguments.
|
||||||
@@ -498,7 +536,23 @@ def running(
|
@@ -497,7 +537,23 @@ def running(
|
||||||
|
|
||||||
:param name: name of the virtual machine to run
|
:param name: name of the virtual machine to run
|
||||||
:param cpu: number of CPUs for the virtual machine to create
|
:param cpu: number of CPUs for the virtual machine to create
|
||||||
@ -650,7 +609,7 @@ index 1a0c889d58..740f6c5746 100644
|
|||||||
:param vm_type: force virtual machine type for the new VM. The default value is taken from
|
:param vm_type: force virtual machine type for the new VM. The default value is taken from
|
||||||
the host capabilities. This could be useful for example to use ``'qemu'`` type instead
|
the host capabilities. This could be useful for example to use ``'qemu'`` type instead
|
||||||
of the ``'kvm'`` one.
|
of the ``'kvm'`` one.
|
||||||
@@ -609,6 +663,14 @@ def running(
|
@@ -608,6 +664,14 @@ def running(
|
||||||
|
|
||||||
.. versionadded:: Magnesium
|
.. versionadded:: Magnesium
|
||||||
|
|
||||||
@ -665,7 +624,7 @@ index 1a0c889d58..740f6c5746 100644
|
|||||||
.. rubric:: Example States
|
.. rubric:: Example States
|
||||||
|
|
||||||
Make sure an already-defined virtual machine called ``domain_name`` is running:
|
Make sure an already-defined virtual machine called ``domain_name`` is running:
|
||||||
@@ -677,6 +739,7 @@ def running(
|
@@ -676,6 +740,7 @@ def running(
|
||||||
boot=boot,
|
boot=boot,
|
||||||
update=update,
|
update=update,
|
||||||
boot_dev=boot_dev,
|
boot_dev=boot_dev,
|
||||||
@ -722,60 +681,31 @@ index 18728a75b5..fb4c9f40d0 100644
|
|||||||
{% for disk in disks %}
|
{% for disk in disks %}
|
||||||
<disk type='{{ disk.type }}' device='{{ disk.device }}'>
|
<disk type='{{ disk.type }}' device='{{ disk.device }}'>
|
||||||
diff --git a/salt/utils/xmlutil.py b/salt/utils/xmlutil.py
|
diff --git a/salt/utils/xmlutil.py b/salt/utils/xmlutil.py
|
||||||
index 68191bc528..6c32f22ad4 100644
|
index 111ca155d4..d25f5c8da5 100644
|
||||||
--- a/salt/utils/xmlutil.py
|
--- a/salt/utils/xmlutil.py
|
||||||
+++ b/salt/utils/xmlutil.py
|
+++ b/salt/utils/xmlutil.py
|
||||||
@@ -2,12 +2,10 @@
|
@@ -299,7 +299,7 @@ def change_xml(doc, data, mapping):
|
||||||
Various XML utilities
|
|
||||||
"""
|
|
||||||
|
|
||||||
-# Import Python libs
|
|
||||||
import re
|
|
||||||
import string # pylint: disable=deprecated-module
|
|
||||||
from xml.etree import ElementTree
|
|
||||||
|
|
||||||
-# Import salt libs
|
|
||||||
import salt.utils.data
|
|
||||||
from salt.ext import six
|
|
||||||
|
|
||||||
@@ -301,7 +299,7 @@ def change_xml(doc, data, mapping):
|
|
||||||
if convert_fn:
|
if convert_fn:
|
||||||
new_value = convert_fn(new_value)
|
new_value = convert_fn(new_value)
|
||||||
|
|
||||||
- if current_value != new_value:
|
- if current_value != new_value:
|
||||||
+ if six.text_type(current_value) != six.text_type(new_value):
|
+ if str(current_value) != str(new_value):
|
||||||
set_fn(node, new_value)
|
set_fn(node, new_value)
|
||||||
need_update = True
|
need_update = True
|
||||||
else:
|
else:
|
||||||
diff --git a/tests/unit/modules/test_virt.py b/tests/unit/modules/test_virt.py
|
diff --git a/tests/unit/modules/test_virt.py b/tests/unit/modules/test_virt.py
|
||||||
index 6e61544a1f..ca5e80d2d2 100644
|
index e214e406e2..fba821ea53 100644
|
||||||
--- a/tests/unit/modules/test_virt.py
|
--- a/tests/unit/modules/test_virt.py
|
||||||
+++ b/tests/unit/modules/test_virt.py
|
+++ b/tests/unit/modules/test_virt.py
|
||||||
@@ -4,7 +4,6 @@ virt execution module unit tests
|
@@ -21,7 +21,6 @@ from salt.ext import six
|
||||||
|
|
||||||
# pylint: disable=3rd-party-module-not-gated
|
|
||||||
|
|
||||||
-# Import python libs
|
|
||||||
|
|
||||||
import datetime
|
|
||||||
import os
|
|
||||||
@@ -16,7 +15,6 @@ import salt.modules.config as config
|
|
||||||
import salt.modules.virt as virt
|
|
||||||
import salt.syspaths
|
|
||||||
|
|
||||||
-# Import salt libs
|
|
||||||
import salt.utils.yaml
|
|
||||||
from salt._compat import ElementTree as ET
|
|
||||||
from salt.exceptions import CommandExecutionError, SaltInvocationError
|
|
||||||
@@ -24,7 +22,6 @@ from salt.exceptions import CommandExecutionError, SaltInvocationError
|
|
||||||
# pylint: disable=import-error
|
# pylint: disable=import-error
|
||||||
from salt.ext.six.moves import range # pylint: disable=redefined-builtin
|
from salt.ext.six.moves import range # pylint: disable=redefined-builtin
|
||||||
|
-from tests.support.helpers import dedent
|
||||||
-# Import Salt Testing libs
|
|
||||||
from tests.support.mixins import LoaderModuleMockMixin
|
from tests.support.mixins import LoaderModuleMockMixin
|
||||||
from tests.support.mock import MagicMock, patch
|
from tests.support.mock import MagicMock, patch
|
||||||
from tests.support.unit import TestCase
|
from tests.support.unit import TestCase
|
||||||
@@ -1859,6 +1856,25 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -1856,6 +1855,25 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
virt.update("my_vm"),
|
virt.update("my_vm"),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -801,7 +731,7 @@ index 6e61544a1f..ca5e80d2d2 100644
|
|||||||
# Same parameters passed than in default virt.defined state case
|
# Same parameters passed than in default virt.defined state case
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
{
|
{
|
||||||
@@ -2004,6 +2020,50 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -2001,6 +2019,50 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
with self.assertRaises(SaltInvocationError):
|
with self.assertRaises(SaltInvocationError):
|
||||||
virt.update("my_vm", boot={"efi": "Not a boolean value"})
|
virt.update("my_vm", boot={"efi": "Not a boolean value"})
|
||||||
|
|
||||||
@ -852,7 +782,7 @@ index 6e61544a1f..ca5e80d2d2 100644
|
|||||||
# Update memory case
|
# Update memory case
|
||||||
setmem_mock = MagicMock(return_value=0)
|
setmem_mock = MagicMock(return_value=0)
|
||||||
domain_mock.setMemoryFlags = setmem_mock
|
domain_mock.setMemoryFlags = setmem_mock
|
||||||
@@ -2018,10 +2078,43 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -2015,10 +2077,43 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
virt.update("my_vm", mem=2048),
|
virt.update("my_vm", mem=2048),
|
||||||
)
|
)
|
||||||
setxml = ET.fromstring(define_mock.call_args[0][0])
|
setxml = ET.fromstring(define_mock.call_args[0][0])
|
||||||
@ -898,7 +828,7 @@ index 6e61544a1f..ca5e80d2d2 100644
|
|||||||
# Update disks case
|
# Update disks case
|
||||||
devattach_mock = MagicMock(return_value=0)
|
devattach_mock = MagicMock(return_value=0)
|
||||||
devdetach_mock = MagicMock(return_value=0)
|
devdetach_mock = MagicMock(return_value=0)
|
||||||
@@ -2536,7 +2629,6 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -2533,7 +2628,6 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
"""
|
"""
|
||||||
Test virt.update() with existing boot parameters.
|
Test virt.update() with existing boot parameters.
|
||||||
"""
|
"""
|
||||||
@ -906,7 +836,7 @@ index 6e61544a1f..ca5e80d2d2 100644
|
|||||||
xml_boot = """
|
xml_boot = """
|
||||||
<domain type='kvm' id='8'>
|
<domain type='kvm' id='8'>
|
||||||
<name>vm_with_boot_param</name>
|
<name>vm_with_boot_param</name>
|
||||||
@@ -2594,9 +2686,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -2591,9 +2685,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
</video>
|
</video>
|
||||||
</devices>
|
</devices>
|
||||||
</domain>
|
</domain>
|
||||||
@ -917,7 +847,7 @@ index 6e61544a1f..ca5e80d2d2 100644
|
|||||||
domain_mock_boot = self.set_mock_vm("vm_with_boot_param", xml_boot)
|
domain_mock_boot = self.set_mock_vm("vm_with_boot_param", xml_boot)
|
||||||
domain_mock_boot.OSType = MagicMock(return_value="hvm")
|
domain_mock_boot.OSType = MagicMock(return_value="hvm")
|
||||||
define_mock_boot = MagicMock(return_value=True)
|
define_mock_boot = MagicMock(return_value=True)
|
||||||
@@ -2697,6 +2787,218 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -2694,6 +2786,218 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
self.assertEqual(setxml.find("os").find("loader"), None)
|
self.assertEqual(setxml.find("os").find("loader"), None)
|
||||||
self.assertEqual(setxml.find("os").find("nvram"), None)
|
self.assertEqual(setxml.find("os").find("nvram"), None)
|
||||||
|
|
||||||
@ -1137,32 +1067,18 @@ index 6e61544a1f..ca5e80d2d2 100644
|
|||||||
"""
|
"""
|
||||||
Test virt._nic_profile with mixed dictionaries and lists as input.
|
Test virt._nic_profile with mixed dictionaries and lists as input.
|
||||||
diff --git a/tests/unit/states/test_virt.py b/tests/unit/states/test_virt.py
|
diff --git a/tests/unit/states/test_virt.py b/tests/unit/states/test_virt.py
|
||||||
index f03159334b..1923ae5c0f 100644
|
index 8fe892f607..1923ae5c0f 100644
|
||||||
--- a/tests/unit/states/test_virt.py
|
--- a/tests/unit/states/test_virt.py
|
||||||
+++ b/tests/unit/states/test_virt.py
|
+++ b/tests/unit/states/test_virt.py
|
||||||
@@ -1,21 +1,15 @@
|
@@ -8,7 +8,6 @@ import tempfile
|
||||||
"""
|
|
||||||
:codeauthor: Jayesh Kariya <jayeshk@saltstack.com>
|
|
||||||
"""
|
|
||||||
-# Import Python libs
|
|
||||||
|
|
||||||
import shutil
|
|
||||||
import tempfile
|
|
||||||
|
|
||||||
-# Import Salt Libs
|
|
||||||
import salt.states.virt as virt
|
import salt.states.virt as virt
|
||||||
import salt.utils.files
|
import salt.utils.files
|
||||||
from salt.exceptions import CommandExecutionError, SaltInvocationError
|
from salt.exceptions import CommandExecutionError, SaltInvocationError
|
||||||
-
|
-from salt.ext import six
|
||||||
-# Import 3rd-party libs
|
|
||||||
from tests.support.mixins import LoaderModuleMockMixin
|
from tests.support.mixins import LoaderModuleMockMixin
|
||||||
from tests.support.mock import MagicMock, mock_open, patch
|
from tests.support.mock import MagicMock, mock_open, patch
|
||||||
-
|
|
||||||
-# Import Salt Testing Libs
|
|
||||||
from tests.support.runtests import RUNTIME_VARS
|
from tests.support.runtests import RUNTIME_VARS
|
||||||
from tests.support.unit import TestCase
|
@@ -346,6 +345,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
|
|
||||||
@@ -351,6 +345,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
|
||||||
install=False,
|
install=False,
|
||||||
pub_key="/path/to/key.pub",
|
pub_key="/path/to/key.pub",
|
||||||
priv_key="/path/to/key",
|
priv_key="/path/to/key",
|
||||||
@ -1170,7 +1086,7 @@ index f03159334b..1923ae5c0f 100644
|
|||||||
connection="someconnection",
|
connection="someconnection",
|
||||||
username="libvirtuser",
|
username="libvirtuser",
|
||||||
password="supersecret",
|
password="supersecret",
|
||||||
@@ -376,6 +371,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -371,6 +371,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
start=False,
|
start=False,
|
||||||
pub_key="/path/to/key.pub",
|
pub_key="/path/to/key.pub",
|
||||||
priv_key="/path/to/key",
|
priv_key="/path/to/key",
|
||||||
@ -1178,7 +1094,7 @@ index f03159334b..1923ae5c0f 100644
|
|||||||
connection="someconnection",
|
connection="someconnection",
|
||||||
username="libvirtuser",
|
username="libvirtuser",
|
||||||
password="supersecret",
|
password="supersecret",
|
||||||
@@ -489,6 +485,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -484,6 +485,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
password=None,
|
password=None,
|
||||||
boot=None,
|
boot=None,
|
||||||
test=False,
|
test=False,
|
||||||
@ -1186,7 +1102,7 @@ index f03159334b..1923ae5c0f 100644
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Failed definition update case
|
# Failed definition update case
|
||||||
@@ -559,6 +556,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -554,6 +556,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
install=False,
|
install=False,
|
||||||
pub_key="/path/to/key.pub",
|
pub_key="/path/to/key.pub",
|
||||||
priv_key="/path/to/key",
|
priv_key="/path/to/key",
|
||||||
@ -1194,7 +1110,7 @@ index f03159334b..1923ae5c0f 100644
|
|||||||
connection="someconnection",
|
connection="someconnection",
|
||||||
username="libvirtuser",
|
username="libvirtuser",
|
||||||
password="supersecret",
|
password="supersecret",
|
||||||
@@ -601,6 +599,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -596,6 +599,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
boot=None,
|
boot=None,
|
||||||
test=True,
|
test=True,
|
||||||
boot_dev=None,
|
boot_dev=None,
|
||||||
@ -1202,7 +1118,7 @@ index f03159334b..1923ae5c0f 100644
|
|||||||
)
|
)
|
||||||
|
|
||||||
# No changes case
|
# No changes case
|
||||||
@@ -636,6 +635,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -631,6 +635,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
boot=None,
|
boot=None,
|
||||||
test=True,
|
test=True,
|
||||||
boot_dev=None,
|
boot_dev=None,
|
||||||
@ -1210,7 +1126,7 @@ index f03159334b..1923ae5c0f 100644
|
|||||||
)
|
)
|
||||||
|
|
||||||
def test_running(self):
|
def test_running(self):
|
||||||
@@ -713,6 +713,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -708,6 +713,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
pub_key=None,
|
pub_key=None,
|
||||||
priv_key=None,
|
priv_key=None,
|
||||||
boot_dev=None,
|
boot_dev=None,
|
||||||
@ -1218,7 +1134,7 @@ index f03159334b..1923ae5c0f 100644
|
|||||||
connection=None,
|
connection=None,
|
||||||
username=None,
|
username=None,
|
||||||
password=None,
|
password=None,
|
||||||
@@ -775,6 +776,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -770,6 +776,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
pub_key="/path/to/key.pub",
|
pub_key="/path/to/key.pub",
|
||||||
priv_key="/path/to/key",
|
priv_key="/path/to/key",
|
||||||
boot_dev="network hd",
|
boot_dev="network hd",
|
||||||
@ -1226,7 +1142,7 @@ index f03159334b..1923ae5c0f 100644
|
|||||||
connection="someconnection",
|
connection="someconnection",
|
||||||
username="libvirtuser",
|
username="libvirtuser",
|
||||||
password="supersecret",
|
password="supersecret",
|
||||||
@@ -800,6 +802,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -795,6 +802,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
pub_key="/path/to/key.pub",
|
pub_key="/path/to/key.pub",
|
||||||
priv_key="/path/to/key",
|
priv_key="/path/to/key",
|
||||||
boot_dev="network hd",
|
boot_dev="network hd",
|
||||||
@ -1234,7 +1150,7 @@ index f03159334b..1923ae5c0f 100644
|
|||||||
connection="someconnection",
|
connection="someconnection",
|
||||||
username="libvirtuser",
|
username="libvirtuser",
|
||||||
password="supersecret",
|
password="supersecret",
|
||||||
@@ -945,6 +948,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -940,6 +948,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
boot=None,
|
boot=None,
|
||||||
test=False,
|
test=False,
|
||||||
boot_dev=None,
|
boot_dev=None,
|
||||||
@ -1242,7 +1158,7 @@ index f03159334b..1923ae5c0f 100644
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Failed definition update case
|
# Failed definition update case
|
||||||
@@ -1018,6 +1022,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -1013,6 +1022,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
install=False,
|
install=False,
|
||||||
pub_key="/path/to/key.pub",
|
pub_key="/path/to/key.pub",
|
||||||
priv_key="/path/to/key",
|
priv_key="/path/to/key",
|
||||||
@ -1250,7 +1166,7 @@ index f03159334b..1923ae5c0f 100644
|
|||||||
connection="someconnection",
|
connection="someconnection",
|
||||||
username="libvirtuser",
|
username="libvirtuser",
|
||||||
password="supersecret",
|
password="supersecret",
|
||||||
@@ -1064,6 +1069,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -1059,6 +1069,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
boot=None,
|
boot=None,
|
||||||
test=True,
|
test=True,
|
||||||
boot_dev=None,
|
boot_dev=None,
|
||||||
@ -1258,7 +1174,7 @@ index f03159334b..1923ae5c0f 100644
|
|||||||
)
|
)
|
||||||
start_mock.assert_not_called()
|
start_mock.assert_not_called()
|
||||||
|
|
||||||
@@ -1101,6 +1107,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -1096,6 +1107,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
boot=None,
|
boot=None,
|
||||||
test=True,
|
test=True,
|
||||||
boot_dev=None,
|
boot_dev=None,
|
||||||
@ -1267,6 +1183,6 @@ index f03159334b..1923ae5c0f 100644
|
|||||||
|
|
||||||
def test_stopped(self):
|
def test_stopped(self):
|
||||||
--
|
--
|
||||||
2.28.0
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,42 +1,34 @@
|
|||||||
From c5edf396ffd66b6ac1479aa01367aae3eff7683d Mon Sep 17 00:00:00 2001
|
From 1606379714f4776e2b529fb1d45891266985c896 Mon Sep 17 00:00:00 2001
|
||||||
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||||
<psuarezhernandez@suse.com>
|
<psuarezhernandez@suse.com>
|
||||||
Date: Fri, 28 Feb 2020 15:11:53 +0000
|
Date: Fri, 28 Feb 2020 15:11:53 +0000
|
||||||
Subject: [PATCH] Batch Async: Catch exceptions and safety unregister and
|
Subject: [PATCH] Batch Async: Catch exceptions and safety unregister
|
||||||
close instances
|
and close instances
|
||||||
|
|
||||||
---
|
---
|
||||||
salt/cli/batch_async.py | 156 +++++++++++++++++++++++-----------------
|
salt/cli/batch_async.py | 160 ++++++++++++++++++++++++----------------
|
||||||
1 file changed, 89 insertions(+), 67 deletions(-)
|
1 file changed, 96 insertions(+), 64 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/cli/batch_async.py b/salt/cli/batch_async.py
|
diff --git a/salt/cli/batch_async.py b/salt/cli/batch_async.py
|
||||||
index da069b64bd..b8f272ed67 100644
|
index 1e2ac5b0d3..3dc04826d1 100644
|
||||||
--- a/salt/cli/batch_async.py
|
--- a/salt/cli/batch_async.py
|
||||||
+++ b/salt/cli/batch_async.py
|
+++ b/salt/cli/batch_async.py
|
||||||
@@ -13,7 +13,6 @@ import salt.client
|
@@ -107,22 +107,25 @@ class BatchAsync:
|
||||||
|
|
||||||
# pylint: enable=import-error,no-name-in-module,redefined-builtin
|
|
||||||
import logging
|
|
||||||
-import fnmatch
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
@@ -104,22 +103,25 @@ class BatchAsync(object):
|
|
||||||
def __event_handler(self, raw):
|
def __event_handler(self, raw):
|
||||||
if not self.event:
|
if not self.event:
|
||||||
return
|
return
|
||||||
- mtag, data = self.event.unpack(raw, self.event.serial)
|
- mtag, data = self.event.unpack(raw, self.event.serial)
|
||||||
- for (pattern, op) in self.patterns:
|
- for (pattern, op) in self.patterns:
|
||||||
- if mtag.startswith(pattern[:-1]):
|
- if mtag.startswith(pattern[:-1]):
|
||||||
- minion = data['id']
|
- minion = data["id"]
|
||||||
- if op == 'ping_return':
|
- if op == "ping_return":
|
||||||
- self.minions.add(minion)
|
- self.minions.add(minion)
|
||||||
- if self.targeted_minions == self.minions:
|
- if self.targeted_minions == self.minions:
|
||||||
- self.event.io_loop.spawn_callback(self.start_batch)
|
- self.event.io_loop.spawn_callback(self.start_batch)
|
||||||
- elif op == 'find_job_return':
|
- elif op == "find_job_return":
|
||||||
- if data.get("return", None):
|
- if data.get("return", None):
|
||||||
- self.find_job_returned.add(minion)
|
- self.find_job_returned.add(minion)
|
||||||
- elif op == 'batch_run':
|
- elif op == "batch_run":
|
||||||
- if minion in self.active:
|
- if minion in self.active:
|
||||||
- self.active.remove(minion)
|
- self.active.remove(minion)
|
||||||
- self.done_minions.add(minion)
|
- self.done_minions.add(minion)
|
||||||
@ -45,15 +37,15 @@ index da069b64bd..b8f272ed67 100644
|
|||||||
+ mtag, data = self.event.unpack(raw, self.event.serial)
|
+ mtag, data = self.event.unpack(raw, self.event.serial)
|
||||||
+ for (pattern, op) in self.patterns:
|
+ for (pattern, op) in self.patterns:
|
||||||
+ if mtag.startswith(pattern[:-1]):
|
+ if mtag.startswith(pattern[:-1]):
|
||||||
+ minion = data['id']
|
+ minion = data["id"]
|
||||||
+ if op == 'ping_return':
|
+ if op == "ping_return":
|
||||||
+ self.minions.add(minion)
|
+ self.minions.add(minion)
|
||||||
+ if self.targeted_minions == self.minions:
|
+ if self.targeted_minions == self.minions:
|
||||||
+ self.event.io_loop.spawn_callback(self.start_batch)
|
+ self.event.io_loop.spawn_callback(self.start_batch)
|
||||||
+ elif op == 'find_job_return':
|
+ elif op == "find_job_return":
|
||||||
+ if data.get("return", None):
|
+ if data.get("return", None):
|
||||||
+ self.find_job_returned.add(minion)
|
+ self.find_job_returned.add(minion)
|
||||||
+ elif op == 'batch_run':
|
+ elif op == "batch_run":
|
||||||
+ if minion in self.active:
|
+ if minion in self.active:
|
||||||
+ self.active.remove(minion)
|
+ self.active.remove(minion)
|
||||||
+ self.done_minions.add(minion)
|
+ self.done_minions.add(minion)
|
||||||
@ -62,8 +54,8 @@ index da069b64bd..b8f272ed67 100644
|
|||||||
+ log.error("Exception occured while processing event: {}".format(ex))
|
+ log.error("Exception occured while processing event: {}".format(ex))
|
||||||
|
|
||||||
def _get_next(self):
|
def _get_next(self):
|
||||||
to_run = self.minions.difference(
|
to_run = (
|
||||||
@@ -146,54 +148,59 @@ class BatchAsync(object):
|
@@ -154,53 +157,67 @@ class BatchAsync:
|
||||||
if timedout_minions:
|
if timedout_minions:
|
||||||
self.schedule_next()
|
self.schedule_next()
|
||||||
|
|
||||||
@ -74,112 +66,118 @@ index da069b64bd..b8f272ed67 100644
|
|||||||
|
|
||||||
@tornado.gen.coroutine
|
@tornado.gen.coroutine
|
||||||
def find_job(self, minions):
|
def find_job(self, minions):
|
||||||
- not_done = minions.difference(self.done_minions).difference(self.timedout_minions)
|
- not_done = minions.difference(self.done_minions).difference(
|
||||||
|
- self.timedout_minions
|
||||||
|
- )
|
||||||
-
|
-
|
||||||
- if not_done:
|
- if not_done:
|
||||||
- jid = self.jid_gen()
|
- jid = self.jid_gen()
|
||||||
- find_job_return_pattern = 'salt/job/{0}/ret/*'.format(jid)
|
- find_job_return_pattern = "salt/job/{}/ret/*".format(jid)
|
||||||
- self.patterns.add((find_job_return_pattern, "find_job_return"))
|
- self.patterns.add((find_job_return_pattern, "find_job_return"))
|
||||||
- self.event.subscribe(find_job_return_pattern, match_type='glob')
|
- self.event.subscribe(find_job_return_pattern, match_type="glob")
|
||||||
-
|
-
|
||||||
- ret = yield self.local.run_job_async(
|
- ret = yield self.local.run_job_async(
|
||||||
- not_done,
|
- not_done,
|
||||||
- 'saltutil.find_job',
|
- "saltutil.find_job",
|
||||||
- [self.batch_jid],
|
- [self.batch_jid],
|
||||||
- 'list',
|
- "list",
|
||||||
- gather_job_timeout=self.opts['gather_job_timeout'],
|
- gather_job_timeout=self.opts["gather_job_timeout"],
|
||||||
- jid=jid,
|
- jid=jid,
|
||||||
- **self.eauth)
|
- **self.eauth
|
||||||
- yield tornado.gen.sleep(self.opts['gather_job_timeout'])
|
|
||||||
- self.event.io_loop.spawn_callback(
|
|
||||||
- self.check_find_job,
|
|
||||||
- not_done,
|
|
||||||
- jid)
|
|
||||||
+ if self.event:
|
+ if self.event:
|
||||||
+ not_done = minions.difference(self.done_minions).difference(self.timedout_minions)
|
+ not_done = minions.difference(self.done_minions).difference(
|
||||||
|
+ self.timedout_minions
|
||||||
|
)
|
||||||
|
- yield tornado.gen.sleep(self.opts["gather_job_timeout"])
|
||||||
|
- self.event.io_loop.spawn_callback(self.check_find_job, not_done, jid)
|
||||||
+ try:
|
+ try:
|
||||||
+ if not_done:
|
+ if not_done:
|
||||||
+ jid = self.jid_gen()
|
+ jid = self.jid_gen()
|
||||||
+ find_job_return_pattern = 'salt/job/{0}/ret/*'.format(jid)
|
+ find_job_return_pattern = "salt/job/{}/ret/*".format(jid)
|
||||||
+ self.patterns.add((find_job_return_pattern, "find_job_return"))
|
+ self.patterns.add((find_job_return_pattern, "find_job_return"))
|
||||||
+ self.event.subscribe(find_job_return_pattern, match_type='glob')
|
+ self.event.subscribe(find_job_return_pattern, match_type="glob")
|
||||||
+ ret = yield self.local.run_job_async(
|
+ ret = yield self.local.run_job_async(
|
||||||
+ not_done,
|
+ not_done,
|
||||||
+ 'saltutil.find_job',
|
+ "saltutil.find_job",
|
||||||
+ [self.batch_jid],
|
+ [self.batch_jid],
|
||||||
+ 'list',
|
+ "list",
|
||||||
+ gather_job_timeout=self.opts['gather_job_timeout'],
|
+ gather_job_timeout=self.opts["gather_job_timeout"],
|
||||||
+ jid=jid,
|
+ jid=jid,
|
||||||
+ **self.eauth)
|
+ **self.eauth
|
||||||
+ yield tornado.gen.sleep(self.opts['gather_job_timeout'])
|
+ )
|
||||||
|
+ yield tornado.gen.sleep(self.opts["gather_job_timeout"])
|
||||||
+ if self.event:
|
+ if self.event:
|
||||||
+ self.event.io_loop.spawn_callback(
|
+ self.event.io_loop.spawn_callback(
|
||||||
+ self.check_find_job,
|
+ self.check_find_job, not_done, jid
|
||||||
+ not_done,
|
+ )
|
||||||
+ jid)
|
|
||||||
+ except Exception as ex:
|
+ except Exception as ex:
|
||||||
+ log.error("Exception occured handling batch async: {}. Aborting execution.".format(ex))
|
+ log.error(
|
||||||
|
+ "Exception occured handling batch async: {}. Aborting execution.".format(
|
||||||
|
+ ex
|
||||||
|
+ )
|
||||||
|
+ )
|
||||||
+ self.close_safe()
|
+ self.close_safe()
|
||||||
|
|
||||||
@tornado.gen.coroutine
|
@tornado.gen.coroutine
|
||||||
def start(self):
|
def start(self):
|
||||||
- self.__set_event_handler()
|
- self.__set_event_handler()
|
||||||
- ping_return = yield self.local.run_job_async(
|
- ping_return = yield self.local.run_job_async(
|
||||||
- self.opts['tgt'],
|
- self.opts["tgt"],
|
||||||
- 'test.ping',
|
- "test.ping",
|
||||||
- [],
|
- [],
|
||||||
- self.opts.get(
|
- self.opts.get("selected_target_option", self.opts.get("tgt_type", "glob")),
|
||||||
- 'selected_target_option',
|
- gather_job_timeout=self.opts["gather_job_timeout"],
|
||||||
- self.opts.get('tgt_type', 'glob')
|
|
||||||
- ),
|
|
||||||
- gather_job_timeout=self.opts['gather_job_timeout'],
|
|
||||||
- jid=self.ping_jid,
|
- jid=self.ping_jid,
|
||||||
- metadata=self.metadata,
|
- metadata=self.metadata,
|
||||||
- **self.eauth)
|
- **self.eauth
|
||||||
- self.targeted_minions = set(ping_return['minions'])
|
- )
|
||||||
- #start batching even if not all minions respond to ping
|
- self.targeted_minions = set(ping_return["minions"])
|
||||||
- yield tornado.gen.sleep(self.batch_presence_ping_timeout or self.opts['gather_job_timeout'])
|
- # start batching even if not all minions respond to ping
|
||||||
|
- yield tornado.gen.sleep(
|
||||||
|
- self.batch_presence_ping_timeout or self.opts["gather_job_timeout"]
|
||||||
|
- )
|
||||||
- self.event.io_loop.spawn_callback(self.start_batch)
|
- self.event.io_loop.spawn_callback(self.start_batch)
|
||||||
-
|
|
||||||
+ if self.event:
|
+ if self.event:
|
||||||
+ self.__set_event_handler()
|
+ self.__set_event_handler()
|
||||||
+ ping_return = yield self.local.run_job_async(
|
+ ping_return = yield self.local.run_job_async(
|
||||||
+ self.opts['tgt'],
|
+ self.opts["tgt"],
|
||||||
+ 'test.ping',
|
+ "test.ping",
|
||||||
+ [],
|
+ [],
|
||||||
+ self.opts.get(
|
+ self.opts.get(
|
||||||
+ 'selected_target_option',
|
+ "selected_target_option", self.opts.get("tgt_type", "glob")
|
||||||
+ self.opts.get('tgt_type', 'glob')
|
|
||||||
+ ),
|
+ ),
|
||||||
+ gather_job_timeout=self.opts['gather_job_timeout'],
|
+ gather_job_timeout=self.opts["gather_job_timeout"],
|
||||||
+ jid=self.ping_jid,
|
+ jid=self.ping_jid,
|
||||||
+ metadata=self.metadata,
|
+ metadata=self.metadata,
|
||||||
+ **self.eauth)
|
+ **self.eauth
|
||||||
+ self.targeted_minions = set(ping_return['minions'])
|
+ )
|
||||||
+ #start batching even if not all minions respond to ping
|
+ self.targeted_minions = set(ping_return["minions"])
|
||||||
+ yield tornado.gen.sleep(self.batch_presence_ping_timeout or self.opts['gather_job_timeout'])
|
+ # start batching even if not all minions respond to ping
|
||||||
|
+ yield tornado.gen.sleep(
|
||||||
|
+ self.batch_presence_ping_timeout or self.opts["gather_job_timeout"]
|
||||||
|
+ )
|
||||||
+ if self.event:
|
+ if self.event:
|
||||||
+ self.event.io_loop.spawn_callback(self.start_batch)
|
+ self.event.io_loop.spawn_callback(self.start_batch)
|
||||||
|
|
||||||
@tornado.gen.coroutine
|
@tornado.gen.coroutine
|
||||||
def start_batch(self):
|
def start_batch(self):
|
||||||
@@ -206,7 +213,8 @@ class BatchAsync(object):
|
@@ -215,7 +232,8 @@ class BatchAsync:
|
||||||
"metadata": self.metadata
|
ret = self.event.fire_event(
|
||||||
}
|
data, "salt/batch/{}/start".format(self.batch_jid)
|
||||||
ret = self.event.fire_event(data, "salt/batch/{0}/start".format(self.batch_jid))
|
)
|
||||||
- self.event.io_loop.spawn_callback(self.run_next)
|
- self.event.io_loop.spawn_callback(self.run_next)
|
||||||
+ if self.event:
|
+ if self.event:
|
||||||
+ self.event.io_loop.spawn_callback(self.run_next)
|
+ self.event.io_loop.spawn_callback(self.run_next)
|
||||||
|
|
||||||
@tornado.gen.coroutine
|
@tornado.gen.coroutine
|
||||||
def end_batch(self):
|
def end_batch(self):
|
||||||
@@ -221,11 +229,21 @@ class BatchAsync(object):
|
@@ -232,11 +250,21 @@ class BatchAsync:
|
||||||
"metadata": self.metadata
|
"metadata": self.metadata,
|
||||||
}
|
}
|
||||||
self.event.fire_event(data, "salt/batch/{0}/done".format(self.batch_jid))
|
self.event.fire_event(data, "salt/batch/{}/done".format(self.batch_jid))
|
||||||
- for (pattern, label) in self.patterns:
|
- for (pattern, label) in self.patterns:
|
||||||
- if label in ["ping_return", "batch_run"]:
|
- if label in ["ping_return", "batch_run"]:
|
||||||
- self.event.unsubscribe(pattern, match_type='glob')
|
- self.event.unsubscribe(pattern, match_type="glob")
|
||||||
- del self
|
- del self
|
||||||
- gc.collect()
|
- gc.collect()
|
||||||
+
|
+
|
||||||
@ -190,7 +188,7 @@ index da069b64bd..b8f272ed67 100644
|
|||||||
+
|
+
|
||||||
+ def close_safe(self):
|
+ def close_safe(self):
|
||||||
+ for (pattern, label) in self.patterns:
|
+ for (pattern, label) in self.patterns:
|
||||||
+ self.event.unsubscribe(pattern, match_type='glob')
|
+ self.event.unsubscribe(pattern, match_type="glob")
|
||||||
+ self.event.remove_event_handler(self.__event_handler)
|
+ self.event.remove_event_handler(self.__event_handler)
|
||||||
+ self.event = None
|
+ self.event = None
|
||||||
+ self.local = None
|
+ self.local = None
|
||||||
@ -200,7 +198,7 @@ index da069b64bd..b8f272ed67 100644
|
|||||||
|
|
||||||
@tornado.gen.coroutine
|
@tornado.gen.coroutine
|
||||||
def schedule_next(self):
|
def schedule_next(self):
|
||||||
@@ -233,7 +251,8 @@ class BatchAsync(object):
|
@@ -244,7 +272,8 @@ class BatchAsync:
|
||||||
self.scheduled = True
|
self.scheduled = True
|
||||||
# call later so that we maybe gather more returns
|
# call later so that we maybe gather more returns
|
||||||
yield tornado.gen.sleep(self.batch_delay)
|
yield tornado.gen.sleep(self.batch_delay)
|
||||||
@ -210,10 +208,10 @@ index da069b64bd..b8f272ed67 100644
|
|||||||
|
|
||||||
@tornado.gen.coroutine
|
@tornado.gen.coroutine
|
||||||
def run_next(self):
|
def run_next(self):
|
||||||
@@ -254,17 +273,20 @@ class BatchAsync(object):
|
@@ -266,17 +295,20 @@ class BatchAsync:
|
||||||
metadata=self.metadata)
|
)
|
||||||
|
|
||||||
yield tornado.gen.sleep(self.opts['timeout'])
|
yield tornado.gen.sleep(self.opts["timeout"])
|
||||||
- self.event.io_loop.spawn_callback(self.find_job, set(next_batch))
|
- self.event.io_loop.spawn_callback(self.find_job, set(next_batch))
|
||||||
+
|
+
|
||||||
+ # The batch can be done already at this point, which means no self.event
|
+ # The batch can be done already at this point, which means no self.event
|
||||||
@ -235,6 +233,6 @@ index da069b64bd..b8f272ed67 100644
|
|||||||
self.ioloop = None
|
self.ioloop = None
|
||||||
gc.collect()
|
gc.collect()
|
||||||
--
|
--
|
||||||
2.23.0
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
From bbd2e622f7e165a6e16fd5edf5f4596764748208 Mon Sep 17 00:00:00 2001
|
From 03f0aa44f6963e09a92dd3ea2090ef9ee463cb94 Mon Sep 17 00:00:00 2001
|
||||||
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||||
<psuarezhernandez@suse.com>
|
<psuarezhernandez@suse.com>
|
||||||
Date: Wed, 5 Jun 2019 15:15:04 +0100
|
Date: Wed, 5 Jun 2019 15:15:04 +0100
|
||||||
Subject: [PATCH] batch.py: avoid exception when minion does not respond
|
Subject: [PATCH] batch.py: avoid exception when minion does not
|
||||||
(bsc#1135507)
|
respond (bsc#1135507)
|
||||||
MIME-Version: 1.0
|
MIME-Version: 1.0
|
||||||
Content-Type: text/plain; charset=UTF-8
|
Content-Type: text/plain; charset=UTF-8
|
||||||
Content-Transfer-Encoding: 8bit
|
Content-Transfer-Encoding: 8bit
|
||||||
@ -18,26 +18,29 @@ bsc#1135507
|
|||||||
|
|
||||||
Signed-off-by: José Guilherme Vanz <jguilhermevanz@suse.com>
|
Signed-off-by: José Guilherme Vanz <jguilhermevanz@suse.com>
|
||||||
---
|
---
|
||||||
salt/cli/batch.py | 5 +++++
|
salt/cli/batch.py | 8 ++++++++
|
||||||
1 file changed, 5 insertions(+)
|
1 file changed, 8 insertions(+)
|
||||||
|
|
||||||
diff --git a/salt/cli/batch.py b/salt/cli/batch.py
|
diff --git a/salt/cli/batch.py b/salt/cli/batch.py
|
||||||
index 67f03c8a45..10fc81a5f4 100644
|
index 2bc5444aef..6285a45434 100644
|
||||||
--- a/salt/cli/batch.py
|
--- a/salt/cli/batch.py
|
||||||
+++ b/salt/cli/batch.py
|
+++ b/salt/cli/batch.py
|
||||||
@@ -318,6 +318,11 @@ class Batch(object):
|
@@ -348,6 +348,14 @@ class Batch:
|
||||||
if self.opts.get('failhard') and data['retcode'] > 0:
|
if self.opts.get("failhard") and data["retcode"] > 0:
|
||||||
failhard = True
|
failhard = True
|
||||||
|
|
||||||
+ # avoid an exception if the minion does not respond.
|
+ # avoid an exception if the minion does not respond.
|
||||||
+ if data.get("failed") is True:
|
+ if data.get("failed") is True:
|
||||||
+ log.debug('Minion %s failed to respond: data=%s', minion, data)
|
+ log.debug("Minion %s failed to respond: data=%s", minion, data)
|
||||||
+ data = {'ret': 'Minion did not return. [Failed]', 'retcode': salt.defaults.exitcodes.EX_GENERIC}
|
+ data = {
|
||||||
|
+ "ret": "Minion did not return. [Failed]",
|
||||||
|
+ "retcode": salt.defaults.exitcodes.EX_GENERIC,
|
||||||
|
+ }
|
||||||
+
|
+
|
||||||
if self.opts.get('raw'):
|
if self.opts.get("raw"):
|
||||||
ret[minion] = data
|
ret[minion] = data
|
||||||
yield data
|
yield data
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,26 +1,27 @@
|
|||||||
From bd20cd2655a1141fe9ea892e974e40988c3fb83c Mon Sep 17 00:00:00 2001
|
From 31fedcb3173f73fbffc3b053bc64c94a7b608118 Mon Sep 17 00:00:00 2001
|
||||||
From: Silvio Moioli <smoioli@suse.de>
|
From: Silvio Moioli <smoioli@suse.de>
|
||||||
Date: Mon, 2 Mar 2020 11:23:59 +0100
|
Date: Mon, 2 Mar 2020 11:23:59 +0100
|
||||||
Subject: [PATCH] batch_async: avoid using fnmatch to match event (#217)
|
Subject: [PATCH] batch_async: avoid using fnmatch to match event
|
||||||
|
(#217)
|
||||||
|
|
||||||
---
|
---
|
||||||
salt/cli/batch_async.py | 2 +-
|
salt/cli/batch_async.py | 2 +-
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
diff --git a/salt/cli/batch_async.py b/salt/cli/batch_async.py
|
diff --git a/salt/cli/batch_async.py b/salt/cli/batch_async.py
|
||||||
index c4545e3ebc..da069b64bd 100644
|
index 8d2601e636..1e2ac5b0d3 100644
|
||||||
--- a/salt/cli/batch_async.py
|
--- a/salt/cli/batch_async.py
|
||||||
+++ b/salt/cli/batch_async.py
|
+++ b/salt/cli/batch_async.py
|
||||||
@@ -106,7 +106,7 @@ class BatchAsync(object):
|
@@ -109,7 +109,7 @@ class BatchAsync:
|
||||||
return
|
return
|
||||||
mtag, data = self.event.unpack(raw, self.event.serial)
|
mtag, data = self.event.unpack(raw, self.event.serial)
|
||||||
for (pattern, op) in self.patterns:
|
for (pattern, op) in self.patterns:
|
||||||
- if fnmatch.fnmatch(mtag, pattern):
|
- if fnmatch.fnmatch(mtag, pattern):
|
||||||
+ if mtag.startswith(pattern[:-1]):
|
+ if mtag.startswith(pattern[:-1]):
|
||||||
minion = data['id']
|
minion = data["id"]
|
||||||
if op == 'ping_return':
|
if op == "ping_return":
|
||||||
self.minions.add(minion)
|
self.minions.add(minion)
|
||||||
--
|
--
|
||||||
2.23.0
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From 8973063f6ad24fd5b3788292aa8cc341221d7fb5 Mon Sep 17 00:00:00 2001
|
From 60b8f6cdaab10a12973a074678608b86a34e23b7 Mon Sep 17 00:00:00 2001
|
||||||
From: Victor Zhestkov <35733135+vzhestkov@users.noreply.github.com>
|
From: Victor Zhestkov <35733135+vzhestkov@users.noreply.github.com>
|
||||||
Date: Tue, 6 Oct 2020 12:36:41 +0300
|
Date: Tue, 6 Oct 2020 12:36:41 +0300
|
||||||
Subject: [PATCH] bsc#1176024: Fix file/directory user and group
|
Subject: [PATCH] bsc#1176024: Fix file/directory user and group
|
||||||
@ -12,22 +12,22 @@ Subject: [PATCH] bsc#1176024: Fix file/directory user and group
|
|||||||
|
|
||||||
Co-authored-by: Victor Zhestkov <vzhestkov@vz-thinkpad.vzhestkov.net>
|
Co-authored-by: Victor Zhestkov <vzhestkov@vz-thinkpad.vzhestkov.net>
|
||||||
---
|
---
|
||||||
salt/modules/file.py | 18 +++++++++---------
|
salt/modules/file.py | 26 +++++++++++++++++---------
|
||||||
salt/states/file.py | 4 ++--
|
salt/states/file.py | 12 ++++++++++--
|
||||||
2 files changed, 11 insertions(+), 11 deletions(-)
|
2 files changed, 27 insertions(+), 11 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/modules/file.py b/salt/modules/file.py
|
diff --git a/salt/modules/file.py b/salt/modules/file.py
|
||||||
index b5b70e2d4c..0b516aff05 100644
|
index 989a7ad92d..b830b390d3 100644
|
||||||
--- a/salt/modules/file.py
|
--- a/salt/modules/file.py
|
||||||
+++ b/salt/modules/file.py
|
+++ b/salt/modules/file.py
|
||||||
@@ -256,7 +256,7 @@ def group_to_gid(group):
|
@@ -252,7 +252,7 @@ def group_to_gid(group):
|
||||||
try:
|
try:
|
||||||
if isinstance(group, int):
|
if isinstance(group, int):
|
||||||
return group
|
return group
|
||||||
- return grp.getgrnam(group).gr_gid
|
- return grp.getgrnam(group).gr_gid
|
||||||
+ return grp.getgrnam(salt.utils.stringutils.to_str(group)).gr_gid
|
+ return grp.getgrnam(salt.utils.stringutils.to_str(group)).gr_gid
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return ''
|
return ""
|
||||||
|
|
||||||
@@ -344,7 +344,7 @@ def user_to_uid(user):
|
@@ -344,7 +344,7 @@ def user_to_uid(user):
|
||||||
try:
|
try:
|
||||||
@ -36,77 +36,91 @@ index b5b70e2d4c..0b516aff05 100644
|
|||||||
- return pwd.getpwnam(user).pw_uid
|
- return pwd.getpwnam(user).pw_uid
|
||||||
+ return pwd.getpwnam(salt.utils.stringutils.to_str(user)).pw_uid
|
+ return pwd.getpwnam(salt.utils.stringutils.to_str(user)).pw_uid
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return ''
|
return ""
|
||||||
|
|
||||||
@@ -4574,7 +4574,7 @@ def check_perms(name, ret, user, group, mode, attrs=None, follow_symlinks=False)
|
@@ -4977,7 +4977,10 @@ def check_perms(
|
||||||
if (salt.utils.platform.is_windows() and
|
if (
|
||||||
user_to_uid(user) != user_to_uid(perms['luser'])
|
salt.utils.platform.is_windows()
|
||||||
) or (
|
and user_to_uid(user) != user_to_uid(perms["luser"])
|
||||||
- not salt.utils.platform.is_windows() and user != perms['luser']
|
- ) or (not salt.utils.platform.is_windows() and user != perms["luser"]):
|
||||||
+ not salt.utils.platform.is_windows() and salt.utils.stringutils.to_str(user) != perms['luser']
|
+ ) or (
|
||||||
):
|
+ not salt.utils.platform.is_windows()
|
||||||
perms['cuser'] = user
|
+ and salt.utils.stringutils.to_str(user) != perms["luser"]
|
||||||
|
+ ):
|
||||||
|
perms["cuser"] = user
|
||||||
|
|
||||||
@@ -4584,7 +4584,7 @@ def check_perms(name, ret, user, group, mode, attrs=None, follow_symlinks=False)
|
if group:
|
||||||
if (salt.utils.platform.is_windows() and
|
@@ -4986,7 +4989,10 @@ def check_perms(
|
||||||
group_to_gid(group) != group_to_gid(perms['lgroup'])
|
if (
|
||||||
) or (
|
salt.utils.platform.is_windows()
|
||||||
- not salt.utils.platform.is_windows() and group != perms['lgroup']
|
and group_to_gid(group) != group_to_gid(perms["lgroup"])
|
||||||
+ not salt.utils.platform.is_windows() and salt.utils.stringutils.to_str(group) != perms['lgroup']
|
- ) or (not salt.utils.platform.is_windows() and group != perms["lgroup"]):
|
||||||
):
|
+ ) or (
|
||||||
perms['cgroup'] = group
|
+ not salt.utils.platform.is_windows()
|
||||||
|
+ and salt.utils.stringutils.to_str(group) != perms["lgroup"]
|
||||||
|
+ ):
|
||||||
|
perms["cgroup"] = group
|
||||||
|
|
||||||
@@ -4615,7 +4615,7 @@ def check_perms(name, ret, user, group, mode, attrs=None, follow_symlinks=False)
|
if "cuser" in perms or "cgroup" in perms:
|
||||||
user != ''
|
@@ -5017,7 +5023,8 @@ def check_perms(
|
||||||
|
and user != ""
|
||||||
) or (
|
) or (
|
||||||
not salt.utils.platform.is_windows() and
|
not salt.utils.platform.is_windows()
|
||||||
- user != get_user(name, follow_symlinks=follow_symlinks) and
|
- and user != get_user(name, follow_symlinks=follow_symlinks)
|
||||||
+ salt.utils.stringutils.to_str(user) != get_user(name, follow_symlinks=follow_symlinks) and
|
+ and salt.utils.stringutils.to_str(user)
|
||||||
user != ''
|
+ != get_user(name, follow_symlinks=follow_symlinks)
|
||||||
|
and user != ""
|
||||||
):
|
):
|
||||||
if __opts__['test'] is True:
|
if __opts__["test"] is True:
|
||||||
@@ -4633,10 +4633,10 @@ def check_perms(name, ret, user, group, mode, attrs=None, follow_symlinks=False)
|
@@ -5035,18 +5042,19 @@ def check_perms(
|
||||||
if (salt.utils.platform.is_windows() and
|
salt.utils.platform.is_windows()
|
||||||
group_to_gid(group) != group_to_gid(
|
and group_to_gid(group)
|
||||||
get_group(name, follow_symlinks=follow_symlinks)) and
|
!= group_to_gid(get_group(name, follow_symlinks=follow_symlinks))
|
||||||
- user != '') or (
|
- and user != ""
|
||||||
+ group != '') or (
|
+ and group != ""
|
||||||
not salt.utils.platform.is_windows() and
|
) or (
|
||||||
- group != get_group(name, follow_symlinks=follow_symlinks) and
|
not salt.utils.platform.is_windows()
|
||||||
- user != ''
|
- and group != get_group(name, follow_symlinks=follow_symlinks)
|
||||||
+ salt.utils.stringutils.to_str(group) != get_group(name, follow_symlinks=follow_symlinks) and
|
- and user != ""
|
||||||
+ group != ''
|
+ and salt.utils.stringutils.to_str(group)
|
||||||
|
+ != get_group(name, follow_symlinks=follow_symlinks)
|
||||||
|
+ and group != ""
|
||||||
):
|
):
|
||||||
if __opts__['test'] is True:
|
if __opts__["test"] is True:
|
||||||
ret['changes']['group'] = group
|
ret["changes"]["group"] = group
|
||||||
@@ -4644,7 +4644,7 @@ def check_perms(name, ret, user, group, mode, attrs=None, follow_symlinks=False)
|
else:
|
||||||
ret['result'] = False
|
ret["result"] = False
|
||||||
ret['comment'].append('Failed to change group to {0}'
|
ret["comment"].append("Failed to change group to {}".format(group))
|
||||||
.format(group))
|
- elif "cgroup" in perms and user != "":
|
||||||
- elif 'cgroup' in perms and user != '':
|
+ elif "cgroup" in perms and group != "":
|
||||||
+ elif 'cgroup' in perms and group != '':
|
ret["changes"]["group"] = group
|
||||||
ret['changes']['group'] = group
|
|
||||||
|
|
||||||
# Mode changes if needed
|
# Mode changes if needed
|
||||||
diff --git a/salt/states/file.py b/salt/states/file.py
|
diff --git a/salt/states/file.py b/salt/states/file.py
|
||||||
index 0e925bb2ed..f21e0d12fc 100644
|
index 9e24e389d8..89c70eb454 100644
|
||||||
--- a/salt/states/file.py
|
--- a/salt/states/file.py
|
||||||
+++ b/salt/states/file.py
|
+++ b/salt/states/file.py
|
||||||
@@ -960,11 +960,11 @@ def _check_dir_meta(name,
|
@@ -989,9 +989,17 @@ def _check_dir_meta(name, user, group, mode, follow_symlinks=False):
|
||||||
changes['directory'] = 'new'
|
if not stats:
|
||||||
|
changes["directory"] = "new"
|
||||||
return changes
|
return changes
|
||||||
if (user is not None
|
- if user is not None and user != stats["user"] and user != stats.get("uid"):
|
||||||
- and user != stats['user']
|
+ if (
|
||||||
+ and salt.utils.stringutils.to_str(user) != stats['user']
|
+ user is not None
|
||||||
and user != stats.get('uid')):
|
+ and salt.utils.stringutils.to_str(user) != stats["user"]
|
||||||
changes['user'] = user
|
+ and user != stats.get("uid")
|
||||||
if (group is not None
|
+ ):
|
||||||
- and group != stats['group']
|
changes["user"] = user
|
||||||
+ and salt.utils.stringutils.to_str(group) != stats['group']
|
- if group is not None and group != stats["group"] and group != stats.get("gid"):
|
||||||
and group != stats.get('gid')):
|
+ if (
|
||||||
changes['group'] = group
|
+ group is not None
|
||||||
|
+ and salt.utils.stringutils.to_str(group) != stats["group"]
|
||||||
|
+ and group != stats.get("gid")
|
||||||
|
+ ):
|
||||||
|
changes["group"] = group
|
||||||
# Normalize the dir mode
|
# Normalize the dir mode
|
||||||
|
smode = salt.utils.files.normalize_mode(stats["mode"])
|
||||||
--
|
--
|
||||||
2.28.0
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From 07f5a1d984b5a86c24620503f5e373ea0f11484a Mon Sep 17 00:00:00 2001
|
From d9362f10681a2dfdb057939eee1ffae3a35d4a8d Mon Sep 17 00:00:00 2001
|
||||||
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||||
<psuarezhernandez@suse.com>
|
<psuarezhernandez@suse.com>
|
||||||
Date: Fri, 12 Apr 2019 16:47:03 +0100
|
Date: Fri, 12 Apr 2019 16:47:03 +0100
|
||||||
@ -7,54 +7,81 @@ Subject: [PATCH] Calculate FQDNs in parallel to avoid blockings
|
|||||||
|
|
||||||
Fix pylint issue
|
Fix pylint issue
|
||||||
---
|
---
|
||||||
salt/grains/core.py | 31 ++++++++++++++++++++++++++-----
|
salt/grains/core.py | 55 +++++++++++++++++++++++++++++++++------------
|
||||||
1 file changed, 26 insertions(+), 5 deletions(-)
|
1 file changed, 41 insertions(+), 14 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/grains/core.py b/salt/grains/core.py
|
diff --git a/salt/grains/core.py b/salt/grains/core.py
|
||||||
index 309e4c9c4a..4600f055dd 100644
|
index 006878f806..883e3ebe09 100644
|
||||||
--- a/salt/grains/core.py
|
--- a/salt/grains/core.py
|
||||||
+++ b/salt/grains/core.py
|
+++ b/salt/grains/core.py
|
||||||
@@ -20,12 +20,15 @@ import platform
|
@@ -20,8 +20,10 @@ import socket
|
||||||
import logging
|
import sys
|
||||||
import locale
|
import time
|
||||||
import uuid
|
import uuid
|
||||||
+import time
|
+import warnings
|
||||||
import zlib
|
import zlib
|
||||||
from errno import EACCES, EPERM
|
from errno import EACCES, EPERM
|
||||||
import datetime
|
|
||||||
import warnings
|
|
||||||
import time
|
|
||||||
|
|
||||||
+from multiprocessing.dummy import Pool as ThreadPool
|
+from multiprocessing.dummy import Pool as ThreadPool
|
||||||
|
|
||||||
|
import distro
|
||||||
|
import salt.exceptions
|
||||||
|
@@ -44,6 +46,14 @@ import salt.utils.versions
|
||||||
|
from salt.ext.six.moves import range
|
||||||
|
from salt.utils.network import _get_interfaces
|
||||||
|
|
||||||
|
+# pylint: disable=import-error
|
||||||
|
+try:
|
||||||
|
+ import dateutil.tz
|
||||||
+
|
+
|
||||||
# pylint: disable=import-error
|
+ _DATEUTIL_TZ = True
|
||||||
try:
|
+except ImportError:
|
||||||
import dateutil.tz
|
+ _DATEUTIL_TZ = False
|
||||||
@@ -2275,13 +2278,10 @@ def fqdns():
|
+
|
||||||
|
|
||||||
|
# rewrite distro.linux_distribution to allow best=True kwarg in version(), needed to get the minor version numbers in CentOS
|
||||||
|
def _linux_distribution():
|
||||||
|
@@ -2402,22 +2412,12 @@ def fqdns():
|
||||||
grains = {}
|
grains = {}
|
||||||
fqdns = set()
|
fqdns = set()
|
||||||
|
|
||||||
- addresses = salt.utils.network.ip_addrs(include_loopback=False, interface_data=_get_interfaces())
|
- addresses = salt.utils.network.ip_addrs(
|
||||||
- addresses.extend(salt.utils.network.ip_addrs6(include_loopback=False, interface_data=_get_interfaces()))
|
- include_loopback=False, interface_data=_get_interfaces()
|
||||||
- err_message = 'Exception during resolving address: %s'
|
- )
|
||||||
|
- addresses.extend(
|
||||||
|
- salt.utils.network.ip_addrs6(
|
||||||
|
- include_loopback=False, interface_data=_get_interfaces()
|
||||||
|
- )
|
||||||
|
- )
|
||||||
|
- err_message = "Exception during resolving address: %s"
|
||||||
- for ip in addresses:
|
- for ip in addresses:
|
||||||
+ def _lookup_fqdn(ip):
|
+ def _lookup_fqdn(ip):
|
||||||
try:
|
try:
|
||||||
name, aliaslist, addresslist = socket.gethostbyaddr(ip)
|
name, aliaslist, addresslist = socket.gethostbyaddr(ip)
|
||||||
- fqdns.update([socket.getfqdn(name)] + [als for als in aliaslist if salt.utils.network.is_fqdn(als)])
|
- fqdns.update(
|
||||||
+ return [socket.getfqdn(name)] + [als for als in aliaslist if salt.utils.network.is_fqdn(als)]
|
- [socket.getfqdn(name)]
|
||||||
|
- + [als for als in aliaslist if salt.utils.network.is_fqdn(als)]
|
||||||
|
- )
|
||||||
|
+ return [socket.getfqdn(name)] + [
|
||||||
|
+ als for als in aliaslist if salt.utils.network.is_fqdn(als)
|
||||||
|
+ ]
|
||||||
except socket.herror as err:
|
except socket.herror as err:
|
||||||
if err.errno in (0, HOST_NOT_FOUND, NO_DATA):
|
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.
|
# No FQDN for this IP address, so we don't need to know this all the time.
|
||||||
@@ -2291,6 +2291,27 @@ def fqdns():
|
@@ -2427,6 +2427,33 @@ def fqdns():
|
||||||
except (socket.error, socket.gaierror, socket.timeout) as err:
|
except (OSError, socket.gaierror, socket.timeout) as err:
|
||||||
log.error(err_message, ip, err)
|
log.error(err_message, ip, err)
|
||||||
|
|
||||||
+ start = time.time()
|
+ start = time.time()
|
||||||
+
|
+
|
||||||
+ addresses = salt.utils.network.ip_addrs(include_loopback=False, interface_data=_get_interfaces())
|
+ addresses = salt.utils.network.ip_addrs(
|
||||||
+ addresses.extend(salt.utils.network.ip_addrs6(include_loopback=False, interface_data=_get_interfaces()))
|
+ include_loopback=False, interface_data=_get_interfaces()
|
||||||
+ err_message = 'Exception during resolving address: %s'
|
+ )
|
||||||
|
+ addresses.extend(
|
||||||
|
+ salt.utils.network.ip_addrs6(
|
||||||
|
+ include_loopback=False, interface_data=_get_interfaces()
|
||||||
|
+ )
|
||||||
|
+ )
|
||||||
|
+ err_message = "Exception during resolving address: %s"
|
||||||
+
|
+
|
||||||
+ # Create a ThreadPool to process the underlying calls to 'socket.gethostbyaddr' in parallel.
|
+ # Create a ThreadPool to process the underlying calls to 'socket.gethostbyaddr' in parallel.
|
||||||
+ # This avoid blocking the execution when the "fqdn" is not defined for certains IP addresses, which was causing
|
+ # This avoid blocking the execution when the "fqdn" is not defined for certains IP addresses, which was causing
|
||||||
@ -69,12 +96,12 @@ index 309e4c9c4a..4600f055dd 100644
|
|||||||
+ fqdns.update(item)
|
+ fqdns.update(item)
|
||||||
+
|
+
|
||||||
+ elapsed = time.time() - start
|
+ elapsed = time.time() - start
|
||||||
+ log.debug('Elapsed time getting FQDNs: {} seconds'.format(elapsed))
|
+ log.debug("Elapsed time getting FQDNs: {} seconds".format(elapsed))
|
||||||
+
|
+
|
||||||
return {"fqdns": sorted(list(fqdns))}
|
return {"fqdns": sorted(list(fqdns))}
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,38 +1,36 @@
|
|||||||
From 0cf1a655aa9353b22ae011e492a33aa52d780f83 Mon Sep 17 00:00:00 2001
|
From 5db9ccdb4f557cdbff670b18c45e55124e29c57c Mon Sep 17 00:00:00 2001
|
||||||
From: Jochen Breuer <jbreuer@suse.de>
|
From: Jochen Breuer <jbreuer@suse.de>
|
||||||
Date: Tue, 10 Mar 2020 14:02:17 +0100
|
Date: Tue, 10 Mar 2020 14:02:17 +0100
|
||||||
Subject: [PATCH] Changed imports to vendored Tornado
|
Subject: [PATCH] Changed imports to vendored Tornado
|
||||||
|
|
||||||
---
|
---
|
||||||
salt/cli/batch_async.py | 26 ++++++++++++------------
|
salt/cli/batch_async.py | 25 ++++++++++++-----------
|
||||||
salt/master.py | 2 +-
|
salt/master.py | 2 +-
|
||||||
salt/transport/ipc.py | 4 ++--
|
|
||||||
tests/unit/cli/test_batch_async.py | 32 +++++++++++++++---------------
|
tests/unit/cli/test_batch_async.py | 32 +++++++++++++++---------------
|
||||||
4 files changed, 32 insertions(+), 32 deletions(-)
|
3 files changed, 30 insertions(+), 29 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/cli/batch_async.py b/salt/cli/batch_async.py
|
diff --git a/salt/cli/batch_async.py b/salt/cli/batch_async.py
|
||||||
index b8f272ed67..08eeb34f1c 100644
|
index 3dc04826d1..09aa85258b 100644
|
||||||
--- a/salt/cli/batch_async.py
|
--- a/salt/cli/batch_async.py
|
||||||
+++ b/salt/cli/batch_async.py
|
+++ b/salt/cli/batch_async.py
|
||||||
@@ -6,7 +6,7 @@ Execute a job on the targeted minions by using a moving window of fixed size `ba
|
@@ -8,6 +8,7 @@ import gc
|
||||||
# Import python libs
|
import logging
|
||||||
from __future__ import absolute_import, print_function, unicode_literals
|
|
||||||
import gc
|
|
||||||
-import tornado
|
|
||||||
+import salt.ext.tornado
|
|
||||||
|
|
||||||
# Import salt libs
|
|
||||||
import salt.client
|
import salt.client
|
||||||
@@ -50,7 +50,7 @@ class BatchAsync(object):
|
+import salt.ext.tornado
|
||||||
}
|
import tornado
|
||||||
'''
|
from salt.cli.batch import batch_get_eauth, batch_get_opts, get_bnum
|
||||||
|
|
||||||
|
@@ -46,7 +47,7 @@ class BatchAsync:
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, parent_opts, jid_gen, clear_load):
|
def __init__(self, parent_opts, jid_gen, clear_load):
|
||||||
- ioloop = tornado.ioloop.IOLoop.current()
|
- ioloop = tornado.ioloop.IOLoop.current()
|
||||||
+ ioloop = salt.ext.tornado.ioloop.IOLoop.current()
|
+ ioloop = salt.ext.tornado.ioloop.IOLoop.current()
|
||||||
self.local = salt.client.get_local_client(parent_opts['conf_file'], io_loop=ioloop)
|
self.local = salt.client.get_local_client(
|
||||||
if 'gather_job_timeout' in clear_load['kwargs']:
|
parent_opts["conf_file"], io_loop=ioloop
|
||||||
clear_load['gather_job_timeout'] = clear_load['kwargs'].pop('gather_job_timeout')
|
)
|
||||||
@@ -152,7 +152,7 @@ class BatchAsync(object):
|
@@ -161,7 +162,7 @@ class BatchAsync:
|
||||||
self.find_job_returned = self.find_job_returned.difference(running)
|
self.find_job_returned = self.find_job_returned.difference(running)
|
||||||
self.event.io_loop.spawn_callback(self.find_job, running)
|
self.event.io_loop.spawn_callback(self.find_job, running)
|
||||||
|
|
||||||
@ -40,18 +38,18 @@ index b8f272ed67..08eeb34f1c 100644
|
|||||||
+ @salt.ext.tornado.gen.coroutine
|
+ @salt.ext.tornado.gen.coroutine
|
||||||
def find_job(self, minions):
|
def find_job(self, minions):
|
||||||
if self.event:
|
if self.event:
|
||||||
not_done = minions.difference(self.done_minions).difference(self.timedout_minions)
|
not_done = minions.difference(self.done_minions).difference(
|
||||||
@@ -170,7 +170,7 @@ class BatchAsync(object):
|
@@ -182,7 +183,7 @@ class BatchAsync:
|
||||||
gather_job_timeout=self.opts['gather_job_timeout'],
|
|
||||||
jid=jid,
|
jid=jid,
|
||||||
**self.eauth)
|
**self.eauth
|
||||||
- yield tornado.gen.sleep(self.opts['gather_job_timeout'])
|
)
|
||||||
+ yield salt.ext.tornado.gen.sleep(self.opts['gather_job_timeout'])
|
- yield tornado.gen.sleep(self.opts["gather_job_timeout"])
|
||||||
|
+ yield salt.ext.tornado.gen.sleep(self.opts["gather_job_timeout"])
|
||||||
if self.event:
|
if self.event:
|
||||||
self.event.io_loop.spawn_callback(
|
self.event.io_loop.spawn_callback(
|
||||||
self.check_find_job,
|
self.check_find_job, not_done, jid
|
||||||
@@ -180,7 +180,7 @@ class BatchAsync(object):
|
@@ -195,7 +196,7 @@ class BatchAsync:
|
||||||
log.error("Exception occured handling batch async: {}. Aborting execution.".format(ex))
|
)
|
||||||
self.close_safe()
|
self.close_safe()
|
||||||
|
|
||||||
- @tornado.gen.coroutine
|
- @tornado.gen.coroutine
|
||||||
@ -59,12 +57,14 @@ index b8f272ed67..08eeb34f1c 100644
|
|||||||
def start(self):
|
def start(self):
|
||||||
if self.event:
|
if self.event:
|
||||||
self.__set_event_handler()
|
self.__set_event_handler()
|
||||||
@@ -198,11 +198,11 @@ class BatchAsync(object):
|
@@ -213,13 +214,13 @@ class BatchAsync:
|
||||||
**self.eauth)
|
)
|
||||||
self.targeted_minions = set(ping_return['minions'])
|
self.targeted_minions = set(ping_return["minions"])
|
||||||
#start batching even if not all minions respond to ping
|
# start batching even if not all minions respond to ping
|
||||||
- yield tornado.gen.sleep(self.batch_presence_ping_timeout or self.opts['gather_job_timeout'])
|
- yield tornado.gen.sleep(
|
||||||
+ yield salt.ext.tornado.gen.sleep(self.batch_presence_ping_timeout or self.opts['gather_job_timeout'])
|
+ yield salt.ext.tornado.gen.sleep(
|
||||||
|
self.batch_presence_ping_timeout or self.opts["gather_job_timeout"]
|
||||||
|
)
|
||||||
if self.event:
|
if self.event:
|
||||||
self.event.io_loop.spawn_callback(self.start_batch)
|
self.event.io_loop.spawn_callback(self.start_batch)
|
||||||
|
|
||||||
@ -73,16 +73,16 @@ index b8f272ed67..08eeb34f1c 100644
|
|||||||
def start_batch(self):
|
def start_batch(self):
|
||||||
if not self.initialized:
|
if not self.initialized:
|
||||||
self.batch_size = get_bnum(self.opts, self.minions, True)
|
self.batch_size = get_bnum(self.opts, self.minions, True)
|
||||||
@@ -216,7 +216,7 @@ class BatchAsync(object):
|
@@ -235,7 +236,7 @@ class BatchAsync:
|
||||||
if self.event:
|
if self.event:
|
||||||
self.event.io_loop.spawn_callback(self.run_next)
|
self.event.io_loop.spawn_callback(self.run_next)
|
||||||
|
|
||||||
- @tornado.gen.coroutine
|
- @tornado.gen.coroutine
|
||||||
+ @salt.ext.tornado.gen.coroutine
|
+ @salt.ext.tornado.gen.coroutine
|
||||||
def end_batch(self):
|
def end_batch(self):
|
||||||
left = self.minions.symmetric_difference(self.done_minions.union(self.timedout_minions))
|
left = self.minions.symmetric_difference(
|
||||||
if not left and not self.ended:
|
self.done_minions.union(self.timedout_minions)
|
||||||
@@ -232,7 +232,7 @@ class BatchAsync(object):
|
@@ -253,7 +254,7 @@ class BatchAsync:
|
||||||
|
|
||||||
# release to the IOLoop to allow the event to be published
|
# release to the IOLoop to allow the event to be published
|
||||||
# before closing batch async execution
|
# before closing batch async execution
|
||||||
@ -91,7 +91,7 @@ index b8f272ed67..08eeb34f1c 100644
|
|||||||
self.close_safe()
|
self.close_safe()
|
||||||
|
|
||||||
def close_safe(self):
|
def close_safe(self):
|
||||||
@@ -245,16 +245,16 @@ class BatchAsync(object):
|
@@ -266,16 +267,16 @@ class BatchAsync:
|
||||||
del self
|
del self
|
||||||
gc.collect()
|
gc.collect()
|
||||||
|
|
||||||
@ -111,66 +111,44 @@ index b8f272ed67..08eeb34f1c 100644
|
|||||||
def run_next(self):
|
def run_next(self):
|
||||||
self.scheduled = False
|
self.scheduled = False
|
||||||
next_batch = self._get_next()
|
next_batch = self._get_next()
|
||||||
@@ -272,7 +272,7 @@ class BatchAsync(object):
|
@@ -294,7 +295,7 @@ class BatchAsync:
|
||||||
jid=self.batch_jid,
|
metadata=self.metadata,
|
||||||
metadata=self.metadata)
|
)
|
||||||
|
|
||||||
- yield tornado.gen.sleep(self.opts['timeout'])
|
- yield tornado.gen.sleep(self.opts["timeout"])
|
||||||
+ yield salt.ext.tornado.gen.sleep(self.opts['timeout'])
|
+ yield salt.ext.tornado.gen.sleep(self.opts["timeout"])
|
||||||
|
|
||||||
# The batch can be done already at this point, which means no self.event
|
# The batch can be done already at this point, which means no self.event
|
||||||
if self.event:
|
if self.event:
|
||||||
diff --git a/salt/master.py b/salt/master.py
|
diff --git a/salt/master.py b/salt/master.py
|
||||||
index 3abf7ae60b..3a9d12999d 100644
|
index 7a99af357a..ab85c7f5c6 100644
|
||||||
--- a/salt/master.py
|
--- a/salt/master.py
|
||||||
+++ b/salt/master.py
|
+++ b/salt/master.py
|
||||||
@@ -2049,7 +2049,7 @@ class ClearFuncs(object):
|
@@ -2237,7 +2237,7 @@ class ClearFuncs(TransportMethods):
|
||||||
functools.partial(self._prep_jid, clear_load, {}),
|
functools.partial(self._prep_jid, clear_load, {}),
|
||||||
batch_load
|
batch_load,
|
||||||
)
|
)
|
||||||
- ioloop = tornado.ioloop.IOLoop.current()
|
- ioloop = tornado.ioloop.IOLoop.current()
|
||||||
+ ioloop = salt.ext.tornado.ioloop.IOLoop.current()
|
+ ioloop = salt.ext.tornado.ioloop.IOLoop.current()
|
||||||
ioloop.add_callback(batch.start)
|
ioloop.add_callback(batch.start)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
diff --git a/salt/transport/ipc.py b/salt/transport/ipc.py
|
|
||||||
index d2b295a633..33ee3d4182 100644
|
|
||||||
--- a/salt/transport/ipc.py
|
|
||||||
+++ b/salt/transport/ipc.py
|
|
||||||
@@ -697,7 +697,7 @@ class IPCMessageSubscriber(IPCClient):
|
|
||||||
for callback in self.callbacks:
|
|
||||||
self.io_loop.spawn_callback(callback, raw)
|
|
||||||
|
|
||||||
- @tornado.gen.coroutine
|
|
||||||
+ @salt.ext.tornado.gen.coroutine
|
|
||||||
def read_async(self):
|
|
||||||
'''
|
|
||||||
Asynchronously read messages and invoke a callback when they are ready.
|
|
||||||
@@ -712,7 +712,7 @@ class IPCMessageSubscriber(IPCClient):
|
|
||||||
yield salt.ext.tornado.gen.sleep(1)
|
|
||||||
except Exception as exc: # pylint: disable=broad-except
|
|
||||||
log.error('Exception occurred while Subscriber connecting: %s', exc)
|
|
||||||
- yield tornado.gen.sleep(1)
|
|
||||||
+ yield salt.ext.tornado.gen.sleep(1)
|
|
||||||
yield self._read(None, self.__run_callbacks)
|
|
||||||
|
|
||||||
def close(self):
|
|
||||||
diff --git a/tests/unit/cli/test_batch_async.py b/tests/unit/cli/test_batch_async.py
|
diff --git a/tests/unit/cli/test_batch_async.py b/tests/unit/cli/test_batch_async.py
|
||||||
index e1ce60859b..635dc689a8 100644
|
index dcee9a87bd..82a712b15b 100644
|
||||||
--- a/tests/unit/cli/test_batch_async.py
|
--- a/tests/unit/cli/test_batch_async.py
|
||||||
+++ b/tests/unit/cli/test_batch_async.py
|
+++ b/tests/unit/cli/test_batch_async.py
|
||||||
@@ -5,8 +5,8 @@ from __future__ import absolute_import
|
@@ -1,8 +1,8 @@
|
||||||
# Import Salt Libs
|
|
||||||
from salt.cli.batch_async import BatchAsync
|
|
||||||
|
|
||||||
-import tornado
|
-import tornado
|
||||||
-from tornado.testing import AsyncTestCase
|
|
||||||
+import salt.ext.tornado
|
+import salt.ext.tornado
|
||||||
|
from salt.cli.batch_async import BatchAsync
|
||||||
+from salt.ext.tornado.testing import AsyncTestCase
|
+from salt.ext.tornado.testing import AsyncTestCase
|
||||||
from tests.support.unit import skipIf, TestCase
|
from tests.support.mock import NO_MOCK, NO_MOCK_REASON, MagicMock, patch
|
||||||
from tests.support.mock import MagicMock, patch, NO_MOCK, NO_MOCK_REASON
|
from tests.support.unit import TestCase, skipIf
|
||||||
|
-from tornado.testing import AsyncTestCase
|
||||||
|
|
||||||
@@ -59,10 +59,10 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
|
||||||
|
@skipIf(NO_MOCK, NO_MOCK_REASON)
|
||||||
|
@@ -52,10 +52,10 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
||||||
self.batch.start_batch()
|
self.batch.start_batch()
|
||||||
self.assertEqual(self.batch.batch_size, 2)
|
self.assertEqual(self.batch.batch_size, 2)
|
||||||
|
|
||||||
@ -180,12 +158,12 @@ index e1ce60859b..635dc689a8 100644
|
|||||||
self.batch.event = MagicMock()
|
self.batch.event = MagicMock()
|
||||||
- future = tornado.gen.Future()
|
- future = tornado.gen.Future()
|
||||||
+ future = salt.ext.tornado.gen.Future()
|
+ future = salt.ext.tornado.gen.Future()
|
||||||
future.set_result({'minions': ['foo', 'bar']})
|
future.set_result({"minions": ["foo", "bar"]})
|
||||||
self.batch.local.run_job_async.return_value = future
|
self.batch.local.run_job_async.return_value = future
|
||||||
ret = self.batch.start()
|
ret = self.batch.start()
|
||||||
@@ -78,10 +78,10 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
@@ -71,10 +71,10 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
||||||
# assert targeted_minions == all minions matched by tgt
|
# assert targeted_minions == all minions matched by tgt
|
||||||
self.assertEqual(self.batch.targeted_minions, set(['foo', 'bar']))
|
self.assertEqual(self.batch.targeted_minions, {"foo", "bar"})
|
||||||
|
|
||||||
- @tornado.testing.gen_test
|
- @tornado.testing.gen_test
|
||||||
+ @salt.ext.tornado.testing.gen_test
|
+ @salt.ext.tornado.testing.gen_test
|
||||||
@ -193,11 +171,11 @@ index e1ce60859b..635dc689a8 100644
|
|||||||
self.batch.event = MagicMock()
|
self.batch.event = MagicMock()
|
||||||
- future = tornado.gen.Future()
|
- future = tornado.gen.Future()
|
||||||
+ future = salt.ext.tornado.gen.Future()
|
+ future = salt.ext.tornado.gen.Future()
|
||||||
future.set_result({'minions': ['foo', 'bar']})
|
future.set_result({"minions": ["foo", "bar"]})
|
||||||
self.batch.local.run_job_async.return_value = future
|
self.batch.local.run_job_async.return_value = future
|
||||||
self.batch.batch_presence_ping_timeout = None
|
self.batch.batch_presence_ping_timeout = None
|
||||||
@@ -109,7 +109,7 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
@@ -103,7 +103,7 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
- @tornado.testing.gen_test
|
- @tornado.testing.gen_test
|
||||||
@ -205,26 +183,26 @@ index e1ce60859b..635dc689a8 100644
|
|||||||
def test_start_batch_calls_next(self):
|
def test_start_batch_calls_next(self):
|
||||||
self.batch.run_next = MagicMock(return_value=MagicMock())
|
self.batch.run_next = MagicMock(return_value=MagicMock())
|
||||||
self.batch.event = MagicMock()
|
self.batch.event = MagicMock()
|
||||||
@@ -165,14 +165,14 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
@@ -160,14 +160,14 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
||||||
self.assertEqual(
|
self.assertEqual(len(event.unsubscribe.mock_calls), 2)
|
||||||
len(event.remove_event_handler.mock_calls), 1)
|
self.assertEqual(len(event.remove_event_handler.mock_calls), 1)
|
||||||
|
|
||||||
- @tornado.testing.gen_test
|
- @tornado.testing.gen_test
|
||||||
+ @salt.ext.tornado.testing.gen_test
|
+ @salt.ext.tornado.testing.gen_test
|
||||||
def test_batch_next(self):
|
def test_batch_next(self):
|
||||||
self.batch.event = MagicMock()
|
self.batch.event = MagicMock()
|
||||||
self.batch.opts['fun'] = 'my.fun'
|
self.batch.opts["fun"] = "my.fun"
|
||||||
self.batch.opts['arg'] = []
|
self.batch.opts["arg"] = []
|
||||||
self.batch._get_next = MagicMock(return_value={'foo', 'bar'})
|
self.batch._get_next = MagicMock(return_value={"foo", "bar"})
|
||||||
self.batch.batch_size = 2
|
self.batch.batch_size = 2
|
||||||
- future = tornado.gen.Future()
|
- future = tornado.gen.Future()
|
||||||
+ future = salt.ext.tornado.gen.Future()
|
+ future = salt.ext.tornado.gen.Future()
|
||||||
future.set_result({'minions': ['foo', 'bar']})
|
future.set_result({"minions": ["foo", "bar"]})
|
||||||
self.batch.local.run_job_async.return_value = future
|
self.batch.local.run_job_async.return_value = future
|
||||||
self.batch.run_next()
|
self.batch.run_next()
|
||||||
@@ -284,38 +284,38 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
@@ -290,38 +290,38 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
||||||
self.batch._BatchAsync__event_handler(MagicMock())
|
self.batch._BatchAsync__event_handler(MagicMock())
|
||||||
self.assertEqual(self.batch.find_job_returned, {'foo'})
|
self.assertEqual(self.batch.find_job_returned, {"foo"})
|
||||||
|
|
||||||
- @tornado.testing.gen_test
|
- @tornado.testing.gen_test
|
||||||
+ @salt.ext.tornado.testing.gen_test
|
+ @salt.ext.tornado.testing.gen_test
|
||||||
@ -242,33 +220,33 @@ index e1ce60859b..635dc689a8 100644
|
|||||||
+ future = salt.ext.tornado.gen.Future()
|
+ future = salt.ext.tornado.gen.Future()
|
||||||
future.set_result({})
|
future.set_result({})
|
||||||
self.batch.local.run_job_async.return_value = future
|
self.batch.local.run_job_async.return_value = future
|
||||||
self.batch.minions = set(['foo', 'bar'])
|
self.batch.minions = {"foo", "bar"}
|
||||||
self.batch.jid_gen = MagicMock(return_value="1234")
|
self.batch.jid_gen = MagicMock(return_value="1234")
|
||||||
- tornado.gen.sleep = MagicMock(return_value=future)
|
- tornado.gen.sleep = MagicMock(return_value=future)
|
||||||
+ salt.ext.tornado.gen.sleep = MagicMock(return_value=future)
|
+ salt.ext.tornado.gen.sleep = MagicMock(return_value=future)
|
||||||
self.batch.find_job({'foo', 'bar'})
|
self.batch.find_job({"foo", "bar"})
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.batch.event.io_loop.spawn_callback.call_args[0],
|
self.batch.event.io_loop.spawn_callback.call_args[0],
|
||||||
(self.batch.check_find_job, {'foo', 'bar'}, "1234")
|
(self.batch.check_find_job, {"foo", "bar"}, "1234"),
|
||||||
)
|
)
|
||||||
|
|
||||||
- @tornado.testing.gen_test
|
- @tornado.testing.gen_test
|
||||||
+ @salt.ext.tornado.testing.gen_test
|
+ @salt.ext.tornado.testing.gen_test
|
||||||
def test_batch_find_job_with_done_minions(self):
|
def test_batch_find_job_with_done_minions(self):
|
||||||
self.batch.done_minions = {'bar'}
|
self.batch.done_minions = {"bar"}
|
||||||
self.batch.event = MagicMock()
|
self.batch.event = MagicMock()
|
||||||
- future = tornado.gen.Future()
|
- future = tornado.gen.Future()
|
||||||
+ future = salt.ext.tornado.gen.Future()
|
+ future = salt.ext.tornado.gen.Future()
|
||||||
future.set_result({})
|
future.set_result({})
|
||||||
self.batch.local.run_job_async.return_value = future
|
self.batch.local.run_job_async.return_value = future
|
||||||
self.batch.minions = set(['foo', 'bar'])
|
self.batch.minions = {"foo", "bar"}
|
||||||
self.batch.jid_gen = MagicMock(return_value="1234")
|
self.batch.jid_gen = MagicMock(return_value="1234")
|
||||||
- tornado.gen.sleep = MagicMock(return_value=future)
|
- tornado.gen.sleep = MagicMock(return_value=future)
|
||||||
+ salt.ext.tornado.gen.sleep = MagicMock(return_value=future)
|
+ salt.ext.tornado.gen.sleep = MagicMock(return_value=future)
|
||||||
self.batch.find_job({'foo', 'bar'})
|
self.batch.find_job({"foo", "bar"})
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.batch.event.io_loop.spawn_callback.call_args[0],
|
self.batch.event.io_loop.spawn_callback.call_args[0],
|
||||||
--
|
--
|
||||||
2.23.0
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,54 +0,0 @@
|
|||||||
From 615a8f8dfa8ef12eeb4c387e48309cc466b8597d Mon Sep 17 00:00:00 2001
|
|
||||||
From: Bo Maryniuk <bo@suse.de>
|
|
||||||
Date: Tue, 4 Dec 2018 16:39:08 +0100
|
|
||||||
Subject: [PATCH] Decide if the source should be actually skipped
|
|
||||||
|
|
||||||
---
|
|
||||||
salt/modules/aptpkg.py | 23 ++++++++++++++++++++++-
|
|
||||||
1 file changed, 22 insertions(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/salt/modules/aptpkg.py b/salt/modules/aptpkg.py
|
|
||||||
index 4ec9158476..3b0d8423db 100644
|
|
||||||
--- a/salt/modules/aptpkg.py
|
|
||||||
+++ b/salt/modules/aptpkg.py
|
|
||||||
@@ -1620,6 +1620,27 @@ def list_repo_pkgs(*args, **kwargs): # pylint: disable=unused-import
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
+def _skip_source(source):
|
|
||||||
+ '''
|
|
||||||
+ Decide to skip source or not.
|
|
||||||
+
|
|
||||||
+ :param source:
|
|
||||||
+ :return:
|
|
||||||
+ '''
|
|
||||||
+ if source.invalid:
|
|
||||||
+ if source.uri and source.type and source.type in ("deb", "deb-src", "rpm", "rpm-src"):
|
|
||||||
+ pieces = source.mysplit(source.line)
|
|
||||||
+ if pieces[1].strip()[0] == "[":
|
|
||||||
+ options = pieces.pop(1).strip("[]").split()
|
|
||||||
+ if len(options) > 0:
|
|
||||||
+ log.debug("Source %s will be included although is marked invalid", source.uri)
|
|
||||||
+ return False
|
|
||||||
+ return True
|
|
||||||
+ else:
|
|
||||||
+ return True
|
|
||||||
+ return False
|
|
||||||
+
|
|
||||||
+
|
|
||||||
def list_repos():
|
|
||||||
'''
|
|
||||||
Lists all repos in the sources.list (and sources.lists.d) files
|
|
||||||
@@ -1635,7 +1656,7 @@ def list_repos():
|
|
||||||
repos = {}
|
|
||||||
sources = sourceslist.SourcesList()
|
|
||||||
for source in sources.list:
|
|
||||||
- if source.invalid:
|
|
||||||
+ if _skip_source(source):
|
|
||||||
continue
|
|
||||||
repo = {}
|
|
||||||
repo['file'] = source.file
|
|
||||||
--
|
|
||||||
2.16.4
|
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
From f81a5b92d691c1d511a814f9344104dd37466bc3 Mon Sep 17 00:00:00 2001
|
From e986ed8fc0d5da74374d9ded82e10c16fc984ca8 Mon Sep 17 00:00:00 2001
|
||||||
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||||
<psuarezhernandez@suse.com>
|
<psuarezhernandez@suse.com>
|
||||||
Date: Wed, 29 May 2019 11:03:16 +0100
|
Date: Wed, 29 May 2019 11:03:16 +0100
|
||||||
@ -6,42 +6,45 @@ Subject: [PATCH] Do not break repo files with multiple line values on
|
|||||||
yumpkg (bsc#1135360)
|
yumpkg (bsc#1135360)
|
||||||
|
|
||||||
---
|
---
|
||||||
tests/integration/modules/test_pkg.py | 48 +++++++++++++++++++++++++++++++++++
|
tests/integration/modules/test_pkg.py | 51 +++++++++++++++++++++++++++
|
||||||
1 file changed, 48 insertions(+)
|
1 file changed, 51 insertions(+)
|
||||||
|
|
||||||
diff --git a/tests/integration/modules/test_pkg.py b/tests/integration/modules/test_pkg.py
|
diff --git a/tests/integration/modules/test_pkg.py b/tests/integration/modules/test_pkg.py
|
||||||
index e8374db2c0..61748f9477 100644
|
index 7a720523da..e32013800d 100644
|
||||||
--- a/tests/integration/modules/test_pkg.py
|
--- a/tests/integration/modules/test_pkg.py
|
||||||
+++ b/tests/integration/modules/test_pkg.py
|
+++ b/tests/integration/modules/test_pkg.py
|
||||||
@@ -182,6 +182,54 @@ class PkgModuleTest(ModuleCase, SaltReturnAssertsMixin):
|
@@ -194,6 +194,57 @@ class PkgModuleTest(ModuleCase, SaltReturnAssertsMixin):
|
||||||
if repo is not None:
|
if repo is not None:
|
||||||
self.run_function('pkg.del_repo', [repo])
|
self.run_function("pkg.del_repo", [repo])
|
||||||
|
|
||||||
+ def test_mod_del_repo_multiline_values(self):
|
+ def test_mod_del_repo_multiline_values(self):
|
||||||
+ '''
|
+ """
|
||||||
+ test modifying and deleting a software repository defined with multiline values
|
+ test modifying and deleting a software repository defined with multiline values
|
||||||
+ '''
|
+ """
|
||||||
+ os_grain = self.run_function('grains.item', ['os'])['os']
|
+ os_grain = self.run_function("grains.item", ["os"])["os"]
|
||||||
+ repo = None
|
+ repo = None
|
||||||
+ try:
|
+ try:
|
||||||
+ if os_grain in ['CentOS', 'RedHat', 'SUSE']:
|
+ if os_grain in ["CentOS", "RedHat", "SUSE"]:
|
||||||
+ my_baseurl = 'http://my.fake.repo/foo/bar/\n http://my.fake.repo.alt/foo/bar/'
|
+ my_baseurl = (
|
||||||
+ expected_get_repo_baseurl = 'http://my.fake.repo/foo/bar/\nhttp://my.fake.repo.alt/foo/bar/'
|
+ "http://my.fake.repo/foo/bar/\n http://my.fake.repo.alt/foo/bar/"
|
||||||
+ major_release = int(
|
|
||||||
+ self.run_function(
|
|
||||||
+ 'grains.item',
|
|
||||||
+ ['osmajorrelease']
|
|
||||||
+ )['osmajorrelease']
|
|
||||||
+ )
|
+ )
|
||||||
+ repo = 'fakerepo'
|
+ expected_get_repo_baseurl = (
|
||||||
+ name = 'Fake repo for RHEL/CentOS/SUSE'
|
+ "http://my.fake.repo/foo/bar/\nhttp://my.fake.repo.alt/foo/bar/"
|
||||||
|
+ )
|
||||||
|
+ major_release = int(
|
||||||
|
+ self.run_function("grains.item", ["osmajorrelease"])[
|
||||||
|
+ "osmajorrelease"
|
||||||
|
+ ]
|
||||||
|
+ )
|
||||||
|
+ repo = "fakerepo"
|
||||||
|
+ name = "Fake repo for RHEL/CentOS/SUSE"
|
||||||
+ baseurl = my_baseurl
|
+ baseurl = my_baseurl
|
||||||
+ gpgkey = 'https://my.fake.repo/foo/bar/MY-GPG-KEY.pub'
|
+ gpgkey = "https://my.fake.repo/foo/bar/MY-GPG-KEY.pub"
|
||||||
+ failovermethod = 'priority'
|
+ failovermethod = "priority"
|
||||||
+ gpgcheck = 1
|
+ gpgcheck = 1
|
||||||
+ enabled = 1
|
+ enabled = 1
|
||||||
+ ret = self.run_function(
|
+ ret = self.run_function(
|
||||||
+ 'pkg.mod_repo',
|
+ "pkg.mod_repo",
|
||||||
+ [repo],
|
+ [repo],
|
||||||
+ name=name,
|
+ name=name,
|
||||||
+ baseurl=baseurl,
|
+ baseurl=baseurl,
|
||||||
@ -55,20 +58,20 @@ index e8374db2c0..61748f9477 100644
|
|||||||
+ self.assertNotEqual(ret, {})
|
+ self.assertNotEqual(ret, {})
|
||||||
+ repo_info = ret[next(iter(ret))]
|
+ repo_info = ret[next(iter(ret))]
|
||||||
+ self.assertIn(repo, repo_info)
|
+ self.assertIn(repo, repo_info)
|
||||||
+ self.assertEqual(repo_info[repo]['baseurl'], my_baseurl)
|
+ self.assertEqual(repo_info[repo]["baseurl"], my_baseurl)
|
||||||
+ ret = self.run_function('pkg.get_repo', [repo])
|
+ ret = self.run_function("pkg.get_repo", [repo])
|
||||||
+ self.assertEqual(ret['baseurl'], expected_get_repo_baseurl)
|
+ self.assertEqual(ret["baseurl"], expected_get_repo_baseurl)
|
||||||
+ self.run_function('pkg.mod_repo', [repo])
|
+ self.run_function("pkg.mod_repo", [repo])
|
||||||
+ ret = self.run_function('pkg.get_repo', [repo])
|
+ ret = self.run_function("pkg.get_repo", [repo])
|
||||||
+ self.assertEqual(ret['baseurl'], expected_get_repo_baseurl)
|
+ self.assertEqual(ret["baseurl"], expected_get_repo_baseurl)
|
||||||
+ finally:
|
+ finally:
|
||||||
+ if repo is not None:
|
+ if repo is not None:
|
||||||
+ self.run_function('pkg.del_repo', [repo])
|
+ self.run_function("pkg.del_repo", [repo])
|
||||||
+
|
+
|
||||||
@requires_salt_modules('pkg.owner')
|
@requires_salt_modules("pkg.owner")
|
||||||
def test_owner(self):
|
def test_owner(self):
|
||||||
'''
|
"""
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From bfee3a7c47786bb860663de97fca26725101f1d0 Mon Sep 17 00:00:00 2001
|
From 998136ffd4c8442e0c3a7030af3d8196abec6be1 Mon Sep 17 00:00:00 2001
|
||||||
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||||
<psuarezhernandez@suse.com>
|
<psuarezhernandez@suse.com>
|
||||||
Date: Tue, 7 May 2019 15:33:51 +0100
|
Date: Tue, 7 May 2019 15:33:51 +0100
|
||||||
@ -11,24 +11,24 @@ Add unit test for '_netlink_tool_remote_on'
|
|||||||
1 file changed, 5 insertions(+)
|
1 file changed, 5 insertions(+)
|
||||||
|
|
||||||
diff --git a/salt/utils/network.py b/salt/utils/network.py
|
diff --git a/salt/utils/network.py b/salt/utils/network.py
|
||||||
index 2ae2e213b7..307cab885f 100644
|
index dd7fceb91a..d253ded3ab 100644
|
||||||
--- a/salt/utils/network.py
|
--- a/salt/utils/network.py
|
||||||
+++ b/salt/utils/network.py
|
+++ b/salt/utils/network.py
|
||||||
@@ -1442,8 +1442,13 @@ def _netlink_tool_remote_on(port, which_end):
|
@@ -1623,8 +1623,13 @@ def _netlink_tool_remote_on(port, which_end):
|
||||||
elif 'ESTAB' not in line:
|
elif "ESTAB" not in line:
|
||||||
continue
|
continue
|
||||||
chunks = line.split()
|
chunks = line.split()
|
||||||
+ local_host, local_port = chunks[3].rsplit(':', 1)
|
+ local_host, local_port = chunks[3].rsplit(":", 1)
|
||||||
remote_host, remote_port = chunks[4].rsplit(':', 1)
|
remote_host, remote_port = chunks[4].rsplit(":", 1)
|
||||||
|
|
||||||
+ if which_end == 'remote_port' and int(remote_port) != port:
|
+ if which_end == "remote_port" and int(remote_port) != port:
|
||||||
+ continue
|
+ continue
|
||||||
+ if which_end == 'local_port' and int(local_port) != port:
|
+ if which_end == "local_port" and int(local_port) != port:
|
||||||
+ continue
|
+ continue
|
||||||
remotes.add(remote_host.strip("[]"))
|
remotes.add(remote_host.strip("[]"))
|
||||||
|
|
||||||
if valid is False:
|
if valid is False:
|
||||||
--
|
--
|
||||||
2.23.0
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From 3d5d89428ca333caa2c2259f679f8fffd7110ba6 Mon Sep 17 00:00:00 2001
|
From 57f9da0bd7727c46eab866941fee46a3eaf8c8ea Mon Sep 17 00:00:00 2001
|
||||||
From: Bo Maryniuk <bo@suse.de>
|
From: Bo Maryniuk <bo@suse.de>
|
||||||
Date: Fri, 21 Sep 2018 17:31:39 +0200
|
Date: Fri, 21 Sep 2018 17:31:39 +0200
|
||||||
Subject: [PATCH] Do not load pip state if there is no 3rd party
|
Subject: [PATCH] Do not load pip state if there is no 3rd party
|
||||||
@ -6,40 +6,355 @@ Subject: [PATCH] Do not load pip state if there is no 3rd party
|
|||||||
|
|
||||||
Safe import 3rd party dependency
|
Safe import 3rd party dependency
|
||||||
---
|
---
|
||||||
salt/modules/pip.py | 12 ++++++++++--
|
salt/modules/pip.py | 93 ++++++++++++++++++++++++---------------------
|
||||||
1 file changed, 10 insertions(+), 2 deletions(-)
|
1 file changed, 50 insertions(+), 43 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/modules/pip.py b/salt/modules/pip.py
|
diff --git a/salt/modules/pip.py b/salt/modules/pip.py
|
||||||
index 0a0773a8f4..f19593ed1a 100644
|
index f7c101f6e4..742e0dd48a 100644
|
||||||
--- a/salt/modules/pip.py
|
--- a/salt/modules/pip.py
|
||||||
+++ b/salt/modules/pip.py
|
+++ b/salt/modules/pip.py
|
||||||
@@ -82,7 +82,10 @@ from __future__ import absolute_import, print_function, unicode_literals
|
@@ -1,4 +1,3 @@
|
||||||
# Import python libs
|
-# -*- coding: utf-8 -*-
|
||||||
|
r"""
|
||||||
|
Install Python packages with pip to either the system or a virtualenv
|
||||||
|
|
||||||
|
@@ -77,9 +76,7 @@ of the 2015.5 branch:
|
||||||
|
The issue is described here: https://github.com/saltstack/salt/issues/46163
|
||||||
|
|
||||||
|
"""
|
||||||
|
-from __future__ import absolute_import, print_function, unicode_literals
|
||||||
|
|
||||||
|
-# Import python libs
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
-import pkg_resources
|
import re
|
||||||
|
@@ -89,7 +86,6 @@ import tempfile
|
||||||
|
|
||||||
|
import pkg_resources # pylint: disable=3rd-party-module-not-gated
|
||||||
|
|
||||||
|
-# Import Salt libs
|
||||||
|
import salt.utils.data
|
||||||
|
import salt.utils.files
|
||||||
|
import salt.utils.json
|
||||||
|
@@ -101,6 +97,12 @@ import salt.utils.versions
|
||||||
|
from salt.exceptions import CommandExecutionError, CommandNotFoundError
|
||||||
|
from salt.ext import six
|
||||||
|
|
||||||
+try:
|
+try:
|
||||||
+ import pkg_resources
|
+ import pkg_resources
|
||||||
+except ImportError:
|
+except ImportError:
|
||||||
+ pkg_resources = None
|
+ pkg_resources = None
|
||||||
import re
|
+
|
||||||
import shutil
|
+
|
||||||
import sys
|
# This needs to be named logger so we don't shadow it in pip.install
|
||||||
@@ -121,7 +124,12 @@ def __virtual__():
|
logger = logging.getLogger(__name__) # pylint: disable=C0103
|
||||||
|
|
||||||
|
@@ -118,7 +120,12 @@ def __virtual__():
|
||||||
entire filesystem. If it's not installed in a conventional location, the
|
entire filesystem. If it's not installed in a conventional location, the
|
||||||
user is required to provide the location of pip each time it is used.
|
user is required to provide the location of pip each time it is used.
|
||||||
'''
|
"""
|
||||||
- return 'pip'
|
- return "pip"
|
||||||
+ if pkg_resources is None:
|
+ if pkg_resources is None:
|
||||||
+ ret = False, 'Package dependency "pkg_resource" is missing'
|
+ ret = False, 'Package dependency "pkg_resource" is missing'
|
||||||
+ else:
|
+ else:
|
||||||
+ ret = 'pip'
|
+ ret = "pip"
|
||||||
+
|
+
|
||||||
+ return ret
|
+ return ret
|
||||||
|
|
||||||
|
|
||||||
def _pip_bin_env(cwd, bin_env):
|
def _pip_bin_env(cwd, bin_env):
|
||||||
|
@@ -140,7 +147,7 @@ def _clear_context(bin_env=None):
|
||||||
|
"""
|
||||||
|
contextkey = "pip.version"
|
||||||
|
if bin_env is not None:
|
||||||
|
- contextkey = "{0}.{1}".format(contextkey, bin_env)
|
||||||
|
+ contextkey = "{}.{}".format(contextkey, bin_env)
|
||||||
|
__context__.pop(contextkey, None)
|
||||||
|
|
||||||
|
|
||||||
|
@@ -196,7 +203,7 @@ def _get_pip_bin(bin_env):
|
||||||
|
bin_path,
|
||||||
|
)
|
||||||
|
raise CommandNotFoundError(
|
||||||
|
- "Could not find a pip binary in virtualenv {0}".format(bin_env)
|
||||||
|
+ "Could not find a pip binary in virtualenv {}".format(bin_env)
|
||||||
|
)
|
||||||
|
|
||||||
|
# bin_env is the python or pip binary
|
||||||
|
@@ -209,11 +216,11 @@ def _get_pip_bin(bin_env):
|
||||||
|
return [os.path.normpath(bin_env)]
|
||||||
|
|
||||||
|
raise CommandExecutionError(
|
||||||
|
- "Could not find a pip binary within {0}".format(bin_env)
|
||||||
|
+ "Could not find a pip binary within {}".format(bin_env)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
raise CommandNotFoundError(
|
||||||
|
- "Access denied to {0}, could not find a pip binary".format(bin_env)
|
||||||
|
+ "Access denied to {}, could not find a pip binary".format(bin_env)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@@ -283,7 +290,7 @@ def _resolve_requirements_chain(requirements):
|
||||||
|
|
||||||
|
chain = []
|
||||||
|
|
||||||
|
- if isinstance(requirements, six.string_types):
|
||||||
|
+ if isinstance(requirements, str):
|
||||||
|
requirements = [requirements]
|
||||||
|
|
||||||
|
for req_file in requirements:
|
||||||
|
@@ -300,7 +307,7 @@ def _process_requirements(requirements, cmd, cwd, saltenv, user):
|
||||||
|
cleanup_requirements = []
|
||||||
|
|
||||||
|
if requirements is not None:
|
||||||
|
- if isinstance(requirements, six.string_types):
|
||||||
|
+ if isinstance(requirements, str):
|
||||||
|
requirements = [r.strip() for r in requirements.split(",")]
|
||||||
|
elif not isinstance(requirements, list):
|
||||||
|
raise TypeError("requirements must be a string or list")
|
||||||
|
@@ -314,7 +321,7 @@ def _process_requirements(requirements, cmd, cwd, saltenv, user):
|
||||||
|
if not cached_requirements:
|
||||||
|
ret = {
|
||||||
|
"result": False,
|
||||||
|
- "comment": "pip requirements file '{0}' not found".format(
|
||||||
|
+ "comment": "pip requirements file '{}' not found".format(
|
||||||
|
requirement
|
||||||
|
),
|
||||||
|
}
|
||||||
|
@@ -412,15 +419,15 @@ def _format_env_vars(env_vars):
|
||||||
|
ret = {}
|
||||||
|
if env_vars:
|
||||||
|
if isinstance(env_vars, dict):
|
||||||
|
- for key, val in six.iteritems(env_vars):
|
||||||
|
- if not isinstance(key, six.string_types):
|
||||||
|
+ for key, val in env_vars.items():
|
||||||
|
+ if not isinstance(key, str):
|
||||||
|
key = str(key) # future lint: disable=blacklisted-function
|
||||||
|
- if not isinstance(val, six.string_types):
|
||||||
|
+ if not isinstance(val, str):
|
||||||
|
val = str(val) # future lint: disable=blacklisted-function
|
||||||
|
ret[key] = val
|
||||||
|
else:
|
||||||
|
raise CommandExecutionError(
|
||||||
|
- "env_vars {0} is not a dictionary".format(env_vars)
|
||||||
|
+ "env_vars {} is not a dictionary".format(env_vars)
|
||||||
|
)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
@@ -762,9 +769,9 @@ def install(
|
||||||
|
|
||||||
|
if log:
|
||||||
|
if os.path.isdir(log):
|
||||||
|
- raise IOError("'{0}' is a directory. Use --log path_to_file".format(log))
|
||||||
|
+ raise OSError("'{}' is a directory. Use --log path_to_file".format(log))
|
||||||
|
elif not os.access(log, os.W_OK):
|
||||||
|
- raise IOError("'{0}' is not writeable".format(log))
|
||||||
|
+ raise OSError("'{}' is not writeable".format(log))
|
||||||
|
|
||||||
|
cmd.extend(["--log", log])
|
||||||
|
|
||||||
|
@@ -790,12 +797,12 @@ def install(
|
||||||
|
int(timeout)
|
||||||
|
except ValueError:
|
||||||
|
raise ValueError(
|
||||||
|
- "'{0}' is not a valid timeout, must be an integer".format(timeout)
|
||||||
|
+ "'{}' is not a valid timeout, must be an integer".format(timeout)
|
||||||
|
)
|
||||||
|
cmd.extend(["--timeout", timeout])
|
||||||
|
|
||||||
|
if find_links:
|
||||||
|
- if isinstance(find_links, six.string_types):
|
||||||
|
+ if isinstance(find_links, str):
|
||||||
|
find_links = [l.strip() for l in find_links.split(",")]
|
||||||
|
|
||||||
|
for link in find_links:
|
||||||
|
@@ -803,7 +810,7 @@ def install(
|
||||||
|
salt.utils.url.validate(link, VALID_PROTOS) or os.path.exists(link)
|
||||||
|
):
|
||||||
|
raise CommandExecutionError(
|
||||||
|
- "'{0}' is not a valid URL or path".format(link)
|
||||||
|
+ "'{}' is not a valid URL or path".format(link)
|
||||||
|
)
|
||||||
|
cmd.extend(["--find-links", link])
|
||||||
|
|
||||||
|
@@ -815,13 +822,13 @@ def install(
|
||||||
|
|
||||||
|
if index_url:
|
||||||
|
if not salt.utils.url.validate(index_url, VALID_PROTOS):
|
||||||
|
- raise CommandExecutionError("'{0}' is not a valid URL".format(index_url))
|
||||||
|
+ raise CommandExecutionError("'{}' is not a valid URL".format(index_url))
|
||||||
|
cmd.extend(["--index-url", index_url])
|
||||||
|
|
||||||
|
if extra_index_url:
|
||||||
|
if not salt.utils.url.validate(extra_index_url, VALID_PROTOS):
|
||||||
|
raise CommandExecutionError(
|
||||||
|
- "'{0}' is not a valid URL".format(extra_index_url)
|
||||||
|
+ "'{}' is not a valid URL".format(extra_index_url)
|
||||||
|
)
|
||||||
|
cmd.extend(["--extra-index-url", extra_index_url])
|
||||||
|
|
||||||
|
@@ -836,13 +843,13 @@ def install(
|
||||||
|
" use index_url and/or extra_index_url instead"
|
||||||
|
)
|
||||||
|
|
||||||
|
- if isinstance(mirrors, six.string_types):
|
||||||
|
+ if isinstance(mirrors, str):
|
||||||
|
mirrors = [m.strip() for m in mirrors.split(",")]
|
||||||
|
|
||||||
|
cmd.append("--use-mirrors")
|
||||||
|
for mirror in mirrors:
|
||||||
|
if not mirror.startswith("http://"):
|
||||||
|
- raise CommandExecutionError("'{0}' is not a valid URL".format(mirror))
|
||||||
|
+ raise CommandExecutionError("'{}' is not a valid URL".format(mirror))
|
||||||
|
cmd.extend(["--mirrors", mirror])
|
||||||
|
|
||||||
|
if disable_version_check:
|
||||||
|
@@ -883,7 +890,7 @@ def install(
|
||||||
|
if exists_action.lower() not in ("s", "i", "w", "b"):
|
||||||
|
raise CommandExecutionError(
|
||||||
|
"The exists_action pip option only supports the values "
|
||||||
|
- "s, i, w, and b. '{0}' is not valid.".format(exists_action)
|
||||||
|
+ "s, i, w, and b. '{}' is not valid.".format(exists_action)
|
||||||
|
)
|
||||||
|
cmd.extend(["--exists-action", exists_action])
|
||||||
|
|
||||||
|
@@ -911,14 +918,14 @@ def install(
|
||||||
|
cmd.extend(["--cert", cert])
|
||||||
|
|
||||||
|
if global_options:
|
||||||
|
- if isinstance(global_options, six.string_types):
|
||||||
|
+ if isinstance(global_options, str):
|
||||||
|
global_options = [go.strip() for go in global_options.split(",")]
|
||||||
|
|
||||||
|
for opt in global_options:
|
||||||
|
cmd.extend(["--global-option", opt])
|
||||||
|
|
||||||
|
if install_options:
|
||||||
|
- if isinstance(install_options, six.string_types):
|
||||||
|
+ if isinstance(install_options, str):
|
||||||
|
install_options = [io.strip() for io in install_options.split(",")]
|
||||||
|
|
||||||
|
for opt in install_options:
|
||||||
|
@@ -929,7 +936,7 @@ def install(
|
||||||
|
try:
|
||||||
|
pkgs = [p.strip() for p in pkgs.split(",")]
|
||||||
|
except AttributeError:
|
||||||
|
- pkgs = [p.strip() for p in six.text_type(pkgs).split(",")]
|
||||||
|
+ pkgs = [p.strip() for p in str(pkgs).split(",")]
|
||||||
|
pkgs = salt.utils.data.stringify(salt.utils.data.decode_list(pkgs))
|
||||||
|
|
||||||
|
# It's possible we replaced version-range commas with semicolons so
|
||||||
|
@@ -945,7 +952,7 @@ def install(
|
||||||
|
|
||||||
|
if editable:
|
||||||
|
egg_match = re.compile(r"(?:#|#.*?&)egg=([^&]*)")
|
||||||
|
- if isinstance(editable, six.string_types):
|
||||||
|
+ if isinstance(editable, str):
|
||||||
|
editable = [e.strip() for e in editable.split(",")]
|
||||||
|
|
||||||
|
for entry in editable:
|
||||||
|
@@ -964,14 +971,14 @@ def install(
|
||||||
|
cmd.append("--allow-all-external")
|
||||||
|
|
||||||
|
if allow_external:
|
||||||
|
- if isinstance(allow_external, six.string_types):
|
||||||
|
+ if isinstance(allow_external, str):
|
||||||
|
allow_external = [p.strip() for p in allow_external.split(",")]
|
||||||
|
|
||||||
|
for pkg in allow_external:
|
||||||
|
cmd.extend(["--allow-external", pkg])
|
||||||
|
|
||||||
|
if allow_unverified:
|
||||||
|
- if isinstance(allow_unverified, six.string_types):
|
||||||
|
+ if isinstance(allow_unverified, str):
|
||||||
|
allow_unverified = [p.strip() for p in allow_unverified.split(",")]
|
||||||
|
|
||||||
|
for pkg in allow_unverified:
|
||||||
|
@@ -1106,8 +1113,8 @@ def uninstall(
|
||||||
|
try:
|
||||||
|
# TODO make this check if writeable
|
||||||
|
os.path.exists(log)
|
||||||
|
- except IOError:
|
||||||
|
- raise IOError("'{0}' is not writeable".format(log))
|
||||||
|
+ except OSError:
|
||||||
|
+ raise OSError("'{}' is not writeable".format(log))
|
||||||
|
|
||||||
|
cmd.extend(["--log", log])
|
||||||
|
|
||||||
|
@@ -1133,12 +1140,12 @@ def uninstall(
|
||||||
|
int(timeout)
|
||||||
|
except ValueError:
|
||||||
|
raise ValueError(
|
||||||
|
- "'{0}' is not a valid timeout, must be an integer".format(timeout)
|
||||||
|
+ "'{}' is not a valid timeout, must be an integer".format(timeout)
|
||||||
|
)
|
||||||
|
cmd.extend(["--timeout", timeout])
|
||||||
|
|
||||||
|
if pkgs:
|
||||||
|
- if isinstance(pkgs, six.string_types):
|
||||||
|
+ if isinstance(pkgs, str):
|
||||||
|
pkgs = [p.strip() for p in pkgs.split(",")]
|
||||||
|
if requirements:
|
||||||
|
for requirement in requirements:
|
||||||
|
@@ -1323,7 +1330,7 @@ def version(bin_env=None, cwd=None, user=None):
|
||||||
|
cwd = _pip_bin_env(cwd, bin_env)
|
||||||
|
contextkey = "pip.version"
|
||||||
|
if bin_env is not None:
|
||||||
|
- contextkey = "{0}.{1}".format(contextkey, bin_env)
|
||||||
|
+ contextkey = "{}.{}".format(contextkey, bin_env)
|
||||||
|
|
||||||
|
if contextkey in __context__:
|
||||||
|
return __context__[contextkey]
|
||||||
|
@@ -1402,7 +1409,7 @@ def list_upgrades(bin_env=None, user=None, cwd=None):
|
||||||
|
if match:
|
||||||
|
name, version_ = match.groups()
|
||||||
|
else:
|
||||||
|
- logger.error("Can't parse line '{0}'".format(line))
|
||||||
|
+ logger.error("Can't parse line '{}'".format(line))
|
||||||
|
continue
|
||||||
|
packages[name] = version_
|
||||||
|
|
||||||
|
@@ -1414,7 +1421,7 @@ def list_upgrades(bin_env=None, user=None, cwd=None):
|
||||||
|
raise CommandExecutionError("Invalid JSON", info=result)
|
||||||
|
|
||||||
|
for pkg in pkgs:
|
||||||
|
- packages[pkg["name"]] = "{0} [{1}]".format(
|
||||||
|
+ packages[pkg["name"]] = "{} [{}]".format(
|
||||||
|
pkg["latest_version"], pkg["latest_filetype"]
|
||||||
|
)
|
||||||
|
|
||||||
|
@@ -1602,17 +1609,17 @@ def list_all_versions(
|
||||||
|
"""
|
||||||
|
cwd = _pip_bin_env(cwd, bin_env)
|
||||||
|
cmd = _get_pip_bin(bin_env)
|
||||||
|
- cmd.extend(["install", "{0}==versions".format(pkg)])
|
||||||
|
+ cmd.extend(["install", "{}==versions".format(pkg)])
|
||||||
|
|
||||||
|
if index_url:
|
||||||
|
if not salt.utils.url.validate(index_url, VALID_PROTOS):
|
||||||
|
- raise CommandExecutionError("'{0}' is not a valid URL".format(index_url))
|
||||||
|
+ raise CommandExecutionError("'{}' is not a valid URL".format(index_url))
|
||||||
|
cmd.extend(["--index-url", index_url])
|
||||||
|
|
||||||
|
if extra_index_url:
|
||||||
|
if not salt.utils.url.validate(extra_index_url, VALID_PROTOS):
|
||||||
|
raise CommandExecutionError(
|
||||||
|
- "'{0}' is not a valid URL".format(extra_index_url)
|
||||||
|
+ "'{}' is not a valid URL".format(extra_index_url)
|
||||||
|
)
|
||||||
|
cmd.extend(["--extra-index-url", extra_index_url])
|
||||||
|
|
||||||
|
@@ -1632,7 +1639,7 @@ def list_all_versions(
|
||||||
|
if not include_rc:
|
||||||
|
filtered.append("rc")
|
||||||
|
if filtered:
|
||||||
|
- excludes = re.compile(r"^((?!{0}).)*$".format("|".join(filtered)))
|
||||||
|
+ excludes = re.compile(r"^((?!{}).)*$".format("|".join(filtered)))
|
||||||
|
else:
|
||||||
|
excludes = re.compile(r"")
|
||||||
|
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From 235cca81be2f64ed3feb48ed42bfa3f9196bff39 Mon Sep 17 00:00:00 2001
|
From 5d465a5b392efa1b4df7870161b32e0125efa4af Mon Sep 17 00:00:00 2001
|
||||||
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||||
<psuarezhernandez@suse.com>
|
<psuarezhernandez@suse.com>
|
||||||
Date: Fri, 28 Jun 2019 15:17:56 +0100
|
Date: Fri, 28 Jun 2019 15:17:56 +0100
|
||||||
@ -10,77 +10,315 @@ Move MockTimedProc implementation to tests.support.mock
|
|||||||
|
|
||||||
Add unit test for ansible caller
|
Add unit test for ansible caller
|
||||||
---
|
---
|
||||||
salt/modules/ansiblegate.py | 14 +++++++++---
|
salt/modules/ansiblegate.py | 7 +-
|
||||||
tests/support/mock.py | 31 +++++++++++++++++++++++++
|
tests/support/mock.py | 128 +++++++++-------
|
||||||
tests/unit/modules/test_ansiblegate.py | 41 ++++++++++++++++++++++++++++++++++
|
tests/unit/modules/test_ansiblegate.py | 201 +++++++++++++++++++++++++
|
||||||
tests/unit/modules/test_cmdmod.py | 35 ++---------------------------
|
tests/unit/modules/test_cmdmod.py | 1 +
|
||||||
4 files changed, 85 insertions(+), 36 deletions(-)
|
4 files changed, 280 insertions(+), 57 deletions(-)
|
||||||
|
create mode 100644 tests/unit/modules/test_ansiblegate.py
|
||||||
|
|
||||||
diff --git a/salt/modules/ansiblegate.py b/salt/modules/ansiblegate.py
|
diff --git a/salt/modules/ansiblegate.py b/salt/modules/ansiblegate.py
|
||||||
index 6b903c2b94..8e28fcafa3 100644
|
index 0279a26017..5d4b986ec2 100644
|
||||||
--- a/salt/modules/ansiblegate.py
|
--- a/salt/modules/ansiblegate.py
|
||||||
+++ b/salt/modules/ansiblegate.py
|
+++ b/salt/modules/ansiblegate.py
|
||||||
@@ -147,6 +147,10 @@ class AnsibleModuleCaller(object):
|
@@ -160,6 +160,7 @@ class AnsibleModuleCaller:
|
||||||
:param kwargs: keywords to the module
|
:param kwargs: keywords to the module
|
||||||
:return:
|
:return:
|
||||||
'''
|
"""
|
||||||
+ if six.PY3:
|
+ python_exec = "python3"
|
||||||
+ python_exec = 'python3'
|
|
||||||
+ else:
|
|
||||||
+ python_exec = 'python'
|
|
||||||
|
|
||||||
module = self._resolver.load_module(module)
|
module = self._resolver.load_module(module)
|
||||||
if not hasattr(module, 'main'):
|
if not hasattr(module, "main"):
|
||||||
@@ -162,9 +166,13 @@ class AnsibleModuleCaller(object):
|
@@ -182,9 +183,9 @@ class AnsibleModuleCaller:
|
||||||
["echo", "{0}".format(js_args)],
|
timeout=self.timeout,
|
||||||
stdout=subprocess.PIPE, timeout=self.timeout)
|
)
|
||||||
proc_out.run()
|
proc_out.run()
|
||||||
+ if six.PY3:
|
- proc_out_stdout = salt.utils.stringutils.to_str(proc_out.stdout)
|
||||||
+ proc_out_stdout = proc_out.stdout.decode()
|
+ proc_out_stdout = proc_out.stdout.decode()
|
||||||
+ else:
|
|
||||||
+ proc_out_stdout = proc_out.stdout
|
|
||||||
proc_exc = salt.utils.timed_subprocess.TimedProc(
|
proc_exc = salt.utils.timed_subprocess.TimedProc(
|
||||||
- ['python', module.__file__],
|
- [sys.executable, module.__file__],
|
||||||
- stdin=proc_out.stdout, stdout=subprocess.PIPE, timeout=self.timeout)
|
|
||||||
+ [python_exec, module.__file__],
|
+ [python_exec, module.__file__],
|
||||||
+ stdin=proc_out_stdout, stdout=subprocess.PIPE, timeout=self.timeout)
|
stdin=proc_out_stdout,
|
||||||
proc_exc.run()
|
stdout=subprocess.PIPE,
|
||||||
|
timeout=self.timeout,
|
||||||
try:
|
@@ -298,7 +299,7 @@ def help(module=None, *args):
|
||||||
@@ -263,7 +271,7 @@ def help(module=None, *args):
|
'Available sections on module "{}"'.format(
|
||||||
description = doc.get('description') or ''
|
module.__name__.replace("ansible.modules.", "")
|
||||||
del doc['description']
|
)
|
||||||
ret['Description'] = description
|
- ] = list(doc)
|
||||||
- ret['Available sections on module "{}"'.format(module.__name__.replace('ansible.modules.', ''))] = doc.keys()
|
+ ] = [i for i in doc.keys()]
|
||||||
+ ret['Available sections on module "{}"'.format(module.__name__.replace('ansible.modules.', ''))] = [i for i in doc.keys()]
|
|
||||||
else:
|
else:
|
||||||
for arg in args:
|
for arg in args:
|
||||||
info = doc.get(arg)
|
info = doc.get(arg)
|
||||||
diff --git a/tests/support/mock.py b/tests/support/mock.py
|
diff --git a/tests/support/mock.py b/tests/support/mock.py
|
||||||
index 805a60377c..67ecb4838a 100644
|
index 7ef02e0701..87d052c399 100644
|
||||||
--- a/tests/support/mock.py
|
--- a/tests/support/mock.py
|
||||||
+++ b/tests/support/mock.py
|
+++ b/tests/support/mock.py
|
||||||
@@ -461,6 +461,37 @@ class MockOpen(object):
|
@@ -1,4 +1,3 @@
|
||||||
|
-# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
:codeauthor: Pedro Algarvio (pedro@algarvio.me)
|
||||||
|
|
||||||
|
@@ -14,7 +13,6 @@
|
||||||
|
"""
|
||||||
|
# pylint: disable=unused-import,function-redefined,blacklisted-module,blacklisted-external-module
|
||||||
|
|
||||||
|
-from __future__ import absolute_import
|
||||||
|
|
||||||
|
import collections
|
||||||
|
import copy
|
||||||
|
@@ -42,8 +40,6 @@ from mock import (
|
||||||
|
patch,
|
||||||
|
sentinel,
|
||||||
|
)
|
||||||
|
-
|
||||||
|
-# Import salt libs
|
||||||
|
from salt.ext import six
|
||||||
|
|
||||||
|
# pylint: disable=no-name-in-module,no-member
|
||||||
|
@@ -57,7 +53,7 @@ if sys.version_info < (3, 6) and __mock_version < (2,):
|
||||||
|
raise ImportError("Please install mock>=2.0.0")
|
||||||
|
|
||||||
|
|
||||||
|
-class MockFH(object):
|
||||||
|
+class MockFH:
|
||||||
|
def __init__(self, filename, read_data, *args, **kwargs):
|
||||||
|
self.filename = filename
|
||||||
|
self.read_data = read_data
|
||||||
|
@@ -89,7 +85,7 @@ class MockFH(object):
|
||||||
|
"""
|
||||||
|
# Newline will always be a bytestring on PY2 because mock_open will have
|
||||||
|
# normalized it to one.
|
||||||
|
- newline = b"\n" if isinstance(read_data, six.binary_type) else "\n"
|
||||||
|
+ newline = b"\n" if isinstance(read_data, bytes) else "\n"
|
||||||
|
|
||||||
|
read_data = [line + newline for line in read_data.split(newline)]
|
||||||
|
|
||||||
|
@@ -103,8 +99,7 @@ class MockFH(object):
|
||||||
|
# newline that we added in the list comprehension.
|
||||||
|
read_data[-1] = read_data[-1][:-1]
|
||||||
|
|
||||||
|
- for line in read_data:
|
||||||
|
- yield line
|
||||||
|
+ yield from read_data
|
||||||
|
|
||||||
|
@property
|
||||||
|
def write_calls(self):
|
||||||
|
@@ -126,18 +121,18 @@ class MockFH(object):
|
||||||
|
def __check_read_data(self):
|
||||||
|
if not self.__read_data_ok:
|
||||||
|
if self.binary_mode:
|
||||||
|
- if not isinstance(self.read_data, six.binary_type):
|
||||||
|
+ if not isinstance(self.read_data, bytes):
|
||||||
|
raise TypeError(
|
||||||
|
- "{0} opened in binary mode, expected read_data to be "
|
||||||
|
- "bytes, not {1}".format(
|
||||||
|
+ "{} opened in binary mode, expected read_data to be "
|
||||||
|
+ "bytes, not {}".format(
|
||||||
|
self.filename, type(self.read_data).__name__
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
if not isinstance(self.read_data, str):
|
||||||
|
raise TypeError(
|
||||||
|
- "{0} opened in non-binary mode, expected read_data to "
|
||||||
|
- "be str, not {1}".format(
|
||||||
|
+ "{} opened in non-binary mode, expected read_data to "
|
||||||
|
+ "be str, not {}".format(
|
||||||
|
self.filename, type(self.read_data).__name__
|
||||||
|
)
|
||||||
|
)
|
||||||
|
@@ -147,8 +142,8 @@ class MockFH(object):
|
||||||
|
def _read(self, size=0):
|
||||||
|
self.__check_read_data()
|
||||||
|
if not self.read_mode:
|
||||||
|
- raise IOError("File not open for reading")
|
||||||
|
- if not isinstance(size, six.integer_types) or size < 0:
|
||||||
|
+ raise OSError("File not open for reading")
|
||||||
|
+ if not isinstance(size, int) or size < 0:
|
||||||
|
raise TypeError("a positive integer is required")
|
||||||
|
|
||||||
|
joined = self.empty_string.join(self.read_data_iter)
|
||||||
|
@@ -169,7 +164,7 @@ class MockFH(object):
|
||||||
|
# TODO: Implement "size" argument
|
||||||
|
self.__check_read_data()
|
||||||
|
if not self.read_mode:
|
||||||
|
- raise IOError("File not open for reading")
|
||||||
|
+ raise OSError("File not open for reading")
|
||||||
|
ret = list(self.read_data_iter)
|
||||||
|
self.__loc += sum(len(x) for x in ret)
|
||||||
|
return ret
|
||||||
|
@@ -178,7 +173,7 @@ class MockFH(object):
|
||||||
|
# TODO: Implement "size" argument
|
||||||
|
self.__check_read_data()
|
||||||
|
if not self.read_mode:
|
||||||
|
- raise IOError("File not open for reading")
|
||||||
|
+ raise OSError("File not open for reading")
|
||||||
|
try:
|
||||||
|
ret = next(self.read_data_iter)
|
||||||
|
self.__loc += len(ret)
|
||||||
|
@@ -189,7 +184,7 @@ class MockFH(object):
|
||||||
|
def __iter__(self):
|
||||||
|
self.__check_read_data()
|
||||||
|
if not self.read_mode:
|
||||||
|
- raise IOError("File not open for reading")
|
||||||
|
+ raise OSError("File not open for reading")
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
ret = next(self.read_data_iter)
|
||||||
|
@@ -200,30 +195,22 @@ class MockFH(object):
|
||||||
|
|
||||||
|
def _write(self, content):
|
||||||
|
if not self.write_mode:
|
||||||
|
- raise IOError("File not open for writing")
|
||||||
|
- if six.PY2:
|
||||||
|
- if isinstance(content, six.text_type):
|
||||||
|
- # encoding intentionally not specified to force a
|
||||||
|
- # UnicodeEncodeError when non-ascii unicode type is passed
|
||||||
|
- content.encode()
|
||||||
|
- else:
|
||||||
|
- content_type = type(content)
|
||||||
|
- if self.binary_mode and content_type is not bytes:
|
||||||
|
- raise TypeError(
|
||||||
|
- "a bytes-like object is required, not '{0}'".format(
|
||||||
|
- content_type.__name__
|
||||||
|
- )
|
||||||
|
- )
|
||||||
|
- elif not self.binary_mode and content_type is not str:
|
||||||
|
- raise TypeError(
|
||||||
|
- "write() argument must be str, not {0}".format(
|
||||||
|
- content_type.__name__
|
||||||
|
- )
|
||||||
|
+ raise OSError("File not open for writing")
|
||||||
|
+ content_type = type(content)
|
||||||
|
+ if self.binary_mode and content_type is not bytes:
|
||||||
|
+ raise TypeError(
|
||||||
|
+ "a bytes-like object is required, not '{}'".format(
|
||||||
|
+ content_type.__name__
|
||||||
|
)
|
||||||
|
+ )
|
||||||
|
+ elif not self.binary_mode and content_type is not str:
|
||||||
|
+ raise TypeError(
|
||||||
|
+ "write() argument must be str, not {}".format(content_type.__name__)
|
||||||
|
+ )
|
||||||
|
|
||||||
|
def _writelines(self, lines):
|
||||||
|
if not self.write_mode:
|
||||||
|
- raise IOError("File not open for writing")
|
||||||
|
+ raise OSError("File not open for writing")
|
||||||
|
for line in lines:
|
||||||
|
self._write(line)
|
||||||
|
|
||||||
|
@@ -234,26 +221,24 @@ class MockFH(object):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
-class MockCall(object):
|
||||||
|
+class MockCall:
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
self.args = args
|
||||||
|
self.kwargs = kwargs
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
# future lint: disable=blacklisted-function
|
||||||
|
- ret = str("MockCall(")
|
||||||
|
+ ret = "MockCall("
|
||||||
|
for arg in self.args:
|
||||||
|
- ret += repr(arg) + str(", ")
|
||||||
|
+ ret += repr(arg) + ", "
|
||||||
|
if not self.kwargs:
|
||||||
|
if self.args:
|
||||||
|
# Remove trailing ', '
|
||||||
|
ret = ret[:-2]
|
||||||
|
else:
|
||||||
|
- for key, val in six.iteritems(self.kwargs):
|
||||||
|
- ret += str("{0}={1}").format(
|
||||||
|
- salt.utils.stringutils.to_str(key), repr(val)
|
||||||
|
- )
|
||||||
|
- ret += str(")")
|
||||||
|
+ for key, val in self.kwargs.items():
|
||||||
|
+ ret += "{}={}".format(salt.utils.stringutils.to_str(key), repr(val))
|
||||||
|
+ ret += ")"
|
||||||
|
return ret
|
||||||
|
# future lint: enable=blacklisted-function
|
||||||
|
|
||||||
|
@@ -264,7 +249,7 @@ class MockCall(object):
|
||||||
|
return self.args == other.args and self.kwargs == other.kwargs
|
||||||
|
|
||||||
|
|
||||||
|
-class MockOpen(object):
|
||||||
|
+class MockOpen:
|
||||||
|
r'''
|
||||||
|
This class can be used to mock the use of ``open()``.
|
||||||
|
|
||||||
|
@@ -379,7 +364,7 @@ class MockOpen(object):
|
||||||
|
# .__class__() used here to preserve the dict class in the event that
|
||||||
|
# an OrderedDict was used.
|
||||||
|
new_read_data = read_data.__class__()
|
||||||
|
- for key, val in six.iteritems(read_data):
|
||||||
|
+ for key, val in read_data.items():
|
||||||
|
try:
|
||||||
|
val = salt.utils.data.decode(val, to_str=True)
|
||||||
|
except TypeError:
|
||||||
|
@@ -424,7 +409,7 @@ class MockOpen(object):
|
||||||
|
except IndexError:
|
||||||
|
# We've run out of file contents, abort!
|
||||||
|
raise RuntimeError(
|
||||||
|
- "File matching expression '{0}' opened more times than "
|
||||||
|
+ "File matching expression '{}' opened more times than "
|
||||||
|
"expected".format(matched_pattern)
|
||||||
|
)
|
||||||
|
|
||||||
|
@@ -443,7 +428,7 @@ class MockOpen(object):
|
||||||
|
except KeyError:
|
||||||
|
# No matching glob in read_data, treat this as a file that does
|
||||||
|
# not exist and raise the appropriate exception.
|
||||||
|
- raise IOError(errno.ENOENT, "No such file or directory", name)
|
||||||
|
+ raise OSError(errno.ENOENT, "No such file or directory", name)
|
||||||
|
|
||||||
|
def write_calls(self, path=None):
|
||||||
|
"""
|
||||||
|
@@ -451,7 +436,7 @@ class MockOpen(object):
|
||||||
|
the results to files matching a given pattern.
|
||||||
|
"""
|
||||||
|
ret = []
|
||||||
|
- for filename, handles in six.iteritems(self.filehandles):
|
||||||
|
+ for filename, handles in self.filehandles.items():
|
||||||
|
if path is None or fnmatch.fnmatch(filename, path):
|
||||||
|
for fh_ in handles:
|
||||||
|
ret.extend(fh_.write_calls)
|
||||||
|
@@ -463,19 +448,54 @@ class MockOpen(object):
|
||||||
|
narrow the results to files matching a given pattern.
|
||||||
|
"""
|
||||||
|
ret = []
|
||||||
|
- for filename, handles in six.iteritems(self.filehandles):
|
||||||
|
+ for filename, handles in self.filehandles.items():
|
||||||
|
if path is None or fnmatch.fnmatch(filename, path):
|
||||||
|
for fh_ in handles:
|
||||||
ret.extend(fh_.writelines_calls)
|
ret.extend(fh_.writelines_calls)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
+class MockTimedProc(object):
|
|
||||||
+ '''
|
-class MockTimedProc(object):
|
||||||
|
+class MockTimedProc:
|
||||||
|
+ """
|
||||||
+ Class used as a stand-in for salt.utils.timed_subprocess.TimedProc
|
+ Class used as a stand-in for salt.utils.timed_subprocess.TimedProc
|
||||||
+ '''
|
+ """
|
||||||
+ class _Process(object):
|
+
|
||||||
+ '''
|
+ class _Process:
|
||||||
|
+ """
|
||||||
+ Used to provide a dummy "process" attribute
|
+ Used to provide a dummy "process" attribute
|
||||||
+ '''
|
+ """
|
||||||
|
+
|
||||||
+ def __init__(self, returncode=0, pid=12345):
|
+ def __init__(self, returncode=0, pid=12345):
|
||||||
+ self.returncode = returncode
|
+ self.returncode = returncode
|
||||||
+ self.pid = pid
|
+ self.pid = pid
|
||||||
+
|
+
|
||||||
+ def __init__(self, stdout=None, stderr=None, returncode=0, pid=12345):
|
+ def __init__(self, stdout=None, stderr=None, returncode=0, pid=12345):
|
||||||
+ if stdout is not None and not isinstance(stdout, bytes):
|
+ if stdout is not None and not isinstance(stdout, bytes):
|
||||||
+ raise TypeError('Must pass stdout to MockTimedProc as bytes')
|
+ raise TypeError("Must pass stdout to MockTimedProc as bytes")
|
||||||
+ if stderr is not None and not isinstance(stderr, bytes):
|
+ if stderr is not None and not isinstance(stderr, bytes):
|
||||||
+ raise TypeError('Must pass stderr to MockTimedProc as bytes')
|
+ raise TypeError("Must pass stderr to MockTimedProc as bytes")
|
||||||
+ self._stdout = stdout
|
+ self._stdout = stdout
|
||||||
+ self._stderr = stderr
|
+ self._stderr = stderr
|
||||||
+ self.process = self._Process(returncode=returncode, pid=pid)
|
+ self.process = self._Process(returncode=returncode, pid=pid)
|
||||||
@ -95,124 +333,238 @@ index 805a60377c..67ecb4838a 100644
|
|||||||
+ @property
|
+ @property
|
||||||
+ def stderr(self):
|
+ def stderr(self):
|
||||||
+ return self._stderr
|
+ return self._stderr
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+class MockTimedProc:
|
||||||
|
"""
|
||||||
|
Class used as a stand-in for salt.utils.timed_subprocess.TimedProc
|
||||||
|
"""
|
||||||
|
|
||||||
# reimplement mock_open to support multiple filehandles
|
- class _Process(object):
|
||||||
mock_open = MockOpen
|
+ class _Process:
|
||||||
|
"""
|
||||||
|
Used to provide a dummy "process" attribute
|
||||||
|
"""
|
||||||
diff --git a/tests/unit/modules/test_ansiblegate.py b/tests/unit/modules/test_ansiblegate.py
|
diff --git a/tests/unit/modules/test_ansiblegate.py b/tests/unit/modules/test_ansiblegate.py
|
||||||
index 5613a0e79b..b7b43efda4 100644
|
new file mode 100644
|
||||||
--- a/tests/unit/modules/test_ansiblegate.py
|
index 0000000000..61aad44b5c
|
||||||
|
--- /dev/null
|
||||||
+++ b/tests/unit/modules/test_ansiblegate.py
|
+++ b/tests/unit/modules/test_ansiblegate.py
|
||||||
@@ -29,11 +29,13 @@ from tests.support.unit import TestCase, skipIf
|
@@ -0,0 +1,201 @@
|
||||||
from tests.support.mock import (
|
+#
|
||||||
patch,
|
+# Author: Bo Maryniuk <bo@suse.de>
|
||||||
MagicMock,
|
+#
|
||||||
+ MockTimedProc,
|
+# Copyright 2017 SUSE LLC
|
||||||
)
|
+# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
+# you may not use this file except in compliance with the License.
|
||||||
import salt.modules.ansiblegate as ansible
|
+# You may obtain a copy of the License at
|
||||||
import salt.utils.platform
|
+#
|
||||||
from salt.exceptions import LoaderError
|
+# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
+#
|
||||||
|
+# Unless required by applicable law or agreed to in writing, software
|
||||||
|
+# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
+# See the License for the specific language governing permissions and
|
||||||
|
+# limitations under the License.
|
||||||
|
+
|
||||||
|
+import os
|
||||||
|
+
|
||||||
|
+import salt.modules.ansiblegate as ansible
|
||||||
|
+import salt.utils.platform
|
||||||
|
+from salt.exceptions import LoaderError
|
||||||
+from salt.ext import six
|
+from salt.ext import six
|
||||||
|
+from tests.support.mixins import LoaderModuleMockMixin
|
||||||
|
+from tests.support.mock import MagicMock, MockTimedProc, patch
|
||||||
@skipIf(NO_PYTEST, False)
|
+from tests.support.unit import TestCase, skipIf
|
||||||
@@ -134,3 +136,42 @@ description:
|
+
|
||||||
'''
|
+try:
|
||||||
with patch('salt.modules.ansiblegate.ansible', None):
|
+ import pytest
|
||||||
assert ansible.__virtual__() == 'ansible'
|
+except ImportError as import_error:
|
||||||
|
+ pytest = None
|
||||||
|
+NO_PYTEST = not bool(pytest)
|
||||||
|
+
|
||||||
|
+
|
||||||
|
+@skipIf(NO_PYTEST, False)
|
||||||
|
+@skipIf(salt.utils.platform.is_windows(), "Not supported on Windows")
|
||||||
|
+class AnsiblegateTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
|
+ def setUp(self):
|
||||||
|
+ self.resolver = ansible.AnsibleModuleResolver({})
|
||||||
|
+ self.resolver._modules_map = {
|
||||||
|
+ "one.two.three": os.sep + os.path.join("one", "two", "three.py"),
|
||||||
|
+ "four.five.six": os.sep + os.path.join("four", "five", "six.py"),
|
||||||
|
+ "three.six.one": os.sep + os.path.join("three", "six", "one.py"),
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ def tearDown(self):
|
||||||
|
+ self.resolver = None
|
||||||
|
+
|
||||||
|
+ def setup_loader_modules(self):
|
||||||
|
+ return {ansible: {}}
|
||||||
|
+
|
||||||
|
+ def test_ansible_module_help(self):
|
||||||
|
+ """
|
||||||
|
+ Test help extraction from the module
|
||||||
|
+ :return:
|
||||||
|
+ """
|
||||||
|
+
|
||||||
|
+ class Module:
|
||||||
|
+ """
|
||||||
|
+ An ansible module mock.
|
||||||
|
+ """
|
||||||
|
+
|
||||||
|
+ __name__ = "foo"
|
||||||
|
+ DOCUMENTATION = """
|
||||||
|
+---
|
||||||
|
+one:
|
||||||
|
+ text here
|
||||||
|
+---
|
||||||
|
+two:
|
||||||
|
+ text here
|
||||||
|
+description:
|
||||||
|
+ describe the second part
|
||||||
|
+ """
|
||||||
|
+
|
||||||
|
+ with patch.object(ansible, "_resolver", self.resolver), patch.object(
|
||||||
|
+ ansible._resolver, "load_module", MagicMock(return_value=Module())
|
||||||
|
+ ):
|
||||||
|
+ ret = ansible.help("dummy")
|
||||||
|
+ assert sorted(
|
||||||
|
+ ret.get('Available sections on module "{}"'.format(Module().__name__))
|
||||||
|
+ ) == ["one", "two"]
|
||||||
|
+ assert ret.get("Description") == "describe the second part"
|
||||||
|
+
|
||||||
|
+ def test_module_resolver_modlist(self):
|
||||||
|
+ """
|
||||||
|
+ Test Ansible resolver modules list.
|
||||||
|
+ :return:
|
||||||
|
+ """
|
||||||
|
+ assert self.resolver.get_modules_list() == [
|
||||||
|
+ "four.five.six",
|
||||||
|
+ "one.two.three",
|
||||||
|
+ "three.six.one",
|
||||||
|
+ ]
|
||||||
|
+ for ptr in ["five", "fi", "ve"]:
|
||||||
|
+ assert self.resolver.get_modules_list(ptr) == ["four.five.six"]
|
||||||
|
+ for ptr in ["si", "ix", "six"]:
|
||||||
|
+ assert self.resolver.get_modules_list(ptr) == [
|
||||||
|
+ "four.five.six",
|
||||||
|
+ "three.six.one",
|
||||||
|
+ ]
|
||||||
|
+ assert self.resolver.get_modules_list("one") == [
|
||||||
|
+ "one.two.three",
|
||||||
|
+ "three.six.one",
|
||||||
|
+ ]
|
||||||
|
+ assert self.resolver.get_modules_list("one.two") == ["one.two.three"]
|
||||||
|
+ assert self.resolver.get_modules_list("four") == ["four.five.six"]
|
||||||
|
+
|
||||||
|
+ def test_resolver_module_loader_failure(self):
|
||||||
|
+ """
|
||||||
|
+ Test Ansible module loader.
|
||||||
|
+ :return:
|
||||||
|
+ """
|
||||||
|
+ mod = "four.five.six"
|
||||||
|
+ with pytest.raises(ImportError) as import_error:
|
||||||
|
+ self.resolver.load_module(mod)
|
||||||
|
+
|
||||||
|
+ mod = "i.even.do.not.exist.at.all"
|
||||||
|
+ with pytest.raises(LoaderError) as loader_error:
|
||||||
|
+ self.resolver.load_module(mod)
|
||||||
|
+
|
||||||
|
+ def test_resolver_module_loader(self):
|
||||||
|
+ """
|
||||||
|
+ Test Ansible module loader.
|
||||||
|
+ :return:
|
||||||
|
+ """
|
||||||
|
+ with patch("salt.modules.ansiblegate.importlib", MagicMock()), patch(
|
||||||
|
+ "salt.modules.ansiblegate.importlib.import_module", lambda x: x
|
||||||
|
+ ):
|
||||||
|
+ assert (
|
||||||
|
+ self.resolver.load_module("four.five.six")
|
||||||
|
+ == "ansible.modules.four.five.six"
|
||||||
|
+ )
|
||||||
|
+
|
||||||
|
+ def test_resolver_module_loader_import_failure(self):
|
||||||
|
+ """
|
||||||
|
+ Test Ansible module loader failure.
|
||||||
|
+ :return:
|
||||||
|
+ """
|
||||||
|
+ with patch("salt.modules.ansiblegate.importlib", MagicMock()), patch(
|
||||||
|
+ "salt.modules.ansiblegate.importlib.import_module", lambda x: x
|
||||||
|
+ ):
|
||||||
|
+ with pytest.raises(LoaderError) as loader_error:
|
||||||
|
+ self.resolver.load_module("something.strange")
|
||||||
|
+
|
||||||
|
+ def test_virtual_function(self):
|
||||||
|
+ """
|
||||||
|
+ Test Ansible module __virtual__ when ansible is not installed on the minion.
|
||||||
|
+ :return:
|
||||||
|
+ """
|
||||||
|
+ with patch("salt.modules.ansiblegate.ansible", None):
|
||||||
|
+ assert ansible.__virtual__() == "ansible"
|
||||||
+
|
+
|
||||||
+ def test_ansible_module_call(self):
|
+ def test_ansible_module_call(self):
|
||||||
+ '''
|
+ """
|
||||||
+ Test Ansible module call from ansible gate module
|
+ Test Ansible module call from ansible gate module
|
||||||
+
|
+
|
||||||
+ :return:
|
+ :return:
|
||||||
+ '''
|
+ """
|
||||||
+
|
+
|
||||||
+ class Module(object):
|
+ class Module:
|
||||||
+ '''
|
+ """
|
||||||
+ An ansible module mock.
|
+ An ansible module mock.
|
||||||
+ '''
|
+ """
|
||||||
+ __name__ = 'one.two.three'
|
+
|
||||||
+ __file__ = 'foofile'
|
+ __name__ = "one.two.three"
|
||||||
|
+ __file__ = "foofile"
|
||||||
+
|
+
|
||||||
+ def main():
|
+ def main():
|
||||||
+ pass
|
+ pass
|
||||||
+
|
+
|
||||||
+ ANSIBLE_MODULE_ARGS = '{"ANSIBLE_MODULE_ARGS": ["arg_1", {"kwarg1": "foobar"}]}'
|
+ ANSIBLE_MODULE_ARGS = '{"ANSIBLE_MODULE_ARGS": ["arg_1", {"kwarg1": "foobar"}]}'
|
||||||
+
|
+
|
||||||
+ proc = MagicMock(side_effect=[
|
+ proc = MagicMock(
|
||||||
+ MockTimedProc(
|
+ side_effect=[
|
||||||
+ stdout=ANSIBLE_MODULE_ARGS.encode(),
|
+ MockTimedProc(stdout=ANSIBLE_MODULE_ARGS.encode(), stderr=None),
|
||||||
+ stderr=None),
|
+ MockTimedProc(stdout=b'{"completed": true}', stderr=None),
|
||||||
+ MockTimedProc(stdout='{"completed": true}'.encode(), stderr=None)
|
+ ]
|
||||||
+ ])
|
+ )
|
||||||
+
|
+
|
||||||
+ with patch.object(ansible, '_resolver', self.resolver), \
|
+ with patch.object(ansible, "_resolver", self.resolver), patch.object(
|
||||||
+ patch.object(ansible._resolver, 'load_module', MagicMock(return_value=Module())):
|
+ ansible._resolver, "load_module", MagicMock(return_value=Module())
|
||||||
|
+ ):
|
||||||
+ _ansible_module_caller = ansible.AnsibleModuleCaller(ansible._resolver)
|
+ _ansible_module_caller = ansible.AnsibleModuleCaller(ansible._resolver)
|
||||||
+ with patch('salt.utils.timed_subprocess.TimedProc', proc):
|
+ with patch("salt.utils.timed_subprocess.TimedProc", proc):
|
||||||
+ ret = _ansible_module_caller.call("one.two.three", "arg_1", kwarg1="foobar")
|
+ ret = _ansible_module_caller.call(
|
||||||
+ if six.PY3:
|
+ "one.two.three", "arg_1", kwarg1="foobar"
|
||||||
+ proc.assert_any_call(['echo', '{"ANSIBLE_MODULE_ARGS": {"kwarg1": "foobar", "_raw_params": "arg_1"}}'], stdout=-1, timeout=1200)
|
+ )
|
||||||
+ proc.assert_any_call(['python3', 'foofile'], stdin=ANSIBLE_MODULE_ARGS, stdout=-1, timeout=1200)
|
+ proc.assert_any_call(
|
||||||
+ else:
|
+ [
|
||||||
+ proc.assert_any_call(['echo', '{"ANSIBLE_MODULE_ARGS": {"_raw_params": "arg_1", "kwarg1": "foobar"}}'], stdout=-1, timeout=1200)
|
+ "echo",
|
||||||
+ proc.assert_any_call(['python', 'foofile'], stdin=ANSIBLE_MODULE_ARGS, stdout=-1, timeout=1200)
|
+ '{"ANSIBLE_MODULE_ARGS": {"kwarg1": "foobar", "_raw_params": "arg_1"}}',
|
||||||
|
+ ],
|
||||||
|
+ stdout=-1,
|
||||||
|
+ timeout=1200,
|
||||||
|
+ )
|
||||||
|
+ proc.assert_any_call(
|
||||||
|
+ ["python3", "foofile"],
|
||||||
|
+ stdin=ANSIBLE_MODULE_ARGS,
|
||||||
|
+ stdout=-1,
|
||||||
|
+ timeout=1200,
|
||||||
|
+ )
|
||||||
+ assert ret == {"completed": True, "timeout": 1200}
|
+ assert ret == {"completed": True, "timeout": 1200}
|
||||||
diff --git a/tests/unit/modules/test_cmdmod.py b/tests/unit/modules/test_cmdmod.py
|
diff --git a/tests/unit/modules/test_cmdmod.py b/tests/unit/modules/test_cmdmod.py
|
||||||
index 8170a56b4e..f8fba59294 100644
|
index 15b97f8568..f3348bc379 100644
|
||||||
--- a/tests/unit/modules/test_cmdmod.py
|
--- a/tests/unit/modules/test_cmdmod.py
|
||||||
+++ b/tests/unit/modules/test_cmdmod.py
|
+++ b/tests/unit/modules/test_cmdmod.py
|
||||||
@@ -26,6 +26,7 @@ from tests.support.helpers import TstSuiteLoggingHandler
|
@@ -24,6 +24,7 @@ DEFAULT_SHELL = "foo/bar"
|
||||||
from tests.support.mock import (
|
MOCK_SHELL_FILE = "# List of acceptable shells\n" "\n" "/bin/bash\n"
|
||||||
mock_open,
|
|
||||||
Mock,
|
|
||||||
+ MockTimedProc,
|
|
||||||
MagicMock,
|
|
||||||
patch
|
|
||||||
)
|
|
||||||
@@ -36,39 +37,7 @@ MOCK_SHELL_FILE = '# List of acceptable shells\n' \
|
|
||||||
'/bin/bash\n'
|
|
||||||
|
|
||||||
|
|
||||||
-class MockTimedProc(object):
|
|
||||||
- '''
|
|
||||||
- Class used as a stand-in for salt.utils.timed_subprocess.TimedProc
|
|
||||||
- '''
|
|
||||||
- class _Process(object):
|
|
||||||
- '''
|
|
||||||
- Used to provide a dummy "process" attribute
|
|
||||||
- '''
|
|
||||||
- def __init__(self, returncode=0, pid=12345):
|
|
||||||
- self.returncode = returncode
|
|
||||||
- self.pid = pid
|
|
||||||
-
|
|
||||||
- def __init__(self, stdout=None, stderr=None, returncode=0, pid=12345):
|
|
||||||
- if stdout is not None and not isinstance(stdout, bytes):
|
|
||||||
- raise TypeError('Must pass stdout to MockTimedProc as bytes')
|
|
||||||
- if stderr is not None and not isinstance(stderr, bytes):
|
|
||||||
- raise TypeError('Must pass stderr to MockTimedProc as bytes')
|
|
||||||
- self._stdout = stdout
|
|
||||||
- self._stderr = stderr
|
|
||||||
- self.process = self._Process(returncode=returncode, pid=pid)
|
|
||||||
-
|
|
||||||
- def run(self):
|
|
||||||
- pass
|
|
||||||
-
|
|
||||||
- @property
|
|
||||||
- def stdout(self):
|
|
||||||
- return self._stdout
|
|
||||||
-
|
|
||||||
- @property
|
|
||||||
- def stderr(self):
|
|
||||||
- return self._stderr
|
|
||||||
-
|
|
||||||
-
|
|
||||||
+@skipIf(NO_MOCK, NO_MOCK_REASON)
|
+@skipIf(NO_MOCK, NO_MOCK_REASON)
|
||||||
class CMDMODTestCase(TestCase, LoaderModuleMockMixin):
|
class CMDMODTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
'''
|
"""
|
||||||
Unit tests for the salt.modules.cmdmod module
|
Unit tests for the salt.modules.cmdmod module
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From b651c2cd8b719a72e66b63afd9061739624763e1 Mon Sep 17 00:00:00 2001
|
From 81d0105b0c0464c375070ffbc863a020a67e7965 Mon Sep 17 00:00:00 2001
|
||||||
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||||
<psuarezhernandez@suse.com>
|
<psuarezhernandez@suse.com>
|
||||||
Date: Wed, 26 Aug 2020 10:24:58 +0100
|
Date: Wed, 26 Aug 2020 10:24:58 +0100
|
||||||
@ -10,18 +10,18 @@ Subject: [PATCH] Do not raise StreamClosedError traceback but only log
|
|||||||
1 file changed, 1 deletion(-)
|
1 file changed, 1 deletion(-)
|
||||||
|
|
||||||
diff --git a/salt/transport/ipc.py b/salt/transport/ipc.py
|
diff --git a/salt/transport/ipc.py b/salt/transport/ipc.py
|
||||||
index 33ee3d4182..624eca5a9c 100644
|
index f411907da2..5ff0956dde 100644
|
||||||
--- a/salt/transport/ipc.py
|
--- a/salt/transport/ipc.py
|
||||||
+++ b/salt/transport/ipc.py
|
+++ b/salt/transport/ipc.py
|
||||||
@@ -667,7 +667,6 @@ class IPCMessageSubscriber(IPCClient):
|
@@ -688,7 +688,6 @@ class IPCMessageSubscriber(IPCClient):
|
||||||
except StreamClosedError as exc:
|
except StreamClosedError as exc:
|
||||||
log.trace('Subscriber disconnected from IPC %s', self.socket_path)
|
log.trace("Subscriber disconnected from IPC %s", self.socket_path)
|
||||||
self._read_stream_future = None
|
self._read_stream_future = None
|
||||||
- exc_to_raise = exc
|
- exc_to_raise = exc
|
||||||
except Exception as exc: # pylint: disable=broad-except
|
except Exception as exc: # pylint: disable=broad-except
|
||||||
log.error('Exception occurred in Subscriber while handling stream: %s', exc)
|
log.error("Exception occurred in Subscriber while handling stream: %s", exc)
|
||||||
self._read_stream_future = None
|
self._read_stream_future = None
|
||||||
--
|
--
|
||||||
2.28.0
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
From 7e9adda8dfd53050756d0ac0cf64570b76ce7365 Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
|
||||||
<psuarezhernandez@suse.com>
|
|
||||||
Date: Wed, 13 Mar 2019 16:14:07 +0000
|
|
||||||
Subject: [PATCH] Do not report patches as installed when not all the
|
|
||||||
related packages are installed (bsc#1128061)
|
|
||||||
|
|
||||||
Co-authored-by: Mihai Dinca <mdinca@suse.de>
|
|
||||||
---
|
|
||||||
salt/modules/yumpkg.py | 4 ++++
|
|
||||||
1 file changed, 4 insertions(+)
|
|
||||||
|
|
||||||
diff --git a/salt/modules/yumpkg.py b/salt/modules/yumpkg.py
|
|
||||||
index b1257d0de0..3ddf989511 100644
|
|
||||||
--- a/salt/modules/yumpkg.py
|
|
||||||
+++ b/salt/modules/yumpkg.py
|
|
||||||
@@ -3220,7 +3220,11 @@ def _get_patches(installed_only=False):
|
|
||||||
for line in salt.utils.itertools.split(ret, os.linesep):
|
|
||||||
inst, advisory_id, sev, pkg = re.match(r'([i|\s]) ([^\s]+) +([^\s]+) +([^\s]+)',
|
|
||||||
line).groups()
|
|
||||||
+<<<<<<< HEAD
|
|
||||||
if advisory_id not in patches:
|
|
||||||
+=======
|
|
||||||
+ if not advisory_id in patches:
|
|
||||||
+>>>>>>> Do not report patches as installed when not all the related packages are installed (bsc#1128061)
|
|
||||||
patches[advisory_id] = {
|
|
||||||
'installed': True if inst == 'i' else False,
|
|
||||||
'summary': [pkg]
|
|
||||||
--
|
|
||||||
2.16.4
|
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
From c1f5e6332bf025394b81868bf1edc6ae44944a7c Mon Sep 17 00:00:00 2001
|
From 421988aea296ced1f8c63cfa4b517b25eedfb00c Mon Sep 17 00:00:00 2001
|
||||||
From: =?UTF-8?q?C=C3=A9dric=20Bosdonnat?= <cbosdonnat@suse.com>
|
From: =?UTF-8?q?C=C3=A9dric=20Bosdonnat?= <cbosdonnat@suse.com>
|
||||||
Date: Tue, 29 Jan 2019 09:44:03 +0100
|
Date: Tue, 29 Jan 2019 09:44:03 +0100
|
||||||
Subject: [PATCH] Don't call zypper with more than one --no-refresh
|
Subject: [PATCH] Don't call zypper with more than one --no-refresh
|
||||||
@ -11,32 +11,32 @@ passed twice. Make sure we won't hit this.
|
|||||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
2 files changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py
|
diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py
|
||||||
index 04a6a6872d..37428cf67c 100644
|
index 6fa6e3e0a1..dfaaf420a1 100644
|
||||||
--- a/salt/modules/zypperpkg.py
|
--- a/salt/modules/zypperpkg.py
|
||||||
+++ b/salt/modules/zypperpkg.py
|
+++ b/salt/modules/zypperpkg.py
|
||||||
@@ -282,7 +282,7 @@ class _Zypper(object):
|
@@ -300,7 +300,7 @@ class _Zypper:
|
||||||
self.__called = True
|
self.__called = True
|
||||||
if self.__xml:
|
if self.__xml:
|
||||||
self.__cmd.append('--xmlout')
|
self.__cmd.append("--xmlout")
|
||||||
- if not self.__refresh:
|
- if not self.__refresh:
|
||||||
+ if not self.__refresh and '--no-refresh' not in args:
|
+ if not self.__refresh and "--no-refresh" not in args:
|
||||||
self.__cmd.append('--no-refresh')
|
self.__cmd.append("--no-refresh")
|
||||||
|
if self.__root:
|
||||||
self.__cmd.extend(args)
|
self.__cmd.extend(["--root", self.__root])
|
||||||
diff --git a/tests/unit/modules/test_zypperpkg.py b/tests/unit/modules/test_zypperpkg.py
|
diff --git a/tests/unit/modules/test_zypperpkg.py b/tests/unit/modules/test_zypperpkg.py
|
||||||
index b3162f10cd..956902eab3 100644
|
index 7bff7065c6..b07f9a3af7 100644
|
||||||
--- a/tests/unit/modules/test_zypperpkg.py
|
--- a/tests/unit/modules/test_zypperpkg.py
|
||||||
+++ b/tests/unit/modules/test_zypperpkg.py
|
+++ b/tests/unit/modules/test_zypperpkg.py
|
||||||
@@ -135,7 +135,7 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -136,7 +136,7 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
self.assertEqual(zypper.__zypper__.call('foo'), stdout_xml_snippet)
|
self.assertEqual(zypper.__zypper__.call("foo"), stdout_xml_snippet)
|
||||||
self.assertEqual(len(sniffer.calls), 1)
|
self.assertEqual(len(sniffer.calls), 1)
|
||||||
|
|
||||||
- zypper.__zypper__.call('bar')
|
- zypper.__zypper__.call("bar")
|
||||||
+ zypper.__zypper__.call('--no-refresh', 'bar')
|
+ zypper.__zypper__.call("--no-refresh", "bar")
|
||||||
self.assertEqual(len(sniffer.calls), 2)
|
self.assertEqual(len(sniffer.calls), 2)
|
||||||
self.assertEqual(sniffer.calls[0]['args'][0], ['zypper', '--non-interactive', '--no-refresh', 'foo'])
|
self.assertEqual(
|
||||||
self.assertEqual(sniffer.calls[1]['args'][0], ['zypper', '--non-interactive', '--no-refresh', 'bar'])
|
sniffer.calls[0]["args"][0],
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From e2c3b1cb72b796fe12f94af64baa2e64cbe5db0b Mon Sep 17 00:00:00 2001
|
From 3dc61b426cee5c40976ee25a0357fd07244a630b Mon Sep 17 00:00:00 2001
|
||||||
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||||
<psuarezhernandez@suse.com>
|
<psuarezhernandez@suse.com>
|
||||||
Date: Tue, 13 Oct 2020 12:02:00 +0100
|
Date: Tue, 13 Oct 2020 12:02:00 +0100
|
||||||
@ -9,11 +9,11 @@ Subject: [PATCH] Drop wrong mock from chroot unit test
|
|||||||
1 file changed, 1 deletion(-)
|
1 file changed, 1 deletion(-)
|
||||||
|
|
||||||
diff --git a/tests/unit/modules/test_chroot.py b/tests/unit/modules/test_chroot.py
|
diff --git a/tests/unit/modules/test_chroot.py b/tests/unit/modules/test_chroot.py
|
||||||
index 62808ed680..045d56c5b0 100644
|
index 196e3ad27f..a0f3f8e6af 100644
|
||||||
--- a/tests/unit/modules/test_chroot.py
|
--- a/tests/unit/modules/test_chroot.py
|
||||||
+++ b/tests/unit/modules/test_chroot.py
|
+++ b/tests/unit/modules/test_chroot.py
|
||||||
@@ -83,7 +83,6 @@ class ChrootTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -71,7 +71,6 @@ class ChrootTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
self.assertTrue(chroot.create('/chroot'))
|
self.assertTrue(chroot.create("/chroot"))
|
||||||
makedirs.assert_called()
|
makedirs.assert_called()
|
||||||
|
|
||||||
- @patch("salt.modules.chroot.exist")
|
- @patch("salt.modules.chroot.exist")
|
||||||
@ -21,6 +21,6 @@ index 62808ed680..045d56c5b0 100644
|
|||||||
def test_in_chroot(self, fopen):
|
def test_in_chroot(self, fopen):
|
||||||
"""
|
"""
|
||||||
--
|
--
|
||||||
2.28.0
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
99
drop-wrong-virt-capabilities-code-after-rebasing-pat.patch
Normal file
99
drop-wrong-virt-capabilities-code-after-rebasing-pat.patch
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
From 79ae019ac7515614c6fbc620e66575f015bc447d Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||||
|
<psuarezhernandez@suse.com>
|
||||||
|
Date: Tue, 5 Jan 2021 09:34:45 +0000
|
||||||
|
Subject: [PATCH] Drop wrong virt capabilities code after rebasing
|
||||||
|
patches
|
||||||
|
|
||||||
|
---
|
||||||
|
salt/modules/virt.py | 66 --------------------------------------------
|
||||||
|
1 file changed, 66 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/salt/modules/virt.py b/salt/modules/virt.py
|
||||||
|
index e3960a5a90..786bfa1e58 100644
|
||||||
|
--- a/salt/modules/virt.py
|
||||||
|
+++ b/salt/modules/virt.py
|
||||||
|
@@ -143,7 +143,6 @@ import salt.utils.xmlutil as xmlutil
|
||||||
|
import salt.utils.yaml
|
||||||
|
from salt._compat import ElementTree, ipaddress, saxutils
|
||||||
|
from salt.exceptions import CommandExecutionError, SaltInvocationError
|
||||||
|
-from salt.ext import six
|
||||||
|
from salt.ext.six.moves import range # pylint: disable=import-error,redefined-builtin
|
||||||
|
from salt.ext.six.moves.urllib.parse import urlparse, urlunparse
|
||||||
|
from salt.utils.virt import check_remote, download_remote
|
||||||
|
@@ -5416,71 +5415,6 @@ def _parse_domain_caps(caps):
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
-def _parse_domain_caps(caps):
|
||||||
|
- """
|
||||||
|
- Parse the XML document of domain capabilities into a structure.
|
||||||
|
- """
|
||||||
|
- result = {
|
||||||
|
- "emulator": caps.find("path").text if caps.find("path") is not None else None,
|
||||||
|
- "domain": caps.find("domain").text if caps.find("domain") is not None else None,
|
||||||
|
- "machine": caps.find("machine").text
|
||||||
|
- if caps.find("machine") is not None
|
||||||
|
- else None,
|
||||||
|
- "arch": caps.find("arch").text if caps.find("arch") is not None else None,
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
-
|
||||||
|
-def all_capabilities(**kwargs):
|
||||||
|
- """
|
||||||
|
- Return the host and domain capabilities in a single call.
|
||||||
|
-
|
||||||
|
- .. versionadded:: 3001
|
||||||
|
-
|
||||||
|
- :param connection: libvirt connection URI, overriding defaults
|
||||||
|
- :param username: username to connect with, overriding defaults
|
||||||
|
- :param password: password to connect with, overriding defaults
|
||||||
|
-
|
||||||
|
- CLI Example:
|
||||||
|
-
|
||||||
|
- .. code-block:: bash
|
||||||
|
-
|
||||||
|
- salt '*' virt.all_capabilities
|
||||||
|
-
|
||||||
|
- """
|
||||||
|
- conn = __get_conn(**kwargs)
|
||||||
|
- try:
|
||||||
|
- host_caps = ElementTree.fromstring(conn.getCapabilities())
|
||||||
|
- domains = [
|
||||||
|
- [
|
||||||
|
- (guest.get("arch", {}).get("name", None), key)
|
||||||
|
- for key in guest.get("arch", {}).get("domains", {}).keys()
|
||||||
|
- ]
|
||||||
|
- for guest in [
|
||||||
|
- _parse_caps_guest(guest) for guest in host_caps.findall("guest")
|
||||||
|
- ]
|
||||||
|
- ]
|
||||||
|
- flattened = [pair for item in (x for x in domains) for pair in item]
|
||||||
|
- result = {
|
||||||
|
- "host": {
|
||||||
|
- "host": _parse_caps_host(host_caps.find("host")),
|
||||||
|
- "guests": [
|
||||||
|
- _parse_caps_guest(guest) for guest in host_caps.findall("guest")
|
||||||
|
- ],
|
||||||
|
- },
|
||||||
|
- "domains": [
|
||||||
|
- _parse_domain_caps(
|
||||||
|
- ElementTree.fromstring(
|
||||||
|
- conn.getDomainCapabilities(None, arch, None, domain)
|
||||||
|
- )
|
||||||
|
- )
|
||||||
|
- for (arch, domain) in flattened
|
||||||
|
- ],
|
||||||
|
- }
|
||||||
|
- return result
|
||||||
|
- finally:
|
||||||
|
- conn.close()
|
||||||
|
-
|
||||||
|
-
|
||||||
|
def domain_capabilities(emulator=None, arch=None, machine=None, domain=None, **kwargs):
|
||||||
|
"""
|
||||||
|
Return the domain capabilities given an emulator, architecture, machine or virtualization type.
|
||||||
|
--
|
||||||
|
2.29.2
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
|||||||
From cc3bd759bc0e4cc3414ccc5a2928c593fa2eee04 Mon Sep 17 00:00:00 2001
|
From fec7f65b4debede8cf0eef335182fce2206e200d Mon Sep 17 00:00:00 2001
|
||||||
From: Maximilian Meister <mmeister@suse.de>
|
From: Maximilian Meister <mmeister@suse.de>
|
||||||
Date: Thu, 3 May 2018 15:52:23 +0200
|
Date: Thu, 3 May 2018 15:52:23 +0200
|
||||||
Subject: [PATCH] enable passing a unix_socket for mysql returners
|
Subject: [PATCH] enable passing a unix_socket for mysql returners
|
||||||
@ -15,14 +15,19 @@ the refactor is done upstream
|
|||||||
|
|
||||||
Signed-off-by: Maximilian Meister <mmeister@suse.de>
|
Signed-off-by: Maximilian Meister <mmeister@suse.de>
|
||||||
---
|
---
|
||||||
salt/returners/mysql.py | 11 ++++++++---
|
salt/returners/mysql.py | 63 ++++++++++++++++++++---------------------
|
||||||
1 file changed, 8 insertions(+), 3 deletions(-)
|
1 file changed, 30 insertions(+), 33 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/returners/mysql.py b/salt/returners/mysql.py
|
diff --git a/salt/returners/mysql.py b/salt/returners/mysql.py
|
||||||
index 69599ec36a..ff9d380843 100644
|
index b7bb05164f..4aa8aeddfa 100644
|
||||||
--- a/salt/returners/mysql.py
|
--- a/salt/returners/mysql.py
|
||||||
+++ b/salt/returners/mysql.py
|
+++ b/salt/returners/mysql.py
|
||||||
@@ -18,6 +18,7 @@ config. These are the defaults:
|
@@ -1,4 +1,3 @@
|
||||||
|
-# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Return data to a mysql server
|
||||||
|
|
||||||
|
@@ -18,6 +17,7 @@ config. These are the defaults:
|
||||||
mysql.pass: 'salt'
|
mysql.pass: 'salt'
|
||||||
mysql.db: 'salt'
|
mysql.db: 'salt'
|
||||||
mysql.port: 3306
|
mysql.port: 3306
|
||||||
@ -30,7 +35,7 @@ index 69599ec36a..ff9d380843 100644
|
|||||||
|
|
||||||
SSL is optional. The defaults are set to None. If you do not want to use SSL,
|
SSL is optional. The defaults are set to None. If you do not want to use SSL,
|
||||||
either exclude these options or set them to None.
|
either exclude these options or set them to None.
|
||||||
@@ -43,6 +44,7 @@ optional. The following ssl options are simply for illustration purposes:
|
@@ -43,6 +43,7 @@ optional. The following ssl options are simply for illustration purposes:
|
||||||
alternative.mysql.ssl_ca: '/etc/pki/mysql/certs/localhost.pem'
|
alternative.mysql.ssl_ca: '/etc/pki/mysql/certs/localhost.pem'
|
||||||
alternative.mysql.ssl_cert: '/etc/pki/mysql/certs/localhost.crt'
|
alternative.mysql.ssl_cert: '/etc/pki/mysql/certs/localhost.crt'
|
||||||
alternative.mysql.ssl_key: '/etc/pki/mysql/certs/localhost.key'
|
alternative.mysql.ssl_key: '/etc/pki/mysql/certs/localhost.key'
|
||||||
@ -38,37 +43,195 @@ index 69599ec36a..ff9d380843 100644
|
|||||||
|
|
||||||
Should you wish the returner data to be cleaned out every so often, set
|
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.
|
`keep_jobs` to the number of hours for the jobs to live in the tables.
|
||||||
@@ -198,7 +200,8 @@ def _get_options(ret=None):
|
@@ -138,22 +139,15 @@ To override individual configuration items, append --return_kwargs '{"key:": "va
|
||||||
'port': 3306,
|
salt '*' test.ping --return mysql --return_kwargs '{"db": "another-salt"}'
|
||||||
'ssl_ca': None,
|
|
||||||
'ssl_cert': None,
|
|
||||||
- 'ssl_key': None}
|
|
||||||
+ 'ssl_key': None,
|
|
||||||
+ 'unix_socket': '/tmp/mysql.sock'}
|
|
||||||
|
|
||||||
attrs = {'host': 'host',
|
"""
|
||||||
'user': 'user',
|
-from __future__ import absolute_import, print_function, unicode_literals
|
||||||
@@ -207,7 +210,8 @@ def _get_options(ret=None):
|
|
||||||
'port': 'port',
|
|
||||||
'ssl_ca': 'ssl_ca',
|
|
||||||
'ssl_cert': 'ssl_cert',
|
|
||||||
- 'ssl_key': 'ssl_key'}
|
|
||||||
+ 'ssl_key': 'ssl_key',
|
|
||||||
+ 'unix_socket': 'unix_socket'}
|
|
||||||
|
|
||||||
_options = salt.returners.get_returner_options(__virtualname__,
|
import logging
|
||||||
ret,
|
import sys
|
||||||
@@ -261,7 +265,8 @@ def _get_serv(ret=None, commit=False):
|
-
|
||||||
passwd=_options.get('pass'),
|
-# Import python libs
|
||||||
db=_options.get('db'),
|
from contextlib import contextmanager
|
||||||
port=_options.get('port'),
|
|
||||||
- ssl=ssl_options)
|
import salt.exceptions
|
||||||
+ ssl=ssl_options,
|
-
|
||||||
+ unix_socket=_options.get('unix_socket'))
|
-# Import salt libs
|
||||||
|
import salt.returners
|
||||||
|
import salt.utils.jid
|
||||||
|
import salt.utils.json
|
||||||
|
-
|
||||||
|
-# Import 3rd-party libs
|
||||||
|
from salt.ext import six
|
||||||
|
|
||||||
|
# Let's not allow PyLint complain about string substitution
|
||||||
|
@@ -205,6 +199,7 @@ def _get_options(ret=None):
|
||||||
|
"ssl_ca": None,
|
||||||
|
"ssl_cert": None,
|
||||||
|
"ssl_key": None,
|
||||||
|
+ "unix_socket": "/tmp/mysql.sock",
|
||||||
|
}
|
||||||
|
|
||||||
|
attrs = {
|
||||||
|
@@ -216,6 +211,7 @@ def _get_options(ret=None):
|
||||||
|
"ssl_ca": "ssl_ca",
|
||||||
|
"ssl_cert": "ssl_cert",
|
||||||
|
"ssl_key": "ssl_key",
|
||||||
|
+ "unix_socket": "unix_socket",
|
||||||
|
}
|
||||||
|
|
||||||
|
_options = salt.returners.get_returner_options(
|
||||||
|
@@ -227,8 +223,8 @@ def _get_options(ret=None):
|
||||||
|
defaults=defaults,
|
||||||
|
)
|
||||||
|
# post processing
|
||||||
|
- for k, v in six.iteritems(_options):
|
||||||
|
- if isinstance(v, six.string_types) and v.lower() == "none":
|
||||||
|
+ for k, v in _options.items():
|
||||||
|
+ if isinstance(v, str) and v.lower() == "none":
|
||||||
|
# Ensure 'None' is rendered as None
|
||||||
|
_options[k] = None
|
||||||
|
if k == "port":
|
||||||
|
@@ -274,6 +270,7 @@ def _get_serv(ret=None, commit=False):
|
||||||
|
db=_options.get("db"),
|
||||||
|
port=_options.get("port"),
|
||||||
|
ssl=ssl_options,
|
||||||
|
+ unix_socket=_options.get("unix_socket"),
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
__context__['mysql_returner_conn'] = conn
|
@@ -291,9 +288,9 @@ def _get_serv(ret=None, commit=False):
|
||||||
|
yield cursor
|
||||||
|
except MySQLdb.DatabaseError as err:
|
||||||
|
error = err.args
|
||||||
|
- sys.stderr.write(six.text_type(error))
|
||||||
|
+ sys.stderr.write(str(error))
|
||||||
|
cursor.execute("ROLLBACK")
|
||||||
|
- six.reraise(*sys.exc_info())
|
||||||
|
+ raise
|
||||||
|
else:
|
||||||
|
if commit:
|
||||||
|
cursor.execute("COMMIT")
|
||||||
|
@@ -515,8 +512,8 @@ def _purge_jobs(timestamp):
|
||||||
|
log.error(
|
||||||
|
"mysql returner archiver was unable to delete contents of table 'jids'"
|
||||||
|
)
|
||||||
|
- log.error(six.text_type(e))
|
||||||
|
- raise salt.exceptions.SaltRunnerError(six.text_type(e))
|
||||||
|
+ log.error(str(e))
|
||||||
|
+ raise salt.exceptions.SaltRunnerError(str(e))
|
||||||
|
|
||||||
|
try:
|
||||||
|
sql = "delete from `salt_returns` where alter_time < %s"
|
||||||
|
@@ -526,8 +523,8 @@ def _purge_jobs(timestamp):
|
||||||
|
log.error(
|
||||||
|
"mysql returner archiver was unable to delete contents of table 'salt_returns'"
|
||||||
|
)
|
||||||
|
- log.error(six.text_type(e))
|
||||||
|
- raise salt.exceptions.SaltRunnerError(six.text_type(e))
|
||||||
|
+ log.error(str(e))
|
||||||
|
+ raise salt.exceptions.SaltRunnerError(str(e))
|
||||||
|
|
||||||
|
try:
|
||||||
|
sql = "delete from `salt_events` where alter_time < %s"
|
||||||
|
@@ -537,8 +534,8 @@ def _purge_jobs(timestamp):
|
||||||
|
log.error(
|
||||||
|
"mysql returner archiver was unable to delete contents of table 'salt_events'"
|
||||||
|
)
|
||||||
|
- log.error(six.text_type(e))
|
||||||
|
- raise salt.exceptions.SaltRunnerError(six.text_type(e))
|
||||||
|
+ log.error(str(e))
|
||||||
|
+ raise salt.exceptions.SaltRunnerError(str(e))
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
@@ -556,7 +553,7 @@ def _archive_jobs(timestamp):
|
||||||
|
for table_name in source_tables:
|
||||||
|
try:
|
||||||
|
tmp_table_name = table_name + "_archive"
|
||||||
|
- sql = "create table if not exists {0} like {1}".format(
|
||||||
|
+ sql = "create table if not exists {} like {}".format(
|
||||||
|
tmp_table_name, table_name
|
||||||
|
)
|
||||||
|
cur.execute(sql)
|
||||||
|
@@ -566,11 +563,11 @@ def _archive_jobs(timestamp):
|
||||||
|
log.error(
|
||||||
|
"mysql returner archiver was unable to create the archive tables."
|
||||||
|
)
|
||||||
|
- log.error(six.text_type(e))
|
||||||
|
- raise salt.exceptions.SaltRunnerError(six.text_type(e))
|
||||||
|
+ log.error(str(e))
|
||||||
|
+ raise salt.exceptions.SaltRunnerError(str(e))
|
||||||
|
|
||||||
|
try:
|
||||||
|
- sql = "insert into `{0}` select * from `{1}` where jid in (select distinct jid from salt_returns where alter_time < %s)".format(
|
||||||
|
+ sql = "insert into `{}` select * from `{}` where jid in (select distinct jid from salt_returns where alter_time < %s)".format(
|
||||||
|
target_tables["jids"], "jids"
|
||||||
|
)
|
||||||
|
cur.execute(sql, (timestamp,))
|
||||||
|
@@ -579,14 +576,14 @@ def _archive_jobs(timestamp):
|
||||||
|
log.error(
|
||||||
|
"mysql returner archiver was unable to copy contents of table 'jids'"
|
||||||
|
)
|
||||||
|
- log.error(six.text_type(e))
|
||||||
|
- raise salt.exceptions.SaltRunnerError(six.text_type(e))
|
||||||
|
+ log.error(str(e))
|
||||||
|
+ raise salt.exceptions.SaltRunnerError(str(e))
|
||||||
|
except Exception as e: # pylint: disable=broad-except
|
||||||
|
log.error(e)
|
||||||
|
raise
|
||||||
|
|
||||||
|
try:
|
||||||
|
- sql = "insert into `{0}` select * from `{1}` where alter_time < %s".format(
|
||||||
|
+ sql = "insert into `{}` select * from `{}` where alter_time < %s".format(
|
||||||
|
target_tables["salt_returns"], "salt_returns"
|
||||||
|
)
|
||||||
|
cur.execute(sql, (timestamp,))
|
||||||
|
@@ -595,11 +592,11 @@ def _archive_jobs(timestamp):
|
||||||
|
log.error(
|
||||||
|
"mysql returner archiver was unable to copy contents of table 'salt_returns'"
|
||||||
|
)
|
||||||
|
- log.error(six.text_type(e))
|
||||||
|
- raise salt.exceptions.SaltRunnerError(six.text_type(e))
|
||||||
|
+ log.error(str(e))
|
||||||
|
+ raise salt.exceptions.SaltRunnerError(str(e))
|
||||||
|
|
||||||
|
try:
|
||||||
|
- sql = "insert into `{0}` select * from `{1}` where alter_time < %s".format(
|
||||||
|
+ sql = "insert into `{}` select * from `{}` where alter_time < %s".format(
|
||||||
|
target_tables["salt_events"], "salt_events"
|
||||||
|
)
|
||||||
|
cur.execute(sql, (timestamp,))
|
||||||
|
@@ -608,8 +605,8 @@ def _archive_jobs(timestamp):
|
||||||
|
log.error(
|
||||||
|
"mysql returner archiver was unable to copy contents of table 'salt_events'"
|
||||||
|
)
|
||||||
|
- log.error(six.text_type(e))
|
||||||
|
- raise salt.exceptions.SaltRunnerError(six.text_type(e))
|
||||||
|
+ log.error(str(e))
|
||||||
|
+ raise salt.exceptions.SaltRunnerError(str(e))
|
||||||
|
|
||||||
|
return _purge_jobs(timestamp)
|
||||||
|
|
||||||
|
@@ -623,7 +620,7 @@ def clean_old_jobs():
|
||||||
|
if __opts__.get("keep_jobs", False) and int(__opts__.get("keep_jobs", 0)) > 0:
|
||||||
|
try:
|
||||||
|
with _get_serv() as cur:
|
||||||
|
- sql = "select date_sub(now(), interval {0} hour) as stamp;".format(
|
||||||
|
+ sql = "select date_sub(now(), interval {} hour) as stamp;".format(
|
||||||
|
__opts__["keep_jobs"]
|
||||||
|
)
|
||||||
|
cur.execute(sql)
|
||||||
|
@@ -638,5 +635,5 @@ def clean_old_jobs():
|
||||||
|
log.error(
|
||||||
|
"Mysql returner was unable to get timestamp for purge/archive of jobs"
|
||||||
|
)
|
||||||
|
- log.error(six.text_type(e))
|
||||||
|
- raise salt.exceptions.SaltRunnerError(six.text_type(e))
|
||||||
|
+ log.error(str(e))
|
||||||
|
+ raise salt.exceptions.SaltRunnerError(str(e))
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From 173444cecc1e7b4867570f1f8764db1b7f82061e Mon Sep 17 00:00:00 2001
|
From 1cea7d065d8da7c713af8136162c21187d5186f5 Mon Sep 17 00:00:00 2001
|
||||||
From: Cedric Bosdonnat <cbosdonnat@suse.com>
|
From: Cedric Bosdonnat <cbosdonnat@suse.com>
|
||||||
Date: Wed, 14 Oct 2020 12:39:16 +0200
|
Date: Wed, 14 Oct 2020 12:39:16 +0200
|
||||||
Subject: [PATCH] Ensure virt.update stop_on_reboot is updated with its
|
Subject: [PATCH] Ensure virt.update stop_on_reboot is updated with its
|
||||||
@ -14,22 +14,22 @@ this value.
|
|||||||
2 files changed, 3 insertions(+)
|
2 files changed, 3 insertions(+)
|
||||||
|
|
||||||
diff --git a/salt/modules/virt.py b/salt/modules/virt.py
|
diff --git a/salt/modules/virt.py b/salt/modules/virt.py
|
||||||
index 87ab7ca12d..9bc7bc6093 100644
|
index 8e2180608a..e3960a5a90 100644
|
||||||
--- a/salt/modules/virt.py
|
--- a/salt/modules/virt.py
|
||||||
+++ b/salt/modules/virt.py
|
+++ b/salt/modules/virt.py
|
||||||
@@ -2742,6 +2742,7 @@ def update(
|
@@ -2738,6 +2738,7 @@ def update(
|
||||||
]
|
]
|
||||||
|
|
||||||
data = {k: v for k, v in six.iteritems(locals()) if bool(v)}
|
data = {k: v for k, v in locals().items() if bool(v)}
|
||||||
+ data["stop_on_reboot"] = stop_on_reboot
|
+ data["stop_on_reboot"] = stop_on_reboot
|
||||||
if boot_dev:
|
if boot_dev:
|
||||||
data["boot_dev"] = {i + 1: dev for i, dev in enumerate(boot_dev.split())}
|
data["boot_dev"] = {i + 1: dev for i, dev in enumerate(boot_dev.split())}
|
||||||
need_update = salt.utils.xmlutil.change_xml(
|
need_update = (
|
||||||
diff --git a/tests/unit/modules/test_virt.py b/tests/unit/modules/test_virt.py
|
diff --git a/tests/unit/modules/test_virt.py b/tests/unit/modules/test_virt.py
|
||||||
index ca5e80d2d2..fbc03cf7a6 100644
|
index fba821ea53..83152eda6e 100644
|
||||||
--- a/tests/unit/modules/test_virt.py
|
--- a/tests/unit/modules/test_virt.py
|
||||||
+++ b/tests/unit/modules/test_virt.py
|
+++ b/tests/unit/modules/test_virt.py
|
||||||
@@ -1778,6 +1778,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -1777,6 +1777,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
<memory unit='KiB'>1048576</memory>
|
<memory unit='KiB'>1048576</memory>
|
||||||
<currentMemory unit='KiB'>1048576</currentMemory>
|
<currentMemory unit='KiB'>1048576</currentMemory>
|
||||||
<vcpu placement='auto'>1</vcpu>
|
<vcpu placement='auto'>1</vcpu>
|
||||||
@ -37,7 +37,7 @@ index ca5e80d2d2..fbc03cf7a6 100644
|
|||||||
<os>
|
<os>
|
||||||
<type arch='x86_64' machine='pc-i440fx-2.6'>hvm</type>
|
<type arch='x86_64' machine='pc-i440fx-2.6'>hvm</type>
|
||||||
<boot dev="hd"/>
|
<boot dev="hd"/>
|
||||||
@@ -2350,6 +2351,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -2349,6 +2350,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
<memory unit='KiB'>1048576</memory>
|
<memory unit='KiB'>1048576</memory>
|
||||||
<currentMemory unit='KiB'>1048576</currentMemory>
|
<currentMemory unit='KiB'>1048576</currentMemory>
|
||||||
<vcpu placement='auto'>1</vcpu>
|
<vcpu placement='auto'>1</vcpu>
|
||||||
@ -46,6 +46,6 @@ index ca5e80d2d2..fbc03cf7a6 100644
|
|||||||
<type arch='x86_64' machine='pc-i440fx-2.6'>hvm</type>
|
<type arch='x86_64' machine='pc-i440fx-2.6'>hvm</type>
|
||||||
</os>
|
</os>
|
||||||
--
|
--
|
||||||
2.28.0
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From f0098b4b9e5abaaca7bbc6c17f5a60bb2129dda5 Mon Sep 17 00:00:00 2001
|
From 188a97fc20c3e24950b82dc6fcd0da878509cf7a Mon Sep 17 00:00:00 2001
|
||||||
From: Maximilian Meister <mmeister@suse.de>
|
From: Maximilian Meister <mmeister@suse.de>
|
||||||
Date: Thu, 5 Apr 2018 13:23:23 +0200
|
Date: Thu, 5 Apr 2018 13:23:23 +0200
|
||||||
Subject: [PATCH] fall back to PyMySQL
|
Subject: [PATCH] fall back to PyMySQL
|
||||||
@ -11,10 +11,10 @@ Signed-off-by: Maximilian Meister <mmeister@suse.de>
|
|||||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/modules/mysql.py b/salt/modules/mysql.py
|
diff --git a/salt/modules/mysql.py b/salt/modules/mysql.py
|
||||||
index 87e2361e28..e785e5219c 100644
|
index fdfe35158a..385e4d92a3 100644
|
||||||
--- a/salt/modules/mysql.py
|
--- a/salt/modules/mysql.py
|
||||||
+++ b/salt/modules/mysql.py
|
+++ b/salt/modules/mysql.py
|
||||||
@@ -58,7 +58,7 @@ try:
|
@@ -55,7 +55,7 @@ try:
|
||||||
import MySQLdb.cursors
|
import MySQLdb.cursors
|
||||||
import MySQLdb.converters
|
import MySQLdb.converters
|
||||||
from MySQLdb.constants import FIELD_TYPE, FLAG
|
from MySQLdb.constants import FIELD_TYPE, FLAG
|
||||||
@ -23,7 +23,7 @@ index 87e2361e28..e785e5219c 100644
|
|||||||
except ImportError:
|
except ImportError:
|
||||||
try:
|
try:
|
||||||
# MySQLdb import failed, try to import PyMySQL
|
# MySQLdb import failed, try to import PyMySQL
|
||||||
@@ -68,7 +68,7 @@ except ImportError:
|
@@ -66,7 +66,7 @@ except ImportError:
|
||||||
import MySQLdb.cursors
|
import MySQLdb.cursors
|
||||||
import MySQLdb.converters
|
import MySQLdb.converters
|
||||||
from MySQLdb.constants import FIELD_TYPE, FLAG
|
from MySQLdb.constants import FIELD_TYPE, FLAG
|
||||||
@ -33,6 +33,6 @@ index 87e2361e28..e785e5219c 100644
|
|||||||
MySQLdb = None
|
MySQLdb = None
|
||||||
|
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From 7ad2d6067400f55dc7b70745216fab20620f35fd Mon Sep 17 00:00:00 2001
|
From 1e00e2b72321b5312efb7b8b426a037c8db72b79 Mon Sep 17 00:00:00 2001
|
||||||
From: Alberto Planas <aplanas@suse.com>
|
From: Alberto Planas <aplanas@suse.com>
|
||||||
Date: Wed, 29 Jul 2020 16:11:47 +0200
|
Date: Wed, 29 Jul 2020 16:11:47 +0200
|
||||||
Subject: [PATCH] Fix __mount_device wrapper (#254)
|
Subject: [PATCH] Fix __mount_device wrapper (#254)
|
||||||
@ -17,9 +17,9 @@ Fix #58012
|
|||||||
(cherry picked from commit 2089645e2478751dc795127cfd14d0385c2e0899)
|
(cherry picked from commit 2089645e2478751dc795127cfd14d0385c2e0899)
|
||||||
---
|
---
|
||||||
changelog/58012.fixed | 1 +
|
changelog/58012.fixed | 1 +
|
||||||
salt/states/btrfs.py | 6 +++---
|
salt/states/btrfs.py | 4 ++--
|
||||||
tests/unit/states/test_btrfs.py | 27 +++++++++++++++++++++++++++
|
tests/unit/states/test_btrfs.py | 27 +++++++++++++++++++++++++++
|
||||||
3 files changed, 31 insertions(+), 3 deletions(-)
|
3 files changed, 30 insertions(+), 2 deletions(-)
|
||||||
create mode 100644 changelog/58012.fixed
|
create mode 100644 changelog/58012.fixed
|
||||||
|
|
||||||
diff --git a/changelog/58012.fixed b/changelog/58012.fixed
|
diff --git a/changelog/58012.fixed b/changelog/58012.fixed
|
||||||
@ -31,27 +31,25 @@ index 0000000000..13a1ef747d
|
|||||||
+Fix btrfs state decorator, that produces exceptions when creating subvolumes.
|
+Fix btrfs state decorator, that produces exceptions when creating subvolumes.
|
||||||
\ No newline at end of file
|
\ No newline at end of file
|
||||||
diff --git a/salt/states/btrfs.py b/salt/states/btrfs.py
|
diff --git a/salt/states/btrfs.py b/salt/states/btrfs.py
|
||||||
index af78c8ae00..d0d6095c46 100644
|
index 1374bbffb4..62a3553758 100644
|
||||||
--- a/salt/states/btrfs.py
|
--- a/salt/states/btrfs.py
|
||||||
+++ b/salt/states/btrfs.py
|
+++ b/salt/states/btrfs.py
|
||||||
@@ -103,9 +103,9 @@ def __mount_device(action):
|
@@ -103,8 +103,8 @@ def __mount_device(action):
|
||||||
'''
|
|
||||||
@functools.wraps(action)
|
@functools.wraps(action)
|
||||||
def wrapper(*args, **kwargs):
|
def wrapper(*args, **kwargs):
|
||||||
- name = kwargs['name']
|
- name = kwargs["name"]
|
||||||
- device = kwargs['device']
|
- device = kwargs["device"]
|
||||||
- use_default = kwargs.get('use_default', False)
|
|
||||||
+ name = kwargs.get("name", args[0] if args else None)
|
+ name = kwargs.get("name", args[0] if args else None)
|
||||||
+ device = kwargs.get("device", args[1] if len(args) > 1 else None)
|
+ device = kwargs.get("device", args[1] if len(args) > 1 else None)
|
||||||
+ use_default = kwargs.get("use_default", False)
|
use_default = kwargs.get("use_default", False)
|
||||||
|
|
||||||
ret = {
|
ret = {
|
||||||
'name': name,
|
|
||||||
diff --git a/tests/unit/states/test_btrfs.py b/tests/unit/states/test_btrfs.py
|
diff --git a/tests/unit/states/test_btrfs.py b/tests/unit/states/test_btrfs.py
|
||||||
index c68f6279dc..c722630aef 100644
|
index b8f70bccfe..dceb971aa1 100644
|
||||||
--- a/tests/unit/states/test_btrfs.py
|
--- a/tests/unit/states/test_btrfs.py
|
||||||
+++ b/tests/unit/states/test_btrfs.py
|
+++ b/tests/unit/states/test_btrfs.py
|
||||||
@@ -245,6 +245,33 @@ class BtrfsTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -231,6 +231,33 @@ class BtrfsTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
mount.assert_called_once()
|
mount.assert_called_once()
|
||||||
umount.assert_called_once()
|
umount.assert_called_once()
|
||||||
|
|
||||||
@ -82,10 +80,10 @@ index c68f6279dc..c722630aef 100644
|
|||||||
+ mount.assert_called_once()
|
+ mount.assert_called_once()
|
||||||
+ umount.assert_called_once()
|
+ umount.assert_called_once()
|
||||||
+
|
+
|
||||||
@patch('salt.states.btrfs._umount')
|
@patch("salt.states.btrfs._umount")
|
||||||
@patch('salt.states.btrfs._mount')
|
@patch("salt.states.btrfs._mount")
|
||||||
def test_subvolume_created_exists_test(self, mount, umount):
|
def test_subvolume_created_exists_test(self, mount, umount):
|
||||||
--
|
--
|
||||||
2.27.0
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From c1e66b9953c753dc9eff3652aef316e19c22deb4 Mon Sep 17 00:00:00 2001
|
From daf29460408a5e0eb042b3c234c7e21a6b994cf1 Mon Sep 17 00:00:00 2001
|
||||||
From: Alberto Planas <aplanas@suse.com>
|
From: Alberto Planas <aplanas@suse.com>
|
||||||
Date: Tue, 12 May 2020 14:16:23 +0200
|
Date: Tue, 12 May 2020 14:16:23 +0200
|
||||||
Subject: [PATCH] Fix a test and some variable names (#229)
|
Subject: [PATCH] Fix a test and some variable names (#229)
|
||||||
@ -7,60 +7,23 @@ Subject: [PATCH] Fix a test and some variable names (#229)
|
|||||||
|
|
||||||
* Fix test_core tests for fqdns errors
|
* Fix test_core tests for fqdns errors
|
||||||
---
|
---
|
||||||
salt/modules/network.py | 2 +-
|
tests/unit/grains/test_core.py | 2 +-
|
||||||
tests/unit/grains/test_core.py | 24 +++++++++++++-----------
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
2 files changed, 14 insertions(+), 12 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/salt/modules/network.py b/salt/modules/network.py
|
|
||||||
index 880f4f8d5f..9e11eb816e 100644
|
|
||||||
--- a/salt/modules/network.py
|
|
||||||
+++ b/salt/modules/network.py
|
|
||||||
@@ -1946,4 +1946,4 @@ def fqdns():
|
|
||||||
elapsed = time.time() - start
|
|
||||||
log.debug('Elapsed time getting FQDNs: {} seconds'.format(elapsed))
|
|
||||||
|
|
||||||
- return {"fqdns": sorted(list(fqdns))}
|
|
||||||
\ No newline at end of file
|
|
||||||
+ return {"fqdns": sorted(list(fqdns))}
|
|
||||||
diff --git a/tests/unit/grains/test_core.py b/tests/unit/grains/test_core.py
|
diff --git a/tests/unit/grains/test_core.py b/tests/unit/grains/test_core.py
|
||||||
index 94e4199814..36aa49f232 100644
|
index 196dbcf83d..918a9155cb 100644
|
||||||
--- a/tests/unit/grains/test_core.py
|
--- a/tests/unit/grains/test_core.py
|
||||||
+++ b/tests/unit/grains/test_core.py
|
+++ b/tests/unit/grains/test_core.py
|
||||||
@@ -1122,20 +1122,22 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -1416,7 +1416,7 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
|
with patch("salt.modules.network.log", mock_log):
|
||||||
for errno in (0, core.HOST_NOT_FOUND, core.NO_DATA):
|
self.assertEqual(core.fqdns(), {"fqdns": []})
|
||||||
mock_log = MagicMock()
|
|
||||||
+ with patch.dict(core.__salt__, {'network.fqdns': salt.modules.network.fqdns}):
|
|
||||||
+ with patch.object(socket, 'gethostbyaddr',
|
|
||||||
+ side_effect=_gen_gethostbyaddr(errno)):
|
|
||||||
+ with patch('salt.modules.network.log', mock_log):
|
|
||||||
+ self.assertEqual(core.fqdns(), {'fqdns': []})
|
|
||||||
+ mock_log.debug.assert_called()
|
|
||||||
+ mock_log.error.assert_not_called()
|
|
||||||
+
|
|
||||||
+ mock_log = MagicMock()
|
|
||||||
+ with patch.dict(core.__salt__, {'network.fqdns': salt.modules.network.fqdns}):
|
|
||||||
with patch.object(socket, 'gethostbyaddr',
|
|
||||||
- side_effect=_gen_gethostbyaddr(errno)):
|
|
||||||
- with patch('salt.grains.core.log', mock_log):
|
|
||||||
+ side_effect=_gen_gethostbyaddr(-1)):
|
|
||||||
+ with patch('salt.modules.network.log', mock_log):
|
|
||||||
self.assertEqual(core.fqdns(), {'fqdns': []})
|
|
||||||
mock_log.debug.assert_called_once()
|
mock_log.debug.assert_called_once()
|
||||||
- mock_log.error.assert_not_called()
|
- mock_log.error.assert_called()
|
||||||
-
|
|
||||||
- mock_log = MagicMock()
|
|
||||||
- with patch.object(socket, 'gethostbyaddr',
|
|
||||||
- side_effect=_gen_gethostbyaddr(-1)):
|
|
||||||
- with patch('salt.grains.core.log', mock_log):
|
|
||||||
- self.assertEqual(core.fqdns(), {'fqdns': []})
|
|
||||||
- mock_log.debug.assert_not_called()
|
|
||||||
- mock_log.error.assert_called_once()
|
|
||||||
+ mock_log.error.assert_called_once()
|
+ mock_log.error.assert_called_once()
|
||||||
|
|
||||||
@patch.object(salt.utils.platform, 'is_windows', MagicMock(return_value=False))
|
@patch.object(salt.utils.platform, "is_windows", MagicMock(return_value=False))
|
||||||
@patch('salt.utils.network.ip_addrs', MagicMock(return_value=['1.2.3.4', '5.6.7.8']))
|
@patch(
|
||||||
--
|
--
|
||||||
2.26.2
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From 67830ea17ae1e87a6bffca2a9542788c200d7dd9 Mon Sep 17 00:00:00 2001
|
From 3d5f3cff6b43d7aba35063e970d016401bb82921 Mon Sep 17 00:00:00 2001
|
||||||
From: Alberto Planas <aplanas@gmail.com>
|
From: Alberto Planas <aplanas@gmail.com>
|
||||||
Date: Fri, 25 Oct 2019 15:43:16 +0200
|
Date: Fri, 25 Oct 2019 15:43:16 +0200
|
||||||
Subject: [PATCH] Fix a wrong rebase in test_core.py (#180)
|
Subject: [PATCH] Fix a wrong rebase in test_core.py (#180)
|
||||||
@ -17,89 +17,128 @@ This patch ignore this kind of issue during the grains creation.
|
|||||||
|
|
||||||
(cherry picked from commit bd0213bae00b737b24795bec3c030ebfe476e0d8)
|
(cherry picked from commit bd0213bae00b737b24795bec3c030ebfe476e0d8)
|
||||||
---
|
---
|
||||||
salt/grains/core.py | 4 ++--
|
salt/grains/core.py | 8 +++-
|
||||||
tests/unit/grains/test_core.py | 45 ------------------------------------------
|
tests/unit/grains/test_core.py | 80 ----------------------------------
|
||||||
2 files changed, 2 insertions(+), 47 deletions(-)
|
2 files changed, 6 insertions(+), 82 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/grains/core.py b/salt/grains/core.py
|
diff --git a/salt/grains/core.py b/salt/grains/core.py
|
||||||
index 68c43482d3..20950988d9 100644
|
index a2983e388b..5dff6ecfd4 100644
|
||||||
--- a/salt/grains/core.py
|
--- a/salt/grains/core.py
|
||||||
+++ b/salt/grains/core.py
|
+++ b/salt/grains/core.py
|
||||||
@@ -1000,7 +1000,7 @@ def _virtual(osdata):
|
@@ -1066,7 +1066,9 @@ def _virtual(osdata):
|
||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
# Some firmwares provide non-valid 'product_name'
|
# Some firmwares provide non-valid 'product_name'
|
||||||
# files, ignore them
|
# files, ignore them
|
||||||
- pass
|
- pass
|
||||||
+ log.debug('The content in /sys/devices/virtual/dmi/id/product_name is not valid')
|
+ log.debug(
|
||||||
except IOError:
|
+ "The content in /sys/devices/virtual/dmi/id/product_name is not valid"
|
||||||
|
+ )
|
||||||
|
except OSError:
|
||||||
pass
|
pass
|
||||||
elif osdata['kernel'] == 'FreeBSD':
|
elif osdata["kernel"] == "FreeBSD":
|
||||||
@@ -2568,7 +2568,7 @@ def _hw_data(osdata):
|
@@ -2716,7 +2718,9 @@ def _hw_data(osdata):
|
||||||
except UnicodeDecodeError:
|
except UnicodeDecodeError:
|
||||||
# Some firmwares provide non-valid 'product_name'
|
# Some firmwares provide non-valid 'product_name'
|
||||||
# files, ignore them
|
# files, ignore them
|
||||||
- pass
|
- pass
|
||||||
+ log.debug('The content in /sys/devices/virtual/dmi/id/product_name is not valid')
|
+ log.debug(
|
||||||
except (IOError, OSError) as err:
|
+ "The content in /sys/devices/virtual/dmi/id/product_name is not valid"
|
||||||
|
+ )
|
||||||
|
except OSError as err:
|
||||||
# PermissionError is new to Python 3, but corresponds to the EACESS and
|
# PermissionError is new to Python 3, but corresponds to the EACESS and
|
||||||
# EPERM error numbers. Use those instead here for PY2 compatibility.
|
# EPERM error numbers. Use those instead here for PY2 compatibility.
|
||||||
diff --git a/tests/unit/grains/test_core.py b/tests/unit/grains/test_core.py
|
diff --git a/tests/unit/grains/test_core.py b/tests/unit/grains/test_core.py
|
||||||
index 33d6a9507f..7fa2436e58 100644
|
index 0dc3423646..85d434dd9d 100644
|
||||||
--- a/tests/unit/grains/test_core.py
|
--- a/tests/unit/grains/test_core.py
|
||||||
+++ b/tests/unit/grains/test_core.py
|
+++ b/tests/unit/grains/test_core.py
|
||||||
@@ -1560,51 +1560,6 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -2047,86 +2047,6 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
assert all([x is not None for x in info])
|
result = core.path()
|
||||||
assert all([isinstance(x, int) for x in info])
|
assert result == {"path": path, "systempath": comps}, result
|
||||||
|
|
||||||
- @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
|
- @skipIf(not salt.utils.platform.is_linux(), "System is not Linux")
|
||||||
|
- @patch("os.path.exists")
|
||||||
|
- @patch("salt.utils.platform.is_proxy")
|
||||||
- def test_kernelparams_return(self):
|
- def test_kernelparams_return(self):
|
||||||
- expectations = [
|
- expectations = [
|
||||||
- ('BOOT_IMAGE=/vmlinuz-3.10.0-693.2.2.el7.x86_64',
|
- (
|
||||||
- {'kernelparams': [('BOOT_IMAGE', '/vmlinuz-3.10.0-693.2.2.el7.x86_64')]}),
|
- "BOOT_IMAGE=/vmlinuz-3.10.0-693.2.2.el7.x86_64",
|
||||||
- ('root=/dev/mapper/centos_daemon-root',
|
- {
|
||||||
- {'kernelparams': [('root', '/dev/mapper/centos_daemon-root')]}),
|
- "kernelparams": [
|
||||||
- ('rhgb quiet ro',
|
- ("BOOT_IMAGE", "/vmlinuz-3.10.0-693.2.2.el7.x86_64")
|
||||||
- {'kernelparams': [('rhgb', None), ('quiet', None), ('ro', None)]}),
|
- ]
|
||||||
- ('param="value1"',
|
- },
|
||||||
- {'kernelparams': [('param', 'value1')]}),
|
- ),
|
||||||
- ('param="value1 value2 value3"',
|
- (
|
||||||
- {'kernelparams': [('param', 'value1 value2 value3')]}),
|
- "root=/dev/mapper/centos_daemon-root",
|
||||||
- ('param="value1 value2 value3" LANG="pl" ro',
|
- {"kernelparams": [("root", "/dev/mapper/centos_daemon-root")]},
|
||||||
- {'kernelparams': [('param', 'value1 value2 value3'), ('LANG', 'pl'), ('ro', None)]}),
|
- ),
|
||||||
- ('ipv6.disable=1',
|
- (
|
||||||
- {'kernelparams': [('ipv6.disable', '1')]}),
|
- "rhgb quiet ro",
|
||||||
- ('param="value1:value2:value3"',
|
- {"kernelparams": [("rhgb", None), ("quiet", None), ("ro", None)]},
|
||||||
- {'kernelparams': [('param', 'value1:value2:value3')]}),
|
- ),
|
||||||
- ('param="value1,value2,value3"',
|
- ('param="value1"', {"kernelparams": [("param", "value1")]}),
|
||||||
- {'kernelparams': [('param', 'value1,value2,value3')]}),
|
- (
|
||||||
- ('param="value1" param="value2" param="value3"',
|
- 'param="value1 value2 value3"',
|
||||||
- {'kernelparams': [('param', 'value1'), ('param', 'value2'), ('param', 'value3')]}),
|
- {"kernelparams": [("param", "value1 value2 value3")]},
|
||||||
|
- ),
|
||||||
|
- (
|
||||||
|
- 'param="value1 value2 value3" LANG="pl" ro',
|
||||||
|
- {
|
||||||
|
- "kernelparams": [
|
||||||
|
- ("param", "value1 value2 value3"),
|
||||||
|
- ("LANG", "pl"),
|
||||||
|
- ("ro", None),
|
||||||
|
- ]
|
||||||
|
- },
|
||||||
|
- ),
|
||||||
|
- ("ipv6.disable=1", {"kernelparams": [("ipv6.disable", "1")]}),
|
||||||
|
- (
|
||||||
|
- 'param="value1:value2:value3"',
|
||||||
|
- {"kernelparams": [("param", "value1:value2:value3")]},
|
||||||
|
- ),
|
||||||
|
- (
|
||||||
|
- 'param="value1,value2,value3"',
|
||||||
|
- {"kernelparams": [("param", "value1,value2,value3")]},
|
||||||
|
- ),
|
||||||
|
- (
|
||||||
|
- 'param="value1" param="value2" param="value3"',
|
||||||
|
- {
|
||||||
|
- "kernelparams": [
|
||||||
|
- ("param", "value1"),
|
||||||
|
- ("param", "value2"),
|
||||||
|
- ("param", "value3"),
|
||||||
|
- ]
|
||||||
|
- },
|
||||||
|
- ),
|
||||||
- ]
|
- ]
|
||||||
-
|
-
|
||||||
- for cmdline, expectation in expectations:
|
- for cmdline, expectation in expectations:
|
||||||
- with patch('salt.utils.files.fopen', mock_open(read_data=cmdline)):
|
- with patch("salt.utils.files.fopen", mock_open(read_data=cmdline)):
|
||||||
- self.assertEqual(core.kernelparams(), expectation)
|
- self.assertEqual(core.kernelparams(), expectation)
|
||||||
-
|
-
|
||||||
- @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
|
- @skipIf(not salt.utils.platform.is_linux(), "System is not Linux")
|
||||||
- @patch('os.path.exists')
|
- @patch("os.path.exists")
|
||||||
- @patch('salt.utils.platform.is_proxy')
|
- @patch("salt.utils.platform.is_proxy")
|
||||||
- def test__hw_data_linux_empty(self, is_proxy, exists):
|
- def test__hw_data_linux_empty(self, is_proxy, exists):
|
||||||
- is_proxy.return_value = False
|
- is_proxy.return_value = False
|
||||||
- exists.return_value = True
|
- exists.return_value = True
|
||||||
- with patch('salt.utils.files.fopen', mock_open(read_data='')):
|
- with patch("salt.utils.files.fopen", mock_open(read_data="")):
|
||||||
- self.assertEqual(core._hw_data({'kernel': 'Linux'}), {
|
- self.assertEqual(
|
||||||
- 'biosreleasedate': '',
|
- core._hw_data({"kernel": "Linux"}),
|
||||||
- 'biosversion': '',
|
- {
|
||||||
- 'manufacturer': '',
|
- "biosreleasedate": "",
|
||||||
- 'productname': '',
|
- "biosversion": "",
|
||||||
- 'serialnumber': '',
|
- "manufacturer": "",
|
||||||
- 'uuid': ''
|
- "productname": "",
|
||||||
- })
|
- "serialnumber": "",
|
||||||
|
- "uuid": "",
|
||||||
|
- },
|
||||||
|
- )
|
||||||
-
|
-
|
||||||
@skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
|
@skipIf(not salt.utils.platform.is_linux(), "System is not Linux")
|
||||||
@skipIf(six.PY2, 'UnicodeDecodeError is throw in Python 3')
|
@skipIf(six.PY2, "UnicodeDecodeError is throw in Python 3")
|
||||||
@patch('os.path.exists')
|
@patch("os.path.exists")
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,40 +1,41 @@
|
|||||||
From c2989e749f04aa8477130df649e550f5349a9a1f Mon Sep 17 00:00:00 2001
|
From 5dadda6822323f409c99112244c2c809e58126e1 Mon Sep 17 00:00:00 2001
|
||||||
From: Mihai Dinca <mdinca@suse.de>
|
From: Mihai Dinca <mdinca@suse.de>
|
||||||
Date: Wed, 31 Jul 2019 15:29:03 +0200
|
Date: Wed, 31 Jul 2019 15:29:03 +0200
|
||||||
Subject: [PATCH] Fix aptpkg systemd call (bsc#1143301)
|
Subject: [PATCH] Fix aptpkg systemd call (bsc#1143301)
|
||||||
|
|
||||||
---
|
---
|
||||||
salt/modules/aptpkg.py | 2 +-
|
salt/modules/aptpkg.py | 2 +-
|
||||||
tests/unit/modules/test_aptpkg.py | 2 +-
|
tests/unit/modules/test_aptpkg.py | 3 +--
|
||||||
2 files changed, 2 insertions(+), 2 deletions(-)
|
2 files changed, 2 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/modules/aptpkg.py b/salt/modules/aptpkg.py
|
diff --git a/salt/modules/aptpkg.py b/salt/modules/aptpkg.py
|
||||||
index 13484c96bc..a5b039fc79 100644
|
index bf90d0614f..c47ee852f4 100644
|
||||||
--- a/salt/modules/aptpkg.py
|
--- a/salt/modules/aptpkg.py
|
||||||
+++ b/salt/modules/aptpkg.py
|
+++ b/salt/modules/aptpkg.py
|
||||||
@@ -168,7 +168,7 @@ def _call_apt(args, scope=True, **kwargs):
|
@@ -160,7 +160,7 @@ def _call_apt(args, scope=True, **kwargs):
|
||||||
'''
|
and salt.utils.systemd.has_scope(__context__)
|
||||||
cmd = []
|
and __salt__["config.get"]("systemd.scope", True)
|
||||||
if scope and salt.utils.systemd.has_scope(__context__) and __salt__['config.get']('systemd.scope', True):
|
):
|
||||||
- cmd.extend(['systemd-run', '--scope'])
|
- cmd.extend(["systemd-run", "--scope", "--description", '"{}"'.format(__name__)])
|
||||||
+ cmd.extend(['systemd-run', '--scope', '--description "{0}"'.format(__name__)])
|
+ cmd.extend(["systemd-run", "--scope", '--description "{}"'.format(__name__)])
|
||||||
cmd.extend(args)
|
cmd.extend(args)
|
||||||
|
|
||||||
params = {'output_loglevel': 'trace',
|
params = {
|
||||||
diff --git a/tests/unit/modules/test_aptpkg.py b/tests/unit/modules/test_aptpkg.py
|
diff --git a/tests/unit/modules/test_aptpkg.py b/tests/unit/modules/test_aptpkg.py
|
||||||
index 10e960f090..88eed062c4 100644
|
index 77d8b84896..c3769a7df1 100644
|
||||||
--- a/tests/unit/modules/test_aptpkg.py
|
--- a/tests/unit/modules/test_aptpkg.py
|
||||||
+++ b/tests/unit/modules/test_aptpkg.py
|
+++ b/tests/unit/modules/test_aptpkg.py
|
||||||
@@ -645,7 +645,7 @@ class AptUtilsTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -896,8 +896,7 @@ class AptUtilsTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
with patch.dict(aptpkg.__salt__, {'cmd.run_all': MagicMock(), 'config.get': MagicMock(return_value=True)}):
|
[
|
||||||
aptpkg._call_apt(['apt-get', 'purge', 'vim']) # pylint: disable=W0106
|
"systemd-run",
|
||||||
aptpkg.__salt__['cmd.run_all'].assert_called_once_with(
|
"--scope",
|
||||||
- ['systemd-run', '--scope', 'apt-get', 'purge', 'vim'], env={},
|
- "--description",
|
||||||
+ ['systemd-run', '--scope', '--description "salt.modules.aptpkg"', 'apt-get', 'purge', 'vim'], env={},
|
- '"salt.modules.aptpkg"',
|
||||||
output_loglevel='trace', python_shell=False)
|
+ '--description "salt.modules.aptpkg"',
|
||||||
|
"apt-get",
|
||||||
def test_call_apt_with_kwargs(self):
|
"purge",
|
||||||
|
"vim",
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
42
fix-aptpkg.normalize_name-when-package-arch-is-all.patch
Normal file
42
fix-aptpkg.normalize_name-when-package-arch-is-all.patch
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
From 763d63b72b9a20f22555b665033899e10f091b60 Mon Sep 17 00:00:00 2001
|
||||||
|
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||||
|
<psuarezhernandez@suse.com>
|
||||||
|
Date: Mon, 11 Jan 2021 15:45:28 +0000
|
||||||
|
Subject: [PATCH] Fix aptpkg.normalize_name when package arch is 'all'
|
||||||
|
|
||||||
|
Add test case of DEB package where arch is 'all'
|
||||||
|
---
|
||||||
|
salt/modules/aptpkg.py | 2 +-
|
||||||
|
tests/unit/modules/test_aptpkg.py | 2 ++
|
||||||
|
2 files changed, 3 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/salt/modules/aptpkg.py b/salt/modules/aptpkg.py
|
||||||
|
index e001d2f11c..03e99af733 100644
|
||||||
|
--- a/salt/modules/aptpkg.py
|
||||||
|
+++ b/salt/modules/aptpkg.py
|
||||||
|
@@ -208,7 +208,7 @@ def normalize_name(name):
|
||||||
|
pkgname = name
|
||||||
|
pkgarch = __grains__["osarch"]
|
||||||
|
|
||||||
|
- return pkgname if pkgarch in (__grains__["osarch"], "any") else name
|
||||||
|
+ return pkgname if pkgarch in (__grains__["osarch"], "all", "any") else name
|
||||||
|
|
||||||
|
|
||||||
|
def parse_arch(name):
|
||||||
|
diff --git a/tests/unit/modules/test_aptpkg.py b/tests/unit/modules/test_aptpkg.py
|
||||||
|
index 51dfce29eb..eb3f9e2da7 100644
|
||||||
|
--- a/tests/unit/modules/test_aptpkg.py
|
||||||
|
+++ b/tests/unit/modules/test_aptpkg.py
|
||||||
|
@@ -808,6 +808,8 @@ class AptPkgTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
|
assert result == "foo", result
|
||||||
|
result = aptpkg.normalize_name("foo:any")
|
||||||
|
assert result == "foo", result
|
||||||
|
+ result = aptpkg.normalize_name("foo:all")
|
||||||
|
+ assert result == "foo", result
|
||||||
|
result = aptpkg.normalize_name("foo:i386")
|
||||||
|
assert result == "foo:i386", result
|
||||||
|
|
||||||
|
--
|
||||||
|
2.29.2
|
||||||
|
|
||||||
|
|
@ -1,55 +1,57 @@
|
|||||||
From 42d7e1de2c69d82447e73eab483e5d3c299d55f7 Mon Sep 17 00:00:00 2001
|
From 85b8666b138cab170327f0217c799277371b2e80 Mon Sep 17 00:00:00 2001
|
||||||
From: Mihai Dinca <mdinca@suse.de>
|
From: Mihai Dinca <mdinca@suse.de>
|
||||||
Date: Tue, 7 May 2019 12:24:35 +0200
|
Date: Tue, 7 May 2019 12:24:35 +0200
|
||||||
Subject: [PATCH] Fix async-batch multiple done events
|
Subject: [PATCH] Fix async-batch multiple done events
|
||||||
|
|
||||||
---
|
---
|
||||||
salt/cli/batch_async.py | 17 ++++++++++++-----
|
salt/cli/batch_async.py | 19 ++++++++++++-------
|
||||||
tests/unit/cli/test_batch_async.py | 20 +++++++++++++-------
|
tests/unit/cli/test_batch_async.py | 20 +++++++++++++-------
|
||||||
2 files changed, 25 insertions(+), 12 deletions(-)
|
2 files changed, 25 insertions(+), 14 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/cli/batch_async.py b/salt/cli/batch_async.py
|
diff --git a/salt/cli/batch_async.py b/salt/cli/batch_async.py
|
||||||
index 9c20b2fc6e..8c8f481e34 100644
|
index b0ab9d9f47..7225491228 100644
|
||||||
--- a/salt/cli/batch_async.py
|
--- a/salt/cli/batch_async.py
|
||||||
+++ b/salt/cli/batch_async.py
|
+++ b/salt/cli/batch_async.py
|
||||||
@@ -84,6 +84,7 @@ class BatchAsync(object):
|
@@ -86,6 +86,7 @@ class BatchAsync:
|
||||||
listen=True,
|
|
||||||
io_loop=ioloop,
|
io_loop=ioloop,
|
||||||
keep_loop=True)
|
keep_loop=True,
|
||||||
|
)
|
||||||
+ self.scheduled = False
|
+ self.scheduled = False
|
||||||
|
|
||||||
def __set_event_handler(self):
|
def __set_event_handler(self):
|
||||||
ping_return_pattern = 'salt/job/{0}/ret/*'.format(self.ping_jid)
|
ping_return_pattern = "salt/job/{}/ret/*".format(self.ping_jid)
|
||||||
@@ -116,8 +117,7 @@ class BatchAsync(object):
|
@@ -118,10 +119,7 @@ class BatchAsync:
|
||||||
if minion in self.active:
|
if minion in self.active:
|
||||||
self.active.remove(minion)
|
self.active.remove(minion)
|
||||||
self.done_minions.add(minion)
|
self.done_minions.add(minion)
|
||||||
- # call later so that we maybe gather more returns
|
- # call later so that we maybe gather more returns
|
||||||
- self.event.io_loop.call_later(self.batch_delay, self.schedule_next)
|
- self.event.io_loop.call_later(
|
||||||
|
- self.batch_delay, self.schedule_next
|
||||||
|
- )
|
||||||
+ self.schedule_next()
|
+ self.schedule_next()
|
||||||
|
|
||||||
def _get_next(self):
|
def _get_next(self):
|
||||||
to_run = self.minions.difference(
|
to_run = (
|
||||||
@@ -137,7 +137,7 @@ class BatchAsync(object):
|
@@ -146,7 +144,7 @@ class BatchAsync:
|
||||||
self.active = self.active.difference(self.timedout_minions)
|
self.timedout_minions
|
||||||
running = batch_minions.difference(self.done_minions).difference(self.timedout_minions)
|
)
|
||||||
if timedout_minions:
|
if timedout_minions:
|
||||||
- self.event.io_loop.call_later(self.batch_delay, self.schedule_next)
|
- self.event.io_loop.call_later(self.batch_delay, self.schedule_next)
|
||||||
+ self.schedule_next()
|
+ self.schedule_next()
|
||||||
if running:
|
if running:
|
||||||
self.event.io_loop.add_callback(self.find_job, running)
|
self.event.io_loop.add_callback(self.find_job, running)
|
||||||
|
|
||||||
@@ -189,7 +189,7 @@ class BatchAsync(object):
|
@@ -197,7 +195,7 @@ class BatchAsync:
|
||||||
"metadata": self.metadata
|
"metadata": self.metadata,
|
||||||
}
|
}
|
||||||
self.event.fire_event(data, "salt/batch/{0}/start".format(self.batch_jid))
|
self.event.fire_event(data, "salt/batch/{}/start".format(self.batch_jid))
|
||||||
- yield self.schedule_next()
|
- yield self.schedule_next()
|
||||||
+ yield self.run_next()
|
+ yield self.run_next()
|
||||||
|
|
||||||
def end_batch(self):
|
def end_batch(self):
|
||||||
left = self.minions.symmetric_difference(self.done_minions.union(self.timedout_minions))
|
left = self.minions.symmetric_difference(
|
||||||
@@ -204,8 +204,14 @@ class BatchAsync(object):
|
@@ -214,8 +212,14 @@ class BatchAsync:
|
||||||
self.event.fire_event(data, "salt/batch/{0}/done".format(self.batch_jid))
|
self.event.fire_event(data, "salt/batch/{}/done".format(self.batch_jid))
|
||||||
self.event.remove_event_handler(self.__event_handler)
|
self.event.remove_event_handler(self.__event_handler)
|
||||||
|
|
||||||
- @tornado.gen.coroutine
|
- @tornado.gen.coroutine
|
||||||
@ -64,16 +66,16 @@ index 9c20b2fc6e..8c8f481e34 100644
|
|||||||
next_batch = self._get_next()
|
next_batch = self._get_next()
|
||||||
if next_batch:
|
if next_batch:
|
||||||
self.active = self.active.union(next_batch)
|
self.active = self.active.union(next_batch)
|
||||||
@@ -225,3 +231,4 @@ class BatchAsync(object):
|
@@ -238,3 +242,4 @@ class BatchAsync:
|
||||||
self.active = self.active.difference(next_batch)
|
self.active = self.active.difference(next_batch)
|
||||||
else:
|
else:
|
||||||
self.end_batch()
|
self.end_batch()
|
||||||
+ self.scheduled = False
|
+ self.scheduled = False
|
||||||
diff --git a/tests/unit/cli/test_batch_async.py b/tests/unit/cli/test_batch_async.py
|
diff --git a/tests/unit/cli/test_batch_async.py b/tests/unit/cli/test_batch_async.py
|
||||||
index d519157d92..441f9c58b9 100644
|
index d6a4bfcf60..66332a548a 100644
|
||||||
--- a/tests/unit/cli/test_batch_async.py
|
--- a/tests/unit/cli/test_batch_async.py
|
||||||
+++ b/tests/unit/cli/test_batch_async.py
|
+++ b/tests/unit/cli/test_batch_async.py
|
||||||
@@ -111,14 +111,14 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
@@ -105,14 +105,14 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
||||||
|
|
||||||
@tornado.testing.gen_test
|
@tornado.testing.gen_test
|
||||||
def test_start_batch_calls_next(self):
|
def test_start_batch_calls_next(self):
|
||||||
@ -90,27 +92,27 @@ index d519157d92..441f9c58b9 100644
|
|||||||
+ self.assertEqual(len(self.batch.run_next.mock_calls), 1)
|
+ self.assertEqual(len(self.batch.run_next.mock_calls), 1)
|
||||||
|
|
||||||
def test_batch_fire_done_event(self):
|
def test_batch_fire_done_event(self):
|
||||||
self.batch.targeted_minions = {'foo', 'baz', 'bar'}
|
self.batch.targeted_minions = {"foo", "baz", "bar"}
|
||||||
@@ -154,7 +154,7 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
@@ -147,7 +147,7 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
||||||
future = tornado.gen.Future()
|
future = tornado.gen.Future()
|
||||||
future.set_result({'minions': ['foo', 'bar']})
|
future.set_result({"minions": ["foo", "bar"]})
|
||||||
self.batch.local.run_job_async.return_value = future
|
self.batch.local.run_job_async.return_value = future
|
||||||
- ret = self.batch.schedule_next().result()
|
- ret = self.batch.schedule_next().result()
|
||||||
+ ret = self.batch.run_next().result()
|
+ ret = self.batch.run_next().result()
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.batch.local.run_job_async.call_args[0],
|
self.batch.local.run_job_async.call_args[0],
|
||||||
({'foo', 'bar'}, 'my.fun', [], 'list')
|
({"foo", "bar"}, "my.fun", [], "list"),
|
||||||
@@ -253,7 +253,7 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
@@ -250,7 +250,7 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
||||||
self.assertEqual(self.batch.done_minions, {'foo'})
|
self.assertEqual(self.batch.done_minions, {"foo"})
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.batch.event.io_loop.call_later.call_args[0],
|
self.batch.event.io_loop.call_later.call_args[0],
|
||||||
- (self.batch.batch_delay, self.batch.schedule_next))
|
- (self.batch.batch_delay, self.batch.schedule_next),
|
||||||
+ (self.batch.batch_delay, self.batch.run_next))
|
+ (self.batch.batch_delay, self.batch.run_next),
|
||||||
|
)
|
||||||
|
|
||||||
def test_batch__event_handler_find_job_return(self):
|
def test_batch__event_handler_find_job_return(self):
|
||||||
self.batch.event = MagicMock(
|
@@ -262,10 +262,10 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
||||||
@@ -263,10 +263,10 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
self.assertEqual(self.batch.find_job_returned, {"foo"})
|
||||||
self.assertEqual(self.batch.find_job_returned, {'foo'})
|
|
||||||
|
|
||||||
@tornado.testing.gen_test
|
@tornado.testing.gen_test
|
||||||
- def test_batch_schedule_next_end_batch_when_no_next(self):
|
- def test_batch_schedule_next_end_batch_when_no_next(self):
|
||||||
@ -122,9 +124,9 @@ index d519157d92..441f9c58b9 100644
|
|||||||
self.assertEqual(len(self.batch.end_batch.mock_calls), 1)
|
self.assertEqual(len(self.batch.end_batch.mock_calls), 1)
|
||||||
|
|
||||||
@tornado.testing.gen_test
|
@tornado.testing.gen_test
|
||||||
@@ -342,3 +342,9 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
@@ -345,3 +345,9 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
||||||
self.batch.event.io_loop.add_callback.call_args[0],
|
self.batch.event.io_loop.add_callback.call_args[0],
|
||||||
(self.batch.find_job, {'foo'})
|
(self.batch.find_job, {"foo"}),
|
||||||
)
|
)
|
||||||
+
|
+
|
||||||
+ def test_only_on_run_next_is_scheduled(self):
|
+ def test_only_on_run_next_is_scheduled(self):
|
||||||
@ -133,6 +135,6 @@ index d519157d92..441f9c58b9 100644
|
|||||||
+ self.batch.schedule_next()
|
+ self.batch.schedule_next()
|
||||||
+ self.assertEqual(len(self.batch.event.io_loop.call_later.mock_calls), 0)
|
+ self.assertEqual(len(self.batch.event.io_loop.call_later.mock_calls), 0)
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
From dc001cb47fd88a8e8a1bd82a1457325822d1220b Mon Sep 17 00:00:00 2001
|
From 4b3badeb52a9de10d6085ee3cc7598a827d1e68f Mon Sep 17 00:00:00 2001
|
||||||
From: Mihai Dinca <mdinca@suse.de>
|
From: Mihai Dinca <mdinca@suse.de>
|
||||||
Date: Thu, 11 Apr 2019 15:57:59 +0200
|
Date: Thu, 11 Apr 2019 15:57:59 +0200
|
||||||
Subject: [PATCH] Fix async batch race conditions
|
Subject: [PATCH] Fix async batch race conditions
|
||||||
|
|
||||||
Close batching when there is no next batch
|
Close batching when there is no next batch
|
||||||
---
|
---
|
||||||
salt/cli/batch_async.py | 80 +++++++++++++++++++-------------------
|
salt/cli/batch_async.py | 96 +++++++++++++++---------------
|
||||||
tests/unit/cli/test_batch_async.py | 35 +++++++----------
|
tests/unit/cli/test_batch_async.py | 38 +++++-------
|
||||||
2 files changed, 54 insertions(+), 61 deletions(-)
|
2 files changed, 62 insertions(+), 72 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/cli/batch_async.py b/salt/cli/batch_async.py
|
diff --git a/salt/cli/batch_async.py b/salt/cli/batch_async.py
|
||||||
index 3160d46d8b..9c20b2fc6e 100644
|
index 1557e5105b..b0ab9d9f47 100644
|
||||||
--- a/salt/cli/batch_async.py
|
--- a/salt/cli/batch_async.py
|
||||||
+++ b/salt/cli/batch_async.py
|
+++ b/salt/cli/batch_async.py
|
||||||
@@ -37,14 +37,14 @@ class BatchAsync(object):
|
@@ -32,14 +32,14 @@ class BatchAsync:
|
||||||
- tag: salt/batch/<batch-jid>/start
|
- tag: salt/batch/<batch-jid>/start
|
||||||
- data: {
|
- data: {
|
||||||
"available_minions": self.minions,
|
"available_minions": self.minions,
|
||||||
@ -30,36 +30,38 @@ index 3160d46d8b..9c20b2fc6e 100644
|
|||||||
"done_minions": self.done_minions,
|
"done_minions": self.done_minions,
|
||||||
"timedout_minions": self.timedout_minions
|
"timedout_minions": self.timedout_minions
|
||||||
}
|
}
|
||||||
@@ -67,7 +67,7 @@ class BatchAsync(object):
|
@@ -68,7 +68,7 @@ class BatchAsync:
|
||||||
self.eauth = batch_get_eauth(clear_load['kwargs'])
|
self.eauth = batch_get_eauth(clear_load["kwargs"])
|
||||||
self.metadata = clear_load['kwargs'].get('metadata', {})
|
self.metadata = clear_load["kwargs"].get("metadata", {})
|
||||||
self.minions = set()
|
self.minions = set()
|
||||||
- self.down_minions = set()
|
- self.down_minions = set()
|
||||||
+ self.targeted_minions = set()
|
+ self.targeted_minions = set()
|
||||||
self.timedout_minions = set()
|
self.timedout_minions = set()
|
||||||
self.done_minions = set()
|
self.done_minions = set()
|
||||||
self.active = set()
|
self.active = set()
|
||||||
@@ -108,8 +108,7 @@ class BatchAsync(object):
|
@@ -110,8 +110,7 @@ class BatchAsync:
|
||||||
minion = data['id']
|
minion = data["id"]
|
||||||
if op == 'ping_return':
|
if op == "ping_return":
|
||||||
self.minions.add(minion)
|
self.minions.add(minion)
|
||||||
- self.down_minions.remove(minion)
|
- self.down_minions.remove(minion)
|
||||||
- if not self.down_minions:
|
- if not self.down_minions:
|
||||||
+ if self.targeted_minions == self.minions:
|
+ if self.targeted_minions == self.minions:
|
||||||
self.event.io_loop.spawn_callback(self.start_batch)
|
self.event.io_loop.spawn_callback(self.start_batch)
|
||||||
elif op == 'find_job_return':
|
elif op == "find_job_return":
|
||||||
self.find_job_returned.add(minion)
|
self.find_job_returned.add(minion)
|
||||||
@@ -120,9 +119,6 @@ class BatchAsync(object):
|
@@ -124,11 +123,6 @@ class BatchAsync:
|
||||||
# call later so that we maybe gather more returns
|
self.batch_delay, self.schedule_next
|
||||||
self.event.io_loop.call_later(self.batch_delay, self.schedule_next)
|
)
|
||||||
|
|
||||||
- if self.initialized and self.done_minions == self.minions.difference(self.timedout_minions):
|
- if self.initialized and self.done_minions == self.minions.difference(
|
||||||
|
- self.timedout_minions
|
||||||
|
- ):
|
||||||
- self.end_batch()
|
- self.end_batch()
|
||||||
-
|
-
|
||||||
def _get_next(self):
|
def _get_next(self):
|
||||||
to_run = self.minions.difference(
|
to_run = (
|
||||||
self.done_minions).difference(
|
self.minions.difference(self.done_minions)
|
||||||
@@ -135,16 +131,13 @@ class BatchAsync(object):
|
@@ -142,20 +136,17 @@ class BatchAsync:
|
||||||
return set(list(to_run)[:next_batch_size])
|
return set(list(to_run)[:next_batch_size])
|
||||||
|
|
||||||
@tornado.gen.coroutine
|
@tornado.gen.coroutine
|
||||||
@ -72,35 +74,42 @@ index 3160d46d8b..9c20b2fc6e 100644
|
|||||||
- if minion in self.active:
|
- if minion in self.active:
|
||||||
- self.active.remove(minion)
|
- self.active.remove(minion)
|
||||||
- self.timedout_minions.add(minion)
|
- self.timedout_minions.add(minion)
|
||||||
- running = minions.difference(did_not_return).difference(self.done_minions).difference(self.timedout_minions)
|
- running = (
|
||||||
|
- minions.difference(did_not_return)
|
||||||
|
- .difference(self.done_minions)
|
||||||
|
- .difference(self.timedout_minions)
|
||||||
+ def check_find_job(self, batch_minions):
|
+ def check_find_job(self, batch_minions):
|
||||||
+ timedout_minions = batch_minions.difference(self.find_job_returned).difference(self.done_minions)
|
+ timedout_minions = batch_minions.difference(self.find_job_returned).difference(
|
||||||
|
+ self.done_minions
|
||||||
|
)
|
||||||
+ self.timedout_minions = self.timedout_minions.union(timedout_minions)
|
+ self.timedout_minions = self.timedout_minions.union(timedout_minions)
|
||||||
+ self.active = self.active.difference(self.timedout_minions)
|
+ self.active = self.active.difference(self.timedout_minions)
|
||||||
+ running = batch_minions.difference(self.done_minions).difference(self.timedout_minions)
|
+ running = batch_minions.difference(self.done_minions).difference(
|
||||||
|
+ self.timedout_minions
|
||||||
|
+ )
|
||||||
+ if timedout_minions:
|
+ if timedout_minions:
|
||||||
+ self.event.io_loop.call_later(self.batch_delay, self.schedule_next)
|
+ self.event.io_loop.call_later(self.batch_delay, self.schedule_next)
|
||||||
if running:
|
if running:
|
||||||
self.event.io_loop.add_callback(self.find_job, running)
|
self.event.io_loop.add_callback(self.find_job, running)
|
||||||
|
|
||||||
@@ -183,7 +176,7 @@ class BatchAsync(object):
|
@@ -193,7 +184,7 @@ class BatchAsync:
|
||||||
jid=self.ping_jid,
|
|
||||||
metadata=self.metadata,
|
metadata=self.metadata,
|
||||||
**self.eauth)
|
**self.eauth
|
||||||
- self.down_minions = set(ping_return['minions'])
|
)
|
||||||
+ self.targeted_minions = set(ping_return['minions'])
|
- self.down_minions = set(ping_return["minions"])
|
||||||
|
+ self.targeted_minions = set(ping_return["minions"])
|
||||||
|
|
||||||
@tornado.gen.coroutine
|
@tornado.gen.coroutine
|
||||||
def start_batch(self):
|
def start_batch(self):
|
||||||
@@ -192,36 +185,43 @@ class BatchAsync(object):
|
@@ -202,39 +193,48 @@ class BatchAsync:
|
||||||
self.initialized = True
|
self.initialized = True
|
||||||
data = {
|
data = {
|
||||||
"available_minions": self.minions,
|
"available_minions": self.minions,
|
||||||
- "down_minions": self.down_minions,
|
- "down_minions": self.down_minions,
|
||||||
+ "down_minions": self.targeted_minions.difference(self.minions),
|
+ "down_minions": self.targeted_minions.difference(self.minions),
|
||||||
"metadata": self.metadata
|
"metadata": self.metadata,
|
||||||
}
|
}
|
||||||
self.event.fire_event(data, "salt/batch/{0}/start".format(self.batch_jid))
|
self.event.fire_event(data, "salt/batch/{}/start".format(self.batch_jid))
|
||||||
yield self.schedule_next()
|
yield self.schedule_next()
|
||||||
|
|
||||||
def end_batch(self):
|
def end_batch(self):
|
||||||
@ -109,20 +118,22 @@ index 3160d46d8b..9c20b2fc6e 100644
|
|||||||
- "down_minions": self.down_minions,
|
- "down_minions": self.down_minions,
|
||||||
- "done_minions": self.done_minions,
|
- "done_minions": self.done_minions,
|
||||||
- "timedout_minions": self.timedout_minions,
|
- "timedout_minions": self.timedout_minions,
|
||||||
- "metadata": self.metadata
|
- "metadata": self.metadata,
|
||||||
- }
|
- }
|
||||||
- self.event.fire_event(data, "salt/batch/{0}/done".format(self.batch_jid))
|
- self.event.fire_event(data, "salt/batch/{}/done".format(self.batch_jid))
|
||||||
- self.event.remove_event_handler(self.__event_handler)
|
- self.event.remove_event_handler(self.__event_handler)
|
||||||
+ left = self.minions.symmetric_difference(self.done_minions.union(self.timedout_minions))
|
+ left = self.minions.symmetric_difference(
|
||||||
|
+ self.done_minions.union(self.timedout_minions)
|
||||||
|
+ )
|
||||||
+ if not left:
|
+ if not left:
|
||||||
+ data = {
|
+ data = {
|
||||||
+ "available_minions": self.minions,
|
+ "available_minions": self.minions,
|
||||||
+ "down_minions": self.targeted_minions.difference(self.minions),
|
+ "down_minions": self.targeted_minions.difference(self.minions),
|
||||||
+ "done_minions": self.done_minions,
|
+ "done_minions": self.done_minions,
|
||||||
+ "timedout_minions": self.timedout_minions,
|
+ "timedout_minions": self.timedout_minions,
|
||||||
+ "metadata": self.metadata
|
+ "metadata": self.metadata,
|
||||||
+ }
|
+ }
|
||||||
+ self.event.fire_event(data, "salt/batch/{0}/done".format(self.batch_jid))
|
+ self.event.fire_event(data, "salt/batch/{}/done".format(self.batch_jid))
|
||||||
+ self.event.remove_event_handler(self.__event_handler)
|
+ self.event.remove_event_handler(self.__event_handler)
|
||||||
|
|
||||||
@tornado.gen.coroutine
|
@tornado.gen.coroutine
|
||||||
@ -131,116 +142,125 @@ index 3160d46d8b..9c20b2fc6e 100644
|
|||||||
if next_batch:
|
if next_batch:
|
||||||
- yield self.local.run_job_async(
|
- yield self.local.run_job_async(
|
||||||
- next_batch,
|
- next_batch,
|
||||||
- self.opts['fun'],
|
- self.opts["fun"],
|
||||||
- self.opts['arg'],
|
- self.opts["arg"],
|
||||||
- 'list',
|
- "list",
|
||||||
- raw=self.opts.get('raw', False),
|
- raw=self.opts.get("raw", False),
|
||||||
- ret=self.opts.get('return', ''),
|
- ret=self.opts.get("return", ""),
|
||||||
- gather_job_timeout=self.opts['gather_job_timeout'],
|
- gather_job_timeout=self.opts["gather_job_timeout"],
|
||||||
- jid=self.batch_jid,
|
- jid=self.batch_jid,
|
||||||
- metadata=self.metadata)
|
- metadata=self.metadata,
|
||||||
- self.event.io_loop.call_later(self.opts['timeout'], self.find_job, set(next_batch))
|
- )
|
||||||
|
- self.event.io_loop.call_later(
|
||||||
|
- self.opts["timeout"], self.find_job, set(next_batch)
|
||||||
|
- )
|
||||||
self.active = self.active.union(next_batch)
|
self.active = self.active.union(next_batch)
|
||||||
+ try:
|
+ try:
|
||||||
+ yield self.local.run_job_async(
|
+ yield self.local.run_job_async(
|
||||||
+ next_batch,
|
+ next_batch,
|
||||||
+ self.opts['fun'],
|
+ self.opts["fun"],
|
||||||
+ self.opts['arg'],
|
+ self.opts["arg"],
|
||||||
+ 'list',
|
+ "list",
|
||||||
+ raw=self.opts.get('raw', False),
|
+ raw=self.opts.get("raw", False),
|
||||||
+ ret=self.opts.get('return', ''),
|
+ ret=self.opts.get("return", ""),
|
||||||
+ gather_job_timeout=self.opts['gather_job_timeout'],
|
+ gather_job_timeout=self.opts["gather_job_timeout"],
|
||||||
+ jid=self.batch_jid,
|
+ jid=self.batch_jid,
|
||||||
+ metadata=self.metadata)
|
+ metadata=self.metadata,
|
||||||
+ self.event.io_loop.call_later(self.opts['timeout'], self.find_job, set(next_batch))
|
+ )
|
||||||
|
+ self.event.io_loop.call_later(
|
||||||
|
+ self.opts["timeout"], self.find_job, set(next_batch)
|
||||||
|
+ )
|
||||||
+ except Exception as ex:
|
+ except Exception as ex:
|
||||||
+ self.active = self.active.difference(next_batch)
|
+ self.active = self.active.difference(next_batch)
|
||||||
+ else:
|
+ else:
|
||||||
+ self.end_batch()
|
+ self.end_batch()
|
||||||
diff --git a/tests/unit/cli/test_batch_async.py b/tests/unit/cli/test_batch_async.py
|
diff --git a/tests/unit/cli/test_batch_async.py b/tests/unit/cli/test_batch_async.py
|
||||||
index f65b6a06c3..d519157d92 100644
|
index 3f8626a2dd..d6a4bfcf60 100644
|
||||||
--- a/tests/unit/cli/test_batch_async.py
|
--- a/tests/unit/cli/test_batch_async.py
|
||||||
+++ b/tests/unit/cli/test_batch_async.py
|
+++ b/tests/unit/cli/test_batch_async.py
|
||||||
@@ -75,8 +75,8 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
@@ -68,8 +68,8 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
||||||
self.batch.local.run_job_async.call_args[0],
|
self.assertEqual(
|
||||||
('*', 'test.ping', [], 'glob')
|
self.batch.local.run_job_async.call_args[0], ("*", "test.ping", [], "glob")
|
||||||
)
|
)
|
||||||
- # assert down_minions == all minions matched by tgt
|
- # assert down_minions == all minions matched by tgt
|
||||||
- self.assertEqual(self.batch.down_minions, set(['foo', 'bar']))
|
- self.assertEqual(self.batch.down_minions, {"foo", "bar"})
|
||||||
+ # assert targeted_minions == all minions matched by tgt
|
+ # assert targeted_minions == all minions matched by tgt
|
||||||
+ self.assertEqual(self.batch.targeted_minions, set(['foo', 'bar']))
|
+ self.assertEqual(self.batch.targeted_minions, {"foo", "bar"})
|
||||||
|
|
||||||
@tornado.testing.gen_test
|
@tornado.testing.gen_test
|
||||||
def test_batch_start_on_gather_job_timeout(self):
|
def test_batch_start_on_gather_job_timeout(self):
|
||||||
@@ -121,7 +121,10 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
@@ -115,7 +115,10 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
||||||
self.assertEqual(len(self.batch.schedule_next.mock_calls), 1)
|
self.assertEqual(len(self.batch.schedule_next.mock_calls), 1)
|
||||||
|
|
||||||
def test_batch_fire_done_event(self):
|
def test_batch_fire_done_event(self):
|
||||||
+ self.batch.targeted_minions = {'foo', 'baz', 'bar'}
|
+ self.batch.targeted_minions = {"foo", "baz", "bar"}
|
||||||
self.batch.minions = set(['foo', 'bar'])
|
self.batch.minions = {"foo", "bar"}
|
||||||
+ self.batch.done_minions = {'foo'}
|
+ self.batch.done_minions = {"foo"}
|
||||||
+ self.batch.timedout_minions = {'bar'}
|
+ self.batch.timedout_minions = {"bar"}
|
||||||
self.batch.event = MagicMock()
|
self.batch.event = MagicMock()
|
||||||
self.batch.metadata = {'mykey': 'myvalue'}
|
self.batch.metadata = {"mykey": "myvalue"}
|
||||||
self.batch.end_batch()
|
self.batch.end_batch()
|
||||||
@@ -130,9 +133,9 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
@@ -124,9 +127,9 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
||||||
(
|
(
|
||||||
{
|
{
|
||||||
'available_minions': set(['foo', 'bar']),
|
"available_minions": {"foo", "bar"},
|
||||||
- 'done_minions': set(),
|
- "done_minions": set(),
|
||||||
- 'down_minions': set(),
|
- "down_minions": set(),
|
||||||
- 'timedout_minions': set(),
|
- "timedout_minions": set(),
|
||||||
+ 'done_minions': self.batch.done_minions,
|
+ "done_minions": self.batch.done_minions,
|
||||||
+ 'down_minions': {'baz'},
|
+ "down_minions": {"baz"},
|
||||||
+ 'timedout_minions': self.batch.timedout_minions,
|
+ "timedout_minions": self.batch.timedout_minions,
|
||||||
'metadata': self.batch.metadata
|
"metadata": self.batch.metadata,
|
||||||
},
|
},
|
||||||
"salt/batch/1235/done"
|
"salt/batch/1235/done",
|
||||||
@@ -212,7 +215,7 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
@@ -205,7 +208,7 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
||||||
self.assertEqual(self.batch._get_next(), set())
|
self.assertEqual(self.batch._get_next(), set())
|
||||||
|
|
||||||
def test_batch__event_handler_ping_return(self):
|
def test_batch__event_handler_ping_return(self):
|
||||||
- self.batch.down_minions = {'foo'}
|
- self.batch.down_minions = {"foo"}
|
||||||
+ self.batch.targeted_minions = {'foo'}
|
+ self.batch.targeted_minions = {"foo"}
|
||||||
self.batch.event = MagicMock(
|
self.batch.event = MagicMock(
|
||||||
unpack=MagicMock(return_value=('salt/job/1234/ret/foo', {'id': 'foo'})))
|
unpack=MagicMock(return_value=("salt/job/1234/ret/foo", {"id": "foo"}))
|
||||||
self.batch.start()
|
)
|
||||||
@@ -222,7 +225,7 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
@@ -216,7 +219,7 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
||||||
self.assertEqual(self.batch.done_minions, set())
|
self.assertEqual(self.batch.done_minions, set())
|
||||||
|
|
||||||
def test_batch__event_handler_call_start_batch_when_all_pings_return(self):
|
def test_batch__event_handler_call_start_batch_when_all_pings_return(self):
|
||||||
- self.batch.down_minions = {'foo'}
|
- self.batch.down_minions = {"foo"}
|
||||||
+ self.batch.targeted_minions = {'foo'}
|
+ self.batch.targeted_minions = {"foo"}
|
||||||
self.batch.event = MagicMock(
|
self.batch.event = MagicMock(
|
||||||
unpack=MagicMock(return_value=('salt/job/1234/ret/foo', {'id': 'foo'})))
|
unpack=MagicMock(return_value=("salt/job/1234/ret/foo", {"id": "foo"}))
|
||||||
self.batch.start()
|
)
|
||||||
@@ -232,7 +235,7 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
@@ -228,7 +231,7 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
||||||
(self.batch.start_batch,))
|
)
|
||||||
|
|
||||||
def test_batch__event_handler_not_call_start_batch_when_not_all_pings_return(self):
|
def test_batch__event_handler_not_call_start_batch_when_not_all_pings_return(self):
|
||||||
- self.batch.down_minions = {'foo', 'bar'}
|
- self.batch.down_minions = {"foo", "bar"}
|
||||||
+ self.batch.targeted_minions = {'foo', 'bar'}
|
+ self.batch.targeted_minions = {"foo", "bar"}
|
||||||
self.batch.event = MagicMock(
|
self.batch.event = MagicMock(
|
||||||
unpack=MagicMock(return_value=('salt/job/1234/ret/foo', {'id': 'foo'})))
|
unpack=MagicMock(return_value=("salt/job/1234/ret/foo", {"id": "foo"}))
|
||||||
self.batch.start()
|
)
|
||||||
@@ -260,20 +263,10 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
@@ -259,23 +262,10 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
||||||
self.assertEqual(self.batch.find_job_returned, {'foo'})
|
self.assertEqual(self.batch.find_job_returned, {"foo"})
|
||||||
|
|
||||||
@tornado.testing.gen_test
|
@tornado.testing.gen_test
|
||||||
- def test_batch__event_handler_end_batch(self):
|
- def test_batch__event_handler_end_batch(self):
|
||||||
- self.batch.event = MagicMock(
|
- self.batch.event = MagicMock(
|
||||||
- unpack=MagicMock(return_value=('salt/job/not-my-jid/ret/foo', {'id': 'foo'})))
|
- unpack=MagicMock(
|
||||||
|
- return_value=("salt/job/not-my-jid/ret/foo", {"id": "foo"})
|
||||||
|
- )
|
||||||
|
- )
|
||||||
- future = tornado.gen.Future()
|
- future = tornado.gen.Future()
|
||||||
- future.set_result({'minions': ['foo', 'bar', 'baz']})
|
- future.set_result({"minions": ["foo", "bar", "baz"]})
|
||||||
- self.batch.local.run_job_async.return_value = future
|
- self.batch.local.run_job_async.return_value = future
|
||||||
- self.batch.start()
|
- self.batch.start()
|
||||||
- self.batch.initialized = True
|
- self.batch.initialized = True
|
||||||
- self.assertEqual(self.batch.down_minions, {'foo', 'bar', 'baz'})
|
- self.assertEqual(self.batch.down_minions, {"foo", "bar", "baz"})
|
||||||
+ def test_batch_schedule_next_end_batch_when_no_next(self):
|
+ def test_batch_schedule_next_end_batch_when_no_next(self):
|
||||||
self.batch.end_batch = MagicMock()
|
self.batch.end_batch = MagicMock()
|
||||||
- self.batch.minions = {'foo', 'bar', 'baz'}
|
- self.batch.minions = {"foo", "bar", "baz"}
|
||||||
- self.batch.done_minions = {'foo', 'bar'}
|
- self.batch.done_minions = {"foo", "bar"}
|
||||||
- self.batch.timedout_minions = {'baz'}
|
- self.batch.timedout_minions = {"baz"}
|
||||||
- self.batch._BatchAsync__event_handler(MagicMock())
|
- self.batch._BatchAsync__event_handler(MagicMock())
|
||||||
+ self.batch._get_next = MagicMock(return_value={})
|
+ self.batch._get_next = MagicMock(return_value={})
|
||||||
+ self.batch.schedule_next()
|
+ self.batch.schedule_next()
|
||||||
@ -248,6 +268,6 @@ index f65b6a06c3..d519157d92 100644
|
|||||||
|
|
||||||
@tornado.testing.gen_test
|
@tornado.testing.gen_test
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From 49780d409630fe18293a077e767aabfd183ff823 Mon Sep 17 00:00:00 2001
|
From 5a83801b7733f09c35a7ff0abb5aa32d4c857e4b Mon Sep 17 00:00:00 2001
|
||||||
From: Mihai Dinca <mdinca@suse.de>
|
From: Mihai Dinca <mdinca@suse.de>
|
||||||
Date: Tue, 3 Dec 2019 11:22:42 +0100
|
Date: Tue, 3 Dec 2019 11:22:42 +0100
|
||||||
Subject: [PATCH] Fix batch_async obsolete test
|
Subject: [PATCH] Fix batch_async obsolete test
|
||||||
@ -8,26 +8,25 @@ Subject: [PATCH] Fix batch_async obsolete test
|
|||||||
1 file changed, 7 insertions(+), 1 deletion(-)
|
1 file changed, 7 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
diff --git a/tests/unit/cli/test_batch_async.py b/tests/unit/cli/test_batch_async.py
|
diff --git a/tests/unit/cli/test_batch_async.py b/tests/unit/cli/test_batch_async.py
|
||||||
index 12dfe543bc..f1d36a81fb 100644
|
index c18b42be57..b04965268a 100644
|
||||||
--- a/tests/unit/cli/test_batch_async.py
|
--- a/tests/unit/cli/test_batch_async.py
|
||||||
+++ b/tests/unit/cli/test_batch_async.py
|
+++ b/tests/unit/cli/test_batch_async.py
|
||||||
@@ -140,8 +140,14 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
@@ -134,7 +134,13 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
||||||
"salt/batch/1235/done"
|
"salt/batch/1235/done",
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
|
- self.assertEqual(len(self.batch.event.remove_event_handler.mock_calls), 1)
|
||||||
+
|
+
|
||||||
+ def test_batch__del__(self):
|
+ def test_batch__del__(self):
|
||||||
+ batch = BatchAsync(MagicMock(), MagicMock(), MagicMock())
|
+ batch = BatchAsync(MagicMock(), MagicMock(), MagicMock())
|
||||||
+ event = MagicMock()
|
+ event = MagicMock()
|
||||||
+ batch.event = event
|
+ batch.event = event
|
||||||
+ batch.__del__()
|
+ batch.__del__()
|
||||||
self.assertEqual(
|
+ self.assertEqual(len(event.remove_event_handler.mock_calls), 1)
|
||||||
- len(self.batch.event.remove_event_handler.mock_calls), 1)
|
|
||||||
+ len(event.remove_event_handler.mock_calls), 1)
|
|
||||||
|
|
||||||
@tornado.testing.gen_test
|
@tornado.testing.gen_test
|
||||||
def test_batch_next(self):
|
def test_batch_next(self):
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,25 +1,42 @@
|
|||||||
From 4acbe70851e3ef7a04fc5ad0dc9a2519f6989c66 Mon Sep 17 00:00:00 2001
|
From 1b9a160f578cf446f5ae622a450d23022e7e3ca5 Mon Sep 17 00:00:00 2001
|
||||||
From: Bo Maryniuk <bo@suse.de>
|
From: Bo Maryniuk <bo@suse.de>
|
||||||
Date: Thu, 14 Dec 2017 16:21:40 +0100
|
Date: Thu, 14 Dec 2017 16:21:40 +0100
|
||||||
Subject: [PATCH] Fix bsc#1065792
|
Subject: [PATCH] Fix bsc#1065792
|
||||||
|
|
||||||
---
|
---
|
||||||
salt/states/service.py | 1 +
|
salt/states/service.py | 5 +----
|
||||||
1 file changed, 1 insertion(+)
|
1 file changed, 1 insertion(+), 4 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/states/service.py b/salt/states/service.py
|
diff --git a/salt/states/service.py b/salt/states/service.py
|
||||||
index de7718ea49..987e37cd42 100644
|
index d19c245756..4ea36a78f6 100644
|
||||||
--- a/salt/states/service.py
|
--- a/salt/states/service.py
|
||||||
+++ b/salt/states/service.py
|
+++ b/salt/states/service.py
|
||||||
@@ -80,6 +80,7 @@ def __virtual__():
|
@@ -56,16 +56,12 @@ set the reload value to True:
|
||||||
|
:ref:`Requisites <requisites>` documentation.
|
||||||
|
|
||||||
|
"""
|
||||||
|
-# Import Python libs
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
-# Import Salt libs
|
||||||
|
import salt.utils.data
|
||||||
|
import salt.utils.platform
|
||||||
|
from salt.exceptions import CommandExecutionError
|
||||||
|
-
|
||||||
|
-# Import 3rd-party libs
|
||||||
|
from salt.utils.args import get_function_argspec as _argspec
|
||||||
|
from salt.utils.systemd import booted
|
||||||
|
|
||||||
|
@@ -79,6 +75,7 @@ def __virtual__():
|
||||||
Only make these states available if a service provider has been detected or
|
Only make these states available if a service provider has been detected or
|
||||||
assigned for this minion
|
assigned for this minion
|
||||||
'''
|
"""
|
||||||
+ __salt__._load_all()
|
+ __salt__._load_all()
|
||||||
if 'service.start' in __salt__:
|
if "service.start" in __salt__:
|
||||||
return __virtualname__
|
return __virtualname__
|
||||||
else:
|
else:
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From e7514afcba4f57c5cb8599f561fcefdcc3db7314 Mon Sep 17 00:00:00 2001
|
From bc7acab857b952353a959339b06c79d851a9d879 Mon Sep 17 00:00:00 2001
|
||||||
From: "Daniel A. Wozniak" <dwozniak@saltstack.com>
|
From: "Daniel A. Wozniak" <dwozniak@saltstack.com>
|
||||||
Date: Wed, 16 Sep 2020 00:25:10 +0000
|
Date: Wed, 16 Sep 2020 00:25:10 +0000
|
||||||
Subject: [PATCH] Fix CVE-2020-25592 and add tests (bsc#1178319)
|
Subject: [PATCH] Fix CVE-2020-25592 and add tests (bsc#1178319)
|
||||||
@ -7,184 +7,17 @@ Properly validate eauth credentials and tokens on SSH calls made by Salt API
|
|||||||
|
|
||||||
(bsc#1178319) (bsc#1178362) (bsc#1178361) (CVE-2020-25592) (CVE-2020-17490) (CVE-2020-16846)
|
(bsc#1178319) (bsc#1178362) (bsc#1178361) (CVE-2020-25592) (CVE-2020-17490) (CVE-2020-16846)
|
||||||
---
|
---
|
||||||
salt/client/ssh/shell.py | 26 ++-
|
salt/netapi/__init__.py | 43 +++++++++++++++++++++++++
|
||||||
salt/modules/tls.py | 18 +-
|
tests/integration/netapi/test_client.py | 13 ++++++--
|
||||||
salt/netapi/__init__.py | 67 ++++++
|
2 files changed, 53 insertions(+), 3 deletions(-)
|
||||||
tests/integration/netapi/test_client.py | 296 +++++++++++++++++++++++-
|
|
||||||
4 files changed, 388 insertions(+), 19 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/salt/client/ssh/shell.py b/salt/client/ssh/shell.py
|
|
||||||
index bd55c514ee..27aba7b382 100644
|
|
||||||
--- a/salt/client/ssh/shell.py
|
|
||||||
+++ b/salt/client/ssh/shell.py
|
|
||||||
@@ -8,6 +8,7 @@ from __future__ import absolute_import, print_function, unicode_literals
|
|
||||||
import re
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
+import shlex
|
|
||||||
import time
|
|
||||||
import logging
|
|
||||||
import subprocess
|
|
||||||
@@ -43,10 +44,10 @@ def gen_key(path):
|
|
||||||
'''
|
|
||||||
Generate a key for use with salt-ssh
|
|
||||||
'''
|
|
||||||
- cmd = 'ssh-keygen -P "" -f {0} -t rsa -q'.format(path)
|
|
||||||
+ cmd = ["ssh-keygen", "-P", '""', "-f", path, "-t", "rsa", "-q"]
|
|
||||||
if not os.path.isdir(os.path.dirname(path)):
|
|
||||||
os.makedirs(os.path.dirname(path))
|
|
||||||
- subprocess.call(cmd, shell=True)
|
|
||||||
+ subprocess.call(cmd)
|
|
||||||
|
|
||||||
|
|
||||||
def gen_shell(opts, **kwargs):
|
|
||||||
@@ -289,8 +290,7 @@ class Shell(object):
|
|
||||||
'''
|
|
||||||
try:
|
|
||||||
proc = salt.utils.nb_popen.NonBlockingPopen(
|
|
||||||
- cmd,
|
|
||||||
- shell=True,
|
|
||||||
+ self._split_cmd(cmd),
|
|
||||||
stderr=subprocess.PIPE,
|
|
||||||
stdout=subprocess.PIPE,
|
|
||||||
)
|
|
||||||
@@ -369,6 +369,21 @@ class Shell(object):
|
|
||||||
|
|
||||||
return self._run_cmd(cmd)
|
|
||||||
|
|
||||||
+ def _split_cmd(self, cmd):
|
|
||||||
+ """
|
|
||||||
+ Split a command string so that it is suitable to pass to Popen without
|
|
||||||
+ shell=True. This prevents shell injection attacks in the options passed
|
|
||||||
+ to ssh or some other command.
|
|
||||||
+ """
|
|
||||||
+ try:
|
|
||||||
+ ssh_part, cmd_part = cmd.split("/bin/sh")
|
|
||||||
+ except ValueError:
|
|
||||||
+ cmd_lst = shlex.split(cmd)
|
|
||||||
+ else:
|
|
||||||
+ cmd_lst = shlex.split(ssh_part)
|
|
||||||
+ cmd_lst.append("/bin/sh {}".format(cmd_part))
|
|
||||||
+ return cmd_lst
|
|
||||||
+
|
|
||||||
def _run_cmd(self, cmd, key_accept=False, passwd_retries=3):
|
|
||||||
'''
|
|
||||||
Execute a shell command via VT. This is blocking and assumes that ssh
|
|
||||||
@@ -378,8 +393,7 @@ class Shell(object):
|
|
||||||
return '', 'No command or passphrase', 245
|
|
||||||
|
|
||||||
term = salt.utils.vt.Terminal(
|
|
||||||
- cmd,
|
|
||||||
- shell=True,
|
|
||||||
+ self._split_cmd(cmd),
|
|
||||||
log_stdout=True,
|
|
||||||
log_stdout_level='trace',
|
|
||||||
log_stderr=True,
|
|
||||||
diff --git a/salt/modules/tls.py b/salt/modules/tls.py
|
|
||||||
index af845621a3..116b5fe379 100644
|
|
||||||
--- a/salt/modules/tls.py
|
|
||||||
+++ b/salt/modules/tls.py
|
|
||||||
@@ -798,12 +798,13 @@ def create_ca(ca_name,
|
|
||||||
if old_key.strip() == keycontent.strip():
|
|
||||||
write_key = False
|
|
||||||
else:
|
|
||||||
- log.info('Saving old CA ssl key in %s', bck)
|
|
||||||
- with salt.utils.files.fopen(bck, 'w') as bckf:
|
|
||||||
+ log.info('Saving old CA ssl key in {0}'.format(bck))
|
|
||||||
+ fp = os.open(bck, os.O_CREAT | os.O_RDWR, 0o600)
|
|
||||||
+ with os.fdopen(fp, 'w') as bckf:
|
|
||||||
bckf.write(old_key)
|
|
||||||
- os.chmod(bck, 0o600)
|
|
||||||
if write_key:
|
|
||||||
- with salt.utils.files.fopen(ca_keyp, 'wb') as ca_key:
|
|
||||||
+ fp = os.open(ca_keyp, os.O_CREAT | os.O_RDWR, 0o600)
|
|
||||||
+ with os.fdopen(fp, 'wb') as ca_key:
|
|
||||||
ca_key.write(salt.utils.stringutils.to_bytes(keycontent))
|
|
||||||
|
|
||||||
with salt.utils.files.fopen(certp, 'wb') as ca_crt:
|
|
||||||
@@ -1115,9 +1116,9 @@ def create_csr(ca_name,
|
|
||||||
req.sign(key, salt.utils.stringutils.to_str(digest))
|
|
||||||
|
|
||||||
# Write private key and request
|
|
||||||
- with salt.utils.files.fopen('{0}/{1}.key'.format(csr_path,
|
|
||||||
- csr_filename),
|
|
||||||
- 'wb+') as priv_key:
|
|
||||||
+ priv_keyp = '{0}/{1}.key'.format(csr_path, csr_filename)
|
|
||||||
+ fp = os.open(priv_keyp, os.O_CREAT | os.O_RDWR, 0o600)
|
|
||||||
+ with os.fdopen(fp, 'wb+') as priv_key:
|
|
||||||
priv_key.write(
|
|
||||||
salt.utils.stringutils.to_bytes(
|
|
||||||
OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM,
|
|
||||||
@@ -1266,7 +1267,8 @@ def create_self_signed_cert(tls_dir='tls',
|
|
||||||
priv_key_path = '{0}/{1}/certs/{2}.key'.format(cert_base_path(),
|
|
||||||
tls_dir,
|
|
||||||
cert_filename)
|
|
||||||
- with salt.utils.files.fopen(priv_key_path, 'wb+') as priv_key:
|
|
||||||
+ fp = os.open(priv_key_path, os.O_CREAT | os.O_RDWR, 0o600)
|
|
||||||
+ with os.fdopen(fp, 'wb+') as priv_key:
|
|
||||||
priv_key.write(
|
|
||||||
salt.utils.stringutils.to_bytes(
|
|
||||||
OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM,
|
|
||||||
diff --git a/salt/netapi/__init__.py b/salt/netapi/__init__.py
|
diff --git a/salt/netapi/__init__.py b/salt/netapi/__init__.py
|
||||||
index 31a24bb420..4e5b6b093a 100644
|
index dec19b37ef..cba1ec574f 100644
|
||||||
--- a/salt/netapi/__init__.py
|
--- a/salt/netapi/__init__.py
|
||||||
+++ b/salt/netapi/__init__.py
|
+++ b/salt/netapi/__init__.py
|
||||||
@@ -3,24 +3,36 @@
|
@@ -109,6 +109,49 @@ class NetapiClient:
|
||||||
Make api awesomeness
|
"Authorization error occurred."
|
||||||
'''
|
)
|
||||||
from __future__ import absolute_import, print_function, unicode_literals
|
|
||||||
+
|
|
||||||
+import copy
|
|
||||||
+
|
|
||||||
# Import Python libs
|
|
||||||
import inspect
|
|
||||||
+import logging
|
|
||||||
import os
|
|
||||||
|
|
||||||
# Import Salt libs
|
|
||||||
import salt.log # pylint: disable=W0611
|
|
||||||
+import salt.auth
|
|
||||||
import salt.client
|
|
||||||
import salt.config
|
|
||||||
+import salt.daemons.masterapi
|
|
||||||
import salt.runner
|
|
||||||
import salt.syspaths
|
|
||||||
import salt.wheel
|
|
||||||
import salt.utils.args
|
|
||||||
import salt.client.ssh.client
|
|
||||||
import salt.exceptions
|
|
||||||
+import salt.utils.args
|
|
||||||
+import salt.utils.minions
|
|
||||||
+import salt.wheel
|
|
||||||
+from salt.defaults import DEFAULT_TARGET_DELIM
|
|
||||||
|
|
||||||
# Import third party libs
|
|
||||||
from salt.ext import six
|
|
||||||
|
|
||||||
+log = logging.getLogger(__name__)
|
|
||||||
+
|
|
||||||
|
|
||||||
class NetapiClient(object):
|
|
||||||
'''
|
|
||||||
@@ -34,6 +46,15 @@ class NetapiClient(object):
|
|
||||||
|
|
||||||
def __init__(self, opts):
|
|
||||||
self.opts = opts
|
|
||||||
+ apiopts = copy.deepcopy(self.opts)
|
|
||||||
+ apiopts["enable_ssh_minions"] = True
|
|
||||||
+ apiopts["cachedir"] = os.path.join(opts["cachedir"], "saltapi")
|
|
||||||
+ if not os.path.exists(apiopts["cachedir"]):
|
|
||||||
+ os.makedirs(apiopts["cachedir"])
|
|
||||||
+ self.resolver = salt.auth.Resolver(apiopts)
|
|
||||||
+ self.loadauth = salt.auth.LoadAuth(apiopts)
|
|
||||||
+ self.key = salt.daemons.masterapi.access_keys(apiopts)
|
|
||||||
+ self.ckminions = salt.utils.minions.CkMinions(apiopts)
|
|
||||||
|
|
||||||
def _is_master_running(self):
|
|
||||||
'''
|
|
||||||
@@ -55,6 +76,49 @@ class NetapiClient(object):
|
|
||||||
self.opts['sock_dir'],
|
|
||||||
ipc_file))
|
|
||||||
|
|
||||||
+ def _prep_auth_info(self, clear_load):
|
+ def _prep_auth_info(self, clear_load):
|
||||||
+ sensitive_load_keys = []
|
+ sensitive_load_keys = []
|
||||||
@ -230,352 +63,58 @@ index 31a24bb420..4e5b6b093a 100644
|
|||||||
+ )
|
+ )
|
||||||
+
|
+
|
||||||
def run(self, low):
|
def run(self, low):
|
||||||
'''
|
"""
|
||||||
Execute the specified function in the specified client by passing the
|
Execute the specified function in the specified client by passing the
|
||||||
@@ -80,6 +144,9 @@ class NetapiClient(object):
|
|
||||||
raise salt.exceptions.EauthAuthenticationError(
|
|
||||||
'Raw shell option not allowed.')
|
|
||||||
|
|
||||||
+ if low['client'] == 'ssh':
|
|
||||||
+ self._authorize_ssh(low)
|
|
||||||
+
|
|
||||||
l_fun = getattr(self, low['client'])
|
|
||||||
f_call = salt.utils.args.format_call(l_fun, low)
|
|
||||||
return l_fun(*f_call.get('args', ()), **f_call.get('kwargs', {}))
|
|
||||||
diff --git a/tests/integration/netapi/test_client.py b/tests/integration/netapi/test_client.py
|
diff --git a/tests/integration/netapi/test_client.py b/tests/integration/netapi/test_client.py
|
||||||
index 08030f31ec..b99bdfe313 100644
|
index 70471d3148..9eb6e52920 100644
|
||||||
--- a/tests/integration/netapi/test_client.py
|
--- a/tests/integration/netapi/test_client.py
|
||||||
+++ b/tests/integration/netapi/test_client.py
|
+++ b/tests/integration/netapi/test_client.py
|
||||||
@@ -1,26 +1,30 @@
|
@@ -15,10 +15,12 @@ from tests.support.helpers import (
|
||||||
# encoding: utf-8
|
SKIP_IF_NOT_RUNNING_PYTEST,
|
||||||
-
|
SaveRequestsPostHandler,
|
||||||
# Import Python libs
|
Webserver,
|
||||||
from __future__ import absolute_import, print_function, unicode_literals
|
+ requires_sshd_server,
|
||||||
+import copy
|
slowTest,
|
||||||
import logging
|
)
|
||||||
import os
|
from tests.support.mixins import AdaptedConfigurationTestCaseMixin
|
||||||
import time
|
from tests.support.mock import patch
|
||||||
|
+from tests.support.paths import TMP, TMP_CONF_DIR
|
||||||
+import salt.config
|
|
||||||
+import salt.netapi
|
|
||||||
+import salt.utils.files
|
|
||||||
+import salt.utils.platform
|
|
||||||
+import salt.utils.pycrypto
|
|
||||||
+
|
|
||||||
# Import Salt Testing libs
|
|
||||||
from tests.support.paths import TMP_CONF_DIR, TMP
|
|
||||||
from tests.support.runtests import RUNTIME_VARS
|
from tests.support.runtests import RUNTIME_VARS
|
||||||
from tests.support.unit import TestCase, skipIf
|
from tests.support.unit import TestCase, skipIf
|
||||||
from tests.support.mock import patch
|
|
||||||
-from tests.support.case import SSHCase
|
|
||||||
+from tests.support.case import ModuleCase, SSHCase
|
|
||||||
+from salt.exceptions import EauthAuthenticationError
|
|
||||||
from tests.support.helpers import (
|
|
||||||
Webserver,
|
|
||||||
SaveRequestsPostHandler,
|
|
||||||
requires_sshd_server
|
|
||||||
)
|
|
||||||
|
|
||||||
-# Import Salt libs
|
@@ -178,7 +180,12 @@ class NetapiSSHClientTest(SSHCase):
|
||||||
-import salt.config
|
"""
|
||||||
-import salt.netapi
|
opts = AdaptedConfigurationTestCaseMixin.get_config("client_config").copy()
|
||||||
|
|
||||||
from salt.exceptions import (
|
|
||||||
EauthAuthenticationError
|
|
||||||
@@ -174,6 +178,10 @@ class NetapiSSHClientTest(SSHCase):
|
|
||||||
'''
|
|
||||||
opts = salt.config.client_config(os.path.join(TMP_CONF_DIR, 'master'))
|
|
||||||
self.netapi = salt.netapi.NetapiClient(opts)
|
self.netapi = salt.netapi.NetapiClient(opts)
|
||||||
+ opts = salt.config.client_config(os.path.join(TMP_CONF_DIR, "master"))
|
- self.priv_file = os.path.join(RUNTIME_VARS.TMP_SSH_CONF_DIR, "client_key")
|
||||||
+ naopts = copy.deepcopy(opts)
|
|
||||||
+ naopts["ignore_host_keys"] = True
|
|
||||||
+ self.netapi = salt.netapi.NetapiClient(naopts)
|
|
||||||
|
|
||||||
self.priv_file = os.path.join(RUNTIME_VARS.TMP_CONF_DIR, 'key_test')
|
|
||||||
self.rosters = os.path.join(RUNTIME_VARS.TMP_CONF_DIR)
|
|
||||||
@@ -271,3 +279,281 @@ class NetapiSSHClientTest(SSHCase):
|
|
||||||
|
|
||||||
self.assertEqual(ret, None)
|
|
||||||
self.assertFalse(os.path.exists('badfile.txt'))
|
|
||||||
+
|
|
||||||
+ @staticmethod
|
|
||||||
+ def cleanup_file(path):
|
|
||||||
+ try:
|
|
||||||
+ os.remove(path)
|
|
||||||
+ except OSError:
|
|
||||||
+ pass
|
|
||||||
+
|
|
||||||
+ @staticmethod
|
|
||||||
+ def cleanup_dir(path):
|
|
||||||
+ try:
|
|
||||||
+ salt.utils.files.rm_rf(path)
|
|
||||||
+ except OSError:
|
|
||||||
+ pass
|
|
||||||
+
|
|
||||||
+ def test_shell_inject_ssh_priv(self):
|
|
||||||
+ """
|
|
||||||
+ Verify CVE-2020-16846 for ssh_priv variable
|
|
||||||
+ """
|
|
||||||
+ # ZDI-CAN-11143
|
|
||||||
+ path = "/tmp/test-11143"
|
|
||||||
+ self.addCleanup(self.cleanup_file, path)
|
|
||||||
+ self.addCleanup(self.cleanup_file, "aaa")
|
|
||||||
+ self.addCleanup(self.cleanup_file, "aaa.pub")
|
|
||||||
+ self.addCleanup(self.cleanup_dir, "aaa|id>")
|
|
||||||
+ low = {
|
|
||||||
+ "roster": "cache",
|
|
||||||
+ "client": "ssh",
|
|
||||||
+ "tgt": "www.zerodayinitiative.com",
|
|
||||||
+ "ssh_priv": "aaa|id>{} #".format(path),
|
|
||||||
+ "fun": "test.ping",
|
|
||||||
+ "eauth": "auto",
|
|
||||||
+ "username": "saltdev_auto",
|
|
||||||
+ "password": "saltdev",
|
|
||||||
+ }
|
|
||||||
+ ret = self.netapi.run(low)
|
|
||||||
+ self.assertFalse(os.path.exists(path))
|
|
||||||
+
|
|
||||||
+ def test_shell_inject_tgt(self):
|
|
||||||
+ """
|
|
||||||
+ Verify CVE-2020-16846 for tgt variable
|
|
||||||
+ """
|
|
||||||
+ # ZDI-CAN-11167
|
|
||||||
+ path = "/tmp/test-11167"
|
|
||||||
+ self.addCleanup(self.cleanup_file, path)
|
|
||||||
+ low = {
|
|
||||||
+ "roster": "cache",
|
|
||||||
+ "client": "ssh",
|
|
||||||
+ "tgt": "root|id>{} #@127.0.0.1".format(path),
|
|
||||||
+ "roster_file": "/tmp/salt-tests-tmpdir/config/roaster",
|
|
||||||
+ "rosters": "/",
|
|
||||||
+ "fun": "test.ping",
|
|
||||||
+ "eauth": "auto",
|
|
||||||
+ "username": "saltdev_auto",
|
|
||||||
+ "password": "saltdev",
|
|
||||||
+ }
|
|
||||||
+ ret = self.netapi.run(low)
|
|
||||||
+ self.assertFalse(os.path.exists(path))
|
|
||||||
+
|
|
||||||
+ def test_shell_inject_ssh_options(self):
|
|
||||||
+ """
|
|
||||||
+ Verify CVE-2020-16846 for ssh_options
|
|
||||||
+ """
|
|
||||||
+ # ZDI-CAN-11169
|
|
||||||
+ path = "/tmp/test-11169"
|
|
||||||
+ self.addCleanup(self.cleanup_file, path)
|
|
||||||
+ low = {
|
|
||||||
+ "roster": "cache",
|
|
||||||
+ "client": "ssh",
|
|
||||||
+ "tgt": "127.0.0.1",
|
|
||||||
+ "renderer": "cheetah",
|
|
||||||
+ "fun": "test.ping",
|
|
||||||
+ "eauth": "auto",
|
|
||||||
+ "username": "saltdev_auto",
|
|
||||||
+ "password": "saltdev",
|
|
||||||
+ "roster_file": "/tmp/salt-tests-tmpdir/config/roaster",
|
|
||||||
+ "rosters": "/",
|
|
||||||
+ "ssh_options": ["|id>{} #".format(path), "lol"],
|
|
||||||
+ }
|
|
||||||
+ ret = self.netapi.run(low)
|
|
||||||
+ self.assertFalse(os.path.exists(path))
|
|
||||||
+
|
|
||||||
+ def test_shell_inject_ssh_port(self):
|
|
||||||
+ """
|
|
||||||
+ Verify CVE-2020-16846 for ssh_port variable
|
|
||||||
+ """
|
|
||||||
+ # ZDI-CAN-11172
|
|
||||||
+ path = "/tmp/test-11172"
|
|
||||||
+ self.addCleanup(self.cleanup_file, path)
|
|
||||||
+ low = {
|
|
||||||
+ "roster": "cache",
|
|
||||||
+ "client": "ssh",
|
|
||||||
+ "tgt": "127.0.0.1",
|
|
||||||
+ "renderer": "cheetah",
|
|
||||||
+ "fun": "test.ping",
|
|
||||||
+ "eauth": "auto",
|
|
||||||
+ "username": "saltdev_auto",
|
|
||||||
+ "password": "saltdev",
|
|
||||||
+ "roster_file": "/tmp/salt-tests-tmpdir/config/roaster",
|
|
||||||
+ "rosters": "/",
|
|
||||||
+ "ssh_port": "hhhhh|id>{} #".format(path),
|
|
||||||
+ }
|
|
||||||
+ ret = self.netapi.run(low)
|
|
||||||
+ self.assertFalse(os.path.exists(path))
|
|
||||||
+
|
|
||||||
+ def test_shell_inject_remote_port_forwards(self):
|
|
||||||
+ """
|
|
||||||
+ Verify CVE-2020-16846 for remote_port_forwards variable
|
|
||||||
+ """
|
|
||||||
+ # ZDI-CAN-11173
|
|
||||||
+ path = "/tmp/test-1173"
|
|
||||||
+ self.addCleanup(self.cleanup_file, path)
|
|
||||||
+ low = {
|
|
||||||
+ "roster": "cache",
|
|
||||||
+ "client": "ssh",
|
|
||||||
+ "tgt": "127.0.0.1",
|
|
||||||
+ "renderer": "cheetah",
|
|
||||||
+ "fun": "test.ping",
|
|
||||||
+ "roster_file": "/tmp/salt-tests-tmpdir/config/roaster",
|
|
||||||
+ "rosters": "/",
|
|
||||||
+ "ssh_remote_port_forwards": "hhhhh|id>{} #, lol".format(path),
|
|
||||||
+ "eauth": "auto",
|
|
||||||
+ "username": "saltdev_auto",
|
|
||||||
+ "password": "saltdev",
|
|
||||||
+ }
|
|
||||||
+ ret = self.netapi.run(low)
|
|
||||||
+ self.assertFalse(os.path.exists(path))
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+@requires_sshd_server
|
|
||||||
+class NetapiSSHClientAuthTest(SSHCase):
|
|
||||||
+
|
|
||||||
+ USERA = "saltdev"
|
|
||||||
+ USERA_PWD = "saltdev"
|
|
||||||
+
|
|
||||||
+ def setUp(self):
|
|
||||||
+ """
|
|
||||||
+ Set up a NetapiClient instance
|
|
||||||
+ """
|
|
||||||
+ opts = salt.config.client_config(os.path.join(TMP_CONF_DIR, "master"))
|
+ opts = salt.config.client_config(os.path.join(TMP_CONF_DIR, "master"))
|
||||||
+ naopts = copy.deepcopy(opts)
|
+ naopts = copy.deepcopy(opts)
|
||||||
+ naopts["ignore_host_keys"] = True
|
+ naopts["ignore_host_keys"] = True
|
||||||
+ self.netapi = salt.netapi.NetapiClient(naopts)
|
+ self.netapi = salt.netapi.NetapiClient(naopts)
|
||||||
+
|
+
|
||||||
+ self.priv_file = os.path.join(RUNTIME_VARS.TMP_CONF_DIR, "key_test")
|
+ self.priv_file = os.path.join(RUNTIME_VARS.TMP_CONF_DIR, "key_test")
|
||||||
+ self.rosters = os.path.join(RUNTIME_VARS.TMP_CONF_DIR)
|
self.rosters = os.path.join(RUNTIME_VARS.TMP_CONF_DIR)
|
||||||
+ # Initialize salt-ssh
|
self.roster_file = os.path.join(self.rosters, "roster")
|
||||||
+ self.run_function("test.ping")
|
|
||||||
+ self.mod_case = ModuleCase()
|
@@ -325,7 +332,7 @@ class NetapiSSHClientTest(SSHCase):
|
||||||
+ try:
|
"roster": "cache",
|
||||||
+ add_user = self.mod_case.run_function(
|
"client": "ssh",
|
||||||
+ "user.add", [self.USERA], createhome=False
|
"tgt": "root|id>{} #@127.0.0.1".format(path),
|
||||||
+ )
|
- "roster_file": self.roster_file,
|
||||||
+ self.assertTrue(add_user)
|
|
||||||
+ if salt.utils.platform.is_darwin():
|
|
||||||
+ hashed_password = self.USERA_PWD
|
|
||||||
+ else:
|
|
||||||
+ hashed_password = salt.utils.pycrypto.gen_hash(password=self.USERA_PWD)
|
|
||||||
+ add_pwd = self.mod_case.run_function(
|
|
||||||
+ "shadow.set_password", [self.USERA, hashed_password],
|
|
||||||
+ )
|
|
||||||
+ self.assertTrue(add_pwd)
|
|
||||||
+ except AssertionError:
|
|
||||||
+ self.mod_case.run_function("user.delete", [self.USERA], remove=True)
|
|
||||||
+ self.skipTest("Could not add user or password, skipping test")
|
|
||||||
+
|
|
||||||
+ def tearDown(self):
|
|
||||||
+ del self.netapi
|
|
||||||
+ self.mod_case.run_function("user.delete", [self.USERA], remove=True)
|
|
||||||
+
|
|
||||||
+ @classmethod
|
|
||||||
+ def setUpClass(cls):
|
|
||||||
+ cls.post_webserver = Webserver(handler=SaveRequestsPostHandler)
|
|
||||||
+ cls.post_webserver.start()
|
|
||||||
+ cls.post_web_root = cls.post_webserver.web_root
|
|
||||||
+ cls.post_web_handler = cls.post_webserver.handler
|
|
||||||
+
|
|
||||||
+ @classmethod
|
|
||||||
+ def tearDownClass(cls):
|
|
||||||
+ cls.post_webserver.stop()
|
|
||||||
+ del cls.post_webserver
|
|
||||||
+
|
|
||||||
+ def test_ssh_auth_bypass(self):
|
|
||||||
+ """
|
|
||||||
+ CVE-2020-25592 - Bogus eauth raises exception.
|
|
||||||
+ """
|
|
||||||
+ low = {
|
|
||||||
+ "roster": "cache",
|
|
||||||
+ "client": "ssh",
|
|
||||||
+ "tgt": "127.0.0.1",
|
|
||||||
+ "renderer": "cheetah",
|
|
||||||
+ "fun": "test.ping",
|
|
||||||
+ "roster_file": "/tmp/salt-tests-tmpdir/config/roaster",
|
+ "roster_file": "/tmp/salt-tests-tmpdir/config/roaster",
|
||||||
+ "rosters": "/",
|
"rosters": "/",
|
||||||
+ "eauth": "xx",
|
"fun": "test.ping",
|
||||||
+ }
|
"eauth": "auto",
|
||||||
+ with self.assertRaises(salt.exceptions.EauthAuthenticationError):
|
@@ -355,7 +362,7 @@ class NetapiSSHClientTest(SSHCase):
|
||||||
+ ret = self.netapi.run(low)
|
"eauth": "auto",
|
||||||
+
|
"username": "saltdev_auto",
|
||||||
+ def test_ssh_auth_valid(self):
|
"password": "saltdev",
|
||||||
+ """
|
- "roster_file": self.roster_file,
|
||||||
+ CVE-2020-25592 - Valid eauth works as expected.
|
+ "roster_file": "/tmp/salt-tests-tmpdir/config/roaster",
|
||||||
+ """
|
"rosters": "/",
|
||||||
+ low = {
|
"ssh_options": ["|id>{} #".format(path), "lol"],
|
||||||
+ "client": "ssh",
|
}
|
||||||
+ "tgt": "localhost",
|
|
||||||
+ "fun": "test.ping",
|
|
||||||
+ "roster_file": "roster",
|
|
||||||
+ "rosters": [self.rosters],
|
|
||||||
+ "ssh_priv": self.priv_file,
|
|
||||||
+ "eauth": "pam",
|
|
||||||
+ "username": "saltdev",
|
|
||||||
+ "password": "saltdev",
|
|
||||||
+ }
|
|
||||||
+ ret = self.netapi.run(low)
|
|
||||||
+ assert "localhost" in ret
|
|
||||||
+ assert ret["localhost"]["return"] is True
|
|
||||||
+
|
|
||||||
+ def test_ssh_auth_invalid(self):
|
|
||||||
+ """
|
|
||||||
+ CVE-2020-25592 - Wrong password raises exception.
|
|
||||||
+ """
|
|
||||||
+ low = {
|
|
||||||
+ "client": "ssh",
|
|
||||||
+ "tgt": "localhost",
|
|
||||||
+ "fun": "test.ping",
|
|
||||||
+ "roster_file": "roster",
|
|
||||||
+ "rosters": [self.rosters],
|
|
||||||
+ "ssh_priv": self.priv_file,
|
|
||||||
+ "eauth": "pam",
|
|
||||||
+ "username": "saltdev",
|
|
||||||
+ "password": "notvalidpassword",
|
|
||||||
+ }
|
|
||||||
+ with self.assertRaises(salt.exceptions.EauthAuthenticationError):
|
|
||||||
+ ret = self.netapi.run(low)
|
|
||||||
+
|
|
||||||
+ def test_ssh_auth_invalid_acl(self):
|
|
||||||
+ """
|
|
||||||
+ CVE-2020-25592 - Eauth ACL enforced.
|
|
||||||
+ """
|
|
||||||
+ low = {
|
|
||||||
+ "client": "ssh",
|
|
||||||
+ "tgt": "localhost",
|
|
||||||
+ "fun": "at.at",
|
|
||||||
+ "args": ["12:05am", "echo foo"],
|
|
||||||
+ "roster_file": "roster",
|
|
||||||
+ "rosters": [self.rosters],
|
|
||||||
+ "ssh_priv": self.priv_file,
|
|
||||||
+ "eauth": "pam",
|
|
||||||
+ "username": "saltdev",
|
|
||||||
+ "password": "notvalidpassword",
|
|
||||||
+ }
|
|
||||||
+ with self.assertRaises(salt.exceptions.EauthAuthenticationError):
|
|
||||||
+ ret = self.netapi.run(low)
|
|
||||||
+
|
|
||||||
+ def test_ssh_auth_token(self):
|
|
||||||
+ """
|
|
||||||
+ CVE-2020-25592 - Eauth tokens work as expected.
|
|
||||||
+ """
|
|
||||||
+ low = {
|
|
||||||
+ "eauth": "pam",
|
|
||||||
+ "username": "saltdev",
|
|
||||||
+ "password": "saltdev",
|
|
||||||
+ }
|
|
||||||
+ ret = self.netapi.loadauth.mk_token(low)
|
|
||||||
+ assert "token" in ret and ret["token"]
|
|
||||||
+ low = {
|
|
||||||
+ "client": "ssh",
|
|
||||||
+ "tgt": "localhost",
|
|
||||||
+ "fun": "test.ping",
|
|
||||||
+ "roster_file": "roster",
|
|
||||||
+ "rosters": [self.rosters],
|
|
||||||
+ "ssh_priv": self.priv_file,
|
|
||||||
+ "token": ret["token"],
|
|
||||||
+ }
|
|
||||||
+ ret = self.netapi.run(low)
|
|
||||||
+ assert "localhost" in ret
|
|
||||||
+ assert ret["localhost"]["return"] is True
|
|
||||||
--
|
--
|
||||||
2.28.0
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From e6f6b38c75027c4c4f6395117b734dce6fb7433e Mon Sep 17 00:00:00 2001
|
From 3b96edd8d23c65c6788a9980114a7e1c220c9640 Mon Sep 17 00:00:00 2001
|
||||||
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||||
<psuarezhernandez@suse.com>
|
<psuarezhernandez@suse.com>
|
||||||
Date: Fri, 4 Oct 2019 15:00:50 +0100
|
Date: Fri, 4 Oct 2019 15:00:50 +0100
|
||||||
@ -6,49 +6,49 @@ Subject: [PATCH] Fix failing unit tests for batch async
|
|||||||
|
|
||||||
---
|
---
|
||||||
salt/cli/batch_async.py | 2 +-
|
salt/cli/batch_async.py | 2 +-
|
||||||
tests/unit/cli/test_batch_async.py | 57 ++++++++++++++++++++++----------------
|
tests/unit/cli/test_batch_async.py | 66 +++++++++++++++++-------------
|
||||||
2 files changed, 34 insertions(+), 25 deletions(-)
|
2 files changed, 39 insertions(+), 29 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/cli/batch_async.py b/salt/cli/batch_async.py
|
diff --git a/salt/cli/batch_async.py b/salt/cli/batch_async.py
|
||||||
index f9e736f804..6d0dca1da5 100644
|
index 89405ba917..b2d04f9d4d 100644
|
||||||
--- a/salt/cli/batch_async.py
|
--- a/salt/cli/batch_async.py
|
||||||
+++ b/salt/cli/batch_async.py
|
+++ b/salt/cli/batch_async.py
|
||||||
@@ -88,7 +88,7 @@ class BatchAsync(object):
|
@@ -91,7 +91,7 @@ class BatchAsync:
|
||||||
io_loop=ioloop,
|
keep_loop=True,
|
||||||
keep_loop=True)
|
)
|
||||||
self.scheduled = False
|
self.scheduled = False
|
||||||
- self.patterns = {}
|
- self.patterns = {}
|
||||||
+ self.patterns = set()
|
+ self.patterns = set()
|
||||||
|
|
||||||
def __set_event_handler(self):
|
def __set_event_handler(self):
|
||||||
ping_return_pattern = 'salt/job/{0}/ret/*'.format(self.ping_jid)
|
ping_return_pattern = "salt/job/{}/ret/*".format(self.ping_jid)
|
||||||
diff --git a/tests/unit/cli/test_batch_async.py b/tests/unit/cli/test_batch_async.py
|
diff --git a/tests/unit/cli/test_batch_async.py b/tests/unit/cli/test_batch_async.py
|
||||||
index 441f9c58b9..12dfe543bc 100644
|
index 66332a548a..c18b42be57 100644
|
||||||
--- a/tests/unit/cli/test_batch_async.py
|
--- a/tests/unit/cli/test_batch_async.py
|
||||||
+++ b/tests/unit/cli/test_batch_async.py
|
+++ b/tests/unit/cli/test_batch_async.py
|
||||||
@@ -68,8 +68,8 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
@@ -61,8 +61,8 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
||||||
ret = self.batch.start()
|
ret = self.batch.start()
|
||||||
# assert start_batch is called later with batch_presence_ping_timeout as param
|
# assert start_batch is called later with batch_presence_ping_timeout as param
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
- self.batch.event.io_loop.call_later.call_args[0],
|
- self.batch.event.io_loop.call_later.call_args[0],
|
||||||
- (self.batch.batch_presence_ping_timeout, self.batch.start_batch))
|
- (self.batch.batch_presence_ping_timeout, self.batch.start_batch),
|
||||||
+ self.batch.event.io_loop.spawn_callback.call_args[0],
|
+ self.batch.event.io_loop.spawn_callback.call_args[0],
|
||||||
+ (self.batch.start_batch,))
|
+ (self.batch.start_batch,),
|
||||||
|
)
|
||||||
# assert test.ping called
|
# assert test.ping called
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.batch.local.run_job_async.call_args[0],
|
@@ -81,8 +81,8 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
||||||
@@ -88,8 +88,8 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
|
||||||
ret = self.batch.start()
|
ret = self.batch.start()
|
||||||
# assert start_batch is called later with gather_job_timeout as param
|
# assert start_batch is called later with gather_job_timeout as param
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
- self.batch.event.io_loop.call_later.call_args[0],
|
- self.batch.event.io_loop.call_later.call_args[0],
|
||||||
- (self.batch.opts['gather_job_timeout'], self.batch.start_batch))
|
- (self.batch.opts["gather_job_timeout"], self.batch.start_batch),
|
||||||
+ self.batch.event.io_loop.spawn_callback.call_args[0],
|
+ self.batch.event.io_loop.spawn_callback.call_args[0],
|
||||||
+ (self.batch.start_batch,))
|
+ (self.batch.start_batch,),
|
||||||
|
)
|
||||||
|
|
||||||
def test_batch_fire_start_event(self):
|
def test_batch_fire_start_event(self):
|
||||||
self.batch.minions = set(['foo', 'bar'])
|
@@ -107,12 +107,11 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
||||||
@@ -113,12 +113,11 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
|
||||||
def test_start_batch_calls_next(self):
|
def test_start_batch_calls_next(self):
|
||||||
self.batch.run_next = MagicMock(return_value=MagicMock())
|
self.batch.run_next = MagicMock(return_value=MagicMock())
|
||||||
self.batch.event = MagicMock()
|
self.batch.event = MagicMock()
|
||||||
@ -59,127 +59,138 @@ index 441f9c58b9..12dfe543bc 100644
|
|||||||
self.assertEqual(self.batch.initialized, True)
|
self.assertEqual(self.batch.initialized, True)
|
||||||
- self.assertEqual(len(self.batch.run_next.mock_calls), 1)
|
- self.assertEqual(len(self.batch.run_next.mock_calls), 1)
|
||||||
+ self.assertEqual(
|
+ self.assertEqual(
|
||||||
+ self.batch.event.io_loop.spawn_callback.call_args[0],
|
+ self.batch.event.io_loop.spawn_callback.call_args[0], (self.batch.run_next,)
|
||||||
+ (self.batch.run_next,))
|
+ )
|
||||||
|
|
||||||
def test_batch_fire_done_event(self):
|
def test_batch_fire_done_event(self):
|
||||||
self.batch.targeted_minions = {'foo', 'baz', 'bar'}
|
self.batch.targeted_minions = {"foo", "baz", "bar"}
|
||||||
@@ -154,14 +153,14 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
@@ -147,14 +146,14 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
||||||
future = tornado.gen.Future()
|
future = tornado.gen.Future()
|
||||||
future.set_result({'minions': ['foo', 'bar']})
|
future.set_result({"minions": ["foo", "bar"]})
|
||||||
self.batch.local.run_job_async.return_value = future
|
self.batch.local.run_job_async.return_value = future
|
||||||
- ret = self.batch.run_next().result()
|
- ret = self.batch.run_next().result()
|
||||||
+ self.batch.run_next()
|
+ self.batch.run_next()
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.batch.local.run_job_async.call_args[0],
|
self.batch.local.run_job_async.call_args[0],
|
||||||
({'foo', 'bar'}, 'my.fun', [], 'list')
|
({"foo", "bar"}, "my.fun", [], "list"),
|
||||||
)
|
)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
- self.batch.event.io_loop.call_later.call_args[0],
|
- self.batch.event.io_loop.call_later.call_args[0],
|
||||||
- (self.batch.opts['timeout'], self.batch.find_job, {'foo', 'bar'})
|
- (self.batch.opts["timeout"], self.batch.find_job, {"foo", "bar"}),
|
||||||
+ self.batch.event.io_loop.spawn_callback.call_args[0],
|
+ self.batch.event.io_loop.spawn_callback.call_args[0],
|
||||||
+ (self.batch.find_job, {'foo', 'bar'})
|
+ (self.batch.find_job, {"foo", "bar"}),
|
||||||
)
|
)
|
||||||
self.assertEqual(self.batch.active, {'bar', 'foo'})
|
self.assertEqual(self.batch.active, {"bar", "foo"})
|
||||||
|
|
||||||
@@ -252,13 +251,14 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
@@ -249,15 +248,21 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
||||||
self.assertEqual(self.batch.active, set())
|
self.assertEqual(self.batch.active, set())
|
||||||
self.assertEqual(self.batch.done_minions, {'foo'})
|
self.assertEqual(self.batch.done_minions, {"foo"})
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
- self.batch.event.io_loop.call_later.call_args[0],
|
- self.batch.event.io_loop.call_later.call_args[0],
|
||||||
- (self.batch.batch_delay, self.batch.run_next))
|
- (self.batch.batch_delay, self.batch.run_next),
|
||||||
+ self.batch.event.io_loop.spawn_callback.call_args[0],
|
+ self.batch.event.io_loop.spawn_callback.call_args[0],
|
||||||
+ (self.batch.schedule_next,))
|
+ (self.batch.schedule_next,),
|
||||||
|
)
|
||||||
|
|
||||||
def test_batch__event_handler_find_job_return(self):
|
def test_batch__event_handler_find_job_return(self):
|
||||||
self.batch.event = MagicMock(
|
self.batch.event = MagicMock(
|
||||||
- unpack=MagicMock(return_value=('salt/job/1236/ret/foo', {'id': 'foo'})))
|
- unpack=MagicMock(return_value=("salt/job/1236/ret/foo", {"id": "foo"}))
|
||||||
+ unpack=MagicMock(return_value=('salt/job/1236/ret/foo', {'id': 'foo', 'return': 'deadbeaf'})))
|
+ unpack=MagicMock(
|
||||||
|
+ return_value=(
|
||||||
|
+ "salt/job/1236/ret/foo",
|
||||||
|
+ {"id": "foo", "return": "deadbeaf"},
|
||||||
|
+ )
|
||||||
|
+ )
|
||||||
|
)
|
||||||
self.batch.start()
|
self.batch.start()
|
||||||
+ self.batch.patterns.add(('salt/job/1236/ret/*', 'find_job_return'))
|
+ self.batch.patterns.add(("salt/job/1236/ret/*", "find_job_return"))
|
||||||
self.batch._BatchAsync__event_handler(MagicMock())
|
self.batch._BatchAsync__event_handler(MagicMock())
|
||||||
self.assertEqual(self.batch.find_job_returned, {'foo'})
|
self.assertEqual(self.batch.find_job_returned, {"foo"})
|
||||||
|
|
||||||
@@ -275,10 +275,13 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
@@ -274,14 +279,13 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
||||||
future = tornado.gen.Future()
|
future = tornado.gen.Future()
|
||||||
future.set_result({})
|
future.set_result({})
|
||||||
self.batch.local.run_job_async.return_value = future
|
self.batch.local.run_job_async.return_value = future
|
||||||
+ self.batch.minions = set(['foo', 'bar'])
|
+ self.batch.minions = {"foo", "bar"}
|
||||||
+ self.batch.jid_gen = MagicMock(return_value="1234")
|
+ self.batch.jid_gen = MagicMock(return_value="1234")
|
||||||
+ tornado.gen.sleep = MagicMock(return_value=future)
|
+ tornado.gen.sleep = MagicMock(return_value=future)
|
||||||
self.batch.find_job({'foo', 'bar'})
|
self.batch.find_job({"foo", "bar"})
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
- self.batch.event.io_loop.call_later.call_args[0],
|
- self.batch.event.io_loop.call_later.call_args[0],
|
||||||
- (self.batch.opts['gather_job_timeout'], self.batch.check_find_job, {'foo', 'bar'})
|
- (
|
||||||
|
- self.batch.opts["gather_job_timeout"],
|
||||||
|
- self.batch.check_find_job,
|
||||||
|
- {"foo", "bar"},
|
||||||
|
- ),
|
||||||
+ self.batch.event.io_loop.spawn_callback.call_args[0],
|
+ self.batch.event.io_loop.spawn_callback.call_args[0],
|
||||||
+ (self.batch.check_find_job, {'foo', 'bar'}, "1234")
|
+ (self.batch.check_find_job, {"foo", "bar"}, "1234"),
|
||||||
)
|
)
|
||||||
|
|
||||||
@tornado.testing.gen_test
|
@tornado.testing.gen_test
|
||||||
@@ -288,17 +291,21 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
@@ -291,17 +295,21 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
||||||
future = tornado.gen.Future()
|
future = tornado.gen.Future()
|
||||||
future.set_result({})
|
future.set_result({})
|
||||||
self.batch.local.run_job_async.return_value = future
|
self.batch.local.run_job_async.return_value = future
|
||||||
+ self.batch.minions = set(['foo', 'bar'])
|
+ self.batch.minions = {"foo", "bar"}
|
||||||
+ self.batch.jid_gen = MagicMock(return_value="1234")
|
+ self.batch.jid_gen = MagicMock(return_value="1234")
|
||||||
+ tornado.gen.sleep = MagicMock(return_value=future)
|
+ tornado.gen.sleep = MagicMock(return_value=future)
|
||||||
self.batch.find_job({'foo', 'bar'})
|
self.batch.find_job({"foo", "bar"})
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
- self.batch.event.io_loop.call_later.call_args[0],
|
- self.batch.event.io_loop.call_later.call_args[0],
|
||||||
- (self.batch.opts['gather_job_timeout'], self.batch.check_find_job, {'foo'})
|
- (self.batch.opts["gather_job_timeout"], self.batch.check_find_job, {"foo"}),
|
||||||
+ self.batch.event.io_loop.spawn_callback.call_args[0],
|
+ self.batch.event.io_loop.spawn_callback.call_args[0],
|
||||||
+ (self.batch.check_find_job, {'foo'}, "1234")
|
+ (self.batch.check_find_job, {"foo"}, "1234"),
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_batch_check_find_job_did_not_return(self):
|
def test_batch_check_find_job_did_not_return(self):
|
||||||
self.batch.event = MagicMock()
|
self.batch.event = MagicMock()
|
||||||
self.batch.active = {'foo'}
|
self.batch.active = {"foo"}
|
||||||
self.batch.find_job_returned = set()
|
self.batch.find_job_returned = set()
|
||||||
- self.batch.check_find_job({'foo'})
|
- self.batch.check_find_job({"foo"})
|
||||||
+ self.batch.patterns = { ('salt/job/1234/ret/*', 'find_job_return') }
|
+ self.batch.patterns = {("salt/job/1234/ret/*", "find_job_return")}
|
||||||
+ self.batch.check_find_job({'foo'}, jid="1234")
|
+ self.batch.check_find_job({"foo"}, jid="1234")
|
||||||
self.assertEqual(self.batch.find_job_returned, set())
|
self.assertEqual(self.batch.find_job_returned, set())
|
||||||
self.assertEqual(self.batch.active, set())
|
self.assertEqual(self.batch.active, set())
|
||||||
self.assertEqual(len(self.batch.event.io_loop.add_callback.mock_calls), 0)
|
self.assertEqual(len(self.batch.event.io_loop.add_callback.mock_calls), 0)
|
||||||
@@ -306,9 +313,10 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
@@ -309,9 +317,10 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
||||||
def test_batch_check_find_job_did_return(self):
|
def test_batch_check_find_job_did_return(self):
|
||||||
self.batch.event = MagicMock()
|
self.batch.event = MagicMock()
|
||||||
self.batch.find_job_returned = {'foo'}
|
self.batch.find_job_returned = {"foo"}
|
||||||
- self.batch.check_find_job({'foo'})
|
- self.batch.check_find_job({"foo"})
|
||||||
+ self.batch.patterns = { ('salt/job/1234/ret/*', 'find_job_return') }
|
+ self.batch.patterns = {("salt/job/1234/ret/*", "find_job_return")}
|
||||||
+ self.batch.check_find_job({'foo'}, jid="1234")
|
+ self.batch.check_find_job({"foo"}, jid="1234")
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
- self.batch.event.io_loop.add_callback.call_args[0],
|
- self.batch.event.io_loop.add_callback.call_args[0],
|
||||||
+ self.batch.event.io_loop.spawn_callback.call_args[0],
|
+ self.batch.event.io_loop.spawn_callback.call_args[0],
|
||||||
(self.batch.find_job, {'foo'})
|
(self.batch.find_job, {"foo"}),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -329,7 +337,8 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
@@ -332,7 +341,8 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
||||||
# both not yet done but only 'foo' responded to find_job
|
# both not yet done but only 'foo' responded to find_job
|
||||||
not_done = {'foo', 'bar'}
|
not_done = {"foo", "bar"}
|
||||||
|
|
||||||
- self.batch.check_find_job(not_done)
|
- self.batch.check_find_job(not_done)
|
||||||
+ self.batch.patterns = { ('salt/job/1234/ret/*', 'find_job_return') }
|
+ self.batch.patterns = {("salt/job/1234/ret/*", "find_job_return")}
|
||||||
+ self.batch.check_find_job(not_done, jid="1234")
|
+ self.batch.check_find_job(not_done, jid="1234")
|
||||||
|
|
||||||
# assert 'bar' removed from active
|
# assert 'bar' removed from active
|
||||||
self.assertEqual(self.batch.active, {'foo'})
|
self.assertEqual(self.batch.active, {"foo"})
|
||||||
@@ -339,7 +348,7 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
@@ -342,7 +352,7 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
||||||
|
|
||||||
# assert 'find_job' schedueled again only for 'foo'
|
# assert 'find_job' schedueled again only for 'foo'
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
- self.batch.event.io_loop.add_callback.call_args[0],
|
- self.batch.event.io_loop.add_callback.call_args[0],
|
||||||
+ self.batch.event.io_loop.spawn_callback.call_args[0],
|
+ self.batch.event.io_loop.spawn_callback.call_args[0],
|
||||||
(self.batch.find_job, {'foo'})
|
(self.batch.find_job, {"foo"}),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -347,4 +356,4 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
@@ -350,4 +360,4 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
||||||
self.batch.event = MagicMock()
|
self.batch.event = MagicMock()
|
||||||
self.batch.scheduled = True
|
self.batch.scheduled = True
|
||||||
self.batch.schedule_next()
|
self.batch.schedule_next()
|
||||||
- self.assertEqual(len(self.batch.event.io_loop.call_later.mock_calls), 0)
|
- self.assertEqual(len(self.batch.event.io_loop.call_later.mock_calls), 0)
|
||||||
+ self.assertEqual(len(self.batch.event.io_loop.spawn_callback.mock_calls), 0)
|
+ self.assertEqual(len(self.batch.event.io_loop.spawn_callback.mock_calls), 0)
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,738 +0,0 @@
|
|||||||
From c3d8ef9d1387ac3d69fbbd1f8042bf89ba87821a Mon Sep 17 00:00:00 2001
|
|
||||||
From: Victor Zhestkov <vzhestkov@suse.com>
|
|
||||||
Date: Tue, 13 Oct 2020 09:28:39 +0300
|
|
||||||
Subject: [PATCH] Fix for bsc#1102248 - psutil is broken and so Process
|
|
||||||
is not working on Python 3 as it is implemented
|
|
||||||
|
|
||||||
---
|
|
||||||
salt/modules/ps.py | 268 ++++++++++++++++++++++++++-------------------
|
|
||||||
1 file changed, 157 insertions(+), 111 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/salt/modules/ps.py b/salt/modules/ps.py
|
|
||||||
index bb37873f48..9925e29968 100644
|
|
||||||
--- a/salt/modules/ps.py
|
|
||||||
+++ b/salt/modules/ps.py
|
|
||||||
@@ -1,31 +1,33 @@
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
-'''
|
|
||||||
+"""
|
|
||||||
A salt interface to psutil, a system and process library.
|
|
||||||
See http://code.google.com/p/psutil.
|
|
||||||
|
|
||||||
:depends: - psutil Python module, version 0.3.0 or later
|
|
||||||
- python-utmp package (optional)
|
|
||||||
-'''
|
|
||||||
+"""
|
|
||||||
|
|
||||||
# Import python libs
|
|
||||||
-from __future__ import absolute_import, unicode_literals, print_function
|
|
||||||
-import time
|
|
||||||
+from __future__ import absolute_import, print_function, unicode_literals
|
|
||||||
+
|
|
||||||
import datetime
|
|
||||||
import re
|
|
||||||
+import time
|
|
||||||
|
|
||||||
# Import salt libs
|
|
||||||
import salt.utils.data
|
|
||||||
-from salt.exceptions import SaltInvocationError, CommandExecutionError
|
|
||||||
|
|
||||||
# Import third party libs
|
|
||||||
import salt.utils.decorators.path
|
|
||||||
+from salt.exceptions import CommandExecutionError, SaltInvocationError
|
|
||||||
from salt.ext import six
|
|
||||||
+
|
|
||||||
# pylint: disable=import-error
|
|
||||||
try:
|
|
||||||
import salt.utils.psutil_compat as psutil
|
|
||||||
|
|
||||||
HAS_PSUTIL = True
|
|
||||||
- PSUTIL2 = getattr(psutil, 'version_info', ()) >= (2, 0)
|
|
||||||
+ PSUTIL2 = getattr(psutil, "version_info", ()) >= (2, 0)
|
|
||||||
except ImportError:
|
|
||||||
HAS_PSUTIL = False
|
|
||||||
# pylint: enable=import-error
|
|
||||||
@@ -33,7 +35,10 @@ except ImportError:
|
|
||||||
|
|
||||||
def __virtual__():
|
|
||||||
if not HAS_PSUTIL:
|
|
||||||
- return False, 'The ps module cannot be loaded: python module psutil not installed.'
|
|
||||||
+ return (
|
|
||||||
+ False,
|
|
||||||
+ "The ps module cannot be loaded: python module psutil not installed.",
|
|
||||||
+ )
|
|
||||||
|
|
||||||
# Functions and attributes used in this execution module seem to have been
|
|
||||||
# added as of psutil 0.3.0, from an inspection of the source code. Only
|
|
||||||
@@ -44,15 +49,20 @@ def __virtual__():
|
|
||||||
# as of Dec. 2013 EPEL is on 0.6.1, Debian 7 is on 0.5.1, etc.).
|
|
||||||
if psutil.version_info >= (0, 3, 0):
|
|
||||||
return True
|
|
||||||
- return (False, 'The ps execution module cannot be loaded: the psutil python module version {0} is less than 0.3.0'.format(psutil.version_info))
|
|
||||||
+ return (
|
|
||||||
+ False,
|
|
||||||
+ "The ps execution module cannot be loaded: the psutil python module version {0} is less than 0.3.0".format(
|
|
||||||
+ psutil.version_info
|
|
||||||
+ ),
|
|
||||||
+ )
|
|
||||||
|
|
||||||
|
|
||||||
def _get_proc_cmdline(proc):
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
Returns the cmdline of a Process instance.
|
|
||||||
|
|
||||||
It's backward compatible with < 2.0 versions of psutil.
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
try:
|
|
||||||
return salt.utils.data.decode(proc.cmdline() if PSUTIL2 else proc.cmdline)
|
|
||||||
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
|
||||||
@@ -60,23 +70,25 @@ def _get_proc_cmdline(proc):
|
|
||||||
|
|
||||||
|
|
||||||
def _get_proc_create_time(proc):
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
Returns the create_time of a Process instance.
|
|
||||||
|
|
||||||
It's backward compatible with < 2.0 versions of psutil.
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
try:
|
|
||||||
- return salt.utils.data.decode(proc.create_time() if PSUTIL2 else proc.create_time)
|
|
||||||
+ return salt.utils.data.decode(
|
|
||||||
+ proc.create_time() if PSUTIL2 else proc.create_time
|
|
||||||
+ )
|
|
||||||
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def _get_proc_name(proc):
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
Returns the name of a Process instance.
|
|
||||||
|
|
||||||
It's backward compatible with < 2.0 versions of psutil.
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
try:
|
|
||||||
return salt.utils.data.decode(proc.name() if PSUTIL2 else proc.name)
|
|
||||||
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
|
||||||
@@ -84,11 +96,11 @@ def _get_proc_name(proc):
|
|
||||||
|
|
||||||
|
|
||||||
def _get_proc_status(proc):
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
Returns the status of a Process instance.
|
|
||||||
|
|
||||||
It's backward compatible with < 2.0 versions of psutil.
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
try:
|
|
||||||
return salt.utils.data.decode(proc.status() if PSUTIL2 else proc.status)
|
|
||||||
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
|
||||||
@@ -96,11 +108,11 @@ def _get_proc_status(proc):
|
|
||||||
|
|
||||||
|
|
||||||
def _get_proc_username(proc):
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
Returns the username of a Process instance.
|
|
||||||
|
|
||||||
It's backward compatible with < 2.0 versions of psutil.
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
try:
|
|
||||||
return salt.utils.data.decode(proc.username() if PSUTIL2 else proc.username)
|
|
||||||
except (psutil.NoSuchProcess, psutil.AccessDenied, KeyError):
|
|
||||||
@@ -108,16 +120,16 @@ def _get_proc_username(proc):
|
|
||||||
|
|
||||||
|
|
||||||
def _get_proc_pid(proc):
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
Returns the pid of a Process instance.
|
|
||||||
|
|
||||||
It's backward compatible with < 2.0 versions of psutil.
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
return proc.pid
|
|
||||||
|
|
||||||
|
|
||||||
def top(num_processes=5, interval=3):
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
Return a list of top CPU consuming processes during the interval.
|
|
||||||
num_processes = return the top N CPU consuming processes
|
|
||||||
interval = the number of seconds to sample CPU usage over
|
|
||||||
@@ -129,57 +141,63 @@ def top(num_processes=5, interval=3):
|
|
||||||
salt '*' ps.top
|
|
||||||
|
|
||||||
salt '*' ps.top 5 10
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
result = []
|
|
||||||
start_usage = {}
|
|
||||||
for pid in psutil.pids():
|
|
||||||
try:
|
|
||||||
process = psutil.Process(pid)
|
|
||||||
- user, system = process.cpu_times()
|
|
||||||
- except ValueError:
|
|
||||||
- user, system, _, _ = process.cpu_times()
|
|
||||||
except psutil.NoSuchProcess:
|
|
||||||
continue
|
|
||||||
+ else:
|
|
||||||
+ try:
|
|
||||||
+ user, system = process.cpu_times()[:2]
|
|
||||||
+ except psutil.ZombieProcess:
|
|
||||||
+ user = system = 0.0
|
|
||||||
start_usage[process] = user + system
|
|
||||||
time.sleep(interval)
|
|
||||||
usage = set()
|
|
||||||
for process, start in six.iteritems(start_usage):
|
|
||||||
try:
|
|
||||||
- user, system = process.cpu_times()
|
|
||||||
- except ValueError:
|
|
||||||
- user, system, _, _ = process.cpu_times()
|
|
||||||
+ user, system = process.cpu_times()[:2]
|
|
||||||
except psutil.NoSuchProcess:
|
|
||||||
continue
|
|
||||||
now = user + system
|
|
||||||
diff = now - start
|
|
||||||
usage.add((diff, process))
|
|
||||||
|
|
||||||
- for idx, (diff, process) in enumerate(reversed(sorted(usage))):
|
|
||||||
- if num_processes and idx >= num_processes:
|
|
||||||
- break
|
|
||||||
- if len(_get_proc_cmdline(process)) == 0:
|
|
||||||
- cmdline = _get_proc_name(process)
|
|
||||||
- else:
|
|
||||||
- cmdline = _get_proc_cmdline(process)
|
|
||||||
- info = {'cmd': cmdline,
|
|
||||||
- 'user': _get_proc_username(process),
|
|
||||||
- 'status': _get_proc_status(process),
|
|
||||||
- 'pid': _get_proc_pid(process),
|
|
||||||
- 'create_time': _get_proc_create_time(process),
|
|
||||||
- 'cpu': {},
|
|
||||||
- 'mem': {},
|
|
||||||
+ for diff, process in sorted(usage, key=lambda x: x[0], reverse=True):
|
|
||||||
+ info = {
|
|
||||||
+ "cmd": _get_proc_cmdline(process) or _get_proc_name(process),
|
|
||||||
+ "user": _get_proc_username(process),
|
|
||||||
+ "status": _get_proc_status(process),
|
|
||||||
+ "pid": _get_proc_pid(process),
|
|
||||||
+ "create_time": _get_proc_create_time(process),
|
|
||||||
+ "cpu": {},
|
|
||||||
+ "mem": {},
|
|
||||||
}
|
|
||||||
- for key, value in six.iteritems(process.cpu_times()._asdict()):
|
|
||||||
- info['cpu'][key] = value
|
|
||||||
- for key, value in six.iteritems(process.memory_info()._asdict()):
|
|
||||||
- info['mem'][key] = value
|
|
||||||
+ try:
|
|
||||||
+ for key, value in six.iteritems(process.cpu_times()._asdict()):
|
|
||||||
+ info["cpu"][key] = value
|
|
||||||
+ for key, value in six.iteritems(process.memory_info()._asdict()):
|
|
||||||
+ info["mem"][key] = value
|
|
||||||
+ except psutil.NoSuchProcess:
|
|
||||||
+ # Process ended since psutil.pids() was run earlier in this
|
|
||||||
+ # function. Ignore this process and do not include this process in
|
|
||||||
+ # the return data.
|
|
||||||
+ continue
|
|
||||||
+
|
|
||||||
result.append(info)
|
|
||||||
|
|
||||||
+ # Stop gathering process info since we've reached the desired number
|
|
||||||
+ if len(result) >= num_processes:
|
|
||||||
+ break
|
|
||||||
+
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def get_pid_list():
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
Return a list of process ids (PIDs) for all running processes.
|
|
||||||
|
|
||||||
CLI Example:
|
|
||||||
@@ -187,12 +205,12 @@ def get_pid_list():
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
salt '*' ps.get_pid_list
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
return psutil.pids()
|
|
||||||
|
|
||||||
|
|
||||||
def proc_info(pid, attrs=None):
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
Return a dictionary of information for a process id (PID).
|
|
||||||
|
|
||||||
CLI Example:
|
|
||||||
@@ -209,7 +227,7 @@ def proc_info(pid, attrs=None):
|
|
||||||
Optional list of desired process attributes. The list of possible
|
|
||||||
attributes can be found here:
|
|
||||||
http://pythonhosted.org/psutil/#psutil.Process
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
try:
|
|
||||||
proc = psutil.Process(pid)
|
|
||||||
return proc.as_dict(attrs)
|
|
||||||
@@ -218,7 +236,7 @@ def proc_info(pid, attrs=None):
|
|
||||||
|
|
||||||
|
|
||||||
def kill_pid(pid, signal=15):
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
Kill a process by PID.
|
|
||||||
|
|
||||||
.. code-block:: bash
|
|
||||||
@@ -239,7 +257,7 @@ def kill_pid(pid, signal=15):
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
salt 'minion' ps.kill_pid 2000 signal=9
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
try:
|
|
||||||
psutil.Process(pid).send_signal(signal)
|
|
||||||
return True
|
|
||||||
@@ -248,7 +266,7 @@ def kill_pid(pid, signal=15):
|
|
||||||
|
|
||||||
|
|
||||||
def pkill(pattern, user=None, signal=15, full=False):
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
Kill processes matching a pattern.
|
|
||||||
|
|
||||||
.. code-block:: bash
|
|
||||||
@@ -283,12 +301,15 @@ def pkill(pattern, user=None, signal=15, full=False):
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
salt '*' ps.pkill bash signal=9 user=tom
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
|
|
||||||
killed = []
|
|
||||||
for proc in psutil.process_iter():
|
|
||||||
- name_match = pattern in ' '.join(_get_proc_cmdline(proc)) if full \
|
|
||||||
+ name_match = (
|
|
||||||
+ pattern in " ".join(_get_proc_cmdline(proc))
|
|
||||||
+ if full
|
|
||||||
else pattern in _get_proc_name(proc)
|
|
||||||
+ )
|
|
||||||
user_match = True if user is None else user == _get_proc_username(proc)
|
|
||||||
if name_match and user_match:
|
|
||||||
try:
|
|
||||||
@@ -299,11 +320,11 @@ def pkill(pattern, user=None, signal=15, full=False):
|
|
||||||
if not killed:
|
|
||||||
return None
|
|
||||||
else:
|
|
||||||
- return {'killed': killed}
|
|
||||||
+ return {"killed": killed}
|
|
||||||
|
|
||||||
|
|
||||||
-def pgrep(pattern, user=None, full=False):
|
|
||||||
- '''
|
|
||||||
+def pgrep(pattern, user=None, full=False, pattern_is_regex=False):
|
|
||||||
+ """
|
|
||||||
Return the pids for processes matching a pattern.
|
|
||||||
|
|
||||||
If full is true, the full command line is searched for a match,
|
|
||||||
@@ -323,6 +344,12 @@ def pgrep(pattern, user=None, full=False):
|
|
||||||
A boolean value indicating whether only the name of the command or
|
|
||||||
the full command line should be matched against the pattern.
|
|
||||||
|
|
||||||
+ pattern_is_regex
|
|
||||||
+ This flag enables ps.pgrep to mirror the regex search functionality
|
|
||||||
+ found in the pgrep command line utility.
|
|
||||||
+
|
|
||||||
+ .. versionadded:: 3001
|
|
||||||
+
|
|
||||||
**Examples:**
|
|
||||||
|
|
||||||
Find all httpd processes on all 'www' minions:
|
|
||||||
@@ -336,20 +363,34 @@ def pgrep(pattern, user=None, full=False):
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
salt '*' ps.pgrep bash user=tom
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
|
|
||||||
procs = []
|
|
||||||
+
|
|
||||||
+ if pattern_is_regex:
|
|
||||||
+ pattern = re.compile(str(pattern))
|
|
||||||
+
|
|
||||||
for proc in psutil.process_iter():
|
|
||||||
- name_match = pattern in ' '.join(_get_proc_cmdline(proc)) if full \
|
|
||||||
- else pattern in _get_proc_name(proc)
|
|
||||||
+ if full:
|
|
||||||
+ process_line = " ".join(_get_proc_cmdline(proc))
|
|
||||||
+ else:
|
|
||||||
+ process_line = _get_proc_name(proc)
|
|
||||||
+
|
|
||||||
+ if pattern_is_regex:
|
|
||||||
+ name_match = re.search(pattern, process_line)
|
|
||||||
+ else:
|
|
||||||
+ name_match = pattern in process_line
|
|
||||||
+
|
|
||||||
user_match = True if user is None else user == _get_proc_username(proc)
|
|
||||||
+
|
|
||||||
if name_match and user_match:
|
|
||||||
procs.append(_get_proc_pid(proc))
|
|
||||||
+
|
|
||||||
return procs or None
|
|
||||||
|
|
||||||
|
|
||||||
def cpu_percent(interval=0.1, per_cpu=False):
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
Return the percent of time the CPU is busy.
|
|
||||||
|
|
||||||
interval
|
|
||||||
@@ -363,7 +404,7 @@ def cpu_percent(interval=0.1, per_cpu=False):
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
salt '*' ps.cpu_percent
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
if per_cpu:
|
|
||||||
result = list(psutil.cpu_percent(interval, True))
|
|
||||||
else:
|
|
||||||
@@ -372,7 +413,7 @@ def cpu_percent(interval=0.1, per_cpu=False):
|
|
||||||
|
|
||||||
|
|
||||||
def cpu_times(per_cpu=False):
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
Return the percent of time the CPU spends in each state,
|
|
||||||
e.g. user, system, idle, nice, iowait, irq, softirq.
|
|
||||||
|
|
||||||
@@ -385,7 +426,7 @@ def cpu_times(per_cpu=False):
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
salt '*' ps.cpu_times
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
if per_cpu:
|
|
||||||
result = [dict(times._asdict()) for times in psutil.cpu_times(True)]
|
|
||||||
else:
|
|
||||||
@@ -394,7 +435,7 @@ def cpu_times(per_cpu=False):
|
|
||||||
|
|
||||||
|
|
||||||
def virtual_memory():
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
.. versionadded:: 2014.7.0
|
|
||||||
|
|
||||||
Return a dict that describes statistics about system memory usage.
|
|
||||||
@@ -408,15 +449,15 @@ def virtual_memory():
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
salt '*' ps.virtual_memory
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
if psutil.version_info < (0, 6, 0):
|
|
||||||
- msg = 'virtual_memory is only available in psutil 0.6.0 or greater'
|
|
||||||
+ msg = "virtual_memory is only available in psutil 0.6.0 or greater"
|
|
||||||
raise CommandExecutionError(msg)
|
|
||||||
return dict(psutil.virtual_memory()._asdict())
|
|
||||||
|
|
||||||
|
|
||||||
def swap_memory():
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
.. versionadded:: 2014.7.0
|
|
||||||
|
|
||||||
Return a dict that describes swap memory statistics.
|
|
||||||
@@ -430,15 +471,15 @@ def swap_memory():
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
salt '*' ps.swap_memory
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
if psutil.version_info < (0, 6, 0):
|
|
||||||
- msg = 'swap_memory is only available in psutil 0.6.0 or greater'
|
|
||||||
+ msg = "swap_memory is only available in psutil 0.6.0 or greater"
|
|
||||||
raise CommandExecutionError(msg)
|
|
||||||
return dict(psutil.swap_memory()._asdict())
|
|
||||||
|
|
||||||
|
|
||||||
def disk_partitions(all=False):
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
Return a list of disk partitions and their device, mount point, and
|
|
||||||
filesystem type.
|
|
||||||
|
|
||||||
@@ -451,14 +492,13 @@ def disk_partitions(all=False):
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
salt '*' ps.disk_partitions
|
|
||||||
- '''
|
|
||||||
- result = [dict(partition._asdict()) for partition in
|
|
||||||
- psutil.disk_partitions(all)]
|
|
||||||
+ """
|
|
||||||
+ result = [dict(partition._asdict()) for partition in psutil.disk_partitions(all)]
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def disk_usage(path):
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
Given a path, return a dict listing the total available space as well as
|
|
||||||
the free space, and used space.
|
|
||||||
|
|
||||||
@@ -467,12 +507,12 @@ def disk_usage(path):
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
salt '*' ps.disk_usage /home
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
return dict(psutil.disk_usage(path)._asdict())
|
|
||||||
|
|
||||||
|
|
||||||
def disk_partition_usage(all=False):
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
Return a list of disk partitions plus the mount point, filesystem and usage
|
|
||||||
statistics.
|
|
||||||
|
|
||||||
@@ -481,15 +521,15 @@ def disk_partition_usage(all=False):
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
salt '*' ps.disk_partition_usage
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
result = disk_partitions(all)
|
|
||||||
for partition in result:
|
|
||||||
- partition.update(disk_usage(partition['mountpoint']))
|
|
||||||
+ partition.update(disk_usage(partition["mountpoint"]))
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def total_physical_memory():
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
Return the total number of bytes of physical memory.
|
|
||||||
|
|
||||||
CLI Example:
|
|
||||||
@@ -497,9 +537,9 @@ def total_physical_memory():
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
salt '*' ps.total_physical_memory
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
if psutil.version_info < (0, 6, 0):
|
|
||||||
- msg = 'virtual_memory is only available in psutil 0.6.0 or greater'
|
|
||||||
+ msg = "virtual_memory is only available in psutil 0.6.0 or greater"
|
|
||||||
raise CommandExecutionError(msg)
|
|
||||||
try:
|
|
||||||
return psutil.virtual_memory().total
|
|
||||||
@@ -510,7 +550,7 @@ def total_physical_memory():
|
|
||||||
|
|
||||||
|
|
||||||
def num_cpus():
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
Return the number of CPUs.
|
|
||||||
|
|
||||||
CLI Example:
|
|
||||||
@@ -518,7 +558,7 @@ def num_cpus():
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
salt '*' ps.num_cpus
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
try:
|
|
||||||
return psutil.cpu_count()
|
|
||||||
except AttributeError:
|
|
||||||
@@ -528,7 +568,7 @@ def num_cpus():
|
|
||||||
|
|
||||||
|
|
||||||
def boot_time(time_format=None):
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
Return the boot time in number of seconds since the epoch began.
|
|
||||||
|
|
||||||
CLI Example:
|
|
||||||
@@ -545,7 +585,7 @@ def boot_time(time_format=None):
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
salt '*' ps.boot_time
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
try:
|
|
||||||
b_time = int(psutil.boot_time())
|
|
||||||
except AttributeError:
|
|
||||||
@@ -558,12 +598,12 @@ def boot_time(time_format=None):
|
|
||||||
try:
|
|
||||||
return b_time.strftime(time_format)
|
|
||||||
except TypeError as exc:
|
|
||||||
- raise SaltInvocationError('Invalid format string: {0}'.format(exc))
|
|
||||||
+ raise SaltInvocationError("Invalid format string: {0}".format(exc))
|
|
||||||
return b_time
|
|
||||||
|
|
||||||
|
|
||||||
def network_io_counters(interface=None):
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
Return network I/O statistics.
|
|
||||||
|
|
||||||
CLI Example:
|
|
||||||
@@ -573,7 +613,7 @@ def network_io_counters(interface=None):
|
|
||||||
salt '*' ps.network_io_counters
|
|
||||||
|
|
||||||
salt '*' ps.network_io_counters interface=eth0
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
if not interface:
|
|
||||||
return dict(psutil.net_io_counters()._asdict())
|
|
||||||
else:
|
|
||||||
@@ -585,7 +625,7 @@ def network_io_counters(interface=None):
|
|
||||||
|
|
||||||
|
|
||||||
def disk_io_counters(device=None):
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
Return disk I/O statistics.
|
|
||||||
|
|
||||||
CLI Example:
|
|
||||||
@@ -595,7 +635,7 @@ def disk_io_counters(device=None):
|
|
||||||
salt '*' ps.disk_io_counters
|
|
||||||
|
|
||||||
salt '*' ps.disk_io_counters device=sda1
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
if not device:
|
|
||||||
return dict(psutil.disk_io_counters()._asdict())
|
|
||||||
else:
|
|
||||||
@@ -607,7 +647,7 @@ def disk_io_counters(device=None):
|
|
||||||
|
|
||||||
|
|
||||||
def get_users():
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
Return logged-in users.
|
|
||||||
|
|
||||||
CLI Example:
|
|
||||||
@@ -615,7 +655,7 @@ def get_users():
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
salt '*' ps.get_users
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
try:
|
|
||||||
recs = psutil.users()
|
|
||||||
return [dict(x._asdict()) for x in recs]
|
|
||||||
@@ -634,14 +674,20 @@ def get_users():
|
|
||||||
started = rec[8]
|
|
||||||
if isinstance(started, tuple):
|
|
||||||
started = started[0]
|
|
||||||
- result.append({'name': rec[4], 'terminal': rec[2],
|
|
||||||
- 'started': started, 'host': rec[5]})
|
|
||||||
+ result.append(
|
|
||||||
+ {
|
|
||||||
+ "name": rec[4],
|
|
||||||
+ "terminal": rec[2],
|
|
||||||
+ "started": started,
|
|
||||||
+ "host": rec[5],
|
|
||||||
+ }
|
|
||||||
+ )
|
|
||||||
except ImportError:
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
def lsof(name):
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
Retrieve the lsof information of the given process name.
|
|
||||||
|
|
||||||
CLI Example:
|
|
||||||
@@ -649,17 +695,17 @@ def lsof(name):
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
salt '*' ps.lsof apache2
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
sanitize_name = six.text_type(name)
|
|
||||||
- lsof_infos = __salt__['cmd.run']("lsof -c " + sanitize_name)
|
|
||||||
+ lsof_infos = __salt__["cmd.run"]("lsof -c " + sanitize_name)
|
|
||||||
ret = []
|
|
||||||
ret.extend([sanitize_name, lsof_infos])
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
-@salt.utils.decorators.path.which('netstat')
|
|
||||||
+@salt.utils.decorators.path.which("netstat")
|
|
||||||
def netstat(name):
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
Retrieve the netstat information of the given process name.
|
|
||||||
|
|
||||||
CLI Example:
|
|
||||||
@@ -667,9 +713,9 @@ def netstat(name):
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
salt '*' ps.netstat apache2
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
sanitize_name = six.text_type(name)
|
|
||||||
- netstat_infos = __salt__['cmd.run']("netstat -nap")
|
|
||||||
+ netstat_infos = __salt__["cmd.run"]("netstat -nap")
|
|
||||||
found_infos = []
|
|
||||||
ret = []
|
|
||||||
for info in netstat_infos.splitlines():
|
|
||||||
@@ -679,9 +725,9 @@ def netstat(name):
|
|
||||||
return ret
|
|
||||||
|
|
||||||
|
|
||||||
-@salt.utils.decorators.path.which('ss')
|
|
||||||
+@salt.utils.decorators.path.which("ss")
|
|
||||||
def ss(name):
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
Retrieve the ss information of the given process name.
|
|
||||||
|
|
||||||
CLI Example:
|
|
||||||
@@ -692,9 +738,9 @@ def ss(name):
|
|
||||||
|
|
||||||
.. versionadded:: 2016.11.6
|
|
||||||
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
sanitize_name = six.text_type(name)
|
|
||||||
- ss_infos = __salt__['cmd.run']("ss -neap")
|
|
||||||
+ ss_infos = __salt__["cmd.run"]("ss -neap")
|
|
||||||
found_infos = []
|
|
||||||
ret = []
|
|
||||||
for info in ss_infos.splitlines():
|
|
||||||
@@ -705,7 +751,7 @@ def ss(name):
|
|
||||||
|
|
||||||
|
|
||||||
def psaux(name):
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
Retrieve information corresponding to a "ps aux" filtered
|
|
||||||
with the given pattern. It could be just a name or a regular
|
|
||||||
expression (using python search from "re" module).
|
|
||||||
@@ -715,11 +761,11 @@ def psaux(name):
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
salt '*' ps.psaux www-data.+apache2
|
|
||||||
- '''
|
|
||||||
+ """
|
|
||||||
sanitize_name = six.text_type(name)
|
|
||||||
pattern = re.compile(sanitize_name)
|
|
||||||
salt_exception_pattern = re.compile("salt.+ps.psaux.+")
|
|
||||||
- ps_aux = __salt__['cmd.run']("ps aux")
|
|
||||||
+ ps_aux = __salt__["cmd.run"]("ps aux")
|
|
||||||
found_infos = []
|
|
||||||
ret = []
|
|
||||||
nb_lines = 0
|
|
||||||
--
|
|
||||||
2.29.1
|
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
From e0ca0d0d2a62f18e2712223e130af5faa8e0fe05 Mon Sep 17 00:00:00 2001
|
From b4f54187ae7d231250f72244ffd874cc2c846150 Mon Sep 17 00:00:00 2001
|
||||||
From: Jochen Breuer <jbreuer@suse.de>
|
From: Jochen Breuer <jbreuer@suse.de>
|
||||||
Date: Thu, 28 Nov 2019 15:23:36 +0100
|
Date: Thu, 28 Nov 2019 15:23:36 +0100
|
||||||
Subject: [PATCH] Fix for log checking in x509 test
|
Subject: [PATCH] Fix for log checking in x509 test
|
||||||
@ -9,10 +9,10 @@ We are logging in debug and not in trace mode here.
|
|||||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
diff --git a/tests/unit/modules/test_x509.py b/tests/unit/modules/test_x509.py
|
diff --git a/tests/unit/modules/test_x509.py b/tests/unit/modules/test_x509.py
|
||||||
index 624a927bec..976af634c7 100644
|
index 40aea12272..e7503395eb 100644
|
||||||
--- a/tests/unit/modules/test_x509.py
|
--- a/tests/unit/modules/test_x509.py
|
||||||
+++ b/tests/unit/modules/test_x509.py
|
+++ b/tests/unit/modules/test_x509.py
|
||||||
@@ -68,9 +68,9 @@ class X509TestCase(TestCase, LoaderModuleMockMixin):
|
@@ -127,9 +127,9 @@ class X509TestCase(TestCase, LoaderModuleMockMixin):
|
||||||
|
|
||||||
subj = FakeSubject()
|
subj = FakeSubject()
|
||||||
x509._parse_subject(subj)
|
x509._parse_subject(subj)
|
||||||
@ -23,9 +23,9 @@ index 624a927bec..976af634c7 100644
|
|||||||
+ assert x509.log.debug.call_args[0][1] == list(subj.nid.keys())[0]
|
+ assert x509.log.debug.call_args[0][1] == list(subj.nid.keys())[0]
|
||||||
+ assert isinstance(x509.log.debug.call_args[0][2], TypeError)
|
+ assert isinstance(x509.log.debug.call_args[0][2], TypeError)
|
||||||
|
|
||||||
@skipIf(not HAS_M2CRYPTO, 'Skipping, M2Crypto is unavailble')
|
@skipIf(not HAS_M2CRYPTO, "Skipping, M2Crypto is unavailable")
|
||||||
def test_get_pem_entry(self):
|
def test_get_pem_entry(self):
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,113 +0,0 @@
|
|||||||
From 0c988e1db59a255b2f707c4e626cec21ff06d7a3 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jochen Breuer <jbreuer@suse.de>
|
|
||||||
Date: Thu, 9 Apr 2020 17:12:54 +0200
|
|
||||||
Subject: [PATCH] Fix for return value ret vs return in batch mode
|
|
||||||
|
|
||||||
The least intrusive fix for ret vs return in batch mode.
|
|
||||||
---
|
|
||||||
salt/cli/batch.py | 16 ++++++----
|
|
||||||
tests/unit/cli/test_batch.py | 62 ++++++++++++++++++++++++++++++++++++
|
|
||||||
2 files changed, 71 insertions(+), 7 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/salt/cli/batch.py b/salt/cli/batch.py
|
|
||||||
index 10fc81a5f4..d5b8754ad7 100644
|
|
||||||
--- a/salt/cli/batch.py
|
|
||||||
+++ b/salt/cli/batch.py
|
|
||||||
@@ -234,14 +234,16 @@ class Batch(object):
|
|
||||||
if not self.quiet:
|
|
||||||
salt.utils.stringutils.print_cli('\nExecuting run on {0}\n'.format(sorted(next_)))
|
|
||||||
# create a new iterator for this batch of minions
|
|
||||||
+ return_value = self.opts.get("return", self.opts.get("ret", ""))
|
|
||||||
new_iter = self.local.cmd_iter_no_block(
|
|
||||||
- *args,
|
|
||||||
- raw=self.opts.get('raw', False),
|
|
||||||
- ret=self.opts.get('return', ''),
|
|
||||||
- show_jid=show_jid,
|
|
||||||
- verbose=show_verbose,
|
|
||||||
- gather_job_timeout=self.opts['gather_job_timeout'],
|
|
||||||
- **self.eauth)
|
|
||||||
+ *args,
|
|
||||||
+ raw=self.opts.get("raw", False),
|
|
||||||
+ ret=return_value,
|
|
||||||
+ show_jid=show_jid,
|
|
||||||
+ verbose=show_verbose,
|
|
||||||
+ gather_job_timeout=self.opts["gather_job_timeout"],
|
|
||||||
+ **self.eauth
|
|
||||||
+ )
|
|
||||||
# add it to our iterators and to the minion_tracker
|
|
||||||
iters.append(new_iter)
|
|
||||||
minion_tracker[new_iter] = {}
|
|
||||||
diff --git a/tests/unit/cli/test_batch.py b/tests/unit/cli/test_batch.py
|
|
||||||
index acabbe51f5..d7411e8039 100644
|
|
||||||
--- a/tests/unit/cli/test_batch.py
|
|
||||||
+++ b/tests/unit/cli/test_batch.py
|
|
||||||
@@ -72,3 +72,65 @@ class BatchTestCase(TestCase):
|
|
||||||
'''
|
|
||||||
ret = Batch.get_bnum(self.batch)
|
|
||||||
self.assertEqual(ret, None)
|
|
||||||
+
|
|
||||||
+ def test_return_value_in_run_for_ret(self):
|
|
||||||
+ """
|
|
||||||
+ cmd_iter_no_block should have been called with a return no matter if
|
|
||||||
+ the return value was in ret or return.
|
|
||||||
+ """
|
|
||||||
+ self.batch.opts = {
|
|
||||||
+ "batch": "100%",
|
|
||||||
+ "timeout": 5,
|
|
||||||
+ "fun": "test",
|
|
||||||
+ "arg": "foo",
|
|
||||||
+ "gather_job_timeout": 5,
|
|
||||||
+ "ret": "my_return",
|
|
||||||
+ }
|
|
||||||
+ self.batch.minions = ["foo", "bar", "baz"]
|
|
||||||
+ self.batch.local.cmd_iter_no_block = MagicMock(return_value=iter([]))
|
|
||||||
+ ret = Batch.run(self.batch)
|
|
||||||
+ # We need to fetch at least one object to trigger the relevant code path.
|
|
||||||
+ x = next(ret)
|
|
||||||
+ self.batch.local.cmd_iter_no_block.assert_called_with(
|
|
||||||
+ ["baz", "bar", "foo"],
|
|
||||||
+ "test",
|
|
||||||
+ "foo",
|
|
||||||
+ 5,
|
|
||||||
+ "list",
|
|
||||||
+ raw=False,
|
|
||||||
+ ret="my_return",
|
|
||||||
+ show_jid=False,
|
|
||||||
+ verbose=False,
|
|
||||||
+ gather_job_timeout=5,
|
|
||||||
+ )
|
|
||||||
+
|
|
||||||
+ def test_return_value_in_run_for_return(self):
|
|
||||||
+ """
|
|
||||||
+ cmd_iter_no_block should have been called with a return no matter if
|
|
||||||
+ the return value was in ret or return.
|
|
||||||
+ """
|
|
||||||
+ self.batch.opts = {
|
|
||||||
+ "batch": "100%",
|
|
||||||
+ "timeout": 5,
|
|
||||||
+ "fun": "test",
|
|
||||||
+ "arg": "foo",
|
|
||||||
+ "gather_job_timeout": 5,
|
|
||||||
+ "return": "my_return",
|
|
||||||
+ }
|
|
||||||
+ self.batch.minions = ["foo", "bar", "baz"]
|
|
||||||
+ self.batch.local.cmd_iter_no_block = MagicMock(return_value=iter([]))
|
|
||||||
+ ret = Batch.run(self.batch)
|
|
||||||
+ # We need to fetch at least one object to trigger the relevant code path.
|
|
||||||
+ x = next(ret)
|
|
||||||
+ self.batch.local.cmd_iter_no_block.assert_called_with(
|
|
||||||
+ ["baz", "bar", "foo"],
|
|
||||||
+ "test",
|
|
||||||
+ "foo",
|
|
||||||
+ 5,
|
|
||||||
+ "list",
|
|
||||||
+ raw=False,
|
|
||||||
+ ret="my_return",
|
|
||||||
+ show_jid=False,
|
|
||||||
+ verbose=False,
|
|
||||||
+ gather_job_timeout=5,
|
|
||||||
+ )
|
|
||||||
--
|
|
||||||
2.26.1
|
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
From 16d656744d2e7d915757d6f2ae26b57ad8230b0b Mon Sep 17 00:00:00 2001
|
From 369a732537937dd6865152a87f04777539b27fcd Mon Sep 17 00:00:00 2001
|
||||||
From: Jochen Breuer <jbreuer@suse.de>
|
From: Jochen Breuer <jbreuer@suse.de>
|
||||||
Date: Thu, 6 Sep 2018 17:15:18 +0200
|
Date: Thu, 6 Sep 2018 17:15:18 +0200
|
||||||
Subject: [PATCH] Fix for SUSE Expanded Support detection
|
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(+)
|
1 file changed, 9 insertions(+)
|
||||||
|
|
||||||
diff --git a/salt/grains/core.py b/salt/grains/core.py
|
diff --git a/salt/grains/core.py b/salt/grains/core.py
|
||||||
index 9b244def9c..2851809472 100644
|
index 436c058eb6..00bd0565bf 100644
|
||||||
--- a/salt/grains/core.py
|
--- a/salt/grains/core.py
|
||||||
+++ b/salt/grains/core.py
|
+++ b/salt/grains/core.py
|
||||||
@@ -1892,6 +1892,15 @@ def os_data():
|
@@ -1990,6 +1990,15 @@ def os_data():
|
||||||
log.trace('Parsing distrib info from /etc/centos-release')
|
log.trace("Parsing distrib info from /etc/centos-release")
|
||||||
# CentOS Linux
|
# CentOS Linux
|
||||||
grains['lsb_distrib_id'] = 'CentOS'
|
grains["lsb_distrib_id"] = "CentOS"
|
||||||
+ # Maybe CentOS Linux; could also be SUSE Expanded Support.
|
+ # Maybe CentOS Linux; could also be SUSE Expanded Support.
|
||||||
+ # SUSE ES has both, centos-release and redhat-release.
|
+ # SUSE ES has both, centos-release and redhat-release.
|
||||||
+ if os.path.isfile('/etc/redhat-release'):
|
+ if os.path.isfile("/etc/redhat-release"):
|
||||||
+ with salt.utils.files.fopen('/etc/redhat-release') as ifile:
|
+ with salt.utils.files.fopen("/etc/redhat-release") as ifile:
|
||||||
+ for line in ifile:
|
+ for line in ifile:
|
||||||
+ if "red hat enterprise linux server" in line.lower():
|
+ if "red hat enterprise linux server" in line.lower():
|
||||||
+ # This is a SUSE Expanded Support Rhel installation
|
+ # This is a SUSE Expanded Support Rhel installation
|
||||||
+ grains['lsb_distrib_id'] = 'RedHat'
|
+ grains["lsb_distrib_id"] = "RedHat"
|
||||||
+ break
|
+ break
|
||||||
with salt.utils.files.fopen('/etc/centos-release') as ifile:
|
with salt.utils.files.fopen("/etc/centos-release") as ifile:
|
||||||
for line in ifile:
|
for line in ifile:
|
||||||
# Need to pull out the version and codename
|
# Need to pull out the version and codename
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From dd01a0fc594f024eee2267bed2f698f5a6c729bf Mon Sep 17 00:00:00 2001
|
From 33766e59bd53fac2c75e6ccfa1f363e2f7b1b65f Mon Sep 17 00:00:00 2001
|
||||||
From: Jochen Breuer <jbreuer@suse.de>
|
From: Jochen Breuer <jbreuer@suse.de>
|
||||||
Date: Mon, 16 Mar 2020 15:25:42 +0100
|
Date: Mon, 16 Mar 2020 15:25:42 +0100
|
||||||
Subject: [PATCH] Fix for temp folder definition in loader unit test
|
Subject: [PATCH] Fix for temp folder definition in loader unit test
|
||||||
@ -8,13 +8,13 @@ Subject: [PATCH] Fix for temp folder definition in loader unit test
|
|||||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
diff --git a/tests/unit/test_loader.py b/tests/unit/test_loader.py
|
diff --git a/tests/unit/test_loader.py b/tests/unit/test_loader.py
|
||||||
index fe11cd0681..7e369f2c3b 100644
|
index 863e2182b9..5b23ad83e3 100644
|
||||||
--- a/tests/unit/test_loader.py
|
--- a/tests/unit/test_loader.py
|
||||||
+++ b/tests/unit/test_loader.py
|
+++ b/tests/unit/test_loader.py
|
||||||
@@ -152,12 +152,12 @@ class LazyLoaderUtilsTest(TestCase):
|
@@ -240,12 +240,12 @@ class LazyLoaderUtilsTest(TestCase):
|
||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
cls.opts = salt.config.minion_config(None)
|
cls.opts = salt.config.minion_config(None)
|
||||||
cls.opts['grains'] = salt.loader.grains(cls.opts)
|
cls.opts["grains"] = salt.loader.grains(cls.opts)
|
||||||
- if not os.path.isdir(TMP):
|
- if not os.path.isdir(TMP):
|
||||||
- os.makedirs(TMP)
|
- os.makedirs(TMP)
|
||||||
+ if not os.path.isdir(RUNTIME_VARS.TMP):
|
+ if not os.path.isdir(RUNTIME_VARS.TMP):
|
||||||
@ -24,19 +24,19 @@ index fe11cd0681..7e369f2c3b 100644
|
|||||||
# Setup the module
|
# Setup the module
|
||||||
- self.module_dir = tempfile.mkdtemp(dir=TMP)
|
- self.module_dir = tempfile.mkdtemp(dir=TMP)
|
||||||
+ self.module_dir = tempfile.mkdtemp(dir=RUNTIME_VARS.TMP)
|
+ self.module_dir = tempfile.mkdtemp(dir=RUNTIME_VARS.TMP)
|
||||||
self.module_file = os.path.join(self.module_dir,
|
self.module_file = os.path.join(
|
||||||
'{}.py'.format(self.module_name))
|
self.module_dir, "{}.py".format(self.module_name)
|
||||||
with salt.utils.files.fopen(self.module_file, 'w') as fh:
|
)
|
||||||
@@ -165,7 +165,7 @@ class LazyLoaderUtilsTest(TestCase):
|
@@ -254,7 +254,7 @@ class LazyLoaderUtilsTest(TestCase):
|
||||||
fh.flush()
|
fh.flush()
|
||||||
os.fsync(fh.fileno())
|
os.fsync(fh.fileno())
|
||||||
|
|
||||||
- self.utils_dir = tempfile.mkdtemp(dir=TMP)
|
- self.utils_dir = tempfile.mkdtemp(dir=TMP)
|
||||||
+ self.utils_dir = tempfile.mkdtemp(dir=RUNTIME_VARS.TMP)
|
+ self.utils_dir = tempfile.mkdtemp(dir=RUNTIME_VARS.TMP)
|
||||||
self.utils_file = os.path.join(self.utils_dir,
|
self.utils_file = os.path.join(self.utils_dir, "{}.py".format(self.utils_name))
|
||||||
'{}.py'.format(self.utils_name))
|
with salt.utils.files.fopen(self.utils_file, "w") as fh:
|
||||||
with salt.utils.files.fopen(self.utils_file, 'w') as fh:
|
fh.write(salt.utils.stringutils.to_str(loader_template_utils))
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From 900d63bc5e85496e16373025457561b405f2329f Mon Sep 17 00:00:00 2001
|
From f5c9527aeee190a66a908037770c80a75e911d8c Mon Sep 17 00:00:00 2001
|
||||||
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||||
<psuarezhernandez@suse.com>
|
<psuarezhernandez@suse.com>
|
||||||
Date: Tue, 6 Nov 2018 16:38:54 +0000
|
Date: Tue, 6 Nov 2018 16:38:54 +0000
|
||||||
@ -11,37 +11,42 @@ Test git ext_pillar across multiple repos using __env__
|
|||||||
|
|
||||||
Remove unicode references
|
Remove unicode references
|
||||||
---
|
---
|
||||||
tests/integration/pillar/test_git_pillar.py | 45 +++++++++++++++++++++++++++++
|
tests/integration/pillar/test_git_pillar.py | 55 +++++++++++++++++++++
|
||||||
1 file changed, 45 insertions(+)
|
1 file changed, 55 insertions(+)
|
||||||
|
|
||||||
diff --git a/tests/integration/pillar/test_git_pillar.py b/tests/integration/pillar/test_git_pillar.py
|
diff --git a/tests/integration/pillar/test_git_pillar.py b/tests/integration/pillar/test_git_pillar.py
|
||||||
index 2e549f3948..d417a7ebc3 100644
|
index c0362127f6..979dfebb94 100644
|
||||||
--- a/tests/integration/pillar/test_git_pillar.py
|
--- a/tests/integration/pillar/test_git_pillar.py
|
||||||
+++ b/tests/integration/pillar/test_git_pillar.py
|
+++ b/tests/integration/pillar/test_git_pillar.py
|
||||||
@@ -1382,6 +1382,51 @@ class TestPygit2SSH(GitPillarSSHTestBase):
|
@@ -1600,6 +1600,61 @@ class TestPygit2SSH(GitPillarSSHTestBase):
|
||||||
'nested_dict': {'master': True}}}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
+
|
+
|
||||||
+@skipIf(NO_MOCK, NO_MOCK_REASON)
|
+@skipIf(NO_MOCK, NO_MOCK_REASON)
|
||||||
+@skipIf(_windows_or_mac(), 'minion is windows or mac')
|
+@skipIf(_windows_or_mac(), "minion is windows or mac")
|
||||||
+@skip_if_not_root
|
+@skip_if_not_root
|
||||||
+@skipIf(not HAS_PYGIT2, 'pygit2 >= {0} and libgit2 >= {1} required'.format(PYGIT2_MINVER, LIBGIT2_MINVER))
|
+@skipIf(
|
||||||
+@skipIf(not HAS_NGINX, 'nginx not present')
|
+ not HAS_PYGIT2,
|
||||||
+@skipIf(not HAS_VIRTUALENV, 'virtualenv not present')
|
+ "pygit2 >= {} and libgit2 >= {} required".format(PYGIT2_MINVER, LIBGIT2_MINVER),
|
||||||
|
+)
|
||||||
|
+@skipIf(not HAS_NGINX, "nginx not present")
|
||||||
|
+@skipIf(not HAS_VIRTUALENV, "virtualenv not present")
|
||||||
+class TestPygit2HTTP(GitPillarHTTPTestBase):
|
+class TestPygit2HTTP(GitPillarHTTPTestBase):
|
||||||
+ '''
|
+ """
|
||||||
+ Test git_pillar with pygit2 using SSH authentication
|
+ Test git_pillar with pygit2 using SSH authentication
|
||||||
+ '''
|
+ """
|
||||||
|
+
|
||||||
+ def test_single_source(self):
|
+ def test_single_source(self):
|
||||||
+ '''
|
+ """
|
||||||
+ Test with git_pillar_includes enabled and using "__env__" as the branch
|
+ Test with git_pillar_includes enabled and using "__env__" as the branch
|
||||||
+ name for the configured repositories.
|
+ name for the configured repositories.
|
||||||
+ The "gitinfo" repository contains top.sls file with a local reference
|
+ The "gitinfo" repository contains top.sls file with a local reference
|
||||||
+ and also referencing external "nowhere.foo" which is provided by "webinfo"
|
+ and also referencing external "nowhere.foo" which is provided by "webinfo"
|
||||||
+ repository mounted as "nowhere".
|
+ repository mounted as "nowhere".
|
||||||
+ '''
|
+ """
|
||||||
+ ret = self.get_pillar('''\
|
+ ret = self.get_pillar(
|
||||||
|
+ """\
|
||||||
+ file_ignore_regex: []
|
+ file_ignore_regex: []
|
||||||
+ file_ignore_glob: []
|
+ file_ignore_glob: []
|
||||||
+ git_pillar_provider: pygit2
|
+ git_pillar_provider: pygit2
|
||||||
@ -56,21 +61,26 @@ index 2e549f3948..d417a7ebc3 100644
|
|||||||
+ - __env__ {url}:
|
+ - __env__ {url}:
|
||||||
+ - name: webinfo
|
+ - name: webinfo
|
||||||
+ - mountpoint: nowhere
|
+ - mountpoint: nowhere
|
||||||
+ ''')
|
+ """
|
||||||
|
+ )
|
||||||
+ self.assertEqual(
|
+ self.assertEqual(
|
||||||
+ ret,
|
+ ret,
|
||||||
+ {'branch': 'master',
|
+ {
|
||||||
+ 'motd': 'The force will be with you. Always.',
|
+ "branch": "master",
|
||||||
+ 'mylist': ['master'],
|
+ "motd": "The force will be with you. Always.",
|
||||||
+ 'mydict': {'master': True,
|
+ "mylist": ["master"],
|
||||||
+ 'nested_list': ['master'],
|
+ "mydict": {
|
||||||
+ 'nested_dict': {'master': True}}}
|
+ "master": True,
|
||||||
|
+ "nested_list": ["master"],
|
||||||
|
+ "nested_dict": {"master": True},
|
||||||
|
+ },
|
||||||
|
+ },
|
||||||
+ )
|
+ )
|
||||||
+
|
+
|
||||||
@requires_system_grains
|
@slowTest
|
||||||
def test_root_parameter(self, grains):
|
def test_root_parameter(self):
|
||||||
'''
|
"""
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From 4998996a08db72a1b925b2c3f725c4fba4fe9622 Mon Sep 17 00:00:00 2001
|
From e2ff2f339ce7938ecdadf867f285a559bc2431dd Mon Sep 17 00:00:00 2001
|
||||||
From: Dominik Gedon <dgedon@suse.de>
|
From: Dominik Gedon <dgedon@suse.de>
|
||||||
Date: Tue, 6 Oct 2020 14:00:55 +0200
|
Date: Tue, 6 Oct 2020 14:00:55 +0200
|
||||||
Subject: [PATCH] Fix grains.test_core unit test (#277)
|
Subject: [PATCH] Fix grains.test_core unit test (#277)
|
||||||
@ -6,41 +6,38 @@ Subject: [PATCH] Fix grains.test_core unit test (#277)
|
|||||||
This reverts 63b94ae and fixes the grains test_core unit test. The
|
This reverts 63b94ae and fixes the grains test_core unit test. The
|
||||||
changes are aligned with upstream.
|
changes are aligned with upstream.
|
||||||
---
|
---
|
||||||
tests/unit/grains/test_core.py | 13 ++++++++-----
|
tests/unit/grains/test_core.py | 9 ++++-----
|
||||||
1 file changed, 8 insertions(+), 5 deletions(-)
|
1 file changed, 4 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
diff --git a/tests/unit/grains/test_core.py b/tests/unit/grains/test_core.py
|
diff --git a/tests/unit/grains/test_core.py b/tests/unit/grains/test_core.py
|
||||||
index 36aa49f232..d3b6515d00 100644
|
index 918a9155cb..15de4e363e 100644
|
||||||
--- a/tests/unit/grains/test_core.py
|
--- a/tests/unit/grains/test_core.py
|
||||||
+++ b/tests/unit/grains/test_core.py
|
+++ b/tests/unit/grains/test_core.py
|
||||||
@@ -69,10 +69,11 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -60,11 +60,10 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
def test_parse_etc_os_release(self, path_isfile_mock):
|
with salt.utils.files.fopen(
|
||||||
path_isfile_mock.side_effect = lambda x: x == "/usr/lib/os-release"
|
os.path.join(OS_RELEASE_DIR, "ubuntu-17.10")
|
||||||
with salt.utils.files.fopen(os.path.join(OS_RELEASE_DIR, "ubuntu-17.10")) as os_release_file:
|
) as os_release_file:
|
||||||
- os_release_content = os_release_file.readlines()
|
- os_release_content = os_release_file.readlines()
|
||||||
- with patch("salt.utils.files.fopen", mock_open()) as os_release_file:
|
- with patch("salt.utils.files.fopen", mock_open()) as os_release_file:
|
||||||
- os_release_file.return_value.__iter__.return_value = os_release_content
|
- os_release_file.return_value.__iter__.return_value = os_release_content
|
||||||
- os_release = core._parse_os_release(["/etc/os-release", "/usr/lib/os-release"])
|
|
||||||
+ os_release_content = os_release_file.read()
|
+ os_release_content = os_release_file.read()
|
||||||
+ with patch("salt.utils.files.fopen", mock_open(read_data=os_release_content)):
|
+ with patch("salt.utils.files.fopen", mock_open(read_data=os_release_content)):
|
||||||
+ os_release = core._parse_os_release(
|
os_release = core._parse_os_release(
|
||||||
|
- ["/etc/os-release", "/usr/lib/os-release"]
|
||||||
+ "/etc/os-release", "/usr/lib/os-release"
|
+ "/etc/os-release", "/usr/lib/os-release"
|
||||||
+ )
|
)
|
||||||
self.assertEqual(os_release, {
|
self.assertEqual(
|
||||||
"NAME": "Ubuntu",
|
os_release,
|
||||||
"VERSION": "17.10 (Artful Aardvark)",
|
@@ -174,7 +173,7 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
@@ -134,7 +135,9 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
|
|
||||||
|
|
||||||
def test_missing_os_release(self):
|
def test_missing_os_release(self):
|
||||||
with patch('salt.utils.files.fopen', mock_open(read_data={})):
|
with patch("salt.utils.files.fopen", mock_open(read_data={})):
|
||||||
- os_release = core._parse_os_release(['/etc/os-release', '/usr/lib/os-release'])
|
os_release = core._parse_os_release(
|
||||||
+ os_release = core._parse_os_release(
|
- ["/etc/os-release", "/usr/lib/os-release"]
|
||||||
+ "/etc/os-release", "/usr/lib/os-release"
|
+ "/etc/os-release", "/usr/lib/os-release"
|
||||||
+ )
|
)
|
||||||
self.assertEqual(os_release, {})
|
self.assertEqual(os_release, {})
|
||||||
|
|
||||||
@skipIf(not salt.utils.platform.is_windows(), 'System is not Windows')
|
|
||||||
--
|
--
|
||||||
2.28.0
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From 2cb7515f83e2c358b84724e4eb581daa78012fdf Mon Sep 17 00:00:00 2001
|
From 082bb6a25b2b025a5c7c6fdbf7dbcbe64a39da2c Mon Sep 17 00:00:00 2001
|
||||||
From: Bo Maryniuk <bo@suse.de>
|
From: Bo Maryniuk <bo@suse.de>
|
||||||
Date: Fri, 28 Sep 2018 15:22:33 +0200
|
Date: Fri, 28 Sep 2018 15:22:33 +0200
|
||||||
Subject: [PATCH] Fix IPv6 scope (bsc#1108557)
|
Subject: [PATCH] Fix IPv6 scope (bsc#1108557)
|
||||||
@ -69,14 +69,14 @@ Lintfix: W0611
|
|||||||
|
|
||||||
Reverse skipping tests: if no ipaddress
|
Reverse skipping tests: if no ipaddress
|
||||||
---
|
---
|
||||||
salt/_compat.py | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
salt/_compat.py | 74 +++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
1 file changed, 74 insertions(+)
|
1 file changed, 74 insertions(+)
|
||||||
|
|
||||||
diff --git a/salt/_compat.py b/salt/_compat.py
|
diff --git a/salt/_compat.py b/salt/_compat.py
|
||||||
index e999605d2c..965bb90da3 100644
|
index 011eb8af9e..d9425523cf 100644
|
||||||
--- a/salt/_compat.py
|
--- a/salt/_compat.py
|
||||||
+++ b/salt/_compat.py
|
+++ b/salt/_compat.py
|
||||||
@@ -230,7 +230,81 @@ class IPv6InterfaceScoped(ipaddress.IPv6Interface, IPv6AddressScoped):
|
@@ -242,7 +242,81 @@ class IPv6InterfaceScoped(ipaddress.IPv6Interface, IPv6AddressScoped):
|
||||||
self.hostmask = self.network.hostmask
|
self.hostmask = self.network.hostmask
|
||||||
|
|
||||||
|
|
||||||
@ -159,6 +159,6 @@ index e999605d2c..965bb90da3 100644
|
|||||||
+ ipaddress.ip_address = ip_address
|
+ ipaddress.ip_address = ip_address
|
||||||
+ ipaddress.ip_interface = ip_interface
|
+ ipaddress.ip_interface = ip_interface
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From bfdd7f946d56d799e89b33f7e3b72426732b0195 Mon Sep 17 00:00:00 2001
|
From db77ad3e24daf3bc014dc3d85a49aa1bb33ae1ae Mon Sep 17 00:00:00 2001
|
||||||
From: Bo Maryniuk <bo@suse.de>
|
From: Bo Maryniuk <bo@suse.de>
|
||||||
Date: Wed, 9 Jan 2019 16:08:19 +0100
|
Date: Wed, 9 Jan 2019 16:08:19 +0100
|
||||||
Subject: [PATCH] Fix issue #2068 test
|
Subject: [PATCH] Fix issue #2068 test
|
||||||
@ -13,19 +13,19 @@ Minor update: more correct is-dict check.
|
|||||||
1 file changed, 6 insertions(+), 3 deletions(-)
|
1 file changed, 6 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/state.py b/salt/state.py
|
diff --git a/salt/state.py b/salt/state.py
|
||||||
index bc5277554e..2fa5f64ca5 100644
|
index b1bce4e0cd..cc6db7e1b2 100644
|
||||||
--- a/salt/state.py
|
--- a/salt/state.py
|
||||||
+++ b/salt/state.py
|
+++ b/salt/state.py
|
||||||
@@ -25,6 +25,7 @@ import traceback
|
@@ -12,6 +12,7 @@ The data sent to the state calls is as follows:
|
||||||
import re
|
"""
|
||||||
import time
|
|
||||||
import random
|
|
||||||
+import collections
|
|
||||||
|
|
||||||
# Import salt libs
|
|
||||||
import salt.loader
|
+import collections
|
||||||
@@ -2896,16 +2897,18 @@ class State(object):
|
import copy
|
||||||
'''
|
import datetime
|
||||||
|
import fnmatch
|
||||||
|
@@ -3206,16 +3207,18 @@ class State:
|
||||||
|
"""
|
||||||
for chunk in high:
|
for chunk in high:
|
||||||
state = high[chunk]
|
state = high[chunk]
|
||||||
+ if not isinstance(state, collections.Mapping):
|
+ if not isinstance(state, collections.Mapping):
|
||||||
@ -35,18 +35,18 @@ index bc5277554e..2fa5f64ca5 100644
|
|||||||
+ if not isinstance(state[state_ref], list):
|
+ if not isinstance(state[state_ref], list):
|
||||||
+ continue
|
+ continue
|
||||||
for argset in state[state_ref]:
|
for argset in state[state_ref]:
|
||||||
if isinstance(argset, six.string_types):
|
if isinstance(argset, str):
|
||||||
needs_default = False
|
needs_default = False
|
||||||
break
|
break
|
||||||
if needs_default:
|
if needs_default:
|
||||||
- order = state[state_ref].pop(-1)
|
- order = state[state_ref].pop(-1)
|
||||||
- state[state_ref].append('__call__')
|
- state[state_ref].append("__call__")
|
||||||
- state[state_ref].append(order)
|
- state[state_ref].append(order)
|
||||||
+ state[state_ref].insert(-1, '__call__')
|
+ state[state_ref].insert(-1, "__call__")
|
||||||
|
|
||||||
def call_high(self, high, orchestration_jid=None):
|
def call_high(self, high, orchestration_jid=None):
|
||||||
'''
|
"""
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From 77d53d9567b7aec045a8fffd29afcb76a8405caf Mon Sep 17 00:00:00 2001
|
From 00c538383e463febba492e74577ae64be80d4d00 Mon Sep 17 00:00:00 2001
|
||||||
From: Mihai Dinca <mdinca@suse.de>
|
From: Mihai Dinca <mdinca@suse.de>
|
||||||
Date: Mon, 16 Sep 2019 11:27:30 +0200
|
Date: Mon, 16 Sep 2019 11:27:30 +0200
|
||||||
Subject: [PATCH] Fix memory leak produced by batch async find_jobs
|
Subject: [PATCH] Fix memory leak produced by batch async find_jobs
|
||||||
@ -16,16 +16,16 @@ Multiple fixes:
|
|||||||
|
|
||||||
Co-authored-by: Pablo Suárez Hernández <psuarezhernandez@suse.com>
|
Co-authored-by: Pablo Suárez Hernández <psuarezhernandez@suse.com>
|
||||||
---
|
---
|
||||||
salt/cli/batch_async.py | 60 ++++++++++++++++++++++++++++++++-----------------
|
salt/cli/batch_async.py | 59 ++++++++++++++++++++++++++++-------------
|
||||||
salt/client/__init__.py | 1 +
|
salt/client/__init__.py | 1 +
|
||||||
salt/master.py | 1 -
|
salt/master.py | 2 --
|
||||||
3 files changed, 41 insertions(+), 21 deletions(-)
|
3 files changed, 41 insertions(+), 21 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/cli/batch_async.py b/salt/cli/batch_async.py
|
diff --git a/salt/cli/batch_async.py b/salt/cli/batch_async.py
|
||||||
index 8c8f481e34..8a67331102 100644
|
index 7225491228..388b709416 100644
|
||||||
--- a/salt/cli/batch_async.py
|
--- a/salt/cli/batch_async.py
|
||||||
+++ b/salt/cli/batch_async.py
|
+++ b/salt/cli/batch_async.py
|
||||||
@@ -72,6 +72,7 @@ class BatchAsync(object):
|
@@ -73,6 +73,7 @@ class BatchAsync:
|
||||||
self.done_minions = set()
|
self.done_minions = set()
|
||||||
self.active = set()
|
self.active = set()
|
||||||
self.initialized = False
|
self.initialized = False
|
||||||
@ -33,55 +33,58 @@ index 8c8f481e34..8a67331102 100644
|
|||||||
self.ping_jid = jid_gen()
|
self.ping_jid = jid_gen()
|
||||||
self.batch_jid = jid_gen()
|
self.batch_jid = jid_gen()
|
||||||
self.find_job_jid = jid_gen()
|
self.find_job_jid = jid_gen()
|
||||||
@@ -89,14 +90,11 @@ class BatchAsync(object):
|
@@ -91,14 +92,11 @@ class BatchAsync:
|
||||||
def __set_event_handler(self):
|
def __set_event_handler(self):
|
||||||
ping_return_pattern = 'salt/job/{0}/ret/*'.format(self.ping_jid)
|
ping_return_pattern = "salt/job/{}/ret/*".format(self.ping_jid)
|
||||||
batch_return_pattern = 'salt/job/{0}/ret/*'.format(self.batch_jid)
|
batch_return_pattern = "salt/job/{}/ret/*".format(self.batch_jid)
|
||||||
- find_job_return_pattern = 'salt/job/{0}/ret/*'.format(self.find_job_jid)
|
- find_job_return_pattern = "salt/job/{}/ret/*".format(self.find_job_jid)
|
||||||
self.event.subscribe(ping_return_pattern, match_type='glob')
|
self.event.subscribe(ping_return_pattern, match_type="glob")
|
||||||
self.event.subscribe(batch_return_pattern, match_type='glob')
|
self.event.subscribe(batch_return_pattern, match_type="glob")
|
||||||
- self.event.subscribe(find_job_return_pattern, match_type='glob')
|
- self.event.subscribe(find_job_return_pattern, match_type="glob")
|
||||||
- self.event.patterns = {
|
- self.event.patterns = {
|
||||||
+ self.patterns = {
|
+ self.patterns = {
|
||||||
(ping_return_pattern, 'ping_return'),
|
(ping_return_pattern, "ping_return"),
|
||||||
(batch_return_pattern, 'batch_run'),
|
(batch_return_pattern, "batch_run"),
|
||||||
- (find_job_return_pattern, 'find_job_return')
|
- (find_job_return_pattern, "find_job_return"),
|
||||||
}
|
}
|
||||||
self.event.set_event_handler(self.__event_handler)
|
self.event.set_event_handler(self.__event_handler)
|
||||||
|
|
||||||
@@ -104,7 +102,7 @@ class BatchAsync(object):
|
@@ -106,7 +104,7 @@ class BatchAsync:
|
||||||
if not self.event:
|
if not self.event:
|
||||||
return
|
return
|
||||||
mtag, data = self.event.unpack(raw, self.event.serial)
|
mtag, data = self.event.unpack(raw, self.event.serial)
|
||||||
- for (pattern, op) in self.event.patterns:
|
- for (pattern, op) in self.event.patterns:
|
||||||
+ for (pattern, op) in self.patterns:
|
+ for (pattern, op) in self.patterns:
|
||||||
if fnmatch.fnmatch(mtag, pattern):
|
if fnmatch.fnmatch(mtag, pattern):
|
||||||
minion = data['id']
|
minion = data["id"]
|
||||||
if op == 'ping_return':
|
if op == "ping_return":
|
||||||
@@ -112,7 +110,8 @@ class BatchAsync(object):
|
@@ -114,7 +112,8 @@ class BatchAsync:
|
||||||
if self.targeted_minions == self.minions:
|
if self.targeted_minions == self.minions:
|
||||||
self.event.io_loop.spawn_callback(self.start_batch)
|
self.event.io_loop.spawn_callback(self.start_batch)
|
||||||
elif op == 'find_job_return':
|
elif op == "find_job_return":
|
||||||
- self.find_job_returned.add(minion)
|
- self.find_job_returned.add(minion)
|
||||||
+ if data.get("return", None):
|
+ if data.get("return", None):
|
||||||
+ self.find_job_returned.add(minion)
|
+ self.find_job_returned.add(minion)
|
||||||
elif op == 'batch_run':
|
elif op == "batch_run":
|
||||||
if minion in self.active:
|
if minion in self.active:
|
||||||
self.active.remove(minion)
|
self.active.remove(minion)
|
||||||
@@ -131,31 +130,46 @@ class BatchAsync(object):
|
@@ -134,7 +133,11 @@ class BatchAsync:
|
||||||
return set(list(to_run)[:next_batch_size])
|
return set(list(to_run)[:next_batch_size])
|
||||||
|
|
||||||
@tornado.gen.coroutine
|
@tornado.gen.coroutine
|
||||||
- def check_find_job(self, batch_minions):
|
- def check_find_job(self, batch_minions):
|
||||||
+ def check_find_job(self, batch_minions, jid):
|
+ def check_find_job(self, batch_minions, jid):
|
||||||
+ find_job_return_pattern = 'salt/job/{0}/ret/*'.format(jid)
|
+ find_job_return_pattern = "salt/job/{}/ret/*".format(jid)
|
||||||
+ self.event.unsubscribe(find_job_return_pattern, match_type='glob')
|
+ self.event.unsubscribe(find_job_return_pattern, match_type="glob")
|
||||||
+ self.patterns.remove((find_job_return_pattern, "find_job_return"))
|
+ self.patterns.remove((find_job_return_pattern, "find_job_return"))
|
||||||
+
|
+
|
||||||
timedout_minions = batch_minions.difference(self.find_job_returned).difference(self.done_minions)
|
timedout_minions = batch_minions.difference(self.find_job_returned).difference(
|
||||||
self.timedout_minions = self.timedout_minions.union(timedout_minions)
|
self.done_minions
|
||||||
self.active = self.active.difference(self.timedout_minions)
|
)
|
||||||
running = batch_minions.difference(self.done_minions).difference(self.timedout_minions)
|
@@ -143,27 +146,39 @@ class BatchAsync:
|
||||||
|
running = batch_minions.difference(self.done_minions).difference(
|
||||||
|
self.timedout_minions
|
||||||
|
)
|
||||||
+
|
+
|
||||||
if timedout_minions:
|
if timedout_minions:
|
||||||
self.schedule_next()
|
self.schedule_next()
|
||||||
@ -95,56 +98,59 @@ index 8c8f481e34..8a67331102 100644
|
|||||||
- not_done = minions.difference(self.done_minions)
|
- not_done = minions.difference(self.done_minions)
|
||||||
- ping_return = yield self.local.run_job_async(
|
- ping_return = yield self.local.run_job_async(
|
||||||
- not_done,
|
- not_done,
|
||||||
- 'saltutil.find_job',
|
- "saltutil.find_job",
|
||||||
- [self.batch_jid],
|
- [self.batch_jid],
|
||||||
- 'list',
|
- "list",
|
||||||
- gather_job_timeout=self.opts['gather_job_timeout'],
|
- gather_job_timeout=self.opts["gather_job_timeout"],
|
||||||
- jid=self.find_job_jid,
|
- jid=self.find_job_jid,
|
||||||
- **self.eauth)
|
- **self.eauth
|
||||||
|
- )
|
||||||
- self.event.io_loop.call_later(
|
- self.event.io_loop.call_later(
|
||||||
- self.opts['gather_job_timeout'],
|
- self.opts["gather_job_timeout"], self.check_find_job, not_done
|
||||||
- self.check_find_job,
|
+ not_done = minions.difference(self.done_minions).difference(
|
||||||
- not_done)
|
+ self.timedout_minions
|
||||||
+ not_done = minions.difference(self.done_minions).difference(self.timedout_minions)
|
)
|
||||||
+
|
|
||||||
+ if not_done:
|
+ if not_done:
|
||||||
+ jid = self.jid_gen()
|
+ jid = self.jid_gen()
|
||||||
+ find_job_return_pattern = 'salt/job/{0}/ret/*'.format(jid)
|
+ find_job_return_pattern = "salt/job/{}/ret/*".format(jid)
|
||||||
+ self.patterns.add((find_job_return_pattern, "find_job_return"))
|
+ self.patterns.add((find_job_return_pattern, "find_job_return"))
|
||||||
+ self.event.subscribe(find_job_return_pattern, match_type='glob')
|
+ self.event.subscribe(find_job_return_pattern, match_type="glob")
|
||||||
+
|
+
|
||||||
+ ret = yield self.local.run_job_async(
|
+ ret = yield self.local.run_job_async(
|
||||||
+ not_done,
|
+ not_done,
|
||||||
+ 'saltutil.find_job',
|
+ "saltutil.find_job",
|
||||||
+ [self.batch_jid],
|
+ [self.batch_jid],
|
||||||
+ 'list',
|
+ "list",
|
||||||
+ gather_job_timeout=self.opts['gather_job_timeout'],
|
+ gather_job_timeout=self.opts["gather_job_timeout"],
|
||||||
+ jid=jid,
|
+ jid=jid,
|
||||||
+ **self.eauth)
|
+ **self.eauth
|
||||||
|
+ )
|
||||||
+ self.event.io_loop.call_later(
|
+ self.event.io_loop.call_later(
|
||||||
+ self.opts['gather_job_timeout'],
|
+ self.opts["gather_job_timeout"], self.check_find_job, not_done, jid
|
||||||
+ self.check_find_job,
|
+ )
|
||||||
+ not_done,
|
+
|
||||||
+ jid)
|
|
||||||
|
|
||||||
@tornado.gen.coroutine
|
@tornado.gen.coroutine
|
||||||
def start(self):
|
def start(self):
|
||||||
@@ -203,6 +217,9 @@ class BatchAsync(object):
|
self.__set_event_handler()
|
||||||
|
@@ -211,6 +226,9 @@ class BatchAsync:
|
||||||
}
|
}
|
||||||
self.event.fire_event(data, "salt/batch/{0}/done".format(self.batch_jid))
|
self.event.fire_event(data, "salt/batch/{}/done".format(self.batch_jid))
|
||||||
self.event.remove_event_handler(self.__event_handler)
|
self.event.remove_event_handler(self.__event_handler)
|
||||||
+ for (pattern, label) in self.patterns:
|
+ for (pattern, label) in self.patterns:
|
||||||
+ if label in ["ping_return", "batch_run"]:
|
+ if label in ["ping_return", "batch_run"]:
|
||||||
+ self.event.unsubscribe(pattern, match_type='glob')
|
+ self.event.unsubscribe(pattern, match_type="glob")
|
||||||
|
|
||||||
def schedule_next(self):
|
def schedule_next(self):
|
||||||
if not self.scheduled:
|
if not self.scheduled:
|
||||||
@@ -226,9 +243,12 @@ class BatchAsync(object):
|
@@ -235,11 +253,14 @@ class BatchAsync:
|
||||||
gather_job_timeout=self.opts['gather_job_timeout'],
|
|
||||||
jid=self.batch_jid,
|
jid=self.batch_jid,
|
||||||
metadata=self.metadata)
|
metadata=self.metadata,
|
||||||
|
)
|
||||||
+
|
+
|
||||||
self.event.io_loop.call_later(self.opts['timeout'], self.find_job, set(next_batch))
|
self.event.io_loop.call_later(
|
||||||
|
self.opts["timeout"], self.find_job, set(next_batch)
|
||||||
|
)
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
+ log.error("Error in scheduling next batch: %s", ex)
|
+ log.error("Error in scheduling next batch: %s", ex)
|
||||||
self.active = self.active.difference(next_batch)
|
self.active = self.active.difference(next_batch)
|
||||||
@ -153,30 +159,31 @@ index 8c8f481e34..8a67331102 100644
|
|||||||
self.scheduled = False
|
self.scheduled = False
|
||||||
+ yield
|
+ yield
|
||||||
diff --git a/salt/client/__init__.py b/salt/client/__init__.py
|
diff --git a/salt/client/__init__.py b/salt/client/__init__.py
|
||||||
index 3bbc7f9de7..a48d79ef8d 100644
|
index 1e9f11df4c..cc8fd4048d 100644
|
||||||
--- a/salt/client/__init__.py
|
--- a/salt/client/__init__.py
|
||||||
+++ b/salt/client/__init__.py
|
+++ b/salt/client/__init__.py
|
||||||
@@ -1622,6 +1622,7 @@ class LocalClient(object):
|
@@ -1776,6 +1776,7 @@ class LocalClient:
|
||||||
'key': self.key,
|
"key": self.key,
|
||||||
'tgt_type': tgt_type,
|
"tgt_type": tgt_type,
|
||||||
'ret': ret,
|
"ret": ret,
|
||||||
+ 'timeout': timeout,
|
+ "timeout": timeout,
|
||||||
'jid': jid}
|
"jid": jid,
|
||||||
|
}
|
||||||
|
|
||||||
# if kwargs are passed, pack them.
|
|
||||||
diff --git a/salt/master.py b/salt/master.py
|
diff --git a/salt/master.py b/salt/master.py
|
||||||
index 5e2277ba76..3abf7ae60b 100644
|
index b9bc1a7a67..7a99af357a 100644
|
||||||
--- a/salt/master.py
|
--- a/salt/master.py
|
||||||
+++ b/salt/master.py
|
+++ b/salt/master.py
|
||||||
@@ -2044,7 +2044,6 @@ class ClearFuncs(object):
|
@@ -2232,8 +2232,6 @@ class ClearFuncs(TransportMethods):
|
||||||
def publish_batch(self, clear_load, minions, missing):
|
def publish_batch(self, clear_load, minions, missing):
|
||||||
batch_load = {}
|
batch_load = {}
|
||||||
batch_load.update(clear_load)
|
batch_load.update(clear_load)
|
||||||
- import salt.cli.batch_async
|
- import salt.cli.batch_async
|
||||||
|
-
|
||||||
batch = salt.cli.batch_async.BatchAsync(
|
batch = salt.cli.batch_async.BatchAsync(
|
||||||
self.local.opts,
|
self.local.opts,
|
||||||
functools.partial(self._prep_jid, clear_load, {}),
|
functools.partial(self._prep_jid, clear_load, {}),
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From f69c1178de003866af412e61e0146597974eec0d Mon Sep 17 00:00:00 2001
|
From 4123cf7b9428af1442f4aa0a54489e5c0deb4aaa Mon Sep 17 00:00:00 2001
|
||||||
From: Martin Seidl <mseidl@suse.de>
|
From: Martin Seidl <mseidl@suse.de>
|
||||||
Date: Tue, 27 Oct 2020 16:12:29 +0100
|
Date: Tue, 27 Oct 2020 16:12:29 +0100
|
||||||
Subject: [PATCH] Fix novendorchange option (#284)
|
Subject: [PATCH] Fix novendorchange option (#284)
|
||||||
@ -7,15 +7,15 @@ Subject: [PATCH] Fix novendorchange option (#284)
|
|||||||
|
|
||||||
* refactor handling of novendorchange and fix tests
|
* refactor handling of novendorchange and fix tests
|
||||||
---
|
---
|
||||||
salt/modules/zypperpkg.py | 19 ++--
|
salt/modules/zypperpkg.py | 21 +++---
|
||||||
tests/unit/modules/test_zypperpkg.py | 150 ++++++++++++++++++++++++---
|
tests/unit/modules/test_zypperpkg.py | 100 ++++++++++++++++++++++++++-
|
||||||
2 files changed, 148 insertions(+), 21 deletions(-)
|
2 files changed, 108 insertions(+), 13 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py
|
diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py
|
||||||
index ad11da4ad1..d84a6af6e0 100644
|
index 5369a0342e..d06c265202 100644
|
||||||
--- a/salt/modules/zypperpkg.py
|
--- a/salt/modules/zypperpkg.py
|
||||||
+++ b/salt/modules/zypperpkg.py
|
+++ b/salt/modules/zypperpkg.py
|
||||||
@@ -1617,7 +1617,7 @@ def upgrade(refresh=True,
|
@@ -1707,7 +1707,7 @@ def upgrade(
|
||||||
dryrun=False,
|
dryrun=False,
|
||||||
dist_upgrade=False,
|
dist_upgrade=False,
|
||||||
fromrepo=None,
|
fromrepo=None,
|
||||||
@ -24,22 +24,26 @@ index ad11da4ad1..d84a6af6e0 100644
|
|||||||
skip_verify=False,
|
skip_verify=False,
|
||||||
no_recommends=False,
|
no_recommends=False,
|
||||||
root=None,
|
root=None,
|
||||||
@@ -1701,13 +1701,18 @@ def upgrade(refresh=True,
|
@@ -1794,19 +1794,18 @@ def upgrade(
|
||||||
log.info('Targeting repos: %s', fromrepo)
|
log.info("Targeting repos: %s", fromrepo)
|
||||||
|
|
||||||
if dist_upgrade:
|
if dist_upgrade:
|
||||||
- if novendorchange:
|
- if novendorchange:
|
||||||
- # TODO: Grains validation should be moved to Zypper class
|
- # TODO: Grains validation should be moved to Zypper class
|
||||||
- if __grains__['osrelease_info'][0] > 11:
|
- if __grains__["osrelease_info"][0] > 11:
|
||||||
- cmd_update.append('--no-allow-vendor-change')
|
|
||||||
- log.info('Disabling vendor changes')
|
|
||||||
+ # TODO: Grains validation should be moved to Zypper class
|
+ # TODO: Grains validation should be moved to Zypper class
|
||||||
+ if __grains__["osrelease_info"][0] > 11:
|
+ if __grains__["osrelease_info"][0] > 11:
|
||||||
+ if novendorchange:
|
+ if novendorchange:
|
||||||
+ cmd_update.append("--no-allow-vendor-change")
|
cmd_update.append("--no-allow-vendor-change")
|
||||||
+ log.info("Disabling vendor changes")
|
log.info("Disabling vendor changes")
|
||||||
else:
|
else:
|
||||||
- log.warning('Disabling vendor changes is not supported on this Zypper version')
|
- log.warning(
|
||||||
|
- "Disabling vendor changes is not supported on this Zypper version"
|
||||||
|
- )
|
||||||
|
-
|
||||||
|
- if no_recommends:
|
||||||
|
- cmd_update.append("--no-recommends")
|
||||||
|
- log.info("Disabling recommendations")
|
||||||
+ cmd_update.append("--allow-vendor-change")
|
+ cmd_update.append("--allow-vendor-change")
|
||||||
+ log.info("Enabling vendor changes")
|
+ log.info("Enabling vendor changes")
|
||||||
+ else:
|
+ else:
|
||||||
@ -48,121 +52,26 @@ index ad11da4ad1..d84a6af6e0 100644
|
|||||||
+ )
|
+ )
|
||||||
|
|
||||||
if no_recommends:
|
if no_recommends:
|
||||||
cmd_update.append('--no-recommends')
|
cmd_update.append("--no-recommends")
|
||||||
diff --git a/tests/unit/modules/test_zypperpkg.py b/tests/unit/modules/test_zypperpkg.py
|
diff --git a/tests/unit/modules/test_zypperpkg.py b/tests/unit/modules/test_zypperpkg.py
|
||||||
index a3d20f66d5..8cc84485b5 100644
|
index a60b1546c6..eaa4d9a76a 100644
|
||||||
--- a/tests/unit/modules/test_zypperpkg.py
|
--- a/tests/unit/modules/test_zypperpkg.py
|
||||||
+++ b/tests/unit/modules/test_zypperpkg.py
|
+++ b/tests/unit/modules/test_zypperpkg.py
|
||||||
@@ -480,7 +480,11 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -642,7 +642,9 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
with patch('salt.modules.zypperpkg.list_pkgs', MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.2"}])):
|
|
||||||
ret = zypper.upgrade(dist_upgrade=True)
|
ret = zypper.upgrade(dist_upgrade=True)
|
||||||
self.assertDictEqual(ret, {"vim": {"old": "1.1", "new": "1.2"}})
|
self.assertDictEqual(ret, {"vim": {"old": "1.1", "new": "1.2"}})
|
||||||
- zypper_mock.assert_any_call('dist-upgrade', '--auto-agree-with-licenses')
|
zypper_mock.assert_any_call(
|
||||||
+ zypper_mock.assert_any_call(
|
- "dist-upgrade", "--auto-agree-with-licenses"
|
||||||
+ "dist-upgrade",
|
+ "dist-upgrade",
|
||||||
+ "--auto-agree-with-licenses",
|
+ "--auto-agree-with-licenses",
|
||||||
+ "--no-allow-vendor-change",
|
+ "--no-allow-vendor-change",
|
||||||
+ )
|
)
|
||||||
|
|
||||||
with patch('salt.modules.zypperpkg.list_pkgs', MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.1"}])):
|
with patch(
|
||||||
ret = zypper.upgrade(dist_upgrade=True, dryrun=True)
|
@@ -660,6 +662,76 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
@@ -488,25 +492,138 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin):
|
"--debug-solver",
|
||||||
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=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', '--no-allow-vendor-change')
|
|
||||||
- zypper_mock.assert_any_call('dist-upgrade', '--auto-agree-with-licenses', '--dry-run',
|
|
||||||
- '--from', "Dummy", '--from', 'Dummy2', '--no-allow-vendor-change',
|
|
||||||
- '--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.2"}])):
|
|
||||||
ret = zypper.upgrade(dist_upgrade=True, fromrepo=["Dummy", "Dummy2"], novendorchange=True)
|
|
||||||
+ zypper_mock.assert_any_call(
|
|
||||||
+ "dist-upgrade",
|
|
||||||
+ "--auto-agree-with-licenses",
|
|
||||||
+ "--dry-run",
|
|
||||||
+ "--no-allow-vendor-change",
|
|
||||||
+ )
|
|
||||||
+ zypper_mock.assert_any_call(
|
|
||||||
+ "dist-upgrade",
|
|
||||||
+ "--auto-agree-with-licenses",
|
|
||||||
+ "--dry-run",
|
|
||||||
+ "--no-allow-vendor-change",
|
|
||||||
+ )
|
|
||||||
+
|
|
||||||
+ 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=False,
|
|
||||||
+ )
|
|
||||||
+ zypper_mock.assert_any_call(
|
|
||||||
+ "dist-upgrade",
|
|
||||||
+ "--auto-agree-with-licenses",
|
|
||||||
+ "--dry-run",
|
|
||||||
+ "--from",
|
|
||||||
+ "Dummy",
|
|
||||||
+ "--from",
|
|
||||||
+ "Dummy2",
|
|
||||||
+ "--allow-vendor-change",
|
|
||||||
+ )
|
|
||||||
+ zypper_mock.assert_any_call(
|
|
||||||
+ "dist-upgrade",
|
|
||||||
+ "--auto-agree-with-licenses",
|
|
||||||
+ "--dry-run",
|
|
||||||
+ "--from",
|
|
||||||
+ "Dummy",
|
|
||||||
+ "--from",
|
|
||||||
+ "Dummy2",
|
|
||||||
+ "--allow-vendor-change",
|
|
||||||
+ "--debug-solver",
|
|
||||||
+ )
|
|
||||||
+
|
|
||||||
+
|
|
||||||
+ 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",
|
|
||||||
+ "--no-allow-vendor-change",
|
|
||||||
+ )
|
|
||||||
+ zypper_mock.assert_any_call(
|
|
||||||
+ "dist-upgrade",
|
|
||||||
+ "--auto-agree-with-licenses",
|
|
||||||
+ "--dry-run",
|
|
||||||
+ "--from",
|
|
||||||
+ "Dummy",
|
|
||||||
+ "--from",
|
|
||||||
+ "Dummy2",
|
|
||||||
+ "--no-allow-vendor-change",
|
|
||||||
+ "--debug-solver",
|
|
||||||
+ )
|
|
||||||
+
|
|
||||||
+ with patch(
|
+ with patch(
|
||||||
+ "salt.modules.zypperpkg.list_pkgs",
|
+ "salt.modules.zypperpkg.list_pkgs",
|
||||||
+ MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.1"}]),
|
+ MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.1"}]),
|
||||||
@ -188,9 +97,57 @@ index a3d20f66d5..8cc84485b5 100644
|
|||||||
+ fromrepo=["Dummy", "Dummy2"],
|
+ fromrepo=["Dummy", "Dummy2"],
|
||||||
+ novendorchange=True,
|
+ novendorchange=True,
|
||||||
+ )
|
+ )
|
||||||
self.assertDictEqual(ret, {"vim": {"old": "1.1", "new": "1.2"}})
|
+ zypper_mock.assert_any_call(
|
||||||
zypper_mock.assert_any_call('dist-upgrade', '--auto-agree-with-licenses', '--from', "Dummy",
|
+ "dist-upgrade",
|
||||||
'--from', 'Dummy2', '--no-allow-vendor-change')
|
+ "--auto-agree-with-licenses",
|
||||||
|
+ "--dry-run",
|
||||||
|
+ "--no-allow-vendor-change",
|
||||||
|
+ )
|
||||||
|
+ zypper_mock.assert_any_call(
|
||||||
|
+ "dist-upgrade",
|
||||||
|
+ "--auto-agree-with-licenses",
|
||||||
|
+ "--dry-run",
|
||||||
|
+ "--no-allow-vendor-change",
|
||||||
|
+ )
|
||||||
|
+
|
||||||
|
+ 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=False,
|
||||||
|
+ )
|
||||||
|
+ zypper_mock.assert_any_call(
|
||||||
|
+ "dist-upgrade",
|
||||||
|
+ "--auto-agree-with-licenses",
|
||||||
|
+ "--dry-run",
|
||||||
|
+ "--from",
|
||||||
|
+ "Dummy",
|
||||||
|
+ "--from",
|
||||||
|
+ "Dummy2",
|
||||||
|
+ "--allow-vendor-change",
|
||||||
|
+ )
|
||||||
|
+ zypper_mock.assert_any_call(
|
||||||
|
+ "dist-upgrade",
|
||||||
|
+ "--auto-agree-with-licenses",
|
||||||
|
+ "--dry-run",
|
||||||
|
+ "--from",
|
||||||
|
+ "Dummy",
|
||||||
|
+ "--from",
|
||||||
|
+ "Dummy2",
|
||||||
|
+ "--allow-vendor-change",
|
||||||
|
+ "--debug-solver",
|
||||||
|
+ )
|
||||||
|
+
|
||||||
|
with patch(
|
||||||
|
"salt.modules.zypperpkg.list_pkgs",
|
||||||
|
MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.1"}]),
|
||||||
|
@@ -728,6 +800,26 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
|
"--no-allow-vendor-change",
|
||||||
|
)
|
||||||
|
|
||||||
+ with patch(
|
+ with patch(
|
||||||
+ "salt.modules.zypperpkg.list_pkgs",
|
+ "salt.modules.zypperpkg.list_pkgs",
|
||||||
@ -211,30 +168,24 @@ index a3d20f66d5..8cc84485b5 100644
|
|||||||
+ "Dummy2",
|
+ "Dummy2",
|
||||||
+ "--allow-vendor-change",
|
+ "--allow-vendor-change",
|
||||||
+ )
|
+ )
|
||||||
|
+
|
||||||
def test_upgrade_kernel(self):
|
def test_upgrade_kernel(self):
|
||||||
'''
|
"""
|
||||||
Test kernel package upgrade success.
|
Test kernel package upgrade success.
|
||||||
@@ -558,10 +675,15 @@ Repository 'DUMMY' not found by its alias, number, or URI.
|
@@ -815,7 +907,11 @@ Repository 'DUMMY' not found by its alias, number, or URI.
|
||||||
with patch('salt.modules.zypperpkg.list_pkgs', MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.1"}])):
|
self.assertEqual(cmd_exc.exception.info["changes"], {})
|
||||||
with self.assertRaises(CommandExecutionError) as cmd_exc:
|
self.assertEqual(cmd_exc.exception.info["result"]["stdout"], zypper_out)
|
||||||
ret = zypper.upgrade(dist_upgrade=True, fromrepo=["DUMMY"])
|
zypper_mock.noraise.call.assert_called_with(
|
||||||
- self.assertEqual(cmd_exc.exception.info['changes'], {})
|
- "dist-upgrade", "--auto-agree-with-licenses", "--from", "DUMMY"
|
||||||
- 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')
|
|
||||||
+ 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",
|
+ "dist-upgrade",
|
||||||
+ "--auto-agree-with-licenses",
|
+ "--auto-agree-with-licenses",
|
||||||
+ "--from",
|
+ "--from",
|
||||||
+ "DUMMY",
|
+ "DUMMY",
|
||||||
+ "--no-allow-vendor-change",
|
+ "--no-allow-vendor-change",
|
||||||
+ )
|
)
|
||||||
|
|
||||||
def test_upgrade_available(self):
|
def test_upgrade_available(self):
|
||||||
'''
|
|
||||||
--
|
--
|
||||||
2.28.0
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
99
fix-salt.utils.stringutils.to_str-calls-to-make-it-w.patch
Normal file
99
fix-salt.utils.stringutils.to_str-calls-to-make-it-w.patch
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
From 435d9fbee299b06e1c58cdc0574b6a1975841879 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
|
||||||
|
|
||||||
|
---
|
||||||
|
salt/modules/file.py | 16 ++++++++++------
|
||||||
|
salt/states/file.py | 11 +++++++++--
|
||||||
|
2 files changed, 19 insertions(+), 8 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/salt/modules/file.py b/salt/modules/file.py
|
||||||
|
index b830b390d3..b9744393d7 100644
|
||||||
|
--- a/salt/modules/file.py
|
||||||
|
+++ b/salt/modules/file.py
|
||||||
|
@@ -4970,6 +4970,12 @@ def check_perms(
|
||||||
|
is_dir = os.path.isdir(name)
|
||||||
|
is_link = os.path.islink(name)
|
||||||
|
|
||||||
|
+ def __safe_to_str(s):
|
||||||
|
+ try:
|
||||||
|
+ return salt.utils.stringutils.to_str(s)
|
||||||
|
+ except:
|
||||||
|
+ return salt.utils.stringutils.to_str(str(s))
|
||||||
|
+
|
||||||
|
# user/group changes if needed, then check if it worked
|
||||||
|
if user:
|
||||||
|
if isinstance(user, int):
|
||||||
|
@@ -4979,7 +4985,7 @@ def check_perms(
|
||||||
|
and user_to_uid(user) != user_to_uid(perms["luser"])
|
||||||
|
) or (
|
||||||
|
not salt.utils.platform.is_windows()
|
||||||
|
- and salt.utils.stringutils.to_str(user) != perms["luser"]
|
||||||
|
+ and __safe_to_str(user) != perms["luser"]
|
||||||
|
):
|
||||||
|
perms["cuser"] = user
|
||||||
|
|
||||||
|
@@ -4991,7 +4997,7 @@ def check_perms(
|
||||||
|
and group_to_gid(group) != group_to_gid(perms["lgroup"])
|
||||||
|
) or (
|
||||||
|
not salt.utils.platform.is_windows()
|
||||||
|
- and salt.utils.stringutils.to_str(group) != perms["lgroup"]
|
||||||
|
+ and __safe_to_str(group) != perms["lgroup"]
|
||||||
|
):
|
||||||
|
perms["cgroup"] = group
|
||||||
|
|
||||||
|
@@ -5023,8 +5029,7 @@ def check_perms(
|
||||||
|
and user != ""
|
||||||
|
) 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 != ""
|
||||||
|
):
|
||||||
|
if __opts__["test"] is True:
|
||||||
|
@@ -5045,8 +5050,7 @@ def check_perms(
|
||||||
|
and group != ""
|
||||||
|
) 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 != ""
|
||||||
|
):
|
||||||
|
if __opts__["test"] is True:
|
||||||
|
diff --git a/salt/states/file.py b/salt/states/file.py
|
||||||
|
index 89c70eb454..fd8ffde757 100644
|
||||||
|
--- a/salt/states/file.py
|
||||||
|
+++ b/salt/states/file.py
|
||||||
|
@@ -989,15 +989,22 @@ def _check_dir_meta(name, user, group, mode, follow_symlinks=False):
|
||||||
|
if not stats:
|
||||||
|
changes["directory"] = "new"
|
||||||
|
return changes
|
||||||
|
+
|
||||||
|
+ def __safe_to_str(s):
|
||||||
|
+ try:
|
||||||
|
+ return salt.utils.stringutils.to_str(s)
|
||||||
|
+ except:
|
||||||
|
+ return salt.utils.stringutils.to_str(str(s))
|
||||||
|
+
|
||||||
|
if (
|
||||||
|
user is not None
|
||||||
|
- and salt.utils.stringutils.to_str(user) != stats["user"]
|
||||||
|
+ and __safe_to_str(user) != stats["user"]
|
||||||
|
and user != stats.get("uid")
|
||||||
|
):
|
||||||
|
changes["user"] = user
|
||||||
|
if (
|
||||||
|
group is not None
|
||||||
|
- and salt.utils.stringutils.to_str(group) != stats["group"]
|
||||||
|
+ and __safe_to_str(group) != stats["group"]
|
||||||
|
and group != stats.get("gid")
|
||||||
|
):
|
||||||
|
changes["group"] = group
|
||||||
|
--
|
||||||
|
2.29.2
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
From 5b6ac3bb81f24bbb8c39f80c71c490c339cce756 Mon Sep 17 00:00:00 2001
|
From 01e2e60a5aba609d219b73f1018f12517a294a64 Mon Sep 17 00:00:00 2001
|
||||||
From: Cedric Bosdonnat <cbosdonnat@suse.com>
|
From: Cedric Bosdonnat <cbosdonnat@suse.com>
|
||||||
Date: Tue, 15 Sep 2020 13:46:06 +0200
|
Date: Tue, 15 Sep 2020 13:46:06 +0200
|
||||||
Subject: [PATCH] Fix the removed six.itermitems and six.*_type* (#262)
|
Subject: [PATCH] Fix the removed six.itermitems and six.*_type* (#262)
|
||||||
@ -11,29 +11,81 @@ on python 2.7.
|
|||||||
|
|
||||||
* fixup! Fix the removed six.itermitems and six.*_type*
|
* fixup! Fix the removed six.itermitems and six.*_type*
|
||||||
---
|
---
|
||||||
salt/_compat.py | 1 +
|
salt/_compat.py | 25 ++++++++++++++++---------
|
||||||
salt/modules/virt.py | 57 +++++++++++-----------
|
salt/modules/virt.py | 11 ++++-------
|
||||||
salt/states/virt.py | 15 +++---
|
salt/states/virt.py | 1 +
|
||||||
salt/utils/data.py | 51 ++++++++++----------
|
salt/utils/xmlutil.py | 3 ++-
|
||||||
salt/utils/xmlutil.py | 5 +-
|
|
||||||
tests/unit/modules/test_virt.py | 2 +-
|
tests/unit/modules/test_virt.py | 2 +-
|
||||||
tests/unit/utils/test_data.py | 85 ++++++++++++++++++---------------
|
5 files changed, 24 insertions(+), 18 deletions(-)
|
||||||
7 files changed, 115 insertions(+), 101 deletions(-)
|
|
||||||
|
|
||||||
diff --git a/salt/_compat.py b/salt/_compat.py
|
diff --git a/salt/_compat.py b/salt/_compat.py
|
||||||
index 965bb90da3..22daaa31a0 100644
|
index d9425523cf..de100de3fa 100644
|
||||||
--- a/salt/_compat.py
|
--- a/salt/_compat.py
|
||||||
+++ b/salt/_compat.py
|
+++ b/salt/_compat.py
|
||||||
@@ -39,6 +39,7 @@ except Exception: # pylint: disable=broad-except
|
@@ -7,6 +7,7 @@ Salt compatibility code
|
||||||
# True if we are running on Python 3.
|
import binascii
|
||||||
PY3 = sys.version_info.major == 3
|
import logging
|
||||||
|
import sys
|
||||||
+import xml.sax.saxutils as saxutils
|
+import xml.sax.saxutils as saxutils
|
||||||
|
|
||||||
if PY3:
|
from salt.exceptions import SaltException
|
||||||
import builtins
|
from salt.ext.six import binary_type, integer_types, string_types, text_type
|
||||||
|
@@ -261,21 +262,25 @@ def ip_address(address):
|
||||||
|
try:
|
||||||
|
return ipaddress.IPv4Address(address)
|
||||||
|
except (ipaddress.AddressValueError, ipaddress.NetmaskValueError) as err:
|
||||||
|
- log.debug('Error while parsing IPv4 address: %s', address)
|
||||||
|
+ log.debug("Error while parsing IPv4 address: %s", address)
|
||||||
|
log.debug(err)
|
||||||
|
|
||||||
|
try:
|
||||||
|
return IPv6AddressScoped(address)
|
||||||
|
except (ipaddress.AddressValueError, ipaddress.NetmaskValueError) as err:
|
||||||
|
- log.debug('Error while parsing IPv6 address: %s', address)
|
||||||
|
+ log.debug("Error while parsing IPv6 address: %s", address)
|
||||||
|
log.debug(err)
|
||||||
|
|
||||||
|
if isinstance(address, bytes):
|
||||||
|
- raise ipaddress.AddressValueError('{} does not appear to be an IPv4 or IPv6 address. '
|
||||||
|
- 'Did you pass in a bytes (str in Python 2) instead '
|
||||||
|
- 'of a unicode object?'.format(repr(address)))
|
||||||
|
+ raise ipaddress.AddressValueError(
|
||||||
|
+ "{} does not appear to be an IPv4 or IPv6 address. "
|
||||||
|
+ "Did you pass in a bytes (str in Python 2) instead "
|
||||||
|
+ "of a unicode object?".format(repr(address))
|
||||||
|
+ )
|
||||||
|
|
||||||
|
- raise ValueError('{} does not appear to be an IPv4 or IPv6 address'.format(repr(address)))
|
||||||
|
+ raise ValueError(
|
||||||
|
+ "{} does not appear to be an IPv4 or IPv6 address".format(repr(address))
|
||||||
|
+ )
|
||||||
|
|
||||||
|
|
||||||
|
def ip_interface(address):
|
||||||
|
@@ -302,16 +307,18 @@ def ip_interface(address):
|
||||||
|
try:
|
||||||
|
return ipaddress.IPv4Interface(address)
|
||||||
|
except (ipaddress.AddressValueError, ipaddress.NetmaskValueError) as err:
|
||||||
|
- log.debug('Error while getting IPv4 interface for address %s', address)
|
||||||
|
+ log.debug("Error while getting IPv4 interface for address %s", address)
|
||||||
|
log.debug(err)
|
||||||
|
|
||||||
|
try:
|
||||||
|
return ipaddress.IPv6Interface(address)
|
||||||
|
except (ipaddress.AddressValueError, ipaddress.NetmaskValueError) as err:
|
||||||
|
- log.debug('Error while getting IPv6 interface for address %s', address)
|
||||||
|
+ log.debug("Error while getting IPv6 interface for address %s", address)
|
||||||
|
log.debug(err)
|
||||||
|
|
||||||
|
- raise ValueError('{} does not appear to be an IPv4 or IPv6 interface'.format(address))
|
||||||
|
+ raise ValueError(
|
||||||
|
+ "{} does not appear to be an IPv4 or IPv6 interface".format(address)
|
||||||
|
+ )
|
||||||
|
|
||||||
|
|
||||||
|
if ipaddress:
|
||||||
diff --git a/salt/modules/virt.py b/salt/modules/virt.py
|
diff --git a/salt/modules/virt.py b/salt/modules/virt.py
|
||||||
index cd80fbe608..c07fabb406 100644
|
index ec40f08359..c042738370 100644
|
||||||
--- a/salt/modules/virt.py
|
--- a/salt/modules/virt.py
|
||||||
+++ b/salt/modules/virt.py
|
+++ b/salt/modules/virt.py
|
||||||
@@ -88,8 +88,6 @@ import string # pylint: disable=deprecated-module
|
@@ -88,8 +88,6 @@ import string # pylint: disable=deprecated-module
|
||||||
@ -43,87 +95,20 @@ index cd80fbe608..c07fabb406 100644
|
|||||||
-from xml.etree import ElementTree
|
-from xml.etree import ElementTree
|
||||||
-from xml.sax import saxutils
|
-from xml.sax import saxutils
|
||||||
|
|
||||||
# Import third party libs
|
|
||||||
import jinja2.exceptions
|
import jinja2.exceptions
|
||||||
@@ -104,7 +102,10 @@ import salt.utils.templates
|
import salt.utils.files
|
||||||
|
@@ -99,8 +97,9 @@ import salt.utils.stringutils
|
||||||
|
import salt.utils.templates
|
||||||
import salt.utils.xmlutil as xmlutil
|
import salt.utils.xmlutil as xmlutil
|
||||||
import salt.utils.yaml
|
import salt.utils.yaml
|
||||||
from salt._compat import ipaddress
|
-from salt._compat import ipaddress
|
||||||
+from salt._compat import ElementTree
|
+from salt._compat import ElementTree, ipaddress, saxutils
|
||||||
+from salt._compat import saxutils
|
|
||||||
from salt.exceptions import CommandExecutionError, SaltInvocationError
|
from salt.exceptions import CommandExecutionError, SaltInvocationError
|
||||||
+from salt.ext import six
|
+from salt.ext import six
|
||||||
from salt.ext.six.moves import range # pylint: disable=import-error,redefined-builtin
|
from salt.ext.six.moves import range # pylint: disable=import-error,redefined-builtin
|
||||||
from salt.ext.six.moves.urllib.parse import urlparse, urlunparse
|
from salt.ext.six.moves.urllib.parse import urlparse, urlunparse
|
||||||
from salt.utils.virt import check_remote, download_remote
|
from salt.utils.virt import check_remote, download_remote
|
||||||
@@ -657,8 +658,8 @@ def _gen_xml(
|
@@ -1516,7 +1515,7 @@ def _handle_remote_boot_params(orig_boot):
|
||||||
context = {
|
|
||||||
"hypervisor": hypervisor,
|
|
||||||
"name": name,
|
|
||||||
- "cpu": str(cpu),
|
|
||||||
- "mem": str(mem),
|
|
||||||
+ "cpu": six.text_type(cpu),
|
|
||||||
+ "mem": six.text_type(mem),
|
|
||||||
}
|
|
||||||
if hypervisor in ["qemu", "kvm"]:
|
|
||||||
context["controller_model"] = False
|
|
||||||
@@ -722,7 +723,7 @@ def _gen_xml(
|
|
||||||
"target_dev": _get_disk_target(targets, len(diskp), prefix),
|
|
||||||
"disk_bus": disk["model"],
|
|
||||||
"format": disk.get("format", "raw"),
|
|
||||||
- "index": str(i),
|
|
||||||
+ "index": six.text_type(i),
|
|
||||||
}
|
|
||||||
targets.append(disk_context["target_dev"])
|
|
||||||
if disk.get("source_file"):
|
|
||||||
@@ -827,8 +828,8 @@ def _gen_vol_xml(
|
|
||||||
"name": name,
|
|
||||||
"target": {"permissions": permissions, "nocow": nocow},
|
|
||||||
"format": format,
|
|
||||||
- "size": str(size),
|
|
||||||
- "allocation": str(int(allocation) * 1024),
|
|
||||||
+ "size": six.text_type(size),
|
|
||||||
+ "allocation": six.text_type(int(allocation) * 1024),
|
|
||||||
"backingStore": backing_store,
|
|
||||||
}
|
|
||||||
fn_ = "libvirt_volume.jinja"
|
|
||||||
@@ -1253,7 +1254,7 @@ def _disk_profile(conn, profile, hypervisor, disks, vm_name):
|
|
||||||
)
|
|
||||||
|
|
||||||
# Transform the list to remove one level of dictionary and add the name as a property
|
|
||||||
- disklist = [dict(d, name=name) for disk in disklist for name, d in disk.items()]
|
|
||||||
+ disklist = [dict(d, name=name) for disk in disklist for name, d in six.iteritems(disk)]
|
|
||||||
|
|
||||||
# Merge with the user-provided disks definitions
|
|
||||||
if disks:
|
|
||||||
@@ -1274,7 +1275,7 @@ def _disk_profile(conn, profile, hypervisor, disks, vm_name):
|
|
||||||
disk["model"] = "ide"
|
|
||||||
|
|
||||||
# Add the missing properties that have defaults
|
|
||||||
- for key, val in overlay.items():
|
|
||||||
+ for key, val in six.iteritems(overlay):
|
|
||||||
if key not in disk:
|
|
||||||
disk[key] = val
|
|
||||||
|
|
||||||
@@ -1422,7 +1423,7 @@ def _complete_nics(interfaces, hypervisor):
|
|
||||||
"""
|
|
||||||
Apply the default overlay to attributes
|
|
||||||
"""
|
|
||||||
- for key, value in overlays[hypervisor].items():
|
|
||||||
+ for key, value in six.iteritems(overlays[hypervisor]):
|
|
||||||
if key not in attributes or not attributes[key]:
|
|
||||||
attributes[key] = value
|
|
||||||
|
|
||||||
@@ -1449,7 +1450,7 @@ def _nic_profile(profile_name, hypervisor):
|
|
||||||
"""
|
|
||||||
Append dictionary profile data to interfaces list
|
|
||||||
"""
|
|
||||||
- for interface_name, attributes in profile_dict.items():
|
|
||||||
+ for interface_name, attributes in six.iteritems(profile_dict):
|
|
||||||
attributes["name"] = interface_name
|
|
||||||
interfaces.append(attributes)
|
|
||||||
|
|
||||||
@@ -1520,7 +1521,7 @@ def _handle_remote_boot_params(orig_boot):
|
|
||||||
"""
|
"""
|
||||||
saltinst_dir = None
|
saltinst_dir = None
|
||||||
new_boot = orig_boot.copy()
|
new_boot = orig_boot.copy()
|
||||||
@ -132,139 +117,22 @@ index cd80fbe608..c07fabb406 100644
|
|||||||
cases = [
|
cases = [
|
||||||
{"efi"},
|
{"efi"},
|
||||||
{"kernel", "initrd", "efi"},
|
{"kernel", "initrd", "efi"},
|
||||||
@@ -2380,8 +2381,8 @@ def update(
|
@@ -2559,9 +2558,7 @@ def update(
|
||||||
# Update the cpu
|
|
||||||
cpu_node = desc.find("vcpu")
|
|
||||||
if cpu and int(cpu_node.text) != cpu:
|
|
||||||
- cpu_node.text = str(cpu)
|
|
||||||
- cpu_node.set("current", str(cpu))
|
|
||||||
+ cpu_node.text = six.text_type(cpu)
|
|
||||||
+ cpu_node.set("current", six.text_type(cpu))
|
|
||||||
need_update = True
|
|
||||||
|
|
||||||
def _set_loader(node, value):
|
|
||||||
@@ -2394,7 +2395,7 @@ def update(
|
|
||||||
node.set("template", value)
|
|
||||||
|
|
||||||
def _set_with_mib_unit(node, value):
|
|
||||||
- node.text = str(value)
|
|
||||||
+ node.text = six.text_type(value)
|
|
||||||
node.set("unit", "MiB")
|
|
||||||
|
|
||||||
# Update the kernel boot parameters
|
|
||||||
@@ -2426,7 +2427,7 @@ def update(
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
- data = {k: v for k, v in locals().items() if bool(v)}
|
|
||||||
+ data = {k: v for k, v in six.iteritems(locals()) if bool(v)}
|
|
||||||
if boot_dev:
|
|
||||||
data["boot_dev"] = {i + 1: dev for i, dev in enumerate(boot_dev.split())}
|
|
||||||
need_update = need_update or salt.utils.xmlutil.change_xml(
|
|
||||||
@@ -2547,7 +2548,7 @@ def update(
|
|
||||||
# Attaching device
|
# Attaching device
|
||||||
if source_file:
|
if source_file:
|
||||||
ElementTree.SubElement(
|
- ElementTree.SubElement(
|
||||||
- updated_disk, "source", attrib={"file": source_file}
|
- updated_disk, "source", attrib={"file": source_file}
|
||||||
+ updated_disk, "source", file=source_file
|
- )
|
||||||
)
|
+ ElementTree.SubElement(updated_disk, "source", file=source_file)
|
||||||
|
|
||||||
changes["disk"]["new"] = new_disks
|
changes["disk"]["new"] = new_disks
|
||||||
@@ -2609,7 +2610,7 @@ def update(
|
|
||||||
except libvirt.libvirtError as err:
|
|
||||||
if "errors" not in status:
|
|
||||||
status["errors"] = []
|
|
||||||
- status["errors"].append(str(err))
|
|
||||||
+ status["errors"].append(six.text_type(err))
|
|
||||||
|
|
||||||
conn.close()
|
|
||||||
return status
|
|
||||||
@@ -2823,7 +2824,7 @@ def _node_info(conn):
|
|
||||||
info = {
|
|
||||||
"cpucores": raw[6],
|
|
||||||
"cpumhz": raw[3],
|
|
||||||
- "cpumodel": str(raw[0]),
|
|
||||||
+ "cpumodel": six.text_type(raw[0]),
|
|
||||||
"cpus": raw[2],
|
|
||||||
"cputhreads": raw[7],
|
|
||||||
"numanodes": raw[4],
|
|
||||||
@@ -3628,7 +3629,7 @@ def _define_vol_xml_str(conn, xml, pool=None): # pylint: disable=redefined-oute
|
|
||||||
poolname = (
|
|
||||||
pool if pool else __salt__["config.get"]("virt:storagepool", default_pool)
|
|
||||||
)
|
|
||||||
- pool = conn.storagePoolLookupByName(str(poolname))
|
|
||||||
+ pool = conn.storagePoolLookupByName(six.text_type(poolname))
|
|
||||||
ret = pool.createXML(xml, 0) is not None
|
|
||||||
return ret
|
|
||||||
|
|
||||||
@@ -3829,7 +3830,7 @@ def seed_non_shared_migrate(disks, force=False):
|
|
||||||
|
|
||||||
salt '*' virt.seed_non_shared_migrate <disks>
|
|
||||||
"""
|
|
||||||
- for _, data in disks.items():
|
|
||||||
+ for _, data in six.iteritems(disks):
|
|
||||||
fn_ = data["file"]
|
|
||||||
form = data["file format"]
|
|
||||||
size = data["virtual size"].split()[1][1:]
|
|
||||||
@@ -4852,7 +4853,7 @@ def capabilities(**kwargs):
|
|
||||||
try:
|
|
||||||
caps = _capabilities(conn)
|
|
||||||
except libvirt.libvirtError as err:
|
|
||||||
- raise CommandExecutionError(str(err))
|
|
||||||
+ raise CommandExecutionError(six.text_type(err))
|
|
||||||
finally:
|
|
||||||
conn.close()
|
|
||||||
return caps
|
|
||||||
@@ -5352,7 +5353,7 @@ def network_info(name=None, **kwargs):
|
|
||||||
for net in nets
|
|
||||||
}
|
|
||||||
except libvirt.libvirtError as err:
|
|
||||||
- log.debug("Silenced libvirt error: %s", str(err))
|
|
||||||
+ log.debug("Silenced libvirt error: %s", six.text_type(err))
|
|
||||||
finally:
|
|
||||||
conn.close()
|
|
||||||
return result
|
|
||||||
@@ -6214,7 +6215,7 @@ def pool_info(name=None, **kwargs):
|
|
||||||
]
|
|
||||||
result = {pool.name(): _pool_extract_infos(pool) for pool in pools}
|
|
||||||
except libvirt.libvirtError as err:
|
|
||||||
- log.debug("Silenced libvirt error: %s", str(err))
|
|
||||||
+ log.debug("Silenced libvirt error: %s", six.text_type(err))
|
|
||||||
finally:
|
|
||||||
conn.close()
|
|
||||||
return result
|
|
||||||
@@ -6591,12 +6592,12 @@ def volume_infos(pool=None, volume=None, **kwargs):
|
|
||||||
if vol.path():
|
|
||||||
as_backing_store = {
|
|
||||||
path
|
|
||||||
- for (path, all_paths) in backing_stores.items()
|
|
||||||
+ for (path, all_paths) in six.iteritems(backing_stores)
|
|
||||||
if vol.path() in all_paths
|
|
||||||
}
|
|
||||||
used_by = [
|
|
||||||
vm_name
|
|
||||||
- for (vm_name, vm_disks) in disks.items()
|
|
||||||
+ for (vm_name, vm_disks) in six.iteritems(disks)
|
|
||||||
if vm_disks & as_backing_store or vol.path() in vm_disks
|
|
||||||
]
|
|
||||||
|
|
||||||
@@ -6625,9 +6626,9 @@ def volume_infos(pool=None, volume=None, **kwargs):
|
|
||||||
}
|
|
||||||
for pool_obj in pools
|
|
||||||
}
|
|
||||||
- return {pool_name: volumes for (pool_name, volumes) in vols.items() if volumes}
|
|
||||||
+ return {pool_name: volumes for (pool_name, volumes) in six.iteritems(vols) if volumes}
|
|
||||||
except libvirt.libvirtError as err:
|
|
||||||
- log.debug("Silenced libvirt error: %s", str(err))
|
|
||||||
+ log.debug("Silenced libvirt error: %s", six.text_type(err))
|
|
||||||
finally:
|
|
||||||
conn.close()
|
|
||||||
return result
|
|
||||||
diff --git a/salt/states/virt.py b/salt/states/virt.py
|
diff --git a/salt/states/virt.py b/salt/states/virt.py
|
||||||
index 3d99fd53c8..1a0c889d58 100644
|
index b45cf72ed3..df7ebb63e6 100644
|
||||||
--- a/salt/states/virt.py
|
--- a/salt/states/virt.py
|
||||||
+++ b/salt/states/virt.py
|
+++ b/salt/states/virt.py
|
||||||
@@ -23,6 +23,7 @@ import salt.utils.files
|
@@ -22,6 +22,7 @@ import salt.utils.files
|
||||||
import salt.utils.stringutils
|
import salt.utils.stringutils
|
||||||
import salt.utils.versions
|
import salt.utils.versions
|
||||||
from salt.exceptions import CommandExecutionError, SaltInvocationError
|
from salt.exceptions import CommandExecutionError, SaltInvocationError
|
||||||
@ -272,288 +140,19 @@ index 3d99fd53c8..1a0c889d58 100644
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
import libvirt # pylint: disable=import-error
|
import libvirt # pylint: disable=import-error
|
||||||
@@ -97,7 +98,7 @@ def keys(name, basepath="/etc/pki", **kwargs):
|
|
||||||
# rename them to something hopefully unique to avoid
|
|
||||||
# overriding anything existing
|
|
||||||
pillar_kwargs = {}
|
|
||||||
- for key, value in kwargs.items():
|
|
||||||
+ for key, value in six.iteritems(kwargs):
|
|
||||||
pillar_kwargs["ext_pillar_virt.{}".format(key)] = value
|
|
||||||
|
|
||||||
pillar = __salt__["pillar.ext"]({"libvirt": "_"}, pillar_kwargs)
|
|
||||||
@@ -187,7 +188,7 @@ def _virt_call(
|
|
||||||
else:
|
|
||||||
noaction_domains.append(targeted_domain)
|
|
||||||
except libvirt.libvirtError as err:
|
|
||||||
- ignored_domains.append({"domain": targeted_domain, "issue": str(err)})
|
|
||||||
+ ignored_domains.append({"domain": targeted_domain, "issue": six.text_type(err)})
|
|
||||||
if not changed_domains:
|
|
||||||
ret["result"] = not ignored_domains and bool(targeted_domains)
|
|
||||||
ret["comment"] = "No changes had happened"
|
|
||||||
@@ -461,7 +462,7 @@ def defined(
|
|
||||||
ret["comment"] = "Domain {} defined".format(name)
|
|
||||||
except libvirt.libvirtError as err:
|
|
||||||
# Something bad happened when defining / updating the VM, report it
|
|
||||||
- ret["comment"] = str(err)
|
|
||||||
+ ret["comment"] = six.text_type(err)
|
|
||||||
ret["result"] = False
|
|
||||||
|
|
||||||
return ret
|
|
||||||
@@ -704,7 +705,7 @@ def running(
|
|
||||||
|
|
||||||
except libvirt.libvirtError as err:
|
|
||||||
# Something bad happened when starting / updating the VM, report it
|
|
||||||
- ret["comment"] = str(err)
|
|
||||||
+ ret["comment"] = six.text_type(err)
|
|
||||||
ret["result"] = False
|
|
||||||
|
|
||||||
return ret
|
|
||||||
@@ -867,7 +868,7 @@ def reverted(
|
|
||||||
}
|
|
||||||
except CommandExecutionError as err:
|
|
||||||
if len(domains) > 1:
|
|
||||||
- ignored_domains.append({"domain": domain, "issue": str(err)})
|
|
||||||
+ ignored_domains.append({"domain": domain, "issue": six.text_type(err)})
|
|
||||||
if len(domains) > 1:
|
|
||||||
if result:
|
|
||||||
ret["changes"]["reverted"].append(result)
|
|
||||||
@@ -885,9 +886,9 @@ def reverted(
|
|
||||||
if not ret["changes"]["reverted"]:
|
|
||||||
ret["changes"].pop("reverted")
|
|
||||||
except libvirt.libvirtError as err:
|
|
||||||
- ret["comment"] = str(err)
|
|
||||||
+ ret["comment"] = six.text_type(err)
|
|
||||||
except CommandExecutionError as err:
|
|
||||||
- ret["comment"] = str(err)
|
|
||||||
+ ret["comment"] = six.text_type(err)
|
|
||||||
|
|
||||||
return ret
|
|
||||||
|
|
||||||
diff --git a/salt/utils/data.py b/salt/utils/data.py
|
|
||||||
index 1c4c22efb3..d98b56e06f 100644
|
|
||||||
--- a/salt/utils/data.py
|
|
||||||
+++ b/salt/utils/data.py
|
|
||||||
@@ -4,6 +4,7 @@ Functions for manipulating, inspecting, or otherwise working with data types
|
|
||||||
and data structures.
|
|
||||||
"""
|
|
||||||
|
|
||||||
+from __future__ import absolute_import, print_function, unicode_literals
|
|
||||||
|
|
||||||
# Import Python libs
|
|
||||||
import copy
|
|
||||||
@@ -71,7 +72,7 @@ class CaseInsensitiveDict(MutableMapping):
|
|
||||||
return self._data[to_lowercase(key)][1]
|
|
||||||
|
|
||||||
def __iter__(self):
|
|
||||||
- return (item[0] for item in self._data.values())
|
|
||||||
+ return (item[0] for item in six.itervalues(self._data))
|
|
||||||
|
|
||||||
def __eq__(self, rval):
|
|
||||||
if not isinstance(rval, Mapping):
|
|
||||||
@@ -80,20 +81,20 @@ class CaseInsensitiveDict(MutableMapping):
|
|
||||||
return dict(self.items_lower()) == dict(CaseInsensitiveDict(rval).items_lower())
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
- return repr(dict(self.items()))
|
|
||||||
+ return repr(dict(six.iteritems(self)))
|
|
||||||
|
|
||||||
def items_lower(self):
|
|
||||||
"""
|
|
||||||
Returns a generator iterating over keys and values, with the keys all
|
|
||||||
being lowercase.
|
|
||||||
"""
|
|
||||||
- return ((key, val[1]) for key, val in self._data.items())
|
|
||||||
+ return ((key, val[1]) for key, val in six.iteritems(self._data))
|
|
||||||
|
|
||||||
def copy(self):
|
|
||||||
"""
|
|
||||||
Returns a copy of the object
|
|
||||||
"""
|
|
||||||
- return CaseInsensitiveDict(self._data.items())
|
|
||||||
+ return CaseInsensitiveDict(six.iteritems(self._data))
|
|
||||||
|
|
||||||
|
|
||||||
def __change_case(data, attr, preserve_dict_class=False):
|
|
||||||
@@ -115,7 +116,7 @@ def __change_case(data, attr, preserve_dict_class=False):
|
|
||||||
__change_case(key, attr, preserve_dict_class),
|
|
||||||
__change_case(val, attr, preserve_dict_class),
|
|
||||||
)
|
|
||||||
- for key, val in data.items()
|
|
||||||
+ for key, val in six.iteritems(data)
|
|
||||||
)
|
|
||||||
if isinstance(data, Sequence):
|
|
||||||
return data_type(
|
|
||||||
@@ -145,7 +146,7 @@ def compare_dicts(old=None, new=None):
|
|
||||||
dict describing the changes that were made.
|
|
||||||
"""
|
|
||||||
ret = {}
|
|
||||||
- for key in set(new or {}).union(old or {}):
|
|
||||||
+ for key in set((new or {})).union((old or {})):
|
|
||||||
if key not in old:
|
|
||||||
# New key
|
|
||||||
ret[key] = {"old": "", "new": new[key]}
|
|
||||||
@@ -205,7 +206,7 @@ def _remove_circular_refs(ob, _seen=None):
|
|
||||||
if isinstance(ob, dict):
|
|
||||||
res = {
|
|
||||||
_remove_circular_refs(k, _seen): _remove_circular_refs(v, _seen)
|
|
||||||
- for k, v in ob.items()
|
|
||||||
+ for k, v in six.iteritems(ob)
|
|
||||||
}
|
|
||||||
elif isinstance(ob, (list, tuple, set, frozenset)):
|
|
||||||
res = type(ob)(_remove_circular_refs(v, _seen) for v in ob)
|
|
||||||
@@ -336,7 +337,7 @@ def decode_dict(
|
|
||||||
)
|
|
||||||
# Make sure we preserve OrderedDicts
|
|
||||||
ret = data.__class__() if preserve_dict_class else {}
|
|
||||||
- for key, value in data.items():
|
|
||||||
+ for key, value in six.iteritems(data):
|
|
||||||
if isinstance(key, tuple):
|
|
||||||
key = (
|
|
||||||
decode_tuple(
|
|
||||||
@@ -592,7 +593,7 @@ def encode_dict(
|
|
||||||
# Clean data object before encoding to avoid circular references
|
|
||||||
data = _remove_circular_refs(data)
|
|
||||||
ret = data.__class__() if preserve_dict_class else {}
|
|
||||||
- for key, value in data.items():
|
|
||||||
+ for key, value in six.iteritems(data):
|
|
||||||
if isinstance(key, tuple):
|
|
||||||
key = (
|
|
||||||
encode_tuple(key, encoding, errors, keep, preserve_dict_class)
|
|
||||||
@@ -734,8 +735,8 @@ def filter_by(lookup_dict, lookup, traverse, merge=None, default="default", base
|
|
||||||
# lookup_dict keys
|
|
||||||
for each in val if isinstance(val, list) else [val]:
|
|
||||||
for key in lookup_dict:
|
|
||||||
- test_key = key if isinstance(key, str) else str(key)
|
|
||||||
- test_each = each if isinstance(each, str) else str(each)
|
|
||||||
+ test_key = key if isinstance(key, six.string_types) else six.text_type(key)
|
|
||||||
+ test_each = each if isinstance(each, six.string_types) else six.text_type(each)
|
|
||||||
if fnmatch.fnmatchcase(test_each, test_key):
|
|
||||||
ret = lookup_dict[key]
|
|
||||||
break
|
|
||||||
@@ -851,11 +852,11 @@ def subdict_match(
|
|
||||||
# begin with is that (by design) to_unicode will raise a TypeError if a
|
|
||||||
# non-string/bytestring/bytearray value is passed.
|
|
||||||
try:
|
|
||||||
- target = str(target).lower()
|
|
||||||
+ target = six.text_type(target).lower()
|
|
||||||
except UnicodeDecodeError:
|
|
||||||
target = salt.utils.stringutils.to_unicode(target).lower()
|
|
||||||
try:
|
|
||||||
- pattern = str(pattern).lower()
|
|
||||||
+ pattern = six.text_type(pattern).lower()
|
|
||||||
except UnicodeDecodeError:
|
|
||||||
pattern = salt.utils.stringutils.to_unicode(pattern).lower()
|
|
||||||
|
|
||||||
@@ -997,7 +998,7 @@ def repack_dictlist(data, strict=False, recurse=False, key_cb=None, val_cb=None)
|
|
||||||
Takes a list of one-element dicts (as found in many SLS schemas) and
|
|
||||||
repacks into a single dictionary.
|
|
||||||
"""
|
|
||||||
- if isinstance(data, str):
|
|
||||||
+ if isinstance(data, six.string_types):
|
|
||||||
try:
|
|
||||||
data = salt.utils.yaml.safe_load(data)
|
|
||||||
except salt.utils.yaml.parser.ParserError as err:
|
|
||||||
@@ -1009,7 +1010,7 @@ def repack_dictlist(data, strict=False, recurse=False, key_cb=None, val_cb=None)
|
|
||||||
if val_cb is None:
|
|
||||||
val_cb = lambda x, y: y
|
|
||||||
|
|
||||||
- valid_non_dict = ((str,), (int,), float)
|
|
||||||
+ valid_non_dict = (six.string_types, six.integer_types, float)
|
|
||||||
if isinstance(data, list):
|
|
||||||
for element in data:
|
|
||||||
if isinstance(element, valid_non_dict):
|
|
||||||
@@ -1067,7 +1068,7 @@ def is_list(value):
|
|
||||||
|
|
||||||
|
|
||||||
@jinja_filter("is_iter")
|
|
||||||
-def is_iter(thing, ignore=(str,)):
|
|
||||||
+def is_iter(thing, ignore=six.string_types):
|
|
||||||
"""
|
|
||||||
Test if an object is iterable, but not a string type.
|
|
||||||
|
|
||||||
@@ -1124,10 +1125,10 @@ def is_true(value=None):
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Now check for truthiness
|
|
||||||
- if isinstance(value, ((int,), float)):
|
|
||||||
+ if isinstance(value, (six.integer_types, float)):
|
|
||||||
return value > 0
|
|
||||||
- if isinstance(value, str):
|
|
||||||
- return str(value).lower() == "true"
|
|
||||||
+ if isinstance(value, six.string_types):
|
|
||||||
+ return six.text_type(value).lower() == "true"
|
|
||||||
return bool(value)
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1167,7 +1168,7 @@ def simple_types_filter(data):
|
|
||||||
if data is None:
|
|
||||||
return data
|
|
||||||
|
|
||||||
- simpletypes_keys = ((str,), str, (int,), float, bool)
|
|
||||||
+ simpletypes_keys = (six.string_types, six.text_type, six.integer_types, float, bool)
|
|
||||||
simpletypes_values = tuple(list(simpletypes_keys) + [list, tuple])
|
|
||||||
|
|
||||||
if isinstance(data, (list, tuple)):
|
|
||||||
@@ -1183,7 +1184,7 @@ def simple_types_filter(data):
|
|
||||||
|
|
||||||
if isinstance(data, dict):
|
|
||||||
simpledict = {}
|
|
||||||
- for key, value in data.items():
|
|
||||||
+ for key, value in six.iteritems(data):
|
|
||||||
if key is not None and not isinstance(key, simpletypes_keys):
|
|
||||||
key = repr(key)
|
|
||||||
if value is not None and isinstance(value, (dict, list, tuple)):
|
|
||||||
@@ -1205,8 +1206,8 @@ def stringify(data):
|
|
||||||
for item in data:
|
|
||||||
if six.PY2 and isinstance(item, str):
|
|
||||||
item = salt.utils.stringutils.to_unicode(item)
|
|
||||||
- elif not isinstance(item, str):
|
|
||||||
- item = str(item)
|
|
||||||
+ elif not isinstance(item, six.string_types):
|
|
||||||
+ item = six.text_type(item)
|
|
||||||
ret.append(item)
|
|
||||||
return ret
|
|
||||||
|
|
||||||
@@ -1282,7 +1283,7 @@ def filter_falsey(data, recurse_depth=None, ignore_types=()):
|
|
||||||
|
|
||||||
if isinstance(data, dict):
|
|
||||||
processed_elements = [
|
|
||||||
- (key, filter_element(value)) for key, value in data.items()
|
|
||||||
+ (key, filter_element(value)) for key, value in six.iteritems(data)
|
|
||||||
]
|
|
||||||
return type(data)(
|
|
||||||
[
|
|
||||||
@@ -1472,7 +1473,7 @@ def get_value(obj, path, default=None):
|
|
||||||
if obj is None:
|
|
||||||
return res
|
|
||||||
if isinstance(obj, dict):
|
|
||||||
- items = obj.items()
|
|
||||||
+ items = six.iteritems(obj)
|
|
||||||
elif isinstance(obj, list):
|
|
||||||
items = enumerate(obj)
|
|
||||||
|
|
||||||
diff --git a/salt/utils/xmlutil.py b/salt/utils/xmlutil.py
|
diff --git a/salt/utils/xmlutil.py b/salt/utils/xmlutil.py
|
||||||
index 2b9c7bf43f..68191bc528 100644
|
index b9f047820b..111ca155d4 100644
|
||||||
--- a/salt/utils/xmlutil.py
|
--- a/salt/utils/xmlutil.py
|
||||||
+++ b/salt/utils/xmlutil.py
|
+++ b/salt/utils/xmlutil.py
|
||||||
@@ -9,6 +9,7 @@ from xml.etree import ElementTree
|
@@ -7,6 +7,7 @@ import string # pylint: disable=deprecated-module
|
||||||
|
from xml.etree import ElementTree
|
||||||
|
|
||||||
# Import salt libs
|
|
||||||
import salt.utils.data
|
import salt.utils.data
|
||||||
+from salt.ext import six
|
+from salt.ext import six
|
||||||
|
|
||||||
|
|
||||||
def _conv_name(x):
|
def _conv_name(x):
|
||||||
@@ -147,7 +148,7 @@ def set_node_text(node, value):
|
@@ -160,7 +161,7 @@ def clean_node(parent_map, node, ignored=None):
|
||||||
:param node: the node to set the text to
|
|
||||||
:param value: the value to set
|
|
||||||
"""
|
|
||||||
- node.text = str(value)
|
|
||||||
+ node.text = six.text_type(value)
|
|
||||||
|
|
||||||
|
|
||||||
def clean_node(parent_map, node, ignored=None):
|
|
||||||
@@ -162,7 +163,7 @@ def clean_node(parent_map, node, ignored=None):
|
|
||||||
has_text = node.text is not None and node.text.strip()
|
has_text = node.text is not None and node.text.strip()
|
||||||
parent = parent_map.get(node)
|
parent = parent_map.get(node)
|
||||||
if (
|
if (
|
||||||
@ -563,10 +162,10 @@ index 2b9c7bf43f..68191bc528 100644
|
|||||||
and not has_text
|
and not has_text
|
||||||
):
|
):
|
||||||
diff --git a/tests/unit/modules/test_virt.py b/tests/unit/modules/test_virt.py
|
diff --git a/tests/unit/modules/test_virt.py b/tests/unit/modules/test_virt.py
|
||||||
index 5ec8de77e7..27c4b9d1b0 100644
|
index 4775fec31f..4a4c0395a7 100644
|
||||||
--- a/tests/unit/modules/test_virt.py
|
--- a/tests/unit/modules/test_virt.py
|
||||||
+++ b/tests/unit/modules/test_virt.py
|
+++ b/tests/unit/modules/test_virt.py
|
||||||
@@ -48,7 +48,7 @@ class LibvirtMock(MagicMock): # pylint: disable=too-many-ancestors
|
@@ -45,7 +45,7 @@ class LibvirtMock(MagicMock): # pylint: disable=too-many-ancestors
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, msg):
|
def __init__(self, msg):
|
||||||
@ -575,202 +174,7 @@ index 5ec8de77e7..27c4b9d1b0 100644
|
|||||||
self.msg = msg
|
self.msg = msg
|
||||||
|
|
||||||
def get_error_message(self):
|
def get_error_message(self):
|
||||||
diff --git a/tests/unit/utils/test_data.py b/tests/unit/utils/test_data.py
|
|
||||||
index 8a6956d442..fb4a8cc3c2 100644
|
|
||||||
--- a/tests/unit/utils/test_data.py
|
|
||||||
+++ b/tests/unit/utils/test_data.py
|
|
||||||
@@ -1,14 +1,17 @@
|
|
||||||
+# -*- coding: utf-8 -*-
|
|
||||||
"""
|
|
||||||
Tests for salt.utils.data
|
|
||||||
"""
|
|
||||||
|
|
||||||
# Import Python libs
|
|
||||||
+from __future__ import absolute_import, print_function, unicode_literals
|
|
||||||
|
|
||||||
import logging
|
|
||||||
|
|
||||||
# Import Salt libs
|
|
||||||
import salt.utils.data
|
|
||||||
import salt.utils.stringutils
|
|
||||||
+from salt.ext import six
|
|
||||||
|
|
||||||
# Import 3rd party libs
|
|
||||||
from salt.ext.six.moves import ( # pylint: disable=import-error,redefined-builtin
|
|
||||||
@@ -414,18 +417,19 @@ class DataTestCase(TestCase):
|
|
||||||
)
|
|
||||||
self.assertEqual(ret, expected)
|
|
||||||
|
|
||||||
- # The binary data in the data structure should fail to decode, even
|
|
||||||
- # using the fallback, and raise an exception.
|
|
||||||
- self.assertRaises(
|
|
||||||
- UnicodeDecodeError,
|
|
||||||
- salt.utils.data.decode,
|
|
||||||
- self.test_data,
|
|
||||||
- keep=False,
|
|
||||||
- normalize=True,
|
|
||||||
- preserve_dict_class=True,
|
|
||||||
- preserve_tuples=True,
|
|
||||||
- to_str=True,
|
|
||||||
- )
|
|
||||||
+ if six.PY3:
|
|
||||||
+ # The binary data in the data structure should fail to decode, even
|
|
||||||
+ # using the fallback, and raise an exception.
|
|
||||||
+ self.assertRaises(
|
|
||||||
+ UnicodeDecodeError,
|
|
||||||
+ salt.utils.data.decode,
|
|
||||||
+ self.test_data,
|
|
||||||
+ keep=False,
|
|
||||||
+ normalize=True,
|
|
||||||
+ preserve_dict_class=True,
|
|
||||||
+ preserve_tuples=True,
|
|
||||||
+ to_str=True,
|
|
||||||
+ )
|
|
||||||
|
|
||||||
# Now munge the expected data so that we get what we would expect if we
|
|
||||||
# disable preservation of dict class and tuples
|
|
||||||
@@ -469,9 +473,14 @@ class DataTestCase(TestCase):
|
|
||||||
|
|
||||||
# Test binary blob
|
|
||||||
self.assertEqual(salt.utils.data.decode(BYTES, keep=True, to_str=True), BYTES)
|
|
||||||
- self.assertRaises(
|
|
||||||
- UnicodeDecodeError, salt.utils.data.decode, BYTES, keep=False, to_str=True,
|
|
||||||
- )
|
|
||||||
+ if six.PY3:
|
|
||||||
+ self.assertRaises(
|
|
||||||
+ UnicodeDecodeError,
|
|
||||||
+ salt.utils.data.decode,
|
|
||||||
+ BYTES,
|
|
||||||
+ keep=False,
|
|
||||||
+ to_str=True,
|
|
||||||
+ )
|
|
||||||
|
|
||||||
def test_decode_fallback(self):
|
|
||||||
"""
|
|
||||||
@@ -666,7 +675,7 @@ class DataTestCase(TestCase):
|
|
||||||
self.assertRaises(TypeError, salt.utils.data.stringify, 9)
|
|
||||||
self.assertEqual(
|
|
||||||
salt.utils.data.stringify(
|
|
||||||
- ["one", "two", "three", 4, 5]
|
|
||||||
+ ["one", "two", str("three"), 4, 5]
|
|
||||||
), # future lint: disable=blacklisted-function
|
|
||||||
["one", "two", "three", "4", "5"],
|
|
||||||
)
|
|
||||||
@@ -720,7 +729,7 @@ class FilterFalseyTestCase(TestCase):
|
|
||||||
# Check returned type equality
|
|
||||||
self.assertIs(type(old_list), type(new_list))
|
|
||||||
# Test with set
|
|
||||||
- old_set = {"foo", "bar"}
|
|
||||||
+ old_set = set(["foo", "bar"])
|
|
||||||
new_set = salt.utils.data.filter_falsey(old_set)
|
|
||||||
self.assertEqual(old_set, new_set)
|
|
||||||
# Check returned type equality
|
|
||||||
@@ -839,9 +848,9 @@ class FilterFalseyTestCase(TestCase):
|
|
||||||
Test filtering a set without recursing.
|
|
||||||
Note that a set cannot contain unhashable types, so recursion is not possible.
|
|
||||||
"""
|
|
||||||
- old_set = {"foo", None, 0, ""}
|
|
||||||
+ old_set = set(["foo", None, 0, ""])
|
|
||||||
new_set = salt.utils.data.filter_falsey(old_set)
|
|
||||||
- expect_set = {"foo"}
|
|
||||||
+ expect_set = set(["foo"])
|
|
||||||
self.assertEqual(expect_set, new_set)
|
|
||||||
self.assertIs(type(expect_set), type(new_set))
|
|
||||||
|
|
||||||
@@ -1053,13 +1062,13 @@ class FilterRecursiveDiff(TestCase):
|
|
||||||
"""
|
|
||||||
Test cases where equal sets are compared.
|
|
||||||
"""
|
|
||||||
- test_set = {0, 1, 2, 3, "foo"}
|
|
||||||
+ test_set = set([0, 1, 2, 3, "foo"])
|
|
||||||
self.assertEqual({}, salt.utils.data.recursive_diff(test_set, test_set))
|
|
||||||
|
|
||||||
# This is a bit of an oddity, as python seems to sort the sets in memory
|
|
||||||
# so both sets end up with the same ordering (0..3).
|
|
||||||
- set_one = {0, 1, 2, 3}
|
|
||||||
- set_two = {3, 2, 1, 0}
|
|
||||||
+ set_one = set([0, 1, 2, 3])
|
|
||||||
+ set_two = set([3, 2, 1, 0])
|
|
||||||
self.assertEqual({}, salt.utils.data.recursive_diff(set_one, set_two))
|
|
||||||
|
|
||||||
def test_tuple_equality(self):
|
|
||||||
@@ -1149,13 +1158,13 @@ class FilterRecursiveDiff(TestCase):
|
|
||||||
Tricky as the sets are compared zipped, so shuffled sets of equal values
|
|
||||||
are considered different.
|
|
||||||
"""
|
|
||||||
- set_one = {0, 1, 2, 4}
|
|
||||||
- set_two = {0, 1, 3, 4}
|
|
||||||
- expected_result = {"old": {2}, "new": {3}}
|
|
||||||
+ set_one = set([0, 1, 2, 4])
|
|
||||||
+ set_two = set([0, 1, 3, 4])
|
|
||||||
+ expected_result = {"old": set([2]), "new": set([3])}
|
|
||||||
self.assertEqual(
|
|
||||||
expected_result, salt.utils.data.recursive_diff(set_one, set_two)
|
|
||||||
)
|
|
||||||
- expected_result = {"new": {2}, "old": {3}}
|
|
||||||
+ expected_result = {"new": set([2]), "old": set([3])}
|
|
||||||
self.assertEqual(
|
|
||||||
expected_result, salt.utils.data.recursive_diff(set_two, set_one)
|
|
||||||
)
|
|
||||||
@@ -1164,8 +1173,8 @@ class FilterRecursiveDiff(TestCase):
|
|
||||||
# Python 2.7 seems to sort it (i.e. set_one below becomes {0, 1, 'foo', 'bar'}
|
|
||||||
# However Python 3.6.8 stores it differently each run.
|
|
||||||
# So just test for "not equal" here.
|
|
||||||
- set_one = {0, "foo", 1, "bar"}
|
|
||||||
- set_two = {"foo", 1, "bar", 2}
|
|
||||||
+ set_one = set([0, "foo", 1, "bar"])
|
|
||||||
+ set_two = set(["foo", 1, "bar", 2])
|
|
||||||
expected_result = {}
|
|
||||||
self.assertNotEqual(
|
|
||||||
expected_result, salt.utils.data.recursive_diff(set_one, set_two)
|
|
||||||
@@ -1203,18 +1212,18 @@ class FilterRecursiveDiff(TestCase):
|
|
||||||
expected_result, salt.utils.data.recursive_diff(list_two, list_one)
|
|
||||||
)
|
|
||||||
|
|
||||||
- mixed_one = {"foo": {0, 1, 2}, "bar": [0, 1, 2]}
|
|
||||||
- mixed_two = {"foo": {1, 2, 3}, "bar": [1, 2, 3]}
|
|
||||||
+ mixed_one = {"foo": set([0, 1, 2]), "bar": [0, 1, 2]}
|
|
||||||
+ mixed_two = {"foo": set([1, 2, 3]), "bar": [1, 2, 3]}
|
|
||||||
expected_result = {
|
|
||||||
- "old": {"foo": {0}, "bar": [0, 1, 2]},
|
|
||||||
- "new": {"foo": {3}, "bar": [1, 2, 3]},
|
|
||||||
+ "old": {"foo": set([0]), "bar": [0, 1, 2]},
|
|
||||||
+ "new": {"foo": set([3]), "bar": [1, 2, 3]},
|
|
||||||
}
|
|
||||||
self.assertEqual(
|
|
||||||
expected_result, salt.utils.data.recursive_diff(mixed_one, mixed_two)
|
|
||||||
)
|
|
||||||
expected_result = {
|
|
||||||
- "new": {"foo": {0}, "bar": [0, 1, 2]},
|
|
||||||
- "old": {"foo": {3}, "bar": [1, 2, 3]},
|
|
||||||
+ "new": {"foo": set([0]), "bar": [0, 1, 2]},
|
|
||||||
+ "old": {"foo": set([3]), "bar": [1, 2, 3]},
|
|
||||||
}
|
|
||||||
self.assertEqual(
|
|
||||||
expected_result, salt.utils.data.recursive_diff(mixed_two, mixed_one)
|
|
||||||
@@ -1236,7 +1245,7 @@ class FilterRecursiveDiff(TestCase):
|
|
||||||
Test case comparing a list with a set, will be compared unordered.
|
|
||||||
"""
|
|
||||||
mixed_one = [1, 2, 3]
|
|
||||||
- mixed_two = {3, 2, 1}
|
|
||||||
+ mixed_two = set([3, 2, 1])
|
|
||||||
expected_result = {}
|
|
||||||
self.assertEqual(
|
|
||||||
expected_result, salt.utils.data.recursive_diff(mixed_one, mixed_two)
|
|
||||||
@@ -1351,9 +1360,9 @@ class FilterRecursiveDiff(TestCase):
|
|
||||||
Test case comparing two sets of unequal length.
|
|
||||||
This does not do anything special, as it is unordered.
|
|
||||||
"""
|
|
||||||
- set_one = {1, 2, 3}
|
|
||||||
- set_two = {4, 3, 2, 1}
|
|
||||||
- expected_result = {"old": set(), "new": {4}}
|
|
||||||
+ set_one = set([1, 2, 3])
|
|
||||||
+ set_two = set([4, 3, 2, 1])
|
|
||||||
+ expected_result = {"old": set([]), "new": set([4])}
|
|
||||||
self.assertEqual(
|
|
||||||
expected_result, salt.utils.data.recursive_diff(set_one, set_two)
|
|
||||||
)
|
|
||||||
--
|
--
|
||||||
2.28.0
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
From 5a2c7671be0fcdf03050049ac4a1bbf4929abf1e Mon Sep 17 00:00:00 2001
|
|
||||||
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
|
||||||
<psuarezhernandez@suse.com>
|
|
||||||
Date: Fri, 27 Mar 2020 15:58:40 +0000
|
|
||||||
Subject: [PATCH] Fix typo on msgpack version when sanitizing msgpack
|
|
||||||
kwargs (bsc#1167437)
|
|
||||||
|
|
||||||
---
|
|
||||||
salt/utils/msgpack.py | 2 +-
|
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
||||||
|
|
||||||
diff --git a/salt/utils/msgpack.py b/salt/utils/msgpack.py
|
|
||||||
index 1d02aa96ba8b659eb4038f00563c9cfc31a568e5..4b5a256513a524a33d7d42773644567a0970a46b 100644
|
|
||||||
--- a/salt/utils/msgpack.py
|
|
||||||
+++ b/salt/utils/msgpack.py
|
|
||||||
@@ -61,7 +61,7 @@ def _sanitize_msgpack_kwargs(kwargs):
|
|
||||||
assert isinstance(kwargs, dict)
|
|
||||||
if version < (0, 6, 0) and kwargs.pop('strict_map_key', None) is not None:
|
|
||||||
log.info('removing unsupported `strict_map_key` argument from msgpack call')
|
|
||||||
- if version < (0, 5, 5) and kwargs.pop('raw', None) is not None:
|
|
||||||
+ if version < (0, 5, 2) and kwargs.pop('raw', None) is not None:
|
|
||||||
log.info('removing unsupported `raw` argument from msgpack call')
|
|
||||||
if version < (0, 4, 0) and kwargs.pop('use_bin_type', None) is not None:
|
|
||||||
log.info('removing unsupported `use_bin_type` argument from msgpack call')
|
|
||||||
--
|
|
||||||
2.23.0
|
|
||||||
|
|
||||||
|
|
@ -1,42 +1,41 @@
|
|||||||
From 6bb7b6c4a530abb7e831449545a35ee5ede49dcb Mon Sep 17 00:00:00 2001
|
From 192bac1ae2f20b098384264c8802034a340cd124 Mon Sep 17 00:00:00 2001
|
||||||
From: Bo Maryniuk <bo@suse.de>
|
From: Bo Maryniuk <bo@suse.de>
|
||||||
Date: Thu, 11 Oct 2018 16:20:40 +0200
|
Date: Thu, 11 Oct 2018 16:20:40 +0200
|
||||||
Subject: [PATCH] Fix unit test for grains core
|
Subject: [PATCH] Fix unit test for grains core
|
||||||
|
|
||||||
---
|
---
|
||||||
tests/unit/grains/test_core.py | 11 +++++------
|
tests/unit/grains/test_core.py | 9 +++++----
|
||||||
1 file changed, 5 insertions(+), 6 deletions(-)
|
1 file changed, 5 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
diff --git a/tests/unit/grains/test_core.py b/tests/unit/grains/test_core.py
|
diff --git a/tests/unit/grains/test_core.py b/tests/unit/grains/test_core.py
|
||||||
index b31f5dcddd..c40595eb3f 100644
|
index 34aaa4f5bc..7dbf34deac 100644
|
||||||
--- a/tests/unit/grains/test_core.py
|
--- a/tests/unit/grains/test_core.py
|
||||||
+++ b/tests/unit/grains/test_core.py
|
+++ b/tests/unit/grains/test_core.py
|
||||||
@@ -68,11 +68,10 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -59,10 +59,11 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
def test_parse_etc_os_release(self, path_isfile_mock):
|
with salt.utils.files.fopen(
|
||||||
path_isfile_mock.side_effect = lambda x: x == "/usr/lib/os-release"
|
os.path.join(OS_RELEASE_DIR, "ubuntu-17.10")
|
||||||
with salt.utils.files.fopen(os.path.join(OS_RELEASE_DIR, "ubuntu-17.10")) as os_release_file:
|
) as os_release_file:
|
||||||
- os_release_content = os_release_file.read()
|
- os_release_content = os_release_file.read()
|
||||||
- with patch("salt.utils.files.fopen", mock_open(read_data=os_release_content)):
|
- with patch("salt.utils.files.fopen", mock_open(read_data=os_release_content)):
|
||||||
- os_release = core._parse_os_release(
|
|
||||||
- '/etc/os-release',
|
|
||||||
- '/usr/lib/os-release')
|
|
||||||
+ os_release_content = os_release_file.readlines()
|
+ os_release_content = os_release_file.readlines()
|
||||||
+ with patch("salt.utils.files.fopen", mock_open()) as os_release_file:
|
+ with patch("salt.utils.files.fopen", mock_open()) as os_release_file:
|
||||||
+ os_release_file.return_value.__iter__.return_value = os_release_content
|
+ os_release_file.return_value.__iter__.return_value = os_release_content
|
||||||
+ os_release = core._parse_os_release(["/etc/os-release", "/usr/lib/os-release"])
|
os_release = core._parse_os_release(
|
||||||
self.assertEqual(os_release, {
|
- "/etc/os-release", "/usr/lib/os-release"
|
||||||
"NAME": "Ubuntu",
|
+ ["/etc/os-release", "/usr/lib/os-release"]
|
||||||
"VERSION": "17.10 (Artful Aardvark)",
|
)
|
||||||
@@ -134,7 +133,7 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
|
self.assertEqual(
|
||||||
|
os_release,
|
||||||
|
@@ -172,7 +173,7 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
def test_missing_os_release(self):
|
def test_missing_os_release(self):
|
||||||
with patch('salt.utils.files.fopen', mock_open(read_data={})):
|
with patch("salt.utils.files.fopen", mock_open(read_data={})):
|
||||||
- os_release = core._parse_os_release('/etc/os-release', '/usr/lib/os-release')
|
os_release = core._parse_os_release(
|
||||||
+ os_release = core._parse_os_release(['/etc/os-release', '/usr/lib/os-release'])
|
- "/etc/os-release", "/usr/lib/os-release"
|
||||||
|
+ ["/etc/os-release", "/usr/lib/os-release"]
|
||||||
|
)
|
||||||
self.assertEqual(os_release, {})
|
self.assertEqual(os_release, {})
|
||||||
|
|
||||||
@skipIf(not salt.utils.platform.is_windows(), 'System is not Windows')
|
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
From e9f2af1256a52d58a7c8e6dd0122eb6d5cc47dd3 Mon Sep 17 00:00:00 2001
|
From 09a871c197be4933475ee4582755d9b0cb5a700e Mon Sep 17 00:00:00 2001
|
||||||
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||||
<psuarezhernandez@suse.com>
|
<psuarezhernandez@suse.com>
|
||||||
Date: Wed, 4 Mar 2020 10:13:43 +0000
|
Date: Wed, 4 Mar 2020 10:13:43 +0000
|
||||||
Subject: [PATCH] Fix unit tests for batch async after refactor
|
Subject: [PATCH] Fix unit tests for batch async after refactor
|
||||||
|
|
||||||
---
|
---
|
||||||
tests/unit/cli/test_batch_async.py | 18 +++++++++++++++++-
|
tests/unit/cli/test_batch_async.py | 20 +++++++++++++++++++-
|
||||||
1 file changed, 17 insertions(+), 1 deletion(-)
|
1 file changed, 19 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
diff --git a/tests/unit/cli/test_batch_async.py b/tests/unit/cli/test_batch_async.py
|
diff --git a/tests/unit/cli/test_batch_async.py b/tests/unit/cli/test_batch_async.py
|
||||||
index f1d36a81fb..e1ce60859b 100644
|
index b04965268a..dcee9a87bd 100644
|
||||||
--- a/tests/unit/cli/test_batch_async.py
|
--- a/tests/unit/cli/test_batch_async.py
|
||||||
+++ b/tests/unit/cli/test_batch_async.py
|
+++ b/tests/unit/cli/test_batch_async.py
|
||||||
@@ -126,9 +126,10 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
@@ -120,9 +120,10 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
||||||
self.batch.timedout_minions = {'bar'}
|
self.batch.timedout_minions = {"bar"}
|
||||||
self.batch.event = MagicMock()
|
self.batch.event = MagicMock()
|
||||||
self.batch.metadata = {'mykey': 'myvalue'}
|
self.batch.metadata = {"mykey": "myvalue"}
|
||||||
+ old_event = self.batch.event
|
+ old_event = self.batch.event
|
||||||
self.batch.end_batch()
|
self.batch.end_batch()
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
@ -23,8 +23,8 @@ index f1d36a81fb..e1ce60859b 100644
|
|||||||
+ old_event.fire_event.call_args[0],
|
+ old_event.fire_event.call_args[0],
|
||||||
(
|
(
|
||||||
{
|
{
|
||||||
'available_minions': set(['foo', 'bar']),
|
"available_minions": {"foo", "bar"},
|
||||||
@@ -146,6 +147,21 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
@@ -140,6 +141,23 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
|
||||||
event = MagicMock()
|
event = MagicMock()
|
||||||
batch.event = event
|
batch.event = event
|
||||||
batch.__del__()
|
batch.__del__()
|
||||||
@ -36,17 +36,19 @@ index f1d36a81fb..e1ce60859b 100644
|
|||||||
+ batch = BatchAsync(MagicMock(), MagicMock(), MagicMock())
|
+ batch = BatchAsync(MagicMock(), MagicMock(), MagicMock())
|
||||||
+ event = MagicMock()
|
+ event = MagicMock()
|
||||||
+ batch.event = event
|
+ batch.event = event
|
||||||
+ batch.patterns = { ('salt/job/1234/ret/*', 'find_job_return'), ('salt/job/4321/ret/*', 'find_job_return') }
|
+ batch.patterns = {
|
||||||
|
+ ("salt/job/1234/ret/*", "find_job_return"),
|
||||||
|
+ ("salt/job/4321/ret/*", "find_job_return"),
|
||||||
|
+ }
|
||||||
+ batch.close_safe()
|
+ batch.close_safe()
|
||||||
+ self.assertEqual(batch.local, None)
|
+ self.assertEqual(batch.local, None)
|
||||||
+ self.assertEqual(batch.event, None)
|
+ self.assertEqual(batch.event, None)
|
||||||
+ self.assertEqual(batch.ioloop, None)
|
+ self.assertEqual(batch.ioloop, None)
|
||||||
+ self.assertEqual(
|
+ self.assertEqual(len(event.unsubscribe.mock_calls), 2)
|
||||||
+ len(event.unsubscribe.mock_calls), 2)
|
self.assertEqual(len(event.remove_event_handler.mock_calls), 1)
|
||||||
self.assertEqual(
|
|
||||||
len(event.remove_event_handler.mock_calls), 1)
|
|
||||||
|
|
||||||
|
@tornado.testing.gen_test
|
||||||
--
|
--
|
||||||
2.23.0
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From 37800f008e46a7321bcd4b88b4858d3ea1fabcdf Mon Sep 17 00:00:00 2001
|
From c05d571058b9520dbaf4aba3de001b1aefe8e2c2 Mon Sep 17 00:00:00 2001
|
||||||
From: Cedric Bosdonnat <cbosdonnat@suse.com>
|
From: Cedric Bosdonnat <cbosdonnat@suse.com>
|
||||||
Date: Tue, 15 Sep 2020 16:03:30 +0200
|
Date: Tue, 15 Sep 2020 16:03:30 +0200
|
||||||
Subject: [PATCH] Fix virt.update with cpu defined (#263)
|
Subject: [PATCH] Fix virt.update with cpu defined (#263)
|
||||||
@ -10,11 +10,11 @@ updated.
|
|||||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/modules/virt.py b/salt/modules/virt.py
|
diff --git a/salt/modules/virt.py b/salt/modules/virt.py
|
||||||
index c07fabb406..4a8a55ced6 100644
|
index c042738370..c1a73fcb7f 100644
|
||||||
--- a/salt/modules/virt.py
|
--- a/salt/modules/virt.py
|
||||||
+++ b/salt/modules/virt.py
|
+++ b/salt/modules/virt.py
|
||||||
@@ -2430,9 +2430,9 @@ def update(
|
@@ -2441,9 +2441,9 @@ def update(
|
||||||
data = {k: v for k, v in six.iteritems(locals()) if bool(v)}
|
data = {k: v for k, v in locals().items() if bool(v)}
|
||||||
if boot_dev:
|
if boot_dev:
|
||||||
data["boot_dev"] = {i + 1: dev for i, dev in enumerate(boot_dev.split())}
|
data["boot_dev"] = {i + 1: dev for i, dev in enumerate(boot_dev.split())}
|
||||||
- need_update = need_update or salt.utils.xmlutil.change_xml(
|
- need_update = need_update or salt.utils.xmlutil.change_xml(
|
||||||
@ -26,6 +26,6 @@ index c07fabb406..4a8a55ced6 100644
|
|||||||
# Update the XML definition with the new disks and diff changes
|
# Update the XML definition with the new disks and diff changes
|
||||||
devices_node = desc.find("devices")
|
devices_node = desc.find("devices")
|
||||||
--
|
--
|
||||||
2.28.0
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,70 +1,79 @@
|
|||||||
From a8f0a15e4067ec278c8a2d690e3bf815523286ca Mon Sep 17 00:00:00 2001
|
From f3ac041e34952a4b753e4afc9dc4b6adaa1d0ff2 Mon Sep 17 00:00:00 2001
|
||||||
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||||
<psuarezhernandez@suse.com>
|
<psuarezhernandez@suse.com>
|
||||||
Date: Thu, 12 Mar 2020 13:26:51 +0000
|
Date: Thu, 12 Mar 2020 13:26:51 +0000
|
||||||
Subject: [PATCH] Fix wrong test_mod_del_repo_multiline_values test after
|
Subject: [PATCH] Fix wrong test_mod_del_repo_multiline_values test
|
||||||
rebase
|
after rebase
|
||||||
|
|
||||||
---
|
---
|
||||||
tests/integration/modules/test_pkg.py | 56 +++------------------------
|
tests/integration/modules/test_pkg.py | 63 ++++-----------------------
|
||||||
1 file changed, 6 insertions(+), 50 deletions(-)
|
1 file changed, 8 insertions(+), 55 deletions(-)
|
||||||
|
|
||||||
diff --git a/tests/integration/modules/test_pkg.py b/tests/integration/modules/test_pkg.py
|
diff --git a/tests/integration/modules/test_pkg.py b/tests/integration/modules/test_pkg.py
|
||||||
index 6f3767bfbd272848277b877d1fe640caf8f349f6..0f4c5c9d459c56bb485408f943c1dee49c46cd21 100644
|
index 3ece73074b..933755a9ec 100644
|
||||||
--- a/tests/integration/modules/test_pkg.py
|
--- a/tests/integration/modules/test_pkg.py
|
||||||
+++ b/tests/integration/modules/test_pkg.py
|
+++ b/tests/integration/modules/test_pkg.py
|
||||||
@@ -134,6 +134,10 @@ class PkgModuleTest(ModuleCase, SaltReturnAssertsMixin):
|
@@ -143,6 +143,10 @@ class PkgModuleTest(ModuleCase, SaltReturnAssertsMixin):
|
||||||
if repo is not None:
|
self.run_function("pkg.del_repo", [repo])
|
||||||
self.run_function('pkg.del_repo', [repo])
|
|
||||||
|
|
||||||
|
@slowTest
|
||||||
+ @destructiveTest
|
+ @destructiveTest
|
||||||
+ @requires_salt_modules('pkg.mod_repo', 'pkg.del_repo', 'pkg.get_repo')
|
+ @requires_salt_modules("pkg.mod_repo", "pkg.del_repo", "pkg.get_repo")
|
||||||
+ @requires_network()
|
+ @requires_network()
|
||||||
+ @requires_system_grains
|
+ @requires_system_grains
|
||||||
def test_mod_del_repo_multiline_values(self):
|
def test_mod_del_repo_multiline_values(self):
|
||||||
'''
|
"""
|
||||||
test modifying and deleting a software repository defined with multiline values
|
test modifying and deleting a software repository defined with multiline values
|
||||||
@@ -141,8 +145,9 @@ class PkgModuleTest(ModuleCase, SaltReturnAssertsMixin):
|
@@ -150,10 +154,13 @@ class PkgModuleTest(ModuleCase, SaltReturnAssertsMixin):
|
||||||
os_grain = self.run_function('grains.item', ['os'])['os']
|
os_grain = self.run_function("grains.item", ["os"])["os"]
|
||||||
repo = None
|
repo = None
|
||||||
try:
|
try:
|
||||||
- if os_grain in ['CentOS', 'RedHat']:
|
- if os_grain in ["CentOS", "RedHat"]:
|
||||||
+ if os_grain in ['CentOS', 'RedHat', 'SUSE']:
|
+ if os_grain in ["CentOS", "RedHat", "SUSE"]:
|
||||||
my_baseurl = 'http://my.fake.repo/foo/bar/\n http://my.fake.repo.alt/foo/bar/'
|
my_baseurl = (
|
||||||
+ expected_get_repo_baseurl_zypp = 'http://my.fake.repo/foo/bar/%0A%20http://my.fake.repo.alt/foo/bar/'
|
"http://my.fake.repo/foo/bar/\n http://my.fake.repo.alt/foo/bar/"
|
||||||
expected_get_repo_baseurl = 'http://my.fake.repo/foo/bar/\nhttp://my.fake.repo.alt/foo/bar/'
|
)
|
||||||
major_release = int(
|
+ expected_get_repo_baseurl_zypp = (
|
||||||
self.run_function(
|
+ "http://my.fake.repo/foo/bar/%0A%20http://my.fake.repo.alt/foo/bar/"
|
||||||
@@ -189,55 +194,6 @@ class PkgModuleTest(ModuleCase, SaltReturnAssertsMixin):
|
+ )
|
||||||
|
expected_get_repo_baseurl = (
|
||||||
|
"http://my.fake.repo/foo/bar/\nhttp://my.fake.repo.alt/foo/bar/"
|
||||||
|
)
|
||||||
|
@@ -207,60 +214,6 @@ class PkgModuleTest(ModuleCase, SaltReturnAssertsMixin):
|
||||||
if repo is not None:
|
if repo is not None:
|
||||||
self.run_function('pkg.del_repo', [repo])
|
self.run_function("pkg.del_repo", [repo])
|
||||||
|
|
||||||
- def test_mod_del_repo_multiline_values(self):
|
- def test_mod_del_repo_multiline_values(self):
|
||||||
- '''
|
- """
|
||||||
- test modifying and deleting a software repository defined with multiline values
|
- test modifying and deleting a software repository defined with multiline values
|
||||||
- '''
|
- """
|
||||||
- os_grain = self.run_function('grains.item', ['os'])['os']
|
- os_grain = self.run_function("grains.item", ["os"])["os"]
|
||||||
- repo = None
|
- repo = None
|
||||||
- try:
|
- try:
|
||||||
- if os_grain in ['CentOS', 'RedHat', 'SUSE']:
|
- if os_grain in ["CentOS", "RedHat", "SUSE"]:
|
||||||
- my_baseurl = 'http://my.fake.repo/foo/bar/\n http://my.fake.repo.alt/foo/bar/'
|
- my_baseurl = (
|
||||||
- expected_get_repo_baseurl_zypp = 'http://my.fake.repo/foo/bar/%0A%20http://my.fake.repo.alt/foo/bar/'
|
- "http://my.fake.repo/foo/bar/\n http://my.fake.repo.alt/foo/bar/"
|
||||||
- expected_get_repo_baseurl = 'http://my.fake.repo/foo/bar/\nhttp://my.fake.repo.alt/foo/bar/'
|
|
||||||
- major_release = int(
|
|
||||||
- self.run_function(
|
|
||||||
- 'grains.item',
|
|
||||||
- ['osmajorrelease']
|
|
||||||
- )['osmajorrelease']
|
|
||||||
- )
|
- )
|
||||||
- repo = 'fakerepo'
|
- expected_get_repo_baseurl_zypp = (
|
||||||
- name = 'Fake repo for RHEL/CentOS/SUSE'
|
- "http://my.fake.repo/foo/bar/%0A%20http://my.fake.repo.alt/foo/bar/"
|
||||||
|
- )
|
||||||
|
- expected_get_repo_baseurl = (
|
||||||
|
- "http://my.fake.repo/foo/bar/\nhttp://my.fake.repo.alt/foo/bar/"
|
||||||
|
- )
|
||||||
|
- major_release = int(
|
||||||
|
- self.run_function("grains.item", ["osmajorrelease"])[
|
||||||
|
- "osmajorrelease"
|
||||||
|
- ]
|
||||||
|
- )
|
||||||
|
- repo = "fakerepo"
|
||||||
|
- name = "Fake repo for RHEL/CentOS/SUSE"
|
||||||
- baseurl = my_baseurl
|
- baseurl = my_baseurl
|
||||||
- gpgkey = 'https://my.fake.repo/foo/bar/MY-GPG-KEY.pub'
|
- gpgkey = "https://my.fake.repo/foo/bar/MY-GPG-KEY.pub"
|
||||||
- failovermethod = 'priority'
|
- failovermethod = "priority"
|
||||||
- gpgcheck = 1
|
- gpgcheck = 1
|
||||||
- enabled = 1
|
- enabled = 1
|
||||||
- ret = self.run_function(
|
- ret = self.run_function(
|
||||||
- 'pkg.mod_repo',
|
- "pkg.mod_repo",
|
||||||
- [repo],
|
- [repo],
|
||||||
- name=name,
|
- name=name,
|
||||||
- baseurl=baseurl,
|
- baseurl=baseurl,
|
||||||
@ -78,20 +87,20 @@ index 6f3767bfbd272848277b877d1fe640caf8f349f6..0f4c5c9d459c56bb485408f943c1dee4
|
|||||||
- self.assertNotEqual(ret, {})
|
- self.assertNotEqual(ret, {})
|
||||||
- repo_info = ret[next(iter(ret))]
|
- repo_info = ret[next(iter(ret))]
|
||||||
- self.assertIn(repo, repo_info)
|
- self.assertIn(repo, repo_info)
|
||||||
- self.assertEqual(repo_info[repo]['baseurl'], my_baseurl)
|
- self.assertEqual(repo_info[repo]["baseurl"], my_baseurl)
|
||||||
- ret = self.run_function('pkg.get_repo', [repo])
|
- ret = self.run_function("pkg.get_repo", [repo])
|
||||||
- self.assertEqual(ret['baseurl'], expected_get_repo_baseurl)
|
- self.assertEqual(ret["baseurl"], expected_get_repo_baseurl)
|
||||||
- self.run_function('pkg.mod_repo', [repo])
|
- self.run_function("pkg.mod_repo", [repo])
|
||||||
- ret = self.run_function('pkg.get_repo', [repo])
|
- ret = self.run_function("pkg.get_repo", [repo])
|
||||||
- self.assertEqual(ret['baseurl'], expected_get_repo_baseurl)
|
- self.assertEqual(ret["baseurl"], expected_get_repo_baseurl)
|
||||||
- finally:
|
- finally:
|
||||||
- if repo is not None:
|
- if repo is not None:
|
||||||
- self.run_function('pkg.del_repo', [repo])
|
- self.run_function("pkg.del_repo", [repo])
|
||||||
-
|
-
|
||||||
@requires_salt_modules('pkg.owner')
|
@requires_salt_modules("pkg.owner")
|
||||||
def test_owner(self):
|
def test_owner(self):
|
||||||
'''
|
"""
|
||||||
--
|
--
|
||||||
2.23.0
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,43 +1,53 @@
|
|||||||
From eb51734ad93b1fa0c6bc8fde861fdabfe3e0d6b0 Mon Sep 17 00:00:00 2001
|
From 81f38c8cb16634b2c86b3e1e7c745870f90771d0 Mon Sep 17 00:00:00 2001
|
||||||
From: Mihai Dinca <mdinca@suse.de>
|
From: Mihai Dinca <mdinca@suse.de>
|
||||||
Date: Thu, 13 Jun 2019 17:48:55 +0200
|
Date: Thu, 13 Jun 2019 17:48:55 +0200
|
||||||
Subject: [PATCH] Fix zypper pkg.list_pkgs expectation and dpkg mocking
|
Subject: [PATCH] Fix zypper pkg.list_pkgs expectation and dpkg mocking
|
||||||
|
|
||||||
---
|
---
|
||||||
tests/unit/modules/test_dpkg_lowpkg.py | 12 ++++++------
|
tests/unit/modules/test_dpkg_lowpkg.py | 22 ++++++++++++++++------
|
||||||
1 file changed, 6 insertions(+), 6 deletions(-)
|
1 file changed, 16 insertions(+), 6 deletions(-)
|
||||||
|
|
||||||
diff --git a/tests/unit/modules/test_dpkg_lowpkg.py b/tests/unit/modules/test_dpkg_lowpkg.py
|
diff --git a/tests/unit/modules/test_dpkg_lowpkg.py b/tests/unit/modules/test_dpkg_lowpkg.py
|
||||||
index a0b3346f9d..bc564f080a 100644
|
index 160bbcd5b1..dadbc30dfa 100644
|
||||||
--- a/tests/unit/modules/test_dpkg_lowpkg.py
|
--- a/tests/unit/modules/test_dpkg_lowpkg.py
|
||||||
+++ b/tests/unit/modules/test_dpkg_lowpkg.py
|
+++ b/tests/unit/modules/test_dpkg_lowpkg.py
|
||||||
@@ -125,9 +125,9 @@ class DpkgTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -308,9 +308,14 @@ class DpkgTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
with patch.dict(dpkg.__salt__, {'cmd.run_all': mock}):
|
dpkg.bin_pkg_info("package.deb")["name"], "package_name"
|
||||||
self.assertEqual(dpkg.file_dict('httpd'), 'Error: error')
|
)
|
||||||
|
|
||||||
- @patch('salt.modules.dpkg._get_pkg_ds_avail', MagicMock(return_value=dselect_pkg))
|
- @patch("salt.modules.dpkg._get_pkg_ds_avail", MagicMock(return_value=dselect_pkg))
|
||||||
- @patch('salt.modules.dpkg._get_pkg_info', MagicMock(return_value=pkgs_info))
|
- @patch("salt.modules.dpkg._get_pkg_info", MagicMock(return_value=pkgs_info))
|
||||||
- @patch('salt.modules.dpkg._get_pkg_license', MagicMock(return_value='BSD v3'))
|
- @patch("salt.modules.dpkg._get_pkg_license", MagicMock(return_value="BSD v3"))
|
||||||
+ @patch('salt.modules.dpkg_lowpkg._get_pkg_ds_avail', MagicMock(return_value=dselect_pkg))
|
+ @patch(
|
||||||
+ @patch('salt.modules.dpkg_lowpkg._get_pkg_info', MagicMock(return_value=pkgs_info))
|
+ "salt.modules.dpkg_lowpkg._get_pkg_ds_avail",
|
||||||
+ @patch('salt.modules.dpkg_lowpkg._get_pkg_license', MagicMock(return_value='BSD v3'))
|
+ MagicMock(return_value=dselect_pkg),
|
||||||
|
+ )
|
||||||
|
+ @patch("salt.modules.dpkg_lowpkg._get_pkg_info", MagicMock(return_value=pkgs_info))
|
||||||
|
+ @patch(
|
||||||
|
+ "salt.modules.dpkg_lowpkg._get_pkg_license", MagicMock(return_value="BSD v3")
|
||||||
|
+ )
|
||||||
def test_info(self):
|
def test_info(self):
|
||||||
'''
|
"""
|
||||||
Test info
|
Test info
|
||||||
@@ -152,9 +152,9 @@ class DpkgTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -359,9 +364,14 @@ class DpkgTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
assert pkg_data['maintainer'] == 'Simpsons Developers <simpsons-devel-discuss@lists.springfield.org>'
|
)
|
||||||
assert pkg_data['license'] == 'BSD v3'
|
assert pkg_data["license"] == "BSD v3"
|
||||||
|
|
||||||
- @patch('salt.modules.dpkg._get_pkg_ds_avail', MagicMock(return_value=dselect_pkg))
|
- @patch("salt.modules.dpkg._get_pkg_ds_avail", MagicMock(return_value=dselect_pkg))
|
||||||
- @patch('salt.modules.dpkg._get_pkg_info', MagicMock(return_value=pkgs_info))
|
- @patch("salt.modules.dpkg._get_pkg_info", MagicMock(return_value=pkgs_info))
|
||||||
- @patch('salt.modules.dpkg._get_pkg_license', MagicMock(return_value='BSD v3'))
|
- @patch("salt.modules.dpkg._get_pkg_license", MagicMock(return_value="BSD v3"))
|
||||||
+ @patch('salt.modules.dpkg_lowpkg._get_pkg_ds_avail', MagicMock(return_value=dselect_pkg))
|
+ @patch(
|
||||||
+ @patch('salt.modules.dpkg_lowpkg._get_pkg_info', MagicMock(return_value=pkgs_info))
|
+ "salt.modules.dpkg_lowpkg._get_pkg_ds_avail",
|
||||||
+ @patch('salt.modules.dpkg_lowpkg._get_pkg_license', MagicMock(return_value='BSD v3'))
|
+ MagicMock(return_value=dselect_pkg),
|
||||||
|
+ )
|
||||||
|
+ @patch("salt.modules.dpkg_lowpkg._get_pkg_info", MagicMock(return_value=pkgs_info))
|
||||||
|
+ @patch(
|
||||||
|
+ "salt.modules.dpkg_lowpkg._get_pkg_license", MagicMock(return_value="BSD v3")
|
||||||
|
+ )
|
||||||
def test_info_attr(self):
|
def test_info_attr(self):
|
||||||
'''
|
"""
|
||||||
Test info with 'attr' parameter
|
Test info with 'attr' parameter
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From 0612549b3acfeb15e0b499b6f469d64062d6ae2d Mon Sep 17 00:00:00 2001
|
From b9ba6875945e1ffafdeb862d8b2ac7fccd9cccf5 Mon Sep 17 00:00:00 2001
|
||||||
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||||
<psuarezhernandez@suse.com>
|
<psuarezhernandez@suse.com>
|
||||||
Date: Mon, 25 Jun 2018 13:06:40 +0100
|
Date: Mon, 25 Jun 2018 13:06:40 +0100
|
||||||
@ -14,17 +14,17 @@ Fix '_find_remove_targets' after aligning Zypper with pkg state
|
|||||||
1 file changed, 21 deletions(-)
|
1 file changed, 21 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/states/pkg.py b/salt/states/pkg.py
|
diff --git a/salt/states/pkg.py b/salt/states/pkg.py
|
||||||
index c0fa2f6b69..a13d418400 100644
|
index a1b2a122bb..f7327a33e3 100644
|
||||||
--- a/salt/states/pkg.py
|
--- a/salt/states/pkg.py
|
||||||
+++ b/salt/states/pkg.py
|
+++ b/salt/states/pkg.py
|
||||||
@@ -450,16 +450,6 @@ def _find_remove_targets(name=None,
|
@@ -477,16 +477,6 @@ def _find_remove_targets(
|
||||||
|
|
||||||
if __grains__['os'] == 'FreeBSD' and origin:
|
if __grains__["os"] == "FreeBSD" and origin:
|
||||||
cver = [k for k, v in six.iteritems(cur_pkgs) if v['origin'] == pkgname]
|
cver = [k for k, v in cur_pkgs.items() if v["origin"] == pkgname]
|
||||||
- elif __grains__['os_family'] == 'Suse':
|
- elif __grains__["os_family"] == "Suse":
|
||||||
- # On SUSE systems. Zypper returns packages without "arch" in name
|
- # On SUSE systems. Zypper returns packages without "arch" in name
|
||||||
- try:
|
- try:
|
||||||
- namepart, archpart = pkgname.rsplit('.', 1)
|
- namepart, archpart = pkgname.rsplit(".", 1)
|
||||||
- except ValueError:
|
- except ValueError:
|
||||||
- cver = cur_pkgs.get(pkgname, [])
|
- cver = cur_pkgs.get(pkgname, [])
|
||||||
- else:
|
- else:
|
||||||
@ -34,14 +34,14 @@ index c0fa2f6b69..a13d418400 100644
|
|||||||
else:
|
else:
|
||||||
cver = cur_pkgs.get(pkgname, [])
|
cver = cur_pkgs.get(pkgname, [])
|
||||||
|
|
||||||
@@ -866,17 +856,6 @@ def _verify_install(desired, new_pkgs, ignore_epoch=False, new_caps=None):
|
@@ -930,17 +920,6 @@ def _verify_install(desired, new_pkgs, ignore_epoch=None, new_caps=None):
|
||||||
cver = new_pkgs.get(pkgname.split('%')[0])
|
cver = new_pkgs.get(pkgname.split("%")[0])
|
||||||
elif __grains__['os_family'] == 'Debian':
|
elif __grains__["os_family"] == "Debian":
|
||||||
cver = new_pkgs.get(pkgname.split('=')[0])
|
cver = new_pkgs.get(pkgname.split("=")[0])
|
||||||
- elif __grains__['os_family'] == 'Suse':
|
- elif __grains__["os_family"] == "Suse":
|
||||||
- # On SUSE systems. Zypper returns packages without "arch" in name
|
- # On SUSE systems. Zypper returns packages without "arch" in name
|
||||||
- try:
|
- try:
|
||||||
- namepart, archpart = pkgname.rsplit('.', 1)
|
- namepart, archpart = pkgname.rsplit(".", 1)
|
||||||
- except ValueError:
|
- except ValueError:
|
||||||
- cver = new_pkgs.get(pkgname)
|
- cver = new_pkgs.get(pkgname)
|
||||||
- else:
|
- else:
|
||||||
@ -53,6 +53,6 @@ index c0fa2f6b69..a13d418400 100644
|
|||||||
cver = new_pkgs.get(pkgname)
|
cver = new_pkgs.get(pkgname)
|
||||||
if not cver and pkgname in new_caps:
|
if not cver and pkgname in new_caps:
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From 3df8359421f60140fd335d95c3c06de0bfd6ac4f Mon Sep 17 00:00:00 2001
|
From 17ad05e3cbb3718ca12cef20600be81aa5d42d33 Mon Sep 17 00:00:00 2001
|
||||||
From: tyl0re <andreas@vogler.name>
|
From: tyl0re <andreas@vogler.name>
|
||||||
Date: Wed, 17 Jul 2019 10:13:09 +0200
|
Date: Wed, 17 Jul 2019 10:13:09 +0200
|
||||||
Subject: [PATCH] Fixed Bug LVM has no Parttion Type. the Scipt Later
|
Subject: [PATCH] Fixed Bug LVM has no Parttion Type. the Scipt Later
|
||||||
@ -11,23 +11,41 @@ Subject: [PATCH] Fixed Bug LVM has no Parttion Type. the Scipt Later
|
|||||||
|
|
||||||
So the check on not defined fs_type is missing
|
So the check on not defined fs_type is missing
|
||||||
---
|
---
|
||||||
salt/modules/parted_partition.py | 2 +-
|
salt/modules/parted_partition.py | 19 ++++++++++++++++---
|
||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
1 file changed, 16 insertions(+), 3 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/modules/parted_partition.py b/salt/modules/parted_partition.py
|
diff --git a/salt/modules/parted_partition.py b/salt/modules/parted_partition.py
|
||||||
index 9441fec49fd1833da590b3f65637e8e92b287d1c..7d08a7b315c990e7a87c9c77fd6550a6174b7160 100644
|
index 015d4cbc29..bb34cd58b4 100644
|
||||||
--- a/salt/modules/parted_partition.py
|
--- a/salt/modules/parted_partition.py
|
||||||
+++ b/salt/modules/parted_partition.py
|
+++ b/salt/modules/parted_partition.py
|
||||||
@@ -515,7 +515,7 @@ def mkpartfs(device, part_type, fs_type, start, end):
|
@@ -552,10 +552,23 @@ def mkpartfs(device, part_type, fs_type=None, start=None, end=None):
|
||||||
'Invalid part_type passed to partition.mkpartfs'
|
|
||||||
)
|
|
||||||
|
|
||||||
- if not _is_fstype(fs_type):
|
.. code-block:: bash
|
||||||
|
|
||||||
|
- salt '*' partition.mkpartfs /dev/sda primary fs_type=fat32 start=0 end=639
|
||||||
|
- salt '*' partition.mkpartfs /dev/sda primary start=0 end=639
|
||||||
|
+ salt '*' partition.mkpartfs /dev/sda logical ext2 440 670
|
||||||
|
"""
|
||||||
|
- out = mkpart(device, part_type, fs_type, start, end)
|
||||||
|
+ _validate_device(device)
|
||||||
|
+
|
||||||
|
+ if part_type not in {"primary", "logical", "extended"}:
|
||||||
|
+ raise CommandExecutionError("Invalid part_type passed to partition.mkpartfs")
|
||||||
|
+
|
||||||
+ if fs_type and not _is_fstype(fs_type):
|
+ if fs_type and not _is_fstype(fs_type):
|
||||||
raise CommandExecutionError(
|
+ raise CommandExecutionError("Invalid fs_type passed to partition.mkpartfs")
|
||||||
'Invalid fs_type passed to partition.mkpartfs'
|
+
|
||||||
)
|
+ _validate_partition_boundary(start)
|
||||||
|
+ _validate_partition_boundary(end)
|
||||||
|
+
|
||||||
|
+ cmd = "parted -m -s -- {} mkpart {} {} {} {}".format(
|
||||||
|
+ device, part_type, fs_type, start, end
|
||||||
|
+ )
|
||||||
|
+ out = __salt__["cmd.run"](cmd).splitlines()
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
2.23.0
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From 9ec54e8c1394ab678c6129d98f07c6eafd446399 Mon Sep 17 00:00:00 2001
|
From 731a53bd241240e08c455a8cb3a59e4d65a6abb5 Mon Sep 17 00:00:00 2001
|
||||||
From: Erik Johnson <palehose@gmail.com>
|
From: Erik Johnson <palehose@gmail.com>
|
||||||
Date: Fri, 24 Aug 2018 10:35:55 -0500
|
Date: Fri, 24 Aug 2018 10:35:55 -0500
|
||||||
Subject: [PATCH] Fixes: CVE-2018-15750, CVE-2018-15751
|
Subject: [PATCH] Fixes: CVE-2018-15750, CVE-2018-15751
|
||||||
@ -12,43 +12,47 @@ Handle Auth exceptions in run_job
|
|||||||
Update tornado test to correct authentication message
|
Update tornado test to correct authentication message
|
||||||
---
|
---
|
||||||
salt/netapi/rest_cherrypy/app.py | 7 -------
|
salt/netapi/rest_cherrypy/app.py | 7 -------
|
||||||
tests/integration/netapi/rest_tornado/test_app.py | 4 ++--
|
tests/integration/netapi/rest_tornado/test_app.py | 8 ++++++--
|
||||||
2 files changed, 2 insertions(+), 9 deletions(-)
|
2 files changed, 6 insertions(+), 9 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/netapi/rest_cherrypy/app.py b/salt/netapi/rest_cherrypy/app.py
|
diff --git a/salt/netapi/rest_cherrypy/app.py b/salt/netapi/rest_cherrypy/app.py
|
||||||
index fa1b540e5f..f8b500482b 100644
|
index e7641ccbc5..5dfbadf759 100644
|
||||||
--- a/salt/netapi/rest_cherrypy/app.py
|
--- a/salt/netapi/rest_cherrypy/app.py
|
||||||
+++ b/salt/netapi/rest_cherrypy/app.py
|
+++ b/salt/netapi/rest_cherrypy/app.py
|
||||||
@@ -1176,13 +1176,6 @@ class LowDataAdapter(object):
|
@@ -1181,13 +1181,6 @@ class LowDataAdapter:
|
||||||
except (TypeError, ValueError):
|
except (TypeError, ValueError):
|
||||||
raise cherrypy.HTTPError(401, 'Invalid token')
|
raise cherrypy.HTTPError(401, "Invalid token")
|
||||||
|
|
||||||
- if 'token' in chunk:
|
- if "token" in chunk:
|
||||||
- # Make sure that auth token is hex
|
- # Make sure that auth token is hex
|
||||||
- try:
|
- try:
|
||||||
- int(chunk['token'], 16)
|
- int(chunk["token"], 16)
|
||||||
- except (TypeError, ValueError):
|
- except (TypeError, ValueError):
|
||||||
- raise cherrypy.HTTPError(401, 'Invalid token')
|
- raise cherrypy.HTTPError(401, "Invalid token")
|
||||||
-
|
-
|
||||||
if client:
|
if client:
|
||||||
chunk['client'] = client
|
chunk["client"] = client
|
||||||
|
|
||||||
diff --git a/tests/integration/netapi/rest_tornado/test_app.py b/tests/integration/netapi/rest_tornado/test_app.py
|
diff --git a/tests/integration/netapi/rest_tornado/test_app.py b/tests/integration/netapi/rest_tornado/test_app.py
|
||||||
index 10ec29f7fa..4102b5645a 100644
|
index e3ad8820d3..4e5e741f1d 100644
|
||||||
--- a/tests/integration/netapi/rest_tornado/test_app.py
|
--- a/tests/integration/netapi/rest_tornado/test_app.py
|
||||||
+++ b/tests/integration/netapi/rest_tornado/test_app.py
|
+++ b/tests/integration/netapi/rest_tornado/test_app.py
|
||||||
@@ -282,8 +282,8 @@ class TestSaltAPIHandler(_SaltnadoIntegrationTestCase):
|
@@ -326,8 +326,12 @@ class TestSaltAPIHandler(_SaltnadoIntegrationTestCase):
|
||||||
self.assertIn('jid', ret[0]) # the first 2 are regular returns
|
self.assertIn("jid", ret[0]) # the first 2 are regular returns
|
||||||
self.assertIn('jid', ret[1])
|
self.assertIn("jid", ret[1])
|
||||||
self.assertIn('Failed to authenticate', ret[2]) # bad auth
|
self.assertIn("Failed to authenticate", ret[2]) # bad auth
|
||||||
- self.assertEqual(ret[0]['minions'], sorted(['minion', 'sub_minion']))
|
- self.assertEqual(ret[0]["minions"], sorted(["minion", "sub_minion"]))
|
||||||
- self.assertEqual(ret[1]['minions'], sorted(['minion', 'sub_minion']))
|
- self.assertEqual(ret[1]["minions"], sorted(["minion", "sub_minion"]))
|
||||||
+ self.assertEqual(ret[0]['minions'], sorted(['minion', 'sub_minion', 'localhost']))
|
+ self.assertEqual(
|
||||||
+ self.assertEqual(ret[1]['minions'], sorted(['minion', 'sub_minion', 'localhost']))
|
+ ret[0]["minions"], sorted(["minion", "sub_minion", "localhost"])
|
||||||
|
+ )
|
||||||
|
+ self.assertEqual(
|
||||||
|
+ ret[1]["minions"], sorted(["minion", "sub_minion", "localhost"])
|
||||||
|
+ )
|
||||||
|
|
||||||
|
@slowTest
|
||||||
def test_simple_local_async_post_no_tgt(self):
|
def test_simple_local_async_post_no_tgt(self):
|
||||||
low = [{'client': 'local_async',
|
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From 9a5f007a5baa4ba1d28b0e6708bac8b134e4891c Mon Sep 17 00:00:00 2001
|
From 82d1cadff4fa6248a9d891a3c228fc415207d8d6 Mon Sep 17 00:00:00 2001
|
||||||
From: =?UTF-8?q?Mihai=20Dinc=C4=83?= <dincamihai@users.noreply.github.com>
|
From: =?UTF-8?q?Mihai=20Dinc=C4=83?= <dincamihai@users.noreply.github.com>
|
||||||
Date: Tue, 26 Nov 2019 18:26:31 +0100
|
Date: Tue, 26 Nov 2019 18:26:31 +0100
|
||||||
Subject: [PATCH] Fixing StreamClosed issue
|
Subject: [PATCH] Fixing StreamClosed issue
|
||||||
@ -8,18 +8,18 @@ Subject: [PATCH] Fixing StreamClosed issue
|
|||||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
diff --git a/salt/cli/batch_async.py b/salt/cli/batch_async.py
|
diff --git a/salt/cli/batch_async.py b/salt/cli/batch_async.py
|
||||||
index 754c257b36..c4545e3ebc 100644
|
index f3d92b88f1..8d2601e636 100644
|
||||||
--- a/salt/cli/batch_async.py
|
--- a/salt/cli/batch_async.py
|
||||||
+++ b/salt/cli/batch_async.py
|
+++ b/salt/cli/batch_async.py
|
||||||
@@ -221,7 +221,6 @@ class BatchAsync(object):
|
@@ -232,7 +232,6 @@ class BatchAsync:
|
||||||
"metadata": self.metadata
|
"metadata": self.metadata,
|
||||||
}
|
}
|
||||||
self.event.fire_event(data, "salt/batch/{0}/done".format(self.batch_jid))
|
self.event.fire_event(data, "salt/batch/{}/done".format(self.batch_jid))
|
||||||
- self.event.remove_event_handler(self.__event_handler)
|
- self.event.remove_event_handler(self.__event_handler)
|
||||||
for (pattern, label) in self.patterns:
|
for (pattern, label) in self.patterns:
|
||||||
if label in ["ping_return", "batch_run"]:
|
if label in ["ping_return", "batch_run"]:
|
||||||
self.event.unsubscribe(pattern, match_type='glob')
|
self.event.unsubscribe(pattern, match_type="glob")
|
||||||
@@ -265,6 +264,7 @@ class BatchAsync(object):
|
@@ -277,6 +276,7 @@ class BatchAsync:
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
self.local = None
|
self.local = None
|
||||||
@ -28,6 +28,6 @@ index 754c257b36..c4545e3ebc 100644
|
|||||||
self.ioloop = None
|
self.ioloop = None
|
||||||
gc.collect()
|
gc.collect()
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
29
force-zyppnotify-to-prefer-packages.db-than-packages.patch
Normal file
29
force-zyppnotify-to-prefer-packages.db-than-packages.patch
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
From 36b107fb5108fe4e52e9ef522765d6ada588c50d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Victor Zhestkov <vzhestkov@suse.com>
|
||||||
|
Date: Wed, 9 Dec 2020 14:58:55 +0300
|
||||||
|
Subject: [PATCH] Force zyppnotify to prefer Packages.db than Packages
|
||||||
|
if it exists
|
||||||
|
|
||||||
|
---
|
||||||
|
scripts/suse/zypper/plugins/commit/zyppnotify | 4 +++-
|
||||||
|
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/scripts/suse/zypper/plugins/commit/zyppnotify b/scripts/suse/zypper/plugins/commit/zyppnotify
|
||||||
|
index 51ac02254e..d6a1bef42b 100755
|
||||||
|
--- a/scripts/suse/zypper/plugins/commit/zyppnotify
|
||||||
|
+++ b/scripts/suse/zypper/plugins/commit/zyppnotify
|
||||||
|
@@ -20,7 +20,9 @@ class DriftDetector(Plugin):
|
||||||
|
def __init__(self):
|
||||||
|
Plugin.__init__(self)
|
||||||
|
self.ck_path = "/var/cache/salt/minion/rpmdb.cookie"
|
||||||
|
- self.rpm_path = "/var/lib/rpm/Packages"
|
||||||
|
+ self.rpm_path = "/var/lib/rpm/Packages.db"
|
||||||
|
+ if not os.path.exists(self.rpm_path):
|
||||||
|
+ self.rpm_path = "/var/lib/rpm/Packages"
|
||||||
|
|
||||||
|
def _get_mtime(self):
|
||||||
|
"""
|
||||||
|
--
|
||||||
|
2.29.2
|
||||||
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
From 98f3bd70aaa145b88e8bd4b947b578435e2b1e57 Mon Sep 17 00:00:00 2001
|
From e987664551debb9affce8ce5a70593ef0750dcd5 Mon Sep 17 00:00:00 2001
|
||||||
From: Bo Maryniuk <bo@suse.de>
|
From: Bo Maryniuk <bo@suse.de>
|
||||||
Date: Wed, 14 Nov 2018 17:36:23 +0100
|
Date: Wed, 14 Nov 2018 17:36:23 +0100
|
||||||
Subject: [PATCH] Get os_arch also without RPM package installed
|
Subject: [PATCH] Get os_arch also without RPM package installed
|
||||||
@ -17,29 +17,31 @@ Add UT for OS arch detection when no CPU arch or machine can be determined
|
|||||||
|
|
||||||
Remove unsupported testcase
|
Remove unsupported testcase
|
||||||
---
|
---
|
||||||
tests/unit/utils/test_pkg.py | 48 ++++++++------------------------------------
|
tests/unit/utils/test_pkg.py | 53 ++++++------------------------------
|
||||||
1 file changed, 8 insertions(+), 40 deletions(-)
|
1 file changed, 8 insertions(+), 45 deletions(-)
|
||||||
|
|
||||||
diff --git a/tests/unit/utils/test_pkg.py b/tests/unit/utils/test_pkg.py
|
diff --git a/tests/unit/utils/test_pkg.py b/tests/unit/utils/test_pkg.py
|
||||||
index e8b19bef14..361e0bf92f 100644
|
index b4a67b8e57..404b01b12b 100644
|
||||||
--- a/tests/unit/utils/test_pkg.py
|
--- a/tests/unit/utils/test_pkg.py
|
||||||
+++ b/tests/unit/utils/test_pkg.py
|
+++ b/tests/unit/utils/test_pkg.py
|
||||||
@@ -2,51 +2,19 @@
|
@@ -1,53 +1,16 @@
|
||||||
|
-# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, unicode_literals, print_function
|
-
|
||||||
|
-from __future__ import absolute_import, print_function, unicode_literals
|
||||||
-from tests.support.unit import TestCase
|
-
|
||||||
-from tests.support.mock import MagicMock, patch
|
|
||||||
+from tests.support.unit import TestCase, skipIf
|
|
||||||
+from tests.support.mock import Mock, MagicMock, patch, NO_MOCK, NO_MOCK_REASON
|
|
||||||
import salt.utils.pkg
|
import salt.utils.pkg
|
||||||
from salt.utils.pkg import rpm
|
from salt.utils.pkg import rpm
|
||||||
|
-from tests.support.mock import MagicMock, patch
|
||||||
|
-from tests.support.unit import TestCase
|
||||||
-
|
-
|
||||||
|
+from tests.support.mock import NO_MOCK, NO_MOCK_REASON, MagicMock, Mock, patch
|
||||||
|
+from tests.support.unit import TestCase, skipIf
|
||||||
|
|
||||||
-class PkgUtilsTestCase(TestCase):
|
-class PkgUtilsTestCase(TestCase):
|
||||||
- '''
|
- """
|
||||||
- TestCase for salt.utils.pkg module
|
- TestCase for salt.utils.pkg module
|
||||||
- '''
|
- """
|
||||||
|
-
|
||||||
- test_parameters = [
|
- test_parameters = [
|
||||||
- ("16.0.0.49153-0+f1", "", "16.0.0.49153-0+f1"),
|
- ("16.0.0.49153-0+f1", "", "16.0.0.49153-0+f1"),
|
||||||
- ("> 15.0.0", ">", "15.0.0"),
|
- ("> 15.0.0", ">", "15.0.0"),
|
||||||
@ -62,13 +64,13 @@ index e8b19bef14..361e0bf92f 100644
|
|||||||
- ("<=>15.0.0", "<=>", "15.0.0"),
|
- ("<=>15.0.0", "<=>", "15.0.0"),
|
||||||
- ("<>15.0.0", "<>", "15.0.0"),
|
- ("<>15.0.0", "<>", "15.0.0"),
|
||||||
- ("=15.0.0", "=", "15.0.0"),
|
- ("=15.0.0", "=", "15.0.0"),
|
||||||
- ("", "", "")
|
- ("", "", ""),
|
||||||
- ]
|
- ]
|
||||||
-
|
-
|
||||||
- def test_split_comparison(self):
|
- def test_split_comparison(self):
|
||||||
- '''
|
- """
|
||||||
- Tests salt.utils.pkg.split_comparison
|
- Tests salt.utils.pkg.split_comparison
|
||||||
- '''
|
- """
|
||||||
- for test_parameter in self.test_parameters:
|
- for test_parameter in self.test_parameters:
|
||||||
- oper, verstr = salt.utils.pkg.split_comparison(test_parameter[0])
|
- oper, verstr = salt.utils.pkg.split_comparison(test_parameter[0])
|
||||||
- self.assertEqual(test_parameter[1], oper)
|
- self.assertEqual(test_parameter[1], oper)
|
||||||
@ -80,11 +82,11 @@ index e8b19bef14..361e0bf92f 100644
|
|||||||
|
|
||||||
|
|
||||||
+@skipIf(NO_MOCK, NO_MOCK_REASON)
|
+@skipIf(NO_MOCK, NO_MOCK_REASON)
|
||||||
+@skipIf(pytest is None, 'PyTest is missing')
|
+@skipIf(pytest is None, "PyTest is missing")
|
||||||
class PkgRPMTestCase(TestCase):
|
class PkgRPMTestCase(TestCase):
|
||||||
'''
|
"""
|
||||||
Test case for pkg.rpm utils
|
Test case for pkg.rpm utils
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From 0b6106815b708bc4cf25b4a02ebc8b7ebf299b39 Mon Sep 17 00:00:00 2001
|
From d9618fed8ff241c6f127f08ec59fea9c8b8e12a6 Mon Sep 17 00:00:00 2001
|
||||||
From: Alberto Planas <aplanas@suse.com>
|
From: Alberto Planas <aplanas@suse.com>
|
||||||
Date: Tue, 27 Oct 2020 13:16:37 +0100
|
Date: Tue, 27 Oct 2020 13:16:37 +0100
|
||||||
Subject: [PATCH] grains: master can read grains
|
Subject: [PATCH] grains: master can read grains
|
||||||
@ -8,10 +8,10 @@ Subject: [PATCH] grains: master can read grains
|
|||||||
1 file changed, 8 insertions(+), 2 deletions(-)
|
1 file changed, 8 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/grains/extra.py b/salt/grains/extra.py
|
diff --git a/salt/grains/extra.py b/salt/grains/extra.py
|
||||||
index 6a26aece77..f80061ff4e 100644
|
index d25faac3b7..7729a5c0a5 100644
|
||||||
--- a/salt/grains/extra.py
|
--- a/salt/grains/extra.py
|
||||||
+++ b/salt/grains/extra.py
|
+++ b/salt/grains/extra.py
|
||||||
@@ -94,8 +94,14 @@ def __secure_boot():
|
@@ -76,8 +76,14 @@ def __secure_boot():
|
||||||
enabled = False
|
enabled = False
|
||||||
sboot = glob.glob("/sys/firmware/efi/vars/SecureBoot-*/data")
|
sboot = glob.glob("/sys/firmware/efi/vars/SecureBoot-*/data")
|
||||||
if len(sboot) == 1:
|
if len(sboot) == 1:
|
||||||
@ -29,6 +29,6 @@ index 6a26aece77..f80061ff4e 100644
|
|||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
2.29.1
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:b2c1abe2851b8a9055a361fc2409477ac01ec4829f0588f3b58533cb5f1e4e89
|
oid sha256:7480c92d4197b02504c9a130a0268fd028eb0fd45d3c7a7075b8b78da85050ed
|
||||||
size 8775440
|
size 9943287
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From a11587a1209cd198f421fafdb43510b6d651f4b2 Mon Sep 17 00:00:00 2001
|
From ac34a8d839f91285f4ced605250422a1ecf5cb55 Mon Sep 17 00:00:00 2001
|
||||||
From: EricS <54029547+ESiebigteroth@users.noreply.github.com>
|
From: EricS <54029547+ESiebigteroth@users.noreply.github.com>
|
||||||
Date: Tue, 3 Sep 2019 11:22:53 +0200
|
Date: Tue, 3 Sep 2019 11:22:53 +0200
|
||||||
Subject: [PATCH] Implement network.fqdns module function (bsc#1134860)
|
Subject: [PATCH] Implement network.fqdns module function (bsc#1134860)
|
||||||
@ -9,70 +9,30 @@ Subject: [PATCH] Implement network.fqdns module function (bsc#1134860)
|
|||||||
* Reuse network.fqdns in grains.core.fqdns
|
* Reuse network.fqdns in grains.core.fqdns
|
||||||
* Return empty list when fqdns grains is disabled
|
* Return empty list when fqdns grains is disabled
|
||||||
|
|
||||||
|
|
||||||
Co-authored-by: Eric Siebigteroth <eric.siebigteroth@suse.de>
|
Co-authored-by: Eric Siebigteroth <eric.siebigteroth@suse.de>
|
||||||
---
|
---
|
||||||
salt/grains/core.py | 66 +++++-------------------------------------
|
salt/grains/core.py | 58 +++-------------------------------
|
||||||
salt/modules/network.py | 60 ++++++++++++++++++++++++++++++++++++++
|
salt/modules/network.py | 12 +++----
|
||||||
salt/utils/network.py | 12 ++++++++
|
salt/utils/network.py | 2 +-
|
||||||
tests/unit/grains/test_core.py | 63 +++++++++++++++++++++++++++++++---------
|
tests/unit/grains/test_core.py | 55 ++++++++++++--------------------
|
||||||
4 files changed, 130 insertions(+), 71 deletions(-)
|
4 files changed, 31 insertions(+), 96 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/grains/core.py b/salt/grains/core.py
|
diff --git a/salt/grains/core.py b/salt/grains/core.py
|
||||||
index 0f3ccd9b92..77ae99590f 100644
|
index 5f18ba4a58..0dc1d97f97 100644
|
||||||
--- a/salt/grains/core.py
|
--- a/salt/grains/core.py
|
||||||
+++ b/salt/grains/core.py
|
+++ b/salt/grains/core.py
|
||||||
@@ -26,8 +26,9 @@ from errno import EACCES, EPERM
|
@@ -23,7 +23,6 @@ import uuid
|
||||||
import datetime
|
|
||||||
import warnings
|
import warnings
|
||||||
import time
|
import zlib
|
||||||
+import salt.modules.network
|
from errno import EACCES, EPERM
|
||||||
|
|
||||||
-from multiprocessing.pool import ThreadPool
|
-from multiprocessing.pool import ThreadPool
|
||||||
+from salt.utils.network import _get_interfaces
|
|
||||||
|
|
||||||
# pylint: disable=import-error
|
import distro
|
||||||
try:
|
import salt.exceptions
|
||||||
@@ -84,6 +85,7 @@ __salt__ = {
|
@@ -2406,59 +2405,10 @@ def fqdns():
|
||||||
'cmd.run_all': salt.modules.cmdmod._run_all_quiet,
|
|
||||||
'smbios.records': salt.modules.smbios.records,
|
|
||||||
'smbios.get': salt.modules.smbios.get,
|
|
||||||
+ 'network.fqdns': salt.modules.network.fqdns,
|
|
||||||
}
|
|
||||||
log = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
@@ -107,7 +109,6 @@ HAS_UNAME = True
|
|
||||||
if not hasattr(os, 'uname'):
|
|
||||||
HAS_UNAME = False
|
|
||||||
|
|
||||||
-_INTERFACES = {}
|
|
||||||
|
|
||||||
# Possible value for h_errno defined in netdb.h
|
|
||||||
HOST_NOT_FOUND = 1
|
|
||||||
@@ -1553,17 +1554,6 @@ def _linux_bin_exists(binary):
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
-def _get_interfaces():
|
|
||||||
- '''
|
|
||||||
- Provide a dict of the connected interfaces and their ip addresses
|
|
||||||
- '''
|
|
||||||
-
|
|
||||||
- global _INTERFACES
|
|
||||||
- if not _INTERFACES:
|
|
||||||
- _INTERFACES = salt.utils.network.interfaces()
|
|
||||||
- return _INTERFACES
|
|
||||||
-
|
|
||||||
-
|
|
||||||
def _parse_lsb_release():
|
|
||||||
ret = {}
|
|
||||||
try:
|
|
||||||
@@ -2271,52 +2261,12 @@ def fqdns():
|
|
||||||
'''
|
|
||||||
Return all known FQDNs for the system by enumerating all interfaces and
|
|
||||||
then trying to reverse resolve them (excluding 'lo' interface).
|
then trying to reverse resolve them (excluding 'lo' interface).
|
||||||
+ To disable the fqdns grain, set enable_fqdns_grains: False in the minion configuration file.
|
To disable the fqdns grain, set enable_fqdns_grains: False in the minion configuration file.
|
||||||
'''
|
"""
|
||||||
- # Provides:
|
- # Provides:
|
||||||
- # fqdns
|
- # fqdns
|
||||||
-
|
-
|
||||||
@ -82,21 +42,29 @@ index 0f3ccd9b92..77ae99590f 100644
|
|||||||
- def _lookup_fqdn(ip):
|
- def _lookup_fqdn(ip):
|
||||||
- try:
|
- try:
|
||||||
- name, aliaslist, addresslist = socket.gethostbyaddr(ip)
|
- name, aliaslist, addresslist = socket.gethostbyaddr(ip)
|
||||||
- return [socket.getfqdn(name)] + [als for als in aliaslist if salt.utils.network.is_fqdn(als)]
|
- return [socket.getfqdn(name)] + [
|
||||||
|
- als for als in aliaslist if salt.utils.network.is_fqdn(als)
|
||||||
|
- ]
|
||||||
- except socket.herror as err:
|
- except socket.herror as err:
|
||||||
- if err.errno in (0, HOST_NOT_FOUND, NO_DATA):
|
- 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.
|
- # No FQDN for this IP address, so we don't need to know this all the time.
|
||||||
- log.debug("Unable to resolve address %s: %s", ip, err)
|
- log.debug("Unable to resolve address %s: %s", ip, err)
|
||||||
- else:
|
- else:
|
||||||
- log.error(err_message, ip, err)
|
- log.error(err_message, ip, err)
|
||||||
- except (socket.error, socket.gaierror, socket.timeout) as err:
|
- except (OSError, socket.gaierror, socket.timeout) as err:
|
||||||
- log.error(err_message, ip, err)
|
- log.error(err_message, ip, err)
|
||||||
-
|
-
|
||||||
- start = time.time()
|
- start = time.time()
|
||||||
-
|
-
|
||||||
- addresses = salt.utils.network.ip_addrs(include_loopback=False, interface_data=_get_interfaces())
|
- addresses = salt.utils.network.ip_addrs(
|
||||||
- addresses.extend(salt.utils.network.ip_addrs6(include_loopback=False, interface_data=_get_interfaces()))
|
- include_loopback=False, interface_data=_get_interfaces()
|
||||||
- err_message = 'Exception during resolving address: %s'
|
- )
|
||||||
|
- addresses.extend(
|
||||||
|
- salt.utils.network.ip_addrs6(
|
||||||
|
- include_loopback=False, interface_data=_get_interfaces()
|
||||||
|
- )
|
||||||
|
- )
|
||||||
|
- err_message = "Exception during resolving address: %s"
|
||||||
-
|
-
|
||||||
- # Create a ThreadPool to process the underlying calls to 'socket.gethostbyaddr' in parallel.
|
- # Create a ThreadPool to process the underlying calls to 'socket.gethostbyaddr' in parallel.
|
||||||
- # This avoid blocking the execution when the "fqdn" is not defined for certains IP addresses, which was causing
|
- # This avoid blocking the execution when the "fqdn" is not defined for certains IP addresses, which was causing
|
||||||
@ -115,191 +83,179 @@ index 0f3ccd9b92..77ae99590f 100644
|
|||||||
- fqdns.update(item)
|
- fqdns.update(item)
|
||||||
-
|
-
|
||||||
- elapsed = time.time() - start
|
- elapsed = time.time() - start
|
||||||
- log.debug('Elapsed time getting FQDNs: {} seconds'.format(elapsed))
|
- log.debug("Elapsed time getting FQDNs: {} seconds".format(elapsed))
|
||||||
-
|
-
|
||||||
- return {"fqdns": sorted(list(fqdns))}
|
- return {"fqdns": sorted(list(fqdns))}
|
||||||
+ opt = {"fqdns": []}
|
+ opt = {"fqdns": []}
|
||||||
+ if __opts__.get('enable_fqdns_grains', True) == True:
|
+ if __opts__.get("enable_fqdns_grains", True) == True:
|
||||||
+ opt = __salt__['network.fqdns']()
|
+ opt = __salt__["network.fqdns"]()
|
||||||
+ return opt
|
+ return opt
|
||||||
|
|
||||||
|
|
||||||
def ip_fqdn():
|
def ip_fqdn():
|
||||||
diff --git a/salt/modules/network.py b/salt/modules/network.py
|
diff --git a/salt/modules/network.py b/salt/modules/network.py
|
||||||
index 38e2bc326e..880f4f8d5f 100644
|
index 2e1410c288..59ed43bba6 100644
|
||||||
--- a/salt/modules/network.py
|
--- a/salt/modules/network.py
|
||||||
+++ b/salt/modules/network.py
|
+++ b/salt/modules/network.py
|
||||||
@@ -11,6 +11,10 @@ import logging
|
@@ -2,7 +2,6 @@
|
||||||
import re
|
Module for gathering and managing network information
|
||||||
import os
|
"""
|
||||||
import socket
|
|
||||||
+import time
|
|
||||||
+
|
|
||||||
+from multiprocessing.pool import ThreadPool
|
|
||||||
+
|
|
||||||
|
|
||||||
# Import salt libs
|
-# Import python libs
|
||||||
|
import datetime
|
||||||
|
import hashlib
|
||||||
|
import logging
|
||||||
|
@@ -12,7 +11,6 @@ import socket
|
||||||
|
import time
|
||||||
|
from multiprocessing.pool import ThreadPool
|
||||||
|
|
||||||
|
-# Import salt libs
|
||||||
import salt.utils.decorators.path
|
import salt.utils.decorators.path
|
||||||
@@ -1887,3 +1891,59 @@ def iphexval(ip):
|
import salt.utils.functools
|
||||||
a = ip.split('.')
|
import salt.utils.network
|
||||||
hexval = ['%02X' % int(x) for x in a] # pylint: disable=E1321
|
@@ -20,8 +18,6 @@ import salt.utils.platform
|
||||||
return ''.join(hexval)
|
import salt.utils.validate.net
|
||||||
+
|
from salt._compat import ipaddress
|
||||||
+
|
from salt.exceptions import CommandExecutionError
|
||||||
+def fqdns():
|
-
|
||||||
+ '''
|
-# Import 3rd-party libs
|
||||||
+ Return all known FQDNs for the system by enumerating all interfaces and
|
from salt.ext.six.moves import range
|
||||||
+ then trying to reverse resolve them (excluding 'lo' interface).
|
|
||||||
+ '''
|
log = logging.getLogger(__name__)
|
||||||
+ # Provides:
|
@@ -2076,7 +2072,10 @@ def fqdns():
|
||||||
+ # fqdns
|
|
||||||
+
|
def _lookup_fqdn(ip):
|
||||||
+ # Possible value for h_errno defined in netdb.h
|
try:
|
||||||
+ HOST_NOT_FOUND = 1
|
- return [socket.getfqdn(socket.gethostbyaddr(ip)[0])]
|
||||||
+ NO_DATA = 4
|
|
||||||
+
|
|
||||||
+ grains = {}
|
|
||||||
+ fqdns = set()
|
|
||||||
+
|
|
||||||
+ def _lookup_fqdn(ip):
|
|
||||||
+ try:
|
|
||||||
+ name, aliaslist, addresslist = socket.gethostbyaddr(ip)
|
+ name, aliaslist, addresslist = socket.gethostbyaddr(ip)
|
||||||
+ return [socket.getfqdn(name)] + [als for als in aliaslist if salt.utils.network.is_fqdn(als)]
|
+ return [socket.getfqdn(name)] + [
|
||||||
+ except socket.herror as err:
|
+ als for als in aliaslist if salt.utils.network.is_fqdn(als)
|
||||||
+ 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.
|
except socket.herror as err:
|
||||||
+ log.debug("Unable to resolve address %s: %s", ip, err)
|
if err.errno in (0, HOST_NOT_FOUND, NO_DATA):
|
||||||
+ else:
|
# No FQDN for this IP address, so we don't need to know this all the time.
|
||||||
+ log.error(err_message, err)
|
@@ -2102,13 +2101,12 @@ def fqdns():
|
||||||
+ except (socket.error, socket.gaierror, socket.timeout) as err:
|
# This avoid blocking the execution when the "fqdn" is not defined for certains IP addresses, which was causing
|
||||||
+ log.error(err_message, err)
|
# that "socket.timeout" was reached multiple times secuencially, blocking execution for several seconds.
|
||||||
+
|
|
||||||
+ start = time.time()
|
- results = []
|
||||||
+
|
try:
|
||||||
+ addresses = salt.utils.network.ip_addrs(include_loopback=False, interface_data=salt.utils.network._get_interfaces())
|
pool = ThreadPool(8)
|
||||||
+ addresses.extend(salt.utils.network.ip_addrs6(include_loopback=False, interface_data=salt.utils.network._get_interfaces()))
|
results = pool.map(_lookup_fqdn, addresses)
|
||||||
+ err_message = 'Exception during resolving address: %s'
|
pool.close()
|
||||||
+
|
pool.join()
|
||||||
+ # Create a ThreadPool to process the underlying calls to 'socket.gethostbyaddr' in parallel.
|
- except Exception as exc: # pylint: disable=broad-except
|
||||||
+ # This avoid blocking the execution when the "fqdn" is not defined for certains IP addresses, which was causing
|
|
||||||
+ # that "socket.timeout" was reached multiple times secuencially, blocking execution for several seconds.
|
|
||||||
+
|
|
||||||
+ try:
|
|
||||||
+ pool = ThreadPool(8)
|
|
||||||
+ results = pool.map(_lookup_fqdn, addresses)
|
|
||||||
+ pool.close()
|
|
||||||
+ pool.join()
|
|
||||||
+ except Exception as exc:
|
+ except Exception as exc:
|
||||||
+ log.error("Exception while creating a ThreadPool for resolving FQDNs: %s", exc)
|
log.error("Exception while creating a ThreadPool for resolving FQDNs: %s", exc)
|
||||||
+
|
|
||||||
+ for item in results:
|
for item in results:
|
||||||
+ if item:
|
|
||||||
+ fqdns.update(item)
|
|
||||||
+
|
|
||||||
+ elapsed = time.time() - start
|
|
||||||
+ log.debug('Elapsed time getting FQDNs: {} seconds'.format(elapsed))
|
|
||||||
+
|
|
||||||
+ return {"fqdns": sorted(list(fqdns))}
|
|
||||||
\ No newline at end of file
|
|
||||||
diff --git a/salt/utils/network.py b/salt/utils/network.py
|
diff --git a/salt/utils/network.py b/salt/utils/network.py
|
||||||
index 74536cc143..4cc8a05c4a 100644
|
index d253ded3ab..25b2d06758 100644
|
||||||
--- a/salt/utils/network.py
|
--- a/salt/utils/network.py
|
||||||
+++ b/salt/utils/network.py
|
+++ b/salt/utils/network.py
|
||||||
@@ -50,6 +50,18 @@ except (ImportError, OSError, AttributeError, TypeError):
|
@@ -49,7 +49,7 @@ except (ImportError, OSError, AttributeError, TypeError):
|
||||||
pass
|
_INTERFACES = {}
|
||||||
|
|
||||||
|
|
||||||
+_INTERFACES = {}
|
-def _get_interfaces():
|
||||||
+def _get_interfaces(): #! function
|
+def _get_interfaces(): #! function
|
||||||
+ '''
|
"""
|
||||||
+ Provide a dict of the connected interfaces and their ip addresses
|
Provide a dict of the connected interfaces and their ip addresses
|
||||||
+ '''
|
"""
|
||||||
+
|
|
||||||
+ global _INTERFACES
|
|
||||||
+ if not _INTERFACES:
|
|
||||||
+ _INTERFACES = interfaces()
|
|
||||||
+ return _INTERFACES
|
|
||||||
+
|
|
||||||
+
|
|
||||||
def sanitize_host(host):
|
|
||||||
'''
|
|
||||||
Sanitize host string.
|
|
||||||
diff --git a/tests/unit/grains/test_core.py b/tests/unit/grains/test_core.py
|
diff --git a/tests/unit/grains/test_core.py b/tests/unit/grains/test_core.py
|
||||||
index ac03b57226..60914204b0 100644
|
index d760e57a54..a5ceeb8317 100644
|
||||||
--- a/tests/unit/grains/test_core.py
|
--- a/tests/unit/grains/test_core.py
|
||||||
+++ b/tests/unit/grains/test_core.py
|
+++ b/tests/unit/grains/test_core.py
|
||||||
@@ -35,6 +35,7 @@ import salt.utils.path
|
@@ -18,6 +18,7 @@ import salt.utils.network
|
||||||
import salt.modules.cmdmod
|
import salt.utils.path
|
||||||
import salt.modules.smbios
|
import salt.utils.platform
|
||||||
import salt.grains.core as core
|
from salt._compat import ipaddress
|
||||||
+import salt.modules.network
|
+from salt.ext import six
|
||||||
|
from tests.support.mixins import LoaderModuleMockMixin
|
||||||
# Import 3rd-party libs
|
from tests.support.mock import MagicMock, Mock, mock_open, patch
|
||||||
from salt.ext import six
|
from tests.support.unit import TestCase, skipIf
|
||||||
@@ -1029,6 +1030,40 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -1293,14 +1294,14 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
with patch.object(salt.utils.dns, 'parse_resolv', MagicMock(return_value=resolv_mock)):
|
):
|
||||||
assert core.dns() == ret
|
assert core.dns() == ret
|
||||||
|
|
||||||
+
|
- def test_enable_fqdns_false(self):
|
||||||
+ def test_enablefqdnsFalse(self):
|
+ def test_enablefqdnsFalse(self):
|
||||||
+ '''
|
"""
|
||||||
+ tests enable_fqdns_grains is set to False
|
tests enable_fqdns_grains is set to False
|
||||||
+ '''
|
"""
|
||||||
+ with patch.dict('salt.grains.core.__opts__', {'enable_fqdns_grains':False}):
|
with patch.dict("salt.grains.core.__opts__", {"enable_fqdns_grains": False}):
|
||||||
+ assert core.fqdns() == {"fqdns": []}
|
assert core.fqdns() == {"fqdns": []}
|
||||||
+
|
|
||||||
+
|
- def test_enable_fqdns_true(self):
|
||||||
+ def test_enablefqdnsTrue(self):
|
+ def test_enablefqdnsTrue(self):
|
||||||
+ '''
|
"""
|
||||||
+ testing that grains uses network.fqdns module
|
testing that grains uses network.fqdns module
|
||||||
+ '''
|
"""
|
||||||
+ with patch.dict('salt.grains.core.__salt__', {'network.fqdns': MagicMock(return_value="my.fake.domain")}):
|
@@ -1311,14 +1312,14 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
+ with patch.dict('salt.grains.core.__opts__', {'enable_fqdns_grains':True}):
|
with patch.dict("salt.grains.core.__opts__", {"enable_fqdns_grains": True}):
|
||||||
+ assert core.fqdns() == 'my.fake.domain'
|
assert core.fqdns() == "my.fake.domain"
|
||||||
+
|
|
||||||
+
|
- def test_enable_fqdns_none(self):
|
||||||
+ def test_enablefqdnsNone(self):
|
+ def test_enablefqdnsNone(self):
|
||||||
+ '''
|
"""
|
||||||
+ testing default fqdns grains is returned when enable_fqdns_grains is None
|
testing default fqdns grains is returned when enable_fqdns_grains is None
|
||||||
+ '''
|
"""
|
||||||
+ with patch.dict('salt.grains.core.__opts__', {'enable_fqdns_grains':None}):
|
with patch.dict("salt.grains.core.__opts__", {"enable_fqdns_grains": None}):
|
||||||
+ assert core.fqdns() == {"fqdns": []}
|
assert core.fqdns() == {"fqdns": []}
|
||||||
+
|
|
||||||
+
|
- def test_enable_fqdns_without_patching(self):
|
||||||
+ def test_enablefqdnswithoutpaching(self):
|
+ def test_enablefqdnswithoutpaching(self):
|
||||||
+ '''
|
"""
|
||||||
+ testing fqdns grains is enabled by default
|
testing fqdns grains is enabled by default
|
||||||
+ '''
|
"""
|
||||||
+ with patch.dict('salt.grains.core.__salt__', {'network.fqdns': MagicMock(return_value="my.fake.domain")}):
|
@@ -1326,23 +1327,7 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
+ assert core.fqdns() == 'my.fake.domain'
|
"salt.grains.core.__salt__",
|
||||||
+
|
{"network.fqdns": MagicMock(return_value="my.fake.domain")},
|
||||||
+
|
):
|
||||||
@skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
|
- # fqdns is disabled by default on Windows
|
||||||
@patch('salt.utils.network.ip_addrs', MagicMock(return_value=['1.2.3.4', '5.6.7.8']))
|
- if salt.utils.platform.is_windows():
|
||||||
@patch('salt.utils.network.ip_addrs6',
|
- assert core.fqdns() == {"fqdns": []}
|
||||||
@@ -1044,11 +1079,12 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
|
- else:
|
||||||
('foo.bar.baz', [], ['fe80::a8b2:93ff:fe00:0']),
|
- assert core.fqdns() == "my.fake.domain"
|
||||||
('bluesniff.foo.bar', [], ['fe80::a8b2:93ff:dead:beef'])]
|
-
|
||||||
ret = {'fqdns': ['bluesniff.foo.bar', 'foo.bar.baz', 'rinzler.evil-corp.com']}
|
- def test_enable_fqdns_false_is_proxy(self):
|
||||||
- with patch.object(socket, 'gethostbyaddr', side_effect=reverse_resolv_mock):
|
- """
|
||||||
|
- testing fqdns grains is disabled by default for proxy minions
|
||||||
|
- """
|
||||||
|
- with patch("salt.utils.platform.is_proxy", return_value=True, autospec=True):
|
||||||
|
- with patch.dict(
|
||||||
|
- "salt.grains.core.__salt__",
|
||||||
|
- {"network.fqdns": MagicMock(return_value="my.fake.domain")},
|
||||||
|
- ):
|
||||||
|
- # fqdns is disabled by default on proxy minions
|
||||||
|
- assert core.fqdns() == {"fqdns": []}
|
||||||
|
+ assert core.fqdns() == "my.fake.domain"
|
||||||
|
|
||||||
|
@skipIf(not salt.utils.platform.is_linux(), "System is not Linux")
|
||||||
|
@patch(
|
||||||
|
@@ -1367,11 +1352,12 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
|
("bluesniff.foo.bar", [], ["fe80::a8b2:93ff:dead:beef"]),
|
||||||
|
]
|
||||||
|
ret = {"fqdns": ["bluesniff.foo.bar", "foo.bar.baz", "rinzler.evil-corp.com"]}
|
||||||
|
- with patch.object(socket, "gethostbyaddr", side_effect=reverse_resolv_mock):
|
||||||
- fqdns = core.fqdns()
|
- fqdns = core.fqdns()
|
||||||
- assert "fqdns" in fqdns
|
- assert "fqdns" in fqdns
|
||||||
- assert len(fqdns['fqdns']) == len(ret['fqdns'])
|
- assert len(fqdns["fqdns"]) == len(ret["fqdns"])
|
||||||
- assert set(fqdns['fqdns']) == set(ret['fqdns'])
|
- assert set(fqdns["fqdns"]) == set(ret["fqdns"])
|
||||||
+ with patch.dict(core.__salt__, {'network.fqdns': salt.modules.network.fqdns}):
|
+ with patch.dict(core.__salt__, {"network.fqdns": salt.modules.network.fqdns}):
|
||||||
+ with patch.object(socket, 'gethostbyaddr', side_effect=reverse_resolv_mock):
|
+ with patch.object(socket, "gethostbyaddr", side_effect=reverse_resolv_mock):
|
||||||
+ fqdns = core.fqdns()
|
+ fqdns = core.fqdns()
|
||||||
+ assert "fqdns" in fqdns
|
+ assert "fqdns" in fqdns
|
||||||
+ assert len(fqdns['fqdns']) == len(ret['fqdns'])
|
+ assert len(fqdns["fqdns"]) == len(ret["fqdns"])
|
||||||
+ assert set(fqdns['fqdns']) == set(ret['fqdns'])
|
+ assert set(fqdns["fqdns"]) == set(ret["fqdns"])
|
||||||
|
|
||||||
@skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
|
@skipIf(not salt.utils.platform.is_linux(), "System is not Linux")
|
||||||
@patch('salt.utils.network.ip_addrs', MagicMock(return_value=['1.2.3.4']))
|
@patch("salt.utils.network.ip_addrs", MagicMock(return_value=["1.2.3.4"]))
|
||||||
@@ -1094,14 +1130,15 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -1437,14 +1423,15 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
('rinzler.evil-corp.com', ["false-hostname", "badaliass"], ['5.6.7.8']),
|
["fe80::a8b2:93ff:dead:beef"],
|
||||||
('foo.bar.baz', [], ['fe80::a8b2:93ff:fe00:0']),
|
),
|
||||||
('bluesniff.foo.bar', ["alias.bluesniff.foo.bar"], ['fe80::a8b2:93ff:dead:beef'])]
|
]
|
||||||
- with patch.object(socket, 'gethostbyaddr', side_effect=reverse_resolv_mock):
|
- with patch.object(socket, "gethostbyaddr", side_effect=reverse_resolv_mock):
|
||||||
- fqdns = core.fqdns()
|
- fqdns = core.fqdns()
|
||||||
- assert "fqdns" in fqdns
|
- assert "fqdns" in fqdns
|
||||||
- for alias in ["this.is.valid.alias", "alias.bluesniff.foo.bar"]:
|
- for alias in ["this.is.valid.alias", "alias.bluesniff.foo.bar"]:
|
||||||
@ -307,8 +263,8 @@ index ac03b57226..60914204b0 100644
|
|||||||
-
|
-
|
||||||
- for alias in ["throwmeaway", "false-hostname", "badaliass"]:
|
- for alias in ["throwmeaway", "false-hostname", "badaliass"]:
|
||||||
- assert alias not in fqdns["fqdns"]
|
- assert alias not in fqdns["fqdns"]
|
||||||
+ with patch.dict(core.__salt__, {'network.fqdns': salt.modules.network.fqdns}):
|
+ with patch.dict(core.__salt__, {"network.fqdns": salt.modules.network.fqdns}):
|
||||||
+ with patch.object(socket, 'gethostbyaddr', side_effect=reverse_resolv_mock):
|
+ with patch.object(socket, "gethostbyaddr", side_effect=reverse_resolv_mock):
|
||||||
+ fqdns = core.fqdns()
|
+ fqdns = core.fqdns()
|
||||||
+ assert "fqdns" in fqdns
|
+ assert "fqdns" in fqdns
|
||||||
+ for alias in ["this.is.valid.alias", "alias.bluesniff.foo.bar"]:
|
+ for alias in ["this.is.valid.alias", "alias.bluesniff.foo.bar"]:
|
||||||
@ -318,8 +274,8 @@ index ac03b57226..60914204b0 100644
|
|||||||
+ assert alias not in fqdns["fqdns"]
|
+ assert alias not in fqdns["fqdns"]
|
||||||
|
|
||||||
def test_core_virtual(self):
|
def test_core_virtual(self):
|
||||||
'''
|
"""
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From 65e33acaf10fdd838c0cdf34ec93df3a2ed1f0d2 Mon Sep 17 00:00:00 2001
|
From e53d50ce5fabf67eeb5344f7be9cccbb09d0179b Mon Sep 17 00:00:00 2001
|
||||||
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||||
<psuarezhernandez@suse.com>
|
<psuarezhernandez@suse.com>
|
||||||
Date: Thu, 26 Sep 2019 10:41:06 +0100
|
Date: Thu, 26 Sep 2019 10:41:06 +0100
|
||||||
@ -6,38 +6,39 @@ Subject: [PATCH] Improve batch_async to release consumed memory
|
|||||||
(bsc#1140912)
|
(bsc#1140912)
|
||||||
|
|
||||||
---
|
---
|
||||||
salt/cli/batch_async.py | 73 ++++++++++++++++++++++++++++++-------------------
|
salt/cli/batch_async.py | 89 ++++++++++++++++++++++++-----------------
|
||||||
1 file changed, 45 insertions(+), 28 deletions(-)
|
1 file changed, 52 insertions(+), 37 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/cli/batch_async.py b/salt/cli/batch_async.py
|
diff --git a/salt/cli/batch_async.py b/salt/cli/batch_async.py
|
||||||
index 8a67331102..2bb50459c8 100644
|
index 388b709416..0a0b8f5f83 100644
|
||||||
--- a/salt/cli/batch_async.py
|
--- a/salt/cli/batch_async.py
|
||||||
+++ b/salt/cli/batch_async.py
|
+++ b/salt/cli/batch_async.py
|
||||||
@@ -5,6 +5,7 @@ Execute a job on the targeted minions by using a moving window of fixed size `ba
|
@@ -2,7 +2,7 @@
|
||||||
|
Execute a job on the targeted minions by using a moving window of fixed size `batch`.
|
||||||
|
"""
|
||||||
|
|
||||||
# Import python libs
|
-import fnmatch
|
||||||
from __future__ import absolute_import, print_function, unicode_literals
|
|
||||||
+import gc
|
+import gc
|
||||||
import tornado
|
|
||||||
|
|
||||||
# Import salt libs
|
# pylint: enable=import-error,no-name-in-module,redefined-builtin
|
||||||
@@ -77,6 +78,7 @@ class BatchAsync(object):
|
import logging
|
||||||
|
@@ -78,6 +78,7 @@ class BatchAsync:
|
||||||
self.batch_jid = jid_gen()
|
self.batch_jid = jid_gen()
|
||||||
self.find_job_jid = jid_gen()
|
self.find_job_jid = jid_gen()
|
||||||
self.find_job_returned = set()
|
self.find_job_returned = set()
|
||||||
+ self.ended = False
|
+ self.ended = False
|
||||||
self.event = salt.utils.event.get_event(
|
self.event = salt.utils.event.get_event(
|
||||||
'master',
|
"master",
|
||||||
self.opts['sock_dir'],
|
self.opts["sock_dir"],
|
||||||
@@ -86,6 +88,7 @@ class BatchAsync(object):
|
@@ -88,6 +89,7 @@ class BatchAsync:
|
||||||
io_loop=ioloop,
|
keep_loop=True,
|
||||||
keep_loop=True)
|
)
|
||||||
self.scheduled = False
|
self.scheduled = False
|
||||||
+ self.patterns = {}
|
+ self.patterns = {}
|
||||||
|
|
||||||
def __set_event_handler(self):
|
def __set_event_handler(self):
|
||||||
ping_return_pattern = 'salt/job/{0}/ret/*'.format(self.ping_jid)
|
ping_return_pattern = "salt/job/{}/ret/*".format(self.ping_jid)
|
||||||
@@ -116,7 +119,7 @@ class BatchAsync(object):
|
@@ -118,7 +120,7 @@ class BatchAsync:
|
||||||
if minion in self.active:
|
if minion in self.active:
|
||||||
self.active.remove(minion)
|
self.active.remove(minion)
|
||||||
self.done_minions.add(minion)
|
self.done_minions.add(minion)
|
||||||
@ -45,29 +46,37 @@ index 8a67331102..2bb50459c8 100644
|
|||||||
+ self.event.io_loop.spawn_callback(self.schedule_next)
|
+ self.event.io_loop.spawn_callback(self.schedule_next)
|
||||||
|
|
||||||
def _get_next(self):
|
def _get_next(self):
|
||||||
to_run = self.minions.difference(
|
to_run = (
|
||||||
@@ -129,23 +132,23 @@ class BatchAsync(object):
|
@@ -132,27 +134,27 @@ class BatchAsync:
|
||||||
)
|
)
|
||||||
return set(list(to_run)[:next_batch_size])
|
return set(list(to_run)[:next_batch_size])
|
||||||
|
|
||||||
- @tornado.gen.coroutine
|
- @tornado.gen.coroutine
|
||||||
def check_find_job(self, batch_minions, jid):
|
def check_find_job(self, batch_minions, jid):
|
||||||
- find_job_return_pattern = 'salt/job/{0}/ret/*'.format(jid)
|
- find_job_return_pattern = "salt/job/{}/ret/*".format(jid)
|
||||||
- self.event.unsubscribe(find_job_return_pattern, match_type='glob')
|
- self.event.unsubscribe(find_job_return_pattern, match_type="glob")
|
||||||
- self.patterns.remove((find_job_return_pattern, "find_job_return"))
|
- self.patterns.remove((find_job_return_pattern, "find_job_return"))
|
||||||
+ if self.event:
|
+ if self.event:
|
||||||
+ find_job_return_pattern = 'salt/job/{0}/ret/*'.format(jid)
|
+ find_job_return_pattern = "salt/job/{}/ret/*".format(jid)
|
||||||
+ self.event.unsubscribe(find_job_return_pattern, match_type='glob')
|
+ self.event.unsubscribe(find_job_return_pattern, match_type="glob")
|
||||||
+ self.patterns.remove((find_job_return_pattern, "find_job_return"))
|
+ self.patterns.remove((find_job_return_pattern, "find_job_return"))
|
||||||
|
|
||||||
- timedout_minions = batch_minions.difference(self.find_job_returned).difference(self.done_minions)
|
- timedout_minions = batch_minions.difference(self.find_job_returned).difference(
|
||||||
|
- self.done_minions
|
||||||
|
- )
|
||||||
- self.timedout_minions = self.timedout_minions.union(timedout_minions)
|
- self.timedout_minions = self.timedout_minions.union(timedout_minions)
|
||||||
- self.active = self.active.difference(self.timedout_minions)
|
- self.active = self.active.difference(self.timedout_minions)
|
||||||
- running = batch_minions.difference(self.done_minions).difference(self.timedout_minions)
|
- running = batch_minions.difference(self.done_minions).difference(
|
||||||
+ timedout_minions = batch_minions.difference(self.find_job_returned).difference(self.done_minions)
|
- self.timedout_minions
|
||||||
|
- )
|
||||||
|
+ timedout_minions = batch_minions.difference(
|
||||||
|
+ self.find_job_returned
|
||||||
|
+ ).difference(self.done_minions)
|
||||||
+ self.timedout_minions = self.timedout_minions.union(timedout_minions)
|
+ self.timedout_minions = self.timedout_minions.union(timedout_minions)
|
||||||
+ self.active = self.active.difference(self.timedout_minions)
|
+ self.active = self.active.difference(self.timedout_minions)
|
||||||
+ running = batch_minions.difference(self.done_minions).difference(self.timedout_minions)
|
+ running = batch_minions.difference(self.done_minions).difference(
|
||||||
|
+ self.timedout_minions
|
||||||
|
+ )
|
||||||
|
|
||||||
- if timedout_minions:
|
- if timedout_minions:
|
||||||
- self.schedule_next()
|
- self.schedule_next()
|
||||||
@ -83,61 +92,65 @@ index 8a67331102..2bb50459c8 100644
|
|||||||
|
|
||||||
@tornado.gen.coroutine
|
@tornado.gen.coroutine
|
||||||
def find_job(self, minions):
|
def find_job(self, minions):
|
||||||
@@ -165,8 +168,8 @@ class BatchAsync(object):
|
@@ -175,18 +177,12 @@ class BatchAsync:
|
||||||
gather_job_timeout=self.opts['gather_job_timeout'],
|
|
||||||
jid=jid,
|
jid=jid,
|
||||||
**self.eauth)
|
**self.eauth
|
||||||
|
)
|
||||||
- self.event.io_loop.call_later(
|
- self.event.io_loop.call_later(
|
||||||
- self.opts['gather_job_timeout'],
|
- self.opts["gather_job_timeout"], self.check_find_job, not_done, jid
|
||||||
+ yield tornado.gen.sleep(self.opts['gather_job_timeout'])
|
- )
|
||||||
+ self.event.io_loop.spawn_callback(
|
+ yield tornado.gen.sleep(self.opts["gather_job_timeout"])
|
||||||
self.check_find_job,
|
+ self.event.io_loop.spawn_callback(self.check_find_job, not_done, jid)
|
||||||
not_done,
|
|
||||||
jid)
|
|
||||||
@@ -174,10 +177,6 @@ class BatchAsync(object):
|
|
||||||
@tornado.gen.coroutine
|
@tornado.gen.coroutine
|
||||||
def start(self):
|
def start(self):
|
||||||
self.__set_event_handler()
|
self.__set_event_handler()
|
||||||
- #start batching even if not all minions respond to ping
|
- # start batching even if not all minions respond to ping
|
||||||
- self.event.io_loop.call_later(
|
- self.event.io_loop.call_later(
|
||||||
- self.batch_presence_ping_timeout or self.opts['gather_job_timeout'],
|
- self.batch_presence_ping_timeout or self.opts["gather_job_timeout"],
|
||||||
- self.start_batch)
|
- self.start_batch,
|
||||||
|
- )
|
||||||
ping_return = yield self.local.run_job_async(
|
ping_return = yield self.local.run_job_async(
|
||||||
self.opts['tgt'],
|
self.opts["tgt"],
|
||||||
'test.ping',
|
"test.ping",
|
||||||
@@ -191,6 +190,10 @@ class BatchAsync(object):
|
@@ -198,6 +194,11 @@ class BatchAsync:
|
||||||
metadata=self.metadata,
|
**self.eauth
|
||||||
**self.eauth)
|
)
|
||||||
self.targeted_minions = set(ping_return['minions'])
|
self.targeted_minions = set(ping_return["minions"])
|
||||||
+ #start batching even if not all minions respond to ping
|
+ # start batching even if not all minions respond to ping
|
||||||
+ yield tornado.gen.sleep(self.batch_presence_ping_timeout or self.opts['gather_job_timeout'])
|
+ yield tornado.gen.sleep(
|
||||||
|
+ self.batch_presence_ping_timeout or self.opts["gather_job_timeout"]
|
||||||
|
+ )
|
||||||
+ self.event.io_loop.spawn_callback(self.start_batch)
|
+ self.event.io_loop.spawn_callback(self.start_batch)
|
||||||
+
|
|
||||||
|
|
||||||
@tornado.gen.coroutine
|
@tornado.gen.coroutine
|
||||||
def start_batch(self):
|
def start_batch(self):
|
||||||
@@ -202,12 +205,14 @@ class BatchAsync(object):
|
@@ -209,14 +210,18 @@ class BatchAsync:
|
||||||
"down_minions": self.targeted_minions.difference(self.minions),
|
"down_minions": self.targeted_minions.difference(self.minions),
|
||||||
"metadata": self.metadata
|
"metadata": self.metadata,
|
||||||
}
|
}
|
||||||
- self.event.fire_event(data, "salt/batch/{0}/start".format(self.batch_jid))
|
- self.event.fire_event(data, "salt/batch/{}/start".format(self.batch_jid))
|
||||||
- yield self.run_next()
|
- yield self.run_next()
|
||||||
+ ret = self.event.fire_event(data, "salt/batch/{0}/start".format(self.batch_jid))
|
+ ret = self.event.fire_event(
|
||||||
|
+ data, "salt/batch/{}/start".format(self.batch_jid)
|
||||||
|
+ )
|
||||||
+ self.event.io_loop.spawn_callback(self.run_next)
|
+ self.event.io_loop.spawn_callback(self.run_next)
|
||||||
|
|
||||||
+ @tornado.gen.coroutine
|
+ @tornado.gen.coroutine
|
||||||
def end_batch(self):
|
def end_batch(self):
|
||||||
left = self.minions.symmetric_difference(self.done_minions.union(self.timedout_minions))
|
left = self.minions.symmetric_difference(
|
||||||
|
self.done_minions.union(self.timedout_minions)
|
||||||
|
)
|
||||||
- if not left:
|
- if not left:
|
||||||
+ if not left and not self.ended:
|
+ if not left and not self.ended:
|
||||||
+ self.ended = True
|
+ self.ended = True
|
||||||
data = {
|
data = {
|
||||||
"available_minions": self.minions,
|
"available_minions": self.minions,
|
||||||
"down_minions": self.targeted_minions.difference(self.minions),
|
"down_minions": self.targeted_minions.difference(self.minions),
|
||||||
@@ -220,20 +225,26 @@ class BatchAsync(object):
|
@@ -229,20 +234,26 @@ class BatchAsync:
|
||||||
for (pattern, label) in self.patterns:
|
for (pattern, label) in self.patterns:
|
||||||
if label in ["ping_return", "batch_run"]:
|
if label in ["ping_return", "batch_run"]:
|
||||||
self.event.unsubscribe(pattern, match_type='glob')
|
self.event.unsubscribe(pattern, match_type="glob")
|
||||||
+ del self
|
+ del self
|
||||||
+ gc.collect()
|
+ gc.collect()
|
||||||
+ yield
|
+ yield
|
||||||
@ -161,14 +174,16 @@ index 8a67331102..2bb50459c8 100644
|
|||||||
- yield self.local.run_job_async(
|
- yield self.local.run_job_async(
|
||||||
+ ret = yield self.local.run_job_async(
|
+ ret = yield self.local.run_job_async(
|
||||||
next_batch,
|
next_batch,
|
||||||
self.opts['fun'],
|
self.opts["fun"],
|
||||||
self.opts['arg'],
|
self.opts["arg"],
|
||||||
@@ -244,11 +255,17 @@ class BatchAsync(object):
|
@@ -254,13 +265,17 @@ class BatchAsync:
|
||||||
jid=self.batch_jid,
|
metadata=self.metadata,
|
||||||
metadata=self.metadata)
|
)
|
||||||
|
|
||||||
- self.event.io_loop.call_later(self.opts['timeout'], self.find_job, set(next_batch))
|
- self.event.io_loop.call_later(
|
||||||
+ yield tornado.gen.sleep(self.opts['timeout'])
|
- self.opts["timeout"], self.find_job, set(next_batch)
|
||||||
|
- )
|
||||||
|
+ yield tornado.gen.sleep(self.opts["timeout"])
|
||||||
+ self.event.io_loop.spawn_callback(self.find_job, set(next_batch))
|
+ self.event.io_loop.spawn_callback(self.find_job, set(next_batch))
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
log.error("Error in scheduling next batch: %s", ex)
|
log.error("Error in scheduling next batch: %s", ex)
|
||||||
@ -185,6 +200,6 @@ index 8a67331102..2bb50459c8 100644
|
|||||||
+ self.ioloop = None
|
+ self.ioloop = None
|
||||||
+ gc.collect()
|
+ gc.collect()
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From 512b189808ea0d7b333587689d7e7eb52d16b189 Mon Sep 17 00:00:00 2001
|
From 3c956a1cf1de17c5c49f0856051cabe2ffb4d0f2 Mon Sep 17 00:00:00 2001
|
||||||
From: Bo Maryniuk <bo@suse.de>
|
From: Bo Maryniuk <bo@suse.de>
|
||||||
Date: Tue, 29 Jan 2019 11:11:38 +0100
|
Date: Tue, 29 Jan 2019 11:11:38 +0100
|
||||||
Subject: [PATCH] Include aliases in the fqdns grains
|
Subject: [PATCH] Include aliases in the fqdns grains
|
||||||
@ -15,54 +15,116 @@ Add UT for fqdns aliases
|
|||||||
|
|
||||||
Leverage cached interfaces, if any.
|
Leverage cached interfaces, if any.
|
||||||
---
|
---
|
||||||
salt/grains/core.py | 14 ++++++--------
|
salt/grains/core.py | 69 +++++++++++++++++++++-----------
|
||||||
salt/utils/network.py | 12 ++++++++++++
|
salt/utils/network.py | 16 ++++++++
|
||||||
tests/unit/grains/test_core.py | 28 +++++++++++++++++++++++++---
|
tests/unit/grains/test_core.py | 45 ++++++++++++++++++---
|
||||||
tests/unit/utils/test_network.py | 24 ++++++++++++++++++++++++
|
tests/unit/utils/test_network.py | 37 +++++++++++++++++
|
||||||
4 files changed, 67 insertions(+), 11 deletions(-)
|
4 files changed, 138 insertions(+), 29 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/grains/core.py b/salt/grains/core.py
|
diff --git a/salt/grains/core.py b/salt/grains/core.py
|
||||||
index 7b7e328520..309e4c9c4a 100644
|
index bc3cf129cd..006878f806 100644
|
||||||
--- a/salt/grains/core.py
|
--- a/salt/grains/core.py
|
||||||
+++ b/salt/grains/core.py
|
+++ b/salt/grains/core.py
|
||||||
@@ -2275,14 +2275,13 @@ def fqdns():
|
@@ -1733,29 +1733,31 @@ def _parse_cpe_name(cpe):
|
||||||
grains = {}
|
|
||||||
fqdns = set()
|
|
||||||
|
|
||||||
- addresses = salt.utils.network.ip_addrs(include_loopback=False,
|
|
||||||
- interface_data=_INTERFACES)
|
def _parse_cpe_name(cpe):
|
||||||
- addresses.extend(salt.utils.network.ip_addrs6(include_loopback=False,
|
- '''
|
||||||
- interface_data=_INTERFACES))
|
+ """
|
||||||
- err_message = 'An exception occurred resolving address \'%s\': %s'
|
Parse CPE_NAME data from the os-release
|
||||||
+ addresses = salt.utils.network.ip_addrs(include_loopback=False, interface_data=_get_interfaces())
|
|
||||||
+ addresses.extend(salt.utils.network.ip_addrs6(include_loopback=False, interface_data=_get_interfaces()))
|
Info: https://csrc.nist.gov/projects/security-content-automation-protocol/scap-specifications/cpe
|
||||||
+ err_message = 'Exception during resolving address: %s'
|
|
||||||
for ip in addresses:
|
:param cpe:
|
||||||
try:
|
:return:
|
||||||
- fqdns.add(socket.getfqdn(socket.gethostbyaddr(ip)[0]))
|
- '''
|
||||||
|
+ """
|
||||||
|
part = {
|
||||||
|
- 'o': 'operating system',
|
||||||
|
- 'h': 'hardware',
|
||||||
|
- 'a': 'application',
|
||||||
|
+ "o": "operating system",
|
||||||
|
+ "h": "hardware",
|
||||||
|
+ "a": "application",
|
||||||
|
}
|
||||||
|
ret = {}
|
||||||
|
- cpe = (cpe or '').split(':')
|
||||||
|
- if len(cpe) > 4 and cpe[0] == 'cpe':
|
||||||
|
- if cpe[1].startswith('/'): # WFN to URI
|
||||||
|
- ret['vendor'], ret['product'], ret['version'] = cpe[2:5]
|
||||||
|
- ret['phase'] = cpe[5] if len(cpe) > 5 else None
|
||||||
|
- ret['part'] = part.get(cpe[1][1:])
|
||||||
|
- elif len(cpe) == 13 and cpe[1] == '2.3': # WFN to a string
|
||||||
|
- ret['vendor'], ret['product'], ret['version'], ret['phase'] = [x if x != '*' else None for x in cpe[3:7]]
|
||||||
|
- ret['part'] = part.get(cpe[2])
|
||||||
|
+ cpe = (cpe or "").split(":")
|
||||||
|
+ if len(cpe) > 4 and cpe[0] == "cpe":
|
||||||
|
+ if cpe[1].startswith("/"): # WFN to URI
|
||||||
|
+ ret["vendor"], ret["product"], ret["version"] = cpe[2:5]
|
||||||
|
+ ret["phase"] = cpe[5] if len(cpe) > 5 else None
|
||||||
|
+ ret["part"] = part.get(cpe[1][1:])
|
||||||
|
+ elif len(cpe) == 13 and cpe[1] == "2.3": # WFN to a string
|
||||||
|
+ ret["vendor"], ret["product"], ret["version"], ret["phase"] = [
|
||||||
|
+ x if x != "*" else None for x in cpe[3:7]
|
||||||
|
+ ]
|
||||||
|
+ ret["part"] = part.get(cpe[2])
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
@@ -2396,15 +2398,36 @@ def fqdns():
|
||||||
|
"""
|
||||||
|
# Provides:
|
||||||
|
# fqdns
|
||||||
|
- opt = {"fqdns": []}
|
||||||
|
- if __opts__.get(
|
||||||
|
- "enable_fqdns_grains",
|
||||||
|
- False
|
||||||
|
- if salt.utils.platform.is_windows() or salt.utils.platform.is_proxy()
|
||||||
|
- else True,
|
||||||
|
- ):
|
||||||
|
- opt = __salt__["network.fqdns"]()
|
||||||
|
- return opt
|
||||||
|
+
|
||||||
|
+ grains = {}
|
||||||
|
+ fqdns = set()
|
||||||
|
+
|
||||||
|
+ addresses = salt.utils.network.ip_addrs(
|
||||||
|
+ include_loopback=False, interface_data=_get_interfaces()
|
||||||
|
+ )
|
||||||
|
+ addresses.extend(
|
||||||
|
+ salt.utils.network.ip_addrs6(
|
||||||
|
+ include_loopback=False, interface_data=_get_interfaces()
|
||||||
|
+ )
|
||||||
|
+ )
|
||||||
|
+ err_message = "Exception during resolving address: %s"
|
||||||
|
+ for ip in addresses:
|
||||||
|
+ try:
|
||||||
+ name, aliaslist, addresslist = socket.gethostbyaddr(ip)
|
+ name, aliaslist, addresslist = socket.gethostbyaddr(ip)
|
||||||
+ fqdns.update([socket.getfqdn(name)] + [als for als in aliaslist if salt.utils.network.is_fqdn(als)])
|
+ fqdns.update(
|
||||||
except socket.herror as err:
|
+ [socket.getfqdn(name)]
|
||||||
if err.errno in (0, HOST_NOT_FOUND, NO_DATA):
|
+ + [als for als in aliaslist if salt.utils.network.is_fqdn(als)]
|
||||||
# No FQDN for this IP address, so we don't need to know this all the time.
|
+ )
|
||||||
@@ -2292,8 +2291,7 @@ def fqdns():
|
+ except socket.herror as err:
|
||||||
except (socket.error, socket.gaierror, socket.timeout) as err:
|
+ if err.errno in (0, HOST_NOT_FOUND, NO_DATA):
|
||||||
log.error(err_message, ip, err)
|
+ # No FQDN for this IP address, so we don't need to know this all the time.
|
||||||
|
+ log.debug("Unable to resolve address %s: %s", ip, err)
|
||||||
- grains['fqdns'] = sorted(list(fqdns))
|
+ else:
|
||||||
- return grains
|
+ log.error(err_message, ip, err)
|
||||||
|
+ except (OSError, socket.gaierror, socket.timeout) as err:
|
||||||
|
+ log.error(err_message, ip, err)
|
||||||
|
+
|
||||||
+ return {"fqdns": sorted(list(fqdns))}
|
+ return {"fqdns": sorted(list(fqdns))}
|
||||||
|
|
||||||
|
|
||||||
def ip_fqdn():
|
def ip_fqdn():
|
||||||
diff --git a/salt/utils/network.py b/salt/utils/network.py
|
diff --git a/salt/utils/network.py b/salt/utils/network.py
|
||||||
index 906d1cb3bc..2ae2e213b7 100644
|
index b3e8db3886..dd7fceb91a 100644
|
||||||
--- a/salt/utils/network.py
|
--- a/salt/utils/network.py
|
||||||
+++ b/salt/utils/network.py
|
+++ b/salt/utils/network.py
|
||||||
@@ -1958,3 +1958,15 @@ def parse_host_port(host_port):
|
@@ -2208,3 +2208,19 @@ def filter_by_networks(values, networks):
|
||||||
raise ValueError('bad hostname: "{}"'.format(host))
|
raise ValueError("Do not know how to filter a {}".format(type(values)))
|
||||||
|
else:
|
||||||
return host, port
|
return values
|
||||||
+
|
+
|
||||||
+
|
+
|
||||||
+def is_fqdn(hostname):
|
+def is_fqdn(hostname):
|
||||||
@ -74,42 +136,63 @@ index 906d1cb3bc..2ae2e213b7 100644
|
|||||||
+ """
|
+ """
|
||||||
+
|
+
|
||||||
+ compliant = re.compile(r"(?!-)[A-Z\d\-\_]{1,63}(?<!-)$", re.IGNORECASE)
|
+ compliant = re.compile(r"(?!-)[A-Z\d\-\_]{1,63}(?<!-)$", re.IGNORECASE)
|
||||||
+ return "." in hostname and len(hostname) < 0xff and all(compliant.match(x) for x in hostname.rstrip(".").split("."))
|
+ return (
|
||||||
|
+ "." in hostname
|
||||||
|
+ and len(hostname) < 0xFF
|
||||||
|
+ and all(compliant.match(x) for x in hostname.rstrip(".").split("."))
|
||||||
|
+ )
|
||||||
diff --git a/tests/unit/grains/test_core.py b/tests/unit/grains/test_core.py
|
diff --git a/tests/unit/grains/test_core.py b/tests/unit/grains/test_core.py
|
||||||
index c40595eb3f..ac03b57226 100644
|
index 7dbf34deac..d760e57a54 100644
|
||||||
--- a/tests/unit/grains/test_core.py
|
--- a/tests/unit/grains/test_core.py
|
||||||
+++ b/tests/unit/grains/test_core.py
|
+++ b/tests/unit/grains/test_core.py
|
||||||
@@ -1046,9 +1046,9 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -1367,12 +1367,11 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
ret = {'fqdns': ['bluesniff.foo.bar', 'foo.bar.baz', 'rinzler.evil-corp.com']}
|
("bluesniff.foo.bar", [], ["fe80::a8b2:93ff:dead:beef"]),
|
||||||
with patch.object(socket, 'gethostbyaddr', side_effect=reverse_resolv_mock):
|
]
|
||||||
fqdns = core.fqdns()
|
ret = {"fqdns": ["bluesniff.foo.bar", "foo.bar.baz", "rinzler.evil-corp.com"]}
|
||||||
- self.assertIn('fqdns', fqdns)
|
- with patch.dict(core.__salt__, {"network.fqdns": salt.modules.network.fqdns}):
|
||||||
- self.assertEqual(len(fqdns['fqdns']), len(ret['fqdns']))
|
- with patch.object(socket, "gethostbyaddr", side_effect=reverse_resolv_mock):
|
||||||
- self.assertEqual(set(fqdns['fqdns']), set(ret['fqdns']))
|
- fqdns = core.fqdns()
|
||||||
|
- assert "fqdns" in fqdns
|
||||||
|
- assert len(fqdns["fqdns"]) == len(ret["fqdns"])
|
||||||
|
- assert set(fqdns["fqdns"]) == set(ret["fqdns"])
|
||||||
|
+ with patch.object(socket, "gethostbyaddr", side_effect=reverse_resolv_mock):
|
||||||
|
+ fqdns = core.fqdns()
|
||||||
+ assert "fqdns" in fqdns
|
+ assert "fqdns" in fqdns
|
||||||
+ assert len(fqdns['fqdns']) == len(ret['fqdns'])
|
+ assert len(fqdns["fqdns"]) == len(ret["fqdns"])
|
||||||
+ assert set(fqdns['fqdns']) == set(ret['fqdns'])
|
+ assert set(fqdns["fqdns"]) == set(ret["fqdns"])
|
||||||
|
|
||||||
@skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
|
@skipIf(not salt.utils.platform.is_linux(), "System is not Linux")
|
||||||
@patch('salt.utils.network.ip_addrs', MagicMock(return_value=['1.2.3.4']))
|
@patch("salt.utils.network.ip_addrs", MagicMock(return_value=["1.2.3.4"]))
|
||||||
@@ -1081,6 +1081,28 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -1413,6 +1412,40 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
mock_log.debug.assert_not_called()
|
mock_log.debug.assert_called_once()
|
||||||
mock_log.error.assert_called_once()
|
mock_log.error.assert_called()
|
||||||
|
|
||||||
+ @patch.object(salt.utils.platform, 'is_windows', MagicMock(return_value=False))
|
+ @patch.object(salt.utils.platform, "is_windows", MagicMock(return_value=False))
|
||||||
+ @patch('salt.utils.network.ip_addrs', MagicMock(return_value=['1.2.3.4', '5.6.7.8']))
|
+ @patch(
|
||||||
+ @patch('salt.utils.network.ip_addrs6',
|
+ "salt.utils.network.ip_addrs", MagicMock(return_value=["1.2.3.4", "5.6.7.8"])
|
||||||
+ MagicMock(return_value=['fe80::a8b2:93ff:fe00:0', 'fe80::a8b2:93ff:dead:beef']))
|
+ )
|
||||||
+ @patch('salt.utils.network.socket.getfqdn', MagicMock(side_effect=lambda v: v)) # Just pass-through
|
+ @patch(
|
||||||
|
+ "salt.utils.network.ip_addrs6",
|
||||||
|
+ MagicMock(return_value=["fe80::a8b2:93ff:fe00:0", "fe80::a8b2:93ff:dead:beef"]),
|
||||||
|
+ )
|
||||||
|
+ @patch(
|
||||||
|
+ "salt.utils.network.socket.getfqdn", MagicMock(side_effect=lambda v: v)
|
||||||
|
+ ) # Just pass-through
|
||||||
+ def test_fqdns_aliases(self):
|
+ def test_fqdns_aliases(self):
|
||||||
+ '''
|
+ """
|
||||||
+ FQDNs aliases
|
+ FQDNs aliases
|
||||||
+ '''
|
+ """
|
||||||
+ reverse_resolv_mock = [('foo.bar.baz', ["throwmeaway", "this.is.valid.alias"], ['1.2.3.4']),
|
+ reverse_resolv_mock = [
|
||||||
+ ('rinzler.evil-corp.com', ["false-hostname", "badaliass"], ['5.6.7.8']),
|
+ ("foo.bar.baz", ["throwmeaway", "this.is.valid.alias"], ["1.2.3.4"]),
|
||||||
+ ('foo.bar.baz', [], ['fe80::a8b2:93ff:fe00:0']),
|
+ ("rinzler.evil-corp.com", ["false-hostname", "badaliass"], ["5.6.7.8"]),
|
||||||
+ ('bluesniff.foo.bar', ["alias.bluesniff.foo.bar"], ['fe80::a8b2:93ff:dead:beef'])]
|
+ ("foo.bar.baz", [], ["fe80::a8b2:93ff:fe00:0"]),
|
||||||
+ with patch.object(socket, 'gethostbyaddr', side_effect=reverse_resolv_mock):
|
+ (
|
||||||
|
+ "bluesniff.foo.bar",
|
||||||
|
+ ["alias.bluesniff.foo.bar"],
|
||||||
|
+ ["fe80::a8b2:93ff:dead:beef"],
|
||||||
|
+ ),
|
||||||
|
+ ]
|
||||||
|
+ with patch.object(socket, "gethostbyaddr", side_effect=reverse_resolv_mock):
|
||||||
+ fqdns = core.fqdns()
|
+ fqdns = core.fqdns()
|
||||||
+ assert "fqdns" in fqdns
|
+ assert "fqdns" in fqdns
|
||||||
+ for alias in ["this.is.valid.alias", "alias.bluesniff.foo.bar"]:
|
+ for alias in ["this.is.valid.alias", "alias.bluesniff.foo.bar"]:
|
||||||
@ -119,21 +202,21 @@ index c40595eb3f..ac03b57226 100644
|
|||||||
+ assert alias not in fqdns["fqdns"]
|
+ assert alias not in fqdns["fqdns"]
|
||||||
+
|
+
|
||||||
def test_core_virtual(self):
|
def test_core_virtual(self):
|
||||||
'''
|
"""
|
||||||
test virtual grain with cmd virt-what
|
test virtual grain with cmd virt-what
|
||||||
diff --git a/tests/unit/utils/test_network.py b/tests/unit/utils/test_network.py
|
diff --git a/tests/unit/utils/test_network.py b/tests/unit/utils/test_network.py
|
||||||
index 7dcca0166e..74479b0cae 100644
|
index 779fc0fc34..9a37a94d8f 100644
|
||||||
--- a/tests/unit/utils/test_network.py
|
--- a/tests/unit/utils/test_network.py
|
||||||
+++ b/tests/unit/utils/test_network.py
|
+++ b/tests/unit/utils/test_network.py
|
||||||
@@ -701,3 +701,27 @@ class NetworkTestCase(TestCase):
|
@@ -1274,3 +1274,40 @@ class NetworkTestCase(TestCase):
|
||||||
# An exception is raised if unicode is passed to socket.getfqdn
|
),
|
||||||
minion_id = network.generate_minion_id()
|
):
|
||||||
assert minion_id != '', minion_id
|
self.assertEqual(network.get_fqhostname(), host)
|
||||||
+
|
+
|
||||||
+ def test_netlink_tool_remote_on(self):
|
+ def test_netlink_tool_remote_on(self):
|
||||||
+ with patch('subprocess.check_output', return_value=NETLINK_SS):
|
+ with patch("subprocess.check_output", return_value=NETLINK_SS):
|
||||||
+ remotes = network._netlink_tool_remote_on('4505', 'remote')
|
+ remotes = network._netlink_tool_remote_on("4505", "remote")
|
||||||
+ self.assertEqual(remotes, set(['127.0.0.1', '::ffff:1.2.3.4']))
|
+ self.assertEqual(remotes, {"127.0.0.1", "::ffff:1.2.3.4"})
|
||||||
+
|
+
|
||||||
+ def test_is_fqdn(self):
|
+ def test_is_fqdn(self):
|
||||||
+ """
|
+ """
|
||||||
@ -141,8 +224,16 @@ index 7dcca0166e..74479b0cae 100644
|
|||||||
+
|
+
|
||||||
+ :return: None
|
+ :return: None
|
||||||
+ """
|
+ """
|
||||||
+ for fqdn in ["host.domain.com", "something.with.the.dots.still.ok", "UPPERCASE.ALSO.SHOULD.WORK",
|
+ for fqdn in [
|
||||||
+ "MiXeD.CaSe.AcCePtAbLe", "123.host.com", "host123.com", "some_underscore.com", "host-here.com"]:
|
+ "host.domain.com",
|
||||||
|
+ "something.with.the.dots.still.ok",
|
||||||
|
+ "UPPERCASE.ALSO.SHOULD.WORK",
|
||||||
|
+ "MiXeD.CaSe.AcCePtAbLe",
|
||||||
|
+ "123.host.com",
|
||||||
|
+ "host123.com",
|
||||||
|
+ "some_underscore.com",
|
||||||
|
+ "host-here.com",
|
||||||
|
+ ]:
|
||||||
+ assert network.is_fqdn(fqdn)
|
+ assert network.is_fqdn(fqdn)
|
||||||
+
|
+
|
||||||
+ def test_is_not_fqdn(self):
|
+ def test_is_not_fqdn(self):
|
||||||
@ -151,9 +242,14 @@ index 7dcca0166e..74479b0cae 100644
|
|||||||
+
|
+
|
||||||
+ :return: None
|
+ :return: None
|
||||||
+ """
|
+ """
|
||||||
+ for fqdn in ["hostname", "/some/path", "$variable.here", "verylonghostname.{}".format("domain" * 45)]:
|
+ for fqdn in [
|
||||||
|
+ "hostname",
|
||||||
|
+ "/some/path",
|
||||||
|
+ "$variable.here",
|
||||||
|
+ "verylonghostname.{}".format("domain" * 45),
|
||||||
|
+ ]:
|
||||||
+ assert not network.is_fqdn(fqdn)
|
+ assert not network.is_fqdn(fqdn)
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From 8275c229fcca0e43513ea680e48cbf6263247b41 Mon Sep 17 00:00:00 2001
|
From 0ef6eed4f5e120a584843c33272066ba477feb3f Mon Sep 17 00:00:00 2001
|
||||||
From: Jochen Breuer <brejoc@gmail.com>
|
From: Jochen Breuer <brejoc@gmail.com>
|
||||||
Date: Tue, 19 May 2020 10:34:35 +0200
|
Date: Tue, 19 May 2020 10:34:35 +0200
|
||||||
Subject: [PATCH] info_installed works without status attr now
|
Subject: [PATCH] info_installed works without status attr now
|
||||||
@ -8,39 +8,39 @@ detect if a package was installed or not. Now info_installed adds the
|
|||||||
'status' for the 'lowpkg.info' request again.
|
'status' for the 'lowpkg.info' request again.
|
||||||
---
|
---
|
||||||
salt/modules/aptpkg.py | 9 +++++++++
|
salt/modules/aptpkg.py | 9 +++++++++
|
||||||
tests/unit/modules/test_aptpkg.py | 17 +++++++++++++++++
|
tests/unit/modules/test_aptpkg.py | 20 ++++++++++++++++++++
|
||||||
2 files changed, 26 insertions(+)
|
2 files changed, 29 insertions(+)
|
||||||
|
|
||||||
diff --git a/salt/modules/aptpkg.py b/salt/modules/aptpkg.py
|
diff --git a/salt/modules/aptpkg.py b/salt/modules/aptpkg.py
|
||||||
index 2835d32263..765d69aff2 100644
|
index db0480b45d..e4a9872aad 100644
|
||||||
--- a/salt/modules/aptpkg.py
|
--- a/salt/modules/aptpkg.py
|
||||||
+++ b/salt/modules/aptpkg.py
|
+++ b/salt/modules/aptpkg.py
|
||||||
@@ -2867,6 +2867,15 @@ def info_installed(*names, **kwargs):
|
@@ -2923,6 +2923,15 @@ def info_installed(*names, **kwargs):
|
||||||
failhard = kwargs.pop('failhard', True)
|
failhard = kwargs.pop("failhard", True)
|
||||||
kwargs.pop('errors', None) # Only for compatibility with RPM
|
kwargs.pop("errors", None) # Only for compatibility with RPM
|
||||||
attr = kwargs.pop('attr', None) # Package attributes to return
|
attr = kwargs.pop("attr", None) # Package attributes to return
|
||||||
+
|
+
|
||||||
+ # status is needed to see if a package is installed. So we have to add it,
|
+ # status is needed to see if a package is installed. So we have to add it,
|
||||||
+ # even if it's excluded via attr parameter. Otherwise all packages are
|
+ # even if it's excluded via attr parameter. Otherwise all packages are
|
||||||
+ # returned.
|
+ # returned.
|
||||||
+ if attr:
|
+ if attr:
|
||||||
+ attr_list = set(attr.split(','))
|
+ attr_list = set(attr.split(","))
|
||||||
+ attr_list.add('status')
|
+ attr_list.add("status")
|
||||||
+ attr = ','.join(attr_list)
|
+ attr = ",".join(attr_list)
|
||||||
+
|
+
|
||||||
all_versions = kwargs.pop('all_versions', False) # This is for backward compatible structure only
|
all_versions = kwargs.pop(
|
||||||
|
"all_versions", False
|
||||||
if kwargs:
|
) # This is for backward compatible structure only
|
||||||
diff --git a/tests/unit/modules/test_aptpkg.py b/tests/unit/modules/test_aptpkg.py
|
diff --git a/tests/unit/modules/test_aptpkg.py b/tests/unit/modules/test_aptpkg.py
|
||||||
index ba1d874e69..b0193aeaf7 100644
|
index 3c9744e224..51dfce29eb 100644
|
||||||
--- a/tests/unit/modules/test_aptpkg.py
|
--- a/tests/unit/modules/test_aptpkg.py
|
||||||
+++ b/tests/unit/modules/test_aptpkg.py
|
+++ b/tests/unit/modules/test_aptpkg.py
|
||||||
@@ -257,6 +257,23 @@ class AptPkgTestCase(TestCase, LoaderModuleMockMixin):
|
@@ -297,6 +297,26 @@ class AptPkgTestCase(TestCase, LoaderModuleMockMixin):
|
||||||
self.assertEqual(aptpkg.info_installed('wget'), installed)
|
self.assertEqual(aptpkg.info_installed("wget"), installed)
|
||||||
self.assertEqual(len(aptpkg.info_installed()), 1)
|
self.assertEqual(len(aptpkg.info_installed()), 1)
|
||||||
|
|
||||||
+ def test_info_installed_attr_without_status(self):
|
+ def test_info_installed_attr_without_status(self):
|
||||||
+ '''
|
+ """
|
||||||
+ Test info_installed 'attr' for inclusion of 'status' attribute.
|
+ Test info_installed 'attr' for inclusion of 'status' attribute.
|
||||||
+
|
+
|
||||||
+ Since info_installed should only return installed packages, we need to
|
+ Since info_installed should only return installed packages, we need to
|
||||||
@ -49,17 +49,20 @@ index ba1d874e69..b0193aeaf7 100644
|
|||||||
+ to check if the package is installed and would return everything.
|
+ to check if the package is installed and would return everything.
|
||||||
+
|
+
|
||||||
+ :return:
|
+ :return:
|
||||||
+ '''
|
+ """
|
||||||
+ with patch('salt.modules.aptpkg.__salt__', {'lowpkg.info': MagicMock(return_value=LOWPKG_INFO)}) as wget_lowpkg:
|
+ with patch(
|
||||||
+ ret = aptpkg.info_installed('wget', attr='version')
|
+ "salt.modules.aptpkg.__salt__",
|
||||||
+ calls = wget_lowpkg['lowpkg.info'].call_args_list.pop()
|
+ {"lowpkg.info": MagicMock(return_value=LOWPKG_INFO)},
|
||||||
+ self.assertIn('status', calls.kwargs['attr'])
|
+ ) as wget_lowpkg:
|
||||||
+ self.assertIn('version', calls.kwargs['attr'])
|
+ ret = aptpkg.info_installed("wget", attr="version")
|
||||||
|
+ calls = wget_lowpkg["lowpkg.info"].call_args_list.pop()
|
||||||
|
+ self.assertIn("status", calls.kwargs["attr"])
|
||||||
|
+ self.assertIn("version", calls.kwargs["attr"])
|
||||||
+
|
+
|
||||||
@patch('salt.modules.aptpkg.__salt__', {'lowpkg.info': MagicMock(return_value=LOWPKG_INFO)})
|
@patch(
|
||||||
def test_info_installed_attr(self):
|
"salt.modules.aptpkg.__salt__",
|
||||||
'''
|
{"lowpkg.info": MagicMock(return_value=LOWPKG_INFO)},
|
||||||
--
|
--
|
||||||
2.27.0
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,18 +1,23 @@
|
|||||||
From c750e854c637e405a788f91d5b9a7bd1a0a6edfd Mon Sep 17 00:00:00 2001
|
From bb2070d4f4e8fbb5a963c521d61feb7419abdec1 Mon Sep 17 00:00:00 2001
|
||||||
From: ed lane <ed.lane.0@gmail.com>
|
From: ed lane <ed.lane.0@gmail.com>
|
||||||
Date: Thu, 30 Aug 2018 06:07:08 -0600
|
Date: Thu, 30 Aug 2018 06:07:08 -0600
|
||||||
Subject: [PATCH] Integration of MSI authentication with azurearm cloud
|
Subject: [PATCH] Integration of MSI authentication with azurearm cloud
|
||||||
driver (#105)
|
driver (#105)
|
||||||
|
|
||||||
---
|
---
|
||||||
salt/cloud/clouds/azurearm.py | 7 ++++++-
|
salt/cloud/clouds/azurearm.py | 98 +++++++++++++++--------------------
|
||||||
1 file changed, 6 insertions(+), 1 deletion(-)
|
1 file changed, 43 insertions(+), 55 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/cloud/clouds/azurearm.py b/salt/cloud/clouds/azurearm.py
|
diff --git a/salt/cloud/clouds/azurearm.py b/salt/cloud/clouds/azurearm.py
|
||||||
index 047fdac0a9..2c1fa04ae8 100644
|
index 54fc7b497b..8b9254cecb 100644
|
||||||
--- a/salt/cloud/clouds/azurearm.py
|
--- a/salt/cloud/clouds/azurearm.py
|
||||||
+++ b/salt/cloud/clouds/azurearm.py
|
+++ b/salt/cloud/clouds/azurearm.py
|
||||||
@@ -58,6 +58,9 @@ The Azure ARM cloud module is used to control access to Microsoft Azure Resource
|
@@ -1,4 +1,3 @@
|
||||||
|
-# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Azure ARM Cloud Module
|
||||||
|
======================
|
||||||
|
@@ -61,6 +60,9 @@ The Azure ARM cloud module is used to control access to Microsoft Azure Resource
|
||||||
virtual machine type will be "Windows". Only set this parameter on profiles which install Windows operating systems.
|
virtual machine type will be "Windows". Only set this parameter on profiles which install Windows operating systems.
|
||||||
|
|
||||||
|
|
||||||
@ -22,25 +27,361 @@ index 047fdac0a9..2c1fa04ae8 100644
|
|||||||
Example ``/etc/salt/cloud.providers`` or
|
Example ``/etc/salt/cloud.providers`` or
|
||||||
``/etc/salt/cloud.providers.d/azure.conf`` configuration:
|
``/etc/salt/cloud.providers.d/azure.conf`` configuration:
|
||||||
|
|
||||||
@@ -258,7 +261,8 @@ def get_configured_provider():
|
@@ -91,7 +93,6 @@ Example ``/etc/salt/cloud.providers`` or
|
||||||
provider = __is_provider_configured(
|
|
||||||
__opts__,
|
|
||||||
__active_provider_name__ or __virtualname__,
|
# pylint: disable=wrong-import-position,wrong-import-order
|
||||||
- ('subscription_id', 'username', 'password')
|
-from __future__ import absolute_import, print_function, unicode_literals
|
||||||
+ required_keys=('subscription_id', 'username', 'password'),
|
|
||||||
+ log_message=False
|
import importlib
|
||||||
|
import logging
|
||||||
|
@@ -121,7 +122,6 @@ from salt.exceptions import (
|
||||||
|
# Salt libs
|
||||||
|
from salt.ext import six
|
||||||
|
|
||||||
|
-# Import 3rd-party libs
|
||||||
|
HAS_LIBS = False
|
||||||
|
try:
|
||||||
|
import azure.mgmt.compute.models as compute_models
|
||||||
|
@@ -179,7 +179,7 @@ def get_api_versions(call=None, kwargs=None): # pylint: disable=unused-argument
|
||||||
)
|
)
|
||||||
|
|
||||||
return provider
|
for resource in provider_query.resource_types:
|
||||||
@@ -301,6 +305,7 @@ def get_conn(client_type):
|
- if six.text_type(resource.resource_type) == kwargs["resource_type"]:
|
||||||
|
+ if str(resource.resource_type) == kwargs["resource_type"]:
|
||||||
|
resource_dict = resource.as_dict()
|
||||||
|
api_versions = resource_dict["api_versions"]
|
||||||
|
except CloudError as exc:
|
||||||
|
@@ -263,6 +263,7 @@ def get_conn(client_type):
|
||||||
)
|
)
|
||||||
|
|
||||||
if tenant is not None:
|
if tenant is not None:
|
||||||
+ # using Service Principle style authentication...
|
+ # using Service Principle style authentication...
|
||||||
client_id = config.get_cloud_config_value(
|
client_id = config.get_cloud_config_value(
|
||||||
'client_id',
|
"client_id", get_configured_provider(), __opts__, search_global=False
|
||||||
get_configured_provider(), __opts__, search_global=False
|
)
|
||||||
|
@@ -319,7 +320,7 @@ def avail_locations(call=None):
|
||||||
|
)
|
||||||
|
locations = []
|
||||||
|
for resource in provider_query.resource_types:
|
||||||
|
- if six.text_type(resource.resource_type) == "virtualMachines":
|
||||||
|
+ if str(resource.resource_type) == "virtualMachines":
|
||||||
|
resource_dict = resource.as_dict()
|
||||||
|
locations = resource_dict["locations"]
|
||||||
|
for location in locations:
|
||||||
|
@@ -399,7 +400,7 @@ def avail_images(call=None):
|
||||||
|
results = pool.map_async(_get_publisher_images, publishers)
|
||||||
|
results.wait()
|
||||||
|
|
||||||
|
- ret = {k: v for result in results.get() for k, v in six.iteritems(result)}
|
||||||
|
+ ret = {k: v for result in results.get() for k, v in result.items()}
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
@@ -529,7 +530,7 @@ def list_nodes_full(call=None):
|
||||||
|
results = pool.map_async(_get_node_info, nodes)
|
||||||
|
results.wait()
|
||||||
|
|
||||||
|
- group_ret = {k: v for result in results.get() for k, v in six.iteritems(result)}
|
||||||
|
+ group_ret = {k: v for result in results.get() for k, v in result.items()}
|
||||||
|
ret.update(group_ret)
|
||||||
|
|
||||||
|
return ret
|
||||||
|
@@ -707,7 +708,7 @@ def create_network_interface(call=None, kwargs=None):
|
||||||
|
)
|
||||||
|
|
||||||
|
if kwargs.get("iface_name") is None:
|
||||||
|
- kwargs["iface_name"] = "{0}-iface0".format(vm_["name"])
|
||||||
|
+ kwargs["iface_name"] = "{}-iface0".format(vm_["name"])
|
||||||
|
|
||||||
|
try:
|
||||||
|
subnet_obj = netconn.subnets.get(
|
||||||
|
@@ -717,7 +718,7 @@ def create_network_interface(call=None, kwargs=None):
|
||||||
|
)
|
||||||
|
except CloudError as exc:
|
||||||
|
raise SaltCloudSystemExit(
|
||||||
|
- '{0} (Resource Group: "{1}", VNET: "{2}", Subnet: "{3}")'.format(
|
||||||
|
+ '{} (Resource Group: "{}", VNET: "{}", Subnet: "{}")'.format(
|
||||||
|
exc.message,
|
||||||
|
kwargs["network_resource_group"],
|
||||||
|
kwargs["network"],
|
||||||
|
@@ -740,11 +741,11 @@ def create_network_interface(call=None, kwargs=None):
|
||||||
|
)
|
||||||
|
pool_ids.append({"id": lbbep_data.as_dict()["id"]})
|
||||||
|
except CloudError as exc:
|
||||||
|
- log.error("There was a cloud error: %s", six.text_type(exc))
|
||||||
|
+ log.error("There was a cloud error: %s", str(exc))
|
||||||
|
except KeyError as exc:
|
||||||
|
log.error(
|
||||||
|
"There was an error getting the Backend Pool ID: %s",
|
||||||
|
- six.text_type(exc),
|
||||||
|
+ str(exc),
|
||||||
|
)
|
||||||
|
ip_kwargs["load_balancer_backend_address_pools"] = pool_ids
|
||||||
|
|
||||||
|
@@ -755,7 +756,7 @@ def create_network_interface(call=None, kwargs=None):
|
||||||
|
ip_kwargs["private_ip_allocation_method"] = IPAllocationMethod.dynamic
|
||||||
|
|
||||||
|
if kwargs.get("allocate_public_ip") is True:
|
||||||
|
- pub_ip_name = "{0}-ip".format(kwargs["iface_name"])
|
||||||
|
+ pub_ip_name = "{}-ip".format(kwargs["iface_name"])
|
||||||
|
poller = netconn.public_ip_addresses.create_or_update(
|
||||||
|
resource_group_name=kwargs["resource_group"],
|
||||||
|
public_ip_address_name=pub_ip_name,
|
||||||
|
@@ -773,11 +774,11 @@ def create_network_interface(call=None, kwargs=None):
|
||||||
|
)
|
||||||
|
if pub_ip_data.ip_address: # pylint: disable=no-member
|
||||||
|
ip_kwargs["public_ip_address"] = PublicIPAddress(
|
||||||
|
- id=six.text_type(pub_ip_data.id), # pylint: disable=no-member
|
||||||
|
+ id=str(pub_ip_data.id), # pylint: disable=no-member
|
||||||
|
)
|
||||||
|
ip_configurations = [
|
||||||
|
NetworkInterfaceIPConfiguration(
|
||||||
|
- name="{0}-ip".format(kwargs["iface_name"]),
|
||||||
|
+ name="{}-ip".format(kwargs["iface_name"]),
|
||||||
|
subnet=subnet_obj,
|
||||||
|
**ip_kwargs
|
||||||
|
)
|
||||||
|
@@ -790,7 +791,7 @@ def create_network_interface(call=None, kwargs=None):
|
||||||
|
raise ValueError("Timed out waiting for public IP Address.")
|
||||||
|
time.sleep(5)
|
||||||
|
else:
|
||||||
|
- priv_ip_name = "{0}-ip".format(kwargs["iface_name"])
|
||||||
|
+ priv_ip_name = "{}-ip".format(kwargs["iface_name"])
|
||||||
|
ip_configurations = [
|
||||||
|
NetworkInterfaceIPConfiguration(
|
||||||
|
name=priv_ip_name, subnet=subnet_obj, **ip_kwargs
|
||||||
|
@@ -900,7 +901,7 @@ def request_instance(vm_):
|
||||||
|
)
|
||||||
|
vm_["iface_id"] = iface_data["id"]
|
||||||
|
|
||||||
|
- disk_name = "{0}-vol0".format(vm_["name"])
|
||||||
|
+ disk_name = "{}-vol0".format(vm_["name"])
|
||||||
|
|
||||||
|
vm_username = config.get_cloud_config_value(
|
||||||
|
"ssh_username",
|
||||||
|
@@ -922,8 +923,8 @@ def request_instance(vm_):
|
||||||
|
ssh_publickeyfile_contents = spkc_.read()
|
||||||
|
except Exception as exc: # pylint: disable=broad-except
|
||||||
|
raise SaltCloudConfigError(
|
||||||
|
- "Failed to read ssh publickey file '{0}': "
|
||||||
|
- "{1}".format(ssh_publickeyfile, exc.args[-1])
|
||||||
|
+ "Failed to read ssh publickey file '{}': "
|
||||||
|
+ "{}".format(ssh_publickeyfile, exc.args[-1])
|
||||||
|
)
|
||||||
|
|
||||||
|
disable_password_authentication = config.get_cloud_config_value(
|
||||||
|
@@ -941,7 +942,7 @@ def request_instance(vm_):
|
||||||
|
if not win_installer and ssh_publickeyfile_contents is not None:
|
||||||
|
sshpublickey = SshPublicKey(
|
||||||
|
key_data=ssh_publickeyfile_contents,
|
||||||
|
- path="/home/{0}/.ssh/authorized_keys".format(vm_username),
|
||||||
|
+ path="/home/{}/.ssh/authorized_keys".format(vm_username),
|
||||||
|
)
|
||||||
|
sshconfiguration = SshConfiguration(public_keys=[sshpublickey],)
|
||||||
|
linuxconfiguration = LinuxConfiguration(
|
||||||
|
@@ -991,9 +992,9 @@ def request_instance(vm_):
|
||||||
|
availability_set = config.get_cloud_config_value(
|
||||||
|
"availability_set", vm_, __opts__, search_global=False, default=None
|
||||||
|
)
|
||||||
|
- if availability_set is not None and isinstance(availability_set, six.string_types):
|
||||||
|
+ if availability_set is not None and isinstance(availability_set, str):
|
||||||
|
availability_set = {
|
||||||
|
- "id": "/subscriptions/{0}/resourceGroups/{1}/providers/Microsoft.Compute/availabilitySets/{2}".format(
|
||||||
|
+ "id": "/subscriptions/{}/resourceGroups/{}/providers/Microsoft.Compute/availabilitySets/{}".format(
|
||||||
|
subscription_id, vm_["resource_group"], availability_set
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@@ -1004,7 +1005,7 @@ def request_instance(vm_):
|
||||||
|
|
||||||
|
storage_endpoint_suffix = cloud_env.suffixes.storage_endpoint
|
||||||
|
|
||||||
|
- if isinstance(vm_.get("volumes"), six.string_types):
|
||||||
|
+ if isinstance(vm_.get("volumes"), str):
|
||||||
|
volumes = salt.utils.yaml.safe_load(vm_["volumes"])
|
||||||
|
else:
|
||||||
|
volumes = vm_.get("volumes")
|
||||||
|
@@ -1018,16 +1019,14 @@ def request_instance(vm_):
|
||||||
|
lun = 0
|
||||||
|
luns = []
|
||||||
|
for volume in volumes:
|
||||||
|
- if isinstance(volume, six.string_types):
|
||||||
|
+ if isinstance(volume, str):
|
||||||
|
volume = {"name": volume}
|
||||||
|
|
||||||
|
volume.setdefault(
|
||||||
|
"name",
|
||||||
|
volume.get(
|
||||||
|
"name",
|
||||||
|
- volume.get(
|
||||||
|
- "name", "{0}-datadisk{1}".format(vm_["name"], six.text_type(lun))
|
||||||
|
- ),
|
||||||
|
+ volume.get("name", "{}-datadisk{}".format(vm_["name"], str(lun))),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
@@ -1050,7 +1049,7 @@ def request_instance(vm_):
|
||||||
|
del volume["media_link"]
|
||||||
|
elif volume.get("vhd") == "unmanaged":
|
||||||
|
volume["vhd"] = VirtualHardDisk(
|
||||||
|
- uri="https://{0}.blob.{1}/vhds/{2}-datadisk{3}.vhd".format(
|
||||||
|
+ uri="https://{}.blob.{}/vhds/{}-datadisk{}.vhd".format(
|
||||||
|
vm_["storage_account"],
|
||||||
|
storage_endpoint_suffix,
|
||||||
|
vm_["name"],
|
||||||
|
@@ -1090,7 +1089,7 @@ def request_instance(vm_):
|
||||||
|
create_option=DiskCreateOptionTypes.from_image,
|
||||||
|
name=disk_name,
|
||||||
|
vhd=VirtualHardDisk(
|
||||||
|
- uri="https://{0}.blob.{1}/vhds/{2}.vhd".format(
|
||||||
|
+ uri="https://{}.blob.{}/vhds/{}.vhd".format(
|
||||||
|
vm_["storage_account"], storage_endpoint_suffix, disk_name,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
@@ -1209,7 +1208,7 @@ def request_instance(vm_):
|
||||||
|
__utils__["cloud.fire_event"](
|
||||||
|
"event",
|
||||||
|
"requesting instance",
|
||||||
|
- "salt/cloud/{0}/requesting".format(vm_["name"]),
|
||||||
|
+ "salt/cloud/{}/requesting".format(vm_["name"]),
|
||||||
|
args=__utils__["cloud.filter_event"](
|
||||||
|
"requesting", vm_, ["name", "profile", "provider", "driver"]
|
||||||
|
),
|
||||||
|
@@ -1260,7 +1259,7 @@ def create(vm_):
|
||||||
|
__utils__["cloud.fire_event"](
|
||||||
|
"event",
|
||||||
|
"starting create",
|
||||||
|
- "salt/cloud/{0}/creating".format(vm_["name"]),
|
||||||
|
+ "salt/cloud/{}/creating".format(vm_["name"]),
|
||||||
|
args=__utils__["cloud.filter_event"](
|
||||||
|
"creating", vm_, ["name", "profile", "provider", "driver"]
|
||||||
|
),
|
||||||
|
@@ -1278,9 +1277,7 @@ def create(vm_):
|
||||||
|
vm_request = request_instance(vm_=vm_)
|
||||||
|
|
||||||
|
if not vm_request or "error" in vm_request:
|
||||||
|
- err_message = "Error creating VM {0}! ({1})".format(
|
||||||
|
- vm_["name"], six.text_type(vm_request)
|
||||||
|
- )
|
||||||
|
+ err_message = "Error creating VM {}! ({})".format(vm_["name"], str(vm_request))
|
||||||
|
log.error(err_message)
|
||||||
|
raise SaltCloudSystemExit(err_message)
|
||||||
|
|
||||||
|
@@ -1322,7 +1319,7 @@ def create(vm_):
|
||||||
|
try:
|
||||||
|
log.warning(exc)
|
||||||
|
finally:
|
||||||
|
- raise SaltCloudSystemExit(six.text_type(exc))
|
||||||
|
+ raise SaltCloudSystemExit(str(exc))
|
||||||
|
|
||||||
|
vm_["ssh_host"] = data
|
||||||
|
if not vm_.get("ssh_username"):
|
||||||
|
@@ -1341,7 +1338,7 @@ def create(vm_):
|
||||||
|
__utils__["cloud.fire_event"](
|
||||||
|
"event",
|
||||||
|
"created instance",
|
||||||
|
- "salt/cloud/{0}/created".format(vm_["name"]),
|
||||||
|
+ "salt/cloud/{}/created".format(vm_["name"]),
|
||||||
|
args=__utils__["cloud.filter_event"](
|
||||||
|
"created", vm_, ["name", "profile", "provider", "driver"]
|
||||||
|
),
|
||||||
|
@@ -1548,9 +1545,7 @@ def _get_cloud_environment():
|
||||||
|
cloud_env = getattr(cloud_env_module, cloud_environment or "AZURE_PUBLIC_CLOUD")
|
||||||
|
except (AttributeError, ImportError):
|
||||||
|
raise SaltCloudSystemExit(
|
||||||
|
- "The azure {0} cloud environment is not available.".format(
|
||||||
|
- cloud_environment
|
||||||
|
- )
|
||||||
|
+ "The azure {} cloud environment is not available.".format(cloud_environment)
|
||||||
|
)
|
||||||
|
|
||||||
|
return cloud_env
|
||||||
|
@@ -1585,7 +1580,7 @@ def _get_block_blob_service(kwargs=None):
|
||||||
|
resource_group, storage_account
|
||||||
|
)
|
||||||
|
storage_keys = {v.key_name: v.value for v in storage_keys.keys}
|
||||||
|
- storage_key = next(six.itervalues(storage_keys))
|
||||||
|
+ storage_key = next(iter(storage_keys.values()))
|
||||||
|
|
||||||
|
cloud_env = _get_cloud_environment()
|
||||||
|
|
||||||
|
@@ -1620,7 +1615,7 @@ def list_blobs(call=None, kwargs=None): # pylint: disable=unused-argument
|
||||||
|
"server_encrypted": blob.properties.server_encrypted,
|
||||||
|
}
|
||||||
|
except Exception as exc: # pylint: disable=broad-except
|
||||||
|
- log.warning(six.text_type(exc))
|
||||||
|
+ log.warning(str(exc))
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
@@ -1655,9 +1650,7 @@ def delete_managed_disk(call=None, kwargs=None): # pylint: disable=unused-argum
|
||||||
|
compconn.disks.delete(kwargs["resource_group"], kwargs["blob"])
|
||||||
|
except Exception as exc: # pylint: disable=broad-except
|
||||||
|
log.error(
|
||||||
|
- "Error deleting managed disk %s - %s",
|
||||||
|
- kwargs.get("blob"),
|
||||||
|
- six.text_type(exc),
|
||||||
|
+ "Error deleting managed disk %s - %s", kwargs.get("blob"), str(exc),
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
|
||||||
|
@@ -1834,7 +1827,7 @@ def create_or_update_vmextension(
|
||||||
|
except CloudError as exc:
|
||||||
|
__utils__["azurearm.log_cloud_error"](
|
||||||
|
"compute",
|
||||||
|
- "Error attempting to create the VM extension: {0}".format(exc.message),
|
||||||
|
+ "Error attempting to create the VM extension: {}".format(exc.message),
|
||||||
|
)
|
||||||
|
ret = {"error": exc.message}
|
||||||
|
|
||||||
|
@@ -1881,11 +1874,9 @@ def stop(name, call=None):
|
||||||
|
ret = {"error": exc.message}
|
||||||
|
if not ret:
|
||||||
|
__utils__["azurearm.log_cloud_error"](
|
||||||
|
- "compute", "Unable to find virtual machine with name: {0}".format(name)
|
||||||
|
+ "compute", "Unable to find virtual machine with name: {}".format(name)
|
||||||
|
)
|
||||||
|
- ret = {
|
||||||
|
- "error": "Unable to find virtual machine with name: {0}".format(name)
|
||||||
|
- }
|
||||||
|
+ ret = {"error": "Unable to find virtual machine with name: {}".format(name)}
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
instance = compconn.virtual_machines.deallocate(
|
||||||
|
@@ -1896,7 +1887,7 @@ def stop(name, call=None):
|
||||||
|
ret = vm_result.as_dict()
|
||||||
|
except CloudError as exc:
|
||||||
|
__utils__["azurearm.log_cloud_error"](
|
||||||
|
- "compute", "Error attempting to stop {0}: {1}".format(name, exc.message)
|
||||||
|
+ "compute", "Error attempting to stop {}: {}".format(name, exc.message)
|
||||||
|
)
|
||||||
|
ret = {"error": exc.message}
|
||||||
|
|
||||||
|
@@ -1945,11 +1936,9 @@ def start(name, call=None):
|
||||||
|
ret = {"error": exc.message}
|
||||||
|
if not ret:
|
||||||
|
__utils__["azurearm.log_cloud_error"](
|
||||||
|
- "compute", "Unable to find virtual machine with name: {0}".format(name)
|
||||||
|
+ "compute", "Unable to find virtual machine with name: {}".format(name)
|
||||||
|
)
|
||||||
|
- ret = {
|
||||||
|
- "error": "Unable to find virtual machine with name: {0}".format(name)
|
||||||
|
- }
|
||||||
|
+ ret = {"error": "Unable to find virtual machine with name: {}".format(name)}
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
instance = compconn.virtual_machines.start(
|
||||||
|
@@ -1960,8 +1949,7 @@ def start(name, call=None):
|
||||||
|
ret = vm_result.as_dict()
|
||||||
|
except CloudError as exc:
|
||||||
|
__utils__["azurearm.log_cloud_error"](
|
||||||
|
- "compute",
|
||||||
|
- "Error attempting to start {0}: {1}".format(name, exc.message),
|
||||||
|
+ "compute", "Error attempting to start {}: {}".format(name, exc.message),
|
||||||
|
)
|
||||||
|
ret = {"error": exc.message}
|
||||||
|
|
||||||
--
|
--
|
||||||
2.16.4
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
From 1ca1bb7c01b1e589147c32b16eda719537ab5b62 Mon Sep 17 00:00:00 2001
|
From c9268ec731371cdd7b2fc129ad111d9f73800752 Mon Sep 17 00:00:00 2001
|
||||||
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
|
||||||
<psuarezhernandez@suse.com>
|
<psuarezhernandez@suse.com>
|
||||||
Date: Tue, 22 Sep 2020 15:15:51 +0100
|
Date: Tue, 22 Sep 2020 15:15:51 +0100
|
||||||
@ -8,16 +8,16 @@ Subject: [PATCH] Invalidate file list cache when cache file modified
|
|||||||
Add test_future_file_list_cache_file_ignored unit test
|
Add test_future_file_list_cache_file_ignored unit test
|
||||||
---
|
---
|
||||||
salt/fileserver/__init__.py | 2 +-
|
salt/fileserver/__init__.py | 2 +-
|
||||||
tests/unit/test_fileserver.py | 47 +++++++++++++++++++++++++++++++++--
|
tests/unit/test_fileserver.py | 53 +++++++++++++++++++++++------------
|
||||||
2 files changed, 46 insertions(+), 3 deletions(-)
|
2 files changed, 36 insertions(+), 19 deletions(-)
|
||||||
|
|
||||||
diff --git a/salt/fileserver/__init__.py b/salt/fileserver/__init__.py
|
diff --git a/salt/fileserver/__init__.py b/salt/fileserver/__init__.py
|
||||||
index 919987e2fc..1b8de51bdc 100644
|
index c8c417168f..b9e345d8c3 100644
|
||||||
--- a/salt/fileserver/__init__.py
|
--- a/salt/fileserver/__init__.py
|
||||||
+++ b/salt/fileserver/__init__.py
|
+++ b/salt/fileserver/__init__.py
|
||||||
@@ -142,7 +142,7 @@ def check_file_list_cache(opts, form, list_cache, w_lock):
|
@@ -132,7 +132,7 @@ def check_file_list_cache(opts, form, list_cache, w_lock):
|
||||||
'file=%s mtime=%s current_time=%s',
|
current_time,
|
||||||
list_cache, current_time, file_mtime
|
file_mtime,
|
||||||
)
|
)
|
||||||
- age = 0
|
- age = 0
|
||||||
+ age = -1
|
+ age = -1
|
||||||
@ -25,46 +25,58 @@ index 919987e2fc..1b8de51bdc 100644
|
|||||||
age = current_time - file_mtime
|
age = current_time - file_mtime
|
||||||
else:
|
else:
|
||||||
diff --git a/tests/unit/test_fileserver.py b/tests/unit/test_fileserver.py
|
diff --git a/tests/unit/test_fileserver.py b/tests/unit/test_fileserver.py
|
||||||
index d38e22c8e1..b92b32947b 100644
|
index 0bf30ee5cc..a1087bf4b0 100644
|
||||||
--- a/tests/unit/test_fileserver.py
|
--- a/tests/unit/test_fileserver.py
|
||||||
+++ b/tests/unit/test_fileserver.py
|
+++ b/tests/unit/test_fileserver.py
|
||||||
@@ -6,11 +6,17 @@
|
@@ -1,14 +1,15 @@
|
||||||
# Import Python libs
|
-# -*- coding: utf-8 -*-
|
||||||
from __future__ import absolute_import, print_function, unicode_literals
|
"""
|
||||||
|
:codeauthor: Joao Mesquita <jmesquita@sangoma.com>
|
||||||
|
"""
|
||||||
|
|
||||||
-# Import Salt Testing libs
|
-# Import Python libs
|
||||||
-from tests.support.unit import TestCase
|
-from __future__ import absolute_import, print_function, unicode_literals
|
||||||
|
|
||||||
|
-from salt import fileserver
|
||||||
+import datetime
|
+import datetime
|
||||||
+import os
|
+import os
|
||||||
+import time
|
+import time
|
||||||
|
|
||||||
|
-# Import Salt Testing libs
|
||||||
+import salt.utils.files
|
+import salt.utils.files
|
||||||
from salt import fileserver
|
+from salt import fileserver
|
||||||
|
|
||||||
+# Import Salt Testing libs
|
|
||||||
+from tests.support.helpers import with_tempdir
|
+from tests.support.helpers import with_tempdir
|
||||||
+from tests.support.unit import TestCase
|
from tests.support.mixins import LoaderModuleMockMixin
|
||||||
+
|
from tests.support.unit import TestCase
|
||||||
|
|
||||||
class MapDiffTestCase(TestCase):
|
@@ -31,22 +32,38 @@ class MapDiffTestCase(TestCase):
|
||||||
def test_diff_with_diffent_keys(self):
|
|
||||||
@@ -28,3 +34,40 @@ class MapDiffTestCase(TestCase):
|
|
||||||
map1 = {'file1': 12345}
|
|
||||||
map2 = {'file1': 1234}
|
|
||||||
assert fileserver.diff_mtime_map(map1, map2) is True
|
assert fileserver.diff_mtime_map(map1, map2) is True
|
||||||
+
|
|
||||||
+
|
|
||||||
|
-class VCSBackendWhitelistCase(TestCase, LoaderModuleMockMixin):
|
||||||
+class VCSBackendWhitelistCase(TestCase):
|
+class VCSBackendWhitelistCase(TestCase):
|
||||||
+ def setup_loader_modules(self):
|
def setup_loader_modules(self):
|
||||||
+ return {fileserver: {}}
|
return {fileserver: {}}
|
||||||
+
|
|
||||||
|
- def test_whitelist(self):
|
||||||
+ @with_tempdir()
|
+ @with_tempdir()
|
||||||
+ def test_future_file_list_cache_file_ignored(self, cachedir):
|
+ def test_future_file_list_cache_file_ignored(self, cachedir):
|
||||||
+ opts = {
|
opts = {
|
||||||
|
- "fileserver_backend": ["roots", "git", "hgfs", "svn"],
|
||||||
+ "fileserver_backend": ["roots"],
|
+ "fileserver_backend": ["roots"],
|
||||||
+ "cachedir": cachedir,
|
+ "cachedir": cachedir,
|
||||||
+ "extension_modules": "",
|
"extension_modules": "",
|
||||||
+ }
|
}
|
||||||
|
- fs = fileserver.Fileserver(opts)
|
||||||
|
- assert fs.servers.whitelist == [
|
||||||
|
- "git",
|
||||||
|
- "gitfs",
|
||||||
|
- "hg",
|
||||||
|
- "hgfs",
|
||||||
|
- "svn",
|
||||||
|
- "svnfs",
|
||||||
|
- "roots",
|
||||||
|
- ], fs.servers.whitelist
|
||||||
+
|
+
|
||||||
+ back_cachedir = os.path.join(cachedir, "file_lists/roots")
|
+ back_cachedir = os.path.join(cachedir, "file_lists/roots")
|
||||||
+ os.makedirs(os.path.join(back_cachedir))
|
+ os.makedirs(os.path.join(back_cachedir))
|
||||||
@ -90,6 +102,6 @@ index d38e22c8e1..b92b32947b 100644
|
|||||||
+ ret[1] is True
|
+ ret[1] is True
|
||||||
+ ), "Cache file list cache file is not refreshed when future modification time"
|
+ ), "Cache file list cache file is not refreshed when future modification time"
|
||||||
--
|
--
|
||||||
2.28.0
|
2.29.2
|
||||||
|
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user