def sync_assessment_statuses(): """Synchronizes issue tracker ticket statuses with the Assessment statuses. Checks for Assessments which are in sync with Issue Tracker issues and updates their statuses in accordance to the corresponding Assessments if differ. """ assessment_issues = sync_utils.collect_issue_tracker_info("Assessment", include_ccs=True) if not assessment_issues: return logger.debug('Syncing state of %d issues.', len(assessment_issues)) cli = issues.Client() processed_ids = set() for batch in sync_utils.iter_issue_batches(assessment_issues.keys()): for issue_id, issuetracker_state in batch.iteritems(): issue_id = str(issue_id) issue_info = assessment_issues.get(issue_id) if not issue_info: logger.warning( 'Got an unexpected issue from Issue Tracker: %s', issue_id) continue processed_ids.add(issue_id) assessment_state = issue_info['state'] status_value = ASSESSMENT_STATUSES_MAPPING.get( assessment_state["status"]) if not status_value: logger.error( 'Inexistent Issue Tracker status for assessment ID=%d ' 'with status: %s.', issue_info['object_id'], status_value) continue assessment_state["status"] = status_value if all( assessment_state.get(field) == issuetracker_state.get( field) for field in FIELDS_TO_CHECK) and _compare_ccs( assessment_state.get("ccs", []), issuetracker_state.get("ccs", [])): continue try: sync_utils.update_issue(cli, issue_id, assessment_state) except integrations_errors.Error as error: logger.error( 'Unable to update status of Issue Tracker issue ID=%s for ' 'assessment ID=%d: %r', issue_id, issue_info['object_id'], error) logger.debug('Sync is done, %d issue(s) were processed.', len(processed_ids)) missing_ids = set(assessment_issues) - processed_ids if missing_ids: logger.warning( 'Some issues are linked to Assessments ' 'but were not found in Issue Tracker: %s', ', '.join(str(i) for i in missing_ids))
def test_update_issue_with_raise(self): """Tests updating issue with raising an exception.""" cli_mock = mock.MagicMock() exception = integrations_errors.HttpError('Test', status=429) cli_mock.update_issue.side_effect = iter([ exception, exception, exception, exception, exception, ]) with mock.patch.object(sync_utils.time, 'sleep') as sleep_mock: with self.assertRaises(integrations_errors.HttpError) as exc_mock: sync_utils.update_issue(cli_mock, 1, 'params') self.assertEqual(exc_mock.exception.status, 429) self.assertEqual(cli_mock.update_issue.call_args_list, [ mock.call(1, 'params'), mock.call(1, 'params'), mock.call(1, 'params'), mock.call(1, 'params'), mock.call(1, 'params'), ]) self.assertEqual(sleep_mock.call_args_list, [ mock.call(1), mock.call(1), mock.call(1), mock.call(1), ])
def sync_assessment_statuses(): """Synchronizes issue tracker ticket statuses with the Assessment statuses. Checks for Assessments which are in sync with Issue Tracker issues and updates their statuses in accordance to the corresponding Assessments if differ. """ assessment_issues = sync_utils.collect_issue_tracker_info("Assessment") if not assessment_issues: return logger.debug('Syncing state of %d issues.', len(assessment_issues)) cli = issues.Client() processed_ids = set() for batch in sync_utils.iter_issue_batches(assessment_issues.keys()): for issue_id, issuetracker_state in batch.iteritems(): issue_id = str(issue_id) issue_info = assessment_issues.get(issue_id) if not issue_info: logger.warning( 'Got an unexpected issue from Issue Tracker: %s', issue_id) continue processed_ids.add(issue_id) assessment_state = issue_info['state'] status_value = ASSESSMENT_STATUSES_MAPPING.get( assessment_state["status"] ) if not status_value: logger.error( 'Inexistent Issue Tracker status for assessment ID=%d ' 'with status: %s.', issue_info['object_id'], status_value ) continue assessment_state["status"] = status_value if all( assessment_state.get(field) == issuetracker_state.get(field) for field in FIELDS_TO_CHECK ): continue try: sync_utils.update_issue(cli, issue_id, assessment_state) except integrations_errors.Error as error: logger.error( 'Unable to update status of Issue Tracker issue ID=%s for ' 'assessment ID=%d: %r', issue_id, issue_info['object_id'], error) logger.debug('Sync is done, %d issue(s) were processed.', len(processed_ids)) missing_ids = set(assessment_issues) - processed_ids if missing_ids: logger.warning( 'Some issues are linked to Assessments ' 'but were not found in Issue Tracker: %s', ', '.join(str(i) for i in missing_ids))
def sync_issue(self, issue_json, issue_id=None): """Update existing issue in issuetracker with provided params.""" return sync_utils.update_issue( self.client, issue_id, issue_json )
def _update_issue(cli, issue_id, object_id, issue_payload): """Update issue tracker with logging state. Args: - cli: object of Issue Tracker Client - issue_id: Id of IssueTracker - object_id: Id of related object for IssueTracker - issue_payload: Dictionary with information for Issue payload. Returns: - """ try: sync_utils.update_issue(cli, issue_id, issue_payload) except integrations_errors.Error as error: logger.error( "Unable to update status of Issue Tracker issue ID=%s for " "assessment ID=%d: %r", issue_id, object_id, error)
def test_update_issue_with_retry(self): """Tests updating issue with retry.""" cli_mock = mock.MagicMock() exception = integrations_errors.HttpError('Test', status=429) cli_mock.update_issue.side_effect = iter([ exception, exception, None, ]) with mock.patch.object(sync_utils.time, 'sleep') as sleep_mock: sync_utils.update_issue(cli_mock, 5, 'params') self.assertEqual(cli_mock.update_issue.call_args_list, [ mock.call(5, 'params'), mock.call(5, 'params'), mock.call(5, 'params'), ]) self.assertEqual(sleep_mock.call_args_list, [ mock.call(5), mock.call(5), ])
def test_update_issue(self): """Tests updating issue.""" cli_mock = mock.MagicMock() self.assertIsNotNone(sync_utils.update_issue(cli_mock, 1, 'params')) cli_mock.update_issue.assert_called_once_with(1, 'params')