mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
LibraryElements: Creates usage stats for panels and variables (#34476)
* LibraryPanels: Adds usage collection * Refactor: renames Panel and Variable consts * Chore: initialize stats * Refactor: moves library element migrations to migration namespace
This commit is contained in:
@@ -22,7 +22,7 @@ SELECT DISTINCT
|
||||
, u1.email AS created_by_email
|
||||
, u2.login AS updated_by_name
|
||||
, u2.email AS updated_by_email
|
||||
, (SELECT COUNT(connection_id) FROM ` + connectionTableName + ` WHERE element_id = le.id AND kind=1) AS connected_dashboards`
|
||||
, (SELECT COUNT(connection_id) FROM ` + models.LibraryElementConnectionTableName + ` WHERE element_id = le.id AND kind=1) AS connected_dashboards`
|
||||
)
|
||||
|
||||
func getFromLibraryElementDTOWithMeta(dialect migrator.Dialect) string {
|
||||
@@ -41,9 +41,9 @@ func syncFieldsWithModel(libraryElement *LibraryElement) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if LibraryElementKind(libraryElement.Kind) == Panel {
|
||||
if models.LibraryElementKind(libraryElement.Kind) == models.PanelElement {
|
||||
model["title"] = libraryElement.Name
|
||||
} else if LibraryElementKind(libraryElement.Kind) == Variable {
|
||||
} else if models.LibraryElementKind(libraryElement.Kind) == models.VariableElement {
|
||||
model["name"] = libraryElement.Name
|
||||
}
|
||||
if model["type"] != nil {
|
||||
@@ -520,7 +520,7 @@ func (l *LibraryElementService) getConnections(c *models.ReqContext, uid string)
|
||||
var libraryElementConnections []libraryElementConnectionWithMeta
|
||||
builder := sqlstore.SQLBuilder{}
|
||||
builder.Write("SELECT lec.*, u1.login AS created_by_name, u1.email AS created_by_email")
|
||||
builder.Write(" FROM " + connectionTableName + " AS lec")
|
||||
builder.Write(" FROM " + models.LibraryElementConnectionTableName + " AS lec")
|
||||
builder.Write(" LEFT JOIN " + l.SQLStore.Dialect.Quote("user") + " AS u1 ON lec.created_by = u1.id")
|
||||
builder.Write(" INNER JOIN dashboard AS dashboard on lec.connection_id = dashboard.id")
|
||||
builder.Write(` WHERE lec.element_id=?`, element.ID)
|
||||
@@ -562,7 +562,7 @@ func (l *LibraryElementService) getElementsForDashboardID(c *models.ReqContext,
|
||||
", coalesce(dashboard.uid, '') AS folder_uid" +
|
||||
getFromLibraryElementDTOWithMeta(l.SQLStore.Dialect) +
|
||||
" LEFT JOIN dashboard AS dashboard ON dashboard.id = le.folder_id" +
|
||||
" INNER JOIN " + connectionTableName + " AS lce ON lce.element_id = le.id AND lce.kind=1 AND lce.connection_id=?"
|
||||
" INNER JOIN " + models.LibraryElementConnectionTableName + " AS lce ON lce.element_id = le.id AND lce.kind=1 AND lce.connection_id=?"
|
||||
sess := session.SQL(sql, dashboardID)
|
||||
err := sess.Find(&libraryElements)
|
||||
if err != nil {
|
||||
@@ -610,7 +610,7 @@ func (l *LibraryElementService) getElementsForDashboardID(c *models.ReqContext,
|
||||
// connectElementsToDashboardID adds connections for all elements Library Elements in a Dashboard.
|
||||
func (l *LibraryElementService) connectElementsToDashboardID(c *models.ReqContext, elementUIDs []string, dashboardID int64) error {
|
||||
err := l.SQLStore.WithTransactionalDbSession(c.Context.Req.Context(), func(session *sqlstore.DBSession) error {
|
||||
_, err := session.Exec("DELETE FROM "+connectionTableName+" WHERE kind=1 AND connection_id=?", dashboardID)
|
||||
_, err := session.Exec("DELETE FROM "+models.LibraryElementConnectionTableName+" WHERE kind=1 AND connection_id=?", dashboardID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -646,7 +646,7 @@ func (l *LibraryElementService) connectElementsToDashboardID(c *models.ReqContex
|
||||
// disconnectElementsFromDashboardID deletes connections for all Library Elements in a Dashboard.
|
||||
func (l *LibraryElementService) disconnectElementsFromDashboardID(c *models.ReqContext, dashboardID int64) error {
|
||||
return l.SQLStore.WithTransactionalDbSession(c.Context.Req.Context(), func(session *sqlstore.DBSession) error {
|
||||
_, err := session.Exec("DELETE FROM "+connectionTableName+" WHERE kind=1 AND connection_id=?", dashboardID)
|
||||
_, err := session.Exec("DELETE FROM "+models.LibraryElementConnectionTableName+" WHERE kind=1 AND connection_id=?", dashboardID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -676,7 +676,7 @@ func (l *LibraryElementService) deleteLibraryElementsInFolderUID(c *models.ReqCo
|
||||
ConnectionID int64 `xorm:"connection_id"`
|
||||
}
|
||||
sql := "SELECT lec.connection_id FROM library_element AS le"
|
||||
sql += " INNER JOIN " + connectionTableName + " AS lec on le.id = lec.element_id"
|
||||
sql += " INNER JOIN " + models.LibraryElementConnectionTableName + " AS lec on le.id = lec.element_id"
|
||||
sql += " WHERE le.folder_id=? AND le.org_id=?"
|
||||
err = session.SQL(sql, folderID, c.SignedInUser.OrgId).Find(&connectionIDs)
|
||||
if err != nil {
|
||||
@@ -694,7 +694,7 @@ func (l *LibraryElementService) deleteLibraryElementsInFolderUID(c *models.ReqCo
|
||||
return err
|
||||
}
|
||||
for _, elementID := range elementIDs {
|
||||
_, err := session.Exec("DELETE FROM "+connectionTableName+" WHERE element_id=?", elementID.ID)
|
||||
_, err := session.Exec("DELETE FROM "+models.LibraryElementConnectionTableName+" WHERE element_id=?", elementID.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -11,11 +11,11 @@ func isGeneralFolder(folderID int64) bool {
|
||||
}
|
||||
|
||||
func (l *LibraryElementService) requireSupportedElementKind(kindAsInt int64) error {
|
||||
kind := LibraryElementKind(kindAsInt)
|
||||
kind := models.LibraryElementKind(kindAsInt)
|
||||
switch kind {
|
||||
case Panel:
|
||||
case models.PanelElement:
|
||||
return nil
|
||||
case Variable:
|
||||
case models.VariableElement:
|
||||
return nil
|
||||
default:
|
||||
return errLibraryElementUnSupportedElementKind
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/registry"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
@@ -27,8 +26,6 @@ type LibraryElementService struct {
|
||||
log log.Logger
|
||||
}
|
||||
|
||||
const connectionTableName = "library_element_connection"
|
||||
|
||||
func init() {
|
||||
registry.RegisterService(&LibraryElementService{})
|
||||
}
|
||||
@@ -66,51 +63,3 @@ func (l *LibraryElementService) DisconnectElementsFromDashboard(c *models.ReqCon
|
||||
func (l *LibraryElementService) DeleteLibraryElementsInFolder(c *models.ReqContext, folderUID string) error {
|
||||
return l.deleteLibraryElementsInFolderUID(c, folderUID)
|
||||
}
|
||||
|
||||
// AddMigration defines database migrations.
|
||||
// If Panel Library is not enabled does nothing.
|
||||
func (l *LibraryElementService) AddMigration(mg *migrator.Migrator) {
|
||||
libraryElementsV1 := migrator.Table{
|
||||
Name: "library_element",
|
||||
Columns: []*migrator.Column{
|
||||
{Name: "id", Type: migrator.DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true},
|
||||
{Name: "org_id", Type: migrator.DB_BigInt, Nullable: false},
|
||||
{Name: "folder_id", Type: migrator.DB_BigInt, Nullable: false},
|
||||
{Name: "uid", Type: migrator.DB_NVarchar, Length: 40, Nullable: false},
|
||||
{Name: "name", Type: migrator.DB_NVarchar, Length: 150, Nullable: false},
|
||||
{Name: "kind", Type: migrator.DB_BigInt, Nullable: false},
|
||||
{Name: "type", Type: migrator.DB_NVarchar, Length: 40, Nullable: false},
|
||||
{Name: "description", Type: migrator.DB_NVarchar, Length: 255, Nullable: false},
|
||||
{Name: "model", Type: migrator.DB_Text, Nullable: false},
|
||||
{Name: "created", Type: migrator.DB_DateTime, Nullable: false},
|
||||
{Name: "created_by", Type: migrator.DB_BigInt, Nullable: false},
|
||||
{Name: "updated", Type: migrator.DB_DateTime, Nullable: false},
|
||||
{Name: "updated_by", Type: migrator.DB_BigInt, Nullable: false},
|
||||
{Name: "version", Type: migrator.DB_BigInt, Nullable: false},
|
||||
},
|
||||
Indices: []*migrator.Index{
|
||||
{Cols: []string{"org_id", "folder_id", "name", "kind"}, Type: migrator.UniqueIndex},
|
||||
},
|
||||
}
|
||||
|
||||
mg.AddMigration("create library_element table v1", migrator.NewAddTableMigration(libraryElementsV1))
|
||||
mg.AddMigration("add index library_element org_id-folder_id-name-kind", migrator.NewAddIndexMigration(libraryElementsV1, libraryElementsV1.Indices[0]))
|
||||
|
||||
libraryElementConnectionV1 := migrator.Table{
|
||||
Name: connectionTableName,
|
||||
Columns: []*migrator.Column{
|
||||
{Name: "id", Type: migrator.DB_BigInt, IsPrimaryKey: true, IsAutoIncrement: true},
|
||||
{Name: "element_id", Type: migrator.DB_BigInt, Nullable: false},
|
||||
{Name: "kind", Type: migrator.DB_BigInt, Nullable: false},
|
||||
{Name: "connection_id", Type: migrator.DB_BigInt, Nullable: false},
|
||||
{Name: "created", Type: migrator.DB_DateTime, Nullable: false},
|
||||
{Name: "created_by", Type: migrator.DB_BigInt, Nullable: false},
|
||||
},
|
||||
Indices: []*migrator.Index{
|
||||
{Cols: []string{"element_id", "kind", "connection_id"}, Type: migrator.UniqueIndex},
|
||||
},
|
||||
}
|
||||
|
||||
mg.AddMigration("create "+connectionTableName+" table v1", migrator.NewAddTableMigration(libraryElementConnectionV1))
|
||||
mg.AddMigration("add index "+connectionTableName+" element_id-kind-connection_id", migrator.NewAddIndexMigration(libraryElementConnectionV1, libraryElementConnectionV1.Indices[0]))
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ import (
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
func TestCreateLibraryElement(t *testing.T) {
|
||||
@@ -24,7 +26,7 @@ func TestCreateLibraryElement(t *testing.T) {
|
||||
FolderID: 1,
|
||||
UID: sc.initialResult.Result.UID,
|
||||
Name: "Text - Library Panel",
|
||||
Kind: int64(Panel),
|
||||
Kind: int64(models.PanelElement),
|
||||
Type: "text",
|
||||
Description: "A description",
|
||||
Model: map[string]interface{}{
|
||||
@@ -69,7 +71,7 @@ func TestCreateLibraryElement(t *testing.T) {
|
||||
FolderID: 1,
|
||||
UID: result.Result.UID,
|
||||
Name: "Library Panel Name",
|
||||
Kind: int64(Panel),
|
||||
Kind: int64(models.PanelElement),
|
||||
Type: "text",
|
||||
Description: "A description",
|
||||
Model: map[string]interface{}{
|
||||
|
||||
@@ -42,7 +42,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
|
||||
err := sc.reqContext.Req.ParseForm()
|
||||
require.NoError(t, err)
|
||||
sc.reqContext.Req.Form.Add("kind", strconv.FormatInt(int64(Panel), 10))
|
||||
sc.reqContext.Req.Form.Add("kind", strconv.FormatInt(int64(models.PanelElement), 10))
|
||||
|
||||
resp = sc.service.getAllHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
@@ -62,7 +62,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
FolderID: 1,
|
||||
UID: result.Result.Elements[0].UID,
|
||||
Name: "Text - Library Panel",
|
||||
Kind: int64(Panel),
|
||||
Kind: int64(models.PanelElement),
|
||||
Type: "text",
|
||||
Description: "A description",
|
||||
Model: map[string]interface{}{
|
||||
@@ -107,7 +107,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
|
||||
err := sc.reqContext.Req.ParseForm()
|
||||
require.NoError(t, err)
|
||||
sc.reqContext.Req.Form.Add("kind", strconv.FormatInt(int64(Variable), 10))
|
||||
sc.reqContext.Req.Form.Add("kind", strconv.FormatInt(int64(models.VariableElement), 10))
|
||||
|
||||
resp = sc.service.getAllHandler(sc.reqContext)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
@@ -127,7 +127,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
FolderID: 1,
|
||||
UID: result.Result.Elements[0].UID,
|
||||
Name: "query0",
|
||||
Kind: int64(Variable),
|
||||
Kind: int64(models.VariableElement),
|
||||
Type: "query",
|
||||
Description: "A description",
|
||||
Model: map[string]interface{}{
|
||||
@@ -187,7 +187,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
FolderID: 1,
|
||||
UID: result.Result.Elements[0].UID,
|
||||
Name: "Text - Library Panel",
|
||||
Kind: int64(Panel),
|
||||
Kind: int64(models.PanelElement),
|
||||
Type: "text",
|
||||
Description: "A description",
|
||||
Model: map[string]interface{}{
|
||||
@@ -222,7 +222,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
FolderID: 1,
|
||||
UID: result.Result.Elements[1].UID,
|
||||
Name: "Text - Library Panel2",
|
||||
Kind: int64(Panel),
|
||||
Kind: int64(models.PanelElement),
|
||||
Type: "text",
|
||||
Description: "A description",
|
||||
Model: map[string]interface{}{
|
||||
@@ -286,7 +286,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
FolderID: 1,
|
||||
UID: result.Result.Elements[0].UID,
|
||||
Name: "Text - Library Panel2",
|
||||
Kind: int64(Panel),
|
||||
Kind: int64(models.PanelElement),
|
||||
Type: "text",
|
||||
Description: "A description",
|
||||
Model: map[string]interface{}{
|
||||
@@ -321,7 +321,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
FolderID: 1,
|
||||
UID: result.Result.Elements[1].UID,
|
||||
Name: "Text - Library Panel",
|
||||
Kind: int64(Panel),
|
||||
Kind: int64(models.PanelElement),
|
||||
Type: "text",
|
||||
Description: "A description",
|
||||
Model: map[string]interface{}{
|
||||
@@ -360,7 +360,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
|
||||
scenarioWithPanel(t, "When an admin tries to get all library panels and two exist and typeFilter is set to existing types, it should succeed and the result should be correct",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreateCommandWithModel(sc.folder.Id, "Gauge - Library Panel", Panel, []byte(`
|
||||
command := getCreateCommandWithModel(sc.folder.Id, "Gauge - Library Panel", models.PanelElement, []byte(`
|
||||
{
|
||||
"datasource": "${DS_GDEV-TESTDATA}",
|
||||
"id": 1,
|
||||
@@ -372,7 +372,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
resp := sc.service.createHandler(sc.reqContext, command)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
|
||||
command = getCreateCommandWithModel(sc.folder.Id, "BarGauge - Library Panel", Panel, []byte(`
|
||||
command = getCreateCommandWithModel(sc.folder.Id, "BarGauge - Library Panel", models.PanelElement, []byte(`
|
||||
{
|
||||
"datasource": "${DS_GDEV-TESTDATA}",
|
||||
"id": 1,
|
||||
@@ -405,7 +405,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
FolderID: 1,
|
||||
UID: result.Result.Elements[0].UID,
|
||||
Name: "BarGauge - Library Panel",
|
||||
Kind: int64(Panel),
|
||||
Kind: int64(models.PanelElement),
|
||||
Type: "bargauge",
|
||||
Description: "BarGauge description",
|
||||
Model: map[string]interface{}{
|
||||
@@ -440,7 +440,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
FolderID: 1,
|
||||
UID: result.Result.Elements[1].UID,
|
||||
Name: "Gauge - Library Panel",
|
||||
Kind: int64(Panel),
|
||||
Kind: int64(models.PanelElement),
|
||||
Type: "gauge",
|
||||
Description: "Gauge description",
|
||||
Model: map[string]interface{}{
|
||||
@@ -479,7 +479,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
|
||||
scenarioWithPanel(t, "When an admin tries to get all library panels and two exist and typeFilter is set to a nonexistent type, it should succeed and the result should be correct",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreateCommandWithModel(sc.folder.Id, "Gauge - Library Panel", Panel, []byte(`
|
||||
command := getCreateCommandWithModel(sc.folder.Id, "Gauge - Library Panel", models.PanelElement, []byte(`
|
||||
{
|
||||
"datasource": "${DS_GDEV-TESTDATA}",
|
||||
"id": 1,
|
||||
@@ -542,7 +542,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
FolderID: newFolder.Id,
|
||||
UID: result.Result.Elements[0].UID,
|
||||
Name: "Text - Library Panel2",
|
||||
Kind: int64(Panel),
|
||||
Kind: int64(models.PanelElement),
|
||||
Type: "text",
|
||||
Description: "A description",
|
||||
Model: map[string]interface{}{
|
||||
@@ -637,7 +637,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
FolderID: 1,
|
||||
UID: result.Result.Elements[0].UID,
|
||||
Name: "Text - Library Panel",
|
||||
Kind: int64(Panel),
|
||||
Kind: int64(models.PanelElement),
|
||||
Type: "text",
|
||||
Description: "A description",
|
||||
Model: map[string]interface{}{
|
||||
@@ -672,7 +672,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
FolderID: 1,
|
||||
UID: result.Result.Elements[1].UID,
|
||||
Name: "Text - Library Panel2",
|
||||
Kind: int64(Panel),
|
||||
Kind: int64(models.PanelElement),
|
||||
Type: "text",
|
||||
Description: "A description",
|
||||
Model: map[string]interface{}{
|
||||
@@ -736,7 +736,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
FolderID: 1,
|
||||
UID: result.Result.Elements[0].UID,
|
||||
Name: "Text - Library Panel2",
|
||||
Kind: int64(Panel),
|
||||
Kind: int64(models.PanelElement),
|
||||
Type: "text",
|
||||
Description: "A description",
|
||||
Model: map[string]interface{}{
|
||||
@@ -800,7 +800,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
FolderID: 1,
|
||||
UID: result.Result.Elements[0].UID,
|
||||
Name: "Text - Library Panel",
|
||||
Kind: int64(Panel),
|
||||
Kind: int64(models.PanelElement),
|
||||
Type: "text",
|
||||
Description: "A description",
|
||||
Model: map[string]interface{}{
|
||||
@@ -865,7 +865,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
FolderID: 1,
|
||||
UID: result.Result.Elements[0].UID,
|
||||
Name: "Text - Library Panel2",
|
||||
Kind: int64(Panel),
|
||||
Kind: int64(models.PanelElement),
|
||||
Type: "text",
|
||||
Description: "A description",
|
||||
Model: map[string]interface{}{
|
||||
@@ -904,7 +904,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
|
||||
scenarioWithPanel(t, "When an admin tries to get all library panels and two exist and searchString exists in the description, it should succeed and the result should be correct",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreateCommandWithModel(sc.folder.Id, "Text - Library Panel2", Panel, []byte(`
|
||||
command := getCreateCommandWithModel(sc.folder.Id, "Text - Library Panel2", models.PanelElement, []byte(`
|
||||
{
|
||||
"datasource": "${DS_GDEV-TESTDATA}",
|
||||
"id": 1,
|
||||
@@ -939,7 +939,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
FolderID: 1,
|
||||
UID: result.Result.Elements[0].UID,
|
||||
Name: "Text - Library Panel",
|
||||
Kind: int64(Panel),
|
||||
Kind: int64(models.PanelElement),
|
||||
Type: "text",
|
||||
Description: "A description",
|
||||
Model: map[string]interface{}{
|
||||
@@ -978,7 +978,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
|
||||
scenarioWithPanel(t, "When an admin tries to get all library panels and two exist and searchString exists in both name and description, it should succeed and the result should be correct",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
command := getCreateCommandWithModel(sc.folder.Id, "Some Other", Panel, []byte(`
|
||||
command := getCreateCommandWithModel(sc.folder.Id, "Some Other", models.PanelElement, []byte(`
|
||||
{
|
||||
"datasource": "${DS_GDEV-TESTDATA}",
|
||||
"id": 1,
|
||||
@@ -1011,7 +1011,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
FolderID: 1,
|
||||
UID: result.Result.Elements[0].UID,
|
||||
Name: "Some Other",
|
||||
Kind: int64(Panel),
|
||||
Kind: int64(models.PanelElement),
|
||||
Type: "text",
|
||||
Description: "A Library Panel",
|
||||
Model: map[string]interface{}{
|
||||
@@ -1046,7 +1046,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
FolderID: 1,
|
||||
UID: result.Result.Elements[1].UID,
|
||||
Name: "Text - Library Panel",
|
||||
Kind: int64(Panel),
|
||||
Kind: int64(models.PanelElement),
|
||||
Type: "text",
|
||||
Description: "A description",
|
||||
Model: map[string]interface{}{
|
||||
@@ -1112,7 +1112,7 @@ func TestGetAllLibraryElements(t *testing.T) {
|
||||
FolderID: 1,
|
||||
UID: result.Result.Elements[0].UID,
|
||||
Name: "Text - Library Panel2",
|
||||
Kind: int64(Panel),
|
||||
Kind: int64(models.PanelElement),
|
||||
Type: "text",
|
||||
Description: "A description",
|
||||
Model: map[string]interface{}{
|
||||
|
||||
@@ -35,7 +35,7 @@ func TestGetLibraryElement(t *testing.T) {
|
||||
FolderID: 1,
|
||||
UID: res.Result.UID,
|
||||
Name: "Text - Library Panel",
|
||||
Kind: int64(Panel),
|
||||
Kind: int64(models.PanelElement),
|
||||
Type: "text",
|
||||
Description: "A description",
|
||||
Model: map[string]interface{}{
|
||||
@@ -130,7 +130,7 @@ func TestGetLibraryElement(t *testing.T) {
|
||||
FolderID: 1,
|
||||
UID: res.Result.UID,
|
||||
Name: "Text - Library Panel",
|
||||
Kind: int64(Panel),
|
||||
Kind: int64(models.PanelElement),
|
||||
Type: "text",
|
||||
Description: "A description",
|
||||
Model: map[string]interface{}{
|
||||
|
||||
@@ -5,12 +5,14 @@ import (
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
func TestPatchLibraryElement(t *testing.T) {
|
||||
scenarioWithPanel(t, "When an admin tries to patch a library panel that does not exist, it should fail",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
cmd := patchLibraryElementCommand{Kind: int64(Panel)}
|
||||
cmd := patchLibraryElementCommand{Kind: int64(models.PanelElement)}
|
||||
sc.reqContext.ReplaceAllParams(map[string]string{":uid": "unknown"})
|
||||
resp := sc.service.patchHandler(sc.reqContext, cmd)
|
||||
require.Equal(t, 404, resp.Status())
|
||||
@@ -31,7 +33,7 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
"type": "graph"
|
||||
}
|
||||
`),
|
||||
Kind: int64(Panel),
|
||||
Kind: int64(models.PanelElement),
|
||||
Version: 1,
|
||||
}
|
||||
sc.reqContext.ReplaceAllParams(map[string]string{":uid": sc.initialResult.Result.UID})
|
||||
@@ -45,7 +47,7 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
FolderID: newFolder.Id,
|
||||
UID: sc.initialResult.Result.UID,
|
||||
Name: "Panel - New name",
|
||||
Kind: int64(Panel),
|
||||
Kind: int64(models.PanelElement),
|
||||
Type: "graph",
|
||||
Description: "An updated description",
|
||||
Model: map[string]interface{}{
|
||||
@@ -83,7 +85,7 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
newFolder := createFolderWithACL(t, sc.sqlStore, "NewFolder", sc.user, []folderACLItem{})
|
||||
cmd := patchLibraryElementCommand{
|
||||
FolderID: newFolder.Id,
|
||||
Kind: int64(Panel),
|
||||
Kind: int64(models.PanelElement),
|
||||
Version: 1,
|
||||
}
|
||||
sc.reqContext.ReplaceAllParams(map[string]string{":uid": sc.initialResult.Result.UID})
|
||||
@@ -104,7 +106,7 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
cmd := patchLibraryElementCommand{
|
||||
FolderID: -1,
|
||||
Name: "New Name",
|
||||
Kind: int64(Panel),
|
||||
Kind: int64(models.PanelElement),
|
||||
Version: 1,
|
||||
}
|
||||
sc.reqContext.ReplaceAllParams(map[string]string{":uid": sc.initialResult.Result.UID})
|
||||
@@ -125,7 +127,7 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
cmd := patchLibraryElementCommand{
|
||||
FolderID: -1,
|
||||
Model: []byte(`{ "title": "New Model Title", "name": "New Model Name", "type":"graph", "description": "New description" }`),
|
||||
Kind: int64(Panel),
|
||||
Kind: int64(models.PanelElement),
|
||||
Version: 1,
|
||||
}
|
||||
sc.reqContext.ReplaceAllParams(map[string]string{":uid": sc.initialResult.Result.UID})
|
||||
@@ -152,7 +154,7 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
cmd := patchLibraryElementCommand{
|
||||
FolderID: -1,
|
||||
Model: []byte(`{ "description": "New description" }`),
|
||||
Kind: int64(Panel),
|
||||
Kind: int64(models.PanelElement),
|
||||
Version: 1,
|
||||
}
|
||||
sc.reqContext.ReplaceAllParams(map[string]string{":uid": sc.initialResult.Result.UID})
|
||||
@@ -178,7 +180,7 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
cmd := patchLibraryElementCommand{
|
||||
FolderID: -1,
|
||||
Model: []byte(`{ "type": "graph" }`),
|
||||
Kind: int64(Panel),
|
||||
Kind: int64(models.PanelElement),
|
||||
Version: 1,
|
||||
}
|
||||
sc.reqContext.ReplaceAllParams(map[string]string{":uid": sc.initialResult.Result.UID})
|
||||
@@ -201,7 +203,7 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
|
||||
scenarioWithPanel(t, "When another admin tries to patch a library panel, it should change UpdatedBy successfully and return correct result",
|
||||
func(t *testing.T, sc scenarioContext) {
|
||||
cmd := patchLibraryElementCommand{FolderID: -1, Version: 1, Kind: int64(Panel)}
|
||||
cmd := patchLibraryElementCommand{FolderID: -1, Version: 1, Kind: int64(models.PanelElement)}
|
||||
sc.reqContext.UserId = 2
|
||||
sc.reqContext.ReplaceAllParams(map[string]string{":uid": sc.initialResult.Result.UID})
|
||||
resp := sc.service.patchHandler(sc.reqContext, cmd)
|
||||
@@ -223,7 +225,7 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
cmd := patchLibraryElementCommand{
|
||||
Name: "Text - Library Panel",
|
||||
Version: 1,
|
||||
Kind: int64(Panel),
|
||||
Kind: int64(models.PanelElement),
|
||||
}
|
||||
sc.reqContext.ReplaceAllParams(map[string]string{":uid": result.Result.UID})
|
||||
resp = sc.service.patchHandler(sc.reqContext, cmd)
|
||||
@@ -239,7 +241,7 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
cmd := patchLibraryElementCommand{
|
||||
FolderID: 1,
|
||||
Version: 1,
|
||||
Kind: int64(Panel),
|
||||
Kind: int64(models.PanelElement),
|
||||
}
|
||||
sc.reqContext.ReplaceAllParams(map[string]string{":uid": result.Result.UID})
|
||||
resp = sc.service.patchHandler(sc.reqContext, cmd)
|
||||
@@ -251,7 +253,7 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
cmd := patchLibraryElementCommand{
|
||||
FolderID: sc.folder.Id,
|
||||
Version: 1,
|
||||
Kind: int64(Panel),
|
||||
Kind: int64(models.PanelElement),
|
||||
}
|
||||
sc.reqContext.OrgId = 2
|
||||
sc.reqContext.ReplaceAllParams(map[string]string{":uid": sc.initialResult.Result.UID})
|
||||
@@ -264,7 +266,7 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
cmd := patchLibraryElementCommand{
|
||||
FolderID: sc.folder.Id,
|
||||
Version: 1,
|
||||
Kind: int64(Panel),
|
||||
Kind: int64(models.PanelElement),
|
||||
}
|
||||
sc.reqContext.ReplaceAllParams(map[string]string{":uid": sc.initialResult.Result.UID})
|
||||
resp := sc.service.patchHandler(sc.reqContext, cmd)
|
||||
@@ -278,14 +280,14 @@ func TestPatchLibraryElement(t *testing.T) {
|
||||
cmd := patchLibraryElementCommand{
|
||||
FolderID: sc.folder.Id,
|
||||
Version: 1,
|
||||
Kind: int64(Variable),
|
||||
Kind: int64(models.VariableElement),
|
||||
}
|
||||
sc.reqContext.ReplaceAllParams(map[string]string{":uid": sc.initialResult.Result.UID})
|
||||
resp := sc.service.patchHandler(sc.reqContext, cmd)
|
||||
require.Equal(t, 200, resp.Status())
|
||||
var result = validateAndUnMarshalResponse(t, resp)
|
||||
sc.initialResult.Result.Type = "text"
|
||||
sc.initialResult.Result.Kind = int64(Panel)
|
||||
sc.initialResult.Result.Kind = int64(models.PanelElement)
|
||||
sc.initialResult.Result.Description = "A description"
|
||||
sc.initialResult.Result.Model = map[string]interface{}{
|
||||
"datasource": "${DS_GDEV-TESTDATA}",
|
||||
|
||||
@@ -84,7 +84,7 @@ func TestLibraryElementPermissions(t *testing.T) {
|
||||
toFolder := createFolderWithACL(t, sc.sqlStore, "Folder", sc.user, testCase.items)
|
||||
sc.reqContext.SignedInUser.OrgRole = testCase.role
|
||||
|
||||
cmd := patchLibraryElementCommand{FolderID: toFolder.Id, Version: 1, Kind: int64(Panel)}
|
||||
cmd := patchLibraryElementCommand{FolderID: toFolder.Id, Version: 1, Kind: int64(models.PanelElement)}
|
||||
sc.reqContext.ReplaceAllParams(map[string]string{":uid": result.Result.UID})
|
||||
resp = sc.service.patchHandler(sc.reqContext, cmd)
|
||||
require.Equal(t, testCase.status, resp.Status())
|
||||
@@ -99,7 +99,7 @@ func TestLibraryElementPermissions(t *testing.T) {
|
||||
toFolder := createFolderWithACL(t, sc.sqlStore, "Folder", sc.user, everyonePermissions)
|
||||
sc.reqContext.SignedInUser.OrgRole = testCase.role
|
||||
|
||||
cmd := patchLibraryElementCommand{FolderID: toFolder.Id, Version: 1, Kind: int64(Panel)}
|
||||
cmd := patchLibraryElementCommand{FolderID: toFolder.Id, Version: 1, Kind: int64(models.PanelElement)}
|
||||
sc.reqContext.ReplaceAllParams(map[string]string{":uid": result.Result.UID})
|
||||
resp = sc.service.patchHandler(sc.reqContext, cmd)
|
||||
require.Equal(t, testCase.status, resp.Status())
|
||||
@@ -146,7 +146,7 @@ func TestLibraryElementPermissions(t *testing.T) {
|
||||
result := validateAndUnMarshalResponse(t, resp)
|
||||
sc.reqContext.SignedInUser.OrgRole = testCase.role
|
||||
|
||||
cmd := patchLibraryElementCommand{FolderID: 0, Version: 1, Kind: int64(Panel)}
|
||||
cmd := patchLibraryElementCommand{FolderID: 0, Version: 1, Kind: int64(models.PanelElement)}
|
||||
sc.reqContext.ReplaceAllParams(map[string]string{":uid": result.Result.UID})
|
||||
resp = sc.service.patchHandler(sc.reqContext, cmd)
|
||||
require.Equal(t, testCase.status, resp.Status())
|
||||
@@ -160,7 +160,7 @@ func TestLibraryElementPermissions(t *testing.T) {
|
||||
result := validateAndUnMarshalResponse(t, resp)
|
||||
sc.reqContext.SignedInUser.OrgRole = testCase.role
|
||||
|
||||
cmd := patchLibraryElementCommand{FolderID: folder.Id, Version: 1, Kind: int64(Panel)}
|
||||
cmd := patchLibraryElementCommand{FolderID: folder.Id, Version: 1, Kind: int64(models.PanelElement)}
|
||||
sc.reqContext.ReplaceAllParams(map[string]string{":uid": result.Result.UID})
|
||||
resp = sc.service.patchHandler(sc.reqContext, cmd)
|
||||
require.Equal(t, testCase.status, resp.Status())
|
||||
@@ -205,7 +205,7 @@ func TestLibraryElementPermissions(t *testing.T) {
|
||||
result := validateAndUnMarshalResponse(t, resp)
|
||||
sc.reqContext.SignedInUser.OrgRole = testCase.role
|
||||
|
||||
cmd := patchLibraryElementCommand{FolderID: -100, Version: 1, Kind: int64(Panel)}
|
||||
cmd := patchLibraryElementCommand{FolderID: -100, Version: 1, Kind: int64(models.PanelElement)}
|
||||
sc.reqContext.ReplaceAllParams(map[string]string{":uid": result.Result.UID})
|
||||
resp = sc.service.patchHandler(sc.reqContext, cmd)
|
||||
require.Equal(t, 404, resp.Status())
|
||||
|
||||
@@ -126,7 +126,7 @@ type libraryElementsSearchResult struct {
|
||||
}
|
||||
|
||||
func getCreatePanelCommand(folderID int64, name string) CreateLibraryElementCommand {
|
||||
command := getCreateCommandWithModel(folderID, name, Panel, []byte(`
|
||||
command := getCreateCommandWithModel(folderID, name, models.PanelElement, []byte(`
|
||||
{
|
||||
"datasource": "${DS_GDEV-TESTDATA}",
|
||||
"id": 1,
|
||||
@@ -140,7 +140,7 @@ func getCreatePanelCommand(folderID int64, name string) CreateLibraryElementComm
|
||||
}
|
||||
|
||||
func getCreateVariableCommand(folderID int64, name string) CreateLibraryElementCommand {
|
||||
command := getCreateCommandWithModel(folderID, name, Variable, []byte(`
|
||||
command := getCreateCommandWithModel(folderID, name, models.VariableElement, []byte(`
|
||||
{
|
||||
"datasource": "${DS_GDEV-TESTDATA}",
|
||||
"name": "query0",
|
||||
@@ -152,7 +152,7 @@ func getCreateVariableCommand(folderID int64, name string) CreateLibraryElementC
|
||||
return command
|
||||
}
|
||||
|
||||
func getCreateCommandWithModel(folderID int64, name string, kind LibraryElementKind, model []byte) CreateLibraryElementCommand {
|
||||
func getCreateCommandWithModel(folderID int64, name string, kind models.LibraryElementKind, model []byte) CreateLibraryElementCommand {
|
||||
command := CreateLibraryElementCommand{
|
||||
FolderID: folderID,
|
||||
Name: name,
|
||||
|
||||
@@ -6,13 +6,6 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type LibraryElementKind int
|
||||
|
||||
const (
|
||||
Panel LibraryElementKind = iota + 1
|
||||
Variable
|
||||
)
|
||||
|
||||
type LibraryConnectionKind int
|
||||
|
||||
const (
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
)
|
||||
|
||||
@@ -38,7 +39,7 @@ func writePerPageSQL(query searchLibraryElementsQuery, sqlStore *sqlstore.SQLSto
|
||||
}
|
||||
|
||||
func writeKindSQL(query searchLibraryElementsQuery, builder *sqlstore.SQLBuilder) {
|
||||
if LibraryElementKind(query.kind) == Panel || LibraryElementKind(query.kind) == Variable {
|
||||
if models.LibraryElementKind(query.kind) == models.PanelElement || models.LibraryElementKind(query.kind) == models.VariableElement {
|
||||
builder.Write(" AND le.kind = ?", query.kind)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user