Merge branch '2014.7' into develop

Conflicts:
	salt/modules/rabbitmq.py
	salt/states/rabbitmq_cluster.py
This commit is contained in:
Colton Myers 2014-11-10 09:59:17 -07:00
commit 9841103427
9 changed files with 420 additions and 64 deletions

View File

@ -21,11 +21,13 @@ major updates in Salt Cloud and the merging of Salt API into the main project.
.. important::
Compound and pillar matching have been temporarily disabled for this
release due to the possibility of inferring pillar data using pillar glob
matching. We will have a proper fix (just disabling pillar glob matching)
in the 2014.7.1 release, and compound matching and non-globbing pillar
matching will be re-enabled at that point.
Compound/pillar matching have been temporarily disabled for the ``mine``
and ``publish`` modules for this release due to the possibility of
inferring pillar data using pillar glob matching. A proper fix is now in
the 2014.7 branch and scheduled for the 2014.7.1 release, and compound
matching and non-globbing pillar matching will be re-enabled at that point.
Compound and pillar matching for normal salt commands are unaffected.
New Transport!

View File

@ -5,6 +5,8 @@ Execute chef in server or solo mode
# Import Python libs
import logging
import tempfile
import os
# Import Salt libs
import salt.utils
@ -17,64 +19,171 @@ def __virtual__():
'''
Only load if chef is installed
'''
if salt.utils.which('chef-client'):
return True
return False
if not salt.utils.which('chef-client'):
return False
if not salt.utils.which('script'):
return False
return True
@decorators.which('chef-client')
def client(*args, **kwargs):
def client(whyrun=False, localmode=False, logfile='/var/log/chef-client.log', **kwargs):
'''
Execute a chef client run and return a dict with the stderr, stdout,
return code, etc.
return code, and pid.
CLI Example:
.. code-block:: bash
salt '*' chef.client server=https://localhost -l debug
salt '*' chef.client server=https://localhost
server
The chef server URL
client_key
Set the client key file location
config
The configuration file to use
config-file-jail
Directory under which config files are allowed to be loaded
(no client.rb or knife.rb outside this path will be loaded).
environment
Set the Chef Environment on the node
group
Group to set privilege to
json-attributes
Load attributes from a JSON file or URL
localmode
Point chef-client at local repository if True
log_level
Set the log level (debug, info, warn, error, fatal)
logfile
Set the log file location
node-name
The node name for this client
override-runlist
Replace current run list with specified items for a single run
pid
Set the PID file location, defaults to /tmp/chef-client.pid
run-lock-timeout
Set maximum duration to wait for another client run to finish,
default is indefinitely.
runlist
Permanently replace current run list with specified items
user
User to set privilege to
validation_key
Set the validation key file location, used for registering new clients
whyrun
Enable whyrun mode when set to True
'''
args += ('chef-client',)
return __exec_cmd(*args, **kwargs)
args = ['chef-client', '--no-color', '--once', '--logfile {0}'.format(logfile)]
if whyrun:
args.append('--why-run')
if localmode:
args.append('--local-mode')
return _exec_cmd(*args, **kwargs)
@decorators.which('chef-solo')
def solo(*args, **kwargs):
def solo(whyrun=False, logfile='/var/log/chef-solo.log', **kwargs):
'''
Execute a chef solo run and return a dict with the stderr, stdout,
return code, etc.
return code, and pid.
CLI Example:
.. code-block:: bash
salt '*' chef.solo config=/etc/chef/solo.rb -l debug
salt '*' chef.solo override-runlist=test
config
The configuration file to use
environment
Set the Chef Environment on the node
group
Group to set privilege to
json-attributes
Load attributes from a JSON file or URL
log_level
Set the log level (debug, info, warn, error, fatal)
logfile
Set the log file location
node-name
The node name for this client
override-runlist
Replace current run list with specified items for a single run
recipe-url
Pull down a remote gzipped tarball of recipes and untar it to
the cookbook cache
run-lock-timeout
Set maximum duration to wait for another client run to finish,
default is indefinitely.
user
User to set privilege to
whyrun
Enable whyrun mode when set to True
'''
args += ('chef-solo',)
return __exec_cmd(*args, **kwargs)
args = ['chef-solo', '--no-color', '--logfile {0}'.format(logfile)]
if whyrun:
args.append('--why-run')
return _exec_cmd(*args, **kwargs)
@decorators.which('ohai')
def ohai(*args, **kwargs):
'''
Execute a ohai and return a dict with the stderr, stdout,
return code, etc.
def _exec_cmd(*args, **kwargs):
CLI Example:
.. code-block:: bash
salt '*' chef.ohai
'''
args += ('ohai',)
return __exec_cmd(*args, **kwargs)
def __exec_cmd(*args, **kwargs):
cmd = ''.join([arg for arg in args])
cmd_args = ''.join([
# Compile the command arguments
cmd_args = ' '.join(args)
cmd_kwargs = ''.join([
' --{0} {1}'.format(k, v) for k, v in kwargs.items() if not k.startswith('__')]
)
cmd_exec = '{0} {1}'.format(cmd, cmd_args)
log.debug('ChefCommand: {0}'.format(cmd_exec))
return __salt__['cmd.run'](cmd_exec)
cmd_exec = '{0}{1}'.format(cmd_args, cmd_kwargs)
log.debug('Chef command: {0}'.format(cmd_exec))
# The only way to capture all the command output, including the
# summary line, is to use the script command to write out to a file
(filedesc, filename) = tempfile.mkstemp()
result = __salt__['cmd.run_all']('script -q -c "{0}" {1}'.format(cmd_exec, filename))
# Read the output from the script command, stripping the first line
with open(filename, 'r') as outfile:
stdout = outfile.readlines()
result['stdout'] = ''.join(stdout[1:])
os.remove(filename)
return result

View File

@ -49,9 +49,8 @@ def _get_rabbitmq_plugin():
if rabbitmq is None:
version = __salt__['pkg.version']('rabbitmq-server').split('-')[0]
path = '/usr/lib/rabbitmq/lib/rabbitmq_server-{0}/\
sbin/rabbitmq-plugins'
rabbitmq = path.format(version)
rabbitmq = ('/usr/lib/rabbitmq/lib/rabbitmq_server-{0}'
'/sbin/rabbitmq-plugins').format(version)
return rabbitmq
@ -67,6 +66,8 @@ def list_users(runas=None):
salt '*' rabbitmq.list_users
'''
ret = {}
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run']('rabbitmqctl list_users',
runas=runas)
for line in res.splitlines():
@ -89,6 +90,8 @@ def list_vhosts(runas=None):
salt '*' rabbitmq.list_vhosts
'''
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run']('rabbitmqctl list_vhosts',
runas=runas)
lines = res.splitlines()
@ -106,6 +109,8 @@ def user_exists(name, runas=None):
salt '*' rabbitmq.user_exists rabbit_user
'''
if runas is None:
runas = salt.utils.get_user()
user_list = list_users(runas=runas)
log.debug(user_list)
@ -122,6 +127,8 @@ def vhost_exists(name, runas=None):
salt '*' rabbitmq.vhost_exists rabbit_host
'''
if runas is None:
runas = salt.utils.get_user()
return name in list_vhosts(runas=runas)
@ -143,6 +150,8 @@ def add_user(name, password=None, runas=None):
password = ''.join(random.SystemRandom().choice(
string.ascii_uppercase + string.digits) for x in range(15))
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run'](
'rabbitmqctl add_user {0} {1!r}'.format(name, password),
output_loglevel='quiet',
@ -173,6 +182,8 @@ def delete_user(name, runas=None):
salt '*' rabbitmq.delete_user rabbit_user
'''
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run']('rabbitmqctl delete_user {0}'.format(name),
runas=runas)
msg = 'Deleted'
@ -190,6 +201,8 @@ def change_password(name, password, runas=None):
salt '*' rabbitmq.change_password rabbit_user password
'''
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run'](
'rabbitmqctl change_password {0} {1!r}'.format(name, password),
output_loglevel='quiet',
@ -209,6 +222,8 @@ def clear_password(name, runas=None):
salt '*' rabbitmq.clear_password rabbit_user
'''
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run']('rabbitmqctl clear_password {0}'.format(name),
runas=runas)
msg = 'Password Cleared'
@ -226,6 +241,8 @@ def add_vhost(vhost, runas=None):
salt '*' rabbitmq add_vhost '<vhost_name>'
'''
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run']('rabbitmqctl add_vhost {0}'.format(vhost),
runas=runas)
@ -243,14 +260,15 @@ def delete_vhost(vhost, runas=None):
salt '*' rabbitmq.delete_vhost '<vhost_name>'
'''
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run']('rabbitmqctl delete_vhost {0}'.format(vhost),
runas=runas)
msg = 'Deleted'
return _format_response(res, msg)
def set_permissions(vhost, user, conf='.*', write='.*', read='.*',
runas=None):
def set_permissions(vhost, user, conf='.*', write='.*', read='.*', runas=None):
'''
Sets permissions for vhost via rabbitmqctl set_permissions
@ -260,6 +278,8 @@ def set_permissions(vhost, user, conf='.*', write='.*', read='.*',
salt '*' rabbitmq.set_permissions 'myvhost' 'myuser'
'''
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),
@ -278,13 +298,15 @@ def list_permissions(vhost, runas=None):
salt '*' rabbitmq.list_permissions '/myvhost'
'''
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run'](
'rabbitmqctl list_permissions -p {0}'.format(vhost),
runas=runas)
return [r.split('\t') for r in res.splitlines()]
def list_user_permissions(name, user=None):
def list_user_permissions(name, runas=None):
'''
List permissions for a user via rabbitmqctl list_user_permissions
@ -294,9 +316,11 @@ def list_user_permissions(name, user=None):
salt '*' rabbitmq.list_user_permissions 'user'.
'''
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run'](
'rabbitmqctl list_user_permissions {0}'.format(name),
runas=user)
runas=runas)
return [r.split('\t') for r in res.splitlines()]
@ -309,6 +333,8 @@ def set_user_tags(name, tags, runas=None):
salt '*' rabbitmq.set_user_tags 'myadmin' 'administrator'
'''
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run'](
'rabbitmqctl set_user_tags {0} {1}'.format(name, tags),
runas=runas)
@ -316,7 +342,7 @@ def set_user_tags(name, tags, runas=None):
return _format_response(res, msg)
def status(user=None):
def status(runas=None):
'''
return rabbitmq status
@ -326,14 +352,16 @@ def status(user=None):
salt '*' rabbitmq.status
'''
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run'](
'rabbitmqctl status',
runas=user
runas=runas
)
return res
def cluster_status(user=None):
def cluster_status(runas=None):
'''
return rabbitmq cluster_status
@ -343,9 +371,11 @@ def cluster_status(user=None):
salt '*' rabbitmq.cluster_status
'''
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run'](
'rabbitmqctl cluster_status',
runas=user)
runas=runas)
return res
@ -365,6 +395,8 @@ def join_cluster(host, user='rabbit', ram_node=None, runas=None):
else:
cmd = 'rabbitmqctl join_cluster {0}@{1}'.format(user, host)
if runas is None:
runas = salt.utils.get_user()
stop_app(runas)
res = __salt__['cmd.run'](cmd, runas=runas)
start_app(runas)
@ -382,6 +414,8 @@ def stop_app(runas=None):
salt '*' rabbitmq.stop_app
'''
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run'](
'rabbitmqctl stop_app',
runas=runas)
@ -399,6 +433,8 @@ def start_app(runas=None):
salt '*' rabbitmq.start_app
'''
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run'](
'rabbitmqctl start_app',
runas=runas)
@ -416,6 +452,8 @@ def reset(runas=None):
salt '*' rabbitmq.reset
'''
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run'](
'rabbitmqctl reset',
runas=runas)
@ -433,6 +471,8 @@ def force_reset(runas=None):
salt '*' rabbitmq.force_reset
'''
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run'](
'rabbitmqctl force_reset',
runas=runas)
@ -440,7 +480,7 @@ def force_reset(runas=None):
return res
def list_queues(*kwargs):
def list_queues(runas=None, *kwargs):
'''
Returns queue details of the / virtual host
@ -450,12 +490,16 @@ def list_queues(*kwargs):
salt '*' rabbitmq.list_queues messages consumers
'''
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run'](
'rabbitmqctl list_queues {0}'.format(' '.join(list(kwargs))))
'rabbitmqctl list_queues {0}'.format(' '.join(list(kwargs))),
runas=runas,
)
return res
def list_queues_vhost(vhost, *kwargs):
def list_queues_vhost(vhost, runas=None, *kwargs):
'''
Returns queue details of specified virtual host. This command will consider
first parameter as the vhost name and rest will be treated as
@ -468,8 +512,15 @@ def list_queues_vhost(vhost, *kwargs):
salt '*' rabbitmq.list_queues messages consumers
'''
res = __salt__['cmd.run']('rabbitmqctl list_queues -p\
{0} {1}'.format(vhost, ' '.join(list(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))
),
runas=runas,
)
return res
@ -487,6 +538,8 @@ def list_policies(runas=None):
salt '*' rabbitmq.list_policies'
'''
ret = {}
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run']('rabbitmqctl list_policies',
runas=runas)
for line in res.splitlines():
@ -523,6 +576,8 @@ def set_policy(vhost, name, pattern, definition, priority=None, runas=None):
salt '*' rabbitmq.set_policy / HA '.*' '{"ha-mode": "all"}'
'''
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,
@ -548,6 +603,8 @@ def delete_policy(vhost, name, runas=None):
salt '*' rabbitmq.delete_policy / HA'
'''
if runas is None:
runas = salt.utils.get_user()
res = __salt__['cmd.run'](
'rabbitmqctl clear_policy -p {0} {1}'.format(
vhost, name),
@ -568,6 +625,8 @@ def policy_exists(vhost, name, runas=None):
salt '*' rabbitmq.policy_exists / HA
'''
if runas is None:
runas = salt.utils.get_user()
policies = list_policies(runas=runas)
return bool(vhost in policies and name in policies[vhost])
@ -584,6 +643,8 @@ def plugin_is_enabled(name, runas=None):
'''
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, runas=runas)
return bool(name in ret)
@ -601,6 +662,8 @@ def enable_plugin(name, runas=None):
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, runas=runas)
return _format_response(ret, 'Enabled')
@ -620,6 +683,8 @@ def disable_plugin(name, runas=None):
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, runas=runas)
return _format_response(ret, 'Disabled')

167
salt/states/chef.py Normal file
View File

@ -0,0 +1,167 @@
# -*- coding: utf-8 -*-
'''
Execute Chef client runs
=====================================================================
Run chef-client or chef-solo
.. code-block:: yaml
my-chef-run:
chef.client:
- override-runlist: 'demo1,demo2'
- server: 'https://chef.domain.com'
default-chef-run:
chef.client: []
my-solo-run:
chef.solo:
- environment: dev
'''
# Import python libs
import re
def __virtual__():
'''
Only load if Chef execution module is available.
'''
return True if 'chef.client' in __salt__ else False
def client(name, **kwargs):
'''
name
Unique identifier for the state. Does not affect the Chef run.
server
The chef server URL
client_key
Set the client key file location
config
The configuration file to use
config-file-jail
Directory under which config files are allowed to be loaded
(no client.rb or knife.rb outside this path will be loaded).
environment
Set the Chef Environment on the node
group
Group to set privilege to
json-attributes
Load attributes from a JSON file or URL
localmode
Point chef-client at local repository if True
log_level
Set the log level (debug, info, warn, error, fatal)
logfile
Set the log file location
node-name
The node name for this client
override-runlist
Replace current run list with specified items for a single run
pid
Set the PID file location, defaults to /tmp/chef-client.pid
run-lock-timeout
Set maximum duration to wait for another client run to finish,
default is indefinitely.
runlist
Permanently replace current run list with specified items
user
User to set privilege to
validation_key
Set the validation key file location, used for registering new clients
'''
return _run(name, 'chef.client', kwargs)
def solo(name, **kwargs):
'''
name
Unique identifier for the state. Does not affect the Chef run.
config
The configuration file to use
environment
Set the Chef Environment on the node
group
Group to set privilege to
json-attributes
Load attributes from a JSON file or URL
log_level
Set the log level (debug, info, warn, error, fatal)
logfile
Set the log file location
node-name
The node name for this client
override-runlist
Replace current run list with specified items for a single run
recipe-url
Pull down a remote gzipped tarball of recipes and untar it to
the cookbook cache
run-lock-timeout
Set maximum duration to wait for another client run to finish,
default is indefinitely.
user
User to set privilege to
'''
return _run(name, 'chef.solo', kwargs)
def _run(name, mod, kwargs):
ret = {'name': name,
'changes': {},
'result': None,
'comment': ''}
result = __salt__[mod](whyrun=__opts__['test'], **kwargs)
if result['retcode'] == 0:
if _has_changes(result['stdout']):
# Populate the 'changes' dict if anything changed
ret['changes']['summary'] = _summary(result['stdout'])
ret['result'] = True if not __opts__['test'] else None
else:
ret['result'] = True
else:
ret['result'] = False
ret['comment'] = result['stdout']
return ret
def _summary(stdout):
return stdout.splitlines()[-1]
def _has_changes(stdout):
regex = re.search(r'Chef Client finished, (\d+)', _summary(stdout), re.IGNORECASE)
return int(regex.group(1)) > 0

View File

@ -29,7 +29,7 @@ def __virtual__():
return False
def enabled(name, runas='root'):
def enabled(name, runas=None):
'''
Ensure the RabbitMQ plugin is enabled.
@ -62,7 +62,7 @@ def enabled(name, runas='root'):
return ret
def disabled(name, runas='root'):
def disabled(name, runas=None):
'''
Ensure the RabbitMQ plugin is disabled.

View File

@ -37,7 +37,7 @@ def present(name,
definition,
priority=0,
vhost='/',
runas='root'):
runas=None):
'''
Ensure the RabbitMQ policy exists.
@ -107,7 +107,7 @@ def present(name,
def absent(name,
vhost='/',
runas='root'):
runas=None):
'''
Ensure the named policy is absent

View File

@ -43,7 +43,7 @@ def present(name,
force=False,
tags=None,
perms=(),
runas='root'):
runas=None):
'''
Ensure the RabbitMQ user exists.
@ -144,7 +144,7 @@ def present(name,
def absent(name,
runas='root'):
runas=None):
'''
Ensure the named user is absent

View File

@ -33,11 +33,11 @@ def __virtual__():
def present(name,
user=None,
owner='root',
owner=None,
conf=None,
write=None,
read=None,
runas='root'):
runas=None):
'''
Ensure the RabbitMQ VHost exists.
@ -146,7 +146,7 @@ def present(name,
def absent(name,
runas='root'):
runas=None):
'''
Ensure the RabbitMQ Virtual Host is absent

View File

@ -1896,6 +1896,19 @@ def warn_until(version,
)
if _dont_call_warnings is False:
def _formatwarning(message,
category,
filename,
lineno,
line=None): # pylint: disable=W0613
'''
Replacement for warnings.formatwarning that disables the echoing of
the 'line' parameter.
'''
return '{0}:{1}: {2}: {3}'.format(
filename, lineno, category.__name__, message
)
warnings.formatwarning = _formatwarning
warnings.warn(
message.format(version=version.formatted_version),
category,