diff options
author | Lars Wirzenius <lars.wirzenius@codethink.co.uk> | 2014-02-24 15:23:38 +0000 |
---|---|---|
committer | Lars Wirzenius <lars.wirzenius@codethink.co.uk> | 2014-02-24 15:23:38 +0000 |
commit | a2ce097c089156023da2e7c03f5c5aa6953ec580 (patch) | |
tree | 07ed19fb5ef3db72ff8fa941a3c9c5f400dfc04f | |
parent | 0b5d07a256ca9f965c79ffb8b8802826d9a51049 (diff) | |
download | lorry-controller-a2ce097c089156023da2e7c03f5c5aa6953ec580.tar.gz |
Implement /1.0/job-update
-rwxr-xr-x | lorry-controller-webapp | 49 | ||||
-rw-r--r-- | yarns.webapp/040-running-jobs.yarn | 23 | ||||
-rw-r--r-- | yarns.webapp/900-implementations.yarn | 38 |
3 files changed, 94 insertions, 16 deletions
diff --git a/lorry-controller-webapp b/lorry-controller-webapp index 803a7b5..ba1cdf5 100755 --- a/lorry-controller-webapp +++ b/lorry-controller-webapp @@ -60,6 +60,14 @@ class LorryNotFoundError(Exception): self, 'Lorry with path %r not found in STATEDB' % path) +class WrongNumberLorriesRunningJob(Exception): + + def __init__(self, job_id, row_count): + Exception.__init__( + self, 'STATEDB has %d Lorry specs running jobs %r, should be 1', + row_count, job_id) + + class StateDB(object): '''A wrapper around raw Sqlite for STATEDB.''' @@ -217,6 +225,17 @@ class StateDB(object): 'UPDATE lorries SET running_job=? WHERE path=?', (job_id, path)) + def find_lorry_running_job(self, job_id): + logging.debug('StateDB.find_path_running_job(%r) called', job_id) + c = self.get_cursor() + c.execute( + 'SELECT path FROM lorries WHERE running_job IS ?', + (job_id,)) + rows = c.fetchall() + if len(rows) != 1: + raise WrongNumberLorriesRunningJob(job_id, len(rows)) + return rows[0][0] + class LorryControllerRoute(object): @@ -465,9 +484,33 @@ class GiveMeJob(LorryControllerRoute): for lorry_info in lorry_infos: if lorry_info['running_job'] is None: path = lorry_info['path'] - self.statedb.set_running_job(path, 1) - return { 'job-id': path} - return { 'job-id': None } + running_job = 1 + self.statedb.set_running_job(path, running_job) + return { + 'job_id': running_job, + 'path': path, + } + return { 'job_id': None } + + +class JobUpdate(LorryControllerRoute): + + http_method = 'POST' + path = '/1.0/job-update' + + def run(self, **kwargs): + logging.debug('%s %s called', self.http_method, self.path) + + job_id = bottle.request.forms.job_id + exit = bottle.request.forms.exit + + logging.debug('form job_id: %r', job_id) + logging.debug('form exit: %r', exit) + + if exit is not None: + with self.statedb.transaction(): + path = self.statedb.find_lorry_running_job(job_id) + self.statedb.set_running_job(path, None) class WEBAPP(cliapp.Application): diff --git a/yarns.webapp/040-running-jobs.yarn b/yarns.webapp/040-running-jobs.yarn index 8d35ab0..5c028a8 100644 --- a/yarns.webapp/040-running-jobs.yarn +++ b/yarns.webapp/040-running-jobs.yarn @@ -4,13 +4,9 @@ Running jobs This chapter contains tests that verify that WEBAPP schedules jobs, accepts job output, and lets the admin kill running jobs. - -Schedule a job --------------- - To start with, with an empty run-queue, nothing should be scheduled. - SCENARIO job scheduling + SCENARIO run a job GIVEN a new git repository in CONFGIT AND an empty lorry-controller.conf in CONFGIT AND lorry-controller.conf in CONFGIT adds lorries *.lorry using prefix upstream @@ -18,17 +14,28 @@ To start with, with an empty run-queue, nothing should be scheduled. AND a running WEBAPP WHEN admin makes request GET /1.0/give-me-job - THEN response has job-id set to null + THEN response has job_id set to null Add a Lorry spec to the run-queue, and request a job. We should get that job now. GIVEN Lorry file CONFGIT/foo.lorry with {"foo":{"type":"git","url":"git://foo"}} + WHEN admin makes request GET /1.0/read-configuration AND admin makes request GET /1.0/give-me-job - THEN response has job-id set to "upstream/foo" + THEN response has job_id set to 1 + AND response has path set to "upstream/foo" + + WHEN admin makes request GET /1.0/lorry/upstream/foo + THEN response has running_job set to 1 Requesting another job should now again return null. WHEN admin makes request GET /1.0/give-me-job - THEN response has job-id set to null + THEN response has job_id set to null + +Inform WEBAPP the job is finished. + + WHEN MINION makes request POST /1.0/job-update with job_id=1&exit=0 + AND admin makes request GET /1.0/lorry/upstream/foo + THEN response has running_job set to null diff --git a/yarns.webapp/900-implementations.yarn b/yarns.webapp/900-implementations.yarn index 9fb2786..4215fd9 100644 --- a/yarns.webapp/900-implementations.yarn +++ b/yarns.webapp/900-implementations.yarn @@ -131,21 +131,24 @@ configuration directory is. add_to_config_file "$DATADIR/webapp.conf" \ configuration-directory "$DATADIR/$MATCH_1" -Making and analysing GET requests +Making and analysing HTTP requests --------------------------------- -Simple HTTP GET requests are simple. We make the request, and capture -the response: HTTP status code, response headers, response body. +Simple HTTP GET and POST requests are simple. We make the request, +sending a body if given, and capture the response: HTTP status code, +response headers, response body. We make the request using the `curl` command line program, which makes capturing the response quite convenient. -HTTP requests can be made by various entities. For now, we assume -they're all made by the admin. +HTTP requests can be made by various entities. This does not affect +test code, but allows for nicer scenario steps. We check that the HTTP status indicates success, so that every scenario doesn't need ot check that separately. +A GET request: + IMPLEMENTS WHEN admin makes request GET (\S+) rm -f "$DATADIR/response.headers" rm -f "$DATADIR/response.body" @@ -163,6 +166,31 @@ scenario doesn't need ot check that separately. cat "$DATADIR/response.body" head -n1 "$DATADIR/response.headers" | grep '^HTTP/1\.[01] 200 ' +A POST request always has a body. The body consists of `foo=bar` +pairs, separated by `&` signs. + + IMPLEMENTS WHEN (\S+) makes request POST (\S+) with (.*) + rm -f "$DATADIR/response.headers" + rm -f "$DATADIR/response.body" + port=$(cat "$DATADIR/webapp.port") + + # The timestamp is needed by "THEN static status page got updated" + touch "$DATADIR/request.timestamp" + + curl \ + -D "$DATADIR/response.headers" \ + -o "$DATADIR/response.body" \ + --silent --show-error \ + --request POST \ + --data "$MATCH_3" \ + "http://127.0.0.1:$port$MATCH_2" + cat "$DATADIR/response.headers" + if [ -e "$DATADIR/response.body" ] + then + cat "$DATADIR/response.body" + fi + head -n1 "$DATADIR/response.headers" | grep '^HTTP/1\.[01] 200 ' + Check the Content-Type of the response has the desired type. IMPLEMENTS THEN response is (\S+) |