Dashboard Alert Extractor: Create service for dashboard extractor and remove bus (#45518)

* Create DashAlertService service

* Remove no used dashboard service from plugin's manager that generates dependency cycle in Enterprise

* Remove bus for dashboard permissions

* Remove bus from dashboard extractor service

* Add missing argument

* Fix wire

* Fix lint

* More goimports

* Use datasource service instead sql calls

* Fix integration test
This commit is contained in:
Selene 2022-02-28 09:54:56 +01:00 committed by GitHub
parent 1df040eb23
commit 2c90dcf3c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 294 additions and 232 deletions

View File

@ -364,7 +364,7 @@ func setupHTTPServerWithCfg(t *testing.T, useFakeAccessControl, enableAccessCont
RouteRegister: routeRegister,
SQLStore: db,
searchUsersService: searchusers.ProvideUsersService(bus, filters.ProvideOSSSearchUserFilter()),
dashboardService: dashboardservice.ProvideDashboardService(dashboardsStore),
dashboardService: dashboardservice.ProvideDashboardService(dashboardsStore, nil),
}
// Defining the accesscontrol service has to be done before registering routes

View File

@ -29,7 +29,7 @@ func TestDashboardPermissionAPIEndpoint(t *testing.T) {
hs := &HTTPServer{
Cfg: settings,
dashboardService: dashboardservice.ProvideDashboardService(dashboardStore),
dashboardService: dashboardservice.ProvideDashboardService(dashboardStore, nil),
SQLStore: mockSQLStore,
}

View File

@ -219,7 +219,7 @@ func TestDashboardAPIEndpoint(t *testing.T) {
Live: newTestLive(t),
LibraryPanelService: &mockLibraryPanelService{},
LibraryElementService: &mockLibraryElementService{},
dashboardService: service.ProvideDashboardService(dashboardStore),
dashboardService: service.ProvideDashboardService(dashboardStore, nil),
SQLStore: mockSQLStore,
}
hs.SQLStore = mockSQLStore
@ -939,7 +939,7 @@ func getDashboardShouldReturn200WithConfig(t *testing.T, sc *scenarioContext, pr
LibraryPanelService: &libraryPanelsService,
LibraryElementService: &libraryElementsService,
ProvisioningService: provisioningService,
dashboardProvisioningService: service.ProvideDashboardService(dashboardStore),
dashboardProvisioningService: service.ProvideDashboardService(dashboardStore, nil),
SQLStore: sc.sqlStore,
}

View File

@ -15,6 +15,7 @@ import (
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/datasources/permissions"
"github.com/grafana/grafana/pkg/services/sqlstore/mockstore"
"github.com/grafana/grafana/pkg/setting"
"github.com/stretchr/testify/assert"
@ -29,7 +30,7 @@ const (
func TestDataSourcesProxy_userLoggedIn(t *testing.T) {
mockSQLStore := mockstore.NewSQLStoreMock()
mockDatasourcePermissionService := newMockDatasourcePermissionService()
mockDatasourcePermissionService := permissions.NewMockDatasourcePermissionService()
loggedInUserScenario(t, "When calling GET on", "/api/datasources/", "/api/datasources/", func(sc *scenarioContext) {
// Stubs the database query
ds := []*models.DataSource{
@ -38,7 +39,7 @@ func TestDataSourcesProxy_userLoggedIn(t *testing.T) {
{Name: "BBB"},
{Name: "aaa"},
}
mockDatasourcePermissionService.dsResult = ds
mockDatasourcePermissionService.DsResult = ds
// handler func being tested
hs := &HTTPServer{
@ -209,8 +210,8 @@ func TestAPI_Datasources_AccessControl(t *testing.T) {
dsServiceMock := &dataSourcesServiceMock{
expectedDatasource: &testDatasource,
}
dsPermissionService := newMockDatasourcePermissionService()
dsPermissionService.dsResult = []*models.DataSource{
dsPermissionService := permissions.NewMockDatasourcePermissionService()
dsPermissionService.DsResult = []*models.DataSource{
&testDatasource,
}
@ -505,9 +506,9 @@ func TestAPI_Datasources_AccessControl(t *testing.T) {
// mock sqlStore and datasource permission service
dsServiceMock.expectedError = test.expectedSQLError
dsServiceMock.expectedDatasource = test.expectedDS
dsPermissionService.dsResult = []*models.DataSource{test.expectedDS}
dsPermissionService.DsResult = []*models.DataSource{test.expectedDS}
if test.expectedDS == nil {
dsPermissionService.dsResult = nil
dsPermissionService.DsResult = nil
}
hs.DataSourcesService = dsServiceMock
hs.DatasourcePermissionsService = dsPermissionService

View File

@ -30,7 +30,7 @@ func TestFolderPermissionAPIEndpoint(t *testing.T) {
dashboardStore := &database.FakeDashboardStore{}
defer dashboardStore.AssertExpectations(t)
hs := &HTTPServer{Cfg: settings, folderService: folderService, dashboardService: service.ProvideDashboardService(dashboardStore)}
hs := &HTTPServer{Cfg: settings, folderService: folderService, dashboardService: service.ProvideDashboardService(dashboardStore, nil)}
t.Run("Given folder not exists", func(t *testing.T) {
folderService.On("GetFolderByUID", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, models.ErrFolderNotFound).Twice()

View File

@ -36,6 +36,7 @@ import (
"github.com/grafana/grafana/pkg/services/dashboardsnapshots"
"github.com/grafana/grafana/pkg/services/datasourceproxy"
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/datasources/permissions"
"github.com/grafana/grafana/pkg/services/encryption"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/hooks"
@ -135,7 +136,7 @@ type HTTPServer struct {
dashboardService dashboards.DashboardService
dashboardProvisioningService dashboards.DashboardProvisioningService
folderService dashboards.FolderService
DatasourcePermissionsService DatasourcePermissionsService
DatasourcePermissionsService permissions.DatasourcePermissionsService
commentsService *comments.Service
AlertNotificationService *alerting.AlertNotificationService
DashboardsnapshotsService *dashboardsnapshots.Service
@ -169,7 +170,7 @@ func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routi
authInfoService login.AuthInfoService, permissionsServices accesscontrol.PermissionsServices,
notificationService *notifications.NotificationService, dashboardService dashboards.DashboardService,
dashboardProvisioningService dashboards.DashboardProvisioningService, folderService dashboards.FolderService,
datasourcePermissionsService DatasourcePermissionsService, alertNotificationService *alerting.AlertNotificationService,
datasourcePermissionsService permissions.DatasourcePermissionsService, alertNotificationService *alerting.AlertNotificationService,
dashboardsnapshotsService *dashboardsnapshots.Service, commentsService *comments.Service, pluginSettings *pluginsettings.ServiceImpl,
) (*HTTPServer, error) {
web.Env = cfg.Env

View File

@ -11,9 +11,6 @@ import (
"github.com/grafana/grafana/pkg/plugins/backendplugin/provider"
"github.com/grafana/grafana/pkg/plugins/manager/loader"
"github.com/grafana/grafana/pkg/plugins/manager/signature"
"github.com/grafana/grafana/pkg/services/dashboards/database"
service "github.com/grafana/grafana/pkg/services/dashboards/manager"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/setting"
"github.com/stretchr/testify/require"
)
@ -27,9 +24,8 @@ func TestGetPluginDashboards(t *testing.T) {
},
}
pmCfg := plugins.FromGrafanaCfg(cfg)
dashboardService := service.ProvideDashboardService(database.ProvideDashboardStore(&sqlstore.SQLStore{}))
pm, err := ProvideService(cfg, loader.New(pmCfg, nil,
signature.NewUnsignedAuthorizer(pmCfg), &provider.Service{}), dashboardService)
signature.NewUnsignedAuthorizer(pmCfg), &provider.Service{}))
require.NoError(t, err)
bus.AddHandler("test", func(ctx context.Context, query *models.GetDashboardQuery) error {

View File

@ -14,7 +14,6 @@ import (
"github.com/grafana/grafana/pkg/plugins/backendplugin"
"github.com/grafana/grafana/pkg/plugins/backendplugin/instrumentation"
"github.com/grafana/grafana/pkg/plugins/manager/installer"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/setting"
"github.com/grafana/grafana/pkg/util/errutil"
)
@ -30,38 +29,35 @@ var _ plugins.StaticRouteResolver = (*PluginManager)(nil)
var _ plugins.RendererManager = (*PluginManager)(nil)
type PluginManager struct {
cfg *plugins.Cfg
store map[string]*plugins.Plugin
pluginInstaller plugins.Installer
pluginLoader plugins.Loader
pluginsMu sync.RWMutex
pluginPaths map[plugins.Class][]string
dashboardService dashboards.DashboardService
log log.Logger
cfg *plugins.Cfg
store map[string]*plugins.Plugin
pluginInstaller plugins.Installer
pluginLoader plugins.Loader
pluginsMu sync.RWMutex
pluginPaths map[plugins.Class][]string
log log.Logger
}
func ProvideService(grafanaCfg *setting.Cfg, pluginLoader plugins.Loader, dashboardService dashboards.DashboardService) (*PluginManager, error) {
func ProvideService(grafanaCfg *setting.Cfg, pluginLoader plugins.Loader) (*PluginManager, error) {
pm := New(plugins.FromGrafanaCfg(grafanaCfg), map[plugins.Class][]string{
plugins.Core: corePluginPaths(grafanaCfg),
plugins.Bundled: {grafanaCfg.BundledPluginsPath},
plugins.External: append([]string{grafanaCfg.PluginsPath}, pluginSettingPaths(grafanaCfg)...),
}, pluginLoader, dashboardService)
}, pluginLoader)
if err := pm.Init(); err != nil {
return nil, err
}
return pm, nil
}
func New(cfg *plugins.Cfg, pluginPaths map[plugins.Class][]string, pluginLoader plugins.Loader,
dashboardService dashboards.DashboardService) *PluginManager {
func New(cfg *plugins.Cfg, pluginPaths map[plugins.Class][]string, pluginLoader plugins.Loader) *PluginManager {
return &PluginManager{
cfg: cfg,
pluginLoader: pluginLoader,
pluginPaths: pluginPaths,
store: make(map[string]*plugins.Plugin),
log: log.New("plugin.manager"),
pluginInstaller: installer.New(false, cfg.BuildVersion, newInstallerLogger("plugin.installer", true)),
dashboardService: dashboardService,
cfg: cfg,
pluginLoader: pluginLoader,
pluginPaths: pluginPaths,
store: make(map[string]*plugins.Plugin),
log: log.New("plugin.manager"),
pluginInstaller: installer.New(false, cfg.BuildVersion, newInstallerLogger("plugin.installer", true)),
}
}

View File

@ -14,7 +14,6 @@ import (
"github.com/grafana/grafana/pkg/plugins/backendplugin/provider"
"github.com/grafana/grafana/pkg/plugins/manager/loader"
"github.com/grafana/grafana/pkg/plugins/manager/signature"
service "github.com/grafana/grafana/pkg/services/dashboards/manager"
"github.com/grafana/grafana/pkg/services/featuremgmt"
"github.com/grafana/grafana/pkg/services/licensing"
"github.com/grafana/grafana/pkg/services/searchV2"
@ -94,7 +93,7 @@ func TestPluginManager_int_init(t *testing.T) {
pmCfg := plugins.FromGrafanaCfg(cfg)
pm, err := ProvideService(cfg, loader.New(pmCfg, license, signature.NewUnsignedAuthorizer(pmCfg),
provider.ProvideService(coreRegistry)), &service.DashboardServiceImpl{})
provider.ProvideService(coreRegistry)))
require.NoError(t, err)
verifyCorePluginCatalogue(t, pm)

View File

@ -12,9 +12,6 @@ import (
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/backendplugin"
"github.com/grafana/grafana/pkg/services/dashboards/database"
service "github.com/grafana/grafana/pkg/services/dashboards/manager"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@ -469,8 +466,7 @@ func TestPluginManager_lifecycle_unmanaged(t *testing.T) {
func createManager(t *testing.T, cbs ...func(*PluginManager)) *PluginManager {
t.Helper()
dashboardService := service.ProvideDashboardService(database.ProvideDashboardStore(&sqlstore.SQLStore{}))
pm := New(&plugins.Cfg{}, nil, &fakeLoader{}, dashboardService)
pm := New(&plugins.Cfg{}, nil, &fakeLoader{})
for _, cb := range cbs {
cb(pm)
@ -524,8 +520,7 @@ func newScenario(t *testing.T, managed bool, fn func(t *testing.T, ctx *managerS
cfg.Azure.ManagedIdentityClientId = "client-id"
loader := &fakeLoader{}
dashboardService := service.ProvideDashboardService(database.ProvideDashboardStore(&sqlstore.SQLStore{}))
manager := New(cfg, nil, loader, dashboardService)
manager := New(cfg, nil, loader)
manager.pluginLoader = loader
ctx := &managerScenarioCtx{
manager: manager,

View File

@ -213,6 +213,8 @@ var wireBasicSet = wire.NewSet(
dashboardimportservice.ProvideService,
wire.Bind(new(dashboardimport.Service), new(*dashboardimportservice.ImportDashboardService)),
plugindashboards.ProvideService,
alerting.ProvideDashAlertExtractorService,
wire.Bind(new(alerting.DashAlertExtractor), new(*alerting.DashAlertExtractorService)),
comments.ProvideService,
)

View File

@ -5,7 +5,6 @@ package server
import (
"github.com/google/wire"
"github.com/grafana/grafana/pkg/api"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/backendplugin/provider"
@ -18,6 +17,7 @@ import (
"github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions"
"github.com/grafana/grafana/pkg/services/auth"
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/datasources/permissions"
datasourceservice "github.com/grafana/grafana/pkg/services/datasources/service"
"github.com/grafana/grafana/pkg/services/encryption"
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
@ -75,8 +75,8 @@ var wireExtsBasicSet = wire.NewSet(
wire.Bind(new(kmsproviders.Service), new(osskmsproviders.Service)),
ldap.ProvideGroupsService,
wire.Bind(new(ldap.Groups), new(*ldap.OSSGroups)),
api.ProvideDatasourcePermissionsService,
wire.Bind(new(api.DatasourcePermissionsService), new(*api.OSSDatasourcePermissionsService)),
permissions.ProvideDatasourcePermissionsService,
wire.Bind(new(permissions.DatasourcePermissionsService), new(*permissions.OSSDatasourcePermissionsService)),
ossaccesscontrol.ProvidePermissionsServices,
wire.Bind(new(accesscontrol.PermissionsServices), new(*ossaccesscontrol.PermissionsService)),
)

View File

@ -45,16 +45,17 @@ type AlertEngine struct {
DataService legacydata.RequestHandler
Cfg *setting.Cfg
execQueue chan *Job
ticker *Ticker
scheduler scheduler
evalHandler evalHandler
ruleReader ruleReader
log log.Logger
resultHandler resultHandler
usageStatsService usagestats.Service
tracer tracing.Tracer
sqlStore AlertStore
execQueue chan *Job
ticker *Ticker
scheduler scheduler
evalHandler evalHandler
ruleReader ruleReader
log log.Logger
resultHandler resultHandler
usageStatsService usagestats.Service
tracer tracing.Tracer
sqlStore AlertStore
dashAlertExtractor DashAlertExtractor
}
// IsDisabled returns true if the alerting service is disabled for this instance.
@ -65,16 +66,18 @@ func (e *AlertEngine) IsDisabled() bool {
// ProvideAlertEngine returns a new AlertEngine.
func ProvideAlertEngine(renderer rendering.Service, bus bus.Bus, requestValidator models.PluginRequestValidator,
dataService legacydata.RequestHandler, usageStatsService usagestats.Service, encryptionService encryption.Internal,
notificationService *notifications.NotificationService, tracer tracing.Tracer, sqlStore AlertStore, cfg *setting.Cfg) *AlertEngine {
notificationService *notifications.NotificationService, tracer tracing.Tracer, sqlStore AlertStore, cfg *setting.Cfg,
dashAlertExtractor DashAlertExtractor) *AlertEngine {
e := &AlertEngine{
Cfg: cfg,
RenderService: renderer,
Bus: bus,
RequestValidator: requestValidator,
DataService: dataService,
usageStatsService: usageStatsService,
tracer: tracer,
sqlStore: sqlStore,
Cfg: cfg,
RenderService: renderer,
Bus: bus,
RequestValidator: requestValidator,
DataService: dataService,
usageStatsService: usageStatsService,
tracer: tracer,
sqlStore: sqlStore,
dashAlertExtractor: dashAlertExtractor,
}
e.ticker = NewTicker(time.Now(), time.Second*0, clock.New(), 1)
e.execQueue = make(chan *Job, 1000)

View File

@ -24,7 +24,7 @@ func TestEngineTimeouts(t *testing.T) {
usMock := &usagestats.UsageStatsMock{T: t}
tracer, err := tracing.InitializeTracerForTest()
require.NoError(t, err)
engine := ProvideAlertEngine(nil, nil, nil, nil, usMock, ossencryption.ProvideService(), nil, tracer, nil, setting.NewCfg())
engine := ProvideAlertEngine(nil, nil, nil, nil, usMock, ossencryption.ProvideService(), nil, tracer, nil, setting.NewCfg(), nil)
setting.AlertingNotificationTimeout = 30 * time.Second
setting.AlertingMaxAttempts = 3
engine.resultHandler = &FakeResultHandler{}

View File

@ -102,7 +102,7 @@ func TestEngineProcessJob(t *testing.T) {
require.NoError(t, err)
store := &AlertStoreMock{}
engine := ProvideAlertEngine(nil, bus, nil, nil, usMock, ossencryption.ProvideService(), nil, tracer, store, setting.NewCfg())
engine := ProvideAlertEngine(nil, bus, nil, nil, usMock, ossencryption.ProvideService(), nil, tracer, store, setting.NewCfg(), nil)
setting.AlertingEvaluationTimeout = 30 * time.Second
setting.AlertingNotificationTimeout = 30 * time.Second
setting.AlertingMaxAttempts = 3

View File

@ -6,31 +6,34 @@ import (
"errors"
"fmt"
"github.com/grafana/grafana/pkg/bus"
"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/datasources"
"github.com/grafana/grafana/pkg/services/datasources/permissions"
)
// DashAlertExtractor extracts alerts from the dashboard json.
type DashAlertExtractor struct {
User *models.SignedInUser
Dash *models.Dashboard
OrgID int64
log log.Logger
type DashAlertExtractor interface {
GetAlerts(ctx context.Context, dashAlertInfo DashAlertInfo) ([]*models.Alert, error)
ValidateAlerts(ctx context.Context, dashAlertInfo DashAlertInfo) error
}
// NewDashAlertExtractor returns a new DashAlertExtractor.
func NewDashAlertExtractor(dash *models.Dashboard, orgID int64, user *models.SignedInUser) *DashAlertExtractor {
return &DashAlertExtractor{
User: user,
Dash: dash,
OrgID: orgID,
log: log.New("alerting.extractor"),
// DashAlertExtractorService extracts alerts from the dashboard json.
type DashAlertExtractorService struct {
datasourcePermissionsService permissions.DatasourcePermissionsService
datasourceService datasources.DataSourceService
log log.Logger
}
func ProvideDashAlertExtractorService(datasourcePermissionsService permissions.DatasourcePermissionsService, datasourceService datasources.DataSourceService) *DashAlertExtractorService {
return &DashAlertExtractorService{
datasourcePermissionsService: datasourcePermissionsService,
datasourceService: datasourceService,
log: log.New("alerting.extractor"),
}
}
func (e *DashAlertExtractor) lookupQueryDataSource(ctx context.Context, panel *simplejson.Json, panelQuery *simplejson.Json) (*models.DataSource, error) {
func (e *DashAlertExtractorService) lookupQueryDataSource(ctx context.Context, panel *simplejson.Json, panelQuery *simplejson.Json, orgID int64) (*models.DataSource, error) {
dsName := ""
dsUid := ""
@ -47,15 +50,15 @@ func (e *DashAlertExtractor) lookupQueryDataSource(ctx context.Context, panel *s
}
if dsName == "" && dsUid == "" {
query := &models.GetDefaultDataSourceQuery{OrgId: e.OrgID}
if err := bus.Dispatch(ctx, query); err != nil {
query := &models.GetDefaultDataSourceQuery{OrgId: orgID}
if err := e.datasourceService.GetDefaultDataSource(ctx, query); err != nil {
return nil, err
}
return query.Result, nil
}
query := &models.GetDataSourceQuery{Name: dsName, Uid: dsUid, OrgId: e.OrgID}
if err := bus.Dispatch(ctx, query); err != nil {
query := &models.GetDataSourceQuery{Name: dsName, Uid: dsUid, OrgId: orgID}
if err := e.datasourceService.GetDataSource(ctx, query); err != nil {
return nil, err
}
@ -101,7 +104,7 @@ func UAEnabled(ctx context.Context) bool {
return enabled
}
func (e *DashAlertExtractor) getAlertFromPanels(ctx context.Context, jsonWithPanels *simplejson.Json, validateAlertFunc func(*models.Alert) bool, logTranslationFailures bool) ([]*models.Alert, error) {
func (e *DashAlertExtractorService) getAlertFromPanels(ctx context.Context, jsonWithPanels *simplejson.Json, validateAlertFunc func(*models.Alert) bool, logTranslationFailures bool, dashAlertInfo DashAlertInfo) ([]*models.Alert, error) {
alerts := make([]*models.Alert, 0)
for _, panelObj := range jsonWithPanels.Get("panels").MustArray() {
@ -111,7 +114,7 @@ func (e *DashAlertExtractor) getAlertFromPanels(ctx context.Context, jsonWithPan
// check if the panel is collapsed
if collapsed && collapsedJSON.MustBool() {
// extract alerts from sub panels for collapsed panels
alertSlice, err := e.getAlertFromPanels(ctx, panel, validateAlertFunc, logTranslationFailures)
alertSlice, err := e.getAlertFromPanels(ctx, panel, validateAlertFunc, logTranslationFailures, dashAlertInfo)
if err != nil {
return nil, err
}
@ -143,8 +146,8 @@ func (e *DashAlertExtractor) getAlertFromPanels(ctx context.Context, jsonWithPan
Err: validationErr.Err,
PanelID: panelID,
}
if e.Dash != nil {
ve.DashboardID = e.Dash.Id
if dashAlertInfo.Dash != nil {
ve.DashboardID = dashAlertInfo.Dash.Id
}
return ve
}
@ -170,8 +173,8 @@ func (e *DashAlertExtractor) getAlertFromPanels(ctx context.Context, jsonWithPan
}
alert := &models.Alert{
DashboardId: e.Dash.Id,
OrgId: e.OrgID,
DashboardId: dashAlertInfo.Dash.Id,
OrgId: dashAlertInfo.OrgID,
PanelId: panelID,
Id: jsonAlert.Get("id").MustInt64(),
Name: jsonAlert.Get("name").MustString(),
@ -198,24 +201,21 @@ func (e *DashAlertExtractor) getAlertFromPanels(ctx context.Context, jsonWithPan
return nil, ValidationError{Reason: reason}
}
datasource, err := e.lookupQueryDataSource(ctx, panel, panelQuery)
datasource, err := e.lookupQueryDataSource(ctx, panel, panelQuery, dashAlertInfo.OrgID)
if err != nil {
return nil, err
}
dsFilterQuery := models.DatasourcesPermissionFilterQuery{
User: e.User,
User: dashAlertInfo.User,
Datasources: []*models.DataSource{datasource},
}
if err := bus.Dispatch(ctx, &dsFilterQuery); err != nil {
if !errors.Is(err, bus.ErrHandlerNotFound) {
return nil, err
}
} else {
if len(dsFilterQuery.Result) == 0 {
return nil, models.ErrDataSourceAccessDenied
}
if err := e.datasourcePermissionsService.FilterDatasourcesBasedOnQueryPermissions(ctx, &dsFilterQuery); err != nil {
return nil, err
}
if len(dsFilterQuery.Result) == 0 {
return nil, models.ErrDataSourceAccessDenied
}
jsonQuery.SetPath([]string{"datasourceId"}, datasource.Id)
@ -250,12 +250,12 @@ func validateAlertRule(alert *models.Alert) bool {
}
// GetAlerts extracts alerts from the dashboard json and does full validation on the alert json data.
func (e *DashAlertExtractor) GetAlerts(ctx context.Context) ([]*models.Alert, error) {
return e.extractAlerts(ctx, validateAlertRule, true)
func (e *DashAlertExtractorService) GetAlerts(ctx context.Context, dashAlertInfo DashAlertInfo) ([]*models.Alert, error) {
return e.extractAlerts(ctx, validateAlertRule, true, dashAlertInfo)
}
func (e *DashAlertExtractor) extractAlerts(ctx context.Context, validateFunc func(alert *models.Alert) bool, logTranslationFailures bool) ([]*models.Alert, error) {
dashboardJSON, err := copyJSON(e.Dash.Data)
func (e *DashAlertExtractorService) extractAlerts(ctx context.Context, validateFunc func(alert *models.Alert) bool, logTranslationFailures bool, dashAlertInfo DashAlertInfo) ([]*models.Alert, error) {
dashboardJSON, err := copyJSON(dashAlertInfo.Dash.Data)
if err != nil {
return nil, err
}
@ -268,7 +268,7 @@ func (e *DashAlertExtractor) extractAlerts(ctx context.Context, validateFunc fun
if len(rows) > 0 {
for _, rowObj := range rows {
row := simplejson.NewFromAny(rowObj)
a, err := e.getAlertFromPanels(ctx, row, validateFunc, logTranslationFailures)
a, err := e.getAlertFromPanels(ctx, row, validateFunc, logTranslationFailures, dashAlertInfo)
if err != nil {
return nil, err
}
@ -276,7 +276,7 @@ func (e *DashAlertExtractor) extractAlerts(ctx context.Context, validateFunc fun
alerts = append(alerts, a...)
}
} else {
a, err := e.getAlertFromPanels(ctx, dashboardJSON, validateFunc, logTranslationFailures)
a, err := e.getAlertFromPanels(ctx, dashboardJSON, validateFunc, logTranslationFailures, dashAlertInfo)
if err != nil {
return nil, err
}
@ -290,9 +290,9 @@ func (e *DashAlertExtractor) extractAlerts(ctx context.Context, validateFunc fun
// ValidateAlerts validates alerts in the dashboard json but does not require a valid dashboard id
// in the first validation pass.
func (e *DashAlertExtractor) ValidateAlerts(ctx context.Context) error {
func (e *DashAlertExtractorService) ValidateAlerts(ctx context.Context, dashAlertInfo DashAlertInfo) error {
_, err := e.extractAlerts(ctx, func(alert *models.Alert) bool {
return alert.OrgId != 0 && alert.PanelId != 0
}, false)
}, false, dashAlertInfo)
return err
}

View File

@ -6,9 +6,10 @@ import (
"testing"
"time"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/datasources"
"github.com/grafana/grafana/pkg/services/datasources/permissions"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/stretchr/testify/require"
)
@ -21,40 +22,24 @@ func TestAlertRuleExtraction(t *testing.T) {
// mock data
defaultDs := &models.DataSource{Id: 12, OrgId: 1, Name: "I am default", IsDefault: true, Uid: "def-uid"}
graphite2Ds := &models.DataSource{Id: 15, OrgId: 1, Name: "graphite2", Uid: "graphite2-uid"}
influxDBDs := &models.DataSource{Id: 16, OrgId: 1, Name: "InfluxDB", Uid: "InfluxDB-uid"}
prom := &models.DataSource{Id: 17, OrgId: 1, Name: "Prometheus", Uid: "Prometheus-uid"}
bus.AddHandler("test", func(ctx context.Context, query *models.GetDefaultDataSourceQuery) error {
query.Result = defaultDs
return nil
})
bus.AddHandler("test", func(ctx context.Context, query *models.GetDataSourceQuery) error {
if query.Name == defaultDs.Name || query.Uid == defaultDs.Uid {
query.Result = defaultDs
}
if query.Name == graphite2Ds.Name || query.Uid == graphite2Ds.Uid {
query.Result = graphite2Ds
}
if query.Name == influxDBDs.Name || query.Uid == influxDBDs.Uid {
query.Result = influxDBDs
}
if query.Name == prom.Name || query.Uid == prom.Uid {
query.Result = prom
}
return nil
})
json, err := ioutil.ReadFile("./testdata/graphite-alert.json")
require.Nil(t, err)
dsPermissions := permissions.NewMockDatasourcePermissionService()
dsPermissions.DsResult = []*models.DataSource{
{
Id: 1,
},
}
dsService := &fakeDatasourceService{ExpectedDatasource: defaultDs}
extractor := ProvideDashAlertExtractorService(dsPermissions, dsService)
t.Run("Parsing alert rules from dashboard json", func(t *testing.T) {
dashJSON, err := simplejson.NewJson(json)
require.Nil(t, err)
dash := models.NewDashboardFromJson(dashJSON)
getTarget := func(j *simplejson.Json) string {
rowObj := j.Get("rows").MustArray()[0]
row := simplejson.NewFromAny(rowObj)
@ -67,8 +52,11 @@ func TestAlertRuleExtraction(t *testing.T) {
require.Equal(t, getTarget(dashJSON), "")
extractor := NewDashAlertExtractor(dash, 1, nil)
_, _ = extractor.GetAlerts(context.Background())
_, _ = extractor.GetAlerts(context.Background(), DashAlertInfo{
User: nil,
Dash: models.NewDashboardFromJson(dashJSON),
OrgID: 1,
})
require.Equal(t, getTarget(dashJSON), "")
})
@ -77,10 +65,12 @@ func TestAlertRuleExtraction(t *testing.T) {
dashJSON, err := simplejson.NewJson(json)
require.Nil(t, err)
dash := models.NewDashboardFromJson(dashJSON)
extractor := NewDashAlertExtractor(dash, 1, nil)
alerts, err := extractor.GetAlerts(context.Background())
dsService.ExpectedDatasource = &models.DataSource{Id: 12}
alerts, err := extractor.GetAlerts(context.Background(), DashAlertInfo{
User: nil,
Dash: models.NewDashboardFromJson(dashJSON),
OrgID: 1,
})
require.Nil(t, err)
@ -127,10 +117,12 @@ func TestAlertRuleExtraction(t *testing.T) {
dashJSON, err := simplejson.NewJson(panelWithoutID)
require.Nil(t, err)
dash := models.NewDashboardFromJson(dashJSON)
extractor := NewDashAlertExtractor(dash, 1, nil)
_, err = extractor.GetAlerts(context.Background())
_, err = extractor.GetAlerts(context.Background(), DashAlertInfo{
User: nil,
Dash: models.NewDashboardFromJson(dashJSON),
OrgID: 1,
})
require.NotNil(t, err)
})
@ -141,10 +133,12 @@ func TestAlertRuleExtraction(t *testing.T) {
dashJSON, err := simplejson.NewJson(panelWithIDZero)
require.Nil(t, err)
dash := models.NewDashboardFromJson(dashJSON)
extractor := NewDashAlertExtractor(dash, 1, nil)
_, err = extractor.GetAlerts(context.Background())
_, err = extractor.GetAlerts(context.Background(), DashAlertInfo{
User: nil,
Dash: models.NewDashboardFromJson(dashJSON),
OrgID: 1,
})
require.NotNil(t, err)
})
@ -154,10 +148,12 @@ func TestAlertRuleExtraction(t *testing.T) {
require.Nil(t, err)
dashJSON, err := simplejson.NewJson(panelWithQuery)
require.Nil(t, err)
dash := models.NewDashboardFromJson(dashJSON)
extractor := NewDashAlertExtractor(dash, 1, nil)
_, err = extractor.GetAlerts(WithUAEnabled(context.Background(), true))
_, err = extractor.GetAlerts(WithUAEnabled(context.Background(), true), DashAlertInfo{
User: nil,
Dash: models.NewDashboardFromJson(dashJSON),
OrgID: 1,
})
require.Equal(t, "alert validation error: Alert on PanelId: 2 refers to query(B) that cannot be found. Legacy alerting queries are not able to be removed at this time in order to preserve the ability to rollback to previous versions of Grafana", err.Error())
})
@ -167,10 +163,13 @@ func TestAlertRuleExtraction(t *testing.T) {
dashJSON, err := simplejson.NewJson(panelWithoutSpecifiedDatasource)
require.Nil(t, err)
dash := models.NewDashboardFromJson(dashJSON)
extractor := NewDashAlertExtractor(dash, 1, nil)
alerts, err := extractor.GetAlerts(context.Background())
dsService.ExpectedDatasource = &models.DataSource{Id: 12}
alerts, err := extractor.GetAlerts(context.Background(), DashAlertInfo{
User: nil,
Dash: models.NewDashboardFromJson(dashJSON),
OrgID: 1,
})
require.Nil(t, err)
condition := simplejson.NewFromAny(alerts[0].Settings.Get("conditions").MustArray()[0])
@ -184,10 +183,12 @@ func TestAlertRuleExtraction(t *testing.T) {
dashJSON, err := simplejson.NewJson(json)
require.Nil(t, err)
dash := models.NewDashboardFromJson(dashJSON)
extractor := NewDashAlertExtractor(dash, 1, nil)
alerts, err := extractor.GetAlerts(context.Background())
alerts, err := extractor.GetAlerts(context.Background(), DashAlertInfo{
User: nil,
Dash: models.NewDashboardFromJson(dashJSON),
OrgID: 1,
})
require.Nil(t, err)
require.Len(t, alerts, 2)
@ -209,10 +210,12 @@ func TestAlertRuleExtraction(t *testing.T) {
dashJSON, err := simplejson.NewJson(json)
require.Nil(t, err)
dash := models.NewDashboardFromJson(dashJSON)
extractor := NewDashAlertExtractor(dash, 1, nil)
alerts, err := extractor.GetAlerts(context.Background())
alerts, err := extractor.GetAlerts(context.Background(), DashAlertInfo{
User: nil,
Dash: models.NewDashboardFromJson(dashJSON),
OrgID: 1,
})
require.Nil(t, err)
require.Len(t, alerts, 1)
@ -235,9 +238,12 @@ func TestAlertRuleExtraction(t *testing.T) {
require.Nil(t, err)
dash := models.NewDashboardFromJson(dashJSON)
extractor := NewDashAlertExtractor(dash, 1, nil)
alerts, err := extractor.GetAlerts(context.Background())
alerts, err := extractor.GetAlerts(context.Background(), DashAlertInfo{
User: nil,
Dash: dash,
OrgID: 1,
})
require.Nil(t, err)
require.Len(t, alerts, 4)
@ -249,14 +255,17 @@ func TestAlertRuleExtraction(t *testing.T) {
dashJSON, err := simplejson.NewJson(json)
require.Nil(t, err)
dash := models.NewDashboardFromJson(dashJSON)
extractor := NewDashAlertExtractor(dash, 1, nil)
err = extractor.ValidateAlerts(context.Background())
dashAlertInfo := DashAlertInfo{
User: nil,
Dash: models.NewDashboardFromJson(dashJSON),
OrgID: 1,
}
err = extractor.ValidateAlerts(context.Background(), dashAlertInfo)
require.Nil(t, err)
_, err = extractor.GetAlerts(context.Background())
_, err = extractor.GetAlerts(context.Background(), dashAlertInfo)
require.Equal(t, err.Error(), "alert validation error: Panel id is not correct, alertName=Influxdb, panelId=1")
})
@ -266,14 +275,18 @@ func TestAlertRuleExtraction(t *testing.T) {
dashJSON, err := simplejson.NewJson(json)
require.Nil(t, err)
dash := models.NewDashboardFromJson(dashJSON)
extractor := NewDashAlertExtractor(dash, 1, nil)
err = extractor.ValidateAlerts(context.Background())
dsService.ExpectedDatasource = graphite2Ds
dashAlertInfo := DashAlertInfo{
User: nil,
Dash: models.NewDashboardFromJson(dashJSON),
OrgID: 1,
}
err = extractor.ValidateAlerts(context.Background(), dashAlertInfo)
require.Nil(t, err)
alerts, err := extractor.GetAlerts(context.Background())
alerts, err := extractor.GetAlerts(context.Background(), dashAlertInfo)
require.Nil(t, err)
condition := simplejson.NewFromAny(alerts[0].Settings.Get("conditions").MustArray()[0])
@ -281,3 +294,18 @@ func TestAlertRuleExtraction(t *testing.T) {
require.EqualValues(t, 15, query.Get("datasourceId").MustInt64())
})
}
type fakeDatasourceService struct {
ExpectedDatasource *models.DataSource
datasources.DataSourceService
}
func (f *fakeDatasourceService) GetDefaultDataSource(ctx context.Context, query *models.GetDefaultDataSourceQuery) error {
query.Result = f.ExpectedDatasource
return nil
}
func (f *fakeDatasourceService) GetDataSource(ctx context.Context, query *models.GetDataSourceQuery) error {
query.Result = f.ExpectedDatasource
return nil
}

View File

@ -4,6 +4,7 @@ import (
"sync"
"github.com/grafana/grafana/pkg/components/null"
"github.com/grafana/grafana/pkg/models"
)
// Job holds state about when the alert rule should be evaluated.
@ -42,3 +43,9 @@ type EvalMatch struct {
Metric string `json:"metric"`
Tags map[string]string `json:"tags"`
}
type DashAlertInfo struct {
User *models.SignedInUser
Dash *models.Dashboard
OrgID int64
}

View File

@ -11,9 +11,12 @@ import (
// AlertTest makes a test alert.
func (e *AlertEngine) AlertTest(orgID int64, dashboard *simplejson.Json, panelID int64, user *models.SignedInUser) (*EvalContext, error) {
dash := models.NewDashboardFromJson(dashboard)
extractor := NewDashAlertExtractor(dash, orgID, user)
alerts, err := extractor.GetAlerts(context.Background())
dashInfo := DashAlertInfo{
User: user,
Dash: dash,
OrgID: orgID,
}
alerts, err := e.dashAlertExtractor.GetAlerts(context.Background(), dashInfo)
if err != nil {
return nil, err
}

View File

@ -19,14 +19,16 @@ import (
)
type DashboardServiceImpl struct {
dashboardStore m.Store
log log.Logger
dashboardStore m.Store
dashAlertExtractor alerting.DashAlertExtractor
log log.Logger
}
func ProvideDashboardService(store m.Store) *DashboardServiceImpl {
func ProvideDashboardService(store m.Store, dashAlertExtractor alerting.DashAlertExtractor) *DashboardServiceImpl {
return &DashboardServiceImpl{
dashboardStore: store,
log: log.New("dashboard-service"),
dashboardStore: store,
dashAlertExtractor: dashAlertExtractor,
log: log.New("dashboard-service"),
}
}
@ -74,7 +76,8 @@ func (dr *DashboardServiceImpl) BuildSaveDashboardCommand(ctx context.Context, d
}
if shouldValidateAlerts {
if err := validateAlerts(ctx, dash, dto.User); err != nil {
dashAlertInfo := alerting.DashAlertInfo{Dash: dash, User: dto.User, OrgID: dash.OrgId}
if err := dr.dashAlertExtractor.ValidateAlerts(ctx, dashAlertInfo); err != nil {
return nil, err
}
}
@ -139,11 +142,6 @@ func (dr *DashboardServiceImpl) DeleteOrphanedProvisionedDashboards(ctx context.
return dr.dashboardStore.DeleteOrphanedProvisionedDashboards(ctx, cmd)
}
var validateAlerts = func(ctx context.Context, dash *models.Dashboard, user *models.SignedInUser) error {
extractor := alerting.NewDashAlertExtractor(dash, dash.OrgId, user)
return extractor.ValidateAlerts(ctx)
}
func validateDashboardRefreshInterval(dash *models.Dashboard) error {
if setting.MinRefreshInterval == "" {
return nil
@ -171,19 +169,6 @@ func validateDashboardRefreshInterval(dash *models.Dashboard) error {
return nil
}
// UpdateAlerting updates alerting.
//
// Stubbable by tests.
var UpdateAlerting = func(ctx context.Context, store m.Store, orgID int64, dashboard *models.Dashboard, user *models.SignedInUser) error {
extractor := alerting.NewDashAlertExtractor(dashboard, orgID, user)
alerts, err := extractor.GetAlerts(ctx)
if err != nil {
return err
}
return store.SaveAlerts(ctx, dashboard.Id, alerts)
}
func (dr *DashboardServiceImpl) SaveProvisionedDashboard(ctx context.Context, dto *m.SaveDashboardDTO,
provisioning *models.DashboardProvisioning) (*models.Dashboard, error) {
if err := validateDashboardRefreshInterval(dto.Dashboard); err != nil {
@ -210,7 +195,19 @@ func (dr *DashboardServiceImpl) SaveProvisionedDashboard(ctx context.Context, dt
}
// alerts
if err := UpdateAlerting(ctx, dr.dashboardStore, dto.OrgId, dash, dto.User); err != nil {
dashAlertInfo := alerting.DashAlertInfo{
User: dto.User,
Dash: dash,
OrgID: dto.OrgId,
}
alerts, err := dr.dashAlertExtractor.GetAlerts(ctx, dashAlertInfo)
if err != nil {
return nil, err
}
err = dr.dashboardStore.SaveAlerts(ctx, dash.Id, alerts)
if err != nil {
return nil, err
}
@ -232,7 +229,19 @@ func (dr *DashboardServiceImpl) SaveFolderForProvisionedDashboards(ctx context.C
return nil, err
}
if err := UpdateAlerting(ctx, dr.dashboardStore, dto.OrgId, dash, dto.User); err != nil {
dashAlertInfo := alerting.DashAlertInfo{
User: dto.User,
Dash: dash,
OrgID: dto.OrgId,
}
alerts, err := dr.dashAlertExtractor.GetAlerts(ctx, dashAlertInfo)
if err != nil {
return nil, err
}
err = dr.dashboardStore.SaveAlerts(ctx, dash.Id, alerts)
if err != nil {
return nil, err
}
@ -258,7 +267,19 @@ func (dr *DashboardServiceImpl) SaveDashboard(ctx context.Context, dto *m.SaveDa
return nil, fmt.Errorf("saving dashboard failed: %w", err)
}
if err := UpdateAlerting(ctx, dr.dashboardStore, dto.OrgId, dash, dto.User); err != nil {
dashAlertInfo := alerting.DashAlertInfo{
User: dto.User,
Dash: dash,
OrgID: dto.OrgId,
}
alerts, err := dr.dashAlertExtractor.GetAlerts(ctx, dashAlertInfo)
if err != nil {
return nil, err
}
err = dr.dashboardStore.SaveAlerts(ctx, dash.Id, alerts)
if err != nil {
return nil, err
}

View File

@ -5,6 +5,7 @@ package service
import (
"context"
"github.com/grafana/grafana/pkg/services/alerting"
"testing"
"github.com/grafana/grafana/pkg/components/simplejson"
@ -21,14 +22,6 @@ const testOrgID int64 = 1
func TestIntegratedDashboardService(t *testing.T) {
t.Run("Given saved folders and dashboards in organization A", func(t *testing.T) {
origUpdateAlerting := UpdateAlerting
t.Cleanup(func() {
UpdateAlerting = origUpdateAlerting
})
UpdateAlerting = func(ctx context.Context, store dashbboardservice.Store, orgID int64, dashboard *models.Dashboard, user *models.SignedInUser) error {
return nil
}
// Basic validation tests
permissionScenario(t, "When saving a dashboard with non-existing id", true,
@ -861,7 +854,7 @@ func callSaveWithResult(t *testing.T, cmd models.SaveDashboardCommand, sqlStore
dto := toSaveDashboardDto(cmd)
dashboardStore := database.ProvideDashboardStore(sqlStore)
res, err := ProvideDashboardService(dashboardStore).SaveDashboard(context.Background(), &dto, false)
res, err := ProvideDashboardService(dashboardStore, &dummyDashAlertExtractor{}).SaveDashboard(context.Background(), &dto, false)
require.NoError(t, err)
return res
@ -870,7 +863,7 @@ func callSaveWithResult(t *testing.T, cmd models.SaveDashboardCommand, sqlStore
func callSaveWithError(cmd models.SaveDashboardCommand, sqlStore *sqlstore.SQLStore) error {
dto := toSaveDashboardDto(cmd)
dashboardStore := database.ProvideDashboardStore(sqlStore)
_, err := ProvideDashboardService(dashboardStore).SaveDashboard(context.Background(), &dto, false)
_, err := ProvideDashboardService(dashboardStore, &dummyDashAlertExtractor{}).SaveDashboard(context.Background(), &dto, false)
return err
}
@ -897,7 +890,7 @@ func saveTestDashboard(t *testing.T, title string, orgID, folderID int64, sqlSto
}
dashboardStore := database.ProvideDashboardStore(sqlStore)
res, err := ProvideDashboardService(dashboardStore).SaveDashboard(context.Background(), &dto, false)
res, err := ProvideDashboardService(dashboardStore, &dummyDashAlertExtractor{}).SaveDashboard(context.Background(), &dto, false)
require.NoError(t, err)
return res
@ -925,7 +918,7 @@ func saveTestFolder(t *testing.T, title string, orgID int64, sqlStore *sqlstore.
}
dashboardStore := database.ProvideDashboardStore(sqlStore)
res, err := ProvideDashboardService(dashboardStore).SaveDashboard(context.Background(), &dto, false)
res, err := ProvideDashboardService(dashboardStore, &dummyDashAlertExtractor{}).SaveDashboard(context.Background(), &dto, false)
require.NoError(t, err)
return res
@ -942,3 +935,14 @@ func toSaveDashboardDto(cmd models.SaveDashboardCommand) dashbboardservice.SaveD
Overwrite: cmd.Overwrite,
}
}
type dummyDashAlertExtractor struct {
}
func (d *dummyDashAlertExtractor) GetAlerts(ctx context.Context, dashAlertInfo alerting.DashAlertInfo) ([]*models.Alert, error) {
return nil, nil
}
func (d *dummyDashAlertExtractor) ValidateAlerts(ctx context.Context, dashAlertInfo alerting.DashAlertInfo) error {
return nil
}

View File

@ -27,8 +27,9 @@ func TestDashboardService(t *testing.T) {
fakeStore := database.FakeDashboardStore{}
defer fakeStore.AssertExpectations(t)
service := &DashboardServiceImpl{
log: log.New("test.logger"),
dashboardStore: &fakeStore,
log: log.New("test.logger"),
dashboardStore: &fakeStore,
dashAlertExtractor: &dummyDashAlertExtractor{},
}
origNewDashboardGuardian := guardian.New

View File

@ -25,7 +25,7 @@ func TestFolderService(t *testing.T) {
store := &database.FakeDashboardStore{}
defer store.AssertExpectations(t)
service := ProvideFolderService(
&dashboards.FakeDashboardService{DashboardService: ProvideDashboardService(store)},
&dashboards.FakeDashboardService{DashboardService: ProvideDashboardService(store, nil)},
store,
nil,
)

View File

@ -1,4 +1,4 @@
package api
package permissions
import (
"context"

View File

@ -1,4 +1,4 @@
package api
package permissions
import (
"context"
@ -7,14 +7,14 @@ import (
)
type mockDatasourcePermissionService struct {
dsResult []*models.DataSource
DsResult []*models.DataSource
}
func (m *mockDatasourcePermissionService) FilterDatasourcesBasedOnQueryPermissions(ctx context.Context, cmd *models.DatasourcesPermissionFilterQuery) error {
cmd.Result = m.dsResult
cmd.Result = m.DsResult
return nil
}
func newMockDatasourcePermissionService() *mockDatasourcePermissionService {
func NewMockDatasourcePermissionService() *mockDatasourcePermissionService {
return &mockDatasourcePermissionService{}
}

View File

@ -13,6 +13,7 @@ import (
"github.com/grafana/grafana/pkg/api/response"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/alerting"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/dashboards/database"
dashboardservice "github.com/grafana/grafana/pkg/services/dashboards/manager"
@ -195,7 +196,8 @@ func createDashboard(t *testing.T, sqlStore *sqlstore.SQLStore, user models.Sign
}
dashboardStore := database.ProvideDashboardStore(sqlStore)
dashboard, err := dashboardservice.ProvideDashboardService(dashboardStore).SaveDashboard(context.Background(), dashItem, true)
dashAlertExtractor := alerting.ProvideDashAlertExtractorService(nil, nil)
dashboard, err := dashboardservice.ProvideDashboardService(dashboardStore, dashAlertExtractor).SaveDashboard(context.Background(), dashItem, true)
require.NoError(t, err)
return dashboard
@ -206,7 +208,7 @@ func createFolderWithACL(t *testing.T, sqlStore *sqlstore.SQLStore, title string
t.Helper()
dashboardStore := database.ProvideDashboardStore(sqlStore)
d := dashboardservice.ProvideDashboardService(dashboardStore)
d := dashboardservice.ProvideDashboardService(dashboardStore, nil)
s := dashboardservice.ProvideFolderService(d, dashboardStore, nil)
t.Logf("Creating folder with title and UID %q", title)
folder, err := s.CreateFolder(context.Background(), &user, user.OrgId, title, title)
@ -292,7 +294,7 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
role := models.ROLE_ADMIN
sqlStore := sqlstore.InitTestDB(t)
dashboardStore := database.ProvideDashboardStore(sqlStore)
dashboardService := dashboardservice.ProvideDashboardService(dashboardStore)
dashboardService := dashboardservice.ProvideDashboardService(dashboardStore, &alerting.DashAlertExtractorService{})
service := LibraryElementService{
Cfg: setting.NewCfg(),
SQLStore: sqlStore,

View File

@ -11,6 +11,7 @@ import (
"github.com/grafana/grafana/pkg/api/routing"
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/services/alerting"
"github.com/grafana/grafana/pkg/services/dashboards"
"github.com/grafana/grafana/pkg/services/dashboards/database"
dashboardservice "github.com/grafana/grafana/pkg/services/dashboards/manager"
@ -1416,7 +1417,8 @@ func createDashboard(t *testing.T, sqlStore *sqlstore.SQLStore, user *models.Sig
}
dashboadStore := database.ProvideDashboardStore(sqlStore)
dashboard, err := dashboardservice.ProvideDashboardService(dashboadStore).SaveDashboard(context.Background(), dashItem, true)
dashAlertService := alerting.ProvideDashAlertExtractorService(nil, nil)
dashboard, err := dashboardservice.ProvideDashboardService(dashboadStore, dashAlertService).SaveDashboard(context.Background(), dashItem, true)
require.NoError(t, err)
return dashboard
@ -1427,7 +1429,7 @@ func createFolderWithACL(t *testing.T, sqlStore *sqlstore.SQLStore, title string
t.Helper()
dashboardStore := database.ProvideDashboardStore(sqlStore)
d := dashboardservice.ProvideDashboardService(dashboardStore)
d := dashboardservice.ProvideDashboardService(dashboardStore, nil)
s := dashboardservice.ProvideFolderService(d, dashboardStore, nil)
t.Logf("Creating folder with title and UID %q", title)
folder, err := s.CreateFolder(context.Background(), user, user.OrgId, title, title)
@ -1516,7 +1518,7 @@ func testScenario(t *testing.T, desc string, fn func(t *testing.T, sc scenarioCo
role := models.ROLE_ADMIN
sqlStore := sqlstore.InitTestDB(t)
dashboardStore := database.ProvideDashboardStore(sqlStore)
folderService := dashboardservice.ProvideFolderService(dashboardservice.ProvideDashboardService(dashboardStore), dashboardStore, nil)
folderService := dashboardservice.ProvideFolderService(dashboardservice.ProvideDashboardService(dashboardStore, &alerting.DashAlertExtractorService{}), dashboardStore, nil)
elementService := libraryelements.ProvideService(cfg, sqlStore, routing.NewRouteRegister(), folderService)
service := LibraryPanelService{

View File

@ -41,7 +41,7 @@ func SetupTestEnv(t *testing.T, baseInterval time.Duration) (*ngalert.AlertNG, *
sqlStore := sqlstore.InitTestDB(t)
secretsService := secretsManager.SetupTestService(t, database.ProvideSecretsStore(sqlStore))
dashboardStore := databasestore.ProvideDashboardStore(sqlStore)
folderService := dashboardservice.ProvideFolderService(dashboardservice.ProvideDashboardService(dashboardStore), dashboardStore, nil)
folderService := dashboardservice.ProvideFolderService(dashboardservice.ProvideDashboardService(dashboardStore, nil), dashboardStore, nil)
ng, err := ngalert.ProvideService(
cfg, nil, routing.NewRouteRegister(), sqlStore,
nil, nil, nil, nil, secretsService, nil, m, folderService,

View File

@ -503,6 +503,7 @@ func (m *SQLStoreMock) GetDataSourcesByType(ctx context.Context, query *models.G
}
func (m *SQLStoreMock) GetDefaultDataSource(ctx context.Context, query *models.GetDefaultDataSourceQuery) error {
query.Result = m.ExpectedDatasource
return m.ExpectedError
}