Skip to content

Commit 8304d9f

Browse files
committed
labels filter interface changed in checkmk
1 parent 5835624 commit 8304d9f

File tree

5 files changed

+74
-52
lines changed

5 files changed

+74
-52
lines changed

src/DataSource.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import RestApiBackend from './backend/rest';
66
import { Backend } from './backend/types';
77
import WebApiBackend from './backend/web';
88
import { Backend as BackendType, CmkQuery, DataSourceOptions, Edition, ResponseDataAutocomplete } from './types';
9-
import { createAutocompleteConfig } from './ui/autocomplete';
9+
import { AutoCompleteParams } from './ui/autocomplete';
10+
import { createCmkContext } from './utils';
1011
import { WebApiResponse, buildRequestBody } from './webapi';
1112

1213
export class DataSource extends DataSourceApi<CmkQuery> {
@@ -40,13 +41,13 @@ export class DataSource extends DataSourceApi<CmkQuery> {
4041
ident: string,
4142
partialRequestSpec: Partial<RequestSpec>,
4243
prefix: string,
43-
params: Record<string, string | boolean>
44+
params: Partial<AutoCompleteParams>
4445
): Promise<Array<{ value: string; label: string; isDisabled: boolean }>> {
4546
if (ident === 'label' && this.getBackendType() === 'web') {
4647
// we have a 2.1.0 version without werk #15074 so label autocompleter is a special edge case
4748
// can be removed after we stop supporting 2.1.0
4849
const response = await this.autocompleterRequest<Array<{ value: string }>>('ajax_autocomplete_labels.py', {
49-
world: params['world'],
50+
world: params.world,
5051
search_label: prefix,
5152
});
5253
return response.data.result.map((val: { value: string }) => ({
@@ -55,10 +56,15 @@ export class DataSource extends DataSourceApi<CmkQuery> {
5556
isDisabled: false,
5657
}));
5758
}
58-
const response = await this.autocompleterRequest<ResponseDataAutocomplete>(
59-
'ajax_vs_autocomplete.py',
60-
createAutocompleteConfig(partialRequestSpec, ident, prefix, params)
61-
);
59+
const context = createCmkContext(partialRequestSpec, this.getBackendType() === 'rest' ? 'latest' : '2.1.0');
60+
const response = await this.autocompleterRequest<ResponseDataAutocomplete>('ajax_vs_autocomplete.py', {
61+
ident,
62+
value: prefix,
63+
params: {
64+
...params,
65+
context,
66+
},
67+
});
6268
return response.data.result.choices.map(([value, label]: [string, string]) => ({
6369
value,
6470
label,

src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export interface Context {
1818
hostregex?: { host_regex: string; neg_host_regex?: Negative };
1919
service?: { service: string };
2020
serviceregex?: { neg_service_regex?: Negative; service_regex: string };
21-
host_labels?: { host_label: string };
21+
host_labels?: Record<string, string>;
2222
opthostgroup?: { opthost_group: string; neg_opthost_group?: Negative };
2323
optservicegroup?: { optservice_group: string; neg_optservice_group?: Negative };
2424
host_tags?: {

src/ui/autocomplete.ts

Lines changed: 10 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,17 @@
1-
import { RequestSpec } from '../RequestSpec';
21
import { ContextHTTPVars } from '../types';
3-
import { createCmkContext } from '../utils';
42

53
type Context = Record<string, ContextHTTPVars>;
64

75
export type Presentation = 'lines' | 'sum' | 'average' | 'min' | 'max';
86

9-
interface AutoCompleteConfig {
10-
ident: string;
11-
value?: string;
12-
params: {
13-
group_id?: string;
14-
strict?: string | boolean;
15-
mode?: string;
16-
presentation?: Presentation;
17-
context?: Context;
18-
datasource?: string;
19-
single_infos?: string[];
20-
};
21-
}
22-
23-
export function createAutocompleteConfig(
24-
requestSpec: Partial<RequestSpec>,
25-
ident: string,
26-
value: string,
27-
params: Record<string, string | boolean>
28-
): AutoCompleteConfig {
29-
const context = createCmkContext(requestSpec) as Context;
30-
31-
return {
32-
ident,
33-
value,
34-
params: {
35-
...params,
36-
context,
37-
},
38-
};
7+
export interface AutoCompleteParams {
8+
group_id: string;
9+
strict: string | boolean;
10+
mode: string;
11+
presentation: Presentation;
12+
context: Context;
13+
datasource: string;
14+
single_infos: string[];
15+
world: string;
16+
group_type: string;
3917
}

src/utils.ts

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ export function contextEntryFromNegatableOption(option: NegatableOption, keyName
1515
return result;
1616
}
1717

18-
export function createCmkContext(requestSpec: Partial<RequestSpec>): Record<string, unknown> {
18+
export function createCmkContext(
19+
requestSpec: Partial<RequestSpec>,
20+
checkmkVersion: 'latest' | '2.1.0' = 'latest'
21+
): Record<string, unknown> {
1922
const context: Record<string, unknown> = {};
2023

2124
if (!isUndefined(requestSpec.site)) {
@@ -28,15 +31,34 @@ export function createCmkContext(requestSpec: Partial<RequestSpec>): Record<stri
2831
context['service'] = { service: requestSpec.service };
2932
}
3033
if (!isUndefined(requestSpec.host_labels) && requestSpec.host_labels.length !== 0) {
31-
context['host_labels'] = {
32-
host_label: JSON.stringify(
33-
requestSpec.host_labels.map((v: string) => {
34-
return {
35-
value: v,
36-
};
37-
})
38-
),
39-
};
34+
if (checkmkVersion === 'latest') {
35+
const count = requestSpec.host_labels.length;
36+
const hl: Record<string, string> = {
37+
host_labels_count: '1',
38+
host_labels_1_bool: 'and',
39+
host_labels_1_vs_count: `${count}`,
40+
};
41+
for (let i = 1; i < count + 1; i++) {
42+
const label = requestSpec.host_labels[i - 1];
43+
hl[`host_labels_1_vs_${i}_bool`] = 'and';
44+
if (label !== undefined) {
45+
hl[`host_labels_1_vs_${i}_vs`] = label;
46+
}
47+
}
48+
context['host_labels'] = hl;
49+
} else if (checkmkVersion === '2.1.0') {
50+
context['host_labels'] = {
51+
host_label: JSON.stringify(
52+
requestSpec.host_labels.map((v: string) => {
53+
return {
54+
value: v,
55+
};
56+
})
57+
),
58+
};
59+
} else {
60+
throw new Error(`checkmk version ${checkmkVersion} not known`);
61+
}
4062
}
4163

4264
if (!isUndefined(requestSpec.service_in_group) && requestSpec.service_in_group.value !== '') {

tests/unit/webapi.test.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Context, Params } from '../../src/types';
33
import { createCmkContext } from '../../src/utils';
44
import { requestSpecFromLegacy } from '../../src/webapi';
55

6+
// representation of the query in grafana plugin
67
const rs: RequestSpec = {
78
aggregation: 'off',
89
graph_type: 'single_metric',
@@ -21,18 +22,31 @@ const rs: RequestSpec = {
2122
service_in_group: { value: 'APT_Updates', negated: true },
2223
};
2324

25+
// filter query that is sent to checkmk for graph and autocompleters
2426
const context: Context = {
2527
host: { host: 'ut_hostname' },
2628
siteopt: { site: 'ut_site' },
2729
hostregex: { host_regex: 'ut_host_regex' },
2830
service: { service: 'Check_MK' },
2931
serviceregex: { service_regex: 'ut_service_regex' },
30-
host_labels: { host_label: '[{"value":"cmk/site:cmk210d"}]' },
32+
host_labels: {
33+
host_labels_1_bool: 'and',
34+
host_labels_1_vs_1_bool: 'and',
35+
host_labels_1_vs_1_vs: 'cmk/site:cmk210d',
36+
host_labels_1_vs_count: '1',
37+
host_labels_count: '1',
38+
},
3139
opthostgroup: { opthost_group: 'Drucker', neg_opthost_group: 'on' },
3240
optservicegroup: { optservice_group: 'APT_Updates', neg_optservice_group: 'on' },
3341
host_tags: { host_tag_0_grp: 'criticality', host_tag_0_op: 'is', host_tag_0_val: 'prod' },
3442
};
3543

44+
// filter query as it was persisted with version < 3.0.0
45+
const legacy_context: Context = {
46+
...context,
47+
host_labels: { host_label: '[{"value":"cmk/site:cmk210d"}]' },
48+
};
49+
3650
const params: Params = {
3751
presentation: 'lines',
3852
graphMode: 'metric',
@@ -55,6 +69,7 @@ const rs_graph: Partial<RequestSpec> = {
5569
host_in_group: undefined,
5670
};
5771

72+
// no differences between legacy_context and context for graphs, yet.
5873
const context_graph: Context = {
5974
host: { host: 'localhost' },
6075
service: { service: 'Check_MK' },
@@ -71,9 +86,10 @@ const params_graph: Params = {
7186
describe('requestspec transformation', () => {
7287
it('requestspec -> context', () => {
7388
expect(createCmkContext(rs)).toStrictEqual(context);
89+
expect(createCmkContext(rs, '2.1.0')).toStrictEqual(legacy_context);
7490
});
7591
it('legacyQuery -> requestspec', () => {
76-
expect(requestSpecFromLegacy(context, params)).toStrictEqual(rs);
92+
expect(requestSpecFromLegacy(legacy_context, params)).toStrictEqual(rs);
7793
});
7894
it('legacyQuery -> requestspec (simple graph)', () => {
7995
expect(requestSpecFromLegacy(context_graph, params_graph)).toStrictEqual(rs_graph);

0 commit comments

Comments
 (0)