From 709afb7413d096627e27916a6861d27e25a7b970 Mon Sep 17 00:00:00 2001 From: Tomas Kopecek Date: Jun 02 2021 09:46:19 +0000 Subject: [PATCH 1/5] sidetags: configurable naming template Fixes: https://pagure.io/koji/issue/2893 --- diff --git a/plugins/hub/sidetag.conf b/plugins/hub/sidetag.conf index fefa32d..3a2ed0f 100644 --- a/plugins/hub/sidetag.conf +++ b/plugins/hub/sidetag.conf @@ -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)s-sidetag-%%(tag_id)d diff --git a/plugins/hub/sidetag_hub.py b/plugins/hub/sidetag_hub.py index 4dc8247..4fb96b6 100644 --- a/plugins/hub/sidetag_hub.py +++ b/plugins/hub/sidetag_hub.py @@ -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 % {'basetag': basetag["name"], 'tag_id': tag_id} if suffix: sidetag_name += '-%s' % suffix extra = { @@ -314,9 +314,14 @@ def handle_sidetag_untag(cbtype, *args, **kws): # read config and register if not CONFIG: CONFIG = koji.read_config_files(CONFIG_FILE) + print(open(CONFIG_FILE).read()) 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)s-side-%(tag_id)d' From e932adb1ea0dd8cf31dbd3aed982a79a868a4aff Mon Sep 17 00:00:00 2001 From: Tomas Kopecek Date: Jun 03 2021 07:50:09 +0000 Subject: [PATCH 2/5] update docs --- diff --git a/docs/source/plugins.rst b/docs/source/plugins.rst index a9baebb..1ec332f 100644 --- a/docs/source/plugins.rst +++ b/docs/source/plugins.rst @@ -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 --- From f1bc50a544362766773e4f917af53ab20be52d1b Mon Sep 17 00:00:00 2001 From: Tomas Kopecek Date: Jun 03 2021 07:50:28 +0000 Subject: [PATCH 3/5] use format for name_template --- diff --git a/plugins/hub/sidetag.conf b/plugins/hub/sidetag.conf index 3a2ed0f..d4e55a4 100644 --- a/plugins/hub/sidetag.conf +++ b/plugins/hub/sidetag.conf @@ -6,4 +6,4 @@ remove_empty = off # 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)s-sidetag-%%(tag_id)d +# name_template = {basetag}-side-{tag_id} diff --git a/plugins/hub/sidetag_hub.py b/plugins/hub/sidetag_hub.py index 4fb96b6..2d184f4 100644 --- a/plugins/hub/sidetag_hub.py +++ b/plugins/hub/sidetag_hub.py @@ -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 = NAME_TEMPLATE % {'basetag': basetag["name"], 'tag_id': tag_id} + sidetag_name = NAME_TEMPLATE.format(basetag=basetag["name"], tag_id=tag_id) if suffix: sidetag_name += '-%s' % suffix extra = { @@ -313,7 +313,7 @@ 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) print(open(CONFIG_FILE).read()) if CONFIG.has_option("sidetag", "remove_empty") and CONFIG.getboolean( "sidetag", "remove_empty" @@ -324,4 +324,4 @@ if not CONFIG: if CONFIG.has_option("sidetag", "name_template"): NAME_TEMPLATE = CONFIG.get("sidetag", "name_template") else: - NAME_TEMPLATE = '%(basetag)s-side-%(tag_id)d' + NAME_TEMPLATE = '{basetag}-side-{tag_id}' From 9729f3cec4fef8d73a5b8dbd244fe1ffd70328c6 Mon Sep 17 00:00:00 2001 From: Tomas Kopecek Date: Jun 03 2021 07:50:58 +0000 Subject: [PATCH 4/5] remove debug --- diff --git a/plugins/hub/sidetag_hub.py b/plugins/hub/sidetag_hub.py index 2d184f4..5ce0e4d 100644 --- a/plugins/hub/sidetag_hub.py +++ b/plugins/hub/sidetag_hub.py @@ -314,7 +314,6 @@ def handle_sidetag_untag(cbtype, *args, **kws): # read config and register if not CONFIG: CONFIG = koji.read_config_files(CONFIG_FILE, raw=True) - print(open(CONFIG_FILE).read()) if CONFIG.has_option("sidetag", "remove_empty") and CONFIG.getboolean( "sidetag", "remove_empty" ): From 2544c2fbb45f479d3ee58f83cff62300498b2bbd Mon Sep 17 00:00:00 2001 From: Tomas Kopecek Date: Jun 03 2021 11:14:36 +0000 Subject: [PATCH 5/5] basic test --- diff --git a/tests/test_plugins/test_sidetag_hub.py b/tests/test_plugins/test_sidetag_hub.py new file mode 100644 index 0000000..d0792a5 --- /dev/null +++ b/tests/test_plugins/test_sidetag_hub.py @@ -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')