summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <lars.wirzenius@codethink.co.uk>2014-02-24 15:23:38 +0000
committerLars Wirzenius <lars.wirzenius@codethink.co.uk>2014-02-24 15:23:38 +0000
commita2ce097c089156023da2e7c03f5c5aa6953ec580 (patch)
tree07ed19fb5ef3db72ff8fa941a3c9c5f400dfc04f
parent0b5d07a256ca9f965c79ffb8b8802826d9a51049 (diff)
downloadlorry-controller-a2ce097c089156023da2e7c03f5c5aa6953ec580.tar.gz
Implement /1.0/job-update
-rwxr-xr-xlorry-controller-webapp49
-rw-r--r--yarns.webapp/040-running-jobs.yarn23
-rw-r--r--yarns.webapp/900-implementations.yarn38
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+)