This is an automated email from the ASF dual-hosted git repository.
beto pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/superset.git
The following commit(s) were added to refs/heads/master by this push:
new 674f234 feat: add logic to creation_method for reports schedule
(#15685)
674f234 is described below
commit 674f234de6f31f998943b083f37144e3685823be
Author: AAfghahi <[email protected]>
AuthorDate: Thu Jul 15 21:27:54 2021 -0400
feat: add logic to creation_method for reports schedule (#15685)
* migration
* added logic for creation_method
* revisions
* added index
* Update
superset/migrations/versions/3317e9248280_add_creation_method_to_reports_model.py
* filters
* Update superset/models/reports.py
Co-authored-by: Beto Dealmeida <[email protected]>
* Update superset/reports/schemas.py
Co-authored-by: Beto Dealmeida <[email protected]>
* Update tests/integration_tests/reports/api_tests.py
Co-authored-by: Beto Dealmeida <[email protected]>
* revisions
Co-authored-by: Beto Dealmeida <[email protected]>
---
superset/models/reports.py | 9 +++
superset/reports/api.py | 11 +++-
superset/reports/schemas.py | 18 ++++++
tests/integration_tests/reports/api_tests.py | 92 ++++++++++++++++++++++++++++
4 files changed, 129 insertions(+), 1 deletion(-)
diff --git a/superset/models/reports.py b/superset/models/reports.py
index 73c74eb..f0bbcac 100644
--- a/superset/models/reports.py
+++ b/superset/models/reports.py
@@ -74,6 +74,12 @@ class ReportDataFormat(str, enum.Enum):
DATA = "CSV"
+class ReportCreationMethodType(str, enum.Enum):
+ CHARTS = "charts"
+ DASHBOARDS = "dashboards"
+ ALERTS_REPORTS = "alerts_reports"
+
+
report_schedule_user = Table(
"report_schedule_user",
metadata,
@@ -102,6 +108,9 @@ class ReportSchedule(Model, AuditMixinNullable):
context_markdown = Column(Text)
active = Column(Boolean, default=True, index=True)
crontab = Column(String(1000), nullable=False)
+ creation_method = Column(
+ String(255), server_default=ReportCreationMethodType.ALERTS_REPORTS
+ )
report_format = Column(String(50), default=ReportDataFormat.VISUALIZATION)
sql = Column(Text())
# (Alerts/Reports) M-O to chart
diff --git a/superset/reports/api.py b/superset/reports/api.py
index c9efae1..ccbda74 100644
--- a/superset/reports/api.py
+++ b/superset/reports/api.py
@@ -84,6 +84,7 @@ class ReportScheduleRestApi(BaseSupersetModelRestApi):
"chart.id",
"chart.slice_name",
"context_markdown",
+ "creation_method",
"crontab",
"dashboard.dashboard_title",
"dashboard.id",
@@ -123,6 +124,7 @@ class ReportScheduleRestApi(BaseSupersetModelRestApi):
"created_by.first_name",
"created_by.last_name",
"created_on",
+ "creation_method",
"crontab",
"crontab_humanized",
"id",
@@ -140,6 +142,7 @@ class ReportScheduleRestApi(BaseSupersetModelRestApi):
"active",
"chart",
"context_markdown",
+ "creation_method",
"crontab",
"dashboard",
"database",
@@ -173,7 +176,13 @@ class ReportScheduleRestApi(BaseSupersetModelRestApi):
"type",
"crontab_humanized",
]
- search_columns = ["name", "active", "created_by", "type", "last_state"]
+ search_columns = [
+ "name",
+ "active",
+ "created_by",
+ "type",
+ "last_state",
+ ]
search_filters = {"name": [ReportScheduleAllTextFilter]}
allowed_rel_fields = {"owners", "chart", "dashboard", "database",
"created_by"}
filter_rel_fields = {
diff --git a/superset/reports/schemas.py b/superset/reports/schemas.py
index 1ea711f..acbb658 100644
--- a/superset/reports/schemas.py
+++ b/superset/reports/schemas.py
@@ -20,8 +20,10 @@ from croniter import croniter
from flask_babel import gettext as _
from marshmallow import fields, Schema, validate, validates_schema
from marshmallow.validate import Length, Range, ValidationError
+from marshmallow_enum import EnumField
from superset.models.reports import (
+ ReportCreationMethodType,
ReportDataFormat,
ReportRecipientType,
ReportScheduleType,
@@ -83,6 +85,10 @@ working_timeout_description = (
"If an alert is staled at a working state, how long until it's state is
reseted to"
" error"
)
+creation_method_description = (
+ "Creation method is used to inform the frontend whether the report/alert
was "
+ "created in the dashboard, chart, or alerts and reports UI."
+)
def validate_crontab(value: Union[bytes, bytearray, str]) -> None:
@@ -150,6 +156,12 @@ class ReportSchedulePostSchema(Schema):
description=sql_description, example="SELECT value FROM
time_series_table"
)
chart = fields.Integer(required=False, allow_none=True)
+ creation_method = EnumField(
+ ReportCreationMethodType,
+ by_value=True,
+ required=True,
+ description=creation_method_description,
+ )
dashboard = fields.Integer(required=False, allow_none=True)
database = fields.Integer(required=False)
owners = fields.List(fields.Integer(description=owners_description))
@@ -226,6 +238,12 @@ class ReportSchedulePutSchema(Schema):
allow_none=True,
)
chart = fields.Integer(required=False, allow_none=True)
+ creation_method = EnumField(
+ ReportCreationMethodType,
+ by_value=True,
+ allow_none=True,
+ description=creation_method_description,
+ )
dashboard = fields.Integer(required=False, allow_none=True)
database = fields.Integer(required=False)
owners = fields.List(fields.Integer(description=owners_description),
required=False)
diff --git a/tests/integration_tests/reports/api_tests.py
b/tests/integration_tests/reports/api_tests.py
index 995aa22..1fe7106 100644
--- a/tests/integration_tests/reports/api_tests.py
+++ b/tests/integration_tests/reports/api_tests.py
@@ -29,6 +29,7 @@ from superset.models.slice import Slice
from superset.models.dashboard import Dashboard
from superset.models.reports import (
ReportSchedule,
+ ReportCreationMethodType,
ReportRecipients,
ReportExecutionLog,
ReportScheduleType,
@@ -269,6 +270,7 @@ class TestReportSchedulesApi(SupersetTestCase):
"changed_on_delta_humanized",
"created_by",
"created_on",
+ "creation_method",
"crontab",
"crontab_humanized",
"id",
@@ -442,6 +444,7 @@ class TestReportSchedulesApi(SupersetTestCase):
"name": "new3",
"description": "description",
"crontab": "0 9 * * *",
+ "creation_method": ReportCreationMethodType.ALERTS_REPORTS,
"recipients": [
{
"type": ReportRecipientType.EMAIL,
@@ -470,6 +473,7 @@ class TestReportSchedulesApi(SupersetTestCase):
assert created_model.crontab == report_schedule_data["crontab"]
assert created_model.chart.id == report_schedule_data["chart"]
assert created_model.database.id == report_schedule_data["database"]
+ assert created_model.creation_method ==
report_schedule_data["creation_method"]
# Rollback changes
db.session.delete(created_model)
db.session.commit()
@@ -487,6 +491,7 @@ class TestReportSchedulesApi(SupersetTestCase):
"type": ReportScheduleType.ALERT,
"name": "name3",
"description": "description",
+ "creation_method": ReportCreationMethodType.ALERTS_REPORTS,
"crontab": "0 9 * * *",
"chart": chart.id,
"database": example_db.id,
@@ -503,6 +508,7 @@ class TestReportSchedulesApi(SupersetTestCase):
"name": "name3",
"description": "description",
"crontab": "0 9 * * *",
+ "creation_method": ReportCreationMethodType.ALERTS_REPORTS,
"chart": chart.id,
}
uri = "api/v1/report/"
@@ -532,6 +538,7 @@ class TestReportSchedulesApi(SupersetTestCase):
"type": ReportScheduleType.REPORT,
"name": "name3",
"description": "description",
+ "creation_method": ReportCreationMethodType.ALERTS_REPORTS,
"crontab": "0 9 * * *",
"chart": chart.id,
"database": example_db.id,
@@ -545,6 +552,7 @@ class TestReportSchedulesApi(SupersetTestCase):
"type": ReportScheduleType.ALERT,
"name": "new3",
"description": "description",
+ "creation_method": ReportCreationMethodType.ALERTS_REPORTS,
"crontab": "0 9 * * *",
"recipients": [
{
@@ -569,6 +577,7 @@ class TestReportSchedulesApi(SupersetTestCase):
"type": ReportScheduleType.ALERT,
"name": "new3",
"description": "description",
+ "creation_method": ReportCreationMethodType.ALERTS_REPORTS,
"crontab": "0 9 * * *",
"recipients": [
{
@@ -592,6 +601,7 @@ class TestReportSchedulesApi(SupersetTestCase):
"type": ReportScheduleType.ALERT,
"name": "new3",
"description": "description",
+ "creation_method": ReportCreationMethodType.ALERTS_REPORTS,
"crontab": "0 9 * * *",
"recipients": [
{
@@ -617,6 +627,7 @@ class TestReportSchedulesApi(SupersetTestCase):
"type": ReportScheduleType.ALERT,
"name": "new4",
"description": "description",
+ "creation_method": ReportCreationMethodType.ALERTS_REPORTS,
"crontab": "0 9 * * *",
"recipients": [
{
@@ -642,6 +653,7 @@ class TestReportSchedulesApi(SupersetTestCase):
"type": ReportScheduleType.ALERT,
"name": "new5",
"description": "description",
+ "creation_method": ReportCreationMethodType.ALERTS_REPORTS,
"crontab": "0 9 * * *",
"recipients": [
{
@@ -678,6 +690,7 @@ class TestReportSchedulesApi(SupersetTestCase):
"name": "new3",
"description": "description",
"crontab": "0 9 * * *",
+ "creation_method": ReportCreationMethodType.ALERTS_REPORTS,
"chart": chart.id,
"dashboard": dashboard.id,
"database": example_db.id,
@@ -701,6 +714,7 @@ class TestReportSchedulesApi(SupersetTestCase):
"type": ReportScheduleType.ALERT,
"name": "new3",
"description": "description",
+ "creation_method": ReportCreationMethodType.ALERTS_REPORTS,
"crontab": "0 9 * * *",
"chart": chart.id,
}
@@ -726,6 +740,7 @@ class TestReportSchedulesApi(SupersetTestCase):
"type": ReportScheduleType.ALERT,
"name": "new3",
"description": "description",
+ "creation_method": ReportCreationMethodType.ALERTS_REPORTS,
"crontab": "0 9 * * *",
"chart": chart_max_id + 1,
"database": database_max_id + 1,
@@ -748,6 +763,7 @@ class TestReportSchedulesApi(SupersetTestCase):
"name": "new3",
"description": "description",
"crontab": "0 9 * * *",
+ "creation_method": ReportCreationMethodType.ALERTS_REPORTS,
"dashboard": dashboard_max_id + 1,
"database": examples_db.id,
}
@@ -757,6 +773,82 @@ class TestReportSchedulesApi(SupersetTestCase):
data = json.loads(rv.data.decode("utf-8"))
assert data == {"message": {"dashboard": "Dashboard does not exist"}}
+ @pytest.mark.usefixtures("load_birth_names_dashboard_with_slices")
+ # TODO (AAfghahi): I am going to enable this when the report schedule
feature is fully finished
+ # def test_create_report_schedule_no_creation_method(self):
+ # """
+ # ReportSchedule Api: Test create report schedule
+ # """
+ # self.login(username="admin")
+
+ # chart = db.session.query(Slice).first()
+ # example_db = get_example_database()
+ # report_schedule_data = {
+ # "type": ReportScheduleType.ALERT,
+ # "name": "new3",
+ # "description": "description",
+ # "crontab": "0 9 * * *",
+ # "recipients": [
+ # {
+ # "type": ReportRecipientType.EMAIL,
+ # "recipient_config_json": {"target":
"[email protected]"},
+ # },
+ # {
+ # "type": ReportRecipientType.SLACK,
+ # "recipient_config_json": {"target": "channel"},
+ # },
+ # ],
+ # "grace_period": 14400,
+ # "working_timeout": 3600,
+ # "chart": chart.id,
+ # "database": example_db.id,
+ # }
+ # uri = "api/v1/report/"
+ # rv = self.client.post(uri, json=report_schedule_data)
+ # response = json.loads(rv.data.decode("utf-8"))
+ # assert response == {
+ # "message": {"creation_method": ["Missing data for required
field."]}
+ # }
+ # assert rv.status_code == 400
+
+ @pytest.mark.usefixtures("load_birth_names_dashboard_with_slices")
+ def test_create_report_schedule_invalid_creation_method(self):
+ """
+ ReportSchedule API: Test create report schedule
+ """
+ self.login(username="admin")
+
+ chart = db.session.query(Slice).first()
+ example_db = get_example_database()
+ report_schedule_data = {
+ "type": ReportScheduleType.ALERT,
+ "name": "new3",
+ "description": "description",
+ "creation_method": "BAD_CREATION_METHOD",
+ "crontab": "0 9 * * *",
+ "recipients": [
+ {
+ "type": ReportRecipientType.EMAIL,
+ "recipient_config_json": {"target": "[email protected]"},
+ },
+ {
+ "type": ReportRecipientType.SLACK,
+ "recipient_config_json": {"target": "channel"},
+ },
+ ],
+ "grace_period": 14400,
+ "working_timeout": 3600,
+ "chart": chart.id,
+ "database": example_db.id,
+ }
+ uri = "api/v1/report/"
+ rv = self.client.post(uri, json=report_schedule_data)
+ response = json.loads(rv.data.decode("utf-8"))
+ assert response == {
+ "message": {"creation_method": ["Invalid enum value
BAD_CREATION_METHOD"]}
+ }
+ assert rv.status_code == 400
+
@pytest.mark.usefixtures("create_report_schedules")
def test_update_report_schedule(self):
"""