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