From 3a4106a6619b9521b3ffc7504b5568624aafba26 Mon Sep 17 00:00:00 2001
From: Tomas Kopecek <tkopecek@redhat.com>
Date: Jun 25 2024 22:39:54 +0000
Subject: Provide tag data in policy_data_from_task_args


Also included
* unit test
* only set scratch if opt is present

---

diff --git a/kojihub/kojihub.py b/kojihub/kojihub.py
index a408491..bf1bdc7 100644
--- a/kojihub/kojihub.py
+++ b/kojihub/kojihub.py
@@ -10150,9 +10150,30 @@ def policy_data_from_task_args(method, arglist):
                 target = tinfo['name']
         policy_data['target'] = target
 
+    # parameters that indicate a tag
+    hastag = False
+    for k in ('tag', 'tag_id', 'tag_info'):
+        if k in params:
+            tag = params.get(k)
+            hastag = True
+            break
+    if hastag:
+        try:
+            policy_data['tag'] = lookup_tag(tag, strict=True)['name']
+        except Exception:
+            logger.warning("Bad tag parameter: %r", tag)
+
+    if 'build_tag' in params:
+        try:
+            policy_data['build_tag'] = lookup_tag(params['build_tag'], strict=True)['name']
+        except Exception:
+            logger.warning("Bad tag parameter: %(build_tag)r", params)
+
+    # provide scratch opt if given
     # we may have param['opts'] that is explicitly None
     t_opts = params.get('opts') or {}
-    policy_data['scratch'] = t_opts.get('scratch', False)
+    if 'scratch' in t_opts:
+        policy_data['scratch'] = t_opts['scratch']
 
     return policy_data
 
diff --git a/tests/test_hub/test_policy_tests.py b/tests/test_hub/test_policy_tests.py
index 95d791d..d8b0ca8 100644
--- a/tests/test_hub/test_policy_tests.py
+++ b/tests/test_hub/test_policy_tests.py
@@ -761,3 +761,95 @@ class IsBuildOwnerTest(unittest.TestCase):
         self.get_user.assert_called_once_with(3)
         self.policy_get_user.assert_called_once_with(data)
         self.get_user_groups.assert_not_called()
+
+
+class TestPolicyDataFromTask(unittest.TestCase):
+
+    def setUp(self):
+        self.lookup_build_target = mock.patch('kojihub.kojihub.lookup_build_target').start()
+        self.lookup_build_target.return_value = {'id': 100, 'name': 'MYTARGET'}
+        self.lookup_tag = mock.patch('kojihub.kojihub.lookup_tag').start()
+        self.lookup_tag.return_value = {'id': 100, 'name': 'MYTAG'}
+
+    def tearDown(self):
+        mock.patch.stopall()
+
+    GOOD = [
+        # method, kwargs, expect
+        ['build',
+            {'src': 'git://foo', 'target': 100, 'opts': {}},
+            {'source': 'git://foo', 'target': 'MYTARGET'}],
+        ['build',
+            {'src': 'git://foo', 'target': 100, 'opts': {'scratch': True}},
+            {'source': 'git://foo', 'target': 'MYTARGET', 'scratch': True}],
+        ['build', 
+            {'src': 'git://foo', 'target': {'name': 'MYTARGET'}, 'opts': {}},
+            {'source': 'git://foo', 'target': 'MYTARGET'}],
+        ['newRepo',
+            {'tag': 100},
+            {'tag': 'MYTAG'}],
+        ['newRepo',
+            {'tag': 'MYTAG', 'src': 'should be ignored'},
+            {'tag': 'MYTAG'}],
+        ['rebuildSRPM',
+            {'srpm': 'SRPM', 'build_tag': 100},
+            {'build_tag': 'MYTAG'}],
+        ['indirectionimage',
+            {'opts': {'scratch': True, 'target': 100}},
+            {'target': 'MYTARGET', 'scratch': True}],
+    ]
+
+    BAD = [
+        # method, arglist
+        ['nosuchmethod', []],
+        ['build', [1,2,3,4,5,6,7,8]],  # too many args
+        ['build', True],  # not a list
+    ]
+
+    def test_good(self):
+        for method, kwargs, expect in self.GOOD:
+            arglist = koji.encode_args(**kwargs)
+            data = kojihub.policy_data_from_task_args(method, arglist)
+            self.assertEqual(data, expect)
+
+    def test_bad(self):
+        # this function should be tolerant of bad parameters
+        for method, arglist in self.BAD:
+            data = kojihub.policy_data_from_task_args(method, arglist)
+            self.assertEqual(data, {})
+
+    def test_unexpected_exception(self):
+        arglist = mock.MagicMock()
+        arglist.__len__.side_effect = Exception('highly unlikely scenario')
+        data = kojihub.policy_data_from_task_args('build', arglist)
+        self.assertEqual(data, {})
+
+    def test_bad_target(self):
+        kwargs = {'src': 'git://foo', 'target': {}}
+        arglist = koji.encode_args(**kwargs)
+        data = kojihub.policy_data_from_task_args('build', arglist)
+        self.assertEqual(data, {'source': 'git://foo', 'target': None})
+
+    def test_bad_target2(self):
+        kwargs = {'src': 'git://foo', 'target': 100}
+        arglist = koji.encode_args(**kwargs)
+        self.lookup_build_target.return_value = None
+        data = kojihub.policy_data_from_task_args('build', arglist)
+        self.assertEqual(data, {'source': 'git://foo', 'target': None})
+
+    def test_bad_tag(self):
+        kwargs = {'tag': 100}
+        arglist = koji.encode_args(**kwargs)
+        self.lookup_tag.side_effect = koji.GenericError('...')
+        data = kojihub.policy_data_from_task_args('newRepo', arglist)
+        self.assertEqual(data, {})
+
+    def test_bad_build_tag(self):
+        kwargs = {'srpm': 'SRPM', 'build_tag': 100}
+        arglist = koji.encode_args(**kwargs)
+        self.lookup_tag.side_effect = koji.GenericError('...')
+        data = kojihub.policy_data_from_task_args('rebuildSRPM', arglist)
+        self.assertEqual(data, {})
+
+
+# the end

