Skip to content

direct: Add dashboards support - #3725

Merged
shreyas-goenka merged 104 commits into
mainfrom
direct/dashboard
Nov 5, 2025
Merged

direct: Add dashboards support#3725
shreyas-goenka merged 104 commits into
mainfrom
direct/dashboard

Conversation

@shreyas-goenka

@shreyas-goenkashreyas-goenka commented Oct 6, 2025

Copy link
Copy Markdown
Contributor

Summary

This PR adds support for Databricks Lakeview Dashboards in the direct deployment mode (DATABRICKS_BUNDLE_ENGINE=direct-exp). Dashboards can now be deployed, updated, and deleted directly via API calls without using Terraform.

Key Features

1. Full Dashboard Lifecycle Management

  • Create: Creates draft dashboards and automatically publishes them with warehouse and credential settings
  • Update: Updates both dashboard content and publish settings (warehouse_id, embed_credentials)
  • Delete: Safely trashes dashboards with idempotent handling
  • Refresh: Fetches dashboard state from both draft and published endpoints in parallel

2. Smart Field Change Detection

The implementation uses FieldTriggers to determine the correct action for each field change:

Update Actions (in-place modifications):

  • display_name - Dashboard name changes
  • warehouse_id - SQL warehouse assignment changes
  • embed_credentials - Credential embedding toggle
  • serialized_dashboard - Dashboard content/layout changes

Recreate Actions (delete + create):

  • parent_path - Moving dashboard to different folder requires recreation

Skip Actions (ignored for diff):

  • Output-only fields: dashboard_id, path, create_time, update_time, lifecycle_state
  • etag - Skipped for local changes (user edits), but triggers updates for remote drift detection
  • serialized_dashboard - Skipped for remote drift (etag is sufficient)

3. Advanced Capabilities

Parallel API Calls: Refresh operations fetch both draft and published dashboard states concurrently using goroutines for better performance.

Automatic Parent Directory Creation: If the parent directory doesn't exist, it's automatically created before dashboard creation.

Idempotent Delete: Handles already-trashed dashboards gracefully by checking the dashboard state on 403 errors.

embed_credentials Edge Case: Unlike Terraform, this implementation properly detects changes to the embed_credentials field by fetching published dashboard state separately.

Serialized Dashboard Flexibility: Supports both string and map/object formats for serialized_dashboard in bundle configuration.

4. Comprehensive Test Coverage

Added 5 new acceptance test suites testing field change behavior:

  • change-name - Tests display_name updates
  • change-warehouse-id - Tests warehouse assignment updates
  • change-embed-credentials - Tests credential embedding toggle
  • change-serialized-dashboard - Tests dashboard content updates
  • change-parent-path - Tests parent path changes trigger recreate

Each test verifies:

  • Correct API methods (POST/PATCH/DELETE) are called
  • Dashboard ID changes (or doesn't change) as expected
  • Field values are properly updated in remote state

Testing

Existing and new unit and integration tests.

github-merge-queueBot pushed a commit that referenced this pull request Oct 13, 2025
## Why
Used in #3725 to provide local
test coverage.
## Tests
Existing tests pass with slight modifications.
@eng-dev-ecosystem-bot

eng-dev-ecosystem-bot commented Oct 13, 2025

Copy link
Copy Markdown
Collaborator

Run: 19101439812

Env❌​FAIL🟨​KNOWN🔄​flaky💚​RECOVERED🙈​SKIP✅​pass🙈​skip
💚​aws linux11356592
💚​aws windows11357591
💚​aws-ucws linux11479487
💚​aws-ucws windows11480486
❌​azure linux241351591
❌​azure windows241352590
💚​azure-ucws linux11475486
🔄​azure-ucws windows511471485
❌​gcp linux1411341593
❌​gcp windows2011336592
39 failing tests:
Test Nameaws linuxaws windowsaws-ucws linuxaws-ucws windowsazure linuxazure windowsazure-ucws linuxazure-ucws windowsgcp linuxgcp windows
TestAccept💚​R💚​R💚​R💚​R🔄​f🔄​f💚​R💚​R🟨​K🟨​K
TestAccept/bundle/deployment/bind/experiment✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p❌​F
TestAccept/bundle/deployment/bind/job/job-abort-bind✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p❌​F✅​p
TestAccept/bundle/deployment/unbind/permissions✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p❌​F✅​p
TestAccept/bundle/resources/clusters/deploy/data_security_mode✅​p✅​p✅​p✅​p🔄​f🔄​f✅​p🔄​f✅​p✅​p
TestAccept/bundle/resources/clusters/deploy/data_security_mode/DATABRICKS_BUNDLE_ENGINE=direct✅​p✅​p✅​p✅​p🔄​f🔄​f✅​p🔄​f✅​p✅​p
TestAccept/bundle/resources/clusters/deploy/update-after-create✅​p✅​p✅​p✅​p❌​F❌​F✅​p🔄​f✅​p✅​p
TestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=direct✅​p✅​p✅​p✅​p❌​F❌​F✅​p🔄​f✅​p✅​p
TestAccept/bundle/resources/clusters/deploy/update-after-create/DATABRICKS_BUNDLE_ENGINE=terraform✅​p✅​p✅​p✅​p🔄​f🔄​f✅​p🔄​f✅​p✅​p
TestAccept/bundle/resources/pipelines/lakeflow-pipeline✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p❌​F✅​p
TestAccept/bundle/resources/pipelines/lakeflow-pipeline/DATABRICKS_BUNDLE_ENGINE=direct✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p❌​F✅​p
TestAccept/bundle/resources/pipelines/lakeflow-pipeline/DATABRICKS_BUNDLE_ENGINE=terraform✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p❌​F✅​p
TestAccept/bundle/resources/pipelines/update✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p❌​F✅​p
TestAccept/bundle/resources/pipelines/update/DATABRICKS_BUNDLE_ENGINE=direct✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p❌​F✅​p
TestAccept/bundle/resources/pipelines/update/DATABRICKS_BUNDLE_ENGINE=terraform✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p❌​F✅​p
TestAccept/bundle/run/app-with-job🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S🙈​S
TestAccept/bundle/templates/default-python/combinations/classic✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p❌​F❌​F
TestAccept/bundle/templates/default-python/combinations/classic/DATABRICKS_BUNDLE_ENGINE=direct/DLT=no/NBOOK=no/PY=no✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p❌​F
TestAccept/bundle/templates/default-python/combinations/classic/DATABRICKS_BUNDLE_ENGINE=direct/DLT=no/NBOOK=yes/PY=no✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p❌​F
TestAccept/bundle/templates/default-python/combinations/classic/DATABRICKS_BUNDLE_ENGINE=direct/DLT=no/NBOOK=yes/PY=yes✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p❌​F
TestAccept/bundle/templates/default-python/combinations/classic/DATABRICKS_BUNDLE_ENGINE=direct/DLT=yes/NBOOK=no/PY=no✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p❌​F
TestAccept/bundle/templates/default-python/combinations/classic/DATABRICKS_BUNDLE_ENGINE=direct/DLT=yes/NBOOK=no/PY=yes✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p❌​F
TestAccept/bundle/templates/default-python/combinations/classic/DATABRICKS_BUNDLE_ENGINE=direct/DLT=yes/NBOOK=yes/PY=no✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p❌​F
TestAccept/bundle/templates/default-python/combinations/classic/DATABRICKS_BUNDLE_ENGINE=direct/DLT=yes/NBOOK=yes/PY=yes✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p❌​F
TestAccept/bundle/templates/default-python/combinations/classic/DATABRICKS_BUNDLE_ENGINE=terraform/DLT=no/NBOOK=no/PY=no✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p❌​F
TestAccept/bundle/templates/default-python/combinations/classic/DATABRICKS_BUNDLE_ENGINE=terraform/DLT=no/NBOOK=no/PY=yes✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p❌​F✅​p
TestAccept/bundle/templates/default-python/combinations/classic/DATABRICKS_BUNDLE_ENGINE=terraform/DLT=no/NBOOK=yes/PY=no✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p❌​F❌​F
TestAccept/bundle/templates/default-python/combinations/classic/DATABRICKS_BUNDLE_ENGINE=terraform/DLT=no/NBOOK=yes/PY=yes✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p❌​F✅​p
TestAccept/bundle/templates/default-python/combinations/classic/DATABRICKS_BUNDLE_ENGINE=terraform/DLT=yes/NBOOK=no/PY=no✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p❌​F✅​p
TestAccept/bundle/templates/default-python/combinations/classic/DATABRICKS_BUNDLE_ENGINE=terraform/DLT=yes/NBOOK=no/PY=yes✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p❌​F✅​p
TestAccept/bundle/templates/default-python/combinations/classic/DATABRICKS_BUNDLE_ENGINE=terraform/DLT=yes/NBOOK=yes/PY=yes✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p❌​F
TestSparkJarTaskDeployAndRunOnWorkspace✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p❌​F
TestSparkJarTaskDeployAndRunOnWorkspace/Databricks_Runtime_15.4_LTS✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p❌​F
TestFsCpDir✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p❌​F
TestFsCpDir/dbfs_to_dbfs✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p❌​F
TestFsRmEmptyDir✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p❌​F
TestFsRmEmptyDir/dbfs✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p❌​F
TestFsRmFile✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p❌​F
TestFsRmFile/dbfs✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p✅​p❌​F

shreyas-goenkaand others added 4 commits October 13, 2025 10:01
…ange
This merge incorporates changes from PR #3741 which adds an isLocal
parameter to FieldTriggers and ClassifyChange methods to differentiate
between local changes (user modifications) and remote changes (drift
detection).
Key changes:
- Renamed ActionTypeUnset to ActionTypeUndefined
- Updated FieldTriggers to accept isLocal bool parameter
- Updated ClassifyChange to accept isLocal bool parameter
- Consolidated dashboard's separate FieldTriggersLocal/Remote methods
into single FieldTriggers(isLocal bool) method
- Updated adapter to store separate trigger maps for local and remote
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Resolved conflicts:
- bundle/direct/dresources/adapter.go: Merged documentation for FieldTriggers method, combining detailed explanation from HEAD with note about initialization timing from main
- acceptance/bundle/resources/dashboards/test.toml: Kept HEAD version with proper warehouse requirements and etag replacements for new dashboard tests
Comment threadacceptance/bundle/resources/dashboards/detect-change/script
Comment threadbundle/direct/dresources/dashboard.go Outdated
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@shreyas-goenka@eng-dev-ecosystem-bot@denik