Files
grafana/pkg/services/ngalert/database_test.go
Sofia Papagiannaki 43f580c299 AlertingNG: manage and evaluate alert definitions via the API (#28377)
* Alerting NG: prototype v2 (WIP)

* Separate eval package

* Modify eval alert definition endpoint

* Disable migration if ngalert is not enabled

* Remove premature test

* Fix lint issues

* Delete obsolete struct

* Apply suggestions from code review

* Update pkg/services/ngalert/ngalert.go

Co-authored-by: Kyle Brandt <kyle@grafana.com>

* Add API endpoint for listing alert definitions

* Introduce index for alert_definition table

* make ds object for expression to avoid panic

* wrap error

* Update pkg/services/ngalert/eval/eval.go

* Swith to backend.DataQuery

* Export TransformWrapper callback

* Fix lint issues

* Update pkg/services/ngalert/ngalert.go

Co-authored-by: Kyle Brandt <kyle@grafana.com>

* Validate alert definitions before storing them

* Introduce AlertQuery

* Add test

* Add QueryType in AlertQuery

* Accept only float64 (seconds) durations

* Apply suggestions from code review

* Get rid of bus

* Do not export symbols

* Fix failing test

* Fix failure due to service initialization order

Introduce MediumHigh service priority and assign it to backendplugin
service

* Fix test

* Apply suggestions from code review

* Fix renamed reference

Co-authored-by: Kyle Brandt <kyle@grafana.com>
2020-11-12 15:11:30 +02:00

182 lines
4.4 KiB
Go

// +build integration
package ngalert
import (
"encoding/json"
"testing"
"time"
"github.com/grafana/grafana/pkg/services/ngalert/eval"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/setting"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestCreatingAlertDefinition(t *testing.T) {
t.Run("should fail gracefully when creating alert definition with invalid relative time range", func(t *testing.T) {
ng := setupTestEnv(t)
q := saveAlertDefinitionCommand{
OrgID: 1,
Name: "something completely different",
Condition: condition{
RefID: "B",
QueriesAndExpressions: []eval.AlertQuery{
{
Model: json.RawMessage(`{
"datasource": "__expr__",
"type":"math",
"expression":"2 + 3 > 1"
}`),
RefID: "B",
},
},
},
}
err := ng.saveAlertDefinition(&q)
require.NoError(t, err)
})
}
func TestUpdatingAlertDefinition(t *testing.T) {
t.Run("zero rows affected when updating unknown alert", func(t *testing.T) {
ng := setupTestEnv(t)
q := updateAlertDefinitionCommand{
ID: 1,
OrgID: 1,
Name: "something completely different",
Condition: condition{
RefID: "A",
QueriesAndExpressions: []eval.AlertQuery{
{
Model: json.RawMessage(`{
"datasource": "__expr__",
"type":"math",
"expression":"2 + 2 > 1"
}`),
RefID: "A",
RelativeTimeRange: eval.RelativeTimeRange{
From: eval.Duration(time.Duration(5) * time.Hour),
To: eval.Duration(time.Duration(3) * time.Hour),
},
},
},
},
}
err := ng.updateAlertDefinition(&q)
require.NoError(t, err)
assert.Equal(t, int64(0), q.RowsAffected)
})
t.Run("updating successfully existing alert", func(t *testing.T) {
ng := setupTestEnv(t)
alertDefinition := createTestAlertDefinition(t, ng)
q := updateAlertDefinitionCommand{
ID: (*alertDefinition).Id,
OrgID: 1,
Name: "something completely different",
Condition: condition{
RefID: "B",
QueriesAndExpressions: []eval.AlertQuery{
{
Model: json.RawMessage(`{
"datasource": "__expr__",
"type":"math",
"expression":"2 + 3 > 1"
}`),
RefID: "B",
RelativeTimeRange: eval.RelativeTimeRange{
From: eval.Duration(5 * time.Hour),
To: eval.Duration(3 * time.Hour),
},
},
},
},
}
err := ng.updateAlertDefinition(&q)
require.NoError(t, err)
assert.Equal(t, int64(1), q.RowsAffected)
assert.Equal(t, int64(1), q.Result.Id)
getAlertDefinitionByIDQuery := getAlertDefinitionByIDQuery{ID: (*alertDefinition).Id}
err = ng.getAlertDefinitionByID(&getAlertDefinitionByIDQuery)
require.NoError(t, err)
assert.Equal(t, "something completely different", getAlertDefinitionByIDQuery.Result.Name)
assert.Equal(t, "B", getAlertDefinitionByIDQuery.Result.Condition)
assert.Equal(t, 1, len(getAlertDefinitionByIDQuery.Result.Data))
})
}
func TestDeletingAlertDefinition(t *testing.T) {
t.Run("zero rows affected when deleting unknown alert", func(t *testing.T) {
ng := setupTestEnv(t)
q := deleteAlertDefinitionByIDQuery{
ID: 1,
OrgID: 1,
}
err := ng.deleteAlertDefinitionByID(&q)
require.NoError(t, err)
assert.Equal(t, int64(0), q.RowsAffected)
})
t.Run("deleting successfully existing alert", func(t *testing.T) {
ng := setupTestEnv(t)
alertDefinition := createTestAlertDefinition(t, ng)
q := deleteAlertDefinitionByIDQuery{
ID: (*alertDefinition).Id,
OrgID: 1,
}
err := ng.deleteAlertDefinitionByID(&q)
require.NoError(t, err)
assert.Equal(t, int64(1), q.RowsAffected)
})
}
func setupTestEnv(t *testing.T) AlertNG {
sqlStore := sqlstore.InitTestDB(t)
cfg := setting.Cfg{}
cfg.FeatureToggles = map[string]bool{"ngalert": true}
ng := AlertNG{
SQLStore: sqlStore,
Cfg: &cfg,
}
return ng
}
func createTestAlertDefinition(t *testing.T, ng AlertNG) *AlertDefinition {
cmd := saveAlertDefinitionCommand{
OrgID: 1,
Name: "an alert definition",
Condition: condition{
RefID: "A",
QueriesAndExpressions: []eval.AlertQuery{
{
Model: json.RawMessage(`{
"datasource": "__expr__",
"type":"math",
"expression":"2 + 2 > 1"
}`),
RelativeTimeRange: eval.RelativeTimeRange{
From: eval.Duration(5 * time.Hour),
To: eval.Duration(3 * time.Hour),
},
RefID: "A",
},
},
},
}
err := ng.saveAlertDefinition(&cmd)
require.NoError(t, err)
return cmd.Result
}