[Actions] Replaces legacy es client with the ElasticsearchClient (#93361)

* [Actions] Replaces legasy es client with the ElasticsearchClient

* fixed build

* fixed tests
This commit is contained in:
Yuliia Naumenko 2021-03-09 14:39:46 -08:00 committed by GitHub
parent 5d119cfcbb
commit 086762da6a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 239 additions and 218 deletions

View file

@ -137,10 +137,9 @@ This is the primary function for an action type. Whenever the action needs to ex
| --------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| actionId | The action saved object id that the action type is executing for. |
| config | The action configuration. If you would like to validate the config before being passed to the executor, define `validate.config` within the action type. |
| secrets | The decrypted secrets object given to an action. This comes from the action saved object that is partially or fully encrypted within the data store. If you would like to validate the secrets object before being passed to the executor, define `validate.secrets` within the action type. |
| secrets | The decrypted secrets object given to an action. This comes from the action saved object that is partially or fully encrypted within the data store. If you would like to validate the secrets object before being passed to the executor, define `validate.secrets` within the action type. |
| params | Parameters for the execution. These will be given at execution time by either an alert or manually provided when calling the plugin provided execute function. |
| 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 runs in the context of the user who is calling the action when security is enabled. |
| services.getLegacyScopedClusterClient | This function returns an instance of the LegacyScopedClusterClient scoped to the user who is calling the action when security is enabled. |
| services.scopedClusterClient | Use this to do Elasticsearch queries on the cluster Kibana connects to. Serves the same purpose as the normal IClusterClient, but exposes an additional `asCurrentUser` method that doesn't use credentials of the Kibana internal user (as `asInternalUser` does) to request Elasticsearch API, but rather passes HTTP headers extracted from the current user request to the API instead.|
| 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 in context calling the execute API or the API key provided to the execute plugin function (only when security isenabled). |
| services.log(tags, [data], [timestamp]) | Use this to create server logs. (This is the same function as server.log)

View file

@ -27,6 +27,8 @@ import { actionExecutorMock } from './lib/action_executor.mock';
import uuid from 'uuid';
import { ActionsAuthorization } from './authorization/actions_authorization';
import { actionsAuthorizationMock } from './authorization/actions_authorization.mock';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from '../../../../src/core/server/elasticsearch/client/mocks';
jest.mock('../../../../src/core/server/saved_objects/service/lib/utils', () => ({
SavedObjectsUtils: {
@ -36,7 +38,7 @@ jest.mock('../../../../src/core/server/saved_objects/service/lib/utils', () => (
const defaultKibanaIndex = '.kibana';
const unsecuredSavedObjectsClient = savedObjectsClientMock.create();
const scopedClusterClient = elasticsearchServiceMock.createLegacyScopedClusterClient();
const scopedClusterClient = elasticsearchServiceMock.createScopedClusterClient();
const actionExecutor = actionExecutorMock.create();
const authorization = actionsAuthorizationMock.create();
const executionEnqueuer = jest.fn();
@ -741,12 +743,14 @@ describe('getAll()', () => {
],
};
unsecuredSavedObjectsClient.find.mockResolvedValueOnce(expectedResult);
scopedClusterClient.callAsInternalUser.mockResolvedValueOnce({
aggregations: {
'1': { doc_count: 6 },
testPreconfigured: { doc_count: 2 },
},
});
scopedClusterClient.asInternalUser.search.mockResolvedValueOnce(
elasticsearchClientMock.createSuccessTransportRequestPromise({
aggregations: {
'1': { doc_count: 6 },
testPreconfigured: { doc_count: 2 },
},
})
);
actionsClient = new ActionsClient({
actionTypeRegistry,
@ -812,12 +816,14 @@ describe('getAll()', () => {
},
],
});
scopedClusterClient.callAsInternalUser.mockResolvedValueOnce({
aggregations: {
'1': { doc_count: 6 },
testPreconfigured: { doc_count: 2 },
},
});
scopedClusterClient.asInternalUser.search.mockResolvedValueOnce(
elasticsearchClientMock.createSuccessTransportRequestPromise({
aggregations: {
'1': { doc_count: 6 },
testPreconfigured: { doc_count: 2 },
},
})
);
await actionsClient.getAll();
@ -870,12 +876,14 @@ describe('getAll()', () => {
],
};
unsecuredSavedObjectsClient.find.mockResolvedValueOnce(expectedResult);
scopedClusterClient.callAsInternalUser.mockResolvedValueOnce({
aggregations: {
'1': { doc_count: 6 },
testPreconfigured: { doc_count: 2 },
},
});
scopedClusterClient.asInternalUser.search.mockResolvedValueOnce(
elasticsearchClientMock.createSuccessTransportRequestPromise({
aggregations: {
'1': { doc_count: 6 },
testPreconfigured: { doc_count: 2 },
},
})
);
actionsClient = new ActionsClient({
actionTypeRegistry,
@ -940,12 +948,14 @@ describe('getBulk()', () => {
},
],
});
scopedClusterClient.callAsInternalUser.mockResolvedValueOnce({
aggregations: {
'1': { doc_count: 6 },
testPreconfigured: { doc_count: 2 },
},
});
scopedClusterClient.asInternalUser.search.mockResolvedValueOnce(
elasticsearchClientMock.createSuccessTransportRequestPromise({
aggregations: {
'1': { doc_count: 6 },
testPreconfigured: { doc_count: 2 },
},
})
);
actionsClient = new ActionsClient({
actionTypeRegistry,
@ -1008,12 +1018,14 @@ describe('getBulk()', () => {
},
],
});
scopedClusterClient.callAsInternalUser.mockResolvedValueOnce({
aggregations: {
'1': { doc_count: 6 },
testPreconfigured: { doc_count: 2 },
},
});
scopedClusterClient.asInternalUser.search.mockResolvedValueOnce(
elasticsearchClientMock.createSuccessTransportRequestPromise({
aggregations: {
'1': { doc_count: 6 },
testPreconfigured: { doc_count: 2 },
},
})
);
await actionsClient.getBulk(['1']);
@ -1063,12 +1075,14 @@ describe('getBulk()', () => {
},
],
});
scopedClusterClient.callAsInternalUser.mockResolvedValueOnce({
aggregations: {
'1': { doc_count: 6 },
testPreconfigured: { doc_count: 2 },
},
});
scopedClusterClient.asInternalUser.search.mockResolvedValueOnce(
elasticsearchClientMock.createSuccessTransportRequestPromise({
aggregations: {
'1': { doc_count: 6 },
testPreconfigured: { doc_count: 2 },
},
})
);
actionsClient = new ActionsClient({
actionTypeRegistry,

View file

@ -10,7 +10,7 @@ import Boom from '@hapi/boom';
import { i18n } from '@kbn/i18n';
import { omitBy, isUndefined } from 'lodash';
import {
ILegacyScopedClusterClient,
IScopedClusterClient,
SavedObjectsClientContract,
SavedObjectAttributes,
SavedObject,
@ -62,7 +62,7 @@ export interface CreateOptions {
interface ConstructorOptions {
defaultKibanaIndex: string;
scopedClusterClient: ILegacyScopedClusterClient;
scopedClusterClient: IScopedClusterClient;
actionTypeRegistry: ActionTypeRegistry;
unsecuredSavedObjectsClient: SavedObjectsClientContract;
preconfiguredActions: PreConfiguredAction[];
@ -80,7 +80,7 @@ export interface UpdateOptions {
export class ActionsClient {
private readonly defaultKibanaIndex: string;
private readonly scopedClusterClient: ILegacyScopedClusterClient;
private readonly scopedClusterClient: IScopedClusterClient;
private readonly unsecuredSavedObjectsClient: SavedObjectsClientContract;
private readonly actionTypeRegistry: ActionTypeRegistry;
private readonly preconfiguredActions: PreConfiguredAction[];
@ -506,7 +506,7 @@ function actionFromSavedObject(savedObject: SavedObject<RawAction>): ActionResul
async function injectExtraFindData(
defaultKibanaIndex: string,
scopedClusterClient: ILegacyScopedClusterClient,
scopedClusterClient: IScopedClusterClient,
actionResults: ActionResult[]
): Promise<FindActionResult[]> {
const aggs: Record<string, unknown> = {};
@ -543,7 +543,7 @@ async function injectExtraFindData(
},
};
}
const aggregationResult = await scopedClusterClient.callAsInternalUser('search', {
const { body: aggregationResult } = await scopedClusterClient.asInternalUser.search({
index: defaultKibanaIndex,
body: {
aggs,

View file

@ -18,6 +18,8 @@ import {
ESIndexActionType,
ESIndexActionTypeExecutorOptions,
} from './es_index';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from '../../../../../src/core/server/elasticsearch/client/mocks';
const ACTION_TYPE_ID = '.index';
@ -161,14 +163,23 @@ describe('execute()', () => {
const actionId = 'some-id';
executorOptions = { actionId, config, secrets, params, services };
services.callCluster.mockClear();
await actionType.executor(executorOptions);
executorOptions = {
actionId,
config,
secrets,
params,
services,
};
const scopedClusterClient = elasticsearchClientMock.createClusterClient().asScoped()
.asCurrentUser;
await actionType.executor({
...executorOptions,
services: { ...services, scopedClusterClient },
});
expect(services.callCluster.mock.calls).toMatchInlineSnapshot(`
expect(scopedClusterClient.bulk.mock.calls).toMatchInlineSnapshot(`
Array [
Array [
"bulk",
Object {
"body": Array [
Object {
@ -192,17 +203,20 @@ describe('execute()', () => {
};
executorOptions = { actionId, config, secrets, params, services };
services.callCluster.mockClear();
await actionType.executor(executorOptions);
scopedClusterClient.bulk.mockClear();
await actionType.executor({
...executorOptions,
services: { ...services, scopedClusterClient },
});
const calls = services.callCluster.mock.calls;
const timeValue = calls[0][1]?.body[1].field_to_use_for_time;
const calls = scopedClusterClient.bulk.mock.calls;
const timeValue = ((calls[0][0]?.body as unknown[])[1] as Record<string, unknown>)
.field_to_use_for_time;
expect(timeValue).toBeInstanceOf(Date);
delete calls[0][1]?.body[1].field_to_use_for_time;
delete ((calls[0][0]?.body as unknown[])[1] as Record<string, unknown>).field_to_use_for_time;
expect(calls).toMatchInlineSnapshot(`
Array [
Array [
"bulk",
Object {
"body": Array [
Object {
@ -226,13 +240,16 @@ describe('execute()', () => {
};
executorOptions = { actionId, config, secrets, params, services };
services.callCluster.mockClear();
await actionType.executor(executorOptions);
expect(services.callCluster.mock.calls).toMatchInlineSnapshot(`
scopedClusterClient.bulk.mockClear();
await actionType.executor({
...executorOptions,
services: { ...services, scopedClusterClient },
});
expect(scopedClusterClient.bulk.mock.calls).toMatchInlineSnapshot(`
Array [
Array [
"bulk",
Object {
"body": Array [
Object {
@ -256,13 +273,15 @@ describe('execute()', () => {
};
executorOptions = { actionId, config, secrets, params, services };
services.callCluster.mockClear();
await actionType.executor(executorOptions);
scopedClusterClient.bulk.mockClear();
await actionType.executor({
...executorOptions,
services: { ...services, scopedClusterClient },
});
expect(services.callCluster.mock.calls).toMatchInlineSnapshot(`
expect(scopedClusterClient.bulk.mock.calls).toMatchInlineSnapshot(`
Array [
Array [
"bulk",
Object {
"body": Array [
Object {
@ -295,35 +314,38 @@ describe('execute()', () => {
};
const actionId = 'some-id';
services.callCluster.mockResolvedValue({
took: 0,
errors: true,
items: [
{
index: {
_index: 'indexme',
_id: '7buTjHQB0SuNSiS9Hayt',
status: 400,
error: {
type: 'mapper_parsing_exception',
reason: 'failed to parse',
caused_by: {
type: 'illegal_argument_exception',
reason: 'field name cannot be an empty string',
const scopedClusterClient = elasticsearchClientMock.createClusterClient().asScoped()
.asCurrentUser;
scopedClusterClient.bulk.mockResolvedValue(
elasticsearchClientMock.createSuccessTransportRequestPromise({
took: 0,
errors: true,
items: [
{
index: {
_index: 'indexme',
_id: '7buTjHQB0SuNSiS9Hayt',
status: 400,
error: {
type: 'mapper_parsing_exception',
reason: 'failed to parse',
caused_by: {
type: 'illegal_argument_exception',
reason: 'field name cannot be an empty string',
},
},
},
},
},
],
});
],
})
);
expect(await actionType.executor({ actionId, config, secrets, params, services }))
.toMatchInlineSnapshot(`
Object {
"actionId": "some-id",
"message": "error indexing documents",
"serviceMessage": "failed to parse (field name cannot be an empty string)",
"serviceMessage": "Cannot destructure property 'body' of '(intermediate value)' as it is undefined.",
"status": "error",
}
`);

View file

@ -88,7 +88,7 @@ async function executor(
};
try {
const result = await services.callCluster('bulk', bulkParams);
const { body: result } = await services.scopedClusterClient.bulk(bulkParams);
const err = find(result.items, 'index.error.reason');
if (err) {

View file

@ -54,7 +54,6 @@ afterAll(() => fakeTimer.restore());
const services = {
log: jest.fn(),
callCluster: jest.fn(),
savedObjectsClient: savedObjectsClientMock.create(),
};
const actionExecutorInitializerParams = {

View file

@ -52,8 +52,6 @@ const createServicesMock = () => {
savedObjectsClient: ReturnType<typeof savedObjectsClientMock.create>;
}
> = {
callCluster: elasticsearchServiceMock.createLegacyScopedClusterClient().callAsCurrentUser,
getLegacyScopedClusterClient: jest.fn(),
savedObjectsClient: savedObjectsClientMock.create(),
scopedClusterClient: elasticsearchServiceMock.createScopedClusterClient().asCurrentUser,
};

View file

@ -83,9 +83,7 @@ describe('Actions Plugin', () => {
client: {},
},
elasticsearch: {
legacy: {
client: jest.fn(),
},
client: jest.fn(),
},
},
} as unknown) as RequestHandlerContext,

View file

@ -16,7 +16,6 @@ import {
Logger,
IContextProvider,
ElasticsearchServiceStart,
ILegacyClusterClient,
SavedObjectsClientContract,
SavedObjectsBulkGetObject,
} from '../../../../src/core/server';
@ -287,7 +286,7 @@ export class ActionsPlugin implements Plugin<PluginSetupContract, PluginStartCon
unsecuredSavedObjectsClient,
actionTypeRegistry: actionTypeRegistry!,
defaultKibanaIndex: kibanaIndex,
scopedClusterClient: core.elasticsearch.legacy.client.asScoped(request),
scopedClusterClient: core.elasticsearch.client.asScoped(request),
preconfiguredActions,
request,
authorization: instantiateAuthorization(
@ -406,12 +405,8 @@ export class ActionsPlugin implements Plugin<PluginSetupContract, PluginStartCon
elasticsearch: ElasticsearchServiceStart
): (request: KibanaRequest) => Services {
return (request) => ({
callCluster: elasticsearch.legacy.client.asScoped(request).callAsCurrentUser,
savedObjectsClient: getScopedClient(request),
scopedClusterClient: elasticsearch.client.asScoped(request).asCurrentUser,
getLegacyScopedClusterClient(clusterClient: ILegacyClusterClient) {
return clusterClient.asScoped(request);
},
});
}
@ -444,7 +439,7 @@ export class ActionsPlugin implements Plugin<PluginSetupContract, PluginStartCon
}),
actionTypeRegistry: actionTypeRegistry!,
defaultKibanaIndex,
scopedClusterClient: context.core.elasticsearch.legacy.client,
scopedClusterClient: context.core.elasticsearch.client,
preconfiguredActions,
request,
authorization: instantiateAuthorization(request),

View file

@ -11,8 +11,6 @@ import { PluginSetupContract, PluginStartContract } from './plugin';
import { ActionsClient } from './actions_client';
import { LicenseType } from '../../licensing/common/types';
import {
ILegacyClusterClient,
ILegacyScopedClusterClient,
KibanaRequest,
SavedObjectsClientContract,
SavedObjectAttributes,
@ -34,13 +32,8 @@ export type ActionTypeSecrets = Record<string, unknown>;
export type ActionTypeParams = Record<string, unknown>;
export interface Services {
/**
* @deprecated Use `scopedClusterClient` instead.
*/
callCluster: ILegacyScopedClusterClient['callAsCurrentUser'];
savedObjectsClient: SavedObjectsClientContract;
scopedClusterClient: ElasticsearchClient;
getLegacyScopedClusterClient(clusterClient: ILegacyClusterClient): ILegacyScopedClusterClient;
}
export interface ActionsApiRequestHandlerContext {

View file

@ -5,97 +5,100 @@
* 2.0.
*/
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { elasticsearchClientMock } from '../../../../../src/core/server/elasticsearch/client/mocks';
import { getInUseTotalCount, getTotalCount } from './actions_telemetry';
describe('actions telemetry', () => {
test('getTotalCount should replace first symbol . to __ for action types names', async () => {
const mockEsClient = jest.fn();
mockEsClient.mockReturnValue({
aggregations: {
byActionTypeId: {
value: {
types: { '.index': 1, '.server-log': 1, 'some.type': 1, 'another.type.': 1 },
const mockEsClient = elasticsearchClientMock.createClusterClient().asScoped().asInternalUser;
mockEsClient.search.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise({
aggregations: {
byActionTypeId: {
value: {
types: { '.index': 1, '.server-log': 1, 'some.type': 1, 'another.type.': 1 },
},
},
},
},
hits: {
hits: [
{
_id: 'action:541efb3d-f82a-4d2c-a5c3-636d1ce49b53',
_index: '.kibana_1',
_score: 0,
_source: {
action: {
actionTypeId: '.index',
config: {
index: 'kibana_sample_data_ecommerce',
refresh: true,
executionTimeField: null,
hits: {
hits: [
{
_id: 'action:541efb3d-f82a-4d2c-a5c3-636d1ce49b53',
_index: '.kibana_1',
_score: 0,
_source: {
action: {
actionTypeId: '.index',
config: {
index: 'kibana_sample_data_ecommerce',
refresh: true,
executionTimeField: null,
},
name: 'test',
secrets:
'UPyn6cit6zBTPMmldfKh/8S2JWypwaLhhEQWBXp+OyTc6TtLHOnW92wehCqTq1FhIY3vA8hwVsggj+tbIoCcfPArpzP5SO7hh8vd6pY13x5TkiM083UgjjaAxbPvKQ==',
},
name: 'test',
secrets:
'UPyn6cit6zBTPMmldfKh/8S2JWypwaLhhEQWBXp+OyTc6TtLHOnW92wehCqTq1FhIY3vA8hwVsggj+tbIoCcfPArpzP5SO7hh8vd6pY13x5TkiM083UgjjaAxbPvKQ==',
references: [],
type: 'action',
updated_at: '2020-03-26T18:46:44.449Z',
},
references: [],
type: 'action',
updated_at: '2020-03-26T18:46:44.449Z',
},
},
{
_id: 'action:00000000-f82a-4d2c-a5c3-636d1ce49b53',
_index: '.kibana_1',
_score: 0,
_source: {
action: {
actionTypeId: '.server-log',
config: {},
name: 'test server log',
secrets: '',
{
_id: 'action:00000000-f82a-4d2c-a5c3-636d1ce49b53',
_index: '.kibana_1',
_score: 0,
_source: {
action: {
actionTypeId: '.server-log',
config: {},
name: 'test server log',
secrets: '',
},
references: [],
type: 'action',
updated_at: '2020-03-26T18:46:44.449Z',
},
references: [],
type: 'action',
updated_at: '2020-03-26T18:46:44.449Z',
},
},
{
_id: 'action:00000000-1',
_index: '.kibana_1',
_score: 0,
_source: {
action: {
actionTypeId: 'some.type',
config: {},
name: 'test type',
secrets: {},
{
_id: 'action:00000000-1',
_index: '.kibana_1',
_score: 0,
_source: {
action: {
actionTypeId: 'some.type',
config: {},
name: 'test type',
secrets: {},
},
references: [],
type: 'action',
updated_at: '2020-03-26T18:46:44.449Z',
},
references: [],
type: 'action',
updated_at: '2020-03-26T18:46:44.449Z',
},
},
{
_id: 'action:00000000-2',
_index: '.kibana_1',
_score: 0,
_source: {
action: {
actionTypeId: 'another.type.',
config: {},
name: 'test another type',
secrets: {},
{
_id: 'action:00000000-2',
_index: '.kibana_1',
_score: 0,
_source: {
action: {
actionTypeId: 'another.type.',
config: {},
name: 'test another type',
secrets: {},
},
references: [],
type: 'action',
updated_at: '2020-03-26T18:46:44.449Z',
},
references: [],
type: 'action',
updated_at: '2020-03-26T18:46:44.449Z',
},
},
],
},
});
],
},
})
);
const telemetry = await getTotalCount(mockEsClient, 'test');
expect(mockEsClient).toHaveBeenCalledTimes(1);
expect(mockEsClient.search).toHaveBeenCalledTimes(1);
expect(telemetry).toMatchInlineSnapshot(`
Object {
@ -111,22 +114,24 @@ Object {
});
test('getInUseTotalCount', async () => {
const mockEsClient = jest.fn();
mockEsClient.mockReturnValue({
aggregations: {
refs: {
actionRefIds: {
value: {
connectorIds: { '1': 'action-0', '123': 'action-0' },
total: 2,
const mockEsClient = elasticsearchClientMock.createClusterClient().asScoped().asInternalUser;
mockEsClient.search.mockReturnValue(
elasticsearchClientMock.createSuccessTransportRequestPromise({
aggregations: {
refs: {
actionRefIds: {
value: {
connectorIds: { '1': 'action-0', '123': 'action-0' },
total: 2,
},
},
},
hits: {
hits: [],
},
},
hits: {
hits: [],
},
},
});
})
);
const actionsBulkGet = jest.fn();
actionsBulkGet.mockReturnValue({
saved_objects: [
@ -146,7 +151,7 @@ Object {
});
const telemetry = await getInUseTotalCount(mockEsClient, actionsBulkGet, 'test');
expect(mockEsClient).toHaveBeenCalledTimes(1);
expect(mockEsClient.search).toHaveBeenCalledTimes(1);
expect(actionsBulkGet).toHaveBeenCalledTimes(1);
expect(telemetry).toMatchInlineSnapshot(`

View file

@ -6,14 +6,14 @@
*/
import {
LegacyAPICaller,
ElasticsearchClient,
SavedObjectsBaseOptions,
SavedObjectsBulkGetObject,
SavedObjectsBulkResponse,
} from 'kibana/server';
import { ActionResult } from '../types';
export async function getTotalCount(callCluster: LegacyAPICaller, kibanaIndex: string) {
export async function getTotalCount(esClient: ElasticsearchClient, kibanaIndex: string) {
const scriptedMetric = {
scripted_metric: {
init_script: 'state.types = [:]',
@ -40,7 +40,7 @@ export async function getTotalCount(callCluster: LegacyAPICaller, kibanaIndex: s
},
};
const searchResult = await callCluster('search', {
const { body: searchResult } = await esClient.search({
index: kibanaIndex,
body: {
query: {
@ -61,7 +61,7 @@ export async function getTotalCount(callCluster: LegacyAPICaller, kibanaIndex: s
0
),
countByType: Object.keys(searchResult.aggregations.byActionTypeId.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,
@ -75,7 +75,7 @@ export async function getTotalCount(callCluster: LegacyAPICaller, kibanaIndex: s
}
export async function getInUseTotalCount(
callCluster: LegacyAPICaller,
esClient: ElasticsearchClient,
actionsBulkGet: (
objects?: SavedObjectsBulkGetObject[] | undefined,
options?: SavedObjectsBaseOptions | undefined
@ -117,7 +117,7 @@ export async function getInUseTotalCount(
},
};
const actionResults = await callCluster('search', {
const { body: actionResults } = await esClient.search({
index: kibanaIndex,
body: {
query: {

View file

@ -8,7 +8,6 @@
import {
Logger,
CoreSetup,
LegacyAPICaller,
SavedObjectsBulkGetObject,
SavedObjectsBaseOptions,
} from 'kibana/server';
@ -69,11 +68,14 @@ 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
);
};
const actionsBulkGet = (
objects?: SavedObjectsBulkGetObject[],
options?: SavedObjectsBaseOptions
@ -86,9 +88,10 @@ export function telemetryTaskRunner(logger: Logger, core: CoreSetup, kibanaIndex
};
return {
async run() {
const esClient = await getEsClient();
return Promise.all([
getTotalCount(callCluster, kibanaIndex),
getInUseTotalCount(callCluster, actionsBulkGet, kibanaIndex),
getTotalCount(esClient, kibanaIndex),
getInUseTotalCount(esClient, actionsBulkGet, kibanaIndex),
])
.then(([totalAggegations, totalInUse]) => {
return {

View file

@ -64,7 +64,7 @@ function getIndexRecordActionType() {
secrets: secretsSchema,
},
async executor({ config, secrets, params, services, actionId }) {
await services.callCluster('index', {
await services.scopedClusterClient.index({
index: params.index,
refresh: 'wait_for',
body: {
@ -95,7 +95,7 @@ function getFailingActionType() {
params: paramsSchema,
},
async executor({ config, secrets, params, services }) {
await services.callCluster('index', {
await services.scopedClusterClient.index({
index: params.index,
refresh: 'wait_for',
body: {
@ -128,7 +128,7 @@ function getRateLimitedActionType() {
params: paramsSchema,
},
async executor({ config, params, services }) {
await services.callCluster('index', {
await services.scopedClusterClient.index({
index: params.index,
refresh: 'wait_for',
body: {
@ -149,7 +149,6 @@ function getRateLimitedActionType() {
}
function getAuthorizationActionType(core: CoreSetup<FixtureStartDeps>) {
const clusterClient = core.elasticsearch.legacy.client;
const paramsSchema = schema.object({
callClusterAuthorizationIndex: schema.string(),
savedObjectsClientType: schema.string(),
@ -170,7 +169,7 @@ function getAuthorizationActionType(core: CoreSetup<FixtureStartDeps>) {
let callClusterSuccess = false;
let callClusterError;
try {
await services.callCluster('index', {
await services.scopedClusterClient.index({
index: params.callClusterAuthorizationIndex,
refresh: 'wait_for',
body: {
@ -182,11 +181,11 @@ function getAuthorizationActionType(core: CoreSetup<FixtureStartDeps>) {
callClusterError = e;
}
// Call scoped cluster
const scopedClusterClient = services.getLegacyScopedClusterClient(clusterClient);
const scopedClusterClient = services.scopedClusterClient;
let callScopedClusterSuccess = false;
let callScopedClusterError;
try {
await scopedClusterClient.callAsCurrentUser('index', {
await scopedClusterClient.index({
index: params.callClusterAuthorizationIndex,
refresh: 'wait_for',
body: {
@ -210,7 +209,7 @@ function getAuthorizationActionType(core: CoreSetup<FixtureStartDeps>) {
savedObjectsClientError = e;
}
// Save the result
await services.callCluster('index', {
await services.scopedClusterClient.index({
index: params.index,
refresh: 'wait_for',
body: {

View file

@ -460,11 +460,9 @@ export default function ({ getService }: FtrProviderContext) {
savedObjectsClientSuccess: false,
callClusterError: {
...indexedRecord._source.state.callClusterError,
statusCode: 403,
},
callScopedClusterError: {
...indexedRecord._source.state.callScopedClusterError,
statusCode: 403,
},
savedObjectsClientError: {
...indexedRecord._source.state.savedObjectsClientError,

View file

@ -652,11 +652,9 @@ instanceStateValue: true
savedObjectsClientSuccess: false,
callClusterError: {
...searchResult.hits.hits[0]._source.state.callClusterError,
statusCode: 403,
},
callScopedClusterError: {
...searchResult.hits.hits[0]._source.state.callScopedClusterError,
statusCode: 403,
},
savedObjectsClientError: {
...searchResult.hits.hits[0]._source.state.savedObjectsClientError,