Port per-change status to zuul-web
Also, re-enable the test for it.
Change-Id: I121fce92cc01018e4e95cd3cda54948415a0d55a
diff --git a/tests/unit/test_web.py b/tests/unit/test_web.py
index 35827a0..7f9e651 100644
--- a/tests/unit/test_web.py
+++ b/tests/unit/test_web.py
@@ -184,7 +184,6 @@
"http://localhost:%s/status/foo" % self.port)
self.assertRaises(urllib.error.HTTPError, urllib.request.urlopen, req)
- @skip("This is not supported by zuul-web")
def test_web_find_change(self):
# can we filter by change id
req = urllib.request.Request(
diff --git a/zuul/web/__init__.py b/zuul/web/__init__.py
index abe9bfa..08df42a 100755
--- a/zuul/web/__init__.py
+++ b/zuul/web/__init__.py
@@ -16,6 +16,7 @@
import asyncio
+import copy
import json
import logging
import os
@@ -158,41 +159,45 @@
'key_get': self.key_get,
}
- async def tenant_list(self, request):
+ async def tenant_list(self, request, result_filter=None):
job = self.rpc.submitJob('zuul:tenant_list', {})
return web.json_response(json.loads(job.data[0]))
- async def status_get(self, request):
+ async def status_get(self, request, result_filter=None):
tenant = request.match_info["tenant"]
if tenant not in self.cache or \
(time.time() - self.cache_time[tenant]) > self.cache_expiry:
job = self.rpc.submitJob('zuul:status_get', {'tenant': tenant})
self.cache[tenant] = json.loads(job.data[0])
self.cache_time[tenant] = time.time()
- resp = web.json_response(self.cache[tenant])
+ payload = self.cache[tenant]
+ if result_filter:
+ payload = result_filter.filterPayload(payload)
+ resp = web.json_response(payload)
resp.headers['Access-Control-Allow-Origin'] = '*'
resp.headers["Cache-Control"] = "public, max-age=%d" % \
self.cache_expiry
resp.last_modified = self.cache_time[tenant]
return resp
- async def job_list(self, request):
+ async def job_list(self, request, result_filter=None):
tenant = request.match_info["tenant"]
job = self.rpc.submitJob('zuul:job_list', {'tenant': tenant})
resp = web.json_response(json.loads(job.data[0]))
resp.headers['Access-Control-Allow-Origin'] = '*'
return resp
- async def key_get(self, request):
+ async def key_get(self, request, result_filter=None):
tenant = request.match_info["tenant"]
project = request.match_info["project"]
job = self.rpc.submitJob('zuul:key_get', {'tenant': tenant,
'project': project})
return web.Response(body=job.data[0])
- async def processRequest(self, request, action):
+ async def processRequest(self, request, action, result_filter=None):
+ resp = None
try:
- resp = await self.controllers[action](request)
+ resp = await self.controllers[action](request, result_filter)
except asyncio.CancelledError:
self.log.debug("request handling cancelled")
except Exception as e:
@@ -202,6 +207,24 @@
return resp
+class ChangeFilter(object):
+ def __init__(self, desired):
+ self.desired = desired
+
+ def filterPayload(self, payload):
+ status = []
+ for pipeline in payload['pipelines']:
+ for change_queue in pipeline['change_queues']:
+ for head in change_queue['heads']:
+ for change in head:
+ if self.wantChange(change):
+ status.append(copy.deepcopy(change))
+ return status
+
+ def wantChange(self, change):
+ return change['id'] == self.desired
+
+
class ZuulWeb(object):
log = logging.getLogger("zuul.web.ZuulWeb")
@@ -238,6 +261,11 @@
async def _handleStatusRequest(self, request):
return await self.gearman_handler.processRequest(request, 'status_get')
+ async def _handleStatusChangeRequest(self, request):
+ change = request.match_info["change"]
+ return await self.gearman_handler.processRequest(
+ request, 'status_get', ChangeFilter(change))
+
async def _handleJobsRequest(self, request):
return await self.gearman_handler.processRequest(request, 'job_list')
@@ -259,6 +287,8 @@
('GET', '/tenants', self._handleTenantsRequest),
('GET', '/{tenant}/status', self._handleStatusRequest),
('GET', '/{tenant}/jobs', self._handleJobsRequest),
+ ('GET', '/{tenant}/status/change/{change}',
+ self._handleStatusChangeRequest),
('GET', '/{tenant}/console-stream', self._handleWebsocket),
('GET', '/{tenant}/{project:.*}.pub', self._handleKeyRequest),
]