#1111 Handle lost message from Koji informing MBS about Component being tagged into Koji tag.
Merged 3 months ago by mcurlej. Opened 4 months ago by jkaluza.
jkaluza/fm-orchestrator factory-3677  into  master

@@ -52,6 +52,7 @@ 

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

              )

              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)

@@ -25,6 +25,7 @@ 

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

          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

Adds new 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,
the fake "tagged" message is added to work queue.

Does this need to consult the configuration value to determine whether or not MBS is responsible for tagging (instead of module tagging service)?

This is about tagging the components (Koji RPM builds) into the modular Koji tag. So MBS is always responsible for this.

The MTS is responsible for tagging the modular content generator build. This commit does not change the MBS behaviour regarding CG build tagging.

I think c.tagged should be c.tagged_in_final since you are checking the destination tag right now.

I think c.tagged_in_final should be c.tagged because you are dealing with the -build tag here. Also, why are you guarding against c.build_time_only here? It seems to me that it shouldn't matter since it's the -build tag.

You should also likely check if the component has build_time_only set to True before checking to see if it's untagged.

It'd be nice to validate the messages as well

rebased onto 3c7f8b7

3 months ago

@mprahl: Updated, there were more issues, please review.

Pull-Request has been merged by mcurlej

3 months ago