Before requesting the metadata check the access mode (#55403)

* Before requesting the metadata check the access mode

* Update tests

* Update tests again
This commit is contained in:
ismail simsek
2022-09-19 18:56:51 +02:00
committed by GitHub
parent 04ec76aaf3
commit 89410ffd0c
3 changed files with 61 additions and 29 deletions
@@ -131,6 +131,7 @@ describe('PrometheusDatasource', () => {
describe('customQueryParams', () => {
const target = { expr: 'test{job="testjob"}', format: 'time_series', refId: '' };
function makeQuery(target: PromQuery) {
return {
range: { from: time({ seconds: 63 }), to: time({ seconds: 183 }) },
@@ -140,19 +141,27 @@ describe('PrometheusDatasource', () => {
}
describe('with GET http method', () => {
const promDs = new PrometheusDatasource(
{ ...instanceSettings, jsonData: { customQueryParameters: 'customQuery=123', httpMethod: 'GET' } as any },
templateSrvStub as any,
timeSrvStub as any
);
const getPromDs = (access: 'direct' | 'proxy') => {
return new PrometheusDatasource(
{
...instanceSettings,
access,
jsonData: { customQueryParameters: 'customQuery=123', httpMethod: 'GET' } as any,
},
templateSrvStub as any,
timeSrvStub as any
);
};
it('added to metadata request', () => {
const promDs = getPromDs('proxy');
promDs.metadataRequest('/foo');
expect(fetchMock.mock.calls.length).toBe(1);
expect(fetchMock.mock.calls[0][0].url).toBe('/api/datasources/1/resources/foo?customQuery=123');
});
it('adds params to timeseries query', () => {
const promDs = getPromDs('direct');
promDs.query(makeQuery(target));
expect(fetchMock.mock.calls.length).toBe(1);
expect(fetchMock.mock.calls[0][0].url).toBe(
@@ -160,6 +169,7 @@ describe('PrometheusDatasource', () => {
);
});
it('adds params to exemplars query', () => {
const promDs = getPromDs('direct');
promDs.query(makeQuery({ ...target, exemplar: true }));
// We do also range query for single exemplars target
expect(fetchMock.mock.calls.length).toBe(2);
@@ -168,6 +178,7 @@ describe('PrometheusDatasource', () => {
});
it('adds params to instant query', () => {
const promDs = getPromDs('direct');
promDs.query(makeQuery({ ...target, instant: true }));
expect(fetchMock.mock.calls.length).toBe(1);
expect(fetchMock.mock.calls[0][0].url).toContain('&customQuery=123');
@@ -175,19 +186,31 @@ describe('PrometheusDatasource', () => {
});
describe('with POST http method', () => {
const promDs = new PrometheusDatasource(
{ ...instanceSettings, jsonData: { customQueryParameters: 'customQuery=123', httpMethod: 'POST' } as any },
templateSrvStub as any,
timeSrvStub as any
);
const getPromDs = (access: 'direct' | 'proxy') => {
return new PrometheusDatasource(
{
...instanceSettings,
access,
jsonData: { customQueryParameters: 'customQuery=123', httpMethod: 'POST' } as any,
},
templateSrvStub as any,
timeSrvStub as any
);
};
it('added to metadata request with non-POST endpoint', () => {
promDs.metadataRequest('/foo');
it('added to metadata request with non-POST endpoint ', () => {
const proxyPromDs = getPromDs('proxy');
proxyPromDs.metadataRequest('/foo');
expect(fetchMock.mock.calls.length).toBe(1);
expect(fetchMock.mock.calls[0][0].url).toBe('/api/datasources/1/resources/foo?customQuery=123');
const directPromDs = getPromDs('direct');
directPromDs.metadataRequest('/foo');
expect(fetchMock.mock.calls.length).toBe(2);
expect(fetchMock.mock.calls[1][0].url).toBe('proxied/foo?customQuery=123');
});
it('added to metadata request with POST endpoint', () => {
const promDs = getPromDs('proxy');
promDs.metadataRequest('/api/v1/labels');
expect(fetchMock.mock.calls.length).toBe(1);
expect(fetchMock.mock.calls[0][0].url).toBe('/api/datasources/1/resources/api/v1/labels');
@@ -195,6 +218,7 @@ describe('PrometheusDatasource', () => {
});
it('adds params to timeseries query', () => {
const promDs = getPromDs('direct');
promDs.query(makeQuery(target));
expect(fetchMock.mock.calls.length).toBe(1);
expect(fetchMock.mock.calls[0][0].url).toBe('proxied/api/v1/query_range');
@@ -206,7 +230,9 @@ describe('PrometheusDatasource', () => {
start: 60,
});
});
it('adds params to exemplars query', () => {
const promDs = getPromDs('direct');
promDs.query(makeQuery({ ...target, exemplar: true }));
// We do also range query for single exemplars target
expect(fetchMock.mock.calls.length).toBe(2);
@@ -215,6 +241,7 @@ describe('PrometheusDatasource', () => {
});
it('adds params to instant query', () => {
const promDs = getPromDs('direct');
promDs.query(makeQuery({ ...target, instant: true }));
expect(fetchMock.mock.calls.length).toBe(1);
expect(fetchMock.mock.calls[0][0].data.customQuery).toBe('123');
@@ -5,8 +5,10 @@ import { forkJoin, lastValueFrom, merge, Observable, of, OperatorFunction, pipe,
import { catchError, filter, map, tap } from 'rxjs/operators';
import {
AbstractQuery,
AnnotationEvent,
CoreApp,
DataFrame,
DataQueryError,
DataQueryRequest,
DataQueryResponse,
@@ -15,31 +17,29 @@ import {
DataSourceWithQueryImportSupport,
dateMath,
DateTime,
AbstractQuery,
dateTime,
LoadingState,
QueryFixAction,
rangeUtil,
ScopedVars,
TimeRange,
DataFrame,
dateTime,
QueryFixAction,
} from '@grafana/data';
import {
BackendDataSourceResponse,
BackendSrvRequest,
DataSourceWithBackend,
FetchError,
FetchResponse,
getBackendSrv,
DataSourceWithBackend,
BackendDataSourceResponse,
toDataQueryResponse,
isFetchError,
toDataQueryResponse,
} from '@grafana/runtime';
import { Badge, BadgeColor, Tooltip } from '@grafana/ui';
import { safeStringifyValue } from 'app/core/utils/explore';
import { discoverDataSourceFeatures } from 'app/features/alerting/unified/api/buildInfo';
import { getTimeSrv, TimeSrv } from 'app/features/dashboard/services/TimeSrv';
import { getTemplateSrv, TemplateSrv } from 'app/features/templating/template_srv';
import { PromApplication, PromApiFeatures } from 'app/types/unified-alerting-dto';
import { PromApiFeatures, PromApplication } from 'app/types/unified-alerting-dto';
import { addLabelToQuery } from './add_label_to_query';
import { AnnotationQueryEditor } from './components/AnnotationQueryEditor';
@@ -214,11 +214,16 @@ export class PrometheusDatasource
// Use this for tab completion features, wont publish response to other components
async metadataRequest<T = any>(url: string, params = {}, options?: Partial<BackendSrvRequest>) {
// Build the request URL based on the access mode
let queryUrl = url;
if (this.access === 'proxy') {
queryUrl = `/api/datasources/${this.id}/resources` + queryUrl;
}
// If URL includes endpoint that supports POST and GET method, try to use configured method. This might fail as POST is supported only in v2.10+.
if (GET_AND_POST_METADATA_ENDPOINTS.some((endpoint) => url.includes(endpoint))) {
try {
return await lastValueFrom(
this._request<T>(`/api/datasources/${this.id}/resources${url}`, params, {
this._request<T>(queryUrl, params, {
method: this.httpMethod,
hideFromInspector: true,
showErrorAlert: false,
@@ -236,7 +241,7 @@ export class PrometheusDatasource
}
return await lastValueFrom(
this._request<T>(`/api/datasources/${this.id}/resources${url}`, params, {
this._request<T>(queryUrl, params, {
method: 'GET',
hideFromInspector: true,
...options,
@@ -76,7 +76,7 @@ describe('PrometheusMetricFindQuery', () => {
expect(fetchMock).toHaveBeenCalledTimes(1);
expect(fetchMock).toHaveBeenCalledWith({
method: 'GET',
url: `/api/datasources/1/resources/api/v1/labels?start=${raw.from.unix()}&end=${raw.to.unix()}`,
url: `proxied/api/v1/labels?start=${raw.from.unix()}&end=${raw.to.unix()}`,
hideFromInspector: true,
showErrorAlert: false,
headers: {},
@@ -96,7 +96,7 @@ describe('PrometheusMetricFindQuery', () => {
expect(fetchMock).toHaveBeenCalledTimes(1);
expect(fetchMock).toHaveBeenCalledWith({
method: 'GET',
url: `/api/datasources/1/resources/api/v1/label/resource/values?start=${raw.from.unix()}&end=${raw.to.unix()}`,
url: `proxied/api/v1/label/resource/values?start=${raw.from.unix()}&end=${raw.to.unix()}`,
hideFromInspector: true,
headers: {},
});
@@ -119,7 +119,7 @@ describe('PrometheusMetricFindQuery', () => {
expect(fetchMock).toHaveBeenCalledTimes(1);
expect(fetchMock).toHaveBeenCalledWith({
method: 'GET',
url: `/api/datasources/1/resources/api/v1/series?match${encodeURIComponent(
url: `proxied/api/v1/series?match${encodeURIComponent(
'[]'
)}=metric&start=${raw.from.unix()}&end=${raw.to.unix()}`,
hideFromInspector: true,
@@ -145,7 +145,7 @@ describe('PrometheusMetricFindQuery', () => {
expect(fetchMock).toHaveBeenCalledTimes(1);
expect(fetchMock).toHaveBeenCalledWith({
method: 'GET',
url: '/api/datasources/1/resources/api/v1/series?match%5B%5D=metric%7Blabel1%3D%22foo%22%2C%20label2%3D%22bar%22%2C%20label3%3D%22baz%22%7D&start=1524650400&end=1524654000',
url: 'proxied/api/v1/series?match%5B%5D=metric%7Blabel1%3D%22foo%22%2C%20label2%3D%22bar%22%2C%20label3%3D%22baz%22%7D&start=1524650400&end=1524654000',
hideFromInspector: true,
showErrorAlert: false,
headers: {},
@@ -171,7 +171,7 @@ describe('PrometheusMetricFindQuery', () => {
expect(fetchMock).toHaveBeenCalledTimes(1);
expect(fetchMock).toHaveBeenCalledWith({
method: 'GET',
url: `/api/datasources/1/resources/api/v1/series?match${encodeURIComponent(
url: `proxied/api/v1/series?match${encodeURIComponent(
'[]'
)}=metric&start=${raw.from.unix()}&end=${raw.to.unix()}`,
hideFromInspector: true,
@@ -193,7 +193,7 @@ describe('PrometheusMetricFindQuery', () => {
expect(fetchMock).toHaveBeenCalledTimes(1);
expect(fetchMock).toHaveBeenCalledWith({
method: 'GET',
url: `/api/datasources/1/resources/api/v1/label/__name__/values?start=${raw.from.unix()}&end=${raw.to.unix()}`,
url: `proxied/api/v1/label/__name__/values?start=${raw.from.unix()}&end=${raw.to.unix()}`,
hideFromInspector: true,
headers: {},
});
@@ -269,7 +269,7 @@ describe('PrometheusMetricFindQuery', () => {
expect(fetchMock).toHaveBeenCalledTimes(1);
expect(fetchMock).toHaveBeenCalledWith({
method: 'GET',
url: `/api/datasources/1/resources/api/v1/series?match${encodeURIComponent('[]')}=${encodeURIComponent(
url: `proxied/api/v1/series?match${encodeURIComponent('[]')}=${encodeURIComponent(
'up{job="job1"}'
)}&start=${raw.from.unix()}&end=${raw.to.unix()}`,
hideFromInspector: true,