PR#2894: sidetags: configurable naming template

Merges #2894
https://pagure.io/koji/pull-request/2894

Fixes: #2893
https://pagure.io/koji/issue/2893
sidetags: configurable naming template
This commit is contained in:
Tomas Kopecek 2021-06-03 15:24:05 +02:00
commit b345b62b6d
4 changed files with 126 additions and 5 deletions

View file

@ -130,9 +130,20 @@ Now Sidetag Koji plugin should be installed. To verify that, run
as one of available API calls.
Plugin has also its own configuration file
``/etc/koji-hub/plugins/sidetag.conf`` which for now contains the only boolean
option ``remove_empty``. If it is set, sidetag is automatically deleted when
last package is untagged from there.
``/etc/koji-hub/plugins/sidetag.conf`` which contains following options:
.. glossary::
remove_empty = off
If this is set, sidetag is automatically deleted when
last package is untagged from there.
allowed_suffixes =
List of strings delimited by commas. These suffixes are then allowed to
be requested via ``createSideTag``
name_template = {basetag}s-side-{tag_id}d
Python string template to be used for generation of sidetag name. It needs
to contain both basetag/tag_id placeholders.
CLI
---

View file

@ -3,3 +3,7 @@
remove_empty = off
# potential suffixes for sidetag names
# allowed_suffixes =
# template for sidetag names. It must contain basetag and tag_id parts
# if allowed_suffixes is not empty and suffix was requested, it will be added
# as {name_template}-{suffix}. (percent-signs need to be escaped)
# name_template = {basetag}-side-{tag_id}

View file

@ -118,7 +118,7 @@ def createSideTag(basetag, debuginfo=False, suffix=None):
# ugly, it will waste one number in tag_id_seq, but result will match with
# id assigned by _create_tag
tag_id = nextval("tag_id_seq") + 1
sidetag_name = "%s-side-%s" % (basetag["name"], tag_id)
sidetag_name = NAME_TEMPLATE.format(basetag=basetag["name"], tag_id=tag_id)
if suffix:
sidetag_name += '-%s' % suffix
extra = {
@ -313,10 +313,14 @@ def handle_sidetag_untag(cbtype, *args, **kws):
# read config and register
if not CONFIG:
CONFIG = koji.read_config_files(CONFIG_FILE)
CONFIG = koji.read_config_files(CONFIG_FILE, raw=True)
if CONFIG.has_option("sidetag", "remove_empty") and CONFIG.getboolean(
"sidetag", "remove_empty"
):
handle_sidetag_untag = callback("postUntag")(handle_sidetag_untag)
if CONFIG.has_option("sidetag", "allowed_suffixes"):
ALLOWED_SUFFIXES = CONFIG.get("sidetag", "allowed_suffixes").split(',')
if CONFIG.has_option("sidetag", "name_template"):
NAME_TEMPLATE = CONFIG.get("sidetag", "name_template")
else:
NAME_TEMPLATE = '{basetag}-side-{tag_id}'

View file

@ -0,0 +1,102 @@
from __future__ import absolute_import
import mock
import unittest
import koji
import kojihub
import sidetag_hub
class TestSideTagHub(unittest.TestCase):
def setUp(self):
self.QueryProcessor = mock.patch('sidetag_hub.QueryProcessor',
side_effect=self.getQuery).start()
self.queries = []
def getQuery(self, *args, **kwargs):
query = kojihub.QueryProcessor(*args, **kwargs)
query.execute = mock.MagicMock()
query.executeOne = mock.MagicMock()
query.executeOne.return_value = {'user_tags': 0}
self.queries.append(query)
return query
@mock.patch('sidetag_hub.nextval')
@mock.patch('sidetag_hub._create_build_target')
@mock.patch('sidetag_hub._create_tag')
@mock.patch('sidetag_hub.assert_policy')
@mock.patch('sidetag_hub.get_tag')
@mock.patch('sidetag_hub.get_user')
@mock.patch('sidetag_hub.context')
def test_createsidetag_basic(self, context, get_user, get_tag, assert_policy,
_create_tag, _create_build_target, nextval):
basetag = {
'id': 32,
'name': 'base_tag',
'arches': ['x86_64', 'i686']
}
user = {
'id': 23,
'name': 'username',
}
sidetag_name = 'base_tag-side-12346'
context.session.assertLogin = mock.MagicMock()
context.session.user_id = 123
get_user.return_value = user
get_tag.return_value = basetag
nextval.return_value = 12345
_create_tag.return_value = 12346
ret = sidetag_hub.createSideTag('base_tag')
self.assertEqual(ret, {'name': sidetag_name, 'id': 12346})
get_user.assert_called_once_with(123, strict=True)
get_tag.assert_called_once_with(basetag['name'], strict=True)
assert_policy.assert_called_once_with(
"sidetag", {"tag": basetag["id"], "number_of_tags": 0}
)
nextval.assert_called_once_with('tag_id_seq')
_create_tag.assert_called_once_with(
sidetag_name,
parent=basetag['id'],
arches=basetag['arches'],
extra={
"sidetag": True,
"sidetag_user": user["name"],
"sidetag_user_id": user["id"],
})
_create_build_target.assert_called_once_with(sidetag_name, 12346, 12346)
@mock.patch('sidetag_hub.nextval')
@mock.patch('sidetag_hub._create_build_target')
@mock.patch('sidetag_hub._create_tag')
@mock.patch('sidetag_hub.assert_policy')
@mock.patch('sidetag_hub.get_tag')
@mock.patch('sidetag_hub.get_user')
@mock.patch('sidetag_hub.context')
def test_createsidetag_template(self, context, get_user, get_tag, assert_policy,
_create_tag, _create_build_target, nextval):
basetag = {
'id': 32,
'name': 'base_tag',
'arches': ['x86_64', 'i686']
}
user = {
'id': 23,
'name': 'username',
}
sidetag_name = 'base_tag-sidetag-12346-suffix'
context.session.assertLogin = mock.MagicMock()
context.session.user_id = 123
get_user.return_value = user
get_tag.return_value = basetag
nextval.return_value = 12345
_create_tag.return_value = 12346
sidetag_hub.ALLOWED_SUFFIXES = ['suffix', 'another']
sidetag_hub.NAME_TEMPLATE = '{basetag}-sidetag-{tag_id}'
ret = sidetag_hub.createSideTag('base_tag', suffix='suffix')
self.assertEqual(ret, {'name': sidetag_name, 'id': 12346})
with self.assertRaises(koji.GenericError):
ret = sidetag_hub.createSideTag('base_tag', suffix='forbidden_suffix')