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