Repository :
http://git.fedorahosted.org/cgit/copr.git
On branch : master
---------------------------------------------------------------
commit 5ae4b8e4fd7b70de86563d3105432763d4b76dc1
Author: Valentin Gologuzov <vgologuz(a)redhat.com>
Date: Mon Aug 31 16:25:32 2015 +0200
[frontend][api] Added PUT method to /builds/<id> resource
---------------------------------------------------------------
frontend/coprs_frontend/coprs/exceptions.py | 4 +
frontend/coprs_frontend/coprs/helpers.py | 1 +
.../coprs_frontend/coprs/logic/builds_logic.py | 3 +
.../coprs/rest_api/resources/build.py | 22 ++++-
.../coprs/rest_api/resources/project.py | 2 -
.../coprs_frontend/tests/test_api/test_build_r.py | 110 ++++++++++++++++++--
.../test_views/test_coprs_ns/test_coprs_builds.py | 10 ++-
7 files changed, 140 insertions(+), 12 deletions(-)
diff --git a/frontend/coprs_frontend/coprs/exceptions.py
b/frontend/coprs_frontend/coprs/exceptions.py
index 8806c1c..8216e3a 100644
--- a/frontend/coprs_frontend/coprs/exceptions.py
+++ b/frontend/coprs_frontend/coprs/exceptions.py
@@ -18,6 +18,10 @@ class InsufficientRightsException(BaseException):
pass
+class RequestCannotBeExecuted(Exception):
+ pass
+
+
class ActionInProgressException(BaseException):
def __init__(self, msg, action):
diff --git a/frontend/coprs_frontend/coprs/helpers.py
b/frontend/coprs_frontend/coprs/helpers.py
index c5d614f..7d253af 100644
--- a/frontend/coprs_frontend/coprs/helpers.py
+++ b/frontend/coprs_frontend/coprs/helpers.py
@@ -161,6 +161,7 @@ def chroot_to_branch(chroot):
os = "el"
return "{}{}".format(os, version)
+
def branch_to_os_version(branch):
os = None
version = None
diff --git a/frontend/coprs_frontend/coprs/logic/builds_logic.py
b/frontend/coprs_frontend/coprs/logic/builds_logic.py
index 250f82e..48a11da 100644
--- a/frontend/coprs_frontend/coprs/logic/builds_logic.py
+++ b/frontend/coprs_frontend/coprs/logic/builds_logic.py
@@ -408,6 +408,9 @@ class BuildsLogic(object):
if not user.can_build_in(build.copr):
raise exceptions.InsufficientRightsException(
"You are not allowed to cancel this build.")
+ if not build.cancelable:
+ raise exceptions.RequestCannotBeExecuted(
+ "Cannot cancel build {}".format(build.id))
build.canceled = True
for chroot in build.build_chroots:
chroot.status = 2 # canceled
diff --git a/frontend/coprs_frontend/coprs/rest_api/resources/build.py
b/frontend/coprs_frontend/coprs/rest_api/resources/build.py
index 80e5b17..a12a96e 100644
--- a/frontend/coprs_frontend/coprs/rest_api/resources/build.py
+++ b/frontend/coprs_frontend/coprs/rest_api/resources/build.py
@@ -6,7 +6,7 @@ from flask import url_for, make_response
# from flask_restful_swagger import swagger
from coprs import db, models
-from coprs.exceptions import ActionInProgressException, InsufficientRightsException
+from coprs.exceptions import ActionInProgressException, InsufficientRightsException,
RequestCannotBeExecuted
from coprs.logic.coprs_logic import CoprsLogic
from coprs.logic.builds_logic import BuildsLogic
from coprs.logic.users_logic import UsersLogic
@@ -193,6 +193,24 @@ class BuildR(Resource):
return "", 204
+ @rest_api_auth_required
+ def put(self, build_id):
+ build = get_one_safe(BuildsLogic.get(build_id),
+ "Not found build with id: {}".format(build_id))
+ """:type : models.Build """
+ build_dict = mm_deserialize(BuildSchema(), flask.request.data).data
+ try:
+ if not build.canceled and build_dict["state"] ==
"canceled":
+ BuildsLogic.cancel_build(flask.g.user, build)
+ db.session.commit()
+ except (RequestCannotBeExecuted, ActionInProgressException) as err:
+ db.session.rollback()
+ raise CannotProcessRequest("Cannot update build due to: {}"
+ .format(err))
+ except InsufficientRightsException as err:
+ raise AccessForbidden("Failed to update build: {}".format(err))
-
+ resp = make_response("", 201)
+ resp.headers["Location"] = url_for(".buildr",
build_id=build_id)
+ return resp
diff --git a/frontend/coprs_frontend/coprs/rest_api/resources/project.py
b/frontend/coprs_frontend/coprs/rest_api/resources/project.py
index 7a3f293..92a2d3c 100644
--- a/frontend/coprs_frontend/coprs/rest_api/resources/project.py
+++ b/frontend/coprs_frontend/coprs/rest_api/resources/project.py
@@ -80,8 +80,6 @@ class ProjectListR(Resource):
owner = flask.g.user
result = mm_deserialize(ProjectSchema(), flask.request.data)
- if result.errors:
- return "Failed to parse request", 400
# todo check that chroots are available
req = result.data
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 406b7a0..a2067eb 100644
--- a/frontend/coprs_frontend/tests/test_api/test_build_r.py
+++ b/frontend/coprs_frontend/tests/test_api/test_build_r.py
@@ -3,8 +3,9 @@ from cStringIO import StringIO
import json
import math
import random
+from marshmallow import pprint
-from coprs.helpers import BuildSourceEnum
+from coprs.helpers import BuildSourceEnum, StatusEnum
from coprs.logic.coprs_logic import CoprsLogic
from coprs.logic.builds_logic import BuildsLogic
from tests.coprs_test_case import CoprsTestCase
@@ -366,7 +367,6 @@ class TestBuildResource(CoprsTestCase):
def test_delete_build_ok(self, f_users, f_coprs,
f_mock_chroots, f_builds,f_users_api, ):
-
self.db.session.commit()
b_id = self.b1.id
href = "/api_2/builds/{}".format(b_id)
@@ -408,10 +408,106 @@ class TestBuildResource(CoprsTestCase):
login=login, token=token,
)
assert r.status_code == 400
- print(r.data)
- # test_put_build_wrong_user
- # test_put_build_not_found
- # test_put_cancel_build
- # test_put_cancel_build_wrong_state
+ def test_put_build_wrong_user(
+ self, f_users, f_coprs,
+ f_mock_chroots, f_builds,f_users_api, ):
+
+ login = self.u2.api_login
+ token = self.u2.api_token
+
+ for bc in self.b1_bc:
+ bc.status = StatusEnum("pending")
+ bc.ended_on = None
+
+ self.b1.ended_on = None
+ self.db.session.add_all(self.b1_bc)
+ self.db.session.add(self.b1)
+
+ self.db.session.commit()
+
+ href = "/api_2/builds/{}".format(self.b1.id)
+ build_dict = {
+ "state": "canceled"
+ }
+ r = self.request_rest_api_with_auth(
+ href,
+ method="put",
+ login=login, token=token,
+ content=build_dict
+ )
+ assert r.status_code == 403
+
+ def test_put_build_not_found(
+ self, f_users, f_coprs,
+ f_mock_chroots, f_builds,f_users_api, ):
+
+ self.db.session.commit()
+ href = "/api_2/builds/{}".format(10005000)
+ build_dict = {
+ "state": "canceled"
+ }
+ r = self.request_rest_api_with_auth(
+ href,
+ method="put",
+ content=build_dict
+ )
+ assert r.status_code == 404
+
+ def test_put_cancel_build(
+ self, f_users, f_coprs,
+ f_mock_chroots, f_builds,f_users_api, ):
+
+ for bc in self.b1_bc:
+ bc.status = StatusEnum("pending")
+ bc.ended_on = None
+
+ self.b1.ended_on = None
+ self.db.session.add_all(self.b1_bc)
+ self.db.session.add(self.b1)
+
+ self.db.session.commit()
+
+ href = "/api_2/builds/{}".format(self.b1.id)
+ build_dict = {
+ "state": "canceled"
+ }
+ r = self.request_rest_api_with_auth(
+ href,
+ method="put",
+ content=build_dict
+ )
+ assert r.status_code == 201
+
+ r2 = self.tc.get(r.headers["Location"])
+ assert r2.status_code == 200
+ obj = json.loads(r2.data)
+ assert obj["build"]["state"] == "canceled"
+
+ def test_put_cancel_build_wrong_state(
+ self, f_users, f_coprs,
+ f_mock_chroots, f_builds,f_users_api, ):
+
+ self.b1.ended_on = None
+ old_state = self.b1.state
+ self.db.session.add_all(self.b1_bc)
+ self.db.session.add(self.b1)
+
+ self.db.session.commit()
+
+ href = "/api_2/builds/{}".format(self.b1.id)
+ build_dict = {
+ "state": "canceled"
+ }
+ r = self.request_rest_api_with_auth(
+ href,
+ method="put",
+ content=build_dict
+ )
+ assert r.status_code == 400
+
+ r2 = self.tc.get(href)
+ assert r2.status_code == 200
+ obj = json.loads(r2.data)
+ assert obj["build"]["state"] == old_state
diff --git a/frontend/coprs_frontend/tests/test_views/test_coprs_ns/test_coprs_builds.py
b/frontend/coprs_frontend/tests/test_views/test_coprs_ns/test_coprs_builds.py
index aafc17c..7d0e1be 100644
--- a/frontend/coprs_frontend/tests/test_views/test_coprs_ns/test_coprs_builds.py
+++ b/frontend/coprs_frontend/tests/test_views/test_coprs_ns/test_coprs_builds.py
@@ -1,5 +1,6 @@
import json
from coprs import models
+from coprs.helpers import StatusEnum
from tests.coprs_test_case import CoprsTestCase, TransactionDecorator
@@ -89,6 +90,10 @@ class TestCoprCancelBuild(CoprsTestCase):
f_mock_chroots,
f_builds, f_db):
+ for bc in self.b1_bc:
+ bc.status = StatusEnum("pending")
+ bc.ended_on = None
+ self.db.session.add_all(self.b1_bc)
self.db.session.add_all([self.u1, self.c1, self.b1])
self.test_client.post("/coprs/{0}/{1}/cancel_build/{2}/"
.format(self.u1.name, self.c1.name, self.b1.id),
@@ -102,7 +107,10 @@ class TestCoprCancelBuild(CoprsTestCase):
f_coprs,
f_mock_chroots,
f_builds, f_db):
-
+ for bc in self.b1_bc:
+ bc.status = StatusEnum("pending")
+ bc.ended_on = None
+ self.db.session.add_all(self.b1_bc)
self.db.session.add_all([self.u1, self.c1, self.b1])
self.test_client.post("/coprs/{0}/{1}/cancel_build/{2}/"
.format(self.u1.name, self.c1.name, self.b1.id),