Skip to content

Commit ffd13c6

Browse files
setting max page limit for pagination via grafana config (#1075)
Co-authored-by: ivanahuckova <[email protected]>
1 parent 1921093 commit ffd13c6

File tree

7 files changed

+101
-14
lines changed

7 files changed

+101
-14
lines changed

.changeset/soft-lobsters-enjoy.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'grafana-infinity-datasource': minor
3+
---
4+
5+
Setting backend pagination max page size via grafana config (ini file)

conf/grafana.ini

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[plugin.yesoreyeram-infinity-datasource]
2+
pagination_max_pages=8

docker-compose.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@ services:
1111
volumes:
1212
- ./provisioning/dashboards-actual/:/dashboards/
1313
- ./provisioning:/etc/grafana/provisioning
14+
- ./conf:/grafana-config
1415
- ./dist:/var/lib/grafana/plugins/yesoreyeram-infinity-datasource
1516
environment:
1617
- TERM=linux
1718
- GF_DEFAULT_APP_MODE=development
19+
- GF_PATHS_CONFIG=/grafana-config/grafana.ini
1820
- GF_AUTH_ANONYMOUS_ENABLED=true
1921
- GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
2022
- GF_SECURITY_ANGULAR_SUPPORT_ENABLED=false

pkg/models/grafana_config.go

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package models
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"os"
7+
"strings"
8+
9+
"github.com/grafana/grafana-plugin-sdk-go/backend"
10+
)
11+
12+
// GetGrafanaConfig allow you to retrieve config set via grafana.ini file
13+
func GetGrafanaConfig(ctx context.Context, pCtx *backend.PluginContext, key string) (output string) {
14+
key = strings.TrimSpace(strings.ToUpper(key))
15+
if v := strings.TrimSpace(os.Getenv(fmt.Sprintf("GF_PLUGIN_%s", key))); v != "" {
16+
output = v
17+
}
18+
return output
19+
}

pkg/models/query.go

+22-8
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"errors"
77
"fmt"
88
"net/http"
9+
"strconv"
910
"strings"
1011

1112
"github.com/grafana/grafana-plugin-sdk-go/backend"
@@ -188,7 +189,7 @@ type InfinityDataOverride struct {
188189
Override string `json:"override"`
189190
}
190191

191-
func ApplyDefaultsToQuery(ctx context.Context, query Query, settings InfinitySettings) Query {
192+
func ApplyDefaultsToQuery(ctx context.Context, pCtx *backend.PluginContext, query Query, settings InfinitySettings) Query {
192193
if query.Type == "" {
193194
query.Type = QueryTypeJSON
194195
if query.Source == "" {
@@ -254,12 +255,7 @@ func ApplyDefaultsToQuery(ctx context.Context, query Query, settings InfinitySet
254255
}
255256
if query.Parser == InfinityParserBackend && query.Source == "url" && !(query.PageMode == "" || query.PageMode == PaginationModeNone) {
256257
if query.PageMode != PaginationModeNone {
257-
if query.PageMaxPages <= 0 {
258-
query.PageMaxPages = 1
259-
}
260-
if query.PageMaxPages >= 5 {
261-
query.PageMaxPages = 5
262-
}
258+
query.PageMaxPages = GetPaginationMaxPagesValue(ctx, pCtx, query)
263259
if query.PageParamSizeFieldName == "" {
264260
query.PageParamSizeFieldName = "limit"
265261
}
@@ -315,10 +311,28 @@ func LoadQuery(ctx context.Context, backendQuery backend.DataQuery, pluginContex
315311
if err != nil {
316312
return query, backend.DownstreamError(fmt.Errorf("error while parsing the query json. %w", err))
317313
}
318-
query = ApplyDefaultsToQuery(ctx, query, settings)
314+
query = ApplyDefaultsToQuery(ctx, &pluginContext, query, settings)
319315
if query.PageMode == PaginationModeList && strings.TrimSpace(query.PageParamListFieldName) == "" {
320316
// Downstream error as user input is not correct
321317
return query, backend.DownstreamError(errors.New("pagination_param_list_field_name cannot be empty"))
322318
}
323319
return ApplyMacros(ctx, query, backendQuery.TimeRange, pluginContext)
324320
}
321+
322+
func GetPaginationMaxPagesValue(ctx context.Context, pCtx *backend.PluginContext, query Query) int {
323+
maxPages := 5
324+
if query.PageMaxPages <= 0 {
325+
maxPages = 1
326+
}
327+
if query.PageMaxPages >= 5 {
328+
maxPages = 5
329+
}
330+
maxPageFromEnv := GetGrafanaConfig(ctx, pCtx, "pagination_max_pages")
331+
if maxPageFromEnvValue, err := strconv.Atoi(maxPageFromEnv); err == nil && maxPageFromEnvValue > 0 {
332+
maxPages = maxPageFromEnvValue
333+
}
334+
if query.PageMaxPages <= maxPages && query.PageMaxPages > 0 {
335+
return query.PageMaxPages
336+
}
337+
return maxPages
338+
}

pkg/models/query_test.go

+46
Original file line numberDiff line numberDiff line change
@@ -134,3 +134,49 @@ func TestLoadQuery(t *testing.T) {
134134
})
135135
}
136136
}
137+
138+
func TestGetPaginationMaxPagesValue(t *testing.T) {
139+
tests := []struct {
140+
name string
141+
pCtx *backend.PluginContext
142+
envVars map[string]string
143+
query models.Query
144+
want int
145+
}{
146+
{
147+
name: "should return 1 if no defaults set",
148+
want: 1,
149+
},
150+
{
151+
name: "should return 1 if negative values set in query",
152+
query: models.Query{PageMaxPages: -5},
153+
want: 1,
154+
},
155+
{
156+
name: "should return 5 if higher values set",
157+
query: models.Query{PageMaxPages: 100},
158+
want: 5,
159+
},
160+
{
161+
name: "should respect GF_PLUGIN_pagination_max_pages key",
162+
query: models.Query{PageMaxPages: 100},
163+
envVars: map[string]string{"GF_PLUGIN_PAGINATION_MAX_PAGES": "10"},
164+
want: 10,
165+
},
166+
{
167+
name: "should respect query page max if the value is lesser than environment variable",
168+
query: models.Query{PageMaxPages: 6},
169+
envVars: map[string]string{"GF_PLUGIN_PAGINATION_MAX_PAGES": "8"},
170+
want: 6,
171+
},
172+
}
173+
for _, tt := range tests {
174+
t.Run(tt.name, func(t *testing.T) {
175+
for k, v := range tt.envVars {
176+
t.Setenv(k, v)
177+
}
178+
got := models.GetPaginationMaxPagesValue(context.TODO(), tt.pCtx, tt.query)
179+
require.Equal(t, tt.want, got)
180+
})
181+
}
182+
}

src/editors/query/query.pagination.tsx

+5-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React from 'react';
2-
import { InlineLabel, Input, Select, Stack } from '@grafana/ui';
3-
import { SelectableValue } from '@grafana/data';
2+
import { FeatureBadge, InlineLabel, Input, Select, Stack } from '@grafana/ui';
3+
import { FeatureState, SelectableValue } from '@grafana/data';
44
import { EditorField } from './../../components/extended/EditorField';
55
import { EditorRow } from './../../components/extended/EditorRow';
66
import type { InfinityQuery, PaginationParamType, PaginationType } from './../../types';
@@ -30,22 +30,21 @@ type PaginationEditorProps = {
3030
export const PaginationEditor = (props: PaginationEditorProps) => {
3131
const { query, onChange } = props;
3232
return (
33-
<EditorRow label={'Pagination'} collapsible={true} collapsed={false} title={() => 'beta'}>
33+
<EditorRow label={'Pagination'} collapsible={true} collapsed={false} title={() => <FeatureBadge featureState={FeatureState.beta} />}>
3434
<Stack direction="row" wrap={'wrap'}>
3535
<Stack wrap={'nowrap'} direction="column">
3636
<EditorField label="Pagination Type">
3737
<Select<PaginationType> width={30} value={query.pagination_mode || 'none'} options={paginationTypes} onChange={(e) => onChange({ ...query, pagination_mode: e.value || 'none' })} />
3838
</EditorField>
3939
{query.pagination_mode && query.pagination_mode !== 'none' && (
40-
<EditorField label="Max pages" tooltip={'maximum of 5 pages. minimum of 1 page. Default 1'}>
40+
<EditorField label="Max pages" tooltip={'Enter a value between 1 and a maximum of 5 pages, or the maximum page limit set in the Grafana configuration for the Infinity plugin.'}>
4141
<Input
4242
type={'number'}
4343
min={1}
44-
max={5}
4544
width={30}
4645
value={query.pagination_max_pages}
4746
onChange={(e) => onChange({ ...query, pagination_max_pages: e.currentTarget.valueAsNumber || 1 })}
48-
placeholder="min:1, max:5"
47+
placeholder="1"
4948
/>
5049
</EditorField>
5150
)}

0 commit comments

Comments
 (0)