Merge pull request #38531 from rallytime/bp-33601

Back-port #33601 to 2016.3
This commit is contained in:
Mike Place 2017-01-04 09:56:52 -07:00 committed by GitHub
commit 0056620a53

View file

@ -20,18 +20,26 @@ prefaced with a ``!``.
valid_commands:
- test.ping
- cmd.run
- list_jobs
- list_commands
aliases:
list_jobs:
type: runner
cmd: jobs.list_jobs
list_commands:
cmd: pillar.get salt:engines:slack:valid_commands target=saltmaster
:depends: slackclient
'''
# Import python libraries
from __future__ import absolute_import
import datetime
import json
import logging
import pprint
import time
import re
import yaml
try:
import slackclient
HAS_SLACKCLIENT = True
@ -49,10 +57,7 @@ import salt.utils.slack
def __virtual__():
if not HAS_SLACKCLIENT:
return False
else:
return True
return HAS_SLACKCLIENT
log = logging.getLogger(__name__)
@ -62,16 +67,16 @@ def _get_users(token):
Get all users from Slack
'''
log.debug('running _get_users')
ret = salt.utils.slack.query(function='users',
api_key=token,
opts=__opts__)
users = {}
if 'message' in ret:
for item in ret['message']:
if not item['is_bot']:
users[item['name']] = item['id']
users[item['id']] = item['name']
if 'is_bot' in item:
if not item['is_bot']:
users[item['name']] = item['id']
users[item['id']] = item['name']
return users
@ -92,18 +97,22 @@ def start(token,
fire_master = None
def fire(tag, msg):
'''
Fire event to salt bus
'''
if fire_master:
fire_master(msg, tag)
else:
__salt__['event.send'](tag, msg)
if not token:
log.debug('Slack Bot token not found')
return
raise UserWarning('Slack Bot token not found')
all_users = _get_users(token)
sc = slackclient.SlackClient(token)
slack_connect = sc.rtm_connect()
log.debug('connected to slack')
runner_functions = sorted(salt.runner.Runner(__opts__).functions)
@ -118,6 +127,11 @@ def start(token,
# Edited messages have text in message
_text = _m.get('text', None) or _m.get('message', {}).get('text', None)
# Convert UTF to string
_text = json.dumps(_text)
_text = yaml.safe_load(_text)
if _text:
if _text.startswith('!') and control:
@ -131,6 +145,21 @@ def start(token,
# Trim the ! from the front
# cmdline = _text[1:].split(' ', 1)
cmdline = salt.utils.shlex_split(_text[1:])
# Remove slack url parsing
# Translate target=<http://host.domain.net|host.domain.net>
# to target=host.domain.net
cmdlist = []
for cmditem in cmdline:
pattern = r'(?P<begin>.*)(<.*\|)(?P<url>.*)(>)(?P<remainder>.*)'
m = re.match(pattern, cmditem)
if m:
origtext = m.group('begin') + m.group('url') + m.group('remainder')
cmdlist.append(origtext)
else:
cmdlist.append(cmditem)
cmdline = cmdlist
cmd = cmdline[0]
args = []
kwargs = {}
@ -141,6 +170,13 @@ def start(token,
channel.send_message('Using {0} is not allowed.'.format(cmd))
return
# Evaluate aliases
if aliases and isinstance(aliases, dict) and cmd in aliases.keys():
cmdline = aliases[cmd].get('cmd')
cmdline = salt.utils.shlex_split(cmdline)
cmd = cmdline[0]
# Parse args and kwargs
if len(cmdline) > 1:
for item in cmdline[1:]:
if '=' in item:
@ -149,6 +185,7 @@ def start(token,
else:
args.append(item)
# Check for target. Otherwise assume *
if 'target' not in kwargs:
target = '*'
else:
@ -156,39 +193,35 @@ def start(token,
del kwargs['target']
ret = {}
if aliases and isinstance(aliases, dict) and cmd in aliases.keys():
salt_cmd = aliases[cmd].get('cmd')
if 'type' in aliases[cmd]:
if aliases[cmd]['type'] == 'runner':
runner = salt.runner.RunnerClient(__opts__)
ret = runner.cmd(salt_cmd, arg=args, kwarg=kwargs)
else:
local = salt.client.LocalClient()
ret = local.cmd('{0}'.format(target), salt_cmd, args, kwargs)
elif cmd in runner_functions:
if cmd in runner_functions:
runner = salt.runner.RunnerClient(__opts__)
ret = runner.cmd(cmd, arg=args, kwarg=kwargs)
# default to trying to run as a client module.
# Default to trying to run as a client module.
else:
local = salt.client.LocalClient()
ret = local.cmd('{0}'.format(target), cmd, args, kwargs)
if ret:
pp = pprint.PrettyPrinter(indent=4)
return_text = pp.pformat(ret)
# Slack messages need to be under 4000 characters.
length = 4000
if len(return_text) >= length:
channel.send_message(return_text[0:3999])
channel.send_message('Returned first 4k characters.')
else:
channel.send_message(return_text)
return_text = json.dumps(ret, sort_keys=True, indent=1)
ts = time.time()
st = datetime.datetime.fromtimestamp(ts).strftime('%Y%m%d%H%M%S%f')
filename = 'salt-results-{0}.yaml'.format(st)
result = sc.api_call(
"files.upload", channels=_m['channel'], filename=filename,
content=return_text
)
# Handle unicode return
result = json.dumps(result)
result = yaml.safe_load(result)
if 'ok' in result and result['ok'] is False:
channel.send_message('Error: {0}'.format(result['error']))
else:
# Fire event to event bus
fire('{0}/{1}'.format(tag, _m['type']), _m)
else:
# Fire event to event bus
fire('{0}/{1}'.format(tag, _m['type']), _m)
else:
raise UserWarning("Could not connect to slack")