def test_delete_expired_coprs(self, f_users, f_mock_chroots, f_coprs, f_builds, f_db): query = self.db.session.query(models.Copr) # nothing is deleted at the beginning assert len([c for c in query.all() if c.deleted]) == 0 # one is to be deleted in the future self.c1.delete_after_days = 2 # one is already to be deleted self.c2.delete_after = datetime.datetime.now() - datetime.timedelta( days=1) # and one is not to be temporary at all (c3) ComplexLogic.delete_expired_projects() self.db.session.commit() query = self.db.session.query(models.Copr) assert len(query.all()) == 3 # we only set deleted=true # some builds are not finished, nothing deleted yet assert len([c for c in query.all() if c.deleted]) == 0 b = self.db.session.query(models.Build).get(3) b.canceled = True ComplexLogic.delete_expired_projects() self.db.session.commit() # some builds are not finished, nothing deleted yet assert len([c for c in query.all() if c.deleted]) == 1 # test that build is deleted as well assert not self.db.session.query(models.Build).get(3)
def clean_expired_projects(): """ Clean all the expired temporary projects. This command is meant to be executed by cron. """ with db_session_scope(): ComplexLogic.delete_expired_projects()
def wrapper(username, coprname, **kwargs): if username.startswith("@"): group_name = username[1:] copr = ComplexLogic.get_group_copr_safe(group_name, coprname) else: copr = ComplexLogic.get_copr_safe(username, coprname) return f(copr, **kwargs)
def wrapper(**kwargs): coprname = kwargs.pop("coprname") if "group_name" in kwargs: group_name = kwargs.pop("group_name") copr = ComplexLogic.get_group_copr_safe(group_name, coprname, with_mock_chroots=True) else: username = kwargs.pop("username") copr = ComplexLogic.get_copr_safe(username, coprname, with_mock_chroots=True) return f(copr, **kwargs)
def list_projects_by_group(group_name, page=1): group = ComplexLogic.get_group_by_name_safe(group_name) query = CoprsLogic.get_multiple_by_group_id(group.id) paginator = Paginator(query, query.count(), page) coprs = paginator.sliced_query return render_template("coprs/show/group.html", user=flask.g.user, coprs=coprs, paginator=paginator, tasks_info=ComplexLogic.get_queues_size(), group=group)
def test_delete_project_that_is_pinned(self, f_users, f_coprs, f_db): pc1 = models.PinnedCoprs(id=1, copr_id=self.c2.id, user_id=self.u2.id, position=1) pc2 = models.PinnedCoprs(id=2, copr_id=self.c3.id, user_id=self.u2.id, position=2) self.db.session.add_all([pc1, pc2]) ComplexLogic.delete_copr(self.c2, admin_action=True) assert set(CoprsLogic.get_multiple_by_username( self.u2.name)) == {self.c3} assert set(PinnedCoprsLogic.get_by_owner(self.u2)) == {pc2}
def get_build_config(ownername, projectname, chrootname): copr = get_copr(ownername, projectname) chroot = ComplexLogic.get_copr_chroot_safe(copr, chrootname) if not chroot: raise ObjectNotFound('Chroot not found.') config = to_build_config_dict(chroot) return flask.jsonify(config)
def process_copr_repeat_build(build_id, copr): build = ComplexLogic.get_build_safe(build_id) if not flask.g.user.can_build_in(build.copr): flask.flash("You are not allowed to repeat this build.") form = forms.BuildFormRebuildFactory.create_form_cls(build.chroots)( build_id=build_id, enable_net=build.enable_net, ) # remove all checkboxes by default for ch in build.chroots: field = getattr(form, ch.name) field.data = False chroot_to_build = request.args.get("chroot") app.logger.debug("got param chroot: {}".format(chroot_to_build)) if chroot_to_build: # set single checkbox if chroot query arg was provided if hasattr(form, chroot_to_build): getattr(form, chroot_to_build).data = True else: # set checkbox on the failed chroots chroots_to_select = set(ch.name for ch in build.get_chroots_by_status([ helpers.StatusEnum('failed'), helpers.StatusEnum('canceled'), ])) for ch in build.chroots: if ch.name in chroots_to_select: getattr(form, ch.name).data = True return flask.render_template("coprs/detail/add_build/rebuild.html", copr=copr, build=build, form=form)
def delete_project(ownername, projectname): copr = get_copr(ownername, projectname) copr_dict = to_dict(copr) form = forms.APICoprDeleteForm(meta={'csrf': False}) if form.validate_on_submit() and copr: try: ComplexLogic.delete_copr(copr) except (ActionInProgressException, InsufficientRightsException) as err: db.session.rollback() raise err else: db.session.commit() else: raise BadRequest(form.errors) return flask.jsonify(copr_dict)
def copr_fork_post(copr): form = forms.CoprForkFormFactory.create_form_cls( copr=copr, user=flask.g.user, groups=flask.g.user.user_groups)() if form.validate_on_submit(): dstgroup = ([ g for g in flask.g.user.user_groups if g.at_name == form.owner.data ] or [None])[0] if flask.g.user.name != form.owner.data and not dstgroup: return generic_error("There is no such group: {}".format( form.owner.data)) fcopr, created = ComplexLogic.fork_copr(copr, flask.g.user, dstname=form.name.data, dstgroup=dstgroup) if created: msg = ( "Forking project {} for you into {}. Please be aware that it may take a few minutes " "to duplicate a backend data.".format(copr.full_name, fcopr.full_name)) elif not created and form.confirm.data == True: msg = ( "Updating packages in {} from {}. Please be aware that it may take a few minutes " "to duplicate a backend data.".format(copr.full_name, fcopr.full_name)) else: return render_copr_fork(copr, form, confirm=True) db.session.commit() flask.flash(msg) return flask.redirect(url_for_copr_details(fcopr)) return render_copr_fork(copr, form)
def group_copr_add(group_name): group = ComplexLogic.get_group_by_name_safe(group_name) form = forms.CoprFormFactory.create_form_cls()() return flask.render_template("coprs/group_add.html", form=form, group=group)
def group_copr_new(group_name): group = ComplexLogic.get_group_by_name_safe(group_name) form = forms.CoprFormFactory.create_form_cls(group=group)() if form.validate_on_submit(): try: copr = coprs_logic.CoprsLogic.add( flask.g.user, name=form.name.data, homepage=form.homepage.data, contact=form.contact.data, repos=form.repos.data.replace("\n", " "), selected_chroots=form.selected_chroots, description=form.description.data, instructions=form.instructions.data, disable_createrepo=form.disable_createrepo.data, build_enable_net=form.build_enable_net.data, unlisted_on_hp=form.unlisted_on_hp.data, group=group, persistent=form.persistent.data, ) except (exceptions.DuplicateException, exceptions.NonAdminCannotCreatePersistentProject) as e: flask.flash(str(e), "error") return flask.render_template("coprs/group_add.html", form=form, group=group) db.session.add(copr) db.session.commit() after_the_project_creation(copr, form) return flask.redirect(url_for_copr_details(copr)) else: return flask.render_template("coprs/group_add.html", form=form, group=group)
def coprs_by_user(username=None, page=1): user = users_logic.UsersLogic.get(username).first() if not user: return page_not_found("User {0} does not exist.".format(username)) pinned = [pin.copr for pin in PinnedCoprsLogic.get_by_user_id(user.id) ] if page == 1 else [] query = CoprsLogic.get_multiple_owned_by_username(username) query = CoprsLogic.filter_without_ids(query, [copr.id for copr in pinned]) query = CoprsLogic.filter_without_group_projects(query) query = CoprsLogic.set_query_order(query, desc=True) paginator = helpers.Paginator(query, query.count(), page) coprs = paginator.sliced_query # flask.g.user is none when no user is logged - showing builds from everyone users_builds = builds_logic.BuildsLogic.get_recent_tasks(flask.g.user, 4) data = builds_logic.BuildsLogic.get_small_graph_data('30min') return flask.render_template("coprs/show/user.html", user=user, coprs=coprs, pinned=pinned, paginator=paginator, tasks_info=ComplexLogic.get_queue_sizes(), users_builds=users_builds, graph=data)
def dist_git_upload_completed(): app.logger.debug(flask.request.json) build_id = flask.request.json.get("build_id") try: build = ComplexLogic.get_build_safe(build_id) except ObjectNotFound: return flask.jsonify({"updated": False}) collected_branch_chroots = [] for branch, git_hash in flask.request.json.get("branch_commits", {}).items(): branch_chroots = BuildsLogic.get_buildchroots_by_build_id_and_branch( build_id, branch) for ch in branch_chroots: ch.status = StatusEnum("pending") ch.git_hash = git_hash db.session.add(ch) collected_branch_chroots.append((ch.task_id)) final_source_status = StatusEnum("succeeded") for ch in build.build_chroots: if ch.task_id not in collected_branch_chroots: final_source_status = StatusEnum("failed") ch.status = StatusEnum("failed") db.session.add(ch) build.source_status = final_source_status db.session.add(build) db.session.commit() BuildsLogic.delete_local_source(build) return flask.jsonify({"updated": True})
def process_rebuild(copr, build_id, view, url_on_success): source_build = ComplexLogic.get_build_safe(build_id) form = forms.BuildFormRebuildFactory.create_form_cls(copr.active_chroots)() if form.validate_on_submit(): try: build_options = { "enable_net": form.enable_net.data, "timeout": form.timeout.data, } BuildsLogic.create_new_from_other_build( flask.g.user, copr, source_build, chroot_names=form.selected_chroots, **build_options) except (ActionInProgressException, InsufficientRightsException) as e: flask.flash(str(e), "error") db.session.rollback() else: flask.flash("New build has been created", "success") db.session.commit() return flask.redirect(url_on_success) else: return render_add_build(copr, form, view)
def copr_rebuild_package(copr, package_name): package = ComplexLogic.get_package_safe(copr.main_dir, package_name) data = package.source_json_dict if package.source_type_text == "scm": form = forms.BuildFormScmFactory f = render_add_build_scm view_suffix = "_scm" elif package.source_type_text == "pypi": form = forms.BuildFormPyPIFactory f = render_add_build_pypi view_suffix = "_pypi" elif package.source_type_text == "custom": form = forms.BuildFormCustomFactory f = render_add_build_custom view_suffix = "_custom" else: flask.flash( "Package {} has not the default source which is required for rebuild. Please configure some source" .format(package_name, copr.full_name)) return flask.redirect( helpers.copr_url("coprs_ns.copr_edit_package", copr, package_name=package_name)) form = form(copr.active_chroots, package)(data=data) return f(copr, form, view="coprs_ns.copr_new_build" + view_suffix, package=package)
def build_detail(build_id): build = ComplexLogic.get_build_safe(build_id) chroots = {} results_by_chroot = {} for chroot in build.build_chroots: chroots[chroot.name] = chroot.state results_by_chroot[chroot.name] = chroot.result_dir_url built_packages = None if build.built_packages: built_packages = build.built_packages.split("\n") output = { "output": "ok", "status": build.state, "project": build.copr.name, "owner": build.copr.user.name, "results": build.results, "built_pkgs": built_packages, "src_version": build.pkg_version, "chroots": chroots, "submitted_on": build.submitted_on, "started_on": build.min_started_on, "ended_on": build.max_ended_on, "src_pkg": build.pkgs, "submitted_by": build.user.name, "results_by_chroot": results_by_chroot } return flask.jsonify(output)
def group_copr_new(group_name): group = ComplexLogic.get_group_by_name_safe(group_name) form = forms.CoprFormFactory.create_form_cls(group=group)() if form.validate_on_submit(): copr = coprs_logic.CoprsLogic.add( flask.g.user, name=form.name.data, homepage=form.homepage.data, contact=form.contact.data, repos=form.repos.data.replace("\n", " "), selected_chroots=form.selected_chroots, description=form.description.data, instructions=form.instructions.data, disable_createrepo=form.disable_createrepo.data, build_enable_net=form.build_enable_net.data, group=group) db.session.add(copr) db.session.commit() after_the_project_creation(copr, form) return flask.redirect(url_for_copr_details(copr)) else: return flask.render_template("coprs/group_add.html", form=form, group=group)
def webhooks_hello(copr_id, uuid): # For the documentation of the data we receive see: # https://developer.github.com/v3/activity/events/types/#pushevent try: copr = ComplexLogic.get_copr_by_id_safe(copr_id) except ObjectNotFound: return page_not_found("Project does not exist") if copr.webhook_secret != uuid: return access_restricted("This webhook is not valid") try: request_json = flask.request.json clone_url = request_json["repository"]["clone_url"] except KeyError: return "Bad Request", 400 if "commits" in request_json: commits = request_json["commits"] else: commits = [] packages = PackagesLogic.get_for_webhook_rebuild(copr_id, uuid, clone_url, commits) for package in packages: BuildsLogic.rebuild_package(package) db.session.commit() return "OK", 200
def copr_rebuild_all_packages(copr): form = forms.RebuildAllPackagesFormFactory( copr.active_chroots, [package.name for package in copr.packages])() if flask.request.method == "POST" and form.validate_on_submit(): try: packages = [] for package_name in form.packages.data: packages.append( ComplexLogic.get_package_safe(copr.main_dir, package_name)) PackagesLogic.batch_build(flask.g.user, copr, packages, form.selected_chroots, enable_net=form.enable_net.data) except (ObjectNotFound, ActionInProgressException, NoPackageSourceException, \ InsufficientRightsException, MalformedArgumentException) as e: db.session.rollback() flask.flash(str(e), "error") else: db.session.commit() flask.flash("Batch build successfully started.", "success") return flask.redirect(helpers.url_for_copr_builds(copr)) return flask.render_template("coprs/detail/packages_rebuild_all.html", view="coprs_ns.copr_rebuild_all_packages", form=form, copr=copr)
def copr_edit_package(copr, package_name, source_type_text=None, **kwargs): package = ComplexLogic.get_package_safe(copr.main_dir, package_name) data = package.source_json_dict data["webhook_rebuild"] = package.webhook_rebuild data["chroot_blacklist"] = package.chroot_blacklist_raw data["max_builds"] = package.max_builds if package.has_source_type_set and not source_type_text: source_type_text = package.source_type_text elif not source_type_text: source_type_text = "scm" form_classes = { "scm": forms.PackageFormScm, "pypi": forms.PackageFormPyPI, "rubygems": forms.PackageFormRubyGems, "custom": forms.PackageFormCustom, } form = {k: v(formdata=None) for k, v in form_classes.items()} if "form" in kwargs: form[source_type_text] = kwargs["form"] elif package.has_source_type_set: form[package.source_type_text] = form_classes[ package.source_type_text](data=data) return flask.render_template("coprs/detail/edit_package.html", package=package, copr=copr, source_type_text=source_type_text, view="coprs_ns.copr_edit_package", form_scm=form["scm"], form_pypi=form["pypi"], form_rubygems=form["rubygems"], form_custom=form['custom'])
def reschedule_build_chroot(): response = {} if "build_id" in flask.request.json and "chroot" in flask.request.json: build = ComplexLogic.get_build_safe(flask.request.json["build_id"]) else: response["result"] = "bad request" response["msg"] = "Request missing `build_id` and/or `chroot`" return flask.jsonify(response) if build: if build.canceled: response["result"] = "noop" response["msg"] = "build was cancelled, ignoring" else: chroot = flask.request.json["chroot"] build_chroot = build.chroots_dict_by_name.get(chroot) run_statuses = set([StatusEnum("starting"), StatusEnum("running")]) if build_chroot and build_chroot.status in run_statuses: log.info("rescheduling build {} chroot: {}".format(build.id, build_chroot.name)) BuildsLogic.update_state_from_dict(build, { "chroot": chroot, "status": StatusEnum("pending") }) db.session.commit() response["result"] = "done" else: response["result"] = "noop" response["msg"] = "build is not in running states, ignoring" else: response["result"] = "noop" response["msg"] = "Build {} wasn't found".format(flask.request.json["build_id"]) return flask.jsonify(response)
def edit_project_chroot(ownername, projectname, chrootname): copr = get_copr(ownername, projectname) data = rename_fields(get_form_compatible_data()) form = forms.ModifyChrootForm(data, meta={'csrf': False}) chroot = ComplexLogic.get_copr_chroot_safe(copr, chrootname) if not form.validate_on_submit(): raise BadRequest(form.errors) buildroot_pkgs = repos = comps_xml = comps_name = with_opts = without_opts = None if "buildroot_pkgs" in data: buildroot_pkgs = form.buildroot_pkgs.data if "repos" in data: repos = form.repos.data if "with_opts" in data: with_opts = form.with_opts.data if "without_opts" in data: without_opts = form.without_opts.data if form.upload_comps.has_file(): comps_xml = form.upload_comps.data.stream.read() comps_name = form.upload_comps.data.filename if form.delete_comps.data: CoprChrootsLogic.remove_comps(flask.g.user, chroot) CoprChrootsLogic.update_chroot(flask.g.user, chroot, buildroot_pkgs, repos, comps=comps_xml, comps_name=comps_name, with_opts=with_opts, without_opts=without_opts) db.session.commit() return flask.jsonify(to_dict(chroot))
def copr_package_icon(copr, package_name): try: package = ComplexLogic.get_package_safe(copr.main_dir, package_name) except ObjectNotFound: return send_file("static/status_images/bad_url.png", mimetype='image/png') return send_build_icon(package.last_build())
def copr_edit_package(copr, package_name, source_type_text=None, **kwargs): package = ComplexLogic.get_package_safe(copr, package_name) data = package.source_json_dict data["webhook_rebuild"] = package.webhook_rebuild if package.has_source_type_set and not source_type_text: source_type_text = package.source_type_text elif not source_type_text: source_type_text = "git_and_tito" form_classes = { "git_and_tito": forms.PackageFormTito, "mock_scm": forms.PackageFormMock, "pypi": forms.PackageFormPyPI, "rubygems": forms.PackageFormRubyGems, } form = {k: v(formdata=None) for k, v in form_classes.items()} if "form" in kwargs: form[source_type_text] = kwargs["form"] elif package.has_source_type_set: if package.source_type_text == "git_and_tito" and "git_dir" in data: data["git_directory"] = data["git_dir"] # @FIXME workaround form[package.source_type_text] = form_classes[ package.source_type_text](data=data) return flask.render_template("coprs/detail/edit_package.html", package=package, copr=copr, source_type_text=source_type_text, view="coprs_ns.copr_edit_package", form_tito=form["git_and_tito"], form_mock=form["mock_scm"], form_pypi=form["pypi"], form_rubygems=form["rubygems"])
def get_copr(ownername=None, projectname=None): request = flask.request ownername = ownername or request.form.get( "ownername") or request.json["ownername"] projectname = projectname or request.form.get( "projectname") or request.json["projectname"] return ComplexLogic.get_copr_by_owner_safe(ownername, projectname)
def copr_rebuild_package(copr, package_name): package = ComplexLogic.get_package_safe(copr, package_name) data = package.source_json_dict if package.source_type_text == "git_and_tito": data["git_directory"] = data["git_dir"] # @FIXME workaround form = forms.BuildFormTitoFactory f = render_add_build_tito view_suffix = "_tito" elif package.source_type_text == "mock_scm": form = forms.BuildFormMockFactory f = render_add_build_mock view_suffix = "_mock" elif package.source_type_text == "pypi": form = forms.BuildFormPyPIFactory f = render_add_build_pypi view_suffix = "_pypi" else: flask.flash( "Package {} has not the default source which is required for rebuild. Please configure some source" .format(package_name, copr.full_name)) return flask.redirect( helpers.copr_url("coprs_ns.copr_edit_package", copr, package_name=package_name)) form = form(copr.active_chroots)(data=data) return f(copr, form, view="coprs_ns.copr_new_build" + view_suffix, package=package)
def build_detail(build_id): build = ComplexLogic.get_build_safe(build_id) chroots = {} results_by_chroot = {} for chroot in build.build_chroots: chroots[chroot.name] = chroot.state results_by_chroot[chroot.name] = chroot.result_dir_url built_packages = None if build.built_packages: built_packages = build.built_packages.split("\n") output = { "output": "ok", "status": build.state, "project": build.copr.name, "owner": build.copr.owner.name, "results": build.results, "built_pkgs": built_packages, "src_version": build.pkg_version, "chroots": chroots, "submitted_on": build.submitted_on, "started_on": build.min_started_on, "ended_on": build.ended_on, "src_pkg": build.pkgs, "submitted_by": build.user.name, "results_by_chroot": results_by_chroot } return flask.jsonify(output)
def factory(**build_options): source_build = ComplexLogic.get_build_safe(build_id) BuildsLogic.create_new_from_other_build( flask.g.user, copr, source_build, chroot_names=form.selected_chroots, **build_options )
def process_rebuild(copr, build_id, view, url_on_success): source_build = ComplexLogic.get_build_safe(build_id) form = forms.BuildFormRebuildFactory.create_form_cls(copr.active_chroots)() if form.validate_on_submit(): try: build_options = { "enable_net": form.enable_net.data, "timeout": form.timeout.data, } BuildsLogic.create_new_from_other_build( flask.g.user, copr, source_build, chroot_names=form.selected_chroots, **build_options ) except (ActionInProgressException, InsufficientRightsException) as e: flask.flash(str(e), "error") db.session.rollback() else: flask.flash("New build has been created", "success") db.session.commit() return flask.redirect(url_on_success) else: return render_add_build(copr, form, view)
def process_copr_repeat_build(build_id, copr): build = ComplexLogic.get_build_safe(build_id) if not flask.g.user.can_build_in(build.copr): flask.flash("You are not allowed to repeat this build.") form = forms.BuildFormRebuildFactory.create_form_cls(build.chroots)( build_id=build_id, enable_net=build.enable_net, ) # remove all checkboxes by default for ch in build.chroots: field = getattr(form, ch.name) field.data = False chroot_to_build = request.args.get("chroot") app.logger.debug("got param chroot: {}".format(chroot_to_build)) if chroot_to_build: # set single checkbox if chroot query arg was provided if hasattr(form, chroot_to_build): getattr(form, chroot_to_build).data = True else: # set checkbox on the failed chroots chroots_to_select = set(ch.name for ch in build.get_chroots_by_status([ helpers.StatusEnum('failed'), helpers.StatusEnum('canceled'), ])) for ch in build.chroots: if ch.name in chroots_to_select: getattr(form, ch.name).data = True return flask.render_template( "coprs/detail/add_build/rebuild.html", copr=copr, build=build, form=form)
def copr_edit_chroot(copr, chrootname): form = forms.ModifyChrootForm(meta={'csrf': False}) chroot = ComplexLogic.get_copr_chroot_safe(copr, chrootname) if not form.validate_on_submit(): raise LegacyApiError("Invalid request: {0}".format(form.errors)) else: buildroot_pkgs = repos = comps_xml = comps_name = None if "buildroot_pkgs" in flask.request.form: buildroot_pkgs = form.buildroot_pkgs.data if "repos" in flask.request.form: repos = form.repos.data if form.upload_comps.has_file(): comps_xml = form.upload_comps.data.stream.read() comps_name = form.upload_comps.data.filename if form.delete_comps.data: coprs_logic.CoprChrootsLogic.remove_comps(flask.g.user, chroot) coprs_logic.CoprChrootsLogic.update_chroot(flask.g.user, chroot, buildroot_pkgs, repos, comps=comps_xml, comps_name=comps_name) db.session.commit() output = { "output": "ok", "message": "Edit chroot operation was successful.", "chroot": chroot.to_dict(), } return flask.jsonify(output)
def build_detail(build_id): build = ComplexLogic.get_build_safe(build_id) chroots = {} results_by_chroot = {} for chroot in build.build_chroots: chroots[chroot.name] = chroot.state results_by_chroot[chroot.name] = chroot.result_dir_url built_packages = None if build.built_packages: built_packages = build.built_packages.split("\n") output = { "output": "ok", "status": build.state, "project": build.copr_name, "project_dirname": build.copr_dirname, "owner": build.copr.owner_name, "results": build.copr.repo_url, # TODO: in new api return build results url "built_pkgs": built_packages, "src_version": build.pkg_version, "chroots": chroots, "submitted_on": build.submitted_on, "started_on": build.min_started_on, "ended_on": build.max_ended_on, "src_pkg": build.pkgs, "submitted_by": build.user.name if build.user else None, # there is no user for webhook builds "results_by_chroot": results_by_chroot } return flask.jsonify(output)
def group_copr_new(group_name): group = ComplexLogic.get_group_by_name_safe(group_name) form = forms.CoprFormFactory.create_form_cls(group=group)() if form.validate_on_submit(): copr = coprs_logic.CoprsLogic.add( flask.g.user, name=form.name.data, homepage=form.homepage.data, contact=form.contact.data, repos=form.repos.data.replace("\n", " "), selected_chroots=form.selected_chroots, description=form.description.data, instructions=form.instructions.data, disable_createrepo=form.disable_createrepo.data, build_enable_net=form.build_enable_net.data, group=group ) db.session.add(copr) db.session.commit() after_the_project_creation(copr, form) return flask.redirect(url_for_copr_details(copr)) else: return flask.render_template("coprs/group_add.html", form=form, group=group)
def copr_edit_package(copr, package_name, source_type=None, **kwargs): package = ComplexLogic.get_package_safe(copr, package_name) data = package.source_json_dict data["webhook_rebuild"] = package.webhook_rebuild if package.source_type and not source_type: source_type = package.source_type_text elif not source_type: source_type = "git_and_tito" form_classes = { "git_and_tito": forms.PackageFormTito, "mock_scm": forms.PackageFormMock, "pypi": forms.PackageFormPyPI, } form = {k: v(formdata=None) for k, v in form_classes.items()} if "form" in kwargs: form[kwargs["form"].source_type.data] = kwargs["form"] elif package.source_type: if package.source_type_text == "git_and_tito" and "git_dir" in data: data["git_directory"] = data["git_dir"] # @FIXME workaround form[package.source_type_text] = form_classes[package.source_type_text](data=data) return flask.render_template("coprs/detail/package_edit.html", package=package, copr=copr, source_type=source_type, view="coprs_ns.copr_edit_package", form_tito=form["git_and_tito"], form_mock=form["mock_scm"], form_pypi=form["pypi"])
def list_projects_by_group(group_name, page=1): group = ComplexLogic.get_group_by_name_safe(group_name) query = CoprsLogic.get_multiple_by_group_id(group.id) paginator = Paginator(query, query.count(), page) coprs = paginator.sliced_query return render_template( "coprs/show/group.html", user=flask.g.user, coprs=coprs, paginator=paginator, tasks_info=ComplexLogic.get_queues_size(), group=group )
def factory(**build_options): source_build = ComplexLogic.get_build_safe(build_id) BuildsLogic.create_new_from_other_build( flask.g.user, copr, source_build, chroot_names=form.selected_chroots, **build_options)
def process_delete(copr, url_on_error, url_on_success): form = forms.CoprDeleteForm() if form.validate_on_submit(): try: ComplexLogic.delete_copr(copr) except (exceptions.ActionInProgressException, exceptions.InsufficientRightsException) as e: db.session.rollback() flask.flash(str(e), "error") return flask.redirect(url_on_error) else: db.session.commit() flask.flash("Project has been deleted successfully.") return flask.redirect(url_on_success) else: return render_template("coprs/detail/settings/delete.html", form=form, copr=copr)
def copr_createrepo(copr_id): copr = ComplexLogic.get_copr_by_id_safe(copr_id) chroots = [c.name for c in copr.active_chroots] actions_logic.ActionsLogic.send_createrepo( username=('@'+copr.group.name if copr.is_a_group_project else copr.user.name), coprname=copr.name, chroots=chroots) db.session.commit() flask.flash("Repository metadata will be regenerated in a few minutes ...") return flask.redirect(url_for_copr_details(copr))
def cancel_build(build_id): build = ComplexLogic.get_build_safe(build_id) try: builds_logic.BuildsLogic.cancel_build(flask.g.user, build) db.session.commit() except exceptions.InsufficientRightsException as e: raise LegacyApiError("Invalid request: {}".format(e)) output = {'output': 'ok', 'status': "Build canceled"} return flask.jsonify(output)
def copr_delete_build(username, coprname, build_id): build = ComplexLogic.get_build_safe(build_id) try: builds_logic.BuildsLogic.delete_build(flask.g.user, build) except (InsufficientRightsException, ActionInProgressException) as e: flask.flash(str(e), "error") else: db.session.commit() flask.flash("Build has been deleted successfully.", "success") return flask.redirect(url_for_copr_builds(build.copr))
def copr_delete_package(copr, package_id): package = ComplexLogic.get_package_by_id_safe(package_id) try: PackagesLogic.delete_package(flask.g.user, package) except (InsufficientRightsException, ActionInProgressException) as e: flask.flash(str(e), "error") else: db.session.commit() flask.flash("Package has been deleted successfully.", "success") return flask.redirect(helpers.copr_url("coprs_ns.copr_packages", copr))
def api_copr_delete(copr): """ Deletes selected user's project """ form = forms.CoprDeleteForm(csrf_enabled=False) httpcode = 200 if form.validate_on_submit() and copr: try: ComplexLogic.delete_copr(copr) except (exceptions.ActionInProgressException, exceptions.InsufficientRightsException) as err: db.session.rollback() raise LegacyApiError(str(err)) else: message = "Project {} has been deleted.".format(copr.name) output = {"output": "ok", "message": message} db.session.commit() else: raise LegacyApiError("Invalid request") return flask.jsonify(output)
def copr_modify_chroot(copr, chrootname): form = forms.ModifyChrootForm(csrf_enabled=False) # chroot = coprs_logic.MockChrootsLogic.get_from_name(chrootname, active_only=True).first() chroot = ComplexLogic.get_copr_chroot_safe(copr, chrootname) if not form.validate_on_submit(): raise LegacyApiError("Invalid request: bad request parameters") else: coprs_logic.CoprChrootsLogic.update_chroot(flask.g.user, chroot, form.buildroot_pkgs.data) db.session.commit() output = {'output': 'ok', 'buildroot_pkgs': chroot.buildroot_pkgs} return flask.jsonify(output)
def render_package_edit(copr, package_name, view, form_tito=None, form_mock=None): package = ComplexLogic.get_package_safe(copr, package_name) if not form_tito: data = package.source_json_dict if "git_dir" in data: data["git_directory"] = data["git_dir"] # @FIXME workaround form_tito = forms.PackageFormTitoFactory.create_form_cls()(data=data) if not form_mock: data = package.source_json_dict form_mock = forms.PackageFormMockFactory.create_form_cls()(data=data) return flask.render_template("coprs/detail/package_edit.html", package=package, copr=copr, form_tito=form_tito, form_mock=form_mock, view=view)
def render_chroot_edit(copr, chroot_name): chroot = ComplexLogic.get_copr_chroot_safe(copr, chroot_name) # todo: get COPR_chroot, not mock chroot, WTF?! # form = forms.ChrootForm(buildroot_pkgs=copr.buildroot_pkgs(chroot)) form = forms.ChrootForm(buildroot_pkgs=chroot.buildroot_pkgs) # FIXME - test if chroot belongs to copr if flask.g.user.can_build_in(copr): return render_template("coprs/detail/edit_chroot.html", form=form, copr=copr, chroot=chroot) else: raise AccessRestricted( "You are not allowed to modify chroots in project {0}." .format(copr.name))
def copr_build_redirect(build_id): build = ComplexLogic.get_build_safe(build_id) copr = build.copr if copr.is_a_group_project: return flask.redirect(url_for( "coprs_ns.group_copr_build", group_name=build.copr.group.name, coprname=build.copr.name, build_id=build_id)) else: return flask.redirect(url_for( "coprs_ns.copr_build", username=build.copr.user.name, coprname=build.copr.name, build_id=build_id))
def generate_repo_file(username, coprname, name_release, repofile): """ Generate repo file for a given repo name. Reponame = username-coprname """ # This solution is used because flask splits off the last part after a # dash, therefore user-re-po resolves to user-re/po instead of user/re-po # FAS usernames may not contain dashes, so this construction is safe. # support access to the group projects using @-notation # todo: remove when yum/dnf plugin is updated to use new url schema if username.startswith("@"): return group_generate_repo_file(group_name=username[1:], coprname=coprname, name_release=name_release, repofile=repofile) copr = ComplexLogic.get_copr_safe(username, coprname) return render_generate_repo_file(copr, name_release)
def render_copr_package_rebuild(copr, package_name, view): package = ComplexLogic.get_package_safe(copr, package_name) data = package.source_json_dict if package.source_type_text == "git_and_tito": data["git_directory"] = data["git_dir"] # @FIXME workaround form = forms.BuildFormTitoFactory f = render_add_build_tito view_suffix = "_tito" elif package.source_type_text == "mock_scm": form = forms.BuildFormMockFactory f = render_add_build_mock view_suffix = "_mock" form = form.create_form_cls(copr.active_chroots)(data=data) return f(copr, form, view=view + view_suffix)
def coprs_show(page=1): query = CoprsLogic.get_multiple() query = CoprsLogic.set_query_order(query, desc=True) paginator = helpers.Paginator(query, query.count(), page) coprs = paginator.sliced_query # flask.g.user is none when no user is logged - showing builds from everyone # TODO: builds_logic.BuildsLogic.get_recent_tasks(flask.g.user, 5) takes too much time, optimize sql # users_builds = builds_logic.BuildsLogic.get_recent_tasks(flask.g.user, 5) users_builds = builds_logic.BuildsLogic.get_recent_tasks(None, 5) return flask.render_template("coprs/show/all.html", coprs=coprs, paginator=paginator, tasks_info=ComplexLogic.get_queues_size(), users_builds=users_builds)
def test_fork_copr_sends_actions(self, mc_flask_g, f_users, f_coprs, f_mock_chroots, f_builds, f_db): mc_flask_g.user.name = self.u2.name fc1, created = ComplexLogic.fork_copr(self.c1, self.u2, u"dstname") self.db.session.commit() actions = ActionsLogic.get_many(ActionTypeEnum("gen_gpg_key")).all() assert len(actions) == 1 data = json.loads(actions[0].data) assert data["username"] == self.u2.name assert data["projectname"] == "dstname" actions = ActionsLogic.get_many(ActionTypeEnum("fork")).all() assert len(actions) == 1 data = json.loads(actions[0].data) assert data["user"] == self.u2.name assert data["copr"] == "dstname" last_build, forked_build = self.c1.packages[0].builds[1], fc1.builds[0] assert data["builds_map"] == {str(forked_build.id): str(last_build.result_dir_name)}
def copr_fork_post(copr): form = forms.CoprForkFormFactory.create_form_cls(copr=copr, user=flask.g.user, groups=flask.g.user.user_groups)() if form.validate_on_submit(): dstgroup = ([g for g in flask.g.user.user_groups if g.at_name == form.owner.data] or [None])[0] if flask.g.user.name != form.owner.data and not dstgroup: return generic_error("There is no such group: {}".format(form.owner.data)) fcopr = CoprsLogic.get_by_group_id(dstgroup.id, form.name.data).first() if dstgroup \ else CoprsLogic.filter_without_group_projects(CoprsLogic.get(flask.g.user.name, form.name.data)).first() if not fcopr: fcopr = ComplexLogic.fork_copr(copr, flask.g.user, dstname=form.name.data, dstgroup=dstgroup) db.session.commit() flask.flash("Forking project {} for you into {}. Please be aware that it may take a few minutes " "to duplicate a backend data.".format(copr.full_name, fcopr.full_name)) return flask.redirect(url_for_copr_details(fcopr)) return render_copr_fork(copr, form)
def coprs_fulltext_search(page=1): fulltext = flask.request.args.get("fulltext", "") try: query = coprs_logic.CoprsLogic.get_multiple_fulltext(fulltext) except ValueError as e: flask.flash(str(e), "error") return flask.redirect(flask.request.referrer or flask.url_for("coprs_ns.coprs_show")) paginator = helpers.Paginator(query, query.count(), page, additional_params={"fulltext": fulltext}) coprs = paginator.sliced_query return render_template( "coprs/show/fulltext.html", coprs=coprs, paginator=paginator, fulltext=fulltext, tasks_info=ComplexLogic.get_queues_size(), )
def starting_build(): """ Check if the build is not cancelled and set it to running state """ result = {"can_start": False} if "build_id" in flask.request.json and "chroot" in flask.request.json: build = ComplexLogic.get_build_safe(flask.request.json["build_id"]) chroot = flask.request.json.get("chroot") if build and chroot and not build.canceled: log.info("mark build {} chroot {} as starting".format(build.id, chroot)) BuildsLogic.update_state_from_dict(build, { "chroot": chroot, "status": StatusEnum("starting") }) db.session.commit() result["can_start"] = True return flask.jsonify(result)
def process_copr_repeat_build(build_id, copr): build = ComplexLogic.get_build_safe(build_id) if not flask.g.user.can_build_in(build.copr): flask.flash("You are not allowed to repeat this build.") if build.source_type == helpers.BuildSourceEnum('srpm_upload'): # If the original build's source is 'srpm_upload', we will show only the # original build's chroots and skip import. available_chroots = build.chroots else: # For all other sources, we will show all chroots enabled in the project # and proceed with import. available_chroots = copr.active_chroots form = forms.BuildFormRebuildFactory.create_form_cls(available_chroots)( build_id=build_id, enable_net=build.enable_net) # remove all checkboxes by default for ch in available_chroots: field = getattr(form, ch.name) field.data = False chroot_to_build = request.args.get("chroot") app.logger.debug("got param chroot: {}".format(chroot_to_build)) if chroot_to_build: # set single checkbox if chroot query arg was provided if hasattr(form, chroot_to_build): getattr(form, chroot_to_build).data = True else: build_chroot_names = set(ch.name for ch in build.chroots) build_failed_chroot_names = set(ch.name for ch in build.get_chroots_by_status([ helpers.StatusEnum('failed'), helpers.StatusEnum('canceled'), ])) for ch in available_chroots: # check checkbox on all the chroots that have not been (successfully) built before if (ch.name not in build_chroot_names) or (ch.name in build_failed_chroot_names): getattr(form, ch.name).data = True return flask.render_template( "coprs/detail/add_build/rebuild.html", copr=copr, build=build, form=form)
def copr_fork_post(copr): form = forms.CoprForkFormFactory.create_form_cls(copr=copr, user=flask.g.user, groups=flask.g.user.user_groups)() if form.validate_on_submit(): dstgroup = ([g for g in flask.g.user.user_groups if g.at_name == form.owner.data] or [None])[0] if flask.g.user.name != form.owner.data and not dstgroup: return generic_error("There is no such group: {}".format(form.owner.data)) fcopr, created = ComplexLogic.fork_copr(copr, flask.g.user, dstname=form.name.data, dstgroup=dstgroup) if created: msg = ("Forking project {} for you into {}. Please be aware that it may take a few minutes " "to duplicate a backend data.".format(copr.full_name, fcopr.full_name)) elif not created and form.confirm.data == True: msg = ("Updating packages in {} from {}. Please be aware that it may take a few minutes " "to duplicate a backend data.".format(copr.full_name, fcopr.full_name)) else: return render_copr_fork(copr, form, confirm=True) db.session.commit() flask.flash(msg) return flask.redirect(url_for_copr_details(fcopr)) return render_copr_fork(copr, form)