Accepting request 791976 from systemsmanagement:saltstack

- Update to Salt version 3000 
  See release notes: https://docs.saltstack.com/en/latest/topics/releases/3000.html
- Do not make file.recurse state to fail when msgpack 0.5.4 (bsc#1167437)
- Fixes status attribute issue in aptpkg test
- Make setup.py script not to require setuptools greater than 9.1
  loop: fix variable names for until_no_eval
- Drop conflictive module.run state patch (bsc#1167437)
- Update patches after rebase with upstream v3000 tag (bsc#1167437)
- Fix some requirements issues depending on Python3 versions
- Removes obsolete patch
- Fix for low rpm_lowpkg unit test
- Add python-singledispatch as dependency for python2-salt
- Fix for temp folder definition in loader unit test
- Make "salt.ext.tornado.gen" to use "salt.ext.backports_abc" on Python 2
- Fix regression in service states with reload argument
- Fix integration test failure for test_mod_del_repo_multiline_values
- Fix for unless requisite when pip is not installed
- Fix errors from unit tests due NO_MOCK and NO_MOCK_REASON deprecation
- Fix tornado imports and missing _utils after rebasing patches
- Removes unresolved merge conflict in yumpkg module
- Added:
  * make-setup.py-script-to-not-require-setuptools-9.1.patch
  * opensuse-3000-virt-defined-states-222.patch
  * fix-for-unless-requisite-when-pip-is-not-installed.patch
  * fix-typo-on-msgpack-version-when-sanitizing-msgpack-.patch
  * fix-regression-in-service-states-with-reload-argumen.patch
  * batch_async-avoid-using-fnmatch-to-match-event-217.patch
  * make-salt.ext.tornado.gen-to-use-salt.ext.backports_.patch
  * virt._get_domain-don-t-raise-an-exception-if-there-i.patch
  * loop-fix-variable-names-for-until_no_eval.patch

OBS-URL: https://build.opensuse.org/request/show/791976
OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/salt?expand=0&rev=102
This commit is contained in:
Dominique Leuenberger 2020-04-10 21:52:30 +00:00 committed by Git OBS Bridge
commit 95bab810af
140 changed files with 2472 additions and 14167 deletions

View File

@ -1,224 +0,0 @@
From c9e39c7af97180414205a8ad752f86f579e75a58 Mon Sep 17 00:00:00 2001
From: Cedric Bosdonnat <cbosdonnat@suse.com>
Date: Tue, 3 Sep 2019 15:16:30 +0200
Subject: [PATCH] 2019.2.0 PR 54196 backport (#173)
* virt.network_define doesn't have vport as positional argument
virt.network_running state calls virt.network_define with vport as a
positional argument resulting in an error at runtime. Fix the state to
use the vport named argument instead.
* Fix virt.pool_running state documentation
virt.pool_running needs the source to be a dictionary, which the
documentation was not reflecting. Along the same lines the source hosts
need to be a list, adjust the example to show it.
* Get virt.pool_running to start the pool after creating it
Commit 25b96815 is wrong in assuming the pool build also starts it. The
pool needs to be stopped before building it, but we still need to start
it after the build: libvirt won't do it automagically for us.
* Fix states to match virt.{network,pool}_infos return
virt.network_infos and virt.pool_infos return the infos as a dictionary
with the network or pool name as a key even when there is only one
value. Adapt the network_running and pool_running states to this.
* Fix virt.running use of virt.vm_state
vm_state return a dictionary with the VM name as a key. Fix virt.running
state and its tests to match this. See issue #53107.
---
salt/states/virt.py | 26 ++++++++++++++++----------
tests/unit/states/test_virt.py | 27 +++++++++++++++------------
2 files changed, 31 insertions(+), 22 deletions(-)
diff --git a/salt/states/virt.py b/salt/states/virt.py
index d411f864cd..32a9e31ae5 100644
--- a/salt/states/virt.py
+++ b/salt/states/virt.py
@@ -389,8 +389,8 @@ def running(name,
try:
try:
- __salt__['virt.vm_state'](name)
- if __salt__['virt.vm_state'](name) != 'running':
+ domain_state = __salt__['virt.vm_state'](name)
+ if domain_state.get(name, None) != 'running':
action_msg = 'started'
if update:
status = __salt__['virt.update'](name,
@@ -670,7 +670,7 @@ def network_running(name,
try:
info = __salt__['virt.network_info'](name, connection=connection, username=username, password=password)
if info:
- if info['active']:
+ if info[name]['active']:
ret['comment'] = 'Network {0} exists and is running'.format(name)
else:
__salt__['virt.network_start'](name, connection=connection, username=username, password=password)
@@ -680,7 +680,7 @@ def network_running(name,
__salt__['virt.network_define'](name,
bridge,
forward,
- vport,
+ vport=vport,
tag=tag,
autostart=autostart,
start=True,
@@ -744,11 +744,11 @@ def pool_running(name,
- owner: 1000
- group: 100
- source:
- - dir: samba_share
- - hosts:
- one.example.com
- two.example.com
- - format: cifs
+ dir: samba_share
+ hosts:
+ - one.example.com
+ - two.example.com
+ format: cifs
- autostart: True
'''
@@ -761,7 +761,7 @@ def pool_running(name,
try:
info = __salt__['virt.pool_info'](name, connection=connection, username=username, password=password)
if info:
- if info['state'] == 'running':
+ if info[name]['state'] == 'running':
ret['comment'] = 'Pool {0} exists and is running'.format(name)
else:
__salt__['virt.pool_start'](name, connection=connection, username=username, password=password)
@@ -795,6 +795,12 @@ def pool_running(name,
connection=connection,
username=username,
password=password)
+
+ __salt__['virt.pool_start'](name,
+ connection=connection,
+ username=username,
+ password=password)
+
ret['changes'][name] = 'Pool defined and started'
ret['comment'] = 'Pool {0} defined and started'.format(name)
except libvirt.libvirtError as err:
diff --git a/tests/unit/states/test_virt.py b/tests/unit/states/test_virt.py
index 8022989937..2904fa224d 100644
--- a/tests/unit/states/test_virt.py
+++ b/tests/unit/states/test_virt.py
@@ -229,7 +229,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
'result': True,
'comment': 'myvm is running'}
with patch.dict(virt.__salt__, { # pylint: disable=no-member
- 'virt.vm_state': MagicMock(return_value='stopped'),
+ 'virt.vm_state': MagicMock(return_value={'myvm': 'stopped'}),
'virt.start': MagicMock(return_value=0),
}):
ret.update({'changes': {'myvm': 'Domain started'},
@@ -322,7 +322,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
password='supersecret')
with patch.dict(virt.__salt__, { # pylint: disable=no-member
- 'virt.vm_state': MagicMock(return_value='stopped'),
+ 'virt.vm_state': MagicMock(return_value={'myvm': 'stopped'}),
'virt.start': MagicMock(side_effect=[self.mock_libvirt.libvirtError('libvirt error msg')])
}):
ret.update({'changes': {}, 'result': False, 'comment': 'libvirt error msg'})
@@ -330,7 +330,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
# Working update case when running
with patch.dict(virt.__salt__, { # pylint: disable=no-member
- 'virt.vm_state': MagicMock(return_value='running'),
+ 'virt.vm_state': MagicMock(return_value={'myvm': 'running'}),
'virt.update': MagicMock(return_value={'definition': True, 'cpu': True})
}):
ret.update({'changes': {'myvm': {'definition': True, 'cpu': True}},
@@ -340,7 +340,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
# Working update case when stopped
with patch.dict(virt.__salt__, { # pylint: disable=no-member
- 'virt.vm_state': MagicMock(return_value='stopped'),
+ 'virt.vm_state': MagicMock(return_value={'myvm': 'stopped'}),
'virt.start': MagicMock(return_value=0),
'virt.update': MagicMock(return_value={'definition': True})
}):
@@ -351,7 +351,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
# Failed live update case
with patch.dict(virt.__salt__, { # pylint: disable=no-member
- 'virt.vm_state': MagicMock(return_value='running'),
+ 'virt.vm_state': MagicMock(return_value={'myvm': 'running'}),
'virt.update': MagicMock(return_value={'definition': True, 'cpu': False, 'errors': ['some error']})
}):
ret.update({'changes': {'myvm': {'definition': True, 'cpu': False, 'errors': ['some error']}},
@@ -361,7 +361,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
# Failed definition update case
with patch.dict(virt.__salt__, { # pylint: disable=no-member
- 'virt.vm_state': MagicMock(return_value='running'),
+ 'virt.vm_state': MagicMock(return_value={'myvm': 'running'}),
'virt.update': MagicMock(side_effect=[self.mock_libvirt.libvirtError('error message')])
}):
ret.update({'changes': {},
@@ -573,7 +573,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
define_mock.assert_called_with('mynet',
'br2',
'bridge',
- 'openvswitch',
+ vport='openvswitch',
tag=180,
autostart=False,
start=True,
@@ -582,7 +582,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
password='secret')
with patch.dict(virt.__salt__, { # pylint: disable=no-member
- 'virt.network_info': MagicMock(return_value={'active': True}),
+ 'virt.network_info': MagicMock(return_value={'mynet': {'active': True}}),
'virt.network_define': define_mock,
}):
ret.update({'changes': {}, 'comment': 'Network mynet exists and is running'})
@@ -590,7 +590,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
start_mock = MagicMock(return_value=True)
with patch.dict(virt.__salt__, { # pylint: disable=no-member
- 'virt.network_info': MagicMock(return_value={'active': False}),
+ 'virt.network_info': MagicMock(return_value={'mynet': {'active': False}}),
'virt.network_start': start_mock,
'virt.network_define': define_mock,
}):
@@ -666,10 +666,13 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
connection='myconnection',
username='user',
password='secret')
- mocks['start'].assert_not_called()
+ mocks['start'].assert_called_with('mypool',
+ connection='myconnection',
+ username='user',
+ password='secret')
with patch.dict(virt.__salt__, { # pylint: disable=no-member
- 'virt.pool_info': MagicMock(return_value={'state': 'running'}),
+ 'virt.pool_info': MagicMock(return_value={'mypool': {'state': 'running'}}),
}):
ret.update({'changes': {}, 'comment': 'Pool mypool exists and is running'})
self.assertDictEqual(virt.pool_running('mypool',
@@ -680,7 +683,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
for mock in mocks:
mocks[mock].reset_mock()
with patch.dict(virt.__salt__, { # pylint: disable=no-member
- 'virt.pool_info': MagicMock(return_value={'state': 'stopped'}),
+ 'virt.pool_info': MagicMock(return_value={'mypool': {'state': 'stopped'}}),
'virt.pool_build': mocks['build'],
'virt.pool_start': mocks['start']
}):
--
2.16.4

View File

@ -1 +1 @@
eb41abdc4d70c344f2d84dc6d693b9fb9cb4c247
c96fc684a059121ecc7baf013768b1b611777d73

View File

@ -3,7 +3,7 @@
<param name="url">https://github.com/openSUSE/salt-packaging.git</param>
<param name="subdir">salt</param>
<param name="filename">package</param>
<param name="revision">2019.2.3</param>
<param name="revision">3000</param>
<param name="scm">git</param>
</service>
<service name="extract_file" mode="disabled">
@ -12,8 +12,8 @@
</service>
<service name="download_url" mode="disabled">
<param name="host">codeload.github.com</param>
<param name="path">openSUSE/salt/tar.gz/v2019.2.3-suse</param>
<param name="filename">v2019.2.3.tar.gz</param>
<param name="path">openSUSE/salt/tar.gz/v3000-suse</param>
<param name="filename">v3000.tar.gz</param>
</service>
<service name="update_changelog" mode="disabled"></service>
</services>

View File

@ -1,4 +1,4 @@
From bfaac404ffa334157f4408b312b12a59b059df69 Mon Sep 17 00:00:00 2001
From 63f28a891449889fa3d7139470266162b10e88f2 Mon Sep 17 00:00:00 2001
From: Alberto Planas <aplanas@gmail.com>
Date: Tue, 22 Oct 2019 11:02:33 +0200
Subject: [PATCH] Accumulated changes from Yomi (#167)
@ -17,17 +17,17 @@ This patch ignore this kind of issue during the grains creation.
(cherry picked from commit b865491b74679140f7a71c5ba50d482db47b600f)
---
salt/grains/core.py | 4 ++++
salt/modules/zypperpkg.py | 30 ++++++++++++++++--------
tests/unit/grains/test_core.py | 45 ++++++++++++++++++++++++++++++++++++
tests/unit/modules/test_zypperpkg.py | 26 +++++++++++++++++++++
4 files changed, 96 insertions(+), 9 deletions(-)
salt/grains/core.py | 4 +++
salt/modules/zypperpkg.py | 30 +++++++++++-----
tests/unit/grains/test_core.py | 68 ++++++++++++++++++++++++++++++++++++
tests/unit/modules/test_zypperpkg.py | 26 ++++++++++++++
4 files changed, 119 insertions(+), 9 deletions(-)
diff --git a/salt/grains/core.py b/salt/grains/core.py
index e1d08b76cf..6b1f2d2223 100644
index 77ae99590f..68c43482d3 100644
--- a/salt/grains/core.py
+++ b/salt/grains/core.py
@@ -987,6 +987,10 @@ def _virtual(osdata):
@@ -997,6 +997,10 @@ def _virtual(osdata):
grains['virtual'] = 'gce'
elif 'BHYVE' in output:
grains['virtual'] = 'bhyve'
@ -39,10 +39,10 @@ index e1d08b76cf..6b1f2d2223 100644
pass
elif osdata['kernel'] == 'FreeBSD':
diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py
index da1953b2a5..a87041aa70 100644
index f7158e0810..5f3b6d6855 100644
--- a/salt/modules/zypperpkg.py
+++ b/salt/modules/zypperpkg.py
@@ -861,23 +861,35 @@ def list_pkgs(versions_as_list=False, root=None, includes=None, **kwargs):
@@ -863,23 +863,35 @@ 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:
@ -88,13 +88,14 @@ index da1953b2a5..a87041aa70 100644
'install_date_time_t': None,
}]
diff --git a/tests/unit/grains/test_core.py b/tests/unit/grains/test_core.py
index 09e197a2e4..7153a078f4 100644
index 60914204b0..c4731f667a 100644
--- a/tests/unit/grains/test_core.py
+++ b/tests/unit/grains/test_core.py
@@ -1317,6 +1317,51 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
'uuid': ''
})
@@ -1543,3 +1543,71 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
self.assertIn('osfullname', os_grains)
self.assertEqual(os_grains.get('osfullname'), 'FreeBSD')
+
+ @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
+ def test_kernelparams_return(self):
+ expectations = [
@ -140,14 +141,33 @@ index 09e197a2e4..7153a078f4 100644
+ 'uuid': ''
+ })
+
@skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
@skipIf(six.PY2, 'UnicodeDecodeError is throw in Python 3')
@patch('os.path.exists')
+ @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
+ @skipIf(six.PY2, 'UnicodeDecodeError is throw in Python 3')
+ @patch('os.path.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
index 695d982ca6..7617113401 100644
index 6102043384..76937cc358 100644
--- a/tests/unit/modules/test_zypperpkg.py
+++ b/tests/unit/modules/test_zypperpkg.py
@@ -943,6 +943,32 @@ Repository 'DUMMY' not found by its alias, number, or URI.
@@ -944,6 +944,32 @@ Repository 'DUMMY' not found by its alias, number, or URI.
with self.assertRaisesRegex(CommandExecutionError, '^Advisory id "SUSE-PATCH-XXX" not found$'):
zypper.install(advisory_ids=['SUSE-PATCH-XXX'])

View File

@ -1,4 +1,4 @@
From 78f5d1bd931f5329792d0e430c75025b45c14041 Mon Sep 17 00:00:00 2001
From 9f29577b75cac1e79ec7c30a5dff0dff0ab9da3a Mon Sep 17 00:00:00 2001
From: Alberto Planas <aplanas@gmail.com>
Date: Tue, 30 Jul 2019 11:23:12 +0200
Subject: [PATCH] Accumulated changes required for Yomi (#165)
@ -58,133 +58,17 @@ so the cached data will be separated too.
(cherry picked from commit 9c54bb3e8c93ba21fc583bdefbcadbe53cbcd7b5)
---
salt/modules/chroot.py | 36 +++++++++++----------
salt/modules/cmdmod.py | 12 +++++--
salt/modules/freezer.py | 20 ++++++++----
salt/modules/zypperpkg.py | 13 ++++++--
tests/unit/modules/test_chroot.py | 36 +++++++++++++++++++--
tests/unit/modules/test_cmdmod.py | 50 +++++++++++++++++++++++++++++
tests/unit/modules/test_freezer.py | 62 ++++++++++++++++++++++++++++++++----
tests/unit/modules/test_zypperpkg.py | 21 ++++++++++++
8 files changed, 214 insertions(+), 36 deletions(-)
salt/modules/cmdmod.py | 12 +++++++++---
salt/modules/zypperpkg.py | 13 ++++++++++---
tests/unit/modules/test_cmdmod.py | 16 ++++++++++++++++
tests/unit/modules/test_zypperpkg.py | 21 +++++++++++++++++++++
4 files changed, 56 insertions(+), 6 deletions(-)
diff --git a/salt/modules/chroot.py b/salt/modules/chroot.py
index 6e4705b67e..17b5890d8c 100644
--- a/salt/modules/chroot.py
+++ b/salt/modules/chroot.py
@@ -50,16 +50,17 @@ def __virtual__():
return (False, 'Module chroot requires the command chroot')
-def exist(name):
+def exist(root):
'''
Return True if the chroot environment is present.
'''
- dev = os.path.join(name, 'dev')
- proc = os.path.join(name, 'proc')
- return all(os.path.isdir(i) for i in (name, dev, proc))
+ dev = os.path.join(root, 'dev')
+ proc = os.path.join(root, 'proc')
+ sys = os.path.join(root, 'sys')
+ return all(os.path.isdir(i) for i in (root, dev, proc, sys))
-def create(name):
+def create(root):
'''
Create a basic chroot environment.
@@ -67,7 +68,7 @@ def create(name):
install the minimal required binaries, including Python if
chroot.call is called.
- name
+ root
Path to the chroot environment
CLI Example:
@@ -77,26 +78,28 @@ def create(name):
salt myminion chroot.create /chroot
'''
- if not exist(name):
- dev = os.path.join(name, 'dev')
- proc = os.path.join(name, 'proc')
+ if not exist(root):
+ dev = os.path.join(root, 'dev')
+ proc = os.path.join(root, 'proc')
+ sys = os.path.join(root, 'sys')
try:
os.makedirs(dev, mode=0o755)
os.makedirs(proc, mode=0o555)
+ os.makedirs(sys, mode=0o555)
except OSError as e:
log.error('Error when trying to create chroot directories: %s', e)
return False
return True
-def call(name, function, *args, **kwargs):
+def call(root, function, *args, **kwargs):
'''
Executes a Salt function inside a chroot environment.
The chroot does not need to have Salt installed, but Python is
required.
- name
+ root
Path to the chroot environment
function
@@ -107,18 +110,19 @@ def call(name, function, *args, **kwargs):
.. code-block:: bash
salt myminion chroot.call /chroot test.ping
+ salt myminion chroot.call /chroot ssh.set_auth_key user key=mykey
'''
if not function:
raise CommandExecutionError('Missing function parameter')
- if not exist(name):
+ if not exist(root):
raise CommandExecutionError('Chroot environment not found')
# Create a temporary directory inside the chroot where we can
# untar salt-thin
- thin_dest_path = tempfile.mkdtemp(dir=name)
+ thin_dest_path = tempfile.mkdtemp(dir=root)
thin_path = __utils__['thin.gen_thin'](
__opts__['cachedir'],
extra_mods=__salt__['config.option']('thin_extra_mods', ''),
@@ -130,7 +134,7 @@ def call(name, function, *args, **kwargs):
return {'result': False, 'comment': stdout}
chroot_path = os.path.join(os.path.sep,
- os.path.relpath(thin_dest_path, name))
+ os.path.relpath(thin_dest_path, root))
try:
safe_kwargs = clean_kwargs(**kwargs)
salt_argv = [
@@ -144,8 +148,8 @@ def call(name, function, *args, **kwargs):
'-l', 'quiet',
'--',
function
- ] + list(args) + ['{}={}'.format(k, v) for (k, v) in safe_kwargs]
- ret = __salt__['cmd.run_chroot'](name, [str(x) for x in salt_argv])
+ ] + list(args) + ['{}={}'.format(k, v) for (k, v) in safe_kwargs.items()]
+ ret = __salt__['cmd.run_chroot'](root, [str(x) for x in salt_argv])
if ret['retcode'] != EX_OK:
raise CommandExecutionError(ret['stderr'])
diff --git a/salt/modules/cmdmod.py b/salt/modules/cmdmod.py
index 1801147f57..a7e1553ec3 100644
index eed7656a6d..0d2f720bbb 100644
--- a/salt/modules/cmdmod.py
+++ b/salt/modules/cmdmod.py
@@ -3079,13 +3079,19 @@ def run_chroot(root,
@@ -3094,13 +3094,19 @@ def run_chroot(root,
if isinstance(cmd, (list, tuple)):
cmd = ' '.join([six.text_type(i) for i in cmd])
@ -207,69 +91,8 @@ index 1801147f57..a7e1553ec3 100644
cwd=cwd,
stdin=stdin,
shell=shell,
diff --git a/salt/modules/freezer.py b/salt/modules/freezer.py
index 786dfe4515..85adbfeb82 100644
--- a/salt/modules/freezer.py
+++ b/salt/modules/freezer.py
@@ -151,7 +151,7 @@ def freeze(name=None, force=False, **kwargs):
states_path = _states_path()
try:
- os.makedirs(states_path)
+ os.makedirs(states_path, exist_ok=True)
except OSError as e:
msg = 'Error when trying to create the freezer storage %s: %s'
log.error(msg, states_path, e)
@@ -163,13 +163,13 @@ def freeze(name=None, force=False, **kwargs):
safe_kwargs = clean_kwargs(**kwargs)
pkgs = __salt__['pkg.list_pkgs'](**safe_kwargs)
repos = __salt__['pkg.list_repos'](**safe_kwargs)
- for name, content in zip(_paths(name), (pkgs, repos)):
- with fopen(name, 'w') as fp:
+ for fname, content in zip(_paths(name), (pkgs, repos)):
+ with fopen(fname, 'w') as fp:
json.dump(content, fp)
return True
-def restore(name=None, **kwargs):
+def restore(name=None, clean=False, **kwargs):
'''
Make sure that the system contains the packages and repos from a
frozen state.
@@ -190,6 +190,9 @@ def restore(name=None, **kwargs):
name
Name of the frozen state. Optional.
+ clean
+ In True remove the frozen information YAML from the cache
+
CLI Example:
.. code-block:: bash
@@ -203,8 +206,8 @@ def restore(name=None, **kwargs):
frozen_pkgs = {}
frozen_repos = {}
- for name, content in zip(_paths(name), (frozen_pkgs, frozen_repos)):
- with fopen(name) as fp:
+ for fname, content in zip(_paths(name), (frozen_pkgs, frozen_repos)):
+ with fopen(fname) as fp:
content.update(json.load(fp))
# The ordering of removing or adding packages and repos can be
@@ -291,4 +294,9 @@ def restore(name=None, **kwargs):
log.error(msg, repo, e)
res['comment'].append(msg % (repo, e))
+ # Clean the cached YAML files
+ if clean and not res['comment']:
+ for fname in _paths(name):
+ os.remove(fname)
+
return res
diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py
index 6bc7211f59..f71d6aac9e 100644
index 3760b525e7..8179cd8c1d 100644
--- a/salt/modules/zypperpkg.py
+++ b/salt/modules/zypperpkg.py
@@ -449,8 +449,14 @@ def _clean_cache():
@ -288,7 +111,7 @@ index 6bc7211f59..f71d6aac9e 100644
def list_upgrades(refresh=True, root=None, **kwargs):
@@ -809,9 +815,10 @@ def list_pkgs(versions_as_list=False, root=None, includes=None, **kwargs):
@@ -811,9 +817,10 @@ def list_pkgs(versions_as_list=False, root=None, includes=None, **kwargs):
includes = includes if includes else []
@ -301,64 +124,11 @@ index 6bc7211f59..f71d6aac9e 100644
if contextkey not in __context__:
ret = {}
cmd = ['rpm']
diff --git a/tests/unit/modules/test_chroot.py b/tests/unit/modules/test_chroot.py
index 7181dd7e50..0e65a26606 100644
--- a/tests/unit/modules/test_chroot.py
+++ b/tests/unit/modules/test_chroot.py
@@ -63,10 +63,10 @@ class ChrootTestCase(TestCase, LoaderModuleMockMixin):
'''
Test if the chroot environment exist.
'''
- isdir.side_effect = (True, True, True)
+ isdir.side_effect = (True, True, True, True)
self.assertTrue(chroot.exist('/chroot'))
- isdir.side_effect = (True, True, False)
+ isdir.side_effect = (True, True, True, False)
self.assertFalse(chroot.exist('/chroot'))
@patch('os.makedirs')
@@ -182,3 +182,35 @@ class ChrootTestCase(TestCase, LoaderModuleMockMixin):
salt_mock['archive.tar'].assert_called_once()
salt_mock['cmd.run_chroot'].assert_called_once()
utils_mock['files.rm_rf'].assert_called_once()
+
+ @patch('salt.modules.chroot.exist')
+ @patch('tempfile.mkdtemp')
+ def test_call_success_parameters(self, mkdtemp, exist):
+ '''
+ Test execution of Salt functions in chroot with parameters.
+ '''
+ # Success test
+ exist.return_value = True
+ mkdtemp.return_value = '/chroot/tmp01'
+ utils_mock = {
+ 'thin.gen_thin': MagicMock(return_value='/salt-thin.tgz'),
+ 'files.rm_rf': MagicMock(),
+ 'json.find_json': MagicMock(return_value={'return': 'result'})
+ }
+ salt_mock = {
+ 'archive.tar': MagicMock(return_value=''),
+ 'config.option': MagicMock(),
+ 'cmd.run_chroot': MagicMock(return_value={
+ 'retcode': 0,
+ 'stdout': '',
+ }),
+ }
+ with patch.dict(chroot.__utils__, utils_mock), \
+ patch.dict(chroot.__salt__, salt_mock):
+ self.assertEqual(chroot.call('/chroot', 'ssh.set_auth_key',
+ user='user', key='key'), 'result')
+ utils_mock['thin.gen_thin'].assert_called_once()
+ salt_mock['config.option'].assert_called()
+ salt_mock['archive.tar'].assert_called_once()
+ salt_mock['cmd.run_chroot'].assert_called_once()
+ utils_mock['files.rm_rf'].assert_called_once()
diff --git a/tests/unit/modules/test_cmdmod.py b/tests/unit/modules/test_cmdmod.py
index a20afaca0f..6f3964f7aa 100644
index f8fba59294..8d763435f8 100644
--- a/tests/unit/modules/test_cmdmod.py
+++ b/tests/unit/modules/test_cmdmod.py
@@ -312,6 +312,22 @@ class CMDMODTestCase(TestCase, LoaderModuleMockMixin):
@@ -371,6 +371,22 @@ class CMDMODTestCase(TestCase, LoaderModuleMockMixin):
else:
raise RuntimeError
@ -381,161 +151,11 @@ index a20afaca0f..6f3964f7aa 100644
def test_run_all_binary_replace(self):
'''
Test for failed decoding of binary data, for instance when doing
@@ -401,3 +417,37 @@ class CMDMODTestCase(TestCase, LoaderModuleMockMixin):
ret = cmdmod.run_all('some command', output_encoding='latin1')
self.assertEqual(ret['stdout'], stdout)
+
+ def test_run_chroot_runas(self):
+ '''
+ Test run_chroot when a runas parameter is provided
+ '''
+ with patch.dict(cmdmod.__salt__, {'mount.mount': MagicMock(),
+ 'mount.umount': MagicMock()}):
+ with patch('salt.modules.cmdmod.run_all') as run_all_mock:
+ cmdmod.run_chroot('/mnt', 'ls', runas='foobar')
+ run_all_mock.assert_called_with(
+ 'chroot --userspec foobar: /mnt /bin/sh -c ls',
+ bg=False,
+ clean_env=False,
+ cwd=None,
+ env=None,
+ ignore_retcode=False,
+ log_callback=None,
+ output_encoding=None,
+ output_loglevel='quiet',
+ pillar=None,
+ pillarenv=None,
+ python_shell=True,
+ reset_system_locale=True,
+ rstrip=True,
+ saltenv='base',
+ shell='/bin/bash',
+ stdin=None,
+ success_retcodes=None,
+ success_stderr=None,
+ success_stdout=None,
+ template=None,
+ timeout=None,
+ umask=None,
+ use_vt=False)
diff --git a/tests/unit/modules/test_freezer.py b/tests/unit/modules/test_freezer.py
index f6cf2f374f..70d315c17a 100644
--- a/tests/unit/modules/test_freezer.py
+++ b/tests/unit/modules/test_freezer.py
@@ -112,6 +112,30 @@ class FreezerTestCase(TestCase, LoaderModuleMockMixin):
self.assertRaises(CommandExecutionError, freezer.freeze)
makedirs.assert_called_once()
+ @patch('salt.utils.json.dump')
+ @patch('salt.modules.freezer.fopen')
+ @patch('salt.modules.freezer.status')
+ @patch('os.makedirs')
+ def test_freeze_success_two_freeze(self, makedirs, status, fopen, dump):
+ '''
+ Test to freeze a current installation
+ '''
+ # Freeze the current new state
+ status.return_value = False
+ salt_mock = {
+ 'pkg.list_pkgs': MagicMock(return_value={}),
+ 'pkg.list_repos': MagicMock(return_value={}),
+ }
+ with patch.dict(freezer.__salt__, salt_mock):
+ self.assertTrue(freezer.freeze('one'))
+ self.assertTrue(freezer.freeze('two'))
+
+ self.assertEqual(makedirs.call_count, 2)
+ self.assertEqual(salt_mock['pkg.list_pkgs'].call_count, 2)
+ self.assertEqual(salt_mock['pkg.list_repos'].call_count, 2)
+ fopen.assert_called()
+ dump.assert_called()
+
@patch('salt.utils.json.dump')
@patch('salt.modules.freezer.fopen')
@patch('salt.modules.freezer.status')
@@ -132,7 +156,7 @@ class FreezerTestCase(TestCase, LoaderModuleMockMixin):
salt_mock['pkg.list_pkgs'].assert_called_once()
salt_mock['pkg.list_repos'].assert_called_once()
fopen.assert_called()
- dump.asster_called()
+ dump.assert_called()
@patch('salt.utils.json.dump')
@patch('salt.modules.freezer.fopen')
@@ -154,7 +178,7 @@ class FreezerTestCase(TestCase, LoaderModuleMockMixin):
salt_mock['pkg.list_pkgs'].assert_called_once()
salt_mock['pkg.list_repos'].assert_called_once()
fopen.assert_called()
- dump.asster_called()
+ dump.assert_called()
@patch('salt.modules.freezer.status')
def test_restore_fails_missing_state(self, status):
@@ -190,7 +214,7 @@ class FreezerTestCase(TestCase, LoaderModuleMockMixin):
salt_mock['pkg.list_repos'].assert_called()
salt_mock['pkg.mod_repo'].assert_called_once()
fopen.assert_called()
- load.asster_called()
+ load.assert_called()
@patch('salt.utils.json.load')
@patch('salt.modules.freezer.fopen')
@@ -217,7 +241,7 @@ class FreezerTestCase(TestCase, LoaderModuleMockMixin):
salt_mock['pkg.list_repos'].assert_called()
salt_mock['pkg.install'].assert_called_once()
fopen.assert_called()
- load.asster_called()
+ load.assert_called()
@patch('salt.utils.json.load')
@patch('salt.modules.freezer.fopen')
@@ -244,7 +268,7 @@ class FreezerTestCase(TestCase, LoaderModuleMockMixin):
salt_mock['pkg.list_repos'].assert_called()
salt_mock['pkg.remove'].assert_called_once()
fopen.assert_called()
- load.asster_called()
+ load.assert_called()
@patch('salt.utils.json.load')
@patch('salt.modules.freezer.fopen')
@@ -271,4 +295,30 @@ class FreezerTestCase(TestCase, LoaderModuleMockMixin):
salt_mock['pkg.list_repos'].assert_called()
salt_mock['pkg.del_repo'].assert_called_once()
fopen.assert_called()
- load.asster_called()
+ load.assert_called()
+
+ @patch('os.remove')
+ @patch('salt.utils.json.load')
+ @patch('salt.modules.freezer.fopen')
+ @patch('salt.modules.freezer.status')
+ def test_restore_clean_yml(self, status, fopen, load, remove):
+ '''
+ Test to restore an old state
+ '''
+ status.return_value = True
+ salt_mock = {
+ 'pkg.list_pkgs': MagicMock(return_value={}),
+ 'pkg.list_repos': MagicMock(return_value={}),
+ 'pkg.install': MagicMock(),
+ }
+ with patch.dict(freezer.__salt__, salt_mock):
+ self.assertEqual(freezer.restore(clean=True), {
+ 'pkgs': {'add': [], 'remove': []},
+ 'repos': {'add': [], 'remove': []},
+ 'comment': [],
+ })
+ salt_mock['pkg.list_pkgs'].assert_called()
+ salt_mock['pkg.list_repos'].assert_called()
+ fopen.assert_called()
+ load.assert_called()
+ self.assertEqual(remove.call_count, 2)
diff --git a/tests/unit/modules/test_zypperpkg.py b/tests/unit/modules/test_zypperpkg.py
index 0a3053680f..695d982ca6 100644
index 12c22bfcb2..6102043384 100644
--- a/tests/unit/modules/test_zypperpkg.py
+++ b/tests/unit/modules/test_zypperpkg.py
@@ -570,6 +570,7 @@ Repository 'DUMMY' not found by its alias, number, or URI.
@@ -571,6 +571,7 @@ Repository 'DUMMY' not found by its alias, number, or URI.
patch.dict(zypper.__salt__, {'pkg_resource.stringify': MagicMock()}):
pkgs = zypper.list_pkgs(versions_as_list=True)
self.assertFalse(pkgs.get('gpg-pubkey', False))
@ -543,7 +163,7 @@ index 0a3053680f..695d982ca6 100644
for pkg_name, pkg_version in {
'jakarta-commons-discovery': ['0.4-129.686'],
'yast2-ftp-server': ['3.1.8-8.1'],
@@ -612,6 +613,7 @@ Repository 'DUMMY' not found by its alias, number, or URI.
@@ -613,6 +614,7 @@ Repository 'DUMMY' not found by its alias, number, or URI.
patch.dict(pkg_resource.__salt__, {'pkg.parse_arch_from_name': zypper.parse_arch_from_name}):
pkgs = zypper.list_pkgs(attr=['epoch', 'release', 'arch', 'install_date_time_t'])
self.assertFalse(pkgs.get('gpg-pubkey', False))
@ -551,7 +171,7 @@ index 0a3053680f..695d982ca6 100644
for pkg_name, pkg_attr in {
'jakarta-commons-discovery': [{
'version': '0.4',
@@ -1455,3 +1457,22 @@ pattern() = package-c'''),
@@ -1456,3 +1458,22 @@ pattern() = package-c'''),
'summary': 'description b',
},
}

View File

@ -1,4 +1,4 @@
From 45b3ee6c8255c2daa6ed291a430a6325155ef29c Mon Sep 17 00:00:00 2001
From 6df4cef549665aad5b9e2af50eb06124a2bb0997 Mon Sep 17 00:00:00 2001
From: Bo Maryniuk <bo@suse.de>
Date: Tue, 17 Oct 2017 16:52:33 +0200
Subject: [PATCH] Activate all beacons sources: config/pillar/grains
@ -8,10 +8,10 @@ Subject: [PATCH] Activate all beacons sources: config/pillar/grains
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/salt/minion.py b/salt/minion.py
index 6912d9587f..c5f637eaa6 100644
index 6a77d90185..457f485b0a 100644
--- a/salt/minion.py
+++ b/salt/minion.py
@@ -484,7 +484,7 @@ class MinionBase(object):
@@ -483,7 +483,7 @@ class MinionBase(object):
the pillar or grains changed
'''
if 'config.merge' in functions:

View File

@ -1,4 +1,4 @@
From 56c38610b083997cebf00070efe781d114fc33b6 Mon Sep 17 00:00:00 2001
From cd66b1e6636013440577a38a5a68729fec2f3f99 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Mon, 14 May 2018 11:33:13 +0100
@ -23,10 +23,10 @@ Allow removing only specific package versions with zypper and yum
1 file changed, 21 insertions(+)
diff --git a/salt/states/pkg.py b/salt/states/pkg.py
index 0aca1e0af8..2034262b23 100644
index a13d418400..c0fa2f6b69 100644
--- a/salt/states/pkg.py
+++ b/salt/states/pkg.py
@@ -455,6 +455,16 @@ def _find_remove_targets(name=None,
@@ -450,6 +450,16 @@ def _find_remove_targets(name=None,
if __grains__['os'] == 'FreeBSD' and origin:
cver = [k for k, v in six.iteritems(cur_pkgs) if v['origin'] == pkgname]
@ -43,7 +43,7 @@ index 0aca1e0af8..2034262b23 100644
else:
cver = cur_pkgs.get(pkgname, [])
@@ -861,6 +871,17 @@ def _verify_install(desired, new_pkgs, ignore_epoch=False, new_caps=None):
@@ -856,6 +866,17 @@ def _verify_install(desired, new_pkgs, ignore_epoch=False, new_caps=None):
cver = new_pkgs.get(pkgname.split('%')[0])
elif __grains__['os_family'] == 'Debian':
cver = new_pkgs.get(pkgname.split('=')[0])

View File

@ -1,4 +1,4 @@
From 27770ed415e010055fea3a2cf599b56cd4aedf5e Mon Sep 17 00:00:00 2001
From acf0b24353d831dcc2c5b292f99480938f5ecd93 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Julio=20Gonz=C3=A1lez=20Gil?=
<juliogonzalez@users.noreply.github.com>
Date: Wed, 12 Feb 2020 10:05:45 +0100
@ -11,10 +11,10 @@ Subject: [PATCH] Add Astra Linux Common Edition to the OS Family list
2 files changed, 21 insertions(+)
diff --git a/salt/grains/core.py b/salt/grains/core.py
index 31ed8a77aa..67e263d37b 100644
index 20950988d9..f410985198 100644
--- a/salt/grains/core.py
+++ b/salt/grains/core.py
@@ -1508,6 +1508,7 @@ _OS_FAMILY_MAP = {
@@ -1523,6 +1523,7 @@ _OS_FAMILY_MAP = {
'Funtoo': 'Gentoo',
'AIX': 'AIX',
'TurnKey': 'Debian',
@ -23,7 +23,7 @@ index 31ed8a77aa..67e263d37b 100644
# Matches any possible format:
diff --git a/tests/unit/grains/test_core.py b/tests/unit/grains/test_core.py
index 09e197a2e4..700eac2b08 100644
index b4ed9379e5..c276dee9f3 100644
--- a/tests/unit/grains/test_core.py
+++ b/tests/unit/grains/test_core.py
@@ -605,6 +605,26 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
@ -54,6 +54,6 @@ index 09e197a2e4..700eac2b08 100644
def test_windows_platform_data(self):
'''
--
2.23.0
2.16.4

View File

@ -1,4 +1,4 @@
From 669a03b26870a7109c3f4b327dd2b5a4ec4fa1ba Mon Sep 17 00:00:00 2001
From 376a7d2eeb6b3b215fac9322f1baee4497bdb339 Mon Sep 17 00:00:00 2001
From: Marcelo Chiaradia <mchiaradia@suse.com>
Date: Thu, 4 Apr 2019 13:57:38 +0200
Subject: [PATCH] Add 'batch_presence_ping_timeout' and

View File

@ -1,4 +1,4 @@
From 2c4676963dfb4646ae0d2ad8aedba0aa83d266e9 Mon Sep 17 00:00:00 2001
From a90f35bc03b477a63aae20c58f8957c075569465 Mon Sep 17 00:00:00 2001
From: Bo Maryniuk <bo@suse.de>
Date: Tue, 9 Oct 2018 14:08:50 +0200
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(+)
diff --git a/salt/grains/core.py b/salt/grains/core.py
index cd7ee39d2f..f59eeb5780 100644
index 9c1b5d930e..7b7e328520 100644
--- a/salt/grains/core.py
+++ b/salt/grains/core.py
@@ -1623,6 +1623,34 @@ def _parse_cpe_name(cpe):
@@ -1642,6 +1642,34 @@ def _parse_cpe_name(cpe):
return ret

View File

@ -1,4 +1,4 @@
From a96d99e4bf7a43c99037aee6b6e030cdc46ab542 Mon Sep 17 00:00:00 2001
From e57dd3c2ae655422f0f6939825154ce5827d43c4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Thu, 21 Jun 2018 11:57:57 +0100
@ -9,7 +9,7 @@ Subject: [PATCH] Add custom SUSE capabilities as Grains
1 file changed, 7 insertions(+)
diff --git a/salt/grains/extra.py b/salt/grains/extra.py
index fff70e9f5b..4fb58674bf 100644
index 9ce644b766..1082b05dba 100644
--- a/salt/grains/extra.py
+++ b/salt/grains/extra.py
@@ -75,3 +75,10 @@ def config():

View File

@ -1,4 +1,4 @@
From 960c7f29239a23c3d46c31692d2e881735f4d2a7 Mon Sep 17 00:00:00 2001
From 874b1229babf5244debac141cd260f695ccc1e9d Mon Sep 17 00:00:00 2001
From: Marcelo Chiaradia <mchiaradia@suse.com>
Date: Thu, 7 Jun 2018 10:29:41 +0200
Subject: [PATCH] Add environment variable to know if yum is invoked from
@ -9,10 +9,10 @@ Subject: [PATCH] Add environment variable to know if yum is invoked from
1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/salt/modules/yumpkg.py b/salt/modules/yumpkg.py
index c250b94f0e..a56a2e8366 100644
index f7e4ac9753..c89d321a1b 100644
--- a/salt/modules/yumpkg.py
+++ b/salt/modules/yumpkg.py
@@ -887,7 +887,8 @@ def list_repo_pkgs(*args, **kwargs):
@@ -913,7 +913,8 @@ def list_repo_pkgs(*args, **kwargs):
yum_version = None if _yum() != 'yum' else _LooseVersion(
__salt__['cmd.run'](
['yum', '--version'],
@ -22,7 +22,7 @@ index c250b94f0e..a56a2e8366 100644
).splitlines()[0].strip()
)
# Really old version of yum; does not even have --showduplicates option
@@ -2298,7 +2299,8 @@ def list_holds(pattern=__HOLD_PATTERN, full=True):
@@ -2324,7 +2325,8 @@ def list_holds(pattern=__HOLD_PATTERN, full=True):
_check_versionlock()
out = __salt__['cmd.run']([_yum(), 'versionlock', 'list'],
@ -32,7 +32,7 @@ index c250b94f0e..a56a2e8366 100644
ret = []
for line in salt.utils.itertools.split(out, '\n'):
match = _get_hold(line, pattern=pattern, full=full)
@@ -2364,7 +2366,8 @@ def group_list():
@@ -2390,7 +2392,8 @@ def group_list():
out = __salt__['cmd.run_stdout'](
[_yum(), 'grouplist', 'hidden'],
output_loglevel='trace',
@ -42,7 +42,7 @@ index c250b94f0e..a56a2e8366 100644
)
key = None
for line in salt.utils.itertools.split(out, '\n'):
@@ -2431,7 +2434,8 @@ def group_info(name, expand=False):
@@ -2457,7 +2460,8 @@ def group_info(name, expand=False):
out = __salt__['cmd.run_stdout'](
cmd,
output_loglevel='trace',
@ -52,7 +52,7 @@ index c250b94f0e..a56a2e8366 100644
)
g_info = {}
@@ -3100,7 +3104,8 @@ def download(*packages):
@@ -3134,7 +3138,8 @@ def download(*packages):
__salt__['cmd.run'](
cmd,
output_loglevel='trace',
@ -62,7 +62,7 @@ index c250b94f0e..a56a2e8366 100644
)
ret = {}
for dld_result in os.listdir(CACHE_DIR):
@@ -3175,7 +3180,8 @@ def _get_patches(installed_only=False):
@@ -3209,7 +3214,8 @@ def _get_patches(installed_only=False):
cmd = [_yum(), '--quiet', 'updateinfo', 'list', 'all']
ret = __salt__['cmd.run_stdout'](
cmd,

View File

@ -1,4 +1,4 @@
From 1a98027d94dc7491182a16eef2e6134c2d8423b6 Mon Sep 17 00:00:00 2001
From 666f62917bbc48cbee2ed0aa319a61afd1b1fcb2 Mon Sep 17 00:00:00 2001
From: Bo Maryniuk <bo@suse.de>
Date: Thu, 6 Dec 2018 16:26:23 +0100
Subject: [PATCH] Add hold/unhold functions
@ -11,7 +11,7 @@ Add warnings
1 file changed, 87 insertions(+), 1 deletion(-)
diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py
index 001b852fc4..0c26e2214c 100644
index 50279ccbd1..08a9c2ed4d 100644
--- a/salt/modules/zypperpkg.py
+++ b/salt/modules/zypperpkg.py
@@ -41,6 +41,7 @@ import salt.utils.pkg
@ -22,7 +22,7 @@ index 001b852fc4..0c26e2214c 100644
from salt.utils.versions import LooseVersion
import salt.utils.environment
from salt.exceptions import CommandExecutionError, MinionError, SaltInvocationError
@@ -1742,7 +1743,7 @@ def clean_locks():
@@ -1771,7 +1772,7 @@ def clean_locks():
return out
@ -31,7 +31,7 @@ index 001b852fc4..0c26e2214c 100644
'''
Remove specified package lock.
@@ -1754,7 +1755,47 @@ def remove_lock(packages, **kwargs): # pylint: disable=unused-argument
@@ -1783,7 +1784,47 @@ def remove_lock(packages, **kwargs): # pylint: disable=unused-argument
salt '*' pkg.remove_lock <package1>,<package2>,<package3>
salt '*' pkg.remove_lock pkgs='["foo", "bar"]'
'''
@ -79,7 +79,7 @@ index 001b852fc4..0c26e2214c 100644
locks = list_locks()
try:
packages = list(__salt__['pkg_resource.parse_targets'](packages)[0].keys())
@@ -1775,6 +1816,50 @@ def remove_lock(packages, **kwargs): # pylint: disable=unused-argument
@@ -1804,6 +1845,50 @@ def remove_lock(packages, **kwargs): # pylint: disable=unused-argument
return {'removed': len(removed), 'not_found': missing}
@ -130,7 +130,7 @@ index 001b852fc4..0c26e2214c 100644
def add_lock(packages, **kwargs): # pylint: disable=unused-argument
'''
Add a package lock. Specify packages to lock by exact name.
@@ -1787,6 +1872,7 @@ def add_lock(packages, **kwargs): # pylint: disable=unused-argument
@@ -1816,6 +1901,7 @@ def add_lock(packages, **kwargs): # pylint: disable=unused-argument
salt '*' pkg.add_lock <package1>,<package2>,<package3>
salt '*' pkg.add_lock pkgs='["foo", "bar"]'
'''

View File

@ -0,0 +1,26 @@
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

View File

@ -1,4 +1,4 @@
From 3ae0b949dacc7ac597dc94a5141d2f4c23d6efc5 Mon Sep 17 00:00:00 2001
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
@ -9,7 +9,7 @@ Subject: [PATCH] Add missing 'fun' for returns from wfunc executions
1 file changed, 4 insertions(+)
diff --git a/salt/client/ssh/__init__.py b/salt/client/ssh/__init__.py
index 1453430e73..0df918d634 100644
index 4881540837..1373274739 100644
--- a/salt/client/ssh/__init__.py
+++ b/salt/client/ssh/__init__.py
@@ -682,6 +682,8 @@ class SSH(object):

View File

@ -1,4 +1,4 @@
From ddc5439536e8d7a0b2fca1fcb9db0b18ed961d54 Mon Sep 17 00:00:00 2001
From 0a6b5e92a4a74dee94eb33a939600f8c2e429c01 Mon Sep 17 00:00:00 2001
From: Bo Maryniuk <bo@suse.de>
Date: Fri, 12 Oct 2018 16:20:40 +0200
Subject: [PATCH] Add multi-file support and globbing to the filetree

View File

@ -1,4 +1,4 @@
From 4a8c36db7ece51efdd04caa37c79b0cb6a22ecf6 Mon Sep 17 00:00:00 2001
From ad1323b4f83fa8f2954c0a965f4acaf91575a59b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Thu, 26 Mar 2020 13:08:16 +0000
@ -10,7 +10,7 @@ Subject: [PATCH] Add new custom SUSE capability for saltutil state
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/salt/grains/extra.py b/salt/grains/extra.py
index 4fb58674bf04d44ada1cb1620384aba7d3a76bad..e78cc64e0dedc728cbef68942b8767c526daa1a8 100644
index 1082b05dba7830ee53078cff86b5183b5eea2829..b30ab0091fee7cda8f74b861e9e9f95f8ad85b39 100644
--- a/salt/grains/extra.py
+++ b/salt/grains/extra.py
@@ -80,5 +80,6 @@ def config():

View File

@ -1,27 +0,0 @@
From 27e882ff23e24ec26339503e727e5dec0507b55f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Fri, 24 May 2019 16:27:07 +0100
Subject: [PATCH] Add 'ppc64le' as a valid RPM package architecture
---
salt/utils/pkg/rpm.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/salt/utils/pkg/rpm.py b/salt/utils/pkg/rpm.py
index 828b0cecda..cb85eb99fe 100644
--- a/salt/utils/pkg/rpm.py
+++ b/salt/utils/pkg/rpm.py
@@ -21,7 +21,7 @@ log = logging.getLogger(__name__)
# These arches compiled from the rpmUtils.arch python module source
ARCHES_64 = ('x86_64', 'athlon', 'amd64', 'ia32e', 'ia64', 'geode')
ARCHES_32 = ('i386', 'i486', 'i586', 'i686')
-ARCHES_PPC = ('ppc', 'ppc64', 'ppc64iseries', 'ppc64pseries')
+ARCHES_PPC = ('ppc', 'ppc64', 'ppc64le', 'ppc64iseries', 'ppc64pseries')
ARCHES_S390 = ('s390', 's390x')
ARCHES_SPARC = (
'sparc', 'sparcv8', 'sparcv9', 'sparcv9v', 'sparc64', 'sparc64v'
--
2.16.4

View File

@ -1,4 +1,4 @@
From ee67c569786f5381fa0fb34c64f6796ecef5b21f Mon Sep 17 00:00:00 2001
From 369567107fa18187f8cbc5040728037d0774287b Mon Sep 17 00:00:00 2001
From: Bo Maryniuk <bo@suse.de>
Date: Mon, 12 Mar 2018 12:01:39 +0100
Subject: [PATCH] Add SaltSSH multi-version support across Python
@ -466,7 +466,7 @@ index cd7549a178..95b3931a32 100644
if __name__ == '__main__':
sys.exit(main(sys.argv))
diff --git a/salt/utils/thin.py b/salt/utils/thin.py
index 3c8ffec8af..b6fa90abae 100644
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

View File

@ -1,4 +1,4 @@
From d150fed197f47d17227f1801b29357ab509ebbd4 Mon Sep 17 00:00:00 2001
From 717c9bc6cb81994c5f23de87cfa91112fa7bf89c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Wed, 22 May 2019 13:00:46 +0100

View File

@ -1,4 +1,4 @@
From 4bf9567fd28470085ee501e5e17c75a932b5dde5 Mon Sep 17 00:00:00 2001
From f4388ef82b5053e9996272b182c29a2da21a6258 Mon Sep 17 00:00:00 2001
From: Bo Maryniuk <bo@suse.de>
Date: Fri, 19 Oct 2018 15:44:47 +0200
Subject: [PATCH] Add supportconfig module for remote calls and SaltSSH
@ -267,10 +267,10 @@ index a4343297b6..cbae189aea 100644
archive_path = self.collector.archive_path
diff --git a/salt/loader.py b/salt/loader.py
index 0cff0c72bb..d494c452ed 100644
index 428fb338c9..860162b791 100644
--- a/salt/loader.py
+++ b/salt/loader.py
@@ -1687,8 +1687,10 @@ class LazyLoader(salt.utils.lazy.LazyDict):
@@ -1727,8 +1727,10 @@ class LazyLoader(salt.utils.lazy.LazyDict):
))
for attr in getattr(mod, '__load__', dir(mod)):
@ -671,10 +671,10 @@ index 0000000000..750b2655d6
+
+ return __virtualname__
diff --git a/salt/state.py b/salt/state.py
index dfa9c6de58..c3119b6a33 100644
index 1db1c35c52..bc5277554e 100644
--- a/salt/state.py
+++ b/salt/state.py
@@ -1358,8 +1358,9 @@ class State(object):
@@ -1406,8 +1406,9 @@ class State(object):
names = []
if state.startswith('__'):
continue
@ -686,7 +686,7 @@ index dfa9c6de58..c3119b6a33 100644
if orchestration_jid is not None:
chunk['__orchestration_jid__'] = orchestration_jid
if '__sls__' in body:
@@ -1929,8 +1930,12 @@ class State(object):
@@ -1977,8 +1978,12 @@ class State(object):
ret = self.call_parallel(cdata, low)
else:
self.format_slots(cdata)
@ -701,7 +701,7 @@ index dfa9c6de58..c3119b6a33 100644
self.states.inject_globals = {}
if 'check_cmd' in low and '{0[state]}.mod_run_check_cmd'.format(low) not in self.states:
ret.update(self._run_check_cmd(low))
@@ -2762,10 +2767,31 @@ class State(object):
@@ -2882,10 +2887,31 @@ class State(object):
running.update(errors)
return running
@ -946,7 +946,7 @@ index 0000000000..f245f7f137
+ '''
+ return __virtualname__
diff --git a/salt/utils/args.py b/salt/utils/args.py
index 57dbf5861a..1f4d5d2e0f 100644
index 8cc0f35196..666a502498 100644
--- a/salt/utils/args.py
+++ b/salt/utils/args.py
@@ -20,9 +20,7 @@ import salt.utils.data
@ -970,10 +970,10 @@ index 57dbf5861a..1f4d5d2e0f 100644
aspec = get_function_argspec(fun, is_class_method=is_class_method)
diff --git a/salt/utils/decorators/__init__.py b/salt/utils/decorators/__init__.py
index a6da91447a..7529013a8e 100644
index 45d69072c7..b2abb15425 100644
--- a/salt/utils/decorators/__init__.py
+++ b/salt/utils/decorators/__init__.py
@@ -671,3 +671,27 @@ def ensure_unicode_args(function):
@@ -690,3 +690,27 @@ def ensure_unicode_args(function):
else:
return function(*args, **kwargs)
return wrapped

View File

@ -1,4 +1,4 @@
From fdc0a1f4adc40d9e5b5f7164f750e4580b9cd3f4 Mon Sep 17 00:00:00 2001
From 82ddc9d93f6c0d6bc1e8dc6ebd30d6809d9f4d8f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Bosdonnat?= <cbosdonnat@suse.com>
Date: Thu, 18 Oct 2018 13:32:59 +0200
Subject: [PATCH] Add virt.all_capabilities
@ -15,10 +15,10 @@ virt.all_capabilities call.
2 files changed, 134 insertions(+), 29 deletions(-)
diff --git a/salt/modules/virt.py b/salt/modules/virt.py
index 8d63b6ff4c..195da49296 100644
index a2412bb745..3889238ecd 100644
--- a/salt/modules/virt.py
+++ b/salt/modules/virt.py
@@ -4097,37 +4097,10 @@ def _parse_caps_loader(node):
@@ -4254,37 +4254,10 @@ def _parse_caps_loader(node):
return result
@ -58,7 +58,7 @@ index 8d63b6ff4c..195da49296 100644
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,
@@ -4167,6 +4140,82 @@ def domain_capabilities(emulator=None, arch=None, machine=None, domain=None, **k
@@ -4324,6 +4297,82 @@ def domain_capabilities(emulator=None, arch=None, machine=None, domain=None, **k
return result
@ -142,10 +142,10 @@ index 8d63b6ff4c..195da49296 100644
'''
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
index 6546a0467c..36fcf0d4c0 100644
index 32f4302e5f..94372c6d72 100644
--- a/tests/unit/modules/test_virt.py
+++ b/tests/unit/modules/test_virt.py
@@ -2204,6 +2204,62 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
@@ -2216,6 +2216,62 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
self.assertEqual(expected, caps)

View File

@ -1,123 +0,0 @@
From a5072a8e834127c9633c1af78631dcef6db0e6cb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Bosdonnat?= <cbosdonnat@suse.com>
Date: Mon, 30 Dec 2019 17:28:50 +0100
Subject: [PATCH] Add virt.network_get_xml function
Users may want to see the full XML definition of a network.
Add virt.pool_get_xml function
Users may want to see the full XML definition of a virtual storage pool.
---
salt/modules/virt.py | 48 +++++++++++++++++++++++++++++++++++++++++
tests/unit/modules/test_virt.py | 20 +++++++++++++++++
2 files changed, 68 insertions(+)
diff --git a/salt/modules/virt.py b/salt/modules/virt.py
index 44c7e78ef0..339760ead4 100644
--- a/salt/modules/virt.py
+++ b/salt/modules/virt.py
@@ -4633,6 +4633,30 @@ def network_info(name=None, **kwargs):
return result
+def network_get_xml(name, **kwargs):
+ '''
+ Return the XML definition of a virtual network
+
+ :param name: libvirt network name
+ :param connection: libvirt connection URI, overriding defaults
+ :param username: username to connect with, overriding defaults
+ :param password: password to connect with, overriding defaults
+
+ .. versionadded:: Neon
+
+ CLI Example:
+
+ .. code-block:: bash
+
+ salt '*' virt.network_get_xml default
+ '''
+ conn = __get_conn(**kwargs)
+ try:
+ return conn.networkLookupByName(name).XMLDesc()
+ finally:
+ conn.close()
+
+
def network_start(name, **kwargs):
'''
Start a defined virtual network.
@@ -5377,6 +5401,30 @@ def pool_info(name=None, **kwargs):
return result
+def pool_get_xml(name, **kwargs):
+ '''
+ Return the XML definition of a virtual storage pool
+
+ :param name: libvirt storage pool name
+ :param connection: libvirt connection URI, overriding defaults
+ :param username: username to connect with, overriding defaults
+ :param password: password to connect with, overriding defaults
+
+ .. versionadded:: Neon
+
+ CLI Example:
+
+ .. code-block:: bash
+
+ salt '*' virt.pool_get_xml default
+ '''
+ conn = __get_conn(**kwargs)
+ try:
+ return conn.storagePoolLookupByName(name).XMLDesc()
+ finally:
+ conn.close()
+
+
def pool_start(name, **kwargs):
'''
Start a defined libvirt storage pool.
diff --git a/tests/unit/modules/test_virt.py b/tests/unit/modules/test_virt.py
index 698e1922fc..719f97a724 100644
--- a/tests/unit/modules/test_virt.py
+++ b/tests/unit/modules/test_virt.py
@@ -2404,6 +2404,16 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
net = virt.network_info('foo')
self.assertEqual({}, net)
+ def test_network_get_xml(self):
+ '''
+ Test virt.network_get_xml
+ '''
+ network_mock = MagicMock()
+ network_mock.XMLDesc.return_value = '<net>Raw XML</net>'
+ self.mock_conn.networkLookupByName.return_value = network_mock
+
+ self.assertEqual('<net>Raw XML</net>', virt.network_get_xml('default'))
+
def test_pool(self):
'''
Test virt._gen_pool_xml()
@@ -2806,6 +2816,16 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
}
}, pool)
+ def test_pool_get_xml(self):
+ '''
+ Test virt.pool_get_xml
+ '''
+ pool_mock = MagicMock()
+ pool_mock.XMLDesc.return_value = '<pool>Raw XML</pool>'
+ self.mock_conn.storagePoolLookupByName.return_value = pool_mock
+
+ self.assertEqual('<pool>Raw XML</pool>', virt.pool_get_xml('default'))
+
def test_pool_list_volumes(self):
'''
Test virt.pool_list_volumes
--
2.16.4

View File

@ -1,358 +0,0 @@
From 3bb798795f89e1af5132c6a97ddb0cf414912265 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Bosdonnat?= <cbosdonnat@suse.com>
Date: Fri, 15 Feb 2019 17:28:00 +0100
Subject: [PATCH] Add virt.volume_infos() and virt.volume_delete()
Expose more functions to handle libvirt storage volumes.
virt.volume_infos() expose informations of the volumes, either for one or
all the volumes. Among the provided data, this function exposes the
names of the virtual machines using the volumes of file type.
virt.volume_delete() allows removing a given volume.
---
salt/modules/virt.py | 126 ++++++++++++++++++++++++++
tests/unit/modules/test_virt.py | 195 ++++++++++++++++++++++++++++++++++++++++
2 files changed, 321 insertions(+)
diff --git a/salt/modules/virt.py b/salt/modules/virt.py
index 195da49296..9bb3636bd1 100644
--- a/salt/modules/virt.py
+++ b/salt/modules/virt.py
@@ -4991,3 +4991,129 @@ def pool_list_volumes(name, **kwargs):
return pool.listVolumes()
finally:
conn.close()
+
+
+def _get_storage_vol(conn, pool, vol):
+ '''
+ Helper function getting a storage volume. Will throw a libvirtError
+ if the pool or the volume couldn't be found.
+ '''
+ pool_obj = conn.storagePoolLookupByName(pool)
+ return pool_obj.storageVolLookupByName(vol)
+
+
+def _is_valid_volume(vol):
+ '''
+ Checks whether a volume is valid for further use since those may have disappeared since
+ the last pool refresh.
+ '''
+ try:
+ # Getting info on an invalid volume raises error
+ vol.info()
+ return True
+ except libvirt.libvirtError as err:
+ return False
+
+
+def _get_all_volumes_paths(conn):
+ '''
+ Extract the path and backing stores path of all volumes.
+
+ :param conn: libvirt connection to use
+ '''
+ volumes = [vol for l in [obj.listAllVolumes() for obj in conn.listAllStoragePools()] for vol in l]
+ return {vol.path(): [path.text for path in ElementTree.fromstring(vol.XMLDesc()).findall('.//backingStore/path')]
+ for vol in volumes if _is_valid_volume(vol)}
+
+
+def volume_infos(pool=None, volume=None, **kwargs):
+ '''
+ Provide details on a storage volume. If no volume name is provided, the infos
+ all the volumes contained in the pool are provided. If no pool is provided,
+ the infos of the volumes of all pools are output.
+
+ :param pool: libvirt storage pool name (default: ``None``)
+ :param volume: name of the volume to get infos from (default: ``None``)
+ :param connection: libvirt connection URI, overriding defaults
+ :param username: username to connect with, overriding defaults
+ :param password: password to connect with, overriding defaults
+
+ .. versionadded:: Neon
+
+ CLI Example:
+
+ .. code-block:: bash
+
+ salt "*" virt.volume_infos <pool> <volume>
+ '''
+ result = {}
+ conn = __get_conn(**kwargs)
+ try:
+ backing_stores = _get_all_volumes_paths(conn)
+ disks = {domain.name():
+ {node.get('file') for node
+ in ElementTree.fromstring(domain.XMLDesc(0)).findall('.//disk/source/[@file]')}
+ for domain in _get_domain(conn)}
+
+ def _volume_extract_infos(vol):
+ '''
+ Format the volume info dictionary
+
+ :param vol: the libvirt storage volume object.
+ '''
+ types = ['file', 'block', 'dir', 'network', 'netdir', 'ploop']
+ infos = vol.info()
+
+ # If we have a path, check its use.
+ used_by = []
+ if vol.path():
+ as_backing_store = {path for (path, all_paths) in backing_stores.items() if vol.path() in all_paths}
+ used_by = [vm_name for (vm_name, vm_disks) in disks.items()
+ if vm_disks & as_backing_store or vol.path() in vm_disks]
+
+ return {
+ 'type': types[infos[0]] if infos[0] < len(types) else 'unknown',
+ 'key': vol.key(),
+ 'path': vol.path(),
+ 'capacity': infos[1],
+ 'allocation': infos[2],
+ 'used_by': used_by,
+ }
+
+ pools = [obj for obj in conn.listAllStoragePools() if pool is None or obj.name() == pool]
+ vols = {pool_obj.name(): {vol.name(): _volume_extract_infos(vol)
+ for vol in pool_obj.listAllVolumes()
+ if (volume is None or vol.name() == volume) and _is_valid_volume(vol)}
+ for pool_obj in pools}
+ return {pool_name: volumes for (pool_name, volumes) in vols.items() if volumes}
+ except libvirt.libvirtError as err:
+ log.debug('Silenced libvirt error: %s', str(err))
+ finally:
+ conn.close()
+ return result
+
+
+def volume_delete(pool, volume, **kwargs):
+ '''
+ Delete a libvirt managed volume.
+
+ :param pool: libvirt storage pool name
+ :param volume: name of the volume to delete
+ :param connection: libvirt connection URI, overriding defaults
+ :param username: username to connect with, overriding defaults
+ :param password: password to connect with, overriding defaults
+
+ .. versionadded:: Neon
+
+ CLI Example:
+
+ .. code-block:: bash
+
+ salt "*" virt.volume_delete <pool> <volume>
+ '''
+ conn = __get_conn(**kwargs)
+ try:
+ vol = _get_storage_vol(conn, pool, volume)
+ return not bool(vol.delete())
+ finally:
+ conn.close()
diff --git a/tests/unit/modules/test_virt.py b/tests/unit/modules/test_virt.py
index 36fcf0d4c0..6f9eea241a 100644
--- a/tests/unit/modules/test_virt.py
+++ b/tests/unit/modules/test_virt.py
@@ -2698,3 +2698,198 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
self.mock_conn.storagePoolLookupByName.return_value = mock_pool
# pylint: enable=no-member
self.assertEqual(names, virt.pool_list_volumes('default'))
+
+ def test_volume_infos(self):
+ '''
+ Test virt.volume_infos
+ '''
+ vms_disks = [
+ '''
+ <disk type='file' device='disk'>
+ <driver name='qemu' type='qcow2'/>
+ <source file='/path/to/vol0.qcow2'/>
+ <target dev='vda' bus='virtio'/>
+ </disk>
+ ''',
+ '''
+ <disk type='file' device='disk'>
+ <driver name='qemu' type='qcow2'/>
+ <source file='/path/to/vol3.qcow2'/>
+ <target dev='vda' bus='virtio'/>
+ </disk>
+ ''',
+ '''
+ <disk type='file' device='disk'>
+ <driver name='qemu' type='qcow2'/>
+ <source file='/path/to/vol2.qcow2'/>
+ <target dev='vda' bus='virtio'/>
+ </disk>
+ '''
+ ]
+ mock_vms = []
+ for idx, disk in enumerate(vms_disks):
+ vm = MagicMock()
+ # pylint: disable=no-member
+ vm.name.return_value = 'vm{0}'.format(idx)
+ vm.XMLDesc.return_value = '''
+ <domain type='kvm' id='1'>
+ <name>vm{0}</name>
+ <devices>{1}</devices>
+ </domain>
+ '''.format(idx, disk)
+ # pylint: enable=no-member
+ mock_vms.append(vm)
+
+ mock_pool_data = [
+ {
+ 'name': 'pool0',
+ 'volumes': [
+ {
+ 'key': '/key/of/vol0',
+ 'name': 'vol0',
+ 'path': '/path/to/vol0.qcow2',
+ 'info': [0, 123456789, 123456],
+ 'backingStore': None
+ }
+ ]
+ },
+ {
+ 'name': 'pool1',
+ 'volumes': [
+ {
+ 'key': '/key/of/vol0bad',
+ 'name': 'vol0bad',
+ 'path': '/path/to/vol0bad.qcow2',
+ 'info': None,
+ 'backingStore': None
+ },
+ {
+ 'key': '/key/of/vol1',
+ 'name': 'vol1',
+ 'path': '/path/to/vol1.qcow2',
+ 'info': [0, 12345, 1234],
+ 'backingStore': None
+ },
+ {
+ 'key': '/key/of/vol2',
+ 'name': 'vol2',
+ 'path': '/path/to/vol2.qcow2',
+ 'info': [0, 12345, 1234],
+ 'backingStore': '/path/to/vol0.qcow2'
+ },
+ ],
+ }
+ ]
+ mock_pools = []
+ for pool_data in mock_pool_data:
+ mock_pool = MagicMock()
+ mock_pool.name.return_value = pool_data['name'] # pylint: disable=no-member
+ mock_volumes = []
+ for vol_data in pool_data['volumes']:
+ mock_volume = MagicMock()
+ # pylint: disable=no-member
+ mock_volume.name.return_value = vol_data['name']
+ mock_volume.key.return_value = vol_data['key']
+ mock_volume.path.return_value = '/path/to/{0}.qcow2'.format(vol_data['name'])
+ if vol_data['info']:
+ mock_volume.info.return_value = vol_data['info']
+ backing_store = '''
+ <backingStore>
+ <format>qcow2</format>
+ <path>{0}</path>
+ </backingStore>
+ '''.format(vol_data['backingStore']) if vol_data['backingStore'] else '<backingStore/>'
+ mock_volume.XMLDesc.return_value = '''
+ <volume type='file'>
+ <name>{0}</name>
+ <target>
+ <format>qcow2</format>
+ <path>/path/to/{0}.qcow2</path>
+ </target>
+ {1}
+ </volume>
+ '''.format(vol_data['name'], backing_store)
+ else:
+ mock_volume.info.side_effect = self.mock_libvirt.libvirtError('No such volume')
+ mock_volume.XMLDesc.side_effect = self.mock_libvirt.libvirtError('No such volume')
+ mock_volumes.append(mock_volume)
+ # pylint: enable=no-member
+ mock_pool.listAllVolumes.return_value = mock_volumes # pylint: disable=no-member
+ mock_pools.append(mock_pool)
+
+ self.mock_conn.listAllStoragePools.return_value = mock_pools # pylint: disable=no-member
+
+ with patch('salt.modules.virt._get_domain', MagicMock(return_value=mock_vms)):
+ actual = virt.volume_infos('pool0', 'vol0')
+ self.assertEqual(1, len(actual.keys()))
+ self.assertEqual(1, len(actual['pool0'].keys()))
+ self.assertEqual(['vm0', 'vm2'], sorted(actual['pool0']['vol0']['used_by']))
+ self.assertEqual('/path/to/vol0.qcow2', actual['pool0']['vol0']['path'])
+ self.assertEqual('file', actual['pool0']['vol0']['type'])
+ self.assertEqual('/key/of/vol0', actual['pool0']['vol0']['key'])
+ self.assertEqual(123456789, actual['pool0']['vol0']['capacity'])
+ self.assertEqual(123456, actual['pool0']['vol0']['allocation'])
+
+ self.assertEqual(virt.volume_infos('pool1', None), {
+ 'pool1': {
+ 'vol1': {
+ 'type': 'file',
+ 'key': '/key/of/vol1',
+ 'path': '/path/to/vol1.qcow2',
+ 'capacity': 12345,
+ 'allocation': 1234,
+ 'used_by': [],
+ },
+ 'vol2': {
+ 'type': 'file',
+ 'key': '/key/of/vol2',
+ 'path': '/path/to/vol2.qcow2',
+ 'capacity': 12345,
+ 'allocation': 1234,
+ 'used_by': ['vm2'],
+ }
+ }
+ })
+
+ self.assertEqual(virt.volume_infos(None, 'vol2'), {
+ 'pool1': {
+ 'vol2': {
+ 'type': 'file',
+ 'key': '/key/of/vol2',
+ 'path': '/path/to/vol2.qcow2',
+ 'capacity': 12345,
+ 'allocation': 1234,
+ 'used_by': ['vm2'],
+ }
+ }
+ })
+
+ def test_volume_delete(self):
+ '''
+ Test virt.volume_delete
+ '''
+ mock_delete = MagicMock(side_effect=[0, 1])
+ mock_volume = MagicMock()
+ mock_volume.delete = mock_delete # pylint: disable=no-member
+ mock_pool = MagicMock()
+ # pylint: disable=no-member
+ mock_pool.storageVolLookupByName.side_effect = [
+ mock_volume,
+ mock_volume,
+ self.mock_libvirt.libvirtError("Missing volume"),
+ mock_volume,
+ ]
+ self.mock_conn.storagePoolLookupByName.side_effect = [
+ mock_pool,
+ mock_pool,
+ mock_pool,
+ self.mock_libvirt.libvirtError("Missing pool"),
+ ]
+
+ # pylint: enable=no-member
+ self.assertTrue(virt.volume_delete('default', 'test_volume'))
+ self.assertFalse(virt.volume_delete('default', 'test_volume'))
+ with self.assertRaises(self.mock_libvirt.libvirtError):
+ virt.volume_delete('default', 'missing')
+ virt.volume_delete('missing', 'test_volume')
+ self.assertEqual(mock_delete.call_count, 2)
--
2.16.4

View File

@ -0,0 +1,33 @@
From 2182f2cbc835fee8a95101ce0c722d582b7456aa Mon Sep 17 00:00:00 2001
From: Jochen Breuer <jbreuer@suse.de>
Date: Wed, 1 Apr 2020 16:13:23 +0200
Subject: [PATCH] Adds explicit type cast for port
If a port was passed as a string, the execution logic was broken
and a wrong set of remotes was returned.
The type casting to int solves this issue.
---
salt/utils/network.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/salt/utils/network.py b/salt/utils/network.py
index d6543ff160..def997f3dc 100644
--- a/salt/utils/network.py
+++ b/salt/utils/network.py
@@ -1457,9 +1457,9 @@ def _netlink_tool_remote_on(port, which_end):
local_host, local_port = chunks[3].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) != int(port):
continue
- if which_end == 'local_port' and int(local_port) != port:
+ if which_end == 'local_port' and int(local_port) != int(port):
continue
remotes.add(remote_host.strip("[]"))
--
2.16.4

View File

@ -1,88 +0,0 @@
From 812709918226b98cccdcb388863ce68b6cf076b6 Mon Sep 17 00:00:00 2001
From: Jochen Breuer <jbreuer@suse.de>
Date: Fri, 27 Sep 2019 11:33:47 +0200
Subject: [PATCH] Adds the possibility to also use downloadonly in kwargs
The download_only parameter in the apt module is not in line with
the yum and zypper modules. Both of them use downloadonly without
the underline.
With this change apt now additionally supports the downloadonly
parameter.
Fixes #54790
---
salt/modules/aptpkg.py | 7 ++++---
tests/unit/modules/test_aptpkg.py | 30 ++++++++++++++++++++++++++++++
2 files changed, 34 insertions(+), 3 deletions(-)
diff --git a/salt/modules/aptpkg.py b/salt/modules/aptpkg.py
index a11bb51c16..1a60255a1d 100644
--- a/salt/modules/aptpkg.py
+++ b/salt/modules/aptpkg.py
@@ -1054,8 +1054,9 @@ def upgrade(refresh=True, dist_upgrade=False, **kwargs):
Skip refreshing the package database if refresh has already occurred within
<value> seconds
- download_only
- Only download the packages, don't unpack or install them
+ download_only (or downloadonly)
+ Only download the packages, don't unpack or install them. Use
+ downloadonly to be in line with yum and zypper module.
.. versionadded:: 2018.3.0
@@ -1086,7 +1087,7 @@ def upgrade(refresh=True, dist_upgrade=False, **kwargs):
cmd.append('--force-yes')
if kwargs.get('skip_verify', False):
cmd.append('--allow-unauthenticated')
- if kwargs.get('download_only', False):
+ if kwargs.get('download_only', False) or kwargs.get('downloadonly', False):
cmd.append('--download-only')
cmd.append('dist-upgrade' if dist_upgrade else 'upgrade')
diff --git a/tests/unit/modules/test_aptpkg.py b/tests/unit/modules/test_aptpkg.py
index 85360da181..d3fac5902a 100644
--- a/tests/unit/modules/test_aptpkg.py
+++ b/tests/unit/modules/test_aptpkg.py
@@ -393,6 +393,36 @@ class AptPkgTestCase(TestCase, LoaderModuleMockMixin):
with patch.multiple(aptpkg, **patch_kwargs):
self.assertEqual(aptpkg.upgrade(), dict())
+ def test_upgrade_downloadonly(self):
+ '''
+ Tests the download-only options for upgrade.
+ '''
+ with patch('salt.utils.pkg.clear_rtag', MagicMock()):
+ with patch('salt.modules.aptpkg.list_pkgs',
+ MagicMock(return_value=UNINSTALL)):
+ mock_cmd = MagicMock(return_value={
+ 'retcode': 0,
+ 'stdout': UPGRADE
+ })
+ patch_kwargs = {
+ '__salt__': {
+ 'config.get': MagicMock(return_value=True),
+ 'cmd.run_all': mock_cmd
+ },
+ }
+ with patch.multiple(aptpkg, **patch_kwargs):
+ aptpkg.upgrade()
+ args_matching = [True for args in patch_kwargs['__salt__']['cmd.run_all'].call_args.args if "--download-only" in args]
+ self.assertFalse(any(args_matching))
+
+ aptpkg.upgrade(downloadonly=True)
+ args_matching = [True for args in patch_kwargs['__salt__']['cmd.run_all'].call_args.args if "--download-only" in args]
+ self.assertTrue(any(args_matching))
+
+ aptpkg.upgrade(download_only=True)
+ args_matching = [True for args in patch_kwargs['__salt__']['cmd.run_all'].call_args.args if "--download-only" in args]
+ self.assertTrue(any(args_matching))
+
def test_show(self):
'''
Test that the pkg.show function properly parses apt-cache show output.
--
2.16.4

View File

@ -1,116 +0,0 @@
From d569054ebc63718e62fe5799685b0623910f7e1f Mon Sep 17 00:00:00 2001
From: Cedric Bosdonnat <cbosdonnat@suse.com>
Date: Mon, 9 Dec 2019 17:27:41 +0100
Subject: [PATCH] Align virt full info fixes with upstream (#192)
* Porting PR #52574 to 2019.2.1
* Partly revert 4ce0bc544174fdb00482db4653fb4b0ef411e78b to match upstream's fix
---
salt/modules/virt.py | 12 +++++++-----
tests/unit/modules/test_virt.py | 23 ++++++++++++++++++++++-
2 files changed, 29 insertions(+), 6 deletions(-)
diff --git a/salt/modules/virt.py b/salt/modules/virt.py
index 3abc140a00..5e26964449 100644
--- a/salt/modules/virt.py
+++ b/salt/modules/virt.py
@@ -331,7 +331,7 @@ def _get_uuid(dom):
salt '*' virt.get_uuid <domain>
'''
- return ElementTree.fromstring(dom.XMLDesc(0)).find('uuid').text
+ return ElementTree.fromstring(get_xml(dom)).find('uuid').text
def _get_on_poweroff(dom):
@@ -344,7 +344,7 @@ def _get_on_poweroff(dom):
salt '*' virt.get_on_restart <domain>
'''
- node = ElementTree.fromstring(dom.XMLDesc(0)).find('on_poweroff')
+ node = ElementTree.fromstring(get_xml(dom)).find('on_poweroff')
return node.text if node is not None else ''
@@ -358,7 +358,7 @@ def _get_on_reboot(dom):
salt '*' virt.get_on_reboot <domain>
'''
- node = ElementTree.fromstring(dom.XMLDesc(0)).find('on_reboot')
+ node = ElementTree.fromstring(get_xml(dom)).find('on_reboot')
return node.text if node is not None else ''
@@ -372,7 +372,7 @@ def _get_on_crash(dom):
salt '*' virt.get_on_crash <domain>
'''
- node = ElementTree.fromstring(dom.XMLDesc(0)).find('on_crash')
+ node = ElementTree.fromstring(get_xml(dom)).find('on_crash')
return node.text if node is not None else ''
@@ -2435,7 +2435,9 @@ def get_xml(vm_, **kwargs):
salt '*' virt.get_xml <domain>
'''
conn = __get_conn(**kwargs)
- xml_desc = _get_domain(conn, vm_).XMLDesc(0)
+ xml_desc = vm_.XMLDesc(0) if isinstance(
+ vm_, libvirt.virDomain
+ ) else _get_domain(conn, vm_).XMLDesc(0)
conn.close()
return xml_desc
diff --git a/tests/unit/modules/test_virt.py b/tests/unit/modules/test_virt.py
index b95f51807f..d8efafc063 100644
--- a/tests/unit/modules/test_virt.py
+++ b/tests/unit/modules/test_virt.py
@@ -38,6 +38,10 @@ class LibvirtMock(MagicMock): # pylint: disable=too-many-ancestors
'''
Libvirt library mock
'''
+ class virDomain(MagicMock):
+ '''
+ virDomain mock
+ '''
class libvirtError(Exception):
'''
@@ -76,7 +80,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
Define VM to use in tests
'''
self.mock_conn.listDefinedDomains.return_value = [name] # pylint: disable=no-member
- mock_domain = MagicMock()
+ mock_domain = self.mock_libvirt.virDomain()
self.mock_conn.lookupByName.return_value = mock_domain # pylint: disable=no-member
mock_domain.XMLDesc.return_value = xml # pylint: disable=no-member
@@ -1396,6 +1400,23 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
re.match('^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$',
interface_attrs['mac'], re.I))
+ def test_get_xml(self):
+ '''
+ Test virt.get_xml()
+ '''
+ xml = '''<domain type='kvm' id='7'>
+ <name>test-vm</name>
+ <devices>
+ <graphics type='vnc' port='5900' autoport='yes' listen='0.0.0.0'>
+ <listen type='address' address='0.0.0.0'/>
+ </graphics>
+ </devices>
+ </domain>
+ '''
+ domain = self.set_mock_vm("test-vm", xml)
+ self.assertEqual(xml, virt.get_xml('test-vm'))
+ self.assertEqual(xml, virt.get_xml(domain))
+
def test_parse_qemu_img_info(self):
'''
Make sure that qemu-img info output is properly parsed
--
2.23.0

View File

@ -1,4 +1,4 @@
From eadcab9b1b03041360d27421e5e8204f2a463e61 Mon Sep 17 00:00:00 2001
From 206a2f7c4c1104f2f35dfa2c0b775bef4adc5b91 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Wed, 3 Jul 2019 09:34:50 +0100
@ -12,10 +12,10 @@ Add unit test for pkg.list_downloaded with kwargs
2 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py
index 9d0407e674..6bc7211f59 100644
index 582caffb59..3760b525e7 100644
--- a/salt/modules/zypperpkg.py
+++ b/salt/modules/zypperpkg.py
@@ -2553,7 +2553,7 @@ def download(*packages, **kwargs):
@@ -2557,7 +2557,7 @@ def download(*packages, **kwargs):
)
@ -25,10 +25,10 @@ index 9d0407e674..6bc7211f59 100644
.. versionadded:: 2017.7.0
diff --git a/tests/unit/modules/test_zypperpkg.py b/tests/unit/modules/test_zypperpkg.py
index d2ae06a98e..0a3053680f 100644
index 3a6466f061..12c22bfcb2 100644
--- a/tests/unit/modules/test_zypperpkg.py
+++ b/tests/unit/modules/test_zypperpkg.py
@@ -766,6 +766,33 @@ Repository 'DUMMY' not found by its alias, number, or URI.
@@ -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)

View File

@ -1,4 +1,4 @@
From 41a0d937511356dc75f4f041a08c1458b4e0ccf4 Mon Sep 17 00:00:00 2001
From b8226467e665650a0587b8fd64242faefb805e13 Mon Sep 17 00:00:00 2001
From: Steve Kowalik <steven@wedontsleep.org>
Date: Mon, 17 Feb 2020 15:34:00 +1100
Subject: [PATCH] Apply patch from upstream to support Python 3.8
@ -35,10 +35,10 @@ index e3e678af3b..0f6a9bc012 100644
# requirements/opt.txt (not all)
Recommends: python-MySQL-python
diff --git a/salt/config/__init__.py b/salt/config/__init__.py
index 658128dac0..a372200892 100644
index 0ebe1181dd..f484d94e7e 100644
--- a/salt/config/__init__.py
+++ b/salt/config/__init__.py
@@ -3276,7 +3276,9 @@ def apply_cloud_providers_config(overrides, defaults=None):
@@ -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()):
@ -50,7 +50,7 @@ index 658128dac0..a372200892 100644
if 'extends' not in details:
# Extends resolved or non existing, continue!
diff --git a/salt/grains/core.py b/salt/grains/core.py
index 67e263d37b..0017c0f472 100644
index f410985198..358b66fdb0 100644
--- a/salt/grains/core.py
+++ b/salt/grains/core.py
@@ -40,20 +40,20 @@ except ImportError:
@ -81,7 +81,7 @@ index 67e263d37b..0017c0f472 100644
except ImportError:
from distro import linux_distribution
@@ -1961,7 +1961,7 @@ def os_data():
@@ -1976,7 +1976,7 @@ def os_data():
)
(osname, osrelease, oscodename) = \
[x.strip('"').strip("'") for x in
@ -91,7 +91,7 @@ index 67e263d37b..0017c0f472 100644
# 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
index 8cd0235c99..2ce888d5f3 100644
index cfce9e6926..5c8a8322ed 100644
--- a/salt/renderers/stateconf.py
+++ b/salt/renderers/stateconf.py
@@ -224,10 +224,10 @@ def render(input, saltenv='base', sls='', argline='', **kws):
@ -110,7 +110,7 @@ index 8cd0235c99..2ce888d5f3 100644
tmplctx = {}
diff --git a/tests/unit/modules/test_virt.py b/tests/unit/modules/test_virt.py
index 719f97a724..3079657a9b 100644
index 94372c6d72..d762dcc479 100644
--- a/tests/unit/modules/test_virt.py
+++ b/tests/unit/modules/test_virt.py
@@ -1256,7 +1256,7 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):

View File

@ -1,4 +1,4 @@
From 6dea5186842285588ee02b66701cc91a4a2c4fa9 Mon Sep 17 00:00:00 2001
From 9b47e4497ca16ec3671dd9da838895820ea9b0af Mon Sep 17 00:00:00 2001
From: Mihai Dinca <mdinca@suse.de>
Date: Fri, 16 Nov 2018 17:05:29 +0100
Subject: [PATCH] Async batch implementation
@ -26,20 +26,20 @@ Pass only metadata not all **kwargs
Add separate batch presence_ping timeout
---
salt/auth/__init__.py | 4 +-
salt/cli/batch.py | 91 ++++++--
salt/cli/batch_async.py | 227 +++++++++++++++++++
salt/client/__init__.py | 44 +---
salt/master.py | 25 ++
salt/cli/batch.py | 91 ++++++++--
salt/cli/batch_async.py | 227 ++++++++++++++++++++++++
salt/client/__init__.py | 41 +----
salt/master.py | 25 +++
salt/netapi/__init__.py | 3 +-
salt/transport/ipc.py | 9 +-
salt/transport/ipc.py | 13 +-
salt/utils/event.py | 8 +-
tests/unit/cli/test_batch_async.py | 351 +++++++++++++++++++++++++++++
9 files changed, 703 insertions(+), 59 deletions(-)
tests/unit/cli/test_batch_async.py | 351 +++++++++++++++++++++++++++++++++++++
9 files changed, 703 insertions(+), 60 deletions(-)
create mode 100644 salt/cli/batch_async.py
create mode 100644 tests/unit/cli/test_batch_async.py
diff --git a/salt/auth/__init__.py b/salt/auth/__init__.py
index d43c57338c..e44c94fb37 100644
index ecbd1c808c..ba9dbad509 100644
--- a/salt/auth/__init__.py
+++ b/salt/auth/__init__.py
@@ -52,7 +52,9 @@ AUTH_INTERNAL_KEYWORDS = frozenset([
@ -396,10 +396,10 @@ index 0000000000..3160d46d8b
+ self.event.io_loop.call_later(self.opts['timeout'], self.find_job, set(next_batch))
+ self.active = self.active.union(next_batch)
diff --git a/salt/client/__init__.py b/salt/client/__init__.py
index 6a62e53fdc..8b37422cbf 100644
index 08fbe191d4..3bbc7f9de7 100644
--- a/salt/client/__init__.py
+++ b/salt/client/__init__.py
@@ -531,45 +531,14 @@ class LocalClient(object):
@@ -529,45 +529,14 @@ class LocalClient(object):
{'dave': {...}}
{'stewart': {...}}
'''
@ -450,21 +450,11 @@ index 6a62e53fdc..8b37422cbf 100644
batch = salt.cli.batch.Batch(opts, eauth=eauth, quiet=True)
for ret in batch.run():
yield ret
@@ -1732,7 +1701,8 @@ class LocalClient(object):
if listen and not self.event.connect_pub(timeout=timeout):
raise SaltReqTimeoutError()
payload = channel.send(payload_kwargs, timeout=timeout)
- except SaltReqTimeoutError:
+ except SaltReqTimeoutError as err:
+ log.error(err)
raise SaltReqTimeoutError(
'Salt request timed out. The master is not responding. You '
'may need to run your command with `--async` in order to '
diff --git a/salt/master.py b/salt/master.py
index 606be7319c..ee968410f7 100644
index fb2e0c35bf..5e2277ba76 100644
--- a/salt/master.py
+++ b/salt/master.py
@@ -32,6 +32,7 @@ import tornado.gen # pylint: disable=F0401
@@ -31,6 +31,7 @@ import salt.ext.tornado.gen # pylint: disable=F0401
# Import salt libs
import salt.crypt
@ -511,10 +501,10 @@ index 606be7319c..ee968410f7 100644
if jid is None:
return {'enc': 'clear',
diff --git a/salt/netapi/__init__.py b/salt/netapi/__init__.py
index 95f6384889..43b6e943a7 100644
index 88d550f27f..31a24bb420 100644
--- a/salt/netapi/__init__.py
+++ b/salt/netapi/__init__.py
@@ -88,7 +88,8 @@ class NetapiClient(object):
@@ -93,7 +93,8 @@ class NetapiClient(object):
:return: job ID
'''
local = salt.client.get_local_client(mopts=self.opts)
@ -525,45 +515,48 @@ index 95f6384889..43b6e943a7 100644
def local(self, *args, **kwargs):
'''
diff --git a/salt/transport/ipc.py b/salt/transport/ipc.py
index dbcba18e5c..d0e1639b6e 100644
index 89fb31fb4f..d2b295a633 100644
--- a/salt/transport/ipc.py
+++ b/salt/transport/ipc.py
@@ -615,6 +615,7 @@ class IPCMessageSubscriber(IPCClient):
@@ -618,6 +618,7 @@ class IPCMessageSubscriber(IPCClient):
self._read_stream_future = None
self._saved_data = []
self._read_in_progress = Lock()
+ self.callbacks = set()
@tornado.gen.coroutine
@salt.ext.tornado.gen.coroutine
def _read(self, timeout, callback=None):
@@ -689,8 +690,12 @@ class IPCMessageSubscriber(IPCClient):
@@ -692,8 +693,12 @@ class IPCMessageSubscriber(IPCClient):
return self._saved_data.pop(0)
return self.io_loop.run_sync(lambda: self._read(timeout))
- @salt.ext.tornado.gen.coroutine
- def read_async(self, callback):
+ def __run_callbacks(self, raw):
+ for callback in self.callbacks:
+ self.io_loop.spawn_callback(callback, raw)
+
@tornado.gen.coroutine
- def read_async(self, callback):
+ @tornado.gen.coroutine
+ def read_async(self):
'''
Asynchronously read messages and invoke a callback when they are ready.
@@ -705,7 +710,7 @@ class IPCMessageSubscriber(IPCClient):
except Exception as exc:
@@ -707,8 +712,8 @@ 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, callback)
+ yield tornado.gen.sleep(1)
+ yield self._read(None, self.__run_callbacks)
def close(self):
'''
diff --git a/salt/utils/event.py b/salt/utils/event.py
index 0b877980aa..ad9c85b576 100644
index 0a3074a6f7..19e5db070d 100644
--- a/salt/utils/event.py
+++ b/salt/utils/event.py
@@ -858,6 +858,10 @@ class SaltEvent(object):
@@ -857,6 +857,10 @@ class SaltEvent(object):
# Minion fired a bad retcode, fire an event
self._fire_ret_load_specific_fun(load)
@ -574,7 +567,7 @@ index 0b877980aa..ad9c85b576 100644
def set_event_handler(self, event_handler):
'''
Invoke the event_handler callback each time an event arrives.
@@ -866,8 +870,10 @@ class SaltEvent(object):
@@ -865,8 +869,10 @@ class SaltEvent(object):
if not self.cpub:
self.connect_pub()
@ -584,8 +577,8 @@ index 0b877980aa..ad9c85b576 100644
- return self.subscriber.read_async(event_handler)
+ return self.subscriber.read_async()
# pylint: disable=W1701
def __del__(self):
# skip exceptions in destroy-- since destroy() doesn't cover interpreter
diff --git a/tests/unit/cli/test_batch_async.py b/tests/unit/cli/test_batch_async.py
new file mode 100644
index 0000000000..f65b6a06c3
@ -944,6 +937,6 @@ index 0000000000..f65b6a06c3
+ (self.batch.find_job, {'foo'})
+ )
--
2.23.0
2.16.4

View File

@ -1,4 +1,4 @@
From 47adf8fbd8ff1baeef83b2ba8f525dfd5eaef123 Mon Sep 17 00:00:00 2001
From 638ad2baa04e96f744f97c97f3840151937e8aac Mon Sep 17 00:00:00 2001
From: Hubert Mantel <mantel@suse.de>
Date: Mon, 27 Nov 2017 13:55:13 +0100
Subject: [PATCH] avoid excessive syslogging by watchdog cronjob (#58)

View File

@ -1,4 +1,4 @@
From 58504344b62fd577c0ef9c8d55378ea668a57912 Mon Sep 17 00:00:00 2001
From e45658e074fbf8c038816dc56b86c3daf33d6ebc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Mon, 29 Jul 2019 11:17:53 +0100
@ -11,11 +11,11 @@ Improve error logging when http.query cannot be performed
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/salt/utils/http.py b/salt/utils/http.py
index c75ca73a85..ced01e110f 100644
index dee0563679..c2fdffb266 100644
--- a/salt/utils/http.py
+++ b/salt/utils/http.py
@@ -567,11 +567,13 @@ def query(url,
except tornado.httpclient.HTTPError as exc:
@@ -580,11 +580,13 @@ def query(url,
except salt.ext.tornado.httpclient.HTTPError as exc:
ret['status'] = exc.code
ret['error'] = six.text_type(exc)
+ log.error("Cannot perform 'http.query': {0} - {1}".format(url_full, ret['error']))

View File

@ -1,465 +0,0 @@
From d99badeda9818ba54a3af1d0145c5278fe0edee1 Mon Sep 17 00:00:00 2001
From: Christian McHugh <mchughc@dnb.com>
Date: Wed, 24 Oct 2018 15:49:58 +0100
Subject: [PATCH] Backport "saltutil" state module to 2019.2 codebase
add individual syncers and release note
add individual syncers
adjust state comment output and cleanup tests
---
salt/states/saltutil.py | 311 +++++++++++++++++++++++++++++
tests/unit/states/test_saltutil.py | 121 +++++++++++
2 files changed, 432 insertions(+)
create mode 100644 salt/states/saltutil.py
create mode 100644 tests/unit/states/test_saltutil.py
diff --git a/salt/states/saltutil.py b/salt/states/saltutil.py
new file mode 100644
index 0000000000000000000000000000000000000000..99952a1b7d1b8a70bac940ec083eb75776c146c6
--- /dev/null
+++ b/salt/states/saltutil.py
@@ -0,0 +1,311 @@
+# -*- coding: utf-8 -*-
+'''
+Saltutil State
+==============
+
+This state wraps the saltutil execution modules to make them easier to run
+from a states. Rather than needing to to use ``module.run`` this state allows for
+improved change detection.
+
+ .. versionadded: Neon
+'''
+from __future__ import absolute_import, unicode_literals, print_function
+
+import logging
+
+# Define the module's virtual name
+__virtualname__ = 'saltutil'
+
+log = logging.getLogger(__name__)
+
+
+def __virtual__():
+ '''
+ Named saltutil
+ '''
+ return __virtualname__
+
+
+def _sync_single(name, module, **kwargs):
+ ret = {'name': name, 'changes': {}, 'result': True, 'comment': ''}
+
+ if __opts__['test']:
+ ret['result'] = None
+ ret['comment'] = "saltutil.sync_{0} would have been run".format(module)
+ return ret
+
+ try:
+ sync_status = __salt__['saltutil.sync_{0}'.format(module)](**kwargs)
+ if sync_status:
+ ret['changes'][module] = sync_status
+ ret['comment'] = "Updated {0}.".format(module)
+ except Exception as e:
+ log.error("Failed to run saltutil.sync_%s: %s", module, e)
+ ret['result'] = False
+ ret['comment'] = "Failed to run sync_{0}: {1}".format(module, e)
+ return ret
+
+ if not ret['changes']:
+ ret['comment'] = "No updates to sync"
+
+ return ret
+
+
+def sync_all(name, **kwargs):
+ '''
+ Performs the same task as saltutil.sync_all module
+ See :mod:`saltutil module for full list of options <salt.modules.saltutil>`
+
+ .. code-block:: yaml
+
+ sync_everything:
+ saltutil.sync_all:
+ - refresh: True
+ '''
+ ret = {'name': name, 'changes': {}, 'result': True, 'comment': ''}
+
+ if __opts__['test']:
+ ret['result'] = None
+ ret['comment'] = "saltutil.sync_all would have been run"
+ return ret
+
+ try:
+ sync_status = __salt__['saltutil.sync_all'](**kwargs)
+ for key, value in sync_status.items():
+ if value:
+ ret['changes'][key] = value
+ ret['comment'] = "Sync performed"
+ except Exception as e:
+ log.error("Failed to run saltutil.sync_all: %s", e)
+ ret['result'] = False
+ ret['comment'] = "Failed to run sync_all: {0}".format(e)
+ return ret
+
+ if not ret['changes']:
+ ret['comment'] = "No updates to sync"
+
+ return ret
+
+
+def sync_beacons(name, **kwargs):
+ '''
+ Performs the same task as saltutil.sync_beacons module
+ See :mod:`saltutil module for full list of options <salt.modules.saltutil>`
+
+ .. code-block:: yaml
+
+ sync_everything:
+ saltutil.sync_beacons:
+ - refresh: True
+ '''
+ return _sync_single(name, "beacons", **kwargs)
+
+
+def sync_clouds(name, **kwargs):
+ '''
+ Performs the same task as saltutil.sync_clouds module
+ See :mod:`saltutil module for full list of options <salt.modules.saltutil>`
+
+ .. code-block:: yaml
+
+ sync_everything:
+ saltutil.sync_clouds:
+ - refresh: True
+ '''
+ return _sync_single(name, "clouds", **kwargs)
+
+
+def sync_engines(name, **kwargs):
+ '''
+ Performs the same task as saltutil.sync_engines module
+ See :mod:`saltutil module for full list of options <salt.modules.saltutil>`
+
+ .. code-block:: yaml
+
+ sync_everything:
+ saltutil.sync_engines:
+ - refresh: True
+ '''
+ return _sync_single(name, "engines", **kwargs)
+
+
+def sync_grains(name, **kwargs):
+ '''
+ Performs the same task as saltutil.sync_grains module
+ See :mod:`saltutil module for full list of options <salt.modules.saltutil>`
+
+ .. code-block:: yaml
+
+ sync_everything:
+ saltutil.sync_grains:
+ - refresh: True
+ '''
+ return _sync_single(name, "grains", **kwargs)
+
+
+def sync_log_handlers(name, **kwargs):
+ '''
+ Performs the same task as saltutil.sync_log_handlers module
+ See :mod:`saltutil module for full list of options <salt.modules.saltutil>`
+
+ .. code-block:: yaml
+
+ sync_everything:
+ saltutil.sync_log_handlers:
+ - refresh: True
+ '''
+ return _sync_single(name, "log_handlers", **kwargs)
+
+
+def sync_modules(name, **kwargs):
+ '''
+ Performs the same task as saltutil.sync_modules module
+ See :mod:`saltutil module for full list of options <salt.modules.saltutil>`
+
+ .. code-block:: yaml
+
+ sync_everything:
+ saltutil.sync_modules:
+ - refresh: True
+ '''
+ return _sync_single(name, "modules", **kwargs)
+
+
+def sync_output(name, **kwargs):
+ '''
+ Performs the same task as saltutil.sync_output module
+ See :mod:`saltutil module for full list of options <salt.modules.saltutil>`
+
+ .. code-block:: yaml
+
+ sync_everything:
+ saltutil.sync_output:
+ - refresh: True
+ '''
+ return _sync_single(name, "output", **kwargs)
+
+
+def sync_outputters(name, **kwargs):
+ '''
+ Performs the same task as saltutil.sync_outputters module
+ See :mod:`saltutil module for full list of options <salt.modules.saltutil>`
+
+ .. code-block:: yaml
+
+ sync_everything:
+ saltutil.sync_outputters:
+ - refresh: True
+ '''
+ return _sync_single(name, "outputters", **kwargs)
+
+
+def sync_pillar(name, **kwargs):
+ '''
+ Performs the same task as saltutil.sync_pillar module
+ See :mod:`saltutil module for full list of options <salt.modules.saltutil>`
+
+ .. code-block:: yaml
+
+ sync_everything:
+ saltutil.sync_pillar:
+ - refresh: True
+ '''
+ return _sync_single(name, "pillar", **kwargs)
+
+
+def sync_proxymodules(name, **kwargs):
+ '''
+ Performs the same task as saltutil.sync_proxymodules module
+ See :mod:`saltutil module for full list of options <salt.modules.saltutil>`
+
+ .. code-block:: yaml
+
+ sync_everything:
+ saltutil.sync_proxymodules:
+ - refresh: True
+ '''
+ return _sync_single(name, "proxymodules", **kwargs)
+
+
+def sync_renderers(name, **kwargs):
+ '''
+ Performs the same task as saltutil.sync_renderers module
+ See :mod:`saltutil module for full list of options <salt.modules.saltutil>`
+
+ .. code-block:: yaml
+
+ sync_everything:
+ saltutil.sync_renderers:
+ - refresh: True
+ '''
+ return _sync_single(name, "renderers", **kwargs)
+
+
+def sync_returners(name, **kwargs):
+ '''
+ Performs the same task as saltutil.sync_returners module
+ See :mod:`saltutil module for full list of options <salt.modules.saltutil>`
+
+ .. code-block:: yaml
+
+ sync_everything:
+ saltutil.sync_returners:
+ - refresh: True
+ '''
+ return _sync_single(name, "returners", **kwargs)
+
+
+def sync_sdb(name, **kwargs):
+ '''
+ Performs the same task as saltutil.sync_sdb module
+ See :mod:`saltutil module for full list of options <salt.modules.saltutil>`
+
+ .. code-block:: yaml
+
+ sync_everything:
+ saltutil.sync_sdb:
+ - refresh: True
+ '''
+ return _sync_single(name, "sdb", **kwargs)
+
+
+def sync_states(name, **kwargs):
+ '''
+ Performs the same task as saltutil.sync_states module
+ See :mod:`saltutil module for full list of options <salt.modules.saltutil>`
+
+ .. code-block:: yaml
+
+ sync_everything:
+ saltutil.sync_states:
+ - refresh: True
+ '''
+ return _sync_single(name, "states", **kwargs)
+
+
+def sync_thorium(name, **kwargs):
+ '''
+ Performs the same task as saltutil.sync_thorium module
+ See :mod:`saltutil module for full list of options <salt.modules.saltutil>`
+
+ .. code-block:: yaml
+
+ sync_everything:
+ saltutil.sync_thorium:
+ - refresh: True
+ '''
+ return _sync_single(name, "thorium", **kwargs)
+
+
+def sync_utils(name, **kwargs):
+ '''
+ Performs the same task as saltutil.sync_utils module
+ See :mod:`saltutil module for full list of options <salt.modules.saltutil>`
+
+ .. code-block:: yaml
+
+ sync_everything:
+ saltutil.sync_utils:
+ - refresh: True
+ '''
+ return _sync_single(name, "utils", **kwargs)
diff --git a/tests/unit/states/test_saltutil.py b/tests/unit/states/test_saltutil.py
new file mode 100644
index 0000000000000000000000000000000000000000..707201e9e2d3c285ed497e7f497158907a1834eb
--- /dev/null
+++ b/tests/unit/states/test_saltutil.py
@@ -0,0 +1,121 @@
+# -*- coding: utf-8 -*-
+'''
+ Tests for the saltutil state
+'''
+# Import Python libs
+from __future__ import absolute_import, print_function, unicode_literals
+
+# Import Salt Testing Libs
+from tests.support.mixins import LoaderModuleMockMixin
+from tests.support.unit import skipIf, TestCase
+from tests.support.mock import (
+ NO_MOCK,
+ NO_MOCK_REASON,
+ MagicMock,
+ patch
+)
+
+# Import Salt Libs
+import salt.states.saltutil as saltutil
+
+
+@skipIf(NO_MOCK, NO_MOCK_REASON)
+class Saltutil(TestCase, LoaderModuleMockMixin):
+ '''
+ Test cases for salt.states.saltutil
+ '''
+ def setup_loader_modules(self):
+ return {saltutil: {'__opts__': {'test': False}}}
+
+ def test_saltutil_sync_all_nochange(self):
+ sync_output = {
+ "clouds": [],
+ "engines": [],
+ "grains": [],
+ "beacons": [],
+ "utils": [],
+ "returners": [],
+ "modules": [],
+ "renderers": [],
+ "log_handlers": [],
+ "thorium": [],
+ "states": [],
+ "sdb": [],
+ "proxymodules": [],
+ "output": [],
+ "pillar": []
+ }
+ state_id = 'somename'
+ state_result = {'changes': {},
+ 'comment': 'No updates to sync',
+ 'name': 'somename',
+ 'result': True
+ }
+
+ mock_moduleout = MagicMock(return_value=sync_output)
+ with patch.dict(saltutil.__salt__, {'saltutil.sync_all': mock_moduleout}):
+ result = saltutil.sync_all(state_id, refresh=True)
+ self.assertEqual(result, state_result)
+
+ def test_saltutil_sync_all_test(self):
+ sync_output = {
+ "clouds": [],
+ "engines": [],
+ "grains": [],
+ "beacons": [],
+ "utils": [],
+ "returners": [],
+ "modules": [],
+ "renderers": [],
+ "log_handlers": [],
+ "thorium": [],
+ "states": [],
+ "sdb": [],
+ "proxymodules": [],
+ "output": [],
+ "pillar": []
+ }
+ state_id = 'somename'
+ state_result = {'changes': {},
+ 'comment': 'saltutil.sync_all would have been run',
+ 'name': 'somename',
+ 'result': None
+ }
+
+ mock_moduleout = MagicMock(return_value=sync_output)
+ with patch.dict(saltutil.__salt__, {'saltutil.sync_all': mock_moduleout}):
+ with patch.dict(saltutil.__opts__, {"test": True}):
+ result = saltutil.sync_all(state_id, refresh=True)
+ self.assertEqual(result, state_result)
+
+
+ def test_saltutil_sync_all_change(self):
+ sync_output = {
+ "clouds": [],
+ "engines": [],
+ "grains": [],
+ "beacons": [],
+ "utils": [],
+ "returners": [],
+ "modules": ["modules.file"],
+ "renderers": [],
+ "log_handlers": [],
+ "thorium": [],
+ "states": ["states.saltutil", "states.ssh_auth"],
+ "sdb": [],
+ "proxymodules": [],
+ "output": [],
+ "pillar": []
+ }
+ state_id = 'somename'
+ state_result = {'changes': {'modules': ['modules.file'],
+ 'states': ['states.saltutil', 'states.ssh_auth']},
+ 'comment': 'Sync performed',
+ 'name': 'somename',
+ 'result': True
+ }
+
+ mock_moduleout = MagicMock(return_value=sync_output)
+ with patch.dict(saltutil.__salt__, {'saltutil.sync_all': mock_moduleout}):
+ result = saltutil.sync_all(state_id, refresh=True)
+ self.assertEqual(result, state_result)
--
2.23.0

View File

@ -1,9 +1,9 @@
From cd0e4240e11dfe8a656de1c8d8f1c7f5c6655311 Mon Sep 17 00:00:00 2001
From c5edf396ffd66b6ac1479aa01367aae3eff7683d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Fri, 28 Feb 2020 15:11:53 +0000
Subject: [PATCH] Batch Async: Catch exceptions and safety unregister
and close instances
Subject: [PATCH] Batch Async: Catch exceptions and safety unregister and
close instances
---
salt/cli/batch_async.py | 156 +++++++++++++++++++++++-----------------

View File

@ -1,4 +1,4 @@
From b7e1ff5b0d023fef1f86fa970323dc01bfaabd41 Mon Sep 17 00:00:00 2001
From bbd2e622f7e165a6e16fd5edf5f4596764748208 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Wed, 5 Jun 2019 15:15:04 +0100

View File

@ -1,8 +1,7 @@
From 885940513b7a5c800fcc33dd47f2e92e864ec230 Mon Sep 17 00:00:00 2001
From bd20cd2655a1141fe9ea892e974e40988c3fb83c Mon Sep 17 00:00:00 2001
From: Silvio Moioli <smoioli@suse.de>
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 +-

View File

@ -1,29 +0,0 @@
From 160103e536cfb5c956d64ed13b9c633153fb7a2e Mon Sep 17 00:00:00 2001
From: Bo Maryniuk <bo@suse.de>
Date: Fri, 5 Oct 2018 12:02:08 +0200
Subject: [PATCH] Bugfix: any unicode string of length 16 will raise
TypeError instead of ValueError
---
salt/_compat.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/salt/_compat.py b/salt/_compat.py
index 61842b4bf3..42153f2395 100644
--- a/salt/_compat.py
+++ b/salt/_compat.py
@@ -190,8 +190,8 @@ class IPv6AddressScoped(ipaddress.IPv6Address):
packed = False
if isinstance(data, bytes) and len(data) == 16 and b':' not in data:
try:
- packed = bool(int(binascii.hexlify(data), 16))
- except ValueError:
+ packed = bool(int(str(bytearray(data)).encode('hex'), 16))
+ except (ValueError, TypeError):
pass
return packed
--
2.16.4

View File

@ -1,4 +1,4 @@
From e27ccce1429fa604137df35d8dabbc8016c2b5c9 Mon Sep 17 00:00:00 2001
From 07f5a1d984b5a86c24620503f5e373ea0f11484a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Fri, 12 Apr 2019 16:47:03 +0100
@ -11,7 +11,7 @@ Fix pylint issue
1 file changed, 26 insertions(+), 5 deletions(-)
diff --git a/salt/grains/core.py b/salt/grains/core.py
index 7d75d48bb5..ac66a437fd 100644
index 309e4c9c4a..4600f055dd 100644
--- a/salt/grains/core.py
+++ b/salt/grains/core.py
@@ -20,12 +20,15 @@ import platform
@ -30,7 +30,7 @@ index 7d75d48bb5..ac66a437fd 100644
# pylint: disable=import-error
try:
import dateutil.tz
@@ -2255,13 +2258,10 @@ def fqdns():
@@ -2275,13 +2278,10 @@ def fqdns():
grains = {}
fqdns = set()
@ -44,9 +44,9 @@ index 7d75d48bb5..ac66a437fd 100644
- fqdns.update([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:
if err.errno == 0:
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.
@@ -2271,6 +2271,27 @@ def fqdns():
@@ -2291,6 +2291,27 @@ def fqdns():
except (socket.error, socket.gaierror, socket.timeout) as err:
log.error(err_message, ip, err)

View File

@ -0,0 +1,274 @@
From 0cf1a655aa9353b22ae011e492a33aa52d780f83 Mon Sep 17 00:00:00 2001
From: Jochen Breuer <jbreuer@suse.de>
Date: Tue, 10 Mar 2020 14:02:17 +0100
Subject: [PATCH] Changed imports to vendored Tornado
---
salt/cli/batch_async.py | 26 ++++++++++++------------
salt/master.py | 2 +-
salt/transport/ipc.py | 4 ++--
tests/unit/cli/test_batch_async.py | 32 +++++++++++++++---------------
4 files changed, 32 insertions(+), 32 deletions(-)
diff --git a/salt/cli/batch_async.py b/salt/cli/batch_async.py
index b8f272ed67..08eeb34f1c 100644
--- a/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
# Import python libs
from __future__ import absolute_import, print_function, unicode_literals
import gc
-import tornado
+import salt.ext.tornado
# Import salt libs
import salt.client
@@ -50,7 +50,7 @@ class BatchAsync(object):
}
'''
def __init__(self, parent_opts, jid_gen, clear_load):
- ioloop = 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)
if 'gather_job_timeout' in clear_load['kwargs']:
clear_load['gather_job_timeout'] = clear_load['kwargs'].pop('gather_job_timeout')
@@ -152,7 +152,7 @@ class BatchAsync(object):
self.find_job_returned = self.find_job_returned.difference(running)
self.event.io_loop.spawn_callback(self.find_job, running)
- @tornado.gen.coroutine
+ @salt.ext.tornado.gen.coroutine
def find_job(self, minions):
if self.event:
not_done = minions.difference(self.done_minions).difference(self.timedout_minions)
@@ -170,7 +170,7 @@ class BatchAsync(object):
gather_job_timeout=self.opts['gather_job_timeout'],
jid=jid,
**self.eauth)
- yield tornado.gen.sleep(self.opts['gather_job_timeout'])
+ yield salt.ext.tornado.gen.sleep(self.opts['gather_job_timeout'])
if self.event:
self.event.io_loop.spawn_callback(
self.check_find_job,
@@ -180,7 +180,7 @@ class BatchAsync(object):
log.error("Exception occured handling batch async: {}. Aborting execution.".format(ex))
self.close_safe()
- @tornado.gen.coroutine
+ @salt.ext.tornado.gen.coroutine
def start(self):
if self.event:
self.__set_event_handler()
@@ -198,11 +198,11 @@ class BatchAsync(object):
**self.eauth)
self.targeted_minions = set(ping_return['minions'])
#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 salt.ext.tornado.gen.sleep(self.batch_presence_ping_timeout or self.opts['gather_job_timeout'])
if self.event:
self.event.io_loop.spawn_callback(self.start_batch)
- @tornado.gen.coroutine
+ @salt.ext.tornado.gen.coroutine
def start_batch(self):
if not self.initialized:
self.batch_size = get_bnum(self.opts, self.minions, True)
@@ -216,7 +216,7 @@ class BatchAsync(object):
if self.event:
self.event.io_loop.spawn_callback(self.run_next)
- @tornado.gen.coroutine
+ @salt.ext.tornado.gen.coroutine
def end_batch(self):
left = self.minions.symmetric_difference(self.done_minions.union(self.timedout_minions))
if not left and not self.ended:
@@ -232,7 +232,7 @@ class BatchAsync(object):
# release to the IOLoop to allow the event to be published
# before closing batch async execution
- yield tornado.gen.sleep(1)
+ yield salt.ext.tornado.gen.sleep(1)
self.close_safe()
def close_safe(self):
@@ -245,16 +245,16 @@ class BatchAsync(object):
del self
gc.collect()
- @tornado.gen.coroutine
+ @salt.ext.tornado.gen.coroutine
def schedule_next(self):
if not self.scheduled:
self.scheduled = True
# call later so that we maybe gather more returns
- yield tornado.gen.sleep(self.batch_delay)
+ yield salt.ext.tornado.gen.sleep(self.batch_delay)
if self.event:
self.event.io_loop.spawn_callback(self.run_next)
- @tornado.gen.coroutine
+ @salt.ext.tornado.gen.coroutine
def run_next(self):
self.scheduled = False
next_batch = self._get_next()
@@ -272,7 +272,7 @@ class BatchAsync(object):
jid=self.batch_jid,
metadata=self.metadata)
- yield 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
if self.event:
diff --git a/salt/master.py b/salt/master.py
index 3abf7ae60b..3a9d12999d 100644
--- a/salt/master.py
+++ b/salt/master.py
@@ -2049,7 +2049,7 @@ class ClearFuncs(object):
functools.partial(self._prep_jid, clear_load, {}),
batch_load
)
- ioloop = tornado.ioloop.IOLoop.current()
+ ioloop = salt.ext.tornado.ioloop.IOLoop.current()
ioloop.add_callback(batch.start)
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
index e1ce60859b..635dc689a8 100644
--- a/tests/unit/cli/test_batch_async.py
+++ b/tests/unit/cli/test_batch_async.py
@@ -5,8 +5,8 @@ from __future__ import absolute_import
# Import Salt Libs
from salt.cli.batch_async import BatchAsync
-import tornado
-from tornado.testing import AsyncTestCase
+import salt.ext.tornado
+from salt.ext.tornado.testing import AsyncTestCase
from tests.support.unit import skipIf, TestCase
from tests.support.mock import MagicMock, patch, NO_MOCK, NO_MOCK_REASON
@@ -59,10 +59,10 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
self.batch.start_batch()
self.assertEqual(self.batch.batch_size, 2)
- @tornado.testing.gen_test
+ @salt.ext.tornado.testing.gen_test
def test_batch_start_on_batch_presence_ping_timeout(self):
self.batch.event = MagicMock()
- future = tornado.gen.Future()
+ future = salt.ext.tornado.gen.Future()
future.set_result({'minions': ['foo', 'bar']})
self.batch.local.run_job_async.return_value = future
ret = self.batch.start()
@@ -78,10 +78,10 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
# assert targeted_minions == all minions matched by tgt
self.assertEqual(self.batch.targeted_minions, set(['foo', 'bar']))
- @tornado.testing.gen_test
+ @salt.ext.tornado.testing.gen_test
def test_batch_start_on_gather_job_timeout(self):
self.batch.event = MagicMock()
- future = tornado.gen.Future()
+ future = salt.ext.tornado.gen.Future()
future.set_result({'minions': ['foo', 'bar']})
self.batch.local.run_job_async.return_value = future
self.batch.batch_presence_ping_timeout = None
@@ -109,7 +109,7 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
)
)
- @tornado.testing.gen_test
+ @salt.ext.tornado.testing.gen_test
def test_start_batch_calls_next(self):
self.batch.run_next = MagicMock(return_value=MagicMock())
self.batch.event = MagicMock()
@@ -165,14 +165,14 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
self.assertEqual(
len(event.remove_event_handler.mock_calls), 1)
- @tornado.testing.gen_test
+ @salt.ext.tornado.testing.gen_test
def test_batch_next(self):
self.batch.event = MagicMock()
self.batch.opts['fun'] = 'my.fun'
self.batch.opts['arg'] = []
self.batch._get_next = MagicMock(return_value={'foo', 'bar'})
self.batch.batch_size = 2
- future = tornado.gen.Future()
+ future = salt.ext.tornado.gen.Future()
future.set_result({'minions': ['foo', 'bar']})
self.batch.local.run_job_async.return_value = future
self.batch.run_next()
@@ -284,38 +284,38 @@ class AsyncBatchTestCase(AsyncTestCase, TestCase):
self.batch._BatchAsync__event_handler(MagicMock())
self.assertEqual(self.batch.find_job_returned, {'foo'})
- @tornado.testing.gen_test
+ @salt.ext.tornado.testing.gen_test
def test_batch_run_next_end_batch_when_no_next(self):
self.batch.end_batch = MagicMock()
self.batch._get_next = MagicMock(return_value={})
self.batch.run_next()
self.assertEqual(len(self.batch.end_batch.mock_calls), 1)
- @tornado.testing.gen_test
+ @salt.ext.tornado.testing.gen_test
def test_batch_find_job(self):
self.batch.event = MagicMock()
- future = tornado.gen.Future()
+ future = salt.ext.tornado.gen.Future()
future.set_result({})
self.batch.local.run_job_async.return_value = future
self.batch.minions = set(['foo', 'bar'])
self.batch.jid_gen = MagicMock(return_value="1234")
- tornado.gen.sleep = MagicMock(return_value=future)
+ salt.ext.tornado.gen.sleep = MagicMock(return_value=future)
self.batch.find_job({'foo', 'bar'})
self.assertEqual(
self.batch.event.io_loop.spawn_callback.call_args[0],
(self.batch.check_find_job, {'foo', 'bar'}, "1234")
)
- @tornado.testing.gen_test
+ @salt.ext.tornado.testing.gen_test
def test_batch_find_job_with_done_minions(self):
self.batch.done_minions = {'bar'}
self.batch.event = MagicMock()
- future = tornado.gen.Future()
+ future = salt.ext.tornado.gen.Future()
future.set_result({})
self.batch.local.run_job_async.return_value = future
self.batch.minions = set(['foo', 'bar'])
self.batch.jid_gen = MagicMock(return_value="1234")
- tornado.gen.sleep = MagicMock(return_value=future)
+ salt.ext.tornado.gen.sleep = MagicMock(return_value=future)
self.batch.find_job({'foo', 'bar'})
self.assertEqual(
self.batch.event.io_loop.spawn_callback.call_args[0],
--
2.23.0

View File

@ -1,35 +0,0 @@
From d1e016a5deb8f79adc8473b02171b5661cb93ea8 Mon Sep 17 00:00:00 2001
From: Jochen Breuer <jbreuer@suse.de>
Date: Tue, 9 Apr 2019 16:32:46 +0200
Subject: [PATCH] Checking for jid before returning data
Seems raw can have returns for the same minion, but an other job. In
order to not return resutls from the wrong job, we need to check for the
jid.
---
salt/client/__init__.py | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/salt/client/__init__.py b/salt/client/__init__.py
index 8b37422cbf..aff354a021 100644
--- a/salt/client/__init__.py
+++ b/salt/client/__init__.py
@@ -1560,8 +1560,12 @@ class LocalClient(object):
if 'minions' in raw.get('data', {}):
continue
try:
- found.add(raw['id'])
- ret = {raw['id']: {'ret': raw['return']}}
+ # There might be two jobs for the same minion, so we have to check for the jid
+ if jid == raw['jid']:
+ found.add(raw['id'])
+ ret = {raw['id']: {'ret': raw['return']}}
+ else:
+ continue
except KeyError:
# Ignore other erroneous messages
continue
--
2.16.4

View File

@ -1,4 +1,4 @@
From f7ae2b3ebe7d78ca60ada7fd2bb30f3cdbd75427 Mon Sep 17 00:00:00 2001
From 068eecfba4b2a14b334ff17a295d4005d17491f3 Mon Sep 17 00:00:00 2001
From: Bo Maryniuk <bo@suse.de>
Date: Tue, 20 Nov 2018 16:06:31 +0100
Subject: [PATCH] Debian info_installed compatibility (#50453)
@ -51,15 +51,15 @@ Fix wrong Git merge: missing function signature
---
salt/modules/aptpkg.py | 20 ++++-
salt/modules/dpkg_lowpkg.py | 93 +++++++++++++++++---
tests/unit/modules/test_aptpkg.py | 151 +++++++++++++++++++++------------
tests/unit/modules/test_dpkg_lowpkg.py | 69 +++++++++++++++
4 files changed, 267 insertions(+), 66 deletions(-)
tests/unit/modules/test_aptpkg.py | 153 +++++++++++++++++++++------------
tests/unit/modules/test_dpkg_lowpkg.py | 127 ++++++++++++++-------------
4 files changed, 263 insertions(+), 130 deletions(-)
diff --git a/salt/modules/aptpkg.py b/salt/modules/aptpkg.py
index 6b3a921a82..64620647c2 100644
index 8f4d95a195..4ec9158476 100644
--- a/salt/modules/aptpkg.py
+++ b/salt/modules/aptpkg.py
@@ -2776,6 +2776,15 @@ def info_installed(*names, **kwargs):
@@ -2825,6 +2825,15 @@ def info_installed(*names, **kwargs):
.. versionadded:: 2016.11.3
@ -75,7 +75,7 @@ index 6b3a921a82..64620647c2 100644
CLI example:
.. code-block:: bash
@@ -2786,11 +2795,15 @@ def info_installed(*names, **kwargs):
@@ -2835,11 +2844,15 @@ def info_installed(*names, **kwargs):
'''
kwargs = salt.utils.args.clean_kwargs(**kwargs)
failhard = kwargs.pop('failhard', True)
@ -90,9 +90,9 @@ index 6b3a921a82..64620647c2 100644
- for pkg_name, pkg_nfo in __salt__['lowpkg.info'](*names, failhard=failhard).items():
+ for pkg_name, pkg_nfo in __salt__['lowpkg.info'](*names, failhard=failhard, attr=attr).items():
t_nfo = dict()
# Translate dpkg-specific keys to a common structure
for key, value in pkg_nfo.items():
@@ -2807,7 +2820,10 @@ def info_installed(*names, **kwargs):
if pkg_nfo.get('status', 'ii')[1] != 'i':
continue # return only packages that are really installed
@@ -2860,7 +2873,10 @@ def info_installed(*names, **kwargs):
else:
t_nfo[key] = value
@ -105,7 +105,7 @@ index 6b3a921a82..64620647c2 100644
return ret
diff --git a/salt/modules/dpkg_lowpkg.py b/salt/modules/dpkg_lowpkg.py
index 03be5f821a..26ca5dcf5a 100644
index 4ac8efd2f2..b78e844830 100644
--- a/salt/modules/dpkg_lowpkg.py
+++ b/salt/modules/dpkg_lowpkg.py
@@ -252,6 +252,38 @@ def file_dict(*packages):
@ -156,7 +156,7 @@ index 03be5f821a..26ca5dcf5a 100644
"maintainer:${Maintainer}\\n" \
"summary:${Summary}\\n" \
"source:${source:Package}\\n" \
@@ -307,9 +339,14 @@ def _get_pkg_info(*packages, **kwargs):
@@ -308,9 +340,14 @@ def _get_pkg_info(*packages, **kwargs):
key, value = pkg_info_line.split(":", 1)
if value:
pkg_data[key] = value
@ -174,7 +174,7 @@ index 03be5f821a..26ca5dcf5a 100644
pkg_data['description'] = pkg_descr.split(":", 1)[-1]
ret.append(pkg_data)
@@ -335,19 +372,32 @@ def _get_pkg_license(pkg):
@@ -336,19 +373,32 @@ def _get_pkg_license(pkg):
return ", ".join(sorted(licenses))
@ -213,7 +213,7 @@ index 03be5f821a..26ca5dcf5a 100644
def _get_pkg_ds_avail():
@@ -397,6 +447,15 @@ def info(*packages, **kwargs):
@@ -398,6 +448,15 @@ def info(*packages, **kwargs):
.. versionadded:: 2016.11.3
@ -229,7 +229,7 @@ index 03be5f821a..26ca5dcf5a 100644
CLI example:
.. code-block:: bash
@@ -411,6 +470,10 @@ def info(*packages, **kwargs):
@@ -412,6 +471,10 @@ def info(*packages, **kwargs):
kwargs = salt.utils.args.clean_kwargs(**kwargs)
failhard = kwargs.pop('failhard', True)
@ -240,7 +240,7 @@ index 03be5f821a..26ca5dcf5a 100644
if kwargs:
salt.utils.args.invalid_kwargs(kwargs)
@@ -430,6 +493,14 @@ def info(*packages, **kwargs):
@@ -431,6 +494,14 @@ def info(*packages, **kwargs):
lic = _get_pkg_license(pkg['package'])
if lic:
pkg['license'] = lic
@ -257,10 +257,10 @@ index 03be5f821a..26ca5dcf5a 100644
return ret
diff --git a/tests/unit/modules/test_aptpkg.py b/tests/unit/modules/test_aptpkg.py
index 1e963ee5db..580b840197 100644
index e1b6602df5..10e960f090 100644
--- a/tests/unit/modules/test_aptpkg.py
+++ b/tests/unit/modules/test_aptpkg.py
@@ -20,6 +20,8 @@ from tests.support.mock import Mock, MagicMock, patch, NO_MOCK, NO_MOCK_REASON
@@ -20,6 +20,8 @@ from tests.support.mock import Mock, MagicMock, patch
from salt.ext import six
from salt.exceptions import CommandExecutionError, SaltInvocationError
import salt.modules.aptpkg as aptpkg
@ -269,7 +269,7 @@ index 1e963ee5db..580b840197 100644
try:
import pytest
@@ -148,51 +150,39 @@ class AptPkgTestCase(TestCase, LoaderModuleMockMixin):
@@ -166,51 +168,39 @@ class AptPkgTestCase(TestCase, LoaderModuleMockMixin):
def setup_loader_modules(self):
return {aptpkg: {}}
@ -334,7 +334,7 @@ index 1e963ee5db..580b840197 100644
def test_get_repo_keys(self):
'''
@@ -205,35 +195,31 @@ class AptPkgTestCase(TestCase, LoaderModuleMockMixin):
@@ -223,35 +213,31 @@ class AptPkgTestCase(TestCase, LoaderModuleMockMixin):
with patch.dict(aptpkg.__salt__, {'cmd.run_all': mock}):
self.assertEqual(aptpkg.get_repo_keys(), REPO_KEYS)
@ -381,13 +381,15 @@ index 1e963ee5db..580b840197 100644
def test_info_installed(self):
'''
Test - Return the information of the named package(s) installed on the system.
@@ -249,19 +235,72 @@ class AptPkgTestCase(TestCase, LoaderModuleMockMixin):
@@ -267,21 +253,72 @@ class AptPkgTestCase(TestCase, LoaderModuleMockMixin):
if installed['wget'].get(names[name], False):
installed['wget'][name] = installed['wget'].pop(names[name])
- mock = MagicMock(return_value=LOWPKG_INFO)
- with patch.dict(aptpkg.__salt__, {'lowpkg.info': mock}):
- del installed['wget']['status']
- self.assertEqual(aptpkg.info_installed('wget'), installed)
- self.assertEqual(len(aptpkg.info_installed()), 1)
+ assert aptpkg.info_installed('wget') == installed
+
+ @patch('salt.modules.aptpkg.__salt__', {'lowpkg.info': MagicMock(return_value=LOWPKG_INFO)})
@ -461,7 +463,7 @@ index 1e963ee5db..580b840197 100644
def test_refresh_db(self):
'''
Test - Updates the APT database to latest packages based upon repositories.
@@ -281,6 +320,10 @@ class AptPkgTestCase(TestCase, LoaderModuleMockMixin):
@@ -301,6 +338,10 @@ class AptPkgTestCase(TestCase, LoaderModuleMockMixin):
with patch.dict(aptpkg.__salt__, {'cmd.run_all': mock, 'config.get': MagicMock(return_value=False)}):
self.assertEqual(aptpkg.refresh_db(), refresh_db)
@ -472,7 +474,7 @@ index 1e963ee5db..580b840197 100644
def test_refresh_db_failed(self):
'''
Test - Update the APT database using unreachable repositories.
@@ -312,22 +355,24 @@ class AptPkgTestCase(TestCase, LoaderModuleMockMixin):
@@ -332,22 +373,24 @@ class AptPkgTestCase(TestCase, LoaderModuleMockMixin):
assert aptpkg.autoremove(list_only=True) == []
assert aptpkg.autoremove(list_only=True, purge=True) == []
@ -504,10 +506,10 @@ index 1e963ee5db..580b840197 100644
'''
Test - Upgrades all packages.
diff --git a/tests/unit/modules/test_dpkg_lowpkg.py b/tests/unit/modules/test_dpkg_lowpkg.py
index bdcb7eec89..d16ce3cc1a 100644
index 6c07a75417..a0b3346f9d 100644
--- a/tests/unit/modules/test_dpkg_lowpkg.py
+++ b/tests/unit/modules/test_dpkg_lowpkg.py
@@ -25,6 +25,30 @@ class DpkgTestCase(TestCase, LoaderModuleMockMixin):
@@ -23,6 +23,30 @@ class DpkgTestCase(TestCase, LoaderModuleMockMixin):
'''
Test cases for salt.modules.dpkg
'''
@ -538,19 +540,80 @@ index bdcb7eec89..d16ce3cc1a 100644
def setup_loader_modules(self):
return {dpkg: {}}
@@ -102,3 +126,48 @@ class DpkgTestCase(TestCase, LoaderModuleMockMixin):
'stdout': 'Salt'})
@@ -101,68 +125,47 @@ class DpkgTestCase(TestCase, LoaderModuleMockMixin):
with patch.dict(dpkg.__salt__, {'cmd.run_all': mock}):
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_info', MagicMock(return_value=pkgs_info))
+ @patch('salt.modules.dpkg._get_pkg_license', MagicMock(return_value='BSD v3'))
+ def test_info(self):
+ '''
def test_info(self):
'''
- Test package info
+ Test info
+ :return:
+ '''
'''
- mock = MagicMock(return_value={'retcode': 0,
- 'stderr': '',
- 'stdout':
- os.linesep.join([
- 'package:bash',
- 'revision:',
- 'architecture:amd64',
- 'maintainer:Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>',
- 'summary:',
- 'source:bash',
- 'version:4.4.18-2ubuntu1',
- 'section:shells',
- 'installed_size:1588',
- 'size:',
- 'MD5:',
- 'SHA1:',
- 'SHA256:',
- 'origin:',
- 'homepage:http://tiswww.case.edu/php/chet/bash/bashtop.html',
- 'status:ii ',
- '======',
- 'description:GNU Bourne Again SHell',
- ' Bash is an sh-compatible command language interpreter that executes',
- ' commands read from the standard input or from a file. Bash also',
- ' incorporates useful features from the Korn and C shells (ksh and csh).',
- ' .',
- ' Bash is ultimately intended to be a conformant implementation of the',
- ' IEEE POSIX Shell and Tools specification (IEEE Working Group 1003.2).',
- ' .',
- ' The Programmable Completion Code, by Ian Macdonald, is now found in',
- ' the bash-completion package.',
- '------'
- ])})
-
- with patch.dict(dpkg.__salt__, {'cmd.run_all': mock}), \
- patch.dict(dpkg.__grains__, {'os': 'Ubuntu', 'osrelease_info': (18, 4)}), \
- patch('salt.utils.path.which', MagicMock(return_value=False)), \
- patch('os.path.exists', MagicMock(return_value=False)),\
- patch('os.path.getmtime', MagicMock(return_value=1560199259.0)):
- self.assertDictEqual(dpkg.info('bash'),
- {'bash': {'architecture': 'amd64',
- 'description': os.linesep.join([
- 'GNU Bourne Again SHell',
- ' Bash is an sh-compatible command language interpreter that executes',
- ' commands read from the standard input or from a file. Bash also',
- ' incorporates useful features from the Korn and C shells (ksh and csh).',
- ' .',
- ' Bash is ultimately intended to be a conformant implementation of the',
- ' IEEE POSIX Shell and Tools specification (IEEE Working Group 1003.2).',
- ' .',
- ' The Programmable Completion Code, by Ian Macdonald, is now found in',
- ' the bash-completion package.' + os.linesep
- ]),
- 'homepage': 'http://tiswww.case.edu/php/chet/bash/bashtop.html',
- 'maintainer': 'Ubuntu Developers '
- '<ubuntu-devel-discuss@lists.ubuntu.com>',
- 'package': 'bash',
- 'section': 'shells',
- 'source': 'bash',
- 'status': 'ii',
- 'version': '4.4.18-2ubuntu1'}})
+ ret = dpkg.info('emacs')
+
+ assert isinstance(ret, dict)

View File

@ -1,4 +1,4 @@
From 263c8c98a5601179a53c00523a1579883e705f1f Mon Sep 17 00:00:00 2001
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
@ -8,10 +8,10 @@ Subject: [PATCH] Decide if the source should be actually skipped
1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/salt/modules/aptpkg.py b/salt/modules/aptpkg.py
index 64620647c2..4a331444c9 100644
index 4ec9158476..3b0d8423db 100644
--- a/salt/modules/aptpkg.py
+++ b/salt/modules/aptpkg.py
@@ -1574,6 +1574,27 @@ def list_repo_pkgs(*args, **kwargs): # pylint: disable=unused-import
@@ -1620,6 +1620,27 @@ def list_repo_pkgs(*args, **kwargs): # pylint: disable=unused-import
return ret
@ -39,7 +39,7 @@ index 64620647c2..4a331444c9 100644
def list_repos():
'''
Lists all repos in the sources.list (and sources.lists.d) files
@@ -1589,7 +1610,7 @@ def list_repos():
@@ -1635,7 +1656,7 @@ def list_repos():
repos = {}
sources = sourceslist.SourcesList()
for source in sources.list:

View File

@ -1,4 +1,4 @@
From a8f289c4eb03c051d8ffc60eed28985f3b49d921 Mon Sep 17 00:00:00 2001
From f81a5b92d691c1d511a814f9344104dd37466bc3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Wed, 29 May 2019 11:03:16 +0100
@ -6,51 +6,14 @@ Subject: [PATCH] Do not break repo files with multiple line values on
yumpkg (bsc#1135360)
---
salt/modules/yumpkg.py | 16 +++++++++---
tests/integration/modules/test_pkg.py | 48 +++++++++++++++++++++++++++++++++++
2 files changed, 60 insertions(+), 4 deletions(-)
1 file changed, 48 insertions(+)
diff --git a/salt/modules/yumpkg.py b/salt/modules/yumpkg.py
index 5ec3835574..3a4fe47a45 100644
--- a/salt/modules/yumpkg.py
+++ b/salt/modules/yumpkg.py
@@ -2763,7 +2763,12 @@ def del_repo(repo, basedir=None, **kwargs): # pylint: disable=W0613
del filerepos[stanza]['comments']
content += '\n[{0}]'.format(stanza)
for line in filerepos[stanza]:
- content += '\n{0}={1}'.format(line, filerepos[stanza][line])
+ # A whitespace is needed at the begining of the new line in order
+ # to avoid breaking multiple line values allowed on repo files.
+ value = filerepos[stanza][line]
+ if isinstance(value, six.string_types) and '\n' in value:
+ value = '\n '.join(value.split('\n'))
+ content += '\n{0}={1}'.format(line, value)
content += '\n{0}\n'.format(comments)
with salt.utils.files.fopen(repofile, 'w') as fileout:
@@ -2898,11 +2903,14 @@ def mod_repo(repo, basedir=None, **kwargs):
)
content += '[{0}]\n'.format(stanza)
for line in six.iterkeys(filerepos[stanza]):
+ # A whitespace is needed at the begining of the new line in order
+ # to avoid breaking multiple line values allowed on repo files.
+ value = filerepos[stanza][line]
+ if isinstance(value, six.string_types) and '\n' in value:
+ value = '\n '.join(value.split('\n'))
content += '{0}={1}\n'.format(
line,
- filerepos[stanza][line]
- if not isinstance(filerepos[stanza][line], bool)
- else _bool_to_str(filerepos[stanza][line])
+ value if not isinstance(value, bool) else _bool_to_str(value)
)
content += comments + '\n'
diff --git a/tests/integration/modules/test_pkg.py b/tests/integration/modules/test_pkg.py
index 66ac3cfb61..7204428eca 100644
index e8374db2c0..61748f9477 100644
--- a/tests/integration/modules/test_pkg.py
+++ b/tests/integration/modules/test_pkg.py
@@ -136,6 +136,54 @@ class PkgModuleTest(ModuleCase, SaltReturnAssertsMixin):
@@ -182,6 +182,54 @@ class PkgModuleTest(ModuleCase, SaltReturnAssertsMixin):
if repo is not None:
self.run_function('pkg.del_repo', [repo])

View File

@ -1,4 +1,4 @@
From c6c8ce93bb0be6fe22fb5d65517a002595a9eb7b Mon Sep 17 00:00:00 2001
From bfee3a7c47786bb860663de97fca26725101f1d0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Tue, 7 May 2019 15:33:51 +0100
@ -7,75 +7,28 @@ Subject: [PATCH] Do not crash when there are IPv6 established
Add unit test for '_netlink_tool_remote_on'
---
salt/utils/network.py | 5 +++--
tests/unit/utils/test_network.py | 16 ++++++++++++++++
2 files changed, 19 insertions(+), 2 deletions(-)
salt/utils/network.py | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/salt/utils/network.py b/salt/utils/network.py
index a183c9776a..a3fd6e848e 100644
index 2ae2e213b7..307cab885f 100644
--- a/salt/utils/network.py
+++ b/salt/utils/network.py
@@ -1457,7 +1457,7 @@ def _parse_tcp_line(line):
def _netlink_tool_remote_on(port, which_end):
'''
- Returns set of ipv4 host addresses of remote established connections
+ Returns set of IPv4/IPv6 host addresses of remote established connections
on local or remote tcp port.
Parses output of shell 'ss' to get connections
@@ -1467,6 +1467,7 @@ def _netlink_tool_remote_on(port, which_end):
LISTEN 0 511 *:80 *:*
LISTEN 0 128 *:22 *:*
ESTAB 0 0 127.0.0.1:56726 127.0.0.1:4505
+ ESTAB 0 0 [::ffff:127.0.0.1]:41323 [::ffff:127.0.0.1]:4505
'''
remotes = set()
valid = False
@@ -1493,7 +1494,7 @@ def _netlink_tool_remote_on(port, which_end):
@@ -1442,8 +1442,13 @@ def _netlink_tool_remote_on(port, which_end):
elif 'ESTAB' not in line:
continue
if which_end == 'local_port' and int(local_port) != port:
continue
- remotes.add(remote_host)
+ remotes.add(remote_host.strip("[]"))
chunks = line.split()
+ local_host, local_port = chunks[3].rsplit(':', 1)
remote_host, remote_port = chunks[4].rsplit(':', 1)
+ if which_end == 'remote_port' and int(remote_port) != port:
+ continue
+ if which_end == 'local_port' and int(local_port) != port:
+ continue
remotes.add(remote_host.strip("[]"))
if valid is False:
remotes = None
diff --git a/tests/unit/utils/test_network.py b/tests/unit/utils/test_network.py
index f4c849d124..06e3aea6ea 100644
--- a/tests/unit/utils/test_network.py
+++ b/tests/unit/utils/test_network.py
@@ -128,6 +128,14 @@ ESTAB 0 0 127.0.0.1:56726 127.0.
ESTAB 0 0 ::ffff:1.2.3.4:5678 ::ffff:1.2.3.4:4505
'''
+LINUX_NETLINK_SS_OUTPUT = '''\
+State Recv-Q Send-Q Local Address:Port Peer Address:Port
+TIME-WAIT 0 0 [::1]:8009 [::1]:40368
+LISTEN 0 128 127.0.0.1:5903 0.0.0.0:*
+ESTAB 0 0 [::ffff:127.0.0.1]:4506 [::ffff:127.0.0.1]:32315
+ESTAB 0 0 192.168.122.1:4506 192.168.122.177:24545
+'''
+
IPV4_SUBNETS = {True: ('10.10.0.0/24',),
False: ('10.10.0.0', '10.10.0.0/33', 'FOO', 9, '0.9.800.1000/24')}
IPV6_SUBNETS = {True: ('::1/128',),
@@ -491,6 +499,14 @@ class NetworkTestCase(TestCase):
remotes = network._freebsd_remotes_on('4506', 'remote')
self.assertEqual(remotes, set(['127.0.0.1']))
+ def test_netlink_tool_remote_on(self):
+ with patch('salt.utils.platform.is_sunos', lambda: False):
+ with patch('salt.utils.platform.is_linux', lambda: True):
+ with patch('subprocess.check_output',
+ return_value=LINUX_NETLINK_SS_OUTPUT):
+ remotes = network._netlink_tool_remote_on('4506', 'local')
+ self.assertEqual(remotes, set(['192.168.122.177', '::ffff:127.0.0.1']))
+
def test_generate_minion_id_distinct(self):
'''
Test if minion IDs are distinct in the pool.
--
2.16.4
2.23.0

View File

@ -1,4 +1,4 @@
From 016e0c30718dac2a144090f82a2c35d5ce13bb8c Mon Sep 17 00:00:00 2001
From b1c96bdaec9723fd76a6dd5d72cf7fbfd681566f Mon Sep 17 00:00:00 2001
From: Bo Maryniuk <bo@suse.de>
Date: Fri, 21 Sep 2018 17:31:39 +0200
Subject: [PATCH] Do not load pip state if there is no 3rd party
@ -10,10 +10,10 @@ Safe import 3rd party dependency
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/salt/modules/pip.py b/salt/modules/pip.py
index eac40c719c..988ae695a7 100644
index ffdb73aefa..ff0836c35f 100644
--- a/salt/modules/pip.py
+++ b/salt/modules/pip.py
@@ -79,7 +79,10 @@ from __future__ import absolute_import, print_function, unicode_literals
@@ -82,7 +82,10 @@ from __future__ import absolute_import, print_function, unicode_literals
# Import python libs
import logging
import os
@ -25,7 +25,7 @@ index eac40c719c..988ae695a7 100644
import re
import shutil
import sys
@@ -116,7 +119,12 @@ def __virtual__():
@@ -119,7 +122,12 @@ def __virtual__():
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.
'''

View File

@ -1,4 +1,4 @@
From ee69f252a71b950377987d7fad3515082e09abff Mon Sep 17 00:00:00 2001
From 235cca81be2f64ed3feb48ed42bfa3f9196bff39 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Fri, 28 Jun 2019 15:17:56 +0100
@ -13,11 +13,11 @@ Add unit test for ansible caller
salt/modules/ansiblegate.py | 14 +++++++++---
tests/support/mock.py | 31 +++++++++++++++++++++++++
tests/unit/modules/test_ansiblegate.py | 41 ++++++++++++++++++++++++++++++++++
tests/unit/modules/test_cmdmod.py | 34 +---------------------------
4 files changed, 84 insertions(+), 36 deletions(-)
tests/unit/modules/test_cmdmod.py | 35 ++---------------------------
4 files changed, 85 insertions(+), 36 deletions(-)
diff --git a/salt/modules/ansiblegate.py b/salt/modules/ansiblegate.py
index 771db6d6aa..88e8147573 100644
index 6b903c2b94..8e28fcafa3 100644
--- a/salt/modules/ansiblegate.py
+++ b/salt/modules/ansiblegate.py
@@ -147,6 +147,10 @@ class AnsibleModuleCaller(object):
@ -57,10 +57,10 @@ index 771db6d6aa..88e8147573 100644
for arg in args:
info = doc.get(arg)
diff --git a/tests/support/mock.py b/tests/support/mock.py
index 38b68bd5c4..4b44c112ee 100644
index 805a60377c..67ecb4838a 100644
--- a/tests/support/mock.py
+++ b/tests/support/mock.py
@@ -510,6 +510,37 @@ class MockOpen(object):
@@ -461,6 +461,37 @@ class MockOpen(object):
ret.extend(fh_.writelines_calls)
return ret
@ -99,26 +99,24 @@ index 38b68bd5c4..4b44c112ee 100644
# reimplement mock_open to support multiple filehandles
mock_open = MockOpen
diff --git a/tests/unit/modules/test_ansiblegate.py b/tests/unit/modules/test_ansiblegate.py
index 1fbb083eb7..70b47f8bc2 100644
index 5613a0e79b..b7b43efda4 100644
--- a/tests/unit/modules/test_ansiblegate.py
+++ b/tests/unit/modules/test_ansiblegate.py
@@ -29,6 +29,7 @@ from tests.support.unit import TestCase, skipIf
@@ -29,11 +29,13 @@ from tests.support.unit import TestCase, skipIf
from tests.support.mock import (
patch,
MagicMock,
+ MockTimedProc,
NO_MOCK,
NO_MOCK_REASON
)
@@ -36,6 +37,7 @@ from tests.support.mock import (
import salt.modules.ansiblegate as ansible
import salt.utils.platform
from salt.exceptions import LoaderError
+from salt.ext import six
@skipIf(NO_MOCK, NO_MOCK_REASON)
@@ -137,3 +139,42 @@ description:
@skipIf(NO_PYTEST, False)
@@ -134,3 +136,42 @@ description:
'''
with patch('salt.modules.ansiblegate.ansible', None):
assert ansible.__virtual__() == 'ansible'
@ -162,18 +160,18 @@ index 1fbb083eb7..70b47f8bc2 100644
+ proc.assert_any_call(['python', 'foofile'], stdin=ANSIBLE_MODULE_ARGS, stdout=-1, timeout=1200)
+ assert ret == {"completed": True, "timeout": 1200}
diff --git a/tests/unit/modules/test_cmdmod.py b/tests/unit/modules/test_cmdmod.py
index 8da672dd22..a20afaca0f 100644
index 8170a56b4e..f8fba59294 100644
--- a/tests/unit/modules/test_cmdmod.py
+++ b/tests/unit/modules/test_cmdmod.py
@@ -24,6 +24,7 @@ from tests.support.paths import FILES
@@ -26,6 +26,7 @@ from tests.support.helpers import TstSuiteLoggingHandler
from tests.support.mock import (
mock_open,
Mock,
+ MockTimedProc,
MagicMock,
NO_MOCK,
NO_MOCK_REASON,
@@ -36,39 +37,6 @@ MOCK_SHELL_FILE = '# List of acceptable shells\n' \
patch
)
@@ -36,39 +37,7 @@ MOCK_SHELL_FILE = '# List of acceptable shells\n' \
'/bin/bash\n'
@ -210,9 +208,10 @@ index 8da672dd22..a20afaca0f 100644
- return self._stderr
-
-
@skipIf(NO_MOCK, NO_MOCK_REASON)
+@skipIf(NO_MOCK, NO_MOCK_REASON)
class CMDMODTestCase(TestCase, LoaderModuleMockMixin):
'''
Unit tests for the salt.modules.cmdmod module
--
2.16.4

View File

@ -1,4 +1,4 @@
From 3c39b7ae5e4a0cd11a77241abde9407a8e1b3f07 Mon Sep 17 00:00:00 2001
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
@ -7,38 +7,25 @@ Subject: [PATCH] Do not report patches as installed when not all the
Co-authored-by: Mihai Dinca <mdinca@suse.de>
---
salt/modules/yumpkg.py | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
salt/modules/yumpkg.py | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/salt/modules/yumpkg.py b/salt/modules/yumpkg.py
index 4f26a41670..5ec3835574 100644
index b1257d0de0..3ddf989511 100644
--- a/salt/modules/yumpkg.py
+++ b/salt/modules/yumpkg.py
@@ -3212,12 +3212,18 @@ def _get_patches(installed_only=False):
@@ -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()
- if inst != 'i' and installed_only:
- continue
- patches[advisory_id] = {
- 'installed': True if inst == 'i' else False,
- 'summary': pkg
- }
+<<<<<<< HEAD
if advisory_id not in patches:
+=======
+ if not advisory_id in patches:
+ patches[advisory_id] = {
+ 'installed': True if inst == 'i' else False,
+ 'summary': [pkg]
+ }
+ else:
+ patches[advisory_id]['summary'].append(pkg)
+ if inst != 'i':
+ patches[advisory_id]['installed'] = False
+
+ if installed_only:
+ patches = {k: v for k, v in patches.items() if v['installed']}
return 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

View File

@ -1,4 +1,4 @@
From a2e40158ad3b92a20ec9c12f7cd75edb4a01c2fc Mon Sep 17 00:00:00 2001
From c1f5e6332bf025394b81868bf1edc6ae44944a7c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Bosdonnat?= <cbosdonnat@suse.com>
Date: Tue, 29 Jan 2019 09:44:03 +0100
Subject: [PATCH] Don't call zypper with more than one --no-refresh
@ -11,7 +11,7 @@ passed twice. Make sure we won't hit this.
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/salt/modules/zypperpkg.py b/salt/modules/zypperpkg.py
index 92e7052020..7ac0df26c6 100644
index 04a6a6872d..37428cf67c 100644
--- a/salt/modules/zypperpkg.py
+++ b/salt/modules/zypperpkg.py
@@ -282,7 +282,7 @@ class _Zypper(object):
@ -24,10 +24,10 @@ index 92e7052020..7ac0df26c6 100644
self.__cmd.extend(args)
diff --git a/tests/unit/modules/test_zypperpkg.py b/tests/unit/modules/test_zypperpkg.py
index f586c23fd0..5c5091a570 100644
index b3162f10cd..956902eab3 100644
--- a/tests/unit/modules/test_zypperpkg.py
+++ b/tests/unit/modules/test_zypperpkg.py
@@ -138,7 +138,7 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin):
@@ -135,7 +135,7 @@ class ZypperTestCase(TestCase, LoaderModuleMockMixin):
self.assertEqual(zypper.__zypper__.call('foo'), stdout_xml_snippet)
self.assertEqual(len(sniffer.calls), 1)

View File

@ -1,4 +1,4 @@
From 0e4ac6001d552e649f8ab9d6c04b18bd531e4240 Mon Sep 17 00:00:00 2001
From 33a85b16a4740f3dd803fd0e47e26819afeecdd7 Mon Sep 17 00:00:00 2001
From: Bo Maryniuk <bo@suse.de>
Date: Tue, 10 Jul 2018 12:06:33 +0200
Subject: [PATCH] early feature: support-config
@ -291,24 +291,24 @@ Remove development stub. Ughh...
Removed blacklist of pkg_resources
---
salt/cli/support/__init__.py | 65 ++++
salt/cli/support/collector.py | 495 ++++++++++++++++++++++++++++++
salt/cli/support/console.py | 165 ++++++++++
salt/cli/support/intfunc.py | 42 +++
salt/cli/support/__init__.py | 65 +++
salt/cli/support/collector.py | 495 ++++++++++++++++++++++
salt/cli/support/console.py | 165 ++++++++
salt/cli/support/intfunc.py | 42 ++
salt/cli/support/localrunner.py | 34 ++
salt/cli/support/profiles/default.yml | 71 +++++
salt/cli/support/profiles/default.yml | 71 ++++
salt/cli/support/profiles/jobs-active.yml | 3 +
salt/cli/support/profiles/jobs-last.yml | 3 +
salt/cli/support/profiles/jobs-trace.yml | 7 +
salt/cli/support/profiles/network.yml | 27 ++
salt/cli/support/profiles/postgres.yml | 11 +
salt/cli/support/profiles/salt.yml | 9 +
salt/cli/support/profiles/users.yml | 22 ++
salt/cli/support/profiles/users.yml | 22 +
salt/scripts.py | 14 +
salt/utils/parsers.py | 65 ++++
salt/utils/parsers.py | 65 +++
scripts/salt-support | 11 +
setup.py | 2 +
tests/unit/cli/test_support.py | 477 ++++++++++++++++++++++++++++
tests/unit/cli/test_support.py | 477 +++++++++++++++++++++
18 files changed, 1523 insertions(+)
create mode 100644 salt/cli/support/__init__.py
create mode 100644 salt/cli/support/collector.py
@ -328,7 +328,7 @@ Removed blacklist of pkg_resources
diff --git a/salt/cli/support/__init__.py b/salt/cli/support/__init__.py
new file mode 100644
index 0000000000..6a98a2d656
index 0000000000000000000000000000000000000000..6a98a2d65656c0ad89d921b6842067a7399eab2c
--- /dev/null
+++ b/salt/cli/support/__init__.py
@@ -0,0 +1,65 @@
@ -399,7 +399,7 @@ index 0000000000..6a98a2d656
+ return sorted(profiles)
diff --git a/salt/cli/support/collector.py b/salt/cli/support/collector.py
new file mode 100644
index 0000000000..478d07e13b
index 0000000000000000000000000000000000000000..478d07e13bf264b5d0caacd487cc45441ff259fb
--- /dev/null
+++ b/salt/cli/support/collector.py
@@ -0,0 +1,495 @@
@ -900,7 +900,7 @@ index 0000000000..478d07e13b
+ sys.exit(exit_code)
diff --git a/salt/cli/support/console.py b/salt/cli/support/console.py
new file mode 100644
index 0000000000..fb6992d657
index 0000000000000000000000000000000000000000..fb6992d657e21a6b933e81135d812f7bd3720a9e
--- /dev/null
+++ b/salt/cli/support/console.py
@@ -0,0 +1,165 @@
@ -1071,7 +1071,7 @@ index 0000000000..fb6992d657
+ return wrapper.wrap(txt)
diff --git a/salt/cli/support/intfunc.py b/salt/cli/support/intfunc.py
new file mode 100644
index 0000000000..2727cd6394
index 0000000000000000000000000000000000000000..2727cd6394c364e35c99403b75e7fd23856187c6
--- /dev/null
+++ b/salt/cli/support/intfunc.py
@@ -0,0 +1,42 @@
@ -1119,7 +1119,7 @@ index 0000000000..2727cd6394
+ filetree(collector, fname)
diff --git a/salt/cli/support/localrunner.py b/salt/cli/support/localrunner.py
new file mode 100644
index 0000000000..26deb883bc
index 0000000000000000000000000000000000000000..26deb883bccc98079201d26deba01008cca72921
--- /dev/null
+++ b/salt/cli/support/localrunner.py
@@ -0,0 +1,34 @@
@ -1159,7 +1159,7 @@ index 0000000000..26deb883bc
+ return self.low(fun, low, print_event=False, full_return=False)
diff --git a/salt/cli/support/profiles/default.yml b/salt/cli/support/profiles/default.yml
new file mode 100644
index 0000000000..01d9a26193
index 0000000000000000000000000000000000000000..01d9a261933333a6246e932556cdd88f3adf1f82
--- /dev/null
+++ b/salt/cli/support/profiles/default.yml
@@ -0,0 +1,71 @@
@ -1236,7 +1236,7 @@ index 0000000000..01d9a26193
+
diff --git a/salt/cli/support/profiles/jobs-active.yml b/salt/cli/support/profiles/jobs-active.yml
new file mode 100644
index 0000000000..508c54ece7
index 0000000000000000000000000000000000000000..508c54ece79087c98ba2dd4bd0ee265b09520296
--- /dev/null
+++ b/salt/cli/support/profiles/jobs-active.yml
@@ -0,0 +1,3 @@
@ -1245,7 +1245,7 @@ index 0000000000..508c54ece7
+ info: List of all actively running jobs
diff --git a/salt/cli/support/profiles/jobs-last.yml b/salt/cli/support/profiles/jobs-last.yml
new file mode 100644
index 0000000000..e3b719f552
index 0000000000000000000000000000000000000000..e3b719f552d2288d15dc5af4d6c320e0386ed7d0
--- /dev/null
+++ b/salt/cli/support/profiles/jobs-last.yml
@@ -0,0 +1,3 @@
@ -1254,7 +1254,7 @@ index 0000000000..e3b719f552
+ info: List all detectable jobs and associated functions
diff --git a/salt/cli/support/profiles/jobs-trace.yml b/salt/cli/support/profiles/jobs-trace.yml
new file mode 100644
index 0000000000..00b28e0502
index 0000000000000000000000000000000000000000..00b28e0502e2e6dbd9fe3e990750cbc1f9a94a30
--- /dev/null
+++ b/salt/cli/support/profiles/jobs-trace.yml
@@ -0,0 +1,7 @@
@ -1267,7 +1267,7 @@ index 0000000000..00b28e0502
+ {% endfor %}
diff --git a/salt/cli/support/profiles/network.yml b/salt/cli/support/profiles/network.yml
new file mode 100644
index 0000000000..268f02e61f
index 0000000000000000000000000000000000000000..268f02e61fbe9b5f0870569a9343da6e778a7017
--- /dev/null
+++ b/salt/cli/support/profiles/network.yml
@@ -0,0 +1,27 @@
@ -1300,7 +1300,7 @@ index 0000000000..268f02e61f
+ info: ARP table
diff --git a/salt/cli/support/profiles/postgres.yml b/salt/cli/support/profiles/postgres.yml
new file mode 100644
index 0000000000..2238752c7a
index 0000000000000000000000000000000000000000..2238752c7a90a09bddc9cd3cbf27acbbf2a85c1c
--- /dev/null
+++ b/salt/cli/support/profiles/postgres.yml
@@ -0,0 +1,11 @@
@ -1317,7 +1317,7 @@ index 0000000000..2238752c7a
+ - /etc/postgresql
diff --git a/salt/cli/support/profiles/salt.yml b/salt/cli/support/profiles/salt.yml
new file mode 100644
index 0000000000..4b18d98870
index 0000000000000000000000000000000000000000..4b18d9887002f9a9efdd6f54870db4b74384a19e
--- /dev/null
+++ b/salt/cli/support/profiles/salt.yml
@@ -0,0 +1,9 @@
@ -1332,7 +1332,7 @@ index 0000000000..4b18d98870
+ - {{salt('config.get', 'log_file')}}
diff --git a/salt/cli/support/profiles/users.yml b/salt/cli/support/profiles/users.yml
new file mode 100644
index 0000000000..391acdb606
index 0000000000000000000000000000000000000000..391acdb606d2ebb35ac7cff10844fffd84d96915
--- /dev/null
+++ b/salt/cli/support/profiles/users.yml
@@ -0,0 +1,22 @@
@ -1359,13 +1359,13 @@ index 0000000000..391acdb606
+ info: List of all available groups
+ output: table
diff --git a/salt/scripts.py b/salt/scripts.py
index 71120366e0..c789df4e39 100644
index 5e623a578e8363b51e10af247b325069741064d5..401ec2055303dd3b342110ddbab155e30d5b4e31 100644
--- a/salt/scripts.py
+++ b/salt/scripts.py
@@ -539,3 +539,17 @@ def salt_extend(extension, name, description, salt_dir, merge):
description=description,
salt_dir=salt_dir,
merge=merge)
@@ -579,3 +579,17 @@ def salt_unity():
sys.argv.pop(1)
s_fun = getattr(sys.modules[__name__], 'salt_{0}'.format(cmd))
s_fun()
+
+
+def salt_support():
@ -1381,10 +1381,10 @@ index 71120366e0..c789df4e39 100644
+ _install_signal_handlers(client)
+ client.run()
diff --git a/salt/utils/parsers.py b/salt/utils/parsers.py
index 1e652a845e..aa13310d5a 100644
index fb9b0987a65ce1607de63f6f83ce96f6987800aa..83dfe717f6a66305ad1c2505da5d3aa380495171 100644
--- a/salt/utils/parsers.py
+++ b/salt/utils/parsers.py
@@ -20,6 +20,7 @@ import getpass
@@ -21,6 +21,7 @@ import getpass
import logging
import optparse
import traceback
@ -1392,15 +1392,15 @@ index 1e652a845e..aa13310d5a 100644
from functools import partial
@@ -34,6 +35,7 @@ import salt.utils.data
@@ -34,6 +35,7 @@ import salt.utils.args
import salt.utils.data
import salt.utils.files
import salt.utils.jid
import salt.utils.kinds as kinds
+import salt.utils.network
import salt.utils.platform
import salt.utils.process
import salt.utils.stringutils
@@ -1902,6 +1904,69 @@ class SyndicOptionParser(six.with_metaclass(OptionParserMeta,
@@ -1913,6 +1915,69 @@ class SyndicOptionParser(six.with_metaclass(OptionParserMeta,
self.get_config_file_path('minion'))
@ -1472,7 +1472,7 @@ index 1e652a845e..aa13310d5a 100644
ConfigDirMixIn,
diff --git a/scripts/salt-support b/scripts/salt-support
new file mode 100755
index 0000000000..48ce141c67
index 0000000000000000000000000000000000000000..48ce141c673aa390174f88f0e18b857c561ab6f5
--- /dev/null
+++ b/scripts/salt-support
@@ -0,0 +1,11 @@
@ -1488,10 +1488,10 @@ index 0000000000..48ce141c67
+if __name__ == '__main__':
+ salt_support()
diff --git a/setup.py b/setup.py
index 3e930df8db..25e06a42f6 100755
index 788664e14e1e93ffe51e9ace4409b48e9b4afeaf..06374647df5e82a21fc39b08d41c596f0483ff0c 100755
--- a/setup.py
+++ b/setup.py
@@ -1051,6 +1051,7 @@ class SaltDistribution(distutils.dist.Distribution):
@@ -1058,6 +1058,7 @@ class SaltDistribution(distutils.dist.Distribution):
'scripts/salt-master',
'scripts/salt-minion',
'scripts/salt-proxy',
@ -1499,7 +1499,7 @@ index 3e930df8db..25e06a42f6 100755
'scripts/salt-ssh',
'scripts/salt-syndic',
'scripts/salt-unity',
@@ -1086,6 +1087,7 @@ class SaltDistribution(distutils.dist.Distribution):
@@ -1093,6 +1094,7 @@ class SaltDistribution(distutils.dist.Distribution):
'salt-key = salt.scripts:salt_key',
'salt-master = salt.scripts:salt_master',
'salt-minion = salt.scripts:salt_minion',
@ -1509,7 +1509,7 @@ index 3e930df8db..25e06a42f6 100755
'salt-unity = salt.scripts:salt_unity',
diff --git a/tests/unit/cli/test_support.py b/tests/unit/cli/test_support.py
new file mode 100644
index 0000000000..85ea957d79
index 0000000000000000000000000000000000000000..85ea957d7921257d9ebfff3c136438524008c7cd
--- /dev/null
+++ b/tests/unit/cli/test_support.py
@@ -0,0 +1,477 @@
@ -1991,6 +1991,6 @@ index 0000000000..85ea957d79
+ assert jobs_trace['jobs-details'][0]['run:jobs.list_job']['info'] == 'Details on JID 0000'
+ assert jobs_trace['jobs-details'][0]['run:jobs.list_job']['args'] == [0]
--
2.16.4
2.23.0

View File

@ -1,4 +1,4 @@
From 7482f815a80c2c789bc09e2c72c522e6eb091fa3 Mon Sep 17 00:00:00 2001
From cc3bd759bc0e4cc3414ccc5a2928c593fa2eee04 Mon Sep 17 00:00:00 2001
From: Maximilian Meister <mmeister@suse.de>
Date: Thu, 3 May 2018 15:52:23 +0200
Subject: [PATCH] enable passing a unix_socket for mysql returners
@ -19,7 +19,7 @@ Signed-off-by: Maximilian Meister <mmeister@suse.de>
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/salt/returners/mysql.py b/salt/returners/mysql.py
index fbaaacfe0d..06b249e664 100644
index 69599ec36a..ff9d380843 100644
--- a/salt/returners/mysql.py
+++ b/salt/returners/mysql.py
@@ -18,6 +18,7 @@ config. These are the defaults:

View File

@ -1,132 +0,0 @@
From 79f566ba99f48d60e4948c9b8df9c6b6f497eced Mon Sep 17 00:00:00 2001
From: Abid Mehmood <amehmood@suse.de>
Date: Thu, 1 Aug 2019 13:14:22 +0200
Subject: [PATCH] enable passing grains to start event based on
'start_event_grains' configuration parameter
unit tests
---
conf/minion | 5 +++++
doc/ref/configuration/minion.rst | 15 +++++++++++++++
salt/config/__init__.py | 1 +
salt/minion.py | 5 +++++
tests/unit/test_minion.py | 32 ++++++++++++++++++++++++++++++++
5 files changed, 58 insertions(+)
diff --git a/conf/minion b/conf/minion
index f2b6655932..cc7e962120 100644
--- a/conf/minion
+++ b/conf/minion
@@ -548,6 +548,11 @@
# - edit.vim
# - hyper
#
+# List of grains to pass in start event when minion starts up:
+#start_event_grains:
+# - machine_id
+# - uuid
+#
# Top file to execute if startup_states is 'top':
#top_file: ''
diff --git a/doc/ref/configuration/minion.rst b/doc/ref/configuration/minion.rst
index 30343ebd8e..fe556ef9ce 100644
--- a/doc/ref/configuration/minion.rst
+++ b/doc/ref/configuration/minion.rst
@@ -2000,6 +2000,21 @@ List of states to run when the minion starts up if ``startup_states`` is set to
- edit.vim
- hyper
+.. conf_minion:: start_event_grains
+
+``start_event_grains``
+----------------------
+
+Default: ``[]``
+
+List of grains to pass in start event when minion starts up.
+
+.. code-block:: yaml
+
+ start_event_grains:
+ - machine_id
+ - uuid
+
.. conf_minion:: top_file
``top_file``
diff --git a/salt/config/__init__.py b/salt/config/__init__.py
index ee90eb3120..788128b903 100644
--- a/salt/config/__init__.py
+++ b/salt/config/__init__.py
@@ -1283,6 +1283,7 @@ DEFAULT_MINION_OPTS = {
'state_top_saltenv': None,
'startup_states': '',
'sls_list': [],
+ 'start_event_grains': [],
'top_file': '',
'thoriumenv': None,
'thorium_top': 'top.sls',
diff --git a/salt/minion.py b/salt/minion.py
index 2c0a18604e..2b53da4f18 100644
--- a/salt/minion.py
+++ b/salt/minion.py
@@ -1456,6 +1456,11 @@ class Minion(MinionBase):
else:
return
+ if self.opts['start_event_grains']:
+ grains_to_add = dict(
+ [(k, v) for k, v in six.iteritems(self.opts.get('grains', {})) if k in self.opts['start_event_grains']])
+ load['grains'] = grains_to_add
+
if sync:
try:
self._send_req_sync(load, timeout)
diff --git a/tests/unit/test_minion.py b/tests/unit/test_minion.py
index b78e0f6abd..83215151ee 100644
--- a/tests/unit/test_minion.py
+++ b/tests/unit/test_minion.py
@@ -305,6 +305,38 @@ class MinionTestCase(TestCase, AdaptedConfigurationTestCaseMixin):
finally:
minion.destroy()
+ def test_when_passed_start_event_grains(self):
+ mock_opts = self.get_config('minion', from_scratch=True)
+ mock_opts['start_event_grains'] = ["os"]
+ io_loop = tornado.ioloop.IOLoop()
+ io_loop.make_current()
+ minion = salt.minion.Minion(mock_opts, io_loop=io_loop)
+ try:
+ minion.tok = MagicMock()
+ minion._send_req_sync = MagicMock()
+ minion._fire_master('Minion has started', 'minion_start')
+ load = minion._send_req_sync.call_args[0][0]
+
+ self.assertTrue('grains' in load)
+ self.assertTrue('os' in load['grains'])
+ finally:
+ minion.destroy()
+
+ def test_when_not_passed_start_event_grains(self):
+ mock_opts = self.get_config('minion', from_scratch=True)
+ io_loop = tornado.ioloop.IOLoop()
+ io_loop.make_current()
+ minion = salt.minion.Minion(mock_opts, io_loop=io_loop)
+ try:
+ minion.tok = MagicMock()
+ minion._send_req_sync = MagicMock()
+ minion._fire_master('Minion has started', 'minion_start')
+ load = minion._send_req_sync.call_args[0][0]
+
+ self.assertTrue('grains' not in load)
+ finally:
+ minion.destroy()
+
def test_minion_retry_dns_count(self):
'''
Tests that the resolve_dns will retry dns look ups for a maximum of
--
2.16.4

View File

@ -1,4 +1,4 @@
From 37a3628e3a3cd2d1f18e7834a151efab21b10433 Mon Sep 17 00:00:00 2001
From f0098b4b9e5abaaca7bbc6c17f5a60bb2129dda5 Mon Sep 17 00:00:00 2001
From: Maximilian Meister <mmeister@suse.de>
Date: Thu, 5 Apr 2018 13:23:23 +0200
Subject: [PATCH] fall back to PyMySQL
@ -11,7 +11,7 @@ Signed-off-by: Maximilian Meister <mmeister@suse.de>
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/salt/modules/mysql.py b/salt/modules/mysql.py
index 94f4b4acce..7e8e6026b3 100644
index 87e2361e28..e785e5219c 100644
--- a/salt/modules/mysql.py
+++ b/salt/modules/mysql.py
@@ -58,7 +58,7 @@ try:

View File

@ -1,4 +1,4 @@
From 3812df3a2776e745160ef406dae85aa8acdf2333 Mon Sep 17 00:00:00 2001
From 6418d9ebc3b269a0246262f79c0bab367e39cc52 Mon Sep 17 00:00:00 2001
From: Alberto Planas <aplanas@gmail.com>
Date: Fri, 25 Oct 2019 15:43:16 +0200
Subject: [PATCH] Fix a wrong rebase in test_core.py (#180)
@ -22,10 +22,10 @@ This patch ignore this kind of issue during the grains creation.
2 files changed, 2 insertions(+), 47 deletions(-)
diff --git a/salt/grains/core.py b/salt/grains/core.py
index 6b1f2d2223..31ed8a77aa 100644
index 68c43482d3..20950988d9 100644
--- a/salt/grains/core.py
+++ b/salt/grains/core.py
@@ -990,7 +990,7 @@ def _virtual(osdata):
@@ -1000,7 +1000,7 @@ def _virtual(osdata):
except UnicodeDecodeError:
# Some firmwares provide non-valid 'product_name'
# files, ignore them
@ -34,7 +34,7 @@ index 6b1f2d2223..31ed8a77aa 100644
except IOError:
pass
elif osdata['kernel'] == 'FreeBSD':
@@ -2545,7 +2545,7 @@ def _hw_data(osdata):
@@ -2568,7 +2568,7 @@ def _hw_data(osdata):
except UnicodeDecodeError:
# Some firmwares provide non-valid 'product_name'
# files, ignore them
@ -44,12 +44,12 @@ index 6b1f2d2223..31ed8a77aa 100644
# PermissionError is new to Python 3, but corresponds to the EACESS and
# 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
index 7153a078f4..09e197a2e4 100644
index c4731f667a..b4ed9379e5 100644
--- a/tests/unit/grains/test_core.py
+++ b/tests/unit/grains/test_core.py
@@ -1317,51 +1317,6 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
'uuid': ''
})
@@ -1544,51 +1544,6 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
self.assertIn('osfullname', os_grains)
self.assertEqual(os_grains.get('osfullname'), 'FreeBSD')
- @skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
- def test_kernelparams_return(self):

View File

@ -1,4 +1,4 @@
From db65ebf356238c151af7798ed34684847ed4a5c0 Mon Sep 17 00:00:00 2001
From c2989e749f04aa8477130df649e550f5349a9a1f Mon Sep 17 00:00:00 2001
From: Mihai Dinca <mdinca@suse.de>
Date: Wed, 31 Jul 2019 15:29:03 +0200
Subject: [PATCH] Fix aptpkg systemd call (bsc#1143301)
@ -9,10 +9,10 @@ Subject: [PATCH] Fix aptpkg systemd call (bsc#1143301)
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/salt/modules/aptpkg.py b/salt/modules/aptpkg.py
index e537f5b007..b7c1a342ef 100644
index 13484c96bc..a5b039fc79 100644
--- a/salt/modules/aptpkg.py
+++ b/salt/modules/aptpkg.py
@@ -165,7 +165,7 @@ def _call_apt(args, scope=True, **kwargs):
@@ -168,7 +168,7 @@ def _call_apt(args, scope=True, **kwargs):
'''
cmd = []
if scope and salt.utils.systemd.has_scope(__context__) and __salt__['config.get']('systemd.scope', True):
@ -22,10 +22,10 @@ index e537f5b007..b7c1a342ef 100644
params = {'output_loglevel': 'trace',
diff --git a/tests/unit/modules/test_aptpkg.py b/tests/unit/modules/test_aptpkg.py
index 580b840197..06f3a9f6aa 100644
index 10e960f090..88eed062c4 100644
--- a/tests/unit/modules/test_aptpkg.py
+++ b/tests/unit/modules/test_aptpkg.py
@@ -544,7 +544,7 @@ class AptUtilsTestCase(TestCase, LoaderModuleMockMixin):
@@ -645,7 +645,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
aptpkg.__salt__['cmd.run_all'].assert_called_once_with(

View File

@ -1,4 +1,4 @@
From 2fe38d075efce89dd94c1088ab8c97656e589c8f Mon Sep 17 00:00:00 2001
From 42d7e1de2c69d82447e73eab483e5d3c299d55f7 Mon Sep 17 00:00:00 2001
From: Mihai Dinca <mdinca@suse.de>
Date: Tue, 7 May 2019 12:24:35 +0200
Subject: [PATCH] Fix async-batch multiple done events

View File

@ -1,4 +1,4 @@
From 2c1311f544950fe417fb8609aa3a30da32656637 Mon Sep 17 00:00:00 2001
From dc001cb47fd88a8e8a1bd82a1457325822d1220b Mon Sep 17 00:00:00 2001
From: Mihai Dinca <mdinca@suse.de>
Date: Thu, 11 Apr 2019 15:57:59 +0200
Subject: [PATCH] Fix async batch race conditions

View File

@ -1,4 +1,4 @@
From 78b466b0d45de8b7edace542dd3815ca852def40 Mon Sep 17 00:00:00 2001
From 49780d409630fe18293a077e767aabfd183ff823 Mon Sep 17 00:00:00 2001
From: Mihai Dinca <mdinca@suse.de>
Date: Tue, 3 Dec 2019 11:22:42 +0100
Subject: [PATCH] Fix batch_async obsolete test
@ -28,6 +28,6 @@ index 12dfe543bc..f1d36a81fb 100644
@tornado.testing.gen_test
def test_batch_next(self):
--
2.23.0
2.16.4

View File

@ -1,4 +1,4 @@
From bff330bce4b6e8a848400417c5858ece1dc7b5cf Mon Sep 17 00:00:00 2001
From 4acbe70851e3ef7a04fc5ad0dc9a2519f6989c66 Mon Sep 17 00:00:00 2001
From: Bo Maryniuk <bo@suse.de>
Date: Thu, 14 Dec 2017 16:21:40 +0100
Subject: [PATCH] Fix bsc#1065792
@ -8,7 +8,7 @@ Subject: [PATCH] Fix bsc#1065792
1 file changed, 1 insertion(+)
diff --git a/salt/states/service.py b/salt/states/service.py
index a0e553ead9..1fdcf126ff 100644
index de7718ea49..987e37cd42 100644
--- a/salt/states/service.py
+++ b/salt/states/service.py
@@ -80,6 +80,7 @@ def __virtual__():

View File

@ -1,4 +1,4 @@
From 927cef6dfa547bf2410740a8c8b41a97492510f0 Mon Sep 17 00:00:00 2001
From e6f6b38c75027c4c4f6395117b734dce6fb7433e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Fri, 4 Oct 2019 15:00:50 +0100

View File

@ -1,4 +1,4 @@
From f114484307a2b8a3cf72bef28febe44e73b498ed Mon Sep 17 00:00:00 2001
From e0ca0d0d2a62f18e2712223e130af5faa8e0fe05 Mon Sep 17 00:00:00 2001
From: Jochen Breuer <jbreuer@suse.de>
Date: Thu, 28 Nov 2019 15:23:36 +0100
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(-)
diff --git a/tests/unit/modules/test_x509.py b/tests/unit/modules/test_x509.py
index 7030f96484..143abe82bf 100644
index 624a927bec..976af634c7 100644
--- a/tests/unit/modules/test_x509.py
+++ b/tests/unit/modules/test_x509.py
@@ -71,9 +71,9 @@ class X509TestCase(TestCase, LoaderModuleMockMixin):
@@ -68,9 +68,9 @@ class X509TestCase(TestCase, LoaderModuleMockMixin):
subj = FakeSubject()
x509._parse_subject(subj)

View File

@ -1,37 +0,0 @@
From 56dde3e54715bd488e4110955ca066d9661512bf Mon Sep 17 00:00:00 2001
From: Jochen Breuer <jbreuer@suse.de>
Date: Fri, 25 Oct 2019 16:18:58 +0200
Subject: [PATCH] Fix for older mock module
Seems like args is not working with older mock modules.
---
tests/unit/modules/test_aptpkg.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/tests/unit/modules/test_aptpkg.py b/tests/unit/modules/test_aptpkg.py
index d3fac5902a..bc6b610d86 100644
--- a/tests/unit/modules/test_aptpkg.py
+++ b/tests/unit/modules/test_aptpkg.py
@@ -412,15 +412,15 @@ class AptPkgTestCase(TestCase, LoaderModuleMockMixin):
}
with patch.multiple(aptpkg, **patch_kwargs):
aptpkg.upgrade()
- args_matching = [True for args in patch_kwargs['__salt__']['cmd.run_all'].call_args.args if "--download-only" in args]
+ args_matching = [True for args in patch_kwargs['__salt__']['cmd.run_all'].call_args[0] if "--download-only" in args]
self.assertFalse(any(args_matching))
aptpkg.upgrade(downloadonly=True)
- args_matching = [True for args in patch_kwargs['__salt__']['cmd.run_all'].call_args.args if "--download-only" in args]
+ args_matching = [True for args in patch_kwargs['__salt__']['cmd.run_all'].call_args[0] if "--download-only" in args]
self.assertTrue(any(args_matching))
aptpkg.upgrade(download_only=True)
- args_matching = [True for args in patch_kwargs['__salt__']['cmd.run_all'].call_args.args if "--download-only" in args]
+ args_matching = [True for args in patch_kwargs['__salt__']['cmd.run_all'].call_args[0] if "--download-only" in args]
self.assertTrue(any(args_matching))
def test_show(self):
--
2.16.4

View File

@ -1,4 +1,4 @@
From 0c16dd5a3c7bef0fe980ac8517f099a8e034c6c9 Mon Sep 17 00:00:00 2001
From 16d656744d2e7d915757d6f2ae26b57ad8230b0b Mon Sep 17 00:00:00 2001
From: Jochen Breuer <jbreuer@suse.de>
Date: Thu, 6 Sep 2018 17:15:18 +0200
Subject: [PATCH] Fix for SUSE Expanded Support detection
@ -14,10 +14,10 @@ This change also adds a check for redhat-release and then marks the
1 file changed, 9 insertions(+)
diff --git a/salt/grains/core.py b/salt/grains/core.py
index 04c1ae91b5..82cd3fb657 100644
index 9b244def9c..2851809472 100644
--- a/salt/grains/core.py
+++ b/salt/grains/core.py
@@ -1873,6 +1873,15 @@ def os_data():
@@ -1892,6 +1892,15 @@ def os_data():
log.trace('Parsing distrib info from /etc/centos-release')
# CentOS Linux
grains['lsb_distrib_id'] = 'CentOS'

View File

@ -0,0 +1,42 @@
From dd01a0fc594f024eee2267bed2f698f5a6c729bf Mon Sep 17 00:00:00 2001
From: Jochen Breuer <jbreuer@suse.de>
Date: Mon, 16 Mar 2020 15:25:42 +0100
Subject: [PATCH] Fix for temp folder definition in loader unit test
---
tests/unit/test_loader.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/tests/unit/test_loader.py b/tests/unit/test_loader.py
index fe11cd0681..7e369f2c3b 100644
--- a/tests/unit/test_loader.py
+++ b/tests/unit/test_loader.py
@@ -152,12 +152,12 @@ class LazyLoaderUtilsTest(TestCase):
def setUpClass(cls):
cls.opts = salt.config.minion_config(None)
cls.opts['grains'] = salt.loader.grains(cls.opts)
- if not os.path.isdir(TMP):
- os.makedirs(TMP)
+ if not os.path.isdir(RUNTIME_VARS.TMP):
+ os.makedirs(RUNTIME_VARS.TMP)
def setUp(self):
# Setup the module
- self.module_dir = tempfile.mkdtemp(dir=TMP)
+ self.module_dir = tempfile.mkdtemp(dir=RUNTIME_VARS.TMP)
self.module_file = os.path.join(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):
fh.flush()
os.fsync(fh.fileno())
- self.utils_dir = tempfile.mkdtemp(dir=TMP)
+ self.utils_dir = tempfile.mkdtemp(dir=RUNTIME_VARS.TMP)
self.utils_file = os.path.join(self.utils_dir,
'{}.py'.format(self.utils_name))
with salt.utils.files.fopen(self.utils_file, 'w') as fh:
--
2.16.4

View File

@ -0,0 +1,50 @@
From f8b490c26be8e7f76947cc07f606f95c133805a7 Mon Sep 17 00:00:00 2001
From: "Daniel A. Wozniak" <dwozniak@saltstack.com>
Date: Thu, 20 Feb 2020 21:07:07 +0000
Subject: [PATCH] Fix for unless requisite when pip is not installed
Only remove pip relasted modules
---
salt/states/pip_state.py | 17 ++---------------
1 file changed, 2 insertions(+), 15 deletions(-)
diff --git a/salt/states/pip_state.py b/salt/states/pip_state.py
index 0f762752d02bf5ced17928a4c7fd2a3f027b66d5..11e466389fc46574923e2a71d8ca06f2c411f369 100644
--- a/salt/states/pip_state.py
+++ b/salt/states/pip_state.py
@@ -51,7 +51,7 @@ def purge_pip():
return
pip_related_entries = [
(k, v) for (k, v) in sys.modules.items()
- or getattr(v, '__module__', '').startswith('pip.')
+ if getattr(v, '__module__', '').startswith('pip.')
or (isinstance(v, types.ModuleType) and v.__name__.startswith('pip.'))
]
for name, entry in pip_related_entries:
@@ -96,21 +96,8 @@ try:
HAS_PIP = True
except ImportError:
HAS_PIP = False
- # Remove references to the loaded pip module above so reloading works
- import sys
- pip_related_entries = [
- (k, v) for (k, v) in sys.modules.items()
- or getattr(v, '__module__', '').startswith('pip.')
- or (isinstance(v, types.ModuleType) and v.__name__.startswith('pip.'))
- ]
- for name, entry in pip_related_entries:
- sys.modules.pop(name)
- del entry
+ purge_pip()
- del pip
- sys_modules_pip = sys.modules.pop('pip', None)
- if sys_modules_pip is not None:
- del sys_modules_pip
if HAS_PIP is True:
if not hasattr(purge_pip, '__pip_ver__'):
--
2.23.0

View File

@ -1,4 +1,4 @@
From 31b9186f48ac37e2b814b8db61ec1d5a5868659f Mon Sep 17 00:00:00 2001
From 900d63bc5e85496e16373025457561b405f2329f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Tue, 6 Nov 2018 16:38:54 +0000
@ -15,10 +15,10 @@ Remove unicode references
1 file changed, 45 insertions(+)
diff --git a/tests/integration/pillar/test_git_pillar.py b/tests/integration/pillar/test_git_pillar.py
index 9ade88840b..ab3b1a89cf 100644
index 2e549f3948..d417a7ebc3 100644
--- a/tests/integration/pillar/test_git_pillar.py
+++ b/tests/integration/pillar/test_git_pillar.py
@@ -1388,6 +1388,51 @@ class TestPygit2SSH(GitPillarSSHTestBase):
@@ -1382,6 +1382,51 @@ class TestPygit2SSH(GitPillarSSHTestBase):
'nested_dict': {'master': True}}}
)

View File

@ -1,4 +1,4 @@
From 682964fe1cb3fc859eb72da524beaeb2a85ff610 Mon Sep 17 00:00:00 2001
From 2cb7515f83e2c358b84724e4eb581daa78012fdf Mon Sep 17 00:00:00 2001
From: Bo Maryniuk <bo@suse.de>
Date: Fri, 28 Sep 2018 15:22:33 +0200
Subject: [PATCH] Fix IPv6 scope (bsc#1108557)
@ -73,10 +73,10 @@ Reverse skipping tests: if no ipaddress
1 file changed, 74 insertions(+)
diff --git a/salt/_compat.py b/salt/_compat.py
index ed6f4a38ea..61842b4bf3 100644
index e999605d2c..965bb90da3 100644
--- a/salt/_compat.py
+++ b/salt/_compat.py
@@ -229,7 +229,81 @@ class IPv6InterfaceScoped(ipaddress.IPv6Interface, IPv6AddressScoped):
@@ -230,7 +230,81 @@ class IPv6InterfaceScoped(ipaddress.IPv6Interface, IPv6AddressScoped):
self.hostmask = self.network.hostmask

View File

@ -1,4 +1,4 @@
From f81e6022b51b10406e52401fc75d7ef1ae93c55d Mon Sep 17 00:00:00 2001
From bfdd7f946d56d799e89b33f7e3b72426732b0195 Mon Sep 17 00:00:00 2001
From: Bo Maryniuk <bo@suse.de>
Date: Wed, 9 Jan 2019 16:08:19 +0100
Subject: [PATCH] Fix issue #2068 test
@ -13,7 +13,7 @@ Minor update: more correct is-dict check.
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/salt/state.py b/salt/state.py
index c3119b6a33..6af1b89037 100644
index bc5277554e..2fa5f64ca5 100644
--- a/salt/state.py
+++ b/salt/state.py
@@ -25,6 +25,7 @@ import traceback
@ -24,7 +24,7 @@ index c3119b6a33..6af1b89037 100644
# Import salt libs
import salt.loader
@@ -2776,16 +2777,18 @@ class State(object):
@@ -2896,16 +2897,18 @@ class State(object):
'''
for chunk in high:
state = high[chunk]

View File

@ -1,129 +0,0 @@
From 14f7acde30ea99abed535ab9491e9881ce609fdf Mon Sep 17 00:00:00 2001
From: Sergey Yurchik <srg91.snz@gmail.com>
Date: Fri, 10 Jan 2020 12:19:54 +0300
Subject: [PATCH] Fix load cached grain "osrelease_info"
Before fix the module `loader._load_cached_grains` loaded `osrelease_info` grain as list.
But everythere it expects `tuple`.
Now we force `osrelease_info` type and it works as expected.
Fixes #54908
Sanitize grains loaded from roster_grains.json
Ensure _format_cached_grains is called on state.pkg test
---
salt/loader.py | 13 ++++++++++++-
salt/modules/state.py | 3 ++-
tests/unit/modules/test_state.py | 4 +++-
tests/unit/test_loader.py | 28 ++++++++++++++++++++++++++++
4 files changed, 45 insertions(+), 3 deletions(-)
diff --git a/salt/loader.py b/salt/loader.py
index 26b44de511d77dd498a1db655a44144f6e9fbf0a..984d80758ba8bd733a211f42d89e2d4e4fb25341 100644
--- a/salt/loader.py
+++ b/salt/loader.py
@@ -689,6 +689,17 @@ def grain_funcs(opts, proxy=None):
return ret
+def _format_cached_grains(cached_grains):
+ """
+ Returns cached grains with fixed types, like tuples.
+ """
+ if cached_grains.get('osrelease_info'):
+ osrelease_info = cached_grains['osrelease_info']
+ if isinstance(osrelease_info, list):
+ cached_grains['osrelease_info'] = tuple(osrelease_info)
+ return cached_grains
+
+
def _load_cached_grains(opts, cfn):
'''
Returns the grains cached in cfn, or None if the cache is too old or is
@@ -721,7 +732,7 @@ def _load_cached_grains(opts, cfn):
log.debug('Cached grains are empty, cache might be corrupted. Refreshing.')
return None
- return cached_grains
+ return _format_cached_grains(cached_grains)
except (IOError, OSError):
return None
diff --git a/salt/modules/state.py b/salt/modules/state.py
index a757e401d4f5c8fff33ad4b0f30f2882631fab80..197d69e1ff53e759ab268b9d562e6eb54f828e4c 100644
--- a/salt/modules/state.py
+++ b/salt/modules/state.py
@@ -42,6 +42,7 @@ import salt.defaults.exitcodes
from salt.exceptions import CommandExecutionError, SaltInvocationError
from salt.runners.state import orchestrate as _orchestrate
from salt.utils.odict import OrderedDict
+from salt.loader import _format_cached_grains
# Import 3rd-party libs
from salt.ext import six
@@ -2177,7 +2178,7 @@ def pkg(pkg_path,
roster_grains_json = os.path.join(root, 'roster_grains.json')
if os.path.isfile(roster_grains_json):
with salt.utils.files.fopen(roster_grains_json, 'r') as fp_:
- roster_grains = salt.utils.json.load(fp_)
+ roster_grains = _format_cached_grains(salt.utils.json.load(fp_))
if os.path.isfile(roster_grains_json):
popts['grains'] = roster_grains
diff --git a/tests/unit/modules/test_state.py b/tests/unit/modules/test_state.py
index 0d15458be0a9b187efc7b2963612ea4bb078918e..8fc90d33bf22bf37a9597ecd1c6ff7ad43a60b6d 100644
--- a/tests/unit/modules/test_state.py
+++ b/tests/unit/modules/test_state.py
@@ -1164,8 +1164,10 @@ class StateTestCase(TestCase, LoaderModuleMockMixin):
MockTarFile.path = ""
with patch('salt.utils.files.fopen', mock_open()), \
- patch.object(salt.utils.json, 'loads', mock_json_loads_true):
+ patch.object(salt.utils.json, 'loads', mock_json_loads_true), \
+ patch.object(state, '_format_cached_grains', MagicMock()):
self.assertEqual(state.pkg(tar_file, 0, "md5"), True)
+ state._format_cached_grains.assert_called_once()
MockTarFile.path = ""
if six.PY2:
diff --git a/tests/unit/test_loader.py b/tests/unit/test_loader.py
index 38dcb181090c61935835f14dd780bad2aa02d9e8..4c2c1b44af2d2931505ddcbb4339e087be88b4fc 100644
--- a/tests/unit/test_loader.py
+++ b/tests/unit/test_loader.py
@@ -1334,3 +1334,31 @@ class LazyLoaderOptimizationOrderTest(TestCase):
basename = os.path.basename(filename)
expected = 'lazyloadertest.py' if six.PY3 else 'lazyloadertest.pyc'
assert basename == expected, basename
+
+
+class LoaderLoadCachedGrainsTest(TestCase):
+ '''
+ Test how the loader works with cached grains
+ '''
+
+ @classmethod
+ def setUpClass(cls):
+ cls.opts = salt.config.minion_config(None)
+ if not os.path.isdir(RUNTIME_VARS.TMP):
+ os.makedirs(RUNTIME_VARS.TMP)
+
+ def setUp(self):
+ self.cache_dir = tempfile.mkdtemp(dir=RUNTIME_VARS.TMP)
+ self.addCleanup(shutil.rmtree, self.cache_dir, ignore_errors=True)
+
+ self.opts['cachedir'] = self.cache_dir
+ self.opts['grains_cache'] = True
+ self.opts['grains'] = salt.loader.grains(self.opts)
+
+ def test_osrelease_info_has_correct_type(self):
+ '''
+ Make sure osrelease_info is tuple after caching
+ '''
+ grains = salt.loader.grains(self.opts)
+ osrelease_info = grains['osrelease_info']
+ assert isinstance(osrelease_info, tuple), osrelease_info
--
2.23.0

View File

@ -1,4 +1,4 @@
From d6432f9ebaba32f75a476a6d4a2989d54d149731 Mon Sep 17 00:00:00 2001
From 77d53d9567b7aec045a8fffd29afcb76a8405caf Mon Sep 17 00:00:00 2001
From: Mihai Dinca <mdinca@suse.de>
Date: Mon, 16 Sep 2019 11:27:30 +0200
Subject: [PATCH] Fix memory leak produced by batch async find_jobs
@ -153,10 +153,10 @@ index 8c8f481e34..8a67331102 100644
self.scheduled = False
+ yield
diff --git a/salt/client/__init__.py b/salt/client/__init__.py
index aff354a021..0bb6d2b111 100644
index 3bbc7f9de7..a48d79ef8d 100644
--- a/salt/client/__init__.py
+++ b/salt/client/__init__.py
@@ -1624,6 +1624,7 @@ class LocalClient(object):
@@ -1622,6 +1622,7 @@ class LocalClient(object):
'key': self.key,
'tgt_type': tgt_type,
'ret': ret,
@ -165,7 +165,7 @@ index aff354a021..0bb6d2b111 100644
# if kwargs are passed, pack them.
diff --git a/salt/master.py b/salt/master.py
index ee968410f7..224725a1ba 100644
index 5e2277ba76..3abf7ae60b 100644
--- a/salt/master.py
+++ b/salt/master.py
@@ -2044,7 +2044,6 @@ class ClearFuncs(object):

View File

@ -0,0 +1,131 @@
From 1a3e69af7c69a4893642dd1e9a9c4d3eb99cf874 Mon Sep 17 00:00:00 2001
From: Erik Johnson <erik.johnson@level3.com>
Date: Mon, 17 Feb 2020 18:43:06 -0600
Subject: [PATCH] Fix regression in service states with reload argument
Add functional test
Fix failing test
Add __opts__ and __grains__ just in case
Skip on OSX for now
---
salt/states/service.py | 2 +-
tests/unit/states/test_service.py | 79 +++++++++++++++++++++++++++++--
2 files changed, 75 insertions(+), 6 deletions(-)
diff --git a/salt/states/service.py b/salt/states/service.py
index 987e37cd421713313c41db4459b85019c041d549..89afa0dfa625e9ee3d9ecd7566232452d79ca99c 100644
--- a/salt/states/service.py
+++ b/salt/states/service.py
@@ -488,7 +488,7 @@ def running(name,
time.sleep(init_delay)
# only force a change state if we have explicitly detected them
- after_toggle_status = __salt__['service.status'](name, sig, **kwargs)
+ after_toggle_status = __salt__['service.status'](name, sig, **status_kwargs)
if 'service.enabled' in __salt__:
after_toggle_enable_status = __salt__['service.enabled'](name)
else:
diff --git a/tests/unit/states/test_service.py b/tests/unit/states/test_service.py
index 30c716025495f537efddf69bf6df8c68bc938e2e..3eead4c3576eefdd8d96eec4cc113edf194ebbc6 100644
--- a/tests/unit/states/test_service.py
+++ b/tests/unit/states/test_service.py
@@ -7,14 +7,15 @@
from __future__ import absolute_import, print_function, unicode_literals
# Import Salt Testing Libs
+from tests.support.helpers import destructiveTest
from tests.support.mixins import LoaderModuleMockMixin
-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 MagicMock, patch
# Import Salt Libs
+import salt.utils.platform
+import salt.config
+import salt.loader
import salt.states.service as service
@@ -251,3 +252,71 @@ class ServiceTestCase(TestCase, LoaderModuleMockMixin):
ret[3])
self.assertDictEqual(service.mod_watch("salt", "stack"), ret[1])
+
+
+@destructiveTest
+@skipIf(salt.utils.platform.is_darwin(), "service.running is currently failing on OSX")
+class ServiceTestCaseFunctional(TestCase, LoaderModuleMockMixin):
+ '''
+ Validate the service state
+ '''
+ def setup_loader_modules(self):
+ self.opts = salt.config.DEFAULT_MINION_OPTS.copy()
+ self.opts['grains'] = salt.loader.grains(self.opts)
+ self.utils = salt.loader.utils(self.opts)
+ self.modules = salt.loader.minion_mods(self.opts, utils=self.utils)
+
+ self.service_name = 'cron'
+ cmd_name = 'crontab'
+ os_family = self.opts['grains']['os_family']
+ os_release = self.opts['grains']['osrelease']
+ if os_family == 'RedHat':
+ self.service_name = 'crond'
+ elif os_family == 'Arch':
+ self.service_name = 'sshd'
+ cmd_name = 'systemctl'
+ elif os_family == 'MacOS':
+ self.service_name = 'org.ntp.ntpd'
+ if int(os_release.split('.')[1]) >= 13:
+ self.service_name = 'com.openssh.sshd'
+ elif os_family == 'Windows':
+ self.service_name = 'Spooler'
+
+ if os_family != 'Windows' and salt.utils.path.which(cmd_name) is None:
+ self.skipTest('{0} is not installed'.format(cmd_name))
+
+ return {
+ service: {
+ '__grains__': self.opts['grains'],
+ '__opts__': self.opts,
+ '__salt__': self.modules,
+ '__utils__': self.utils,
+ },
+ }
+
+ def setUp(self):
+ self.pre_srv_enabled = True if self.service_name in self.modules['service.get_enabled']() else False
+ self.post_srv_disable = False
+ if not self.pre_srv_enabled:
+ self.modules['service.enable'](self.service_name)
+ self.post_srv_disable = True
+
+ def tearDown(self):
+ if self.post_srv_disable:
+ self.modules['service.disable'](self.service_name)
+
+ def test_running_with_reload(self):
+ with patch.dict(service.__opts__, {'test': False}):
+ service.dead(self.service_name, enable=False)
+ result = service.running(name=self.service_name, enable=True, reload=False)
+
+ expected = {
+ 'changes': {
+ self.service_name: True
+ },
+ 'comment': 'Service {0} has been enabled, and is '
+ 'running'.format(self.service_name),
+ 'name': self.service_name,
+ 'result': True
+ }
+ self.assertDictEqual(result, expected)
--
2.23.0

View File

@ -0,0 +1,28 @@
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

View File

@ -1,4 +1,4 @@
From 91a864f7613927e47b9271bf0f947cf96a3bbfbf Mon Sep 17 00:00:00 2001
From 6bb7b6c4a530abb7e831449545a35ee5ede49dcb Mon Sep 17 00:00:00 2001
From: Bo Maryniuk <bo@suse.de>
Date: Thu, 11 Oct 2018 16:20:40 +0200
Subject: [PATCH] Fix unit test for grains core
@ -8,7 +8,7 @@ Subject: [PATCH] Fix unit test for grains core
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/tests/unit/grains/test_core.py b/tests/unit/grains/test_core.py
index 8c45ee194a..c85225e959 100644
index b31f5dcddd..c40595eb3f 100644
--- a/tests/unit/grains/test_core.py
+++ b/tests/unit/grains/test_core.py
@@ -68,11 +68,10 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):

View File

@ -1,4 +1,4 @@
From 357865060d439e7bf54e5971deb68c0d70cfe91b Mon Sep 17 00:00:00 2001
From e9f2af1256a52d58a7c8e6dd0122eb6d5cc47dd3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Wed, 4 Mar 2020 10:13:43 +0000

View File

@ -1,217 +0,0 @@
From 46aeb732ed61051d436ac748bd95a50c6379682a Mon Sep 17 00:00:00 2001
From: Cedric Bosdonnat <cbosdonnat@suse.com>
Date: Mon, 16 Dec 2019 11:27:49 +0100
Subject: [PATCH] Fix virt states to not fail on VMs already stopped.
(#195)
The virt.stopped and virt.powered_off states need to do nothing and
not fail if one of the targeted VMs is already in shutdown state.
---
salt/states/virt.py | 45 ++++++++++++++++++++--------------
tests/unit/states/test_virt.py | 36 +++++++++++++++++++++++++++
2 files changed, 63 insertions(+), 18 deletions(-)
diff --git a/salt/states/virt.py b/salt/states/virt.py
index 32a9e31ae5..68e9ac6fb6 100644
--- a/salt/states/virt.py
+++ b/salt/states/virt.py
@@ -145,35 +145,45 @@ def keys(name, basepath='/etc/pki', **kwargs):
return ret
-def _virt_call(domain, function, section, comment,
+def _virt_call(domain, function, section, comment, state=None,
connection=None, username=None, password=None, **kwargs):
'''
Helper to call the virt functions. Wildcards supported.
- :param domain:
- :param function:
- :param section:
- :param comment:
- :return:
+ :param domain: the domain to apply the function on. Can contain wildcards.
+ :param function: virt function to call
+ :param section: key for the changed domains in the return changes dictionary
+ :param comment: comment to return
+ :param state: the expected final state of the VM. If None the VM state won't be checked.
+ :return: the salt state return
'''
ret = {'name': domain, 'changes': {}, 'result': True, 'comment': ''}
targeted_domains = fnmatch.filter(__salt__['virt.list_domains'](), domain)
changed_domains = list()
ignored_domains = list()
+ noaction_domains = list()
for targeted_domain in targeted_domains:
try:
- response = __salt__['virt.{0}'.format(function)](targeted_domain,
- connection=connection,
- username=username,
- password=password,
- **kwargs)
- if isinstance(response, dict):
- response = response['name']
- changed_domains.append({'domain': targeted_domain, function: response})
+ action_needed = True
+ # If a state has been provided, use it to see if we have something to do
+ if state is not None:
+ domain_state = __salt__['virt.vm_state'](targeted_domain)
+ action_needed = domain_state.get(targeted_domain) != state
+ if action_needed:
+ response = __salt__['virt.{0}'.format(function)](targeted_domain,
+ connection=connection,
+ username=username,
+ password=password,
+ **kwargs)
+ if isinstance(response, dict):
+ response = response['name']
+ changed_domains.append({'domain': targeted_domain, function: response})
+ else:
+ noaction_domains.append(targeted_domain)
except libvirt.libvirtError as err:
ignored_domains.append({'domain': targeted_domain, 'issue': six.text_type(err)})
if not changed_domains:
- ret['result'] = False
+ ret['result'] = not ignored_domains and bool(targeted_domains)
ret['comment'] = 'No changes had happened'
if ignored_domains:
ret['changes'] = {'ignored': ignored_domains}
@@ -206,7 +216,7 @@ def stopped(name, connection=None, username=None, password=None):
virt.stopped
'''
- return _virt_call(name, 'shutdown', 'stopped', "Machine has been shut down",
+ return _virt_call(name, 'shutdown', 'stopped', 'Machine has been shut down', state='shutdown',
connection=connection, username=username, password=password)
@@ -231,8 +241,7 @@ def powered_off(name, connection=None, username=None, password=None):
domain_name:
virt.stopped
'''
-
- return _virt_call(name, 'stop', 'unpowered', 'Machine has been powered off',
+ return _virt_call(name, 'stop', 'unpowered', 'Machine has been powered off', state='shutdown',
connection=connection, username=username, password=password)
diff --git a/tests/unit/states/test_virt.py b/tests/unit/states/test_virt.py
index 2904fa224d..2af5caca1b 100644
--- a/tests/unit/states/test_virt.py
+++ b/tests/unit/states/test_virt.py
@@ -378,8 +378,11 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
'result': True}
shutdown_mock = MagicMock(return_value=True)
+
+ # Normal case
with patch.dict(virt.__salt__, { # pylint: disable=no-member
'virt.list_domains': MagicMock(return_value=['myvm', 'vm1']),
+ 'virt.vm_state': MagicMock(return_value={'myvm': 'running'}),
'virt.shutdown': shutdown_mock
}):
ret.update({'changes': {
@@ -389,8 +392,10 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
self.assertDictEqual(virt.stopped('myvm'), ret)
shutdown_mock.assert_called_with('myvm', connection=None, username=None, password=None)
+ # Normal case with user-provided connection parameters
with patch.dict(virt.__salt__, { # pylint: disable=no-member
'virt.list_domains': MagicMock(return_value=['myvm', 'vm1']),
+ 'virt.vm_state': MagicMock(return_value={'myvm': 'running'}),
'virt.shutdown': shutdown_mock,
}):
self.assertDictEqual(virt.stopped('myvm',
@@ -399,8 +404,10 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
password='secret'), ret)
shutdown_mock.assert_called_with('myvm', connection='myconnection', username='user', password='secret')
+ # Case where an error occurred during the shutdown
with patch.dict(virt.__salt__, { # pylint: disable=no-member
'virt.list_domains': MagicMock(return_value=['myvm', 'vm1']),
+ 'virt.vm_state': MagicMock(return_value={'myvm': 'running'}),
'virt.shutdown': MagicMock(side_effect=self.mock_libvirt.libvirtError('Some error'))
}):
ret.update({'changes': {'ignored': [{'domain': 'myvm', 'issue': 'Some error'}]},
@@ -408,10 +415,21 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
'comment': 'No changes had happened'})
self.assertDictEqual(virt.stopped('myvm'), ret)
+ # Case there the domain doesn't exist
with patch.dict(virt.__salt__, {'virt.list_domains': MagicMock(return_value=[])}): # pylint: disable=no-member
ret.update({'changes': {}, 'result': False, 'comment': 'No changes had happened'})
self.assertDictEqual(virt.stopped('myvm'), ret)
+ # Case where the domain is already stopped
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
+ 'virt.list_domains': MagicMock(return_value=['myvm', 'vm1']),
+ 'virt.vm_state': MagicMock(return_value={'myvm': 'shutdown'})
+ }):
+ ret.update({'changes': {},
+ 'result': True,
+ 'comment': 'No changes had happened'})
+ self.assertDictEqual(virt.stopped('myvm'), ret)
+
def test_powered_off(self):
'''
powered_off state test cases.
@@ -421,8 +439,11 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
'result': True}
stop_mock = MagicMock(return_value=True)
+
+ # Normal case
with patch.dict(virt.__salt__, { # pylint: disable=no-member
'virt.list_domains': MagicMock(return_value=['myvm', 'vm1']),
+ 'virt.vm_state': MagicMock(return_value={'myvm': 'running'}),
'virt.stop': stop_mock
}):
ret.update({'changes': {
@@ -432,8 +453,10 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
self.assertDictEqual(virt.powered_off('myvm'), ret)
stop_mock.assert_called_with('myvm', connection=None, username=None, password=None)
+ # Normal case with user-provided connection parameters
with patch.dict(virt.__salt__, { # pylint: disable=no-member
'virt.list_domains': MagicMock(return_value=['myvm', 'vm1']),
+ 'virt.vm_state': MagicMock(return_value={'myvm': 'running'}),
'virt.stop': stop_mock,
}):
self.assertDictEqual(virt.powered_off('myvm',
@@ -442,8 +465,10 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
password='secret'), ret)
stop_mock.assert_called_with('myvm', connection='myconnection', username='user', password='secret')
+ # Case where an error occurred during the poweroff
with patch.dict(virt.__salt__, { # pylint: disable=no-member
'virt.list_domains': MagicMock(return_value=['myvm', 'vm1']),
+ 'virt.vm_state': MagicMock(return_value={'myvm': 'running'}),
'virt.stop': MagicMock(side_effect=self.mock_libvirt.libvirtError('Some error'))
}):
ret.update({'changes': {'ignored': [{'domain': 'myvm', 'issue': 'Some error'}]},
@@ -451,10 +476,21 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
'comment': 'No changes had happened'})
self.assertDictEqual(virt.powered_off('myvm'), ret)
+ # Case there the domain doesn't exist
with patch.dict(virt.__salt__, {'virt.list_domains': MagicMock(return_value=[])}): # pylint: disable=no-member
ret.update({'changes': {}, 'result': False, 'comment': 'No changes had happened'})
self.assertDictEqual(virt.powered_off('myvm'), ret)
+ # Case where the domain is already stopped
+ with patch.dict(virt.__salt__, { # pylint: disable=no-member
+ 'virt.list_domains': MagicMock(return_value=['myvm', 'vm1']),
+ 'virt.vm_state': MagicMock(return_value={'myvm': 'shutdown'})
+ }):
+ ret.update({'changes': {},
+ 'result': True,
+ 'comment': 'No changes had happened'})
+ self.assertDictEqual(virt.powered_off('myvm'), ret)
+
def test_snapshot(self):
'''
snapshot state test cases.
--
2.23.0

View File

@ -1,374 +0,0 @@
From ab55daa8b642f7b7fde589f971bb078eea098059 Mon Sep 17 00:00:00 2001
From: Cedric Bosdonnat <cbosdonnat@suse.com>
Date: Tue, 3 Sep 2019 15:18:04 +0200
Subject: [PATCH] Fix virt.full_info (#176)
* virt.get_xml doesn't take a domain object
In some places in the virt module, the get_xml function was called with
a domain object, leading to runtime errors like the following one:
'ERROR: The VM "<libvirt.virDomain object at 0x7fad04208650>" is not present'
* qemu-img info needs -U flag on running VMs
When getting VM disks informations on a running VM, the following error
occured:
The minion function caused an exception: Traceback (most recent call last):
File "/usr/lib/python3.6/site-packages/salt/minion.py", line 1673, in _thread_return
return_data = minion_instance.executors[fname](opts, data, func, args, kwargs)
File "/usr/lib/python3.6/site-packages/salt/executors/direct_call.py", line 12, in execute
return func(*args, **kwargs)
File "/usr/lib/python3.6/site-packages/salt/modules/virt.py", line 2411, in full_info
'vm_info': vm_info()}
File "/usr/lib/python3.6/site-packages/salt/modules/virt.py", line 2020, in vm_info
info[domain.name()] = _info(domain)
File "/usr/lib/python3.6/site-packages/salt/modules/virt.py", line 2004, in _info
'disks': _get_disks(dom),
File "/usr/lib/python3.6/site-packages/salt/modules/virt.py", line 465, in _get_disks
output = _parse_qemu_img_info(qemu_output)
File "/usr/lib/python3.6/site-packages/salt/modules/virt.py", line 287, in _parse_qemu_img_info
raw_infos = salt.utils.json.loads(info)
File "/usr/lib/python3.6/site-packages/salt/utils/json.py", line 92, in loads
return json_module.loads(s, **kwargs)
File "/usr/lib64/python3.6/json/__init__.py", line 354, in loads
return _default_decoder.decode(s)
File "/usr/lib64/python3.6/json/decoder.py", line 339, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/lib64/python3.6/json/decoder.py", line 357, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
This is due to the fact that qemu-img can't get infos on a disk that is
already used like by a running VM. Using the qemu-img -U flag gets it
running in all cases.
---
salt/modules/virt.py | 10 +-
tests/unit/modules/test_virt.py | 242 +++++++++++++++++++++-------------------
2 files changed, 132 insertions(+), 120 deletions(-)
diff --git a/salt/modules/virt.py b/salt/modules/virt.py
index 96c17bd60b..d01b6c3f1e 100644
--- a/salt/modules/virt.py
+++ b/salt/modules/virt.py
@@ -331,7 +331,7 @@ def _get_uuid(dom):
salt '*' virt.get_uuid <domain>
'''
- return ElementTree.fromstring(get_xml(dom)).find('uuid').text
+ return ElementTree.fromstring(dom.XMLDesc(0)).find('uuid').text
def _get_on_poweroff(dom):
@@ -344,7 +344,7 @@ def _get_on_poweroff(dom):
salt '*' virt.get_on_restart <domain>
'''
- node = ElementTree.fromstring(get_xml(dom)).find('on_poweroff')
+ node = ElementTree.fromstring(dom.XMLDesc(0)).find('on_poweroff')
return node.text if node is not None else ''
@@ -358,7 +358,7 @@ def _get_on_reboot(dom):
salt '*' virt.get_on_reboot <domain>
'''
- node = ElementTree.fromstring(get_xml(dom)).find('on_reboot')
+ node = ElementTree.fromstring(dom.XMLDesc(0)).find('on_reboot')
return node.text if node is not None else ''
@@ -372,7 +372,7 @@ def _get_on_crash(dom):
salt '*' virt.get_on_crash <domain>
'''
- node = ElementTree.fromstring(get_xml(dom)).find('on_crash')
+ node = ElementTree.fromstring(dom.XMLDesc(0)).find('on_crash')
return node.text if node is not None else ''
@@ -458,7 +458,7 @@ def _get_disks(dom):
if driver is not None and driver.get('type') == 'qcow2':
try:
stdout = subprocess.Popen(
- ['qemu-img', 'info', '--output', 'json', '--backing-chain', disk['file']],
+ ['qemu-img', 'info', '-U', '--output', 'json', '--backing-chain', disk['file']],
shell=False,
stdout=subprocess.PIPE).communicate()[0]
qemu_output = salt.utils.stringutils.to_str(stdout)
diff --git a/tests/unit/modules/test_virt.py b/tests/unit/modules/test_virt.py
index e644e62452..4d20e998d8 100644
--- a/tests/unit/modules/test_virt.py
+++ b/tests/unit/modules/test_virt.py
@@ -81,7 +81,9 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
mock_domain.XMLDesc.return_value = xml # pylint: disable=no-member
# Return state as shutdown
- mock_domain.info.return_value = [4, 0, 0, 0] # pylint: disable=no-member
+ mock_domain.info.return_value = [4, 2048 * 1024, 1024 * 1024, 2, 1234] # pylint: disable=no-member
+ mock_domain.ID.return_value = 1
+ mock_domain.name.return_value = name
return mock_domain
def test_disk_profile_merge(self):
@@ -1394,49 +1396,6 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
re.match('^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$',
interface_attrs['mac'], re.I))
- def test_get_graphics(self):
- '''
- Test virt.get_graphics()
- '''
- xml = '''<domain type='kvm' id='7'>
- <name>test-vm</name>
- <devices>
- <graphics type='vnc' port='5900' autoport='yes' listen='0.0.0.0'>
- <listen type='address' address='0.0.0.0'/>
- </graphics>
- </devices>
- </domain>
- '''
- self.set_mock_vm("test-vm", xml)
-
- graphics = virt.get_graphics('test-vm')
- self.assertEqual('vnc', graphics['type'])
- self.assertEqual('5900', graphics['port'])
- self.assertEqual('0.0.0.0', graphics['listen'])
-
- def test_get_nics(self):
- '''
- Test virt.get_nics()
- '''
- xml = '''<domain type='kvm' id='7'>
- <name>test-vm</name>
- <devices>
- <interface type='bridge'>
- <mac address='ac:de:48:b6:8b:59'/>
- <source bridge='br0'/>
- <model type='virtio'/>
- <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
- </interface>
- </devices>
- </domain>
- '''
- self.set_mock_vm("test-vm", xml)
-
- nics = virt.get_nics('test-vm')
- nic = nics[list(nics)[0]]
- self.assertEqual('bridge', nic['type'])
- self.assertEqual('ac:de:48:b6:8b:59', nic['mac'])
-
def test_parse_qemu_img_info(self):
'''
Make sure that qemu-img info output is properly parsed
@@ -1558,77 +1517,6 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
],
}, virt._parse_qemu_img_info(qemu_infos))
- def test_get_disks(self):
- '''
- Test virt.get_disks()
- '''
- xml = '''<domain type='kvm' id='7'>
- <name>test-vm</name>
- <devices>
- <disk type='file' device='disk'>
- <driver name='qemu' type='qcow2'/>
- <source file='/disks/test.qcow2'/>
- <target dev='vda' bus='virtio'/>
- </disk>
- <disk type='file' device='cdrom'>
- <driver name='qemu' type='raw'/>
- <source file='/disks/test-cdrom.iso'/>
- <target dev='hda' bus='ide'/>
- <readonly/>
- </disk>
- </devices>
- </domain>
- '''
- self.set_mock_vm("test-vm", xml)
-
- qemu_infos = '''[{
- "virtual-size": 25769803776,
- "filename": "/disks/test.qcow2",
- "cluster-size": 65536,
- "format": "qcow2",
- "actual-size": 217088,
- "format-specific": {
- "type": "qcow2",
- "data": {
- "compat": "1.1",
- "lazy-refcounts": false,
- "refcount-bits": 16,
- "corrupt": false
- }
- },
- "full-backing-filename": "/disks/mybacking.qcow2",
- "backing-filename": "mybacking.qcow2",
- "dirty-flag": false
- },
- {
- "virtual-size": 25769803776,
- "filename": "/disks/mybacking.qcow2",
- "cluster-size": 65536,
- "format": "qcow2",
- "actual-size": 393744384,
- "format-specific": {
- "type": "qcow2",
- "data": {
- "compat": "1.1",
- "lazy-refcounts": false,
- "refcount-bits": 16,
- "corrupt": false
- }
- },
- "dirty-flag": false
- }]'''
-
- self.mock_popen.communicate.return_value = [qemu_infos] # pylint: disable=no-member
- disks = virt.get_disks('test-vm')
- disk = disks.get('vda')
- self.assertEqual('/disks/test.qcow2', disk['file'])
- self.assertEqual('disk', disk['type'])
- self.assertEqual('/disks/mybacking.qcow2', disk['backing file']['file'])
- cdrom = disks.get('hda')
- self.assertEqual('/disks/test-cdrom.iso', cdrom['file'])
- self.assertEqual('cdrom', cdrom['type'])
- self.assertFalse('backing file' in cdrom.keys())
-
@patch('salt.modules.virt.stop', return_value=True)
@patch('salt.modules.virt.undefine')
@patch('os.remove')
@@ -2994,3 +2882,127 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
virt.volume_delete('default', 'missing')
virt.volume_delete('missing', 'test_volume')
self.assertEqual(mock_delete.call_count, 2)
+
+ def test_full_info(self):
+ '''
+ Test virt.full_info
+ '''
+ xml = '''<domain type='kvm' id='7'>
+ <uuid>28deee33-4859-4f23-891c-ee239cffec94</uuid>
+ <name>test-vm</name>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <disk type='file' device='disk'>
+ <driver name='qemu' type='qcow2'/>
+ <source file='/disks/test.qcow2'/>
+ <target dev='vda' bus='virtio'/>
+ </disk>
+ <disk type='file' device='cdrom'>
+ <driver name='qemu' type='raw'/>
+ <source file='/disks/test-cdrom.iso'/>
+ <target dev='hda' bus='ide'/>
+ <readonly/>
+ </disk>
+ <interface type='bridge'>
+ <mac address='ac:de:48:b6:8b:59'/>
+ <source bridge='br0'/>
+ <model type='virtio'/>
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
+ </interface>
+ <graphics type='vnc' port='5900' autoport='yes' listen='0.0.0.0'>
+ <listen type='address' address='0.0.0.0'/>
+ </graphics>
+ </devices>
+ </domain>
+ '''
+ self.set_mock_vm("test-vm", xml)
+
+ qemu_infos = '''[{
+ "virtual-size": 25769803776,
+ "filename": "/disks/test.qcow2",
+ "cluster-size": 65536,
+ "format": "qcow2",
+ "actual-size": 217088,
+ "format-specific": {
+ "type": "qcow2",
+ "data": {
+ "compat": "1.1",
+ "lazy-refcounts": false,
+ "refcount-bits": 16,
+ "corrupt": false
+ }
+ },
+ "full-backing-filename": "/disks/mybacking.qcow2",
+ "backing-filename": "mybacking.qcow2",
+ "dirty-flag": false
+ },
+ {
+ "virtual-size": 25769803776,
+ "filename": "/disks/mybacking.qcow2",
+ "cluster-size": 65536,
+ "format": "qcow2",
+ "actual-size": 393744384,
+ "format-specific": {
+ "type": "qcow2",
+ "data": {
+ "compat": "1.1",
+ "lazy-refcounts": false,
+ "refcount-bits": 16,
+ "corrupt": false
+ }
+ },
+ "dirty-flag": false
+ }]'''
+
+ self.mock_popen.communicate.return_value = [qemu_infos] # pylint: disable=no-member
+
+ self.mock_conn.getInfo = MagicMock(return_value=['x86_64', 4096, 8, 2712, 1, 2, 4, 2])
+
+ actual = virt.full_info()
+
+ # Test the hypervisor infos
+ self.assertEqual(2816, actual['freemem'])
+ self.assertEqual(6, actual['freecpu'])
+ self.assertEqual(4, actual['node_info']['cpucores'])
+ self.assertEqual(2712, actual['node_info']['cpumhz'])
+ self.assertEqual('x86_64', actual['node_info']['cpumodel'])
+ self.assertEqual(8, actual['node_info']['cpus'])
+ self.assertEqual(2, actual['node_info']['cputhreads'])
+ self.assertEqual(1, actual['node_info']['numanodes'])
+ self.assertEqual(4096, actual['node_info']['phymemory'])
+ self.assertEqual(2, actual['node_info']['sockets'])
+
+ # Test the vm_info output:
+ self.assertEqual(2, actual['vm_info']['test-vm']['cpu'])
+ self.assertEqual(1234, actual['vm_info']['test-vm']['cputime'])
+ self.assertEqual(1024 * 1024, actual['vm_info']['test-vm']['mem'])
+ self.assertEqual(2048 * 1024, actual['vm_info']['test-vm']['maxMem'])
+ self.assertEqual('shutdown', actual['vm_info']['test-vm']['state'])
+ self.assertEqual('28deee33-4859-4f23-891c-ee239cffec94', actual['vm_info']['test-vm']['uuid'])
+ self.assertEqual('destroy', actual['vm_info']['test-vm']['on_crash'])
+ self.assertEqual('restart', actual['vm_info']['test-vm']['on_reboot'])
+ self.assertEqual('destroy', actual['vm_info']['test-vm']['on_poweroff'])
+
+ # Test the nics
+ nic = actual['vm_info']['test-vm']['nics']['ac:de:48:b6:8b:59']
+ self.assertEqual('bridge', nic['type'])
+ self.assertEqual('ac:de:48:b6:8b:59', nic['mac'])
+
+ # Test the disks
+ disks = actual['vm_info']['test-vm']['disks']
+ disk = disks.get('vda')
+ self.assertEqual('/disks/test.qcow2', disk['file'])
+ self.assertEqual('disk', disk['type'])
+ self.assertEqual('/disks/mybacking.qcow2', disk['backing file']['file'])
+ cdrom = disks.get('hda')
+ self.assertEqual('/disks/test-cdrom.iso', cdrom['file'])
+ self.assertEqual('cdrom', cdrom['type'])
+ self.assertFalse('backing file' in cdrom.keys())
+
+ # Test the graphics
+ graphics = actual['vm_info']['test-vm']['graphics']
+ self.assertEqual('vnc', graphics['type'])
+ self.assertEqual('5900', graphics['port'])
+ self.assertEqual('0.0.0.0', graphics['listen'])
--
2.16.4

View File

@ -1,54 +0,0 @@
From 4e315730c1cf91c8c3efb1aad3c6370953c78459 Mon Sep 17 00:00:00 2001
From: Cedric Bosdonnat <cbosdonnat@suse.com>
Date: Tue, 10 Dec 2019 10:27:26 +0100
Subject: [PATCH] Fix virt.get_hypervisor() (#188)
virt.get_hypervisor resulted in:
AttributeError: module 'salt.loader.dev-srv.tf.local.int.module.virt' has no attribute '_is_{}_hyper'
This was due to missplaced parenthese.
---
salt/modules/virt.py | 2 +-
tests/unit/modules/test_virt.py | 14 ++++++++++++++
2 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/salt/modules/virt.py b/salt/modules/virt.py
index 5e26964449..dedcf8cb6f 100644
--- a/salt/modules/virt.py
+++ b/salt/modules/virt.py
@@ -3309,7 +3309,7 @@ def get_hypervisor():
# To add a new 'foo' hypervisor, add the _is_foo_hyper function,
# add 'foo' to the list below and add it to the docstring with a .. versionadded::
hypervisors = ['kvm', 'xen']
- result = [hyper for hyper in hypervisors if getattr(sys.modules[__name__], '_is_{}_hyper').format(hyper)()]
+ result = [hyper for hyper in hypervisors if getattr(sys.modules[__name__], '_is_{}_hyper'.format(hyper))()]
return result[0] if result else None
diff --git a/tests/unit/modules/test_virt.py b/tests/unit/modules/test_virt.py
index d8efafc063..6f594a8ff3 100644
--- a/tests/unit/modules/test_virt.py
+++ b/tests/unit/modules/test_virt.py
@@ -3044,3 +3044,17 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
# Shouldn't be called with another parameter so far since those are not implemented
# and thus throwing exceptions.
mock_pool.delete.assert_called_once_with(self.mock_libvirt.VIR_STORAGE_POOL_DELETE_NORMAL)
+
+ @patch('salt.modules.virt._is_kvm_hyper', return_value=True)
+ @patch('salt.modules.virt._is_xen_hyper', return_value=False)
+ def test_get_hypervisor(self, isxen_mock, iskvm_mock):
+ '''
+ test the virt.get_hypervisor() function
+ '''
+ self.assertEqual('kvm', virt.get_hypervisor())
+
+ iskvm_mock.return_value = False
+ self.assertIsNone(virt.get_hypervisor())
+
+ isxen_mock.return_value = True
+ self.assertEqual('xen', virt.get_hypervisor())
--
2.23.0

View File

@ -0,0 +1,97 @@
From a8f0a15e4067ec278c8a2d690e3bf815523286ca Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Thu, 12 Mar 2020 13:26:51 +0000
Subject: [PATCH] Fix wrong test_mod_del_repo_multiline_values test after
rebase
---
tests/integration/modules/test_pkg.py | 56 +++------------------------
1 file changed, 6 insertions(+), 50 deletions(-)
diff --git a/tests/integration/modules/test_pkg.py b/tests/integration/modules/test_pkg.py
index 6f3767bfbd272848277b877d1fe640caf8f349f6..0f4c5c9d459c56bb485408f943c1dee49c46cd21 100644
--- a/tests/integration/modules/test_pkg.py
+++ b/tests/integration/modules/test_pkg.py
@@ -134,6 +134,10 @@ class PkgModuleTest(ModuleCase, SaltReturnAssertsMixin):
if repo is not None:
self.run_function('pkg.del_repo', [repo])
+ @destructiveTest
+ @requires_salt_modules('pkg.mod_repo', 'pkg.del_repo', 'pkg.get_repo')
+ @requires_network()
+ @requires_system_grains
def test_mod_del_repo_multiline_values(self):
'''
test modifying and deleting a software repository defined with multiline values
@@ -141,8 +145,9 @@ class PkgModuleTest(ModuleCase, SaltReturnAssertsMixin):
os_grain = self.run_function('grains.item', ['os'])['os']
repo = None
try:
- if os_grain in ['CentOS', 'RedHat']:
+ if os_grain in ['CentOS', 'RedHat', 'SUSE']:
my_baseurl = 'http://my.fake.repo/foo/bar/\n http://my.fake.repo.alt/foo/bar/'
+ expected_get_repo_baseurl_zypp = '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(
@@ -189,55 +194,6 @@ class PkgModuleTest(ModuleCase, SaltReturnAssertsMixin):
if repo is not None:
self.run_function('pkg.del_repo', [repo])
- def test_mod_del_repo_multiline_values(self):
- '''
- test modifying and deleting a software repository defined with multiline values
- '''
- os_grain = self.run_function('grains.item', ['os'])['os']
- repo = None
- try:
- if os_grain in ['CentOS', 'RedHat', 'SUSE']:
- my_baseurl = 'http://my.fake.repo/foo/bar/\n http://my.fake.repo.alt/foo/bar/'
- expected_get_repo_baseurl_zypp = '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
- gpgkey = 'https://my.fake.repo/foo/bar/MY-GPG-KEY.pub'
- failovermethod = 'priority'
- gpgcheck = 1
- enabled = 1
- ret = self.run_function(
- 'pkg.mod_repo',
- [repo],
- name=name,
- baseurl=baseurl,
- gpgkey=gpgkey,
- gpgcheck=gpgcheck,
- enabled=enabled,
- failovermethod=failovermethod,
- )
- # return data from pkg.mod_repo contains the file modified at
- # the top level, so use next(iter(ret)) to get that key
- self.assertNotEqual(ret, {})
- repo_info = ret[next(iter(ret))]
- self.assertIn(repo, repo_info)
- self.assertEqual(repo_info[repo]['baseurl'], my_baseurl)
- ret = self.run_function('pkg.get_repo', [repo])
- self.assertEqual(ret['baseurl'], expected_get_repo_baseurl)
- self.run_function('pkg.mod_repo', [repo])
- ret = self.run_function('pkg.get_repo', [repo])
- self.assertEqual(ret['baseurl'], expected_get_repo_baseurl)
- finally:
- if repo is not None:
- self.run_function('pkg.del_repo', [repo])
-
@requires_salt_modules('pkg.owner')
def test_owner(self):
'''
--
2.23.0

View File

@ -1,18 +1,17 @@
From 10c3c47a4c6ae173e2831d4256b8d8af6b33cf5a Mon Sep 17 00:00:00 2001
From eb51734ad93b1fa0c6bc8fde861fdabfe3e0d6b0 Mon Sep 17 00:00:00 2001
From: Mihai Dinca <mdinca@suse.de>
Date: Thu, 13 Jun 2019 17:48:55 +0200
Subject: [PATCH] Fix zypper pkg.list_pkgs expectation and dpkg mocking
---
tests/unit/modules/test_dpkg_lowpkg.py | 12 ++++++------
tests/unit/modules/test_zypperpkg.py | 2 +-
2 files changed, 7 insertions(+), 7 deletions(-)
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/tests/unit/modules/test_dpkg_lowpkg.py b/tests/unit/modules/test_dpkg_lowpkg.py
index d16ce3cc1a..98557a1d10 100644
index a0b3346f9d..bc564f080a 100644
--- a/tests/unit/modules/test_dpkg_lowpkg.py
+++ b/tests/unit/modules/test_dpkg_lowpkg.py
@@ -127,9 +127,9 @@ class DpkgTestCase(TestCase, LoaderModuleMockMixin):
@@ -125,9 +125,9 @@ class DpkgTestCase(TestCase, LoaderModuleMockMixin):
with patch.dict(dpkg.__salt__, {'cmd.run_all': mock}):
self.assertEqual(dpkg.file_dict('httpd'), 'Error: error')
@ -25,7 +24,7 @@ index d16ce3cc1a..98557a1d10 100644
def test_info(self):
'''
Test info
@@ -154,9 +154,9 @@ class DpkgTestCase(TestCase, LoaderModuleMockMixin):
@@ -152,9 +152,9 @@ class DpkgTestCase(TestCase, LoaderModuleMockMixin):
assert pkg_data['maintainer'] == 'Simpsons Developers <simpsons-devel-discuss@lists.springfield.org>'
assert pkg_data['license'] == 'BSD v3'
@ -38,19 +37,6 @@ index d16ce3cc1a..98557a1d10 100644
def test_info_attr(self):
'''
Test info with 'attr' parameter
diff --git a/tests/unit/modules/test_zypperpkg.py b/tests/unit/modules/test_zypperpkg.py
index 5c5091a570..a7063e47c6 100644
--- a/tests/unit/modules/test_zypperpkg.py
+++ b/tests/unit/modules/test_zypperpkg.py
@@ -659,7 +659,7 @@ Repository 'DUMMY' not found by its alias, number, or URI.
'install_date_time_t': 1503572639,
'epoch': None,
}],
- 'perseus-dummy.i586': [{
+ 'perseus-dummy': [{
'version': '1.1',
'release': '1.1',
'arch': 'i586',
--
2.16.4

View File

@ -1,4 +1,4 @@
From 3b85fa4cadc10881f2408e95700f7a6dae35ce21 Mon Sep 17 00:00:00 2001
From 0612549b3acfeb15e0b499b6f469d64062d6ae2d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Mon, 25 Jun 2018 13:06:40 +0100
@ -14,10 +14,10 @@ Fix '_find_remove_targets' after aligning Zypper with pkg state
1 file changed, 21 deletions(-)
diff --git a/salt/states/pkg.py b/salt/states/pkg.py
index 2034262b23..0aca1e0af8 100644
index c0fa2f6b69..a13d418400 100644
--- a/salt/states/pkg.py
+++ b/salt/states/pkg.py
@@ -455,16 +455,6 @@ def _find_remove_targets(name=None,
@@ -450,16 +450,6 @@ def _find_remove_targets(name=None,
if __grains__['os'] == 'FreeBSD' and origin:
cver = [k for k, v in six.iteritems(cur_pkgs) if v['origin'] == pkgname]
@ -34,7 +34,7 @@ index 2034262b23..0aca1e0af8 100644
else:
cver = cur_pkgs.get(pkgname, [])
@@ -871,17 +861,6 @@ def _verify_install(desired, new_pkgs, ignore_epoch=False, new_caps=None):
@@ -866,17 +856,6 @@ def _verify_install(desired, new_pkgs, ignore_epoch=False, new_caps=None):
cver = new_pkgs.get(pkgname.split('%')[0])
elif __grains__['os_family'] == 'Debian':
cver = new_pkgs.get(pkgname.split('=')[0])

View File

@ -1,4 +1,4 @@
From b9185139c688999c10ed90ca96120c6dad597666 Mon Sep 17 00:00:00 2001
From 9ec54e8c1394ab678c6129d98f07c6eafd446399 Mon Sep 17 00:00:00 2001
From: Erik Johnson <palehose@gmail.com>
Date: Fri, 24 Aug 2018 10:35:55 -0500
Subject: [PATCH] Fixes: CVE-2018-15750, CVE-2018-15751
@ -16,10 +16,10 @@ Update tornado test to correct authentication message
2 files changed, 2 insertions(+), 9 deletions(-)
diff --git a/salt/netapi/rest_cherrypy/app.py b/salt/netapi/rest_cherrypy/app.py
index 82615afb29..d230d822cd 100644
index fa1b540e5f..f8b500482b 100644
--- a/salt/netapi/rest_cherrypy/app.py
+++ b/salt/netapi/rest_cherrypy/app.py
@@ -1174,13 +1174,6 @@ class LowDataAdapter(object):
@@ -1176,13 +1176,6 @@ class LowDataAdapter(object):
except (TypeError, ValueError):
raise cherrypy.HTTPError(401, 'Invalid token')
@ -34,10 +34,10 @@ index 82615afb29..d230d822cd 100644
chunk['client'] = client
diff --git a/tests/integration/netapi/rest_tornado/test_app.py b/tests/integration/netapi/rest_tornado/test_app.py
index 2c348a679d..40cf1ce580 100644
index 10ec29f7fa..4102b5645a 100644
--- a/tests/integration/netapi/rest_tornado/test_app.py
+++ b/tests/integration/netapi/rest_tornado/test_app.py
@@ -276,8 +276,8 @@ class TestSaltAPIHandler(_SaltnadoIntegrationTestCase):
@@ -282,8 +282,8 @@ class TestSaltAPIHandler(_SaltnadoIntegrationTestCase):
self.assertIn('jid', ret[0]) # the first 2 are regular returns
self.assertIn('jid', ret[1])
self.assertIn('Failed to authenticate', ret[2]) # bad auth

View File

@ -1,4 +1,4 @@
From 11d5623a4b9b8ac40f29adb79f203ab8bbfdd8fc Mon Sep 17 00:00:00 2001
From 9a5f007a5baa4ba1d28b0e6708bac8b134e4891c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mihai=20Dinc=C4=83?= <dincamihai@users.noreply.github.com>
Date: Tue, 26 Nov 2019 18:26:31 +0100
Subject: [PATCH] Fixing StreamClosed issue
@ -28,6 +28,6 @@ index 754c257b36..c4545e3ebc 100644
self.ioloop = None
gc.collect()
--
2.23.0
2.16.4

View File

@ -1,4 +1,4 @@
From 9fc2217cd12d313f87d4db0e408e5b68b23c2330 Mon Sep 17 00:00:00 2001
From 98f3bd70aaa145b88e8bd4b947b578435e2b1e57 Mon Sep 17 00:00:00 2001
From: Bo Maryniuk <bo@suse.de>
Date: Wed, 14 Nov 2018 17:36:23 +0100
Subject: [PATCH] Get os_arch also without RPM package installed
@ -17,80 +17,29 @@ Add UT for OS arch detection when no CPU arch or machine can be determined
Remove unsupported testcase
---
salt/utils/pkg/rpm.py | 18 +++++---
tests/unit/utils/test_pkg.py | 105 ++++++++++++++++++++++++++-----------------
2 files changed, 77 insertions(+), 46 deletions(-)
tests/unit/utils/test_pkg.py | 48 ++++++++------------------------------------
1 file changed, 8 insertions(+), 40 deletions(-)
diff --git a/salt/utils/pkg/rpm.py b/salt/utils/pkg/rpm.py
index 94e231da4b..bb8c3fb589 100644
--- a/salt/utils/pkg/rpm.py
+++ b/salt/utils/pkg/rpm.py
@@ -9,7 +9,9 @@ import collections
import datetime
import logging
import subprocess
+import platform
import salt.utils.stringutils
+import salt.utils.path
# Import 3rd-party libs
from salt.ext import six
@@ -42,12 +44,16 @@ def get_osarch():
'''
Get the os architecture using rpm --eval
'''
- ret = subprocess.Popen(
- 'rpm --eval "%{_host_cpu}"',
- shell=True,
- close_fds=True,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE).communicate()[0]
+ if salt.utils.path.which('rpm'):
+ ret = subprocess.Popen(
+ 'rpm --eval "%{_host_cpu}"',
+ shell=True,
+ close_fds=True,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE).communicate()[0]
+ else:
+ ret = ''.join(list(filter(None, platform.uname()[-2:]))[-1:])
+
return salt.utils.stringutils.to_str(ret).strip() or 'unknown'
diff --git a/tests/unit/utils/test_pkg.py b/tests/unit/utils/test_pkg.py
index c293852058..361e0bf92f 100644
index e8b19bef14..361e0bf92f 100644
--- a/tests/unit/utils/test_pkg.py
+++ b/tests/unit/utils/test_pkg.py
@@ -1,47 +1,72 @@
# -*- coding: utf-8 -*-
@@ -2,51 +2,19 @@
-# Import Python libs
-from __future__ import absolute_import
-# Import Salt Libs
+from __future__ import absolute_import, unicode_literals, print_function
+
from __future__ import absolute_import, unicode_literals, print_function
-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 Testing Libs
-from tests.support.unit import TestCase
+from salt.utils.pkg import rpm
+
+try:
+ import pytest
+except ImportError:
+ pytest = None
from salt.utils.pkg import rpm
-
-class PkgUtilsTestCase(TestCase):
+@skipIf(NO_MOCK, NO_MOCK_REASON)
+@skipIf(pytest is None, 'PyTest is missing')
+class PkgRPMTestCase(TestCase):
'''
- '''
- TestCase for salt.utils.pkg module
+ Test case for pkg.rpm utils
'''
- '''
- test_parameters = [
- ("16.0.0.49153-0+f1", "", "16.0.0.49153-0+f1"),
- ("> 15.0.0", ">", "15.0.0"),
@ -124,57 +73,17 @@ index c293852058..361e0bf92f 100644
- oper, verstr = salt.utils.pkg.split_comparison(test_parameter[0])
- self.assertEqual(test_parameter[1], oper)
- self.assertEqual(test_parameter[2], verstr)
+
+ @patch('salt.utils.path.which', MagicMock(return_value=True))
+ def test_get_osarch_by_rpm(self):
+ '''
+ Get os_arch if RPM package is installed.
+ :return:
+ '''
+ subprocess_mock = MagicMock()
+ subprocess_mock.Popen = MagicMock()
+ subprocess_mock.Popen().communicate = MagicMock(return_value=['Z80'])
+ with patch('salt.utils.pkg.rpm.subprocess', subprocess_mock):
+ assert rpm.get_osarch() == 'Z80'
+ assert subprocess_mock.Popen.call_count == 2 # One within the mock
+ assert subprocess_mock.Popen.call_args[1]['close_fds']
+ assert subprocess_mock.Popen.call_args[1]['shell']
+ assert len(subprocess_mock.Popen.call_args_list) == 2
+ assert subprocess_mock.Popen.call_args[0][0] == 'rpm --eval "%{_host_cpu}"'
+
+ @patch('salt.utils.path.which', MagicMock(return_value=False))
+ @patch('salt.utils.pkg.rpm.subprocess', MagicMock(return_value=False))
+ @patch('salt.utils.pkg.rpm.platform.uname', MagicMock(
+ return_value=('Sinclair BASIC', 'motophone', '1982 Sinclair Research Ltd', '1.0', 'ZX81', 'Z80')))
+ def test_get_osarch_by_platform(self):
+ '''
+ Get os_arch if RPM package is not installed (inird image, for example).
+ :return:
+ '''
+ assert rpm.get_osarch() == 'Z80'
+
+ @patch('salt.utils.path.which', MagicMock(return_value=False))
+ @patch('salt.utils.pkg.rpm.subprocess', MagicMock(return_value=False))
+ @patch('salt.utils.pkg.rpm.platform.uname', MagicMock(
+ return_value=('Sinclair BASIC', 'motophone', '1982 Sinclair Research Ltd', '1.0', 'ZX81', '')))
+ def test_get_osarch_by_platform_no_cpu_arch(self):
+ '''
+ Get os_arch if RPM package is not installed (inird image, for example) but cpu arch cannot be determined.
+ :return:
+ '''
+ assert rpm.get_osarch() == 'ZX81'
+
+ @patch('salt.utils.path.which', MagicMock(return_value=False))
+ @patch('salt.utils.pkg.rpm.subprocess', MagicMock(return_value=False))
+ @patch('salt.utils.pkg.rpm.platform.uname', MagicMock(
+ return_value=('Sinclair BASIC', 'motophone', '1982 Sinclair Research Ltd', '1.0', '', '')))
+ def test_get_osarch_by_platform_no_cpu_arch_no_machine(self):
+ '''
+ Get os_arch if RPM package is not installed (inird image, for example)
+ where both cpu arch and machine cannot be determined.
+ :return:
+ '''
+ assert rpm.get_osarch() == 'unknown'
+try:
+ import pytest
+except ImportError:
+ pytest = None
+@skipIf(NO_MOCK, NO_MOCK_REASON)
+@skipIf(pytest is None, 'PyTest is missing')
class PkgRPMTestCase(TestCase):
'''
Test case for pkg.rpm utils
--
2.16.4

View File

@ -1,4 +1,4 @@
From a94e1316565a30e166a5a846404fd2c2bd85e2ca Mon Sep 17 00:00:00 2001
From a11587a1209cd198f421fafdb43510b6d651f4b2 Mon Sep 17 00:00:00 2001
From: EricS <54029547+ESiebigteroth@users.noreply.github.com>
Date: Tue, 3 Sep 2019 11:22:53 +0200
Subject: [PATCH] Implement network.fqdns module function (bsc#1134860)
@ -15,11 +15,11 @@ Co-authored-by: Eric Siebigteroth <eric.siebigteroth@suse.de>
salt/grains/core.py | 66 +++++-------------------------------------
salt/modules/network.py | 60 ++++++++++++++++++++++++++++++++++++++
salt/utils/network.py | 12 ++++++++
tests/unit/grains/test_core.py | 64 +++++++++++++++++++++++++++++++---------
4 files changed, 131 insertions(+), 71 deletions(-)
tests/unit/grains/test_core.py | 63 +++++++++++++++++++++++++++++++---------
4 files changed, 130 insertions(+), 71 deletions(-)
diff --git a/salt/grains/core.py b/salt/grains/core.py
index 30eba0ce99..e1d08b76cf 100644
index 0f3ccd9b92..77ae99590f 100644
--- a/salt/grains/core.py
+++ b/salt/grains/core.py
@@ -26,8 +26,9 @@ from errno import EACCES, EPERM
@ -49,7 +49,7 @@ index 30eba0ce99..e1d08b76cf 100644
# Possible value for h_errno defined in netdb.h
HOST_NOT_FOUND = 1
@@ -1538,17 +1539,6 @@ def _linux_bin_exists(binary):
@@ -1553,17 +1554,6 @@ def _linux_bin_exists(binary):
return False
@ -67,7 +67,7 @@ index 30eba0ce99..e1d08b76cf 100644
def _parse_lsb_release():
ret = {}
try:
@@ -2255,52 +2245,12 @@ def fqdns():
@@ -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).
@ -126,7 +126,7 @@ index 30eba0ce99..e1d08b76cf 100644
def ip_fqdn():
diff --git a/salt/modules/network.py b/salt/modules/network.py
index 8b4dfcead4..2f1b1c09e0 100644
index 38e2bc326e..880f4f8d5f 100644
--- a/salt/modules/network.py
+++ b/salt/modules/network.py
@@ -11,6 +11,10 @@ import logging
@ -202,11 +202,11 @@ index 8b4dfcead4..2f1b1c09e0 100644
+ return {"fqdns": sorted(list(fqdns))}
\ No newline at end of file
diff --git a/salt/utils/network.py b/salt/utils/network.py
index a3fd6e848e..3c8178eeb4 100644
index 74536cc143..4cc8a05c4a 100644
--- a/salt/utils/network.py
+++ b/salt/utils/network.py
@@ -55,6 +55,18 @@ except (ImportError, OSError, AttributeError, TypeError):
# pylint: disable=C0103
@@ -50,6 +50,18 @@ except (ImportError, OSError, AttributeError, TypeError):
pass
+_INTERFACES = {}
@ -225,18 +225,18 @@ index a3fd6e848e..3c8178eeb4 100644
'''
Sanitize host string.
diff --git a/tests/unit/grains/test_core.py b/tests/unit/grains/test_core.py
index af9d27dd0e..09e197a2e4 100644
index ac03b57226..60914204b0 100644
--- a/tests/unit/grains/test_core.py
+++ b/tests/unit/grains/test_core.py
@@ -34,6 +34,7 @@ import salt.utils.network
import salt.utils.platform
import salt.utils.path
@@ -35,6 +35,7 @@ import salt.utils.path
import salt.modules.cmdmod
import salt.modules.smbios
import salt.grains.core as core
+import salt.modules.network
# Import 3rd-party libs
from salt.ext import six
@@ -976,6 +977,40 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
@@ -1029,6 +1030,40 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
with patch.object(salt.utils.dns, 'parse_resolv', MagicMock(return_value=resolv_mock)):
assert core.dns() == ret
@ -275,9 +275,9 @@ index af9d27dd0e..09e197a2e4 100644
+
+
@skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
@patch.object(salt.utils, 'is_windows', MagicMock(return_value=False))
@patch('salt.utils.network.ip_addrs', MagicMock(return_value=['1.2.3.4', '5.6.7.8']))
@@ -992,11 +1027,12 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
@patch('salt.utils.network.ip_addrs6',
@@ -1044,11 +1079,12 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
('foo.bar.baz', [], ['fe80::a8b2:93ff:fe00:0']),
('bluesniff.foo.bar', [], ['fe80::a8b2:93ff:dead:beef'])]
ret = {'fqdns': ['bluesniff.foo.bar', 'foo.bar.baz', 'rinzler.evil-corp.com']}
@ -294,8 +294,8 @@ index af9d27dd0e..09e197a2e4 100644
+ assert set(fqdns['fqdns']) == set(ret['fqdns'])
@skipIf(not salt.utils.platform.is_linux(), 'System is not Linux')
@patch.object(salt.utils.platform, 'is_windows', MagicMock(return_value=False))
@@ -1012,14 +1048,16 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
@patch('salt.utils.network.ip_addrs', MagicMock(return_value=['1.2.3.4']))
@@ -1094,14 +1130,15 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
('rinzler.evil-corp.com', ["false-hostname", "badaliass"], ['5.6.7.8']),
('foo.bar.baz', [], ['fe80::a8b2:93ff:fe00:0']),
('bluesniff.foo.bar', ["alias.bluesniff.foo.bar"], ['fe80::a8b2:93ff:dead:beef'])]
@ -316,10 +316,9 @@ index af9d27dd0e..09e197a2e4 100644
+
+ for alias in ["throwmeaway", "false-hostname", "badaliass"]:
+ assert alias not in fqdns["fqdns"]
+
def test_core_virtual(self):
'''
test virtual grain with cmd virt-what
--
2.16.4

View File

@ -1,4 +1,4 @@
From c54cdb24f09abf990fc23aa35a763c1ec3bd122a Mon Sep 17 00:00:00 2001
From 65e33acaf10fdd838c0cdf34ec93df3a2ed1f0d2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Thu, 26 Sep 2019 10:41:06 +0100

View File

@ -1,4 +1,4 @@
From 83fa749ca09eb8eb5eb29aaa30f8565106ee3c65 Mon Sep 17 00:00:00 2001
From 512b189808ea0d7b333587689d7e7eb52d16b189 Mon Sep 17 00:00:00 2001
From: Bo Maryniuk <bo@suse.de>
Date: Tue, 29 Jan 2019 11:11:38 +0100
Subject: [PATCH] Include aliases in the fqdns grains
@ -18,14 +18,14 @@ Leverage cached interfaces, if any.
salt/grains/core.py | 14 ++++++--------
salt/utils/network.py | 12 ++++++++++++
tests/unit/grains/test_core.py | 28 +++++++++++++++++++++++++---
tests/unit/utils/test_network.py | 19 +++++++++++++++++++
4 files changed, 62 insertions(+), 11 deletions(-)
tests/unit/utils/test_network.py | 24 ++++++++++++++++++++++++
4 files changed, 67 insertions(+), 11 deletions(-)
diff --git a/salt/grains/core.py b/salt/grains/core.py
index f59eeb5780..7d75d48bb5 100644
index 7b7e328520..309e4c9c4a 100644
--- a/salt/grains/core.py
+++ b/salt/grains/core.py
@@ -2255,14 +2255,13 @@ def fqdns():
@@ -2275,14 +2275,13 @@ def fqdns():
grains = {}
fqdns = set()
@ -43,9 +43,9 @@ index f59eeb5780..7d75d48bb5 100644
+ name, aliaslist, addresslist = socket.gethostbyaddr(ip)
+ fqdns.update([socket.getfqdn(name)] + [als for als in aliaslist if salt.utils.network.is_fqdn(als)])
except socket.herror as err:
if err.errno == 0:
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.
@@ -2272,8 +2271,7 @@ def fqdns():
@@ -2292,8 +2291,7 @@ def fqdns():
except (socket.error, socket.gaierror, socket.timeout) as err:
log.error(err_message, ip, err)
@ -56,10 +56,10 @@ index f59eeb5780..7d75d48bb5 100644
def ip_fqdn():
diff --git a/salt/utils/network.py b/salt/utils/network.py
index d6fc6a98c6..a183c9776a 100644
index 906d1cb3bc..2ae2e213b7 100644
--- a/salt/utils/network.py
+++ b/salt/utils/network.py
@@ -2007,3 +2007,15 @@ def parse_host_port(host_port):
@@ -1958,3 +1958,15 @@ def parse_host_port(host_port):
raise ValueError('bad hostname: "{}"'.format(host))
return host, port
@ -76,10 +76,10 @@ index d6fc6a98c6..a183c9776a 100644
+ 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("."))
diff --git a/tests/unit/grains/test_core.py b/tests/unit/grains/test_core.py
index c85225e959..e43be4939c 100644
index c40595eb3f..ac03b57226 100644
--- a/tests/unit/grains/test_core.py
+++ b/tests/unit/grains/test_core.py
@@ -994,10 +994,32 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
@@ -1046,9 +1046,9 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
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()
@ -90,7 +90,12 @@ index c85225e959..e43be4939c 100644
+ assert len(fqdns['fqdns']) == len(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']))
@@ -1081,6 +1081,28 @@ class CoreGrainsTestCase(TestCase, LoaderModuleMockMixin):
mock_log.debug.assert_not_called()
mock_log.error.assert_called_once()
+ @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('salt.utils.network.ip_addrs6',
@ -112,17 +117,23 @@ index c85225e959..e43be4939c 100644
+
+ for alias in ["throwmeaway", "false-hostname", "badaliass"]:
+ assert alias not in fqdns["fqdns"]
+
def test_core_virtual(self):
'''
test virtual grain with cmd virt-what
diff --git a/tests/unit/utils/test_network.py b/tests/unit/utils/test_network.py
index af5cbbab2b..f4c849d124 100644
index 7dcca0166e..74479b0cae 100644
--- a/tests/unit/utils/test_network.py
+++ b/tests/unit/utils/test_network.py
@@ -680,3 +680,22 @@ class NetworkTestCase(TestCase):
with patch('subprocess.check_output', return_value=NETLINK_SS):
remotes = network._netlink_tool_remote_on('4505', 'remote')
self.assertEqual(remotes, set(['127.0.0.1', '::ffff:1.2.3.4']))
@@ -701,3 +701,27 @@ 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
+
+ def test_netlink_tool_remote_on(self):
+ with patch('subprocess.check_output', return_value=NETLINK_SS):
+ remotes = network._netlink_tool_remote_on('4505', 'remote')
+ self.assertEqual(remotes, set(['127.0.0.1', '::ffff:1.2.3.4']))
+
+ def test_is_fqdn(self):
+ """

View File

@ -1,4 +1,4 @@
From 13855ebda730a0a369c9b98d397d62b9d9a67145 Mon Sep 17 00:00:00 2001
From c750e854c637e405a788f91d5b9a7bd1a0a6edfd Mon Sep 17 00:00:00 2001
From: ed lane <ed.lane.0@gmail.com>
Date: Thu, 30 Aug 2018 06:07:08 -0600
Subject: [PATCH] Integration of MSI authentication with azurearm cloud
@ -9,7 +9,7 @@ Subject: [PATCH] Integration of MSI authentication with azurearm cloud
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/salt/cloud/clouds/azurearm.py b/salt/cloud/clouds/azurearm.py
index a422feca4f..9948dedc6c 100644
index 047fdac0a9..2c1fa04ae8 100644
--- a/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

View File

@ -1,4 +1,4 @@
From 43cdd24d035ff21c946f6de0a973f5db0e50c8a5 Mon Sep 17 00:00:00 2001
From 2b5903d2429607a3f46d648520e24c357a56aea6 Mon Sep 17 00:00:00 2001
From: Can Bulut Bayburt <1103552+cbbayburt@users.noreply.github.com>
Date: Wed, 4 Dec 2019 15:59:46 +0100
Subject: [PATCH] Let salt-ssh use 'platform-python' binary in RHEL8
@ -14,7 +14,7 @@ creating the sh shim.
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/salt/client/ssh/__init__.py b/salt/client/ssh/__init__.py
index 0df918d634..d5bc6e5c27 100644
index 1373274739..d9e91b0f50 100644
--- a/salt/client/ssh/__init__.py
+++ b/salt/client/ssh/__init__.py
@@ -147,7 +147,7 @@ elif [ "$SUDO" ] && [ -n "$SUDO_USER" ]
@ -27,6 +27,6 @@ index 0df918d634..d5bc6e5c27 100644
do
if command -v "$py_cmd" >/dev/null 2>&1 && "$py_cmd" -c "import sys; sys.exit(not (sys.version_info >= (2, 6)));"
--
2.23.0
2.16.4

View File

@ -1,162 +0,0 @@
From a1e0904a640d01d4bab0871db1ab8ea653335443 Mon Sep 17 00:00:00 2001
From: Jochen Breuer <jbreuer@suse.de>
Date: Thu, 9 Jan 2020 10:11:13 +0100
Subject: [PATCH] list_downloaded for apt Module
---
salt/modules/aptpkg.py | 41 +++++++++++++++++++++++++++++++++++++++
salt/states/pkg.py | 4 ++--
tests/unit/modules/test_aptpkg.py | 29 +++++++++++++++++++++++++++
3 files changed, 72 insertions(+), 2 deletions(-)
diff --git a/salt/modules/aptpkg.py b/salt/modules/aptpkg.py
index 1a60255a1d..023049b2af 100644
--- a/salt/modules/aptpkg.py
+++ b/salt/modules/aptpkg.py
@@ -18,6 +18,9 @@ import os
import re
import logging
import time
+import fnmatch
+import datetime
+
# Import third party libs
# pylint: disable=no-name-in-module,import-error,redefined-builtin
@@ -422,6 +425,7 @@ def install(name=None,
pkgs=None,
sources=None,
reinstall=False,
+ downloadonly=False,
ignore_epoch=False,
**kwargs):
'''
@@ -768,6 +772,9 @@ def install(name=None,
cmd.extend(downgrade)
cmds.append(cmd)
+ if downloadonly:
+ cmd.append("--download-only")
+
if to_reinstall:
all_pkgs.extend(to_reinstall)
cmd = copy.deepcopy(cmd_prefix)
@@ -2917,3 +2924,37 @@ def _get_http_proxy_url():
)
return http_proxy_url
+
+
+def list_downloaded(root=None, **kwargs):
+ '''
+ .. versionadded:: 3000?
+
+ List prefetched packages downloaded by apt in the local disk.
+
+ root
+ operate on a different root directory.
+
+ CLI example:
+
+ .. code-block:: bash
+
+ salt '*' pkg.list_downloaded
+ '''
+ CACHE_DIR = '/var/cache/apt'
+ if root:
+ CACHE_DIR = os.path.join(root, os.path.relpath(CACHE_DIR, os.path.sep))
+
+ ret = {}
+ for root, dirnames, filenames in salt.utils.path.os_walk(CACHE_DIR):
+ for filename in fnmatch.filter(filenames, '*.deb'):
+ package_path = os.path.join(root, filename)
+ pkg_info = __salt__['lowpkg.bin_pkg_info'](package_path)
+ pkg_timestamp = int(os.path.getctime(package_path))
+ ret.setdefault(pkg_info['name'], {})[pkg_info['version']] = {
+ 'path': package_path,
+ 'size': os.path.getsize(package_path),
+ 'creation_date_time_t': pkg_timestamp,
+ 'creation_date_time': datetime.datetime.utcfromtimestamp(pkg_timestamp).isoformat(),
+ }
+ return ret
diff --git a/salt/states/pkg.py b/salt/states/pkg.py
index 22a97fe98c..be00498135 100644
--- a/salt/states/pkg.py
+++ b/salt/states/pkg.py
@@ -1975,7 +1975,7 @@ def downloaded(name,
(if specified).
Currently supported for the following pkg providers:
- :mod:`yumpkg <salt.modules.yumpkg>` and :mod:`zypper <salt.modules.zypper>`
+ :mod:`yumpkg <salt.modules.yumpkg>`, :mod:`zypper <salt.modules.zypper>` and :mod:`zypper <salt.modules.aptpkg>`
:param str name:
The name of the package to be downloaded. This parameter is ignored if
@@ -2114,7 +2114,7 @@ def downloaded(name,
if not ret['changes'] and not ret['comment']:
ret['result'] = True
- ret['comment'] = 'Packages are already downloaded: ' \
+ ret['comment'] = 'Packages downloaded: ' \
'{0}'.format(', '.join(targets))
return ret
diff --git a/tests/unit/modules/test_aptpkg.py b/tests/unit/modules/test_aptpkg.py
index bc6b610d86..5c7e38eae7 100644
--- a/tests/unit/modules/test_aptpkg.py
+++ b/tests/unit/modules/test_aptpkg.py
@@ -413,14 +413,17 @@ class AptPkgTestCase(TestCase, LoaderModuleMockMixin):
with patch.multiple(aptpkg, **patch_kwargs):
aptpkg.upgrade()
args_matching = [True for args in patch_kwargs['__salt__']['cmd.run_all'].call_args[0] if "--download-only" in args]
+ # Here we shouldn't see the parameter and args_matching should be empty.
self.assertFalse(any(args_matching))
aptpkg.upgrade(downloadonly=True)
args_matching = [True for args in patch_kwargs['__salt__']['cmd.run_all'].call_args[0] if "--download-only" in args]
+ # --download-only should be in the args list and we should have at least on True in the list.
self.assertTrue(any(args_matching))
aptpkg.upgrade(download_only=True)
args_matching = [True for args in patch_kwargs['__salt__']['cmd.run_all'].call_args[0] if "--download-only" in args]
+ # --download-only should be in the args list and we should have at least on True in the list.
self.assertTrue(any(args_matching))
def test_show(self):
@@ -545,6 +548,32 @@ class AptPkgTestCase(TestCase, LoaderModuleMockMixin):
self.assert_called_once(refresh_mock)
refresh_mock.reset_mock()
+ @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/apt/archive/test_package.rpm']))
+ def test_list_downloaded(self):
+ '''
+ Test downloaded packages listing.
+ :return:
+ '''
+ DOWNLOADED_RET = {
+ 'test-package': {
+ '1.0': {
+ 'path': '/var/cache/apt/archive/test_package.rpm',
+ 'size': 123456,
+ 'creation_date_time_t': 1234567890,
+ 'creation_date_time': '2009-02-13T23:31:30',
+ }
+ }
+ }
+
+ with patch.dict(aptpkg.__salt__, {'lowpkg.bin_pkg_info': MagicMock(return_value={'name': 'test-package',
+ 'version': '1.0'})}):
+ list_downloaded = aptpkg.list_downloaded()
+ self.assertEqual(len(list_downloaded), 1)
+ self.assertDictEqual(list_downloaded, DOWNLOADED_RET)
+
@skipIf(pytest is None, 'PyTest is missing')
class AptUtilsTestCase(TestCase, LoaderModuleMockMixin):
--
2.16.4

View File

@ -1,4 +1,4 @@
From 3d92c4e096dca27b95e485b70594186151e40092 Mon Sep 17 00:00:00 2001
From 444e00c6601b878444923f573fdb5f000342be9a Mon Sep 17 00:00:00 2001
From: Alberto Planas <aplanas@suse.com>
Date: Thu, 12 Mar 2020 16:39:42 +0100
Subject: [PATCH] loader: invalidate the import cachefor extra modules
@ -14,10 +14,10 @@ extra_module_dirs
1 file changed, 12 insertions(+)
diff --git a/salt/loader.py b/salt/loader.py
index 52cb4cfcb5..26b44de511 100644
index 742b2f8e22..5bd4773645 100644
--- a/salt/loader.py
+++ b/salt/loader.py
@@ -1506,9 +1506,11 @@ class LazyLoader(salt.utils.lazy.LazyDict):
@@ -1544,9 +1544,11 @@ class LazyLoader(salt.utils.lazy.LazyDict):
self._clean_module_dirs.append(directory)
def __clean_sys_path(self):
@ -29,7 +29,7 @@ index 52cb4cfcb5..26b44de511 100644
self._clean_module_dirs = []
# Be sure that sys.path_importer_cache do not contains any
@@ -1516,6 +1518,16 @@ class LazyLoader(salt.utils.lazy.LazyDict):
@@ -1554,6 +1556,16 @@ class LazyLoader(salt.utils.lazy.LazyDict):
if USE_IMPORTLIB:
importlib.invalidate_caches()

View File

@ -0,0 +1,32 @@
From 2670f83fd1309fbf9fdc98f15f9a6e6a3ecc038d Mon Sep 17 00:00:00 2001
From: Alberto Planas <aplanas@suse.com>
Date: Tue, 24 Mar 2020 17:46:23 +0100
Subject: [PATCH] loop: fix variable names for until_no_eval
---
salt/states/loop.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/salt/states/loop.py b/salt/states/loop.py
index 726c8c80165803f3b2d98bf7a197013c53f3ebc8..b631e6c8f62416c04b458a595dc31393987eb904 100644
--- a/salt/states/loop.py
+++ b/salt/states/loop.py
@@ -185,10 +185,10 @@ def until_no_eval(
''.format(name, expected))
if ret['comment']:
return ret
- if not m_args:
- m_args = []
- if not m_kwargs:
- m_kwargs = {}
+ if not args:
+ args = []
+ if not kwargs:
+ kwargs = {}
if init_wait:
time.sleep(init_wait)
--
2.23.0

View File

@ -1,4 +1,4 @@
From 0cd0d8d50c500f3d8948470c2ecd5344f9c494a5 Mon Sep 17 00:00:00 2001
From c9538180f4dd8875ab57dfa3f51ff59608d2481b Mon Sep 17 00:00:00 2001
From: Joachim Gleissner <jgleissner@suse.com>
Date: Tue, 18 Sep 2018 15:07:13 +0200
Subject: [PATCH] loosen azure sdk dependencies in azurearm cloud driver
@ -12,7 +12,7 @@ remove unused import from azurearm driver
1 file changed, 6 insertions(+)
diff --git a/salt/cloud/clouds/azurearm.py b/salt/cloud/clouds/azurearm.py
index 9948dedc6c..5f0d4b7e6f 100644
index 2c1fa04ae8..d5757c6d28 100644
--- a/salt/cloud/clouds/azurearm.py
+++ b/salt/cloud/clouds/azurearm.py
@@ -104,6 +104,7 @@ import time

View File

@ -1,4 +1,4 @@
From 9e543a835c870eaea424735fb8e52a82480dce90 Mon Sep 17 00:00:00 2001
From 93f69a227b7f8c3d4625c0699ab3923d4a0b3127 Mon Sep 17 00:00:00 2001
From: Bo Maryniuk <bo@suse.de>
Date: Fri, 16 Nov 2018 10:54:12 +0100
Subject: [PATCH] Make aptpkg.list_repos compatible on enabled/disabled
@ -9,10 +9,10 @@ Subject: [PATCH] Make aptpkg.list_repos compatible on enabled/disabled
1 file changed, 1 insertion(+)
diff --git a/salt/modules/aptpkg.py b/salt/modules/aptpkg.py
index ead7c6391e..6b3a921a82 100644
index b5503f0b10..8f4d95a195 100644
--- a/salt/modules/aptpkg.py
+++ b/salt/modules/aptpkg.py
@@ -1595,6 +1595,7 @@ def list_repos():
@@ -1641,6 +1641,7 @@ def list_repos():
repo['file'] = source.file
repo['comps'] = getattr(source, 'comps', [])
repo['disabled'] = source.disabled

View File

@ -1,4 +1,4 @@
From 117d2af99095cce3c0ab7222d7333334b73aa971 Mon Sep 17 00:00:00 2001
From 2aeefa07ff52048e2db5c8c4ebb1cde6efe87cee Mon Sep 17 00:00:00 2001
From: Bo Maryniuk <bo@suse.de>
Date: Mon, 8 Oct 2018 17:52:07 +0200
Subject: [PATCH] Make profiles a package.

View File

@ -0,0 +1,35 @@
From 023d1256106319d042233021c0f200bcdc0cd1f0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Fri, 13 Mar 2020 13:01:57 +0000
Subject: [PATCH] Make salt.ext.tornado.gen to use salt.ext.backports_abc
on Python 2
---
salt/ext/tornado/gen.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/salt/ext/tornado/gen.py b/salt/ext/tornado/gen.py
index 6cb19730bf1ef3893a4626e9e144eac1c6fa9683..72f422ce28fa43132782a7a0d61b31acd32d138b 100644
--- a/salt/ext/tornado/gen.py
+++ b/salt/ext/tornado/gen.py
@@ -115,13 +115,13 @@ try:
# py35+
from collections.abc import Generator as GeneratorType # type: ignore
except ImportError:
- from backports_abc import Generator as GeneratorType # type: ignore
+ from salt.ext.backports_abc import Generator as GeneratorType # type: ignore
try:
# py35+
from inspect import isawaitable # type: ignore
except ImportError:
- from backports_abc import isawaitable
+ from salt.ext.backports_abc import isawaitable
except ImportError:
if 'APPENGINE_RUNTIME' not in os.environ:
raise
--
2.23.0

View File

@ -0,0 +1,34 @@
From 39b88fd0a3f882e0b33973665bbbacdd60c26a9b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Wed, 25 Mar 2020 13:09:52 +0000
Subject: [PATCH] Make setup.py script to not require setuptools > 9.1
---
setup.py | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/setup.py b/setup.py
index 06374647df5e82a21fc39b08d41c596f0483ff0c..67a915c64ce5d774e8f89ff3502e85b6bc04b82f 100755
--- a/setup.py
+++ b/setup.py
@@ -700,15 +700,6 @@ class Install(install):
install.finalize_options(self)
def run(self):
- from distutils.version import StrictVersion
- if StrictVersion(setuptools.__version__) < StrictVersion('9.1'):
- sys.stderr.write(
- '\n\nInstalling Salt requires setuptools >= 9.1\n'
- 'Available setuptools version is {}\n\n'.format(setuptools.__version__)
- )
- sys.stderr.flush()
- sys.exit(1)
-
# Let's set the running_salt_install attribute so we can add
# _version.py in the build command
self.distribution.running_salt_install = True
--
2.23.0

View File

@ -1,4 +1,4 @@
From 10df6dcff22785962dc372064c899b942f3c1ff9 Mon Sep 17 00:00:00 2001
From c375d1e25e8b5c77b6a8f89855f17df6e49db9f2 Mon Sep 17 00:00:00 2001
From: Mihai Dinca <mdinca@suse.de>
Date: Fri, 14 Jun 2019 15:13:12 +0200
Subject: [PATCH] Move server_id deprecation warning to reduce log
@ -10,10 +10,10 @@ Subject: [PATCH] Move server_id deprecation warning to reduce log
2 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/salt/grains/core.py b/salt/grains/core.py
index ab37a4dd44..30eba0ce99 100644
index b58c29dbc3..0f3ccd9b92 100644
--- a/salt/grains/core.py
+++ b/salt/grains/core.py
@@ -2867,10 +2867,6 @@ def get_server_id():
@@ -2890,10 +2890,6 @@ def get_server_id():
if bool(use_crc):
id_hash = getattr(zlib, use_crc, zlib.adler32)(__opts__.get('id', '').encode()) & 0xffffffff
else:
@ -25,18 +25,18 @@ index ab37a4dd44..30eba0ce99 100644
server_id = {'server_id': id_hash}
diff --git a/salt/minion.py b/salt/minion.py
index c5f637eaa6..2c0a18604e 100644
index 457f485b0a..4730f68b87 100644
--- a/salt/minion.py
+++ b/salt/minion.py
@@ -102,6 +102,7 @@ from salt.utils.odict import OrderedDict
@@ -97,6 +97,7 @@ from salt.utils.odict import OrderedDict
from salt.utils.process import (default_signals,
SignalHandlingMultiprocessingProcess,
SignalHandlingProcess,
ProcessManager)
+from salt.utils.versions import warn_until
from salt.exceptions import (
CommandExecutionError,
CommandNotFoundError,
@@ -993,6 +994,14 @@ class MinionManager(MinionBase):
@@ -1002,6 +1003,14 @@ class MinionManager(MinionBase):
if (self.opts['master_type'] in ('failover', 'distributed')) or not isinstance(self.opts['master'], list):
masters = [masters]

View File

@ -1,7 +1,7 @@
From 66e635ecf9643053c0fdb54718f63782ed998f2f Mon Sep 17 00:00:00 2001
From e5d42c6313ba051f22f83cbde3da9410fd7fc3b9 Mon Sep 17 00:00:00 2001
From: Cedric Bosdonnat <cbosdonnat@suse.com>
Date: Fri, 13 Mar 2020 16:38:46 +0100
Subject: [PATCH] Open suse 2019.2.3 virt defined states (#219)
Date: Fri, 13 Mar 2020 16:38:08 +0100
Subject: [PATCH] openSUSE-3000 virt-defined-states (#222)
* Create virt.pool_defined state out of virt.pool_running
@ -45,13 +45,13 @@ parameters. This was not handled in _gen_xml(). Also add some more tests
cases matching this for virt.update.
---
salt/modules/virt.py | 16 +-
salt/states/virt.py | 675 +++++++++++++++-----
salt/states/virt.py | 673 +++++++++++++++-----
tests/unit/modules/test_virt.py | 26 +
tests/unit/states/test_virt.py | 1346 ++++++++++++++++++++++++++++++++-------
4 files changed, 1666 insertions(+), 397 deletions(-)
4 files changed, 1665 insertions(+), 396 deletions(-)
diff --git a/salt/modules/virt.py b/salt/modules/virt.py
index 339760ead4..b44d1a65bf 100644
index 3889238ecd..f0820e8825 100644
--- a/salt/modules/virt.py
+++ b/salt/modules/virt.py
@@ -1783,6 +1783,7 @@ def update(name,
@ -64,7 +64,7 @@ index 339760ead4..b44d1a65bf 100644
Update the definition of an existing domain.
@@ -1835,6 +1836,10 @@ def update(name,
.. versionadded:: neon
.. versionadded:: 3000
+ :param test: run in dry-run mode if set to True
+
@ -109,7 +109,7 @@ index 339760ead4..b44d1a65bf 100644
if device_type in ['cpu', 'mem']:
status[device_type] = not bool(ret)
diff --git a/salt/states/virt.py b/salt/states/virt.py
index d1c9191a29..8932496b76 100644
index 55a9ad2616..819776d707 100644
--- a/salt/states/virt.py
+++ b/salt/states/virt.py
@@ -14,6 +14,7 @@ for the generation and signing of certificates for systems running libvirt:
@ -320,7 +320,7 @@ index d1c9191a29..8932496b76 100644
:param connection: libvirt connection URI, overriding defaults
.. versionadded:: 2019.2.0
@@ -407,93 +590,74 @@ def running(name,
@@ -424,93 +607,74 @@ def running(name,
address: 192.168.0.125
'''
@ -385,7 +385,7 @@ index d1c9191a29..8932496b76 100644
+ changed = ret['changes'][name].get('definition', False)
try:
domain_state = __salt__['virt.vm_state'](name)
- if domain_state.get(name, None) != 'running':
if domain_state.get(name) != 'running':
- action_msg = 'started'
- if update:
- status = __salt__['virt.update'](name,
@ -462,7 +462,6 @@ index d1c9191a29..8932496b76 100644
- # Something bad happened when starting / updating the VM, report it
- ret['comment'] = six.text_type(err)
- ret['result'] = False
+ if domain_state.get(name) != 'running':
+ if not __opts__['test']:
+ __salt__['virt.start'](name, connection=connection, username=username, password=password)
+ comment = 'Domain {} started'.format(name)
@ -480,7 +479,7 @@ index d1c9191a29..8932496b76 100644
return ret
@@ -653,6 +817,106 @@ def reverted(name, snapshot=None, cleanup=False): # pylint: disable=redefined-o
@@ -670,6 +834,106 @@ def reverted(name, snapshot=None, cleanup=False): # pylint: disable=redefined-o
return ret
@ -587,7 +586,7 @@ index d1c9191a29..8932496b76 100644
def network_running(name,
bridge,
forward,
@@ -698,13 +962,13 @@ def network_running(name,
@@ -715,13 +979,13 @@ def network_running(name,
.. code-block:: yaml
@ -604,7 +603,7 @@ index d1c9191a29..8932496b76 100644
- bridge: main
- forward: bridge
- vport: openvswitch
@@ -714,7 +978,7 @@ def network_running(name,
@@ -731,7 +995,7 @@ def network_running(name,
.. code-block:: yaml
network_name:
@ -613,7 +612,7 @@ index d1c9191a29..8932496b76 100644
- bridge: natted
- forward: nat
- ipv4_config:
@@ -727,44 +991,46 @@ def network_running(name,
@@ -744,44 +1008,46 @@ def network_running(name,
- autostart: True
'''
@ -693,7 +692,7 @@ index d1c9191a29..8932496b76 100644
ptype=None,
target=None,
permissions=None,
@@ -775,9 +1041,9 @@ def pool_running(name,
@@ -792,9 +1058,9 @@ def pool_running(name,
username=None,
password=None):
'''
@ -705,7 +704,7 @@ index d1c9191a29..8932496b76 100644
:param ptype: libvirt pool type
:param target: full path to the target device or folder. (Default: ``None``)
@@ -799,12 +1065,7 @@ def pool_running(name,
@@ -816,12 +1082,7 @@ def pool_running(name,
.. code-block:: yaml
pool_name:
@ -719,7 +718,7 @@ index d1c9191a29..8932496b76 100644
- ptype: netfs
- target: /mnt/cifs
- permissions:
@@ -867,29 +1128,19 @@ def pool_running(name,
@@ -884,29 +1145,19 @@ def pool_running(name,
username=username,
password=password)
@ -758,7 +757,7 @@ index d1c9191a29..8932496b76 100644
else:
needs_autostart = autostart
if not __opts__['test']:
@@ -915,17 +1166,12 @@ def pool_running(name,
@@ -932,17 +1183,12 @@ def pool_running(name,
connection=connection,
username=username,
password=password)
@ -780,7 +779,7 @@ index d1c9191a29..8932496b76 100644
if needs_autostart:
if not __opts__['test']:
@@ -941,6 +1187,117 @@ def pool_running(name,
@@ -958,6 +1204,117 @@ def pool_running(name,
return ret
@ -899,7 +898,7 @@ index d1c9191a29..8932496b76 100644
purge=False,
connection=None,
diff --git a/tests/unit/modules/test_virt.py b/tests/unit/modules/test_virt.py
index 3079657a9b..2d3417ce91 100644
index d762dcc479..8690154662 100644
--- a/tests/unit/modules/test_virt.py
+++ b/tests/unit/modules/test_virt.py
@@ -1272,6 +1272,32 @@ class VirtTestCase(TestCase, LoaderModuleMockMixin):
@ -936,10 +935,10 @@ index 3079657a9b..2d3417ce91 100644
setvcpus_mock = MagicMock(return_value=0)
domain_mock.setVcpusFlags = setvcpus_mock
diff --git a/tests/unit/states/test_virt.py b/tests/unit/states/test_virt.py
index 334c33b7d0..38a732b50c 100644
index c50c04b8ab..6727704494 100644
--- a/tests/unit/states/test_virt.py
+++ b/tests/unit/states/test_virt.py
@@ -220,6 +220,243 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
@@ -217,6 +217,243 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
organization='SaltStack',
expiration_days=700), ret)
@ -1183,7 +1182,7 @@ index 334c33b7d0..38a732b50c 100644
def test_running(self):
'''
running state test cases.
@@ -228,163 +465,369 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
@@ -225,163 +462,369 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
'changes': {},
'result': True,
'comment': 'myvm is running'}
@ -1701,7 +1700,7 @@ index 334c33b7d0..38a732b50c 100644
def test_stopped(self):
'''
@@ -602,92 +1045,506 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
@@ -599,92 +1042,506 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
ret.update({'changes': {}, 'result': False, 'comment': 'No changes had happened'})
self.assertDictEqual(virt.rebooted('myvm'), ret)
@ -2284,7 +2283,7 @@ index 334c33b7d0..38a732b50c 100644
def test_pool_running(self):
'''
@@ -697,14 +1554,14 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
@@ -694,14 +1551,14 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
mocks = {mock: MagicMock(return_value=True) for mock in ['define', 'autostart', 'build', 'start', 'stop']}
with patch.dict(virt.__opts__, {'test': False}):
with patch.dict(virt.__salt__, { # pylint: disable=no-member
@ -2302,7 +2301,7 @@ index 334c33b7d0..38a732b50c 100644
self.assertDictEqual(virt.pool_running('mypool',
ptype='logical',
target='/dev/base',
@@ -757,7 +1614,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
@@ -754,7 +1611,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
'virt.pool_info': MagicMock(return_value={'mypool': {'state': 'running', 'autostart': True}}),
'virt.pool_update': MagicMock(return_value=False),
}):
@ -2311,7 +2310,7 @@ index 334c33b7d0..38a732b50c 100644
self.assertDictEqual(virt.pool_running('mypool',
ptype='logical',
target='/dev/base',
@@ -800,8 +1657,8 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
@@ -797,8 +1654,8 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
'virt.pool_build': mocks['build'],
'virt.pool_start': mocks['start']
}):
@ -2322,7 +2321,7 @@ index 334c33b7d0..38a732b50c 100644
'result': True})
self.assertDictEqual(virt.pool_running('mypool',
ptype='logical',
@@ -845,8 +1702,8 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
@@ -842,8 +1699,8 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
'virt.pool_start': mocks['start'],
'virt.pool_stop': mocks['stop']
}):
@ -2333,7 +2332,7 @@ index 334c33b7d0..38a732b50c 100644
'result': True})
self.assertDictEqual(virt.pool_running('mypool',
ptype='logical',
@@ -885,7 +1742,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
@@ -882,7 +1739,7 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
'virt.pool_info': MagicMock(return_value={'mypool': {'state': 'running', 'autostart': True}}),
'virt.pool_update': MagicMock(return_value=False),
}):
@ -2342,7 +2341,7 @@ index 334c33b7d0..38a732b50c 100644
'result': True})
self.assertDictEqual(virt.pool_running('mypool',
ptype='logical',
@@ -908,6 +1765,29 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
@@ -905,6 +1762,29 @@ class LibvirtTestCase(TestCase, LoaderModuleMockMixin):
target='/dev/base',
source={'devices': [{'path': '/dev/sda'}]}), ret)

View File

@ -1,34 +0,0 @@
From a83a3a01e3bb16ec7bf4463dea1b4770c4b2955c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Mon, 3 Jun 2019 11:38:36 +0100
Subject: [PATCH] Preserve already defined DESTRUCTIVE_TESTS and
EXPENSIVE_TESTS env variables
---
tests/support/parser/__init__.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/support/parser/__init__.py b/tests/support/parser/__init__.py
index a188f8945f..2802b20c62 100644
--- a/tests/support/parser/__init__.py
+++ b/tests/support/parser/__init__.py
@@ -598,12 +598,12 @@ class SaltTestingParser(optparse.OptionParser):
self.validate_options()
- if self.support_destructive_tests_selection:
+ if self.support_destructive_tests_selection and not os.environ.get('DESTRUCTIVE_TESTS', None):
# Set the required environment variable in order to know if
# destructive tests should be executed or not.
os.environ['DESTRUCTIVE_TESTS'] = str(self.options.run_destructive)
- if self.support_expensive_tests_selection:
+ if self.support_expensive_tests_selection and not os.environ.get('EXPENSIVE_TESTS', None):
# Set the required environment variable in order to know if
# expensive tests should be executed or not.
os.environ['EXPENSIVE_TESTS'] = str(self.options.run_expensive)
--
2.16.4

View File

@ -1,89 +0,0 @@
From ae46bb899f3c7d70af62081b2ae0473f07a2a7b9 Mon Sep 17 00:00:00 2001
From: Bo Maryniuk <bo@suse.de>
Date: Mon, 15 Oct 2018 17:26:16 +0200
Subject: [PATCH] Preserving signature in "module.run" state (U#50049)
Add unit test for _call_function on signature aligning named arguments
Add unit test for _call_function routine for unnamed positional arguments
Remove redundant docstrings
Add different test function signature with the same outcome
Replace standalone function with lambda-proxy for signatures only
---
salt/states/module.py | 7 +++++--
tests/unit/states/test_module.py | 27 +++++++++++++++++++++++++++
2 files changed, 32 insertions(+), 2 deletions(-)
diff --git a/salt/states/module.py b/salt/states/module.py
index 9968529ffd..a6096ba35b 100644
--- a/salt/states/module.py
+++ b/salt/states/module.py
@@ -324,7 +324,7 @@ def _call_function(name, returner=None, **kwargs):
# func_args is initialized to a list of positional arguments that the function to be run accepts
func_args = argspec.args[:len(argspec.args or []) - len(argspec.defaults or [])]
- arg_type, na_type, kw_type = [], {}, False
+ arg_type, kw_to_arg_type, na_type, kw_type = [], {}, {}, False
for funcset in reversed(kwargs.get('func_args') or []):
if not isinstance(funcset, dict):
# We are just receiving a list of args to the function to be run, so just append
@@ -335,13 +335,16 @@ def _call_function(name, returner=None, **kwargs):
# We are going to pass in a keyword argument. The trick here is to make certain
# that if we find that in the *args* list that we pass it there and not as a kwarg
if kwarg_key in func_args:
- arg_type.append(funcset[kwarg_key])
+ kw_to_arg_type[kwarg_key] = funcset[kwarg_key]
continue
else:
# Otherwise, we're good and just go ahead and pass the keyword/value pair into
# the kwargs list to be run.
func_kw.update(funcset)
arg_type.reverse()
+ for arg in func_args:
+ if arg in kw_to_arg_type:
+ arg_type.append(kw_to_arg_type[arg])
_exp_prm = len(argspec.args or []) - len(argspec.defaults or [])
_passed_prm = len(arg_type)
missing = []
diff --git a/tests/unit/states/test_module.py b/tests/unit/states/test_module.py
index b505e85b90..2aff53eeaf 100644
--- a/tests/unit/states/test_module.py
+++ b/tests/unit/states/test_module.py
@@ -324,3 +324,30 @@ class ModuleStateTest(TestCase, LoaderModuleMockMixin):
self.assertIn(comment, ret['comment'])
self.assertIn('world', ret['comment'])
self.assertIn('hello', ret['comment'])
+
+ def test_call_function_named_args(self):
+ '''
+ Test _call_function routine when params are named. Their position ordering should not matter.
+
+ :return:
+ '''
+ with patch.dict(module.__salt__,
+ {'testfunc': lambda a, b, c, *args, **kwargs: (a, b, c, args, kwargs)}, clear=True):
+ assert module._call_function('testfunc', func_args=[{'a': 1}, {'b': 2}, {'c': 3}]) == (1, 2, 3, (), {})
+ assert module._call_function('testfunc', func_args=[{'c': 3}, {'a': 1}, {'b': 2}]) == (1, 2, 3, (), {})
+
+ with patch.dict(module.__salt__,
+ {'testfunc': lambda c, a, b, *args, **kwargs: (a, b, c, args, kwargs)}, clear=True):
+ assert module._call_function('testfunc', func_args=[{'a': 1}, {'b': 2}, {'c': 3}]) == (1, 2, 3, (), {})
+ assert module._call_function('testfunc', func_args=[{'c': 3}, {'a': 1}, {'b': 2}]) == (1, 2, 3, (), {})
+
+ def test_call_function_ordered_args(self):
+ '''
+ Test _call_function routine when params are not named. Their position should matter.
+
+ :return:
+ '''
+ with patch.dict(module.__salt__,
+ {'testfunc': lambda a, b, c, *args, **kwargs: (a, b, c, args, kwargs)}, clear=True):
+ assert module._call_function('testfunc', func_args=[1, 2, 3]) == (1, 2, 3, (), {})
+ assert module._call_function('testfunc', func_args=[3, 1, 2]) == (3, 1, 2, (), {})
--
2.16.4

View File

@ -1,4 +1,4 @@
From 32691d82e32dbc70adec03bee214b971c82a73cd Mon Sep 17 00:00:00 2001
From 73afbe5fe00c47427a032f8d94c113e1375e32ea Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?=
<psuarezhernandez@suse.com>
Date: Mon, 8 Jul 2019 14:46:10 +0100
@ -9,10 +9,10 @@ Subject: [PATCH] Prevent ansiblegate unit tests to fail on Ubuntu
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/tests/unit/modules/test_ansiblegate.py b/tests/unit/modules/test_ansiblegate.py
index 70b47f8bc2..2a24d6f147 100644
index b7b43efda4..05dff4a4fa 100644
--- a/tests/unit/modules/test_ansiblegate.py
+++ b/tests/unit/modules/test_ansiblegate.py
@@ -172,9 +172,11 @@ description:
@@ -169,9 +169,11 @@ description:
with patch('salt.utils.timed_subprocess.TimedProc', proc):
ret = _ansible_module_caller.call("one.two.three", "arg_1", kwarg1="foobar")
if six.PY3:

Some files were not shown because too many files have changed in this diff Show More