#1085 Show expanded buildrequires in API output
Merged 4 months ago by mprahl. Opened 5 months ago by cqi.
cqi/fm-orchestrator show-buildrequires-in-api  into  master

@@ -35,6 +35,7 @@ 

  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 @@ 

          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 @@ 

              '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()

file modified
+18 -2

@@ -41,6 +41,22 @@ 

  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 @@ 

          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 @@ 

          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')

@@ -34,6 +34,7 @@ 

  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 @@ 

                  "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 @@ 

                  "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 @@ 

                  "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 @@ 

              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 @@ 

  

          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')

I prefer the use of {} instead of dict(). It's technically faster as well.

+         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')

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

I prefer the use of {} instead of dict(). It's technically faster as well.

Commit 8d36d97 fixes this pull-request

Pull-Request has been merged by mprahl

4 months ago

Pull-Request has been merged by mprahl

4 months ago