Add _get_module in DBResolver and fix _record_ursine_rpms

_record_ursine_rpms needs to get each collision module's koji_tag and
then get built RPMs from that koji_tag eventually. _get_module on each
individual resolver is called to get module metadata accordingly. So,
when running a local build, module metadata is got from remote MBS, and
for a MBS instance, connected database is queried.

Signed-off-by: Chenxiong Qi <cqi@redhat.com>
This commit is contained in:
Chenxiong Qi
2018-11-01 09:32:32 +08:00
parent 476c51e1f4
commit d517a72de9
4 changed files with 49 additions and 21 deletions

View File

@@ -40,6 +40,15 @@ class DBResolver(GenericResolver):
def __init__(self, config):
self.config = config
def _get_module(self, name, stream, version, context, strict=False):
with models.make_session(self.config) as session:
mb = models.ModuleBuild.get_build_from_nsvc(
session, name, stream, version, context)
if mb is None and strict:
raise UnprocessableEntity(
'Cannot find any module builds for %s:%s' % (name, stream))
return mb.extended_json()
def get_module_modulemds(self, name, stream, version=None, context=None, strict=False,
stream_version_lte=False):
"""
@@ -57,11 +66,12 @@ class DBResolver(GenericResolver):
less than or equal the stream version computed from `stream`.
:return: List of Modulemd metadata instances matching the query
"""
if version and context:
mmd = self._get_module(name, stream, version, context, strict=strict)
return [self.extract_modulemd(mmd['modulemd'])]
with models.make_session(self.config) as session:
if version and context:
builds = [models.ModuleBuild.get_build_from_nsvc(
session, name, stream, version, context)]
elif not version and not context:
if not version and not context:
if (stream_version_lte and len(str(models.ModuleBuild.get_stream_version(
stream, right_pad=False))) >= 5):
stream_version = models.ModuleBuild.get_stream_version(stream)

View File

@@ -37,7 +37,14 @@ class GenericResolver(six.with_metaclass(ABCMeta)):
"""
_resolvers = cfg.SUPPORTED_RESOLVERS
# Resolver name. Each subclass of GenericResolver must set its own name.
backend = "generic"
# Supported resolver backends registry. Generally, resolver backend is
# registered by calling :meth:`GenericResolver.register_backend_class`.
# This is a mapping from resolver name to backend class object
# For example, {'mbs': MBSResolver}
backends = {}
@classmethod
@@ -46,13 +53,19 @@ class GenericResolver(six.with_metaclass(ABCMeta)):
@classmethod
def create(cls, config, backend=None, **extra):
"""
:param backend: a string representing resolver e.g. 'db'
"""Factory method to create a resolver object
Any additional arguments are optional extras which can be passed along
and are implementation-dependent.
:param config: MBS config object.
:type config: :class:`Config`
:kwarg str backend: resolver backend name, e.g. 'db'. If omitted,
system configuration ``resolver`` is used.
:kwarg extra: any additional arguments are optional extras which can
be passed along and are implementation-dependent.
:return: resolver backend object.
:rtype: corresponding registered resolver class.
:raises ValueError: if specified resolver backend name is not
registered.
"""
# get the appropriate resolver backend via configuration
if not backend:
backend = conf.resolver

View File

@@ -136,21 +136,27 @@ def _record_ursine_rpms(req_data):
with a list of RPMs N-E:V-R which are built for the found stream
collision modules.
"""
from module_build_service.builder import GenericBuilder
from module_build_service.builder.KojiModuleBuilder import KojiModuleBuilder
resolver = module_build_service.resolver.GenericResolver.create(conf)
# Key stream_collision_modules is not used after rpms are recorded, but
# just keep it here in case it would be helpful in the future.
modules_nsvc = req_data['stream_collision_modules']
get_built_rpms = GenericBuilder.backends[conf.system].get_built_rpms_in_module_build
built_rpms = []
koji_session = KojiModuleBuilder.get_session(conf, None)
for nsvc in modules_nsvc:
name, stream, version, context = nsvc.split(':')
mmd = resolver.get_module_modulemds(
name, stream, version, context, True)[0]
built_rpms.extend(get_built_rpms(mmd))
module = resolver._get_module(name, stream, version, context, strict=True)
rpms = koji_session.listTaggedRPMS(module['koji_tag'], latest=True)[0]
built_rpms.extend(
kobo.rpmlib.make_nvr(rpm, force_epoch=True) for rpm in rpms
)
# In case there is duplicate NEVRs, ensure every NEVR is unique in the final list.
# And, sometimes, sorted list of RPMs would be easier to read.
built_rpms = sorted(set(built_rpms))
req_data['ursine_rpms'] = built_rpms

View File

@@ -1156,11 +1156,8 @@ class TestRecordFilteredRPMs:
def teardown_method(self):
clean_database()
# For simplicity, test just queries database. So, no need to code more for
# mocking remote MBS service.
@patch.object(module_build_service.conf, 'resolver', new='db')
@patch('module_build_service.builder.KojiModuleBuilder.KojiModuleBuilder.get_session')
def test_generate_and_store_filtered_rpms(self, get_session):
@patch('koji.ClientSession')
def test_generate_and_store_filtered_rpms(self, ClientSession):
def mocklistTaggedRPMs(tag, latest):
# Result returned from listTaggedRPMs should contain two lists.
@@ -1197,9 +1194,11 @@ class TestRecordFilteredRPMs:
}
return rpms[tag]
get_session.return_value.listTaggedRPMS.side_effect = mocklistTaggedRPMs
ClientSession.return_value.listTaggedRPMS.side_effect = mocklistTaggedRPMs
with patch.object(conf, 'resolver', new='db'):
mmd = module_build_service.utils.submit.record_filtered_rpms(self.mmd)
mmd = module_build_service.utils.submit.record_filtered_rpms(self.mmd)
xmd_mbs = mmd.get_xmd()['mbs'].unpack()
assert ['pkg-1.0-1.fc28'] == xmd_mbs['buildrequires']['modulea']['filtered_rpms']