mirror of
https://github.com/grafana/grafana.git
synced 2026-08-18 17:15:08 -05:00
Chore: Sql store split for legacy alerting (#52901)
Moves ~20 sqlstore methods for legacy alerting out of sqlstore (sqlstore.Store interface) and into alerting.
This commit is contained in:
@@ -29,7 +29,7 @@ type UsageStatsQuerier interface {
|
||||
// configured in Grafana.
|
||||
func (e *AlertEngine) QueryUsageStats(ctx context.Context) (*UsageStats, error) {
|
||||
cmd := &models.GetAllAlertsQuery{}
|
||||
err := e.sqlStore.GetAllAlertQueryHandler(ctx, cmd)
|
||||
err := e.AlertStore.GetAllAlertQueryHandler(ctx, cmd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -64,7 +64,7 @@ func (e *AlertEngine) mapRulesToUsageStats(ctx context.Context, rules []*models.
|
||||
result := map[string]int{}
|
||||
for k, v := range typeCount {
|
||||
query := &datasources.GetDataSourceQuery{Id: k}
|
||||
err := e.sqlStore.GetDataSource(ctx, query)
|
||||
err := e.datasourceService.GetDataSource(ctx, query)
|
||||
if err != nil {
|
||||
return map[string]int{}, nil
|
||||
}
|
||||
|
||||
@@ -12,12 +12,22 @@ import (
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
fd "github.com/grafana/grafana/pkg/services/datasources/fakes"
|
||||
)
|
||||
|
||||
func TestAlertingUsageStats(t *testing.T) {
|
||||
store := &AlertStoreMock{}
|
||||
dsMock := &fd.FakeDataSourceService{
|
||||
DataSources: []*datasources.DataSource{
|
||||
{Id: 1, Type: datasources.DS_INFLUXDB},
|
||||
{Id: 2, Type: datasources.DS_GRAPHITE},
|
||||
{Id: 3, Type: datasources.DS_PROMETHEUS},
|
||||
{Id: 4, Type: datasources.DS_PROMETHEUS},
|
||||
},
|
||||
}
|
||||
ae := &AlertEngine{
|
||||
sqlStore: store,
|
||||
AlertStore: store,
|
||||
datasourceService: dsMock,
|
||||
}
|
||||
|
||||
store.getAllAlerts = func(ctx context.Context, query *models.GetAllAlertsQuery) error {
|
||||
@@ -41,23 +51,6 @@ func TestAlertingUsageStats(t *testing.T) {
|
||||
return nil
|
||||
}
|
||||
|
||||
store.getDataSource = func(ctx context.Context, query *datasources.GetDataSourceQuery) error {
|
||||
ds := map[int64]*datasources.DataSource{
|
||||
1: {Type: "influxdb"},
|
||||
2: {Type: "graphite"},
|
||||
3: {Type: "prometheus"},
|
||||
4: {Type: "prometheus"},
|
||||
}
|
||||
|
||||
r, exist := ds[query.Id]
|
||||
if !exist {
|
||||
return datasources.ErrDataSourceNotFound
|
||||
}
|
||||
|
||||
query.Result = r
|
||||
return nil
|
||||
}
|
||||
|
||||
result, err := ae.QueryUsageStats(context.Background())
|
||||
require.NoError(t, err, "getAlertingUsage should not return error")
|
||||
|
||||
|
||||
@@ -147,7 +147,7 @@ func (c *QueryCondition) executeQuery(context *alerting.EvalContext, timeRange l
|
||||
OrgId: context.Rule.OrgID,
|
||||
}
|
||||
|
||||
if err := context.Store.GetDataSource(context.Ctx, getDsInfo); err != nil {
|
||||
if err := context.GetDataSource(context.Ctx, getDsInfo); err != nil {
|
||||
return nil, fmt.Errorf("could not find datasource: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/services/alerting"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
fd "github.com/grafana/grafana/pkg/services/datasources/fakes"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/mockstore"
|
||||
"github.com/grafana/grafana/pkg/services/validations"
|
||||
"github.com/grafana/grafana/pkg/tsdb/intervalv2"
|
||||
@@ -138,7 +139,6 @@ func (rh fakeIntervalTestReqHandler) HandleRequest(ctx context.Context, dsInfo *
|
||||
func applyScenario(t *testing.T, timeRange string, dataSourceJsonData *simplejson.Json, queryModel string, verifier func(query legacydata.DataSubQuery)) {
|
||||
t.Run("desc", func(t *testing.T) {
|
||||
store := mockstore.NewSQLStoreMock()
|
||||
store.ExpectedDatasource = &datasources.DataSource{Id: 1, Type: "graphite", JsonData: dataSourceJsonData}
|
||||
|
||||
ctx := &queryIntervalTestContext{}
|
||||
ctx.result = &alerting.EvalContext{
|
||||
@@ -146,6 +146,11 @@ func applyScenario(t *testing.T, timeRange string, dataSourceJsonData *simplejso
|
||||
Rule: &alerting.Rule{},
|
||||
RequestValidator: &validations.OSSPluginRequestValidator{},
|
||||
Store: store,
|
||||
DatasourceService: &fd.FakeDataSourceService{
|
||||
DataSources: []*datasources.DataSource{
|
||||
{Id: 1, Type: datasources.DS_GRAPHITE, JsonData: dataSourceJsonData},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
jsonModel, err := simplejson.NewJson([]byte(`{
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
fd "github.com/grafana/grafana/pkg/services/datasources/fakes"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/mockstore"
|
||||
"github.com/grafana/grafana/pkg/services/validations"
|
||||
"github.com/grafana/grafana/pkg/tsdb/legacydata"
|
||||
@@ -37,7 +38,6 @@ func TestQueryCondition(t *testing.T) {
|
||||
setup := func() *queryConditionTestContext {
|
||||
ctx := &queryConditionTestContext{}
|
||||
store := mockstore.NewSQLStoreMock()
|
||||
store.ExpectedDatasource = &datasources.DataSource{Id: 1, Type: "graphite"}
|
||||
|
||||
ctx.reducer = `{"type":"avg"}`
|
||||
ctx.evaluator = `{"type":"gt","params":[100]}`
|
||||
@@ -46,6 +46,11 @@ func TestQueryCondition(t *testing.T) {
|
||||
Rule: &alerting.Rule{},
|
||||
RequestValidator: &validations.OSSPluginRequestValidator{},
|
||||
Store: store,
|
||||
DatasourceService: &fd.FakeDataSourceService{
|
||||
DataSources: []*datasources.DataSource{
|
||||
{Id: 1, Type: datasources.DS_GRAPHITE},
|
||||
},
|
||||
},
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"golang.org/x/sync/errgroup"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/localcache"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/infra/usagestats"
|
||||
@@ -25,19 +26,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/tsdb/legacydata"
|
||||
)
|
||||
|
||||
// AlertStore is a subset of SQLStore API to satisfy the needs of the alerting service.
|
||||
// A subset is needed to make it easier to mock during the tests.
|
||||
type AlertStore interface {
|
||||
GetAllAlertQueryHandler(context.Context, *models.GetAllAlertsQuery) error
|
||||
GetDataSource(context.Context, *datasources.GetDataSourceQuery) error
|
||||
SetAlertNotificationStateToCompleteCommand(context.Context, *models.SetAlertNotificationStateToCompleteCommand) error
|
||||
SetAlertNotificationStateToPendingCommand(context.Context, *models.SetAlertNotificationStateToPendingCommand) error
|
||||
GetAlertNotificationUidWithId(context.Context, *models.GetAlertNotificationUidQuery) error
|
||||
GetAlertNotificationsWithUidToSend(context.Context, *models.GetAlertNotificationsWithUidToSendQuery) error
|
||||
GetOrCreateAlertNotificationState(context.Context, *models.GetOrCreateNotificationStateQuery) error
|
||||
SetAlertState(context.Context, *models.SetAlertStateCommand) error
|
||||
}
|
||||
|
||||
// AlertEngine is the background process that
|
||||
// schedules alert evaluations and makes sure notifications
|
||||
// are sent.
|
||||
@@ -56,9 +44,10 @@ type AlertEngine struct {
|
||||
resultHandler resultHandler
|
||||
usageStatsService usagestats.Service
|
||||
tracer tracing.Tracer
|
||||
sqlStore AlertStore
|
||||
AlertStore AlertStore
|
||||
dashAlertExtractor DashAlertExtractor
|
||||
dashboardService dashboards.DashboardService
|
||||
datasourceService datasources.DataSourceService
|
||||
}
|
||||
|
||||
// IsDisabled returns true if the alerting service is disabled for this instance.
|
||||
@@ -69,8 +58,8 @@ func (e *AlertEngine) IsDisabled() bool {
|
||||
// ProvideAlertEngine returns a new AlertEngine.
|
||||
func ProvideAlertEngine(renderer rendering.Service, requestValidator models.PluginRequestValidator,
|
||||
dataService legacydata.RequestHandler, usageStatsService usagestats.Service, encryptionService encryption.Internal,
|
||||
notificationService *notifications.NotificationService, tracer tracing.Tracer, sqlStore AlertStore, cfg *setting.Cfg,
|
||||
dashAlertExtractor DashAlertExtractor, dashboardService dashboards.DashboardService) *AlertEngine {
|
||||
notificationService *notifications.NotificationService, tracer tracing.Tracer, store AlertStore, cfg *setting.Cfg,
|
||||
dashAlertExtractor DashAlertExtractor, dashboardService dashboards.DashboardService, cacheService *localcache.CacheService, dsService datasources.DataSourceService) *AlertEngine {
|
||||
e := &AlertEngine{
|
||||
Cfg: cfg,
|
||||
RenderService: renderer,
|
||||
@@ -78,16 +67,17 @@ func ProvideAlertEngine(renderer rendering.Service, requestValidator models.Plug
|
||||
DataService: dataService,
|
||||
usageStatsService: usageStatsService,
|
||||
tracer: tracer,
|
||||
sqlStore: sqlStore,
|
||||
AlertStore: store,
|
||||
dashAlertExtractor: dashAlertExtractor,
|
||||
dashboardService: dashboardService,
|
||||
datasourceService: dsService,
|
||||
}
|
||||
e.execQueue = make(chan *Job, 1000)
|
||||
e.scheduler = newScheduler()
|
||||
e.evalHandler = NewEvalHandler(e.DataService)
|
||||
e.ruleReader = newRuleReader(sqlStore)
|
||||
e.ruleReader = newRuleReader(store)
|
||||
e.log = log.New("alerting.engine")
|
||||
e.resultHandler = newResultHandler(e.RenderService, sqlStore, notificationService, encryptionService.GetDecryptedValue)
|
||||
e.resultHandler = newResultHandler(e.RenderService, store, notificationService, encryptionService.GetDecryptedValue)
|
||||
|
||||
e.registerUsageMetrics()
|
||||
|
||||
@@ -203,7 +193,7 @@ func (e *AlertEngine) processJob(attemptID int, attemptChan chan int, cancelChan
|
||||
alertCtx, cancelFn := context.WithTimeout(context.Background(), setting.AlertingEvaluationTimeout)
|
||||
cancelChan <- cancelFn
|
||||
alertCtx, span := e.tracer.Start(alertCtx, "alert execution")
|
||||
evalContext := NewEvalContext(alertCtx, job.Rule, e.RequestValidator, e.sqlStore, e.dashboardService)
|
||||
evalContext := NewEvalContext(alertCtx, job.Rule, e.RequestValidator, e.AlertStore, e.dashboardService, e.datasourceService)
|
||||
evalContext.Ctx = alertCtx
|
||||
|
||||
go func() {
|
||||
|
||||
@@ -9,8 +9,10 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/localcache"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/infra/usagestats"
|
||||
datasources "github.com/grafana/grafana/pkg/services/datasources/fakes"
|
||||
encryptionprovider "github.com/grafana/grafana/pkg/services/encryption/provider"
|
||||
encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
@@ -32,7 +34,8 @@ func TestIntegrationEngineTimeouts(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
tracer := tracing.InitializeTracerForTest()
|
||||
engine := ProvideAlertEngine(nil, nil, nil, usMock, encService, nil, tracer, nil, cfg, nil, nil)
|
||||
dsMock := &datasources.FakeDataSourceService{}
|
||||
engine := ProvideAlertEngine(nil, nil, nil, usMock, encService, nil, tracer, nil, setting.NewCfg(), nil, nil, localcache.New(time.Minute, time.Minute), dsMock)
|
||||
setting.AlertingNotificationTimeout = 30 * time.Second
|
||||
setting.AlertingMaxAttempts = 3
|
||||
engine.resultHandler = &FakeResultHandler{}
|
||||
|
||||
@@ -8,10 +8,12 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/localcache"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/infra/usagestats"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
fd "github.com/grafana/grafana/pkg/services/datasources/fakes"
|
||||
encryptionprovider "github.com/grafana/grafana/pkg/services/encryption/provider"
|
||||
encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
@@ -46,15 +48,11 @@ func (handler *FakeResultHandler) handle(evalContext *EvalContext) error {
|
||||
// A mock implementation of the AlertStore interface, allowing to override certain methods individually
|
||||
type AlertStoreMock struct {
|
||||
getAllAlerts func(context.Context, *models.GetAllAlertsQuery) error
|
||||
getDataSource func(context.Context, *datasources.GetDataSourceQuery) error
|
||||
getAlertNotificationsWithUidToSend func(ctx context.Context, query *models.GetAlertNotificationsWithUidToSendQuery) error
|
||||
getOrCreateNotificationState func(ctx context.Context, query *models.GetOrCreateNotificationStateQuery) error
|
||||
}
|
||||
|
||||
func (a *AlertStoreMock) GetDataSource(c context.Context, cmd *datasources.GetDataSourceQuery) error {
|
||||
if a.getDataSource != nil {
|
||||
return a.getDataSource(c, cmd)
|
||||
}
|
||||
func (a *AlertStoreMock) GetAlertById(c context.Context, cmd *models.GetAlertByIdQuery) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -99,6 +97,22 @@ func (a *AlertStoreMock) SetAlertState(_ context.Context, _ *models.SetAlertStat
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *AlertStoreMock) GetAlertStatesForDashboard(_ context.Context, _ *models.GetAlertStatesForDashboardQuery) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *AlertStoreMock) HandleAlertsQuery(context.Context, *models.GetAlertsQuery) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *AlertStoreMock) PauseAlert(context.Context, *models.PauseAlertCommand) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *AlertStoreMock) PauseAllAlerts(context.Context, *models.PauseAllAlertCommand) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestEngineProcessJob(t *testing.T) {
|
||||
usMock := &usagestats.UsageStatsMock{T: t}
|
||||
|
||||
@@ -111,7 +125,10 @@ func TestEngineProcessJob(t *testing.T) {
|
||||
tracer := tracing.InitializeTracerForTest()
|
||||
|
||||
store := &AlertStoreMock{}
|
||||
engine := ProvideAlertEngine(nil, nil, nil, usMock, encService, nil, tracer, store, cfg, nil, nil)
|
||||
dsMock := &fd.FakeDataSourceService{
|
||||
DataSources: []*datasources.DataSource{{Id: 1, Type: datasources.DS_PROMETHEUS}},
|
||||
}
|
||||
engine := ProvideAlertEngine(nil, nil, nil, usMock, encService, nil, tracer, store, setting.NewCfg(), nil, nil, localcache.New(time.Minute, time.Minute), dsMock)
|
||||
setting.AlertingEvaluationTimeout = 30 * time.Second
|
||||
setting.AlertingNotificationTimeout = 30 * time.Second
|
||||
setting.AlertingMaxAttempts = 3
|
||||
@@ -128,11 +145,6 @@ func TestEngineProcessJob(t *testing.T) {
|
||||
return nil
|
||||
}
|
||||
|
||||
store.getDataSource = func(ctx context.Context, q *datasources.GetDataSourceQuery) error {
|
||||
q.Result = &datasources.DataSource{Id: 1, Type: datasources.DS_PROMETHEUS}
|
||||
return nil
|
||||
}
|
||||
|
||||
report, err := usMock.GetUsageReport(context.Background())
|
||||
require.Nil(t, err)
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
@@ -38,25 +39,27 @@ type EvalContext struct {
|
||||
|
||||
Ctx context.Context
|
||||
|
||||
Store AlertStore
|
||||
dashboardService dashboards.DashboardService
|
||||
Store AlertStore
|
||||
dashboardService dashboards.DashboardService
|
||||
DatasourceService datasources.DataSourceService
|
||||
}
|
||||
|
||||
// NewEvalContext is the EvalContext constructor.
|
||||
func NewEvalContext(alertCtx context.Context, rule *Rule, requestValidator models.PluginRequestValidator,
|
||||
sqlStore AlertStore, dashboardService dashboards.DashboardService) *EvalContext {
|
||||
alertStore AlertStore, dashboardService dashboards.DashboardService, dsService datasources.DataSourceService) *EvalContext {
|
||||
return &EvalContext{
|
||||
Ctx: alertCtx,
|
||||
StartTime: time.Now(),
|
||||
Rule: rule,
|
||||
Logs: make([]*ResultLogEntry, 0),
|
||||
EvalMatches: make([]*EvalMatch, 0),
|
||||
AllMatches: make([]*EvalMatch, 0),
|
||||
Log: log.New("alerting.evalContext"),
|
||||
PrevAlertState: rule.State,
|
||||
RequestValidator: requestValidator,
|
||||
Store: sqlStore,
|
||||
dashboardService: dashboardService,
|
||||
Ctx: alertCtx,
|
||||
StartTime: time.Now(),
|
||||
Rule: rule,
|
||||
Logs: make([]*ResultLogEntry, 0),
|
||||
EvalMatches: make([]*EvalMatch, 0),
|
||||
AllMatches: make([]*EvalMatch, 0),
|
||||
Log: log.New("alerting.evalContext"),
|
||||
PrevAlertState: rule.State,
|
||||
RequestValidator: requestValidator,
|
||||
Store: alertStore,
|
||||
dashboardService: dashboardService,
|
||||
DatasourceService: dsService,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,6 +223,10 @@ func (c *EvalContext) evaluateNotificationTemplateFields() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *EvalContext) GetDataSource(ctx context.Context, q *datasources.GetDataSourceQuery) error {
|
||||
return c.DatasourceService.GetDataSource(ctx, q)
|
||||
}
|
||||
|
||||
// getTemplateMatches returns the values we should use to parse the templates
|
||||
func (c *EvalContext) getTemplateMatches() []*EvalMatch {
|
||||
// EvalMatches represent series violating the rule threshold,
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
)
|
||||
|
||||
func TestStateIsUpdatedWhenNeeded(t *testing.T) {
|
||||
ctx := NewEvalContext(context.Background(), &Rule{Conditions: []Condition{&conditionStub{firing: true}}}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
ctx := NewEvalContext(context.Background(), &Rule{Conditions: []Condition{&conditionStub{firing: true}}}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
|
||||
t.Run("ok -> alerting", func(t *testing.T) {
|
||||
ctx.PrevAlertState = models.AlertStateOK
|
||||
@@ -199,7 +199,7 @@ func TestGetStateFromEvalContext(t *testing.T) {
|
||||
}
|
||||
|
||||
for _, tc := range tcs {
|
||||
evalContext := NewEvalContext(context.Background(), &Rule{Conditions: []Condition{&conditionStub{firing: true}}}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
evalContext := NewEvalContext(context.Background(), &Rule{Conditions: []Condition{&conditionStub{firing: true}}}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
|
||||
tc.applyFn(evalContext)
|
||||
newState := evalContext.GetNewState()
|
||||
@@ -391,7 +391,7 @@ func TestEvaluateNotificationTemplateFields(t *testing.T) {
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(tt *testing.T) {
|
||||
evalContext := NewEvalContext(context.Background(), &Rule{Name: "Rule name: ${value1}", Message: "Rule message: ${value2}",
|
||||
Conditions: []Condition{&conditionStub{firing: true}}}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
Conditions: []Condition{&conditionStub{firing: true}}}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
evalContext.EvalMatches = test.evalMatches
|
||||
evalContext.AllMatches = test.allMatches
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ func TestAlertingEvaluationHandler(t *testing.T) {
|
||||
Conditions: []Condition{&conditionStub{
|
||||
firing: true,
|
||||
}},
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
|
||||
handler.Eval(context)
|
||||
require.Equal(t, true, context.Firing)
|
||||
@@ -39,7 +39,7 @@ func TestAlertingEvaluationHandler(t *testing.T) {
|
||||
t.Run("Show return triggered with single passing condition2", func(t *testing.T) {
|
||||
context := NewEvalContext(context.Background(), &Rule{
|
||||
Conditions: []Condition{&conditionStub{firing: true, operator: "and"}},
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
|
||||
handler.Eval(context)
|
||||
require.Equal(t, true, context.Firing)
|
||||
@@ -52,7 +52,7 @@ func TestAlertingEvaluationHandler(t *testing.T) {
|
||||
&conditionStub{firing: true, operator: "and", matches: []*EvalMatch{{}, {}}},
|
||||
&conditionStub{firing: false, operator: "and"},
|
||||
},
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
|
||||
handler.Eval(context)
|
||||
require.Equal(t, false, context.Firing)
|
||||
@@ -65,7 +65,7 @@ func TestAlertingEvaluationHandler(t *testing.T) {
|
||||
&conditionStub{firing: true, operator: "and"},
|
||||
&conditionStub{firing: false, operator: "or"},
|
||||
},
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
|
||||
handler.Eval(context)
|
||||
require.Equal(t, true, context.Firing)
|
||||
@@ -78,7 +78,7 @@ func TestAlertingEvaluationHandler(t *testing.T) {
|
||||
&conditionStub{firing: true, operator: "and"},
|
||||
&conditionStub{firing: false, operator: "and"},
|
||||
},
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
|
||||
handler.Eval(context)
|
||||
require.Equal(t, false, context.Firing)
|
||||
@@ -92,7 +92,7 @@ func TestAlertingEvaluationHandler(t *testing.T) {
|
||||
&conditionStub{firing: true, operator: "and"},
|
||||
&conditionStub{firing: false, operator: "or"},
|
||||
},
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
|
||||
handler.Eval(context)
|
||||
require.Equal(t, true, context.Firing)
|
||||
@@ -106,7 +106,7 @@ func TestAlertingEvaluationHandler(t *testing.T) {
|
||||
&conditionStub{firing: false, operator: "and"},
|
||||
&conditionStub{firing: false, operator: "or"},
|
||||
},
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
|
||||
handler.Eval(context)
|
||||
require.Equal(t, false, context.Firing)
|
||||
@@ -120,7 +120,7 @@ func TestAlertingEvaluationHandler(t *testing.T) {
|
||||
&conditionStub{firing: false, operator: "and"},
|
||||
&conditionStub{firing: true, operator: "and"},
|
||||
},
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
|
||||
handler.Eval(context)
|
||||
require.Equal(t, false, context.Firing)
|
||||
@@ -134,7 +134,7 @@ func TestAlertingEvaluationHandler(t *testing.T) {
|
||||
&conditionStub{firing: false, operator: "or"},
|
||||
&conditionStub{firing: true, operator: "or"},
|
||||
},
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
|
||||
handler.Eval(context)
|
||||
require.Equal(t, true, context.Firing)
|
||||
@@ -148,7 +148,7 @@ func TestAlertingEvaluationHandler(t *testing.T) {
|
||||
&conditionStub{firing: false, operator: "or"},
|
||||
&conditionStub{firing: false, operator: "or"},
|
||||
},
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
|
||||
handler.Eval(context)
|
||||
require.Equal(t, false, context.Firing)
|
||||
@@ -163,7 +163,7 @@ func TestAlertingEvaluationHandler(t *testing.T) {
|
||||
&conditionStub{operator: "or", noData: false},
|
||||
&conditionStub{operator: "or", noData: false},
|
||||
},
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
|
||||
handler.Eval(context)
|
||||
require.False(t, context.NoDataFound)
|
||||
@@ -174,7 +174,7 @@ func TestAlertingEvaluationHandler(t *testing.T) {
|
||||
Conditions: []Condition{
|
||||
&conditionStub{operator: "and", noData: true},
|
||||
},
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
|
||||
handler.Eval(context)
|
||||
require.Equal(t, false, context.Firing)
|
||||
@@ -187,7 +187,7 @@ func TestAlertingEvaluationHandler(t *testing.T) {
|
||||
&conditionStub{operator: "and", noData: true},
|
||||
&conditionStub{operator: "and", noData: false},
|
||||
},
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
|
||||
handler.Eval(context)
|
||||
require.True(t, context.NoDataFound)
|
||||
@@ -199,7 +199,7 @@ func TestAlertingEvaluationHandler(t *testing.T) {
|
||||
&conditionStub{operator: "or", noData: true},
|
||||
&conditionStub{operator: "or", noData: false},
|
||||
},
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
|
||||
handler.Eval(context)
|
||||
require.True(t, context.NoDataFound)
|
||||
|
||||
@@ -26,11 +26,11 @@ type DashAlertExtractorService struct {
|
||||
log log.Logger
|
||||
}
|
||||
|
||||
func ProvideDashAlertExtractorService(datasourcePermissionsService permissions.DatasourcePermissionsService, datasourceService datasources.DataSourceService, alertStore AlertStore) *DashAlertExtractorService {
|
||||
func ProvideDashAlertExtractorService(datasourcePermissionsService permissions.DatasourcePermissionsService, datasourceService datasources.DataSourceService, store AlertStore) *DashAlertExtractorService {
|
||||
return &DashAlertExtractorService{
|
||||
datasourcePermissionsService: datasourcePermissionsService,
|
||||
datasourceService: datasourceService,
|
||||
alertStore: alertStore,
|
||||
alertStore: store,
|
||||
log: log.New("alerting.extractor"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,7 +200,7 @@ func TestAlertRuleExtraction(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("Alert notifications are in DB", func(t *testing.T) {
|
||||
sqlStore := sqlstore.InitTestDB(t)
|
||||
sqlStore := sqlStore{db: sqlstore.InitTestDB(t)}
|
||||
|
||||
firstNotification := models.CreateAlertNotificationCommand{Uid: "notifier1", OrgId: 1, Name: "1"}
|
||||
err = sqlStore.CreateAlertNotificationCommand(context.Background(), &firstNotification)
|
||||
|
||||
@@ -20,18 +20,18 @@ import (
|
||||
func TestNotificationService(t *testing.T) {
|
||||
testRule := &Rule{Name: "Test", Message: "Something is bad"}
|
||||
store := &AlertStoreMock{}
|
||||
evalCtx := NewEvalContext(context.Background(), testRule, &validations.OSSPluginRequestValidator{}, store, nil)
|
||||
evalCtx := NewEvalContext(context.Background(), testRule, &validations.OSSPluginRequestValidator{}, store, nil, nil)
|
||||
|
||||
testRuleTemplated := &Rule{Name: "Test latency ${quantile}", Message: "Something is bad on instance ${instance}"}
|
||||
|
||||
evalCtxWithMatch := NewEvalContext(context.Background(), testRuleTemplated, &validations.OSSPluginRequestValidator{}, store, nil)
|
||||
evalCtxWithMatch := NewEvalContext(context.Background(), testRuleTemplated, &validations.OSSPluginRequestValidator{}, store, nil, nil)
|
||||
evalCtxWithMatch.EvalMatches = []*EvalMatch{{
|
||||
Tags: map[string]string{
|
||||
"instance": "localhost:3000",
|
||||
"quantile": "0.99",
|
||||
},
|
||||
}}
|
||||
evalCtxWithoutMatch := NewEvalContext(context.Background(), testRuleTemplated, &validations.OSSPluginRequestValidator{}, store, nil)
|
||||
evalCtxWithoutMatch := NewEvalContext(context.Background(), testRuleTemplated, &validations.OSSPluginRequestValidator{}, store, nil, nil)
|
||||
|
||||
notificationServiceScenario(t, "Given alert rule with upload image enabled should render and upload image and send notification",
|
||||
evalCtx, true, func(sc *scenarioContext) {
|
||||
|
||||
@@ -68,7 +68,7 @@ func TestWhenAlertManagerShouldNotify(t *testing.T) {
|
||||
am := &AlertmanagerNotifier{log: log.New("test.logger")}
|
||||
evalContext := alerting.NewEvalContext(context.Background(), &alerting.Rule{
|
||||
State: tc.prevState,
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
|
||||
evalContext.Rule.State = tc.newState
|
||||
|
||||
|
||||
@@ -170,7 +170,7 @@ func TestShouldSendAlertNotification(t *testing.T) {
|
||||
for _, tc := range tcs {
|
||||
evalContext := alerting.NewEvalContext(context.Background(), &alerting.Rule{
|
||||
State: tc.prevState,
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
|
||||
if tc.state == nil {
|
||||
tc.state = &models.AlertNotificationState{}
|
||||
|
||||
@@ -52,7 +52,7 @@ func TestDingDingNotifier(t *testing.T) {
|
||||
&alerting.Rule{
|
||||
State: models.AlertStateAlerting,
|
||||
Message: `{host="localhost"}`,
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
_, err = notifier.genBody(evalContext, "")
|
||||
require.Nil(t, err)
|
||||
})
|
||||
|
||||
@@ -105,7 +105,7 @@ func TestOpsGenieNotifier(t *testing.T) {
|
||||
Message: "someMessage",
|
||||
State: models.AlertStateAlerting,
|
||||
AlertRuleTags: tagPairs,
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
evalContext.IsTestRun = true
|
||||
|
||||
tags := make([]string, 0)
|
||||
@@ -154,7 +154,7 @@ func TestOpsGenieNotifier(t *testing.T) {
|
||||
Message: "someMessage",
|
||||
State: models.AlertStateAlerting,
|
||||
AlertRuleTags: tagPairs,
|
||||
}, nil, nil, nil)
|
||||
}, nil, nil, nil, nil)
|
||||
evalContext.IsTestRun = true
|
||||
|
||||
tags := make([]string, 0)
|
||||
@@ -203,7 +203,7 @@ func TestOpsGenieNotifier(t *testing.T) {
|
||||
Message: "someMessage",
|
||||
State: models.AlertStateAlerting,
|
||||
AlertRuleTags: tagPairs,
|
||||
}, nil, nil, nil)
|
||||
}, nil, nil, nil, nil)
|
||||
evalContext.IsTestRun = true
|
||||
|
||||
tags := make([]string, 0)
|
||||
|
||||
@@ -142,7 +142,7 @@ func TestPagerdutyNotifier(t *testing.T) {
|
||||
Name: "someRule",
|
||||
Message: "someMessage",
|
||||
State: models.AlertStateAlerting,
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
evalContext.IsTestRun = true
|
||||
|
||||
payloadJSON, err := pagerdutyNotifier.buildEventPayload(evalContext)
|
||||
@@ -198,7 +198,7 @@ func TestPagerdutyNotifier(t *testing.T) {
|
||||
ID: 0,
|
||||
Name: "someRule",
|
||||
State: models.AlertStateAlerting,
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
evalContext.IsTestRun = true
|
||||
|
||||
payloadJSON, err := pagerdutyNotifier.buildEventPayload(evalContext)
|
||||
@@ -256,7 +256,7 @@ func TestPagerdutyNotifier(t *testing.T) {
|
||||
Name: "someRule",
|
||||
Message: "someMessage",
|
||||
State: models.AlertStateAlerting,
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
evalContext.IsTestRun = true
|
||||
evalContext.EvalMatches = []*alerting.EvalMatch{
|
||||
{
|
||||
@@ -335,7 +335,7 @@ func TestPagerdutyNotifier(t *testing.T) {
|
||||
{Key: "severity", Value: "warning"},
|
||||
{Key: "dedup_key", Value: "key-" + strings.Repeat("x", 260)},
|
||||
},
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
evalContext.ImagePublicURL = "http://somewhere.com/omg_dont_panic.png"
|
||||
evalContext.IsTestRun = true
|
||||
|
||||
@@ -414,7 +414,7 @@ func TestPagerdutyNotifier(t *testing.T) {
|
||||
{Key: "component", Value: "aComponent"},
|
||||
{Key: "severity", Value: "info"},
|
||||
},
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
evalContext.ImagePublicURL = "http://somewhere.com/omg_dont_panic.png"
|
||||
evalContext.IsTestRun = true
|
||||
|
||||
@@ -493,7 +493,7 @@ func TestPagerdutyNotifier(t *testing.T) {
|
||||
{Key: "component", Value: "aComponent"},
|
||||
{Key: "severity", Value: "llama"},
|
||||
},
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
evalContext.ImagePublicURL = "http://somewhere.com/omg_dont_panic.png"
|
||||
evalContext.IsTestRun = true
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ func TestGenPushoverBody(t *testing.T) {
|
||||
evalContext := alerting.NewEvalContext(context.Background(),
|
||||
&alerting.Rule{
|
||||
State: models.AlertStateAlerting,
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
_, pushoverBody, err := notifier.genPushoverBody(evalContext, "", "")
|
||||
|
||||
require.Nil(t, err)
|
||||
@@ -87,7 +87,7 @@ func TestGenPushoverBody(t *testing.T) {
|
||||
evalContext := alerting.NewEvalContext(context.Background(),
|
||||
&alerting.Rule{
|
||||
State: models.AlertStateOK,
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
_, pushoverBody, err := notifier.genPushoverBody(evalContext, "", "")
|
||||
|
||||
require.Nil(t, err)
|
||||
|
||||
@@ -61,7 +61,7 @@ func TestTelegramNotifier(t *testing.T) {
|
||||
Name: "This is an alarm",
|
||||
Message: "Some kind of message.",
|
||||
State: models.AlertStateOK,
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
|
||||
caption := generateImageCaption(evalContext, "http://grafa.url/abcdef", "")
|
||||
require.LessOrEqual(t, len(caption), 1024)
|
||||
@@ -77,7 +77,7 @@ func TestTelegramNotifier(t *testing.T) {
|
||||
Name: "This is an alarm",
|
||||
Message: "Some kind of message.",
|
||||
State: models.AlertStateOK,
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
|
||||
caption := generateImageCaption(evalContext,
|
||||
"http://grafa.url/abcdefaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||
@@ -95,7 +95,7 @@ func TestTelegramNotifier(t *testing.T) {
|
||||
Name: "This is an alarm",
|
||||
Message: "Some kind of message that is too long for appending to our pretty little message, this line is actually exactly 197 chars long and I will get there in the end I promise I will. Yes siree that's it. But suddenly Telegram increased the length so now we need some lorem ipsum to fix this test. Here we go: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus consectetur molestie cursus. Donec suscipit egestas nisi. Proin ut efficitur ex. Mauris mi augue, volutpat a nisi vel, euismod dictum arcu. Sed quis tempor eros, sed malesuada dolor. Ut orci augue, viverra sit amet blandit quis, faucibus sit amet ex. Duis condimentum efficitur lectus, id dignissim quam tempor id. Morbi sollicitudin rhoncus diam, id tincidunt lectus scelerisque vitae. Etiam imperdiet semper sem, vel eleifend ligula mollis eget. Etiam ultrices fringilla lacus, sit amet pharetra ex blandit quis. Suspendisse in egestas neque, et posuere lectus. Vestibulum eu ex dui. Sed molestie nulla a lobortis scelerisque. Nulla ipsum ex, iaculis vitae vehicula sit amet, fermentum eu eros.",
|
||||
State: models.AlertStateOK,
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
|
||||
caption := generateImageCaption(evalContext,
|
||||
"http://grafa.url/foo",
|
||||
@@ -112,7 +112,7 @@ func TestTelegramNotifier(t *testing.T) {
|
||||
Name: "This is an alarm",
|
||||
Message: "Some kind of message that is too long for appending to our pretty little message, this line is actually exactly 197 chars long and I will get there in the end I promise I will. Yes siree that's it. But suddenly Telegram increased the length so now we need some lorem ipsum to fix this test. Here we go: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus consectetur molestie cursus. Donec suscipit egestas nisi. Proin ut efficitur ex. Mauris mi augue, volutpat a nisi vel, euismod dictum arcu. Sed quis tempor eros, sed malesuada dolor. Ut orci augue, viverra sit amet blandit quis, faucibus sit amet ex. Duis condimentum efficitur lectus, id dignissim quam tempor id. Morbi sollicitudin rhoncus diam, id tincidunt lectus scelerisque vitae. Etiam imperdiet semper sem, vel eleifend ligula mollis eget. Etiam ultrices fringilla lacus, sit amet pharetra ex blandit quis. Suspendisse in egestas neque, et posuere lectus. Vestibulum eu ex dui. Sed molestie nulla a lobortis sceleri",
|
||||
State: models.AlertStateOK,
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
|
||||
caption := generateImageCaption(evalContext,
|
||||
"http://grafa.url/foo",
|
||||
|
||||
@@ -93,7 +93,7 @@ func TestVictoropsNotifier(t *testing.T) {
|
||||
{Key: "keyOnly"},
|
||||
{Key: "severity", Value: "warning"},
|
||||
},
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
evalContext.IsTestRun = true
|
||||
|
||||
payload, err := victoropsNotifier.buildEventPayload(evalContext)
|
||||
@@ -141,7 +141,7 @@ func TestVictoropsNotifier(t *testing.T) {
|
||||
{Key: "keyOnly"},
|
||||
{Key: "severity", Value: "warning"},
|
||||
},
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil)
|
||||
}, &validations.OSSPluginRequestValidator{}, nil, nil, nil)
|
||||
evalContext.IsTestRun = true
|
||||
|
||||
payload, err := victoropsNotifier.buildEventPayload(evalContext)
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/localcache"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/tsdb/legacydata"
|
||||
@@ -84,7 +85,7 @@ func TestAlertRuleForParsing(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAlertRuleModel(t *testing.T) {
|
||||
sqlStore := sqlstore.InitTestDB(t)
|
||||
sqlStore := &sqlStore{db: sqlstore.InitTestDB(t), cache: localcache.New(time.Minute, time.Minute)}
|
||||
RegisterCondition("test", func(model *simplejson.Json, index int) (Condition, error) {
|
||||
return &FakeCondition{}, nil
|
||||
})
|
||||
|
||||
@@ -7,21 +7,21 @@ import (
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/encryption"
|
||||
"github.com/grafana/grafana/pkg/services/notifications"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/db"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
type AlertNotificationService struct {
|
||||
SQLStore *sqlstore.SQLStore
|
||||
SQLStore AlertNotificationStore
|
||||
EncryptionService encryption.Internal
|
||||
NotificationService *notifications.NotificationService
|
||||
}
|
||||
|
||||
func ProvideService(store *sqlstore.SQLStore, encryptionService encryption.Internal,
|
||||
func ProvideService(store db.DB, encryptionService encryption.Internal,
|
||||
notificationService *notifications.NotificationService) *AlertNotificationService {
|
||||
s := &AlertNotificationService{
|
||||
SQLStore: store,
|
||||
SQLStore: &sqlStore{db: store},
|
||||
EncryptionService: encryptionService,
|
||||
NotificationService: notificationService,
|
||||
}
|
||||
|
||||
@@ -4,8 +4,11 @@ import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/localcache"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/infra/usagestats"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
encryptionprovider "github.com/grafana/grafana/pkg/services/encryption/provider"
|
||||
@@ -17,7 +20,11 @@ import (
|
||||
)
|
||||
|
||||
func TestService(t *testing.T) {
|
||||
sqlStore := sqlstore.InitTestDB(t)
|
||||
sqlStore := &sqlStore{
|
||||
db: sqlstore.InitTestDB(t),
|
||||
log: &log.ConcreteLogger{},
|
||||
cache: localcache.New(time.Minute, time.Minute),
|
||||
}
|
||||
|
||||
nType := "test"
|
||||
registerTestNotifier(nType)
|
||||
@@ -30,7 +37,7 @@ func TestService(t *testing.T) {
|
||||
encService, err := encryptionservice.ProvideEncryptionService(encProvider, usMock, settings)
|
||||
require.NoError(t, err)
|
||||
|
||||
s := ProvideService(sqlStore, encService, nil)
|
||||
s := ProvideService(sqlStore.db, encService, nil)
|
||||
|
||||
origSecret := setting.SecretKey
|
||||
setting.SecretKey = "alert_notification_service_test"
|
||||
|
||||
@@ -1,20 +1,53 @@
|
||||
package sqlstore
|
||||
package alerting
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/localcache"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/db"
|
||||
)
|
||||
|
||||
// timeNow makes it possible to test usage of time
|
||||
var timeNow = time.Now
|
||||
// AlertStore is a subset of SQLStore API to satisfy the needs of the alerting service.
|
||||
// A subset is needed to make it easier to mock during the tests.
|
||||
type AlertStore interface {
|
||||
GetAlertById(context.Context, *models.GetAlertByIdQuery) error
|
||||
GetAllAlertQueryHandler(context.Context, *models.GetAllAlertsQuery) error
|
||||
GetAlertStatesForDashboard(context.Context, *models.GetAlertStatesForDashboardQuery) error
|
||||
HandleAlertsQuery(context.Context, *models.GetAlertsQuery) error
|
||||
SetAlertNotificationStateToCompleteCommand(context.Context, *models.SetAlertNotificationStateToCompleteCommand) error
|
||||
SetAlertNotificationStateToPendingCommand(context.Context, *models.SetAlertNotificationStateToPendingCommand) error
|
||||
GetAlertNotificationUidWithId(context.Context, *models.GetAlertNotificationUidQuery) error
|
||||
GetAlertNotificationsWithUidToSend(context.Context, *models.GetAlertNotificationsWithUidToSendQuery) error
|
||||
GetOrCreateAlertNotificationState(context.Context, *models.GetOrCreateNotificationStateQuery) error
|
||||
SetAlertState(context.Context, *models.SetAlertStateCommand) error
|
||||
PauseAlert(context.Context, *models.PauseAlertCommand) error
|
||||
PauseAllAlerts(context.Context, *models.PauseAllAlertCommand) error
|
||||
}
|
||||
|
||||
func (ss *SQLStore) GetAlertById(ctx context.Context, query *models.GetAlertByIdQuery) error {
|
||||
return ss.WithDbSession(ctx, func(sess *DBSession) error {
|
||||
type sqlStore struct {
|
||||
db db.DB
|
||||
cache *localcache.CacheService
|
||||
log *log.ConcreteLogger
|
||||
}
|
||||
|
||||
func ProvideAlertStore(
|
||||
db db.DB,
|
||||
cacheService *localcache.CacheService) AlertStore {
|
||||
return &sqlStore{
|
||||
db: db,
|
||||
cache: cacheService,
|
||||
log: log.New("alerting.store"),
|
||||
}
|
||||
}
|
||||
|
||||
func (ss *sqlStore) GetAlertById(ctx context.Context, query *models.GetAlertByIdQuery) error {
|
||||
return ss.db.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||
alert := models.Alert{}
|
||||
has, err := sess.ID(query.Id).Get(&alert)
|
||||
if !has {
|
||||
@@ -29,8 +62,8 @@ func (ss *SQLStore) GetAlertById(ctx context.Context, query *models.GetAlertById
|
||||
})
|
||||
}
|
||||
|
||||
func (ss *SQLStore) GetAllAlertQueryHandler(ctx context.Context, query *models.GetAllAlertsQuery) error {
|
||||
return ss.WithDbSession(ctx, func(sess *DBSession) error {
|
||||
func (ss *sqlStore) GetAllAlertQueryHandler(ctx context.Context, query *models.GetAllAlertsQuery) error {
|
||||
return ss.db.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||
var alerts []*models.Alert
|
||||
err := sess.SQL("select * from alert").Find(&alerts)
|
||||
if err != nil {
|
||||
@@ -42,8 +75,8 @@ func (ss *SQLStore) GetAllAlertQueryHandler(ctx context.Context, query *models.G
|
||||
})
|
||||
}
|
||||
|
||||
func deleteAlertByIdInternal(alertId int64, reason string, sess *DBSession) error {
|
||||
sqlog.Debug("Deleting alert", "id", alertId, "reason", reason)
|
||||
func deleteAlertByIdInternal(alertId int64, reason string, sess *sqlstore.DBSession, log *log.ConcreteLogger) error {
|
||||
log.Debug("Deleting alert", "id", alertId, "reason", reason)
|
||||
|
||||
if _, err := sess.Exec("DELETE FROM alert WHERE id = ?", alertId); err != nil {
|
||||
return err
|
||||
@@ -64,9 +97,9 @@ func deleteAlertByIdInternal(alertId int64, reason string, sess *DBSession) erro
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ss *SQLStore) HandleAlertsQuery(ctx context.Context, query *models.GetAlertsQuery) error {
|
||||
return ss.WithDbSession(ctx, func(sess *DBSession) error {
|
||||
builder := SQLBuilder{}
|
||||
func (ss *sqlStore) HandleAlertsQuery(ctx context.Context, query *models.GetAlertsQuery) error {
|
||||
return ss.db.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||
builder := sqlstore.SQLBuilder{}
|
||||
|
||||
builder.Write(`SELECT
|
||||
alert.id,
|
||||
@@ -86,11 +119,11 @@ func (ss *SQLStore) HandleAlertsQuery(ctx context.Context, query *models.GetAler
|
||||
builder.Write(`WHERE alert.org_id = ?`, query.OrgId)
|
||||
|
||||
if len(strings.TrimSpace(query.Query)) > 0 {
|
||||
builder.Write(" AND alert.name "+dialect.LikeStr()+" ?", "%"+query.Query+"%")
|
||||
builder.Write(" AND alert.name "+ss.db.GetDialect().LikeStr()+" ?", "%"+query.Query+"%")
|
||||
}
|
||||
|
||||
if len(query.DashboardIDs) > 0 {
|
||||
builder.sql.WriteString(` AND alert.dashboard_id IN (?` + strings.Repeat(",?", len(query.DashboardIDs)-1) + `) `)
|
||||
builder.Write(` AND alert.dashboard_id IN (?` + strings.Repeat(",?", len(query.DashboardIDs)-1) + `) `)
|
||||
|
||||
for _, dbID := range query.DashboardIDs {
|
||||
builder.AddParams(dbID)
|
||||
@@ -125,11 +158,11 @@ func (ss *SQLStore) HandleAlertsQuery(ctx context.Context, query *models.GetAler
|
||||
builder.Write(" ORDER BY name ASC")
|
||||
|
||||
if query.Limit != 0 {
|
||||
builder.Write(dialect.Limit(query.Limit))
|
||||
builder.Write(ss.db.GetDialect().Limit(query.Limit))
|
||||
}
|
||||
|
||||
alerts := make([]*models.AlertListItemDTO, 0)
|
||||
if err := sess.SQL(builder.GetSQLString(), builder.params...).Find(&alerts); err != nil {
|
||||
if err := sess.SQL(builder.GetSQLString(), builder.GetParams()...).Find(&alerts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -144,18 +177,18 @@ func (ss *SQLStore) HandleAlertsQuery(ctx context.Context, query *models.GetAler
|
||||
})
|
||||
}
|
||||
|
||||
func (ss *SQLStore) SaveAlerts(ctx context.Context, dashID int64, alerts []*models.Alert) error {
|
||||
return ss.WithTransactionalDbSession(ctx, func(sess *DBSession) error {
|
||||
func (ss *sqlStore) SaveAlerts(ctx context.Context, dashID int64, alerts []*models.Alert) error {
|
||||
return ss.db.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||
existingAlerts, err := GetAlertsByDashboardId2(dashID, sess)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := updateAlerts(existingAlerts, alerts, sess); err != nil {
|
||||
if err := updateAlerts(existingAlerts, alerts, sess, ss.log); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := deleteMissingAlerts(existingAlerts, alerts, sess); err != nil {
|
||||
if err := deleteMissingAlerts(existingAlerts, alerts, sess, ss.log); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -163,7 +196,7 @@ func (ss *SQLStore) SaveAlerts(ctx context.Context, dashID int64, alerts []*mode
|
||||
})
|
||||
}
|
||||
|
||||
func updateAlerts(existingAlerts []*models.Alert, alerts []*models.Alert, sess *DBSession) error {
|
||||
func updateAlerts(existingAlerts []*models.Alert, alerts []*models.Alert, sess *sqlstore.DBSession, log *log.ConcreteLogger) error {
|
||||
for _, alert := range alerts {
|
||||
update := false
|
||||
var alertToUpdate *models.Alert
|
||||
@@ -188,7 +221,7 @@ func updateAlerts(existingAlerts []*models.Alert, alerts []*models.Alert, sess *
|
||||
return err
|
||||
}
|
||||
|
||||
sqlog.Debug("Alert updated", "name", alert.Name, "id", alert.Id)
|
||||
log.Debug("Alert updated", "name", alert.Name, "id", alert.Id)
|
||||
}
|
||||
} else {
|
||||
alert.Updated = timeNow()
|
||||
@@ -201,14 +234,14 @@ func updateAlerts(existingAlerts []*models.Alert, alerts []*models.Alert, sess *
|
||||
return err
|
||||
}
|
||||
|
||||
sqlog.Debug("Alert inserted", "name", alert.Name, "id", alert.Id)
|
||||
log.Debug("Alert inserted", "name", alert.Name, "id", alert.Id)
|
||||
}
|
||||
tags := alert.GetTagsFromSettings()
|
||||
if _, err := sess.Exec("DELETE FROM alert_rule_tag WHERE alert_id = ?", alert.Id); err != nil {
|
||||
return err
|
||||
}
|
||||
if tags != nil {
|
||||
tags, err := EnsureTagsExist(sess, tags)
|
||||
tags, err := sqlstore.EnsureTagsExist(sess, tags)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -223,7 +256,7 @@ func updateAlerts(existingAlerts []*models.Alert, alerts []*models.Alert, sess *
|
||||
return nil
|
||||
}
|
||||
|
||||
func deleteMissingAlerts(alerts []*models.Alert, existingAlerts []*models.Alert, sess *DBSession) error {
|
||||
func deleteMissingAlerts(alerts []*models.Alert, existingAlerts []*models.Alert, sess *sqlstore.DBSession, log *log.ConcreteLogger) error {
|
||||
for _, missingAlert := range alerts {
|
||||
missing := true
|
||||
|
||||
@@ -235,7 +268,7 @@ func deleteMissingAlerts(alerts []*models.Alert, existingAlerts []*models.Alert,
|
||||
}
|
||||
|
||||
if missing {
|
||||
if err := deleteAlertByIdInternal(missingAlert.Id, "Removed from dashboard", sess); err != nil {
|
||||
if err := deleteAlertByIdInternal(missingAlert.Id, "Removed from dashboard", sess, log); err != nil {
|
||||
// No use trying to delete more, since we're in a transaction and it will be
|
||||
// rolled back on error.
|
||||
return err
|
||||
@@ -246,7 +279,7 @@ func deleteMissingAlerts(alerts []*models.Alert, existingAlerts []*models.Alert,
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetAlertsByDashboardId2(dashboardId int64, sess *DBSession) ([]*models.Alert, error) {
|
||||
func GetAlertsByDashboardId2(dashboardId int64, sess *sqlstore.DBSession) ([]*models.Alert, error) {
|
||||
alerts := make([]*models.Alert, 0)
|
||||
err := sess.Where("dashboard_id = ?", dashboardId).Find(&alerts)
|
||||
|
||||
@@ -257,8 +290,8 @@ func GetAlertsByDashboardId2(dashboardId int64, sess *DBSession) ([]*models.Aler
|
||||
return alerts, nil
|
||||
}
|
||||
|
||||
func (ss *SQLStore) SetAlertState(ctx context.Context, cmd *models.SetAlertStateCommand) error {
|
||||
return ss.WithTransactionalDbSession(ctx, func(sess *DBSession) error {
|
||||
func (ss *sqlStore) SetAlertState(ctx context.Context, cmd *models.SetAlertStateCommand) error {
|
||||
return ss.db.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||
alert := models.Alert{}
|
||||
|
||||
if has, err := sess.ID(cmd.AlertId).Get(&alert); err != nil {
|
||||
@@ -296,8 +329,8 @@ func (ss *SQLStore) SetAlertState(ctx context.Context, cmd *models.SetAlertState
|
||||
})
|
||||
}
|
||||
|
||||
func (ss *SQLStore) PauseAlert(ctx context.Context, cmd *models.PauseAlertCommand) error {
|
||||
return ss.WithTransactionalDbSession(ctx, func(sess *DBSession) error {
|
||||
func (ss *sqlStore) PauseAlert(ctx context.Context, cmd *models.PauseAlertCommand) error {
|
||||
return ss.db.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||
if len(cmd.AlertIds) == 0 {
|
||||
return fmt.Errorf("command contains no alertids")
|
||||
}
|
||||
@@ -330,8 +363,8 @@ func (ss *SQLStore) PauseAlert(ctx context.Context, cmd *models.PauseAlertComman
|
||||
})
|
||||
}
|
||||
|
||||
func (ss *SQLStore) PauseAllAlerts(ctx context.Context, cmd *models.PauseAllAlertCommand) error {
|
||||
return ss.WithTransactionalDbSession(ctx, func(sess *DBSession) error {
|
||||
func (ss *sqlStore) PauseAllAlerts(ctx context.Context, cmd *models.PauseAllAlertCommand) error {
|
||||
return ss.db.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||
var newState string
|
||||
if cmd.Paused {
|
||||
newState = string(models.AlertStatePaused)
|
||||
@@ -348,8 +381,8 @@ func (ss *SQLStore) PauseAllAlerts(ctx context.Context, cmd *models.PauseAllAler
|
||||
})
|
||||
}
|
||||
|
||||
func (ss *SQLStore) GetAlertStatesForDashboard(ctx context.Context, query *models.GetAlertStatesForDashboardQuery) error {
|
||||
return ss.WithDbSession(ctx, func(sess *DBSession) error {
|
||||
func (ss *sqlStore) GetAlertStatesForDashboard(ctx context.Context, query *models.GetAlertStatesForDashboardQuery) error {
|
||||
return ss.db.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||
var rawSQL = `SELECT
|
||||
id,
|
||||
dashboard_id,
|
||||
+41
-37
@@ -1,4 +1,4 @@
|
||||
package sqlstore
|
||||
package alerting
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
@@ -28,8 +29,11 @@ type AlertNotificationStore interface {
|
||||
GetOrCreateAlertNotificationState(ctx context.Context, cmd *models.GetOrCreateNotificationStateQuery) error
|
||||
}
|
||||
|
||||
func (ss *SQLStore) DeleteAlertNotification(ctx context.Context, cmd *models.DeleteAlertNotificationCommand) error {
|
||||
return ss.WithTransactionalDbSession(ctx, func(sess *DBSession) error {
|
||||
// timeNow makes it possible to test usage of time
|
||||
var timeNow = time.Now
|
||||
|
||||
func (ss *sqlStore) DeleteAlertNotification(ctx context.Context, cmd *models.DeleteAlertNotificationCommand) error {
|
||||
return ss.db.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||
sql := "DELETE FROM alert_notification WHERE alert_notification.org_id = ? AND alert_notification.id = ?"
|
||||
res, err := sess.Exec(sql, cmd.OrgId, cmd.Id)
|
||||
if err != nil {
|
||||
@@ -52,9 +56,9 @@ func (ss *SQLStore) DeleteAlertNotification(ctx context.Context, cmd *models.Del
|
||||
})
|
||||
}
|
||||
|
||||
func (ss *SQLStore) DeleteAlertNotificationWithUid(ctx context.Context, cmd *models.DeleteAlertNotificationWithUidCommand) error {
|
||||
func (ss *sqlStore) DeleteAlertNotificationWithUid(ctx context.Context, cmd *models.DeleteAlertNotificationWithUidCommand) error {
|
||||
existingNotification := &models.GetAlertNotificationsWithUidQuery{OrgId: cmd.OrgId, Uid: cmd.Uid}
|
||||
if err := getAlertNotificationWithUidInternal(ctx, existingNotification, ss.newSession(ctx)); err != nil {
|
||||
if err := getAlertNotificationWithUidInternal(ctx, existingNotification, ss.db.NewSession(ctx)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -74,24 +78,24 @@ func (ss *SQLStore) DeleteAlertNotificationWithUid(ctx context.Context, cmd *mod
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ss *SQLStore) GetAlertNotifications(ctx context.Context, query *models.GetAlertNotificationsQuery) error {
|
||||
return getAlertNotificationInternal(ctx, query, ss.newSession(ctx))
|
||||
func (ss *sqlStore) GetAlertNotifications(ctx context.Context, query *models.GetAlertNotificationsQuery) error {
|
||||
return getAlertNotificationInternal(ctx, query, ss.db.NewSession(ctx))
|
||||
}
|
||||
|
||||
func (ss *SQLStore) GetAlertNotificationUidWithId(ctx context.Context, query *models.GetAlertNotificationUidQuery) error {
|
||||
func (ss *sqlStore) GetAlertNotificationUidWithId(ctx context.Context, query *models.GetAlertNotificationUidQuery) error {
|
||||
cacheKey := newAlertNotificationUidCacheKey(query.OrgId, query.Id)
|
||||
|
||||
if cached, found := ss.CacheService.Get(cacheKey); found {
|
||||
if cached, found := ss.cache.Get(cacheKey); found {
|
||||
query.Result = cached.(string)
|
||||
return nil
|
||||
}
|
||||
|
||||
err := getAlertNotificationUidInternal(ctx, query, ss.newSession(ctx))
|
||||
err := getAlertNotificationUidInternal(ctx, query, ss.db.NewSession(ctx))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ss.CacheService.Set(cacheKey, query.Result, -1) // Infinite, never changes
|
||||
ss.cache.Set(cacheKey, query.Result, -1) // Infinite, never changes
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -100,12 +104,12 @@ func newAlertNotificationUidCacheKey(orgID, notificationId int64) string {
|
||||
return fmt.Sprintf("notification-uid-by-org-%d-and-id-%d", orgID, notificationId)
|
||||
}
|
||||
|
||||
func (ss *SQLStore) GetAlertNotificationsWithUid(ctx context.Context, query *models.GetAlertNotificationsWithUidQuery) error {
|
||||
return getAlertNotificationWithUidInternal(ctx, query, ss.newSession(ctx))
|
||||
func (ss *sqlStore) GetAlertNotificationsWithUid(ctx context.Context, query *models.GetAlertNotificationsWithUidQuery) error {
|
||||
return getAlertNotificationWithUidInternal(ctx, query, ss.db.NewSession(ctx))
|
||||
}
|
||||
|
||||
func (ss *SQLStore) GetAllAlertNotifications(ctx context.Context, query *models.GetAllAlertNotificationsQuery) error {
|
||||
return ss.WithDbSession(ctx, func(sess *DBSession) error {
|
||||
func (ss *sqlStore) GetAllAlertNotifications(ctx context.Context, query *models.GetAllAlertNotificationsQuery) error {
|
||||
return ss.db.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||
results := make([]*models.AlertNotification, 0)
|
||||
if err := sess.Where("org_id = ?", query.OrgId).Asc("name").Find(&results); err != nil {
|
||||
return err
|
||||
@@ -116,8 +120,8 @@ func (ss *SQLStore) GetAllAlertNotifications(ctx context.Context, query *models.
|
||||
})
|
||||
}
|
||||
|
||||
func (ss *SQLStore) GetAlertNotificationsWithUidToSend(ctx context.Context, query *models.GetAlertNotificationsWithUidToSendQuery) error {
|
||||
return ss.WithDbSession(ctx, func(sess *DBSession) error {
|
||||
func (ss *sqlStore) GetAlertNotificationsWithUidToSend(ctx context.Context, query *models.GetAlertNotificationsWithUidToSendQuery) error {
|
||||
return ss.db.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||
var sql bytes.Buffer
|
||||
params := make([]interface{}, 0)
|
||||
|
||||
@@ -142,7 +146,7 @@ func (ss *SQLStore) GetAlertNotificationsWithUidToSend(ctx context.Context, quer
|
||||
params = append(params, query.OrgId)
|
||||
|
||||
sql.WriteString(` AND ((alert_notification.is_default = ?)`)
|
||||
params = append(params, dialect.BooleanStr(true))
|
||||
params = append(params, ss.db.GetDialect().BooleanStr(true))
|
||||
|
||||
if len(query.Uids) > 0 {
|
||||
sql.WriteString(` OR alert_notification.uid IN (?` + strings.Repeat(",?", len(query.Uids)-1) + ")")
|
||||
@@ -162,7 +166,7 @@ func (ss *SQLStore) GetAlertNotificationsWithUidToSend(ctx context.Context, quer
|
||||
})
|
||||
}
|
||||
|
||||
func getAlertNotificationUidInternal(ctx context.Context, query *models.GetAlertNotificationUidQuery, sess *DBSession) error {
|
||||
func getAlertNotificationUidInternal(ctx context.Context, query *models.GetAlertNotificationUidQuery, sess *sqlstore.DBSession) error {
|
||||
var sql bytes.Buffer
|
||||
params := make([]interface{}, 0)
|
||||
|
||||
@@ -191,7 +195,7 @@ func getAlertNotificationUidInternal(ctx context.Context, query *models.GetAlert
|
||||
return nil
|
||||
}
|
||||
|
||||
func getAlertNotificationInternal(ctx context.Context, query *models.GetAlertNotificationsQuery, sess *DBSession) error {
|
||||
func getAlertNotificationInternal(ctx context.Context, query *models.GetAlertNotificationsQuery, sess *sqlstore.DBSession) error {
|
||||
var sql bytes.Buffer
|
||||
params := make([]interface{}, 0)
|
||||
|
||||
@@ -241,7 +245,7 @@ func getAlertNotificationInternal(ctx context.Context, query *models.GetAlertNot
|
||||
return nil
|
||||
}
|
||||
|
||||
func getAlertNotificationWithUidInternal(ctx context.Context, query *models.GetAlertNotificationsWithUidQuery, sess *DBSession) error {
|
||||
func getAlertNotificationWithUidInternal(ctx context.Context, query *models.GetAlertNotificationsWithUidQuery, sess *sqlstore.DBSession) error {
|
||||
var sql bytes.Buffer
|
||||
params := make([]interface{}, 0)
|
||||
|
||||
@@ -279,8 +283,8 @@ func getAlertNotificationWithUidInternal(ctx context.Context, query *models.GetA
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ss *SQLStore) CreateAlertNotificationCommand(ctx context.Context, cmd *models.CreateAlertNotificationCommand) error {
|
||||
return ss.WithTransactionalDbSession(ctx, func(sess *DBSession) error {
|
||||
func (ss *sqlStore) CreateAlertNotificationCommand(ctx context.Context, cmd *models.CreateAlertNotificationCommand) error {
|
||||
return ss.db.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||
if cmd.Uid == "" {
|
||||
uid, uidGenerationErr := generateNewAlertNotificationUid(ctx, sess, cmd.OrgId)
|
||||
if uidGenerationErr != nil {
|
||||
@@ -353,7 +357,7 @@ func (ss *SQLStore) CreateAlertNotificationCommand(ctx context.Context, cmd *mod
|
||||
})
|
||||
}
|
||||
|
||||
func generateNewAlertNotificationUid(ctx context.Context, sess *DBSession, orgId int64) (string, error) {
|
||||
func generateNewAlertNotificationUid(ctx context.Context, sess *sqlstore.DBSession, orgId int64) (string, error) {
|
||||
for i := 0; i < 3; i++ {
|
||||
uid := util.GenerateShortUID()
|
||||
exists, err := sess.Where("org_id=? AND uid=?", orgId, uid).Get(&models.AlertNotification{})
|
||||
@@ -369,8 +373,8 @@ func generateNewAlertNotificationUid(ctx context.Context, sess *DBSession, orgId
|
||||
return "", models.ErrAlertNotificationFailedGenerateUniqueUid
|
||||
}
|
||||
|
||||
func (ss *SQLStore) UpdateAlertNotification(ctx context.Context, cmd *models.UpdateAlertNotificationCommand) error {
|
||||
return ss.WithTransactionalDbSession(ctx, func(sess *DBSession) (err error) {
|
||||
func (ss *sqlStore) UpdateAlertNotification(ctx context.Context, cmd *models.UpdateAlertNotificationCommand) error {
|
||||
return ss.db.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) (err error) {
|
||||
current := models.AlertNotification{}
|
||||
|
||||
if _, err = sess.ID(cmd.Id).Get(¤t); err != nil {
|
||||
@@ -437,10 +441,10 @@ func (ss *SQLStore) UpdateAlertNotification(ctx context.Context, cmd *models.Upd
|
||||
})
|
||||
}
|
||||
|
||||
func (ss *SQLStore) UpdateAlertNotificationWithUid(ctx context.Context, cmd *models.UpdateAlertNotificationWithUidCommand) error {
|
||||
func (ss *sqlStore) UpdateAlertNotificationWithUid(ctx context.Context, cmd *models.UpdateAlertNotificationWithUidCommand) error {
|
||||
getAlertNotificationWithUidQuery := &models.GetAlertNotificationsWithUidQuery{OrgId: cmd.OrgId, Uid: cmd.Uid}
|
||||
|
||||
if err := getAlertNotificationWithUidInternal(ctx, getAlertNotificationWithUidQuery, ss.newSession(ctx)); err != nil {
|
||||
if err := getAlertNotificationWithUidInternal(ctx, getAlertNotificationWithUidQuery, ss.db.NewSession(ctx)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -478,8 +482,8 @@ func (ss *SQLStore) UpdateAlertNotificationWithUid(ctx context.Context, cmd *mod
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ss *SQLStore) SetAlertNotificationStateToCompleteCommand(ctx context.Context, cmd *models.SetAlertNotificationStateToCompleteCommand) error {
|
||||
return ss.WithTransactionalDbSession(ctx, func(sess *DBSession) error {
|
||||
func (ss *sqlStore) SetAlertNotificationStateToCompleteCommand(ctx context.Context, cmd *models.SetAlertNotificationStateToCompleteCommand) error {
|
||||
return ss.db.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||
version := cmd.Version
|
||||
var current models.AlertNotificationState
|
||||
if _, err := sess.ID(cmd.Id).Get(¤t); err != nil {
|
||||
@@ -500,15 +504,15 @@ func (ss *SQLStore) SetAlertNotificationStateToCompleteCommand(ctx context.Conte
|
||||
}
|
||||
|
||||
if current.Version != version {
|
||||
sqlog.Error("notification state out of sync. the notification is marked as complete but has been modified between set as pending and completion.", "notifierId", current.NotifierId)
|
||||
ss.log.Error("notification state out of sync. the notification is marked as complete but has been modified between set as pending and completion.", "notifierId", current.NotifierId)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (ss *SQLStore) SetAlertNotificationStateToPendingCommand(ctx context.Context, cmd *models.SetAlertNotificationStateToPendingCommand) error {
|
||||
return ss.WithDbSession(ctx, func(sess *DBSession) error {
|
||||
func (ss *sqlStore) SetAlertNotificationStateToPendingCommand(ctx context.Context, cmd *models.SetAlertNotificationStateToPendingCommand) error {
|
||||
return ss.db.WithDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||
newVersion := cmd.Version + 1
|
||||
sql := `UPDATE alert_notification_state SET
|
||||
state = ?,
|
||||
@@ -543,8 +547,8 @@ func (ss *SQLStore) SetAlertNotificationStateToPendingCommand(ctx context.Contex
|
||||
})
|
||||
}
|
||||
|
||||
func (ss *SQLStore) GetOrCreateAlertNotificationState(ctx context.Context, cmd *models.GetOrCreateNotificationStateQuery) error {
|
||||
return ss.WithTransactionalDbSession(ctx, func(sess *DBSession) error {
|
||||
func (ss *sqlStore) GetOrCreateAlertNotificationState(ctx context.Context, cmd *models.GetOrCreateNotificationStateQuery) error {
|
||||
return ss.db.WithTransactionalDbSession(ctx, func(sess *sqlstore.DBSession) error {
|
||||
nj := &models.AlertNotificationState{}
|
||||
|
||||
exist, err := getAlertNotificationState(ctx, sess, cmd, nj)
|
||||
@@ -568,7 +572,7 @@ func (ss *SQLStore) GetOrCreateAlertNotificationState(ctx context.Context, cmd *
|
||||
}
|
||||
|
||||
if _, err := sess.Insert(notificationState); err != nil {
|
||||
if dialect.IsUniqueConstraintViolation(err) {
|
||||
if ss.db.GetDialect().IsUniqueConstraintViolation(err) {
|
||||
exist, err = getAlertNotificationState(ctx, sess, cmd, nj)
|
||||
|
||||
if err != nil {
|
||||
@@ -591,7 +595,7 @@ func (ss *SQLStore) GetOrCreateAlertNotificationState(ctx context.Context, cmd *
|
||||
})
|
||||
}
|
||||
|
||||
func getAlertNotificationState(ctx context.Context, sess *DBSession, cmd *models.GetOrCreateNotificationStateQuery, nj *models.AlertNotificationState) (bool, error) {
|
||||
func getAlertNotificationState(ctx context.Context, sess *sqlstore.DBSession, cmd *models.GetOrCreateNotificationStateQuery, nj *models.AlertNotificationState) (bool, error) {
|
||||
return sess.
|
||||
Where("alert_notification_state.org_id = ?", cmd.OrgId).
|
||||
Where("alert_notification_state.alert_id = ?", cmd.AlertId).
|
||||
+58
-51
@@ -1,4 +1,4 @@
|
||||
package sqlstore
|
||||
package alerting
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -8,7 +8,10 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/localcache"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@@ -17,8 +20,13 @@ func TestIntegrationAlertNotificationSQLAccess(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping integration test")
|
||||
}
|
||||
var sqlStore *SQLStore
|
||||
setup := func() { sqlStore = InitTestDB(t) }
|
||||
var store *sqlStore
|
||||
setup := func() {
|
||||
store = &sqlStore{
|
||||
db: sqlstore.InitTestDB(t),
|
||||
log: log.New(),
|
||||
cache: localcache.New(time.Minute, time.Minute)}
|
||||
}
|
||||
|
||||
t.Run("Alert notification state", func(t *testing.T) {
|
||||
setup()
|
||||
@@ -33,7 +41,7 @@ func TestIntegrationAlertNotificationSQLAccess(t *testing.T) {
|
||||
|
||||
t.Run("Get no existing state should create a new state", func(t *testing.T) {
|
||||
query := &models.GetOrCreateNotificationStateQuery{AlertId: alertID, OrgId: orgID, NotifierId: notifierID}
|
||||
err := sqlStore.GetOrCreateAlertNotificationState(context.Background(), query)
|
||||
err := store.GetOrCreateAlertNotificationState(context.Background(), query)
|
||||
require.Nil(t, err)
|
||||
require.NotNil(t, query.Result)
|
||||
require.Equal(t, models.AlertNotificationStateUnknown, query.Result.State)
|
||||
@@ -42,7 +50,7 @@ func TestIntegrationAlertNotificationSQLAccess(t *testing.T) {
|
||||
|
||||
t.Run("Get existing state should not create a new state", func(t *testing.T) {
|
||||
query2 := &models.GetOrCreateNotificationStateQuery{AlertId: alertID, OrgId: orgID, NotifierId: notifierID}
|
||||
err := sqlStore.GetOrCreateAlertNotificationState(context.Background(), query2)
|
||||
err := store.GetOrCreateAlertNotificationState(context.Background(), query2)
|
||||
require.Nil(t, err)
|
||||
require.NotNil(t, query2.Result)
|
||||
require.Equal(t, query.Result.Id, query2.Result.Id)
|
||||
@@ -58,12 +66,12 @@ func TestIntegrationAlertNotificationSQLAccess(t *testing.T) {
|
||||
AlertRuleStateUpdatedVersion: s.AlertRuleStateUpdatedVersion,
|
||||
}
|
||||
|
||||
err := sqlStore.SetAlertNotificationStateToPendingCommand(context.Background(), &cmd)
|
||||
err := store.SetAlertNotificationStateToPendingCommand(context.Background(), &cmd)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, int64(1), cmd.ResultVersion)
|
||||
|
||||
query2 := &models.GetOrCreateNotificationStateQuery{AlertId: alertID, OrgId: orgID, NotifierId: notifierID}
|
||||
err = sqlStore.GetOrCreateAlertNotificationState(context.Background(), query2)
|
||||
err = store.GetOrCreateAlertNotificationState(context.Background(), query2)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, int64(1), query2.Result.Version)
|
||||
require.Equal(t, models.AlertNotificationStatePending, query2.Result.State)
|
||||
@@ -75,11 +83,11 @@ func TestIntegrationAlertNotificationSQLAccess(t *testing.T) {
|
||||
Id: s.Id,
|
||||
Version: cmd.ResultVersion,
|
||||
}
|
||||
err := sqlStore.SetAlertNotificationStateToCompleteCommand(context.Background(), &setStateCmd)
|
||||
err := store.SetAlertNotificationStateToCompleteCommand(context.Background(), &setStateCmd)
|
||||
require.Nil(t, err)
|
||||
|
||||
query3 := &models.GetOrCreateNotificationStateQuery{AlertId: alertID, OrgId: orgID, NotifierId: notifierID}
|
||||
err = sqlStore.GetOrCreateAlertNotificationState(context.Background(), query3)
|
||||
err = store.GetOrCreateAlertNotificationState(context.Background(), query3)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, int64(2), query3.Result.Version)
|
||||
require.Equal(t, models.AlertNotificationStateCompleted, query3.Result.State)
|
||||
@@ -93,11 +101,11 @@ func TestIntegrationAlertNotificationSQLAccess(t *testing.T) {
|
||||
Id: s.Id,
|
||||
Version: unknownVersion,
|
||||
}
|
||||
err := sqlStore.SetAlertNotificationStateToCompleteCommand(context.Background(), &cmd)
|
||||
err := store.SetAlertNotificationStateToCompleteCommand(context.Background(), &cmd)
|
||||
require.Nil(t, err)
|
||||
|
||||
query3 := &models.GetOrCreateNotificationStateQuery{AlertId: alertID, OrgId: orgID, NotifierId: notifierID}
|
||||
err = sqlStore.GetOrCreateAlertNotificationState(context.Background(), query3)
|
||||
err = store.GetOrCreateAlertNotificationState(context.Background(), query3)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, unknownVersion+1, query3.Result.Version)
|
||||
require.Equal(t, models.AlertNotificationStateCompleted, query3.Result.State)
|
||||
@@ -113,7 +121,7 @@ func TestIntegrationAlertNotificationSQLAccess(t *testing.T) {
|
||||
Version: s.Version,
|
||||
AlertRuleStateUpdatedVersion: s.AlertRuleStateUpdatedVersion,
|
||||
}
|
||||
err := sqlStore.SetAlertNotificationStateToPendingCommand(context.Background(), &cmd)
|
||||
err := store.SetAlertNotificationStateToPendingCommand(context.Background(), &cmd)
|
||||
require.Equal(t, models.ErrAlertNotificationStateVersionConflict, err)
|
||||
})
|
||||
|
||||
@@ -124,7 +132,7 @@ func TestIntegrationAlertNotificationSQLAccess(t *testing.T) {
|
||||
Version: s.Version,
|
||||
AlertRuleStateUpdatedVersion: 1000,
|
||||
}
|
||||
err := sqlStore.SetAlertNotificationStateToPendingCommand(context.Background(), &cmd)
|
||||
err := store.SetAlertNotificationStateToPendingCommand(context.Background(), &cmd)
|
||||
require.Nil(t, err)
|
||||
|
||||
require.Equal(t, int64(1), cmd.ResultVersion)
|
||||
@@ -138,7 +146,7 @@ func TestIntegrationAlertNotificationSQLAccess(t *testing.T) {
|
||||
Version: s.Version,
|
||||
AlertRuleStateUpdatedVersion: s.AlertRuleStateUpdatedVersion,
|
||||
}
|
||||
err := sqlStore.SetAlertNotificationStateToPendingCommand(context.Background(), &cmd)
|
||||
err := store.SetAlertNotificationStateToPendingCommand(context.Background(), &cmd)
|
||||
require.Error(t, err)
|
||||
})
|
||||
})
|
||||
@@ -151,7 +159,7 @@ func TestIntegrationAlertNotificationSQLAccess(t *testing.T) {
|
||||
Name: "email",
|
||||
}
|
||||
|
||||
err := sqlStore.GetAlertNotifications(context.Background(), cmd)
|
||||
err := store.GetAlertNotifications(context.Background(), cmd)
|
||||
require.Nil(t, err)
|
||||
require.Nil(t, cmd.Result)
|
||||
})
|
||||
@@ -167,13 +175,13 @@ func TestIntegrationAlertNotificationSQLAccess(t *testing.T) {
|
||||
}
|
||||
|
||||
t.Run("and missing frequency", func(t *testing.T) {
|
||||
err := sqlStore.CreateAlertNotificationCommand(context.Background(), cmd)
|
||||
err := store.CreateAlertNotificationCommand(context.Background(), cmd)
|
||||
require.Equal(t, models.ErrNotificationFrequencyNotFound, err)
|
||||
})
|
||||
|
||||
t.Run("invalid frequency", func(t *testing.T) {
|
||||
cmd.Frequency = "invalid duration"
|
||||
err := sqlStore.CreateAlertNotificationCommand(context.Background(), cmd)
|
||||
err := store.CreateAlertNotificationCommand(context.Background(), cmd)
|
||||
require.True(t, regexp.MustCompile(`^time: invalid duration "?invalid duration"?$`).MatchString(
|
||||
err.Error()))
|
||||
})
|
||||
@@ -189,7 +197,7 @@ func TestIntegrationAlertNotificationSQLAccess(t *testing.T) {
|
||||
Settings: simplejson.New(),
|
||||
}
|
||||
|
||||
err := sqlStore.CreateAlertNotificationCommand(context.Background(), cmd)
|
||||
err := store.CreateAlertNotificationCommand(context.Background(), cmd)
|
||||
require.Nil(t, err)
|
||||
|
||||
updateCmd := &models.UpdateAlertNotificationCommand{
|
||||
@@ -198,14 +206,14 @@ func TestIntegrationAlertNotificationSQLAccess(t *testing.T) {
|
||||
}
|
||||
|
||||
t.Run("and missing frequency", func(t *testing.T) {
|
||||
err := sqlStore.UpdateAlertNotification(context.Background(), updateCmd)
|
||||
err := store.UpdateAlertNotification(context.Background(), updateCmd)
|
||||
require.Equal(t, models.ErrNotificationFrequencyNotFound, err)
|
||||
})
|
||||
|
||||
t.Run("invalid frequency", func(t *testing.T) {
|
||||
updateCmd.Frequency = "invalid duration"
|
||||
|
||||
err := sqlStore.UpdateAlertNotification(context.Background(), updateCmd)
|
||||
err := store.UpdateAlertNotification(context.Background(), updateCmd)
|
||||
require.Error(t, err)
|
||||
require.True(t, regexp.MustCompile(`^time: invalid duration "?invalid duration"?$`).MatchString(
|
||||
err.Error()))
|
||||
@@ -223,7 +231,7 @@ func TestIntegrationAlertNotificationSQLAccess(t *testing.T) {
|
||||
Settings: simplejson.New(),
|
||||
}
|
||||
|
||||
err := sqlStore.CreateAlertNotificationCommand(context.Background(), cmd)
|
||||
err := store.CreateAlertNotificationCommand(context.Background(), cmd)
|
||||
require.Nil(t, err)
|
||||
require.NotEqual(t, 0, cmd.Result.Id)
|
||||
require.NotEqual(t, 0, cmd.Result.OrgId)
|
||||
@@ -233,7 +241,7 @@ func TestIntegrationAlertNotificationSQLAccess(t *testing.T) {
|
||||
require.NotEmpty(t, cmd.Result.Uid)
|
||||
|
||||
t.Run("Cannot save Alert Notification with the same name", func(t *testing.T) {
|
||||
err = sqlStore.CreateAlertNotificationCommand(context.Background(), cmd)
|
||||
err = store.CreateAlertNotificationCommand(context.Background(), cmd)
|
||||
require.Error(t, err)
|
||||
})
|
||||
t.Run("Cannot save Alert Notification with the same name and another uid", func(t *testing.T) {
|
||||
@@ -246,7 +254,7 @@ func TestIntegrationAlertNotificationSQLAccess(t *testing.T) {
|
||||
Settings: cmd.Settings,
|
||||
Uid: "notifier1",
|
||||
}
|
||||
err = sqlStore.CreateAlertNotificationCommand(context.Background(), anotherUidCmd)
|
||||
err = store.CreateAlertNotificationCommand(context.Background(), anotherUidCmd)
|
||||
require.Error(t, err)
|
||||
})
|
||||
t.Run("Can save Alert Notification with another name and another uid", func(t *testing.T) {
|
||||
@@ -259,7 +267,7 @@ func TestIntegrationAlertNotificationSQLAccess(t *testing.T) {
|
||||
Settings: cmd.Settings,
|
||||
Uid: "notifier2",
|
||||
}
|
||||
err = sqlStore.CreateAlertNotificationCommand(context.Background(), anotherUidCmd)
|
||||
err = store.CreateAlertNotificationCommand(context.Background(), anotherUidCmd)
|
||||
require.Nil(t, err)
|
||||
})
|
||||
|
||||
@@ -274,7 +282,7 @@ func TestIntegrationAlertNotificationSQLAccess(t *testing.T) {
|
||||
Settings: simplejson.New(),
|
||||
Id: cmd.Result.Id,
|
||||
}
|
||||
err := sqlStore.UpdateAlertNotification(context.Background(), newCmd)
|
||||
err := store.UpdateAlertNotification(context.Background(), newCmd)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, "NewName", newCmd.Result.Name)
|
||||
require.Equal(t, 60*time.Second, newCmd.Result.Frequency)
|
||||
@@ -290,7 +298,7 @@ func TestIntegrationAlertNotificationSQLAccess(t *testing.T) {
|
||||
Settings: simplejson.New(),
|
||||
Id: cmd.Result.Id,
|
||||
}
|
||||
err := sqlStore.UpdateAlertNotification(context.Background(), newCmd)
|
||||
err := store.UpdateAlertNotification(context.Background(), newCmd)
|
||||
require.Nil(t, err)
|
||||
require.False(t, newCmd.Result.SendReminder)
|
||||
})
|
||||
@@ -305,11 +313,11 @@ func TestIntegrationAlertNotificationSQLAccess(t *testing.T) {
|
||||
|
||||
otherOrg := models.CreateAlertNotificationCommand{Name: "default", Type: "email", OrgId: 2, SendReminder: true, Frequency: "10s", Settings: simplejson.New()}
|
||||
|
||||
require.Nil(t, sqlStore.CreateAlertNotificationCommand(context.Background(), &cmd1))
|
||||
require.Nil(t, sqlStore.CreateAlertNotificationCommand(context.Background(), &cmd2))
|
||||
require.Nil(t, sqlStore.CreateAlertNotificationCommand(context.Background(), &cmd3))
|
||||
require.Nil(t, sqlStore.CreateAlertNotificationCommand(context.Background(), &cmd4))
|
||||
require.Nil(t, sqlStore.CreateAlertNotificationCommand(context.Background(), &otherOrg))
|
||||
require.Nil(t, store.CreateAlertNotificationCommand(context.Background(), &cmd1))
|
||||
require.Nil(t, store.CreateAlertNotificationCommand(context.Background(), &cmd2))
|
||||
require.Nil(t, store.CreateAlertNotificationCommand(context.Background(), &cmd3))
|
||||
require.Nil(t, store.CreateAlertNotificationCommand(context.Background(), &cmd4))
|
||||
require.Nil(t, store.CreateAlertNotificationCommand(context.Background(), &otherOrg))
|
||||
|
||||
t.Run("search", func(t *testing.T) {
|
||||
query := &models.GetAlertNotificationsWithUidToSendQuery{
|
||||
@@ -317,7 +325,7 @@ func TestIntegrationAlertNotificationSQLAccess(t *testing.T) {
|
||||
OrgId: 1,
|
||||
}
|
||||
|
||||
err := sqlStore.GetAlertNotificationsWithUidToSend(context.Background(), query)
|
||||
err := store.GetAlertNotificationsWithUidToSend(context.Background(), query)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, 3, len(query.Result))
|
||||
})
|
||||
@@ -327,7 +335,7 @@ func TestIntegrationAlertNotificationSQLAccess(t *testing.T) {
|
||||
OrgId: 1,
|
||||
}
|
||||
|
||||
err := sqlStore.GetAllAlertNotifications(context.Background(), query)
|
||||
err := store.GetAllAlertNotifications(context.Background(), query)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, 4, len(query.Result))
|
||||
require.Equal(t, cmd4.Name, query.Result[0].Name)
|
||||
@@ -339,10 +347,9 @@ func TestIntegrationAlertNotificationSQLAccess(t *testing.T) {
|
||||
|
||||
t.Run("Notification Uid by Id Caching", func(t *testing.T) {
|
||||
setup()
|
||||
ss := InitTestDB(t)
|
||||
|
||||
notification := &models.CreateAlertNotificationCommand{Uid: "aNotificationUid", OrgId: 1, Name: "aNotificationUid"}
|
||||
err := sqlStore.CreateAlertNotificationCommand(context.Background(), notification)
|
||||
err := store.CreateAlertNotificationCommand(context.Background(), notification)
|
||||
require.Nil(t, err)
|
||||
|
||||
byUidQuery := &models.GetAlertNotificationsWithUidQuery{
|
||||
@@ -350,7 +357,7 @@ func TestIntegrationAlertNotificationSQLAccess(t *testing.T) {
|
||||
OrgId: notification.OrgId,
|
||||
}
|
||||
|
||||
notificationByUidErr := sqlStore.GetAlertNotificationsWithUid(context.Background(), byUidQuery)
|
||||
notificationByUidErr := store.GetAlertNotificationsWithUid(context.Background(), byUidQuery)
|
||||
require.Nil(t, notificationByUidErr)
|
||||
|
||||
t.Run("Can cache notification Uid", func(t *testing.T) {
|
||||
@@ -361,14 +368,14 @@ func TestIntegrationAlertNotificationSQLAccess(t *testing.T) {
|
||||
|
||||
cacheKey := newAlertNotificationUidCacheKey(byIdQuery.OrgId, byIdQuery.Id)
|
||||
|
||||
resultBeforeCaching, foundBeforeCaching := ss.CacheService.Get(cacheKey)
|
||||
resultBeforeCaching, foundBeforeCaching := store.cache.Get(cacheKey)
|
||||
require.False(t, foundBeforeCaching)
|
||||
require.Nil(t, resultBeforeCaching)
|
||||
|
||||
notificationByIdErr := ss.GetAlertNotificationUidWithId(context.Background(), byIdQuery)
|
||||
notificationByIdErr := store.GetAlertNotificationUidWithId(context.Background(), byIdQuery)
|
||||
require.Nil(t, notificationByIdErr)
|
||||
|
||||
resultAfterCaching, foundAfterCaching := ss.CacheService.Get(cacheKey)
|
||||
resultAfterCaching, foundAfterCaching := store.cache.Get(cacheKey)
|
||||
require.True(t, foundAfterCaching)
|
||||
require.Equal(t, notification.Uid, resultAfterCaching)
|
||||
})
|
||||
@@ -379,9 +386,9 @@ func TestIntegrationAlertNotificationSQLAccess(t *testing.T) {
|
||||
OrgId: 100,
|
||||
}
|
||||
cacheKey := newAlertNotificationUidCacheKey(query.OrgId, query.Id)
|
||||
ss.CacheService.Set(cacheKey, "a-cached-uid", -1)
|
||||
store.cache.Set(cacheKey, "a-cached-uid", -1)
|
||||
|
||||
err := ss.GetAlertNotificationUidWithId(context.Background(), query)
|
||||
err := store.GetAlertNotificationUidWithId(context.Background(), query)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, "a-cached-uid", query.Result)
|
||||
})
|
||||
@@ -392,13 +399,13 @@ func TestIntegrationAlertNotificationSQLAccess(t *testing.T) {
|
||||
OrgId: 100,
|
||||
}
|
||||
|
||||
err := ss.GetAlertNotificationUidWithId(context.Background(), query)
|
||||
err := store.GetAlertNotificationUidWithId(context.Background(), query)
|
||||
require.Equal(t, "", query.Result)
|
||||
require.Error(t, err)
|
||||
require.True(t, errors.Is(err, models.ErrAlertNotificationFailedTranslateUniqueID))
|
||||
|
||||
cacheKey := newAlertNotificationUidCacheKey(query.OrgId, query.Id)
|
||||
result, found := ss.CacheService.Get(cacheKey)
|
||||
result, found := store.cache.Get(cacheKey)
|
||||
require.False(t, found)
|
||||
require.Nil(t, result)
|
||||
})
|
||||
@@ -416,7 +423,7 @@ func TestIntegrationAlertNotificationSQLAccess(t *testing.T) {
|
||||
Settings: simplejson.New(),
|
||||
Id: 1,
|
||||
}
|
||||
err := sqlStore.UpdateAlertNotification(context.Background(), updateCmd)
|
||||
err := store.UpdateAlertNotification(context.Background(), updateCmd)
|
||||
require.Equal(t, models.ErrAlertNotificationNotFound, err)
|
||||
|
||||
t.Run("using UID", func(t *testing.T) {
|
||||
@@ -431,7 +438,7 @@ func TestIntegrationAlertNotificationSQLAccess(t *testing.T) {
|
||||
Uid: "uid",
|
||||
NewUid: "newUid",
|
||||
}
|
||||
err := sqlStore.UpdateAlertNotificationWithUid(context.Background(), updateWithUidCmd)
|
||||
err := store.UpdateAlertNotificationWithUid(context.Background(), updateWithUidCmd)
|
||||
require.Equal(t, models.ErrAlertNotificationNotFound, err)
|
||||
})
|
||||
})
|
||||
@@ -446,18 +453,18 @@ func TestIntegrationAlertNotificationSQLAccess(t *testing.T) {
|
||||
Settings: simplejson.New(),
|
||||
}
|
||||
|
||||
err := sqlStore.CreateAlertNotificationCommand(context.Background(), cmd)
|
||||
err := store.CreateAlertNotificationCommand(context.Background(), cmd)
|
||||
require.Nil(t, err)
|
||||
|
||||
deleteCmd := &models.DeleteAlertNotificationCommand{
|
||||
Id: cmd.Result.Id,
|
||||
OrgId: 1,
|
||||
}
|
||||
err = sqlStore.DeleteAlertNotification(context.Background(), deleteCmd)
|
||||
err = store.DeleteAlertNotification(context.Background(), deleteCmd)
|
||||
require.Nil(t, err)
|
||||
|
||||
t.Run("using UID", func(t *testing.T) {
|
||||
err := sqlStore.CreateAlertNotificationCommand(context.Background(), cmd)
|
||||
err := store.CreateAlertNotificationCommand(context.Background(), cmd)
|
||||
require.Nil(t, err)
|
||||
|
||||
deleteWithUidCmd := &models.DeleteAlertNotificationWithUidCommand{
|
||||
@@ -465,7 +472,7 @@ func TestIntegrationAlertNotificationSQLAccess(t *testing.T) {
|
||||
OrgId: 1,
|
||||
}
|
||||
|
||||
err = sqlStore.DeleteAlertNotificationWithUid(context.Background(), deleteWithUidCmd)
|
||||
err = store.DeleteAlertNotificationWithUid(context.Background(), deleteWithUidCmd)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, cmd.Result.Id, deleteWithUidCmd.DeletedAlertNotificationId)
|
||||
})
|
||||
@@ -477,7 +484,7 @@ func TestIntegrationAlertNotificationSQLAccess(t *testing.T) {
|
||||
Id: 1,
|
||||
OrgId: 1,
|
||||
}
|
||||
err := sqlStore.DeleteAlertNotification(context.Background(), deleteCmd)
|
||||
err := store.DeleteAlertNotification(context.Background(), deleteCmd)
|
||||
require.Equal(t, models.ErrAlertNotificationNotFound, err)
|
||||
|
||||
t.Run("using UID", func(t *testing.T) {
|
||||
@@ -485,7 +492,7 @@ func TestIntegrationAlertNotificationSQLAccess(t *testing.T) {
|
||||
Uid: "uid",
|
||||
OrgId: 1,
|
||||
}
|
||||
err = sqlStore.DeleteAlertNotificationWithUid(context.Background(), deleteWithUidCmd)
|
||||
err = store.DeleteAlertNotificationWithUid(context.Background(), deleteWithUidCmd)
|
||||
require.Equal(t, models.ErrAlertNotificationNotFound, err)
|
||||
})
|
||||
})
|
||||
@@ -1,4 +1,4 @@
|
||||
package sqlstore
|
||||
package alerting
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -6,7 +6,13 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
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/util"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@@ -32,14 +38,17 @@ func TestIntegrationAlertingDataAccess(t *testing.T) {
|
||||
mockTimeNow()
|
||||
defer resetTimeNow()
|
||||
|
||||
var sqlStore *SQLStore
|
||||
var store *sqlStore
|
||||
var testDash *models.Dashboard
|
||||
var items []*models.Alert
|
||||
|
||||
setup := func(t *testing.T) {
|
||||
sqlStore = InitTestDB(t)
|
||||
store = &sqlStore{
|
||||
db: sqlstore.InitTestDB(t),
|
||||
log: log.New(),
|
||||
}
|
||||
|
||||
testDash = insertTestDashboard(t, sqlStore, "dashboard with alerts", 1, 0, false, "alert")
|
||||
testDash = insertTestDashboard(t, store.db, "dashboard with alerts", 1, 0, false, "alert")
|
||||
evalData, err := simplejson.NewJson([]byte(`{"test": "test"}`))
|
||||
require.Nil(t, err)
|
||||
items = []*models.Alert{
|
||||
@@ -55,7 +64,7 @@ func TestIntegrationAlertingDataAccess(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
err = sqlStore.SaveAlerts(context.Background(), testDash.Id, items)
|
||||
err = store.SaveAlerts(context.Background(), testDash.Id, items)
|
||||
require.Nil(t, err)
|
||||
}
|
||||
|
||||
@@ -64,7 +73,7 @@ func TestIntegrationAlertingDataAccess(t *testing.T) {
|
||||
|
||||
// Get alert so we can use its ID in tests
|
||||
alertQuery := models.GetAlertsQuery{DashboardIDs: []int64{testDash.Id}, PanelId: 1, OrgId: 1, User: &models.SignedInUser{OrgRole: models.ROLE_ADMIN}}
|
||||
err2 := sqlStore.HandleAlertsQuery(context.Background(), &alertQuery)
|
||||
err2 := store.HandleAlertsQuery(context.Background(), &alertQuery)
|
||||
require.Nil(t, err2)
|
||||
|
||||
insertedAlert := alertQuery.Result[0]
|
||||
@@ -75,15 +84,15 @@ func TestIntegrationAlertingDataAccess(t *testing.T) {
|
||||
State: models.AlertStateOK,
|
||||
}
|
||||
|
||||
err := sqlStore.SetAlertState(context.Background(), cmd)
|
||||
err := store.SetAlertState(context.Background(), cmd)
|
||||
require.Nil(t, err)
|
||||
})
|
||||
|
||||
alert, _ := getAlertById(t, insertedAlert.Id, sqlStore)
|
||||
alert, _ := getAlertById(t, insertedAlert.Id, store)
|
||||
stateDateBeforePause := alert.NewStateDate
|
||||
|
||||
t.Run("can pause all alerts", func(t *testing.T) {
|
||||
err := sqlStore.pauseAllAlerts(t, true)
|
||||
err := store.pauseAllAlerts(t, true)
|
||||
require.Nil(t, err)
|
||||
|
||||
t.Run("cannot updated paused alert", func(t *testing.T) {
|
||||
@@ -92,26 +101,26 @@ func TestIntegrationAlertingDataAccess(t *testing.T) {
|
||||
State: models.AlertStateOK,
|
||||
}
|
||||
|
||||
err = sqlStore.SetAlertState(context.Background(), cmd)
|
||||
err = store.SetAlertState(context.Background(), cmd)
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("alert is paused", func(t *testing.T) {
|
||||
alert, _ = getAlertById(t, insertedAlert.Id, sqlStore)
|
||||
alert, _ = getAlertById(t, insertedAlert.Id, store)
|
||||
currentState := alert.State
|
||||
require.Equal(t, models.AlertStatePaused, currentState)
|
||||
})
|
||||
|
||||
t.Run("pausing alerts should update their NewStateDate", func(t *testing.T) {
|
||||
alert, _ = getAlertById(t, insertedAlert.Id, sqlStore)
|
||||
alert, _ = getAlertById(t, insertedAlert.Id, store)
|
||||
stateDateAfterPause := alert.NewStateDate
|
||||
require.True(t, stateDateBeforePause.Before(stateDateAfterPause))
|
||||
})
|
||||
|
||||
t.Run("unpausing alerts should update their NewStateDate again", func(t *testing.T) {
|
||||
err := sqlStore.pauseAllAlerts(t, false)
|
||||
err := store.pauseAllAlerts(t, false)
|
||||
require.Nil(t, err)
|
||||
alert, _ = getAlertById(t, insertedAlert.Id, sqlStore)
|
||||
alert, _ = getAlertById(t, insertedAlert.Id, store)
|
||||
stateDateAfterUnpause := alert.NewStateDate
|
||||
require.True(t, stateDateBeforePause.Before(stateDateAfterUnpause))
|
||||
})
|
||||
@@ -121,7 +130,7 @@ func TestIntegrationAlertingDataAccess(t *testing.T) {
|
||||
t.Run("Can read properties", func(t *testing.T) {
|
||||
setup(t)
|
||||
alertQuery := models.GetAlertsQuery{DashboardIDs: []int64{testDash.Id}, PanelId: 1, OrgId: 1, User: &models.SignedInUser{OrgRole: models.ROLE_ADMIN}}
|
||||
err2 := sqlStore.HandleAlertsQuery(context.Background(), &alertQuery)
|
||||
err2 := store.HandleAlertsQuery(context.Background(), &alertQuery)
|
||||
|
||||
alert := alertQuery.Result[0]
|
||||
require.Nil(t, err2)
|
||||
@@ -143,7 +152,7 @@ func TestIntegrationAlertingDataAccess(t *testing.T) {
|
||||
setup(t)
|
||||
viewerUser := &models.SignedInUser{OrgRole: models.ROLE_VIEWER, OrgId: 1}
|
||||
alertQuery := models.GetAlertsQuery{DashboardIDs: []int64{testDash.Id}, PanelId: 1, OrgId: 1, User: viewerUser}
|
||||
err2 := sqlStore.HandleAlertsQuery(context.Background(), &alertQuery)
|
||||
err2 := store.HandleAlertsQuery(context.Background(), &alertQuery)
|
||||
|
||||
require.Nil(t, err2)
|
||||
require.Equal(t, 1, len(alertQuery.Result))
|
||||
@@ -154,7 +163,7 @@ func TestIntegrationAlertingDataAccess(t *testing.T) {
|
||||
modifiedItems := items
|
||||
modifiedItems[0].Name = "Name"
|
||||
|
||||
err := sqlStore.SaveAlerts(context.Background(), testDash.Id, items)
|
||||
err := store.SaveAlerts(context.Background(), testDash.Id, items)
|
||||
|
||||
t.Run("Can save alerts with same dashboard and panel id", func(t *testing.T) {
|
||||
require.Nil(t, err)
|
||||
@@ -162,7 +171,7 @@ func TestIntegrationAlertingDataAccess(t *testing.T) {
|
||||
|
||||
t.Run("Alerts should be updated", func(t *testing.T) {
|
||||
query := models.GetAlertsQuery{DashboardIDs: []int64{testDash.Id}, OrgId: 1, User: &models.SignedInUser{OrgRole: models.ROLE_ADMIN}}
|
||||
err2 := sqlStore.HandleAlertsQuery(context.Background(), &query)
|
||||
err2 := store.HandleAlertsQuery(context.Background(), &query)
|
||||
|
||||
require.Nil(t, err2)
|
||||
require.Equal(t, 1, len(query.Result))
|
||||
@@ -174,7 +183,7 @@ func TestIntegrationAlertingDataAccess(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("Updates without changes should be ignored", func(t *testing.T) {
|
||||
err3 := sqlStore.SaveAlerts(context.Background(), testDash.Id, items)
|
||||
err3 := store.SaveAlerts(context.Background(), testDash.Id, items)
|
||||
require.Nil(t, err3)
|
||||
})
|
||||
})
|
||||
@@ -205,13 +214,13 @@ func TestIntegrationAlertingDataAccess(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
err := sqlStore.SaveAlerts(context.Background(), testDash.Id, multipleItems)
|
||||
err := store.SaveAlerts(context.Background(), testDash.Id, multipleItems)
|
||||
|
||||
t.Run("Should save 3 dashboards", func(t *testing.T) {
|
||||
require.Nil(t, err)
|
||||
|
||||
queryForDashboard := models.GetAlertsQuery{DashboardIDs: []int64{testDash.Id}, OrgId: 1, User: &models.SignedInUser{OrgRole: models.ROLE_ADMIN}}
|
||||
err2 := sqlStore.HandleAlertsQuery(context.Background(), &queryForDashboard)
|
||||
err2 := store.HandleAlertsQuery(context.Background(), &queryForDashboard)
|
||||
|
||||
require.Nil(t, err2)
|
||||
require.Equal(t, 3, len(queryForDashboard.Result))
|
||||
@@ -220,11 +229,11 @@ func TestIntegrationAlertingDataAccess(t *testing.T) {
|
||||
t.Run("should updated two dashboards and delete one", func(t *testing.T) {
|
||||
missingOneAlert := multipleItems[:2]
|
||||
|
||||
err = sqlStore.SaveAlerts(context.Background(), testDash.Id, missingOneAlert)
|
||||
err = store.SaveAlerts(context.Background(), testDash.Id, missingOneAlert)
|
||||
|
||||
t.Run("should delete the missing alert", func(t *testing.T) {
|
||||
query := models.GetAlertsQuery{DashboardIDs: []int64{testDash.Id}, OrgId: 1, User: &models.SignedInUser{OrgRole: models.ROLE_ADMIN}}
|
||||
err2 := sqlStore.HandleAlertsQuery(context.Background(), &query)
|
||||
err2 := store.HandleAlertsQuery(context.Background(), &query)
|
||||
require.Nil(t, err2)
|
||||
require.Equal(t, 2, len(query.Result))
|
||||
})
|
||||
@@ -242,10 +251,10 @@ func TestIntegrationAlertingDataAccess(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
err := sqlStore.SaveAlerts(context.Background(), testDash.Id, items)
|
||||
err := store.SaveAlerts(context.Background(), testDash.Id, items)
|
||||
require.Nil(t, err)
|
||||
|
||||
err = sqlStore.WithDbSession(context.Background(), func(sess *DBSession) error {
|
||||
err = store.db.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
|
||||
dash := models.Dashboard{Id: testDash.Id, OrgId: 1}
|
||||
_, err := sess.Delete(dash)
|
||||
return err
|
||||
@@ -254,7 +263,7 @@ func TestIntegrationAlertingDataAccess(t *testing.T) {
|
||||
|
||||
t.Run("Alerts should be removed", func(t *testing.T) {
|
||||
query := models.GetAlertsQuery{DashboardIDs: []int64{testDash.Id}, OrgId: 1, User: &models.SignedInUser{OrgRole: models.ROLE_ADMIN}}
|
||||
err2 := sqlStore.HandleAlertsQuery(context.Background(), &query)
|
||||
err2 := store.HandleAlertsQuery(context.Background(), &query)
|
||||
|
||||
require.Nil(t, err2)
|
||||
require.Equal(t, 0, len(query.Result))
|
||||
@@ -270,9 +279,9 @@ func TestIntegrationPausingAlerts(t *testing.T) {
|
||||
defer resetTimeNow()
|
||||
|
||||
t.Run("Given an alert", func(t *testing.T) {
|
||||
sqlStore := InitTestDB(t)
|
||||
sqlStore := sqlStore{db: sqlstore.InitTestDB(t), log: log.New()}
|
||||
|
||||
testDash := insertTestDashboard(t, sqlStore, "dashboard with alerts", 1, 0, false, "alert")
|
||||
testDash := insertTestDashboard(t, sqlStore.db, "dashboard with alerts", 1, 0, false, "alert")
|
||||
alert, err := insertTestAlert("Alerting title", "Alerting message", testDash.OrgId, testDash.Id, simplejson.New(), sqlStore)
|
||||
require.Nil(t, err)
|
||||
|
||||
@@ -291,7 +300,7 @@ func TestIntegrationPausingAlerts(t *testing.T) {
|
||||
require.Nil(t, err)
|
||||
|
||||
t.Run("the NewStateDate should be updated", func(t *testing.T) {
|
||||
alert, err := getAlertById(t, insertedAlert.Id, sqlStore)
|
||||
alert, err := getAlertById(t, insertedAlert.Id, &sqlStore)
|
||||
require.Nil(t, err)
|
||||
|
||||
stateDateAfterPause = alert.NewStateDate
|
||||
@@ -304,7 +313,7 @@ func TestIntegrationPausingAlerts(t *testing.T) {
|
||||
require.Nil(t, err)
|
||||
|
||||
t.Run("the NewStateDate should be updated again", func(t *testing.T) {
|
||||
alert, err := getAlertById(t, insertedAlert.Id, sqlStore)
|
||||
alert, err := getAlertById(t, insertedAlert.Id, &sqlStore)
|
||||
require.Nil(t, err)
|
||||
|
||||
stateDateAfterUnpause := alert.NewStateDate
|
||||
@@ -313,7 +322,8 @@ func TestIntegrationPausingAlerts(t *testing.T) {
|
||||
})
|
||||
})
|
||||
}
|
||||
func (ss *SQLStore) pauseAlert(t *testing.T, orgId int64, alertId int64, pauseState bool) (int64, error) {
|
||||
|
||||
func (ss *sqlStore) pauseAlert(t *testing.T, orgId int64, alertId int64, pauseState bool) (int64, error) {
|
||||
cmd := &models.PauseAlertCommand{
|
||||
OrgId: orgId,
|
||||
AlertIds: []int64{alertId},
|
||||
@@ -323,7 +333,8 @@ func (ss *SQLStore) pauseAlert(t *testing.T, orgId int64, alertId int64, pauseSt
|
||||
require.Nil(t, err)
|
||||
return cmd.ResultCount, err
|
||||
}
|
||||
func insertTestAlert(title string, message string, orgId int64, dashId int64, settings *simplejson.Json, ss *SQLStore) (*models.Alert, error) {
|
||||
|
||||
func insertTestAlert(title string, message string, orgId int64, dashId int64, settings *simplejson.Json, ss sqlStore) (*models.Alert, error) {
|
||||
items := []*models.Alert{
|
||||
{
|
||||
PanelId: 1,
|
||||
@@ -340,7 +351,7 @@ func insertTestAlert(title string, message string, orgId int64, dashId int64, se
|
||||
return items[0], err
|
||||
}
|
||||
|
||||
func getAlertById(t *testing.T, id int64, ss *SQLStore) (*models.Alert, error) {
|
||||
func getAlertById(t *testing.T, id int64, ss *sqlStore) (*models.Alert, error) {
|
||||
q := &models.GetAlertByIdQuery{
|
||||
Id: id,
|
||||
}
|
||||
@@ -349,7 +360,7 @@ func getAlertById(t *testing.T, id int64, ss *SQLStore) (*models.Alert, error) {
|
||||
return q.Result, err
|
||||
}
|
||||
|
||||
func (ss *SQLStore) pauseAllAlerts(t *testing.T, pauseState bool) error {
|
||||
func (ss *sqlStore) pauseAllAlerts(t *testing.T, pauseState bool) error {
|
||||
cmd := &models.PauseAllAlertCommand{
|
||||
Paused: pauseState,
|
||||
}
|
||||
@@ -357,3 +368,59 @@ func (ss *SQLStore) pauseAllAlerts(t *testing.T, pauseState bool) error {
|
||||
require.Nil(t, err)
|
||||
return err
|
||||
}
|
||||
|
||||
func insertTestDashboard(t *testing.T, db db.DB, title string, orgId int64,
|
||||
folderId int64, isFolder bool, tags ...interface{}) *models.Dashboard {
|
||||
t.Helper()
|
||||
cmd := models.SaveDashboardCommand{
|
||||
OrgId: orgId,
|
||||
FolderId: folderId,
|
||||
IsFolder: isFolder,
|
||||
Dashboard: simplejson.NewFromAny(map[string]interface{}{
|
||||
"id": nil,
|
||||
"title": title,
|
||||
"tags": tags,
|
||||
}),
|
||||
}
|
||||
|
||||
var dash *models.Dashboard
|
||||
err := db.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
|
||||
dash = cmd.GetDashboardModel()
|
||||
dash.SetVersion(1)
|
||||
dash.Created = time.Now()
|
||||
dash.Updated = time.Now()
|
||||
dash.Uid = util.GenerateShortUID()
|
||||
_, err := sess.Insert(dash)
|
||||
return err
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, dash)
|
||||
dash.Data.Set("id", dash.Id)
|
||||
dash.Data.Set("uid", dash.Uid)
|
||||
|
||||
err = db.WithDbSession(context.Background(), func(sess *sqlstore.DBSession) error {
|
||||
dashVersion := &dashver.DashboardVersion{
|
||||
DashboardID: dash.Id,
|
||||
ParentVersion: dash.Version,
|
||||
RestoredFrom: cmd.RestoredFrom,
|
||||
Version: dash.Version,
|
||||
Created: time.Now(),
|
||||
CreatedBy: dash.UpdatedBy,
|
||||
Message: cmd.Message,
|
||||
Data: dash.Data,
|
||||
}
|
||||
require.NoError(t, err)
|
||||
|
||||
if affectedRows, err := sess.Insert(dashVersion); err != nil {
|
||||
return err
|
||||
} else if affectedRows == 0 {
|
||||
return dashboards.ErrDashboardNotFound
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
return dash
|
||||
}
|
||||
@@ -57,7 +57,7 @@ func createTestEvalContext(cmd *NotificationTestCommand) *EvalContext {
|
||||
ID: rand.Int63(),
|
||||
}
|
||||
|
||||
ctx := NewEvalContext(context.Background(), testRule, fakeRequestValidator{}, nil, nil)
|
||||
ctx := NewEvalContext(context.Background(), testRule, fakeRequestValidator{}, nil, nil, nil)
|
||||
if cmd.Settings.Get("uploadImage").MustBool(true) {
|
||||
ctx.ImagePublicURL = "https://grafana.com/assets/img/blog/mixed_styles.png"
|
||||
}
|
||||
|
||||
@@ -25,14 +25,14 @@ func (e *AlertEngine) AlertTest(orgID int64, dashboard *simplejson.Json, panelID
|
||||
if alert.PanelId != panelID {
|
||||
continue
|
||||
}
|
||||
rule, err := NewRuleFromDBAlert(context.Background(), e.sqlStore, alert, true)
|
||||
rule, err := NewRuleFromDBAlert(context.Background(), e.AlertStore, alert, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
handler := NewEvalHandler(e.DataService)
|
||||
|
||||
context := NewEvalContext(context.Background(), rule, fakeRequestValidator{}, e.sqlStore, nil)
|
||||
context := NewEvalContext(context.Background(), rule, fakeRequestValidator{}, e.AlertStore, nil, e.datasourceService)
|
||||
context.IsTestRun = true
|
||||
context.IsDebug = true
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/alerting"
|
||||
"github.com/grafana/grafana/pkg/services/alerting/notifiers"
|
||||
encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service"
|
||||
"github.com/grafana/grafana/pkg/services/notifications"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -31,6 +32,7 @@ var (
|
||||
|
||||
func TestNotificationAsConfig(t *testing.T) {
|
||||
var sqlStore *sqlstore.SQLStore
|
||||
var ns *alerting.AlertNotificationService
|
||||
logger := log.New("fake.log")
|
||||
|
||||
encryptionService := encryptionservice.SetupTestService(t)
|
||||
@@ -38,6 +40,8 @@ func TestNotificationAsConfig(t *testing.T) {
|
||||
t.Run("Testing notification as configuration", func(t *testing.T) {
|
||||
setup := func() {
|
||||
sqlStore = sqlstore.InitTestDB(t)
|
||||
nm := ¬ifications.NotificationService{}
|
||||
ns = alerting.ProvideService(sqlStore, encryptionService, nm)
|
||||
|
||||
for i := 1; i < 5; i++ {
|
||||
orgCommand := models.CreateOrgCommand{Name: fmt.Sprintf("Main Org. %v", i)}
|
||||
@@ -158,11 +162,11 @@ func TestNotificationAsConfig(t *testing.T) {
|
||||
Uid: "notifier1",
|
||||
Type: "slack",
|
||||
}
|
||||
err := sqlStore.CreateAlertNotificationCommand(context.Background(), &existingNotificationCmd)
|
||||
err := ns.SQLStore.CreateAlertNotificationCommand(context.Background(), &existingNotificationCmd)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, existingNotificationCmd.Result)
|
||||
notificationsQuery := models.GetAllAlertNotificationsQuery{OrgId: 1}
|
||||
err = sqlStore.GetAllAlertNotifications(context.Background(), ¬ificationsQuery)
|
||||
err = ns.SQLStore.GetAllAlertNotifications(context.Background(), ¬ificationsQuery)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, notificationsQuery.Result)
|
||||
require.Equal(t, len(notificationsQuery.Result), 1)
|
||||
@@ -175,6 +179,7 @@ func TestNotificationAsConfig(t *testing.T) {
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Two notifications with is_default", func(t *testing.T) {
|
||||
setup()
|
||||
dc := newNotificationProvisioner(sqlStore, &fakeAlertNotification{}, encryptionService, nil, logger)
|
||||
@@ -194,7 +199,7 @@ func TestNotificationAsConfig(t *testing.T) {
|
||||
Uid: "notifier0",
|
||||
Type: "slack",
|
||||
}
|
||||
err := sqlStore.CreateAlertNotificationCommand(context.Background(), &existingNotificationCmd)
|
||||
err := ns.SQLStore.CreateAlertNotificationCommand(context.Background(), &existingNotificationCmd)
|
||||
require.NoError(t, err)
|
||||
existingNotificationCmd = models.CreateAlertNotificationCommand{
|
||||
Name: "channel3",
|
||||
@@ -202,11 +207,11 @@ func TestNotificationAsConfig(t *testing.T) {
|
||||
Uid: "notifier3",
|
||||
Type: "slack",
|
||||
}
|
||||
err = sqlStore.CreateAlertNotificationCommand(context.Background(), &existingNotificationCmd)
|
||||
err = ns.SQLStore.CreateAlertNotificationCommand(context.Background(), &existingNotificationCmd)
|
||||
require.NoError(t, err)
|
||||
|
||||
notificationsQuery := models.GetAllAlertNotificationsQuery{OrgId: 1}
|
||||
err = sqlStore.GetAllAlertNotifications(context.Background(), ¬ificationsQuery)
|
||||
err = ns.GetAllAlertNotifications(context.Background(), ¬ificationsQuery)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, notificationsQuery.Result)
|
||||
require.Equal(t, len(notificationsQuery.Result), 2)
|
||||
@@ -223,6 +228,7 @@ func TestNotificationAsConfig(t *testing.T) {
|
||||
|
||||
t.Run("Can read correct properties with orgName instead of orgId", func(t *testing.T) {
|
||||
setup()
|
||||
|
||||
existingOrg1 := models.GetOrgByNameQuery{Name: "Main Org. 1"}
|
||||
err := sqlStore.GetOrgByNameHandler(context.Background(), &existingOrg1)
|
||||
require.NoError(t, err)
|
||||
@@ -238,7 +244,7 @@ func TestNotificationAsConfig(t *testing.T) {
|
||||
Uid: "notifier2",
|
||||
Type: "slack",
|
||||
}
|
||||
err = sqlStore.CreateAlertNotificationCommand(context.Background(), &existingNotificationCmd)
|
||||
err = ns.SQLStore.CreateAlertNotificationCommand(context.Background(), &existingNotificationCmd)
|
||||
require.NoError(t, err)
|
||||
|
||||
dc := newNotificationProvisioner(sqlStore, &fakeAlertNotification{}, encryptionService, nil, logger)
|
||||
@@ -270,7 +276,7 @@ func TestNotificationAsConfig(t *testing.T) {
|
||||
t.Fatalf("applyChanges return an error %v", err)
|
||||
}
|
||||
notificationsQuery := models.GetAllAlertNotificationsQuery{OrgId: 1}
|
||||
err = sqlStore.GetAllAlertNotifications(context.Background(), ¬ificationsQuery)
|
||||
err = ns.GetAllAlertNotifications(context.Background(), ¬ificationsQuery)
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, notificationsQuery.Result)
|
||||
})
|
||||
|
||||
@@ -10,5 +10,6 @@ import (
|
||||
type DB interface {
|
||||
WithTransactionalDbSession(ctx context.Context, callback sqlstore.DBTransactionFunc) error
|
||||
WithDbSession(ctx context.Context, callback sqlstore.DBTransactionFunc) error
|
||||
NewSession(ctx context.Context) *sqlstore.DBSession
|
||||
GetDialect() migrator.Dialect
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package sqlstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
@@ -9,6 +10,8 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
)
|
||||
|
||||
var timeNow = time.Now
|
||||
|
||||
type Store interface {
|
||||
GetAdminStats(ctx context.Context, query *models.GetAdminStatsQuery) error
|
||||
GetAlertNotifiersUsageStats(ctx context.Context, query *models.GetAlertNotifierUsageStatsQuery) error
|
||||
@@ -84,13 +87,6 @@ type Store interface {
|
||||
SearchPlaylists(ctx context.Context, query *models.GetPlaylistsQuery) error
|
||||
// deprecated
|
||||
GetPlaylistItem(ctx context.Context, query *models.GetPlaylistItemsByUidQuery) error
|
||||
GetAlertById(ctx context.Context, query *models.GetAlertByIdQuery) error
|
||||
GetAllAlertQueryHandler(ctx context.Context, query *models.GetAllAlertsQuery) error
|
||||
HandleAlertsQuery(ctx context.Context, query *models.GetAlertsQuery) error
|
||||
SetAlertState(ctx context.Context, cmd *models.SetAlertStateCommand) error
|
||||
PauseAlert(ctx context.Context, cmd *models.PauseAlertCommand) error
|
||||
PauseAllAlerts(ctx context.Context, cmd *models.PauseAllAlertCommand) error
|
||||
GetAlertStatesForDashboard(ctx context.Context, query *models.GetAlertStatesForDashboardQuery) error
|
||||
AddOrgUser(ctx context.Context, cmd *models.AddOrgUserCommand) error
|
||||
UpdateOrgUser(ctx context.Context, cmd *models.UpdateOrgUserCommand) error
|
||||
GetOrgUsers(ctx context.Context, query *models.GetOrgUsersQuery) error
|
||||
@@ -107,19 +103,6 @@ type Store interface {
|
||||
Sync() error
|
||||
Reset() error
|
||||
Quote(value string) string
|
||||
DeleteAlertNotification(ctx context.Context, cmd *models.DeleteAlertNotificationCommand) error
|
||||
DeleteAlertNotificationWithUid(ctx context.Context, cmd *models.DeleteAlertNotificationWithUidCommand) error
|
||||
GetAlertNotifications(ctx context.Context, query *models.GetAlertNotificationsQuery) error
|
||||
GetAlertNotificationUidWithId(ctx context.Context, query *models.GetAlertNotificationUidQuery) error
|
||||
GetAlertNotificationsWithUid(ctx context.Context, query *models.GetAlertNotificationsWithUidQuery) error
|
||||
GetAllAlertNotifications(ctx context.Context, query *models.GetAllAlertNotificationsQuery) error
|
||||
GetAlertNotificationsWithUidToSend(ctx context.Context, query *models.GetAlertNotificationsWithUidToSendQuery) error
|
||||
CreateAlertNotificationCommand(ctx context.Context, cmd *models.CreateAlertNotificationCommand) error
|
||||
UpdateAlertNotification(ctx context.Context, cmd *models.UpdateAlertNotificationCommand) error
|
||||
UpdateAlertNotificationWithUid(ctx context.Context, cmd *models.UpdateAlertNotificationWithUidCommand) error
|
||||
SetAlertNotificationStateToCompleteCommand(ctx context.Context, cmd *models.SetAlertNotificationStateToCompleteCommand) error
|
||||
SetAlertNotificationStateToPendingCommand(ctx context.Context, cmd *models.SetAlertNotificationStateToPendingCommand) error
|
||||
GetOrCreateAlertNotificationState(ctx context.Context, cmd *models.GetOrCreateNotificationStateQuery) error
|
||||
UpdateTempUserStatus(ctx context.Context, cmd *models.UpdateTempUserStatusCommand) error
|
||||
CreateTempUser(ctx context.Context, cmd *models.CreateTempUserCommand) error
|
||||
UpdateTempUserWithEmailSent(ctx context.Context, cmd *models.UpdateTempUserWithEmailSentCommand) error
|
||||
|
||||
Reference in New Issue
Block a user