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
12 from coprs.views.misc import login_required, api_login_required
13
14 from coprs.views.api_ns import api_ns
15
16 from coprs.logic import builds_logic
17 from coprs.logic import coprs_logic
18
19
20 @api_ns.route("/")
21 -def api_home():
22 """
23 Render the home page of the api.
24 This page provides information on how to call/use the API.
25 """
26
27 return flask.render_template("api.html")
28
29
30 @api_ns.route("/new/", methods=["GET", "POST"])
31 @login_required
32 -def api_new_token():
51
52
53 @api_ns.route("/coprs/<username>/new/", methods=["POST"])
54 @api_login_required
55 -def api_new_copr(username):
56 """
57 Receive information from the user on how to create its new copr,
58 check their validity and create the corresponding copr.
59
60 :arg name: the name of the copr to add
61 :arg chroots: a comma separated list of chroots to use
62 :kwarg repos: a comma separated list of repository that this copr
63 can use.
64 :kwarg initial_pkgs: a comma separated list of initial packages to
65 build in this new copr
66
67 """
68
69 form = forms.CoprFormFactory.create_form_cls()(csrf_enabled=False)
70 httpcode = 200
71
72
73 if sum([1 for post_key in flask.request.form.keys() \
74 if post_key not in form.__dict__.keys()]):
75 output = {"output": "notok", "error":
76 "Unknown arguments passed (non-existing chroot probably)"}
77 httpcode = 500
78
79 elif form.validate_on_submit():
80 infos = []
81 try:
82 copr = coprs_logic.CoprsLogic.add(
83 name=form.name.data.strip(),
84 repos=" ".join(form.repos.data.split()),
85 user=flask.g.user,
86 selected_chroots=form.selected_chroots,
87 description=form.description.data,
88 instructions=form.instructions.data,
89 check_for_duplicates=True)
90 infos.append("New project was successfully created.")
91
92 if form.initial_pkgs.data:
93 pkgs = form.initial_pkgs.data.split()
94 for pkg in pkgs:
95 builds_logic.BuildsLogic.add(
96 user=flask.g.user,
97 pkgs=pkg,
98 copr=copr)
99
100 infos.append("Initial packages were successfully "
101 "submitted for building.")
102
103 output = {"output": "ok", "message": "\n".join(infos)}
104 db.session.commit()
105 except exceptions.DuplicateException as err:
106 output = {"output": "notok", "error": err}
107 httpcode = 500
108 db.session.rollback()
109
110 else:
111 errormsg = "Validation error\n"
112 if form.errors:
113 for field, emsgs in form.errors.items():
114 errormsg += "- {0}: {1}\n".format(field, "\n".join(emsgs))
115
116 errormsg = errormsg.replace('"', "'")
117 output = {"output": "notok", "error": errormsg}
118 httpcode = 500
119
120 jsonout = flask.jsonify(output)
121 jsonout.status_code = httpcode
122 return jsonout
123
124
125 @api_ns.route("/coprs/<username>/<coprname>/delete/", methods=["POST"])
126 @api_login_required
127 -def api_copr_delete(username, coprname):
157
158
159 @api_ns.route("/coprs/")
160 @api_ns.route("/coprs/<username>/")
161 -def api_coprs_by_owner(username=None):
162 """ Return the list of coprs owned by the given user.
163 username is taken either from GET params or from the URL itself
164 (in this order).
165
166 :arg username: the username of the person one would like to the
167 coprs of.
168
169 """
170 username = flask.request.args.get("username", None) or username
171 release_tmpl = "{chroot.os_release}-{chroot.os_version}-{chroot.arch}"
172 httpcode = 200
173 if username:
174 query = coprs_logic.CoprsLogic.get_multiple(
175 flask.g.user, user_relation="owned",
176 username=username, with_builds=True)
177
178 repos = query.all()
179 output = {"output": "ok", "repos": []}
180 for repo in repos:
181 yum_repos = {}
182 for build in repo.builds:
183 if build.results:
184 for chroot in repo.active_chroots:
185 release = release_tmpl.format(chroot=chroot)
186 yum_repos[release] = urlparse.urljoin(
187 build.results, release + '/')
188 break
189
190 output["repos"].append({"name": repo.name,
191 "additional_repos": repo.repos,
192 "yum_repos": yum_repos,
193 "description": repo.description,
194 "instructions": repo.instructions})
195 else:
196 output = {"output": "notok", "error": "Invalid request"}
197 httpcode = 500
198
199 jsonout = flask.jsonify(output)
200 jsonout.status_code = httpcode
201 return jsonout
202
205 """ Return detail of one project.
206
207 :arg username: the username of the person one would like to the
208 coprs of.
209 :arg coprname: the name of project.
210
211 """
212 copr = coprs_logic.CoprsLogic.get(flask.g.user, username,
213 coprname).first()
214 release_tmpl = "{chroot.os_release}-{chroot.os_version}-{chroot.arch}"
215 httpcode = 200
216 if username and copr:
217 output = {"output": "ok", "detail": {}}
218 yum_repos = {}
219 for build in copr.builds:
220 if build.results:
221 for chroot in copr.active_chroots:
222 release = release_tmpl.format(chroot=chroot)
223 yum_repos[release] = urlparse.urljoin(
224 build.results, release + '/')
225 break
226 output["detail"] = {"name": copr.name,
227 "additional_repos": copr.repos,
228 "yum_repos": yum_repos,
229 "description": copr.description,
230 "instructions": copr.instructions,
231 "last_modified": builds_logic.BuildsLogic.last_modified(copr)}
232 else:
233 output = {"output": "notok", "error": "Copr with name {0} does not exist.".format(coprname)}
234 httpcode = 500
235
236 jsonout = flask.jsonify(output)
237 jsonout.status_code = httpcode
238 return jsonout
239
240 @api_ns.route("/coprs/<username>/<coprname>/new_build/", methods=["POST"])
241 @api_login_required
242 -def copr_new_build(username, coprname):
243 copr = coprs_logic.CoprsLogic.get(flask.g.user, username,
244 coprname).first()
245 httpcode = 200
246 if not copr:
247 output = {"output": "notok", "error":
248 "Copr with name {0} does not exist.".format(coprname)}
249 httpcode = 500
250
251 else:
252 form = forms.BuildFormFactory.create_form_cls(
253 copr.active_chroots)(csrf_enabled=False)
254
255
256 if sum([1 for post_key in flask.request.form.keys() \
257 if post_key not in form.__dict__.keys()]):
258 output = {"output": "notok", "error":
259 "Unknown arguments passed (non-existing chroot probably)"}
260 httpcode = 500
261
262 elif form.validate_on_submit() and flask.g.user.can_build_in(copr):
263
264
265 pkgs = form.pkgs.data.replace('\n', ' ').split(" ")
266 ids = []
267 chroots = []
268 for chroot in copr.active_chroots:
269 if chroot.name in form.selected_chroots:
270 chroots.append(chroot)
271
272 for pkg in pkgs:
273 build = builds_logic.BuildsLogic.add(
274 user=flask.g.user,
275 pkgs=pkg,
276 copr=copr,
277 chroots=chroots)
278
279 if flask.g.user.proven:
280 build.memory_reqs = form.memory_reqs.data
281 build.timeout = form.timeout.data
282
283 db.session.commit()
284 ids.append(build.id)
285
286
287 output = {"output": "ok",
288 "ids": ids,
289 "message": "Build was added to {0}.".format(coprname)}
290 else:
291 output = {"output": "notok", "error": "Invalid request"}
292 httpcode = 500
293
294 jsonout = flask.jsonify(output)
295 jsonout.status_code = httpcode
296 return jsonout
297
298
299 @api_ns.route("/coprs/build_status/<build_id>/", methods=["GET"])
300 @api_login_required
301 -def build_status(build_id):
302 if build_id.isdigit():
303 build = builds_logic.BuildsLogic.get(build_id).first()
304 else:
305 build = None
306
307 if build:
308 httpcode = 200
309 output = {"output": "ok",
310 "status": build.state}
311 else:
312 output = {"output": "notok", "error": "Invalid build"}
313 httpcode = 404
314
315 jsonout = flask.jsonify(output)
316 jsonout.status_code = httpcode
317 return jsonout
318
319 @api_ns.route("/coprs/build_detail/<build_id>/", methods=["GET"])
320 @api_ns.route("/coprs/build/<build_id>/", methods=["GET"])
321 -def build_detail(build_id):
322 if build_id.isdigit():
323 build = builds_logic.BuildsLogic.get(build_id).first()
324 else:
325 build = None
326
327 if build:
328 httpcode = 200
329 chroots = {}
330 for chroot in build.build_chroots:
331 chroots[chroot.name] = chroot.state
332
333 built_packages = None
334 if build.built_packages:
335 built_packages = build.built_packages.split("\n")
336
337 output = {"output": "ok",
338 "status": build.state,
339 "project": build.copr.name,
340 "owner": build.copr.owner.name,
341 "results": build.results,
342 "built_pkgs": built_packages,
343 "src_version": build.pkg_version,
344 "chroots": chroots,
345 "submitted_on": build.submitted_on,
346 "started_on": build.started_on,
347 "ended_on": build.ended_on,
348 "src_pkg": build.pkgs,
349 "submitted_by": build.user.name}
350 else:
351 output = {"output": "notok", "error": "Invalid build"}
352 httpcode = 404
353
354 jsonout = flask.jsonify(output)
355 jsonout.status_code = httpcode
356 return jsonout
357
358 @api_ns.route("/coprs/cancel_build/<build_id>/", methods=["POST"])
359 @api_login_required
360 -def cancel_build(build_id):
382
383 @api_ns.route('/coprs/<username>/<coprname>/modify/', methods=["POST"])
384 @api_login_required
385 -def copr_modify(username, coprname):
386 form = forms.CoprModifyForm(csrf_enabled=False)
387 copr = coprs_logic.CoprsLogic.get(flask.g.user, username, coprname).first()
388
389 if copr is None:
390 output = {'output': 'notok', 'error': 'Invalid copr name or username'}
391 httpcode = 500
392 elif not form.validate_on_submit():
393 output = {'output': 'notok', 'error': 'Invalid request'}
394 httpcode = 500
395 else:
396
397
398 if form.description.raw_data and len(form.description.raw_data):
399 copr.description = form.description.data
400 if form.instructions.raw_data and len(form.instructions.raw_data):
401 copr.instructions = form.instructions.data
402 if form.repos.raw_data and len(form.repos.raw_data):
403 copr.repos = form.repos.data
404
405 try:
406 coprs_logic.CoprsLogic.update(flask.g.user, copr)
407 except (exceptions.ActionInProgressException, exceptions.InsufficientRightsException) as e:
408 db.session.rollback()
409
410 output = {'output': 'notok', 'error': str(e)}
411 httpcode = 500
412 else:
413 db.session.commit()
414
415 output = {'output': 'ok',
416 'description': copr.description,
417 'instructions': copr.instructions,
418 'repos': copr.repos}
419 httpcode = 200
420
421 jsonout = flask.jsonify(output)
422 jsonout.status_code = httpcode
423 return jsonout
424
425 @api_ns.route('/coprs/<username>/<coprname>/modify/<chrootname>/', methods=["POST"])
426 @api_login_required
427 -def copr_modify_chroot(username, coprname, chrootname):
452
453 @api_ns.route('/coprs/<username>/<coprname>/detail/<chrootname>/', methods=["GET"])
454 -def copr_chroot_details(username, coprname, chrootname):
455 copr = coprs_logic.CoprsLogic.get(flask.g.user, username, coprname).first()
456 chroot = coprs_logic.MockChrootsLogic.get_from_name(chrootname, active_only=True).first()
457
458 if copr is None:
459 output = {'output': 'notok', 'error': 'Invalid copr name or username'}
460 httpcode = 500
461 elif chroot is None:
462 output = {'output': 'notok', 'error': 'Invalid chroot name'}
463 httpcode = 500
464 else:
465 ch = copr.check_copr_chroot(chroot)
466 if ch:
467 output = {'output': 'ok', 'buildroot_pkgs': ch.buildroot_pkgs}
468 httpcode = 200
469 else:
470 output = {"output": "notok", "error": "Invalid chroot for this project."}
471 httpcode = 404
472
473
474 jsonout = flask.jsonify(output)
475 jsonout.status_code = httpcode
476 return jsonout
477
481 """ Return the list of coprs found in search by the given text.
482 project is taken either from GET params or from the URL itself
483 (in this order).
484
485 :arg project: the text one would like find for coprs.
486
487 """
488 project = flask.request.args.get("project", None) or project
489 httpcode = 200
490 if project:
491 try:
492 query = coprs_logic.CoprsLogic.get_multiple_fulltext(
493 flask.g.user, project)
494
495 repos = query.all()
496 output = {"output": "ok", "repos": []}
497 for repo in repos:
498 output["repos"].append({"username": repo.owner.name,
499 "coprname": repo.name,
500 "description": repo.description})
501 except ValueError as e:
502 output = {"output": "nook", "error": str(e)}
503
504 else:
505 output = {"output": "notok", "error": "Invalid request"}
506 httpcode = 500
507
508 jsonout = flask.jsonify(output)
509 jsonout.status_code = httpcode
510 return jsonout
511
514 """ Return list of coprs which are part of playground """
515 query = coprs_logic.CoprsLogic.get_playground()
516 repos = query.all()
517 output = {"output": "ok", "repos": []}
518 for repo in repos:
519 output["repos"].append({"username": repo.owner.name,
520 "coprname": repo.name,
521 "chroots": [chroot.name for chroot in repo.active_chroots]})
522
523 jsonout = flask.jsonify(output)
524 jsonout.status_code = 200
525 return jsonout
526