def test_return_added_dependency_relationship(self): event = Event.create(db.session, "test_msg_id", "test", events.TestingEvent) event1 = Event.create(db.session, "test_msg_id2", "test2", events.TestingEvent) db.session.commit() dep_rel = event.add_event_dependency(db.session, event1) db.session.commit() self.assertEqual(event.id, dep_rel.event_id) self.assertEqual(event1.id, dep_rel.event_dependency_id)
def test_add_existing_dependent_event(self): event = Event.create(db.session, "test_msg_id", "test", events.TestingEvent) event1 = Event.create(db.session, "test_msg_id2", "test2", events.TestingEvent) db.session.commit() event.add_event_dependency(db.session, event1) db.session.commit() rel = event.add_event_dependency(db.session, event1) self.assertIsNone(rel) self.assertEqual(event.event_dependencies, [event1]) self.assertEqual(event1.depending_events, [event])
def test_add_a_dependent_event(self): event = Event.create(db.session, "test_msg_id", "test", events.TestingEvent) event1 = Event.create(db.session, "test_msg_id2", "test2", events.TestingEvent) db.session.commit() event.add_event_dependency(db.session, event1) db.session.commit() self.assertEqual(event.event_dependencies, [event1]) self.assertEqual(event.event_dependencies[0].search_key, "test2") self.assertEqual(event1.event_dependencies, []) self.assertEqual(event1.depending_events, [event]) self.assertEqual(event.depending_events, [])
def test_not_rebuild_if_errata_state_is_not_allowed( self, rebuild_if_not_exists): rebuild_if_not_exists.return_value = [Mock(), Mock()] Event.create(db.session, "msg-id-123", "123456", ErrataAdvisoryRPMsSignedEvent, False) db.session.commit() event = ErrataAdvisoryStateChangedEvent( 'msg-id-123', ErrataAdvisory(123456, 'name', 'SHIPPED_LIVE', ['rpm'])) handler = UpdateDBOnAdvisoryChange() msgs = handler.handle(event) self.assertEqual([], msgs)
def test_get_or_create_from_event(self): event = events.TestingEvent('msg-1') # First call creates new event, second call returns the same one. for i in range(2): db_event = Event.get_or_create_from_event(db.session, event) self.assertEqual(db_event.id, 1) self.assertEqual(db_event.message_id, 'msg-1')
def test_event_json_min(self): with patch('freshmaker.models.datetime') as datetime_patch: datetime_patch.utcnow.return_value = datetime.datetime(2017, 8, 21, 13, 42, 20) event = Event.create(db.session, "test_msg_id5", "RHSA-2017-289", events.TestingEvent) build = ArtifactBuild.create(db.session, event, "ed", "module", 1234) build.state = ArtifactBuildState.FAILED ArtifactBuild.create(db.session, event, "mksh", "module", 1235, build) db.session.commit() self.assertEqual(event.json_min(), { 'builds_summary': {'BUILD': 1, 'FAILED': 1, 'total': 2}, 'dry_run': False, 'event_type_id': 3, 'id': 1, 'message_id': 'test_msg_id5', 'requester': None, 'search_key': 'RHSA-2017-289', 'state': 0, 'state_name': 'INITIALIZED', 'state_reason': None, 'time_created': '2017-08-21T13:42:20Z', 'time_done': None, 'url': 'http://localhost:5001/api/1/events/1', 'requested_rebuilds': [], 'requester_metadata': {}, 'depending_events': [], 'depends_on_events': [], })
def test_consumer_mark_event_as_failed_on_exception( self, global_consumer, handle): """ Tests that Consumer.consume marks the DB Event as failed in case there is an error in a handler. """ consumer = self.create_consumer() global_consumer.return_value = consumer @fail_event_on_handler_exception def mocked_handle(cls, msg): event = Event.get_or_create(db.session, "msg_id", "msg_id", 0) ArtifactBuild.create(db.session, event, "foo", 0) db.session.commit() cls.set_context(event) raise ValueError("Expected exception") handle.side_effect = mocked_handle msg = self._compose_state_change_msg() consumer.consume(msg) db_event = Event.get(db.session, "msg_id") for build in db_event.builds: self.assertEqual(build.state, ArtifactBuildState.FAILED.value) self.assertTrue(build.state_reason, "Failed with traceback")
def test_handle(self, allow_build, handle_auto_rebuild, prepare_builds, start_to_build_images): event = BotasErrataShippedEvent("test_msg_id", self.botas_advisory) db_event = Event.get_or_create_from_event(db.session, event) allow_build.return_value = True handle_auto_rebuild.return_value = [{"bundle": 1}, {"bundle": 2}] prepare_builds.return_value = [ ArtifactBuild.create(db.session, db_event, "ed0", "image", 1234, original_nvr="some_name-2-12345", rebuilt_nvr="some_name-2-12346"), ArtifactBuild.create(db.session, db_event, "ed0", "image", 12345, original_nvr="some_name_2-2-2", rebuilt_nvr="some_name_2-2-210") ] self.handler.handle(event) self.handler._prepare_builds.assert_called_once() self.assertEqual(self.handler._prepare_builds.call_args[0][0], db_event) self.assertEqual(self.handler._prepare_builds.call_args[0][1], [{ "bundle": 1 }, { "bundle": 2 }])
def test_event_transition(self): for i, state in enumerate([ EventState.COMPLETE, EventState.COMPLETE.value, "complete"]): event = Event.create(db.session, "test_msg_id_{}".format(i), "test", events.TestingEvent) event.transition(state, "reason") self.assertEqual(event.state, EventState.COMPLETE.value) self.assertTrue(event.time_done is not None)
def test_rebuild_if_not_exists_already_exists(self, advisories_from_event): handler = UpdateDBOnAdvisoryChange() db_event = Event.create(db.session, "msg124", "123", ErrataAdvisoryRPMsSignedEvent) db.session.commit() for manual in [True, False]: for db_event_state in [ EventState.INITIALIZED, EventState.BUILDING, EventState.COMPLETE, EventState.FAILED, EventState.SKIPPED ]: db_event.state = db_event_state db.session.commit() for state in [ "REL_PREP", "PUSH_READY", "IN_PUSH", "SHIPPED_LIVE" ]: advisories_from_event.return_value = [ ErrataAdvisory(123, "RHSA-2017", state, ["rpm"], "Critical") ] ev = ErrataAdvisoryStateChangedEvent( "msg123", ErrataAdvisory(123, 'RHSA-2017', state, ['rpm'])) ev.manual = manual ev.dry_run = manual # use also manual just for the sake of test. ret = handler.handle(ev) if db_event_state == EventState.FAILED or ev.manual: self.assertEqual(len(ret), 1) self.assertEqual(ret[0].manual, manual) self.assertEqual(ret[0].dry_run, manual) else: self.assertEqual(len(ret), 0)
def test_creating_event_and_builds(self): event = Event.create(db.session, "test_msg_id", "RHSA-2017-284", events.TestingEvent) build = ArtifactBuild.create(db.session, event, "ed", "module", 1234, rebuild_reason=RebuildReason.DIRECTLY_AFFECTED.value) ArtifactBuild.create(db.session, event, "mksh", "module", 1235, build, rebuild_reason=RebuildReason.DEPENDENCY.value) db.session.commit() db.session.expire_all() e = db.session.query(Event).filter(event.id == 1).one() self.assertEqual(e.message_id, "test_msg_id") self.assertEqual(e.search_key, "RHSA-2017-284") self.assertEqual(e.event_type, events.TestingEvent) self.assertEqual(len(e.builds.all()), 2) self.assertEqual(e.builds[0].name, "ed") self.assertEqual(e.builds[0].type, 2) self.assertEqual(e.builds[0].state, 0) self.assertEqual(e.builds[0].build_id, 1234) self.assertEqual(e.builds[0].dep_on, None) self.assertEqual(e.builds[0].rebuild_reason, RebuildReason.DIRECTLY_AFFECTED.value) self.assertEqual(e.builds[1].name, "mksh") self.assertEqual(e.builds[1].type, 2) self.assertEqual(e.builds[1].state, 0) self.assertEqual(e.builds[1].build_id, 1235) self.assertEqual(e.builds[1].dep_on.name, "ed") self.assertEqual(e.builds[1].rebuild_reason, RebuildReason.DEPENDENCY.value)
def test_handle_isnt_allowed_by_internal_policy(self): event = BotasErrataShippedEvent("test_msg_id", self.botas_advisory) self.handler.handle(event) db_event = Event.get(db.session, message_id='test_msg_id') self.assertEqual(db_event.state, EventState.SKIPPED.value) self.assertTrue(db_event.state_reason.startswith( "This image rebuild is not allowed by internal policy."))
def test_context_event(self): db_event = Event.get_or_create(db.session, "msg1", "current_event", ErrataAdvisoryRPMsSignedEvent) db.session.commit() handler = MyHandler() handler.set_context(db_event) self.assertEqual(handler.current_db_event_id, db_event.id) self.assertEqual(handler.current_db_artifact_build_id, None)
def test_handle_manual_isnt_allowed_by_internal_policy(self): event = ManualBundleRebuild("test_msg_id", [], []) self.handler.handle(event) db_event = Event.get(db.session, message_id='test_msg_id') self.assertEqual(db_event.state, EventState.SKIPPED.value) self.assertTrue( db_event.state_reason.startswith( "This image rebuild is not allowed by internal policy."))
def test_depending_artifact_builds(self): event = Event.create(db.session, "test_msg_id", "test", events.TestingEvent) parent = ArtifactBuild.create(db.session, event, "parent", "module", 1234) build2 = ArtifactBuild.create(db.session, event, "mksh", "module", 1235, parent) build3 = ArtifactBuild.create(db.session, event, "runtime", "module", 1236, parent) ArtifactBuild.create(db.session, event, "perl-runtime", "module", 1237) db.session.commit() deps = set(parent.depending_artifact_builds()) self.assertEqual(deps, set([build2, build3]))
def setUp(self): super(TestPrepareYumRepo, self).setUp() self.ev = Event.create(db.session, 'msg-id', '123', 100) ArtifactBuild.create(db.session, self.ev, "parent", "image", state=ArtifactBuildState.PLANNED) db.session.commit()
def test_get_published_original_nvr(self): event1 = Event.create(db.session, "id1", "RHSA-1", TestingEvent) ArtifactBuild.create(db.session, event1, "ed0", "image", 1234, original_nvr="nvr1", rebuilt_nvr="nvr1-001") event2 = Event.create(db.session, "id2", "RHSA-1", ManualRebuildWithAdvisoryEvent) ArtifactBuild.create(db.session, event2, "ed1", "image", 12345, original_nvr="nvr1-001", rebuilt_nvr="nvr1-002") event3 = Event.create(db.session, "id3", "RHSA-1", ManualRebuildWithAdvisoryEvent) ArtifactBuild.create(db.session, event3, "ed2", "image", 123456, original_nvr="nvr1-002", rebuilt_nvr="nvr1-003") db.session.commit() self.pyxis()._pagination.side_effect = [[{ "repositories": [{ "published": False }] }], [{ "repositories": [{ "published": True }] }]] ret_nvr = self.handler.get_published_original_nvr("nvr1-003") self.assertEqual(ret_nvr, "nvr1-001")
def test_handle_no_digests_error(self): event = BotasErrataShippedEvent("test_msg_id", self.botas_advisory) self.pyxis().get_digests_by_nvrs.return_value = set() self.botas_advisory._builds = {} self.handler.handle(event) db_event = Event.get(db.session, message_id='test_msg_id') self.assertEqual(db_event.state, EventState.SKIPPED.value) self.assertTrue( db_event.state_reason.startswith("There are no digests for NVRs:"))
def test_context_artifact_build(self): db_event = Event.get_or_create(db.session, "msg1", "current_event", ErrataAdvisoryRPMsSignedEvent) build = ArtifactBuild.create(db.session, db_event, "parent1-1-4", "image") db.session.commit() handler = MyHandler() handler.set_context(build) self.assertEqual(handler.current_db_event_id, db_event.id) self.assertEqual(handler.current_db_artifact_build_id, build.id)
def test_get_published_original_nvr_single_event(self): event1 = Event.create(db.session, "id1", "RHSA-1", TestingEvent) ArtifactBuild.create(db.session, event1, "ed0", "image", 1234, original_nvr="nvr1-0-1", rebuilt_nvr="nvr1-0-2") db.session.commit() self.pyxis()._pagination.return_value = [ {"repositories": [{"published": True}]} ] ret_nvr = self.handler.get_published_original_nvr("nvr1-0-2") self.assertEqual(ret_nvr, "nvr1-0-1")
def test_get_root_dep_on(self): event = Event.create(db.session, "test_msg_id", "test", events.TestingEvent) build1 = ArtifactBuild.create(db.session, event, "ed", "module", 1234) build2 = ArtifactBuild.create(db.session, event, "mksh", "module", 1235, build1) build3 = ArtifactBuild.create(db.session, event, "runtime", "module", 1236, build2) build4 = ArtifactBuild.create(db.session, event, "perl-runtime", "module", 1237, build3) db.session.commit() db.session.expire_all() self.assertEqual(build1.get_root_dep_on(), None) self.assertEqual(build2.get_root_dep_on(), build1) self.assertEqual(build3.get_root_dep_on(), build1) self.assertEqual(build4.get_root_dep_on(), build1)
def test_handle_no_digests_error(self): event = BotasErrataShippedEvent("test_msg_id", self.botas_advisory) self.pyxis().get_manifest_list_digest_by_nvr.return_value = None self.botas_advisory._builds = {} self.handler.handle(event) db_event = Event.get(db.session, message_id='test_msg_id') self.assertEqual(db_event.state, EventState.SKIPPED.value) self.assertTrue( db_event.state_reason.startswith( "None of the original images have digest"))
def test_get_unreleased(self): event1 = Event.create(db.session, "test_msg_id1", "test", events.TestingEvent) event1.state = EventState.COMPLETE event1.released = False event2 = Event.create(db.session, "test_msg_id2", "test", events.TestingEvent) event2.state = EventState.COMPLETE event2.released = True event3 = Event.create(db.session, "test_msg_id3", "test", events.TestingEvent) event3.state = EventState.SKIPPED event3.released = False event4 = Event.create(db.session, "test_msg_id4", "test", events.TestingEvent) event4.state = EventState.SKIPPED event4.released = True db.session.commit() # No state means only COMPLETE should be returned ret = Event.get_unreleased(db.session) self.assertEqual(ret, [event1]) # No state means only COMPLETE should be returned ret = Event.get_unreleased(db.session, states=[EventState.SKIPPED]) self.assertEqual(ret, [event3])
def test_failed_to_build_images_never_built_before(self): """ This test checks that trying to build an image that was never built before (for that branch) will make the build fail. """ self.mock_find_images_to_rebuild.return_value = [self.image_a] self.mock_find_images_trees_to_rebuild = self.patcher.patch( 'find_images_trees_to_rebuild', return_value=[[self.image_a]]) event = FreshmakerAsyncManualBuildEvent( 'msg-id-123', 'another-branch', ['image-a-container']) handler = RebuildImagesOnAsyncManualBuild() handler.handle(event) db_event = Event.get(db.session, 'msg-id-123') self.assertEqual(EventState.FAILED.value, db_event.state)
def test_mark_as_released_wrong_advisory_status(self): db_event = Event.create(db.session, "msg124", "123", ErrataAdvisoryRPMsSignedEvent, False) db.session.commit() for state in ["NEW_FILES", "QE", "REL_PREP", "PUSH_READY", "IN_PUSH"]: ev = ErrataAdvisoryStateChangedEvent( "msg123", ErrataAdvisory(123, "name", state, ['rpm'])) handler = UpdateDBOnAdvisoryChange() handler.handle(ev) db.session.refresh(db_event) self.assertEqual(db_event.released, False)
def handle(self, event): log.info("Finding out all advisories including %s", event.nvr) # When get a signed RPM, first step is to find out advisories # containing that RPM and ensure all builds are signed. errata = Errata() advisories = errata.advisories_from_event(event) # Filter out advisories which are not allowed by configuration. advisories = [ advisory for advisory in advisories if self.allow_build( ArtifactType.IMAGE, advisory_name=advisory.name, advisory_security_impact=advisory.security_impact, advisory_highest_cve_severity=advisory.highest_cve_severity, advisory_state=advisory.state) ] # Filter out advisories which are already in Freshmaker DB. advisories = self._filter_out_existing_advisories(advisories) if not advisories: log.info("No advisories found suitable for rebuilding Docker " "images") return [] if not all((errata.builds_signed(advisory.errata_id) for advisory in advisories)): log.info( 'Not all builds in %s are signed. Do not rebuild any ' 'docker image until signed.', advisories) return [] # Now we know that all advisories with this signed RPM have also other # RPMs signed. We can then proceed and generate # ErrataAdvisoryRPMsSignedEvent. new_events = [] for advisory in advisories: new_event = ErrataAdvisoryRPMsSignedEvent( event.msg_id + "." + str(advisory.name), advisory) db_event = Event.create(db.session, new_event.msg_id, new_event.search_key, new_event.__class__, released=False) db.session.add(db_event) new_events.append(new_event) db.session.commit() return new_events
def test_mark_as_released(self): db_event = Event.create(db.session, "msg124", "123", ErrataAdvisoryRPMsSignedEvent, False) db.session.commit() self.assertEqual(db_event.released, False) ev = ErrataAdvisoryStateChangedEvent( "msg123", ErrataAdvisory(123, "name", "SHIPPED_LIVE", ["rpm"])) handler = UpdateDBOnAdvisoryChange() handler.handle(ev) db.session.refresh(db_event) self.assertEqual(db_event.released, True)
def setUp(self): super(TestCheckUnfinishedKojiTasks, self).setUp() self.koji_read_config_patcher = patch( 'koji.read_config', return_value={'server': 'http://localhost/'}) self.koji_read_config_patcher.start() db_event = Event.get_or_create( db.session, "msg1", "current_event", ErrataAdvisoryRPMsSignedEvent) db_event.state = EventState.BUILDING self.build = ArtifactBuild.create(db.session, db_event, "parent1-1-4", "image") self.build.state = ArtifactBuildState.BUILD self.build.build_id = 10 db.session.commit()
def test_building_single_image(self): """ This tests the successful build of a single image """ self.mock_find_images_to_rebuild.return_value = [self.image_a] self.mock_find_images_trees_to_rebuild = self.patcher.patch( 'find_images_trees_to_rebuild', return_value=[[self.image_a]]) event = FreshmakerAsyncManualBuildEvent( 'msg-id-123', 'test_branch', ['image-a-container']) handler = RebuildImagesOnAsyncManualBuild() handler.handle(event) db_event = Event.get(db.session, 'msg-id-123') self.assertEqual(EventState.BUILDING.value, db_event.state) self.mock_get_image_builds_in_first_batch.assert_called_once_with(db.session) self.assertEqual(len(db_event.builds.all()), 1) self.mock_start_to_build_images.assert_called_once()
def test_start_to_build_images(self, build_artifact): build_artifact.side_effect = [HTTPError('500 Server Error'), 1] db_event = Event.get_or_create(db.session, 'msg1', 'current_event', ErrataAdvisoryRPMsSignedEvent) build = ArtifactBuild.create(db.session, db_event, 'parent1-1-4', 'image') build2 = ArtifactBuild.create(db.session, db_event, 'parent1-1-5', 'image') db.session.commit() handler = MyHandler() with self.assertLogs('freshmaker', 'ERROR'): handler.start_to_build_images([build, build2]) self.assertEqual(build.state, ArtifactBuildState.FAILED.value) self.assertEqual(build2.state, ArtifactBuildState.BUILD.value) self.assertEqual(len(db.session.query(ArtifactBuild).all()), 2)