grafana/pkg/services/alerting/rule_test.go
Joan López de la Franca Beltran 722c414fef
Encryption: Refactor securejsondata.SecureJsonData to stop relying on global functions (#38865)
* Encryption: Add support to encrypt/decrypt sjd

* Add datasources.Service as a proxy to datasources db operations

* Encrypt ds.SecureJsonData before calling SQLStore

* Move ds cache code into ds service

* Fix tlsmanager tests

* Fix pluginproxy tests

* Remove some securejsondata.GetEncryptedJsonData usages

* Add pluginsettings.Service as a proxy for plugin settings db operations

* Add AlertNotificationService as a proxy for alert notification db operations

* Remove some securejsondata.GetEncryptedJsonData usages

* Remove more securejsondata.GetEncryptedJsonData usages

* Fix lint errors

* Minor fixes

* Remove encryption global functions usages from ngalert

* Fix lint errors

* Minor fixes

* Minor fixes

* Remove securejsondata.DecryptedValue usage

* Refactor the refactor

* Remove securejsondata.DecryptedValue usage

* Move securejsondata to migrations package

* Move securejsondata to migrations package

* Minor fix

* Fix integration test

* Fix integration tests

* Undo undesired changes

* Fix tests

* Add context.Context into encryption methods

* Fix tests

* Fix tests

* Fix tests

* Trigger CI

* Fix test

* Add names to params of encryption service interface

* Remove bus from CacheServiceImpl

* Add logging

* Add keys to logger

Co-authored-by: Emil Tullstedt <emil.tullstedt@grafana.com>

* Add missing key to logger

Co-authored-by: Emil Tullstedt <emil.tullstedt@grafana.com>

* Undo changes in markdown files

* Fix formatting

* Add context to secrets service

* Rename decryptSecureJsonData to decryptSecureJsonDataFn

* Name args in GetDecryptedValueFn

* Add template back to NewAlertmanagerNotifier

* Copy GetDecryptedValueFn to ngalert

* Add logging to pluginsettings

* Fix pluginsettings test

Co-authored-by: Tania B <yalyna.ts@gmail.com>
Co-authored-by: Emil Tullstedt <emil.tullstedt@grafana.com>
2021-10-07 17:33:50 +03:00

245 lines
6.1 KiB
Go

package alerting
import (
"fmt"
"testing"
"time"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
type FakeCondition struct{}
func (f *FakeCondition) Eval(context *EvalContext, reqHandler plugins.DataRequestHandler) (*ConditionResult, error) {
return &ConditionResult{}, nil
}
func TestAlertRuleFrequencyParsing(t *testing.T) {
tcs := []struct {
input string
err error
result int64
}{
{input: "10s", result: 10},
{input: "10m", result: 600},
{input: "1h", result: 3600},
{input: "1d", result: 86400},
{input: "1o", err: ErrWrongUnitFormat},
{input: "0s", err: ErrFrequencyCannotBeZeroOrLess},
{input: "0m", err: ErrFrequencyCannotBeZeroOrLess},
{input: "0h", err: ErrFrequencyCannotBeZeroOrLess},
{input: "0", err: ErrFrequencyCouldNotBeParsed},
{input: "", err: ErrFrequencyCouldNotBeParsed},
{input: "-1s", err: ErrFrequencyCouldNotBeParsed},
}
for _, tc := range tcs {
t.Run(tc.input, func(t *testing.T) {
r, err := getTimeDurationStringToSeconds(tc.input)
if tc.err == nil {
require.NoError(t, err)
} else {
require.EqualError(t, err, tc.err.Error())
}
assert.Equal(t, tc.result, r)
})
}
}
func TestAlertRuleForParsing(t *testing.T) {
tcs := []struct {
input string
err error
result time.Duration
}{
{input: "10s", result: time.Duration(10000000000)},
{input: "10m", result: time.Duration(600000000000)},
{input: "1h", result: time.Duration(3600000000000)},
{input: "1o", err: fmt.Errorf("alert validation error: could not parse for field, error: %s", ErrWrongUnitFormat)},
{input: "1", err: fmt.Errorf("alert validation error: no specified unit, error: %s", ErrWrongUnitFormat)},
{input: "0s", result: time.Duration(0)},
{input: "0m", result: time.Duration(0)},
{input: "0h", result: time.Duration(0)},
{input: "0", result: time.Duration(0)},
{input: "", result: time.Duration(0)},
}
for _, tc := range tcs {
t.Run(tc.input, func(t *testing.T) {
r, err := getForValue(tc.input)
if tc.err == nil {
require.NoError(t, err)
} else {
require.EqualError(t, err, tc.err.Error())
}
assert.Equal(t, tc.result, r)
})
}
}
func TestAlertRuleModel(t *testing.T) {
sqlStore := sqlstore.InitTestDB(t)
RegisterCondition("test", func(model *simplejson.Json, index int) (Condition, error) {
return &FakeCondition{}, nil
})
firstNotification := models.CreateAlertNotificationCommand{Uid: "notifier1", OrgId: 1, Name: "1"}
err := sqlStore.CreateAlertNotificationCommand(&firstNotification)
require.Nil(t, err)
secondNotification := models.CreateAlertNotificationCommand{Uid: "notifier2", OrgId: 1, Name: "2"}
err = sqlStore.CreateAlertNotificationCommand(&secondNotification)
require.Nil(t, err)
t.Run("Testing alert rule with notification id and uid", func(t *testing.T) {
json := `
{
"name": "name2",
"description": "desc2",
"handler": 0,
"noDataMode": "critical",
"enabled": true,
"frequency": "60s",
"conditions": [
{
"type": "test",
"prop": 123
}
],
"notifications": [
{"id": 1},
{"uid": "notifier2"}
]
}
`
alertJSON, jsonErr := simplejson.NewJson([]byte(json))
require.Nil(t, jsonErr)
alert := &models.Alert{
Id: 1,
OrgId: 1,
DashboardId: 1,
PanelId: 1,
Settings: alertJSON,
}
alertRule, err := NewRuleFromDBAlert(alert, false)
require.Nil(t, err)
require.Len(t, alertRule.Conditions, 1)
require.Len(t, alertRule.Notifications, 2)
require.Contains(t, alertRule.Notifications, "notifier2")
require.Contains(t, alertRule.Notifications, "notifier1")
})
t.Run("Testing alert rule with non existing notification id", func(t *testing.T) {
json := `
{
"name": "name3",
"description": "desc3",
"handler": 0,
"noDataMode": "critical",
"enabled": true,
"frequency": "60s",
"conditions": [{"type": "test", "prop": 123 }],
"notifications": [
{"id": 999},
{"uid": "notifier2"}
]
}
`
alertJSON, jsonErr := simplejson.NewJson([]byte(json))
require.Nil(t, jsonErr)
alert := &models.Alert{
Id: 1,
OrgId: 1,
DashboardId: 1,
PanelId: 1,
Settings: alertJSON,
}
alertRule, err := NewRuleFromDBAlert(alert, false)
require.Nil(t, err)
require.NotContains(t, alertRule.Notifications, "999")
require.Contains(t, alertRule.Notifications, "notifier2")
})
t.Run("Testing alert rule which can construct alert rule model with invalid frequency", func(t *testing.T) {
json := `
{
"name": "name2",
"description": "desc2",
"noDataMode": "critical",
"enabled": true,
"frequency": "0s",
"conditions": [ { "type": "test", "prop": 123 } ],
"notifications": []
}`
alertJSON, jsonErr := simplejson.NewJson([]byte(json))
require.Nil(t, jsonErr)
alert := &models.Alert{
Id: 1,
OrgId: 1,
DashboardId: 1,
PanelId: 1,
Frequency: 0,
Settings: alertJSON,
}
alertRule, err := NewRuleFromDBAlert(alert, false)
require.Nil(t, err)
require.EqualValues(t, alertRule.Frequency, 60)
})
t.Run("Testing alert rule which will raise error in case of missing notification id and uid", func(t *testing.T) {
json := `
{
"name": "name2",
"description": "desc2",
"noDataMode": "critical",
"enabled": true,
"frequency": "60s",
"conditions": [
{
"type": "test",
"prop": 123
}
],
"notifications": [
{"not_id_uid": "1134"}
]
}
`
alertJSON, jsonErr := simplejson.NewJson([]byte(json))
require.Nil(t, jsonErr)
alert := &models.Alert{
Id: 1,
OrgId: 1,
DashboardId: 1,
PanelId: 1,
Frequency: 0,
Settings: alertJSON,
}
_, err := NewRuleFromDBAlert(alert, false)
require.NotNil(t, err)
require.EqualValues(t, err.Error(), "alert validation error: Neither id nor uid is specified in 'notifications' block, type assertion to string failed AlertId: 1 PanelId: 1 DashboardId: 1")
})
}