Add a config_errors info to {tenant}/config-errors endpoint

This patch is a follow up on the patch that make Zuul
able to start with a broken configuration. Errors
detected during tenants configurations will be available
under the {tenant}/config-errors endpoint.

Change-Id: Iabc34072dd8d74bcbc50c88d4261c8ca9eafda4e
This commit is contained in:
Fabien Boucher 2018-06-06 11:55:23 +02:00
parent 909013d19d
commit 8800f97c89
4 changed files with 59 additions and 7 deletions

View File

@ -57,13 +57,15 @@ class BaseTestWeb(ZuulTestCase):
info=zuul.model.WebInfo.fromConfig(self.zuul_ini_config)))
self.executor_server.hold_jobs_in_build = True
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
A.addApproval('Code-Review', 2)
self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
B.addApproval('Code-Review', 2)
self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
self.waitUntilSettled()
if self.tenant_config_file != 'config/broken/main.yaml':
A = self.fake_gerrit.addFakeChange('org/project', 'master', 'A')
A.addApproval('Code-Review', 2)
self.fake_gerrit.addEvent(A.addApproval('Approved', 1))
B = self.fake_gerrit.addFakeChange('org/project1', 'master', 'B')
B.addApproval('Code-Review', 2)
self.fake_gerrit.addEvent(B.addApproval('Approved', 1))
self.waitUntilSettled()
self.host = 'localhost'
self.port = self.web.port
@ -315,6 +317,25 @@ class TestInfo(BaseTestWeb):
})
class TestTenantInfoConfigBroken(BaseTestWeb):
tenant_config_file = 'config/broken/main.yaml'
def test_tenant_info_broken_config(self):
config_errors = self.get_url(
"api/tenant/tenant-one/config-errors").json()
self.assertEqual(
len(config_errors), 1)
self.assertEqual(
config_errors[0]['source_context']['project'], 'org/project2')
self.assertEqual(
config_errors[0]['source_context']['branch'], 'master')
self.assertEqual(
config_errors[0]['source_context']['path'], '.zuul.yaml')
self.assertIn('Zuul encountered a syntax error',
config_errors[0]['error'])
class TestWebSocketInfo(TestInfo):
config_ini_data = {

View File

@ -760,6 +760,13 @@ class SourceContext(ConfigObject):
self.path == other.path and
self.trusted == other.trusted)
def toDict(self):
return dict(
project=self.project.name,
branch=self.branch,
path=self.path,
)
class PlaybookContext(ConfigObject):
"""A reference to a playbook in the context of a project.

View File

@ -62,6 +62,7 @@ class RPCListener(object):
self.worker.registerFunction("zuul:status_get")
self.worker.registerFunction("zuul:job_list")
self.worker.registerFunction("zuul:key_get")
self.worker.registerFunction("zuul:config_errors_list")
def getFunctions(self):
functions = {}
@ -356,3 +357,13 @@ class RPCListener(object):
(trusted, project) = tenant.getProject(args.get("project"))
job.sendWorkComplete(
encryption.serialize_rsa_public_key(project.public_key))
def handle_config_errors_list(self, job):
args = json.loads(job.arguments)
tenant = self.sched.abide.tenants.get(args.get("tenant"))
output = []
for err in tenant.layout.loading_errors.errors:
output.append({
'source_context': err[0].toDict(),
'error': err[1]})
job.sendWorkComplete(json.dumps(output))

View File

@ -272,6 +272,17 @@ class ZuulWebAPI(object):
resp.headers['Access-Control-Allow-Origin'] = '*'
return ret
@cherrypy.expose
@cherrypy.tools.save_params()
@cherrypy.tools.json_out(content_type='application/json; charset=utf-8')
def config_errors(self, tenant):
config_errors = self.rpc.submitJob(
'zuul:config_errors_list', {'tenant': tenant})
ret = json.loads(config_errors.data[0])
resp = cherrypy.response
resp.headers['Access-Control-Allow-Origin'] = '*'
return ret
@cherrypy.expose
@cherrypy.tools.save_params()
def key(self, tenant, project):
@ -456,6 +467,8 @@ class ZuulWeb(object):
controller=api, action='console_stream')
route_map.connect('api', '/api/tenant/{tenant}/builds',
controller=api, action='builds')
route_map.connect('api', '/api/tenant/{tenant}/config-errors',
controller=api, action='config_errors')
for connection in connections.connections.values():
controller = connection.getWebController(self)