def test_run_reports_handles_error(): reports = [ ReportConfig("nonexistent", None, ["*****@*****.**"], "subject1", 600, "a.ssignee"), ReportConfig("diagnostic", {}, ["*****@*****.**"], "subject2", 600, "a.ssignee") ] config = Config() wrapper = OrderlyWebClientWrapper(config) success = {} error = {} def success_callback(report, version): success[report.name] = version def error_callback(report, message): error[report.name] = message running_reports_repository = RunningReportsRepository() versions = run_reports(wrapper, "testGroup", "testDisease", "testTouchstone", config, reports, success_callback, error_callback, running_reports_repository) keys = list(versions.keys()) assert len(keys) == 1 assert versions[keys[0]]["published"] is True assert success["diagnostic"] == keys[0] assert "Failure for key" in error["nonexistent"] assert len(success) == 1 assert len(error) == 1
def test_retries_when_token_expired(logging): auth = MockReturnAuthorisedClient().auth wrapper = OrderlyWebClientWrapper(None, auth) success = {} error = {} def success_callback(report, version): success["called"] = True def error_callback(report, version=None): error["called"] = True mock_running_reports = MockRunningReportRepository() versions = run_reports(wrapper, group, disease, touchstone, MockConfig(), reports, success_callback, error_callback, mock_running_reports) assert versions == {"r1-version": {"published": True, "report": "r1"}} logging.info.assert_has_calls([ call("Running report: r1 with parameters touchstone=2021test-1," " touchstone_name=2021test. " "Key is r1-key. Timeout is 1000s."), call("Success for key r1-key. New version is r1-version"), call("Publishing report version r1-r1-version"), call("Successfully published report version r1-r1-version") ], any_order=False) assert success["called"] is True assert len(error) == 0
def test_handles_auth_errors(logging_ow, logging_reports): wrapper = OrderlyWebClientWrapper({}) success = {} error = {} def success_callback(report, version): success["called"] = True def error_callback(report, version=None): error["called"] = True mock_running_reports = MockRunningReportRepository() versions = run_reports(wrapper, group, disease, touchstone, MockConfig(), reports, success_callback, error_callback, mock_running_reports) # the wrapper will have an auth failure because no auth config # supplied expected_error = AttributeError( "'dict' object has no attribute 'montagu_url'") logging_ow.exception.assert_called_once_with( ExceptionMatching(expected_error)) logging_reports.error.assert_called_once_with( "Orderlyweb authentication failed; could not begin task") assert len(success) == 0 assert len(versions) == 0 assert error["called"] is True
def test_run_reports_with_run_error(logging): run_successfully = ["r2"] report_responses = { "r2-key": [ReportStatusResult({"status": "success", "version": "r2-version", "output": None})] } ow = MockOrderlyWebAPI(run_successfully, report_responses, expected_params, expected_timeouts) wrapper = OrderlyWebClientWrapper(None, lambda x: ow) success = {} error = {"called": False} def success_callback(report, version): success["called"] = True def error_callback(report, message): error["called"] = message mock_running_reports = MockRunningReportRepository() versions = run_reports(wrapper, group, disease, touchstone, MockConfig(), reports, success_callback, error_callback, mock_running_reports) assert versions == { "r2-version": {"published": True, "report": "r2"} } expected_err = "test-run-error: r1" logging.info.assert_has_calls([ call(expected_run_rpt_2_log), call("Success for key r2-key. New version is r2-version"), call("Publishing report version r2-r2-version"), call("Successfully published report version r2-r2-version") ], any_order=False) args, kwargs = logging.exception.call_args assert str(args[0]) == expected_err # Different from standard set of expected calls, as error running r1 mock_running_reports.get.assert_has_calls([ call(group, disease, "r1"), call(group, disease, "r2") ], any_order=False) mock_running_reports.set.assert_has_calls([ call(group, disease, "r2", "r2-key") ], any_order=False) mock_running_reports.delete_if_matches.assert_has_calls([ call(group, disease, "r2", "r2-key") ], any_order=False) ow.kill_report.assert_not_called() assert success["called"] is True assert error["called"] == expected_err
def test_run_reports_kills_currently_running(logging): run_successfully = ["r1", "r2"] report_responses = { "r1-key": [ReportStatusResult({"status": "success", "version": "r1-version", "output": None})], "r2-key": [ReportStatusResult({"status": "success", "version": "r2-version", "output": None})] } ow = MockOrderlyWebAPI(run_successfully, report_responses, expected_params, expected_timeouts) wrapper = OrderlyWebClientWrapper(None, lambda x: ow) success = {} error = {"called": False} def success_callback(report, version): success["called"] = True def error_callback(report, message): error["called"] = message mock_running_reports = \ MockRunningReportRepository(["r1-old-key", "r2-old-key"]) versions = run_reports(wrapper, group, disease, touchstone, MockConfig(), reports, success_callback, error_callback, mock_running_reports) assert versions == { "r1-version": {"published": True, "report": "r1"}, "r2-version": {"published": True, "report": "r2"} } logging.info.assert_has_calls([ call("Killing already running report: r1. Key is r1-old-key"), call(expected_run_rpt_1_log), call("Killing already running report: r2. Key is r2-old-key"), call(expected_run_rpt_2_log), call("Success for key r1-key. New version is r1-version"), call("Publishing report version r1-r1-version"), call("Successfully published report version r1-r1-version"), call("Success for key r2-key. New version is r2-version"), call("Publishing report version r2-r2-version"), call("Successfully published report version r2-r2-version") ], any_order=False) mock_running_reports.assert_expected_calls() ow.kill_report.assert_has_calls([ call("r1-old-key"), call("r2-old-key") ], any_order=False) assert success["called"] is True assert error["called"] is False
def run_diagnostic_reports(group, disease, touchstone, utc_time, # ISO string e.g 2020-11-03T10:15:30 scenario, *additional_recipients): config = Config() reports = config.diagnostic_reports(group, disease) if len(reports) > 0: wrapper = OrderlyWebClientWrapper(config) emailer = Emailer(config.smtp_host, config.smtp_port, config.smtp_user, config.smtp_password) yt_token = config.youtrack_token if yt_token is None or yt_token == "None": # allow yt token passed as env var when running locally # or during CI tests yt_token = os.environ["YOUTRACK_TOKEN"] yt = YTClient('https://mrc-ide.myjetbrains.com/youtrack/', token=yt_token) def success_callback(report, version): send_diagnostic_report_email(emailer, report, version, group, disease, touchstone, utc_time, scenario, config, *additional_recipients) create_ticket(group, disease, touchstone, scenario, report, version, None, yt, config) def error_callback(report, error): create_ticket(group, disease, touchstone, scenario, report, None, error, yt, config) running_reports_repo = RunningReportsRepository(host=config.host) return run_reports(wrapper, group, disease, touchstone, config, reports, success_callback, error_callback, running_reports_repo) else: msg = "No configured diagnostic reports for group {}, disease {}" logging.warning(msg.format(group, disease)) return {}
def test_run_reports_with_publish_failure(logging): run_successfully = ["r1", "r2"] report_responses = { "r1-key": [ReportStatusResult({"status": "success", "version": "r1-version", "output": None})], "r2-key": [ReportStatusResult({"status": "success", "version": "r2-version", "output": None})] } fail_publish = ["r2"] ow = MockOrderlyWebAPI(run_successfully, report_responses, expected_params, expected_timeouts, fail_publish) wrapper = OrderlyWebClientWrapper(None, lambda x: ow) success = {} error = {} def success_callback(report, version): success["called"] = version def error_callback(report, message): error["called"] = message mock_running_reports = MockRunningReportRepository() versions = run_reports(wrapper, group, disease, touchstone, MockConfig(), reports, success_callback, error_callback, mock_running_reports) assert versions == { "r1-version": {"published": True, "report": "r1"}, "r2-version": {"published": False, "report": "r2"} } expected_err = "Failed to publish report version r2-r2-version" logging.info.assert_has_calls([ call(expected_run_rpt_1_log), call(expected_run_rpt_2_log), call("Success for key r1-key. New version is r1-version"), call("Publishing report version r1-r1-version"), call("Successfully published report version r1-r1-version"), call("Success for key r2-key. New version is r2-version"), call("Publishing report version r2-r2-version") ], any_order=False) logging.error.assert_has_calls([ call(expected_err) ], any_order=False) mock_running_reports.assert_expected_calls() ow.kill_report.assert_not_called() assert success["called"] == "r1-version" assert error["called"] == expected_err
def test_run_reports_with_multi_hyphen_touchstone(): run_successfully = ["r1", "r2"] report_responses = { "r1-key": [ReportStatusResult({"status": "success", "version": "r1-version", "output": None})], "r2-key": [ReportStatusResult({"status": "success", "version": "r2-version", "output": None})] } multi_touchstone = "2021test-extra-1" expected_multi_params = { "r1": {"touchstone": "2021test-extra-1", "touchstone_name": "2021test-extra"}, "r2": {"p1": "v1", "touchstone": "2021test-extra-1", "touchstone_name": "2021test-extra"} } ow = MockOrderlyWebAPI(run_successfully, report_responses, expected_multi_params, expected_timeouts) wrapper = OrderlyWebClientWrapper(None, lambda x: ow) success = {} error = {"called": False} def success_callback(report, version): success["called"] = True def error_callback(report, message): error["called"] = message mock_running_reports = MockRunningReportRepository() versions = run_reports(wrapper, group, disease, multi_touchstone, MockConfig(), reports, success_callback, error_callback, mock_running_reports) assert versions == { "r1-version": {"published": True, "report": "r1"}, "r2-version": {"published": True, "report": "r2"} } assert success["called"] is True assert error["called"] is False