diff --git a/salt/modules/aptpkg.py b/salt/modules/aptpkg.py index 178b8bb0fb..eca020836e 100644 --- a/salt/modules/aptpkg.py +++ b/salt/modules/aptpkg.py @@ -585,6 +585,8 @@ def upgrade(refresh=True, dist_upgrade=True, **kwargs): def hold(name=None, pkgs=None, sources=None, *kwargs): ''' + .. versionadded:: Helium + Set package in 'hold' state, meaning it will not be upgraded. name @@ -604,49 +606,60 @@ def hold(name=None, pkgs=None, sources=None, *kwargs): .. code-block:: bash salt '*' pkg.hold pkgs='["foo", "bar"]' - - .. versionadded:: Helium - ''' - if not name and not pkgs and not sources: - return 'Error: name, pkgs or sources needs to be specified.' + raise SaltInvocationError( + 'One of name, pkgs, or sources must be specified.' + ) + if pkgs and sources: + raise SaltInvocationError( + 'Only one of pkgs or sources can be specified.' + ) - if name and not pkgs: - pkgs = [] - pkgs.append(name) - elif name and sources: - pkgs = [] + targets = [] + if pkgs: + targets.extend(pkgs) + elif sources: for source in sources: - pkgs += source.keys() + targets.append(next(iter(source))) + else: + targets.append(name) ret = {} - for pkg in pkgs: - if isinstance(pkg, dict): - pkg = pkg.keys()[0] + for target in targets: + if isinstance(target, dict): + target = next(iter(target)) - ret[pkg] = {'name': pkg, 'changes': {}, 'result': False, 'comment': ''} - state = get_selections(pattern=pkg, state=hold) + ret[target] = {'name': target, + 'changes': {}, + 'result': False, + 'comment': ''} + + state = get_selections(pattern=target, state='hold') if not state: - ret[pkg]['comment'] = 'Package {0} not currently held.'.format(pkg) + ret[target]['comment'] = ('Package {0} not currently held.' + .format(target)) elif not salt.utils.is_true(state.get('hold', False)): if 'test' in kwargs and kwargs['test']: - ret[pkg].update(result=None) - ret[pkg]['comment'] = 'Package {0} is set to be held.'.format(pkg) + ret[target].update(result=None) + ret[target]['comment'] = ('Package {0} is set to be held.' + .format(target)) else: - result = set_selections( - selection={'hold': [pkg]} - ) - ret[pkg].update(changes=result[pkg], result=True) - ret[pkg]['comment'] = 'Package {0} is now being held.'.format(pkg) + result = set_selections(selection={'hold': [target]}) + ret[target].update(changes=result[target], result=True) + ret[target]['comment'] = ('Package {0} is now being held.' + .format(target)) else: - ret[pkg].update(result=True) - ret[pkg]['comment'] = 'Package {0} is already set to be held.'.format(pkg) + ret[target].update(result=True) + ret[target]['comment'] = ('Package {0} is already set to be held.' + .format(target)) return ret def unhold(name=None, pkgs=None, sources=None, **kwargs): ''' + .. versionadded:: Helium + Set package current in 'hold' state to install state, meaning it will be upgraded. @@ -667,46 +680,53 @@ def unhold(name=None, pkgs=None, sources=None, **kwargs): .. code-block:: bash salt '*' pkg.unhold pkgs='["foo", "bar"]' - - .. versionadded:: Helium - ''' - if not name and not pkgs and not sources: - return 'Error: name, pkgs or sources needs to be specified.' + raise SaltInvocationError( + 'One of name, pkgs, or sources must be specified.' + ) + if pkgs and sources: + raise SaltInvocationError( + 'Only one of pkgs or sources can be specified.' + ) - if name and not pkgs: - pkgs = [] - pkgs.append(name) - elif name and sources: - pkgs = [] + targets = [] + if pkgs: + targets.extend(pkgs) + elif sources: for source in sources: - pkgs += source.keys() + targets.append(next(iter(source))) + else: + targets.append(name) ret = {} - for pkg in pkgs: - if isinstance(pkg, dict): - pkg = pkg.keys()[0] + for target in targets: + if isinstance(target, dict): + target = next(iter(target)) - ret[pkg] = {'changes': {}, 'result': False, 'comment': ''} - state = get_selections(pattern=pkg) + ret[target] = {'name': target, + 'changes': {}, + 'result': False, + 'comment': ''} + + state = get_selections(pattern=target) if not state: - ret[pkg]['comment'] = 'Package {0} does not have a state.'.format(pkg) + ret[target]['comment'] = ('Package {0} does not have a state.' + .format(target)) elif salt.utils.is_true(state.get('hold', False)): if 'test' in kwargs and kwargs['test']: - ret[pkg].update(result=None) - ret['comment'] = 'Package {0} is set not to be held.'.format(pkg) + ret[target].update(result=None) + ret['comment'] = ('Package {0} is set not to be held.' + .format(target)) else: - result = set_selections( - selection={'install': [pkg]} - ) - ret[pkg].update(changes=result[pkg], result=True) - ret[pkg]['comment'] = 'Package {0} is no longer being held.'.format(pkg) + result = set_selections(selection={'install': [target]}) + ret[target].update(changes=result[target], result=True) + ret[target]['comment'] = ('Package {0} is no longer being ' + 'held.'.format(target)) else: - ret[pkg].update(result=True) - ret[pkg]['comment'] = 'Package {0} is already set not to be held.'.format(pkg) - - log.debug('in unhold {0}'.format(ret)) + ret[target].update(result=True) + ret[target]['comment'] = ('Package {0} is already set not to be ' + 'held.'.format(target)) return ret diff --git a/salt/modules/yumpkg.py b/salt/modules/yumpkg.py index d3c5fa3485..8ba9f5badd 100644 --- a/salt/modules/yumpkg.py +++ b/salt/modules/yumpkg.py @@ -1026,6 +1026,8 @@ def purge(name=None, pkgs=None, **kwargs): # pylint: disable=W0613 def hold(name=None, pkgs=None, sources=None, **kwargs): # pylint: disable=W0613 ''' + .. versionadded:: Helium + Hold packages with ``yum -q versionlock``. name @@ -1037,9 +1039,6 @@ def hold(name=None, pkgs=None, sources=None, **kwargs): # pylint: disable=W0613 A list of packages to hold. Must be passed as a python list. The ``name`` parameter will be ignored if this option is passed. - .. versionadded:: Helium - - Returns a dict containing the changes. CLI Example: @@ -1049,54 +1048,68 @@ def hold(name=None, pkgs=None, sources=None, **kwargs): # pylint: disable=W0613 salt '*' pkg.hold salt '*' pkg.hold pkgs='["foo", "bar"]' ''' + if 'yum-plugin-versionlock' not in list_pkgs(): + raise SaltInvocationError( + 'Packages cannot be held, yum-plugin-versionlock is not installed.' + ) if not name and not pkgs and not sources: - return 'Error: name or pkgs needs to be specified.' + raise SaltInvocationError( + 'One of name, pkgs, or sources must be specified.' + ) + if pkgs and sources: + raise SaltInvocationError( + 'Only one of pkgs or sources can be specified.' + ) - if name and not pkgs and not sources: - pkgs = [] - pkgs.append(name) - elif name and sources: - pkgs = [] + targets = [] + if pkgs: + targets.extend(pkgs) + elif sources: for source in sources: - pkgs += source.keys() - - current_pkgs = list_pkgs() - if 'yum-plugin-versionlock' not in current_pkgs: - ret = {} - ret['result'] = False - ret['comment'] = 'Packages cannot be held, yum-plugin-versionlock needs to be installed.' - return ret + targets.append(next(iter(source))) + else: + targets.append(name) current_locks = get_locked_packages() ret = {} - for pkg in pkgs: - if isinstance(pkg, dict): - pkg = pkg.keys()[0] + for target in targets: + if isinstance(target, dict): + target = next(iter(target)) - ret[pkg] = {'name': pkg, 'changes': {}, 'result': False, 'comment': ''} - if pkg not in current_locks: + ret[target] = {'name': target, + 'changes': {}, + 'result': False, + 'comment': ''} + + if target not in current_locks: if 'test' in kwargs and kwargs['test']: - ret[pkg].update(result=None) - ret[pkg]['comment'] = 'Package {0} is set to be held.'.format(pkg) + ret[target].update(result=None) + ret[target]['comment'] = ('Package {0} is set to be held.' + .format(target)) else: - cmd = 'yum -q versionlock {0}'.format(pkg) + cmd = 'yum -q versionlock {0}'.format(target) out = __salt__['cmd.run_all'](cmd) if out['retcode'] == 0: - ret[pkg].update(result=True) - ret[pkg]['comment'] = 'Package {0} is now being held.'.format(pkg) - ret[pkg]['changes']['new'] = 'hold' - ret[pkg]['changes']['old'] = '' + ret[target].update(result=True) + ret[target]['comment'] = ('Package {0} is now being held.' + .format(target)) + ret[target]['changes']['new'] = 'hold' + ret[target]['changes']['old'] = '' else: - ret[pkg]['comment'] = 'Package {0} was unable to be held.'.format(pkg) + ret[target]['comment'] = ('Package {0} was unable to be held.' + .format(target)) else: - ret[pkg].update(result=True) - ret[pkg]['comment'] = 'Package {0} is already set to be held.'.format(pkg) + ret[target].update(result=True) + ret[target]['comment'] = ('Package {0} is already set to be held.' + .format(target)) return ret def unhold(name=None, pkgs=None, sources=None, **kwargs): # pylint: disable=W0613 ''' + .. versionadded:: Helium + Hold packages with ``yum -q versionlock``. name @@ -1108,9 +1121,6 @@ def unhold(name=None, pkgs=None, sources=None, **kwargs): # pylint: disable=W06 A list of packages to unhold. Must be passed as a python list. The ``name`` parameter will be ignored if this option is passed. - .. versionadded:: Helium - - Returns a dict containing the changes. CLI Example: @@ -1120,52 +1130,64 @@ def unhold(name=None, pkgs=None, sources=None, **kwargs): # pylint: disable=W06 salt '*' pkg.unhold salt '*' pkg.unhold pkgs='["foo", "bar"]' ''' + if 'yum-plugin-versionlock' not in list_pkgs(): + raise SaltInvocationError( + 'Packages cannot be unheld, yum-plugin-versionlock is not installed.' + ) if not name and not pkgs and not sources: - return 'Error: name, pkgs or sources needs to be specified.' + raise SaltInvocationError( + 'One of name, pkgs, or sources must be specified.' + ) + if pkgs and sources: + raise SaltInvocationError( + 'Only one of pkgs or sources can be specified.' + ) - if name and not pkgs: - pkgs = [] - pkgs.append(name) - elif name and sources: - pkgs = [] + targets = [] + if pkgs: + targets.extend(pkgs) + elif sources: for source in sources: - pkgs += source.keys() - - current_pkgs = list_pkgs() - if 'yum-plugin-versionlock' not in current_pkgs: - ret = {} - ret['result'] = False - ret['comment'] = 'Error: Package yum-plugin-versionlock needs to be installed.' - return ret + targets.append(next(iter(source))) + else: + targets.append(name) current_locks = get_locked_packages(full=True) ret = {} - for pkg in pkgs: - if isinstance(pkg, dict): - pkg = pkg.keys()[0] + for target in targets: + if isinstance(target, dict): + target = next(iter(target)) - ret[pkg] = {'name': pkg, 'changes': {}, 'result': False, 'comment': ''} + ret[target] = {'name': target, + 'changes': {}, + 'result': False, + 'comment': ''} - search_locks = [lock for lock in current_locks if lock.startswith(pkg)] + search_locks = [lock for lock in current_locks + if lock.startswith(target)] if search_locks: if 'test' in kwargs and kwargs['test']: - ret[pkg].update(result=None) - ret[pkg]['comment'] = 'Package {0} is set to be unheld.'.format(pkg) + ret[target].update(result=None) + ret[target]['comment'] = ('Package {0} is set to be unheld.' + .format(target)) else: - _pkgs = ' '.join('"0:' + item + '"' for item in search_locks) - cmd = 'yum -q versionlock delete {0}'.format(_pkgs) + _targets = ' '.join('"0:' + item + '"' for item in search_locks) + cmd = 'yum -q versionlock delete {0}'.format(_targets) out = __salt__['cmd.run_all'](cmd) if out['retcode'] == 0: - ret[pkg].update(result=True) - ret[pkg]['comment'] = 'Package {0} is no longer held.'.format(pkg) - ret[pkg]['changes']['new'] = '' - ret[pkg]['changes']['old'] = 'hold' + ret[target].update(result=True) + ret[target]['comment'] = ('Package {0} is no longer held.' + .format(target)) + ret[target]['changes']['new'] = '' + ret[target]['changes']['old'] = 'hold' else: - ret[pkg]['comment'] = 'Package {0} was unable to be unheld.'.format(pkg) + ret[target]['comment'] = ('Package {0} was unable to be ' + 'unheld.'.format(target)) else: - ret[pkg].update(result=True) - ret[pkg]['comment'] = 'Package {0} is not being held.'.format(pkg) + ret[target].update(result=True) + ret[target]['comment'] = ('Package {0} is not being held.' + .format(target)) return ret diff --git a/salt/states/pkg.py b/salt/states/pkg.py index bf8f38d28c..e4628985c3 100644 --- a/salt/states/pkg.py +++ b/salt/states/pkg.py @@ -44,7 +44,9 @@ from salt.output import nested from salt.utils import namespaced_function as _namespaced_function from salt.utils.odict import OrderedDict from salt._compat import string_types -from salt.exceptions import CommandExecutionError, MinionError +from salt.exceptions import ( + CommandExecutionError, MinionError, SaltInvocationError +) from salt.modules.pkg_resource import _repack_pkgs _repack_pkgs = _namespaced_function(_repack_pkgs, globals()) @@ -184,7 +186,7 @@ def _find_install_targets(name=None, 'changes': {}, 'result': True, 'comment': 'Version {0} of package {1!r} is already ' - 'installed'.format(version, name)} + 'installed.'.format(version, name)} # if cver is not an empty string, the package is already installed elif cver and version is None and not pkg_verify: @@ -193,7 +195,7 @@ def _find_install_targets(name=None, 'changes': {}, 'result': True, 'comment': 'Package {0} is already ' - 'installed'.format(name)} + 'installed.'.format(name)} version_spec = False # Find out which packages will be targeted in the call to pkg.install @@ -655,28 +657,42 @@ def installed( # check that the hold function is available if 'pkg.hold' in __salt__: if 'hold' in kwargs: - if kwargs['hold']: - hold_ret = __salt__['pkg.hold'](name=name, pkgs=pkgs, sources=sources) - else: - hold_ret = __salt__['pkg.unhold'](name=name, pkgs=pkgs, sources=sources) + try: + if kwargs['hold']: + hold_ret = __salt__['pkg.hold']( + name=name, pkgs=pkgs, sources=sources + ) + else: + hold_ret = __salt__['pkg.unhold']( + name=name, pkgs=pkgs, sources=sources + ) + except (CommandExecutionError, SaltInvocationError) as exc: + return {'name': name, + 'changes': {}, + 'result': False, + 'comment': exc.message} if 'result' in hold_ret and not hold_ret['result']: return {'name': name, 'changes': {}, 'result': False, - 'comment': 'An error was encountered while holding/unholding ' - 'package(s): {0}'.format(hold_ret['comment'])} + 'comment': 'An error was encountered while ' + 'holding/unholding package(s): {0}' + .format(hold_ret['comment'])} else: - modified_hold = [hold_ret[x] for x in hold_ret.keys() if hold_ret[x]['changes']] - not_modified_hold = [hold_ret[x] for x in hold_ret.keys() if not hold_ret[x]['changes'] and hold_ret[x]['result']] - failed_hold = [hold_ret[x] for x in hold_ret.keys() if not hold_ret[x]['result']] + modified_hold = [hold_ret[x] for x in hold_ret + if hold_ret[x]['changes']] + not_modified_hold = [hold_ret[x] for x in hold_ret + if not hold_ret[x]['changes'] + and hold_ret[x]['result']] + failed_hold = [hold_ret[x] for x in hold_ret + if not hold_ret[x]['result']] if modified_hold: for i in modified_hold: result['comment'] += ' {0}'.format(i['comment']) result['result'] = i['result'] - change_name = i['name'] - result['changes'][change_name] = i['changes'] + result['changes'][i['name']] = i['changes'] if not_modified_hold: for i in not_modified_hold: @@ -759,31 +775,47 @@ def installed( 'changes': {}, 'result': False, 'comment': 'An error was encountered while installing ' - 'package(s): {0}'.format(exc)} - - if 'pkg.hold' in __salt__: - if 'hold' in kwargs: - if kwargs['hold']: - hold_ret = __salt__['pkg.hold'](name=name, pkgs=pkgs, sources=sources) - else: - hold_ret = __salt__['pkg.unhold'](name=name, pkgs=pkgs, sources=sources) - - if 'result' in hold_ret and not hold_ret['result']: - return {'name': name, - 'changes': {}, - 'result': False, - 'comment': 'An error was encountered while holding/unholding ' - 'package(s): {0}'.format(hold_ret['comment'])} - else: - modified_hold = [hold_ret[x] for x in hold_ret.keys() if hold_ret[x]['changes']] - not_modified_hold = [hold_ret[x] for x in hold_ret.keys() if not hold_ret[x]['changes'] and hold_ret[x]['result']] - failed_hold = [hold_ret[x] for x in hold_ret.keys() if not hold_ret[x]['result']] + 'package(s): {0}'.format(exc)} if isinstance(pkg_ret, dict): changes['installed'].update(pkg_ret) elif isinstance(pkg_ret, string_types): comment.append(pkg_ret) + if 'pkg.hold' in __salt__: + if 'hold' in kwargs: + try: + if kwargs['hold']: + hold_ret = __salt__['pkg.hold']( + name=name, pkgs=pkgs, sources=sources + ) + else: + hold_ret = __salt__['pkg.unhold']( + name=name, pkgs=pkgs, sources=sources + ) + except (CommandExecutionError, SaltInvocationError) as exc: + comment.append(exc.message) + return {'name': name, + 'changes': changes, + 'result': False, + 'comment': ' '.join(comment)} + else: + if 'result' in hold_ret and not hold_ret['result']: + return {'name': name, + 'changes': {}, + 'result': False, + 'comment': 'An error was encountered while ' + 'holding/unholding package(s): {0}' + .format(hold_ret['comment'])} + else: + modified_hold = [hold_ret[x] for x in hold_ret + if hold_ret[x]['changes']] + not_modified_hold = [hold_ret[x] for x in hold_ret + if not hold_ret[x]['changes'] + and hold_ret[x]['result']] + failed_hold = [hold_ret[x] for x in hold_ret + if not hold_ret[x]['result']] + if to_unpurge: changes['purge_desired'] = __salt__['lowpkg.unpurge'](*to_unpurge)