mirror of
https://pagure.io/fm-orchestrator.git
synced 2026-11-03 22:05:11 +08:00
Init event handler handles module stream collision
Fixes: FACTORY-3616 Signed-off-by: Chenxiong Qi <cqi@redhat.com>
This commit is contained in:
@@ -35,6 +35,7 @@ from module_build_service.utils import (
|
||||
generate_koji_tag,
|
||||
record_filtered_rpms)
|
||||
from module_build_service.errors import UnprocessableEntity, Forbidden, ValidationError
|
||||
from module_build_service.utils.ursine import handle_stream_collision_modules
|
||||
|
||||
from requests.exceptions import ConnectionError
|
||||
|
||||
@@ -152,6 +153,7 @@ def init(config, session, msg):
|
||||
try:
|
||||
mmd = build.mmd()
|
||||
record_component_builds(mmd, build, session=session)
|
||||
handle_stream_collision_modules(mmd)
|
||||
mmd = record_filtered_rpms(mmd)
|
||||
build.modulemd = mmd.dumps()
|
||||
build.transition(conf, models.BUILD_STATES["wait"])
|
||||
|
||||
@@ -41,8 +41,8 @@ from module_build_service import conf, db, log, models, Modulemd
|
||||
from module_build_service.errors import (
|
||||
ValidationError, UnprocessableEntity, Forbidden, Conflict)
|
||||
from module_build_service import glib
|
||||
from module_build_service.resolver import GenericResolver
|
||||
from .mse import generate_expanded_mmds
|
||||
from module_build_service.utils.ursine import record_stream_collision_modules
|
||||
|
||||
|
||||
def record_filtered_rpms(mmd):
|
||||
@@ -53,19 +53,41 @@ def record_filtered_rpms(mmd):
|
||||
* Reads the mmd["xmd"]["buildrequires"] and extends it with "filtered_rpms"
|
||||
list containing the NVRs of filtered RPMs in a buildrequired module.
|
||||
|
||||
* Every base module could have stream collision modules, whose built RPMs
|
||||
should be filtered out to avoid collision. The filtered out RPMs will be
|
||||
stored into the base module as well.
|
||||
|
||||
:param Modulemd mmd: Modulemd that will be built next.
|
||||
:rtype: Modulemd.Module
|
||||
:return: Modulemd extended with the "filtered_rpms" in XMD section.
|
||||
"""
|
||||
# Imported here to allow import of utils in GenericBuilder.
|
||||
from module_build_service.builder import GenericBuilder
|
||||
|
||||
resolver = GenericResolver.create(conf)
|
||||
builder = GenericBuilder.backends[conf.system]
|
||||
|
||||
new_buildrequires = {}
|
||||
for req_name, req_data in mmd.get_xmd()["mbs"]["buildrequires"].items():
|
||||
_record_filtered_rpms(req_name, req_data)
|
||||
if req_name in conf.base_module_names and 'stream_collision_modules' in req_data:
|
||||
_record_ursine_rpms(req_data)
|
||||
# In case this is module resubmit or local build, the filtered_rpms
|
||||
# will already be there, so there is no point in generating them again.
|
||||
if "filtered_rpms" in req_data:
|
||||
continue
|
||||
|
||||
# We can just get the first modulemd data from result right here thanks to
|
||||
# strict=True, so in case the module cannot be found, get_module_modulemds
|
||||
# raises an exception.
|
||||
req_mmd = resolver.get_module_modulemds(
|
||||
req_name, req_data["stream"], req_data["version"], req_data["context"], True)[0]
|
||||
|
||||
# Find out the particular NVR of filtered packages
|
||||
filtered_rpms = []
|
||||
rpm_filter = req_mmd.get_rpm_filter()
|
||||
if rpm_filter and rpm_filter.get():
|
||||
rpm_filter = rpm_filter.get()
|
||||
built_nvrs = builder.get_built_rpms_in_module_build(req_mmd)
|
||||
for nvr in built_nvrs:
|
||||
parsed_nvr = kobo.rpmlib.parse_nvr(nvr)
|
||||
if parsed_nvr["name"] in rpm_filter:
|
||||
filtered_rpms.append(nvr)
|
||||
req_data["filtered_rpms"] = filtered_rpms
|
||||
|
||||
new_buildrequires[req_name] = req_data
|
||||
|
||||
# Replace the old buildrequires with new ones.
|
||||
@@ -75,91 +97,6 @@ def record_filtered_rpms(mmd):
|
||||
return mmd
|
||||
|
||||
|
||||
def _record_filtered_rpms(req_name, req_data):
|
||||
"""Store filtered RPMs by a buildrequire module
|
||||
|
||||
This methods looks for key ``filtered_rpms`` in a buildrequired module's
|
||||
metadata. If there is, nothing is done, just keep it unchanged, which case
|
||||
could be a module is resubmitted or a local build.
|
||||
|
||||
Otherwise, ``_record_filtered_rpms`` will get module's RPMs listed in
|
||||
filter section, then store them with the key into metadata in place.
|
||||
|
||||
:param str req_name: name of a buildrequired module.
|
||||
:param dict req_data: a mapping containing metadata of the buildrequired
|
||||
module. A pair of ``req_name`` and ``req_data`` is usually the one of
|
||||
xmd.mbs.buildrequires, which are stored during the module stream
|
||||
expansion process. At least, ``req_data`` must have keys stream,
|
||||
version and context. Key ``filtered_rpms`` will be added as a list of
|
||||
RPMs N-E:V-R.
|
||||
"""
|
||||
# Imported here to allow import of utils in GenericBuilder.
|
||||
from module_build_service.builder import GenericBuilder
|
||||
|
||||
# In case this is module resubmit or local build, the filtered_rpms
|
||||
# will already be there, so there is no point in generating them again.
|
||||
if "filtered_rpms" in req_data:
|
||||
return
|
||||
|
||||
resolver = module_build_service.resolver.GenericResolver.create(conf)
|
||||
|
||||
# We can just get the first modulemd data from result right here thanks to
|
||||
# strict=True, so in case the module cannot be found, get_module_modulemds
|
||||
# raises an exception.
|
||||
req_mmd = resolver.get_module_modulemds(
|
||||
req_name, req_data["stream"], req_data["version"], req_data["context"], True)[0]
|
||||
|
||||
# Find out the particular NVR of filtered packages
|
||||
filtered_rpms = []
|
||||
rpm_filter = req_mmd.get_rpm_filter()
|
||||
if rpm_filter and rpm_filter.get():
|
||||
rpm_filter = rpm_filter.get()
|
||||
built_nvrs = GenericBuilder.backends[conf.system].get_built_rpms_in_module_build(
|
||||
req_mmd)
|
||||
for nvr in built_nvrs:
|
||||
parsed_nvr = kobo.rpmlib.parse_nvr(nvr)
|
||||
if parsed_nvr["name"] in rpm_filter:
|
||||
filtered_rpms.append(nvr)
|
||||
req_data["filtered_rpms"] = filtered_rpms
|
||||
|
||||
|
||||
def _record_ursine_rpms(req_data):
|
||||
"""Store ursine RPMs
|
||||
|
||||
This method handles key ``stream_collision_modules`` from a buildrequired
|
||||
module's metadata to find out all built RPMs and then store them with a new
|
||||
key ``ursine_rpms`` into metadata in place.
|
||||
|
||||
:param dict req_data: a mapping containing metadata of the buildrequired
|
||||
module. At least, ``req_data`` must have keys stream, version and
|
||||
context. As a result, a new key ``filtered_ursine_rpms`` will be added
|
||||
with a list of RPMs N-E:V-R which are built for the found stream
|
||||
collision modules.
|
||||
"""
|
||||
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']
|
||||
built_rpms = []
|
||||
|
||||
koji_session = KojiModuleBuilder.get_session(conf, None)
|
||||
|
||||
for nsvc in modules_nsvc:
|
||||
name, stream, version, context = nsvc.split(':')
|
||||
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
|
||||
|
||||
|
||||
def _scm_get_latest(pkg):
|
||||
try:
|
||||
# If the modulemd specifies that the 'f25' branch is what
|
||||
@@ -587,9 +524,6 @@ def submit_module_build(username, url, mmd, optional_params=None):
|
||||
module.transition(conf, transition_to, "Resubmitted by %s" % username)
|
||||
log.info("Resumed existing module build in previous state %s" % module.state)
|
||||
else:
|
||||
log.info('Start to handle potential module stream collision.')
|
||||
record_stream_collision_modules(mmd)
|
||||
|
||||
log.debug('Creating new module build')
|
||||
module = models.ModuleBuild.create(
|
||||
db.session,
|
||||
|
||||
@@ -184,10 +184,11 @@ def find_stream_collision_modules(buildrequired_modules, koji_tag):
|
||||
return collision_modules
|
||||
|
||||
|
||||
def record_stream_collision_modules(mmd):
|
||||
def handle_stream_collision_modules(mmd):
|
||||
"""
|
||||
Find out modules from ursine content and record those that are buildrequire
|
||||
module but have different stream.
|
||||
module but have different stream. And finally, record built RPMs of these
|
||||
found modules for later use to exclude them from buildroot.
|
||||
|
||||
Note that this depends on the result of module stream expansion.
|
||||
|
||||
@@ -205,6 +206,7 @@ def record_stream_collision_modules(mmd):
|
||||
:param mmd: a module's metadata which will be built.
|
||||
:type mmd: Modulemd.Module
|
||||
"""
|
||||
log.info('Start to find out stream collision modules.')
|
||||
unpacked_xmd = glib.from_variant_dict(mmd.get_xmd())
|
||||
buildrequires = unpacked_xmd['mbs']['buildrequires']
|
||||
|
||||
@@ -214,15 +216,65 @@ def record_stream_collision_modules(mmd):
|
||||
log.info(
|
||||
'Base module %s is not a buildrequire of module %s. '
|
||||
'Skip handling module stream collision for this base module.',
|
||||
mmd.get_name())
|
||||
module_name, mmd.get_name())
|
||||
continue
|
||||
|
||||
# Module stream collision is handled only for newly created module
|
||||
# build. However, if a build is resumed and restarted from init
|
||||
# state, we have to ensure stream collision is not handled twice for a
|
||||
# base module.
|
||||
# Just check the existence, and following code ensures this key exists
|
||||
# even if no stream collision module is found.
|
||||
if ('stream_collision_modules' in base_module_info and
|
||||
'ursine_rpms' in base_module_info):
|
||||
log.debug('Base module %s has stream collision modules and ursine '
|
||||
'rpms. Skip to handle stream collision again for it.',
|
||||
module_name)
|
||||
continue
|
||||
|
||||
modules_nsvc = find_stream_collision_modules(
|
||||
buildrequires, base_module_info['koji_tag'])
|
||||
|
||||
if modules_nsvc:
|
||||
# Save modules NSVC for later use in subsequent event handlers to
|
||||
# log readable messages.
|
||||
base_module_info['stream_collision_modules'] = modules_nsvc
|
||||
base_module_info['ursine_rpms'] = find_module_built_rpms(modules_nsvc)
|
||||
else:
|
||||
log.info('No stream collision module is found against base module %s.',
|
||||
module_name)
|
||||
# Always set in order to mark it as handled already.
|
||||
base_module_info['stream_collision_modules'] = None
|
||||
base_module_info['ursine_rpms'] = None
|
||||
|
||||
mmd.set_xmd(glib.dict_values(unpacked_xmd))
|
||||
|
||||
|
||||
def find_module_built_rpms(modules_nsvc):
|
||||
"""Find out built RPMs of given modules
|
||||
|
||||
:param modules_nsvc: a list of modules' NSVC to find out built RPMs for
|
||||
each of them.
|
||||
:type modules_nsvc: list[str]
|
||||
:return: a sorted list of RPMs, each of them is represented as NEVR.
|
||||
:rtype: list[str]
|
||||
"""
|
||||
import kobo.rpmlib
|
||||
from module_build_service.resolver import GenericResolver
|
||||
from module_build_service.builder.KojiModuleBuilder import KojiModuleBuilder
|
||||
resolver = GenericResolver.create(conf)
|
||||
|
||||
built_rpms = []
|
||||
koji_session = KojiModuleBuilder.get_session(conf, None)
|
||||
|
||||
for nsvc in modules_nsvc:
|
||||
name, stream, version, context = nsvc.split(':')
|
||||
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.
|
||||
return sorted(set(built_rpms))
|
||||
|
||||
@@ -292,7 +292,7 @@ def cleanup_moksha():
|
||||
import moksha.hub.reactor # noqa
|
||||
|
||||
|
||||
@patch('module_build_service.utils.submit.record_stream_collision_modules')
|
||||
@patch('module_build_service.scheduler.handlers.modules.handle_stream_collision_modules')
|
||||
@patch.object(module_build_service.config.Config, 'system', new_callable=PropertyMock,
|
||||
return_value='test')
|
||||
@patch("module_build_service.builder.GenericBuilder.default_buildroot_groups",
|
||||
@@ -1259,7 +1259,7 @@ class TestLocalBuild:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
@patch('module_build_service.utils.submit.record_stream_collision_modules')
|
||||
@patch('module_build_service.scheduler.handlers.modules.handle_stream_collision_modules')
|
||||
@patch('module_build_service.auth.get_user', return_value=user)
|
||||
@patch('module_build_service.scm.SCM')
|
||||
@patch("module_build_service.config.Config.mock_resultsdir",
|
||||
|
||||
@@ -58,7 +58,8 @@ class TestModuleInit:
|
||||
@patch("module_build_service.builder.KojiModuleBuilder.KojiModuleBuilder."
|
||||
"get_built_rpms_in_module_build")
|
||||
@patch('module_build_service.scm.SCM')
|
||||
def test_init_basic(self, mocked_scm, built_rpms):
|
||||
@patch('module_build_service.scheduler.handlers.modules.handle_stream_collision_modules')
|
||||
def test_init_basic(self, rscm, mocked_scm, built_rpms):
|
||||
FakeSCM(mocked_scm, 'testmodule', 'testmodule_init.yaml',
|
||||
'620ec77321b2ea7b0d67d82992dda3e1d67055b4')
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
|
||||
import copy
|
||||
|
||||
from mock import patch, Mock
|
||||
|
||||
from module_build_service import conf, glib
|
||||
@@ -208,15 +210,15 @@ class TestRecordStreamCollisionModules:
|
||||
original_xmd = glib.from_variant_dict(fake_mmd.get_xmd())
|
||||
|
||||
with patch.object(ursine, 'log') as log:
|
||||
ursine.record_stream_collision_modules(fake_mmd)
|
||||
log.info.assert_called_once()
|
||||
ursine.handle_stream_collision_modules(fake_mmd)
|
||||
assert 2 == log.info.call_count
|
||||
find_stream_collision_modules.assert_not_called()
|
||||
|
||||
assert original_xmd == glib.from_variant_dict(fake_mmd.get_xmd())
|
||||
|
||||
@patch.object(conf, 'base_module_names', new=['platform'])
|
||||
@patch('module_build_service.utils.ursine.get_modulemds_from_ursine_content')
|
||||
def test_nothing_changed_if_no_modules_in_ursine_content(
|
||||
def test_mark_handled_even_if_no_modules_in_ursine_content(
|
||||
self, get_modulemds_from_ursine_content):
|
||||
xmd = {
|
||||
'mbs': {
|
||||
@@ -232,14 +234,21 @@ class TestRecordStreamCollisionModules:
|
||||
get_modulemds_from_ursine_content.return_value = []
|
||||
|
||||
with patch.object(ursine, 'log') as log:
|
||||
ursine.record_stream_collision_modules(fake_mmd)
|
||||
log.info.assert_called()
|
||||
ursine.handle_stream_collision_modules(fake_mmd)
|
||||
assert 2 == log.info.call_count
|
||||
|
||||
assert original_xmd == glib.from_variant_dict(fake_mmd.get_xmd())
|
||||
expected_xmd = copy.deepcopy(original_xmd)
|
||||
# Ensure stream_collision_modules is set.
|
||||
expected_xmd['mbs']['buildrequires']['platform']['stream_collision_modules'] = ''
|
||||
expected_xmd['mbs']['buildrequires']['platform']['ursine_rpms'] = ''
|
||||
assert expected_xmd == glib.from_variant_dict(fake_mmd.get_xmd())
|
||||
|
||||
@patch.object(conf, 'base_module_names', new=['platform', 'project-platform'])
|
||||
@patch('module_build_service.utils.ursine.get_modulemds_from_ursine_content')
|
||||
def test_add_collision_modules(self, get_modulemds_from_ursine_content):
|
||||
@patch('module_build_service.resolver.GenericResolver.create')
|
||||
@patch('koji.ClientSession')
|
||||
def test_add_collision_modules(self, ClientSession, resolver_create,
|
||||
get_modulemds_from_ursine_content):
|
||||
xmd = {
|
||||
'mbs': {
|
||||
'buildrequires': {
|
||||
@@ -253,35 +262,84 @@ class TestRecordStreamCollisionModules:
|
||||
}
|
||||
}
|
||||
}
|
||||
fake_mmd = make_module('name1:s:2020:c', xmd=xmd, store_to_db=False)
|
||||
fake_mmd = make_module('name1:s:2020:c',
|
||||
xmd=xmd, store_to_db=False)
|
||||
|
||||
def mock_get_ursine_modulemds(koji_tag):
|
||||
if koji_tag == 'module-rhel-8.0-build':
|
||||
return [
|
||||
make_module('modulea:10:20180813041838:5ea3b708', store_to_db=False),
|
||||
make_module('moduleb:1.0:20180113042038:6ea3b105', store_to_db=False),
|
||||
# This is the one
|
||||
make_module('modulea:10:20180813041838:5ea3b708',
|
||||
store_to_db=False),
|
||||
make_module('moduleb:1.0:20180113042038:6ea3b105',
|
||||
store_to_db=False),
|
||||
]
|
||||
if koji_tag == 'module-project-1.0-build':
|
||||
return [
|
||||
make_module('bar:6:20181013041838:817fa3a8', store_to_db=False),
|
||||
make_module('foo:2:20180113041838:95f078a1', store_to_db=False),
|
||||
# Both of them are the collided modules
|
||||
make_module('bar:6:20181013041838:817fa3a8',
|
||||
store_to_db=False),
|
||||
make_module('foo:2:20180113041838:95f078a1',
|
||||
store_to_db=False),
|
||||
]
|
||||
|
||||
get_modulemds_from_ursine_content.side_effect = mock_get_ursine_modulemds
|
||||
|
||||
ursine.record_stream_collision_modules(fake_mmd)
|
||||
# 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 = glib.from_variant_dict(fake_mmd.get_xmd())
|
||||
buildrequires = xmd['mbs']['buildrequires']
|
||||
|
||||
assert (['modulea:10:20180813041838:5ea3b708'] ==
|
||||
buildrequires['platform']['stream_collision_modules'])
|
||||
assert (['pkg1-0:1.0-1.fc28'] ==
|
||||
buildrequires['platform']['ursine_rpms'])
|
||||
|
||||
modules = buildrequires['project-platform']['stream_collision_modules']
|
||||
modules.sort()
|
||||
expected_modules = ['bar:6:20181013041838:817fa3a8', 'foo:2:20180113041838:95f078a1']
|
||||
modules = sorted(
|
||||
buildrequires['project-platform']['stream_collision_modules'])
|
||||
expected_modules = ['bar:6:20181013041838:817fa3a8',
|
||||
'foo:2:20180113041838:95f078a1']
|
||||
assert expected_modules == modules
|
||||
|
||||
assert (['pkg2-0:2.0-1.fc28', 'pkg3-0:3.0-1.fc28'] ==
|
||||
sorted(buildrequires['project-platform']['ursine_rpms']))
|
||||
|
||||
|
||||
class TestFindStreamCollisionModules:
|
||||
"""Test ursine.find_stream_collision_modules"""
|
||||
|
||||
@@ -1093,123 +1093,3 @@ class TestLocalBuilds:
|
||||
assert len(local_modules) == 1
|
||||
assert local_modules[0].koji_tag.endswith(
|
||||
"/module-platform-f28-3/results")
|
||||
|
||||
|
||||
class TestRecordFilteredRPMs:
|
||||
"""Test submit.record_filtered_rpms"""
|
||||
|
||||
def setup_method(self):
|
||||
clean_database(add_platform_module=False)
|
||||
|
||||
# Prepare fake data for resolver.get_module_modulemds
|
||||
xmd = {
|
||||
'mbs': {
|
||||
'buildrequires': {
|
||||
# This module has its own filtered_rpms, which should be unchanged.
|
||||
'modulea': {'stream': '201808', 'version': '2', 'context': '00000000',
|
||||
'filtered_rpms': ['pkg-1.0-1.fc28']},
|
||||
|
||||
# Whereas no filtered_rpms in this module, filtered rpms should be
|
||||
# injected eventually.
|
||||
'moduleb': {'stream': '7', 'version': '2', 'context': '00000000'},
|
||||
|
||||
# For test recording rpms included in stream collision modules
|
||||
'platform': {'stream': 'f28', 'version': '2', 'context': '00000000',
|
||||
# Don't care about platform module's filtered rpms here
|
||||
'filtered_rpms': [],
|
||||
'stream_collision_modules': ['foo:master:1:00000000',
|
||||
'bar:master:2:00000000']},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.mmd = make_module('cool-module:201809:1:00000000', xmd=xmd, store_to_db=False)
|
||||
|
||||
# Store buildrequires modules into database in order to be queried in the test
|
||||
for module_name, md_dict in xmd['mbs']['buildrequires'].items():
|
||||
br_module_nsvc = (module_name, md_dict['stream'],
|
||||
md_dict['version'], md_dict['context'])
|
||||
br_module_xmd = {
|
||||
'mbs': {
|
||||
'koji_tag': 'module-{}-{}-{}-{}'.format(*br_module_nsvc),
|
||||
}
|
||||
}
|
||||
br_module_filtered_rpms = None
|
||||
if module_name == 'moduleb':
|
||||
# Add this RPM to filter section.
|
||||
# Test will verify if this package is listed in final filtered_rpms list.
|
||||
br_module_filtered_rpms = ['foo']
|
||||
|
||||
# Modules have to be created in database whose NSVC appears in
|
||||
# stream_collision_modules. This is for testing recording rpms
|
||||
# built for stream collision modules.
|
||||
if module_name == 'platform':
|
||||
for nsvc in md_dict['stream_collision_modules']:
|
||||
make_module(nsvc, xmd={'mbs': {
|
||||
'koji_tag': 'module-{}-{}-{}-{}'.format(*nsvc.split(':'))
|
||||
}})
|
||||
|
||||
make_module('{}:{}:{}:{}'.format(*br_module_nsvc),
|
||||
filtered_rpms=br_module_filtered_rpms,
|
||||
xmd=br_module_xmd)
|
||||
|
||||
def teardown_method(self):
|
||||
clean_database()
|
||||
|
||||
@patch('koji.ClientSession')
|
||||
def test_generate_and_store_filtered_rpms(self, ClientSession):
|
||||
|
||||
def mocklistTaggedRPMs(tag, latest):
|
||||
# Result returned from listTaggedRPMs should contain two lists.
|
||||
# The second one is the build, which is not used in test and
|
||||
# omitted here.
|
||||
rpms = {
|
||||
'module-modulea-201808-2-00000000': [
|
||||
[
|
||||
{'name': 'pkg1', 'version': '1.0', 'release': '1.fc28'},
|
||||
{'name': 'pkg2', 'version': '2.34', 'release': '1.fc28'},
|
||||
],
|
||||
],
|
||||
'module-moduleb-7-2-00000000': [
|
||||
[
|
||||
{'name': 'foo', 'version': '2.0', 'release': '1.fc28'},
|
||||
{'name': 'bar', 'version': '1.0', 'release': '1.fc28'},
|
||||
],
|
||||
],
|
||||
|
||||
# These rpms are built for stream collision modules. See above
|
||||
# in setup_method.
|
||||
'module-foo-master-1-00000000': [
|
||||
[
|
||||
{'name': 'foo-a', 'version': '1.0', 'release': '1.fc28'},
|
||||
{'name': 'foo-a-devel', 'version': '1.0', 'release': '1.fc28'},
|
||||
],
|
||||
],
|
||||
'module-bar-master-2-00000000': [
|
||||
[
|
||||
{'name': 'bar-a', 'version': '0.2', 'release': '2.fc28'},
|
||||
{'name': 'bar-a-devel', 'version': '0.2', 'release': '2.fc28'},
|
||||
],
|
||||
]
|
||||
}
|
||||
return rpms[tag]
|
||||
|
||||
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)
|
||||
|
||||
xmd_mbs = mmd.get_xmd()['mbs'].unpack()
|
||||
|
||||
assert ['pkg-1.0-1.fc28'] == xmd_mbs['buildrequires']['modulea']['filtered_rpms']
|
||||
assert ['foo-0:2.0-1.fc28'] == xmd_mbs['buildrequires']['moduleb']['filtered_rpms']
|
||||
|
||||
expected_ursine_rpms = [
|
||||
'foo-a-0:1.0-1.fc28', 'foo-a-devel-0:1.0-1.fc28',
|
||||
'bar-a-0:0.2-2.fc28', 'bar-a-devel-0:0.2-2.fc28',
|
||||
]
|
||||
expected_ursine_rpms.sort()
|
||||
|
||||
found_ursine_rpms = xmd_mbs['buildrequires']['platform']['ursine_rpms']
|
||||
found_ursine_rpms.sort()
|
||||
assert expected_ursine_rpms == found_ursine_rpms
|
||||
|
||||
@@ -756,10 +756,9 @@ class TestViews:
|
||||
assert data['meta']['total'] == 0
|
||||
|
||||
@pytest.mark.parametrize('api_version', [1, 2])
|
||||
@patch('module_build_service.utils.submit.record_stream_collision_modules')
|
||||
@patch('module_build_service.auth.get_user', return_value=user)
|
||||
@patch('module_build_service.scm.SCM')
|
||||
def test_submit_build(self, mocked_scm, mocked_get_user, rscm, api_version):
|
||||
def test_submit_build(self, mocked_scm, mocked_get_user, api_version):
|
||||
FakeSCM(mocked_scm, 'testmodule', 'testmodule.yaml',
|
||||
'620ec77321b2ea7b0d67d82992dda3e1d67055b4')
|
||||
|
||||
@@ -805,10 +804,9 @@ class TestViews:
|
||||
assert module.buildrequires[0].context == '00000000'
|
||||
assert module.buildrequires[0].stream_version == 280000
|
||||
|
||||
@patch('module_build_service.utils.submit.record_stream_collision_modules')
|
||||
@patch('module_build_service.auth.get_user', return_value=user)
|
||||
@patch('module_build_service.scm.SCM')
|
||||
def test_submit_build_no_base_module(self, mocked_scm, mocked_get_user, rscm):
|
||||
def test_submit_build_no_base_module(self, mocked_scm, mocked_get_user):
|
||||
FakeSCM(mocked_scm, 'testmodule', 'testmodule-no-base-module.yaml',
|
||||
'620ec77321b2ea7b0d67d82992dda3e1d67055b4')
|
||||
|
||||
@@ -823,12 +821,11 @@ class TestViews:
|
||||
'error': 'Unprocessable Entity'
|
||||
}
|
||||
|
||||
@patch('module_build_service.utils.submit.record_stream_collision_modules')
|
||||
@patch('module_build_service.auth.get_user', return_value=user)
|
||||
@patch('module_build_service.scm.SCM')
|
||||
@patch('module_build_service.config.Config.rebuild_strategy_allow_override',
|
||||
new_callable=PropertyMock, return_value=True)
|
||||
def test_submit_build_rebuild_strategy(self, mocked_rmao, mocked_scm, mocked_get_user, hmsc):
|
||||
def test_submit_build_rebuild_strategy(self, mocked_rmao, mocked_scm, mocked_get_user):
|
||||
FakeSCM(mocked_scm, 'testmodule', 'testmodule.yaml',
|
||||
'620ec77321b2ea7b0d67d82992dda3e1d67055b4')
|
||||
|
||||
@@ -902,10 +899,9 @@ class TestViews:
|
||||
}
|
||||
assert data == expected_error
|
||||
|
||||
@patch('module_build_service.utils.submit.record_stream_collision_modules')
|
||||
@patch('module_build_service.auth.get_user', return_value=user)
|
||||
@patch('module_build_service.scm.SCM')
|
||||
def test_submit_componentless_build(self, mocked_scm, mocked_get_user, rscm):
|
||||
def test_submit_componentless_build(self, mocked_scm, mocked_get_user):
|
||||
FakeSCM(mocked_scm, 'fakemodule', 'fakemodule.yaml',
|
||||
'3da541559918a808c2402bba5012f6c60b27661c')
|
||||
|
||||
@@ -1127,12 +1123,11 @@ class TestViews:
|
||||
assert result['status'] == 400
|
||||
assert "The request contains 'owner' parameter" in result['message']
|
||||
|
||||
@patch('module_build_service.utils.submit.record_stream_collision_modules')
|
||||
@patch('module_build_service.auth.get_user', return_value=anonymous_user)
|
||||
@patch('module_build_service.scm.SCM')
|
||||
@patch("module_build_service.config.Config.no_auth", new_callable=PropertyMock,
|
||||
return_value=True)
|
||||
def test_submit_build_no_auth_set_owner(self, mocked_conf, mocked_scm, mocked_get_user, hmsc):
|
||||
def test_submit_build_no_auth_set_owner(self, mocked_conf, mocked_scm, mocked_get_user):
|
||||
FakeSCM(mocked_scm, 'testmodule', 'testmodule.yaml',
|
||||
'620ec77321b2ea7b0d67d82992dda3e1d67055b4')
|
||||
|
||||
@@ -1148,11 +1143,10 @@ class TestViews:
|
||||
build = ModuleBuild.query.filter(ModuleBuild.id == result['id']).one()
|
||||
assert (build.owner == result['owner'] == 'foo') is True
|
||||
|
||||
@patch('module_build_service.utils.submit.record_stream_collision_modules')
|
||||
@patch('module_build_service.auth.get_user', return_value=anonymous_user)
|
||||
@patch('module_build_service.scm.SCM')
|
||||
@patch("module_build_service.config.Config.no_auth", new_callable=PropertyMock)
|
||||
def test_patch_set_different_owner(self, mocked_no_auth, mocked_scm, mocked_get_user, hmsc):
|
||||
def test_patch_set_different_owner(self, mocked_no_auth, mocked_scm, mocked_get_user):
|
||||
FakeSCM(mocked_scm, 'testmodule', 'testmodule.yaml',
|
||||
'620ec77321b2ea7b0d67d82992dda3e1d67055b4')
|
||||
|
||||
@@ -1193,11 +1187,10 @@ class TestViews:
|
||||
assert data['status'] == 422
|
||||
assert data['error'] == 'Unprocessable Entity'
|
||||
|
||||
@patch('module_build_service.utils.submit.record_stream_collision_modules')
|
||||
@patch('module_build_service.auth.get_user', return_value=user)
|
||||
@patch('module_build_service.scm.SCM')
|
||||
@patch("module_build_service.config.Config.allow_custom_scmurls", new_callable=PropertyMock)
|
||||
def test_submit_custom_scmurl(self, allow_custom_scmurls, mocked_scm, mocked_get_user, hmsc):
|
||||
def test_submit_custom_scmurl(self, allow_custom_scmurls, mocked_scm, mocked_get_user):
|
||||
FakeSCM(mocked_scm, 'testmodule', 'testmodule.yaml',
|
||||
'620ec77321b2ea7b0d67d82992dda3e1d67055b4')
|
||||
|
||||
@@ -1220,11 +1213,10 @@ class TestViews:
|
||||
(['f28'], None),
|
||||
(['f28'], ['f28']),
|
||||
))
|
||||
@patch('module_build_service.utils.submit.record_stream_collision_modules')
|
||||
@patch('module_build_service.auth.get_user', return_value=user)
|
||||
@patch('module_build_service.scm.SCM')
|
||||
def test_submit_build_dep_override(
|
||||
self, mocked_scm, mocked_get_user, rscm, br_override_streams, req_override_streams):
|
||||
self, mocked_scm, mocked_get_user, br_override_streams, req_override_streams):
|
||||
init_data(data_size=1, multiple_stream_versions=True)
|
||||
FakeSCM(mocked_scm, 'testmodule', 'testmodule_platform_f290000.yaml',
|
||||
'620ec77321b2ea7b0d67d82992dda3e1d67055b4')
|
||||
|
||||
Reference in New Issue
Block a user