grafana/pkg/services/sqlstore/alert_test.go
Kat Yang bd35e6917a
Chore: Exclude integration tests from running on test-backend step (#50359)
* Chore: Exclude integration tests from running on test-backend step

* Remove -v from go test command

* Add check to skip integration tests before each integration test

* Try to restart pipeline

* Retrying to make pipeline run
2022-06-10 11:46:21 -04:00

360 lines
11 KiB
Go

package sqlstore
import (
"context"
"testing"
"time"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/models"
"github.com/stretchr/testify/require"
)
func mockTimeNow() {
var timeSeed int64
timeNow = func() time.Time {
loc := time.FixedZone("MockZoneUTC-5", -5*60*60)
fakeNow := time.Unix(timeSeed, 0).In(loc)
timeSeed++
return fakeNow
}
}
func resetTimeNow() {
timeNow = time.Now
}
func TestIntegrationAlertingDataAccess(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
mockTimeNow()
defer resetTimeNow()
var sqlStore *SQLStore
var testDash *models.Dashboard
var items []*models.Alert
setup := func(t *testing.T) {
sqlStore = InitTestDB(t)
testDash = insertTestDashboard(t, sqlStore, "dashboard with alerts", 1, 0, false, "alert")
evalData, err := simplejson.NewJson([]byte(`{"test": "test"}`))
require.Nil(t, err)
items = []*models.Alert{
{
PanelId: 1,
DashboardId: testDash.Id,
OrgId: testDash.OrgId,
Name: "Alerting title",
Message: "Alerting message",
Settings: simplejson.New(),
Frequency: 1,
EvalData: evalData,
},
}
err = sqlStore.SaveAlerts(context.Background(), testDash.Id, items)
require.Nil(t, err)
}
t.Run("Can set new states", func(t *testing.T) {
setup(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)
require.Nil(t, err2)
insertedAlert := alertQuery.Result[0]
t.Run("new state ok", func(t *testing.T) {
cmd := &models.SetAlertStateCommand{
AlertId: insertedAlert.Id,
State: models.AlertStateOK,
}
err := sqlStore.SetAlertState(context.Background(), cmd)
require.Nil(t, err)
})
alert, _ := getAlertById(t, insertedAlert.Id, sqlStore)
stateDateBeforePause := alert.NewStateDate
t.Run("can pause all alerts", func(t *testing.T) {
err := sqlStore.pauseAllAlerts(t, true)
require.Nil(t, err)
t.Run("cannot updated paused alert", func(t *testing.T) {
cmd := &models.SetAlertStateCommand{
AlertId: insertedAlert.Id,
State: models.AlertStateOK,
}
err = sqlStore.SetAlertState(context.Background(), cmd)
require.Error(t, err)
})
t.Run("alert is paused", func(t *testing.T) {
alert, _ = getAlertById(t, insertedAlert.Id, sqlStore)
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)
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)
require.Nil(t, err)
alert, _ = getAlertById(t, insertedAlert.Id, sqlStore)
stateDateAfterUnpause := alert.NewStateDate
require.True(t, stateDateBeforePause.Before(stateDateAfterUnpause))
})
})
})
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)
alert := alertQuery.Result[0]
require.Nil(t, err2)
require.Greater(t, alert.Id, int64(0))
require.Equal(t, testDash.Id, alert.DashboardId)
require.Equal(t, int64(1), alert.PanelId)
require.Equal(t, "Alerting title", alert.Name)
require.Equal(t, models.AlertStateUnknown, alert.State)
require.NotNil(t, alert.NewStateDate)
require.NotNil(t, alert.EvalData)
require.Equal(t, "test", alert.EvalData.Get("test").MustString())
require.NotNil(t, alert.EvalDate)
require.Equal(t, "", alert.ExecutionError)
require.NotNil(t, alert.DashboardUid)
require.Equal(t, "dashboard-with-alerts", alert.DashboardSlug)
})
t.Run("Viewer can read alerts", func(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)
require.Nil(t, err2)
require.Equal(t, 1, len(alertQuery.Result))
})
t.Run("Alerts with same dashboard id and panel id should update", func(t *testing.T) {
setup(t)
modifiedItems := items
modifiedItems[0].Name = "Name"
err := sqlStore.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)
})
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)
require.Nil(t, err2)
require.Equal(t, 1, len(query.Result))
require.Equal(t, "Name", query.Result[0].Name)
t.Run("Alert state should not be updated", func(t *testing.T) {
require.Equal(t, models.AlertStateUnknown, query.Result[0].State)
})
})
t.Run("Updates without changes should be ignored", func(t *testing.T) {
err3 := sqlStore.SaveAlerts(context.Background(), testDash.Id, items)
require.Nil(t, err3)
})
})
t.Run("Multiple alerts per dashboard", func(t *testing.T) {
setup(t)
multipleItems := []*models.Alert{
{
DashboardId: testDash.Id,
PanelId: 1,
Name: "1",
OrgId: 1,
Settings: simplejson.New(),
},
{
DashboardId: testDash.Id,
PanelId: 2,
Name: "2",
OrgId: 1,
Settings: simplejson.New(),
},
{
DashboardId: testDash.Id,
PanelId: 3,
Name: "3",
OrgId: 1,
Settings: simplejson.New(),
},
}
err := sqlStore.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)
require.Nil(t, err2)
require.Equal(t, 3, len(queryForDashboard.Result))
})
t.Run("should updated two dashboards and delete one", func(t *testing.T) {
missingOneAlert := multipleItems[:2]
err = sqlStore.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)
require.Nil(t, err2)
require.Equal(t, 2, len(query.Result))
})
})
})
t.Run("When dashboard is removed", func(t *testing.T) {
setup(t)
items := []*models.Alert{
{
PanelId: 1,
DashboardId: testDash.Id,
Name: "Alerting title",
Message: "Alerting message",
},
}
err := sqlStore.SaveAlerts(context.Background(), testDash.Id, items)
require.Nil(t, err)
err = sqlStore.WithDbSession(context.Background(), func(sess *DBSession) error {
dash := models.Dashboard{Id: testDash.Id, OrgId: 1}
_, err := sess.Delete(dash)
return err
})
require.Nil(t, err)
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)
require.Nil(t, err2)
require.Equal(t, 0, len(query.Result))
})
})
}
func TestIntegrationPausingAlerts(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
mockTimeNow()
defer resetTimeNow()
t.Run("Given an alert", func(t *testing.T) {
sqlStore := InitTestDB(t)
testDash := insertTestDashboard(t, sqlStore, "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)
stateDateBeforePause := alert.NewStateDate
stateDateAfterPause := stateDateBeforePause
// 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)
require.Nil(t, err2)
insertedAlert := alertQuery.Result[0]
t.Run("when paused", func(t *testing.T) {
_, err := sqlStore.pauseAlert(t, testDash.OrgId, insertedAlert.Id, true)
require.Nil(t, err)
t.Run("the NewStateDate should be updated", func(t *testing.T) {
alert, err := getAlertById(t, insertedAlert.Id, sqlStore)
require.Nil(t, err)
stateDateAfterPause = alert.NewStateDate
require.True(t, stateDateBeforePause.Before(stateDateAfterPause))
})
})
t.Run("when unpaused", func(t *testing.T) {
_, err := sqlStore.pauseAlert(t, testDash.OrgId, insertedAlert.Id, false)
require.Nil(t, err)
t.Run("the NewStateDate should be updated again", func(t *testing.T) {
alert, err := getAlertById(t, insertedAlert.Id, sqlStore)
require.Nil(t, err)
stateDateAfterUnpause := alert.NewStateDate
require.True(t, stateDateAfterPause.Before(stateDateAfterUnpause))
})
})
})
}
func (ss *SQLStore) pauseAlert(t *testing.T, orgId int64, alertId int64, pauseState bool) (int64, error) {
cmd := &models.PauseAlertCommand{
OrgId: orgId,
AlertIds: []int64{alertId},
Paused: pauseState,
}
err := ss.PauseAlert(context.Background(), cmd)
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) {
items := []*models.Alert{
{
PanelId: 1,
DashboardId: dashId,
OrgId: orgId,
Name: title,
Message: message,
Settings: settings,
Frequency: 1,
},
}
err := ss.SaveAlerts(context.Background(), dashId, items)
return items[0], err
}
func getAlertById(t *testing.T, id int64, ss *SQLStore) (*models.Alert, error) {
q := &models.GetAlertByIdQuery{
Id: id,
}
err := ss.GetAlertById(context.Background(), q)
require.Nil(t, err)
return q.Result, err
}
func (ss *SQLStore) pauseAllAlerts(t *testing.T, pauseState bool) error {
cmd := &models.PauseAllAlertCommand{
Paused: pauseState,
}
err := ss.PauseAllAlerts(context.Background(), cmd)
require.Nil(t, err)
return err
}