-
Notifications
You must be signed in to change notification settings - Fork 6
Fix dashboard deployment/creation #230
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
fd41b6c
Rename deploy_dashboard to create_dashboard
JCZuurmond f8b6406
Add legacy deprecation warning
JCZuurmond 04a980a
Add dashboard publish option to create dashboard
JCZuurmond 0ff455e
Update test names
JCZuurmond ed04987
Add test for calling publish
JCZuurmond 3e52db3
Add validate to tile
JCZuurmond 18dd2c4
Let create dashboard expect dashboard metadata
JCZuurmond 9f464a3
Validate dashboard before creating
JCZuurmond a638783
Fix tile validate
JCZuurmond e316f8a
Add test for tile validate raising key error when content is empty
JCZuurmond 41b2b6d
QueryTile with invalid query should raise value error
JCZuurmond 0612d36
Test tiles are from markdown and query files
JCZuurmond cf00ed8
Fix tests
JCZuurmond ddc3b80
Test deploy dashboard is deprecated
JCZuurmond a2bd0c6
Fix docs
JCZuurmond 145fbf0
Assert dashboard id is not None
JCZuurmond 27be252
Fix cli
JCZuurmond f9a043f
Fix integration tests
JCZuurmond 04a1515
Simplify method
JCZuurmond bf9a650
Remove publish
JCZuurmond 7db1fcc
Implement deploy_dashboard with legacy API
JCZuurmond f5bcc48
Implement deploy_dashboard with legacy API
JCZuurmond a393c36
Format
JCZuurmond da90c3f
Remove publish flag
JCZuurmond 8f6b1c1
Test save to folder markdown file
JCZuurmond File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -62,22 +62,21 @@ def tmp_path(tmp_path, make_random): | |
| The folder name becomes the dashboard name, which then becomes the Lakeview file name with the | ||
| `.lvdash.json` extension. `tmp_path` last subfolder contains the test name cut off at thirty characters plus a | ||
| number starting at zero indicating the test run. `tmp_path` adds randomness in the parent folders. Because most test | ||
| start with `test_dashboards_deploys_dashboard_`, the dashboard name for most tests ends up being | ||
| start with `test_dashboards_creates_dashboard_`, the dashboard name for most tests ends up being | ||
| `test_dashboard_deploys_dashboa0.lvdash.json`, causing collisions. This is solved by adding a random subfolder name. | ||
| """ | ||
| folder = tmp_path / f"created_by_lsql_{make_random()}" | ||
| folder.mkdir(parents=True, exist_ok=True) | ||
| return folder | ||
|
|
||
|
|
||
| def test_dashboards_deploys_exported_dashboard_definition(ws, make_dashboard): | ||
| def test_dashboards_creates_exported_dashboard_definition(ws, make_dashboard): | ||
| dashboards = Dashboards(ws) | ||
| sdk_dashboard = make_dashboard() | ||
| dashboard_content = (Path(__file__).parent / "dashboards" / "dashboard.lvdash.json").read_text() | ||
|
|
||
| dashboard_file = Path(__file__).parent / "dashboards" / "dashboard.lvdash.json" | ||
| lakeview_dashboard = Dashboard.from_dict(json.loads(dashboard_file.read_text())) | ||
|
|
||
| sdk_dashboard = dashboards.deploy_dashboard(lakeview_dashboard, dashboard_id=sdk_dashboard.dashboard_id) | ||
| ws.lakeview.update(sdk_dashboard.dashboard_id, serialized_dashboard=dashboard_content) | ||
| lakeview_dashboard = Dashboard.from_dict(json.loads(dashboard_content)) | ||
| new_dashboard = dashboards.get_dashboard(sdk_dashboard.path) | ||
|
|
||
| assert ( | ||
|
|
@@ -92,13 +91,12 @@ def test_dashboard_deploys_dashboard_the_same_as_created_dashboard(ws, make_dash | |
|
|
||
| (tmp_path / "counter.sql").write_text("SELECT 10 AS count") | ||
| dashboard_metadata = DashboardMetadata.from_path(tmp_path) | ||
| lakeview_dashboard = dashboard_metadata.as_lakeview() | ||
|
|
||
| sdk_dashboard = dashboards.deploy_dashboard(lakeview_dashboard, dashboard_id=sdk_dashboard.dashboard_id) | ||
| sdk_dashboard = dashboards.create_dashboard(dashboard_metadata, dashboard_id=sdk_dashboard.dashboard_id) | ||
| new_dashboard = dashboards.get_dashboard(sdk_dashboard.path) | ||
|
|
||
| assert ( | ||
| dashboards._with_better_names(lakeview_dashboard).as_dict() | ||
| dashboards._with_better_names(dashboard_metadata.as_lakeview()).as_dict() | ||
| == dashboards._with_better_names(new_dashboard).as_dict() | ||
| ) | ||
|
|
||
|
|
@@ -110,9 +108,8 @@ def test_dashboard_deploys_dashboard_with_ten_counters(ws, make_dashboard, tmp_p | |
| for i in range(10): | ||
| (tmp_path / f"counter_{i}.sql").write_text(f"SELECT {i} AS count") | ||
| dashboard_metadata = DashboardMetadata.from_path(tmp_path) | ||
| lakeview_dashboard = dashboard_metadata.as_lakeview() | ||
|
|
||
| sdk_dashboard = dashboards.deploy_dashboard(lakeview_dashboard, dashboard_id=sdk_dashboard.dashboard_id) | ||
| sdk_dashboard = dashboards.create_dashboard(dashboard_metadata, dashboard_id=sdk_dashboard.dashboard_id) | ||
|
|
||
| assert ws.lakeview.get(sdk_dashboard.dashboard_id) | ||
|
|
||
|
|
@@ -124,9 +121,8 @@ def test_dashboard_deploys_dashboard_with_display_name(ws, make_dashboard, tmp_p | |
| (tmp_path / "dashboard.yml").write_text("display_name: Counter") | ||
| (tmp_path / "counter.sql").write_text("SELECT 102132 AS count") | ||
| dashboard_metadata = DashboardMetadata.from_path(tmp_path) | ||
| lakeview_dashboard = dashboard_metadata.as_lakeview() | ||
|
|
||
| sdk_dashboard = dashboards.deploy_dashboard(lakeview_dashboard, dashboard_id=sdk_dashboard.dashboard_id) | ||
| sdk_dashboard = dashboards.create_dashboard(dashboard_metadata, dashboard_id=sdk_dashboard.dashboard_id) | ||
|
|
||
| assert ws.lakeview.get(sdk_dashboard.dashboard_id) | ||
|
|
||
|
|
@@ -137,9 +133,8 @@ def test_dashboard_deploys_dashboard_with_counter_variation(ws, make_dashboard, | |
|
|
||
| (tmp_path / "counter.sql").write_text("SELECT 10 AS `Something Else Than Count`") | ||
| dashboard_metadata = DashboardMetadata.from_path(tmp_path) | ||
| lakeview_dashboard = dashboard_metadata.as_lakeview() | ||
|
|
||
| sdk_dashboard = dashboards.deploy_dashboard(lakeview_dashboard, dashboard_id=sdk_dashboard.dashboard_id) | ||
| sdk_dashboard = dashboards.create_dashboard(dashboard_metadata, dashboard_id=sdk_dashboard.dashboard_id) | ||
|
|
||
| assert ws.lakeview.get(sdk_dashboard.dashboard_id) | ||
|
|
||
|
|
@@ -151,14 +146,13 @@ def test_dashboard_deploys_dashboard_with_big_widget(ws, make_dashboard, tmp_pat | |
| query = """-- --width 6 --height 3\nSELECT 82917019218921 AS big_number_needs_big_widget""" | ||
| (tmp_path / "counter.sql").write_text(query) | ||
| dashboard_metadata = DashboardMetadata.from_path(tmp_path) | ||
| lakeview_dashboard = dashboard_metadata.as_lakeview() | ||
|
|
||
| sdk_dashboard = dashboards.deploy_dashboard(lakeview_dashboard, dashboard_id=sdk_dashboard.dashboard_id) | ||
| sdk_dashboard = dashboards.create_dashboard(dashboard_metadata, dashboard_id=sdk_dashboard.dashboard_id) | ||
|
|
||
| assert ws.lakeview.get(sdk_dashboard.dashboard_id) | ||
|
|
||
|
|
||
| def test_dashboards_deploys_dashboard_with_order_overwrite_in_query_header(ws, make_dashboard, tmp_path): | ||
| def test_dashboards_creates_dashboard_with_order_overwrite_in_query_header(ws, make_dashboard, tmp_path): | ||
| dashboards = Dashboards(ws) | ||
| sdk_dashboard = make_dashboard() | ||
|
|
||
|
|
@@ -168,14 +162,13 @@ def test_dashboards_deploys_dashboard_with_order_overwrite_in_query_header(ws, m | |
| # order tiebreaker the query name decides the final order. | ||
| (tmp_path / "4.sql").write_text("-- --order 1\nSELECT 4 AS count") | ||
| dashboard_metadata = DashboardMetadata.from_path(tmp_path) | ||
| lakeview_dashboard = dashboard_metadata.as_lakeview() | ||
|
|
||
| sdk_dashboard = dashboards.deploy_dashboard(lakeview_dashboard, dashboard_id=sdk_dashboard.dashboard_id) | ||
| sdk_dashboard = dashboards.create_dashboard(dashboard_metadata, dashboard_id=sdk_dashboard.dashboard_id) | ||
|
|
||
| assert ws.lakeview.get(sdk_dashboard.dashboard_id) | ||
|
|
||
|
|
||
| def test_dashboards_deploys_dashboard_with_order_overwrite_in_dashboard_yaml(ws, make_dashboard, tmp_path): | ||
| def test_dashboards_creates_dashboard_with_order_overwrite_in_dashboard_yaml(ws, make_dashboard, tmp_path): | ||
| dashboards = Dashboards(ws) | ||
| sdk_dashboard = make_dashboard() | ||
|
|
||
|
|
@@ -192,9 +185,8 @@ def test_dashboards_deploys_dashboard_with_order_overwrite_in_dashboard_yaml(ws, | |
| for query_name in range(6): | ||
| (tmp_path / f"query_{query_name}.sql").write_text(f"SELECT {query_name} AS count") | ||
| dashboard_metadata = DashboardMetadata.from_path(tmp_path) | ||
| lakeview_dashboard = dashboard_metadata.as_lakeview() | ||
|
|
||
| sdk_dashboard = dashboards.deploy_dashboard(lakeview_dashboard, dashboard_id=sdk_dashboard.dashboard_id) | ||
| sdk_dashboard = dashboards.create_dashboard(dashboard_metadata, dashboard_id=sdk_dashboard.dashboard_id) | ||
|
|
||
| assert ws.lakeview.get(sdk_dashboard.dashboard_id) | ||
|
|
||
|
|
@@ -205,58 +197,40 @@ def test_dashboard_deploys_dashboard_with_table(ws, make_dashboard): | |
|
|
||
| dashboard_folder = Path(__file__).parent / "dashboards" / "one_table" | ||
| dashboard_metadata = DashboardMetadata.from_path(dashboard_folder) | ||
| lakeview_dashboard = dashboard_metadata.as_lakeview() | ||
|
|
||
| sdk_dashboard = dashboards.deploy_dashboard(lakeview_dashboard, dashboard_id=sdk_dashboard.dashboard_id) | ||
| sdk_dashboard = dashboards.create_dashboard(dashboard_metadata, dashboard_id=sdk_dashboard.dashboard_id) | ||
|
|
||
| assert ws.lakeview.get(sdk_dashboard.dashboard_id) | ||
|
|
||
|
|
||
| def test_dashboards_deploys_dashboard_with_invalid_query(ws, make_dashboard, tmp_path): | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed as we want the dashboard creation with an invalid query to fail |
||
| dashboards = Dashboards(ws) | ||
| sdk_dashboard = make_dashboard() | ||
|
|
||
| for query_name in range(6): | ||
| (tmp_path / f"{query_name}.sql").write_text(f"SELECT {query_name} AS count") | ||
| (tmp_path / "4.sql").write_text("SELECT COUNT(* AS invalid_column") | ||
| dashboard_metadata = DashboardMetadata.from_path(tmp_path) | ||
| lakeview_dashboard = dashboard_metadata.as_lakeview() | ||
|
|
||
| sdk_dashboard = dashboards.deploy_dashboard(lakeview_dashboard, dashboard_id=sdk_dashboard.dashboard_id) | ||
|
|
||
| assert ws.lakeview.get(sdk_dashboard.dashboard_id) | ||
|
|
||
|
|
||
| def test_dashboards_deploys_dashboard_with_markdown_header(ws, make_dashboard, tmp_path): | ||
| def test_dashboards_creates_dashboard_with_markdown_header(ws, make_dashboard, tmp_path): | ||
| dashboards = Dashboards(ws) | ||
| sdk_dashboard = make_dashboard() | ||
|
|
||
| for count, query_name in enumerate("abcdef"): | ||
| (tmp_path / f"{query_name}.sql").write_text(f"SELECT {count} AS count") | ||
| (tmp_path / "z_description.md").write_text("---\norder: -1\n---\nBelow you see counters.") | ||
| dashboard_metadata = DashboardMetadata.from_path(tmp_path) | ||
| lakeview_dashboard = dashboard_metadata.as_lakeview() | ||
|
|
||
| sdk_dashboard = dashboards.deploy_dashboard(lakeview_dashboard, dashboard_id=sdk_dashboard.dashboard_id) | ||
| sdk_dashboard = dashboards.create_dashboard(dashboard_metadata, dashboard_id=sdk_dashboard.dashboard_id) | ||
|
|
||
| assert ws.lakeview.get(sdk_dashboard.dashboard_id) | ||
|
|
||
|
|
||
| def test_dashboards_deploys_dashboard_with_widget_title_and_description(ws, make_dashboard, tmp_path): | ||
| def test_dashboards_creates_dashboard_with_widget_title_and_description(ws, make_dashboard, tmp_path): | ||
| dashboards = Dashboards(ws) | ||
| sdk_dashboard = make_dashboard() | ||
|
|
||
| description = "-- --title 'Counting' --description 'The answer to life'\nSELECT 42" | ||
| (tmp_path / "counter.sql").write_text(description) | ||
| dashboard_metadata = DashboardMetadata.from_path(tmp_path) | ||
| lakeview_dashboard = dashboard_metadata.as_lakeview() | ||
|
|
||
| sdk_dashboard = dashboards.deploy_dashboard(lakeview_dashboard, dashboard_id=sdk_dashboard.dashboard_id) | ||
| sdk_dashboard = dashboards.create_dashboard(dashboard_metadata, dashboard_id=sdk_dashboard.dashboard_id) | ||
|
|
||
| assert ws.lakeview.get(sdk_dashboard.dashboard_id) | ||
|
|
||
|
|
||
| def test_dashboards_deploys_dashboard_from_query_with_cte(ws, make_dashboard, tmp_path): | ||
| def test_dashboards_creates_dashboard_from_query_with_cte(ws, make_dashboard, tmp_path): | ||
| dashboards = Dashboards(ws) | ||
| sdk_dashboard = make_dashboard() | ||
|
|
||
|
|
@@ -269,24 +243,22 @@ def test_dashboards_deploys_dashboard_from_query_with_cte(ws, make_dashboard, tm | |
| ) | ||
| (tmp_path / "table.sql").write_text(query_with_cte) | ||
| dashboard_metadata = DashboardMetadata.from_path(tmp_path) | ||
| lakeview_dashboard = dashboard_metadata.as_lakeview() | ||
|
|
||
| sdk_dashboard = dashboards.deploy_dashboard(lakeview_dashboard, dashboard_id=sdk_dashboard.dashboard_id) | ||
| sdk_dashboard = dashboards.create_dashboard(dashboard_metadata, dashboard_id=sdk_dashboard.dashboard_id) | ||
|
|
||
| assert ws.lakeview.get(sdk_dashboard.dashboard_id) | ||
|
|
||
|
|
||
| def test_dashboards_deploys_dashboard_with_filters(ws, make_dashboard, tmp_path): | ||
| def test_dashboards_creates_dashboard_with_filters(ws, make_dashboard, tmp_path): | ||
| dashboards = Dashboards(ws) | ||
| sdk_dashboard = make_dashboard() | ||
|
|
||
| table_query_path = Path(__file__).parent / "dashboards/one_table/databricks_office_locations.sql" | ||
| office_locations = table_query_path.read_text() | ||
| (tmp_path / "table.sql").write_text(f"-- --width 2 --filter City State Country\n{office_locations}") | ||
| dashboard_metadata = DashboardMetadata.from_path(tmp_path) | ||
| lakeview_dashboard = dashboard_metadata.as_lakeview() | ||
|
|
||
| sdk_dashboard = dashboards.deploy_dashboard(lakeview_dashboard, dashboard_id=sdk_dashboard.dashboard_id) | ||
| sdk_dashboard = dashboards.create_dashboard(dashboard_metadata, dashboard_id=sdk_dashboard.dashboard_id) | ||
|
|
||
| assert ws.lakeview.get(sdk_dashboard.dashboard_id) | ||
|
|
||
|
|
@@ -298,8 +270,22 @@ def test_dashboard_deploys_dashboard_with_empty_title(ws, make_dashboard, tmp_pa | |
| query = '-- --overrides \'{"spec": {"frame": {"showTitle": true}}}\'\nSELECT 102132 AS count' | ||
| (tmp_path / "counter.sql").write_text(query) | ||
| dashboard_metadata = DashboardMetadata.from_path(tmp_path) | ||
| lakeview_dashboard = dashboard_metadata.as_lakeview() | ||
|
|
||
| sdk_dashboard = dashboards.deploy_dashboard(lakeview_dashboard, dashboard_id=sdk_dashboard.dashboard_id) | ||
| sdk_dashboard = dashboards.create_dashboard(dashboard_metadata, dashboard_id=sdk_dashboard.dashboard_id) | ||
|
|
||
| assert ws.lakeview.get(sdk_dashboard.dashboard_id) | ||
|
|
||
|
|
||
| def test_dashboards_creates_dashboard_via_legacy_method(ws, make_dashboard, tmp_path): | ||
| dashboards = Dashboards(ws) | ||
| sdk_dashboard = make_dashboard() | ||
|
|
||
| (tmp_path / "a.md").write_text("Below you see counters.") | ||
| for count, query_name in enumerate("bcdefg"): | ||
| (tmp_path / f"{query_name}.sql").write_text(f"SELECT {count} AS count") | ||
| dashboard_metadata = DashboardMetadata.from_path(tmp_path) | ||
| dashboard = dashboard_metadata.as_lakeview() | ||
|
|
||
| sdk_dashboard = dashboards.deploy_dashboard(dashboard, dashboard_id=sdk_dashboard.dashboard_id) | ||
|
|
||
| assert ws.lakeview.get(sdk_dashboard.dashboard_id) | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To use the
DashboardMetadata.validateon the before dashboard creation, the signature is updated to expectDashboardMetadatainstead ofDashboard. For backwards capability, thedeploy_dashboardsignature is unchanged, but intended to be deprecated. The implementation below creates theDashboardMetadatafrom theDashboardthrough saving the dashboard to a temporary folder.@nfx: Do you want to add a date to the deprecation warning?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
one transition version is fine