Anton Shestakov <av6@dwimlabs.net>, Wed, 24 Aug 2016 19:29:28 +0800
queue: handle invalid JSON payload by raising HTTPError(400)
hooks-queue.py
Permissions: -rwxr-xr-x
from argparse import ArgumentParser, FileType, SUPPRESS from tornado.ioloop import IOLoop from tornado.options import define, options from tornado.web import Application, HTTPError, RequestHandler, URLSpec from candolint.utils import lookup_option, timestamp define('listen', metavar='IP', default='127.0.0.1') define('port', metavar='PORT', default=8034, type=int) define('xheaders', metavar='True|False', default=False, type=bool) class BaseHookHandler(RequestHandler): return self.application.rconn def parse_json_payload(self): return json.loads(self.request.body) raise HTTPError(400, 'malformed JSON') def push(self, base, changes): logging.debug('Pushing %s', data) self.rconn.rpush('candolint:queue:changes', data) logging.info('Pushed a change for %s', item['repo']) self.finish({'result': 'OK', 'queued': len(changes)}) class BitbucketHookHandler(BaseHookHandler): payload = self.parse_json_payload() 'url': payload['repository']['links']['html']['href'], 'scm': payload['repository']['scm'], 'repo': payload['repository']['name'], 'timestamp': timestamp(), 'source': 'bitbucket.org' if payload['repository']['scm'] == 'git': for change in payload['push']['changes']: if change['new']['type'] == 'branch': changes.add(change['new']['name']) for change in payload['push']['changes']: for head in change['new'].get('heads', []): changes.add(head['hash']) changes.add(change['new']['target']['hash']) class GithubHookHandler(BaseHookHandler): event = self.request.headers.get('X-GitHub-Event') getattr(self, 'handle_' + event, self.unknown_event)() self.finish({'result': 'pong'}) payload = self.parse_json_payload() 'url': payload['repository']['html_url'], 'repo': payload['repository']['name'], 'timestamp': timestamp(), ref = payload['ref'].rpartition('/')[-1] self.finish({'result': 'unknown event type'}) class CandolintHooks(Application): def __init__(self, rconn, debug): URLSpec(r'/bitbucket', BitbucketHookHandler), URLSpec(r'/github', GithubHookHandler), super(CandolintHooks, self).__init__(handlers, debug=debug) def listen(self, port, address='', **kwargs): name = self.__class__.__name__ logging.info('%s is serving on http://%s:%d/', name, address, port) super(CandolintHooks, self).listen(port, address, **kwargs) parser = ArgumentParser(argument_default=SUPPRESS) '-c', '--config', type=FileType('r'), help='configuration file (YAML)') '-d', '--debug', action='store_true', default=False, help='enable debugging output') group = parser.add_argument_group( 'these options that can also be specified in the configuration file') group.add_argument('--redis-host', help='(default: 127.0.0.1)') group.add_argument('--redis-port', type=int, help='(default: 6379)') group.add_argument('--redis-password') args, extra = parser.parse_known_args() options.parse_command_line([None] + extra) # 1st argument is ignored config = yaml.safe_load(args.config) if hasattr(args, 'config') else {} rhost = lookup_option('redis-host', args, config, default='127.0.0.1') rport = lookup_option('redis-port', args, config, default=6379) rpass = lookup_option('redis-password', args, config) level=logging.DEBUG if args.debug else logging.INFO, format='%(asctime)s %(levelname)-8s %(message)s') logging.debug('Connecting to Redis server') rconn = redis.StrictRedis(host=rhost, port=rport, password=rpass, db=0) logging.info('Connected to Redis server') application = CandolintHooks(rconn, args.debug) application.listen(options.port, options.listen, xheaders=options.xheaders) IOLoop.instance().start() if __name__ == '__main__':