Dashboards: Split GetDashboardVersions method (#49967)
* Split GetDashboarVersions method * Add sqlstore dialect and tests * Fix signature of PAtchPreference * Add GetDialect to sqlstore and remove GetDashboardVersions * Add GetDialect to db interface * Implement List * add deleted test function * Remove GetDialect from sqlstore interface * Remove deleted method from mock * Refactor test
This commit is contained in:
@@ -20,7 +20,8 @@ type Service struct {
|
||||
func ProvideService(db db.DB) dashver.Service {
|
||||
return &Service{
|
||||
store: &sqlStore{
|
||||
db: db,
|
||||
db: db,
|
||||
dialect: db.GetDialect(),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -63,3 +64,11 @@ func (s *Service) DeleteExpired(ctx context.Context, cmd *dashver.DeleteExpiredV
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// List all dashboard versions for the given dashboard ID.
|
||||
func (s *Service) List(ctx context.Context, query *dashver.ListDashboardVersionsQuery) ([]*dashver.DashboardVersionDTO, error) {
|
||||
if query.Limit == 0 {
|
||||
query.Limit = 1000
|
||||
}
|
||||
return s.store.List(ctx, query)
|
||||
}
|
||||
|
||||
@@ -53,10 +53,24 @@ func TestDeleteExpiredVersions(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestListDashboardVersions(t *testing.T) {
|
||||
dashboardVersionStore := newDashboardVersionStoreFake()
|
||||
dashboardVersionService := Service{store: dashboardVersionStore}
|
||||
|
||||
t.Run("Get all versions for a given Dashboard ID", func(t *testing.T) {
|
||||
query := dashver.ListDashboardVersionsQuery{}
|
||||
dashboardVersionStore.ExpectedListVersions = []*dashver.DashboardVersionDTO{{}}
|
||||
res, err := dashboardVersionService.List(context.Background(), &query)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, 1, len(res))
|
||||
})
|
||||
}
|
||||
|
||||
type FakeDashboardVersionStore struct {
|
||||
ExpectedDashboardVersion *dashver.DashboardVersion
|
||||
ExptectedDeletedVersions int64
|
||||
ExpectedVersions []interface{}
|
||||
ExpectedListVersions []*dashver.DashboardVersionDTO
|
||||
ExpectedError error
|
||||
}
|
||||
|
||||
@@ -75,3 +89,7 @@ func (f *FakeDashboardVersionStore) GetBatch(ctx context.Context, cmd *dashver.D
|
||||
func (f *FakeDashboardVersionStore) DeleteBatch(ctx context.Context, cmd *dashver.DeleteExpiredVersionsCommand, versionIdsToDelete []interface{}) (int64, error) {
|
||||
return f.ExptectedDeletedVersions, f.ExpectedError
|
||||
}
|
||||
|
||||
func (f *FakeDashboardVersionStore) List(ctx context.Context, query *dashver.ListDashboardVersionsQuery) ([]*dashver.DashboardVersionDTO, error) {
|
||||
return f.ExpectedListVersions, f.ExpectedError
|
||||
}
|
||||
|
||||
@@ -7,16 +7,19 @@ import (
|
||||
dashver "github.com/grafana/grafana/pkg/services/dashboardversion"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/db"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
|
||||
)
|
||||
|
||||
type store interface {
|
||||
Get(context.Context, *dashver.GetDashboardVersionQuery) (*dashver.DashboardVersion, error)
|
||||
GetBatch(context.Context, *dashver.DeleteExpiredVersionsCommand, int, int) ([]interface{}, error)
|
||||
DeleteBatch(context.Context, *dashver.DeleteExpiredVersionsCommand, []interface{}) (int64, error)
|
||||
List(context.Context, *dashver.ListDashboardVersionsQuery) ([]*dashver.DashboardVersionDTO, error)
|
||||
}
|
||||
|
||||
type sqlStore struct {
|
||||
db db.DB
|
||||
db db.DB
|
||||
dialect migrator.Dialect
|
||||
}
|
||||
|
||||
func (ss *sqlStore) Get(ctx context.Context, query *dashver.GetDashboardVersionQuery) (*dashver.DashboardVersion, error) {
|
||||
@@ -75,3 +78,38 @@ func (ss *sqlStore) DeleteBatch(ctx context.Context, cmd *dashver.DeleteExpiredV
|
||||
})
|
||||
return deleted, err
|
||||
}
|
||||
|
||||
func (ss *sqlStore) List(ctx context.Context, query *dashver.ListDashboardVersionsQuery) ([]*dashver.DashboardVersionDTO, error) {
|
||||
var dashboardVersion []*dashver.DashboardVersionDTO
|
||||
err := ss.db.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||
err := sess.Table("dashboard_version").
|
||||
Select(`dashboard_version.id,
|
||||
dashboard_version.dashboard_id,
|
||||
dashboard_version.parent_version,
|
||||
dashboard_version.restored_from,
|
||||
dashboard_version.version,
|
||||
dashboard_version.created,
|
||||
dashboard_version.created_by as created_by_id,
|
||||
dashboard_version.message,
|
||||
dashboard_version.data,`+
|
||||
ss.dialect.Quote("user")+`.login as created_by`).
|
||||
Join("LEFT", ss.dialect.Quote("user"), `dashboard_version.created_by = `+ss.dialect.Quote("user")+`.id`).
|
||||
Join("LEFT", "dashboard", `dashboard.id = dashboard_version.dashboard_id`).
|
||||
Where("dashboard_version.dashboard_id=? AND dashboard.org_id=?", query.DashboardID, query.OrgID).
|
||||
OrderBy("dashboard_version.version DESC").
|
||||
Limit(query.Limit, query.Start).
|
||||
Find(&dashboardVersion)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(dashboardVersion) < 1 {
|
||||
return dashver.ErrNoVersionsForDashboardID
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dashboardVersion, nil
|
||||
}
|
||||
|
||||
@@ -30,8 +30,8 @@ func TestIntegrationGetDashboardVersion(t *testing.T) {
|
||||
|
||||
res, err := dashVerStore.Get(context.Background(), &query)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, query.DashboardID, savedDash.Id)
|
||||
require.Equal(t, query.Version, savedDash.Version)
|
||||
assert.Equal(t, query.DashboardID, savedDash.Id)
|
||||
assert.Equal(t, query.Version, savedDash.Version)
|
||||
|
||||
dashCmd := &models.Dashboard{
|
||||
Id: res.ID,
|
||||
@@ -41,8 +41,8 @@ func TestIntegrationGetDashboardVersion(t *testing.T) {
|
||||
err = getDashboard(t, ss, dashCmd)
|
||||
require.Nil(t, err)
|
||||
|
||||
require.EqualValues(t, dashCmd.Data.Get("uid"), res.Data.Get("uid"))
|
||||
require.EqualValues(t, dashCmd.Data.Get("orgId"), res.Data.Get("orgId"))
|
||||
assert.EqualValues(t, dashCmd.Data.Get("uid"), res.Data.Get("uid"))
|
||||
assert.EqualValues(t, dashCmd.Data.Get("orgId"), res.Data.Get("orgId"))
|
||||
})
|
||||
|
||||
t.Run("Attempt to get a version that doesn't exist", func(t *testing.T) {
|
||||
@@ -54,7 +54,7 @@ func TestIntegrationGetDashboardVersion(t *testing.T) {
|
||||
|
||||
_, err := dashVerStore.Get(context.Background(), &query)
|
||||
require.Error(t, err)
|
||||
require.Equal(t, models.ErrDashboardVersionNotFound, err)
|
||||
assert.Equal(t, models.ErrDashboardVersionNotFound, err)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -79,6 +79,44 @@ func TestIntegrationDeleteExpiredVersions(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestIntegrationListDashboardVersions(t *testing.T) {
|
||||
ss := sqlstore.InitTestDB(t)
|
||||
dashVerStore := sqlStore{db: ss, dialect: ss.Dialect}
|
||||
savedDash := insertTestDashboard(t, ss, "test dash 43", 1, 0, false, "diff-all")
|
||||
|
||||
t.Run("Get all versions for a given Dashboard ID", func(t *testing.T) {
|
||||
query := dashver.ListDashboardVersionsQuery{
|
||||
DashboardID: savedDash.Id,
|
||||
OrgID: 1,
|
||||
Limit: 1000,
|
||||
}
|
||||
|
||||
res, err := dashVerStore.List(context.Background(), &query)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, 1, len(res))
|
||||
})
|
||||
|
||||
t.Run("Attempt to get the versions for a non-existent Dashboard ID", func(t *testing.T) {
|
||||
query := dashver.ListDashboardVersionsQuery{DashboardID: int64(999), OrgID: 1, Limit: 1000}
|
||||
|
||||
res, err := dashVerStore.List(context.Background(), &query)
|
||||
require.Error(t, err)
|
||||
assert.ErrorIs(t, dashver.ErrNoVersionsForDashboardID, err)
|
||||
assert.Equal(t, 0, len(res))
|
||||
})
|
||||
|
||||
t.Run("Get all versions for an updated dashboard", func(t *testing.T) {
|
||||
updateTestDashboard(t, ss, savedDash, map[string]interface{}{
|
||||
"tags": "different-tag",
|
||||
})
|
||||
query := dashver.ListDashboardVersionsQuery{DashboardID: savedDash.Id, OrgID: 1, Limit: 1000}
|
||||
res, err := dashVerStore.List(context.Background(), &query)
|
||||
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, 2, len(res))
|
||||
})
|
||||
}
|
||||
|
||||
func getDashboard(t *testing.T, sqlStore *sqlstore.SQLStore, dashboard *models.Dashboard) error {
|
||||
t.Helper()
|
||||
return sqlStore.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
|
||||
@@ -95,6 +133,7 @@ func getDashboard(t *testing.T, sqlStore *sqlstore.SQLStore, dashboard *models.D
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func insertTestDashboard(t *testing.T, sqlStore *sqlstore.SQLStore, title string, orgId int64,
|
||||
folderId int64, isFolder bool, tags ...interface{}) *models.Dashboard {
|
||||
t.Helper()
|
||||
@@ -149,3 +188,64 @@ func insertTestDashboard(t *testing.T, sqlStore *sqlstore.SQLStore, title string
|
||||
|
||||
return dash
|
||||
}
|
||||
|
||||
func updateTestDashboard(t *testing.T, sqlStore *sqlstore.SQLStore, dashboard *models.Dashboard, data map[string]interface{}) {
|
||||
t.Helper()
|
||||
|
||||
data["id"] = dashboard.Id
|
||||
|
||||
parentVersion := dashboard.Version
|
||||
|
||||
cmd := models.SaveDashboardCommand{
|
||||
OrgId: dashboard.OrgId,
|
||||
Overwrite: true,
|
||||
Dashboard: simplejson.NewFromAny(data),
|
||||
}
|
||||
var dash *models.Dashboard
|
||||
err := sqlStore.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
|
||||
var existing models.Dashboard
|
||||
dash = cmd.GetDashboardModel()
|
||||
dashWithIdExists, err := sess.Where("id=? AND org_id=?", dash.Id, dash.OrgId).Get(&existing)
|
||||
require.NoError(t, err)
|
||||
require.True(t, dashWithIdExists)
|
||||
|
||||
if dash.Version != existing.Version {
|
||||
dash.SetVersion(existing.Version)
|
||||
dash.Version = existing.Version
|
||||
}
|
||||
|
||||
dash.SetVersion(dash.Version + 1)
|
||||
dash.Created = time.Now()
|
||||
dash.Updated = time.Now()
|
||||
dash.Id = dashboard.Id
|
||||
dash.Uid = util.GenerateShortUID()
|
||||
|
||||
_, err = sess.MustCols("folder_id").ID(dash.Id).Update(dash)
|
||||
return err
|
||||
})
|
||||
|
||||
require.Nil(t, err)
|
||||
|
||||
err = sqlStore.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
|
||||
dashVersion := &models.DashboardVersion{
|
||||
DashboardId: dash.Id,
|
||||
ParentVersion: parentVersion,
|
||||
RestoredFrom: cmd.RestoredFrom,
|
||||
Version: dash.Version,
|
||||
Created: time.Now(),
|
||||
CreatedBy: dash.UpdatedBy,
|
||||
Message: cmd.Message,
|
||||
Data: dash.Data,
|
||||
}
|
||||
|
||||
if affectedRows, err := sess.Insert(dashVersion); err != nil {
|
||||
return err
|
||||
} else if affectedRows == 0 {
|
||||
return models.ErrDashboardNotFound
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user