Merge pull request #27521 from terminalmage/zh107

Remove raw string formatting in execution modules
This commit is contained in:
Mike Place 2015-10-13 10:57:08 -06:00
commit 59e93ddde6
57 changed files with 2583 additions and 2149 deletions

View File

@ -17,10 +17,6 @@ import os
import re
import logging
import json
try:
from shlex import quote as _cmd_quote # pylint: disable=E0611
except ImportError:
from pipes import quote as _cmd_quote
# Import third party libs
import yaml
@ -181,8 +177,11 @@ def _get_virtual():
__context__['pkg._get_virtual'][realpkg] = []
__context__['pkg._get_virtual'][realpkg].append(pkg.name)
elif _has_dctrl_tools():
cmd = 'grep-available -F Provides -s Package,Provides -e "^.+$"'
out = __salt__['cmd.run_stdout'](cmd, output_loglevel='trace')
cmd = ['grep-available', '-F', 'Provides', '-s',
'Package,Provides', '-e', '^.+$']
out = __salt__['cmd.run_stdout'](cmd,
output_loglevel='trace',
python_shell=False)
virtpkg_re = re.compile(r'Package: (\S+)\nProvides: ([\S, ]+)')
for realpkg, provides in virtpkg_re.findall(out):
__context__['pkg._get_virtual'][realpkg] = provides.split(', ')
@ -241,7 +240,7 @@ def latest_version(*names, **kwargs):
ret[name] = ''
pkgs = list_pkgs(versions_as_list=True)
repo = ['-o', 'APT::Default-Release={0}'.format(fromrepo)] \
if fromrepo else ''
if fromrepo else None
# Refresh before looking for the latest version available
if refresh:
@ -254,10 +253,11 @@ def latest_version(*names, **kwargs):
for name in names:
cmd = ['apt-cache', '-q', 'policy', name]
if isinstance(repo, list):
cmd = cmd + repo
out = __salt__['cmd.run_all'](cmd, python_shell=False,
output_loglevel='trace')
if repo is not None:
cmd.extend(repo)
out = __salt__['cmd.run_all'](cmd,
output_loglevel='trace',
python_shell=False)
candidate = ''
for line in out['stdout'].splitlines():
if 'Candidate' in line:
@ -335,8 +335,10 @@ def refresh_db():
salt '*' pkg.refresh_db
'''
ret = {}
cmd = 'apt-get -q update'
call = __salt__['cmd.run_all'](cmd, output_loglevel='trace')
cmd = ['apt-get', '-q', 'update']
call = __salt__['cmd.run_all'](cmd,
output_loglevel='trace',
python_shell=False)
if call['retcode'] != 0:
comment = ''
if 'stderr' in call:
@ -666,7 +668,7 @@ def install(name=None,
env.update(DPKG_ENV_VARS.copy())
for cmd in cmds:
__salt__['cmd.run'](cmd, python_shell=False, output_loglevel='trace')
__salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False)
__context__.pop('pkg.list_pkgs', None)
new = list_pkgs()
@ -704,8 +706,8 @@ def _uninstall(action='remove', name=None, pkgs=None, **kwargs):
__salt__['cmd.run'](
cmd,
env=env,
output_loglevel='trace',
python_shell=False,
output_loglevel='trace'
)
__context__.pop('pkg.list_pkgs', None)
new = list_pkgs()
@ -1267,12 +1269,6 @@ def version_cmp(pkg1, pkg2):
salt '*' pkg.version_cmp '0.2.4-0ubuntu1' '0.2.4.1-0ubuntu1'
'''
# both apt_pkg.version_compare and _cmd_quote need string arguments.
pkg1 = str(pkg1)
pkg2 = str(pkg2)
# if we have apt_pkg, this will be quickier this way
# and also do not rely on shell.
if HAS_APTPKG:
try:
# the apt_pkg module needs to be manually initialized
@ -1282,23 +1278,21 @@ def version_cmp(pkg1, pkg2):
# return an int representing the difference in minor versions, or
# 1/-1 if the difference is smaller than minor versions. normalize
# to -1, 0 or 1.
try:
ret = apt_pkg.version_compare(pkg1, pkg2)
if ret > 0:
return 1
if ret < 0:
return -1
return 0
except (TypeError, ValueError):
# try to use shell version in case of errors via
# the python binding
except TypeError:
ret = apt_pkg.version_compare(str(pkg1), str(pkg2))
return 1 if ret > 0 else -1 if ret < 0 else 0
except Exception:
# Try to use shell version in case of errors w/python bindings
pass
try:
for oper, ret in (('lt', -1), ('eq', 0), ('gt', 1)):
cmd = 'dpkg --compare-versions {0} {1} ' \
'{2}'.format(_cmd_quote(pkg1), oper, _cmd_quote(pkg2))
retcode = __salt__['cmd.retcode'](
cmd, output_loglevel='trace', ignore_retcode=True
)
cmd = ['dpkg', '--compare-versions', pkg1, oper, pkg2]
retcode = __salt__['cmd.retcode'](cmd,
output_loglevel='trace',
python_shell=False,
ignore_retcode=True)
if retcode == 0:
return ret
except Exception as exc:
@ -1319,8 +1313,12 @@ def _consolidate_repo_sources(sources):
Consolidate APT sources.
'''
if not isinstance(sources, sourceslist.SourcesList):
raise TypeError('{0!r} not a {1!r}'.format(type(sources),
sourceslist.SourcesList))
raise TypeError(
'\'{0}\' not a \'{1}\''.format(
type(sources),
sourceslist.SourcesList
)
)
consolidated = {}
delete_files = set()
@ -1438,7 +1436,7 @@ def get_repo(repo, **kwargs):
uri_match.group(2))
except SyntaxError:
raise CommandExecutionError(
'Error: repo {0!r} is not a well formatted definition'
'Error: repo \'{0}\' is not a well formatted definition'
.format(repo)
)
@ -1662,15 +1660,21 @@ def mod_repo(repo, saltenv='base', **kwargs):
return {repo: repo_info}
else:
if float(__grains__['osrelease']) < 12.04:
cmd = 'apt-add-repository {0}'.format(_cmd_quote(repo))
cmd = ['apt-add-repository', repo]
else:
cmd = 'apt-add-repository -y {0}'.format(_cmd_quote(repo))
out = __salt__['cmd.run_all'](cmd, **kwargs)
cmd = ['apt-add-repository', '-y', repo]
out = __salt__['cmd.run_all'](cmd,
python_shell=False,
**kwargs)
if out['retcode']:
raise CommandExecutionError(
'Unable to add PPA {0!r}. '
'{1!r} exited with status {2!s}: '
'{3!r} '.format(repo[4:], cmd, out['retcode'], out['stderr'])
'Unable to add PPA \'{0}\'. \'{1}\' exited with '
'status {2!s}: \'{3}\' '.format(
repo[4:],
cmd,
out['retcode'],
out['stderr']
)
)
# explicit refresh when a repo is modified.
if kwargs.get('refresh_db', True):
@ -1690,7 +1694,7 @@ def mod_repo(repo, saltenv='base', **kwargs):
'Unable to get PPA info from argument. '
'Expected format "<PPA_OWNER>/<PPA_NAME>" '
'(e.g. saltstack/salt) not found. Received '
'{0!r} instead.'.format(repo[4:])
'\'{0}\' instead.'.format(repo[4:])
)
dist = __grains__['lsb_distrib_codename']
# ppa has a lot of implicit arguments. Make them explicit.
@ -1770,7 +1774,7 @@ def mod_repo(repo, saltenv='base', **kwargs):
repo_type, repo_uri, repo_dist, repo_comps = _split_repo_str(repo)
except SyntaxError:
raise SyntaxError(
'Error: repo {0!r} not a well formatted definition'.format(repo)
'Error: repo \'{0}\' not a well formatted definition'.format(repo)
)
full_comp_list = set(repo_comps)
@ -1783,15 +1787,15 @@ def mod_repo(repo, saltenv='base', **kwargs):
raise NameError(error_str)
if isinstance(keyid, int): # yaml can make this an int, we need the hex version
keyid = hex(keyid)
cmd = 'apt-key export {0}'.format(_cmd_quote(keyid))
output = __salt__['cmd.run_stdout'](cmd, **kwargs)
cmd = ['apt-key', 'export', keyid]
output = __salt__['cmd.run_stdout'](cmd, python_shell=False, **kwargs)
imported = output.startswith('-----BEGIN PGP')
if keyserver:
if not imported:
cmd = ('apt-key adv --keyserver {0} --logger-fd 1 '
'--recv-keys {1}')
ret = __salt__['cmd.run_all'](cmd.format(_cmd_quote(keyserver),
_cmd_quote(keyid)),
cmd = ['apt-key', 'adv', '--keyserver', keyserver,
'--logger-fd', '1', '--recv-keys', keyid]
ret = __salt__['cmd.run_all'](cmd,
python_shell=False,
**kwargs)
if ret['retcode'] != 0:
raise CommandExecutionError(
@ -1806,11 +1810,11 @@ def mod_repo(repo, saltenv='base', **kwargs):
raise CommandExecutionError(
'Error: file not found: {0}'.format(key_url)
)
cmd = 'apt-key add {0}'.format(_cmd_quote(fn_))
out = __salt__['cmd.run_stdout'](cmd, **kwargs)
cmd = ['apt-key', 'add', fn_]
out = __salt__['cmd.run_stdout'](cmd, python_shell=False, **kwargs)
if not out.upper().startswith('OK'):
raise CommandExecutionError(
'Error: key retrieval failed: {0}'.format(cmd.format(key_url))
'Error: failed to add key from {0}'.format(key_url)
)
if 'comps' in kwargs:
@ -2016,12 +2020,11 @@ def get_selections(pattern=None, state=None):
salt '*' pkg.get_selections 'openssh*' state=hold
'''
ret = {}
cmd = 'dpkg --get-selections'
if pattern:
cmd += ' {0!r}'.format(_cmd_quote(pattern))
else:
cmd += ' "*"'
stdout = __salt__['cmd.run_stdout'](cmd, output_loglevel='trace')
cmd = ['dpkg', '--get-selections']
cmd.append(pattern if pattern else '*')
stdout = __salt__['cmd.run_stdout'](cmd,
output_loglevel='trace',
python_shell=False)
ret = _parse_selections(stdout)
if state:
return {state: ret.get(state, [])}
@ -2207,10 +2210,11 @@ def owner(*paths):
if not paths:
return ''
ret = {}
cmd = 'dpkg -S {0!r}'
for path in paths:
output = __salt__['cmd.run_stdout'](cmd.format(_cmd_quote(path)),
output_loglevel='trace')
cmd = ['dpkg', '-S', path]
output = __salt__['cmd.run_stdout'](cmd,
output_loglevel='trace',
python_shell=False)
ret[path] = output.split(':')[0]
if 'no path found' in ret[path].lower():
ret[path] = ''

View File

@ -16,6 +16,7 @@ import datetime
# pylint: disable=import-error,redefined-builtin
from salt.ext.six.moves import map
# pylint: enable=import-error,redefined-builtin
from salt.exceptions import CommandNotFoundError
# Import salt libs
import salt.utils
@ -40,11 +41,12 @@ def _cmd(binary, *args):
'''
Wrapper to run at(1) or return None.
'''
# TODO: Use CommandNotFoundException for this
binary = salt.utils.which(binary)
if binary:
return __salt__['cmd.run_stdout']('{0} {1}'.format(binary,
' '.join(args)))
if not binary:
raise CommandNotFoundError('{0}: command not found'.format(binary))
cmd = [binary] + list(args)
return __salt__['cmd.run_stdout']([binary] + list(args),
python_shell=False)
def atq(tag=None):
@ -211,10 +213,10 @@ def at(*args, **kwargs): # pylint: disable=C0103
stdin = ' '.join(args[1:])
cmd = [binary, args[0]]
cmd_kwargs = {'stdin': stdin, 'python_shell': False}
if 'runas' in kwargs:
output = __salt__['cmd.run'](cmd, stdin=stdin, python_shell=False, runas=kwargs['runas'])
else:
output = __salt__['cmd.run'](cmd, stdin=stdin, python_shell=False)
cmd_kwargs['runas'] = kwargs['runas']
output = __salt__['cmd.run'](cmd, **cmd_kwargs)
if output is None:
return '\'at.at\' is not available.'
@ -255,7 +257,7 @@ def atc(jobid):
if output is None:
return '\'at.atc\' is not available.'
elif output == '':
return {'error': 'invalid job id {0!r}'.format(jobid)}
return {'error': 'invalid job id \'{0}\''.format(jobid)}
return output

View File

@ -10,6 +10,11 @@ try:
except ImportError:
pass
# Import salt libs
import salt.ext.six as six
import salt.utils
from salt.exceptions import SaltInvocationError
# Define the module's virtual name
__virtualname__ = 'shadow'
@ -51,30 +56,47 @@ def info(name):
'name': '',
'passwd': ''}
cmd = ""
if __salt__['cmd.has_exec']('pw'):
cmd = 'pw user show {0}'.format(name)
elif __grains__['kernel'] in ('NetBSD', 'OpenBSD'):
cmd = 'grep "^{0}:" /etc/master.passwd'.format(name)
if not isinstance(name, six.string_types):
name = str(name)
if ':' in name:
raise SaltInvocationError('Invalid username \'{0}\''.format(name))
if cmd:
cmd += '| cut -f6,7 -d:'
if __salt__['cmd.has_exec']('pw'):
change, expire = __salt__['cmd.run_stdout'](
['pw', 'user', 'show', name],
python_shell=False).split(':')[5:7]
elif __grains__['kernel'] in ('NetBSD', 'OpenBSD'):
try:
change, expire = __salt__['cmd.run_all'](cmd, python_shell=True)['stdout'].split(':')
with salt.utils.fopen('/etc/master.passwd', 'r') as fp_:
for line in fp_:
if line.startswith('{0}:'.format(name)):
change, expire = line.rstrip('\n')[5:7]
break
except IOError:
change = expire = None
else:
change = expire = None
try:
ret['change'] = int(change)
except ValueError:
pass
else:
ret['change'] = int(change)
try:
ret['expire'] = int(expire)
except ValueError:
pass
return ret
def set_change(name, change):
'''
Sets the time at which the password expires (in seconds since the EPOCH).
See man usermod on NetBSD and OpenBSD or man pw on FreeBSD.
"0" means the password never expires.
Sets the time at which the password expires (in seconds since the UNIX
epoch). See ``man 8 usermod`` on NetBSD and OpenBSD or ``man 8 pw`` on
FreeBSD.
A value of ``0`` sets the password to never expire.
CLI Example:
@ -86,10 +108,10 @@ def set_change(name, change):
if change == pre_info['change']:
return True
if __grains__['kernel'] == 'FreeBSD':
cmd = 'pw user mod {0} -f {1}'.format(name, change)
cmd = ['pw', 'user', 'mod', name, '-f', change]
else:
cmd = 'usermod -f {0} {1}'.format(change, name)
__salt__['cmd.run'](cmd)
cmd = ['usermod', '-f', change, name]
__salt__['cmd.run'](cmd, python_shell=False)
post_info = info(name)
if post_info['change'] != pre_info['change']:
return post_info['change'] == change
@ -97,9 +119,11 @@ def set_change(name, change):
def set_expire(name, expire):
'''
Sets the time at which the account expires (in seconds since the EPOCH).
See man usermod on NetBSD and OpenBSD or man pw on FreeBSD.
"0" means the account never expires.
Sets the time at which the account expires (in seconds since the UNIX
epoch). See ``man 8 usermod`` on NetBSD and OpenBSD or ``man 8 pw`` on
FreeBSD.
A value of ``0`` sets the account to never expire.
CLI Example:
@ -111,10 +135,10 @@ def set_expire(name, expire):
if expire == pre_info['expire']:
return True
if __grains__['kernel'] == 'FreeBSD':
cmd = 'pw user mod {0} -e {1}'.format(name, expire)
cmd = ['pw', 'user', 'mod', name, '-e', expire]
else:
cmd = 'usermod -e {0} {1}'.format(expire, name)
__salt__['cmd.run'](cmd)
cmd = ['usermod', '-e', expire, name]
__salt__['cmd.run'](cmd, python_shell=False)
post_info = info(name)
if post_info['expire'] != pre_info['expire']:
return post_info['expire'] == expire
@ -127,8 +151,9 @@ def set_password(name, password):
``python -c "import crypt; print crypt.crypt('password', ciphersalt)"``
:strong:`NOTE:` When constructing the ``ciphersalt`` string, you must
escape any dollar signs, to avoid them being interpolated by the shell.
.. note::
When constructing the ``ciphersalt`` string, you must escape any dollar
signs, to avoid them being interpolated by the shell.
``'password'`` is, of course, the password for which you want to generate
a hash.
@ -148,10 +173,13 @@ def set_password(name, password):
salt '*' shadow.set_password someuser '$1$UYCIxa628.9qXjpQCjM4a..'
'''
if __grains__.get('os', '') == 'FreeBSD':
cmd = 'pw user mod {0} -H 0'.format(name)
cmd = ['pw', 'user', 'mod', name, '-H', '0']
stdin = password
else:
cmd = 'usermod -p {0!r} {1}'.format(password, name)
cmd = ['usermod', '-p', password, name]
stdin = None
__salt__['cmd.run'](cmd, stdin=stdin, output_loglevel='quiet')
__salt__['cmd.run'](cmd,
stdin=stdin,
output_loglevel='quiet',
python_shell=False)
return info(name)['passwd'] == password

View File

@ -25,11 +25,11 @@ from salt.utils import vt
import salt.utils
import salt.utils.timed_subprocess
import salt.grains.extra
from salt.ext.six import string_types
import salt.ext.six as six
from salt.exceptions import CommandExecutionError, TimedProcTimeoutError
from salt.log import LOG_LEVELS
import salt.ext.six as six
from salt.ext.six.moves import range
from salt.ext.six.moves import shlex_quote as _cmd_quote
# Only available on POSIX systems, nonfatal on windows
try:
@ -156,7 +156,7 @@ def _check_loglevel(level='info', quiet=False):
'''
def _bad_level(level):
log.error(
'Invalid output_loglevel {0!r}. Valid levels are: {1}. Falling '
'Invalid output_loglevel \'{0}\'. Valid levels are: {1}. Falling '
'back to \'info\'.'
.format(
level,
@ -290,7 +290,7 @@ def _run(cmd,
env = _parse_env(env)
for bad_env_key in (x for x, y in six.iteritems(env) if y is None):
log.error('Environment variable {0!r} passed without a value. '
log.error('Environment variable \'{0}\' passed without a value. '
'Setting value to an empty string'.format(bad_env_key))
env[bad_env_key] = ''
@ -305,7 +305,7 @@ def _run(cmd,
pwd.getpwnam(runas)
except KeyError:
raise CommandExecutionError(
'User {0!r} is not available'.format(runas)
'User \'{0}\' is not available'.format(runas)
)
try:
# Getting the environment for the runas user
@ -343,7 +343,7 @@ def _run(cmd,
env[key] = val.encode(fse)
except ValueError:
raise CommandExecutionError(
'Environment could not be retrieved for User {0!r}'.format(
'Environment could not be retrieved for User \'{0}\''.format(
runas
)
)
@ -353,8 +353,11 @@ def _run(cmd,
# requested. The command output is what will be controlled by the
# 'loglevel' parameter.
msg = (
'Executing command {0!r} {1}in directory {2!r}'.format(
cmd, 'as user {0!r} '.format(runas) if runas else '', cwd
'Executing command {0}{1}{0} {2}in directory \'{3}\''.format(
'\'' if not isinstance(cmd, list) else '',
cmd,
'as user \'{0}\' '.format(runas) if runas else '',
cwd
)
)
log.info(log_callback(msg))
@ -418,7 +421,7 @@ def _run(cmd,
if not os.path.isabs(cwd) or not os.path.isdir(cwd):
raise CommandExecutionError(
'Specified cwd {0!r} either not absolute or does not exist'
'Specified cwd \'{0}\' either not absolute or does not exist'
.format(cwd)
)
@ -433,8 +436,8 @@ def _run(cmd,
proc = salt.utils.timed_subprocess.TimedProc(cmd, **kwargs)
except (OSError, IOError) as exc:
raise CommandExecutionError(
'Unable to run command {0!r} with the context {1!r}, reason: {2}'
.format(cmd, kwargs, exc)
'Unable to run command \'{0}\' with the context \'{1}\', '
'reason: {2}'.format(cmd, kwargs, exc)
)
try:
@ -832,8 +835,10 @@ def run(cmd,
if lvl < LOG_LEVELS['error']:
lvl = LOG_LEVELS['error']
msg = (
'Command {0!r} failed with return code: {1}'
.format(cmd, ret['retcode'])
'Command \'{0}\' failed with return code: {1}'.format(
cmd,
ret['retcode']
)
)
log.error(log_callback(msg))
log.log(lvl, 'output: {0}'.format(log_callback(ret['stdout'])))
@ -1194,8 +1199,10 @@ def run_stdout(cmd,
if lvl < LOG_LEVELS['error']:
lvl = LOG_LEVELS['error']
msg = (
'Command {0!r} failed with return code: {1}'
.format(cmd, ret['retcode'])
'Command \'{0}\' failed with return code: {1}'.format(
cmd,
ret['retcode']
)
)
log.error(log_callback(msg))
if ret['stdout']:
@ -1376,8 +1383,10 @@ def run_stderr(cmd,
if lvl < LOG_LEVELS['error']:
lvl = LOG_LEVELS['error']
msg = (
'Command {0!r} failed with return code: {1}'
.format(cmd, ret['retcode'])
'Command \'{0}\' failed with return code: {1}'.format(
cmd,
ret['retcode']
)
)
log.error(log_callback(msg))
if ret['stdout']:
@ -1558,8 +1567,10 @@ def run_all(cmd,
if lvl < LOG_LEVELS['error']:
lvl = LOG_LEVELS['error']
msg = (
'Command {0!r} failed with return code: {1}'
.format(cmd, ret['retcode'])
'Command \'{0}\' failed with return code: {1}'.format(
cmd,
ret['retcode']
)
)
log.error(log_callback(msg))
if ret['stdout']:
@ -1741,8 +1752,10 @@ def retcode(cmd,
if lvl < LOG_LEVELS['error']:
lvl = LOG_LEVELS['error']
msg = (
'Command {0!r} failed with return code: {1}'
.format(cmd, ret['retcode'])
'Command \'{0}\' failed with return code: {1}'.format(
cmd,
ret['retcode']
)
)
log.error(log_callback(msg))
log.log(lvl, 'output: {0}'.format(log_callback(ret['stdout'])))
@ -1938,10 +1951,14 @@ def script(source,
try:
os.remove(path)
except (IOError, OSError) as exc:
log.error('cmd.script: Unable to clean tempfile {0!r}: {1}'
.format(path, exc))
log.error(
'cmd.script: Unable to clean tempfile \'{0}\': {1}'.format(
path,
exc
)
)
if isinstance(__env__, string_types):
if isinstance(__env__, six.string_types):
salt.utils.warn_until(
'Boron',
'Passing a salt environment should be done using \'saltenv\' not '
@ -2416,7 +2433,7 @@ def run_chroot(root,
if isinstance(cmd, (list, tuple)):
cmd = ' '.join([str(i) for i in cmd])
cmd = 'chroot {0} {1} -c {2!r}'.format(root, sh_, cmd)
cmd = 'chroot {0} {1} -c {2}'.format(root, sh_, _cmd_quote(cmd))
run_func = __context__.pop('cmd.run_chroot.func', run_all)

View File

@ -7,10 +7,15 @@ from __future__ import absolute_import
# Import python libs
import logging
import os.path
import shlex
# Import salt libs
import salt.utils
from salt.exceptions import CommandExecutionError, CommandNotFoundError, SaltInvocationError
from salt.exceptions import (
CommandExecutionError,
CommandNotFoundError,
SaltInvocationError
)
log = logging.getLogger(__name__)
@ -56,7 +61,7 @@ def did_composer_install(dir):
def _run_composer(action,
dir=None,
directory=None,
composer=None,
php=None,
runas=None,
@ -79,7 +84,7 @@ def _run_composer(action,
action
The action to pass to composer ('install', 'update', 'selfupdate', etc).
dir
directory
Directory location of the composer.json file. Required except when
action='selfupdate'
@ -130,53 +135,55 @@ def _run_composer(action,
# Validate Composer is there
if not _valid_composer(composer):
raise CommandNotFoundError('\'composer.{0}\' is not available. Couldn\'t find {1!r}.'
.format(action, composer))
# Don't need a dir for the 'selfupdate' action; all other actions do need a dir
if dir is None and action != 'selfupdate':
raise SaltInvocationError('{0!r} is required for \'composer.{1}\''
.format('dir', action))
raise CommandNotFoundError(
'\'composer.{0}\' is not available. Couldn\'t find \'{1}\'.'
.format(action, composer)
)
if action is None:
raise SaltInvocationError('{0!r} is required for {1!r}'
.format('action', 'composer._run_composer'))
raise SaltInvocationError('The \'action\' argument is required')
# Don't need a dir for the 'selfupdate' action; all other actions do need a dir
if directory is None and action != 'selfupdate':
raise SaltInvocationError(
'The \'directory\' argument is required for composer.{0}'.format(action)
)
# Base Settings
cmd = '{0} {1} {2}'.format(composer, action, '--no-interaction --no-ansi')
cmd = [composer, action, '--no-interaction', '--no-ansi']
if extra_flags is not None:
cmd = '{0} {1}'.format(cmd, extra_flags)
cmd.extend(shlex.split(extra_flags))
# If php is set, prepend it
if php is not None:
cmd = php + ' ' + cmd
cmd = [php] + cmd
# Add Working Dir
if dir is not None:
cmd += ' --working-dir=' + dir
if directory is not None:
cmd.extend(['--working-dir', directory])
# Other Settings
if quiet is True:
cmd += ' --quiet'
cmd.append('--quiet')
if no_dev is True:
cmd += ' --no-dev'
cmd.append('--no-dev')
if prefer_source is True:
cmd += ' --prefer-source'
cmd.append('--prefer-source')
if prefer_dist is True:
cmd += ' --prefer-dist'
cmd.append('--prefer-dist')
if no_scripts is True:
cmd += ' --no-scripts'
cmd.append('--no-scripts')
if no_plugins is True:
cmd += ' --no-plugins'
cmd.append('--no-plugins')
if optimize is True:
cmd += ' --optimize-autoloader'
cmd.append('--optimize-autoloader')
result = __salt__['cmd.run_all'](cmd,
runas=runas,
@ -192,7 +199,7 @@ def _run_composer(action,
return result
def install(dir,
def install(directory,
composer=None,
php=None,
runas=None,
@ -211,7 +218,7 @@ def install(dir,
system PATH & making it executable, the ``composer`` and ``php`` parameters
will need to be set to the location of the executables.
dir
directory
Directory location of the composer.json file.
composer
@ -260,7 +267,7 @@ def install(dir,
no_dev=True optimize=True
'''
result = _run_composer('install',
dir=dir,
directory=directory,
composer=composer,
php=php,
runas=runas,
@ -275,7 +282,7 @@ def install(dir,
return result
def update(dir,
def update(directory,
composer=None,
php=None,
runas=None,
@ -297,7 +304,7 @@ def update(dir,
system PATH & making it executable, the ``composer`` and ``php`` parameters
will need to be set to the location of the executables.
dir
directory
Directory location of the composer.json file.
composer
@ -346,8 +353,8 @@ def update(dir,
no_dev=True optimize=True
'''
result = _run_composer('update',
directory=directory,
extra_flags='--no-progress',
dir=dir,
composer=composer,
php=php,
runas=runas,

View File

@ -365,7 +365,7 @@ def cache_file(path, saltenv='base', env=None):
result = __context__['cp.fileclient'].cache_file(path, saltenv)
if not result:
log.error(
'Unable to cache file {0!r} from saltenv {1!r}.'.format(
'Unable to cache file \'{0}\' from saltenv \'{1}\'.'.format(
path, saltenv
)
)
@ -685,7 +685,7 @@ def push(path, keep_symlinks=False, upload_path=None):
salt '*' cp.push /etc/system-release keep_symlinks=True
salt '*' cp.push /etc/fstab upload_path='/new/path/fstab'
'''
log.debug('Trying to copy {0!r} to master'.format(path))
log.debug('Trying to copy \'{0}\' to master'.format(path))
if '../' in path or not os.path.isabs(path):
log.debug('Path must be absolute, returning False')
return False

View File

@ -12,12 +12,15 @@ import os.path
# Import 3rd-party libs
from salt.ext.six.moves import urllib # pylint: disable=import-error
# Import salt libs
import salt.utils.itertools
# Don't shadow built-in's.
__func_alias__ = {
'list_': 'list'
}
PKGUTIL = "/usr/sbin/pkgutil"
__PKGUTIL = '/usr/sbin/pkgutil'
def __virtual__():
@ -36,8 +39,8 @@ def list_():
salt '*' darwin_pkgutil.list
'''
cmd = PKGUTIL + ' --pkgs'
return __salt__['cmd.run_stdout'](cmd)
cmd = [__PKGUTIL, '--pkgs']
return __salt__['cmd.run_stdout'](cmd, python_shell=False)
def is_installed(package_id):
@ -50,20 +53,15 @@ def is_installed(package_id):
salt '*' darwin_pkgutil.is_installed com.apple.pkg.gcc4.2Leo
'''
def has_package_id(lines):
for line in lines:
for line in salt.utils.itertools.split(list_(), '\n'):
if line == package_id:
return True
return False
cmd = PKGUTIL + ' --pkgs'
out = __salt__['cmd.run_stdout'](cmd)
return has_package_id(out.splitlines())
def _install_from_path(path):
if not os.path.exists(path):
msg = "Path {0!r} does not exist, cannot install".format(path)
msg = 'Path \'{0}\' does not exist, cannot install'.format(path)
raise ValueError(msg)
else:
cmd = 'installer -pkg "{0}" -target /'.format(path)
@ -78,8 +76,7 @@ def install(source, package_id=None):
.. code-block:: bash
salt '*' darwin_pkgutil.install source=/vagrant/build_essentials.pkg \
package_id=com.apple.pkg.gcc4.2Leo
salt '*' darwin_pkgutil.install source=/vagrant/build_essentials.pkg package_id=com.apple.pkg.gcc4.2Leo
'''
if package_id is not None and is_installed(package_id):
return ''
@ -88,5 +85,5 @@ def install(source, package_id=None):
if uri.scheme == "":
return _install_from_path(source)
else:
msg = "Unsupported scheme for source uri: {0!r}".format(uri.scheme)
msg = 'Unsupported scheme for source uri: \'{0}\''.format(uri.scheme)
raise ValueError(msg)

View File

@ -360,9 +360,9 @@ def __within2(value, within=None, errmsg=None, dtype=None):
typename = getattr(dtype, '__name__',
hasattr(dtype, '__class__')
and getattr(dtype.__class__, 'name', dtype))
errmsg = '{0} within {1!r}'.format(typename, within)
errmsg = '{0} within \'{1}\''.format(typename, within)
else:
errmsg = 'within {0!r}'.format(within)
errmsg = 'within \'{0}\''.format(within)
return (valid, _value, errmsg)
@ -1259,7 +1259,11 @@ def _parse_settings_eth(opts, iface_type, enabled, iface):
_optname, valuestr, addrfam=addrfam)
if not valid:
_raise_error_iface(iface, '{0!r} {1!r}'.format(opt, valuestr), [errmsg]) # TODO
_raise_error_iface(
iface,
'\'{0}\' \'{1}\''.format(opt, valuestr),
[errmsg]
)
# replace dashes with underscores for jinja
_optname = _optname.replace('-', '_')
@ -1543,14 +1547,10 @@ def build_bond(iface, **settings):
_write_file(iface, data, _DEB_NETWORK_CONF_FILES, '{0}.conf'.format(iface))
path = os.path.join(_DEB_NETWORK_CONF_FILES, '{0}.conf'.format(iface))
if deb_major == '5':
__salt__['cmd.run'](
'sed -i -e "/^alias\\s{0}.*/d" /etc/modprobe.conf'.format(iface),
python_shell=False
)
__salt__['cmd.run'](
'sed -i -e "/^options\\s{0}.*/d" /etc/modprobe.conf'.format(iface),
python_shell=False
)
for line_type in ('alias', 'options'):
cmd = ['sed', '-i', '-e', r'/^{0}\s{1}.*/d'.format(line_type, iface),
'/etc/modprobe.conf']
__salt__['cmd.run'](cmd, python_shell=False)
__salt__['file.append']('/etc/modprobe.conf', path)
# Load kernel module
@ -1606,7 +1606,10 @@ def build_interface(iface, iface_type, enabled, **settings):
elif iface_type == 'bridge':
if 'ports' not in settings:
msg = 'ports is a required setting for bridge interfaces on Debian or Ubuntu based systems'
msg = (
'ports is a required setting for bridge interfaces on Debian '
'or Ubuntu based systems'
)
log.error(msg)
raise AttributeError(msg)
__salt__['pkg.install']('bridge-utils')
@ -1648,17 +1651,27 @@ def build_routes(iface, **settings):
log.error('Could not load template route_eth.jinja')
return ''
add_routecfg = template.render(route_type='add', routes=opts['routes'], iface=iface)
add_routecfg = template.render(route_type='add',
routes=opts['routes'],
iface=iface)
del_routecfg = template.render(route_type='del', routes=opts['routes'], iface=iface)
del_routecfg = template.render(route_type='del',
routes=opts['routes'],
iface=iface)
if 'test' in settings and settings['test']:
return _read_temp(add_routecfg + del_routecfg)
filename = _write_file_routes(iface, add_routecfg, _DEB_NETWORK_UP_DIR, 'route-{0}')
filename = _write_file_routes(iface,
add_routecfg,
_DEB_NETWORK_UP_DIR,
'route-{0}')
results = _read_file(filename)
filename = _write_file_routes(iface, del_routecfg, _DEB_NETWORK_DOWN_DIR, 'route-{0}')
filename = _write_file_routes(iface,
del_routecfg,
_DEB_NETWORK_DOWN_DIR,
'route-{0}')
results += _read_file(filename)
return results
@ -1677,7 +1690,7 @@ def down(iface, iface_type):
# Slave devices are controlled by the master.
# Source 'interfaces' aren't brought down.
if iface_type not in ['slave', 'source']:
return __salt__['cmd.run']('ifdown {0}'.format(iface))
return __salt__['cmd.run'](['ifdown', iface])
return None
@ -1737,8 +1750,8 @@ def up(iface, iface_type): # pylint: disable=C0103
'''
# Slave devices are controlled by the master.
# Source 'interfaces' aren't brought up.
if iface_type not in ['slave', 'source']:
return __salt__['cmd.run']('ifup {0}'.format(iface))
if iface_type not in ('slave', 'source'):
return __salt__['cmd.run'](['ifup', iface])
return None

View File

@ -205,7 +205,7 @@ def SPF(domain, record='SPF', nameserver=None):
# In this case, 0 is not the same as False
if result['retcode'] != 0:
log.warn(
'dig returned exit code {0!r}. Returning empty list as fallback.'
'dig returned exit code \'{0}\'. Returning empty list as fallback.'
.format(result['retcode'])
)
return []

View File

@ -331,7 +331,7 @@ def _get_image_infos(image):
if not status['id']:
_invalid(status)
raise CommandExecutionError(
'ImageID {0!r} could not be resolved to '
'ImageID \'{0}\' could not be resolved to '
'an existing Image'.format(image)
)
return status['out']
@ -859,8 +859,8 @@ def kill(container, signal=None):
# no need to check if container is running
# because some signals might not stop the container.
_valid(status,
comment='Kill signal {0!r} successfully'
' sent to the container {1!r}'.format(signal, container),
comment='Kill signal \'{0}\' successfully'
' sent to the container \'{1}\''.format(signal, container),
id_=container)
else:
if not is_running(dcontainer):
@ -1858,7 +1858,7 @@ def _run_wrapper(status, container, func, cmd, *args, **kwargs):
)
else:
raise NotImplementedError(
'Unknown docker ExecutionDriver {0!r}. Or didn\'t find command'
'Unknown docker ExecutionDriver \'{0}\'. Or didn\'t find command'
' to attach to the container'.format(driver))
# now execute the command

View File

@ -154,7 +154,7 @@ def check_db(*names, **kwargs):
ret = {}
for name in names:
if name in ret:
log.warning('pkg.check_db: Duplicate package name {0!r} '
log.warning('pkg.check_db: Duplicate package name \'{0}\' '
'submitted'.format(name))
continue
if '/' not in name:
@ -587,16 +587,16 @@ def install(name=None,
if pkg_params is None or len(pkg_params) == 0:
return {}
elif pkg_type == 'file':
emerge_opts = 'tbz2file'
emerge_opts = ['tbz2file']
else:
emerge_opts = ''
emerge_opts = []
if binhost == 'try':
bin_opts = '-g'
bin_opts = ['-g']
elif binhost == 'force':
bin_opts = '-G'
bin_opts = ['-G']
else:
bin_opts = ''
bin_opts = []
changes = {}
@ -655,7 +655,10 @@ def install(name=None,
targets.append(target)
else:
targets = pkg_params
cmd = 'emerge --ask n --quiet {0} {1} {2}'.format(bin_opts, emerge_opts, ' '.join(targets))
cmd = ['emerge', '--ask', 'n', '--quiet']
cmd.extend(bin_opts)
cmd.extend(emerge_opts)
cmd.extend(targets)
old = list_pkgs()
call = __salt__['cmd.run_all'](cmd,
@ -708,14 +711,17 @@ def update(pkg, slot=None, fromrepo=None, refresh=False, binhost=None):
full_atom = '{0}::{1}'.format(full_atom, fromrepo)
if binhost == 'try':
bin_opts = '-g'
bin_opts = ['-g']
elif binhost == 'force':
bin_opts = '-G'
bin_opts = ['-G']
else:
bin_opts = ''
bin_opts = []
old = list_pkgs()
cmd = 'emerge --ask n --quiet --update --newuse --oneshot {0} {1}'.format(bin_opts, full_atom)
cmd = ['emerge', '--ask', 'n', '--quiet', '--update', '--newuse',
'--oneshot']
cmd.extend(bin_opts)
cmd.append(full_atom)
call = __salt__['cmd.run_all'](cmd,
output_loglevel='trace',
python_shell=False)
@ -755,18 +761,17 @@ def upgrade(refresh=True, binhost=None, backtrack=3):
'''
ret = {'changes': {},
'result': True,
'comment': '',
}
'comment': ''}
if salt.utils.is_true(refresh):
refresh_db()
if binhost == 'try':
bin_opts = '--getbinpkg'
bin_opts = ['--getbinpkg']
elif binhost == 'force':
bin_opts = '--getbinpkgonly'
bin_opts = ['--getbinpkgonly']
else:
bin_opts = ''
bin_opts = []
old = list_pkgs()
cmd = ['emerge',
@ -777,7 +782,7 @@ def upgrade(refresh=True, binhost=None, backtrack=3):
'--newuse',
'--deep']
if bin_opts:
cmd.append(bin_opts)
cmd.extend(bin_opts)
cmd.append('@world')
call = __salt__['cmd.run_all'](cmd,
@ -846,8 +851,8 @@ def remove(name=None, slot=None, fromrepo=None, pkgs=None, **kwargs):
if not targets:
return {}
cmd = 'emerge --ask n --quiet --unmerge --quiet-unmerge-warn ' \
'{0}'.format(' '.join(targets))
cmd = ['emerge', '--ask', 'n', '--quiet', '--unmerge',
'--quiet-unmerge-warn'] + targets
__salt__['cmd.run_all'](cmd,
output_loglevel='trace',
python_shell=False)
@ -938,7 +943,7 @@ def depclean(name=None, slot=None, fromrepo=None, pkgs=None):
else:
targets = [x for x in pkg_params if x in old]
cmd = 'emerge --ask n --quiet --depclean {0}'.format(' '.join(targets))
cmd = ['emerge', '--ask', 'n', '--quiet', '--depclean'] + targets
__salt__['cmd.run_all'](cmd,
output_loglevel='trace',
python_shell=False)

View File

@ -71,7 +71,7 @@ def setval(key, val, false_unsets=False, permanent=False):
if not isinstance(key, six.string_types):
log.debug(
'{0}: "key" argument is not a string type: {1!r}'
'{0}: \'key\' argument is not a string type: \'{1}\''
.format(__name__, key)
)
if val is False:
@ -84,7 +84,7 @@ def setval(key, val, false_unsets=False, permanent=False):
except Exception as exc:
log.error(
'{0}: Exception occurred when unsetting '
'environ key "{1!r}": {2!r}'
'environ key \'{1}\': \'{2}\''
.format(__name__, key, exc)
)
return False
@ -99,14 +99,14 @@ def setval(key, val, false_unsets=False, permanent=False):
except Exception as exc:
log.error(
'{0}: Exception occurred when setting'
'environ key "{1!r}": {2!r}'
'environ key \'{1}\': \'{2}\''
.format(__name__, key, exc)
)
return False
else:
log.debug(
'{0}: "val" argument for key "{1!r}" is not a string '
'or False: {2!r}'
'{0}: \'val\' argument for key \'{1}\' is not a string '
'or False: \'{2}\''
.format(__name__, key, val)
)
return False
@ -162,7 +162,7 @@ def setenv(environ, false_unsets=False, clear_all=False, update_minion=False, pe
ret = {}
if not isinstance(environ, dict):
log.debug(
'{0}: "environ" argument is not a dict: {1!r}'
'{0}: \'environ\' argument is not a dict: \'{1}\''
.format(__name__, environ)
)
return False
@ -178,8 +178,8 @@ def setenv(environ, false_unsets=False, clear_all=False, update_minion=False, pe
ret[key] = setval(key, val, false_unsets, permanent=permanent)
else:
log.debug(
'{0}: "val" argument for key "{1!r}" is not a string '
'or False: {2!r}'
'{0}: \'val\' argument for key \'{1}\' is not a string '
'or False: \'{2}\''
.format(__name__, key, val)
)
return False
@ -215,7 +215,7 @@ def get(key, default=''):
'''
if not isinstance(key, six.string_types):
log.debug(
'{0}: "key" argument is not a string type: {1!r}'
'{0}: \'key\' argument is not a string type: \'{1}\''
.format(__name__, key)
)
return False
@ -243,7 +243,7 @@ def has_value(key, value=None):
'''
if not isinstance(key, six.string_types):
log.debug(
'{0}: "key" argument is not a string type: {1!r}'
'{0}: \'key\' argument is not a string type: \'{1}\''
.format(__name__, key)
)
return False
@ -287,7 +287,7 @@ def item(keys, default=''):
key_list = keys
else:
log.debug(
'{0}: "keys" argument is not a string or list type: {1!r}'
'{0}: \'keys\' argument is not a string or list type: \'{1}\''
.format(__name__, keys)
)
for key in key_list:

View File

@ -22,6 +22,7 @@ import logging
import operator
import os
import re
import shlex
import shutil
import stat
import sys
@ -561,7 +562,7 @@ def check_hash(path, file_hash):
# Support "=" for backward compatibility.
hash_parts = file_hash.split('=', 1)
if len(hash_parts) != 2:
raise ValueError('Bad hash format: {0!r}'.format(file_hash))
raise ValueError('Bad hash format: \'{0}\''.format(file_hash))
hash_form, hash_value = hash_parts
return get_hash(path, hash_form) == hash_value
@ -776,19 +777,19 @@ def sed(path,
if sys.platform == 'darwin':
options = options.replace('-r', '-E')
cmd = (
r'''sed {backup}{options} '{limit}{negate_match}s/{before}/{after}/{flags}' {path}'''
.format(
backup='-i{0} '.format(backup) if backup else '-i ',
options=options,
cmd = ['sed']
cmd.append('-i{0}'.format(backup) if backup else '-i')
cmd.extend(shlex.split(options))
cmd.append(
r'{limit}{negate_match}s/{before}/{after}/{flags}'.format(
limit='/{0}/ '.format(limit) if limit else '',
negate_match='!' if negate_match else '',
before=before,
after=after,
flags=flags,
path=path,
negate_match='!' if negate_match else '',
flags=flags
)
)
cmd.append(path)
return __salt__['cmd.run_all'](cmd, python_shell=False)
@ -824,12 +825,16 @@ def sed_contains(path,
if sys.platform == 'darwin':
options = options.replace('-r', '-E')
cmd = r"sed {options} '{limit}s/{before}/$/{flags}' {path}".format(
options=options,
cmd = ['sed']
cmd.extend(shlex.split(options))
cmd.append(
r'{limit}s/{before}/$/{flags}'.format(
limit='/{0}/ '.format(limit) if limit else '',
before=before,
flags='p{0}'.format(flags),
path=path)
flags='p{0}'.format(flags)
)
)
cmd.append(path)
result = __salt__['cmd.run'](cmd, python_shell=False)
@ -2241,20 +2246,22 @@ def patch(originalfile, patchfile, options='', dry_run=False):
salt '*' file.patch /opt/file.txt /tmp/file.txt.patch
'''
if dry_run:
if __grains__['kernel'] in ('FreeBSD', 'OpenBSD'):
dry_run_opt = ' -C'
else:
dry_run_opt = ' --dry-run'
else:
dry_run_opt = ''
patchpath = salt.utils.which('patch')
if not patchpath:
raise CommandExecutionError('patch executable not found. Is the distribution\'s patch package installed?')
raise CommandExecutionError(
'patch executable not found. Is the distribution\'s patch '
'package installed?'
)
cmd = [patchpath]
cmd.extend(shlex.split(options))
if dry_run:
if __grains__['kernel'] in ('FreeBSD', 'OpenBSD'):
cmd.append('-C')
else:
cmd.append('--dry-run')
cmd.extend([originalfile, patchfile])
cmd = '{0} {1}{2} "{3}" "{4}"'.format(
patchpath, options, dry_run_opt, originalfile, patchfile)
return __salt__['cmd.run_all'](cmd, python_shell=False)
@ -2702,7 +2709,7 @@ def link(src, path):
os.link(src, path)
return True
except (OSError, IOError):
raise CommandExecutionError('Could not create {0!r}'.format(path))
raise CommandExecutionError('Could not create \'{0}\''.format(path))
return False
@ -2743,7 +2750,7 @@ def symlink(src, path):
os.symlink(src, path)
return True
except (OSError, IOError):
raise CommandExecutionError('Could not create {0!r}'.format(path))
raise CommandExecutionError('Could not create \'{0}\''.format(path))
return False
@ -2768,7 +2775,7 @@ def rename(src, dst):
return True
except OSError:
raise CommandExecutionError(
'Could not rename {0!r} to {1!r}'.format(src, dst)
'Could not rename \'{0}\' to \'{1}\''.format(src, dst)
)
return False
@ -2819,7 +2826,7 @@ def copy(src, dst, recurse=False, remove_existing=False):
shutil.copyfile(src, dst)
except OSError:
raise CommandExecutionError(
'Could not copy {0!r} to {1!r}'.format(src, dst)
'Could not copy \'{0}\' to \'{1}\''.format(src, dst)
)
if not salt.utils.is_windows():
@ -2967,7 +2974,7 @@ def statvfs(path):
'f_blocks', 'f_bsize', 'f_favail', 'f_ffree', 'f_files', 'f_flag',
'f_frsize', 'f_namemax'))
except (OSError, IOError):
raise CommandExecutionError('Could not statvfs {0!r}'.format(path))
raise CommandExecutionError('Could not statvfs \'{0}\''.format(path))
return False
@ -3079,7 +3086,7 @@ def remove(path):
return True
except (OSError, IOError) as exc:
raise CommandExecutionError(
'Could not remove {0!r}: {1}'.format(path, exc)
'Could not remove \'{0}\': {1}'.format(path, exc)
)
return False
@ -3141,9 +3148,9 @@ def restorecon(path, recursive=False):
salt '*' file.restorecon /home/user/.ssh/authorized_keys
'''
if recursive:
cmd = 'restorecon -FR {0}'.format(path)
cmd = ['restorecon', '-FR', path]
else:
cmd = 'restorecon -F {0}'.format(path)
cmd = ['restorecon', '-F', path]
return not __salt__['cmd.retcode'](cmd, python_shell=False)
@ -3157,12 +3164,14 @@ def get_selinux_context(path):
salt '*' file.get_selinux_context /etc/hosts
'''
out = __salt__['cmd.run']('ls -Z {0}'.format(path), python_shell=False)
out = __salt__['cmd.run'](['ls', '-Z', path], python_shell=False)
try:
ret = re.search(r'\w+:\w+:\w+:\w+', out).group(0)
except AttributeError:
ret = 'No selinux context information is available for {0}'.format(path)
ret = (
'No selinux context information is available for {0}'.format(path)
)
return ret
@ -3184,17 +3193,17 @@ def set_selinux_context(path,
if not any((user, role, type, range)):
return False
cmd = 'chcon '
cmd = ['chcon']
if user:
cmd += '-u {0} '.format(user)
cmd.extend(['-u', user])
if role:
cmd += '-r {0} '.format(role)
cmd.extend(['-r', role])
if type:
cmd += '-t {0} '.format(type)
cmd.extend(['-t', type])
if range:
cmd += '-l {0} '.format(range)
cmd.extend(['-l', range])
cmd.append(path)
cmd += path
ret = not __salt__['cmd.retcode'](cmd, python_shell=False)
if ret:
return get_selinux_context(path)
@ -3379,7 +3388,7 @@ def get_managed(
# exists doesn't play nice with sfn as bool
# but if cache failed, sfn == False
if not sfn or not os.path.exists(sfn):
return sfn, {}, 'Source file {0!r} not found'.format(source)
return sfn, {}, 'Source file \'{0}\' not found'.format(source)
if sfn == name:
raise SaltInvocationError(
'Source file cannot be the same as destination'
@ -3984,7 +3993,7 @@ def manage_file(name,
sfn = __salt__['cp.cache_file'](source, saltenv)
if not sfn:
return _error(
ret, 'Source file {0!r} not found'.format(source))
ret, 'Source file \'{0}\' not found'.format(source))
# If the downloaded file came from a non salt server or local source
# verify that it matches the intended sum value
if _urlparse(source).scheme not in ('salt', ''):
@ -4077,7 +4086,7 @@ def manage_file(name,
sfn = __salt__['cp.cache_file'](source, saltenv)
if not sfn:
return _error(
ret, 'Source file {0!r} not found'.format(source))
ret, 'Source file \'{0}\' not found'.format(source))
# If the downloaded file came from a non salt server source verify
# that it matches the intended sum value
if _urlparse(source).scheme != 'salt':
@ -4146,7 +4155,7 @@ def manage_file(name,
sfn = __salt__['cp.cache_file'](source, saltenv)
if not sfn:
return _error(
ret, 'Source file {0!r} not found'.format(source))
ret, 'Source file \'{0}\' not found'.format(source))
# If the downloaded file came from a non salt server source verify
# that it matches the intended sum value
if _urlparse(source).scheme != 'salt':
@ -4300,12 +4309,12 @@ def makedirs_(path,
if os.path.isdir(dirname):
# There's nothing for us to do
msg = 'Directory {0!r} already exists'.format(dirname)
msg = 'Directory \'{0}\' already exists'.format(dirname)
log.debug(msg)
return msg
if os.path.exists(dirname):
msg = 'The path {0!r} already exists and is not a directory'.format(
msg = 'The path \'{0}\' already exists and is not a directory'.format(
dirname
)
log.debug(msg)
@ -4635,7 +4644,7 @@ def mknod(name,
ret = mknod_fifo(name, user, group, mode)
else:
raise SaltInvocationError(
'Node type unavailable: {0!r}. Available node types are '
'Node type unavailable: \'{0}\'. Available node types are '
'character (\'c\'), block (\'b\'), and pipe (\'p\').'.format(ntype)
)
return ret
@ -4888,7 +4897,7 @@ remove_backup = delete_backup
def grep(path,
pattern,
*args):
*opts):
'''
Grep for a string in the specified file
@ -4897,40 +4906,52 @@ def grep(path,
versions of Salt
path
A file path
Path to the file to be searched
.. note::
Globbing is supported (i.e. ``/var/log/foo/*.log``, but if globbing
is being used then the path should be quoted to keep the shell from
attempting to expand the glob expression.
pattern
A string. For example:
``test``
``a[0-5]``
args
grep options. For example:
``" -v"``
``" -i -B2"``
Pattern to match. For example: ``test``, or ``a[0-5]``
opts
Additional command-line flags to pass to the grep command. For example:
``-v``, or ``-i -B2``
.. note::
The options should come after a double-dash (as shown in the
examples below) to keep Salt's own argument parser from
interpreting them.
CLI Example:
.. code-block:: bash
salt '*' file.grep /etc/passwd nobody
salt '*' file.grep /etc/sysconfig/network-scripts/ifcfg-eth0 ipaddr " -i"
salt '*' file.grep /etc/sysconfig/network-scripts/ifcfg-eth0 ipaddr " -i -B2"
salt '*' file.grep "/etc/sysconfig/network-scripts/*" ipaddr " -i -l"
salt '*' file.grep /etc/sysconfig/network-scripts/ifcfg-eth0 ipaddr -- -i
salt '*' file.grep /etc/sysconfig/network-scripts/ifcfg-eth0 ipaddr -- -i -B2
salt '*' file.grep "/etc/sysconfig/network-scripts/*" ipaddr -- -i -l
'''
path = os.path.expanduser(path)
if args:
options = ' '.join(args)
else:
options = ''
cmd = (
r'''grep {options} {pattern} {path}'''
.format(
options=options,
pattern=pattern,
path=path,
)
split_opts = []
for opt in opts:
try:
opt = shlex.split(opt)
except AttributeError:
opt = shlex.split(str(opt))
if len(opt) > 1:
salt.utils.warn_until(
'Carbon',
'Additional command line options for file.grep should be '
'passed one at a time, please do not pass more than one in a '
'single argument.'
)
split_opts.extend(opt)
cmd = ['grep'] + split_opts + [pattern, path]
try:
ret = __salt__['cmd.run_all'](cmd, python_shell=False)
except (IOError, OSError) as exc:

View File

@ -139,7 +139,9 @@ def _match(names):
# Look for full matches
full_pkg_strings = []
out = __salt__['cmd.run_stdout']('pkg_info', output_loglevel='trace')
out = __salt__['cmd.run_stdout'](['pkg_info'],
output_loglevel='trace',
python_shell=False)
for line in out.splitlines():
try:
full_pkg_strings.append(line.split()[0])
@ -158,7 +160,7 @@ def _match(names):
else:
ambiguous.append(name)
errors.append(
'Ambiguous package {0!r}. Full name/version required. '
'Ambiguous package \'{0}\'. Full name/version required. '
'Possible matches: {1}'.format(
name,
', '.join(['{0}-{1}'.format(name, x) for x in cver])
@ -169,7 +171,7 @@ def _match(names):
not_matched = \
set(names) - set(matches) - set(full_matches) - set(ambiguous)
for name in not_matched:
errors.append('Package {0!r} not found'.format(name))
errors.append('Package \'{0}\' not found'.format(name))
return matches + full_matches, errors
@ -279,7 +281,9 @@ def list_pkgs(versions_as_list=False, with_origin=False, **kwargs):
ret = {}
origins = {}
out = __salt__['cmd.run_stdout']('pkg_info -ao', output_loglevel='trace')
out = __salt__['cmd.run_stdout'](['pkg_info', '-ao'],
output_loglevel='trace',
python_shell=False)
pkgs_re = re.compile(r'Information for ([^:]+):\s*Origin:\n([^\n]+)')
for pkg, origin in pkgs_re.findall(out):
if not pkg:
@ -386,9 +390,10 @@ def install(name=None,
old = list_pkgs()
__salt__['cmd.run'](
'pkg_add {0}'.format(' '.join(args)),
['pkg_add'] + args,
env=env,
output_loglevel='trace'
output_loglevel='trace',
python_shell=False
)
__context__.pop('pkg.list_pkgs', None)
new = list_pkgs()
@ -448,8 +453,11 @@ def remove(name=None, pkgs=None, **kwargs):
log.error(error)
if not targets:
return {}
cmd = 'pkg_delete {0}'.format(' '.join(targets))
__salt__['cmd.run'](cmd, output_loglevel='trace')
__salt__['cmd.run'](
['pkg_delete'] + targets,
output_loglevel='trace',
python_shell=False
)
__context__.pop('pkg.list_pkgs', None)
new = list_pkgs()
return salt.utils.compare_dicts(old, new)
@ -467,7 +475,9 @@ def _rehash():
'''
shell = __salt__['environ.get']('SHELL', output_loglevel='trace')
if shell.split('/')[-1] in ('csh', 'tcsh'):
__salt__['cmd.run']('rehash', output_loglevel='trace')
__salt__['cmd.run'](['rehash'],
output_loglevel='trace',
python_shell=False)
def file_list(*packages):
@ -511,13 +521,13 @@ def file_dict(*packages):
if packages:
match_pattern = '\'{0}-[0-9]*\''
matches = [match_pattern.format(p) for p in packages]
cmd = 'pkg_info -QL {0}'.format(' '.join(matches))
cmd = ['pkg_info', '-QL'] + [match_pattern.format(p) for p in packages]
else:
cmd = 'pkg_info -QLa'
cmd = ['pkg_info', '-QLa']
ret = __salt__['cmd.run_all'](cmd, output_loglevel='trace')
ret = __salt__['cmd.run_all'](cmd,
output_loglevel='trace',
python_shell=False)
for line in ret['stderr'].splitlines():
errors.append(line)

View File

@ -42,10 +42,10 @@ def _portsnap():
'''
Return 'portsnap --interactive' for FreeBSD 10, otherwise 'portsnap'
'''
return 'portsnap{0}'.format(
' --interactive' if float(__grains__['osrelease']) >= 10
else ''
)
ret = ['portsnap']
if float(__grains__['osrelease']) >= 10:
ret.append('--interactive')
return ret
def _check_portname(name):
@ -55,12 +55,12 @@ def _check_portname(name):
'''
if not isinstance(name, string_types) or '/' not in name:
raise SaltInvocationError(
'Invalid port name {0!r} (category required)'.format(name)
'Invalid port name \'{0}\' (category required)'.format(name)
)
path = os.path.join('/usr/ports', name)
if not os.path.isdir(path):
raise SaltInvocationError('Path {0!r} does not exist'.format(path))
raise SaltInvocationError('Path \'{0}\' does not exist'.format(path))
return path
@ -164,9 +164,15 @@ def install(name, clean=True):
old = __salt__['pkg.list_pkgs']()
if old.get(name.rsplit('/')[-1]):
deinstall(name)
cmd = ['make', 'install']
if clean:
cmd.append('clean')
cmd.append('BATCH=yes')
result = __salt__['cmd.run_all'](
'make install{0} BATCH=yes'.format(' clean' if clean else ''),
cwd=portpath, reset_system_locale=False
cmd,
cwd=portpath,
reset_system_locale=False,
python_shell=False
)
if result['retcode'] != 0:
__context__['ports.install_error'] = result['stderr']
@ -195,7 +201,11 @@ def deinstall(name):
'''
portpath = _check_portname(name)
old = __salt__['pkg.list_pkgs']()
__salt__['cmd.run']('make deinstall BATCH=yes', cwd=portpath)
result = __salt__['cmd.run_all'](
['make', 'deinstall', 'BATCH=yes'],
cwd=portpath,
python_shell=False
)
__context__.pop('pkg.list_pkgs', None)
new = __salt__['pkg.list_pkgs']()
return salt.utils.compare_dicts(old, new)
@ -215,7 +225,11 @@ def rmconfig(name):
salt '*' ports.rmconfig security/nmap
'''
portpath = _check_portname(name)
return __salt__['cmd.run']('make rmconfig', cwd=portpath)
return __salt__['cmd.run'](
['make', 'rmconfig'],
cwd=portpath,
python_shell=False
)
def showconfig(name, default=False, dict_return=False):
@ -250,7 +264,11 @@ def showconfig(name, default=False, dict_return=False):
return default_config
try:
result = __salt__['cmd.run_all']('make showconfig', cwd=portpath)
result = __salt__['cmd.run_all'](
['make', 'showconfig'],
cwd=portpath,
python_shell=False
)
output = result['stdout'].splitlines()
if result['retcode'] != 0:
error = result['stderr']
@ -323,7 +341,7 @@ def config(name, reset=False, **kwargs):
if not configuration:
raise CommandExecutionError(
'Unable to get port configuration for {0!r}'.format(name)
'Unable to get port configuration for \'{0}\''.format(name)
)
# Get top-level key for later reference
@ -379,7 +397,10 @@ def update(extract=False):
salt '*' ports.update
'''
result = __salt__['cmd.run_all']('{0} fetch'.format(_portsnap()))
result = __salt__['cmd.run_all'](
_portsnap() + ['fetch'],
python_shell=False
)
if not result['retcode'] == 0:
raise CommandExecutionError(
'Unable to fetch ports snapshot: {0}'.format(result['stderr'])
@ -404,13 +425,19 @@ def update(extract=False):
ret.append('Fetched {0} new ports or files'.format(new_port_count))
if extract:
result = __salt__['cmd.run_all']('{0} extract'.format(_portsnap()))
result = __salt__['cmd.run_all'](
_portsnap() + ['extract'],
python_shell=False
)
if not result['retcode'] == 0:
raise CommandExecutionError(
'Unable to extract ports snapshot {0}'.format(result['stderr'])
)
result = __salt__['cmd.run_all']('{0} update'.format(_portsnap()))
result = __salt__['cmd.run_all'](
_portsnap() + ['update'],
python_shell=False
)
if not result['retcode'] == 0:
raise CommandExecutionError(
'Unable to apply ports snapshot: {0}'.format(result['stderr'])
@ -466,7 +493,7 @@ def search(name):
if '/' in name:
if name.count('/') > 1:
raise SaltInvocationError(
'Invalid search string {0!r}. Port names cannot have more '
'Invalid search string \'{0}\'. Port names cannot have more '
'than one slash'
)
else:

View File

@ -4,20 +4,14 @@ Manage ruby gems.
'''
from __future__ import absolute_import
try:
from shlex import quote as _cmd_quote # pylint: disable=E0611
except ImportError:
from pipes import quote as _cmd_quote
# Import python libs
import re
import logging
# Import salt libs
import salt.utils.itertools
from salt.exceptions import CommandExecutionError
logger = logging.getLogger(__name__) # pylint: disable=C0103
# Import salt libs
import salt.utils
@ -25,6 +19,8 @@ __func_alias__ = {
'list_': 'list'
}
log = logging.getLogger(__name__) # pylint: disable=C0103
def _gem(command, ruby=None, runas=None, gem_bin=None):
'''
@ -45,7 +41,7 @@ def _gem(command, ruby=None, runas=None, gem_bin=None):
:return:
Returns the full standard out including success codes or False if it fails
'''
cmdline = '{gem} {command}'.format(gem=gem_bin or 'gem', command=command)
cmdline = [gem_bin or 'gem'] + command
# If a custom gem is given, use that and don't check for rvm/rbenv. User
# knows best!
@ -53,22 +49,20 @@ def _gem(command, ruby=None, runas=None, gem_bin=None):
if __salt__['rvm.is_installed'](runas=runas):
return __salt__['rvm.do'](ruby, cmdline, runas=runas)
if not salt.utils.is_windows() and __salt__['rbenv.is_installed'](runas=runas):
if not salt.utils.is_windows() \
and __salt__['rbenv.is_installed'](runas=runas):
if ruby is None:
return __salt__['rbenv.do'](cmdline, runas=runas)
else:
return __salt__['rbenv.do_with_ruby'](ruby, cmdline, runas=runas)
ret = __salt__['cmd.run_all'](
return __salt__['rbenv.do_with_ruby'](ruby,
cmdline,
runas=runas,
python_shell=True
)
runas=runas)
ret = __salt__['cmd.run_all'](cmdline, runas=runas, python_shell=False)
if ret['retcode'] == 0:
return ret['stdout']
else:
logger.error(ret['stderr'])
raise CommandExecutionError(ret['stderr'])
@ -118,19 +112,14 @@ def install(gems, # pylint: disable=C0103
salt '*' gem.install redphone gem_bin=/opt/sensu/embedded/bin/gem
'''
# Check for injection
if gems:
gems = ' '.join([_cmd_quote(gem) for gem in gems.split()])
if ruby:
ruby = _cmd_quote(ruby)
if gem_bin:
gem_bin = _cmd_quote(gem_bin)
try:
gems = gems.split()
except AttributeError:
pass
options = []
if version:
version = _cmd_quote(version) # injection check
options.append('--version {0}'.format(version))
options.extend(['--version', version])
if not rdoc:
options.append('--no-rdoc')
if not ri:
@ -138,14 +127,11 @@ def install(gems, # pylint: disable=C0103
if pre_releases:
options.append('--pre')
if proxy:
proxy = _cmd_quote(proxy) # injection check
options.append('-p {0}'.format(proxy))
options.extend(['-p', proxy])
if source:
options.append('--source {0}'.format(source))
options.extend(['--source', source])
cmdline_args = ' '.join(options)
return _gem('install {gems} {options}'.format(gems=gems,
options=cmdline_args),
return _gem(['install'] + gems + options,
ruby,
gem_bin=gem_bin,
runas=runas)
@ -171,15 +157,12 @@ def uninstall(gems, ruby=None, runas=None, gem_bin=None):
salt '*' gem.uninstall vagrant
'''
# Check for injection
if gems:
gems = ' '.join([_cmd_quote(gem) for gem in gems.split()])
if ruby:
ruby = _cmd_quote(ruby)
if gem_bin:
gem_bin = _cmd_quote(gem_bin)
try:
gems = gems.split()
except AttributeError:
pass
return _gem('uninstall {gems} -a -x'.format(gems=gems),
return _gem(['uninstall'] + gems + ['-a', '-x'],
ruby,
gem_bin=gem_bin,
runas=runas)
@ -205,15 +188,12 @@ def update(gems, ruby=None, runas=None, gem_bin=None):
salt '*' gem.update vagrant
'''
# Check for injection
if gems:
gems = ' '.join([_cmd_quote(gem) for gem in gems.split()])
if ruby:
ruby = _cmd_quote(ruby)
if gem_bin:
gem_bin = _cmd_quote(gem_bin)
try:
gems = gems.split()
except AttributeError:
pass
return _gem('update {gems}'.format(gems=gems),
return _gem(['update'] + gems,
ruby,
gem_bin=gem_bin,
runas=runas)
@ -239,15 +219,7 @@ def update_system(version='', ruby=None, runas=None, gem_bin=None):
salt '*' gem.update_system
'''
# Check for injection
if version:
version = _cmd_quote(version)
if ruby:
ruby = _cmd_quote(ruby)
if gem_bin:
gem_bin = _cmd_quote(gem_bin)
return _gem('update --system {version}'.format(version=version),
return _gem(['update', '--system', version],
ruby,
gem_bin=gem_bin,
runas=runas)
@ -273,28 +245,21 @@ def list_(prefix='', ruby=None, runas=None, gem_bin=None):
salt '*' gem.list
'''
gems = {}
# Check for injection
cmd = ['list']
if prefix:
prefix = _cmd_quote(prefix)
if ruby:
ruby = _cmd_quote(ruby)
if gem_bin:
gem_bin = _cmd_quote(gem_bin)
stdout = _gem('list {prefix}'.format(prefix=prefix),
cmd.append(prefix)
stdout = _gem(cmd,
ruby,
gem_bin=gem_bin,
runas=runas)
lines = stdout.splitlines()
for line in lines:
ret = {}
for line in salt.utils.itertools.split(stdout, '\n'):
match = re.match(r'^([^ ]+) \((.+)\)', line)
if match:
gem = match.group(1)
versions = match.group(2).split(', ')
gems[gem] = versions
return gems
ret[gem] = versions
return ret
def list_upgrades(ruby=None,
@ -319,20 +284,20 @@ def list_upgrades(ruby=None,
salt '*' gem.list_upgrades
'''
result = _gem('outdated',
result = _gem(['outdated'],
ruby,
gem_bin=gem_bin,
runas=runas)
outdated = {}
for line in result.splitlines():
ret = {}
for line in salt.utils.itertools.split(result, '\n'):
match = re.search(r'(\S+) \(\S+ < (\S+)\)', line)
if match:
name, version = match.groups()
else:
logger.error('Can\'t parse line {0!r}'.format(line))
log.error('Can\'t parse line \'{0}\''.format(line))
continue
outdated[name] = version
return outdated
ret[name] = version
return ret
def sources_add(source_uri, ruby=None, runas=None, gem_bin=None):
@ -355,15 +320,7 @@ def sources_add(source_uri, ruby=None, runas=None, gem_bin=None):
salt '*' gem.sources_add http://rubygems.org/
'''
# Check for injection
if source_uri:
source_uri = _cmd_quote(source_uri)
if ruby:
ruby = _cmd_quote(ruby)
if gem_bin:
gem_bin = _cmd_quote(gem_bin)
return _gem('sources --add {source_uri}'.format(source_uri=source_uri),
return _gem(['sources', '--add', source_uri],
ruby,
gem_bin=gem_bin,
runas=runas)
@ -389,15 +346,7 @@ def sources_remove(source_uri, ruby=None, runas=None, gem_bin=None):
salt '*' gem.sources_remove http://rubygems.org/
'''
# Check for injection
if source_uri:
source_uri = _cmd_quote(source_uri)
if ruby:
ruby = _cmd_quote(ruby)
if gem_bin:
gem_bin = _cmd_quote(gem_bin)
return _gem('sources --remove {source_uri}'.format(source_uri=source_uri),
return _gem(['sources', '--remove', source_uri],
ruby,
gem_bin=gem_bin,
runas=runas)
@ -421,11 +370,5 @@ def sources_list(ruby=None, runas=None, gem_bin=None):
salt '*' gem.sources_list
'''
# Check for injection
if ruby:
ruby = _cmd_quote(ruby)
if gem_bin:
gem_bin = _cmd_quote(gem_bin)
ret = _gem('sources', ruby, gem_bin=gem_bin, runas=runas)
ret = _gem(['sources'], ruby, gem_bin=gem_bin, runas=runas)
return [] if ret is False else ret.splitlines()[2:]

View File

@ -2,8 +2,8 @@
'''
InfluxDB - A distributed time series database
Module to provide InfluxDB compatibility to Salt
(compatible with InfluxDB version 0.5+)
Module to provide InfluxDB compatibility to Salt (compatible with InfluxDB
version 0.5+)
.. versionadded:: 2014.7.0
@ -63,7 +63,7 @@ def _client(user=None, password=None, host=None, port=None):
def db_list(user=None, password=None, host=None, port=None):
"""
'''
List all InfluxDB databases
user
@ -85,7 +85,7 @@ def db_list(user=None, password=None, host=None, port=None):
salt '*' influxdb.db_list
salt '*' influxdb.db_list <user> <password> <host> <port>
"""
'''
client = _client(user=user, password=password, host=host, port=port)
return client.get_list_database()
@ -123,7 +123,7 @@ def db_exists(name, user=None, password=None, host=None, port=None):
def db_create(name, user=None, password=None, host=None, port=None):
"""
'''
Create a database
name
@ -147,16 +147,16 @@ def db_create(name, user=None, password=None, host=None, port=None):
salt '*' influxdb.db_create <name>
salt '*' influxdb.db_create <name> <user> <password> <host> <port>
"""
'''
if db_exists(name, user, password, host, port):
log.info('DB {0!r} already exists'.format(name))
log.info('DB \'{0}\' already exists'.format(name))
return False
client = _client(user=user, password=password, host=host, port=port)
return client.create_database(name)
def db_remove(name, user=None, password=None, host=None, port=None):
"""
'''
Remove a database
name
@ -180,16 +180,16 @@ def db_remove(name, user=None, password=None, host=None, port=None):
salt '*' influxdb.db_remove <name>
salt '*' influxdb.db_remove <name> <user> <password> <host> <port>
"""
'''
if not db_exists(name, user, password, host, port):
log.info('DB {0!r} does not exist'.format(name))
log.info('DB \'{0}\' does not exist'.format(name))
return False
client = _client(user=user, password=password, host=host, port=port)
return client.delete_database(name)
def user_list(database=None, user=None, password=None, host=None, port=None):
"""
'''
List cluster admins or database users.
If a database is specified: it will return database users list.
@ -217,7 +217,7 @@ def user_list(database=None, user=None, password=None, host=None, port=None):
salt '*' influxdb.user_list
salt '*' influxdb.user_list <database>
salt '*' influxdb.user_list <database> <user> <password> <host> <port>
"""
'''
client = _client(user=user, password=password, host=host, port=port)
if database:
client.switch_database(database)
@ -267,7 +267,7 @@ def user_exists(
def user_create(name, passwd, database=None, user=None, password=None,
host=None, port=None):
"""
'''
Create a cluster admin or a database user.
If a database is specified: it will create database user.
@ -301,13 +301,13 @@ def user_create(name, passwd, database=None, user=None, password=None,
salt '*' influxdb.user_create <name> <passwd>
salt '*' influxdb.user_create <name> <passwd> <database>
salt '*' influxdb.user_create <name> <passwd> <database> <user> <password> <host> <port>
"""
'''
if user_exists(name, database, user, password, host, port):
if database:
log.info('User {0!r} already exists for DB {1!r}'.format(
log.info('User \'{0}\' already exists for DB \'{1}\''.format(
name, database))
else:
log.info('Cluster admin {0!r} already exists'.format(name))
log.info('Cluster admin \'{0}\' already exists'.format(name))
return False
client = _client(user=user, password=password, host=host, port=port)
@ -319,7 +319,7 @@ def user_create(name, passwd, database=None, user=None, password=None,
def user_chpass(name, passwd, database=None, user=None, password=None,
host=None, port=None):
"""
'''
Change password for a cluster admin or a database user.
If a database is specified: it will update database user password.
@ -353,13 +353,17 @@ def user_chpass(name, passwd, database=None, user=None, password=None,
salt '*' influxdb.user_chpass <name> <passwd>
salt '*' influxdb.user_chpass <name> <passwd> <database>
salt '*' influxdb.user_chpass <name> <passwd> <database> <user> <password> <host> <port>
"""
'''
if not user_exists(name, database, user, password, host, port):
if database:
log.info('User {0!r} does not exist for DB {1!r}'.format(
name, database))
log.info(
'User \'{0}\' does not exist for DB \'{1}\''.format(
name,
database
)
)
else:
log.info('Cluster admin {0!r} does not exist'.format(name))
log.info('Cluster admin \'{0}\' does not exist'.format(name))
return False
client = _client(user=user, password=password, host=host, port=port)
if database:
@ -370,7 +374,7 @@ def user_chpass(name, passwd, database=None, user=None, password=None,
def user_remove(name, database=None, user=None, password=None, host=None,
port=None):
"""
'''
Remove a cluster admin or a database user.
If a database is specified: it will remove the database user.
@ -404,13 +408,16 @@ def user_remove(name, database=None, user=None, password=None, host=None,
salt '*' influxdb.user_remove <name>
salt '*' influxdb.user_remove <name> <database>
salt '*' influxdb.user_remove <name> <database> <user> <password> <host> <port>
"""
'''
if not user_exists(name, database, user, password, host, port):
if database:
log.info('User {0!r} does not exist for DB {1!r}'.format(
name, database))
log.info(
'User \'{0}\' does not exist for DB \'{1}\''.format(
name, database
)
)
else:
log.info('Cluster admin {0!r} does not exist'.format(name))
log.info('Cluster admin \'{0}\' does not exist'.format(name))
return False
client = _client(user=user, password=password, host=host, port=port)
if database:
@ -421,7 +428,7 @@ def user_remove(name, database=None, user=None, password=None, host=None,
def query(database, query, time_precision='s', chunked=False, user=None,
password=None, host=None, port=None):
"""
'''
Querying data
database
@ -454,7 +461,7 @@ def query(database, query, time_precision='s', chunked=False, user=None,
salt '*' influxdb.query <database> <query>
salt '*' influxdb.query <database> <query> <time_precision> <chunked> <user> <password> <host> <port>
"""
'''
client = _client(user=user, password=password, host=host, port=port)
client.switch_database(database)
return client.query(query, time_precision=time_precision, chunked=chunked)

View File

@ -12,6 +12,7 @@ except ImportError:
# Import Salt Libs
import salt.utils
import salt.utils.itertools
from salt.exceptions import CommandExecutionError, SaltInvocationError
from salt.modules.mac_user import _dscl, _flush_dscl_cache
@ -44,7 +45,9 @@ def add(name, gid=None, **kwargs):
### NOTE: **kwargs isn't used here but needs to be included in this
### function for compatibility with the group.present state
if info(name):
raise CommandExecutionError('Group {0!r} already exists'.format(name))
raise CommandExecutionError(
'Group \'{0}\' already exists'.format(name)
)
if salt.utils.contains_whitespace(name):
raise SaltInvocationError('Group name cannot contain whitespace')
if name.startswith('_'):
@ -57,28 +60,30 @@ def add(name, gid=None, **kwargs):
gid_list = _list_gids()
if str(gid) in gid_list:
raise CommandExecutionError(
'gid {0!r} already exists'.format(gid)
'gid \'{0}\' already exists'.format(gid)
)
cmd = 'dseditgroup -o create '
cmd = ['dseditgroup', '-o', 'create']
if gid:
cmd += '-i {0} '.format(gid)
cmd += str(name)
return __salt__['cmd.retcode'](cmd) == 0
cmd.extend(['-i', gid])
cmd.append(name)
return __salt__['cmd.retcode'](cmd, python_shell=False) == 0
def _list_gids():
'''
Return a list of gids in use
'''
cmd = __salt__['cmd.run']('dscacheutil -q group | grep gid:',
output = __salt__['cmd.run'](
['dscacheutil', '-q', 'group'],
output_loglevel='quiet',
python_shell=True)
data_list = cmd.split()
for item in data_list:
if item == 'gid:':
data_list.remove(item)
return sorted(set(data_list))
python_shell=False
)
ret = set()
for line in salt.utils.itertools.split(output, '\n'):
if line.startswith('gid:'):
ret.update(line.split()[1:])
return sorted(ret)
def delete(name):
@ -99,8 +104,8 @@ def delete(name):
)
if not info(name):
return True
cmd = 'dseditgroup -o delete {0}'.format(name)
return __salt__['cmd.retcode'](cmd) == 0
cmd = ['dseditgroup', '-o', 'delete', name]
return __salt__['cmd.retcode'](cmd, python_shell=False) == 0
def adduser(group, name):
@ -235,8 +240,10 @@ def chgid(name, gid):
pre_gid = __salt__['file.group_to_gid'](name)
pre_info = info(name)
if not pre_info:
raise CommandExecutionError('Group {0!r} does not exist'.format(name))
raise CommandExecutionError(
'Group \'{0}\' does not exist'.format(name)
)
if gid == pre_info['gid']:
return True
cmd = 'dseditgroup -o edit -i {0} {1}'.format(gid, name)
return __salt__['cmd.retcode'](cmd) == 0
cmd = ['dseditgroup', '-o', 'edit', '-i', gid, name]
return __salt__['cmd.retcode'](cmd, python_shell=False) == 0

View File

@ -22,11 +22,6 @@ import salt.utils
from salt.exceptions import CommandExecutionError, SaltInvocationError
from salt.ext.six import string_types
try:
from shlex import quote as _cmd_quote # pylint: disable=E0611
except ImportError:
from pipes import quote as _cmd_quote
log = logging.getLogger(__name__)
# Define the module's virtual name
@ -45,7 +40,7 @@ def _flush_dscl_cache():
'''
Flush dscl cache
'''
__salt__['cmd.run']('dscacheutil -flushcache')
__salt__['cmd.run'](['dscacheutil', '-flushcache'], python_shell=False)
def _dscl(cmd, ctype='create'):
@ -56,11 +51,13 @@ def _dscl(cmd, ctype='create'):
source, noderoot = '.', ''
else:
source, noderoot = 'localhost', '/Local/Default'
if noderoot:
cmd[0] = noderoot + cmd[0]
# Note, it's OK that cmd is not quoted here, we clean it up below
return __salt__['cmd.run_all'](
'dscl {0} -{1} {2}{3}'.format(source, ctype, noderoot, cmd),
output_loglevel='quiet' if ctype == 'passwd' else 'warning'
['dscl', source, '-' + ctype] + cmd,
output_loglevel='quiet' if ctype == 'passwd' else 'debug',
python_shell=False
)
@ -90,7 +87,7 @@ def add(name,
salt '*' user.add name <uid> <gid> <groups> <home> <shell>
'''
if info(name):
raise CommandExecutionError('User {0!r} already exists'.format(name))
raise CommandExecutionError('User \'{0}\' already exists'.format(name))
if salt.utils.contains_whitespace(name):
raise SaltInvocationError('Username cannot contain whitespace')
@ -112,22 +109,20 @@ def add(name,
if not isinstance(gid, int):
raise SaltInvocationError('gid must be an integer')
_dscl('/Users/{0} UniqueID {1!r}'.format(_cmd_quote(name), uid))
_dscl('/Users/{0} PrimaryGroupID {1!r}'.format(_cmd_quote(name), gid))
_dscl('/Users/{0} UserShell {1!r}'.format(_cmd_quote(name),
_cmd_quote(shell)))
_dscl('/Users/{0} NFSHomeDirectory {1!r}'.format(_cmd_quote(name),
_cmd_quote(home)))
_dscl('/Users/{0} RealName {1!r}'.format(_cmd_quote(name),
_cmd_quote(fullname)))
name_path = '/Users/{0}'.format(name)
_dscl([name_path, 'UniqueID', uid])
_dscl([name_path, 'PrimaryGroupID', gid])
_dscl([name_path, 'UserShell', shell])
_dscl([name_path, 'NFSHomeDirectory', home])
_dscl([name_path, 'RealName', fullname])
# Set random password, since without a password the account will not be
# available. TODO: add shadow module
randpass = ''.join(
random.SystemRandom().choice(string.letters + string.digits) for x in range(20)
random.SystemRandom().choice(string.letters + string.digits)
for x in range(20)
)
_dscl('/Users/{0} {1!r}'.format(_cmd_quote(name),
_cmd_quote(randpass)), ctype='passwd')
_dscl([name_path, randpass], ctype='passwd')
# dscl buffers changes, sleep before setting group membership
time.sleep(1)
@ -156,7 +151,7 @@ def delete(name, *args):
# group membership is managed separately from users and an entry for the
# user will persist even after the user is removed.
chgroups(name, ())
return _dscl('/Users/{0}'.format(_cmd_quote(name)), ctype='delete')['retcode'] == 0
return _dscl(['/Users/{0}'.format(name)], ctype='delete')['retcode'] == 0
def getent(refresh=False):
@ -193,13 +188,11 @@ def chuid(name, uid):
raise SaltInvocationError('uid must be an integer')
pre_info = info(name)
if not pre_info:
raise CommandExecutionError('User {0!r} does not exist'.format(name))
raise CommandExecutionError('User \'{0}\' does not exist'.format(name))
if uid == pre_info['uid']:
return True
_dscl(
'/Users/{0} UniqueID {1!r} {2!r}'.format(_cmd_quote(name),
pre_info['uid'],
uid),
['/Users/{0}'.format(name), 'UniqueID', pre_info['uid'], uid],
ctype='change'
)
# dscl buffers changes, sleep 1 second before checking if new value
@ -222,14 +215,11 @@ def chgid(name, gid):
raise SaltInvocationError('gid must be an integer')
pre_info = info(name)
if not pre_info:
raise CommandExecutionError('User {0!r} does not exist'.format(name))
raise CommandExecutionError('User \'{0}\' does not exist'.format(name))
if gid == pre_info['gid']:
return True
_dscl(
'/Users/{0} PrimaryGroupID {1!r} {2!r}'.format(
_cmd_quote(name),
pre_info['gid'],
gid),
['/Users/{0}'.format(name), 'PrimaryGroupID', pre_info['gid'], gid],
ctype='change'
)
# dscl buffers changes, sleep 1 second before checking if new value
@ -250,14 +240,11 @@ def chshell(name, shell):
'''
pre_info = info(name)
if not pre_info:
raise CommandExecutionError('User {0!r} does not exist'.format(name))
raise CommandExecutionError('User \'{0}\' does not exist'.format(name))
if shell == pre_info['shell']:
return True
_dscl(
'/Users/{0} UserShell {1!r} {2!r}'.format(
_cmd_quote(name),
_cmd_quote(pre_info['shell']),
_cmd_quote(shell)),
['/Users/{0}'.format(name), 'UserShell', pre_info['shell'], shell],
ctype='change'
)
# dscl buffers changes, sleep 1 second before checking if new value
@ -278,14 +265,12 @@ def chhome(name, home):
'''
pre_info = info(name)
if not pre_info:
raise CommandExecutionError('User {0!r} does not exist'.format(name))
raise CommandExecutionError('User \'{0}\' does not exist'.format(name))
if home == pre_info['home']:
return True
_dscl(
'/Users/{0} NFSHomeDirectory {1!r} {2!r}'.format(
_cmd_quote(name),
_cmd_quote(pre_info['home']),
_cmd_quote(home)),
['/Users/{0}'.format(name), 'NFSHomeDirectory',
pre_info['home'], home],
ctype='change'
)
# dscl buffers changes, sleep 1 second before checking if new value
@ -307,13 +292,13 @@ def chfullname(name, fullname):
fullname = str(fullname)
pre_info = info(name)
if not pre_info:
raise CommandExecutionError('User {0!r} does not exist'.format(name))
raise CommandExecutionError('User \'{0}\' does not exist'.format(name))
if fullname == pre_info['fullname']:
return True
_dscl(
'/Users/{0} RealName {1!r}'.format(_cmd_quote(name), fullname),
# use a "create" command, because a "change" command would fail if
# current fullname is an empty string. The "create" will just overwrite
['/Users/{0}'.format(name), 'RealName', fullname],
# use a 'create' command, because a 'change' command would fail if
# current fullname is an empty string. The 'create' will just overwrite
# this field.
ctype='create'
)
@ -347,7 +332,7 @@ def chgroups(name, groups, append=False):
### function for compatibility with the user.present state
uinfo = info(name)
if not uinfo:
raise CommandExecutionError('User {0!r} does not exist'.format(name))
raise CommandExecutionError('User \'{0}\' does not exist'.format(name))
if isinstance(groups, string_types):
groups = groups.split(',')
@ -366,16 +351,14 @@ def chgroups(name, groups, append=False):
# Add groups from which user is missing
for group in desired - ugrps:
_dscl(
'/Groups/{0} GroupMembership {1}'.format(_cmd_quote(group),
_cmd_quote(name)),
['/Groups/{0}'.format(group), 'GroupMembership', name],
ctype='append'
)
if not append:
# Remove from extra groups
for group in ugrps - desired:
_dscl(
'/Groups/{0} GroupMembership {1}'.format(_cmd_quote(group),
_cmd_quote(name)),
['/Groups/{0}'.format(group), 'GroupMembership', name],
ctype='delete'
)
time.sleep(1)
@ -423,7 +406,8 @@ def list_groups(name):
salt '*' user.list_groups foo
'''
groups = [group for group in salt.utils.get_group_list(name) if not group.startswith('_')]
groups = [group for group in salt.utils.get_group_list(name)
if not group.startswith('_')]
return groups
@ -452,12 +436,14 @@ def rename(name, new_name):
'''
current_info = info(name)
if not current_info:
raise CommandExecutionError('User {0!r} does not exist'.format(name))
raise CommandExecutionError('User \'{0}\' does not exist'.format(name))
new_info = info(new_name)
if new_info:
raise CommandExecutionError('User {0!r} already exists'.format(new_name))
raise CommandExecutionError(
'User \'{0}\' already exists'.format(new_name)
)
_dscl(
'/Users/{0} RecordName {0!r} {2!r}'.format(name, new_name),
['/Users/{0}'.format(name), 'RecordName', name, new_name],
ctype='change'
)
# dscl buffers changes, sleep 1 second before checking if new value

View File

@ -222,10 +222,10 @@ def increment(key, delta=1, host=DEFAULT_HOST, port=DEFAULT_PORT):
cur = get(key)
if cur is None:
raise CommandExecutionError('Key {0!r} does not exist'.format(key))
raise CommandExecutionError('Key \'{0}\' does not exist'.format(key))
elif not isinstance(cur, integer_types):
raise CommandExecutionError(
'Value for key {0!r} must be an integer to be '
'Value for key \'{0}\' must be an integer to be '
'incremented'.format(key)
)
@ -253,10 +253,10 @@ def decrement(key, delta=1, host=DEFAULT_HOST, port=DEFAULT_PORT):
cur = get(key)
if cur is None:
raise CommandExecutionError('Key {0!r} does not exist'.format(key))
raise CommandExecutionError('Key \'{0}\' does not exist'.format(key))
elif not isinstance(cur, integer_types):
raise CommandExecutionError(
'Value for key {0!r} must be an integer to be '
'Value for key \'{0}\' must be an integer to be '
'decremented'.format(key)
)

View File

@ -26,12 +26,11 @@ Module to provide MySQL compatibility to salt.
mysql.default_file: '/etc/mysql/debian.cnf'
.. versionchanged:: 2014.1.0
charset connection argument added. This is a MySQL charset, not a python one
\'charset\' connection argument added. This is a MySQL charset, not a python one.
.. versionchanged:: 0.16.2
Connection arguments from the minion config file can be overridden on the
CLI by using the arguments defined :doc:`here
</ref/states/all/salt.states.mysql_user>`. Additionally, it is now possible
to setup a user with no password.
CLI by using the arguments defined :mod:`here <salt.states.mysql_user>`.
Additionally, it is now possible to setup a user with no password.
'''
# Import python libs
@ -119,68 +118,76 @@ __ssl_options__ = __ssl_options_parameterized__ + [
'X509'
]
################################################################################
# DEVELOPER NOTE: ABOUT arguments management, escapes, formats, arguments and
# security of SQL.
#
# A general rule of SQL security is to use queries with _execute call in this
# code using args parameter to let MySQLdb manage the arguments proper escaping.
# Another way of escaping values arguments could be '{0!r}'.format(), using
# __repr__ to ensure things get properly used as strings. But this could lead
# to two problems:
#
# * In ANSI mode, which is available on MySQL, but not by default, double
# quotes " should not be used as a string delimiters, in ANSI mode this is an
# identifier delimiter (like `).
#
# * Some rare exploits with bad multibytes management, either on python or
# MySQL could defeat this barrier, bindings internal escape functions
# should manage theses cases.
#
# So query with arguments should use a paramstyle defined in PEP249:
#
# http://www.python.org/dev/peps/pep-0249/#paramstyle
# We use pyformat, which means 'SELECT * FROM foo WHERE bar=%(myval)s'
# used with {'myval': 'some user input'}
#
# So far so good. But this cannot be used for identifier escapes. Identifiers
# are database names, table names and column names. Theses names are not values
# and do not follow the same escape rules (see quote_identifier function for
# details on `_ and % escape policies on identifiers). Using value escaping on
# identifier could fool the SQL engine (badly escaping quotes and not doubling
# ` characters. So for identifiers a call to quote_identifier should be done and
# theses identifiers should then be added in strings with format, but without
# __repr__ filter.
#
# Note also that when using query with arguments in _execute all '%' characters
# used in the query should get escaped to '%%' fo MySQLdb, but should not be
# escaped if the query runs without arguments. This is managed by _execute() and
# quote_identifier. This is not the same as escaping '%' to '\%' or '_' to '\%'
# when using a LIKE query (example in db_exists), as this escape is there to
# avoid having _ or % characters interpreted in LIKE queries. The string parted
# of the first query could become (still used with args dictionary for myval):
# 'SELECT * FROM {0} WHERE bar=%(myval)s'.format(quote_identifier('user input'))
#
# Check integration tests if you find a hole in theses strings and escapes rules
#
# Finally some examples to sum up.
#
# Given a name f_o%o`b'a"r, in python that would be '''f_o%o`b'a"r'''. I'll
# avoid python syntax for clarity:
#
# The MySQL way of writing this name is:
#
# value : 'f_o%o`b\'a"r' (managed by MySQLdb)
# identifier : `f_o%o``b'a"r`
# db identifier in general GRANT: `f\_o\%o``b'a"r`
# db identifier in table GRANT : `f_o%o``b'a"r`
# in mySQLdb, query with args : `f_o%%o``b'a"r` (as identifier)
# in mySQLdb, query without args: `f_o%o``b'a"r` (as identifier)
# value in a LIKE query : 'f\_o\%o`b\'a"r' (quotes managed by MySQLdb)
#
# And theses could be mixed, in a like query value with args: 'f\_o\%%o`b\'a"r'
#
################################################################################
r'''
DEVELOPER NOTE: ABOUT arguments management, escapes, formats, arguments and
security of SQL.
A general rule of SQL security is to use queries with _execute call in this
code using args parameter to let MySQLdb manage the arguments proper escaping.
Another way of escaping values arguments could be '{0!r}'.format(), using
__repr__ to ensure things get properly used as strings. But this could lead
to three problems:
* In ANSI mode, which is available on MySQL, but not by default, double
quotes " should not be used as a string delimiters, in ANSI mode this is an
identifier delimiter (like `).
* Some rare exploits with bad multibytes management, either on python or
MySQL could defeat this barrier, bindings internal escape functions
should manage theses cases.
* Unicode strings in Python 2 will include the 'u' before the repr'ed string,
like so:
Python 2.7.10 (default, May 26 2015, 04:16:29)
[GCC 5.1.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> u'something something {0!r}'.format(u'foo')
u"something something u'foo'"
So query with arguments should use a paramstyle defined in PEP249:
http://www.python.org/dev/peps/pep-0249/#paramstyle
We use pyformat, which means 'SELECT * FROM foo WHERE bar=%(myval)s'
used with {'myval': 'some user input'}
So far so good. But this cannot be used for identifier escapes. Identifiers
are database names, table names and column names. Theses names are not values
and do not follow the same escape rules (see quote_identifier function for
details on `_ and % escape policies on identifiers). Using value escaping on
identifier could fool the SQL engine (badly escaping quotes and not doubling
` characters. So for identifiers a call to quote_identifier should be done and
theses identifiers should then be added in strings with format, but without
__repr__ filter.
Note also that when using query with arguments in _execute all '%' characters
used in the query should get escaped to '%%' fo MySQLdb, but should not be
escaped if the query runs without arguments. This is managed by _execute() and
quote_identifier. This is not the same as escaping '%' to '\%' or '_' to '\%'
when using a LIKE query (example in db_exists), as this escape is there to
avoid having _ or % characters interpreted in LIKE queries. The string parted
of the first query could become (still used with args dictionary for myval):
'SELECT * FROM {0} WHERE bar=%(myval)s'.format(quote_identifier('user input'))
Check integration tests if you find a hole in theses strings and escapes rules
Finally some examples to sum up.
Given a name f_o%o`b'a"r, in python that would be """f_o%o`b'a"r""". I'll
avoid python syntax for clarity:
The MySQL way of writing this name is:
value : 'f_o%o`b\'a"r' (managed by MySQLdb)
identifier : `f_o%o``b'a"r`
db identifier in general GRANT: `f\_o\%o``b'a"r`
db identifier in table GRANT : `f_o%o``b'a"r`
in mySQLdb, query with args : `f_o%%o``b'a"r` (as identifier)
in mySQLdb, query without args: `f_o%o``b'a"r` (as identifier)
value in a LIKE query : 'f\_o\%o`b\'a"r' (quotes managed by MySQLdb)
And theses could be mixed, in a like query value with args: 'f\_o\%%o`b\'a"r'
'''
def __virtual__():
@ -342,7 +349,7 @@ def _grant_to_tokens(grant):
- grant: [grant1, grant2] (ala SELECT, USAGE, etc)
- database: MySQL DB
'''
log.debug('_grant_to_tokens entry {0!r}'.format(grant))
log.debug('_grant_to_tokens entry \'{0}\''.format(grant))
dict_mode = False
if isinstance(grant, dict):
dict_mode = True
@ -386,7 +393,7 @@ def _grant_to_tokens(grant):
position_tracker = 1 # Skip the initial 'GRANT' word token
database = ''
phrase = 'grants'
#log.debug('_grant_to_tokens lex analysis {0!r}'.format(exploded_grant))
#log.debug('_grant_to_tokens lex analysis \'{0}\''.format(exploded_grant))
for token in exploded_grant[position_tracker:]:
@ -455,12 +462,14 @@ def _grant_to_tokens(grant):
if not dict_mode:
user = user.strip("'")
host = host.strip("'")
log.debug('grant to token {0!r}::{1!r}::{2!r}::{3!r}'.format(
log.debug(
'grant to token \'{0}\'::\'{1}\'::\'{2}\'::\'{3}\''.format(
user,
host,
grant_tokens,
database
))
)
)
except UnboundLocalError:
host = ''
@ -836,7 +845,7 @@ def db_tables(name, **connection_args):
salt '*' mysql.db_tables 'database'
'''
if not db_exists(name, **connection_args):
log.info('Database {0!r} does not exist'.format(name,))
log.info('Database \'{0}\' does not exist'.format(name))
return False
dbc = _connect(**connection_args)
@ -914,7 +923,7 @@ def db_create(name, character_set=None, collate=None, **connection_args):
'''
# check if db exists
if db_exists(name, **connection_args):
log.info('DB {0!r} already exists'.format(name))
log.info('DB \'{0}\' already exists'.format(name))
return False
# db doesn't exist, proceed
@ -936,7 +945,7 @@ def db_create(name, character_set=None, collate=None, **connection_args):
try:
if _execute(cur, qry, args):
log.info('DB {0!r} created'.format(name))
log.info('DB \'{0}\' created'.format(name))
return True
except MySQLdb.OperationalError as exc:
err = 'MySQL Error {0}: {1}'.format(*exc)
@ -957,11 +966,11 @@ def db_remove(name, **connection_args):
'''
# check if db exists
if not db_exists(name, **connection_args):
log.info('DB {0!r} does not exist'.format(name))
log.info('DB \'{0}\' does not exist'.format(name))
return False
if name in ('mysql', 'information_scheme'):
log.info('DB {0!r} may not be removed'.format(name))
log.info('DB \'{0}\' may not be removed'.format(name))
return False
# db does exists, proceed
@ -981,10 +990,10 @@ def db_remove(name, **connection_args):
return False
if not db_exists(name, **connection_args):
log.info('Database {0!r} has been removed'.format(name))
log.info('Database \'{0}\' has been removed'.format(name))
return True
log.info('Database {0!r} has not been removed'.format(name))
log.info('Database \'{0}\' has not been removed'.format(name))
return False
@ -1166,7 +1175,7 @@ def user_create(user,
salt '*' mysql.user_create 'username' 'hostname' allow_passwordless=True
'''
if user_exists(user, host, **connection_args):
log.info('User {0!r}@{1!r} already exists'.format(user, host))
log.info('User \'{0}\'@\'{1}\' already exists'.format(user, host))
return False
dbc = _connect(**connection_args)
@ -1206,13 +1215,13 @@ def user_create(user,
return False
if user_exists(user, host, password, password_hash, **connection_args):
msg = 'User {0!r}@{1!r} has been created'.format(user, host)
msg = 'User \'{0}\'@\'{1}\' has been created'.format(user, host)
if not any((password, password_hash)):
msg += ' with passwordless login'
log.info(msg)
return True
log.info('User {0!r}@{1!r} was not created'.format(user, host))
log.info('User \'{0}\'@\'{1}\' was not created'.format(user, host))
return False
@ -1302,7 +1311,7 @@ def user_chpass(user,
if result:
_execute(cur, 'FLUSH PRIVILEGES;')
log.info(
'Password for user {0!r}@{1!r} has been {2}'.format(
'Password for user \'{0}\'@\'{1}\' has been {2}'.format(
user, host,
'changed' if any((password, password_hash)) else 'cleared'
)
@ -1310,7 +1319,7 @@ def user_chpass(user,
return True
log.info(
'Password for user {0!r}@{1!r} was not {2}'.format(
'Password for user \'{0}\'@\'{1}\' was not {2}'.format(
user, host,
'changed' if any((password, password_hash)) else 'cleared'
)
@ -1348,10 +1357,10 @@ def user_remove(user,
return False
if not user_exists(user, host, **connection_args):
log.info('User {0!r}@{1!r} has been removed'.format(user, host))
log.info('User \'{0}\'@\'{1}\' has been removed'.format(user, host))
return True
log.info('User {0!r}@{1!r} has NOT been removed'.format(user, host))
log.info('User \'{0}\'@\'{1}\' has NOT been removed'.format(user, host))
return False
@ -1391,11 +1400,11 @@ def db_check(name,
tables = db_tables(name, **connection_args)
for table in tables:
log.info(
'Checking table {0!r} in db {1!r}..'.format(name, table)
'Checking table \'{0}\' in db \'{1}\'..'.format(name, table)
)
ret.append(__check_table(name, table, **connection_args))
else:
log.info('Checking table {0!r} in db {1!r}..'.format(name, table))
log.info('Checking table \'{0}\' in db \'{1}\'..'.format(name, table))
ret = __check_table(name, table, **connection_args)
return ret
@ -1418,11 +1427,11 @@ def db_repair(name,
tables = db_tables(name, **connection_args)
for table in tables:
log.info(
'Repairing table {0!r} in db {1!r}..'.format(name, table)
'Repairing table \'{0}\' in db \'{1}\'..'.format(name, table)
)
ret.append(__repair_table(name, table, **connection_args))
else:
log.info('Repairing table {0!r} in db {1!r}..'.format(name, table))
log.info('Repairing table \'{0}\' in db \'{1}\'..'.format(name, table))
ret = __repair_table(name, table, **connection_args)
return ret
@ -1445,12 +1454,12 @@ def db_optimize(name,
tables = db_tables(name, **connection_args)
for table in tables:
log.info(
'Optimizing table {0!r} in db {1!r}..'.format(name, table)
'Optimizing table \'{0}\' in db \'{1}\'..'.format(name, table)
)
ret.append(__optimize_table(name, table, **connection_args))
else:
log.info(
'Optimizing table {0!r} in db {1!r}..'.format(name, table)
'Optimizing table \'{0}\' in db \'{1}\'..'.format(name, table)
)
ret = __optimize_table(name, table, **connection_args)
return ret
@ -1467,7 +1476,7 @@ def __grant_normalize(grant):
exploded_grants = grant.split(",")
for chkgrant in exploded_grants:
if chkgrant.strip().upper() not in __grants__:
raise Exception('Invalid grant : {0!r}'.format(
raise Exception('Invalid grant : \'{0}\''.format(
chkgrant
))
@ -1484,7 +1493,7 @@ def __ssl_option_sanitize(ssl_option):
normal_key = key.strip().upper()
if normal_key not in __ssl_options__:
raise Exception('Invalid SSL option : {0!r}'.format(
raise Exception('Invalid SSL option : \'{0}\''.format(
key
))
@ -1554,7 +1563,7 @@ def user_grants(user,
salt '*' mysql.user_grants 'frank' 'localhost'
'''
if not user_exists(user, host, **connection_args):
log.info('User {0!r}@{1!r} does not exist'.format(user, host))
log.info('User \'{0}\'@\'{1}\' does not exist'.format(user, host))
return False
dbc = _connect(**connection_args)
@ -1628,7 +1637,7 @@ def grant_exists(grant,
set(grant_tokens['grant']) == set(target_tokens['grant']):
return True
else:
log.debug('grants mismatch {0!r}<>{1!r}'.format(
log.debug('grants mismatch \'{0}\'<>\'{1}\''.format(
grant_tokens,
target_tokens
))
@ -1686,14 +1695,14 @@ def grant_add(grant,
grant, database, user, host, grant_option, escape,
**connection_args):
log.info(
'Grant {0!r} on {1!r} for user {2!r} has been added'.format(
'Grant \'{0}\' on \'{1}\' for user \'{2}\' has been added'.format(
grant, database, user
)
)
return True
log.info(
'Grant {0!r} on {1!r} for user {2!r} has NOT been added'.format(
'Grant \'{0}\' on \'{1}\' for user \'{2}\' has NOT been added'.format(
grant, database, user
)
)
@ -1767,13 +1776,13 @@ def grant_revoke(grant,
escape,
**connection_args):
log.info(
'Grant {0!r} on {1!r} for user {2!r} has been '
'Grant \'{0}\' on \'{1}\' for user \'{2}\' has been '
'revoked'.format(grant, database, user)
)
return True
log.info(
'Grant {0!r} on {1!r} for user {2!r} has NOT been '
'Grant \'{0}\' on \'{1}\' for user \'{2}\' has NOT been '
'revoked'.format(grant, database, user)
)
return False

View File

@ -25,6 +25,7 @@ except ImportError:
# Import salt libs
import salt.utils
import salt.utils.itertools
from salt.utils.decorators import which as _which
from salt.exceptions import (
@ -80,8 +81,10 @@ def latest_version(*names, **kwargs):
refresh_db()
cmd = ['opkg', 'list-upgradable']
out = __salt__['cmd.run_stdout'](cmd, output_loglevel='trace')
for line in out.splitlines():
out = __salt__['cmd.run_stdout'](cmd,
output_loglevel='trace',
python_shell=False)
for line in salt.utils.itertools.split(out, '\n'):
try:
name, _oldversion, newversion = line.split(' - ')
if name in names:
@ -133,8 +136,9 @@ def refresh_db():
'''
ret = {}
cmd = ['opkg', 'update']
call = __salt__['cmd.run_all'](cmd, output_loglevel='trace')
call = __salt__['cmd.run_all'](cmd,
output_loglevel='trace',
python_shell=False)
if call['retcode'] != 0:
comment = ''
if 'stderr' in call:
@ -146,7 +150,7 @@ def refresh_db():
else:
out = call['stdout']
for line in out.splitlines():
for line in salt.utils.itertools.split(out, '\n'):
if 'Inflating' in line:
key = line.strip().split()[1].split('.')[0]
ret[key] = True
@ -239,7 +243,7 @@ def install(name=None,
if refreshdb:
refresh_db()
__salt__['cmd.run'](cmd, output_loglevel='trace')
__salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False)
__context__.pop('pkg.list_pkgs', None)
new = list_pkgs()
return salt.utils.compare_dicts(old, new)
@ -281,7 +285,7 @@ def remove(name=None, pkgs=None, **kwargs): # pylint: disable=unused-argument
return {}
cmd = ['opkg', 'remove']
cmd.extend(targets)
__salt__['cmd.run'](cmd, output_loglevel='trace')
__salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False)
__context__.pop('pkg.list_pkgs', None)
new = list_pkgs()
return salt.utils.compare_dicts(old, new)
@ -342,7 +346,9 @@ def upgrade(refresh=True):
old = list_pkgs()
cmd = ['opkg', 'upgrade']
call = __salt__['cmd.run_all'](cmd, output_loglevel='trace')
call = __salt__['cmd.run_all'](cmd,
output_loglevel='trace',
python_shell=False)
if call['retcode'] != 0:
ret['result'] = False
@ -508,9 +514,9 @@ def _get_state(pkg):
'''
cmd = ['opkg', 'status']
cmd.append(pkg)
out = __salt__['cmd.run'](cmd)
out = __salt__['cmd.run'](cmd, python_shell=False)
state_flag = ''
for line in out.splitlines():
for line in salt.utils.itertools.split(out, '\n'):
if line.startswith('Status'):
_status, _state_want, state_flag, _state_status = line.split()
@ -546,7 +552,7 @@ def _set_state(pkg, state):
cmd = ['opkg', 'flag']
cmd.append(state)
cmd.append(pkg)
_out = __salt__['cmd.run'](cmd)
_out = __salt__['cmd.run'](cmd, python_shell=False)
# Missing return value check due to opkg issue 160
ret[pkg] = {'old': oldstate,
@ -583,8 +589,8 @@ def list_pkgs(versions_as_list=False, **kwargs):
cmd = ['opkg', 'list-installed']
ret = {}
out = __salt__['cmd.run'](cmd, output_loglevel='trace')
for line in out.splitlines():
out = __salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False)
for line in salt.utils.itertools.split(out, '\n'):
pkg_name, pkg_version = line.split(' - ')
__salt__['pkg_resource.add_pkg'](ret, pkg_name, pkg_version)
@ -610,7 +616,9 @@ def list_upgrades(refresh=True):
refresh_db()
cmd = ['opkg', 'list-upgradable']
call = __salt__['cmd.run_all'](cmd, output_loglevel='trace')
call = __salt__['cmd.run_all'](cmd,
output_loglevel='trace',
python_shell=False)
if call['retcode'] != 0:
comment = ''
@ -663,9 +671,10 @@ def version_cmp(pkg1, pkg2):
cmd.append(_cmd_quote(pkg1))
cmd.append(oper)
cmd.append(_cmd_quote(pkg2))
retcode = __salt__['cmd.retcode'](
cmd, output_loglevel='trace', ignore_retcode=True
)
retcode = __salt__['cmd.retcode'](cmd,
output_loglevel='trace',
ignore_retcode=True,
python_shell=False)
if retcode == 0:
return ret
return None
@ -803,9 +812,9 @@ def del_repo(alias):
if source['file'] in deleted_from:
deleted_from[source['file']] += 1
for repo_file, count in six.iteritems(deleted_from):
msg = 'Repo {0!r} has been removed from {1}.\n'
msg = 'Repo \'{0}\' has been removed from {1}.\n'
if count == 1 and os.path.isfile(repo_file):
msg = ('File {1} containing repo {0!r} has been '
msg = ('File {1} containing repo \'{0}\' has been '
'removed.\n')
try:
os.remove(repo_file)
@ -930,7 +939,9 @@ def file_dict(*packages):
files = []
cmd = cmd_files[:]
cmd.append(package)
out = __salt__['cmd.run_all'](cmd, output_loglevel='trace')
out = __salt__['cmd.run_all'](cmd,
output_loglevel='trace',
python_shell=False)
for line in out['stdout'].splitlines():
if line.startswith('/'):
files.append(line)
@ -966,8 +977,10 @@ def owner(*paths):
cmd_search = ['opkg', 'search']
for path in paths:
cmd = cmd_search[:]
cmd.append(_cmd_quote(path))
output = __salt__['cmd.run_stdout'](cmd, output_loglevel='trace')
cmd.append(path)
output = __salt__['cmd.run_stdout'](cmd,
output_loglevel='trace',
python_shell=False)
if output:
ret[path] = output.split(' - ')[0].strip()
else:

View File

@ -12,6 +12,7 @@ import re
# Import salt libs
import salt.utils
import salt.utils.itertools
from salt.exceptions import CommandExecutionError, MinionError
# Import 3rd-party libs
@ -68,10 +69,12 @@ def latest_version(*names, **kwargs):
# Initialize the dict with empty strings
for name in names:
ret[name] = ''
cmd = 'pacman -Sp --needed --print-format "%n %v" ' \
'{0}'.format(' '.join(names))
out = __salt__['cmd.run_stdout'](cmd, output_loglevel='trace')
for line in out.splitlines():
cmd = ['pacman', '-Sp', '--needed', '--print-format', '%n %v']
cmd.extend(names)
out = __salt__['cmd.run_stdout'](cmd,
output_loglevel='trace',
python_shell=False)
for line in salt.utils.itertools.split(out, '\n'):
try:
name, version_num = line.split()
# Only add to return dict if package is in the list of packages
@ -123,14 +126,14 @@ def list_upgrades(refresh=False):
salt '*' pkg.list_upgrades
'''
upgrades = {}
options = ['-S', '-p', '-u', '--print-format "%n %v"']
cmd = ['pacman', '-S', '-p', '-u', '--print-format', '%n %v']
if refresh:
options.append('-y')
cmd.append('-y')
cmd = ('pacman {0}').format(' '.join(options))
call = __salt__['cmd.run_all'](cmd, output_loglevel='trace')
call = __salt__['cmd.run_all'](cmd,
output_loglevel='trace',
python_shell=False)
if call['retcode'] != 0:
comment = ''
@ -138,13 +141,13 @@ def list_upgrades(refresh=False):
comment += call['stderr']
if 'stdout' in call:
comment += call['stdout']
raise CommandExecutionError(
'{0}'.format(comment)
)
if comment:
comment = ': ' + comment
raise CommandExecutionError('Error listing upgrades' + comment)
else:
out = call['stdout']
for line in iter(out.splitlines()):
for line in salt.utils.itertools.split(out, '\n'):
comps = line.split(' ')
if len(comps) != 2:
continue
@ -194,17 +197,17 @@ def list_pkgs(versions_as_list=False, **kwargs):
__salt__['pkg_resource.stringify'](ret)
return ret
cmd = 'pacman -Q'
cmd = ['pacman', '-Q']
ret = {}
out = __salt__['cmd.run'](cmd, output_loglevel='trace')
for line in out.splitlines():
out = __salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False)
for line in salt.utils.itertools.split(out, '\n'):
if not line:
continue
try:
name, version_num = line.split()[0:2]
except ValueError:
log.error('Problem parsing pacman -Q: Unexpected formatting in '
'line: "{0}"'.format(line))
'line: \'{0}\''.format(line))
else:
__salt__['pkg_resource.add_pkg'](ret, name, version_num)
@ -227,22 +230,23 @@ def refresh_db():
salt '*' pkg.refresh_db
'''
cmd = 'LANG=C pacman -Sy'
cmd = ['pacman', '-Sy']
ret = {}
call = __salt__['cmd.run_all'](cmd, output_loglevel='trace',
python_shell=True)
call = __salt__['cmd.run_all'](cmd,
output_loglevel='trace',
env={'LANG': 'C'},
python_shell=False)
if call['retcode'] != 0:
comment = ''
if 'stderr' in call:
comment += call['stderr']
comment += ': ' + call['stderr']
raise CommandExecutionError(
'{0}'.format(comment)
'Error refreshing package database' + comment
)
else:
out = call['stdout']
for line in out.splitlines():
for line in salt.utils.itertools.split(out, '\n'):
if line.strip().startswith('::'):
continue
if not line:
@ -335,16 +339,14 @@ def install(name=None,
version_num = kwargs.get('version')
if version_num:
if pkgs is None and sources is None:
# Allow "version" to work for single package target
# Allow 'version' to work for single package target
pkg_params = {name: version_num}
else:
log.warning('"version" parameter will be ignored for multiple '
log.warning('\'version\' parameter will be ignored for multiple '
'package targets')
if pkg_type == 'file':
cmd = 'pacman -U --noprogressbar --noconfirm ' \
'{0}'.format(' '.join(pkg_params))
targets = pkg_params
cmd = ['pacman', '-U', '--noprogressbar', '--noconfirm'] + pkg_params
elif pkg_type == 'repository':
targets = []
problems = []
@ -362,8 +364,8 @@ def install(name=None,
prefix = prefix or '='
targets.append('{0}{1}{2}'.format(param, prefix, verstr))
else:
msg = 'Invalid version string "{0}" for package ' \
'"{1}"'.format(version_num, name)
msg = 'Invalid version string \'{0}\' for package ' \
'\'{1}\''.format(version_num, name)
problems.append(msg)
if problems:
for problem in problems:
@ -375,10 +377,10 @@ def install(name=None,
if salt.utils.is_true(sysupgrade):
options.append('-u')
cmd = 'pacman -S "{0}"'.format('" "'.join(options+targets))
cmd = ['pacman', '-S'] + options + targets
old = list_pkgs()
__salt__['cmd.run'](cmd, output_loglevel='trace')
__salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False)
__context__.pop('pkg.list_pkgs', None)
new = list_pkgs()
return salt.utils.compare_dicts(old, new)
@ -404,14 +406,15 @@ def upgrade(refresh=False):
'''
ret = {'changes': {},
'result': True,
'comment': '',
}
'comment': ''}
old = list_pkgs()
cmd = 'pacman -Su --noprogressbar --noconfirm'
cmd = ['pacman', '-Su', '--noprogressbar', '--noconfirm']
if salt.utils.is_true(refresh):
cmd += ' -y'
call = __salt__['cmd.run_all'](cmd, output_loglevel='trace')
cmd.append('-y')
call = __salt__['cmd.run_all'](cmd,
output_loglevel='trace',
python_shell=False)
if call['retcode'] != 0:
ret['result'] = False
if 'stderr' in call:
@ -439,13 +442,11 @@ def _uninstall(action='remove', name=None, pkgs=None, **kwargs):
targets = [x for x in pkg_params if x in old]
if not targets:
return {}
remove_arg = '-Rsc' if action == 'purge' else '-R'
cmd = (
'pacman {0} '
'--noprogressbar '
'--noconfirm {1}'
).format(remove_arg, ' '.join(targets))
__salt__['cmd.run'](cmd, output_loglevel='trace')
cmd = ['pacman',
'-Rsc' if action == 'purge' else '-R',
'--noprogressbar',
'--noconfirm'] + targets
__salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False)
__context__.pop('pkg.list_pkgs', None)
new = list_pkgs()
return salt.utils.compare_dicts(old, new)
@ -528,9 +529,10 @@ def file_list(*packages):
'''
errors = []
ret = []
cmd = 'pacman -Ql {0}'.format(' '.join(packages))
out = __salt__['cmd.run'](cmd, output_loglevel='trace')
for line in out.splitlines():
cmd = ['pacman', '-Ql']
cmd.extend(packages)
out = __salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False)
for line in salt.utils.itertools.split(out, '\n'):
if line.startswith('error'):
errors.append(line)
else:
@ -555,9 +557,10 @@ def file_dict(*packages):
'''
errors = []
ret = {}
cmd = 'pacman -Ql {0}'.format(' '.join(packages))
out = __salt__['cmd.run'](cmd, output_loglevel='trace')
for line in out.splitlines():
cmd = ['pacman', '-Ql']
cmd.extend(packages)
out = __salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False)
for line in salt.utils.itertools.split(out, '\n'):
if line.startswith('error'):
errors.append(line)
else:
@ -588,9 +591,10 @@ def owner(*paths):
if not paths:
return ''
ret = {}
cmd = 'pacman -Qqo {0!r}'
cmd_prefix = ['pacman', '-Qqo']
for path in paths:
ret[path] = __salt__['cmd.run_stdout'](cmd.format(path))
ret[path] = __salt__['cmd.run_stdout'](cmd_prefix + [path],
python_shell=False)
if len(ret) == 1:
return next(six.itervalues(ret))
return ret

View File

@ -74,11 +74,11 @@ def _pkg(jail=None, chroot=None):
Returns the prefix for a pkg command, using -j if a jail is specified, or
-c if chroot is specified.
'''
ret = 'pkg'
ret = ['pkg']
if jail:
ret += ' -j {0!r}'.format(jail)
ret.extend(['-j', jail])
elif chroot:
ret += ' -c {0!r}'.format(chroot)
ret.extend(['-c', chroot])
return ret
@ -94,7 +94,7 @@ def _get_version(name, results):
``pkg search`` will return all packages for which the pattern is a match.
Narrow this down and return the package version, or None if no exact match.
'''
for line in results.splitlines():
for line in salt.utils.itertools.split(results, '\n'):
if not line:
continue
try:
@ -228,12 +228,11 @@ def refresh_db(jail=None, chroot=None, force=False):
salt '*' pkg.refresh_db force=True
'''
opts = ''
cmd = _pkg(jail, chroot)
cmd.append('update')
if force:
opts += ' -f'
return __salt__['cmd.retcode'](
'{0} update{1}'.format(_pkg(jail, chroot), opts),
python_shell=False) == 0
cmd.append('-f')
return __salt__['cmd.retcode'](cmd, python_shell=False) == 0
# Support pkg.update to refresh the db, since this is the CLI usage
@ -273,6 +272,7 @@ def latest_version(*names, **kwargs):
else:
quiet = False
cmd_prefix = _pkg(jail, chroot) + ['search']
for name in names:
cmd = [_pkg(jail, chroot), 'search']
if quiet:
@ -281,7 +281,9 @@ def latest_version(*names, **kwargs):
pkgver = _get_version(
name,
__salt__['cmd.run'](cmd, python_shell=False, output_loglevel='trace')
__salt__['cmd.run'](cmd_prefix + [name],
output_loglevel='trace',
python_shell=False)
)
if pkgver is not None:
installed = pkgs.get(name, [])
@ -360,12 +362,11 @@ def list_pkgs(versions_as_list=False,
ret = {}
origins = {}
cmd = '{0} info -ao'.format(_pkg(jail, chroot))
out = __salt__['cmd.run_stdout'](
cmd,
python_shell=False,
output_loglevel='trace')
for line in out.splitlines():
_pkg(jail, chroot) + ['info', '-ao'],
output_loglevel='trace',
python_shell=False)
for line in salt.utils.itertools.split(out, '\n'):
if not line:
continue
try:
@ -467,16 +468,13 @@ def stats(local=False, remote=False, jail=None, chroot=None):
opts += 'l'
if remote:
opts += 'r'
if opts:
opts = '-' + opts
res = __salt__['cmd.run'](
'{0} stats {1}'.format(_pkg(jail, chroot), opts),
python_shell=False,
output_loglevel='trace'
)
res = [x.strip("\t") for x in res.split("\n")]
return res
cmd = _pkg(jail, chroot)
cmd.append('stats')
if opts:
cmd.append('-' + opts)
out = __salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False)
return [x.strip('\t') for x in salt.utils.itertools.split(out, '\n')]
def backup(file_name, jail=None, chroot=None):
@ -512,12 +510,12 @@ def backup(file_name, jail=None, chroot=None):
salt '*' pkg.backup /tmp/pkg chroot=/path/to/chroot
'''
res = __salt__['cmd.run'](
'{0} backup -d {1!r}'.format(_pkg(jail, chroot), file_name),
python_shell=False,
output_loglevel='trace'
ret = __salt__['cmd.run'](
_pkg(jail, chroot) + ['backup', '-d', file_name],
output_loglevel='trace',
python_shell=False
)
return res.split('...')[1]
return ret.split('...')[1]
def restore(file_name, jail=None, chroot=None):
@ -554,9 +552,9 @@ def restore(file_name, jail=None, chroot=None):
salt '*' pkg.restore /tmp/pkg chroot=/path/to/chroot
'''
return __salt__['cmd.run'](
'{0} backup -r {1!r}'.format(_pkg(jail, chroot), file_name),
python_shell=False,
output_loglevel='trace'
_pkg(jail, chroot) + ['backup', '-r', file_name],
output_loglevel='trace',
python_shell=False
)
@ -590,9 +588,9 @@ def audit(jail=None, chroot=None):
salt '*' pkg.audit chroot=/path/to/chroot
'''
return __salt__['cmd.run'](
'{0} audit -F'.format(_pkg(jail, chroot)),
python_shell=False,
output_loglevel='trace'
_pkg(jail, chroot) + ['audit', '-F'],
output_loglevel='trace',
python_shell=False
)
@ -743,7 +741,6 @@ def install(name=None,
return {}
opts = ''
repo_opts = ''
if salt.utils.is_true(orphan):
opts += 'A'
if salt.utils.is_true(force):
@ -760,16 +757,10 @@ def install(name=None,
opts += 'q'
if salt.utils.is_true(reinstall_requires):
opts += 'R'
if fromrepo:
repo_opts += 'r {0}'.format(fromrepo)
if salt.utils.is_true(regex):
opts += 'x'
if salt.utils.is_true(pcre):
opts += 'X'
if opts:
opts = '-' + opts
if repo_opts:
repo_opts = '-' + repo_opts
old = list_pkgs(jail=jail, chroot=chroot)
@ -791,15 +782,19 @@ def install(name=None,
else:
targets.append('{0}-{1}'.format(param, version_num))
cmd = '{0} {1} {2} {3} {4}'.format(
_pkg(jail, chroot), pkg_cmd, repo_opts, opts, ' '.join(targets)
)
cmd = _pkg(jail, chroot)
cmd.append(pkg_cmd)
if fromrepo:
cmd.extend(['-r', fromrepo])
if opts:
cmd.append('-' + opts)
cmd.extend(targets)
if pkg_cmd == 'add' and salt.utils.is_true(dryrun):
# pkg add doesn't have a dryrun mode, so echo out what will be run
return cmd
return ' '.join(cmd)
__salt__['cmd.run'](cmd, python_shell=False, output_loglevel='trace')
__salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False)
__context__.pop(_contextkey(jail, chroot), None)
__context__.pop(_contextkey(jail, chroot, prefix='pkg.origin'), None)
new = list_pkgs(jail=jail, chroot=chroot)
@ -944,13 +939,13 @@ def remove(name=None,
opts += 'x'
if salt.utils.is_true(pcre):
opts += 'X'
if opts:
opts = '-' + opts
cmd = '{0} delete {1} {2}'.format(
_pkg(jail, chroot), opts, ' '.join(targets)
)
__salt__['cmd.run'](cmd, python_shell=False, output_loglevel='trace')
cmd = _pkg(jail, chroot)
cmd.append('delete')
if opts:
cmd.append('-' + opts)
cmd.extend(targets)
__salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False)
__context__.pop(_contextkey(jail, chroot), None)
__context__.pop(_contextkey(jail, chroot, prefix='pkg.origin'), None)
new = list_pkgs(jail=jail, chroot=chroot, with_origin=True)
@ -1048,11 +1043,17 @@ def upgrade(*names, **kwargs):
if opts:
opts = '-' + opts
cmd = _pkg(jail, chroot)
cmd.append('upgrade')
if opts:
cmd.append('-' + opts)
cmd.extend(names)
old = list_pkgs()
call = __salt__['cmd.run_all'](
'{0} upgrade {1} {2}'.format(_pkg(jail, chroot), opts, ' '.join(names)),
python_shell=False,
output_loglevel='trace'
cmd,
output_loglevel='trace',
python_shell=False
)
if call['retcode'] != 0:
ret['result'] = False
@ -1080,9 +1081,9 @@ def clean(jail=None, chroot=None):
salt '*' pkg.clean chroot=/path/to/chroot
'''
return __salt__['cmd.run'](
'{0} clean'.format(_pkg(jail, chroot)),
python_shell=False,
output_loglevel='trace'
_pkg(jail, chroot) + ['clean'],
output_loglevel='trace',
python_shell=False
)
@ -1109,12 +1110,15 @@ def autoremove(jail=None, chroot=None, dryrun=False):
opts += 'n'
else:
opts += 'y'
cmd = _pkg(jail, chroot)
cmd.append('autoremove')
if opts:
opts = '-' + opts
cmd.append('-' + opts)
return __salt__['cmd.run'](
'{0} autoremove {1}'.format(_pkg(jail, chroot), opts),
python_shell=False,
output_loglevel='trace'
cmd,
output_loglevel='trace',
python_shell=False
)
@ -1185,13 +1189,15 @@ def check(jail=None,
opts += 'r'
if checksum:
opts += 's'
if opts:
opts = '-' + opts
cmd = _pkg(jail, chroot)
cmd.append('check')
if opts:
cmd.append('-' + opts)
return __salt__['cmd.run'](
'{0} check {1}'.format(_pkg(jail, chroot), opts),
python_shell=False,
output_loglevel='trace'
cmd,
output_loglevel='trace',
python_shell=False
)
@ -1248,12 +1254,16 @@ def which(path, jail=None, chroot=None, origin=False, quiet=False):
opts += 'q'
if origin:
opts += 'o'
cmd = _pkg(jail, chroot)
cmd.append('which')
if opts:
opts = '-' + opts
cmd.append('-' + opts)
cmd.append(path)
return __salt__['cmd.run'](
'{0} which {1} {2}'.format(_pkg(jail, chroot), opts, path),
python_shell=False,
output_loglevel='trace'
cmd,
output_loglevel='trace',
python_shell=False
)
@ -1435,13 +1445,16 @@ def search(name,
opts += 'o'
if prefix:
opts += 'p'
if opts:
opts = '-' + opts
cmd = _pkg(jail, chroot)
cmd.append('search')
if opts:
cmd.append('-' + opts)
cmd.append(name)
return __salt__['cmd.run'](
'{0} search {1} {2}'.format(_pkg(jail, chroot), opts, name),
python_shell=False,
output_loglevel='trace'
cmd,
output_loglevel='trace',
python_shell=False
)
@ -1559,13 +1572,10 @@ def fetch(name,
salt '*' pkg.fetch <package name> depends=True
'''
opts = ''
repo_opts = ''
if fetch_all:
opts += 'a'
if quiet:
opts += 'q'
if fromrepo:
repo_opts += 'r {0}'.format(fromrepo)
if glob:
opts += 'g'
if regex:
@ -1576,17 +1586,18 @@ def fetch(name,
opts += 'L'
if depends:
opts += 'd'
if opts:
opts = '-' + opts
if repo_opts:
repo_opts = '-' + repo_opts
cmd = _pkg(jail, chroot)
cmd.extend(['fetch', '-y'])
if fromrepo:
cmd.extend(['-r', fromrepo])
if opts:
cmd.append('-' + opts)
cmd.append(name)
return __salt__['cmd.run'](
'{0} fetch -y {1} {2} {3}'.format(
_pkg(jail, chroot), opts, repo_opts, name
),
python_shell=False,
output_loglevel='trace'
cmd,
output_loglevel='trace',
python_shell=False
)
@ -1647,11 +1658,14 @@ def updating(name,
opts += 'd {0}'.format(filedate)
if filename:
opts += 'f {0}'.format(filename)
if opts:
opts = '-' + opts
cmd = _pkg(jail, chroot)
cmd.append('updating')
if opts:
cmd.append('-' + opts)
cmd.append(name)
return __salt__['cmd.run'](
'{0} updating {1} {2}'.format(_pkg(jail, chroot), opts, name),
python_shell=False,
output_loglevel='trace'
cmd,
output_loglevel='trace',
python_shell=False
)

View File

@ -33,14 +33,14 @@ import hashlib
import os
import tempfile
try:
import pipes
import csv
HAS_ALL_IMPORTS = True
HAS_CSV = True
except ImportError:
HAS_ALL_IMPORTS = False
HAS_CSV = False
# Import salt libs
import salt.utils
import salt.utils.itertools
# Import 3rd-party libs
import salt.ext.six as six
@ -68,7 +68,7 @@ def __virtual__():
'''
Only load this module if the psql bin exists
'''
if all((salt.utils.which('psql'), HAS_ALL_IMPORTS)):
if all((salt.utils.which('psql'), HAS_CSV)):
return True
return False
@ -146,7 +146,8 @@ def version(user=None, host=None, port=None, maintenance_db=None,
ret = _run_psql(
cmd, runas=runas, password=password, host=host, port=port, user=user)
for line in ret['stdout'].splitlines():
for line in salt.utils.itertools.split(ret['stdout'], '\n'):
# Just return the first line
return line
@ -221,10 +222,9 @@ def _psql_cmd(*args, **kwargs):
cmd += ['--port', str(port)]
if not maintenance_db:
maintenance_db = 'postgres'
cmd += ['--dbname', maintenance_db]
cmd += args
cmdstr = ' '.join([pipes.quote(c) for c in cmd])
return cmdstr
cmd.extend(['--dbname', maintenance_db])
cmd.extend(args)
return cmd
def _psql_prepare_and_run(cmd,
@ -377,9 +377,9 @@ def db_create(name,
# doesn't get thrown by dashes in the name
'OWNER': owner and '"{0}"'.format(owner),
'TEMPLATE': template,
'ENCODING': encoding and '{0!r}'.format(encoding),
'LC_COLLATE': lc_collate and '{0!r}'.format(lc_collate),
'LC_CTYPE': lc_ctype and '{0!r}'.format(lc_ctype),
'ENCODING': encoding and '\'{0}\''.format(encoding),
'LC_COLLATE': lc_collate and '\'{0}\''.format(lc_collate),
'LC_CTYPE': lc_ctype and '\'{0}\''.format(lc_ctype),
'TABLESPACE': tablespace,
})
with_chunks = []
@ -878,7 +878,7 @@ def _role_cmd_args(name,
):
skip_passwd = True
if isinstance(rolepassword, six.string_types) and bool(rolepassword):
escaped_password = '{0!r}'.format(
escaped_password = '\'{0}\''.format(
_maybe_encrypt_password(name,
rolepassword.replace('\'', '\'\''),
encrypted=encrypted))
@ -943,7 +943,7 @@ def _role_create(name,
# check if role exists
if user_exists(name, user, host, port, maintenance_db,
password=password, runas=runas):
log.info('{0} {1!r} already exists'.format(typ_.capitalize(), name))
log.info('{0} \'{1}\' already exists'.format(typ_.capitalize(), name))
return False
sub_cmd = 'CREATE ROLE "{0}" WITH'.format(name)
@ -1053,7 +1053,9 @@ def _role_update(name,
# check if user exists
if not bool(role):
log.info('{0} {1!r} could not be found'.format(typ_.capitalize(), name))
log.info(
'{0} \'{1}\' could not be found'.format(typ_.capitalize(), name)
)
return False
sub_cmd = 'ALTER ROLE "{0}" WITH'.format(name)
@ -1139,7 +1141,7 @@ def _role_remove(name, user=None, host=None, port=None, maintenance_db=None,
# check if user exists
if not user_exists(name, user, host, port, maintenance_db,
password=password, runas=runas):
log.info('User {0!r} does not exist'.format(name))
log.info('User \'{0}\' does not exist'.format(name))
return False
# user exists, proceed
@ -1153,7 +1155,7 @@ def _role_remove(name, user=None, host=None, port=None, maintenance_db=None,
password=password, runas=runas):
return True
else:
log.info('Failed to delete user {0!r}.'.format(name))
log.info('Failed to delete user \'{0}\'.'.format(name))
return False
@ -1779,7 +1781,7 @@ def schema_create(dbname, name, owner=None,
if schema_exists(dbname, name,
db_user=db_user, db_password=db_password,
db_host=db_host, db_port=db_port):
log.info('{0!r} already exists in {1!r}'.format(name, dbname))
log.info('\'{0}\' already exists in \'{1}\''.format(name, dbname))
return False
sub_cmd = 'CREATE SCHEMA {0}'.format(name)
@ -1834,7 +1836,7 @@ def schema_remove(dbname, name,
if not schema_exists(dbname, name,
db_user=db_user, db_password=db_password,
db_host=db_host, db_port=db_port):
log.info('Schema {0!r} does not exist in {1!r}'.format(name, dbname))
log.info('Schema \'{0}\' does not exist in \'{1}\''.format(name, dbname))
return False
# schema exists, proceed
@ -1850,7 +1852,7 @@ def schema_remove(dbname, name,
db_host=db_host, db_port=db_port):
return True
else:
log.info('Failed to delete schema {0!r}.'.format(name))
log.info('Failed to delete schema \'{0}\'.'.format(name))
return False

View File

@ -75,7 +75,7 @@ def _publish(
arg = _parse_args(arg)
log.info('Publishing {0!r} to {master_uri}'.format(fun, **__opts__))
log.info('Publishing \'{0}\' to {master_uri}'.format(fun, **__opts__))
auth = salt.crypt.SAuth(__opts__)
tok = auth.gen_token('salt')
load = {'cmd': 'minion_pub',
@ -93,7 +93,7 @@ def _publish(
try:
peer_data = channel.send(load)
except SaltReqTimeoutError:
return '{0!r} publish timed out'.format(fun)
return '\'{0}\' publish timed out'.format(fun)
if not peer_data:
return {}
# CLI args are passed as strings, re-cast to keep time.sleep happy
@ -263,7 +263,7 @@ def runner(fun, arg=None, timeout=5):
if 'master_uri' not in __opts__:
return 'No access to master. If using salt-call with --local, please remove.'
log.info('Publishing runner {0!r} to {master_uri}'.format(fun, **__opts__))
log.info('Publishing runner \'{0}\' to {master_uri}'.format(fun, **__opts__))
auth = salt.crypt.SAuth(__opts__)
tok = auth.gen_token('salt')
load = {'cmd': 'minion_runner',
@ -277,4 +277,4 @@ def runner(fun, arg=None, timeout=5):
try:
return channel.send(load)
except SaltReqTimeoutError:
return '{0!r} runner publish timed out'.format(fun)
return '\'{0}\' runner publish timed out'.format(fun)

View File

@ -63,7 +63,12 @@ def _get_gecos(name):
'''
Retrieve GECOS field info and return it in dictionary form
'''
try:
gecos_field = pwd.getpwnam(name).pw_gecos.split(',', 3)
except KeyError:
raise CommandExecutionError(
'User \'{0}\' does not exist'.format(name)
)
if not gecos_field:
return {}
else:
@ -87,6 +92,25 @@ def _build_gecos(gecos_dict):
gecos_dict.get('homephone', ''))
def _update_gecos(name, key, value):
'''
Common code to change a user's GECOS information
'''
if not isinstance(value, six.string_types):
value = str(value)
pre_info = _get_gecos(name)
if not pre_info:
return False
if value == pre_info[key]:
return True
gecos_data = copy.deepcopy(pre_info)
gecos_data[key] = value
cmd = ['pw', 'usermod', name, '-c', _build_gecos(gecos_data)]
__salt__['cmd.run'](cmd, python_shell=False)
post_info = info(name)
return _get_gecos(name).get(key) == value
def add(name,
uid=None,
gid=None,
@ -118,32 +142,30 @@ def add(name,
if isinstance(groups, six.string_types):
groups = groups.split(',')
cmd = 'pw useradd '
cmd = ['pw', 'useradd']
if uid:
cmd += '-u {0} '.format(uid)
cmd.extend(['-u', uid])
if gid:
cmd += '-g {0} '.format(gid)
cmd.extend(['-g', gid])
if groups:
cmd += '-G {0} '.format(','.join(groups))
cmd.extend(['-G', ','.join(groups)])
if home is not None:
cmd += '-d {0} '.format(home)
cmd.extend(['-d', home])
if createhome is True:
cmd += '-m '
cmd.append('-m')
if loginclass:
cmd += '-L {0}'.format(loginclass)
cmd.extend(['-L', loginclass])
if shell:
cmd += '-s {0} '.format(shell)
cmd.extend(['-s', shell])
if not salt.utils.is_true(unique):
cmd += '-o '
gecos_field = '{0},{1},{2},{3}'.format(fullname,
roomnumber,
workphone,
homephone)
cmd += '-c "{0}" '.format(gecos_field)
cmd += '-n {0}'.format(name)
ret = __salt__['cmd.run_all'](cmd, python_shell=False)
return not ret['retcode']
cmd.append('-o')
gecos_field = _build_gecos({'fullname': fullname,
'roomnumber': roomnumber,
'workphone': workphone,
'homephone': homephone})
cmd.extend(['-c', gecos_field])
cmd.extend(['-n', name])
return __salt__['cmd.retcode'](cmd, python_shell=False) == 0
def delete(name, remove=False, force=False):
@ -159,14 +181,11 @@ def delete(name, remove=False, force=False):
if salt.utils.is_true(force):
log.error('pw userdel does not support force-deleting user while '
'user is logged in')
cmd = 'pw userdel '
cmd = ['pw', 'userdel']
if remove:
cmd += '-r '
cmd += '-n ' + name
ret = __salt__['cmd.run_all'](cmd, python_shell=False)
return not ret['retcode']
cmd.append('-r')
cmd.extend(['-n', name])
return __salt__['cmd.retcode'](cmd, python_shell=False) == 0
def getent(refresh=False):
@ -200,14 +219,15 @@ def chuid(name, uid):
salt '*' user.chuid foo 4376
'''
pre_info = info(name)
if not pre_info:
raise CommandExecutionError(
'User \'{0}\' does not exist'.format(name)
)
if uid == pre_info['uid']:
return True
cmd = 'pw usermod -u {0} -n {1}'.format(uid, name)
cmd = ['pw', 'usermod', '-u', uid, '-n', name]
__salt__['cmd.run'](cmd, python_shell=False)
post_info = info(name)
if post_info['uid'] != pre_info['uid']:
return post_info['uid'] == uid
return False
return info(name).get('uid') == uid
def chgid(name, gid):
@ -221,14 +241,15 @@ def chgid(name, gid):
salt '*' user.chgid foo 4376
'''
pre_info = info(name)
if not pre_info:
raise CommandExecutionError(
'User \'{0}\' does not exist'.format(name)
)
if gid == pre_info['gid']:
return True
cmd = 'pw usermod -g {0} -n {1}'.format(gid, name)
cmd = ['pw', 'usermod', '-g', gid, '-n', name]
__salt__['cmd.run'](cmd, python_shell=False)
post_info = info(name)
if post_info['gid'] != pre_info['gid']:
return post_info['gid'] == gid
return False
return info(name).get('gid') == gid
def chshell(name, shell):
@ -242,20 +263,31 @@ def chshell(name, shell):
salt '*' user.chshell foo /bin/zsh
'''
pre_info = info(name)
if not pre_info:
raise CommandExecutionError(
'User \'{0}\' does not exist'.format(name)
)
if shell == pre_info['shell']:
return True
cmd = 'pw usermod -s {0} -n {1}'.format(shell, name)
cmd = ['pw', 'usermod', '-s', shell, '-n', name]
__salt__['cmd.run'](cmd, python_shell=False)
post_info = info(name)
if post_info['shell'] != pre_info['shell']:
return post_info['shell'] == shell
return False
return info(name).get('shell') == shell
def chhome(name, home, persist=False):
'''
Change the home directory of the user, pass true for persist to copy files
to the new home dir
Set a new home directory for an existing user
name
Username to modify
home
New home directory to set
persist : False
Set to ``True`` to prevent configuration files in the new home
directory from being overwritten by the files from the skeleton
directory.
CLI Example:
@ -264,22 +296,34 @@ def chhome(name, home, persist=False):
salt '*' user.chhome foo /home/users/foo True
'''
pre_info = info(name)
if not pre_info:
raise CommandExecutionError(
'User \'{0}\' does not exist'.format(name)
)
if home == pre_info['home']:
return True
cmd = 'pw usermod {0} -d {1}'.format(name, home)
cmd = ['pw', 'usermod', name, '-d', home]
if persist:
cmd += ' -m '
cmd.append('-m')
__salt__['cmd.run'](cmd, python_shell=False)
post_info = info(name)
if post_info['home'] != pre_info['home']:
return post_info['home'] == home
return False
return info(name).get('home') == home
def chgroups(name, groups, append=False):
'''
Change the groups this user belongs to, add append to append the specified
Change the groups to which a user belongs
name
Username to modify
groups
List of groups to set for the user. Can be passed as a comma-separated
list or a Python list.
append : False
Set to ``True`` to append these groups to the user's existing list of
groups. Otherwise, the specified groups will replace any existing
groups for the user.
CLI Example:
@ -294,8 +338,8 @@ def chgroups(name, groups, append=False):
return True
if append:
groups += ugrps
cmd = 'pw usermod -G {0} -n {1}'.format(','.join(groups), name)
return not __salt__['cmd.retcode'](cmd, python_shell=False)
cmd = ['pw', 'usermod', '-G', ','.join(groups), '-n', name]
return __salt__['cmd.retcode'](cmd, python_shell=False) == 0
def chfullname(name, fullname):
@ -308,20 +352,7 @@ def chfullname(name, fullname):
salt '*' user.chfullname foo "Foo Bar"
'''
fullname = str(fullname)
pre_info = _get_gecos(name)
if not pre_info:
return False
if fullname == pre_info['fullname']:
return True
gecos_field = copy.deepcopy(pre_info)
gecos_field['fullname'] = fullname
cmd = 'pw usermod {0} -c "{1}"'.format(name, _build_gecos(gecos_field))
__salt__['cmd.run'](cmd, python_shell=False)
post_info = info(name)
if post_info['fullname'] != pre_info['fullname']:
return post_info['fullname'] == fullname
return False
return _update_gecos(name, 'fullname', fullname)
def chroomnumber(name, roomnumber):
@ -334,20 +365,7 @@ def chroomnumber(name, roomnumber):
salt '*' user.chroomnumber foo 123
'''
roomnumber = str(roomnumber)
pre_info = _get_gecos(name)
if not pre_info:
return False
if roomnumber == pre_info['roomnumber']:
return True
gecos_field = copy.deepcopy(pre_info)
gecos_field['roomnumber'] = roomnumber
cmd = 'pw usermod {0} -c "{1}"'.format(name, _build_gecos(gecos_field))
__salt__['cmd.run'](cmd, python_shell=False)
post_info = info(name)
if post_info['roomnumber'] != pre_info['roomnumber']:
return post_info['roomnumber'] == roomnumber
return False
return _update_gecos(name, 'roomnumber', roomnumber)
def chworkphone(name, workphone):
@ -360,20 +378,7 @@ def chworkphone(name, workphone):
salt '*' user.chworkphone foo "7735550123"
'''
workphone = str(workphone)
pre_info = _get_gecos(name)
if not pre_info:
return False
if workphone == pre_info['workphone']:
return True
gecos_field = copy.deepcopy(pre_info)
gecos_field['workphone'] = workphone
cmd = 'pw usermod {0} -c "{1}"'.format(name, _build_gecos(gecos_field))
__salt__['cmd.run'](cmd, python_shell=False)
post_info = info(name)
if post_info['workphone'] != pre_info['workphone']:
return post_info['workphone'] == workphone
return False
return _update_gecos(name, 'workphone', workphone)
def chhomephone(name, homephone):
@ -386,20 +391,7 @@ def chhomephone(name, homephone):
salt '*' user.chhomephone foo "7735551234"
'''
homephone = str(homephone)
pre_info = _get_gecos(name)
if not pre_info:
return False
if homephone == pre_info['homephone']:
return True
gecos_field = copy.deepcopy(pre_info)
gecos_field['homephone'] = homephone
cmd = 'pw usermod {0} -c "{1}"'.format(name, _build_gecos(gecos_field))
__salt__['cmd.run'](cmd, python_shell=False)
post_info = info(name)
if post_info['homephone'] != pre_info['homephone']:
return post_info['homephone'] == homephone
return False
return _update_gecos(name, 'homephone', homephone)
def info(name):
@ -494,11 +486,13 @@ def rename(name, new_name):
'''
current_info = info(name)
if not current_info:
raise CommandExecutionError('User {0!r} does not exist'.format(name))
raise CommandExecutionError('User \'{0}\' does not exist'.format(name))
new_info = info(new_name)
if new_info:
raise CommandExecutionError('User {0!r} already exists'.format(new_name))
cmd = 'pw usermod -l {0} -n {1}'.format(new_name, name)
raise CommandExecutionError(
'User \'{0}\' already exists'.format(new_name)
)
cmd = ['pw', 'usermod', '-l', new_name, '-n', name]
__salt__['cmd.run'](cmd)
post_info = info(new_name)
if post_info['name'] != current_info['name']:

View File

@ -6,13 +6,17 @@ data.
'''
from __future__ import absolute_import
# Import salt libs
import salt.utils
# Import python libs
import json
import logging
import random
import string
# Import salt libs
import salt.utils
import salt.utils.itertools
import salt.ext.six as six
from salt.exceptions import SaltInvocationError
from salt.ext.six.moves import range
log = logging.getLogger(__name__)
@ -108,8 +112,10 @@ def list_users(runas=None):
'''
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run']('rabbitmqctl list_users',
runas=runas)
res = __salt__['cmd.run'](
['rabbitmqctl', 'list_users'],
runas=runas,
python_shell=False)
# func to get tags from string such as "[admin, monitoring]"
func = lambda string: set(string[1:-1].split(','))
@ -128,8 +134,10 @@ def list_vhosts(runas=None):
'''
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run']('rabbitmqctl list_vhosts',
runas=runas)
res = __salt__['cmd.run'](
['rabbitmqctl', 'list_vhosts'],
runas=runas,
python_shell=False)
# remove first and last line: Listing ... - ...done
return _strip_listing_to_done(res.splitlines())
@ -189,10 +197,10 @@ def add_user(name, password=None, runas=None):
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run'](
'rabbitmqctl add_user {0} {1!r}'.format(name, password),
['rabbitmqctl', 'add_user', name, password],
output_loglevel='quiet',
python_shell=False,
runas=runas)
runas=runas,
python_shell=False)
if clear_pw:
# Now, Clear the random password from the account, if necessary
@ -221,7 +229,8 @@ def delete_user(name, runas=None):
'''
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run']('rabbitmqctl delete_user {0}'.format(name),
res = __salt__['cmd.run'](
['rabbitmqctl', 'delete_user', name],
python_shell=False,
runas=runas)
msg = 'Deleted'
@ -242,10 +251,10 @@ def change_password(name, password, runas=None):
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run'](
'rabbitmqctl change_password {0} {1!r}'.format(name, password),
['rabbitmqctl', 'change_password', name, password],
runas=runas,
output_loglevel='quiet',
python_shell=False,
runas=runas)
python_shell=False)
msg = 'Password Changed'
return _format_response(res, msg)
@ -263,9 +272,10 @@ def clear_password(name, runas=None):
'''
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run']('rabbitmqctl clear_password {0}'.format(name),
python_shell=False,
runas=runas)
res = __salt__['cmd.run'](
['rabbitmqctl', 'clear_password', name],
runas=runas,
python_shell=False)
msg = 'Password Cleared'
return _format_response(res, msg)
@ -283,9 +293,10 @@ def add_vhost(vhost, runas=None):
'''
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run']('rabbitmqctl add_vhost {0}'.format(vhost),
python_shell=False,
runas=runas)
res = __salt__['cmd.run'](
['rabbitmqctl', 'add_vhost', vhost],
runas=runas,
python_shell=False)
msg = 'Added'
return _format_response(res, msg)
@ -303,9 +314,10 @@ def delete_vhost(vhost, runas=None):
'''
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run']('rabbitmqctl delete_vhost {0}'.format(vhost),
python_shell=False,
runas=runas)
res = __salt__['cmd.run'](
['rabbitmqctl', 'delete_vhost', vhost],
runas=runas,
python_shell=False)
msg = 'Deleted'
return _format_response(res, msg)
@ -323,10 +335,10 @@ def set_permissions(vhost, user, conf='.*', write='.*', read='.*', runas=None):
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run'](
'rabbitmqctl set_permissions -p {0} {1} "{2}" "{3}" "{4}"'.format(
vhost, user, conf, write, read),
python_shell=False,
runas=runas)
['rabbitmqctl', 'set_permissions', '-p',
vhost, user, conf, write, read],
runas=runas,
python_shell=False)
msg = 'Permissions Set'
return _format_response(res, msg)
@ -344,9 +356,9 @@ def list_permissions(vhost, runas=None):
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run'](
'rabbitmqctl list_permissions -p {0}'.format(vhost),
python_shell=False,
runas=runas)
['rabbitmqctl', 'list_permissions', '-p', vhost],
runas=runas,
python_shell=False)
return _output_to_dict(res)
@ -364,9 +376,9 @@ def list_user_permissions(name, runas=None):
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run'](
'rabbitmqctl list_user_permissions {0}'.format(name),
python_shell=False,
runas=runas)
['rabbitmqctl', 'list_user_permissions', name],
runas=runas,
python_shell=False)
return _output_to_dict(res)
@ -387,9 +399,9 @@ def set_user_tags(name, tags, runas=None):
tags = ' '.join(tags)
res = __salt__['cmd.run'](
'rabbitmqctl set_user_tags {0} {1}'.format(name, tags),
python_shell=False,
runas=runas)
['rabbitmqctl', 'set_user_tags', name, tags],
runas=runas,
python_shell=False)
msg = "Tag(s) set"
return _format_response(res, msg)
@ -407,9 +419,9 @@ def status(runas=None):
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run'](
'rabbitmqctl status',
runas=runas
)
['rabbitmqctl', 'status'],
runas=runas,
python_shell=False)
return res
@ -426,8 +438,9 @@ def cluster_status(runas=None):
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run'](
'rabbitmqctl cluster_status',
runas=runas)
['rabbitmqctl', 'cluster_status'],
runas=runas,
python_shell=False)
return res
@ -442,10 +455,10 @@ def join_cluster(host, user='rabbit', ram_node=None, runas=None):
salt '*' rabbitmq.join_cluster 'rabbit.example.com' 'rabbit'
'''
cmd = ['rabbitmqctl', 'join_cluster']
if ram_node:
cmd = 'rabbitmqctl join_cluster --ram {0}@{1}'.format(user, host)
else:
cmd = 'rabbitmqctl join_cluster {0}@{1}'.format(user, host)
cmd.append('--ram')
cmd.append('{0}@{1}'.format(user, host))
if runas is None:
runas = salt.utils.get_user()
@ -468,11 +481,10 @@ def stop_app(runas=None):
'''
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run'](
'rabbitmqctl stop_app',
runas=runas)
return res
return __salt__['cmd.run'](
['rabbitmqctl', 'stop_app'],
runas=runas,
python_shell=False)
def start_app(runas=None):
@ -487,11 +499,10 @@ def start_app(runas=None):
'''
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run'](
'rabbitmqctl start_app',
runas=runas)
return res
return __salt__['cmd.run'](
['rabbitmqctl', 'start_app'],
runas=runas,
python_shell=False)
def reset(runas=None):
@ -506,11 +517,10 @@ def reset(runas=None):
'''
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run'](
'rabbitmqctl reset',
runas=runas)
return res
return __salt__['cmd.run'](
['rabbitmqctl', 'reset'],
runas=runas,
python_shell=False)
def force_reset(runas=None):
@ -525,14 +535,13 @@ def force_reset(runas=None):
'''
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run'](
'rabbitmqctl force_reset',
runas=runas)
return res
return __salt__['cmd.run'](
['rabbitmqctl', 'force_reset'],
runas=runas,
python_shell=False)
def list_queues(runas=None, *kwargs):
def list_queues(runas=None, *args):
'''
Returns queue details of the / virtual host
@ -544,15 +553,12 @@ def list_queues(runas=None, *kwargs):
'''
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run'](
'rabbitmqctl list_queues {0}'.format(' '.join(list(kwargs))),
python_shell=False,
runas=runas,
)
return res
cmd = ['rabbitmqctl', 'list_queues']
cmd.extend(args)
return __salt__['cmd.run'](cmd, runas=runas, python_shell=False)
def list_queues_vhost(vhost, runas=None, *kwargs):
def list_queues_vhost(vhost, runas=None, *args):
'''
Returns queue details of specified virtual host. This command will consider
first parameter as the vhost name and rest will be treated as
@ -567,15 +573,9 @@ def list_queues_vhost(vhost, runas=None, *kwargs):
'''
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run'](
'rabbitmqctl list_queues -p {0} {1}'.format(
vhost,
' '.join(list(kwargs))
),
python_shell=False,
runas=runas,
)
return res
cmd = ['rabbitmqctl', 'list_queues', '-p', vhost]
cmd.extend(args)
return __salt__['cmd.run'](cmd, runas=runas, python_shell=False)
def list_policies(vhost="/", runas=None):
@ -594,11 +594,12 @@ def list_policies(vhost="/", runas=None):
ret = {}
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run']('rabbitmqctl list_policies -p {0}'.format(
vhost),
runas=runas)
for line in res.splitlines():
if '...' not in line and line != '\n':
output = __salt__['cmd.run'](
['rabbitmqctl', 'list_policies', '-p', vhost],
runas=runas,
python_shell=False)
for line in salt.utils.itertools.split(output, '\n'):
if '...' not in line:
parts = line.split('\t')
if len(parts) not in (5, 6):
continue
@ -606,7 +607,8 @@ def list_policies(vhost="/", runas=None):
if vhost not in ret:
ret[vhost] = {}
ret[vhost][name] = {}
# How many fields are there? - 'apply_to' was inserted in position 2 at somepoint
# How many fields are there? - 'apply_to' was inserted in position
# 2 at some point
offset = len(parts) - 5
if len(parts) == 6:
ret[vhost][name]['apply_to'] = parts[2]
@ -633,16 +635,17 @@ def set_policy(vhost, name, pattern, definition, priority=None, runas=None):
'''
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run'](
"rabbitmqctl set_policy -p {0}{1}{2} {3} '{4}' '{5}'".format(
vhost,
' --priority ' if priority else '',
priority if priority else '',
name,
pattern,
definition.replace("'", '"')),
python_shell=False,
runas=runas)
if isinstance(definition, dict):
definition = json.dumps(definition)
if not isinstance(definition, six.string_types):
raise SaltInvocationError(
'The \'definition\' argument must be a dictionary or JSON string'
)
cmd = ['rabbitmqctl', 'set_policy', '-p', vhost]
if priority:
cmd.extend(['--priority', priority])
cmd.extend([name, pattern, definition])
res = __salt__['cmd.run'](cmd, runas=runas, python_shell=False)
log.debug('Set policy: {0}'.format(res))
return _format_response(res, 'Set')
@ -662,10 +665,9 @@ def delete_policy(vhost, name, runas=None):
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run'](
'rabbitmqctl clear_policy -p {0} {1}'.format(
vhost, name),
python_shell=False,
runas=runas)
['rabbitmqctl', 'clear_policy', '-p', vhost, name],
runas=runas,
python_shell=False)
log.debug('Delete policy: {0}'.format(res))
return _format_response(res, 'Deleted')
@ -698,11 +700,10 @@ def plugin_is_enabled(name, runas=None):
salt '*' rabbitmq.plugin_is_enabled foo
'''
rabbitmq = _get_rabbitmq_plugin()
cmd = '{0} list -m -e'.format(rabbitmq)
if runas is None:
runas = salt.utils.get_user()
ret = __salt__['cmd.run'](cmd, python_shell=False, runas=runas)
cmd = [_get_rabbitmq_plugin(), 'list', '-m', '-e']
ret = __salt__['cmd.run'](cmd, runas=runas, python_shell=False)
return bool(name in ret)
@ -716,13 +717,10 @@ def enable_plugin(name, runas=None):
salt '*' rabbitmq.enable_plugin foo
'''
rabbitmq = _get_rabbitmq_plugin()
cmd = '{0} enable {1}'.format(rabbitmq, name)
if runas is None:
runas = salt.utils.get_user()
ret = __salt__['cmd.run_all'](cmd, python_shell=False, runas=runas)
cmd = [_get_rabbitmq_plugin(), 'enable', name]
ret = __salt__['cmd.run_all'](cmd, runas=runas, python_shell=False)
return _format_response(ret, 'Enabled')
@ -736,12 +734,8 @@ def disable_plugin(name, runas=None):
salt '*' rabbitmq.disable_plugin foo
'''
rabbitmq = _get_rabbitmq_plugin()
cmd = '{0} disable {1}'.format(rabbitmq, name)
if runas is None:
runas = salt.utils.get_user()
ret = __salt__['cmd.run_all'](cmd, python_shell=False, runas=runas)
cmd = [_get_rabbitmq_plugin(), 'disable', name]
ret = __salt__['cmd.run_all'](cmd, runas=runas, python_shell=False)
return _format_response(ret, 'Disabled')

View File

@ -84,7 +84,7 @@ def _publish(
try:
peer_data = channel.send(load)
except SaltReqTimeoutError:
return '{0!r} publish timed out'.format(fun)
return '\'{0}\' publish timed out'.format(fun)
if not peer_data:
return {}
# CLI args are passed as strings, re-cast to keep time.sleep happy
@ -216,4 +216,4 @@ def runner(fun, arg=None, timeout=5):
try:
return channel.send(load)
except SaltReqTimeoutError:
return '{0!r} runner publish timed out'.format(fun)
return '\'{0}\' runner publish timed out'.format(fun)

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
'''
Manage ruby installations with rbenv. Rbenv is supported on Linux and Mac OS X.
Rbenv doesn't work on Windows (and isn't really necessary on Windows as there is
Manage ruby installations with rbenv. rbenv is supported on Linux and Mac OS X.
rbenv doesn't work on Windows (and isn't really necessary on Windows as there is
no system Ruby on Windows). On Windows, the RubyInstaller and/or Pik are both
good alternatives to work with multiple versions of Ruby on the same box.
@ -19,10 +19,10 @@ import shlex
# Import Salt libs
import salt.utils
from salt.exceptions import SaltInvocationError
# Import 3rd-party libs
import salt.ext.six as six
from salt.ext.six.moves import shlex_quote as _cmd_quote # pylint: disable=import-error
# Set up logger
log = logging.getLogger(__name__)
@ -38,9 +38,9 @@ __opts__ = {
def __virtual__():
"""
'''
Only work on POSIX-like systems
"""
'''
if salt.utils.is_windows():
return False
return True
@ -66,14 +66,30 @@ def _parse_env(env):
env = {}
for bad_env_key in (x for x, y in six.iteritems(env) if y is None):
log.error('Environment variable {0!r} passed without a value. '
log.error('Environment variable \'{0}\' passed without a value. '
'Setting value to an empty string'.format(bad_env_key))
env[bad_env_key] = ''
return env
def _rbenv_exec(command, args='', env=None, runas=None, ret=None):
def _rbenv_bin(runas=None):
path = _rbenv_path(runas)
return '{0}/bin/rbenv'.format(path)
def _rbenv_path(runas=None):
path = None
if runas in (None, 'root'):
path = __salt__['config.option']('rbenv.root') or '/usr/local/rbenv'
else:
path = __salt__['config.option']('rbenv.root') \
or '~{0}/.rbenv'.format(runas)
return os.path.expanduser(path)
def _rbenv_exec(command, env=None, runas=None, ret=None):
if not is_installed(runas):
return False
@ -83,10 +99,8 @@ def _rbenv_exec(command, args='', env=None, runas=None, ret=None):
environ = _parse_env(env)
environ['RBENV_ROOT'] = path
args = ' '.join([_cmd_quote(arg) for arg in _shlex_split(args)])
result = __salt__['cmd.run_all'](
'{0} {1} {2}'.format(binary, _cmd_quote(command), args),
[binary] + command,
runas=runas,
env=environ
)
@ -101,29 +115,12 @@ def _rbenv_exec(command, args='', env=None, runas=None, ret=None):
return False
def _rbenv_bin(runas=None):
path = _rbenv_path(runas)
return '{0}/bin/rbenv'.format(path)
def _rbenv_path(runas=None):
path = None
if runas in (None, 'root'):
path = __salt__['config.option']('rbenv.root') or '/usr/local/rbenv'
else:
path = (__salt__['config.option']('rbenv.root') or
'~{0}/.rbenv'.format(runas))
return _cmd_quote(os.path.expanduser(path))
def _install_rbenv(path, runas=None):
if os.path.isdir(path):
return True
return 0 == __salt__['cmd.retcode'](
'git clone https://github.com/sstephenson/rbenv.git {0}'
.format(_cmd_quote(path)), runas=runas)
cmd = ['git', 'clone', 'https://github.com/sstephenson/rbenv.git', path]
return __salt__['cmd.retcode'](cmd, runas=runas, python_shell=False) == 0
def _install_ruby_build(path, runas=None):
@ -131,17 +128,19 @@ def _install_ruby_build(path, runas=None):
if os.path.isdir(path):
return True
return 0 == __salt__['cmd.retcode'](
'git clone https://github.com/sstephenson/ruby-build.git {0}'
.format(_cmd_quote(path)), runas=runas)
cmd = ['git', 'clone',
'https://github.com/sstephenson/ruby-build.git', path]
return __salt__['cmd.retcode'](cmd, runas=runas, python_shell=False) == 0
def _update_rbenv(path, runas=None):
if not os.path.isdir(path):
return False
return 0 == __salt__['cmd.retcode'](
'git pull', runas=runas, cwd=path)
return __salt__['cmd.retcode'](['git', 'pull'],
runas=runas,
cwd=path,
python_shell=False) == 0
def _update_ruby_build(path, runas=None):
@ -149,13 +148,15 @@ def _update_ruby_build(path, runas=None):
if not os.path.isdir(path):
return False
return 0 == __salt__['cmd.retcode'](
'git pull', runas=runas, cwd=path)
return __salt__['cmd.retcode'](['git', 'pull'],
runas=runas,
cwd=path,
python_shell=False) == 0
def install(runas=None, path=None):
'''
Install Rbenv systemwide
Install rbenv systemwide
CLI Example:
@ -170,7 +171,11 @@ def install(runas=None, path=None):
def update(runas=None, path=None):
'''
Updates the current versions of Rbenv and Ruby-Build
Updates the current versions of rbenv and ruby-build
runas
The user under which to run rbenv. If not specified, then rbenv will be
run as the user under which Salt is running.
CLI Example:
@ -186,7 +191,7 @@ def update(runas=None, path=None):
def is_installed(runas=None):
'''
Check if Rbenv is installed.
Check if rbenv is installed
CLI Example:
@ -203,7 +208,11 @@ def install_ruby(ruby, runas=None):
ruby
The version of Ruby to install, should match one of the
versions listed by rbenv.list
versions listed by :py:func:`rbenv.list <salt.modules.rbenv.list>`
runas
The user under which to run rbenv. If not specified, then rbenv will be
run as the user under which Salt is running.
Additional environment variables can be configured in pillar /
grains / master:
@ -236,7 +245,7 @@ def install_ruby(ruby, runas=None):
env = ' '.join(env_list)
ret = {}
ret = _rbenv_exec('install', ruby, env=env, runas=runas, ret=ret)
ret = _rbenv_exec(['install', ruby], env=env, runas=runas, ret=ret)
if ret['retcode'] == 0:
rehash(runas=runas)
return ret['stderr']
@ -252,7 +261,11 @@ def uninstall_ruby(ruby, runas=None):
ruby
The version of ruby to uninstall. Should match one of the versions
listed by :mod:`rbenv.versions <salt.modules.rbenv.versions>`
listed by :py:func:`rbenv.versions <salt.modules.rbenv.versions>`.
runas
The user under which to run rbenv. If not specified, then rbenv will be
run as the user under which Salt is running.
CLI Example:
@ -261,15 +274,13 @@ def uninstall_ruby(ruby, runas=None):
salt '*' rbenv.uninstall_ruby 2.0.0-p0
'''
ruby = re.sub(r'^ruby-', '', ruby)
args = '--force {0}'.format(ruby)
_rbenv_exec('uninstall', args, runas=runas)
_rbenv_exec(['uninstall', '--force', ruby], runas=runas)
return True
def versions(runas=None):
'''
List the installed versions of ruby.
List the installed versions of ruby
CLI Example:
@ -277,18 +288,18 @@ def versions(runas=None):
salt '*' rbenv.versions
'''
ret = _rbenv_exec('versions', '--bare', runas=runas)
ret = _rbenv_exec(['versions', '--bare'], runas=runas)
return [] if ret is False else ret.splitlines()
def default(ruby=None, runas=None):
'''
Returns or sets the currently defined default ruby.
Returns or sets the currently defined default ruby
ruby=None
ruby
The version to set as the default. Should match one of the versions
listed by :mod:`rbenv.versions <salt.modules.rbenv.versions>`. Leave
blank to return the current default.
listed by :py:func:`rbenv.versions <salt.modules.rbenv.versions>`.
Leave blank to return the current default.
CLI Example:
@ -298,16 +309,20 @@ def default(ruby=None, runas=None):
salt '*' rbenv.default 2.0.0-p0
'''
if ruby:
_rbenv_exec('global', ruby, runas=runas)
_rbenv_exec(['global', ruby], runas=runas)
return True
else:
ret = _rbenv_exec('global', runas=runas)
ret = _rbenv_exec(['global'], runas=runas)
return '' if ret is False else ret.strip()
def list_(runas=None):
'''
List the installable versions of ruby.
List the installable versions of ruby
runas
The user under which to run rbenv. If not specified, then rbenv will be
run as the user under which Salt is running.
CLI Example:
@ -316,7 +331,7 @@ def list_(runas=None):
salt '*' rbenv.list
'''
ret = []
output = _rbenv_exec('install', '--list', runas=runas)
output = _rbenv_exec(['install', '--list'], runas=runas)
if output:
for line in output.splitlines():
if line == 'Available versions:':
@ -327,7 +342,11 @@ def list_(runas=None):
def rehash(runas=None):
'''
Run rbenv rehash to update the installed shims.
Run ``rbenv rehash`` to update the installed shims
runas
The user under which to run rbenv. If not specified, then rbenv will be
run as the user under which Salt is running.
CLI Example:
@ -335,13 +354,13 @@ def rehash(runas=None):
salt '*' rbenv.rehash
'''
_rbenv_exec('rehash', runas=runas)
_rbenv_exec(['rehash'], runas=runas)
return True
def do(cmdline=None, runas=None):
def do(cmdline, runas=None):
'''
Execute a ruby command with rbenv's shims from the user or the system.
Execute a ruby command with rbenv's shims from the user or the system
CLI Example:
@ -350,13 +369,25 @@ def do(cmdline=None, runas=None):
salt '*' rbenv.do 'gem list bundler'
salt '*' rbenv.do 'gem list bundler' deploy
'''
if not cmdline:
# This is a positional argument so this should never happen, but this
# will handle cases where someone explicitly passes a false value for
# cmdline.
raise SaltInvocationError('Command must be specified')
path = _rbenv_path(runas)
environ = {'PATH': '{0}/shims:{1}'.format(path, os.environ['PATH'])}
cmdline = ' '.join([_cmd_quote(cmd) for cmd in _shlex_split(cmdline)])
try:
cmdline = shlex.split(cmdline)
except AttributeError:
cmdline = shlex.split(str(cmdline))
result = __salt__['cmd.run_all'](
cmdline,
runas=runas,
env=environ
env=environ,
python_shell=False
)
if result['retcode'] == 0:
@ -368,17 +399,28 @@ def do(cmdline=None, runas=None):
def do_with_ruby(ruby, cmdline, runas=None):
'''
Execute a ruby command with rbenv's shims using a specific ruby version.
Execute a ruby command with rbenv's shims using a specific ruby version
CLI Example:
.. code-block:: bash
salt '*' rbenv.do_with_ruby 2.0.0-p0 'gem list bundler'
salt '*' rbenv.do_with_ruby 2.0.0-p0 'gem list bundler' deploy
salt '*' rbenv.do_with_ruby 2.0.0-p0 'gem list bundler' runas=deploy
'''
if not cmdline:
# This is a positional argument so this should never happen, but this
# will handle cases where someone explicitly passes a false value for
# cmdline.
raise SaltInvocationError('Command must be specified')
try:
cmdline = shlex.split(cmdline)
except AttributeError:
cmdline = shlex.split(str(cmdline))
if ruby:
cmd = 'RBENV_VERSION={0} {1}'.format(ruby, cmdline)
cmd = ['RBENV_VERSION={0}'.format(ruby)] + cmdline
else:
cmd = cmdline

View File

@ -13,10 +13,10 @@ import datetime
# Import Salt libs
import salt.utils
import salt.utils.itertools
import salt.utils.decorators as decorators
import salt.utils.pkg.rpm
# pylint: disable=import-error,redefined-builtin
from salt.ext.six.moves import shlex_quote as _cmd_quote
from salt.ext.six.moves import zip
# pylint: enable=import-error,redefined-builtin
from salt.exceptions import CommandExecutionError, SaltInvocationError
@ -93,9 +93,10 @@ def bin_pkg_info(path, saltenv='base'):
# with 'none'
queryformat = salt.utils.pkg.rpm.QUERYFORMAT.replace('%{REPOID}', 'none')
output = __salt__['cmd.run_stdout'](
'rpm -qp --queryformat {0} {1}'.format(_cmd_quote(queryformat), path),
['rpm', '-qp', '--queryformat', queryformat, path],
output_loglevel='trace',
ignore_retcode=True
ignore_retcode=True,
python_shell=False
)
ret = {}
pkginfo = salt.utils.pkg.rpm.parse_pkginfo(
@ -120,14 +121,12 @@ def list_pkgs(*packages):
salt '*' lowpkg.list_pkgs
'''
pkgs = {}
if not packages:
cmd = 'rpm -qa --qf \'%{NAME} %{VERSION}\\n\''
else:
cmd = 'rpm -q --qf \'%{{NAME}} %{{VERSION}}\\n\' {0}'.format(
' '.join(packages)
)
out = __salt__['cmd.run'](cmd, python_shell=False, output_loglevel='trace')
for line in out.splitlines():
cmd = ['rpm', '-q' if packages else '-qa',
'--queryformat', r'%{NAME} %{VERSION}\n']
if packages:
cmd.extend(packages)
out = __salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False)
for line in salt.utils.itertools.split(out, '\n'):
if 'is not installed' in line:
continue
comps = line.split()
@ -135,7 +134,7 @@ def list_pkgs(*packages):
return pkgs
def verify(*package, **kwargs):
def verify(*packages, **kwargs):
'''
Runs an rpm -Va on a system, and returns the results in a dict
@ -148,8 +147,8 @@ def verify(*package, **kwargs):
salt '*' lowpkg.verify
salt '*' lowpkg.verify httpd
salt '*' lowpkg.verify 'httpd postfix'
salt '*' lowpkg.verify 'httpd postfix' ignore_types=['config','doc']
salt '*' lowpkg.verify httpd postfix
salt '*' lowpkg.verify httpd postfix ignore_types=['config','doc']
'''
ftypes = {'c': 'config',
'd': 'doc',
@ -158,17 +157,17 @@ def verify(*package, **kwargs):
'r': 'readme'}
ret = {}
ignore_types = kwargs.get('ignore_types', [])
if package:
packages = ' '.join(package)
cmd = 'rpm -V {0}'.format(packages)
if packages:
cmd = ['rpm', '-V']
# Can't concatenate a tuple, must do a list.extend()
cmd.extend(packages)
else:
cmd = 'rpm -Va'
out = __salt__['cmd.run'](
cmd,
python_shell=False,
cmd = ['rpm', '-Va']
out = __salt__['cmd.run'](cmd,
output_loglevel='trace',
ignore_retcode=True)
for line in out.splitlines():
ignore_retcode=True,
python_shell=False)
for line in salt.utils.itertools.split(out, '\n'):
fdict = {'mismatch': []}
if 'missing' in line:
line = ' ' + line
@ -217,8 +216,8 @@ def modified(*packages, **flags):
'''
ret = __salt__['cmd.run_all'](
['rpm', '-Va'] + list(packages),
python_shell=False,
output_loglevel='trace')
output_loglevel='trace',
python_shell=False)
data = {}
@ -233,7 +232,7 @@ def modified(*packages, **flags):
ptrn = re.compile(r"\s+")
changes = cfg = f_name = None
for f_info in ret['stdout'].splitlines():
for f_info in salt.utils.itertools.split(ret['stdout'], '\n'):
f_info = ptrn.split(f_info)
if len(f_info) == 3: # Config file
changes, cfg, f_name = f_info
@ -244,7 +243,7 @@ def modified(*packages, **flags):
'owner', 'group', 'time', 'capabilities']
changes = list(changes)
if len(changes) == 8: # Older RPMs do not support capabilities
changes.append(".")
changes.append('.')
stats = []
for k, v in zip(keys, changes):
if v != '.':
@ -288,13 +287,15 @@ def file_list(*packages):
salt '*' lowpkg.file_list
'''
if not packages:
cmd = 'rpm -qla'
cmd = ['rpm', '-qla']
else:
cmd = 'rpm -ql {0}'.format(' '.join(packages))
cmd = ['rpm', '-ql']
# Can't concatenate a tuple, must do a list.extend()
cmd.extend(packages)
ret = __salt__['cmd.run'](
cmd,
python_shell=False,
output_loglevel='trace').splitlines()
output_loglevel='trace',
python_shell=False).splitlines()
return {'errors': [], 'files': ret}
@ -315,14 +316,12 @@ def file_dict(*packages):
errors = []
ret = {}
pkgs = {}
if not packages:
cmd = 'rpm -qa --qf \'%{NAME} %{VERSION}\\n\''
else:
cmd = 'rpm -q --qf \'%{{NAME}} %{{VERSION}}\\n\' {0}'.format(
' '.join(packages)
)
out = __salt__['cmd.run'](cmd, python_shell=False, output_loglevel='trace')
for line in out.splitlines():
cmd = ['rpm', '-q' if packages else '-qa',
'--queryformat', r'%{NAME} %{VERSION}\n']
if packages:
cmd.extend(packages)
out = __salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False)
for line in salt.utils.itertools.split(out, '\n'):
if 'is not installed' in line:
errors.append(line)
continue
@ -330,11 +329,12 @@ def file_dict(*packages):
pkgs[comps[0]] = {'version': comps[1]}
for pkg in pkgs:
files = []
cmd = 'rpm -ql {0}'.format(pkg)
out = __salt__['cmd.run'](cmd, python_shell=False, output_loglevel='trace')
for line in out.splitlines():
files.append(line)
ret[pkg] = files
cmd = ['rpm', '-ql', pkg]
out = __salt__['cmd.run'](
['rpm', '-ql', pkg],
output_loglevel='trace',
python_shell=False)
ret[pkg] = out.splitlines()
return {'errors': errors, 'packages': ret}
@ -358,10 +358,11 @@ def owner(*paths):
if not paths:
return ''
ret = {}
cmd = 'rpm -qf --queryformat "%{{NAME}}" {0!r}'
for path in paths:
ret[path] = __salt__['cmd.run_stdout'](cmd.format(path),
output_loglevel='trace')
cmd = ['rpm', '-qf', '--queryformat', '%{{NAME}}', path]
ret[path] = __salt__['cmd.run_stdout'](cmd,
output_loglevel='trace',
python_shell=False)
if 'not owned' in ret[path].lower():
ret[path] = ''
if len(ret) == 1:
@ -392,9 +393,11 @@ def diff(package, path):
cmd = "rpm2cpio {0} " \
"| cpio -i --quiet --to-stdout .{1} " \
"| diff -u --label 'A {1}' --from-file=- --label 'B {1}' {1}"
res = __salt__['cmd.shell'](cmd.format(package, path), output_loglevel='trace')
res = __salt__['cmd.shell'](cmd.format(package, path),
output_loglevel='trace')
if res and res.startswith('Binary file'):
return 'File "{0}" is binary and its content has been modified.'.format(path)
return 'File \'{0}\' is binary and its content has been ' \
'modified.'.format(path)
return res

View File

@ -10,11 +10,12 @@ Options passed into opts will overwrite options passed into pillar.
from __future__ import absolute_import
# Import python libs
import errno
import logging
import os
# Import salt libs
from salt.exceptions import CommandExecutionError
import salt.utils
from salt.exceptions import CommandExecutionError, SaltInvocationError
log = logging.getLogger(__name__)
@ -32,15 +33,14 @@ def _check(delete, force, update, passwordfile, exclude, excludefrom):
if update:
options.append('--update')
if passwordfile:
options.append('--password-file={0}'.format(passwordfile))
options.extend(['--password-file', passwordfile])
if excludefrom:
options.append('--exclude-from={0}'.format(excludefrom))
options.extend(['--exclude-from', excludefrom])
if exclude:
exclude = None
exclude = False
if exclude:
options.append('--exclude={0}'.format(exclude))
return ' '.join(options)
options.extend(['--exclude', exclude])
return options
def rsync(src,
@ -50,9 +50,13 @@ def rsync(src,
update=False,
passwordfile=None,
exclude=None,
excludefrom=None,
):
excludefrom=None):
'''
.. versionchanged:: Boron
Return data now contains just the output of the rsync command, instead
of a dictionary as returned from :py:func:`cmd.run_all
<salt.modules.cmdmod.run_all>`.
Rsync files from src to dst
CLI Example:
@ -79,29 +83,24 @@ def rsync(src,
if not excludefrom:
excludefrom = __salt__['config.option']('rsync.excludefrom')
if not src or not dst:
raise CommandExecutionError('ERROR: src and dst cannot be empty.')
raise SaltInvocationError('src and dst cannot be empty')
option = _check(delete, force, update, passwordfile, exclude, excludefrom)
cmd = (
r'''rsync {option} {src} {dst}'''
.format(
option=option,
src=src,
dst=dst,
)
)
cmd = ['rsync'] + option + [src, dst]
try:
ret = __salt__['cmd.run_all'](cmd, python_shell=False)
return __salt__['cmd.run'](cmd, python_shell=False)
except (IOError, OSError) as exc:
raise CommandExecutionError(exc.strerror)
return ret
def version():
'''
Return rsync version
.. versionchanged:: Boron
Return data now contains just the version number as a string, instead
of a dictionary as returned from :py:func:`cmd.run_all
<salt.modules.cmdmod.run_all>`.
Returns rsync version
CLI Example:
@ -109,21 +108,29 @@ def version():
salt '*' rsync.version
'''
cmd = (r'''rsync --version''')
try:
ret = __salt__['cmd.run_all'](cmd)
out = __salt__['cmd.run_stdout'](
['rsync', '--version'],
python_shell=False)
except (IOError, OSError) as exc:
raise CommandExecutionError(exc.strerror)
ret['stdout'] = ret['stdout'].split('\n')[0].split()[2]
return ret
try:
return out.split('\n')[0].split()[2]
except IndexError:
raise CommandExecutionError('Unable to determine rsync version')
def config(confile='/etc/rsyncd.conf'):
def config(conf_path='/etc/rsyncd.conf'):
'''
Return rsync config
.. versionchanged:: Boron
Return data now contains just the contents of the rsyncd.conf as a
string, instead of a dictionary as returned from :py:func:`cmd.run_all
<salt.modules.cmdmod.run_all>`.
Returns the contents of the rsync config file
conf_path : /etc/rsyncd.conf
Path to the config file
CLI Example:
@ -131,20 +138,25 @@ def config(confile='/etc/rsyncd.conf'):
salt '*' rsync.config
'''
if not os.path.isfile(confile):
raise CommandExecutionError('{0!r} does not exit'.format(confile))
cmd = (
r'''cat {confile}'''
.format(
confile=confile
)
)
ret = ''
try:
ret = __salt__['cmd.run_all'](cmd, python_shell=False)
except (IOError, OSError) as exc:
raise CommandExecutionError(exc.strerror)
with salt.utils.fopen(conf_path, 'r') as fp_:
for line in fp_:
ret += line
except IOError as exc:
if exc.errno == errno.ENOENT:
raise CommandExecutionError('{0} does not exist'.format(conf_path))
elif exc.errno == errno.EACCES:
raise CommandExecutionError(
'Unable to read {0}, access denied'.format(conf_path)
)
elif exc.errno == errno.EISDIR:
raise CommandExecutionError(
'Unable to read {0}, path is a directory'.format(conf_path)
)
else:
raise CommandExecutionError(
'Error {0}: {1}'.format(exc.errno, exc.strerror)
)
else:
return ret

View File

@ -8,10 +8,10 @@ from __future__ import absolute_import
import re
import os
import logging
try:
from shlex import quote as _cmd_quote # pylint: disable=E0611
except ImportError:
from pipes import quote as _cmd_quote
import shlex
# Import salt libs
from salt.exceptions import CommandExecutionError
log = logging.getLogger(__name__)
@ -30,21 +30,22 @@ def _get_rvm_location(runas=None):
runas_home = os.path.expanduser('~{0}'.format(runas))
rvmpath = '{0}/.rvm/bin/rvm'.format(runas_home)
if os.path.exists(rvmpath):
return rvmpath
return '/usr/local/rvm/bin/rvm'
return [rvmpath]
return ['/usr/local/rvm/bin/rvm']
def _rvm(command, arguments=None, runas=None, cwd=None):
def _rvm(command, runas=None, cwd=None):
if runas is None:
runas = __salt__['config.option']('rvm.runas')
if not is_installed(runas):
return False
cmd = [_get_rvm_location(runas), _cmd_quote(command)]
if arguments:
cmd.extend([_cmd_quote(arg) for arg in arguments.split()])
cmd = _get_rvm_location(runas) + command
ret = __salt__['cmd.run_all'](' '.join(cmd), runas=runas, cwd=cwd)
ret = __salt__['cmd.run_all'](cmd,
runas=runas,
cwd=cwd,
python_shell=False)
if ret['retcode'] == 0:
return ret['stdout']
@ -52,9 +53,7 @@ def _rvm(command, arguments=None, runas=None, cwd=None):
def _rvm_do(ruby, command, runas=None, cwd=None):
return _rvm('{ruby}'.format(ruby=ruby or 'default'),
arguments='do {command}'.format(command=command),
runas=runas, cwd=cwd)
return _rvm([ruby or 'default', 'do'] + command, runas=runas, cwd=cwd)
def is_installed(runas=None):
@ -67,12 +66,19 @@ def is_installed(runas=None):
salt '*' rvm.is_installed
'''
return __salt__['cmd.has_exec'](_get_rvm_location(runas))
try:
return __salt__['cmd.has_exec'](_get_rvm_location(runas)[0])
except IndexError:
return False
def install(runas=None):
'''
Install RVM system wide.
Install RVM system-wide
runas
The user under which to run the rvm installer script. If not specified,
then it be run as the user under which Salt is running.
CLI Example:
@ -91,11 +97,10 @@ def install(runas=None):
python_shell=True
)
if ret['retcode'] > 0:
log.debug(
'Error while downloading the RVM installer. Command '
'returned: {0!r}'.format(ret)
)
return False
msg = 'Error encountered while downloading the RVM installer'
if ret['stderr']:
msg += '. stderr follows:\n\n' + ret['stderr']
raise CommandExecutionError(msg)
return True
@ -104,9 +109,11 @@ def install_ruby(ruby, runas=None):
Install a ruby implementation.
ruby
The version of ruby to install.
runas : None
The user to run rvm as.
The version of ruby to install
runas
The user under which to run rvm. If not specified, then rvm will be run
as the user under which Salt is running.
CLI Example:
@ -120,20 +127,22 @@ def install_ruby(ruby, runas=None):
# libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev autoconf libc6-dev
# libncurses5-dev automake libtool bison subversion ruby
if runas and runas != 'root':
_rvm('autolibs', 'disable {ruby}'.format(ruby=ruby), runas=runas)
return _rvm('install', '--disable-binary {ruby}'.format(ruby=ruby), runas=runas)
_rvm(['autolibs', 'disable', ruby], runas=runas)
return _rvm(['install', '--disable-binary', ruby], runas=runas)
else:
return _rvm('install', ruby, runas=runas)
return _rvm(['install', ruby], runas=runas)
def reinstall_ruby(ruby, runas=None):
'''
Reinstall a ruby implementation.
Reinstall a ruby implementation
ruby
The version of ruby to reinstall.
runas : None
The user to run rvm as.
The version of ruby to reinstall
runas
The user under which to run rvm. If not specified, then rvm will be run
as the user under which Salt is running.
CLI Example:
@ -141,15 +150,16 @@ def reinstall_ruby(ruby, runas=None):
salt '*' rvm.reinstall_ruby 1.9.3-p385
'''
return _rvm('reinstall', ruby, runas=runas)
return _rvm(['reinstall', ruby], runas=runas)
def list_(runas=None):
'''
List all rvm installed rubies.
List all rvm-installed rubies
runas : None
The user to run rvm as.
runas
The user under which to run rvm. If not specified, then rvm will be run
as the user under which Salt is running.
CLI Example:
@ -158,7 +168,7 @@ def list_(runas=None):
salt '*' rvm.list
'''
rubies = []
output = _rvm('list', '', runas=runas)
output = _rvm(['list'], runas=runas)
if output:
regex = re.compile(r'^[= ]([*> ]) ([^- ]+)-([^ ]+) \[ (.*) \]')
for line in output.splitlines():
@ -172,12 +182,14 @@ def list_(runas=None):
def set_default(ruby, runas=None):
'''
Set the default ruby.
Set the default ruby
ruby
The version of ruby to make the default.
runas : None
The user to run rvm as.
The version of ruby to make the default
runas
The user under which to run rvm. If not specified, then rvm will be run
as the user under which Salt is running.
CLI Example:
@ -185,18 +197,15 @@ def set_default(ruby, runas=None):
salt '*' rvm.set_default 2.0.0
'''
return _rvm('alias',
'create default {ruby}'.format(ruby=ruby), runas=runas)
return _rvm(['alias', 'create', 'default', ruby], runas=runas)
def get(version='stable', runas=None):
'''
Update RVM.
Update RVM
version : stable
Which version of RVM to install, e.g. stable or head.
ruby
The version of ruby to reinstall.
Which version of RVM to install, (e.g. stable or head)
CLI Example:
@ -204,19 +213,23 @@ def get(version='stable', runas=None):
salt '*' rvm.get
'''
return _rvm('get', version, runas=runas)
return _rvm(['get', version], runas=runas)
def wrapper(ruby_string, wrapper_prefix, runas=None, *binaries):
'''
Install RVM wrapper scripts.
Install RVM wrapper scripts
ruby_string
Ruby/gemset to install wrappers for.
Ruby/gemset to install wrappers for
wrapper_prefix
What to prepend to the name of the generated wrapper binaries.
runas : None
The user to run rvm as.
What to prepend to the name of the generated wrapper binaries
runas
The user under which to run rvm. If not specified, then rvm will be run
as the user under which Salt is running.
binaries : None
The names of the binaries to create wrappers for. When nothing is
given, wrappers for ruby, gem, rake, irb, rdoc, ri and testrb are
@ -228,26 +241,25 @@ def wrapper(ruby_string, wrapper_prefix, runas=None, *binaries):
salt '*' rvm.wrapper <ruby_string> <wrapper_prefix>
'''
return _rvm('wrapper',
'{ruby_string} {wrapper_prefix} {binaries}'.format(
ruby_string=ruby_string,
wrapper_prefix=wrapper_prefix,
binaries=' '.join(binaries)
),
runas=runas)
cmd = ['wrapper', ruby_string, wrapper_prefix]
cmd.extend(binaries)
return _rvm(cmd, runas=runas)
def rubygems(ruby, version, runas=None):
'''
Installs a specific rubygems version in the given ruby.
Installs a specific rubygems version in the given ruby
ruby
The ruby to install rubygems for.
The ruby for which to install rubygems
version
The version of rubygems to install or 'remove' to use the version that
The version of rubygems to install, or 'remove' to use the version that
ships with 1.9
runas : None
The user to run rvm as.
runas
The user under which to run rvm. If not specified, then rvm will be run
as the user under which Salt is running.
CLI Example:
@ -255,7 +267,7 @@ def rubygems(ruby, version, runas=None):
salt '*' rvm.rubygems 2.0.0 1.8.24
'''
return _rvm_do(ruby, 'rubygems {0}'.format(version), runas=runas)
return _rvm_do(ruby, ['rubygems', version], runas=runas)
def gemset_create(ruby, gemset, runas=None):
@ -263,11 +275,14 @@ def gemset_create(ruby, gemset, runas=None):
Creates a gemset.
ruby
The ruby version to create the gemset for.
The ruby version for which to create the gemset
gemset
The name of the gemset to create.
runas : None
The user to run rvm as.
The name of the gemset to create
runas
The user under which to run rvm. If not specified, then rvm will be run
as the user under which Salt is running.
CLI Example:
@ -275,9 +290,7 @@ def gemset_create(ruby, gemset, runas=None):
salt '*' rvm.gemset_create 2.0.0 foobar
'''
return _rvm_do(ruby,
'rvm gemset create {gemset}'.format(gemset=gemset),
runas=runas)
return _rvm_do(ruby, ['rvm', 'gemset', 'create', gemset], runas=runas)
def gemset_list(ruby='default', runas=None):
@ -285,9 +298,11 @@ def gemset_list(ruby='default', runas=None):
List all gemsets for the given ruby.
ruby : default
The ruby version to list the gemsets for
runas : None
The user to run rvm as.
The ruby version for which to list the gemsets
runas
The user under which to run rvm. If not specified, then rvm will be run
as the user under which Salt is running.
CLI Example:
@ -296,7 +311,7 @@ def gemset_list(ruby='default', runas=None):
salt '*' rvm.gemset_list
'''
gemsets = []
output = _rvm_do(ruby, 'rvm gemset list', runas=runas)
output = _rvm_do(ruby, ['rvm', 'gemset', 'list'], runas=runas)
if output:
regex = re.compile('^ ([^ ]+)')
for line in output.splitlines():
@ -308,14 +323,17 @@ def gemset_list(ruby='default', runas=None):
def gemset_delete(ruby, gemset, runas=None):
'''
Deletes a gemset.
Delete a gemset
ruby
The ruby version the gemset belongs to.
The ruby version to which the gemset belongs
gemset
The gemset to delete.
runas : None
The user to run rvm as.
The gemset to delete
runas
The user under which to run rvm. If not specified, then rvm will be run
as the user under which Salt is running.
CLI Example:
@ -324,7 +342,7 @@ def gemset_delete(ruby, gemset, runas=None):
salt '*' rvm.gemset_delete 2.0.0 foobar
'''
return _rvm_do(ruby,
'rvm --force gemset delete {gemset}'.format(gemset=gemset),
['rvm', '--force', 'gemset', 'delete', gemset],
runas=runas)
@ -333,11 +351,14 @@ def gemset_empty(ruby, gemset, runas=None):
Remove all gems from a gemset.
ruby
The ruby version the gemset belongs to.
The ruby version to which the gemset belongs
gemset
The gemset to empty.
runas : None
The user to run rvm as.
The gemset to empty
runas
The user under which to run rvm. If not specified, then rvm will be run
as the user under which Salt is running.
CLI Example:
@ -346,7 +367,7 @@ def gemset_empty(ruby, gemset, runas=None):
salt '*' rvm.gemset_empty 2.0.0 foobar
'''
return _rvm_do(ruby,
'rvm --force gemset empty {gemset}'.format(gemset=gemset),
['rvm', '--force', 'gemset', 'empty', gemset],
runas=runas)
@ -355,11 +376,14 @@ def gemset_copy(source, destination, runas=None):
Copy all gems from one gemset to another.
source
The name of the gemset to copy, complete with ruby version.
The name of the gemset to copy, complete with ruby version
destination
The destination gemset.
runas : None
The user to run rvm as.
The destination gemset
runas
The user under which to run rvm. If not specified, then rvm will be run
as the user under which Salt is running.
CLI Example:
@ -367,7 +391,7 @@ def gemset_copy(source, destination, runas=None):
salt '*' rvm.gemset_copy foobar bazquo
'''
return _rvm('gemset copy {0} {1}'.format(source, destination), runas=runas)
return _rvm(['gemset', 'copy', source, destination], runas=runas)
def gemset_list_all(runas=None):
@ -376,8 +400,9 @@ def gemset_list_all(runas=None):
Note that you must have set a default ruby before this can work.
runas : None
The user to run rvm as.
runas
The user under which to run rvm. If not specified, then rvm will be run
as the user under which Salt is running.
CLI Example:
@ -387,7 +412,7 @@ def gemset_list_all(runas=None):
'''
gemsets = {}
current_ruby = None
output = _rvm_do('default', 'rvm gemset list_all', runas=runas)
output = _rvm_do('default', ['rvm', 'gemset', 'list_all'], runas=runas)
if output:
gems_regex = re.compile('^ ([^ ]+)')
gemset_regex = re.compile('^gemsets for ([^ ]+)')
@ -406,14 +431,19 @@ def do(ruby, command, runas=None, cwd=None): # pylint: disable=C0103
'''
Execute a command in an RVM controlled environment.
ruby:
The ruby to use.
command:
The command to execute.
runas : None
The user to run rvm as.
cwd : None
The current working directory.
ruby
Which ruby to use
command
The rvm command to execute
runas
The user under which to run rvm. If not specified, then rvm will be run
as the user under which Salt is running.
cwd
The directory from which to run the rvm command. Defaults to the user's
home directory.
CLI Example:
@ -421,4 +451,8 @@ def do(ruby, command, runas=None, cwd=None): # pylint: disable=C0103
salt '*' rvm.do 2.0.0 <command>
'''
try:
command = shlex.split(command)
except AttributeError:
command = shlex.split(str(command))
return _rvm_do(ruby, command, runas=runas, cwd=cwd)

View File

@ -95,14 +95,14 @@ def _sync(form, saltenv=None):
source = salt.utils.url.create('_' + form)
mod_dir = os.path.join(__opts__['extension_modules'], '{0}'.format(form))
if not os.path.isdir(mod_dir):
log.info('Creating module dir {0!r}'.format(mod_dir))
log.info('Creating module dir \'{0}\''.format(mod_dir))
try:
os.makedirs(mod_dir)
except (IOError, OSError):
msg = 'Cannot create cache module directory {0}. Check permissions.'
log.error(msg.format(mod_dir))
for sub_env in saltenv:
log.info('Syncing {0} for environment {1!r}'.format(form, sub_env))
log.info('Syncing {0} for environment \'{1}\''.format(form, sub_env))
cache = []
log.info('Loading cache from {0}, for {1})'.format(source, sub_env))
# Grab only the desired files (.py, .pyx, .so)
@ -117,13 +117,13 @@ def _sync(form, saltenv=None):
sub_env,
'_{0}'.format(form)
)
log.debug('Local cache dir: {0!r}'.format(local_cache_dir))
log.debug('Local cache dir: \'{0}\''.format(local_cache_dir))
for fn_ in cache:
relpath = os.path.relpath(fn_, local_cache_dir)
relname = os.path.splitext(relpath)[0].replace(os.sep, '.')
remote.add(relpath)
dest = os.path.join(mod_dir, relpath)
log.info('Copying {0!r} to {1!r}'.format(fn_, dest))
log.info('Copying \'{0}\' to \'{1}\''.format(fn_, dest))
if os.path.isfile(dest):
# The file is present, if the sum differs replace it
hash_type = __opts__.get('hash_type', 'md5')

View File

@ -268,7 +268,7 @@ def _check_install(root):
sh_ = '/bin/bash'
cmd = ('if ! type salt-minion; then exit 1; fi')
cmd = 'chroot \'{0}\' {1} -c {2!r}'.format(
cmd = 'chroot \'{0}\' {1} -c \'{2}\''.format(
root,
sh_,
cmd)

View File

@ -7,14 +7,15 @@ Manage users with the useradd command
from __future__ import absolute_import
try:
import pwd
HAS_PWD = True
except ImportError:
pass
HAS_PWD = False
import copy
import logging
from copy import deepcopy
# Import salt libs
import salt.utils
from salt.ext.six import string_types
import salt.ext.six as six
from salt.exceptions import CommandExecutionError
log = logging.getLogger(__name__)
@ -27,8 +28,14 @@ def __virtual__():
'''
Set the user module if the kernel is SunOS
'''
return __virtualname__ if __grains__['kernel'] == 'SunOS' else False
if __grains__['kernel'] == 'SunOS':
if not HAS_PWD:
log.warning(
'pwd module not found, user management will not be possible'
)
else:
return __virtualname__
return False
def _get_gecos(name):
@ -59,6 +66,25 @@ def _build_gecos(gecos_dict):
gecos_dict.get('homephone', ''))
def _update_gecos(name, key, value):
'''
Common code to change a user's GECOS information
'''
if not isinstance(value, six.string_types):
value = str(value)
pre_info = _get_gecos(name)
if not pre_info:
return False
if value == pre_info[key]:
return True
gecos_data = copy.deepcopy(pre_info)
gecos_data[key] = value
cmd = ['usermod', '-c', _build_gecos(gecos_data), name]
__salt__['cmd.run'](cmd, python_shell=False)
post_info = info(name)
return _get_gecos(name).get(key) == value
def add(name,
uid=None,
gid=None,
@ -87,32 +113,26 @@ def add(name,
if kwargs:
log.warning('Invalid kwargs passed to user.add')
if isinstance(groups, string_types):
if isinstance(groups, six.string_types):
groups = groups.split(',')
cmd = 'useradd '
cmd = ['useradd']
if shell:
cmd += '-s {0} '.format(shell)
cmd.extend(['-s', shell])
if uid:
cmd += '-u {0} '.format(uid)
cmd.extend(['-u', uid])
if gid:
cmd += '-g {0} '.format(gid)
cmd.extend(['-g', gid])
if groups:
cmd += '-G {0} '.format(','.join(groups))
if home is None:
cmd.extend(['-G', ','.join(groups)])
if createhome:
cmd += '-m '
else:
if createhome:
cmd += '-m -d {0} '.format(home)
else:
cmd += '-d {0} '.format(home)
cmd.append('-m')
if home is not None:
cmd.extend(['-d', home])
if not unique:
cmd += '-o '
cmd += name
ret = __salt__['cmd.retcode'](cmd, python_shell=False)
if ret != 0:
cmd.append('-o')
cmd.append(name)
if __salt__['cmd.retcode'](cmd, python_shell=False) != 0:
return False
else:
# At this point, the user was successfully created, so return true
@ -145,16 +165,15 @@ def delete(name, remove=False, force=False):
salt '*' user.delete name remove=True force=True
'''
if salt.utils.is_true(force):
log.error('userdel does not support force-deleting user while '
'user is logged in')
cmd = 'userdel '
log.warning(
'userdel does not support force-deleting user while user is '
'logged in'
)
cmd = ['userdel']
if remove:
cmd += '-r '
cmd += name
ret = __salt__['cmd.run_all'](cmd, python_shell=False)
return not ret['retcode']
cmd.append('-r')
cmd.append(name)
return __salt__['cmd.retcode'](cmd, python_shell=False) == 0
def getent(refresh=False):
@ -188,14 +207,15 @@ def chuid(name, uid):
salt '*' user.chuid foo 4376
'''
pre_info = info(name)
if not pre_info:
raise CommandExecutionError(
'User \'{0}\' does not exist'.format(name)
)
if uid == pre_info['uid']:
return True
cmd = 'usermod -u {0} {1}'.format(uid, name)
cmd = ['usermod', '-u', uid, name]
__salt__['cmd.run'](cmd, python_shell=False)
post_info = info(name)
if post_info['uid'] != pre_info['uid']:
return post_info['uid'] == uid
return False
return info(name).get('uid') == uid
def chgid(name, gid):
@ -209,14 +229,15 @@ def chgid(name, gid):
salt '*' user.chgid foo 4376
'''
pre_info = info(name)
if not pre_info:
raise CommandExecutionError(
'User \'{0}\' does not exist'.format(name)
)
if gid == pre_info['gid']:
return True
cmd = 'usermod -g {0} {1}'.format(gid, name)
cmd = ['usermod', '-g', gid, name]
__salt__['cmd.run'](cmd, python_shell=False)
post_info = info(name)
if post_info['gid'] != pre_info['gid']:
return post_info['gid'] == gid
return False
return info(name).get('gid') == gid
def chshell(name, shell):
@ -230,20 +251,31 @@ def chshell(name, shell):
salt '*' user.chshell foo /bin/zsh
'''
pre_info = info(name)
if not pre_info:
raise CommandExecutionError(
'User \'{0}\' does not exist'.format(name)
)
if shell == pre_info['shell']:
return True
cmd = 'usermod -s {0} {1}'.format(shell, name)
cmd = ['usermod', '-s', shell, name]
__salt__['cmd.run'](cmd, python_shell=False)
post_info = info(name)
if post_info['shell'] != pre_info['shell']:
return post_info['shell'] == shell
return False
return info(name).get('shell') == shell
def chhome(name, home, persist=False):
'''
Change the home directory of the user, pass true for persist to copy files
to the new home dir
Set a new home directory for an existing user
name
Username to modify
home
New home directory to set
persist : False
Set to ``True`` to prevent configuration files in the new home
directory from being overwritten by the files from the skeleton
directory.
CLI Example:
@ -252,23 +284,35 @@ def chhome(name, home, persist=False):
salt '*' user.chhome foo /home/users/foo True
'''
pre_info = info(name)
if not pre_info:
raise CommandExecutionError(
'User \'{0}\' does not exist'.format(name)
)
if home == pre_info['home']:
return True
cmd = 'usermod -d {0} '.format(home)
cmd = ['usermod', '-d', home]
if persist:
cmd += ' -m '
cmd += name
cmd.append('-m')
cmd.append(name)
__salt__['cmd.run'](cmd, python_shell=False)
post_info = info(name)
if post_info['home'] != pre_info['home']:
return post_info['home'] == home
return False
return info(name).get('home') == home
def chgroups(name, groups, append=False):
'''
Change the groups this user belongs to, add append to append the specified
Change the groups to which a user belongs
name
Username to modify
groups
List of groups to set for the user. Can be passed as a comma-separated
list or a Python list.
append : False
Set to ``True`` to append these groups to the user's existing list of
groups. Otherwise, the specified groups will replace any existing
groups for the user.
CLI Example:
@ -276,15 +320,15 @@ def chgroups(name, groups, append=False):
salt '*' user.chgroups foo wheel,root True
'''
if isinstance(groups, string_types):
if isinstance(groups, six.string_types):
groups = groups.split(',')
ugrps = set(list_groups(name))
if ugrps == set(groups):
return True
if append:
groups += ugrps
cmd = 'usermod -G {0} {1} '.format(','.join(groups), name)
return not __salt__['cmd.retcode'](cmd, python_shell=False)
groups.update(ugrps)
cmd = ['usermod', '-G', ','.join(groups), name]
return __salt__['cmd.retcode'](cmd, python_shell=False) == 0
def chfullname(name, fullname):
@ -297,20 +341,7 @@ def chfullname(name, fullname):
salt '*' user.chfullname foo "Foo Bar"
'''
fullname = str(fullname)
pre_info = _get_gecos(name)
if not pre_info:
return False
if fullname == pre_info['fullname']:
return True
gecos_field = deepcopy(pre_info)
gecos_field['fullname'] = fullname
cmd = 'usermod -c "{0}" {1}'.format(_build_gecos(gecos_field), name)
__salt__['cmd.run'](cmd, python_shell=False)
post_info = info(name)
if post_info['fullname'] != pre_info['fullname']:
return post_info['fullname'] == fullname
return False
return _update_gecos(name, 'fullname', fullname)
def chroomnumber(name, roomnumber):
@ -323,20 +354,7 @@ def chroomnumber(name, roomnumber):
salt '*' user.chroomnumber foo 123
'''
roomnumber = str(roomnumber)
pre_info = _get_gecos(name)
if not pre_info:
return False
if roomnumber == pre_info['roomnumber']:
return True
gecos_field = deepcopy(pre_info)
gecos_field['roomnumber'] = roomnumber
cmd = 'usermod -c "{0}" {1}'.format(_build_gecos(gecos_field), name)
__salt__['cmd.run'](cmd, python_shell=False)
post_info = info(name)
if post_info['roomnumber'] != pre_info['roomnumber']:
return post_info['roomnumber'] == roomnumber
return False
return _update_gecos(name, 'roomnumber', roomnumber)
def chworkphone(name, workphone):
@ -349,20 +367,7 @@ def chworkphone(name, workphone):
salt '*' user.chworkphone foo "7735550123"
'''
workphone = str(workphone)
pre_info = _get_gecos(name)
if not pre_info:
return False
if workphone == pre_info['workphone']:
return True
gecos_field = deepcopy(pre_info)
gecos_field['workphone'] = workphone
cmd = 'usermod -c "{0}" {1}'.format(_build_gecos(gecos_field), name)
__salt__['cmd.run'](cmd, python_shell=False)
post_info = info(name)
if post_info['workphone'] != pre_info['workphone']:
return post_info['workphone'] == workphone
return False
return _update_gecos(name, 'workphone', workphone)
def chhomephone(name, homephone):
@ -375,20 +380,7 @@ def chhomephone(name, homephone):
salt '*' user.chhomephone foo "7735551234"
'''
homephone = str(homephone)
pre_info = _get_gecos(name)
if not pre_info:
return False
if homephone == pre_info['homephone']:
return True
gecos_field = deepcopy(pre_info)
gecos_field['homephone'] = homephone
cmd = 'usermod -c "{0}" {1}'.format(_build_gecos(gecos_field), name)
__salt__['cmd.run'](cmd, python_shell=False)
post_info = info(name)
if post_info['homephone'] != pre_info['homephone']:
return post_info['homephone'] == homephone
return False
return _update_gecos(name, 'homephone', homephone)
def info(name):
@ -450,13 +442,12 @@ def rename(name, new_name):
'''
current_info = info(name)
if not current_info:
raise CommandExecutionError('User {0!r} does not exist'.format(name))
raise CommandExecutionError('User \'{0}\' does not exist'.format(name))
new_info = info(new_name)
if new_info:
raise CommandExecutionError('User {0!r} already exists'.format(new_name))
cmd = 'usermod -l {0} {1}'.format(new_name, name)
__salt__['cmd.run'](cmd)
post_info = info(new_name)
if post_info['name'] != current_info['name']:
return post_info['name'] == new_name
return False
raise CommandExecutionError(
'User \'{0}\' already exists'.format(new_name)
)
cmd = ['usermod', '-l', new_name, name]
__salt__['cmd.run'](cmd, python_shell=False)
return info(new_name).get('name') == new_name

View File

@ -64,7 +64,7 @@ def _refine_enc(enc):
return 'ssh-ed25519'
else:
raise CommandExecutionError(
'Incorrect encryption key type {0!r}.'.format(enc)
'Incorrect encryption key type \'{0}\'.'.format(enc)
)
@ -114,7 +114,7 @@ def _get_config_file(user, config):
'''
uinfo = __salt__['user.info'](user)
if not uinfo:
raise CommandExecutionError('User {0!r} does not exist'.format(user))
raise CommandExecutionError('User \'{0}\' does not exist'.format(user))
home = uinfo['home']
if not os.path.isabs(config):
config = os.path.join(home, config)
@ -751,8 +751,9 @@ def get_known_host(user, hostname, config=None, port=None):
return full
ssh_hostname = _hostname_and_port_to_ssh_hostname(hostname, port)
cmd = 'ssh-keygen -F "{0}" -f "{1}"'.format(ssh_hostname, full)
lines = __salt__['cmd.run'](cmd, ignore_retcode=True,
cmd = ['ssh-keygen', '-F', ssh_hostname, '-f', full]
lines = __salt__['cmd.run'](cmd,
ignore_retcode=True,
python_shell=False).splitlines()
known_hosts = list(_parse_openssh_output(lines))
return known_hosts[0] if known_hosts else None
@ -771,19 +772,18 @@ def recv_known_host(hostname, enc=None, port=None, hash_hostname=False):
'''
# The following list of OSes have an old version of openssh-clients
# and thus require the '-t' option for ssh-keyscan
need_dash_t = ['CentOS-5']
need_dash_t = ('CentOS-5',)
chunks = ['ssh-keyscan']
cmd = ['ssh-keyscan']
if port:
chunks += ['-p', str(port)]
cmd.extend(['-p', port])
if enc:
chunks += ['-t', str(enc)]
cmd.extend(['-t', enc])
if not enc and __grains__.get('osfinger') in need_dash_t:
chunks += ['-t', 'rsa']
cmd.extend(['-t', 'rsa'])
if hash_hostname:
chunks.append('-H')
chunks.append(str(hostname))
cmd = ' '.join(chunks)
cmd.append('-H')
cmd.append(hostname)
lines = __salt__['cmd.run'](cmd, python_shell=False).splitlines()
known_hosts = list(_parse_openssh_output(lines))
return known_hosts[0] if known_hosts else None
@ -854,7 +854,7 @@ def rm_known_host(user=None, hostname=None, config=None, port=None):
'error': 'Known hosts file {0} does not exist'.format(full)}
ssh_hostname = _hostname_and_port_to_ssh_hostname(hostname, port)
cmd = 'ssh-keygen -R "{0}" -f "{1}"'.format(ssh_hostname, full)
cmd = ['ssh-keygen', '-R', ssh_hostname, '-f', full]
cmd_result = __salt__['cmd.run'](cmd, python_shell=False)
# ssh-keygen creates a new file, thus a chown is required.
if os.geteuid() == 0 and user:
@ -1139,7 +1139,7 @@ def hash_known_hosts(user=None, config=None):
if not os.path.isfile(full):
return {'status': 'error',
'error': 'Known hosts file {0} does not exist'.format(full)}
cmd = 'ssh-keygen -H -f "{0}"'.format(full)
cmd = ['ssh-keygen', '-H', '-f', full]
cmd_result = __salt__['cmd.run'](cmd, python_shell=False)
# ssh-keygen creates a new file, thus a chown is required.
if os.geteuid() == 0 and user:

View File

@ -59,7 +59,7 @@ def _ctl_cmd(cmd, name, conf_file, bin_env):
ret.append(cmd)
if name:
ret.append(name)
return ' ' .join(ret)
return ret
def _get_return(ret):
@ -395,7 +395,7 @@ def options(name, conf_file=None):
config = _read_config(conf_file)
section_name = 'program:{0}'.format(name)
if section_name not in config.sections():
raise CommandExecutionError('Process {0!r} not found'.format(name))
raise CommandExecutionError('Process \'{0}\' not found'.format(name))
ret = {}
for key, val in config.items(section_name):
val = salt.utils.str_to_num(val.split(';')[0].strip())

View File

@ -59,8 +59,8 @@ __func_alias__ = {
'reload_': 'reload'
}
_INDENT = ""
_INDENT_STEP = " "
_INDENT = ''
_INDENT_STEP = ' '
# These are needed during building of the configuration tree
_current_statement = None
@ -89,14 +89,14 @@ def _indent(value):
'''
Returns the indented parameter.
'''
return "{0}{1}".format(_INDENT, value)
return '{0}{1}'.format(_INDENT, value)
def _indentln(string):
'''
Return the indented parameter with newline.
'''
return _indent(string + "\n")
return _indent(string + '\n')
class Buildable(object):
@ -132,7 +132,7 @@ class Buildable(object):
_increase_indent()
body_array = [x.build() for x in self.iterable]
nl = "\n" if self.append_extra_newline else ''
nl = '\n' if self.append_extra_newline else ''
if len(self.iterable) >= 1:
body = self.join_body_on.join(body_array) + nl
@ -162,7 +162,9 @@ class Statement(Buildable):
'''
def __init__(self, type, id='', options=None, has_name=True):
super(Statement, self).__init__(options, join_body_on='', append_extra_newline=False)
super(Statement, self).__init__(options,
join_body_on='',
append_extra_newline=False)
self.type = type
self.id = id
self.options = options if options else []
@ -171,12 +173,12 @@ class Statement(Buildable):
def build_header(self):
if self.has_name:
return _indentln("{0} {1} {{".format(self.type, self.id))
return _indentln('{0} {1} {{'.format(self.type, self.id))
else:
return _indentln("{0} {{".format(self.type))
return _indentln('{0} {{'.format(self.type))
def build_tail(self):
return _indentln("};")
return _indentln('};')
def add_child(self, option):
self.options.append(option)
@ -201,7 +203,10 @@ class UnnamedStatement(Statement):
'''
def __init__(self, type, options=None):
super(UnnamedStatement, self).__init__(type, id='', options=options, has_name=False)
super(UnnamedStatement, self).__init__(type,
id='',
options=options,
has_name=False)
class GivenStatement(Buildable):
@ -219,7 +224,7 @@ class GivenStatement(Buildable):
def build(self):
if self.add_newline:
return self.value + "\n"
return self.value + '\n'
else:
return self.value
@ -234,14 +239,14 @@ class Option(Buildable):
'''
def __init__(self, type='', params=None):
super(Option, self).__init__(params, ",\n")
super(Option, self).__init__(params, ',\n')
self.type = type
self.params = params if params else []
self.iterable = self.params
def build(self):
header = _indentln("{0}(".format(self.type))
tail = _indentln(");")
header = _indentln('{0}('.format(self.type))
tail = _indentln(');')
body = self.build_body()
return header + body + tail
@ -263,7 +268,8 @@ class Parameter(Buildable):
class SimpleParameter(Parameter):
'''
A Parameter is a SimpleParameter, if it's just a simple type, like a string.
A Parameter is a SimpleParameter, if it's just a simple type, like a
string.
For example:
@ -271,7 +277,7 @@ class SimpleParameter(Parameter):
destination d_file {
file(
"/var/log/messages"
'/var/log/messages'
);
};
@ -306,14 +312,14 @@ class TypedParameter(Parameter):
'''
def __init__(self, type='', values=None):
super(TypedParameter, self).__init__(values, ",\n")
super(TypedParameter, self).__init__(values, ',\n')
self.type = type
self.values = values if values else []
self.iterable = self.values
def build(self):
header = _indentln("{0}(".format(self.type))
tail = _indent(")")
header = _indentln('{0}('.format(self.type))
tail = _indent(')')
body = self.build_body()
return header + body + tail
@ -364,8 +370,8 @@ class TypedParameterValue(ParameterValue):
ip(0.0.0.0)
port(1999)
tls(
key_file("/opt/syslog-ng/etc/syslog-ng/key.d/syslog-ng.key")
cert_file("/opt/syslog-ng/etc/syslog-ng/cert.d/syslog-ng.cert")
key_file('/opt/syslog-ng/etc/syslog-ng/key.d/syslog-ng.key')
cert_file('/opt/syslog-ng/etc/syslog-ng/cert.d/syslog-ng.cert')
)
);
};
@ -374,14 +380,14 @@ class TypedParameterValue(ParameterValue):
'''
def __init__(self, type='', arguments=None):
super(TypedParameterValue, self).__init__(arguments, "\n")
super(TypedParameterValue, self).__init__(arguments, '\n')
self.type = type
self.arguments = arguments if arguments else []
self.iterable = self.arguments
def build(self):
header = _indentln("{0}(".format(self.type))
tail = _indent(")")
header = _indentln('{0}('.format(self.type))
tail = _indent(')')
body = self.build_body()
return header + body + tail
@ -650,7 +656,7 @@ def config(name,
.. code-block:: bash
salt '*' syslog_ng.config name="s_local" config="[{'tcp':[{'ip':'127.0.0.1'},{'port':1233}]}]"
salt '*' syslog_ng.config name='s_local' config="[{'tcp':[{'ip':'127.0.0.1'},{'port':1233}]}]"
'''
@ -658,14 +664,18 @@ def config(name,
configs = _render_configuration()
if __opts__.get('test', False):
comment = "State syslog_ng will write '{0}' into {1}".format(configs, __SYSLOG_NG_CONFIG_FILE)
comment = 'State syslog_ng will write \'{0}\' into {1}'.format(
configs,
__SYSLOG_NG_CONFIG_FILE
)
return _format_state_result(name, result=None, comment=comment)
succ = write
if write:
succ = _write_config(config=configs)
return _format_state_result(name, result=succ, changes={'new': configs, 'old': ''})
return _format_state_result(name, result=succ,
changes={'new': configs, 'old': ''})
def set_binary_path(name):
@ -680,7 +690,7 @@ def set_binary_path(name):
.. code-block:: bash
salt '*' syslog_ng.set_binary_path name="/usr/sbin"
salt '*' syslog_ng.set_binary_path name=/usr/sbin
'''
global __SYSLOG_NG_BINARY_PATH
@ -692,13 +702,14 @@ def set_binary_path(name):
def set_config_file(name):
'''
Sets the configuration's name. This function is intended to be used from states.
Sets the configuration's name. This function is intended to be used from
states.
CLI Example:
.. code-block:: bash
salt '*' syslog_ng.set_config_file name="/etc/syslog-ng"
salt '*' syslog_ng.set_config_file name=/etc/syslog-ng
'''
global __SYSLOG_NG_CONFIG_FILE
@ -724,19 +735,12 @@ def get_config_file():
def _run_command(cmd, options=()):
'''
Runs the command cmd with options as its CLI parameters and returns the result
as a dictionary.
Runs the command cmd with options as its CLI parameters and returns the
result as a dictionary.
'''
cmd_with_params = [cmd]
cmd_with_params.extend(options)
cmd_to_run = " ".join(cmd_with_params)
try:
return __salt__['cmd.run_all'](cmd_to_run)
except Exception as err:
log.error(str(err))
raise CommandExecutionError("Unable to run command: " + str(type(err)))
params = [cmd]
params.extend(options)
return __salt__['cmd.run_all'](params, python_shell=False)
def _determine_config_version(syslog_ng_sbin_dir):
@ -764,8 +768,8 @@ def set_parameters(version=None,
.. code-block:: bash
salt '*' syslog_ng.set_parameters version="3.6"
salt '*' syslog_ng.set_parameters binary_path="/home/user/install/syslog-ng/sbin" config_file="/home/user/install/syslog-ng/etc/syslog-ng.conf"
salt '*' syslog_ng.set_parameters version='3.6'
salt '*' syslog_ng.set_parameters binary_path=/home/user/install/syslog-ng/sbin config_file=/home/user/install/syslog-ng/etc/syslog-ng.conf
'''
if binary_path:
@ -787,10 +791,11 @@ def _add_to_path_envvar(directory):
orig_path = os.environ.get('PATH', '')
if directory:
if not os.path.isdir(directory):
log.error("The given parameter is not a directory")
os.environ["PATH"] = "{0}{1}{2}".format(orig_path, os.pathsep, directory)
log.error('The given parameter is not a directory')
os.environ['PATH'] = '{0}{1}{2}'.format(orig_path,
os.pathsep,
directory)
return orig_path
@ -799,7 +804,7 @@ def _restore_path_envvar(original):
Sets the PATH environment variable to the parameter.
'''
if original:
os.environ["PATH"] = original
os.environ['PATH'] = original
def _run_command_in_extended_path(syslog_ng_sbin_dir, command, params):
@ -810,7 +815,10 @@ def _run_command_in_extended_path(syslog_ng_sbin_dir, command, params):
orig_path = _add_to_path_envvar(syslog_ng_sbin_dir)
if not salt.utils.which(command):
error_message = "Unable to execute the command '{0}'. It is not in the PATH.".format(command)
error_message = (
'Unable to execute the command \'{0}\'. It is not in the PATH.'
.format(command)
)
log.error(error_message)
_restore_path_envvar(orig_path)
raise CommandExecutionError(error_message)
@ -825,11 +833,11 @@ def _format_return_data(retcode, stdout=None, stderr=None):
Creates a dictionary from the parameters, which can be used to return data
to Salt.
'''
ret = {"retcode": retcode}
ret = {'retcode': retcode}
if stdout is not None:
ret["stdout"] = stdout
ret['stdout'] = stdout
if stderr is not None:
ret["stderr"] = stderr
ret['stderr'] = stderr
return ret
@ -846,25 +854,28 @@ def config_test(syslog_ng_sbin_dir=None, cfgfile=None):
salt '*' syslog_ng.config_test /home/user/install/syslog-ng/sbin
salt '*' syslog_ng.config_test /home/user/install/syslog-ng/sbin /etc/syslog-ng/syslog-ng.conf
'''
params = ["--syntax-only", ]
params = ['--syntax-only']
if cfgfile:
params.append("--cfgfile={0}".format(cfgfile))
params.append('--cfgfile={0}'.format(cfgfile))
try:
ret = _run_command_in_extended_path(syslog_ng_sbin_dir, "syslog-ng", params)
ret = _run_command_in_extended_path(syslog_ng_sbin_dir,
'syslog-ng',
params)
except CommandExecutionError as err:
return _format_return_data(retcode=-1, stderr=str(err))
retcode = ret.get("retcode", -1)
stderr = ret.get("stderr", None)
stdout = ret.get("stdout", None)
retcode = ret.get('retcode', -1)
stderr = ret.get('stderr', None)
stdout = ret.get('stdout', None)
return _format_return_data(retcode, stdout, stderr)
def version(syslog_ng_sbin_dir=None):
'''
Returns the version of the installed syslog-ng. If syslog_ng_sbin_dir is specified, it
is added to the PATH during the execution of the command syslog-ng.
Returns the version of the installed syslog-ng. If syslog_ng_sbin_dir is
specified, it is added to the PATH during the execution of the command
syslog-ng.
CLI Example:
@ -874,14 +885,18 @@ def version(syslog_ng_sbin_dir=None):
salt '*' syslog_ng.version /home/user/install/syslog-ng/sbin
'''
try:
ret = _run_command_in_extended_path(syslog_ng_sbin_dir, "syslog-ng", ("-V",))
ret = _run_command_in_extended_path(syslog_ng_sbin_dir,
'syslog-ng',
('-V',))
except CommandExecutionError as err:
return _format_return_data(retcode=-1, stderr=str(err))
if ret["retcode"] != 0:
return _format_return_data(ret["retcode"], stderr=ret["stderr"], stdout=ret["stdout"])
if ret['retcode'] != 0:
return _format_return_data(ret['retcode'],
stderr=ret['stderr'],
stdout=ret['stdout'])
lines = ret["stdout"].split("\n")
lines = ret['stdout'].split('\n')
# The format of the first line in the output is:
# syslog-ng 3.6.0alpha0
version_line_index = 0
@ -903,25 +918,31 @@ def modules(syslog_ng_sbin_dir=None):
salt '*' syslog_ng.modules /home/user/install/syslog-ng/sbin
'''
try:
ret = _run_command_in_extended_path(syslog_ng_sbin_dir, "syslog-ng", ("-V",))
ret = _run_command_in_extended_path(syslog_ng_sbin_dir,
'syslog-ng',
('-V',))
except CommandExecutionError as err:
return _format_return_data(retcode=-1, stderr=str(err))
if ret["retcode"] != 0:
return _format_return_data(ret["retcode"], ret.get("stdout", None), ret.get("stderr", None))
if ret['retcode'] != 0:
return _format_return_data(ret['retcode'],
ret.get('stdout'),
ret.get('stderr'))
lines = ret["stdout"].split("\n")
lines = ret['stdout'].split('\n')
for line in lines:
if line.startswith("Available-Modules"):
if line.startswith('Available-Modules'):
label, installed_modules = line.split()
return _format_return_data(ret["retcode"], stdout=installed_modules)
return _format_return_data(-1, stderr="Unable to find the modules.")
return _format_return_data(ret['retcode'],
stdout=installed_modules)
return _format_return_data(-1, stderr='Unable to find the modules.')
def stats(syslog_ng_sbin_dir=None):
'''
Returns statistics from the running syslog-ng instance. If syslog_ng_sbin_dir is specified, it
is added to the PATH during the execution of the command syslog-ng-ctl.
Returns statistics from the running syslog-ng instance. If
syslog_ng_sbin_dir is specified, it is added to the PATH during the
execution of the command syslog-ng-ctl.
CLI Example:
@ -931,11 +952,15 @@ def stats(syslog_ng_sbin_dir=None):
salt '*' syslog_ng.stats /home/user/install/syslog-ng/sbin
'''
try:
ret = _run_command_in_extended_path(syslog_ng_sbin_dir, "syslog-ng-ctl", ("stats",))
ret = _run_command_in_extended_path(syslog_ng_sbin_dir,
'syslog-ng-ctl',
('stats',))
except CommandExecutionError as err:
return _format_return_data(retcode=-1, stderr=str(err))
return _format_return_data(ret["retcode"], ret.get("stdout", None), ret.get("stderr", None))
return _format_return_data(ret['retcode'],
ret.get('stdout'),
ret.get('stderr'))
def _format_changes(old='', new=''):
@ -948,7 +973,8 @@ def _format_state_result(name, result, changes=None, comment=''):
'''
if changes is None:
changes = {'old': '', 'new': ''}
return {'name': name, 'result': result, 'changes': changes, 'comment': comment}
return {'name': name, 'result': result,
'changes': changes, 'comment': comment}
def _add_cli_param(params, key, value):
@ -972,8 +998,9 @@ def stop(name=None):
Kills syslog-ng. This function is intended to be used from the state module.
Users shouldn't use this function, if the service module is available on
their system. If :mod:`syslog_ng.set_config_file <salt.modules.syslog_ng.set_binary_path>`
is called before, this function will use the set binary path.
their system. If :mod:`syslog_ng.set_config_file
<salt.modules.syslog_ng.set_binary_path>` is called before, this function
will use the set binary path.
CLI Example:
@ -990,7 +1017,7 @@ def stop(name=None):
comment='Syslog-ng is not running')
if __opts__.get('test', False):
comment = "Syslog_ng state module will kill {0} pids"
comment = 'Syslog_ng state module will kill {0} pids'
return _format_state_result(name, result=None, comment=comment)
res = __salt__['ps.pkill']('syslog-ng')
@ -1024,8 +1051,9 @@ def start(name=None,
is intended to be used from the state module.
Users shouldn't use this function, if the service module is available on
their system. If :mod:`syslog_ng.set_config_file <salt.modules.syslog_ng.set_binary_path>`,
is called before, this function will use the set binary path.
their system. If :mod:`syslog_ng.set_config_file
<salt.modules.syslog_ng.set_binary_path>`, is called before, this function
will use the set binary path.
CLI Example:
@ -1051,24 +1079,23 @@ def start(name=None,
_add_boolean_cli_param(params, 'persist-file', persist_file)
_add_cli_param(params, 'control', control)
_add_cli_param(params, 'worker-threads', worker_threads)
cli_params = ' '.join(params)
if __SYSLOG_NG_BINARY_PATH:
syslog_ng_binary = os.path.join(__SYSLOG_NG_BINARY_PATH, 'syslog-ng')
command = syslog_ng_binary + ' ' + cli_params
command = [syslog_ng_binary] + params
if __opts__.get('test', False):
comment = "Syslog_ng state module will start {0}".format(command)
comment = 'Syslog_ng state module will start {0}'.format(command)
return _format_state_result(name, result=None, comment=comment)
result = __salt__['cmd.run_all'](command)
result = __salt__['cmd.run_all'](command, python_shell=False)
else:
command = 'syslog-ng ' + cli_params
command = ['syslog-ng'] + params
if __opts__.get('test', False):
comment = "Syslog_ng state module will start {0}".format(command)
comment = 'Syslog_ng state module will start {0}'.format(command)
return _format_state_result(name, result=None, comment=comment)
result = __salt__['cmd.run_all'](command)
result = __salt__['cmd.run_all'](command, python_shell=False)
if result['pid'] > 0:
succ = True
@ -1076,7 +1103,7 @@ def start(name=None,
succ = False
return _format_state_result(
name, result=succ, changes={'new': command, 'old': ''}
name, result=succ, changes={'new': ' '.join(command), 'old': ''}
)
@ -1084,8 +1111,9 @@ def reload_(name):
'''
Reloads syslog-ng. This function is intended to be used from states.
If :mod:`syslog_ng.set_config_file <salt.modules.syslog_ng.set_binary_path>`,
is called before, this function will use the set binary path.
If :mod:`syslog_ng.set_config_file
<salt.modules.syslog_ng.set_binary_path>`, is called before, this function
will use the set binary path.
CLI Example:
@ -1095,12 +1123,13 @@ def reload_(name):
'''
if __SYSLOG_NG_BINARY_PATH:
syslog_ng_ctl_binary = os.path.join(__SYSLOG_NG_BINARY_PATH, 'syslog-ng-ctl')
command = syslog_ng_ctl_binary + ' reload'
result = __salt__['cmd.run_all'](command)
syslog_ng_ctl_binary = os.path.join(__SYSLOG_NG_BINARY_PATH,
'syslog-ng-ctl')
command = [syslog_ng_ctl_binary, 'reload']
result = __salt__['cmd.run_all'](command, python_shell=False)
else:
command = 'syslog-ng-ctl reload'
result = __salt__['cmd.run_all'](command)
command = ['syslog-ng-ctl', 'reload']
result = __salt__['cmd.run_all'](command, python_shell=False)
succ = True if result['retcode'] == 0 else False
return _format_state_result(name, result=succ, comment=result['stdout'])
@ -1119,14 +1148,15 @@ def write_config(config, newlines=2):
Writes the given parameter config into the config file. This function is
intended to be used from states.
If :mod:`syslog_ng.set_config_file <salt.modules.syslog_ng.set_config_file>`,
is called before, this function will use the set config file.
If :mod:`syslog_ng.set_config_file
<salt.modules.syslog_ng.set_config_file>`, is called before, this function
will use the set config file.
CLI Example:
.. code-block:: bash
salt '*' syslog_ng.write_config config="# comment"
salt '*' syslog_ng.write_config config='# comment'
'''
succ = _write_config(config, newlines)
@ -1157,11 +1187,12 @@ def _write_config(config, newlines=2):
def write_version(name):
'''
Removes the previous configuration file, then creates a new one and writes the name line.
This function is intended to be used from states.
Removes the previous configuration file, then creates a new one and writes
the name line. This function is intended to be used from states.
If :mod:`syslog_ng.set_config_file <salt.modules.syslog_ng.set_config_file>`,
is called before, this function will use the set config file.
If :mod:`syslog_ng.set_config_file
<salt.modules.syslog_ng.set_config_file>`, is called before, this function
will use the set config file.
CLI Example:
@ -1174,7 +1205,9 @@ def write_version(name):
try:
if os.path.exists(__SYSLOG_NG_CONFIG_FILE):
log.debug(
'Removing previous configuration file: {0}'.format(__SYSLOG_NG_CONFIG_FILE)
'Removing previous configuration file: {0}'.format(
__SYSLOG_NG_CONFIG_FILE
)
)
os.remove(__SYSLOG_NG_CONFIG_FILE)
log.debug('Configuration file successfully removed')
@ -1184,9 +1217,9 @@ def write_version(name):
_write_config(config=line, newlines=2)
return _format_state_result(name, result=True)
except os.error as err:
except OSError as err:
log.error(
'Failed to remove previous configuration file {0!r} because: {1}'
'Failed to remove previous configuration file \'{0}\': {1}'
.format(__SYSLOG_NG_CONFIG_FILE, str(err))
)
return _format_state_result(name, result=False)

View File

@ -13,6 +13,7 @@ import string
# Import salt libs
import salt.utils
import salt.utils.itertools
from salt.exceptions import SaltInvocationError, CommandExecutionError
log = logging.getLogger(__name__)
@ -101,7 +102,7 @@ def get_zone():
cmd = ''
if salt.utils.which('timedatectl'):
out = __salt__['cmd.run'](['timedatectl'], python_shell=False)
for line in (x.strip() for x in out.splitlines()):
for line in (x.strip() for x in salt.utils.itertools.split(out, '\n')):
try:
return re.match(r'Time ?zone:\s+(\S+)', line).group(1)
except AttributeError:
@ -237,7 +238,7 @@ def zone_compare(timezone):
try:
usrzone = salt.utils.get_hash(zonepath, hash_type)
except IOError as exc:
raise SaltInvocationError('Invalid timezone {0!r}'.format(timezone))
raise SaltInvocationError('Invalid timezone \'{0}\''.format(timezone))
try:
etczone = salt.utils.get_hash(tzfile, hash_type)

View File

@ -9,11 +9,10 @@ import glob
import shutil
import logging
import os
import os.path
# Import salt libs
import salt.utils
import salt.exceptions
from salt.exceptions import CommandExecutionError, SaltInvocationError
from salt.ext.six import string_types
KNOWN_BINARY_NAMES = frozenset(
@ -40,6 +39,20 @@ def __virtual__():
return __virtualname__
def _not_a_virtualenv(path):
raise CommandExecutionError(
'Path \'{0}\' does not appear to be a virtualenv'.format(path)
)
def _verify_safe_py_code(*args):
for arg in args:
if not salt.utils.verify.safe_py_code(arg):
raise SaltInvocationError(
'Unsafe python code detected in \'{0}\''.format(arg)
)
def create(path,
venv_bin=None,
system_site_packages=False,
@ -59,42 +72,56 @@ def create(path,
Create a virtualenv
path
The path to create the virtualenv
venv_bin : None (default 'virtualenv')
The path to the virtualenv to be created
venv_bin
The name (and optionally path) of the virtualenv command. This can also
be set globally in the minion config file as ``virtualenv.venv_bin``.
Defaults to ``virtualenv``.
system_site_packages : False
Passthrough argument given to virtualenv or pyvenv
distribute : False
Passthrough argument given to virtualenv
pip : False
Install pip after creating a virtual environment,
implies distribute=True
Install pip after creating a virtual environment. Implies
``distribute=True``
clear : False
Passthrough argument given to virtualenv or pyvenv
python : None (default)
Passthrough argument given to virtualenv
extra_search_dir : None (default)
Passthrough argument given to virtualenv
never_download : None (default)
Passthrough argument given to virtualenv if True
prompt : None (default)
Passthrough argument given to virtualenv if not None
symlinks : None
Passthrough argument given to pyvenv if True
upgrade : None
Passthrough argument given to pyvenv if True
user : None
Set ownership for the virtualenv
runas : None
Set ownership for the virtualenv
.. deprecated:: 2014.1.0
``user`` should be used instead
use_vt
Use VT terminal emulation (see ouptut while installing)
.. note::
The ``runas`` argument is deprecated as of 2014.1.0. ``user`` should be
used instead.
CLI Example:
.. code-block:: bash
@ -113,14 +140,14 @@ def create(path,
# If any of the following values are not None, it means that the user
# is actually passing a True or False value. Stop Him!
if upgrade is not None:
raise salt.exceptions.CommandExecutionError(
raise CommandExecutionError(
'The `upgrade`(`--upgrade`) option is not supported '
'by {0!r}'.format(venv_bin)
'by \'{0}\''.format(venv_bin)
)
elif symlinks is not None:
raise salt.exceptions.CommandExecutionError(
raise CommandExecutionError(
'The `symlinks`(`--symlinks`) option is not supported '
'by {0!r}'.format(venv_bin)
'by \'{0}\''.format(venv_bin)
)
# <---- Stop the user if pyvenv only options are used ----------------
@ -134,14 +161,14 @@ def create(path,
)
except ImportError:
# Unable to import?? Let's parse the version from the console
version_cmd = '{0} --version'.format(venv_bin)
version_cmd = [venv_bin, '--version']
ret = __salt__['cmd.run_all'](
version_cmd, runas=user, python_shell=False
)
if ret['retcode'] > 0 or not ret['stdout'].strip():
raise salt.exceptions.CommandExecutionError(
'Unable to get the virtualenv version output using {0!r}. '
'Returned data: {1!r}'.format(version_cmd, ret)
raise CommandExecutionError(
'Unable to get the virtualenv version output using \'{0}\'. '
'Returned data: {1}'.format(version_cmd, ret)
)
virtualenv_version_info = tuple(
[int(i) for i in
@ -161,7 +188,7 @@ def create(path,
if python is not None and python.strip() != '':
if not salt.utils.which(python):
raise salt.exceptions.CommandExecutionError(
raise CommandExecutionError(
'Cannot find requested python ({0}).'.format(python)
)
cmd.append('--python={0}'.format(python))
@ -184,7 +211,7 @@ def create(path,
else:
cmd.append('--never-download')
if prompt is not None and prompt.strip() != '':
cmd.append('--prompt={0!r}'.format(prompt))
cmd.append('--prompt=\'{0}\''.format(prompt))
else:
# venv module from the Python >= 3.3 standard library
@ -192,24 +219,24 @@ def create(path,
# If any of the following values are not None, it means that the user
# is actually passing a True or False value. Stop Him!
if python is not None and python.strip() != '':
raise salt.exceptions.CommandExecutionError(
raise CommandExecutionError(
'The `python`(`--python`) option is not supported '
'by {0!r}'.format(venv_bin)
'by \'{0}\''.format(venv_bin)
)
elif extra_search_dir is not None and extra_search_dir.strip() != '':
raise salt.exceptions.CommandExecutionError(
raise CommandExecutionError(
'The `extra_search_dir`(`--extra-search-dir`) option is not '
'supported by {0!r}'.format(venv_bin)
'supported by \'{0}\''.format(venv_bin)
)
elif never_download is not None:
raise salt.exceptions.CommandExecutionError(
raise CommandExecutionError(
'The `never_download`(`--never-download`) option is not '
'supported by {0!r}'.format(venv_bin)
'supported by \'{0}\''.format(venv_bin)
)
elif prompt is not None and prompt.strip() != '':
raise salt.exceptions.CommandExecutionError(
raise CommandExecutionError(
'The `prompt`(`--prompt`) option is not supported '
'by {0!r}'.format(venv_bin)
'by \'{0}\''.format(venv_bin)
)
# <---- Stop the user if virtualenv only options are being used ------
@ -290,12 +317,16 @@ def get_site_packages(venv):
'''
bin_path = os.path.join(venv, 'bin/python')
if not os.path.exists(bin_path):
raise salt.exceptions.CommandExecutionError("Path does not appear to be a virtualenv: '{0}'".format(venv))
_not_a_virtualenv(venv)
ret = __salt__['cmd.exec_code_all'](bin_path, 'from distutils import sysconfig; print sysconfig.get_python_lib()')
ret = __salt__['cmd.exec_code_all'](
bin_path,
'from distutils import sysconfig; '
'print sysconfig.get_python_lib()'
)
if ret['retcode'] != 0:
raise salt.exceptions.CommandExecutionError('{stdout}\n{stderr}'.format(**ret))
raise CommandExecutionError('{stdout}\n{stderr}'.format(**ret))
return ret['stdout']
@ -318,37 +349,59 @@ def get_distribution_path(venv, distribution):
salt '*' virtualenv.get_distribution_path /path/to/my/venv my_distribution
'''
if not salt.utils.verify.safe_py_code(distribution):
raise salt.exceptions.CommandExecutionError
_verify_safe_py_code(distribution)
bin_path = os.path.join(venv, 'bin/python')
if not os.path.exists(bin_path):
raise salt.exceptions.CommandExecutionError("Path does not appear to be a virtualenv: '{0}'".format(venv))
_not_a_virtualenv(venv)
ret = __salt__['cmd.exec_code_all'](bin_path, "import pkg_resources; print(pkg_resources.get_distribution('{0}').location)".format(distribution))
ret = __salt__['cmd.exec_code_all'](
bin_path,
'import pkg_resources; '
"print(pkg_resources.get_distribution('{0}').location)".format(
distribution
)
)
if ret['retcode'] != 0:
raise salt.exceptions.CommandExecutionError('{stdout}\n{stderr}'.format(bin_path=bin_path, **ret))
raise CommandExecutionError('{stdout}\n{stderr}'.format(**ret))
return ret['stdout']
def get_resource_path(venv, package_or_requirement=None, resource_name=None, package=None, resource=None):
def get_resource_path(venv,
package_or_requirement=None,
resource_name=None,
package=None,
resource=None):
'''
Returns the path to a resource of a package or a distribution inside a virtualenv
Returns the path to a resource of a package or a distribution inside a
virtualenv
venv
Path to the virtualenv.
Path to the virtualenv
package
Name of the package in which the resource resides
.. versionadded:: Boron
Name of the package where the resource resides in.
package_or_requirement
Deprecated in favor of package.
Name of the package in which the resource resides
.. deprecated:: Boron
Use ``package`` instead.
resource
Name of the resource of which the path is to be returned
.. versionadded:: Boron
Name of the resource of which the path is to be returned.
resource_name
Deprecated in favor of resource.
Name of the resource of which the path is to be returned
.. deprecated:: Boron
CLI Example:
@ -357,49 +410,84 @@ def get_resource_path(venv, package_or_requirement=None, resource_name=None, pac
salt '*' virtualenv.get_resource_path /path/to/my/venv my_package my/resource.xml
'''
if package_or_requirement is not None:
salt.utils.warn_until('Nitrogen', "Use 'package' in favor of 'package_or_requirement'.")
salt.utils.warn_until(
'Nitrogen',
'The \'package_or_requirement\' argument to '
'virtualenv.get_resource_path is deprecated. Please use '
'\'package\' instead.'
)
if package is not None:
raise salt.exceptions.CommandExecutionError("Do not use 'package' and 'package_or_requirement' as the same time.")
raise CommandExecutionError(
'Only one of \'package\' and \'package_or_requirement\' is '
'permitted.'
)
package = package_or_requirement
if resource_name is not None:
salt.utils.warn_until('Nitrogen', "Use 'resource' in favor of 'resource_name'.")
salt.utils.warn_until(
'Nitrogen',
'The \'resource_name\' argument to virtualenv.get_resource_path '
'is deprecated. Please use \'resource\' instead.'
)
if resource is not None:
raise salt.exceptions.CommandExecutionError("Do not use 'resource' and 'resource_name' as the same time.")
raise CommandExecutionError(
'Only one of \'resource\' and \'resource_name\' is permitted.'
)
resource = resource_name
if not salt.utils.verify.safe_py_code(package):
raise salt.exceptions.CommandExecutionError
if not salt.utils.verify.safe_py_code(resource):
raise salt.exceptions.CommandExecutionError
_verify_safe_py_code(package, resource)
bin_path = os.path.join(venv, 'bin/python')
if not os.path.exists(bin_path):
raise salt.exceptions.CommandExecutionError("Path does not appear to be a virtualenv: '{0}'".format(venv))
_not_a_virtualenv(venv)
ret = __salt__['cmd.exec_code_all'](bin_path, "import pkg_resources; print pkg_resources.resource_filename('{0}', '{1}')".format(package, resource))
ret = __salt__['cmd.exec_code_all'](
bin_path,
'import pkg_resources; '
"print(pkg_resources.resource_filename('{0}', '{1}'))".format(
package,
resource
)
)
if ret['retcode'] != 0:
raise salt.exceptions.CommandExecutionError('{stdout}\n{stderr}'.format(**ret))
raise CommandExecutionError('{stdout}\n{stderr}'.format(**ret))
return ret['stdout']
def get_resource_content(venv, package_or_requirement=None, resource_name=None, package=None, resource=None):
def get_resource_content(venv,
package_or_requirement=None,
resource_name=None,
package=None,
resource=None):
'''
Returns the content of a resource of a package or a distribution inside a virtualenv
Returns the content of a resource of a package or a distribution inside a
virtualenv
venv
Path to the virtualenv.
Path to the virtualenv
package
Name of the package in which the resource resides
.. versionadded:: Boron
Name of the package where the resource resides in.
package_or_requirement
Deprecated in favor of package.
Name of the package in which the resource resides
.. deprecated:: Boron
Use ``package`` instead.
resource
Name of the resource of which the content is to be returned
.. versionadded:: Boron
Name of the resource of which the content is to be returned.
resource_name
Deprecated in favor of resource.
Name of the resource of which the content is to be returned
.. deprecated:: Boron
CLI Example:
@ -408,29 +496,48 @@ def get_resource_content(venv, package_or_requirement=None, resource_name=None,
salt '*' virtualenv.get_resource_content /path/to/my/venv my_package my/resource.xml
'''
if package_or_requirement is not None:
salt.utils.warn_until('Nitrogen', "Use 'package' in favor of 'package_or_requirement'.")
salt.utils.warn_until(
'Nitrogen',
'The \'package_or_requirement\' argument to '
'virtualenv.get_resource_content is deprecated. Please use '
'\'package\' instead.'
)
if package is not None:
raise salt.exceptions.CommandExecutionError("Do not use 'package' and 'package_or_requirement' as the same time.")
raise CommandExecutionError(
'Only one of \'package\' and \'package_or_requirement\' is '
'permitted.'
)
package = package_or_requirement
if resource_name is not None:
salt.utils.warn_until('Nitrogen', "Use 'resource' in favor of 'resource_name'.")
salt.utils.warn_until(
'Nitrogen',
'The \'resource_name\' argument to '
'virtualenv.get_resource_content is deprecated. Please use '
'\'resource\' instead.'
)
if resource is not None:
raise salt.exceptions.CommandExecutionError("Do not use 'resource' and 'resource_name' as the same time.")
raise CommandExecutionError(
'Only one of \'resource\' and \'resource_name\' is permitted.'
)
resource = resource_name
if not salt.utils.verify.safe_py_code(package):
raise salt.exceptions.CommandExecutionError
if not salt.utils.verify.safe_py_code(resource):
raise salt.exceptions.CommandExecutionError
_verify_safe_py_code(package, resource)
bin_path = os.path.join(venv, 'bin/python')
if not os.path.exists(bin_path):
raise salt.exceptions.CommandExecutionError("Path does not appear to be a virtualenv: '{0}'".format(venv))
_not_a_virtualenv(venv)
ret = __salt__['cmd.exec_code_all'](bin_path, "import pkg_resources; print pkg_resources.resource_string('{0}', '{1}')".format(package, resource))
ret = __salt__['cmd.exec_code_all'](
bin_path,
'import pkg_resources; '
"print(pkg_resources.resource_string('{0}', '{1}'))".format(
package,
resource
)
)
if ret['retcode'] != 0:
raise salt.exceptions.CommandExecutionError('{stdout}\n{stderr}'.format(**ret))
raise CommandExecutionError('{stdout}\n{stderr}'.format(**ret))
return ret['stdout']
@ -448,7 +555,7 @@ def _install_script(source, cwd, python, user, saltenv='base', use_vt=False):
os.chown(tmppath, __salt__['file.user_to_uid'](user), -1)
try:
return __salt__['cmd.run_all'](
'{0} {1}'.format(python, tmppath),
[python, tmppath],
runas=user,
cwd=cwd,
env={'VIRTUAL_ENV': cwd},

View File

@ -1083,7 +1083,11 @@ def symlink(src, link):
return True
except pywinerror as exc:
raise CommandExecutionError(
'Could not create {0!r} - [{1}] {2}'.format(link, exc.winerror, exc.strerror)
'Could not create \'{0}\' - [{1}] {2}'.format(
link,
exc.winerror,
exc.strerror
)
)

View File

@ -157,7 +157,9 @@ def is_enabled(iface):
iface_found = True
return line.split()[-1] == 'Connected'
if not iface_found:
raise CommandExecutionError('Interface {0!r} not found'.format(iface))
raise CommandExecutionError(
'Interface \'{0}\' not found'.format(iface)
)
return False
@ -219,7 +221,9 @@ def get_subnet_length(mask):
salt -G 'os_family:Windows' ip.get_subnet_length 255.255.255.0
'''
if not salt.utils.validate.net.netmask(mask):
raise SaltInvocationError('{0!r} is not a valid netmask'.format(mask))
raise SaltInvocationError(
'\'{0}\' is not a valid netmask'.format(mask)
)
return salt.utils.network.get_net_size(mask)
@ -262,11 +266,11 @@ def set_static_ip(iface, addr, gateway=None, append=False):
return {}
if not salt.utils.validate.net.ipv4_addr(addr):
raise SaltInvocationError('Invalid address {0!r}'.format(addr))
raise SaltInvocationError('Invalid address \'{0}\''.format(addr))
if gateway and not salt.utils.validate.net.ipv4_addr(addr):
raise SaltInvocationError(
'Invalid default gateway {0!r}'.format(gateway)
'Invalid default gateway \'{0}\''.format(gateway)
)
if '/' not in addr:
@ -274,8 +278,8 @@ def set_static_ip(iface, addr, gateway=None, append=False):
if append and _find_addr(iface, addr):
raise CommandExecutionError(
'Address {0!r} already exists on interface '
'{1!r}'.format(addr, iface)
'Address \'{0}\' already exists on interface '
'\'{1}\''.format(addr, iface)
)
cmd = ['netsh', 'interface', 'ip']

View File

@ -809,12 +809,14 @@ def rename(name, new_name):
# Load information for the current name
current_info = info(name)
if not current_info:
raise CommandExecutionError('User {0!r} does not exist'.format(name))
raise CommandExecutionError('User \'{0}\' does not exist'.format(name))
# Look for an existing user with the new name
new_info = info(new_name)
if new_info:
raise CommandExecutionError('User {0!r} already exists'.format(new_name))
raise CommandExecutionError(
'User \'{0}\' already exists'.format(new_name)
)
# Rename the user account
# Connect to WMI
@ -825,7 +827,7 @@ def rename(name, new_name):
try:
user = c.Win32_UserAccount(Name=name)[0]
except IndexError:
raise CommandExecutionError('User {0!r} does not exist'.format(name))
raise CommandExecutionError('User \'{0}\' does not exist'.format(name))
# Rename the user
result = user.Rename(new_name)[0]
@ -844,16 +846,12 @@ def rename(name, new_name):
8: 'Operation is not allowed on specified special groups: user, admin, local, or guest',
9: 'Other API error',
10: 'Internal error'}
raise CommandExecutionError('There was an error renaming {0!r} to {1!r}. Error: {2}'.format(name, new_name, error_dict[result]))
raise CommandExecutionError(
'There was an error renaming \'{0}\' to \'{1}\'. Error: {2}'
.format(name, new_name, error_dict[result])
)
# Load information for the new name
post_info = info(new_name)
# Verify that the name has changed
if post_info['name'] != current_info['name']:
return post_info['name'] == new_name
return False
return info(new_name).get('name') == new_name
def current(sam=False):

View File

@ -24,8 +24,6 @@ from distutils.version import LooseVersion as _LooseVersion # pylint: disable=n
# 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
@ -43,6 +41,7 @@ except ImportError:
# Import salt libs
import salt.utils
import salt.utils.itertools
import salt.utils.decorators as decorators
import salt.utils.pkg.rpm
from salt.exceptions import (
@ -80,7 +79,8 @@ def _yum():
'''
contextkey = 'yum_bin'
if contextkey not in __context__:
if 'fedora' in __grains__['os'].lower() and int(__grains__['osrelease']) >= 22:
if 'fedora' in __grains__['os'].lower() \
and int(__grains__['osrelease']) >= 22:
__context__[contextkey] = 'dnf'
else:
__context__[contextkey] = 'yum'
@ -110,8 +110,8 @@ def _check_repoquery():
if not salt.utils.which('repoquery'):
__salt__['cmd.run'](
[_yum(), '-y', 'install', 'yum-utils'],
output_loglevel='trace',
python_shell=False,
output_loglevel='trace'
)
# Check again now that we've installed yum-utils
if not salt.utils.which('repoquery'):
@ -127,30 +127,33 @@ def _repoquery(repoquery_args,
_check_repoquery()
if _yum() == 'dnf':
_query_format = query_format.replace('-%{VERSION}_', '-%{EPOCH}:%{VERSION}_')
_query_format = query_format.replace(
'-%{VERSION}_',
'-%{EPOCH}:%{VERSION}_'
)
else:
_query_format = query_format
cmd = 'repoquery --plugins --queryformat {0} {1}'.format(
_cmd_quote(_query_format), repoquery_args
)
call = __salt__['cmd.run_all'](cmd, output_loglevel='trace')
cmd = ['repoquery', '--plugins', '--queryformat', _query_format]
cmd.extend(repoquery_args)
call = __salt__['cmd.run_all'](cmd,
output_loglevel='trace',
python_shell=False)
if call['retcode'] != 0:
comment = ''
# When checking for packages some yum modules return data via
# stderr that don't cause non-zero return codes. j perfect
# stderr that don't cause non-zero return codes. A perfect
# example of this is when spacewalk is installed but not yet
# registered. We should ignore those when getting pkginfo.
if 'stderr' in call and not salt.utils.is_true(ignore_stderr):
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 the epoch when it is zero to maintain backward
# compatibility
remove_zero_epoch = call['stdout'].replace('-0:', '-')
out = remove_zero_epoch
else:
@ -160,7 +163,7 @@ def _repoquery(repoquery_args,
def _get_repo_options(**kwargs):
'''
Returns a string of '--enablerepo' and '--disablerepo' options to be used
Returns a list of '--enablerepo' and '--disablerepo' options to be used
in the yum command, based on the kwargs.
'''
# Get repo options from the kwargs
@ -173,61 +176,50 @@ def _get_repo_options(**kwargs):
if repo and not fromrepo:
fromrepo = repo
repo_arg = ''
repo_arg = []
if fromrepo:
log.info('Restricting to repo \'{0}\''.format(fromrepo))
repo_arg = ('--disablerepo=\'{0}\' --enablerepo=\'{1}\''
.format('*', fromrepo))
repo_arg.extend(['--disablerepo=*', '--enablerepo=' + 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)
else:
log.info('Disabling repo \'{0}\''.format(disablerepo))
repo_arg += '--disablerepo=\'{0}\''.format(disablerepo)
targets = [disablerepo] \
if not isinstance(disablerepo, list) \
else disablerepo
log.info('Disabling repo(s): {0}'.format(', '.join(disablerepo)))
repo_arg.extend(
['--disablerepo={0}'.format(x) for x in 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)
else:
log.info('Enabling repo \'{0}\''.format(enablerepo))
repo_arg += '--enablerepo=\'{0}\''.format(enablerepo)
targets = [enablerepo] \
if not isinstance(enablerepo, list) \
else enablerepo
log.info('Enabling repo(s): {0}'.format(', '.join(enablerepo)))
repo_arg.extend(['--enablerepo={0}'.format(x) for x in enablerepo])
return repo_arg
def _get_excludes_option(**kwargs):
'''
Returns a string of '--disableexcludes' option to be used in the yum command,
Returns a list 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
return ['--disableexcludes={0}'.format(disable_excludes)]
return []
def _get_branch_option(**kwargs):
'''
Returns a string of '--branch' option to be used in the yum command,
Returns a list of '--branch' option to be used in the yum command,
based on the kwargs. This feature requires 'branch' plugin for YUM.
'''
# Get branch option from the kwargs
branch = kwargs.get('branch', '')
branch_arg = ''
if branch:
log.info('Adding branch \'{0}\''.format(branch))
branch_arg = '--branch=\'{0}\''.format(branch)
return branch_arg
return ['--branch={0}'.format(branch)]
return []
def _get_yum_config():
@ -425,11 +417,10 @@ def latest_version(*names, **kwargs):
# Get updates for specified package(s)
# Sort by version number (highest to lowest) for loop below
repoquery_args = repo_arg + exclude_arg + ['--pkgnarrow=available']
repoquery_args.extend(names)
updates = sorted(
_repoquery_pkginfo(
'{0} {1} --pkgnarrow=available {2}'
.format(repo_arg, exclude_arg, ' '.join(names))
),
_repoquery_pkginfo(repoquery_args),
key=lambda pkginfo: _LooseVersion(pkginfo.version),
reverse=True
)
@ -628,9 +619,8 @@ def list_repo_pkgs(*args, **kwargs):
ret = {}
for repo in repos:
repoquery_cmd = '--all --repoid="{0}" --show-duplicates'.format(repo)
for arg in args:
repoquery_cmd += ' "{0}"'.format(arg)
repoquery_cmd = ['--all', '--repoid={0}'.format(repo),
'--show-duplicates'] + list(args)
all_pkgs = _repoquery_pkginfo(repoquery_cmd)
for pkg in all_pkgs:
repo_dict = ret.setdefault(pkg.repoid, {})
@ -669,9 +659,10 @@ 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)
)
repoquery_args = repo_arg + exclude_arg
repoquery_args.extend(['--all', '--pkgnarrow=updates'])
updates = _repoquery_pkginfo(repoquery_args)
return dict([(x.name, x.version) for x in updates])
@ -728,11 +719,11 @@ def check_db(*names, **kwargs):
salt '*' pkg.check_db <package1> <package2> <package3> fromrepo=epel-testing
salt '*' pkg.check_db <package1> <package2> <package3> disableexcludes=main
'''
normalize = kwargs.pop('normalize') if kwargs.get('normalize') else False
normalize = kwargs.pop('normalize', True)
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 + exclude_arg + ['-all', '--quiet', '--whatprovides']
if 'pkg._avail' in __context__:
avail = __context__['pkg._avail']
@ -740,7 +731,7 @@ def check_db(*names, **kwargs):
# get list of available packages
avail = []
lines = _repoquery(
'{0} --pkgnarrow=all --all'.format(repo_arg),
repo_arg + ['--pkgnarrow=all', '--all'],
query_format='%{NAME}_|-%{ARCH}'
)
for line in lines:
@ -755,7 +746,7 @@ def check_db(*names, **kwargs):
__context__['pkg._avail'] = avail
ret = {}
repoquery_cmd = repoquery_base + ' {0}'.format(" ".join(names))
repoquery_cmd = repoquery_base + list(names)
provides = sorted(
set(x.name for x in _repoquery_pkginfo(repoquery_cmd))
)
@ -816,22 +807,18 @@ def refresh_db(**kwargs):
exclude_arg = _get_excludes_option(**kwargs)
branch_arg = _get_branch_option(**kwargs)
clean_cmd = 'yum -q clean expire-cache {repo} {exclude} {branch}'.format(
repo=repo_arg,
exclude=exclude_arg,
branch=branch_arg
)
update_cmd = 'yum -q check-update {repo} {exclude} {branch}'.format(
repo=repo_arg,
exclude=exclude_arg,
branch=branch_arg
)
clean_cmd = ['yum', '-q', 'clean', 'expire-cache']
update_cmd = ['yum', '-q', 'check-update']
for args in (repo_arg, exclude_arg, branch_arg):
if args:
clean_cmd.extend(args)
update_cmd.extend(args)
__salt__['cmd.run'](clean_cmd)
return retcodes.get(
__salt__['cmd.retcode'](update_cmd, ignore_retcode=True),
False
)
__salt__['cmd.run'](clean_cmd, python_shell=False)
result = __salt__['cmd.retcode'](update_cmd,
ignore_retcode=True,
python_shell=False)
return retcodes.get(result, False)
def clean_metadata(**kwargs):
@ -1056,7 +1043,7 @@ def install(name=None,
arch = '.' + archpart
pkgname = namepart
pkgstr = '"{0}-{1}{2}"'.format(pkgname, version_num, arch)
pkgstr = '{0}-{1}{2}'.format(pkgname, version_num, arch)
else:
pkgstr = pkgpath
@ -1075,44 +1062,40 @@ def install(name=None,
else:
downgrade.append(pkgstr)
if targets:
if _yum() == 'dnf':
dnf_args = '--best --allowerasing'
else:
dnf_args = ''
yum_command = _yum()
cmd = '{yum_command} -y {dnf} {repo} {exclude} {branch} {gpgcheck} install {pkg}'.format(
yum_command=_yum(),
dnf=dnf_args,
repo=repo_arg,
exclude=exclude_arg,
branch=branch_arg,
gpgcheck='--nogpgcheck' if skip_verify else '',
pkg=' '.join(targets),
)
__salt__['cmd.run'](cmd, output_loglevel='trace')
def _add_common_args(cmd):
'''
DRY function to add args common to all yum/dnf commands
'''
for args in (repo_arg, exclude_arg, branch_arg):
if args:
cmd.extend(args)
if skip_verify:
cmd.append('--nogpgcheck')
if targets:
cmd = [yum_command, '-y']
if yum_command == 'dnf':
cmd.extend(['--best', '--allowerasing'])
_add_common_args(cmd)
cmd.append('install')
cmd.extend(targets)
__salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False)
if downgrade:
cmd = '{yum_command} -y {repo} {exclude} {branch} {gpgcheck} downgrade {pkg}'.format(
yum_command=_yum(),
repo=repo_arg,
exclude=exclude_arg,
branch=branch_arg,
gpgcheck='--nogpgcheck' if skip_verify else '',
pkg=' '.join(downgrade),
)
__salt__['cmd.run'](cmd, output_loglevel='trace')
cmd = [yum_command, '-y']
_add_common_args(cmd)
cmd.append('downgrade')
cmd.extend(downgrade)
__salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False)
if to_reinstall:
cmd = '{yum_command} -y {repo} {exclude} {branch} {gpgcheck} reinstall {pkg}'.format(
yum_command=_yum(),
repo=repo_arg,
exclude=exclude_arg,
branch=branch_arg,
gpgcheck='--nogpgcheck' if skip_verify else '',
pkg=' '.join(six.itervalues(to_reinstall)),
)
__salt__['cmd.run'](cmd, output_loglevel='trace')
cmd = [yum_command, '-y']
_add_common_args(cmd)
cmd.append('reinstall')
cmd.extend(six.itervalues(to_reinstall))
__salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False)
__context__.pop('pkg.list_pkgs', None)
new = list_pkgs()
@ -1234,16 +1217,16 @@ def upgrade(refresh=True, skip_verify=False, name=None, pkgs=None, normalize=Tru
pkgname, version_num = pkg_item_list
targets.append(pkgname)
cmd = '{yum_command} -q -y {repo} {exclude} {branch} {gpgcheck} upgrade {pkgs}'.format(
yum_command=_yum(),
repo=repo_arg,
exclude=exclude_arg,
branch=branch_arg,
gpgcheck='--nogpgcheck' if skip_verify else '',
pkgs=' '.join(targets)
)
cmd = [_yum(), '-q', '-y']
for args in (repo_arg, exclude_arg, branch_arg):
if args:
cmd.extend(args)
if skip_verify:
cmd.append('--nogpgcheck')
cmd.append('upgrade')
cmd.extend(targets)
__salt__['cmd.run'](cmd, output_loglevel='trace')
__salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False)
__context__.pop('pkg.list_pkgs', None)
new = list_pkgs()
ret = salt.utils.compare_dicts(old, new)
@ -1288,11 +1271,11 @@ def remove(name=None, pkgs=None, **kwargs): # pylint: disable=W0613
targets = [x for x in pkg_params if x in old]
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())
__salt__['cmd.run'](cmd, output_loglevel='trace')
__salt__['cmd.run'](
[_yum(), '-q', '-y', 'remove'] + targets,
output_loglevel='trace',
python_shell=False
)
__context__.pop('pkg.list_pkgs', None)
new = list_pkgs()
ret = salt.utils.compare_dicts(old, new)
@ -1332,7 +1315,7 @@ def purge(name=None, pkgs=None, **kwargs): # pylint: disable=W0613
return remove(name=name, pkgs=pkgs)
def hold(name=None, pkgs=None, sources=None, **kwargs): # pylint: disable=W0613
def hold(name=None, pkgs=None, sources=None, normalize=True, **kwargs): # pylint: disable=W0613
'''
.. versionadded:: 2014.7.0
@ -1356,7 +1339,6 @@ def hold(name=None, pkgs=None, sources=None, **kwargs): # pylint: disable=W0613
salt '*' pkg.hold <package name>
salt '*' pkg.hold pkgs='["foo", "bar"]'
'''
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():
@ -1375,7 +1357,7 @@ def hold(name=None, pkgs=None, sources=None, **kwargs): # pylint: disable=W0613
targets = []
if pkgs:
for pkg in salt.utils.repack_dictlist(pkgs):
ret = check_db(pkg)
ret = check_db(pkg, normalize=normalize)
if not ret[pkg]['found']:
raise SaltInvocationError(
'Package {0} not available in repository.'.format(name)
@ -1385,7 +1367,7 @@ def hold(name=None, pkgs=None, sources=None, **kwargs): # pylint: disable=W0613
for source in sources:
targets.append(next(six.iterkeys(source)))
else:
ret = check_db(name)
ret = check_db(name, normalize=normalize)
if not ret[name]['found']:
raise SaltInvocationError(
'Package {0} not available in repository.'.format(name)
@ -1409,10 +1391,10 @@ 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())
out = __salt__['cmd.run_all'](cmd)
out = __salt__['cmd.run_all'](
[_yum(), '-q', 'versionlock', target],
python_shell=False
)
if out['retcode'] == 0:
ret[target].update(result=True)
@ -1499,12 +1481,10 @@ def unhold(name=None, pkgs=None, sources=None, **kwargs): # pylint: disable=W06
ret[target]['comment'] = ('Package {0} is set to be unheld.'
.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()
out = __salt__['cmd.run_all'](
[_yum(), '-q', 'versionlock', 'delete'] + search_locks,
python_shell=False
)
out = __salt__['cmd.run_all'](cmd)
if out['retcode'] == 0:
ret[target].update(result=True)
@ -1533,8 +1513,10 @@ def get_locked_packages(pattern=None, full=True):
salt '*' pkg.get_locked_packages
'''
cmd = '{yum_command} -q versionlock list'.format(yum_command=_yum())
ret = __salt__['cmd.run'](cmd).split('\n')
out = __salt__['cmd.run'](
[_yum(), '-q', 'versionlock', 'list'],
python_shell=False
)
if pattern:
if full:
@ -1549,7 +1531,7 @@ def get_locked_packages(pattern=None, full=True):
pat = re.compile(_pat)
current_locks = []
for item in ret:
for item in salt.utils.itertools.split(out, '\n'):
match = pat.search(item)
if match:
if not full:
@ -1596,41 +1578,47 @@ 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'],
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 salt.utils.itertools.split(out, '\n'):
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())
else:
line = out[idx].strip()
try:
name, lang = re.match(r'(.+) \[(.+)\]', line).groups()
except AttributeError:
pass
ret[key].append(line)
else:
match = re.match(r'(.+) \[(.+)\]', line)
if match:
name, lang = match.groups()
ret[key][line] = {'name': name, 'language': lang}
return ret
@ -1655,20 +1643,26 @@ def group_info(name):
'default packages': [],
'description': ''
}
cmd_template = 'repoquery --plugins --group --grouppkgs={0} --list {1}'
cmd_prefix = ['repoquery', '--plugins', '--group', '--list']
cmd = cmd_template.format('all', _cmd_quote(name))
out = __salt__['cmd.run_stdout'](cmd, output_loglevel='trace')
cmd = cmd_prefix + ['--grouppkgs=all', name]
out = __salt__['cmd.run_stdout'](
cmd,
output_loglevel='trace',
python_shell=False
)
all_pkgs = set(out.splitlines())
if not all_pkgs:
raise CommandExecutionError('Group \'{0}\' not found'.format(name))
for pkgtype in ('mandatory', 'optional', 'default'):
cmd = cmd_template.format(pkgtype, _cmd_quote(name))
cmd = cmd_prefix + ['--grouppkgs={0}'.format(pkgtype), name]
packages = set(
__salt__['cmd.run_stdout'](
cmd, output_loglevel='trace'
cmd,
output_loglevel='trace',
python_shell=False
).splitlines()
)
ret['{0} packages'.format(pkgtype)].extend(sorted(packages))
@ -1679,9 +1673,10 @@ def group_info(name):
# 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'
['repoquery', '--plugins', '--group', '--info', name],
output_loglevel='trace',
python_shell=False
)
if out:
ret['description'] = '\n'.join(out.splitlines()[1:]).strip()
@ -2186,14 +2181,12 @@ def owner(*paths):
if not paths:
return ''
ret = {}
cmd_prefix = ['rpm', '-qf', '--queryformat', '%{name}']
for path in paths:
cmd = 'rpm -qf --queryformat {0} \'{1}\''.format(
_cmd_quote('%{{NAME}}'),
path
)
ret[path] = __salt__['cmd.run_stdout'](
cmd.format(path),
output_loglevel='trace'
cmd_prefix + [path],
output_loglevel='trace',
python_shell=False
)
if 'not owned' in ret[path].lower():
ret[path] = ''
@ -2292,11 +2285,12 @@ def download(*packages):
except OSError as exc:
log.error('Unable to remove {0}: {1}'.format(purge_target, exc))
cmd = ['yumdownloader', '-q', '--destdir={0}'.format(CACHE_DIR)]
cmd.extend(packages)
__salt__['cmd.run'](
'yumdownloader -q {0} --destdir={1}'.format(
' '.join(packages), CACHE_DIR
),
output_loglevel='trace'
cmd,
output_loglevel='trace',
python_shell=False
)
ret = {}
for dld_result in os.listdir(CACHE_DIR):

View File

@ -15,6 +15,7 @@ import os
# Import 3rd-party libs
# pylint: disable=import-error,redefined-builtin,no-name-in-module
import salt.ext.six as six
from salt.exceptions import SaltInvocationError
from salt.ext.six.moves import configparser
from salt.ext.six.moves.urllib.parse import urlparse as _urlparse
# pylint: enable=import-error,redefined-builtin,no-name-in-module
@ -63,7 +64,9 @@ def list_upgrades(refresh=True):
refresh_db()
ret = {}
call = __salt__['cmd.run_all'](
'zypper list-updates', output_loglevel='trace'
['zypper', 'list-updates'],
output_loglevel='trace',
python_shell=False
)
if call['retcode'] != 0:
comment = ''
@ -149,18 +152,28 @@ def info_available(*names, **kwargs):
# Run in batches
while batch:
cmd = 'zypper info -t package {0}'.format(' '.join(batch[:batch_size]))
pkg_info.extend(re.split(r"----*", __salt__['cmd.run_stdout'](cmd, output_loglevel='trace')))
cmd = ['zypper', 'info', '-t', 'package']
cmd.extend(batch[:batch_size])
pkg_info.extend(
re.split(
'----*',
__salt__['cmd.run_stdout'](
cmd,
output_loglevel='trace',
python_shell=False
)
)
)
batch = batch[batch_size:]
for pkg_data in pkg_info:
nfo = {}
for line in [data for data in pkg_data.split("\n") if ":" in data]:
kw = [data.strip() for data in line.split(":", 1)]
for line in [data for data in pkg_data.split('\n') if ':' in data]:
kw = [data.strip() for data in line.split(':', 1)]
if len(kw) == 2 and kw[1]:
nfo[kw[0].lower()] = kw[1]
if nfo.get("name"):
name = nfo.pop("name")
if nfo.get('name'):
name = nfo.pop('name')
ret[name] = nfo
return ret
@ -372,8 +385,15 @@ def del_repo(repo):
repos_cfg = _get_configured_repos()
for alias in repos_cfg.sections():
if alias == repo:
cmd = ('zypper -x --non-interactive rr --loose-auth --loose-query {0}'.format(alias))
doc = dom.parseString(__salt__['cmd.run'](cmd, output_loglevel='trace'))
cmd = ['zypper', '-x', '--non-interactive', 'rr', '--loose-auth',
'--loose-query', alias]
doc = dom.parseString(
__salt__['cmd.run'](
cmd,
output_loglevel='trace',
python_shell=False
)
)
msg = doc.getElementsByTagName('message')
if doc.getElementsByTagName('progress') and msg:
return {
@ -431,11 +451,13 @@ def mod_repo(repo, **kwargs):
url = kwargs.get('url', kwargs.get('mirrorlist', kwargs.get('baseurl')))
if not url:
raise CommandExecutionError(
'Repository \'{0}\' not found and no URL passed to create one.'.format(repo))
'Repository \'{0}\' not found and no URL passed'.format(repo)
)
if not _urlparse(url).scheme:
raise CommandExecutionError(
'Repository \'{0}\' not found and passed URL looks wrong.'.format(repo))
'Repository \'{0}\' not found and URL is invalid'.format(repo)
)
# Is there already such repo under different alias?
for alias in repos_cfg.sections():
@ -454,17 +476,26 @@ def mod_repo(repo, **kwargs):
if new_url == base_url:
raise CommandExecutionError(
'Repository \'{0}\' already exists as \'{1}\'.'.format(repo, alias))
'Repository \'{0}\' already exists as \'{1}\'.'.format(
repo,
alias
)
)
# Add new repo
doc = None
try:
# Try to parse the output and find the error,
# but this not always working (depends on Zypper version)
doc = dom.parseString(__salt__['cmd.run'](('zypper -x ar {0} \'{1}\''.format(url, repo)),
output_loglevel='trace'))
doc = dom.parseString(
__salt__['cmd.run'](
['zypper', '-x', 'ar', url, repo],
output_loglevel='trace',
python_shell=False
)
)
except Exception:
# No XML out available, but it is still unknown the state of the result.
# No XML out available, but the the result is still unknown
pass
if doc:
@ -472,14 +503,17 @@ def mod_repo(repo, **kwargs):
if msg_nodes:
msg_node = msg_nodes[0]
if msg_node.getAttribute('type') == 'error':
raise CommandExecutionError(msg_node.childNodes[0].nodeValue)
raise CommandExecutionError(
msg_node.childNodes[0].nodeValue
)
# Verify the repository has been added
repos_cfg = _get_configured_repos()
if repo not in repos_cfg.sections():
raise CommandExecutionError(
'Failed add new repository \'{0}\' for unknown reason. '
'Please look into Zypper logs.'.format(repo))
'Please look into Zypper logs.'.format(repo)
)
added = True
# Modify added or existing repo according to the options
@ -492,7 +526,9 @@ def mod_repo(repo, **kwargs):
cmd_opt.append(kwargs['refresh'] and '--refresh' or '--no-refresh')
if 'cache' in kwargs:
cmd_opt.append(kwargs['cache'] and '--keep-packages' or '--no-keep-packages')
cmd_opt.append(
kwargs['cache'] and '--keep-packages' or '--no-keep-packages'
)
if 'gpgcheck' in kwargs:
cmd_opt.append(kwargs['gpgcheck'] and '--gpgcheck' or '--no-gpgcheck')
@ -501,13 +537,17 @@ def mod_repo(repo, **kwargs):
cmd_opt.append('--gpg-auto-import-keys')
if cmd_opt:
__salt__['cmd.run'](('zypper -x mr {0} \'{1}\''.format(' '.join(cmd_opt), repo)),
output_loglevel='trace')
cmd = ['zypper', '-x', 'mr']
cmd.extend(cmd_opt)
cmd.append(repo)
__salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False)
# If repo nor added neither modified, error should be thrown
if not added and not cmd_opt:
raise CommandExecutionError(
'Modification of the repository \'{0}\' was not specified.'.format(repo))
'Modification of the repository \'{0}\' was not specified.'
.format(repo)
)
return get_repo(repo)
@ -524,17 +564,19 @@ def refresh_db():
salt '*' pkg.refresh_db
'''
cmd = 'zypper refresh'
cmd = ['zypper', 'refresh']
ret = {}
call = __salt__['cmd.run_all'](cmd, output_loglevel='trace')
if call['retcode'] != 0:
comment = ''
if 'stderr' in call:
comment += call['stderr']
raise CommandExecutionError(
'{0}'.format(comment)
call = __salt__['cmd.run_all'](
cmd,
output_loglevel='trace',
python_shell=False
)
if call['retcode'] != 0:
msg = 'Failed to refresh zypper'
if call['stderr']:
msg += ': ' + call['stderr']
raise CommandExecutionError(msg)
else:
out = call['stdout']
@ -566,10 +608,10 @@ def install(name=None,
name
The name of the package to be installed. Note that this parameter is
ignored if either "pkgs" or "sources" is passed. Additionally, please
note that this option can only be used to install packages from a
software repository. To install a package file manually, use the
"sources" option.
ignored if either ``pkgs`` or ``sources`` is passed. Additionally,
please note that this option can only be used to install packages from
a software repository. To install a package file manually, use the
``sources`` option.
CLI Example:
@ -592,7 +634,7 @@ def install(name=None,
version
Can be either a version number, or the combination of a comparison
operator (<, >, <=, >=, =) and a version number (ex. '>1.2.3-4').
This parameter is ignored if "pkgs" or "sources" is passed.
This parameter is ignored if ``pkgs`` or ``sources`` is passed.
Multiple Package Installation Options:
@ -665,8 +707,8 @@ def install(name=None,
targets.append('{0}{1}{2}'.format(param, prefix, verstr))
log.debug(targets)
else:
msg = ('Invalid version string {0!r} for package '
'{1!r}'.format(version_num, name))
msg = ('Invalid version string \'{0}\' for package '
'\'{1}\''.format(version_num, name))
problems.append(msg)
if problems:
for problem in problems:
@ -679,7 +721,7 @@ def install(name=None,
downgrades = []
if fromrepo:
fromrepoopt = ['--force', '--force-resolution', '--from', fromrepo]
log.info('Targeting repo {0!r}'.format(fromrepo))
log.info('Targeting repo \'{0}\''.format(fromrepo))
else:
fromrepoopt = ''
cmd_install = ['zypper', '--non-interactive']
@ -687,7 +729,7 @@ def install(name=None,
cmd_install.append('--no-refresh')
if skip_verify:
cmd_install.append('--no-gpg-checks')
cmd_install += ['install', '--name', '--auto-agree-with-licenses']
cmd_install.extend(['install', '--name', '--auto-agree-with-licenses'])
if downloadonly:
cmd_install.append('--download-only')
if fromrepo:
@ -714,8 +756,8 @@ def install(name=None,
while downgrades:
cmd = cmd_install + ['--force'] + downgrades[:500]
downgrades = downgrades[500:]
__salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False)
__context__.pop('pkg.list_pkgs', None)
new = list_pkgs()
return salt.utils.compare_dicts(old, new)
@ -751,16 +793,20 @@ def upgrade(refresh=True, skip_verify=False):
if salt.utils.is_true(refresh):
refresh_db()
old = list_pkgs()
cmd = 'zypper --non-interactive'
cmd = ['zypper', '--non-interactive']
if skip_verify:
cmd += ' --no-gpg-checks'
cmd += ' update --auto-agree-with-licenses'
call = __salt__['cmd.run_all'](cmd, output_loglevel='trace')
cmd.append('--no-gpg-checks')
cmd.extend(['update', '--auto-agree-with-licenses'])
call = __salt__['cmd.run_all'](
cmd,
output_loglevel='trace',
python_shell=False
)
if call['retcode'] != 0:
ret['result'] = False
if 'stderr' in call:
if call['stderr']:
ret['comment'] += call['stderr']
if 'stdout' in call:
if call['stdout']:
ret['comment'] += call['stdout']
else:
__context__.pop('pkg.list_pkgs', None)
@ -779,17 +825,16 @@ def _uninstall(action='remove', name=None, pkgs=None):
except MinionError as exc:
raise CommandExecutionError(exc)
purge_arg = '-u' if action == 'purge' else ''
old = list_pkgs()
targets = [x for x in pkg_params if x in old]
if not targets:
return {}
while targets:
cmd = (
'zypper --non-interactive remove {0} {1}'
.format(purge_arg, ' '.join(targets[:500]))
)
__salt__['cmd.run'](cmd, output_loglevel='trace')
cmd = ['zypper', '--non-interactive', 'remove']
if action == 'purge':
cmd.append('-u')
cmd.extend(targets[:500])
__salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False)
targets = targets[500:]
__context__.pop('pkg.list_pkgs', None)
new = list_pkgs()
@ -889,7 +934,8 @@ def list_locks():
def clean_locks():
'''
Remove unused locks that do not currently (with regard to repositories used) lock any package.
Remove unused locks that do not currently (with regard to repositories
used) lock any package.
CLI Example:
@ -900,8 +946,8 @@ def clean_locks():
if not os.path.exists(LOCKS):
return False
cmd = ('zypper --non-interactive cl')
__salt__['cmd.run'](cmd, output_loglevel='trace')
cmd = ['zypper', '--non-interactive', 'cl']
__salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False)
return True
@ -922,7 +968,9 @@ def remove_lock(name=None, pkgs=None, **kwargs): # pylint: disable=unused-argum
locks = list_locks()
packages = []
try:
packages = list(__salt__['pkg_resource.parse_targets'](name, pkgs)[0].keys())
packages = list(
__salt__['pkg_resource.parse_targets'](name, pkgs)[0].keys()
)
except MinionError as exc:
raise CommandExecutionError(exc)
@ -935,8 +983,9 @@ def remove_lock(name=None, pkgs=None, **kwargs): # pylint: disable=unused-argum
missing.append(pkg)
if removed:
__salt__['cmd.run'](('zypper --non-interactive rl {0}'.format(' '.join(removed))),
output_loglevel='trace')
cmd = ['zypper', '--non-interactive', 'rl']
cmd.extend(removed)
__salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False)
return {'removed': len(removed), 'not_found': missing}
@ -957,7 +1006,9 @@ def add_lock(name=None, pkgs=None, **kwargs): # pylint: disable=unused-argument
packages = []
added = []
try:
packages = list(__salt__['pkg_resource.parse_targets'](name, pkgs)[0].keys())
packages = list(
__salt__['pkg_resource.parse_targets'](name, pkgs)[0].keys()
)
except MinionError as exc:
raise CommandExecutionError(exc)
@ -966,8 +1017,9 @@ def add_lock(name=None, pkgs=None, **kwargs): # pylint: disable=unused-argument
added.append(pkg)
if added:
__salt__['cmd.run'](('zypper --non-interactive al {0}'.format(' '.join(added))),
output_loglevel='trace')
cmd = ['zypper', '--non-interactive', 'al']
cmd.extend(added)
__salt__['cmd.run'](cmd, output_loglevel='trace', python_shell=False)
return {'added': len(added), 'packages': added}
@ -1099,8 +1151,13 @@ def _get_patterns(installed_only=None):
List all known patterns in repos.
'''
patterns = {}
doc = dom.parseString(__salt__['cmd.run'](('zypper --xmlout se -t pattern'),
output_loglevel='trace'))
doc = dom.parseString(
__salt__['cmd.run'](
['zypper', '--xmlout', 'se', '-t', 'pattern'],
output_loglevel='trace',
python_shell=False
)
)
for element in doc.getElementsByTagName('solvable'):
installed = element.getAttribute('status') == 'installed'
if (installed_only and installed) or not installed_only:
@ -1148,11 +1205,18 @@ def search(criteria):
salt '*' pkg.search <criteria>
'''
doc = dom.parseString(__salt__['cmd.run'](('zypper --xmlout se {0}'.format(criteria)),
output_loglevel='trace'))
doc = dom.parseString(
__salt__['cmd.run'](
['zypper', '--xmlout', 'se', criteria],
output_loglevel='trace',
python_shell=False
)
)
solvables = doc.getElementsByTagName('solvable')
if not solvables:
raise CommandExecutionError('No packages found by criteria "{0}".'.format(criteria))
raise CommandExecutionError(
'No packages found matching \'{0}\''.format(criteria)
)
out = {}
for solvable in [s for s in solvables
@ -1206,7 +1270,9 @@ def list_products():
'''
products_dir = '/etc/products.d'
if not os.path.exists(products_dir):
raise CommandExecutionError('Directory {0} does not exists.'.format(products_dir))
raise CommandExecutionError(
'Directory {0} does not exist'.format(products_dir)
)
p_data = {}
for fname in os.listdir(products_dir):
@ -1229,7 +1295,7 @@ def list_products():
def download(*packages):
"""
'''
Download packages to the local disk.
CLI example:
@ -1238,27 +1304,41 @@ def download(*packages):
salt '*' pkg.download httpd
salt '*' pkg.download httpd postfix
"""
'''
if not packages:
raise CommandExecutionError("No packages has been specified.")
raise SaltInvocationError('No packages specified')
doc = dom.parseString(__salt__['cmd.run'](
('zypper -x --non-interactive download {0}'.format(' '.join(packages))),
output_loglevel='trace'))
cmd = ['zypper', '-x', '--non-interactive', 'download']
cmd.extend(packages)
doc = dom.parseString(
__salt__['cmd.run'](
cmd,
output_loglevel='trace',
python_shell=False
)
)
pkg_ret = {}
for dld_result in doc.getElementsByTagName("download-result"):
repo = dld_result.getElementsByTagName("repository")[0]
for dld_result in doc.getElementsByTagName('download-result'):
repo = dld_result.getElementsByTagName('repository')[0]
path = dld_result.getElementsByTagName(
'localfile')[0].getAttribute('path')
pkg_info = {
'repository-name': repo.getAttribute("name"),
'repository-alias': repo.getAttribute("alias"),
'path': dld_result.getElementsByTagName("localfile")[0].getAttribute("path"),
'repository-name': repo.getAttribute('name'),
'repository-alias': repo.getAttribute('alias'),
'path': path
}
pkg_ret[_get_first_aggregate_text(dld_result.getElementsByTagName("name"))] = pkg_info
key = _get_first_aggregate_text(
dld_result.getElementsByTagName('name')
)
pkg_ret[key] = pkg_info
if pkg_ret:
return pkg_ret
raise CommandExecutionError("Unable to download packages: {0}.".format(', '.join(packages)))
raise CommandExecutionError(
'Unable to download packages: {0}'.format(', '.join(packages))
)
def diff(*paths):
@ -1292,6 +1372,9 @@ def diff(*paths):
local_pkgs = __salt__['pkg.download'](*pkg_to_paths.keys())
for pkg, files in pkg_to_paths.items():
for path in files:
ret[path] = __salt__['lowpkg.diff'](local_pkgs[pkg]['path'], path) or 'Unchanged'
ret[path] = __salt__['lowpkg.diff'](
local_pkgs[pkg]['path'],
path
) or 'Unchanged'
return ret

View File

@ -193,7 +193,8 @@ class AtTestCase(TestCase):
self.assertEqual(at.atc(101), '\'at.atc\' is not available.')
with patch.object(at, '_cmd', return_value=''):
self.assertDictEqual(at.atc(101), {'error': 'invalid job id 101'})
self.assertDictEqual(at.atc(101),
{'error': 'invalid job id \'101\''})
with patch.object(at, '_cmd',
return_value='101\tThu Dec 11 19:48:47 2014 A B'):

View File

@ -26,7 +26,10 @@ class DarwingPkgutilTestCase(TestCase):
output = darwin_pkgutil.list_()
# Then
mock_cmd.assert_called_with("/usr/sbin/pkgutil --pkgs")
mock_cmd.assert_called_with(
['/usr/sbin/pkgutil', '--pkgs'],
python_shell=False
)
def test_list_installed_output(self):
# Given

View File

@ -18,14 +18,18 @@ gem.__salt__ = {}
@skipIf(NO_MOCK, NO_MOCK_REASON)
class TestGemModule(TestCase):
def test__gem(self):
def test_gem(self):
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(gem.__salt__,
{'rvm.is_installed': MagicMock(return_value=False),
'rbenv.is_installed': MagicMock(return_value=False),
'cmd.run_all': mock}):
gem._gem('install rails')
mock.assert_called_once_with('gem install rails', runas=None, python_shell=True)
gem._gem(['install', 'rails'])
mock.assert_called_once_with(
['gem', 'install', 'rails'],
runas=None,
python_shell=False
)
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
rvm_mock = MagicMock()
@ -33,18 +37,28 @@ class TestGemModule(TestCase):
{'rvm.is_installed': rvm_mock,
'rbenv.is_installed': rvm_mock,
'cmd.run_all': mock}):
gem._gem('install rails', gem_bin="/usr/local/bin/gem")
self.assertEqual(False, rvm_mock.called, "Should never call rvm.is_installed if gem_bin provided")
mock.assert_called_once_with('/usr/local/bin/gem install rails', runas=None, python_shell=True)
gem._gem(['install', 'rails'], gem_bin='/usr/local/bin/gem')
self.assertEqual(
False,
rvm_mock.called,
'Should never call rvm.is_installed if gem_bin provided'
)
mock.assert_called_once_with(
['/usr/local/bin/gem', 'install', 'rails'],
runas=None,
python_shell=False
)
mock = MagicMock(return_value=None)
with patch.dict(gem.__salt__,
{'rvm.is_installed': MagicMock(return_value=True),
'rbenv.is_installed': MagicMock(return_value=False),
'rvm.do': mock}):
gem._gem('install rails', ruby='1.9.3')
gem._gem(['install', 'rails'], ruby='1.9.3')
mock.assert_called_once_with(
'1.9.3', 'gem install rails', runas=None
'1.9.3',
['gem', 'install', 'rails'],
runas=None
)
mock = MagicMock(return_value=None)
@ -52,9 +66,10 @@ class TestGemModule(TestCase):
{'rvm.is_installed': MagicMock(return_value=False),
'rbenv.is_installed': MagicMock(return_value=True),
'rbenv.do': mock}):
gem._gem('install rails')
gem._gem(['install', 'rails'])
mock.assert_called_once_with(
'gem install rails', runas=None
['gem', 'install', 'rails'],
runas=None
)
def test_install_pre(self):
@ -65,7 +80,9 @@ class TestGemModule(TestCase):
'cmd.run_all': mock}):
gem.install('rails', pre_releases=True)
mock.assert_called_once_with(
'gem install rails --no-rdoc --no-ri --pre', runas=None, python_shell=True
['gem', 'install', 'rails', '--no-rdoc', '--no-ri', '--pre'],
runas=None,
python_shell=False
)
def test_list(self):

View File

@ -64,7 +64,8 @@ class MacUserTestCase(TestCase):
with patch.dict(mac_user.__grains__,
{'kernel': 'Darwin', 'osrelease': '10.9.1',
'osrelease_info': (10, 9, 1)}):
self.assertEqual(mac_user._dscl('username'), {'pid': 4948,
self.assertEqual(mac_user._dscl(['username', 'UniqueID', 501]),
{'pid': 4948,
'retcode': 0,
'stderr': '',
'stdout': ''})

View File

@ -70,14 +70,16 @@ class PostgresTestCase(TestCase):
owner='otheruser',
runas='foo')
postgres._run_psql.assert_has_calls([
call('/usr/bin/pgsql --no-align --no-readline --no-password --username testuser '
'--host testhost --port testport --dbname maint_db '
'-c \'ALTER DATABASE "dbname" OWNER TO "otheruser"\'',
call(['/usr/bin/pgsql', '--no-align', '--no-readline',
'--no-password', '--username', 'testuser', '--host',
'testhost', '--port', 'testport', '--dbname', 'maint_db',
'-c', 'ALTER DATABASE "dbname" OWNER TO "otheruser"'],
host='testhost', user='testuser',
password='foo', runas='foo', port='testport'),
call('/usr/bin/pgsql --no-align --no-readline --no-password --username testuser '
'--host testhost --port testport --dbname maint_db '
'-c \'ALTER DATABASE "dbname" SET TABLESPACE "testspace"\'',
call(['/usr/bin/pgsql', '--no-align', '--no-readline',
'--no-password', '--username', 'testuser', '--host',
'testhost', '--port', 'testport', '--dbname', 'maint_db',
'-c', 'ALTER DATABASE "dbname" SET TABLESPACE "testspace"'],
host='testhost', user='testuser',
password='foo', runas='foo', port='testport')
])
@ -118,12 +120,12 @@ class PostgresTestCase(TestCase):
runas='foo'
)
qstr = (
'/usr/bin/pgsql --no-align --no-readline --no-password '
'--username testuser --host testhost --port testport --dbname maint_db '
'-c \'CREATE DATABASE "dbname" WITH TABLESPACE = testspace OWNER = "otheruser"\'')
postgres._run_psql.assert_called_once_with(
qstr,
['/usr/bin/pgsql', '--no-align', '--no-readline',
'--no-password', '--username', 'testuser', '--host',
'testhost', '--port', 'testport', '--dbname', 'maint_db',
'-c', 'CREATE DATABASE "dbname" WITH TABLESPACE = testspace '
'OWNER = "otheruser"'],
host='testhost', user='testuser',
password='foo', runas='foo', port='testport')
@ -187,9 +189,10 @@ class PostgresTestCase(TestCase):
runas='foo'
)
postgres._run_psql.assert_called_once_with(
"/usr/bin/pgsql --no-align --no-readline --no-password --username testuser "
"--host testhost --port testport --dbname maint_db "
"-c 'DROP DATABASE test_db'",
['/usr/bin/pgsql', '--no-align', '--no-readline',
'--no-password', '--username', 'testuser', '--host',
'testhost', '--port', 'testport', '--dbname', 'maint_db',
'-c', 'DROP DATABASE test_db'],
host='testhost', user='testuser',
password='foo', runas='foo', port='testport')
@ -213,11 +216,13 @@ class PostgresTestCase(TestCase):
groups='testgroup',
runas='foo'
)
self.assertTrue(re.match(
'/usr/bin/pgsql --no-align --no-readline --no-password --username testuser '
'--host testhost --port testport '
'--dbname maint_db -c (\'|\")CREATE ROLE',
postgres._run_psql.call_args[0][0]))
# postgres._run_psql.call_args[0][0] will contain the list of CLI args.
# The first 13 elements of this list are initial args used in all (or
# virtually all) commands run through _run_psql(), so the actual SQL
# query will be in the 14th argument.
self.assertTrue(
postgres._run_psql.call_args[0][0][13].startswith('CREATE ROLE')
)
@patch('salt.modules.postgres._run_psql',
Mock(return_value={'retcode': 0}))
@ -233,9 +238,10 @@ class PostgresTestCase(TestCase):
runas='foo'
)
postgres._run_psql.assert_called_once_with(
"/usr/bin/pgsql --no-align --no-readline --no-password --username testuser "
"--host testhost --port testport "
"--dbname maint_db -c 'DROP ROLE testgroup'",
['/usr/bin/pgsql', '--no-align', '--no-readline',
'--no-password', '--username', 'testuser', '--host',
'testhost', '--port', 'testport', '--dbname', 'maint_db',
'-c', 'DROP ROLE testgroup'],
host='testhost', user='testuser',
password='foo', runas='foo', port='testport')
@ -259,10 +265,16 @@ class PostgresTestCase(TestCase):
groups='testgroup',
runas='foo'
)
self.assertTrue(re.match(
'.*'
'(\'|\")ALTER.* (\\\\)?"testgroup(\\\\)?" .* UNENCRYPTED PASSWORD',
postgres._run_psql.call_args[0][0]))
# postgres._run_psql.call_args[0][0] will contain the list of CLI args.
# The first 13 elements of this list are initial args used in all (or
# virtually all) commands run through _run_psql(), so the actual SQL
# query will be in the 14th argument.
self.assertTrue(
re.match(
'ALTER.* "testgroup" .* UNENCRYPTED PASSWORD',
postgres._run_psql.call_args[0][0][13]
)
)
@patch('salt.modules.postgres._run_psql',
Mock(return_value={'retcode': 0}))
@ -287,14 +299,12 @@ class PostgresTestCase(TestCase):
groups='test_groups',
runas='foo'
)
call = postgres._run_psql.call_args[0][0]
self.assertTrue(re.match(
'/usr/bin/pgsql --no-align --no-readline --no-password '
'--username testuser'
' --host testhost --port testport'
' --dbname maint_test -c (\'|\")CREATE ROLE (\\\\)?"testuser(\\\\)?"',
call))
# postgres._run_psql.call_args[0][0] will contain the list of CLI args.
# The first 13 elements of this list are initial args used in all (or
# virtually all) commands run through _run_psql(), so the actual SQL
# query will be in the 14th argument.
call = postgres._run_psql.call_args[0][0][13]
self.assertTrue(re.match('CREATE ROLE "testuser"', call))
for i in (
'INHERIT NOCREATEDB NOCREATEROLE '
'NOSUPERUSER NOREPLICATION LOGIN UNENCRYPTED PASSWORD'
@ -379,21 +389,21 @@ class PostgresTestCase(TestCase):
@patch('salt.modules.postgres.user_exists', Mock(return_value=True))
def test_user_remove(self):
postgres.user_remove(
'test_user',
user='test_user',
host='test_host',
port='test_port',
'testuser',
user='testuser',
host='testhost',
port='testport',
maintenance_db='maint_db',
password='test_password',
password='testpassword',
runas='foo'
)
postgres._run_psql.assert_called_once_with(
"/usr/bin/pgsql --no-align --no-readline --no-password "
"--username test_user "
"--host test_host --port test_port "
"--dbname maint_db -c 'DROP ROLE test_user'",
host='test_host', port='test_port', user='test_user',
password='test_password', runas='foo')
['/usr/bin/pgsql', '--no-align', '--no-readline',
'--no-password', '--username', 'testuser', '--host',
'testhost', '--port', 'testport', '--dbname', 'maint_db',
'-c', 'DROP ROLE testuser'],
host='testhost', port='testport', user='testuser',
password='testpassword', runas='foo')
@patch('salt.modules.postgres._run_psql',
Mock(return_value={'retcode': 0}))
@ -418,17 +428,18 @@ class PostgresTestCase(TestCase):
groups='test_groups',
runas='foo'
)
call_output = postgres._run_psql.call_args[0][0]
# postgres._run_psql.call_args[0][0] will contain the list of CLI args.
# The first 13 elements of this list are initial args used in all (or
# virtually all) commands run through _run_psql(), so the actual SQL
# query will be in the 14th argument.
self.assertTrue(
re.match(
'/usr/bin/pgsql --no-align --no-readline --no-password '
'--username test_user '
'--host test_host --port test_port --dbname test_maint '
'-c [\'"]{0,1}ALTER ROLE (\\\\)?"test_username(\\\\)?" WITH INHERIT NOCREATEDB '
'ALTER ROLE "test_username" WITH INHERIT NOCREATEDB '
'NOCREATEROLE NOREPLICATION LOGIN '
'UNENCRYPTED PASSWORD [\'"]{0,5}test_role_pass[\'"]{0,5};'
' GRANT (\\\\)?"test_groups(\\\\)?" TO (\\\\)?"test_username(\\\\)?"[\'"]{0,1}',
call_output)
' GRANT "test_groups" TO "test_username"',
postgres._run_psql.call_args[0][0][13]
)
)
@patch('salt.modules.postgres._run_psql',
@ -453,15 +464,17 @@ class PostgresTestCase(TestCase):
groups='test_groups',
runas='foo'
)
call_output = postgres._run_psql.call_args[0][0]
# postgres._run_psql.call_args[0][0] will contain the list of CLI args.
# The first 13 elements of this list are initial args used in all (or
# virtually all) commands run through _run_psql(), so the actual SQL
# query will be in the 14th argument.
self.assertTrue(
re.match(
'/usr/bin/pgsql --no-align --no-readline --no-password --username test_user '
'--host test_host --port test_port --dbname test_maint '
'-c \'ALTER ROLE "test_username" WITH INHERIT NOCREATEDB '
'ALTER ROLE "test_username" WITH INHERIT NOCREATEDB '
'CREATEROLE NOREPLICATION LOGIN;'
' GRANT "test_groups" TO "test_username"\'',
call_output)
' GRANT "test_groups" TO "test_username"',
postgres._run_psql.call_args[0][0][13]
)
)
@patch('salt.modules.postgres._run_psql',
@ -487,16 +500,17 @@ class PostgresTestCase(TestCase):
groups='test_groups',
runas='foo'
)
call_output = postgres._run_psql.call_args[0][0]
# postgres._run_psql.call_args[0][0] will contain the list of CLI args.
# The first 13 elements of this list are initial args used in all (or
# virtually all) commands run through _run_psql(), so the actual SQL
# query will be in the 14th argument.
self.assertTrue(
re.match(
'/usr/bin/pgsql --no-align --no-readline --no-password '
'--username test_user '
'--host test_host --port test_port --dbname test_maint '
'-c \'ALTER ROLE "test_username" WITH INHERIT NOCREATEDB '
'ALTER ROLE "test_username" WITH INHERIT NOCREATEDB '
'CREATEROLE NOREPLICATION LOGIN NOPASSWORD;'
' GRANT "test_groups" TO "test_username"\'',
call_output)
' GRANT "test_groups" TO "test_username"',
postgres._run_psql.call_args[0][0][13]
)
)
@patch('salt.modules.postgres._run_psql',
@ -522,18 +536,19 @@ class PostgresTestCase(TestCase):
groups='test_groups',
runas='foo'
)
call_output = postgres._run_psql.call_args[0][0]
# postgres._run_psql.call_args[0][0] will contain the list of CLI args.
# The first 13 elements of this list are initial args used in all (or
# virtually all) commands run through _run_psql(), so the actual SQL
# query will be in the 14th argument.
self.assertTrue(
re.match(
'/usr/bin/pgsql --no-align --no-readline --no-password '
'--username test_user '
'--host test_host --port test_port --dbname test_maint '
'-c [\'"]{0,1}ALTER ROLE (\\\\)?"test_username(\\\\)?" WITH INHERIT NOCREATEDB '
'ALTER ROLE "test_username" WITH INHERIT NOCREATEDB '
'CREATEROLE NOREPLICATION LOGIN '
'ENCRYPTED PASSWORD '
'[\'"]{0,5}md531c27e68d3771c392b52102c01be1da1[\'"]{0,5}'
'; GRANT (\\\\)?"test_groups(\\\\)?" TO (\\\\)?"test_username(\\\\)?"[\'"]{0,1}',
call_output)
'; GRANT "test_groups" TO "test_username"',
postgres._run_psql.call_args[0][0][13]
)
)
@patch('salt.modules.postgres._run_psql',
@ -547,14 +562,16 @@ class PostgresTestCase(TestCase):
password='test_pass',
runas='foo'
)
call_output = postgres._run_psql.call_args[0][0]
self.assertTrue(re.match(
'/usr/bin/pgsql --no-align --no-readline --no-password '
'--username test_user '
'--host test_host --port test_port '
'--dbname test_maint '
'-c (\'|\")SELECT setting FROM pg_catalog.pg_settings',
call_output))
# postgres._run_psql.call_args[0][0] will contain the list of CLI args.
# The first 13 elements of this list are initial args used in all (or
# virtually all) commands run through _run_psql(), so the actual SQL
# query will be in the 14th argument.
self.assertTrue(
re.match(
'SELECT setting FROM pg_catalog.pg_settings',
postgres._run_psql.call_args[0][0][13]
)
)
@patch('salt.modules.postgres.psql_query',
Mock(return_value=[{'extname': "foo", 'extversion': "1"}]))
@ -784,21 +801,21 @@ class PostgresTestCase(TestCase):
@patch('salt.modules.postgres.schema_exists', Mock(return_value=False))
def test_schema_create(self):
postgres.schema_create(
'test_db',
'test_schema',
'maint_db',
'testschema',
user='user',
db_host='test_host',
db_port='test_port',
db_user='test_user',
db_password='test_password'
db_host='testhost',
db_port='testport',
db_user='testuser',
db_password='testpassword'
)
postgres._run_psql.assert_called_once_with(
"/usr/bin/pgsql --no-align --no-readline --no-password "
"--username test_user "
"--host test_host --port test_port "
"--dbname test_db -c 'CREATE SCHEMA test_schema'",
host='test_host', port='test_port',
password='test_password', user='test_user', runas='user')
['/usr/bin/pgsql', '--no-align', '--no-readline',
'--no-password', '--username', 'testuser', '--host',
'testhost', '--port', 'testport', '--dbname', 'maint_db',
'-c', 'CREATE SCHEMA testschema'],
host='testhost', port='testport',
password='testpassword', user='testuser', runas='user')
@patch('salt.modules.postgres.schema_exists', Mock(return_value=True))
def test_schema_create2(self):
@ -817,21 +834,21 @@ class PostgresTestCase(TestCase):
@patch('salt.modules.postgres.schema_exists', Mock(return_value=True))
def test_schema_remove(self):
postgres.schema_remove(
'test_db',
'test_schema',
'maint_db',
'testschema',
user='user',
db_host='test_host',
db_port='test_port',
db_user='test_user',
db_password='test_password'
db_host='testhost',
db_port='testport',
db_user='testuser',
db_password='testpassword'
)
postgres._run_psql.assert_called_once_with(
"/usr/bin/pgsql --no-align --no-readline --no-password "
"--username test_user "
"--host test_host --port test_port "
"--dbname test_db -c 'DROP SCHEMA test_schema'",
host='test_host', port='test_port',
password='test_password', user='test_user', runas='user')
['/usr/bin/pgsql', '--no-align', '--no-readline',
'--no-password', '--username', 'testuser', '--host',
'testhost', '--port', 'testport', '--dbname', 'maint_db',
'-c', 'DROP SCHEMA testschema'],
host='testhost', port='testport',
password='testpassword', user='testuser', runas='user')
@patch('salt.modules.postgres.schema_exists', Mock(return_value=False))
def test_schema_remove2(self):

View File

@ -42,17 +42,17 @@ class PwUserTestCase(TestCase):
Test for adding a user
'''
with patch.dict(pw_user.__grains__, {'os_family': 'RedHat'}):
mock = MagicMock(return_value={'retcode': 0, 'stdout': 'salt'})
with patch.dict(pw_user.__salt__, {'cmd.run_all': mock}):
mock = MagicMock(return_value=0)
with patch.dict(pw_user.__salt__, {'cmd.retcode': mock}):
self.assertTrue(pw_user.add('a'))
def test_delete(self):
'''
Test for deleting a user
'''
mock = MagicMock(return_value={'retcode': 0})
with patch.dict(pw_user.__salt__, {'cmd.run_all': mock}):
self.assertTrue(pw_user.delete('A'), 1)
mock = MagicMock(return_value=0)
with patch.dict(pw_user.__salt__, {'cmd.retcode': mock}):
self.assertTrue(pw_user.delete('A'))
def test_getent(self):
'''

View File

@ -73,7 +73,7 @@ class RaetPublishTestCase(TestCase):
with patch.object(salt.transport.Channel, 'factory',
MagicMock(return_value=MockFactory())):
self.assertEqual(raet_publish.runner(1),
'1 runner publish timed out')
'\'1\' runner publish timed out')
if __name__ == '__main__':

View File

@ -122,26 +122,6 @@ class RbenvTestCase(TestCase):
with patch.object(rbenv, '_rbenv_exec', return_value=None):
self.assertTrue(rbenv.rehash())
def test_do(self):
'''
Test for execute a ruby command with rbenv's shims from
the user or the system.
'''
with patch.object(rbenv, '_rbenv_path', return_value='A'):
with patch.dict(rbenv.__salt__,
{'cmd.run_all':
MagicMock(return_value={'retcode': 0,
'stdout': 'stdout'})}):
with patch.object(rbenv, 'rehash', return_value=None):
self.assertEqual(rbenv.do(), 'stdout')
with patch.dict(rbenv.__salt__,
{'cmd.run_all':
MagicMock(return_value={'retcode': 1,
'stdout': 'stdout'})}):
with patch.object(rbenv, 'rehash', return_value=None):
self.assertFalse(rbenv.do(), 'stdout')
def test_do_with_ruby(self):
'''
Test for execute a ruby command with rbenv's shims using a

View File

@ -19,8 +19,7 @@ ensure_in_syspath('../../')
# Import Salt Libs
from salt.modules import rsync
from salt.exceptions import CommandExecutionError
import os
from salt.exceptions import CommandExecutionError, SaltInvocationError
# Globals
rsync.__salt__ = {}
@ -37,13 +36,13 @@ class RsyncTestCase(TestCase):
'''
with patch.dict(rsync.__salt__, {'config.option':
MagicMock(return_value=False)}):
self.assertRaises(CommandExecutionError, rsync.rsync, False, False)
self.assertRaises(SaltInvocationError, rsync.rsync, '', '')
with patch.dict(rsync.__salt__,
{'config.option': MagicMock(return_value='A'),
'cmd.run_all': MagicMock(side_effect=[IOError('f'),
'cmd.run': MagicMock(side_effect=[IOError('f'),
'A'])}):
with patch.object(rsync, '_check', return_value='A'):
with patch.object(rsync, '_check', return_value=['A']):
self.assertRaises(CommandExecutionError, rsync.rsync, 'a', 'b')
self.assertEqual(rsync.rsync('src', 'dst'), 'A')
@ -52,25 +51,11 @@ class RsyncTestCase(TestCase):
'''
Test for return rsync version
'''
mock = MagicMock(side_effect=[IOError('f'), {'stdout': 'A B C\n'}])
with patch.dict(rsync.__salt__, {'cmd.run_all': mock}):
mock = MagicMock(side_effect=[IOError('f'), 'A B C\n'])
with patch.dict(rsync.__salt__, {'cmd.run_stdout': mock}):
self.assertRaises(CommandExecutionError, rsync.version)
self.assertEqual(rsync.version(), {'stdout': 'C'})
def test_config(self):
'''
Test for return rsync config
'''
mock_file = MagicMock(side_effect=[False, True, True])
with patch.object(os.path, 'isfile', mock_file):
self.assertRaises(CommandExecutionError, rsync.config)
mock = MagicMock(side_effect=[IOError('f'), 'A'])
with patch.dict(rsync.__salt__, {'cmd.run_all': mock}):
self.assertRaises(CommandExecutionError, rsync.config)
self.assertEqual(rsync.config('confile'), 'A')
self.assertEqual(rsync.version(), 'C')
if __name__ == '__main__':

View File

@ -22,19 +22,27 @@ rvm.__salt__ = {
@skipIf(NO_MOCK, NO_MOCK_REASON)
class TestRvmModule(TestCase):
def test__rvm(self):
def test_rvm(self):
mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
with patch.dict(rvm.__salt__, {'cmd.run_all': mock}):
rvm._rvm('install', '1.9.3')
rvm._rvm(['install', '1.9.3'])
mock.assert_called_once_with(
'/usr/local/rvm/bin/rvm install 1.9.3', runas=None, cwd=None
['/usr/local/rvm/bin/rvm', 'install', '1.9.3'],
runas=None,
cwd=None,
python_shell=False
)
def test__rvm_do(self):
def test_rvm_do(self):
mock = MagicMock(return_value={'retcode': 0, 'stdout': 'stdout'})
with patch.dict(rvm.__salt__, {'cmd.run_all': mock}):
rvm._rvm_do('1.9.3', 'gemset list')
mock.assert_called_once_with('/usr/local/rvm/bin/rvm 1.9.3 do gemset list', runas=None, cwd=None)
rvm._rvm_do('1.9.3', ['gemset', 'list'])
mock.assert_called_once_with(
['/usr/local/rvm/bin/rvm', '1.9.3', 'do', 'gemset', 'list'],
runas=None,
cwd=None,
python_shell=False
)
def test_install(self):
mock = MagicMock(return_value={'retcode': 0})
@ -45,8 +53,20 @@ class TestRvmModule(TestCase):
def test_install_ruby_nonroot(self):
mock = MagicMock(return_value={'retcode': 0, 'stdout': 'stdout'})
expected = [
call('/usr/local/rvm/bin/rvm autolibs disable 2.0.0', runas='rvm', cwd=None),
call('/usr/local/rvm/bin/rvm install --disable-binary 2.0.0', runas='rvm', cwd=None)]
call(
['/usr/local/rvm/bin/rvm', 'autolibs', 'disable', '2.0.0'],
runas='rvm',
cwd=None,
python_shell=False
),
call(
['/usr/local/rvm/bin/rvm', 'install',
'--disable-binary', '2.0.0'],
runas='rvm',
cwd=None,
python_shell=False
)
]
with patch.dict(rvm.__salt__, {'cmd.run_all': mock}):
rvm.install_ruby('2.0.0', runas='rvm')
self.assertEqual(mock.call_args_list, expected)

View File

@ -310,7 +310,7 @@ class VirtualenvTestCase(TestCase):
with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
virtualenv_mod.create('/tmp/foo', prompt='\'PY\' Prompt')
mock.assert_called_once_with(
['virtualenv', '--prompt="\'PY\' Prompt"', '/tmp/foo'],
['virtualenv', "--prompt=''PY' Prompt'", '/tmp/foo'],
runas=None,
python_shell=False
)