Accepting request 719814 from systemsmanagement:saltstack
- Multiple fixes on cmdmod, chroot, freezer and zypperpkg needed for Yomi cmdmod: fix runas and group in run_chroot chroot: add missing sys directory chroot: change variable name to root chroot: fix bug in safe_kwargs iteration freezer: do not fail in cache dir is present freezer: clean freeze YAML profile on restore zypperpkg: fix pkg.list_pkgs cache - Added: * accumulated-changes-required-for-yomi-165.patch - Avoid traceback on http.query when there are errors with the requested URL (bsc#1128554) - Added: * avoid-traceback-when-http.query-request-cannot-be-pe.patch - Salt python client get_full_returns seems return data from incorrect jid (bsc#1131114) - Added: * checking-for-jid-before-returning-data.patch OBS-URL: https://build.opensuse.org/request/show/719814 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/salt?expand=0&rev=91
This commit is contained in:
commit
59ccf33a3e
@ -1 +1 @@
|
||||
760cec648ef1960ceba0c6f265dc821a2aa1f536
|
||||
3968202dca49a70046366b3807d1e6a2f762ffdf
|
580
accumulated-changes-required-for-yomi-165.patch
Normal file
580
accumulated-changes-required-for-yomi-165.patch
Normal file
@ -0,0 +1,580 @@
|
||||
From 8cd87eba73df54a9ede47eda9425e6ffceff7ac0 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)
|
||||
|
||||
* cmdmod: fix runas and group in run_chroot
|
||||
|
||||
The parameters runas and group for cmdmod.run() will change the efective
|
||||
user and group before executing the command. But in a chroot environment is
|
||||
expected that the change happends inside the chroot, not outside, as the
|
||||
user and groups are refering to objects that can only exist inside the
|
||||
environment.
|
||||
|
||||
This patch add the userspec parameter to the chroot command, to change
|
||||
the user in the correct place.
|
||||
|
||||
(cherry picked from commit f0434aaeeee3ace4e3fc65c04e69984f08b2541e)
|
||||
|
||||
* chroot: add missing sys directory
|
||||
|
||||
(cherry picked from commit cdf74426bcad4e8bf329bf604c77ea83bfca8b2c)
|
||||
|
||||
* chroot: change variable name to root
|
||||
|
||||
(cherry picked from commit 7f68b65b1b0f9eec2a6b07b02714ead0121f0e4b)
|
||||
|
||||
* chroot: fix bug in safe_kwargs iteration
|
||||
|
||||
(cherry picked from commit 39da1c69ea2781bed6e9d8e6879b70d65fa5a5b0)
|
||||
|
||||
* test_cmdmod: fix test_run_cwd_in_combination_with_runas
|
||||
|
||||
(cherry picked from commit 42640ecf161caf64c61e9b02927882f92c850092)
|
||||
|
||||
* test_cmdmod: add test_run_chroot_runas test
|
||||
|
||||
(cherry picked from commit d900035089a22f6741d2095fd1f6694597041a88)
|
||||
|
||||
* freezer: do not fail in cache dir is present
|
||||
|
||||
(cherry picked from commit 25137c51e6d6e53e3099b6cddbf51d4cb2c53d8d)
|
||||
|
||||
* freezer: clean freeze YAML profile on restore
|
||||
|
||||
(cherry picked from commit 56b97c997257f12038399549dc987b7723ab225f)
|
||||
|
||||
* zypperpkg: fix pkg.list_pkgs cache
|
||||
|
||||
The cache from pkg.list_pkgs for the zypper installer is too aggresive.
|
||||
Some parameters will deliver different package lists, like root and
|
||||
includes. The current cache do not take those parameters into
|
||||
consideration, so the next time that this function is called, the last
|
||||
list of packages will be returned, without checking if the current
|
||||
parameters match the old one.
|
||||
|
||||
This patch create a different cache key for each parameter combination,
|
||||
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(-)
|
||||
|
||||
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 d0819f2f79..b279d00a11 100644
|
||||
--- a/salt/modules/cmdmod.py
|
||||
+++ b/salt/modules/cmdmod.py
|
||||
@@ -3064,13 +3064,19 @@ def run_chroot(root,
|
||||
|
||||
if isinstance(cmd, (list, tuple)):
|
||||
cmd = ' '.join([six.text_type(i) for i in cmd])
|
||||
- cmd = 'chroot {0} {1} -c {2}'.format(root, sh_, _cmd_quote(cmd))
|
||||
+
|
||||
+ # If runas and group are provided, we expect that the user lives
|
||||
+ # inside the chroot, not outside.
|
||||
+ if runas:
|
||||
+ userspec = '--userspec {}:{}'.format(runas, group if group else '')
|
||||
+ else:
|
||||
+ userspec = ''
|
||||
+
|
||||
+ cmd = 'chroot {} {} {} -c {}'.format(userspec, root, sh_, _cmd_quote(cmd))
|
||||
|
||||
run_func = __context__.pop('cmd.run_chroot.func', run_all)
|
||||
|
||||
ret = run_func(cmd,
|
||||
- runas=runas,
|
||||
- group=group,
|
||||
cwd=cwd,
|
||||
stdin=stdin,
|
||||
shell=shell,
|
||||
diff --git a/salt/modules/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
|
||||
--- a/salt/modules/zypperpkg.py
|
||||
+++ b/salt/modules/zypperpkg.py
|
||||
@@ -449,8 +449,14 @@ def _clean_cache():
|
||||
'''
|
||||
Clean cached results
|
||||
'''
|
||||
+ keys = []
|
||||
for cache_name in ['pkg.list_pkgs', 'pkg.list_provides']:
|
||||
- __context__.pop(cache_name, None)
|
||||
+ for contextkey in __context__:
|
||||
+ if contextkey.startswith(cache_name):
|
||||
+ keys.append(contextkey)
|
||||
+
|
||||
+ for key in keys:
|
||||
+ __context__.pop(key, None)
|
||||
|
||||
|
||||
def list_upgrades(refresh=True, root=None, **kwargs):
|
||||
@@ -809,9 +815,10 @@ def list_pkgs(versions_as_list=False, root=None, includes=None, **kwargs):
|
||||
|
||||
includes = includes if includes else []
|
||||
|
||||
- contextkey = 'pkg.list_pkgs'
|
||||
+ # Results can be different if a different root or a different
|
||||
+ # inclusion types are passed
|
||||
+ contextkey = 'pkg.list_pkgs_{}_{}'.format(root, includes)
|
||||
|
||||
- # TODO(aplanas): this cached value depends on the parameters
|
||||
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
|
||||
--- a/tests/unit/modules/test_cmdmod.py
|
||||
+++ b/tests/unit/modules/test_cmdmod.py
|
||||
@@ -312,6 +312,22 @@ class CMDMODTestCase(TestCase, LoaderModuleMockMixin):
|
||||
else:
|
||||
raise RuntimeError
|
||||
|
||||
+ @skipIf(salt.utils.platform.is_windows(), 'Do not run on Windows')
|
||||
+ @skipIf(salt.utils.platform.is_darwin(), 'Do not run on MacOS')
|
||||
+ def test_run_cwd_in_combination_with_runas(self):
|
||||
+ '''
|
||||
+ cmd.run executes command in the cwd directory
|
||||
+ when the runas parameter is specified
|
||||
+ '''
|
||||
+ cmd = 'pwd'
|
||||
+ cwd = '/tmp'
|
||||
+ runas = os.getlogin()
|
||||
+
|
||||
+ with patch.dict(cmdmod.__grains__, {'os': 'Darwin',
|
||||
+ 'os_family': 'Solaris'}):
|
||||
+ stdout = cmdmod._run(cmd, cwd=cwd, runas=runas).get('stdout')
|
||||
+ self.assertEqual(stdout, cwd)
|
||||
+
|
||||
def test_run_all_binary_replace(self):
|
||||
'''
|
||||
Test for failed decoding of binary data, for instance when doing
|
||||
@@ -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
|
||||
--- 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.
|
||||
patch.dict(zypper.__salt__, {'pkg_resource.stringify': MagicMock()}):
|
||||
pkgs = zypper.list_pkgs(versions_as_list=True)
|
||||
self.assertFalse(pkgs.get('gpg-pubkey', False))
|
||||
+ self.assertTrue('pkg.list_pkgs_None_[]' in zypper.__context__)
|
||||
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.
|
||||
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))
|
||||
+ self.assertTrue('pkg.list_pkgs_None_[]' in zypper.__context__)
|
||||
for pkg_name, pkg_attr in {
|
||||
'jakarta-commons-discovery': [{
|
||||
'version': '0.4',
|
||||
@@ -1455,3 +1457,22 @@ pattern() = package-c'''),
|
||||
'summary': 'description b',
|
||||
},
|
||||
}
|
||||
+
|
||||
+ def test__clean_cache_empty(self):
|
||||
+ '''Test that an empty cached can be cleaned'''
|
||||
+ context = {}
|
||||
+ with patch.dict(zypper.__context__, context):
|
||||
+ zypper._clean_cache()
|
||||
+ assert context == {}
|
||||
+
|
||||
+ def test__clean_cache_filled(self):
|
||||
+ '''Test that a filled cached can be cleaned'''
|
||||
+ context = {
|
||||
+ 'pkg.list_pkgs_/mnt_[]': None,
|
||||
+ 'pkg.list_pkgs_/mnt_[patterns]': None,
|
||||
+ 'pkg.list_provides': None,
|
||||
+ 'pkg.other_data': None,
|
||||
+ }
|
||||
+ with patch.dict(zypper.__context__, context):
|
||||
+ zypper._clean_cache()
|
||||
+ self.assertEqual(zypper.__context__, {'pkg.other_data': None})
|
||||
--
|
||||
2.21.0
|
||||
|
||||
|
35
avoid-traceback-when-http.query-request-cannot-be-pe.patch
Normal file
35
avoid-traceback-when-http.query-request-cannot-be-pe.patch
Normal file
@ -0,0 +1,35 @@
|
||||
From 36433f3f81fb45ff40ed2d294494342c9f622c2e 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
|
||||
Subject: [PATCH] Avoid traceback when http.query request cannot be
|
||||
performed (bsc#1128554)
|
||||
|
||||
Improve error logging when http.query cannot be performed
|
||||
---
|
||||
salt/utils/http.py | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/salt/utils/http.py b/salt/utils/http.py
|
||||
index 78043b1d6c..1b7dff6202 100644
|
||||
--- a/salt/utils/http.py
|
||||
+++ b/salt/utils/http.py
|
||||
@@ -567,11 +567,13 @@ def query(url,
|
||||
except 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']))
|
||||
return ret
|
||||
- except socket.gaierror as exc:
|
||||
+ except (socket.herror, socket.error, socket.timeout, socket.gaierror) as exc:
|
||||
if status is True:
|
||||
ret['status'] = 0
|
||||
ret['error'] = six.text_type(exc)
|
||||
+ log.error("Cannot perform 'http.query': {0} - {1}".format(url_full, ret['error']))
|
||||
return ret
|
||||
|
||||
if stream is True or handle is True:
|
||||
--
|
||||
2.21.0
|
||||
|
||||
|
35
checking-for-jid-before-returning-data.patch
Normal file
35
checking-for-jid-before-returning-data.patch
Normal file
@ -0,0 +1,35 @@
|
||||
From 8ced9cdeb53e7dc20a1665ba2e373fbdc5d30c5d 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.22.0
|
||||
|
||||
|
31
salt.changes
31
salt.changes
@ -1,3 +1,34 @@
|
||||
-------------------------------------------------------------------
|
||||
Tue Jul 30 09:34:27 UTC 2019 - Pablo Suárez Hernández <pablo.suarezhernandez@suse.com>
|
||||
|
||||
- Multiple fixes on cmdmod, chroot, freezer and zypperpkg needed for Yomi
|
||||
cmdmod: fix runas and group in run_chroot
|
||||
chroot: add missing sys directory
|
||||
chroot: change variable name to root
|
||||
chroot: fix bug in safe_kwargs iteration
|
||||
freezer: do not fail in cache dir is present
|
||||
freezer: clean freeze YAML profile on restore
|
||||
zypperpkg: fix pkg.list_pkgs cache
|
||||
|
||||
- Added:
|
||||
* accumulated-changes-required-for-yomi-165.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Mon Jul 29 10:59:41 UTC 2019 - Pablo Suárez Hernández <pablo.suarezhernandez@suse.com>
|
||||
|
||||
- Avoid traceback on http.query when there are errors with the requested URL (bsc#1128554)
|
||||
|
||||
- Added:
|
||||
* avoid-traceback-when-http.query-request-cannot-be-pe.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Thu Jul 25 10:26:16 UTC 2019 - Mihai Dincă <mihai.dinca@suse.com>
|
||||
|
||||
- Salt python client get_full_returns seems return data from incorrect jid (bsc#1131114)
|
||||
|
||||
- Added:
|
||||
* checking-for-jid-before-returning-data.patch
|
||||
|
||||
-------------------------------------------------------------------
|
||||
Wed Jul 10 08:54:28 UTC 2019 - Pablo Suárez Hernández <pablo.suarezhernandez@suse.com>
|
||||
|
||||
|
12
salt.spec
12
salt.spec
@ -206,6 +206,15 @@ Patch68: allow-passing-kwargs-to-pkg.list_downloaded-bsc-1140.patch
|
||||
Patch69: prevent-ansiblegate-unit-tests-to-fail-on-ubuntu.patch
|
||||
# PATCH_FIX_UPSTREAM: https://github.com/saltstack/salt/pull/53755
|
||||
Patch70: virt-1.volume_infos-fix-for-single-vm.patch
|
||||
# PATCH_FIX_UPSTREAM: https://github.com/saltstack/salt/pull/52459
|
||||
Patch71: checking-for-jid-before-returning-data.patch
|
||||
# PATCH_FIX_UPSTREAM: https://github.com/saltstack/salt/pull/54048
|
||||
Patch72: avoid-traceback-when-http.query-request-cannot-be-pe.patch
|
||||
# PATCH_FIX_UPSTREAM: https://github.com/saltstack/salt/pull/53992
|
||||
# https://github.com/saltstack/salt/pull/53996
|
||||
# https://github.com/saltstack/salt/pull/54022
|
||||
# https://github.com/saltstack/salt/pull/54024
|
||||
Patch73: accumulated-changes-required-for-yomi-165.patch
|
||||
|
||||
# BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-build
|
||||
@ -746,6 +755,9 @@ cp %{S:5} ./.travis.yml
|
||||
%patch68 -p1
|
||||
%patch69 -p1
|
||||
%patch70 -p1
|
||||
%patch71 -p1
|
||||
%patch72 -p1
|
||||
%patch73 -p1
|
||||
|
||||
%build
|
||||
%if 0%{?build_py2}
|
||||
|
Loading…
Reference in New Issue
Block a user