mirror of
https://github.com/apache/superset.git
synced 2026-04-20 00:24:38 +00:00
fix(Slack): Fix Slack recipients migration to V2 (#32336)
This commit is contained in:
@@ -308,7 +308,10 @@ def create_report_slack_chart():
|
||||
def create_report_slack_chartv2():
|
||||
chart = db.session.query(Slice).first()
|
||||
report_schedule = create_report_notification(
|
||||
slack_channel="slack_channel_id", chart=chart, name="report_slack_chartv2"
|
||||
slack_channel="slack_channel_id",
|
||||
chart=chart,
|
||||
name="report_slack_chartv2",
|
||||
use_slack_v2=True,
|
||||
)
|
||||
yield report_schedule
|
||||
|
||||
@@ -1300,9 +1303,7 @@ def test_email_dashboard_report_schedule_force_screenshot(
|
||||
assert_log(ReportState.SUCCESS)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures(
|
||||
"load_birth_names_dashboard_with_slices", "create_report_slack_chart"
|
||||
)
|
||||
@pytest.mark.usefixtures("create_report_slack_chart")
|
||||
@patch("superset.commands.report.execute.get_channels_with_search")
|
||||
@patch("superset.reports.notifications.slack.should_use_v2_api", return_value=True)
|
||||
@patch("superset.reports.notifications.slackv2.get_slack_client")
|
||||
@@ -1316,13 +1317,19 @@ def test_slack_chart_report_schedule_converts_to_v2(
|
||||
):
|
||||
"""
|
||||
ExecuteReport Command: Test chart slack report schedule
|
||||
while converting the recipients list to SlackV2.
|
||||
"""
|
||||
# setup screenshot mock
|
||||
screenshot_mock.return_value = SCREENSHOT_FILE
|
||||
|
||||
channel_id = "slack_channel_id"
|
||||
|
||||
get_channels_with_search_mock.return_value = channel_id
|
||||
get_channels_with_search_mock.return_value = [
|
||||
{
|
||||
"id": channel_id,
|
||||
"name": "slack_channel",
|
||||
"is_member": True,
|
||||
"is_private": False,
|
||||
},
|
||||
]
|
||||
|
||||
with freeze_time("2020-01-01T00:00:00Z"):
|
||||
with patch.object(current_app.config["STATS_LOGGER"], "gauge") as statsd_mock:
|
||||
@@ -1357,33 +1364,40 @@ def test_slack_chart_report_schedule_converts_to_v2(
|
||||
assert statsd_mock.call_args_list[1] == call("reports.slack.send.ok", 1)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures(
|
||||
"load_birth_names_dashboard_with_slices", "create_report_slack_chartv2"
|
||||
)
|
||||
@patch("superset.commands.report.execute.get_channels_with_search")
|
||||
@patch("superset.reports.notifications.slack.should_use_v2_api", return_value=True)
|
||||
@patch("superset.reports.notifications.slackv2.get_slack_client")
|
||||
@patch("superset.utils.screenshots.ChartScreenshot.get_screenshot")
|
||||
def test_slack_chart_report_schedule_v2(
|
||||
def test_slack_chart_report_schedule_converts_to_v2_channel_with_hash(
|
||||
screenshot_mock,
|
||||
slack_client_mock,
|
||||
slack_should_use_v2_api_mock,
|
||||
get_channels_with_search_mock,
|
||||
create_report_slack_chart,
|
||||
):
|
||||
"""
|
||||
ExecuteReport Command: Test chart slack report schedule
|
||||
ExecuteReport Command: Test converting a Slack report to v2 when
|
||||
the channel name includes the leading hash (supported in v1).
|
||||
"""
|
||||
# setup screenshot mock
|
||||
screenshot_mock.return_value = SCREENSHOT_FILE
|
||||
channel_id = "slack_channel_id"
|
||||
|
||||
get_channels_with_search_mock.return_value = channel_id
|
||||
chart = db.session.query(Slice).first()
|
||||
report_schedule = create_report_notification(
|
||||
slack_channel="#slack_channel", chart=chart
|
||||
)
|
||||
get_channels_with_search_mock.return_value = [
|
||||
{
|
||||
"id": channel_id,
|
||||
"name": "slack_channel",
|
||||
"is_member": True,
|
||||
"is_private": False,
|
||||
},
|
||||
]
|
||||
|
||||
with freeze_time("2020-01-01T00:00:00Z"):
|
||||
with patch.object(current_app.config["STATS_LOGGER"], "gauge") as statsd_mock:
|
||||
AsyncExecuteReportScheduleCommand(
|
||||
TEST_ID, create_report_slack_chart.id, datetime.utcnow()
|
||||
TEST_ID, report_schedule.id, datetime.utcnow()
|
||||
).run()
|
||||
|
||||
assert (
|
||||
@@ -1395,6 +1409,12 @@ def test_slack_chart_report_schedule_v2(
|
||||
== SCREENSHOT_FILE
|
||||
)
|
||||
|
||||
# Assert that the report recipients were updated
|
||||
assert report_schedule.recipients[0].recipient_config_json == json.dumps(
|
||||
{"target": channel_id}
|
||||
)
|
||||
assert report_schedule.recipients[0].type == ReportRecipientType.SLACKV2
|
||||
|
||||
# Assert logs are correct
|
||||
assert_log(ReportState.SUCCESS)
|
||||
# this will send a warning
|
||||
@@ -1403,6 +1423,94 @@ def test_slack_chart_report_schedule_v2(
|
||||
)
|
||||
assert statsd_mock.call_args_list[1] == call("reports.slack.send.ok", 1)
|
||||
|
||||
cleanup_report_schedule(report_schedule)
|
||||
|
||||
|
||||
@patch("superset.commands.report.execute.get_channels_with_search")
|
||||
@patch("superset.reports.notifications.slack.should_use_v2_api", return_value=True)
|
||||
@patch("superset.reports.notifications.slackv2.get_slack_client")
|
||||
@patch("superset.utils.screenshots.ChartScreenshot.get_screenshot")
|
||||
def test_slack_chart_report_schedule_fails_to_converts_to_v2(
|
||||
screenshot_mock,
|
||||
slack_client_mock,
|
||||
slack_should_use_v2_api_mock,
|
||||
get_channels_with_search_mock,
|
||||
):
|
||||
"""
|
||||
ExecuteReport Command: Test converting a Slack report to v2 fails.
|
||||
"""
|
||||
# setup screenshot mock
|
||||
screenshot_mock.return_value = SCREENSHOT_FILE
|
||||
channel_id = "slack_channel_id"
|
||||
chart = db.session.query(Slice).first()
|
||||
report_schedule = create_report_notification(
|
||||
slack_channel="#slack_channel,my_member_ID", chart=chart
|
||||
)
|
||||
get_channels_with_search_mock.return_value = [
|
||||
{
|
||||
"id": channel_id,
|
||||
"name": "slack_channel",
|
||||
"is_member": True,
|
||||
"is_private": False,
|
||||
},
|
||||
]
|
||||
|
||||
with pytest.raises(ReportScheduleSystemErrorsException):
|
||||
AsyncExecuteReportScheduleCommand(
|
||||
TEST_ID, report_schedule.id, datetime.utcnow()
|
||||
).run()
|
||||
|
||||
# Assert failuer with proper log
|
||||
expected_message = (
|
||||
"Failed to update slack recipients to v2: "
|
||||
"Could not find the following channels: my_member_ID"
|
||||
)
|
||||
assert_log(ReportState.ERROR, error_message=expected_message)
|
||||
|
||||
# Assert that previous configuration was kept for manual correction
|
||||
assert report_schedule.recipients[0].recipient_config_json == json.dumps(
|
||||
{"target": "#slack_channel,my_member_ID"}
|
||||
)
|
||||
assert report_schedule.recipients[0].type == ReportRecipientType.SLACK
|
||||
|
||||
cleanup_report_schedule(report_schedule)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("create_report_slack_chartv2")
|
||||
@patch("superset.reports.notifications.slack.should_use_v2_api", return_value=True)
|
||||
@patch("superset.reports.notifications.slackv2.get_slack_client")
|
||||
@patch("superset.utils.screenshots.ChartScreenshot.get_screenshot")
|
||||
def test_slack_chart_report_schedule_v2(
|
||||
screenshot_mock,
|
||||
slack_client_mock,
|
||||
slack_should_use_v2_api_mock,
|
||||
create_report_slack_chartv2,
|
||||
):
|
||||
"""
|
||||
ExecuteReport Command: Test chart slack report schedule using Slack v2.
|
||||
"""
|
||||
# setup screenshot mock
|
||||
screenshot_mock.return_value = SCREENSHOT_FILE
|
||||
|
||||
with freeze_time("2020-01-01T00:00:00Z"):
|
||||
with patch.object(current_app.config["STATS_LOGGER"], "gauge") as statsd_mock:
|
||||
AsyncExecuteReportScheduleCommand(
|
||||
TEST_ID, create_report_slack_chartv2.id, datetime.utcnow()
|
||||
).run()
|
||||
|
||||
assert (
|
||||
slack_client_mock.return_value.files_upload_v2.call_args[1]["channel"]
|
||||
== "slack_channel_id"
|
||||
)
|
||||
assert (
|
||||
slack_client_mock.return_value.files_upload_v2.call_args[1]["file"]
|
||||
== SCREENSHOT_FILE
|
||||
)
|
||||
|
||||
# Assert logs are correct
|
||||
assert_log(ReportState.SUCCESS)
|
||||
assert statsd_mock.call_args_list[0] == call("reports.slack.send.ok", 1)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures(
|
||||
"load_birth_names_dashboard_with_slices", "create_report_slack_chart"
|
||||
|
||||
@@ -119,6 +119,7 @@ def create_report_notification(
|
||||
owners: Optional[list[User]] = None,
|
||||
ccTarget: Optional[str] = None, # noqa: N803
|
||||
bccTarget: Optional[str] = None, # noqa: N803
|
||||
use_slack_v2: bool = False,
|
||||
) -> ReportSchedule:
|
||||
if not owners:
|
||||
owners = [
|
||||
@@ -130,8 +131,11 @@ def create_report_notification(
|
||||
]
|
||||
|
||||
if slack_channel:
|
||||
type = (
|
||||
ReportRecipientType.SLACKV2 if use_slack_v2 else ReportRecipientType.SLACK
|
||||
)
|
||||
recipient = ReportRecipients(
|
||||
type=ReportRecipientType.SLACK,
|
||||
type=type,
|
||||
recipient_config_json=json.dumps(
|
||||
{
|
||||
"target": slack_channel,
|
||||
|
||||
@@ -52,7 +52,7 @@ from superset.utils.core import (
|
||||
GenericDataType,
|
||||
get_form_data_token,
|
||||
as_list,
|
||||
get_email_address_list,
|
||||
recipients_string_to_list,
|
||||
get_stacktrace,
|
||||
merge_extra_filters,
|
||||
merge_extra_form_data,
|
||||
@@ -809,12 +809,12 @@ class TestUtils(SupersetTestCase):
|
||||
assert expected_filename in path
|
||||
assert os.path.exists(path)
|
||||
|
||||
def test_get_email_address_list(self):
|
||||
assert get_email_address_list("a@a") == ["a@a"]
|
||||
assert get_email_address_list(" a@a ") == ["a@a"]
|
||||
assert get_email_address_list("a@a\n") == ["a@a"]
|
||||
assert get_email_address_list(",a@a;") == ["a@a"]
|
||||
assert get_email_address_list(",a@a; b@b c@c a-c@c; d@d, f@f") == [
|
||||
def test_recipients_string_to_list(self):
|
||||
assert recipients_string_to_list("a@a") == ["a@a"]
|
||||
assert recipients_string_to_list(" a@a ") == ["a@a"]
|
||||
assert recipients_string_to_list("a@a\n") == ["a@a"]
|
||||
assert recipients_string_to_list(",a@a;") == ["a@a"]
|
||||
assert recipients_string_to_list(",a@a; b@b c@c a-c@c; d@d, f@f") == [
|
||||
"a@a",
|
||||
"b@b",
|
||||
"c@c",
|
||||
|
||||
Reference in New Issue
Block a user