Handle lost message from Koji informing MBS about Component being tagged into Koji tag.

Adds new meethod checking the "tagged" and "tagged_in_final" attributes of
"complete" ComponentBuilds in the current batch of module builds
in "building" state against the Koji.

In case the Koji shows the build as tagged/tagged_in_final,
the fake "tagged" message is added to work queue.
This commit is contained in:
Jan Kaluza
2018-12-18 11:56:24 +01:00
parent 3515919a94
commit 3c7f8b7006
2 changed files with 115 additions and 0 deletions

View File

@@ -52,6 +52,7 @@ class MBSProducer(PollingProducer):
self.trigger_new_repo_when_stalled(conf, session)
self.delete_old_koji_targets(conf, session)
self.cleanup_stale_failed_builds(conf, session)
self.sync_koji_build_tags(conf, session)
except Exception:
msg = 'Error in poller execution:'
log.exception(msg)
@@ -371,3 +372,54 @@ class MBSProducer(PollingProducer):
)
build.transition(config, state=models.BUILD_STATES["failed"], state_reason=state_reason)
session.commit()
def sync_koji_build_tags(self, config, session):
"""
Method checking the "tagged" and "tagged_in_final" attributes of
"complete" ComponentBuilds in the current batch of module builds
in "building" state against the Koji.
In case the Koji shows the build as tagged/tagged_in_final,
fake "tagged" message is added to work queue.
"""
if conf.system != 'koji':
return
koji_session = KojiModuleBuilder.get_session(conf, login=False)
module_builds = models.ModuleBuild.by_state(session, "build")
for module_build in module_builds:
complete_components = module_build.current_batch(
koji.BUILD_STATES['COMPLETE'])
for c in complete_components:
# In case the component is tagged in the build tag and
# also tagged in the final tag (or it is build_time_only
# and therefore should not be tagged in final tag), skip it.
if c.tagged and (c.tagged_in_final or c.build_time_only):
continue
log.info("%r: Component %r is complete, but not tagged in the "
"final and/or build tags.", module_build, c)
# Check in which tags the component is tagged.
tag_dicts = koji_session.listTags(c.nvr)
tags = [tag_dict["name"] for tag_dict in tag_dicts]
# If it is tagged in final tag, but MBS does not think so,
# schedule fake message.
if not c.tagged_in_final and module_build.koji_tag in tags:
msg = module_build_service.messaging.KojiTagChange(
'sync_koji_build_tags_fake_message',
module_build.koji_tag, c.package, c.nvr)
log.info(" Scheduling faked event %r" % msg)
module_build_service.scheduler.consumer.work_queue_put(msg)
# If it is tagged in the build tag, but MBS does not think so,
# schedule fake message.
build_tag = module_build.koji_tag + "-build"
if not c.tagged and build_tag in tags:
msg = module_build_service.messaging.KojiTagChange(
'sync_koji_build_tags_fake_message',
build_tag, c.package, c.nvr)
log.info(" Scheduling faked event %r" % msg)
module_build_service.scheduler.consumer.work_queue_put(msg)

View File

@@ -25,6 +25,7 @@ from tests import reuse_component_init_data, db, clean_database
import mock
import koji
from module_build_service.scheduler.producer import MBSProducer
from module_build_service.messaging import KojiTagChange
import six.moves.queue as queue
from datetime import datetime, timedelta
@@ -567,3 +568,65 @@ class TestPoller:
module = models.ModuleBuild.query.filter_by(state=4).all()
assert len(module) == 1
assert module[0].id == 2
@pytest.mark.parametrize('tagged, tagged_in_final', ([True, False], [True, False]))
@patch("module_build_service.builder.KojiModuleBuilder.KojiClientSession")
def test_sync_koji_build_tags(
self, ClientSession, create_builder, global_consumer, dbg,
tagged, tagged_in_final):
module_build_2 = models.ModuleBuild.query.filter_by(id=2).one()
# Only module build 1's build target should be deleted.
module_build_2.koji_tag = 'module-tag1'
module_build_2.state = models.BUILD_STATES['build']
c = module_build_2.current_batch()[0]
c.state = koji.BUILD_STATES["COMPLETE"]
c.tagged_in_final = False
c.tagged = False
db.session.commit()
db.session.refresh(module_build_2)
koji_session = ClientSession.return_value
# No created module build has any of these tags.
ret = []
if tagged:
ret.append(
{
'id': 1,
'name': module_build_2.koji_tag + "-build"
},
)
if tagged_in_final:
ret.append(
{
'id': 2,
'name': module_build_2.koji_tag
},
)
koji_session.listTags.return_value = ret
consumer = mock.MagicMock()
consumer.incoming = queue.Queue()
global_consumer.return_value = consumer
hub = mock.MagicMock()
poller = MBSProducer(hub)
assert consumer.incoming.qsize() == 0
poller.sync_koji_build_tags(conf, db.session)
assert consumer.incoming.qsize() == 2 - len(ret)
expected_msg_tags = []
if tagged:
expected_msg_tags.append(module_build_2.koji_tag + "-build")
if tagged_in_final:
expected_msg_tags.append(module_build_2.koji_tag)
assert len(expected_msg_tags) == consumer.incoming.qsize()
for i in range(consumer.incoming.qsize()):
msg = consumer.incoming.get()
assert isinstance(msg, KojiTagChange)
assert msg.artifact == c.package
assert msg.nvr == c.nvr
assert msg.tag in expected_msg_tags