From 11130d8f055e65876b81e6a0427299d6e6bccae0 Mon Sep 17 00:00:00 2001 From: Pavel Raiskup Date: Apr 25 2022 12:45:43 +0000 Subject: frontend: new command 'copr-frontend chroots-template' We have dozens of chroots, and it has been tedious task to configure the comments for them manually (copy-pasting the long comments, maintaining links, etc.). The new command automatizes this by applying rules from a new /etc/copr/chroots.conf configuration file. Merges: #2179 --- diff --git a/doc/how_to_manage_chroots.rst b/doc/how_to_manage_chroots.rst index 9c9eb00..b4c05a2 100644 --- a/doc/how_to_manage_chroots.rst +++ b/doc/how_to_manage_chroots.rst @@ -19,6 +19,7 @@ Chroots can be easily managed with these few commands. copr-frontend alter-chroot --action deactivate copr-frontend branch-fedora copr-frontend rawhide-to-release + copr-frontend chroots-template [--template PATH] However, `enablement process upon Fedora branching <#branching-process>`_ and also `chroot deactivation when Fedora reaches it's EOL phase <#eol-deactivation-process>`_, are not that simple. @@ -108,6 +109,48 @@ When it is done, `send an information email to a mailing list <#mailing-lists>`_ See the :ref:`the disable chroots template `. +.. _managing_chroot_comments: + +Managing chroot comments +------------------------ + +Some of the available Mock chroots deserve a special care in documentation, e.g. +that `epel-8-*` chroots are nowadays built against Red Hat Enterprise Linux 8, +not CentOS 8 (which is EOL). There's an administrator command for this:: + + $ copr-frontend comment-chroot --chroot epel-8-x86_64 --comment 'Built against RHEL 8!' + +Note that HTML text is supported! + +This was though a single-chroot command. There's a better option for those Copr +instances that contain dozens of chroots:: + + $ copr-frontend chroots-template [--template /etc/copr/chroots.conf] + +This file reads the template file in the following format (a Python file +defining the ``config`` dictionary):: + + config = {} + config["emulated"] = "This is an emulated chroot" + config["rules"] = [{ + "match": "fedora-rawhide-i386", + "comment": "This is soon to be removed", + }, { + "match": ["fedora-32", "fedora-33"], + "comment": "Currently EOL, on your own risk", + }, + { + "match": ["aarch64", "ppc64le"], + "match_type", "arch", + "comment_append": "{{ emulated }}", + }] + +When (manually) executed, the command recursively iterates across all the active +Mock chroots, and applies the specified rules (only ``comment`` or +``comment_append`` currently) when the chroot matches the rules (``match`` and +``match_type`` statements). + + Mailing lists ------------- diff --git a/frontend/copr-frontend.spec b/frontend/copr-frontend.spec index 2ff4553..6bd486a 100644 --- a/frontend/copr-frontend.spec +++ b/frontend/copr-frontend.spec @@ -85,6 +85,7 @@ BuildRequires: python3-email-validator BuildRequires: python3-dateutil BuildRequires: python3-decorator BuildRequires: python3-flask +BuildRequires: python3-templated-dictionary %if 0%{?fedora} >= 31 BuildRequires: python3-flask-caching %else @@ -171,6 +172,7 @@ Requires: python3-pylibravatar Requires: python3-pytz Requires: python3-redis Requires: python3-requests +Requires: python3-templated-dictionary Requires: python3-wtforms >= 2.2.1 Requires: python3-zmq Requires: xstatic-bootstrap-scss-common @@ -352,6 +354,7 @@ usermod -L copr-fe %config(noreplace) %{_sysconfdir}/copr/copr.conf %config(noreplace) %{_sysconfdir}/copr/copr_devel.conf %config(noreplace) %{_sysconfdir}/copr/copr_unit_test.conf +%config(noreplace) %{_sysconfdir}/copr/chroots.conf %defattr(-, root, root, -) %config %{_sysconfdir}/cron.hourly/copr-frontend diff --git a/frontend/coprs_frontend/commands/chroots_template.py b/frontend/coprs_frontend/commands/chroots_template.py new file mode 100644 index 0000000..9650606 --- /dev/null +++ b/frontend/coprs_frontend/commands/chroots_template.py @@ -0,0 +1,80 @@ +""" +The 'copr-frontend chroots-template' command implementation. +""" + +import importlib +import click +from templated_dictionary import TemplatedDictionary + +from coprs import db_session_scope +from coprs.logic import coprs_logic + + +def apply_rule(chroot, rule): + """ + The rule is to be applied to this chroot. + """ + already_modified = getattr(chroot, "_already_modified", False) + setattr(chroot, "_already_modified", True) + if "comment" in rule: + chroot.comment = rule["comment"] + return + if "comment_append" in rule: + if not already_modified: + chroot.comment = "" + chroot.comment += rule["comment_append"] + return + raise click.ClickException("Unknown rule type.") + + +def matches(string, rule): + """ + Helper to accept both string and list() values in match argument. + """ + rule = rule["match"] + if isinstance(rule, list): + return string in rule + return string == rule + + +def apply_rules(chroot, config): + """ + Iterate over the rules from the config file, and attempt to apply them. + """ + for rule in config["rules"]: + match_type = rule.get("match_type", "name") + if match_type == "name": + if matches(chroot.name, rule) or matches(chroot.name_release, rule): + apply_rule(chroot, rule) + continue + if match_type == "arch" and matches(chroot.arch, rule): + apply_rule(chroot, rule) + continue + + +@click.command() +@click.option( + "-t", "--template", + help="Batch-configure the enabled chroots from a template file.", + type=click.Path(exists=True, readable=True), + default="/etc/copr/chroots.conf", +) +def chroots_template(template): + """ + Load the MockChroot configuration from /etc/copr/chroots.conf. For more + info take a look at + https://docs.pagure.org/copr.copr/how_to_manage_chroots.html#managing-chroot-comments + """ + + # Meh, this used to be just 'imp.load_source()' (but 'imp' is deprecated). + loader = importlib.machinery.SourceFileLoader("config", template) + spec = importlib.util.spec_from_loader(loader.name, loader) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + + obj = getattr(module, "config") + config = TemplatedDictionary(obj) + config["__jinja_expand"] = True + with db_session_scope(): + for ch in coprs_logic.MockChrootsLogic.get_multiple(active_only=True): + apply_rules(ch, config) diff --git a/frontend/coprs_frontend/config/chroots.conf b/frontend/coprs_frontend/config/chroots.conf new file mode 100644 index 0000000..1da0974 --- /dev/null +++ b/frontend/coprs_frontend/config/chroots.conf @@ -0,0 +1,35 @@ +# Configuration for the 'copr-frontend chroots-template'. That command is to be +# executed manually by the Copr admin (e.g. via Ansible). + +config = {} +config["rules"] = [] + +# Possible options: +# config = { +# # Supports the recursive Jinja2 templating. +# "emulated": 'An emulated chroot', +# "stream": 'For now built against CentOS Stream, will be moved against RHEL once available.', +# "released": 'Built against a GA software', +# } +# +# config["rules"] = [{ +# # Reset comments for aarch64 chroots +# "match": "aarch64", +# "match_type": "arch", +# "comment": "", +# }, { +# # Set a comment for a single chroot +# "match": "epel-9", +# "comment": '{{ stream }}', +# }, { +# # Multiple chroots matched +# "match": ["epel-8", "epel-9"], +# "comment": "Built against RHEL", +# } { +# # Multiple architectures matched, and comment _appended_ +# "match_type": "arch", +# "match": ["s390x", "ppc64le", "armhfp"], +# "comment_append": "{{ emulated }}", +# }] +# +# vim: ft=python diff --git a/frontend/coprs_frontend/manage.py b/frontend/coprs_frontend/manage.py index fe6f5d5..571253b 100755 --- a/frontend/coprs_frontend/manage.py +++ b/frontend/coprs_frontend/manage.py @@ -37,6 +37,7 @@ import commands.clean_expired_projects import commands.clean_old_builds import commands.delete_orphans import commands.fixup_unnoticed_chroots +import commands.chroots_template from coprs import app @@ -63,6 +64,7 @@ commands_list = [ "branch_fedora", "comment_chroot", "fixup_unnoticed_chroots", + "chroots_template", # User commands "alter_user",