mirror of
https://github.com/apache/superset.git
synced 2026-04-19 16:14:52 +00:00
feat: add a command to import dashboards (#11749)
* feat: add a command to import dashboards * Fix lint * Remove print()
This commit is contained in:
@@ -14,16 +14,30 @@
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
# pylint: disable=no-self-use, invalid-name
|
||||
|
||||
import json
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
import yaml
|
||||
|
||||
from superset import db, security_manager
|
||||
from superset.commands.exceptions import CommandInvalidError
|
||||
from superset.commands.importers.exceptions import IncorrectVersionError
|
||||
from superset.dashboards.commands.exceptions import DashboardNotFoundError
|
||||
from superset.dashboards.commands.export import ExportDashboardsCommand
|
||||
from superset.dashboards.commands.importers.v1 import ImportDashboardsCommand
|
||||
from superset.models.dashboard import Dashboard
|
||||
from tests.base_tests import SupersetTestCase
|
||||
from tests.fixtures.importexport import (
|
||||
chart_config,
|
||||
dashboard_config,
|
||||
dashboard_metadata_config,
|
||||
database_config,
|
||||
dataset_config,
|
||||
dataset_metadata_config,
|
||||
)
|
||||
|
||||
|
||||
class TestExportDashboardsCommand(SupersetTestCase):
|
||||
@@ -188,3 +202,168 @@ class TestExportDashboardsCommand(SupersetTestCase):
|
||||
"metadata",
|
||||
"version",
|
||||
]
|
||||
|
||||
|
||||
class TestImportDashboardsCommand(SupersetTestCase):
|
||||
def test_import_v1_dashboard(self):
|
||||
"""Test that we can import a dashboard"""
|
||||
contents = {
|
||||
"metadata.yaml": yaml.safe_dump(dashboard_metadata_config),
|
||||
"databases/imported_database.yaml": yaml.safe_dump(database_config),
|
||||
"datasets/imported_dataset.yaml": yaml.safe_dump(dataset_config),
|
||||
"charts/imported_chart.yaml": yaml.safe_dump(chart_config),
|
||||
"dashboards/imported_dashboard.yaml": yaml.safe_dump(dashboard_config),
|
||||
}
|
||||
command = ImportDashboardsCommand(contents)
|
||||
command.run()
|
||||
|
||||
dashboard = (
|
||||
db.session.query(Dashboard).filter_by(uuid=dashboard_config["uuid"]).one()
|
||||
)
|
||||
assert dashboard.dashboard_title == "Test dash"
|
||||
assert dashboard.description is None
|
||||
assert dashboard.css == ""
|
||||
assert dashboard.slug is None
|
||||
assert json.loads(dashboard.position_json) == {
|
||||
"CHART-SVAlICPOSJ": {
|
||||
"children": [],
|
||||
"id": "CHART-SVAlICPOSJ",
|
||||
"meta": {
|
||||
"chartId": 83,
|
||||
"height": 50,
|
||||
"sliceName": "Number of California Births",
|
||||
"uuid": "0c23747a-6528-4629-97bf-e4b78d3b9df1",
|
||||
"width": 4,
|
||||
},
|
||||
"parents": ["ROOT_ID", "GRID_ID", "ROW-dP_CHaK2q"],
|
||||
"type": "CHART",
|
||||
},
|
||||
"DASHBOARD_VERSION_KEY": "v2",
|
||||
"GRID_ID": {
|
||||
"children": ["ROW-dP_CHaK2q"],
|
||||
"id": "GRID_ID",
|
||||
"parents": ["ROOT_ID"],
|
||||
"type": "GRID",
|
||||
},
|
||||
"HEADER_ID": {
|
||||
"id": "HEADER_ID",
|
||||
"meta": {"text": "Test dash"},
|
||||
"type": "HEADER",
|
||||
},
|
||||
"ROOT_ID": {"children": ["GRID_ID"], "id": "ROOT_ID", "type": "ROOT"},
|
||||
"ROW-dP_CHaK2q": {
|
||||
"children": ["CHART-SVAlICPOSJ"],
|
||||
"id": "ROW-dP_CHaK2q",
|
||||
"meta": {"0": "ROOT_ID", "background": "BACKGROUND_TRANSPARENT"},
|
||||
"parents": ["ROOT_ID", "GRID_ID"],
|
||||
"type": "ROW",
|
||||
},
|
||||
}
|
||||
assert json.loads(dashboard.json_metadata) == {
|
||||
"color_scheme": None,
|
||||
"default_filters": "{}",
|
||||
"expanded_slices": {},
|
||||
"import_time": 1604342885,
|
||||
"refresh_frequency": 0,
|
||||
"remote_id": 7,
|
||||
"timed_refresh_immune_slices": [],
|
||||
}
|
||||
|
||||
assert len(dashboard.slices) == 1
|
||||
chart = dashboard.slices[0]
|
||||
assert str(chart.uuid) == chart_config["uuid"]
|
||||
|
||||
dataset = chart.table
|
||||
assert str(dataset.uuid) == dataset_config["uuid"]
|
||||
|
||||
database = dataset.database
|
||||
assert str(database.uuid) == database_config["uuid"]
|
||||
|
||||
db.session.delete(dashboard)
|
||||
db.session.delete(chart)
|
||||
db.session.delete(dataset)
|
||||
db.session.delete(database)
|
||||
db.session.commit()
|
||||
|
||||
def test_import_v1_dashboard_multiple(self):
|
||||
"""Test that a dashboard can be imported multiple times"""
|
||||
num_dashboards = db.session.query(Dashboard).count()
|
||||
|
||||
contents = {
|
||||
"metadata.yaml": yaml.safe_dump(dashboard_metadata_config),
|
||||
"databases/imported_database.yaml": yaml.safe_dump(database_config),
|
||||
"datasets/imported_dataset.yaml": yaml.safe_dump(dataset_config),
|
||||
"charts/imported_chart.yaml": yaml.safe_dump(chart_config),
|
||||
"dashboards/imported_dashboard.yaml": yaml.safe_dump(dashboard_config),
|
||||
}
|
||||
command = ImportDashboardsCommand(contents)
|
||||
command.run()
|
||||
command.run()
|
||||
|
||||
new_num_dashboards = db.session.query(Dashboard).count()
|
||||
assert new_num_dashboards == num_dashboards + 1
|
||||
|
||||
dashboard = (
|
||||
db.session.query(Dashboard).filter_by(uuid=dashboard_config["uuid"]).one()
|
||||
)
|
||||
chart = dashboard.slices[0]
|
||||
dataset = chart.table
|
||||
database = dataset.database
|
||||
|
||||
db.session.delete(dashboard)
|
||||
db.session.delete(chart)
|
||||
db.session.delete(dataset)
|
||||
db.session.delete(database)
|
||||
db.session.commit()
|
||||
|
||||
def test_import_v1_dashboard_validation(self):
|
||||
"""Test different validations applied when importing a dashboard"""
|
||||
# metadata.yaml must be present
|
||||
contents = {
|
||||
"databases/imported_database.yaml": yaml.safe_dump(database_config),
|
||||
"datasets/imported_dataset.yaml": yaml.safe_dump(dataset_config),
|
||||
"charts/imported_chart.yaml": yaml.safe_dump(chart_config),
|
||||
"dashboards/imported_dashboard.yaml": yaml.safe_dump(dashboard_config),
|
||||
}
|
||||
command = ImportDashboardsCommand(contents)
|
||||
with pytest.raises(IncorrectVersionError) as excinfo:
|
||||
command.run()
|
||||
assert str(excinfo.value) == "Missing metadata.yaml"
|
||||
|
||||
# version should be 1.0.0
|
||||
contents["metadata.yaml"] = yaml.safe_dump(
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"type": "Database",
|
||||
"timestamp": "2020-11-04T21:27:44.423819+00:00",
|
||||
}
|
||||
)
|
||||
command = ImportDashboardsCommand(contents)
|
||||
with pytest.raises(IncorrectVersionError) as excinfo:
|
||||
command.run()
|
||||
assert str(excinfo.value) == "Must be equal to 1.0.0."
|
||||
|
||||
# type should be Database
|
||||
contents["metadata.yaml"] = yaml.safe_dump(dataset_metadata_config)
|
||||
command = ImportDashboardsCommand(contents)
|
||||
with pytest.raises(CommandInvalidError) as excinfo:
|
||||
command.run()
|
||||
assert str(excinfo.value) == "Error importing dashboard"
|
||||
assert excinfo.value.normalized_messages() == {
|
||||
"metadata.yaml": {"type": ["Must be equal to Dashboard."]}
|
||||
}
|
||||
|
||||
# must also validate datasets
|
||||
broken_config = dataset_config.copy()
|
||||
del broken_config["table_name"]
|
||||
contents["metadata.yaml"] = yaml.safe_dump(dashboard_metadata_config)
|
||||
contents["datasets/imported_dataset.yaml"] = yaml.safe_dump(broken_config)
|
||||
command = ImportDashboardsCommand(contents)
|
||||
with pytest.raises(CommandInvalidError) as excinfo:
|
||||
command.run()
|
||||
assert str(excinfo.value) == "Error importing dashboard"
|
||||
assert excinfo.value.normalized_messages() == {
|
||||
"datasets/imported_dataset.yaml": {
|
||||
"table_name": ["Missing data for required field."],
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user