From bfd3034141a4648d7408a921075970c28692858d Mon Sep 17 00:00:00 2001 From: Tomas Kopecek Date: Oct 05 2020 10:36:12 +0000 Subject: PR#2493: getBuildConfig returns inheritance history Merges #2493 https://pagure.io/koji/pull-request/2493 Fixes: #1870 https://pagure.io/koji/issue/1870 a new API to get tag extra with / without inheritance --- diff --git a/cli/koji_cli/commands.py b/cli/koji_cli/commands.py index b5b5a4c..bc09cc2 100644 --- a/cli/koji_cli/commands.py +++ b/cli/koji_cli/commands.py @@ -4866,10 +4866,10 @@ def anon_handle_taginfo(goptions, session, args): tags = [] for tag in args: - info = session.getTag(tag, **event_opts) + info = session.getBuildConfig(tag, **event_opts) if info is None: try: - info = session.getTag(int(tag), **event_opts) + info = session.getBuildConfig(int(tag), **event_opts) except ValueError: info = None if info is None: @@ -4896,7 +4896,10 @@ def anon_handle_taginfo(goptions, session, args): if 'extra' in info: print("Tag options:") for key in sorted(info['extra'].keys()): - print(" %s : %s" % (key, pprint.pformat(info['extra'][key]))) + line = " %s : %s" % (key, pprint.pformat(info['extra'][key])) + if key in info.get('config_inheritance', {}).get('extra', []): + line = "%-30s [%s]" % (line, info['config_inheritance']['extra'][key]['name']) + print(line) dest_targets = session.getBuildTargets(destTagID=info['id'], **event_opts) build_targets = session.getBuildTargets(buildTagID=info['id'], **event_opts) repos = {} diff --git a/hub/kojihub.py b/hub/kojihub.py index aa18a8d..c142af5 100644 --- a/hub/kojihub.py +++ b/hub/kojihub.py @@ -11949,6 +11949,7 @@ class RootExports(object): def getBuildConfig(self, tag, event=None): """Return build configuration associated with a tag""" taginfo = get_tag(tag, strict=True, event=event, blocked=True) + taginfo['config_inheritance'] = {'extra': {}, 'arches': None} order = readFullInheritance(taginfo['id'], event=event) # follow inheritance for arches and extra for link in order: @@ -11957,9 +11958,11 @@ class RootExports(object): ancestor = get_tag(link['parent_id'], strict=True, event=event, blocked=True) if taginfo['arches'] is None and ancestor['arches'] is not None: taginfo['arches'] = ancestor['arches'] + taginfo['config_inheritance']['arches'] = dslice(ancestor, ('id', 'name')) for key in ancestor['extra']: if key not in taginfo['extra']: taginfo['extra'][key] = ancestor['extra'][key] + taginfo['config_inheritance']['extra'][key] = dslice(ancestor, ('id', 'name')) # cleanup extras by blocked for k, v in list(taginfo['extra'].items()): if v[0]: diff --git a/tests/test_hub/test_get_build_config.py b/tests/test_hub/test_get_build_config.py new file mode 100644 index 0000000..f3e6eb3 --- /dev/null +++ b/tests/test_hub/test_get_build_config.py @@ -0,0 +1,126 @@ +import mock +import unittest + +import kojihub + + +class TestGetBuildConfig(unittest.TestCase): + + @mock.patch('kojihub.readFullInheritance') + @mock.patch('kojihub.get_tag') + def test_simple_tag(self, get_tag, readFullInheritance): + tag = 'tag_name' + get_tag.return_value = {'id': 123, 'name': tag, 'extra': {}} + readFullInheritance.return_value = [] + + taginfo = kojihub.RootExports().getBuildConfig(tag) + + get_tag.assert_called_with(tag, event=None, strict=True) + readFullInheritance.assert_called_with(123, event=None) + + self.assertEqual(taginfo, { + 'id': 123, + 'name': tag, + 'extra': {}, + 'config_inheritance': {'extra': {}, 'arches': None}, + }) + + @mock.patch('kojihub.readFullInheritance') + @mock.patch('kojihub.get_tag') + def test_basic_inherited(self, get_tag, readFullInheritance): + tag = 'tag_name' + get_tag.side_effect = [ + { + 'id': 123, + 'name': tag, + 'extra': {}, + 'arches': None, + }, + { + 'id': 1234, + 'name': 'parent', + 'extra': {'value': 'inherited'}, + 'arches': 'x86_64', + }, + ] + readFullInheritance.return_value = [ + { + 'child_id': 123, + 'currdepth': 1, + 'filter': [], + 'intransitive': False, + 'maxdepth': None, + 'name': tag, + 'nextdepth': None, + 'noconfig': False, + 'parent_id': 1234, + 'pkg_filter': '', + 'priority': 0 + } + ] + + taginfo = kojihub.RootExports().getBuildConfig(tag, event=1111) + + get_tag.assert_has_calls([ + mock.call(tag, event=1111, strict=True), + mock.call(1234, event=1111, strict=True), + ]) + readFullInheritance.assert_called_with(123, event=1111) + + self.assertEqual(taginfo, { + 'arches': 'x86_64', + 'extra': {'value': 'inherited'}, + 'config_inheritance': { + 'arches': {'id': 1234, 'name': 'parent'}, + 'extra' : {'value': {'id': 1234, 'name': 'parent'}} + }, + 'id': 123, + 'name': 'tag_name' + }) + + @mock.patch('kojihub.readFullInheritance') + @mock.patch('kojihub.get_tag') + def test_inherited_noconfig(self, get_tag, readFullInheritance): + tag = 'tag_name' + get_tag.side_effect = [ + { + 'id': 123, + 'name': tag, + 'extra': {}, + 'arches': None, + }, + { + 'id': 1234, + 'name': 'parent', + 'extra': {'value': 'inherited'}, + 'arches': 'x86_64', + }, + ] + readFullInheritance.return_value = [ + { + 'child_id': 123, + 'currdepth': 1, + 'filter': [], + 'intransitive': False, + 'maxdepth': None, + 'name': tag, + 'nextdepth': None, + 'noconfig': True, + 'parent_id': 1234, + 'pkg_filter': '', + 'priority': 0 + } + ] + + taginfo = kojihub.RootExports().getBuildConfig(tag, event=1111) + + get_tag.assert_called_once_with(tag, event=1111, strict=True) + readFullInheritance.assert_called_with(123, event=1111) + + self.assertEqual(taginfo, { + 'arches': None, + 'extra': {}, + 'config_inheritance': {'extra': {}, 'arches': None}, + 'id': 123, + 'name': 'tag_name' + })