Merge pull request #33710 from rallytime/merge-2016.3

[2016.3] Merge forward from 2015.8 to 2016.3
This commit is contained in:
Mike Place 2016-06-02 09:19:00 -07:00
commit 78966f5f30
7 changed files with 267 additions and 39 deletions

View file

@ -790,6 +790,8 @@ def free_slave(**connection_args):
salt '*' mysql.free_slave
'''
slave_db = _connect(**connection_args)
if slave_db is None:
return ''
slave_cur = slave_db.cursor(MySQLdb.cursors.DictCursor)
slave_cur.execute('show slave status')
slave_status = slave_cur.fetchone()
@ -802,6 +804,8 @@ def free_slave(**connection_args):
# servers here, and only overriding the host option in the connect
# function.
master_db = _connect(**master)
if master_db is None:
return ''
master_cur = master_db.cursor()
master_cur.execute('flush logs')
master_db.close()
@ -1900,6 +1904,8 @@ def processlist(**connection_args):
ret = []
dbc = _connect(**connection_args)
if dbc is None:
return []
cur = dbc.cursor()
_execute(cur, 'SHOW FULL PROCESSLIST')
hdr = [c[0] for c in cur.description]
@ -1980,6 +1986,8 @@ def get_master_status(**connection_args):
mod = sys._getframe().f_code.co_name
log.debug('{0}<--'.format(mod))
conn = _connect(**connection_args)
if conn is None:
return []
rtnv = __do_query_into_hash(conn, "SHOW MASTER STATUS")
conn.close()
@ -2048,6 +2056,8 @@ def get_slave_status(**connection_args):
mod = sys._getframe().f_code.co_name
log.debug('{0}<--'.format(mod))
conn = _connect(**connection_args)
if conn is None:
return []
rtnv = __do_query_into_hash(conn, "SHOW SLAVE STATUS")
conn.close()
@ -2076,6 +2086,8 @@ def showvariables(**connection_args):
mod = sys._getframe().f_code.co_name
log.debug('{0}<--'.format(mod))
conn = _connect(**connection_args)
if conn is None:
return []
rtnv = __do_query_into_hash(conn, "SHOW VARIABLES")
conn.close()
if len(rtnv) == 0:
@ -2102,6 +2114,8 @@ def showglobal(**connection_args):
mod = sys._getframe().f_code.co_name
log.debug('{0}<--'.format(mod))
conn = _connect(**connection_args)
if conn is None:
return []
rtnv = __do_query_into_hash(conn, "SHOW GLOBAL VARIABLES")
conn.close()
if len(rtnv) == 0:

View file

@ -770,6 +770,7 @@ def mod_repo(repo, **kwargs):
# Modify added or existing repo according to the options
cmd_opt = []
global_cmd_opt = []
call_refresh = False
if 'enabled' in kwargs:
cmd_opt.append(kwargs['enabled'] and '--enable' or '--disable')
@ -793,13 +794,19 @@ def mod_repo(repo, **kwargs):
if kwargs.get('gpgautoimport') is True:
global_cmd_opt.append('--gpg-auto-import-keys')
call_refresh = True
if cmd_opt:
cmd_opt = global_cmd_opt + ['mr'] + cmd_opt + [repo]
__zypper__.refreshable.xml.call(*cmd_opt)
# If repo nor added neither modified, error should be thrown
if not added and not cmd_opt:
if call_refresh:
# when used with "zypper ar --refresh" or "zypper mr --refresh"
# --gpg-auto-import-keys is not doing anything
# so we need to specifically refresh here with --gpg-auto-import-keys
refresh_opts = global_cmd_opt + ['refresh'] + [repo]
__zypper__.xml.call(*refresh_opts)
elif not added and not cmd_opt:
raise CommandExecutionError(
'Specified arguments did not result in modification of repo'
)

View file

@ -49,22 +49,13 @@ if HAS_PIP is True:
if 'pip' in sys.modules:
del sys.modules['pip']
ver = pip.__version__.split('.')
pip_ver = tuple([int(x) for x in ver if x.isdigit()])
if pip_ver >= (8, 0, 0):
try:
from pip.exceptions import InstallationError
else:
except ImportError:
InstallationError = ValueError
# pylint: enable=import-error
ver = pip.__version__.split('.')
pip_ver = tuple([int(x) for x in ver if x.isdigit()])
if pip_ver >= (8, 0, 0):
from pip.exceptions import InstallationError
else:
InstallationError = ValueError
logger = logging.getLogger(__name__)
# Define the module's virtual name

View file

@ -572,7 +572,16 @@ class ZeroMQReqServerChannel(salt.transport.mixins.auth.AESReqServerMixin, salt.
payload = self.serial.loads(payload[0])
payload = self._decode_payload(payload)
except Exception as exc:
log.error('Bad load from minion: %s: %s', type(exc).__name__, exc)
exc_type = type(exc).__name__
if exc_type == 'AuthenticationError':
log.debug(
'Minion failed to auth to master. Since the payload is '
'encrypted, it is not known which minion failed to '
'authenticate. It is likely that this is a transient '
'failure due to the master rotating its public key.'
)
else:
log.error('Bad load from minion: %s: %s', exc_type, exc)
stream.send(self.serial.dumps('bad load'))
raise tornado.gen.Return()

View file

@ -145,9 +145,8 @@ class CPModuleTest(integration.ModuleCase):
def test_get_url(self):
'''
cp.get_url
cp.get_url with salt:// source
'''
# We should add a 'if the internet works download some files'
tgt = os.path.join(integration.TMP, 'scene33')
self.run_function(
'cp.get_url',
@ -160,6 +159,24 @@ class CPModuleTest(integration.ModuleCase):
self.assertIn('KNIGHT: They\'re nervous, sire.', data)
self.assertNotIn('bacon', data)
def test_get_url_https(self):
'''
cp.get_url with https:// source
'''
tgt = os.path.join(integration.TMP, 'test_get_url_https')
self.run_function(
'cp.get_url',
[
'https://repo.saltstack.com/index.html',
tgt,
])
with salt.utils.fopen(tgt, 'r') as instructions:
data = instructions.read()
self.assertIn('Bootstrap', data)
self.assertIn('Debian', data)
self.assertIn('Windows', data)
self.assertNotIn('AYBABTU', data)
def test_cache_file(self):
'''
cp.cache_file

View file

@ -269,6 +269,17 @@ class MySQLTestCase(TestCase):
'''
self._test_call(mysql.get_slave_status, 'SHOW SLAVE STATUS')
def test_get_slave_status_bad_server(self):
'''
Test get_slave_status in the mysql execution module, simulating a broken server
'''
connect_mock = MagicMock(return_value=None)
mysql._connect = connect_mock
with patch.dict(mysql.__salt__, {'config.option': MagicMock()}):
rslt = mysql.get_slave_status()
connect_mock.assert_has_calls([call()])
self.assertEqual(rslt, [])
@skipIf(True, 'MySQL module claims this function is not ready for production')
def test_free_slave(self):
pass

View file

@ -11,6 +11,7 @@ from salttesting import TestCase, skipIf
from salttesting.mock import (
Mock,
MagicMock,
call,
patch,
NO_MOCK,
NO_MOCK_REASON
@ -55,10 +56,26 @@ zypper.rpm = None
@skipIf(NO_MOCK, NO_MOCK_REASON)
class ZypperTestCase(TestCase):
'''
Test cases for salt.modules.zypper
'''
def setUp(self):
self.new_repo_config = dict(
name='mock-repo-name',
url='http://repo.url/some/path'
)
side_effect = [
Mock(**{'sections.return_value': []}),
Mock(**{'sections.return_value': [self.new_repo_config['name']]})
]
self.zypper_patcher_config = {
'_get_configured_repos': Mock(side_effect=side_effect),
'__zypper__': Mock(),
'get_repo': Mock()
}
def test_list_upgrades(self):
'''
List package upgrades
@ -438,37 +455,199 @@ class ZypperTestCase(TestCase):
self.assertEqual(r_info['enabled'], alias == 'SLE12-SP1-x86_64-Update')
self.assertEqual(r_info['autorefresh'], alias == 'SLE12-SP1-x86_64-Update')
def test_modify_repo_gpg_auto_import_keys_parameter_position(self):
def test_repo_add_nomod_noref(self):
'''
Tests if when modifying a repo, --gpg-auto-import-keys is a global option
Test mod_repo adds the new repo and nothing else
:return:
'''
zypper_patcher = patch.multiple(
'salt.modules.zypper',
**{
'_get_configured_repos': Mock(
**{
'return_value.sections.return_value': ['mock-repo-name']
}
),
'__zypper__': Mock(),
'get_repo': Mock()
}
)
'salt.modules.zypper', **self.zypper_patcher_config)
url = self.new_repo_config['url']
name = self.new_repo_config['name']
with zypper_patcher:
zypper.mod_repo(
'mock-repo-name',
**{
'disabled': False,
'url': 'http://repo.url/some/path',
'gpgkey': 'http://repo.key',
'refresh': True,
'gpgautoimport': True
}
zypper.mod_repo(name, **{'url': url})
self.assertEqual(
zypper.__zypper__.xml.call.call_args_list,
[call('ar', url, name)]
)
zypper.__zypper__.refreshable.xml.call.assert_not_called()
def test_repo_noadd_nomod_noref(self):
'''
Test mod_repo detects the repo already exists,
no modification was requested and no refresh requested either
:return:
'''
url = self.new_repo_config['url']
name = self.new_repo_config['name']
self.zypper_patcher_config['_get_configured_repos'] = Mock(
**{'return_value.sections.return_value': [name]}
)
zypper_patcher = patch.multiple(
'salt.modules.zypper', **self.zypper_patcher_config)
with zypper_patcher:
with self.assertRaisesRegexp(
Exception,
'Specified arguments did not result in modification of repo'
):
zypper.mod_repo(name, **{'url': url})
with self.assertRaisesRegexp(
Exception,
'Specified arguments did not result in modification of repo'
):
zypper.mod_repo(name, **{'url': url, 'gpgautoimport': 'a'})
zypper.__zypper__.xml.call.assert_not_called()
zypper.__zypper__.refreshable.xml.call.assert_not_called()
def test_repo_add_mod_noref(self):
'''
Test mod_repo adds the new repo and call modify to update autorefresh
:return:
'''
zypper_patcher = patch.multiple(
'salt.modules.zypper', **self.zypper_patcher_config)
url = self.new_repo_config['url']
name = self.new_repo_config['name']
with zypper_patcher:
zypper.mod_repo(name, **{'url': url, 'refresh': True})
self.assertEqual(
zypper.__zypper__.xml.call.call_args_list,
[call('ar', url, name)]
)
zypper.__zypper__.refreshable.xml.call.assert_called_once_with(
'--gpg-auto-import-keys', 'mr', '--refresh', 'mock-repo-name'
'mr', '--refresh', name
)
def test_repo_noadd_mod_noref(self):
'''
Test mod_repo detects the repository exists,
calls modify to update 'autorefresh' but does not call refresh
:return:
'''
url = self.new_repo_config['url']
name = self.new_repo_config['name']
self.zypper_patcher_config['_get_configured_repos'] = Mock(
**{'return_value.sections.return_value': [name]})
zypper_patcher = patch.multiple(
'salt.modules.zypper', **self.zypper_patcher_config)
with zypper_patcher:
zypper.mod_repo(name, **{'url': url, 'refresh': True})
zypper.__zypper__.xml.call.assert_not_called()
zypper.__zypper__.refreshable.xml.call.assert_called_once_with(
'mr', '--refresh', name
)
def test_repo_add_nomod_ref(self):
'''
Test mod_repo adds the new repo and refreshes the repo with
`zypper --gpg-auto-import-keys refresh <repo-name>`
:return:
'''
zypper_patcher = patch.multiple(
'salt.modules.zypper', **self.zypper_patcher_config)
url = self.new_repo_config['url']
name = self.new_repo_config['name']
with zypper_patcher:
zypper.mod_repo(name, **{'url': url, 'gpgautoimport': True})
self.assertEqual(
zypper.__zypper__.xml.call.call_args_list,
[
call('ar', url, name),
call('--gpg-auto-import-keys', 'refresh', name)
]
)
zypper.__zypper__.refreshable.xml.call.assert_not_called()
def test_repo_noadd_nomod_ref(self):
'''
Test mod_repo detects the repo already exists,
has nothing to modify and refreshes the repo with
`zypper --gpg-auto-import-keys refresh <repo-name>`
:return:
'''
url = self.new_repo_config['url']
name = self.new_repo_config['name']
self.zypper_patcher_config['_get_configured_repos'] = Mock(
**{'return_value.sections.return_value': [name]}
)
zypper_patcher = patch.multiple(
'salt.modules.zypper', **self.zypper_patcher_config)
with zypper_patcher:
zypper.mod_repo(name, **{'url': url, 'gpgautoimport': True})
self.assertEqual(
zypper.__zypper__.xml.call.call_args_list,
[call('--gpg-auto-import-keys', 'refresh', name)]
)
zypper.__zypper__.refreshable.xml.call.assert_not_called()
def test_repo_add_mod_ref(self):
'''
Test mod_repo adds the new repo,
calls modify to update 'autorefresh' and refreshes the repo with
`zypper --gpg-auto-import-keys refresh <repo-name>`
:return:
'''
zypper_patcher = patch.multiple(
'salt.modules.zypper', **self.zypper_patcher_config)
url = self.new_repo_config['url']
name = self.new_repo_config['name']
with zypper_patcher:
zypper.mod_repo(
name,
**{'url': url, 'refresh': True, 'gpgautoimport': True}
)
self.assertEqual(
zypper.__zypper__.xml.call.call_args_list,
[
call('ar', url, name),
call('--gpg-auto-import-keys', 'refresh', name)
]
)
zypper.__zypper__.refreshable.xml.call.assert_called_once_with(
'--gpg-auto-import-keys', 'mr', '--refresh', name
)
def test_repo_noadd_mod_ref(self):
'''
Test mod_repo detects the repo already exists,
calls modify to update 'autorefresh' and refreshes the repo with
`zypper --gpg-auto-import-keys refresh <repo-name>`
:return:
'''
url = self.new_repo_config['url']
name = self.new_repo_config['name']
self.zypper_patcher_config['_get_configured_repos'] = Mock(
**{'return_value.sections.return_value': [name]}
)
zypper_patcher = patch.multiple(
'salt.modules.zypper', **self.zypper_patcher_config)
with zypper_patcher:
zypper.mod_repo(
name,
**{'url': url, 'refresh': True, 'gpgautoimport': True}
)
self.assertEqual(
zypper.__zypper__.xml.call.call_args_list,
[call('--gpg-auto-import-keys', 'refresh', name)]
)
zypper.__zypper__.refreshable.xml.call.assert_called_once_with(
'--gpg-auto-import-keys', 'mr', '--refresh', name
)
if __name__ == '__main__':