mirror of
https://pagure.io/fm-orchestrator.git
synced 2026-04-05 11:48:33 +08:00
Add the ability to query by the base modules a module build buildrequires
Future use cases will require the ability to find compatible module builds to buildrequire based on the base module the module used to build. This commit adds an association table that will contain module build IDs and the base module they buildrequire. Addresses FACTORY-3353
This commit is contained in:
19
README.rst
19
README.rst
@@ -369,6 +369,15 @@ parameters::
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"base_module_buildrequires": [
|
||||
{
|
||||
"context": "00000000",
|
||||
"name": "platform",
|
||||
"stream": "f29",
|
||||
"stream_version": 290000,
|
||||
"version": "5"
|
||||
}
|
||||
],
|
||||
"component_builds": [
|
||||
57047,
|
||||
57048
|
||||
@@ -479,6 +488,16 @@ Filtering module builds
|
||||
The module builds can be filtered by a variety of GET parameters. Some of these
|
||||
parameters include:
|
||||
|
||||
- ``base_module_br`` - the name:stream:version:context of a base module the module buildrequires
|
||||
- ``base_module_br_context`` - the context of a base module the module buildrequires
|
||||
- ``base_module_br_name`` - the name of a base module the module buildrequires
|
||||
- ``base_module_br_stream`` - the stream of a base module the module buildrequires
|
||||
- ``base_module_br_stream_version`` - the stream version of a base module the module buildrequires
|
||||
- ``base_module_br_stream_version_lte`` - less than or equal to the stream version of a base module
|
||||
the module buildrequires
|
||||
- ``base_module_br_stream_version_gte`` - greater than or equal to the stream version of a base
|
||||
module the module buildrequires
|
||||
- ``base_module_br_version`` - the version of a base module the module buildrequires
|
||||
- ``batch``
|
||||
- ``cg_build_koji_tag``
|
||||
- ``completed_after`` - Zulu ISO 8601 format e.g. ``completed_after=2016-08-23T09:40:07Z``
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
"""Add an association table for module buildrequires
|
||||
|
||||
Revision ID: 526fb7d445f7
|
||||
Revises: 9d5e6938588f
|
||||
Create Date: 2018-10-11 12:46:36.060460
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '526fb7d445f7'
|
||||
down_revision = '9d5e6938588f'
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
# Data migration imports
|
||||
from module_build_service import Modulemd, conf
|
||||
from module_build_service.models import ModuleBuild
|
||||
|
||||
# Data migration tables
|
||||
mb = sa.Table(
|
||||
'module_builds',
|
||||
sa.MetaData(),
|
||||
sa.Column('id', sa.Integer, primary_key=True),
|
||||
sa.Column('name', sa.String()),
|
||||
sa.Column('stream', sa.String()),
|
||||
sa.Column('version', sa.String()),
|
||||
sa.Column('context', sa.String()),
|
||||
sa.Column('stream_version', sa.Integer()),
|
||||
sa.Column('modulemd', sa.String())
|
||||
)
|
||||
|
||||
mb_to_mbr = sa.Table(
|
||||
'module_builds_to_module_buildrequires',
|
||||
sa.MetaData(),
|
||||
sa.Column('module_id', sa.Integer(), nullable=False),
|
||||
sa.Column('module_buildrequire_id', sa.Integer(), nullable=False),
|
||||
sa.ForeignKeyConstraint(['module_id'], ['module_builds.id']),
|
||||
sa.ForeignKeyConstraint(['module_buildrequire_id'], ['module_builds.id']),
|
||||
sa.UniqueConstraint('module_id', 'module_buildrequire_id')
|
||||
)
|
||||
|
||||
|
||||
def upgrade():
|
||||
with op.batch_alter_table('module_builds', schema=None) as batch_op:
|
||||
batch_op.add_column(sa.Column('stream_version', sa.Integer()))
|
||||
|
||||
op.create_table(
|
||||
'module_builds_to_module_buildrequires',
|
||||
sa.Column('module_id', sa.Integer(), nullable=False),
|
||||
sa.Column('module_buildrequire_id', sa.Integer(), nullable=False),
|
||||
sa.ForeignKeyConstraint(['module_buildrequire_id'], ['module_buildrequires.id']),
|
||||
sa.ForeignKeyConstraint(['module_id'], ['module_builds.id']),
|
||||
sa.UniqueConstraint('module_id', 'module_buildrequire_id')
|
||||
)
|
||||
|
||||
connection = op.get_bind()
|
||||
# Create all the base module buildrequire entries
|
||||
for build in connection.execute(mb.select()):
|
||||
if not build.modulemd:
|
||||
# If the modulemd is empty, skip this build
|
||||
continue
|
||||
|
||||
brs = None
|
||||
try:
|
||||
mmd = Modulemd.Module().new_from_string(build.modulemd)
|
||||
mmd.upgrade()
|
||||
brs = mmd.get_xmd()['mbs']['buildrequires']
|
||||
except Exception:
|
||||
# If the modulemd isn't parseable then skip this build
|
||||
continue
|
||||
|
||||
for base_module in conf.base_module_names:
|
||||
base_module_dict = brs.get(base_module)
|
||||
if not base_module_dict:
|
||||
# If this base module isn't a buildrequire, continue to see if the next one is
|
||||
continue
|
||||
|
||||
select = mb.select()\
|
||||
.where(mb.c.name == base_module)\
|
||||
.where(mb.c.stream == base_module_dict['stream'])\
|
||||
.where(mb.c.version == base_module_dict['version'])\
|
||||
.where(mb.c.context == base_module_dict['context'])
|
||||
br = connection.execute(select).fetchone()
|
||||
if not br:
|
||||
# If the buildrequire isn't in the datbase, then skip it
|
||||
continue
|
||||
|
||||
connection.execute(mb_to_mbr.insert().values(
|
||||
module_id=build.id,
|
||||
module_buildrequire_id=br.id
|
||||
))
|
||||
|
||||
for base_module in conf.base_module_names:
|
||||
for build in connection.execute(mb.select().where(mb.c.name == base_module)):
|
||||
stream_version = ModuleBuild.get_stream_version(build.stream)
|
||||
if not stream_version:
|
||||
# If a stream version isn't parseable, then skip it
|
||||
continue
|
||||
connection.execute(mb.update().where(mb.c.id == build.id).values(
|
||||
stream_version=stream_version))
|
||||
|
||||
|
||||
def downgrade():
|
||||
with op.batch_alter_table('module_builds', schema=None) as batch_op:
|
||||
batch_op.drop_column(sa.Column('stream_version'))
|
||||
op.drop_table('module_builds_to_module_buildrequires')
|
||||
@@ -166,6 +166,15 @@ class MBSBase(db.Model):
|
||||
__abstract__ = True
|
||||
|
||||
|
||||
module_builds_to_module_buildrequires = db.Table(
|
||||
'module_builds_to_module_buildrequires',
|
||||
db.Column('module_id', db.Integer, db.ForeignKey('module_builds.id'), nullable=False),
|
||||
db.Column('module_buildrequire_id', db.Integer, db.ForeignKey('module_builds.id'),
|
||||
nullable=False),
|
||||
db.UniqueConstraint('module_id', 'module_buildrequire_id', name='unique_buildrequires')
|
||||
)
|
||||
|
||||
|
||||
class ModuleBuild(MBSBase):
|
||||
__tablename__ = "module_builds"
|
||||
id = db.Column(db.Integer, primary_key=True)
|
||||
@@ -195,6 +204,16 @@ class ModuleBuild(MBSBase):
|
||||
# components. Think like 'mockchain --recurse'
|
||||
batch = db.Column(db.Integer, default=0)
|
||||
|
||||
# This is only used for base modules for ordering purposes (f27.0.1 => 270001)
|
||||
stream_version = db.Column(db.Integer)
|
||||
buildrequires = db.relationship(
|
||||
'ModuleBuild',
|
||||
secondary=module_builds_to_module_buildrequires,
|
||||
primaryjoin=module_builds_to_module_buildrequires.c.module_id == id,
|
||||
secondaryjoin=module_builds_to_module_buildrequires.c.module_buildrequire_id == id,
|
||||
backref='buildrequire_for'
|
||||
)
|
||||
|
||||
rebuild_strategies = {
|
||||
'all': 'All components will be rebuilt',
|
||||
'changed-and-after': ('All components that have changed and those in subsequent batches '
|
||||
@@ -429,6 +448,11 @@ class ModuleBuild(MBSBase):
|
||||
# Add a state transition to "init"
|
||||
mbt = ModuleBuildTrace(state_time=now, state=module.state)
|
||||
module.module_builds_trace.append(mbt)
|
||||
|
||||
# Record the base modules this module buildrequires
|
||||
for base_module in module.get_buildrequired_base_modules():
|
||||
module.buildrequires.append(base_module)
|
||||
|
||||
session.add(module)
|
||||
session.commit()
|
||||
if publish_msg:
|
||||
@@ -535,8 +559,8 @@ class ModuleBuild(MBSBase):
|
||||
|
||||
return query.first()
|
||||
|
||||
def short_json(self):
|
||||
return {
|
||||
def short_json(self, show_stream_version=False):
|
||||
rv = {
|
||||
'id': self.id,
|
||||
'state': self.state,
|
||||
'state_name': INVERSE_BUILD_STATES[self.state],
|
||||
@@ -545,6 +569,9 @@ class ModuleBuild(MBSBase):
|
||||
'name': self.name,
|
||||
'context': self.context,
|
||||
}
|
||||
if show_stream_version:
|
||||
rv['stream_version'] = self.stream_version
|
||||
return rv
|
||||
|
||||
def json(self, show_tasks=True):
|
||||
json = self.short_json()
|
||||
@@ -576,7 +603,9 @@ class ModuleBuild(MBSBase):
|
||||
state_url = None
|
||||
if show_state_url:
|
||||
state_url = get_url_for('module_build', api_version=api_version, id=self.id)
|
||||
|
||||
json.update({
|
||||
'base_module_buildrequires': [br.short_json(True) for br in self.buildrequires],
|
||||
'build_context': self.build_context,
|
||||
'modulemd': self.modulemd,
|
||||
'ref_build_context': self.ref_build_context,
|
||||
@@ -621,13 +650,15 @@ class ModuleBuild(MBSBase):
|
||||
module_id=module_id).order_by(ModuleBuildTrace.state_time).all()
|
||||
|
||||
@staticmethod
|
||||
def get_stream_version(stream):
|
||||
def get_stream_version(stream, right_pad=True):
|
||||
"""
|
||||
Parse the supplied stream to find its version.
|
||||
|
||||
This will parse a stream such as "f27" and return 270000. Another example would be a stream
|
||||
of "f27.0.1" and return 270001.
|
||||
:param str stream: the module stream
|
||||
:kwarg bool right_pad: determines if the right side of the stream version should be padded
|
||||
with zeroes (e.g. `f27` => `27` vs `270000`)
|
||||
:return: a stream version represented as an integer
|
||||
:rtype: int or None if the stream doesn't have a valid version
|
||||
"""
|
||||
@@ -652,10 +683,44 @@ class ModuleBuild(MBSBase):
|
||||
version = ''.join([section.zfill(2) for section in version.split('.')])
|
||||
|
||||
if version:
|
||||
if right_pad:
|
||||
version += (6 - len(version)) * '0'
|
||||
# Since the version must be stored as a number, we convert the string back to
|
||||
# an integer which consequently drops the leading zero if there is one
|
||||
return int(version)
|
||||
|
||||
def get_buildrequired_base_modules(self):
|
||||
"""
|
||||
Find the base modules in the modulemd's xmd section.
|
||||
|
||||
:return: a list of ModuleBuild objects of the base modules that are buildrequired with the
|
||||
ordering in conf.base_module_names preserved
|
||||
:rtype: list
|
||||
:raises RuntimeError: when the xmd section isn't properly filled out by MBS
|
||||
"""
|
||||
rv = []
|
||||
xmd = self.mmd().get_xmd()
|
||||
with make_session(conf) as db_session:
|
||||
for bm in conf.base_module_names:
|
||||
# xmd is a GLib Variant and doesn't support .get() syntax
|
||||
try:
|
||||
bm_dict = xmd['mbs']['buildrequires'].get(bm)
|
||||
except KeyError:
|
||||
raise RuntimeError(
|
||||
'The module\'s mmd is missing information in the xmd section')
|
||||
|
||||
if not bm_dict:
|
||||
continue
|
||||
base_module = self.get_build_from_nsvc(
|
||||
db_session, bm, bm_dict['stream'], bm_dict['version'], bm_dict['context'])
|
||||
if not base_module:
|
||||
log.error('Module #{} buildrequires "{}" but it wasn\'t found in the database'
|
||||
.format(self.id, repr(bm_dict)))
|
||||
continue
|
||||
rv.append(base_module)
|
||||
|
||||
return rv
|
||||
|
||||
def __repr__(self):
|
||||
return (("<ModuleBuild %s, id=%d, stream=%s, version=%s, state %r,"
|
||||
" batch %r, state_reason %r>")
|
||||
|
||||
@@ -29,10 +29,11 @@ import logging
|
||||
import kobo.rpmlib
|
||||
import requests
|
||||
|
||||
from module_build_service import db
|
||||
from module_build_service import db, 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.utils.general import import_mmd
|
||||
|
||||
log = logging.getLogger()
|
||||
|
||||
@@ -363,5 +364,9 @@ class MBSResolver(GenericResolver):
|
||||
raise RuntimeError(
|
||||
'The module "{0}" didn\'t contain either a commit hash or a'
|
||||
' version in MBS'.format(module_name))
|
||||
# If the module is a base module, then import it in the database so that entries in
|
||||
# the module_builds_to_module_buildrequires table can be created later on
|
||||
if module_name in conf.base_module_names:
|
||||
import_mmd(db.session, mmd)
|
||||
|
||||
return new_requires
|
||||
|
||||
@@ -334,6 +334,8 @@ def import_mmd(session, mmd):
|
||||
build.time_submitted = datetime.utcnow()
|
||||
build.time_modified = datetime.utcnow()
|
||||
build.time_completed = datetime.utcnow()
|
||||
if build.name in conf.base_module_names:
|
||||
build.stream_version = models.ModuleBuild.get_stream_version(stream)
|
||||
session.add(build)
|
||||
session.commit()
|
||||
msg = "Module {} imported".format(nsvc)
|
||||
|
||||
@@ -239,7 +239,7 @@ def get_prefixed_version(mmd):
|
||||
return version
|
||||
|
||||
# The platform version (e.g. prefix1.2.0 => 010200)
|
||||
version_prefix = models.ModuleBuild.get_stream_version(base_module_stream)
|
||||
version_prefix = models.ModuleBuild.get_stream_version(base_module_stream, right_pad=False)
|
||||
|
||||
if not version_prefix:
|
||||
log.warning('The "{0}" stream "{1}" couldn\'t be used to prefix the module\'s '
|
||||
|
||||
@@ -29,6 +29,7 @@ from datetime import datetime
|
||||
|
||||
from flask import request, url_for, Response
|
||||
from sqlalchemy.sql.sqltypes import Boolean as sqlalchemy_boolean
|
||||
from sqlalchemy.orm import aliased
|
||||
|
||||
from module_build_service import models, api_version, conf
|
||||
from module_build_service.errors import ValidationError, NotFound
|
||||
@@ -265,6 +266,55 @@ def filter_module_builds(flask_request):
|
||||
elif context == 'before':
|
||||
query = query.filter(column <= item_datetime)
|
||||
|
||||
br_joined = False
|
||||
module_br_alias = None
|
||||
for item in ('base_module_br', 'name', 'stream', 'version', 'context', 'stream_version',
|
||||
'stream_version_lte', 'stream_version_gte'):
|
||||
if item == 'base_module_br':
|
||||
request_arg_name = item
|
||||
else:
|
||||
request_arg_name = 'base_module_br_{}'.format(item)
|
||||
request_arg = flask_request.args.get(request_arg_name)
|
||||
|
||||
if not request_arg:
|
||||
continue
|
||||
|
||||
if not br_joined:
|
||||
module_br_alias = aliased(models.ModuleBuild, name='module_br')
|
||||
# Shorten this table name for clarity in the query below
|
||||
mb_to_br = models.module_builds_to_module_buildrequires
|
||||
# The following joins get added:
|
||||
# JOIN module_builds_to_module_buildrequires
|
||||
# ON module_builds_to_module_buildrequires.module_id = module_builds.id
|
||||
# JOIN module_builds AS module_br
|
||||
# ON module_builds_to_module_buildrequires.module_buildrequire_id = module_br.id
|
||||
query = query.join(mb_to_br, mb_to_br.c.module_id == models.ModuleBuild.id)\
|
||||
.join(module_br_alias,
|
||||
mb_to_br.c.module_buildrequire_id == module_br_alias.id)
|
||||
br_joined = True
|
||||
|
||||
if item == 'base_module_br':
|
||||
try:
|
||||
name, stream, version, context = flask_request.args['base_module_br'].split(':')
|
||||
except ValueError:
|
||||
raise ValidationError(
|
||||
'The filter argument for "base_module_br" must be in the format of N:S:V:C')
|
||||
query = query.filter(
|
||||
module_br_alias.name == name,
|
||||
module_br_alias.stream == stream,
|
||||
module_br_alias.version == version,
|
||||
module_br_alias.context == context
|
||||
)
|
||||
elif item.endswith('_lte'):
|
||||
column = getattr(module_br_alias, item[:-4])
|
||||
query = query.filter(column <= request_arg)
|
||||
elif item.endswith('_gte'):
|
||||
column = getattr(module_br_alias, item[:-4])
|
||||
query = query.filter(column >= request_arg)
|
||||
else:
|
||||
column = getattr(module_br_alias, item)
|
||||
query = query.filter(column == request_arg)
|
||||
|
||||
query = _add_order_by_clause(flask_request, query, models.ModuleBuild)
|
||||
|
||||
page = flask_request.args.get('page', 1, type=int)
|
||||
|
||||
@@ -293,6 +293,8 @@ def scheduler_init_data(tangerine_state=None):
|
||||
mmd.upgrade()
|
||||
mmd.get_rpm_components()['tangerine'].set_buildorder(0)
|
||||
|
||||
platform_br = module_build_service.models.ModuleBuild.query.get(1)
|
||||
|
||||
build_one = module_build_service.models.ModuleBuild()
|
||||
build_one.name = 'testmodule'
|
||||
build_one.stream = 'master'
|
||||
@@ -314,6 +316,7 @@ def scheduler_init_data(tangerine_state=None):
|
||||
build_one.rebuild_strategy = 'changed-and-after'
|
||||
build_one.modulemd = mmd.dumps()
|
||||
build_one_component_release = get_rpm_release(build_one)
|
||||
build_one.buildrequires.append(platform_br)
|
||||
|
||||
component_one_build_one = module_build_service.models.ComponentBuild()
|
||||
component_one_build_one.package = 'perl-Tangerine'
|
||||
@@ -381,6 +384,7 @@ def scheduler_init_data(tangerine_state=None):
|
||||
component_four_build_one.build_time_only = True
|
||||
|
||||
with make_session(conf) as session:
|
||||
session.add(platform_br)
|
||||
session.add(build_one)
|
||||
session.add(component_one_build_one)
|
||||
session.add(component_two_build_one)
|
||||
@@ -398,6 +402,8 @@ def reuse_component_init_data():
|
||||
mmd = Modulemd.Module().new_from_file(formatted_testmodule_yml_path)
|
||||
mmd.upgrade()
|
||||
|
||||
platform_br = module_build_service.models.ModuleBuild.query.get(1)
|
||||
|
||||
build_one = module_build_service.models.ModuleBuild()
|
||||
build_one.name = 'testmodule'
|
||||
build_one.stream = 'master'
|
||||
@@ -422,6 +428,7 @@ def reuse_component_init_data():
|
||||
xmd['mbs']['commit'] = 'ff1ea79fc952143efeed1851aa0aa006559239ba'
|
||||
mmd.set_xmd(glib.dict_values(xmd))
|
||||
build_one.modulemd = mmd.dumps()
|
||||
build_one.buildrequires.append(platform_br)
|
||||
|
||||
component_one_build_one = module_build_service.models.ComponentBuild()
|
||||
component_one_build_one.package = 'perl-Tangerine'
|
||||
@@ -506,6 +513,7 @@ def reuse_component_init_data():
|
||||
xmd['mbs']['commit'] = '55f4a0a2e6cc255c88712a905157ab39315b8fd8'
|
||||
mmd.set_xmd(glib.dict_values(xmd))
|
||||
build_two.modulemd = mmd.dumps()
|
||||
build_two.buildrequires.append(platform_br)
|
||||
|
||||
component_one_build_two = module_build_service.models.ComponentBuild()
|
||||
component_one_build_two.package = 'perl-Tangerine'
|
||||
@@ -550,6 +558,7 @@ def reuse_component_init_data():
|
||||
component_four_build_two.build_time_only = True
|
||||
|
||||
with make_session(conf) as session:
|
||||
session.add(platform_br)
|
||||
session.add(build_one)
|
||||
session.add(component_one_build_one)
|
||||
session.add(component_two_build_one)
|
||||
|
||||
@@ -28,7 +28,7 @@ data:
|
||||
testmodule: {ref: 147dca4ca65aa9a1ac51f71b7e687f9178ffa5df, stream: master,
|
||||
version: '20170616125652', context: '321'}
|
||||
requires:
|
||||
platform: {ref: virtual, stream: f28, version: '3'}
|
||||
platform: {ref: virtual, stream: f28, version: '3', context: '00000000'}
|
||||
commit: 722fd739fd6cf66faf29f6fb95dd64f60ba3e39a
|
||||
rpms:
|
||||
ed: {ref: 01bf8330812fea798671925cc537f2f29b0bd216}
|
||||
|
||||
@@ -25,7 +25,7 @@ data:
|
||||
xmd:
|
||||
mbs:
|
||||
buildrequires:
|
||||
platform: {ref: virtual, stream: f28, version: '3'}
|
||||
platform: {ref: virtual, stream: f28, version: '3', context: '00000000'}
|
||||
commit: 722fd739fd6cf66faf29f6fb95dd64f60ba3e39a
|
||||
rpms:
|
||||
ed: {ref: 01bf8330812fea798671925cc537f2f29b0bd216}
|
||||
|
||||
@@ -25,7 +25,7 @@ data:
|
||||
xmd:
|
||||
mbs:
|
||||
buildrequires:
|
||||
platform: {ref: virtual, stream: f28, version: '3'}
|
||||
platform: {ref: virtual, stream: f28, version: '3', context: '00000000'}
|
||||
commit: 722fd739fd6cf66faf29f6fb95dd64f60ba3e39a
|
||||
rpms:
|
||||
ed: {ref: 01bf8330812fea798671925cc537f2f29b0bd216}
|
||||
|
||||
@@ -50,18 +50,6 @@ class TestMockModuleBuilder:
|
||||
mmd = Modulemd.Module().new_from_file(os.path.join(
|
||||
base_dir, '..', 'staged_data', 'testmodule-with-filters.yaml'))
|
||||
mmd.upgrade()
|
||||
|
||||
module = ModuleBuild.create(
|
||||
session,
|
||||
conf,
|
||||
name="mbs-testmodule",
|
||||
stream="test",
|
||||
version="20171027111452",
|
||||
modulemd=mmd.dumps(),
|
||||
scmurl="file:///testdir",
|
||||
username="test",
|
||||
)
|
||||
module.koji_tag = "module-mbs-testmodule-test-20171027111452"
|
||||
mmd.set_xmd(glib.dict_values({
|
||||
'mbs': {
|
||||
'rpms': {
|
||||
@@ -74,13 +62,16 @@ class TestMockModuleBuilder:
|
||||
'version': '20171024133034',
|
||||
'filtered_rpms': [],
|
||||
'stream': 'master',
|
||||
'ref': '6df253bb3c53e84706c01b8ab2d5cac24f0b6d45'
|
||||
'ref': '6df253bb3c53e84706c01b8ab2d5cac24f0b6d45',
|
||||
'context': '00000000'
|
||||
},
|
||||
'platform': {
|
||||
'version': '20171028112959',
|
||||
'filtered_rpms': [],
|
||||
'stream': 'master',
|
||||
'ref': '4f7787370a931d57421f9f9555fc41c3e31ff1fa'}
|
||||
'ref': '4f7787370a931d57421f9f9555fc41c3e31ff1fa',
|
||||
'context': '00000000'
|
||||
}
|
||||
},
|
||||
'scmurl': 'file:///testdir',
|
||||
'commit': '5566bc792ec7a03bb0e28edd1b104a96ba342bd8',
|
||||
@@ -89,11 +80,23 @@ class TestMockModuleBuilder:
|
||||
'version': '20171028112959',
|
||||
'filtered_rpms': [],
|
||||
'stream': 'master',
|
||||
'ref': '4f7787370a931d57421f9f9555fc41c3e31ff1fa'}
|
||||
'ref': '4f7787370a931d57421f9f9555fc41c3e31ff1fa',
|
||||
'context': '00000000'
|
||||
}
|
||||
}
|
||||
}
|
||||
}))
|
||||
module.modulemd = mmd.dumps()
|
||||
module = ModuleBuild.create(
|
||||
session,
|
||||
conf,
|
||||
name="mbs-testmodule",
|
||||
stream="test",
|
||||
version="20171027111452",
|
||||
modulemd=mmd.dumps(),
|
||||
scmurl="file:///testdir",
|
||||
username="test",
|
||||
)
|
||||
module.koji_tag = "module-mbs-testmodule-test-20171027111452"
|
||||
module.batch = batch
|
||||
session.add(module)
|
||||
|
||||
@@ -101,6 +104,7 @@ class TestMockModuleBuilder:
|
||||
cb = ComponentBuild(**dict(build, format="rpms", state=state))
|
||||
session.add(cb)
|
||||
session.commit()
|
||||
session.commit()
|
||||
|
||||
return module
|
||||
|
||||
|
||||
@@ -98,6 +98,11 @@ class TestModels:
|
||||
assert ModuleBuild.get_stream_version('f27') == 270000
|
||||
assert ModuleBuild.get_stream_version('f27.02.30') == 270230
|
||||
|
||||
def test_get_stream_version_no_right_pad(self):
|
||||
"""Test the ModuleBuild.get_stream_version method when right_pad is False."""
|
||||
assert ModuleBuild.get_stream_version('f27', False) == 27
|
||||
assert ModuleBuild.get_stream_version('f27.02.30', False) == 270230
|
||||
|
||||
|
||||
class TestModelsGetStreamsContexts:
|
||||
|
||||
|
||||
@@ -213,7 +213,7 @@ class TestModuleWait:
|
||||
@patch('module_build_service.resolver.DBResolver')
|
||||
@patch('module_build_service.resolver.GenericResolver')
|
||||
@patch("module_build_service.config.Config.base_module_names",
|
||||
new_callable=mock.PropertyMock, return_value=set(["base-runtime"]))
|
||||
new_callable=mock.PropertyMock, return_value=set(["base-runtime", "platform"]))
|
||||
def test_set_cg_build_koji_tag(
|
||||
self, cfg, generic_resolver, resolver, create_builder, koji_get_session, dbg):
|
||||
"""
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
# Written by Matt Prahl <mprahl@redhat.com>
|
||||
|
||||
import json
|
||||
from datetime import datetime
|
||||
|
||||
import module_build_service.scm
|
||||
|
||||
@@ -39,6 +40,7 @@ from module_build_service.models import ModuleBuild
|
||||
from module_build_service import db, version, Modulemd
|
||||
import module_build_service.config as mbs_config
|
||||
import module_build_service.scheduler.handlers.modules
|
||||
from module_build_service.utils import import_mmd, load_mmd
|
||||
|
||||
|
||||
user = ('Homer J. Simpson', set(['packager']))
|
||||
@@ -172,6 +174,7 @@ class TestViews:
|
||||
def test_query_build_with_verbose_mode(self):
|
||||
rv = self.client.get('/module-build-service/1/module-builds/2?verbose=true')
|
||||
data = json.loads(rv.data)
|
||||
assert data['base_module_buildrequires'] == []
|
||||
assert data['component_builds'] == [1, 2]
|
||||
assert data['context'] == '00000000'
|
||||
# There is no xmd information on this module, so these values should be None
|
||||
@@ -216,6 +219,21 @@ class TestViews:
|
||||
assert data['rebuild_strategy'] == 'changed-and-after'
|
||||
assert data['siblings'] == []
|
||||
|
||||
def test_query_build_with_br_verbose_mode(self):
|
||||
reuse_component_init_data()
|
||||
rv = self.client.get('/module-build-service/1/module-builds/2?verbose=true')
|
||||
data = json.loads(rv.data)
|
||||
assert data['base_module_buildrequires'] == [{
|
||||
'context': '00000000',
|
||||
'id': 1,
|
||||
'name': 'platform',
|
||||
'state': 5,
|
||||
'state_name': 'ready',
|
||||
'stream': 'f28',
|
||||
'stream_version': 280000,
|
||||
'version': '3'
|
||||
}]
|
||||
|
||||
def test_pagination_metadata(self):
|
||||
rv = self.client.get('/module-build-service/1/module-builds/?per_page=2&page=2')
|
||||
meta_data = json.loads(rv.data)['meta']
|
||||
@@ -662,6 +680,77 @@ class TestViews:
|
||||
assert data['error'] == 'Bad Request'
|
||||
assert data['message'] == 'An invalid order_by or order_desc_by key was supplied'
|
||||
|
||||
def test_query_base_module_br_filters(self):
|
||||
reuse_component_init_data()
|
||||
mmd = load_mmd(path.join(base_dir, 'staged_data', 'platform.yaml'), True)
|
||||
mmd.set_stream('f30.1.3')
|
||||
import_mmd(db.session, mmd)
|
||||
platform_f300103 = ModuleBuild.query.filter_by(stream='f30.1.3').one()
|
||||
build = ModuleBuild(
|
||||
name='testmodule',
|
||||
stream='master',
|
||||
version=20170109091357,
|
||||
state=5,
|
||||
build_context='dd4de1c346dcf09ce77d38cd4e75094ec1c08ec3',
|
||||
runtime_context='ec4de1c346dcf09ce77d38cd4e75094ec1c08ef7',
|
||||
context='7c29193d',
|
||||
koji_tag='module-testmodule-master-20170109091357-7c29193d',
|
||||
scmurl='git://pkgs.stg.fedoraproject.org/modules/testmodule.git?#ff1ea79',
|
||||
batch=3,
|
||||
owner='Dr. Pepper',
|
||||
time_submitted=datetime(2018, 11, 15, 16, 8, 18),
|
||||
time_modified=datetime(2018, 11, 15, 16, 19, 35),
|
||||
rebuild_strategy='changed-and-after',
|
||||
modulemd='---'
|
||||
)
|
||||
build.buildrequires.append(platform_f300103)
|
||||
db.session.add(build)
|
||||
db.session.commit()
|
||||
# Query by NSVC
|
||||
rv = self.client.get(
|
||||
'/module-build-service/1/module-builds/?base_module_br=platform:f28:3:00000000')
|
||||
data = json.loads(rv.data)
|
||||
assert data['meta']['total'] == 2
|
||||
rv = self.client.get(
|
||||
'/module-build-service/1/module-builds/?base_module_br=platform:f30.1.3:3:00000000')
|
||||
data = json.loads(rv.data)
|
||||
assert data['meta']['total'] == 1
|
||||
# Query by non-existent NVC
|
||||
rv = self.client.get(
|
||||
'/module-build-service/1/module-builds/?base_module_br=platform:f12:3:00000000')
|
||||
data = json.loads(rv.data)
|
||||
assert data['meta']['total'] == 0
|
||||
# Query by name and stream
|
||||
rv = self.client.get('/module-build-service/1/module-builds/?base_module_br_name=platform'
|
||||
'&base_module_br_stream=f28')
|
||||
data = json.loads(rv.data)
|
||||
assert data['meta']['total'] == 2
|
||||
# Query by stream version
|
||||
rv = self.client.get('/module-build-service/1/module-builds/?base_module_br_stream_version='
|
||||
'280000')
|
||||
data = json.loads(rv.data)
|
||||
assert data['meta']['total'] == 2
|
||||
# Query by lte stream version
|
||||
rv = self.client.get('/module-build-service/1/module-builds/?base_module_br_stream_version_'
|
||||
'lte=290000')
|
||||
data = json.loads(rv.data)
|
||||
assert data['meta']['total'] == 2
|
||||
# Query by lte stream version with no results
|
||||
rv = self.client.get('/module-build-service/1/module-builds/?base_module_br_stream_version_'
|
||||
'lte=270000')
|
||||
data = json.loads(rv.data)
|
||||
assert data['meta']['total'] == 0
|
||||
# Query by gte stream version
|
||||
rv = self.client.get('/module-build-service/1/module-builds/?base_module_br_stream_version_'
|
||||
'gte=270000')
|
||||
data = json.loads(rv.data)
|
||||
assert data['meta']['total'] == 3
|
||||
# Query by gte stream version with no results
|
||||
rv = self.client.get('/module-build-service/1/module-builds/?base_module_br_stream_version_'
|
||||
'gte=320000')
|
||||
data = json.loads(rv.data)
|
||||
assert data['meta']['total'] == 0
|
||||
|
||||
@pytest.mark.parametrize('api_version', [1, 2])
|
||||
@patch('module_build_service.auth.get_user', return_value=user)
|
||||
@patch('module_build_service.scm.SCM')
|
||||
@@ -702,6 +791,15 @@ class TestViews:
|
||||
mmd = Modulemd.Module().new_from_string(data['modulemd'])
|
||||
mmd.upgrade()
|
||||
|
||||
# Make sure the buildrequires entry was created
|
||||
module = ModuleBuild.query.get(8)
|
||||
assert len(module.buildrequires) == 1
|
||||
assert module.buildrequires[0].name == 'platform'
|
||||
assert module.buildrequires[0].stream == 'f28'
|
||||
assert module.buildrequires[0].version == '3'
|
||||
assert module.buildrequires[0].context == '00000000'
|
||||
assert module.buildrequires[0].stream_version == 280000
|
||||
|
||||
@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',
|
||||
|
||||
Reference in New Issue
Block a user