Update webapp status json to support tenants

Now that zuul is supports multi tenants, we need to update our json
too. Also enable unit tests for it too.

Change-Id: I8dbac9090aab705aa32d4af3c9995b37e96174b6
Signed-off-by: Paul Belanger <pabelanger@redhat.com>
diff --git a/tests/test_webapp.py b/tests/test_webapp.py
index 555c08f..e191244 100644
--- a/tests/test_webapp.py
+++ b/tests/test_webapp.py
@@ -16,6 +16,7 @@
 # under the License.
 
 import json
+from unittest import skip
 
 from six.moves import urllib
 
@@ -23,24 +24,23 @@
 
 
 class TestWebapp(ZuulTestCase):
+    tenant_config_file = 'config/single-tenant/main.yaml'
 
     def _cleanup(self):
-        self.worker.hold_jobs_in_build = False
-        self.worker.release()
+        self.launch_server.hold_jobs_in_build = False
+        self.launch_server.release()
         self.waitUntilSettled()
 
     def setUp(self):
-        self.skip("Disabled for early v3 development")
-
         super(TestWebapp, self).setUp()
         self.addCleanup(self._cleanup)
-        self.worker.hold_jobs_in_build = True
+        self.launch_server.hold_jobs_in_build = True
         A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
-        A.addApproval('CRVW', 2)
-        self.fake_gerrit.addEvent(A.addApproval('APRV', 1))
+        A.addApproval('code-review', 2)
+        self.fake_gerrit.addEvent(A.addApproval('approved', 1))
         B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
-        B.addApproval('CRVW', 2)
-        self.fake_gerrit.addEvent(B.addApproval('APRV', 1))
+        A.addApproval('code-review', 2)
+        self.fake_gerrit.addEvent(B.addApproval('approved', 1))
         self.waitUntilSettled()
         self.port = self.webapp.server.socket.getsockname()[1]
 
@@ -48,7 +48,7 @@
         "Test that we can filter to only certain changes in the webapp."
 
         req = urllib.request.Request(
-            "http://localhost:%s/status" % self.port)
+            "http://localhost:%s/tenant-one/status" % self.port)
         f = urllib.request.urlopen(req)
         data = json.loads(f.read())
 
@@ -57,7 +57,7 @@
     def test_webapp_status_compat(self):
         # testing compat with status.json
         req = urllib.request.Request(
-            "http://localhost:%s/status.json" % self.port)
+            "http://localhost:%s/tenant-one/status.json" % self.port)
         f = urllib.request.urlopen(req)
         data = json.loads(f.read())
 
@@ -69,6 +69,7 @@
             "http://localhost:%s/status/foo" % self.port)
         self.assertRaises(urllib.error.HTTPError, urllib.request.urlopen, req)
 
+    @skip("Disabled for early v3 development")
     def test_webapp_find_change(self):
         # can we filter by change id
         req = urllib.request.Request(
diff --git a/zuul/scheduler.py b/zuul/scheduler.py
index 8b7f50f..b000a6f 100644
--- a/zuul/scheduler.py
+++ b/zuul/scheduler.py
@@ -803,7 +803,7 @@
             return
         pipeline.manager.onNodesProvisioned(event)
 
-    def formatStatusJSON(self):
+    def formatStatusJSON(self, tenant_name):
         # TODOv3(jeblair): use tenants
         if self.config.has_option('zuul', 'url_pattern'):
             url_pattern = self.config.get('zuul', 'url_pattern')
@@ -834,6 +834,7 @@
 
         pipelines = []
         data['pipelines'] = pipelines
-        for pipeline in self.layout.pipelines.values():
+        tenant = self.abide.tenants.get(tenant_name)
+        for pipeline in tenant.layout.pipelines.values():
             pipelines.append(pipeline.formatStatusJSON(url_pattern))
         return json.dumps(data)
diff --git a/zuul/webapp.py b/zuul/webapp.py
index c1c848b..a63f102 100644
--- a/zuul/webapp.py
+++ b/zuul/webapp.py
@@ -51,7 +51,7 @@
         self.port = port
         self.cache_expiry = cache_expiry
         self.cache_time = 0
-        self.cache = None
+        self.cache = {}
         self.daemon = True
         self.server = httpserver.serve(
             dec.wsgify(self.app), host=self.listen_address, port=self.port,
@@ -97,14 +97,17 @@
         return None
 
     def app(self, request):
-        path = self._normalize_path(request.path)
+        tenant_name = request.path.split('/')[1]
+        path = request.path.replace('/' + tenant_name, '')
+        path = self._normalize_path(path)
         if path is None:
             raise webob.exc.HTTPNotFound()
 
-        if (not self.cache or
+        if (tenant_name not in self.cache or
             (time.time() - self.cache_time) > self.cache_expiry):
             try:
-                self.cache = self.scheduler.formatStatusJSON()
+                self.cache[tenant_name] = self.scheduler.formatStatusJSON(
+                    tenant_name)
                 # Call time.time() again because formatting above may take
                 # longer than the cache timeout.
                 self.cache_time = time.time()
@@ -113,7 +116,7 @@
                 raise
 
         if path == 'status':
-            response = webob.Response(body=self.cache,
+            response = webob.Response(body=self.cache[tenant_name],
                                       content_type='application/json')
         else:
             status = self._status_for_change(path)