From bc4a019e7d998f4c1b54dd0050fd56caec97119d Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Thu, 4 Apr 2019 15:52:46 +0200 Subject: [PATCH] Allow getting the latest stream of base module. If base module name:stream is not found, consider `stream` as virtual stream and return the latest (the one with highest stream_version) base module with that virtual stream. --- module_build_service/utils/mse.py | 47 ++++++++++++++++++++++++++++-- tests/test_utils/test_utils_mse.py | 25 ++++++++++++++++ 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/module_build_service/utils/mse.py b/module_build_service/utils/mse.py index 0a75db1f..3d80627c 100644 --- a/module_build_service/utils/mse.py +++ b/module_build_service/utils/mse.py @@ -188,6 +188,39 @@ def _get_mmds_from_requires(requires, mmds, recursive=False, return mmds +def _get_latest_base_module_mmd_with_virtual_stream(name, virtual_stream): + """ + Returns the Modulemd instance of Module build with highest stream_version, + with name `name`, and containing the virtual stream `virtual_stream` in its + xmd["mbs"]["virtual_streams"] section + + :param str name: Name of a module to return. + :param str virtual_stream: Name of virtual stream which must be included in + the virtual_streams xmd section. + :return Modulemd: Modulemd instance of such module with highest stream_version. + """ + with models.make_session(conf) as session: + builds = models.ModuleBuild.get_last_build_in_all_streams(session, name) + if not builds: + return None + + build_to_return = None + for build in builds: + mmd = build.mmd() + xmd = mmd.get_xmd() + if "mbs" not in xmd.keys() or "virtual_streams" not in xmd["mbs"].keys(): + continue + + virtual_streams = xmd["mbs"]["virtual_streams"] + if virtual_stream not in virtual_streams: + continue + + if not build_to_return or build_to_return.stream_version < build.stream_version: + build_to_return = build + + return build_to_return.mmd() if build_to_return else None + + def _get_base_module_mmds(mmd): """ Returns list of MMDs of base modules buildrequired by `mmd` including the compatible @@ -226,8 +259,18 @@ def _get_base_module_mmds(mmd): # zero or one module build. mmds = resolver.get_module_modulemds(name, stream) if not mmds: - continue - stream_mmd = mmds[0] + # The given name:stream base module does not exist. It might be the case + # when user requests name:virtual_stream (like platform:f29). In this case, + # we need to find the latest (the one with highest stream_version) base + # module. + stream_mmd = _get_latest_base_module_mmd_with_virtual_stream(name, stream) + if not stream_mmd: + continue + # The `stream` does not exist and we are going to use the stream name of + # the latest base module with given virtual stream, so override it here. + stream = stream_mmd.get_stream() + else: + stream_mmd = mmds[0] # In case there are no virtual_streams in the buildrequired name:stream, # it is clear that there are no compatible streams, so return just this diff --git a/tests/test_utils/test_utils_mse.py b/tests/test_utils/test_utils_mse.py index 49bc78e5..2e55487d 100644 --- a/tests/test_utils/test_utils_mse.py +++ b/tests/test_utils/test_utils_mse.py @@ -403,3 +403,28 @@ class TestUtilsModuleStreamExpansion: for mmd_ in mmds: actual.add('{}:{}'.format(mmd_.get_name(), mmd_.get_stream())) assert actual == expected + + def test__get_base_module_mmds_virtual_streams_latest_stream_version(self): + init_data(data_size=1, multiple_stream_versions=True) + mmd = module_build_service.utils.load_mmd( + os.path.join(base_dir, 'staged_data', 'testmodule_v2.yaml'), True) + deps = mmd.get_dependencies() + brs = deps[0].get_buildrequires() + brs['platform'].set(['f35']) + deps[0].set_buildrequires(brs) + mmd.set_dependencies(deps) + + make_module("platform:f35.1.0:1:1", {}, {}, virtual_streams=["f35"]) + make_module("platform:f35.2.0:1:1", {}, {}, virtual_streams=["f35"]) + make_module("platform:f35.0.0:1:1", {}, {}, virtual_streams=["f35"]) + + mmds = module_build_service.utils.mse._get_base_module_mmds(mmd) + expected = set(['platform:f35.0.0', 'platform:f35.1.0', 'platform:f35.2.0']) + + # Verify no duplicates were returned before doing set operations + assert len(mmds) == len(expected) + # Verify the expected ones were returned + actual = set() + for mmd_ in mmds: + actual.add('{}:{}'.format(mmd_.get_name(), mmd_.get_stream())) + assert actual == expected