From b5e46d058a792073eed83202e83b1c7493bd811a Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Thu, 28 Mar 2019 10:50:52 +0000 Subject: [PATCH] web: Add '/' API route At present, navigating to '/api' will redirect you to '/status'. This makes things a little less discoverable than they should be. Documentation can solve a lot of problems here but simply returning _something_ to let people know the API lives here is a good first step. File permissions for the 'tests/unit/test_web.py' file are fixed. Change-Id: I34b8890146db8adbf54f5b7e0c2fabb4ba819ec2 --- tests/unit/test_web.py | 8 ++++++++ zuul/web/__init__.py | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) mode change 100755 => 100644 tests/unit/test_web.py diff --git a/tests/unit/test_web.py b/tests/unit/test_web.py old mode 100755 new mode 100644 index 211f7cb1d8..58edc49f52 --- a/tests/unit/test_web.py +++ b/tests/unit/test_web.py @@ -91,6 +91,14 @@ class BaseTestWeb(ZuulTestCase): class TestWeb(BaseTestWeb): + def test_web_index(self): + "Test that we can retrieve the index page" + resp = self.get_url('api') + data = resp.json() + # no point checking the whole thing; just make sure _something_ we + # expect is here + self.assertIn('info', data) + def test_web_status(self): "Test that we can retrieve JSON status info" self.add_base_changes() diff --git a/zuul/web/__init__.py b/zuul/web/__init__.py index f533582137..140d6f3806 100755 --- a/zuul/web/__init__.py +++ b/zuul/web/__init__.py @@ -206,6 +206,37 @@ class ZuulWebAPI(object): self.static_cache_expiry = zuulweb.static_cache_expiry self.status_lock = threading.Lock() + @cherrypy.expose + @cherrypy.tools.json_out(content_type='application/json; charset=utf-8') + def index(self): + return { + 'info': '/api/info', + 'connections': '/api/connections', + 'tenants': '/api/tenants', + 'tenant_info': '/api/tenant/{tenant}/info', + 'status': '/api/tenant/{tenant}/status', + 'status_change': '/api/tenant/{tenant}/status/change/{change}', + 'jobs': '/api/tenant/{tenant}/jobs', + 'job': '/api/tenant/{tenant}/job/{job_name}', + 'projects': '/api/tenant/{tenant}/projects', + 'project': '/api/tenant/{tenant}/project/{project:.*}', + 'project_freeze_jobs': '/api/tenant/{tenant}/pipeline/{pipeline}/' + 'project/{project:.*}/branch/{branch:.*}/' + 'freeze-jobs', + 'pipelines': '/api/tenant/{tenant}/pipelines', + 'labels': '/api/tenant/{tenant}/labels', + 'nodes': '/api/tenant/{tenant}/nodes', + 'key': '/api/tenant/{tenant}/key/{project:.*}.pub', + 'project_ssh_key': '/api/tenant/{tenant}/project-ssh-key/' + '{project:.*}.pub', + 'console_stream': '/api/tenant/{tenant}/console-stream', + 'builds': '/api/tenant/{tenant}/builds', + 'build': '/api/tenant/{tenant}/build/{uuid}', + 'buildsets': '/api/tenant/{tenant}/buildsets', + 'buildset': '/api/tenant/{tenant}/buildset/{uuid}', + 'config_errors': '/api/tenant/{tenant}/config-errors', + } + @cherrypy.expose @cherrypy.tools.json_out(content_type='application/json; charset=utf-8') def info(self): @@ -707,6 +738,8 @@ class ZuulWeb(object): route_map = cherrypy.dispatch.RoutesDispatcher() api = ZuulWebAPI(self) + route_map.connect('api', '/api', + controller=api, action='index') route_map.connect('api', '/api/info', controller=api, action='info') route_map.connect('api', '/api/connections',