Merge branch '2015.8' into '2016.3'

Conflicts:
  - salt/modules/gpg.py
  - salt/modules/zypper.py
This commit is contained in:
rallytime 2016-10-21 16:09:17 -06:00
commit 8fff95b3b4
5 changed files with 163 additions and 39 deletions

View file

@ -1,13 +1,14 @@
# -*- coding: utf-8 -*-
'''
Manage a GPG keychains, add keys, create keys, retrieve keys
from keyservers. Sign, encrypt and sign & encrypt text and files.
Manage a GPG keychains, add keys, create keys, retrieve keys from keyservers.
Sign, encrypt and sign plus encrypt text and files.
.. versionadded:: 2015.5.0
.. note::
The ``python-gnupg`` library and gpg binary are
required to be installed.
The ``python-gnupg`` library and ``gpg`` binary are required to be
installed.
'''
@ -565,7 +566,7 @@ def get_key(keyid=None, fingerprint=None, user=None, gnupghome=None):
Get a key from the GPG keychain
keyid
The keyid of the key to be retrieved.
The key ID (short or long) of the key to be retrieved.
fingerprint
The fingerprint of the key to be retrieved.
@ -591,7 +592,9 @@ def get_key(keyid=None, fingerprint=None, user=None, gnupghome=None):
'''
tmp = {}
for _key in _list_keys(user, gnupghome):
if _key['fingerprint'] == fingerprint or _key['keyid'] == keyid:
if (_key['fingerprint'] == fingerprint or
_key['keyid'] == keyid or
_key['keyid'][8:] == keyid):
tmp['keyid'] = _key['keyid']
tmp['fingerprint'] = _key['fingerprint']
tmp['uids'] = _key['uids']
@ -625,7 +628,7 @@ def get_secret_key(keyid=None, fingerprint=None, user=None, gnupghome=None):
Get a key from the GPG keychain
keyid
The keyid of the key to be retrieved.
The key ID (short or long) of the key to be retrieved.
fingerprint
The fingerprint of the key to be retrieved.
@ -651,7 +654,9 @@ def get_secret_key(keyid=None, fingerprint=None, user=None, gnupghome=None):
'''
tmp = {}
for _key in _list_keys(user, gnupghome, secret=True):
if _key['fingerprint'] == fingerprint or _key['keyid'] == keyid:
if (_key['fingerprint'] == fingerprint or
_key['keyid'] == keyid or
_key['keyid'][8:] == keyid):
tmp['keyid'] = _key['keyid']
tmp['fingerprint'] = _key['fingerprint']
tmp['uids'] = _key['uids']
@ -681,24 +686,24 @@ def get_secret_key(keyid=None, fingerprint=None, user=None, gnupghome=None):
@_restore_ownership
def import_key(user=None,
text=None,
def import_key(text=None,
filename=None,
user=None,
gnupghome=None):
r'''
Import a key from text or file
user
Which user's keychain to access, defaults to user Salt is running as.
Passing the user as ``salt`` will set the GnuPG home directory to the
``/etc/salt/gpgkeys``.
text
The text containing to import.
filename
The filename containing the key to import.
user
Which user's keychain to access, defaults to user Salt is running as.
Passing the user as ``salt`` will set the GnuPG home directory to the
``/etc/salt/gpgkeys``.
gnupghome
Specify the location where GPG keyring and related files are stored.
@ -711,9 +716,9 @@ def import_key(user=None,
'''
ret = {
'res': True,
'message': ''
}
'res': True,
'message': ''
}
gpg = _create_gpg(user, gnupghome)
@ -761,12 +766,13 @@ def export_key(keyids=None, secret=False, user=None, gnupghome=None):
Export a key from the GPG keychain
keyids
The keyid(s) of the key(s) to be exported. Can be specified as a comma
separated string or a list. Anything which GnuPG itself accepts to
identify a key - for example, the keyid or the fingerprint could be used.
The key ID(s) of the key(s) to be exported. Can be specified as a comma
separated string or a list. Anything which GnuPG itself accepts to
identify a key - for example, the key ID or the fingerprint could be
used.
secret
Export the secret key identified by the keyid information passed.
Export the secret key identified by the ``keyids`` information passed.
user
Which user's keychain to access, defaults to user Salt is running as.
@ -784,7 +790,7 @@ def export_key(keyids=None, secret=False, user=None, gnupghome=None):
salt '*' gpg.export_key keyids=3FAD9F1E secret=True
salt '*' gpg.export_key keyid="['3FAD9F1E','3FBD8F1E']" user=username
salt '*' gpg.export_key keyids="['3FAD9F1E','3FBD8F1E']" user=username
'''
gpg = _create_gpg(user, gnupghome)

View file

@ -1070,7 +1070,13 @@ def install(name=None,
return ret
def upgrade(refresh=True, skip_verify=False):
def upgrade(refresh=True,
dryrun=False,
dist_upgrade=False,
fromrepo=None,
novendorchange=False,
skip_verify=False,
**kwargs): # pylint: disable=unused-argument
'''
.. versionchanged:: 2015.8.12,2016.3.3,Carbon
On minions running systemd>=205, `systemd-run(1)`_ is now used to
@ -1093,6 +1099,22 @@ def upgrade(refresh=True, skip_verify=False):
If set to False it depends on zypper if a refresh is
executed.
dryrun
If set to True, it creates a debug solver log file and then perform
a dry-run upgrade (no changes are made). Default: False
dist_upgrade
Perform a system dist-upgrade. Default: False
fromrepo
Specify a list of package repositories to upgrade from. Default: None
novendorchange
If set to True, no allow vendor changes. Default: False
skip_verify
Skip the GPG verification check (e.g., ``--no-gpg-checks``)
Return a dict containing the new package names and versions::
{'<package>': {'old': '<old-version>',
@ -1103,36 +1125,57 @@ def upgrade(refresh=True, skip_verify=False):
.. code-block:: bash
salt '*' pkg.upgrade
Options:
skip_verify
Skip the GPG verification check (e.g., ``--no-gpg-checks``)
salt '*' pkg.upgrade dist-upgrade=True fromrepo='["MyRepoName"]' novendorchange=True
salt '*' pkg.upgrade dist-upgrade=True dryrun=True
'''
ret = {'changes': {},
'result': True,
'comment': '',
}
cmd_update = (['dist-upgrade'] if dist_upgrade else ['update']) + ['--auto-agree-with-licenses']
if refresh:
refresh_db()
old = list_pkgs()
if dryrun:
cmd_update.append('--dry-run')
if dist_upgrade:
if dryrun:
# Creates a solver test case for debugging.
log.info('Executing debugsolver and performing a dry-run dist-upgrade')
__zypper__.noraise.call(*cmd_update + ['--debug-solver'])
if fromrepo:
for repo in fromrepo:
cmd_update.extend(['--from', repo])
log.info('Targeting repos: {0!r}'.format(fromrepo))
if novendorchange:
# TODO: Grains validation should be moved to Zypper class
if __grains__['osrelease_info'][0] > 11:
cmd_update.append('--no-allow-vendor-change')
log.info('Disabling vendor changes')
else:
log.warn('Disabling vendor changes is not supported on this Zypper version')
if skip_verify:
__zypper__(systemd_scope=_systemd_scope()).noraise.call('update', '--auto-agree-with-licenses', '--no-gpg-checks')
else:
__zypper__(systemd_scope=_systemd_scope()).noraise.call('update', '--auto-agree-with-licenses')
cmd_update.append('--no-gpg-checks')
old = list_pkgs()
__zypper__(systemd_scope=_systemd_scope()).noraise.call(*cmd_update)
if __zypper__.exit_code not in __zypper__.SUCCESS_EXIT_CODES:
ret['result'] = False
ret['comment'] = (__zypper__.stdout() + os.linesep + __zypper__.stderr()).strip()
else:
__context__.pop('pkg.list_pkgs', None)
new = list_pkgs()
ret['changes'] = salt.utils.compare_dicts(old, new)
if dryrun or not ret['result']:
ret['comment'] = (__zypper__.stdout() + os.linesep + __zypper__.stderr()).strip()
return ret

View file

@ -361,7 +361,7 @@ class SPMClient(object):
metadata = yaml.safe_load(rpm)
else:
response = http.query(dl_path, text=True)
metadata = response.get('text', {})
metadata = yaml.safe_load(response.get('text', '{}'))
cache_path = '{0}/{1}.p'.format(
self.opts['spm_cache_dir'],
repo

View file

@ -54,7 +54,8 @@ def running(name,
update=False,
user=None,
conf_file=None,
bin_env=None):
bin_env=None,
**kwargs):
'''
Ensure the named service is running.
@ -271,7 +272,8 @@ def running(name,
def dead(name,
user=None,
conf_file=None,
bin_env=None):
bin_env=None,
**kwargs):
'''
Ensure the named service is dead (not running).

View file

@ -50,6 +50,7 @@ from salt.modules import zypper
# Globals
zypper.__salt__ = dict()
zypper.__grains__ = dict()
zypper.__context__ = dict()
zypper.rpm = None
@ -329,6 +330,78 @@ class ZypperTestCase(TestCase):
with patch('salt.modules.zypper.__zypper__', ZyppCallMock(return_value=get_test_data('zypper-available.txt'))):
self.assertEqual(zypper.latest_version('vim'), '7.4.326-2.62')
@patch('salt.modules.zypper.refresh_db', MagicMock(return_value=True))
@patch('salt.modules.zypper._systemd_scope', MagicMock(return_value=False))
@patch.dict('salt.modules.zypper.__grains__', {'osrelease_info': [12, 1]})
def test_upgrade_success(self):
'''
Test system upgrade and dist-upgrade success.
:return:
'''
with patch('salt.modules.zypper.__zypper__.noraise.call', MagicMock()) as zypper_mock:
with patch('salt.modules.zypper.list_pkgs', MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.2"}])):
ret = zypper.upgrade()
self.assertTrue(ret['result'])
self.assertDictEqual(ret['changes'], {"vim": {"old": "1.1", "new": "1.2"}})
zypper_mock.assert_any_call('update', '--auto-agree-with-licenses')
with patch('salt.modules.zypper.list_pkgs', MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.2"}])):
ret = zypper.upgrade(dist_upgrade=True)
self.assertTrue(ret['result'])
self.assertDictEqual(ret['changes'], {"vim": {"old": "1.1", "new": "1.2"}})
zypper_mock.assert_any_call('dist-upgrade', '--auto-agree-with-licenses')
with patch('salt.modules.zypper.list_pkgs', MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.1"}])):
ret = zypper.upgrade(dist_upgrade=True, dryrun=True)
self.assertTrue(ret['result'])
self.assertDictEqual(ret['changes'], {})
zypper_mock.assert_any_call('dist-upgrade', '--auto-agree-with-licenses', '--dry-run')
zypper_mock.assert_any_call('dist-upgrade', '--auto-agree-with-licenses', '--dry-run', '--debug-solver')
with patch('salt.modules.zypper.list_pkgs', MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.2"}])):
ret = zypper.upgrade(dist_upgrade=True, fromrepo=["Dummy", "Dummy2"], novendorchange=True)
self.assertTrue(ret['result'])
self.assertDictEqual(ret['changes'], {"vim": {"old": "1.1", "new": "1.2"}})
zypper_mock.assert_any_call('dist-upgrade', '--auto-agree-with-licenses', '--from', "Dummy", '--from', 'Dummy2', '--no-allow-vendor-change')
@patch('salt.modules.zypper.refresh_db', MagicMock(return_value=True))
@patch('salt.modules.zypper._systemd_scope', MagicMock(return_value=False))
@patch.dict('salt.modules.zypper.__grains__', {'osrelease_info': [12, 1]})
def test_upgrade_failure(self):
'''
Test system upgrade failure.
:return:
'''
zypper_out = '''
Loading repository data...
Reading installed packages...
Computing distribution upgrade...
Use 'zypper repos' to get the list of defined repositories.
Repository 'DUMMY' not found by its alias, number, or URI.
'''
class FailingZypperDummy(object):
def __init__(self):
self.stdout = MagicMock(return_value=zypper_out)
self.stderr = MagicMock(return_value="")
self.exit_code = MagicMock(return_value=555)
self.noraise = MagicMock()
self.SUCCESS_EXIT_CODES = [0]
def __call__(self, *args, **kwargs):
return self
with patch('salt.modules.zypper.__zypper__', FailingZypperDummy()) as zypper_mock:
zypper_mock.noraise.call = MagicMock()
with patch('salt.modules.zypper.list_pkgs', MagicMock(side_effect=[{"vim": "1.1"}, {"vim": "1.1"}])):
ret = zypper.upgrade(dist_upgrade=True, fromrepo=["DUMMY"])
self.assertFalse(ret['result'])
self.assertEqual(ret['comment'], zypper_out.strip())
self.assertDictEqual(ret['changes'], {})
zypper_mock.noraise.call.assert_called_with('dist-upgrade', '--auto-agree-with-licenses', '--from', 'DUMMY')
@patch('salt.modules.zypper.refresh_db', MagicMock(return_value=True))
def test_upgrade_available(self):
'''