diff --git a/module_build_service/resolver/KojiResolver.py b/module_build_service/resolver/KojiResolver.py index 48faeea5..0fe35e42 100644 --- a/module_build_service/resolver/KojiResolver.py +++ b/module_build_service/resolver/KojiResolver.py @@ -59,15 +59,15 @@ class KojiResolver(DBResolver): return result - def get_buildrequired_modules(self, name, stream, base_module_mmd): + def get_buildrequired_koji_builds(self, name, stream, base_module_mmd): """ - Returns ModuleBuild objects of all module builds with `name` and `stream` which are tagged - in the Koji tag defined in `base_module_mmd`. + Returns list of Koji build dicts of all module builds with `name` and `stream` which are + tagged in the Koji tag defined in `base_module_mmd`. :param str name: Name of module to return. :param str stream: Stream of module to return. :param Modulemd base_module_mmd: Base module metadata. - :return list: List of ModuleBuilds. + :return list: List of Koji build dicts. """ # Get the `koji_tag_with_modules`. If the `koji_tag_with_modules` is not configured for # the base module, fallback to DBResolver. @@ -121,6 +121,19 @@ class KojiResolver(DBResolver): ns_builds, key=lambda x: x["release"].split(".")[0]): latest_builds += list(nsv_builds) break + return latest_builds + + def get_buildrequired_modules(self, name, stream, base_module_mmd): + """ + Returns ModuleBuild objects of all module builds with `name` and `stream` which are tagged + in the Koji tag defined in `base_module_mmd`. + + :param str name: Name of module to return. + :param str stream: Stream of module to return. + :param Modulemd base_module_mmd: Base module metadata. + :return list: List of ModuleBuilds. + """ + latest_builds = self.get_buildrequired_koji_builds(name, stream, base_module_mmd) # For each latest module build, find the matching ModuleBuild and store it into `ret`. ret = [] @@ -129,6 +142,7 @@ class KojiResolver(DBResolver): module = models.ModuleBuild.get_build_from_nsvc( self.db_session, name, stream, version, context) if not module: + tag = base_module_mmd.get_xmd().get("mbs", {}).get("koji_tag_with_modules") raise ValueError( "Module %s is tagged in the %s Koji tag, but does not exist " "in MBS DB." % (":".join([name, stream, version, context]), tag)) diff --git a/module_build_service/resolver/MBSResolver.py b/module_build_service/resolver/MBSResolver.py index 2694f522..e35ae99d 100644 --- a/module_build_service/resolver/MBSResolver.py +++ b/module_build_service/resolver/MBSResolver.py @@ -8,14 +8,14 @@ import kobo.rpmlib from module_build_service import conf from module_build_service import models from module_build_service.errors import UnprocessableEntity -from module_build_service.resolver.base import GenericResolver +from module_build_service.resolver.KojiResolver import KojiResolver from module_build_service.utils.general import import_mmd, load_mmd from module_build_service.utils.request_utils import requests_session log = logging.getLogger() -class MBSResolver(GenericResolver): +class MBSResolver(KojiResolver): backend = "mbs" @@ -234,7 +234,7 @@ class MBSResolver(GenericResolver): name, stream, stream_version_lte=stream_version_lte, virtual_streams=virtual_streams, states=states) - def get_buildrequired_modulemds(self, name, stream, base_module_nsvc): + def get_buildrequired_modulemds(self, name, stream, base_module_mmd): """ Returns modulemd metadata of all module builds with `name` and `stream` buildrequiring base module defined by `base_module_nsvc` NSVC. @@ -252,8 +252,21 @@ class MBSResolver(GenericResolver): if local_modules: return [m.mmd() for m in local_modules] - modules = self._get_modules(name, stream, strict=False, base_module_br=base_module_nsvc) - return [load_mmd(module["modulemd"]) for module in modules] + tag = base_module_mmd.get_xmd().get("mbs", {}).get("koji_tag_with_modules") + if tag: + # In case KojiResolver is enabled for this base module, ask Koji for list of + # Koji builds and then get the modulemd file from the MBS running in infra. + koji_builds = self.get_buildrequired_koji_builds(name, stream, base_module_mmd) + ret = [] + for build in koji_builds: + version, context = build["release"].split(".") + ret += self.get_module_modulemds(name, stream, version, context, strict=True) + + return ret + else: + modules = self._get_modules( + name, stream, strict=False, base_module_br=base_module_mmd.get_nsvc()) + return [load_mmd(module["modulemd"]) for module in modules] def resolve_profiles(self, mmd, keys): """ diff --git a/tests/test_resolver/test_mbs.py b/tests/test_resolver/test_mbs.py index b76f40ab..4982ca12 100644 --- a/tests/test_resolver/test_mbs.py +++ b/tests/test_resolver/test_mbs.py @@ -341,7 +341,8 @@ class TestMBSModule: request_session.get.return_value = Mock(ok=True) request_session.get.return_value.json.return_value = {"items": [], "meta": {"next": None}} - result = resolver.get_buildrequired_modulemds("nodejs", "10", "platform:el8:1:00000000") + platform = db_session.query(module_build_service.models.ModuleBuild).filter_by(id=1).one() + result = resolver.get_buildrequired_modulemds("nodejs", "10", platform.mmd()) assert [] == result @patch("module_build_service.resolver.MBSResolver.requests_session") @@ -372,7 +373,8 @@ class TestMBSModule: "meta": {"next": None}, } - result = resolver.get_buildrequired_modulemds("nodejs", "10", "platform:el8:1:00000000") + platform = db_session.query(module_build_service.models.ModuleBuild).filter_by(id=1).one() + result = resolver.get_buildrequired_modulemds("nodejs", "10", platform.mmd()) assert 1 == len(result) mmd = result[0] @@ -458,3 +460,49 @@ class TestMBSModule: assert "master" == mmd.get_stream_name() assert 20170816080816 == mmd.get_version() assert "321" == mmd.get_context() + + @patch("module_build_service.resolver.MBSResolver.requests_session") + def test_get_buildrequired_modulemds_kojiresolver(self, mock_session, db_session): + """ + Test that MBSResolver uses KojiResolver as input when KojiResolver is enabled for + the base module. + """ + mock_session.get.return_value = Mock(ok=True) + mock_session.get.return_value.json.return_value = { + "items": [ + { + "name": "nodejs", + "stream": "10", + "version": 2, + "context": "c1", + "modulemd": mmd_to_str( + tests.make_module("nodejs:10:2:c1"), + ), + }, + ], + "meta": {"next": None}, + } + + resolver = mbs_resolver.GenericResolver.create(db_session, tests.conf, backend="mbs") + + platform = db_session.query( + module_build_service.models.ModuleBuild).filter_by(id=1).one() + platform_mmd = platform.mmd() + platform_xmd = platform_mmd.get_xmd() + platform_xmd["mbs"]["koji_tag_with_modules"] = "module-f29-build" + platform_mmd.set_xmd(platform_xmd) + + with patch.object( + resolver, "get_buildrequired_koji_builds") as get_buildrequired_koji_builds: + get_buildrequired_koji_builds.return_value = [{ + "build_id": 124, "name": "nodejs", "version": "10", + "release": "2.c1", "tag_name": "foo-test"}] + result = resolver.get_buildrequired_modulemds("nodejs", "10", platform_mmd) + get_buildrequired_koji_builds.assert_called_once() + + assert 1 == len(result) + mmd = result[0] + assert "nodejs" == mmd.get_module_name() + assert "10" == mmd.get_stream_name() + assert 2 == mmd.get_version() + assert "c1" == mmd.get_context()