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():
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
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):
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
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
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
265
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):
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
398
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):
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
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
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):
542