Repository : http://git.fedorahosted.org/cgit/copr.git
On branch : master
commit 3ca8a07387d89a930c67a7d53e4faa74e1d303ab Author: Valentin Gologuzov vgologuz@redhat.com Date: Wed Sep 9 12:14:44 2015 +0200
[frontend][API] fixed tests and updated doc to reflect recent changes
.../coprs_frontend/coprs/logic/builds_logic.py | 10 +++++- frontend/coprs_frontend/coprs/rest_api/common.py | 31 ++++++++++------- .../coprs/rest_api/resources/build.py | 17 ++++++--- .../coprs/rest_api/resources/build_task.py | 7 +--- .../coprs_frontend/tests/test_api/test_build_r.py | 16 ++++---- ...test_build_chroot_r.py => test_build_task_r.py} | 32 +++++++++--------- frontend/docs/api_2/source/Resources/build.rst | 29 ++++++++-------- .../docs/api_2/source/Resources/build_task.rst | 35 ++++++++++--------- frontend/docs/api_2/source/index.rst | 3 ++ 9 files changed, 99 insertions(+), 81 deletions(-)
diff --git a/frontend/coprs_frontend/coprs/logic/builds_logic.py b/frontend/coprs_frontend/coprs/logic/builds_logic.py index 3992ed0..3082b5c 100644 --- a/frontend/coprs_frontend/coprs/logic/builds_logic.py +++ b/frontend/coprs_frontend/coprs/logic/builds_logic.py @@ -511,6 +511,15 @@ class BuildsLogic(object): else: return None
+ @classmethod + def filter_is_finished(cls, query, is_finished): + # todo: check that ended_on is set correctly for all cases + # e.g.: failed dist-git import, cancellation + if is_finished: + return query.filter(models.Build.ended_on.isnot(None)) + else: + return query.filter(models.Build.ended_on.is_(None)) +
class BuildChrootsLogic(object): @classmethod @@ -531,7 +540,6 @@ class BuildChrootsLogic(object): .join(models.BuildChroot.mock_chroot) .join(models.Build.copr) .join(models.Copr.owner) - ) return query
diff --git a/frontend/coprs_frontend/coprs/rest_api/common.py b/frontend/coprs_frontend/coprs/rest_api/common.py index 7bc9c81..1945ce8 100644 --- a/frontend/coprs_frontend/coprs/rest_api/common.py +++ b/frontend/coprs_frontend/coprs/rest_api/common.py @@ -3,23 +3,23 @@ import base64 import datetime import functools from logging import getLogger -from coprs.logic.builds_logic import BuildsLogic -from coprs.logic.coprs_logic import CoprsLogic -from coprs.rest_api.schemas import BuildTaskSchema -from coprs.rest_api.util import mm_serialize_one, get_one_safe - -log = getLogger(__name__)
from flask import url_for import flask
from .. import models from ..logic.users_logic import UsersLogic +from ..logic.builds_logic import BuildsLogic +from ..logic.coprs_logic import CoprsLogic +from ..rest_api.schemas import BuildTaskSchema +from ..rest_api.util import mm_serialize_one, get_one_safe
from .exceptions import AuthFailed, ObjectNotFoundError from .schemas import CoprChrootSchema, BuildSchema, ProjectSchema from .util import mm_serialize_one
+log = getLogger(__name__) +
def render_copr_chroot(chroot): return { @@ -41,21 +41,25 @@ def render_build(build, self_params=None): "_links": { "self": {"href": url_for(".buildr", build_id=build.id, **self_params)}, "project": {"href": url_for(".projectr", project_id=build.copr_id)}, - "tasks": {"href": url_for(".buildtasklistr", build_id=build.id)} + "build_tasks": {"href": url_for(".buildtasklistr", build_id=build.id)} } }
-def render_project(copr, self_params=None): +def render_project(project, self_params=None): + """ + :param models.Copr project: + """ if self_params is None: self_params = {}
return { - "project": mm_serialize_one(ProjectSchema, copr), + "project": mm_serialize_one(ProjectSchema, project), "_links": { - "self": {"href": url_for(".projectr", project_id=copr.id, **self_params)}, - "builds": {"href": url_for(".buildlistr", project_id=copr.id)}, - "chroots": {"href": url_for(".projectchrootlistr", project_id=copr.id)} + "self": {"href": url_for(".projectr", project_id=project.id, **self_params)}, + "builds": {"href": url_for(".buildlistr", project_id=project.id)}, + "chroots": {"href": url_for(".projectchrootlistr", project_id=project.id)}, + "build_tasks": {"href":url_for(".buildtasklistr", project_id=project.id) } }, }
@@ -65,9 +69,10 @@ def render_build_task(chroot): :type chroot: models.BuildChroot """ return { - "task": mm_serialize_one(BuildTaskSchema, chroot), + "build_task": mm_serialize_one(BuildTaskSchema, chroot), "_links": { "project": {"href": url_for(".projectr", project_id=chroot.build.copr_id)}, + "build": {"href": url_for(".buildr", build_id=chroot.build_id)}, "self": {"href": url_for(".buildtaskr", build_id=chroot.build.id, name=chroot.name)}, diff --git a/frontend/coprs_frontend/coprs/rest_api/resources/build.py b/frontend/coprs_frontend/coprs/rest_api/resources/build.py index 7d31412..bc1605f 100644 --- a/frontend/coprs_frontend/coprs/rest_api/resources/build.py +++ b/frontend/coprs_frontend/coprs/rest_api/resources/build.py @@ -27,7 +27,7 @@ class BuildListR(Resource): parser.add_argument('limit', type=int) parser.add_argument('offset', type=int)
- parser.add_argument('state', type=str) + parser.add_argument('is_finished', type=bool) # parser.add_argument('package', type=str)
req_args = parser.parse_args() @@ -41,6 +41,11 @@ class BuildListR(Resource): else: query = BuildsLogic.get_multiple()
+ if req_args["is_finished"] is not None: + is_finished = req_args["is_finished"] + query = BuildsLogic.filter_is_finished(query, is_finished) + # TODO: add test! + if req_args["limit"] is not None: limit = req_args["limit"] if limit <= 0 or limit > 100: @@ -156,18 +161,18 @@ class BuildR(Resource):
def get(self, build_id): parser = get_request_parser() - parser.add_argument('show_chroots', type=bool, default=False) + parser.add_argument('show_build_tasks', type=bool, default=False) req_args = parser.parse_args()
build = get_build_safe(build_id)
self_params = {} - if req_args["show_chroots"]: - self_params["show_chroots"] = req_args["show_chroots"] + if req_args["show_build_tasks"]: + self_params["show_build_tasks"] = req_args["show_build_tasks"]
result = render_build(build, self_params) - if req_args["show_chroots"]: - result["build_chroots"] = [ + if req_args["show_build_tasks"]: + result["build_tasks"] = [ render_build_task(chroot) for chroot in build.build_chroots ] diff --git a/frontend/coprs_frontend/coprs/rest_api/resources/build_task.py b/frontend/coprs_frontend/coprs/rest_api/resources/build_task.py index c17a1d1..4c2109c 100644 --- a/frontend/coprs_frontend/coprs/rest_api/resources/build_task.py +++ b/frontend/coprs_frontend/coprs/rest_api/resources/build_task.py @@ -24,11 +24,6 @@ from ..util import get_one_safe, get_request_parser # resp.headers["Location"] == url_for(".buildtasklistr", build_id=build_id)
-class BuildTaskListQuerySchema(Schema): - - build_id = fields.Int() - - class BuildTaskListR(Resource): state_choices = StatusEnum.vals.keys()
@@ -80,7 +75,7 @@ class BuildTaskListR(Resource):
build_chroots = query.all() return { - "tasks": [ + "build_tasks": [ render_build_task(chroot) for chroot in build_chroots ], diff --git a/frontend/coprs_frontend/tests/test_api/test_build_r.py b/frontend/coprs_frontend/tests/test_api/test_build_r.py index 1f0075d..bcc5cf7 100644 --- a/frontend/coprs_frontend/tests/test_api/test_build_r.py +++ b/frontend/coprs_frontend/tests/test_api/test_build_r.py @@ -295,13 +295,13 @@ class TestBuildResource(CoprsTestCase):
assert build_obj["build"]["source_type"] == "srpm_upload"
- chroots_href = build_obj["_links"]["chroots"]["href"] - r2 = self.tc.get(chroots_href) + tasks_href = build_obj["_links"]["build_tasks"]["href"] + r2 = self.tc.get(tasks_href) build_chroots_obj = json.loads(r2.data) - build_chroots_names = set([bc["chroot"]["name"] for bc in - build_chroots_obj["chroots"]]) + build_chroots_names = set([bc["build_task"]["chroot_name"] for bc in + build_chroots_obj["build_tasks"]]) assert set(chroot_name_list) == build_chroots_names - assert len(chroot_name_list) == len(build_chroots_obj["chroots"]) + assert len(chroot_name_list) == len(build_chroots_obj["build_tasks"])
def test_post_multipart_missing_file( self,f_users, f_coprs, f_builds, f_db, @@ -351,20 +351,20 @@ class TestBuildResource(CoprsTestCase): assert obj["build"]["id"] == b_id assert obj["_links"]["self"]["href"] == href
- def test_get_one_build_with_chroots(self, f_users, f_coprs, f_builds, f_db, + def test_get_one_build_with_tasks(self, f_users, f_coprs, f_builds, f_db, f_users_api, f_mock_chroots):
build_id_list = [b.id for b in self.basic_builds] self.db.session.commit()
for b_id in build_id_list: - href = "/api_2/builds/{}?show_chroots=True".format(b_id) + href = "/api_2/builds/{}?show_build_tasks=True".format(b_id) r = self.tc.get(href) assert r.status_code == 200 obj = json.loads(r.data) assert obj["build"]["id"] == b_id assert obj["_links"]["self"]["href"] == href - assert "build_chroots" in obj + assert "build_tasks" in obj
def test_get_one_build_not_found(self, f_users, f_coprs, f_builds, f_db, f_users_api, f_mock_chroots): diff --git a/frontend/coprs_frontend/tests/test_api/test_build_chroot_r.py b/frontend/coprs_frontend/tests/test_api/test_build_task_r.py similarity index 75% rename from frontend/coprs_frontend/tests/test_api/test_build_chroot_r.py rename to frontend/coprs_frontend/tests/test_api/test_build_task_r.py index 8b1b40a..253ed95 100644 --- a/frontend/coprs_frontend/tests/test_api/test_build_chroot_r.py +++ b/frontend/coprs_frontend/tests/test_api/test_build_task_r.py @@ -13,14 +13,12 @@ from coprs.logic.coprs_logic import CoprsLogic from tests.coprs_test_case import CoprsTestCase, TransactionDecorator
-class TestBuildChrootResource(CoprsTestCase): +class TestBuildTaskResource(CoprsTestCase):
def test_collection_ok(self, f_users, f_coprs, f_mock_chroots, f_builds, f_db, f_users_api):
- # project_id = self.c1.id - # import ipdb; ipdb.set_trace() - href = "/api_2/builds/1/chroots" + href = "/api_2/build_tasks?build_id=1&limit=5" bc_list = copy.deepcopy(self.b1_bc)
self.db.session.commit() @@ -28,14 +26,14 @@ class TestBuildChrootResource(CoprsTestCase): r0 = self.tc.get(href) assert r0.status_code == 200 obj = json.loads(r0.data) - assert len(obj["chroots"]) == len(bc_list) + assert len(obj["build_tasks"]) == len(bc_list) assert obj["_links"]["self"]["href"] == href
def test_post_not_allowed(self, f_users, f_coprs, f_mock_chroots, f_builds, f_db, f_users_api): self.db.session.commit() r0 = self.request_rest_api_with_auth( - "/api_2/builds/1/chroots", + "/api_2/build_tasks", method="post", content={}, ) @@ -44,30 +42,32 @@ class TestBuildChrootResource(CoprsTestCase): def test_get_one(self, f_users, f_coprs, f_mock_chroots, f_builds, f_db, f_users_api): expected_fields = [ - "state", - "git_hash", - "started_on", - "ended_on", - "name" + ("state", None), + ("git_hash", None), + ("started_on", None), + ("ended_on", None), + ("name", "chroot_name"), ] bc = self.b1_bc[0] expected_dict = { f: getattr(bc, f) - for f in expected_fields + for f, _ in expected_fields } - href = "/api_2/builds/1/chroots/{}".format(bc.name) + href = "/api_2/build_tasks/1/{}".format(bc.name) self.db.session.commit()
r0 = self.tc.get(href) assert r0.status_code == 200 obj = json.loads(r0.data) - for k in expected_fields: - assert obj["chroot"][k] == expected_dict[k] + for k, res_k in expected_fields: + if res_k is None: + res_k = k + assert obj["build_task"][res_k] == expected_dict[k]
def test_get_one_bad_name(self, f_users, f_coprs, f_mock_chroots, f_builds, f_db, f_users_api):
- href = "/api_2/builds/1/chroots/surely_bad_chroot_name" + href = "/api_2/build_tasks/1/surely_bad_chroot_name" self.db.session.commit()
r0 = self.tc.get(href) diff --git a/frontend/docs/api_2/source/Resources/build.rst b/frontend/docs/api_2/source/Resources/build.rst index 3769808..517df70 100644 --- a/frontend/docs/api_2/source/Resources/build.rst +++ b/frontend/docs/api_2/source/Resources/build.rst @@ -4,7 +4,7 @@ Build Build resources allows to submit new builds and access current build progress.
Build in fact consists of the few tasks, one per chroot, and detail information -is available through sub-resource :doc:`./build_chroot`. +is available through sub-resource :doc:`./build_task`.
@@ -47,10 +47,10 @@ Build fields Field Type Description ================== ==================== =============== id int unique build identifier -state string current state of the build, value is aggregated from build chroots +state string current state of the build, value is aggregated from build tasks submitted_on int(unixtime UTC) time of the build submission -started_on int(unixtime UTC) time when the first build chroot started, otherwise ``null`` -ended_on int(unixtime UTC) time when the last build chroot ended, otherwise ``null`` +started_on int(unixtime UTC) time when the first build task started, otherwise ``null`` +ended_on int(unixtime UTC) time when the last build task ended, otherwise ``null`` source_type string method used for build creation source_metadata json object build source information package_version string version of the source package @@ -108,8 +108,8 @@ List builds "self": { "href": "/api_2/builds/106897" }, - "chroots": { - "href": "/api_2/builds/106897/chroots" + "build_tasks": { + "href": "/api_2/build_tasks?build_id=106897" } }, "build": { @@ -269,7 +269,7 @@ Get build details Returns details about build
:param int build_id: a unique identifier of the build - :query bool show_chroots: embed :doc:`./build_chroot` sub-resources into the result, default is False + :query bool show_build_tasks: embed :doc:`./build_task` sub-resources into the result, default is False
:statuscode 200: no error :statuscode 404: build not found @@ -278,7 +278,7 @@ Get build details
.. sourcecode:: http
- GET /api_2/builds/106897 HTTP/1.1 + GET /api_2/builds/106897?show_build_tasks=True HTTP/1.1 Host: copr.fedoraproject.org
**Response** @@ -289,10 +289,11 @@ Get build details Content-Type: application/json
{ - "build_chroots": [ + "build_tasks": [ { - "chroot": { - "name": "fedora-21-i386", + "tasks": { + "build_id": 3985, + "chroot_name": "fedora-21-i386", "started_on": 1441366860, "state": "succeeded", "ended_on": 1441366969, @@ -304,7 +305,7 @@ Get build details "href": "/api_2/projects/3985" }, "self": { - "href": "/api_2/builds/106897/chroots/fedora-21-i386" + "href": "/api_2/build_tasks/106897/fedora-21-i386" } } } @@ -316,8 +317,8 @@ Get build details "self": { "href": "/api_2/builds/106897?show_chroots=True" }, - "chroots": { - "href": "/api_2/builds/106897/chroots" + "build_tasks": { + "href": "/api_2/build_tasks/?build_id=3985" } }, "build": { diff --git a/frontend/docs/api_2/source/Resources/build_task.rst b/frontend/docs/api_2/source/Resources/build_task.rst index c5871a4..2212475 100644 --- a/frontend/docs/api_2/source/Resources/build_task.rst +++ b/frontend/docs/api_2/source/Resources/build_task.rst @@ -1,7 +1,7 @@ Build Task ==========
-Build task represents information about individual build tasks per each chroot. +Build task represents information about individual build tasks. One task is responsible for one chroot.
Structure of the build task entity ---------------------------------- @@ -9,7 +9,7 @@ Structure of the build task entity .. code-block:: javascript
{ - "name": "fedora-rawhide-x86_64", + "chroot_name": "fedora-rawhide-x86_64", "build_id": 12345, "started_on": 1440753865, "ended_on": 1440753919, @@ -18,14 +18,14 @@ Structure of the build task entity "git_hash": "d241064b14f9dcd5d9032d0aca3b4e78fbd1aafd" }
-Build chroot fields -~~~~~~~~~~~~~~~~~~~ +Build tasks fields +~~~~~~~~~~~~~~~~~~ ================== ==================== =============== Field Type Description ================== ==================== =============== chroot_name str chroot name build_id int unique build identifier -state str current build state +state str current build task state started_on int(unixtime UTC) time when the build chroot started ended_on int(unixtime UTC) time when the build chroot ended git_hash str hash of the git commit in dist-git used for the build @@ -37,8 +37,8 @@ result_dir_url str(URL) location of the build results Build Chroot doesn't currently support any modifications, so all fields are read-only.
-List build chroots ------------------- +List build tasks +----------------
.. http:get:: /api_2/builds_tasks
@@ -77,10 +77,10 @@ List build chroots Content-Type: application/json
{ - "chroots": [ + "build_tasks": [ { - "chroot": { - "name": "fedora-rawhide-x86_64", + "build_task": { + "chroot_name": "fedora-rawhide-x86_64", "started_on": 1440753865, "state": "succeeded", "ended_on": 1440753919, @@ -92,14 +92,14 @@ List build chroots "href": "/api_2/projects/3985" }, "self": { - "href": "/api_2/builds/106882/chroots/fedora-rawhide-x86_64" + "href": "/api_2/build_tasks/106882/fedora-rawhide-x86_64" } } } ], "_links": { "self": { - "href": "/api_2/builds/106882/chroots" + "href": "/api_2/build_tasks?build_id=106882" } } } @@ -109,7 +109,7 @@ List build chroots Get build task details ----------------------
-.. http:get:: /api_2/builds/(int:build_id)/chroots/(str:name) +.. http:get:: /api_2/build_tasks/(int:build_id)/(str:name)
Returns details about one build task
@@ -123,7 +123,7 @@ Get build task details
.. sourcecode:: http
- GET /api_2/builds/106882/chroots/fedora-rawhide-x86_64 HTTP/1.1 + GET /api_2/build_tasks/106882/fedora-rawhide-x86_64 HTTP/1.1 Host: copr.fedoraproject.org
**Response** @@ -134,8 +134,9 @@ Get build task details Content-Type: application/json
{ - "chroot": { - "name": "fedora-rawhide-x86_64", + "build_task": { + "chroot_name": "fedora-rawhide-x86_64", + "build_id": 3985, "started_on": 1440753865, "state": "succeeded", "ended_on": 1440753919, @@ -147,7 +148,7 @@ Get build task details "href": "/api_2/projects/3985" }, "self": { - "href": "/api_2/builds/106882/chroots/fedora-rawhide-x86_64" + "href": "/api_2/build_tasks/106882/fedora-rawhide-x86_64" } } } diff --git a/frontend/docs/api_2/source/index.rst b/frontend/docs/api_2/source/index.rst index 3ed6a68..6bf0743 100644 --- a/frontend/docs/api_2/source/index.rst +++ b/frontend/docs/api_2/source/index.rst @@ -52,6 +52,9 @@ Here is a short example with the content of API root: "builds": { "href": "/api_2/builds" } + "build_tasks": { + "href": "/api_2/build_tasks" + } }
Response structure