mirror of
https://github.com/grafana/grafana.git
synced 2025-01-13 09:32:12 -06:00
backend/datasources: move datasources models into the datasources service package (#51267)
* backend/datasources: move datasources models into the datasources service pkg
This commit is contained in:
parent
78c012df65
commit
945f015770
@ -11,6 +11,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/alerting"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/guardian"
|
||||
"github.com/grafana/grafana/pkg/services/ngalert/notifier"
|
||||
"github.com/grafana/grafana/pkg/services/search"
|
||||
@ -151,7 +152,7 @@ func (hs *HTTPServer) AlertTest(c *models.ReqContext) response.Response {
|
||||
if errors.As(err, &validationErr) {
|
||||
return response.Error(422, validationErr.Error(), nil)
|
||||
}
|
||||
if errors.Is(err, models.ErrDataSourceAccessDenied) {
|
||||
if errors.Is(err, datasources.ErrDataSourceAccessDenied) {
|
||||
return response.Error(403, "Access denied to datasource", err)
|
||||
}
|
||||
return response.Error(500, "Failed to test rule", err)
|
||||
|
@ -11,25 +11,25 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/gofrs/uuid"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/localcache"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
fakeDatasources "github.com/grafana/grafana/pkg/services/datasources/fakes"
|
||||
"github.com/grafana/grafana/pkg/services/datasources/service"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/query"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/web/webtest"
|
||||
|
||||
fakeDatasources "github.com/grafana/grafana/pkg/services/datasources/fakes"
|
||||
)
|
||||
|
||||
func TestAPIGetPublicDashboard(t *testing.T) {
|
||||
@ -259,7 +259,7 @@ func TestAPIQueryPublicDashboard(t *testing.T) {
|
||||
qds := query.ProvideService(
|
||||
nil,
|
||||
&fakeDatasources.FakeCacheService{
|
||||
DataSources: []*models.DataSource{
|
||||
DataSources: []*datasources.DataSource{
|
||||
{Uid: "mysqlds"},
|
||||
{Uid: "promds"},
|
||||
{Uid: "promds2"},
|
||||
@ -547,12 +547,12 @@ func TestIntegrationUnauthenticatedUserCanGetPubdashPanelQueryData(t *testing.T)
|
||||
)
|
||||
scenario.hs.queryDataService = qds
|
||||
|
||||
_ = db.AddDataSource(context.Background(), &models.AddDataSourceCommand{
|
||||
_ = db.AddDataSource(context.Background(), &datasources.AddDataSourceCommand{
|
||||
Uid: "ds1",
|
||||
OrgId: 1,
|
||||
Name: "laban",
|
||||
Type: models.DS_MYSQL,
|
||||
Access: models.DS_ACCESS_DIRECT,
|
||||
Type: datasources.DS_MYSQL,
|
||||
Access: datasources.DS_ACCESS_DIRECT,
|
||||
Url: "http://test",
|
||||
Database: "site",
|
||||
ReadOnly: true,
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"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/tsdb/mssql"
|
||||
)
|
||||
|
||||
@ -16,20 +16,20 @@ var logger = log.New("datasource")
|
||||
|
||||
// requiredURL contains the set of data sources that require a URL.
|
||||
var requiredURL = map[string]bool{
|
||||
models.DS_GRAPHITE: true,
|
||||
models.DS_INFLUXDB: true,
|
||||
models.DS_INFLUXDB_08: true,
|
||||
models.DS_ES: true,
|
||||
models.DS_PROMETHEUS: true,
|
||||
models.DS_ALERTMANAGER: true,
|
||||
models.DS_JAEGER: true,
|
||||
models.DS_LOKI: true,
|
||||
models.DS_OPENTSDB: true,
|
||||
models.DS_TEMPO: true,
|
||||
models.DS_ZIPKIN: true,
|
||||
models.DS_MYSQL: true,
|
||||
models.DS_POSTGRES: true,
|
||||
models.DS_MSSQL: true,
|
||||
datasources.DS_GRAPHITE: true,
|
||||
datasources.DS_INFLUXDB: true,
|
||||
datasources.DS_INFLUXDB_08: true,
|
||||
datasources.DS_ES: true,
|
||||
datasources.DS_PROMETHEUS: true,
|
||||
datasources.DS_ALERTMANAGER: true,
|
||||
datasources.DS_JAEGER: true,
|
||||
datasources.DS_LOKI: true,
|
||||
datasources.DS_OPENTSDB: true,
|
||||
datasources.DS_TEMPO: true,
|
||||
datasources.DS_ZIPKIN: true,
|
||||
datasources.DS_MYSQL: true,
|
||||
datasources.DS_POSTGRES: true,
|
||||
datasources.DS_MSSQL: true,
|
||||
}
|
||||
|
||||
// URLValidationError represents an error from validating a data source URL.
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"strconv"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/datasource"
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
@ -24,10 +25,10 @@ import (
|
||||
)
|
||||
|
||||
var datasourcesLogger = log.New("datasources")
|
||||
var secretsPluginError models.ErrDatasourceSecretsPluginUserFriendly
|
||||
var secretsPluginError datasources.ErrDatasourceSecretsPluginUserFriendly
|
||||
|
||||
func (hs *HTTPServer) GetDataSources(c *models.ReqContext) response.Response {
|
||||
query := models.GetDataSourcesQuery{OrgId: c.OrgId, DataSourceLimit: hs.Cfg.DataSourceLimit}
|
||||
query := datasources.GetDataSourcesQuery{OrgId: c.OrgId, DataSourceLimit: hs.Cfg.DataSourceLimit}
|
||||
|
||||
if err := hs.DataSourcesService.GetDataSources(c.Req.Context(), &query); err != nil {
|
||||
return response.Error(500, "Failed to query datasources", err)
|
||||
@ -78,16 +79,16 @@ func (hs *HTTPServer) GetDataSourceById(c *models.ReqContext) response.Response
|
||||
if err != nil {
|
||||
return response.Error(http.StatusBadRequest, "id is invalid", err)
|
||||
}
|
||||
query := models.GetDataSourceQuery{
|
||||
query := datasources.GetDataSourceQuery{
|
||||
Id: id,
|
||||
OrgId: c.OrgId,
|
||||
}
|
||||
|
||||
if err := hs.DataSourcesService.GetDataSource(c.Req.Context(), &query); err != nil {
|
||||
if errors.Is(err, models.ErrDataSourceNotFound) {
|
||||
if errors.Is(err, datasources.ErrDataSourceNotFound) {
|
||||
return response.Error(404, "Data source not found", nil)
|
||||
}
|
||||
if errors.Is(err, models.ErrDataSourceIdentifierNotSet) {
|
||||
if errors.Is(err, datasources.ErrDataSourceIdentifierNotSet) {
|
||||
return response.Error(400, "Datasource id is missing", nil)
|
||||
}
|
||||
return response.Error(500, "Failed to query datasources", err)
|
||||
@ -114,7 +115,7 @@ func (hs *HTTPServer) DeleteDataSourceById(c *models.ReqContext) response.Respon
|
||||
|
||||
ds, err := hs.getRawDataSourceById(c.Req.Context(), id, c.OrgId)
|
||||
if err != nil {
|
||||
if errors.Is(err, models.ErrDataSourceNotFound) {
|
||||
if errors.Is(err, datasources.ErrDataSourceNotFound) {
|
||||
return response.Error(404, "Data source not found", nil)
|
||||
}
|
||||
return response.Error(400, "Failed to delete datasource", nil)
|
||||
@ -124,7 +125,7 @@ func (hs *HTTPServer) DeleteDataSourceById(c *models.ReqContext) response.Respon
|
||||
return response.Error(403, "Cannot delete read-only data source", nil)
|
||||
}
|
||||
|
||||
cmd := &models.DeleteDataSourceCommand{ID: id, OrgID: c.OrgId, Name: ds.Name}
|
||||
cmd := &datasources.DeleteDataSourceCommand{ID: id, OrgID: c.OrgId, Name: ds.Name}
|
||||
|
||||
err = hs.DataSourcesService.DeleteDataSource(c.Req.Context(), cmd)
|
||||
if err != nil {
|
||||
@ -144,7 +145,7 @@ func (hs *HTTPServer) GetDataSourceByUID(c *models.ReqContext) response.Response
|
||||
ds, err := hs.getRawDataSourceByUID(c.Req.Context(), web.Params(c.Req)[":uid"], c.OrgId)
|
||||
|
||||
if err != nil {
|
||||
if errors.Is(err, models.ErrDataSourceNotFound) {
|
||||
if errors.Is(err, datasources.ErrDataSourceNotFound) {
|
||||
return response.Error(http.StatusNotFound, "Data source not found", nil)
|
||||
}
|
||||
return response.Error(http.StatusInternalServerError, "Failed to query datasource", err)
|
||||
@ -168,7 +169,7 @@ func (hs *HTTPServer) DeleteDataSourceByUID(c *models.ReqContext) response.Respo
|
||||
|
||||
ds, err := hs.getRawDataSourceByUID(c.Req.Context(), uid, c.OrgId)
|
||||
if err != nil {
|
||||
if errors.Is(err, models.ErrDataSourceNotFound) {
|
||||
if errors.Is(err, datasources.ErrDataSourceNotFound) {
|
||||
return response.Error(404, "Data source not found", nil)
|
||||
}
|
||||
return response.Error(400, "Failed to delete datasource", nil)
|
||||
@ -178,7 +179,7 @@ func (hs *HTTPServer) DeleteDataSourceByUID(c *models.ReqContext) response.Respo
|
||||
return response.Error(403, "Cannot delete read-only data source", nil)
|
||||
}
|
||||
|
||||
cmd := &models.DeleteDataSourceCommand{UID: uid, OrgID: c.OrgId, Name: ds.Name}
|
||||
cmd := &datasources.DeleteDataSourceCommand{UID: uid, OrgID: c.OrgId, Name: ds.Name}
|
||||
|
||||
err = hs.DataSourcesService.DeleteDataSource(c.Req.Context(), cmd)
|
||||
if err != nil {
|
||||
@ -204,9 +205,9 @@ func (hs *HTTPServer) DeleteDataSourceByName(c *models.ReqContext) response.Resp
|
||||
return response.Error(400, "Missing valid datasource name", nil)
|
||||
}
|
||||
|
||||
getCmd := &models.GetDataSourceQuery{Name: name, OrgId: c.OrgId}
|
||||
getCmd := &datasources.GetDataSourceQuery{Name: name, OrgId: c.OrgId}
|
||||
if err := hs.DataSourcesService.GetDataSource(c.Req.Context(), getCmd); err != nil {
|
||||
if errors.Is(err, models.ErrDataSourceNotFound) {
|
||||
if errors.Is(err, datasources.ErrDataSourceNotFound) {
|
||||
return response.Error(404, "Data source not found", nil)
|
||||
}
|
||||
return response.Error(500, "Failed to delete datasource", err)
|
||||
@ -216,7 +217,7 @@ func (hs *HTTPServer) DeleteDataSourceByName(c *models.ReqContext) response.Resp
|
||||
return response.Error(403, "Cannot delete read-only data source", nil)
|
||||
}
|
||||
|
||||
cmd := &models.DeleteDataSourceCommand{Name: name, OrgID: c.OrgId}
|
||||
cmd := &datasources.DeleteDataSourceCommand{Name: name, OrgID: c.OrgId}
|
||||
err := hs.DataSourcesService.DeleteDataSource(c.Req.Context(), cmd)
|
||||
if err != nil {
|
||||
if errors.As(err, &secretsPluginError) {
|
||||
@ -243,7 +244,7 @@ func validateURL(cmdType string, url string) response.Response {
|
||||
|
||||
// POST /api/datasources/
|
||||
func (hs *HTTPServer) AddDataSource(c *models.ReqContext) response.Response {
|
||||
cmd := models.AddDataSourceCommand{}
|
||||
cmd := datasources.AddDataSourceCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
@ -258,7 +259,7 @@ func (hs *HTTPServer) AddDataSource(c *models.ReqContext) response.Response {
|
||||
}
|
||||
|
||||
if err := hs.DataSourcesService.AddDataSource(c.Req.Context(), &cmd); err != nil {
|
||||
if errors.Is(err, models.ErrDataSourceNameExists) || errors.Is(err, models.ErrDataSourceUidExists) {
|
||||
if errors.Is(err, datasources.ErrDataSourceNameExists) || errors.Is(err, datasources.ErrDataSourceUidExists) {
|
||||
return response.Error(409, err.Error(), err)
|
||||
}
|
||||
|
||||
@ -280,7 +281,7 @@ func (hs *HTTPServer) AddDataSource(c *models.ReqContext) response.Response {
|
||||
|
||||
// PUT /api/datasources/:id
|
||||
func (hs *HTTPServer) UpdateDataSourceByID(c *models.ReqContext) response.Response {
|
||||
cmd := models.UpdateDataSourceCommand{}
|
||||
cmd := datasources.UpdateDataSourceCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
@ -296,7 +297,7 @@ func (hs *HTTPServer) UpdateDataSourceByID(c *models.ReqContext) response.Respon
|
||||
|
||||
ds, err := hs.getRawDataSourceById(c.Req.Context(), cmd.Id, cmd.OrgId)
|
||||
if err != nil {
|
||||
if errors.Is(err, models.ErrDataSourceNotFound) {
|
||||
if errors.Is(err, datasources.ErrDataSourceNotFound) {
|
||||
return response.Error(404, "Data source not found", nil)
|
||||
}
|
||||
return response.Error(500, "Failed to update datasource", err)
|
||||
@ -306,7 +307,7 @@ func (hs *HTTPServer) UpdateDataSourceByID(c *models.ReqContext) response.Respon
|
||||
|
||||
// PUT /api/datasources/:uid
|
||||
func (hs *HTTPServer) UpdateDataSourceByUID(c *models.ReqContext) response.Response {
|
||||
cmd := models.UpdateDataSourceCommand{}
|
||||
cmd := datasources.UpdateDataSourceCommand{}
|
||||
if err := web.Bind(c.Req, &cmd); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
@ -318,7 +319,7 @@ func (hs *HTTPServer) UpdateDataSourceByUID(c *models.ReqContext) response.Respo
|
||||
|
||||
ds, err := hs.getRawDataSourceByUID(c.Req.Context(), web.Params(c.Req)[":uid"], c.OrgId)
|
||||
if err != nil {
|
||||
if errors.Is(err, models.ErrDataSourceNotFound) {
|
||||
if errors.Is(err, datasources.ErrDataSourceNotFound) {
|
||||
return response.Error(http.StatusNotFound, "Data source not found", nil)
|
||||
}
|
||||
return response.Error(http.StatusInternalServerError, "Failed to update datasource", err)
|
||||
@ -327,14 +328,14 @@ func (hs *HTTPServer) UpdateDataSourceByUID(c *models.ReqContext) response.Respo
|
||||
return hs.updateDataSourceByID(c, ds, cmd)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) updateDataSourceByID(c *models.ReqContext, ds *models.DataSource, cmd models.UpdateDataSourceCommand) response.Response {
|
||||
func (hs *HTTPServer) updateDataSourceByID(c *models.ReqContext, ds *datasources.DataSource, cmd datasources.UpdateDataSourceCommand) response.Response {
|
||||
if ds.ReadOnly {
|
||||
return response.Error(403, "Cannot update read-only data source", nil)
|
||||
}
|
||||
|
||||
err := hs.DataSourcesService.UpdateDataSource(c.Req.Context(), &cmd)
|
||||
if err != nil {
|
||||
if errors.Is(err, models.ErrDataSourceUpdatingOldVersion) {
|
||||
if errors.Is(err, datasources.ErrDataSourceUpdatingOldVersion) {
|
||||
return response.Error(409, "Datasource has already been updated by someone else. Please reload and try again", err)
|
||||
}
|
||||
|
||||
@ -344,13 +345,13 @@ func (hs *HTTPServer) updateDataSourceByID(c *models.ReqContext, ds *models.Data
|
||||
return response.Error(500, "Failed to update datasource", err)
|
||||
}
|
||||
|
||||
query := models.GetDataSourceQuery{
|
||||
query := datasources.GetDataSourceQuery{
|
||||
Id: cmd.Id,
|
||||
OrgId: c.OrgId,
|
||||
}
|
||||
|
||||
if err := hs.DataSourcesService.GetDataSource(c.Req.Context(), &query); err != nil {
|
||||
if errors.Is(err, models.ErrDataSourceNotFound) {
|
||||
if errors.Is(err, datasources.ErrDataSourceNotFound) {
|
||||
return response.Error(404, "Data source not found", nil)
|
||||
}
|
||||
return response.Error(500, "Failed to query datasource", err)
|
||||
@ -368,8 +369,8 @@ func (hs *HTTPServer) updateDataSourceByID(c *models.ReqContext, ds *models.Data
|
||||
})
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) getRawDataSourceById(ctx context.Context, id int64, orgID int64) (*models.DataSource, error) {
|
||||
query := models.GetDataSourceQuery{
|
||||
func (hs *HTTPServer) getRawDataSourceById(ctx context.Context, id int64, orgID int64) (*datasources.DataSource, error) {
|
||||
query := datasources.GetDataSourceQuery{
|
||||
Id: id,
|
||||
OrgId: orgID,
|
||||
}
|
||||
@ -381,8 +382,8 @@ func (hs *HTTPServer) getRawDataSourceById(ctx context.Context, id int64, orgID
|
||||
return query.Result, nil
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) getRawDataSourceByUID(ctx context.Context, uid string, orgID int64) (*models.DataSource, error) {
|
||||
query := models.GetDataSourceQuery{
|
||||
func (hs *HTTPServer) getRawDataSourceByUID(ctx context.Context, uid string, orgID int64) (*datasources.DataSource, error) {
|
||||
query := datasources.GetDataSourceQuery{
|
||||
Uid: uid,
|
||||
OrgId: orgID,
|
||||
}
|
||||
@ -396,10 +397,10 @@ func (hs *HTTPServer) getRawDataSourceByUID(ctx context.Context, uid string, org
|
||||
|
||||
// Get /api/datasources/name/:name
|
||||
func (hs *HTTPServer) GetDataSourceByName(c *models.ReqContext) response.Response {
|
||||
query := models.GetDataSourceQuery{Name: web.Params(c.Req)[":name"], OrgId: c.OrgId}
|
||||
query := datasources.GetDataSourceQuery{Name: web.Params(c.Req)[":name"], OrgId: c.OrgId}
|
||||
|
||||
if err := hs.DataSourcesService.GetDataSource(c.Req.Context(), &query); err != nil {
|
||||
if errors.Is(err, models.ErrDataSourceNotFound) {
|
||||
if errors.Is(err, datasources.ErrDataSourceNotFound) {
|
||||
return response.Error(404, "Data source not found", nil)
|
||||
}
|
||||
return response.Error(500, "Failed to query datasources", err)
|
||||
@ -411,10 +412,10 @@ func (hs *HTTPServer) GetDataSourceByName(c *models.ReqContext) response.Respons
|
||||
|
||||
// Get /api/datasources/id/:name
|
||||
func (hs *HTTPServer) GetDataSourceIdByName(c *models.ReqContext) response.Response {
|
||||
query := models.GetDataSourceQuery{Name: web.Params(c.Req)[":name"], OrgId: c.OrgId}
|
||||
query := datasources.GetDataSourceQuery{Name: web.Params(c.Req)[":name"], OrgId: c.OrgId}
|
||||
|
||||
if err := hs.DataSourcesService.GetDataSource(c.Req.Context(), &query); err != nil {
|
||||
if errors.Is(err, models.ErrDataSourceNotFound) {
|
||||
if errors.Is(err, datasources.ErrDataSourceNotFound) {
|
||||
return response.Error(404, "Data source not found", nil)
|
||||
}
|
||||
return response.Error(500, "Failed to query datasources", err)
|
||||
@ -437,7 +438,7 @@ func (hs *HTTPServer) CallDatasourceResource(c *models.ReqContext) {
|
||||
}
|
||||
ds, err := hs.DataSourceCache.GetDatasource(c.Req.Context(), datasourceID, c.SignedInUser, c.SkipCache)
|
||||
if err != nil {
|
||||
if errors.Is(err, models.ErrDataSourceAccessDenied) {
|
||||
if errors.Is(err, datasources.ErrDataSourceAccessDenied) {
|
||||
c.JsonApiErr(403, "Access denied to datasource", err)
|
||||
return
|
||||
}
|
||||
@ -464,7 +465,7 @@ func (hs *HTTPServer) CallDatasourceResourceWithUID(c *models.ReqContext) {
|
||||
|
||||
ds, err := hs.DataSourceCache.GetDatasourceByUID(c.Req.Context(), dsUID, c.SignedInUser, c.SkipCache)
|
||||
if err != nil {
|
||||
if errors.Is(err, models.ErrDataSourceAccessDenied) {
|
||||
if errors.Is(err, datasources.ErrDataSourceAccessDenied) {
|
||||
c.JsonApiErr(http.StatusForbidden, "Access denied to datasource", err)
|
||||
return
|
||||
}
|
||||
@ -481,7 +482,7 @@ func (hs *HTTPServer) CallDatasourceResourceWithUID(c *models.ReqContext) {
|
||||
hs.callPluginResourceWithDataSource(c, plugin.ID, ds)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) convertModelToDtos(ctx context.Context, ds *models.DataSource) dtos.DataSource {
|
||||
func (hs *HTTPServer) convertModelToDtos(ctx context.Context, ds *datasources.DataSource) dtos.DataSource {
|
||||
dto := dtos.DataSource{
|
||||
Id: ds.Id,
|
||||
UID: ds.Uid,
|
||||
@ -526,7 +527,7 @@ func (hs *HTTPServer) CheckDatasourceHealthWithUID(c *models.ReqContext) respons
|
||||
|
||||
ds, err := hs.DataSourceCache.GetDatasourceByUID(c.Req.Context(), dsUID, c.SignedInUser, c.SkipCache)
|
||||
if err != nil {
|
||||
if errors.Is(err, models.ErrDataSourceAccessDenied) {
|
||||
if errors.Is(err, datasources.ErrDataSourceAccessDenied) {
|
||||
return response.Error(http.StatusForbidden, "Access denied to datasource", err)
|
||||
}
|
||||
return response.Error(http.StatusInternalServerError, "Unable to load datasource metadata", err)
|
||||
@ -544,7 +545,7 @@ func (hs *HTTPServer) CheckDatasourceHealth(c *models.ReqContext) response.Respo
|
||||
|
||||
ds, err := hs.DataSourceCache.GetDatasource(c.Req.Context(), datasourceID, c.SignedInUser, c.SkipCache)
|
||||
if err != nil {
|
||||
if errors.Is(err, models.ErrDataSourceAccessDenied) {
|
||||
if errors.Is(err, datasources.ErrDataSourceAccessDenied) {
|
||||
return response.Error(http.StatusForbidden, "Access denied to datasource", err)
|
||||
}
|
||||
return response.Error(http.StatusInternalServerError, "Unable to load datasource metadata", err)
|
||||
@ -552,7 +553,7 @@ func (hs *HTTPServer) CheckDatasourceHealth(c *models.ReqContext) response.Respo
|
||||
return hs.checkDatasourceHealth(c, ds)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) checkDatasourceHealth(c *models.ReqContext, ds *models.DataSource) response.Response {
|
||||
func (hs *HTTPServer) checkDatasourceHealth(c *models.ReqContext, ds *datasources.DataSource) response.Response {
|
||||
plugin, exists := hs.pluginStore.Plugin(c.Req.Context(), ds.Type)
|
||||
if !exists {
|
||||
return response.Error(http.StatusInternalServerError, "Unable to find datasource plugin", nil)
|
||||
@ -625,8 +626,8 @@ func (hs *HTTPServer) checkDatasourceHealth(c *models.ReqContext, ds *models.Dat
|
||||
return response.JSON(http.StatusOK, payload)
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) decryptSecureJsonDataFn(ctx context.Context) func(ds *models.DataSource) map[string]string {
|
||||
return func(ds *models.DataSource) map[string]string {
|
||||
func (hs *HTTPServer) decryptSecureJsonDataFn(ctx context.Context) func(ds *datasources.DataSource) map[string]string {
|
||||
return func(ds *datasources.DataSource) map[string]string {
|
||||
decryptedJsonData, err := hs.DataSourcesService.DecryptedValues(ctx, ds)
|
||||
if err != nil {
|
||||
hs.log.Error("Failed to decrypt secure json data", "error", err)
|
||||
@ -635,18 +636,18 @@ func (hs *HTTPServer) decryptSecureJsonDataFn(ctx context.Context) func(ds *mode
|
||||
}
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) filterDatasourcesByQueryPermission(ctx context.Context, user *models.SignedInUser, datasources []*models.DataSource) ([]*models.DataSource, error) {
|
||||
query := models.DatasourcesPermissionFilterQuery{
|
||||
func (hs *HTTPServer) filterDatasourcesByQueryPermission(ctx context.Context, user *models.SignedInUser, ds []*datasources.DataSource) ([]*datasources.DataSource, error) {
|
||||
query := datasources.DatasourcesPermissionFilterQuery{
|
||||
User: user,
|
||||
Datasources: datasources,
|
||||
Datasources: ds,
|
||||
}
|
||||
query.Result = datasources
|
||||
query.Result = ds
|
||||
|
||||
if err := hs.DatasourcePermissionsService.FilterDatasourcesBasedOnQueryPermissions(ctx, &query); err != nil {
|
||||
if !errors.Is(err, permissions.ErrNotImplemented) {
|
||||
return nil, err
|
||||
}
|
||||
return datasources, nil
|
||||
return ds, nil
|
||||
}
|
||||
|
||||
return query.Result, nil
|
||||
|
@ -34,7 +34,7 @@ func TestDataSourcesProxy_userLoggedIn(t *testing.T) {
|
||||
mockDatasourcePermissionService := permissions.NewMockDatasourcePermissionService()
|
||||
loggedInUserScenario(t, "When calling GET on", "/api/datasources/", "/api/datasources/", func(sc *scenarioContext) {
|
||||
// Stubs the database query
|
||||
ds := []*models.DataSource{
|
||||
ds := []*datasources.DataSource{
|
||||
{Name: "mmm"},
|
||||
{Name: "ZZZ"},
|
||||
{Name: "BBB"},
|
||||
@ -85,7 +85,7 @@ func TestAddDataSource_InvalidURL(t *testing.T) {
|
||||
}
|
||||
|
||||
sc.m.Post(sc.url, routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
c.Req.Body = mockRequestBody(models.AddDataSourceCommand{
|
||||
c.Req.Body = mockRequestBody(datasources.AddDataSourceCommand{
|
||||
Name: "Test",
|
||||
Url: "invalid:url",
|
||||
Access: "direct",
|
||||
@ -106,14 +106,14 @@ func TestAddDataSource_URLWithoutProtocol(t *testing.T) {
|
||||
|
||||
hs := &HTTPServer{
|
||||
DataSourcesService: &dataSourcesServiceMock{
|
||||
expectedDatasource: &models.DataSource{},
|
||||
expectedDatasource: &datasources.DataSource{},
|
||||
},
|
||||
}
|
||||
|
||||
sc := setupScenarioContext(t, "/api/datasources")
|
||||
|
||||
sc.m.Post(sc.url, routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
c.Req.Body = mockRequestBody(models.AddDataSourceCommand{
|
||||
c.Req.Body = mockRequestBody(datasources.AddDataSourceCommand{
|
||||
Name: name,
|
||||
Url: url,
|
||||
Access: "direct",
|
||||
@ -135,7 +135,7 @@ func TestUpdateDataSource_InvalidURL(t *testing.T) {
|
||||
sc := setupScenarioContext(t, "/api/datasources/1234")
|
||||
|
||||
sc.m.Put(sc.url, routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
c.Req.Body = mockRequestBody(models.AddDataSourceCommand{
|
||||
c.Req.Body = mockRequestBody(datasources.AddDataSourceCommand{
|
||||
Name: "Test",
|
||||
Url: "invalid:url",
|
||||
Access: "direct",
|
||||
@ -156,14 +156,14 @@ func TestUpdateDataSource_URLWithoutProtocol(t *testing.T) {
|
||||
|
||||
hs := &HTTPServer{
|
||||
DataSourcesService: &dataSourcesServiceMock{
|
||||
expectedDatasource: &models.DataSource{},
|
||||
expectedDatasource: &datasources.DataSource{},
|
||||
},
|
||||
}
|
||||
|
||||
sc := setupScenarioContext(t, "/api/datasources/1234")
|
||||
|
||||
sc.m.Put(sc.url, routing.Wrap(func(c *models.ReqContext) response.Response {
|
||||
c.Req.Body = mockRequestBody(models.AddDataSourceCommand{
|
||||
c.Req.Body = mockRequestBody(datasources.AddDataSourceCommand{
|
||||
Name: name,
|
||||
Url: url,
|
||||
Access: "direct",
|
||||
@ -178,7 +178,7 @@ func TestUpdateDataSource_URLWithoutProtocol(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAPI_Datasources_AccessControl(t *testing.T) {
|
||||
testDatasource := models.DataSource{
|
||||
testDatasource := datasources.DataSource{
|
||||
Id: 3,
|
||||
Uid: "testUID",
|
||||
OrgId: testOrgID,
|
||||
@ -187,7 +187,7 @@ func TestAPI_Datasources_AccessControl(t *testing.T) {
|
||||
Type: "postgresql",
|
||||
Access: "Proxy",
|
||||
}
|
||||
testDatasourceReadOnly := models.DataSource{
|
||||
testDatasourceReadOnly := datasources.DataSource{
|
||||
Id: 4,
|
||||
Uid: "testUID",
|
||||
OrgId: testOrgID,
|
||||
@ -199,7 +199,7 @@ func TestAPI_Datasources_AccessControl(t *testing.T) {
|
||||
}
|
||||
|
||||
addDatasourceBody := func() io.Reader {
|
||||
s, _ := json.Marshal(models.AddDataSourceCommand{
|
||||
s, _ := json.Marshal(datasources.AddDataSourceCommand{
|
||||
Name: "test",
|
||||
Url: "http://localhost:5432",
|
||||
Type: "postgresql",
|
||||
@ -212,12 +212,12 @@ func TestAPI_Datasources_AccessControl(t *testing.T) {
|
||||
expectedDatasource: &testDatasource,
|
||||
}
|
||||
dsPermissionService := permissions.NewMockDatasourcePermissionService()
|
||||
dsPermissionService.DsResult = []*models.DataSource{
|
||||
dsPermissionService.DsResult = []*datasources.DataSource{
|
||||
&testDatasource,
|
||||
}
|
||||
|
||||
updateDatasourceBody := func() io.Reader {
|
||||
s, _ := json.Marshal(models.UpdateDataSourceCommand{
|
||||
s, _ := json.Marshal(datasources.UpdateDataSourceCommand{
|
||||
Name: "test",
|
||||
Url: "http://localhost:5432",
|
||||
Type: "postgresql",
|
||||
@ -228,7 +228,7 @@ func TestAPI_Datasources_AccessControl(t *testing.T) {
|
||||
type acTestCaseWithHandler struct {
|
||||
body func() io.Reader
|
||||
accessControlTestCase
|
||||
expectedDS *models.DataSource
|
||||
expectedDS *datasources.DataSource
|
||||
expectedSQLError error
|
||||
}
|
||||
tests := []acTestCaseWithHandler{
|
||||
@ -246,7 +246,7 @@ func TestAPI_Datasources_AccessControl(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedSQLError: models.ErrDataSourceNotFound,
|
||||
expectedSQLError: datasources.ErrDataSourceNotFound,
|
||||
},
|
||||
{
|
||||
accessControlTestCase: accessControlTestCase{
|
||||
@ -507,7 +507,7 @@ 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 = []*datasources.DataSource{test.expectedDS}
|
||||
if test.expectedDS == nil {
|
||||
dsPermissionService.DsResult = nil
|
||||
}
|
||||
@ -547,44 +547,44 @@ func TestAPI_Datasources_AccessControl(t *testing.T) {
|
||||
type dataSourcesServiceMock struct {
|
||||
datasources.DataSourceService
|
||||
|
||||
expectedDatasources []*models.DataSource
|
||||
expectedDatasource *models.DataSource
|
||||
expectedDatasources []*datasources.DataSource
|
||||
expectedDatasource *datasources.DataSource
|
||||
expectedError error
|
||||
}
|
||||
|
||||
func (m *dataSourcesServiceMock) GetDataSource(ctx context.Context, query *models.GetDataSourceQuery) error {
|
||||
func (m *dataSourcesServiceMock) GetDataSource(ctx context.Context, query *datasources.GetDataSourceQuery) error {
|
||||
query.Result = m.expectedDatasource
|
||||
return m.expectedError
|
||||
}
|
||||
|
||||
func (m *dataSourcesServiceMock) GetDataSources(ctx context.Context, query *models.GetDataSourcesQuery) error {
|
||||
func (m *dataSourcesServiceMock) GetDataSources(ctx context.Context, query *datasources.GetDataSourcesQuery) error {
|
||||
query.Result = m.expectedDatasources
|
||||
return m.expectedError
|
||||
}
|
||||
|
||||
func (m *dataSourcesServiceMock) GetDataSourcesByType(ctx context.Context, query *models.GetDataSourcesByTypeQuery) error {
|
||||
func (m *dataSourcesServiceMock) GetDataSourcesByType(ctx context.Context, query *datasources.GetDataSourcesByTypeQuery) error {
|
||||
return m.expectedError
|
||||
}
|
||||
|
||||
func (m *dataSourcesServiceMock) GetDefaultDataSource(ctx context.Context, query *models.GetDefaultDataSourceQuery) error {
|
||||
func (m *dataSourcesServiceMock) GetDefaultDataSource(ctx context.Context, query *datasources.GetDefaultDataSourceQuery) error {
|
||||
return m.expectedError
|
||||
}
|
||||
|
||||
func (m *dataSourcesServiceMock) DeleteDataSource(ctx context.Context, cmd *models.DeleteDataSourceCommand) error {
|
||||
func (m *dataSourcesServiceMock) DeleteDataSource(ctx context.Context, cmd *datasources.DeleteDataSourceCommand) error {
|
||||
return m.expectedError
|
||||
}
|
||||
|
||||
func (m *dataSourcesServiceMock) AddDataSource(ctx context.Context, cmd *models.AddDataSourceCommand) error {
|
||||
func (m *dataSourcesServiceMock) AddDataSource(ctx context.Context, cmd *datasources.AddDataSourceCommand) error {
|
||||
cmd.Result = m.expectedDatasource
|
||||
return m.expectedError
|
||||
}
|
||||
|
||||
func (m *dataSourcesServiceMock) UpdateDataSource(ctx context.Context, cmd *models.UpdateDataSourceCommand) error {
|
||||
func (m *dataSourcesServiceMock) UpdateDataSource(ctx context.Context, cmd *datasources.UpdateDataSourceCommand) error {
|
||||
cmd.Result = m.expectedDatasource
|
||||
return m.expectedError
|
||||
}
|
||||
|
||||
func (m *dataSourcesServiceMock) DecryptedValues(ctx context.Context, ds *models.DataSource) (map[string]string, error) {
|
||||
func (m *dataSourcesServiceMock) DecryptedValues(ctx context.Context, ds *datasources.DataSource) (map[string]string, error) {
|
||||
decryptedValues := make(map[string]string)
|
||||
return decryptedValues, m.expectedError
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ package definitions
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
)
|
||||
|
||||
// swagger:route GET /datasources datasources getDatasources
|
||||
@ -457,14 +457,14 @@ type DatasourceProxyPOSTByUIDcallsParams struct {
|
||||
type AddDatasourceParams struct {
|
||||
// in:body
|
||||
// required:true
|
||||
Body models.AddDataSourceCommand
|
||||
Body datasources.AddDataSourceCommand
|
||||
}
|
||||
|
||||
// swagger:parameters updateDatasourceByID
|
||||
type UpdateDatasourceParams struct {
|
||||
// in:body
|
||||
// required:true
|
||||
Body models.UpdateDataSourceCommand
|
||||
Body datasources.UpdateDataSourceCommand
|
||||
// in:path
|
||||
// required:true
|
||||
DatasourceID string `json:"id"`
|
||||
@ -474,7 +474,7 @@ type UpdateDatasourceParams struct {
|
||||
type UpdateDatasourceByUIDParams struct {
|
||||
// in:body
|
||||
// required:true
|
||||
Body models.UpdateDataSourceCommand
|
||||
Body datasources.UpdateDataSourceCommand
|
||||
// in:path
|
||||
// required:true
|
||||
DatasourceUID string `json:"uid"`
|
||||
|
@ -4,8 +4,8 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
)
|
||||
|
||||
type DataSource struct {
|
||||
@ -15,7 +15,7 @@ type DataSource struct {
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
TypeLogoUrl string `json:"typeLogoUrl"`
|
||||
Access models.DsAccess `json:"access"`
|
||||
Access datasources.DsAccess `json:"access"`
|
||||
Url string `json:"url"`
|
||||
User string `json:"user"`
|
||||
Database string `json:"database"`
|
||||
@ -31,21 +31,21 @@ type DataSource struct {
|
||||
}
|
||||
|
||||
type DataSourceListItemDTO struct {
|
||||
Id int64 `json:"id"`
|
||||
UID string `json:"uid"`
|
||||
OrgId int64 `json:"orgId"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
TypeName string `json:"typeName"`
|
||||
TypeLogoUrl string `json:"typeLogoUrl"`
|
||||
Access models.DsAccess `json:"access"`
|
||||
Url string `json:"url"`
|
||||
User string `json:"user"`
|
||||
Database string `json:"database"`
|
||||
BasicAuth bool `json:"basicAuth"`
|
||||
IsDefault bool `json:"isDefault"`
|
||||
JsonData *simplejson.Json `json:"jsonData,omitempty"`
|
||||
ReadOnly bool `json:"readOnly"`
|
||||
Id int64 `json:"id"`
|
||||
UID string `json:"uid"`
|
||||
OrgId int64 `json:"orgId"`
|
||||
Name string `json:"name"`
|
||||
Type string `json:"type"`
|
||||
TypeName string `json:"typeName"`
|
||||
TypeLogoUrl string `json:"typeLogoUrl"`
|
||||
Access datasources.DsAccess `json:"access"`
|
||||
Url string `json:"url"`
|
||||
User string `json:"user"`
|
||||
Database string `json:"database"`
|
||||
BasicAuth bool `json:"basicAuth"`
|
||||
IsDefault bool `json:"isDefault"`
|
||||
JsonData *simplejson.Json `json:"jsonData,omitempty"`
|
||||
ReadOnly bool `json:"readOnly"`
|
||||
}
|
||||
|
||||
type DataSourceList []DataSourceListItemDTO
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/licensing"
|
||||
"github.com/grafana/grafana/pkg/services/pluginsettings"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
@ -191,10 +192,10 @@ func (hs *HTTPServer) getFrontendSettingsMap(c *models.ReqContext) (map[string]i
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) getFSDataSources(c *models.ReqContext, enabledPlugins EnabledPlugins) (map[string]plugins.DataSourceDTO, error) {
|
||||
orgDataSources := make([]*models.DataSource, 0)
|
||||
orgDataSources := make([]*datasources.DataSource, 0)
|
||||
|
||||
if c.OrgId != 0 {
|
||||
query := models.GetDataSourcesQuery{OrgId: c.OrgId, DataSourceLimit: hs.Cfg.DataSourceLimit}
|
||||
query := datasources.GetDataSourcesQuery{OrgId: c.OrgId, DataSourceLimit: hs.Cfg.DataSourceLimit}
|
||||
err := hs.SQLStore.GetDataSources(c.Req.Context(), &query)
|
||||
|
||||
if err != nil {
|
||||
@ -214,7 +215,7 @@ func (hs *HTTPServer) getFSDataSources(c *models.ReqContext, enabledPlugins Enab
|
||||
for _, ds := range orgDataSources {
|
||||
url := ds.Url
|
||||
|
||||
if ds.Access == models.DS_ACCESS_PROXY {
|
||||
if ds.Access == datasources.DS_ACCESS_PROXY {
|
||||
url = "/api/datasources/proxy/" + strconv.FormatInt(ds.Id, 10)
|
||||
}
|
||||
|
||||
@ -248,7 +249,7 @@ func (hs *HTTPServer) getFSDataSources(c *models.ReqContext, enabledPlugins Enab
|
||||
dsDTO.JSONData = ds.JsonData.MustMap()
|
||||
}
|
||||
|
||||
if ds.Access == models.DS_ACCESS_DIRECT {
|
||||
if ds.Access == datasources.DS_ACCESS_DIRECT {
|
||||
if ds.BasicAuth {
|
||||
password, err := hs.DataSourcesService.DecryptedBasicAuthPassword(c.Req.Context(), ds)
|
||||
if err != nil {
|
||||
@ -264,7 +265,7 @@ func (hs *HTTPServer) getFSDataSources(c *models.ReqContext, enabledPlugins Enab
|
||||
dsDTO.WithCredentials = ds.WithCredentials
|
||||
}
|
||||
|
||||
if ds.Type == models.DS_INFLUXDB_08 {
|
||||
if ds.Type == datasources.DS_INFLUXDB_08 {
|
||||
password, err := hs.DataSourcesService.DecryptedPassword(c.Req.Context(), ds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -275,7 +276,7 @@ func (hs *HTTPServer) getFSDataSources(c *models.ReqContext, enabledPlugins Enab
|
||||
dsDTO.URL = url + "/db/" + ds.Database
|
||||
}
|
||||
|
||||
if ds.Type == models.DS_INFLUXDB {
|
||||
if ds.Type == datasources.DS_INFLUXDB {
|
||||
password, err := hs.DataSourcesService.DecryptedPassword(c.Req.Context(), ds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -287,11 +288,11 @@ func (hs *HTTPServer) getFSDataSources(c *models.ReqContext, enabledPlugins Enab
|
||||
}
|
||||
}
|
||||
|
||||
if (ds.Type == models.DS_INFLUXDB) || (ds.Type == models.DS_ES) {
|
||||
if (ds.Type == datasources.DS_INFLUXDB) || (ds.Type == datasources.DS_ES) {
|
||||
dsDTO.Database = ds.Database
|
||||
}
|
||||
|
||||
if ds.Type == models.DS_PROMETHEUS {
|
||||
if ds.Type == datasources.DS_PROMETHEUS {
|
||||
// add unproxied server URL for link to Prometheus web UI
|
||||
ds.JsonData.Set("directUrl", ds.Url)
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/plugins/backendplugin"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/query"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
@ -17,10 +18,10 @@ import (
|
||||
)
|
||||
|
||||
func (hs *HTTPServer) handleQueryMetricsError(err error) *response.NormalResponse {
|
||||
if errors.Is(err, models.ErrDataSourceAccessDenied) {
|
||||
if errors.Is(err, datasources.ErrDataSourceAccessDenied) {
|
||||
return response.Error(http.StatusForbidden, "Access denied to data source", err)
|
||||
}
|
||||
if errors.Is(err, models.ErrDataSourceNotFound) {
|
||||
if errors.Is(err, datasources.ErrDataSourceNotFound) {
|
||||
return response.Error(http.StatusNotFound, "Data source not found", err)
|
||||
}
|
||||
var badQuery *query.ErrBadQuery
|
||||
|
@ -8,9 +8,11 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/web/webtest"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
@ -51,7 +53,7 @@ func (ts *fakeOAuthTokenService) GetCurrentOAuthToken(context.Context, *models.S
|
||||
return ts.token
|
||||
}
|
||||
|
||||
func (ts *fakeOAuthTokenService) IsOAuthPassThruEnabled(*models.DataSource) bool {
|
||||
func (ts *fakeOAuthTokenService) IsOAuthPassThruEnabled(*datasources.DataSource) bool {
|
||||
return ts.passThruEnabled
|
||||
}
|
||||
|
||||
|
@ -12,8 +12,10 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/plugins/backendplugin"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/util/proxyutil"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
)
|
||||
@ -47,7 +49,7 @@ func (hs *HTTPServer) callPluginResource(c *models.ReqContext, pluginID string)
|
||||
}
|
||||
}
|
||||
|
||||
func (hs *HTTPServer) callPluginResourceWithDataSource(c *models.ReqContext, pluginID string, ds *models.DataSource) {
|
||||
func (hs *HTTPServer) callPluginResourceWithDataSource(c *models.ReqContext, pluginID string, ds *datasources.DataSource) {
|
||||
pCtx, found, err := hs.PluginContextProvider.GetWithDataSource(c.Req.Context(), pluginID, c.SignedInUser, ds)
|
||||
if err != nil {
|
||||
c.JsonApiErr(500, "Failed to get plugin settings", err)
|
||||
|
@ -11,6 +11,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/datasource"
|
||||
"github.com/grafana/grafana/pkg/infra/httpclient"
|
||||
glog "github.com/grafana/grafana/pkg/infra/log"
|
||||
@ -22,7 +24,6 @@ import (
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
"github.com/grafana/grafana/pkg/util/proxyutil"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -31,7 +32,7 @@ var (
|
||||
)
|
||||
|
||||
type DataSourceProxy struct {
|
||||
ds *models.DataSource
|
||||
ds *datasources.DataSource
|
||||
ctx *models.ReqContext
|
||||
targetUrl *url.URL
|
||||
proxyPath string
|
||||
@ -49,7 +50,7 @@ type httpClient interface {
|
||||
}
|
||||
|
||||
// NewDataSourceProxy creates a new Datasource proxy
|
||||
func NewDataSourceProxy(ds *models.DataSource, pluginRoutes []*plugins.Route, ctx *models.ReqContext,
|
||||
func NewDataSourceProxy(ds *datasources.DataSource, pluginRoutes []*plugins.Route, ctx *models.ReqContext,
|
||||
proxyPath string, cfg *setting.Cfg, clientProvider httpclient.Provider,
|
||||
oAuthTokenService oauthtoken.OAuthTokenService, dsService datasources.DataSourceService,
|
||||
tracer tracing.Tracer) (*DataSourceProxy, error) {
|
||||
@ -167,7 +168,7 @@ func (proxy *DataSourceProxy) director(req *http.Request) {
|
||||
reqQueryVals := req.URL.Query()
|
||||
|
||||
switch proxy.ds.Type {
|
||||
case models.DS_INFLUXDB_08:
|
||||
case datasources.DS_INFLUXDB_08:
|
||||
password, err := proxy.dataSourcesService.DecryptedPassword(req.Context(), proxy.ds)
|
||||
if err != nil {
|
||||
logger.Error("Error interpolating proxy url", "error", err)
|
||||
@ -178,7 +179,7 @@ func (proxy *DataSourceProxy) director(req *http.Request) {
|
||||
reqQueryVals.Add("u", proxy.ds.User)
|
||||
reqQueryVals.Add("p", password)
|
||||
req.URL.RawQuery = reqQueryVals.Encode()
|
||||
case models.DS_INFLUXDB:
|
||||
case datasources.DS_INFLUXDB:
|
||||
password, err := proxy.dataSourcesService.DecryptedPassword(req.Context(), proxy.ds)
|
||||
if err != nil {
|
||||
logger.Error("Error interpolating proxy url", "error", err)
|
||||
@ -266,7 +267,7 @@ func (proxy *DataSourceProxy) validateRequest() error {
|
||||
return errors.New("target URL is not a valid target")
|
||||
}
|
||||
|
||||
if proxy.ds.Type == models.DS_ES {
|
||||
if proxy.ds.Type == datasources.DS_ES {
|
||||
if proxy.ctx.Req.Method == "DELETE" {
|
||||
return errors.New("deletes not allowed on proxied Elasticsearch datasource")
|
||||
}
|
||||
@ -301,7 +302,7 @@ func (proxy *DataSourceProxy) validateRequest() error {
|
||||
}
|
||||
|
||||
// Trailing validation below this point for routes that were not matched
|
||||
if proxy.ds.Type == models.DS_PROMETHEUS {
|
||||
if proxy.ds.Type == datasources.DS_PROMETHEUS {
|
||||
if proxy.ctx.Req.Method == "DELETE" {
|
||||
return errors.New("non allow-listed DELETEs not allowed on proxied Prometheus datasource")
|
||||
}
|
||||
|
@ -13,6 +13,10 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/datasource"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/httpclient"
|
||||
@ -20,6 +24,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
acmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
datasourceservice "github.com/grafana/grafana/pkg/services/datasources/service"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/oauthtoken"
|
||||
@ -29,9 +34,6 @@ import (
|
||||
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
func TestDataSourceProxy_routeRule(t *testing.T) {
|
||||
@ -96,7 +98,7 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
|
||||
key, err := secretsService.Encrypt(context.Background(), []byte("123"), secrets.WithoutScope())
|
||||
require.NoError(t, err)
|
||||
|
||||
ds := &models.DataSource{
|
||||
ds := &datasources.DataSource{
|
||||
JsonData: simplejson.NewFromAny(map[string]interface{}{
|
||||
"clientId": "asd",
|
||||
"dynamicUrl": "https://dynamic.grafana.com",
|
||||
@ -249,7 +251,7 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
|
||||
key, err := secretsService.Encrypt(context.Background(), []byte("123"), secrets.WithoutScope())
|
||||
require.NoError(t, err)
|
||||
|
||||
ds := &models.DataSource{
|
||||
ds := &datasources.DataSource{
|
||||
JsonData: simplejson.NewFromAny(map[string]interface{}{
|
||||
"clientId": "asd",
|
||||
"tenantId": "mytenantId",
|
||||
@ -340,7 +342,7 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
|
||||
|
||||
t.Run("When proxying graphite", func(t *testing.T) {
|
||||
var routes []*plugins.Route
|
||||
ds := &models.DataSource{Url: "htttp://graphite:8080", Type: models.DS_GRAPHITE}
|
||||
ds := &datasources.DataSource{Url: "htttp://graphite:8080", Type: datasources.DS_GRAPHITE}
|
||||
ctx := &models.ReqContext{}
|
||||
|
||||
secretsStore := kvstore.SetupTestService(t)
|
||||
@ -360,8 +362,8 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("When proxying InfluxDB", func(t *testing.T) {
|
||||
ds := &models.DataSource{
|
||||
Type: models.DS_INFLUXDB_08,
|
||||
ds := &datasources.DataSource{
|
||||
Type: datasources.DS_INFLUXDB_08,
|
||||
Url: "http://influxdb:8083",
|
||||
Database: "site",
|
||||
User: "user",
|
||||
@ -386,8 +388,8 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
|
||||
json, err := simplejson.NewJson([]byte(`{"keepCookies": []}`))
|
||||
require.NoError(t, err)
|
||||
|
||||
ds := &models.DataSource{
|
||||
Type: models.DS_GRAPHITE,
|
||||
ds := &datasources.DataSource{
|
||||
Type: datasources.DS_GRAPHITE,
|
||||
Url: "http://graphite:8086",
|
||||
JsonData: json,
|
||||
}
|
||||
@ -415,8 +417,8 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
|
||||
json, err := simplejson.NewJson([]byte(`{"keepCookies": ["JSESSION_ID"]}`))
|
||||
require.NoError(t, err)
|
||||
|
||||
ds := &models.DataSource{
|
||||
Type: models.DS_GRAPHITE,
|
||||
ds := &datasources.DataSource{
|
||||
Type: datasources.DS_GRAPHITE,
|
||||
Url: "http://graphite:8086",
|
||||
JsonData: json,
|
||||
}
|
||||
@ -441,7 +443,7 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("When proxying a custom datasource", func(t *testing.T) {
|
||||
ds := &models.DataSource{
|
||||
ds := &datasources.DataSource{
|
||||
Type: "custom-datasource",
|
||||
Url: "http://host/root/",
|
||||
}
|
||||
@ -466,7 +468,7 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("When proxying a datasource that has OAuth token pass-through enabled", func(t *testing.T) {
|
||||
ds := &models.DataSource{
|
||||
ds := &datasources.DataSource{
|
||||
Type: "custom-datasource",
|
||||
Url: "http://host/root/",
|
||||
JsonData: simplejson.NewFromAny(map[string]interface{}{
|
||||
@ -555,18 +557,18 @@ func TestDataSourceProxy_routeRule(t *testing.T) {
|
||||
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
|
||||
|
||||
tests := []*testCase{
|
||||
createAuthTest(t, secretsStore, models.DS_INFLUXDB_08, "http://localhost:9090", authTypePassword, authCheckQuery),
|
||||
createAuthTest(t, secretsStore, models.DS_INFLUXDB_08, "http://localhost:9090", authTypePassword, authCheckQuery),
|
||||
createAuthTest(t, secretsStore, models.DS_INFLUXDB, "http://localhost:9090", authTypePassword, authCheckHeader),
|
||||
createAuthTest(t, secretsStore, models.DS_INFLUXDB, "http://localhost:9090", authTypePassword, authCheckHeader),
|
||||
createAuthTest(t, secretsStore, models.DS_INFLUXDB, "http://localhost:9090", authTypeBasic, authCheckHeader),
|
||||
createAuthTest(t, secretsStore, models.DS_INFLUXDB, "http://localhost:9090", authTypeBasic, authCheckHeader),
|
||||
createAuthTest(t, secretsStore, datasources.DS_INFLUXDB_08, "http://localhost:9090", authTypePassword, authCheckQuery),
|
||||
createAuthTest(t, secretsStore, datasources.DS_INFLUXDB_08, "http://localhost:9090", authTypePassword, authCheckQuery),
|
||||
createAuthTest(t, secretsStore, datasources.DS_INFLUXDB, "http://localhost:9090", authTypePassword, authCheckHeader),
|
||||
createAuthTest(t, secretsStore, datasources.DS_INFLUXDB, "http://localhost:9090", authTypePassword, authCheckHeader),
|
||||
createAuthTest(t, secretsStore, datasources.DS_INFLUXDB, "http://localhost:9090", authTypeBasic, authCheckHeader),
|
||||
createAuthTest(t, secretsStore, datasources.DS_INFLUXDB, "http://localhost:9090", authTypeBasic, authCheckHeader),
|
||||
|
||||
// These two should be enough for any other datasource at the moment. Proxy has special handling
|
||||
// only for Influx, others have the same path and only BasicAuth. Non BasicAuth datasources
|
||||
// do not go through proxy but through TSDB API which is not tested here.
|
||||
createAuthTest(t, secretsStore, models.DS_ES, "http://localhost:9200", authTypeBasic, authCheckHeader),
|
||||
createAuthTest(t, secretsStore, models.DS_ES, "http://localhost:9200", authTypeBasic, authCheckHeader),
|
||||
createAuthTest(t, secretsStore, datasources.DS_ES, "http://localhost:9200", authTypeBasic, authCheckHeader),
|
||||
createAuthTest(t, secretsStore, datasources.DS_ES, "http://localhost:9200", authTypeBasic, authCheckHeader),
|
||||
}
|
||||
for _, test := range tests {
|
||||
runDatasourceAuthTest(t, secretsService, secretsStore, cfg, test)
|
||||
@ -585,7 +587,7 @@ func TestDataSourceProxy_requestHandling(t *testing.T) {
|
||||
writeCb func(w http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
|
||||
setUp := func(t *testing.T, cfgs ...setUpCfg) (*models.ReqContext, *models.DataSource) {
|
||||
setUp := func(t *testing.T, cfgs ...setUpCfg) (*models.ReqContext, *datasources.DataSource) {
|
||||
writeErr = nil
|
||||
|
||||
backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
@ -606,7 +608,7 @@ func TestDataSourceProxy_requestHandling(t *testing.T) {
|
||||
}))
|
||||
t.Cleanup(backend.Close)
|
||||
|
||||
ds := &models.DataSource{Url: backend.URL, Type: models.DS_GRAPHITE}
|
||||
ds := &datasources.DataSource{Url: backend.URL, Type: datasources.DS_GRAPHITE}
|
||||
|
||||
responseWriter := web.NewResponseWriter("GET", httptest.NewRecorder())
|
||||
|
||||
@ -758,7 +760,7 @@ func TestNewDataSourceProxy_InvalidURL(t *testing.T) {
|
||||
Context: &web.Context{},
|
||||
SignedInUser: &models.SignedInUser{OrgRole: models.ROLE_EDITOR},
|
||||
}
|
||||
ds := models.DataSource{
|
||||
ds := datasources.DataSource{
|
||||
Type: "test",
|
||||
Url: "://host/root",
|
||||
}
|
||||
@ -778,7 +780,7 @@ func TestNewDataSourceProxy_ProtocolLessURL(t *testing.T) {
|
||||
Context: &web.Context{},
|
||||
SignedInUser: &models.SignedInUser{OrgRole: models.ROLE_EDITOR},
|
||||
}
|
||||
ds := models.DataSource{
|
||||
ds := datasources.DataSource{
|
||||
Type: "test",
|
||||
Url: "127.0.01:5432",
|
||||
}
|
||||
@ -823,7 +825,7 @@ func TestNewDataSourceProxy_MSSQL(t *testing.T) {
|
||||
for _, tc := range tcs {
|
||||
t.Run(tc.description, func(t *testing.T) {
|
||||
cfg := &setting.Cfg{}
|
||||
ds := models.DataSource{
|
||||
ds := datasources.DataSource{
|
||||
Type: "mssql",
|
||||
Url: tc.url,
|
||||
}
|
||||
@ -849,7 +851,7 @@ func TestNewDataSourceProxy_MSSQL(t *testing.T) {
|
||||
|
||||
// getDatasourceProxiedRequest is a helper for easier setup of tests based on global config and ReqContext.
|
||||
func getDatasourceProxiedRequest(t *testing.T, ctx *models.ReqContext, cfg *setting.Cfg) *http.Request {
|
||||
ds := &models.DataSource{
|
||||
ds := &datasources.DataSource{
|
||||
Type: "custom",
|
||||
Url: "http://host/root/",
|
||||
}
|
||||
@ -897,7 +899,7 @@ func newFakeHTTPClient(t *testing.T, fakeBody []byte) httpClient {
|
||||
}
|
||||
|
||||
type testCase struct {
|
||||
datasource *models.DataSource
|
||||
datasource *datasources.DataSource
|
||||
checkReq func(req *http.Request)
|
||||
}
|
||||
|
||||
@ -916,7 +918,7 @@ func createAuthTest(t *testing.T, secretsStore kvstore.SecretsKVStore, dsType st
|
||||
base64AuthHeader := "Basic dXNlcjpwYXNzd29yZA=="
|
||||
|
||||
test := &testCase{
|
||||
datasource: &models.DataSource{
|
||||
datasource: &datasources.DataSource{
|
||||
Id: 1,
|
||||
OrgId: 1,
|
||||
Name: fmt.Sprintf("%s,%s,%s,%s", dsType, url, authType, authCheck),
|
||||
@ -1019,7 +1021,7 @@ func Test_PathCheck(t *testing.T) {
|
||||
secretsStore := kvstore.SetupTestService(t)
|
||||
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
|
||||
dsService := datasourceservice.ProvideService(nil, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService())
|
||||
proxy, err := NewDataSourceProxy(&models.DataSource{}, routes, ctx, "b", &setting.Cfg{}, httpclient.NewProvider(), &oauthtoken.Service{}, dsService, tracer)
|
||||
proxy, err := NewDataSourceProxy(&datasources.DataSource{}, routes, ctx, "b", &setting.Cfg{}, httpclient.NewProvider(), &oauthtoken.Service{}, dsService, tracer)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Nil(t, proxy.validateRequest())
|
||||
@ -1035,6 +1037,6 @@ func (m *mockOAuthTokenService) GetCurrentOAuthToken(ctx context.Context, user *
|
||||
return m.token
|
||||
}
|
||||
|
||||
func (m *mockOAuthTokenService) IsOAuthPassThruEnabled(ds *models.DataSource) bool {
|
||||
func (m *mockOAuthTokenService) IsOAuthPassThruEnabled(ds *datasources.DataSource) bool {
|
||||
return m.oAuthEnabled
|
||||
}
|
||||
|
@ -5,13 +5,14 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/cmd/grafana-cli/commands/commandstest"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestPasswordMigrationCommand(t *testing.T) {
|
||||
@ -20,7 +21,7 @@ func TestPasswordMigrationCommand(t *testing.T) {
|
||||
session := sqlstore.NewSession(context.Background())
|
||||
defer session.Close()
|
||||
|
||||
datasources := []*models.DataSource{
|
||||
ds := []*datasources.DataSource{
|
||||
{Type: "influxdb", Name: "influxdb", Password: "foobar", Uid: "influx"},
|
||||
{Type: "graphite", Name: "graphite", BasicAuthPassword: "foobar", Uid: "graphite"},
|
||||
{Type: "prometheus", Name: "prometheus", Uid: "prom"},
|
||||
@ -28,7 +29,7 @@ func TestPasswordMigrationCommand(t *testing.T) {
|
||||
}
|
||||
|
||||
// set required default values
|
||||
for _, ds := range datasources {
|
||||
for _, ds := range ds {
|
||||
ds.Created = time.Now()
|
||||
ds.Updated = time.Now()
|
||||
|
||||
@ -42,7 +43,7 @@ func TestPasswordMigrationCommand(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
_, err := session.Insert(&datasources)
|
||||
_, err := session.Insert(&ds)
|
||||
require.NoError(t, err)
|
||||
|
||||
// force secure_json_data to be null to verify that migration can handle that
|
||||
@ -56,7 +57,7 @@ func TestPasswordMigrationCommand(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
// verify that no datasources still have password or basic_auth
|
||||
var dss []*models.DataSource
|
||||
var dss []*datasources.DataSource
|
||||
err = session.SQL("select * from data_source").Find(&dss)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, len(dss), 4)
|
||||
@ -95,7 +96,7 @@ func TestPasswordMigrationCommand(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func DecryptSecureJsonData(ds *models.DataSource) (map[string]string, error) {
|
||||
func DecryptSecureJsonData(ds *datasources.DataSource) (map[string]string, error) {
|
||||
decrypted := make(map[string]string)
|
||||
for key, data := range ds.SecureJsonData {
|
||||
decryptedData, err := util.Decrypt(data, setting.SecretKey)
|
||||
|
@ -4,8 +4,9 @@ import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
)
|
||||
|
||||
func TestServicebuildPipeLine(t *testing.T) {
|
||||
@ -30,7 +31,7 @@ func TestServicebuildPipeLine(t *testing.T) {
|
||||
},
|
||||
{
|
||||
RefID: "B",
|
||||
DataSource: &models.DataSource{
|
||||
DataSource: &datasources.DataSource{
|
||||
Uid: "Fake",
|
||||
},
|
||||
},
|
||||
@ -140,7 +141,7 @@ func TestServicebuildPipeLine(t *testing.T) {
|
||||
},
|
||||
{
|
||||
RefID: "C",
|
||||
DataSource: &models.DataSource{
|
||||
DataSource: &datasources.DataSource{
|
||||
Uid: "Fake",
|
||||
},
|
||||
},
|
||||
@ -194,7 +195,7 @@ func TestServicebuildPipeLine(t *testing.T) {
|
||||
},
|
||||
{
|
||||
RefID: "C",
|
||||
DataSource: &models.DataSource{
|
||||
DataSource: &datasources.DataSource{
|
||||
Uid: "Fake",
|
||||
},
|
||||
},
|
||||
@ -217,7 +218,7 @@ func TestServicebuildPipeLine(t *testing.T) {
|
||||
},
|
||||
{
|
||||
RefID: "B",
|
||||
DataSource: &models.DataSource{
|
||||
DataSource: &datasources.DataSource{
|
||||
Uid: "Fake",
|
||||
},
|
||||
},
|
||||
|
@ -12,8 +12,8 @@ import (
|
||||
"github.com/grafana/grafana/pkg/expr/classic"
|
||||
"github.com/grafana/grafana/pkg/expr/mathexp"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/plugins/adapters"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
|
||||
"gonum.org/v1/gonum/graph/simple"
|
||||
)
|
||||
@ -46,7 +46,7 @@ type rawNode struct {
|
||||
Query map[string]interface{}
|
||||
QueryType string
|
||||
TimeRange TimeRange
|
||||
DataSource *models.DataSource
|
||||
DataSource *datasources.DataSource
|
||||
}
|
||||
|
||||
func (rn *rawNode) GetCommandType() (c CommandType, err error) {
|
||||
@ -138,7 +138,7 @@ const (
|
||||
type DSNode struct {
|
||||
baseNode
|
||||
query json.RawMessage
|
||||
datasource *models.DataSource
|
||||
datasource *datasources.DataSource
|
||||
|
||||
orgID int64
|
||||
queryType string
|
||||
@ -268,7 +268,7 @@ func (dn *DSNode) Execute(ctx context.Context, vars mathexp.Vars, s *Service) (m
|
||||
// Check for TimeSeriesTypeNot in InfluxDB queries. A data frame of this type will cause
|
||||
// the WideToMany() function to error out, which results in unhealthy alerts.
|
||||
// This check should be removed once inconsistencies in data source responses are solved.
|
||||
if frame.TimeSeriesSchema().Type == data.TimeSeriesTypeNot && dataSource == models.DS_INFLUXDB {
|
||||
if frame.TimeSeriesSchema().Type == data.TimeSeriesTypeNot && dataSource == datasources.DS_INFLUXDB {
|
||||
logger.Warn("ignoring InfluxDB data frame due to missing numeric fields", "frame", frame)
|
||||
continue
|
||||
}
|
||||
|
@ -4,8 +4,8 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
|
||||
"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/datasources"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
@ -76,8 +76,8 @@ func (s *Service) ExecutePipeline(ctx context.Context, pipeline DataPipeline) (*
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func DataSourceModel() *models.DataSource {
|
||||
return &models.DataSource{
|
||||
func DataSourceModel() *datasources.DataSource {
|
||||
return &datasources.DataSource{
|
||||
Id: DatasourceID,
|
||||
Uid: DatasourceUID,
|
||||
Name: DatasourceUID,
|
||||
|
@ -10,10 +10,11 @@ import (
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
datasources "github.com/grafana/grafana/pkg/services/datasources/fakes"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
datafakes "github.com/grafana/grafana/pkg/services/datasources/fakes"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
func TestService(t *testing.T) {
|
||||
@ -30,13 +31,13 @@ func TestService(t *testing.T) {
|
||||
s := Service{
|
||||
cfg: cfg,
|
||||
dataService: me,
|
||||
dataSourceService: &datasources.FakeDataSourceService{},
|
||||
dataSourceService: &datafakes.FakeDataSourceService{},
|
||||
}
|
||||
|
||||
queries := []Query{
|
||||
{
|
||||
RefID: "A",
|
||||
DataSource: &models.DataSource{
|
||||
DataSource: &datasources.DataSource{
|
||||
OrgId: 1,
|
||||
Uid: "test",
|
||||
Type: "test",
|
||||
|
@ -7,8 +7,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -41,7 +42,7 @@ type Request struct {
|
||||
type Query struct {
|
||||
RefID string
|
||||
TimeRange TimeRange
|
||||
DataSource *models.DataSource `json:"datasource"`
|
||||
DataSource *datasources.DataSource `json:"datasource"`
|
||||
JSON json.RawMessage
|
||||
Interval time.Duration
|
||||
QueryType string
|
||||
@ -126,8 +127,8 @@ func hiddenRefIDs(queries []Query) (map[string]struct{}, error) {
|
||||
return hidden, nil
|
||||
}
|
||||
|
||||
func (s *Service) decryptSecureJsonDataFn(ctx context.Context) func(ds *models.DataSource) map[string]string {
|
||||
return func(ds *models.DataSource) map[string]string {
|
||||
func (s *Service) decryptSecureJsonDataFn(ctx context.Context) func(ds *datasources.DataSource) map[string]string {
|
||||
return func(ds *datasources.DataSource) map[string]string {
|
||||
decryptedJsonData, err := s.dataSourceService.DecryptedValues(ctx, ds)
|
||||
if err != nil {
|
||||
logger.Error("Failed to decrypt secure json data", "error", err)
|
||||
|
@ -7,13 +7,15 @@ import (
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/contexthandler/ctxkey"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/mockstore"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestApi_getUsageStats(t *testing.T) {
|
||||
@ -49,7 +51,7 @@ func TestApi_getUsageStats(t *testing.T) {
|
||||
|
||||
sqlStore.ExpectedSystemStats = &models.SystemStats{}
|
||||
sqlStore.ExpectedDataSourceStats = []*models.DataSourceStats{}
|
||||
sqlStore.ExpectedDataSources = []*models.DataSource{}
|
||||
sqlStore.ExpectedDataSources = []*datasources.DataSource{}
|
||||
sqlStore.ExpectedDataSourcesAccessStats = []*models.DataSourceAccessStats{}
|
||||
sqlStore.ExpectedNotifierUsageStats = []*models.NotifierUsageStats{}
|
||||
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
)
|
||||
|
||||
const promFlavorCacheLifetime = time.Hour
|
||||
@ -37,7 +37,7 @@ func (s *Service) detectPrometheusVariants(ctx context.Context) (map[string]int6
|
||||
return s.promFlavorCache.variants, nil
|
||||
}
|
||||
|
||||
dsProm := &models.GetDataSourcesByTypeQuery{Type: "prometheus"}
|
||||
dsProm := &datasources.GetDataSourcesByTypeQuery{Type: "prometheus"}
|
||||
err := s.datasources.GetDataSourcesByType(ctx, dsProm)
|
||||
if err != nil {
|
||||
s.log.Error("Failed to read all Prometheus data sources", "error", err)
|
||||
@ -65,7 +65,7 @@ func (s *Service) detectPrometheusVariants(ctx context.Context) (map[string]int6
|
||||
return variants, nil
|
||||
}
|
||||
|
||||
func (s *Service) detectPrometheusVariant(ctx context.Context, ds *models.DataSource) (string, error) {
|
||||
func (s *Service) detectPrometheusVariant(ctx context.Context, ds *datasources.DataSource) (string, error) {
|
||||
type buildInfo struct {
|
||||
Data struct {
|
||||
Application *string `json:"application"`
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/mockstore"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
@ -37,7 +37,7 @@ func TestDetectPrometheusVariant(t *testing.T) {
|
||||
t,
|
||||
setting.NewCfg(),
|
||||
sqlStore,
|
||||
withDatasources(mockDatasourceService{datasources: []*models.DataSource{
|
||||
withDatasources(mockDatasourceService{datasources: []*datasources.DataSource{
|
||||
{
|
||||
Id: 1,
|
||||
OrgId: 1,
|
||||
|
@ -256,7 +256,7 @@ func (s *Service) collectDatasourceStats(ctx context.Context) (map[string]interf
|
||||
|
||||
func (s *Service) collectElasticStats(ctx context.Context) (map[string]interface{}, error) {
|
||||
m := map[string]interface{}{}
|
||||
esDataSourcesQuery := models.GetDataSourcesByTypeQuery{Type: models.DS_ES}
|
||||
esDataSourcesQuery := datasources.GetDataSourcesByTypeQuery{Type: datasources.DS_ES}
|
||||
if err := s.sqlstore.GetDataSourcesByType(ctx, &esDataSourcesQuery); err != nil {
|
||||
s.log.Error("Failed to get elasticsearch json data", "error", err)
|
||||
return nil, err
|
||||
|
@ -190,11 +190,11 @@ func TestDatasourceStats(t *testing.T) {
|
||||
|
||||
sqlStore.ExpectedDataSourceStats = []*models.DataSourceStats{
|
||||
{
|
||||
Type: models.DS_ES,
|
||||
Type: datasources.DS_ES,
|
||||
Count: 9,
|
||||
},
|
||||
{
|
||||
Type: models.DS_PROMETHEUS,
|
||||
Type: datasources.DS_PROMETHEUS,
|
||||
Count: 10,
|
||||
},
|
||||
{
|
||||
@ -207,7 +207,7 @@ func TestDatasourceStats(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
sqlStore.ExpectedDataSources = []*models.DataSource{
|
||||
sqlStore.ExpectedDataSources = []*datasources.DataSource{
|
||||
{
|
||||
JsonData: simplejson.NewFromAny(map[string]interface{}{
|
||||
"esVersion": 2,
|
||||
@ -227,17 +227,17 @@ func TestDatasourceStats(t *testing.T) {
|
||||
|
||||
sqlStore.ExpectedDataSourcesAccessStats = []*models.DataSourceAccessStats{
|
||||
{
|
||||
Type: models.DS_ES,
|
||||
Type: datasources.DS_ES,
|
||||
Access: "direct",
|
||||
Count: 1,
|
||||
},
|
||||
{
|
||||
Type: models.DS_ES,
|
||||
Type: datasources.DS_ES,
|
||||
Access: "proxy",
|
||||
Count: 2,
|
||||
},
|
||||
{
|
||||
Type: models.DS_PROMETHEUS,
|
||||
Type: datasources.DS_PROMETHEUS,
|
||||
Access: "proxy",
|
||||
Count: 3,
|
||||
},
|
||||
@ -272,8 +272,8 @@ func TestDatasourceStats(t *testing.T) {
|
||||
db, err := s.collectDatasourceStats(context.Background())
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.EqualValues(t, 9, db["stats.ds."+models.DS_ES+".count"])
|
||||
assert.EqualValues(t, 10, db["stats.ds."+models.DS_PROMETHEUS+".count"])
|
||||
assert.EqualValues(t, 9, db["stats.ds."+datasources.DS_ES+".count"])
|
||||
assert.EqualValues(t, 10, db["stats.ds."+datasources.DS_PROMETHEUS+".count"])
|
||||
assert.EqualValues(t, 11+12, db["stats.ds.other.count"])
|
||||
}
|
||||
|
||||
@ -281,9 +281,9 @@ func TestDatasourceStats(t *testing.T) {
|
||||
dba, err := s.collectDatasourceAccess(context.Background())
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.EqualValues(t, 1, dba["stats.ds_access."+models.DS_ES+".direct.count"])
|
||||
assert.EqualValues(t, 2, dba["stats.ds_access."+models.DS_ES+".proxy.count"])
|
||||
assert.EqualValues(t, 3, dba["stats.ds_access."+models.DS_PROMETHEUS+".proxy.count"])
|
||||
assert.EqualValues(t, 1, dba["stats.ds_access."+datasources.DS_ES+".direct.count"])
|
||||
assert.EqualValues(t, 2, dba["stats.ds_access."+datasources.DS_ES+".proxy.count"])
|
||||
assert.EqualValues(t, 3, dba["stats.ds_access."+datasources.DS_PROMETHEUS+".proxy.count"])
|
||||
assert.EqualValues(t, 6+7, dba["stats.ds_access.other.direct.count"])
|
||||
assert.EqualValues(t, 4+8, dba["stats.ds_access.other.proxy.count"])
|
||||
}
|
||||
@ -383,16 +383,16 @@ func setupSomeDataSourcePlugins(t *testing.T, s *Service) {
|
||||
|
||||
s.plugins = &fakePluginStore{
|
||||
plugins: map[string]plugins.PluginDTO{
|
||||
models.DS_ES: {
|
||||
datasources.DS_ES: {
|
||||
Signature: "internal",
|
||||
},
|
||||
models.DS_PROMETHEUS: {
|
||||
datasources.DS_PROMETHEUS: {
|
||||
Signature: "internal",
|
||||
},
|
||||
models.DS_GRAPHITE: {
|
||||
datasources.DS_GRAPHITE: {
|
||||
Signature: "internal",
|
||||
},
|
||||
models.DS_MYSQL: {
|
||||
datasources.DS_MYSQL: {
|
||||
Signature: "internal",
|
||||
},
|
||||
},
|
||||
@ -446,14 +446,14 @@ func withDatasources(ds datasources.DataSourceService) func(*serviceOptions) {
|
||||
type mockDatasourceService struct {
|
||||
datasources.DataSourceService
|
||||
|
||||
datasources []*models.DataSource
|
||||
datasources []*datasources.DataSource
|
||||
}
|
||||
|
||||
func (s mockDatasourceService) GetDataSourcesByType(ctx context.Context, query *models.GetDataSourcesByTypeQuery) error {
|
||||
func (s mockDatasourceService) GetDataSourcesByType(ctx context.Context, query *datasources.GetDataSourcesByTypeQuery) error {
|
||||
query.Result = s.datasources
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s mockDatasourceService) GetHTTPTransport(ctx context.Context, ds *models.DataSource, provider httpclient.Provider, customMiddlewares ...sdkhttpclient.Middleware) (http.RoundTripper, error) {
|
||||
func (s mockDatasourceService) GetHTTPTransport(ctx context.Context, ds *datasources.DataSource, provider httpclient.Provider, customMiddlewares ...sdkhttpclient.Middleware) (http.RoundTripper, error) {
|
||||
return provider.GetTransport()
|
||||
}
|
||||
|
@ -5,11 +5,13 @@ import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
)
|
||||
|
||||
// ModelToInstanceSettings converts a models.DataSource to a backend.DataSourceInstanceSettings.
|
||||
func ModelToInstanceSettings(ds *models.DataSource, decryptFn func(ds *models.DataSource) map[string]string,
|
||||
// ModelToInstanceSettings converts a datasources.DataSource to a backend.DataSourceInstanceSettings.
|
||||
func ModelToInstanceSettings(ds *datasources.DataSource, decryptFn func(ds *datasources.DataSource) map[string]string,
|
||||
) (*backend.DataSourceInstanceSettings, error) {
|
||||
var jsonDataBytes json.RawMessage
|
||||
if ds.JsonData != nil {
|
||||
|
@ -49,7 +49,7 @@ func (p *Provider) Get(ctx context.Context, pluginID string, user *models.Signed
|
||||
|
||||
// GetWithDataSource allows getting plugin context by its ID and PluginContext.DataSourceInstanceSettings will be
|
||||
// resolved and appended to the returned context.
|
||||
func (p *Provider) GetWithDataSource(ctx context.Context, pluginID string, user *models.SignedInUser, ds *models.DataSource) (backend.PluginContext, bool, error) {
|
||||
func (p *Provider) GetWithDataSource(ctx context.Context, pluginID string, user *models.SignedInUser, ds *datasources.DataSource) (backend.PluginContext, bool, error) {
|
||||
pCtx, exists, err := p.pluginContext(ctx, pluginID, user)
|
||||
if err != nil {
|
||||
return pCtx, exists, err
|
||||
@ -127,8 +127,8 @@ func (p *Provider) getCachedPluginSettings(ctx context.Context, pluginID string,
|
||||
return ps, nil
|
||||
}
|
||||
|
||||
func (p *Provider) decryptSecureJsonDataFn(ctx context.Context) func(ds *models.DataSource) map[string]string {
|
||||
return func(ds *models.DataSource) map[string]string {
|
||||
func (p *Provider) decryptSecureJsonDataFn(ctx context.Context) func(ds *datasources.DataSource) map[string]string {
|
||||
return func(ds *datasources.DataSource) map[string]string {
|
||||
decryptedJsonData, err := p.dataSourceService.DecryptedValues(ctx, ds)
|
||||
if err != nil {
|
||||
p.logger.Error("Failed to decrypt secure json data", "error", err)
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/resourcepermissions/types"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
)
|
||||
|
||||
@ -75,11 +76,11 @@ func setupResourceBenchmark(b *testing.B, dsNum, usersNum int) (*AccessControlSt
|
||||
func GenerateDatasourcePermissions(b *testing.B, db *sqlstore.SQLStore, ac *AccessControlStore, dsNum, usersNum, permissionsPerDs int) []int64 {
|
||||
dataSources := make([]int64, 0)
|
||||
for i := 0; i < dsNum; i++ {
|
||||
addDSCommand := &models.AddDataSourceCommand{
|
||||
addDSCommand := &datasources.AddDataSourceCommand{
|
||||
OrgId: 0,
|
||||
Name: fmt.Sprintf("ds_%d", i),
|
||||
Type: models.DS_GRAPHITE,
|
||||
Access: models.DS_ACCESS_DIRECT,
|
||||
Type: datasources.DS_GRAPHITE,
|
||||
Access: datasources.DS_ACCESS_DIRECT,
|
||||
Url: "http://test",
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,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/sqlstore"
|
||||
)
|
||||
|
||||
@ -39,7 +40,7 @@ func benchmarkFilter(b *testing.B, numDs, numPermissions int) {
|
||||
)
|
||||
require.NoError(b, err)
|
||||
|
||||
var datasources []models.DataSource
|
||||
var datasources []datasources.DataSource
|
||||
sess := store.NewSession(context.Background())
|
||||
err = sess.SQL(baseSql+acFilter.Where, acFilter.Args...).Find(&datasources)
|
||||
require.NoError(b, err)
|
||||
@ -53,7 +54,7 @@ func setupFilterBenchmark(b *testing.B, numDs, numPermissions int) (*sqlstore.SQ
|
||||
store := sqlstore.InitTestDB(b)
|
||||
|
||||
for i := 1; i <= numDs; i++ {
|
||||
err := store.AddDataSource(context.Background(), &models.AddDataSourceCommand{
|
||||
err := store.AddDataSource(context.Background(), &datasources.AddDataSourceCommand{
|
||||
Name: fmt.Sprintf("ds:%d", i),
|
||||
OrgId: 1,
|
||||
})
|
||||
|
@ -10,6 +10,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/sqlstore"
|
||||
)
|
||||
|
||||
@ -170,7 +171,7 @@ func TestFilter_Datasources(t *testing.T) {
|
||||
|
||||
// seed 10 data sources
|
||||
for i := 1; i <= 10; i++ {
|
||||
err := store.AddDataSource(context.Background(), &models.AddDataSourceCommand{Name: fmt.Sprintf("ds:%d", i), Uid: fmt.Sprintf("uid%d", i)})
|
||||
err := store.AddDataSource(context.Background(), &datasources.AddDataSourceCommand{Name: fmt.Sprintf("ds:%d", i), Uid: fmt.Sprintf("uid%d", i)})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
@ -187,7 +188,7 @@ func TestFilter_Datasources(t *testing.T) {
|
||||
|
||||
if !tt.expectErr {
|
||||
require.NoError(t, err)
|
||||
var datasources []models.DataSource
|
||||
var datasources []datasources.DataSource
|
||||
err = sess.SQL(baseSql+acFilter.Where, acFilter.Args...).Find(&datasources)
|
||||
require.NoError(t, err)
|
||||
|
||||
|
@ -1,40 +1,43 @@
|
||||
package accesscontrol
|
||||
package accesscontrol_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
)
|
||||
|
||||
func TestResolveKeywordScope(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
user *models.SignedInUser
|
||||
permission Permission
|
||||
want Permission
|
||||
permission accesscontrol.Permission
|
||||
want accesscontrol.Permission
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "no scope",
|
||||
user: testUser,
|
||||
permission: Permission{Action: "users:read"},
|
||||
want: Permission{Action: "users:read"},
|
||||
permission: accesscontrol.Permission{Action: "users:read"},
|
||||
want: accesscontrol.Permission{Action: "users:read"},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "user if resolution",
|
||||
user: testUser,
|
||||
permission: Permission{Action: "users:read", Scope: "users:self"},
|
||||
want: Permission{Action: "users:read", Scope: "users:id:2"},
|
||||
permission: accesscontrol.Permission{Action: "users:read", Scope: "users:self"},
|
||||
want: accesscontrol.Permission{Action: "users:read", Scope: "users:id:2"},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
var err error
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
resolvers := NewScopeResolvers()
|
||||
resolvers := accesscontrol.NewScopeResolvers()
|
||||
scopeModifier := resolvers.GetScopeKeywordMutator(tt.user)
|
||||
tt.permission.Scope, err = scopeModifier(context.TODO(), tt.permission.Scope)
|
||||
if tt.wantErr {
|
||||
@ -60,64 +63,64 @@ var testUser = &models.SignedInUser{
|
||||
func TestResolveAttributeScope(t *testing.T) {
|
||||
// Calls allow us to see how many times the fakeDataSourceResolution has been called
|
||||
calls := 0
|
||||
fakeDataSourceResolver := ScopeAttributeResolverFunc(func(ctx context.Context, orgID int64, initialScope string) ([]string, error) {
|
||||
fakeDataSourceResolver := accesscontrol.ScopeAttributeResolverFunc(func(ctx context.Context, orgID int64, initialScope string) ([]string, error) {
|
||||
calls++
|
||||
if initialScope == "datasources:name:testds" {
|
||||
return []string{Scope("datasources", "id", "1")}, nil
|
||||
return []string{accesscontrol.Scope("datasources", "id", "1")}, nil
|
||||
} else if initialScope == "datasources:name:testds2" {
|
||||
return []string{Scope("datasources", "id", "2")}, nil
|
||||
return []string{accesscontrol.Scope("datasources", "id", "2")}, nil
|
||||
} else if initialScope == "datasources:name:test:ds4" {
|
||||
return []string{Scope("datasources", "id", "4")}, nil
|
||||
return []string{accesscontrol.Scope("datasources", "id", "4")}, nil
|
||||
} else if initialScope == "datasources:name:testds5*" {
|
||||
return []string{Scope("datasources", "id", "5")}, nil
|
||||
return []string{accesscontrol.Scope("datasources", "id", "5")}, nil
|
||||
} else {
|
||||
return nil, models.ErrDataSourceNotFound
|
||||
return nil, datasources.ErrDataSourceNotFound
|
||||
}
|
||||
})
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
orgID int64
|
||||
evaluator Evaluator
|
||||
wantEvaluator Evaluator
|
||||
evaluator accesscontrol.Evaluator
|
||||
wantEvaluator accesscontrol.Evaluator
|
||||
wantCalls int
|
||||
wantErr error
|
||||
}{
|
||||
{
|
||||
name: "should work with scope less permissions",
|
||||
evaluator: EvalPermission("datasources:read"),
|
||||
wantEvaluator: EvalPermission("datasources:read"),
|
||||
evaluator: accesscontrol.EvalPermission("datasources:read"),
|
||||
wantEvaluator: accesscontrol.EvalPermission("datasources:read"),
|
||||
wantCalls: 0,
|
||||
},
|
||||
{
|
||||
name: "should handle an error",
|
||||
orgID: 1,
|
||||
evaluator: EvalPermission("datasources:read", Scope("datasources", "name", "testds3")),
|
||||
wantErr: models.ErrDataSourceNotFound,
|
||||
evaluator: accesscontrol.EvalPermission("datasources:read", accesscontrol.Scope("datasources", "name", "testds3")),
|
||||
wantErr: datasources.ErrDataSourceNotFound,
|
||||
wantCalls: 1,
|
||||
},
|
||||
{
|
||||
name: "should resolve a scope",
|
||||
orgID: 1,
|
||||
evaluator: EvalPermission("datasources:read", Scope("datasources", "name", "testds")),
|
||||
wantEvaluator: EvalPermission("datasources:read", Scope("datasources", "id", "1")),
|
||||
evaluator: accesscontrol.EvalPermission("datasources:read", accesscontrol.Scope("datasources", "name", "testds")),
|
||||
wantEvaluator: accesscontrol.EvalPermission("datasources:read", accesscontrol.Scope("datasources", "id", "1")),
|
||||
wantCalls: 1,
|
||||
},
|
||||
{
|
||||
name: "should resolve nested scopes with cache",
|
||||
orgID: 1,
|
||||
evaluator: EvalAll(
|
||||
EvalPermission("datasources:read", Scope("datasources", "name", "testds")),
|
||||
EvalAny(
|
||||
EvalPermission("datasources:read", Scope("datasources", "name", "testds")),
|
||||
EvalPermission("datasources:read", Scope("datasources", "name", "testds2")),
|
||||
evaluator: accesscontrol.EvalAll(
|
||||
accesscontrol.EvalPermission("datasources:read", accesscontrol.Scope("datasources", "name", "testds")),
|
||||
accesscontrol.EvalAny(
|
||||
accesscontrol.EvalPermission("datasources:read", accesscontrol.Scope("datasources", "name", "testds")),
|
||||
accesscontrol.EvalPermission("datasources:read", accesscontrol.Scope("datasources", "name", "testds2")),
|
||||
),
|
||||
),
|
||||
wantEvaluator: EvalAll(
|
||||
EvalPermission("datasources:read", Scope("datasources", "id", "1")),
|
||||
EvalAny(
|
||||
EvalPermission("datasources:read", Scope("datasources", "id", "1")),
|
||||
EvalPermission("datasources:read", Scope("datasources", "id", "2")),
|
||||
wantEvaluator: accesscontrol.EvalAll(
|
||||
accesscontrol.EvalPermission("datasources:read", accesscontrol.Scope("datasources", "id", "1")),
|
||||
accesscontrol.EvalAny(
|
||||
accesscontrol.EvalPermission("datasources:read", accesscontrol.Scope("datasources", "id", "1")),
|
||||
accesscontrol.EvalPermission("datasources:read", accesscontrol.Scope("datasources", "id", "2")),
|
||||
),
|
||||
),
|
||||
wantCalls: 2,
|
||||
@ -125,20 +128,20 @@ func TestResolveAttributeScope(t *testing.T) {
|
||||
{
|
||||
name: "should resolve name with colon",
|
||||
orgID: 1,
|
||||
evaluator: EvalPermission("datasources:read", Scope("datasources", "name", "test:ds4")),
|
||||
wantEvaluator: EvalPermission("datasources:read", Scope("datasources", "id", "4")),
|
||||
evaluator: accesscontrol.EvalPermission("datasources:read", accesscontrol.Scope("datasources", "name", "test:ds4")),
|
||||
wantEvaluator: accesscontrol.EvalPermission("datasources:read", accesscontrol.Scope("datasources", "id", "4")),
|
||||
wantCalls: 1,
|
||||
},
|
||||
{
|
||||
name: "should resolve names with '*'",
|
||||
orgID: 1,
|
||||
evaluator: EvalPermission("datasources:read", Scope("datasources", "name", "testds5*")),
|
||||
wantEvaluator: EvalPermission("datasources:read", Scope("datasources", "id", "5")),
|
||||
evaluator: accesscontrol.EvalPermission("datasources:read", accesscontrol.Scope("datasources", "name", "testds5*")),
|
||||
wantEvaluator: accesscontrol.EvalPermission("datasources:read", accesscontrol.Scope("datasources", "id", "5")),
|
||||
wantCalls: 1,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
resolvers := NewScopeResolvers()
|
||||
resolvers := accesscontrol.NewScopeResolvers()
|
||||
|
||||
// Reset calls counter
|
||||
calls = 0
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
)
|
||||
|
||||
// DatasourceAlertUsage is a hash where the key represents the
|
||||
@ -62,7 +63,7 @@ func (e *AlertEngine) mapRulesToUsageStats(ctx context.Context, rules []*models.
|
||||
// map of datsource types and frequency
|
||||
result := map[string]int{}
|
||||
for k, v := range typeCount {
|
||||
query := &models.GetDataSourceQuery{Id: k}
|
||||
query := &datasources.GetDataSourceQuery{Id: k}
|
||||
err := e.sqlStore.GetDataSource(ctx, query)
|
||||
if err != nil {
|
||||
return map[string]int{}, nil
|
||||
|
@ -7,9 +7,11 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
)
|
||||
|
||||
func TestAlertingUsageStats(t *testing.T) {
|
||||
@ -39,8 +41,8 @@ func TestAlertingUsageStats(t *testing.T) {
|
||||
return nil
|
||||
}
|
||||
|
||||
store.getDataSource = func(ctx context.Context, query *models.GetDataSourceQuery) error {
|
||||
ds := map[int64]*models.DataSource{
|
||||
store.getDataSource = func(ctx context.Context, query *datasources.GetDataSourceQuery) error {
|
||||
ds := map[int64]*datasources.DataSource{
|
||||
1: {Type: "influxdb"},
|
||||
2: {Type: "graphite"},
|
||||
3: {Type: "prometheus"},
|
||||
@ -49,7 +51,7 @@ func TestAlertingUsageStats(t *testing.T) {
|
||||
|
||||
r, exist := ds[query.Id]
|
||||
if !exist {
|
||||
return models.ErrDataSourceNotFound
|
||||
return datasources.ErrDataSourceNotFound
|
||||
}
|
||||
|
||||
query.Result = r
|
||||
|
@ -13,10 +13,11 @@ import (
|
||||
gocontext "context"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/null"
|
||||
"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/datasources"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -115,7 +116,7 @@ func (c *QueryCondition) Eval(context *alerting.EvalContext, requestHandler lega
|
||||
}, nil
|
||||
}
|
||||
|
||||
func calculateInterval(timeRange legacydata.DataTimeRange, model *simplejson.Json, dsInfo *models.DataSource) (time.Duration, error) {
|
||||
func calculateInterval(timeRange legacydata.DataTimeRange, model *simplejson.Json, dsInfo *datasources.DataSource) (time.Duration, error) {
|
||||
// if there is no min-interval specified in the datasource or in the dashboard-panel,
|
||||
// the value of 1ms is used (this is how it is done in the dashboard-interval-calculation too,
|
||||
// see https://github.com/grafana/grafana/blob/9a0040c0aeaae8357c650cec2ee644a571dddf3d/packages/grafana-data/src/datetime/rangeutil.ts#L264)
|
||||
@ -141,7 +142,7 @@ func calculateInterval(timeRange legacydata.DataTimeRange, model *simplejson.Jso
|
||||
|
||||
func (c *QueryCondition) executeQuery(context *alerting.EvalContext, timeRange legacydata.DataTimeRange,
|
||||
requestHandler legacydata.RequestHandler) (legacydata.DataTimeSeriesSlice, error) {
|
||||
getDsInfo := &models.GetDataSourceQuery{
|
||||
getDsInfo := &datasources.GetDataSourceQuery{
|
||||
Id: c.Query.DatasourceID,
|
||||
OrgId: context.Rule.OrgID,
|
||||
}
|
||||
@ -253,7 +254,7 @@ func (c *QueryCondition) executeQuery(context *alerting.EvalContext, timeRange l
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *QueryCondition) getRequestForAlertRule(datasource *models.DataSource, timeRange legacydata.DataTimeRange,
|
||||
func (c *QueryCondition) getRequestForAlertRule(datasource *datasources.DataSource, timeRange legacydata.DataTimeRange,
|
||||
debug bool) (legacydata.DataQuery, error) {
|
||||
queryModel := c.Query.Model
|
||||
|
||||
|
@ -5,8 +5,8 @@ import (
|
||||
"testing"
|
||||
|
||||
"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/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/mockstore"
|
||||
"github.com/grafana/grafana/pkg/services/validations"
|
||||
"github.com/grafana/grafana/pkg/tsdb/intervalv2"
|
||||
@ -127,7 +127,7 @@ type fakeIntervalTestReqHandler struct {
|
||||
}
|
||||
|
||||
//nolint: staticcheck // legacydata.DataResponse deprecated
|
||||
func (rh fakeIntervalTestReqHandler) HandleRequest(ctx context.Context, dsInfo *models.DataSource, query legacydata.DataQuery) (
|
||||
func (rh fakeIntervalTestReqHandler) HandleRequest(ctx context.Context, dsInfo *datasources.DataSource, query legacydata.DataQuery) (
|
||||
legacydata.DataResponse, error) {
|
||||
q := query.Queries[0]
|
||||
rh.verifier(q)
|
||||
@ -138,7 +138,7 @@ func (rh fakeIntervalTestReqHandler) HandleRequest(ctx context.Context, dsInfo *
|
||||
func applyScenario(t *testing.T, timeRange string, dataSourceJsonData *simplejson.Json, queryModel string, verifier func(query legacydata.DataSubQuery)) {
|
||||
t.Run("desc", func(t *testing.T) {
|
||||
store := mockstore.NewSQLStoreMock()
|
||||
store.ExpectedDatasource = &models.DataSource{Id: 1, Type: "graphite", JsonData: dataSourceJsonData}
|
||||
store.ExpectedDatasource = &datasources.DataSource{Id: 1, Type: "graphite", JsonData: dataSourceJsonData}
|
||||
|
||||
ctx := &queryIntervalTestContext{}
|
||||
ctx.result = &alerting.EvalContext{
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/mockstore"
|
||||
"github.com/grafana/grafana/pkg/services/validations"
|
||||
"github.com/grafana/grafana/pkg/tsdb/legacydata"
|
||||
@ -13,9 +14,9 @@ import (
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/null"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/alerting"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
@ -36,7 +37,7 @@ func TestQueryCondition(t *testing.T) {
|
||||
setup := func() *queryConditionTestContext {
|
||||
ctx := &queryConditionTestContext{}
|
||||
store := mockstore.NewSQLStoreMock()
|
||||
store.ExpectedDatasource = &models.DataSource{Id: 1, Type: "graphite"}
|
||||
store.ExpectedDatasource = &datasources.DataSource{Id: 1, Type: "graphite"}
|
||||
|
||||
ctx.reducer = `{"type":"avg"}`
|
||||
ctx.evaluator = `{"type":"gt","params":[100]}`
|
||||
@ -249,7 +250,7 @@ type fakeReqHandler struct {
|
||||
}
|
||||
|
||||
//nolint: staticcheck // legacydata.DataPlugin deprecated
|
||||
func (rh fakeReqHandler) HandleRequest(context.Context, *models.DataSource, legacydata.DataQuery) (
|
||||
func (rh fakeReqHandler) HandleRequest(context.Context, *datasources.DataSource, legacydata.DataQuery) (
|
||||
legacydata.DataResponse, error) {
|
||||
return rh.response, nil
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/alerting/metrics"
|
||||
"github.com/grafana/grafana/pkg/services/dashboards"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/encryption"
|
||||
"github.com/grafana/grafana/pkg/services/notifications"
|
||||
"github.com/grafana/grafana/pkg/services/rendering"
|
||||
@ -28,7 +29,7 @@ import (
|
||||
// A subset is needed to make it easier to mock during the tests.
|
||||
type AlertStore interface {
|
||||
GetAllAlertQueryHandler(context.Context, *models.GetAllAlertsQuery) error
|
||||
GetDataSource(context.Context, *models.GetDataSourceQuery) error
|
||||
GetDataSource(context.Context, *datasources.GetDataSourceQuery) error
|
||||
SetAlertNotificationStateToCompleteCommand(context.Context, *models.SetAlertNotificationStateToCompleteCommand) error
|
||||
SetAlertNotificationStateToPendingCommand(context.Context, *models.SetAlertNotificationStateToPendingCommand) error
|
||||
GetAlertNotificationUidWithId(context.Context, *models.GetAlertNotificationUidQuery) error
|
||||
|
@ -7,14 +7,15 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/infra/usagestats"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type FakeEvalHandler struct {
|
||||
@ -45,12 +46,12 @@ func (handler *FakeResultHandler) handle(evalContext *EvalContext) error {
|
||||
// A mock implementation of the AlertStore interface, allowing to override certain methods individually
|
||||
type AlertStoreMock struct {
|
||||
getAllAlerts func(context.Context, *models.GetAllAlertsQuery) error
|
||||
getDataSource func(context.Context, *models.GetDataSourceQuery) error
|
||||
getDataSource func(context.Context, *datasources.GetDataSourceQuery) error
|
||||
getAlertNotificationsWithUidToSend func(ctx context.Context, query *models.GetAlertNotificationsWithUidToSendQuery) error
|
||||
getOrCreateNotificationState func(ctx context.Context, query *models.GetOrCreateNotificationStateQuery) error
|
||||
}
|
||||
|
||||
func (a *AlertStoreMock) GetDataSource(c context.Context, cmd *models.GetDataSourceQuery) error {
|
||||
func (a *AlertStoreMock) GetDataSource(c context.Context, cmd *datasources.GetDataSourceQuery) error {
|
||||
if a.getDataSource != nil {
|
||||
return a.getDataSource(c, cmd)
|
||||
}
|
||||
@ -120,8 +121,8 @@ func TestEngineProcessJob(t *testing.T) {
|
||||
return nil
|
||||
}
|
||||
|
||||
store.getDataSource = func(ctx context.Context, q *models.GetDataSourceQuery) error {
|
||||
q.Result = &models.DataSource{Id: 1, Type: models.DS_PROMETHEUS}
|
||||
store.getDataSource = func(ctx context.Context, q *datasources.GetDataSourceQuery) error {
|
||||
q.Result = &datasources.DataSource{Id: 1, Type: datasources.DS_PROMETHEUS}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ func ProvideDashAlertExtractorService(datasourcePermissionsService permissions.D
|
||||
}
|
||||
}
|
||||
|
||||
func (e *DashAlertExtractorService) lookupQueryDataSource(ctx context.Context, panel *simplejson.Json, panelQuery *simplejson.Json, orgID int64) (*models.DataSource, error) {
|
||||
func (e *DashAlertExtractorService) lookupQueryDataSource(ctx context.Context, panel *simplejson.Json, panelQuery *simplejson.Json, orgID int64) (*datasources.DataSource, error) {
|
||||
dsName := ""
|
||||
dsUid := ""
|
||||
|
||||
@ -52,14 +52,14 @@ func (e *DashAlertExtractorService) lookupQueryDataSource(ctx context.Context, p
|
||||
}
|
||||
|
||||
if dsName == "" && dsUid == "" {
|
||||
query := &models.GetDefaultDataSourceQuery{OrgId: orgID}
|
||||
query := &datasources.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: orgID}
|
||||
query := &datasources.GetDataSourceQuery{Name: dsName, Uid: dsUid, OrgId: orgID}
|
||||
if err := e.datasourceService.GetDataSource(ctx, query); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -208,9 +208,9 @@ func (e *DashAlertExtractorService) getAlertFromPanels(ctx context.Context, json
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dsFilterQuery := models.DatasourcesPermissionFilterQuery{
|
||||
dsFilterQuery := datasources.DatasourcesPermissionFilterQuery{
|
||||
User: dashAlertInfo.User,
|
||||
Datasources: []*models.DataSource{datasource},
|
||||
Datasources: []*datasources.DataSource{datasource},
|
||||
}
|
||||
|
||||
if err := e.datasourcePermissionsService.FilterDatasourcesBasedOnQueryPermissions(ctx, &dsFilterQuery); err != nil {
|
||||
@ -218,7 +218,7 @@ func (e *DashAlertExtractorService) getAlertFromPanels(ctx context.Context, json
|
||||
return nil, err
|
||||
}
|
||||
} else if len(dsFilterQuery.Result) == 0 {
|
||||
return nil, models.ErrDataSourceAccessDenied
|
||||
return nil, datasources.ErrDataSourceAccessDenied
|
||||
}
|
||||
|
||||
jsonQuery.SetPath([]string{"datasourceId"}, datasource.Id)
|
||||
|
@ -7,14 +7,15 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"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/grafana/grafana/pkg/services/sqlstore/mockstore"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestAlertRuleExtraction(t *testing.T) {
|
||||
@ -23,14 +24,14 @@ 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"}
|
||||
defaultDs := &datasources.DataSource{Id: 12, OrgId: 1, Name: "I am default", IsDefault: true, Uid: "def-uid"}
|
||||
graphite2Ds := &datasources.DataSource{Id: 15, OrgId: 1, Name: "graphite2", Uid: "graphite2-uid"}
|
||||
|
||||
json, err := ioutil.ReadFile("./testdata/graphite-alert.json")
|
||||
require.Nil(t, err)
|
||||
|
||||
dsPermissions := permissions.NewMockDatasourcePermissionService()
|
||||
dsPermissions.DsResult = []*models.DataSource{
|
||||
dsPermissions.DsResult = []*datasources.DataSource{
|
||||
{
|
||||
Id: 1,
|
||||
},
|
||||
@ -69,7 +70,7 @@ func TestAlertRuleExtraction(t *testing.T) {
|
||||
dashJSON, err := simplejson.NewJson(json)
|
||||
require.Nil(t, err)
|
||||
|
||||
dsService.ExpectedDatasource = &models.DataSource{Id: 12}
|
||||
dsService.ExpectedDatasource = &datasources.DataSource{Id: 12}
|
||||
alerts, err := extractor.GetAlerts(context.Background(), DashAlertInfo{
|
||||
User: nil,
|
||||
Dash: models.NewDashboardFromJson(dashJSON),
|
||||
@ -168,7 +169,7 @@ func TestAlertRuleExtraction(t *testing.T) {
|
||||
dashJSON, err := simplejson.NewJson(panelWithoutSpecifiedDatasource)
|
||||
require.Nil(t, err)
|
||||
|
||||
dsService.ExpectedDatasource = &models.DataSource{Id: 12}
|
||||
dsService.ExpectedDatasource = &datasources.DataSource{Id: 12}
|
||||
alerts, err := extractor.GetAlerts(context.Background(), DashAlertInfo{
|
||||
User: nil,
|
||||
Dash: models.NewDashboardFromJson(dashJSON),
|
||||
@ -305,7 +306,7 @@ func TestFilterPermissionsErrors(t *testing.T) {
|
||||
})
|
||||
|
||||
// mock data
|
||||
defaultDs := &models.DataSource{Id: 12, OrgId: 1, Name: "I am default", IsDefault: true, Uid: "def-uid"}
|
||||
defaultDs := &datasources.DataSource{Id: 12, OrgId: 1, Name: "I am default", IsDefault: true, Uid: "def-uid"}
|
||||
|
||||
json, err := ioutil.ReadFile("./testdata/graphite-alert.json")
|
||||
require.Nil(t, err)
|
||||
@ -318,13 +319,13 @@ func TestFilterPermissionsErrors(t *testing.T) {
|
||||
|
||||
tc := []struct {
|
||||
name string
|
||||
result []*models.DataSource
|
||||
result []*datasources.DataSource
|
||||
err error
|
||||
expectedErr error
|
||||
}{
|
||||
{
|
||||
"Data sources are filtered and return results don't return an error",
|
||||
[]*models.DataSource{defaultDs},
|
||||
[]*datasources.DataSource{defaultDs},
|
||||
nil,
|
||||
nil,
|
||||
},
|
||||
@ -332,7 +333,7 @@ func TestFilterPermissionsErrors(t *testing.T) {
|
||||
"Data sources are filtered but return empty results should return error",
|
||||
nil,
|
||||
nil,
|
||||
models.ErrDataSourceAccessDenied,
|
||||
datasources.ErrDataSourceAccessDenied,
|
||||
},
|
||||
{
|
||||
"Using default OSS implementation doesn't return an error",
|
||||
@ -363,16 +364,16 @@ func TestFilterPermissionsErrors(t *testing.T) {
|
||||
}
|
||||
|
||||
type fakeDatasourceService struct {
|
||||
ExpectedDatasource *models.DataSource
|
||||
ExpectedDatasource *datasources.DataSource
|
||||
datasources.DataSourceService
|
||||
}
|
||||
|
||||
func (f *fakeDatasourceService) GetDefaultDataSource(ctx context.Context, query *models.GetDefaultDataSourceQuery) error {
|
||||
func (f *fakeDatasourceService) GetDefaultDataSource(ctx context.Context, query *datasources.GetDefaultDataSourceQuery) error {
|
||||
query.Result = f.ExpectedDatasource
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *fakeDatasourceService) GetDataSource(ctx context.Context, query *models.GetDataSourceQuery) error {
|
||||
func (f *fakeDatasourceService) GetDataSource(ctx context.Context, query *datasources.GetDataSourceQuery) error {
|
||||
query.Result = f.ExpectedDatasource
|
||||
return nil
|
||||
}
|
||||
|
@ -92,18 +92,18 @@ func (p *DataSourceProxyService) ProxyDatasourceRequestWithID(c *models.ReqConte
|
||||
}
|
||||
|
||||
func toAPIError(c *models.ReqContext, err error) {
|
||||
if errors.Is(err, models.ErrDataSourceAccessDenied) {
|
||||
if errors.Is(err, datasources.ErrDataSourceAccessDenied) {
|
||||
c.JsonApiErr(http.StatusForbidden, "Access denied to datasource", err)
|
||||
return
|
||||
}
|
||||
if errors.Is(err, models.ErrDataSourceNotFound) {
|
||||
if errors.Is(err, datasources.ErrDataSourceNotFound) {
|
||||
c.JsonApiErr(http.StatusNotFound, "Unable to find datasource", err)
|
||||
return
|
||||
}
|
||||
c.JsonApiErr(http.StatusInternalServerError, "Unable to load datasource meta data", err)
|
||||
}
|
||||
|
||||
func (p *DataSourceProxyService) proxyDatasourceRequest(c *models.ReqContext, ds *models.DataSource) {
|
||||
func (p *DataSourceProxyService) proxyDatasourceRequest(c *models.ReqContext, ds *datasources.DataSource) {
|
||||
err := p.PluginRequestValidator.Validate(ds.Url, c.Req)
|
||||
if err != nil {
|
||||
c.JsonApiErr(http.StatusForbidden, "Access denied", err)
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"net/http"
|
||||
|
||||
sdkhttpclient "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/httpclient"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
@ -12,51 +13,51 @@ import (
|
||||
// DataSourceService interface for interacting with datasources.
|
||||
type DataSourceService interface {
|
||||
// GetDataSource gets a datasource.
|
||||
GetDataSource(ctx context.Context, query *models.GetDataSourceQuery) error
|
||||
GetDataSource(ctx context.Context, query *GetDataSourceQuery) error
|
||||
|
||||
// GetDataSources gets datasources.
|
||||
GetDataSources(ctx context.Context, query *models.GetDataSourcesQuery) error
|
||||
GetDataSources(ctx context.Context, query *GetDataSourcesQuery) error
|
||||
|
||||
// GetDataSourcesByType gets datasources by type.
|
||||
GetDataSourcesByType(ctx context.Context, query *models.GetDataSourcesByTypeQuery) error
|
||||
GetDataSourcesByType(ctx context.Context, query *GetDataSourcesByTypeQuery) error
|
||||
|
||||
// AddDataSource adds a new datasource.
|
||||
AddDataSource(ctx context.Context, cmd *models.AddDataSourceCommand) error
|
||||
AddDataSource(ctx context.Context, cmd *AddDataSourceCommand) error
|
||||
|
||||
// DeleteDataSource deletes an existing datasource.
|
||||
DeleteDataSource(ctx context.Context, cmd *models.DeleteDataSourceCommand) error
|
||||
DeleteDataSource(ctx context.Context, cmd *DeleteDataSourceCommand) error
|
||||
|
||||
// UpdateDataSource updates an existing datasource.
|
||||
UpdateDataSource(ctx context.Context, cmd *models.UpdateDataSourceCommand) error
|
||||
UpdateDataSource(ctx context.Context, cmd *UpdateDataSourceCommand) error
|
||||
|
||||
// GetDefaultDataSource gets the default datasource.
|
||||
GetDefaultDataSource(ctx context.Context, query *models.GetDefaultDataSourceQuery) error
|
||||
GetDefaultDataSource(ctx context.Context, query *GetDefaultDataSourceQuery) error
|
||||
|
||||
// GetHTTPTransport gets a datasource specific HTTP transport.
|
||||
GetHTTPTransport(ctx context.Context, ds *models.DataSource, provider httpclient.Provider, customMiddlewares ...sdkhttpclient.Middleware) (http.RoundTripper, error)
|
||||
GetHTTPTransport(ctx context.Context, ds *DataSource, provider httpclient.Provider, customMiddlewares ...sdkhttpclient.Middleware) (http.RoundTripper, error)
|
||||
|
||||
// DecryptedValues decrypts the encrypted secureJSONData of the provided datasource and
|
||||
// returns the decrypted values.
|
||||
DecryptedValues(ctx context.Context, ds *models.DataSource) (map[string]string, error)
|
||||
DecryptedValues(ctx context.Context, ds *DataSource) (map[string]string, error)
|
||||
|
||||
// DecryptedValue decrypts the encrypted datasource secureJSONData identified by key
|
||||
// and returns the decrypted value.
|
||||
DecryptedValue(ctx context.Context, ds *models.DataSource, key string) (string, bool, error)
|
||||
DecryptedValue(ctx context.Context, ds *DataSource, key string) (string, bool, error)
|
||||
|
||||
// DecryptedBasicAuthPassword decrypts the encrypted datasource basic authentication
|
||||
// password and returns the decrypted value.
|
||||
DecryptedBasicAuthPassword(ctx context.Context, ds *models.DataSource) (string, error)
|
||||
DecryptedBasicAuthPassword(ctx context.Context, ds *DataSource) (string, error)
|
||||
|
||||
// DecryptedPassword decrypts the encrypted datasource password and returns the
|
||||
// decrypted value.
|
||||
DecryptedPassword(ctx context.Context, ds *models.DataSource) (string, error)
|
||||
DecryptedPassword(ctx context.Context, ds *DataSource) (string, error)
|
||||
}
|
||||
|
||||
// CacheService interface for retrieving a cached datasource.
|
||||
type CacheService interface {
|
||||
// GetDatasource gets a datasource identified by datasource numeric identifier.
|
||||
GetDatasource(ctx context.Context, datasourceID int64, user *models.SignedInUser, skipCache bool) (*models.DataSource, error)
|
||||
GetDatasource(ctx context.Context, datasourceID int64, user *models.SignedInUser, skipCache bool) (*DataSource, error)
|
||||
|
||||
// GetDatasourceByUID gets a datasource identified by datasource unique identifier (UID).
|
||||
GetDatasourceByUID(ctx context.Context, datasourceUID string, user *models.SignedInUser, skipCache bool) (*models.DataSource, error)
|
||||
GetDatasourceByUID(ctx context.Context, datasourceUID string, user *models.SignedInUser, skipCache bool) (*DataSource, error)
|
||||
}
|
||||
|
13
pkg/services/datasources/errors.go
Normal file
13
pkg/services/datasources/errors.go
Normal file
@ -0,0 +1,13 @@
|
||||
package datasources
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
ErrDataSourceNotFound = errors.New("data source not found")
|
||||
ErrDataSourceNameExists = errors.New("data source with the same name already exists")
|
||||
ErrDataSourceUidExists = errors.New("data source with the same uid already exists")
|
||||
ErrDataSourceUpdatingOldVersion = errors.New("trying to update old version of datasource")
|
||||
ErrDataSourceAccessDenied = errors.New("data source access denied")
|
||||
ErrDataSourceFailedGenerateUniqueUid = errors.New("failed to generate unique datasource ID")
|
||||
ErrDataSourceIdentifierNotSet = errors.New("unique identifier and org id are needed to be able to get or delete a datasource")
|
||||
)
|
@ -8,25 +8,25 @@ import (
|
||||
)
|
||||
|
||||
type FakeCacheService struct {
|
||||
DataSources []*models.DataSource
|
||||
DataSources []*datasources.DataSource
|
||||
}
|
||||
|
||||
var _ datasources.CacheService = &FakeCacheService{}
|
||||
|
||||
func (c *FakeCacheService) GetDatasource(ctx context.Context, datasourceID int64, user *models.SignedInUser, skipCache bool) (*models.DataSource, error) {
|
||||
func (c *FakeCacheService) GetDatasource(ctx context.Context, datasourceID int64, user *models.SignedInUser, skipCache bool) (*datasources.DataSource, error) {
|
||||
for _, datasource := range c.DataSources {
|
||||
if datasource.Id == datasourceID {
|
||||
return datasource, nil
|
||||
}
|
||||
}
|
||||
return nil, models.ErrDataSourceNotFound
|
||||
return nil, datasources.ErrDataSourceNotFound
|
||||
}
|
||||
|
||||
func (c *FakeCacheService) GetDatasourceByUID(ctx context.Context, datasourceUID string, user *models.SignedInUser, skipCache bool) (*models.DataSource, error) {
|
||||
func (c *FakeCacheService) GetDatasourceByUID(ctx context.Context, datasourceUID string, user *models.SignedInUser, skipCache bool) (*datasources.DataSource, error) {
|
||||
for _, datasource := range c.DataSources {
|
||||
if datasource.Uid == datasourceUID {
|
||||
return datasource, nil
|
||||
}
|
||||
}
|
||||
return nil, models.ErrDataSourceNotFound
|
||||
return nil, datasources.ErrDataSourceNotFound
|
||||
}
|
||||
|
@ -5,19 +5,19 @@ import (
|
||||
"net/http"
|
||||
|
||||
sdkhttpclient "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/httpclient"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
)
|
||||
|
||||
type FakeDataSourceService struct {
|
||||
lastId int64
|
||||
DataSources []*models.DataSource
|
||||
DataSources []*datasources.DataSource
|
||||
}
|
||||
|
||||
var _ datasources.DataSourceService = &FakeDataSourceService{}
|
||||
|
||||
func (s *FakeDataSourceService) GetDataSource(ctx context.Context, query *models.GetDataSourceQuery) error {
|
||||
func (s *FakeDataSourceService) GetDataSource(ctx context.Context, query *datasources.GetDataSourceQuery) error {
|
||||
for _, datasource := range s.DataSources {
|
||||
idMatch := query.Id != 0 && query.Id == datasource.Id
|
||||
uidMatch := query.Uid != "" && query.Uid == datasource.Uid
|
||||
@ -28,10 +28,10 @@ func (s *FakeDataSourceService) GetDataSource(ctx context.Context, query *models
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return models.ErrDataSourceNotFound
|
||||
return datasources.ErrDataSourceNotFound
|
||||
}
|
||||
|
||||
func (s *FakeDataSourceService) GetDataSources(ctx context.Context, query *models.GetDataSourcesQuery) error {
|
||||
func (s *FakeDataSourceService) GetDataSources(ctx context.Context, query *datasources.GetDataSourcesQuery) error {
|
||||
for _, datasource := range s.DataSources {
|
||||
orgMatch := query.OrgId != 0 && query.OrgId == datasource.OrgId
|
||||
if orgMatch {
|
||||
@ -41,7 +41,7 @@ func (s *FakeDataSourceService) GetDataSources(ctx context.Context, query *model
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *FakeDataSourceService) GetDataSourcesByType(ctx context.Context, query *models.GetDataSourcesByTypeQuery) error {
|
||||
func (s *FakeDataSourceService) GetDataSourcesByType(ctx context.Context, query *datasources.GetDataSourcesByTypeQuery) error {
|
||||
for _, datasource := range s.DataSources {
|
||||
typeMatch := query.Type != "" && query.Type == datasource.Type
|
||||
if typeMatch {
|
||||
@ -51,11 +51,11 @@ func (s *FakeDataSourceService) GetDataSourcesByType(ctx context.Context, query
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *FakeDataSourceService) AddDataSource(ctx context.Context, cmd *models.AddDataSourceCommand) error {
|
||||
func (s *FakeDataSourceService) AddDataSource(ctx context.Context, cmd *datasources.AddDataSourceCommand) error {
|
||||
if s.lastId == 0 {
|
||||
s.lastId = int64(len(s.DataSources) - 1)
|
||||
}
|
||||
cmd.Result = &models.DataSource{
|
||||
cmd.Result = &datasources.DataSource{
|
||||
Id: s.lastId + 1,
|
||||
Name: cmd.Name,
|
||||
Type: cmd.Type,
|
||||
@ -66,7 +66,7 @@ func (s *FakeDataSourceService) AddDataSource(ctx context.Context, cmd *models.A
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *FakeDataSourceService) DeleteDataSource(ctx context.Context, cmd *models.DeleteDataSourceCommand) error {
|
||||
func (s *FakeDataSourceService) DeleteDataSource(ctx context.Context, cmd *datasources.DeleteDataSourceCommand) error {
|
||||
for i, datasource := range s.DataSources {
|
||||
idMatch := cmd.ID != 0 && cmd.ID == datasource.Id
|
||||
uidMatch := cmd.UID != "" && cmd.UID == datasource.Uid
|
||||
@ -76,10 +76,10 @@ func (s *FakeDataSourceService) DeleteDataSource(ctx context.Context, cmd *model
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return models.ErrDataSourceNotFound
|
||||
return datasources.ErrDataSourceNotFound
|
||||
}
|
||||
|
||||
func (s *FakeDataSourceService) UpdateDataSource(ctx context.Context, cmd *models.UpdateDataSourceCommand) error {
|
||||
func (s *FakeDataSourceService) UpdateDataSource(ctx context.Context, cmd *datasources.UpdateDataSourceCommand) error {
|
||||
for _, datasource := range s.DataSources {
|
||||
idMatch := cmd.Id != 0 && cmd.Id == datasource.Id
|
||||
uidMatch := cmd.Uid != "" && cmd.Uid == datasource.Uid
|
||||
@ -91,14 +91,14 @@ func (s *FakeDataSourceService) UpdateDataSource(ctx context.Context, cmd *model
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return models.ErrDataSourceNotFound
|
||||
return datasources.ErrDataSourceNotFound
|
||||
}
|
||||
|
||||
func (s *FakeDataSourceService) GetDefaultDataSource(ctx context.Context, query *models.GetDefaultDataSourceQuery) error {
|
||||
func (s *FakeDataSourceService) GetDefaultDataSource(ctx context.Context, query *datasources.GetDefaultDataSourceQuery) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *FakeDataSourceService) GetHTTPTransport(ctx context.Context, ds *models.DataSource, provider httpclient.Provider, customMiddlewares ...sdkhttpclient.Middleware) (http.RoundTripper, error) {
|
||||
func (s *FakeDataSourceService) GetHTTPTransport(ctx context.Context, ds *datasources.DataSource, provider httpclient.Provider, customMiddlewares ...sdkhttpclient.Middleware) (http.RoundTripper, error) {
|
||||
rt, err := provider.GetTransport(sdkhttpclient.Options{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -106,19 +106,19 @@ func (s *FakeDataSourceService) GetHTTPTransport(ctx context.Context, ds *models
|
||||
return rt, nil
|
||||
}
|
||||
|
||||
func (s *FakeDataSourceService) DecryptedValues(ctx context.Context, ds *models.DataSource) (map[string]string, error) {
|
||||
func (s *FakeDataSourceService) DecryptedValues(ctx context.Context, ds *datasources.DataSource) (map[string]string, error) {
|
||||
values := make(map[string]string)
|
||||
return values, nil
|
||||
}
|
||||
|
||||
func (s *FakeDataSourceService) DecryptedValue(ctx context.Context, ds *models.DataSource, key string) (string, bool, error) {
|
||||
func (s *FakeDataSourceService) DecryptedValue(ctx context.Context, ds *datasources.DataSource, key string) (string, bool, error) {
|
||||
return "", false, nil
|
||||
}
|
||||
|
||||
func (s *FakeDataSourceService) DecryptedBasicAuthPassword(ctx context.Context, ds *models.DataSource) (string, error) {
|
||||
func (s *FakeDataSourceService) DecryptedBasicAuthPassword(ctx context.Context, ds *datasources.DataSource) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
func (s *FakeDataSourceService) DecryptedPassword(ctx context.Context, ds *models.DataSource) (string, error) {
|
||||
func (s *FakeDataSourceService) DecryptedPassword(ctx context.Context, ds *datasources.DataSource) (string, error) {
|
||||
return "", nil
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
package models
|
||||
package datasources
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -28,17 +28,6 @@ const (
|
||||
DS_ES_OPENSEARCH = "grafana-opensearch-datasource"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrDataSourceNotFound = errors.New("data source not found")
|
||||
ErrDataSourceNameExists = errors.New("data source with the same name already exists")
|
||||
ErrDataSourceUidExists = errors.New("data source with the same uid already exists")
|
||||
ErrDataSourceUpdatingOldVersion = errors.New("trying to update old version of datasource")
|
||||
ErrDatasourceIsReadOnly = errors.New("data source is readonly, can only be updated from configuration")
|
||||
ErrDataSourceAccessDenied = errors.New("data source access denied")
|
||||
ErrDataSourceFailedGenerateUniqueUid = errors.New("failed to generate unique datasource ID")
|
||||
ErrDataSourceIdentifierNotSet = errors.New("unique identifier and org id are needed to be able to get or delete a datasource")
|
||||
)
|
||||
|
||||
type DsAccess string
|
||||
|
||||
type DataSource struct {
|
||||
@ -167,7 +156,7 @@ type UpdateSecretFn func() error
|
||||
type GetDataSourcesQuery struct {
|
||||
OrgId int64
|
||||
DataSourceLimit int
|
||||
User *SignedInUser
|
||||
User *models.SignedInUser
|
||||
Result []*DataSource
|
||||
}
|
||||
|
||||
@ -178,7 +167,7 @@ type GetDataSourcesByTypeQuery struct {
|
||||
|
||||
type GetDefaultDataSourceQuery struct {
|
||||
OrgId int64
|
||||
User *SignedInUser
|
||||
User *models.SignedInUser
|
||||
Result *DataSource
|
||||
}
|
||||
|
||||
@ -220,7 +209,7 @@ func (p DsPermissionType) String() string {
|
||||
}
|
||||
|
||||
type DatasourcesPermissionFilterQuery struct {
|
||||
User *SignedInUser
|
||||
User *models.SignedInUser
|
||||
Datasources []*DataSource
|
||||
Result []*DataSource
|
||||
}
|
@ -4,17 +4,17 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
)
|
||||
|
||||
var ErrNotImplemented = errors.New("not implemented")
|
||||
|
||||
type DatasourcePermissionsService interface {
|
||||
FilterDatasourcesBasedOnQueryPermissions(ctx context.Context, cmd *models.DatasourcesPermissionFilterQuery) error
|
||||
FilterDatasourcesBasedOnQueryPermissions(ctx context.Context, cmd *datasources.DatasourcesPermissionFilterQuery) error
|
||||
}
|
||||
|
||||
// dummy method
|
||||
func (hs *OSSDatasourcePermissionsService) FilterDatasourcesBasedOnQueryPermissions(ctx context.Context, cmd *models.DatasourcesPermissionFilterQuery) error {
|
||||
func (hs *OSSDatasourcePermissionsService) FilterDatasourcesBasedOnQueryPermissions(ctx context.Context, cmd *datasources.DatasourcesPermissionFilterQuery) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
|
@ -3,15 +3,15 @@ package permissions
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
)
|
||||
|
||||
type mockDatasourcePermissionService struct {
|
||||
DsResult []*models.DataSource
|
||||
DsResult []*datasources.DataSource
|
||||
ErrResult error
|
||||
}
|
||||
|
||||
func (m *mockDatasourcePermissionService) FilterDatasourcesBasedOnQueryPermissions(ctx context.Context, cmd *models.DatasourcesPermissionFilterQuery) error {
|
||||
func (m *mockDatasourcePermissionService) FilterDatasourcesBasedOnQueryPermissions(ctx context.Context, cmd *datasources.DatasourcesPermissionFilterQuery) error {
|
||||
cmd.Result = m.DsResult
|
||||
return m.ErrResult
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/localcache"
|
||||
"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/sqlstore"
|
||||
)
|
||||
|
||||
@ -30,12 +31,12 @@ func (dc *CacheServiceImpl) GetDatasource(
|
||||
datasourceID int64,
|
||||
user *models.SignedInUser,
|
||||
skipCache bool,
|
||||
) (*models.DataSource, error) {
|
||||
) (*datasources.DataSource, error) {
|
||||
cacheKey := idKey(datasourceID)
|
||||
|
||||
if !skipCache {
|
||||
if cached, found := dc.CacheService.Get(cacheKey); found {
|
||||
ds := cached.(*models.DataSource)
|
||||
ds := cached.(*datasources.DataSource)
|
||||
if ds.OrgId == user.OrgId {
|
||||
return ds, nil
|
||||
}
|
||||
@ -44,7 +45,7 @@ func (dc *CacheServiceImpl) GetDatasource(
|
||||
|
||||
dc.logger.Debug("Querying for data source via SQL store", "id", datasourceID, "orgId", user.OrgId)
|
||||
|
||||
query := &models.GetDataSourceQuery{Id: datasourceID, OrgId: user.OrgId}
|
||||
query := &datasources.GetDataSourceQuery{Id: datasourceID, OrgId: user.OrgId}
|
||||
err := dc.SQLStore.GetDataSource(ctx, query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -64,7 +65,7 @@ func (dc *CacheServiceImpl) GetDatasourceByUID(
|
||||
datasourceUID string,
|
||||
user *models.SignedInUser,
|
||||
skipCache bool,
|
||||
) (*models.DataSource, error) {
|
||||
) (*datasources.DataSource, error) {
|
||||
if datasourceUID == "" {
|
||||
return nil, fmt.Errorf("can not get data source by uid, uid is empty")
|
||||
}
|
||||
@ -75,7 +76,7 @@ func (dc *CacheServiceImpl) GetDatasourceByUID(
|
||||
|
||||
if !skipCache {
|
||||
if cached, found := dc.CacheService.Get(uidCacheKey); found {
|
||||
ds := cached.(*models.DataSource)
|
||||
ds := cached.(*datasources.DataSource)
|
||||
if ds.OrgId == user.OrgId {
|
||||
return ds, nil
|
||||
}
|
||||
@ -83,7 +84,7 @@ func (dc *CacheServiceImpl) GetDatasourceByUID(
|
||||
}
|
||||
|
||||
dc.logger.Debug("Querying for data source via SQL store", "uid", datasourceUID, "orgId", user.OrgId)
|
||||
query := &models.GetDataSourceQuery{Uid: datasourceUID, OrgId: user.OrgId}
|
||||
query := &datasources.GetDataSourceQuery{Uid: datasourceUID, OrgId: user.OrgId}
|
||||
err := dc.SQLStore.GetDataSource(ctx, query)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -15,7 +15,6 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/httpclient"
|
||||
"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/featuremgmt"
|
||||
@ -73,7 +72,7 @@ func ProvideService(
|
||||
// DataSourceRetriever interface for retrieving a datasource.
|
||||
type DataSourceRetriever interface {
|
||||
// GetDataSource gets a datasource.
|
||||
GetDataSource(ctx context.Context, query *models.GetDataSourceQuery) error
|
||||
GetDataSource(ctx context.Context, query *datasources.GetDataSourceQuery) error
|
||||
}
|
||||
|
||||
const secretType = "datasource"
|
||||
@ -92,7 +91,7 @@ func NewNameScopeResolver(db DataSourceRetriever) (string, accesscontrol.ScopeAt
|
||||
return nil, accesscontrol.ErrInvalidScope
|
||||
}
|
||||
|
||||
query := models.GetDataSourceQuery{Name: dsName, OrgId: orgID}
|
||||
query := datasources.GetDataSourceQuery{Name: dsName, OrgId: orgID}
|
||||
if err := db.GetDataSource(ctx, &query); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -120,7 +119,7 @@ func NewIDScopeResolver(db DataSourceRetriever) (string, accesscontrol.ScopeAttr
|
||||
return nil, accesscontrol.ErrInvalidScope
|
||||
}
|
||||
|
||||
query := models.GetDataSourceQuery{Id: dsID, OrgId: orgID}
|
||||
query := datasources.GetDataSourceQuery{Id: dsID, OrgId: orgID}
|
||||
if err := db.GetDataSource(ctx, &query); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -129,19 +128,19 @@ func NewIDScopeResolver(db DataSourceRetriever) (string, accesscontrol.ScopeAttr
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Service) GetDataSource(ctx context.Context, query *models.GetDataSourceQuery) error {
|
||||
func (s *Service) GetDataSource(ctx context.Context, query *datasources.GetDataSourceQuery) error {
|
||||
return s.SQLStore.GetDataSource(ctx, query)
|
||||
}
|
||||
|
||||
func (s *Service) GetDataSources(ctx context.Context, query *models.GetDataSourcesQuery) error {
|
||||
func (s *Service) GetDataSources(ctx context.Context, query *datasources.GetDataSourcesQuery) error {
|
||||
return s.SQLStore.GetDataSources(ctx, query)
|
||||
}
|
||||
|
||||
func (s *Service) GetDataSourcesByType(ctx context.Context, query *models.GetDataSourcesByTypeQuery) error {
|
||||
func (s *Service) GetDataSourcesByType(ctx context.Context, query *datasources.GetDataSourcesByTypeQuery) error {
|
||||
return s.SQLStore.GetDataSourcesByType(ctx, query)
|
||||
}
|
||||
|
||||
func (s *Service) AddDataSource(ctx context.Context, cmd *models.AddDataSourceCommand) error {
|
||||
func (s *Service) AddDataSource(ctx context.Context, cmd *datasources.AddDataSourceCommand) error {
|
||||
return s.SQLStore.InTransaction(ctx, func(ctx context.Context) error {
|
||||
var err error
|
||||
// this is here for backwards compatibility
|
||||
@ -185,7 +184,7 @@ func (s *Service) AddDataSource(ctx context.Context, cmd *models.AddDataSourceCo
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Service) DeleteDataSource(ctx context.Context, cmd *models.DeleteDataSourceCommand) error {
|
||||
func (s *Service) DeleteDataSource(ctx context.Context, cmd *datasources.DeleteDataSourceCommand) error {
|
||||
return s.SQLStore.InTransaction(ctx, func(ctx context.Context) error {
|
||||
cmd.UpdateSecretFn = func() error {
|
||||
return s.SecretsStore.Del(ctx, cmd.OrgID, cmd.Name, secretType)
|
||||
@ -195,11 +194,11 @@ func (s *Service) DeleteDataSource(ctx context.Context, cmd *models.DeleteDataSo
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Service) UpdateDataSource(ctx context.Context, cmd *models.UpdateDataSourceCommand) error {
|
||||
func (s *Service) UpdateDataSource(ctx context.Context, cmd *datasources.UpdateDataSourceCommand) error {
|
||||
return s.SQLStore.InTransaction(ctx, func(ctx context.Context) error {
|
||||
var err error
|
||||
|
||||
query := &models.GetDataSourceQuery{
|
||||
query := &datasources.GetDataSourceQuery{
|
||||
Id: cmd.Id,
|
||||
OrgId: cmd.OrgId,
|
||||
}
|
||||
@ -234,11 +233,11 @@ func (s *Service) UpdateDataSource(ctx context.Context, cmd *models.UpdateDataSo
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Service) GetDefaultDataSource(ctx context.Context, query *models.GetDefaultDataSourceQuery) error {
|
||||
func (s *Service) GetDefaultDataSource(ctx context.Context, query *datasources.GetDefaultDataSourceQuery) error {
|
||||
return s.SQLStore.GetDefaultDataSource(ctx, query)
|
||||
}
|
||||
|
||||
func (s *Service) GetHTTPClient(ctx context.Context, ds *models.DataSource, provider httpclient.Provider) (*http.Client, error) {
|
||||
func (s *Service) GetHTTPClient(ctx context.Context, ds *datasources.DataSource, provider httpclient.Provider) (*http.Client, error) {
|
||||
transport, err := s.GetHTTPTransport(ctx, ds, provider)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -250,7 +249,7 @@ func (s *Service) GetHTTPClient(ctx context.Context, ds *models.DataSource, prov
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Service) GetHTTPTransport(ctx context.Context, ds *models.DataSource, provider httpclient.Provider,
|
||||
func (s *Service) GetHTTPTransport(ctx context.Context, ds *datasources.DataSource, provider httpclient.Provider,
|
||||
customMiddlewares ...sdkhttpclient.Middleware) (http.RoundTripper, error) {
|
||||
s.ptc.Lock()
|
||||
defer s.ptc.Unlock()
|
||||
@ -279,7 +278,7 @@ func (s *Service) GetHTTPTransport(ctx context.Context, ds *models.DataSource, p
|
||||
return rt, nil
|
||||
}
|
||||
|
||||
func (s *Service) GetTLSConfig(ctx context.Context, ds *models.DataSource, httpClientProvider httpclient.Provider) (*tls.Config, error) {
|
||||
func (s *Service) GetTLSConfig(ctx context.Context, ds *datasources.DataSource, httpClientProvider httpclient.Provider) (*tls.Config, error) {
|
||||
opts, err := s.httpClientOptions(ctx, ds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -287,7 +286,7 @@ func (s *Service) GetTLSConfig(ctx context.Context, ds *models.DataSource, httpC
|
||||
return httpClientProvider.GetTLSConfig(*opts)
|
||||
}
|
||||
|
||||
func (s *Service) DecryptedValues(ctx context.Context, ds *models.DataSource) (map[string]string, error) {
|
||||
func (s *Service) DecryptedValues(ctx context.Context, ds *datasources.DataSource) (map[string]string, error) {
|
||||
decryptedValues := make(map[string]string)
|
||||
secret, exist, err := s.SecretsStore.Get(ctx, ds.OrgId, ds.Name, secretType)
|
||||
if err != nil {
|
||||
@ -308,7 +307,7 @@ func (s *Service) DecryptedValues(ctx context.Context, ds *models.DataSource) (m
|
||||
return decryptedValues, nil
|
||||
}
|
||||
|
||||
func (s *Service) MigrateSecrets(ctx context.Context, ds *models.DataSource) (map[string]string, error) {
|
||||
func (s *Service) MigrateSecrets(ctx context.Context, ds *datasources.DataSource) (map[string]string, error) {
|
||||
secureJsonData := make(map[string]string)
|
||||
for k, v := range ds.SecureJsonData {
|
||||
decrypted, err := s.SecretsService.Decrypt(ctx, v)
|
||||
@ -327,7 +326,7 @@ func (s *Service) MigrateSecrets(ctx context.Context, ds *models.DataSource) (ma
|
||||
return secureJsonData, err
|
||||
}
|
||||
|
||||
func (s *Service) DecryptedValue(ctx context.Context, ds *models.DataSource, key string) (string, bool, error) {
|
||||
func (s *Service) DecryptedValue(ctx context.Context, ds *datasources.DataSource, key string) (string, bool, error) {
|
||||
values, err := s.DecryptedValues(ctx, ds)
|
||||
if err != nil {
|
||||
return "", false, err
|
||||
@ -336,7 +335,7 @@ func (s *Service) DecryptedValue(ctx context.Context, ds *models.DataSource, key
|
||||
return value, exists, nil
|
||||
}
|
||||
|
||||
func (s *Service) DecryptedBasicAuthPassword(ctx context.Context, ds *models.DataSource) (string, error) {
|
||||
func (s *Service) DecryptedBasicAuthPassword(ctx context.Context, ds *datasources.DataSource) (string, error) {
|
||||
value, ok, err := s.DecryptedValue(ctx, ds, "basicAuthPassword")
|
||||
if ok {
|
||||
return value, nil
|
||||
@ -345,7 +344,7 @@ func (s *Service) DecryptedBasicAuthPassword(ctx context.Context, ds *models.Dat
|
||||
return "", err
|
||||
}
|
||||
|
||||
func (s *Service) DecryptedPassword(ctx context.Context, ds *models.DataSource) (string, error) {
|
||||
func (s *Service) DecryptedPassword(ctx context.Context, ds *datasources.DataSource) (string, error) {
|
||||
value, ok, err := s.DecryptedValue(ctx, ds, "password")
|
||||
if ok {
|
||||
return value, nil
|
||||
@ -354,7 +353,7 @@ func (s *Service) DecryptedPassword(ctx context.Context, ds *models.DataSource)
|
||||
return "", err
|
||||
}
|
||||
|
||||
func (s *Service) httpClientOptions(ctx context.Context, ds *models.DataSource) (*sdkhttpclient.Options, error) {
|
||||
func (s *Service) httpClientOptions(ctx context.Context, ds *datasources.DataSource) (*sdkhttpclient.Options, error) {
|
||||
tlsOptions, err := s.dsTLSOptions(ctx, ds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -442,7 +441,7 @@ func (s *Service) httpClientOptions(ctx context.Context, ds *models.DataSource)
|
||||
return opts, nil
|
||||
}
|
||||
|
||||
func (s *Service) dsTLSOptions(ctx context.Context, ds *models.DataSource) (sdkhttpclient.TLSOptions, error) {
|
||||
func (s *Service) dsTLSOptions(ctx context.Context, ds *datasources.DataSource) (sdkhttpclient.TLSOptions, error) {
|
||||
var tlsSkipVerify, tlsClientAuth, tlsAuthWithCACert bool
|
||||
var serverName string
|
||||
|
||||
@ -491,7 +490,7 @@ func (s *Service) dsTLSOptions(ctx context.Context, ds *models.DataSource) (sdkh
|
||||
return opts, nil
|
||||
}
|
||||
|
||||
func (s *Service) getTimeout(ds *models.DataSource) time.Duration {
|
||||
func (s *Service) getTimeout(ds *datasources.DataSource) time.Duration {
|
||||
timeout := 0
|
||||
if ds.JsonData != nil {
|
||||
timeout = ds.JsonData.Get("timeout").MustInt()
|
||||
@ -540,16 +539,16 @@ func (s *Service) getCustomHeaders(jsonData *simplejson.Json, decryptedValues ma
|
||||
|
||||
func awsServiceNamespace(dsType string) string {
|
||||
switch dsType {
|
||||
case models.DS_ES, models.DS_ES_OPEN_DISTRO, models.DS_ES_OPENSEARCH:
|
||||
case datasources.DS_ES, datasources.DS_ES_OPEN_DISTRO, datasources.DS_ES_OPENSEARCH:
|
||||
return "es"
|
||||
case models.DS_PROMETHEUS, models.DS_ALERTMANAGER:
|
||||
case datasources.DS_PROMETHEUS, datasources.DS_ALERTMANAGER:
|
||||
return "aps"
|
||||
default:
|
||||
panic(fmt.Sprintf("Unsupported datasource %q", dsType))
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) fillWithSecureJSONData(ctx context.Context, cmd *models.UpdateDataSourceCommand, ds *models.DataSource) error {
|
||||
func (s *Service) fillWithSecureJSONData(ctx context.Context, cmd *datasources.UpdateDataSourceCommand, ds *datasources.DataSource) error {
|
||||
decrypted, err := s.DecryptedValues(ctx, ds)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -10,27 +10,27 @@ import (
|
||||
"time"
|
||||
|
||||
sdkhttpclient "github.com/grafana/grafana-plugin-sdk-go/backend/httpclient"
|
||||
"github.com/grafana/grafana/pkg/services/secrets"
|
||||
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/httpclient"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
acmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/secrets"
|
||||
"github.com/grafana/grafana/pkg/services/secrets/fakes"
|
||||
"github.com/grafana/grafana/pkg/services/secrets/kvstore"
|
||||
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type dataSourceMockRetriever struct {
|
||||
res []*models.DataSource
|
||||
res []*datasources.DataSource
|
||||
}
|
||||
|
||||
func (d *dataSourceMockRetriever) GetDataSource(ctx context.Context, query *models.GetDataSourceQuery) error {
|
||||
func (d *dataSourceMockRetriever) GetDataSource(ctx context.Context, query *datasources.GetDataSourceQuery) error {
|
||||
for _, datasource := range d.res {
|
||||
idMatch := query.Id != 0 && query.Id == datasource.Id
|
||||
uidMatch := query.Uid != "" && query.Uid == datasource.Uid
|
||||
@ -41,11 +41,11 @@ func (d *dataSourceMockRetriever) GetDataSource(ctx context.Context, query *mode
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return models.ErrDataSourceNotFound
|
||||
return datasources.ErrDataSourceNotFound
|
||||
}
|
||||
|
||||
func TestService_NameScopeResolver(t *testing.T) {
|
||||
retriever := &dataSourceMockRetriever{[]*models.DataSource{
|
||||
retriever := &dataSourceMockRetriever{[]*datasources.DataSource{
|
||||
{Name: "test-datasource", Uid: "1"},
|
||||
{Name: "*", Uid: "2"},
|
||||
{Name: ":/*", Uid: "3"},
|
||||
@ -88,7 +88,7 @@ func TestService_NameScopeResolver(t *testing.T) {
|
||||
desc: "unknown datasource",
|
||||
given: "datasources:name:unknown-datasource",
|
||||
want: "",
|
||||
wantErr: models.ErrDataSourceNotFound,
|
||||
wantErr: datasources.ErrDataSourceNotFound,
|
||||
},
|
||||
{
|
||||
desc: "malformed scope",
|
||||
@ -122,7 +122,7 @@ func TestService_NameScopeResolver(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestService_IDScopeResolver(t *testing.T) {
|
||||
retriever := &dataSourceMockRetriever{[]*models.DataSource{
|
||||
retriever := &dataSourceMockRetriever{[]*datasources.DataSource{
|
||||
{Id: 1, Uid: "NnftN9Lnz"},
|
||||
}}
|
||||
|
||||
@ -189,7 +189,7 @@ func TestService_GetHttpTransport(t *testing.T) {
|
||||
},
|
||||
})
|
||||
|
||||
ds := models.DataSource{
|
||||
ds := datasources.DataSource{
|
||||
Id: 1,
|
||||
Url: "http://k8s:8001",
|
||||
Type: "Kubernetes",
|
||||
@ -233,7 +233,7 @@ func TestService_GetHttpTransport(t *testing.T) {
|
||||
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
|
||||
dsService := ProvideService(nil, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService())
|
||||
|
||||
ds := models.DataSource{
|
||||
ds := datasources.DataSource{
|
||||
Id: 1,
|
||||
Url: "http://k8s:8001",
|
||||
Type: "Kubernetes",
|
||||
@ -281,7 +281,7 @@ func TestService_GetHttpTransport(t *testing.T) {
|
||||
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
|
||||
dsService := ProvideService(nil, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService())
|
||||
|
||||
ds := models.DataSource{
|
||||
ds := datasources.DataSource{
|
||||
Id: 1,
|
||||
OrgId: 1,
|
||||
Name: "kubernetes",
|
||||
@ -326,7 +326,7 @@ func TestService_GetHttpTransport(t *testing.T) {
|
||||
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
|
||||
dsService := ProvideService(nil, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService())
|
||||
|
||||
ds := models.DataSource{
|
||||
ds := datasources.DataSource{
|
||||
Id: 1,
|
||||
OrgId: 1,
|
||||
Name: "kubernetes",
|
||||
@ -368,7 +368,7 @@ func TestService_GetHttpTransport(t *testing.T) {
|
||||
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
|
||||
dsService := ProvideService(nil, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService())
|
||||
|
||||
ds := models.DataSource{
|
||||
ds := datasources.DataSource{
|
||||
Id: 1,
|
||||
Url: "http://k8s:8001",
|
||||
Type: "Kubernetes",
|
||||
@ -400,7 +400,7 @@ func TestService_GetHttpTransport(t *testing.T) {
|
||||
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
|
||||
dsService := ProvideService(nil, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService())
|
||||
|
||||
ds := models.DataSource{
|
||||
ds := datasources.DataSource{
|
||||
Id: 1,
|
||||
OrgId: 1,
|
||||
Name: "kubernetes",
|
||||
@ -466,7 +466,7 @@ func TestService_GetHttpTransport(t *testing.T) {
|
||||
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
|
||||
dsService := ProvideService(nil, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService())
|
||||
|
||||
ds := models.DataSource{
|
||||
ds := datasources.DataSource{
|
||||
Id: 1,
|
||||
Url: "http://k8s:8001",
|
||||
Type: "Kubernetes",
|
||||
@ -500,8 +500,8 @@ func TestService_GetHttpTransport(t *testing.T) {
|
||||
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
|
||||
dsService := ProvideService(nil, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService())
|
||||
|
||||
ds := models.DataSource{
|
||||
Type: models.DS_ES,
|
||||
ds := datasources.DataSource{
|
||||
Type: datasources.DS_ES,
|
||||
JsonData: sjson,
|
||||
}
|
||||
|
||||
@ -537,7 +537,7 @@ func TestService_getTimeout(t *testing.T) {
|
||||
dsService := ProvideService(nil, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService())
|
||||
|
||||
for _, tc := range testCases {
|
||||
ds := &models.DataSource{
|
||||
ds := &datasources.DataSource{
|
||||
JsonData: tc.jsonData,
|
||||
}
|
||||
assert.Equal(t, tc.expectedTimeout, dsService.getTimeout(ds))
|
||||
@ -546,7 +546,7 @@ func TestService_getTimeout(t *testing.T) {
|
||||
|
||||
func TestService_GetDecryptedValues(t *testing.T) {
|
||||
t.Run("should migrate and retrieve values from secure json data", func(t *testing.T) {
|
||||
ds := &models.DataSource{
|
||||
ds := &datasources.DataSource{
|
||||
Id: 1,
|
||||
Url: "https://api.example.com",
|
||||
Type: "prometheus",
|
||||
@ -571,7 +571,7 @@ func TestService_GetDecryptedValues(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("should retrieve values from secret store", func(t *testing.T) {
|
||||
ds := &models.DataSource{
|
||||
ds := &datasources.DataSource{
|
||||
Id: 1,
|
||||
Url: "https://api.example.com",
|
||||
Type: "prometheus",
|
||||
|
16
pkg/services/datasources/store.go
Normal file
16
pkg/services/datasources/store.go
Normal file
@ -0,0 +1,16 @@
|
||||
package datasources
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
// Store is the interface for the datasource Service's storage.
|
||||
type Store interface {
|
||||
GetDataSource(context.Context, *GetDataSourceQuery) error
|
||||
GetDataSources(context.Context, *GetDataSourcesQuery) error
|
||||
GetDataSourcesByType(context.Context, *GetDataSourcesByTypeQuery) error
|
||||
GetDefaultDataSource(context.Context, *GetDefaultDataSourceQuery) error
|
||||
DeleteDataSource(context.Context, *DeleteDataSourceCommand) error
|
||||
AddDataSource(context.Context, *AddDataSourceCommand) error
|
||||
UpdateDataSource(context.Context, *UpdateDataSourceCommand) error
|
||||
}
|
@ -593,7 +593,7 @@ func (g *GrafanaLive) handleOnRPC(client *centrifuge.Client, e centrifuge.RPCEve
|
||||
resp, err := g.queryDataService.QueryData(client.Context(), user, false, req, true)
|
||||
if err != nil {
|
||||
logger.Error("Error query data", "user", client.UserID(), "client", client.ID(), "method", e.Method, "error", err)
|
||||
if errors.Is(err, models.ErrDataSourceAccessDenied) {
|
||||
if errors.Is(err, datasources.ErrDataSourceAccessDenied) {
|
||||
return centrifuge.RPCReply{}, ¢rifuge.Error{Code: uint32(http.StatusForbidden), Message: http.StatusText(http.StatusForbidden)}
|
||||
}
|
||||
var badQuery *query.ErrBadQuery
|
||||
|
@ -62,7 +62,7 @@ func TestRouteTestGrafanaRuleConfig(t *testing.T) {
|
||||
{Action: datasources.ActionQuery, Scope: datasources.ScopeProvider.GetResourceScopeUID(data2.DatasourceUID)},
|
||||
})
|
||||
|
||||
ds := &fakes.FakeCacheService{DataSources: []*models2.DataSource{
|
||||
ds := &fakes.FakeCacheService{DataSources: []*datasources.DataSource{
|
||||
{Uid: data1.DatasourceUID},
|
||||
{Uid: data2.DatasourceUID},
|
||||
}}
|
||||
@ -103,7 +103,7 @@ func TestRouteTestGrafanaRuleConfig(t *testing.T) {
|
||||
t.Run("should require user to be signed in", func(t *testing.T) {
|
||||
data1 := models.GenerateAlertQuery()
|
||||
|
||||
ds := &fakes.FakeCacheService{DataSources: []*models2.DataSource{
|
||||
ds := &fakes.FakeCacheService{DataSources: []*datasources.DataSource{
|
||||
{Uid: data1.DatasourceUID},
|
||||
}}
|
||||
|
||||
@ -183,7 +183,7 @@ func TestRouteEvalQueries(t *testing.T) {
|
||||
{Action: datasources.ActionQuery, Scope: datasources.ScopeProvider.GetResourceScopeUID(data2.DatasourceUID)},
|
||||
})
|
||||
|
||||
ds := &fakes.FakeCacheService{DataSources: []*models2.DataSource{
|
||||
ds := &fakes.FakeCacheService{DataSources: []*datasources.DataSource{
|
||||
{Uid: data1.DatasourceUID},
|
||||
{Uid: data2.DatasourceUID},
|
||||
}}
|
||||
@ -227,7 +227,7 @@ func TestRouteEvalQueries(t *testing.T) {
|
||||
t.Run("should require user to be signed in", func(t *testing.T) {
|
||||
data1 := models.GenerateAlertQuery()
|
||||
|
||||
ds := &fakes.FakeCacheService{DataSources: []*models2.DataSource{
|
||||
ds := &fakes.FakeCacheService{DataSources: []*datasources.DataSource{
|
||||
{Uid: data1.DatasourceUID},
|
||||
}}
|
||||
|
||||
|
@ -8,12 +8,14 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"github.com/grafana/grafana/pkg/api/response"
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
apimodels "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions"
|
||||
"github.com/grafana/grafana/pkg/web"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
var endpoints = map[string]map[string]string{
|
||||
@ -74,10 +76,10 @@ func (am *LotexAM) withAMReq(
|
||||
|
||||
ds, err := am.DataProxy.DataSourceCache.GetDatasourceByUID(ctx.Req.Context(), datasourceUID, ctx.SignedInUser, ctx.SkipCache)
|
||||
if err != nil {
|
||||
if errors.Is(err, models.ErrDataSourceAccessDenied) {
|
||||
if errors.Is(err, datasources.ErrDataSourceAccessDenied) {
|
||||
return ErrResp(http.StatusForbidden, err, "Access denied to datasource")
|
||||
}
|
||||
if errors.Is(err, models.ErrDataSourceNotFound) {
|
||||
if errors.Is(err, datasources.ErrDataSourceNotFound) {
|
||||
return ErrResp(http.StatusNotFound, err, "Unable to find datasource")
|
||||
}
|
||||
return ErrResp(http.StatusInternalServerError, err, "Unable to load datasource meta data")
|
||||
|
@ -32,58 +32,58 @@ func TestLotexRuler_ValidateAndGetPrefix(t *testing.T) {
|
||||
{
|
||||
name: "with an error while trying to fetch the datasource",
|
||||
namedParams: map[string]string{":DatasourceUID": "d164"},
|
||||
datasourceCache: fakeCacheService{err: models.ErrDataSourceNotFound},
|
||||
datasourceCache: fakeCacheService{err: datasources.ErrDataSourceNotFound},
|
||||
err: errors.New("data source not found"),
|
||||
},
|
||||
{
|
||||
name: "with an empty datasource URL",
|
||||
namedParams: map[string]string{":DatasourceUID": "d164"},
|
||||
datasourceCache: fakeCacheService{datasource: &models.DataSource{}},
|
||||
datasourceCache: fakeCacheService{datasource: &datasources.DataSource{}},
|
||||
err: errors.New("URL for this data source is empty"),
|
||||
},
|
||||
{
|
||||
name: "with an unsupported datasource type",
|
||||
namedParams: map[string]string{":DatasourceUID": "d164"},
|
||||
datasourceCache: fakeCacheService{datasource: &models.DataSource{Url: "http://loki.com"}},
|
||||
datasourceCache: fakeCacheService{datasource: &datasources.DataSource{Url: "http://loki.com"}},
|
||||
err: errors.New("unexpected datasource type. expecting loki or prometheus"),
|
||||
},
|
||||
{
|
||||
name: "with a Loki datasource",
|
||||
namedParams: map[string]string{":DatasourceUID": "d164"},
|
||||
datasourceCache: fakeCacheService{datasource: &models.DataSource{Url: "http://loki.com", Type: LokiDatasourceType}},
|
||||
datasourceCache: fakeCacheService{datasource: &datasources.DataSource{Url: "http://loki.com", Type: LokiDatasourceType}},
|
||||
expected: "/api/prom/rules",
|
||||
},
|
||||
{
|
||||
name: "with a Prometheus datasource",
|
||||
namedParams: map[string]string{":DatasourceUID": "d164"},
|
||||
datasourceCache: fakeCacheService{datasource: &models.DataSource{Url: "http://loki.com", Type: PrometheusDatasourceType}},
|
||||
datasourceCache: fakeCacheService{datasource: &datasources.DataSource{Url: "http://loki.com", Type: PrometheusDatasourceType}},
|
||||
expected: "/rules",
|
||||
},
|
||||
{
|
||||
name: "with a Prometheus datasource and subtype of Cortex",
|
||||
namedParams: map[string]string{":DatasourceUID": "d164"},
|
||||
urlParams: "?subtype=cortex",
|
||||
datasourceCache: fakeCacheService{datasource: &models.DataSource{Url: "http://loki.com", Type: PrometheusDatasourceType}},
|
||||
datasourceCache: fakeCacheService{datasource: &datasources.DataSource{Url: "http://loki.com", Type: PrometheusDatasourceType}},
|
||||
expected: "/rules",
|
||||
},
|
||||
{
|
||||
name: "with a Prometheus datasource and subtype of Mimir",
|
||||
namedParams: map[string]string{":DatasourceUID": "d164"},
|
||||
urlParams: "?subtype=mimir",
|
||||
datasourceCache: fakeCacheService{datasource: &models.DataSource{Url: "http://loki.com", Type: PrometheusDatasourceType}},
|
||||
datasourceCache: fakeCacheService{datasource: &datasources.DataSource{Url: "http://loki.com", Type: PrometheusDatasourceType}},
|
||||
expected: "/config/v1/rules",
|
||||
},
|
||||
{
|
||||
name: "with a Prometheus datasource and subtype of Prometheus",
|
||||
namedParams: map[string]string{":DatasourceUID": "d164"},
|
||||
urlParams: "?subtype=prometheus",
|
||||
datasourceCache: fakeCacheService{datasource: &models.DataSource{Url: "http://loki.com", Type: PrometheusDatasourceType}},
|
||||
datasourceCache: fakeCacheService{datasource: &datasources.DataSource{Url: "http://loki.com", Type: PrometheusDatasourceType}},
|
||||
expected: "/rules",
|
||||
},
|
||||
{
|
||||
name: "with a Prometheus datasource and no subtype",
|
||||
namedParams: map[string]string{":DatasourceUID": "d164"},
|
||||
datasourceCache: fakeCacheService{datasource: &models.DataSource{Url: "http://loki.com", Type: PrometheusDatasourceType}},
|
||||
datasourceCache: fakeCacheService{datasource: &datasources.DataSource{Url: "http://loki.com", Type: PrometheusDatasourceType}},
|
||||
expected: "/rules",
|
||||
},
|
||||
}
|
||||
@ -109,11 +109,11 @@ func TestLotexRuler_ValidateAndGetPrefix(t *testing.T) {
|
||||
}
|
||||
|
||||
type fakeCacheService struct {
|
||||
datasource *models.DataSource
|
||||
datasource *datasources.DataSource
|
||||
err error
|
||||
}
|
||||
|
||||
func (f fakeCacheService) GetDatasource(_ context.Context, datasourceID int64, _ *models.SignedInUser, _ bool) (*models.DataSource, error) {
|
||||
func (f fakeCacheService) GetDatasource(_ context.Context, datasourceID int64, _ *models.SignedInUser, _ bool) (*datasources.DataSource, error) {
|
||||
if f.err != nil {
|
||||
return nil, f.err
|
||||
}
|
||||
@ -121,7 +121,7 @@ func (f fakeCacheService) GetDatasource(_ context.Context, datasourceID int64, _
|
||||
return f.datasource, nil
|
||||
}
|
||||
|
||||
func (f fakeCacheService) GetDatasourceByUID(ctx context.Context, datasourceUID string, user *models.SignedInUser, skipCache bool) (*models.DataSource, error) {
|
||||
func (f fakeCacheService) GetDatasourceByUID(ctx context.Context, datasourceUID string, user *models.SignedInUser, skipCache bool) (*datasources.DataSource, error) {
|
||||
if f.err != nil {
|
||||
return nil, f.err
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ func GetExprRequest(ctx AlertExecCtx, data []models.AlertQuery, now time.Time, d
|
||||
},
|
||||
}
|
||||
|
||||
datasources := make(map[string]*m.DataSource, len(data))
|
||||
datasources := make(map[string]*datasources.DataSource, len(data))
|
||||
|
||||
for i := range data {
|
||||
q := data[i]
|
||||
|
@ -4,11 +4,13 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/login/social"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/login"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -22,7 +24,7 @@ type Service struct {
|
||||
|
||||
type OAuthTokenService interface {
|
||||
GetCurrentOAuthToken(context.Context, *models.SignedInUser) *oauth2.Token
|
||||
IsOAuthPassThruEnabled(*models.DataSource) bool
|
||||
IsOAuthPassThruEnabled(*datasources.DataSource) bool
|
||||
}
|
||||
|
||||
func ProvideService(socialService social.Service, authInfoService login.AuthInfoService) *Service {
|
||||
@ -100,7 +102,7 @@ func (o *Service) GetCurrentOAuthToken(ctx context.Context, user *models.SignedI
|
||||
}
|
||||
|
||||
// IsOAuthPassThruEnabled returns true if Forward OAuth Identity (oauthPassThru) is enabled for the provided data source.
|
||||
func (o *Service) IsOAuthPassThruEnabled(ds *models.DataSource) bool {
|
||||
func (o *Service) IsOAuthPassThruEnabled(ds *datasources.DataSource) bool {
|
||||
return ds.JsonData != nil && ds.JsonData.Get("oauthPassThru").MustBool()
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
"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/provisioning/utils"
|
||||
)
|
||||
|
||||
@ -135,12 +135,12 @@ func (cr *configReader) validateAccessAndOrgID(ctx context.Context, ds *upsertDa
|
||||
}
|
||||
|
||||
if ds.Access == "" {
|
||||
ds.Access = models.DS_ACCESS_PROXY
|
||||
ds.Access = datasources.DS_ACCESS_PROXY
|
||||
}
|
||||
|
||||
if ds.Access != models.DS_ACCESS_DIRECT && ds.Access != models.DS_ACCESS_PROXY {
|
||||
if ds.Access != datasources.DS_ACCESS_DIRECT && ds.Access != datasources.DS_ACCESS_PROXY {
|
||||
cr.log.Warn("invalid access value, will use 'proxy' instead", "value", ds.Access)
|
||||
ds.Access = models.DS_ACCESS_PROXY
|
||||
ds.Access = datasources.DS_ACCESS_PROXY
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -5,11 +5,12 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"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/util"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -39,14 +40,14 @@ func TestDatasourceAsConfig(t *testing.T) {
|
||||
|
||||
require.Equal(t, len(store.inserted), 1)
|
||||
require.Equal(t, store.inserted[0].OrgId, int64(1))
|
||||
require.Equal(t, store.inserted[0].Access, models.DsAccess("proxy"))
|
||||
require.Equal(t, store.inserted[0].Access, datasources.DsAccess("proxy"))
|
||||
require.Equal(t, store.inserted[0].Name, "My datasource name")
|
||||
require.Equal(t, store.inserted[0].Uid, "P2AD1F727255C56BA")
|
||||
})
|
||||
|
||||
t.Run("when some values missing should not change UID when updates", func(t *testing.T) {
|
||||
store := &spyStore{
|
||||
items: []*models.DataSource{{Name: "My datasource name", OrgId: 1, Id: 1, Uid: util.GenerateShortUID()}},
|
||||
items: []*datasources.DataSource{{Name: "My datasource name", OrgId: 1, Id: 1, Uid: util.GenerateShortUID()}},
|
||||
}
|
||||
orgStore := &mockOrgStore{}
|
||||
dc := newDatasourceProvisioner(logger, store, orgStore)
|
||||
@ -76,7 +77,7 @@ func TestDatasourceAsConfig(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("One datasource in database with same name should update one datasource", func(t *testing.T) {
|
||||
store := &spyStore{items: []*models.DataSource{{Name: "Graphite", OrgId: 1, Id: 1}}}
|
||||
store := &spyStore{items: []*datasources.DataSource{{Name: "Graphite", OrgId: 1, Id: 1}}}
|
||||
orgStore := &mockOrgStore{}
|
||||
dc := newDatasourceProvisioner(logger, store, orgStore)
|
||||
err := dc.applyChanges(context.Background(), twoDatasourcesConfig)
|
||||
@ -127,7 +128,7 @@ func TestDatasourceAsConfig(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("Two configured datasource and purge others", func(t *testing.T) {
|
||||
store := &spyStore{items: []*models.DataSource{{Name: "old-graphite", OrgId: 1, Id: 1}, {Name: "old-graphite2", OrgId: 1, Id: 2}}}
|
||||
store := &spyStore{items: []*datasources.DataSource{{Name: "old-graphite", OrgId: 1, Id: 1}, {Name: "old-graphite2", OrgId: 1, Id: 2}}}
|
||||
orgStore := &mockOrgStore{}
|
||||
dc := newDatasourceProvisioner(logger, store, orgStore)
|
||||
err := dc.applyChanges(context.Background(), twoDatasourcesConfigPurgeOthers)
|
||||
@ -141,7 +142,7 @@ func TestDatasourceAsConfig(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("Two configured datasource and purge others = false", func(t *testing.T) {
|
||||
store := &spyStore{items: []*models.DataSource{{Name: "Graphite", OrgId: 1, Id: 1}, {Name: "old-graphite2", OrgId: 1, Id: 2}}}
|
||||
store := &spyStore{items: []*datasources.DataSource{{Name: "Graphite", OrgId: 1, Id: 1}, {Name: "old-graphite2", OrgId: 1, Id: 2}}}
|
||||
orgStore := &mockOrgStore{}
|
||||
dc := newDatasourceProvisioner(logger, store, orgStore)
|
||||
err := dc.applyChanges(context.Background(), twoDatasourcesConfig)
|
||||
@ -164,7 +165,7 @@ func TestDatasourceAsConfig(t *testing.T) {
|
||||
reader := &configReader{log: logger, orgStore: &mockOrgStore{}}
|
||||
configs, err := reader.readConfig(context.Background(), invalidAccess)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, configs[0].Datasources[0].Access, models.DS_ACCESS_PROXY)
|
||||
require.Equal(t, configs[0].Datasources[0].Access, datasources.DS_ACCESS_PROXY)
|
||||
})
|
||||
|
||||
t.Run("skip invalid directory", func(t *testing.T) {
|
||||
@ -236,7 +237,7 @@ func validateDatasource(t *testing.T, dsCfg *configs) {
|
||||
ds := dsCfg.Datasources[0]
|
||||
require.Equal(t, ds.Name, "name")
|
||||
require.Equal(t, ds.Type, "type")
|
||||
require.Equal(t, ds.Access, models.DS_ACCESS_PROXY)
|
||||
require.Equal(t, ds.Access, datasources.DS_ACCESS_PROXY)
|
||||
require.Equal(t, ds.OrgID, int64(2))
|
||||
require.Equal(t, ds.URL, "url")
|
||||
require.Equal(t, ds.User, "user")
|
||||
@ -273,33 +274,33 @@ func (m *mockOrgStore) GetOrgById(c context.Context, cmd *models.GetOrgByIdQuery
|
||||
}
|
||||
|
||||
type spyStore struct {
|
||||
inserted []*models.AddDataSourceCommand
|
||||
deleted []*models.DeleteDataSourceCommand
|
||||
updated []*models.UpdateDataSourceCommand
|
||||
items []*models.DataSource
|
||||
inserted []*datasources.AddDataSourceCommand
|
||||
deleted []*datasources.DeleteDataSourceCommand
|
||||
updated []*datasources.UpdateDataSourceCommand
|
||||
items []*datasources.DataSource
|
||||
}
|
||||
|
||||
func (s *spyStore) GetDataSource(ctx context.Context, query *models.GetDataSourceQuery) error {
|
||||
func (s *spyStore) GetDataSource(ctx context.Context, query *datasources.GetDataSourceQuery) error {
|
||||
for _, v := range s.items {
|
||||
if query.Name == v.Name && query.OrgId == v.OrgId {
|
||||
query.Result = v
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return models.ErrDataSourceNotFound
|
||||
return datasources.ErrDataSourceNotFound
|
||||
}
|
||||
|
||||
func (s *spyStore) DeleteDataSource(ctx context.Context, cmd *models.DeleteDataSourceCommand) error {
|
||||
func (s *spyStore) DeleteDataSource(ctx context.Context, cmd *datasources.DeleteDataSourceCommand) error {
|
||||
s.deleted = append(s.deleted, cmd)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *spyStore) AddDataSource(ctx context.Context, cmd *models.AddDataSourceCommand) error {
|
||||
func (s *spyStore) AddDataSource(ctx context.Context, cmd *datasources.AddDataSourceCommand) error {
|
||||
s.inserted = append(s.inserted, cmd)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *spyStore) UpdateDataSource(ctx context.Context, cmd *models.UpdateDataSourceCommand) error {
|
||||
func (s *spyStore) UpdateDataSource(ctx context.Context, cmd *datasources.UpdateDataSourceCommand) error {
|
||||
s.updated = append(s.updated, cmd)
|
||||
return nil
|
||||
}
|
||||
|
@ -5,16 +5,15 @@ import (
|
||||
"errors"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/provisioning/utils"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
)
|
||||
|
||||
type Store interface {
|
||||
GetDataSource(ctx context.Context, query *models.GetDataSourceQuery) error
|
||||
AddDataSource(ctx context.Context, cmd *models.AddDataSourceCommand) error
|
||||
UpdateDataSource(ctx context.Context, cmd *models.UpdateDataSourceCommand) error
|
||||
DeleteDataSource(ctx context.Context, cmd *models.DeleteDataSourceCommand) error
|
||||
GetDataSource(ctx context.Context, query *datasources.GetDataSourceQuery) error
|
||||
AddDataSource(ctx context.Context, cmd *datasources.AddDataSourceCommand) error
|
||||
UpdateDataSource(ctx context.Context, cmd *datasources.UpdateDataSourceCommand) error
|
||||
DeleteDataSource(ctx context.Context, cmd *datasources.DeleteDataSourceCommand) error
|
||||
}
|
||||
|
||||
var (
|
||||
@ -52,13 +51,13 @@ func (dc *DatasourceProvisioner) apply(ctx context.Context, cfg *configs) error
|
||||
}
|
||||
|
||||
for _, ds := range cfg.Datasources {
|
||||
cmd := &models.GetDataSourceQuery{OrgId: ds.OrgID, Name: ds.Name}
|
||||
cmd := &datasources.GetDataSourceQuery{OrgId: ds.OrgID, Name: ds.Name}
|
||||
err := dc.store.GetDataSource(ctx, cmd)
|
||||
if err != nil && !errors.Is(err, models.ErrDataSourceNotFound) {
|
||||
if err != nil && !errors.Is(err, datasources.ErrDataSourceNotFound) {
|
||||
return err
|
||||
}
|
||||
|
||||
if errors.Is(err, models.ErrDataSourceNotFound) {
|
||||
if errors.Is(err, datasources.ErrDataSourceNotFound) {
|
||||
insertCmd := createInsertCommand(ds)
|
||||
dc.log.Info("inserting datasource from configuration ", "name", insertCmd.Name, "uid", insertCmd.Uid)
|
||||
if err := dc.store.AddDataSource(ctx, insertCmd); err != nil {
|
||||
@ -93,7 +92,7 @@ func (dc *DatasourceProvisioner) applyChanges(ctx context.Context, configPath st
|
||||
|
||||
func (dc *DatasourceProvisioner) deleteDatasources(ctx context.Context, dsToDelete []*deleteDatasourceConfig) error {
|
||||
for _, ds := range dsToDelete {
|
||||
cmd := &models.DeleteDataSourceCommand{OrgID: ds.OrgID, Name: ds.Name}
|
||||
cmd := &datasources.DeleteDataSourceCommand{OrgID: ds.OrgID, Name: ds.Name}
|
||||
if err := dc.store.DeleteDataSource(ctx, cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
|
||||
"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/provisioning/values"
|
||||
)
|
||||
|
||||
@ -189,7 +189,7 @@ func (cfg *configsV0) mapToDatasourceFromConfig(apiVersion int64) *configs {
|
||||
return r
|
||||
}
|
||||
|
||||
func createInsertCommand(ds *upsertDataSourceFromConfig) *models.AddDataSourceCommand {
|
||||
func createInsertCommand(ds *upsertDataSourceFromConfig) *datasources.AddDataSourceCommand {
|
||||
jsonData := simplejson.New()
|
||||
if len(ds.JSONData) > 0 {
|
||||
for k, v := range ds.JSONData {
|
||||
@ -197,11 +197,11 @@ func createInsertCommand(ds *upsertDataSourceFromConfig) *models.AddDataSourceCo
|
||||
}
|
||||
}
|
||||
|
||||
cmd := &models.AddDataSourceCommand{
|
||||
cmd := &datasources.AddDataSourceCommand{
|
||||
OrgId: ds.OrgID,
|
||||
Name: ds.Name,
|
||||
Type: ds.Type,
|
||||
Access: models.DsAccess(ds.Access),
|
||||
Access: datasources.DsAccess(ds.Access),
|
||||
Url: ds.URL,
|
||||
User: ds.User,
|
||||
Database: ds.Database,
|
||||
@ -228,7 +228,7 @@ func safeUIDFromName(name string) string {
|
||||
return strings.ToUpper(fmt.Sprintf("P%x", bs[:8]))
|
||||
}
|
||||
|
||||
func createUpdateCommand(ds *upsertDataSourceFromConfig, id int64) *models.UpdateDataSourceCommand {
|
||||
func createUpdateCommand(ds *upsertDataSourceFromConfig, id int64) *datasources.UpdateDataSourceCommand {
|
||||
jsonData := simplejson.New()
|
||||
if len(ds.JSONData) > 0 {
|
||||
for k, v := range ds.JSONData {
|
||||
@ -236,13 +236,13 @@ func createUpdateCommand(ds *upsertDataSourceFromConfig, id int64) *models.Updat
|
||||
}
|
||||
}
|
||||
|
||||
return &models.UpdateDataSourceCommand{
|
||||
return &datasources.UpdateDataSourceCommand{
|
||||
Id: id,
|
||||
Uid: ds.UID,
|
||||
OrgId: ds.OrgID,
|
||||
Name: ds.Name,
|
||||
Type: ds.Type,
|
||||
Access: models.DsAccess(ds.Access),
|
||||
Access: datasources.DsAccess(ds.Access),
|
||||
Url: ds.URL,
|
||||
User: ds.User,
|
||||
Database: ds.Database,
|
||||
|
@ -146,7 +146,7 @@ func (s *Service) handleExpressions(ctx context.Context, user *models.SignedInUs
|
||||
func (s *Service) handleQueryData(ctx context.Context, user *models.SignedInUser, parsedReq *parsedRequest) (*backend.QueryDataResponse, error) {
|
||||
ds := parsedReq.parsedQueries[0].datasource
|
||||
if err := s.pluginRequestValidator.Validate(ds.Url, nil); err != nil {
|
||||
return nil, models.ErrDataSourceAccessDenied
|
||||
return nil, datasources.ErrDataSourceAccessDenied
|
||||
}
|
||||
|
||||
instanceSettings, err := adapters.ModelToInstanceSettings(ds, s.decryptSecureJsonDataFn(ctx))
|
||||
@ -205,7 +205,7 @@ func (s *Service) handleQueryData(ctx context.Context, user *models.SignedInUser
|
||||
}
|
||||
|
||||
type parsedQuery struct {
|
||||
datasource *models.DataSource
|
||||
datasource *datasources.DataSource
|
||||
query backend.DataQuery
|
||||
}
|
||||
|
||||
@ -247,7 +247,7 @@ func (s *Service) parseMetricRequest(ctx context.Context, user *models.SignedInU
|
||||
}
|
||||
|
||||
// Parse the queries
|
||||
datasourcesByUid := map[string]*models.DataSource{}
|
||||
datasourcesByUid := map[string]*datasources.DataSource{}
|
||||
for _, query := range reqDTO.Queries {
|
||||
ds, err := s.getDataSourceFromQuery(ctx, user, skipCache, query, datasourcesByUid)
|
||||
if err != nil {
|
||||
@ -299,7 +299,7 @@ func (s *Service) parseMetricRequest(ctx context.Context, user *models.SignedInU
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func (s *Service) getDataSourceFromQuery(ctx context.Context, user *models.SignedInUser, skipCache bool, query *simplejson.Json, history map[string]*models.DataSource) (*models.DataSource, error) {
|
||||
func (s *Service) getDataSourceFromQuery(ctx context.Context, user *models.SignedInUser, skipCache bool, query *simplejson.Json, history map[string]*datasources.DataSource) (*datasources.DataSource, error) {
|
||||
var err error
|
||||
uid := query.Get("datasource").Get("uid").MustString()
|
||||
|
||||
@ -343,8 +343,8 @@ func (s *Service) getDataSourceFromQuery(ctx context.Context, user *models.Signe
|
||||
return nil, NewErrBadQuery("missing data source ID/UID")
|
||||
}
|
||||
|
||||
func (s *Service) decryptSecureJsonDataFn(ctx context.Context) func(ds *models.DataSource) map[string]string {
|
||||
return func(ds *models.DataSource) map[string]string {
|
||||
func (s *Service) decryptSecureJsonDataFn(ctx context.Context) func(ds *datasources.DataSource) map[string]string {
|
||||
return func(ds *datasources.DataSource) map[string]string {
|
||||
decryptedJsonData, err := s.dataSourceService.DecryptedValues(ctx, ds)
|
||||
if err != nil {
|
||||
s.log.Error("Failed to decrypt secure json data", "error", err)
|
||||
|
@ -6,22 +6,22 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
acmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
|
||||
datasources "github.com/grafana/grafana/pkg/services/datasources/service"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
dsSvc "github.com/grafana/grafana/pkg/services/datasources/service"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/query"
|
||||
"github.com/grafana/grafana/pkg/services/secrets/fakes"
|
||||
"github.com/grafana/grafana/pkg/services/secrets/kvstore"
|
||||
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestQueryData(t *testing.T) {
|
||||
@ -102,13 +102,13 @@ func TestQueryData(t *testing.T) {
|
||||
|
||||
func setup(t *testing.T) *testContext {
|
||||
pc := &fakePluginClient{}
|
||||
dc := &fakeDataSourceCache{ds: &models.DataSource{}}
|
||||
dc := &fakeDataSourceCache{ds: &datasources.DataSource{}}
|
||||
tc := &fakeOAuthTokenService{}
|
||||
rv := &fakePluginRequestValidator{}
|
||||
|
||||
ss := kvstore.SetupTestService(t)
|
||||
ssvc := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
|
||||
ds := datasources.ProvideService(nil, ssvc, ss, nil, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService())
|
||||
ds := dsSvc.ProvideService(nil, ssvc, ss, nil, featuremgmt.WithFeatures(), acmock.New(), acmock.NewMockedPermissionsService())
|
||||
|
||||
return &testContext{
|
||||
pluginContext: pc,
|
||||
@ -156,19 +156,19 @@ func (ts *fakeOAuthTokenService) GetCurrentOAuthToken(context.Context, *models.S
|
||||
return ts.token
|
||||
}
|
||||
|
||||
func (ts *fakeOAuthTokenService) IsOAuthPassThruEnabled(*models.DataSource) bool {
|
||||
func (ts *fakeOAuthTokenService) IsOAuthPassThruEnabled(*datasources.DataSource) bool {
|
||||
return ts.passThruEnabled
|
||||
}
|
||||
|
||||
type fakeDataSourceCache struct {
|
||||
ds *models.DataSource
|
||||
ds *datasources.DataSource
|
||||
}
|
||||
|
||||
func (c *fakeDataSourceCache) GetDatasource(ctx context.Context, datasourceID int64, user *models.SignedInUser, skipCache bool) (*models.DataSource, error) {
|
||||
func (c *fakeDataSourceCache) GetDatasource(ctx context.Context, datasourceID int64, user *models.SignedInUser, skipCache bool) (*datasources.DataSource, error) {
|
||||
return c.ds, nil
|
||||
}
|
||||
|
||||
func (c *fakeDataSourceCache) GetDatasourceByUID(ctx context.Context, datasourceUID string, user *models.SignedInUser, skipCache bool) (*models.DataSource, error) {
|
||||
func (c *fakeDataSourceCache) GetDatasourceByUID(ctx context.Context, datasourceUID string, user *models.SignedInUser, skipCache bool) (*datasources.DataSource, error) {
|
||||
return c.ds, nil
|
||||
}
|
||||
|
||||
|
@ -4,8 +4,8 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
smp "github.com/grafana/grafana/pkg/plugins/backendplugin/secretsmanagerplugin"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/secrets"
|
||||
)
|
||||
|
||||
@ -124,6 +124,6 @@ func parseKeys(keys []*smp.Key) []Key {
|
||||
return newKeys
|
||||
}
|
||||
|
||||
func wrapUserFriendlySecretError(ufe string) models.ErrDatasourceSecretsPluginUserFriendly {
|
||||
return models.ErrDatasourceSecretsPluginUserFriendly{Err: ufe}
|
||||
func wrapUserFriendlySecretError(ufe string) datasources.ErrDatasourceSecretsPluginUserFriendly {
|
||||
return datasources.ErrDatasourceSecretsPluginUserFriendly{Err: ufe}
|
||||
}
|
||||
|
@ -12,14 +12,14 @@ import (
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/events"
|
||||
"github.com/grafana/grafana/pkg/infra/metrics"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
// GetDataSource adds a datasource to the query model by querying by org_id as well as
|
||||
// either uid (preferred), id, or name and is added to the bus.
|
||||
func (ss *SQLStore) GetDataSource(ctx context.Context, query *models.GetDataSourceQuery) error {
|
||||
func (ss *SQLStore) GetDataSource(ctx context.Context, query *datasources.GetDataSourceQuery) error {
|
||||
metrics.MDBDataSourceQueryByID.Inc()
|
||||
|
||||
return ss.WithDbSession(ctx, func(sess *DBSession) error {
|
||||
@ -27,19 +27,19 @@ func (ss *SQLStore) GetDataSource(ctx context.Context, query *models.GetDataSour
|
||||
})
|
||||
}
|
||||
|
||||
func (ss *SQLStore) getDataSource(ctx context.Context, query *models.GetDataSourceQuery, sess *DBSession) error {
|
||||
func (ss *SQLStore) getDataSource(ctx context.Context, query *datasources.GetDataSourceQuery, sess *DBSession) error {
|
||||
if query.OrgId == 0 || (query.Id == 0 && len(query.Name) == 0 && len(query.Uid) == 0) {
|
||||
return models.ErrDataSourceIdentifierNotSet
|
||||
return datasources.ErrDataSourceIdentifierNotSet
|
||||
}
|
||||
|
||||
datasource := &models.DataSource{Name: query.Name, OrgId: query.OrgId, Id: query.Id, Uid: query.Uid}
|
||||
datasource := &datasources.DataSource{Name: query.Name, OrgId: query.OrgId, Id: query.Id, Uid: query.Uid}
|
||||
has, err := sess.Get(datasource)
|
||||
|
||||
if err != nil {
|
||||
sqlog.Error("Failed getting data source", "err", err, "uid", query.Uid, "id", query.Id, "name", query.Name, "orgId", query.OrgId)
|
||||
return err
|
||||
} else if !has {
|
||||
return models.ErrDataSourceNotFound
|
||||
return datasources.ErrDataSourceNotFound
|
||||
}
|
||||
|
||||
query.Result = datasource
|
||||
@ -47,7 +47,7 @@ func (ss *SQLStore) getDataSource(ctx context.Context, query *models.GetDataSour
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ss *SQLStore) GetDataSources(ctx context.Context, query *models.GetDataSourcesQuery) error {
|
||||
func (ss *SQLStore) GetDataSources(ctx context.Context, query *datasources.GetDataSourcesQuery) error {
|
||||
var sess *xorm.Session
|
||||
return ss.WithDbSession(ctx, func(dbSess *DBSession) error {
|
||||
if query.DataSourceLimit <= 0 {
|
||||
@ -56,31 +56,31 @@ func (ss *SQLStore) GetDataSources(ctx context.Context, query *models.GetDataSou
|
||||
sess = dbSess.Limit(query.DataSourceLimit, 0).Where("org_id=?", query.OrgId).Asc("name")
|
||||
}
|
||||
|
||||
query.Result = make([]*models.DataSource, 0)
|
||||
query.Result = make([]*datasources.DataSource, 0)
|
||||
return sess.Find(&query.Result)
|
||||
})
|
||||
}
|
||||
|
||||
// GetDataSourcesByType returns all datasources for a given type or an error if the specified type is an empty string
|
||||
func (ss *SQLStore) GetDataSourcesByType(ctx context.Context, query *models.GetDataSourcesByTypeQuery) error {
|
||||
func (ss *SQLStore) GetDataSourcesByType(ctx context.Context, query *datasources.GetDataSourcesByTypeQuery) error {
|
||||
if query.Type == "" {
|
||||
return fmt.Errorf("datasource type cannot be empty")
|
||||
}
|
||||
|
||||
query.Result = make([]*models.DataSource, 0)
|
||||
query.Result = make([]*datasources.DataSource, 0)
|
||||
return ss.WithDbSession(ctx, func(sess *DBSession) error {
|
||||
return sess.Where("type=?", query.Type).Asc("id").Find(&query.Result)
|
||||
})
|
||||
}
|
||||
|
||||
// GetDefaultDataSource is used to get the default datasource of organization
|
||||
func (ss *SQLStore) GetDefaultDataSource(ctx context.Context, query *models.GetDefaultDataSourceQuery) error {
|
||||
datasource := models.DataSource{}
|
||||
func (ss *SQLStore) GetDefaultDataSource(ctx context.Context, query *datasources.GetDefaultDataSourceQuery) error {
|
||||
datasource := datasources.DataSource{}
|
||||
return ss.WithDbSession(ctx, func(sess *DBSession) error {
|
||||
exists, err := sess.Where("org_id=? AND is_default=?", query.OrgId, true).Get(&datasource)
|
||||
|
||||
if !exists {
|
||||
return models.ErrDataSourceNotFound
|
||||
return datasources.ErrDataSourceNotFound
|
||||
}
|
||||
|
||||
query.Result = &datasource
|
||||
@ -90,12 +90,12 @@ func (ss *SQLStore) GetDefaultDataSource(ctx context.Context, query *models.GetD
|
||||
|
||||
// DeleteDataSource removes a datasource by org_id as well as either uid (preferred), id, or name
|
||||
// and is added to the bus. It also removes permissions related to the datasource.
|
||||
func (ss *SQLStore) DeleteDataSource(ctx context.Context, cmd *models.DeleteDataSourceCommand) error {
|
||||
func (ss *SQLStore) DeleteDataSource(ctx context.Context, cmd *datasources.DeleteDataSourceCommand) error {
|
||||
return ss.WithTransactionalDbSession(ctx, func(sess *DBSession) error {
|
||||
dsQuery := &models.GetDataSourceQuery{Id: cmd.ID, Uid: cmd.UID, Name: cmd.Name, OrgId: cmd.OrgID}
|
||||
dsQuery := &datasources.GetDataSourceQuery{Id: cmd.ID, Uid: cmd.UID, Name: cmd.Name, OrgId: cmd.OrgID}
|
||||
errGettingDS := ss.getDataSource(ctx, dsQuery, sess)
|
||||
|
||||
if errGettingDS != nil && !errors.Is(errGettingDS, models.ErrDataSourceNotFound) {
|
||||
if errGettingDS != nil && !errors.Is(errGettingDS, datasources.ErrDataSourceNotFound) {
|
||||
return errGettingDS
|
||||
}
|
||||
|
||||
@ -136,13 +136,13 @@ func (ss *SQLStore) DeleteDataSource(ctx context.Context, cmd *models.DeleteData
|
||||
})
|
||||
}
|
||||
|
||||
func (ss *SQLStore) AddDataSource(ctx context.Context, cmd *models.AddDataSourceCommand) error {
|
||||
func (ss *SQLStore) AddDataSource(ctx context.Context, cmd *datasources.AddDataSourceCommand) error {
|
||||
return ss.WithTransactionalDbSession(ctx, func(sess *DBSession) error {
|
||||
existing := models.DataSource{OrgId: cmd.OrgId, Name: cmd.Name}
|
||||
existing := datasources.DataSource{OrgId: cmd.OrgId, Name: cmd.Name}
|
||||
has, _ := sess.Get(&existing)
|
||||
|
||||
if has {
|
||||
return models.ErrDataSourceNameExists
|
||||
return datasources.ErrDataSourceNameExists
|
||||
}
|
||||
|
||||
if cmd.JsonData == nil {
|
||||
@ -157,7 +157,7 @@ func (ss *SQLStore) AddDataSource(ctx context.Context, cmd *models.AddDataSource
|
||||
cmd.Uid = uid
|
||||
}
|
||||
|
||||
ds := &models.DataSource{
|
||||
ds := &datasources.DataSource{
|
||||
OrgId: cmd.OrgId,
|
||||
Name: cmd.Name,
|
||||
Type: cmd.Type,
|
||||
@ -180,7 +180,7 @@ func (ss *SQLStore) AddDataSource(ctx context.Context, cmd *models.AddDataSource
|
||||
|
||||
if _, err := sess.Insert(ds); err != nil {
|
||||
if dialect.IsUniqueConstraintViolation(err) && strings.Contains(strings.ToLower(dialect.ErrorMessage(err)), "uid") {
|
||||
return models.ErrDataSourceUidExists
|
||||
return datasources.ErrDataSourceUidExists
|
||||
}
|
||||
return err
|
||||
}
|
||||
@ -208,7 +208,7 @@ func (ss *SQLStore) AddDataSource(ctx context.Context, cmd *models.AddDataSource
|
||||
})
|
||||
}
|
||||
|
||||
func updateIsDefaultFlag(ds *models.DataSource, sess *DBSession) error {
|
||||
func updateIsDefaultFlag(ds *datasources.DataSource, sess *DBSession) error {
|
||||
// Handle is default flag
|
||||
if ds.IsDefault {
|
||||
rawSQL := "UPDATE data_source SET is_default=? WHERE org_id=? AND id <> ?"
|
||||
@ -219,13 +219,13 @@ func updateIsDefaultFlag(ds *models.DataSource, sess *DBSession) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ss *SQLStore) UpdateDataSource(ctx context.Context, cmd *models.UpdateDataSourceCommand) error {
|
||||
func (ss *SQLStore) UpdateDataSource(ctx context.Context, cmd *datasources.UpdateDataSourceCommand) error {
|
||||
return ss.WithTransactionalDbSession(ctx, func(sess *DBSession) error {
|
||||
if cmd.JsonData == nil {
|
||||
cmd.JsonData = simplejson.New()
|
||||
}
|
||||
|
||||
ds := &models.DataSource{
|
||||
ds := &datasources.DataSource{
|
||||
Id: cmd.Id,
|
||||
OrgId: cmd.OrgId,
|
||||
Name: cmd.Name,
|
||||
@ -272,7 +272,7 @@ func (ss *SQLStore) UpdateDataSource(ctx context.Context, cmd *models.UpdateData
|
||||
}
|
||||
|
||||
if affected == 0 {
|
||||
return models.ErrDataSourceUpdatingOldVersion
|
||||
return datasources.ErrDataSourceUpdatingOldVersion
|
||||
}
|
||||
|
||||
err = updateIsDefaultFlag(ds, sess)
|
||||
@ -293,7 +293,7 @@ func generateNewDatasourceUid(sess *DBSession, orgId int64) (string, error) {
|
||||
for i := 0; i < 3; i++ {
|
||||
uid := generateNewUid()
|
||||
|
||||
exists, err := sess.Where("org_id=? AND uid=?", orgId, uid).Get(&models.DataSource{})
|
||||
exists, err := sess.Where("org_id=? AND uid=?", orgId, uid).Get(&datasources.DataSource{})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@ -303,7 +303,7 @@ func generateNewDatasourceUid(sess *DBSession, orgId int64) (string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
return "", models.ErrDataSourceFailedGenerateUniqueUid
|
||||
return "", datasources.ErrDataSourceFailedGenerateUniqueUid
|
||||
}
|
||||
|
||||
var generateNewUid func() string = util.GenerateShortUID
|
||||
|
@ -8,39 +8,40 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/events"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/events"
|
||||
ac "github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
)
|
||||
|
||||
func TestIntegrationDataAccess(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping integration test")
|
||||
}
|
||||
defaultAddDatasourceCommand := models.AddDataSourceCommand{
|
||||
defaultAddDatasourceCommand := datasources.AddDataSourceCommand{
|
||||
OrgId: 10,
|
||||
Name: "nisse",
|
||||
Type: models.DS_GRAPHITE,
|
||||
Access: models.DS_ACCESS_DIRECT,
|
||||
Type: datasources.DS_GRAPHITE,
|
||||
Access: datasources.DS_ACCESS_DIRECT,
|
||||
Url: "http://test",
|
||||
}
|
||||
|
||||
defaultUpdateDatasourceCommand := models.UpdateDataSourceCommand{
|
||||
defaultUpdateDatasourceCommand := datasources.UpdateDataSourceCommand{
|
||||
OrgId: 10,
|
||||
Name: "nisse_updated",
|
||||
Type: models.DS_GRAPHITE,
|
||||
Access: models.DS_ACCESS_DIRECT,
|
||||
Type: datasources.DS_GRAPHITE,
|
||||
Access: datasources.DS_ACCESS_DIRECT,
|
||||
Url: "http://test",
|
||||
}
|
||||
|
||||
initDatasource := func(sqlStore *SQLStore) *models.DataSource {
|
||||
initDatasource := func(sqlStore *SQLStore) *datasources.DataSource {
|
||||
cmd := defaultAddDatasourceCommand
|
||||
err := sqlStore.AddDataSource(context.Background(), &cmd)
|
||||
require.NoError(t, err)
|
||||
|
||||
query := models.GetDataSourcesQuery{OrgId: 10}
|
||||
query := datasources.GetDataSourcesQuery{OrgId: 10}
|
||||
err = sqlStore.GetDataSources(context.Background(), &query)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(query.Result))
|
||||
@ -52,18 +53,18 @@ func TestIntegrationDataAccess(t *testing.T) {
|
||||
t.Run("Can add datasource", func(t *testing.T) {
|
||||
sqlStore := InitTestDB(t)
|
||||
|
||||
err := sqlStore.AddDataSource(context.Background(), &models.AddDataSourceCommand{
|
||||
err := sqlStore.AddDataSource(context.Background(), &datasources.AddDataSourceCommand{
|
||||
OrgId: 10,
|
||||
Name: "laban",
|
||||
Type: models.DS_GRAPHITE,
|
||||
Access: models.DS_ACCESS_DIRECT,
|
||||
Type: datasources.DS_GRAPHITE,
|
||||
Access: datasources.DS_ACCESS_DIRECT,
|
||||
Url: "http://test",
|
||||
Database: "site",
|
||||
ReadOnly: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
query := models.GetDataSourcesQuery{OrgId: 10}
|
||||
query := datasources.GetDataSourcesQuery{OrgId: 10}
|
||||
err = sqlStore.GetDataSources(context.Background(), &query)
|
||||
require.NoError(t, err)
|
||||
|
||||
@ -91,7 +92,7 @@ func TestIntegrationDataAccess(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
err = sqlStore.AddDataSource(context.Background(), &cmd2)
|
||||
require.Error(t, err)
|
||||
require.IsType(t, models.ErrDataSourceUidExists, err)
|
||||
require.IsType(t, datasources.ErrDataSourceUidExists, err)
|
||||
})
|
||||
|
||||
t.Run("fires an event when the datasource is added", func(t *testing.T) {
|
||||
@ -110,7 +111,7 @@ func TestIntegrationDataAccess(t *testing.T) {
|
||||
return assert.NotNil(t, created)
|
||||
}, time.Second, time.Millisecond)
|
||||
|
||||
query := models.GetDataSourcesQuery{OrgId: 10}
|
||||
query := datasources.GetDataSourcesQuery{OrgId: 10}
|
||||
err = sqlStore.GetDataSources(context.Background(), &query)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(query.Result))
|
||||
@ -143,7 +144,7 @@ func TestIntegrationDataAccess(t *testing.T) {
|
||||
err := sqlStore.UpdateDataSource(context.Background(), &cmd)
|
||||
require.NoError(t, err)
|
||||
|
||||
query := models.GetDataSourceQuery{Id: ds.Id, OrgId: 10}
|
||||
query := datasources.GetDataSourceQuery{Id: ds.Id, OrgId: 10}
|
||||
err = sqlStore.GetDataSource(context.Background(), &query)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, ds.Uid, query.Result.Uid)
|
||||
@ -153,12 +154,12 @@ func TestIntegrationDataAccess(t *testing.T) {
|
||||
sqlStore := InitTestDB(t)
|
||||
ds := initDatasource(sqlStore)
|
||||
|
||||
cmd := models.UpdateDataSourceCommand{
|
||||
cmd := datasources.UpdateDataSourceCommand{
|
||||
Id: ds.Id,
|
||||
OrgId: 10,
|
||||
Name: "nisse",
|
||||
Type: models.DS_GRAPHITE,
|
||||
Access: models.DS_ACCESS_PROXY,
|
||||
Type: datasources.DS_GRAPHITE,
|
||||
Access: datasources.DS_ACCESS_PROXY,
|
||||
Url: "http://test",
|
||||
Version: ds.Version,
|
||||
}
|
||||
@ -176,12 +177,12 @@ func TestIntegrationDataAccess(t *testing.T) {
|
||||
sqlStore := InitTestDB(t)
|
||||
ds := initDatasource(sqlStore)
|
||||
|
||||
cmd := &models.UpdateDataSourceCommand{
|
||||
cmd := &datasources.UpdateDataSourceCommand{
|
||||
Id: ds.Id,
|
||||
OrgId: 10,
|
||||
Name: "nisse",
|
||||
Type: models.DS_GRAPHITE,
|
||||
Access: models.DS_ACCESS_PROXY,
|
||||
Type: datasources.DS_GRAPHITE,
|
||||
Access: datasources.DS_ACCESS_PROXY,
|
||||
Url: "http://test",
|
||||
}
|
||||
|
||||
@ -193,12 +194,12 @@ func TestIntegrationDataAccess(t *testing.T) {
|
||||
sqlStore := InitTestDB(t)
|
||||
ds := initDatasource(sqlStore)
|
||||
|
||||
cmd := &models.UpdateDataSourceCommand{
|
||||
cmd := &datasources.UpdateDataSourceCommand{
|
||||
Id: ds.Id,
|
||||
OrgId: 10,
|
||||
Name: "nisse",
|
||||
Type: models.DS_GRAPHITE,
|
||||
Access: models.DS_ACCESS_PROXY,
|
||||
Type: datasources.DS_GRAPHITE,
|
||||
Access: datasources.DS_ACCESS_PROXY,
|
||||
Url: "http://test",
|
||||
Version: 90000,
|
||||
}
|
||||
@ -213,10 +214,10 @@ func TestIntegrationDataAccess(t *testing.T) {
|
||||
sqlStore := InitTestDB(t)
|
||||
ds := initDatasource(sqlStore)
|
||||
|
||||
err := sqlStore.DeleteDataSource(context.Background(), &models.DeleteDataSourceCommand{ID: ds.Id, OrgID: ds.OrgId})
|
||||
err := sqlStore.DeleteDataSource(context.Background(), &datasources.DeleteDataSourceCommand{ID: ds.Id, OrgID: ds.OrgId})
|
||||
require.NoError(t, err)
|
||||
|
||||
query := models.GetDataSourcesQuery{OrgId: 10}
|
||||
query := datasources.GetDataSourcesQuery{OrgId: 10}
|
||||
err = sqlStore.GetDataSources(context.Background(), &query)
|
||||
require.NoError(t, err)
|
||||
|
||||
@ -228,10 +229,10 @@ func TestIntegrationDataAccess(t *testing.T) {
|
||||
ds := initDatasource(sqlStore)
|
||||
|
||||
err := sqlStore.DeleteDataSource(context.Background(),
|
||||
&models.DeleteDataSourceCommand{ID: ds.Id, OrgID: 123123})
|
||||
&datasources.DeleteDataSourceCommand{ID: ds.Id, OrgID: 123123})
|
||||
require.NoError(t, err)
|
||||
|
||||
query := models.GetDataSourcesQuery{OrgId: 10}
|
||||
query := datasources.GetDataSourcesQuery{OrgId: 10}
|
||||
err = sqlStore.GetDataSources(context.Background(), &query)
|
||||
require.NoError(t, err)
|
||||
|
||||
@ -250,7 +251,7 @@ func TestIntegrationDataAccess(t *testing.T) {
|
||||
})
|
||||
|
||||
err := sqlStore.DeleteDataSource(context.Background(),
|
||||
&models.DeleteDataSourceCommand{ID: ds.Id, UID: "nisse-uid", Name: "nisse", OrgID: int64(123123)})
|
||||
&datasources.DeleteDataSourceCommand{ID: ds.Id, UID: "nisse-uid", Name: "nisse", OrgID: int64(123123)})
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Eventually(t, func() bool {
|
||||
@ -266,9 +267,9 @@ func TestIntegrationDataAccess(t *testing.T) {
|
||||
t.Run("DeleteDataSourceByName", func(t *testing.T) {
|
||||
sqlStore := InitTestDB(t)
|
||||
ds := initDatasource(sqlStore)
|
||||
query := models.GetDataSourcesQuery{OrgId: 10}
|
||||
query := datasources.GetDataSourcesQuery{OrgId: 10}
|
||||
|
||||
err := sqlStore.DeleteDataSource(context.Background(), &models.DeleteDataSourceCommand{Name: ds.Name, OrgID: ds.OrgId})
|
||||
err := sqlStore.DeleteDataSource(context.Background(), &datasources.DeleteDataSourceCommand{Name: ds.Name, OrgID: ds.OrgId})
|
||||
require.NoError(t, err)
|
||||
|
||||
err = sqlStore.GetDataSources(context.Background(), &query)
|
||||
@ -293,10 +294,10 @@ func TestIntegrationDataAccess(t *testing.T) {
|
||||
return err
|
||||
})
|
||||
require.NoError(t, errAddPermissions)
|
||||
query := models.GetDataSourcesQuery{OrgId: 10}
|
||||
query := datasources.GetDataSourcesQuery{OrgId: 10}
|
||||
|
||||
errDeletingDS := sqlStore.DeleteDataSource(context.Background(),
|
||||
&models.DeleteDataSourceCommand{Name: ds.Name, OrgID: ds.OrgId},
|
||||
&datasources.DeleteDataSourceCommand{Name: ds.Name, OrgID: ds.OrgId},
|
||||
)
|
||||
require.NoError(t, errDeletingDS)
|
||||
|
||||
@ -318,18 +319,18 @@ func TestIntegrationDataAccess(t *testing.T) {
|
||||
sqlStore := InitTestDB(t)
|
||||
datasourceLimit := 6
|
||||
for i := 0; i < datasourceLimit+1; i++ {
|
||||
err := sqlStore.AddDataSource(context.Background(), &models.AddDataSourceCommand{
|
||||
err := sqlStore.AddDataSource(context.Background(), &datasources.AddDataSourceCommand{
|
||||
OrgId: 10,
|
||||
Name: "laban" + strconv.Itoa(i),
|
||||
Type: models.DS_GRAPHITE,
|
||||
Access: models.DS_ACCESS_DIRECT,
|
||||
Type: datasources.DS_GRAPHITE,
|
||||
Access: datasources.DS_ACCESS_DIRECT,
|
||||
Url: "http://test",
|
||||
Database: "site",
|
||||
ReadOnly: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
query := models.GetDataSourcesQuery{OrgId: 10, DataSourceLimit: datasourceLimit}
|
||||
query := datasources.GetDataSourcesQuery{OrgId: 10, DataSourceLimit: datasourceLimit}
|
||||
|
||||
err := sqlStore.GetDataSources(context.Background(), &query)
|
||||
|
||||
@ -341,18 +342,18 @@ func TestIntegrationDataAccess(t *testing.T) {
|
||||
sqlStore := InitTestDB(t)
|
||||
numberOfDatasource := 5100
|
||||
for i := 0; i < numberOfDatasource; i++ {
|
||||
err := sqlStore.AddDataSource(context.Background(), &models.AddDataSourceCommand{
|
||||
err := sqlStore.AddDataSource(context.Background(), &datasources.AddDataSourceCommand{
|
||||
OrgId: 10,
|
||||
Name: "laban" + strconv.Itoa(i),
|
||||
Type: models.DS_GRAPHITE,
|
||||
Access: models.DS_ACCESS_DIRECT,
|
||||
Type: datasources.DS_GRAPHITE,
|
||||
Access: datasources.DS_ACCESS_DIRECT,
|
||||
Url: "http://test",
|
||||
Database: "site",
|
||||
ReadOnly: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
query := models.GetDataSourcesQuery{OrgId: 10}
|
||||
query := datasources.GetDataSourcesQuery{OrgId: 10}
|
||||
|
||||
err := sqlStore.GetDataSources(context.Background(), &query)
|
||||
|
||||
@ -364,18 +365,18 @@ func TestIntegrationDataAccess(t *testing.T) {
|
||||
sqlStore := InitTestDB(t)
|
||||
numberOfDatasource := 5100
|
||||
for i := 0; i < numberOfDatasource; i++ {
|
||||
err := sqlStore.AddDataSource(context.Background(), &models.AddDataSourceCommand{
|
||||
err := sqlStore.AddDataSource(context.Background(), &datasources.AddDataSourceCommand{
|
||||
OrgId: 10,
|
||||
Name: "laban" + strconv.Itoa(i),
|
||||
Type: models.DS_GRAPHITE,
|
||||
Access: models.DS_ACCESS_DIRECT,
|
||||
Type: datasources.DS_GRAPHITE,
|
||||
Access: datasources.DS_ACCESS_DIRECT,
|
||||
Url: "http://test",
|
||||
Database: "site",
|
||||
ReadOnly: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
query := models.GetDataSourcesQuery{OrgId: 10, DataSourceLimit: -1}
|
||||
query := datasources.GetDataSourcesQuery{OrgId: 10, DataSourceLimit: -1}
|
||||
|
||||
err := sqlStore.GetDataSources(context.Background(), &query)
|
||||
|
||||
@ -388,29 +389,29 @@ func TestIntegrationDataAccess(t *testing.T) {
|
||||
t.Run("Only returns datasources of specified type", func(t *testing.T) {
|
||||
sqlStore := InitTestDB(t)
|
||||
|
||||
err := sqlStore.AddDataSource(context.Background(), &models.AddDataSourceCommand{
|
||||
err := sqlStore.AddDataSource(context.Background(), &datasources.AddDataSourceCommand{
|
||||
OrgId: 10,
|
||||
Name: "Elasticsearch",
|
||||
Type: models.DS_ES,
|
||||
Access: models.DS_ACCESS_DIRECT,
|
||||
Type: datasources.DS_ES,
|
||||
Access: datasources.DS_ACCESS_DIRECT,
|
||||
Url: "http://test",
|
||||
Database: "site",
|
||||
ReadOnly: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
err = sqlStore.AddDataSource(context.Background(), &models.AddDataSourceCommand{
|
||||
err = sqlStore.AddDataSource(context.Background(), &datasources.AddDataSourceCommand{
|
||||
OrgId: 10,
|
||||
Name: "Graphite",
|
||||
Type: models.DS_GRAPHITE,
|
||||
Access: models.DS_ACCESS_DIRECT,
|
||||
Type: datasources.DS_GRAPHITE,
|
||||
Access: datasources.DS_ACCESS_DIRECT,
|
||||
Url: "http://test",
|
||||
Database: "site",
|
||||
ReadOnly: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
query := models.GetDataSourcesByTypeQuery{Type: models.DS_ES}
|
||||
query := datasources.GetDataSourcesByTypeQuery{Type: datasources.DS_ES}
|
||||
|
||||
err = sqlStore.GetDataSourcesByType(context.Background(), &query)
|
||||
|
||||
@ -421,7 +422,7 @@ func TestIntegrationDataAccess(t *testing.T) {
|
||||
t.Run("Returns an error if no type specified", func(t *testing.T) {
|
||||
sqlStore := InitTestDB(t)
|
||||
|
||||
query := models.GetDataSourcesByTypeQuery{}
|
||||
query := datasources.GetDataSourcesByTypeQuery{}
|
||||
|
||||
err := sqlStore.GetDataSourcesByType(context.Background(), &query)
|
||||
|
||||
@ -439,31 +440,31 @@ func TestIntegrationGetDefaultDataSource(t *testing.T) {
|
||||
t.Run("should return error if there is no default datasource", func(t *testing.T) {
|
||||
sqlStore := InitTestDB(t)
|
||||
|
||||
cmd := models.AddDataSourceCommand{
|
||||
cmd := datasources.AddDataSourceCommand{
|
||||
OrgId: 10,
|
||||
Name: "nisse",
|
||||
Type: models.DS_GRAPHITE,
|
||||
Access: models.DS_ACCESS_DIRECT,
|
||||
Type: datasources.DS_GRAPHITE,
|
||||
Access: datasources.DS_ACCESS_DIRECT,
|
||||
Url: "http://test",
|
||||
}
|
||||
|
||||
err := sqlStore.AddDataSource(context.Background(), &cmd)
|
||||
require.NoError(t, err)
|
||||
|
||||
query := models.GetDefaultDataSourceQuery{OrgId: 10}
|
||||
query := datasources.GetDefaultDataSourceQuery{OrgId: 10}
|
||||
err = sqlStore.GetDefaultDataSource(context.Background(), &query)
|
||||
require.Error(t, err)
|
||||
assert.True(t, errors.Is(err, models.ErrDataSourceNotFound))
|
||||
assert.True(t, errors.Is(err, datasources.ErrDataSourceNotFound))
|
||||
})
|
||||
|
||||
t.Run("should return default datasource if exists", func(t *testing.T) {
|
||||
sqlStore := InitTestDB(t)
|
||||
|
||||
cmd := models.AddDataSourceCommand{
|
||||
cmd := datasources.AddDataSourceCommand{
|
||||
OrgId: 10,
|
||||
Name: "default datasource",
|
||||
Type: models.DS_GRAPHITE,
|
||||
Access: models.DS_ACCESS_DIRECT,
|
||||
Type: datasources.DS_GRAPHITE,
|
||||
Access: datasources.DS_ACCESS_DIRECT,
|
||||
Url: "http://test",
|
||||
IsDefault: true,
|
||||
}
|
||||
@ -471,7 +472,7 @@ func TestIntegrationGetDefaultDataSource(t *testing.T) {
|
||||
err := sqlStore.AddDataSource(context.Background(), &cmd)
|
||||
require.NoError(t, err)
|
||||
|
||||
query := models.GetDefaultDataSourceQuery{OrgId: 10}
|
||||
query := datasources.GetDefaultDataSourceQuery{OrgId: 10}
|
||||
err = sqlStore.GetDefaultDataSource(context.Background(), &query)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "default datasource", query.Result.Name)
|
||||
@ -479,9 +480,9 @@ func TestIntegrationGetDefaultDataSource(t *testing.T) {
|
||||
|
||||
t.Run("should not return default datasource of other organisation", func(t *testing.T) {
|
||||
sqlStore := InitTestDB(t)
|
||||
query := models.GetDefaultDataSourceQuery{OrgId: 1}
|
||||
query := datasources.GetDefaultDataSourceQuery{OrgId: 1}
|
||||
err := sqlStore.GetDefaultDataSource(context.Background(), &query)
|
||||
require.Error(t, err)
|
||||
assert.True(t, errors.Is(err, models.ErrDataSourceNotFound))
|
||||
assert.True(t, errors.Is(err, datasources.ErrDataSourceNotFound))
|
||||
})
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
|
||||
"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/sqlstore/migrations"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/migrations/ualert"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
|
||||
@ -556,9 +557,9 @@ func createDashboard(t *testing.T, id int64, orgId int64, uid string) *models.Da
|
||||
}
|
||||
|
||||
// createDatasource creates a ddatasource for inserting into the test database.
|
||||
func createDatasource(t *testing.T, id int64, orgId int64, uid string) *models.DataSource {
|
||||
func createDatasource(t *testing.T, id int64, orgId int64, uid string) *datasources.DataSource {
|
||||
t.Helper()
|
||||
return &models.DataSource{
|
||||
return &datasources.DataSource{
|
||||
Id: id,
|
||||
OrgId: orgId,
|
||||
Uid: uid,
|
||||
@ -613,7 +614,7 @@ func setupLegacyAlertsTables(t *testing.T, x *xorm.Engine, legacyChannels []*mod
|
||||
require.NoError(t, errDashboards)
|
||||
|
||||
// Setup data_sources.
|
||||
dataSources := []models.DataSource{
|
||||
dataSources := []datasources.DataSource{
|
||||
*createDatasource(t, 1, 1, "ds1-1"),
|
||||
*createDatasource(t, 2, 1, "ds2-1"),
|
||||
*createDatasource(t, 3, 2, "ds3-2"),
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
|
||||
)
|
||||
@ -18,7 +19,7 @@ type SQLStoreMock struct {
|
||||
LatestUserId int64
|
||||
|
||||
ExpectedUser *models.User
|
||||
ExpectedDatasource *models.DataSource
|
||||
ExpectedDatasource *datasources.DataSource
|
||||
ExpectedAlert *models.Alert
|
||||
ExpectedPluginSetting *models.PluginSetting
|
||||
ExpectedDashboards []*models.Dashboard
|
||||
@ -28,11 +29,11 @@ type SQLStoreMock struct {
|
||||
ExpectedTeamsByUser []*models.TeamDTO
|
||||
ExpectedSearchOrgList []*models.OrgDTO
|
||||
ExpectedSearchUsers models.SearchUserQueryResult
|
||||
ExpectedDatasources []*models.DataSource
|
||||
ExpectedDatasources []*datasources.DataSource
|
||||
ExpectedOrg *models.Org
|
||||
ExpectedSystemStats *models.SystemStats
|
||||
ExpectedDataSourceStats []*models.DataSourceStats
|
||||
ExpectedDataSources []*models.DataSource
|
||||
ExpectedDataSources []*datasources.DataSource
|
||||
ExpectedDataSourcesAccessStats []*models.DataSourceAccessStats
|
||||
ExpectedNotifierUsageStats []*models.NotifierUsageStats
|
||||
ExpectedPersistedDashboards models.HitList
|
||||
@ -415,35 +416,35 @@ func (m *SQLStoreMock) GetDashboards(ctx context.Context, query *models.GetDashb
|
||||
return m.ExpectedError
|
||||
}
|
||||
|
||||
func (m SQLStoreMock) GetDataSource(ctx context.Context, query *models.GetDataSourceQuery) error {
|
||||
func (m SQLStoreMock) GetDataSource(ctx context.Context, query *datasources.GetDataSourceQuery) error {
|
||||
query.Result = m.ExpectedDatasource
|
||||
return m.ExpectedError
|
||||
}
|
||||
|
||||
func (m *SQLStoreMock) GetDataSources(ctx context.Context, query *models.GetDataSourcesQuery) error {
|
||||
func (m *SQLStoreMock) GetDataSources(ctx context.Context, query *datasources.GetDataSourcesQuery) error {
|
||||
query.Result = m.ExpectedDatasources
|
||||
return m.ExpectedError
|
||||
}
|
||||
|
||||
func (m *SQLStoreMock) GetDataSourcesByType(ctx context.Context, query *models.GetDataSourcesByTypeQuery) error {
|
||||
func (m *SQLStoreMock) GetDataSourcesByType(ctx context.Context, query *datasources.GetDataSourcesByTypeQuery) error {
|
||||
return m.ExpectedError
|
||||
}
|
||||
|
||||
func (m *SQLStoreMock) GetDefaultDataSource(ctx context.Context, query *models.GetDefaultDataSourceQuery) error {
|
||||
func (m *SQLStoreMock) GetDefaultDataSource(ctx context.Context, query *datasources.GetDefaultDataSourceQuery) error {
|
||||
query.Result = m.ExpectedDatasource
|
||||
return m.ExpectedError
|
||||
}
|
||||
|
||||
func (m *SQLStoreMock) DeleteDataSource(ctx context.Context, cmd *models.DeleteDataSourceCommand) error {
|
||||
func (m *SQLStoreMock) DeleteDataSource(ctx context.Context, cmd *datasources.DeleteDataSourceCommand) error {
|
||||
return m.ExpectedError
|
||||
}
|
||||
|
||||
func (m *SQLStoreMock) AddDataSource(ctx context.Context, cmd *models.AddDataSourceCommand) error {
|
||||
func (m *SQLStoreMock) AddDataSource(ctx context.Context, cmd *datasources.AddDataSourceCommand) error {
|
||||
cmd.Result = m.ExpectedDatasource
|
||||
return m.ExpectedError
|
||||
}
|
||||
|
||||
func (m *SQLStoreMock) UpdateDataSource(ctx context.Context, cmd *models.UpdateDataSourceCommand) error {
|
||||
func (m *SQLStoreMock) UpdateDataSource(ctx context.Context, cmd *datasources.UpdateDataSourceCommand) error {
|
||||
cmd.Result = m.ExpectedDatasource
|
||||
return m.ExpectedError
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore/migrator"
|
||||
)
|
||||
|
||||
@ -88,13 +89,13 @@ type Store interface {
|
||||
GetOrgUsers(ctx context.Context, query *models.GetOrgUsersQuery) error
|
||||
SearchOrgUsers(ctx context.Context, query *models.SearchOrgUsersQuery) error
|
||||
RemoveOrgUser(ctx context.Context, cmd *models.RemoveOrgUserCommand) error
|
||||
GetDataSource(ctx context.Context, query *models.GetDataSourceQuery) error
|
||||
GetDataSources(ctx context.Context, query *models.GetDataSourcesQuery) error
|
||||
GetDataSourcesByType(ctx context.Context, query *models.GetDataSourcesByTypeQuery) error
|
||||
GetDefaultDataSource(ctx context.Context, query *models.GetDefaultDataSourceQuery) error
|
||||
DeleteDataSource(ctx context.Context, cmd *models.DeleteDataSourceCommand) error
|
||||
AddDataSource(ctx context.Context, cmd *models.AddDataSourceCommand) error
|
||||
UpdateDataSource(ctx context.Context, cmd *models.UpdateDataSourceCommand) error
|
||||
GetDataSource(ctx context.Context, query *datasources.GetDataSourceQuery) error
|
||||
GetDataSources(ctx context.Context, query *datasources.GetDataSourcesQuery) error
|
||||
GetDataSourcesByType(ctx context.Context, query *datasources.GetDataSourcesByTypeQuery) error
|
||||
GetDefaultDataSource(ctx context.Context, query *datasources.GetDefaultDataSourceQuery) error
|
||||
DeleteDataSource(ctx context.Context, cmd *datasources.DeleteDataSourceCommand) error
|
||||
AddDataSource(ctx context.Context, cmd *datasources.AddDataSourceCommand) error
|
||||
UpdateDataSource(ctx context.Context, cmd *datasources.UpdateDataSourceCommand) error
|
||||
Migrate(bool) error
|
||||
Sync() error
|
||||
Reset() error
|
||||
|
@ -7,8 +7,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
|
||||
"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/tsdb/azuremonitor/azlog"
|
||||
"github.com/grafana/grafana/pkg/tsdb/azuremonitor/types"
|
||||
"github.com/grafana/grafana/pkg/tsdb/legacydata/interval"
|
||||
@ -114,7 +115,7 @@ func (m *kqlMacroEngine) evaluateMacro(name string, defaultTimeField string, arg
|
||||
azlog.Warn("Unable to parse model from query", "JSON", m.query.JSON)
|
||||
it = defaultInterval
|
||||
} else {
|
||||
it, err = interval.GetIntervalFrom(&models.DataSource{
|
||||
it, err = interval.GetIntervalFrom(&datasources.DataSource{
|
||||
JsonData: simplejson.NewFromAny(dsInfo.JSONData),
|
||||
}, model, defaultInterval)
|
||||
if err != nil {
|
||||
|
@ -9,8 +9,9 @@ import (
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
|
||||
"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/searchV2"
|
||||
"github.com/grafana/grafana/pkg/services/store"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
@ -56,8 +57,8 @@ type Service struct {
|
||||
store store.StorageService
|
||||
}
|
||||
|
||||
func DataSourceModel(orgId int64) *models.DataSource {
|
||||
return &models.DataSource{
|
||||
func DataSourceModel(orgId int64) *datasources.DataSource {
|
||||
return &datasources.DataSource{
|
||||
Id: DatasourceID,
|
||||
Uid: DatasourceUID,
|
||||
Name: DatasourceName,
|
||||
|
@ -5,8 +5,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
)
|
||||
|
||||
func TestIntervalCalculator_Calculate(t *testing.T) {
|
||||
@ -103,7 +104,7 @@ func TestFormatDuration(t *testing.T) {
|
||||
func TestGetIntervalFrom(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
dsInfo *models.DataSource
|
||||
dsInfo *datasources.DataSource
|
||||
queryInterval string
|
||||
queryIntervalMs int64
|
||||
defaultInterval time.Duration
|
||||
|
@ -7,26 +7,28 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/data"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/null"
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
)
|
||||
|
||||
// RequestHandler is a data request handler interface.
|
||||
// Deprecated: use backend.QueryDataHandler instead.
|
||||
type RequestHandler interface {
|
||||
// HandleRequest handles a data request.
|
||||
HandleRequest(context.Context, *models.DataSource, DataQuery) (DataResponse, error)
|
||||
HandleRequest(context.Context, *datasources.DataSource, DataQuery) (DataResponse, error)
|
||||
}
|
||||
|
||||
// DataSubQuery represents a data sub-query. New work should use the plugin SDK.
|
||||
type DataSubQuery struct {
|
||||
RefID string `json:"refId"`
|
||||
Model *simplejson.Json `json:"model,omitempty"`
|
||||
DataSource *models.DataSource `json:"datasource"`
|
||||
MaxDataPoints int64 `json:"maxDataPoints"`
|
||||
IntervalMS int64 `json:"intervalMs"`
|
||||
QueryType string `json:"queryType"`
|
||||
RefID string `json:"refId"`
|
||||
Model *simplejson.Json `json:"model,omitempty"`
|
||||
DataSource *datasources.DataSource `json:"datasource"`
|
||||
MaxDataPoints int64 `json:"maxDataPoints"`
|
||||
IntervalMS int64 `json:"intervalMs"`
|
||||
QueryType string `json:"queryType"`
|
||||
}
|
||||
|
||||
// DataQuery contains all information about a data query request. New work should use the plugin SDK.
|
||||
|
@ -7,8 +7,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend/gtime"
|
||||
|
||||
"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/tsdb/legacydata"
|
||||
)
|
||||
|
||||
@ -77,7 +78,7 @@ func (ic *intervalCalculator) CalculateSafeInterval(timerange legacydata.DataTim
|
||||
return Interval{Text: FormatDuration(rounded), Value: rounded}
|
||||
}
|
||||
|
||||
func GetIntervalFrom(dsInfo *models.DataSource, queryModel *simplejson.Json, defaultInterval time.Duration) (time.Duration, error) {
|
||||
func GetIntervalFrom(dsInfo *datasources.DataSource, queryModel *simplejson.Json, defaultInterval time.Duration) (time.Duration, error) {
|
||||
interval := queryModel.Get("interval").MustString("")
|
||||
|
||||
// intervalMs field appears in the v2 plugins API and should be preferred
|
||||
|
@ -4,11 +4,12 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/tsdb/legacydata"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/tsdb/legacydata"
|
||||
)
|
||||
|
||||
func TestIntervalCalculator_Calculate(t *testing.T) {
|
||||
@ -98,7 +99,7 @@ func TestGetIntervalFrom(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
testCases := []struct {
|
||||
name string
|
||||
dsInfo *models.DataSource
|
||||
dsInfo *datasources.DataSource
|
||||
queryModel string
|
||||
defaultInterval time.Duration
|
||||
expected time.Duration
|
||||
@ -108,7 +109,7 @@ func TestGetIntervalFrom(t *testing.T) {
|
||||
{"2m", nil, `{"interval": "2m"}`, time.Second * 15, time.Minute * 2},
|
||||
{"intervalMs", nil, `{"intervalMs": 45000}`, time.Second * 15, time.Second * 45},
|
||||
{"intervalMs sub-seconds", nil, `{"intervalMs": 45200}`, time.Second * 15, time.Millisecond * 45200},
|
||||
{"dsInfo timeInterval", &models.DataSource{
|
||||
{"dsInfo timeInterval", &datasources.DataSource{
|
||||
JsonData: dsJSON,
|
||||
}, `{}`, time.Second * 15, time.Second * 60},
|
||||
{"defaultInterval when interval empty", nil, `{"interval": ""}`, time.Second * 15, time.Second * 15},
|
||||
|
@ -7,8 +7,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
"github.com/grafana/grafana/pkg/plugins/adapters"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
@ -21,7 +21,7 @@ const (
|
||||
headerValue = "httpHeaderValue"
|
||||
)
|
||||
|
||||
var oAuthIsOAuthPassThruEnabledFunc = func(oAuthTokenService oauthtoken.OAuthTokenService, ds *models.DataSource) bool {
|
||||
var oAuthIsOAuthPassThruEnabledFunc = func(oAuthTokenService oauthtoken.OAuthTokenService, ds *datasources.DataSource) bool {
|
||||
return oAuthTokenService.IsOAuthPassThruEnabled(ds)
|
||||
}
|
||||
|
||||
@ -41,7 +41,7 @@ func ProvideService(pluginsClient plugins.Client, oAuthTokenService oauthtoken.O
|
||||
}
|
||||
|
||||
//nolint: staticcheck // legacydata.DataResponse deprecated
|
||||
func (h *Service) HandleRequest(ctx context.Context, ds *models.DataSource, query legacydata.DataQuery) (legacydata.DataResponse, error) {
|
||||
func (h *Service) HandleRequest(ctx context.Context, ds *datasources.DataSource, query legacydata.DataQuery) (legacydata.DataResponse, error) {
|
||||
decryptedJsonData, err := h.dataSourcesService.DecryptedValues(ctx, ds)
|
||||
if err != nil {
|
||||
return legacydata.DataResponse{}, err
|
||||
@ -91,7 +91,7 @@ func (h *Service) HandleRequest(ctx context.Context, ds *models.DataSource, quer
|
||||
return tR, nil
|
||||
}
|
||||
|
||||
func generateRequest(ctx context.Context, ds *models.DataSource, decryptedJsonData map[string]string, query legacydata.DataQuery) (*backend.QueryDataRequest, error) {
|
||||
func generateRequest(ctx context.Context, ds *datasources.DataSource, decryptedJsonData map[string]string, query legacydata.DataQuery) (*backend.QueryDataRequest, error) {
|
||||
jsonDataBytes, err := ds.JsonData.MarshalJSON()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -5,10 +5,12 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/plugins"
|
||||
acmock "github.com/grafana/grafana/pkg/services/accesscontrol/mock"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
datasourceservice "github.com/grafana/grafana/pkg/services/datasources/service"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/oauthtoken"
|
||||
@ -17,7 +19,6 @@ import (
|
||||
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/grafana/grafana/pkg/tsdb/legacydata"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestHandleRequest(t *testing.T) {
|
||||
@ -25,7 +26,7 @@ func TestHandleRequest(t *testing.T) {
|
||||
|
||||
t.Run("Should invoke plugin manager QueryData when handling request for query", func(t *testing.T) {
|
||||
origOAuthIsOAuthPassThruEnabledFunc := oAuthIsOAuthPassThruEnabledFunc
|
||||
oAuthIsOAuthPassThruEnabledFunc = func(oAuthTokenService oauthtoken.OAuthTokenService, ds *models.DataSource) bool {
|
||||
oAuthIsOAuthPassThruEnabledFunc = func(oAuthTokenService oauthtoken.OAuthTokenService, ds *datasources.DataSource) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
@ -45,12 +46,12 @@ func TestHandleRequest(t *testing.T) {
|
||||
dsService := datasourceservice.ProvideService(nil, secretsService, secretsStore, cfg, featuremgmt.WithFeatures(), acmock.New(), datasourcePermissions)
|
||||
s := ProvideService(client, nil, dsService)
|
||||
|
||||
ds := &models.DataSource{Id: 12, Type: "unregisteredType", JsonData: simplejson.New()}
|
||||
ds := &datasources.DataSource{Id: 12, Type: "unregisteredType", JsonData: simplejson.New()}
|
||||
req := legacydata.DataQuery{
|
||||
TimeRange: &legacydata.DataTimeRange{},
|
||||
Queries: []legacydata.DataSubQuery{
|
||||
{RefID: "A", DataSource: &models.DataSource{Id: 1, Type: "test"}, Model: simplejson.New()},
|
||||
{RefID: "B", DataSource: &models.DataSource{Id: 1, Type: "test"}, Model: simplejson.New()},
|
||||
{RefID: "A", DataSource: &datasources.DataSource{Id: 1, Type: "test"}, Model: simplejson.New()},
|
||||
{RefID: "B", DataSource: &datasources.DataSource{Id: 1, Type: "test"}, Model: simplejson.New()},
|
||||
},
|
||||
}
|
||||
res, err := s.HandleRequest(context.Background(), ds, req)
|
||||
@ -73,12 +74,12 @@ func Test_generateRequest(t *testing.T) {
|
||||
"something": "else",
|
||||
}
|
||||
|
||||
ds := &models.DataSource{Id: 12, Type: "unregisteredType", JsonData: jsonData}
|
||||
ds := &datasources.DataSource{Id: 12, Type: "unregisteredType", JsonData: jsonData}
|
||||
query := legacydata.DataQuery{
|
||||
TimeRange: &legacydata.DataTimeRange{},
|
||||
Queries: []legacydata.DataSubQuery{
|
||||
{RefID: "A", DataSource: &models.DataSource{Id: 1, Type: "test"}, Model: simplejson.New()},
|
||||
{RefID: "B", DataSource: &models.DataSource{Id: 1, Type: "test"}, Model: simplejson.New()},
|
||||
{RefID: "A", DataSource: &datasources.DataSource{Id: 1, Type: "test"}, Model: simplejson.New()},
|
||||
{RefID: "B", DataSource: &datasources.DataSource{Id: 1, Type: "test"}, Model: simplejson.New()},
|
||||
},
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user