[Alerts] Replaces legacy es client with the ElasticsearchClient for alerts and triggers_actions_ui plugins. (#93364)

* [Alerts] Replaces legasy es client with the ElasticsearchClient

* fixed build

* fixed build

* fixed ci build

* fixed ci build

* fixed infra callCLuster

* fixed infra callCLuster

* fixed infra callCLuster

* fixed ci build

* fixed ci build

* fixed ci build

* fixed infra tests

* fixed security tests

* fixed security tests

* fixed security tests

* fixed tests

* fixed monitoring unit tests

* fixed monitoring unit tests

* fixed type checks

* fixed type checks

* fixed type checks

* migrated lists plugin

* fixed type checks

* fixed tests

* fixed security tests

* fixed type checks

* fixed tests

* fixed type checks

* fixed tests

* fixed tests

* fixed tests

* fixed due to comments

* fixed tests

* fixed comment

* fixed tests

* fixed tests

* fixed searh

* fixed searh

* fixed test

* fixed due to comment

* fixed detections failing test and replaces scopedClusterClient exposure with IScopedClusterClient instead of ElasticsearchClient asCurrentUser

* fixed test

* fixed test

* fixed test

* fixed typecheck

* fixed typecheck

* fixed typecheck

* fixed merge
This commit is contained in:
Yuliia Naumenko 2021-03-16 12:03:24 -07:00 committed by GitHub
parent ec41ae3c49
commit 21587dc79e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
191 changed files with 2097 additions and 1347 deletions

View file

@ -116,9 +116,8 @@ This is the primary function for an alert type. Whenever the alert needs to exec
|Property|Description|
|---|---|
|services.callCluster(path, opts)|Use this to do Elasticsearch queries on the cluster Kibana connects to. This function is the same as any other `callCluster` in Kibana but in the context of the user who created the alert when security is enabled.|
|services.scopedClusterClient|This is an instance of the Elasticsearch client. Use this to do Elasticsearch queries in the context of the user who created the alert when security is enabled.|
|services.savedObjectsClient|This is an instance of the saved objects client. This provides the ability to do CRUD on any saved objects within the same space the alert lives in.<br><br>The scope of the saved objects client is tied to the user who created the alert (only when security isenabled).|
|services.getLegacyScopedClusterClient|This function returns an instance of the LegacyScopedClusterClient scoped to the user who created the alert when security is enabled.|
|services.alertInstanceFactory(id)|This [alert instance factory](#alert-instance-factory) creates instances of alerts and must be used in order to execute actions. The id you give to the alert instance factory is a unique identifier to the alert instance.|
|services.log(tags, [data], [timestamp])|Use this to create server logs. (This is the same function as server.log)|
|startedAt|The date and time the alert type started execution.|

View file

@ -70,10 +70,8 @@ const createAlertServicesMock = <
alertInstanceFactory: jest
.fn<jest.Mocked<AlertInstance<InstanceState, InstanceContext>>, [string]>()
.mockReturnValue(alertInstanceFactoryMock),
callCluster: elasticsearchServiceMock.createLegacyScopedClusterClient().callAsCurrentUser,
getLegacyScopedClusterClient: jest.fn(),
savedObjectsClient: savedObjectsClientMock.create(),
scopedClusterClient: elasticsearchServiceMock.createScopedClusterClient().asCurrentUser,
scopedClusterClient: elasticsearchServiceMock.createScopedClusterClient(),
};
};
export type AlertServicesMock = ReturnType<typeof createAlertServicesMock>;

View file

@ -31,7 +31,6 @@ import {
SavedObjectsServiceStart,
IContextProvider,
ElasticsearchServiceStart,
ILegacyClusterClient,
StatusServiceSetup,
ServiceStatus,
SavedObjectsBulkGetObject,
@ -420,12 +419,8 @@ export class AlertingPlugin {
elasticsearch: ElasticsearchServiceStart
): (request: KibanaRequest) => Services {
return (request) => ({
callCluster: elasticsearch.legacy.client.asScoped(request).callAsCurrentUser,
savedObjectsClient: this.getScopedClientWithAlertSavedObjectType(savedObjects, request),
scopedClusterClient: elasticsearch.client.asScoped(request).asCurrentUser,
getLegacyScopedClusterClient(clusterClient: ILegacyClusterClient) {
return clusterClient.asScoped(request);
},
scopedClusterClient: elasticsearch.client.asScoped(request),
});
}

View file

@ -5,9 +5,11 @@
* 2.0.
*/
import { KibanaRequest, KibanaResponseFactory, ILegacyClusterClient } from 'kibana/server';
import { KibanaRequest, KibanaResponseFactory } from 'kibana/server';
import { identity } from 'lodash';
import type { MethodKeysOf } from '@kbn/utility-types';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { ScopedClusterClientMock } from '../../../../../src/core/server/elasticsearch/client/mocks';
import { httpServerMock } from '../../../../../src/core/server/mocks';
import { alertsClientMock, AlertsClientMock } from '../alerts_client.mock';
import { AlertsHealth, AlertType } from '../../common';
@ -18,12 +20,12 @@ export function mockHandlerArguments(
{
alertsClient = alertsClientMock.create(),
listTypes: listTypesRes = [],
esClient = elasticsearchServiceMock.createLegacyClusterClient(),
esClient = elasticsearchServiceMock.createScopedClusterClient(),
getFrameworkHealth,
}: {
alertsClient?: AlertsClientMock;
listTypes?: AlertType[];
esClient?: jest.Mocked<ILegacyClusterClient>;
esClient?: jest.Mocked<ScopedClusterClientMock>;
getFrameworkHealth?: jest.MockInstance<Promise<AlertsHealth>, []> &
(() => Promise<AlertsHealth>);
},
@ -37,7 +39,7 @@ export function mockHandlerArguments(
const listTypes = jest.fn(() => listTypesRes);
return [
({
core: { elasticsearch: { legacy: { client: esClient } } },
core: { elasticsearch: { client: esClient } },
alerting: {
listTypes,
getAlertsClient() {

View file

@ -15,6 +15,8 @@ import { encryptedSavedObjectsMock } from '../../../encrypted_saved_objects/serv
import { alertsClientMock } from '../alerts_client.mock';
import { HealthStatus } from '../types';
import { alertsMock } from '../mocks';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from '../../../../../src/core/server/elasticsearch/client/mocks';
const alertsClient = alertsClientMock.create();
jest.mock('../lib/license_api_access.ts', () => ({
@ -63,8 +65,10 @@ describe('healthRoute', () => {
healthRoute(router, licenseState, encryptedSavedObjects);
const [, handler] = router.get.mock.calls[0];
const esClient = elasticsearchServiceMock.createLegacyClusterClient();
esClient.callAsInternalUser.mockReturnValue(Promise.resolve({}));
const esClient = elasticsearchServiceMock.createScopedClusterClient();
esClient.asInternalUser.transport.request.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise({})
);
const [context, req, res] = mockHandlerArguments({ esClient, alertsClient }, {}, ['ok']);
@ -72,9 +76,8 @@ describe('healthRoute', () => {
expect(verifyApiAccess).toHaveBeenCalledWith(licenseState);
expect(esClient.callAsInternalUser.mock.calls[0]).toMatchInlineSnapshot(`
expect(esClient.asInternalUser.transport.request.mock.calls[0]).toMatchInlineSnapshot(`
Array [
"transport.request",
Object {
"method": "GET",
"path": "/_xpack/usage",
@ -91,8 +94,10 @@ describe('healthRoute', () => {
healthRoute(router, licenseState, encryptedSavedObjects);
const [, handler] = router.get.mock.calls[0];
const esClient = elasticsearchServiceMock.createLegacyClusterClient();
esClient.callAsInternalUser.mockReturnValue(Promise.resolve({}));
const esClient = elasticsearchServiceMock.createScopedClusterClient();
esClient.asInternalUser.transport.request.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise({})
);
const [context, req, res] = mockHandlerArguments(
{ esClient, alertsClient, getFrameworkHealth: alerting.getFrameworkHealth },
@ -130,8 +135,10 @@ describe('healthRoute', () => {
healthRoute(router, licenseState, encryptedSavedObjects);
const [, handler] = router.get.mock.calls[0];
const esClient = elasticsearchServiceMock.createLegacyClusterClient();
esClient.callAsInternalUser.mockReturnValue(Promise.resolve({}));
const esClient = elasticsearchServiceMock.createScopedClusterClient();
esClient.asInternalUser.transport.request.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise({})
);
const [context, req, res] = mockHandlerArguments(
{ esClient, alertsClient, getFrameworkHealth: alerting.getFrameworkHealth },
@ -169,8 +176,10 @@ describe('healthRoute', () => {
healthRoute(router, licenseState, encryptedSavedObjects);
const [, handler] = router.get.mock.calls[0];
const esClient = elasticsearchServiceMock.createLegacyClusterClient();
esClient.callAsInternalUser.mockReturnValue(Promise.resolve({ security: {} }));
const esClient = elasticsearchServiceMock.createScopedClusterClient();
esClient.asInternalUser.transport.request.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise({ security: {} })
);
const [context, req, res] = mockHandlerArguments(
{ esClient, alertsClient, getFrameworkHealth: alerting.getFrameworkHealth },
@ -208,8 +217,10 @@ describe('healthRoute', () => {
healthRoute(router, licenseState, encryptedSavedObjects);
const [, handler] = router.get.mock.calls[0];
const esClient = elasticsearchServiceMock.createLegacyClusterClient();
esClient.callAsInternalUser.mockReturnValue(Promise.resolve({ security: { enabled: true } }));
const esClient = elasticsearchServiceMock.createScopedClusterClient();
esClient.asInternalUser.transport.request.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise({ security: { enabled: true } })
);
const [context, req, res] = mockHandlerArguments(
{ esClient, alertsClient, getFrameworkHealth: alerting.getFrameworkHealth },
@ -247,9 +258,11 @@ describe('healthRoute', () => {
healthRoute(router, licenseState, encryptedSavedObjects);
const [, handler] = router.get.mock.calls[0];
const esClient = elasticsearchServiceMock.createLegacyClusterClient();
esClient.callAsInternalUser.mockReturnValue(
Promise.resolve({ security: { enabled: true, ssl: {} } })
const esClient = elasticsearchServiceMock.createScopedClusterClient();
esClient.asInternalUser.transport.request.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise({
security: { enabled: true, ssl: {} },
})
);
const [context, req, res] = mockHandlerArguments(
@ -288,9 +301,11 @@ describe('healthRoute', () => {
healthRoute(router, licenseState, encryptedSavedObjects);
const [, handler] = router.get.mock.calls[0];
const esClient = elasticsearchServiceMock.createLegacyClusterClient();
esClient.callAsInternalUser.mockReturnValue(
Promise.resolve({ security: { enabled: true, ssl: { http: { enabled: true } } } })
const esClient = elasticsearchServiceMock.createScopedClusterClient();
esClient.asInternalUser.transport.request.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise({
security: { enabled: true, ssl: { http: { enabled: true } } },
})
);
const [context, req, res] = mockHandlerArguments(

View file

@ -5,6 +5,7 @@
* 2.0.
*/
import { ApiResponse } from '@elastic/elasticsearch';
import type { AlertingRouter } from '../types';
import { ILicenseState } from '../lib/license_state';
import { verifyApiAccess } from '../lib/license_api_access';
@ -39,14 +40,14 @@ export function healthRoute(
}
try {
const {
security: {
enabled: isSecurityEnabled = false,
ssl: { http: { enabled: isTLSEnabled = false } = {} } = {},
} = {},
}: XPackUsageSecurity = await context.core.elasticsearch.legacy.client
// `transport.request` is potentially unsafe when combined with untrusted user input.
// Do not augment with such input.
.callAsInternalUser('transport.request', {
body: {
security: {
enabled: isSecurityEnabled = false,
ssl: { http: { enabled: isTLSEnabled = false } = {} } = {},
} = {},
},
}: ApiResponse<XPackUsageSecurity> = await context.core.elasticsearch.client.asInternalUser.transport // Do not augment with such input. // `transport.request` is potentially unsafe when combined with untrusted user input.
.request({
method: 'GET',
path: '/_xpack/usage',
});

View file

@ -206,7 +206,7 @@ describe('Task Runner', () => {
expect(call.createdBy).toBe('alert-creator');
expect(call.updatedBy).toBe('alert-updater');
expect(call.services.alertInstanceFactory).toBeTruthy();
expect(call.services.callCluster).toBeTruthy();
expect(call.services.scopedClusterClient).toBeTruthy();
expect(call.services).toBeTruthy();
const logger = taskRunnerFactoryInitializerParams.logger;

View file

@ -13,9 +13,7 @@ import { PluginSetupContract, PluginStartContract } from './plugin';
import { AlertsClient } from './alerts_client';
export * from '../common';
import {
ElasticsearchClient,
ILegacyClusterClient,
ILegacyScopedClusterClient,
IScopedClusterClient,
KibanaRequest,
SavedObjectAttributes,
SavedObjectsClientContract,
@ -63,13 +61,8 @@ export interface AlertingRequestHandlerContext extends RequestHandlerContext {
export type AlertingRouter = IRouter<AlertingRequestHandlerContext>;
export interface Services {
/**
* @deprecated Use `scopedClusterClient` instead.
*/
callCluster: ILegacyScopedClusterClient['callAsCurrentUser'];
savedObjectsClient: SavedObjectsClientContract;
scopedClusterClient: ElasticsearchClient;
getLegacyScopedClusterClient(clusterClient: ILegacyClusterClient): ILegacyScopedClusterClient;
scopedClusterClient: IScopedClusterClient;
}
export interface AlertServices<

View file

@ -5,27 +5,31 @@
* 2.0.
*/
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from '../../../../../src/core/server/elasticsearch/client/mocks';
import { getTotalCountInUse } from './alerts_telemetry';
describe('alerts telemetry', () => {
test('getTotalCountInUse should replace first "." symbol to "__" in alert types names', async () => {
const mockEsClient = jest.fn();
mockEsClient.mockReturnValue({
aggregations: {
byAlertTypeId: {
value: {
types: { '.index-threshold': 2, 'logs.alert.document.count': 1, 'document.test.': 1 },
const mockEsClient = elasticsearchClientMock.createClusterClient().asScoped().asInternalUser;
mockEsClient.search.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise({
aggregations: {
byAlertTypeId: {
value: {
types: { '.index-threshold': 2, 'logs.alert.document.count': 1, 'document.test.': 1 },
},
},
},
},
hits: {
hits: [],
},
});
hits: {
hits: [],
},
})
);
const telemetry = await getTotalCountInUse(mockEsClient, 'test');
expect(mockEsClient).toHaveBeenCalledTimes(1);
expect(mockEsClient.search).toHaveBeenCalledTimes(1);
expect(telemetry).toMatchInlineSnapshot(`
Object {

View file

@ -5,8 +5,7 @@
* 2.0.
*/
import { LegacyAPICaller } from 'kibana/server';
import { SearchResponse } from 'elasticsearch';
import { ElasticsearchClient } from 'kibana/server';
import { AlertsUsage } from './types';
const alertTypeMetric = {
@ -36,7 +35,7 @@ const alertTypeMetric = {
};
export async function getTotalCountAggregations(
callCluster: LegacyAPICaller,
esClient: ElasticsearchClient,
kibanaInex: string
): Promise<
Pick<
@ -223,7 +222,7 @@ export async function getTotalCountAggregations(
},
};
const results = await callCluster('search', {
const { body: results } = await esClient.search({
index: kibanaInex,
body: {
query: {
@ -256,7 +255,7 @@ export async function getTotalCountAggregations(
return {
count_total: totalAlertsCount,
count_by_type: Object.keys(results.aggregations.byAlertTypeId.value.types).reduce(
// ES DSL aggregations are returned as `any` by callCluster
// ES DSL aggregations are returned as `any` by esClient.search
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(obj: any, key: string) => ({
...obj,
@ -295,8 +294,8 @@ export async function getTotalCountAggregations(
};
}
export async function getTotalCountInUse(callCluster: LegacyAPICaller, kibanaInex: string) {
const searchResult: SearchResponse<unknown> = await callCluster('search', {
export async function getTotalCountInUse(esClient: ElasticsearchClient, kibanaInex: string) {
const { body: searchResult } = await esClient.search({
index: kibanaInex,
body: {
query: {
@ -316,7 +315,7 @@ export async function getTotalCountInUse(callCluster: LegacyAPICaller, kibanaIne
0
),
countByType: Object.keys(searchResult.aggregations.byAlertTypeId.value.types).reduce(
// ES DSL aggregations are returned as `any` by callCluster
// ES DSL aggregations are returned as `any` by esClient.search
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(obj: any, key: string) => ({
...obj,

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import { Logger, CoreSetup, LegacyAPICaller } from 'kibana/server';
import { Logger, CoreSetup } from 'kibana/server';
import moment from 'moment';
import {
RunContext,
@ -65,17 +65,21 @@ async function scheduleTasks(logger: Logger, taskManager: TaskManagerStartContra
export function telemetryTaskRunner(logger: Logger, core: CoreSetup, kibanaIndex: string) {
return ({ taskInstance }: RunContext) => {
const { state } = taskInstance;
const callCluster = (...args: Parameters<LegacyAPICaller>) => {
return core.getStartServices().then(([{ elasticsearch: { legacy: { client } } }]) =>
client.callAsInternalUser(...args)
const getEsClient = () =>
core.getStartServices().then(
([
{
elasticsearch: { client },
},
]) => client.asInternalUser
);
};
return {
async run() {
const esClient = await getEsClient();
return Promise.all([
getTotalCountAggregations(callCluster, kibanaIndex),
getTotalCountInUse(callCluster, kibanaIndex),
getTotalCountAggregations(esClient, kibanaIndex),
getTotalCountInUse(esClient, kibanaIndex),
])
.then(([totalCountAggregations, totalInUse]) => {
return {

View file

@ -5,6 +5,7 @@
* 2.0.
*/
import { ApiResponse } from '@elastic/elasticsearch';
import { ThresholdMetActionGroupId } from '../../../common/alert_types';
import {
ESSearchRequest,
@ -23,8 +24,8 @@ export function alertingEsClient<TParams extends ESSearchRequest>(
ThresholdMetActionGroupId
>,
params: TParams
): Promise<ESSearchResponse<unknown, TParams>> {
return services.callCluster('search', {
): Promise<ApiResponse<ESSearchResponse<unknown, TParams>>> {
return services.scopedClusterClient.asCurrentUser.search({
...params,
ignore_unavailable: true,
});

View file

@ -13,6 +13,9 @@ import { AlertingPlugin } from '../../../../alerting/server';
import { APMConfig } from '../..';
import { registerErrorCountAlertType } from './register_error_count_alert_type';
import { elasticsearchServiceMock } from 'src/core/server/mocks';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks';
type Operator<T1, T2> = (source: Rx.Observable<T1>) => Rx.Observable<T2>;
const pipeClosure = <T1, T2>(fn: Operator<T1, T2>): Operator<T1, T2> => {
@ -43,16 +46,20 @@ describe('Error count alert', () => {
expect(alertExecutor).toBeDefined();
const services = {
callCluster: jest.fn(() => ({
scopedClusterClient: elasticsearchServiceMock.createScopedClusterClient(),
alertInstanceFactory: jest.fn(),
};
const params = { threshold: 1 };
services.scopedClusterClient.asCurrentUser.search.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise({
hits: {
total: {
value: 0,
},
},
})),
alertInstanceFactory: jest.fn(),
};
const params = { threshold: 1 };
})
);
await alertExecutor!({ services, params });
expect(services.alertInstanceFactory).not.toBeCalled();
@ -74,7 +81,13 @@ describe('Error count alert', () => {
const scheduleActions = jest.fn();
const services = {
callCluster: jest.fn(() => ({
scopedClusterClient: elasticsearchServiceMock.createScopedClusterClient(),
alertInstanceFactory: jest.fn(() => ({ scheduleActions })),
};
const params = { threshold: 1, windowSize: 5, windowUnit: 'm' };
services.scopedClusterClient.asCurrentUser.search.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise({
hits: {
total: {
value: 2,
@ -98,10 +111,8 @@ describe('Error count alert', () => {
],
},
},
})),
alertInstanceFactory: jest.fn(() => ({ scheduleActions })),
};
const params = { threshold: 1, windowSize: 5, windowUnit: 'm' };
})
);
await alertExecutor!({ services, params });
[
@ -158,7 +169,13 @@ describe('Error count alert', () => {
const scheduleActions = jest.fn();
const services = {
callCluster: jest.fn(() => ({
scopedClusterClient: elasticsearchServiceMock.createScopedClusterClient(),
alertInstanceFactory: jest.fn(() => ({ scheduleActions })),
};
const params = { threshold: 1, windowSize: 5, windowUnit: 'm' };
services.scopedClusterClient.asCurrentUser.search.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise({
hits: {
total: {
value: 2,
@ -176,10 +193,8 @@ describe('Error count alert', () => {
],
},
},
})),
alertInstanceFactory: jest.fn(() => ({ scheduleActions })),
};
const params = { threshold: 1, windowSize: 5, windowUnit: 'm' };
})
);
await alertExecutor!({ services, params });
['apm.error_rate_foo', 'apm.error_rate_bar'].forEach((instanceName) =>

View file

@ -127,7 +127,7 @@ export function registerErrorCountAlertType({
},
};
const response = await alertingEsClient(services, searchParams);
const { body: response } = await alertingEsClient(services, searchParams);
const errorCount = response.hits.total.value;
if (errorCount > alertParams.threshold) {

View file

@ -122,7 +122,7 @@ export function registerTransactionDurationAlertType({
},
};
const response = await alertingEsClient(services, searchParams);
const { body: response } = await alertingEsClient(services, searchParams);
if (!response.aggregations) {
return;

View file

@ -11,6 +11,9 @@ import { toArray, map } from 'rxjs/operators';
import { AlertingPlugin } from '../../../../alerting/server';
import { APMConfig } from '../..';
import { registerTransactionErrorRateAlertType } from './register_transaction_error_rate_alert_type';
import { elasticsearchServiceMock } from 'src/core/server/mocks';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks';
type Operator<T1, T2> = (source: Rx.Observable<T1>) => Rx.Observable<T2>;
const pipeClosure = <T1, T2>(fn: Operator<T1, T2>): Operator<T1, T2> => {
@ -41,16 +44,20 @@ describe('Transaction error rate alert', () => {
expect(alertExecutor).toBeDefined();
const services = {
callCluster: jest.fn(() => ({
scopedClusterClient: elasticsearchServiceMock.createScopedClusterClient(),
alertInstanceFactory: jest.fn(),
};
const params = { threshold: 1 };
services.scopedClusterClient.asCurrentUser.search.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise({
hits: {
total: {
value: 0,
},
},
})),
alertInstanceFactory: jest.fn(),
};
const params = { threshold: 1 };
})
);
await alertExecutor!({ services, params });
expect(services.alertInstanceFactory).not.toBeCalled();
@ -72,7 +79,13 @@ describe('Transaction error rate alert', () => {
const scheduleActions = jest.fn();
const services = {
callCluster: jest.fn(() => ({
scopedClusterClient: elasticsearchServiceMock.createScopedClusterClient(),
alertInstanceFactory: jest.fn(() => ({ scheduleActions })),
};
const params = { threshold: 10, windowSize: 5, windowUnit: 'm' };
services.scopedClusterClient.asCurrentUser.search.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise({
hits: {
total: {
value: 4,
@ -113,10 +126,8 @@ describe('Transaction error rate alert', () => {
],
},
},
})),
alertInstanceFactory: jest.fn(() => ({ scheduleActions })),
};
const params = { threshold: 10, windowSize: 5, windowUnit: 'm' };
})
);
await alertExecutor!({ services, params });
[
@ -177,7 +188,13 @@ describe('Transaction error rate alert', () => {
const scheduleActions = jest.fn();
const services = {
callCluster: jest.fn(() => ({
scopedClusterClient: elasticsearchServiceMock.createScopedClusterClient(),
alertInstanceFactory: jest.fn(() => ({ scheduleActions })),
};
const params = { threshold: 10, windowSize: 5, windowUnit: 'm' };
services.scopedClusterClient.asCurrentUser.search.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise({
hits: {
total: {
value: 4,
@ -204,10 +221,8 @@ describe('Transaction error rate alert', () => {
],
},
},
})),
alertInstanceFactory: jest.fn(() => ({ scheduleActions })),
};
const params = { threshold: 10, windowSize: 5, windowUnit: 'm' };
})
);
await alertExecutor!({ services, params });
[
@ -251,7 +266,13 @@ describe('Transaction error rate alert', () => {
const scheduleActions = jest.fn();
const services = {
callCluster: jest.fn(() => ({
scopedClusterClient: elasticsearchServiceMock.createScopedClusterClient(),
alertInstanceFactory: jest.fn(() => ({ scheduleActions })),
};
const params = { threshold: 10, windowSize: 5, windowUnit: 'm' };
services.scopedClusterClient.asCurrentUser.search.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise({
hits: {
total: {
value: 4,
@ -265,10 +286,8 @@ describe('Transaction error rate alert', () => {
buckets: [{ key: 'foo' }, { key: 'bar' }],
},
},
})),
alertInstanceFactory: jest.fn(() => ({ scheduleActions })),
};
const params = { threshold: 10, windowSize: 5, windowUnit: 'm' };
})
);
await alertExecutor!({ services, params });
[

View file

@ -134,7 +134,7 @@ export function registerTransactionErrorRateAlertType({
},
};
const response = await alertingEsClient(services, searchParams);
const { body: response } = await alertingEsClient(services, searchParams);
if (!response.aggregations) {
return;
}

View file

@ -5,6 +5,13 @@
* 2.0.
*/
import {
IndicesExistsAlias,
IndicesGet,
MlGetBuckets,
Msearch,
} from '@elastic/elasticsearch/api/requestParams';
import { TransportRequestParams } from '@elastic/elasticsearch/lib/Transport';
import {
InfraRouteConfig,
InfraTSVBResponse,
@ -134,10 +141,58 @@ export class KibanaFramework {
}
: {};
return elasticsearch.legacy.client.callAsCurrentUser(endpoint, {
...params,
...frozenIndicesParams,
});
let apiResult;
switch (endpoint) {
case 'search':
apiResult = elasticsearch.client.asCurrentUser.search({
...params,
...frozenIndicesParams,
});
break;
case 'msearch':
apiResult = elasticsearch.client.asCurrentUser.msearch({
...params,
...frozenIndicesParams,
} as Msearch<any>);
break;
case 'fieldCaps':
apiResult = elasticsearch.client.asCurrentUser.fieldCaps({
...params,
...frozenIndicesParams,
});
break;
case 'indices.existsAlias':
apiResult = elasticsearch.client.asCurrentUser.indices.existsAlias({
...params,
...frozenIndicesParams,
} as IndicesExistsAlias);
break;
case 'indices.getAlias':
apiResult = elasticsearch.client.asCurrentUser.indices.getAlias({
...params,
...frozenIndicesParams,
});
break;
case 'indices.get':
apiResult = elasticsearch.client.asCurrentUser.indices.get({
...params,
...frozenIndicesParams,
} as IndicesGet);
break;
case 'transport.request':
apiResult = elasticsearch.client.asCurrentUser.transport.request({
...params,
...frozenIndicesParams,
} as TransportRequestParams);
break;
case 'ml.getBuckets':
apiResult = elasticsearch.client.asCurrentUser.ml.getBuckets({
...params,
...frozenIndicesParams,
} as MlGetBuckets<any>);
break;
}
return apiResult ? (await apiResult).body : undefined;
}
public getIndexPatternsService(

View file

@ -7,6 +7,7 @@
import { mapValues, last, first } from 'lodash';
import moment from 'moment';
import { ElasticsearchClient } from 'kibana/server';
import { SnapshotCustomMetricInput } from '../../../../common/http_api/snapshot_api';
import {
isTooManyBucketsPreviewException,
@ -17,7 +18,6 @@ import {
CallWithRequestParams,
} from '../../adapters/framework/adapter_types';
import { Comparator, InventoryMetricConditions } from './types';
import { AlertServices } from '../../../../../alerting/server';
import { InventoryItemType, SnapshotMetricType } from '../../../../common/inventory_models/types';
import { InfraTimerangeInput, SnapshotRequest } from '../../../../common/http_api/snapshot_api';
import { InfraSource } from '../../sources';
@ -36,7 +36,7 @@ export const evaluateCondition = async (
condition: InventoryMetricConditions,
nodeType: InventoryItemType,
source: InfraSource,
callCluster: AlertServices['callCluster'],
esClient: ElasticsearchClient,
filterQuery?: string,
lookbackSize?: number
): Promise<Record<string, ConditionResult>> => {
@ -53,7 +53,7 @@ export const evaluateCondition = async (
}
const currentValues = await getData(
callCluster,
esClient,
nodeType,
metric,
timerange,
@ -96,7 +96,7 @@ const getCurrentValue: (value: any) => number = (value) => {
type DataValue = number | null | Array<number | string | null | undefined>;
const getData = async (
callCluster: AlertServices['callCluster'],
esClient: ElasticsearchClient,
nodeType: InventoryItemType,
metric: SnapshotMetricType,
timerange: InfraTimerangeInput,
@ -104,9 +104,10 @@ const getData = async (
filterQuery?: string,
customMetric?: SnapshotCustomMetricInput
) => {
const client = <Hit = {}, Aggregation = undefined>(
const client = async <Hit = {}, Aggregation = undefined>(
options: CallWithRequestParams
): Promise<InfraDatabaseSearchResponse<Hit, Aggregation>> => callCluster('search', options);
): Promise<InfraDatabaseSearchResponse<Hit, Aggregation>> =>
(await esClient.search(options)).body as InfraDatabaseSearchResponse<Hit, Aggregation>;
const metrics = [
metric === 'custom' ? (customMetric as SnapshotCustomMetricInput) : { type: metric },

View file

@ -69,7 +69,15 @@ export const createInventoryMetricThresholdExecutor = (libs: InfraBackendLibs) =
);
const results = await Promise.all(
criteria.map((c) => evaluateCondition(c, nodeType, source, services.callCluster, filterQuery))
criteria.map((c) =>
evaluateCondition(
c,
nodeType,
source,
services.scopedClusterClient.asCurrentUser,
filterQuery
)
)
);
const inventoryItems = Object.keys(first(results)!);

View file

@ -13,7 +13,7 @@ import {
TOO_MANY_BUCKETS_PREVIEW_EXCEPTION,
isTooManyBucketsPreviewException,
} from '../../../../common/alerting/metrics';
import { ILegacyScopedClusterClient } from '../../../../../../../src/core/server';
import { ElasticsearchClient } from '../../../../../../../src/core/server';
import { InfraSource } from '../../../../common/http_api/source_api';
import { getIntervalInSeconds } from '../../../utils/get_interval_in_seconds';
import { InventoryItemType } from '../../../../common/inventory_models/types';
@ -27,7 +27,7 @@ interface InventoryMetricThresholdParams {
}
interface PreviewInventoryMetricThresholdAlertParams {
callCluster: ILegacyScopedClusterClient['callAsCurrentUser'];
esClient: ElasticsearchClient;
params: InventoryMetricThresholdParams;
source: InfraSource;
lookback: Unit;
@ -40,7 +40,7 @@ interface PreviewInventoryMetricThresholdAlertParams {
export const previewInventoryMetricThresholdAlert: (
params: PreviewInventoryMetricThresholdAlertParams
) => Promise<PreviewResult[]> = async ({
callCluster,
esClient,
params,
source,
lookback,
@ -68,7 +68,7 @@ export const previewInventoryMetricThresholdAlert: (
try {
const results = await Promise.all(
criteria.map((c) =>
evaluateCondition(c, nodeType, source, callCluster, filterQuery, lookbackSize)
evaluateCondition(c, nodeType, source, esClient, filterQuery, lookbackSize)
)
);

View file

@ -6,6 +6,7 @@
*/
import { i18n } from '@kbn/i18n';
import { ElasticsearchClient } from 'kibana/server';
import {
AlertExecutorOptions,
AlertServices,
@ -67,7 +68,7 @@ const checkValueAgainstComparatorMap: {
export const createLogThresholdExecutor = (libs: InfraBackendLibs) =>
async function ({ services, params }: LogThresholdAlertExecutorOptions) {
const { alertInstanceFactory, savedObjectsClient, callCluster } = services;
const { alertInstanceFactory, savedObjectsClient, scopedClusterClient } = services;
const { sources } = libs;
const sourceConfiguration = await sources.getSourceConfiguration(savedObjectsClient, 'default');
@ -82,7 +83,7 @@ export const createLogThresholdExecutor = (libs: InfraBackendLibs) =>
validatedParams,
timestampField,
indexPattern,
callCluster,
scopedClusterClient.asCurrentUser,
alertInstanceFactory
);
} else {
@ -90,7 +91,7 @@ export const createLogThresholdExecutor = (libs: InfraBackendLibs) =>
validatedParams,
timestampField,
indexPattern,
callCluster,
scopedClusterClient.asCurrentUser,
alertInstanceFactory
);
}
@ -103,7 +104,7 @@ async function executeAlert(
alertParams: CountAlertParams,
timestampField: string,
indexPattern: string,
callCluster: LogThresholdAlertServices['callCluster'],
esClient: ElasticsearchClient,
alertInstanceFactory: LogThresholdAlertServices['alertInstanceFactory']
) {
const query = getESQuery(alertParams, timestampField, indexPattern);
@ -114,14 +115,14 @@ async function executeAlert(
if (hasGroupBy(alertParams)) {
processGroupByResults(
await getGroupedResults(query, callCluster),
await getGroupedResults(query, esClient),
alertParams,
alertInstanceFactory,
updateAlertInstance
);
} else {
processUngroupedResults(
await getUngroupedResults(query, callCluster),
await getUngroupedResults(query, esClient),
alertParams,
alertInstanceFactory,
updateAlertInstance
@ -133,7 +134,7 @@ async function executeRatioAlert(
alertParams: RatioAlertParams,
timestampField: string,
indexPattern: string,
callCluster: LogThresholdAlertServices['callCluster'],
esClient: ElasticsearchClient,
alertInstanceFactory: LogThresholdAlertServices['alertInstanceFactory']
) {
// Ratio alert params are separated out into two standard sets of alert params
@ -155,8 +156,8 @@ async function executeRatioAlert(
}
if (hasGroupBy(alertParams)) {
const numeratorGroupedResults = await getGroupedResults(numeratorQuery, callCluster);
const denominatorGroupedResults = await getGroupedResults(denominatorQuery, callCluster);
const numeratorGroupedResults = await getGroupedResults(numeratorQuery, esClient);
const denominatorGroupedResults = await getGroupedResults(denominatorQuery, esClient);
processGroupByRatioResults(
numeratorGroupedResults,
denominatorGroupedResults,
@ -165,8 +166,8 @@ async function executeRatioAlert(
updateAlertInstance
);
} else {
const numeratorUngroupedResults = await getUngroupedResults(numeratorQuery, callCluster);
const denominatorUngroupedResults = await getUngroupedResults(denominatorQuery, callCluster);
const numeratorUngroupedResults = await getUngroupedResults(numeratorQuery, esClient);
const denominatorUngroupedResults = await getUngroupedResults(denominatorQuery, esClient);
processUngroupedRatioResults(
numeratorUngroupedResults,
denominatorUngroupedResults,
@ -605,17 +606,11 @@ const getQueryMappingForComparator = (comparator: Comparator) => {
return queryMappings[comparator];
};
const getUngroupedResults = async (
query: object,
callCluster: LogThresholdAlertServices['callCluster']
) => {
return decodeOrThrow(UngroupedSearchQueryResponseRT)(await callCluster('search', query));
const getUngroupedResults = async (query: object, esClient: ElasticsearchClient) => {
return decodeOrThrow(UngroupedSearchQueryResponseRT)((await esClient.search(query)).body);
};
const getGroupedResults = async (
query: object,
callCluster: LogThresholdAlertServices['callCluster']
) => {
const getGroupedResults = async (query: object, esClient: ElasticsearchClient) => {
let compositeGroupBuckets: GroupedSearchQueryResponse['aggregations']['groups']['buckets'] = [];
let lastAfterKey: GroupedSearchQueryResponse['aggregations']['groups']['after_key'] | undefined;
@ -623,7 +618,7 @@ const getGroupedResults = async (
const queryWithAfterKey: any = { ...query };
queryWithAfterKey.body.aggregations.groups.composite.after = lastAfterKey;
const groupResponse: GroupedSearchQueryResponse = decodeOrThrow(GroupedSearchQueryResponseRT)(
await callCluster('search', queryWithAfterKey)
(await esClient.search(queryWithAfterKey)).body
);
compositeGroupBuckets = [
...compositeGroupBuckets,

View file

@ -6,6 +6,7 @@
*/
import { mapValues, first, last, isNaN } from 'lodash';
import { ElasticsearchClient } from 'kibana/server';
import {
isTooManyBucketsPreviewException,
TOO_MANY_BUCKETS_PREVIEW_EXCEPTION,
@ -13,7 +14,6 @@ import {
import { InfraSource } from '../../../../../common/http_api/source_api';
import { InfraDatabaseSearchResponse } from '../../../adapters/framework/adapter_types';
import { createAfterKeyHandler } from '../../../../utils/create_afterkey_handler';
import { AlertServices } from '../../../../../../alerting/server';
import { getAllCompositeData } from '../../../../utils/get_all_composite_data';
import { DOCUMENT_COUNT_I18N } from '../../common/messages';
import { UNGROUPED_FACTORY_KEY } from '../../common/utils';
@ -43,7 +43,7 @@ export interface EvaluatedAlertParams {
}
export const evaluateAlert = <Params extends EvaluatedAlertParams = EvaluatedAlertParams>(
callCluster: AlertServices['callCluster'],
esClient: ElasticsearchClient,
params: Params,
config: InfraSource['configuration'],
timeframe?: { start: number; end: number }
@ -52,7 +52,7 @@ export const evaluateAlert = <Params extends EvaluatedAlertParams = EvaluatedAle
return Promise.all(
criteria.map(async (criterion) => {
const currentValues = await getMetric(
callCluster,
esClient,
criterion,
config.metricAlias,
config.fields.timestamp,
@ -91,7 +91,7 @@ export const evaluateAlert = <Params extends EvaluatedAlertParams = EvaluatedAle
};
const getMetric: (
callCluster: AlertServices['callCluster'],
esClient: ElasticsearchClient,
params: MetricExpressionParams,
index: string,
timefield: string,
@ -99,7 +99,7 @@ const getMetric: (
filterQuery: string | undefined,
timeframe?: { start: number; end: number }
) => Promise<Record<string, number[]>> = async function (
callCluster,
esClient,
params,
index,
timefield,
@ -127,7 +127,7 @@ const getMetric: (
(response) => response.aggregations?.groupings?.after_key
);
const compositeBuckets = (await getAllCompositeData(
(body) => callCluster('search', { body, index }),
(body) => esClient.search({ body, index }),
searchBody,
bucketSelector,
afterKeyHandler
@ -142,7 +142,7 @@ const getMetric: (
{}
);
}
const result = await callCluster('search', {
const { body: result } = await esClient.search({
body: searchBody,
index,
});

View file

@ -16,6 +16,8 @@ import {
} from '../../../../../alerting/server/mocks';
import { InfraSources } from '../../sources';
import { MetricThresholdAlertExecutorOptions } from './register_metric_threshold_alert_type';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks';
interface AlertTestInstance {
instance: AlertInstanceMock;
@ -439,26 +441,36 @@ const mockLibs: any = {
const executor = createMetricThresholdExecutor(mockLibs);
const services: AlertServicesMock = alertsMock.createAlertServices();
services.callCluster.mockImplementation(async (_: string, { body, index }: any) => {
if (index === 'alternatebeat-*') return mocks.changedSourceIdResponse;
const metric = body.query.bool.filter[1]?.exists.field;
if (body.aggs.groupings) {
if (body.aggs.groupings.composite.after) {
return mocks.compositeEndResponse;
services.scopedClusterClient.asCurrentUser.search.mockImplementation((params?: any): any => {
if (params.index === 'alternatebeat-*') return mocks.changedSourceIdResponse;
const metric = params?.body.query.bool.filter[1]?.exists.field;
if (params?.body.aggs.groupings) {
if (params?.body.aggs.groupings.composite.after) {
return elasticsearchClientMock.createSuccessTransportRequestPromise(
mocks.compositeEndResponse
);
}
if (metric === 'test.metric.2') {
return mocks.alternateCompositeResponse;
return elasticsearchClientMock.createSuccessTransportRequestPromise(
mocks.alternateCompositeResponse
);
}
return mocks.basicCompositeResponse;
return elasticsearchClientMock.createSuccessTransportRequestPromise(
mocks.basicCompositeResponse
);
}
if (metric === 'test.metric.2') {
return mocks.alternateMetricResponse;
return elasticsearchClientMock.createSuccessTransportRequestPromise(
mocks.alternateMetricResponse
);
} else if (metric === 'test.metric.3') {
return body.aggs.aggregatedIntervals.aggregations.aggregatedValue_max
? mocks.emptyRateResponse
: mocks.emptyMetricResponse;
return elasticsearchClientMock.createSuccessTransportRequestPromise(
params?.body.aggs.aggregatedIntervals.aggregations.aggregatedValue_max
? mocks.emptyRateResponse
: mocks.emptyMetricResponse
);
}
return mocks.basicMetricResponse;
return elasticsearchClientMock.createSuccessTransportRequestPromise(mocks.basicMetricResponse);
});
services.savedObjectsClient.get.mockImplementation(async (type: string, sourceId: string) => {
if (sourceId === 'alternate')

View file

@ -44,7 +44,7 @@ export const createMetricThresholdExecutor = (
);
const config = source.configuration;
const alertResults = await evaluateAlert(
services.callCluster,
services.scopedClusterClient.asCurrentUser,
params as EvaluatedAlertParams,
config
);

View file

@ -9,6 +9,8 @@ import * as mocks from './test_mocks';
import { Comparator, Aggregators, MetricExpressionParams } from './types';
import { alertsMock, AlertServicesMock } from '../../../../../alerting/server/mocks';
import { previewMetricThresholdAlert } from './preview_metric_threshold_alert';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks';
describe('Previewing the metric threshold alert type', () => {
describe('querying the entire infrastructure', () => {
@ -163,21 +165,32 @@ describe('Previewing the metric threshold alert type', () => {
});
const services: AlertServicesMock = alertsMock.createAlertServices();
services.callCluster.mockImplementation(async (_: string, { body, index }: any) => {
const metric = body.query.bool.filter[1]?.exists.field;
if (body.aggs.groupings) {
if (body.aggs.groupings.composite.after) {
return mocks.compositeEndResponse;
services.scopedClusterClient.asCurrentUser.search.mockImplementation((params?: any): any => {
const metric = params?.body.query.bool.filter[1]?.exists.field;
if (params?.body.aggs.groupings) {
if (params?.body.aggs.groupings.composite.after) {
return elasticsearchClientMock.createSuccessTransportRequestPromise(
mocks.compositeEndResponse
);
}
return mocks.basicCompositePreviewResponse;
return elasticsearchClientMock.createSuccessTransportRequestPromise(
mocks.basicCompositePreviewResponse
);
}
if (metric === 'test.metric.2') {
return mocks.alternateMetricPreviewResponse;
return elasticsearchClientMock.createSuccessTransportRequestPromise(
mocks.alternateMetricPreviewResponse
);
}
if (metric === 'test.metric.3') {
return mocks.repeatingMetricPreviewResponse;
return elasticsearchClientMock.createSuccessTransportRequestPromise(
mocks.repeatingMetricPreviewResponse
);
}
return mocks.basicMetricPreviewResponse;
return elasticsearchClientMock.createSuccessTransportRequestPromise(
mocks.basicMetricPreviewResponse
);
});
const baseCriterion = {
@ -197,7 +210,7 @@ const config = {
} as any;
const baseParams = {
callCluster: services.callCluster,
esClient: services.scopedClusterClient.asCurrentUser,
params: {
criteria: [baseCriterion],
groupBy: undefined,

View file

@ -11,7 +11,7 @@ import {
TOO_MANY_BUCKETS_PREVIEW_EXCEPTION,
isTooManyBucketsPreviewException,
} from '../../../../common/alerting/metrics';
import { ILegacyScopedClusterClient } from '../../../../../../../src/core/server';
import { ElasticsearchClient } from '../../../../../../../src/core/server';
import { InfraSource } from '../../../../common/http_api/source_api';
import { getIntervalInSeconds } from '../../../utils/get_interval_in_seconds';
import { PreviewResult } from '../common/types';
@ -21,7 +21,7 @@ import { evaluateAlert } from './lib/evaluate_alert';
const MAX_ITERATIONS = 50;
interface PreviewMetricThresholdAlertParams {
callCluster: ILegacyScopedClusterClient['callAsCurrentUser'];
esClient: ElasticsearchClient;
params: {
criteria: MetricExpressionParams[];
groupBy: string | undefined | string[];
@ -43,7 +43,7 @@ export const previewMetricThresholdAlert: (
precalculatedNumberOfGroups?: number
) => Promise<PreviewResult[]> = async (
{
callCluster,
esClient,
params,
config,
lookback,
@ -79,7 +79,7 @@ export const previewMetricThresholdAlert: (
// Get a date histogram using the bucket interval and the lookback interval
try {
const alertResults = await evaluateAlert(callCluster, params, config, timeframe);
const alertResults = await evaluateAlert(esClient, params, config, timeframe);
const groups = Object.keys(first(alertResults)!);
// Now determine how to interpolate this histogram based on the alert interval
@ -174,7 +174,7 @@ export const previewMetricThresholdAlert: (
// If there's too much data on the first request, recursively slice the lookback interval
// until all the data can be retrieved
const basePreviewParams = {
callCluster,
esClient,
params,
config,
lookback,
@ -187,7 +187,7 @@ export const previewMetricThresholdAlert: (
// If this is still the first iteration, try to get the number of groups in order to
// calculate max buckets. If this fails, just estimate based on 1 group
const currentAlertResults = !precalculatedNumberOfGroups
? await evaluateAlert(callCluster, params, config)
? await evaluateAlert(esClient, params, config)
: [];
const numberOfGroups =
precalculatedNumberOfGroups ?? Math.max(Object.keys(first(currentAlertResults)!).length, 1);

View file

@ -26,7 +26,6 @@ import { InfraBackendLibs } from '../../lib/infra_types';
import { assertHasInfraMlPlugins } from '../../utils/request_context';
export const initAlertPreviewRoute = ({ framework, sources }: InfraBackendLibs) => {
const { callWithRequest } = framework;
framework.registerRoute(
{
method: 'post',
@ -46,9 +45,7 @@ export const initAlertPreviewRoute = ({ framework, sources }: InfraBackendLibs)
alertNotifyWhen,
} = request.body;
const callCluster = (endpoint: string, opts: Record<string, any>) => {
return callWithRequest(requestContext, endpoint, opts);
};
const esClient = requestContext.core.elasticsearch.client.asCurrentUser;
const source = await sources.getSourceConfiguration(
requestContext.core.savedObjects.client,
@ -64,7 +61,7 @@ export const initAlertPreviewRoute = ({ framework, sources }: InfraBackendLibs)
filterQuery,
} = request.body as MetricThresholdAlertPreviewRequestParams;
const previewResult = await previewMetricThresholdAlert({
callCluster,
esClient,
params: { criteria, filterQuery, groupBy },
lookback,
config: source.configuration,
@ -86,7 +83,7 @@ export const initAlertPreviewRoute = ({ framework, sources }: InfraBackendLibs)
filterQuery,
} = request.body as InventoryAlertPreviewRequestParams;
const previewResult = await previewInventoryMetricThresholdAlert({
callCluster,
esClient,
params: { criteria, filterQuery, nodeType },
lookback,
source,

View file

@ -5,6 +5,7 @@
* 2.0.
*/
import { ApiResponse } from '@elastic/elasticsearch/lib/Transport';
import { InfraDatabaseSearchResponse } from '../lib/adapters/framework';
export const getAllCompositeData = async <
@ -12,13 +13,15 @@ export const getAllCompositeData = async <
Bucket = {},
Options extends object = {}
>(
callCluster: (options: Options) => Promise<InfraDatabaseSearchResponse<{}, Aggregation>>,
esClientSearch: (
options: Options
) => Promise<ApiResponse<InfraDatabaseSearchResponse<{}, Aggregation>>>,
options: Options,
bucketSelector: (response: InfraDatabaseSearchResponse<{}, Aggregation>) => Bucket[],
onAfterKey: (options: Options, response: InfraDatabaseSearchResponse<{}, Aggregation>) => Options,
previousBuckets: Bucket[] = []
): Promise<Bucket[]> => {
const response = await callCluster(options);
const { body: response } = await esClientSearch(options);
// Nothing available, return the previous buckets.
if (response.hits.total.value === 0) {
@ -40,7 +43,7 @@ export const getAllCompositeData = async <
// There is possibly more data, concat previous and current buckets and call ourselves recursively.
const newOptions = onAfterKey(options, response);
return getAllCompositeData(
callCluster,
esClientSearch,
newOptions,
bucketSelector,
onAfterKey,

View file

@ -58,10 +58,10 @@ export class ListPlugin
user,
});
},
getListClient: (callCluster, spaceId, user): ListClient => {
getListClient: (esClient, spaceId, user): ListClient => {
return new ListClient({
callCluster,
config,
esClient,
spaceId,
user,
});
@ -86,9 +86,7 @@ export class ListPlugin
core: {
savedObjects: { client: savedObjectsClient },
elasticsearch: {
legacy: {
client: { callAsCurrentUser: callCluster },
},
client: { asCurrentUser: esClient },
},
},
} = context;
@ -105,8 +103,8 @@ export class ListPlugin
}),
getListClient: (): ListClient =>
new ListClient({
callCluster,
config,
esClient,
spaceId,
user,
}),

View file

@ -5,7 +5,9 @@
* 2.0.
*/
import { getCallClusterMock } from '../../../common/get_call_cluster.mock';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks';
import { CreateListItemOptions } from '../items';
import {
DATE_NOW,
@ -19,9 +21,9 @@ import {
} from '../../../common/constants.mock';
export const getCreateListItemOptionsMock = (): CreateListItemOptions => ({
callCluster: getCallClusterMock(),
dateNow: DATE_NOW,
deserializer: undefined,
esClient: elasticsearchClientMock.createScopedClusterClient().asCurrentUser,
id: LIST_ITEM_ID,
listId: LIST_ID,
listItemIndex: LIST_ITEM_INDEX,

View file

@ -5,6 +5,9 @@
* 2.0.
*/
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks';
import { getListItemResponseMock } from '../../../common/schemas/response/list_item_schema.mock';
import { getIndexESListItemMock } from '../../../common/schemas/elastic_query/index_es_list_item_schema.mock';
import { LIST_ITEM_ID, LIST_ITEM_INDEX } from '../../../common/constants.mock';
@ -23,13 +26,17 @@ describe('crete_list_item', () => {
test('it returns a list item as expected with the id changed out for the elastic id', async () => {
const options = getCreateListItemOptionsMock();
const listItem = await createListItem(options);
const esClient = elasticsearchClientMock.createScopedClusterClient().asCurrentUser;
esClient.index.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise({ _id: 'elastic-id-123' })
);
const listItem = await createListItem({ ...options, esClient });
const expected = getListItemResponseMock();
expected.id = 'elastic-id-123';
expect(listItem).toEqual(expected);
});
test('It calls "callCluster" with body, index, and listIndex', async () => {
test('It calls "esClient" with body, index, and listIndex', async () => {
const options = getCreateListItemOptionsMock();
await createListItem(options);
const body = getIndexESListItemMock();
@ -39,13 +46,17 @@ describe('crete_list_item', () => {
index: LIST_ITEM_INDEX,
refresh: 'wait_for',
};
expect(options.callCluster).toBeCalledWith('index', expected);
expect(options.esClient.index).toBeCalledWith(expected);
});
test('It returns an auto-generated id if id is sent in undefined', async () => {
const options = getCreateListItemOptionsMock();
options.id = undefined;
const list = await createListItem(options);
const esClient = elasticsearchClientMock.createScopedClusterClient().asCurrentUser;
esClient.index.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise({ _id: 'elastic-id-123' })
);
const list = await createListItem({ ...options, esClient });
const expected = getListItemResponseMock();
expected.id = 'elastic-id-123';
expect(list).toEqual(expected);

View file

@ -7,7 +7,7 @@
import uuid from 'uuid';
import { CreateDocumentResponse } from 'elasticsearch';
import { LegacyAPICaller } from 'kibana/server';
import { ElasticsearchClient } from 'kibana/server';
import {
DeserializerOrUndefined,
@ -28,7 +28,7 @@ export interface CreateListItemOptions {
listId: string;
type: Type;
value: string;
callCluster: LegacyAPICaller;
esClient: ElasticsearchClient;
listItemIndex: string;
user: string;
meta: MetaOrUndefined;
@ -43,7 +43,7 @@ export const createListItem = async ({
listId,
type,
value,
callCluster,
esClient,
listItemIndex,
user,
meta,
@ -69,7 +69,7 @@ export const createListItem = async ({
...baseBody,
...elasticQuery,
};
const response = await callCluster<CreateDocumentResponse>('index', {
const { body: response } = await esClient.index<CreateDocumentResponse>({
body,
id,
index: listItemIndex,

View file

@ -5,7 +5,9 @@
* 2.0.
*/
import { getCallClusterMock } from '../../../common/get_call_cluster.mock';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks';
import { CreateListItemsBulkOptions } from '../items';
import {
DATE_NOW,
@ -20,9 +22,9 @@ import {
} from '../../../common/constants.mock';
export const getCreateListItemBulkOptionsMock = (): CreateListItemsBulkOptions => ({
callCluster: getCallClusterMock(),
dateNow: DATE_NOW,
deserializer: undefined,
esClient: elasticsearchClientMock.createScopedClusterClient().asCurrentUser,
listId: LIST_ID,
listItemIndex: LIST_ITEM_INDEX,
meta: META,

View file

@ -20,13 +20,13 @@ describe('crete_list_item_bulk', () => {
jest.clearAllMocks();
});
test('It calls "callCluster" with body, index, and the bulk items', async () => {
test('It calls "esClient" with body, index, and the bulk items', async () => {
const options = getCreateListItemBulkOptionsMock();
await createListItemsBulk(options);
const firstRecord = getIndexESListItemMock();
const secondRecord = getIndexESListItemMock(VALUE_2);
[firstRecord.tie_breaker_id, secondRecord.tie_breaker_id] = TIE_BREAKERS;
expect(options.callCluster).toBeCalledWith('bulk', {
expect(options.esClient.bulk).toBeCalledWith({
body: [
{ create: { _index: LIST_ITEM_INDEX } },
firstRecord,
@ -41,7 +41,7 @@ describe('crete_list_item_bulk', () => {
test('It should not call the dataClient when the values are empty', async () => {
const options = getCreateListItemBulkOptionsMock();
options.value = [];
expect(options.callCluster).not.toBeCalled();
expect(options.esClient.bulk).not.toBeCalled();
});
test('It should skip over a value if it is not able to add that item because it is not parsable such as an ip_range with a serializer that only matches one ip', async () => {
@ -52,7 +52,7 @@ describe('crete_list_item_bulk', () => {
value: ['127.0.0.1', '127.0.0.2'],
};
await createListItemsBulk(options);
expect(options.callCluster).toBeCalledWith('bulk', {
expect(options.esClient.bulk).toBeCalledWith({
body: [
{ create: { _index: LIST_ITEM_INDEX } },
{

View file

@ -6,7 +6,7 @@
*/
import uuid from 'uuid';
import { LegacyAPICaller } from 'kibana/server';
import { ElasticsearchClient } from 'kibana/server';
import { transformListItemToElasticQuery } from '../utils';
import {
@ -24,7 +24,7 @@ export interface CreateListItemsBulkOptions {
listId: string;
type: Type;
value: string[];
callCluster: LegacyAPICaller;
esClient: ElasticsearchClient;
listItemIndex: string;
user: string;
meta: MetaOrUndefined;
@ -38,7 +38,7 @@ export const createListItemsBulk = async ({
deserializer,
serializer,
value,
callCluster,
esClient,
listItemIndex,
user,
meta,
@ -82,7 +82,7 @@ export const createListItemsBulk = async ({
[]
);
try {
await callCluster('bulk', {
await esClient.bulk({
body,
index: listItemIndex,
refresh: 'wait_for',

View file

@ -5,12 +5,14 @@
* 2.0.
*/
import { getCallClusterMock } from '../../../common/get_call_cluster.mock';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks';
import { DeleteListItemOptions } from '../items';
import { LIST_ITEM_ID, LIST_ITEM_INDEX } from '../../../common/constants.mock';
export const getDeleteListItemOptionsMock = (): DeleteListItemOptions => ({
callCluster: getCallClusterMock(),
esClient: elasticsearchClientMock.createScopedClusterClient().asCurrentUser,
id: LIST_ITEM_ID,
listItemIndex: LIST_ITEM_INDEX,
});

View file

@ -50,6 +50,6 @@ describe('delete_list_item', () => {
index: LIST_ITEM_INDEX,
refresh: 'wait_for',
};
expect(options.callCluster).toBeCalledWith('delete', deleteQuery);
expect(options.esClient.delete).toBeCalledWith(deleteQuery);
});
});

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import { LegacyAPICaller } from 'kibana/server';
import { ElasticsearchClient } from 'kibana/server';
import { Id, ListItemSchema } from '../../../common/schemas';
@ -13,20 +13,20 @@ import { getListItem } from '.';
export interface DeleteListItemOptions {
id: Id;
callCluster: LegacyAPICaller;
esClient: ElasticsearchClient;
listItemIndex: string;
}
export const deleteListItem = async ({
id,
callCluster,
esClient,
listItemIndex,
}: DeleteListItemOptions): Promise<ListItemSchema | null> => {
const listItem = await getListItem({ callCluster, id, listItemIndex });
const listItem = await getListItem({ esClient, id, listItemIndex });
if (listItem == null) {
return null;
} else {
await callCluster('delete', {
await esClient.delete({
id,
index: listItemIndex,
refresh: 'wait_for',

View file

@ -5,12 +5,14 @@
* 2.0.
*/
import { getCallClusterMock } from '../../../common/get_call_cluster.mock';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks';
import { DeleteListItemByValueOptions } from '../items';
import { LIST_ID, LIST_ITEM_INDEX, TYPE, VALUE } from '../../../common/constants.mock';
export const getDeleteListItemByValueOptionsMock = (): DeleteListItemByValueOptions => ({
callCluster: getCallClusterMock(),
esClient: elasticsearchClientMock.createScopedClusterClient().asCurrentUser,
listId: LIST_ID,
listItemIndex: LIST_ITEM_INDEX,
type: TYPE,

View file

@ -61,8 +61,8 @@ describe('delete_list_item_by_value', () => {
},
},
index: '.items',
refresh: 'wait_for',
refresh: false,
};
expect(options.callCluster).toBeCalledWith('deleteByQuery', deleteByQuery);
expect(options.esClient.deleteByQuery).toBeCalledWith(deleteByQuery);
});
});

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import { LegacyAPICaller } from 'kibana/server';
import { ElasticsearchClient } from 'kibana/server';
import { ListItemArraySchema, Type } from '../../../common/schemas';
import { getQueryFilterFromTypeValue } from '../utils';
@ -16,7 +16,7 @@ export interface DeleteListItemByValueOptions {
listId: string;
type: Type;
value: string;
callCluster: LegacyAPICaller;
esClient: ElasticsearchClient;
listItemIndex: string;
}
@ -24,11 +24,11 @@ export const deleteListItemByValue = async ({
listId,
value,
type,
callCluster,
esClient,
listItemIndex,
}: DeleteListItemByValueOptions): Promise<ListItemArraySchema> => {
const listItems = await getListItemByValues({
callCluster,
esClient,
listId,
listItemIndex,
type,
@ -40,7 +40,7 @@ export const deleteListItemByValue = async ({
type,
value: values,
});
await callCluster('deleteByQuery', {
await esClient.deleteByQuery({
body: {
query: {
bool: {
@ -49,7 +49,7 @@ export const deleteListItemByValue = async ({
},
},
index: listItemIndex,
refresh: 'wait_for',
refresh: false,
});
return listItems;
};

View file

@ -6,11 +6,10 @@
*/
import { Client } from 'elasticsearch';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks';
import { getSearchListMock } from '../../../common/schemas/elastic_response/search_es_list_schema.mock';
import { getShardMock } from '../../../common/get_shard.mock';
import { getSearchListItemMock } from '../../../common/schemas/elastic_response/search_es_list_item_schema.mock';
import { getCallClusterMockMultiTimes } from '../../../common/get_call_cluster.mock';
import { LIST_ID, LIST_INDEX, LIST_ITEM_INDEX } from '../../../common/constants.mock';
import { FindListItemOptions } from './find_list_item';
@ -23,14 +22,9 @@ export const getFindCount = (): ReturnType<Client['count']> => {
};
export const getFindListItemOptionsMock = (): FindListItemOptions => {
const callCluster = getCallClusterMockMultiTimes([
getSearchListMock(),
getFindCount(),
getSearchListItemMock(),
]);
return {
callCluster,
currentIndexPosition: 0,
esClient: elasticsearchClientMock.createScopedClusterClient().asCurrentUser,
filter: '',
listId: LIST_ID,
listIndex: LIST_INDEX,

View file

@ -5,9 +5,12 @@
* 2.0.
*/
import { getEmptySearchListMock } from '../../../common/schemas/elastic_response/search_es_list_schema.mock';
import { getCallClusterMockMultiTimes } from '../../../common/get_call_cluster.mock';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks';
import { getShardMock } from '../../../common/get_shard.mock';
import { getFoundListItemSchemaMock } from '../../../common/schemas/response/found_list_item_schema.mock';
import { getEmptySearchListMock } from '../../../common/schemas/elastic_response/search_es_list_schema.mock';
import { getFindListItemOptionsMock } from './find_list_item.mock';
import { findListItem } from './find_list_item';
@ -15,15 +18,53 @@ import { findListItem } from './find_list_item';
describe('find_list_item', () => {
test('should find a simple single list item', async () => {
const options = getFindListItemOptionsMock();
const item = await findListItem(options);
const esClient = elasticsearchClientMock.createScopedClusterClient().asCurrentUser;
esClient.count.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise({ count: 1 })
);
esClient.search.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise({
_scroll_id: '123',
_shards: getShardMock(),
hits: {
hits: [
{
_id: 'some-list-item-id',
_source: {
_version: 'undefined',
created_at: '2020-04-20T15:25:31.830Z',
created_by: 'some user',
date_range: '127.0.0.1',
deserializer: undefined,
list_id: 'some-list-id',
meta: {},
serializer: undefined,
tie_breaker_id: '6a76b69d-80df-4ab2-8c3e-85f466b06a0e',
type: 'ip',
updated_at: '2020-04-20T15:25:31.830Z',
updated_by: 'some user',
},
},
],
max_score: 0,
total: 1,
},
timed_out: false,
took: 10,
})
);
const item = await findListItem({ ...options, esClient });
const expected = getFoundListItemSchemaMock();
expect(item).toEqual(expected);
});
test('should return null if the list is null', async () => {
const options = getFindListItemOptionsMock();
options.callCluster = getCallClusterMockMultiTimes([getEmptySearchListMock()]);
const item = await findListItem(options);
const esClient = elasticsearchClientMock.createScopedClusterClient().asCurrentUser;
esClient.search.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise(getEmptySearchListMock())
);
const item = await findListItem({ ...options, esClient });
expect(item).toEqual(null);
});
});

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import { LegacyAPICaller } from 'kibana/server';
import { ElasticsearchClient } from 'kibana/server';
import { SearchResponse } from 'elasticsearch';
import {
@ -37,13 +37,13 @@ export interface FindListItemOptions {
page: Page;
sortField: SortFieldOrUndefined;
sortOrder: SortOrderOrUndefined;
callCluster: LegacyAPICaller;
esClient: ElasticsearchClient;
listIndex: string;
listItemIndex: string;
}
export const findListItem = async ({
callCluster,
esClient,
currentIndexPosition,
filter,
listId,
@ -55,7 +55,7 @@ export const findListItem = async ({
listItemIndex,
sortOrder,
}: FindListItemOptions): Promise<FoundListItemSchema | null> => {
const list = await getList({ callCluster, id: listId, listIndex });
const list = await getList({ esClient, id: listId, listIndex });
if (list == null) {
return null;
} else {
@ -63,8 +63,8 @@ export const findListItem = async ({
const sortField =
sortFieldWithPossibleValue === 'value' ? list.type : sortFieldWithPossibleValue;
const scroll = await scrollToStartPage({
callCluster,
currentIndexPosition,
esClient,
filter,
hopSize: 100,
index: listItemIndex,
@ -75,25 +75,25 @@ export const findListItem = async ({
sortOrder,
});
const { count } = await callCluster('count', {
const { body: respose } = await esClient.count<{ count: number }>({
body: {
query,
},
ignoreUnavailable: true,
ignore_unavailable: true,
index: listItemIndex,
});
if (scroll.validSearchAfterFound) {
// Note: This typing of response = await callCluster<SearchResponse<SearchEsListSchema>>
// Note: This typing of response = await esClient<SearchResponse<SearchEsListSchema>>
// is because when you pass in seq_no_primary_term: true it does a "fall through" type and you have
// to explicitly define the type <T>.
const response = await callCluster<SearchResponse<SearchEsListItemSchema>>('search', {
const { body: response } = await esClient.search<SearchResponse<SearchEsListItemSchema>>({
body: {
query,
search_after: scroll.searchAfter,
sort: getSortWithTieBreaker({ sortField, sortOrder }),
},
ignoreUnavailable: true,
ignore_unavailable: true,
index: listItemIndex,
seq_no_primary_term: true,
size: perPage,
@ -107,7 +107,7 @@ export const findListItem = async ({
data: transformElasticToListItem({ response, type: list.type }),
page,
per_page: perPage,
total: count,
total: respose.count,
};
} else {
return {
@ -115,7 +115,7 @@ export const findListItem = async ({
data: [],
page,
per_page: perPage,
total: count,
total: respose.count,
};
}
}

View file

@ -5,9 +5,11 @@
* 2.0.
*/
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks';
import { getSearchListItemMock } from '../../../common/schemas/elastic_response/search_es_list_item_schema.mock';
import { getListItemResponseMock } from '../../../common/schemas/response/list_item_schema.mock';
import { getCallClusterMock } from '../../../common/get_call_cluster.mock';
import {
DATE_NOW,
LIST_ID,
@ -30,8 +32,11 @@ describe('get_list_item', () => {
test('it returns a list item as expected if the list item is found', async () => {
const data = getSearchListItemMock();
const callCluster = getCallClusterMock(data);
const list = await getListItem({ callCluster, id: LIST_ID, listItemIndex: LIST_INDEX });
const esClient = elasticsearchClientMock.createScopedClusterClient().asCurrentUser;
esClient.search.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise(data)
);
const list = await getListItem({ esClient, id: LIST_ID, listItemIndex: LIST_INDEX });
const expected = getListItemResponseMock();
expect(list).toEqual(expected);
});
@ -39,8 +44,11 @@ describe('get_list_item', () => {
test('it returns null if the search is empty', async () => {
const data = getSearchListItemMock();
data.hits.hits = [];
const callCluster = getCallClusterMock(data);
const list = await getListItem({ callCluster, id: LIST_ID, listItemIndex: LIST_INDEX });
const esClient = elasticsearchClientMock.createScopedClusterClient().asCurrentUser;
esClient.search.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise(data)
);
const list = await getListItem({ esClient, id: LIST_ID, listItemIndex: LIST_INDEX });
expect(list).toEqual(null);
});
@ -80,8 +88,11 @@ describe('get_list_item', () => {
updated_at: DATE_NOW,
updated_by: USER,
};
const callCluster = getCallClusterMock(data);
const list = await getListItem({ callCluster, id: LIST_ID, listItemIndex: LIST_INDEX });
const esClient = elasticsearchClientMock.createScopedClusterClient().asCurrentUser;
esClient.search.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise(data)
);
const list = await getListItem({ esClient, id: LIST_ID, listItemIndex: LIST_INDEX });
expect(list).toEqual(null);
});
});

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import { LegacyAPICaller } from 'kibana/server';
import { ElasticsearchClient } from 'kibana/server';
import { SearchResponse } from 'elasticsearch';
import { Id, ListItemSchema, SearchEsListItemSchema } from '../../../common/schemas';
@ -14,19 +14,19 @@ import { findSourceType } from '../utils/find_source_type';
interface GetListItemOptions {
id: Id;
callCluster: LegacyAPICaller;
esClient: ElasticsearchClient;
listItemIndex: string;
}
export const getListItem = async ({
id,
callCluster,
esClient,
listItemIndex,
}: GetListItemOptions): Promise<ListItemSchema | null> => {
// Note: This typing of response = await callCluster<SearchResponse<SearchEsListSchema>>
// Note: This typing of response = await esClient<SearchResponse<SearchEsListSchema>>
// is because when you pass in seq_no_primary_term: true it does a "fall through" type and you have
// to explicitly define the type <T>.
const listItemES = await callCluster<SearchResponse<SearchEsListItemSchema>>('search', {
const { body: listItemES } = await esClient.search<SearchResponse<SearchEsListItemSchema>>({
body: {
query: {
term: {
@ -34,7 +34,7 @@ export const getListItem = async ({
},
},
},
ignoreUnavailable: true,
ignore_unavailable: true,
index: listItemIndex,
seq_no_primary_term: true,
});

View file

@ -5,12 +5,14 @@
* 2.0.
*/
import { getCallClusterMock } from '../../../common/get_call_cluster.mock';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks';
import { GetListItemByValueOptions } from '../items';
import { LIST_ID, LIST_ITEM_INDEX, TYPE, VALUE } from '../../../common/constants.mock';
export const getListItemByValueOptionsMocks = (): GetListItemByValueOptions => ({
callCluster: getCallClusterMock(),
esClient: elasticsearchClientMock.createScopedClusterClient().asCurrentUser,
listId: LIST_ID,
listItemIndex: LIST_ITEM_INDEX,
type: TYPE,

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import { LegacyAPICaller } from 'kibana/server';
import { ElasticsearchClient } from 'kibana/server';
import { ListItemArraySchema, Type } from '../../../common/schemas';
@ -13,7 +13,7 @@ import { getListItemByValues } from '.';
export interface GetListItemByValueOptions {
listId: string;
callCluster: LegacyAPICaller;
esClient: ElasticsearchClient;
listItemIndex: string;
type: Type;
value: string;
@ -21,13 +21,13 @@ export interface GetListItemByValueOptions {
export const getListItemByValue = async ({
listId,
callCluster,
esClient,
listItemIndex,
type,
value,
}: GetListItemByValueOptions): Promise<ListItemArraySchema> =>
getListItemByValues({
callCluster,
esClient,
listId,
listItemIndex,
type,

View file

@ -5,12 +5,14 @@
* 2.0.
*/
import { getCallClusterMock } from '../../../common/get_call_cluster.mock';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks';
import { GetListItemByValuesOptions } from '../items';
import { LIST_ID, LIST_ITEM_INDEX, TYPE, VALUE, VALUE_2 } from '../../../common/constants.mock';
export const getListItemByValuesOptionsMocks = (): GetListItemByValuesOptions => ({
callCluster: getCallClusterMock(),
esClient: elasticsearchClientMock.createScopedClusterClient().asCurrentUser,
listId: LIST_ID,
listItemIndex: LIST_ITEM_INDEX,
type: TYPE,

View file

@ -5,8 +5,10 @@
* 2.0.
*/
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks';
import { getSearchListItemMock } from '../../../common/schemas/elastic_response/search_es_list_item_schema.mock';
import { getCallClusterMock } from '../../../common/get_call_cluster.mock';
import {
DATE_NOW,
LIST_ID,
@ -34,9 +36,12 @@ describe('get_list_item_by_values', () => {
test('Returns a an empty array if the ES query is also empty', async () => {
const data = getSearchListItemMock();
data.hits.hits = [];
const callCluster = getCallClusterMock(data);
const esClient = elasticsearchClientMock.createScopedClusterClient().asCurrentUser;
esClient.search.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise(data)
);
const listItem = await getListItemByValues({
callCluster,
esClient,
listId: LIST_ID,
listItemIndex: LIST_ITEM_INDEX,
type: TYPE,
@ -48,9 +53,12 @@ describe('get_list_item_by_values', () => {
test('Returns transformed list item if the data exists within ES', async () => {
const data = getSearchListItemMock();
const callCluster = getCallClusterMock(data);
const esClient = elasticsearchClientMock.createScopedClusterClient().asCurrentUser;
esClient.search.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise(data)
);
const listItem = await getListItemByValues({
callCluster,
esClient,
listId: LIST_ID,
listItemIndex: LIST_ITEM_INDEX,
type: TYPE,

View file

@ -5,14 +5,18 @@
* 2.0.
*/
import { LegacyAPICaller } from 'kibana/server';
import { ElasticsearchClient } from 'kibana/server';
import { ListItemArraySchema, SearchEsListItemSchema, Type } from '../../../common/schemas';
import { getQueryFilterFromTypeValue, transformElasticToListItem } from '../utils';
import {
TransformElasticToListItemOptions,
getQueryFilterFromTypeValue,
transformElasticToListItem,
} from '../utils';
export interface GetListItemByValuesOptions {
listId: string;
callCluster: LegacyAPICaller;
esClient: ElasticsearchClient;
listItemIndex: string;
type: Type;
value: string[];
@ -20,12 +24,12 @@ export interface GetListItemByValuesOptions {
export const getListItemByValues = async ({
listId,
callCluster,
esClient,
listItemIndex,
type,
value,
}: GetListItemByValuesOptions): Promise<ListItemArraySchema> => {
const response = await callCluster<SearchEsListItemSchema>('search', {
const { body: response } = await esClient.search<SearchEsListItemSchema>({
body: {
query: {
bool: {
@ -33,9 +37,12 @@ export const getListItemByValues = async ({
},
},
},
ignoreUnavailable: true,
ignore_unavailable: true,
index: listItemIndex,
size: 10000, // TODO: This has a limit on the number which is 10,000 the default of Elastic but we might want to provide a way to increase that number
});
return transformElasticToListItem({ response, type });
return transformElasticToListItem(({
response,
type,
} as unknown) as TransformElasticToListItemOptions);
};

View file

@ -5,12 +5,14 @@
* 2.0.
*/
import { getCallClusterMock } from '../../../common/get_call_cluster.mock';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks';
import { SearchListItemByValuesOptions } from '../items';
import { LIST_ID, LIST_ITEM_INDEX, TYPE, VALUE, VALUE_2 } from '../../../common/constants.mock';
export const searchListItemByValuesOptionsMocks = (): SearchListItemByValuesOptions => ({
callCluster: getCallClusterMock(),
esClient: elasticsearchClientMock.createScopedClusterClient().asCurrentUser,
listId: LIST_ID,
listItemIndex: LIST_ITEM_INDEX,
type: TYPE,

View file

@ -5,9 +5,11 @@
* 2.0.
*/
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks';
import { SearchListItemArraySchema } from '../../../common/schemas';
import { getSearchListItemMock } from '../../../common/schemas/elastic_response/search_es_list_item_schema.mock';
import { getCallClusterMock } from '../../../common/get_call_cluster.mock';
import { LIST_ID, LIST_ITEM_INDEX, TYPE, VALUE, VALUE_2 } from '../../../common/constants.mock';
import { searchListItemByValues } from './search_list_item_by_values';
@ -24,9 +26,12 @@ describe('search_list_item_by_values', () => {
test('Returns a an empty array of items if the value is empty', async () => {
const data = getSearchListItemMock();
data.hits.hits = [];
const callCluster = getCallClusterMock(data);
const esClient = elasticsearchClientMock.createScopedClusterClient().asCurrentUser;
esClient.search.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise(data)
);
const listItem = await searchListItemByValues({
callCluster,
esClient,
listId: LIST_ID,
listItemIndex: LIST_ITEM_INDEX,
type: TYPE,
@ -39,9 +44,12 @@ describe('search_list_item_by_values', () => {
test('Returns a an empty array of items if the ES query is also empty', async () => {
const data = getSearchListItemMock();
data.hits.hits = [];
const callCluster = getCallClusterMock(data);
const esClient = elasticsearchClientMock.createScopedClusterClient().asCurrentUser;
esClient.search.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise(data)
);
const listItem = await searchListItemByValues({
callCluster,
esClient,
listId: LIST_ID,
listItemIndex: LIST_ITEM_INDEX,
type: TYPE,
@ -57,9 +65,12 @@ describe('search_list_item_by_values', () => {
test('Returns transformed list item if the data exists within ES', async () => {
const data = getSearchListItemMock();
const callCluster = getCallClusterMock(data);
const esClient = elasticsearchClientMock.createScopedClusterClient().asCurrentUser;
esClient.search.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise(data)
);
const listItem = await searchListItemByValues({
callCluster,
esClient,
listId: LIST_ID,
listItemIndex: LIST_ITEM_INDEX,
type: TYPE,

View file

@ -5,14 +5,18 @@
* 2.0.
*/
import { LegacyAPICaller } from 'kibana/server';
import { ElasticsearchClient } from 'kibana/server';
import { SearchEsListItemSchema, SearchListItemArraySchema, Type } from '../../../common/schemas';
import { getQueryFilterFromTypeValue, transformElasticNamedSearchToListItem } from '../utils';
import {
TransformElasticMSearchToListItemOptions,
getQueryFilterFromTypeValue,
transformElasticNamedSearchToListItem,
} from '../utils';
export interface SearchListItemByValuesOptions {
listId: string;
callCluster: LegacyAPICaller;
esClient: ElasticsearchClient;
listItemIndex: string;
type: Type;
value: unknown[];
@ -20,12 +24,12 @@ export interface SearchListItemByValuesOptions {
export const searchListItemByValues = async ({
listId,
callCluster,
esClient,
listItemIndex,
type,
value,
}: SearchListItemByValuesOptions): Promise<SearchListItemArraySchema> => {
const response = await callCluster<SearchEsListItemSchema>('search', {
const { body: response } = await esClient.search<SearchEsListItemSchema>({
body: {
query: {
bool: {
@ -33,9 +37,13 @@ export const searchListItemByValues = async ({
},
},
},
ignoreUnavailable: true,
ignore_unavailable: true,
index: listItemIndex,
size: 10000, // TODO: This has a limit on the number which is 10,000 the default of Elastic but we might want to provide a way to increase that number
});
return transformElasticNamedSearchToListItem({ response, type, value });
return transformElasticNamedSearchToListItem(({
response,
type,
value,
} as unknown) as TransformElasticMSearchToListItemOptions);
};

View file

@ -5,7 +5,9 @@
* 2.0.
*/
import { getCallClusterMock } from '../../../common/get_call_cluster.mock';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks';
import { UpdateListItemOptions } from '../items';
import {
DATE_NOW,
@ -18,8 +20,8 @@ import {
export const getUpdateListItemOptionsMock = (): UpdateListItemOptions => ({
_version: undefined,
callCluster: getCallClusterMock(),
dateNow: DATE_NOW,
esClient: elasticsearchClientMock.createScopedClusterClient().asCurrentUser,
id: LIST_ITEM_ID,
listItemIndex: LIST_ITEM_INDEX,
meta: META,

View file

@ -5,6 +5,9 @@
* 2.0.
*/
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks';
import { ListItemSchema } from '../../../common/schemas';
import { getListItemResponseMock } from '../../../common/schemas/response/list_item_schema.mock';
@ -29,7 +32,11 @@ describe('update_list_item', () => {
const listItem = getListItemResponseMock();
((getListItem as unknown) as jest.Mock).mockResolvedValueOnce(listItem);
const options = getUpdateListItemOptionsMock();
const updatedList = await updateListItem(options);
const esClient = elasticsearchClientMock.createScopedClusterClient().asCurrentUser;
esClient.update.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise({ _id: 'elastic-id-123' })
);
const updatedList = await updateListItem({ ...options, esClient });
const expected: ListItemSchema = { ...getListItemResponseMock(), id: 'elastic-id-123' };
expect(updatedList).toEqual(expected);
});

View file

@ -6,7 +6,7 @@
*/
import { CreateDocumentResponse } from 'elasticsearch';
import { LegacyAPICaller } from 'kibana/server';
import { ElasticsearchClient } from 'kibana/server';
import {
Id,
@ -25,7 +25,7 @@ export interface UpdateListItemOptions {
_version: _VersionOrUndefined;
id: Id;
value: string | null | undefined;
callCluster: LegacyAPICaller;
esClient: ElasticsearchClient;
listItemIndex: string;
user: string;
meta: MetaOrUndefined;
@ -36,14 +36,14 @@ export const updateListItem = async ({
_version,
id,
value,
callCluster,
esClient,
listItemIndex,
user,
meta,
dateNow,
}: UpdateListItemOptions): Promise<ListItemSchema | null> => {
const updatedAt = dateNow ?? new Date().toISOString();
const listItem = await getListItem({ callCluster, id, listItemIndex });
const listItem = await getListItem({ esClient, id, listItemIndex });
if (listItem == null) {
return null;
} else {
@ -62,7 +62,7 @@ export const updateListItem = async ({
...elasticQuery,
};
const response = await callCluster<CreateDocumentResponse>('update', {
const { body: response } = await esClient.update<CreateDocumentResponse>({
...decodeVersion(_version),
body: {
doc,

View file

@ -5,7 +5,9 @@
* 2.0.
*/
import { getCallClusterMock } from '../../../common/get_call_cluster.mock';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks';
import { ImportListItemsToStreamOptions, WriteBufferToItemsOptions } from '../items';
import {
LIST_ID,
@ -21,9 +23,9 @@ import { getConfigMockDecoded } from '../../config.mock';
import { TestReadable } from './test_readable.mock';
export const getImportListItemsToStreamOptionsMock = (): ImportListItemsToStreamOptions => ({
callCluster: getCallClusterMock(),
config: getConfigMockDecoded(),
deserializer: undefined,
esClient: elasticsearchClientMock.createScopedClusterClient().asCurrentUser,
listId: LIST_ID,
listIndex: LIST_INDEX,
listItemIndex: LIST_ITEM_INDEX,
@ -37,8 +39,8 @@ export const getImportListItemsToStreamOptionsMock = (): ImportListItemsToStream
export const getWriteBufferToItemsOptionsMock = (): WriteBufferToItemsOptions => ({
buffer: [],
callCluster: getCallClusterMock(),
deserializer: undefined,
esClient: elasticsearchClientMock.createScopedClusterClient().asCurrentUser,
listId: LIST_ID,
listItemIndex: LIST_ITEM_INDEX,
meta: META,

View file

@ -7,7 +7,7 @@
import { Readable } from 'stream';
import { LegacyAPICaller } from 'kibana/server';
import { ElasticsearchClient } from 'kibana/server';
import { createListIfItDoesNotExist } from '../lists/create_list_if_it_does_not_exist';
import {
@ -31,7 +31,7 @@ export interface ImportListItemsToStreamOptions {
deserializer: DeserializerOrUndefined;
serializer: SerializerOrUndefined;
stream: Readable;
callCluster: LegacyAPICaller;
esClient: ElasticsearchClient;
listItemIndex: string;
type: Type;
user: string;
@ -45,7 +45,7 @@ export const importListItemsToStream = ({
serializer,
listId,
stream,
callCluster,
esClient,
listItemIndex,
listIndex,
type,
@ -62,9 +62,9 @@ export const importListItemsToStream = ({
fileName = fileNameEmitted;
if (listId == null) {
list = await createListIfItDoesNotExist({
callCluster,
description: `File uploaded from file system of ${fileNameEmitted}`,
deserializer,
esClient,
id: fileNameEmitted,
immutable: false,
listIndex,
@ -83,8 +83,8 @@ export const importListItemsToStream = ({
if (listId != null) {
await writeBufferToItems({
buffer: lines,
callCluster,
deserializer,
esClient,
listId,
listItemIndex,
meta,
@ -95,8 +95,8 @@ export const importListItemsToStream = ({
} else if (fileName != null) {
await writeBufferToItems({
buffer: lines,
callCluster,
deserializer,
esClient,
listId: fileName,
listItemIndex,
meta,
@ -117,7 +117,7 @@ export interface WriteBufferToItemsOptions {
listId: string;
deserializer: DeserializerOrUndefined;
serializer: SerializerOrUndefined;
callCluster: LegacyAPICaller;
esClient: ElasticsearchClient;
listItemIndex: string;
buffer: string[];
type: Type;
@ -131,7 +131,7 @@ export interface LinesResult {
export const writeBufferToItems = async ({
listId,
callCluster,
esClient,
deserializer,
serializer,
listItemIndex,
@ -141,8 +141,8 @@ export const writeBufferToItems = async ({
meta,
}: WriteBufferToItemsOptions): Promise<LinesResult> => {
await createListItemsBulk({
callCluster,
deserializer,
esClient,
listId,
listItemIndex,
meta,

View file

@ -5,8 +5,10 @@
* 2.0.
*/
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks';
import { getSearchListItemMock } from '../../../common/schemas/elastic_response/search_es_list_item_schema.mock';
import { getCallClusterMock } from '../../../common/get_call_cluster.mock';
import { LIST_ID, LIST_ITEM_INDEX } from '../../../common/constants.mock';
import {
@ -38,8 +40,11 @@ describe('write_list_items_to_stream', () => {
const options = getExportListItemsToStreamOptionsMock();
const firstResponse = getSearchListItemMock();
firstResponse.hits.hits = [];
options.callCluster = getCallClusterMock(firstResponse);
exportListItemsToStream(options);
const esClient = elasticsearchClientMock.createScopedClusterClient().asCurrentUser;
esClient.search.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise(firstResponse)
);
exportListItemsToStream({ ...options, esClient });
let chunks: string[] = [];
options.stream.on('data', (chunk: Buffer) => {
@ -54,7 +59,12 @@ describe('write_list_items_to_stream', () => {
test('It exports single list item to the stream', (done) => {
const options = getExportListItemsToStreamOptionsMock();
exportListItemsToStream(options);
const response = getSearchListItemMock();
const esClient = elasticsearchClientMock.createScopedClusterClient().asCurrentUser;
esClient.search.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise(response)
);
exportListItemsToStream({ ...options, esClient });
let chunks: string[] = [];
options.stream.on('data', (chunk: Buffer) => {
@ -72,8 +82,11 @@ describe('write_list_items_to_stream', () => {
const firstResponse = getSearchListItemMock();
const secondResponse = getSearchListItemMock();
firstResponse.hits.hits = [...firstResponse.hits.hits, ...secondResponse.hits.hits];
options.callCluster = getCallClusterMock(firstResponse);
exportListItemsToStream(options);
const esClient = elasticsearchClientMock.createScopedClusterClient().asCurrentUser;
esClient.search.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise(firstResponse)
);
exportListItemsToStream({ ...options, esClient });
let chunks: string[] = [];
options.stream.on('data', (chunk: Buffer) => {
@ -95,12 +108,14 @@ describe('write_list_items_to_stream', () => {
const secondResponse = getSearchListItemMock();
secondResponse.hits.hits[0]._source.ip = '255.255.255.255';
options.callCluster = jest
.fn()
.mockResolvedValueOnce(firstResponse)
.mockResolvedValueOnce(secondResponse);
exportListItemsToStream(options);
const esClient = elasticsearchClientMock.createScopedClusterClient().asCurrentUser;
esClient.search.mockResolvedValueOnce(
elasticsearchClientMock.createSuccessTransportRequestPromise(firstResponse)
);
esClient.search.mockResolvedValueOnce(
elasticsearchClientMock.createSuccessTransportRequestPromise(secondResponse)
);
exportListItemsToStream({ ...options, esClient });
let chunks: string[] = [];
options.stream.on('data', (chunk: Buffer) => {
@ -117,7 +132,12 @@ describe('write_list_items_to_stream', () => {
describe('writeNextResponse', () => {
test('It returns an empty searchAfter response when there is no sort defined', async () => {
const options = getWriteNextResponseOptions();
const searchAfter = await writeNextResponse(options);
const listItem = getSearchListItemMock();
const esClient = elasticsearchClientMock.createScopedClusterClient().asCurrentUser;
esClient.search.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise(listItem)
);
const searchAfter = await writeNextResponse({ ...options, esClient });
expect(searchAfter).toEqual(undefined);
});
@ -125,8 +145,11 @@ describe('write_list_items_to_stream', () => {
const listItem = getSearchListItemMock();
listItem.hits.hits[0].sort = ['sort-value-1'];
const options = getWriteNextResponseOptions();
options.callCluster = getCallClusterMock(listItem);
const searchAfter = await writeNextResponse(options);
const esClient = elasticsearchClientMock.createScopedClusterClient().asCurrentUser;
esClient.search.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise(listItem)
);
const searchAfter = await writeNextResponse({ ...options, esClient });
expect(searchAfter).toEqual(['sort-value-1']);
});
@ -134,8 +157,11 @@ describe('write_list_items_to_stream', () => {
const listItem = getSearchListItemMock();
listItem.hits.hits = [];
const options = getWriteNextResponseOptions();
options.callCluster = getCallClusterMock(listItem);
const searchAfter = await writeNextResponse(options);
const esClient = elasticsearchClientMock.createScopedClusterClient().asCurrentUser;
esClient.search.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise(listItem)
);
const searchAfter = await writeNextResponse({ ...options, esClient });
expect(searchAfter).toEqual(undefined);
});
});
@ -183,11 +209,11 @@ describe('write_list_items_to_stream', () => {
search_after: ['string 1', 'string 2'],
sort: [{ tie_breaker_id: 'asc' }],
},
ignoreUnavailable: true,
ignore_unavailable: true,
index: LIST_ITEM_INDEX,
size: 100,
};
expect(options.callCluster).toBeCalledWith('search', expected);
expect(options.esClient.search).toBeCalledWith(expected);
});
test('It returns a simple response with expected values and size changed', async () => {
@ -201,11 +227,11 @@ describe('write_list_items_to_stream', () => {
search_after: ['string 1', 'string 2'],
sort: [{ tie_breaker_id: 'asc' }],
},
ignoreUnavailable: true,
ignore_unavailable: true,
index: LIST_ITEM_INDEX,
size: 33,
};
expect(options.callCluster).toBeCalledWith('search', expected);
expect(options.esClient.search).toBeCalledWith(expected);
});
});

View file

@ -8,7 +8,7 @@
import { PassThrough } from 'stream';
import { SearchResponse } from 'elasticsearch';
import { LegacyAPICaller } from 'kibana/server';
import { ElasticsearchClient } from 'kibana/server';
import { SearchEsListItemSchema } from '../../../common/schemas';
import { ErrorWithStatusCode } from '../../error_with_status_code';
@ -22,7 +22,7 @@ export const SIZE = 100;
export interface ExportListItemsToStreamOptions {
listId: string;
callCluster: LegacyAPICaller;
esClient: ElasticsearchClient;
listItemIndex: string;
stream: PassThrough;
stringToAppend: string | null | undefined;
@ -30,7 +30,7 @@ export interface ExportListItemsToStreamOptions {
export const exportListItemsToStream = ({
listId,
callCluster,
esClient,
stream,
listItemIndex,
stringToAppend,
@ -39,7 +39,7 @@ export const exportListItemsToStream = ({
// and prevent the async await from bubbling up to the caller
setTimeout(async () => {
let searchAfter = await writeNextResponse({
callCluster,
esClient,
listId,
listItemIndex,
searchAfter: undefined,
@ -48,7 +48,7 @@ export const exportListItemsToStream = ({
});
while (searchAfter != null) {
searchAfter = await writeNextResponse({
callCluster,
esClient,
listId,
listItemIndex,
searchAfter,
@ -62,7 +62,7 @@ export const exportListItemsToStream = ({
export interface WriteNextResponseOptions {
listId: string;
callCluster: LegacyAPICaller;
esClient: ElasticsearchClient;
listItemIndex: string;
stream: PassThrough;
searchAfter: string[] | undefined;
@ -71,14 +71,14 @@ export interface WriteNextResponseOptions {
export const writeNextResponse = async ({
listId,
callCluster,
esClient,
stream,
listItemIndex,
searchAfter,
stringToAppend,
}: WriteNextResponseOptions): Promise<string[] | undefined> => {
const response = await getResponse({
callCluster,
esClient,
listId,
listItemIndex,
searchAfter,
@ -102,7 +102,7 @@ export const getSearchAfterFromResponse = <T>({
: undefined;
export interface GetResponseOptions {
callCluster: LegacyAPICaller;
esClient: ElasticsearchClient;
listId: string;
searchAfter: undefined | string[];
listItemIndex: string;
@ -110,26 +110,28 @@ export interface GetResponseOptions {
}
export const getResponse = async ({
callCluster,
esClient,
searchAfter,
listId,
listItemIndex,
size = SIZE,
}: GetResponseOptions): Promise<SearchResponse<SearchEsListItemSchema>> => {
return callCluster<SearchEsListItemSchema>('search', {
body: {
query: {
term: {
list_id: listId,
return ((
await esClient.search<SearchEsListItemSchema>({
body: {
query: {
term: {
list_id: listId,
},
},
search_after: searchAfter,
sort: [{ tie_breaker_id: 'asc' }],
},
search_after: searchAfter,
sort: [{ tie_breaker_id: 'asc' }],
},
ignoreUnavailable: true,
index: listItemIndex,
size,
});
ignore_unavailable: true,
index: listItemIndex,
size,
})
).body as unknown) as SearchResponse<SearchEsListItemSchema>;
};
export interface WriteResponseHitsToStreamOptions {

View file

@ -7,8 +7,10 @@
import { Stream } from 'stream';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks';
import { getSearchListItemMock } from '../../../common/schemas/elastic_response/search_es_list_item_schema.mock';
import { getCallClusterMock } from '../../../common/get_call_cluster.mock';
import {
ExportListItemsToStreamOptions,
GetResponseOptions,
@ -18,7 +20,7 @@ import {
import { LIST_ID, LIST_ITEM_INDEX } from '../../../common/constants.mock';
export const getExportListItemsToStreamOptionsMock = (): ExportListItemsToStreamOptions => ({
callCluster: getCallClusterMock(getSearchListItemMock()),
esClient: elasticsearchClientMock.createScopedClusterClient().asCurrentUser,
listId: LIST_ID,
listItemIndex: LIST_ITEM_INDEX,
stream: new Stream.PassThrough(),
@ -26,7 +28,7 @@ export const getExportListItemsToStreamOptionsMock = (): ExportListItemsToStream
});
export const getWriteNextResponseOptions = (): WriteNextResponseOptions => ({
callCluster: getCallClusterMock(getSearchListItemMock()),
esClient: elasticsearchClientMock.createScopedClusterClient().asCurrentUser,
listId: LIST_ID,
listItemIndex: LIST_ITEM_INDEX,
searchAfter: [],
@ -35,7 +37,7 @@ export const getWriteNextResponseOptions = (): WriteNextResponseOptions => ({
});
export const getResponseOptionsMock = (): GetResponseOptions => ({
callCluster: getCallClusterMock(),
esClient: elasticsearchClientMock.createScopedClusterClient().asCurrentUser,
listId: LIST_ID,
listItemIndex: LIST_ITEM_INDEX,
searchAfter: [],

View file

@ -5,7 +5,9 @@
* 2.0.
*/
import { getCallClusterMock } from '../../../common/get_call_cluster.mock';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks';
import { CreateListOptions } from '../lists';
import {
DATE_NOW,
@ -22,10 +24,10 @@ import {
} from '../../../common/constants.mock';
export const getCreateListOptionsMock = (): CreateListOptions => ({
callCluster: getCallClusterMock(),
dateNow: DATE_NOW,
description: DESCRIPTION,
deserializer: undefined,
esClient: elasticsearchClientMock.createScopedClusterClient().asCurrentUser,
id: LIST_ID,
immutable: IMMUTABLE,
listIndex: LIST_INDEX,

View file

@ -5,6 +5,9 @@
* 2.0.
*/
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks';
import { ListSchema } from '../../../common/schemas';
import { getListResponseMock } from '../../../common/schemas/response/list_schema.mock';
import { getIndexESListMock } from '../../../common/schemas/elastic_query/index_es_list_schema.mock';
@ -24,7 +27,11 @@ describe('crete_list', () => {
test('it returns a list as expected with the id changed out for the elastic id', async () => {
const options = getCreateListOptionsMock();
const list = await createList(options);
const esClient = elasticsearchClientMock.createScopedClusterClient().asCurrentUser;
esClient.index.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise({ _id: 'elastic-id-123' })
);
const list = await createList({ ...options, esClient });
const expected: ListSchema = { ...getListResponseMock(), id: 'elastic-id-123' };
expect(list).toEqual(expected);
});
@ -35,7 +42,11 @@ describe('crete_list', () => {
deserializer: '{{value}}',
serializer: '(?<value>)',
};
const list = await createList(options);
const esClient = elasticsearchClientMock.createScopedClusterClient().asCurrentUser;
esClient.index.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise({ _id: 'elastic-id-123' })
);
const list = await createList({ ...options, esClient });
const expected: ListSchema = {
...getListResponseMock(),
deserializer: '{{value}}',
@ -45,7 +56,7 @@ describe('crete_list', () => {
expect(list).toEqual(expected);
});
test('It calls "callCluster" with body, index, and listIndex', async () => {
test('It calls "esClient" with body, index, and listIndex', async () => {
const options = getCreateListOptionsMock();
await createList(options);
const body = getIndexESListMock();
@ -55,13 +66,17 @@ describe('crete_list', () => {
index: LIST_INDEX,
refresh: 'wait_for',
};
expect(options.callCluster).toBeCalledWith('index', expected);
expect(options.esClient.index).toBeCalledWith(expected);
});
test('It returns an auto-generated id if id is sent in undefined', async () => {
const options = getCreateListOptionsMock();
options.id = undefined;
const list = await createList(options);
const esClient = elasticsearchClientMock.createScopedClusterClient().asCurrentUser;
esClient.index.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise({ _id: 'elastic-id-123' })
);
const list = await createList({ ...options, esClient });
const expected: ListSchema = { ...getListResponseMock(), id: 'elastic-id-123' };
expect(list).toEqual(expected);
});

View file

@ -7,7 +7,7 @@
import uuid from 'uuid';
import { CreateDocumentResponse } from 'elasticsearch';
import { LegacyAPICaller } from 'kibana/server';
import { ElasticsearchClient } from 'kibana/server';
import { encodeHitVersion } from '../utils/encode_hit_version';
import {
@ -31,7 +31,7 @@ export interface CreateListOptions {
type: Type;
name: Name;
description: Description;
callCluster: LegacyAPICaller;
esClient: ElasticsearchClient;
listIndex: string;
user: string;
meta: MetaOrUndefined;
@ -48,7 +48,7 @@ export const createList = async ({
name,
type,
description,
callCluster,
esClient,
listIndex,
user,
meta,
@ -73,7 +73,7 @@ export const createList = async ({
updated_by: user,
version,
};
const response = await callCluster<CreateDocumentResponse>('index', {
const { body: response } = await esClient.index<CreateDocumentResponse>({
body,
id,
index: listIndex,

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import { LegacyAPICaller } from 'kibana/server';
import { ElasticsearchClient } from 'kibana/server';
import {
Description,
@ -31,7 +31,7 @@ export interface CreateListIfItDoesNotExistOptions {
serializer: SerializerOrUndefined;
description: Description;
immutable: Immutable;
callCluster: LegacyAPICaller;
esClient: ElasticsearchClient;
listIndex: string;
user: string;
meta: MetaOrUndefined;
@ -46,7 +46,7 @@ export const createListIfItDoesNotExist = async ({
type,
description,
deserializer,
callCluster,
esClient,
listIndex,
user,
meta,
@ -56,13 +56,13 @@ export const createListIfItDoesNotExist = async ({
version,
immutable,
}: CreateListIfItDoesNotExistOptions): Promise<ListSchema> => {
const list = await getList({ callCluster, id, listIndex });
const list = await getList({ esClient, id, listIndex });
if (list == null) {
return createList({
callCluster,
dateNow,
description,
deserializer,
esClient,
id,
immutable,
listIndex,

View file

@ -5,12 +5,14 @@
* 2.0.
*/
import { getCallClusterMock } from '../../../common/get_call_cluster.mock';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks';
import { DeleteListOptions } from '../lists';
import { LIST_ID, LIST_INDEX, LIST_ITEM_INDEX } from '../../../common/constants.mock';
export const getDeleteListOptionsMock = (): DeleteListOptions => ({
callCluster: getCallClusterMock(),
esClient: elasticsearchClientMock.createScopedClusterClient().asCurrentUser,
id: LIST_ID,
listIndex: LIST_INDEX,
listItemIndex: LIST_ITEM_INDEX,

View file

@ -48,9 +48,9 @@ describe('delete_list', () => {
const deleteByQuery = {
body: { query: { term: { list_id: LIST_ID } } },
index: LIST_ITEM_INDEX,
refresh: 'wait_for',
refresh: false,
};
expect(options.callCluster).toBeCalledWith('deleteByQuery', deleteByQuery);
expect(options.esClient.deleteByQuery).toBeCalledWith(deleteByQuery);
});
test('Delete calls "delete" second if a list is returned from getList', async () => {
@ -61,15 +61,15 @@ describe('delete_list', () => {
const deleteQuery = {
id: LIST_ID,
index: LIST_INDEX,
refresh: 'wait_for',
refresh: false,
};
expect(options.callCluster).toHaveBeenNthCalledWith(2, 'delete', deleteQuery);
expect(options.esClient.delete).toHaveBeenNthCalledWith(1, deleteQuery);
});
test('Delete does not call data client if the list returns null', async () => {
((getList as unknown) as jest.Mock).mockResolvedValueOnce(null);
const options = getDeleteListOptionsMock();
await deleteList(options);
expect(options.callCluster).not.toHaveBeenCalled();
expect(options.esClient.delete).not.toHaveBeenCalled();
});
});

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import { LegacyAPICaller } from 'kibana/server';
import { ElasticsearchClient } from 'kibana/server';
import { Id, ListSchema } from '../../../common/schemas';
@ -13,22 +13,22 @@ import { getList } from './get_list';
export interface DeleteListOptions {
id: Id;
callCluster: LegacyAPICaller;
esClient: ElasticsearchClient;
listIndex: string;
listItemIndex: string;
}
export const deleteList = async ({
id,
callCluster,
esClient,
listIndex,
listItemIndex,
}: DeleteListOptions): Promise<ListSchema | null> => {
const list = await getList({ callCluster, id, listIndex });
const list = await getList({ esClient, id, listIndex });
if (list == null) {
return null;
} else {
await callCluster('deleteByQuery', {
await esClient.deleteByQuery({
body: {
query: {
term: {
@ -37,13 +37,13 @@ export const deleteList = async ({
},
},
index: listItemIndex,
refresh: 'wait_for',
refresh: false,
});
await callCluster('delete', {
await esClient.delete({
id,
index: listIndex,
refresh: 'wait_for',
refresh: false,
});
return list;
}

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import { LegacyAPICaller } from 'kibana/server';
import { ElasticsearchClient } from 'kibana/server';
import { SearchResponse } from 'elasticsearch';
import {
@ -34,12 +34,12 @@ interface FindListOptions {
page: Page;
sortField: SortFieldOrUndefined;
sortOrder: SortOrderOrUndefined;
callCluster: LegacyAPICaller;
esClient: ElasticsearchClient;
listIndex: string;
}
export const findList = async ({
callCluster,
esClient,
currentIndexPosition,
filter,
page,
@ -52,8 +52,8 @@ export const findList = async ({
const query = getQueryFilter({ filter });
const scroll = await scrollToStartPage({
callCluster,
currentIndexPosition,
esClient,
filter,
hopSize: 100,
index: listIndex,
@ -64,25 +64,25 @@ export const findList = async ({
sortOrder,
});
const { count } = await callCluster('count', {
const { body: totalCount } = await esClient.count({
body: {
query,
},
ignoreUnavailable: true,
ignore_unavailable: true,
index: listIndex,
});
if (scroll.validSearchAfterFound) {
// Note: This typing of response = await callCluster<SearchResponse<SearchEsListSchema>>
// Note: This typing of response = await esClient<SearchResponse<SearchEsListSchema>>
// is because when you pass in seq_no_primary_term: true it does a "fall through" type and you have
// to explicitly define the type <T>.
const response = await callCluster<SearchResponse<SearchEsListSchema>>('search', {
const { body: response } = await esClient.search<SearchResponse<SearchEsListSchema>>({
body: {
query,
search_after: scroll.searchAfter,
sort: getSortWithTieBreaker({ sortField, sortOrder }),
},
ignoreUnavailable: true,
ignore_unavailable: true,
index: listIndex,
seq_no_primary_term: true,
size: perPage,
@ -96,7 +96,7 @@ export const findList = async ({
data: transformElasticToList({ response }),
page,
per_page: perPage,
total: count,
total: totalCount.count,
};
} else {
return {
@ -104,7 +104,7 @@ export const findList = async ({
data: [],
page,
per_page: perPage,
total: count,
total: totalCount.count,
};
}
};

View file

@ -5,9 +5,11 @@
* 2.0.
*/
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks';
import { getSearchListMock } from '../../../common/schemas/elastic_response/search_es_list_schema.mock';
import { getListResponseMock } from '../../../common/schemas/response/list_schema.mock';
import { getCallClusterMock } from '../../../common/get_call_cluster.mock';
import { LIST_ID, LIST_INDEX } from '../../../common/constants.mock';
import { getList } from './get_list';
@ -23,8 +25,11 @@ describe('get_list', () => {
test('it returns a list as expected if the list is found', async () => {
const data = getSearchListMock();
const callCluster = getCallClusterMock(data);
const list = await getList({ callCluster, id: LIST_ID, listIndex: LIST_INDEX });
const esClient = elasticsearchClientMock.createScopedClusterClient().asCurrentUser;
esClient.search.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise(data)
);
const list = await getList({ esClient, id: LIST_ID, listIndex: LIST_INDEX });
const expected = getListResponseMock();
expect(list).toEqual(expected);
});
@ -32,8 +37,11 @@ describe('get_list', () => {
test('it returns null if the search is empty', async () => {
const data = getSearchListMock();
data.hits.hits = [];
const callCluster = getCallClusterMock(data);
const list = await getList({ callCluster, id: LIST_ID, listIndex: LIST_INDEX });
const esClient = elasticsearchClientMock.createScopedClusterClient().asCurrentUser;
esClient.search.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise(data)
);
const list = await getList({ esClient, id: LIST_ID, listIndex: LIST_INDEX });
expect(list).toEqual(null);
});
});

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import { LegacyAPICaller } from 'kibana/server';
import { ElasticsearchClient } from 'kibana/server';
import { SearchResponse } from 'elasticsearch';
import { Id, ListSchema, SearchEsListSchema } from '../../../common/schemas';
@ -13,19 +13,19 @@ import { transformElasticToList } from '../utils/transform_elastic_to_list';
interface GetListOptions {
id: Id;
callCluster: LegacyAPICaller;
esClient: ElasticsearchClient;
listIndex: string;
}
export const getList = async ({
id,
callCluster,
esClient,
listIndex,
}: GetListOptions): Promise<ListSchema | null> => {
// Note: This typing of response = await callCluster<SearchResponse<SearchEsListSchema>>
// Note: This typing of response = await esClient<SearchResponse<SearchEsListSchema>>
// is because when you pass in seq_no_primary_term: true it does a "fall through" type and you have
// to explicitly define the type <T>.
const response = await callCluster<SearchResponse<SearchEsListSchema>>('search', {
const { body: response } = await esClient.search<SearchResponse<SearchEsListSchema>>({
body: {
query: {
term: {
@ -33,7 +33,7 @@ export const getList = async ({
},
},
},
ignoreUnavailable: true,
ignore_unavailable: true,
index: listIndex,
seq_no_primary_term: true,
});

View file

@ -5,11 +5,13 @@
* 2.0.
*/
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks';
import { getFoundListItemSchemaMock } from '../../../common/schemas/response/found_list_item_schema.mock';
import { getFoundListSchemaMock } from '../../../common/schemas/response/found_list_schema.mock';
import { getListItemResponseMock } from '../../../common/schemas/response/list_item_schema.mock';
import { getListResponseMock } from '../../../common/schemas/response/list_schema.mock';
import { getCallClusterMock } from '../../../common/get_call_cluster.mock';
import {
IMPORT_BUFFER_SIZE,
IMPORT_TIMEOUT,
@ -63,7 +65,6 @@ export class ListClientMock extends ListClient {
export const getListClientMock = (): ListClient => {
const mock = new ListClientMock({
callCluster: getCallClusterMock(),
config: {
enabled: true,
importBufferSize: IMPORT_BUFFER_SIZE,
@ -72,6 +73,7 @@ export const getListClientMock = (): ListClient => {
listItemIndex: LIST_ITEM_INDEX,
maxImportPayloadBytes: MAX_IMPORT_PAYLOAD_BYTES,
},
esClient: elasticsearchClientMock.createScopedClusterClient().asCurrentUser,
spaceId: 'default',
user: 'elastic',
});

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import { LegacyAPICaller } from 'kibana/server';
import { ElasticsearchClient } from 'kibana/server';
import {
FoundListItemSchema,
@ -80,13 +80,13 @@ export class ListClient {
private readonly spaceId: string;
private readonly user: string;
private readonly config: ConfigType;
private readonly callCluster: LegacyAPICaller;
private readonly esClient: ElasticsearchClient;
constructor({ spaceId, user, config, callCluster }: ConstructorOptions) {
constructor({ spaceId, user, config, esClient }: ConstructorOptions) {
this.spaceId = spaceId;
this.user = user;
this.config = config;
this.callCluster = callCluster;
this.esClient = esClient;
}
public getListIndex = (): string => {
@ -106,9 +106,9 @@ export class ListClient {
};
public getList = async ({ id }: GetListOptions): Promise<ListSchema | null> => {
const { callCluster } = this;
const { esClient } = this;
const listIndex = this.getListIndex();
return getList({ callCluster, id, listIndex });
return getList({ esClient, id, listIndex });
};
public createList = async ({
@ -122,12 +122,12 @@ export class ListClient {
meta,
version,
}: CreateListOptions): Promise<ListSchema> => {
const { callCluster, user } = this;
const { esClient, user } = this;
const listIndex = this.getListIndex();
return createList({
callCluster,
description,
deserializer,
esClient,
id,
immutable,
listIndex,
@ -151,12 +151,12 @@ export class ListClient {
meta,
version,
}: CreateListIfItDoesNotExistOptions): Promise<ListSchema> => {
const { callCluster, user } = this;
const { esClient, user } = this;
const listIndex = this.getListIndex();
return createListIfItDoesNotExist({
callCluster,
description,
deserializer,
esClient,
id,
immutable,
listIndex,
@ -170,51 +170,51 @@ export class ListClient {
};
public getListIndexExists = async (): Promise<boolean> => {
const { callCluster } = this;
const { esClient } = this;
const listIndex = this.getListIndex();
return getIndexExists(callCluster, listIndex);
return getIndexExists(esClient, listIndex);
};
public getListItemIndexExists = async (): Promise<boolean> => {
const { callCluster } = this;
const { esClient } = this;
const listItemIndex = this.getListItemIndex();
return getIndexExists(callCluster, listItemIndex);
return getIndexExists(esClient, listItemIndex);
};
public createListBootStrapIndex = async (): Promise<unknown> => {
const { callCluster } = this;
const { esClient } = this;
const listIndex = this.getListIndex();
return createBootstrapIndex(callCluster, listIndex);
return createBootstrapIndex(esClient, listIndex);
};
public createListItemBootStrapIndex = async (): Promise<unknown> => {
const { callCluster } = this;
const { esClient } = this;
const listItemIndex = this.getListItemIndex();
return createBootstrapIndex(callCluster, listItemIndex);
return createBootstrapIndex(esClient, listItemIndex);
};
public getListPolicyExists = async (): Promise<boolean> => {
const { callCluster } = this;
const { esClient } = this;
const listIndex = this.getListIndex();
return getPolicyExists(callCluster, listIndex);
return getPolicyExists(esClient, listIndex);
};
public getListItemPolicyExists = async (): Promise<boolean> => {
const { callCluster } = this;
const { esClient } = this;
const listsItemIndex = this.getListItemIndex();
return getPolicyExists(callCluster, listsItemIndex);
return getPolicyExists(esClient, listsItemIndex);
};
public getListTemplateExists = async (): Promise<boolean> => {
const { callCluster } = this;
const { esClient } = this;
const listIndex = this.getListIndex();
return getTemplateExists(callCluster, listIndex);
return getTemplateExists(esClient, listIndex);
};
public getListItemTemplateExists = async (): Promise<boolean> => {
const { callCluster } = this;
const { esClient } = this;
const listItemIndex = this.getListItemIndex();
return getTemplateExists(callCluster, listItemIndex);
return getTemplateExists(esClient, listItemIndex);
};
public getListTemplate = (): Record<string, unknown> => {
@ -228,71 +228,71 @@ export class ListClient {
};
public setListTemplate = async (): Promise<unknown> => {
const { callCluster } = this;
const { esClient } = this;
const template = this.getListTemplate();
const listIndex = this.getListIndex();
return setTemplate(callCluster, listIndex, template);
return setTemplate(esClient, listIndex, template);
};
public setListItemTemplate = async (): Promise<unknown> => {
const { callCluster } = this;
const { esClient } = this;
const template = this.getListItemTemplate();
const listItemIndex = this.getListItemIndex();
return setTemplate(callCluster, listItemIndex, template);
return setTemplate(esClient, listItemIndex, template);
};
public setListPolicy = async (): Promise<unknown> => {
const { callCluster } = this;
const { esClient } = this;
const listIndex = this.getListIndex();
return setPolicy(callCluster, listIndex, listPolicy);
return setPolicy(esClient, listIndex, listPolicy);
};
public setListItemPolicy = async (): Promise<unknown> => {
const { callCluster } = this;
const { esClient } = this;
const listItemIndex = this.getListItemIndex();
return setPolicy(callCluster, listItemIndex, listsItemsPolicy);
return setPolicy(esClient, listItemIndex, listsItemsPolicy);
};
public deleteListIndex = async (): Promise<boolean> => {
const { callCluster } = this;
const { esClient } = this;
const listIndex = this.getListIndex();
return deleteAllIndex(callCluster, `${listIndex}-*`);
return deleteAllIndex(esClient, `${listIndex}-*`);
};
public deleteListItemIndex = async (): Promise<boolean> => {
const { callCluster } = this;
const { esClient } = this;
const listItemIndex = this.getListItemIndex();
return deleteAllIndex(callCluster, `${listItemIndex}-*`);
return deleteAllIndex(esClient, `${listItemIndex}-*`);
};
public deleteListPolicy = async (): Promise<unknown> => {
const { callCluster } = this;
const { esClient } = this;
const listIndex = this.getListIndex();
return deletePolicy(callCluster, listIndex);
return deletePolicy(esClient, listIndex);
};
public deleteListItemPolicy = async (): Promise<unknown> => {
const { callCluster } = this;
const { esClient } = this;
const listItemIndex = this.getListItemIndex();
return deletePolicy(callCluster, listItemIndex);
return deletePolicy(esClient, listItemIndex);
};
public deleteListTemplate = async (): Promise<unknown> => {
const { callCluster } = this;
const { esClient } = this;
const listIndex = this.getListIndex();
return deleteTemplate(callCluster, listIndex);
return deleteTemplate(esClient, listIndex);
};
public deleteListItemTemplate = async (): Promise<unknown> => {
const { callCluster } = this;
const { esClient } = this;
const listItemIndex = this.getListItemIndex();
return deleteTemplate(callCluster, listItemIndex);
return deleteTemplate(esClient, listItemIndex);
};
public deleteListItem = async ({ id }: DeleteListItemOptions): Promise<ListItemSchema | null> => {
const { callCluster } = this;
const { esClient } = this;
const listItemIndex = this.getListItemIndex();
return deleteListItem({ callCluster, id, listItemIndex });
return deleteListItem({ esClient, id, listItemIndex });
};
public deleteListItemByValue = async ({
@ -300,10 +300,10 @@ export class ListClient {
value,
type,
}: DeleteListItemByValueOptions): Promise<ListItemArraySchema> => {
const { callCluster } = this;
const { esClient } = this;
const listItemIndex = this.getListItemIndex();
return deleteListItemByValue({
callCluster,
esClient,
listId,
listItemIndex,
type,
@ -312,11 +312,11 @@ export class ListClient {
};
public deleteList = async ({ id }: DeleteListOptions): Promise<ListSchema | null> => {
const { callCluster } = this;
const { esClient } = this;
const listIndex = this.getListIndex();
const listItemIndex = this.getListItemIndex();
return deleteList({
callCluster,
esClient,
id,
listIndex,
listItemIndex,
@ -328,10 +328,10 @@ export class ListClient {
listId,
stream,
}: ExportListItemsToStreamOptions): void => {
const { callCluster } = this;
const { esClient } = this;
const listItemIndex = this.getListItemIndex();
exportListItemsToStream({
callCluster,
esClient,
listId,
listItemIndex,
stream,
@ -348,13 +348,13 @@ export class ListClient {
meta,
version,
}: ImportListItemsToStreamOptions): Promise<ListSchema | null> => {
const { callCluster, user, config } = this;
const { esClient, user, config } = this;
const listItemIndex = this.getListItemIndex();
const listIndex = this.getListIndex();
return importListItemsToStream({
callCluster,
config,
deserializer,
esClient,
listId,
listIndex,
listItemIndex,
@ -372,10 +372,10 @@ export class ListClient {
value,
type,
}: GetListItemByValueOptions): Promise<ListItemArraySchema> => {
const { callCluster } = this;
const { esClient } = this;
const listItemIndex = this.getListItemIndex();
return getListItemByValue({
callCluster,
esClient,
listId,
listItemIndex,
type,
@ -392,11 +392,11 @@ export class ListClient {
type,
meta,
}: CreateListItemOptions): Promise<ListItemSchema | null> => {
const { callCluster, user } = this;
const { esClient, user } = this;
const listItemIndex = this.getListItemIndex();
return createListItem({
callCluster,
deserializer,
esClient,
id,
listId,
listItemIndex,
@ -414,11 +414,11 @@ export class ListClient {
value,
meta,
}: UpdateListItemOptions): Promise<ListItemSchema | null> => {
const { callCluster, user } = this;
const { esClient, user } = this;
const listItemIndex = this.getListItemIndex();
return updateListItem({
_version,
callCluster,
esClient,
id,
listItemIndex,
meta,
@ -435,12 +435,12 @@ export class ListClient {
meta,
version,
}: UpdateListOptions): Promise<ListSchema | null> => {
const { callCluster, user } = this;
const { esClient, user } = this;
const listIndex = this.getListIndex();
return updateList({
_version,
callCluster,
description,
esClient,
id,
listIndex,
meta,
@ -451,10 +451,10 @@ export class ListClient {
};
public getListItem = async ({ id }: GetListItemOptions): Promise<ListItemSchema | null> => {
const { callCluster } = this;
const { esClient } = this;
const listItemIndex = this.getListItemIndex();
return getListItem({
callCluster,
esClient,
id,
listItemIndex,
});
@ -465,10 +465,10 @@ export class ListClient {
listId,
value,
}: GetListItemsByValueOptions): Promise<ListItemArraySchema> => {
const { callCluster } = this;
const { esClient } = this;
const listItemIndex = this.getListItemIndex();
return getListItemByValues({
callCluster,
esClient,
listId,
listItemIndex,
type,
@ -481,10 +481,10 @@ export class ListClient {
listId,
value,
}: SearchListItemByValuesOptions): Promise<SearchListItemArraySchema> => {
const { callCluster } = this;
const { esClient } = this;
const listItemIndex = this.getListItemIndex();
return searchListItemByValues({
callCluster,
esClient,
listId,
listItemIndex,
type,
@ -501,11 +501,11 @@ export class ListClient {
sortOrder,
searchAfter,
}: FindListOptions): Promise<FoundListSchema> => {
const { callCluster } = this;
const { esClient } = this;
const listIndex = this.getListIndex();
return findList({
callCluster,
currentIndexPosition,
esClient,
filter,
listIndex,
page,
@ -526,12 +526,12 @@ export class ListClient {
sortOrder,
searchAfter,
}: FindListItemOptions): Promise<FoundListItemSchema | null> => {
const { callCluster } = this;
const { esClient } = this;
const listIndex = this.getListIndex();
const listItemIndex = this.getListItemIndex();
return findListItem({
callCluster,
currentIndexPosition,
esClient,
filter,
listId,
listIndex,

View file

@ -7,7 +7,7 @@
import { PassThrough, Readable } from 'stream';
import { LegacyAPICaller } from 'kibana/server';
import { ElasticsearchClient } from 'kibana/server';
import {
Description,
@ -35,7 +35,7 @@ import {
import { ConfigType } from '../../config';
export interface ConstructorOptions {
callCluster: LegacyAPICaller;
esClient: ElasticsearchClient;
config: ConfigType;
spaceId: string;
user: string;

View file

@ -5,7 +5,9 @@
* 2.0.
*/
import { getCallClusterMock } from '../../../common/get_call_cluster.mock';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks';
import { UpdateListOptions } from '../lists';
import {
DATE_NOW,
@ -20,9 +22,9 @@ import {
export const getUpdateListOptionsMock = (): UpdateListOptions => ({
_version: undefined,
callCluster: getCallClusterMock(),
dateNow: DATE_NOW,
description: DESCRIPTION,
esClient: elasticsearchClientMock.createScopedClusterClient().asCurrentUser,
id: LIST_ID,
listIndex: LIST_INDEX,
meta: META,

View file

@ -5,6 +5,9 @@
* 2.0.
*/
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks';
import { ListSchema } from '../../../common/schemas';
import { getListResponseMock } from '../../../common/schemas/response/list_schema.mock';
@ -29,7 +32,11 @@ describe('update_list', () => {
const list = getListResponseMock();
((getList as unknown) as jest.Mock).mockResolvedValueOnce(list);
const options = getUpdateListOptionsMock();
const updatedList = await updateList(options);
const esClient = elasticsearchClientMock.createScopedClusterClient().asCurrentUser;
esClient.update.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise({ _id: 'elastic-id-123' })
);
const updatedList = await updateList({ ...options, esClient });
const expected: ListSchema = { ...getListResponseMock(), id: 'elastic-id-123' };
expect(updatedList).toEqual(expected);
});
@ -42,7 +49,11 @@ describe('update_list', () => {
};
((getList as unknown) as jest.Mock).mockResolvedValueOnce(list);
const options = getUpdateListOptionsMock();
const updatedList = await updateList(options);
const esClient = elasticsearchClientMock.createScopedClusterClient().asCurrentUser;
esClient.update.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise({ _id: 'elastic-id-123' })
);
const updatedList = await updateList({ ...options, esClient });
const expected: ListSchema = {
...getListResponseMock(),
deserializer: '{{value}}',

View file

@ -6,7 +6,7 @@
*/
import { CreateDocumentResponse } from 'elasticsearch';
import { LegacyAPICaller } from 'kibana/server';
import { ElasticsearchClient } from 'kibana/server';
import { decodeVersion } from '../utils/decode_version';
import { encodeHitVersion } from '../utils/encode_hit_version';
@ -26,7 +26,7 @@ import { getList } from '.';
export interface UpdateListOptions {
_version: _VersionOrUndefined;
id: Id;
callCluster: LegacyAPICaller;
esClient: ElasticsearchClient;
listIndex: string;
user: string;
name: NameOrUndefined;
@ -41,7 +41,7 @@ export const updateList = async ({
id,
name,
description,
callCluster,
esClient,
listIndex,
user,
meta,
@ -49,7 +49,7 @@ export const updateList = async ({
version,
}: UpdateListOptions): Promise<ListSchema | null> => {
const updatedAt = dateNow ?? new Date().toISOString();
const list = await getList({ callCluster, id, listIndex });
const list = await getList({ esClient, id, listIndex });
if (list == null) {
return null;
} else {
@ -61,7 +61,7 @@ export const updateList = async ({
updated_at: updatedAt,
updated_by: user,
};
const response = await callCluster<CreateDocumentResponse>('update', {
const { body: response } = await esClient.update<CreateDocumentResponse>({
...decodeVersion(_version),
body: { doc },
id,

View file

@ -5,7 +5,8 @@
* 2.0.
*/
import { LegacyAPICaller } from 'kibana/server';
import { ElasticsearchClient } from 'kibana/server';
import { SearchResponse } from 'elasticsearch';
import { Filter, SortFieldOrUndefined, SortOrderOrUndefined } from '../../../common/schemas';
import { Scroll } from '../lists/types';
@ -16,7 +17,7 @@ import { getSourceWithTieBreaker } from './get_source_with_tie_breaker';
import { TieBreaker, getSearchAfterWithTieBreaker } from './get_search_after_with_tie_breaker';
interface GetSearchAfterOptions {
callCluster: LegacyAPICaller;
esClient: ElasticsearchClient;
filter: Filter;
hops: number;
hopSize: number;
@ -27,7 +28,7 @@ interface GetSearchAfterOptions {
}
export const getSearchAfterScroll = async <T>({
callCluster,
esClient,
filter,
hopSize,
hops,
@ -39,14 +40,14 @@ export const getSearchAfterScroll = async <T>({
const query = getQueryFilter({ filter });
let newSearchAfter = searchAfter;
for (let i = 0; i < hops; ++i) {
const response = await callCluster<TieBreaker<T>>('search', {
const { body: response } = await esClient.search<SearchResponse<TieBreaker<T>>>({
body: {
_source: getSourceWithTieBreaker({ sortField }),
query,
search_after: newSearchAfter,
sort: getSortWithTieBreaker({ sortField, sortOrder }),
},
ignoreUnavailable: true,
ignore_unavailable: true,
index,
size: hopSize,
});

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import { LegacyAPICaller } from 'kibana/server';
import { ElasticsearchClient } from 'kibana/server';
import { Filter, SortFieldOrUndefined, SortOrderOrUndefined } from '../../../common/schemas';
import { Scroll } from '../lists/types';
@ -14,7 +14,7 @@ import { calculateScrollMath } from './calculate_scroll_math';
import { getSearchAfterScroll } from './get_search_after_scroll';
interface ScrollToStartPageOptions {
callCluster: LegacyAPICaller;
esClient: ElasticsearchClient;
filter: Filter;
sortField: SortFieldOrUndefined;
sortOrder: SortOrderOrUndefined;
@ -27,7 +27,7 @@ interface ScrollToStartPageOptions {
}
export const scrollToStartPage = async ({
callCluster,
esClient,
filter,
hopSize,
currentIndexPosition,
@ -58,7 +58,7 @@ export const scrollToStartPage = async ({
};
} else if (hops > 0) {
const scroll = await getSearchAfterScroll({
callCluster,
esClient,
filter,
hopSize,
hops,
@ -69,7 +69,7 @@ export const scrollToStartPage = async ({
});
if (scroll.validSearchAfterFound && leftOverAfterHops > 0) {
return getSearchAfterScroll({
callCluster,
esClient,
filter,
hopSize: leftOverAfterHops,
hops: 1,
@ -83,7 +83,7 @@ export const scrollToStartPage = async ({
}
} else {
return getSearchAfterScroll({
callCluster,
esClient,
filter,
hopSize: leftOverAfterHops,
hops: 1,

View file

@ -6,9 +6,9 @@
*/
import {
ElasticsearchClient,
IContextProvider,
IRouter,
LegacyAPICaller,
RequestHandlerContext,
SavedObjectsClientContract,
} from 'kibana/server';
@ -27,7 +27,7 @@ export interface PluginsStart {
}
export type GetListClientType = (
dataClient: LegacyAPICaller,
esClient: ElasticsearchClient,
spaceId: string,
user: string
) => ListClient;

View file

@ -5,7 +5,7 @@
* 2.0.
*/
import { Logger, LegacyCallAPIOptions } from 'kibana/server';
import { Logger, ElasticsearchClient } from 'kibana/server';
import { i18n } from '@kbn/i18n';
import {
AlertType,
@ -32,7 +32,6 @@ import { fetchClusters } from '../lib/alerts/fetch_clusters';
import { getCcsIndexPattern } from '../lib/alerts/get_ccs_index_pattern';
import { INDEX_PATTERN_ELASTICSEARCH } from '../../common/constants';
import { AlertSeverity } from '../../common/enums';
import { mbSafeQuery } from '../lib/mb_safe_query';
import { appendMetricbeatIndex } from '../lib/alerts/append_mb_index';
import { parseDuration } from '../../../alerting/common/parse_duration';
import { Globals } from '../static_globals';
@ -56,12 +55,6 @@ interface AlertOptions {
accessorKey?: string;
}
type CallCluster = (
endpoint: string,
clientParams?: Record<string, unknown> | undefined,
options?: LegacyCallAPIOptions | undefined
) => Promise<any>;
const defaultAlertOptions = (): AlertOptions => {
return {
id: '',
@ -233,29 +226,15 @@ export class BaseAlert {
`Executing alert with params: ${JSON.stringify(params)} and state: ${JSON.stringify(state)}`
);
const useCallCluster =
Globals.app.monitoringCluster?.callAsInternalUser || services.callCluster;
const callCluster = async (
endpoint: string,
clientParams?: Record<string, unknown>,
options?: LegacyCallAPIOptions
) => {
return await mbSafeQuery(async () => useCallCluster(endpoint, clientParams, options));
};
const availableCcs = Globals.app.config.ui.ccs.enabled
? await fetchAvailableCcs(callCluster)
: [];
const clusters = await this.fetchClusters(
callCluster,
params as CommonAlertParams,
availableCcs
);
const data = await this.fetchData(params, callCluster, clusters, availableCcs);
const esClient = services.scopedClusterClient.asCurrentUser;
const availableCcs = Globals.app.config.ui.ccs.enabled ? await fetchAvailableCcs(esClient) : [];
const clusters = await this.fetchClusters(esClient, params as CommonAlertParams, availableCcs);
const data = await this.fetchData(params, esClient, clusters, availableCcs);
return await this.processData(data, clusters, services, state);
}
protected async fetchClusters(
callCluster: CallCluster,
esClient: ElasticsearchClient,
params: CommonAlertParams,
ccs?: string[]
) {
@ -264,7 +243,7 @@ export class BaseAlert {
esIndexPattern = getCcsIndexPattern(esIndexPattern, ccs);
}
if (!params.limit) {
return await fetchClusters(callCluster, esIndexPattern);
return await fetchClusters(esClient, esIndexPattern);
}
const limit = parseDuration(params.limit);
const rangeFilter = this.alertOptions.fetchClustersRange
@ -275,12 +254,12 @@ export class BaseAlert {
},
}
: undefined;
return await fetchClusters(callCluster, esIndexPattern, rangeFilter);
return await fetchClusters(esClient, esIndexPattern, rangeFilter);
}
protected async fetchData(
params: CommonAlertParams | unknown,
callCluster: CallCluster,
esClient: ElasticsearchClient,
clusters: AlertCluster[],
availableCcs: string[]
): Promise<Array<AlertData & unknown>> {

View file

@ -6,6 +6,7 @@
*/
import { i18n } from '@kbn/i18n';
import { ElasticsearchClient } from 'kibana/server';
import { BaseAlert } from './base_alert';
import {
AlertData,
@ -70,7 +71,7 @@ export class CCRReadExceptionsAlert extends BaseAlert {
protected async fetchData(
params: CommonAlertParams,
callCluster: any,
esClient: ElasticsearchClient,
clusters: AlertCluster[],
availableCcs: string[]
): Promise<AlertData[]> {
@ -83,7 +84,7 @@ export class CCRReadExceptionsAlert extends BaseAlert {
const endMs = +new Date();
const startMs = endMs - duration;
const stats = await fetchCCRReadExceptions(
callCluster,
esClient,
esIndexPattern,
startMs,
endMs,

View file

@ -10,6 +10,7 @@ import { ALERT_CLUSTER_HEALTH } from '../../common/constants';
import { AlertClusterHealthType, AlertSeverity } from '../../common/enums';
import { fetchClusterHealth } from '../lib/alerts/fetch_cluster_health';
import { fetchClusters } from '../lib/alerts/fetch_clusters';
import { elasticsearchServiceMock } from 'src/core/server/mocks';
const RealDate = Date;
@ -80,7 +81,7 @@ describe('ClusterHealthAlert', () => {
const getState = jest.fn();
const executorOptions = {
services: {
callCluster: jest.fn(),
scopedClusterClient: elasticsearchServiceMock.createScopedClusterClient(),
alertInstanceFactory: jest.fn().mockImplementation(() => {
return {
replaceState,

View file

@ -6,6 +6,7 @@
*/
import { i18n } from '@kbn/i18n';
import { ElasticsearchClient } from 'kibana/server';
import { BaseAlert } from './base_alert';
import {
AlertData,
@ -64,7 +65,7 @@ export class ClusterHealthAlert extends BaseAlert {
protected async fetchData(
params: CommonAlertParams,
callCluster: any,
esClient: ElasticsearchClient,
clusters: AlertCluster[],
availableCcs: string[]
): Promise<AlertData[]> {
@ -72,7 +73,7 @@ export class ClusterHealthAlert extends BaseAlert {
if (availableCcs) {
esIndexPattern = getCcsIndexPattern(esIndexPattern, availableCcs);
}
const healths = await fetchClusterHealth(callCluster, clusters, esIndexPattern);
const healths = await fetchClusterHealth(esClient, clusters, esIndexPattern);
return healths.map((clusterHealth) => {
const shouldFire = clusterHealth.health !== AlertClusterHealthType.Green;
const severity =

View file

@ -9,6 +9,7 @@ import { CpuUsageAlert } from './cpu_usage_alert';
import { ALERT_CPU_USAGE } from '../../common/constants';
import { fetchCpuUsageNodeStats } from '../lib/alerts/fetch_cpu_usage_node_stats';
import { fetchClusters } from '../lib/alerts/fetch_clusters';
import { elasticsearchServiceMock } from 'src/core/server/mocks';
const RealDate = Date;
@ -83,7 +84,7 @@ describe('CpuUsageAlert', () => {
const getState = jest.fn();
const executorOptions = {
services: {
callCluster: jest.fn(),
scopedClusterClient: elasticsearchServiceMock.createScopedClusterClient(),
alertInstanceFactory: jest.fn().mockImplementation(() => {
return {
replaceState,

View file

@ -7,6 +7,7 @@
import { i18n } from '@kbn/i18n';
import numeral from '@elastic/numeral';
import { ElasticsearchClient } from 'kibana/server';
import { BaseAlert } from './base_alert';
import {
AlertData,
@ -68,7 +69,7 @@ export class CpuUsageAlert extends BaseAlert {
protected async fetchData(
params: CommonAlertParams,
callCluster: any,
esClient: ElasticsearchClient,
clusters: AlertCluster[],
availableCcs: string[]
): Promise<AlertData[]> {
@ -80,7 +81,7 @@ export class CpuUsageAlert extends BaseAlert {
const endMs = +new Date();
const startMs = endMs - duration;
const stats = await fetchCpuUsageNodeStats(
callCluster,
esClient,
clusters,
esIndexPattern,
startMs,

View file

@ -9,6 +9,7 @@ import { DiskUsageAlert } from './disk_usage_alert';
import { ALERT_DISK_USAGE } from '../../common/constants';
import { fetchDiskUsageNodeStats } from '../lib/alerts/fetch_disk_usage_node_stats';
import { fetchClusters } from '../lib/alerts/fetch_clusters';
import { elasticsearchServiceMock } from 'src/core/server/mocks';
type IDiskUsageAlertMock = DiskUsageAlert & {
defaultParams: {
@ -95,7 +96,7 @@ describe('DiskUsageAlert', () => {
const getState = jest.fn();
const executorOptions = {
services: {
callCluster: jest.fn(),
scopedClusterClient: elasticsearchServiceMock.createScopedClusterClient(),
alertInstanceFactory: jest.fn().mockImplementation(() => {
return {
replaceState,

View file

@ -7,6 +7,7 @@
import { i18n } from '@kbn/i18n';
import numeral from '@elastic/numeral';
import { ElasticsearchClient } from 'kibana/server';
import { BaseAlert } from './base_alert';
import {
AlertData,
@ -67,7 +68,7 @@ export class DiskUsageAlert extends BaseAlert {
protected async fetchData(
params: CommonAlertParams,
callCluster: any,
esClient: ElasticsearchClient,
clusters: AlertCluster[],
availableCcs: string[]
): Promise<AlertData[]> {
@ -77,7 +78,7 @@ export class DiskUsageAlert extends BaseAlert {
}
const { duration, threshold } = params;
const stats = await fetchDiskUsageNodeStats(
callCluster,
esClient,
clusters,
esIndexPattern,
duration as string,

View file

@ -9,6 +9,7 @@ import { ElasticsearchVersionMismatchAlert } from './elasticsearch_version_misma
import { ALERT_ELASTICSEARCH_VERSION_MISMATCH } from '../../common/constants';
import { fetchElasticsearchVersions } from '../lib/alerts/fetch_elasticsearch_versions';
import { fetchClusters } from '../lib/alerts/fetch_clusters';
import { elasticsearchServiceMock } from 'src/core/server/mocks';
const RealDate = Date;
@ -84,7 +85,7 @@ describe('ElasticsearchVersionMismatchAlert', () => {
const getState = jest.fn();
const executorOptions = {
services: {
callCluster: jest.fn(),
scopedClusterClient: elasticsearchServiceMock.createScopedClusterClient(),
alertInstanceFactory: jest.fn().mockImplementation(() => {
return {
replaceState,

View file

@ -6,6 +6,7 @@
*/
import { i18n } from '@kbn/i18n';
import { ElasticsearchClient } from 'kibana/server';
import { BaseAlert } from './base_alert';
import {
AlertData,
@ -53,7 +54,7 @@ export class ElasticsearchVersionMismatchAlert extends BaseAlert {
protected async fetchData(
params: CommonAlertParams,
callCluster: any,
esClient: ElasticsearchClient,
clusters: AlertCluster[],
availableCcs: string[]
): Promise<AlertData[]> {
@ -62,7 +63,7 @@ export class ElasticsearchVersionMismatchAlert extends BaseAlert {
esIndexPattern = getCcsIndexPattern(esIndexPattern, availableCcs);
}
const elasticsearchVersions = await fetchElasticsearchVersions(
callCluster,
esClient,
clusters,
esIndexPattern,
Globals.app.config.ui.max_bucket_size

View file

@ -9,6 +9,7 @@ import { KibanaVersionMismatchAlert } from './kibana_version_mismatch_alert';
import { ALERT_KIBANA_VERSION_MISMATCH } from '../../common/constants';
import { fetchKibanaVersions } from '../lib/alerts/fetch_kibana_versions';
import { fetchClusters } from '../lib/alerts/fetch_clusters';
import { elasticsearchServiceMock } from 'src/core/server/mocks';
const RealDate = Date;
@ -87,7 +88,7 @@ describe('KibanaVersionMismatchAlert', () => {
const getState = jest.fn();
const executorOptions = {
services: {
callCluster: jest.fn(),
scopedClusterClient: elasticsearchServiceMock.createScopedClusterClient(),
alertInstanceFactory: jest.fn().mockImplementation(() => {
return {
replaceState,

View file

@ -6,6 +6,7 @@
*/
import { i18n } from '@kbn/i18n';
import { ElasticsearchClient } from 'kibana/server';
import { BaseAlert } from './base_alert';
import {
AlertData,
@ -66,7 +67,7 @@ export class KibanaVersionMismatchAlert extends BaseAlert {
protected async fetchData(
params: CommonAlertParams,
callCluster: any,
esClient: ElasticsearchClient,
clusters: AlertCluster[],
availableCcs: string[]
): Promise<AlertData[]> {
@ -75,7 +76,7 @@ export class KibanaVersionMismatchAlert extends BaseAlert {
kibanaIndexPattern = getCcsIndexPattern(kibanaIndexPattern, availableCcs);
}
const kibanaVersions = await fetchKibanaVersions(
callCluster,
esClient,
clusters,
kibanaIndexPattern,
Globals.app.config.ui.max_bucket_size

View file

@ -6,6 +6,7 @@
*/
import { i18n } from '@kbn/i18n';
import { ElasticsearchClient } from 'kibana/server';
import { BaseAlert } from './base_alert';
import {
AlertData,
@ -59,7 +60,7 @@ export class LargeShardSizeAlert extends BaseAlert {
protected async fetchData(
params: CommonAlertParams & { indexPattern: string },
callCluster: any,
esClient: ElasticsearchClient,
clusters: AlertCluster[],
availableCcs: string[]
): Promise<AlertData[]> {
@ -70,7 +71,7 @@ export class LargeShardSizeAlert extends BaseAlert {
const { threshold, indexPattern: shardIndexPatterns } = params;
const stats = await fetchIndexShardSize(
callCluster,
esClient,
clusters,
esIndexPattern,
threshold!,

View file

@ -10,6 +10,7 @@ import { ALERT_LICENSE_EXPIRATION } from '../../common/constants';
import { AlertSeverity } from '../../common/enums';
import { fetchLicenses } from '../lib/alerts/fetch_licenses';
import { fetchClusters } from '../lib/alerts/fetch_clusters';
import { elasticsearchServiceMock } from 'src/core/server/mocks';
const RealDate = Date;
@ -85,7 +86,7 @@ describe('LicenseExpirationAlert', () => {
const getState = jest.fn();
const executorOptions = {
services: {
callCluster: jest.fn(),
scopedClusterClient: elasticsearchServiceMock.createScopedClusterClient(),
alertInstanceFactory: jest.fn().mockImplementation(() => {
return {
replaceState,

View file

@ -6,6 +6,7 @@
*/
import moment from 'moment';
import { i18n } from '@kbn/i18n';
import { ElasticsearchClient } from 'kibana/server';
import { BaseAlert } from './base_alert';
import {
AlertData,
@ -78,7 +79,7 @@ export class LicenseExpirationAlert extends BaseAlert {
protected async fetchData(
params: CommonAlertParams,
callCluster: any,
esClient: ElasticsearchClient,
clusters: AlertCluster[],
availableCcs: string[]
): Promise<AlertData[]> {
@ -86,7 +87,7 @@ export class LicenseExpirationAlert extends BaseAlert {
if (availableCcs) {
esIndexPattern = getCcsIndexPattern(esIndexPattern, availableCcs);
}
const licenses = await fetchLicenses(callCluster, clusters, esIndexPattern);
const licenses = await fetchLicenses(esClient, clusters, esIndexPattern);
return licenses.map((license) => {
const { clusterUuid, type, expiryDateMS, status, ccs } = license;

View file

@ -9,6 +9,7 @@ import { LogstashVersionMismatchAlert } from './logstash_version_mismatch_alert'
import { ALERT_LOGSTASH_VERSION_MISMATCH } from '../../common/constants';
import { fetchLogstashVersions } from '../lib/alerts/fetch_logstash_versions';
import { fetchClusters } from '../lib/alerts/fetch_clusters';
import { elasticsearchServiceMock } from 'src/core/server/mocks';
const RealDate = Date;
@ -85,7 +86,7 @@ describe('LogstashVersionMismatchAlert', () => {
const getState = jest.fn();
const executorOptions = {
services: {
callCluster: jest.fn(),
scopedClusterClient: elasticsearchServiceMock.createScopedClusterClient(),
alertInstanceFactory: jest.fn().mockImplementation(() => {
return {
replaceState,

View file

@ -6,6 +6,7 @@
*/
import { i18n } from '@kbn/i18n';
import { ElasticsearchClient } from 'kibana/server';
import { BaseAlert } from './base_alert';
import {
AlertData,
@ -53,7 +54,7 @@ export class LogstashVersionMismatchAlert extends BaseAlert {
protected async fetchData(
params: CommonAlertParams,
callCluster: any,
esClient: ElasticsearchClient,
clusters: AlertCluster[],
availableCcs: string[]
): Promise<AlertData[]> {
@ -62,7 +63,7 @@ export class LogstashVersionMismatchAlert extends BaseAlert {
logstashIndexPattern = getCcsIndexPattern(logstashIndexPattern, availableCcs);
}
const logstashVersions = await fetchLogstashVersions(
callCluster,
esClient,
clusters,
logstashIndexPattern,
Globals.app.config.ui.max_bucket_size

View file

@ -7,6 +7,7 @@
import { i18n } from '@kbn/i18n';
import numeral from '@elastic/numeral';
import { ElasticsearchClient } from 'kibana/server';
import { BaseAlert } from './base_alert';
import {
AlertData,
@ -68,7 +69,7 @@ export class MemoryUsageAlert extends BaseAlert {
protected async fetchData(
params: CommonAlertParams,
callCluster: any,
esClient: ElasticsearchClient,
clusters: AlertCluster[],
availableCcs: string[]
): Promise<AlertData[]> {
@ -82,7 +83,7 @@ export class MemoryUsageAlert extends BaseAlert {
const startMs = endMs - parsedDuration;
const stats = await fetchMemoryUsageNodeStats(
callCluster,
esClient,
clusters,
esIndexPattern,
startMs,

Some files were not shown because too many files have changed in this diff Show more