From b0e9ef20a75131a06488a1a8bea9dd29f481a1cc Mon Sep 17 00:00:00 2001 From: gryf Date: Tue, 29 Oct 2019 19:35:23 +0100 Subject: [PATCH] Added development mode for http/ssh services --- ferrit/rest.py | 85 +++++++++++++++++++++++++++++++++++++++++--------- ferrit/ssh.py | 82 ++++++++++++++++++++++++++++++------------------ 2 files changed, 122 insertions(+), 45 deletions(-) diff --git a/ferrit/rest.py b/ferrit/rest.py index 6cb7557..221784e 100755 --- a/ferrit/rest.py +++ b/ferrit/rest.py @@ -1,40 +1,93 @@ +import json import logging import os +import sys +import time import bottle # This global variable meant to be set in module, which imports this one -FIFO = None +FIFO = 'ferrit.fifo' LOG_PATH = './' LOG = logging.getLogger('bottle') LOG.setLevel(logging.DEBUG) handler = logging.FileHandler(os.path.join(LOG_PATH, 'ferrit-http.log')) -handler.setFormatter(logging.Formatter('%(asctime)s [%(levelname)s] ' - '%(filename)s:%(lineno)s - ' - '%(message)s')) +handler.setFormatter(logging.Formatter('%(asctime)s %(message)s')) LOG.addHandler(handler) +PATCHSET_CREATED = {"change": {"branch": "master", + "commitMessage": "commit msg", + "id": "I1", + "number": "691277", + "owner": {"email": "j.doe@nonexistent.com", + "name": "John Doe", + "username": "jdoe"}, + "project": "foo", + "status": "NEW", + "subject": "create new patch", + "url": "http://localhost:8181/1"}, + "changeKey": {"id": "I1"}, + "eventCreatedOn": int(time.time()), + "patchSet": {"author": {"email": "j.doe@nonexistent.com", + "name": "John Doe", + "username": "jdoe"}, + "createdOn": int(time.time()) - 1000, + "isDraft": False, + "kind": "REWORK", + "number": "1", + "parents": ["559721d9"], + "ref": "refs/changes/77/691277/1", + "revision": "e3c8ac50", + "sizeDeletions": -15, + "sizeInsertions": 29, + "uploader": {"email": "j.doe@nonexistent.com", + "name": "John Doe", + "username": "jdoe"}}, + "project": "foo", + "refName": "refs/heads/master", + "type": "patchset-created", + "uploader": {"email": "j.doe@nonexistent.com", + "name": "John Doe", + "username": "jdoe"}} + + class App(bottle.Bottle): def __init__(self): super(App, self).__init__() self.route('/Documentation/', callback=self._documentation) self.route('/plugins/events-log/', callback=self._events_log) - self.route('/plugins/events-log/events/', callback=self._events) + self.route('/a/plugins/events-log/events/', callback=self._events) self.route('/a/projects/', callback=self._projects) self.post('/a/changes/~~/revisions/' '/review', callback=self._changes) + self.post('/make/event', callback=self._mk_event) + + def _mk_event(self): + if bottle.request.forms.get('type') == 'patchset-created': + data = dict(PATCHSET_CREATED) + + if 'project' in bottle.request.forms: + data['change']['project'] = bottle.request.forms['project'] + data['project'] = bottle.request.forms['project'] + + if 'branch' in bottle.request.forms: + data['change']['branch'] = bottle.request.forms['branch'] + + with open(FIFO, 'w') as fobj: + fobj.write(json.dumps(data)) + fobj.write('\n') def _documentation(self, whatever, params=None): - return '' + return - def _events_log(params=None): - return '' + def _events_log(self, params=None): + return - def _events(self, t1=None): - return {} + def _events(self): + return def _projects(params=None): """ @@ -68,10 +121,8 @@ class App(bottle.Bottle): if not labels: return - if labels.get('Verified') == 1: - LOG.info('True') - else: - LOG.info('False') + LOG.info(json.dumps(bottle.request.json)) + LOG.info('Verified: %s', labels.get('Verified')) def main(): @@ -82,5 +133,9 @@ def main(): if __name__ == "__main__": # development version, meant to be run as stand alone module, like # python -m ferrit.http + handler = logging.StreamHandler(sys.stdout) + handler.setFormatter(logging.Formatter('%(asctime)s %(message)s')) + LOG.addHandler(handler) + app = App() - app.run(port=8181, host='localhost', debug=True, reloader=True) + app.run(port=8181, host='localhost', debug=True) diff --git a/ferrit/ssh.py b/ferrit/ssh.py index ee33b3e..c37e758 100755 --- a/ferrit/ssh.py +++ b/ferrit/ssh.py @@ -34,13 +34,15 @@ GERRIT_SHELL_MSG = """\r \r """.format(GERRIT_PORT=PORT) -LOG = logging.getLogger(__name__) -LOG.setLevel(logging.DEBUG) -handler = logging.FileHandler(os.path.join(LOG_PATH, 'ferrit-ssh.log')) -handler.setFormatter(logging.Formatter('%(asctime)s [%(levelname)s] ' - '%(filename)s:%(lineno)s %(funcName)s ' - '- %(message)s')) -LOG.addHandler(handler) + +if __name__ != "__main__": + LOG = logging.getLogger(__name__) + LOG.setLevel(logging.DEBUG) + handler = logging.FileHandler(os.path.join(LOG_PATH, 'ferrit-ssh.log')) + handler.setFormatter(logging.Formatter('%(asctime)s [%(levelname)s] ' + '%(filename)s:%(lineno)s ' + '%(funcName)s - %(message)s')) + LOG.addHandler(handler) class Server(paramiko.ServerInterface): @@ -98,10 +100,37 @@ class Server(paramiko.ServerInterface): class SSHHandler(socketserver.StreamRequestHandler): + + def __init__(self, request, client_address, server): + self._commands = {'gerrit version': self._version, + 'gerrit ls-projects': self._ls_projects, + 'gerrit stream-events': self._stream_events} + super(SSHHandler, self).__init__(request, client_address, server) + + def _stream_events(self, channel): + with open(FIFO) as fobj: + data = fobj.read() + if not data: + time.sleep(1) + else: + LOG.debug("Writing %s to channel", data) + channel.send(data) + data = None + + def _version(self, channel): + LOG.debug('sending version string') + channel.send(GERRIT_CMD_VERSION) + channel.close() + + def _ls_projects(self, channel): + LOG.debug('sending list of projects') + channel.send(GERRIT_CMD_PROJECTS) + channel.close() + def handle(self): try: transport = paramiko.Transport(self.connection) - transport.add_server_key(HOST_KEY) + transport.add_server_key(paramiko.RSAKey(filename=KEY)) server = Server(self.client_address) try: transport.start_server(server=server) @@ -122,32 +151,17 @@ class SSHHandler(socketserver.StreamRequestHandler): if server.command: cmd = server.command.decode('utf-8') - LOG.debug('received server command: %s', cmd) - - if cmd == 'gerrit version': - LOG.debug('sending version string') - channel.send(GERRIT_CMD_VERSION) + if cmd in self._commands: + self._commands[cmd](channel) + elif cmd.startswith('git-upload-pack '): + # we suppose to transfer somehow data from some git + # repository + LOG.debug('Cloning (well, no) repository %s', + cmd.split(' ')[1][1:-1]) channel.close() - - elif cmd == 'gerrit ls-projects': - LOG.debug('sending list of projects') - channel.send(GERRIT_CMD_PROJECTS) - channel.close() - - elif cmd == 'gerrit stream-events': - with open(FIFO) as fobj: - data = fobj.read() - if not data: - time.sleep(1) - else: - LOG.debug("Writing %s to channel", data) - channel.send(data) - data = None - else: LOG.debug('unknown command -- closing channel') channel.close() - else: LOG.debug('requested interactive session') channel.send_stderr(GERRIT_SHELL_MSG) @@ -167,11 +181,19 @@ def main(): if __name__ == "__main__": + import argparse + parser = argparse.ArgumentParser() + parser.add_argument('-k', '--key', default=KEY, + help='Path to the private server key') + args = parser.parse_args() + KEY = args.key os.mkfifo(FIFO) handler = logging.StreamHandler(sys.stdout) handler.setFormatter(logging.Formatter('%(asctime)s [%(levelname)s] ' '%(funcName)s:%(lineno)s - ' '%(message)s')) + LOG = logging.getLogger(__name__) + LOG.setLevel(logging.DEBUG) LOG.addHandler(handler) LOG.debug('Start up development server') try: