From 709afb7413d096627e27916a6861d27e25a7b970 Mon Sep 17 00:00:00 2001
From: Tomas Kopecek <tkopecek@redhat.com>
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 <tkopecek@redhat.com>
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 <tkopecek@redhat.com>
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 <tkopecek@redhat.com>
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 <tkopecek@redhat.com>
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')

