From cf7bc3d7973e71190f688ddb0ebcc2e801646a45 Mon Sep 17 00:00:00 2001 From: Yashash Gaurav Date: Thu, 30 Oct 2025 17:55:31 -0700 Subject: [PATCH 1/3] fix(dashboards): Detect content changes for file_path attribute --- dashboards/resource_dashboard.go | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/dashboards/resource_dashboard.go b/dashboards/resource_dashboard.go index b1c9d71be2..15cbad4b65 100644 --- a/dashboards/resource_dashboard.go +++ b/dashboards/resource_dashboard.go @@ -20,11 +20,16 @@ type Dashboard struct { DashboardChangeDetected bool `json:"dashboard_change_detected,omitempty"` } -func customDiffSerializedDashboard(k, old, new string, d *schema.ResourceData) bool { - _, newHash, err := common.ReadSerializedJsonContent(new, d.Get("file_path").(string)) +func customDiffDashboardContent(k, old, new string, d *schema.ResourceData) bool { + // Read both serialized_dashboard and file_path from the new config + serializedDashboard := d.Get("serialized_dashboard").(string) + filePath := d.Get("file_path").(string) + + _, newHash, err := common.ReadSerializedJsonContent(serializedDashboard, filePath) if err != nil { - return false + return false // Show diff on error } + // Suppress diff if: stored MD5 matches new hash AND no external changes detected return d.Get("md5").(string) == newHash && !d.Get("dashboard_change_detected").(bool) } @@ -53,8 +58,11 @@ func (Dashboard) CustomizeSchema(s *common.CustomizableSchema) *common.Customiza // Default values s.SchemaPath("embed_credentials").SetDefault(true) - // DiffSuppressFunc - s.SchemaPath("serialized_dashboard").SetCustomSuppressDiff(customDiffSerializedDashboard) + // DiffSuppressFunc - Custom diff logic for serialized_dashboard + s.SchemaPath("serialized_dashboard").SetCustomSuppressDiff(customDiffDashboardContent) + + // Apply same custom diff to file_path to enable content change detection + s.SchemaPath("file_path").SetCustomSuppressDiff(customDiffDashboardContent) return s } From b457c79ff490664b85b9041e75cdfe4f58c6d03c Mon Sep 17 00:00:00 2001 From: Yashash Gaurav Date: Fri, 31 Oct 2025 11:27:17 -0700 Subject: [PATCH 2/3] fix(changelog): Update `databricks_dashboard` resource to detect content changes for `file_path` attribute --- NEXT_CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEXT_CHANGELOG.md b/NEXT_CHANGELOG.md index e974787df3..16ef161b4d 100644 --- a/NEXT_CHANGELOG.md +++ b/NEXT_CHANGELOG.md @@ -8,6 +8,8 @@ ### Bug Fixes +* Fixed `databricks_dashboard` resource to detect content changes when using the `file_path` attribute. Previously, only changes to the path string itself triggered updates, not changes to the file content. + ### Documentation ### Exporter From ec8a692b6e48b9f1bb33bc82c4571b543fb5cfb3 Mon Sep 17 00:00:00 2001 From: Yashash Gaurav Date: Fri, 31 Oct 2025 11:27:31 -0700 Subject: [PATCH 3/3] feat(dashboards): Add test for dashboard creation using file path with temporary JSON file --- dashboards/resource_dashboard_test.go | 63 +++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/dashboards/resource_dashboard_test.go b/dashboards/resource_dashboard_test.go index 564dcc99b1..2162a7d9c1 100644 --- a/dashboards/resource_dashboard_test.go +++ b/dashboards/resource_dashboard_test.go @@ -2,6 +2,7 @@ package dashboards import ( "fmt" + "os" "testing" "github.com/databricks/databricks-sdk-go/apierr" @@ -66,6 +67,68 @@ func TestDashboardCreate(t *testing.T) { }) } +func TestDashboardCreateWithFilePath(t *testing.T) { + // Create a temporary file with dashboard JSON content + tmpFile, err := os.CreateTemp("", "dashboard-*.json") + assert.NoError(t, err) + defer os.Remove(tmpFile.Name()) + + _, err = tmpFile.WriteString("serialized_json") + assert.NoError(t, err) + tmpFile.Close() + + qa.ResourceFixture{ + MockWorkspaceClientFunc: func(w *mocks.MockWorkspaceClient) { + e := w.GetMockLakeviewAPI().EXPECT() + e.Create(mock.Anything, dashboards.CreateDashboardRequest{ + Dashboard: dashboards.Dashboard{ + DisplayName: "Dashboard name", + WarehouseId: "abc", + ParentPath: "/path", + SerializedDashboard: "serialized_json", + }, + }).Return(&dashboards.Dashboard{ + DashboardId: "xyz", + DisplayName: "Dashboard name", + SerializedDashboard: "serialized_json_2", + WarehouseId: "abc", + UpdateTime: "2125678", + }, nil) + e.Publish(mock.Anything, dashboards.PublishRequest{ + EmbedCredentials: true, + WarehouseId: "abc", + DashboardId: "xyz", + ForceSendFields: []string{"EmbedCredentials"}, + }).Return(&dashboards.PublishedDashboard{ + EmbedCredentials: true, + WarehouseId: "abc", + DisplayName: "Dashboard name", + RevisionCreateTime: "823828", + }, nil) + e.Get(mock.Anything, dashboards.GetDashboardRequest{ + DashboardId: "xyz", + }).Return(&dashboards.Dashboard{ + DashboardId: "xyz", + DisplayName: "Dashboard name", + SerializedDashboard: "serialized_json_2", + WarehouseId: "abc", + UpdateTime: "2125678", + }, nil) + }, + Resource: ResourceDashboard(), + Create: true, + HCL: fmt.Sprintf(` + display_name = "Dashboard name" + warehouse_id = "abc" + parent_path = "/path" + file_path = "%s" + `, tmpFile.Name()), + }.ApplyAndExpectData(t, map[string]any{ + "id": "xyz", + "display_name": "Dashboard name", + }) +} + func TestDashboardCreate_NoParent(t *testing.T) { qa.ResourceFixture{ MockWorkspaceClientFunc: func(w *mocks.MockWorkspaceClient) {