Show expanded buildrequires in API output

ModuleBuild.json now includes xmd/mbs/buildrequires in the output JSON
data. As a result, these APIs will show buildrequires by default.

* /module-builds/
* /module-builds/?verbose=True
* /module-builds/$build_id

Buildrequires is accessible like this:

    br_module_names = response_json['buildrequires'].keys()
    br_module_dict = response_json['buildrequires'][module name]

Fixes: FACTORY-2201

Signed-off-by: Chenxiong Qi <cqi@redhat.com>
This commit is contained in:
Chenxiong Qi
2018-11-23 17:30:54 +08:00
parent 086ed4a3f3
commit 04b5a9a2a7
3 changed files with 62 additions and 7 deletions

View File

@@ -35,6 +35,7 @@ import sqlalchemy
from sqlalchemy.orm import validates, scoped_session, sessionmaker, load_only
from flask import has_app_context
from module_build_service import db, log, get_url_for, app, conf, Modulemd
from module_build_service.glib import from_variant_dict
import module_build_service.messaging
from sqlalchemy.orm import lazyload
@@ -620,6 +621,12 @@ class ModuleBuild(MBSBase):
return rv
def json(self, show_tasks=True):
mmd = self.mmd()
xmd = from_variant_dict(mmd.get_xmd())
try:
buildrequires = xmd['mbs']['buildrequires']
except KeyError:
buildrequires = {}
json = self.short_json()
json.update({
'component_builds': [build.id for build in self.component_builds],
@@ -631,7 +638,8 @@ class ModuleBuild(MBSBase):
'state_reason': self.state_reason,
'time_completed': _utc_datetime_to_iso(self.time_completed),
'time_modified': _utc_datetime_to_iso(self.time_modified),
'time_submitted': _utc_datetime_to_iso(self.time_submitted)
'time_submitted': _utc_datetime_to_iso(self.time_submitted),
'buildrequires': buildrequires,
})
if show_tasks:
json['tasks'] = self.tasks()

View File

@@ -41,6 +41,22 @@ app = module_build_service.app
conf = init_config(app)
def read_staged_data(yaml_name):
"""Read module YAML content from staged_data directory
:param str yaml_name: name of YAML file without extension ``.yaml``.
:return: module YAML file's content.
:rtype: str
:raises ValueError: if specified module YAML file does not exist in
staged_data directory.
"""
filename = os.path.join(base_dir, "staged_data", "{}.yaml".format(yaml_name))
if not os.path.exists(filename):
raise ValueError('Staged data {}.yaml does not exist.'.format(yaml_name))
with open(filename, 'r') as mmd:
return mmd.read()
def patch_config():
# add test builders for all resolvers
with_test_builders = dict()
@@ -189,7 +205,7 @@ def _populate_data(session, data_size=10, contexts=False):
build_two.stream = '1'
build_two.version = 2 + index
build_two.state = BUILD_STATES['done']
build_two.modulemd = '' # Skipping since no tests rely on it
build_two.modulemd = read_staged_data('testmodule')
build_two.koji_tag = 'module-postgressql-1.2'
build_two.scmurl = ('git://pkgs.domain.local/modules/postgressql?'
'#aa95886c7a443b36a9ce31abda1f9bef22f2f8c9')
@@ -240,7 +256,7 @@ def _populate_data(session, data_size=10, contexts=False):
build_three.stream = '4.3.43'
build_three.version = 6 + index
build_three.state = BUILD_STATES['wait']
build_three.modulemd = '' # Skipping because no tests rely on it
build_three.modulemd = read_staged_data('testmodule')
build_three.koji_tag = None
build_three.scmurl = ('git://pkgs.domain.local/modules/testmodule?'
'#ca95886c7a443b36a9ce31abda1f9bef22f2f8c9')

View File

@@ -34,6 +34,7 @@ import hashlib
import pytest
from tests import app, init_data, clean_database, reuse_component_init_data
from tests import read_staged_data
from tests.test_scm import base_dir as scm_base_dir
from module_build_service.errors import UnprocessableEntity
from module_build_service.models import ModuleBuild
@@ -295,7 +296,8 @@ class TestViews:
"time_completed": None,
"time_modified": "2016-09-03T12:38:40Z",
"time_submitted": "2016-09-03T12:38:33Z",
"version": "7"
"version": "7",
"buildrequires": {},
},
{
"component_builds": [9, 10],
@@ -331,7 +333,8 @@ class TestViews:
"time_completed": "2016-09-03T11:37:19Z",
"time_modified": "2016-09-03T12:37:19Z",
"time_submitted": "2016-09-03T12:35:33Z",
"version": "3"
"version": "3",
"buildrequires": {},
}
]
@@ -377,7 +380,8 @@ class TestViews:
"time_completed": "2016-09-03T11:25:32Z",
"time_modified": "2016-09-03T11:25:32Z",
"time_submitted": "2016-09-03T11:23:20Z",
"version": "2"
"version": "2",
"buildrequires": {},
}
]
assert items == expected
@@ -701,7 +705,7 @@ class TestViews:
time_submitted=datetime(2018, 11, 15, 16, 8, 18),
time_modified=datetime(2018, 11, 15, 16, 19, 35),
rebuild_strategy='changed-and-after',
modulemd='---'
modulemd=read_staged_data('testmodule'),
)
build.buildrequires.append(platform_f300103)
db.session.add(build)
@@ -1586,3 +1590,30 @@ class TestViews:
assert data['error'] == 'Unprocessable Entity'
assert data['message'].startswith('\'koji_tag\' is not set in xmd[\'mbs\'] for module')
def test_buildrequires_is_included_in_json_output(self):
# Inject xmd/mbs/buildrequires into an existing module build for
# assertion later.
from module_build_service.glib import dict_values, from_variant_dict
from module_build_service.models import make_session
from module_build_service import conf
br_modulea = dict(stream='6', version='1', context='1234')
br_moduleb = dict(stream='10', version='1', context='5678')
with make_session(conf) as session:
build = ModuleBuild.query.first()
mmd = build.mmd()
xmd = from_variant_dict(mmd.get_xmd())
mbs = xmd.setdefault('mbs', {})
buildrequires = mbs.setdefault('buildrequires', {})
buildrequires['modulea'] = br_modulea
buildrequires['moduleb'] = br_moduleb
mmd.set_xmd(dict_values(xmd))
build.modulemd = mmd.dumps()
session.commit()
rv = self.client.get('/module-build-service/1/module-builds/{}'.format(build.id))
data = json.loads(rv.data)
buildrequires = data.get('buildrequires', {})
assert br_modulea == buildrequires.get('modulea')
assert br_moduleb == buildrequires.get('moduleb')