Example #1
0
def test_report_hunter_timeout(bson_library, mongo_host, status, time_later,
                               should_timeout, test_db_name, test_lib_name):
    job_id = str(uuid.uuid4())
    report_name = str(uuid.uuid4())

    serializer = PyMongoNotebookResultSerializer(
        database_name=test_db_name,
        mongo_host=mongo_host,
        result_collection_name=test_lib_name)
    start_time = time_now = datetime.datetime(2018, 1, 12, 2, 30)
    with freezegun.freeze_time(time_now):
        serializer.save_check_stub(job_id, report_name, status=status)
        _report_hunter(
            Serializer.PYMONGO.value,
            mongo_host=mongo_host,
            database_name=test_db_name,
            result_collection_name=test_lib_name,
            run_once=True,
        )
        expected = NotebookResultPending(
            job_id=job_id,
            report_name=report_name,
            report_title=report_name,
            status=status,
            update_time=time_now,
            job_start_time=start_time,
        )
        assert get_report_cache(report_name, job_id) == expected

    time_now += time_later
    with freezegun.freeze_time(time_now):
        _report_hunter(
            Serializer.PYMONGO.value,
            mongo_host=mongo_host,
            database_name=test_db_name,
            result_collection_name=test_lib_name,
            run_once=True,
        )

        if should_timeout:
            mins = (time_later.total_seconds() / 60) - 1
            expected = NotebookResultError(
                job_id=job_id,
                report_name=report_name,
                report_title=report_name,
                status=JobStatus.TIMEOUT,
                update_time=time_now,
                job_start_time=start_time,
                error_info=
                "This request timed out while being submitted to run. "
                "Please try again! "
                "Timed out after {:.0f} minutes 0 seconds.".format(mins),
            )
        else:
            # expected does not change
            pass
        assert get_report_cache(report_name, job_id) == expected
Example #2
0
def test_report_hunter_with_status_change(bson_library, mongo_host,
                                          test_db_name, test_lib_name):
    initialise_base_dirs()
    serializer = PyMongoNotebookResultSerializer(
        database_name=test_db_name,
        mongo_host=mongo_host,
        result_collection_name=test_lib_name)

    job_id = str(uuid.uuid4())
    report_name = str(uuid.uuid4())
    with freezegun.freeze_time(datetime.datetime(2018, 1, 12, 2, 30)):
        serializer.save_check_stub(job_id, report_name)
        _report_hunter(
            Serializer.PYMONGO.value,
            mongo_host=mongo_host,
            database_name=test_db_name,
            result_collection_name=test_lib_name,
            run_once=True,
        )
        expected = NotebookResultPending(
            job_id=job_id,
            report_name=report_name,
            report_title=report_name,
            update_time=datetime.datetime(2018, 1, 12, 2, 30),
            job_start_time=datetime.datetime(2018, 1, 12, 2, 30),
        )
        assert get_report_cache(report_name, job_id) == expected

    with freezegun.freeze_time(datetime.datetime(2018, 1, 12, 2, 32)):
        serializer.update_check_status(job_id,
                                       JobStatus.CANCELLED,
                                       error_info="This was cancelled!")
        _report_hunter(
            Serializer.PYMONGO.value,
            mongo_host=mongo_host,
            database_name=test_db_name,
            result_collection_name=test_lib_name,
            run_once=True,
        )

        expected = NotebookResultError(
            job_id=job_id,
            report_name=report_name,
            report_title=report_name,
            status=JobStatus.CANCELLED,
            update_time=datetime.datetime(2018, 1, 12, 2, 32),
            job_start_time=datetime.datetime(2018, 1, 12, 2, 30),
            error_info="This was cancelled!",
        )
        assert get_report_cache(report_name, job_id) == expected
Example #3
0
def test_report_hunter_timeout(bson_library, status, time_later,
                               should_timeout, webapp_config):
    job_id = str(uuid.uuid4())
    report_name = str(uuid.uuid4())

    serializer = initialize_serializer_from_config(webapp_config)
    start_time = time_now = datetime.datetime(2018, 1, 12, 2, 30)
    with freezegun.freeze_time(time_now):
        serializer.save_check_stub(job_id, report_name, status=status)
        _report_hunter(webapp_config=webapp_config, run_once=True)
        expected = NotebookResultPending(
            job_id=job_id,
            report_name=report_name,
            report_title=report_name,
            status=status,
            update_time=time_now,
            job_start_time=start_time,
        )
        assert get_report_cache(report_name,
                                job_id,
                                cache_dir=webapp_config.CACHE_DIR) == expected

    time_now += time_later
    with freezegun.freeze_time(time_now):
        _report_hunter(webapp_config=webapp_config, run_once=True)

        if should_timeout:
            mins = (time_later.total_seconds() / 60) - 1
            expected = NotebookResultError(
                job_id=job_id,
                report_name=report_name,
                report_title=report_name,
                status=JobStatus.TIMEOUT,
                update_time=time_now,
                job_start_time=start_time,
                error_info=
                "This request timed out while being submitted to run. "
                "Please try again! "
                "Timed out after {:.0f} minutes 0 seconds.".format(mins),
            )
        else:
            # expected does not change
            pass
        assert get_report_cache(report_name,
                                job_id,
                                cache_dir=webapp_config.CACHE_DIR) == expected
Example #4
0
def test_report_hunter_with_status_change(bson_library, webapp_config):
    initialise_base_dirs(webapp_config=webapp_config)
    serializer = initialize_serializer_from_config(webapp_config)

    job_id = str(uuid.uuid4())
    report_name = str(uuid.uuid4())
    with freezegun.freeze_time(datetime.datetime(2018, 1, 12, 2, 30)):
        serializer.save_check_stub(job_id, report_name)
        _report_hunter(webapp_config=webapp_config, run_once=True)
        expected = NotebookResultPending(
            job_id=job_id,
            report_name=report_name,
            report_title=report_name,
            update_time=datetime.datetime(2018, 1, 12, 2, 30),
            job_start_time=datetime.datetime(2018, 1, 12, 2, 30),
        )
        assert get_report_cache(report_name,
                                job_id,
                                cache_dir=webapp_config.CACHE_DIR) == expected

    with freezegun.freeze_time(datetime.datetime(2018, 1, 12, 2, 32)):
        serializer.update_check_status(job_id,
                                       JobStatus.CANCELLED,
                                       error_info="This was cancelled!")
        _report_hunter(webapp_config=webapp_config, run_once=True)

        expected = NotebookResultError(
            job_id=job_id,
            report_name=report_name,
            report_title=report_name,
            status=JobStatus.CANCELLED,
            update_time=datetime.datetime(2018, 1, 12, 2, 32),
            job_start_time=datetime.datetime(2018, 1, 12, 2, 30),
            error_info="This was cancelled!",
        )
        assert get_report_cache(report_name,
                                job_id,
                                cache_dir=webapp_config.CACHE_DIR) == expected
def run_report(
    job_submit_time,
    report_name,
    overrides,
    result_serializer,
    report_title="",
    job_id=None,
    output_base_dir=None,
    template_base_dir=None,
    attempts_remaining=2,
    mailto="",
    generate_pdf_output=True,
    prepare_only=False,
):

    job_id = job_id or str(uuid.uuid4())
    stop_execution = os.getenv("NOTEBOOKER_APP_STOPPING")
    if stop_execution:
        logger.info(
            "Aborting attempt to run %s, jobid=%s as app is shutting down.",
            report_name, job_id)
        result_serializer.update_check_status(job_id,
                                              JobStatus.CANCELLED,
                                              error_info=CANCEL_MESSAGE)
        return
    try:
        logger.info(
            "Calculating a new %s ipynb with parameters: %s (attempts remaining: %s)",
            report_name,
            overrides,
            attempts_remaining,
        )
        result_serializer.update_check_status(job_id,
                                              report_name=report_name,
                                              job_start_time=job_submit_time,
                                              status=JobStatus.PENDING)
        result = _run_checks(
            job_id,
            job_submit_time,
            report_name,
            report_title,
            output_base_dir,
            template_base_dir,
            overrides,
            mailto=mailto,
            generate_pdf_output=generate_pdf_output,
            prepare_only=prepare_only,
        )
        logger.info("Successfully got result.")
        result_serializer.save_check_result(result)
        logger.info("Saved result to mongo successfully.")
    except Exception:
        error_info = traceback.format_exc()
        logger.exception("%s report failed! (job id=%s)", report_name, job_id)
        result = NotebookResultError(
            job_id=job_id,
            job_start_time=job_submit_time,
            report_name=report_name,
            report_title=report_title,
            error_info=error_info,
            overrides=overrides,
            mailto=mailto,
            generate_pdf_output=generate_pdf_output,
        )
        logger.error(
            "Report run failed. Saving error result to mongo library %s@%s...",
            result_serializer.database_name,
            result_serializer.mongo_host,
        )
        result_serializer.save_check_result(result)
        logger.info("Error result saved to mongo successfully.")
        if attempts_remaining > 0:
            logger.info("Retrying report.")
            return run_report(
                job_submit_time,
                report_name,
                overrides,
                result_serializer,
                report_title=report_title,
                job_id=job_id,
                output_base_dir=output_base_dir,
                template_base_dir=template_base_dir,
                attempts_remaining=attempts_remaining - 1,
                mailto=mailto,
                generate_pdf_output=generate_pdf_output,
                prepare_only=prepare_only,
            )
        else:
            logger.info(
                "Abandoning attempt to run report. It failed too many times.")
    return result
Example #6
0
    def _convert_result(
        self,
        result: Dict,
        load_payload: bool = True
    ) -> Union[NotebookResultError, NotebookResultComplete,
               NotebookResultPending, None]:
        if not result:
            return None

        status = result.get("status", "")
        job_status = JobStatus.from_string(status)
        if job_status is None:
            return None
        cls = {
            JobStatus.CANCELLED: NotebookResultError,
            JobStatus.DONE: NotebookResultComplete,
            JobStatus.PENDING: NotebookResultPending,
            JobStatus.ERROR: NotebookResultError,
            JobStatus.SUBMITTED: NotebookResultPending,
            JobStatus.TIMEOUT: NotebookResultError,
            JobStatus.DELETED: None,
        }.get(job_status)
        if cls is None:
            return None

        if load_payload and job_status == JobStatus.DONE:

            def read_file(path):
                try:
                    return self.result_data_store.get_last_version(path).read()
                except NoFile:
                    logger.error("Could not find file %s in %s", path,
                                 self.result_data_store)
                    return ""

            outputs = {
                path: read_file(path)
                for path in result.get("raw_html_resources", {}).get(
                    "outputs", [])
            }
            result["raw_html_resources"]["outputs"] = outputs
            if result.get("generate_pdf_output"):
                pdf_filename = _pdf_filename(result["job_id"])
                result["pdf"] = read_file(pdf_filename)

        if cls == NotebookResultComplete:
            return NotebookResultComplete(
                job_id=result["job_id"],
                job_start_time=result["job_start_time"],
                report_name=result["report_name"],
                status=job_status,
                update_time=result["update_time"],
                job_finish_time=result["job_finish_time"],
                raw_html_resources=result.get("raw_html_resources", {}),
                raw_ipynb_json=result.get("raw_ipynb_json"),
                raw_html=result.get("raw_html"),
                pdf=result.get("pdf", ""),
                overrides=result.get("overrides", {}),
                generate_pdf_output=result.get("generate_pdf_output", True),
                report_title=result.get("report_title", result["report_name"]),
                mailto=result.get("mailto", ""),
                stdout=result.get("stdout", []),
            )
        elif cls == NotebookResultPending:
            return NotebookResultPending(
                job_id=result["job_id"],
                job_start_time=result["job_start_time"],
                report_name=result["report_name"],
                status=job_status,
                update_time=result["update_time"],
                overrides=result.get("overrides", {}),
                generate_pdf_output=result.get("generate_pdf_output", True),
                report_title=result.get("report_title", result["report_name"]),
                mailto=result.get("mailto", ""),
                stdout=result.get("stdout", []),
            )

        elif cls == NotebookResultError:
            return NotebookResultError(
                job_id=result["job_id"],
                job_start_time=result["job_start_time"],
                report_name=result["report_name"],
                status=job_status,
                update_time=result["update_time"],
                error_info=result["error_info"],
                overrides=result.get("overrides", {}),
                generate_pdf_output=result.get("generate_pdf_output", True),
                report_title=result.get("report_title", result["report_name"]),
                mailto=result.get("mailto", ""),
                stdout=result.get("stdout", []),
            )
        else:
            raise ValueError(
                "Could not deserialise {} into result object.".format(result))