mirror of
https://github.com/grafana/grafana.git
synced 2025-02-16 18:34:52 -06:00
Public Dashboards: Only use queries from dashboard for caching (#54596)
Don't accept frontend queries for query caching when its from a public dashboard. Use queries on the dashboard instead.
This commit is contained in:
parent
4223d3a6a7
commit
108678a8cc
@ -158,8 +158,8 @@ func (api *Api) QueryPublicDashboard(c *models.ReqContext) response.Response {
|
||||
return response.Error(http.StatusBadRequest, "invalid panel ID", err)
|
||||
}
|
||||
|
||||
reqDTO := &PublicDashboardQueryDTO{}
|
||||
if err = web.Bind(c.Req, reqDTO); err != nil {
|
||||
reqDTO := PublicDashboardQueryDTO{}
|
||||
if err = web.Bind(c.Req, &reqDTO); err != nil {
|
||||
return response.Error(http.StatusBadRequest, "bad request data", err)
|
||||
}
|
||||
|
||||
|
24
pkg/services/publicdashboards/internal/test_helpers.go
Normal file
24
pkg/services/publicdashboards/internal/test_helpers.go
Normal file
@ -0,0 +1,24 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// Gets time range from dashboard in unix milliseconds
|
||||
func GetTimeRangeFromDashboard(t *testing.T, dashboardData *simplejson.Json) (string, string) {
|
||||
to := dashboardData.GetPath("time", "to").MustString()
|
||||
from := dashboardData.GetPath("time", "from").MustString()
|
||||
toTime, err := time.Parse("2006-01-02T15:04:05.000Z", to)
|
||||
require.NoError(t, err)
|
||||
fromTime, err := time.Parse("2006-01-02T15:04:05.000Z", from)
|
||||
require.NoError(t, err)
|
||||
toUnixMilli := strconv.FormatInt(toTime.UnixMilli(), 10)
|
||||
fromUnixMilli := strconv.FormatInt(fromTime.UnixMilli(), 10)
|
||||
|
||||
return fromUnixMilli, toUnixMilli
|
||||
}
|
@ -1,10 +1,12 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/tsdb/legacydata"
|
||||
)
|
||||
|
||||
// PublicDashboardErr represents a dashboard error.
|
||||
@ -81,24 +83,21 @@ type TimeSettings struct {
|
||||
|
||||
// build time settings object from json on public dashboard. If empty, use
|
||||
// defaults on the dashboard
|
||||
func (pd PublicDashboard) BuildTimeSettings(dashboard *models.Dashboard) *TimeSettings {
|
||||
ts := &TimeSettings{
|
||||
From: dashboard.Data.GetPath("time", "from").MustString(),
|
||||
To: dashboard.Data.GetPath("time", "to").MustString(),
|
||||
func (pd PublicDashboard) BuildTimeSettings(dashboard *models.Dashboard) TimeSettings {
|
||||
from := dashboard.Data.GetPath("time", "from").MustString()
|
||||
to := dashboard.Data.GetPath("time", "to").MustString()
|
||||
timeRange := legacydata.NewDataTimeRange(from, to)
|
||||
|
||||
// Were using epoch ms because this is used to build a MetricRequest, which is used by query caching, which expected the time range in epoch milliseconds.
|
||||
ts := TimeSettings{
|
||||
From: strconv.FormatInt(timeRange.GetFromAsMsEpoch(), 10),
|
||||
To: strconv.FormatInt(timeRange.GetToAsMsEpoch(), 10),
|
||||
}
|
||||
|
||||
if pd.TimeSettings == nil {
|
||||
return ts
|
||||
}
|
||||
|
||||
// merge time settings from public dashboard
|
||||
to := pd.TimeSettings.Get("to").MustString("")
|
||||
from := pd.TimeSettings.Get("from").MustString("")
|
||||
if to != "" && from != "" {
|
||||
ts.From = from
|
||||
ts.To = to
|
||||
}
|
||||
|
||||
return ts
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/publicdashboards/internal"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
@ -13,38 +14,30 @@ func TestPublicDashboardTableName(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBuildTimeSettings(t *testing.T) {
|
||||
var dashboardData = simplejson.NewFromAny(map[string]interface{}{"time": map[string]interface{}{"from": "now-8", "to": "now"}})
|
||||
var dashboardData = simplejson.NewFromAny(map[string]interface{}{"time": map[string]interface{}{"from": "2022-09-01T00:00:00.000Z", "to": "2022-09-01T12:00:00.000Z"}})
|
||||
fromMs, toMs := internal.GetTimeRangeFromDashboard(t, dashboardData)
|
||||
testCases := []struct {
|
||||
name string
|
||||
dashboard *models.Dashboard
|
||||
pubdash *PublicDashboard
|
||||
timeResult *TimeSettings
|
||||
timeResult TimeSettings
|
||||
}{
|
||||
{
|
||||
name: "should use dashboard time if pubdash time empty",
|
||||
dashboard: &models.Dashboard{Data: dashboardData},
|
||||
pubdash: &PublicDashboard{},
|
||||
timeResult: &TimeSettings{
|
||||
From: "now-8",
|
||||
To: "now",
|
||||
timeResult: TimeSettings{
|
||||
From: fromMs,
|
||||
To: toMs,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "should use dashboard time if pubdash to/from empty",
|
||||
dashboard: &models.Dashboard{Data: dashboardData},
|
||||
pubdash: &PublicDashboard{},
|
||||
timeResult: &TimeSettings{
|
||||
From: "now-8",
|
||||
To: "now",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "should use pubdash time",
|
||||
name: "should use dashboard time even if pubdash time exists",
|
||||
dashboard: &models.Dashboard{Data: dashboardData},
|
||||
pubdash: &PublicDashboard{TimeSettings: simplejson.NewFromAny(map[string]interface{}{"from": "now-12", "to": "now"})},
|
||||
timeResult: &TimeSettings{
|
||||
From: "now-12",
|
||||
To: "now",
|
||||
timeResult: TimeSettings{
|
||||
From: fromMs,
|
||||
To: toMs,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -4,13 +4,19 @@ package publicdashboards
|
||||
|
||||
import (
|
||||
context "context"
|
||||
testing "testing"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
models "github.com/grafana/grafana/pkg/models"
|
||||
publicdashboardsmodels "github.com/grafana/grafana/pkg/services/publicdashboards/models"
|
||||
backend "github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
|
||||
dtos "github.com/grafana/grafana/pkg/api/dtos"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
models "github.com/grafana/grafana/pkg/models"
|
||||
|
||||
publicdashboardsmodels "github.com/grafana/grafana/pkg/services/publicdashboards/models"
|
||||
|
||||
testing "testing"
|
||||
|
||||
user "github.com/grafana/grafana/pkg/services/user"
|
||||
)
|
||||
|
||||
@ -63,27 +69,6 @@ func (_m *FakePublicDashboardService) BuildAnonymousUser(ctx context.Context, da
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetQueryDataResponse provides a mock function with given fields: ctx, skipCache, reqDTO, panelId, accessToken
|
||||
func (_m *FakePublicDashboardService) GetQueryDataResponse(ctx context.Context, skipCache bool, reqDTO *publicdashboardsmodels.PublicDashboardQueryDTO, panelId int64, accessToken string) (*backend.QueryDataResponse, error) {
|
||||
ret := _m.Called(ctx, skipCache, reqDTO, panelId, accessToken)
|
||||
|
||||
var r0 *backend.QueryDataResponse
|
||||
if rf, ok := ret.Get(0).(func(context.Context, bool, *publicdashboardsmodels.PublicDashboardQueryDTO, int64, string) *backend.QueryDataResponse); ok {
|
||||
r0 = rf(ctx, skipCache, reqDTO, panelId, accessToken)
|
||||
} else {
|
||||
r0 = ret.Get(0).(*backend.QueryDataResponse)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, bool, *publicdashboardsmodels.PublicDashboardQueryDTO, int64, string) error); ok {
|
||||
r1 = rf(ctx, skipCache, reqDTO, panelId, accessToken)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetDashboard provides a mock function with given fields: ctx, dashboardUid
|
||||
func (_m *FakePublicDashboardService) GetDashboard(ctx context.Context, dashboardUid string) (*models.Dashboard, error) {
|
||||
ret := _m.Called(ctx, dashboardUid)
|
||||
@ -107,6 +92,27 @@ func (_m *FakePublicDashboardService) GetDashboard(ctx context.Context, dashboar
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetMetricRequest provides a mock function with given fields: ctx, dashboard, publicDashboard, panelId, reqDTO
|
||||
func (_m *FakePublicDashboardService) GetMetricRequest(ctx context.Context, dashboard *models.Dashboard, publicDashboard *publicdashboardsmodels.PublicDashboard, panelId int64, reqDTO publicdashboardsmodels.PublicDashboardQueryDTO) (dtos.MetricRequest, error) {
|
||||
ret := _m.Called(ctx, dashboard, publicDashboard, panelId, reqDTO)
|
||||
|
||||
var r0 dtos.MetricRequest
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *models.Dashboard, *publicdashboardsmodels.PublicDashboard, int64, publicdashboardsmodels.PublicDashboardQueryDTO) dtos.MetricRequest); ok {
|
||||
r0 = rf(ctx, dashboard, publicDashboard, panelId, reqDTO)
|
||||
} else {
|
||||
r0 = ret.Get(0).(dtos.MetricRequest)
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, *models.Dashboard, *publicdashboardsmodels.PublicDashboard, int64, publicdashboardsmodels.PublicDashboardQueryDTO) error); ok {
|
||||
r1 = rf(ctx, dashboard, publicDashboard, panelId, reqDTO)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetPublicDashboard provides a mock function with given fields: ctx, accessToken
|
||||
func (_m *FakePublicDashboardService) GetPublicDashboard(ctx context.Context, accessToken string) (*publicdashboardsmodels.PublicDashboard, *models.Dashboard, error) {
|
||||
ret := _m.Called(ctx, accessToken)
|
||||
@ -162,6 +168,29 @@ func (_m *FakePublicDashboardService) GetPublicDashboardConfig(ctx context.Conte
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetQueryDataResponse provides a mock function with given fields: ctx, skipCache, reqDTO, panelId, accessToken
|
||||
func (_m *FakePublicDashboardService) GetQueryDataResponse(ctx context.Context, skipCache bool, reqDTO publicdashboardsmodels.PublicDashboardQueryDTO, panelId int64, accessToken string) (*backend.QueryDataResponse, error) {
|
||||
ret := _m.Called(ctx, skipCache, reqDTO, panelId, accessToken)
|
||||
|
||||
var r0 *backend.QueryDataResponse
|
||||
if rf, ok := ret.Get(0).(func(context.Context, bool, publicdashboardsmodels.PublicDashboardQueryDTO, int64, string) *backend.QueryDataResponse); ok {
|
||||
r0 = rf(ctx, skipCache, reqDTO, panelId, accessToken)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*backend.QueryDataResponse)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(context.Context, bool, publicdashboardsmodels.PublicDashboardQueryDTO, int64, string) error); ok {
|
||||
r1 = rf(ctx, skipCache, reqDTO, panelId, accessToken)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// PublicDashboardEnabled provides a mock function with given fields: ctx, dashboardUid
|
||||
func (_m *FakePublicDashboardService) PublicDashboardEnabled(ctx context.Context, dashboardUid string) (bool, error) {
|
||||
ret := _m.Called(ctx, dashboardUid)
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||
"github.com/grafana/grafana/pkg/api/dtos"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
. "github.com/grafana/grafana/pkg/services/publicdashboards/models"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
@ -13,25 +14,26 @@ import (
|
||||
|
||||
//go:generate mockery --name Service --structname FakePublicDashboardService --inpackage --filename public_dashboard_service_mock.go
|
||||
type Service interface {
|
||||
AccessTokenExists(ctx context.Context, accessToken string) (bool, error)
|
||||
BuildAnonymousUser(ctx context.Context, dashboard *models.Dashboard) (*user.SignedInUser, error)
|
||||
GetPublicDashboard(ctx context.Context, accessToken string) (*PublicDashboard, *models.Dashboard, error)
|
||||
GetDashboard(ctx context.Context, dashboardUid string) (*models.Dashboard, error)
|
||||
GetMetricRequest(ctx context.Context, dashboard *models.Dashboard, publicDashboard *PublicDashboard, panelId int64, reqDTO PublicDashboardQueryDTO) (dtos.MetricRequest, error)
|
||||
GetPublicDashboardConfig(ctx context.Context, orgId int64, dashboardUid string) (*PublicDashboard, error)
|
||||
SavePublicDashboardConfig(ctx context.Context, u *user.SignedInUser, dto *SavePublicDashboardConfigDTO) (*PublicDashboard, error)
|
||||
GetQueryDataResponse(ctx context.Context, skipCache bool, reqDTO *PublicDashboardQueryDTO, panelId int64, accessToken string) (*backend.QueryDataResponse, error)
|
||||
GetQueryDataResponse(ctx context.Context, skipCache bool, reqDTO PublicDashboardQueryDTO, panelId int64, accessToken string) (*backend.QueryDataResponse, error)
|
||||
PublicDashboardEnabled(ctx context.Context, dashboardUid string) (bool, error)
|
||||
AccessTokenExists(ctx context.Context, accessToken string) (bool, error)
|
||||
SavePublicDashboardConfig(ctx context.Context, u *user.SignedInUser, dto *SavePublicDashboardConfigDTO) (*PublicDashboard, error)
|
||||
}
|
||||
|
||||
//go:generate mockery --name Store --structname FakePublicDashboardStore --inpackage --filename public_dashboard_store_mock.go
|
||||
type Store interface {
|
||||
GetPublicDashboard(ctx context.Context, accessToken string) (*PublicDashboard, *models.Dashboard, error)
|
||||
AccessTokenExists(ctx context.Context, accessToken string) (bool, error)
|
||||
GetDashboard(ctx context.Context, dashboardUid string) (*models.Dashboard, error)
|
||||
GetPublicDashboardConfig(ctx context.Context, orgId int64, dashboardUid string) (*PublicDashboard, error)
|
||||
GetPublicDashboardByUid(ctx context.Context, uid string) (*PublicDashboard, error)
|
||||
GenerateNewPublicDashboardUid(ctx context.Context) (string, error)
|
||||
GetPublicDashboard(ctx context.Context, accessToken string) (*PublicDashboard, *models.Dashboard, error)
|
||||
GetPublicDashboardByUid(ctx context.Context, uid string) (*PublicDashboard, error)
|
||||
GetPublicDashboardConfig(ctx context.Context, orgId int64, dashboardUid string) (*PublicDashboard, error)
|
||||
PublicDashboardEnabled(ctx context.Context, dashboardUid string) (bool, error)
|
||||
SavePublicDashboardConfig(ctx context.Context, cmd SavePublicDashboardConfigCommand) error
|
||||
UpdatePublicDashboardConfig(ctx context.Context, cmd SavePublicDashboardConfigCommand) error
|
||||
PublicDashboardEnabled(ctx context.Context, dashboardUid string) (bool, error)
|
||||
AccessTokenExists(ctx context.Context, accessToken string) (bool, error)
|
||||
}
|
||||
|
@ -190,23 +190,13 @@ func (pd *PublicDashboardServiceImpl) updatePublicDashboardConfig(ctx context.Co
|
||||
return dto.PublicDashboard.Uid, pd.store.UpdatePublicDashboardConfig(ctx, cmd)
|
||||
}
|
||||
|
||||
func (pd *PublicDashboardServiceImpl) GetQueryDataResponse(ctx context.Context, skipCache bool, reqDTO *PublicDashboardQueryDTO, panelId int64, accessToken string) (*backend.QueryDataResponse, error) {
|
||||
if err := validation.ValidateQueryPublicDashboardRequest(reqDTO); err != nil {
|
||||
return nil, ErrPublicDashboardBadRequest
|
||||
}
|
||||
|
||||
func (pd *PublicDashboardServiceImpl) GetQueryDataResponse(ctx context.Context, skipCache bool, queryDto PublicDashboardQueryDTO, panelId int64, accessToken string) (*backend.QueryDataResponse, error) {
|
||||
publicDashboard, dashboard, err := pd.GetPublicDashboard(ctx, accessToken)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
metricReqDTO, err := pd.buildPublicDashboardMetricRequest(
|
||||
ctx,
|
||||
dashboard,
|
||||
publicDashboard,
|
||||
panelId,
|
||||
reqDTO,
|
||||
)
|
||||
metricReq, err := pd.GetMetricRequest(ctx, dashboard, publicDashboard, panelId, queryDto)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -216,12 +206,31 @@ func (pd *PublicDashboardServiceImpl) GetQueryDataResponse(ctx context.Context,
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return pd.QueryDataService.QueryDataMultipleSources(ctx, anonymousUser, skipCache, metricReqDTO, true)
|
||||
return pd.QueryDataService.QueryDataMultipleSources(ctx, anonymousUser, skipCache, metricReq, true)
|
||||
}
|
||||
|
||||
// BuildPublicDashboardMetricRequest merges public dashboard parameters with
|
||||
func (pd *PublicDashboardServiceImpl) GetMetricRequest(ctx context.Context, dashboard *models.Dashboard, publicDashboard *PublicDashboard, panelId int64, queryDto PublicDashboardQueryDTO) (dtos.MetricRequest, error) {
|
||||
if err := validation.ValidateQueryPublicDashboardRequest(queryDto); err != nil {
|
||||
return dtos.MetricRequest{}, ErrPublicDashboardBadRequest
|
||||
}
|
||||
|
||||
metricReqDTO, err := pd.buildMetricRequest(
|
||||
ctx,
|
||||
dashboard,
|
||||
publicDashboard,
|
||||
panelId,
|
||||
queryDto,
|
||||
)
|
||||
if err != nil {
|
||||
return dtos.MetricRequest{}, err
|
||||
}
|
||||
|
||||
return metricReqDTO, nil
|
||||
}
|
||||
|
||||
// buildMetricRequest merges public dashboard parameters with
|
||||
// dashboard and returns a metrics request to be sent to query backend
|
||||
func (pd *PublicDashboardServiceImpl) buildPublicDashboardMetricRequest(ctx context.Context, dashboard *models.Dashboard, publicDashboard *PublicDashboard, panelId int64, reqDTO *PublicDashboardQueryDTO) (dtos.MetricRequest, error) {
|
||||
func (pd *PublicDashboardServiceImpl) buildMetricRequest(ctx context.Context, dashboard *models.Dashboard, publicDashboard *PublicDashboard, panelId int64, reqDTO PublicDashboardQueryDTO) (dtos.MetricRequest, error) {
|
||||
// group queries by panel
|
||||
queriesByPanel := queryModels.GroupQueriesByPanelId(dashboard.Data)
|
||||
queries, ok := queriesByPanel[panelId]
|
||||
@ -290,7 +299,7 @@ func GenerateAccessToken() (string, error) {
|
||||
// this is an additional validation, all data sources implements QueryData interface and should have proper validations
|
||||
// of these limits
|
||||
// for the maxDataPoints we took a hard limit from prometheus which is 11000
|
||||
func (pd *PublicDashboardServiceImpl) getSafeIntervalAndMaxDataPoints(reqDTO *PublicDashboardQueryDTO, ts *TimeSettings) (int64, int64) {
|
||||
func (pd *PublicDashboardServiceImpl) getSafeIntervalAndMaxDataPoints(reqDTO PublicDashboardQueryDTO, ts TimeSettings) (int64, int64) {
|
||||
// arbitrary max value for all data sources, it is actually a hard limit defined in prometheus
|
||||
safeResolution := int64(11000)
|
||||
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/publicdashboards/internal"
|
||||
"github.com/grafana/grafana/pkg/services/user"
|
||||
|
||||
"github.com/google/uuid"
|
||||
@ -18,7 +19,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
dashboardsDB "github.com/grafana/grafana/pkg/services/dashboards/database"
|
||||
. "github.com/grafana/grafana/pkg/services/publicdashboards"
|
||||
database "github.com/grafana/grafana/pkg/services/publicdashboards/database"
|
||||
"github.com/grafana/grafana/pkg/services/publicdashboards/database"
|
||||
. "github.com/grafana/grafana/pkg/services/publicdashboards/models"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/tsdb/intervalv2"
|
||||
@ -352,13 +353,57 @@ func TestBuildAnonymousUser(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestBuildPublicDashboardMetricRequest(t *testing.T) {
|
||||
func TestGetMetricRequest(t *testing.T) {
|
||||
sqlStore := sqlstore.InitTestDB(t)
|
||||
dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures())
|
||||
publicdashboardStore := database.ProvideStore(sqlStore)
|
||||
dashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{})
|
||||
publicDashboard := &PublicDashboard{
|
||||
Uid: "1",
|
||||
DashboardUid: dashboard.Uid,
|
||||
IsEnabled: true,
|
||||
AccessToken: "abc123",
|
||||
}
|
||||
service := &PublicDashboardServiceImpl{
|
||||
log: log.New("test.logger"),
|
||||
store: publicdashboardStore,
|
||||
intervalCalculator: intervalv2.NewCalculator(),
|
||||
}
|
||||
|
||||
t.Run("will return an error when validation fails", func(t *testing.T) {
|
||||
publicDashboardQueryDTO := PublicDashboardQueryDTO{
|
||||
IntervalMs: int64(-1),
|
||||
MaxDataPoints: int64(-1),
|
||||
}
|
||||
|
||||
_, err := service.GetMetricRequest(context.Background(), dashboard, publicDashboard, 1, publicDashboardQueryDTO)
|
||||
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("will not return an error when validation succeeds", func(t *testing.T) {
|
||||
publicDashboardQueryDTO := PublicDashboardQueryDTO{
|
||||
IntervalMs: int64(1),
|
||||
MaxDataPoints: int64(1),
|
||||
}
|
||||
from, to := internal.GetTimeRangeFromDashboard(t, dashboard.Data)
|
||||
|
||||
metricReq, err := service.GetMetricRequest(context.Background(), dashboard, publicDashboard, 1, publicDashboardQueryDTO)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, from, metricReq.From)
|
||||
require.Equal(t, to, metricReq.To)
|
||||
})
|
||||
}
|
||||
|
||||
func TestBuildMetricRequest(t *testing.T) {
|
||||
sqlStore := sqlstore.InitTestDB(t)
|
||||
dashboardStore := dashboardsDB.ProvideDashboardStore(sqlStore, featuremgmt.WithFeatures())
|
||||
publicdashboardStore := database.ProvideStore(sqlStore)
|
||||
|
||||
publicDashboard := insertTestDashboard(t, dashboardStore, "testDashie", 1, 0, true, []map[string]interface{}{})
|
||||
nonPublicDashboard := insertTestDashboard(t, dashboardStore, "testNonPublicDashie", 1, 0, true, []map[string]interface{}{})
|
||||
from, to := internal.GetTimeRangeFromDashboard(t, publicDashboard.Data)
|
||||
|
||||
service := &PublicDashboardServiceImpl{
|
||||
log: log.New("test.logger"),
|
||||
@ -366,7 +411,7 @@ func TestBuildPublicDashboardMetricRequest(t *testing.T) {
|
||||
intervalCalculator: intervalv2.NewCalculator(),
|
||||
}
|
||||
|
||||
publicDashboardQueryDTO := &PublicDashboardQueryDTO{
|
||||
publicDashboardQueryDTO := PublicDashboardQueryDTO{
|
||||
IntervalMs: int64(10000000),
|
||||
MaxDataPoints: int64(200),
|
||||
}
|
||||
@ -400,7 +445,7 @@ func TestBuildPublicDashboardMetricRequest(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("extracts queries from provided dashboard", func(t *testing.T) {
|
||||
reqDTO, err := service.buildPublicDashboardMetricRequest(
|
||||
reqDTO, err := service.buildMetricRequest(
|
||||
context.Background(),
|
||||
publicDashboard,
|
||||
publicDashboardPD,
|
||||
@ -409,8 +454,8 @@ func TestBuildPublicDashboardMetricRequest(t *testing.T) {
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, timeSettings.Get("from").MustString(), reqDTO.From)
|
||||
require.Equal(t, timeSettings.Get("to").MustString(), reqDTO.To)
|
||||
require.Equal(t, from, reqDTO.From)
|
||||
require.Equal(t, to, reqDTO.To)
|
||||
|
||||
for i := range reqDTO.Queries {
|
||||
require.Equal(t, publicDashboardQueryDTO.IntervalMs, reqDTO.Queries[i].Get("intervalMs").MustInt64())
|
||||
@ -449,7 +494,7 @@ func TestBuildPublicDashboardMetricRequest(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("returns an error when panel missing", func(t *testing.T) {
|
||||
_, err := service.buildPublicDashboardMetricRequest(
|
||||
_, err := service.buildMetricRequest(
|
||||
context.Background(),
|
||||
publicDashboard,
|
||||
publicDashboardPD,
|
||||
@ -514,6 +559,10 @@ func insertTestDashboard(t *testing.T, dashboardStore *dashboardsDB.DashboardSto
|
||||
"templating": map[string]interface{}{
|
||||
"list": templateVars,
|
||||
},
|
||||
"time": map[string]interface{}{
|
||||
"from": "2022-09-01T00:00:00.000Z",
|
||||
"to": "2022-09-01T12:00:00.000Z",
|
||||
},
|
||||
}),
|
||||
}
|
||||
dash, err := dashboardStore.SaveDashboard(cmd)
|
||||
@ -526,8 +575,8 @@ func insertTestDashboard(t *testing.T, dashboardStore *dashboardsDB.DashboardSto
|
||||
|
||||
func TestPublicDashboardServiceImpl_getSafeIntervalAndMaxDataPoints(t *testing.T) {
|
||||
type args struct {
|
||||
reqDTO *PublicDashboardQueryDTO
|
||||
ts *TimeSettings
|
||||
reqDTO PublicDashboardQueryDTO
|
||||
ts TimeSettings
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
@ -538,11 +587,11 @@ func TestPublicDashboardServiceImpl_getSafeIntervalAndMaxDataPoints(t *testing.T
|
||||
{
|
||||
name: "return original interval",
|
||||
args: args{
|
||||
reqDTO: &PublicDashboardQueryDTO{
|
||||
reqDTO: PublicDashboardQueryDTO{
|
||||
IntervalMs: 10000,
|
||||
MaxDataPoints: 300,
|
||||
},
|
||||
ts: &TimeSettings{
|
||||
ts: TimeSettings{
|
||||
From: "now-3h",
|
||||
To: "now",
|
||||
},
|
||||
@ -553,11 +602,11 @@ func TestPublicDashboardServiceImpl_getSafeIntervalAndMaxDataPoints(t *testing.T
|
||||
{
|
||||
name: "return safe interval because of a small interval",
|
||||
args: args{
|
||||
reqDTO: &PublicDashboardQueryDTO{
|
||||
reqDTO: PublicDashboardQueryDTO{
|
||||
IntervalMs: 1000,
|
||||
MaxDataPoints: 300,
|
||||
},
|
||||
ts: &TimeSettings{
|
||||
ts: TimeSettings{
|
||||
From: "now-6h",
|
||||
To: "now",
|
||||
},
|
||||
@ -568,11 +617,11 @@ func TestPublicDashboardServiceImpl_getSafeIntervalAndMaxDataPoints(t *testing.T
|
||||
{
|
||||
name: "return safe interval for long time range",
|
||||
args: args{
|
||||
reqDTO: &PublicDashboardQueryDTO{
|
||||
reqDTO: PublicDashboardQueryDTO{
|
||||
IntervalMs: 100,
|
||||
MaxDataPoints: 300,
|
||||
},
|
||||
ts: &TimeSettings{
|
||||
ts: TimeSettings{
|
||||
From: "now-90d",
|
||||
To: "now",
|
||||
},
|
||||
@ -583,8 +632,8 @@ func TestPublicDashboardServiceImpl_getSafeIntervalAndMaxDataPoints(t *testing.T
|
||||
{
|
||||
name: "return safe interval when reqDTO is empty",
|
||||
args: args{
|
||||
reqDTO: &PublicDashboardQueryDTO{},
|
||||
ts: &TimeSettings{
|
||||
reqDTO: PublicDashboardQueryDTO{},
|
||||
ts: TimeSettings{
|
||||
From: "now-90d",
|
||||
To: "now",
|
||||
},
|
||||
|
@ -21,7 +21,7 @@ func hasTemplateVariables(dashboard *models.Dashboard) bool {
|
||||
return len(templateVariables) > 0
|
||||
}
|
||||
|
||||
func ValidateQueryPublicDashboardRequest(req *publicDashboardModels.PublicDashboardQueryDTO) error {
|
||||
func ValidateQueryPublicDashboardRequest(req publicDashboardModels.PublicDashboardQueryDTO) error {
|
||||
if req.IntervalMs < 0 {
|
||||
return fmt.Errorf("intervalMS should be greater than 0")
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user