Merge "web: add /{tenant}/buildset/{uuid} route"
This commit is contained in:
commit
875bb95363
@ -815,6 +815,23 @@ class TestBuildInfo(ZuulDBTestCase, BaseTestWeb):
|
|||||||
|
|
||||||
buildsets = self.get_url("api/tenant/tenant-one/buildsets").json()
|
buildsets = self.get_url("api/tenant/tenant-one/buildsets").json()
|
||||||
self.assertEqual(2, len(buildsets))
|
self.assertEqual(2, len(buildsets))
|
||||||
|
project_bs = [x for x in buildsets if x["project"] == "org/project"][0]
|
||||||
|
|
||||||
|
buildset = self.get_url(
|
||||||
|
"api/tenant/tenant-one/buildset/%s" % project_bs['uuid']).json()
|
||||||
|
self.assertEqual(3, len(buildset["builds"]))
|
||||||
|
|
||||||
|
project_test1_build = [x for x in buildset["builds"]
|
||||||
|
if x["job_name"] == "project-test1"][0]
|
||||||
|
self.assertEqual('SUCCESS', project_test1_build['result'])
|
||||||
|
|
||||||
|
project_test2_build = [x for x in buildset["builds"]
|
||||||
|
if x["job_name"] == "project-test2"][0]
|
||||||
|
self.assertEqual('SUCCESS', project_test2_build['result'])
|
||||||
|
|
||||||
|
project_merge_build = [x for x in buildset["builds"]
|
||||||
|
if x["job_name"] == "project-merge"][0]
|
||||||
|
self.assertEqual('SUCCESS', project_merge_build['result'])
|
||||||
|
|
||||||
|
|
||||||
class TestArtifacts(ZuulDBTestCase, BaseTestWeb, AnsibleZuulTestCase):
|
class TestArtifacts(ZuulDBTestCase, BaseTestWeb, AnsibleZuulTestCase):
|
||||||
@ -844,3 +861,32 @@ class TestArtifacts(ZuulDBTestCase, BaseTestWeb, AnsibleZuulTestCase):
|
|||||||
{'url': 'http://example.com/tarball',
|
{'url': 'http://example.com/tarball',
|
||||||
'name': 'tarball'},
|
'name': 'tarball'},
|
||||||
])
|
])
|
||||||
|
|
||||||
|
def test_buildset_artifacts(self):
|
||||||
|
self.add_base_changes()
|
||||||
|
self.executor_server.hold_jobs_in_build = False
|
||||||
|
self.executor_server.release()
|
||||||
|
self.waitUntilSettled()
|
||||||
|
|
||||||
|
buildsets = self.get_url("api/tenant/tenant-one/buildsets").json()
|
||||||
|
project_bs = [x for x in buildsets if x["project"] == "org/project"][0]
|
||||||
|
buildset = self.get_url(
|
||||||
|
"api/tenant/tenant-one/buildset/%s" % project_bs['uuid']).json()
|
||||||
|
print("X" * 120)
|
||||||
|
print(buildset)
|
||||||
|
print("Y" * 120)
|
||||||
|
self.assertEqual(3, len(buildset["builds"]))
|
||||||
|
|
||||||
|
test1_build = [x for x in buildset["builds"]
|
||||||
|
if x["job_name"] == "project-test1"][0]
|
||||||
|
arts = test1_build['artifacts']
|
||||||
|
arts.sort(key=lambda x: x['name'])
|
||||||
|
self.assertEqual([
|
||||||
|
{'url': 'http://example.com/docs',
|
||||||
|
'name': 'docs'},
|
||||||
|
{'url': 'http://logs.example.com/build/relative/docs',
|
||||||
|
'name': 'relative',
|
||||||
|
'metadata': {'foo': 'bar'}},
|
||||||
|
{'url': 'http://example.com/tarball',
|
||||||
|
'name': 'tarball'},
|
||||||
|
], test1_build['artifacts'])
|
||||||
|
@ -31,6 +31,9 @@ PROVIDES_TABLE = 'zuul_provides'
|
|||||||
|
|
||||||
|
|
||||||
class DatabaseSession(object):
|
class DatabaseSession(object):
|
||||||
|
|
||||||
|
log = logging.getLogger("zuul.DatabaseSession")
|
||||||
|
|
||||||
def __init__(self, connection):
|
def __init__(self, connection):
|
||||||
self.connection = connection
|
self.connection = connection
|
||||||
self.session = connection.session
|
self.session = connection.session
|
||||||
@ -134,6 +137,29 @@ class DatabaseSession(object):
|
|||||||
except sqlalchemy.orm.exc.NoResultFound:
|
except sqlalchemy.orm.exc.NoResultFound:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
def getBuildset(self, tenant, uuid):
|
||||||
|
"""Get one buildset with its builds"""
|
||||||
|
|
||||||
|
buildset_table = self.connection.zuul_buildset_table
|
||||||
|
|
||||||
|
q = self.session().query(self.connection.buildSetModel).\
|
||||||
|
options(orm.joinedload(self.connection.buildSetModel.builds).
|
||||||
|
subqueryload(self.connection.buildModel.artifacts)).\
|
||||||
|
options(orm.joinedload(self.connection.buildSetModel.builds).
|
||||||
|
subqueryload(self.connection.buildModel.provides)).\
|
||||||
|
with_hint(buildset_table, 'USE INDEX (PRIMARY)', 'mysql')
|
||||||
|
|
||||||
|
q = self.listFilter(q, buildset_table.c.tenant, tenant)
|
||||||
|
q = self.listFilter(q, buildset_table.c.uuid, uuid)
|
||||||
|
|
||||||
|
try:
|
||||||
|
return q.one()
|
||||||
|
except sqlalchemy.orm.exc.NoResultFound:
|
||||||
|
return None
|
||||||
|
except sqlalchemy.orm.exc.MultipleResultsFound:
|
||||||
|
self.log.error("Multiple buildset found with uuid %s", uuid)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class SQLConnection(BaseConnection):
|
class SQLConnection(BaseConnection):
|
||||||
driver_name = 'sql'
|
driver_name = 'sql'
|
||||||
@ -319,3 +345,8 @@ class SQLConnection(BaseConnection):
|
|||||||
"""Return a list of BuildSet objects"""
|
"""Return a list of BuildSet objects"""
|
||||||
with self.getSession() as db:
|
with self.getSession() as db:
|
||||||
return db.getBuildsets(*args, **kw)
|
return db.getBuildsets(*args, **kw)
|
||||||
|
|
||||||
|
def getBuildset(self, *args, **kw):
|
||||||
|
"""Return a BuildSet objects"""
|
||||||
|
with self.getSession() as db:
|
||||||
|
return db.getBuildset(*args, **kw)
|
||||||
|
@ -431,6 +431,8 @@ class ZuulWebAPI(object):
|
|||||||
'voting': build.voting,
|
'voting': build.voting,
|
||||||
'log_url': build.log_url,
|
'log_url': build.log_url,
|
||||||
'node_name': build.node_name,
|
'node_name': build.node_name,
|
||||||
|
'artifacts': [],
|
||||||
|
'provides': [],
|
||||||
}
|
}
|
||||||
|
|
||||||
if buildset:
|
if buildset:
|
||||||
@ -443,22 +445,20 @@ class ZuulWebAPI(object):
|
|||||||
'ref': buildset.ref,
|
'ref': buildset.ref,
|
||||||
'newrev': buildset.newrev,
|
'newrev': buildset.newrev,
|
||||||
'ref_url': buildset.ref_url,
|
'ref_url': buildset.ref_url,
|
||||||
'artifacts': [],
|
|
||||||
'provides': [],
|
|
||||||
})
|
})
|
||||||
|
|
||||||
for artifact in build.artifacts:
|
for artifact in build.artifacts:
|
||||||
art = {
|
art = {
|
||||||
'name': artifact.name,
|
'name': artifact.name,
|
||||||
'url': artifact.url,
|
'url': artifact.url,
|
||||||
}
|
}
|
||||||
if artifact.meta:
|
if artifact.meta:
|
||||||
art['metadata'] = json.loads(artifact.meta)
|
art['metadata'] = json.loads(artifact.meta)
|
||||||
ret['artifacts'].append(art)
|
ret['artifacts'].append(art)
|
||||||
for provides in build.provides:
|
for provides in build.provides:
|
||||||
ret['provides'].append({
|
ret['provides'].append({
|
||||||
'name': provides.name,
|
'name': provides.name,
|
||||||
})
|
})
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def _get_connection(self, tenant):
|
def _get_connection(self, tenant):
|
||||||
@ -505,7 +505,7 @@ class ZuulWebAPI(object):
|
|||||||
resp.headers['Access-Control-Allow-Origin'] = '*'
|
resp.headers['Access-Control-Allow-Origin'] = '*'
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def buildsetToDict(self, buildset):
|
def buildsetToDict(self, buildset, builds=[]):
|
||||||
ret = {
|
ret = {
|
||||||
'uuid': buildset.uuid,
|
'uuid': buildset.uuid,
|
||||||
'result': buildset.result,
|
'result': buildset.result,
|
||||||
@ -519,6 +519,10 @@ class ZuulWebAPI(object):
|
|||||||
'newrev': buildset.newrev,
|
'newrev': buildset.newrev,
|
||||||
'ref_url': buildset.ref_url,
|
'ref_url': buildset.ref_url,
|
||||||
}
|
}
|
||||||
|
if builds:
|
||||||
|
ret['builds'] = []
|
||||||
|
for build in builds:
|
||||||
|
ret['builds'].append(self.buildToDict(build))
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
@ -539,6 +543,20 @@ class ZuulWebAPI(object):
|
|||||||
resp.headers['Access-Control-Allow-Origin'] = '*'
|
resp.headers['Access-Control-Allow-Origin'] = '*'
|
||||||
return [self.buildsetToDict(b) for b in buildsets]
|
return [self.buildsetToDict(b) for b in buildsets]
|
||||||
|
|
||||||
|
@cherrypy.expose
|
||||||
|
@cherrypy.tools.save_params()
|
||||||
|
@cherrypy.tools.json_out(content_type='application/json; charset=utf-8')
|
||||||
|
def buildset(self, tenant, uuid):
|
||||||
|
connection = self._get_connection(tenant)
|
||||||
|
|
||||||
|
data = connection.getBuildset(tenant, uuid)
|
||||||
|
if not data:
|
||||||
|
raise cherrypy.HTTPError(404, "Buildset not found")
|
||||||
|
data = self.buildsetToDict(data, data.builds)
|
||||||
|
resp = cherrypy.response
|
||||||
|
resp.headers['Access-Control-Allow-Origin'] = '*'
|
||||||
|
return data
|
||||||
|
|
||||||
@cherrypy.expose
|
@cherrypy.expose
|
||||||
@cherrypy.tools.save_params()
|
@cherrypy.tools.save_params()
|
||||||
@cherrypy.tools.websocket(handler_cls=LogStreamHandler)
|
@cherrypy.tools.websocket(handler_cls=LogStreamHandler)
|
||||||
@ -697,6 +715,8 @@ class ZuulWeb(object):
|
|||||||
controller=api, action='build')
|
controller=api, action='build')
|
||||||
route_map.connect('api', '/api/tenant/{tenant}/buildsets',
|
route_map.connect('api', '/api/tenant/{tenant}/buildsets',
|
||||||
controller=api, action='buildsets')
|
controller=api, action='buildsets')
|
||||||
|
route_map.connect('api', '/api/tenant/{tenant}/buildset/{uuid}',
|
||||||
|
controller=api, action='buildset')
|
||||||
route_map.connect('api', '/api/tenant/{tenant}/config-errors',
|
route_map.connect('api', '/api/tenant/{tenant}/config-errors',
|
||||||
controller=api, action='config_errors')
|
controller=api, action='config_errors')
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user