Migrate to Wire for dependency injection (#32289)

Fixes #30144

Co-authored-by: dsotirakis <sotirakis.dim@gmail.com>
Co-authored-by: Marcus Efraimsson <marcus.efraimsson@gmail.com>
Co-authored-by: Ida Furjesova <ida.furjesova@grafana.com>
Co-authored-by: Jack Westbrook <jack.westbrook@gmail.com>
Co-authored-by: Will Browne <wbrowne@users.noreply.github.com>
Co-authored-by: Leon Sorokin <leeoniya@gmail.com>
Co-authored-by: Andrej Ocenas <mr.ocenas@gmail.com>
Co-authored-by: spinillos <selenepinillos@gmail.com>
Co-authored-by: Karl Persson <kalle.persson@grafana.com>
Co-authored-by: Leonard Gram <leo@xlson.com>
This commit is contained in:
Arve Knudsen
2021-08-25 15:11:22 +02:00
committed by GitHub
parent e61bc33163
commit 78596a6756
180 changed files with 2384 additions and 2401 deletions

View File

@@ -0,0 +1,44 @@
package apierrors
import (
"errors"
"github.com/grafana/grafana/pkg/api/response"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/util"
)
// ToFolderErrorResponse returns a different response status according to the folder error type
func ToFolderErrorResponse(err error) response.Response {
var dashboardErr models.DashboardErr
if ok := errors.As(err, &dashboardErr); ok {
return response.Error(dashboardErr.StatusCode, err.Error(), err)
}
if errors.Is(err, models.ErrFolderTitleEmpty) ||
errors.Is(err, models.ErrDashboardTypeMismatch) ||
errors.Is(err, models.ErrDashboardInvalidUid) ||
errors.Is(err, models.ErrDashboardUidTooLong) ||
errors.Is(err, models.ErrFolderContainsAlertRules) {
return response.Error(400, err.Error(), nil)
}
if errors.Is(err, models.ErrFolderAccessDenied) {
return response.Error(403, "Access denied", err)
}
if errors.Is(err, models.ErrFolderNotFound) {
return response.JSON(404, util.DynMap{"status": "not-found", "message": models.ErrFolderNotFound.Error()})
}
if errors.Is(err, models.ErrFolderSameNameExists) ||
errors.Is(err, models.ErrFolderWithSameUIDExists) {
return response.Error(409, err.Error(), nil)
}
if errors.Is(err, models.ErrFolderVersionMismatch) {
return response.JSON(412, util.DynMap{"status": "version-mismatch", "message": models.ErrFolderVersionMismatch.Error()})
}
return response.Error(500, "Folder API error", err)
}

View File

@@ -7,23 +7,23 @@ import (
"path/filepath"
"testing"
"github.com/stretchr/testify/require"
"gopkg.in/macaron.v1"
"github.com/grafana/grafana/pkg/api/response"
"github.com/grafana/grafana/pkg/api/routing"
"github.com/grafana/grafana/pkg/bus"
"github.com/grafana/grafana/pkg/infra/fs"
"github.com/grafana/grafana/pkg/infra/remotecache"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/registry"
"github.com/grafana/grafana/pkg/services/accesscontrol"
accesscontrolmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
"github.com/grafana/grafana/pkg/services/auth"
"github.com/grafana/grafana/pkg/services/auth/jwt"
"github.com/grafana/grafana/pkg/services/contexthandler"
"github.com/grafana/grafana/pkg/services/quota"
"github.com/grafana/grafana/pkg/services/rendering"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/setting"
"github.com/stretchr/testify/require"
"gopkg.in/macaron.v1"
)
func loggedInUserScenario(t *testing.T, desc string, url string, fn scenarioFunc) {
@@ -168,35 +168,7 @@ func getContextHandler(t *testing.T, cfg *setting.Cfg) *contexthandler.ContextHa
userAuthTokenSvc := auth.NewFakeUserAuthTokenService()
renderSvc := &fakeRenderService{}
authJWTSvc := models.NewFakeJWTService()
ctxHdlr := &contexthandler.ContextHandler{}
err := registry.BuildServiceGraph([]interface{}{cfg}, []*registry.Descriptor{
{
Name: sqlstore.ServiceName,
Instance: sqlStore,
},
{
Name: remotecache.ServiceName,
Instance: remoteCacheSvc,
},
{
Name: auth.ServiceName,
Instance: userAuthTokenSvc,
},
{
Name: rendering.ServiceName,
Instance: renderSvc,
},
{
Name: jwt.ServiceName,
Instance: authJWTSvc,
},
{
Name: contexthandler.ServiceName,
Instance: ctxHdlr,
},
})
require.NoError(t, err)
ctxHdlr := contexthandler.ProvideService(cfg, userAuthTokenSvc, authJWTSvc, remoteCacheSvc, renderSvc, sqlStore)
return ctxHdlr
}
@@ -236,6 +208,9 @@ func setupAccessControlScenarioContext(t *testing.T, cfg *setting.Cfg, url strin
hs := &HTTPServer{
Cfg: cfg,
RouteRegister: routing.NewRouteRegister(),
QuotaService: &quota.QuotaService{
Cfg: cfg,
},
AccessControl: accesscontrolmock.New().WithPermissions(permissions),
}

View File

@@ -23,6 +23,7 @@ import (
"github.com/grafana/grafana/pkg/services/live"
"github.com/grafana/grafana/pkg/services/provisioning"
"github.com/grafana/grafana/pkg/services/quota"
"github.com/grafana/grafana/pkg/services/sqlstore"
"github.com/grafana/grafana/pkg/setting"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -86,10 +87,8 @@ type testState struct {
}
func newTestLive(t *testing.T) *live.GrafanaLive {
gLive := live.NewGrafanaLive()
gLive.RouteRegister = routing.NewRouteRegister()
gLive.Cfg = &setting.Cfg{AppURL: "http://localhost:3000/"}
err := gLive.Init()
cfg := &setting.Cfg{AppURL: "http://localhost:3000/"}
gLive, err := live.ProvideService(nil, cfg, routing.NewRouteRegister(), nil, nil, nil, nil, sqlstore.InitTestDB(t))
require.NoError(t, err)
return gLive
}

View File

@@ -363,7 +363,7 @@ func GetDataSourceIdByName(c *models.ReqContext) response.Response {
// /api/datasources/:id/resources/*
func (hs *HTTPServer) CallDatasourceResource(c *models.ReqContext) {
datasourceID := c.ParamsInt64(":id")
ds, err := hs.DatasourceCache.GetDatasource(datasourceID, c.SignedInUser, c.SkipCache)
ds, err := hs.DataSourceCache.GetDatasource(datasourceID, c.SignedInUser, c.SkipCache)
if err != nil {
if errors.Is(err, models.ErrDataSourceAccessDenied) {
c.JsonApiErr(403, "Access denied to datasource", err)
@@ -431,7 +431,7 @@ func convertModelToDtos(ds *models.DataSource) dtos.DataSource {
func (hs *HTTPServer) CheckDatasourceHealth(c *models.ReqContext) response.Response {
datasourceID := c.ParamsInt64("id")
ds, err := hs.DatasourceCache.GetDatasource(datasourceID, c.SignedInUser, c.SkipCache)
ds, err := hs.DataSourceCache.GetDatasource(datasourceID, c.SignedInUser, c.SkipCache)
if err != nil {
if errors.Is(err, models.ErrDataSourceAccessDenied) {
return response.Error(403, "Access denied to datasource", err)

View File

@@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"github.com/grafana/grafana/pkg/api/apierrors"
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/api/response"
"github.com/grafana/grafana/pkg/models"
@@ -19,7 +20,7 @@ func (hs *HTTPServer) GetFolders(c *models.ReqContext) response.Response {
folders, err := s.GetFolders(c.QueryInt64("limit"), c.QueryInt64("page"))
if err != nil {
return ToFolderErrorResponse(err)
return apierrors.ToFolderErrorResponse(err)
}
result := make([]dtos.FolderSearchHit, 0)
@@ -39,7 +40,7 @@ func (hs *HTTPServer) GetFolderByUID(c *models.ReqContext) response.Response {
s := dashboards.NewFolderService(c.OrgId, c.SignedInUser, hs.SQLStore)
folder, err := s.GetFolderByUID(c.Params(":uid"))
if err != nil {
return ToFolderErrorResponse(err)
return apierrors.ToFolderErrorResponse(err)
}
g := guardian.New(folder.Id, c.OrgId, c.SignedInUser)
@@ -50,7 +51,7 @@ func (hs *HTTPServer) GetFolderByID(c *models.ReqContext) response.Response {
s := dashboards.NewFolderService(c.OrgId, c.SignedInUser, hs.SQLStore)
folder, err := s.GetFolderByID(c.ParamsInt64(":id"))
if err != nil {
return ToFolderErrorResponse(err)
return apierrors.ToFolderErrorResponse(err)
}
g := guardian.New(folder.Id, c.OrgId, c.SignedInUser)
@@ -61,7 +62,7 @@ func (hs *HTTPServer) CreateFolder(c *models.ReqContext, cmd models.CreateFolder
s := dashboards.NewFolderService(c.OrgId, c.SignedInUser, hs.SQLStore)
folder, err := s.CreateFolder(cmd.Title, cmd.Uid)
if err != nil {
return ToFolderErrorResponse(err)
return apierrors.ToFolderErrorResponse(err)
}
if hs.Cfg.EditorsCanAdmin {
@@ -79,7 +80,7 @@ func (hs *HTTPServer) UpdateFolder(c *models.ReqContext, cmd models.UpdateFolder
s := dashboards.NewFolderService(c.OrgId, c.SignedInUser, hs.SQLStore)
err := s.UpdateFolder(c.Params(":uid"), &cmd)
if err != nil {
return ToFolderErrorResponse(err)
return apierrors.ToFolderErrorResponse(err)
}
g := guardian.New(cmd.Result.Id, c.OrgId, c.SignedInUser)
@@ -93,12 +94,12 @@ func (hs *HTTPServer) DeleteFolder(c *models.ReqContext) response.Response { //
if errors.Is(err, libraryelements.ErrFolderHasConnectedLibraryElements) {
return response.Error(403, "Folder could not be deleted because it contains library elements in use", err)
}
return ToFolderErrorResponse(err)
return apierrors.ToFolderErrorResponse(err)
}
f, err := s.DeleteFolder(c.Params(":uid"), c.QueryBool("forceDeleteRules"))
if err != nil {
return ToFolderErrorResponse(err)
return apierrors.ToFolderErrorResponse(err)
}
return response.JSON(200, util.DynMap{
@@ -138,38 +139,3 @@ func toFolderDto(ctx context.Context, g guardian.DashboardGuardian, folder *mode
Version: folder.Version,
}
}
// ToFolderErrorResponse returns a different response status according to the folder error type
func ToFolderErrorResponse(err error) response.Response {
var dashboardErr models.DashboardErr
if ok := errors.As(err, &dashboardErr); ok {
return response.Error(dashboardErr.StatusCode, err.Error(), err)
}
if errors.Is(err, models.ErrFolderTitleEmpty) ||
errors.Is(err, models.ErrDashboardTypeMismatch) ||
errors.Is(err, models.ErrDashboardInvalidUid) ||
errors.Is(err, models.ErrDashboardUidTooLong) ||
errors.Is(err, models.ErrFolderContainsAlertRules) {
return response.Error(400, err.Error(), nil)
}
if errors.Is(err, models.ErrFolderAccessDenied) {
return response.Error(403, "Access denied", err)
}
if errors.Is(err, models.ErrFolderNotFound) {
return response.JSON(404, util.DynMap{"status": "not-found", "message": models.ErrFolderNotFound.Error()})
}
if errors.Is(err, models.ErrFolderSameNameExists) ||
errors.Is(err, models.ErrFolderWithSameUIDExists) {
return response.Error(409, err.Error(), nil)
}
if errors.Is(err, models.ErrFolderVersionMismatch) {
return response.JSON(412, util.DynMap{"status": "version-mismatch", "message": models.ErrFolderVersionMismatch.Error()})
}
return response.Error(500, "Folder API error", err)
}

View File

@@ -4,6 +4,7 @@ import (
"errors"
"time"
"github.com/grafana/grafana/pkg/api/apierrors"
"github.com/grafana/grafana/pkg/api/dtos"
"github.com/grafana/grafana/pkg/api/response"
"github.com/grafana/grafana/pkg/models"
@@ -17,13 +18,13 @@ func (hs *HTTPServer) GetFolderPermissionList(c *models.ReqContext) response.Res
folder, err := s.GetFolderByUID(c.Params(":uid"))
if err != nil {
return ToFolderErrorResponse(err)
return apierrors.ToFolderErrorResponse(err)
}
g := guardian.New(folder.Id, c.OrgId, c.SignedInUser)
if canAdmin, err := g.CanAdmin(); err != nil || !canAdmin {
return ToFolderErrorResponse(models.ErrFolderAccessDenied)
return apierrors.ToFolderErrorResponse(models.ErrFolderAccessDenied)
}
acl, err := g.GetAcl()
@@ -64,17 +65,17 @@ func (hs *HTTPServer) UpdateFolderPermissions(c *models.ReqContext, apiCmd dtos.
s := dashboards.NewFolderService(c.OrgId, c.SignedInUser, hs.SQLStore)
folder, err := s.GetFolderByUID(c.Params(":uid"))
if err != nil {
return ToFolderErrorResponse(err)
return apierrors.ToFolderErrorResponse(err)
}
g := guardian.New(folder.Id, c.OrgId, c.SignedInUser)
canAdmin, err := g.CanAdmin()
if err != nil {
return ToFolderErrorResponse(err)
return apierrors.ToFolderErrorResponse(err)
}
if !canAdmin {
return ToFolderErrorResponse(models.ErrFolderAccessDenied)
return apierrors.ToFolderErrorResponse(models.ErrFolderAccessDenied)
}
var items []*models.DashboardAcl

View File

@@ -14,6 +14,10 @@ import (
"sync"
"github.com/grafana/grafana/pkg/login/social"
"github.com/grafana/grafana/pkg/services/cleanup"
"github.com/grafana/grafana/pkg/services/ngalert"
"github.com/grafana/grafana/pkg/services/notifications"
"github.com/grafana/grafana/pkg/services/libraryelements"
"github.com/grafana/grafana/pkg/services/librarypanels"
"github.com/grafana/grafana/pkg/services/oauthtoken"
@@ -24,15 +28,16 @@ import (
"github.com/grafana/grafana/pkg/components/simplejson"
"github.com/grafana/grafana/pkg/infra/localcache"
"github.com/grafana/grafana/pkg/infra/log"
"github.com/grafana/grafana/pkg/infra/metrics"
"github.com/grafana/grafana/pkg/infra/remotecache"
"github.com/grafana/grafana/pkg/infra/tracing"
"github.com/grafana/grafana/pkg/infra/usagestats"
"github.com/grafana/grafana/pkg/middleware"
"github.com/grafana/grafana/pkg/models"
"github.com/grafana/grafana/pkg/plugins"
"github.com/grafana/grafana/pkg/plugins/backendplugin"
_ "github.com/grafana/grafana/pkg/plugins/backendplugin/manager"
"github.com/grafana/grafana/pkg/plugins/plugincontext"
"github.com/grafana/grafana/pkg/plugins/plugindashboards"
"github.com/grafana/grafana/pkg/registry"
"github.com/grafana/grafana/pkg/services/accesscontrol"
"github.com/grafana/grafana/pkg/services/alerting"
"github.com/grafana/grafana/pkg/services/contexthandler"
@@ -58,14 +63,6 @@ import (
"gopkg.in/macaron.v1"
)
func init() {
registry.Register(&registry.Descriptor{
Name: "HTTPServer",
Instance: &HTTPServer{},
InitPriority: registry.High,
})
}
type HTTPServer struct {
log log.Logger
macaron *macaron.Macaron
@@ -73,49 +70,128 @@ type HTTPServer struct {
httpSrv *http.Server
middlewares []macaron.Handler
PluginContextProvider *plugincontext.Provider `inject:""`
RouteRegister routing.RouteRegister `inject:""`
Bus bus.Bus `inject:""`
RenderService rendering.Service `inject:""`
Cfg *setting.Cfg `inject:""`
SettingsProvider setting.Provider `inject:""`
HooksService *hooks.HooksService `inject:""`
CacheService *localcache.CacheService `inject:""`
DatasourceCache datasources.CacheService `inject:""`
AuthTokenService models.UserTokenService `inject:""`
QuotaService *quota.QuotaService `inject:""`
RemoteCacheService *remotecache.RemoteCache `inject:""`
ProvisioningService provisioning.ProvisioningService `inject:""`
Login login.Service `inject:""`
License models.Licensing `inject:""`
AccessControl accesscontrol.AccessControl `inject:""`
BackendPluginManager backendplugin.Manager `inject:""`
DataProxy *datasourceproxy.DatasourceProxyService `inject:""`
PluginRequestValidator models.PluginRequestValidator `inject:""`
PluginManager plugins.Manager `inject:""`
SearchService *search.SearchService `inject:""`
ShortURLService shorturls.Service `inject:""`
Live *live.GrafanaLive `inject:""`
LivePushGateway *pushhttp.Gateway `inject:""`
ContextHandler *contexthandler.ContextHandler `inject:""`
SQLStore *sqlstore.SQLStore `inject:""`
DataService *tsdb.Service `inject:""`
PluginDashboardService *plugindashboards.Service `inject:""`
AlertEngine *alerting.AlertEngine `inject:""`
LoadSchemaService *schemaloader.SchemaLoaderService `inject:""`
LibraryPanelService librarypanels.Service `inject:""`
LibraryElementService libraryelements.Service `inject:""`
SocialService social.Service `inject:""`
OAuthTokenService *oauthtoken.Service `inject:""`
UsageStatsService usagestats.UsageStats
PluginContextProvider *plugincontext.Provider
RouteRegister routing.RouteRegister
Bus bus.Bus
RenderService rendering.Service
Cfg *setting.Cfg
SettingsProvider setting.Provider
HooksService *hooks.HooksService
CacheService *localcache.CacheService
DataSourceCache datasources.CacheService
AuthTokenService models.UserTokenService
QuotaService *quota.QuotaService
RemoteCacheService *remotecache.RemoteCache
ProvisioningService provisioning.ProvisioningService
Login login.Service
License models.Licensing
AccessControl accesscontrol.AccessControl
BackendPluginManager backendplugin.Manager
DataProxy *datasourceproxy.DataSourceProxyService
PluginRequestValidator models.PluginRequestValidator
PluginManager plugins.Manager
SearchService *search.SearchService
ShortURLService shorturls.Service
Live *live.GrafanaLive
LivePushGateway *pushhttp.Gateway
ContextHandler *contexthandler.ContextHandler
SQLStore *sqlstore.SQLStore
DataService *tsdb.Service
AlertEngine *alerting.AlertEngine
LoadSchemaService *schemaloader.SchemaLoaderService
AlertNG *ngalert.AlertNG
LibraryPanelService librarypanels.Service
LibraryElementService libraryelements.Service
notificationService *notifications.NotificationService
SocialService social.Service
OAuthTokenService oauthtoken.OAuthTokenService
Listener net.Listener
cleanUpService *cleanup.CleanUpService
tracingService *tracing.TracingService
internalMetricsSvc *metrics.InternalMetricsService
}
func (hs *HTTPServer) Init() error {
hs.log = log.New("http.server")
type ServerOptions struct {
Listener net.Listener
}
hs.macaron = hs.newMacaron()
func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routing.RouteRegister, bus bus.Bus,
renderService rendering.Service, licensing models.Licensing, hooksService *hooks.HooksService,
cacheService *localcache.CacheService, sqlStore *sqlstore.SQLStore,
dataService *tsdb.Service, alertEngine *alerting.AlertEngine,
usageStatsService *usagestats.UsageStatsService, pluginRequestValidator models.PluginRequestValidator,
pluginManager plugins.Manager, backendPM backendplugin.Manager, settingsProvider setting.Provider,
dataSourceCache datasources.CacheService, userTokenService models.UserTokenService,
cleanUpService *cleanup.CleanUpService, shortURLService shorturls.Service,
remoteCache *remotecache.RemoteCache, provisioningService provisioning.ProvisioningService,
loginService login.Service, accessControl accesscontrol.AccessControl,
dataSourceProxy *datasourceproxy.DataSourceProxyService, searchService *search.SearchService,
live *live.GrafanaLive, livePushGateway *pushhttp.Gateway, plugCtxProvider *plugincontext.Provider,
contextHandler *contexthandler.ContextHandler,
schemaService *schemaloader.SchemaLoaderService, alertNG *ngalert.AlertNG,
libraryPanelService librarypanels.Service, libraryElementService libraryelements.Service,
notificationService *notifications.NotificationService, tracingService *tracing.TracingService,
internalMetricsSvc *metrics.InternalMetricsService, quotaService *quota.QuotaService,
socialService social.Service, oauthTokenService oauthtoken.OAuthTokenService) (*HTTPServer, error) {
macaron.Env = cfg.Env
m := macaron.New()
// automatically set HEAD for every GET
m.SetAutoHead(true)
hs := &HTTPServer{
Cfg: cfg,
RouteRegister: routeRegister,
Bus: bus,
RenderService: renderService,
License: licensing,
HooksService: hooksService,
CacheService: cacheService,
SQLStore: sqlStore,
DataService: dataService,
AlertEngine: alertEngine,
UsageStatsService: usageStatsService,
PluginRequestValidator: pluginRequestValidator,
PluginManager: pluginManager,
BackendPluginManager: backendPM,
SettingsProvider: settingsProvider,
DataSourceCache: dataSourceCache,
AuthTokenService: userTokenService,
cleanUpService: cleanUpService,
ShortURLService: shortURLService,
RemoteCacheService: remoteCache,
ProvisioningService: provisioningService,
Login: loginService,
AccessControl: accessControl,
DataProxy: dataSourceProxy,
SearchService: searchService,
Live: live,
LivePushGateway: livePushGateway,
PluginContextProvider: plugCtxProvider,
ContextHandler: contextHandler,
LoadSchemaService: schemaService,
AlertNG: alertNG,
LibraryPanelService: libraryPanelService,
LibraryElementService: libraryElementService,
QuotaService: quotaService,
notificationService: notificationService,
tracingService: tracingService,
internalMetricsSvc: internalMetricsSvc,
log: log.New("http.server"),
macaron: m,
Listener: opts.Listener,
SocialService: socialService,
OAuthTokenService: oauthTokenService,
}
if hs.Listener != nil {
hs.log.Debug("Using provided listener")
}
hs.registerRoutes()
return hs.declareFixedRoles()
if err := hs.declareFixedRoles(); err != nil {
return nil, err
}
return hs, nil
}
func (hs *HTTPServer) AddMiddleware(middleware macaron.Handler) {
@@ -304,16 +380,6 @@ func (hs *HTTPServer) configureHttp2() error {
return nil
}
func (hs *HTTPServer) newMacaron() *macaron.Macaron {
macaron.Env = hs.Cfg.Env
m := macaron.New()
// automatically set HEAD for every GET
m.SetAutoHead(true)
return m
}
func (hs *HTTPServer) applyRoutes() {
// start with middlewares & static routes
hs.addMiddlewaresAndStaticRoutes()

View File

@@ -52,7 +52,7 @@ func (hs *HTTPServer) QueryMetricsV2(c *models.ReqContext, reqDTO dtos.MetricReq
// So only the datasource from the first query is needed. As all requests
// should be the same data source.
if i == 0 {
ds, err = hs.DatasourceCache.GetDatasource(datasourceID, c.SignedInUser, c.SkipCache)
ds, err = hs.DataSourceCache.GetDatasource(datasourceID, c.SignedInUser, c.SkipCache)
if err != nil {
return hs.handleGetDataSourceError(err, datasourceID)
}
@@ -122,7 +122,7 @@ func (hs *HTTPServer) handleExpressions(c *models.ReqContext, reqDTO dtos.Metric
if name != expr.DatasourceName {
// Expression requests have everything in one request, so need to check
// all data source queries for possible permission / not found issues.
if _, err = hs.DatasourceCache.GetDatasource(datasourceID, c.SignedInUser, c.SkipCache); err != nil {
if _, err = hs.DataSourceCache.GetDatasource(datasourceID, c.SignedInUser, c.SkipCache); err != nil {
return hs.handleGetDataSourceError(err, datasourceID)
}
}
@@ -170,7 +170,7 @@ func (hs *HTTPServer) QueryMetrics(c *models.ReqContext, reqDto dtos.MetricReque
return response.Error(http.StatusBadRequest, "Query missing datasourceId", nil)
}
ds, err := hs.DatasourceCache.GetDatasource(datasourceId, c.SignedInUser, c.SkipCache)
ds, err := hs.DataSourceCache.GetDatasource(datasourceId, c.SignedInUser, c.SkipCache)
if err != nil {
return hs.handleGetDataSourceError(err, datasourceId)
}

View File

@@ -4,6 +4,8 @@ import (
"net/http"
"strings"
"github.com/grafana/grafana/pkg/middleware"
"github.com/grafana/grafana/pkg/setting"
"gopkg.in/macaron.v1"
)
@@ -50,13 +52,17 @@ type RouteRegister interface {
type RegisterNamedMiddleware func(name string) macaron.Handler
func ProvideRegister(cfg *setting.Cfg) *RouteRegisterImpl {
return NewRouteRegister(middleware.ProvideRouteOperationName, middleware.RequestMetrics(cfg))
}
// NewRouteRegister creates a new RouteRegister with all middlewares sent as params
func NewRouteRegister(namedMiddleware ...RegisterNamedMiddleware) RouteRegister {
return &routeRegister{
prefix: "",
routes: []route{},
subfixHandlers: []macaron.Handler{},
namedMiddleware: namedMiddleware,
func NewRouteRegister(namedMiddlewares ...RegisterNamedMiddleware) *RouteRegisterImpl {
return &RouteRegisterImpl{
prefix: "",
routes: []route{},
subfixHandlers: []macaron.Handler{},
namedMiddlewares: namedMiddlewares,
}
}
@@ -66,15 +72,15 @@ type route struct {
handlers []macaron.Handler
}
type routeRegister struct {
prefix string
subfixHandlers []macaron.Handler
namedMiddleware []RegisterNamedMiddleware
routes []route
groups []*routeRegister
type RouteRegisterImpl struct {
prefix string
subfixHandlers []macaron.Handler
namedMiddlewares []RegisterNamedMiddleware
routes []route
groups []*RouteRegisterImpl
}
func (rr *routeRegister) Reset() {
func (rr *RouteRegisterImpl) Reset() {
if rr == nil {
return
}
@@ -84,7 +90,7 @@ func (rr *routeRegister) Reset() {
rr.subfixHandlers = nil
}
func (rr *routeRegister) Insert(pattern string, fn func(RouteRegister), handlers ...macaron.Handler) {
func (rr *RouteRegisterImpl) Insert(pattern string, fn func(RouteRegister), handlers ...macaron.Handler) {
// loop over all groups at current level
for _, g := range rr.groups {
// apply routes if the prefix matches the pattern
@@ -100,19 +106,19 @@ func (rr *routeRegister) Insert(pattern string, fn func(RouteRegister), handlers
}
}
func (rr *routeRegister) Group(pattern string, fn func(rr RouteRegister), handlers ...macaron.Handler) {
group := &routeRegister{
prefix: rr.prefix + pattern,
subfixHandlers: append(rr.subfixHandlers, handlers...),
routes: []route{},
namedMiddleware: rr.namedMiddleware,
func (rr *RouteRegisterImpl) Group(pattern string, fn func(rr RouteRegister), handlers ...macaron.Handler) {
group := &RouteRegisterImpl{
prefix: rr.prefix + pattern,
subfixHandlers: append(rr.subfixHandlers, handlers...),
routes: []route{},
namedMiddlewares: rr.namedMiddlewares,
}
fn(group)
rr.groups = append(rr.groups, group)
}
func (rr *routeRegister) Register(router Router) {
func (rr *RouteRegisterImpl) Register(router Router) {
for _, r := range rr.routes {
// GET requests have to be added to macaron routing using Get()
// Otherwise HEAD requests will not be allowed.
@@ -129,11 +135,11 @@ func (rr *routeRegister) Register(router Router) {
}
}
func (rr *routeRegister) route(pattern, method string, handlers ...macaron.Handler) {
func (rr *RouteRegisterImpl) route(pattern, method string, handlers ...macaron.Handler) {
h := make([]macaron.Handler, 0)
fullPattern := rr.prefix + pattern
for _, fn := range rr.namedMiddleware {
for _, fn := range rr.namedMiddlewares {
h = append(h, fn(fullPattern))
}
@@ -153,26 +159,26 @@ func (rr *routeRegister) route(pattern, method string, handlers ...macaron.Handl
})
}
func (rr *routeRegister) Get(pattern string, handlers ...macaron.Handler) {
func (rr *RouteRegisterImpl) Get(pattern string, handlers ...macaron.Handler) {
rr.route(pattern, http.MethodGet, handlers...)
}
func (rr *routeRegister) Post(pattern string, handlers ...macaron.Handler) {
func (rr *RouteRegisterImpl) Post(pattern string, handlers ...macaron.Handler) {
rr.route(pattern, http.MethodPost, handlers...)
}
func (rr *routeRegister) Delete(pattern string, handlers ...macaron.Handler) {
func (rr *RouteRegisterImpl) Delete(pattern string, handlers ...macaron.Handler) {
rr.route(pattern, http.MethodDelete, handlers...)
}
func (rr *routeRegister) Put(pattern string, handlers ...macaron.Handler) {
func (rr *RouteRegisterImpl) Put(pattern string, handlers ...macaron.Handler) {
rr.route(pattern, http.MethodPut, handlers...)
}
func (rr *routeRegister) Patch(pattern string, handlers ...macaron.Handler) {
func (rr *RouteRegisterImpl) Patch(pattern string, handlers ...macaron.Handler) {
rr.route(pattern, http.MethodPatch, handlers...)
}
func (rr *routeRegister) Any(pattern string, handlers ...macaron.Handler) {
func (rr *RouteRegisterImpl) Any(pattern string, handlers ...macaron.Handler) {
rr.route(pattern, "*", handlers...)
}