コード例 #1
0
def test_email_chart_no_alert(create_no_alert_email_chart):
    """
    ExecuteReport Command: Test chart email no alert
    """
    with freeze_time("2020-01-01T00:00:00Z"):
        AsyncExecuteReportScheduleCommand(create_no_alert_email_chart.id,
                                          datetime.utcnow()).run()
    assert_log(ReportState.NOOP)
コード例 #2
0
ファイル: commands_tests.py プロジェクト: ydayma/superset
def test_report_schedule_not_found(create_report_slack_chart):
    """
    ExecuteReport Command: Test report schedule not found
    """
    max_id = db.session.query(func.max(ReportSchedule.id)).scalar()
    with pytest.raises(ReportScheduleNotFoundError):
        AsyncExecuteReportScheduleCommand(test_id, max_id + 1,
                                          datetime.utcnow()).run()
コード例 #3
0
def test_invalid_sql_alert(create_invalid_sql_alert_email_chart):
    """
    ExecuteReport Command: Test alert with invalid SQL statements
    """
    with freeze_time("2020-01-01T00:00:00Z"):
        with pytest.raises((AlertQueryError, AlertQueryInvalidTypeError)):
            AsyncExecuteReportScheduleCommand(
                create_invalid_sql_alert_email_chart.id, datetime.utcnow()
            ).run()
コード例 #4
0
ファイル: commands_tests.py プロジェクト: zzyifan/superset
def test_email_mul_alert(create_mul_alert_email_chart):
    """
    ExecuteReport Command: Test chart email multiple rows
    """
    with freeze_time("2020-01-01T00:00:00Z"):
        with pytest.raises(
            (AlertQueryMultipleRowsError, AlertQueryMultipleColumnsError)):
            AsyncExecuteReportScheduleCommand(create_mul_alert_email_chart.id,
                                              datetime.utcnow()).run()
コード例 #5
0
ファイル: scheduler.py プロジェクト: yike5460/superset
def execute(report_schedule_id: int, scheduled_dttm: str) -> None:
    try:
        scheduled_dttm_ = parser.parse(scheduled_dttm)
        AsyncExecuteReportScheduleCommand(report_schedule_id,
                                          scheduled_dttm_).run()
    except ReportScheduleUnexpectedError as ex:
        logger.error("An unexpected occurred while executing the report: %s",
                     ex)
    except CommandException as ex:
        logger.info("Report state: %s", ex)
コード例 #6
0
def test_grace_period_error(email_mock, create_invalid_sql_alert_email_chart):
    """
    ExecuteReport Command: Test alert grace period on error
    """
    with freeze_time("2020-01-01T00:00:00Z"):
        with pytest.raises((AlertQueryError, AlertQueryInvalidTypeError)):
            AsyncExecuteReportScheduleCommand(
                TEST_ID, create_invalid_sql_alert_email_chart.id, datetime.utcnow()
            ).run()

        # Only needed for MySQL, understand why
        db.session.commit()
        notification_targets = get_target_from_report_schedule(
            create_invalid_sql_alert_email_chart
        )
        # Assert the email smtp address, asserts a notification was sent with the error
        assert email_mock.call_args[0][0] == OWNER_EMAIL
        assert (
            get_notification_error_sent_count(create_invalid_sql_alert_email_chart) == 1
        )

    with freeze_time("2020-01-01T00:30:00Z"):
        with pytest.raises((AlertQueryError, AlertQueryInvalidTypeError)):
            AsyncExecuteReportScheduleCommand(
                TEST_ID, create_invalid_sql_alert_email_chart.id, datetime.utcnow()
            ).run()
        db.session.commit()
        assert (
            get_notification_error_sent_count(create_invalid_sql_alert_email_chart) == 1
        )

    # Grace period ends, assert a notification was sent
    with freeze_time("2020-01-01T01:30:00Z"):
        with pytest.raises((AlertQueryError, AlertQueryInvalidTypeError)):
            AsyncExecuteReportScheduleCommand(
                TEST_ID, create_invalid_sql_alert_email_chart.id, datetime.utcnow()
            ).run()
        db.session.commit()
        assert (
            get_notification_error_sent_count(create_invalid_sql_alert_email_chart) == 2
        )
コード例 #7
0
def test_report_schedule_working(create_report_slack_chart_working):
    """
    ExecuteReport Command: Test report schedule still working
    """
    # setup screenshot mock
    with pytest.raises(ReportSchedulePreviousWorkingError):
        AsyncExecuteReportScheduleCommand(create_report_slack_chart_working.id,
                                          datetime.utcnow()).run()

    assert_log(ReportLogState.ERROR,
               error_message=ReportSchedulePreviousWorkingError.message)
    assert create_report_slack_chart_working.last_state == ReportLogState.WORKING
コード例 #8
0
def test_invalid_sql_alert(email_mock, create_invalid_sql_alert_email_chart):
    """
    ExecuteReport Command: Test alert with invalid SQL statements
    """
    with freeze_time("2020-01-01T00:00:00Z"):
        with pytest.raises((AlertQueryError, AlertQueryInvalidTypeError)):
            AsyncExecuteReportScheduleCommand(
                TEST_ID, create_invalid_sql_alert_email_chart.id,
                datetime.utcnow()).run()

        notification_targets = get_target_from_report_schedule(
            create_invalid_sql_alert_email_chart)
        # Assert the email smtp address, asserts a notification was sent with the error
        assert email_mock.call_args[0][0] == OWNER_EMAIL
コード例 #9
0
ファイル: commands_tests.py プロジェクト: zzyifan/superset
def test_report_schedule_success_grace_end(create_alert_slack_chart_grace):
    """
    ExecuteReport Command: Test report schedule on grace to noop
    """
    # set current time to within the grace period
    current_time = create_alert_slack_chart_grace.last_eval_dttm + timedelta(
        seconds=create_alert_slack_chart_grace.grace_period + 1)

    with freeze_time(current_time):
        AsyncExecuteReportScheduleCommand(create_alert_slack_chart_grace.id,
                                          datetime.utcnow()).run()

    db.session.commit()
    assert create_alert_slack_chart_grace.last_state == ReportState.NOOP
コード例 #10
0
def test_report_schedule_success_grace(create_alert_slack_chart_success):
    """
    ExecuteReport Command: Test report schedule on success to grace
    """
    # set current time to within the grace period
    current_time = create_alert_slack_chart_success.last_eval_dttm + timedelta(
        seconds=create_alert_slack_chart_success.grace_period - 10)

    with freeze_time(current_time):
        AsyncExecuteReportScheduleCommand(TEST_ID,
                                          create_alert_slack_chart_success.id,
                                          datetime.utcnow()).run()

    db.session.commit()
    assert create_alert_slack_chart_success.last_state == ReportState.GRACE
コード例 #11
0
def test_email_disable_screenshot(email_mock, create_alert_email_chart):
    """
    ExecuteReport Command: Test soft timeout on screenshot
    """

    AsyncExecuteReportScheduleCommand(
        TEST_ID, create_alert_email_chart.id, datetime.utcnow()
    ).run()

    notification_targets = get_target_from_report_schedule(create_alert_email_chart)
    # Assert the email smtp address, asserts a notification was sent with the error
    assert email_mock.call_args[0][0] == notification_targets[0]
    # Assert the there is no attached image
    assert email_mock.call_args[1]["images"] is None

    assert_log(ReportState.SUCCESS)
コード例 #12
0
def test_email_chart_report_dry_run(
    screenshot_mock, email_mock, create_report_email_chart,
):
    """
    ExecuteReport Command: Test chart email report schedule dry run
    """
    # setup screenshot mock
    screenshot_mock.return_value = SCREENSHOT_FILE
    app.config["ALERT_REPORTS_NOTIFICATION_DRY_RUN"] = True
    with freeze_time("2020-01-01T00:00:00Z"):
        AsyncExecuteReportScheduleCommand(
            TEST_ID, create_report_email_chart.id, datetime.utcnow()
        ).run()

        email_mock.assert_not_called()
    app.config["ALERT_REPORTS_NOTIFICATION_DRY_RUN"] = False
コード例 #13
0
def test_report_schedule_working(create_report_slack_chart_working):
    """
    ExecuteReport Command: Test report schedule still working
    """
    # setup screenshot mock
    with freeze_time("2020-01-01T00:00:00Z"):
        with pytest.raises(ReportSchedulePreviousWorkingError):
            AsyncExecuteReportScheduleCommand(
                TEST_ID, create_report_slack_chart_working.id, datetime.utcnow()
            ).run()

        assert_log(
            ReportState.WORKING,
            error_message=ReportSchedulePreviousWorkingError.message,
        )
        assert create_report_slack_chart_working.last_state == ReportState.WORKING
コード例 #14
0
def test_soft_timeout_screenshot(screenshot_mock, email_mock,
                                 create_alert_email_chart):
    """
    ExecuteReport Command: Test soft timeout on screenshot
    """
    from celery.exceptions import SoftTimeLimitExceeded

    screenshot_mock.side_effect = SoftTimeLimitExceeded()
    with pytest.raises(ReportScheduleScreenshotTimeout):
        AsyncExecuteReportScheduleCommand(TEST_ID, create_alert_email_chart.id,
                                          datetime.utcnow()).run()

    # Assert the email smtp address, asserts a notification was sent with the error
    assert email_mock.call_args[0][0] == OWNER_EMAIL

    assert_log(ReportState.ERROR,
               error_message="A timeout occurred while taking a screenshot.")
コード例 #15
0
ファイル: scheduler.py プロジェクト: dodopizza/superset
def execute(report_schedule_id: int, scheduled_dttm: str) -> None:
    task_id = None
    try:
        task_id = execute.request.id
        scheduled_dttm_ = parser.parse(scheduled_dttm)
        AsyncExecuteReportScheduleCommand(
            task_id,
            report_schedule_id,
            scheduled_dttm_,
        ).run()
    except ReportScheduleUnexpectedError:
        logger.exception(
            "An unexpected occurred while executing the report: %s", task_id)
    except CommandException:
        logger.exception(
            "A downstream exception occurred while generating"
            " a report: %s", task_id)
コード例 #16
0
def test_alert_limit_is_applied(screenshot_mock, email_mock, create_alert_email_chart):
    """
    ExecuteReport Command: Test that all alerts apply a SQL limit to stmts
    """

    with patch.object(
        create_alert_email_chart.database.db_engine_spec, "execute", return_value=None
    ) as execute_mock:
        with patch.object(
            create_alert_email_chart.database.db_engine_spec,
            "fetch_data",
            return_value=None,
        ) as fetch_data_mock:
            AsyncExecuteReportScheduleCommand(
                test_id, create_alert_email_chart.id, datetime.utcnow()
            ).run()
            assert "LIMIT 2" in execute_mock.call_args[0][1]
コード例 #17
0
def test_slack_token_callable_chart_report(
    screenshot_mock, slack_client_mock_class, create_report_slack_chart,
):
    """
    ExecuteReport Command: Test chart slack alert (slack token callable)
    """
    slack_client_mock_class.return_value = Mock()
    app.config["SLACK_API_TOKEN"] = Mock(return_value="cool_code")
    # setup screenshot mock
    screenshot_mock.return_value = SCREENSHOT_FILE

    with freeze_time("2020-01-01T00:00:00Z"):
        AsyncExecuteReportScheduleCommand(
            TEST_ID, create_report_slack_chart.id, datetime.utcnow()
        ).run()
        app.config["SLACK_API_TOKEN"].assert_called_once()
        assert slack_client_mock_class.called_with(token="cool_code", proxy="")
        assert_log(ReportState.SUCCESS)
コード例 #18
0
def test_slack_chart_alert_no_attachment(email_mock, create_alert_email_chart):
    """
    ExecuteReport Command: Test chart slack alert
    """
    # setup screenshot mock

    with freeze_time("2020-01-01T00:00:00Z"):
        AsyncExecuteReportScheduleCommand(
            TEST_ID, create_alert_email_chart.id, datetime.utcnow()
        ).run()

        notification_targets = get_target_from_report_schedule(create_alert_email_chart)
        # Assert the email smtp address
        assert email_mock.call_args[0][0] == notification_targets[0]
        # Assert the there is no attached image
        assert email_mock.call_args[1]["images"] is None
        # Assert logs are correct
        assert_log(ReportState.SUCCESS)
コード例 #19
0
def test_email_dashboard_report_fails(
    screenshot_mock, email_mock, create_report_email_dashboard
):
    """
    ExecuteReport Command: Test dashboard email report schedule notification fails
    """
    # setup screenshot mock
    from smtplib import SMTPException

    screenshot_mock.return_value = SCREENSHOT_FILE
    email_mock.side_effect = SMTPException("Could not connect to SMTP XPTO")

    with pytest.raises(ReportScheduleNotificationError):
        AsyncExecuteReportScheduleCommand(
            TEST_ID, create_report_email_dashboard.id, datetime.utcnow()
        ).run()

    assert_log(ReportState.ERROR, error_message="Could not connect to SMTP XPTO")
コード例 #20
0
def test_fail_screenshot(screenshot_mock, email_mock, create_report_email_chart):
    """
    ExecuteReport Command: Test soft timeout on screenshot
    """
    from celery.exceptions import SoftTimeLimitExceeded
    from superset.reports.commands.exceptions import AlertQueryTimeout

    screenshot_mock.side_effect = Exception("Unexpected error")
    with pytest.raises(ReportScheduleScreenshotFailedError):
        AsyncExecuteReportScheduleCommand(
            test_id, create_report_email_chart.id, datetime.utcnow()
        ).run()

    notification_targets = get_target_from_report_schedule(create_report_email_chart)
    # Assert the email smtp address, asserts a notification was sent with the error
    assert email_mock.call_args[0][0] == notification_targets[0]

    assert_log(
        ReportState.ERROR, error_message="Failed taking a screenshot Unexpected error"
    )
コード例 #21
0
ファイル: commands_tests.py プロジェクト: zzyifan/superset
def test_slack_chart_report_schedule(screenshot_mock, file_upload_mock,
                                     create_report_slack_chart):
    """
    ExecuteReport Command: Test chart slack report schedule
    """
    # setup screenshot mock
    screenshot = read_fixture("sample.png")
    screenshot_mock.return_value = screenshot

    with freeze_time("2020-01-01T00:00:00Z"):
        AsyncExecuteReportScheduleCommand(create_report_slack_chart.id,
                                          datetime.utcnow()).run()

        notification_targets = get_target_from_report_schedule(
            create_report_slack_chart)
        assert file_upload_mock.call_args[1][
            "channels"] == notification_targets[0]
        assert file_upload_mock.call_args[1]["file"] == screenshot

        # Assert logs are correct
        assert_log(ReportState.SUCCESS)
コード例 #22
0
ファイル: commands_tests.py プロジェクト: zzyifan/superset
def test_report_schedule_working_timeout(create_report_slack_chart_working):
    """
    ExecuteReport Command: Test report schedule still working but should timed out
    """
    # setup screenshot mock
    current_time = create_report_slack_chart_working.last_eval_dttm + timedelta(
        seconds=create_report_slack_chart_working.working_timeout + 1)

    with freeze_time(current_time):
        with pytest.raises(ReportScheduleWorkingTimeoutError):
            AsyncExecuteReportScheduleCommand(
                create_report_slack_chart_working.id, datetime.utcnow()).run()

    # Only needed for MySQL, understand why
    db.session.commit()
    logs = db.session.query(ReportExecutionLog).all()
    assert len(logs) == 1
    assert logs[0].error_message == ReportScheduleWorkingTimeoutError.message
    assert logs[0].state == ReportState.ERROR

    assert create_report_slack_chart_working.last_state == ReportState.ERROR
コード例 #23
0
def test_slack_chart_alert(screenshot_mock, email_mock, create_alert_email_chart):
    """
    ExecuteReport Command: Test chart slack alert
    """
    # setup screenshot mock
    screenshot = read_fixture("sample.png")
    screenshot_mock.return_value = screenshot

    with freeze_time("2020-01-01T00:00:00Z"):
        AsyncExecuteReportScheduleCommand(
            create_alert_email_chart.id, datetime.utcnow()
        ).run()

        notification_targets = get_target_from_report_schedule(create_alert_email_chart)
        # Assert the email smtp address
        assert email_mock.call_args[0][0] == notification_targets[0]
        # Assert the email inline screenshot
        smtp_images = email_mock.call_args[1]["images"]
        assert smtp_images[list(smtp_images.keys())[0]] == screenshot
        # Assert logs are correct
        assert_log(ReportState.SUCCESS)
コード例 #24
0
def test_email_dashboard_report_schedule(screenshot_mock, email_mock,
                                         create_report_email_dashboard):
    """
    ExecuteReport Command: Test dashboard email report schedule
    """
    # setup screenshot mock
    screenshot_mock.return_value = SCREENSHOT_FILE

    with freeze_time("2020-01-01T00:00:00Z"):
        AsyncExecuteReportScheduleCommand(TEST_ID,
                                          create_report_email_dashboard.id,
                                          datetime.utcnow()).run()

        notification_targets = get_target_from_report_schedule(
            create_report_email_dashboard)
        # Assert the email smtp address
        assert email_mock.call_args[0][0] == notification_targets[0]
        # Assert the email inline screenshot
        smtp_images = email_mock.call_args[1]["images"]
        assert smtp_images[list(smtp_images.keys())[0]] == SCREENSHOT_FILE
        # Assert logs are correct
        assert_log(ReportState.SUCCESS)
コード例 #25
0
ファイル: commands_tests.py プロジェクト: zzyifan/superset
def test_soft_timeout_alert(email_mock, create_alert_email_chart):
    """
    ExecuteReport Command: Test soft timeout on alert queries
    """
    from celery.exceptions import SoftTimeLimitExceeded
    from superset.reports.commands.exceptions import AlertQueryTimeout

    with patch.object(create_alert_email_chart.database.db_engine_spec,
                      "execute",
                      return_value=None) as execute_mock:
        execute_mock.side_effect = SoftTimeLimitExceeded()
        with pytest.raises(AlertQueryTimeout):
            AsyncExecuteReportScheduleCommand(create_alert_email_chart.id,
                                              datetime.utcnow()).run()

    notification_targets = get_target_from_report_schedule(
        create_alert_email_chart)
    # Assert the email smtp address, asserts a notification was sent with the error
    assert email_mock.call_args[0][0] == notification_targets[0]

    assert_log(ReportState.ERROR,
               error_message="A timeout occurred while executing the query.")
コード例 #26
0
def test_fail_csv(csv_mock, mock_open, mock_urlopen, email_mock,
                  create_report_email_chart_with_csv):
    """
    ExecuteReport Command: Test error on csv
    """

    response = Mock()
    mock_open.return_value = response
    mock_urlopen.return_value = response
    mock_urlopen.return_value.getcode.return_value = 500

    with pytest.raises(ReportScheduleCsvFailedError):
        AsyncExecuteReportScheduleCommand(
            TEST_ID, create_report_email_chart_with_csv.id,
            datetime.utcnow()).run()

    notification_targets = get_target_from_report_schedule(
        create_report_email_chart_with_csv)
    # Assert the email smtp address, asserts a notification was sent with the error
    assert email_mock.call_args[0][0] == OWNER_EMAIL

    assert_log(ReportState.ERROR,
               error_message="Failed generating csv <urlopen error 500>")
コード例 #27
0
def test_email_chart_report_schedule_with_csv(
    csv_mock,
    email_mock,
    mock_open,
    mock_urlopen,
    create_report_email_chart_with_csv,
):
    """
    ExecuteReport Command: Test chart email report schedule with CSV
    """
    # setup csv mock
    response = Mock()
    mock_open.return_value = response
    mock_urlopen.return_value = response
    mock_urlopen.return_value.getcode.return_value = 200
    response.read.return_value = CSV_FILE

    with freeze_time("2020-01-01T00:00:00Z"):
        AsyncExecuteReportScheduleCommand(
            TEST_ID, create_report_email_chart_with_csv.id,
            datetime.utcnow()).run()

        notification_targets = get_target_from_report_schedule(
            create_report_email_chart_with_csv)
        # assert that the link sent is correct
        assert (
            f'<a href="http://0.0.0.0:8080/superset/slice/'
            f'{create_report_email_chart_with_csv.chart.id}/">Explore in Superset</a>'
            in email_mock.call_args[0][2])
        # Assert the email smtp address
        assert email_mock.call_args[0][0] == notification_targets[0]
        # Assert the email csv file
        smtp_images = email_mock.call_args[1]["data"]
        assert smtp_images[list(smtp_images.keys())[0]] == CSV_FILE
        # Assert logs are correct
        assert_log(ReportState.SUCCESS)
コード例 #28
0
def test_grace_period_error_flap(
    screenshot_mock, email_mock, create_invalid_sql_alert_email_chart,
):
    """
    ExecuteReport Command: Test alert grace period on error
    """
    with freeze_time("2020-01-01T00:00:00Z"):
        with pytest.raises((AlertQueryError, AlertQueryInvalidTypeError)):
            AsyncExecuteReportScheduleCommand(
                TEST_ID, create_invalid_sql_alert_email_chart.id, datetime.utcnow()
            ).run()
        db.session.commit()
        # Assert we have 1 notification sent on the log
        assert (
            get_notification_error_sent_count(create_invalid_sql_alert_email_chart) == 1
        )

    with freeze_time("2020-01-01T00:30:00Z"):
        with pytest.raises((AlertQueryError, AlertQueryInvalidTypeError)):
            AsyncExecuteReportScheduleCommand(
                TEST_ID, create_invalid_sql_alert_email_chart.id, datetime.utcnow()
            ).run()
        db.session.commit()
        assert (
            get_notification_error_sent_count(create_invalid_sql_alert_email_chart) == 1
        )

    # Change report_schedule to valid
    create_invalid_sql_alert_email_chart.sql = "SELECT 1 AS metric"
    create_invalid_sql_alert_email_chart.grace_period = 0
    db.session.merge(create_invalid_sql_alert_email_chart)
    db.session.commit()

    with freeze_time("2020-01-01T00:31:00Z"):
        # One success
        AsyncExecuteReportScheduleCommand(
            TEST_ID, create_invalid_sql_alert_email_chart.id, datetime.utcnow()
        ).run()
        # Grace period ends
        AsyncExecuteReportScheduleCommand(
            TEST_ID, create_invalid_sql_alert_email_chart.id, datetime.utcnow()
        ).run()

        db.session.commit()

    create_invalid_sql_alert_email_chart.sql = "SELECT 'first'"
    create_invalid_sql_alert_email_chart.grace_period = 10
    db.session.merge(create_invalid_sql_alert_email_chart)
    db.session.commit()

    # assert that after a success, when back to error we send the error notification
    # again
    with freeze_time("2020-01-01T00:32:00Z"):
        with pytest.raises((AlertQueryError, AlertQueryInvalidTypeError)):
            AsyncExecuteReportScheduleCommand(
                TEST_ID, create_invalid_sql_alert_email_chart.id, datetime.utcnow()
            ).run()
        db.session.commit()
        assert (
            get_notification_error_sent_count(create_invalid_sql_alert_email_chart) == 2
        )