mirror of
https://github.com/valitydev/salt.git
synced 2024-11-08 01:18:58 +00:00
Merge pull request #2493 from s0undt3ch/develop
Fix `salt.modules.yumpkg`.
This commit is contained in:
commit
4dcf0e9308
@ -18,7 +18,11 @@ import salt.key
|
||||
|
||||
from salt.utils import parsers
|
||||
from salt.utils.verify import verify_env
|
||||
from salt.exceptions import SaltInvocationError, SaltClientError, EauthAuthenticationError
|
||||
from salt.exceptions import (
|
||||
SaltInvocationError,
|
||||
SaltClientError,
|
||||
EauthAuthenticationError
|
||||
)
|
||||
|
||||
|
||||
class SaltCMD(parsers.SaltCMDOptionParser):
|
||||
@ -33,7 +37,9 @@ class SaltCMD(parsers.SaltCMDOptionParser):
|
||||
self.parse_args()
|
||||
|
||||
try:
|
||||
local = salt.client.LocalClient(self.get_config_file_path('master'))
|
||||
local = salt.client.LocalClient(
|
||||
self.get_config_file_path('master')
|
||||
)
|
||||
except SaltClientError as exc:
|
||||
self.exit(2, '{0}\n'.format(exc))
|
||||
return
|
||||
|
@ -16,6 +16,7 @@ import re
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def __virtual__():
|
||||
'''
|
||||
Confine this module to yum based systems
|
||||
@ -40,37 +41,37 @@ def __virtual__():
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
class _YumErrorLogger(yum.rpmtrans.NoOutputCallBack):
|
||||
'''
|
||||
A YUM callback handler that logs failed packages with their associated
|
||||
script output.
|
||||
'''
|
||||
def __init__(self):
|
||||
self.messages = {}
|
||||
self.failed = []
|
||||
|
||||
def log_accumulated_errors(self):
|
||||
if has_yumdeps:
|
||||
class _YumErrorLogger(yum.rpmtrans.NoOutputCallBack):
|
||||
'''
|
||||
Convenience method for logging all messages from failed packages
|
||||
A YUM callback handler that logs failed packages with their associated
|
||||
script output.
|
||||
'''
|
||||
for pkg in self.failed:
|
||||
log.error('{0} {1}'.format(pkg, self.messages[pkg]))
|
||||
def __init__(self):
|
||||
self.messages = {}
|
||||
self.failed = []
|
||||
|
||||
def errorlog(self, msg):
|
||||
# Log any error we receive
|
||||
log.error(msg)
|
||||
def log_accumulated_errors(self):
|
||||
'''
|
||||
Convenience method for logging all messages from failed packages
|
||||
'''
|
||||
for pkg in self.failed:
|
||||
log.error('{0} {1}'.format(pkg, self.messages[pkg]))
|
||||
|
||||
def filelog(self, package, action):
|
||||
# TODO: extend this for more conclusive transaction handling for
|
||||
# installs and removes VS. the pkg list compare method used now.
|
||||
if action == yum.constants.TS_FAILED:
|
||||
self.failed.append(package)
|
||||
def errorlog(self, msg):
|
||||
# Log any error we receive
|
||||
log.error(msg)
|
||||
|
||||
def scriptout(self, package, msgs):
|
||||
# This handler covers ancillary messages coming from the RPM script.
|
||||
# Will sometimes contain more detailed error messages.
|
||||
self.messages[package] = msgs
|
||||
def filelog(self, package, action):
|
||||
# TODO: extend this for more conclusive transaction handling for
|
||||
# installs and removes VS. the pkg list compare method used now.
|
||||
if action == yum.constants.TS_FAILED:
|
||||
self.failed.append(package)
|
||||
|
||||
def scriptout(self, package, msgs):
|
||||
# This handler covers ancillary messages coming from the RPM script
|
||||
# Will sometimes contain more detailed error messages.
|
||||
self.messages[package] = msgs
|
||||
|
||||
|
||||
def _list_removed(old, new):
|
||||
@ -96,22 +97,23 @@ def _parse_pkg_meta(path):
|
||||
if result['retcode'] == 0:
|
||||
for line in result['stdout'].splitlines():
|
||||
if not name:
|
||||
m = re.match('^Name\s*:\s*(.+)\s*$',line)
|
||||
m = re.match('^Name\s*:\s*(.+)\s*$', line)
|
||||
if m:
|
||||
name = m.group(1)
|
||||
continue
|
||||
if not version:
|
||||
m = re.match('^Version\s*:\s*(.+)\s*$',line)
|
||||
m = re.match('^Version\s*:\s*(.+)\s*$', line)
|
||||
if m:
|
||||
version = m.group(1)
|
||||
continue
|
||||
if not rel:
|
||||
m = re.match('^Release\s*:\s*(.+)\s*$',line)
|
||||
m = re.match('^Release\s*:\s*(.+)\s*$', line)
|
||||
if m:
|
||||
version = m.group(1)
|
||||
continue
|
||||
if rel: version += '-{0}'.format(rel)
|
||||
return name,version
|
||||
if rel:
|
||||
version += '-{0}'.format(rel)
|
||||
return name, version
|
||||
|
||||
|
||||
def _compare_versions(old, new):
|
||||
@ -135,6 +137,7 @@ def _compare_versions(old, new):
|
||||
'new': new[npkg]}
|
||||
return pkgs
|
||||
|
||||
|
||||
def list_upgrades(*args):
|
||||
'''
|
||||
Check whether or not an upgrade is available for all packages
|
||||
@ -143,19 +146,24 @@ def list_upgrades(*args):
|
||||
|
||||
salt '*' pkg.list_upgrades
|
||||
'''
|
||||
pkgs=list_pkgs()
|
||||
pkgs = list_pkgs()
|
||||
|
||||
yb=yum.YumBase()
|
||||
versions_list={}
|
||||
yb = yum.YumBase()
|
||||
versions_list = {}
|
||||
for pkgtype in ['updates']:
|
||||
pl=yb.doPackageLists(pkgtype)
|
||||
pl = yb.doPackageLists(pkgtype)
|
||||
for pkg in pkgs:
|
||||
exactmatch, matched, unmatched = yum.packages.parsePackages(pl, [pkg])
|
||||
exactmatch, matched, unmatched = yum.packages.parsePackages(
|
||||
pl, [pkg]
|
||||
)
|
||||
for pkg in exactmatch:
|
||||
if pkg.arch == getBaseArch() or pkg.arch == 'noarch':
|
||||
versions_list[pkg['name']] = '-'.join([pkg['version'],pkg['release']])
|
||||
versions_list[pkg['name']] = '-'.join(
|
||||
[pkg['version'], pkg['release']]
|
||||
)
|
||||
return versions_list
|
||||
|
||||
|
||||
def available_version(name):
|
||||
'''
|
||||
The available version of the package in the repository
|
||||
@ -190,6 +198,7 @@ def available_version(name):
|
||||
# remove the duplicate items from the list and return the first one
|
||||
return list(set(versions_list))[0]
|
||||
|
||||
|
||||
def upgrade_available(name):
|
||||
'''
|
||||
Check whether or not an upgrade is available for a given package
|
||||
@ -200,6 +209,7 @@ def upgrade_available(name):
|
||||
'''
|
||||
return available_version(name)
|
||||
|
||||
|
||||
def version(name):
|
||||
'''
|
||||
Returns a version if the package is installed, else returns an empty string
|
||||
@ -214,6 +224,7 @@ def version(name):
|
||||
else:
|
||||
return ''
|
||||
|
||||
|
||||
def list_pkgs(*args):
|
||||
'''
|
||||
List the packages currently installed in a dict::
|
||||
@ -226,15 +237,15 @@ def list_pkgs(*args):
|
||||
'''
|
||||
ts = rpm.TransactionSet()
|
||||
pkgs = {}
|
||||
# In order to support specific package versions, we are going to use the yum
|
||||
# libraries to handle pattern matching
|
||||
# In order to support specific package versions, we are going to use the
|
||||
# yum libraries to handle pattern matching
|
||||
yb = yum.YumBase()
|
||||
setattr(yb.conf, 'assumeyes', True)
|
||||
|
||||
# if no args are passed in get all packages
|
||||
if len(args) == 0:
|
||||
for h in ts.dbMatch():
|
||||
pkgs[h['name']] = '-'.join([h['version'],h['release']])
|
||||
pkgs[h['name']] = '-'.join([h['version'], h['release']])
|
||||
else:
|
||||
# get package version for each package in *args
|
||||
for arg in args:
|
||||
@ -242,13 +253,14 @@ def list_pkgs(*args):
|
||||
a = yb.pkgSack.returnPackages(patterns=[arg], ignore_case=False)
|
||||
# make sure there is an a
|
||||
if len(a) > 0:
|
||||
arg = a[0].name
|
||||
arg = a[0].name
|
||||
# use the name from yum to do an rpm lookup
|
||||
for h in ts.dbMatch('name', arg):
|
||||
pkgs[h['name']] = '-'.join([h['version'],h['release']])
|
||||
pkgs[h['name']] = '-'.join([h['version'], h['release']])
|
||||
|
||||
return pkgs
|
||||
|
||||
|
||||
def refresh_db():
|
||||
'''
|
||||
Since yum refreshes the database automatically, this runs a yum clean,
|
||||
@ -262,6 +274,7 @@ def refresh_db():
|
||||
yb.cleanMetadata()
|
||||
return True
|
||||
|
||||
|
||||
def clean_metadata():
|
||||
'''
|
||||
Cleans local yum metadata.
|
||||
@ -272,6 +285,7 @@ def clean_metadata():
|
||||
'''
|
||||
return refresh_db()
|
||||
|
||||
|
||||
def install(pkgs, refresh=False, repo='', skip_verify=False, sources=None,
|
||||
**kwargs):
|
||||
'''
|
||||
@ -319,9 +333,11 @@ def install(pkgs, refresh=False, repo='', skip_verify=False, sources=None,
|
||||
'({1})'.format(len(srcsplit), len(pkgs)))
|
||||
return {}
|
||||
|
||||
sources = [__salt__['cp.cache_file'](x)
|
||||
if __salt__['config.valid_fileproto'](x) else x
|
||||
for x in srcsplit]
|
||||
sources = [
|
||||
__salt__['cp.cache_file'](x)
|
||||
if __salt__['config.valid_fileproto'](x) else x
|
||||
for x in srcsplit
|
||||
]
|
||||
|
||||
# Check metadata to make sure the name passed matches the source
|
||||
for i in range(0, len(pkgs)):
|
||||
@ -332,7 +348,6 @@ def install(pkgs, refresh=False, repo='', skip_verify=False, sources=None,
|
||||
'({2})'.format(sources[i], pname, pkgs[i]))
|
||||
return {}
|
||||
|
||||
|
||||
old = list_pkgs(*pkgs)
|
||||
|
||||
yb = yum.YumBase()
|
||||
@ -340,13 +355,16 @@ def install(pkgs, refresh=False, repo='', skip_verify=False, sources=None,
|
||||
setattr(yb.conf, 'gpgcheck', not skip_verify)
|
||||
|
||||
if repo:
|
||||
log.info("Enabling repo '{0}'".format(repo))
|
||||
log.info('Enabling repo \'{0}\''.format(repo))
|
||||
yb.repos.enableRepo(repo)
|
||||
for i in range(0,len(pkgs)):
|
||||
|
||||
for i in range(0, len(pkgs)):
|
||||
try:
|
||||
if sources is not None:
|
||||
target = sources[i]
|
||||
log.info("Selecting '{0}' for local installation".format(target))
|
||||
log.info(
|
||||
'Selecting \'{0}\' for local installation'.format(target)
|
||||
)
|
||||
a = yb.installLocal(target)
|
||||
# if yum didn't install anything, maybe its a downgrade?
|
||||
log.debug('Added {0} transactions'.format(len(a)))
|
||||
@ -355,7 +373,7 @@ def install(pkgs, refresh=False, repo='', skip_verify=False, sources=None,
|
||||
a = yb.downgradeLocal(target)
|
||||
else:
|
||||
target = pkgs[i]
|
||||
log.info("Selecting '{0}' for installation".format(target))
|
||||
log.info('Selecting \'{0}\' for installation'.format(target))
|
||||
# Changed to pattern to allow specific package versions
|
||||
a = yb.install(pattern=target)
|
||||
# if yum didn't install anything, maybe its a downgrade?
|
||||
@ -382,6 +400,7 @@ def install(pkgs, refresh=False, repo='', skip_verify=False, sources=None,
|
||||
|
||||
return _compare_versions(old, new)
|
||||
|
||||
|
||||
def upgrade():
|
||||
'''
|
||||
Run a full system upgrade, a yum upgrade
|
||||
@ -416,6 +435,7 @@ def upgrade():
|
||||
new = list_pkgs()
|
||||
return _compare_versions(old, new)
|
||||
|
||||
|
||||
def remove(pkgs):
|
||||
'''
|
||||
Removes packages with yum remove
|
||||
@ -448,6 +468,7 @@ def remove(pkgs):
|
||||
|
||||
return _list_removed(old, new)
|
||||
|
||||
|
||||
def purge(pkgs):
|
||||
'''
|
||||
Yum does not have a purge, this function calls remove
|
||||
|
@ -64,8 +64,8 @@ class Runner(RunnerClient):
|
||||
'''
|
||||
ret = super(Runner, self).get_docs()
|
||||
|
||||
for fun, doc in ret.items():
|
||||
print("{0}:\n{1}\n".format(fun, doc))
|
||||
for fun in sorted(ret):
|
||||
print("{0}:\n{1}\n".format(fun, ret[fun]))
|
||||
|
||||
def run(self):
|
||||
'''
|
||||
|
@ -728,9 +728,11 @@ class SaltCMDOptionParser(OptionParser, ConfigDirMixIn, TimeoutMixIn,
|
||||
|
||||
if self.options.doc:
|
||||
# Include the target
|
||||
self.args.insert(0, '*')
|
||||
# Include the function
|
||||
self.args.insert(1, 'sys.doc')
|
||||
if self.args[0] != '*':
|
||||
self.args.insert(0, '*')
|
||||
if len(self.args) < 2 or self.args[1] != 'sys.doc':
|
||||
# Include the function
|
||||
self.args.insert(1, 'sys.doc')
|
||||
|
||||
if self.options.list:
|
||||
self.config['tgt'] = self.args[0].split(',')
|
||||
|
@ -11,6 +11,7 @@ import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
import time
|
||||
from datetime import timedelta
|
||||
try:
|
||||
import pwd
|
||||
except ImportError:
|
||||
@ -326,6 +327,33 @@ class TestDaemon(object):
|
||||
if os.path.isdir(TMP):
|
||||
shutil.rmtree(TMP)
|
||||
|
||||
def wait_for_jid(self, targets, jid, timeout=120):
|
||||
while timeout > 0:
|
||||
running = self.__client_job_running(targets, jid)
|
||||
sys.stdout.write('\r' + ' ' * PNUM + '\r')
|
||||
if not running:
|
||||
return True
|
||||
sys.stdout.write(
|
||||
' * [Quit in {0}] Waiting for {1}'.format(
|
||||
timedelta(seconds=timeout), ', '.join(running)
|
||||
)
|
||||
)
|
||||
sys.stdout.flush()
|
||||
timeout -= 1
|
||||
time.sleep(1)
|
||||
else:
|
||||
sys.stdout.write('\n * ERROR: Failed to get information back\n')
|
||||
sys.stdout.flush()
|
||||
return False
|
||||
|
||||
def __client_job_running(self, targets, jid):
|
||||
running = self.client.cmd(
|
||||
','.join(targets), 'saltutil.running', expr_form='list'
|
||||
)
|
||||
return [
|
||||
k for (k, v) in running.iteritems() if v and v[0]['jid'] == jid
|
||||
]
|
||||
|
||||
def __wait_for_minions_connections(self, evt, targets):
|
||||
print_header(
|
||||
'Waiting at most {0} secs for local minions to connect '
|
||||
@ -362,6 +390,10 @@ class TestDaemon(object):
|
||||
timeout=9999999999999999,
|
||||
)
|
||||
|
||||
if self.wait_for_jid(targets, jid_info['jid']) is False:
|
||||
evt.set()
|
||||
return
|
||||
|
||||
while syncing:
|
||||
rdata = self.client.get_returns(jid_info['jid'], syncing, 1)
|
||||
if rdata:
|
||||
|
@ -150,6 +150,20 @@ class MatchTest(integration.ShellCase, integration.ShellCaseCommonTestsMixIn):
|
||||
data = self.run_salt('-d user.add')
|
||||
self.assertIn('user.add:', data)
|
||||
|
||||
def test_salt_documentation_arguments_not_assumed(self):
|
||||
'''
|
||||
Test to see if we're not auto-adding '*' and 'sys.doc' to the call
|
||||
'''
|
||||
data = self.run_salt('\'*\' -d')
|
||||
self.assertIn('user.add:', data)
|
||||
data = self.run_salt('\'*\' -d user.add')
|
||||
self.assertIn('user.add:', data)
|
||||
data = self.run_salt('\'*\' sys.doc -d user.add')
|
||||
self.assertIn('user.add:', data)
|
||||
data = self.run_salt('\'*\' sys.doc user.add')
|
||||
self.assertIn('user.add:', data)
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
loader = TestLoader()
|
||||
|
Loading…
Reference in New Issue
Block a user