Dashboard tags: add dashboard_uid and org_id (#98500)

pull/98530/head
Stephanie Hingtgen 4 months ago committed by GitHub
parent 17ed25e101
commit 7ab2539449
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 26
      pkg/services/dashboards/database/database.go
  2. 20
      pkg/services/dashboards/database/database_test.go
  3. 55
      pkg/services/sqlstore/migrations/dashboard_mig.go

@ -20,6 +20,7 @@ import (
"github.com/grafana/grafana/pkg/services/folder"
"github.com/grafana/grafana/pkg/services/quota"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/services/sqlstore/migrations"
"github.com/grafana/grafana/pkg/services/sqlstore/permissions"
"github.com/grafana/grafana/pkg/services/sqlstore/searchstore"
"github.com/grafana/grafana/pkg/services/star"
@ -41,9 +42,11 @@ type dashboardStore struct {
// SQL bean helper to save tags
type dashboardTag struct {
Id int64
DashboardId int64
Term string
Id int64
OrgID int64 `xorm:"org_id"`
DashboardId int64
DashboardUID string `xorm:"dashboard_uid"`
Term string
}
// DashboardStore implements the Store interface
@ -57,6 +60,13 @@ func ProvideDashboardStore(sqlStore db.DB, cfg *setting.Cfg, features featuremgm
return nil, err
}
// fill out dashboard_uid and org_id for dashboard_tags
// need to run this at startup in case any downgrade happened after the initial migration
err = migrations.RunDashboardTagMigrations(sqlStore.GetEngine().NewSession(), sqlStore.GetDialect().DriverName())
if err != nil {
s.log.Error("Failed to run dashboard_tag migrations", "err", err)
}
if err := quotaService.RegisterQuotaReporter(&quota.NewUsageReporter{
TargetSrv: dashboards.QuotaTargetSrv,
DefaultLimits: defaultLimits,
@ -438,7 +448,7 @@ func saveDashboard(sess *db.Session, cmd *dashboards.SaveDashboardCommand, emitE
}
// delete existing tags
if _, err = sess.Exec("DELETE FROM dashboard_tag WHERE dashboard_id=?", dash.ID); err != nil {
if _, err = sess.Exec("DELETE FROM dashboard_tag WHERE dashboard_uid=? AND org_id=?", dash.UID, dash.OrgID); err != nil {
return nil, err
}
@ -446,7 +456,7 @@ func saveDashboard(sess *db.Session, cmd *dashboards.SaveDashboardCommand, emitE
tags := dash.GetTags()
if len(tags) > 0 {
for _, tag := range tags {
if _, err := sess.Insert(dashboardTag{DashboardId: dash.ID, Term: tag}); err != nil {
if _, err := sess.Insert(dashboardTag{DashboardId: dash.ID, Term: tag, OrgID: dash.OrgID, DashboardUID: dash.UID}); err != nil {
return nil, err
}
}
@ -604,7 +614,7 @@ func (d *dashboardStore) deleteDashboard(cmd *dashboards.DeleteDashboardCommand,
}
sqlStatements := []statement{
{SQL: "DELETE FROM dashboard_tag WHERE dashboard_id = ? ", args: []any{dashboard.ID}},
{SQL: "DELETE FROM dashboard_tag WHERE dashboard_uid = ? AND org_id = ?", args: []any{dashboard.UID, dashboard.OrgID}},
{SQL: "DELETE FROM star WHERE dashboard_id = ? ", args: []any{dashboard.ID}},
{SQL: "DELETE FROM dashboard WHERE id = ?", args: []any{dashboard.ID}},
{SQL: "DELETE FROM playlist_item WHERE type = 'dashboard_by_id' AND value = ?", args: []any{dashboard.ID}},
@ -935,8 +945,8 @@ func (d *dashboardStore) GetDashboardTags(ctx context.Context, query *dashboards
COUNT(*) as count,
term
FROM dashboard
INNER JOIN dashboard_tag on dashboard_tag.dashboard_id = dashboard.id
WHERE dashboard.org_id=?
INNER JOIN dashboard_tag on dashboard_tag.dashboard_uid = dashboard.uid
WHERE dashboard_tag.org_id=?
GROUP BY term
ORDER BY term`

@ -213,15 +213,31 @@ func TestIntegrationDashboardDataAccess(t *testing.T) {
assert.Equal(t, len(queryResult), 2)
})
t.Run("Should be able to delete dashboard", func(t *testing.T) {
t.Run("Should be able to delete dashboard and associated tags", func(t *testing.T) {
setup()
dash := insertTestDashboard(t, dashboardStore, "delete me", 1, 0, "", false, "delete this")
err := dashboardStore.DeleteDashboard(context.Background(), &dashboards.DeleteDashboardCommand{
tags, err := dashboardStore.GetDashboardTags(context.Background(), &dashboards.GetDashboardTagsQuery{OrgID: 1})
require.NoError(t, err)
terms := make([]string, len(tags))
for i, tag := range tags {
terms[i] = tag.Term
}
require.Contains(t, terms, "delete this")
err = dashboardStore.DeleteDashboard(context.Background(), &dashboards.DeleteDashboardCommand{
ID: dash.ID,
OrgID: 1,
})
require.NoError(t, err)
tags, err = dashboardStore.GetDashboardTags(context.Background(), &dashboards.GetDashboardTagsQuery{OrgID: 1})
require.NoError(t, err)
terms = make([]string, len(tags))
for i, tag := range tags {
terms[i] = tag.Term
}
require.NotContains(t, terms, "delete this")
})
t.Run("Should be able to create dashboard", func(t *testing.T) {

@ -1,7 +1,10 @@
package migrations
import (
"fmt"
. "github.com/grafana/grafana/pkg/services/sqlstore/migrator"
"xorm.io/xorm"
)
func addDashboardMigration(mg *Migrator) {
@ -244,4 +247,56 @@ func addDashboardMigration(mg *Migrator) {
Cols: []string{"deleted"},
Type: IndexType,
}))
mg.AddMigration("Add column dashboard_uid in dashboard_tag", NewAddColumnMigration(dashboardTagV1, &Column{
Name: "dashboard_uid", Type: DB_NVarchar, Length: 40, Nullable: true,
}))
mg.AddMigration("Add column org_id in dashboard_tag", NewAddColumnMigration(dashboardTagV1, &Column{
Name: "org_id", Type: DB_BigInt, Nullable: true, Default: "1",
}))
mg.AddMigration("Add missing dashboard_uid and org_id to dashboard_tag", &FillDashbordUIDAndOrgIDMigration{})
}
type FillDashbordUIDAndOrgIDMigration struct {
MigrationBase
}
func (m *FillDashbordUIDAndOrgIDMigration) SQL(dialect Dialect) string {
return "code migration"
}
func (m *FillDashbordUIDAndOrgIDMigration) Exec(sess *xorm.Session, mg *Migrator) error {
return RunDashboardTagMigrations(sess, mg.Dialect.DriverName())
}
func RunDashboardTagMigrations(sess *xorm.Session, driverName string) error {
// sqlite
sql := `UPDATE dashboard_tag
SET
dashboard_uid = (SELECT uid FROM dashboard WHERE dashboard.id = dashboard_tag.dashboard_id),
org_id = (SELECT org_id FROM dashboard WHERE dashboard.id = dashboard_tag.dashboard_id)
WHERE
(dashboard_uid IS NULL OR org_id IS NULL)
AND EXISTS (SELECT 1 FROM dashboard WHERE dashboard.id = dashboard_tag.dashboard_id);`
if driverName == Postgres {
sql = `UPDATE dashboard_tag
SET dashboard_uid = dashboard.uid,
org_id = dashboard.org_id
FROM dashboard
WHERE dashboard_tag.dashboard_id = dashboard.id
AND (dashboard_tag.dashboard_uid IS NULL OR dashboard_tag.org_id IS NULL);`
} else if driverName == MySQL {
sql = `UPDATE dashboard_tag
LEFT JOIN dashboard ON dashboard_tag.dashboard_id = dashboard.id
SET dashboard_tag.dashboard_uid = dashboard.uid,
dashboard_tag.org_id = dashboard.org_id
WHERE dashboard_tag.dashboard_uid IS NULL OR dashboard_tag.org_id IS NULL;`
}
if _, err := sess.Exec(sql); err != nil {
return fmt.Errorf("failed to set dashboard_uid and org_id in dashboard_tag: %w", err)
}
return nil
}

Loading…
Cancel
Save