Annotations: Use dashboard uids instead of dashboard ids (#106676)
This commit is contained in:
@@ -79,6 +79,7 @@ func (r *RepositoryImpl) Find(ctx context.Context, query *annotations.ItemQuery)
|
||||
}
|
||||
|
||||
// Search without dashboard UID filter is expensive, so check without access control first
|
||||
// nolint: staticcheck
|
||||
if query.DashboardID == 0 && query.DashboardUID == "" {
|
||||
// Return early if no annotations found, it's not necessary to perform expensive access control filtering
|
||||
res, err := r.reader.Get(ctx, *query, &accesscontrol.AccessResources{
|
||||
|
||||
@@ -81,7 +81,7 @@ func TestIntegrationAnnotationListingWithRBAC(t *testing.T) {
|
||||
}),
|
||||
})
|
||||
|
||||
_ = testutil.CreateDashboard(t, sql, cfg, features, dashboards.SaveDashboardCommand{
|
||||
dashboard2 := testutil.CreateDashboard(t, sql, cfg, features, dashboards.SaveDashboardCommand{
|
||||
UserID: 1,
|
||||
OrgID: 1,
|
||||
IsFolder: false,
|
||||
@@ -91,18 +91,20 @@ func TestIntegrationAnnotationListingWithRBAC(t *testing.T) {
|
||||
})
|
||||
|
||||
dash1Annotation := &annotations.Item{
|
||||
OrgID: 1,
|
||||
DashboardID: 1,
|
||||
Epoch: 10,
|
||||
OrgID: 1,
|
||||
DashboardID: 1, // nolint: staticcheck
|
||||
DashboardUID: dashboard1.UID,
|
||||
Epoch: 10,
|
||||
}
|
||||
err = repo.Save(context.Background(), dash1Annotation)
|
||||
require.NoError(t, err)
|
||||
|
||||
dash2Annotation := &annotations.Item{
|
||||
OrgID: 1,
|
||||
DashboardID: 2,
|
||||
Epoch: 10,
|
||||
Tags: []string{"foo:bar"},
|
||||
OrgID: 1,
|
||||
DashboardID: 2, // nolint: staticcheck
|
||||
DashboardUID: dashboard2.UID,
|
||||
Epoch: 10,
|
||||
Tags: []string{"foo:bar"},
|
||||
}
|
||||
err = repo.Save(context.Background(), dash2Annotation)
|
||||
require.NoError(t, err)
|
||||
@@ -292,10 +294,11 @@ func TestIntegrationAnnotationListingWithInheritedRBAC(t *testing.T) {
|
||||
|
||||
annotationTxt := fmt.Sprintf("annotation %d", i)
|
||||
dash1Annotation := &annotations.Item{
|
||||
OrgID: orgID,
|
||||
DashboardID: dashboard.ID,
|
||||
Epoch: 10,
|
||||
Text: annotationTxt,
|
||||
OrgID: orgID,
|
||||
DashboardID: dashboard.ID, // nolint: staticcheck
|
||||
DashboardUID: dashboard.UID,
|
||||
Epoch: 10,
|
||||
Text: annotationTxt,
|
||||
}
|
||||
err = store.Add(context.Background(), dash1Annotation)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -3,6 +3,7 @@ package annotationsimpl
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -238,24 +239,27 @@ func createTestAnnotations(t *testing.T, store db.DB, expectedCount int, oldAnno
|
||||
newAnnotationTags := make([]*annotationTag, 0, 2*expectedCount)
|
||||
for i := 0; i < expectedCount; i++ {
|
||||
a := &annotations.Item{
|
||||
ID: int64(i + 1),
|
||||
DashboardID: 1,
|
||||
OrgID: 1,
|
||||
UserID: 1,
|
||||
PanelID: 1,
|
||||
Text: "",
|
||||
ID: int64(i + 1),
|
||||
DashboardID: 1,
|
||||
DashboardUID: "uid" + strconv.Itoa(i),
|
||||
OrgID: 1,
|
||||
UserID: 1,
|
||||
PanelID: 1,
|
||||
Text: "",
|
||||
}
|
||||
|
||||
// mark every third as an API annotation
|
||||
// that does not belong to a dashboard
|
||||
if i%3 == 1 {
|
||||
a.DashboardID = 0
|
||||
a.DashboardID = 0 // nolint: staticcheck
|
||||
a.DashboardUID = ""
|
||||
}
|
||||
|
||||
// mark every third annotation as an alert annotation
|
||||
if i%3 == 0 {
|
||||
a.AlertID = 10
|
||||
a.DashboardID = 2
|
||||
a.DashboardID = 2 // nolint: staticcheck
|
||||
a.DashboardUID = "dashboard2uid"
|
||||
}
|
||||
|
||||
// create epoch as int annotations.go line 40
|
||||
|
||||
@@ -85,6 +85,7 @@ func (r *LokiHistorianStore) Get(ctx context.Context, query annotations.ItemQuer
|
||||
|
||||
// if the query is filtering on tags, but not on a specific dashboard, we shouldn't query loki
|
||||
// since state history won't have tags for annotations
|
||||
// nolint: staticcheck
|
||||
if len(query.Tags) > 0 && query.DashboardID == 0 && query.DashboardUID == "" {
|
||||
return make([]*annotations.ItemDTO, 0), nil
|
||||
}
|
||||
@@ -178,7 +179,7 @@ func (r *LokiHistorianStore) annotationsFromStream(stream historian.Stream, ac a
|
||||
|
||||
items = append(items, &annotations.ItemDTO{
|
||||
AlertID: entry.RuleID,
|
||||
DashboardID: ac.Dashboards[entry.DashboardUID],
|
||||
DashboardID: ac.Dashboards[entry.DashboardUID], // nolint: staticcheck
|
||||
DashboardUID: &entry.DashboardUID,
|
||||
PanelID: entry.PanelID,
|
||||
NewState: entry.Current,
|
||||
@@ -280,8 +281,10 @@ func buildHistoryQuery(query *annotations.ItemQuery, dashboards map[string]int64
|
||||
RuleUID: ruleUID,
|
||||
}
|
||||
|
||||
// nolint: staticcheck
|
||||
if historyQuery.DashboardUID == "" && query.DashboardID != 0 {
|
||||
for uid, id := range dashboards {
|
||||
// nolint: staticcheck
|
||||
if query.DashboardID == id {
|
||||
historyQuery.DashboardUID = uid
|
||||
break
|
||||
|
||||
@@ -193,7 +193,7 @@ func TestIntegrationAlertStateHistoryStore(t *testing.T) {
|
||||
|
||||
query := annotations.ItemQuery{
|
||||
OrgID: 1,
|
||||
DashboardID: dashboard1.ID,
|
||||
DashboardID: dashboard1.ID, // nolint: staticcheck
|
||||
From: start.UnixMilli(),
|
||||
To: start.Add(time.Second * time.Duration(numTransitions+1)).UnixMilli(),
|
||||
}
|
||||
@@ -243,7 +243,7 @@ func TestIntegrationAlertStateHistoryStore(t *testing.T) {
|
||||
|
||||
query := annotations.ItemQuery{
|
||||
OrgID: 1,
|
||||
DashboardID: dashboard1.ID,
|
||||
DashboardID: dashboard1.ID, // nolint: staticcheck
|
||||
From: start.Add(-2 * time.Second).UnixMilli(),
|
||||
To: start.Add(-1 * time.Second).UnixMilli(),
|
||||
}
|
||||
@@ -273,7 +273,7 @@ func TestIntegrationAlertStateHistoryStore(t *testing.T) {
|
||||
|
||||
query := annotations.ItemQuery{
|
||||
OrgID: 1,
|
||||
DashboardID: dashboard1.ID,
|
||||
DashboardID: dashboard1.ID, // nolint: staticcheck
|
||||
From: start.Add(-1 * time.Second).UnixMilli(), // should clamp to start
|
||||
To: start.Add(1 * time.Second).UnixMilli(),
|
||||
}
|
||||
@@ -294,17 +294,17 @@ func TestIntegrationAlertStateHistoryStore(t *testing.T) {
|
||||
fakeLokiClient.cfg.MaxQueryLength = oldMax
|
||||
})
|
||||
|
||||
t.Run("should sort history by time", func(t *testing.T) {
|
||||
t.Run("should sort history by time and be able to query by dashboard uid", func(t *testing.T) {
|
||||
fakeLokiClient.rangeQueryRes = []historian.Stream{
|
||||
historian.StatesToStream(ruleMetaFromRule(t, dashboardRules[dashboard1.UID][0]), transitions, map[string]string{}, log.NewNopLogger()),
|
||||
historian.StatesToStream(ruleMetaFromRule(t, dashboardRules[dashboard1.UID][1]), transitions, map[string]string{}, log.NewNopLogger()),
|
||||
}
|
||||
|
||||
query := annotations.ItemQuery{
|
||||
OrgID: 1,
|
||||
DashboardID: dashboard1.ID,
|
||||
From: start.UnixMilli(),
|
||||
To: start.Add(time.Second * time.Duration(numTransitions+1)).UnixMilli(),
|
||||
OrgID: 1,
|
||||
DashboardUID: dashboard1.UID,
|
||||
From: start.UnixMilli(),
|
||||
To: start.Add(time.Second * time.Duration(numTransitions+1)).UnixMilli(),
|
||||
}
|
||||
res, err := store.Get(
|
||||
context.Background(),
|
||||
@@ -393,7 +393,7 @@ func TestIntegrationAlertStateHistoryStore(t *testing.T) {
|
||||
|
||||
expected := &annotations.ItemDTO{
|
||||
AlertID: rule.ID,
|
||||
DashboardID: dashboard1.ID,
|
||||
DashboardID: dashboard1.ID, // nolint: staticcheck
|
||||
DashboardUID: &dashboard1.UID,
|
||||
PanelID: *rule.PanelID,
|
||||
Time: transition.LastEvaluationTime.UnixMilli(),
|
||||
@@ -433,6 +433,7 @@ func TestIntegrationAlertStateHistoryStore(t *testing.T) {
|
||||
require.Len(t, items, numTransitions)
|
||||
|
||||
for _, item := range items {
|
||||
// nolint: staticcheck
|
||||
require.Equal(t, dashboard1.ID, item.DashboardID)
|
||||
require.Equal(t, dashboard1.UID, *item.DashboardUID)
|
||||
}
|
||||
@@ -464,7 +465,7 @@ func TestIntegrationAlertStateHistoryStore(t *testing.T) {
|
||||
|
||||
for _, item := range items {
|
||||
require.Zero(t, *item.DashboardUID)
|
||||
require.Zero(t, item.DashboardID)
|
||||
require.Zero(t, item.DashboardID) // nolint: staticcheck
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -553,7 +554,7 @@ func TestBuildHistoryQuery(t *testing.T) {
|
||||
t.Run("should set dashboard UID from dashboard ID if query does not contain UID", func(t *testing.T) {
|
||||
query := buildHistoryQuery(
|
||||
&annotations.ItemQuery{
|
||||
DashboardID: 1,
|
||||
DashboardID: 1, // nolint: staticcheck
|
||||
},
|
||||
map[string]int64{
|
||||
"dashboard-uid": 1,
|
||||
@@ -566,7 +567,7 @@ func TestBuildHistoryQuery(t *testing.T) {
|
||||
t.Run("should skip dashboard UID if missing from query and dashboard map", func(t *testing.T) {
|
||||
query := buildHistoryQuery(
|
||||
&annotations.ItemQuery{
|
||||
DashboardID: 1,
|
||||
DashboardID: 1, // nolint: staticcheck
|
||||
},
|
||||
map[string]int64{
|
||||
"other-dashboard-uid": 2,
|
||||
@@ -794,7 +795,7 @@ func compareAnnotationItem(t *testing.T, expected, actual *annotations.ItemDTO)
|
||||
require.Equal(t, expected.PanelID, actual.PanelID)
|
||||
}
|
||||
if expected.DashboardUID != nil {
|
||||
require.Equal(t, expected.DashboardID, actual.DashboardID)
|
||||
require.Equal(t, expected.DashboardID, actual.DashboardID) // nolint: staticcheck
|
||||
require.Equal(t, *expected.DashboardUID, *actual.DashboardUID)
|
||||
}
|
||||
require.Equal(t, expected.NewState, actual.NewState)
|
||||
|
||||
@@ -5,11 +5,11 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/annotations/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/migrations"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
|
||||
|
||||
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
||||
@@ -46,6 +46,13 @@ type xormRepositoryImpl struct {
|
||||
}
|
||||
|
||||
func NewXormStore(cfg *setting.Cfg, l log.Logger, db db.DB, tagService tag.Service) *xormRepositoryImpl {
|
||||
// populate dashboard_uid at startup, to ensure safe downgrades & upgrades after
|
||||
// the initial migration occurs
|
||||
err := migrations.RunDashboardUIDMigrations(db.GetEngine().NewSession(), db.GetEngine().DriverName())
|
||||
if err != nil {
|
||||
l.Error("failed to populate dashboard_uid for annotations", "error", err)
|
||||
}
|
||||
|
||||
return &xormRepositoryImpl{
|
||||
cfg: cfg,
|
||||
db: db,
|
||||
@@ -255,6 +262,7 @@ func (r *xormRepositoryImpl) Get(ctx context.Context, query annotations.ItemQuer
|
||||
annotation.id,
|
||||
annotation.epoch as time,
|
||||
annotation.epoch_end as time_end,
|
||||
annotation.dashboard_uid,
|
||||
annotation.dashboard_id,
|
||||
annotation.panel_id,
|
||||
annotation.new_state,
|
||||
@@ -292,11 +300,18 @@ func (r *xormRepositoryImpl) Get(ctx context.Context, query annotations.ItemQuer
|
||||
params = append(params, query.AlertUID, query.OrgID)
|
||||
}
|
||||
|
||||
// nolint: staticcheck
|
||||
if query.DashboardID != 0 {
|
||||
sql.WriteString(` AND a.dashboard_id = ?`)
|
||||
params = append(params, query.DashboardID)
|
||||
}
|
||||
|
||||
// note: orgID is already required above
|
||||
if query.DashboardUID != "" {
|
||||
sql.WriteString(` AND a.dashboard_uid = ?`)
|
||||
params = append(params, query.DashboardUID)
|
||||
}
|
||||
|
||||
if query.PanelID != 0 {
|
||||
sql.WriteString(` AND a.panel_id = ?`)
|
||||
params = append(params, query.PanelID)
|
||||
@@ -351,13 +366,11 @@ func (r *xormRepositoryImpl) Get(ctx context.Context, query annotations.ItemQuer
|
||||
}
|
||||
}
|
||||
|
||||
acFilter, err := r.getAccessControlFilter(query.SignedInUser, accessResources)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
acFilter, acParams := r.getAccessControlFilter(query.SignedInUser, accessResources)
|
||||
if acFilter != "" {
|
||||
sql.WriteString(fmt.Sprintf(" AND (%s)", acFilter))
|
||||
}
|
||||
params = append(params, acParams...)
|
||||
|
||||
// order of ORDER BY arguments match the order of a sql index for performance
|
||||
orderBy := " ORDER BY a.org_id, a.epoch_end DESC, a.epoch DESC"
|
||||
@@ -377,41 +390,30 @@ func (r *xormRepositoryImpl) Get(ctx context.Context, query annotations.ItemQuer
|
||||
return items, err
|
||||
}
|
||||
|
||||
func (r *xormRepositoryImpl) getAccessControlFilter(user identity.Requester, accessResources *accesscontrol.AccessResources) (string, error) {
|
||||
func (r *xormRepositoryImpl) getAccessControlFilter(user identity.Requester, accessResources *accesscontrol.AccessResources) (string, []any) {
|
||||
if accessResources.SkipAccessControlFilter {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
var filters []string
|
||||
var params []any
|
||||
|
||||
if accessResources.CanAccessOrgAnnotations {
|
||||
filters = append(filters, "a.dashboard_id = 0")
|
||||
}
|
||||
|
||||
if accessResources.CanAccessDashAnnotations {
|
||||
var dashboardIDs []int64
|
||||
for _, id := range accessResources.Dashboards {
|
||||
dashboardIDs = append(dashboardIDs, id)
|
||||
}
|
||||
|
||||
var inClause string
|
||||
if len(dashboardIDs) == 0 {
|
||||
inClause = "SELECT * FROM (SELECT 0 LIMIT 0) tt" // empty set
|
||||
if len(accessResources.Dashboards) == 0 {
|
||||
filters = append(filters, "1=0") // empty set
|
||||
} else {
|
||||
b := make([]byte, 0, 3*len(dashboardIDs))
|
||||
|
||||
b = strconv.AppendInt(b, dashboardIDs[0], 10)
|
||||
for _, num := range dashboardIDs[1:] {
|
||||
b = append(b, ',')
|
||||
b = strconv.AppendInt(b, num, 10)
|
||||
filters = append(filters, fmt.Sprintf("a.dashboard_uid IN (%s)", strings.Repeat("?,", len(accessResources.Dashboards)-1)+"?"))
|
||||
for uid := range accessResources.Dashboards {
|
||||
params = append(params, uid)
|
||||
}
|
||||
|
||||
inClause = string(b)
|
||||
}
|
||||
filters = append(filters, fmt.Sprintf("a.dashboard_id IN (%s)", inClause))
|
||||
}
|
||||
|
||||
return strings.Join(filters, " OR "), nil
|
||||
return strings.Join(filters, " OR "), params
|
||||
}
|
||||
|
||||
func (r *xormRepositoryImpl) Delete(ctx context.Context, params *annotations.DeleteParams) error {
|
||||
@@ -433,14 +435,27 @@ func (r *xormRepositoryImpl) Delete(ctx context.Context, params *annotations.Del
|
||||
if _, err := sess.Exec(sql, params.ID, params.OrgID); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if params.DashboardUID != "" {
|
||||
annoTagSQL = "DELETE FROM annotation_tag WHERE annotation_id IN (SELECT id FROM annotation WHERE dashboard_uid = ? AND panel_id = ? AND org_id = ?)"
|
||||
sql = "DELETE FROM annotation WHERE dashboard_uid = ? AND panel_id = ? AND org_id = ?"
|
||||
|
||||
if _, err := sess.Exec(annoTagSQL, params.DashboardUID, params.PanelID, params.OrgID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := sess.Exec(sql, params.DashboardUID, params.PanelID, params.OrgID); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
annoTagSQL = "DELETE FROM annotation_tag WHERE annotation_id IN (SELECT id FROM annotation WHERE dashboard_id = ? AND panel_id = ? AND org_id = ?)"
|
||||
sql = "DELETE FROM annotation WHERE dashboard_id = ? AND panel_id = ? AND org_id = ?"
|
||||
|
||||
// nolint: staticcheck
|
||||
if _, err := sess.Exec(annoTagSQL, params.DashboardID, params.PanelID, params.OrgID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// nolint: staticcheck
|
||||
if _, err := sess.Exec(sql, params.DashboardID, params.PanelID, params.OrgID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -78,14 +78,15 @@ func TestIntegrationAnnotations(t *testing.T) {
|
||||
var err error
|
||||
|
||||
annotation := &annotations.Item{
|
||||
OrgID: 1,
|
||||
UserID: 1,
|
||||
DashboardID: dashboard.ID,
|
||||
Text: "hello",
|
||||
Type: "alert",
|
||||
Epoch: 10,
|
||||
Tags: []string{"outage", "error", "type:outage", "server:server-1"},
|
||||
Data: simplejson.NewFromAny(map[string]any{"data1": "I am a cool data", "data2": "I am another cool data"}),
|
||||
OrgID: 1,
|
||||
UserID: 1,
|
||||
DashboardID: dashboard.ID, // nolint: staticcheck
|
||||
DashboardUID: dashboard.UID,
|
||||
Text: "hello",
|
||||
Type: "alert",
|
||||
Epoch: 10,
|
||||
Tags: []string{"outage", "error", "type:outage", "server:server-1"},
|
||||
Data: simplejson.NewFromAny(map[string]any{"data1": "I am a cool data", "data2": "I am another cool data"}),
|
||||
}
|
||||
err = store.Add(context.Background(), annotation)
|
||||
require.NoError(t, err)
|
||||
@@ -93,14 +94,15 @@ func TestIntegrationAnnotations(t *testing.T) {
|
||||
assert.Equal(t, annotation.Epoch, annotation.EpochEnd)
|
||||
|
||||
annotation2 := &annotations.Item{
|
||||
OrgID: 1,
|
||||
UserID: 1,
|
||||
DashboardID: dashboard2.ID,
|
||||
Text: "hello",
|
||||
Type: "alert",
|
||||
Epoch: 21, // Should swap epoch & epochEnd
|
||||
EpochEnd: 20,
|
||||
Tags: []string{"outage", "type:outage", "server:server-1", "error"},
|
||||
OrgID: 1,
|
||||
UserID: 1,
|
||||
DashboardID: dashboard2.ID, // nolint: staticcheck
|
||||
DashboardUID: dashboard2.UID,
|
||||
Text: "hello",
|
||||
Type: "alert",
|
||||
Epoch: 21, // Should swap epoch & epochEnd
|
||||
EpochEnd: 20,
|
||||
Tags: []string{"outage", "type:outage", "server:server-1", "error"},
|
||||
}
|
||||
err = store.Add(context.Background(), annotation2)
|
||||
require.NoError(t, err)
|
||||
@@ -135,7 +137,31 @@ func TestIntegrationAnnotations(t *testing.T) {
|
||||
t.Run("Can query for annotation by dashboard id", func(t *testing.T) {
|
||||
items, err := store.Get(context.Background(), annotations.ItemQuery{
|
||||
OrgID: 1,
|
||||
DashboardID: dashboard.ID,
|
||||
DashboardID: dashboard.ID, // nolint: staticcheck
|
||||
From: 0,
|
||||
To: 15,
|
||||
SignedInUser: testUser,
|
||||
}, &annotation_ac.AccessResources{
|
||||
Dashboards: map[string]int64{
|
||||
dashboard.UID: dashboard.ID,
|
||||
},
|
||||
CanAccessDashAnnotations: true,
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, items, 1)
|
||||
|
||||
assert.Equal(t, []string{"outage", "error", "type:outage", "server:server-1"}, items[0].Tags)
|
||||
|
||||
assert.GreaterOrEqual(t, items[0].Created, int64(0))
|
||||
assert.GreaterOrEqual(t, items[0].Updated, int64(0))
|
||||
assert.Equal(t, items[0].Updated, items[0].Created)
|
||||
})
|
||||
|
||||
t.Run("Can query for annotation by dashboard uid", func(t *testing.T) {
|
||||
items, err := store.Get(context.Background(), annotations.ItemQuery{
|
||||
OrgID: 1,
|
||||
DashboardUID: dashboard.UID,
|
||||
From: 0,
|
||||
To: 15,
|
||||
SignedInUser: testUser,
|
||||
@@ -234,12 +260,13 @@ func TestIntegrationAnnotations(t *testing.T) {
|
||||
|
||||
t.Run("Should not find any when item is outside time range", func(t *testing.T) {
|
||||
accRes := &annotation_ac.AccessResources{
|
||||
Dashboards: map[string]int64{"foo": 1},
|
||||
Dashboards: map[string]int64{dashboard.UID: 1},
|
||||
CanAccessDashAnnotations: true,
|
||||
}
|
||||
items, err := store.Get(context.Background(), annotations.ItemQuery{
|
||||
OrgID: 1,
|
||||
DashboardID: 1,
|
||||
DashboardID: 1, // nolint: staticcheck
|
||||
DashboardUID: dashboard.UID,
|
||||
From: 12,
|
||||
To: 15,
|
||||
SignedInUser: testUser,
|
||||
@@ -250,12 +277,13 @@ func TestIntegrationAnnotations(t *testing.T) {
|
||||
|
||||
t.Run("Should not find one when tag filter does not match", func(t *testing.T) {
|
||||
accRes := &annotation_ac.AccessResources{
|
||||
Dashboards: map[string]int64{"foo": 1},
|
||||
Dashboards: map[string]int64{dashboard.UID: 1},
|
||||
CanAccessDashAnnotations: true,
|
||||
}
|
||||
items, err := store.Get(context.Background(), annotations.ItemQuery{
|
||||
OrgID: 1,
|
||||
DashboardID: 1,
|
||||
DashboardID: 1, // nolint: staticcheck
|
||||
DashboardUID: dashboard.UID,
|
||||
From: 1,
|
||||
To: 15,
|
||||
Tags: []string{"asd"},
|
||||
@@ -267,12 +295,13 @@ func TestIntegrationAnnotations(t *testing.T) {
|
||||
|
||||
t.Run("Should not find one when type filter does not match", func(t *testing.T) {
|
||||
accRes := &annotation_ac.AccessResources{
|
||||
Dashboards: map[string]int64{"foo": 1},
|
||||
Dashboards: map[string]int64{dashboard.UID: 1},
|
||||
CanAccessDashAnnotations: true,
|
||||
}
|
||||
items, err := store.Get(context.Background(), annotations.ItemQuery{
|
||||
OrgID: 1,
|
||||
DashboardID: 1,
|
||||
DashboardID: 1, // nolint: staticcheck
|
||||
DashboardUID: dashboard.UID,
|
||||
From: 1,
|
||||
To: 15,
|
||||
Type: "alert",
|
||||
@@ -284,12 +313,13 @@ func TestIntegrationAnnotations(t *testing.T) {
|
||||
|
||||
t.Run("Should find one when all tag filters does match", func(t *testing.T) {
|
||||
accRes := &annotation_ac.AccessResources{
|
||||
Dashboards: map[string]int64{"foo": 1},
|
||||
Dashboards: map[string]int64{dashboard.UID: 1},
|
||||
CanAccessDashAnnotations: true,
|
||||
}
|
||||
items, err := store.Get(context.Background(), annotations.ItemQuery{
|
||||
OrgID: 1,
|
||||
DashboardID: 1,
|
||||
DashboardID: 1, // nolint: staticcheck
|
||||
DashboardUID: dashboard.UID,
|
||||
From: 1,
|
||||
To: 15, // this will exclude the second test annotation
|
||||
Tags: []string{"outage", "error"},
|
||||
@@ -315,12 +345,13 @@ func TestIntegrationAnnotations(t *testing.T) {
|
||||
|
||||
t.Run("Should find one when all key value tag filters does match", func(t *testing.T) {
|
||||
accRes := &annotation_ac.AccessResources{
|
||||
Dashboards: map[string]int64{"foo": 1},
|
||||
Dashboards: map[string]int64{dashboard.UID: 1},
|
||||
CanAccessDashAnnotations: true,
|
||||
}
|
||||
items, err := store.Get(context.Background(), annotations.ItemQuery{
|
||||
OrgID: 1,
|
||||
DashboardID: 1,
|
||||
DashboardID: 1, // nolint: staticcheck
|
||||
DashboardUID: dashboard.UID,
|
||||
From: 1,
|
||||
To: 15,
|
||||
Tags: []string{"type:outage", "server:server-1"},
|
||||
@@ -333,13 +364,14 @@ func TestIntegrationAnnotations(t *testing.T) {
|
||||
t.Run("Can update annotation and remove all tags", func(t *testing.T) {
|
||||
query := annotations.ItemQuery{
|
||||
OrgID: 1,
|
||||
DashboardID: 1,
|
||||
DashboardID: 1, // nolint: staticcheck
|
||||
DashboardUID: dashboard.UID,
|
||||
From: 0,
|
||||
To: 15,
|
||||
SignedInUser: testUser,
|
||||
}
|
||||
accRes := &annotation_ac.AccessResources{
|
||||
Dashboards: map[string]int64{"foo": 1},
|
||||
Dashboards: map[string]int64{dashboard.UID: 1},
|
||||
CanAccessDashAnnotations: true,
|
||||
}
|
||||
items, err := store.Get(context.Background(), query, accRes)
|
||||
@@ -368,13 +400,14 @@ func TestIntegrationAnnotations(t *testing.T) {
|
||||
t.Run("Can update annotation with new tags", func(t *testing.T) {
|
||||
query := annotations.ItemQuery{
|
||||
OrgID: 1,
|
||||
DashboardID: 1,
|
||||
DashboardID: 1, // nolint: staticcheck
|
||||
DashboardUID: dashboard.UID,
|
||||
From: 0,
|
||||
To: 15,
|
||||
SignedInUser: testUser,
|
||||
}
|
||||
accRes := &annotation_ac.AccessResources{
|
||||
Dashboards: map[string]int64{"foo": 1},
|
||||
Dashboards: map[string]int64{dashboard.UID: 1},
|
||||
CanAccessDashAnnotations: true,
|
||||
}
|
||||
items, err := store.Get(context.Background(), query, accRes)
|
||||
@@ -401,13 +434,14 @@ func TestIntegrationAnnotations(t *testing.T) {
|
||||
t.Run("Can update annotation with additional tags", func(t *testing.T) {
|
||||
query := annotations.ItemQuery{
|
||||
OrgID: 1,
|
||||
DashboardID: 1,
|
||||
DashboardID: 1, // nolint: staticcheck
|
||||
DashboardUID: dashboard.UID,
|
||||
From: 0,
|
||||
To: 15,
|
||||
SignedInUser: testUser,
|
||||
}
|
||||
accRes := &annotation_ac.AccessResources{
|
||||
Dashboards: map[string]int64{"foo": 1},
|
||||
Dashboards: map[string]int64{dashboard.UID: 1},
|
||||
CanAccessDashAnnotations: true,
|
||||
}
|
||||
items, err := store.Get(context.Background(), query, accRes)
|
||||
@@ -434,13 +468,14 @@ func TestIntegrationAnnotations(t *testing.T) {
|
||||
t.Run("Can update annotations with data", func(t *testing.T) {
|
||||
query := annotations.ItemQuery{
|
||||
OrgID: 1,
|
||||
DashboardID: 1,
|
||||
DashboardID: 1, // nolint: staticcheck
|
||||
DashboardUID: dashboard.UID,
|
||||
From: 0,
|
||||
To: 15,
|
||||
SignedInUser: testUser,
|
||||
}
|
||||
accRes := &annotation_ac.AccessResources{
|
||||
Dashboards: map[string]int64{"foo": 1},
|
||||
Dashboards: map[string]int64{dashboard.UID: 1},
|
||||
CanAccessDashAnnotations: true,
|
||||
}
|
||||
items, err := store.Get(context.Background(), query, accRes)
|
||||
@@ -470,13 +505,14 @@ func TestIntegrationAnnotations(t *testing.T) {
|
||||
t.Run("Can delete annotation", func(t *testing.T) {
|
||||
query := annotations.ItemQuery{
|
||||
OrgID: 1,
|
||||
DashboardID: 1,
|
||||
DashboardID: 1, // nolint: staticcheck
|
||||
DashboardUID: dashboard.UID,
|
||||
From: 0,
|
||||
To: 15,
|
||||
SignedInUser: testUser,
|
||||
}
|
||||
accRes := &annotation_ac.AccessResources{
|
||||
Dashboards: map[string]int64{"foo": 1},
|
||||
Dashboards: map[string]int64{dashboard.UID: 1},
|
||||
CanAccessDashAnnotations: true,
|
||||
}
|
||||
items, err := store.Get(context.Background(), query, accRes)
|
||||
@@ -493,14 +529,15 @@ func TestIntegrationAnnotations(t *testing.T) {
|
||||
|
||||
t.Run("Can delete annotation using dashboard id and panel id", func(t *testing.T) {
|
||||
annotation3 := &annotations.Item{
|
||||
OrgID: 1,
|
||||
UserID: 1,
|
||||
DashboardID: dashboard2.ID,
|
||||
Text: "toBeDeletedWithPanelId",
|
||||
Type: "alert",
|
||||
Epoch: 11,
|
||||
Tags: []string{"test"},
|
||||
PanelID: 20,
|
||||
OrgID: 1,
|
||||
UserID: 1,
|
||||
DashboardID: dashboard2.ID, // nolint: staticcheck
|
||||
DashboardUID: dashboard2.UID,
|
||||
Text: "toBeDeletedWithPanelId",
|
||||
Type: "alert",
|
||||
Epoch: 11,
|
||||
Tags: []string{"test"},
|
||||
PanelID: 20,
|
||||
}
|
||||
err = store.Add(context.Background(), annotation3)
|
||||
require.NoError(t, err)
|
||||
@@ -520,9 +557,46 @@ func TestIntegrationAnnotations(t *testing.T) {
|
||||
items, err := store.Get(context.Background(), query, accRes)
|
||||
require.NoError(t, err)
|
||||
|
||||
dashboardId := items[0].DashboardID
|
||||
panelId := items[0].PanelID
|
||||
err = store.Delete(context.Background(), &annotations.DeleteParams{DashboardID: dashboardId, PanelID: panelId, OrgID: 1})
|
||||
// nolint:staticcheck
|
||||
err = store.Delete(context.Background(), &annotations.DeleteParams{DashboardID: items[0].DashboardID, PanelID: items[0].PanelID, OrgID: 1})
|
||||
require.NoError(t, err)
|
||||
|
||||
items, err = store.Get(context.Background(), query, accRes)
|
||||
require.NoError(t, err)
|
||||
assert.Empty(t, items)
|
||||
})
|
||||
|
||||
t.Run("Can delete annotation using dashboard uid and panel id", func(t *testing.T) {
|
||||
annotation3 := &annotations.Item{
|
||||
OrgID: 1,
|
||||
UserID: 1,
|
||||
DashboardUID: dashboard2.UID,
|
||||
Text: "toBeDeletedWithPanelId",
|
||||
Type: "alert",
|
||||
Epoch: 11,
|
||||
Tags: []string{"test"},
|
||||
PanelID: 20,
|
||||
}
|
||||
err = store.Add(context.Background(), annotation3)
|
||||
require.NoError(t, err)
|
||||
|
||||
accRes := &annotation_ac.AccessResources{
|
||||
Dashboards: map[string]int64{
|
||||
dashboard2.UID: dashboard2.ID,
|
||||
},
|
||||
CanAccessDashAnnotations: true,
|
||||
}
|
||||
|
||||
query := annotations.ItemQuery{
|
||||
OrgID: 1,
|
||||
AnnotationID: annotation3.ID,
|
||||
SignedInUser: testUser,
|
||||
}
|
||||
items, err := store.Get(context.Background(), query, accRes)
|
||||
require.NoError(t, err)
|
||||
|
||||
// nolint:staticcheck
|
||||
err = store.Delete(context.Background(), &annotations.DeleteParams{DashboardUID: *items[0].DashboardUID, PanelID: items[0].PanelID, OrgID: 1})
|
||||
require.NoError(t, err)
|
||||
|
||||
items, err = store.Get(context.Background(), query, accRes)
|
||||
@@ -635,15 +709,16 @@ func benchmarkFindTags(b *testing.B, numAnnotations int) {
|
||||
require.NoError(b, err)
|
||||
|
||||
annotationWithTheTag := annotations.Item{
|
||||
ID: int64(numAnnotations) + 1,
|
||||
OrgID: 1,
|
||||
UserID: 1,
|
||||
DashboardID: int64(1),
|
||||
Text: "hello",
|
||||
Type: "alert",
|
||||
Epoch: 10,
|
||||
Tags: []string{"outage", "error", "type:outage", "server:server-1"},
|
||||
Data: simplejson.NewFromAny(map[string]any{"data1": "I am a cool data", "data2": "I am another cool data"}),
|
||||
ID: int64(numAnnotations) + 1,
|
||||
OrgID: 1,
|
||||
UserID: 1,
|
||||
DashboardID: 1, // nolint: staticcheck
|
||||
DashboardUID: "uid",
|
||||
Text: "hello",
|
||||
Type: "alert",
|
||||
Epoch: 10,
|
||||
Tags: []string{"outage", "error", "type:outage", "server:server-1"},
|
||||
Data: simplejson.NewFromAny(map[string]any{"data1": "I am a cool data", "data2": "I am another cool data"}),
|
||||
}
|
||||
err = store.Add(context.Background(), &annotationWithTheTag)
|
||||
require.NoError(b, err)
|
||||
|
||||
Reference in New Issue
Block a user