def test_mark_handled_even_if_no_modules_in_ursine_content( self, get_modulemds_from_ursine_content): xmd = { "mbs": { "buildrequires": { "modulea": { "stream": "master" }, "platform": { "stream": "master", "koji_tag": "module-rhel-8.0-build" }, } } } fake_mmd = make_module("name1:s:2020:c", xmd=xmd) expected_xmd = fake_mmd.get_xmd() get_modulemds_from_ursine_content.return_value = [] with patch.object(ursine, "log") as log: ursine.handle_stream_collision_modules(fake_mmd) assert 2 == log.info.call_count # Ensure stream_collision_modules is set. expected_xmd["mbs"]["buildrequires"]["platform"][ "stream_collision_modules"] = "" expected_xmd["mbs"]["buildrequires"]["platform"]["ursine_rpms"] = "" assert expected_xmd == fake_mmd.get_xmd()
def test_nothing_changed_if_no_base_module_is_in_buildrequires( self, find_stream_collision_modules): xmd = {"mbs": {"buildrequires": {"modulea": {"stream": "master"}}}} fake_mmd = make_module("name1:s:2020:c", xmd=xmd) original_xmd = fake_mmd.get_xmd() with patch.object(ursine, "log") as log: ursine.handle_stream_collision_modules(fake_mmd) assert 2 == log.info.call_count find_stream_collision_modules.assert_not_called() assert original_xmd == fake_mmd.get_xmd()
def test_add_collision_modules(self, ClientSession, resolver_create, get_modulemds_from_ursine_content): xmd = { "mbs": { "buildrequires": { "modulea": { "stream": "master" }, "foo": { "stream": "1" }, "bar": { "stream": "2" }, "platform": { "stream": "master", "koji_tag": "module-rhel-8.0-build" }, "project-platform": { "stream": "master", "koji_tag": "module-project-1.0-build", }, } } } fake_mmd = make_module("name1:s:2020:c", xmd=xmd) def mock_get_ursine_modulemds(koji_tag): if koji_tag == "module-rhel-8.0-build": return [ # This is the one make_module("modulea:10:20180813041838:5ea3b708"), make_module("moduleb:1.0:20180113042038:6ea3b105"), ] if koji_tag == "module-project-1.0-build": return [ # Both of them are the collided modules make_module("bar:6:20181013041838:817fa3a8"), make_module("foo:2:20180113041838:95f078a1"), ] get_modulemds_from_ursine_content.side_effect = mock_get_ursine_modulemds # Mock for finding out built rpms def mock_get_module(name, stream, version, context, strict=True): return { "modulea:10:20180813041838:5ea3b708": { "koji_tag": "module-modulea-10-20180813041838-5ea3b708" }, "bar:6:20181013041838:817fa3a8": { "koji_tag": "module-bar-6-20181013041838-817fa3a8" }, "foo:2:20180113041838:95f078a1": { "koji_tag": "module-foo-2-20180113041838-95f078a1" }, }["{}:{}:{}:{}".format(name, stream, version, context)] resolver = resolver_create.return_value resolver.get_module.side_effect = mock_get_module def mock_listTaggedRPMS(tag, latest): return { "module-modulea-10-20180813041838-5ea3b708": [[{ "name": "pkg1", "version": "1.0", "release": "1.fc28", "epoch": None }]], "module-bar-6-20181013041838-817fa3a8": [[{ "name": "pkg2", "version": "2.0", "release": "1.fc28", "epoch": None }]], "module-foo-2-20180113041838-95f078a1": [[{ "name": "pkg3", "version": "3.0", "release": "1.fc28", "epoch": None }]], }[tag] koji_session = ClientSession.return_value koji_session.listTaggedRPMS.side_effect = mock_listTaggedRPMS ursine.handle_stream_collision_modules(fake_mmd) xmd = fake_mmd.get_xmd() buildrequires = xmd["mbs"]["buildrequires"] modules = buildrequires["platform"]["stream_collision_modules"] assert ["modulea:10:20180813041838:5ea3b708"] == modules assert ["pkg1-0:1.0-1.fc28" ] == buildrequires["platform"]["ursine_rpms"] modules = sorted( buildrequires["project-platform"]["stream_collision_modules"]) expected_modules = [ "bar:6:20181013041838:817fa3a8", "foo:2:20180113041838:95f078a1" ] assert expected_modules == modules rpms = sorted(buildrequires["project-platform"]["ursine_rpms"]) assert ["pkg2-0:2.0-1.fc28", "pkg3-0:3.0-1.fc28"] == rpms
def init(msg_id, module_build_id, module_build_state): """Called whenever a module enters the 'init' state. :param str msg_id: the original id of the message being handled, which is received from message bus. :param int module_build_id: the module build id. :param int module_build_state: the module build state. """ build = models.ModuleBuild.get_by_id(db_session, module_build_id) state_init = models.BUILD_STATES["init"] if module_build_state == state_init and build.state != state_init: log.warning("Module build %r has moved to %s state already.", build, models.INVERSE_BUILD_STATES[build.state]) log.warning( "Ignore this message %s. Is there something wrong with the frontend" " that sends duplicate messages?", msg_id) return # for MockModuleBuilder, set build logs dir to mock results dir # before build_logs start if conf.system == "mock": build_tag_name = generate_module_build_koji_tag(build) mock_resultsdir = os.path.join(conf.mock_resultsdir, build_tag_name) if not os.path.exists(mock_resultsdir): os.makedirs(mock_resultsdir) build_logs.build_logs_dir = mock_resultsdir build_logs.start(db_session, build) log.info("Start to handle %s which is in init state.", build.mmd().get_nsvc()) error_msg = "" failure_reason = "unspec" try: mmd = build.mmd() record_module_build_arches(mmd, build) arches = [arch.name for arch in build.arches] defaults_added = add_default_modules(mmd) # Get map of packages that have SRPM overrides srpm_overrides = get_module_srpm_overrides(build) # Format the modulemd by putting in defaults and replacing streams that # are branches with commit hashes format_mmd(mmd, build.scmurl, build, db_session, srpm_overrides) record_component_builds(mmd, build) # The ursine.handle_stream_collision_modules is Koji specific. # It is also run only when Ursa Prime is not enabled for the base # module (`if not defaults_added`). if conf.system in ["koji", "test"] and not defaults_added: handle_stream_collision_modules(mmd) # Sets xmd["mbs"]["ursine_rpms"] with RPMs from the buildrequired base modules which # conflict with the RPMs from other buildrequired modules. This is done to prefer modular # RPMs over base module RPMs even if their NVR is lower. if conf.system in ("koji", "test"): handle_collisions_with_base_module_rpms(mmd, arches) else: log.warning( "The necessary conflicts could not be generated due to RHBZ#1693683. " "Some RPMs from the base modules (%s) may end up being used over modular RPMs. " "This may result in different behavior than a production build.", ", ".join(conf.base_module_names)) mmd = record_filtered_rpms(mmd) build.modulemd = mmd_to_str(mmd) build.transition(db_session, conf, models.BUILD_STATES["wait"]) # Catch custom exceptions that we can expose to the user except (UnprocessableEntity, Forbidden, ValidationError, RuntimeError) as e: log.exception(str(e)) error_msg = str(e) failure_reason = "user" except (xmlrpclib.ProtocolError, koji.GenericError) as e: log.exception(str(e)) error_msg = 'Koji communication error: "{0}"'.format(str(e)) failure_reason = "infra" except Exception as e: log.exception(str(e)) error_msg = "An unknown error occurred while validating the modulemd" failure_reason = "user" else: db_session.add(build) db_session.commit() finally: if error_msg: # Rollback changes underway db_session.rollback() build.transition( db_session, conf, models.BUILD_STATES["failed"], state_reason=error_msg, failure_type=failure_reason, ) db_session.commit()