Add pagination and verbose flag to the /rida/module-builds/ route

Adds details about the API changes
This commit is contained in:
Matt Prahl
2016-08-12 09:24:28 -04:00
committed by Nils Philippsen
parent 0bef0e0edc
commit 961f22f0b4
4 changed files with 164 additions and 19 deletions

View File

@@ -97,20 +97,112 @@ The list of all tracked builds and their states can be obtained by querying the
::
[
{
"items": [
{
"id": 41",
"state": "done"
"id": 1,
"state": 3
},
{
"id": 42,
"state": "build"
"id": 2,
"state": 3
},
{
"id": 43,
"state": "init"
"id": 3,
"state": 3
},
{
"id": 4,
"state": 4
},
{
"id": 5,
"state": 4
},
{
"id": 6,
"state": 4
},
{
"id": 7,
"state": 4
},
{
"id": 8,
"state": 4
},
{
"id": 9,
"state": 4
},
{
"id": 10,
"state": 1
}
]
],
"meta": {
"first": "https://rida.fedora.local:5000/rida/module-builds/?per_page=10&page=1",
"last": "https://rida.fedora.local:5000/rida/module-builds/?per_page=10&page=3",
"next": "https://rida.fedora.local:5000/rida/module-builds/?per_page=10&page=2",
"page": 1,
"pages": 3,
"per_page": 10,
"total": 30
}
}
The API is paginated, and defaults to 10 items per page. These values are configurable with the `page` and `per_page`
GET parameters respectively. Additionally, there is a `verbose` parameter that defaults to false, which allows you to
query all the builds with the same amount of detail as querying them individually.
::
GET /rida/module-builds/?verbose=true&per_page=3&page=1
::
HTTP 200 OK
::
{
"items": [
{
"id": 1,
"state": 3,
"tasks": {
"rpms/bash": "90109464/1",
"rpms/module-build-macros": "90109446/1"
}
},
{
"id": 2,
"state": 3,
"tasks": {
"rpms/bash": "90109465/1",
"rpms/module-build-macros": "90109450/1"
}
},
{
"id": 3,
"state": 3,
"tasks": {
"rpms/bash": "90109497/1",
"rpms/module-build-macros": "90109480/1"
}
}
],
"meta": {
"first": "https://127.0.0.1:5000/rida/module-builds/?per_page=3&page=1",
"last": "https://127.0.0.1:5000/rida/module-builds/?per_page=3&page=10",
"next": "https://127.0.0.1:5000/rida/module-builds/?per_page=3&page=2",
"page": 1,
"pages": 10,
"per_page": 3,
"total": 30
}
}
HTTP Response Codes

View File

@@ -192,6 +192,18 @@ class ModuleBuild(RidaBase):
'component_builds': [build.id for build in self.component_builds],
}
def tasks(self):
"""
:return: dictionary containing the tasks associated with the build
"""
tasks = dict()
if self.id and self.state != 'init':
for build in ComponentBuild.query.filter_by(module_id=self.id).all():
tasks["%s/%s" % (build.format, build.package)] = "%s/%s" % (build.task_id, build.state)
return tasks
def __repr__(self):
return "<ModuleBuild %s-%s-%s, state %r, batch %r>" % (
self.name, self.version, self.release,

View File

@@ -19,11 +19,12 @@
# SOFTWARE.
#
# Written by Ralph Bean <rbean@redhat.com>
# Matt Prahl <mprahl@redhat.com>
""" Utility functions for rida. """
from flask import request, url_for
import functools
import time
from rida import log
from rida import log, models
def retry(timeout=120, interval=30, wait_on=Exception):
@@ -69,3 +70,29 @@ def start_next_build_batch(module, session, builder, components=None):
c.task_id = builder.build(artifact_name=c.package, source=c.scmurl)
session.commit()
def pagination_metadata(p_query):
"""
Returns a dictionary containing metadata about the paginated query. This must be run as part of a Flask request.
:param p_query: flask_sqlalchemy.Pagination object
:return: a dictionary containing metadata about the paginated query
"""
pagination_data = {
'page': p_query.page,
'per_page': p_query.per_page,
'total': p_query.total,
'pages': p_query.pages,
'first': url_for(request.endpoint, page=1, per_page=p_query.per_page, _external=True),
'last': url_for(request.endpoint, page=p_query.pages, per_page=p_query.per_page, _external=True)
}
if p_query.has_prev:
pagination_data['prev'] = url_for(request.endpoint, page=p_query.prev_num,
per_page=p_query.per_page, _external=True)
if p_query.has_next:
pagination_data['next'] = url_for(request.endpoint, page=p_query.next_num,
per_page=p_query.per_page, _external=True)
return pagination_data

View File

@@ -21,6 +21,7 @@
# SOFTWARE.
#
# Written by Petr Šabata <contyk@redhat.com>
# Matt Prahl <mprahl@redhat.com>
""" The module build orchestrator for Modularity, API.
This is the implementation of the orchestrator's public RESTful API.
@@ -38,6 +39,7 @@ import shutil
import tempfile
from rida import app, conf, db, log
from rida import models
from rida.utils import pagination_metadata
@app.route("/rida/module-builds/", methods=["POST"])
@@ -143,23 +145,35 @@ def submit_build():
@app.route("/rida/module-builds/", methods=["GET"])
def query_builds():
"""Lists all tracked module builds."""
return jsonify(items=[{"id": x.id, "state": x.state}
for x in models.ModuleBuild.query.all()]), 200
page = request.args.get('page', 1, type=int)
per_page = request.args.get('per_page', 10, type=int)
p_query = models.ModuleBuild.query.paginate(page, per_page, False)
verbose_flag = request.args.get('verbose', 'false')
json_data = {
'meta': pagination_metadata(p_query)
}
if verbose_flag.lower() == 'true' or verbose_flag == '1':
json_data['items'] = [{'id': item.id, 'state': item.state, 'tasks': item.tasks()}
for item in p_query.items]
else:
json_data['items'] = [{'id': item.id, 'state': item.state} for item in p_query.items]
return jsonify(json_data), 200
@app.route("/rida/module-builds/<int:id>", methods=["GET"])
def query_build(id):
"""Lists details for the specified module builds."""
module = models.ModuleBuild.query.filter_by(id=id).first()
if module:
tasks = dict()
if module.state != "init":
for build in models.ComponentBuild.query.filter_by(module_id=id).all():
tasks[build.format + "/" + build.package] = \
str(build.task_id) + "/" + str(build.state)
return jsonify({
"id": module.id,
"state": module.state,
"tasks": tasks
}), 200
"tasks": module.tasks()
}), 200
else:
return "No such module found.", 404