summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Thursfield <sam.thursfield@codethink.co.uk>2014-12-10 18:05:24 +0000
committerSam Thursfield <sam.thursfield@codethink.co.uk>2015-03-11 12:48:44 +0000
commit36cf89491a48e20002898a07b348e6f8c6064f54 (patch)
treee62818d66d13af833a13911c2abb2a869ec8794e
parentce97e140f61cfc3781c3082febeacd0e5fb145cd (diff)
downloadlorry-controller-36cf89491a48e20002898a07b348e6f8c6064f54.tar.gz
Add initial support for mirroring to a Gerrit instancesam/support-gerrit
-rwxr-xr-xlorry-controller-webapp5
-rw-r--r--lorrycontroller/__init__.py1
-rw-r--r--lorrycontroller/gerrit.py53
-rw-r--r--lorrycontroller/givemejob.py37
4 files changed, 89 insertions, 7 deletions
diff --git a/lorry-controller-webapp b/lorry-controller-webapp
index faabb2d..2ed601c 100755
--- a/lorry-controller-webapp
+++ b/lorry-controller-webapp
@@ -129,6 +129,11 @@ class WEBAPP(cliapp.Application):
'ghosts and be removed from STATEDB (in seconds)',
default=10*ONE_MINUTE)
+ self.settings.choice(
+ ['git-server-type'],
+ ['gitano', 'gerrit'],
+ 'what API the local Git server speaks')
+
def find_routes(self):
'''Return all classes that are API routes.
diff --git a/lorrycontroller/__init__.py b/lorrycontroller/__init__.py
index a65ff02..9d46441 100644
--- a/lorrycontroller/__init__.py
+++ b/lorrycontroller/__init__.py
@@ -44,6 +44,7 @@ from gitano import (
new_gitano_command)
from static import StaticFile
from proxy import setup_proxy
+from gerrit import Gerrit
__all__ = locals()
diff --git a/lorrycontroller/gerrit.py b/lorrycontroller/gerrit.py
new file mode 100644
index 0000000..042a621
--- /dev/null
+++ b/lorrycontroller/gerrit.py
@@ -0,0 +1,53 @@
+# Copyright (C) 2015 Codethink Limited
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+
+import cliapp
+
+
+class Gerrit(object):
+
+ '''Run commands on a Gerrit instance.
+
+ This uses the SSH API to Gerrit. The REST API is actually much nicer to
+ use, but it requires that the account doing stuff has set an HTTP password.
+ Use of the SSH API requires only the SSH key that we also use for push
+ access.
+
+ '''
+
+ def __init__(self, host, user, port=29418):
+ self._ssh_command_args = [
+ 'ssh', '-oStrictHostKeyChecking=no', '-oBatchMode=yes', '-p%i' % port,
+ '%s@%s' % (user, host)]
+
+ def _ssh_command(self, command):
+ return cliapp.runcmd(self._ssh_command_args + command)
+
+ def has_project(self, name):
+ # There's no 'does this project exist' command in Gerrit 2.9.4; 'list
+ # all projects with this prefix' is as close we can get.
+
+ output = self._ssh_command([
+ 'gerrit', 'ls-projects', '--type=ALL', '--prefix=%s' % name])
+ projects = output.strip().split('\n')
+
+ if name in projects:
+ return True
+ else:
+ return False
+
+ def create_project(self, name):
+ self._ssh_command(['gerrit', 'create-project', name])
diff --git a/lorrycontroller/givemejob.py b/lorrycontroller/givemejob.py
index 755def0..0d9e6ab 100644
--- a/lorrycontroller/givemejob.py
+++ b/lorrycontroller/givemejob.py
@@ -1,4 +1,4 @@
-# Copyright (C) 2014 Codethink Limited
+# Copyright (C) 2014-2015 Codethink Limited
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -14,13 +14,9 @@
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-import collections
import logging
-import re
-import time
import bottle
-import cliapp
import lorrycontroller
@@ -40,8 +36,7 @@ class GiveMeJob(lorrycontroller.LorryControllerRoute):
now = statedb.get_current_time()
for lorry_info in lorry_infos:
if self.ready_to_run(lorry_info, now):
- self.create_repository_in_local_trove(
- statedb, lorry_info)
+ self.create_repository(statedb, lorry_info)
if lorry_info['from_trovehost']:
self.copy_repository_metadata(statedb, lorry_info)
self.give_job_to_minion(statedb, lorry_info, now)
@@ -67,6 +62,13 @@ class GiveMeJob(lorrycontroller.LorryControllerRoute):
due = lorry_info['last_run'] + lorry_info['interval']
return (lorry_info['running_job'] is None and due <= now)
+ def create_repository(self, statedb, lorry_info):
+ api = self.app_settings['git-server-type']
+ if api == 'gitano':
+ self.create_repository_in_local_trove(statedb, lorry_info)
+ elif api == 'gerrit':
+ self.create_gerrit_project(statedb, lorry_info)
+
def create_repository_in_local_trove(self, statedb, lorry_info):
# Create repository on local Trove. If it fails, assume
# it failed because the repository already existed, and
@@ -82,12 +84,33 @@ class GiveMeJob(lorrycontroller.LorryControllerRoute):
else:
logging.info('Created %s on local repo', lorry_info['path'])
+ def create_gerrit_project(self, statedb, lorry_info):
+ '''Create a project in the local Gerrit server.
+
+ The 'lorry' user must have createProject capability in the Gerrit.
+
+ '''
+ gerrit = lorrycontroller.Gerrit(
+ host='localhost', user='lorry')
+ project_name = lorry_info['path']
+
+ if gerrit.has_project(project_name):
+ logging.info('Project %s exists in local Gerrit already.',
+ project_name)
+ else:
+ gerrit.create_project(project_name)
+ logging.info('Created %s project in local Gerrit.', project_name)
+
def copy_repository_metadata(self, statedb, lorry_info):
'''Copy project.head and project.description to the local Trove.'''
assert lorry_info['from_trovehost']
assert lorry_info['from_path']
+ if self.app_settings['git-server-type'] != 'gitano':
+ # FIXME: would be good to have this info in Gerrit too
+ return
+
remote = lorrycontroller.new_gitano_command(statedb, lorry_info['from_trovehost'])
local = lorrycontroller.LocalTroveGitanoCommand()