Skip to content

Commit 45fc33c

Browse files
committed
Support for new autocomplete endpoints
Improved autocompleter endpoint detection. Only needed one request when starting to edit a dashboard. No extra requests made on visualization mode
1 parent e324ccc commit 45fc33c

File tree

6 files changed

+101
-18
lines changed

6 files changed

+101
-18
lines changed

src/DataSource.ts

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { replaceVariables } from 'utils';
1010

1111
import { MetricFindQuery, RequestSpec } from './RequestSpec';
1212
import RestApiBackend from './backend/rest';
13-
import { Backend } from './backend/types';
13+
import { BACKEND_TYPE, Backend } from './backend/types';
1414
import WebApiBackend from './backend/web';
1515
import { Settings } from './settings';
1616
import { Backend as BackendType, CmkQuery, DataSourceOptions, Edition, ResponseDataAutocomplete } from './types';
@@ -22,6 +22,7 @@ export class DataSource extends DataSourceApi<CmkQuery> {
2222
webBackend: WebApiBackend;
2323
restBackend: RestApiBackend;
2424
settings: Settings;
25+
autocompleteBackend: BACKEND_TYPE | null = null;
2526

2627
constructor(private instanceSettings: DataSourceInstanceSettings<DataSourceOptions>) {
2728
super(instanceSettings);
@@ -30,14 +31,18 @@ export class DataSource extends DataSourceApi<CmkQuery> {
3031
this.settings = new Settings(instanceSettings.jsonData);
3132
}
3233

34+
protected async setAutocompleteBackend() {
35+
this.autocompleteBackend = await this.getBackend().getAutocompleteBackend();
36+
}
37+
3338
async query(dataQueryRequest: DataQueryRequest<CmkQuery>): Promise<DataQueryResponse> {
3439
for (const target of dataQueryRequest.targets) {
3540
target.requestSpec = replaceVariables(target.requestSpec, dataQueryRequest.scopedVars);
3641
}
3742
return this.getBackend().query(dataQueryRequest);
3843
}
3944

40-
async metricFindQuery(query: MetricFindQuery, options?: any): Promise<MetricFindValue[]> {
45+
async metricFindQuery(query: MetricFindQuery, options?: unknown): Promise<MetricFindValue[]> {
4146
if (query.objectType === 'site') {
4247
// rest-api site endpoint were added in 2.2.0 so we have to use the web-api here
4348
// TODO: clean up (remove filterSites from Backend) with end of 2.1.0
@@ -51,8 +56,17 @@ export class DataSource extends DataSourceApi<CmkQuery> {
5156
return this.getBackend().testDatasource();
5257
}
5358

54-
async autocompleterRequest<T>(api_url: string, data: unknown): Promise<FetchResponse<WebApiResponse<T>>> {
55-
return this.webBackend.autocompleterRequest(api_url, data);
59+
async autocompleterRequest(
60+
api_url: string,
61+
data: unknown
62+
): Promise<FetchResponse<WebApiResponse<ResponseDataAutocomplete>>> {
63+
this.autocompleteBackend === null && (await this.setAutocompleteBackend());
64+
65+
if (this.autocompleteBackend === BACKEND_TYPE.WEB) {
66+
return this.webBackend.autocompleterRequest(api_url, data);
67+
}
68+
69+
return this.restBackend.autocompleterRequest(api_url, data);
5670
}
5771

5872
async contextAutocomplete(
@@ -64,10 +78,13 @@ export class DataSource extends DataSourceApi<CmkQuery> {
6478
if (ident === 'label' && this.getBackendType() === 'web') {
6579
// we have a 2.1.0 version without werk #15074 so label autocompleter is a special edge case
6680
// can be removed after we stop supporting 2.1.0
67-
const response = await this.autocompleterRequest<Array<{ value: string }>>('ajax_autocomplete_labels.py', {
68-
world: params.world,
69-
search_label: prefix,
70-
});
81+
const response = await this.webBackend.autocompleterRequest<Array<{ value: string }>>(
82+
'ajax_autocomplete_labels.py',
83+
{
84+
world: params.world,
85+
search_label: prefix,
86+
}
87+
);
7188
return response.data.result.map((val: { value: string }) => ({
7289
value: val.value,
7390
label: val.value,
@@ -78,7 +95,7 @@ export class DataSource extends DataSourceApi<CmkQuery> {
7895
replaceVariables(partialRequestSpec),
7996
this.getBackendType() === 'rest' ? 'latest' : '2.1.0'
8097
);
81-
const response = await this.autocompleterRequest<ResponseDataAutocomplete>('ajax_vs_autocomplete.py', {
98+
const response = await this.autocompleterRequest('ajax_vs_autocomplete.py', {
8299
ident,
83100
value: prefix,
84101
params: {

src/backend/rest.ts

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@ import { BackendSrvRequest, FetchError, FetchResponse, getBackendSrv } from '@gr
1616
import { Aggregation, GraphType, MetricFindQuery } from 'RequestSpec';
1717
import * as process from 'process';
1818

19-
import { CmkQuery } from '../types';
19+
import { CmkQuery, ResponseDataAutocomplete } from '../types';
2020
import { createCmkContext, replaceVariables, toLiveStatusQuery, updateMetricTitles, updateQuery } from '../utils';
21-
import { Backend, DatasourceOptions } from './types';
21+
import { WebApiResponse } from './../webapi';
22+
import { BACKEND_TYPE, Backend, DatasourceOptions } from './types';
2223
import { validateRequestSpec } from './validate';
2324

2425
type RestApiError = {
@@ -85,6 +86,14 @@ type RestApiHostResponse = RestApiLivestatusResponse<{ name: string }>;
8586

8687
type RestApiServiceResponse = RestApiLivestatusResponse<{ description: string }>;
8788

89+
type RestApiAutocompleteResponseEntry = {
90+
id: string;
91+
value: string;
92+
};
93+
94+
type RestApiAutocompleteResponse = {
95+
choices: [RestApiAutocompleteResponseEntry];
96+
};
8897
export default class RestApiBackend implements Backend {
8998
datasource: DatasourceOptions;
9099

@@ -362,4 +371,44 @@ export default class RestApiBackend implements Backend {
362371
return new MutableDataFrame();
363372
}
364373
}
374+
375+
async getAutocompleteBackend(): Promise<BACKEND_TYPE> {
376+
return this.api<RestApiAutocompleteResponse>({
377+
url: `/objects/autocomplete/sites`,
378+
method: 'POST',
379+
data: { value: '', parameters: {} },
380+
})
381+
.then(() => {
382+
return BACKEND_TYPE.REST;
383+
})
384+
.catch(() => {
385+
return BACKEND_TYPE.WEB;
386+
});
387+
}
388+
389+
async autocompleterRequest(
390+
api_url = '',
391+
data: unknown
392+
): Promise<FetchResponse<WebApiResponse<ResponseDataAutocomplete>>> {
393+
const { ident, params: parameters, value } = data as { ident: string; value: unknown; params: unknown };
394+
395+
const response = await this.api<RestApiAutocompleteResponse>({
396+
url: `/objects/autocomplete/${ident}`,
397+
method: 'POST',
398+
data: { value, parameters },
399+
});
400+
401+
const choices = response?.data?.choices || [];
402+
403+
const new_data: WebApiResponse<ResponseDataAutocomplete> = {
404+
result_code: 200,
405+
severity: 'success',
406+
result: {
407+
choices: choices.map((element) => [element.id, element.value]),
408+
},
409+
};
410+
411+
const res: FetchResponse<WebApiResponse<ResponseDataAutocomplete>> = { ...response, data: new_data };
412+
return res;
413+
}
365414
}

src/backend/types.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,22 @@ import { DataQueryRequest, DataQueryResponse, MetricFindValue } from '@grafana/d
33
import { MetricFindQuery } from '../RequestSpec';
44
import { CmkQuery, Edition } from '../types';
55

6+
export enum BACKEND_TYPE {
7+
REST = 'rest',
8+
WEB = 'web',
9+
}
10+
611
export interface Backend {
712
query: (options: DataQueryRequest<CmkQuery>) => Promise<DataQueryResponse>;
813
testDatasource: () => Promise<unknown>;
914
metricFindQuery: (query: MetricFindQuery) => Promise<MetricFindValue[]>;
1015
listSites: () => Promise<MetricFindValue[]>;
16+
getAutocompleteBackend: () => Promise<BACKEND_TYPE>;
1117
}
1218

1319
export interface DatasourceOptions {
1420
getBackend: () => Backend;
1521
getEdition: () => Edition;
1622
getUrl: () => string | undefined;
17-
1823
getUsername(): string;
1924
}

src/backend/web.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import {
2020
createWebApiRequestBody,
2121
createWebApiRequestSpecification,
2222
} from './../webapi';
23-
import { Backend, DatasourceOptions } from './types';
23+
import { BACKEND_TYPE, Backend, DatasourceOptions } from './types';
2424
import { validateRequestSpec } from './validate';
2525

2626
export default class WebApiBackend implements Backend {
@@ -203,4 +203,8 @@ export default class WebApiBackend implements Backend {
203203

204204
return frame;
205205
}
206+
207+
async getAutocompleteBackend(): Promise<BACKEND_TYPE> {
208+
return BACKEND_TYPE.WEB;
209+
}
206210
}

src/plugin.json

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,18 @@
1616
"large": "img/checkmk_logo.svg"
1717
},
1818
"links": [
19-
{ "name": "Documentation", "url": "https://docs.checkmk.com/latest/en/grafana.html" },
20-
{ "name": "GitHub", "url": "https://github.com/Checkmk/grafana-checkmk-datasource" },
21-
{ "name": "Checkmk", "url": "https://Checkmk.com" }
19+
{
20+
"name": "Documentation",
21+
"url": "https://docs.checkmk.com/latest/en/grafana.html"
22+
},
23+
{
24+
"name": "GitHub",
25+
"url": "https://github.com/Checkmk/grafana-checkmk-datasource"
26+
},
27+
{
28+
"name": "Checkmk",
29+
"url": "https://Checkmk.com"
30+
}
2231
],
2332
"screenshots": [
2433
{

src/ui/filters.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import React from 'react';
22

33
import { DataSource } from '../DataSource';
44
import { RequestSpec } from '../RequestSpec';
5-
import { ResponseDataAutocomplete } from '../types';
65
import {
76
CheckMkSelect,
87
CheckMkSelectNegatable,
@@ -79,7 +78,7 @@ export const Filters = (props: FiltersProp): JSX.Element => {
7978
} else {
8079
return (async function () {
8180
// TODO: would have expected that this is dependent on the site, but does not look like that?
82-
const response = await datasource.autocompleterRequest<ResponseDataAutocomplete>('ajax_vs_autocomplete.py', {
81+
const response = await datasource.autocompleterRequest('ajax_vs_autocomplete.py', {
8382
ident: 'tag_groups_opt',
8483
params: { group_id: context.groupId, strict: true },
8584
value: prefix,

0 commit comments

Comments
 (0)