Package coprs :: Package views :: Package api_ns :: Module api_general
[hide private]
[frames] | no frames]

Source Code for Module coprs.views.api_ns.api_general

  1  import base64 
  2  import datetime 
  3  import urlparse 
  4   
  5  import flask 
  6   
  7  from coprs import db 
  8  from coprs import exceptions 
  9  from coprs import forms 
 10  from coprs import helpers 
 11  from coprs.logic.api_logic import BuildWrapper, MonitorWrapper 
 12   
 13  from coprs.views.misc import login_required, api_login_required 
 14   
 15  from coprs.views.api_ns import api_ns 
 16   
 17  from coprs.logic import builds_logic 
 18  from coprs.logic import coprs_logic 
19 20 21 @api_ns.route("/") 22 -def api_home():
23 """ 24 Render the home page of the api. 25 This page provides information on how to call/use the API. 26 """ 27 28 return flask.render_template("api.html")
29
30 31 @api_ns.route("/new/", methods=["GET", "POST"]) 32 @login_required 33 -def api_new_token():
34 """ 35 Generate a new API token for the current user. 36 """ 37 38 user = flask.g.user 39 copr64 = base64.b64encode("copr") + "##" 40 api_login = helpers.generate_api_token( 41 flask.current_app.config["API_TOKEN_LENGTH"] - len(copr64)) 42 user.api_login = api_login 43 user.api_token = helpers.generate_api_token( 44 flask.current_app.config["API_TOKEN_LENGTH"]) 45 user.api_token_expiration = datetime.date.today() + \ 46 datetime.timedelta( 47 days=flask.current_app.config["API_TOKEN_EXPIRATION"]) 48 49 db.session.add(user) 50 db.session.commit() 51 return flask.redirect(flask.url_for("api_ns.api_home"))
52
53 54 @api_ns.route("/coprs/<username>/new/", methods=["POST"]) 55 @api_login_required 56 -def api_new_copr(username):
57 """ 58 Receive information from the user on how to create its new copr, 59 check their validity and create the corresponding copr. 60 61 :arg name: the name of the copr to add 62 :arg chroots: a comma separated list of chroots to use 63 :kwarg repos: a comma separated list of repository that this copr 64 can use. 65 :kwarg initial_pkgs: a comma separated list of initial packages to 66 build in this new copr 67 68 """ 69 70 form = forms.CoprFormFactory.create_form_cls()(csrf_enabled=False) 71 httpcode = 200 72 73 # are there any arguments in POST which our form doesn't know? 74 if sum([1 for post_key in flask.request.form.keys() \ 75 if post_key not in form.__dict__.keys()]): 76 output = {"output": "notok", "error": 77 "Unknown arguments passed (non-existing chroot probably)"} 78 httpcode = 500 79 80 elif form.validate_on_submit(): 81 infos = [] 82 try: 83 copr = coprs_logic.CoprsLogic.add( 84 name=form.name.data.strip(), 85 repos=" ".join(form.repos.data.split()), 86 user=flask.g.user, 87 selected_chroots=form.selected_chroots, 88 description=form.description.data, 89 instructions=form.instructions.data, 90 check_for_duplicates=True) 91 infos.append("New project was successfully created.") 92 93 if form.initial_pkgs.data: 94 pkgs = form.initial_pkgs.data.split() 95 for pkg in pkgs: 96 builds_logic.BuildsLogic.add( 97 user=flask.g.user, 98 pkgs=pkg, 99 copr=copr) 100 101 infos.append("Initial packages were successfully " 102 "submitted for building.") 103 104 output = {"output": "ok", "message": "\n".join(infos)} 105 db.session.commit() 106 except exceptions.DuplicateException as err: 107 output = {"output": "notok", "error": err} 108 httpcode = 500 109 db.session.rollback() 110 111 else: 112 errormsg = "Validation error\n" 113 if form.errors: 114 for field, emsgs in form.errors.items(): 115 errormsg += "- {0}: {1}\n".format(field, "\n".join(emsgs)) 116 117 errormsg = errormsg.replace('"', "'") 118 output = {"output": "notok", "error": errormsg} 119 httpcode = 500 120 121 jsonout = flask.jsonify(output) 122 jsonout.status_code = httpcode 123 return jsonout
124
125 126 @api_ns.route("/coprs/<username>/<coprname>/delete/", methods=["POST"]) 127 @api_login_required 128 -def api_copr_delete(username, coprname):
129 """ Deletes selected user's project 130 """ 131 form = forms.CoprDeleteForm(csrf_enabled=False) 132 copr = coprs_logic.CoprsLogic.get(flask.g.user, username, coprname).first() 133 httpcode = 200 134 135 if form.validate_on_submit() and copr: 136 builds_query = builds_logic.BuildsLogic.get_multiple( 137 flask.g.user, copr=copr) 138 try: 139 for build in builds_query: 140 builds_logic.BuildsLogic.delete_build(flask.g.user, build) 141 coprs_logic.CoprsLogic.delete(flask.g.user, copr) 142 except (exceptions.ActionInProgressException, 143 exceptions.InsufficientRightsException) as err: 144 output = {"output": "notok", "error": err} 145 httpcode = 500 146 db.session.rollback() 147 else: 148 message = "Project {0} has been deleted.".format(coprname) 149 output = {"output": "ok", "message": message} 150 db.session.commit() 151 else: 152 output = {"output": "notok", "error": "Invalid request"} 153 httpcode = 500 154 155 jsonout = flask.jsonify(output) 156 jsonout.status_code = httpcode 157 return jsonout
158
159 160 @api_ns.route("/coprs/") 161 @api_ns.route("/coprs/<username>/") 162 -def api_coprs_by_owner(username=None):
163 """ Return the list of coprs owned by the given user. 164 username is taken either from GET params or from the URL itself 165 (in this order). 166 167 :arg username: the username of the person one would like to the 168 coprs of. 169 170 """ 171 username = flask.request.args.get("username", None) or username 172 release_tmpl = "{chroot.os_release}-{chroot.os_version}-{chroot.arch}" 173 httpcode = 200 174 if username: 175 query = coprs_logic.CoprsLogic.get_multiple( 176 flask.g.user, user_relation="owned", 177 username=username, with_builds=True) 178 179 repos = query.all() 180 output = {"output": "ok", "repos": []} 181 for repo in repos: 182 yum_repos = {} 183 for build in repo.builds: 184 if build.results: 185 for chroot in repo.active_chroots: 186 release = release_tmpl.format(chroot=chroot) 187 yum_repos[release] = urlparse.urljoin( 188 build.results, release + '/') 189 break 190 191 output["repos"].append({"name": repo.name, 192 "additional_repos": repo.repos, 193 "yum_repos": yum_repos, 194 "description": repo.description, 195 "instructions": repo.instructions}) 196 else: 197 output = {"output": "notok", "error": "Invalid request"} 198 httpcode = 500 199 200 jsonout = flask.jsonify(output) 201 jsonout.status_code = httpcode 202 return jsonout
203
204 @api_ns.route("/coprs/<username>/<coprname>/detail/") 205 -def api_coprs_by_owner_detail(username, coprname):
206 """ Return detail of one project. 207 208 :arg username: the username of the person one would like to the 209 coprs of. 210 :arg coprname: the name of project. 211 212 """ 213 copr = coprs_logic.CoprsLogic.get(flask.g.user, username, 214 coprname).first() 215 release_tmpl = "{chroot.os_release}-{chroot.os_version}-{chroot.arch}" 216 httpcode = 200 217 if username and copr: 218 output = {"output": "ok", "detail": {}} 219 yum_repos = {} 220 for build in copr.builds: 221 if build.results: 222 for chroot in copr.active_chroots: 223 release = release_tmpl.format(chroot=chroot) 224 yum_repos[release] = urlparse.urljoin( 225 build.results, release + '/') 226 break 227 output["detail"] = {"name": copr.name, 228 "additional_repos": copr.repos, 229 "yum_repos": yum_repos, 230 "description": copr.description, 231 "instructions": copr.instructions, 232 "last_modified": builds_logic.BuildsLogic.last_modified(copr)} 233 else: 234 output = {"output": "notok", "error": "Copr with name {0} does not exist.".format(coprname)} 235 httpcode = 500 236 237 jsonout = flask.jsonify(output) 238 jsonout.status_code = httpcode 239 return jsonout
240
241 @api_ns.route("/coprs/<username>/<coprname>/new_build/", methods=["POST"]) 242 @api_login_required 243 -def copr_new_build(username, coprname):
244 copr = coprs_logic.CoprsLogic.get(flask.g.user, username, 245 coprname).first() 246 httpcode = 200 247 if not copr: 248 output = {"output": "notok", "error": 249 "Copr with name {0} does not exist.".format(coprname)} 250 httpcode = 500 251 252 else: 253 form = forms.BuildFormFactory.create_form_cls( 254 copr.active_chroots)(csrf_enabled=False) 255 256 # are there any arguments in POST which our form doesn't know? 257 if sum([1 for post_key in flask.request.form.keys() \ 258 if post_key not in form.__dict__.keys()]): 259 output = {"output": "notok", "error": 260 "Unknown arguments passed (non-existing chroot probably)"} 261 httpcode = 500 262 263 elif form.validate_on_submit() and flask.g.user.can_build_in(copr): 264 # we're checking authorization above for now 265 # and also creating separate build for each package 266 pkgs = form.pkgs.data.replace('\n', ' ').split(" ") 267 ids = [] 268 chroots = [] 269 for chroot in copr.active_chroots: 270 if chroot.name in form.selected_chroots: 271 chroots.append(chroot) 272 273 for pkg in pkgs: 274 build = builds_logic.BuildsLogic.add( 275 user=flask.g.user, 276 pkgs=pkg, 277 copr=copr, 278 chroots=chroots) 279 280 if flask.g.user.proven: 281 build.memory_reqs = form.memory_reqs.data 282 build.timeout = form.timeout.data 283 284 db.session.commit() 285 ids.append(build.id) 286 287 288 output = {"output": "ok", 289 "ids": ids, 290 "message": "Build was added to {0}.".format(coprname)} 291 else: 292 output = {"output": "notok", "error": "Invalid request"} 293 httpcode = 500 294 295 jsonout = flask.jsonify(output) 296 jsonout.status_code = httpcode 297 return jsonout
298
299 300 @api_ns.route("/coprs/build_status/<build_id>/", methods=["GET"]) 301 @api_login_required 302 -def build_status(build_id):
303 if build_id.isdigit(): 304 build = builds_logic.BuildsLogic.get(build_id).first() 305 else: 306 build = None 307 308 if build: 309 httpcode = 200 310 output = {"output": "ok", 311 "status": build.state} 312 else: 313 output = {"output": "notok", "error": "Invalid build"} 314 httpcode = 404 315 316 jsonout = flask.jsonify(output) 317 jsonout.status_code = httpcode 318 return jsonout
319
320 @api_ns.route("/coprs/build_detail/<build_id>/", methods=["GET"]) 321 @api_ns.route("/coprs/build/<build_id>/", methods=["GET"]) 322 -def build_detail(build_id):
323 if build_id.isdigit(): 324 build = builds_logic.BuildsLogic.get(build_id).first() 325 else: 326 build = None 327 328 if build: 329 httpcode = 200 330 chroots = {} 331 for chroot in build.build_chroots: 332 chroots[chroot.name] = chroot.state 333 334 built_packages = None 335 if build.built_packages: 336 built_packages = build.built_packages.split("\n") 337 338 output = {"output": "ok", 339 "status": build.state, 340 "project": build.copr.name, 341 "owner": build.copr.owner.name, 342 "results": build.results, 343 "built_pkgs": built_packages, 344 "src_version": build.pkg_version, 345 "chroots": chroots, 346 "submitted_on": build.submitted_on, 347 "started_on": build.started_on, 348 "ended_on": build.ended_on, 349 "src_pkg": build.pkgs, 350 "submitted_by": build.user.name} 351 else: 352 output = {"output": "notok", "error": "Invalid build"} 353 httpcode = 404 354 355 jsonout = flask.jsonify(output) 356 jsonout.status_code = httpcode 357 return jsonout
358
359 @api_ns.route("/coprs/cancel_build/<build_id>/", methods=["POST"]) 360 @api_login_required 361 -def cancel_build(build_id):
362 if build_id.isdigit(): 363 build = builds_logic.BuildsLogic.get(build_id).first() 364 else: 365 build = None 366 367 if build: 368 try: 369 builds_logic.BuildsLogic.cancel_build(flask.g.user, build) 370 except exceptions.InsufficientRightsException as e: 371 output = {'output': 'notok', 'error': str(e)} 372 httpcode = 500 373 else: 374 db.session.commit() 375 httpcode = 200 376 output = {'output': 'ok', 'status': "Build canceled"} 377 else: 378 output = {"output": "notok", "error": "Invalid build"} 379 httpcode = 404 380 jsonout = flask.jsonify(output) 381 jsonout.status_code = httpcode 382 return jsonout
383
384 @api_ns.route('/coprs/<username>/<coprname>/modify/', methods=["POST"]) 385 @api_login_required 386 -def copr_modify(username, coprname):
387 form = forms.CoprModifyForm(csrf_enabled=False) 388 copr = coprs_logic.CoprsLogic.get(flask.g.user, username, coprname).first() 389 390 if copr is None: 391 output = {'output': 'notok', 'error': 'Invalid copr name or username'} 392 httpcode = 500 393 elif not form.validate_on_submit(): 394 output = {'output': 'notok', 'error': 'Invalid request'} 395 httpcode = 500 396 else: 397 # .raw_data needs to be inspected to figure out whether the field 398 # was not sent or was sent empty 399 if form.description.raw_data and len(form.description.raw_data): 400 copr.description = form.description.data 401 if form.instructions.raw_data and len(form.instructions.raw_data): 402 copr.instructions = form.instructions.data 403 if form.repos.raw_data and len(form.repos.raw_data): 404 copr.repos = form.repos.data 405 406 try: 407 coprs_logic.CoprsLogic.update(flask.g.user, copr) 408 except (exceptions.ActionInProgressException, exceptions.InsufficientRightsException) as e: 409 db.session.rollback() 410 411 output = {'output': 'notok', 'error': str(e)} 412 httpcode = 500 413 else: 414 db.session.commit() 415 416 output = {'output': 'ok', 417 'description': copr.description, 418 'instructions': copr.instructions, 419 'repos': copr.repos} 420 httpcode = 200 421 422 jsonout = flask.jsonify(output) 423 jsonout.status_code = httpcode 424 return jsonout
425
426 @api_ns.route('/coprs/<username>/<coprname>/modify/<chrootname>/', methods=["POST"]) 427 @api_login_required 428 -def copr_modify_chroot(username, coprname, chrootname):
429 form = forms.ModifyChrootForm(csrf_enabled=False) 430 copr = coprs_logic.CoprsLogic.get(flask.g.user, username, coprname).first() 431 chroot = coprs_logic.MockChrootsLogic.get_from_name(chrootname, active_only=True).first() 432 433 if copr is None: 434 output = {'output': 'notok', 'error': 'Invalid copr name or username'} 435 httpcode = 500 436 elif chroot is None: 437 output = {'output': 'notok', 'error': 'Invalid chroot name'} 438 httpcode = 500 439 elif not form.validate_on_submit(): 440 output = {'output': 'notok', 'error': 'Invalid request'} 441 httpcode = 500 442 else: 443 coprs_logic.CoprChrootsLogic.update_buildroot_pkgs(copr, chroot, form.buildroot_pkgs.data) 444 db.session.commit() 445 446 ch = copr.check_copr_chroot(chroot) 447 output = {'output': 'ok', 'buildroot_pkgs': ch.buildroot_pkgs} 448 httpcode = 200 449 450 jsonout = flask.jsonify(output) 451 jsonout.status_code = httpcode 452 return jsonout
453
454 @api_ns.route('/coprs/<username>/<coprname>/detail/<chrootname>/', methods=["GET"]) 455 -def copr_chroot_details(username, coprname, chrootname):
456 copr = coprs_logic.CoprsLogic.get(flask.g.user, username, coprname).first() 457 chroot = coprs_logic.MockChrootsLogic.get_from_name(chrootname, active_only=True).first() 458 459 if copr is None: 460 output = {'output': 'notok', 'error': 'Invalid copr name or username'} 461 httpcode = 500 462 elif chroot is None: 463 output = {'output': 'notok', 'error': 'Invalid chroot name'} 464 httpcode = 500 465 else: 466 ch = copr.check_copr_chroot(chroot) 467 if ch: 468 output = {'output': 'ok', 'buildroot_pkgs': ch.buildroot_pkgs} 469 httpcode = 200 470 else: 471 output = {"output": "notok", "error": "Invalid chroot for this project."} 472 httpcode = 404 473 474 475 jsonout = flask.jsonify(output) 476 jsonout.status_code = httpcode 477 return jsonout
478
479 @api_ns.route("/coprs/search/") 480 @api_ns.route("/coprs/search/<project>/") 481 -def api_coprs_search_by_project(project=None):
482 """ Return the list of coprs found in search by the given text. 483 project is taken either from GET params or from the URL itself 484 (in this order). 485 486 :arg project: the text one would like find for coprs. 487 488 """ 489 project = flask.request.args.get("project", None) or project 490 httpcode = 200 491 if project: 492 try: 493 query = coprs_logic.CoprsLogic.get_multiple_fulltext( 494 flask.g.user, project) 495 496 repos = query.all() 497 output = {"output": "ok", "repos": []} 498 for repo in repos: 499 output["repos"].append({"username": repo.owner.name, 500 "coprname": repo.name, 501 "description": repo.description}) 502 except ValueError as e: 503 output = {"output": "nook", "error": str(e)} 504 505 else: 506 output = {"output": "notok", "error": "Invalid request"} 507 httpcode = 500 508 509 jsonout = flask.jsonify(output) 510 jsonout.status_code = httpcode 511 return jsonout
512
513 @api_ns.route("/playground/list/") 514 -def playground_list():
515 """ Return list of coprs which are part of playground """ 516 query = coprs_logic.CoprsLogic.get_playground() 517 repos = query.all() 518 output = {"output": "ok", "repos": []} 519 for repo in repos: 520 output["repos"].append({"username": repo.owner.name, 521 "coprname": repo.name, 522 "chroots": [chroot.name for chroot in repo.active_chroots]}) 523 524 jsonout = flask.jsonify(output) 525 jsonout.status_code = 200 526 return jsonout
527
528 @api_ns.route("/coprs/<username>/<coprname>/monitor/", methods=["GET"]) 529 -def monitor(username, coprname):
530 copr = coprs_logic.CoprsLogic.get( 531 flask.g.user, username, coprname).first() 532 533 monitor_data = builds_logic.BuildsMonitorLogic.get_monitor_data(copr) 534 output = MonitorWrapper(monitor_data).to_dict() 535 536 #output["href"] = flask.url_for(".monitor", 537 # username=username, coprname=coprname) 538 539 jsonout = flask.jsonify(output) 540 jsonout.status_code = 200 541 return jsonout
542