d50e2a94a3
Part 2 of adding version messages to the `alert_rule_version` able. This allows setting the message via a header when using the Prometheus conversion API, which can be useful for e.g. linking changes back to source control.
182 lines
6.6 KiB
Go
182 lines
6.6 KiB
Go
package tests
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"github.com/grafana/grafana/pkg/api/routing"
|
|
"github.com/grafana/grafana/pkg/apimachinery/identity"
|
|
"github.com/grafana/grafana/pkg/bus"
|
|
"github.com/grafana/grafana/pkg/infra/db"
|
|
"github.com/grafana/grafana/pkg/infra/httpclient"
|
|
"github.com/grafana/grafana/pkg/infra/kvstore"
|
|
"github.com/grafana/grafana/pkg/infra/log"
|
|
"github.com/grafana/grafana/pkg/infra/tracing"
|
|
acmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
|
|
"github.com/grafana/grafana/pkg/services/annotations/annotationstest"
|
|
"github.com/grafana/grafana/pkg/services/dashboards"
|
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
|
"github.com/grafana/grafana/pkg/services/folder"
|
|
"github.com/grafana/grafana/pkg/services/folder/foldertest"
|
|
"github.com/grafana/grafana/pkg/services/ngalert"
|
|
"github.com/grafana/grafana/pkg/services/ngalert/metrics"
|
|
"github.com/grafana/grafana/pkg/services/ngalert/models"
|
|
"github.com/grafana/grafana/pkg/services/ngalert/store"
|
|
ngalertfakes "github.com/grafana/grafana/pkg/services/ngalert/tests/fakes"
|
|
"github.com/grafana/grafana/pkg/services/org"
|
|
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
|
"github.com/grafana/grafana/pkg/services/quota/quotatest"
|
|
"github.com/grafana/grafana/pkg/services/secrets/database"
|
|
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
|
|
"github.com/grafana/grafana/pkg/services/user"
|
|
"github.com/grafana/grafana/pkg/services/user/usertest"
|
|
"github.com/grafana/grafana/pkg/setting"
|
|
"github.com/grafana/grafana/pkg/util"
|
|
)
|
|
|
|
type TestEnvOptions struct {
|
|
featureToggles featuremgmt.FeatureToggles
|
|
}
|
|
|
|
type TestEnvOption func(*TestEnvOptions)
|
|
|
|
func WithFeatureToggles(toggles featuremgmt.FeatureToggles) TestEnvOption {
|
|
return func(opts *TestEnvOptions) {
|
|
opts.featureToggles = toggles
|
|
}
|
|
}
|
|
|
|
// SetupTestEnv initializes a store to used by the tests.
|
|
func SetupTestEnv(tb testing.TB, baseInterval time.Duration, opts ...TestEnvOption) (*ngalert.AlertNG, *store.DBstore) {
|
|
tb.Helper()
|
|
|
|
options := TestEnvOptions{
|
|
featureToggles: featuremgmt.WithFeatures(),
|
|
}
|
|
|
|
for _, opt := range opts {
|
|
opt(&options)
|
|
}
|
|
|
|
cfg := setting.NewCfg()
|
|
cfg.UnifiedAlerting = setting.UnifiedAlertingSettings{
|
|
BaseInterval: setting.SchedulerBaseInterval,
|
|
InitializationTimeout: 30 * time.Second,
|
|
}
|
|
// AlertNG database migrations run and the relative database tables are created only when it's enabled
|
|
cfg.UnifiedAlerting.Enabled = new(bool)
|
|
*cfg.UnifiedAlerting.Enabled = true
|
|
|
|
m := metrics.NewNGAlert(prometheus.NewRegistry())
|
|
sqlStore := db.InitTestDB(tb)
|
|
secretsService := secretsManager.SetupTestService(tb, database.ProvideSecretsStore(sqlStore))
|
|
|
|
ac := acmock.New()
|
|
|
|
tracer := tracing.InitializeTracerForTest()
|
|
bus := bus.ProvideBus(tracer)
|
|
folderService := foldertest.NewFakeService()
|
|
dashboardService := dashboards.NewFakeDashboardService(tb)
|
|
ruleStore, err := store.ProvideDBStore(cfg, options.featureToggles, sqlStore, folderService, &dashboards.FakeDashboardService{}, ac, bus)
|
|
require.NoError(tb, err)
|
|
ng, err := ngalert.ProvideService(
|
|
cfg, options.featureToggles, nil, nil, routing.NewRouteRegister(), sqlStore, kvstore.NewFakeKVStore(), nil, nil, quotatest.New(false, nil),
|
|
secretsService, nil, m, folderService, ac, &dashboards.FakeDashboardService{}, nil, bus, ac,
|
|
annotationstest.NewFakeAnnotationsRepo(), &pluginstore.FakePluginStore{}, tracer, ruleStore, httpclient.NewProvider(), nil, ngalertfakes.NewFakeReceiverPermissionsService(), usertest.NewUserServiceFake(),
|
|
)
|
|
require.NoError(tb, err)
|
|
|
|
return ng, &store.DBstore{
|
|
FeatureToggles: options.featureToggles,
|
|
SQLStore: ng.SQLStore,
|
|
Cfg: setting.UnifiedAlertingSettings{
|
|
BaseInterval: baseInterval * time.Second,
|
|
},
|
|
Logger: log.New("ngalert-test"),
|
|
DashboardService: dashboardService,
|
|
FolderService: folderService,
|
|
Bus: bus,
|
|
}
|
|
}
|
|
|
|
// CreateTestAlertRule creates a dummy alert definition to be used by the tests.
|
|
func CreateTestAlertRule(t testing.TB, ctx context.Context, dbstore *store.DBstore, intervalSeconds int64, orgID int64) *models.AlertRule {
|
|
return CreateTestAlertRuleWithLabels(t, ctx, dbstore, intervalSeconds, orgID, nil)
|
|
}
|
|
|
|
func CreateTestAlertRuleWithLabels(t testing.TB, ctx context.Context, dbstore *store.DBstore, intervalSeconds int64, orgID int64, labels map[string]string) *models.AlertRule {
|
|
ruleGroup := fmt.Sprintf("ruleGroup-%s", util.GenerateShortUID())
|
|
folderUID := "namespace"
|
|
user := &user.SignedInUser{
|
|
UserID: 1,
|
|
OrgID: orgID,
|
|
OrgRole: org.RoleAdmin,
|
|
IsGrafanaAdmin: true,
|
|
Permissions: map[int64]map[string][]string{
|
|
orgID: {
|
|
dashboards.ActionFoldersCreate: {dashboards.ScopeFoldersAll},
|
|
dashboards.ActionFoldersRead: {dashboards.ScopeFoldersAll},
|
|
},
|
|
},
|
|
}
|
|
|
|
ctx = identity.WithRequester(ctx, user)
|
|
_, err := dbstore.FolderService.Create(ctx, &folder.CreateFolderCommand{OrgID: orgID, Title: "FOLDER-" + util.GenerateShortUID(), UID: folderUID, SignedInUser: user})
|
|
if errors.Is(err, dashboards.ErrFolderWithSameUIDExists) || errors.Is(err, dashboards.ErrFolderVersionMismatch) {
|
|
_, err = dbstore.FolderService.Get(ctx, &folder.GetFolderQuery{OrgID: orgID, UID: &folderUID, SignedInUser: user})
|
|
}
|
|
require.NoError(t, err)
|
|
|
|
_, err = dbstore.InsertAlertRules(ctx, models.NewUserUID(user), []models.InsertRule{{
|
|
AlertRule: models.AlertRule{
|
|
|
|
ID: 0,
|
|
OrgID: orgID,
|
|
Title: fmt.Sprintf("an alert definition %s", util.GenerateShortUID()),
|
|
Condition: "A",
|
|
Data: []models.AlertQuery{
|
|
{
|
|
Model: json.RawMessage(`{
|
|
"datasourceUid": "__expr__",
|
|
"type":"math",
|
|
"expression":"2 + 2 > 1"
|
|
}`),
|
|
RelativeTimeRange: models.RelativeTimeRange{
|
|
From: models.Duration(5 * time.Hour),
|
|
To: models.Duration(3 * time.Hour),
|
|
},
|
|
RefID: "A",
|
|
},
|
|
},
|
|
Labels: labels,
|
|
Annotations: map[string]string{"testAnnoKey": "testAnnoValue"},
|
|
IntervalSeconds: intervalSeconds,
|
|
NamespaceUID: folderUID,
|
|
RuleGroup: ruleGroup,
|
|
NoDataState: models.NoData,
|
|
ExecErrState: models.AlertingErrState,
|
|
}},
|
|
})
|
|
require.NoError(t, err)
|
|
|
|
q := models.ListAlertRulesQuery{
|
|
OrgID: orgID,
|
|
NamespaceUIDs: []string{folderUID},
|
|
RuleGroups: []string{ruleGroup},
|
|
}
|
|
ruleList, err := dbstore.ListAlertRules(ctx, &q)
|
|
require.NoError(t, err)
|
|
require.NotEmpty(t, ruleList)
|
|
|
|
rule := ruleList[0]
|
|
t.Logf("alert definition: %v with title: %q interval: %d folder: %s created", rule.GetKey(), rule.Title, rule.IntervalSeconds, folderUID)
|
|
return rule
|
|
}
|