diff options
author | Lars Wirzenius <lars.wirzenius@codethink.co.uk> | 2014-03-25 16:05:04 +0000 |
---|---|---|
committer | Lars Wirzenius <lars.wirzenius@codethink.co.uk> | 2014-03-25 16:05:04 +0000 |
commit | 1ec5c253fa3e2f2f52bf382326799c801cb8fe1d (patch) | |
tree | b8890d8e3aa89582cc47e640fcac389219c686ca | |
parent | 380aa938e91356e137a03ca9f420333abe783ca7 (diff) | |
download | lorry-controller-1ec5c253fa3e2f2f52bf382326799c801cb8fe1d.tar.gz |
Set project.head and project.description from remote Trove
-rw-r--r-- | lorrycontroller/givemejob.py | 61 | ||||
-rw-r--r-- | lorrycontroller/lstroves.py | 1 | ||||
-rw-r--r-- | lorrycontroller/readconf.py | 2 | ||||
-rw-r--r-- | lorrycontroller/statedb.py | 10 |
4 files changed, 69 insertions, 5 deletions
diff --git a/lorrycontroller/givemejob.py b/lorrycontroller/givemejob.py index 46e8885..bfad6c5 100644 --- a/lorrycontroller/givemejob.py +++ b/lorrycontroller/givemejob.py @@ -23,6 +23,13 @@ import cliapp import lorrycontroller +class GitanoCommandFailure(Exception): + + def __init__(self, trovehost, command): + Exception.__init__( + self, 'Failed to run "%s" on Gitano on %s' % (command, trovehost)) + + class GiveMeJob(lorrycontroller.LorryControllerRoute): http_method = 'POST' @@ -39,6 +46,8 @@ class GiveMeJob(lorrycontroller.LorryControllerRoute): for lorry_info in lorry_infos: if self.ready_to_run(lorry_info): self.create_repository_in_local_trove(lorry_info) + if lorry_info['from_trovehost']: + self.copy_repository_metadata(lorry_info) self.give_job_to_minion(statedb, lorry_info) logging.info( 'Giving job %s to lorry %s to MINION %s:%s', @@ -68,6 +77,58 @@ class GiveMeJob(lorrycontroller.LorryControllerRoute): else: logging.info('Created %s on local repo', lorry_info['path']) + def copy_repository_metadata(self, lorry_info): + '''Copy project.head and project.description to the local Trove.''' + + try: + remote_config = self.get_gitano_config( + lorry_info['from_trovehost'], lorry_info['from_path']) + local_config = self.get_gitano_config('localhost', lorry_info['path']) + + if remote_config['project.head'] != local_config['project.head']: + self.set_gitano_config( + 'localhost', lorry_info['path'], + 'project.head', remote_config['project.head']) + + if not local_config['project.description']: + desc = '{host}: {desc}'.format( + host=lorry_info['from_trovehost'], + desc=remote_config['project.description']) + self.set_gitano_config( + 'localhost', lorry_info['path'], + 'project.description', desc) + except GitanoCommandFailure as e: + logging.error('ERROR: %s' % str(e)) + bottle.abort(500) + + def get_gitano_config(self, trovehost, repo_path): + exit, stdout, stderr = cliapp.runcmd( + ['ssh', 'git@%s' % trovehost, + 'config', cliapp.shell_quote(repo_path), 'show']) + + if exit: + raise GitanoCommandFailure(trovehost, 'config show') + + # "config REPO show" outputs a sequence of lines of the form "key: value". + # Extract those into a collections.defaultdict. + + result = collections.defaultdict(str) + for line in stdout.splitlines(): + m = re.match(r'^([^:])+:\s*(.*)$') + if m: + result[m.group(0)] = m.group(1).strip() + + return result + + def set_gitano_config(self, trovehost, repo_path, key, value): + exit, stdout, stderr = cliapp.runcmd( + ['ssh', 'git@%s' % trovehost, + 'config', cliapp.shell_quote(repo_path), + 'set', cliapp.shell_quote(key), cliapp.shell_quote(value)]) + + if exit: + raise GitanoCommandFailure(trovehost, 'config set') + def give_job_to_minion(self, statedb, lorry_info): path = lorry_info['path'] minion_host = bottle.request.forms.host diff --git a/lorrycontroller/lstroves.py b/lorrycontroller/lstroves.py index d80785e..3c37554 100644 --- a/lorrycontroller/lstroves.py +++ b/lorrycontroller/lstroves.py @@ -137,6 +137,7 @@ class TroveRepositoryLister(object): path=local_path, text=json.dumps(lorry, indent=4), from_trovehost=trovehost, + from_path=remote_path, interval=trove_info['lorry_interval']) all_local_paths = set(statedb.get_lorries_for_trove(trovehost)) diff --git a/lorrycontroller/readconf.py b/lorrycontroller/readconf.py index 9ee1f3d..f4dad65 100644 --- a/lorrycontroller/readconf.py +++ b/lorrycontroller/readconf.py @@ -157,7 +157,7 @@ class ReadConfiguration(lorrycontroller.LorryControllerRoute): old_lorry_info = None statedb.add_to_lorries( - path=path, text=text, from_trovehost='', + path=path, text=text, from_trovehost='', from_path='', interval=interval) added_paths.add(path) diff --git a/lorrycontroller/statedb.py b/lorrycontroller/statedb.py index f1da8c9..b49da60 100644 --- a/lorrycontroller/statedb.py +++ b/lorrycontroller/statedb.py @@ -59,6 +59,7 @@ class StateDB(object): ('path', 'TEXT PRIMARY KEY'), ('text', 'TEXT'), ('from_trovehost', 'TEXT'), + ('from_path', 'TEXT'), ('running_job', 'INT'), ('kill_job', 'INT'), ('last_run', 'INT'), @@ -290,8 +291,8 @@ class StateDB(object): 'SELECT path FROM lorries WHERE from_trovehost IS ?', (trovehost,)) return [row[0] for row in c.fetchall()] - def add_to_lorries(self, path=None, text=None, from_trovehost=None, - interval=None): + def add_to_lorries(self, path=None, text=None, from_trovehost=None, + from_path=None, interval=None): logging.debug( 'StateDB.add_to_lorries(' 'path=%r, text=%r, from_trovehost=%r, interval=%s called', @@ -303,6 +304,7 @@ class StateDB(object): assert path is not None assert text is not None assert from_trovehost is not None + assert from_path is not None assert interval is not None assert self.in_transaction @@ -320,9 +322,9 @@ class StateDB(object): c = self.get_cursor() c.execute( 'UPDATE lorries ' - 'SET text=?, from_trovehost=?, interval=? ' + 'SET text=?, from_trovehost=?, from_path=?, interval=? ' 'WHERE path IS ?', - (text, from_trovehost, interval, path)) + (text, from_trovehost, from_path, interval, path)) def remove_lorry(self, path): logging.debug('StateDB.remove_lorry(%r) called', path) |