Package coprs :: Package rest_api :: Package resources :: Module build
[hide private]
[frames] | no frames]

Source Code for Module coprs.rest_api.resources.build

  1  # coding: utf-8 
  2   
  3  import flask 
  4  from flask import url_for, make_response 
  5  from flask_restful import Resource 
  6   
  7  from ... import db 
  8  from ...exceptions import ActionInProgressException, InsufficientRightsException, RequestCannotBeExecuted 
  9  from ...logic.builds_logic import BuildsLogic 
 10  from ..common import get_project_safe 
 11  from ..exceptions import MalformedRequest, CannotProcessRequest, AccessForbidden 
 12  from ..common import render_build, rest_api_auth_required, render_build_task, get_build_safe, get_user_safe 
 13  from ..schemas import BuildSchema, BuildCreateSchema, BuildCreateFromUrlSchema 
 14  from ..util import mm_deserialize, get_request_parser, arg_bool 
15 16 17 -class BuildListR(Resource):
18 19 @classmethod
20 - def get(cls):
21 22 parser = get_request_parser() 23 24 parser.add_argument('owner', type=str,) 25 parser.add_argument('project_id', type=int) 26 parser.add_argument('group', type=str) 27 28 parser.add_argument('limit', type=int) 29 parser.add_argument('offset', type=int) 30 31 parser.add_argument('is_finished', type=arg_bool) 32 # parser.add_argument('package', type=str) 33 34 req_args = parser.parse_args() 35 36 if req_args["project_id"] is not None: 37 project = get_project_safe(req_args["project_id"]) 38 query = BuildsLogic.get_multiple_by_copr(project) 39 elif req_args["owner"] is not None: 40 user = get_user_safe(req_args["owner"]) 41 query = BuildsLogic.get_multiple_by_user(user) 42 else: 43 query = BuildsLogic.get_multiple() 44 45 if req_args["group"]: 46 query = BuildsLogic.filter_by_group_name(query, req_args["group"]) 47 48 if req_args["is_finished"] is not None: 49 is_finished = req_args["is_finished"] 50 query = BuildsLogic.filter_is_finished(query, is_finished) 51 52 if req_args["limit"] is not None: 53 limit = req_args["limit"] 54 if limit <= 0 or limit > 100: 55 limit = 100 56 else: 57 limit = 100 58 59 query = query.limit(limit) 60 61 if req_args["offset"] is not None: 62 query = query.offset(req_args["offset"]) 63 64 builds = query.all() 65 66 self_params = dict(req_args) 67 self_params["limit"] = limit 68 return { 69 "builds": [ 70 render_build(build) for build in builds 71 ], 72 "_links": { 73 "self": {"href": url_for(".buildlistr", **self_params)}, 74 }, 75 }
76 77 @staticmethod
78 - def handle_post_json(req):
79 """ 80 :return: if of the created build or raise Exception 81 """ 82 build_params = mm_deserialize(BuildCreateFromUrlSchema(), req.data.decode("utf-8")).data 83 project = get_project_safe(build_params["project_id"]) 84 85 chroot_names = build_params.pop("chroots") 86 srpm_url = build_params.pop("srpm_url") 87 try: 88 build = BuildsLogic.create_new_from_url( 89 flask.g.user, project, 90 srpm_url=srpm_url, 91 chroot_names=chroot_names, 92 **build_params 93 ) 94 db.session.commit() 95 except ActionInProgressException as err: 96 db.session.rollback() 97 raise CannotProcessRequest("Cannot create new build due to: {}" 98 .format(err)) 99 except InsufficientRightsException as err: 100 db.session.rollback() 101 raise AccessForbidden("User {} cannot create build in project {}: {}" 102 .format(flask.g.user.username, 103 project.full_name, err)) 104 return build.id
105 106 @staticmethod
107 - def handle_post_multipart(req):
108 """ 109 :return: if of the created build or raise Exception 110 """ 111 try: 112 metadata = req.form["metadata"] 113 except KeyError: 114 raise MalformedRequest("Missing build metadata in the request") 115 116 if "srpm" not in req.files: 117 raise MalformedRequest("Missing srpm file in the request") 118 srpm_handle = req.files["srpm"] 119 120 build_params = mm_deserialize(BuildCreateSchema(), metadata).data 121 project_id = build_params["project_id"] 122 123 project = get_project_safe(project_id) 124 125 chroot_names = build_params.pop("chroots") 126 try: 127 build = BuildsLogic.create_new_from_upload( 128 flask.g.user, project, 129 f_uploader=lambda path: srpm_handle.save(path), 130 orig_filename=srpm_handle.filename, 131 chroot_names=chroot_names, 132 **build_params 133 ) 134 db.session.commit() 135 except ActionInProgressException as err: 136 db.session.rollback() 137 raise CannotProcessRequest("Cannot create new build due to: {}" 138 .format(err)) 139 except InsufficientRightsException as err: 140 db.session.rollback() 141 raise AccessForbidden("User {} cannon create build in project {}: {}" 142 .format(flask.g.user.username, 143 project.full_name, err)) 144 145 return build.id
146 147 @rest_api_auth_required
148 - def post(self):
149 150 req = flask.request 151 if req.content_type is None: 152 raise MalformedRequest("Got request without content type header") 153 154 if "application/json" in req.content_type: 155 build_id = self.handle_post_json(req) 156 elif "multipart/form-data" in req.content_type: 157 build_id = self.handle_post_multipart(req) 158 else: 159 raise MalformedRequest("Got unexpected content type: {}" 160 .format(req.content_type)) 161 resp = make_response("", 201) 162 resp.headers["Location"] = url_for(".buildr", build_id=build_id) 163 164 return resp
165
166 167 -class BuildR(Resource):
168 169 @classmethod
170 - def get(cls, build_id):
171 parser = get_request_parser() 172 parser.add_argument('show_build_tasks', type=arg_bool, default=False) 173 req_args = parser.parse_args() 174 175 build = get_build_safe(build_id) 176 177 self_params = {} 178 if req_args["show_build_tasks"]: 179 self_params["show_build_tasks"] = req_args["show_build_tasks"] 180 181 result = render_build(build, self_params) 182 if req_args["show_build_tasks"]: 183 result["build_tasks"] = [ 184 render_build_task(chroot) 185 for chroot in build.build_chroots 186 ] 187 188 return result
189 190 @classmethod 191 @rest_api_auth_required
192 - def delete(cls, build_id):
193 build = get_build_safe(build_id) 194 try: 195 BuildsLogic.delete_build(flask.g.user, build) 196 db.session.commit() 197 except ActionInProgressException as err: 198 db.session.rollback() 199 raise CannotProcessRequest("Cannot delete build due to: {}" 200 .format(err)) 201 except InsufficientRightsException as err: 202 raise AccessForbidden("Failed to delete build: {}".format(err)) 203 204 return "", 204
205 206 @classmethod 207 @rest_api_auth_required
208 - def put(self, build_id):
209 build = get_build_safe(build_id) 210 build_dict = mm_deserialize(BuildSchema(), flask.request.data.decode("utf-8")).data 211 try: 212 if not build.canceled and build_dict["state"] == "canceled": 213 BuildsLogic.cancel_build(flask.g.user, build) 214 db.session.commit() 215 except (RequestCannotBeExecuted, ActionInProgressException) as err: 216 db.session.rollback() 217 raise CannotProcessRequest("Cannot update build due to: {}" 218 .format(err)) 219 except InsufficientRightsException as err: 220 raise AccessForbidden("Failed to update build: {}".format(err)) 221 222 resp = make_response("", 201) 223 resp.headers["Location"] = url_for(".buildr", build_id=build_id) 224 return resp
225