Repository :
http://git.fedorahosted.org/cgit/copr.git
On branch : master
---------------------------------------------------------------
commit ed6d74ef21a1de107382cb356713afb5f8142b1c
Author: Valentin Gologuzov <vgologuz(a)redhat.com>
Date: Wed Aug 26 16:02:13 2015 +0200
[frontend][api] Updated and added tests for BuildChroot resource
---------------------------------------------------------------
.../coprs_frontend/coprs/logic/builds_logic.py | 19 ++++-
.../coprs/rest_api/resources/build_chroot.py | 68 +++++++++------
frontend/coprs_frontend/coprs/rest_api/schemas.py | 6 +-
frontend/coprs_frontend/tests/coprs_test_case.py | 1 +
.../tests/test_api/test_build_chroot_r.py | 91 ++++++++++++++++++++
.../coprs_frontend/tests/test_api/test_build_r.py | 36 ++++++++
.../tests/test_api/test_mock_chroot_r.py | 9 +--
7 files changed, 194 insertions(+), 36 deletions(-)
diff --git a/frontend/coprs_frontend/coprs/logic/builds_logic.py
b/frontend/coprs_frontend/coprs/logic/builds_logic.py
index be28dbd..0369205 100644
--- a/frontend/coprs_frontend/coprs/logic/builds_logic.py
+++ b/frontend/coprs_frontend/coprs/logic/builds_logic.py
@@ -7,6 +7,7 @@ import pprint
import time
from sqlalchemy import or_
from sqlalchemy import and_
+from sqlalchemy.orm.exc import NoResultFound
from sqlalchemy.sql import false
from coprs import app
@@ -15,12 +16,15 @@ from coprs import exceptions
from coprs import models
from coprs import helpers
from coprs.constants import DEFAULT_BUILD_TIMEOUT, MAX_BUILD_TIMEOUT
+from coprs.exceptions import MalformedArgumentException
from coprs.helpers import StatusEnum
from coprs.logic import coprs_logic
from coprs.logic import users_logic
from coprs.logic import packages_logic
from coprs.logic.actions_logic import ActionsLogic
+from coprs.models import BuildChroot
+from .coprs_logic import MockChrootsLogic
log = app.logger
@@ -382,6 +386,18 @@ class BuildsLogic(object):
return None
+class BuildChrootsLogic(object):
+ @classmethod
+ def get_by_build_id_and_name(cls, build_id, name):
+ mc = MockChrootsLogic.get_from_name(name).one()
+
+ return (
+ BuildChroot.query
+ .filter(BuildChroot.build_id == build_id)
+ .filter(BuildChroot.mock_chroot_id == mc.id)
+ )
+
+
class BuildsMonitorLogic(object):
@classmethod
def get_monitor_data(cls, copr):
@@ -390,7 +406,8 @@ class BuildsMonitorLogic(object):
for pkg in copr_packages:
chroots = {}
for ch in copr.active_chroots:
- query = (models.BuildChroot.query.join(models.Build)
+ query = (
+ models.BuildChroot.query.join(models.Build)
.filter(models.Build.package_id == pkg.id)
.filter(models.BuildChroot.mock_chroot_id == ch.id)
.filter(models.BuildChroot.status !=
helpers.StatusEnum("canceled")))
diff --git a/frontend/coprs_frontend/coprs/rest_api/resources/build_chroot.py
b/frontend/coprs_frontend/coprs/rest_api/resources/build_chroot.py
index 9baf263..751ecaa 100644
--- a/frontend/coprs_frontend/coprs/rest_api/resources/build_chroot.py
+++ b/frontend/coprs_frontend/coprs/rest_api/resources/build_chroot.py
@@ -6,7 +6,11 @@ from flask import url_for
from flask_restful import Resource, reqparse
from marshmallow import Schema, fields, pprint
-from coprs.logic.builds_logic import BuildsLogic
+
+from ... import models
+from coprs.exceptions import MalformedArgumentException
+from coprs.logic.builds_logic import BuildsLogic, BuildChrootsLogic
+from coprs.rest_api.exceptions import MalformedRequest
from coprs.rest_api.schemas import MockChrootSchema, CoprChrootSchema, BuildChrootSchema
from coprs.views.misc import api_login_required
@@ -15,23 +19,31 @@ from coprs.logic.coprs_logic import MockChrootsLogic,
CoprChrootsLogic, CoprsLog
from ..util import get_one_safe, json_loads_safe, mm_deserialize, mm_serialize_one
+def render_build_chroot(chroot):
+ """
+ :type chroot: models.BuildChroot
+ """
+ return {
+ "chroot": mm_serialize_one(BuildChrootSchema, chroot),
+ "_links": {
+ "project": {"href": url_for(".projectr",
project_id=chroot.build.copr_id)},
+ "self": {"href": url_for(".buildchrootr",
+ build_id=chroot.build.id,
+ name=chroot.name)},
+ }
+ }
+
+
class BuildChrootListR(Resource):
def get(self, build_id):
build = get_one_safe(BuildsLogic.get(build_id),
- "Not found build with id: {}".format(build_id))
+ "Build {} Not found".format(build_id))
return {
"chroots": [
- {
- "chroot": mm_serialize_one(BuildChrootSchema, chroot),
- "_links": {
- "project": {"href":
url_for(".projectr", project_id=build.copr_id)},
- "self": {"href":
url_for(".buildchrootr",
- build_id=build.id,
- name=chroot.name)},
- }
- } for chroot in build.build_chroots
- ],
+ render_build_chroot(chroot)
+ for chroot in build.build_chroots
+ ],
"_links": {
"self": {"href":
url_for(".buildchrootlistr", build_id=build_id)}
}
@@ -39,17 +51,21 @@ class BuildChrootListR(Resource):
class BuildChrootR(Resource):
- pass
- # def get(self, project_id, name):
- # copr = get_one_safe(CoprsLogic.get_by_id(int(project_id)))
- # chroot = CoprChrootsLogic.get_by_name_safe(copr, name)
- #
- # return {
- # "chroot": mm_serialize_one(CoprChrootSchema, chroot),
- # "_links": {
- # "project": {"href": url_for(".projectr",
project_id=copr.id)},
- # "self": {"href":
url_for(".projectchrootr",
- # project_id=project_id,
- # name=chroot.name)},
- # }
- # }
+
+ @staticmethod
+ def _get_chroot_safe(build_id, name):
+ try:
+ chroot = get_one_safe(
+ BuildChrootsLogic.get_by_build_id_and_name(build_id, name),
+ "Build chroot {} for build {} not found"
+ )
+ except MalformedArgumentException as err:
+ raise MalformedRequest("Bad mock chroot name: {}".format(err))
+ return chroot
+
+ def get(self, build_id, name):
+ chroot = self._get_chroot_safe(build_id, name)
+ return render_build_chroot(chroot)
+
+ # todo: add put method: allows only to pass status: cancelled to cancel build
+
diff --git a/frontend/coprs_frontend/coprs/rest_api/schemas.py
b/frontend/coprs_frontend/coprs/rest_api/schemas.py
index 160ef14..4371f79 100644
--- a/frontend/coprs_frontend/coprs/rest_api/schemas.py
+++ b/frontend/coprs_frontend/coprs/rest_api/schemas.py
@@ -76,12 +76,14 @@ class BuildChrootSchema(Schema):
class BuildSchema(Schema):
id = fields.Int()
+ state = fields.Str()
+
pkgs = fields.Str()
build_packages = fields.Str()
pkg_version = fields.Str()
repos_list = fields.List(fields.Str())
- repos = fields.Str() # legacy
+ repos = fields.Str() # todo: replace with SpaceSeparatedList
submitted_on = fields.Int()
started_on = fields.Int()
@@ -94,3 +96,5 @@ class BuildSchema(Schema):
source_type = fields.Int()
source_json = fields.Str()
+
+ # owner = fields.Function(lambda b: b.copr.owner.username, dump_only=True)
diff --git a/frontend/coprs_frontend/tests/coprs_test_case.py
b/frontend/coprs_frontend/tests/coprs_test_case.py
index 52fceb2..0bee47d 100644
--- a/frontend/coprs_frontend/tests/coprs_test_case.py
+++ b/frontend/coprs_frontend/tests/coprs_test_case.py
@@ -205,6 +205,7 @@ class CoprsTestCase(object):
self.b4 = models.Build(
copr=self.c2, package=self.p2, user=self.u2, submitted_on=100)
+ self.basic_builds = [self.b1, self.b2, self.b3, self.b4]
self.b1_bc = []
self.b2_bc = []
self.b3_bc = []
diff --git a/frontend/coprs_frontend/tests/test_api/test_build_chroot_r.py
b/frontend/coprs_frontend/tests/test_api/test_build_chroot_r.py
new file mode 100644
index 0000000..6322504
--- /dev/null
+++ b/frontend/coprs_frontend/tests/test_api/test_build_chroot_r.py
@@ -0,0 +1,91 @@
+# coding: utf-8
+import copy
+
+import json
+from marshmallow import pprint
+
+import pytest
+import sqlalchemy
+
+from coprs.logic.users_logic import UsersLogic
+from coprs.logic.coprs_logic import CoprsLogic
+
+from tests.coprs_test_case import CoprsTestCase, TransactionDecorator
+
+
+class TestBuildChrootResource(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"
+ bc_list = copy.deepcopy(self.b1_bc)
+
+ self.db.session.commit()
+
+ r0 = self.tc.get(href)
+ assert r0.status_code == 200
+ obj = json.loads(r0.data)
+ assert len(obj["chroots"]) == 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",
+ method="post",
+ content={},
+ )
+ assert r0.status_code == 405
+
+ 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",
+ ]
+ bc = self.b1_bc[0]
+ expected_dict = {
+ f: getattr(bc, f)
+ for f in expected_fields
+ }
+ href = "/api_2/builds/1/chroots/{}".format(bc.name)
+ self.db.session.commit()
+
+ r0 = self.tc.get(href)
+ assert r0.status_code == 200
+ obj = json.loads(r0.data)
+ assert obj["chroot"] == expected_dict
+
+ 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"
+ self.db.session.commit()
+
+ r0 = self.tc.get(href)
+ assert r0.status_code == 400
+
+ def get_test_not_found(
+ self, f_users, f_coprs, f_mock_chroots, f_builds, f_db, f_users_api):
+
+ bc = self.b1_bc[0]
+ href = "/api_2/builds/48545656/chroots/{}".format(bc.name)
+ href2 = "/api_2/builds/1/chroots/{}".format(bc.name)
+ self.db.session.commit()
+
+ r0 = self.tc.get(href)
+ assert r0.status_code == 404
+
+ r1 = self.tc.get(href2)
+ assert r1.status_code == 404
+
+
+ # def test_put_cancel_build_chroot
+
+
diff --git a/frontend/coprs_frontend/tests/test_api/test_build_r.py
b/frontend/coprs_frontend/tests/test_api/test_build_r.py
new file mode 100644
index 0000000..52f18fa
--- /dev/null
+++ b/frontend/coprs_frontend/tests/test_api/test_build_r.py
@@ -0,0 +1,36 @@
+# coding: utf-8
+
+import json
+from marshmallow import pprint
+
+import pytest
+import sqlalchemy
+
+from coprs.logic.users_logic import UsersLogic
+from coprs.logic.coprs_logic import CoprsLogic
+
+from tests.coprs_test_case import CoprsTestCase, TransactionDecorator
+
+
+class TestBuildResource(CoprsTestCase):
+
+ def test_collection_ok(self, f_users, f_coprs, f_builds, f_db,
+ f_users_api, f_mock_chroots):
+
+ # project_id = self.c1.id
+
+ href = "/api_2/builds/chroots"
+ expected_len = len(self.basic_builds)
+ self.db.session.commit()
+ r = self.tc.get(href)
+
+ def test_collection_ok_by_username(
+ self, f_users, f_coprs, f_builds, f_db,
+ f_users_api, f_mock_chroots):
+
+ # project_id = self.c1.id
+
+ href = "/api_2/builds?owner={}".format(self.u1.username)
+ expected_len = 2
+ self.db.session.commit()
+ r = self.tc.get(href)
diff --git a/frontend/coprs_frontend/tests/test_api/test_mock_chroot_r.py
b/frontend/coprs_frontend/tests/test_api/test_mock_chroot_r.py
index 3c4061c..beb3568 100644
--- a/frontend/coprs_frontend/tests/test_api/test_mock_chroot_r.py
+++ b/frontend/coprs_frontend/tests/test_api/test_mock_chroot_r.py
@@ -36,17 +36,10 @@ class TestMockChrootResource(CoprsTestCase):
assert len(obj["chroots"]) == expected_len
def test_post_not_allowed(self, f_mock_chroots, f_db, f_users, f_users_api):
- data = {
- u'arch': u'i386',
- u'is_active': True,
- u'name': u'fedora-99-i386',
- u'os_release': u'fedora',
- u'os_version': u'99'
- }
r0 = self.request_rest_api_with_auth(
"/api_2/mock_chroots",
method="post",
- content=data,
+ content={},
)
assert r0.status_code == 405