Dashboards: Remove unique name constraints (#90687)

This commit is contained in:
Ryan McKinley
2024-10-29 08:58:39 +03:00
committed by GitHub
parent c8238c7914
commit 2f40fd6741
16 changed files with 51 additions and 174 deletions
+3 -53
View File
@@ -84,12 +84,6 @@ func (d *dashboardStore) ValidateDashboardBeforeSave(ctx context.Context, dashbo
return err
}
isParentFolderChanged, err = getExistingDashboardByTitleAndFolder(sess, dashboard, overwrite,
isParentFolderChanged)
if err != nil {
return err
}
return nil
})
if err != nil {
@@ -353,49 +347,6 @@ func getExistingDashboardByIDOrUIDForUpdate(sess *db.Session, dash *dashboards.D
return isParentFolderChanged, nil
}
// getExistingDashboardByTitleAndFolder returns a boolean (on whether the parent folder changed) and an error for if the dashboard already exists.
func getExistingDashboardByTitleAndFolder(sess *db.Session, dash *dashboards.Dashboard, overwrite,
isParentFolderChanged bool) (bool, error) {
var existing dashboards.Dashboard
condition := "org_id=? AND title=?"
args := []any{dash.OrgID, dash.Title}
if dash.FolderUID != "" {
condition += " AND folder_uid=?"
args = append(args, dash.FolderUID)
} else {
condition += " AND folder_uid IS NULL"
}
exists, err := sess.Where(condition, args...).Get(&existing)
if err != nil {
return isParentFolderChanged, fmt.Errorf("SQL query for existing dashboard by org ID or folder ID failed: %w", err)
}
if exists && dash.ID != existing.ID {
if existing.IsFolder && !dash.IsFolder {
return isParentFolderChanged, dashboards.ErrDashboardWithSameNameAsFolder
}
if !existing.IsFolder && dash.IsFolder {
return isParentFolderChanged, dashboards.ErrDashboardFolderWithSameNameAsDashboard
}
metrics.MFolderIDsServiceCount.WithLabelValues(metrics.Dashboard).Inc()
// nolint:staticcheck
if !dash.IsFolder && (dash.FolderID != existing.FolderID || dash.ID == 0) {
isParentFolderChanged = true
}
if overwrite {
dash.SetID(existing.ID)
dash.SetUID(existing.UID)
dash.SetVersion(existing.Version)
} else {
return isParentFolderChanged, dashboards.ErrDashboardWithSameNameInFolderExists
}
}
return isParentFolderChanged, nil
}
func saveDashboard(sess *db.Session, cmd *dashboards.SaveDashboardCommand, emitEntityEvent bool) (*dashboards.Dashboard, error) {
dash := cmd.GetDashboardModel()
@@ -797,8 +748,8 @@ func (d *dashboardStore) GetDashboard(ctx context.Context, query *dashboards.Get
dashboard := dashboards.Dashboard{OrgID: query.OrgID, ID: query.ID, UID: query.UID}
mustCols := []string{}
if query.Title != nil {
dashboard.Title = *query.Title
if query.Title != nil { // nolint:staticcheck
dashboard.Title = *query.Title // nolint:staticcheck
mustCols = append(mustCols, "title")
}
@@ -806,8 +757,7 @@ func (d *dashboardStore) GetDashboard(ctx context.Context, query *dashboards.Get
dashboard.FolderUID = *query.FolderUID
mustCols = append(mustCols, "folder_uid")
} else if query.FolderID != nil { // nolint:staticcheck
// nolint:staticcheck
dashboard.FolderID = *query.FolderID
dashboard.FolderID = *query.FolderID // nolint:staticcheck
mustCols = append(mustCols, "folder_id")
metrics.MFolderIDsServiceCount.WithLabelValues(metrics.Dashboard).Inc()
}
@@ -781,40 +781,6 @@ func TestIntegrationDashboard_Filter(t *testing.T) {
assert.Equal(t, dashB.ID, results[0].ID)
}
func TestGetExistingDashboardByTitleAndFolder(t *testing.T) {
sqlStore := db.InitTestDB(t)
cfg := setting.NewCfg()
quotaService := quotatest.New(false, nil)
dashboardStore, err := ProvideDashboardStore(sqlStore, cfg, testFeatureToggles, tagimpl.ProvideService(sqlStore), quotaService)
require.NoError(t, err)
insertTestDashboard(t, dashboardStore, "Apple", 1, 0, "", false)
t.Run("Finds a dashboard with existing name in root directory and throws DashboardWithSameNameInFolderExists error", func(t *testing.T) {
err = sqlStore.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
_, err = getExistingDashboardByTitleAndFolder(sess, &dashboards.Dashboard{Title: "Apple", OrgID: 1}, false, false)
return err
})
require.ErrorIs(t, err, dashboards.ErrDashboardWithSameNameInFolderExists)
})
t.Run("Returns no error when dashboard does not exist in root folder", func(t *testing.T) {
err = sqlStore.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
_, err = getExistingDashboardByTitleAndFolder(sess, &dashboards.Dashboard{Title: "Beta", OrgID: 1}, false, false)
return err
})
require.NoError(t, err)
})
t.Run("Finds a dashboard with existing name in specific folder and throws DashboardWithSameNameInFolderExists error", func(t *testing.T) {
savedFolder := insertTestDashboard(t, dashboardStore, "test dash folder", 1, 0, "", true, "prod", "webapp")
savedDash := insertTestDashboard(t, dashboardStore, "test dash", 1, savedFolder.ID, savedFolder.UID, false, "prod", "webapp")
err = sqlStore.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
_, err = getExistingDashboardByTitleAndFolder(sess, &dashboards.Dashboard{Title: savedDash.Title, FolderUID: savedFolder.UID, OrgID: 1}, false, false)
return err
})
require.ErrorIs(t, err, dashboards.ErrDashboardWithSameNameInFolderExists)
})
}
func TestIntegrationFindDashboardsByTitle(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
@@ -98,6 +98,7 @@ func AddDashboardFolderMigrations(mg *migrator.Migrator) {
mg.AddMigration("Delete unique index for dashboard_org_id_folder_uid_title", &DummyMigration{})
// Removed a few lines below
mg.AddMigration("Add unique index for dashboard_org_id_folder_uid_title_is_folder", migrator.NewAddIndexMigration(migrator.Table{Name: "dashboard"}, &migrator.Index{
Cols: []string{"org_id", "folder_uid", "title", "is_folder"}, Type: migrator.UniqueIndex,
}))
@@ -106,4 +107,8 @@ func AddDashboardFolderMigrations(mg *migrator.Migrator) {
mg.AddMigration("Restore index for dashboard_org_id_folder_id_title", migrator.NewAddIndexMigration(migrator.Table{Name: "dashboard"}, &migrator.Index{
Cols: []string{"org_id", "folder_id", "title"},
}))
mg.AddMigration("Remove unique index for dashboard_org_id_folder_uid_title_is_folder", migrator.NewDropIndexMigration(migrator.Table{Name: "dashboard"}, &migrator.Index{
Cols: []string{"org_id", "folder_uid", "title", "is_folder"}, Type: migrator.UniqueIndex,
}))
}