mirror of
https://github.com/valitydev/salt.git
synced 2024-11-08 01:18:58 +00:00
implement resolve_capabilities option for packages
This commit is contained in:
parent
b8db7ab7bf
commit
3d28be0938
@ -20,6 +20,7 @@ import re
|
||||
import os
|
||||
import time
|
||||
import datetime
|
||||
import copy
|
||||
|
||||
# Import 3rd-party libs
|
||||
# pylint: disable=import-error,redefined-builtin,no-name-in-module
|
||||
@ -1049,6 +1050,10 @@ def install(name=None,
|
||||
operator (<, >, <=, >=, =) and a version number (ex. '>1.2.3-4').
|
||||
This parameter is ignored if ``pkgs`` or ``sources`` is passed.
|
||||
|
||||
resolve_capabilities
|
||||
If this option is set to True zypper will take capabilites into
|
||||
account. In this case names which are just provided by a package
|
||||
will get installed. Default is False.
|
||||
|
||||
Multiple Package Installation Options:
|
||||
|
||||
@ -1164,7 +1169,13 @@ def install(name=None,
|
||||
log.info('Targeting repo \'{0}\''.format(fromrepo))
|
||||
else:
|
||||
fromrepoopt = ''
|
||||
cmd_install = ['install', '--name', '--auto-agree-with-licenses']
|
||||
cmd_install = ['install', '--auto-agree-with-licenses']
|
||||
|
||||
if kwargs.get('resolve_capabilities', False):
|
||||
cmd_install.append('--capability')
|
||||
else:
|
||||
cmd_install.append('--name')
|
||||
|
||||
if not refresh:
|
||||
cmd_install.insert(0, '--no-refresh')
|
||||
if skip_verify:
|
||||
@ -1195,6 +1206,7 @@ def install(name=None,
|
||||
__zypper__(no_repo_failure=ignore_repo_failure).call(*cmd)
|
||||
|
||||
__context__.pop('pkg.list_pkgs', None)
|
||||
__context__.pop('pkg.list_list_provides', None)
|
||||
new = list_pkgs(attr=diff_attr) if not downloadonly else list_downloaded()
|
||||
|
||||
# Handle packages which report multiple new versions
|
||||
@ -1312,6 +1324,7 @@ def upgrade(refresh=True,
|
||||
|
||||
__zypper__(systemd_scope=_systemd_scope()).noraise.call(*cmd_update)
|
||||
__context__.pop('pkg.list_pkgs', None)
|
||||
__context__.pop('pkg.list_list_provides', None)
|
||||
new = list_pkgs()
|
||||
|
||||
# Handle packages which report multiple new versions
|
||||
@ -1361,6 +1374,7 @@ def _uninstall(name=None, pkgs=None):
|
||||
targets = targets[500:]
|
||||
|
||||
__context__.pop('pkg.list_pkgs', None)
|
||||
__context__.pop('pkg.list_list_provides', None)
|
||||
ret = salt.utils.data.compare_dicts(old, list_pkgs())
|
||||
|
||||
if errors:
|
||||
@ -2109,3 +2123,85 @@ def list_installed_patches():
|
||||
salt '*' pkg.list_installed_patches
|
||||
'''
|
||||
return _get_patches(installed_only=True)
|
||||
|
||||
def list_provides(**kwargs):
|
||||
'''
|
||||
List package provides currently installed as a dict.
|
||||
{'<provided_name>': ['<package_name', 'package_name', ...]}
|
||||
'''
|
||||
if 'pkg.list_provides' in __context__:
|
||||
cached = __context__['pkg.list_provides']
|
||||
return cached
|
||||
|
||||
cmd = ['rpm', '-qa', '--queryformat', '[%{PROVIDES}_|-%{NAME}\n]']
|
||||
ret = {}
|
||||
for line in __salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False).splitlines():
|
||||
provide, realname = line.split('_|-')
|
||||
|
||||
if provide == realname:
|
||||
continue
|
||||
if provide not in ret:
|
||||
ret[provide] = list()
|
||||
ret[provide].append(realname)
|
||||
|
||||
__context__['pkg.list_list_provides'] = ret
|
||||
|
||||
return ret
|
||||
|
||||
def resolve_capabilities(pkgs, refresh, **kwargs):
|
||||
'''
|
||||
.. versionadded:: Oxygen
|
||||
|
||||
Convert name provides in ``pkgs`` into real package names if
|
||||
``resolve_capabilities`` parameter is set to True. In case of
|
||||
``resolve_capabilities`` is set to False the package list
|
||||
is returned unchanged.
|
||||
|
||||
refresh
|
||||
force a refresh if set to True.
|
||||
If set to False (default) it depends on zypper if a refresh is
|
||||
executed.
|
||||
|
||||
resolve_capabilities
|
||||
If this option is set to True the input will be checked if
|
||||
a package with this name exists. If not, this function will
|
||||
search for a package which provides this name. If one is found
|
||||
the output is exchanged with the real package name.
|
||||
In case this option is set to False (Default) the input will
|
||||
be returned unchanged.
|
||||
|
||||
CLI Examples:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' pkg.resolve_capabilities resolve_capabilities=True w3m_ssl
|
||||
'''
|
||||
if refresh:
|
||||
refresh_db()
|
||||
|
||||
ret = list()
|
||||
for pkg in pkgs:
|
||||
if isinstance(pkg, dict):
|
||||
for name, version in pkg.items():
|
||||
break
|
||||
else:
|
||||
name = pkg
|
||||
version = None
|
||||
|
||||
if kwargs.get('resolve_capabilities', False):
|
||||
try:
|
||||
search(name, match='exact')
|
||||
except CommandExecutionError as e:
|
||||
# no package this such a name found
|
||||
# search for a package which provides this name
|
||||
result = search(name, provides=True, match='exact')
|
||||
if len(result.keys()) == 1:
|
||||
name = result.keys()[0]
|
||||
elif len(result.keys()) > 1:
|
||||
log.warn("Found ambiguous match for capability '{0}'.".format(pkg))
|
||||
|
||||
if version:
|
||||
ret.append({name: version})
|
||||
else:
|
||||
ret.append(name)
|
||||
return ret
|
||||
|
@ -508,8 +508,11 @@ def _find_install_targets(name=None,
|
||||
# add it to the kwargs.
|
||||
kwargs['refresh'] = refresh
|
||||
|
||||
|
||||
resolve_capabilities = kwargs.get('resolve_capabilities', False) and 'pkg.list_provides' in __salt__
|
||||
try:
|
||||
cur_pkgs = __salt__['pkg.list_pkgs'](versions_as_list=True, **kwargs)
|
||||
cur_prov = resolve_capabilities and __salt__['pkg.list_provides'](**kwargs) or dict()
|
||||
except CommandExecutionError as exc:
|
||||
return {'name': name,
|
||||
'changes': {},
|
||||
@ -669,6 +672,9 @@ def _find_install_targets(name=None,
|
||||
failed_verify = False
|
||||
for key, val in six.iteritems(desired):
|
||||
cver = cur_pkgs.get(key, [])
|
||||
if resolve_capabilities and not cver and key in cur_prov:
|
||||
cver = cur_pkgs.get(cur_prov.get(key)[0], [])
|
||||
|
||||
# Package not yet installed, so add to targets
|
||||
if not cver:
|
||||
targets[key] = val
|
||||
@ -786,7 +792,7 @@ def _find_install_targets(name=None,
|
||||
warnings, was_refreshed)
|
||||
|
||||
|
||||
def _verify_install(desired, new_pkgs, ignore_epoch=False):
|
||||
def _verify_install(desired, new_pkgs, ignore_epoch=False, new_caps={}):
|
||||
'''
|
||||
Determine whether or not the installed packages match what was requested in
|
||||
the SLS file.
|
||||
@ -809,6 +815,8 @@ def _verify_install(desired, new_pkgs, ignore_epoch=False):
|
||||
cver = new_pkgs.get(pkgname.split('=')[0])
|
||||
else:
|
||||
cver = new_pkgs.get(pkgname)
|
||||
if not cver and pkgname in new_caps:
|
||||
cver = new_pkgs.get(new_caps.get(pkgname)[0])
|
||||
|
||||
if not cver:
|
||||
failed.append(pkgname)
|
||||
@ -872,6 +880,27 @@ def _nested_output(obj):
|
||||
ret = nested.output(obj).rstrip()
|
||||
return ret
|
||||
|
||||
def _resolve_capabilities(pkgs, refresh=False, **kwargs):
|
||||
'''
|
||||
Resolve capabilities in ``pkgs`` and exchange them with real package
|
||||
names, when the result is distinct.
|
||||
This feature can be turned on while setting the paramter
|
||||
``resolve_capabilities`` to True.
|
||||
|
||||
Return the input dictionary with replaced capability names and as
|
||||
second return value a bool which indicate if a refresh was run.
|
||||
|
||||
In case of ``resolve_capabilities`` is False (disabled) or not
|
||||
supported by the implementation the input is returned unchanged.
|
||||
'''
|
||||
was_refreshed = False
|
||||
if not pkgs or 'pkg.resolve_capabilities' not in __salt__:
|
||||
return (pkgs, was_refreshed)
|
||||
|
||||
ret = __salt__['pkg.resolve_capabilities'](pkgs, refresh=refresh, **kwargs)
|
||||
was_refreshed = refresh
|
||||
return (ret, was_refreshed)
|
||||
|
||||
|
||||
def installed(
|
||||
name,
|
||||
@ -1105,6 +1134,11 @@ def installed(
|
||||
|
||||
.. versionadded:: 2014.1.1
|
||||
|
||||
:param bool resolve_capabilities:
|
||||
Turn on resolving capabilities. This allow to name "provides" or alias names for packages.
|
||||
|
||||
.. versionadded:: Oxygen
|
||||
|
||||
:param bool allow_updates:
|
||||
Allow the package to be updated outside Salt's control (e.g. auto
|
||||
updates on Windows). This means a package on the Minion can have a
|
||||
@ -1448,6 +1482,14 @@ def installed(
|
||||
|
||||
kwargs['saltenv'] = __env__
|
||||
refresh = salt.utils.pkg.check_refresh(__opts__, refresh)
|
||||
|
||||
# check if capabilities should be checked and modify the requested packages
|
||||
# accordingly.
|
||||
if pkgs:
|
||||
(pkgs, was_refreshed) = _resolve_capabilities(pkgs, refresh=refresh, **kwargs)
|
||||
if was_refreshed:
|
||||
refresh = False
|
||||
|
||||
if not isinstance(pkg_verify, list):
|
||||
pkg_verify = pkg_verify is True
|
||||
if (pkg_verify or isinstance(pkg_verify, list)) \
|
||||
@ -1707,8 +1749,13 @@ def installed(
|
||||
if __grains__['os'] == 'FreeBSD':
|
||||
kwargs['with_origin'] = True
|
||||
new_pkgs = __salt__['pkg.list_pkgs'](versions_as_list=True, **kwargs)
|
||||
if kwargs.get('resolve_capabilities', False) and 'pkg.list_provides' in __salt__:
|
||||
new_caps = __salt__['pkg.list_provides'](**kwargs)
|
||||
else:
|
||||
new_caps = {}
|
||||
ok, failed = _verify_install(desired, new_pkgs,
|
||||
ignore_epoch=ignore_epoch)
|
||||
ignore_epoch=ignore_epoch,
|
||||
new_caps=new_caps)
|
||||
modified = [x for x in ok if x in targets]
|
||||
not_modified = [x for x in ok
|
||||
if x not in targets
|
||||
@ -1927,6 +1974,11 @@ def downloaded(name,
|
||||
- dos2unix
|
||||
- salt-minion: 2015.8.5-1.el6
|
||||
|
||||
:param bool resolve_capabilities:
|
||||
Turn on resolving capabilities. This allow to name "provides" or alias names for packages.
|
||||
|
||||
.. versionadded:: Oxygen
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: yaml
|
||||
@ -1952,11 +2004,24 @@ def downloaded(name,
|
||||
ret['comment'] = 'No packages to download provided'
|
||||
return ret
|
||||
|
||||
# If just a name (and optionally a version) is passed, just pack them into
|
||||
# the pkgs argument.
|
||||
if name and not pkgs:
|
||||
if version:
|
||||
pkgs = [{name: version}]
|
||||
version = None
|
||||
else:
|
||||
pkgs = [name]
|
||||
|
||||
# It doesn't make sense here to received 'downloadonly' as kwargs
|
||||
# as we're explicitely passing 'downloadonly=True' to execution module.
|
||||
if 'downloadonly' in kwargs:
|
||||
del kwargs['downloadonly']
|
||||
|
||||
(pkgs, was_refreshed) = _resolve_capabilities(pkgs, **kwargs)
|
||||
if was_refreshed:
|
||||
refresh = False
|
||||
|
||||
# Only downloading not yet downloaded packages
|
||||
targets = _find_download_targets(name,
|
||||
version,
|
||||
@ -2203,6 +2268,10 @@ def latest(
|
||||
This parameter is available only on Debian based distributions and
|
||||
has no effect on the rest.
|
||||
|
||||
:param bool resolve_capabilities:
|
||||
Turn on resolving capabilities. This allow to name "provides" or alias names for packages.
|
||||
|
||||
.. versionadded:: Oxygen
|
||||
|
||||
Multiple Package Installation Options:
|
||||
|
||||
@ -2300,6 +2369,12 @@ def latest(
|
||||
|
||||
kwargs['saltenv'] = __env__
|
||||
|
||||
# check if capabilities should be checked and modify the requested packages
|
||||
# accordingly.
|
||||
(desired_pkgs, was_refreshed) = _resolve_capabilities(desired_pkgs, refresh=refresh, **kwargs)
|
||||
if was_refreshed:
|
||||
refresh = False
|
||||
|
||||
try:
|
||||
avail = __salt__['pkg.latest_version'](*desired_pkgs,
|
||||
fromrepo=fromrepo,
|
||||
@ -2822,6 +2897,11 @@ def uptodate(name, refresh=False, pkgs=None, **kwargs):
|
||||
This parameter available only on Debian based distributions, and
|
||||
have no effect on the rest.
|
||||
|
||||
:param bool resolve_capabilities:
|
||||
Turn on resolving capabilities. This allow to name "provides" or alias names for packages.
|
||||
|
||||
.. versionadded:: Oxygen
|
||||
|
||||
kwargs
|
||||
Any keyword arguments to pass through to ``pkg.upgrade``.
|
||||
|
||||
@ -2841,7 +2921,11 @@ def uptodate(name, refresh=False, pkgs=None, **kwargs):
|
||||
ret['comment'] = '\'fromrepo\' argument not supported on this platform'
|
||||
return ret
|
||||
|
||||
|
||||
if isinstance(refresh, bool):
|
||||
(pkgs, was_refreshed) = _resolve_capabilities(pkgs, refresh=refresh, **kwargs)
|
||||
if was_refreshed:
|
||||
refresh = False
|
||||
try:
|
||||
packages = __salt__['pkg.list_upgrades'](refresh=refresh, **kwargs)
|
||||
if isinstance(pkgs, list):
|
||||
|
Loading…
Reference in New Issue
Block a user