mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge pull request #30529 from terminalmage/2015.5-2015.8
Merge 2015.5 into 2015.8
This commit is contained in:
commit
1da1bb9afc
3 changed files with 428 additions and 251 deletions
|
@ -4,4 +4,4 @@ salt.modules.yumpkg
|
|||
|
||||
.. automodule:: salt.modules.yumpkg
|
||||
:members:
|
||||
:exclude-members: available_version, groupinstall
|
||||
:exclude-members: available_version, groupinstall, get_locked_packages
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
Support for YUM
|
||||
Support for YUM/DNF
|
||||
|
||||
.. note::
|
||||
This module makes heavy use of the **repoquery** utility, from the
|
||||
|
@ -9,6 +9,11 @@ Support for YUM
|
|||
host is being managed using salt-ssh, then as of version 2014.7.0
|
||||
yum-utils_ will be installed automatically to satisfy this dependency.
|
||||
|
||||
DNF is fully supported as of version 2015.5.10 and 2015.8.4 (partial
|
||||
support for DNF was initially added in 2015.8.0), and DNF is used
|
||||
automatically in place of YUM in Fedora 22 and newer. For these versions,
|
||||
repoquery is available from the ``dnf-plugins-core`` package.
|
||||
|
||||
.. _yum-utils: http://yum.baseurl.org/wiki/YumUtils
|
||||
|
||||
'''
|
||||
|
@ -19,13 +24,13 @@ import copy
|
|||
import logging
|
||||
import os
|
||||
import re
|
||||
import string
|
||||
from distutils.version import LooseVersion as _LooseVersion # pylint: disable=no-name-in-module,import-error
|
||||
|
||||
# Import 3rd-party libs
|
||||
# pylint: disable=import-error,redefined-builtin
|
||||
import salt.ext.six as six
|
||||
from salt.ext.six.moves import shlex_quote as _cmd_quote
|
||||
from salt.ext.six.moves import range # pylint: disable=redefined-builtin
|
||||
|
||||
try:
|
||||
import yum
|
||||
|
@ -107,15 +112,68 @@ def _check_repoquery():
|
|||
Check for existence of repoquery and install yum-utils if it is not
|
||||
present.
|
||||
'''
|
||||
if not salt.utils.which('repoquery'):
|
||||
__salt__['cmd.run'](
|
||||
[_yum(), '-y', 'install', 'yum-utils'],
|
||||
python_shell=False,
|
||||
output_loglevel='trace'
|
||||
contextkey = 'yumpkg.has_repoquery'
|
||||
if contextkey in __context__:
|
||||
# We don't really care about the return value, we're just using this
|
||||
# context key as a marker so that we know that repoquery is available,
|
||||
# and we don't have to continue to repeat the check if this function is
|
||||
# called more than once per run. If repoquery is not available, we
|
||||
# raise an exception.
|
||||
return
|
||||
|
||||
if _yum() == 'dnf':
|
||||
# For some silly reason the core plugins and their manpages are in
|
||||
# separate packages. The dnf-plugins-core package contains the manpages
|
||||
# and depends on python-dnf-plugins-core (which contains the actual
|
||||
# plugins).
|
||||
pkgs = ['dnf-plugins-core', 'python-dnf-plugins-core']
|
||||
|
||||
def _check_plugins():
|
||||
if __salt__['cmd.retcode'](['rpm', '-q'] + pkgs,
|
||||
python_shell=False,
|
||||
ignore_retcode=True) == 0:
|
||||
__context__[contextkey] = True
|
||||
return True
|
||||
return False
|
||||
|
||||
if not _check_plugins():
|
||||
__salt__['cmd.run'](['dnf', '-y', 'install'] + pkgs,
|
||||
python_shell=False,
|
||||
output_loglevel='trace')
|
||||
# Check again now that we've installed dnf-plugins-core
|
||||
if not _check_plugins():
|
||||
raise CommandExecutionError('Unable to install dnf-plugins-core')
|
||||
else:
|
||||
if salt.utils.which('repoquery'):
|
||||
__context__[contextkey] = True
|
||||
else:
|
||||
__salt__['cmd.run'](
|
||||
['yum', '-y', 'install', 'yum-utils'],
|
||||
python_shell=False,
|
||||
output_loglevel='trace'
|
||||
)
|
||||
# Check again now that we've installed yum-utils
|
||||
if salt.utils.which('repoquery'):
|
||||
__context__[contextkey] = True
|
||||
else:
|
||||
raise CommandExecutionError('Unable to install yum-utils')
|
||||
|
||||
|
||||
def _check_versionlock():
|
||||
'''
|
||||
Ensure that the appropriate versionlock plugin is present
|
||||
'''
|
||||
if _yum() == 'dnf':
|
||||
vl_plugin = 'python-dnf-plugins-extras-versionlock'
|
||||
else:
|
||||
vl_plugin = 'yum-versionlock' \
|
||||
if __grains__.get('osmajorrelease') == '5' \
|
||||
else 'yum-plugin-versionlock'
|
||||
|
||||
if vl_plugin not in list_pkgs():
|
||||
raise SaltInvocationError(
|
||||
'Cannot proceed, {0} is not installed.'.format(vl_plugin)
|
||||
)
|
||||
# Check again now that we've installed yum-utils
|
||||
if not salt.utils.which('repoquery'):
|
||||
raise CommandExecutionError('Unable to install yum-utils')
|
||||
|
||||
|
||||
def _repoquery(repoquery_args,
|
||||
|
@ -125,15 +183,17 @@ def _repoquery(repoquery_args,
|
|||
Runs a repoquery command and returns a list of namedtuples
|
||||
'''
|
||||
_check_repoquery()
|
||||
|
||||
if _yum() == 'dnf':
|
||||
_query_format = query_format.replace('-%{VERSION}_', '-%{EPOCH}:%{VERSION}_')
|
||||
cmd = 'dnf repoquery --quiet --queryformat {0} {1}'.format(
|
||||
_cmd_quote(
|
||||
query_format.replace('-%{VERSION}_', '-%{EPOCH}:%{VERSION}_')
|
||||
),
|
||||
repoquery_args
|
||||
)
|
||||
else:
|
||||
_query_format = query_format
|
||||
|
||||
cmd = 'repoquery --plugins --queryformat {0} {1}'.format(
|
||||
_cmd_quote(_query_format), repoquery_args
|
||||
)
|
||||
cmd = 'repoquery --plugins --queryformat {0} {1}'.format(
|
||||
_cmd_quote(query_format), repoquery_args
|
||||
)
|
||||
call = __salt__['cmd.run_all'](cmd, output_loglevel='trace')
|
||||
if call['retcode'] != 0:
|
||||
comment = ''
|
||||
|
@ -145,17 +205,13 @@ def _repoquery(repoquery_args,
|
|||
comment += call['stderr']
|
||||
if 'stdout' in call:
|
||||
comment += call['stdout']
|
||||
raise CommandExecutionError(
|
||||
'{0}'.format(comment)
|
||||
)
|
||||
raise CommandExecutionError(comment)
|
||||
else:
|
||||
if _yum() == 'dnf':
|
||||
# Remove the epoch when it is zero to maintain backward compatibility
|
||||
remove_zero_epoch = call['stdout'].replace('-0:', '-')
|
||||
out = remove_zero_epoch
|
||||
return call['stdout'].replace('_|-0:', '_|-').splitlines()
|
||||
else:
|
||||
out = call['stdout']
|
||||
return out.splitlines()
|
||||
return call['stdout'].splitlines()
|
||||
|
||||
|
||||
def _get_repo_options(**kwargs):
|
||||
|
@ -173,30 +229,39 @@ def _get_repo_options(**kwargs):
|
|||
if repo and not fromrepo:
|
||||
fromrepo = repo
|
||||
|
||||
repo_arg = ''
|
||||
use_dnf_repoquery = kwargs.get('repoquery', False) and _yum() == 'dnf'
|
||||
repo_arg = []
|
||||
if fromrepo:
|
||||
log.info('Restricting to repo \'{0}\''.format(fromrepo))
|
||||
repo_arg = ('--disablerepo=\'{0}\' --enablerepo=\'{1}\''
|
||||
.format('*', fromrepo))
|
||||
if use_dnf_repoquery:
|
||||
# dnf-plugins-core renamed --repoid to --repo in version 0.1.7, but
|
||||
# still keeps it as a hidden option for backwards compatibility.
|
||||
# This is good, because --repo does not work at all (see
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=1299261 for more
|
||||
# information). Using --repoid here so this will actually work.
|
||||
repo_arg.append('--repoid=\'{0}\''.format(fromrepo))
|
||||
else:
|
||||
repo_arg.append(
|
||||
'--disablerepo=\'*\' --enablerepo=\'{0}\''.format(fromrepo)
|
||||
)
|
||||
else:
|
||||
repo_arg = ''
|
||||
if disablerepo:
|
||||
if isinstance(disablerepo, list):
|
||||
for repo_item in disablerepo:
|
||||
log.info('Disabling repo \'{0}\''.format(repo_item))
|
||||
repo_arg += '--disablerepo=\'{0}\' '.format(repo_item)
|
||||
if use_dnf_repoquery:
|
||||
log.warning(
|
||||
'ignoring disablerepo, not supported in dnf repoquery'
|
||||
)
|
||||
else:
|
||||
log.info('Disabling repo \'{0}\''.format(disablerepo))
|
||||
repo_arg += '--disablerepo=\'{0}\''.format(disablerepo)
|
||||
repo_arg.append('--disablerepo=\'{0}\''.format(disablerepo))
|
||||
if enablerepo:
|
||||
if isinstance(enablerepo, list):
|
||||
for repo_item in enablerepo:
|
||||
log.info('Enabling repo \'{0}\''.format(repo_item))
|
||||
repo_arg += '--enablerepo=\'{0}\' '.format(repo_item)
|
||||
if use_dnf_repoquery:
|
||||
log.warning(
|
||||
'ignoring enablerepo, not supported in dnf repoquery'
|
||||
)
|
||||
else:
|
||||
log.info('Enabling repo \'{0}\''.format(enablerepo))
|
||||
repo_arg += '--enablerepo=\'{0}\''.format(enablerepo)
|
||||
return repo_arg
|
||||
repo_arg.append('--enablerepo=\'{0}\''.format(enablerepo))
|
||||
return ' '.join(repo_arg)
|
||||
|
||||
|
||||
def _get_excludes_option(**kwargs):
|
||||
|
@ -204,15 +269,18 @@ def _get_excludes_option(**kwargs):
|
|||
Returns a string of '--disableexcludes' option to be used in the yum command,
|
||||
based on the kwargs.
|
||||
'''
|
||||
disable_excludes_arg = ''
|
||||
disable_excludes = kwargs.get('disableexcludes', '')
|
||||
|
||||
if disable_excludes:
|
||||
log.info('Disabling excludes for \'{0}\''.format(disable_excludes))
|
||||
disable_excludes_arg = \
|
||||
'--disableexcludes=\'{0}\''.format(disable_excludes)
|
||||
|
||||
return disable_excludes_arg
|
||||
if kwargs.get('repoquery', False) and _yum() == 'dnf':
|
||||
log.warning(
|
||||
'Ignoring disableexcludes, not supported in dnf repoquery'
|
||||
)
|
||||
return ''
|
||||
else:
|
||||
log.info('Disabling excludes for \'{0}\''.format(disable_excludes))
|
||||
return '--disableexcludes=\'{0}\''.format(disable_excludes)
|
||||
return ''
|
||||
|
||||
|
||||
def _get_branch_option(**kwargs):
|
||||
|
@ -423,24 +491,61 @@ def latest_version(*names, **kwargs):
|
|||
if refresh:
|
||||
refresh_db(**kwargs)
|
||||
|
||||
# Get updates for specified package(s)
|
||||
# Sort by version number (highest to lowest) for loop below
|
||||
updates = sorted(
|
||||
_repoquery_pkginfo(
|
||||
'{0} {1} --pkgnarrow=available {2}'
|
||||
.format(repo_arg, exclude_arg, ' '.join(names))
|
||||
),
|
||||
key=lambda pkginfo: _LooseVersion(pkginfo.version),
|
||||
reverse=True
|
||||
)
|
||||
|
||||
for name in names:
|
||||
for pkg in (x for x in updates if x.name == name):
|
||||
def _query_pkgs(name, pkgs):
|
||||
'''
|
||||
Return the newest available match from the _repoquery_pkginfo() output
|
||||
'''
|
||||
matches = []
|
||||
for pkg in (x for x in pkgs if x.name == name):
|
||||
if pkg.arch == 'noarch' or pkg.arch == namearch_map[name] \
|
||||
or salt.utils.pkg.rpm.check_32(pkg.arch):
|
||||
ret[name] = pkg.version
|
||||
# no need to check another match, if there was one
|
||||
break
|
||||
matches.append(pkg.version)
|
||||
sorted_matches = sorted(
|
||||
[_LooseVersion(x) for x in matches],
|
||||
reverse=True
|
||||
)
|
||||
try:
|
||||
return sorted_matches[0].vstring
|
||||
except IndexError:
|
||||
return None
|
||||
|
||||
if _yum() == 'dnf':
|
||||
avail_pkgs = _repoquery_pkginfo(
|
||||
'{0} --available {1}'.format(repo_arg, ' '.join(names))
|
||||
)
|
||||
# When using 'dnf repoquery --available', all available versions are
|
||||
# returned, irrespective of whether or not they are installed. This is
|
||||
# different from how yum-utils' version of repoquery works.
|
||||
all_pkgs = list_pkgs(versions_as_list=True)
|
||||
for name in names:
|
||||
# Get newest available version of package
|
||||
newest_avail = _query_pkgs(name, avail_pkgs)
|
||||
if newest_avail is None:
|
||||
# No matches, no need to check if pacakge is already installed
|
||||
continue
|
||||
# Get newest installed version of package
|
||||
try:
|
||||
cver = all_pkgs.get(name, [])[-1]
|
||||
except IndexError:
|
||||
cver = None
|
||||
if cver is None \
|
||||
or salt.utils.compare_versions(ver1=newest_avail,
|
||||
oper='>',
|
||||
ver2=cver,
|
||||
cmp_func=version_cmp):
|
||||
ret[name] = newest_avail
|
||||
else:
|
||||
avail_pkgs = _repoquery_pkginfo(
|
||||
'{0} {1} --pkgnarrow=available {2}'.format(
|
||||
repo_arg,
|
||||
exclude_arg,
|
||||
' '.join(names)
|
||||
)
|
||||
)
|
||||
for name in names:
|
||||
newest_avail = _query_pkgs(name, avail_pkgs)
|
||||
if newest_avail is not None:
|
||||
ret[name] = newest_avail
|
||||
|
||||
# Return a string if only one package name passed
|
||||
if len(names) == 1:
|
||||
|
@ -628,7 +733,11 @@ def list_repo_pkgs(*args, **kwargs):
|
|||
|
||||
ret = {}
|
||||
for repo in repos:
|
||||
repoquery_cmd = '--all --repoid="{0}" --show-duplicates'.format(repo)
|
||||
if _yum() == 'dnf':
|
||||
# As of 0.1.15, dnf repoquery does not support showing duplicates
|
||||
repoquery_cmd = '--repoid="{0}"'.format(repo)
|
||||
else:
|
||||
repoquery_cmd = '--all --repoid="{0}" --show-duplicates'.format(repo)
|
||||
for arg in args:
|
||||
repoquery_cmd += ' "{0}"'.format(arg)
|
||||
all_pkgs = _repoquery_pkginfo(repoquery_cmd)
|
||||
|
@ -653,7 +762,8 @@ def list_upgrades(refresh=True, **kwargs):
|
|||
|
||||
The ``fromrepo``, ``enablerepo``, and ``disablerepo`` arguments are
|
||||
supported, as used in pkg states, and the ``disableexcludes`` option is
|
||||
also supported.
|
||||
also supported. However, in Fedora 22 and newer all of these but
|
||||
``fromrepo`` is ignored.
|
||||
|
||||
.. versionadded:: 2014.7.0
|
||||
Support for the ``disableexcludes`` option
|
||||
|
@ -669,9 +779,14 @@ def list_upgrades(refresh=True, **kwargs):
|
|||
|
||||
if salt.utils.is_true(refresh):
|
||||
refresh_db(**kwargs)
|
||||
updates = _repoquery_pkginfo(
|
||||
'{0} {1} --all --pkgnarrow=updates'.format(repo_arg, exclude_arg)
|
||||
)
|
||||
|
||||
if _yum() == 'dnf':
|
||||
upgrades_cmd = '{0} --upgrades'.format(repo_arg)
|
||||
else:
|
||||
upgrades_cmd = '{0} {1} --all --pkgnarrow=updates'.format(
|
||||
repo_arg, exclude_arg)
|
||||
|
||||
updates = _repoquery_pkginfo(upgrades_cmd)
|
||||
return dict([(x.name, x.version) for x in updates])
|
||||
|
||||
|
||||
|
@ -715,7 +830,8 @@ def check_db(*names, **kwargs):
|
|||
|
||||
The ``fromrepo``, ``enablerepo`` and ``disablerepo`` arguments are
|
||||
supported, as used in pkg states, and the ``disableexcludes`` option is
|
||||
also supported.
|
||||
also supported. However, in Fedora 22 and newer all of these but
|
||||
``fromrepo`` is ignored.
|
||||
|
||||
.. versionadded:: 2014.7.0
|
||||
Support for the ``disableexcludes`` option
|
||||
|
@ -729,29 +845,33 @@ def check_db(*names, **kwargs):
|
|||
salt '*' pkg.check_db <package1> <package2> <package3> disableexcludes=main
|
||||
'''
|
||||
normalize = kwargs.pop('normalize') if kwargs.get('normalize') else False
|
||||
repo_arg = _get_repo_options(**kwargs)
|
||||
exclude_arg = _get_excludes_option(**kwargs)
|
||||
repoquery_base = \
|
||||
'{0} {1} --all --quiet --whatprovides'.format(repo_arg, exclude_arg)
|
||||
repo_arg = _get_repo_options(repoquery=True, **kwargs)
|
||||
exclude_arg = _get_excludes_option(repoquery=True, **kwargs)
|
||||
|
||||
if _yum() == 'dnf':
|
||||
repoquery_base = '{0} --whatprovides'.format(repo_arg)
|
||||
avail_cmd = repo_arg
|
||||
else:
|
||||
repoquery_base = '{0} {1} --all --quiet --whatprovides'.format(
|
||||
repo_arg, exclude_arg)
|
||||
avail_cmd = '{0} --pkgnarrow=all --all'.format(repo_arg)
|
||||
|
||||
if 'pkg._avail' in __context__:
|
||||
avail = __context__['pkg._avail']
|
||||
else:
|
||||
# get list of available packages
|
||||
avail = []
|
||||
lines = _repoquery(
|
||||
'{0} --pkgnarrow=all --all'.format(repo_arg),
|
||||
query_format='%{NAME}_|-%{ARCH}'
|
||||
)
|
||||
avail = set()
|
||||
lines = _repoquery(avail_cmd, query_format='%{NAME}_|-%{ARCH}')
|
||||
for line in lines:
|
||||
try:
|
||||
name, arch = line.split('_|-')
|
||||
except ValueError:
|
||||
continue
|
||||
if normalize:
|
||||
avail.append(normalize_name('.'.join((name, arch))))
|
||||
avail.add(normalize_name('.'.join((name, arch))))
|
||||
else:
|
||||
avail.append('.'.join((name, arch)))
|
||||
avail.add('.'.join((name, arch)))
|
||||
avail = sorted(avail)
|
||||
__context__['pkg._avail'] = avail
|
||||
|
||||
ret = {}
|
||||
|
@ -816,13 +936,16 @@ def refresh_db(**kwargs):
|
|||
repo_arg = _get_repo_options(**kwargs)
|
||||
exclude_arg = _get_excludes_option(**kwargs)
|
||||
branch_arg = _get_branch_option(**kwargs)
|
||||
yum_cmd = _yum()
|
||||
|
||||
clean_cmd = 'yum -q clean expire-cache {repo} {exclude} {branch}'.format(
|
||||
clean_cmd = '{yum} -q clean expire-cache {repo} {exclude} {branch}'.format(
|
||||
yum=yum_cmd,
|
||||
repo=repo_arg,
|
||||
exclude=exclude_arg,
|
||||
branch=branch_arg
|
||||
)
|
||||
update_cmd = 'yum -q check-update {repo} {exclude} {branch}'.format(
|
||||
update_cmd = '{yum} -q check-update {repo} {exclude} {branch}'.format(
|
||||
yum=yum_cmd,
|
||||
repo=repo_arg,
|
||||
exclude=exclude_arg,
|
||||
branch=branch_arg
|
||||
|
@ -1076,9 +1199,10 @@ def install(name=None,
|
|||
else:
|
||||
downgrade.append(pkgstr)
|
||||
|
||||
yum_cmd = _yum()
|
||||
if targets:
|
||||
cmd = '{yum_command} -y {repo} {exclude} {branch} {gpgcheck} install {pkg}'.format(
|
||||
yum_command=_yum(),
|
||||
cmd = '{yum} -y {repo} {exclude} {branch} {gpgcheck} install {pkg}'.format(
|
||||
yum=yum_cmd,
|
||||
repo=repo_arg,
|
||||
exclude=exclude_arg,
|
||||
branch=branch_arg,
|
||||
|
@ -1088,8 +1212,8 @@ def install(name=None,
|
|||
__salt__['cmd.run'](cmd, output_loglevel='trace')
|
||||
|
||||
if downgrade:
|
||||
cmd = '{yum_command} -y {repo} {exclude} {branch} {gpgcheck} downgrade {pkg}'.format(
|
||||
yum_command=_yum(),
|
||||
cmd = '{yum} -y {repo} {exclude} {branch} {gpgcheck} downgrade {pkg}'.format(
|
||||
yum=yum_cmd,
|
||||
repo=repo_arg,
|
||||
exclude=exclude_arg,
|
||||
branch=branch_arg,
|
||||
|
@ -1099,8 +1223,8 @@ def install(name=None,
|
|||
__salt__['cmd.run'](cmd, output_loglevel='trace')
|
||||
|
||||
if to_reinstall:
|
||||
cmd = '{yum_command} -y {repo} {exclude} {branch} {gpgcheck} reinstall {pkg}'.format(
|
||||
yum_command=_yum(),
|
||||
cmd = '{yum} -y {repo} {exclude} {branch} {gpgcheck} reinstall {pkg}'.format(
|
||||
yum=yum_cmd,
|
||||
repo=repo_arg,
|
||||
exclude=exclude_arg,
|
||||
branch=branch_arg,
|
||||
|
@ -1168,8 +1292,8 @@ def upgrade(refresh=True, skip_verify=False, **kwargs):
|
|||
refresh_db(**kwargs)
|
||||
|
||||
old = list_pkgs()
|
||||
cmd = '{yum_command} -q -y {repo} {exclude} {branch} {gpgcheck} upgrade'.format(
|
||||
yum_command=_yum(),
|
||||
cmd = '{yum} -q -y {repo} {exclude} {branch} {gpgcheck} upgrade'.format(
|
||||
yum=_yum(),
|
||||
repo=repo_arg,
|
||||
exclude=exclude_arg,
|
||||
branch=branch_arg,
|
||||
|
@ -1186,10 +1310,10 @@ def upgrade(refresh=True, skip_verify=False, **kwargs):
|
|||
|
||||
def remove(name=None, pkgs=None, **kwargs): # pylint: disable=W0613
|
||||
'''
|
||||
Remove packages with ``yum -q -y remove``.
|
||||
Remove packages
|
||||
|
||||
name
|
||||
The name of the package to be deleted.
|
||||
The name of the package to be removed
|
||||
|
||||
|
||||
Multiple Package Options:
|
||||
|
@ -1221,9 +1345,7 @@ def remove(name=None, pkgs=None, **kwargs): # pylint: disable=W0613
|
|||
if not targets:
|
||||
return {}
|
||||
quoted_targets = [_cmd_quote(target) for target in targets]
|
||||
cmd = '{yum_command} -q -y remove {0}'.format(
|
||||
' '.join(quoted_targets),
|
||||
yum_command=_yum())
|
||||
cmd = _yum() + ' -y remove {0}'.format(' '.join(quoted_targets))
|
||||
__salt__['cmd.run'](cmd, output_loglevel='trace')
|
||||
__context__.pop('pkg.list_pkgs', None)
|
||||
new = list_pkgs()
|
||||
|
@ -1239,7 +1361,7 @@ def purge(name=None, pkgs=None, **kwargs): # pylint: disable=W0613
|
|||
:mod:`pkg.remove <salt.modules.yumpkg.remove>`.
|
||||
|
||||
name
|
||||
The name of the package to be deleted.
|
||||
The name of the package to be purged
|
||||
|
||||
|
||||
Multiple Package Options:
|
||||
|
@ -1268,7 +1390,15 @@ def hold(name=None, pkgs=None, sources=None, **kwargs): # pylint: disable=W0613
|
|||
'''
|
||||
.. versionadded:: 2014.7.0
|
||||
|
||||
Hold packages with ``yum -q versionlock``.
|
||||
Version-lock packages
|
||||
|
||||
.. note::
|
||||
Requires the appropriate ``versionlock`` plugin package to be installed:
|
||||
|
||||
- On RHEL 5: ``yum-versionlock``
|
||||
- On RHEL 6 & 7: ``yum-plugin-versionlock``
|
||||
- On Fedora: ``python-dnf-plugins-extras-versionlock``
|
||||
|
||||
|
||||
name
|
||||
The name of the package to be held.
|
||||
|
@ -1288,13 +1418,8 @@ def hold(name=None, pkgs=None, sources=None, **kwargs): # pylint: disable=W0613
|
|||
salt '*' pkg.hold <package name>
|
||||
salt '*' pkg.hold pkgs='["foo", "bar"]'
|
||||
'''
|
||||
_check_versionlock()
|
||||
|
||||
on_redhat_5 = __grains__.get('osmajorrelease', None) == '5'
|
||||
lock_pkg = 'yum-versionlock' if on_redhat_5 else 'yum-plugin-versionlock'
|
||||
if lock_pkg not in list_pkgs():
|
||||
raise SaltInvocationError(
|
||||
'Packages cannot be held, {0} is not installed.'.format(lock_pkg)
|
||||
)
|
||||
if not name and not pkgs and not sources:
|
||||
raise SaltInvocationError(
|
||||
'One of name, pkgs, or sources must be specified.'
|
||||
|
@ -1324,7 +1449,7 @@ def hold(name=None, pkgs=None, sources=None, **kwargs): # pylint: disable=W0613
|
|||
)
|
||||
targets.append(name)
|
||||
|
||||
current_locks = get_locked_packages(full=False)
|
||||
current_locks = list_holds(full=False)
|
||||
ret = {}
|
||||
for target in targets:
|
||||
if isinstance(target, dict):
|
||||
|
@ -1341,9 +1466,7 @@ def hold(name=None, pkgs=None, sources=None, **kwargs): # pylint: disable=W0613
|
|||
ret[target]['comment'] = ('Package {0} is set to be held.'
|
||||
.format(target))
|
||||
else:
|
||||
cmd = '{yum_command} -q versionlock {0}'.format(
|
||||
target,
|
||||
yum_command=_yum())
|
||||
cmd = _yum() + ' versionlock {0}'.format(target)
|
||||
out = __salt__['cmd.run_all'](cmd)
|
||||
|
||||
if out['retcode'] == 0:
|
||||
|
@ -1366,10 +1489,18 @@ def unhold(name=None, pkgs=None, sources=None, **kwargs): # pylint: disable=W06
|
|||
'''
|
||||
.. versionadded:: 2014.7.0
|
||||
|
||||
Hold packages with ``yum -q versionlock``.
|
||||
Remove version locks
|
||||
|
||||
.. note::
|
||||
Requires the appropriate ``versionlock`` plugin package to be installed:
|
||||
|
||||
- On RHEL 5: ``yum-versionlock``
|
||||
- On RHEL 6 & 7: ``yum-plugin-versionlock``
|
||||
- On Fedora: ``python-dnf-plugins-extras-versionlock``
|
||||
|
||||
|
||||
name
|
||||
The name of the package to be deleted.
|
||||
The name of the package to be unheld
|
||||
|
||||
Multiple Package Options:
|
||||
|
||||
|
@ -1386,13 +1517,8 @@ def unhold(name=None, pkgs=None, sources=None, **kwargs): # pylint: disable=W06
|
|||
salt '*' pkg.unhold <package name>
|
||||
salt '*' pkg.unhold pkgs='["foo", "bar"]'
|
||||
'''
|
||||
_check_versionlock()
|
||||
|
||||
on_redhat_5 = __grains__.get('osmajorrelease', None) == '5'
|
||||
lock_pkg = 'yum-versionlock' if on_redhat_5 else 'yum-plugin-versionlock'
|
||||
if lock_pkg not in list_pkgs():
|
||||
raise SaltInvocationError(
|
||||
'Packages cannot be unheld, {0} is not installed.'.format(lock_pkg)
|
||||
)
|
||||
if not name and not pkgs and not sources:
|
||||
raise SaltInvocationError(
|
||||
'One of name, pkgs, or sources must be specified.'
|
||||
|
@ -1412,7 +1538,7 @@ def unhold(name=None, pkgs=None, sources=None, **kwargs): # pylint: disable=W06
|
|||
else:
|
||||
targets.append(name)
|
||||
|
||||
current_locks = get_locked_packages(full=True)
|
||||
current_locks = list_holds(full=False)
|
||||
ret = {}
|
||||
for target in targets:
|
||||
if isinstance(target, dict):
|
||||
|
@ -1432,10 +1558,9 @@ def unhold(name=None, pkgs=None, sources=None, **kwargs): # pylint: disable=W06
|
|||
.format(target))
|
||||
else:
|
||||
quoted_targets = [_cmd_quote(item) for item in search_locks]
|
||||
cmd = '{yum_command} -q versionlock delete {0}'.format(
|
||||
' '.join(quoted_targets),
|
||||
yum_command=_yum()
|
||||
)
|
||||
cmd = _yum() + ' versionlock delete {0}'.format(
|
||||
' '.join(quoted_targets)
|
||||
)
|
||||
out = __salt__['cmd.run_all'](cmd)
|
||||
|
||||
if out['retcode'] == 0:
|
||||
|
@ -1454,45 +1579,71 @@ def unhold(name=None, pkgs=None, sources=None, **kwargs): # pylint: disable=W06
|
|||
return ret
|
||||
|
||||
|
||||
def get_locked_packages(pattern=None, full=True):
|
||||
'''
|
||||
Get packages that are currently locked
|
||||
``yum -q versionlock list``.
|
||||
def list_holds(pattern=r'\w+(?:[.-][^-]+)*', full=True):
|
||||
r'''
|
||||
.. versionchanged:: Boron,2015.8.4,2015.5.10
|
||||
Function renamed from ``pkg.get_locked_pkgs`` to ``pkg.list_holds``.
|
||||
|
||||
List information on locked packages
|
||||
|
||||
.. note::
|
||||
Requires the appropriate ``versionlock`` plugin package to be installed:
|
||||
|
||||
- On RHEL 5: ``yum-versionlock``
|
||||
- On RHEL 6 & 7: ``yum-plugin-versionlock``
|
||||
- On Fedora: ``python-dnf-plugins-extras-versionlock``
|
||||
|
||||
pattern : \w+(?:[.-][^-]+)*
|
||||
Regular expression used to match the package name
|
||||
|
||||
full : True
|
||||
Show the full hold definition including version and epoch. Set to
|
||||
``False`` to return just the name of the package(s) being held.
|
||||
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' pkg.get_locked_packages
|
||||
salt '*' pkg.list_holds
|
||||
salt '*' pkg.list_holds full=False
|
||||
'''
|
||||
cmd = '{yum_command} -q versionlock list'.format(yum_command=_yum())
|
||||
ret = __salt__['cmd.run'](cmd).split('\n')
|
||||
_check_versionlock()
|
||||
|
||||
if pattern:
|
||||
if full:
|
||||
_pat = r'(\d\:{0}\-\S+)'.format(pattern)
|
||||
# yum ==> 2:vim-enhanced-7.4.629-5.el6.*
|
||||
# dnf ==> vim-enhanced-2:7.4.827-1.fc22.*
|
||||
|
||||
yum_cmd = _yum()
|
||||
if full:
|
||||
if yum_cmd == 'dnf':
|
||||
lock_re = r'({0}-\S+)'.format(pattern)
|
||||
else:
|
||||
_pat = r'\d\:({0}\-\S+)'.format(pattern)
|
||||
lock_re = r'(\d+:{0}-\S+)'.format(pattern)
|
||||
else:
|
||||
if full:
|
||||
_pat = r'(\d\:\w+(?:[\.\-][^\-]+)*-\S+)'
|
||||
if yum_cmd == 'dnf':
|
||||
lock_re = r'({0}-\S+)'.format(pattern)
|
||||
else:
|
||||
_pat = r'\d\:(\w+(?:[\.\-][^\-]+)*-\S+)'
|
||||
pat = re.compile(_pat)
|
||||
lock_re = r'\d+:({0}-\S+)'.format(pattern)
|
||||
|
||||
current_locks = []
|
||||
for item in ret:
|
||||
pat = re.compile(lock_re)
|
||||
|
||||
out = __salt__['cmd.run']([yum_cmd, 'versionlock', 'list'],
|
||||
python_shell=False)
|
||||
ret = []
|
||||
for item in out.splitlines():
|
||||
match = pat.search(item)
|
||||
if match:
|
||||
if not full:
|
||||
woarch = match.group(1).rsplit('.', 1)[0]
|
||||
worel = woarch.rsplit('-', 1)[0]
|
||||
wover = worel.rsplit('-', 1)[0]
|
||||
_match = wover
|
||||
target = wover
|
||||
else:
|
||||
_match = match.group(1)
|
||||
current_locks.append(_match)
|
||||
return current_locks
|
||||
target = match.group(1)
|
||||
ret.append(target)
|
||||
return ret
|
||||
|
||||
get_locked_packages = salt.utils.alias_function(list_holds, 'get_locked_packages')
|
||||
|
||||
|
||||
def verify(*names, **kwargs):
|
||||
|
@ -1528,48 +1679,62 @@ def group_list():
|
|||
|
||||
salt '*' pkg.group_list
|
||||
'''
|
||||
ret = {'installed': [], 'available': [], 'installed environments': [], 'available environments': [], 'available languages': {}}
|
||||
cmd = '{yum_command} grouplist'.format(yum_command=_yum())
|
||||
out = __salt__['cmd.run_stdout'](cmd, output_loglevel='trace').splitlines()
|
||||
ret = {'installed': [],
|
||||
'available': [],
|
||||
'installed environments': [],
|
||||
'available environments': [],
|
||||
'available languages': {}}
|
||||
|
||||
section_map = {
|
||||
'installed groups:': 'installed',
|
||||
'available groups:': 'available',
|
||||
'installed environment groups:': 'installed environments',
|
||||
'available environment groups:': 'available environments',
|
||||
'available language groups:': 'available languages',
|
||||
}
|
||||
|
||||
out = __salt__['cmd.run_stdout'](
|
||||
[_yum(), 'grouplist', 'hidden'],
|
||||
output_loglevel='trace',
|
||||
python_shell=False
|
||||
)
|
||||
key = None
|
||||
for idx in range(len(out)):
|
||||
if out[idx].lower() == 'installed groups:':
|
||||
key = 'installed'
|
||||
continue
|
||||
elif out[idx].lower() == 'available groups:':
|
||||
key = 'available'
|
||||
continue
|
||||
elif out[idx].lower() == 'installed environment groups:':
|
||||
key = 'installed environments'
|
||||
continue
|
||||
elif out[idx].lower() == 'available environment groups:':
|
||||
key = 'available environments'
|
||||
continue
|
||||
elif out[idx].lower() == 'available language groups:':
|
||||
key = 'available languages'
|
||||
continue
|
||||
elif out[idx].lower() == 'done':
|
||||
for line in out.splitlines():
|
||||
line_lc = line.lower()
|
||||
if line_lc == 'done':
|
||||
break
|
||||
|
||||
section_lookup = section_map.get(line_lc)
|
||||
if section_lookup is not None and section_lookup != key:
|
||||
key = section_lookup
|
||||
continue
|
||||
|
||||
# Ignore any administrative comments (plugin info, repo info, etc.)
|
||||
if key is None:
|
||||
continue
|
||||
|
||||
line = line.strip()
|
||||
if key != 'available languages':
|
||||
ret[key].append(out[idx].strip())
|
||||
ret[key].append(line)
|
||||
else:
|
||||
line = out[idx].strip()
|
||||
try:
|
||||
name, lang = re.match(r'(.+) \[(.+)\]', line).groups()
|
||||
except AttributeError:
|
||||
pass
|
||||
else:
|
||||
match = re.match(r'(.+) \[(.+)\]', line)
|
||||
if match:
|
||||
name, lang = match.groups()
|
||||
ret[key][line] = {'name': name, 'language': lang}
|
||||
return ret
|
||||
|
||||
|
||||
def group_info(name):
|
||||
def group_info(name, expand=False):
|
||||
'''
|
||||
.. versionadded:: 2014.1.0
|
||||
.. versionchanged:: Boron,2015.8.4,2015.5.10
|
||||
The return data has changed. A new key ``type`` has been added to
|
||||
distinguish environment groups from package groups. Also, keys for the
|
||||
group name and group ID have been added. The ``mandatory packages``,
|
||||
``optional packages``, and ``default packages`` keys have been renamed
|
||||
to ``mandatory``, ``optional``, and ``default`` for accuracy, as
|
||||
environment groups include other groups, and not packages. Finally,
|
||||
this function now properly identifies conditional packages.
|
||||
|
||||
Lists packages belonging to a certain group
|
||||
|
||||
|
@ -1579,44 +1744,67 @@ def group_info(name):
|
|||
|
||||
salt '*' pkg.group_info 'Perl Support'
|
||||
'''
|
||||
# Not using _repoquery_pkginfo() here because group queries are handled
|
||||
# differently, and ignore the '--queryformat' param
|
||||
ret = {
|
||||
'mandatory packages': [],
|
||||
'optional packages': [],
|
||||
'default packages': [],
|
||||
'description': ''
|
||||
}
|
||||
cmd_template = 'repoquery --plugins --group --grouppkgs={0} --list {1}'
|
||||
pkgtypes = ('mandatory', 'optional', 'default', 'conditional')
|
||||
ret = {}
|
||||
for pkgtype in pkgtypes:
|
||||
ret[pkgtype] = set()
|
||||
|
||||
cmd = cmd_template.format('all', _cmd_quote(name))
|
||||
out = __salt__['cmd.run_stdout'](cmd, output_loglevel='trace')
|
||||
all_pkgs = set(out.splitlines())
|
||||
cmd = [_yum(), '--quiet', 'groupinfo', name]
|
||||
out = __salt__['cmd.run_stdout'](
|
||||
cmd,
|
||||
output_loglevel='trace',
|
||||
python_shell=False
|
||||
)
|
||||
|
||||
if not all_pkgs:
|
||||
g_info = {}
|
||||
for line in out.splitlines():
|
||||
try:
|
||||
key, value = [x.strip() for x in line.split(':')]
|
||||
g_info[key.lower()] = value
|
||||
except ValueError:
|
||||
continue
|
||||
|
||||
if 'environment group' in g_info:
|
||||
ret['type'] = 'environment group'
|
||||
elif 'group' in g_info:
|
||||
ret['type'] = 'package group'
|
||||
|
||||
ret['group'] = g_info.get('environment group') or g_info.get('group')
|
||||
ret['id'] = g_info.get('environment-id') or g_info.get('group-id')
|
||||
if not ret['group'] and not ret['id']:
|
||||
raise CommandExecutionError('Group \'{0}\' not found'.format(name))
|
||||
|
||||
for pkgtype in ('mandatory', 'optional', 'default'):
|
||||
cmd = cmd_template.format(pkgtype, _cmd_quote(name))
|
||||
packages = set(
|
||||
__salt__['cmd.run_stdout'](
|
||||
cmd, output_loglevel='trace'
|
||||
).splitlines()
|
||||
)
|
||||
ret['{0} packages'.format(pkgtype)].extend(sorted(packages))
|
||||
all_pkgs -= packages
|
||||
ret['description'] = g_info.get('description', '')
|
||||
|
||||
# 'contitional' is not a valid --grouppkgs value. Any pkgs that show up
|
||||
# in '--grouppkgs=all' that aren't in mandatory, optional, or default are
|
||||
# considered to be conditional packages.
|
||||
ret['conditional packages'] = sorted(all_pkgs)
|
||||
|
||||
cmd = 'repoquery --plugins --group --info {0}'.format(_cmd_quote(name))
|
||||
out = __salt__['cmd.run_stdout'](
|
||||
cmd, output_loglevel='trace'
|
||||
pkgtypes_capturegroup = '(' + '|'.join(pkgtypes) + ')'
|
||||
for pkgtype in pkgtypes:
|
||||
target_found = False
|
||||
for line in out.splitlines():
|
||||
line = line.strip().lstrip(string.punctuation)
|
||||
match = re.match(
|
||||
pkgtypes_capturegroup + r' (?:groups|packages):\s*$',
|
||||
line.lower()
|
||||
)
|
||||
if out:
|
||||
ret['description'] = '\n'.join(out.splitlines()[1:]).strip()
|
||||
if match:
|
||||
if target_found:
|
||||
# We've reached a new section, break from loop
|
||||
break
|
||||
else:
|
||||
if match.group(1) == pkgtype:
|
||||
# We've reached the targeted section
|
||||
target_found = True
|
||||
continue
|
||||
if target_found:
|
||||
if expand and ret['type'] == 'environment group':
|
||||
expanded = group_info(line, expand=True)
|
||||
# Don't shadow the pkgtype variable from the outer loop
|
||||
for p_type in pkgtypes:
|
||||
ret[p_type].update(set(expanded[p_type]))
|
||||
else:
|
||||
ret[pkgtype].add(line)
|
||||
|
||||
for pkgtype in pkgtypes:
|
||||
ret[pkgtype] = sorted(ret[pkgtype])
|
||||
|
||||
return ret
|
||||
|
||||
|
@ -1624,6 +1812,10 @@ def group_info(name):
|
|||
def group_diff(name):
|
||||
'''
|
||||
.. versionadded:: 2014.1.0
|
||||
.. versionchanged:: Boron,2015.8.4,2015.5.10
|
||||
Environment groups are now supported. The key names have been renamed,
|
||||
similar to the changes made in :py:func:`pkg.group_info
|
||||
<salt.modules.yumpkg.group_info>`.
|
||||
|
||||
Lists packages belonging to a certain group, and which are installed
|
||||
|
||||
|
@ -1633,21 +1825,19 @@ def group_diff(name):
|
|||
|
||||
salt '*' pkg.group_diff 'Perl Support'
|
||||
'''
|
||||
ret = {
|
||||
'mandatory packages': {'installed': [], 'not installed': []},
|
||||
'optional packages': {'installed': [], 'not installed': []},
|
||||
'default packages': {'installed': [], 'not installed': []},
|
||||
'conditional packages': {'installed': [], 'not installed': []},
|
||||
}
|
||||
pkgtypes = ('mandatory', 'optional', 'default', 'conditional')
|
||||
ret = {}
|
||||
for pkgtype in pkgtypes:
|
||||
ret[pkgtype] = {'installed': [], 'not installed': []}
|
||||
|
||||
pkgs = list_pkgs()
|
||||
group_pkgs = group_info(name)
|
||||
for pkgtype in ('mandatory', 'optional', 'default', 'conditional'):
|
||||
for member in group_pkgs.get('{0} packages'.format(pkgtype), []):
|
||||
key = '{0} packages'.format(pkgtype)
|
||||
group_pkgs = group_info(name, expand=True)
|
||||
for pkgtype in pkgtypes:
|
||||
for member in group_pkgs.get(pkgtype, []):
|
||||
if member in pkgs:
|
||||
ret[key]['installed'].append(member)
|
||||
ret[pkgtype]['installed'].append(member)
|
||||
else:
|
||||
ret[key]['not installed'].append(member)
|
||||
ret[pkgtype]['not installed'].append(member)
|
||||
return ret
|
||||
|
||||
|
||||
|
@ -1781,8 +1971,8 @@ def list_repos(basedir=None):
|
|||
|
||||
def get_repo(repo, basedir=None, **kwargs): # pylint: disable=W0613
|
||||
'''
|
||||
Display a repo from <basedir> (default basedir: all dirs in `reposdir` yum
|
||||
option).
|
||||
Display a repo from <basedir> (default basedir: all dirs in ``reposdir``
|
||||
yum option).
|
||||
|
||||
CLI Examples:
|
||||
|
||||
|
|
|
@ -1821,8 +1821,8 @@ def group_installed(name, skip=None, include=None, **kwargs):
|
|||
'''
|
||||
.. versionadded:: 2015.8.0
|
||||
|
||||
Ensure that an entire package group is installed. This state is only
|
||||
supported for the :mod:`yum <salt.modules.yumpkg>` package manager.
|
||||
Ensure that an entire package group is installed. This state is currently
|
||||
only supported for the :mod:`yum <salt.modules.yumpkg>` package manager.
|
||||
|
||||
skip
|
||||
Packages that would normally be installed by the package group
|
||||
|
@ -1840,7 +1840,6 @@ def group_installed(name, skip=None, include=None, **kwargs):
|
|||
installed by a ``yum groupinstall`` ("optional" packages). Note that
|
||||
this will not enforce group membership; if you include packages which
|
||||
are not members of the specified groups, they will still be installed.
|
||||
Can be passed either as a comma-separated list or a python list.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
|
@ -1849,12 +1848,15 @@ def group_installed(name, skip=None, include=None, **kwargs):
|
|||
- include:
|
||||
- haproxy
|
||||
|
||||
.. note::
|
||||
.. versionchanged:: Boron
|
||||
This option can no longer be passed as a comma-separated list, it
|
||||
must now be passed as a list (as shown in the above example).
|
||||
|
||||
.. note::
|
||||
Because this is essentially a wrapper around :py:func:`pkg.install
|
||||
<salt.modules.yumpkg.install>`, any argument which can be passed to
|
||||
pkg.install may also be included here, and it will be passed along
|
||||
wholesale.
|
||||
pkg.install may also be included here, and it will be passed on to the
|
||||
call to :py:func:`pkg.install <salt.modules.yumpkg.install>`.
|
||||
'''
|
||||
ret = {'name': name,
|
||||
'changes': {},
|
||||
|
@ -1862,47 +1864,32 @@ def group_installed(name, skip=None, include=None, **kwargs):
|
|||
'comment': ''}
|
||||
|
||||
if 'pkg.group_diff' not in __salt__:
|
||||
ret['comment'] = 'pkg.group_install not implemented for this platform'
|
||||
ret['comment'] = 'pkg.group_install not available for this platform'
|
||||
return ret
|
||||
|
||||
if skip is not None:
|
||||
if isinstance(skip, six.string_types):
|
||||
skip = skip.split(',')
|
||||
elif isinstance(skip, (float, six.integer_types)):
|
||||
skip = [str(skip)]
|
||||
if skip is None:
|
||||
skip = []
|
||||
else:
|
||||
if not isinstance(skip, list):
|
||||
ret['comment'] = 'skip must be formatted as a list'
|
||||
return ret
|
||||
for idx, item in enumerate(skip):
|
||||
if isinstance(item, (float, six.integer_types)):
|
||||
if not isinstance(item, six.string_types):
|
||||
skip[idx] = str(item)
|
||||
if not isinstance(skip[idx], six.string_types):
|
||||
ret['comment'] = 'Invalid \'skip\' item {0}'.format(skip[idx])
|
||||
return ret
|
||||
else:
|
||||
skip = []
|
||||
|
||||
if include is not None:
|
||||
if isinstance(include, six.string_types):
|
||||
include = include.split(',')
|
||||
elif isinstance(include, (float, six.integer_types)):
|
||||
include = [str(include)]
|
||||
if include is None:
|
||||
include = []
|
||||
else:
|
||||
if not isinstance(include, list):
|
||||
ret['comment'] = 'include must be formatted as a list'
|
||||
return ret
|
||||
for idx, item in enumerate(include):
|
||||
if isinstance(item, (float, six.integer_types)):
|
||||
if not isinstance(item, six.string_types):
|
||||
include[idx] = str(item)
|
||||
if not isinstance(include[idx], six.string_types):
|
||||
ret['comment'] = \
|
||||
'Invalid \'include\' item {0}'.format(include[idx])
|
||||
return ret
|
||||
else:
|
||||
include = []
|
||||
|
||||
diff = __salt__['pkg.group_diff'](name)
|
||||
mandatory = diff['mandatory packages']['installed'] + \
|
||||
diff['mandatory packages']['not installed']
|
||||
mandatory = diff['mandatory']['installed'] + \
|
||||
diff['mandatory']['not installed']
|
||||
|
||||
invalid_skip = [x for x in mandatory if x in skip]
|
||||
if invalid_skip:
|
||||
|
@ -1912,8 +1899,8 @@ def group_installed(name, skip=None, include=None, **kwargs):
|
|||
)
|
||||
return ret
|
||||
|
||||
targets = diff['mandatory packages']['not installed']
|
||||
targets.extend([x for x in diff['default packages']['not installed']
|
||||
targets = diff['mandatory']['not installed']
|
||||
targets.extend([x for x in diff['default']['not installed']
|
||||
if x not in skip])
|
||||
targets.extend(include)
|
||||
|
||||
|
@ -1922,9 +1909,9 @@ def group_installed(name, skip=None, include=None, **kwargs):
|
|||
ret['comment'] = 'Group \'{0}\' is already installed'.format(name)
|
||||
return ret
|
||||
|
||||
partially_installed = diff['mandatory packages']['installed'] \
|
||||
or diff['default packages']['installed'] \
|
||||
or diff['optional packages']['installed']
|
||||
partially_installed = diff['mandatory']['installed'] \
|
||||
or diff['default']['installed'] \
|
||||
or diff['optional']['installed']
|
||||
|
||||
if __opts__['test']:
|
||||
ret['result'] = None
|
||||
|
|
Loading…
Add table
Reference in a new issue