From 2dba0d18f10cd55e6f2341f57ff31d990c63554f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Louv-Jansen?= Date: Tue, 26 Oct 2021 03:20:15 +0200 Subject: [PATCH 01/58] [APM] Rename `traceData` to `synthtraceEsClient` (#116215) --- x-pack/test/apm_api_integration/common/config.ts | 4 ++-- .../common/{trace_data.ts => synthtrace_es_client.ts} | 2 +- .../apm_api_integration/tests/error_rate/service_apis.ts | 6 +++--- .../test/apm_api_integration/tests/latency/service_apis.ts | 6 +++--- .../tests/observability_overview/observability_overview.ts | 6 +++--- .../tests/service_overview/instances_main_statistics.ts | 6 +++--- .../test/apm_api_integration/tests/services/throughput.ts | 6 +++--- .../tests/throughput/dependencies_apis.ts | 6 +++--- .../apm_api_integration/tests/throughput/service_apis.ts | 6 +++--- .../transactions/transactions_groups_detailed_statistics.ts | 6 +++--- 10 files changed, 27 insertions(+), 27 deletions(-) rename x-pack/test/apm_api_integration/common/{trace_data.ts => synthtrace_es_client.ts} (96%) diff --git a/x-pack/test/apm_api_integration/common/config.ts b/x-pack/test/apm_api_integration/common/config.ts index 574cfe811bc67..978f3f0d68673 100644 --- a/x-pack/test/apm_api_integration/common/config.ts +++ b/x-pack/test/apm_api_integration/common/config.ts @@ -15,7 +15,7 @@ import { createApmUser, APM_TEST_PASSWORD, ApmUser } from './authentication'; import { APMFtrConfigName } from '../configs'; import { createApmApiClient } from './apm_api_supertest'; import { registry } from './registry'; -import { traceData } from './trace_data'; +import { synthtraceEsClient } from './synthtrace_es_client'; interface Config { name: APMFtrConfigName; @@ -77,7 +77,7 @@ export function createTestConfig(config: Config) { servers, services: { ...services, - traceData, + synthtraceEsClient, apmApiClient: async (context: InheritedFtrProviderContext) => { const security = context.getService('security'); await security.init(); diff --git a/x-pack/test/apm_api_integration/common/trace_data.ts b/x-pack/test/apm_api_integration/common/synthtrace_es_client.ts similarity index 96% rename from x-pack/test/apm_api_integration/common/trace_data.ts rename to x-pack/test/apm_api_integration/common/synthtrace_es_client.ts index 4e813efab2913..68f5c2b08b518 100644 --- a/x-pack/test/apm_api_integration/common/trace_data.ts +++ b/x-pack/test/apm_api_integration/common/synthtrace_es_client.ts @@ -16,7 +16,7 @@ import pLimit from 'p-limit'; import { inspect } from 'util'; import { InheritedFtrProviderContext } from './ftr_provider_context'; -export async function traceData(context: InheritedFtrProviderContext) { +export async function synthtraceEsClient(context: InheritedFtrProviderContext) { const es = context.getService('es'); return { index: (events: any[]) => { diff --git a/x-pack/test/apm_api_integration/tests/error_rate/service_apis.ts b/x-pack/test/apm_api_integration/tests/error_rate/service_apis.ts index ac81b6d5a4412..76f8d20c8ada8 100644 --- a/x-pack/test/apm_api_integration/tests/error_rate/service_apis.ts +++ b/x-pack/test/apm_api_integration/tests/error_rate/service_apis.ts @@ -15,7 +15,7 @@ import { registry } from '../../common/registry'; export default function ApiTest({ getService }: FtrProviderContext) { const apmApiClient = getService('apmApiClient'); - const traceData = getService('traceData'); + const synthtraceEsClient = getService('synthtraceEsClient'); const serviceName = 'synth-go'; const start = new Date('2021-01-01T00:00:00.000Z').getTime(); @@ -128,7 +128,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { const transactionNameProductList = 'GET /api/product/list'; const transactionNameProductId = 'GET /api/product/:id'; - await traceData.index([ + await synthtraceEsClient.index([ ...timerange(start, end) .interval('1m') .rate(GO_PROD_LIST_RATE) @@ -176,7 +176,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { ]); }); - after(() => traceData.clean()); + after(() => synthtraceEsClient.clean()); describe('compare error rate value between service inventory, error rate chart, service inventory and transactions apis', () => { before(async () => { diff --git a/x-pack/test/apm_api_integration/tests/latency/service_apis.ts b/x-pack/test/apm_api_integration/tests/latency/service_apis.ts index c6ecf9e4a4aba..d3ec68c51782d 100644 --- a/x-pack/test/apm_api_integration/tests/latency/service_apis.ts +++ b/x-pack/test/apm_api_integration/tests/latency/service_apis.ts @@ -15,7 +15,7 @@ import { registry } from '../../common/registry'; export default function ApiTest({ getService }: FtrProviderContext) { const apmApiClient = getService('apmApiClient'); - const traceData = getService('traceData'); + const synthtraceEsClient = getService('synthtraceEsClient'); const serviceName = 'synth-go'; const start = new Date('2021-01-01T00:00:00.000Z').getTime(); @@ -129,7 +129,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { const serviceGoDevInstance = service(serviceName, 'development', 'go').instance( 'instance-b' ); - await traceData.index([ + await synthtraceEsClient.index([ ...timerange(start, end) .interval('1m') .rate(GO_PROD_RATE) @@ -153,7 +153,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { ]); }); - after(() => traceData.clean()); + after(() => synthtraceEsClient.clean()); describe('compare latency value between service inventory, latency chart, service inventory and transactions apis', () => { before(async () => { diff --git a/x-pack/test/apm_api_integration/tests/observability_overview/observability_overview.ts b/x-pack/test/apm_api_integration/tests/observability_overview/observability_overview.ts index af95f981a3dc5..e4aad4f3f6975 100644 --- a/x-pack/test/apm_api_integration/tests/observability_overview/observability_overview.ts +++ b/x-pack/test/apm_api_integration/tests/observability_overview/observability_overview.ts @@ -15,7 +15,7 @@ import { roundNumber } from '../../utils'; export default function ApiTest({ getService }: FtrProviderContext) { const apmApiClient = getService('apmApiClient'); - const traceData = getService('traceData'); + const synthtraceEsClient = getService('synthtraceEsClient'); const start = new Date('2021-01-01T00:00:00.000Z').getTime(); const end = new Date('2021-01-01T00:15:00.000Z').getTime() - 1; @@ -99,7 +99,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { 'instance-c' ); - await traceData.index([ + await synthtraceEsClient.index([ ...timerange(start, end) .interval('1m') .rate(GO_PROD_RATE) @@ -133,7 +133,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { ]); }); - after(() => traceData.clean()); + after(() => synthtraceEsClient.clean()); describe('compare throughput values', () => { let throughputValues: PromiseReturnType; diff --git a/x-pack/test/apm_api_integration/tests/service_overview/instances_main_statistics.ts b/x-pack/test/apm_api_integration/tests/service_overview/instances_main_statistics.ts index 68979795f9dcf..1e9051b64a90b 100644 --- a/x-pack/test/apm_api_integration/tests/service_overview/instances_main_statistics.ts +++ b/x-pack/test/apm_api_integration/tests/service_overview/instances_main_statistics.ts @@ -21,7 +21,7 @@ import { SERVICE_NODE_NAME_MISSING } from '../../../../plugins/apm/common/servic export default function ApiTest({ getService }: FtrProviderContext) { const apmApiClient = getService('apmApiClient'); - const traceData = getService('traceData'); + const synthtraceEsClient = getService('synthtraceEsClient'); const archiveName = 'apm_8.0.0'; const { start, end } = archives[archiveName]; @@ -320,7 +320,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { ); } - return traceData.index([ + return synthtraceEsClient.index([ ...interval.rate(GO_A_INSTANCE_RATE_SUCCESS).flatMap((timestamp) => goInstanceA .transaction('GET /api/product/list') @@ -361,7 +361,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { }); after(async () => { - return traceData.clean(); + return synthtraceEsClient.clean(); }); describe('for the go service', () => { diff --git a/x-pack/test/apm_api_integration/tests/services/throughput.ts b/x-pack/test/apm_api_integration/tests/services/throughput.ts index e98ab60af8ca4..abc7988af823d 100644 --- a/x-pack/test/apm_api_integration/tests/services/throughput.ts +++ b/x-pack/test/apm_api_integration/tests/services/throughput.ts @@ -23,7 +23,7 @@ type ThroughputReturn = APIReturnType<'GET /internal/apm/services/{serviceName}/ export default function ApiTest({ getService }: FtrProviderContext) { const apmApiClient = getService('apmApiClient'); - const traceData = getService('traceData'); + const synthtraceEsClient = getService('synthtraceEsClient'); const serviceName = 'synth-go'; const start = new Date('2021-01-01T00:00:00.000Z').getTime(); @@ -81,7 +81,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { 'instance-c' ); - await traceData.index([ + await synthtraceEsClient.index([ ...timerange(start, end) .interval('1m') .rate(GO_PROD_RATE) @@ -115,7 +115,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { ]); }); - after(() => traceData.clean()); + after(() => synthtraceEsClient.clean()); describe('compare transactions and metrics based throughput', () => { let throughputMetrics: ThroughputReturn; diff --git a/x-pack/test/apm_api_integration/tests/throughput/dependencies_apis.ts b/x-pack/test/apm_api_integration/tests/throughput/dependencies_apis.ts index 4df40d1d85d56..22b4486181e62 100644 --- a/x-pack/test/apm_api_integration/tests/throughput/dependencies_apis.ts +++ b/x-pack/test/apm_api_integration/tests/throughput/dependencies_apis.ts @@ -15,7 +15,7 @@ import { roundNumber } from '../../utils'; export default function ApiTest({ getService }: FtrProviderContext) { const apmApiClient = getService('apmApiClient'); - const traceData = getService('traceData'); + const synthtraceEsClient = getService('synthtraceEsClient'); const start = new Date('2021-01-01T00:00:00.000Z').getTime(); const end = new Date('2021-01-01T00:15:00.000Z').getTime() - 1; @@ -101,7 +101,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { 'instance-c' ); - await traceData.index([ + await synthtraceEsClient.index([ ...timerange(start, end) .interval('1m') .rate(GO_PROD_RATE) @@ -159,7 +159,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { ]); }); - after(() => traceData.clean()); + after(() => synthtraceEsClient.clean()); describe('verify top dependencies', () => { before(async () => { diff --git a/x-pack/test/apm_api_integration/tests/throughput/service_apis.ts b/x-pack/test/apm_api_integration/tests/throughput/service_apis.ts index 00e5e57c546dd..ea5252d3490ca 100644 --- a/x-pack/test/apm_api_integration/tests/throughput/service_apis.ts +++ b/x-pack/test/apm_api_integration/tests/throughput/service_apis.ts @@ -15,7 +15,7 @@ import { roundNumber } from '../../utils'; export default function ApiTest({ getService }: FtrProviderContext) { const apmApiClient = getService('apmApiClient'); - const traceData = getService('traceData'); + const synthtraceEsClient = getService('synthtraceEsClient'); const serviceName = 'synth-go'; const start = new Date('2021-01-01T00:00:00.000Z').getTime(); @@ -115,7 +115,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { const serviceGoDevInstance = service(serviceName, 'development', 'go').instance( 'instance-b' ); - await traceData.index([ + await synthtraceEsClient.index([ ...timerange(start, end) .interval('1m') .rate(GO_PROD_RATE) @@ -139,7 +139,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { ]); }); - after(() => traceData.clean()); + after(() => synthtraceEsClient.clean()); describe('compare throughput value between service inventory, throughput chart, service inventory and transactions apis', () => { before(async () => { diff --git a/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_detailed_statistics.ts b/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_detailed_statistics.ts index acdd12f3501bf..fe4058004691b 100644 --- a/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_detailed_statistics.ts +++ b/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_detailed_statistics.ts @@ -20,7 +20,7 @@ type TransactionsGroupsDetailedStatistics = export default function ApiTest({ getService }: FtrProviderContext) { const apmApiClient = getService('apmApiClient'); - const traceData = getService('traceData'); + const synthtraceEsClient = getService('synthtraceEsClient'); const serviceName = 'synth-go'; const start = new Date('2021-01-01T00:00:00.000Z').getTime(); @@ -87,7 +87,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { const transactionName = 'GET /api/product/list'; - await traceData.index([ + await synthtraceEsClient.index([ ...timerange(start, end) .interval('1m') .rate(GO_PROD_RATE) @@ -113,7 +113,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { ]); }); - after(() => traceData.clean()); + after(() => synthtraceEsClient.clean()); describe('without comparisons', () => { let transactionsStatistics: TransactionsGroupsDetailedStatistics; From fd659b762fa4ead26b8663a30e762bebe7348efd Mon Sep 17 00:00:00 2001 From: Jason Rhodes Date: Mon, 25 Oct 2021 23:29:29 -0400 Subject: [PATCH 02/58] Change to infra-monitoring-ui for CODEOWNERS (#116234) logs-metrics-ui and stack-monitoring ui teams have merged into one infra-monitoring-ui team inside of observability --- .github/CODEOWNERS | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index ec03acc752d55..a324b9f429b39 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -95,15 +95,15 @@ # Observability Shared /x-pack/plugins/observability/ @elastic/observability-ui -# Logs and Metrics (Infra) -/x-pack/plugins/infra/ @elastic/logs-metrics-ui -/x-pack/plugins/infra/server/routes/log* @elastic/logs-metrics-ui @elastic/logs-ui -/x-pack/plugins/infra/public/pages/logs/ @elastic/logs-metrics-ui @elastic/logs-ui -/x-pack/plugins/infra/server/routes/metrics* @elastic/logs-metrics-ui @elastic/metrics-ui -/x-pack/plugins/infra/public/pages/metrics/ @elastic/logs-metrics-ui @elastic/metrics-ui - -# Stack Monitoring -/x-pack/plugins/monitoring/ @elastic/stack-monitoring-ui @elastic/logs-metrics-ui @elastic/metrics-ui +# Infra Monitoring +/x-pack/plugins/infra/ @elastic/infra-monitoring-ui +/x-pack/test/functional/apps/infra @elastic/infra-monitoring-ui +/x-pack/test/api_integration/apis/infra @elastic/infra-monitoring-ui + +# Elastic Stack Monitoring +/x-pack/plugins/monitoring/ @elastic/infra-monitoring-ui +/x-pack/test/functional/apps/monitoring @elastic/infra-monitoring-ui +/x-pack/test/api_integration/apis/monitoring @elastic/infra-monitoring-ui # Fleet /x-pack/plugins/fleet/ @elastic/fleet From 8ce1c1f9bb81d320379fb590c317538bccb2cea6 Mon Sep 17 00:00:00 2001 From: Joe Portner <5295965+jportner@users.noreply.github.com> Date: Mon, 25 Oct 2021 23:39:05 -0400 Subject: [PATCH 03/58] Make maps share-capable (#116221) --- x-pack/plugins/maps/server/saved_objects/map.ts | 3 ++- x-pack/test/api_integration/apis/maps/migrations.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/maps/server/saved_objects/map.ts b/x-pack/plugins/maps/server/saved_objects/map.ts index 24effd651a31b..b13f24fc6ba1c 100644 --- a/x-pack/plugins/maps/server/saved_objects/map.ts +++ b/x-pack/plugins/maps/server/saved_objects/map.ts @@ -13,7 +13,8 @@ import { savedObjectMigrations } from './saved_object_migrations'; export const mapSavedObjects: SavedObjectsType = { name: 'map', hidden: false, - namespaceType: 'single', + namespaceType: 'multiple-isolated', + convertToMultiNamespaceTypeVersion: '8.0.0', mappings: { properties: { description: { type: 'text' }, diff --git a/x-pack/test/api_integration/apis/maps/migrations.js b/x-pack/test/api_integration/apis/maps/migrations.js index 47747467ae550..f8b603ac38fde 100644 --- a/x-pack/test/api_integration/apis/maps/migrations.js +++ b/x-pack/test/api_integration/apis/maps/migrations.js @@ -44,7 +44,7 @@ export default function ({ getService }) { type: 'index-pattern', }, ]); - expect(resp.body.migrationVersion).to.eql({ map: '7.14.0' }); + expect(resp.body.migrationVersion).to.eql({ map: '8.0.0' }); // migrtionVersion is derived from both "migrations" and "convertToMultiNamespaceVersion" fields when the object is registered expect(resp.body.attributes.layerListJSON.includes('indexPatternRefName')).to.be(true); }); }); From 8c6ef2054f7b3d8dfe4c042789a63badec269fec Mon Sep 17 00:00:00 2001 From: Scotty Bollinger Date: Tue, 26 Oct 2021 01:17:35 -0500 Subject: [PATCH 04/58] Fix bug where number rendered as date (#116224) --- .../__mocks__/content_sources.mock.ts | 2 +- .../example_result_detail_card.test.tsx | 14 ++++++++++++++ .../example_result_detail_card.tsx | 5 ++++- .../display_settings/result_detail.test.tsx | 5 ++++- 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/__mocks__/content_sources.mock.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/__mocks__/content_sources.mock.ts index 48cbf4ba00d87..7222edad56822 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/__mocks__/content_sources.mock.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/__mocks__/content_sources.mock.ts @@ -376,7 +376,7 @@ export const exampleResult = { source: 'custom', }, ], - schemaFields: {}, + schemaFields: { cats: 'text', dogs: 'text' }, }; export const mostRecentIndexJob = { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_result_detail_card.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_result_detail_card.test.tsx index 5a15ef641be99..eeb7f6b54f2c0 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_result_detail_card.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_result_detail_card.test.tsx @@ -45,6 +45,7 @@ describe('ExampleResultDetailCard', () => { ...exampleResult, searchResultConfig: { detailFields: [{ fieldName: 'date', label: 'Date' }] }, exampleDocuments: [{ date }], + schemaFields: { date: 'date' }, }); const wrapper = shallow(); @@ -52,4 +53,17 @@ describe('ExampleResultDetailCard', () => { new Date(Date.parse(date)).toLocaleString() ); }); + + it('shows non-formatted value when not a date field', () => { + const value = '9999'; + setMockValues({ + ...exampleResult, + searchResultConfig: { detailFields: [{ fieldName: 'value', label: 'Value' }] }, + exampleDocuments: [{ value }], + schemaFields: { value: 'text' }, + }); + const wrapper = shallow(); + + expect(wrapper.find(EuiText).children().text()).toContain(value); + }); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_result_detail_card.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_result_detail_card.tsx index 8b0a72ac23e39..734e370e4c53d 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_result_detail_card.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/display_settings/example_result_detail_card.tsx @@ -12,6 +12,7 @@ import { useValues } from 'kea'; import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText, EuiTitle } from '@elastic/eui'; +import { SchemaType } from '../../../../../shared/schema/types'; import { URL_LABEL } from '../../../../constants'; import { getAsLocalDateTimeString } from '../../../../utils'; @@ -26,6 +27,7 @@ export const ExampleResultDetailCard: React.FC = () => { titleFieldHover, urlFieldHover, exampleDocuments, + schemaFields, } = useValues(DisplaySettingsLogic); const result = exampleDocuments[0]; @@ -63,7 +65,8 @@ export const ExampleResultDetailCard: React.FC = () => { {detailFields.length > 0 ? ( detailFields.map(({ fieldName, label }, index) => { const value = result[fieldName]; - const dateValue = getAsLocalDateTimeString(value); + const fieldType = (schemaFields as { [key: string]: SchemaType })[fieldName]; + const dateValue = fieldType === SchemaType.Date && getAsLocalDateTimeString(value); return (
{ - const { searchResultConfig, exampleDocuments } = exampleResult; + const { searchResultConfig, exampleDocuments, schemaFields } = exampleResult; const availableFieldOptions = [ { value: 'foo', @@ -70,6 +70,7 @@ describe('ResultDetail', () => { searchResultConfig, availableFieldOptions, exampleDocuments, + schemaFields, }); }); @@ -94,6 +95,7 @@ describe('ResultDetail', () => { }, availableFieldOptions, exampleDocuments, + schemaFields, }); const wrapper = shallow(); @@ -122,6 +124,7 @@ describe('ResultDetail', () => { }, availableFieldOptions, exampleDocuments, + schemaFields, }); const wrapper = mount(); From 2c5ecd9b3f6198eac9f4b1eb2913cd866988f84d Mon Sep 17 00:00:00 2001 From: Deepak Sreekumar Date: Tue, 26 Oct 2021 11:54:27 +0530 Subject: [PATCH 05/58] chore: rename functions in aggregated_transactions helper (#116001) * Renamed methods and fixed imports * Fixed lint errors * Renamed file Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../chart_preview/get_transaction_duration.ts | 25 +++++++------------ .../get_transaction_error_rate.ts | 14 ++++------- ...egister_transaction_duration_alert_type.ts | 10 ++++---- ...ister_transaction_error_rate_alert_type.ts | 4 +-- .../lib/environments/get_all_environments.ts | 6 ++--- .../lib/environments/get_environments.ts | 6 ++--- ...t_is_using_transaction_events.test.ts.snap | 0 .../get_is_using_transaction_events.test.ts | 0 .../get_is_using_transaction_events.ts | 0 .../index.ts | 6 ++--- .../get_service_count.ts | 6 ++--- .../get_transactions_per_minute.ts | 12 ++++----- .../get_service_map_service_node_info.ts | 18 ++++++------- .../get_derived_service_annotations.ts | 18 +++++-------- .../server/lib/services/get_service_agent.ts | 6 ++--- .../get_service_instance_metadata_details.ts | 12 ++++----- ...ervice_instances_transaction_statistics.ts | 22 ++++++---------- .../services/get_service_metadata_details.ts | 6 ++--- .../services/get_service_metadata_icons.ts | 6 ++--- ...e_transaction_group_detailed_statistics.ts | 16 ++++++------ .../get_service_transaction_groups.ts | 16 ++++++------ .../services/get_service_transaction_types.ts | 14 ++++------- .../get_service_transaction_stats.ts | 16 ++++++------ ...service_transaction_detailed_statistics.ts | 16 ++++++------ .../apm/server/lib/services/get_throughput.ts | 16 ++++-------- .../agent_configuration/get_service_names.ts | 6 ++--- .../server/lib/suggestions/get_suggestions.ts | 6 ++--- .../server/lib/transaction_groups/fetcher.ts | 14 ++++------- .../lib/transaction_groups/get_error_rate.ts | 16 ++++-------- .../get_transaction_group_stats.ts | 6 ++--- .../transactions/get_latency_charts/index.ts | 25 +++++++------------ .../apm/server/projections/services.ts | 6 ++--- .../plugins/apm/server/routes/environments.ts | 2 +- .../server/routes/fallback_to_transactions.ts | 2 +- .../server/routes/observability_overview.ts | 2 +- .../plugins/apm/server/routes/service_map.ts | 2 +- x-pack/plugins/apm/server/routes/services.ts | 2 +- .../routes/settings/agent_configuration.ts | 2 +- .../routes/settings/anomaly_detection.ts | 2 +- .../plugins/apm/server/routes/suggestions.ts | 2 +- x-pack/plugins/apm/server/routes/traces.ts | 2 +- .../plugins/apm/server/routes/transactions.ts | 2 +- 42 files changed, 143 insertions(+), 227 deletions(-) rename x-pack/plugins/apm/server/lib/helpers/{aggregated_transactions => transactions}/__snapshots__/get_is_using_transaction_events.test.ts.snap (100%) rename x-pack/plugins/apm/server/lib/helpers/{aggregated_transactions => transactions}/get_is_using_transaction_events.test.ts (100%) rename x-pack/plugins/apm/server/lib/helpers/{aggregated_transactions => transactions}/get_is_using_transaction_events.ts (100%) rename x-pack/plugins/apm/server/lib/helpers/{aggregated_transactions => transactions}/index.ts (92%) diff --git a/x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_duration.ts b/x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_duration.ts index 1f8b88b3db3e7..1359f4b925973 100644 --- a/x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_duration.ts +++ b/x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_duration.ts @@ -14,11 +14,11 @@ import { import { environmentQuery } from '../../../../common/utils/environment_query'; import { AlertParams } from '../../../routes/alerts/chart_preview'; import { - getDocumentTypeFilterForAggregatedTransactions, - getProcessorEventForAggregatedTransactions, getSearchAggregatedTransactions, - getTransactionDurationFieldForAggregatedTransactions, -} from '../../helpers/aggregated_transactions'; + getDocumentTypeFilterForTransactions, + getTransactionDurationFieldForTransactions, + getProcessorEventForTransactions, +} from '../../helpers/transactions'; import { Setup } from '../../helpers/setup_request'; export async function getTransactionDurationChartPreview({ @@ -52,17 +52,14 @@ export async function getTransactionDurationChartPreview({ : []), ...rangeQuery(start, end), ...environmentQuery(environment), - ...getDocumentTypeFilterForAggregatedTransactions( - searchAggregatedTransactions - ), + ...getDocumentTypeFilterForTransactions(searchAggregatedTransactions), ] as QueryDslQueryContainer[], }, }; - const transactionDurationField = - getTransactionDurationFieldForAggregatedTransactions( - searchAggregatedTransactions - ); + const transactionDurationField = getTransactionDurationFieldForTransactions( + searchAggregatedTransactions + ); const aggs = { timeseries: { @@ -90,11 +87,7 @@ export async function getTransactionDurationChartPreview({ }; const params = { apm: { - events: [ - getProcessorEventForAggregatedTransactions( - searchAggregatedTransactions - ), - ], + events: [getProcessorEventForTransactions(searchAggregatedTransactions)], }, body: { size: 0, query, aggs }, }; diff --git a/x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_error_rate.ts b/x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_error_rate.ts index 1690c92b23e66..d3f03c597e8fb 100644 --- a/x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_error_rate.ts +++ b/x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_error_rate.ts @@ -13,10 +13,10 @@ import { import { environmentQuery } from '../../../../common/utils/environment_query'; import { AlertParams } from '../../../routes/alerts/chart_preview'; import { - getDocumentTypeFilterForAggregatedTransactions, - getProcessorEventForAggregatedTransactions, getSearchAggregatedTransactions, -} from '../../helpers/aggregated_transactions'; + getDocumentTypeFilterForTransactions, + getProcessorEventForTransactions, +} from '../../helpers/transactions'; import { Setup } from '../../helpers/setup_request'; import { calculateFailedTransactionRate, @@ -45,11 +45,7 @@ export async function getTransactionErrorRateChartPreview({ const params = { apm: { - events: [ - getProcessorEventForAggregatedTransactions( - searchAggregatedTransactions - ), - ], + events: [getProcessorEventForTransactions(searchAggregatedTransactions)], }, body: { size: 0, @@ -62,7 +58,7 @@ export async function getTransactionErrorRateChartPreview({ : []), ...rangeQuery(start, end), ...environmentQuery(environment), - ...getDocumentTypeFilterForAggregatedTransactions( + ...getDocumentTypeFilterForTransactions( searchAggregatedTransactions ), ], diff --git a/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_alert_type.ts b/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_alert_type.ts index df4de254346c9..698bbcdbdb84a 100644 --- a/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_alert_type.ts +++ b/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_alert_type.ts @@ -41,9 +41,9 @@ import { ProcessorEvent } from '../../../common/processor_event'; import { environmentQuery } from '../../../common/utils/environment_query'; import { getDurationFormatter } from '../../../common/utils/formatters'; import { - getDocumentTypeFilterForAggregatedTransactions, - getTransactionDurationFieldForAggregatedTransactions, -} from '../helpers/aggregated_transactions'; + getDocumentTypeFilterForTransactions, + getTransactionDurationFieldForTransactions, +} from '../helpers/transactions'; import { getApmIndices } from '../settings/apm_indices/get_apm_indices'; import { apmActionVariables } from './action_variables'; import { alertingEsClient } from './alerting_es_client'; @@ -122,7 +122,7 @@ export function registerTransactionDurationAlertType({ ? indices.metric : indices.transaction; - const field = getTransactionDurationFieldForAggregatedTransactions( + const field = getTransactionDurationFieldForTransactions( searchAggregatedTransactions ); @@ -140,7 +140,7 @@ export function registerTransactionDurationAlertType({ }, }, }, - ...getDocumentTypeFilterForAggregatedTransactions( + ...getDocumentTypeFilterForTransactions( searchAggregatedTransactions ), { term: { [SERVICE_NAME]: alertParams.serviceName } }, diff --git a/x-pack/plugins/apm/server/lib/alerts/register_transaction_error_rate_alert_type.ts b/x-pack/plugins/apm/server/lib/alerts/register_transaction_error_rate_alert_type.ts index 598487d02625a..5ba7ed5321d70 100644 --- a/x-pack/plugins/apm/server/lib/alerts/register_transaction_error_rate_alert_type.ts +++ b/x-pack/plugins/apm/server/lib/alerts/register_transaction_error_rate_alert_type.ts @@ -46,7 +46,7 @@ import { apmActionVariables } from './action_variables'; import { alertingEsClient } from './alerting_es_client'; import { RegisterRuleDependencies } from './register_apm_alerts'; import { SearchAggregatedTransactionSetting } from '../../../common/aggregated_transactions'; -import { getDocumentTypeFilterForAggregatedTransactions } from '../helpers/aggregated_transactions'; +import { getDocumentTypeFilterForTransactions } from '../helpers/transactions'; import { asPercent } from '../../../../observability/common/utils/formatters'; const ALERT_EVALUATION_THRESHOLD: typeof ALERT_EVALUATION_THRESHOLD_TYPED = @@ -131,7 +131,7 @@ export function registerTransactionErrorRateAlertType({ }, }, }, - ...getDocumentTypeFilterForAggregatedTransactions( + ...getDocumentTypeFilterForTransactions( searchAggregatedTransactions ), { diff --git a/x-pack/plugins/apm/server/lib/environments/get_all_environments.ts b/x-pack/plugins/apm/server/lib/environments/get_all_environments.ts index 1ddc3f7ed888c..d6c53aeea078e 100644 --- a/x-pack/plugins/apm/server/lib/environments/get_all_environments.ts +++ b/x-pack/plugins/apm/server/lib/environments/get_all_environments.ts @@ -12,7 +12,7 @@ import { SERVICE_ENVIRONMENT, } from '../../../common/elasticsearch_fieldnames'; import { ENVIRONMENT_NOT_DEFINED } from '../../../common/environment_filter_values'; -import { getProcessorEventForAggregatedTransactions } from '../helpers/aggregated_transactions'; +import { getProcessorEventForTransactions } from '../helpers/transactions'; /** * This is used for getting *all* environments, and does not filter by range. @@ -45,9 +45,7 @@ export async function getAllEnvironments({ const params = { apm: { events: [ - getProcessorEventForAggregatedTransactions( - searchAggregatedTransactions - ), + getProcessorEventForTransactions(searchAggregatedTransactions), ProcessorEvent.error, ProcessorEvent.metric, ], diff --git a/x-pack/plugins/apm/server/lib/environments/get_environments.ts b/x-pack/plugins/apm/server/lib/environments/get_environments.ts index 08f6f089e8d08..678cfd891ae57 100644 --- a/x-pack/plugins/apm/server/lib/environments/get_environments.ts +++ b/x-pack/plugins/apm/server/lib/environments/get_environments.ts @@ -12,7 +12,7 @@ import { import { ENVIRONMENT_NOT_DEFINED } from '../../../common/environment_filter_values'; import { ProcessorEvent } from '../../../common/processor_event'; import { rangeQuery } from '../../../../observability/server'; -import { getProcessorEventForAggregatedTransactions } from '../helpers/aggregated_transactions'; +import { getProcessorEventForTransactions } from '../helpers/transactions'; import { Setup } from '../helpers/setup_request'; /** @@ -51,9 +51,7 @@ export async function getEnvironments({ const params = { apm: { events: [ - getProcessorEventForAggregatedTransactions( - searchAggregatedTransactions - ), + getProcessorEventForTransactions(searchAggregatedTransactions), ProcessorEvent.metric, ProcessorEvent.error, ], diff --git a/x-pack/plugins/apm/server/lib/helpers/aggregated_transactions/__snapshots__/get_is_using_transaction_events.test.ts.snap b/x-pack/plugins/apm/server/lib/helpers/transactions/__snapshots__/get_is_using_transaction_events.test.ts.snap similarity index 100% rename from x-pack/plugins/apm/server/lib/helpers/aggregated_transactions/__snapshots__/get_is_using_transaction_events.test.ts.snap rename to x-pack/plugins/apm/server/lib/helpers/transactions/__snapshots__/get_is_using_transaction_events.test.ts.snap diff --git a/x-pack/plugins/apm/server/lib/helpers/aggregated_transactions/get_is_using_transaction_events.test.ts b/x-pack/plugins/apm/server/lib/helpers/transactions/get_is_using_transaction_events.test.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/helpers/aggregated_transactions/get_is_using_transaction_events.test.ts rename to x-pack/plugins/apm/server/lib/helpers/transactions/get_is_using_transaction_events.test.ts diff --git a/x-pack/plugins/apm/server/lib/helpers/aggregated_transactions/get_is_using_transaction_events.ts b/x-pack/plugins/apm/server/lib/helpers/transactions/get_is_using_transaction_events.ts similarity index 100% rename from x-pack/plugins/apm/server/lib/helpers/aggregated_transactions/get_is_using_transaction_events.ts rename to x-pack/plugins/apm/server/lib/helpers/transactions/get_is_using_transaction_events.ts diff --git a/x-pack/plugins/apm/server/lib/helpers/aggregated_transactions/index.ts b/x-pack/plugins/apm/server/lib/helpers/transactions/index.ts similarity index 92% rename from x-pack/plugins/apm/server/lib/helpers/aggregated_transactions/index.ts rename to x-pack/plugins/apm/server/lib/helpers/transactions/index.ts index a58a95dd43fcc..f16e03ddc3ea4 100644 --- a/x-pack/plugins/apm/server/lib/helpers/aggregated_transactions/index.ts +++ b/x-pack/plugins/apm/server/lib/helpers/transactions/index.ts @@ -77,7 +77,7 @@ export async function getSearchAggregatedTransactions({ ); } -export function getTransactionDurationFieldForAggregatedTransactions( +export function getTransactionDurationFieldForTransactions( searchAggregatedTransactions: boolean ) { return searchAggregatedTransactions @@ -85,7 +85,7 @@ export function getTransactionDurationFieldForAggregatedTransactions( : TRANSACTION_DURATION; } -export function getDocumentTypeFilterForAggregatedTransactions( +export function getDocumentTypeFilterForTransactions( searchAggregatedTransactions: boolean ) { return searchAggregatedTransactions @@ -93,7 +93,7 @@ export function getDocumentTypeFilterForAggregatedTransactions( : []; } -export function getProcessorEventForAggregatedTransactions( +export function getProcessorEventForTransactions( searchAggregatedTransactions: boolean ): ProcessorEvent.metric | ProcessorEvent.transaction { return searchAggregatedTransactions diff --git a/x-pack/plugins/apm/server/lib/observability_overview/get_service_count.ts b/x-pack/plugins/apm/server/lib/observability_overview/get_service_count.ts index a181b1a41fbc7..3eb11f668115d 100644 --- a/x-pack/plugins/apm/server/lib/observability_overview/get_service_count.ts +++ b/x-pack/plugins/apm/server/lib/observability_overview/get_service_count.ts @@ -9,7 +9,7 @@ import { ProcessorEvent } from '../../../common/processor_event'; import { rangeQuery } from '../../../../observability/server'; import { SERVICE_NAME } from '../../../common/elasticsearch_fieldnames'; import { Setup } from '../helpers/setup_request'; -import { getProcessorEventForAggregatedTransactions } from '../helpers/aggregated_transactions'; +import { getProcessorEventForTransactions } from '../helpers/transactions'; export async function getServiceCount({ setup, @@ -27,9 +27,7 @@ export async function getServiceCount({ const params = { apm: { events: [ - getProcessorEventForAggregatedTransactions( - searchAggregatedTransactions - ), + getProcessorEventForTransactions(searchAggregatedTransactions), ProcessorEvent.error, ProcessorEvent.metric, ], diff --git a/x-pack/plugins/apm/server/lib/observability_overview/get_transactions_per_minute.ts b/x-pack/plugins/apm/server/lib/observability_overview/get_transactions_per_minute.ts index 8c64670f5d2e9..829afa8330164 100644 --- a/x-pack/plugins/apm/server/lib/observability_overview/get_transactions_per_minute.ts +++ b/x-pack/plugins/apm/server/lib/observability_overview/get_transactions_per_minute.ts @@ -13,9 +13,9 @@ import { TRANSACTION_TYPE } from '../../../common/elasticsearch_fieldnames'; import { rangeQuery } from '../../../../observability/server'; import { Setup } from '../helpers/setup_request'; import { - getDocumentTypeFilterForAggregatedTransactions, - getProcessorEventForAggregatedTransactions, -} from '../helpers/aggregated_transactions'; + getDocumentTypeFilterForTransactions, + getProcessorEventForTransactions, +} from '../helpers/transactions'; import { calculateThroughputWithInterval, calculateThroughputWithRange, @@ -43,9 +43,7 @@ export async function getTransactionsPerMinute({ { apm: { events: [ - getProcessorEventForAggregatedTransactions( - searchAggregatedTransactions - ), + getProcessorEventForTransactions(searchAggregatedTransactions), ], }, body: { @@ -54,7 +52,7 @@ export async function getTransactionsPerMinute({ bool: { filter: [ ...rangeQuery(start, end), - ...getDocumentTypeFilterForAggregatedTransactions( + ...getDocumentTypeFilterForTransactions( searchAggregatedTransactions ), ], diff --git a/x-pack/plugins/apm/server/lib/service_map/get_service_map_service_node_info.ts b/x-pack/plugins/apm/server/lib/service_map/get_service_map_service_node_info.ts index 78ca3fad63189..43147684ef3f7 100644 --- a/x-pack/plugins/apm/server/lib/service_map/get_service_map_service_node_info.ts +++ b/x-pack/plugins/apm/server/lib/service_map/get_service_map_service_node_info.ts @@ -23,10 +23,10 @@ import { rangeQuery } from '../../../../observability/server'; import { environmentQuery } from '../../../common/utils/environment_query'; import { withApmSpan } from '../../utils/with_apm_span'; import { - getDocumentTypeFilterForAggregatedTransactions, - getProcessorEventForAggregatedTransactions, - getTransactionDurationFieldForAggregatedTransactions, -} from '../helpers/aggregated_transactions'; + getDocumentTypeFilterForTransactions, + getTransactionDurationFieldForTransactions, + getProcessorEventForTransactions, +} from '../helpers/transactions'; import { Setup } from '../helpers/setup_request'; import { percentCgroupMemoryUsedScript, @@ -131,11 +131,7 @@ async function getTransactionStats({ const params = { apm: { - events: [ - getProcessorEventForAggregatedTransactions( - searchAggregatedTransactions - ), - ], + events: [getProcessorEventForTransactions(searchAggregatedTransactions)], }, body: { size: 0, @@ -143,7 +139,7 @@ async function getTransactionStats({ bool: { filter: [ ...filter, - ...getDocumentTypeFilterForAggregatedTransactions( + ...getDocumentTypeFilterForTransactions( searchAggregatedTransactions ), { @@ -161,7 +157,7 @@ async function getTransactionStats({ aggs: { duration: { avg: { - field: getTransactionDurationFieldForAggregatedTransactions( + field: getTransactionDurationFieldForTransactions( searchAggregatedTransactions ), }, diff --git a/x-pack/plugins/apm/server/lib/services/annotations/get_derived_service_annotations.ts b/x-pack/plugins/apm/server/lib/services/annotations/get_derived_service_annotations.ts index 3af9b557dd127..22b37e33a26e2 100644 --- a/x-pack/plugins/apm/server/lib/services/annotations/get_derived_service_annotations.ts +++ b/x-pack/plugins/apm/server/lib/services/annotations/get_derived_service_annotations.ts @@ -15,9 +15,9 @@ import { import { rangeQuery } from '../../../../../observability/server'; import { environmentQuery } from '../../../../common/utils/environment_query'; import { - getDocumentTypeFilterForAggregatedTransactions, - getProcessorEventForAggregatedTransactions, -} from '../../helpers/aggregated_transactions'; + getDocumentTypeFilterForTransactions, + getProcessorEventForTransactions, +} from '../../helpers/transactions'; import { Setup } from '../../helpers/setup_request'; export async function getDerivedServiceAnnotations({ @@ -39,9 +39,7 @@ export async function getDerivedServiceAnnotations({ const filter: ESFilter[] = [ { term: { [SERVICE_NAME]: serviceName } }, - ...getDocumentTypeFilterForAggregatedTransactions( - searchAggregatedTransactions - ), + ...getDocumentTypeFilterForTransactions(searchAggregatedTransactions), ...environmentQuery(environment), ]; @@ -50,9 +48,7 @@ export async function getDerivedServiceAnnotations({ await apmEventClient.search('get_derived_service_annotations', { apm: { events: [ - getProcessorEventForAggregatedTransactions( - searchAggregatedTransactions - ), + getProcessorEventForTransactions(searchAggregatedTransactions), ], }, body: { @@ -83,9 +79,7 @@ export async function getDerivedServiceAnnotations({ { apm: { events: [ - getProcessorEventForAggregatedTransactions( - searchAggregatedTransactions - ), + getProcessorEventForTransactions(searchAggregatedTransactions), ], }, body: { diff --git a/x-pack/plugins/apm/server/lib/services/get_service_agent.ts b/x-pack/plugins/apm/server/lib/services/get_service_agent.ts index a9bb3c8f3103f..5ef29437d73d6 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_agent.ts +++ b/x-pack/plugins/apm/server/lib/services/get_service_agent.ts @@ -13,7 +13,7 @@ import { } from '../../../common/elasticsearch_fieldnames'; import { rangeQuery } from '../../../../observability/server'; import { Setup } from '../helpers/setup_request'; -import { getProcessorEventForAggregatedTransactions } from '../helpers/aggregated_transactions'; +import { getProcessorEventForTransactions } from '../helpers/transactions'; interface ServiceAgent { agent?: { @@ -46,9 +46,7 @@ export async function getServiceAgent({ apm: { events: [ ProcessorEvent.error, - getProcessorEventForAggregatedTransactions( - searchAggregatedTransactions - ), + getProcessorEventForTransactions(searchAggregatedTransactions), ProcessorEvent.metric, ], }, diff --git a/x-pack/plugins/apm/server/lib/services/get_service_instance_metadata_details.ts b/x-pack/plugins/apm/server/lib/services/get_service_instance_metadata_details.ts index ba122ea5ad0e6..d349ca3ce0399 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_instance_metadata_details.ts +++ b/x-pack/plugins/apm/server/lib/services/get_service_instance_metadata_details.ts @@ -15,9 +15,9 @@ import { rangeQuery } from '../../../../observability/server'; import { Setup } from '../helpers/setup_request'; import { maybe } from '../../../common/utils/maybe'; import { - getDocumentTypeFilterForAggregatedTransactions, - getProcessorEventForAggregatedTransactions, -} from '../helpers/aggregated_transactions'; + getDocumentTypeFilterForTransactions, + getProcessorEventForTransactions, +} from '../helpers/transactions'; export async function getServiceInstanceMetadataDetails({ serviceName, @@ -84,16 +84,14 @@ export async function getServiceInstanceMetadataDetails({ 'get_service_instance_metadata_details_application_transaction_metric', { apm: { - events: [getProcessorEventForAggregatedTransactions(true)], + events: [getProcessorEventForTransactions(true)], }, body: { terminate_after: 1, size: 1, query: { bool: { - filter: filter.concat( - getDocumentTypeFilterForAggregatedTransactions(true) - ), + filter: filter.concat(getDocumentTypeFilterForTransactions(true)), }, }, }, diff --git a/x-pack/plugins/apm/server/lib/services/get_service_instances/get_service_instances_transaction_statistics.ts b/x-pack/plugins/apm/server/lib/services/get_service_instances/get_service_instances_transaction_statistics.ts index ec76e0d35e5c0..b0f64036a1845 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_instances/get_service_instances_transaction_statistics.ts +++ b/x-pack/plugins/apm/server/lib/services/get_service_instances/get_service_instances_transaction_statistics.ts @@ -17,10 +17,10 @@ import { Coordinate } from '../../../../typings/timeseries'; import { kqlQuery, rangeQuery } from '../../../../../observability/server'; import { environmentQuery } from '../../../../common/utils/environment_query'; import { - getDocumentTypeFilterForAggregatedTransactions, - getProcessorEventForAggregatedTransactions, - getTransactionDurationFieldForAggregatedTransactions, -} from '../../helpers/aggregated_transactions'; + getDocumentTypeFilterForTransactions, + getTransactionDurationFieldForTransactions, + getProcessorEventForTransactions, +} from '../../helpers/transactions'; import { calculateThroughput } from '../../helpers/calculate_throughput'; import { getBucketSizeForAggregatedTransactions } from '../../helpers/get_bucket_size_for_aggregated_transactions'; import { @@ -89,7 +89,7 @@ export async function getServiceInstancesTransactionStatistics< } ); - const field = getTransactionDurationFieldForAggregatedTransactions( + const field = getTransactionDurationFieldForTransactions( searchAggregatedTransactions ); @@ -109,15 +109,11 @@ export async function getServiceInstancesTransactionStatistics< filter: [ { term: { [SERVICE_NAME]: serviceName } }, { term: { [TRANSACTION_TYPE]: transactionType } }, - ...getDocumentTypeFilterForAggregatedTransactions( - searchAggregatedTransactions - ), + ...getDocumentTypeFilterForTransactions(searchAggregatedTransactions), ...rangeQuery(start, end), ...environmentQuery(environment), ...kqlQuery(kuery), - ...getDocumentTypeFilterForAggregatedTransactions( - searchAggregatedTransactions - ), + ...getDocumentTypeFilterForTransactions(searchAggregatedTransactions), ...(isComparisonSearch && serviceNodeIds ? [{ terms: { [SERVICE_NODE_NAME]: serviceNodeIds } }] : []), @@ -154,9 +150,7 @@ export async function getServiceInstancesTransactionStatistics< { apm: { events: [ - getProcessorEventForAggregatedTransactions( - searchAggregatedTransactions - ), + getProcessorEventForTransactions(searchAggregatedTransactions), ], }, body: { size: 0, query, aggs }, diff --git a/x-pack/plugins/apm/server/lib/services/get_service_metadata_details.ts b/x-pack/plugins/apm/server/lib/services/get_service_metadata_details.ts index 7a39e953ad496..e2852a51b0c06 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_metadata_details.ts +++ b/x-pack/plugins/apm/server/lib/services/get_service_metadata_details.ts @@ -22,7 +22,7 @@ import { import { ContainerType } from '../../../common/service_metadata'; import { rangeQuery } from '../../../../observability/server'; import { TransactionRaw } from '../../../typings/es_schemas/raw/transaction_raw'; -import { getProcessorEventForAggregatedTransactions } from '../helpers/aggregated_transactions'; +import { getProcessorEventForTransactions } from '../helpers/transactions'; import { Setup } from '../helpers/setup_request'; import { should } from './get_service_metadata_icons'; @@ -81,9 +81,7 @@ export async function getServiceMetadataDetails({ const params = { apm: { events: [ - getProcessorEventForAggregatedTransactions( - searchAggregatedTransactions - ), + getProcessorEventForTransactions(searchAggregatedTransactions), ProcessorEvent.error, ProcessorEvent.metric, ], diff --git a/x-pack/plugins/apm/server/lib/services/get_service_metadata_icons.ts b/x-pack/plugins/apm/server/lib/services/get_service_metadata_icons.ts index 26a3090946ff8..2c93a298cb134 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_metadata_icons.ts +++ b/x-pack/plugins/apm/server/lib/services/get_service_metadata_icons.ts @@ -18,7 +18,7 @@ import { import { ContainerType } from '../../../common/service_metadata'; import { rangeQuery } from '../../../../observability/server'; import { TransactionRaw } from '../../../typings/es_schemas/raw/transaction_raw'; -import { getProcessorEventForAggregatedTransactions } from '../helpers/aggregated_transactions'; +import { getProcessorEventForTransactions } from '../helpers/transactions'; import { Setup } from '../helpers/setup_request'; type ServiceMetadataIconsRaw = Pick< @@ -63,9 +63,7 @@ export async function getServiceMetadataIcons({ const params = { apm: { events: [ - getProcessorEventForAggregatedTransactions( - searchAggregatedTransactions - ), + getProcessorEventForTransactions(searchAggregatedTransactions), ProcessorEvent.error, ProcessorEvent.metric, ], diff --git a/x-pack/plugins/apm/server/lib/services/get_service_transaction_group_detailed_statistics.ts b/x-pack/plugins/apm/server/lib/services/get_service_transaction_group_detailed_statistics.ts index feab6d78f02c8..35256e6a7ecd6 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_transaction_group_detailed_statistics.ts +++ b/x-pack/plugins/apm/server/lib/services/get_service_transaction_group_detailed_statistics.ts @@ -19,10 +19,10 @@ import { kqlQuery, rangeQuery } from '../../../../observability/server'; import { environmentQuery } from '../../../common/utils/environment_query'; import { Coordinate } from '../../../typings/timeseries'; import { - getDocumentTypeFilterForAggregatedTransactions, - getProcessorEventForAggregatedTransactions, - getTransactionDurationFieldForAggregatedTransactions, -} from '../helpers/aggregated_transactions'; + getDocumentTypeFilterForTransactions, + getTransactionDurationFieldForTransactions, + getProcessorEventForTransactions, +} from '../helpers/transactions'; import { getBucketSizeForAggregatedTransactions } from '../helpers/get_bucket_size_for_aggregated_transactions'; import { getLatencyAggregation, @@ -72,7 +72,7 @@ export async function getServiceTransactionGroupDetailedStatistics({ searchAggregatedTransactions, }); - const field = getTransactionDurationFieldForAggregatedTransactions( + const field = getTransactionDurationFieldForTransactions( searchAggregatedTransactions ); @@ -81,9 +81,7 @@ export async function getServiceTransactionGroupDetailedStatistics({ { apm: { events: [ - getProcessorEventForAggregatedTransactions( - searchAggregatedTransactions - ), + getProcessorEventForTransactions(searchAggregatedTransactions), ], }, body: { @@ -93,7 +91,7 @@ export async function getServiceTransactionGroupDetailedStatistics({ filter: [ { term: { [SERVICE_NAME]: serviceName } }, { term: { [TRANSACTION_TYPE]: transactionType } }, - ...getDocumentTypeFilterForAggregatedTransactions( + ...getDocumentTypeFilterForTransactions( searchAggregatedTransactions ), ...rangeQuery(start, end), diff --git a/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups.ts b/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups.ts index fbc1e2880495b..7f624693a3b9c 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups.ts +++ b/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups.ts @@ -16,10 +16,10 @@ import { LatencyAggregationType } from '../../../common/latency_aggregation_type import { rangeQuery, kqlQuery } from '../../../../observability/server'; import { environmentQuery } from '../../../common/utils/environment_query'; import { - getDocumentTypeFilterForAggregatedTransactions, - getProcessorEventForAggregatedTransactions, - getTransactionDurationFieldForAggregatedTransactions, -} from '../helpers/aggregated_transactions'; + getDocumentTypeFilterForTransactions, + getTransactionDurationFieldForTransactions, + getProcessorEventForTransactions, +} from '../helpers/transactions'; import { calculateThroughput } from '../helpers/calculate_throughput'; import { getLatencyAggregation, @@ -59,7 +59,7 @@ export async function getServiceTransactionGroups({ const { apmEventClient, config } = setup; const bucketSize = config.ui.transactionGroupBucketSize; - const field = getTransactionDurationFieldForAggregatedTransactions( + const field = getTransactionDurationFieldForTransactions( searchAggregatedTransactions ); @@ -68,9 +68,7 @@ export async function getServiceTransactionGroups({ { apm: { events: [ - getProcessorEventForAggregatedTransactions( - searchAggregatedTransactions - ), + getProcessorEventForTransactions(searchAggregatedTransactions), ], }, body: { @@ -80,7 +78,7 @@ export async function getServiceTransactionGroups({ filter: [ { term: { [SERVICE_NAME]: serviceName } }, { term: { [TRANSACTION_TYPE]: transactionType } }, - ...getDocumentTypeFilterForAggregatedTransactions( + ...getDocumentTypeFilterForTransactions( searchAggregatedTransactions ), ...rangeQuery(start, end), diff --git a/x-pack/plugins/apm/server/lib/services/get_service_transaction_types.ts b/x-pack/plugins/apm/server/lib/services/get_service_transaction_types.ts index 9e3d39e7f2801..1c2d1c9207bc3 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_transaction_types.ts +++ b/x-pack/plugins/apm/server/lib/services/get_service_transaction_types.ts @@ -12,9 +12,9 @@ import { import { rangeQuery } from '../../../../observability/server'; import { Setup } from '../helpers/setup_request'; import { - getDocumentTypeFilterForAggregatedTransactions, - getProcessorEventForAggregatedTransactions, -} from '../helpers/aggregated_transactions'; + getDocumentTypeFilterForTransactions, + getProcessorEventForTransactions, +} from '../helpers/transactions'; export async function getServiceTransactionTypes({ setup, @@ -33,18 +33,14 @@ export async function getServiceTransactionTypes({ const params = { apm: { - events: [ - getProcessorEventForAggregatedTransactions( - searchAggregatedTransactions - ), - ], + events: [getProcessorEventForTransactions(searchAggregatedTransactions)], }, body: { size: 0, query: { bool: { filter: [ - ...getDocumentTypeFilterForAggregatedTransactions( + ...getDocumentTypeFilterForTransactions( searchAggregatedTransactions ), { term: { [SERVICE_NAME]: serviceName } }, diff --git a/x-pack/plugins/apm/server/lib/services/get_services/get_service_transaction_stats.ts b/x-pack/plugins/apm/server/lib/services/get_services/get_service_transaction_stats.ts index 24d2640024d28..36903f9ca229f 100644 --- a/x-pack/plugins/apm/server/lib/services/get_services/get_service_transaction_stats.ts +++ b/x-pack/plugins/apm/server/lib/services/get_services/get_service_transaction_stats.ts @@ -19,10 +19,10 @@ import { import { environmentQuery } from '../../../../common/utils/environment_query'; import { AgentName } from '../../../../typings/es_schemas/ui/fields/agent'; import { - getDocumentTypeFilterForAggregatedTransactions, - getProcessorEventForAggregatedTransactions, - getTransactionDurationFieldForAggregatedTransactions, -} from '../../helpers/aggregated_transactions'; + getDocumentTypeFilterForTransactions, + getTransactionDurationFieldForTransactions, + getProcessorEventForTransactions, +} from '../../helpers/transactions'; import { calculateThroughput } from '../../helpers/calculate_throughput'; import { calculateFailedTransactionRate, @@ -56,7 +56,7 @@ export async function getServiceTransactionStats({ const metrics = { avg_duration: { avg: { - field: getTransactionDurationFieldForAggregatedTransactions( + field: getTransactionDurationFieldForTransactions( searchAggregatedTransactions ), }, @@ -69,9 +69,7 @@ export async function getServiceTransactionStats({ { apm: { events: [ - getProcessorEventForAggregatedTransactions( - searchAggregatedTransactions - ), + getProcessorEventForTransactions(searchAggregatedTransactions), ], }, body: { @@ -79,7 +77,7 @@ export async function getServiceTransactionStats({ query: { bool: { filter: [ - ...getDocumentTypeFilterForAggregatedTransactions( + ...getDocumentTypeFilterForTransactions( searchAggregatedTransactions ), ...rangeQuery(start, end), diff --git a/x-pack/plugins/apm/server/lib/services/get_services_detailed_statistics/get_service_transaction_detailed_statistics.ts b/x-pack/plugins/apm/server/lib/services/get_services_detailed_statistics/get_service_transaction_detailed_statistics.ts index 14a37600bb4c3..686555e7764ab 100644 --- a/x-pack/plugins/apm/server/lib/services/get_services_detailed_statistics/get_service_transaction_detailed_statistics.ts +++ b/x-pack/plugins/apm/server/lib/services/get_services_detailed_statistics/get_service_transaction_detailed_statistics.ts @@ -18,10 +18,10 @@ import { import { environmentQuery } from '../../../../common/utils/environment_query'; import { getOffsetInMs } from '../../../../common/utils/get_offset_in_ms'; import { - getDocumentTypeFilterForAggregatedTransactions, - getProcessorEventForAggregatedTransactions, - getTransactionDurationFieldForAggregatedTransactions, -} from '../../helpers/aggregated_transactions'; + getDocumentTypeFilterForTransactions, + getTransactionDurationFieldForTransactions, + getProcessorEventForTransactions, +} from '../../helpers/transactions'; import { calculateThroughput } from '../../helpers/calculate_throughput'; import { getBucketSizeForAggregatedTransactions } from '../../helpers/get_bucket_size_for_aggregated_transactions'; import { Setup } from '../../helpers/setup_request'; @@ -61,7 +61,7 @@ export async function getServiceTransactionDetailedStatistics({ const metrics = { avg_duration: { avg: { - field: getTransactionDurationFieldForAggregatedTransactions( + field: getTransactionDurationFieldForTransactions( searchAggregatedTransactions ), }, @@ -74,9 +74,7 @@ export async function getServiceTransactionDetailedStatistics({ { apm: { events: [ - getProcessorEventForAggregatedTransactions( - searchAggregatedTransactions - ), + getProcessorEventForTransactions(searchAggregatedTransactions), ], }, body: { @@ -84,7 +82,7 @@ export async function getServiceTransactionDetailedStatistics({ query: { bool: { filter: [ - ...getDocumentTypeFilterForAggregatedTransactions( + ...getDocumentTypeFilterForTransactions( searchAggregatedTransactions ), ...rangeQuery(startWithOffset, endWithOffset), diff --git a/x-pack/plugins/apm/server/lib/services/get_throughput.ts b/x-pack/plugins/apm/server/lib/services/get_throughput.ts index 669203ad198b9..e31e9dd3b8c9f 100644 --- a/x-pack/plugins/apm/server/lib/services/get_throughput.ts +++ b/x-pack/plugins/apm/server/lib/services/get_throughput.ts @@ -14,9 +14,9 @@ import { import { kqlQuery, rangeQuery } from '../../../../observability/server'; import { environmentQuery } from '../../../common/utils/environment_query'; import { - getDocumentTypeFilterForAggregatedTransactions, - getProcessorEventForAggregatedTransactions, -} from '../helpers/aggregated_transactions'; + getDocumentTypeFilterForTransactions, + getProcessorEventForTransactions, +} from '../helpers/transactions'; import { Setup } from '../helpers/setup_request'; import { calculateThroughputWithInterval } from '../helpers/calculate_throughput'; @@ -52,9 +52,7 @@ export async function getThroughput({ const filter: ESFilter[] = [ { term: { [SERVICE_NAME]: serviceName } }, { term: { [TRANSACTION_TYPE]: transactionType } }, - ...getDocumentTypeFilterForAggregatedTransactions( - searchAggregatedTransactions - ), + ...getDocumentTypeFilterForTransactions(searchAggregatedTransactions), ...rangeQuery(start, end), ...environmentQuery(environment), ...kqlQuery(kuery), @@ -70,11 +68,7 @@ export async function getThroughput({ const params = { apm: { - events: [ - getProcessorEventForAggregatedTransactions( - searchAggregatedTransactions - ), - ], + events: [getProcessorEventForTransactions(searchAggregatedTransactions)], }, body: { size: 0, diff --git a/x-pack/plugins/apm/server/lib/settings/agent_configuration/get_service_names.ts b/x-pack/plugins/apm/server/lib/settings/agent_configuration/get_service_names.ts index 282eacbec66d1..06bd900872a20 100644 --- a/x-pack/plugins/apm/server/lib/settings/agent_configuration/get_service_names.ts +++ b/x-pack/plugins/apm/server/lib/settings/agent_configuration/get_service_names.ts @@ -10,7 +10,7 @@ import { Setup } from '../../helpers/setup_request'; import { PromiseReturnType } from '../../../../../observability/typings/common'; import { SERVICE_NAME } from '../../../../common/elasticsearch_fieldnames'; import { ALL_OPTION_VALUE } from '../../../../common/agent_configuration/all_option'; -import { getProcessorEventForAggregatedTransactions } from '../../helpers/aggregated_transactions'; +import { getProcessorEventForTransactions } from '../../helpers/transactions'; export type AgentConfigurationServicesAPIResponse = PromiseReturnType< typeof getServiceNames @@ -30,9 +30,7 @@ export async function getServiceNames({ const params = { apm: { events: [ - getProcessorEventForAggregatedTransactions( - searchAggregatedTransactions - ), + getProcessorEventForTransactions(searchAggregatedTransactions), ProcessorEvent.error, ProcessorEvent.metric, ], diff --git a/x-pack/plugins/apm/server/lib/suggestions/get_suggestions.ts b/x-pack/plugins/apm/server/lib/suggestions/get_suggestions.ts index acd44366ef4c3..5ea28debc4437 100644 --- a/x-pack/plugins/apm/server/lib/suggestions/get_suggestions.ts +++ b/x-pack/plugins/apm/server/lib/suggestions/get_suggestions.ts @@ -6,7 +6,7 @@ */ import { ProcessorEvent } from '../../../common/processor_event'; -import { getProcessorEventForAggregatedTransactions } from '../helpers/aggregated_transactions'; +import { getProcessorEventForTransactions } from '../helpers/transactions'; import { Setup } from '../helpers/setup_request'; export async function getSuggestions({ @@ -27,9 +27,7 @@ export async function getSuggestions({ const response = await apmEventClient.termsEnum('get_suggestions', { apm: { events: [ - getProcessorEventForAggregatedTransactions( - searchAggregatedTransactions - ), + getProcessorEventForTransactions(searchAggregatedTransactions), ProcessorEvent.error, ProcessorEvent.metric, ], diff --git a/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts b/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts index dc7cc0f804469..f082483c0c109 100644 --- a/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts +++ b/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts @@ -22,9 +22,9 @@ import { environmentQuery } from '../../../common/utils/environment_query'; import { joinByKey } from '../../../common/utils/join_by_key'; import { withApmSpan } from '../../utils/with_apm_span'; import { - getDocumentTypeFilterForAggregatedTransactions, - getProcessorEventForAggregatedTransactions, -} from '../helpers/aggregated_transactions'; + getDocumentTypeFilterForTransactions, + getProcessorEventForTransactions, +} from '../helpers/transactions'; import { Setup } from '../helpers/setup_request'; import { getAverages, getCounts, getSums } from './get_transaction_group_stats'; @@ -75,11 +75,7 @@ function getRequest(topTraceOptions: TopTraceOptions) { return { apm: { - events: [ - getProcessorEventForAggregatedTransactions( - searchAggregatedTransactions - ), - ], + events: [getProcessorEventForTransactions(searchAggregatedTransactions)], }, body: { size: 0, @@ -87,7 +83,7 @@ function getRequest(topTraceOptions: TopTraceOptions) { bool: { filter: [ ...transactionNameFilter, - ...getDocumentTypeFilterForAggregatedTransactions( + ...getDocumentTypeFilterForTransactions( searchAggregatedTransactions ), ...rangeQuery(start, end), diff --git a/x-pack/plugins/apm/server/lib/transaction_groups/get_error_rate.ts b/x-pack/plugins/apm/server/lib/transaction_groups/get_error_rate.ts index d57b0400abed9..e85bd61ac440a 100644 --- a/x-pack/plugins/apm/server/lib/transaction_groups/get_error_rate.ts +++ b/x-pack/plugins/apm/server/lib/transaction_groups/get_error_rate.ts @@ -17,9 +17,9 @@ import { kqlQuery, rangeQuery } from '../../../../observability/server'; import { environmentQuery } from '../../../common/utils/environment_query'; import { Coordinate } from '../../../typings/timeseries'; import { - getDocumentTypeFilterForAggregatedTransactions, - getProcessorEventForAggregatedTransactions, -} from '../helpers/aggregated_transactions'; + getDocumentTypeFilterForTransactions, + getProcessorEventForTransactions, +} from '../helpers/transactions'; import { getBucketSizeForAggregatedTransactions } from '../helpers/get_bucket_size_for_aggregated_transactions'; import { Setup } from '../helpers/setup_request'; import { @@ -71,9 +71,7 @@ export async function getErrorRate({ }, ...transactionNamefilter, ...transactionTypefilter, - ...getDocumentTypeFilterForAggregatedTransactions( - searchAggregatedTransactions - ), + ...getDocumentTypeFilterForTransactions(searchAggregatedTransactions), ...rangeQuery(start, end), ...environmentQuery(environment), ...kqlQuery(kuery), @@ -83,11 +81,7 @@ export async function getErrorRate({ const params = { apm: { - events: [ - getProcessorEventForAggregatedTransactions( - searchAggregatedTransactions - ), - ], + events: [getProcessorEventForTransactions(searchAggregatedTransactions)], }, body: { size: 0, diff --git a/x-pack/plugins/apm/server/lib/transaction_groups/get_transaction_group_stats.ts b/x-pack/plugins/apm/server/lib/transaction_groups/get_transaction_group_stats.ts index 980d8f10610c8..8769a572e33a0 100644 --- a/x-pack/plugins/apm/server/lib/transaction_groups/get_transaction_group_stats.ts +++ b/x-pack/plugins/apm/server/lib/transaction_groups/get_transaction_group_stats.ts @@ -10,7 +10,7 @@ import { estypes } from '@elastic/elasticsearch'; import { TRANSACTION_TYPE } from '../../../common/elasticsearch_fieldnames'; import { arrayUnionToCallable } from '../../../common/utils/array_union_to_callable'; import { TransactionGroupRequestBase, TransactionGroupSetup } from './fetcher'; -import { getTransactionDurationFieldForAggregatedTransactions } from '../helpers/aggregated_transactions'; +import { getTransactionDurationFieldForTransactions } from '../helpers/transactions'; interface MetricParams { request: TransactionGroupRequestBase; @@ -46,7 +46,7 @@ export async function getAverages({ const params = mergeRequestWithAggs(request, { avg: { avg: { - field: getTransactionDurationFieldForAggregatedTransactions( + field: getTransactionDurationFieldForTransactions( searchAggregatedTransactions ), }, @@ -110,7 +110,7 @@ export async function getSums({ const params = mergeRequestWithAggs(request, { sum: { sum: { - field: getTransactionDurationFieldForAggregatedTransactions( + field: getTransactionDurationFieldForTransactions( searchAggregatedTransactions ), }, diff --git a/x-pack/plugins/apm/server/lib/transactions/get_latency_charts/index.ts b/x-pack/plugins/apm/server/lib/transactions/get_latency_charts/index.ts index 01e2d905bbf21..c4bae841764cf 100644 --- a/x-pack/plugins/apm/server/lib/transactions/get_latency_charts/index.ts +++ b/x-pack/plugins/apm/server/lib/transactions/get_latency_charts/index.ts @@ -17,10 +17,10 @@ import { offsetPreviousPeriodCoordinates } from '../../../../common/utils/offset import { kqlQuery, rangeQuery } from '../../../../../observability/server'; import { environmentQuery } from '../../../../common/utils/environment_query'; import { - getDocumentTypeFilterForAggregatedTransactions, - getProcessorEventForAggregatedTransactions, - getTransactionDurationFieldForAggregatedTransactions, -} from '../../../lib/helpers/aggregated_transactions'; + getDocumentTypeFilterForTransactions, + getTransactionDurationFieldForTransactions, + getProcessorEventForTransactions, +} from '../../../lib/helpers/transactions'; import { Setup } from '../../../lib/helpers/setup_request'; import { getBucketSizeForAggregatedTransactions } from '../../helpers/get_bucket_size_for_aggregated_transactions'; import { @@ -63,9 +63,7 @@ function searchLatency({ const filter: ESFilter[] = [ { term: { [SERVICE_NAME]: serviceName } }, - ...getDocumentTypeFilterForAggregatedTransactions( - searchAggregatedTransactions - ), + ...getDocumentTypeFilterForTransactions(searchAggregatedTransactions), ...rangeQuery(start, end), ...environmentQuery(environment), ...kqlQuery(kuery), @@ -79,18 +77,13 @@ function searchLatency({ filter.push({ term: { [TRANSACTION_TYPE]: transactionType } }); } - const transactionDurationField = - getTransactionDurationFieldForAggregatedTransactions( - searchAggregatedTransactions - ); + const transactionDurationField = getTransactionDurationFieldForTransactions( + searchAggregatedTransactions + ); const params = { apm: { - events: [ - getProcessorEventForAggregatedTransactions( - searchAggregatedTransactions - ), - ], + events: [getProcessorEventForTransactions(searchAggregatedTransactions)], }, body: { size: 0, diff --git a/x-pack/plugins/apm/server/projections/services.ts b/x-pack/plugins/apm/server/projections/services.ts index afa6f4ba752f0..139c86acd5144 100644 --- a/x-pack/plugins/apm/server/projections/services.ts +++ b/x-pack/plugins/apm/server/projections/services.ts @@ -9,7 +9,7 @@ import { Setup } from '../../server/lib/helpers/setup_request'; import { SERVICE_NAME } from '../../common/elasticsearch_fieldnames'; import { rangeQuery, kqlQuery } from '../../../observability/server'; import { ProcessorEvent } from '../../common/processor_event'; -import { getProcessorEventForAggregatedTransactions } from '../lib/helpers/aggregated_transactions'; +import { getProcessorEventForTransactions } from '../lib/helpers/transactions'; export function getServicesProjection({ kuery, @@ -27,9 +27,7 @@ export function getServicesProjection({ return { apm: { events: [ - getProcessorEventForAggregatedTransactions( - searchAggregatedTransactions - ), + getProcessorEventForTransactions(searchAggregatedTransactions), ProcessorEvent.metric as const, ProcessorEvent.error as const, ], diff --git a/x-pack/plugins/apm/server/routes/environments.ts b/x-pack/plugins/apm/server/routes/environments.ts index 59e75f6f9c341..e54ad79f177c4 100644 --- a/x-pack/plugins/apm/server/routes/environments.ts +++ b/x-pack/plugins/apm/server/routes/environments.ts @@ -7,7 +7,7 @@ import * as t from 'io-ts'; import { maxSuggestions } from '../../../observability/common'; -import { getSearchAggregatedTransactions } from '../lib/helpers/aggregated_transactions'; +import { getSearchAggregatedTransactions } from '../lib/helpers/transactions'; import { setupRequest } from '../lib/helpers/setup_request'; import { getEnvironments } from '../lib/environments/get_environments'; import { rangeRt } from './default_api_types'; diff --git a/x-pack/plugins/apm/server/routes/fallback_to_transactions.ts b/x-pack/plugins/apm/server/routes/fallback_to_transactions.ts index ba74cc0b7a88a..99c6a290e34b1 100644 --- a/x-pack/plugins/apm/server/routes/fallback_to_transactions.ts +++ b/x-pack/plugins/apm/server/routes/fallback_to_transactions.ts @@ -6,7 +6,7 @@ */ import * as t from 'io-ts'; -import { getIsUsingTransactionEvents } from '../lib/helpers/aggregated_transactions/get_is_using_transaction_events'; +import { getIsUsingTransactionEvents } from '../lib/helpers/transactions/get_is_using_transaction_events'; import { setupRequest } from '../lib/helpers/setup_request'; import { createApmServerRoute } from './create_apm_server_route'; import { createApmServerRouteRepository } from './create_apm_server_route_repository'; diff --git a/x-pack/plugins/apm/server/routes/observability_overview.ts b/x-pack/plugins/apm/server/routes/observability_overview.ts index 0dbebd061e8be..2aff798f9ad0b 100644 --- a/x-pack/plugins/apm/server/routes/observability_overview.ts +++ b/x-pack/plugins/apm/server/routes/observability_overview.ts @@ -12,7 +12,7 @@ import { getServiceCount } from '../lib/observability_overview/get_service_count import { getTransactionsPerMinute } from '../lib/observability_overview/get_transactions_per_minute'; import { getHasData } from '../lib/observability_overview/has_data'; import { rangeRt } from './default_api_types'; -import { getSearchAggregatedTransactions } from '../lib/helpers/aggregated_transactions'; +import { getSearchAggregatedTransactions } from '../lib/helpers/transactions'; import { withApmSpan } from '../utils/with_apm_span'; import { createApmServerRouteRepository } from './create_apm_server_route_repository'; import { createApmServerRoute } from './create_apm_server_route'; diff --git a/x-pack/plugins/apm/server/routes/service_map.ts b/x-pack/plugins/apm/server/routes/service_map.ts index 17fb9d7c98c5f..038f909d7b334 100644 --- a/x-pack/plugins/apm/server/routes/service_map.ts +++ b/x-pack/plugins/apm/server/routes/service_map.ts @@ -10,7 +10,7 @@ import * as t from 'io-ts'; import { isActivePlatinumLicense } from '../../common/license_check'; import { invalidLicenseMessage } from '../../common/service_map'; import { notifyFeatureUsage } from '../feature'; -import { getSearchAggregatedTransactions } from '../lib/helpers/aggregated_transactions'; +import { getSearchAggregatedTransactions } from '../lib/helpers/transactions'; import { setupRequest } from '../lib/helpers/setup_request'; import { getServiceMap } from '../lib/service_map/get_service_map'; import { getServiceMapBackendNodeInfo } from '../lib/service_map/get_service_map_backend_node_info'; diff --git a/x-pack/plugins/apm/server/routes/services.ts b/x-pack/plugins/apm/server/routes/services.ts index f1f29dc2f036c..257aec216eb06 100644 --- a/x-pack/plugins/apm/server/routes/services.ts +++ b/x-pack/plugins/apm/server/routes/services.ts @@ -11,7 +11,7 @@ import * as t from 'io-ts'; import { uniq } from 'lodash'; import { latencyAggregationTypeRt } from '../../common/latency_aggregation_types'; import { ProfilingValueType } from '../../common/profiling'; -import { getSearchAggregatedTransactions } from '../lib/helpers/aggregated_transactions'; +import { getSearchAggregatedTransactions } from '../lib/helpers/transactions'; import { setupRequest } from '../lib/helpers/setup_request'; import { getServiceAnnotations } from '../lib/services/annotations'; import { getServices } from '../lib/services/get_services'; diff --git a/x-pack/plugins/apm/server/routes/settings/agent_configuration.ts b/x-pack/plugins/apm/server/routes/settings/agent_configuration.ts index a904e5e03b531..0488d0ebd01bd 100644 --- a/x-pack/plugins/apm/server/routes/settings/agent_configuration.ts +++ b/x-pack/plugins/apm/server/routes/settings/agent_configuration.ts @@ -24,7 +24,7 @@ import { serviceRt, agentConfigurationIntakeRt, } from '../../../common/agent_configuration/runtime_types/agent_configuration_intake_rt'; -import { getSearchAggregatedTransactions } from '../../lib/helpers/aggregated_transactions'; +import { getSearchAggregatedTransactions } from '../../lib/helpers/transactions'; import { createApmServerRouteRepository } from '../create_apm_server_route_repository'; import { syncAgentConfigsToApmPackagePolicies } from '../../lib/fleet/sync_agent_configs_to_apm_package_policies'; diff --git a/x-pack/plugins/apm/server/routes/settings/anomaly_detection.ts b/x-pack/plugins/apm/server/routes/settings/anomaly_detection.ts index 78db4e0c14b36..f614f35810c57 100644 --- a/x-pack/plugins/apm/server/routes/settings/anomaly_detection.ts +++ b/x-pack/plugins/apm/server/routes/settings/anomaly_detection.ts @@ -16,7 +16,7 @@ import { createAnomalyDetectionJobs } from '../../lib/anomaly_detection/create_a import { setupRequest } from '../../lib/helpers/setup_request'; import { getAllEnvironments } from '../../lib/environments/get_all_environments'; import { hasLegacyJobs } from '../../lib/anomaly_detection/has_legacy_jobs'; -import { getSearchAggregatedTransactions } from '../../lib/helpers/aggregated_transactions'; +import { getSearchAggregatedTransactions } from '../../lib/helpers/transactions'; import { notifyFeatureUsage } from '../../feature'; import { withApmSpan } from '../../utils/with_apm_span'; import { createApmServerRouteRepository } from '../create_apm_server_route_repository'; diff --git a/x-pack/plugins/apm/server/routes/suggestions.ts b/x-pack/plugins/apm/server/routes/suggestions.ts index 8b82601650a48..4834d894f364a 100644 --- a/x-pack/plugins/apm/server/routes/suggestions.ts +++ b/x-pack/plugins/apm/server/routes/suggestions.ts @@ -8,7 +8,7 @@ import * as t from 'io-ts'; import { maxSuggestions } from '../../../observability/common'; import { getSuggestions } from '../lib/suggestions/get_suggestions'; -import { getSearchAggregatedTransactions } from '../lib/helpers/aggregated_transactions'; +import { getSearchAggregatedTransactions } from '../lib/helpers/transactions'; import { setupRequest } from '../lib/helpers/setup_request'; import { createApmServerRoute } from './create_apm_server_route'; import { createApmServerRouteRepository } from './create_apm_server_route_repository'; diff --git a/x-pack/plugins/apm/server/routes/traces.ts b/x-pack/plugins/apm/server/routes/traces.ts index a71b7eefeed3f..cc800c348b165 100644 --- a/x-pack/plugins/apm/server/routes/traces.ts +++ b/x-pack/plugins/apm/server/routes/traces.ts @@ -11,7 +11,7 @@ import { getTraceItems } from '../lib/traces/get_trace_items'; import { getTopTransactionGroupList } from '../lib/transaction_groups'; import { createApmServerRoute } from './create_apm_server_route'; import { environmentRt, kueryRt, rangeRt } from './default_api_types'; -import { getSearchAggregatedTransactions } from '../lib/helpers/aggregated_transactions'; +import { getSearchAggregatedTransactions } from '../lib/helpers/transactions'; import { getRootTransactionByTraceId } from '../lib/transactions/get_transaction_by_trace'; import { createApmServerRouteRepository } from './create_apm_server_route_repository'; import { getTransaction } from '../lib/transactions/get_transaction'; diff --git a/x-pack/plugins/apm/server/routes/transactions.ts b/x-pack/plugins/apm/server/routes/transactions.ts index 0e24d64d8c6c7..56b7ead2254d3 100644 --- a/x-pack/plugins/apm/server/routes/transactions.ts +++ b/x-pack/plugins/apm/server/routes/transactions.ts @@ -11,7 +11,7 @@ import { LatencyAggregationType, latencyAggregationTypeRt, } from '../../common/latency_aggregation_types'; -import { getSearchAggregatedTransactions } from '../lib/helpers/aggregated_transactions'; +import { getSearchAggregatedTransactions } from '../lib/helpers/transactions'; import { setupRequest } from '../lib/helpers/setup_request'; import { getServiceTransactionGroups } from '../lib/services/get_service_transaction_groups'; import { getServiceTransactionGroupDetailedStatisticsPeriods } from '../lib/services/get_service_transaction_group_detailed_statistics'; From e956964c06d693dfb0deeb872342d0ae1808822d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ester=20Mart=C3=AD=20Vilaseca?= Date: Tue, 26 Oct 2021 08:26:48 +0200 Subject: [PATCH 06/58] Add page title to index advanced page (#116134) --- .../pages/elasticsearch/index_advanced_page.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/monitoring/public/application/pages/elasticsearch/index_advanced_page.tsx b/x-pack/plugins/monitoring/public/application/pages/elasticsearch/index_advanced_page.tsx index c51027636b287..1982b7de87cae 100644 --- a/x-pack/plugins/monitoring/public/application/pages/elasticsearch/index_advanced_page.tsx +++ b/x-pack/plugins/monitoring/public/application/pages/elasticsearch/index_advanced_page.tsx @@ -87,7 +87,13 @@ export const ElasticsearchIndexAdvancedPage: React.FC = ({ clust }, [clusterUuid, services.data?.query.timefilter.timefilter, services.http, index]); return ( - + ( From 27866cec6ea512d592f046973960dbb0f9fc7019 Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Tue, 26 Oct 2021 07:41:01 +0100 Subject: [PATCH 07/58] [ML] Adding datafeed api tests (#116133) * [ML] Adding datafeed api tests * updating tests * adding more AD tests * adding test include * renaming function --- .../get_stats_with_spaces.ts | 174 ++++++++++++++++++ .../ml/anomaly_detectors/get_with_spaces.ts | 68 ++++++- .../apis/ml/anomaly_detectors/index.ts | 1 + .../ml/datafeeds/get_stats_with_spaces.ts | 121 ++++++++++++ .../apis/ml/datafeeds/get_with_spaces.ts | 119 ++++++++++++ .../apis/ml/datafeeds/index.ts | 15 ++ x-pack/test/api_integration/apis/ml/index.ts | 1 + 7 files changed, 489 insertions(+), 10 deletions(-) create mode 100644 x-pack/test/api_integration/apis/ml/anomaly_detectors/get_stats_with_spaces.ts create mode 100644 x-pack/test/api_integration/apis/ml/datafeeds/get_stats_with_spaces.ts create mode 100644 x-pack/test/api_integration/apis/ml/datafeeds/get_with_spaces.ts create mode 100644 x-pack/test/api_integration/apis/ml/datafeeds/index.ts diff --git a/x-pack/test/api_integration/apis/ml/anomaly_detectors/get_stats_with_spaces.ts b/x-pack/test/api_integration/apis/ml/anomaly_detectors/get_stats_with_spaces.ts new file mode 100644 index 0000000000000..d15b1ab60f9ff --- /dev/null +++ b/x-pack/test/api_integration/apis/ml/anomaly_detectors/get_stats_with_spaces.ts @@ -0,0 +1,174 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../ftr_provider_context'; +import { USER } from '../../../../functional/services/ml/security_common'; +import { COMMON_REQUEST_HEADERS } from '../../../../functional/services/ml/common_api'; + +export default ({ getService }: FtrProviderContext) => { + const ml = getService('ml'); + const spacesService = getService('spaces'); + const supertest = getService('supertestWithoutAuth'); + + const jobIdSpace1 = 'fq_single_space1'; + const jobIdWildcardSpace1 = 'fq_single_space1*'; + const jobGroupSpace1 = 'space1_group'; + const jobGroupWildcardSpace1 = 'space1_group*'; + const idSpace1 = 'space1'; + const idSpace2 = 'space2'; + + async function getJobStatsById( + jobOrGroup: string | undefined, + expectedStatusCode: number, + space?: string + ) { + const { body } = await supertest + .get( + `${space ? `/s/${space}` : ''}/api/ml/anomaly_detectors${ + jobOrGroup ? `/${jobOrGroup}` : '' + }/_stats` + ) + .auth( + USER.ML_VIEWER_ALL_SPACES, + ml.securityCommon.getPasswordForUser(USER.ML_VIEWER_ALL_SPACES) + ) + .set(COMMON_REQUEST_HEADERS) + .expect(expectedStatusCode); + + return body; + } + + describe('GET anomaly_detectors stats with spaces', () => { + before(async () => { + await spacesService.create({ id: idSpace1, name: 'space_one', disabledFeatures: [] }); + await spacesService.create({ id: idSpace2, name: 'space_two', disabledFeatures: [] }); + + const jobConfig = ml.commonConfig.getADFqSingleMetricJobConfig(jobIdSpace1); + await ml.api.createAnomalyDetectionJob({ ...jobConfig, groups: [jobGroupSpace1] }, idSpace1); + + await ml.testResources.setKibanaTimeZoneToUTC(); + }); + + after(async () => { + await spacesService.delete(idSpace1); + await spacesService.delete(idSpace2); + await ml.api.cleanMlIndices(); + await ml.testResources.cleanMLSavedObjects(); + }); + + it('should fail with non-existing job', async () => { + await getJobStatsById('non-existing-job', 404); + }); + + it('should return empty list with non-existing job wildcard', async () => { + const body = await getJobStatsById('non-existing-job*', 200); + + expect(body.count).to.eql(0, `response count should be 0 (got ${body.count})`); + expect(body.jobs.length).to.eql( + 0, + `response job stats list should be empty (got ${JSON.stringify(body.jobs)})` + ); + }); + + it('should fail with job from different space', async () => { + await getJobStatsById(jobIdSpace1, 404, idSpace2); + }); + + it('should return all job stats when not specifying id', async () => { + const body = await getJobStatsById(undefined, 200, idSpace1); + + expect(body.count).to.eql(1, `response count should be 1 (got ${body.count})`); + expect(body.jobs.length).to.eql( + 1, + `response job stats list should contain correct job (got ${JSON.stringify(body.jobs)})` + ); + }); + + it('should return empty list when not specifying id in difference space', async () => { + const body = await getJobStatsById(undefined, 200, idSpace2); + + expect(body.count).to.eql(0, `response count should be 0 (got ${body.count})`); + expect(body.jobs.length).to.eql( + 0, + `response job stats list should be empty (got ${JSON.stringify(body.jobs)})` + ); + }); + + it('should return job stats with job id from correct space', async () => { + const body = await getJobStatsById(jobIdSpace1, 200, idSpace1); + + expect(body.count).to.eql(1, `response count should be 1 (got ${body.count})`); + expect(body.jobs.length).to.eql( + 1, + `response job stats list should contain correct job (got ${JSON.stringify(body.jobs)})` + ); + }); + + it('should return job stats with job wildcard from correct space', async () => { + const body = await getJobStatsById(jobIdWildcardSpace1, 200, idSpace1); + + expect(body.count).to.eql(1, `response count should be 1 (got ${body.count})`); + expect(body.jobs.length).to.eql( + 1, + `response job stats list should contain correct job (got ${JSON.stringify(body.jobs)})` + ); + }); + + it('should return empty list with job wildcard from different space', async () => { + const body = await getJobStatsById(jobIdWildcardSpace1, 200, idSpace2); + + expect(body.count).to.eql(0, `response count should be 0 (got ${body.count})`); + expect(body.jobs.length).to.eql( + 0, + `response job stats list should be empty (got ${JSON.stringify(body.jobs)})` + ); + }); + + it('should return job stats by group from same space', async () => { + const body = await getJobStatsById(jobGroupSpace1, 200, idSpace1); + + expect(body.count).to.eql(1, `response count should be 1 (got ${body.count})`); + expect(body.jobs.length).to.eql( + 1, + `response job stats list should have one element (got ${JSON.stringify(body.jobs)})` + ); + expect(body.jobs[0].job_id).to.eql( + jobIdSpace1, + `response job id should be ${jobIdSpace1} (got ${body.jobs[0].job_id})` + ); + }); + + it('should return job stats by group wildcard from same space', async () => { + const body = await getJobStatsById(jobGroupWildcardSpace1, 200, idSpace1); + + expect(body.count).to.eql(1, `response count should be 1 (got ${body.count})`); + expect(body.jobs.length).to.eql( + 1, + `response job stats list should have one element (got ${JSON.stringify(body.jobs)})` + ); + expect(body.jobs[0].job_id).to.eql( + jobIdSpace1, + `response job id should be ${jobIdSpace1} (got ${body.jobs[0].job_id})` + ); + }); + + it('should fail with group from different space', async () => { + await getJobStatsById(jobGroupSpace1, 404, idSpace2); + }); + + it('should return empty list with group wildcard from different space', async () => { + const body = await getJobStatsById(jobGroupWildcardSpace1, 200, idSpace2); + + expect(body.count).to.eql(0, `response count should be 0 (got ${body.count})`); + expect(body.jobs.length).to.eql( + 0, + `response job stats list should be empty (got ${JSON.stringify(body.jobs)})` + ); + }); + }); +}; diff --git a/x-pack/test/api_integration/apis/ml/anomaly_detectors/get_with_spaces.ts b/x-pack/test/api_integration/apis/ml/anomaly_detectors/get_with_spaces.ts index 5392b0ef44c8a..2bebea5e63ea1 100644 --- a/x-pack/test/api_integration/apis/ml/anomaly_detectors/get_with_spaces.ts +++ b/x-pack/test/api_integration/apis/ml/anomaly_detectors/get_with_spaces.ts @@ -22,9 +22,17 @@ export default ({ getService }: FtrProviderContext) => { const idSpace1 = 'space1'; const idSpace2 = 'space2'; - async function runRequest(jobOrGroup: string, expectedStatusCode: number, space?: string) { + async function getJobById( + jobOrGroup: string | undefined, + expectedStatusCode: number, + space?: string + ) { const { body } = await supertest - .get(`${space ? `/s/${space}` : ''}/api/ml/anomaly_detectors/${jobOrGroup}`) + .get( + `${space ? `/s/${space}` : ''}/api/ml/anomaly_detectors${ + jobOrGroup ? `/${jobOrGroup}` : '' + }` + ) .auth( USER.ML_VIEWER_ALL_SPACES, ml.securityCommon.getPasswordForUser(USER.ML_VIEWER_ALL_SPACES) @@ -54,11 +62,11 @@ export default ({ getService }: FtrProviderContext) => { }); it('should fail with non-existing job', async () => { - await runRequest('non-existing-job', 404); + await getJobById('non-existing-job', 404); }); it('should return empty list with non-existing job wildcard', async () => { - const body = await runRequest('non-existing-job*', 200); + const body = await getJobById('non-existing-job*', 200); expect(body.count).to.eql(0, `response count should be 0 (got ${body.count})`); expect(body.jobs.length).to.eql( @@ -68,11 +76,51 @@ export default ({ getService }: FtrProviderContext) => { }); it('should fail with job from different space', async () => { - await runRequest(jobIdSpace1, 404, idSpace2); + await getJobById(jobIdSpace1, 404, idSpace2); + }); + + it('should return all jobs when not specifying id', async () => { + const body = await getJobById(undefined, 200, idSpace1); + + expect(body.count).to.eql(1, `response count should be 1 (got ${body.count})`); + expect(body.jobs.length).to.eql( + 1, + `response jobs list should contain correct job (got ${JSON.stringify(body.jobs)})` + ); + }); + + it('should return empty list when not specifying id in difference space', async () => { + const body = await getJobById(undefined, 200, idSpace2); + + expect(body.count).to.eql(0, `response count should be 0 (got ${body.count})`); + expect(body.jobs.length).to.eql( + 0, + `response jobs list should be empty (got ${JSON.stringify(body.jobs)})` + ); + }); + + it('should return job with job id from correct space', async () => { + const body = await getJobById(jobIdSpace1, 200, idSpace1); + + expect(body.count).to.eql(1, `response count should be 1 (got ${body.count})`); + expect(body.jobs.length).to.eql( + 1, + `response jobs list should contain correct job (got ${JSON.stringify(body.jobs)})` + ); + }); + + it('should return job with job wildcard from correct space', async () => { + const body = await getJobById(jobIdWildcardSpace1, 200, idSpace1); + + expect(body.count).to.eql(1, `response count should be 1 (got ${body.count})`); + expect(body.jobs.length).to.eql( + 1, + `response jobs list should contain correct job (got ${JSON.stringify(body.jobs)})` + ); }); it('should return empty list with job wildcard from different space', async () => { - const body = await runRequest(jobIdWildcardSpace1, 200, idSpace2); + const body = await getJobById(jobIdWildcardSpace1, 200, idSpace2); expect(body.count).to.eql(0, `response count should be 0 (got ${body.count})`); expect(body.jobs.length).to.eql( @@ -82,7 +130,7 @@ export default ({ getService }: FtrProviderContext) => { }); it('should return job by group from same space', async () => { - const body = await runRequest(jobGroupSpace1, 200, idSpace1); + const body = await getJobById(jobGroupSpace1, 200, idSpace1); expect(body.count).to.eql(1, `response count should be 1 (got ${body.count})`); expect(body.jobs.length).to.eql( @@ -96,7 +144,7 @@ export default ({ getService }: FtrProviderContext) => { }); it('should return job by group wildcard from same space', async () => { - const body = await runRequest(jobGroupWildcardSpace1, 200, idSpace1); + const body = await getJobById(jobGroupWildcardSpace1, 200, idSpace1); expect(body.count).to.eql(1, `response count should be 1 (got ${body.count})`); expect(body.jobs.length).to.eql( @@ -110,11 +158,11 @@ export default ({ getService }: FtrProviderContext) => { }); it('should fail with group from different space', async () => { - await runRequest(jobGroupSpace1, 404, idSpace2); + await getJobById(jobGroupSpace1, 404, idSpace2); }); it('should return empty list with group wildcard from different space', async () => { - const body = await runRequest(jobGroupWildcardSpace1, 200, idSpace2); + const body = await getJobById(jobGroupWildcardSpace1, 200, idSpace2); expect(body.count).to.eql(0, `response count should be 0 (got ${body.count})`); expect(body.jobs.length).to.eql( diff --git a/x-pack/test/api_integration/apis/ml/anomaly_detectors/index.ts b/x-pack/test/api_integration/apis/ml/anomaly_detectors/index.ts index 86649ece22551..101273405f121 100644 --- a/x-pack/test/api_integration/apis/ml/anomaly_detectors/index.ts +++ b/x-pack/test/api_integration/apis/ml/anomaly_detectors/index.ts @@ -12,6 +12,7 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./create')); loadTestFile(require.resolve('./get')); loadTestFile(require.resolve('./get_with_spaces')); + loadTestFile(require.resolve('./get_stats_with_spaces')); loadTestFile(require.resolve('./open_with_spaces')); loadTestFile(require.resolve('./close_with_spaces')); loadTestFile(require.resolve('./delete_with_spaces')); diff --git a/x-pack/test/api_integration/apis/ml/datafeeds/get_stats_with_spaces.ts b/x-pack/test/api_integration/apis/ml/datafeeds/get_stats_with_spaces.ts new file mode 100644 index 0000000000000..aaa60aabdfbd0 --- /dev/null +++ b/x-pack/test/api_integration/apis/ml/datafeeds/get_stats_with_spaces.ts @@ -0,0 +1,121 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../ftr_provider_context'; +import { USER } from '../../../../functional/services/ml/security_common'; +import { COMMON_REQUEST_HEADERS } from '../../../../functional/services/ml/common_api'; + +export default ({ getService }: FtrProviderContext) => { + const ml = getService('ml'); + const spacesService = getService('spaces'); + const supertest = getService('supertestWithoutAuth'); + + const jobIdSpace1 = 'fq_single_space1'; + const datafeedIdSpace1 = `datafeed-${jobIdSpace1}`; + const datafeedIdWildcardSpace1 = `datafeed-${jobIdSpace1}*`; + const idSpace1 = 'space1'; + const idSpace2 = 'space2'; + + async function getDatafeedStatsById( + datafeedId: string | undefined, + expectedStatusCode: number, + space?: string + ) { + const { body } = await supertest + .get( + `${space ? `/s/${space}` : ''}/api/ml/datafeeds${datafeedId ? `/${datafeedId}` : ''}/_stats` + ) + .auth( + USER.ML_VIEWER_ALL_SPACES, + ml.securityCommon.getPasswordForUser(USER.ML_VIEWER_ALL_SPACES) + ) + .set(COMMON_REQUEST_HEADERS) + .expect(expectedStatusCode); + + return body; + } + + describe('GET datafeed stats with spaces', () => { + before(async () => { + await spacesService.create({ id: idSpace1, name: 'space_one', disabledFeatures: [] }); + await spacesService.create({ id: idSpace2, name: 'space_two', disabledFeatures: [] }); + + const jobConfig = ml.commonConfig.getADFqSingleMetricJobConfig(jobIdSpace1); + await ml.api.createAnomalyDetectionJob(jobConfig, idSpace1); + const datafeedConfig = ml.commonConfig.getADFqDatafeedConfig(jobIdSpace1); + await ml.api.createDatafeed(datafeedConfig, idSpace1); + + await ml.testResources.setKibanaTimeZoneToUTC(); + }); + + after(async () => { + await spacesService.delete(idSpace1); + await spacesService.delete(idSpace2); + await ml.api.cleanMlIndices(); + await ml.testResources.cleanMLSavedObjects(); + }); + + it('should fail with non-existing datafeed', async () => { + await getDatafeedStatsById('non-existing-datafeed', 404); + }); + + it('should return datafeed stats with datafeed id from correct space', async () => { + const body = await getDatafeedStatsById(datafeedIdSpace1, 200, idSpace1); + + expect(body.count).to.eql(1, `response count should be 1 (got ${body.count})`); + expect(body.datafeeds.length).to.eql( + 1, + `response datafeeds list should contain correct datafeed (got ${JSON.stringify(body.jobs)})` + ); + }); + + it('should return datafeed stats with datafeed wildcard from correct space', async () => { + const body = await getDatafeedStatsById(datafeedIdWildcardSpace1, 200, idSpace1); + + expect(body.count).to.eql(1, `response count should be 1 (got ${body.count})`); + expect(body.datafeeds.length).to.eql( + 1, + `response datafeeds list should contain correct datafeed (got ${JSON.stringify(body.jobs)})` + ); + }); + + it('should return all datafeed stats when not specifying id', async () => { + const body = await getDatafeedStatsById(undefined, 200, idSpace1); + + expect(body.count).to.eql(1, `response count should be 1 (got ${body.count})`); + expect(body.datafeeds.length).to.eql( + 1, + `response datafeeds list should contain correct datafeed (got ${JSON.stringify(body.jobs)})` + ); + }); + + it('should return empty list with non-existing datafeed wildcard', async () => { + const body = await getDatafeedStatsById('non-existing-datafeed*', 200); + + expect(body.count).to.eql(0, `response count should be 0 (got ${body.count})`); + expect(body.datafeeds.length).to.eql( + 0, + `response datafeed list should be empty (got ${JSON.stringify(body.datafeeds)})` + ); + }); + + it('should fail with datafeed from different space', async () => { + await getDatafeedStatsById(datafeedIdSpace1, 404, idSpace2); + }); + + it('should return empty list with datafeed wildcard from different space', async () => { + const body = await getDatafeedStatsById(datafeedIdWildcardSpace1, 200, idSpace2); + + expect(body.count).to.eql(0, `response count should be 0 (got ${body.count})`); + expect(body.datafeeds.length).to.eql( + 0, + `response datafeed list should be empty (got ${JSON.stringify(body.datafeeds)})` + ); + }); + }); +}; diff --git a/x-pack/test/api_integration/apis/ml/datafeeds/get_with_spaces.ts b/x-pack/test/api_integration/apis/ml/datafeeds/get_with_spaces.ts new file mode 100644 index 0000000000000..a1b045832789e --- /dev/null +++ b/x-pack/test/api_integration/apis/ml/datafeeds/get_with_spaces.ts @@ -0,0 +1,119 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from '@kbn/expect'; +import { FtrProviderContext } from '../../../ftr_provider_context'; +import { USER } from '../../../../functional/services/ml/security_common'; +import { COMMON_REQUEST_HEADERS } from '../../../../functional/services/ml/common_api'; + +export default ({ getService }: FtrProviderContext) => { + const ml = getService('ml'); + const spacesService = getService('spaces'); + const supertest = getService('supertestWithoutAuth'); + + const jobIdSpace1 = 'fq_single_space1'; + const datafeedIdSpace1 = `datafeed-${jobIdSpace1}`; + const datafeedIdWildcardSpace1 = `datafeed-${jobIdSpace1}*`; + const idSpace1 = 'space1'; + const idSpace2 = 'space2'; + + async function getDatafeedById( + datafeedId: string | undefined, + expectedStatusCode: number, + space?: string + ) { + const { body } = await supertest + .get(`${space ? `/s/${space}` : ''}/api/ml/datafeeds${datafeedId ? `/${datafeedId}` : ''}`) + .auth( + USER.ML_VIEWER_ALL_SPACES, + ml.securityCommon.getPasswordForUser(USER.ML_VIEWER_ALL_SPACES) + ) + .set(COMMON_REQUEST_HEADERS) + .expect(expectedStatusCode); + + return body; + } + + describe('GET datafeeds with spaces', () => { + before(async () => { + await spacesService.create({ id: idSpace1, name: 'space_one', disabledFeatures: [] }); + await spacesService.create({ id: idSpace2, name: 'space_two', disabledFeatures: [] }); + + const jobConfig = ml.commonConfig.getADFqSingleMetricJobConfig(jobIdSpace1); + await ml.api.createAnomalyDetectionJob(jobConfig, idSpace1); + const datafeedConfig = ml.commonConfig.getADFqDatafeedConfig(jobIdSpace1); + await ml.api.createDatafeed(datafeedConfig, idSpace1); + + await ml.testResources.setKibanaTimeZoneToUTC(); + }); + + after(async () => { + await spacesService.delete(idSpace1); + await spacesService.delete(idSpace2); + await ml.api.cleanMlIndices(); + await ml.testResources.cleanMLSavedObjects(); + }); + + it('should fail with non-existing datafeed', async () => { + await getDatafeedById('non-existing-datafeed', 404); + }); + + it('should return datafeed with datafeed id from correct space', async () => { + const body = await getDatafeedById(datafeedIdSpace1, 200, idSpace1); + + expect(body.count).to.eql(1, `response count should be 1 (got ${body.count})`); + expect(body.datafeeds.length).to.eql( + 1, + `response datafeeds list should contain correct datafeed (got ${JSON.stringify(body.jobs)})` + ); + }); + + it('should return datafeed with datafeed wildcard from correct space', async () => { + const body = await getDatafeedById(datafeedIdWildcardSpace1, 200, idSpace1); + + expect(body.count).to.eql(1, `response count should be 1 (got ${body.count})`); + expect(body.datafeeds.length).to.eql( + 1, + `response datafeeds list should contain correct datafeed (got ${JSON.stringify(body.jobs)})` + ); + }); + + it('should return all datafeeds when not specifying id', async () => { + const body = await getDatafeedById(undefined, 200, idSpace1); + + expect(body.count).to.eql(1, `response count should be 1 (got ${body.count})`); + expect(body.datafeeds.length).to.eql( + 1, + `response datafeeds list should contain correct datafeed (got ${JSON.stringify(body.jobs)})` + ); + }); + + it('should return empty list with non-existing datafeed wildcard', async () => { + const body = await getDatafeedById('non-existing-datafeed*', 200); + + expect(body.count).to.eql(0, `response count should be 0 (got ${body.count})`); + expect(body.datafeeds.length).to.eql( + 0, + `response datafeed list should be empty (got ${JSON.stringify(body.datafeeds)})` + ); + }); + + it('should fail with datafeed from different space', async () => { + await getDatafeedById(datafeedIdSpace1, 404, idSpace2); + }); + + it('should return empty list with datafeed wildcard from different space', async () => { + const body = await getDatafeedById(datafeedIdWildcardSpace1, 200, idSpace2); + + expect(body.count).to.eql(0, `response count should be 0 (got ${body.count})`); + expect(body.datafeeds.length).to.eql( + 0, + `response datafeed list should be empty (got ${JSON.stringify(body.datafeeds)})` + ); + }); + }); +}; diff --git a/x-pack/test/api_integration/apis/ml/datafeeds/index.ts b/x-pack/test/api_integration/apis/ml/datafeeds/index.ts new file mode 100644 index 0000000000000..4e92c9969a8f4 --- /dev/null +++ b/x-pack/test/api_integration/apis/ml/datafeeds/index.ts @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ loadTestFile }: FtrProviderContext) { + describe('anomaly detectors', function () { + loadTestFile(require.resolve('./get_with_spaces')); + loadTestFile(require.resolve('./get_stats_with_spaces')); + }); +} diff --git a/x-pack/test/api_integration/apis/ml/index.ts b/x-pack/test/api_integration/apis/ml/index.ts index 9b530873ad165..06910e8fac67e 100644 --- a/x-pack/test/api_integration/apis/ml/index.ts +++ b/x-pack/test/api_integration/apis/ml/index.ts @@ -72,6 +72,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./annotations')); loadTestFile(require.resolve('./anomaly_detectors')); loadTestFile(require.resolve('./calendars')); + loadTestFile(require.resolve('./datafeeds')); loadTestFile(require.resolve('./data_frame_analytics')); loadTestFile(require.resolve('./data_visualizer')); loadTestFile(require.resolve('./fields_service')); From 9c3c489e481c5fe9992584a3a1db2e37ce8f3bf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20S=C3=A1nchez?= Date: Tue, 26 Oct 2021 09:21:58 +0200 Subject: [PATCH 08/58] Hide or button if needed (#116124) --- .../builder/exception_items_renderer.tsx | 3 ++ .../components/builder/logic_buttons.test.tsx | 19 +++++++++++++ .../components/builder/logic_buttons.tsx | 28 +++++++++++-------- .../view/components/form/index.tsx | 3 +- 4 files changed, 40 insertions(+), 13 deletions(-) diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/exception_items_renderer.tsx b/x-pack/plugins/lists/public/exceptions/components/builder/exception_items_renderer.tsx index 1b25a2cb91e85..280dd8acbc7e5 100644 --- a/x-pack/plugins/lists/public/exceptions/components/builder/exception_items_renderer.tsx +++ b/x-pack/plugins/lists/public/exceptions/components/builder/exception_items_renderer.tsx @@ -81,6 +81,7 @@ export interface ExceptionBuilderProps { isAndDisabled: boolean; isNestedDisabled: boolean; isOrDisabled: boolean; + isOrHidden?: boolean; listId: string; listNamespaceType: NamespaceType; listType: ExceptionListType; @@ -103,6 +104,7 @@ export const ExceptionBuilderComponent = ({ isAndDisabled, isNestedDisabled, isOrDisabled, + isOrHidden = false, listId, listNamespaceType, listType, @@ -433,6 +435,7 @@ export const ExceptionBuilderComponent = ({ { expect(wrapper.find('[data-test-subj="exceptionsNestedButton"] button')).toHaveLength(0); }); + test('it hides "or" button', () => { + const wrapper = mount( + + ); + + expect(wrapper.find('[data-test-subj="exceptionsOrButton"] button')).toHaveLength(0); + }); + test('it invokes "onOrClicked" when "or" button is clicked', () => { const onOrClicked = jest.fn(); diff --git a/x-pack/plugins/lists/public/exceptions/components/builder/logic_buttons.tsx b/x-pack/plugins/lists/public/exceptions/components/builder/logic_buttons.tsx index 3846b844bb55a..aa308ecdc3452 100644 --- a/x-pack/plugins/lists/public/exceptions/components/builder/logic_buttons.tsx +++ b/x-pack/plugins/lists/public/exceptions/components/builder/logic_buttons.tsx @@ -20,6 +20,7 @@ interface BuilderLogicButtonsProps { isNested: boolean; isNestedDisabled: boolean; isOrDisabled: boolean; + isOrHidden?: boolean; showNestedButton: boolean; onAddClickWhenNested: () => void; onAndClicked: () => void; @@ -32,6 +33,7 @@ export const BuilderLogicButtons: React.FC = ({ isNested, isNestedDisabled = true, isOrDisabled = false, + isOrHidden = false, showNestedButton = false, onAddClickWhenNested, onAndClicked, @@ -50,18 +52,20 @@ export const BuilderLogicButtons: React.FC = ({ {i18n.AND} - - - {i18n.OR} - - + {!isOrHidden && ( + + + {i18n.OR} + + + )} {showNestedButton && ( = memo( listNamespaceType: 'agnostic', ruleName: RULE_NAME, indexPatterns, - isOrDisabled: true, // TODO: pending to be validated + isOrDisabled: true, + isOrHidden: true, isAndDisabled: false, isNestedDisabled: false, dataTestSubj: 'alert-exception-builder', From 669e0a1555257ee31da2f44b020e6efcac88ed92 Mon Sep 17 00:00:00 2001 From: Thom Heymann <190132+thomheymann@users.noreply.github.com> Date: Tue, 26 Oct 2021 08:34:13 +0100 Subject: [PATCH 09/58] Add not ready response to interactive setup (#116138) --- src/plugins/interactive_setup/common/index.ts | 2 +- src/plugins/interactive_setup/common/types.ts | 22 ++++--- src/plugins/interactive_setup/public/app.tsx | 23 +++++++ .../public/enrollment_token_form.test.tsx | 14 +++++ .../public/enrollment_token_form.tsx | 14 +++++ .../interactive_setup/server/routes/index.ts | 2 + .../server/routes/status.test.ts | 62 +++++++++++++++++++ .../interactive_setup/server/routes/status.ts | 33 ++++++++++ 8 files changed, 161 insertions(+), 11 deletions(-) create mode 100644 src/plugins/interactive_setup/server/routes/status.test.ts create mode 100644 src/plugins/interactive_setup/server/routes/status.ts diff --git a/src/plugins/interactive_setup/common/index.ts b/src/plugins/interactive_setup/common/index.ts index 0ba439eeb7616..352c95c73aee6 100644 --- a/src/plugins/interactive_setup/common/index.ts +++ b/src/plugins/interactive_setup/common/index.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -export type { InteractiveSetupViewState, EnrollmentToken, Certificate, PingResult } from './types'; +export type { EnrollmentToken, Certificate, PingResult, StatusResult } from './types'; export { ElasticsearchConnectionStatus } from './elasticsearch_connection_status'; export { ERROR_CONFIGURE_FAILURE, diff --git a/src/plugins/interactive_setup/common/types.ts b/src/plugins/interactive_setup/common/types.ts index de3f54dbf9a28..4f30faf19a3d3 100644 --- a/src/plugins/interactive_setup/common/types.ts +++ b/src/plugins/interactive_setup/common/types.ts @@ -10,16 +10,6 @@ import type { PeerCertificate } from 'tls'; import type { ElasticsearchConnectionStatus } from './elasticsearch_connection_status'; -/** - * A set of state details that interactive setup view retrieves from the Kibana server. - */ -export interface InteractiveSetupViewState { - /** - * Current status of the Elasticsearch connection. - */ - elasticsearchConnectionStatus: ElasticsearchConnectionStatus; -} - /** * The token that allows one to configure Kibana instance to communicate with an existing Elasticsearch cluster that * has security features enabled. @@ -66,3 +56,15 @@ export interface PingResult { */ certificateChain?: Certificate[]; } + +export interface StatusResult { + /** + * Full certificate chain of cluster at requested address. Only present if cluster uses HTTPS. + */ + connectionStatus: ElasticsearchConnectionStatus; + + /** + * Indicates whether Kibana is currently on hold and cannot proceed to `setup` yet. + */ + isSetupOnHold: boolean; +} diff --git a/src/plugins/interactive_setup/public/app.tsx b/src/plugins/interactive_setup/public/app.tsx index 0f1c1b04d7c90..89218df4208bc 100644 --- a/src/plugins/interactive_setup/public/app.tsx +++ b/src/plugins/interactive_setup/public/app.tsx @@ -11,14 +11,17 @@ import './app.scss'; import { EuiIcon, EuiPanel, EuiSpacer, EuiTitle } from '@elastic/eui'; import type { FunctionComponent } from 'react'; import React, { useState } from 'react'; +import useAsync from 'react-use/lib/useAsync'; import { FormattedMessage } from '@kbn/i18n/react'; +import type { StatusResult } from '../common'; import { ClusterAddressForm } from './cluster_address_form'; import type { ClusterConfigurationFormProps } from './cluster_configuration_form'; import { ClusterConfigurationForm } from './cluster_configuration_form'; import { EnrollmentTokenForm } from './enrollment_token_form'; import { ProgressIndicator } from './progress_indicator'; +import { useKibana } from './use_kibana'; export interface AppProps { onSuccess?(): void; @@ -28,6 +31,26 @@ export const App: FunctionComponent = ({ onSuccess }) => { const [page, setPage] = useState<'token' | 'manual' | 'success'>('token'); const [cluster, setCluster] = useState>(); + const { http } = useKibana(); + const state = useAsync( + () => http.get('/internal/interactive_setup/status'), + [http] + ); + + if (state.loading) { + return null; + } + + if (!state.value || state.value.connectionStatus === 'configured' || !state.value.isSetupOnHold) { + return ( +
+        
+      
+ ); + } return (
diff --git a/src/plugins/interactive_setup/public/enrollment_token_form.test.tsx b/src/plugins/interactive_setup/public/enrollment_token_form.test.tsx index a6a18984ddd94..30983c68e1cf9 100644 --- a/src/plugins/interactive_setup/public/enrollment_token_form.test.tsx +++ b/src/plugins/interactive_setup/public/enrollment_token_form.test.tsx @@ -89,6 +89,20 @@ describe('decodeEnrollmentToken', () => { }); }); + it('should sort IPv4 before IPv6 addresses', () => { + expect( + decodeEnrollmentToken( + btoa( + JSON.stringify({ ...token, adr: ['[::1]:9200', '127.0.0.1:9200', '10.17.1.163:9200'] }) + ) + ) + ).toEqual( + expect.objectContaining({ + adr: ['https://127.0.0.1:9200', 'https://10.17.1.163:9200', 'https://[::1]:9200'], + }) + ); + }); + it('should not decode an invalid token', () => { expect(decodeEnrollmentToken(JSON.stringify(token))).toBeUndefined(); expect( diff --git a/src/plugins/interactive_setup/public/enrollment_token_form.tsx b/src/plugins/interactive_setup/public/enrollment_token_form.tsx index 4b692ed4efcc8..e5a3aca8fd4e2 100644 --- a/src/plugins/interactive_setup/public/enrollment_token_form.tsx +++ b/src/plugins/interactive_setup/public/enrollment_token_form.tsx @@ -205,6 +205,7 @@ export function decodeEnrollmentToken(enrollmentToken: string): EnrollmentToken ) { return; } + json.adr.sort(compareAddresses); return { ...json, adr: json.adr.map((host) => `https://${host}`), @@ -212,3 +213,16 @@ export function decodeEnrollmentToken(enrollmentToken: string): EnrollmentToken }; } catch (error) {} // eslint-disable-line no-empty } + +/** + * Compares two Elasticsearch addresses. Sorts IPv4 addresses before IPv6 addresses. + */ +export function compareAddresses(a: string, b: string) { + if (a.indexOf('[') === -1 && b.indexOf('[') !== -1) { + return -1; + } + if (a.indexOf('[') !== -1 && b.indexOf('[') === -1) { + return 1; + } + return 0; +} diff --git a/src/plugins/interactive_setup/server/routes/index.ts b/src/plugins/interactive_setup/server/routes/index.ts index fb9e06c4c2a18..f1f6b34fb689c 100644 --- a/src/plugins/interactive_setup/server/routes/index.ts +++ b/src/plugins/interactive_setup/server/routes/index.ts @@ -16,6 +16,7 @@ import type { VerificationCode } from '../verification_code'; import { defineConfigureRoute } from './configure'; import { defineEnrollRoutes } from './enroll'; import { definePingRoute } from './ping'; +import { defineStatusRoute } from './status'; import { defineVerifyRoute } from './verify'; /** @@ -39,4 +40,5 @@ export function defineRoutes(params: RouteDefinitionParams) { defineEnrollRoutes(params); definePingRoute(params); defineVerifyRoute(params); + defineStatusRoute(params); } diff --git a/src/plugins/interactive_setup/server/routes/status.test.ts b/src/plugins/interactive_setup/server/routes/status.test.ts new file mode 100644 index 0000000000000..b40c765a8a53a --- /dev/null +++ b/src/plugins/interactive_setup/server/routes/status.test.ts @@ -0,0 +1,62 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { IRouter, RequestHandler, RequestHandlerContext } from 'src/core/server'; +import { kibanaResponseFactory } from 'src/core/server'; +import { httpServerMock } from 'src/core/server/mocks'; + +import { routeDefinitionParamsMock } from './index.mock'; +import { defineStatusRoute } from './status'; + +describe('Status routes', () => { + let router: jest.Mocked; + let mockRouteParams: ReturnType; + let mockContext: RequestHandlerContext; + beforeEach(() => { + mockRouteParams = routeDefinitionParamsMock.create(); + mockRouteParams.preboot.isSetupOnHold.mockReturnValue(false); + router = mockRouteParams.router; + + mockContext = {} as unknown as RequestHandlerContext; + + defineStatusRoute(mockRouteParams); + }); + + describe('#status', () => { + let routeHandler: RequestHandler; + + beforeEach(() => { + const [, statusRouteHandler] = router.get.mock.calls.find( + ([{ path }]) => path === '/internal/interactive_setup/status' + )!; + + routeHandler = statusRouteHandler; + }); + + it('should return connection status', async () => { + const mockRequest = httpServerMock.createKibanaRequest(); + + await expect(routeHandler(mockContext, mockRequest, kibanaResponseFactory)).resolves + .toMatchInlineSnapshot(` + KibanaResponse { + "options": Object { + "body": Object { + "connectionStatus": "configured", + "isSetupOnHold": false, + }, + }, + "payload": Object { + "connectionStatus": "configured", + "isSetupOnHold": false, + }, + "status": 200, + } + `); + }); + }); +}); diff --git a/src/plugins/interactive_setup/server/routes/status.ts b/src/plugins/interactive_setup/server/routes/status.ts new file mode 100644 index 0000000000000..51b98732853ef --- /dev/null +++ b/src/plugins/interactive_setup/server/routes/status.ts @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { first } from 'rxjs/operators'; + +import type { RouteDefinitionParams } from '.'; + +export function defineStatusRoute({ router, elasticsearch, preboot }: RouteDefinitionParams) { + router.get( + { + path: '/internal/interactive_setup/status', + validate: false, + options: { authRequired: false }, + }, + async (context, request, response) => { + // `connectionStatus$` is a `ReplaySubject` with a buffer size of 1 so `first()` operator will + // always return the most recently emitted value. We can't use `connectionStatus$.toPromise()` + // directly since the stream hasn't ended so it would never resolve. + const connectionStatus = await elasticsearch.connectionStatus$.pipe(first()).toPromise(); + return response.ok({ + body: { + connectionStatus, + isSetupOnHold: preboot.isSetupOnHold(), + }, + }); + } + ); +} From 79c43fbfff751341a4dfdc7f3ad1c5076102ed30 Mon Sep 17 00:00:00 2001 From: Thom Heymann <190132+thomheymann@users.noreply.github.com> Date: Tue, 26 Oct 2021 08:34:57 +0100 Subject: [PATCH 10/58] Enable interactive setup by default (#116141) --- src/plugins/interactive_setup/server/config.test.ts | 4 ++-- src/plugins/interactive_setup/server/config.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/interactive_setup/server/config.test.ts b/src/plugins/interactive_setup/server/config.test.ts index b8ae673ad28f9..50e47735ad3c8 100644 --- a/src/plugins/interactive_setup/server/config.test.ts +++ b/src/plugins/interactive_setup/server/config.test.ts @@ -15,7 +15,7 @@ describe('config schema', () => { "connectionCheck": Object { "interval": "PT5S", }, - "enabled": false, + "enabled": true, } `); }); @@ -27,7 +27,7 @@ describe('config schema', () => { "connectionCheck": Object { "interval": "PT1S", }, - "enabled": false, + "enabled": true, } `); }); diff --git a/src/plugins/interactive_setup/server/config.ts b/src/plugins/interactive_setup/server/config.ts index 9986f16e9ce93..1b1a9525e3527 100644 --- a/src/plugins/interactive_setup/server/config.ts +++ b/src/plugins/interactive_setup/server/config.ts @@ -12,7 +12,7 @@ import { schema } from '@kbn/config-schema'; export type ConfigType = TypeOf; export const ConfigSchema = schema.object({ - enabled: schema.boolean({ defaultValue: false }), + enabled: schema.boolean({ defaultValue: true }), connectionCheck: schema.object({ interval: schema.duration({ defaultValue: '5s', From 30c72111ae2ce1da0d58dbd37aa000af639671a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20S=C3=A1nchez?= Date: Tue, 26 Oct 2021 09:43:58 +0200 Subject: [PATCH 11/58] Set required to false until the input is not visited (#116099) --- .../view/components/condition_entry_input/index.tsx | 10 +++++++--- .../view/components/create_trusted_app_form.test.tsx | 12 ++++++++++-- .../view/components/create_trusted_app_form.tsx | 2 +- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/condition_entry_input/index.tsx b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/condition_entry_input/index.tsx index d052138d309ac..f487a38401ef0 100644 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/condition_entry_input/index.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/condition_entry_input/index.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { ChangeEventHandler, memo, useCallback, useMemo } from 'react'; +import React, { ChangeEventHandler, memo, useCallback, useMemo, useState } from 'react'; import styled from 'styled-components'; import { i18n } from '@kbn/i18n'; import { @@ -100,6 +100,7 @@ export const ConditionEntryInput = memo( 'data-test-subj': dataTestSubj, }) => { const getTestId = useTestIdGenerator(dataTestSubj); + const [isVisited, setIsVisited] = useState(false); const fieldOptions = useMemo>>(() => { const getDropdownDisplay = (field: ConditionEntryField) => ( @@ -155,7 +156,10 @@ export const ConditionEntryInput = memo( if (onVisited) { onVisited(entry); } - }, [entry, onVisited]); + if (!isVisited) { + setIsVisited(true); + } + }, [entry, onVisited, isVisited]); return ( @@ -199,7 +203,7 @@ export const ConditionEntryInput = memo( type: entry.type, })} fullWidth - required + required={isVisited} onChange={handleValueUpdate} onBlur={handleValueOnBlur} data-test-subj={getTestId('value')} diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_form.test.tsx b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_form.test.tsx index d3b4a541bd18d..f05d018fe8e9a 100644 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_form.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_form.test.tsx @@ -153,7 +153,11 @@ describe('When using the Trusted App Form', () => { describe('and the form is rendered', () => { beforeEach(() => render()); - it('should show Name as required', () => { + it('should show Name as required after blur', () => { + expect(getNameField().required).toBe(false); + reactTestingLibrary.act(() => { + fireEvent.blur(getNameField()); + }); expect(getNameField().required).toBe(true); }); @@ -224,7 +228,11 @@ describe('When using the Trusted App Form', () => { ]); }); - it('should show the value field as required', () => { + it('should show the value field as required after blur', () => { + expect(getConditionValue(getCondition()).required).toEqual(false); + reactTestingLibrary.act(() => { + fireEvent.blur(getConditionValue(getCondition())); + }); expect(getConditionValue(getCondition()).required).toEqual(true); }); diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_form.tsx b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_form.tsx index d4f456ab8e039..da925ddd8a6c1 100644 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_form.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_form.tsx @@ -478,7 +478,7 @@ export const CreateTrustedAppForm = memo( onChange={handleDomChangeEvents} onBlur={handleDomBlurEvents} fullWidth - required + required={wasVisited?.name} maxLength={256} data-test-subj={getTestId('nameTextField')} /> From 3fb1c1de725f331de881567be7e4e5c45351d558 Mon Sep 17 00:00:00 2001 From: Khristinin Nikita Date: Tue, 26 Oct 2021 10:26:54 +0200 Subject: [PATCH 12/58] New field for integrations field (#116175) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../plugins/security_solution/common/cti/constants.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/security_solution/common/cti/constants.ts b/x-pack/plugins/security_solution/common/cti/constants.ts index e63385a15062f..b33541c5057d8 100644 --- a/x-pack/plugins/security_solution/common/cti/constants.ts +++ b/x-pack/plugins/security_solution/common/cti/constants.ts @@ -59,11 +59,13 @@ export const DEFAULT_EVENT_ENRICHMENT_FROM = 'now-30d'; export const DEFAULT_EVENT_ENRICHMENT_TO = 'now'; export const CTI_DATASET_KEY_MAP: { [key: string]: string } = { - 'Abuse URL': 'ti_abusech.url', - 'Abuse Malware': 'ti_abusech.malware', - 'Malware Bazaar': 'ti_abusech.malwarebazaar', + 'AbuseCH URL': 'ti_abusech.url', + 'AbuseCH Malware': 'ti_abusech.malware', + 'AbuseCH MalwareBazaar': 'ti_abusech.malwarebazaar', 'AlienVault OTX': 'ti_otx.threat', 'Anomali Limo': 'ti_anomali.limo', - 'Anomali ThreatStream': 'ti_anomali.threatstream', + 'Anomali Threatstream': 'ti_anomali.threatstream', MISP: 'ti_misp.threat', + ThreatQuotient: 'ti_threatq.threat', + Cybersixgill: 'ti_cybersixgill.threat', }; From 32460183831e21eca81403a328ca31456539c2c7 Mon Sep 17 00:00:00 2001 From: Shahzad Date: Tue, 26 Oct 2021 10:29:50 +0200 Subject: [PATCH 13/58] [Uptime] TLS and TLS legacy alert translation mismatch (#116113) --- .../translations/translations/ja-JP.json | 2 -- .../translations/translations/zh-CN.json | 2 -- x-pack/plugins/uptime/common/translations.ts | 24 +++++++++---------- 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index a8d3b4a5f3e27..aa1ac61f3b040 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -25423,7 +25423,6 @@ "xpack.uptime.alerts.tls.criteriaExpression.ariaLabel": "このアラートで監視されるモニターの条件を示す式", "xpack.uptime.alerts.tls.criteriaExpression.description": "タイミング", "xpack.uptime.alerts.tls.criteriaExpression.value": "任意のモニター", - "xpack.uptime.alerts.tls.defaultActionMessage": "期限切れになるか古くなりすぎた{count} TLS個のTLS証明書証明書を検知しました。\n{expiringConditionalOpen}\n期限切れになる証明書数:{expiringCount}\n期限切れになる証明書:{expiringCommonNameAndDate}\n{expiringConditionalClose}\n{agingConditionalOpen}\n古い証明書数:{agingCount}\n古い証明書:{agingCommonNameAndDate}\n{agingConditionalClose}\n", "xpack.uptime.alerts.tls.description": "アップタイム監視の TLS 証明書の有効期限が近いときにアラートを発行します。", "xpack.uptime.alerts.tls.expirationExpression.ariaLabel": "証明書有効期限の TLS アラートをトリガーするしきい値を示す式", "xpack.uptime.alerts.tls.expirationExpression.description": "証明書が", @@ -25432,7 +25431,6 @@ "xpack.uptime.alerts.tls.expiringLabel": "まもなく期限切れ", "xpack.uptime.alerts.tls.invalidLabel": "無効", "xpack.uptime.alerts.tls.legacy.clientName": "アップタイムTLS(レガシー)", - "xpack.uptime.alerts.tls.legacy.defaultActionMessage": "発行者{issuer}の検出されたTLS証明書{commonName}は{status}です。証明書{summary}\n", "xpack.uptime.alerts.tls.legacy.description": "アップタイム監視の TLS 証明書の有効期限が近いときにアラートを発行します。このアラートは将来のバージョンで廃止予定です。", "xpack.uptime.alerts.tls.settingsPageNav.text": "これらのしきい値は{settingsPageLink}で編集できます。", "xpack.uptime.alerts.tls.validAfterExpiredString": "{relativeDate}日前、{date}に期限切れになりました。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 4bd2a5907abf3..1de08dd3bbd34 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -25854,7 +25854,6 @@ "xpack.uptime.alerts.tls.criteriaExpression.ariaLabel": "显示此告警监视的监测条件的表达式", "xpack.uptime.alerts.tls.criteriaExpression.description": "当", "xpack.uptime.alerts.tls.criteriaExpression.value": "任意监测", - "xpack.uptime.alerts.tls.defaultActionMessage": "已检测到 {count} 个即将过期或即将过时的 TLS 证书。\n{expiringConditionalOpen}\n即将过期的证书计数:{expiringCount}\n即将过期的证书:{expiringCommonNameAndDate}\n{expiringConditionalClose}\n{agingConditionalOpen}\n过时的证书计数:{agingCount}\n过时的证书:{agingCommonNameAndDate}\n{agingConditionalClose}\n", "xpack.uptime.alerts.tls.description": "运行时间监测的 TLS 证书即将过期时告警。", "xpack.uptime.alerts.tls.expirationExpression.ariaLabel": "显示将触发证书过期 TLS 告警的阈值的表达式", "xpack.uptime.alerts.tls.expirationExpression.description": "具有将在", @@ -25863,7 +25862,6 @@ "xpack.uptime.alerts.tls.expiringLabel": "将到期", "xpack.uptime.alerts.tls.invalidLabel": "无效", "xpack.uptime.alerts.tls.legacy.clientName": "Uptime TLS(旧版)", - "xpack.uptime.alerts.tls.legacy.defaultActionMessage": "检测到来自颁发者 {issuer} 的 TLS 证书 {commonName} 的状态为 {status}。证书 {summary}\n", "xpack.uptime.alerts.tls.legacy.description": "运行时间监测的 TLS 证书即将过期时告警。未来的版本将弃用此告警。", "xpack.uptime.alerts.tls.settingsPageNav.text": "可以在 {settingsPageLink}上编辑这些阈值。", "xpack.uptime.alerts.tls.validAfterExpiredString": "已于 {relativeDate} 天前,即 {date}到期。", diff --git a/x-pack/plugins/uptime/common/translations.ts b/x-pack/plugins/uptime/common/translations.ts index 5211438b8ec45..2b414f22f8c19 100644 --- a/x-pack/plugins/uptime/common/translations.ts +++ b/x-pack/plugins/uptime/common/translations.ts @@ -39,7 +39,7 @@ export const MonitorStatusTranslations = { }; export const TlsTranslations = { - defaultActionMessage: i18n.translate('xpack.uptime.alerts.tls.legacy.defaultActionMessage', { + defaultActionMessage: i18n.translate('xpack.uptime.alerts.tls.defaultActionMessage', { defaultMessage: `Detected TLS certificate {commonName} from issuer {issuer} is {status}. Certificate {summary} `, values: { @@ -49,17 +49,16 @@ export const TlsTranslations = { status: '{{state.status}}', }, }), - name: i18n.translate('xpack.uptime.alerts.tls.legacy.clientName', { - defaultMessage: 'Uptime TLS (Legacy)', + name: i18n.translate('xpack.uptime.alerts.tls.clientName', { + defaultMessage: 'Uptime TLS', }), - description: i18n.translate('xpack.uptime.alerts.tls.legacy.description', { - defaultMessage: - 'Alert when the TLS certificate of an Uptime monitor is about to expire. This alert will be deprecated in a future version.', + description: i18n.translate('xpack.uptime.alerts.tls.description', { + defaultMessage: 'Alert when the TLS certificate of an Uptime monitor is about to expire.', }), }; export const TlsTranslationsLegacy = { - defaultActionMessage: i18n.translate('xpack.uptime.alerts.tls.defaultActionMessage', { + defaultActionMessage: i18n.translate('xpack.uptime.alerts.tls.legacy.defaultActionMessage', { defaultMessage: `Detected {count} TLS certificates expiring or becoming too old. {expiringConditionalOpen} Expiring cert count: {expiringCount} @@ -82,11 +81,12 @@ Aging Certificates: {agingCommonNameAndDate} agingConditionalClose: '{{/state.hasAging}}', }, }), - name: i18n.translate('xpack.uptime.alerts.tls.clientName', { - defaultMessage: 'Uptime TLS', + name: i18n.translate('xpack.uptime.alerts.tls.legacy.clientName', { + defaultMessage: 'Uptime TLS (Legacy)', }), - description: i18n.translate('xpack.uptime.alerts.tls.description', { - defaultMessage: 'Alert when the TLS certificate of an Uptime monitor is about to expire.', + description: i18n.translate('xpack.uptime.alerts.tls.legacy.description', { + defaultMessage: + 'Alert when the TLS certificate of an Uptime monitor is about to expire. This alert will be deprecated in a future version.', }), }; @@ -109,6 +109,6 @@ Response times as high as {slowestAnomalyResponse} have been detected from locat defaultMessage: 'Uptime Duration Anomaly', }), description: i18n.translate('xpack.uptime.alerts.durationAnomaly.description', { - defaultMessage: 'Alert when the Uptime monitor duration is anaomalous.', + defaultMessage: 'Alert when the Uptime monitor duration is anomalous.', }), }; From 73dd334c0963c83b604932696d4ffbdd96617a08 Mon Sep 17 00:00:00 2001 From: Mark Hopkin Date: Tue, 26 Oct 2021 09:33:10 +0100 Subject: [PATCH 14/58] [Fleet] Use data stream name in query to get data stream info (#115805) * reduce number of backing indices we query * remove unused import * revert to using data stream name --- .../server/routes/data_streams/handlers.ts | 26 +++++++------------ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/x-pack/plugins/fleet/server/routes/data_streams/handlers.ts b/x-pack/plugins/fleet/server/routes/data_streams/handlers.ts index 073ff7806d9fe..050b1a2441fed 100644 --- a/x-pack/plugins/fleet/server/routes/data_streams/handlers.ts +++ b/x-pack/plugins/fleet/server/routes/data_streams/handlers.ts @@ -6,7 +6,7 @@ */ import type { estypes } from '@elastic/elasticsearch'; import { keyBy, keys, merge } from 'lodash'; -import type { RequestHandler, SavedObjectsBulkGetObject } from 'src/core/server'; +import type { RequestHandler } from 'src/core/server'; import type { DataStream } from '../../types'; import { KibanaSavedObjectType } from '../../../common'; @@ -15,7 +15,6 @@ import { getPackageSavedObjects } from '../../services/epm/packages/get'; import { defaultIngestErrorHandler } from '../../errors'; const DATA_STREAM_INDEX_PATTERN = 'logs-*-*,metrics-*-*,traces-*-*,synthetics-*-*'; - interface ESDataStreamInfo { name: string; timestamp_field: { @@ -94,17 +93,12 @@ export const getListHandler: RequestHandler = async (context, request, response) const allDashboardSavedObjectsResponse = await context.core.savedObjects.client.bulkGet<{ title?: string; }>( - Object.values(dashboardIdsByPackageName).reduce( - (allDashboards, dashboardIds) => { - return allDashboards.concat( - dashboardIds.map((id) => ({ - id, - type: KibanaSavedObjectType.dashboard, - fields: ['title'], - })) - ); - }, - [] + Object.values(dashboardIdsByPackageName).flatMap((dashboardIds) => + dashboardIds.map((id) => ({ + id, + type: KibanaSavedObjectType.dashboard, + fields: ['title'], + })) ) ); // Ignore dashboards not found @@ -142,12 +136,12 @@ export const getListHandler: RequestHandler = async (context, request, response) const { body: { aggregations: dataStreamAggs }, } = await esClient.search({ - index: dataStream.indices.map((index) => index.index_name), + index: dataStream.name, body: { size: 0, query: { bool: { - must: [ + filter: [ { exists: { field: 'data_stream.namespace', @@ -234,7 +228,7 @@ export const getListHandler: RequestHandler = async (context, request, response) return dataStreamResponse; }); - // Return final data streams objects sorted by last activity, decending + // Return final data streams objects sorted by last activity, descending // After filtering out data streams that are missing dataset/namespace/type fields body.data_streams = (await Promise.all(dataStreamPromises)) .filter(({ dataset, namespace, type }) => dataset && namespace && type) From d7f202937f85ac2af4643e846aee85c61fbb323f Mon Sep 17 00:00:00 2001 From: Esteban Beltran Date: Tue, 26 Oct 2021 10:49:32 +0200 Subject: [PATCH 15/58] [Security Solution] Validate ipv4/CIDR with format x.x.x.x/xx (#116127) --- .../pages/host_isolation_exceptions/utils.ts | 19 ++++++--- .../view/components/form.test.tsx | 39 +++++++++++++------ 2 files changed, 41 insertions(+), 17 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/utils.ts b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/utils.ts index bfb1ac048e286..aecdfd9f0c464 100644 --- a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/utils.ts +++ b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/utils.ts @@ -31,11 +31,20 @@ export function createEmptyHostIsolationException(): CreateExceptionListItemSche }; } +/** + * Validates that an IP is a valid ipv4 or CIDR. + * The initial regex validates the format for x.x.x.x/xx + * Then ipaddr is used for a deeper ipv4 validation + */ export function isValidIPv4OrCIDR(maybeIp: string): boolean { - try { - ipaddr.IPv4.parseCIDR(maybeIp); - return true; - } catch (e) { - return ipaddr.IPv4.isValid(maybeIp); + const ipv4re = /^([0-9]{1,3}\.){3}[0-9]{1,3}(\/([0-9]|[1-2][0-9]|3[0-2]))?$/; + if (ipv4re.test(maybeIp)) { + try { + ipaddr.IPv4.parseCIDR(maybeIp); + return true; + } catch (e) { + return ipaddr.IPv4.isValid(maybeIp); + } } + return false; } diff --git a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/components/form.test.tsx b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/components/form.test.tsx index 826f7bf6c4d8a..eb8294a1f4658 100644 --- a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/components/form.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/components/form.test.tsx @@ -44,6 +44,7 @@ describe('When on the host isolation exceptions add entry form', () => { newException = createEmptyHostIsolationException(); renderResult = render(newException); }); + it('should render the form with empty inputs', () => { expect(renderResult.getByTestId('hostIsolationExceptions-form-name-input')).toHaveValue(''); expect(renderResult.getByTestId('hostIsolationExceptions-form-ip-input')).toHaveValue(''); @@ -51,20 +52,31 @@ describe('When on the host isolation exceptions add entry form', () => { renderResult.getByTestId('hostIsolationExceptions-form-description-input') ).toHaveValue(''); }); - it('should call onError with true when a wrong ip value is introduced', () => { - const ipInput = renderResult.getByTestId('hostIsolationExceptions-form-ip-input'); - userEvent.type(ipInput, 'not an ip'); - expect(onError).toHaveBeenCalledWith(true); - }); - it('should call onError with false when a correct values are introduced', () => { - const ipInput = renderResult.getByTestId('hostIsolationExceptions-form-ip-input'); - const nameInput = renderResult.getByTestId('hostIsolationExceptions-form-name-input'); - userEvent.type(nameInput, 'test name'); - userEvent.type(ipInput, '10.0.0.1'); + it.each(['not an ip', '100', '900.0.0.1', 'x.x.x.x', '10.0.0'])( + 'should call onError with true when a wrong ip value is introduced. Case: "%s"', + (value: string) => { + const nameInput = renderResult.getByTestId('hostIsolationExceptions-form-name-input'); + const ipInput = renderResult.getByTestId('hostIsolationExceptions-form-ip-input'); + userEvent.type(nameInput, 'test name'); + userEvent.type(ipInput, value); + expect(onError).toHaveBeenCalledWith(true); + } + ); + + it.each(['192.168.0.1', '10.0.0.1', '100.90.1.1/24', '192.168.200.6/30'])( + 'should call onError with false when a correct ip value is introduced. Case: "%s"', + (value: string) => { + const ipInput = renderResult.getByTestId('hostIsolationExceptions-form-ip-input'); + const nameInput = renderResult.getByTestId('hostIsolationExceptions-form-name-input'); + + userEvent.type(nameInput, 'test name'); + userEvent.type(ipInput, value); + + expect(onError).toHaveBeenLastCalledWith(false); + } + ); - expect(onError).toHaveBeenLastCalledWith(false); - }); it('should call onChange when a value is introduced in a field', () => { const ipInput = renderResult.getByTestId('hostIsolationExceptions-form-ip-input'); userEvent.type(ipInput, '10.0.0.1'); @@ -76,6 +88,7 @@ describe('When on the host isolation exceptions add entry form', () => { }); }); }); + describe('When editing an existing exception', () => { let existingException: UpdateExceptionListItemSchema; beforeEach(() => { @@ -96,6 +109,7 @@ describe('When on the host isolation exceptions add entry form', () => { }; renderResult = render(existingException); }); + it('should render the form with pre-filled inputs', () => { expect(renderResult.getByTestId('hostIsolationExceptions-form-name-input')).toHaveValue( 'name edit me' @@ -107,6 +121,7 @@ describe('When on the host isolation exceptions add entry form', () => { renderResult.getByTestId('hostIsolationExceptions-form-description-input') ).toHaveValue('initial description'); }); + it('should call onChange when a value is introduced in a field', () => { const ipInput = renderResult.getByTestId('hostIsolationExceptions-form-ip-input'); userEvent.clear(ipInput); From 8d195db519f1cba6ca49a73a880adbb7855a2d49 Mon Sep 17 00:00:00 2001 From: Lucca Miranda <42002892+luckened@users.noreply.github.com> Date: Tue, 26 Oct 2021 06:01:26 -0300 Subject: [PATCH 16/58] chore: rename getApmHref to getLegacyApmHref (#115689) * chore: rename getApmHref to getLegacyApmHref * chore: lint Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../apm/dev_docs/routing_and_linking.md | 2 +- .../components/app/service_map/Controls.tsx | 4 ++-- .../routing/templates/settings_template.tsx | 20 +++++++++++++------ .../components/shared/Links/apm/APMLink.tsx | 6 +++--- .../Links/apm/agentConfigurationLinks.tsx | 4 ++-- .../Links/apm/transaction_detail_link.tsx | 4 ++-- .../Links/apm/transaction_overview_link.tsx | 4 ++-- .../anomaly_detection_setup_link.tsx | 4 ++-- .../shared/apm_header_action_menu/index.tsx | 4 ++-- .../actions_popover/integration_group.tsx | 4 ++-- .../get_apm_href.test.ts | 10 +++++----- .../observability_integration/get_apm_href.ts | 2 +- .../helper/observability_integration/index.ts | 2 +- 13 files changed, 39 insertions(+), 31 deletions(-) diff --git a/x-pack/plugins/apm/dev_docs/routing_and_linking.md b/x-pack/plugins/apm/dev_docs/routing_and_linking.md index af22bcdbdfa11..a1fdff3821c4c 100644 --- a/x-pack/plugins/apm/dev_docs/routing_and_linking.md +++ b/x-pack/plugins/apm/dev_docs/routing_and_linking.md @@ -69,7 +69,7 @@ const serviceOverviewLink = apmRouter.link('/services/:serviceName', { path: { s If you're not in React context, you can also import `apmRouter` directly and call its `link` function - but you have to prepend the basePath manually in that case. -We also have the [`getAPMHref` function and `APMLink` component](../public/components/shared/Links/apm/APMLink.tsx), but we should consider them deprecated, in favor of `router.link`. Other components inside that directory contain other functions and components that provide the same functionality for linking to more specific sections inside the APM plugin. +We also have the [`getLegacyApmHref` function and `APMLink` component](../public/components/shared/Links/apm/APMLink.tsx), but we should consider them deprecated, in favor of `router.link`. Other components inside that directory contain other functions and components that provide the same functionality for linking to more specific sections inside the APM plugin. ### Cross-app linking diff --git a/x-pack/plugins/apm/public/components/app/service_map/Controls.tsx b/x-pack/plugins/apm/public/components/app/service_map/Controls.tsx index dd34110a8ffc6..69644216fc267 100644 --- a/x-pack/plugins/apm/public/components/app/service_map/Controls.tsx +++ b/x-pack/plugins/apm/public/components/app/service_map/Controls.tsx @@ -12,7 +12,7 @@ import { euiStyled } from '../../../../../../../src/plugins/kibana_react/common' import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context'; import { useTheme } from '../../../hooks/use_theme'; import { useUrlParams } from '../../../context/url_params_context/use_url_params'; -import { getAPMHref } from '../../shared/Links/apm/APMLink'; +import { getLegacyApmHref } from '../../shared/Links/apm/APMLink'; import { APMQueryParams } from '../../shared/Links/url_helpers'; import { CytoscapeContext } from './Cytoscape'; import { getAnimationOptions, getNodeHeight } from './cytoscape_options'; @@ -112,7 +112,7 @@ export function Controls() { const [zoom, setZoom] = useState((cy && cy.zoom()) || 1); const duration = parseInt(theme.eui.euiAnimSpeedFast, 10); const downloadUrl = useDebugDownloadUrl(cy); - const viewFullMapUrl = getAPMHref({ + const viewFullMapUrl = getLegacyApmHref({ basePath, path: '/service-map', search: `kuery=${encodeURIComponent(kuery)}`, diff --git a/x-pack/plugins/apm/public/components/routing/templates/settings_template.tsx b/x-pack/plugins/apm/public/components/routing/templates/settings_template.tsx index a76b464731513..ecca2ddb07ec3 100644 --- a/x-pack/plugins/apm/public/components/routing/templates/settings_template.tsx +++ b/x-pack/plugins/apm/public/components/routing/templates/settings_template.tsx @@ -13,7 +13,7 @@ import { useHistory } from 'react-router-dom'; import { CoreStart } from 'kibana/public'; import { ApmMainTemplate } from './apm_main_template'; import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context'; -import { getAPMHref } from '../../shared/Links/apm/APMLink'; +import { getLegacyApmHref } from '../../shared/Links/apm/APMLink'; type Tab = NonNullable[0] & { key: @@ -69,7 +69,7 @@ function getTabs({ label: i18n.translate('xpack.apm.settings.agentConfig', { defaultMessage: 'Agent Configuration', }), - href: getAPMHref({ + href: getLegacyApmHref({ basePath, path: `/settings/agent-configuration`, search, @@ -80,7 +80,7 @@ function getTabs({ label: i18n.translate('xpack.apm.settings.anomalyDetection', { defaultMessage: 'Anomaly detection', }), - href: getAPMHref({ + href: getLegacyApmHref({ basePath, path: `/settings/anomaly-detection`, search, @@ -92,21 +92,29 @@ function getTabs({ label: i18n.translate('xpack.apm.settings.customizeApp', { defaultMessage: 'Customize app', }), - href: getAPMHref({ basePath, path: `/settings/customize-ui`, search }), + href: getLegacyApmHref({ + basePath, + path: `/settings/customize-ui`, + search, + }), }, { key: 'apm-indices', label: i18n.translate('xpack.apm.settings.indices', { defaultMessage: 'Indices', }), - href: getAPMHref({ basePath, path: `/settings/apm-indices`, search }), + href: getLegacyApmHref({ + basePath, + path: `/settings/apm-indices`, + search, + }), }, { key: 'schema', label: i18n.translate('xpack.apm.settings.schema', { defaultMessage: 'Schema', }), - href: getAPMHref({ basePath, path: `/settings/schema`, search }), + href: getLegacyApmHref({ basePath, path: `/settings/schema`, search }), }, ]; diff --git a/x-pack/plugins/apm/public/components/shared/Links/apm/APMLink.tsx b/x-pack/plugins/apm/public/components/shared/Links/apm/APMLink.tsx index 7c9f6479bfc6a..fbf4dff24fbf4 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/apm/APMLink.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/apm/APMLink.tsx @@ -54,13 +54,13 @@ export function useAPMHref({ ...query, }; - return getAPMHref({ basePath, path, query: nextQuery, search }); + return getLegacyApmHref({ basePath, path, query: nextQuery, search }); } /** * Get an APM link for a path. */ -export function getAPMHref({ +export function getLegacyApmHref({ basePath, path = '', search, @@ -91,7 +91,7 @@ export function APMLink({ path = '', query, mergeQuery, ...rest }: Props) { const mergedQuery = mergeQuery ? mergeQuery(query ?? {}) : query; - const href = getAPMHref({ basePath, path, search, query: mergedQuery }); + const href = getLegacyApmHref({ basePath, path, search, query: mergedQuery }); return ; } diff --git a/x-pack/plugins/apm/public/components/shared/Links/apm/agentConfigurationLinks.tsx b/x-pack/plugins/apm/public/components/shared/Links/apm/agentConfigurationLinks.tsx index 58c510eff13a4..c45ab22682ef4 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/apm/agentConfigurationLinks.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/apm/agentConfigurationLinks.tsx @@ -7,14 +7,14 @@ import { IBasePath } from 'kibana/public'; import { AgentConfigurationIntake } from '../../../../../common/agent_configuration/configuration_types'; -import { getAPMHref } from './APMLink'; +import { getLegacyApmHref } from './APMLink'; export function editAgentConfigurationHref( configService: AgentConfigurationIntake['service'], search: string, basePath: IBasePath ) { - return getAPMHref({ + return getLegacyApmHref({ basePath, path: '/settings/agent-configuration/edit', search, diff --git a/x-pack/plugins/apm/public/components/shared/Links/apm/transaction_detail_link.tsx b/x-pack/plugins/apm/public/components/shared/Links/apm/transaction_detail_link.tsx index 2f6016466e37e..06db6c9d42382 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/apm/transaction_detail_link.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/apm/transaction_detail_link.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { useLocation } from 'react-router-dom'; import { EuiLink } from '@elastic/eui'; import { pickBy, identity } from 'lodash'; -import { getAPMHref, APMLinkExtendProps } from './APMLink'; +import { getLegacyApmHref, APMLinkExtendProps } from './APMLink'; import { useUrlParams } from '../../../../context/url_params_context/use_url_params'; import { pickKeys } from '../../../../../common/utils/pick_keys'; import { APMQueryParams } from '../url_helpers'; @@ -43,7 +43,7 @@ export function TransactionDetailLink({ const { urlParams } = useUrlParams(); const { core } = useApmPluginContext(); const location = useLocation(); - const href = getAPMHref({ + const href = getLegacyApmHref({ basePath: core.http.basePath, path: `/services/${serviceName}/transactions/view`, query: { diff --git a/x-pack/plugins/apm/public/components/shared/Links/apm/transaction_overview_link.tsx b/x-pack/plugins/apm/public/components/shared/Links/apm/transaction_overview_link.tsx index e56e4a32d9bad..d3e40aebc1daf 100644 --- a/x-pack/plugins/apm/public/components/shared/Links/apm/transaction_overview_link.tsx +++ b/x-pack/plugins/apm/public/components/shared/Links/apm/transaction_overview_link.tsx @@ -10,7 +10,7 @@ import React from 'react'; import { useLocation } from 'react-router-dom'; import { removeUndefinedProps } from '../../../../context/url_params_context/helpers'; import { useApmPluginContext } from '../../../../context/apm_plugin/use_apm_plugin_context'; -import { APMLinkExtendProps, getAPMHref } from './APMLink'; +import { APMLinkExtendProps, getLegacyApmHref } from './APMLink'; interface Props extends APMLinkExtendProps { serviceName: string; @@ -29,7 +29,7 @@ export function useTransactionsOverviewHref({ const query = { latencyAggregationType, transactionType }; - return getAPMHref({ + return getLegacyApmHref({ basePath: core.http.basePath, path: `/services/${serviceName}/transactions`, query: removeUndefinedProps(query), diff --git a/x-pack/plugins/apm/public/components/shared/apm_header_action_menu/anomaly_detection_setup_link.tsx b/x-pack/plugins/apm/public/components/shared/apm_header_action_menu/anomaly_detection_setup_link.tsx index 970cc886d30bd..4891ca896076a 100644 --- a/x-pack/plugins/apm/public/components/shared/apm_header_action_menu/anomaly_detection_setup_link.tsx +++ b/x-pack/plugins/apm/public/components/shared/apm_header_action_menu/anomaly_detection_setup_link.tsx @@ -24,7 +24,7 @@ import { useApmParams } from '../../../hooks/use_apm_params'; import { FETCH_STATUS } from '../../../hooks/use_fetcher'; import { useTheme } from '../../../hooks/use_theme'; import { APIReturnType } from '../../../services/rest/createCallApmApi'; -import { getAPMHref } from '../Links/apm/APMLink'; +import { getLegacyApmHref } from '../Links/apm/APMLink'; export type AnomalyDetectionApiResponse = APIReturnType<'GET /internal/apm/settings/anomaly-detection/jobs'>; @@ -47,7 +47,7 @@ export function AnomalyDetectionSetupLink() { return ( {canGetJobs && hasValidLicense ? ( diff --git a/x-pack/plugins/apm/public/components/shared/apm_header_action_menu/index.tsx b/x-pack/plugins/apm/public/components/shared/apm_header_action_menu/index.tsx index 633d03ce8e1df..655fc2da2b097 100644 --- a/x-pack/plugins/apm/public/components/shared/apm_header_action_menu/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/apm_header_action_menu/index.tsx @@ -9,7 +9,7 @@ import { EuiHeaderLink, EuiHeaderLinks } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; import { getAlertingCapabilities } from '../../alerting/get_alerting_capabilities'; -import { getAPMHref } from '../Links/apm/APMLink'; +import { getLegacyApmHref } from '../Links/apm/APMLink'; import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context'; import { AlertingPopoverAndFlyout } from './alerting_popover_flyout'; import { AnomalyDetectionSetupLink } from './anomaly_detection_setup_link'; @@ -33,7 +33,7 @@ export function ApmHeaderActionMenu() { const canSaveApmAlerts = capabilities.apm.save && canSaveAlerts; function apmHref(path: string) { - return getAPMHref({ basePath, path, search }); + return getLegacyApmHref({ basePath, path, search }); } function kibanaHref(path: string) { diff --git a/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/actions_popover/integration_group.tsx b/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/actions_popover/integration_group.tsx index 2fbb14ea9c203..5347558ed347e 100644 --- a/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/actions_popover/integration_group.tsx +++ b/x-pack/plugins/uptime/public/components/overview/monitor_list/monitor_list_drawer/actions_popover/integration_group.tsx @@ -11,7 +11,7 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; import { IntegrationLink } from './integration_link'; import { - getApmHref, + getLegacyApmHref, getInfraContainerHref, getInfraIpHref, getInfraKubernetesHref, @@ -65,7 +65,7 @@ export const IntegrationGroup = ({ summary }: IntegrationGroupProps) => { description: 'This value is shown to users when they hover over an icon that will take them to the APM app.', })} - href={getApmHref(summary, basePath, dateRangeStart, dateRangeEnd)} + href={getLegacyApmHref(summary, basePath, dateRangeStart, dateRangeEnd)} iconType="apmApp" message={i18n.translate('xpack.uptime.apmIntegrationAction.text', { defaultMessage: 'Show APM Data', diff --git a/x-pack/plugins/uptime/public/lib/helper/observability_integration/get_apm_href.test.ts b/x-pack/plugins/uptime/public/lib/helper/observability_integration/get_apm_href.test.ts index cc2a88c7ede35..db946fb246964 100644 --- a/x-pack/plugins/uptime/public/lib/helper/observability_integration/get_apm_href.test.ts +++ b/x-pack/plugins/uptime/public/lib/helper/observability_integration/get_apm_href.test.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { getApmHref } from './get_apm_href'; +import { getLegacyApmHref } from './get_apm_href'; import { MonitorSummary, makePing } from '../../../../common/runtime_types'; -describe('getApmHref', () => { +describe('getLegacyApmHref', () => { let summary: MonitorSummary; beforeEach(() => { summary = { @@ -37,14 +37,14 @@ describe('getApmHref', () => { }); it('creates href with base path when present', () => { - const result = getApmHref(summary, 'foo', 'now-15m', 'now'); + const result = getLegacyApmHref(summary, 'foo', 'now-15m', 'now'); expect(result).toMatchInlineSnapshot( `"foo/app/apm#/services?kuery=url.domain:%20%22www.elastic.co%22&rangeFrom=now-15m&rangeTo=now"` ); }); it('does not add a base path or extra slash when base path is empty string', () => { - const result = getApmHref(summary, '', 'now-15m', 'now'); + const result = getLegacyApmHref(summary, '', 'now-15m', 'now'); expect(result).toMatchInlineSnapshot( `"/app/apm#/services?kuery=url.domain:%20%22www.elastic.co%22&rangeFrom=now-15m&rangeTo=now"` ); @@ -57,7 +57,7 @@ describe('getApmHref', () => { }); it('links to the named service', () => { - const result = getApmHref(summary, 'foo', 'now-15m', 'now'); + const result = getLegacyApmHref(summary, 'foo', 'now-15m', 'now'); expect(result).toMatchInlineSnapshot( `"foo/app/apm#/services?kuery=service.name:%20%22${serviceName}%22&rangeFrom=now-15m&rangeTo=now"` ); diff --git a/x-pack/plugins/uptime/public/lib/helper/observability_integration/get_apm_href.ts b/x-pack/plugins/uptime/public/lib/helper/observability_integration/get_apm_href.ts index a4df767ddd7e1..fc5785ceecba1 100644 --- a/x-pack/plugins/uptime/public/lib/helper/observability_integration/get_apm_href.ts +++ b/x-pack/plugins/uptime/public/lib/helper/observability_integration/get_apm_href.ts @@ -8,7 +8,7 @@ import { addBasePath } from './add_base_path'; import { MonitorSummary } from '../../../../common/runtime_types'; -export const getApmHref = ( +export const getLegacyApmHref = ( summary: MonitorSummary, basePath: string, dateRangeStart: string, diff --git a/x-pack/plugins/uptime/public/lib/helper/observability_integration/index.ts b/x-pack/plugins/uptime/public/lib/helper/observability_integration/index.ts index eeee55c380775..c739f6d706923 100644 --- a/x-pack/plugins/uptime/public/lib/helper/observability_integration/index.ts +++ b/x-pack/plugins/uptime/public/lib/helper/observability_integration/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -export { getApmHref } from './get_apm_href'; +export { getLegacyApmHref } from './get_apm_href'; export { getInfraContainerHref, getInfraIpHref, getInfraKubernetesHref } from './get_infra_href'; export { getLoggingContainerHref, From 877db67357fdd0f491a2052e2795eac0d80968ca Mon Sep 17 00:00:00 2001 From: Marta Bondyra Date: Tue, 26 Oct 2021 11:37:49 +0200 Subject: [PATCH 17/58] [Lens] Improve tick placement for binary formatter (#116158) --- .../xy_visualization/expression.test.tsx | 34 +++++++++++++++++++ .../public/xy_visualization/expression.tsx | 8 ++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/lens/public/xy_visualization/expression.test.tsx b/x-pack/plugins/lens/public/xy_visualization/expression.test.tsx index 5f9abba3806cf..e91f9d54ca86c 100644 --- a/x-pack/plugins/lens/public/xy_visualization/expression.test.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/expression.test.tsx @@ -1445,6 +1445,40 @@ describe('xy_expression', () => { }); }); + test('sets up correct yScaleType equal to binary_linear for bytes formatting', () => { + const { args, data } = sampleArgs(); + data.tables.first.columns[0].meta = { + type: 'number', + params: { id: 'bytes', params: { pattern: '0,0.00b' } }, + }; + + const wrapper = mountWithIntl( + + ); + + expect(wrapper.find(LineSeries).at(0).prop('yScaleType')).toEqual('linear_binary'); + }); + test('allowBrushingLastHistogramBin should be fakse for ordinal data', () => { const { args, data } = sampleArgs(); diff --git a/x-pack/plugins/lens/public/xy_visualization/expression.tsx b/x-pack/plugins/lens/public/xy_visualization/expression.tsx index 32ca4c982c10e..a3022e830c861 100644 --- a/x-pack/plugins/lens/public/xy_visualization/expression.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/expression.tsx @@ -31,6 +31,7 @@ import { LabelOverflowConstraint, DisplayValueStyle, RecursivePartial, + ScaleType, } from '@elastic/charts'; import { I18nProvider } from '@kbn/i18n/react'; import type { @@ -767,6 +768,8 @@ export function XYChart({ axisConfiguration.series.find((currentSeries) => currentSeries.accessor === accessor) ); + const formatter = table?.columns.find((column) => column.id === accessor)?.meta?.params; + const seriesProps: SeriesSpec = { splitSeriesAccessors: splitAccessor ? [splitAccessor] : [], stackAccessors: isStacked ? [xAccessor as string] : [], @@ -775,7 +778,10 @@ export function XYChart({ yAccessors: [accessor], data: rows, xScaleType: xAccessor ? xScaleType : 'ordinal', - yScaleType, + yScaleType: + formatter?.id === 'bytes' && yScaleType === ScaleType.Linear + ? ScaleType.LinearBinary + : yScaleType, color: ({ yAccessor, seriesKeys }) => { const overwriteColor = getSeriesColor(layer, accessor); if (overwriteColor !== null) { From 0b2d3b7033b876b71b89df763bb68cbff167f68e Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Tue, 26 Oct 2021 04:47:23 -0500 Subject: [PATCH 18/58] Unskip jest handled promise rejections (#116021) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../__jest__/client_integration/home/indices_tab.test.ts | 1 - .../public/components/fleet_package/custom_fields.test.tsx | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/x-pack/plugins/index_management/__jest__/client_integration/home/indices_tab.test.ts b/x-pack/plugins/index_management/__jest__/client_integration/home/indices_tab.test.ts index f95ea373d58b4..5f5580d263285 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/home/indices_tab.test.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/home/indices_tab.test.ts @@ -22,7 +22,6 @@ import { stubWebWorker } from '@kbn/test/jest'; import { createMemoryHistory } from 'history'; stubWebWorker(); -// unhandled promise rejection https://github.com/elastic/kibana/issues/112699 describe('', () => { let testBed: IndicesTestBed; let server: ReturnType['server']; diff --git a/x-pack/plugins/uptime/public/components/fleet_package/custom_fields.test.tsx b/x-pack/plugins/uptime/public/components/fleet_package/custom_fields.test.tsx index 03bba0f8d2e54..5c24883d588e2 100644 --- a/x-pack/plugins/uptime/public/components/fleet_package/custom_fields.test.tsx +++ b/x-pack/plugins/uptime/public/components/fleet_package/custom_fields.test.tsx @@ -50,8 +50,7 @@ const defaultValidation = centralValidation[DataStream.HTTP]; const defaultHTTPConfig = defaultConfig[DataStream.HTTP]; const defaultTCPConfig = defaultConfig[DataStream.TCP]; -// unhandled promise rejection: https://github.com/elastic/kibana/issues/112699 -describe.skip('', () => { +describe('', () => { const WrappedComponent = ({ validate = defaultValidation, isEditable = false, From 060bd418102078ef2f822bd200638964c44f34a9 Mon Sep 17 00:00:00 2001 From: mgiota Date: Tue, 26 Oct 2021 11:55:51 +0200 Subject: [PATCH 19/58] [RAC]: add experimental badge to alerts (#116090) * [RAC]: add experimental badge to alerts * combine feedback disclaimer into one text * create a reusable AlertsDisclaimer component * apend more details text to the apm alert * fix failing i18n tests * remove basePath from url * fix failing unit tests * fix unit tests * add experimental to the alert annotation * i18n for experimental text * reuse ExperimentalBadge for the flyout and refactor AlertsDisclaimer --- .../helper/get_alert_annotations.test.tsx | 10 ++--- .../charts/helper/get_alert_annotations.tsx | 15 +++++++- .../public/pages/alerts/alerts_disclaimer.tsx | 37 +++++++++++++++++++ .../pages/alerts/alerts_flyout/index.tsx | 3 ++ .../public/pages/alerts/index.tsx | 24 ++---------- .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - 7 files changed, 62 insertions(+), 29 deletions(-) create mode 100644 x-pack/plugins/observability/public/pages/alerts/alerts_disclaimer.tsx diff --git a/x-pack/plugins/apm/public/components/shared/charts/helper/get_alert_annotations.test.tsx b/x-pack/plugins/apm/public/components/shared/charts/helper/get_alert_annotations.test.tsx index 4573e8e5a174f..a3ab10ea6514a 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/helper/get_alert_annotations.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/helper/get_alert_annotations.test.tsx @@ -110,7 +110,7 @@ describe('getAlertAnnotations', () => { setSelectedAlertId, theme, })![0].props.dataValues[0].header - ).toEqual('Alert'); + ).toEqual('Alert - Experimental'); }); it('uses the reason in the annotation details', () => { @@ -123,7 +123,7 @@ describe('getAlertAnnotations', () => { setSelectedAlertId, theme, })![0].props.dataValues[0].details - ).toEqual('a good reason'); + ).toEqual('a good reason. Click to see more details.'); }); describe('with no formatter', () => { @@ -140,7 +140,7 @@ describe('getAlertAnnotations', () => { setSelectedAlertId, theme, })![0].props.dataValues[0].details - ).toEqual(alert[ALERT_RULE_NAME]![0]); + ).toEqual(`${alert[ALERT_RULE_NAME]![0]}. Click to see more details.`); }); }); @@ -191,7 +191,7 @@ describe('getAlertAnnotations', () => { setSelectedAlertId, theme, })![0].props.dataValues[0].header - ).toEqual('Warning Alert'); + ).toEqual('Warning Alert - Experimental'); }); }); @@ -224,7 +224,7 @@ describe('getAlertAnnotations', () => { setSelectedAlertId, theme, })![0].props.dataValues[0].header - ).toEqual('Critical Alert'); + ).toEqual('Critical Alert - Experimental'); }); }); }); diff --git a/x-pack/plugins/apm/public/components/shared/charts/helper/get_alert_annotations.tsx b/x-pack/plugins/apm/public/components/shared/charts/helper/get_alert_annotations.tsx index f4c47a9247e75..038269d3cefdc 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/helper/get_alert_annotations.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/helper/get_alert_annotations.tsx @@ -122,7 +122,13 @@ export function getAlertAnnotations({ const end = start + parsed[ALERT_DURATION]! / 1000; const severityLevel = parsed[ALERT_SEVERITY]; const color = getAlertColor({ severityLevel, theme }); - const header = getAlertHeader({ severityLevel }); + const experimentalLabel = i18n.translate( + 'xpack.apm.alertAnnotationTooltipExperimentalText', + { defaultMessage: 'Experimental' } + ); + const header = `${getAlertHeader({ + severityLevel, + })} - ${experimentalLabel}`; const formatter = getFormatter(parsed[ALERT_RULE_TYPE_ID]!); const formatted = { link: undefined, @@ -133,13 +139,18 @@ export function getAlertAnnotations({ }) ?? {}), }; const isSelected = uuid === selectedAlertId; + const moreDetails = i18n.translate( + 'xpack.apm.alertAnnotationTooltipMoreDetailsText', + { defaultMessage: 'Click to see more details.' } + ); + const details = `${formatted.reason}. ${moreDetails}`; return [ + + {i18n.translate('xpack.observability.alertsDisclaimerLinkText', { + defaultMessage: 'feedback', + })} + + ), + }} + /> + + ); +} diff --git a/x-pack/plugins/observability/public/pages/alerts/alerts_flyout/index.tsx b/x-pack/plugins/observability/public/pages/alerts/alerts_flyout/index.tsx index 7171daa4a56e3..034b7522b9136 100644 --- a/x-pack/plugins/observability/public/pages/alerts/alerts_flyout/index.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/alerts_flyout/index.tsx @@ -46,6 +46,7 @@ import { asDuration } from '../../../../common/utils/formatters'; import type { ObservabilityRuleTypeRegistry } from '../../../rules/create_observability_rule_type_registry'; import { parseAlert } from '../parse_alert'; import { AlertStatusIndicator } from '../../../components/shared/alert_status_indicator'; +import { ExperimentalBadge } from '../../../components/shared/experimental_badge'; type AlertsFlyoutProps = { alert?: TopAlert; @@ -137,6 +138,8 @@ export function AlertsFlyout({ return ( + +

{alertData.fields[ALERT_RULE_NAME]}

diff --git a/x-pack/plugins/observability/public/pages/alerts/index.tsx b/x-pack/plugins/observability/public/pages/alerts/index.tsx index e8b550ac353a6..a3c060f5dc5df 100644 --- a/x-pack/plugins/observability/public/pages/alerts/index.tsx +++ b/x-pack/plugins/observability/public/pages/alerts/index.tsx @@ -5,7 +5,8 @@ * 2.0. */ -import { EuiButtonEmpty, EuiCallOut, EuiFlexGroup, EuiFlexItem, EuiLink } from '@elastic/eui'; +import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; + import { IndexPatternBase } from '@kbn/es-query'; import { i18n } from '@kbn/i18n'; import React, { useCallback, useRef } from 'react'; @@ -26,6 +27,7 @@ import { AlertsTableTGrid } from './alerts_table_t_grid'; import { Provider, alertsPageStateContainer, useAlertsPageStateContainer } from './state_container'; import './styles.scss'; import { WorkflowStatusFilter } from './workflow_status_filter'; +import { AlertsDisclaimer } from './alerts_disclaimer'; export interface TopAlert { fields: ParsedTechnicalFields; @@ -177,25 +179,7 @@ function AlertsPage() { > - -

- {i18n.translate('xpack.observability.alertsDisclaimerText', { - defaultMessage: - 'This page shows an experimental list of alerts. The data might not be accurate. All alerts are available in the ', - })} - - {i18n.translate('xpack.observability.alertsDisclaimerLinkText', { - defaultMessage: 'Rules and Connectors settings.', - })} - -

-
+
75", "xpack.observability.alertsDisclaimerLinkText": "アラートとアクション", - "xpack.observability.alertsDisclaimerText": "このページには実験アラートビューが表示されます。ここに表示されるデータは、アラートを正確に表していない可能性があります。アラートの非実験リストは、スタック管理のアラートとアクション設定にあります。", "xpack.observability.alertsDisclaimerTitle": "実験的", "xpack.observability.alertsFlyout.actualValueLabel": "実際の値", "xpack.observability.alertsFlyout.durationLabel": "期間", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 1de08dd3bbd34..dc43b75b5d1e3 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -7013,7 +7013,6 @@ "xpack.observability.alerts.manageRulesButtonLabel": "管理规则", "xpack.observability.alerts.searchBarPlaceholder": "kibana.alert.evaluation.threshold > 75", "xpack.observability.alertsDisclaimerLinkText": "告警和操作", - "xpack.observability.alertsDisclaimerText": "此页面显示实验性告警视图。此处显示的数据可能无法准确表示告警。在“堆栈管理”的“告警和操作”中提供了告警的非实验性列表。", "xpack.observability.alertsDisclaimerTitle": "实验性", "xpack.observability.alertsFlyout.actualValueLabel": "实际值", "xpack.observability.alertsFlyout.durationLabel": "持续时间", From d442213c0e3f9d961037c780ccd23fbd5c973a34 Mon Sep 17 00:00:00 2001 From: Shahzad Date: Tue, 26 Oct 2021 12:11:35 +0200 Subject: [PATCH 20/58] Fix ux/apm inspector panel (#116188) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/plugins/apm/kibana.json | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/plugins/apm/kibana.json b/x-pack/plugins/apm/kibana.json index 865358959ea72..e57859bfa253e 100644 --- a/x-pack/plugins/apm/kibana.json +++ b/x-pack/plugins/apm/kibana.json @@ -12,6 +12,7 @@ "embeddable", "features", "infra", + "inspector", "licensing", "observability", "ruleRegistry", From 9d9eeb0e8ca4a9567de54d227632cfb277a836e3 Mon Sep 17 00:00:00 2001 From: Dario Gieselaar Date: Tue, 26 Oct 2021 12:42:33 +0200 Subject: [PATCH 21/58] [APM] Optimize synthtrace (#116091) --- packages/elastic-apm-synthtrace/README.md | 31 +-- .../src/lib/output/to_elasticsearch_output.ts | 25 ++- .../src/lib/utils/generate_id.ts | 13 +- .../src/scripts/examples/01_simple_trace.ts | 64 ++++--- .../elastic-apm-synthtrace/src/scripts/run.ts | 85 ++++++--- .../src/scripts/utils/common_options.ts | 53 ------ .../src/scripts/utils/get_common_resources.ts | 28 ++- .../src/scripts/utils/get_write_targets.ts | 3 +- .../src/scripts/utils/logger.ts | 45 ++++- .../utils/start_historical_data_upload.ts | 95 ++++++--- .../scripts/utils/start_live_data_upload.ts | 9 +- .../src/scripts/utils/upload_events.ts | 32 ++-- .../src/scripts/utils/upload_next_batch.js | 15 ++ .../src/scripts/utils/upload_next_batch.ts | 61 ++++++ .../test/scenarios/01_simple_trace.test.ts | 12 +- .../05_transactions_with_errors.test.ts | 2 +- .../01_simple_trace.test.ts.snap | 180 +++++++++--------- .../src/test/to_elasticsearch_output.test.ts | 30 +++ 18 files changed, 482 insertions(+), 301 deletions(-) delete mode 100644 packages/elastic-apm-synthtrace/src/scripts/utils/common_options.ts create mode 100644 packages/elastic-apm-synthtrace/src/scripts/utils/upload_next_batch.js create mode 100644 packages/elastic-apm-synthtrace/src/scripts/utils/upload_next_batch.ts diff --git a/packages/elastic-apm-synthtrace/README.md b/packages/elastic-apm-synthtrace/README.md index 8413ba58a5c42..3d65120b4b6c2 100644 --- a/packages/elastic-apm-synthtrace/README.md +++ b/packages/elastic-apm-synthtrace/README.md @@ -93,23 +93,24 @@ const esEvents = toElasticsearchOutput([ Via the CLI, you can upload scenarios, either using a fixed time range or continuously generating data. Some examples are available in in `src/scripts/examples`. Here's an example for live data: -`$ node packages/elastic-apm-synthtrace/src/scripts/run packages/elastic-apm-synthtrace/src/examples/01_simple_trace.ts --target=http://admin:changeme@localhost:9200 --live` +`$ node packages/elastic-apm-synthtrace/src/scripts/run packages/elastic-apm-generator/src/examples/01_simple_trace.ts --target=http://admin:changeme@localhost:9200 --live` For a fixed time window: -`$ node packages/elastic-apm-synthtrace/src/scripts/run packages/elastic-apm-synthtrace/src/examples/01_simple_trace.ts --target=http://admin:changeme@localhost:9200 --from=now-24h --to=now` +`$ node packages/elastic-apm-synthtrace/src/scripts/run packages/elastic-apm-generator/src/examples/01_simple_trace.ts --target=http://admin:changeme@localhost:9200 --from=now-24h --to=now` -The script will try to automatically find bootstrapped APM indices. **If these indices do not exist, the script will exit with an error. It will not bootstrap the indices itself.** +The script will try to automatically find bootstrapped APM indices. __If these indices do not exist, the script will exit with an error. It will not bootstrap the indices itself.__ The following options are supported: -| Option | Description | Default | -| -------------- | ------------------------------------------------------- | ------------ | -| `--from` | The start of the time window. | `now - 15m` | -| `--to` | The end of the time window. | `now` | -| `--live` | Continously ingest data | `false` | -| `--bucketSize` | Size of bucket for which to generate data. | `15m` | -| `--clean` | Clean APM indices before indexing new data. | `false` | -| `--interval` | The interval at which to index data. | `10s` | -| `--logLevel` | Log level. | `info` | -| `--lookback` | The lookback window for which data should be generated. | `15m` | -| `--target` | Elasticsearch target, including username/password. | **Required** | -| `--workers` | Amount of simultaneously connected ES clients. | `1` | +| Option | Description | Default | +| ------------------| ------------------------------------------------------- | ------------ | +| `--target` | Elasticsearch target, including username/password. | **Required** | +| `--from` | The start of the time window. | `now - 15m` | +| `--to` | The end of the time window. | `now` | +| `--live` | Continously ingest data | `false` | +| `--clean` | Clean APM indices before indexing new data. | `false` | +| `--workers` | Amount of Node.js worker threads | `5` | +| `--bucketSize` | Size of bucket for which to generate data. | `15m` | +| `--interval` | The interval at which to index data. | `10s` | +| `--clientWorkers` | Number of simultaneously connected ES clients | `5` | +| `--batchSize` | Number of documents per bulk index request | `1000` | +| `--logLevel` | Log level. | `info` | diff --git a/packages/elastic-apm-synthtrace/src/lib/output/to_elasticsearch_output.ts b/packages/elastic-apm-synthtrace/src/lib/output/to_elasticsearch_output.ts index 31f3e8c8ed270..016f1c5362fb4 100644 --- a/packages/elastic-apm-synthtrace/src/lib/output/to_elasticsearch_output.ts +++ b/packages/elastic-apm-synthtrace/src/lib/output/to_elasticsearch_output.ts @@ -22,6 +22,18 @@ export interface ElasticsearchOutputWriteTargets { metric: string; } +const observerDefaults = getObserverDefaults(); + +const esDocumentDefaults = { + ecs: { + version: '1.4', + }, +}; + +// eslint-disable-next-line guard-for-in +for (const key in observerDefaults) { + set(esDocumentDefaults, key, observerDefaults[key as keyof typeof observerDefaults]); +} export function toElasticsearchOutput({ events, writeTargets, @@ -30,22 +42,25 @@ export function toElasticsearchOutput({ writeTargets: ElasticsearchOutputWriteTargets; }): ElasticsearchOutput[] { return events.map((event) => { - const values = { - ...event, - ...getObserverDefaults(), + const values = {}; + + Object.assign(values, event, { '@timestamp': new Date(event['@timestamp']!).toISOString(), 'timestamp.us': event['@timestamp']! * 1000, - 'ecs.version': '1.4', 'service.node.name': event['service.node.name'] || event['container.id'] || event['host.name'], - }; + }); const document = {}; + + Object.assign(document, esDocumentDefaults); + // eslint-disable-next-line guard-for-in for (const key in values) { const val = values[key as keyof typeof values]; set(document, key, val); } + return { _index: writeTargets[event['processor.event'] as keyof ElasticsearchOutputWriteTargets], _source: document, diff --git a/packages/elastic-apm-synthtrace/src/lib/utils/generate_id.ts b/packages/elastic-apm-synthtrace/src/lib/utils/generate_id.ts index cc372a56209aa..c65c2843ddd3b 100644 --- a/packages/elastic-apm-synthtrace/src/lib/utils/generate_id.ts +++ b/packages/elastic-apm-synthtrace/src/lib/utils/generate_id.ts @@ -6,20 +6,17 @@ * Side Public License, v 1. */ -import uuidv5 from 'uuid/v5'; - let seq = 0; -const namespace = 'f38d5b83-8eee-4f5b-9aa6-2107e15a71e3'; - -function generateId(seed?: string) { - return uuidv5(seed ?? String(seq++), namespace).replace(/-/g, ''); +function generateId(seed?: string, length: number = 32) { + const str = seed ?? String(seq++); + return str.padStart(length, '0'); } export function generateShortId(seed?: string) { - return generateId(seed).substr(0, 16); + return generateId(seed, 16); } export function generateLongId(seed?: string) { - return generateId(seed).substr(0, 32); + return generateId(seed, 32); } diff --git a/packages/elastic-apm-synthtrace/src/scripts/examples/01_simple_trace.ts b/packages/elastic-apm-synthtrace/src/scripts/examples/01_simple_trace.ts index 6b857391b4f96..8c1f24bd5e64f 100644 --- a/packages/elastic-apm-synthtrace/src/scripts/examples/01_simple_trace.ts +++ b/packages/elastic-apm-synthtrace/src/scripts/examples/01_simple_trace.ts @@ -10,16 +10,20 @@ import { service, timerange, getTransactionMetrics, getSpanDestinationMetrics } import { getBreakdownMetrics } from '../../lib/utils/get_breakdown_metrics'; export default function ({ from, to }: { from: number; to: number }) { - const instance = service('opbeans-go', 'production', 'go').instance('instance'); + const numServices = 3; const range = timerange(from, to); const transactionName = '240rpm/75% 1000ms'; - const successfulTraceEvents = range - .interval('1s') - .rate(3) - .flatMap((timestamp) => + const successfulTimestamps = range.interval('1s').rate(3); + + const failedTimestamps = range.interval('1s').rate(1); + + return new Array(numServices).fill(undefined).flatMap((_, index) => { + const instance = service(`opbeans-go-${index}`, 'production', 'go').instance('instance'); + + const successfulTraceEvents = successfulTimestamps.flatMap((timestamp) => instance .transaction(transactionName) .timestamp(timestamp) @@ -37,10 +41,7 @@ export default function ({ from, to }: { from: number; to: number }) { .serialize() ); - const failedTraceEvents = range - .interval('1s') - .rate(1) - .flatMap((timestamp) => + const failedTraceEvents = failedTimestamps.flatMap((timestamp) => instance .transaction(transactionName) .timestamp(timestamp) @@ -52,27 +53,28 @@ export default function ({ from, to }: { from: number; to: number }) { .serialize() ); - const metricsets = range - .interval('30s') - .rate(1) - .flatMap((timestamp) => - instance - .appMetrics({ - 'system.memory.actual.free': 800, - 'system.memory.total': 1000, - 'system.cpu.total.norm.pct': 0.6, - 'system.process.cpu.total.norm.pct': 0.7, - }) - .timestamp(timestamp) - .serialize() - ); - const events = successfulTraceEvents.concat(failedTraceEvents); + const metricsets = range + .interval('30s') + .rate(1) + .flatMap((timestamp) => + instance + .appMetrics({ + 'system.memory.actual.free': 800, + 'system.memory.total': 1000, + 'system.cpu.total.norm.pct': 0.6, + 'system.process.cpu.total.norm.pct': 0.7, + }) + .timestamp(timestamp) + .serialize() + ); + const events = successfulTraceEvents.concat(failedTraceEvents); - return [ - ...events, - ...metricsets, - ...getTransactionMetrics(events), - ...getSpanDestinationMetrics(events), - ...getBreakdownMetrics(events), - ]; + return [ + ...events, + ...metricsets, + ...getTransactionMetrics(events), + ...getSpanDestinationMetrics(events), + ...getBreakdownMetrics(events), + ]; + }); } diff --git a/packages/elastic-apm-synthtrace/src/scripts/run.ts b/packages/elastic-apm-synthtrace/src/scripts/run.ts index ad453ac96ff10..367cdc2b91505 100644 --- a/packages/elastic-apm-synthtrace/src/scripts/run.ts +++ b/packages/elastic-apm-synthtrace/src/scripts/run.ts @@ -8,15 +8,6 @@ import datemath from '@elastic/datemath'; import yargs from 'yargs/yargs'; import { cleanWriteTargets } from './utils/clean_write_targets'; -import { - bucketSizeOption, - cleanOption, - fileOption, - intervalOption, - targetOption, - workerOption, - logLevelOption, -} from './utils/common_options'; import { intervalToMs } from './utils/interval_to_ms'; import { getCommonResources } from './utils/get_common_resources'; import { startHistoricalDataUpload } from './utils/start_historical_data_upload'; @@ -28,13 +19,16 @@ yargs(process.argv.slice(2)) 'Generate data and index into Elasticsearch', (y) => { return y - .positional('file', fileOption) - .option('bucketSize', bucketSizeOption) - .option('workers', workerOption) - .option('interval', intervalOption) - .option('clean', cleanOption) - .option('target', targetOption) - .option('logLevel', logLevelOption) + .positional('file', { + describe: 'File that contains the trace scenario', + demandOption: true, + string: true, + }) + .option('target', { + describe: 'Elasticsearch target, including username/password', + demandOption: true, + string: true, + }) .option('from', { description: 'The start of the time window', }) @@ -45,20 +39,47 @@ yargs(process.argv.slice(2)) description: 'Generate and index data continuously', boolean: true, }) + .option('clean', { + describe: 'Clean APM indices before indexing new data', + default: false, + boolean: true, + }) + .option('workers', { + describe: 'Amount of Node.js worker threads', + default: 5, + }) + .option('bucketSize', { + describe: 'Size of bucket for which to generate data', + default: '15m', + }) + .option('interval', { + describe: 'The interval at which to index data', + default: '10s', + }) + .option('clientWorkers', { + describe: 'Number of concurrently connected ES clients', + default: 5, + }) + .option('batchSize', { + describe: 'Number of documents per bulk index request', + default: 1000, + }) + .option('logLevel', { + describe: 'Log level', + default: 'info', + }) .conflicts('to', 'live'); }, async (argv) => { - const { - scenario, - intervalInMs, - bucketSizeInMs, - target, - workers, - clean, - logger, - writeTargets, - client, - } = await getCommonResources(argv); + const file = String(argv.file || argv._[0]); + + const { target, workers, clean, clientWorkers, batchSize } = argv; + + const { scenario, intervalInMs, bucketSizeInMs, logger, writeTargets, client, logLevel } = + await getCommonResources({ + ...argv, + file, + }); if (clean) { await cleanWriteTargets({ writeTargets, client, logger }); @@ -91,13 +112,16 @@ yargs(process.argv.slice(2)) startHistoricalDataUpload({ from, to, - scenario, - intervalInMs, + file, bucketSizeInMs, client, workers, + clientWorkers, + batchSize, writeTargets, logger, + logLevel, + target, }); if (live) { @@ -108,7 +132,8 @@ yargs(process.argv.slice(2)) logger, scenario, start: to, - workers, + clientWorkers, + batchSize, writeTargets, }); } diff --git a/packages/elastic-apm-synthtrace/src/scripts/utils/common_options.ts b/packages/elastic-apm-synthtrace/src/scripts/utils/common_options.ts deleted file mode 100644 index eba547114d533..0000000000000 --- a/packages/elastic-apm-synthtrace/src/scripts/utils/common_options.ts +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -const fileOption = { - describe: 'File that contains the trace scenario', - demandOption: true, -}; - -const intervalOption = { - describe: 'The interval at which to index data', - default: '10s', -}; - -const targetOption = { - describe: 'Elasticsearch target, including username/password', - demandOption: true, -}; - -const bucketSizeOption = { - describe: 'Size of bucket for which to generate data', - default: '15m', -}; - -const workerOption = { - describe: 'Amount of simultaneously connected ES clients', - default: 1, -}; - -const cleanOption = { - describe: 'Clean APM indices before indexing new data', - default: false, - boolean: true as const, -}; - -const logLevelOption = { - describe: 'Log level', - default: 'info', -}; - -export { - fileOption, - intervalOption, - targetOption, - bucketSizeOption, - workerOption, - cleanOption, - logLevelOption, -}; diff --git a/packages/elastic-apm-synthtrace/src/scripts/utils/get_common_resources.ts b/packages/elastic-apm-synthtrace/src/scripts/utils/get_common_resources.ts index 1288c1390e92c..3b51ac6c0c0a7 100644 --- a/packages/elastic-apm-synthtrace/src/scripts/utils/get_common_resources.ts +++ b/packages/elastic-apm-synthtrace/src/scripts/utils/get_common_resources.ts @@ -16,21 +16,21 @@ export async function getCommonResources({ file, interval, bucketSize, - workers, target, - clean, logLevel, }: { - file: unknown; - interval: unknown; - bucketSize: unknown; - workers: unknown; - target: unknown; - clean: boolean; - logLevel: unknown; + file: string; + interval: string; + bucketSize: string; + target: string; + logLevel: string; }) { let parsedLogLevel = LogLevel.info; switch (logLevel) { + case 'trace': + parsedLogLevel = LogLevel.trace; + break; + case 'info': parsedLogLevel = LogLevel.info; break; @@ -39,8 +39,8 @@ export async function getCommonResources({ parsedLogLevel = LogLevel.debug; break; - case 'quiet': - parsedLogLevel = LogLevel.quiet; + case 'error': + parsedLogLevel = LogLevel.error; break; } @@ -58,7 +58,7 @@ export async function getCommonResources({ } const client = new Client({ - node: String(target), + node: target, }); const [scenario, writeTargets] = await Promise.all([ @@ -73,8 +73,6 @@ export async function getCommonResources({ client, intervalInMs, bucketSizeInMs, - workers: Number(workers), - target: String(target), - clean, + logLevel: parsedLogLevel, }; } diff --git a/packages/elastic-apm-synthtrace/src/scripts/utils/get_write_targets.ts b/packages/elastic-apm-synthtrace/src/scripts/utils/get_write_targets.ts index 3640e4efaf796..7cbba4e735750 100644 --- a/packages/elastic-apm-synthtrace/src/scripts/utils/get_write_targets.ts +++ b/packages/elastic-apm-synthtrace/src/scripts/utils/get_write_targets.ts @@ -38,7 +38,8 @@ export async function getWriteTargets({ )?.[0], }; }) - .find(({ key }) => key.includes(filter))?.writeIndexAlias!; + .find(({ key, writeIndexAlias }) => writeIndexAlias && key.includes(filter)) + ?.writeIndexAlias!; } const targets = { diff --git a/packages/elastic-apm-synthtrace/src/scripts/utils/logger.ts b/packages/elastic-apm-synthtrace/src/scripts/utils/logger.ts index c9017cb08e663..4afdda74105cf 100644 --- a/packages/elastic-apm-synthtrace/src/scripts/utils/logger.ts +++ b/packages/elastic-apm-synthtrace/src/scripts/utils/logger.ts @@ -6,24 +6,59 @@ * Side Public License, v 1. */ +import { isPromise } from 'util/types'; + export enum LogLevel { - debug = 0, - info = 1, - quiet = 2, + trace = 0, + debug = 1, + info = 2, + error = 3, +} + +function getTimeString() { + return `[${new Date().toLocaleTimeString()}]`; } export function createLogger(logLevel: LogLevel) { + function logPerf(name: string, start: bigint) { + // eslint-disable-next-line no-console + console.debug( + getTimeString(), + `${name}: ${Number(process.hrtime.bigint() - start) / 1000000}ms` + ); + } return { + perf: (name: string, cb: () => T): T => { + if (logLevel <= LogLevel.trace) { + const start = process.hrtime.bigint(); + const val = cb(); + if (isPromise(val)) { + val.then(() => { + logPerf(name, start); + }); + } else { + logPerf(name, start); + } + return val; + } + return cb(); + }, debug: (...args: any[]) => { if (logLevel <= LogLevel.debug) { // eslint-disable-next-line no-console - console.debug(...args); + console.debug(getTimeString(), ...args); } }, info: (...args: any[]) => { if (logLevel <= LogLevel.info) { // eslint-disable-next-line no-console - console.log(...args); + console.log(getTimeString(), ...args); + } + }, + error: (...args: any[]) => { + if (logLevel <= LogLevel.error) { + // eslint-disable-next-line no-console + console.log(getTimeString(), ...args); } }, }; diff --git a/packages/elastic-apm-synthtrace/src/scripts/utils/start_historical_data_upload.ts b/packages/elastic-apm-synthtrace/src/scripts/utils/start_historical_data_upload.ts index db14090dd1d8f..e940896fb3687 100644 --- a/packages/elastic-apm-synthtrace/src/scripts/utils/start_historical_data_upload.ts +++ b/packages/elastic-apm-synthtrace/src/scripts/utils/start_historical_data_upload.ts @@ -5,60 +5,105 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ - import { Client } from '@elastic/elasticsearch'; +import pLimit from 'p-limit'; +import Path from 'path'; +import { Worker } from 'worker_threads'; import { ElasticsearchOutputWriteTargets } from '../../lib/output/to_elasticsearch_output'; -import { Scenario } from './get_scenario'; -import { Logger } from './logger'; -import { uploadEvents } from './upload_events'; +import { Logger, LogLevel } from './logger'; export async function startHistoricalDataUpload({ from, to, - scenario, - intervalInMs, bucketSizeInMs, - client, workers, + clientWorkers, + batchSize, writeTargets, + logLevel, logger, + target, + file, }: { from: number; to: number; - scenario: Scenario; - intervalInMs: number; bucketSizeInMs: number; client: Client; workers: number; + clientWorkers: number; + batchSize: number; writeTargets: ElasticsearchOutputWriteTargets; logger: Logger; + logLevel: LogLevel; + target: string; + file: string; }) { let requestedUntil: number = from; - function uploadNextBatch() { + + function processNextBatch() { const bucketFrom = requestedUntil; const bucketTo = Math.min(to, bucketFrom + bucketSizeInMs); - const events = scenario({ from: bucketFrom, to: bucketTo }); + if (bucketFrom === bucketTo) { + return; + } + + requestedUntil = bucketTo; logger.info( - `Uploading: ${new Date(bucketFrom).toISOString()} to ${new Date(bucketTo).toISOString()}` + `Starting worker for ${new Date(bucketFrom).toISOString()} to ${new Date( + bucketTo + ).toISOString()}` ); - uploadEvents({ - events, - client, - workers, - writeTargets, - logger, - }).then(() => { - if (bucketTo >= to) { - return; - } - uploadNextBatch(); + const worker = new Worker(Path.join(__dirname, './upload_next_batch.js'), { + workerData: { + bucketFrom, + bucketTo, + logLevel, + writeTargets, + target, + file, + clientWorkers, + batchSize, + }, }); - requestedUntil = bucketTo; + logger.perf('created_worker', () => { + return new Promise((resolve, reject) => { + worker.on('online', () => { + resolve(); + }); + }); + }); + + logger.perf('completed_worker', () => { + return new Promise((resolve, reject) => { + worker.on('exit', () => { + resolve(); + }); + }); + }); + + return new Promise((resolve, reject) => { + worker.on('error', (err) => { + reject(err); + }); + + worker.on('exit', (code) => { + if (code !== 0) { + reject(new Error(`Worker stopped: exit code ${code}`)); + return; + } + logger.debug('Worker completed'); + resolve(); + }); + }); } - return uploadNextBatch(); + const numBatches = Math.ceil((to - from) / bucketSizeInMs); + + const limiter = pLimit(workers); + + return Promise.all(new Array(numBatches).fill(undefined).map((_) => limiter(processNextBatch))); } diff --git a/packages/elastic-apm-synthtrace/src/scripts/utils/start_live_data_upload.ts b/packages/elastic-apm-synthtrace/src/scripts/utils/start_live_data_upload.ts index bf330732f343e..0032df1d700e9 100644 --- a/packages/elastic-apm-synthtrace/src/scripts/utils/start_live_data_upload.ts +++ b/packages/elastic-apm-synthtrace/src/scripts/utils/start_live_data_upload.ts @@ -18,7 +18,8 @@ export function startLiveDataUpload({ start, bucketSizeInMs, intervalInMs, - workers, + clientWorkers, + batchSize, writeTargets, scenario, client, @@ -27,7 +28,8 @@ export function startLiveDataUpload({ start: number; bucketSizeInMs: number; intervalInMs: number; - workers: number; + clientWorkers: number; + batchSize: number; writeTargets: ElasticsearchOutputWriteTargets; scenario: Scenario; client: Client; @@ -63,7 +65,8 @@ export function startLiveDataUpload({ uploadEvents({ events: eventsToUpload, client, - workers, + clientWorkers, + batchSize, writeTargets, logger, }); diff --git a/packages/elastic-apm-synthtrace/src/scripts/utils/upload_events.ts b/packages/elastic-apm-synthtrace/src/scripts/utils/upload_events.ts index 89cf4d4602177..ada9f73b09e39 100644 --- a/packages/elastic-apm-synthtrace/src/scripts/utils/upload_events.ts +++ b/packages/elastic-apm-synthtrace/src/scripts/utils/upload_events.ts @@ -19,20 +19,24 @@ import { Logger } from './logger'; export function uploadEvents({ events, client, - workers, + clientWorkers, + batchSize, writeTargets, logger, }: { events: Fields[]; client: Client; - workers: number; + clientWorkers: number; + batchSize: number; writeTargets: ElasticsearchOutputWriteTargets; logger: Logger; }) { - const esDocuments = toElasticsearchOutput({ events, writeTargets }); - const fn = pLimit(workers); + const esDocuments = logger.perf('to_elasticsearch_output', () => { + return toElasticsearchOutput({ events, writeTargets }); + }); + const fn = pLimit(clientWorkers); - const batches = chunk(esDocuments, 5000); + const batches = chunk(esDocuments, batchSize); logger.debug(`Uploading ${esDocuments.length} in ${batches.length} batches`); @@ -41,12 +45,15 @@ export function uploadEvents({ return Promise.all( batches.map((batch) => fn(() => { - return client.bulk({ - require_alias: true, - body: batch.flatMap((doc) => { - return [{ index: { _index: doc._index } }, doc._source]; - }), - }); + return logger.perf('bulk_upload', () => + client.bulk({ + require_alias: true, + refresh: false, + body: batch.flatMap((doc) => { + return [{ index: { _index: doc._index } }, doc._source]; + }), + }) + ); }) ) ) @@ -57,8 +64,7 @@ export function uploadEvents({ .map((item) => item.index?.error); if (errors.length) { - // eslint-disable-next-line no-console - console.error(inspect(errors.slice(0, 10), { depth: null })); + logger.error(inspect(errors.slice(0, 10), { depth: null })); throw new Error('Failed to upload some items'); } diff --git a/packages/elastic-apm-synthtrace/src/scripts/utils/upload_next_batch.js b/packages/elastic-apm-synthtrace/src/scripts/utils/upload_next_batch.js new file mode 100644 index 0000000000000..86c7b67c24ff7 --- /dev/null +++ b/packages/elastic-apm-synthtrace/src/scripts/utils/upload_next_batch.js @@ -0,0 +1,15 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +/* eslint-disable @typescript-eslint/no-var-requires*/ +require('@babel/register')({ + extensions: ['.ts', '.js'], + presets: [['@babel/preset-env', { targets: { node: 'current' } }], '@babel/preset-typescript'], +}); + +require('./upload_next_batch.ts'); diff --git a/packages/elastic-apm-synthtrace/src/scripts/utils/upload_next_batch.ts b/packages/elastic-apm-synthtrace/src/scripts/utils/upload_next_batch.ts new file mode 100644 index 0000000000000..1e0280382e4db --- /dev/null +++ b/packages/elastic-apm-synthtrace/src/scripts/utils/upload_next_batch.ts @@ -0,0 +1,61 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +// add this to workerExample.js file. +import { Client } from '@elastic/elasticsearch'; +import { workerData } from 'worker_threads'; +import { ElasticsearchOutputWriteTargets } from '../../lib/output/to_elasticsearch_output'; +import { getScenario } from './get_scenario'; +import { createLogger, LogLevel } from './logger'; +import { uploadEvents } from './upload_events'; + +const { bucketFrom, bucketTo, file, logLevel, target, writeTargets, clientWorkers, batchSize } = + workerData as { + bucketFrom: number; + bucketTo: number; + file: string; + logLevel: LogLevel; + target: string; + writeTargets: ElasticsearchOutputWriteTargets; + clientWorkers: number; + batchSize: number; + }; + +async function uploadNextBatch() { + if (bucketFrom === bucketTo) { + return; + } + + const logger = createLogger(logLevel); + const client = new Client({ + node: target, + }); + + const scenario = await logger.perf('get_scenario', () => getScenario({ file, logger })); + + const events = logger.perf('execute_scenario', () => + scenario({ from: bucketFrom, to: bucketTo }) + ); + + return uploadEvents({ + events, + client, + clientWorkers, + batchSize, + writeTargets, + logger, + }); +} + +uploadNextBatch() + .then(() => { + process.exit(0); + }) + .catch(() => { + process.exit(1); + }); diff --git a/packages/elastic-apm-synthtrace/src/test/scenarios/01_simple_trace.test.ts b/packages/elastic-apm-synthtrace/src/test/scenarios/01_simple_trace.test.ts index 866a9745befc3..fc20202e210ff 100644 --- a/packages/elastic-apm-synthtrace/src/test/scenarios/01_simple_trace.test.ts +++ b/packages/elastic-apm-synthtrace/src/test/scenarios/01_simple_trace.test.ts @@ -75,9 +75,9 @@ describe('simple trace', () => { 'service.environment': 'production', 'service.name': 'opbeans-java', 'service.node.name': 'instance-1', - 'trace.id': 'f6eb2f1cbba2597e89d2a63771c4344d', + 'trace.id': '00000000000000000000000000000241', 'transaction.duration.us': 1000000, - 'transaction.id': 'e9ece67cbacb52bf', + 'transaction.id': '0000000000000240', 'transaction.name': 'GET /api/product/list', 'transaction.type': 'request', 'transaction.sampled': true, @@ -92,19 +92,19 @@ describe('simple trace', () => { 'agent.name': 'java', 'container.id': 'instance-1', 'event.outcome': 'success', - 'parent.id': 'e7433020f2745625', + 'parent.id': '0000000000000300', 'processor.event': 'span', 'processor.name': 'transaction', 'service.environment': 'production', 'service.name': 'opbeans-java', 'service.node.name': 'instance-1', 'span.duration.us': 900000, - 'span.id': '21a776b44b9853dd', + 'span.id': '0000000000000302', 'span.name': 'GET apm-*/_search', 'span.subtype': 'elasticsearch', 'span.type': 'db', - 'trace.id': '048a0647263853abb94649ec0b92bdb4', - 'transaction.id': 'e7433020f2745625', + 'trace.id': '00000000000000000000000000000301', + 'transaction.id': '0000000000000300', }); }); }); diff --git a/packages/elastic-apm-synthtrace/src/test/scenarios/05_transactions_with_errors.test.ts b/packages/elastic-apm-synthtrace/src/test/scenarios/05_transactions_with_errors.test.ts index 289fdfa6cf565..63fdb691e8e5c 100644 --- a/packages/elastic-apm-synthtrace/src/test/scenarios/05_transactions_with_errors.test.ts +++ b/packages/elastic-apm-synthtrace/src/test/scenarios/05_transactions_with_errors.test.ts @@ -61,6 +61,6 @@ describe('transactions with errors', () => { .serialize(); expect(error['error.grouping_name']).toEqual('test error'); - expect(error['error.grouping_key']).toMatchInlineSnapshot(`"8b96fa10a7f85a5d960198627bf50840"`); + expect(error['error.grouping_key']).toMatchInlineSnapshot(`"0000000000000000000000test error"`); }); }); diff --git a/packages/elastic-apm-synthtrace/src/test/scenarios/__snapshots__/01_simple_trace.test.ts.snap b/packages/elastic-apm-synthtrace/src/test/scenarios/__snapshots__/01_simple_trace.test.ts.snap index 00a55cb87b125..76a76d41ec81d 100644 --- a/packages/elastic-apm-synthtrace/src/test/scenarios/__snapshots__/01_simple_trace.test.ts.snap +++ b/packages/elastic-apm-synthtrace/src/test/scenarios/__snapshots__/01_simple_trace.test.ts.snap @@ -12,9 +12,9 @@ Array [ "service.environment": "production", "service.name": "opbeans-java", "service.node.name": "instance-1", - "trace.id": "b1c6c04a9ac15b138f716d383cc85e6b", + "trace.id": "00000000000000000000000000000001", "transaction.duration.us": 1000000, - "transaction.id": "36c16f18e75058f8", + "transaction.id": "0000000000000000", "transaction.name": "GET /api/product/list", "transaction.sampled": true, "transaction.type": "request", @@ -24,19 +24,19 @@ Array [ "agent.name": "java", "container.id": "instance-1", "event.outcome": "success", - "parent.id": "36c16f18e75058f8", + "parent.id": "0000000000000000", "processor.event": "span", "processor.name": "transaction", "service.environment": "production", "service.name": "opbeans-java", "service.node.name": "instance-1", "span.duration.us": 900000, - "span.id": "fe778a305e6d57dd", + "span.id": "0000000000000002", "span.name": "GET apm-*/_search", "span.subtype": "elasticsearch", "span.type": "db", - "trace.id": "b1c6c04a9ac15b138f716d383cc85e6b", - "transaction.id": "36c16f18e75058f8", + "trace.id": "00000000000000000000000000000001", + "transaction.id": "0000000000000000", }, Object { "@timestamp": 1609459260000, @@ -48,9 +48,9 @@ Array [ "service.environment": "production", "service.name": "opbeans-java", "service.node.name": "instance-1", - "trace.id": "53c6c37bd4c85f4fbc880cd80704a9cd", + "trace.id": "00000000000000000000000000000005", "transaction.duration.us": 1000000, - "transaction.id": "65ce74106eb050be", + "transaction.id": "0000000000000004", "transaction.name": "GET /api/product/list", "transaction.sampled": true, "transaction.type": "request", @@ -60,19 +60,19 @@ Array [ "agent.name": "java", "container.id": "instance-1", "event.outcome": "success", - "parent.id": "65ce74106eb050be", + "parent.id": "0000000000000004", "processor.event": "span", "processor.name": "transaction", "service.environment": "production", "service.name": "opbeans-java", "service.node.name": "instance-1", "span.duration.us": 900000, - "span.id": "ad8c5e249a8658ec", + "span.id": "0000000000000006", "span.name": "GET apm-*/_search", "span.subtype": "elasticsearch", "span.type": "db", - "trace.id": "53c6c37bd4c85f4fbc880cd80704a9cd", - "transaction.id": "65ce74106eb050be", + "trace.id": "00000000000000000000000000000005", + "transaction.id": "0000000000000004", }, Object { "@timestamp": 1609459320000, @@ -84,9 +84,9 @@ Array [ "service.environment": "production", "service.name": "opbeans-java", "service.node.name": "instance-1", - "trace.id": "5eebf2e8d8cc5f85be8c573a1b501c7d", + "trace.id": "00000000000000000000000000000009", "transaction.duration.us": 1000000, - "transaction.id": "91fa709d90625fff", + "transaction.id": "0000000000000008", "transaction.name": "GET /api/product/list", "transaction.sampled": true, "transaction.type": "request", @@ -96,19 +96,19 @@ Array [ "agent.name": "java", "container.id": "instance-1", "event.outcome": "success", - "parent.id": "91fa709d90625fff", + "parent.id": "0000000000000008", "processor.event": "span", "processor.name": "transaction", "service.environment": "production", "service.name": "opbeans-java", "service.node.name": "instance-1", "span.duration.us": 900000, - "span.id": "228b569c530c52ac", + "span.id": "0000000000000010", "span.name": "GET apm-*/_search", "span.subtype": "elasticsearch", "span.type": "db", - "trace.id": "5eebf2e8d8cc5f85be8c573a1b501c7d", - "transaction.id": "91fa709d90625fff", + "trace.id": "00000000000000000000000000000009", + "transaction.id": "0000000000000008", }, Object { "@timestamp": 1609459380000, @@ -120,9 +120,9 @@ Array [ "service.environment": "production", "service.name": "opbeans-java", "service.node.name": "instance-1", - "trace.id": "6e8da4beb752589a86d53287c9d902de", + "trace.id": "00000000000000000000000000000013", "transaction.duration.us": 1000000, - "transaction.id": "6c500d1d19835e68", + "transaction.id": "0000000000000012", "transaction.name": "GET /api/product/list", "transaction.sampled": true, "transaction.type": "request", @@ -132,19 +132,19 @@ Array [ "agent.name": "java", "container.id": "instance-1", "event.outcome": "success", - "parent.id": "6c500d1d19835e68", + "parent.id": "0000000000000012", "processor.event": "span", "processor.name": "transaction", "service.environment": "production", "service.name": "opbeans-java", "service.node.name": "instance-1", "span.duration.us": 900000, - "span.id": "5eb13f140bde5334", + "span.id": "0000000000000014", "span.name": "GET apm-*/_search", "span.subtype": "elasticsearch", "span.type": "db", - "trace.id": "6e8da4beb752589a86d53287c9d902de", - "transaction.id": "6c500d1d19835e68", + "trace.id": "00000000000000000000000000000013", + "transaction.id": "0000000000000012", }, Object { "@timestamp": 1609459440000, @@ -156,9 +156,9 @@ Array [ "service.environment": "production", "service.name": "opbeans-java", "service.node.name": "instance-1", - "trace.id": "0aaa92bd91df543c8fd10b662051d9e8", + "trace.id": "00000000000000000000000000000017", "transaction.duration.us": 1000000, - "transaction.id": "1b3246cc83595869", + "transaction.id": "0000000000000016", "transaction.name": "GET /api/product/list", "transaction.sampled": true, "transaction.type": "request", @@ -168,19 +168,19 @@ Array [ "agent.name": "java", "container.id": "instance-1", "event.outcome": "success", - "parent.id": "1b3246cc83595869", + "parent.id": "0000000000000016", "processor.event": "span", "processor.name": "transaction", "service.environment": "production", "service.name": "opbeans-java", "service.node.name": "instance-1", "span.duration.us": 900000, - "span.id": "582221c79fd75a76", + "span.id": "0000000000000018", "span.name": "GET apm-*/_search", "span.subtype": "elasticsearch", "span.type": "db", - "trace.id": "0aaa92bd91df543c8fd10b662051d9e8", - "transaction.id": "1b3246cc83595869", + "trace.id": "00000000000000000000000000000017", + "transaction.id": "0000000000000016", }, Object { "@timestamp": 1609459500000, @@ -192,9 +192,9 @@ Array [ "service.environment": "production", "service.name": "opbeans-java", "service.node.name": "instance-1", - "trace.id": "26be5f0e2c16576ebf5f39c505eb1ff2", + "trace.id": "00000000000000000000000000000021", "transaction.duration.us": 1000000, - "transaction.id": "12b49e3c83fe58d5", + "transaction.id": "0000000000000020", "transaction.name": "GET /api/product/list", "transaction.sampled": true, "transaction.type": "request", @@ -204,19 +204,19 @@ Array [ "agent.name": "java", "container.id": "instance-1", "event.outcome": "success", - "parent.id": "12b49e3c83fe58d5", + "parent.id": "0000000000000020", "processor.event": "span", "processor.name": "transaction", "service.environment": "production", "service.name": "opbeans-java", "service.node.name": "instance-1", "span.duration.us": 900000, - "span.id": "526d186996835c09", + "span.id": "0000000000000022", "span.name": "GET apm-*/_search", "span.subtype": "elasticsearch", "span.type": "db", - "trace.id": "26be5f0e2c16576ebf5f39c505eb1ff2", - "transaction.id": "12b49e3c83fe58d5", + "trace.id": "00000000000000000000000000000021", + "transaction.id": "0000000000000020", }, Object { "@timestamp": 1609459560000, @@ -228,9 +228,9 @@ Array [ "service.environment": "production", "service.name": "opbeans-java", "service.node.name": "instance-1", - "trace.id": "c17c414c0b51564ca30e2ad839393180", + "trace.id": "00000000000000000000000000000025", "transaction.duration.us": 1000000, - "transaction.id": "d9272009dd4354a1", + "transaction.id": "0000000000000024", "transaction.name": "GET /api/product/list", "transaction.sampled": true, "transaction.type": "request", @@ -240,19 +240,19 @@ Array [ "agent.name": "java", "container.id": "instance-1", "event.outcome": "success", - "parent.id": "d9272009dd4354a1", + "parent.id": "0000000000000024", "processor.event": "span", "processor.name": "transaction", "service.environment": "production", "service.name": "opbeans-java", "service.node.name": "instance-1", "span.duration.us": 900000, - "span.id": "7582541fcbfc5dc6", + "span.id": "0000000000000026", "span.name": "GET apm-*/_search", "span.subtype": "elasticsearch", "span.type": "db", - "trace.id": "c17c414c0b51564ca30e2ad839393180", - "transaction.id": "d9272009dd4354a1", + "trace.id": "00000000000000000000000000000025", + "transaction.id": "0000000000000024", }, Object { "@timestamp": 1609459620000, @@ -264,9 +264,9 @@ Array [ "service.environment": "production", "service.name": "opbeans-java", "service.node.name": "instance-1", - "trace.id": "0280b1ffaae75e7ab097c0b52c3b3e6a", + "trace.id": "00000000000000000000000000000029", "transaction.duration.us": 1000000, - "transaction.id": "bc52ca08063c505b", + "transaction.id": "0000000000000028", "transaction.name": "GET /api/product/list", "transaction.sampled": true, "transaction.type": "request", @@ -276,19 +276,19 @@ Array [ "agent.name": "java", "container.id": "instance-1", "event.outcome": "success", - "parent.id": "bc52ca08063c505b", + "parent.id": "0000000000000028", "processor.event": "span", "processor.name": "transaction", "service.environment": "production", "service.name": "opbeans-java", "service.node.name": "instance-1", "span.duration.us": 900000, - "span.id": "37ab978487935abb", + "span.id": "0000000000000030", "span.name": "GET apm-*/_search", "span.subtype": "elasticsearch", "span.type": "db", - "trace.id": "0280b1ffaae75e7ab097c0b52c3b3e6a", - "transaction.id": "bc52ca08063c505b", + "trace.id": "00000000000000000000000000000029", + "transaction.id": "0000000000000028", }, Object { "@timestamp": 1609459680000, @@ -300,9 +300,9 @@ Array [ "service.environment": "production", "service.name": "opbeans-java", "service.node.name": "instance-1", - "trace.id": "6fb5191297fb59cebdb6a0196e273676", + "trace.id": "00000000000000000000000000000033", "transaction.duration.us": 1000000, - "transaction.id": "186858dd88b75d59", + "transaction.id": "0000000000000032", "transaction.name": "GET /api/product/list", "transaction.sampled": true, "transaction.type": "request", @@ -312,19 +312,19 @@ Array [ "agent.name": "java", "container.id": "instance-1", "event.outcome": "success", - "parent.id": "186858dd88b75d59", + "parent.id": "0000000000000032", "processor.event": "span", "processor.name": "transaction", "service.environment": "production", "service.name": "opbeans-java", "service.node.name": "instance-1", "span.duration.us": 900000, - "span.id": "5ab56f27d0ae569b", + "span.id": "0000000000000034", "span.name": "GET apm-*/_search", "span.subtype": "elasticsearch", "span.type": "db", - "trace.id": "6fb5191297fb59cebdb6a0196e273676", - "transaction.id": "186858dd88b75d59", + "trace.id": "00000000000000000000000000000033", + "transaction.id": "0000000000000032", }, Object { "@timestamp": 1609459740000, @@ -336,9 +336,9 @@ Array [ "service.environment": "production", "service.name": "opbeans-java", "service.node.name": "instance-1", - "trace.id": "77b5ffe303ae59b49f9b0e5d5270c16a", + "trace.id": "00000000000000000000000000000037", "transaction.duration.us": 1000000, - "transaction.id": "0d5f44d48189546c", + "transaction.id": "0000000000000036", "transaction.name": "GET /api/product/list", "transaction.sampled": true, "transaction.type": "request", @@ -348,19 +348,19 @@ Array [ "agent.name": "java", "container.id": "instance-1", "event.outcome": "success", - "parent.id": "0d5f44d48189546c", + "parent.id": "0000000000000036", "processor.event": "span", "processor.name": "transaction", "service.environment": "production", "service.name": "opbeans-java", "service.node.name": "instance-1", "span.duration.us": 900000, - "span.id": "80e94b0847cd5104", + "span.id": "0000000000000038", "span.name": "GET apm-*/_search", "span.subtype": "elasticsearch", "span.type": "db", - "trace.id": "77b5ffe303ae59b49f9b0e5d5270c16a", - "transaction.id": "0d5f44d48189546c", + "trace.id": "00000000000000000000000000000037", + "transaction.id": "0000000000000036", }, Object { "@timestamp": 1609459800000, @@ -372,9 +372,9 @@ Array [ "service.environment": "production", "service.name": "opbeans-java", "service.node.name": "instance-1", - "trace.id": "51c6b70db4dc5cf89b690de45c0c7b71", + "trace.id": "00000000000000000000000000000041", "transaction.duration.us": 1000000, - "transaction.id": "7483e0606e435c83", + "transaction.id": "0000000000000040", "transaction.name": "GET /api/product/list", "transaction.sampled": true, "transaction.type": "request", @@ -384,19 +384,19 @@ Array [ "agent.name": "java", "container.id": "instance-1", "event.outcome": "success", - "parent.id": "7483e0606e435c83", + "parent.id": "0000000000000040", "processor.event": "span", "processor.name": "transaction", "service.environment": "production", "service.name": "opbeans-java", "service.node.name": "instance-1", "span.duration.us": 900000, - "span.id": "2e99d193e0f954c1", + "span.id": "0000000000000042", "span.name": "GET apm-*/_search", "span.subtype": "elasticsearch", "span.type": "db", - "trace.id": "51c6b70db4dc5cf89b690de45c0c7b71", - "transaction.id": "7483e0606e435c83", + "trace.id": "00000000000000000000000000000041", + "transaction.id": "0000000000000040", }, Object { "@timestamp": 1609459860000, @@ -408,9 +408,9 @@ Array [ "service.environment": "production", "service.name": "opbeans-java", "service.node.name": "instance-1", - "trace.id": "5d91a6cde6015897935e413bc500f211", + "trace.id": "00000000000000000000000000000045", "transaction.duration.us": 1000000, - "transaction.id": "f142c4cbc7f3568e", + "transaction.id": "0000000000000044", "transaction.name": "GET /api/product/list", "transaction.sampled": true, "transaction.type": "request", @@ -420,19 +420,19 @@ Array [ "agent.name": "java", "container.id": "instance-1", "event.outcome": "success", - "parent.id": "f142c4cbc7f3568e", + "parent.id": "0000000000000044", "processor.event": "span", "processor.name": "transaction", "service.environment": "production", "service.name": "opbeans-java", "service.node.name": "instance-1", "span.duration.us": 900000, - "span.id": "1fc52f16e2f551ea", + "span.id": "0000000000000046", "span.name": "GET apm-*/_search", "span.subtype": "elasticsearch", "span.type": "db", - "trace.id": "5d91a6cde6015897935e413bc500f211", - "transaction.id": "f142c4cbc7f3568e", + "trace.id": "00000000000000000000000000000045", + "transaction.id": "0000000000000044", }, Object { "@timestamp": 1609459920000, @@ -444,9 +444,9 @@ Array [ "service.environment": "production", "service.name": "opbeans-java", "service.node.name": "instance-1", - "trace.id": "c097c19d884d52579bb11a601b8a98b3", + "trace.id": "00000000000000000000000000000049", "transaction.duration.us": 1000000, - "transaction.id": "2e3a47fa2d905519", + "transaction.id": "0000000000000048", "transaction.name": "GET /api/product/list", "transaction.sampled": true, "transaction.type": "request", @@ -456,19 +456,19 @@ Array [ "agent.name": "java", "container.id": "instance-1", "event.outcome": "success", - "parent.id": "2e3a47fa2d905519", + "parent.id": "0000000000000048", "processor.event": "span", "processor.name": "transaction", "service.environment": "production", "service.name": "opbeans-java", "service.node.name": "instance-1", "span.duration.us": 900000, - "span.id": "7c7828c850685337", + "span.id": "0000000000000050", "span.name": "GET apm-*/_search", "span.subtype": "elasticsearch", "span.type": "db", - "trace.id": "c097c19d884d52579bb11a601b8a98b3", - "transaction.id": "2e3a47fa2d905519", + "trace.id": "00000000000000000000000000000049", + "transaction.id": "0000000000000048", }, Object { "@timestamp": 1609459980000, @@ -480,9 +480,9 @@ Array [ "service.environment": "production", "service.name": "opbeans-java", "service.node.name": "instance-1", - "trace.id": "4591e57f4d7f5986bdd7892561224e0f", + "trace.id": "00000000000000000000000000000053", "transaction.duration.us": 1000000, - "transaction.id": "de5eaa1e47dc56b1", + "transaction.id": "0000000000000052", "transaction.name": "GET /api/product/list", "transaction.sampled": true, "transaction.type": "request", @@ -492,19 +492,19 @@ Array [ "agent.name": "java", "container.id": "instance-1", "event.outcome": "success", - "parent.id": "de5eaa1e47dc56b1", + "parent.id": "0000000000000052", "processor.event": "span", "processor.name": "transaction", "service.environment": "production", "service.name": "opbeans-java", "service.node.name": "instance-1", "span.duration.us": 900000, - "span.id": "8f62257f4a41546a", + "span.id": "0000000000000054", "span.name": "GET apm-*/_search", "span.subtype": "elasticsearch", "span.type": "db", - "trace.id": "4591e57f4d7f5986bdd7892561224e0f", - "transaction.id": "de5eaa1e47dc56b1", + "trace.id": "00000000000000000000000000000053", + "transaction.id": "0000000000000052", }, Object { "@timestamp": 1609460040000, @@ -516,9 +516,9 @@ Array [ "service.environment": "production", "service.name": "opbeans-java", "service.node.name": "instance-1", - "trace.id": "85ee8e618433577b9316a1e14961aa89", + "trace.id": "00000000000000000000000000000057", "transaction.duration.us": 1000000, - "transaction.id": "af7eac7ae61e576a", + "transaction.id": "0000000000000056", "transaction.name": "GET /api/product/list", "transaction.sampled": true, "transaction.type": "request", @@ -528,19 +528,19 @@ Array [ "agent.name": "java", "container.id": "instance-1", "event.outcome": "success", - "parent.id": "af7eac7ae61e576a", + "parent.id": "0000000000000056", "processor.event": "span", "processor.name": "transaction", "service.environment": "production", "service.name": "opbeans-java", "service.node.name": "instance-1", "span.duration.us": 900000, - "span.id": "cc88b4cd921e590e", + "span.id": "0000000000000058", "span.name": "GET apm-*/_search", "span.subtype": "elasticsearch", "span.type": "db", - "trace.id": "85ee8e618433577b9316a1e14961aa89", - "transaction.id": "af7eac7ae61e576a", + "trace.id": "00000000000000000000000000000057", + "transaction.id": "0000000000000056", }, ] `; diff --git a/packages/elastic-apm-synthtrace/src/test/to_elasticsearch_output.test.ts b/packages/elastic-apm-synthtrace/src/test/to_elasticsearch_output.test.ts index d15ea89083112..02d17f6b561ae 100644 --- a/packages/elastic-apm-synthtrace/src/test/to_elasticsearch_output.test.ts +++ b/packages/elastic-apm-synthtrace/src/test/to_elasticsearch_output.test.ts @@ -24,6 +24,7 @@ describe('output to elasticsearch', () => { '@timestamp': new Date('2020-12-31T23:00:00.000Z').getTime(), 'processor.event': 'transaction', 'processor.name': 'transaction', + 'service.node.name': 'instance-a', }; }); @@ -41,4 +42,33 @@ describe('output to elasticsearch', () => { name: 'transaction', }); }); + + it('formats all fields consistently', () => { + const doc = toElasticsearchOutput({ events: [event], writeTargets })[0] as any; + + expect(doc._source).toMatchInlineSnapshot(` + Object { + "@timestamp": "2020-12-31T23:00:00.000Z", + "ecs": Object { + "version": "1.4", + }, + "observer": Object { + "version": "7.16.0", + "version_major": 7, + }, + "processor": Object { + "event": "transaction", + "name": "transaction", + }, + "service": Object { + "node": Object { + "name": "instance-a", + }, + }, + "timestamp": Object { + "us": 1609455600000000, + }, + } + `); + }); }); From 0296f632fb87fe6e35de4dd4ed30b4977f36a164 Mon Sep 17 00:00:00 2001 From: Shahzad Date: Tue, 26 Oct 2021 13:03:51 +0200 Subject: [PATCH 22/58] [Uptime] Added permission for new tls alert (#116107) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/plugins/uptime/server/kibana.index.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/x-pack/plugins/uptime/server/kibana.index.ts b/x-pack/plugins/uptime/server/kibana.index.ts index 3b1001daf0515..589b09e5a13d7 100644 --- a/x-pack/plugins/uptime/server/kibana.index.ts +++ b/x-pack/plugins/uptime/server/kibana.index.ts @@ -48,6 +48,7 @@ export const initServerWithKibana = ( }, alerting: [ 'xpack.uptime.alerts.tls', + 'xpack.uptime.alerts.tlsCertificate', 'xpack.uptime.alerts.monitorStatus', 'xpack.uptime.alerts.durationAnomaly', ], @@ -64,6 +65,7 @@ export const initServerWithKibana = ( rule: { all: [ 'xpack.uptime.alerts.tls', + 'xpack.uptime.alerts.tlsCertificate', 'xpack.uptime.alerts.monitorStatus', 'xpack.uptime.alerts.durationAnomaly', ], @@ -71,6 +73,7 @@ export const initServerWithKibana = ( alert: { all: [ 'xpack.uptime.alerts.tls', + 'xpack.uptime.alerts.tlsCertificate', 'xpack.uptime.alerts.monitorStatus', 'xpack.uptime.alerts.durationAnomaly', ], @@ -93,6 +96,7 @@ export const initServerWithKibana = ( rule: { read: [ 'xpack.uptime.alerts.tls', + 'xpack.uptime.alerts.tlsCertificate', 'xpack.uptime.alerts.monitorStatus', 'xpack.uptime.alerts.durationAnomaly', ], @@ -100,6 +104,7 @@ export const initServerWithKibana = ( alert: { read: [ 'xpack.uptime.alerts.tls', + 'xpack.uptime.alerts.tlsCertificate', 'xpack.uptime.alerts.monitorStatus', 'xpack.uptime.alerts.durationAnomaly', ], From c50511fb3c4eff22b323c5990a7cddfc5d96d544 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Tue, 26 Oct 2021 12:25:40 +0100 Subject: [PATCH 23/58] [Upgrade Assistant] Disable UI by default in 8.0 (#115782) --- x-pack/plugins/upgrade_assistant/server/config.ts | 2 +- x-pack/test/accessibility/apps/upgrade_assistant.ts | 10 +--------- .../apis/upgrade_assistant/upgrade_assistant.ts | 2 +- .../feature_controls/license_management_security.ts | 2 +- .../feature_controls/upgrade_assistant_security.ts | 2 +- .../apps/upgrade_assistant/upgrade_assistant.ts | 10 +--------- 6 files changed, 6 insertions(+), 22 deletions(-) diff --git a/x-pack/plugins/upgrade_assistant/server/config.ts b/x-pack/plugins/upgrade_assistant/server/config.ts index 99e5d486e30c3..cc073a597d046 100644 --- a/x-pack/plugins/upgrade_assistant/server/config.ts +++ b/x-pack/plugins/upgrade_assistant/server/config.ts @@ -19,7 +19,7 @@ const kibanaVersion = new SemVer(MAJOR_VERSION); // ------------------------------- const schemaLatest = schema.object({ ui: schema.object({ - enabled: schema.boolean({ defaultValue: true }), + enabled: schema.boolean({ defaultValue: false }), }), /* * This will default to true up until the last minor before the next major. diff --git a/x-pack/test/accessibility/apps/upgrade_assistant.ts b/x-pack/test/accessibility/apps/upgrade_assistant.ts index 0ea2fd8ce4b4e..1674948fef32e 100644 --- a/x-pack/test/accessibility/apps/upgrade_assistant.ts +++ b/x-pack/test/accessibility/apps/upgrade_assistant.ts @@ -13,21 +13,13 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const testSubjects = getService('testSubjects'); const retry = getService('retry'); - // Failing: See https://github.com/elastic/kibana/issues/115859 describe.skip('Upgrade Assistant', () => { before(async () => { await PageObjects.upgradeAssistant.navigateToPage(); }); - it('Coming soon prompt', async () => { - await retry.waitFor('Upgrade Assistant coming soon prompt to be visible', async () => { - return testSubjects.exists('comingSoonPrompt'); - }); - await a11y.testAppSnapshot(); - }); - // These tests will be skipped until the last minor of the next major release - describe.skip('Upgrade Assistant content', () => { + describe('Upgrade Assistant content', () => { it('Overview page', async () => { await retry.waitFor('Upgrade Assistant overview page to be visible', async () => { return testSubjects.exists('overviewPageContent'); diff --git a/x-pack/test/api_integration/apis/upgrade_assistant/upgrade_assistant.ts b/x-pack/test/api_integration/apis/upgrade_assistant/upgrade_assistant.ts index 7dd7a1584d0ef..c0a6760d4cf53 100644 --- a/x-pack/test/api_integration/apis/upgrade_assistant/upgrade_assistant.ts +++ b/x-pack/test/api_integration/apis/upgrade_assistant/upgrade_assistant.ts @@ -14,7 +14,7 @@ export default function ({ getService }: FtrProviderContext) { const es = getService('es'); const supertest = getService('supertest'); - describe('Upgrade Assistant', () => { + describe.skip('Upgrade Assistant', () => { describe('Reindex operation saved object', () => { const dotKibanaIndex = '.kibana'; const fakeSavedObjectId = 'fakeSavedObjectId'; diff --git a/x-pack/test/functional/apps/license_management/feature_controls/license_management_security.ts b/x-pack/test/functional/apps/license_management/feature_controls/license_management_security.ts index 9608bffb302d1..cf724d721585c 100644 --- a/x-pack/test/functional/apps/license_management/feature_controls/license_management_security.ts +++ b/x-pack/test/functional/apps/license_management/feature_controls/license_management_security.ts @@ -68,7 +68,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { expect(sections).to.have.length(3); expect(sections[2]).to.eql({ sectionId: 'stack', - sectionLinks: ['license_management', 'upgrade_assistant'], + sectionLinks: ['license_management'], }); }); }); diff --git a/x-pack/test/functional/apps/upgrade_assistant/feature_controls/upgrade_assistant_security.ts b/x-pack/test/functional/apps/upgrade_assistant/feature_controls/upgrade_assistant_security.ts index 3de9e252e032a..7aa8bfe4eff69 100644 --- a/x-pack/test/functional/apps/upgrade_assistant/feature_controls/upgrade_assistant_security.ts +++ b/x-pack/test/functional/apps/upgrade_assistant/feature_controls/upgrade_assistant_security.ts @@ -15,7 +15,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { const appsMenu = getService('appsMenu'); const managementMenu = getService('managementMenu'); - describe('security', function () { + describe.skip('security', function () { before(async () => { await esArchiver.load('x-pack/test/functional/es_archives/empty_kibana'); await PageObjects.common.navigateToApp('home'); diff --git a/x-pack/test/functional/apps/upgrade_assistant/upgrade_assistant.ts b/x-pack/test/functional/apps/upgrade_assistant/upgrade_assistant.ts index 09900b6ababef..93475c228ed2f 100644 --- a/x-pack/test/functional/apps/upgrade_assistant/upgrade_assistant.ts +++ b/x-pack/test/functional/apps/upgrade_assistant/upgrade_assistant.ts @@ -17,10 +17,9 @@ export default function upgradeAssistantFunctionalTests({ const security = getService('security'); const log = getService('log'); const retry = getService('retry'); - const testSubjects = getService('testSubjects'); // Updated for the hiding of the UA UI. - describe('Upgrade Checkup', function () { + describe.skip('Upgrade Checkup', function () { this.tags('skipFirefox'); before(async () => { @@ -34,13 +33,6 @@ export default function upgradeAssistantFunctionalTests({ await security.testUser.restoreDefaults(); }); - it('Overview page', async () => { - await PageObjects.upgradeAssistant.navigateToPage(); - await retry.waitFor('Upgrade Assistant overview page to be visible', async () => { - return testSubjects.exists('comingSoonPrompt'); - }); - }); - it.skip('allows user to navigate to upgrade checkup', async () => { await PageObjects.upgradeAssistant.navigateToPage(); }); From 252aef80dc21ee8664278a0305ccab4a9ca90676 Mon Sep 17 00:00:00 2001 From: Gloria Hornero Date: Tue, 26 Oct 2021 14:07:09 +0200 Subject: [PATCH 24/58] adds cases and timelines plugins to security solution cypress tests execution (#116245) --- vars/tasks.groovy | 2 ++ 1 file changed, 2 insertions(+) diff --git a/vars/tasks.groovy b/vars/tasks.groovy index 1842e278282b1..0f509fa8ba132 100644 --- a/vars/tasks.groovy +++ b/vars/tasks.groovy @@ -135,6 +135,8 @@ def functionalXpack(Map params = [:]) { whenChanged([ 'x-pack/plugins/security_solution/', + 'x-pack/plugins/cases/', + 'x-pack/plugins/timelines/', 'x-pack/test/security_solution_cypress/', 'x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/', 'x-pack/plugins/triggers_actions_ui/public/application/context/actions_connectors_context.tsx', From 3c8fa527a7765723d3851afe067315359a4763e7 Mon Sep 17 00:00:00 2001 From: Mikhail Shustov Date: Tue, 26 Oct 2021 14:08:22 +0200 Subject: [PATCH 25/58] [ES] Upgrade client to v8.0 (#113950) * bump to a pre-8.0 version * export KibanaClient from /lib sub-folder * workaround the problem of the absence of estypes * update es client usage in pacakges * export estypes from another path * import errors from root * import errors from root 2 * update transport import * update import path for /api/types * update import path for /api/types * import errors from top export * use TransportResult instead if ApiResponse * fix errors in client_config * fix src/core/server/saved_objects/migrationsv2/actions/integration_tests/actions.test.ts * use KibanaClient in mock. we dont export the original Client * fix client mocks * fix errors on SO * fix remaining core errors * update estype import path * fix errors in data plugin * fix data_views * fix es_ui_shared * fix errors in interactive_setup * fix errors in ./test folder * add @elastic/transport to the runtime deps * fix errors in packages * fix erros in src/core * fix errors in test/ * fix an error in actions plugin * woraround and fix errors in APM plugin * fix errors in canvas * fix errors in event_log * fix errors in fleet * fix errors in ILM * fix errors in infra * fix errors in ingest_pipeline * fix errors in lens * fix errors in license_management * fix errors in licensing * fix errors in logstash * fix errors in ml * fix errors in monitoring * fix errors in observability * fix errors in rule_registry * fix errors in reporting * fix errors in rule_registry * fix errors in security * fix errors in security_solution * fix errors in snapshot_restore * fix errors in transform * fix errors in UA * fix errors in uptime * fix errors in x-pack/test * fix eslint errors * fix new errors * use default HTTP Connection. Undici does not support agent config options keepAlive and maxSockets * create does not accept require_alias option * update deps * use transport types exported from ES client package * fix ErrorCause | string errors * do not use enum * fix errors in data plugin * update x-pack code * fix transport * fix apm search request * do not crash on reporting * fix kbn-test build * mute reporting error to start * fix ftr build * another attempt * update import path * address or mute new errors * REMOVE me. pin transport version temporarily. * remove deep imports from transport package * fix jest crash * fix product check tests * remove unnecessary ts-expect-error * fix a few failed unit tests * bump to canary 24 * remove unnecessary ts-expect-error * remove dependency on transport * fix types in tests * mute errors in xpack tests * product check doesn;t spam in logs anymore * filterPath --> filter_path * ignoreUnavailable --> ignore_unavailable * ignoreUnavailable --> ignore_unavailable * trackScores --> track_scores * trackTotalHits --> track_total_hits * fix es-arcives * fix data plugin crashes * fix watcher test utils * rollback unnecessary changes * fix another problem in es-archiver * fix scroll. for whatever reason scroll fails when request scroll_id in body * add meta: true in kbn-securitysolution-es-utils * bump client to canary 25 * fix errors in accordance with the es client spec * update securityscolution-es-utils * unify scroll api in reporting and fix tests * fix unit tests in watcher * refactor APM to abort request with AbortController API * fix missing es client calls in tests * fix missing meta in detection engine FTR tests * fix another bunch of errors in js tests * fix wrong coercion * remove test-grep pattern * fix apm unit test * rename terminateAfter to terminate_after in infra plugin * rename terminateAfter to terminate_after in uptime plugin * rename terminateAfter to terminate_after in apm plugin * fix security roles FTR tests * fix reference * fix post_privilidges test * fix post_privilidges * bump client to 26 * add meta for index_management test helpers * remove ts-expect-error caused by bad type in reason * bump client to 27 * REMOVE me. workaround until fixed in the es client * fix incorrect type casting * swtich from camelCase params * use `HttpConnection` for FTR-related clients * bump client to 29 * Revert "REMOVE me. workaround until fixed in the es client" This reverts commit c038850c09c378977a50c0e3d176810f4b69b5d6. * fix new util * revert repository changes * do not crash if cannot store event_loop data * fix new estypes imports * fix more types * fix security test types and add ts-ignore for custom ES client * fix more estypes imports * yet more ts violations * line by line fixing is hard * adapt `evaluateAlert` from infra as it's also used from FTR tests * use convertToKibanaClient in FTR test instead of meta:true in plugin code * migrate from deprecated API in fleet * fix intergration tests * fix fleet tests * fix another fleet test * fix more tests * let's call it a day * Removes custom header check on 404 responses, includes es client ProductNotSupportedError in EsUnavailableError conditional (#116029) * Removes custom header check on 404 responses, includes es client ProductNotSupportedError in EsUnavailableError conditional * Updates proxy response integration test * disable APM until compatible with client v8 * skip async_search FTR test * use kbnClient in integration tests * bump version to 29 * bump to 30 * have configureClient return a KibanaClient instead of Client, remove resolved violations. * bump to 31 * bump to 31 * Revert "bump to 31" This reverts commit 5ac713e640bf60ae4b6914e00e3149ffe0b8ae8c. * trigger stop to unusubscribe * update generated docs * remove obsolete test * put "as" back * cleanup * skip test * remove new type errors in apm package * remove ErrorCause casting * update a comment * bump version to 32 * remove unnecessary ts-expect-error in apm code * update comments * update to client v33 * remove outdated type definition * bump to 34 without params mutation * unskip the test that should not fail anymore * remove unnecessary ts-expect-error comments * update to v35. body can be string * move `sort` to body and use body friendly syntax * fix a failing test. maps register the same SO that has been already registered by home Co-authored-by: pgayvallet Co-authored-by: Christiane (Tina) Heiligers --- ...-plugin-core-server.elasticsearchclient.md | 4 +- ...-server.elasticsearcherrordetails.error.md | 14 ++ ...n-core-server.elasticsearcherrordetails.md | 19 ++ .../core/server/kibana-plugin-core-server.md | 1 + ...creategenericnotfoundesunavailableerror.md | 23 -- ...in-core-server.savedobjectserrorhelpers.md | 1 - package.json | 2 +- .../src/scripts/utils/clean_write_targets.ts | 10 +- .../src/scripts/utils/get_write_targets.ts | 7 +- .../src/scripts/utils/upload_events.ts | 2 +- .../src/init_apm.test.ts | 3 +- .../kbn-apm-config-loader/src/init_apm.ts | 3 + .../src/actions/empty_kibana_index.ts | 4 +- packages/kbn-es-archiver/src/actions/load.ts | 4 +- packages/kbn-es-archiver/src/actions/save.ts | 4 +- .../kbn-es-archiver/src/actions/unload.ts | 4 +- packages/kbn-es-archiver/src/cli.ts | 5 +- packages/kbn-es-archiver/src/es_archiver.ts | 6 +- .../docs/generate_doc_records_stream.test.ts | 8 +- .../lib/docs/generate_doc_records_stream.ts | 8 +- .../src/lib/docs/index_doc_records_stream.ts | 4 +- .../src/lib/indices/__mocks__/stubs.ts | 4 +- .../lib/indices/create_index_stream.test.ts | 1 + .../src/lib/indices/create_index_stream.ts | 6 +- .../src/lib/indices/delete_index.ts | 17 +- .../src/lib/indices/delete_index_stream.ts | 4 +- .../indices/generate_index_records_stream.ts | 8 +- .../src/lib/indices/kibana_index.ts | 30 +-- .../src/es_query/decorate_query.ts | 2 +- .../kbn-es-query/src/es_query/from_filters.ts | 2 +- .../src/es_query/lucene_string_to_dsl.ts | 2 +- packages/kbn-es-query/src/es_query/types.ts | 2 +- .../filters/build_filters/custom_filter.ts | 2 +- .../filters/build_filters/match_all_filter.ts | 2 +- .../build_filters/phrase_filter.test.ts | 2 +- .../filters/build_filters/phrase_filter.ts | 2 +- .../filters/build_filters/phrases_filter.ts | 2 +- .../src/filters/build_filters/range_filter.ts | 2 +- packages/kbn-es-query/src/kuery/ast/ast.ts | 2 +- .../src/kuery/functions/exists.ts | 2 +- .../kuery/functions/geo_bounding_box.test.ts | 1 - .../src/kuery/functions/geo_bounding_box.ts | 3 +- .../src/kuery/functions/geo_polygon.ts | 3 +- .../src/kuery/functions/is.test.ts | 2 +- .../kbn-es-query/src/kuery/functions/is.ts | 2 +- .../src/kuery/functions/nested.ts | 2 +- .../kbn-es-query/src/kuery/functions/not.ts | 2 +- .../kbn-es-query/src/kuery/functions/or.ts | 2 +- .../src/kuery/functions/range.test.ts | 2 +- .../kbn-es-query/src/kuery/functions/range.ts | 2 +- packages/kbn-es-query/src/kuery/index.ts | 2 +- packages/kbn-es-query/src/kuery/types.ts | 2 +- packages/kbn-es/src/utils/native_realm.js | 10 +- .../kbn-es/src/utils/native_realm.test.js | 74 +++--- .../src/alerts_as_data_rbac.ts | 2 +- .../src/create_boostrap_index/index.ts | 17 +- .../src/decode_version/index.ts | 4 +- .../src/delete_all_index/index.ts | 2 +- .../src/delete_policy/index.ts | 7 +- .../src/delete_template/index.ts | 9 +- .../src/elasticsearch_client/index.ts | 4 +- .../src/get_index_aliases/index.ts | 9 +- .../src/get_index_count/index.ts | 9 +- .../src/get_index_exists/index.ts | 17 +- .../src/get_policy_exists/index.ts | 4 +- .../src/get_template_exists/index.ts | 9 +- .../src/read_index/index.ts | 9 +- .../src/read_privileges/index.ts | 111 ++++----- .../src/set_policy/index.ts | 13 +- .../src/set_template/index.ts | 11 +- .../src/build_exception_filter/index.ts | 6 +- .../src/es/client_to_kibana_client.ts | 35 +++ packages/kbn-test/src/es/index.ts | 1 + packages/kbn-test/src/es/test_es_cluster.ts | 18 +- .../report_failures_to_es.ts | 5 +- packages/kbn-test/src/index.ts | 1 + src/core/public/public.api.md | 11 +- .../core_usage_data_service.ts | 2 +- .../client/client_config.test.ts | 32 +-- .../elasticsearch/client/client_config.ts | 6 +- .../elasticsearch/client/cluster_client.ts | 6 +- .../client/configure_client.test.ts | 68 ++---- .../elasticsearch/client/configure_client.ts | 67 +++--- .../elasticsearch/client/errors.test.ts | 32 +-- .../server/elasticsearch/client/errors.ts | 8 +- src/core/server/elasticsearch/client/index.ts | 1 + .../server/elasticsearch/client/mocks.test.ts | 6 +- src/core/server/elasticsearch/client/mocks.ts | 69 +++--- src/core/server/elasticsearch/client/types.ts | 20 +- src/core/server/elasticsearch/index.ts | 6 +- .../integration_tests/client.test.ts | 11 - .../is_scripting_enabled.test.ts | 2 +- .../supported_server_response_check.test.ts | 41 ---- .../supported_server_response_check.ts | 33 --- .../version_check/ensure_es_version.test.ts | 1 + .../integration_tests/core_services.test.ts | 8 +- .../server/http/router/response_adapter.ts | 5 +- src/core/server/http/router/router.ts | 4 +- src/core/server/index.ts | 1 + .../deprecations/unknown_object_types.test.ts | 2 +- .../deprecations/unknown_object_types.ts | 2 +- .../server/saved_objects/mappings/types.ts | 2 +- .../migrations/core/call_cluster.ts | 2 +- .../migrations/core/elastic_index.test.ts | 6 +- .../migrations/core/elastic_index.ts | 2 +- .../migrations/core/index_migrator.test.ts | 4 +- .../migrations/core/migration_es_client.ts | 7 +- .../migrations/kibana/kibana_migrator.test.ts | 4 +- .../bulk_overwrite_transformed_documents.ts | 5 +- .../actions/calculate_exclude_filters.ts | 2 +- .../catch_retryable_es_client_errors.ts | 2 +- .../actions/check_for_unknown_docs.test.ts | 3 +- .../actions/check_for_unknown_docs.ts | 2 +- .../migrationsv2/actions/create_index.ts | 4 +- .../migrationsv2/actions/es_errors.ts | 12 +- .../actions/integration_tests/actions.test.ts | 16 +- .../integration_tests/es_errors.test.ts | 6 +- .../migrationsv2/actions/read_with_pit.ts | 2 +- .../migrationsv2/actions/reindex.ts | 2 +- .../actions/remove_write_block.ts | 6 +- .../actions/search_for_outdated_documents.ts | 2 +- .../migrationsv2/actions/set_write_block.ts | 3 +- .../migrationsv2/actions/wait_for_task.ts | 3 +- .../7_13_0_failed_action_tasks.test.ts | 2 +- .../7_13_0_unknown_types.test.ts | 6 +- .../batch_size_bytes.test.ts | 2 +- ...ze_bytes_exceeds_es_content_length.test.ts | 3 +- .../integration_tests/cleanup.test.ts | 2 +- .../multiple_es_nodes.test.ts | 2 +- .../multiple_kibana_nodes.test.ts | 8 +- .../migrations_state_action_machine.test.ts | 4 +- .../saved_objects/migrationsv2/model/model.ts | 2 +- .../saved_objects/migrationsv2/types.ts | 2 +- .../lib/aggregations/validation.test.ts | 2 +- .../service/lib/aggregations/validation.ts | 2 +- ...collect_multi_namespace_references.test.ts | 18 -- .../lib/collect_multi_namespace_references.ts | 11 - .../service/lib/decorate_es_error.test.ts | 22 +- .../service/lib/decorate_es_error.ts | 32 ++- .../saved_objects/service/lib/errors.test.ts | 41 ---- .../saved_objects/service/lib/errors.ts | 12 - .../repository_with_proxy.test.ts | 36 ++- .../lib/internal_bulk_resolve.test.mock.ts | 12 - .../service/lib/internal_bulk_resolve.test.ts | 21 -- .../service/lib/internal_bulk_resolve.ts | 13 +- .../service/lib/point_in_time_finder.ts | 2 +- .../service/lib/repository.test.js | 221 ------------------ .../saved_objects/service/lib/repository.ts | 108 ++------- .../service/lib/repository_es_client.ts | 2 +- .../service/lib/search_dsl/search_dsl.ts | 2 +- .../service/lib/search_dsl/sorting_params.ts | 2 +- .../service/lib/update_objects_spaces.test.ts | 38 --- .../service/lib/update_objects_spaces.ts | 14 +- src/core/server/saved_objects/types.ts | 2 +- src/core/server/server.api.md | 30 ++- .../integration_tests/lib/servers.ts | 4 +- src/core/types/elasticsearch/index.ts | 2 +- src/core/types/elasticsearch/search.ts | 2 +- .../data/common/search/aggs/agg_configs.ts | 2 +- .../data/common/search/aggs/agg_type.ts | 2 +- .../buckets/_terms_other_bucket_helper.ts | 2 +- .../common/search/aggs/utils/time_splits.ts | 2 +- .../search/expressions/es_raw_response.ts | 2 +- .../search_source/inspect/inspector_stats.ts | 2 +- .../search/search_source/search_source.ts | 2 +- .../data/common/search/search_source/types.ts | 2 +- .../search/strategies/eql_search/types.ts | 8 +- .../search/strategies/es_search/types.ts | 2 +- .../common/search/tabify/tabify_docs.test.ts | 2 +- .../data/common/search/tabify/tabify_docs.ts | 2 +- .../data/public/search/errors/types.ts | 2 +- .../data/public/search/errors/utils.ts | 2 +- .../__mocks__/shard_failure_response.ts | 2 +- .../shard_failure_modal.tsx | 2 +- .../shard_failure_open_modal_button.tsx | 2 +- .../shard_failure_types.ts | 2 +- .../server/autocomplete/terms_agg.test.ts | 6 +- .../data/server/autocomplete/terms_agg.ts | 11 +- .../server/autocomplete/terms_enum.test.ts | 6 +- .../data/server/autocomplete/terms_enum.ts | 39 ++-- .../eql_search/eql_search_strategy.ts | 19 +- .../strategies/eql_search/response_utils.ts | 4 +- .../search/strategies/eql_search/types.ts | 2 +- .../es_search/es_search_strategy.test.ts | 26 +-- .../es_search/es_search_strategy.ts | 12 +- .../es_search/request_utils.test.ts | 57 +---- .../strategies/es_search/request_utils.ts | 37 +-- .../es_search/response_utils.test.ts | 2 +- .../strategies/es_search/response_utils.ts | 2 +- .../ese_search/ese_search_strategy.test.ts | 8 +- .../ese_search/ese_search_strategy.ts | 30 +-- .../strategies/ese_search/request_utils.ts | 13 +- .../search/strategies/ese_search/types.ts | 2 +- .../data_views/common/data_views/data_view.ts | 2 +- src/plugins/data_views/common/types.ts | 2 +- .../field_capabilities/field_caps_response.ts | 4 +- .../doc_table/lib/row_formatter.tsx | 2 +- .../apps/main/utils/fetch_chart.test.ts | 2 +- .../application/doc_views/doc_views_types.ts | 2 +- .../application/helpers/format_hit.test.ts | 2 +- .../public/application/helpers/format_hit.ts | 2 +- .../application/helpers/format_value.ts | 2 +- .../application/helpers/get_ignored_reason.ts | 2 +- .../application/services/use_es_doc_search.ts | 2 +- .../discover/public/application/types.ts | 2 +- .../errors/handle_es_error.ts | 9 +- .../server/routes/field_preview.ts | 2 +- .../scripted_fields_table/types.ts | 2 +- .../components/field_editor/field_editor.tsx | 2 +- .../public/scripting_languages/index.ts | 2 +- .../server/elasticsearch_service.test.ts | 6 +- .../server/elasticsearch_service.ts | 4 +- .../interactive_setup/server/errors.ts | 2 +- src/plugins/interactive_setup/server/mocks.ts | 12 +- .../event_loop_delays/track_delays.ts | 6 +- .../kibana_usage_collection/server/plugin.ts | 2 + .../server/report_server_error.ts | 6 +- .../get_local_stats.test.ts | 2 +- .../telemetry_collection/get_local_stats.ts | 2 +- .../telemetry_collection/get_nodes_usage.ts | 2 +- .../vega/public/data_model/es_query_parser.ts | 2 +- .../vis_types/vega/public/data_model/types.ts | 2 +- test/api_integration/apis/home/sample_data.ts | 6 +- .../has_user_index_pattern.ts | 4 +- .../apis/kql_telemetry/kql_telemetry.ts | 4 +- .../saved_objects/delete_unknown_types.ts | 2 +- .../apis/saved_objects/migrations.ts | 13 +- .../telemetry/telemetry_optin_notice_seen.ts | 4 +- .../apis/ui_metric/ui_metric.ts | 8 +- test/common/services/elasticsearch.ts | 9 +- test/common/services/es_delete_all_indices.ts | 1 + .../saved_object_info/saved_object_info.ts | 4 +- .../apps/management/_field_formatter.ts | 4 +- .../management/_handle_version_conflict.js | 30 ++- .../tests/enrollment_flow.ts | 4 +- .../plugins/actions/server/actions_client.ts | 2 +- .../builtin_action_types/es_index.test.ts | 10 +- .../cleanup_tasks.test.ts | 7 +- .../lib/bulk_delete.ts | 5 +- .../extract_bulk_response_delete_failures.ts | 7 +- .../actions/server/usage/actions_telemetry.ts | 2 +- .../alerting_authorization_kuery.ts | 2 +- .../server/lib/errors/es_error_parser.ts | 1 - .../server/rules_client/rules_client.ts | 2 +- .../search_strategies/field_stats_types.ts | 2 +- .../apm/common/utils/environment_query.ts | 2 +- .../components/shared/kuery_bar/index.tsx | 2 +- .../public/components/shared/search_bar.tsx | 2 +- .../aggregate-latency-metrics/index.ts | 8 +- .../create-functional-tests-archive/index.ts | 3 +- .../scripts/shared/create-or-update-index.ts | 8 +- .../apm/scripts/shared/get_es_client.ts | 17 +- .../scripts/upload-telemetry-data/index.ts | 12 +- .../chart_preview/get_transaction_duration.ts | 2 +- ...egister_transaction_duration_alert_type.ts | 2 +- ...transaction_duration_anomaly_alert_type.ts | 2 +- .../collect_data_telemetry/index.ts | 4 +- .../collect_data_telemetry/tasks.ts | 4 +- .../exclude_rum_exit_spans_query.ts | 2 +- .../get_destination_map.ts | 2 +- .../get_connection_stats/get_stats.ts | 2 +- .../connections/get_connection_stats/index.ts | 2 +- .../lib/event_metadata/get_event_metadata.ts | 2 +- .../cancel_es_request_on_abort.ts | 18 +- .../create_apm_event_client/index.test.ts | 20 +- .../create_apm_event_client/index.ts | 36 +-- .../create_internal_es_client/index.ts | 20 +- .../server/lib/helpers/setup_request.test.ts | 48 ++-- ...t_is_using_transaction_events.test.ts.snap | 8 +- .../get_is_using_transaction_events.ts | 2 +- .../server/lib/helpers/transactions/index.ts | 2 +- .../get_overall_latency_distribution.ts | 2 +- .../latency/get_percentile_threshold_value.ts | 2 +- .../lib/observability_overview/has_data.ts | 2 +- .../field_stats/get_boolean_field_stats.ts | 6 +- .../field_stats/get_field_stats.test.ts | 2 +- .../field_stats/get_keyword_field_stats.ts | 5 +- .../field_stats/get_numeric_field_stats.ts | 5 +- .../queries/get_query_with_params.ts | 2 +- .../queries/query_correlation.test.ts | 2 +- .../queries/query_correlation.ts | 2 +- .../queries/query_failure_correlation.ts | 2 +- .../queries/query_field_candidates.test.ts | 2 +- .../queries/query_field_candidates.ts | 2 +- .../queries/query_field_value_pairs.test.ts | 2 +- .../queries/query_field_value_pairs.ts | 2 +- .../queries/query_fractions.test.ts | 2 +- .../queries/query_fractions.ts | 2 +- .../queries/query_histogram.test.ts | 2 +- .../queries/query_histogram.ts | 2 +- .../query_histogram_range_steps.test.ts | 2 +- .../queries/query_histogram_range_steps.ts | 2 +- .../query_histograms_generator.test.ts | 2 +- .../queries/query_histograms_generator.ts | 2 +- .../queries/query_percentiles.test.ts | 2 +- .../queries/query_percentiles.ts | 2 +- .../queries/query_ranges.test.ts | 2 +- .../search_strategies/queries/query_ranges.ts | 2 +- .../search_strategy_provider.test.ts | 2 +- .../utils/compute_expectations_and_ranges.ts | 2 +- .../utils/field_stats_utils.ts | 3 +- .../lib/service_map/get_service_anomalies.ts | 2 +- .../__snapshots__/queries.test.ts.snap | 6 +- .../annotations/get_stored_annotations.ts | 4 +- .../server/lib/services/get_service_agent.ts | 2 +- .../get_services/get_legacy_data_status.ts | 2 +- .../create_agent_config_index.ts | 1 - .../get_agent_name_by_service.ts | 2 +- .../get_transaction.test.ts.snap | 4 +- .../custom_link/create_custom_link_index.ts | 2 +- .../settings/custom_link/get_transaction.ts | 2 +- .../settings/custom_link/list_custom_links.ts | 2 +- .../apm/server/lib/traces/get_trace_items.ts | 2 +- .../server/lib/transaction_groups/fetcher.ts | 2 +- .../get_transaction_group_stats.ts | 2 +- .../transactions/get_anomaly_data/fetcher.ts | 2 +- .../trace_samples/get_trace_samples/index.ts | 2 +- .../plugins/apm/server/projections/metrics.ts | 2 +- .../plugins/apm/server/projections/typings.ts | 2 +- .../has_historical_agent_data.ts | 2 +- .../server/routes/register_routes/index.ts | 4 +- x-pack/plugins/canvas/types/strategy.ts | 6 +- .../cases/server/services/cases/index.ts | 2 +- .../data_enhanced/server/collectors/fetch.ts | 2 +- .../search/session/get_search_status.ts | 10 +- .../data_visualizer/common/types/indices.ts | 2 +- .../common/utils/datafeed_utils.ts | 2 +- .../common/utils/query_utils.ts | 2 +- .../common/utils/runtime_field_utils.ts | 2 +- .../full_time_range_selector_service.ts | 2 +- .../data_loader/data_loader.ts | 2 +- .../services/time_field_range.ts | 2 +- .../services/visualizer_stats.ts | 2 +- .../data_visualizer/check_fields_exist.ts | 2 +- .../models/data_visualizer/data_visualizer.ts | 2 +- .../data_visualizer/get_field_examples.ts | 2 +- .../data_visualizer/get_fields_stats.ts | 2 +- .../get_histogram_for_fields.ts | 2 +- .../data_visualizer/server/routes/routes.ts | 2 +- .../server/es/cluster_client_adapter.test.ts | 11 +- .../server/es/cluster_client_adapter.ts | 6 +- .../event_log/server/es/context.test.ts | 7 +- x-pack/plugins/event_log/server/es/init.ts | 7 +- x-pack/plugins/file_upload/common/types.ts | 2 +- .../server/get_time_field_range.ts | 2 +- .../server/utils/runtime_field_utils.ts | 2 +- .../plugins/fleet/common/types/models/epm.ts | 2 +- x-pack/plugins/fleet/server/errors/index.ts | 6 +- x-pack/plugins/fleet/server/errors/utils.ts | 6 +- .../plugins/fleet/server/routes/app/index.ts | 5 +- .../server/routes/data_streams/handlers.ts | 2 +- .../fleet/server/services/agents/crud.ts | 12 +- .../fleet/server/services/agents/helpers.ts | 2 +- .../server/services/agents/reassign.test.ts | 8 +- .../server/services/agents/unenroll.test.ts | 42 ++-- .../services/api_keys/enrollment_api_key.ts | 10 +- .../services/artifacts/artifacts.test.ts | 19 +- .../server/services/artifacts/artifacts.ts | 4 +- .../server/services/artifacts/client.test.ts | 2 + .../fleet/server/services/artifacts/mocks.ts | 16 +- .../fleet/server/services/artifacts/utils.ts | 6 +- .../elasticsearch/ingest_pipeline/install.ts | 2 +- .../epm/elasticsearch/ml_model/install.ts | 5 +- .../elasticsearch/template/install.test.ts | 55 +++-- .../epm/elasticsearch/template/install.ts | 1 - .../epm/elasticsearch/template/template.ts | 2 +- .../epm/elasticsearch/transform/install.ts | 4 +- .../elasticsearch/transform/transform.test.ts | 4 +- .../server/plugin.ts | 3 +- .../api/policies/register_create_route.ts | 2 +- .../api/policies/register_delete_route.ts | 3 +- .../api/policies/register_fetch_route.ts | 4 +- .../register_fetch_route.ts | 2 +- .../server/lib/fetch_indices.ts | 1 - .../register_update_route.ts | 2 +- .../routes/api/stats/register_stats_route.ts | 2 +- .../server/routes/api/templates/lib.ts | 1 - .../api/templates/register_simulate_route.ts | 4 +- .../resolved_log_source_configuration.ts | 2 +- .../log_entries/log_entries.ts | 2 +- .../components/expression_chart.test.tsx | 1 + .../components/expression_chart.tsx | 3 +- .../log_analysis/api/validate_datasets.ts | 2 +- .../logs/log_analysis/api/validate_indices.ts | 2 +- .../log_analysis/log_analysis_module_types.ts | 2 +- .../log_entry_categories/module_descriptor.ts | 2 +- .../use_log_entry_categories_module.tsx | 2 +- .../log_entry_rate/module_descriptor.ts | 2 +- .../use_log_entry_rate_module.tsx | 2 +- x-pack/plugins/infra/public/lib/lib.ts | 2 +- .../hooks/use_metrics_explorer_data.ts | 3 +- .../public/utils/logs_overview_fetchers.ts | 2 +- .../lib/adapters/framework/adapter_types.ts | 2 +- .../framework/kibana_framework_adapter.ts | 15 +- .../log_entries/kibana_log_entries_adapter.ts | 4 +- .../adapters/metrics/lib/check_valid_node.ts | 2 +- .../inventory_metric_threshold_executor.ts | 2 +- .../log_threshold_executor.test.ts | 2 +- .../log_threshold/log_threshold_executor.ts | 2 +- .../metric_threshold/lib/evaluate_alert.ts | 3 +- .../log_entries_domain/log_entries_domain.ts | 2 +- .../queries/log_entry_datasets.ts | 2 +- .../lib/log_analysis/log_entry_anomalies.ts | 2 +- .../log_entry_categories_analysis.ts | 2 +- .../queries/log_entry_category_examples.ts | 2 +- .../queries/log_entry_examples.ts | 2 +- .../log_analysis/validation/datasets.ts | 2 +- .../routes/log_sources/configuration.ts | 2 + .../routes/metadata/lib/get_node_info.ts | 2 +- .../routes/metadata/lib/get_pod_node_name.ts | 2 +- .../lib/get_dataset_for_field.ts | 2 +- .../server/routes/metrics_sources/index.ts | 2 + .../log_entries_search_strategy.test.ts | 6 +- .../log_entries_search_strategy.ts | 1 - .../log_entry_search_strategy.test.ts | 6 +- .../log_entries/log_entry_search_strategy.ts | 1 - .../log_entries/queries/log_entries.ts | 5 +- .../services/log_entries/queries/log_entry.ts | 3 +- .../server/utils/get_all_composite_data.ts | 4 +- .../common/lib/pipeline_serialization.ts | 2 +- .../server/routes/api/privileges.ts | 1 + .../server/routes/api/simulate.ts | 4 +- .../lens/server/routes/existing_fields.ts | 3 +- .../plugins/lens/server/routes/field_stats.ts | 3 +- .../server/lib/permissions.ts | 12 +- .../plugins/licensing/server/plugin.test.ts | 5 +- x-pack/plugins/licensing/server/plugin.ts | 2 +- .../server/schemas/common/get_shard.mock.ts | 2 +- .../search_es_list_item_schema.mock.ts | 2 +- .../search_es_list_schema.mock.ts | 2 +- .../services/items/find_list_item.mock.ts | 2 +- .../items/write_list_items_to_stream.ts | 2 +- .../utils/get_query_filter_from_type_value.ts | 2 +- .../get_search_after_with_tie_breaker.ts | 2 +- .../utils/get_sort_with_tie_breaker.ts | 2 +- ...sform_elastic_named_search_to_list_item.ts | 2 +- .../utils/transform_elastic_to_list.ts | 2 +- .../utils/transform_elastic_to_list_item.ts | 2 +- .../server/models/cluster/cluster.test.ts | 2 +- .../logstash/server/models/cluster/cluster.ts | 2 +- .../logstash/server/routes/pipeline/save.ts | 1 + .../es_geo_grid_source/es_geo_grid_source.tsx | 2 +- x-pack/plugins/maps/server/plugin.ts | 4 +- .../types/anomaly_detection_jobs/datafeed.ts | 2 +- .../anomaly_detection_jobs/datafeed_stats.ts | 2 +- .../types/anomaly_detection_jobs/job.ts | 2 +- .../types/anomaly_detection_jobs/job_stats.ts | 2 +- .../anomaly_detection_jobs/model_snapshot.ts | 2 +- .../ml/common/types/data_frame_analytics.ts | 2 +- x-pack/plugins/ml/common/types/es_client.ts | 2 +- x-pack/plugins/ml/common/types/fields.ts | 2 +- x-pack/plugins/ml/common/types/results.ts | 2 +- x-pack/plugins/ml/common/util/job_utils.ts | 2 +- .../ml/common/util/runtime_field_utils.ts | 2 +- .../alerting/ml_anomaly_alert_trigger.tsx | 2 +- .../components/data_grid/common.ts | 2 +- .../application/components/data_grid/types.ts | 2 +- .../new_job_awaiting_node_shared.tsx | 2 +- .../scatterplot_matrix/scatterplot_matrix.tsx | 2 +- .../common/get_index_data.ts | 2 +- .../form_options_validation.ts | 2 +- .../configuration_step/use_saved_search.ts | 2 +- .../hooks/use_index_data.ts | 2 +- .../exploration_query_bar.tsx | 2 +- .../job_creator/advanced_job_creator.ts | 2 +- .../new_job/common/job_creator/job_creator.ts | 4 +- .../advanced_detector_modal.tsx | 2 +- .../services/anomaly_detector_service.ts | 2 +- .../application/services/job_service.d.ts | 2 +- .../services/ml_api_service/index.ts | 2 +- .../embeddables/common/process_filters.ts | 2 +- .../lib/alerts/jobs_health_service.test.ts | 2 +- .../server/lib/alerts/jobs_health_service.ts | 2 +- .../register_jobs_monitoring_rule_type.ts | 6 +- .../plugins/ml/server/lib/ml_client/search.ts | 5 +- x-pack/plugins/ml/server/lib/query_utils.ts | 2 +- .../models/annotation_service/annotation.ts | 2 +- .../calculate_model_memory_limit.ts | 3 +- .../models/calendar/calendar_manager.ts | 2 +- .../server/models/calendar/event_manager.ts | 2 +- .../models/data_frame_analytics/validation.ts | 2 +- .../ml/server/models/filter/filter_manager.ts | 2 +- .../job_audit_messages/job_audit_messages.ts | 4 +- .../ml/server/models/job_service/datafeeds.ts | 2 +- .../new_job/categorization/examples.ts | 2 +- .../new_job/categorization/top_categories.ts | 2 +- .../job_service/new_job_caps/field_service.ts | 6 +- .../models/job_service/new_job_caps/rollup.ts | 4 +- .../job_validation/validate_influencers.ts | 5 +- .../ml/server/routes/anomaly_detectors.ts | 3 +- x-pack/plugins/ml/server/routes/datafeeds.ts | 2 +- .../plugins/ml/server/routes/job_service.ts | 2 +- .../shared_services/providers/system.ts | 2 +- .../collectors/lib/fetch_es_usage.ts | 2 +- .../collectors/lib/fetch_license_type.ts | 2 +- .../lib/fetch_stack_product_usage.ts | 2 +- .../lib/alerts/fetch_available_ccs.test.ts | 2 +- .../lib/alerts/fetch_cluster_health.test.ts | 2 +- .../server/lib/alerts/fetch_clusters.test.ts | 2 +- .../alerts/fetch_cpu_usage_node_stats.test.ts | 2 +- .../fetch_elasticsearch_versions.test.ts | 2 +- .../server/lib/alerts/fetch_licenses.test.ts | 2 +- .../elasticsearch_settings/cluster.test.ts | 2 +- .../lib/elasticsearch_settings/cluster.ts | 2 +- .../server/lib/errors/auth_errors.test.ts | 6 +- .../server/lib/errors/esclient_errors.ts | 6 +- .../server/lib/errors/handle_error.ts | 4 +- .../check/internal_monitoring.ts | 2 +- .../monitoring/server/static_globals.ts | 2 +- .../telemetry_collection/get_beats_stats.ts | 2 +- .../telemetry_collection/get_cluster_uuids.ts | 2 +- .../telemetry_collection/get_es_stats.ts | 2 +- .../get_high_level_stats.ts | 2 +- .../get_kibana_stats.test.ts | 2 +- .../telemetry_collection/get_kibana_stats.ts | 2 +- .../telemetry_collection/get_licenses.ts | 2 +- .../get_logstash_stats.ts | 2 +- x-pack/plugins/monitoring/server/types.ts | 4 +- .../common/utils/unwrap_es_response.ts | 8 +- .../series_editor/use_filter_values.ts | 4 +- .../public/hooks/use_es_search.ts | 2 +- .../server/routes/register_routes.ts | 4 +- .../server/utils/create_or_update_index.ts | 2 +- .../observability/server/utils/queries.ts | 2 +- .../search_strategy/osquery/actions/index.ts | 2 +- .../common/search_strategy/osquery/index.ts | 2 +- .../search_strategy/osquery/results/index.ts | 2 +- .../plugins/osquery/public/agents/helpers.ts | 2 +- x-pack/plugins/osquery/public/agents/types.ts | 2 +- .../actions/all/query.all_actions.dsl.ts | 2 +- .../plugins/osquery/server/usage/fetchers.ts | 2 +- .../server/routes/api/update_route.test.ts | 1 + .../server/deprecations/reporting_role.ts | 2 +- .../export_types/csv/execute_job.test.ts | 12 +- .../csv/generate_csv/hit_iterator.ts | 24 +- .../generate_csv/generate_csv.test.ts | 5 +- .../generate_csv/generate_csv.ts | 10 +- .../reporting/server/lib/content_stream.ts | 4 +- .../check_ilm_migration_status.ts | 2 +- .../server/lib/deprecations/index.ts | 2 +- .../lib/store/ilm_policy_manager/constants.ts | 2 +- .../ilm_policy_manager/ilm_policy_manager.ts | 4 +- .../reporting/server/lib/store/store.test.ts | 19 +- .../reporting/server/lib/store/store.ts | 4 +- .../server/lib/tasks/execute_report.ts | 2 +- .../reporting/server/routes/deprecations.ts | 2 +- .../reporting/server/routes/lib/jobs_query.ts | 19 +- .../server/usage/get_reporting_usage.ts | 2 +- .../common/mapping_from_field_map.ts | 2 +- x-pack/plugins/rule_registry/common/types.ts | 2 +- .../server/alert_data_client/alerts_client.ts | 7 +- .../rule_data_client/rule_data_client.ts | 8 +- .../server/rule_data_client/types.ts | 6 +- .../rule_data_plugin_service/index_options.ts | 2 +- .../resource_installer.ts | 8 +- .../server/utils/persistence_types.ts | 6 +- .../authentication/api_keys/api_keys.ts | 8 +- .../server/authorization/check_privileges.ts | 5 +- .../deprecations/kibana_user_role.test.ts | 2 +- .../server/deprecations/kibana_user_role.ts | 2 +- x-pack/plugins/security/server/errors.ts | 2 +- x-pack/plugins/security/server/mocks.ts | 10 +- .../deprecations/kibana_user_role.test.ts | 6 +- .../routes/deprecations/kibana_user_role.ts | 9 +- .../server/routes/indices/get_fields.ts | 6 +- .../data_generators/fleet_agent_generator.ts | 2 +- .../data_loaders/index_endpoint_actions.ts | 82 ++++--- .../data_loaders/index_endpoint_hosts.ts | 56 +++-- .../data_loaders/index_fleet_actions.ts | 64 +++-- .../data_loaders/index_fleet_agent.ts | 42 ++-- .../data_loaders/index_fleet_server.ts | 4 +- .../eql/validation/helpers.mock.ts | 6 +- .../security_solution/hosts/details/index.ts | 2 +- .../security_solution/index.ts | 2 +- .../exceptions/use_add_exception.test.tsx | 2 +- .../exceptions/use_add_exception.tsx | 2 +- .../hooks/eql/eql_search_response.mock.ts | 2 +- .../containers/detection_engine/alerts/api.ts | 2 +- .../alerts/use_fetch_ecs_alerts_data.ts | 2 +- .../components/authentications_table/mock.ts | 2 +- .../public/timelines/containers/index.tsx | 1 + .../endpoint/resolver_generator_script.ts | 8 +- .../migrate_artifacts_to_fleet.test.ts | 2 +- .../check_metadata_transforms_task.test.ts | 8 +- .../check_metadata_transforms_task.ts | 6 +- .../server/endpoint/routes/actions/mocks.ts | 4 +- .../endpoint/routes/metadata/handlers.ts | 6 +- .../routes/metadata/query_builders.ts | 2 +- .../metadata/support/query_strategies.ts | 2 +- .../routes/metadata/support/test_support.ts | 2 +- .../endpoint/routes/policy/handlers.test.ts | 2 +- .../resolver/tree/queries/descendants.ts | 5 +- .../server/endpoint/services/actions.ts | 12 +- .../endpoint/services/metadata/metadata.ts | 2 +- .../endpoint/utils/audit_log_helpers.ts | 16 +- .../migrations/migration_cleanup.ts | 10 +- .../notifications/utils.test.ts | 38 +-- .../routes/__mocks__/request_responses.ts | 2 +- .../routes/index/create_index_route.ts | 2 +- .../lib/detection_engine/rule_types/types.ts | 2 +- .../signals/build_events_query.ts | 2 +- .../signals/bulk_create_ml_signals.ts | 2 +- .../detection_engine/signals/executors/eql.ts | 4 +- .../signals/executors/threshold.ts | 2 +- .../signals/filters/filter_events.ts | 2 +- .../filters/filter_events_against_list.ts | 2 +- .../detection_engine/signals/filters/types.ts | 2 +- .../signals/search_after_bulk_create.test.ts | 4 +- .../signals/search_after_bulk_create.ts | 2 +- .../signals/signal_rule_alert_type.test.ts | 12 +- .../signals/single_search_after.test.ts | 2 +- .../signals/single_search_after.ts | 2 +- .../build_threat_mapping_filter.mock.ts | 2 +- .../signals/threat_mapping/get_threat_list.ts | 2 +- .../signals/threat_mapping/types.ts | 2 +- .../signals/threshold/build_signal_history.ts | 2 +- .../lib/detection_engine/signals/types.ts | 2 +- .../detection_engine/signals/utils.test.ts | 34 +-- .../lib/detection_engine/signals/utils.ts | 8 +- .../server/lib/machine_learning/index.ts | 2 +- .../server/lib/telemetry/receiver.ts | 2 +- .../security_solution/server/plugin.ts | 2 +- .../factory/cti/event_enrichment/helpers.ts | 2 +- .../hosts/authentications/dsl/query.dsl.ts | 2 +- .../authentications/dsl/query_entities.dsl.ts | 2 +- .../hosts/uncommon_processes/dsl/query.dsl.ts | 2 +- .../factory/network/http/index.ts | 1 - .../snapshot_restore/server/routes/api/app.ts | 2 + .../server/routes/api/policy.ts | 4 +- .../server/routes/api/repositories.ts | 26 +-- .../server/routes/api/restore.ts | 2 +- .../server/routes/api/snapshots.ts | 3 +- .../common/build_sorted_events_query.ts | 2 +- .../alert_types/es_query/expression.tsx | 2 +- .../alert_types/es_query/action_context.ts | 2 +- .../server/alert_types/es_query/alert_type.ts | 2 +- .../geo_containment/es_query_builder.ts | 5 +- .../geo_containment/geo_containment.ts | 2 +- .../monitoring/workload_statistics.test.ts | 2 +- .../server/monitoring/workload_statistics.ts | 2 +- .../mark_available_tasks_as_claimed.ts | 2 +- .../server/queries/query_clauses.ts | 2 +- .../server/saved_objects/index.ts | 2 +- .../task_manager/server/task_store.test.ts | 2 +- .../plugins/task_manager/server/task_store.ts | 2 +- .../telemetry_collection/get_license.ts | 2 +- .../get_stats_with_xpack.test.ts | 2 +- .../common/search_strategy/common/index.ts | 2 +- .../eql/validation/helpers.mock.ts | 6 +- .../public/container/use_update_alerts.ts | 2 +- .../common/api_schemas/type_guards.ts | 2 +- .../transform/public/app/common/request.ts | 2 +- .../public/app/hooks/__mocks__/use_api.ts | 2 +- .../transform/public/app/hooks/use_api.ts | 2 +- .../public/app/hooks/use_index_data.ts | 2 +- .../components/filter_term_form.tsx | 2 +- .../transform_health_service.ts | 5 +- .../transform/server/routes/api/privileges.ts | 1 + .../transform/server/routes/api/transforms.ts | 49 ++-- .../server/routes/api/transforms_nodes.ts | 1 + .../server/data/lib/time_series_query.test.ts | 2 +- .../server/data/lib/time_series_query.ts | 2 +- .../plugins/upgrade_assistant/common/types.ts | 9 +- .../server/lib/es_deprecations_status.test.ts | 10 +- .../server/lib/es_deprecations_status.ts | 13 +- .../server/lib/reindexing/index_settings.ts | 2 +- .../lib/reindexing/reindex_actions.test.ts | 6 +- .../lib/reindexing/reindex_service.test.ts | 10 +- .../server/lib/reindexing/reindex_service.ts | 4 +- .../server/lib/reindexing/types.ts | 4 +- .../server/routes/ml_snapshots.ts | 8 +- .../server/routes/update_index_settings.ts | 4 +- .../common/requests/get_certs_request_body.ts | 2 +- .../plugins/uptime/common/utils/es_search.ts | 2 +- .../monitor_list/use_monitor_histogram.ts | 2 +- x-pack/plugins/uptime/server/lib/lib.ts | 2 +- .../server/lib/requests/get_index_status.ts | 2 +- .../lib/requests/get_journey_details.ts | 2 +- .../lib/requests/get_journey_failed_steps.ts | 2 +- .../lib/requests/get_journey_screenshot.ts | 2 +- .../server/lib/requests/get_journey_steps.ts | 2 +- .../lib/requests/get_last_successful_step.ts | 2 +- .../server/lib/requests/get_latest_monitor.ts | 2 +- .../lib/requests/get_monitor_availability.ts | 2 - .../lib/requests/get_monitor_duration.ts | 2 +- .../server/lib/requests/get_monitor_status.ts | 2 +- .../server/lib/requests/get_network_events.ts | 2 +- .../uptime/server/lib/requests/get_pings.ts | 2 +- .../uptime/server/lib/requests/helper.ts | 5 +- .../fetch_all_from_scroll.test.js | 6 +- .../fetch_all_from_scroll.ts | 8 +- .../routes/api/indices/register_get_route.ts | 2 +- .../api/watches/register_delete_route.ts | 2 +- x-pack/test/accessibility/apps/helpers.ts | 39 ++-- .../apps/index_lifecycle_management.ts | 5 +- .../apps/ingest_node_pipelines.ts | 4 +- .../common/lib/es_test_index_tool.ts | 89 +++---- .../common/lib/task_manager_utils.ts | 32 +-- .../actions/builtin_action_types/es_index.ts | 10 +- .../es_index_preconfigured.ts | 10 +- .../tests/actions/execute.ts | 2 + .../tests/alerting/alerts.ts | 38 ++- .../tests/alerting/create.ts | 5 +- .../tests/alerting/enable.ts | 5 +- .../tests/alerting/rbac_legacy.ts | 20 +- .../tests/action_task_params/migrations.ts | 22 +- .../actions/builtin_action_types/es_index.ts | 8 +- .../preconfigured_alert_history_connector.ts | 9 +- .../spaces_only/tests/actions/enqueue.ts | 8 +- .../spaces_only/tests/actions/execute.ts | 9 +- .../spaces_only/tests/alerting/alerts_base.ts | 13 +- .../es_query/create_test_data.ts | 8 +- .../index_threshold/create_test_data.ts | 13 +- .../spaces_only/tests/alerting/create.ts | 16 +- .../spaces_only/tests/alerting/enable.ts | 5 +- .../spaces_only/tests/alerting/ephemeral.ts | 1 + .../spaces_only/tests/alerting/migrations.ts | 58 +++-- .../apis/es/post_privileges.ts | 6 +- .../api_integration/apis/lens/telemetry.ts | 17 +- .../apis/logstash/cluster/load.ts | 2 +- .../lib/elasticsearch.js | 18 +- .../index_management/lib/elasticsearch.js | 10 +- .../ingest_pipelines/lib/elasticsearch.ts | 9 +- .../snapshot_restore/lib/elasticsearch.ts | 53 ++--- .../apis/metrics_ui/metric_threshold_alert.ts | 28 ++- .../apis/metrics_ui/metrics_alerting.ts | 12 +- .../apis/ml/calendars/helpers.ts | 2 +- .../apis/ml/job_audit_messages/index.ts | 2 +- .../datafeed_preview_validation.ts | 2 +- .../apis/monitoring/common/mappings_exist.js | 2 +- .../apis/security/index_fields.ts | 2 +- .../api_integration/apis/security/roles.ts | 19 +- .../api_integration/apis/security/users.ts | 4 +- .../apis/security_solution/utils.ts | 40 ++-- .../telemetry/telemetry_optin_notice_seen.ts | 4 +- .../upgrade_assistant/upgrade_assistant.ts | 2 +- .../apis/uptime/rest/helper/make_checks.ts | 8 +- .../apis/uptime/rest/helper/make_ping.ts | 4 +- .../common/synthtrace_es_client.ts | 2 +- .../tests/alerts/rule_registry.ts | 11 +- .../tests/metadata/event_metadata.ts | 2 +- .../service_overview/dependencies/es_utils.ts | 2 +- .../service_overview/dependencies/index.ts | 2 +- .../tests/services/annotations.ts | 10 +- .../tests/services/derived_annotations.ts | 2 +- .../case_api_integration/common/lib/utils.ts | 100 ++++---- .../tests/common/cases/find_cases.ts | 5 +- .../tests/common/sub_cases/find_sub_cases.ts | 5 +- .../basic/tests/open_close_signals.ts | 2 +- .../basic/tests/update_rac_alerts.ts | 2 +- .../tests/alerts/alerts_compatibility.ts | 2 +- .../tests/create_signals_migrations.ts | 2 +- .../tests/delete_signals_migrations.ts | 5 +- .../security_and_spaces/tests/migrations.ts | 48 ++-- .../tests/open_close_signals.ts | 2 +- .../detection_engine_api_integration/utils.ts | 71 +++--- .../tests/encrypted_saved_objects_api.ts | 4 +- .../search_examples/search_session_example.ts | 2 +- .../agent_policy_with_agents_setup.ts | 2 +- .../apis/agents/services.ts | 9 +- .../apis/agents/unenroll.ts | 16 +- .../apis/data_streams/list.ts | 25 +- .../apis/enrollment_api_keys/crud.ts | 29 +-- .../apis/epm/data_stream.ts | 138 ++++++----- .../apis/epm/final_pipeline.ts | 28 +-- .../fleet_api_integration/apis/epm/ilm.ts | 13 +- .../apis/epm/install_endpoint.ts | 27 ++- .../apis/epm/install_overrides.ts | 71 +++--- .../apis/epm/install_remove_assets.ts | 127 ++++++---- .../fleet_api_integration/apis/epm/setup.ts | 2 +- .../apis/epm/template.ts | 24 +- .../apis/epm/update_assets.ts | 114 +++++---- .../apis/service_tokens.ts | 11 +- .../apis/settings/update.ts | 2 +- .../index_lifecycle_management/home_page.ts | 3 +- .../apps/rollup_job/hybrid_index_pattern.js | 2 +- .../apps/snapshot_restore/home_page.ts | 4 +- x-pack/test/functional/apps/watcher/index.js | 1 - x-pack/test/functional/services/ml/api.ts | 26 +-- .../test/functional/services/transform/api.ts | 18 +- .../apps/ml/alert_flyout.ts | 2 +- .../trial/tests/annotations.ts | 18 +- .../performance/tests/reporting_dashboard.ts | 3 +- .../event_log/service_api_integration.ts | 2 +- .../test_suites/task_manager/migrations.ts | 38 +-- .../task_manager/task_management.ts | 6 +- .../ilm_migration_apis.ts | 11 +- .../common/lib/create_users_and_roles.ts | 4 +- .../common/lib/saved_object_test_utils.ts | 6 +- .../common/suites/import.ts | 8 +- .../common/suites/resolve_import_errors.ts | 4 +- .../test/saved_objects_field_count/runner.ts | 4 +- .../dashboard/async_search/async_search.ts | 2 +- .../async_search/save_search_session.ts | 2 +- .../async_search/search_sessions_tour.ts | 2 +- .../tests/http_bearer/header.ts | 4 +- .../tests/kerberos/kerberos_login.ts | 2 +- .../oidc/authorization_code_flow/oidc_auth.ts | 2 +- .../tests/saml/saml_login.ts | 4 +- .../tests/session_idle/cleanup.ts | 2 +- .../tests/session_lifespan/cleanup.ts | 2 +- .../tests/token/header.ts | 4 +- .../tests/token/session.ts | 2 +- .../services/endpoint.ts | 6 +- .../apis/package.ts | 27 ++- .../services/resolver.ts | 2 +- .../common/lib/create_users_and_roles.ts | 4 +- .../common/lib/space_test_utils.ts | 4 +- .../common/suites/copy_to_space.ts | 8 +- .../common/suites/delete.ts | 12 +- .../suites/disable_legacy_url_aliases.ts | 6 +- .../apps/reporting/util.js | 8 +- .../upgrade_assistant/reindexing.js | 18 +- yarn.lock | 44 +++- 814 files changed, 3045 insertions(+), 3350 deletions(-) create mode 100644 docs/development/core/server/kibana-plugin-core-server.elasticsearcherrordetails.error.md create mode 100644 docs/development/core/server/kibana-plugin-core-server.elasticsearcherrordetails.md delete mode 100644 docs/development/core/server/kibana-plugin-core-server.savedobjectserrorhelpers.creategenericnotfoundesunavailableerror.md create mode 100644 packages/kbn-test/src/es/client_to_kibana_client.ts delete mode 100644 src/core/server/elasticsearch/supported_server_response_check.test.ts delete mode 100644 src/core/server/elasticsearch/supported_server_response_check.ts diff --git a/docs/development/core/server/kibana-plugin-core-server.elasticsearchclient.md b/docs/development/core/server/kibana-plugin-core-server.elasticsearchclient.md index 279262aa6a5ec..f6190fb3bc055 100644 --- a/docs/development/core/server/kibana-plugin-core-server.elasticsearchclient.md +++ b/docs/development/core/server/kibana-plugin-core-server.elasticsearchclient.md @@ -9,9 +9,9 @@ Client used to query the elasticsearch cluster. Signature: ```typescript -export declare type ElasticsearchClient = Omit & { +export declare type ElasticsearchClient = Omit & { transport: { - request(params: TransportRequestParams, options?: TransportRequestOptions): TransportRequestPromise; + request(params: TransportRequestParams, options?: TransportRequestOptions): Promise>; }; }; ``` diff --git a/docs/development/core/server/kibana-plugin-core-server.elasticsearcherrordetails.error.md b/docs/development/core/server/kibana-plugin-core-server.elasticsearcherrordetails.error.md new file mode 100644 index 0000000000000..7191caea54929 --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.elasticsearcherrordetails.error.md @@ -0,0 +1,14 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ElasticsearchErrorDetails](./kibana-plugin-core-server.elasticsearcherrordetails.md) > [error](./kibana-plugin-core-server.elasticsearcherrordetails.error.md) + +## ElasticsearchErrorDetails.error property + +Signature: + +```typescript +error?: { + type: string; + reason?: string; + }; +``` diff --git a/docs/development/core/server/kibana-plugin-core-server.elasticsearcherrordetails.md b/docs/development/core/server/kibana-plugin-core-server.elasticsearcherrordetails.md new file mode 100644 index 0000000000000..7dbf9e89f9b7c --- /dev/null +++ b/docs/development/core/server/kibana-plugin-core-server.elasticsearcherrordetails.md @@ -0,0 +1,19 @@ + + +[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [ElasticsearchErrorDetails](./kibana-plugin-core-server.elasticsearcherrordetails.md) + +## ElasticsearchErrorDetails interface + + +Signature: + +```typescript +export interface ElasticsearchErrorDetails +``` + +## Properties + +| Property | Type | Description | +| --- | --- | --- | +| [error](./kibana-plugin-core-server.elasticsearcherrordetails.error.md) | {
type: string;
reason?: string;
} | | + diff --git a/docs/development/core/server/kibana-plugin-core-server.md b/docs/development/core/server/kibana-plugin-core-server.md index 3970cf005abe4..f22a0fb8283d7 100644 --- a/docs/development/core/server/kibana-plugin-core-server.md +++ b/docs/development/core/server/kibana-plugin-core-server.md @@ -71,6 +71,7 @@ The plugin integrates with the core system via lifecycle events: `setup` | [DeprecationsServiceSetup](./kibana-plugin-core-server.deprecationsservicesetup.md) | The deprecations service provides a way for the Kibana platform to communicate deprecated features and configs with its users. These deprecations are only communicated if the deployment is using these features. Allowing for a user tailored experience for upgrading the stack version.The Deprecation service is consumed by the upgrade assistant to assist with the upgrade experience.If a deprecated feature can be resolved without manual user intervention. Using correctiveActions.api allows the Upgrade Assistant to use this api to correct the deprecation upon a user trigger. | | [DiscoveredPlugin](./kibana-plugin-core-server.discoveredplugin.md) | Small container object used to expose information about discovered plugins that may or may not have been started. | | [ElasticsearchConfigPreboot](./kibana-plugin-core-server.elasticsearchconfigpreboot.md) | A limited set of Elasticsearch configuration entries exposed to the preboot plugins at setup. | +| [ElasticsearchErrorDetails](./kibana-plugin-core-server.elasticsearcherrordetails.md) | | | [ElasticsearchServicePreboot](./kibana-plugin-core-server.elasticsearchservicepreboot.md) | | | [ElasticsearchServiceSetup](./kibana-plugin-core-server.elasticsearchservicesetup.md) | | | [ElasticsearchServiceStart](./kibana-plugin-core-server.elasticsearchservicestart.md) | | diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectserrorhelpers.creategenericnotfoundesunavailableerror.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectserrorhelpers.creategenericnotfoundesunavailableerror.md deleted file mode 100644 index e17877a537d00..0000000000000 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectserrorhelpers.creategenericnotfoundesunavailableerror.md +++ /dev/null @@ -1,23 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-server](./kibana-plugin-core-server.md) > [SavedObjectsErrorHelpers](./kibana-plugin-core-server.savedobjectserrorhelpers.md) > [createGenericNotFoundEsUnavailableError](./kibana-plugin-core-server.savedobjectserrorhelpers.creategenericnotfoundesunavailableerror.md) - -## SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError() method - -Signature: - -```typescript -static createGenericNotFoundEsUnavailableError(type?: string | null, id?: string | null): DecoratedError; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| type | string | null | | -| id | string | null | | - -Returns: - -`DecoratedError` - diff --git a/docs/development/core/server/kibana-plugin-core-server.savedobjectserrorhelpers.md b/docs/development/core/server/kibana-plugin-core-server.savedobjectserrorhelpers.md index 67056c8a3cb50..2dc78f2df3a83 100644 --- a/docs/development/core/server/kibana-plugin-core-server.savedobjectserrorhelpers.md +++ b/docs/development/core/server/kibana-plugin-core-server.savedobjectserrorhelpers.md @@ -18,7 +18,6 @@ export declare class SavedObjectsErrorHelpers | [createBadRequestError(reason)](./kibana-plugin-core-server.savedobjectserrorhelpers.createbadrequesterror.md) | static | | | [createConflictError(type, id, reason)](./kibana-plugin-core-server.savedobjectserrorhelpers.createconflicterror.md) | static | | | [createGenericNotFoundError(type, id)](./kibana-plugin-core-server.savedobjectserrorhelpers.creategenericnotfounderror.md) | static | | -| [createGenericNotFoundEsUnavailableError(type, id)](./kibana-plugin-core-server.savedobjectserrorhelpers.creategenericnotfoundesunavailableerror.md) | static | | | [createIndexAliasNotFoundError(alias)](./kibana-plugin-core-server.savedobjectserrorhelpers.createindexaliasnotfounderror.md) | static | | | [createInvalidVersionError(versionInput)](./kibana-plugin-core-server.savedobjectserrorhelpers.createinvalidversionerror.md) | static | | | [createTooManyRequestsError(type, id)](./kibana-plugin-core-server.savedobjectserrorhelpers.createtoomanyrequestserror.md) | static | | diff --git a/package.json b/package.json index 1f2102f3aff2e..37590371bde73 100644 --- a/package.json +++ b/package.json @@ -100,7 +100,7 @@ "@elastic/apm-rum-react": "^1.3.1", "@elastic/charts": "38.0.1", "@elastic/datemath": "link:bazel-bin/packages/elastic-datemath", - "@elastic/elasticsearch": "npm:@elastic/elasticsearch-canary@^8.0.0-canary.21", + "@elastic/elasticsearch": "npm:@elastic/elasticsearch-canary@^8.0.0-canary.35", "@elastic/ems-client": "7.16.0", "@elastic/eui": "40.0.0", "@elastic/filesaver": "1.1.2", diff --git a/packages/elastic-apm-synthtrace/src/scripts/utils/clean_write_targets.ts b/packages/elastic-apm-synthtrace/src/scripts/utils/clean_write_targets.ts index efa24f164d51e..3c514e1097b31 100644 --- a/packages/elastic-apm-synthtrace/src/scripts/utils/clean_write_targets.ts +++ b/packages/elastic-apm-synthtrace/src/scripts/utils/clean_write_targets.ts @@ -35,7 +35,7 @@ export async function cleanWriteTargets({ wait_for_completion: false, }); - const task = response.body.task; + const task = response.task; if (task) { await new Promise((resolve, reject) => { @@ -45,13 +45,13 @@ export async function cleanWriteTargets({ }); logger.debug( - `Polled for task:\n${JSON.stringify(taskResponse.body, ['completed', 'error'], 2)}` + `Polled for task:\n${JSON.stringify(taskResponse, ['completed', 'error'], 2)}` ); - if (taskResponse.body.completed) { + if (taskResponse.completed) { resolve(); - } else if (taskResponse.body.error) { - reject(taskResponse.body.error); + } else if (taskResponse.error) { + reject(taskResponse.error); } else { setTimeout(pollForTaskCompletion, 2500); } diff --git a/packages/elastic-apm-synthtrace/src/scripts/utils/get_write_targets.ts b/packages/elastic-apm-synthtrace/src/scripts/utils/get_write_targets.ts index 7cbba4e735750..fbe11d295e099 100644 --- a/packages/elastic-apm-synthtrace/src/scripts/utils/get_write_targets.ts +++ b/packages/elastic-apm-synthtrace/src/scripts/utils/get_write_targets.ts @@ -24,16 +24,15 @@ export async function getWriteTargets({ ]); function getDataStreamName(filter: string) { - return datastreamsResponse.body.data_streams.find((stream) => stream.name.includes(filter)) - ?.name; + return datastreamsResponse.data_streams.find((stream) => stream.name.includes(filter))?.name; } function getAlias(filter: string) { - return Object.keys(indicesResponse.body) + return Object.keys(indicesResponse) .map((key) => { return { key, - writeIndexAlias: Object.entries(indicesResponse.body[key].aliases).find( + writeIndexAlias: Object.entries(indicesResponse[key].aliases).find( ([_, alias]) => alias.is_write_index )?.[0], }; diff --git a/packages/elastic-apm-synthtrace/src/scripts/utils/upload_events.ts b/packages/elastic-apm-synthtrace/src/scripts/utils/upload_events.ts index ada9f73b09e39..72258ec2815a8 100644 --- a/packages/elastic-apm-synthtrace/src/scripts/utils/upload_events.ts +++ b/packages/elastic-apm-synthtrace/src/scripts/utils/upload_events.ts @@ -59,7 +59,7 @@ export function uploadEvents({ ) .then((results) => { const errors = results - .flatMap((result) => result.body.items) + .flatMap((result) => result.items) .filter((item) => !!item.index?.error) .map((item) => item.index?.error); diff --git a/packages/kbn-apm-config-loader/src/init_apm.test.ts b/packages/kbn-apm-config-loader/src/init_apm.test.ts index 95f0a15a448c8..6781b1b8b807e 100644 --- a/packages/kbn-apm-config-loader/src/init_apm.test.ts +++ b/packages/kbn-apm-config-loader/src/init_apm.test.ts @@ -11,7 +11,8 @@ import { mockLoadConfiguration } from './init_apm.test.mocks'; import { initApm } from './init_apm'; import apm from 'elastic-apm-node'; -describe('initApm', () => { +// TODO: unskip when https://github.com/elastic/kibana/issues/116109 is fixed +describe.skip('initApm', () => { let apmAddFilterSpy: jest.SpyInstance; let apmStartSpy: jest.SpyInstance; let getConfig: jest.Mock; diff --git a/packages/kbn-apm-config-loader/src/init_apm.ts b/packages/kbn-apm-config-loader/src/init_apm.ts index 21c40c8b39419..33609c2493396 100644 --- a/packages/kbn-apm-config-loader/src/init_apm.ts +++ b/packages/kbn-apm-config-loader/src/init_apm.ts @@ -14,6 +14,9 @@ export const initApm = ( isDistributable: boolean, serviceName: string ) => { + // TODO: re-enabled when https://github.com/elastic/kibana/issues/116109 is fixed + return; + const apmConfigLoader = loadConfiguration(argv, rootDir, isDistributable); const apmConfig = apmConfigLoader.getConfig(serviceName); diff --git a/packages/kbn-es-archiver/src/actions/empty_kibana_index.ts b/packages/kbn-es-archiver/src/actions/empty_kibana_index.ts index 24a1de10b2b1d..96b5b5f8e98e5 100644 --- a/packages/kbn-es-archiver/src/actions/empty_kibana_index.ts +++ b/packages/kbn-es-archiver/src/actions/empty_kibana_index.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import type { Client } from '@elastic/elasticsearch'; import { ToolingLog } from '@kbn/dev-utils'; import { KbnClient } from '@kbn/test'; @@ -17,7 +17,7 @@ export async function emptyKibanaIndexAction({ log, kbnClient, }: { - client: KibanaClient; + client: Client; log: ToolingLog; kbnClient: KbnClient; }) { diff --git a/packages/kbn-es-archiver/src/actions/load.ts b/packages/kbn-es-archiver/src/actions/load.ts index 673fa7e7d96c8..619c946f0c988 100644 --- a/packages/kbn-es-archiver/src/actions/load.ts +++ b/packages/kbn-es-archiver/src/actions/load.ts @@ -11,7 +11,7 @@ import { createReadStream } from 'fs'; import { Readable } from 'stream'; import { ToolingLog, REPO_ROOT } from '@kbn/dev-utils'; import { KbnClient } from '@kbn/test'; -import type { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import type { Client } from '@elastic/elasticsearch'; import { createPromiseFromStreams, concatStreamProviders } from '@kbn/utils'; import { ES_CLIENT_HEADERS } from '../client_headers'; @@ -47,7 +47,7 @@ export async function loadAction({ inputDir: string; skipExisting: boolean; useCreate: boolean; - client: KibanaClient; + client: Client; log: ToolingLog; kbnClient: KbnClient; }) { diff --git a/packages/kbn-es-archiver/src/actions/save.ts b/packages/kbn-es-archiver/src/actions/save.ts index da0966920de24..07ed2b206c1dd 100644 --- a/packages/kbn-es-archiver/src/actions/save.ts +++ b/packages/kbn-es-archiver/src/actions/save.ts @@ -9,7 +9,7 @@ import { resolve, relative } from 'path'; import { createWriteStream, mkdirSync } from 'fs'; import { Readable, Writable } from 'stream'; -import type { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import type { Client } from '@elastic/elasticsearch'; import { ToolingLog, REPO_ROOT } from '@kbn/dev-utils'; import { createListStream, createPromiseFromStreams } from '@kbn/utils'; @@ -31,7 +31,7 @@ export async function saveAction({ }: { outputDir: string; indices: string | string[]; - client: KibanaClient; + client: Client; log: ToolingLog; raw: boolean; query?: Record; diff --git a/packages/kbn-es-archiver/src/actions/unload.ts b/packages/kbn-es-archiver/src/actions/unload.ts index 98bae36095b88..1c5f4cd5d7d03 100644 --- a/packages/kbn-es-archiver/src/actions/unload.ts +++ b/packages/kbn-es-archiver/src/actions/unload.ts @@ -9,7 +9,7 @@ import { resolve, relative } from 'path'; import { createReadStream } from 'fs'; import { Readable, Writable } from 'stream'; -import type { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import type { Client } from '@elastic/elasticsearch'; import { ToolingLog, REPO_ROOT } from '@kbn/dev-utils'; import { KbnClient } from '@kbn/test'; import { createPromiseFromStreams } from '@kbn/utils'; @@ -31,7 +31,7 @@ export async function unloadAction({ kbnClient, }: { inputDir: string; - client: KibanaClient; + client: Client; log: ToolingLog; kbnClient: KbnClient; }) { diff --git a/packages/kbn-es-archiver/src/cli.ts b/packages/kbn-es-archiver/src/cli.ts index 8e4a879282765..db54a3bade74b 100644 --- a/packages/kbn-es-archiver/src/cli.ts +++ b/packages/kbn-es-archiver/src/cli.ts @@ -19,7 +19,7 @@ import Fs from 'fs'; import { RunWithCommands, createFlagError, CA_CERT_PATH } from '@kbn/dev-utils'; import { readConfigFile, KbnClient } from '@kbn/test'; -import { Client } from '@elastic/elasticsearch'; +import { Client, HttpConnection } from '@elastic/elasticsearch'; import { EsArchiver } from './es_archiver'; @@ -106,7 +106,8 @@ export function runCli() { const client = new Client({ node: esUrl, - ssl: esCa ? { ca: esCa } : undefined, + tls: esCa ? { ca: esCa } : undefined, + Connection: HttpConnection, }); addCleanupTask(() => client.close()); diff --git a/packages/kbn-es-archiver/src/es_archiver.ts b/packages/kbn-es-archiver/src/es_archiver.ts index 06a56b79e3012..ed27bc0afcf34 100644 --- a/packages/kbn-es-archiver/src/es_archiver.ts +++ b/packages/kbn-es-archiver/src/es_archiver.ts @@ -9,7 +9,7 @@ import Fs from 'fs'; import Path from 'path'; -import type { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import type { Client } from '@elastic/elasticsearch'; import { ToolingLog, REPO_ROOT } from '@kbn/dev-utils'; import { KbnClient } from '@kbn/test'; @@ -23,14 +23,14 @@ import { } from './actions'; interface Options { - client: KibanaClient; + client: Client; baseDir?: string; log: ToolingLog; kbnClient: KbnClient; } export class EsArchiver { - private readonly client: KibanaClient; + private readonly client: Client; private readonly baseDir: string; private readonly log: ToolingLog; private readonly kbnClient: KbnClient; diff --git a/packages/kbn-es-archiver/src/lib/docs/generate_doc_records_stream.test.ts b/packages/kbn-es-archiver/src/lib/docs/generate_doc_records_stream.test.ts index da7ed4c81b666..2902812f51493 100644 --- a/packages/kbn-es-archiver/src/lib/docs/generate_doc_records_stream.test.ts +++ b/packages/kbn-es-archiver/src/lib/docs/generate_doc_records_stream.test.ts @@ -99,10 +99,8 @@ it('transforms each input index to a stream of docs using scrollSearch helper', Array [ Object { "_source": "true", - "body": Object { - "query": undefined, - }, "index": "bar", + "query": undefined, "rest_total_hits_as_int": true, "scroll": "1m", "size": 1000, @@ -116,10 +114,8 @@ it('transforms each input index to a stream of docs using scrollSearch helper', Array [ Object { "_source": "true", - "body": Object { - "query": undefined, - }, "index": "foo", + "query": undefined, "rest_total_hits_as_int": true, "scroll": "1m", "size": 1000, diff --git a/packages/kbn-es-archiver/src/lib/docs/generate_doc_records_stream.ts b/packages/kbn-es-archiver/src/lib/docs/generate_doc_records_stream.ts index 88e167b3705cb..a0636d6a3f76a 100644 --- a/packages/kbn-es-archiver/src/lib/docs/generate_doc_records_stream.ts +++ b/packages/kbn-es-archiver/src/lib/docs/generate_doc_records_stream.ts @@ -7,7 +7,7 @@ */ import { Transform } from 'stream'; -import type { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import type { Client } from '@elastic/elasticsearch'; import { Stats } from '../stats'; import { Progress } from '../progress'; import { ES_CLIENT_HEADERS } from '../../client_headers'; @@ -21,7 +21,7 @@ export function createGenerateDocRecordsStream({ progress, query, }: { - client: KibanaClient; + client: Client; stats: Stats; progress: Progress; query?: Record; @@ -37,9 +37,7 @@ export function createGenerateDocRecordsStream({ scroll: SCROLL_TIMEOUT, size: SCROLL_SIZE, _source: 'true', - body: { - query, - }, + query, rest_total_hits_as_int: true, }, { diff --git a/packages/kbn-es-archiver/src/lib/docs/index_doc_records_stream.ts b/packages/kbn-es-archiver/src/lib/docs/index_doc_records_stream.ts index 028ff16c9afb2..749bfd0872353 100644 --- a/packages/kbn-es-archiver/src/lib/docs/index_doc_records_stream.ts +++ b/packages/kbn-es-archiver/src/lib/docs/index_doc_records_stream.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import type { Client } from '@elastic/elasticsearch'; import AggregateError from 'aggregate-error'; import { Writable } from 'stream'; import { Stats } from '../stats'; @@ -14,7 +14,7 @@ import { Progress } from '../progress'; import { ES_CLIENT_HEADERS } from '../../client_headers'; export function createIndexDocRecordsStream( - client: KibanaClient, + client: Client, stats: Stats, progress: Progress, useCreate: boolean = false diff --git a/packages/kbn-es-archiver/src/lib/indices/__mocks__/stubs.ts b/packages/kbn-es-archiver/src/lib/indices/__mocks__/stubs.ts index 7dde4075dc3f2..ded56ddfdf0de 100644 --- a/packages/kbn-es-archiver/src/lib/indices/__mocks__/stubs.ts +++ b/packages/kbn-es-archiver/src/lib/indices/__mocks__/stubs.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import type { Client } from '@elastic/elasticsearch'; import sinon from 'sinon'; import { ToolingLog } from '@kbn/dev-utils'; import { Stats } from '../../stats'; @@ -67,7 +67,7 @@ const createEsClientError = (errorType: string) => { const indexAlias = (aliases: Record, index: string) => Object.keys(aliases).find((k) => aliases[k] === index); -type StubClient = KibanaClient; +type StubClient = Client; export const createStubClient = ( existingIndices: string[] = [], diff --git a/packages/kbn-es-archiver/src/lib/indices/create_index_stream.test.ts b/packages/kbn-es-archiver/src/lib/indices/create_index_stream.test.ts index 28c8ccd1c28a8..3a8180b724e07 100644 --- a/packages/kbn-es-archiver/src/lib/indices/create_index_stream.test.ts +++ b/packages/kbn-es-archiver/src/lib/indices/create_index_stream.test.ts @@ -71,6 +71,7 @@ describe('esArchiver: createCreateIndexStream()', () => { "ignore": Array [ 404, ], + "meta": true, }, ], ] diff --git a/packages/kbn-es-archiver/src/lib/indices/create_index_stream.ts b/packages/kbn-es-archiver/src/lib/indices/create_index_stream.ts index fba3df24e896f..50d13fc728c79 100644 --- a/packages/kbn-es-archiver/src/lib/indices/create_index_stream.ts +++ b/packages/kbn-es-archiver/src/lib/indices/create_index_stream.ts @@ -9,8 +9,8 @@ import { Transform, Readable } from 'stream'; import { inspect } from 'util'; -import { estypes } from '@elastic/elasticsearch'; -import type { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { Client } from '@elastic/elasticsearch'; import { ToolingLog } from '@kbn/dev-utils'; import { Stats } from '../stats'; @@ -31,7 +31,7 @@ export function createCreateIndexStream({ skipExisting = false, log, }: { - client: KibanaClient; + client: Client; stats: Stats; skipExisting?: boolean; log: ToolingLog; diff --git a/packages/kbn-es-archiver/src/lib/indices/delete_index.ts b/packages/kbn-es-archiver/src/lib/indices/delete_index.ts index d3d6f85d7a360..3bba96d32ba95 100644 --- a/packages/kbn-es-archiver/src/lib/indices/delete_index.ts +++ b/packages/kbn-es-archiver/src/lib/indices/delete_index.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import type { Client } from '@elastic/elasticsearch'; import { ToolingLog } from '@kbn/dev-utils'; import { Stats } from '../stats'; import { ES_CLIENT_HEADERS } from '../../client_headers'; @@ -15,7 +15,7 @@ import { ES_CLIENT_HEADERS } from '../../client_headers'; const PENDING_SNAPSHOT_STATUSES = ['INIT', 'STARTED', 'WAITING']; export async function deleteIndex(options: { - client: KibanaClient; + client: Client; stats: Stats; index: string | string[]; log: ToolingLog; @@ -32,6 +32,7 @@ export async function deleteIndex(options: { { ignore: [404], headers: ES_CLIENT_HEADERS, + meta: true, } ); @@ -84,15 +85,13 @@ export function isDeleteWhileSnapshotInProgressError(error: any) { * snapshotting this index to complete. */ export async function waitForSnapshotCompletion( - client: KibanaClient, + client: Client, index: string | string[], log: ToolingLog ) { const isSnapshotPending = async (repository: string, snapshot: string) => { const { - body: { - snapshots: [status], - }, + snapshots: [status], } = await client.snapshot.status( { repository, @@ -108,9 +107,7 @@ export async function waitForSnapshotCompletion( }; const getInProgressSnapshots = async (repository: string) => { - const { - body: { snapshots: inProgressSnapshots }, - } = await client.snapshot.get( + const { snapshots: inProgressSnapshots } = await client.snapshot.get( { repository, snapshot: '_current', @@ -123,7 +120,7 @@ export async function waitForSnapshotCompletion( return inProgressSnapshots; }; - const { body: repositoryMap } = await client.snapshot.getRepository({} as any); + const repositoryMap = await client.snapshot.getRepository({}); for (const repository of Object.keys(repositoryMap)) { const allInProgress = await getInProgressSnapshots(repository); const found = allInProgress?.find((s: any) => s.indices.includes(index)); diff --git a/packages/kbn-es-archiver/src/lib/indices/delete_index_stream.ts b/packages/kbn-es-archiver/src/lib/indices/delete_index_stream.ts index 7765419bb9d15..e7763ca251e6f 100644 --- a/packages/kbn-es-archiver/src/lib/indices/delete_index_stream.ts +++ b/packages/kbn-es-archiver/src/lib/indices/delete_index_stream.ts @@ -7,14 +7,14 @@ */ import { Transform } from 'stream'; -import type { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import type { Client } from '@elastic/elasticsearch'; import { ToolingLog } from '@kbn/dev-utils'; import { Stats } from '../stats'; import { deleteIndex } from './delete_index'; import { cleanKibanaIndices } from './kibana_index'; -export function createDeleteIndexStream(client: KibanaClient, stats: Stats, log: ToolingLog) { +export function createDeleteIndexStream(client: Client, stats: Stats, log: ToolingLog) { return new Transform({ readableObjectMode: true, writableObjectMode: true, diff --git a/packages/kbn-es-archiver/src/lib/indices/generate_index_records_stream.ts b/packages/kbn-es-archiver/src/lib/indices/generate_index_records_stream.ts index 6619f1b3a601e..d647a4fe5f501 100644 --- a/packages/kbn-es-archiver/src/lib/indices/generate_index_records_stream.ts +++ b/packages/kbn-es-archiver/src/lib/indices/generate_index_records_stream.ts @@ -6,12 +6,12 @@ * Side Public License, v 1. */ +import type { Client } from '@elastic/elasticsearch'; import { Transform } from 'stream'; -import type { KibanaClient } from '@elastic/elasticsearch/api/kibana'; import { Stats } from '../stats'; import { ES_CLIENT_HEADERS } from '../../client_headers'; -export function createGenerateIndexRecordsStream(client: KibanaClient, stats: Stats) { +export function createGenerateIndexRecordsStream(client: Client, stats: Stats) { return new Transform({ writableObjectMode: true, readableObjectMode: true, @@ -37,9 +37,10 @@ export function createGenerateIndexRecordsStream(client: KibanaClient, stats: St }, { headers: ES_CLIENT_HEADERS, + meta: true, } ) - ).body as Record; + ).body; for (const [index, { settings, mappings }] of Object.entries(resp)) { const { @@ -50,6 +51,7 @@ export function createGenerateIndexRecordsStream(client: KibanaClient, stats: St { index }, { headers: ES_CLIENT_HEADERS, + meta: true, } ); diff --git a/packages/kbn-es-archiver/src/lib/indices/kibana_index.ts b/packages/kbn-es-archiver/src/lib/indices/kibana_index.ts index 635e432468846..069db636c596b 100644 --- a/packages/kbn-es-archiver/src/lib/indices/kibana_index.ts +++ b/packages/kbn-es-archiver/src/lib/indices/kibana_index.ts @@ -8,7 +8,7 @@ import { inspect } from 'util'; -import type { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import type { Client } from '@elastic/elasticsearch'; import { ToolingLog } from '@kbn/dev-utils'; import { KbnClient } from '@kbn/test'; import { Stats } from '../stats'; @@ -23,7 +23,7 @@ export async function deleteKibanaIndices({ stats, log, }: { - client: KibanaClient; + client: Client; stats: Stats; log: ToolingLog; }) { @@ -35,7 +35,7 @@ export async function deleteKibanaIndices({ await client.indices.putSettings( { index: indexNames, - body: { settings: { blocks: { read_only: false } } }, + body: { blocks: { read_only: false } }, }, { headers: ES_CLIENT_HEADERS, @@ -75,7 +75,7 @@ function isKibanaIndex(index?: string): index is string { ); } -async function fetchKibanaIndices(client: KibanaClient) { +async function fetchKibanaIndices(client: Client) { const resp = await client.cat.indices( { index: '.kibana*', format: 'json' }, { @@ -83,11 +83,11 @@ async function fetchKibanaIndices(client: KibanaClient) { } ); - if (!Array.isArray(resp.body)) { - throw new Error(`expected response to be an array ${inspect(resp.body)}`); + if (!Array.isArray(resp)) { + throw new Error(`expected response to be an array ${inspect(resp)}`); } - return resp.body.map((x: { index?: string }) => x.index).filter(isKibanaIndex); + return resp.map((x: { index?: string }) => x.index).filter(isKibanaIndex); } const delay = (delayInMs: number) => new Promise((resolve) => setTimeout(resolve, delayInMs)); @@ -97,7 +97,7 @@ export async function cleanKibanaIndices({ stats, log, }: { - client: KibanaClient; + client: Client; stats: Stats; log: ToolingLog; }) { @@ -123,11 +123,11 @@ export async function cleanKibanaIndices({ } ); - if (resp.body.total !== resp.body.deleted) { + if (resp.total !== resp.deleted) { log.warning( 'delete by query deleted %d of %d total documents, trying again', - resp.body.deleted, - resp.body.total + resp.deleted, + resp.total ); await delay(200); continue; @@ -144,13 +144,7 @@ export async function cleanKibanaIndices({ stats.deletedIndex('.kibana'); } -export async function createDefaultSpace({ - index, - client, -}: { - index: string; - client: KibanaClient; -}) { +export async function createDefaultSpace({ index, client }: { index: string; client: Client }) { await client.create( { index, diff --git a/packages/kbn-es-query/src/es_query/decorate_query.ts b/packages/kbn-es-query/src/es_query/decorate_query.ts index e5bcf01a45915..a58eca575f4bf 100644 --- a/packages/kbn-es-query/src/es_query/decorate_query.ts +++ b/packages/kbn-es-query/src/es_query/decorate_query.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { SerializableRecord } from '@kbn/utility-types'; import { extend, defaults } from 'lodash'; import { getTimeZoneFromSettings } from '../utils'; diff --git a/packages/kbn-es-query/src/es_query/from_filters.ts b/packages/kbn-es-query/src/es_query/from_filters.ts index ac6c8a4a6b2b8..28d8653246e3d 100644 --- a/packages/kbn-es-query/src/es_query/from_filters.ts +++ b/packages/kbn-es-query/src/es_query/from_filters.ts @@ -7,7 +7,7 @@ */ import { isUndefined } from 'lodash'; -import { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { migrateFilter } from './migrate_filter'; import { filterMatchesIndex } from './filter_matches_index'; import { Filter, cleanFilter, isFilterDisabled } from '../filters'; diff --git a/packages/kbn-es-query/src/es_query/lucene_string_to_dsl.ts b/packages/kbn-es-query/src/es_query/lucene_string_to_dsl.ts index 91a912a5da0e3..07b56f281e80e 100644 --- a/packages/kbn-es-query/src/es_query/lucene_string_to_dsl.ts +++ b/packages/kbn-es-query/src/es_query/lucene_string_to_dsl.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { isString } from 'lodash'; /** diff --git a/packages/kbn-es-query/src/es_query/types.ts b/packages/kbn-es-query/src/es_query/types.ts index 75ea320b3431f..9e9888f5d14f6 100644 --- a/packages/kbn-es-query/src/es_query/types.ts +++ b/packages/kbn-es-query/src/es_query/types.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; /** * A field's sub type diff --git a/packages/kbn-es-query/src/filters/build_filters/custom_filter.ts b/packages/kbn-es-query/src/filters/build_filters/custom_filter.ts index 72b775bc688cc..77356006d98ef 100644 --- a/packages/kbn-es-query/src/filters/build_filters/custom_filter.ts +++ b/packages/kbn-es-query/src/filters/build_filters/custom_filter.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Filter, FilterMeta, FILTERS, FilterStateStore } from './types'; /** @public */ diff --git a/packages/kbn-es-query/src/filters/build_filters/match_all_filter.ts b/packages/kbn-es-query/src/filters/build_filters/match_all_filter.ts index 2d14ee8096f13..5e8083c1d1415 100644 --- a/packages/kbn-es-query/src/filters/build_filters/match_all_filter.ts +++ b/packages/kbn-es-query/src/filters/build_filters/match_all_filter.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { has } from 'lodash'; import type { Filter, FilterMeta } from './types'; diff --git a/packages/kbn-es-query/src/filters/build_filters/phrase_filter.test.ts b/packages/kbn-es-query/src/filters/build_filters/phrase_filter.test.ts index 13f18ad0cc7ea..87a7812165a66 100644 --- a/packages/kbn-es-query/src/filters/build_filters/phrase_filter.test.ts +++ b/packages/kbn-es-query/src/filters/build_filters/phrase_filter.test.ts @@ -14,7 +14,7 @@ import { } from './phrase_filter'; import { fields, getField } from '../stubs'; import { DataViewBase } from '../../es_query'; -import { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; describe('Phrase filter builder', () => { let indexPattern: DataViewBase; diff --git a/packages/kbn-es-query/src/filters/build_filters/phrase_filter.ts b/packages/kbn-es-query/src/filters/build_filters/phrase_filter.ts index 1e123900463b5..4c1827dc58c04 100644 --- a/packages/kbn-es-query/src/filters/build_filters/phrase_filter.ts +++ b/packages/kbn-es-query/src/filters/build_filters/phrase_filter.ts @@ -5,7 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import type { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { get, has, isPlainObject } from 'lodash'; import type { Filter, FilterMeta } from './types'; import type { IndexPatternFieldBase, IndexPatternBase } from '../../es_query'; diff --git a/packages/kbn-es-query/src/filters/build_filters/phrases_filter.ts b/packages/kbn-es-query/src/filters/build_filters/phrases_filter.ts index 0e09a191fd549..fe895bbd60a74 100644 --- a/packages/kbn-es-query/src/filters/build_filters/phrases_filter.ts +++ b/packages/kbn-es-query/src/filters/build_filters/phrases_filter.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Filter, FilterMeta, FILTERS } from './types'; import { getPhraseScript, PhraseFilterValue } from './phrase_filter'; import type { IndexPatternFieldBase, IndexPatternBase } from '../../es_query'; diff --git a/packages/kbn-es-query/src/filters/build_filters/range_filter.ts b/packages/kbn-es-query/src/filters/build_filters/range_filter.ts index e559e4d7e1d80..51e8fefe95f70 100644 --- a/packages/kbn-es-query/src/filters/build_filters/range_filter.ts +++ b/packages/kbn-es-query/src/filters/build_filters/range_filter.ts @@ -5,7 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import type { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { map, reduce, mapValues, has, get, keys, pickBy } from 'lodash'; import type { Filter, FilterMeta } from './types'; import type { IndexPatternBase, IndexPatternFieldBase } from '../../es_query'; diff --git a/packages/kbn-es-query/src/kuery/ast/ast.ts b/packages/kbn-es-query/src/kuery/ast/ast.ts index c1b4380ecbfe3..683de9f193901 100644 --- a/packages/kbn-es-query/src/kuery/ast/ast.ts +++ b/packages/kbn-es-query/src/kuery/ast/ast.ts @@ -7,7 +7,7 @@ */ import { JsonObject } from '@kbn/utility-types'; -import { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { nodeTypes } from '../node_types/index'; import { KQLSyntaxError } from '../kuery_syntax_error'; import { KueryNode, KueryParseOptions, KueryQueryOptions } from '../types'; diff --git a/packages/kbn-es-query/src/kuery/functions/exists.ts b/packages/kbn-es-query/src/kuery/functions/exists.ts index d1d0cb7835bca..a0d779c4c7d49 100644 --- a/packages/kbn-es-query/src/kuery/functions/exists.ts +++ b/packages/kbn-es-query/src/kuery/functions/exists.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { IndexPatternFieldBase, IndexPatternBase, KueryNode, KueryQueryOptions } from '../..'; import * as literal from '../node_types/literal'; diff --git a/packages/kbn-es-query/src/kuery/functions/geo_bounding_box.test.ts b/packages/kbn-es-query/src/kuery/functions/geo_bounding_box.test.ts index 9c4a33f50020f..7580765d59282 100644 --- a/packages/kbn-es-query/src/kuery/functions/geo_bounding_box.test.ts +++ b/packages/kbn-es-query/src/kuery/functions/geo_bounding_box.test.ts @@ -109,7 +109,6 @@ describe('kuery functions', () => { const node = nodeTypes.function.buildNode('geoBoundingBox', 'geo', params); const result = geoBoundingBox.toElasticsearchQuery(node, indexPattern); - // @ts-expect-error @elastic/elasticsearch doesn't support ignore_unmapped in QueryDslGeoBoundingBoxQuery expect(result.geo_bounding_box!.ignore_unmapped).toBe(true); }); diff --git a/packages/kbn-es-query/src/kuery/functions/geo_bounding_box.ts b/packages/kbn-es-query/src/kuery/functions/geo_bounding_box.ts index 1dae0b40ff08e..1808b7a2c0106 100644 --- a/packages/kbn-es-query/src/kuery/functions/geo_bounding_box.ts +++ b/packages/kbn-es-query/src/kuery/functions/geo_bounding_box.ts @@ -7,7 +7,7 @@ */ import _ from 'lodash'; -import { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { nodeTypes } from '../node_types'; import * as ast from '../ast'; import { IndexPatternBase, KueryNode, KueryQueryOptions, LatLon } from '../..'; @@ -53,7 +53,6 @@ export function toElasticsearchQuery( } return { - // @ts-expect-error @elastic/elasticsearch doesn't support ignore_unmapped in QueryDslGeoBoundingBoxQuery geo_bounding_box: { [fieldName]: queryParams, ignore_unmapped: true, diff --git a/packages/kbn-es-query/src/kuery/functions/geo_polygon.ts b/packages/kbn-es-query/src/kuery/functions/geo_polygon.ts index cf0bcdafa04c7..0cc95f8012a42 100644 --- a/packages/kbn-es-query/src/kuery/functions/geo_polygon.ts +++ b/packages/kbn-es-query/src/kuery/functions/geo_polygon.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { nodeTypes } from '../node_types'; import * as ast from '../ast'; import { IndexPatternBase, KueryNode, KueryQueryOptions, LatLon } from '../..'; @@ -49,7 +49,6 @@ export function toElasticsearchQuery( } return { - // @ts-expect-error @elastic/elasticsearch doesn't support ignore_unmapped in QueryDslGeoPolygonQuery geo_polygon: { [fieldName]: queryParams, ignore_unmapped: true, diff --git a/packages/kbn-es-query/src/kuery/functions/is.test.ts b/packages/kbn-es-query/src/kuery/functions/is.test.ts index fbc6011331dbb..2ec53629b9dca 100644 --- a/packages/kbn-es-query/src/kuery/functions/is.test.ts +++ b/packages/kbn-es-query/src/kuery/functions/is.test.ts @@ -11,7 +11,7 @@ import { fields } from '../../filters/stubs'; import * as is from './is'; import { DataViewBase } from '../..'; -import { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; jest.mock('../grammar'); diff --git a/packages/kbn-es-query/src/kuery/functions/is.ts b/packages/kbn-es-query/src/kuery/functions/is.ts index 38a62309721a2..854dcd95dc7aa 100644 --- a/packages/kbn-es-query/src/kuery/functions/is.ts +++ b/packages/kbn-es-query/src/kuery/functions/is.ts @@ -7,7 +7,7 @@ */ import { isUndefined } from 'lodash'; -import { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { getPhraseScript } from '../../filters'; import { getFields } from './utils/get_fields'; import { getTimeZoneFromSettings, getDataViewFieldSubtypeNested } from '../../utils'; diff --git a/packages/kbn-es-query/src/kuery/functions/nested.ts b/packages/kbn-es-query/src/kuery/functions/nested.ts index e59f7a6acc07d..3a466e9ddca02 100644 --- a/packages/kbn-es-query/src/kuery/functions/nested.ts +++ b/packages/kbn-es-query/src/kuery/functions/nested.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import * as ast from '../ast'; import * as literal from '../node_types/literal'; import { IndexPatternBase, KueryNode, KueryQueryOptions } from '../..'; diff --git a/packages/kbn-es-query/src/kuery/functions/not.ts b/packages/kbn-es-query/src/kuery/functions/not.ts index 01ec89e9b499d..91954c6a09fc4 100644 --- a/packages/kbn-es-query/src/kuery/functions/not.ts +++ b/packages/kbn-es-query/src/kuery/functions/not.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import * as ast from '../ast'; import { IndexPatternBase, KueryNode, KueryQueryOptions } from '../..'; diff --git a/packages/kbn-es-query/src/kuery/functions/or.ts b/packages/kbn-es-query/src/kuery/functions/or.ts index d48ddb4c32d73..d06f51d2918bd 100644 --- a/packages/kbn-es-query/src/kuery/functions/or.ts +++ b/packages/kbn-es-query/src/kuery/functions/or.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import * as ast from '../ast'; import { IndexPatternBase, KueryNode, KueryQueryOptions } from '../..'; diff --git a/packages/kbn-es-query/src/kuery/functions/range.test.ts b/packages/kbn-es-query/src/kuery/functions/range.test.ts index c541b26ce176f..2a97a74ac385d 100644 --- a/packages/kbn-es-query/src/kuery/functions/range.test.ts +++ b/packages/kbn-es-query/src/kuery/functions/range.test.ts @@ -13,7 +13,7 @@ import { DataViewBase } from '../..'; import { RangeFilterParams } from '../../filters'; import * as range from './range'; -import { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; jest.mock('../grammar'); describe('kuery functions', () => { diff --git a/packages/kbn-es-query/src/kuery/functions/range.ts b/packages/kbn-es-query/src/kuery/functions/range.ts index c5f24a1afdd6f..e016feb908bc7 100644 --- a/packages/kbn-es-query/src/kuery/functions/range.ts +++ b/packages/kbn-es-query/src/kuery/functions/range.ts @@ -7,7 +7,7 @@ */ import { pick, map, mapValues } from 'lodash'; -import { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { nodeTypes } from '../node_types'; import * as ast from '../ast'; import { getRangeScript, RangeFilterParams } from '../../filters'; diff --git a/packages/kbn-es-query/src/kuery/index.ts b/packages/kbn-es-query/src/kuery/index.ts index 15f3a768ebbd3..6e03b3cb18f4c 100644 --- a/packages/kbn-es-query/src/kuery/index.ts +++ b/packages/kbn-es-query/src/kuery/index.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { toElasticsearchQuery as astToElasticsearchQuery } from './ast'; /** diff --git a/packages/kbn-es-query/src/kuery/types.ts b/packages/kbn-es-query/src/kuery/types.ts index 1ab2d07a60a11..c074fa6d90845 100644 --- a/packages/kbn-es-query/src/kuery/types.ts +++ b/packages/kbn-es-query/src/kuery/types.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { SerializableRecord } from '@kbn/utility-types'; import { NodeTypes } from './node_types'; diff --git a/packages/kbn-es/src/utils/native_realm.js b/packages/kbn-es/src/utils/native_realm.js index c1682e0d18002..5c81d1e1147d1 100644 --- a/packages/kbn-es/src/utils/native_realm.js +++ b/packages/kbn-es/src/utils/native_realm.js @@ -16,7 +16,7 @@ exports.NativeRealm = class NativeRealm { const auth = { username: 'elastic', password: elasticPassword }; this._client = new Client( ssl - ? { node: `https://localhost:${port}`, ssl: { ca: caCert, rejectUnauthorized: true }, auth } + ? { node: `https://localhost:${port}`, tls: { ca: caCert, rejectUnauthorized: true }, auth } : { node: `http://localhost:${port}`, auth } ); this._elasticPassword = elasticPassword; @@ -67,9 +67,7 @@ exports.NativeRealm = class NativeRealm { async getReservedUsers(retryOpts = {}) { return await this._autoRetry(retryOpts, async () => { const resp = await this._client.security.getUser(); - const usernames = Object.keys(resp.body).filter( - (user) => resp.body[user].metadata._reserved === true - ); + const usernames = Object.keys(resp).filter((user) => resp[user].metadata._reserved === true); if (!usernames?.length) { throw new Error('no reserved users found, unable to set native realm passwords'); @@ -82,9 +80,7 @@ exports.NativeRealm = class NativeRealm { async isSecurityEnabled(retryOpts = {}) { try { return await this._autoRetry(retryOpts, async () => { - const { - body: { features }, - } = await this._client.xpack.info({ categories: 'features' }); + const { features } = await this._client.xpack.info({ categories: 'features' }); return features.security && features.security.enabled && features.security.available; }); } catch (error) { diff --git a/packages/kbn-es/src/utils/native_realm.test.js b/packages/kbn-es/src/utils/native_realm.test.js index 6d07b1e73b547..e3cb6aee84198 100644 --- a/packages/kbn-es/src/utils/native_realm.test.js +++ b/packages/kbn-es/src/utils/native_realm.test.js @@ -38,12 +38,10 @@ afterAll(() => { function mockXPackInfo(available, enabled) { mockClient.xpack.info.mockImplementation(() => ({ - body: { - features: { - security: { - available, - enabled, - }, + features: { + security: { + available, + enabled, }, }, })); @@ -97,31 +95,29 @@ describe('setPasswords', () => { mockXPackInfo(true, true); mockClient.security.getUser.mockImplementation(() => ({ - body: { - kibana_system: { - metadata: { - _reserved: true, - }, + kibana_system: { + metadata: { + _reserved: true, }, - non_native: { - metadata: { - _reserved: false, - }, + }, + non_native: { + metadata: { + _reserved: false, }, - logstash_system: { - metadata: { - _reserved: true, - }, + }, + logstash_system: { + metadata: { + _reserved: true, }, - elastic: { - metadata: { - _reserved: true, - }, + }, + elastic: { + metadata: { + _reserved: true, }, - beats_system: { - metadata: { - _reserved: true, - }, + }, + beats_system: { + metadata: { + _reserved: true, }, }, })); @@ -176,21 +172,19 @@ Array [ describe('getReservedUsers', () => { it('returns array of reserved usernames', async () => { mockClient.security.getUser.mockImplementation(() => ({ - body: { - kibana_system: { - metadata: { - _reserved: true, - }, + kibana_system: { + metadata: { + _reserved: true, }, - non_native: { - metadata: { - _reserved: false, - }, + }, + non_native: { + metadata: { + _reserved: false, }, - logstash_system: { - metadata: { - _reserved: true, - }, + }, + logstash_system: { + metadata: { + _reserved: true, }, }, })); diff --git a/packages/kbn-rule-data-utils/src/alerts_as_data_rbac.ts b/packages/kbn-rule-data-utils/src/alerts_as_data_rbac.ts index d167b17b83f23..d68f6df5cc4d2 100644 --- a/packages/kbn-rule-data-utils/src/alerts_as_data_rbac.ts +++ b/packages/kbn-rule-data-utils/src/alerts_as_data_rbac.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { EsQueryConfig } from '@kbn/es-query'; /** diff --git a/packages/kbn-securitysolution-es-utils/src/create_boostrap_index/index.ts b/packages/kbn-securitysolution-es-utils/src/create_boostrap_index/index.ts index 6a177f5caac21..973fe27ad7537 100644 --- a/packages/kbn-securitysolution-es-utils/src/create_boostrap_index/index.ts +++ b/packages/kbn-securitysolution-es-utils/src/create_boostrap_index/index.ts @@ -16,15 +16,18 @@ export const createBootstrapIndex = async ( index: string ): Promise => { return ( - await esClient.indices.create({ - index: `${index}-000001`, - body: { - aliases: { - [index]: { - is_write_index: true, + await esClient.indices.create( + { + index: `${index}-000001`, + body: { + aliases: { + [index]: { + is_write_index: true, + }, }, }, }, - }) + { meta: true } + ) ).body; }; diff --git a/packages/kbn-securitysolution-es-utils/src/decode_version/index.ts b/packages/kbn-securitysolution-es-utils/src/decode_version/index.ts index d58c7add67a27..8b3fb6f63d59a 100644 --- a/packages/kbn-securitysolution-es-utils/src/decode_version/index.ts +++ b/packages/kbn-securitysolution-es-utils/src/decode_version/index.ts @@ -23,8 +23,8 @@ export const decodeVersion = ( const parsed = JSON.parse(decoded); if (Array.isArray(parsed) && Number.isInteger(parsed[0]) && Number.isInteger(parsed[1])) { return { - ifPrimaryTerm: parsed[1], - ifSeqNo: parsed[0], + if_primary_term: parsed[1], + if_seq_no: parsed[0], }; } else { return {}; diff --git a/packages/kbn-securitysolution-es-utils/src/delete_all_index/index.ts b/packages/kbn-securitysolution-es-utils/src/delete_all_index/index.ts index 580c104752aea..2ff93f668ea27 100644 --- a/packages/kbn-securitysolution-es-utils/src/delete_all_index/index.ts +++ b/packages/kbn-securitysolution-es-utils/src/delete_all_index/index.ts @@ -25,7 +25,7 @@ export const deleteAllIndex = async ( { index: pattern, }, - { ignore: [404] } + { ignore: [404], meta: true } ); // @ts-expect-error status doesn't exist on response diff --git a/packages/kbn-securitysolution-es-utils/src/delete_policy/index.ts b/packages/kbn-securitysolution-es-utils/src/delete_policy/index.ts index 60a15f6d4625d..af6dca4619004 100644 --- a/packages/kbn-securitysolution-es-utils/src/delete_policy/index.ts +++ b/packages/kbn-securitysolution-es-utils/src/delete_policy/index.ts @@ -10,10 +10,7 @@ import type { ElasticsearchClient } from '../elasticsearch_client'; export const deletePolicy = async ( esClient: ElasticsearchClient, - policy: string + name: string ): Promise => { - return ( - // @ts-expect-error policy_id is required by mistake. fixed in the v8.0 - (await esClient.ilm.deleteLifecycle({ policy })).body - ); + return (await esClient.ilm.deleteLifecycle({ name }, { meta: true })).body; }; diff --git a/packages/kbn-securitysolution-es-utils/src/delete_template/index.ts b/packages/kbn-securitysolution-es-utils/src/delete_template/index.ts index 86565a0c43b3a..92eeadfff860a 100644 --- a/packages/kbn-securitysolution-es-utils/src/delete_template/index.ts +++ b/packages/kbn-securitysolution-es-utils/src/delete_template/index.ts @@ -13,8 +13,11 @@ export const deleteTemplate = async ( name: string ): Promise => { return ( - await esClient.indices.deleteTemplate({ - name, - }) + await esClient.indices.deleteTemplate( + { + name, + }, + { meta: true } + ) ).body; }; diff --git a/packages/kbn-securitysolution-es-utils/src/elasticsearch_client/index.ts b/packages/kbn-securitysolution-es-utils/src/elasticsearch_client/index.ts index a1fb3ff3ecf31..95fa040142c15 100644 --- a/packages/kbn-securitysolution-es-utils/src/elasticsearch_client/index.ts +++ b/packages/kbn-securitysolution-es-utils/src/elasticsearch_client/index.ts @@ -9,7 +9,7 @@ // Copied from src/core/server/elasticsearch/client/types.ts // as these types aren't part of any package yet. Once they are, remove this completely -import type { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import type { KibanaClient } from '@elastic/elasticsearch/lib/api/kibana'; /** * Client used to query the elasticsearch cluster. @@ -18,5 +18,5 @@ import type { KibanaClient } from '@elastic/elasticsearch/api/kibana'; */ export type ElasticsearchClient = Omit< KibanaClient, - 'connectionPool' | 'transport' | 'serializer' | 'extend' | 'child' | 'close' + 'connectionPool' | 'transport' | 'serializer' | 'extend' | 'child' | 'close' | 'diagnostic' >; diff --git a/packages/kbn-securitysolution-es-utils/src/get_index_aliases/index.ts b/packages/kbn-securitysolution-es-utils/src/get_index_aliases/index.ts index ba00c1144edfc..9a0d0fed1b63e 100644 --- a/packages/kbn-securitysolution-es-utils/src/get_index_aliases/index.ts +++ b/packages/kbn-securitysolution-es-utils/src/get_index_aliases/index.ts @@ -39,9 +39,12 @@ export const getIndexAliases = async ({ esClient: ElasticsearchClient; alias: string; }): Promise => { - const response = await esClient.indices.getAlias({ - name: alias, - }); + const response = await esClient.indices.getAlias( + { + name: alias, + }, + { meta: true } + ); return Object.keys(response.body).map((index) => ({ alias, diff --git a/packages/kbn-securitysolution-es-utils/src/get_index_count/index.ts b/packages/kbn-securitysolution-es-utils/src/get_index_count/index.ts index b1dcd4fd0ad9b..59cae505bfded 100644 --- a/packages/kbn-securitysolution-es-utils/src/get_index_count/index.ts +++ b/packages/kbn-securitysolution-es-utils/src/get_index_count/index.ts @@ -23,9 +23,12 @@ export const getIndexCount = async ({ esClient: ElasticsearchClient; index: string; }): Promise => { - const response = await esClient.count<{ count: number }>({ - index, - }); + const response = await esClient.count<{ count: number }>( + { + index, + }, + { meta: true } + ); return response.body.count; }; diff --git a/packages/kbn-securitysolution-es-utils/src/get_index_exists/index.ts b/packages/kbn-securitysolution-es-utils/src/get_index_exists/index.ts index 9208773048474..50ba298d10259 100644 --- a/packages/kbn-securitysolution-es-utils/src/get_index_exists/index.ts +++ b/packages/kbn-securitysolution-es-utils/src/get_index_exists/index.ts @@ -13,14 +13,17 @@ export const getIndexExists = async ( index: string ): Promise => { try { - const { body: response } = await esClient.search({ - index, - size: 0, - allow_no_indices: true, - body: { - terminate_after: 1, + const { body: response } = await esClient.search( + { + index, + size: 0, + allow_no_indices: true, + body: { + terminate_after: 1, + }, }, - }); + { meta: true } + ); return response._shards.total > 0; } catch (err) { if (err.body != null && err.body.status === 404) { diff --git a/packages/kbn-securitysolution-es-utils/src/get_policy_exists/index.ts b/packages/kbn-securitysolution-es-utils/src/get_policy_exists/index.ts index 8172cfb2abaa0..a62ea6e224e7d 100644 --- a/packages/kbn-securitysolution-es-utils/src/get_policy_exists/index.ts +++ b/packages/kbn-securitysolution-es-utils/src/get_policy_exists/index.ts @@ -9,11 +9,11 @@ import type { ElasticsearchClient } from '../elasticsearch_client'; export const getPolicyExists = async ( esClient: ElasticsearchClient, - policy: string + name: string ): Promise => { try { await esClient.ilm.getLifecycle({ - policy, + name, }); // Return true that there exists a policy which is not 404 or some error // Since there is not a policy exists API, this is how we create one by calling diff --git a/packages/kbn-securitysolution-es-utils/src/get_template_exists/index.ts b/packages/kbn-securitysolution-es-utils/src/get_template_exists/index.ts index 72a3a93654482..a310d1d6e9e0e 100644 --- a/packages/kbn-securitysolution-es-utils/src/get_template_exists/index.ts +++ b/packages/kbn-securitysolution-es-utils/src/get_template_exists/index.ts @@ -13,8 +13,11 @@ export const getTemplateExists = async ( template: string ): Promise => { return ( - await esClient.indices.existsTemplate({ - name: template, - }) + await esClient.indices.existsTemplate( + { + name: template, + }, + { meta: true } + ) ).body; }; diff --git a/packages/kbn-securitysolution-es-utils/src/read_index/index.ts b/packages/kbn-securitysolution-es-utils/src/read_index/index.ts index 206a4208b2ecc..a1112f8fceb64 100644 --- a/packages/kbn-securitysolution-es-utils/src/read_index/index.ts +++ b/packages/kbn-securitysolution-es-utils/src/read_index/index.ts @@ -9,7 +9,10 @@ import type { ElasticsearchClient } from '../elasticsearch_client'; export const readIndex = async (esClient: ElasticsearchClient, index: string): Promise => { - return esClient.indices.get({ - index, - }); + return esClient.indices.get( + { + index, + }, + { meta: true } + ); }; diff --git a/packages/kbn-securitysolution-es-utils/src/read_privileges/index.ts b/packages/kbn-securitysolution-es-utils/src/read_privileges/index.ts index 772a6afa18c95..614eb55297980 100644 --- a/packages/kbn-securitysolution-es-utils/src/read_privileges/index.ts +++ b/packages/kbn-securitysolution-es-utils/src/read_privileges/index.ts @@ -13,60 +13,63 @@ export const readPrivileges = async ( index: string ): Promise => { return ( - await esClient.security.hasPrivileges({ - body: { - cluster: [ - 'all', - 'create_snapshot', - 'manage', - 'manage_api_key', - 'manage_ccr', - 'manage_transform', - 'manage_ilm', - 'manage_index_templates', - 'manage_ingest_pipelines', - 'manage_ml', - 'manage_own_api_key', - 'manage_pipeline', - 'manage_rollup', - 'manage_saml', - 'manage_security', - 'manage_token', - 'manage_watcher', - 'monitor', - 'monitor_transform', - 'monitor_ml', - 'monitor_rollup', - 'monitor_watcher', - 'read_ccr', - 'read_ilm', - 'transport_client', - ], - index: [ - { - names: [index], - privileges: [ - 'all', - 'create', - 'create_doc', - 'create_index', - 'delete', - 'delete_index', - 'index', - 'manage', - 'maintenance', - 'manage_follow_index', - 'manage_ilm', - 'manage_leader_index', - 'monitor', - 'read', - 'read_cross_cluster', - 'view_index_metadata', - 'write', - ], - }, - ], + await esClient.security.hasPrivileges( + { + body: { + cluster: [ + 'all', + 'create_snapshot', + 'manage', + 'manage_api_key', + 'manage_ccr', + 'manage_transform', + 'manage_ilm', + 'manage_index_templates', + 'manage_ingest_pipelines', + 'manage_ml', + 'manage_own_api_key', + 'manage_pipeline', + 'manage_rollup', + 'manage_saml', + 'manage_security', + 'manage_token', + 'manage_watcher', + 'monitor', + 'monitor_transform', + 'monitor_ml', + 'monitor_rollup', + 'monitor_watcher', + 'read_ccr', + 'read_ilm', + 'transport_client', + ], + index: [ + { + names: [index], + privileges: [ + 'all', + 'create', + 'create_doc', + 'create_index', + 'delete', + 'delete_index', + 'index', + 'manage', + 'maintenance', + 'manage_follow_index', + 'manage_ilm', + 'manage_leader_index', + 'monitor', + 'read', + 'read_cross_cluster', + 'view_index_metadata', + 'write', + ], + }, + ], + }, }, - }) + { meta: true } + ) ).body; }; diff --git a/packages/kbn-securitysolution-es-utils/src/set_policy/index.ts b/packages/kbn-securitysolution-es-utils/src/set_policy/index.ts index f6c2dcf7c3c3a..091155e491e05 100644 --- a/packages/kbn-securitysolution-es-utils/src/set_policy/index.ts +++ b/packages/kbn-securitysolution-es-utils/src/set_policy/index.ts @@ -9,13 +9,16 @@ import type { ElasticsearchClient } from '../elasticsearch_client'; export const setPolicy = async ( esClient: ElasticsearchClient, - policy: string, + name: string, body: Record ): Promise => { return ( - await esClient.ilm.putLifecycle({ - policy, - body, - }) + await esClient.ilm.putLifecycle( + { + name, + body, + }, + { meta: true } + ) ).body; }; diff --git a/packages/kbn-securitysolution-es-utils/src/set_template/index.ts b/packages/kbn-securitysolution-es-utils/src/set_template/index.ts index 20f6fd5719d51..7e1d6a4fb0a1e 100644 --- a/packages/kbn-securitysolution-es-utils/src/set_template/index.ts +++ b/packages/kbn-securitysolution-es-utils/src/set_template/index.ts @@ -14,9 +14,12 @@ export const setTemplate = async ( body: Record ): Promise => { return ( - await esClient.indices.putTemplate({ - name, - body, - }) + await esClient.indices.putTemplate( + { + name, + body, + }, + { meta: true } + ) ).body; }; diff --git a/packages/kbn-securitysolution-list-utils/src/build_exception_filter/index.ts b/packages/kbn-securitysolution-list-utils/src/build_exception_filter/index.ts index 2aa4cf64073ab..dc00314ece266 100644 --- a/packages/kbn-securitysolution-list-utils/src/build_exception_filter/index.ts +++ b/packages/kbn-securitysolution-list-utils/src/build_exception_filter/index.ts @@ -23,7 +23,7 @@ import { } from '@kbn/securitysolution-io-ts-list-types'; import { Filter } from '@kbn/es-query'; -import { QueryDslBoolQuery, QueryDslNestedQuery } from '@elastic/elasticsearch/api/types'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { hasLargeValueList } from '../has_large_value_list'; type NonListEntry = EntryMatch | EntryMatchAny | EntryNested | EntryExists; @@ -40,11 +40,11 @@ export type ExceptionItemSansLargeValueLists = | CreateExceptionListItemNonLargeList; export interface BooleanFilter { - bool: QueryDslBoolQuery; + bool: estypes.QueryDslBoolQuery; } export interface NestedFilter { - nested: QueryDslNestedQuery; + nested: estypes.QueryDslNestedQuery; } export const chunkExceptions = ( diff --git a/packages/kbn-test/src/es/client_to_kibana_client.ts b/packages/kbn-test/src/es/client_to_kibana_client.ts new file mode 100644 index 0000000000000..778ee0a7705b3 --- /dev/null +++ b/packages/kbn-test/src/es/client_to_kibana_client.ts @@ -0,0 +1,35 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ +import type { KibanaClient } from '@elastic/elasticsearch/lib/api/kibana'; +import type { + Client, + TransportRequestParams, + TransportRequestOptions, + TransportResult, +} from '@elastic/elasticsearch'; +import { Transport } from '@elastic/elasticsearch'; + +// remove once https://github.com/elastic/kibana/issues/116095 is addressed +class KibanaTransport extends Transport { + request(params: TransportRequestParams, options?: TransportRequestOptions) { + const opts: TransportRequestOptions = options || {}; + // Enforce the client to return TransportResult. + // It's required for bwc with responses in 7.x version. + if (opts?.meta === undefined) { + opts.meta = true; + } + return super.request(params, opts) as Promise>; + } +} + +export function convertToKibanaClient(esClient: Client): KibanaClient { + // @ts-expect-error @elastic/elasticsearch fix discrepancy between clients + return esClient.child({ + Transport: KibanaTransport, + }); +} diff --git a/packages/kbn-test/src/es/index.ts b/packages/kbn-test/src/es/index.ts index ccfec67dae848..0c19a6b903742 100644 --- a/packages/kbn-test/src/es/index.ts +++ b/packages/kbn-test/src/es/index.ts @@ -9,3 +9,4 @@ export { createTestEsCluster } from './test_es_cluster'; export type { CreateTestEsClusterOptions, EsTestCluster, ICluster } from './test_es_cluster'; export { esTestConfig } from './es_test_config'; +export { convertToKibanaClient } from './client_to_kibana_client'; diff --git a/packages/kbn-test/src/es/test_es_cluster.ts b/packages/kbn-test/src/es/test_es_cluster.ts index 0d31ffdb99cc2..575fc965962eb 100644 --- a/packages/kbn-test/src/es/test_es_cluster.ts +++ b/packages/kbn-test/src/es/test_es_cluster.ts @@ -11,11 +11,12 @@ import { format } from 'url'; import del from 'del'; // @ts-expect-error in js import { Cluster } from '@kbn/es'; -import { Client } from '@elastic/elasticsearch'; -import type { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import { Client, HttpConnection } from '@elastic/elasticsearch'; +import type { KibanaClient } from '@elastic/elasticsearch/lib/api/kibana'; import type { ToolingLog } from '@kbn/dev-utils'; import { CI_PARALLEL_PROCESS_PREFIX } from '../ci_parallel_process_prefix'; import { esTestConfig } from './es_test_config'; +import { convertToKibanaClient } from './client_to_kibana_client'; import { KIBANA_ROOT } from '../'; @@ -51,7 +52,8 @@ export interface ICluster { start: () => Promise; stop: () => Promise; cleanup: () => Promise; - getClient: () => KibanaClient; + getClient: () => Client; + getKibanaEsClient: () => KibanaClient; getHostUrls: () => string[]; } @@ -280,12 +282,20 @@ export function createTestEsCluster< /** * Returns an ES Client to the configured cluster */ - getClient(): KibanaClient { + getClient(): Client { return new Client({ node: this.getHostUrls()[0], + Connection: HttpConnection, }); } + /** + * Returns an ES Client to the configured cluster + */ + getKibanaEsClient(): KibanaClient { + return convertToKibanaClient(this.getClient()); + } + getUrl() { if (this.nodes.length > 1) { throw new Error( diff --git a/packages/kbn-test/src/failed_tests_reporter/report_failures_to_es.ts b/packages/kbn-test/src/failed_tests_reporter/report_failures_to_es.ts index 754ce2567cb80..a96ca5822775d 100644 --- a/packages/kbn-test/src/failed_tests_reporter/report_failures_to_es.ts +++ b/packages/kbn-test/src/failed_tests_reporter/report_failures_to_es.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { Client } from '@elastic/elasticsearch'; +import { Client, HttpConnection } from '@elastic/elasticsearch'; import { createFailError, ToolingLog } from '@kbn/dev-utils'; import { TestFailure } from './get_failures'; @@ -34,6 +34,7 @@ export async function reportFailuresToEs(log: ToolingLog, failures: TestFailure[ username: process.env.TEST_FAILURES_ES_USERNAME, password: process.env.TEST_FAILURES_ES_PASSWORD, }, + Connection: HttpConnection, }); const body = failures.flatMap((failure) => [ @@ -59,7 +60,7 @@ export async function reportFailuresToEs(log: ToolingLog, failures: TestFailure[ }, ]); - const resp = await client.bulk({ body }); + const resp = await client.bulk({ body }, { meta: true }); if (resp?.body?.errors) { log.error(JSON.stringify(resp.body.items, null, 2)); } diff --git a/packages/kbn-test/src/index.ts b/packages/kbn-test/src/index.ts index dea2ec9d1035e..0ef9fbfed07a0 100644 --- a/packages/kbn-test/src/index.ts +++ b/packages/kbn-test/src/index.ts @@ -31,6 +31,7 @@ export { CreateTestEsClusterOptions, EsTestCluster, ICluster, + convertToKibanaClient, } from './es'; export { kbnTestConfig, kibanaServerTestUser, kibanaTestUser, adminTestUser } from './kbn'; diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index 1992b2d9686ac..cf0b526aa9fd9 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -5,12 +5,11 @@ ```ts import { Action } from 'history'; -import { ApiResponse } from '@elastic/elasticsearch/lib/Transport'; import Boom from '@hapi/boom'; import { ConfigPath } from '@kbn/config'; import { DetailedPeerCertificate } from 'tls'; import { EnvironmentMode } from '@kbn/config'; -import { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { EuiBreadcrumb } from '@elastic/eui'; import { EuiButtonEmptyProps } from '@elastic/eui'; import { EuiConfirmModalProps } from '@elastic/eui'; @@ -20,7 +19,7 @@ import { History } from 'history'; import { Href } from 'history'; import { IconType } from '@elastic/eui'; import { IncomingHttpHeaders } from 'http'; -import { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import { KibanaClient } from '@elastic/elasticsearch/lib/api/kibana'; import { Location } from 'history'; import { LocationDescriptorObject } from 'history'; import { Logger } from '@kbn/logging'; @@ -38,9 +37,9 @@ import { RecursiveReadonly } from '@kbn/utility-types'; import { Request } from '@hapi/hapi'; import * as Rx from 'rxjs'; import { SchemaTypeError } from '@kbn/config-schema'; -import { TransportRequestOptions } from '@elastic/elasticsearch/lib/Transport'; -import { TransportRequestParams } from '@elastic/elasticsearch/lib/Transport'; -import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; +import { TransportRequestOptions } from '@elastic/elasticsearch'; +import { TransportRequestParams } from '@elastic/elasticsearch'; +import { TransportResult } from '@elastic/elasticsearch'; import { Type } from '@kbn/config-schema'; import { TypeOf } from '@kbn/config-schema'; import { UiCounterMetricType } from '@kbn/analytics'; diff --git a/src/core/server/core_usage_data/core_usage_data_service.ts b/src/core/server/core_usage_data/core_usage_data_service.ts index 22dafc7e44e06..2e76bc08658a2 100644 --- a/src/core/server/core_usage_data/core_usage_data_service.ts +++ b/src/core/server/core_usage_data/core_usage_data_service.ts @@ -17,7 +17,7 @@ import { AggregationsFiltersAggregate, AggregationsFiltersBucketItem, SearchTotalHits, -} from '@elastic/elasticsearch/api/types'; +} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { CoreContext } from '../core_context'; import { ElasticsearchConfigType } from '../elasticsearch/elasticsearch_config'; import { HttpConfigType, InternalHttpServiceSetup } from '../http'; diff --git a/src/core/server/elasticsearch/client/client_config.test.ts b/src/core/server/elasticsearch/client/client_config.test.ts index af8e2d64cb6a2..8158b7d116c4b 100644 --- a/src/core/server/elasticsearch/client/client_config.test.ts +++ b/src/core/server/elasticsearch/client/client_config.test.ts @@ -328,10 +328,10 @@ describe('parseClientOptions', () => { }); }); - describe('ssl config', () => { - it('does not generate ssl option is ssl config is not set', () => { - expect(parseClientOptions(createConfig({}), false).ssl).toBeUndefined(); - expect(parseClientOptions(createConfig({}), true).ssl).toBeUndefined(); + describe('tls config', () => { + it('does not generate tls option is ssl config is not set', () => { + expect(parseClientOptions(createConfig({}), false).tls).toBeUndefined(); + expect(parseClientOptions(createConfig({}), true).tls).toBeUndefined(); }); it('handles the `certificateAuthorities` option', () => { @@ -341,7 +341,7 @@ describe('parseClientOptions', () => { ssl: { verificationMode: 'full', certificateAuthorities: ['content-of-ca-path'] }, }), false - ).ssl!.ca + ).tls!.ca ).toEqual(['content-of-ca-path']); expect( parseClientOptions( @@ -349,7 +349,7 @@ describe('parseClientOptions', () => { ssl: { verificationMode: 'full', certificateAuthorities: ['content-of-ca-path'] }, }), true - ).ssl!.ca + ).tls!.ca ).toEqual(['content-of-ca-path']); }); @@ -363,7 +363,7 @@ describe('parseClientOptions', () => { }, }), false - ).ssl + ).tls ).toMatchInlineSnapshot(` Object { "ca": undefined, @@ -380,7 +380,7 @@ describe('parseClientOptions', () => { }, }), false - ).ssl + ).tls ).toMatchInlineSnapshot(` Object { "ca": undefined, @@ -398,7 +398,7 @@ describe('parseClientOptions', () => { }, }), false - ).ssl + ).tls ).toMatchInlineSnapshot(` Object { "ca": undefined, @@ -416,7 +416,7 @@ describe('parseClientOptions', () => { }, }), false - ).ssl + ).tls ).toThrowErrorMatchingInlineSnapshot(`"Unknown ssl verificationMode: unknown"`); }); it('throws for undefined values', () => { @@ -429,7 +429,7 @@ describe('parseClientOptions', () => { }, }), false - ).ssl + ).tls ).toThrowErrorMatchingInlineSnapshot(`"Unknown ssl verificationMode: undefined"`); }); }); @@ -446,7 +446,7 @@ describe('parseClientOptions', () => { }, }), false - ).ssl + ).tls ).toMatchInlineSnapshot(` Object { "ca": undefined, @@ -466,7 +466,7 @@ describe('parseClientOptions', () => { }, }), false - ).ssl + ).tls ).toMatchInlineSnapshot(` Object { "ca": undefined, @@ -487,7 +487,7 @@ describe('parseClientOptions', () => { }, }), false - ).ssl + ).tls ).toMatchInlineSnapshot(` Object { "ca": undefined, @@ -511,7 +511,7 @@ describe('parseClientOptions', () => { }, }), true - ).ssl + ).tls ).toMatchInlineSnapshot(` Object { "ca": undefined, @@ -531,7 +531,7 @@ describe('parseClientOptions', () => { }, }), true - ).ssl + ).tls ).toMatchInlineSnapshot(` Object { "ca": undefined, diff --git a/src/core/server/elasticsearch/client/client_config.ts b/src/core/server/elasticsearch/client/client_config.ts index 24c48012346da..1cb81fd0a417a 100644 --- a/src/core/server/elasticsearch/client/client_config.ts +++ b/src/core/server/elasticsearch/client/client_config.ts @@ -9,7 +9,7 @@ import { ConnectionOptions as TlsConnectionOptions } from 'tls'; import { URL } from 'url'; import { Duration } from 'moment'; -import { ClientOptions, NodeOptions } from '@elastic/elasticsearch'; +import type { ClientOptions } from '@elastic/elasticsearch/lib/client'; import { ElasticsearchConfig } from '../elasticsearch_config'; import { DEFAULT_HEADERS } from '../default_headers'; @@ -93,7 +93,7 @@ export function parseClientOptions( clientOptions.nodes = config.hosts.map((host) => convertHost(host)); if (config.ssl) { - clientOptions.ssl = generateSslConfig( + clientOptions.tls = generateSslConfig( config.ssl, scoped && !config.ssl.alwaysPresentCertificate ); @@ -141,7 +141,7 @@ const generateSslConfig = ( return ssl; }; -const convertHost = (host: string): NodeOptions => { +const convertHost = (host: string): { url: URL } => { const url = new URL(host); const isHTTPS = url.protocol === 'https:'; url.port = url.port || (isHTTPS ? '443' : '80'); diff --git a/src/core/server/elasticsearch/client/cluster_client.ts b/src/core/server/elasticsearch/client/cluster_client.ts index f81b651843013..1f3118c77aa0f 100644 --- a/src/core/server/elasticsearch/client/cluster_client.ts +++ b/src/core/server/elasticsearch/client/cluster_client.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { Client } from '@elastic/elasticsearch'; +import type { KibanaClient } from '@elastic/elasticsearch/lib/api/kibana'; import { Logger } from '../../logging'; import { GetAuthHeaders, Headers, isKibanaRequest, isRealRequest } from '../../http'; import { ensureRawRequest, filterHeaders } from '../../http/router'; @@ -52,8 +52,8 @@ export interface ICustomClusterClient extends IClusterClient { /** @internal **/ export class ClusterClient implements ICustomClusterClient { - public readonly asInternalUser: Client; - private readonly rootScopedClient: Client; + public readonly asInternalUser: KibanaClient; + private readonly rootScopedClient: KibanaClient; private readonly allowListHeaders: string[]; private isClosed = false; diff --git a/src/core/server/elasticsearch/client/configure_client.test.ts b/src/core/server/elasticsearch/client/configure_client.test.ts index 35fcb5819d015..7988e81045d17 100644 --- a/src/core/server/elasticsearch/client/configure_client.test.ts +++ b/src/core/server/elasticsearch/client/configure_client.test.ts @@ -9,13 +9,13 @@ import { Buffer } from 'buffer'; import { Readable } from 'stream'; -import { RequestEvent, errors } from '@elastic/elasticsearch'; -import type { Client } from '@elastic/elasticsearch'; +import { errors } from '@elastic/elasticsearch'; import type { TransportRequestOptions, TransportRequestParams, + DiagnosticResult, RequestBody, -} from '@elastic/elasticsearch/lib/Transport'; +} from '@elastic/elasticsearch'; import { parseClientOptionsMock, ClientMock } from './configure_client.test.mocks'; import { loggingSystemMock } from '../../logging/logging_system.mock'; @@ -36,7 +36,7 @@ const createFakeClient = () => { const client = new actualEs.Client({ nodes: ['http://localhost'], // Enforcing `nodes` because it's mandatory }); - jest.spyOn(client, 'on'); + jest.spyOn(client.diagnostic, 'on'); return client; }; @@ -54,7 +54,7 @@ const createApiResponse = ({ warnings?: string[]; params?: TransportRequestParams; requestOptions?: TransportRequestOptions; -}): RequestEvent => { +}): DiagnosticResult => { return { body, statusCode, @@ -70,14 +70,6 @@ const createApiResponse = ({ }; }; -function getProductCheckValue(client: Client) { - const tSymbol = Object.getOwnPropertySymbols(client.transport || client).filter( - (symbol) => symbol.description === 'product check' - )[0]; - // @ts-expect-error `tSymbol` is missing in the index signature of Transport - return (client.transport || client)[tSymbol]; -} - describe('configureClient', () => { let logger: ReturnType; let config: ElasticsearchClientConfig; @@ -124,26 +116,8 @@ describe('configureClient', () => { it('listens to client on `response` events', () => { const client = configureClient(config, { logger, type: 'test', scoped: false }); - expect(client.on).toHaveBeenCalledTimes(1); - expect(client.on).toHaveBeenCalledWith('response', expect.any(Function)); - }); - - describe('Product check', () => { - it('should not skip the product check for the unscoped client', () => { - const client = configureClient(config, { logger, type: 'test', scoped: false }); - expect(getProductCheckValue(client)).toBe(0); - }); - - it('should skip the product check for the scoped client', () => { - const client = configureClient(config, { logger, type: 'test', scoped: true }); - expect(getProductCheckValue(client)).toBe(2); - }); - - it('should skip the product check for the children of the scoped client', () => { - const client = configureClient(config, { logger, type: 'test', scoped: true }); - const asScoped = client.child({ headers: { 'x-custom-header': 'Custom value' } }); - expect(getProductCheckValue(asScoped)).toBe(2); - }); + expect(client.diagnostic.on).toHaveBeenCalledTimes(1); + expect(client.diagnostic.on).toHaveBeenCalledWith('response', expect.any(Function)); }); describe('Client logging', () => { @@ -176,7 +150,7 @@ describe('configureClient', () => { }, }); - client.emit('response', null, response); + client.diagnostic.emit('response', null, response); expect(loggingSystemMock.collect(logger).debug).toMatchInlineSnapshot(` Array [ Array [ @@ -201,7 +175,7 @@ describe('configureClient', () => { }) ); - client.emit('response', null, response); + client.diagnostic.emit('response', null, response); expect(loggingSystemMock.collect(logger).debug).toMatchInlineSnapshot(` Array [ Array [ @@ -228,7 +202,7 @@ describe('configureClient', () => { ) ); - client.emit('response', null, response); + client.diagnostic.emit('response', null, response); expect(loggingSystemMock.collect(logger).debug).toMatchInlineSnapshot(` Array [ Array [ @@ -255,7 +229,7 @@ describe('configureClient', () => { ) ); - client.emit('response', null, response); + client.diagnostic.emit('response', null, response); expect(loggingSystemMock.collect(logger).debug).toMatchInlineSnapshot(` Array [ Array [ @@ -273,7 +247,7 @@ describe('configureClient', () => { const response = createResponseWithBody(); - client.emit('response', null, response); + client.diagnostic.emit('response', null, response); expect(loggingSystemMock.collect(logger).debug).toMatchInlineSnapshot(` Array [ Array [ @@ -298,7 +272,7 @@ describe('configureClient', () => { }, }); - client.emit('response', null, response); + client.diagnostic.emit('response', null, response); expect(loggingSystemMock.collect(logger).debug).toMatchInlineSnapshot(` Array [ @@ -333,7 +307,7 @@ describe('configureClient', () => { }, }, }); - client.emit('response', new errors.ResponseError(response), response); + client.diagnostic.emit('response', new errors.ResponseError(response), response); expect(loggingSystemMock.collect(logger).debug).toMatchInlineSnapshot(` Array [ @@ -351,7 +325,7 @@ describe('configureClient', () => { const client = configureClient(createFakeConfig(), { logger, type: 'test', scoped: false }); const response = createApiResponse({ body: {} }); - client.emit('response', new errors.TimeoutError('message', response), response); + client.diagnostic.emit('response', new errors.TimeoutError('message', response), response); expect(loggingSystemMock.collect(logger).debug).toMatchInlineSnapshot(` Array [ @@ -381,7 +355,7 @@ describe('configureClient', () => { }, }, }); - client.emit('response', new errors.ResponseError(response), response); + client.diagnostic.emit('response', new errors.ResponseError(response), response); expect(loggingSystemMock.collect(logger).debug).toMatchInlineSnapshot(` Array [ @@ -397,7 +371,7 @@ describe('configureClient', () => { it('logs default error info when the error response body is empty', () => { const client = configureClient(createFakeConfig(), { logger, type: 'test', scoped: false }); - let response: RequestEvent = createApiResponse({ + let response: DiagnosticResult = createApiResponse({ statusCode: 400, headers: {}, params: { @@ -408,7 +382,7 @@ describe('configureClient', () => { error: {}, }, }); - client.emit('response', new errors.ResponseError(response), response); + client.diagnostic.emit('response', new errors.ResponseError(response), response); expect(loggingSystemMock.collect(logger).debug).toMatchInlineSnapshot(` Array [ @@ -431,7 +405,7 @@ describe('configureClient', () => { }, body: undefined, }); - client.emit('response', new errors.ResponseError(response), response); + client.diagnostic.emit('response', new errors.ResponseError(response), response); expect(loggingSystemMock.collect(logger).debug).toMatchInlineSnapshot(` Array [ @@ -461,7 +435,7 @@ describe('configureClient', () => { error: {}, }, }); - client.emit('response', null, response); + client.diagnostic.emit('response', null, response); expect(loggingSystemMock.collect(logger).debug[0][1]).toMatchInlineSnapshot(` Object { @@ -487,7 +461,7 @@ describe('configureClient', () => { }, body: {} as any, }); - client.emit('response', new errors.ResponseError(response), response); + client.diagnostic.emit('response', new errors.ResponseError(response), response); expect(loggingSystemMock.collect(logger).debug[0][1]).toMatchInlineSnapshot(` Object { diff --git a/src/core/server/elasticsearch/client/configure_client.ts b/src/core/server/elasticsearch/client/configure_client.ts index 93c404593af3f..fc8a06660cc5e 100644 --- a/src/core/server/elasticsearch/client/configure_client.ts +++ b/src/core/server/elasticsearch/client/configure_client.ts @@ -8,14 +8,19 @@ import { Buffer } from 'buffer'; import { stringify } from 'querystring'; -import { ApiError, Client, RequestEvent, errors, Transport } from '@elastic/elasticsearch'; +import { Client, errors, Transport, HttpConnection } from '@elastic/elasticsearch'; +import type { KibanaClient } from '@elastic/elasticsearch/lib/api/kibana'; import type { - RequestBody, TransportRequestParams, TransportRequestOptions, -} from '@elastic/elasticsearch/lib/Transport'; + TransportResult, + DiagnosticResult, + RequestBody, +} from '@elastic/elasticsearch'; + import { Logger } from '../../logging'; import { parseClientOptions, ElasticsearchClientConfig } from './client_config'; +import type { ElasticsearchErrorDetails } from './types'; const noop = () => undefined; @@ -32,30 +37,33 @@ export const configureClient = ( scoped?: boolean; getExecutionContext?: () => string | undefined; } -): Client => { +): KibanaClient => { const clientOptions = parseClientOptions(config, scoped); class KibanaTransport extends Transport { request(params: TransportRequestParams, options?: TransportRequestOptions) { - const opts = options || {}; + const opts: TransportRequestOptions = options || {}; const opaqueId = getExecutionContext(); if (opaqueId && !opts.opaqueId) { // rewrites headers['x-opaque-id'] if it presents opts.opaqueId = opaqueId; } - return super.request(params, opts); + // Enforce the client to return TransportResult. + // It's required for bwc with responses in 7.x version. + if (opts.meta === undefined) { + opts.meta = true; + } + return super.request(params, opts) as Promise>; } } - const client = new Client({ ...clientOptions, Transport: KibanaTransport }); + const client = new Client({ + ...clientOptions, + Transport: KibanaTransport, + Connection: HttpConnection, + }); addLogging(client, logger.get('query', type)); - // --------------------------------------------------------------------------------- // - // Hack to disable the "Product check" only in the scoped clients while we // - // come up with a better approach in https://github.com/elastic/kibana/issues/110675 // - if (scoped) skipProductCheck(client); - // --------------------------------------------------------------------------------- // - - return client; + return client as KibanaClient; }; const convertQueryString = (qs: string | Record | undefined): string => { @@ -76,9 +84,10 @@ function ensureString(body: RequestBody): string { * Returns a debug message from an Elasticsearch error in the following format: * [error type] error reason */ -export function getErrorMessage(error: ApiError): string { +export function getErrorMessage(error: errors.ElasticsearchClientError): string { if (error instanceof errors.ResponseError) { - return `[${error.meta.body?.error?.type}]: ${error.meta.body?.error?.reason ?? error.message}`; + const errorBody = error.meta.body as ElasticsearchErrorDetails; + return `[${errorBody?.error?.type}]: ${errorBody?.error?.reason ?? error.message}`; } return `[${error.name}]: ${error.message}`; } @@ -92,7 +101,7 @@ export function getErrorMessage(error: ApiError): string { * * so it could be copy-pasted into the Dev console */ -function getResponseMessage(event: RequestEvent): string { +function getResponseMessage(event: DiagnosticResult): string { const errorMeta = getRequestDebugMeta(event); const body = errorMeta.body ? `\n${errorMeta.body}` : ''; return `${errorMeta.statusCode}\n${errorMeta.method} ${errorMeta.url}${body}`; @@ -102,7 +111,7 @@ function getResponseMessage(event: RequestEvent): string { * Returns stringified debug information from an Elasticsearch request event * useful for logging in case of an unexpected failure. */ -export function getRequestDebugMeta(event: RequestEvent): { +export function getRequestDebugMeta(event: DiagnosticResult): { url: string; body: string; statusCode: number | null; @@ -115,12 +124,12 @@ export function getRequestDebugMeta(event: RequestEvent): { url: `${params.path}${querystring ? `?${querystring}` : ''}`, body: params.body ? `${ensureString(params.body)}` : '', method: params.method, - statusCode: event.statusCode, + statusCode: event.statusCode!, }; } const addLogging = (client: Client, logger: Logger) => { - client.on('response', (error, event) => { + client.diagnostic.on('response', (error, event) => { if (event) { const opaqueId = event.meta.request.options.opaqueId; const meta = opaqueId @@ -140,21 +149,3 @@ const addLogging = (client: Client, logger: Logger) => { } }); }; - -/** - * Hack to skip the Product Check performed by the Elasticsearch-js client. - * We noticed that the scoped clients are always performing this check because - * of the way we initialize the clients. We'll discuss changing this in the issue - * https://github.com/elastic/kibana/issues/110675. In the meanwhile, let's skip - * it for the scoped clients. - * - * The hack is copied from the test/utils in the elasticsearch-js repo - * (https://github.com/elastic/elasticsearch-js/blob/master/test/utils/index.js#L45-L56) - */ -function skipProductCheck(client: Client) { - const tSymbol = Object.getOwnPropertySymbols(client.transport || client).filter( - (symbol) => symbol.description === 'product check' - )[0]; - // @ts-expect-error `tSymbol` is missing in the index signature of Transport - (client.transport || client)[tSymbol] = 2; -} diff --git a/src/core/server/elasticsearch/client/errors.test.ts b/src/core/server/elasticsearch/client/errors.test.ts index a27a1fa794a97..59c4296d2bbb2 100644 --- a/src/core/server/elasticsearch/client/errors.test.ts +++ b/src/core/server/elasticsearch/client/errors.test.ts @@ -6,12 +6,8 @@ * Side Public License, v 1. */ -import { - ResponseError, - ConnectionError, - ConfigurationError, -} from '@elastic/elasticsearch/lib/errors'; -import { ApiResponse } from '@elastic/elasticsearch'; +import { errors } from '@elastic/elasticsearch'; +import type { TransportResult } from '@elastic/elasticsearch'; import { isResponseError, isUnauthorizedError } from './errors'; const createApiResponseError = ({ @@ -22,7 +18,7 @@ const createApiResponseError = ({ statusCode?: number; headers?: Record; body?: Record; -} = {}): ApiResponse => { +} = {}): TransportResult => { return { body, statusCode, @@ -34,38 +30,42 @@ const createApiResponseError = ({ describe('isResponseError', () => { it('returns `true` when the input is a `ResponseError`', () => { - expect(isResponseError(new ResponseError(createApiResponseError()))).toBe(true); + expect(isResponseError(new errors.ResponseError(createApiResponseError()))).toBe(true); }); it('returns `false` when the input is not a `ResponseError`', () => { expect(isResponseError(new Error('foo'))).toBe(false); - expect(isResponseError(new ConnectionError('error', createApiResponseError()))).toBe(false); - expect(isResponseError(new ConfigurationError('foo'))).toBe(false); + expect(isResponseError(new errors.ConnectionError('error', createApiResponseError()))).toBe( + false + ); + expect(isResponseError(new errors.ConfigurationError('foo'))).toBe(false); }); }); describe('isUnauthorizedError', () => { it('returns true when the input is a `ResponseError` and statusCode === 401', () => { expect( - isUnauthorizedError(new ResponseError(createApiResponseError({ statusCode: 401 }))) + isUnauthorizedError(new errors.ResponseError(createApiResponseError({ statusCode: 401 }))) ).toBe(true); }); it('returns false when the input is a `ResponseError` and statusCode !== 401', () => { expect( - isUnauthorizedError(new ResponseError(createApiResponseError({ statusCode: 200 }))) + isUnauthorizedError(new errors.ResponseError(createApiResponseError({ statusCode: 200 }))) ).toBe(false); expect( - isUnauthorizedError(new ResponseError(createApiResponseError({ statusCode: 403 }))) + isUnauthorizedError(new errors.ResponseError(createApiResponseError({ statusCode: 403 }))) ).toBe(false); expect( - isUnauthorizedError(new ResponseError(createApiResponseError({ statusCode: 500 }))) + isUnauthorizedError(new errors.ResponseError(createApiResponseError({ statusCode: 500 }))) ).toBe(false); }); it('returns `false` when the input is not a `ResponseError`', () => { expect(isUnauthorizedError(new Error('foo'))).toBe(false); - expect(isUnauthorizedError(new ConnectionError('error', createApiResponseError()))).toBe(false); - expect(isUnauthorizedError(new ConfigurationError('foo'))).toBe(false); + expect(isUnauthorizedError(new errors.ConnectionError('error', createApiResponseError()))).toBe( + false + ); + expect(isUnauthorizedError(new errors.ConfigurationError('foo'))).toBe(false); }); }); diff --git a/src/core/server/elasticsearch/client/errors.ts b/src/core/server/elasticsearch/client/errors.ts index 356c2e370c471..21452af770ff4 100644 --- a/src/core/server/elasticsearch/client/errors.ts +++ b/src/core/server/elasticsearch/client/errors.ts @@ -6,14 +6,14 @@ * Side Public License, v 1. */ -import { ResponseError } from '@elastic/elasticsearch/lib/errors'; +import { errors } from '@elastic/elasticsearch'; -export type UnauthorizedError = ResponseError & { +export type UnauthorizedError = errors.ResponseError & { statusCode: 401; }; -export function isResponseError(error: unknown): error is ResponseError { - return error instanceof ResponseError; +export function isResponseError(error: unknown): error is errors.ResponseError { + return error instanceof errors.ResponseError; } export function isUnauthorizedError(error: unknown): error is UnauthorizedError { diff --git a/src/core/server/elasticsearch/client/index.ts b/src/core/server/elasticsearch/client/index.ts index 29f8b85695190..2cf5a0229a489 100644 --- a/src/core/server/elasticsearch/client/index.ts +++ b/src/core/server/elasticsearch/client/index.ts @@ -14,6 +14,7 @@ export type { SearchResponse, GetResponse, DeleteDocumentResponse, + ElasticsearchErrorDetails, } from './types'; export { ScopedClusterClient } from './scoped_cluster_client'; export type { IScopedClusterClient } from './scoped_cluster_client'; diff --git a/src/core/server/elasticsearch/client/mocks.test.ts b/src/core/server/elasticsearch/client/mocks.test.ts index e3619e094c8cb..30b50e19f6c7e 100644 --- a/src/core/server/elasticsearch/client/mocks.test.ts +++ b/src/core/server/elasticsearch/client/mocks.test.ts @@ -39,9 +39,9 @@ describe('Mocked client', () => { }); it('used EventEmitter functions should be mocked', () => { - expectMocked(client.on); - expectMocked(client.off); - expectMocked(client.once); + expectMocked(client.diagnostic.on); + expectMocked(client.diagnostic.off); + expectMocked(client.diagnostic.once); }); it('`child` should be mocked and return a mocked Client', () => { diff --git a/src/core/server/elasticsearch/client/mocks.ts b/src/core/server/elasticsearch/client/mocks.ts index 7c4cde1ae424d..16eaf6c49a735 100644 --- a/src/core/server/elasticsearch/client/mocks.ts +++ b/src/core/server/elasticsearch/client/mocks.ts @@ -6,36 +6,33 @@ * Side Public License, v 1. */ -import type { Client, ApiResponse } from '@elastic/elasticsearch'; -import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; +import type { KibanaClient } from '@elastic/elasticsearch/lib/api/kibana'; +import type { TransportResult } from '@elastic/elasticsearch'; import type { DeeplyMockedKeys } from '@kbn/utility-types/jest'; +import type { PublicKeys } from '@kbn/utility-types'; import { ElasticsearchClient } from './types'; import { ICustomClusterClient } from './cluster_client'; -import { PRODUCT_RESPONSE_HEADER } from '../supported_server_response_check'; + +const omittedProps = [ + 'diagnostic', + 'name', + 'connectionPool', + 'transport', + 'serializer', + 'helpers', +] as Array>; + +// the product header expected in every response from es +const PRODUCT_RESPONSE_HEADER = 'x-elastic-product'; // use jest.requireActual() to prevent weird errors when people mock @elastic/elasticsearch const { Client: UnmockedClient } = jest.requireActual('@elastic/elasticsearch'); - -const createInternalClientMock = ( - res?: MockedTransportRequestPromise -): DeeplyMockedKeys => { +const createInternalClientMock = (res?: Promise): DeeplyMockedKeys => { // we mimic 'reflection' on a concrete instance of the client to generate the mocked functions. const client = new UnmockedClient({ - node: 'http://localhost', + node: 'http://127.0.0.1', }); - const omittedProps = [ - '_events', - '_eventsCount', - '_maxListeners', - 'constructor', - 'name', - 'serializer', - 'connectionPool', - 'transport', - 'helpers', - ]; - const getAllPropertyDescriptors = (obj: Record) => { const descriptors = Object.entries(Object.getOwnPropertyDescriptors(obj)); let prototype = Object.getPrototypeOf(obj); @@ -77,21 +74,21 @@ const createInternalClientMock = ( }; // `on`, `off`, and `once` are properties without a setter. - // We can't `client.on = jest.fn()` because the following error will be thrown: + // We can't `client.diagnostic.on = jest.fn()` because the following error will be thrown: // TypeError: Cannot set property on of # which has only a getter - mockGetter(client, 'on'); - mockGetter(client, 'off'); - mockGetter(client, 'once'); + mockGetter(client.diagnostic, 'on'); + mockGetter(client.diagnostic, 'off'); + mockGetter(client.diagnostic, 'once'); client.transport = { request: jest.fn(), }; - return client as DeeplyMockedKeys; + return client as DeeplyMockedKeys; }; export type ElasticsearchClientMock = DeeplyMockedKeys; -const createClientMock = (res?: MockedTransportRequestPromise): ElasticsearchClientMock => +const createClientMock = (res?: Promise): ElasticsearchClientMock => createInternalClientMock(res) as unknown as ElasticsearchClientMock; export interface ScopedClusterClientMock { @@ -139,31 +136,23 @@ const createCustomClusterClientMock = () => { return mock; }; -export type MockedTransportRequestPromise = TransportRequestPromise & { - abort: jest.MockedFunction<() => undefined>; -}; - const createSuccessTransportRequestPromise = ( body: T, { statusCode = 200 }: { statusCode?: number } = {}, headers: Record = { [PRODUCT_RESPONSE_HEADER]: 'Elasticsearch' } -): MockedTransportRequestPromise> => { +): Promise> => { const response = createApiResponse({ body, statusCode, headers }); - const promise = Promise.resolve(response); - (promise as MockedTransportRequestPromise>).abort = jest.fn(); - return promise as MockedTransportRequestPromise>; + return Promise.resolve(response) as Promise>; }; -const createErrorTransportRequestPromise = (err: any): MockedTransportRequestPromise => { - const promise = Promise.reject(err); - (promise as MockedTransportRequestPromise).abort = jest.fn(); - return promise as MockedTransportRequestPromise; +const createErrorTransportRequestPromise = (err: any): Promise> => { + return Promise.reject(err); }; function createApiResponse>( - opts: Partial> = {} -): ApiResponse { + opts: Partial> = {} +): TransportResult { return { body: {} as any, statusCode: 200, diff --git a/src/core/server/elasticsearch/client/types.ts b/src/core/server/elasticsearch/client/types.ts index f5a6fa1f0b1fd..e168a4a4a9c21 100644 --- a/src/core/server/elasticsearch/client/types.ts +++ b/src/core/server/elasticsearch/client/types.ts @@ -6,13 +6,12 @@ * Side Public License, v 1. */ -import type { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import type { KibanaClient } from '@elastic/elasticsearch/lib/api/kibana'; import type { - ApiResponse, + TransportResult, TransportRequestOptions, TransportRequestParams, - TransportRequestPromise, -} from '@elastic/elasticsearch/lib/Transport'; +} from '@elastic/elasticsearch'; /** * Client used to query the elasticsearch cluster. @@ -21,13 +20,13 @@ import type { */ export type ElasticsearchClient = Omit< KibanaClient, - 'connectionPool' | 'transport' | 'serializer' | 'extend' | 'child' | 'close' + 'connectionPool' | 'transport' | 'serializer' | 'extend' | 'child' | 'close' | 'diagnostic' > & { transport: { - request( + request( params: TransportRequestParams, options?: TransportRequestOptions - ): TransportRequestPromise; + ): Promise>; }; }; @@ -133,3 +132,10 @@ export interface DeleteDocumentResponse { type: string; }; } + +/** + * @public + */ +export interface ElasticsearchErrorDetails { + error?: { type: string; reason?: string }; +} diff --git a/src/core/server/elasticsearch/index.ts b/src/core/server/elasticsearch/index.ts index 7f0620a03e5f4..cf7d8a0ce0de2 100644 --- a/src/core/server/elasticsearch/index.ts +++ b/src/core/server/elasticsearch/index.ts @@ -35,10 +35,6 @@ export type { ShardsResponse, GetResponse, DeleteDocumentResponse, + ElasticsearchErrorDetails, } from './client'; export { getRequestDebugMeta, getErrorMessage } from './client'; -export { - isSupportedEsServer, - isNotFoundFromUnsupportedServer, - PRODUCT_RESPONSE_HEADER, -} from './supported_server_response_check'; diff --git a/src/core/server/elasticsearch/integration_tests/client.test.ts b/src/core/server/elasticsearch/integration_tests/client.test.ts index f3c9cf27d3b29..05100564dac03 100644 --- a/src/core/server/elasticsearch/integration_tests/client.test.ts +++ b/src/core/server/elasticsearch/integration_tests/client.test.ts @@ -52,17 +52,6 @@ describe('elasticsearch clients', () => { ); expect(resp2.headers).not.toHaveProperty('warning'); }); - - it('returns deprecation warning when x-elastic-product-orign header is not set', async () => { - const resp = - await kibanaServer.coreStart.elasticsearch.client.asInternalUser.indices.getSettings( - { index: '.kibana' }, - { headers: { 'x-elastic-product-origin': null } } - ); - - expect(resp.headers).toHaveProperty('warning'); - expect(resp.headers!.warning).toMatch('system indices'); - }); }); function createFakeElasticsearchServer() { diff --git a/src/core/server/elasticsearch/is_scripting_enabled.test.ts b/src/core/server/elasticsearch/is_scripting_enabled.test.ts index 6dfb4b13edb9f..dd84c29818556 100644 --- a/src/core/server/elasticsearch/is_scripting_enabled.test.ts +++ b/src/core/server/elasticsearch/is_scripting_enabled.test.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { elasticsearchServiceMock } from './elasticsearch_service.mock'; import { isInlineScriptingEnabled } from './is_scripting_enabled'; diff --git a/src/core/server/elasticsearch/supported_server_response_check.test.ts b/src/core/server/elasticsearch/supported_server_response_check.test.ts deleted file mode 100644 index 589e947142fc3..0000000000000 --- a/src/core/server/elasticsearch/supported_server_response_check.test.ts +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ - -import { isNotFoundFromUnsupportedServer } from './supported_server_response_check'; - -describe('#isNotFoundFromUnsupportedServer', () => { - it('returns true with not found response from unsupported server', () => { - const rawResponse = { - statusCode: 404, - headers: {}, - }; - - const result = isNotFoundFromUnsupportedServer(rawResponse); - expect(result).toBe(true); - }); - - it('returns false with not found response from supported server', async () => { - const rawResponse = { - statusCode: 404, - headers: { 'x-elastic-product': 'Elasticsearch' }, - }; - - const result = isNotFoundFromUnsupportedServer(rawResponse); - expect(result).toBe(false); - }); - - it('returns false when not a 404', async () => { - const rawResponse = { - statusCode: 200, - headers: { 'x-elastic-product': 'Elasticsearch' }, - }; - - const result = isNotFoundFromUnsupportedServer(rawResponse); - expect(result).toBe(false); - }); -}); diff --git a/src/core/server/elasticsearch/supported_server_response_check.ts b/src/core/server/elasticsearch/supported_server_response_check.ts deleted file mode 100644 index 85235d04caf5c..0000000000000 --- a/src/core/server/elasticsearch/supported_server_response_check.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0 and the Server Side Public License, v 1; you may not use this file except - * in compliance with, at your election, the Elastic License 2.0 or the Server - * Side Public License, v 1. - */ -export const PRODUCT_RESPONSE_HEADER = 'x-elastic-product'; -/** - * Response headers check to determine if the response is from Elasticsearch - * @param headers Response headers - * @returns boolean - */ -// This check belongs to the elasticsearch service as a dedicated helper method. -export const isSupportedEsServer = (headers: Record | null) => { - return !!headers && headers[PRODUCT_RESPONSE_HEADER] === 'Elasticsearch'; -}; - -/** - * Check to ensure that a 404 response does not come from Elasticsearch - * - * WARNING: This is a hack to work around for 404 responses returned from a proxy. - * We're aiming to minimise the risk of data loss when consumers act on Not Found errors - * - * @param response response from elasticsearch client call - * @returns boolean 'true' if the status code is 404 and the Elasticsearch product header is missing/unexpected value - */ -export const isNotFoundFromUnsupportedServer = (args: { - statusCode: number | null; - headers: Record | null; -}): boolean => { - return args.statusCode === 404 && !isSupportedEsServer(args.headers); -}; diff --git a/src/core/server/elasticsearch/version_check/ensure_es_version.test.ts b/src/core/server/elasticsearch/version_check/ensure_es_version.test.ts index 70166704679fe..c9bb82d5da65c 100644 --- a/src/core/server/elasticsearch/version_check/ensure_es_version.test.ts +++ b/src/core/server/elasticsearch/version_check/ensure_es_version.test.ts @@ -139,6 +139,7 @@ describe('pollEsNodesVersion', () => { }); const nodeInfosSuccessOnce = (infos: NodesInfo) => { + // @ts-expect-error not full interface internalClient.nodes.info.mockImplementationOnce(() => createEsSuccess(infos)); }; const nodeInfosErrorOnce = (error: any) => { diff --git a/src/core/server/http/integration_tests/core_services.test.ts b/src/core/server/http/integration_tests/core_services.test.ts index 84eed0511cb23..4bf64a96cf773 100644 --- a/src/core/server/http/integration_tests/core_services.test.ts +++ b/src/core/server/http/integration_tests/core_services.test.ts @@ -8,7 +8,7 @@ import { MockElasticsearchClient } from './core_service.test.mocks'; import { elasticsearchClientMock } from '../../elasticsearch/client/mocks'; -import { ResponseError } from '@elastic/elasticsearch/lib/errors'; +import { errors } from '@elastic/elasticsearch'; import * as kbnTestServer from '../../../test_helpers/kbn_server'; import { InternalElasticsearchServiceStart } from '../../elasticsearch'; @@ -205,7 +205,7 @@ describe('http service', () => { esClient.ping.mockImplementation(() => elasticsearchClientMock.createErrorTransportRequestPromise( - new ResponseError({ + new errors.ResponseError({ statusCode: 401, body: { error: { @@ -243,7 +243,7 @@ describe('http service', () => { esClient.ping.mockImplementation(() => elasticsearchClientMock.createErrorTransportRequestPromise( - new ResponseError({ + new errors.ResponseError({ statusCode: 401, body: { error: { @@ -279,7 +279,7 @@ describe('http service', () => { esClient.ping.mockImplementation(() => elasticsearchClientMock.createErrorTransportRequestPromise( - new ResponseError({ + new errors.ResponseError({ statusCode: 404, body: { error: { diff --git a/src/core/server/http/router/response_adapter.ts b/src/core/server/http/router/response_adapter.ts index b03449b2ae194..753c11d5f45ae 100644 --- a/src/core/server/http/router/response_adapter.ts +++ b/src/core/server/http/router/response_adapter.ts @@ -15,6 +15,7 @@ import Boom from '@hapi/boom'; import * as stream from 'stream'; import { isResponseError as isElasticsearchResponseError } from '../../elasticsearch/client/errors'; +import { ElasticsearchErrorDetails } from '../../elasticsearch'; import { HttpResponsePayload, @@ -154,7 +155,9 @@ function getErrorMessage(payload?: ResponseError): string { if (typeof payload === 'string') return payload; // for ES response errors include nested error reason message. it doesn't contain sensitive data. if (isElasticsearchResponseError(payload)) { - return `[${payload.message}]: ${payload.meta.body?.error?.reason}`; + return `[${payload.message}]: ${ + (payload.meta.body as ElasticsearchErrorDetails)?.error?.reason + }`; } return getErrorMessage(payload.message); diff --git a/src/core/server/http/router/router.ts b/src/core/server/http/router/router.ts index d2d8dfa2cc72f..be3b24d5d19a7 100644 --- a/src/core/server/http/router/router.ts +++ b/src/core/server/http/router/router.ts @@ -289,10 +289,10 @@ export class Router { const getAuthenticateHeaderValue = () => { - const header = Object.entries(e.headers).find( + const header = Object.entries(e.headers || {}).find( ([key]) => key.toLowerCase() === 'www-authenticate' ); - return header ? header[1] : 'Basic realm="Authorization Required"'; + return header ? (header[1] as string) : 'Basic realm="Authorization Required"'; }; return { body: e.message, diff --git a/src/core/server/index.ts b/src/core/server/index.ts index c92a91c96da95..bb91b9f9be98f 100644 --- a/src/core/server/index.ts +++ b/src/core/server/index.ts @@ -136,6 +136,7 @@ export type { GetResponse, DeleteDocumentResponse, ElasticsearchConfigPreboot, + ElasticsearchErrorDetails, } from './elasticsearch'; export type { IExternalUrlConfig, IExternalUrlPolicy } from './external_url'; diff --git a/src/core/server/saved_objects/deprecations/unknown_object_types.test.ts b/src/core/server/saved_objects/deprecations/unknown_object_types.test.ts index 3f8fce0bc1c87..5b2687262ab36 100644 --- a/src/core/server/saved_objects/deprecations/unknown_object_types.test.ts +++ b/src/core/server/saved_objects/deprecations/unknown_object_types.test.ts @@ -8,7 +8,7 @@ import { getIndexForTypeMock } from './unknown_object_types.test.mocks'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { deleteUnknownTypeObjects, getUnknownTypesDeprecations } from './unknown_object_types'; import { typeRegistryMock } from '../saved_objects_type_registry.mock'; import { elasticsearchClientMock } from '../../elasticsearch/client/mocks'; diff --git a/src/core/server/saved_objects/deprecations/unknown_object_types.ts b/src/core/server/saved_objects/deprecations/unknown_object_types.ts index 1b34dcad64010..8815065984a27 100644 --- a/src/core/server/saved_objects/deprecations/unknown_object_types.ts +++ b/src/core/server/saved_objects/deprecations/unknown_object_types.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { i18n } from '@kbn/i18n'; import type { DeprecationsDetails } from '../../deprecations'; import { IScopedClusterClient } from '../../elasticsearch'; diff --git a/src/core/server/saved_objects/mappings/types.ts b/src/core/server/saved_objects/mappings/types.ts index e2ad2a91fd000..e225d0ff31022 100644 --- a/src/core/server/saved_objects/mappings/types.ts +++ b/src/core/server/saved_objects/mappings/types.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; /** * Describe a saved object type mapping. * diff --git a/src/core/server/saved_objects/migrations/core/call_cluster.ts b/src/core/server/saved_objects/migrations/core/call_cluster.ts index d158bf7d131f5..156689c8d96f9 100644 --- a/src/core/server/saved_objects/migrations/core/call_cluster.ts +++ b/src/core/server/saved_objects/migrations/core/call_cluster.ts @@ -12,7 +12,7 @@ * funcationality contained here. */ -import type { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; export type AliasAction = | { diff --git a/src/core/server/saved_objects/migrations/core/elastic_index.test.ts b/src/core/server/saved_objects/migrations/core/elastic_index.test.ts index 15bd1d46b092b..2cdeb479f50f9 100644 --- a/src/core/server/saved_objects/migrations/core/elastic_index.test.ts +++ b/src/core/server/saved_objects/migrations/core/elastic_index.test.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import _ from 'lodash'; import { elasticsearchClientMock } from '../../../elasticsearch/client/mocks'; import * as Index from './elastic_index'; @@ -164,7 +164,7 @@ describe('ElasticIndex', () => { client.tasks.get.mockResolvedValue( elasticsearchClientMock.createSuccessTransportRequestPromise({ completed: true, - } as estypes.TaskGetResponse) + } as estypes.TasksGetResponse) ); const info = { @@ -248,7 +248,7 @@ describe('ElasticIndex', () => { reason: 'all shards failed', failed_shards: [], }, - } as estypes.TaskGetResponse) + } as estypes.TasksGetResponse) ); const info = { diff --git a/src/core/server/saved_objects/migrations/core/elastic_index.ts b/src/core/server/saved_objects/migrations/core/elastic_index.ts index dc98139ad513e..64df079897722 100644 --- a/src/core/server/saved_objects/migrations/core/elastic_index.ts +++ b/src/core/server/saved_objects/migrations/core/elastic_index.ts @@ -12,7 +12,7 @@ */ import _ from 'lodash'; -import { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { MigrationEsClient } from './migration_es_client'; import { IndexMapping } from '../../mappings'; import { SavedObjectsMigrationVersion } from '../../types'; diff --git a/src/core/server/saved_objects/migrations/core/index_migrator.test.ts b/src/core/server/saved_objects/migrations/core/index_migrator.test.ts index 64d4fa3609e90..beb0c1d3651c6 100644 --- a/src/core/server/saved_objects/migrations/core/index_migrator.test.ts +++ b/src/core/server/saved_objects/migrations/core/index_migrator.test.ts @@ -7,7 +7,7 @@ */ import _ from 'lodash'; -import type { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { elasticsearchClientMock } from '../../../elasticsearch/client/mocks'; import { SavedObjectUnsanitizedDoc, SavedObjectsSerializer } from '../../serialization'; import { SavedObjectTypeRegistry } from '../../saved_objects_type_registry'; @@ -450,7 +450,7 @@ function withIndex( client.tasks.get.mockReturnValue( elasticsearchClientMock.createSuccessTransportRequestPromise({ completed: true, - } as estypes.TaskGetResponse) + } as estypes.TasksGetResponse) ); client.search.mockReturnValue( elasticsearchClientMock.createSuccessTransportRequestPromise(searchResult(0) as any) diff --git a/src/core/server/saved_objects/migrations/core/migration_es_client.ts b/src/core/server/saved_objects/migrations/core/migration_es_client.ts index e8dc9c94b7861..243b724eb2a67 100644 --- a/src/core/server/saved_objects/migrations/core/migration_es_client.ts +++ b/src/core/server/saved_objects/migrations/core/migration_es_client.ts @@ -5,8 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ - -import type { TransportRequestOptions } from '@elastic/elasticsearch/lib/Transport'; +import type { Client, TransportRequestOptions } from '@elastic/elasticsearch'; import { get } from 'lodash'; import { set } from '@elastic/safer-lodash-set'; @@ -58,7 +57,7 @@ export interface MigrationEsClient { } export function createMigrationEsClient( - client: ElasticsearchClient, + client: ElasticsearchClient | Client, log: Logger, delay?: number ): MigrationEsClient { @@ -69,7 +68,7 @@ export function createMigrationEsClient( throw new Error(`unknown ElasticsearchClient client method [${key}]`); } return await migrationRetryCallCluster( - () => fn.call(client, params, { maxRetries: 0, ...options }), + () => fn.call(client, params, { maxRetries: 0, meta: true, ...options }), log, delay ); diff --git a/src/core/server/saved_objects/migrations/kibana/kibana_migrator.test.ts b/src/core/server/saved_objects/migrations/kibana/kibana_migrator.test.ts index 90274de557fdf..599b5dca0d904 100644 --- a/src/core/server/saved_objects/migrations/kibana/kibana_migrator.test.ts +++ b/src/core/server/saved_objects/migrations/kibana/kibana_migrator.test.ts @@ -7,7 +7,7 @@ */ import { take } from 'rxjs/operators'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { elasticsearchClientMock } from '../../../elasticsearch/client/mocks'; import { KibanaMigratorOptions, KibanaMigrator } from './kibana_migrator'; @@ -252,7 +252,7 @@ const mockV2MigrationOptions = () => { error: undefined, failures: [], task: { description: 'task description' } as any, - } as estypes.TaskGetResponse) + } as estypes.TasksGetResponse) ); options.client.search = jest diff --git a/src/core/server/saved_objects/migrationsv2/actions/bulk_overwrite_transformed_documents.ts b/src/core/server/saved_objects/migrationsv2/actions/bulk_overwrite_transformed_documents.ts index 9353ede9be6ac..f3ddc0c308970 100644 --- a/src/core/server/saved_objects/migrationsv2/actions/bulk_overwrite_transformed_documents.ts +++ b/src/core/server/saved_objects/migrationsv2/actions/bulk_overwrite_transformed_documents.ts @@ -8,7 +8,8 @@ import * as Either from 'fp-ts/lib/Either'; import * as TaskEither from 'fp-ts/lib/TaskEither'; -import { errors as esErrors, estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { errors as esErrors } from '@elastic/elasticsearch'; import { ElasticsearchClient } from '../../../elasticsearch'; import type { SavedObjectsRawDoc } from '../../serialization'; import { @@ -92,7 +93,7 @@ export const bulkOverwriteTransformedDocuments = .then((res) => { // Filter out version_conflict_engine_exception since these just mean // that another instance already updated these documents - const errors = (res.body.items ?? []) + const errors: estypes.ErrorCause[] = (res.body.items ?? []) .filter((item) => item.index?.error) .map((item) => item.index!.error!) .filter(({ type }) => type !== 'version_conflict_engine_exception'); diff --git a/src/core/server/saved_objects/migrationsv2/actions/calculate_exclude_filters.ts b/src/core/server/saved_objects/migrationsv2/actions/calculate_exclude_filters.ts index 9ba098d01870f..2b35e3b59e988 100644 --- a/src/core/server/saved_objects/migrationsv2/actions/calculate_exclude_filters.ts +++ b/src/core/server/saved_objects/migrationsv2/actions/calculate_exclude_filters.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { withTimeout } from '@kbn/std'; import * as Either from 'fp-ts/lib/Either'; import * as TaskEither from 'fp-ts/lib/TaskEither'; diff --git a/src/core/server/saved_objects/migrationsv2/actions/catch_retryable_es_client_errors.ts b/src/core/server/saved_objects/migrationsv2/actions/catch_retryable_es_client_errors.ts index 3d9a51e3b1eba..168e3170d30bf 100644 --- a/src/core/server/saved_objects/migrationsv2/actions/catch_retryable_es_client_errors.ts +++ b/src/core/server/saved_objects/migrationsv2/actions/catch_retryable_es_client_errors.ts @@ -31,7 +31,7 @@ export const catchRetryableEsClientErrors = ( e instanceof EsErrors.ConnectionError || e instanceof EsErrors.TimeoutError || (e instanceof EsErrors.ResponseError && - (retryResponseStatuses.includes(e?.statusCode) || + (retryResponseStatuses.includes(e?.statusCode!) || // ES returns a 400 Bad Request when trying to close or delete an // index while snapshots are in progress. This should have been a 503 // so once https://github.com/elastic/elasticsearch/issues/65883 is diff --git a/src/core/server/saved_objects/migrationsv2/actions/check_for_unknown_docs.test.ts b/src/core/server/saved_objects/migrationsv2/actions/check_for_unknown_docs.test.ts index a52cb2a922968..8a99d28b40de1 100644 --- a/src/core/server/saved_objects/migrationsv2/actions/check_for_unknown_docs.test.ts +++ b/src/core/server/saved_objects/migrationsv2/actions/check_for_unknown_docs.test.ts @@ -8,7 +8,8 @@ import * as Either from 'fp-ts/lib/Either'; import { catchRetryableEsClientErrors } from './catch_retryable_es_client_errors'; -import { errors as EsErrors, estypes } from '@elastic/elasticsearch'; +import { errors as EsErrors } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { elasticsearchClientMock } from '../../../elasticsearch/client/mocks'; import { checkForUnknownDocs } from './check_for_unknown_docs'; diff --git a/src/core/server/saved_objects/migrationsv2/actions/check_for_unknown_docs.ts b/src/core/server/saved_objects/migrationsv2/actions/check_for_unknown_docs.ts index 1db47f0083467..cfeda0548b16a 100644 --- a/src/core/server/saved_objects/migrationsv2/actions/check_for_unknown_docs.ts +++ b/src/core/server/saved_objects/migrationsv2/actions/check_for_unknown_docs.ts @@ -8,7 +8,7 @@ import * as Either from 'fp-ts/lib/Either'; import * as TaskEither from 'fp-ts/lib/TaskEither'; -import { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { SavedObjectsRawDocSource } from '../../serialization'; import { ElasticsearchClient } from '../../../elasticsearch'; import { diff --git a/src/core/server/saved_objects/migrationsv2/actions/create_index.ts b/src/core/server/saved_objects/migrationsv2/actions/create_index.ts index d5269233344c3..9fa8aebcd7dc1 100644 --- a/src/core/server/saved_objects/migrationsv2/actions/create_index.ts +++ b/src/core/server/saved_objects/migrationsv2/actions/create_index.ts @@ -9,7 +9,7 @@ import * as Either from 'fp-ts/lib/Either'; import * as TaskEither from 'fp-ts/lib/TaskEither'; import { pipe } from 'fp-ts/lib/pipeable'; -import type { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { AcknowledgeResponse } from './index'; import { ElasticsearchClient } from '../../../elasticsearch'; import { IndexMapping } from '../../mappings'; @@ -100,7 +100,7 @@ export const createIndex = ({ * - acknowledged=true, shards_acknowledged=true, index creation complete */ return Either.right({ - acknowledged: res.body.acknowledged, + acknowledged: Boolean(res.body.acknowledged), shardsAcknowledged: res.body.shards_acknowledged, }); }) diff --git a/src/core/server/saved_objects/migrationsv2/actions/es_errors.ts b/src/core/server/saved_objects/migrationsv2/actions/es_errors.ts index 49b996bb118d8..4f560468bcb0c 100644 --- a/src/core/server/saved_objects/migrationsv2/actions/es_errors.ts +++ b/src/core/server/saved_objects/migrationsv2/actions/es_errors.ts @@ -5,23 +5,19 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; -export interface EsErrorCause { - type: string; - reason: string; -} - -export const isWriteBlockException = ({ type, reason }: EsErrorCause): boolean => { +export const isWriteBlockException = ({ type, reason }: estypes.ErrorCause): boolean => { return ( type === 'cluster_block_exception' && reason.match(/index \[.+] blocked by: \[FORBIDDEN\/8\/.+ \(api\)\]/) !== null ); }; -export const isIncompatibleMappingException = ({ type }: EsErrorCause): boolean => { +export const isIncompatibleMappingException = ({ type }: estypes.ErrorCause): boolean => { return type === 'strict_dynamic_mapping_exception' || type === 'mapper_parsing_exception'; }; -export const isIndexNotFoundException = ({ type }: EsErrorCause): boolean => { +export const isIndexNotFoundException = ({ type }: estypes.ErrorCause): boolean => { return type === 'index_not_found_exception'; }; diff --git a/src/core/server/saved_objects/migrationsv2/actions/integration_tests/actions.test.ts b/src/core/server/saved_objects/migrationsv2/actions/integration_tests/actions.test.ts index 0a5864dcefac2..3ca3a8505338b 100644 --- a/src/core/server/saved_objects/migrationsv2/actions/integration_tests/actions.test.ts +++ b/src/core/server/saved_objects/migrationsv2/actions/integration_tests/actions.test.ts @@ -38,7 +38,7 @@ import { } from '../../actions'; import * as Either from 'fp-ts/lib/Either'; import * as Option from 'fp-ts/lib/Option'; -import { ResponseError } from '@elastic/elasticsearch/lib/errors'; +import { errors } from '@elastic/elasticsearch'; import { DocumentsTransformFailed, DocumentsTransformSuccess } from '../../../migrations/core'; import { TaskEither } from 'fp-ts/lib/TaskEither'; import Path from 'path'; @@ -61,7 +61,7 @@ describe.skip('migration actions', () => { beforeAll(async () => { esServer = await startES(); - client = esServer.es.getClient(); + client = esServer.es.getKibanaEsClient(); // Create test fixture data: await createIndex({ @@ -281,7 +281,7 @@ describe.skip('migration actions', () => { index: 'red_then_yellow_index', body: { // Enable all shard allocation so that the index status turns yellow - settings: { routing: { allocation: { enable: 'all' } } }, + routing: { allocation: { enable: 'all' } }, }, }); @@ -351,7 +351,7 @@ describe.skip('migration actions', () => { index: 'clone_red_then_yellow_index', body: { // Enable all shard allocation so that the index status goes yellow - settings: { routing: { allocation: { enable: 'all' } } }, + routing: { allocation: { enable: 'all' } }, }, }); indexYellow = true; @@ -413,7 +413,7 @@ describe.skip('migration actions', () => { await expect(cloneIndexPromise).resolves.toMatchObject({ _tag: 'Left', left: { - error: expect.any(ResponseError), + error: expect.any(errors.ResponseError), message: expect.stringMatching(/\"timed_out\":true/), type: 'retryable_es_client_error', }, @@ -811,7 +811,7 @@ describe.skip('migration actions', () => { await expect(task()).resolves.toMatchObject({ _tag: 'Left', left: { - error: expect.any(ResponseError), + error: expect.any(errors.ResponseError), message: expect.stringMatching( /\[timeout_exception\] Timed out waiting for completion of \[org.elasticsearch.index.reindex.BulkByScrollTask/ ), @@ -1170,7 +1170,7 @@ describe.skip('migration actions', () => { await expect(task()).resolves.toMatchObject({ _tag: 'Left', left: { - error: expect.any(ResponseError), + error: expect.any(errors.ResponseError), message: expect.stringMatching( /\[timeout_exception\] Timed out waiting for completion of \[org.elasticsearch.index.reindex.BulkByScrollTask/ ), @@ -1445,7 +1445,7 @@ describe.skip('migration actions', () => { index: 'red_then_yellow_index', body: { // Disable all shard allocation so that the index status is red - settings: { routing: { allocation: { enable: 'all' } } }, + routing: { allocation: { enable: 'all' } }, }, }); indexYellow = true; diff --git a/src/core/server/saved_objects/migrationsv2/actions/integration_tests/es_errors.test.ts b/src/core/server/saved_objects/migrationsv2/actions/integration_tests/es_errors.test.ts index e259b375736d5..2473d8d3ae410 100644 --- a/src/core/server/saved_objects/migrationsv2/actions/integration_tests/es_errors.test.ts +++ b/src/core/server/saved_objects/migrationsv2/actions/integration_tests/es_errors.test.ts @@ -5,7 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ - +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ElasticsearchClient } from '../../../../'; import { InternalCoreStart } from '../../../../internal_types'; import * as kbnTestServer from '../../../../../test_helpers/kbn_server'; @@ -100,7 +100,7 @@ describe('Elasticsearch Errors', () => { ], }); - const cause = res.body.items[0].index!.error!; + const cause = res.body.items[0].index!.error! as estypes.ErrorCause; expect(isWriteBlockException(cause)).toEqual(true); }); @@ -122,7 +122,7 @@ describe('Elasticsearch Errors', () => { ], }); - const cause = res.body.items[0].create!.error!; + const cause = res.body.items[0].create!.error! as estypes.ErrorCause; expect(isWriteBlockException(cause)).toEqual(true); }); diff --git a/src/core/server/saved_objects/migrationsv2/actions/read_with_pit.ts b/src/core/server/saved_objects/migrationsv2/actions/read_with_pit.ts index c8e7d61dce811..0902e206147d3 100644 --- a/src/core/server/saved_objects/migrationsv2/actions/read_with_pit.ts +++ b/src/core/server/saved_objects/migrationsv2/actions/read_with_pit.ts @@ -8,7 +8,7 @@ import * as Either from 'fp-ts/lib/Either'; import * as TaskEither from 'fp-ts/lib/TaskEither'; -import type { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ElasticsearchClient } from '../../../elasticsearch'; import type { SavedObjectsRawDoc } from '../../serialization'; import { diff --git a/src/core/server/saved_objects/migrationsv2/actions/reindex.ts b/src/core/server/saved_objects/migrationsv2/actions/reindex.ts index 92134d2755ac3..e8e054c7a1780 100644 --- a/src/core/server/saved_objects/migrationsv2/actions/reindex.ts +++ b/src/core/server/saved_objects/migrationsv2/actions/reindex.ts @@ -9,7 +9,7 @@ import * as Either from 'fp-ts/lib/Either'; import * as TaskEither from 'fp-ts/lib/TaskEither'; import * as Option from 'fp-ts/lib/Option'; -import type { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ElasticsearchClient } from '../../../elasticsearch'; import { catchRetryableEsClientErrors, diff --git a/src/core/server/saved_objects/migrationsv2/actions/remove_write_block.ts b/src/core/server/saved_objects/migrationsv2/actions/remove_write_block.ts index 77445654d3cc3..cca9ea5e7598e 100644 --- a/src/core/server/saved_objects/migrationsv2/actions/remove_write_block.ts +++ b/src/core/server/saved_objects/migrationsv2/actions/remove_write_block.ts @@ -41,10 +41,8 @@ export const removeWriteBlock = // Don't change any existing settings preserve_existing: true, body: { - settings: { - blocks: { - write: false, - }, + blocks: { + write: false, }, }, }, diff --git a/src/core/server/saved_objects/migrationsv2/actions/search_for_outdated_documents.ts b/src/core/server/saved_objects/migrationsv2/actions/search_for_outdated_documents.ts index 5a6cb3a3d048d..5a92a7c6cc286 100644 --- a/src/core/server/saved_objects/migrationsv2/actions/search_for_outdated_documents.ts +++ b/src/core/server/saved_objects/migrationsv2/actions/search_for_outdated_documents.ts @@ -8,7 +8,7 @@ import * as Either from 'fp-ts/lib/Either'; import * as TaskEither from 'fp-ts/lib/TaskEither'; -import type { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ElasticsearchClient } from '../../../elasticsearch'; import type { SavedObjectsRawDoc, SavedObjectsRawDocSource } from '../../serialization'; import { diff --git a/src/core/server/saved_objects/migrationsv2/actions/set_write_block.ts b/src/core/server/saved_objects/migrationsv2/actions/set_write_block.ts index db519d0246511..9c40e1b64fae0 100644 --- a/src/core/server/saved_objects/migrationsv2/actions/set_write_block.ts +++ b/src/core/server/saved_objects/migrationsv2/actions/set_write_block.ts @@ -6,7 +6,6 @@ * Side Public License, v 1. */ -import type { ElasticsearchClientError } from '@elastic/elasticsearch/lib/errors'; import * as Either from 'fp-ts/lib/Either'; import * as TaskEither from 'fp-ts/lib/TaskEither'; import { errors as EsErrors } from '@elastic/elasticsearch'; @@ -61,7 +60,7 @@ export const setWriteBlock = message: 'set_write_block_failed', }); }) - .catch((e: ElasticsearchClientError) => { + .catch((e: EsErrors.ElasticsearchClientError) => { if (e instanceof EsErrors.ResponseError) { if (e.body?.error?.type === 'index_not_found_exception') { return Either.left({ type: 'index_not_found_exception' as const, index }); diff --git a/src/core/server/saved_objects/migrationsv2/actions/wait_for_task.ts b/src/core/server/saved_objects/migrationsv2/actions/wait_for_task.ts index 212e1ad9c8c81..1a319d17dbce9 100644 --- a/src/core/server/saved_objects/migrationsv2/actions/wait_for_task.ts +++ b/src/core/server/saved_objects/migrationsv2/actions/wait_for_task.ts @@ -5,6 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import * as Either from 'fp-ts/lib/Either'; import * as TaskEither from 'fp-ts/lib/TaskEither'; import * as Option from 'fp-ts/lib/Option'; @@ -86,7 +87,7 @@ export const waitForTask = const failures = body.response?.failures ?? []; return Either.right({ completed: body.completed, - error: Option.fromNullable(body.error), + error: Option.fromNullable(body.error as estypes.ErrorCauseKeys), failures: failures.length > 0 ? Option.some(failures) : Option.none, description: body.task.description, }); diff --git a/src/core/server/saved_objects/migrationsv2/integration_tests/7_13_0_failed_action_tasks.test.ts b/src/core/server/saved_objects/migrationsv2/integration_tests/7_13_0_failed_action_tasks.test.ts index a4ce95a9e0584..479b1e78e1b72 100644 --- a/src/core/server/saved_objects/migrationsv2/integration_tests/7_13_0_failed_action_tasks.test.ts +++ b/src/core/server/saved_objects/migrationsv2/integration_tests/7_13_0_failed_action_tasks.test.ts @@ -55,7 +55,7 @@ describe('migration from 7.13 to 7.14+ with many failed action_tasks', () => { kibanaIndexName = '.kibana', taskManagerIndexName = '.kibana_task_manager' ): Promise<{ tasksCount: number; actionTaskParamsCount: number }> => { - const esClient: ElasticsearchClient = esServer.es.getClient(); + const esClient: ElasticsearchClient = esServer.es.getKibanaEsClient(); const actionTaskParamsResponse = await esClient.count({ index: kibanaIndexName, diff --git a/src/core/server/saved_objects/migrationsv2/integration_tests/7_13_0_unknown_types.test.ts b/src/core/server/saved_objects/migrationsv2/integration_tests/7_13_0_unknown_types.test.ts index a04300ffea626..aea84cea22862 100644 --- a/src/core/server/saved_objects/migrationsv2/integration_tests/7_13_0_unknown_types.test.ts +++ b/src/core/server/saved_objects/migrationsv2/integration_tests/7_13_0_unknown_types.test.ts @@ -8,7 +8,7 @@ import Path from 'path'; import fs from 'fs/promises'; -import { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import * as kbnTestServer from '../../../../test_helpers/kbn_server'; import { Root } from '../../../root'; import JSON5 from 'json5'; @@ -114,7 +114,7 @@ describe('migration v2', () => { ); }); - const client: ElasticsearchClient = esServer.es.getClient(); + const client: ElasticsearchClient = esServer.es.getKibanaEsClient(); const { body: response } = await client.indices.getSettings({ index: targetIndex, }); @@ -178,7 +178,7 @@ describe('migration v2', () => { }); await root.start(); - const client: ElasticsearchClient = esServer.es.getClient(); + const client: ElasticsearchClient = esServer.es.getKibanaEsClient(); const spacesDocsMigrated = await fetchDocs(client, targetIndex, 'space'); expect(spacesDocsMigrated.map((s) => s.id)).toEqual( expect.arrayContaining([ diff --git a/src/core/server/saved_objects/migrationsv2/integration_tests/batch_size_bytes.test.ts b/src/core/server/saved_objects/migrationsv2/integration_tests/batch_size_bytes.test.ts index de25c7b1c6412..e444a3b1a8bdb 100644 --- a/src/core/server/saved_objects/migrationsv2/integration_tests/batch_size_bytes.test.ts +++ b/src/core/server/saved_objects/migrationsv2/integration_tests/batch_size_bytes.test.ts @@ -95,7 +95,7 @@ describe('migration v2', () => { // wait a bit for the count to settle. await new Promise((resolve) => setTimeout(resolve, 5000)); - const esClient: ElasticsearchClient = esServer.es.getClient(); + const esClient: ElasticsearchClient = esServer.es.getKibanaEsClient(); // assert that the docs from the original index have been migrated rather than comparing a doc count after startup const originalDocs = await fetchDocuments(esClient, '.kibana_7.14.0_001'); diff --git a/src/core/server/saved_objects/migrationsv2/integration_tests/batch_size_bytes_exceeds_es_content_length.test.ts b/src/core/server/saved_objects/migrationsv2/integration_tests/batch_size_bytes_exceeds_es_content_length.test.ts index b47156e3a1e9e..d992193730a34 100644 --- a/src/core/server/saved_objects/migrationsv2/integration_tests/batch_size_bytes_exceeds_es_content_length.test.ts +++ b/src/core/server/saved_objects/migrationsv2/integration_tests/batch_size_bytes_exceeds_es_content_length.test.ts @@ -20,7 +20,8 @@ async function removeLogFile() { await fs.unlink(logFilePath).catch(() => void 0); } -describe('migration v2', () => { +// un-skip after https://github.com/elastic/kibana/issues/116111 +describe.skip('migration v2', () => { let esServer: kbnTestServer.TestElasticsearchUtils; let root: Root; let startES: () => Promise; diff --git a/src/core/server/saved_objects/migrationsv2/integration_tests/cleanup.test.ts b/src/core/server/saved_objects/migrationsv2/integration_tests/cleanup.test.ts index c84f72b184261..4f3026c619d3c 100644 --- a/src/core/server/saved_objects/migrationsv2/integration_tests/cleanup.test.ts +++ b/src/core/server/saved_objects/migrationsv2/integration_tests/cleanup.test.ts @@ -133,7 +133,7 @@ describe('migration v2', () => { const pitId = logRecordWithPit.right.pitId; expect(pitId).toBeTruthy(); - const client = esServer.es.getClient(); + const client = esServer.es.getKibanaEsClient(); await expect( client.search({ body: { diff --git a/src/core/server/saved_objects/migrationsv2/integration_tests/multiple_es_nodes.test.ts b/src/core/server/saved_objects/migrationsv2/integration_tests/multiple_es_nodes.test.ts index 6956e53ebc7fa..fabc9222b6858 100644 --- a/src/core/server/saved_objects/migrationsv2/integration_tests/multiple_es_nodes.test.ts +++ b/src/core/server/saved_objects/migrationsv2/integration_tests/multiple_es_nodes.test.ts @@ -179,7 +179,7 @@ describe('migration v2', () => { }); await root.start(); - const esClient = esServer.es.getClient(); + const esClient = esServer.es.getKibanaEsClient(); const migratedFooDocs = await fetchDocs(esClient, migratedIndex, 'foo'); expect(migratedFooDocs.length).toBe(2500); diff --git a/src/core/server/saved_objects/migrationsv2/integration_tests/multiple_kibana_nodes.test.ts b/src/core/server/saved_objects/migrationsv2/integration_tests/multiple_kibana_nodes.test.ts index ef92c823182d8..5d0d662a5360b 100644 --- a/src/core/server/saved_objects/migrationsv2/integration_tests/multiple_kibana_nodes.test.ts +++ b/src/core/server/saved_objects/migrationsv2/integration_tests/multiple_kibana_nodes.test.ts @@ -182,7 +182,7 @@ describe('migration v2', () => { await startWithDelay([rootA, rootB, rootC], 0); - const esClient = esServer.es.getClient(); + const esClient = esServer.es.getKibanaEsClient(); const migratedDocs = await fetchDocs(esClient, migratedIndex); expect(migratedDocs.length).toBe(5000); @@ -201,7 +201,7 @@ describe('migration v2', () => { await startWithDelay([rootA, rootB, rootC], 1); - const esClient = esServer.es.getClient(); + const esClient = esServer.es.getKibanaEsClient(); const migratedDocs = await fetchDocs(esClient, migratedIndex); expect(migratedDocs.length).toBe(5000); @@ -220,7 +220,7 @@ describe('migration v2', () => { await startWithDelay([rootA, rootB, rootC], 5); - const esClient = esServer.es.getClient(); + const esClient = esServer.es.getKibanaEsClient(); const migratedDocs = await fetchDocs(esClient, migratedIndex); expect(migratedDocs.length).toBe(5000); @@ -239,7 +239,7 @@ describe('migration v2', () => { await startWithDelay([rootA, rootB, rootC], 20); - const esClient = esServer.es.getClient(); + const esClient = esServer.es.getKibanaEsClient(); const migratedDocs = await fetchDocs(esClient, migratedIndex); expect(migratedDocs.length).toBe(5000); diff --git a/src/core/server/saved_objects/migrationsv2/migrations_state_action_machine.test.ts b/src/core/server/saved_objects/migrationsv2/migrations_state_action_machine.test.ts index 338eecf151174..c53bd7bbc53dd 100644 --- a/src/core/server/saved_objects/migrationsv2/migrations_state_action_machine.test.ts +++ b/src/core/server/saved_objects/migrationsv2/migrations_state_action_machine.test.ts @@ -12,7 +12,7 @@ import { loggingSystemMock, elasticsearchServiceMock } from '../../mocks'; import { typeRegistryMock } from '../saved_objects_type_registry.mock'; import * as Either from 'fp-ts/lib/Either'; import * as Option from 'fp-ts/lib/Option'; -import { ResponseError } from '@elastic/elasticsearch/lib/errors'; +import { errors } from '@elastic/elasticsearch'; import { elasticsearchClientMock } from '../../elasticsearch/client/mocks'; import { LoggerAdapter } from '../../logging/logger_adapter'; import { AllControlStates, State } from './types'; @@ -193,7 +193,7 @@ describe('migrationsStateActionMachine', () => { logger: mockLogger.get(), model: transitionModel(['LEGACY_REINDEX', 'LEGACY_DELETE', 'FATAL']), next: () => { - throw new ResponseError( + throw new errors.ResponseError( elasticsearchClientMock.createApiResponse({ meta: { request: { options: {}, id: '', params: { method: 'POST', path: '/mock' } }, diff --git a/src/core/server/saved_objects/migrationsv2/model/model.ts b/src/core/server/saved_objects/migrationsv2/model/model.ts index 3c36c668f2d99..ff27045dd91ce 100644 --- a/src/core/server/saved_objects/migrationsv2/model/model.ts +++ b/src/core/server/saved_objects/migrationsv2/model/model.ts @@ -9,7 +9,7 @@ import * as Either from 'fp-ts/lib/Either'; import * as Option from 'fp-ts/lib/Option'; -import { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { AliasAction, isLeftTypeof } from '../actions'; import { AllActionStates, MigrationLog, State } from '../types'; import type { ResponseType } from '../next'; diff --git a/src/core/server/saved_objects/migrationsv2/types.ts b/src/core/server/saved_objects/migrationsv2/types.ts index 4f6419930c6cc..e68e04e5267cc 100644 --- a/src/core/server/saved_objects/migrationsv2/types.ts +++ b/src/core/server/saved_objects/migrationsv2/types.ts @@ -8,7 +8,7 @@ import * as TaskEither from 'fp-ts/lib/TaskEither'; import * as Option from 'fp-ts/lib/Option'; -import { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ControlState } from './state_action_machine'; import { AliasAction } from './actions'; import { IndexMapping } from '../mappings'; diff --git a/src/core/server/saved_objects/service/lib/aggregations/validation.test.ts b/src/core/server/saved_objects/service/lib/aggregations/validation.test.ts index 53f1b5c9d78c5..0296dd25b56ee 100644 --- a/src/core/server/saved_objects/service/lib/aggregations/validation.test.ts +++ b/src/core/server/saved_objects/service/lib/aggregations/validation.test.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { validateAndConvertAggregations } from './validation'; type AggsMap = Record; diff --git a/src/core/server/saved_objects/service/lib/aggregations/validation.ts b/src/core/server/saved_objects/service/lib/aggregations/validation.ts index 5ef89f297a796..445d6b6a7ce22 100644 --- a/src/core/server/saved_objects/service/lib/aggregations/validation.ts +++ b/src/core/server/saved_objects/service/lib/aggregations/validation.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ObjectType } from '@kbn/config-schema'; import { isPlainObject } from 'lodash'; diff --git a/src/core/server/saved_objects/service/lib/collect_multi_namespace_references.test.ts b/src/core/server/saved_objects/service/lib/collect_multi_namespace_references.test.ts index fe97208a6168d..45794e25d00a6 100644 --- a/src/core/server/saved_objects/service/lib/collect_multi_namespace_references.test.ts +++ b/src/core/server/saved_objects/service/lib/collect_multi_namespace_references.test.ts @@ -25,7 +25,6 @@ import { savedObjectsPointInTimeFinderMock } from './point_in_time_finder.mock'; import { savedObjectsRepositoryMock } from './repository.mock'; import { PointInTimeFinder } from './point_in_time_finder'; import { ISavedObjectsRepository } from './repository'; -import { SavedObjectsErrorHelpers } from './errors'; const SPACES = ['default', 'another-space']; const VERSION_PROPS = { _seq_no: 1, _primary_term: 1 }; @@ -319,23 +318,6 @@ describe('collectMultiNamespaceReferences', () => { // obj3 is excluded from the results ]); }); - it(`handles 404 responses that don't come from Elasticsearch`, async () => { - const createEsUnavailableNotFoundError = () => { - return SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError(); - }; - const obj1 = { type: MULTI_NAMESPACE_OBJ_TYPE_1, id: 'id-1' }; - const params = setup([obj1]); - client.mget.mockReturnValueOnce( - elasticsearchClientMock.createSuccessTransportRequestPromise( - { docs: [] }, - { statusCode: 404 }, - {} - ) - ); - await expect(() => collectMultiNamespaceReferences(params)).rejects.toThrowError( - createEsUnavailableNotFoundError() - ); - }); describe('legacy URL aliases', () => { it('uses the PointInTimeFinder to search for legacy URL aliases', async () => { diff --git a/src/core/server/saved_objects/service/lib/collect_multi_namespace_references.ts b/src/core/server/saved_objects/service/lib/collect_multi_namespace_references.ts index 7acbaaea1f5d7..278964c934ba0 100644 --- a/src/core/server/saved_objects/service/lib/collect_multi_namespace_references.ts +++ b/src/core/server/saved_objects/service/lib/collect_multi_namespace_references.ts @@ -7,12 +7,10 @@ */ import * as esKuery from '@kbn/es-query'; -import { isNotFoundFromUnsupportedServer } from '../../../elasticsearch'; import { LegacyUrlAlias, LEGACY_URL_ALIAS_TYPE } from '../../object_types'; import type { ISavedObjectTypeRegistry } from '../../saved_objects_type_registry'; import type { SavedObjectsSerializer } from '../../serialization'; import type { SavedObject, SavedObjectsBaseOptions } from '../../types'; -import { SavedObjectsErrorHelpers } from './errors'; import { getRootFields } from './included_fields'; import { getSavedObjectFromSource, rawDocExistsInNamespace } from './internal_utils'; import type { @@ -199,15 +197,6 @@ async function getObjectsAndReferences({ { body: { docs: makeBulkGetDocs(bulkGetObjects) } }, { ignore: [404] } ); - // exit early if we can't verify a 404 response is from Elasticsearch - if ( - isNotFoundFromUnsupportedServer({ - statusCode: bulkGetResponse.statusCode, - headers: bulkGetResponse.headers, - }) - ) { - throw SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError(); - } const newObjectsToGet = new Set(); for (let i = 0; i < bulkGetObjects.length; i++) { // For every element in bulkGetObjects, there should be a matching element in bulkGetResponse.body.docs diff --git a/src/core/server/saved_objects/service/lib/decorate_es_error.test.ts b/src/core/server/saved_objects/service/lib/decorate_es_error.test.ts index 4e187e85f81a7..e7dd355910362 100644 --- a/src/core/server/saved_objects/service/lib/decorate_es_error.test.ts +++ b/src/core/server/saved_objects/service/lib/decorate_es_error.test.ts @@ -53,6 +53,16 @@ describe('savedObjectsClient/decorateEsError', () => { expect(SavedObjectsErrorHelpers.isEsUnavailableError(error)).toBe(true); }); + it('makes ProductNotSupportedError a SavedObjectsClient/EsUnavailable error', () => { + const error = new esErrors.ProductNotSupportedError( + 'reason', + elasticsearchClientMock.createApiResponse() + ); + expect(SavedObjectsErrorHelpers.isEsUnavailableError(error)).toBe(false); + expect(decorateEsError(error)).toBe(error); + expect(SavedObjectsErrorHelpers.isEsUnavailableError(error)).toBe(true); + }); + it('makes Conflict a SavedObjectsClient/Conflict error', () => { const error = new esErrors.ResponseError( elasticsearchClientMock.createApiResponse({ statusCode: 409 }) @@ -109,18 +119,6 @@ describe('savedObjectsClient/decorateEsError', () => { expect(SavedObjectsErrorHelpers.isNotFoundError(genericError)).toBe(true); }); - it('makes NotFound errors generic NotFoundEsUnavailableError errors when response is from unsupported server', () => { - const error = new esErrors.ResponseError( - // explicitly override the headers - elasticsearchClientMock.createApiResponse({ statusCode: 404, headers: {} }) - ); - expect(SavedObjectsErrorHelpers.isNotFoundError(error)).toBe(false); - const genericError = decorateEsError(error); - expect(genericError).not.toBe(error); - expect(SavedObjectsErrorHelpers.isNotFoundError(genericError)).toBe(false); - expect(SavedObjectsErrorHelpers.isEsUnavailableError(genericError)).toBe(true); - }); - it('if saved objects index does not exist makes NotFound a SavedObjectsClient/generalError', () => { const error = new esErrors.ResponseError( elasticsearchClientMock.createApiResponse({ diff --git a/src/core/server/saved_objects/service/lib/decorate_es_error.ts b/src/core/server/saved_objects/service/lib/decorate_es_error.ts index 016268ccdf9f4..d8734b141bd9b 100644 --- a/src/core/server/saved_objects/service/lib/decorate_es_error.ts +++ b/src/core/server/saved_objects/service/lib/decorate_es_error.ts @@ -8,19 +8,20 @@ import { errors as esErrors } from '@elastic/elasticsearch'; import { get } from 'lodash'; -import { isSupportedEsServer } from '../../../elasticsearch'; +import { ElasticsearchErrorDetails } from '../../../elasticsearch'; const responseErrors = { - isServiceUnavailable: (statusCode: number) => statusCode === 503, - isConflict: (statusCode: number) => statusCode === 409, - isNotAuthorized: (statusCode: number) => statusCode === 401, - isForbidden: (statusCode: number) => statusCode === 403, - isRequestEntityTooLarge: (statusCode: number) => statusCode === 413, - isNotFound: (statusCode: number) => statusCode === 404, - isBadRequest: (statusCode: number) => statusCode === 400, - isTooManyRequests: (statusCode: number) => statusCode === 429, + isServiceUnavailable: (statusCode?: number) => statusCode === 503, + isConflict: (statusCode?: number) => statusCode === 409, + isNotAuthorized: (statusCode?: number) => statusCode === 401, + isForbidden: (statusCode?: number) => statusCode === 403, + isRequestEntityTooLarge: (statusCode?: number) => statusCode === 413, + isNotFound: (statusCode?: number) => statusCode === 404, + isBadRequest: (statusCode?: number) => statusCode === 400, + isTooManyRequests: (statusCode?: number) => statusCode === 429, }; -const { ConnectionError, NoLivingConnectionsError, TimeoutError } = esErrors; +const { ConnectionError, NoLivingConnectionsError, TimeoutError, ProductNotSupportedError } = + esErrors; const SCRIPT_CONTEXT_DISABLED_REGEX = /(?:cannot execute scripts using \[)([a-z]*)(?:\] context)/; const INLINE_SCRIPTS_DISABLED_MESSAGE = 'cannot execute [inline] scripts'; @@ -30,6 +31,7 @@ type EsErrors = | esErrors.ConnectionError | esErrors.NoLivingConnectionsError | esErrors.TimeoutError + | esErrors.ProductNotSupportedError | esErrors.ResponseError; export function decorateEsError(error: EsErrors) { @@ -42,6 +44,7 @@ export function decorateEsError(error: EsErrors) { error instanceof ConnectionError || error instanceof NoLivingConnectionsError || error instanceof TimeoutError || + error instanceof ProductNotSupportedError || responseErrors.isServiceUnavailable(error.statusCode) ) { return SavedObjectsErrorHelpers.decorateEsUnavailableError(error, reason); @@ -64,17 +67,12 @@ export function decorateEsError(error: EsErrors) { } if (responseErrors.isNotFound(error.statusCode)) { - const match = error?.meta?.body?.error?.reason?.match( + const match = (error?.meta?.body as ElasticsearchErrorDetails)?.error?.reason?.match( /no such index \[(.+)\] and \[require_alias\] request flag is \[true\] and \[.+\] is not an alias/ ); - if (match?.length > 0) { + if (match && match.length > 0) { return SavedObjectsErrorHelpers.decorateIndexAliasNotFoundError(error, match[1]); } - // Throw EsUnavailable error if the 404 is not from elasticsearch - // Needed here to verify Product support for any non-ignored 404 responses from calls to ES - if (!isSupportedEsServer(error?.meta?.headers)) { - return SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError(); - } return SavedObjectsErrorHelpers.createGenericNotFoundError(); } diff --git a/src/core/server/saved_objects/service/lib/errors.test.ts b/src/core/server/saved_objects/service/lib/errors.test.ts index 3bea693429254..a366dce626ec2 100644 --- a/src/core/server/saved_objects/service/lib/errors.test.ts +++ b/src/core/server/saved_objects/service/lib/errors.test.ts @@ -439,45 +439,4 @@ describe('savedObjectsClient/errorTypes', () => { }); }); }); - - describe('NotFoundEsUnavailableError', () => { - it('makes an error identifiable as an EsUnavailable error', () => { - const error = SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError('foo', 'bar'); - expect(SavedObjectsErrorHelpers.isEsUnavailableError(error)).toBe(true); - }); - - it('returns a boom error', () => { - const error = SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError('foo', 'bar'); - expect(error).toHaveProperty('isBoom', true); - }); - - it('decorates the error message with the saved object that was not found', () => { - const error = SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError('foo', 'bar'); - expect(error.output.payload).toHaveProperty( - 'message', - 'x-elastic-product not present or not recognized: Saved object [foo/bar] not found' - ); - }); - - describe('error.output', () => { - it('specifies the saved object that was not found', () => { - const error = SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError( - 'foo', - 'bar' - ); - expect(error.output.payload).toHaveProperty( - 'message', - 'x-elastic-product not present or not recognized: Saved object [foo/bar] not found' - ); - }); - - it('sets statusCode to 503', () => { - const error = SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError( - 'foo', - 'bar' - ); - expect(error.output).toHaveProperty('statusCode', 503); - }); - }); - }); }); diff --git a/src/core/server/saved_objects/service/lib/errors.ts b/src/core/server/saved_objects/service/lib/errors.ts index 7412e744f19e7..581145c7c09d1 100644 --- a/src/core/server/saved_objects/service/lib/errors.ts +++ b/src/core/server/saved_objects/service/lib/errors.ts @@ -202,16 +202,4 @@ export class SavedObjectsErrorHelpers { public static isGeneralError(error: Error | DecoratedError) { return isSavedObjectsClientError(error) && error[code] === CODE_GENERAL_ERROR; } - - public static createGenericNotFoundEsUnavailableError( - // type and id not available in all operations (e.g. mget) - type: string | null = null, - id: string | null = null - ) { - const notFoundError = this.createGenericNotFoundError(type, id); - return this.decorateEsUnavailableError( - new Error(`${notFoundError.message}`), - `x-elastic-product not present or not recognized` - ); - } } diff --git a/src/core/server/saved_objects/service/lib/integration_tests/repository_with_proxy.test.ts b/src/core/server/saved_objects/service/lib/integration_tests/repository_with_proxy.test.ts index 925b23a64f03e..b767b28c90608 100644 --- a/src/core/server/saved_objects/service/lib/integration_tests/repository_with_proxy.test.ts +++ b/src/core/server/saved_objects/service/lib/integration_tests/repository_with_proxy.test.ts @@ -289,17 +289,11 @@ describe('404s from proxies', () => { let repository: ISavedObjectsRepository; const myTypeDocs: SavedObject[] = []; - const genericNotFoundEsUnavailableError = (err: any, type?: string, id?: string) => { + const SavedObjectsClientEsUnavailable = (err: any) => { expect(err?.output?.statusCode).toBe(503); - if (type && id) { - expect(err?.output?.payload?.message).toBe( - `x-elastic-product not present or not recognized: Saved object [${type}/${id}] not found` - ); - } else { - expect(err?.output?.payload?.message).toBe( - `x-elastic-product not present or not recognized: Not Found` - ); - } + expect(err?.output?.payload?.message).toBe( + `The client noticed that the server is not Elasticsearch and we do not support this unknown product.` + ); }; beforeAll(async () => { @@ -341,7 +335,7 @@ describe('404s from proxies', () => { } catch (err) { myError = err; } - expect(genericNotFoundEsUnavailableError(myError, 'my_type', 'myTypeId1')); + expect(SavedObjectsClientEsUnavailable(myError)); }); it('returns an EsUnavailable error on `update` requests that are interrupted', async () => { @@ -354,7 +348,7 @@ describe('404s from proxies', () => { } catch (err) { updateError = err; } - expect(genericNotFoundEsUnavailableError(updateError)); + expect(SavedObjectsClientEsUnavailable(updateError)); }); it('returns an EsUnavailable error on `bulkCreate` requests with a 404 proxy response and wrong product header', async () => { @@ -383,7 +377,7 @@ describe('404s from proxies', () => { } catch (err) { bulkCreateError = err; } - expect(genericNotFoundEsUnavailableError(bulkCreateError)); + expect(SavedObjectsClientEsUnavailable(bulkCreateError)); }); it('returns an EsUnavailable error on `find` requests with a 404 proxy response and wrong product header', async () => { @@ -394,7 +388,7 @@ describe('404s from proxies', () => { } catch (err) { findErr = err; } - expect(genericNotFoundEsUnavailableError(findErr)); + expect(SavedObjectsClientEsUnavailable(findErr)); expect(findErr?.output?.payload?.error).toBe('Service Unavailable'); }); @@ -405,7 +399,7 @@ describe('404s from proxies', () => { } catch (err) { deleteErr = err; } - expect(genericNotFoundEsUnavailableError(deleteErr, 'my_type', 'myTypeId1')); + expect(SavedObjectsClientEsUnavailable(deleteErr)); }); it('returns an EsUnavailable error on `bulkResolve` requests with a 404 proxy response and wrong product header for an exact match', async () => { @@ -417,7 +411,7 @@ describe('404s from proxies', () => { } catch (err) { testBulkResolveErr = err; } - expect(genericNotFoundEsUnavailableError(testBulkResolveErr)); + expect(SavedObjectsClientEsUnavailable(testBulkResolveErr)); }); it('returns an EsUnavailable error on `resolve` requests with a 404 proxy response and wrong product header for an exact match', async () => { @@ -428,7 +422,7 @@ describe('404s from proxies', () => { } catch (err) { testResolveErr = err; } - expect(genericNotFoundEsUnavailableError(testResolveErr)); + expect(SavedObjectsClientEsUnavailable(testResolveErr)); }); it('returns an EsUnavailable error on `bulkGet` requests with a 404 proxy response and wrong product header', async () => { @@ -440,7 +434,7 @@ describe('404s from proxies', () => { } catch (err) { bulkGetError = err; } - expect(genericNotFoundEsUnavailableError(bulkGetError)); + expect(SavedObjectsClientEsUnavailable(bulkGetError)); }); it('returns an EsUnavailable error on `openPointInTimeForType` requests with a 404 proxy response and wrong product header', async () => { @@ -451,7 +445,7 @@ describe('404s from proxies', () => { } catch (err) { openPitErr = err; } - expect(genericNotFoundEsUnavailableError(openPitErr)); + expect(SavedObjectsClientEsUnavailable(openPitErr)); }); it('returns an EsUnavailable error on `checkConflicts` requests with a 404 proxy response and wrong product header', async () => { @@ -468,7 +462,7 @@ describe('404s from proxies', () => { } catch (err) { checkConflictsErr = err; } - expect(genericNotFoundEsUnavailableError(checkConflictsErr)); + expect(SavedObjectsClientEsUnavailable(checkConflictsErr)); }); it('returns an EsUnavailable error on `deleteByNamespace` requests with a 404 proxy response and wrong product header', async () => { @@ -479,7 +473,7 @@ describe('404s from proxies', () => { } catch (err) { deleteByNamespaceErr = err; } - expect(genericNotFoundEsUnavailableError(deleteByNamespaceErr)); + expect(SavedObjectsClientEsUnavailable(deleteByNamespaceErr)); }); }); }); diff --git a/src/core/server/saved_objects/service/lib/internal_bulk_resolve.test.mock.ts b/src/core/server/saved_objects/service/lib/internal_bulk_resolve.test.mock.ts index fbd774f1c10d5..513add01cdd83 100644 --- a/src/core/server/saved_objects/service/lib/internal_bulk_resolve.test.mock.ts +++ b/src/core/server/saved_objects/service/lib/internal_bulk_resolve.test.mock.ts @@ -7,7 +7,6 @@ */ import type * as InternalUtils from './internal_utils'; -import type { isNotFoundFromUnsupportedServer } from '../../../elasticsearch'; export const mockGetSavedObjectFromSource = jest.fn() as jest.MockedFunction< typeof InternalUtils['getSavedObjectFromSource'] @@ -24,14 +23,3 @@ jest.mock('./internal_utils', () => { rawDocExistsInNamespace: mockRawDocExistsInNamespace, }; }); - -export const mockIsNotFoundFromUnsupportedServer = jest.fn() as jest.MockedFunction< - typeof isNotFoundFromUnsupportedServer ->; -jest.mock('../../../elasticsearch', () => { - const actual = jest.requireActual('../../../elasticsearch'); - return { - ...actual, - isNotFoundFromUnsupportedServer: mockIsNotFoundFromUnsupportedServer, - }; -}); diff --git a/src/core/server/saved_objects/service/lib/internal_bulk_resolve.test.ts b/src/core/server/saved_objects/service/lib/internal_bulk_resolve.test.ts index 5403e146509ae..4120b077a8981 100644 --- a/src/core/server/saved_objects/service/lib/internal_bulk_resolve.test.ts +++ b/src/core/server/saved_objects/service/lib/internal_bulk_resolve.test.ts @@ -9,7 +9,6 @@ import { mockGetSavedObjectFromSource, mockRawDocExistsInNamespace, - mockIsNotFoundFromUnsupportedServer, } from './internal_bulk_resolve.test.mock'; import type { DeeplyMockedKeys } from '@kbn/utility-types/jest'; @@ -35,8 +34,6 @@ beforeEach(() => { ); mockRawDocExistsInNamespace.mockReset(); mockRawDocExistsInNamespace.mockReturnValue(true); // return true by default - mockIsNotFoundFromUnsupportedServer.mockReset(); - mockIsNotFoundFromUnsupportedServer.mockReturnValue(false); }); describe('internalBulkResolve', () => { @@ -173,24 +170,6 @@ describe('internalBulkResolve', () => { return { saved_object: `mock-obj-for-${id}`, outcome: 'conflict', alias_target_id }; } - it('throws if mget call results in non-ES-originated 404 error', async () => { - const objects = [{ type: OBJ_TYPE, id: '1' }]; - const params = setup(objects, { namespace: 'space-x' }); - mockBulkResults( - { found: false } // fetch alias for obj 1 - ); - mockMgetResults( - { found: false } // fetch obj 1 (actual result body doesn't matter, just needs statusCode and headers) - ); - mockIsNotFoundFromUnsupportedServer.mockReturnValue(true); - - await expect(() => internalBulkResolve(params)).rejects.toThrow( - SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError() - ); - expect(client.bulk).toHaveBeenCalledTimes(1); - expect(client.mget).toHaveBeenCalledTimes(1); - }); - it('returns an empty array if no object args are passed in', async () => { const params = setup([], { namespace: 'space-x' }); diff --git a/src/core/server/saved_objects/service/lib/internal_bulk_resolve.ts b/src/core/server/saved_objects/service/lib/internal_bulk_resolve.ts index f53a85a9a03ef..19f774fb068b6 100644 --- a/src/core/server/saved_objects/service/lib/internal_bulk_resolve.ts +++ b/src/core/server/saved_objects/service/lib/internal_bulk_resolve.ts @@ -6,14 +6,13 @@ * Side Public License, v 1. */ -import type { MgetHit } from '@elastic/elasticsearch/api/types'; +import type { MgetHit } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { CORE_USAGE_STATS_ID, CORE_USAGE_STATS_TYPE, REPOSITORY_RESOLVE_OUTCOME_STATS, } from '../../../core_usage_data'; -import { isNotFoundFromUnsupportedServer } from '../../../elasticsearch'; import { LegacyUrlAlias, LEGACY_URL_ALIAS_TYPE } from '../../object_types'; import type { ISavedObjectTypeRegistry } from '../../saved_objects_type_registry'; import type { SavedObjectsRawDocSource, SavedObjectsSerializer } from '../../serialization'; @@ -141,16 +140,6 @@ export async function internalBulkResolve( { ignore: [404] } ) : undefined; - // exit early if a 404 isn't from elasticsearch - if ( - bulkGetResponse && - isNotFoundFromUnsupportedServer({ - statusCode: bulkGetResponse.statusCode, - headers: bulkGetResponse.headers, - }) - ) { - throw SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError(); - } let getResponseIndex = 0; let aliasTargetIndex = 0; diff --git a/src/core/server/saved_objects/service/lib/point_in_time_finder.ts b/src/core/server/saved_objects/service/lib/point_in_time_finder.ts index 9faf5e85085ed..e7f3e9c378e90 100644 --- a/src/core/server/saved_objects/service/lib/point_in_time_finder.ts +++ b/src/core/server/saved_objects/service/lib/point_in_time_finder.ts @@ -5,7 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import type { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { Logger } from '../../../logging'; import type { SavedObjectsFindOptions, SavedObjectsClientContract } from '../../types'; import type { SavedObjectsFindResponse } from '../'; diff --git a/src/core/server/saved_objects/service/lib/repository.test.js b/src/core/server/saved_objects/service/lib/repository.test.js index 985d609f2da59..32b13ba160d5e 100644 --- a/src/core/server/saved_objects/service/lib/repository.test.js +++ b/src/core/server/saved_objects/service/lib/repository.test.js @@ -46,8 +46,6 @@ const createGenericNotFoundError = (...args) => SavedObjectsErrorHelpers.createGenericNotFoundError(...args).output.payload; const createUnsupportedTypeError = (...args) => SavedObjectsErrorHelpers.createUnsupportedTypeError(...args).output.payload; -const createGenericNotFoundEsUnavailableError = (...args) => - SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError(...args).output.payload; describe('SavedObjectsRepository', () => { let client; @@ -690,29 +688,6 @@ describe('SavedObjectsRepository', () => { }); }; - const unsupportedProductBulkCreateMgetError = async (objects, options) => { - const multiNamespaceObjects = objects.filter( - ({ type, id }) => registry.isMultiNamespace(type) && id - ); - if (multiNamespaceObjects?.length) { - const response = getMockMgetResponse(multiNamespaceObjects, options?.namespace); - client.mget.mockResolvedValue( - elasticsearchClientMock.createSuccessTransportRequestPromise( - { ...response }, - { statusCode: 404 }, - {} - ) - ); - } - const response = getMockBulkCreateResponse(objects, options?.namespace); - client.bulk.mockResolvedValue( - elasticsearchClientMock.createSuccessTransportRequestPromise(response) - ); - await expect(savedObjectsRepository.bulkCreate(objects, options)).rejects.toThrowError( - createGenericNotFoundEsUnavailableError() - ); - }; - it(`throws when options.namespace is '*'`, async () => { await expect( savedObjectsRepository.bulkCreate([obj3], { namespace: ALL_NAMESPACES_STRING }) @@ -868,13 +843,6 @@ describe('SavedObjectsRepository', () => { const expectedErrorResult = { type: obj3.type, id: obj3.id, error: 'Oh no, a bulk error!' }; await bulkCreateError(obj3, true, expectedErrorResult); }); - - it(`throws when ES mget action returns 404 with missing Elasticsearch header`, async () => { - const objects = [obj1, { ...obj2, type: MULTI_NAMESPACE_ISOLATED_TYPE }]; - await unsupportedProductBulkCreateMgetError(objects); - expect(client.mget).toHaveBeenCalledTimes(1); - expect(client.bulk).toHaveBeenCalledTimes(0); - }); }); describe('migration', () => { @@ -1136,21 +1104,6 @@ describe('SavedObjectsRepository', () => { }); }; - const unsupportedProductBulkGetMgetError = async (objects, options) => { - const response = getMockMgetResponse(objects, options?.namespace); - client.mget.mockResolvedValueOnce( - elasticsearchClientMock.createSuccessTransportRequestPromise( - { ...response }, - { statusCode: 404 }, - {} - ) - ); - await expect(bulkGet(objects, options)).rejects.toThrowError( - createGenericNotFoundEsUnavailableError() - ); - expect(client.mget).toHaveBeenCalledTimes(1); - }; - it(`throws when options.namespace is '*'`, async () => { const obj = { type: 'dashboard', id: 'three' }; await expect( @@ -1218,12 +1171,6 @@ describe('SavedObjectsRepository', () => { }; await bulkGetError(obj, true, expectErrorNotFound(obj)); }); - - it(`throws when ES mget action responds with a 404 and a missing Elasticsearch product header`, async () => { - const getId = (type, id) => `${type}:${id}`; - await unsupportedProductBulkGetMgetError([obj1, obj2]); // returns 404 without required product header - _expectClientCallArgs([obj1, obj2], { getId }); - }); }); describe('returns', () => { @@ -1681,34 +1628,6 @@ describe('SavedObjectsRepository', () => { saved_objects: [expectSuccess(obj1), expectErrorNotFound(_obj), expectSuccess(obj2)], }); }; - const unsupportedProductBulkUpdateMgetError = async (objects, options, includeOriginId) => { - const multiNamespaceObjects = objects.filter(({ type }) => registry.isMultiNamespace(type)); - if (multiNamespaceObjects?.length) { - const response = getMockMgetResponse(multiNamespaceObjects, options?.namespace); - client.mget.mockResolvedValueOnce( - elasticsearchClientMock.createSuccessTransportRequestPromise( - { ...response }, - { statusCode: 404 }, - {} - ) - ); - } - const response = getMockBulkUpdateResponse(objects, options?.namespace, includeOriginId); - client.bulk.mockResolvedValueOnce( - elasticsearchClientMock.createSuccessTransportRequestPromise(response) - ); - - await expect(savedObjectsRepository.bulkUpdate(objects, options)).rejects.toThrowError( - createGenericNotFoundEsUnavailableError() - ); - expect(client.mget).toHaveBeenCalledTimes(multiNamespaceObjects?.length ? 1 : 0); - }; - - it(`throws when ES mget action responds with a 404 and a missing Elasticsearch product header`, async () => { - const objects = [obj1, { ...obj2, type: MULTI_NAMESPACE_ISOLATED_TYPE }]; - await unsupportedProductBulkUpdateMgetError(objects); - expect(client.mget).toHaveBeenCalledTimes(1); - }); it(`throws when options.namespace is '*'`, async () => { await expect( @@ -1910,24 +1829,6 @@ describe('SavedObjectsRepository', () => { savedObjectsRepository.checkConflicts([obj1], { namespace: ALL_NAMESPACES_STRING }) ).rejects.toThrowError(createBadRequestError('"options.namespace" cannot be "*"')); }); - - it(`throws when not found responses aren't from Elasticsearch`, async () => { - const checkConflictsMgetError = async (objects, options) => { - const response = getMockMgetResponse(objects, options?.namespace); - client.mget.mockResolvedValue( - elasticsearchClientMock.createSuccessTransportRequestPromise( - { ...response }, - { statusCode: 404 }, - {} - ) - ); - await expect(checkConflicts(objects, options)).rejects.toThrowError( - createGenericNotFoundEsUnavailableError() - ); - expect(client.mget).toHaveBeenCalledTimes(1); - }; - await checkConflictsMgetError([obj1, obj2], { namespace: 'default' }); - }); }); describe('returns', () => { @@ -2515,11 +2416,6 @@ describe('SavedObjectsRepository', () => { createGenericNotFoundError(type, id) ); }; - const expectNotFoundEsUnavailableError = async (type, id) => { - await expect(savedObjectsRepository.delete(type, id)).rejects.toThrowError( - createGenericNotFoundEsUnavailableError(type, id) - ); - }; it(`throws when options.namespace is '*'`, async () => { await expect( @@ -2553,24 +2449,6 @@ describe('SavedObjectsRepository', () => { expect(client.get).toHaveBeenCalledTimes(1); }); - it(`throws when ES is unable to find the document during get with missing Elasticsearch header`, async () => { - client.get.mockResolvedValueOnce( - elasticsearchClientMock.createSuccessTransportRequestPromise( - { found: false }, - { statusCode: 404 }, - {} - ) - ); - await expectNotFoundEsUnavailableError(MULTI_NAMESPACE_ISOLATED_TYPE, id); - }); - - it(`throws when ES is unable to find the index during get with missing Elasticsearch header`, async () => { - client.get.mockResolvedValueOnce( - elasticsearchClientMock.createSuccessTransportRequestPromise({}, { statusCode: 404 }, {}) - ); - await expectNotFoundEsUnavailableError(MULTI_NAMESPACE_ISOLATED_TYPE, id); - }); - it(`throws when the type is multi-namespace and the document exists, but not in this namespace`, async () => { const response = getMockGetResponse({ type: MULTI_NAMESPACE_ISOLATED_TYPE, id }, namespace); client.get.mockResolvedValueOnce( @@ -2885,22 +2763,6 @@ describe('SavedObjectsRepository', () => { savedObjectsRepository.removeReferencesTo(type, id, defaultOptions) ).rejects.toThrowError(createConflictError(type, id)); }); - - it(`throws on 404 with missing Elasticsearch header`, async () => { - client.updateByQuery.mockResolvedValueOnce( - elasticsearchClientMock.createSuccessTransportRequestPromise( - { - updated: updatedCount, - }, - { statusCode: 404 }, - {} - ) - ); - await expect( - savedObjectsRepository.removeReferencesTo(type, id, defaultOptions) - ).rejects.toThrowError(createGenericNotFoundEsUnavailableError(type, id)); - expect(client.updateByQuery).toHaveBeenCalledTimes(1); - }); }); }); @@ -3077,21 +2939,6 @@ describe('SavedObjectsRepository', () => { }); describe('errors', () => { - const findNotSupportedServerError = async (options, namespace) => { - const expectedSearchResults = generateSearchResults(namespace); - client.search.mockResolvedValueOnce( - elasticsearchClientMock.createSuccessTransportRequestPromise( - { ...expectedSearchResults }, - { statusCode: 404 }, - {} - ) - ); - await expect(savedObjectsRepository.find(options)).rejects.toThrowError( - createGenericNotFoundEsUnavailableError() - ); - expect(getSearchDslNS.getSearchDsl).toHaveBeenCalledTimes(1); - expect(client.search).toHaveBeenCalledTimes(1); - }; it(`throws when type is not defined`, async () => { await expect(savedObjectsRepository.find({})).rejects.toThrowError( 'options.type must be a string or an array of strings' @@ -3172,11 +3019,6 @@ describe('SavedObjectsRepository', () => { expect(getSearchDslNS.getSearchDsl).not.toHaveBeenCalled(); expect(client.search).not.toHaveBeenCalled(); }); - - it(`throws when ES is unable to find with missing Elasticsearch`, async () => { - await findNotSupportedServerError({ type }); - expect(client.search).toHaveBeenCalledTimes(1); - }); }); describe('returns', () => { @@ -3548,11 +3390,6 @@ describe('SavedObjectsRepository', () => { createGenericNotFoundError(type, id) ); }; - const expectNotFoundEsUnavailableError = async (type, id) => { - await expect(savedObjectsRepository.get(type, id)).rejects.toThrowError( - createGenericNotFoundEsUnavailableError(type, id) - ); - }; it(`throws when options.namespace is '*'`, async () => { await expect( @@ -3596,19 +3433,6 @@ describe('SavedObjectsRepository', () => { }); expect(client.get).toHaveBeenCalledTimes(1); }); - - it(`throws when ES does not return the correct header when finding the document during get`, async () => { - client.get.mockResolvedValueOnce( - elasticsearchClientMock.createSuccessTransportRequestPromise( - { found: false }, - { statusCode: 404 }, - {} - ) - ); - await expectNotFoundEsUnavailableError(type, id); - - expect(client.get).toHaveBeenCalledTimes(1); - }); }); describe('returns', () => { @@ -4279,11 +4103,6 @@ describe('SavedObjectsRepository', () => { createGenericNotFoundError(type, id) ); }; - const expectNotFoundEsUnavailableError = async (type, id) => { - await expect(savedObjectsRepository.update(type, id)).rejects.toThrowError( - createGenericNotFoundEsUnavailableError(type, id) - ); - }; it(`throws when options.namespace is '*'`, async () => { await expect( @@ -4317,26 +4136,6 @@ describe('SavedObjectsRepository', () => { expect(client.get).toHaveBeenCalledTimes(1); }); - it(`throws when ES is unable to find the document during get with missing Elasticsearch header`, async () => { - client.get.mockResolvedValueOnce( - elasticsearchClientMock.createSuccessTransportRequestPromise( - { found: false }, - { statusCode: 404 }, - {} - ) - ); - await expectNotFoundEsUnavailableError(MULTI_NAMESPACE_ISOLATED_TYPE, id); - expect(client.get).toHaveBeenCalledTimes(1); - }); - - it(`throws when ES is unable to find the index during get with missing Elasticsearch header`, async () => { - client.get.mockResolvedValueOnce( - elasticsearchClientMock.createSuccessTransportRequestPromise({}, { statusCode: 404 }, {}) - ); - await expectNotFoundEsUnavailableError(MULTI_NAMESPACE_ISOLATED_TYPE, id); - expect(client.get).toHaveBeenCalledTimes(1); - }); - it(`throws when type is multi-namespace and the document exists, but not in this namespace`, async () => { const response = getMockGetResponse({ type: MULTI_NAMESPACE_ISOLATED_TYPE, id }, namespace); client.get.mockResolvedValueOnce( @@ -4458,21 +4257,6 @@ describe('SavedObjectsRepository', () => { ); }; - const unsupportedProductExpectNotFoundError = async (type, options) => { - const results = generateResults(); - client.openPointInTime.mockResolvedValueOnce( - elasticsearchClientMock.createSuccessTransportRequestPromise( - { ...results }, - { statusCode: 404 }, - {} - ) - ); - await expect( - savedObjectsRepository.openPointInTimeForType(type, options) - ).rejects.toThrowError(createGenericNotFoundEsUnavailableError()); - expect(client.openPointInTime).toHaveBeenCalledTimes(1); - }; - it(`throws when ES is unable to find the index`, async () => { client.openPointInTime.mockResolvedValueOnce( elasticsearchClientMock.createSuccessTransportRequestPromise({}, { statusCode: 404 }) @@ -4491,11 +4275,6 @@ describe('SavedObjectsRepository', () => { await test(HIDDEN_TYPE); await test(['unknownType', HIDDEN_TYPE]); }); - - it(`throws on 404 with missing Elasticsearch product header`, async () => { - await unsupportedProductExpectNotFoundError(type); - expect(client.openPointInTime).toHaveBeenCalledTimes(1); - }); }); describe('returns', () => { diff --git a/src/core/server/saved_objects/service/lib/repository.ts b/src/core/server/saved_objects/service/lib/repository.ts index 6798f411d87a9..9f69396fac838 100644 --- a/src/core/server/saved_objects/service/lib/repository.ts +++ b/src/core/server/saved_objects/service/lib/repository.ts @@ -7,10 +7,9 @@ */ import { omit, isObject } from 'lodash'; -import type { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import * as esKuery from '@kbn/es-query'; import type { ElasticsearchClient } from '../../../elasticsearch/'; -import { isSupportedEsServer, isNotFoundFromUnsupportedServer } from '../../../elasticsearch'; import type { Logger } from '../../../logging'; import { getRootPropertiesObjects, IndexMapping } from '../../mappings'; import { @@ -366,15 +365,11 @@ export class SavedObjectsRepository { require_alias: true, }; - const { body, statusCode, headers } = + const { body } = id && overwrite ? await this.client.index(requestParams) : await this.client.create(requestParams); - // throw if we can't verify a 404 response is from Elasticsearch - if (isNotFoundFromUnsupportedServer({ statusCode, headers })) { - throw SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError(id, type); - } return this._rawToSavedObject({ ...raw, ...body, @@ -462,16 +457,7 @@ export class SavedObjectsRepository { { ignore: [404] } ) : undefined; - // throw if we can't verify a 404 response is from Elasticsearch - if ( - bulkGetResponse && - isNotFoundFromUnsupportedServer({ - statusCode: bulkGetResponse.statusCode, - headers: bulkGetResponse.headers, - }) - ) { - throw SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError(); - } + let bulkRequestIndexCounter = 0; const bulkCreateParams: object[] = []; const expectedBulkResults: Array, Record>> = @@ -650,16 +636,7 @@ export class SavedObjectsRepository { { ignore: [404] } ) : undefined; - // throw if we can't verify a 404 response is from Elasticsearch - if ( - bulkGetResponse && - isNotFoundFromUnsupportedServer({ - statusCode: bulkGetResponse.statusCode, - headers: bulkGetResponse.headers, - }) - ) { - throw SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError(); - } + const errors: SavedObjectsCheckConflictsResponse['errors'] = []; expectedBulkGetResults.forEach((expectedResult) => { if (isLeft(expectedResult)) { @@ -731,7 +708,7 @@ export class SavedObjectsRepository { } } - const { body, statusCode, headers } = await this.client.delete( + const { body, statusCode } = await this.client.delete( { id: rawId, index: this.getIndexForType(type), @@ -741,10 +718,6 @@ export class SavedObjectsRepository { { ignore: [404] } ); - if (isNotFoundFromUnsupportedServer({ statusCode, headers })) { - throw SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError(type, id); - } - const deleted = body.result === 'deleted'; if (deleted) { return {}; @@ -793,7 +766,7 @@ export class SavedObjectsRepository { const match2 = buildNode('not', buildNode('is', 'type', LEGACY_URL_ALIAS_TYPE)); const kueryNode = buildNode('or', [match1, match2]); - const { body, statusCode, headers } = await this.client.updateByQuery( + const { body } = await this.client.updateByQuery( { index: this.getIndicesForTypes(typesToUpdate), refresh: options.refresh, @@ -822,10 +795,6 @@ export class SavedObjectsRepository { }, { ignore: [404] } ); - // throw if we can't verify a 404 response is from Elasticsearch - if (isNotFoundFromUnsupportedServer({ statusCode, headers })) { - throw SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError(); - } return body; } @@ -970,16 +939,10 @@ export class SavedObjectsRepository { }, }; - const { body, statusCode, headers } = await this.client.search( - esOptions, - { - ignore: [404], - } - ); + const { body, statusCode } = await this.client.search(esOptions, { + ignore: [404], + }); if (statusCode === 404) { - if (!isSupportedEsServer(headers)) { - throw SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError(); - } // 404 is only possible here if the index is missing, which // we don't want to leak, see "404s from missing index" above return { @@ -1086,16 +1049,7 @@ export class SavedObjectsRepository { { ignore: [404] } ) : undefined; - // fail fast if we can't verify a 404 is from Elasticsearch - if ( - bulkGetResponse && - isNotFoundFromUnsupportedServer({ - statusCode: bulkGetResponse.statusCode, - headers: bulkGetResponse.headers, - }) - ) { - throw SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError(); - } + return { saved_objects: expectedBulkGetResults.map((expectedResult) => { if (isLeft(expectedResult)) { @@ -1186,7 +1140,7 @@ export class SavedObjectsRepository { throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); } const namespace = normalizeNamespace(options.namespace); - const { body, statusCode, headers } = await this.client.get( + const { body, statusCode } = await this.client.get( { id: this._serializer.generateRawId(namespace, type, id), index: this.getIndexForType(type), @@ -1194,10 +1148,7 @@ export class SavedObjectsRepository { { ignore: [404] } ); const indexNotFound = statusCode === 404; - // check if we have the elasticsearch header when index is not found and if we do, ensure it is Elasticsearch - if (indexNotFound && !isSupportedEsServer(headers)) { - throw SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError(type, id); - } + if ( !isFoundGetResponse(body) || indexNotFound || @@ -1326,9 +1277,6 @@ export class SavedObjectsRepository { require_alias: true, }) .catch((err) => { - if (SavedObjectsErrorHelpers.isEsUnavailableError(err)) { - throw err; - } if (SavedObjectsErrorHelpers.isNotFoundError(err)) { // see "404s from missing index" above throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); @@ -1501,16 +1449,7 @@ export class SavedObjectsRepository { } ) : undefined; - // fail fast if we can't verify a 404 response is from Elasticsearch - if ( - bulkGetResponse && - isNotFoundFromUnsupportedServer({ - statusCode: bulkGetResponse.statusCode, - headers: bulkGetResponse.headers, - }) - ) { - throw SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError(); - } + let bulkUpdateRequestIndexCounter = 0; const bulkUpdateParams: object[] = []; const expectedBulkUpdateResults: Array, Record>> = @@ -1644,7 +1583,7 @@ export class SavedObjectsRepository { // we need to target all SO indices as all types of objects may have references to the given SO. const targetIndices = this.getIndicesForTypes(allTypes); - const { body, statusCode, headers } = await this.client.updateByQuery( + const { body } = await this.client.updateByQuery( { index: targetIndices, refresh, @@ -1677,10 +1616,7 @@ export class SavedObjectsRepository { }, { ignore: [404] } ); - // fail fast if we can't verify a 404 is from Elasticsearch - if (isNotFoundFromUnsupportedServer({ statusCode, headers })) { - throw SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError(type, id); - } + if (body.failures?.length) { throw SavedObjectsErrorHelpers.createConflictError( type, @@ -1954,15 +1890,12 @@ export class SavedObjectsRepository { ...(preference ? { preference } : {}), }; - const { body, statusCode, headers } = await this.client.openPointInTime(esOptions, { + const { body, statusCode } = await this.client.openPointInTime(esOptions, { ignore: [404], }); + if (statusCode === 404) { - if (!isSupportedEsServer(headers)) { - throw SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError(); - } else { - throw SavedObjectsErrorHelpers.createGenericNotFoundError(); - } + throw SavedObjectsErrorHelpers.createGenericNotFoundError(); } return { @@ -2133,7 +2066,7 @@ export class SavedObjectsRepository { throw new Error(`Cannot make preflight get request for non-multi-namespace type '${type}'.`); } - const { body, statusCode, headers } = await this.client.get( + const { body, statusCode } = await this.client.get( { id: this._serializer.generateRawId(undefined, type, id), index: this.getIndexForType(type), @@ -2155,9 +2088,6 @@ export class SavedObjectsRepository { savedObjectNamespaces: initialNamespaces ?? getSavedObjectNamespaces(namespace, body), rawDocSource: body, }; - } else if (isNotFoundFromUnsupportedServer({ statusCode, headers })) { - // checking if the 404 is from Elasticsearch - throw SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError(type, id); } return { checkResult: 'not_found', diff --git a/src/core/server/saved_objects/service/lib/repository_es_client.ts b/src/core/server/saved_objects/service/lib/repository_es_client.ts index 4e8592fa94cca..4c1ae294cc7db 100644 --- a/src/core/server/saved_objects/service/lib/repository_es_client.ts +++ b/src/core/server/saved_objects/service/lib/repository_es_client.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { TransportRequestOptions } from '@elastic/elasticsearch/lib/Transport'; +import type { TransportRequestOptions } from '@elastic/elasticsearch'; import { ElasticsearchClient } from '../../../elasticsearch/'; import { retryCallCluster } from '../../../elasticsearch/client/retry_call_cluster'; diff --git a/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.ts b/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.ts index 3196a59ca39ee..f2cf0013dfe08 100644 --- a/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.ts +++ b/src/core/server/saved_objects/service/lib/search_dsl/search_dsl.ts @@ -8,7 +8,7 @@ import Boom from '@hapi/boom'; -import type { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { IndexMapping } from '../../../mappings'; import { SavedObjectsPitParams } from '../../../types'; import { getQueryParams, HasReferenceQueryParams, SearchOperator } from './query_params'; diff --git a/src/core/server/saved_objects/service/lib/search_dsl/sorting_params.ts b/src/core/server/saved_objects/service/lib/search_dsl/sorting_params.ts index 592110a5413ec..2a3dca2629098 100644 --- a/src/core/server/saved_objects/service/lib/search_dsl/sorting_params.ts +++ b/src/core/server/saved_objects/service/lib/search_dsl/sorting_params.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import Boom from '@hapi/boom'; import { getProperty, IndexMapping } from '../../../mappings'; diff --git a/src/core/server/saved_objects/service/lib/update_objects_spaces.test.ts b/src/core/server/saved_objects/service/lib/update_objects_spaces.test.ts index ba15fbabfba6b..11dbe6149878c 100644 --- a/src/core/server/saved_objects/service/lib/update_objects_spaces.test.ts +++ b/src/core/server/saved_objects/service/lib/update_objects_spaces.test.ts @@ -23,7 +23,6 @@ import type { UpdateObjectsSpacesParams, } from './update_objects_spaces'; import { updateObjectsSpaces } from './update_objects_spaces'; -import { SavedObjectsErrorHelpers } from './errors'; type SetupParams = Partial< Pick @@ -106,32 +105,6 @@ describe('#updateObjectsSpaces', () => { }) ); } - /** Mocks the saved objects client so as to test unsupported server responding with 404 */ - function mockMgetResultsNotFound(...results: Array<{ found: boolean }>) { - client.mget.mockReturnValueOnce( - elasticsearchClientMock.createSuccessTransportRequestPromise( - { - docs: results.map((x) => - x.found - ? { - _id: 'doesnt-matter', - _index: 'doesnt-matter', - _source: { namespaces: [EXISTING_SPACE] }, - ...VERSION_PROPS, - found: true, - } - : { - _id: 'doesnt-matter', - _index: 'doesnt-matter', - found: false, - } - ), - }, - { statusCode: 404 }, - {} - ) - ); - } /** Asserts that mget is called for the given objects */ function expectMgetArgs(...objects: SavedObjectsUpdateObjectsSpacesObject[]) { @@ -267,17 +240,6 @@ describe('#updateObjectsSpaces', () => { { ...obj7, spaces: [EXISTING_SPACE, 'foo-space'] }, ]); }); - - it('throws when mget not found response is missing the Elasticsearch header', async () => { - const objects = [{ type: SHAREABLE_OBJ_TYPE, id: 'id-1' }]; - const spacesToAdd = ['foo-space']; - const params = setup({ objects, spacesToAdd }); - mockMgetResultsNotFound({ found: true }); - - await expect(() => updateObjectsSpaces(params)).rejects.toThrowError( - SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError() - ); - }); }); // Note: these test cases do not include requested objects that will result in errors (those are covered above) diff --git a/src/core/server/saved_objects/service/lib/update_objects_spaces.ts b/src/core/server/saved_objects/service/lib/update_objects_spaces.ts index 6d7c272c26eec..d88bf700a900e 100644 --- a/src/core/server/saved_objects/service/lib/update_objects_spaces.ts +++ b/src/core/server/saved_objects/service/lib/update_objects_spaces.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import intersection from 'lodash/intersection'; import type { ISavedObjectTypeRegistry } from '../../saved_objects_type_registry'; @@ -28,7 +28,6 @@ import { } from './internal_utils'; import { DEFAULT_REFRESH_SETTING } from './repository'; import type { RepositoryEsClient } from './repository_es_client'; -import { isNotFoundFromUnsupportedServer } from '../../../elasticsearch'; /** * An object that should have its spaces updated. @@ -188,16 +187,6 @@ export async function updateObjectsSpaces({ ) : undefined; - // fail fast if we can't verify a 404 response is from Elasticsearch - if ( - bulkGetResponse && - isNotFoundFromUnsupportedServer({ - statusCode: bulkGetResponse.statusCode, - headers: bulkGetResponse.headers, - }) - ) { - throw SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError(); - } const time = new Date().toISOString(); let bulkOperationRequestIndexCounter = 0; const bulkOperationParams: estypes.BulkOperationContainer[] = []; @@ -259,7 +248,6 @@ export async function updateObjectsSpaces({ // @ts-expect-error BulkOperation.retry_on_conflict, BulkOperation.routing. BulkOperation.version, and BulkOperation.version_type are optional bulkOperationParams.push({ update: documentMetadata }, { doc: documentToSave }); } else { - // @ts-expect-error BulkOperation.retry_on_conflict, BulkOperation.routing. BulkOperation.version, and BulkOperation.version_type are optional bulkOperationParams.push({ delete: documentMetadata }); } } diff --git a/src/core/server/saved_objects/types.ts b/src/core/server/saved_objects/types.ts index dca8814b2914a..68040d9c6e003 100644 --- a/src/core/server/saved_objects/types.ts +++ b/src/core/server/saved_objects/types.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { SavedObjectsClient } from './service/saved_objects_client'; import { SavedObjectsTypeMappingDefinition } from './mappings'; import { SavedObjectMigrationMap } from './migrations'; diff --git a/src/core/server/server.api.md b/src/core/server/server.api.md index 632fea5c6660d..f135d8caaf54e 100644 --- a/src/core/server/server.api.md +++ b/src/core/server/server.api.md @@ -5,11 +5,10 @@ ```ts import { AddConfigDeprecation } from '@kbn/config'; -import { ApiResponse } from '@elastic/elasticsearch/lib/Transport'; import Boom from '@hapi/boom'; import { ByteSizeValue } from '@kbn/config-schema'; import { CliArgs } from '@kbn/config'; -import { ClientOptions } from '@elastic/elasticsearch'; +import { ClientOptions } from '@elastic/elasticsearch/lib/client'; import { ConfigDeprecation } from '@kbn/config'; import { ConfigDeprecationContext } from '@kbn/config'; import { ConfigDeprecationFactory } from '@kbn/config'; @@ -25,9 +24,9 @@ import { EcsEventKind } from '@kbn/logging'; import { EcsEventOutcome } from '@kbn/logging'; import { EcsEventType } from '@kbn/logging'; import { EnvironmentMode } from '@kbn/config'; -import { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { IncomingHttpHeaders } from 'http'; -import { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import { KibanaClient } from '@elastic/elasticsearch/lib/api/kibana'; import { Logger } from '@kbn/logging'; import { LoggerFactory } from '@kbn/logging'; import { LogLevel } from '@kbn/logging'; @@ -49,9 +48,9 @@ import { ResponseToolkit } from '@hapi/hapi'; import { SchemaTypeError } from '@kbn/config-schema'; import { ShallowPromise } from '@kbn/utility-types'; import { Stream } from 'stream'; -import { TransportRequestOptions } from '@elastic/elasticsearch/lib/Transport'; -import { TransportRequestParams } from '@elastic/elasticsearch/lib/Transport'; -import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; +import { TransportRequestOptions } from '@elastic/elasticsearch'; +import { TransportRequestParams } from '@elastic/elasticsearch'; +import { TransportResult } from '@elastic/elasticsearch'; import { Type } from '@kbn/config-schema'; import { TypeOf } from '@kbn/config-schema'; import { UiCounterMetricType } from '@kbn/analytics'; @@ -870,9 +869,9 @@ export { EcsEventOutcome } export { EcsEventType } // @public -export type ElasticsearchClient = Omit & { +export type ElasticsearchClient = Omit & { transport: { - request(params: TransportRequestParams, options?: TransportRequestOptions): TransportRequestPromise; + request(params: TransportRequestParams, options?: TransportRequestOptions): Promise>; }; }; @@ -918,6 +917,15 @@ export interface ElasticsearchConfigPreboot { readonly hosts: string[]; } +// @public (undocumented) +export interface ElasticsearchErrorDetails { + // (undocumented) + error?: { + type: string; + reason?: string; + }; +} + // @public (undocumented) export interface ElasticsearchServicePreboot { readonly config: Readonly; @@ -2171,8 +2179,6 @@ export class SavedObjectsErrorHelpers { // (undocumented) static createGenericNotFoundError(type?: string | null, id?: string | null): DecoratedError; // (undocumented) - static createGenericNotFoundEsUnavailableError(type?: string | null, id?: string | null): DecoratedError; - // (undocumented) static createIndexAliasNotFoundError(alias: string): DecoratedError; // (undocumented) static createInvalidVersionError(versionInput?: string): DecoratedError; @@ -3050,7 +3056,7 @@ export const validBodyOutput: readonly ["data", "stream"]; // Warnings were encountered during analysis: // -// src/core/server/elasticsearch/client/types.ts:94:7 - (ae-forgotten-export) The symbol "Explanation" needs to be exported by the entry point index.d.ts +// src/core/server/elasticsearch/client/types.ts:93:7 - (ae-forgotten-export) The symbol "Explanation" needs to be exported by the entry point index.d.ts // src/core/server/http/router/response.ts:302:3 - (ae-forgotten-export) The symbol "KibanaResponse" needs to be exported by the entry point index.d.ts // src/core/server/plugins/types.ts:375:3 - (ae-forgotten-export) The symbol "SharedGlobalConfigKeys" needs to be exported by the entry point index.d.ts // src/core/server/plugins/types.ts:377:3 - (ae-forgotten-export) The symbol "SavedObjectsConfigType" needs to be exported by the entry point index.d.ts diff --git a/src/core/server/ui_settings/integration_tests/lib/servers.ts b/src/core/server/ui_settings/integration_tests/lib/servers.ts index 96ba08a0728ab..d94ab98060a27 100644 --- a/src/core/server/ui_settings/integration_tests/lib/servers.ts +++ b/src/core/server/ui_settings/integration_tests/lib/servers.ts @@ -8,7 +8,7 @@ import type supertest from 'supertest'; import type { SavedObjectsClientContract, IUiSettingsClient } from 'src/core/server'; -import type { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import type { KibanaClient } from '@elastic/elasticsearch/lib/api/kibana'; import { createTestServers, @@ -55,7 +55,7 @@ export function getServices() { return services; } - const esClient = esServer.es.getClient(); + const esClient = esServer.es.getKibanaEsClient(); const savedObjectsClient = kbn.coreStart.savedObjects.getScopedClient( httpServerMock.createKibanaRequest() diff --git a/src/core/types/elasticsearch/index.ts b/src/core/types/elasticsearch/index.ts index bec611778e6f5..09eff555fc857 100644 --- a/src/core/types/elasticsearch/index.ts +++ b/src/core/types/elasticsearch/index.ts @@ -5,7 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { InferSearchResponseOf, AggregateOf as AggregationResultOf, SearchHit } from './search'; export type ESFilter = estypes.QueryDslQueryContainer; diff --git a/src/core/types/elasticsearch/search.ts b/src/core/types/elasticsearch/search.ts index a54f5f3758ce3..2e79bf6fea57c 100644 --- a/src/core/types/elasticsearch/search.ts +++ b/src/core/types/elasticsearch/search.ts @@ -7,7 +7,7 @@ */ import { ValuesType } from 'utility-types'; -import { estypes } from '@elastic/elasticsearch'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; type InvalidAggregationRequest = unknown; diff --git a/src/plugins/data/common/search/aggs/agg_configs.ts b/src/plugins/data/common/search/aggs/agg_configs.ts index 3157735a39967..9a362466c0fd7 100644 --- a/src/plugins/data/common/search/aggs/agg_configs.ts +++ b/src/plugins/data/common/search/aggs/agg_configs.ts @@ -11,7 +11,7 @@ import _, { cloneDeep } from 'lodash'; import { i18n } from '@kbn/i18n'; import { Assign } from '@kbn/utility-types'; import { isRangeFilter } from '@kbn/es-query'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { IEsSearchResponse, diff --git a/src/plugins/data/common/search/aggs/agg_type.ts b/src/plugins/data/common/search/aggs/agg_type.ts index ebc1705f6c01b..917f80d3b7819 100644 --- a/src/plugins/data/common/search/aggs/agg_type.ts +++ b/src/plugins/data/common/search/aggs/agg_type.ts @@ -14,7 +14,7 @@ import { DatatableColumnType } from 'src/plugins/expressions/common'; import type { RequestAdapter } from 'src/plugins/inspector/common'; import type { SerializedFieldFormat } from 'src/plugins/field_formats/common'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { initParams } from './agg_params'; import { AggConfig } from './agg_config'; import { IAggConfigs } from './agg_configs'; diff --git a/src/plugins/data/common/search/aggs/buckets/_terms_other_bucket_helper.ts b/src/plugins/data/common/search/aggs/buckets/_terms_other_bucket_helper.ts index 436cc5614ac80..ef5066e84f985 100644 --- a/src/plugins/data/common/search/aggs/buckets/_terms_other_bucket_helper.ts +++ b/src/plugins/data/common/search/aggs/buckets/_terms_other_bucket_helper.ts @@ -7,7 +7,7 @@ */ import { isNumber, keys, values, find, each, cloneDeep, flatten } from 'lodash'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { buildExistsFilter, buildPhrasesFilter, buildQueryFromFilters } from '@kbn/es-query'; import { AggGroupNames } from '../agg_groups'; import { IAggConfigs } from '../agg_configs'; diff --git a/src/plugins/data/common/search/aggs/utils/time_splits.ts b/src/plugins/data/common/search/aggs/utils/time_splits.ts index 0510f629540f6..c4a603a383e38 100644 --- a/src/plugins/data/common/search/aggs/utils/time_splits.ts +++ b/src/plugins/data/common/search/aggs/utils/time_splits.ts @@ -8,7 +8,7 @@ import moment from 'moment'; import _, { isArray } from 'lodash'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { RangeFilter } from '@kbn/es-query'; import { AggGroupNames } from '../agg_groups'; diff --git a/src/plugins/data/common/search/expressions/es_raw_response.ts b/src/plugins/data/common/search/expressions/es_raw_response.ts index 2d12af017d88c..61d79939e8635 100644 --- a/src/plugins/data/common/search/expressions/es_raw_response.ts +++ b/src/plugins/data/common/search/expressions/es_raw_response.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ExpressionTypeDefinition } from '../../../../expressions/common'; const name = 'es_raw_response'; diff --git a/src/plugins/data/common/search/search_source/inspect/inspector_stats.ts b/src/plugins/data/common/search/search_source/inspect/inspector_stats.ts index 67c23fb16b8de..df32b6ffed2e7 100644 --- a/src/plugins/data/common/search/search_source/inspect/inspector_stats.ts +++ b/src/plugins/data/common/search/search_source/inspect/inspector_stats.ts @@ -14,7 +14,7 @@ */ import { i18n } from '@kbn/i18n'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ISearchSource } from 'src/plugins/data/public'; import type { RequestStatistics } from 'src/plugins/inspector/common'; diff --git a/src/plugins/data/common/search/search_source/search_source.ts b/src/plugins/data/common/search/search_source/search_source.ts index 7b4537043c31c..50752523403cf 100644 --- a/src/plugins/data/common/search/search_source/search_source.ts +++ b/src/plugins/data/common/search/search_source/search_source.ts @@ -71,7 +71,7 @@ import { tap, } from 'rxjs/operators'; import { defer, EMPTY, from, Observable } from 'rxjs'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { buildEsQuery, Filter } from '@kbn/es-query'; import { normalizeSortRequest } from './normalize_sort_request'; import { fieldWildcardFilter } from '../../../../kibana_utils/common'; diff --git a/src/plugins/data/common/search/search_source/types.ts b/src/plugins/data/common/search/search_source/types.ts index a19316c1c8418..c411e53abfcd2 100644 --- a/src/plugins/data/common/search/search_source/types.ts +++ b/src/plugins/data/common/search/search_source/types.ts @@ -5,7 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { IAggConfigs } from 'src/plugins/data/public'; import { Query } from '../..'; import { Filter } from '../../es_query'; diff --git a/src/plugins/data/common/search/strategies/eql_search/types.ts b/src/plugins/data/common/search/strategies/eql_search/types.ts index a30adbaf47c60..7f6ec4809b2c5 100644 --- a/src/plugins/data/common/search/strategies/eql_search/types.ts +++ b/src/plugins/data/common/search/strategies/eql_search/types.ts @@ -6,17 +6,17 @@ * Side Public License, v 1. */ -import { EqlSearch } from '@elastic/elasticsearch/api/requestParams'; -import { ApiResponse, TransportRequestOptions } from '@elastic/elasticsearch/lib/Transport'; +import type { EqlSearchRequest } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { TransportResult, TransportRequestOptions } from '@elastic/elasticsearch'; import { IKibanaSearchRequest, IKibanaSearchResponse } from '../../types'; export const EQL_SEARCH_STRATEGY = 'eql'; -export type EqlRequestParams = EqlSearch>; +export type EqlRequestParams = EqlSearchRequest; export interface EqlSearchStrategyRequest extends IKibanaSearchRequest { options?: TransportRequestOptions; } -export type EqlSearchStrategyResponse = IKibanaSearchResponse>; +export type EqlSearchStrategyResponse = IKibanaSearchResponse>; diff --git a/src/plugins/data/common/search/strategies/es_search/types.ts b/src/plugins/data/common/search/strategies/es_search/types.ts index 05df661d466c8..73bf7961fea9b 100644 --- a/src/plugins/data/common/search/strategies/es_search/types.ts +++ b/src/plugins/data/common/search/strategies/es_search/types.ts @@ -5,7 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { IKibanaSearchRequest, IKibanaSearchResponse } from '../../types'; diff --git a/src/plugins/data/common/search/tabify/tabify_docs.test.ts b/src/plugins/data/common/search/tabify/tabify_docs.test.ts index 1964247b09585..8bba487cef9b3 100644 --- a/src/plugins/data/common/search/tabify/tabify_docs.test.ts +++ b/src/plugins/data/common/search/tabify/tabify_docs.test.ts @@ -8,7 +8,7 @@ import { tabifyDocs, flattenHit } from './tabify_docs'; import { IndexPattern, DataView } from '../..'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { fieldFormatsMock } from '../../../../field_formats/common/mocks'; import { stubbedSavedObjectIndexPattern } from '../../../../data_views/common/data_view.stub'; diff --git a/src/plugins/data/common/search/tabify/tabify_docs.ts b/src/plugins/data/common/search/tabify/tabify_docs.ts index 353a0c10ba12a..43b6155f6662f 100644 --- a/src/plugins/data/common/search/tabify/tabify_docs.ts +++ b/src/plugins/data/common/search/tabify/tabify_docs.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { isPlainObject } from 'lodash'; import { IndexPattern } from '../..'; import { Datatable, DatatableColumn, DatatableColumnType } from '../../../../expressions/common'; diff --git a/src/plugins/data/public/search/errors/types.ts b/src/plugins/data/public/search/errors/types.ts index 13c5d0c242ed0..d541e53be78f9 100644 --- a/src/plugins/data/public/search/errors/types.ts +++ b/src/plugins/data/public/search/errors/types.ts @@ -5,7 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { KibanaServerError } from '../../../../kibana_utils/common'; export interface FailedShard { diff --git a/src/plugins/data/public/search/errors/utils.ts b/src/plugins/data/public/search/errors/utils.ts index cb3e83dc8001c..4373939878d68 100644 --- a/src/plugins/data/public/search/errors/utils.ts +++ b/src/plugins/data/public/search/errors/utils.ts @@ -5,7 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import type { ErrorCause } from '@elastic/elasticsearch/api/types'; +import type { ErrorCause } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { FailedShard, Reason } from './types'; import { KibanaServerError } from '../../../../kibana_utils/common'; diff --git a/src/plugins/data/public/ui/shard_failure_modal/__mocks__/shard_failure_response.ts b/src/plugins/data/public/ui/shard_failure_modal/__mocks__/shard_failure_response.ts index e4a31995e47b6..50355a933ec5d 100644 --- a/src/plugins/data/public/ui/shard_failure_modal/__mocks__/shard_failure_response.ts +++ b/src/plugins/data/public/ui/shard_failure_modal/__mocks__/shard_failure_response.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; export const shardFailureResponse: estypes.SearchResponse = { _shards: { diff --git a/src/plugins/data/public/ui/shard_failure_modal/shard_failure_modal.tsx b/src/plugins/data/public/ui/shard_failure_modal/shard_failure_modal.tsx index 8e6ad4bc92c8f..e009af4250e6c 100644 --- a/src/plugins/data/public/ui/shard_failure_modal/shard_failure_modal.tsx +++ b/src/plugins/data/public/ui/shard_failure_modal/shard_failure_modal.tsx @@ -21,7 +21,7 @@ import { EuiButtonEmpty, EuiCallOut, } from '@elastic/eui'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ShardFailureTable } from './shard_failure_table'; import { ShardFailureRequest } from './shard_failure_types'; diff --git a/src/plugins/data/public/ui/shard_failure_modal/shard_failure_open_modal_button.tsx b/src/plugins/data/public/ui/shard_failure_modal/shard_failure_open_modal_button.tsx index a230378d6c3d3..4ebdd64fede13 100644 --- a/src/plugins/data/public/ui/shard_failure_modal/shard_failure_open_modal_button.tsx +++ b/src/plugins/data/public/ui/shard_failure_modal/shard_failure_open_modal_button.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; import { EuiButton, EuiTextAlign } from '@elastic/eui'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { getOverlays } from '../../services'; import { toMountPoint } from '../../../../kibana_react/public'; diff --git a/src/plugins/data/public/ui/shard_failure_modal/shard_failure_types.ts b/src/plugins/data/public/ui/shard_failure_modal/shard_failure_types.ts index 83e4abf55d525..c6533f9f0a850 100644 --- a/src/plugins/data/public/ui/shard_failure_modal/shard_failure_types.ts +++ b/src/plugins/data/public/ui/shard_failure_modal/shard_failure_types.ts @@ -5,7 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; export interface ShardFailureRequest { docvalue_fields: string[]; _source: unknown; diff --git a/src/plugins/data/server/autocomplete/terms_agg.test.ts b/src/plugins/data/server/autocomplete/terms_agg.test.ts index dcaa5390f3fe6..eb24b71cae274 100644 --- a/src/plugins/data/server/autocomplete/terms_agg.test.ts +++ b/src/plugins/data/server/autocomplete/terms_agg.test.ts @@ -10,9 +10,9 @@ import { coreMock } from '../../../../core/server/mocks'; import { ElasticsearchClient, SavedObjectsClientContract } from 'kibana/server'; import { ConfigSchema } from '../../config'; import type { DeeplyMockedKeys } from '@kbn/utility-types/jest'; -import type { ApiResponse } from '@elastic/elasticsearch'; +import type { TransportResult } from '@elastic/elasticsearch'; import { termsAggSuggestions } from './terms_agg'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { duration } from 'moment'; let savedObjectsClientMock: jest.Mocked; @@ -32,7 +32,7 @@ const mockResponse = { }, }, }, -} as ApiResponse>; +} as TransportResult>; jest.mock('../data_views'); diff --git a/src/plugins/data/server/autocomplete/terms_agg.ts b/src/plugins/data/server/autocomplete/terms_agg.ts index 41544b9e01233..20a8a5c212f26 100644 --- a/src/plugins/data/server/autocomplete/terms_agg.ts +++ b/src/plugins/data/server/autocomplete/terms_agg.ts @@ -8,11 +8,10 @@ import { get, map } from 'lodash'; import { ElasticsearchClient, SavedObjectsClientContract } from 'kibana/server'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ConfigSchema } from '../../config'; import { IFieldType, getFieldSubtypeNested } from '../../common'; import { findIndexPatternById, getFieldByName } from '../data_views'; -import { shimAbortSignal } from '../search'; export async function termsAggSuggestions( config: ConfigSchema, @@ -38,8 +37,12 @@ export async function termsAggSuggestions( const body = await getBody(autocompleteSearchOptions, field ?? fieldName, query, filters); - const promise = esClient.search({ index, body }); - const result = await shimAbortSignal(promise, abortSignal); + const result = await esClient.search( + { index, body }, + { + signal: abortSignal, + } + ); const buckets = get(result.body, 'aggregations.suggestions.buckets') || diff --git a/src/plugins/data/server/autocomplete/terms_enum.test.ts b/src/plugins/data/server/autocomplete/terms_enum.test.ts index 444ba4e89c58b..c0750ead5cc0a 100644 --- a/src/plugins/data/server/autocomplete/terms_enum.test.ts +++ b/src/plugins/data/server/autocomplete/terms_enum.test.ts @@ -11,8 +11,8 @@ import { coreMock } from '../../../../core/server/mocks'; import { ElasticsearchClient, SavedObjectsClientContract } from 'kibana/server'; import { ConfigSchema } from '../../config'; import type { DeeplyMockedKeys } from '@kbn/utility-types/jest'; -import type { ApiResponse } from '@elastic/elasticsearch'; -import { TermsEnumResponse } from '@elastic/elasticsearch/api/types'; +import type { TransportResult } from '@elastic/elasticsearch'; +import { TermsEnumResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; let savedObjectsClientMock: jest.Mocked; let esClientMock: DeeplyMockedKeys; @@ -31,7 +31,7 @@ describe('_terms_enum suggestions', () => { savedObjectsClientMock = requestHandlerContext.savedObjects.client; esClientMock = requestHandlerContext.elasticsearch.client.asCurrentUser; esClientMock.termsEnum.mockResolvedValue( - mockResponse as unknown as ApiResponse + mockResponse as unknown as TransportResult ); }); diff --git a/src/plugins/data/server/autocomplete/terms_enum.ts b/src/plugins/data/server/autocomplete/terms_enum.ts index 3d7f369233720..201ff32c056ce 100644 --- a/src/plugins/data/server/autocomplete/terms_enum.ts +++ b/src/plugins/data/server/autocomplete/terms_enum.ts @@ -7,10 +7,9 @@ */ import { ElasticsearchClient, SavedObjectsClientContract } from 'kibana/server'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { IFieldType } from '../../common'; import { findIndexPatternById, getFieldByName } from '../data_views'; -import { shimAbortSignal } from '../search'; import { ConfigSchema } from '../../config'; export async function termsEnumSuggestions( @@ -30,26 +29,30 @@ export async function termsEnumSuggestions( field = indexPattern && getFieldByName(fieldName, indexPattern); } - const promise = esClient.termsEnum({ - index, - body: { - field: field?.name ?? fieldName, - string: query, - index_filter: { - bool: { - must: [ - ...(filters ?? []), - { - terms: { - _tier: tiers, + const result = await esClient.termsEnum( + { + index, + body: { + field: field?.name ?? fieldName, + string: query, + index_filter: { + bool: { + must: [ + ...(filters ?? []), + { + terms: { + _tier: tiers, + }, }, - }, - ], + ], + }, }, }, }, - }); + { + signal: abortSignal, + } + ); - const result = await shimAbortSignal(promise, abortSignal); return result.body.terms; } diff --git a/src/plugins/data/server/search/strategies/eql_search/eql_search_strategy.ts b/src/plugins/data/server/search/strategies/eql_search/eql_search_strategy.ts index 4c75d62f12190..3d9294765cc15 100644 --- a/src/plugins/data/server/search/strategies/eql_search/eql_search_strategy.ts +++ b/src/plugins/data/server/search/strategies/eql_search/eql_search_strategy.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { ApiResponse } from '@elastic/elasticsearch'; +import type { TransportResult } from '@elastic/elasticsearch'; import { tap } from 'rxjs/operators'; import type { IScopedClusterClient, Logger } from 'kibana/server'; import { @@ -18,7 +18,7 @@ import { import { toEqlKibanaSearchResponse } from './response_utils'; import { EqlSearchResponse } from './types'; import { ISearchStrategy } from '../../types'; -import { getDefaultSearchParams, shimAbortSignal } from '../es_search'; +import { getDefaultSearchParams } from '../es_search'; import { getDefaultAsyncGetParams, getIgnoreThrottled } from '../ese_search/request_utils'; export const eqlSearchStrategyProvider = ( @@ -52,12 +52,15 @@ export const eqlSearchStrategyProvider = ( ...getDefaultAsyncGetParams(null, options), ...request.params, }; - const promise = id - ? client.get({ ...params, id }, request.options) - : // @ts-expect-error EqlRequestParams | undefined is not assignable to EqlRequestParams - client.search(params as EqlSearchStrategyRequest['params'], request.options); - const response = await shimAbortSignal(promise, options.abortSignal); - return toEqlKibanaSearchResponse(response as ApiResponse); + const response = id + ? await client.get({ ...params, id }, { ...request.options, signal: options.abortSignal }) + : // @ts-expect-error optional key cannot be used since search doesn't expect undefined + await client.search(params as EqlSearchStrategyRequest['params'], { + ...request.options, + abortController: { signal: options.abortSignal }, + }); + + return toEqlKibanaSearchResponse(response as TransportResult); }; const cancel = async () => { diff --git a/src/plugins/data/server/search/strategies/eql_search/response_utils.ts b/src/plugins/data/server/search/strategies/eql_search/response_utils.ts index 11b5a286e709d..f9bdf5bc7de30 100644 --- a/src/plugins/data/server/search/strategies/eql_search/response_utils.ts +++ b/src/plugins/data/server/search/strategies/eql_search/response_utils.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { ApiResponse } from '@elastic/elasticsearch'; +import type { TransportResult } from '@elastic/elasticsearch'; import { EqlSearchResponse } from './types'; import { EqlSearchStrategyResponse } from '../../../../common'; @@ -15,7 +15,7 @@ import { EqlSearchStrategyResponse } from '../../../../common'; * (EQL does not provide _shard info, so total/loaded cannot be calculated.) */ export function toEqlKibanaSearchResponse( - response: ApiResponse + response: TransportResult ): EqlSearchStrategyResponse { return { id: response.body.id, diff --git a/src/plugins/data/server/search/strategies/eql_search/types.ts b/src/plugins/data/server/search/strategies/eql_search/types.ts index 4b3c19fda78ea..695490b668e38 100644 --- a/src/plugins/data/server/search/strategies/eql_search/types.ts +++ b/src/plugins/data/server/search/strategies/eql_search/types.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; export interface EqlSearchResponse extends estypes.SearchResponse { id?: string; diff --git a/src/plugins/data/server/search/strategies/es_search/es_search_strategy.test.ts b/src/plugins/data/server/search/strategies/es_search/es_search_strategy.test.ts index bbbc99d157fe0..c06a75f3148a8 100644 --- a/src/plugins/data/server/search/strategies/es_search/es_search_strategy.test.ts +++ b/src/plugins/data/server/search/strategies/es_search/es_search_strategy.test.ts @@ -5,18 +5,14 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ - -import { - elasticsearchClientMock, - MockedTransportRequestPromise, - // eslint-disable-next-line @kbn/eslint/no-restricted-paths -} from '../../../../../../core/server/elasticsearch/client/mocks'; +import type { TransportResult } from '@elastic/elasticsearch'; +import { elasticsearchServiceMock } from '../../../../../../core/server/mocks'; import { pluginInitializerContextConfigMock } from '../../../../../../core/server/mocks'; import { esSearchStrategyProvider } from './es_search_strategy'; import { SearchStrategyDependencies } from '../../types'; import * as indexNotFoundException from '../../../../common/search/test_data/index_not_found_exception.json'; -import { ElasticsearchClientError, ResponseError } from '@elastic/elasticsearch/lib/errors'; +import { errors } from '@elastic/elasticsearch'; import { KbnServerError } from '../../../../../kibana_utils/server'; describe('ES search strategy', () => { @@ -27,9 +23,9 @@ describe('ES search strategy', () => { skipped: 2, successful: 7, }, - }; - let mockedApiCaller: MockedTransportRequestPromise; - let mockApiCaller: jest.Mock<() => MockedTransportRequestPromise>; + } as const; + let mockedApiCaller: Promise>; + let mockApiCaller: jest.Mock<() => TransportResult>; const mockLogger: any = { debug: () => {}, }; @@ -37,9 +33,9 @@ describe('ES search strategy', () => { function getMockedDeps(err?: Record) { mockApiCaller = jest.fn().mockImplementation(() => { if (err) { - mockedApiCaller = elasticsearchClientMock.createErrorTransportRequestPromise(err); + mockedApiCaller = elasticsearchServiceMock.createErrorTransportRequestPromise(err); } else { - mockedApiCaller = elasticsearchClientMock.createSuccessTransportRequestPromise( + mockedApiCaller = elasticsearchServiceMock.createSuccessTransportRequestPromise( successBody, { statusCode: 200 } ); @@ -108,7 +104,6 @@ describe('ES search strategy', () => { expect(data.isPartial).toBe(false); expect(data).toHaveProperty('loaded'); expect(data).toHaveProperty('rawResponse'); - expect(mockedApiCaller.abort).not.toBeCalled(); done(); })); @@ -127,12 +122,11 @@ describe('ES search strategy', () => { ...params, track_total_hits: true, }); - expect(mockedApiCaller.abort).toBeCalled(); }); it('throws normalized error if ResponseError is thrown', async (done) => { const params = { index: 'logstash-*', ignore_unavailable: false, timeout: '1000ms' }; - const errResponse = new ResponseError({ + const errResponse = new errors.ResponseError({ body: indexNotFoundException, statusCode: 404, headers: {}, @@ -156,7 +150,7 @@ describe('ES search strategy', () => { it('throws normalized error if ElasticsearchClientError is thrown', async (done) => { const params = { index: 'logstash-*', ignore_unavailable: false, timeout: '1000ms' }; - const errResponse = new ElasticsearchClientError('This is a general ESClient error'); + const errResponse = new errors.ElasticsearchClientError('This is a general ESClient error'); try { await esSearchStrategyProvider(mockConfig$, mockLogger) diff --git a/src/plugins/data/server/search/strategies/es_search/es_search_strategy.ts b/src/plugins/data/server/search/strategies/es_search/es_search_strategy.ts index c24aa37082bd8..097e099bf2997 100644 --- a/src/plugins/data/server/search/strategies/es_search/es_search_strategy.ts +++ b/src/plugins/data/server/search/strategies/es_search/es_search_strategy.ts @@ -11,7 +11,7 @@ import { first, tap } from 'rxjs/operators'; import type { Logger, SharedGlobalConfig } from 'kibana/server'; import type { ISearchStrategy } from '../../types'; import type { SearchUsage } from '../../collectors'; -import { getDefaultSearchParams, getShardTimeout, shimAbortSignal } from './request_utils'; +import { getDefaultSearchParams, getShardTimeout } from './request_utils'; import { shimHitsTotal, toKibanaSearchResponse } from './response_utils'; import { searchUsageObserver } from '../../collectors/usage'; import { getKbnServerError, KbnServerError } from '../../../../../kibana_utils/server'; @@ -38,13 +38,17 @@ export const esSearchStrategyProvider = ( const search = async () => { try { const config = await config$.pipe(first()).toPromise(); + // @ts-expect-error params fall back to any, but should be valid SearchRequest params + const { terminateAfter, ...requestParams } = request.params ?? {}; const params = { ...(await getDefaultSearchParams(uiSettingsClient)), ...getShardTimeout(config), - ...request.params, + ...(terminateAfter ? { terminate_after: terminateAfter } : {}), + ...requestParams, }; - const promise = esClient.asCurrentUser.search(params); - const { body } = await shimAbortSignal(promise, abortSignal); + const { body } = await esClient.asCurrentUser.search(params, { + signal: abortSignal, + }); const response = shimHitsTotal(body, options); return toKibanaSearchResponse(response); } catch (e) { diff --git a/src/plugins/data/server/search/strategies/es_search/request_utils.test.ts b/src/plugins/data/server/search/strategies/es_search/request_utils.test.ts index 5d1826d92f182..d6e078c71a87d 100644 --- a/src/plugins/data/server/search/strategies/es_search/request_utils.test.ts +++ b/src/plugins/data/server/search/strategies/es_search/request_utils.test.ts @@ -6,19 +6,9 @@ * Side Public License, v 1. */ -import { getShardTimeout, getDefaultSearchParams, shimAbortSignal } from './request_utils'; +import { getShardTimeout, getDefaultSearchParams } from './request_utils'; import { IUiSettingsClient, SharedGlobalConfig } from 'kibana/server'; -const createSuccessTransportRequestPromise = ( - body: any, - { statusCode = 200 }: { statusCode?: number } = {} -) => { - const promise = Promise.resolve({ body, statusCode }) as any; - promise.abort = jest.fn(); - - return promise; -}; - describe('request utils', () => { describe('getShardTimeout', () => { test('returns an empty object if the config does not contain a value', () => { @@ -89,49 +79,4 @@ describe('request utils', () => { }); }); }); - - describe('shimAbortSignal', () => { - test('aborts the promise if the signal is already aborted', async () => { - const promise = createSuccessTransportRequestPromise({ - success: true, - }); - const controller = new AbortController(); - controller.abort(); - shimAbortSignal(promise, controller.signal); - - expect(promise.abort).toHaveBeenCalled(); - }); - - test('aborts the promise if the signal is aborted', () => { - const promise = createSuccessTransportRequestPromise({ - success: true, - }); - const controller = new AbortController(); - shimAbortSignal(promise, controller.signal); - controller.abort(); - - expect(promise.abort).toHaveBeenCalled(); - }); - - test('returns the original promise', async () => { - const promise = createSuccessTransportRequestPromise({ - success: true, - }); - const controller = new AbortController(); - const response = await shimAbortSignal(promise, controller.signal); - - expect(response).toEqual(expect.objectContaining({ body: { success: true } })); - }); - - test('allows the promise to be aborted manually', () => { - const promise = createSuccessTransportRequestPromise({ - success: true, - }); - const controller = new AbortController(); - const enhancedPromise = shimAbortSignal(promise, controller.signal); - - enhancedPromise.abort(); - expect(promise.abort).toHaveBeenCalled(); - }); - }); }); diff --git a/src/plugins/data/server/search/strategies/es_search/request_utils.ts b/src/plugins/data/server/search/strategies/es_search/request_utils.ts index 15cad34065ddc..9a57ac56ce250 100644 --- a/src/plugins/data/server/search/strategies/es_search/request_utils.ts +++ b/src/plugins/data/server/search/strategies/es_search/request_utils.ts @@ -6,21 +6,24 @@ * Side Public License, v 1. */ -import type { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; -import type { Search } from '@elastic/elasticsearch/api/requestParams'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { IUiSettingsClient, SharedGlobalConfig } from 'kibana/server'; import { UI_SETTINGS } from '../../../../common'; -export function getShardTimeout(config: SharedGlobalConfig): Pick { +export function getShardTimeout( + config: SharedGlobalConfig +): Pick { const timeout = config.elasticsearch.shardTimeout.asMilliseconds(); return timeout ? { timeout: `${timeout}ms` } : {}; } export async function getDefaultSearchParams( uiSettingsClient: Pick -): Promise< - Pick -> { +): Promise<{ + max_concurrent_shard_requests?: number; + ignore_unavailable: boolean; + track_total_hits: boolean; +}> { const maxConcurrentShardRequests = await uiSettingsClient.get( UI_SETTINGS.COURIER_MAX_CONCURRENT_SHARD_REQUESTS ); @@ -31,25 +34,3 @@ export async function getDefaultSearchParams( track_total_hits: true, }; } - -/** - * Temporary workaround until https://github.com/elastic/elasticsearch-js/issues/1297 is resolved. - * Shims the `AbortSignal` behavior so that, if the given `signal` aborts, the `abort` method on the - * `TransportRequestPromise` is called, actually performing the cancellation. - * @internal - */ -export const shimAbortSignal = (promise: TransportRequestPromise, signal?: AbortSignal) => { - if (!signal) return promise; - const abortHandler = () => { - promise.abort(); - cleanup(); - }; - const cleanup = () => signal.removeEventListener('abort', abortHandler); - if (signal.aborted) { - promise.abort(); - } else { - signal.addEventListener('abort', abortHandler); - promise.then(cleanup, cleanup); - } - return promise; -}; diff --git a/src/plugins/data/server/search/strategies/es_search/response_utils.test.ts b/src/plugins/data/server/search/strategies/es_search/response_utils.test.ts index fc35187429a98..043bfd2e518ff 100644 --- a/src/plugins/data/server/search/strategies/es_search/response_utils.test.ts +++ b/src/plugins/data/server/search/strategies/es_search/response_utils.test.ts @@ -7,7 +7,7 @@ */ import { getTotalLoaded, toKibanaSearchResponse, shimHitsTotal } from './response_utils'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; describe('response utils', () => { describe('getTotalLoaded', () => { diff --git a/src/plugins/data/server/search/strategies/es_search/response_utils.ts b/src/plugins/data/server/search/strategies/es_search/response_utils.ts index 0553c015fb2da..4773b6df3bbaf 100644 --- a/src/plugins/data/server/search/strategies/es_search/response_utils.ts +++ b/src/plugins/data/server/search/strategies/es_search/response_utils.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ISearchOptions } from '../../../../common'; /** diff --git a/src/plugins/data/server/search/strategies/ese_search/ese_search_strategy.test.ts b/src/plugins/data/server/search/strategies/ese_search/ese_search_strategy.test.ts index 8d5fbf98db2d3..d4fe74486ee85 100644 --- a/src/plugins/data/server/search/strategies/ese_search/ese_search_strategy.test.ts +++ b/src/plugins/data/server/search/strategies/ese_search/ese_search_strategy.test.ts @@ -8,7 +8,7 @@ import { BehaviorSubject } from 'rxjs'; import { KbnServerError } from '../../../../../kibana_utils/server'; -import { ElasticsearchClientError, ResponseError } from '@elastic/elasticsearch/lib/errors'; +import { errors } from '@elastic/elasticsearch'; import * as indexNotFoundException from '../../../../common/search/test_data/index_not_found_exception.json'; import * as xContentParseException from '../../../../common/search/test_data/x_content_parse_exception.json'; import { SearchStrategyDependencies } from '../../types'; @@ -191,7 +191,7 @@ describe('ES search strategy', () => { }); it('throws normalized error if ResponseError is thrown', async () => { - const errResponse = new ResponseError({ + const errResponse = new errors.ResponseError({ body: indexNotFoundException, statusCode: 404, headers: {}, @@ -254,7 +254,7 @@ describe('ES search strategy', () => { }); it('throws normalized error on ResponseError', async () => { - const errResponse = new ResponseError({ + const errResponse = new errors.ResponseError({ body: xContentParseException, statusCode: 400, headers: {}, @@ -297,7 +297,7 @@ describe('ES search strategy', () => { }); it('throws normalized error on ElasticsearchClientError', async () => { - const errResponse = new ElasticsearchClientError('something is wrong with EsClient'); + const errResponse = new errors.ElasticsearchClientError('something is wrong with EsClient'); mockGetCaller.mockRejectedValue(errResponse); const id = 'some_other_id'; diff --git a/src/plugins/data/server/search/strategies/ese_search/ese_search_strategy.ts b/src/plugins/data/server/search/strategies/ese_search/ese_search_strategy.ts index 75a4ddf051418..e94f1aa44d351 100644 --- a/src/plugins/data/server/search/strategies/ese_search/ese_search_strategy.ts +++ b/src/plugins/data/server/search/strategies/ese_search/ese_search_strategy.ts @@ -9,7 +9,7 @@ import type { Observable } from 'rxjs'; import type { IScopedClusterClient, Logger, SharedGlobalConfig } from 'kibana/server'; import { catchError, first, tap } from 'rxjs/operators'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { from } from 'rxjs'; import type { ISearchStrategy, SearchStrategyDependencies } from '../../types'; import type { @@ -31,7 +31,6 @@ import { getDefaultSearchParams, getShardTimeout, getTotalLoaded, - shimAbortSignal, shimHitsTotal, } from '../es_search'; @@ -68,10 +67,11 @@ export const enhancedEsSearchStrategyProvider = ( )), ...request.params, }; - const promise = id - ? client.asyncSearch.get({ ...params, id }) - : client.asyncSearch.submit(params); - const { body, headers } = await shimAbortSignal(promise, options.abortSignal); + const { body, headers } = id + ? await client.asyncSearch.get({ ...params, id }, { signal: options.abortSignal }) + : await client.asyncSearch.submit(params, { + signal: options.abortSignal, + }); const response = shimHitsTotal(body.response, options); @@ -115,14 +115,18 @@ export const enhancedEsSearchStrategyProvider = ( }; try { - const promise = client.transport.request({ - method, - path, - body, - querystring, - }); + const esResponse = await client.transport.request( + { + method, + path, + body, + querystring, + }, + { + signal: options?.abortSignal, + } + ); - const esResponse = await shimAbortSignal(promise, options?.abortSignal); const response = esResponse.body as estypes.SearchResponse; return { rawResponse: shimHitsTotal(response, options), diff --git a/src/plugins/data/server/search/strategies/ese_search/request_utils.ts b/src/plugins/data/server/search/strategies/ese_search/request_utils.ts index f8fb54cfd870b..85f9f243ad2b1 100644 --- a/src/plugins/data/server/search/strategies/ese_search/request_utils.ts +++ b/src/plugins/data/server/search/strategies/ese_search/request_utils.ts @@ -7,11 +7,8 @@ */ import { IUiSettingsClient } from 'kibana/server'; -import { - AsyncSearchGet, - AsyncSearchSubmit, - Search, -} from '@elastic/elasticsearch/api/requestParams'; +import { AsyncSearchGetRequest } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { AsyncSearchSubmitRequest } from '@elastic/elasticsearch/lib/api/types'; import { ISearchOptions, UI_SETTINGS } from '../../../../common'; import { getDefaultSearchParams } from '../es_search'; import { SearchSessionsConfigSchema } from '../../../../config'; @@ -21,7 +18,7 @@ import { SearchSessionsConfigSchema } from '../../../../config'; */ export async function getIgnoreThrottled( uiSettingsClient: Pick -): Promise> { +): Promise<{ ignore_throttled?: boolean }> { const includeFrozen = await uiSettingsClient.get(UI_SETTINGS.SEARCH_INCLUDE_FROZEN); return includeFrozen ? { ignore_throttled: false } : {}; } @@ -35,7 +32,7 @@ export async function getDefaultAsyncSubmitParams( options: ISearchOptions ): Promise< Pick< - AsyncSearchSubmit, + AsyncSearchSubmitRequest, | 'batched_reduce_size' | 'keep_alive' | 'wait_for_completion_timeout' @@ -75,7 +72,7 @@ export async function getDefaultAsyncSubmitParams( export function getDefaultAsyncGetParams( searchSessionsConfig: SearchSessionsConfigSchema | null, options: ISearchOptions -): Pick { +): Pick { const useSearchSessions = searchSessionsConfig?.enabled && !!options.sessionId; return { diff --git a/src/plugins/data/server/search/strategies/ese_search/types.ts b/src/plugins/data/server/search/strategies/ese_search/types.ts index 7f21aa3616e4e..4116aa4380339 100644 --- a/src/plugins/data/server/search/strategies/ese_search/types.ts +++ b/src/plugins/data/server/search/strategies/ese_search/types.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; export interface AsyncSearchResponse { id?: string; diff --git a/src/plugins/data_views/common/data_views/data_view.ts b/src/plugins/data_views/common/data_views/data_view.ts index b7823677b70f9..9a597d5ae4471 100644 --- a/src/plugins/data_views/common/data_views/data_view.ts +++ b/src/plugins/data_views/common/data_views/data_view.ts @@ -10,7 +10,7 @@ import _, { each, reject } from 'lodash'; import { castEsToKbnFieldTypeName, ES_FIELD_TYPES, KBN_FIELD_TYPES } from '@kbn/field-types'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { FieldAttrs, FieldAttrSet, DataViewAttributes } from '..'; import type { RuntimeField } from '../types'; import { DuplicateField } from '../../../kibana_utils/common'; diff --git a/src/plugins/data_views/common/types.ts b/src/plugins/data_views/common/types.ts index bbc5ad374636f..3a623f89a72e2 100644 --- a/src/plugins/data_views/common/types.ts +++ b/src/plugins/data_views/common/types.ts @@ -5,7 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { DataViewFieldBase, IFieldSubType, DataViewBase } from '@kbn/es-query'; import { ToastInputFields, ErrorToastOptions } from 'src/core/public/notifications'; // eslint-disable-next-line diff --git a/src/plugins/data_views/server/fetcher/lib/field_capabilities/field_caps_response.ts b/src/plugins/data_views/server/fetcher/lib/field_capabilities/field_caps_response.ts index 6dff343f9e00e..75bede61e10d8 100644 --- a/src/plugins/data_views/server/fetcher/lib/field_capabilities/field_caps_response.ts +++ b/src/plugins/data_views/server/fetcher/lib/field_capabilities/field_caps_response.ts @@ -7,7 +7,7 @@ */ import { uniq } from 'lodash'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { castEsToKbnFieldTypeName } from '@kbn/field-types'; import { shouldReadFieldFromDocValues } from './should_read_field_from_doc_values'; import { FieldDescriptor } from '../../../fetcher'; @@ -116,7 +116,6 @@ export function readFieldCapsResponse( }), {} ), - // @ts-expect-error metadata_field: capsByType[types[0]].metadata_field, }; // This is intentionally using a "hash" and a "push" to be highly optimized with very large indexes @@ -133,7 +132,6 @@ export function readFieldCapsResponse( searchable: isSearchable, aggregatable: isAggregatable, readFromDocValues: shouldReadFieldFromDocValues(isAggregatable, esType), - // @ts-expect-error metadata_field: capsByType[types[0]].metadata_field, }; // This is intentionally using a "hash" and a "push" to be highly optimized with very large indexes diff --git a/src/plugins/discover/public/application/apps/main/components/doc_table/lib/row_formatter.tsx b/src/plugins/discover/public/application/apps/main/components/doc_table/lib/row_formatter.tsx index 2702a232f21ef..a73bc3f175be1 100644 --- a/src/plugins/discover/public/application/apps/main/components/doc_table/lib/row_formatter.tsx +++ b/src/plugins/discover/public/application/apps/main/components/doc_table/lib/row_formatter.tsx @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import React, { Fragment } from 'react'; import type { IndexPattern } from 'src/plugins/data/common'; import { MAX_DOC_FIELDS_DISPLAYED } from '../../../../../../../common'; diff --git a/src/plugins/discover/public/application/apps/main/utils/fetch_chart.test.ts b/src/plugins/discover/public/application/apps/main/utils/fetch_chart.test.ts index 2c050a9391a86..2c9350b457779 100644 --- a/src/plugins/discover/public/application/apps/main/utils/fetch_chart.test.ts +++ b/src/plugins/discover/public/application/apps/main/utils/fetch_chart.test.ts @@ -14,7 +14,7 @@ import { ReduxLikeStateContainer } from '../../../../../../kibana_utils/common'; import { AppState } from '../services/discover_state'; import { discoverServiceMock } from '../../../../__mocks__/services'; import { calculateBounds, IKibanaSearchResponse } from '../../../../../../data/common'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; function getDataSubjects() { return { diff --git a/src/plugins/discover/public/application/doc_views/doc_views_types.ts b/src/plugins/discover/public/application/doc_views/doc_views_types.ts index d3e482c0f2e1d..e8faa51bbab40 100644 --- a/src/plugins/discover/public/application/doc_views/doc_views_types.ts +++ b/src/plugins/discover/public/application/doc_views/doc_views_types.ts @@ -8,7 +8,7 @@ import { ComponentType } from 'react'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { IndexPattern } from '../../../../data/public'; export type ElasticSearchHit = estypes.SearchHit; diff --git a/src/plugins/discover/public/application/helpers/format_hit.test.ts b/src/plugins/discover/public/application/helpers/format_hit.test.ts index 2cb46f28dd397..ebf5078238ccf 100644 --- a/src/plugins/discover/public/application/helpers/format_hit.test.ts +++ b/src/plugins/discover/public/application/helpers/format_hit.test.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { indexPatternMock as dataViewMock } from '../../__mocks__/index_pattern'; import { formatHit } from './format_hit'; import { discoverServiceMock } from '../../__mocks__/services'; diff --git a/src/plugins/discover/public/application/helpers/format_hit.ts b/src/plugins/discover/public/application/helpers/format_hit.ts index 3890973a3f3e4..1101439515523 100644 --- a/src/plugins/discover/public/application/helpers/format_hit.ts +++ b/src/plugins/discover/public/application/helpers/format_hit.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { DataView, flattenHit } from '../../../../data/common'; import { MAX_DOC_FIELDS_DISPLAYED } from '../../../common'; import { getServices } from '../../kibana_services'; diff --git a/src/plugins/discover/public/application/helpers/format_value.ts b/src/plugins/discover/public/application/helpers/format_value.ts index cc33276790372..933309d6dcf8e 100644 --- a/src/plugins/discover/public/application/helpers/format_value.ts +++ b/src/plugins/discover/public/application/helpers/format_value.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { DataView, DataViewField, KBN_FIELD_TYPES } from '../../../../data/common'; import { getServices } from '../../kibana_services'; diff --git a/src/plugins/discover/public/application/helpers/get_ignored_reason.ts b/src/plugins/discover/public/application/helpers/get_ignored_reason.ts index 4d2fb85bdb2c4..bf8df6e000d4c 100644 --- a/src/plugins/discover/public/application/helpers/get_ignored_reason.ts +++ b/src/plugins/discover/public/application/helpers/get_ignored_reason.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { DataViewField, KBN_FIELD_TYPES } from '../../../../data/common'; export enum IgnoredReason { diff --git a/src/plugins/discover/public/application/services/use_es_doc_search.ts b/src/plugins/discover/public/application/services/use_es_doc_search.ts index 16a24ff27292b..fa7dce9c7e0a4 100644 --- a/src/plugins/discover/public/application/services/use_es_doc_search.ts +++ b/src/plugins/discover/public/application/services/use_es_doc_search.ts @@ -7,7 +7,7 @@ */ import { useCallback, useEffect, useMemo, useState } from 'react'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { IndexPattern } from '../../../../data/common'; import { DocProps } from '../apps/doc/components/doc'; import { ElasticRequestState } from '../apps/doc/types'; diff --git a/src/plugins/discover/public/application/types.ts b/src/plugins/discover/public/application/types.ts index a28c5bbc89aed..f04f3bf77c2f9 100644 --- a/src/plugins/discover/public/application/types.ts +++ b/src/plugins/discover/public/application/types.ts @@ -5,7 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; export enum FetchStatus { UNINITIALIZED = 'uninitialized', diff --git a/src/plugins/es_ui_shared/__packages_do_not_import__/errors/handle_es_error.ts b/src/plugins/es_ui_shared/__packages_do_not_import__/errors/handle_es_error.ts index 678c46f69d51f..07a681f002f33 100644 --- a/src/plugins/es_ui_shared/__packages_do_not_import__/errors/handle_es_error.ts +++ b/src/plugins/es_ui_shared/__packages_do_not_import__/errors/handle_es_error.ts @@ -6,13 +6,12 @@ * Side Public License, v 1. */ -import { ApiError } from '@elastic/elasticsearch'; -import { ResponseError } from '@elastic/elasticsearch/lib/errors'; +import { errors } from '@elastic/elasticsearch'; import { IKibanaResponse, KibanaResponseFactory } from 'kibana/server'; import { getEsCause } from './es_error_parser'; interface EsErrorHandlerParams { - error: ApiError; + error: errors.ElasticsearchClientError; response: KibanaResponseFactory; handleCustomError?: () => IKibanaResponse; } @@ -34,9 +33,9 @@ export const handleEsError = ({ return handleCustomError(); } - const { statusCode, body } = error as ResponseError; + const { statusCode, body } = error as errors.ResponseError; return response.customError({ - statusCode, + statusCode: statusCode!, body: { message: // We use || instead of ?? as the switch here because reason could be an empty string diff --git a/src/plugins/index_pattern_field_editor/server/routes/field_preview.ts b/src/plugins/index_pattern_field_editor/server/routes/field_preview.ts index 847dd41e0082b..9ffa5c88df8e8 100644 --- a/src/plugins/index_pattern_field_editor/server/routes/field_preview.ts +++ b/src/plugins/index_pattern_field_editor/server/routes/field_preview.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { schema } from '@kbn/config-schema'; import { API_BASE_PATH } from '../../common/constants'; diff --git a/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/types.ts b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/types.ts index 45a59b97b9490..e2657d7111ea6 100644 --- a/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/types.ts +++ b/src/plugins/index_pattern_management/public/components/edit_index_pattern/scripted_fields_table/types.ts @@ -5,7 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; /** @internal **/ export interface ScriptedFieldItem { name: string; diff --git a/src/plugins/index_pattern_management/public/components/field_editor/field_editor.tsx b/src/plugins/index_pattern_management/public/components/field_editor/field_editor.tsx index 9509f4fb46e0b..234da4f3bbe05 100644 --- a/src/plugins/index_pattern_management/public/components/field_editor/field_editor.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/field_editor.tsx @@ -5,7 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import React, { PureComponent, Fragment } from 'react'; import { intersection, union, get } from 'lodash'; diff --git a/src/plugins/index_pattern_management/public/scripting_languages/index.ts b/src/plugins/index_pattern_management/public/scripting_languages/index.ts index aeb38c8172be0..46bb0a359ae89 100644 --- a/src/plugins/index_pattern_management/public/scripting_languages/index.ts +++ b/src/plugins/index_pattern_management/public/scripting_languages/index.ts @@ -5,7 +5,7 @@ * in compliance with, at your election, the Elastic License 2.0 or the Server * Side Public License, v 1. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { i18n } from '@kbn/i18n'; import { HttpStart, NotificationsStart } from 'src/core/public'; diff --git a/src/plugins/interactive_setup/server/elasticsearch_service.test.ts b/src/plugins/interactive_setup/server/elasticsearch_service.test.ts index 9baed65db299d..93870578d8cc4 100644 --- a/src/plugins/interactive_setup/server/elasticsearch_service.test.ts +++ b/src/plugins/interactive_setup/server/elasticsearch_service.test.ts @@ -289,7 +289,8 @@ describe('ElasticsearchService', () => { it('treats product check error the same as successful response', async () => { mockConnectionStatusClient.asInternalUser.ping.mockRejectedValue( - new errors.ProductNotSupportedError(interactiveSetupMock.createApiResponse({ body: {} })) + // @ts-expect-error not full interface + new errors.ProductNotSupportedError('product-name', { body: {} }) ); const mockHandler = jest.fn(); @@ -538,7 +539,8 @@ some weird+ca/with it('fails if host is not supported', async () => { mockPingClient.asInternalUser.ping.mockRejectedValue( - new errors.ProductNotSupportedError(interactiveSetupMock.createApiResponse({ body: {} })) + // @ts-expect-error not full interface + new errors.ProductNotSupportedError('Elasticsearch', { body: {} }) ); await expect(setupContract.ping('http://localhost:9200')).rejects.toMatchInlineSnapshot( diff --git a/src/plugins/interactive_setup/server/elasticsearch_service.ts b/src/plugins/interactive_setup/server/elasticsearch_service.ts index b3b25b13c5a9b..5d41f16b01add 100644 --- a/src/plugins/interactive_setup/server/elasticsearch_service.ts +++ b/src/plugins/interactive_setup/server/elasticsearch_service.ts @@ -6,8 +6,8 @@ * Side Public License, v 1. */ -import type { ApiResponse } from '@elastic/elasticsearch'; import { errors } from '@elastic/elasticsearch'; +import type { TransportResult } from '@elastic/elasticsearch'; import type { Duration } from 'moment'; import type { Observable } from 'rxjs'; import { from, of, timer } from 'rxjs'; @@ -193,7 +193,7 @@ export class ElasticsearchService { .asCurrentUser.transport.request({ method: 'GET', path: '/_security/enroll/kibana', - })) as ApiResponse<{ token: { name: string; value: string }; http_ca: string }>; + })) as TransportResult<{ token: { name: string; value: string }; http_ca: string }>; } catch (err) { // We expect that all hosts belong to exactly same node and any non-connection error for one host would mean // that enrollment will fail for any other host and we should bail out. diff --git a/src/plugins/interactive_setup/server/errors.ts b/src/plugins/interactive_setup/server/errors.ts index 5f1d2388b3938..89962e06e0e61 100644 --- a/src/plugins/interactive_setup/server/errors.ts +++ b/src/plugins/interactive_setup/server/errors.ts @@ -14,7 +14,7 @@ import { errors } from '@elastic/elasticsearch'; */ export function getErrorStatusCode(error: any): number { if (error instanceof errors.ResponseError) { - return error.statusCode; + return error.statusCode!; } return error.statusCode || error.status; diff --git a/src/plugins/interactive_setup/server/mocks.ts b/src/plugins/interactive_setup/server/mocks.ts index 75b28a502b6d4..eb531e35f8dff 100644 --- a/src/plugins/interactive_setup/server/mocks.ts +++ b/src/plugins/interactive_setup/server/mocks.ts @@ -6,15 +6,17 @@ * Side Public License, v 1. */ -import type { ApiResponse } from '@elastic/elasticsearch'; +import type { TransportResult } from '@elastic/elasticsearch'; function createApiResponseMock( - apiResponse: Pick, 'body'> & - Partial, 'body'>> -): ApiResponse { + apiResponse: Pick, 'body'> & + Partial, 'body'>> +): TransportResult { return { + // @ts-expect-error null is not supported statusCode: null, - headers: null, + // @ts-expect-error null is not supported + headers: undefined, warnings: null, meta: {} as any, ...apiResponse, diff --git a/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/track_delays.ts b/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/track_delays.ts index facdb549d0df7..33266cdbd9792 100644 --- a/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/track_delays.ts +++ b/src/plugins/kibana_usage_collection/server/collectors/event_loop_delays/track_delays.ts @@ -52,6 +52,10 @@ export function startTrackingEventLoopDelaysUsage( if (shouldReset) { eventLoopDelaysMonitor.reset(); } - await storeHistogram(histogram, internalRepository, instanceUuid); + try { + await storeHistogram(histogram, internalRepository, instanceUuid); + } catch (e) { + // do not crash if cannot store a histogram. + } }); } diff --git a/src/plugins/kibana_usage_collection/server/plugin.ts b/src/plugins/kibana_usage_collection/server/plugin.ts index 96d37c0303482..19adea4f009a2 100644 --- a/src/plugins/kibana_usage_collection/server/plugin.ts +++ b/src/plugins/kibana_usage_collection/server/plugin.ts @@ -108,6 +108,8 @@ export class KibanaUsageCollectionPlugin implements Plugin { public stop() { this.metric$.complete(); + + this.pluginStop$.next(); this.pluginStop$.complete(); } diff --git a/src/plugins/kibana_utils/server/report_server_error.ts b/src/plugins/kibana_utils/server/report_server_error.ts index 9f0bf34eaebb6..57b8c4e207f72 100644 --- a/src/plugins/kibana_utils/server/report_server_error.ts +++ b/src/plugins/kibana_utils/server/report_server_error.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { ResponseError } from '@elastic/elasticsearch/lib/errors'; +import { errors } from '@elastic/elasticsearch'; import { KibanaResponseFactory } from 'kibana/server'; import { KbnError } from '../common'; @@ -27,8 +27,8 @@ export function getKbnServerError(e: Error) { if (e instanceof KbnServerError) return e; return new KbnServerError( e.message ?? 'Unknown error', - e instanceof ResponseError ? e.statusCode : 500, - e instanceof ResponseError ? e.body : undefined + e instanceof errors.ResponseError ? e.statusCode! : 500, + e instanceof errors.ResponseError ? e.body : undefined ); } diff --git a/src/plugins/telemetry/server/telemetry_collection/get_local_stats.test.ts b/src/plugins/telemetry/server/telemetry_collection/get_local_stats.test.ts index 1a00d0e428016..191e857c777d2 100644 --- a/src/plugins/telemetry/server/telemetry_collection/get_local_stats.test.ts +++ b/src/plugins/telemetry/server/telemetry_collection/get_local_stats.test.ts @@ -7,7 +7,7 @@ */ import { merge, omit } from 'lodash'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { getLocalStats, handleLocalStats } from './get_local_stats'; import { diff --git a/src/plugins/telemetry/server/telemetry_collection/get_local_stats.ts b/src/plugins/telemetry/server/telemetry_collection/get_local_stats.ts index 7860949e098aa..ae2a849ccfa19 100644 --- a/src/plugins/telemetry/server/telemetry_collection/get_local_stats.ts +++ b/src/plugins/telemetry/server/telemetry_collection/get_local_stats.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { StatsGetter, StatsCollectionContext, diff --git a/src/plugins/telemetry/server/telemetry_collection/get_nodes_usage.ts b/src/plugins/telemetry/server/telemetry_collection/get_nodes_usage.ts index 0d58d80ed5965..a5d4f32b3a62f 100644 --- a/src/plugins/telemetry/server/telemetry_collection/get_nodes_usage.ts +++ b/src/plugins/telemetry/server/telemetry_collection/get_nodes_usage.ts @@ -7,7 +7,7 @@ */ import type { ElasticsearchClient } from 'src/core/server'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { TIMEOUT } from './constants'; /** diff --git a/src/plugins/vis_types/vega/public/data_model/es_query_parser.ts b/src/plugins/vis_types/vega/public/data_model/es_query_parser.ts index 7f6ca05df3d7a..f52101212662d 100644 --- a/src/plugins/vis_types/vega/public/data_model/es_query_parser.ts +++ b/src/plugins/vis_types/vega/public/data_model/es_query_parser.ts @@ -9,7 +9,7 @@ import moment from 'moment'; import { i18n } from '@kbn/i18n'; import { cloneDeep, isPlainObject } from 'lodash'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Assign } from 'utility-types'; import { TimeCache } from './time_cache'; import { SearchAPI } from './search_api'; diff --git a/src/plugins/vis_types/vega/public/data_model/types.ts b/src/plugins/vis_types/vega/public/data_model/types.ts index d1568bba6c98c..19efe5a9a4b7d 100644 --- a/src/plugins/vis_types/vega/public/data_model/types.ts +++ b/src/plugins/vis_types/vega/public/data_model/types.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Assign } from '@kbn/utility-types'; import { Spec } from 'vega'; import { EsQueryParser } from './es_query_parser'; diff --git a/test/api_integration/apis/home/sample_data.ts b/test/api_integration/apis/home/sample_data.ts index 1e029bc1e04d7..2525cbe330044 100644 --- a/test/api_integration/apis/home/sample_data.ts +++ b/test/api_integration/apis/home/sample_data.ts @@ -48,7 +48,7 @@ export default function ({ getService }: FtrProviderContext) { }); it('should load elasticsearch index containing sample data with dates relative to current time', async () => { - const { body: resp } = await es.search<{ timestamp: string }>({ + const resp = await es.search<{ timestamp: string }>({ index: 'kibana_sample_data_flights', }); @@ -66,7 +66,7 @@ export default function ({ getService }: FtrProviderContext) { .post(`/api/sample_data/flights?now=${nowString}`) .set('kbn-xsrf', 'kibana'); - const { body: resp } = await es.search<{ timestamp: string }>({ + const resp = await es.search<{ timestamp: string }>({ index: 'kibana_sample_data_flights', }); @@ -85,7 +85,7 @@ export default function ({ getService }: FtrProviderContext) { }); it('should remove elasticsearch index containing sample data', async () => { - const { body: resp } = await es.indices.exists({ + const resp = await es.indices.exists({ index: 'kibana_sample_data_flights', }); expect(resp).to.be(false); diff --git a/test/api_integration/apis/index_patterns/has_user_index_pattern/has_user_index_pattern.ts b/test/api_integration/apis/index_patterns/has_user_index_pattern/has_user_index_pattern.ts index 8dfb892acfd90..8fc4e860e5d9c 100644 --- a/test/api_integration/apis/index_patterns/has_user_index_pattern/has_user_index_pattern.ts +++ b/test/api_integration/apis/index_patterns/has_user_index_pattern/has_user_index_pattern.ts @@ -17,11 +17,11 @@ export default function ({ getService }: FtrProviderContext) { describe('has user index pattern API', () => { beforeEach(async () => { await esArchiver.emptyKibanaIndex(); - if ((await es.indices.exists({ index: 'metrics-test' })).body) { + if (await es.indices.exists({ index: 'metrics-test' })) { await es.indices.delete({ index: 'metrics-test' }); } - if ((await es.indices.exists({ index: 'logs-test' })).body) { + if (await es.indices.exists({ index: 'logs-test' })) { await es.indices.delete({ index: 'logs-test' }); } }); diff --git a/test/api_integration/apis/kql_telemetry/kql_telemetry.ts b/test/api_integration/apis/kql_telemetry/kql_telemetry.ts index 5770ed0866a90..4825b454bc42f 100644 --- a/test/api_integration/apis/kql_telemetry/kql_telemetry.ts +++ b/test/api_integration/apis/kql_telemetry/kql_telemetry.ts @@ -40,7 +40,7 @@ export default function ({ getService }: FtrProviderContext) { index: '.kibana', q: 'type:kql-telemetry', }) - .then(({ body: response }) => { + .then((response) => { const kqlTelemetryDoc = get(response, 'hits.hits[0]._source.kql-telemetry'); expect(kqlTelemetryDoc.optInCount).to.be(1); }); @@ -58,7 +58,7 @@ export default function ({ getService }: FtrProviderContext) { index: '.kibana', q: 'type:kql-telemetry', }) - .then(({ body: response }) => { + .then((response) => { const kqlTelemetryDoc = get(response, 'hits.hits[0]._source.kql-telemetry'); expect(kqlTelemetryDoc.optOutCount).to.be(1); }); diff --git a/test/api_integration/apis/saved_objects/delete_unknown_types.ts b/test/api_integration/apis/saved_objects/delete_unknown_types.ts index 42caa753683e1..af9e413de0279 100644 --- a/test/api_integration/apis/saved_objects/delete_unknown_types.ts +++ b/test/api_integration/apis/saved_objects/delete_unknown_types.ts @@ -31,7 +31,7 @@ export default function ({ getService }: FtrProviderContext) { }); const fetchIndexContent = async () => { - const { body } = await es.search<{ type: string }>({ + const body = await es.search<{ type: string }>({ index: '.kibana', body: { size: 100, diff --git a/test/api_integration/apis/saved_objects/migrations.ts b/test/api_integration/apis/saved_objects/migrations.ts index 0877998ca6c1f..cba62ee51763d 100644 --- a/test/api_integration/apis/saved_objects/migrations.ts +++ b/test/api_integration/apis/saved_objects/migrations.ts @@ -14,7 +14,8 @@ import uuidv5 from 'uuid/v5'; import { set } from '@elastic/safer-lodash-set'; import _ from 'lodash'; import expect from '@kbn/expect'; -import { ElasticsearchClient, SavedObjectsType } from 'src/core/server'; +import { SavedObjectsType } from 'src/core/server'; +import { Client as ElasticsearchClient } from '@elastic/elasticsearch'; import { DocumentMigrator, @@ -136,7 +137,7 @@ export default ({ getService }: FtrProviderContext) => { const migrationATemplate = await esClient.indices.existsTemplate({ name: 'migration_a_template', }); - expect(migrationATemplate.body).to.be.ok(); + expect(migrationATemplate).to.be.ok(); const result = await migrateIndex({ esClient, @@ -150,12 +151,12 @@ export default ({ getService }: FtrProviderContext) => { name: 'migration_a_template', }); - expect(migrationATemplateAfter.body).not.to.be.ok(); + expect(migrationATemplateAfter).not.to.be.ok(); const migrationTestATemplateAfter = await esClient.indices.existsTemplate({ name: 'migration_test_a_template', }); - expect(migrationTestATemplateAfter.body).to.be.ok(); + expect(migrationTestATemplateAfter).to.be.ok(); expect(_.omit(result, 'elapsedMs')).to.eql({ destIndex: '.migration-a_2', sourceIndex: '.migration-a_1', @@ -451,7 +452,7 @@ export default ({ getService }: FtrProviderContext) => { { status: 'skipped', destIndex: undefined }, ]); - const { body } = await esClient.cat.indices({ index: '.migration-c*', format: 'json' }); + const body = await esClient.cat.indices({ index: '.migration-c*', format: 'json' }); // It only created the original and the dest expect(_.map(body, 'index').sort()).to.eql(['.migration-c_1', '.migration-c_2']); @@ -747,7 +748,7 @@ async function migrateIndex({ } async function fetchDocs(esClient: ElasticsearchClient, index: string) { - const { body } = await esClient.search({ index }); + const body = await esClient.search({ index }); return body.hits.hits .map((h) => ({ diff --git a/test/api_integration/apis/telemetry/telemetry_optin_notice_seen.ts b/test/api_integration/apis/telemetry/telemetry_optin_notice_seen.ts index a76d09481eca1..a2c48996069b2 100644 --- a/test/api_integration/apis/telemetry/telemetry_optin_notice_seen.ts +++ b/test/api_integration/apis/telemetry/telemetry_optin_notice_seen.ts @@ -25,9 +25,7 @@ export default function optInTest({ getService }: FtrProviderContext) { await supertest.put('/api/telemetry/v2/userHasSeenNotice').set('kbn-xsrf', 'xxx').expect(200); - const { - body: { _source }, - } = await client.get<{ telemetry: { userHasSeenNotice: boolean } }>({ + const { _source } = await client.get<{ telemetry: { userHasSeenNotice: boolean } }>({ index: '.kibana', id: 'telemetry:telemetry', }); diff --git a/test/api_integration/apis/ui_metric/ui_metric.ts b/test/api_integration/apis/ui_metric/ui_metric.ts index 3f0a4c0778911..83f84af4eb9bd 100644 --- a/test/api_integration/apis/ui_metric/ui_metric.ts +++ b/test/api_integration/apis/ui_metric/ui_metric.ts @@ -50,7 +50,7 @@ export default function ({ getService }: FtrProviderContext) { .send({ report }) .expect(200); - const { body: response } = await es.search({ index: '.kibana', q: 'type:ui-metric' }); + const response = await es.search({ index: '.kibana', q: 'type:ui-metric' }); const ids = response.hits.hits.map(({ _id }: { _id: string }) => _id); expect(ids.includes('ui-metric:myApp:myEvent')).to.eql(true); }); @@ -75,7 +75,7 @@ export default function ({ getService }: FtrProviderContext) { .send({ report }) .expect(200); - const { body: response } = await es.search({ index: '.kibana', q: 'type:ui-metric' }); + const response = await es.search({ index: '.kibana', q: 'type:ui-metric' }); const ids = response.hits.hits.map(({ _id }: { _id: string }) => _id); expect(ids.includes('ui-metric:myApp:myEvent')).to.eql(true); expect(ids.includes(`ui-metric:myApp:${uniqueEventName}`)).to.eql(true); @@ -99,9 +99,7 @@ export default function ({ getService }: FtrProviderContext) { .expect(200); const { - body: { - hits: { hits }, - }, + hits: { hits }, } = await es.search({ index: '.kibana', q: 'type:ui-metric' }); const countTypeEvent = hits.find( diff --git a/test/common/services/elasticsearch.ts b/test/common/services/elasticsearch.ts index 7b8ff6bd6c8f4..384f98e31bf3c 100644 --- a/test/common/services/elasticsearch.ts +++ b/test/common/services/elasticsearch.ts @@ -8,30 +8,31 @@ import { format as formatUrl } from 'url'; import fs from 'fs'; -import { Client } from '@elastic/elasticsearch'; +import { Client, HttpConnection } from '@elastic/elasticsearch'; import { CA_CERT_PATH } from '@kbn/dev-utils'; -import type { KibanaClient } from '@elastic/elasticsearch/api/kibana'; import { FtrProviderContext } from '../ftr_provider_context'; /* registers Kibana-specific @elastic/elasticsearch client instance. */ -export function ElasticsearchProvider({ getService }: FtrProviderContext): KibanaClient { +export function ElasticsearchProvider({ getService }: FtrProviderContext): Client { const config = getService('config'); if (process.env.TEST_CLOUD) { return new Client({ nodes: [formatUrl(config.get('servers.elasticsearch'))], requestTimeout: config.get('timeouts.esRequestTimeout'), + Connection: HttpConnection, }); } else { return new Client({ - ssl: { + tls: { ca: fs.readFileSync(CA_CERT_PATH, 'utf-8'), }, nodes: [formatUrl(config.get('servers.elasticsearch'))], requestTimeout: config.get('timeouts.esRequestTimeout'), + Connection: HttpConnection, }); } } diff --git a/test/common/services/es_delete_all_indices.ts b/test/common/services/es_delete_all_indices.ts index 3443ef23c8ed0..c0ffa44c2e2c3 100644 --- a/test/common/services/es_delete_all_indices.ts +++ b/test/common/services/es_delete_all_indices.ts @@ -37,6 +37,7 @@ export function EsDeleteAllIndicesProvider({ getService }: FtrProviderContext) { }, { ignore: [404], + meta: true, } ); const indices = Object.keys(resp.body) as string[]; diff --git a/test/common/services/saved_object_info/saved_object_info.ts b/test/common/services/saved_object_info/saved_object_info.ts index 61472ea98d879..3442efcc98438 100644 --- a/test/common/services/saved_object_info/saved_object_info.ts +++ b/test/common/services/saved_object_info/saved_object_info.ts @@ -6,7 +6,7 @@ * Side Public License, v 1. */ -import { Client } from '@elastic/elasticsearch'; +import { Client, HttpConnection } from '@elastic/elasticsearch'; import url from 'url'; import { Either, fromNullable, chain, getOrElse, toError } from 'fp-ts/Either'; import { flow, pipe } from 'fp-ts/function'; @@ -37,7 +37,7 @@ export const types = await pipe( TE.tryCatch( async () => { - const { body } = await new Client({ node }).search({ + const body = await new Client({ node, Connection: HttpConnection }).search({ index, size: 0, body: query, diff --git a/test/functional/apps/management/_field_formatter.ts b/test/functional/apps/management/_field_formatter.ts index 2377e714418ee..838d20ccdfb50 100644 --- a/test/functional/apps/management/_field_formatter.ts +++ b/test/functional/apps/management/_field_formatter.ts @@ -423,7 +423,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { let testDocumentId: string; before(async () => { - if ((await es.indices.exists({ index: indexTitle })).body) { + if (await es.indices.exists({ index: indexTitle })) { await es.indices.delete({ index: indexTitle }); } @@ -447,7 +447,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }, {} as Record), refresh: 'wait_for', }); - testDocumentId = docResult.body._id; + testDocumentId = docResult._id; const indexPatternResult = await indexPatterns.create( { title: indexTitle }, diff --git a/test/functional/apps/management/_handle_version_conflict.js b/test/functional/apps/management/_handle_version_conflict.js index 89426805bd503..a04c5d34b2d35 100644 --- a/test/functional/apps/management/_handle_version_conflict.js +++ b/test/functional/apps/management/_handle_version_conflict.js @@ -45,13 +45,16 @@ export default function ({ getService, getPageObjects }) { await PageObjects.settings.clickAddScriptedField(); await PageObjects.settings.setScriptedFieldName(scriptedFiledName); await PageObjects.settings.setScriptedFieldScript(`doc['bytes'].value`); - const response = await es.update({ - index: '.kibana', - id: 'index-pattern:logstash-*', - body: { - doc: { 'index-pattern': { fieldFormatMap: '{"geo.src":{"id":"number"}}' } }, + const response = await es.update( + { + index: '.kibana', + id: 'index-pattern:logstash-*', + body: { + doc: { 'index-pattern': { fieldFormatMap: '{"geo.src":{"id":"number"}}' } }, + }, }, - }); + { meta: true } + ); log.debug(JSON.stringify(response)); expect(response.body.result).to.be('updated'); await PageObjects.settings.setFieldFormat('url'); @@ -76,13 +79,16 @@ export default function ({ getService, getPageObjects }) { ).findAllByCssSelector('[data-test-subj="toggle"]') )[0].click(); await PageObjects.settings.setFieldFormat('url'); - const response = await es.update({ - index: '.kibana', - id: 'index-pattern:logstash-*', - body: { - doc: { 'index-pattern': { fieldFormatMap: '{"geo.dest":{"id":"number"}}' } }, + const response = await es.update( + { + index: '.kibana', + id: 'index-pattern:logstash-*', + body: { + doc: { 'index-pattern': { fieldFormatMap: '{"geo.dest":{"id":"number"}}' } }, + }, }, - }); + { meta: true } + ); log.debug(JSON.stringify(response)); expect(response.body.result).to.be('updated'); await PageObjects.settings.controlChangeSave(); diff --git a/test/interactive_setup_api_integration/tests/enrollment_flow.ts b/test/interactive_setup_api_integration/tests/enrollment_flow.ts index 9f61529cc3439..53454207b73ed 100644 --- a/test/interactive_setup_api_integration/tests/enrollment_flow.ts +++ b/test/interactive_setup_api_integration/tests/enrollment_flow.ts @@ -38,9 +38,7 @@ export default function (context: FtrProviderContext) { let enrollmentAPIKey: string; beforeEach(async () => { const apiResponse = await es.security.createApiKey({ body: { name: 'enrollment_api_key' } }); - enrollmentAPIKey = Buffer.from(`${apiResponse.body.id}:${apiResponse.body.api_key}`).toString( - 'base64' - ); + enrollmentAPIKey = Buffer.from(`${apiResponse.id}:${apiResponse.api_key}`).toString('base64'); }); afterEach(async () => { diff --git a/x-pack/plugins/actions/server/actions_client.ts b/x-pack/plugins/actions/server/actions_client.ts index b391e50283ad1..5a5c5b302fad1 100644 --- a/x-pack/plugins/actions/server/actions_client.ts +++ b/x-pack/plugins/actions/server/actions_client.ts @@ -6,7 +6,7 @@ */ import Boom from '@hapi/boom'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { UsageCounter } from 'src/plugins/usage_collection/server'; import { i18n } from '@kbn/i18n'; diff --git a/x-pack/plugins/actions/server/builtin_action_types/es_index.test.ts b/x-pack/plugins/actions/server/builtin_action_types/es_index.test.ts index 738fa236f89c0..50a1deba5af20 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/es_index.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/es_index.test.ts @@ -8,7 +8,7 @@ jest.mock('./lib/send_email', () => ({ sendEmail: jest.fn(), })); - +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { validateConfig, validateParams } from '../lib'; import { createActionTypeRegistry } from './index.test'; import { actionsMock } from '../mocks'; @@ -216,10 +216,12 @@ describe('execute()', () => { }); const calls = scopedClusterClient.bulk.mock.calls; - const timeValue = ((calls[0][0]?.body as unknown[])[1] as Record) - .field_to_use_for_time; + const timeValue = ( + ((calls[0][0] as estypes.BulkRequest)?.body as unknown[])[1] as Record + ).field_to_use_for_time; expect(timeValue).toBeInstanceOf(Date); - delete ((calls[0][0]?.body as unknown[])[1] as Record).field_to_use_for_time; + delete (((calls[0][0] as estypes.BulkRequest)?.body as unknown[])[1] as Record) + .field_to_use_for_time; expect(calls).toMatchInlineSnapshot(` Array [ Array [ diff --git a/x-pack/plugins/actions/server/cleanup_failed_executions/cleanup_tasks.test.ts b/x-pack/plugins/actions/server/cleanup_failed_executions/cleanup_tasks.test.ts index 451e12b9cf29a..b80a8d092118a 100644 --- a/x-pack/plugins/actions/server/cleanup_failed_executions/cleanup_tasks.test.ts +++ b/x-pack/plugins/actions/server/cleanup_failed_executions/cleanup_tasks.test.ts @@ -10,7 +10,8 @@ import { loggingSystemMock, elasticsearchServiceMock } from '../../../../../src/ import { spacesMock } from '../../../spaces/server/mocks'; import { CleanupTasksOpts, cleanupTasks } from './cleanup_tasks'; import { TaskInstance } from '../../../task_manager/server'; -import { ApiResponse, estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { TransportResult } from '@elastic/elasticsearch'; describe('cleanupTasks', () => { const logger = loggingSystemMock.create().get(); @@ -71,7 +72,7 @@ describe('cleanupTasks', () => { it('should delete action_task_params and task objects', async () => { esClient.bulk.mockResolvedValue({ body: { items: [], errors: false, took: 1 }, - } as unknown as ApiResponse); + } as unknown as TransportResult); const result = await cleanupTasks({ ...cleanupTasksOpts, tasks: [taskSO], @@ -106,7 +107,7 @@ describe('cleanupTasks', () => { errors: true, took: 1, }, - } as unknown as ApiResponse); + } as unknown as TransportResult); const result = await cleanupTasks({ ...cleanupTasksOpts, tasks: [taskSO], diff --git a/x-pack/plugins/actions/server/cleanup_failed_executions/lib/bulk_delete.ts b/x-pack/plugins/actions/server/cleanup_failed_executions/lib/bulk_delete.ts index 2e0037d01943d..5bbb48a3d520d 100644 --- a/x-pack/plugins/actions/server/cleanup_failed_executions/lib/bulk_delete.ts +++ b/x-pack/plugins/actions/server/cleanup_failed_executions/lib/bulk_delete.ts @@ -6,13 +6,14 @@ */ import { ElasticsearchClient } from 'kibana/server'; -import { ApiResponse, estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { TransportResult } from '@elastic/elasticsearch'; export async function bulkDelete( esClient: ElasticsearchClient, index: string, ids: string[] -): Promise | undefined> { +): Promise | undefined> { if (ids.length === 0) { return; } diff --git a/x-pack/plugins/actions/server/cleanup_failed_executions/lib/extract_bulk_response_delete_failures.ts b/x-pack/plugins/actions/server/cleanup_failed_executions/lib/extract_bulk_response_delete_failures.ts index 90418c9763a4d..c3b4866f199d3 100644 --- a/x-pack/plugins/actions/server/cleanup_failed_executions/lib/extract_bulk_response_delete_failures.ts +++ b/x-pack/plugins/actions/server/cleanup_failed_executions/lib/extract_bulk_response_delete_failures.ts @@ -5,12 +5,13 @@ * 2.0. */ -import { ApiResponse, estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { TransportResult } from '@elastic/elasticsearch'; -type ResponseFailures = Array>; +type ResponseFailures = Array>; export function extractBulkResponseDeleteFailures( - response: ApiResponse + response: TransportResult ): ResponseFailures { const result: ResponseFailures = []; for (const item of response.body.items) { diff --git a/x-pack/plugins/actions/server/usage/actions_telemetry.ts b/x-pack/plugins/actions/server/usage/actions_telemetry.ts index 803a2122fe7f8..ab72352d460e3 100644 --- a/x-pack/plugins/actions/server/usage/actions_telemetry.ts +++ b/x-pack/plugins/actions/server/usage/actions_telemetry.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; import { ElasticsearchClient } from 'kibana/server'; import { AlertHistoryEsIndexConnectorId } from '../../common'; import { ActionResult, PreConfiguredAction } from '../types'; diff --git a/x-pack/plugins/alerting/server/authorization/alerting_authorization_kuery.ts b/x-pack/plugins/alerting/server/authorization/alerting_authorization_kuery.ts index 300634af84585..d718373446b60 100644 --- a/x-pack/plugins/alerting/server/authorization/alerting_authorization_kuery.ts +++ b/x-pack/plugins/alerting/server/authorization/alerting_authorization_kuery.ts @@ -8,7 +8,7 @@ import { remove } from 'lodash'; import { EsQueryConfig, nodeBuilder, toElasticsearchQuery, KueryNode } from '@kbn/es-query'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { RegistryAlertTypeWithAuth } from './alerting_authorization'; export enum AlertingAuthorizationFilterType { diff --git a/x-pack/plugins/alerting/server/lib/errors/es_error_parser.ts b/x-pack/plugins/alerting/server/lib/errors/es_error_parser.ts index 3573da3a52eea..f26fa22f8d730 100644 --- a/x-pack/plugins/alerting/server/lib/errors/es_error_parser.ts +++ b/x-pack/plugins/alerting/server/lib/errors/es_error_parser.ts @@ -5,7 +5,6 @@ * 2.0. */ -// import { ResponseError } from '@elastic/elasticsearch/lib/errors'; import { ElasticsearchError, ElasticsearchErrorCausedByObject } from './types'; const getEsCause = ( diff --git a/x-pack/plugins/alerting/server/rules_client/rules_client.ts b/x-pack/plugins/alerting/server/rules_client/rules_client.ts index bde0c35028582..e6f20049bc470 100644 --- a/x-pack/plugins/alerting/server/rules_client/rules_client.ts +++ b/x-pack/plugins/alerting/server/rules_client/rules_client.ts @@ -9,7 +9,7 @@ import Semver from 'semver'; import Boom from '@hapi/boom'; import { omit, isEqual, map, uniq, pick, truncate, trim, mapValues } from 'lodash'; import { i18n } from '@kbn/i18n'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Logger, SavedObjectsClientContract, diff --git a/x-pack/plugins/apm/common/search_strategies/field_stats_types.ts b/x-pack/plugins/apm/common/search_strategies/field_stats_types.ts index d96bb4408f0e8..d63dd7f8d58a1 100644 --- a/x-pack/plugins/apm/common/search_strategies/field_stats_types.ts +++ b/x-pack/plugins/apm/common/search_strategies/field_stats_types.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { SearchStrategyParams } from './types'; export interface FieldStatsCommonRequestParams extends SearchStrategyParams { diff --git a/x-pack/plugins/apm/common/utils/environment_query.ts b/x-pack/plugins/apm/common/utils/environment_query.ts index 7b35f90d87691..e2f9a722e3de2 100644 --- a/x-pack/plugins/apm/common/utils/environment_query.ts +++ b/x-pack/plugins/apm/common/utils/environment_query.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { SERVICE_ENVIRONMENT } from '../elasticsearch_fieldnames'; import { ENVIRONMENT_ALL, diff --git a/x-pack/plugins/apm/public/components/shared/kuery_bar/index.tsx b/x-pack/plugins/apm/public/components/shared/kuery_bar/index.tsx index b3a972bcd59e3..4dc24567259e6 100644 --- a/x-pack/plugins/apm/public/components/shared/kuery_bar/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/kuery_bar/index.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { i18n } from '@kbn/i18n'; import { uniqueId } from 'lodash'; import React, { useState } from 'react'; diff --git a/x-pack/plugins/apm/public/components/shared/search_bar.tsx b/x-pack/plugins/apm/public/components/shared/search_bar.tsx index 5f5a25393c7d1..1a6e9a803d735 100644 --- a/x-pack/plugins/apm/public/components/shared/search_bar.tsx +++ b/x-pack/plugins/apm/public/components/shared/search_bar.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { EuiFlexGroup, EuiFlexGroupProps, diff --git a/x-pack/plugins/apm/scripts/aggregate-latency-metrics/index.ts b/x-pack/plugins/apm/scripts/aggregate-latency-metrics/index.ts index 3d0f0bd3c3c72..d5cc9a63dbfcd 100644 --- a/x-pack/plugins/apm/scripts/aggregate-latency-metrics/index.ts +++ b/x-pack/plugins/apm/scripts/aggregate-latency-metrics/index.ts @@ -135,11 +135,9 @@ export async function aggregateLatencyMetrics() { destOptions = parseIndexUrl(dest); destClient = getEsClient({ node: destOptions.node }); - const mappings = ( - await sourceClient.indices.getMapping({ - index: sourceOptions.index, - }) - ).body; + const mappings = await sourceClient.indices.getMapping({ + index: sourceOptions.index, + }); const lastMapping = mappings[Object.keys(mappings)[0]]; diff --git a/x-pack/plugins/apm/scripts/create-functional-tests-archive/index.ts b/x-pack/plugins/apm/scripts/create-functional-tests-archive/index.ts index b9102efee50dc..559f746ab50f2 100644 --- a/x-pack/plugins/apm/scripts/create-functional-tests-archive/index.ts +++ b/x-pack/plugins/apm/scripts/create-functional-tests-archive/index.ts @@ -10,7 +10,7 @@ import { execSync } from 'child_process'; import moment from 'moment'; import path from 'path'; import fs from 'fs'; -import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { getEsClient } from '../shared/get_es_client'; import { parseIndexUrl } from '../shared/parse_index_url'; @@ -144,6 +144,7 @@ async function run() { // profile const indicesWithDocs = response.body.aggregations?.index.buckets.map( + // @ts-expect-error bucket has any type (bucket) => bucket.key as string ) ?? []; diff --git a/x-pack/plugins/apm/scripts/shared/create-or-update-index.ts b/x-pack/plugins/apm/scripts/shared/create-or-update-index.ts index 8bab4df9006f5..39f398354422f 100644 --- a/x-pack/plugins/apm/scripts/shared/create-or-update-index.ts +++ b/x-pack/plugins/apm/scripts/shared/create-or-update-index.ts @@ -36,11 +36,9 @@ export async function createOrUpdateIndex({ delete settings?.index?.number_of_shards; delete settings?.index?.sort; - const indexExists = ( - await client.indices.exists({ - index: indexName, - }) - ).body as unknown; + const indexExists = await client.indices.exists({ + index: indexName, + }); if (!indexExists) { await client.indices.create({ diff --git a/x-pack/plugins/apm/scripts/shared/get_es_client.ts b/x-pack/plugins/apm/scripts/shared/get_es_client.ts index 42833d28adcb2..3ee5642852c06 100644 --- a/x-pack/plugins/apm/scripts/shared/get_es_client.ts +++ b/x-pack/plugins/apm/scripts/shared/get_es_client.ts @@ -6,7 +6,7 @@ */ import { Client } from '@elastic/elasticsearch'; -import { ApiKeyAuth, BasicAuth } from '@elastic/elasticsearch/lib/pool'; +import type { ClientOptions } from '@elastic/elasticsearch/lib/client'; import { ESSearchResponse, ESSearchRequest, @@ -19,11 +19,13 @@ export function getEsClient({ auth, }: { node: string; - auth?: BasicAuth | ApiKeyAuth; -}) { + auth?: ClientOptions['auth']; + // Should be refactored + // The inferred type of 'getEsClient' references an inaccessible 'unique symbol' type. A type annotation is necessary. +}): any { const client = new Client({ node, - ssl: { + tls: { rejectUnauthorized: false, }, requestTimeout: 120000, @@ -36,14 +38,11 @@ export function getEsClient({ TDocument = unknown, TSearchRequest extends ESSearchRequest = ESSearchRequest >(request: TSearchRequest) { - const response = await originalSearch(request); + const response = await originalSearch(request); return { ...response, - body: response.body as unknown as ESSearchResponse< - TDocument, - TSearchRequest - >, + body: response as unknown as ESSearchResponse, }; } diff --git a/x-pack/plugins/apm/scripts/upload-telemetry-data/index.ts b/x-pack/plugins/apm/scripts/upload-telemetry-data/index.ts index 6397c79ce4ffb..990376ca3e6ba 100644 --- a/x-pack/plugins/apm/scripts/upload-telemetry-data/index.ts +++ b/x-pack/plugins/apm/scripts/upload-telemetry-data/index.ts @@ -17,7 +17,6 @@ import { argv } from 'yargs'; import { Logger } from 'kibana/server'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { CollectTelemetryParams } from '../../server/lib/apm_telemetry/collect_data_telemetry'; -import { unwrapEsResponse } from '../../../observability/common/utils/unwrap_es_response'; import { downloadTelemetryTemplate } from '../shared/download-telemetry-template'; import { mergeApmTelemetryMapping } from '../../common/apm_telemetry'; import { generateSampleDocuments } from './generate-sample-documents'; @@ -87,18 +86,13 @@ async function uploadData() { apmAgentConfigurationIndex: '.apm-agent-configuration', }, search: (body) => { - return unwrapEsResponse(client.search(body)) as Promise; + return client.search(body) as Promise; }, indicesStats: (body) => { - return unwrapEsResponse(client.indices.stats(body)); + return client.indices.stats(body); }, transportRequest: ((params) => { - return unwrapEsResponse( - client.transport.request({ - method: params.method, - path: params.path, - }) - ); + return; }) as CollectTelemetryParams['transportRequest'], }, }); diff --git a/x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_duration.ts b/x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_duration.ts index 1359f4b925973..8767b5a60d9b2 100644 --- a/x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_duration.ts +++ b/x-pack/plugins/apm/server/lib/alerts/chart_preview/get_transaction_duration.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { rangeQuery } from '../../../../../observability/server'; import { SERVICE_NAME, diff --git a/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_alert_type.ts b/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_alert_type.ts index 698bbcdbdb84a..3500dc8fee921 100644 --- a/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_alert_type.ts +++ b/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_alert_type.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { schema } from '@kbn/config-schema'; import type { ALERT_EVALUATION_THRESHOLD as ALERT_EVALUATION_THRESHOLD_TYPED, diff --git a/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_anomaly_alert_type.ts b/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_anomaly_alert_type.ts index 08203646d9004..2809d7feadb37 100644 --- a/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_anomaly_alert_type.ts +++ b/x-pack/plugins/apm/server/lib/alerts/register_transaction_duration_anomaly_alert_type.ts @@ -8,7 +8,7 @@ import { schema } from '@kbn/config-schema'; import { compact } from 'lodash'; import { ESSearchResponse } from 'src/core/types/elasticsearch'; -import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ALERT_EVALUATION_THRESHOLD as ALERT_EVALUATION_THRESHOLD_TYPED, ALERT_EVALUATION_VALUE as ALERT_EVALUATION_VALUE_TYPED, diff --git a/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/index.ts b/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/index.ts index 22a2090dbb6cd..9b5820767690f 100644 --- a/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/index.ts +++ b/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/index.ts @@ -7,7 +7,7 @@ import { merge } from 'lodash'; import { Logger } from 'kibana/server'; -import { IndicesStats } from '@elastic/elasticsearch/api/requestParams'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ESSearchRequest, ESSearchResponse, @@ -22,7 +22,7 @@ type TelemetryTaskExecutor = (params: { params: TSearchRequest ): Promise>; indicesStats( - params: IndicesStats + params: estypes.IndicesStatsRequest // promise returned by client has an abort property // so we cannot use its ReturnType ): Promise<{ diff --git a/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/tasks.ts b/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/tasks.ts index 8764223ad1ebb..f06226c864a98 100644 --- a/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/tasks.ts +++ b/x-pack/plugins/apm/server/lib/apm_telemetry/collect_data_telemetry/tasks.ts @@ -5,7 +5,7 @@ * 2.0. */ import { flatten, merge, sortBy, sum, pickBy } from 'lodash'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { asMutableArray } from '../../../../common/utils/as_mutable_array'; import { ProcessorEvent } from '../../../../common/processor_event'; import { TelemetryTask } from '.'; @@ -599,7 +599,7 @@ export const tasks: TelemetryTask[] = [ executor: async ({ search, indices }) => { const response = await search({ index: [indices.transaction, indices.span, indices.error], - terminateAfter: 1, + terminate_after: 1, body: { query: { exists: { diff --git a/x-pack/plugins/apm/server/lib/connections/exclude_rum_exit_spans_query.ts b/x-pack/plugins/apm/server/lib/connections/exclude_rum_exit_spans_query.ts index 89a510fe508c6..4e15500a59466 100644 --- a/x-pack/plugins/apm/server/lib/connections/exclude_rum_exit_spans_query.ts +++ b/x-pack/plugins/apm/server/lib/connections/exclude_rum_exit_spans_query.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { AGENT_NAME } from '../../../common/elasticsearch_fieldnames'; import { RUM_AGENT_NAMES } from '../../../common/agent_name'; diff --git a/x-pack/plugins/apm/server/lib/connections/get_connection_stats/get_destination_map.ts b/x-pack/plugins/apm/server/lib/connections/get_connection_stats/get_destination_map.ts index be6518708eddb..2eb0ed3db02bd 100644 --- a/x-pack/plugins/apm/server/lib/connections/get_connection_stats/get_destination_map.ts +++ b/x-pack/plugins/apm/server/lib/connections/get_connection_stats/get_destination_map.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import objectHash from 'object-hash'; import { getOffsetInMs } from '../../../../common/utils/get_offset_in_ms'; import { ENVIRONMENT_NOT_DEFINED } from '../../../../common/environment_filter_values'; diff --git a/x-pack/plugins/apm/server/lib/connections/get_connection_stats/get_stats.ts b/x-pack/plugins/apm/server/lib/connections/get_connection_stats/get_stats.ts index 4f48f3388c017..ff46db949d122 100644 --- a/x-pack/plugins/apm/server/lib/connections/get_connection_stats/get_stats.ts +++ b/x-pack/plugins/apm/server/lib/connections/get_connection_stats/get_stats.ts @@ -7,7 +7,7 @@ import { sum } from 'lodash'; import objectHash from 'object-hash'; -import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { AgentName } from '../../../../typings/es_schemas/ui/fields/agent'; import { getOffsetInMs } from '../../../../common/utils/get_offset_in_ms'; import { ENVIRONMENT_NOT_DEFINED } from '../../../../common/environment_filter_values'; diff --git a/x-pack/plugins/apm/server/lib/connections/get_connection_stats/index.ts b/x-pack/plugins/apm/server/lib/connections/get_connection_stats/index.ts index 03b94defda6dd..5c1c628762edb 100644 --- a/x-pack/plugins/apm/server/lib/connections/get_connection_stats/index.ts +++ b/x-pack/plugins/apm/server/lib/connections/get_connection_stats/index.ts @@ -7,7 +7,7 @@ import { ValuesType } from 'utility-types'; import { merge } from 'lodash'; -import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { joinByKey } from '../../../../common/utils/join_by_key'; import { Setup } from '../../helpers/setup_request'; import { getStats } from './get_stats'; diff --git a/x-pack/plugins/apm/server/lib/event_metadata/get_event_metadata.ts b/x-pack/plugins/apm/server/lib/event_metadata/get_event_metadata.ts index 97e2e1356363f..b9e0dee52a42e 100644 --- a/x-pack/plugins/apm/server/lib/event_metadata/get_event_metadata.ts +++ b/x-pack/plugins/apm/server/lib/event_metadata/get_event_metadata.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ERROR_ID, SPAN_ID, diff --git a/x-pack/plugins/apm/server/lib/helpers/create_es_client/cancel_es_request_on_abort.ts b/x-pack/plugins/apm/server/lib/helpers/create_es_client/cancel_es_request_on_abort.ts index a14564fc8e268..41dc33dfa193f 100644 --- a/x-pack/plugins/apm/server/lib/helpers/create_es_client/cancel_es_request_on_abort.ts +++ b/x-pack/plugins/apm/server/lib/helpers/create_es_client/cancel_es_request_on_abort.ts @@ -5,24 +5,18 @@ * 2.0. */ -import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; -import { KibanaRequest } from 'src/core/server'; +import type { KibanaRequest } from 'src/core/server'; -export function cancelEsRequestOnAbort>( +export function cancelEsRequestOnAbort>( promise: T, - request: KibanaRequest + request: KibanaRequest, + controller: AbortController ) { const subscription = request.events.aborted$.subscribe(() => { - promise.abort(); + controller.abort(); }); - // using .catch() here means unsubscribe will be called - // after it has thrown an error, so we use .then(onSuccess, onFailure) - // syntax - promise.then( - () => subscription.unsubscribe(), - () => subscription.unsubscribe() - ); + promise.finally(() => subscription.unsubscribe()); return promise; } diff --git a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.test.ts b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.test.ts index 8f03aceef3348..e9280ba3e5976 100644 --- a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.test.ts +++ b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.test.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import { setTimeout as setTimeoutPromise } from 'timers/promises'; import { contextServiceMock, executionContextServiceMock, @@ -34,17 +34,19 @@ describe('createApmEventClient', () => { }); const router = createRouter('/'); - const abort = jest.fn(); + let abortSignal: AbortSignal | undefined; router.get( { path: '/', validate: false }, async (context, request, res) => { const eventClient = createApmEventClient({ esClient: { - search: () => { - return Object.assign( - new Promise((resolve) => setTimeout(resolve, 3000)), - { abort } - ); + search: async ( + params: any, + { signal }: { signal: AbortSignal } + ) => { + abortSignal = signal; + await setTimeoutPromise(3_000); + return {}; }, } as any, debug: false, @@ -67,6 +69,8 @@ describe('createApmEventClient', () => { await server.start(); + expect(abortSignal?.aborted).toBeFalsy(); + const incomingRequest = supertest(innerServer.listener) .get('/') // end required to send request @@ -83,6 +87,6 @@ describe('createApmEventClient', () => { }, 100); }); - expect(abort).toHaveBeenCalled(); + expect(abortSignal?.aborted).toBe(true); }); }); diff --git a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts index b2b2a0b869c80..26b00b075a5c8 100644 --- a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts +++ b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_apm_event_client/index.ts @@ -8,7 +8,7 @@ import type { TermsEnumRequest, TermsEnumResponse, -} from '@elastic/elasticsearch/api/types'; +} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ValuesType } from 'utility-types'; import { withApmSpan } from '../../../../utils/with_apm_span'; import { Profile } from '../../../../../typings/es_schemas/ui/profile'; @@ -110,9 +110,14 @@ export function createApmEventClient({ return callAsyncWithDebug({ cb: () => { - const searchPromise = withApmSpan(operationName, () => - cancelEsRequestOnAbort(esClient.search(searchParams), request) - ); + const searchPromise = withApmSpan(operationName, () => { + const controller = new AbortController(); + return cancelEsRequestOnAbort( + esClient.search(searchParams, { signal: controller.signal }), + request, + controller + ); + }); return unwrapEsResponse(searchPromise); }, @@ -143,15 +148,20 @@ export function createApmEventClient({ return callAsyncWithDebug({ cb: () => { const { apm, ...rest } = params; - const termsEnumPromise = withApmSpan(operationName, () => - cancelEsRequestOnAbort( - esClient.termsEnum({ - index: Array.isArray(index) ? index.join(',') : index, - ...rest, - }), - request - ) - ); + const termsEnumPromise = withApmSpan(operationName, () => { + const controller = new AbortController(); + return cancelEsRequestOnAbort( + esClient.termsEnum( + { + index: Array.isArray(index) ? index.join(',') : index, + ...rest, + }, + { signal: controller.signal } + ), + request, + controller + ); + }); return unwrapEsResponse(termsEnumPromise); }, diff --git a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_internal_es_client/index.ts b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_internal_es_client/index.ts index 34801cdf94750..621f65f74d9f4 100644 --- a/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_internal_es_client/index.ts +++ b/x-pack/plugins/apm/server/lib/helpers/create_es_client/create_internal_es_client/index.ts @@ -5,8 +5,7 @@ * 2.0. */ -import { TransportRequestPromise } from '@elastic/elasticsearch/lib/Transport'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { unwrapEsResponse } from '../../../../../../observability/server'; import { APMRouteHandlerResources } from '../../../../routes/typings'; import { @@ -39,12 +38,17 @@ export function createInternalESClient({ params, }: { requestType: string; - cb: () => TransportRequestPromise; + cb: (signal: AbortSignal) => Promise; params: Record; } ) { return callAsyncWithDebug({ - cb: () => unwrapEsResponse(cancelEsRequestOnAbort(cb(), request)), + cb: () => { + const controller = new AbortController(); + return unwrapEsResponse( + cancelEsRequestOnAbort(cb(controller.signal), request, controller) + ); + }, getDebugMessage: () => ({ title: getDebugTitle(request), body: getDebugBody({ params, requestType, operationName }), @@ -68,14 +72,14 @@ export function createInternalESClient({ ): Promise> => { return callEs(operationName, { requestType: 'search', - cb: () => asInternalUser.search(params), + cb: (signal) => asInternalUser.search(params, { signal }), params, }); }, index: (operationName: string, params: APMIndexDocumentParams) => { return callEs(operationName, { requestType: 'index', - cb: () => asInternalUser.index(params), + cb: (signal) => asInternalUser.index(params, { signal }), params, }); }, @@ -85,7 +89,7 @@ export function createInternalESClient({ ): Promise<{ result: string }> => { return callEs(operationName, { requestType: 'delete', - cb: () => asInternalUser.delete(params), + cb: (signal) => asInternalUser.delete(params, { signal }), params, }); }, @@ -95,7 +99,7 @@ export function createInternalESClient({ ) => { return callEs(operationName, { requestType: 'indices.create', - cb: () => asInternalUser.indices.create(params), + cb: (signal) => asInternalUser.indices.create(params, { signal }), params, }); }, diff --git a/x-pack/plugins/apm/server/lib/helpers/setup_request.test.ts b/x-pack/plugins/apm/server/lib/helpers/setup_request.test.ts index 5bd883c6381d3..52e9e5a8ea74a 100644 --- a/x-pack/plugins/apm/server/lib/helpers/setup_request.test.ts +++ b/x-pack/plugins/apm/server/lib/helpers/setup_request.test.ts @@ -117,23 +117,28 @@ describe('setupRequest', () => { expect( mockResources.context.core.elasticsearch.client.asCurrentUser.search - ).toHaveBeenCalledWith({ - index: ['apm-*'], - body: { - foo: 'bar', - query: { - bool: { - filter: [ - { terms: { 'processor.event': ['transaction'] } }, - { range: { 'observer.version_major': { gte: 7 } } }, - ], + ).toHaveBeenCalledWith( + { + index: ['apm-*'], + body: { + foo: 'bar', + query: { + bool: { + filter: [ + { terms: { 'processor.event': ['transaction'] } }, + { range: { 'observer.version_major': { gte: 7 } } }, + ], + }, }, }, + ignore_unavailable: true, + ignore_throttled: true, + preference: 'any', }, - ignore_unavailable: true, - ignore_throttled: true, - preference: 'any', - }); + { + signal: expect.any(Object), + } + ); }); it('calls callWithInternalUser', async () => { @@ -145,12 +150,17 @@ describe('setupRequest', () => { } as any); expect( mockResources.context.core.elasticsearch.client.asInternalUser.search - ).toHaveBeenCalledWith({ - index: ['apm-*'], - body: { - foo: 'bar', + ).toHaveBeenCalledWith( + { + index: ['apm-*'], + body: { + foo: 'bar', + }, }, - }); + { + signal: expect.any(Object), + } + ); }); }); diff --git a/x-pack/plugins/apm/server/lib/helpers/transactions/__snapshots__/get_is_using_transaction_events.test.ts.snap b/x-pack/plugins/apm/server/lib/helpers/transactions/__snapshots__/get_is_using_transaction_events.test.ts.snap index 2b629e9849d0d..56d735b5df115 100644 --- a/x-pack/plugins/apm/server/lib/helpers/transactions/__snapshots__/get_is_using_transaction_events.test.ts.snap +++ b/x-pack/plugins/apm/server/lib/helpers/transactions/__snapshots__/get_is_using_transaction_events.test.ts.snap @@ -32,7 +32,7 @@ Object { }, }, }, - "terminateAfter": 1, + "terminate_after": 1, } `; @@ -56,7 +56,7 @@ Object { }, }, }, - "terminateAfter": 1, + "terminate_after": 1, } `; @@ -83,7 +83,7 @@ Array [ }, }, }, - "terminateAfter": 1, + "terminate_after": 1, }, ], Array [ @@ -101,7 +101,7 @@ Array [ }, }, }, - "terminateAfter": 1, + "terminate_after": 1, }, ], ] diff --git a/x-pack/plugins/apm/server/lib/helpers/transactions/get_is_using_transaction_events.ts b/x-pack/plugins/apm/server/lib/helpers/transactions/get_is_using_transaction_events.ts index 66e9697ab7c91..75be545a7e427 100644 --- a/x-pack/plugins/apm/server/lib/helpers/transactions/get_is_using_transaction_events.ts +++ b/x-pack/plugins/apm/server/lib/helpers/transactions/get_is_using_transaction_events.ts @@ -83,7 +83,7 @@ async function getHasTransactions({ }, }, }, - terminateAfter: 1, + terminate_after: 1, }); return response.hits.total.value > 0; diff --git a/x-pack/plugins/apm/server/lib/helpers/transactions/index.ts b/x-pack/plugins/apm/server/lib/helpers/transactions/index.ts index f16e03ddc3ea4..473d34cd5b6fc 100644 --- a/x-pack/plugins/apm/server/lib/helpers/transactions/index.ts +++ b/x-pack/plugins/apm/server/lib/helpers/transactions/index.ts @@ -43,7 +43,7 @@ export async function getHasAggregatedTransactions({ }, }, }, - terminateAfter: 1, + terminate_after: 1, } ); diff --git a/x-pack/plugins/apm/server/lib/latency/get_overall_latency_distribution.ts b/x-pack/plugins/apm/server/lib/latency/get_overall_latency_distribution.ts index 787304c3f8dcd..ad1914d921211 100644 --- a/x-pack/plugins/apm/server/lib/latency/get_overall_latency_distribution.ts +++ b/x-pack/plugins/apm/server/lib/latency/get_overall_latency_distribution.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ProcessorEvent } from '../../../common/processor_event'; diff --git a/x-pack/plugins/apm/server/lib/latency/get_percentile_threshold_value.ts b/x-pack/plugins/apm/server/lib/latency/get_percentile_threshold_value.ts index 0d417a370e0b6..996e039841b88 100644 --- a/x-pack/plugins/apm/server/lib/latency/get_percentile_threshold_value.ts +++ b/x-pack/plugins/apm/server/lib/latency/get_percentile_threshold_value.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ProcessorEvent } from '../../../common/processor_event'; diff --git a/x-pack/plugins/apm/server/lib/observability_overview/has_data.ts b/x-pack/plugins/apm/server/lib/observability_overview/has_data.ts index 3b6993695f3de..f09b67ec98dfb 100644 --- a/x-pack/plugins/apm/server/lib/observability_overview/has_data.ts +++ b/x-pack/plugins/apm/server/lib/observability_overview/has_data.ts @@ -19,7 +19,7 @@ export async function getHasData({ setup }: { setup: Setup }) { ProcessorEvent.metric, ], }, - terminateAfter: 1, + terminate_after: 1, body: { size: 0, }, diff --git a/x-pack/plugins/apm/server/lib/search_strategies/queries/field_stats/get_boolean_field_stats.ts b/x-pack/plugins/apm/server/lib/search_strategies/queries/field_stats/get_boolean_field_stats.ts index 551ecfe3cd4ea..da5493376426c 100644 --- a/x-pack/plugins/apm/server/lib/search_strategies/queries/field_stats/get_boolean_field_stats.ts +++ b/x-pack/plugins/apm/server/lib/search_strategies/queries/field_stats/get_boolean_field_stats.ts @@ -6,8 +6,8 @@ */ import { ElasticsearchClient } from 'kibana/server'; -import { SearchRequest } from '@elastic/elasticsearch/api/types'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; + import { buildSamplerAggregation } from '../../utils/field_stats_utils'; import { FieldValuePair } from '../../../../../common/search_strategies/types'; import { @@ -22,7 +22,7 @@ export const getBooleanFieldStatsRequest = ( params: FieldStatsCommonRequestParams, fieldName: string, termFilters?: FieldValuePair[] -): SearchRequest => { +): estypes.SearchRequest => { const query = getQueryWithParams({ params, termFilters }); const { index, samplerShardSize } = params; diff --git a/x-pack/plugins/apm/server/lib/search_strategies/queries/field_stats/get_field_stats.test.ts b/x-pack/plugins/apm/server/lib/search_strategies/queries/field_stats/get_field_stats.test.ts index d3cee1c4ca596..2775d755c9907 100644 --- a/x-pack/plugins/apm/server/lib/search_strategies/queries/field_stats/get_field_stats.test.ts +++ b/x-pack/plugins/apm/server/lib/search_strategies/queries/field_stats/get_field_stats.test.ts @@ -9,7 +9,7 @@ import { ENVIRONMENT_ALL } from '../../../../../common/environment_filter_values import { getNumericFieldStatsRequest } from './get_numeric_field_stats'; import { getKeywordFieldStatsRequest } from './get_keyword_field_stats'; import { getBooleanFieldStatsRequest } from './get_boolean_field_stats'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ElasticsearchClient } from 'kibana/server'; import { fetchFieldsStats } from './get_fields_stats'; diff --git a/x-pack/plugins/apm/server/lib/search_strategies/queries/field_stats/get_keyword_field_stats.ts b/x-pack/plugins/apm/server/lib/search_strategies/queries/field_stats/get_keyword_field_stats.ts index b15449657cba5..a9c727457d0ae 100644 --- a/x-pack/plugins/apm/server/lib/search_strategies/queries/field_stats/get_keyword_field_stats.ts +++ b/x-pack/plugins/apm/server/lib/search_strategies/queries/field_stats/get_keyword_field_stats.ts @@ -6,8 +6,7 @@ */ import { ElasticsearchClient } from 'kibana/server'; -import { SearchRequest } from '@elastic/elasticsearch/api/types'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { FieldValuePair } from '../../../../../common/search_strategies/types'; import { getQueryWithParams } from '../get_query_with_params'; import { buildSamplerAggregation } from '../../utils/field_stats_utils'; @@ -22,7 +21,7 @@ export const getKeywordFieldStatsRequest = ( params: FieldStatsCommonRequestParams, fieldName: string, termFilters?: FieldValuePair[] -): SearchRequest => { +): estypes.SearchRequest => { const query = getQueryWithParams({ params, termFilters }); const { index, samplerShardSize } = params; diff --git a/x-pack/plugins/apm/server/lib/search_strategies/queries/field_stats/get_numeric_field_stats.ts b/x-pack/plugins/apm/server/lib/search_strategies/queries/field_stats/get_numeric_field_stats.ts index bab4a1af29b65..c45d4356cfe23 100644 --- a/x-pack/plugins/apm/server/lib/search_strategies/queries/field_stats/get_numeric_field_stats.ts +++ b/x-pack/plugins/apm/server/lib/search_strategies/queries/field_stats/get_numeric_field_stats.ts @@ -6,9 +6,8 @@ */ import { ElasticsearchClient } from 'kibana/server'; -import { SearchRequest } from '@elastic/elasticsearch/api/types'; import { find, get } from 'lodash'; -import { estypes } from '@elastic/elasticsearch/index'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { NumericFieldStats, FieldStatsCommonRequestParams, @@ -80,7 +79,7 @@ export const fetchNumericFieldStats = async ( field: FieldValuePair, termFilters?: FieldValuePair[] ): Promise => { - const request: SearchRequest = getNumericFieldStatsRequest( + const request: estypes.SearchRequest = getNumericFieldStatsRequest( params, field.fieldName, termFilters diff --git a/x-pack/plugins/apm/server/lib/search_strategies/queries/get_query_with_params.ts b/x-pack/plugins/apm/server/lib/search_strategies/queries/get_query_with_params.ts index 31a98b0a6bb18..297fd68a7503f 100644 --- a/x-pack/plugins/apm/server/lib/search_strategies/queries/get_query_with_params.ts +++ b/x-pack/plugins/apm/server/lib/search_strategies/queries/get_query_with_params.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { FieldValuePair, SearchStrategyParams, diff --git a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_correlation.test.ts b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_correlation.test.ts index 40fcc17444492..6cbf97a163871 100644 --- a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_correlation.test.ts +++ b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_correlation.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ElasticsearchClient } from 'src/core/server'; import { ENVIRONMENT_ALL } from '../../../../common/environment_filter_values'; diff --git a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_correlation.ts b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_correlation.ts index 24db25f8afd89..a150d23b27113 100644 --- a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_correlation.ts +++ b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_correlation.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ElasticsearchClient } from 'src/core/server'; diff --git a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_failure_correlation.ts b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_failure_correlation.ts index 64249a0f3547e..10a098c4a3ffc 100644 --- a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_failure_correlation.ts +++ b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_failure_correlation.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ElasticsearchClient } from 'kibana/server'; import { SearchStrategyParams } from '../../../../common/search_strategies/types'; import { EVENT_OUTCOME } from '../../../../common/elasticsearch_fieldnames'; diff --git a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_field_candidates.test.ts b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_field_candidates.test.ts index bae42666e6db0..311016a1b0834 100644 --- a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_field_candidates.test.ts +++ b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_field_candidates.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ElasticsearchClient } from 'src/core/server'; import { ENVIRONMENT_ALL } from '../../../../common/environment_filter_values'; diff --git a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_field_candidates.ts b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_field_candidates.ts index 390243295c4f0..292be1b5817aa 100644 --- a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_field_candidates.ts +++ b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_field_candidates.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ElasticsearchClient } from 'src/core/server'; diff --git a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_field_value_pairs.test.ts b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_field_value_pairs.test.ts index ab7a0b4e02072..bb3aa40b328af 100644 --- a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_field_value_pairs.test.ts +++ b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_field_value_pairs.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ElasticsearchClient } from 'src/core/server'; import { ENVIRONMENT_ALL } from '../../../../common/environment_filter_values'; diff --git a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_field_value_pairs.ts b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_field_value_pairs.ts index 296abfd2d8653..39d6aea2f38bd 100644 --- a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_field_value_pairs.ts +++ b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_field_value_pairs.ts @@ -7,7 +7,7 @@ import type { ElasticsearchClient } from 'src/core/server'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { FieldValuePair, diff --git a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_fractions.test.ts b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_fractions.test.ts index 9c704ef7b489a..5c18b21fc029c 100644 --- a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_fractions.test.ts +++ b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_fractions.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ElasticsearchClient } from 'src/core/server'; import { ENVIRONMENT_ALL } from '../../../../common/environment_filter_values'; diff --git a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_fractions.ts b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_fractions.ts index ccea480052c9b..555465466498a 100644 --- a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_fractions.ts +++ b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_fractions.ts @@ -6,7 +6,7 @@ */ import { ElasticsearchClient } from 'kibana/server'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { SearchStrategyParams } from '../../../../common/search_strategies/types'; import { TRANSACTION_DURATION } from '../../../../common/elasticsearch_fieldnames'; diff --git a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_histogram.test.ts b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_histogram.test.ts index 7cc6106f671a7..3c5726ee586da 100644 --- a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_histogram.test.ts +++ b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_histogram.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ElasticsearchClient } from 'src/core/server'; import { ENVIRONMENT_ALL } from '../../../../common/environment_filter_values'; diff --git a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_histogram.ts b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_histogram.ts index 5fb7ef76fc728..4e40834acccd1 100644 --- a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_histogram.ts +++ b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_histogram.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ElasticsearchClient } from 'src/core/server'; diff --git a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_histogram_range_steps.test.ts b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_histogram_range_steps.test.ts index 41a2fa9a5039e..3a79b4375e4a5 100644 --- a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_histogram_range_steps.test.ts +++ b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_histogram_range_steps.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ElasticsearchClient } from 'src/core/server'; import { ENVIRONMENT_ALL } from '../../../../common/environment_filter_values'; diff --git a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_histogram_range_steps.ts b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_histogram_range_steps.ts index 439bb9e4b9cd6..176e7befda53b 100644 --- a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_histogram_range_steps.ts +++ b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_histogram_range_steps.ts @@ -7,7 +7,7 @@ import { scaleLog } from 'd3-scale'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ElasticsearchClient } from 'src/core/server'; diff --git a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_histograms_generator.test.ts b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_histograms_generator.test.ts index 00e8c26497eb2..27fd0dc31432d 100644 --- a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_histograms_generator.test.ts +++ b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_histograms_generator.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ElasticsearchClient } from 'src/core/server'; import { ENVIRONMENT_ALL } from '../../../../common/environment_filter_values'; diff --git a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_histograms_generator.ts b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_histograms_generator.ts index d526c63c7de34..500714ffdf0d5 100644 --- a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_histograms_generator.ts +++ b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_histograms_generator.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ElasticsearchClient } from 'src/core/server'; diff --git a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_percentiles.test.ts b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_percentiles.test.ts index 57e3e6cadb9bc..67b2f580e3f4d 100644 --- a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_percentiles.test.ts +++ b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_percentiles.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ElasticsearchClient } from 'src/core/server'; import { ENVIRONMENT_ALL } from '../../../../common/environment_filter_values'; diff --git a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_percentiles.ts b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_percentiles.ts index 70b5b70ce8912..4e1a7b2015614 100644 --- a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_percentiles.ts +++ b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_percentiles.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ElasticsearchClient } from 'src/core/server'; diff --git a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_ranges.test.ts b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_ranges.test.ts index 7d67e80ae3398..3cafc17e2681b 100644 --- a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_ranges.test.ts +++ b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_ranges.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ElasticsearchClient } from 'src/core/server'; import { ENVIRONMENT_ALL } from '../../../../common/environment_filter_values'; diff --git a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_ranges.ts b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_ranges.ts index a530c997876c4..8b359c3665eaf 100644 --- a/x-pack/plugins/apm/server/lib/search_strategies/queries/query_ranges.ts +++ b/x-pack/plugins/apm/server/lib/search_strategies/queries/query_ranges.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ElasticsearchClient } from 'src/core/server'; diff --git a/x-pack/plugins/apm/server/lib/search_strategies/search_strategy_provider.test.ts b/x-pack/plugins/apm/server/lib/search_strategies/search_strategy_provider.test.ts index 034bd2a60ad19..ccccdeab5132d 100644 --- a/x-pack/plugins/apm/server/lib/search_strategies/search_strategy_provider.test.ts +++ b/x-pack/plugins/apm/server/lib/search_strategies/search_strategy_provider.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { SearchStrategyDependencies } from 'src/plugins/data/server'; diff --git a/x-pack/plugins/apm/server/lib/search_strategies/utils/compute_expectations_and_ranges.ts b/x-pack/plugins/apm/server/lib/search_strategies/utils/compute_expectations_and_ranges.ts index 9ab9689fd6d30..1754a35280f86 100644 --- a/x-pack/plugins/apm/server/lib/search_strategies/utils/compute_expectations_and_ranges.ts +++ b/x-pack/plugins/apm/server/lib/search_strategies/utils/compute_expectations_and_ranges.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { PERCENTILES_STEP } from '../constants'; export const computeExpectationsAndRanges = ( diff --git a/x-pack/plugins/apm/server/lib/search_strategies/utils/field_stats_utils.ts b/x-pack/plugins/apm/server/lib/search_strategies/utils/field_stats_utils.ts index 2eb67ec501bab..7f98f771c50e2 100644 --- a/x-pack/plugins/apm/server/lib/search_strategies/utils/field_stats_utils.ts +++ b/x-pack/plugins/apm/server/lib/search_strategies/utils/field_stats_utils.ts @@ -5,7 +5,8 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; + /* * Contains utility functions for building and processing queries. */ diff --git a/x-pack/plugins/apm/server/lib/service_map/get_service_anomalies.ts b/x-pack/plugins/apm/server/lib/service_map/get_service_anomalies.ts index 9b2d79dc726ee..2ed1966dcacbd 100644 --- a/x-pack/plugins/apm/server/lib/service_map/get_service_anomalies.ts +++ b/x-pack/plugins/apm/server/lib/service_map/get_service_anomalies.ts @@ -7,7 +7,7 @@ import Boom from '@hapi/boom'; import { sortBy, uniqBy } from 'lodash'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ESSearchResponse } from '../../../../../../src/core/types/elasticsearch'; import { MlPluginSetup } from '../../../../ml/server'; import { PromiseReturnType } from '../../../../observability/typings/common'; diff --git a/x-pack/plugins/apm/server/lib/services/__snapshots__/queries.test.ts.snap b/x-pack/plugins/apm/server/lib/services/__snapshots__/queries.test.ts.snap index 99891807e689b..d6d6219440dad 100644 --- a/x-pack/plugins/apm/server/lib/services/__snapshots__/queries.test.ts.snap +++ b/x-pack/plugins/apm/server/lib/services/__snapshots__/queries.test.ts.snap @@ -12,7 +12,7 @@ Object { "body": Object { "size": 0, }, - "terminateAfter": 1, + "terminate_after": 1, } `; @@ -49,7 +49,7 @@ Object { }, "size": 0, }, - "terminateAfter": 1, + "terminate_after": 1, } `; @@ -99,7 +99,7 @@ Object { }, "size": 1, }, - "terminateAfter": 1, + "terminate_after": 1, } `; diff --git a/x-pack/plugins/apm/server/lib/services/annotations/get_stored_annotations.ts b/x-pack/plugins/apm/server/lib/services/annotations/get_stored_annotations.ts index d44468bb0bb60..ac1c2653bf148 100644 --- a/x-pack/plugins/apm/server/lib/services/annotations/get_stored_annotations.ts +++ b/x-pack/plugins/apm/server/lib/services/annotations/get_stored_annotations.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ResponseError } from '@elastic/elasticsearch/lib/errors'; +import { errors } from '@elastic/elasticsearch'; import { ElasticsearchClient, Logger } from 'kibana/server'; import { rangeQuery } from '../../../../../observability/server'; import { environmentQuery } from '../../../../common/utils/environment_query'; @@ -75,7 +75,7 @@ export function getStoredAnnotations({ // so we should handle this error gracefully if ( error instanceof WrappedElasticsearchClientError && - error.originalError instanceof ResponseError + error.originalError instanceof errors.ResponseError ) { const type = error.originalError.body.error.type; diff --git a/x-pack/plugins/apm/server/lib/services/get_service_agent.ts b/x-pack/plugins/apm/server/lib/services/get_service_agent.ts index 5ef29437d73d6..4c9ff9f124b10 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_agent.ts +++ b/x-pack/plugins/apm/server/lib/services/get_service_agent.ts @@ -42,7 +42,7 @@ export async function getServiceAgent({ const { apmEventClient } = setup; const params = { - terminateAfter: 1, + terminate_after: 1, apm: { events: [ ProcessorEvent.error, diff --git a/x-pack/plugins/apm/server/lib/services/get_services/get_legacy_data_status.ts b/x-pack/plugins/apm/server/lib/services/get_services/get_legacy_data_status.ts index cf80222dc8303..5b94bb2314258 100644 --- a/x-pack/plugins/apm/server/lib/services/get_services/get_legacy_data_status.ts +++ b/x-pack/plugins/apm/server/lib/services/get_services/get_legacy_data_status.ts @@ -19,7 +19,7 @@ export async function getLegacyDataStatus( const { apmEventClient } = setup; const params = { - terminateAfter: 1, + terminate_after: 1, apm: { events: [ProcessorEvent.transaction], includeLegacyData: true, diff --git a/x-pack/plugins/apm/server/lib/settings/agent_configuration/create_agent_config_index.ts b/x-pack/plugins/apm/server/lib/settings/agent_configuration/create_agent_config_index.ts index f43938891f1f0..a14019f4dbdec 100644 --- a/x-pack/plugins/apm/server/lib/settings/agent_configuration/create_agent_config_index.ts +++ b/x-pack/plugins/apm/server/lib/settings/agent_configuration/create_agent_config_index.ts @@ -36,7 +36,6 @@ const mappings: Mappings = { dynamic_templates: [ { // force string to keyword (instead of default of text + keyword) - // @ts-expect-error @elastic/elasticsearch expects here mapping: MappingPropertyBase strings: { match_mapping_type: 'string', mapping: { diff --git a/x-pack/plugins/apm/server/lib/settings/agent_configuration/get_agent_name_by_service.ts b/x-pack/plugins/apm/server/lib/settings/agent_configuration/get_agent_name_by_service.ts index 0b6dd10b42e25..6ea3e2a578050 100644 --- a/x-pack/plugins/apm/server/lib/settings/agent_configuration/get_agent_name_by_service.ts +++ b/x-pack/plugins/apm/server/lib/settings/agent_configuration/get_agent_name_by_service.ts @@ -20,7 +20,7 @@ export async function getAgentNameByService({ const { apmEventClient } = setup; const params = { - terminateAfter: 1, + terminate_after: 1, apm: { events: [ ProcessorEvent.transaction, diff --git a/x-pack/plugins/apm/server/lib/settings/custom_link/__snapshots__/get_transaction.test.ts.snap b/x-pack/plugins/apm/server/lib/settings/custom_link/__snapshots__/get_transaction.test.ts.snap index 0649c8c38d29a..921129cf2c1da 100644 --- a/x-pack/plugins/apm/server/lib/settings/custom_link/__snapshots__/get_transaction.test.ts.snap +++ b/x-pack/plugins/apm/server/lib/settings/custom_link/__snapshots__/get_transaction.test.ts.snap @@ -44,7 +44,7 @@ Object { }, }, "size": 1, - "terminateAfter": 1, + "terminate_after": 1, } `; @@ -63,6 +63,6 @@ Object { }, }, "size": 1, - "terminateAfter": 1, + "terminate_after": 1, } `; diff --git a/x-pack/plugins/apm/server/lib/settings/custom_link/create_custom_link_index.ts b/x-pack/plugins/apm/server/lib/settings/custom_link/create_custom_link_index.ts index 085bb2b4be40d..752a7769caea0 100644 --- a/x-pack/plugins/apm/server/lib/settings/custom_link/create_custom_link_index.ts +++ b/x-pack/plugins/apm/server/lib/settings/custom_link/create_custom_link_index.ts @@ -6,7 +6,7 @@ */ import { ElasticsearchClient, Logger } from 'src/core/server'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { createOrUpdateIndex, Mappings, diff --git a/x-pack/plugins/apm/server/lib/settings/custom_link/get_transaction.ts b/x-pack/plugins/apm/server/lib/settings/custom_link/get_transaction.ts index 91bc8c85bc014..1c3d1465527ba 100644 --- a/x-pack/plugins/apm/server/lib/settings/custom_link/get_transaction.ts +++ b/x-pack/plugins/apm/server/lib/settings/custom_link/get_transaction.ts @@ -32,7 +32,7 @@ export async function getTransaction({ ); const params = { - terminateAfter: 1, + terminate_after: 1, apm: { events: [ProcessorEvent.transaction as const], }, diff --git a/x-pack/plugins/apm/server/lib/settings/custom_link/list_custom_links.ts b/x-pack/plugins/apm/server/lib/settings/custom_link/list_custom_links.ts index d477da85e0d9b..633545e16acfd 100644 --- a/x-pack/plugins/apm/server/lib/settings/custom_link/list_custom_links.ts +++ b/x-pack/plugins/apm/server/lib/settings/custom_link/list_custom_links.ts @@ -6,7 +6,7 @@ */ import * as t from 'io-ts'; -import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { CustomLink, CustomLinkES, diff --git a/x-pack/plugins/apm/server/lib/traces/get_trace_items.ts b/x-pack/plugins/apm/server/lib/traces/get_trace_items.ts index 60a28fd9abdbd..55204786b8e67 100644 --- a/x-pack/plugins/apm/server/lib/traces/get_trace_items.ts +++ b/x-pack/plugins/apm/server/lib/traces/get_trace_items.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ProcessorEvent } from '../../../common/processor_event'; import { TRACE_ID, diff --git a/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts b/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts index f082483c0c109..200d3d6ac7459 100644 --- a/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts +++ b/x-pack/plugins/apm/server/lib/transaction_groups/fetcher.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { sortBy } from 'lodash'; import moment from 'moment'; import { Unionize } from 'utility-types'; diff --git a/x-pack/plugins/apm/server/lib/transaction_groups/get_transaction_group_stats.ts b/x-pack/plugins/apm/server/lib/transaction_groups/get_transaction_group_stats.ts index 8769a572e33a0..c79dde721d138 100644 --- a/x-pack/plugins/apm/server/lib/transaction_groups/get_transaction_group_stats.ts +++ b/x-pack/plugins/apm/server/lib/transaction_groups/get_transaction_group_stats.ts @@ -6,7 +6,7 @@ */ import { merge } from 'lodash'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { TRANSACTION_TYPE } from '../../../common/elasticsearch_fieldnames'; import { arrayUnionToCallable } from '../../../common/utils/array_union_to_callable'; import { TransactionGroupRequestBase, TransactionGroupSetup } from './fetcher'; diff --git a/x-pack/plugins/apm/server/lib/transactions/get_anomaly_data/fetcher.ts b/x-pack/plugins/apm/server/lib/transactions/get_anomaly_data/fetcher.ts index a61e0614f5b1a..2fcbf5842d746 100644 --- a/x-pack/plugins/apm/server/lib/transactions/get_anomaly_data/fetcher.ts +++ b/x-pack/plugins/apm/server/lib/transactions/get_anomaly_data/fetcher.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ESSearchResponse } from '../../../../../../../src/core/types/elasticsearch'; import { PromiseReturnType } from '../../../../../observability/typings/common'; import { rangeQuery } from '../../../../../observability/server'; diff --git a/x-pack/plugins/apm/server/lib/transactions/trace_samples/get_trace_samples/index.ts b/x-pack/plugins/apm/server/lib/transactions/trace_samples/get_trace_samples/index.ts index 79eebf0813e36..b085c0fc4a839 100644 --- a/x-pack/plugins/apm/server/lib/transactions/trace_samples/get_trace_samples/index.ts +++ b/x-pack/plugins/apm/server/lib/transactions/trace_samples/get_trace_samples/index.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { withApmSpan } from '../../../../utils/with_apm_span'; import { SERVICE_NAME, diff --git a/x-pack/plugins/apm/server/projections/metrics.ts b/x-pack/plugins/apm/server/projections/metrics.ts index ce5a506752b65..417281f2de487 100644 --- a/x-pack/plugins/apm/server/projections/metrics.ts +++ b/x-pack/plugins/apm/server/projections/metrics.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { SERVICE_NAME, SERVICE_NODE_NAME, diff --git a/x-pack/plugins/apm/server/projections/typings.ts b/x-pack/plugins/apm/server/projections/typings.ts index 0843fa4c9dd64..d252fd311b4fe 100644 --- a/x-pack/plugins/apm/server/projections/typings.ts +++ b/x-pack/plugins/apm/server/projections/typings.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { AggregationOptionsByType } from '../../../../../src/core/types/elasticsearch'; import { APMEventESSearchRequest } from '../lib/helpers/create_es_client/create_apm_event_client'; diff --git a/x-pack/plugins/apm/server/routes/historical_data/has_historical_agent_data.ts b/x-pack/plugins/apm/server/routes/historical_data/has_historical_agent_data.ts index 13591b47a8584..54960c3e48b60 100644 --- a/x-pack/plugins/apm/server/routes/historical_data/has_historical_agent_data.ts +++ b/x-pack/plugins/apm/server/routes/historical_data/has_historical_agent_data.ts @@ -13,7 +13,7 @@ export async function hasHistoricalAgentData(setup: Setup) { const { apmEventClient } = setup; const params = { - terminateAfter: 1, + terminate_after: 1, apm: { events: [ ProcessorEvent.error, diff --git a/x-pack/plugins/apm/server/routes/register_routes/index.ts b/x-pack/plugins/apm/server/routes/register_routes/index.ts index d3587f1fcbe4b..576c23dc0882f 100644 --- a/x-pack/plugins/apm/server/routes/register_routes/index.ts +++ b/x-pack/plugins/apm/server/routes/register_routes/index.ts @@ -8,7 +8,7 @@ import Boom from '@hapi/boom'; import * as t from 'io-ts'; import { KibanaRequest, RouteRegistrar } from 'src/core/server'; -import { RequestAbortedError } from '@elastic/elasticsearch/lib/errors'; +import { errors } from '@elastic/elasticsearch'; import agent from 'elastic-apm-node'; import { ServerRouteRepository } from '@kbn/server-route-repository'; import { merge } from 'lodash'; @@ -170,7 +170,7 @@ export function registerRoutes({ }, }; - if (error instanceof RequestAbortedError) { + if (error instanceof errors.RequestAbortedError) { return response.custom(merge(opts, CLIENT_CLOSED_REQUEST)); } diff --git a/x-pack/plugins/canvas/types/strategy.ts b/x-pack/plugins/canvas/types/strategy.ts index d7115a3e4372f..2cc4c72116cdb 100644 --- a/x-pack/plugins/canvas/types/strategy.ts +++ b/x-pack/plugins/canvas/types/strategy.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { ApiResponse } from '@elastic/elasticsearch/lib/Transport'; -import { estypes } from '@elastic/elasticsearch'; +import { TransportResult } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { IKibanaSearchRequest } from 'src/plugins/data/common'; import { ExpressionValueFilter } from '.'; export interface EssqlSearchStrategyRequest extends IKibanaSearchRequest { @@ -27,5 +27,5 @@ export interface EssqlSearchStrategyResponse { }>; rows: any[]; - rawResponse: ApiResponse; + rawResponse: TransportResult; } diff --git a/x-pack/plugins/cases/server/services/cases/index.ts b/x-pack/plugins/cases/server/services/cases/index.ts index 3c76be6d6dd93..4a22793f78af5 100644 --- a/x-pack/plugins/cases/server/services/cases/index.ts +++ b/x-pack/plugins/cases/server/services/cases/index.ts @@ -19,7 +19,7 @@ import { SavedObjectsResolveResponse, } from 'kibana/server'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { nodeBuilder, KueryNode } from '../../../../../../src/plugins/data/common'; import { SecurityPluginSetup } from '../../../../security/server'; diff --git a/x-pack/plugins/data_enhanced/server/collectors/fetch.ts b/x-pack/plugins/data_enhanced/server/collectors/fetch.ts index 73dcc89a79b39..f60d6f32871d3 100644 --- a/x-pack/plugins/data_enhanced/server/collectors/fetch.ts +++ b/x-pack/plugins/data_enhanced/server/collectors/fetch.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Logger } from 'kibana/server'; import { CollectorFetchContext } from '../../../../../src/plugins/usage_collection/server'; import { SEARCH_SESSION_TYPE } from '../../../../../src/plugins/data/common'; diff --git a/x-pack/plugins/data_enhanced/server/search/session/get_search_status.ts b/x-pack/plugins/data_enhanced/server/search/session/get_search_status.ts index 461c41b46491c..a49dc30b84fb5 100644 --- a/x-pack/plugins/data_enhanced/server/search/session/get_search_status.ts +++ b/x-pack/plugins/data_enhanced/server/search/session/get_search_status.ts @@ -6,7 +6,7 @@ */ import { i18n } from '@kbn/i18n'; -import { ApiResponse } from '@elastic/elasticsearch'; +import type { TransportResult } from '@elastic/elasticsearch'; import { ElasticsearchClient } from 'src/core/server'; import { SearchStatus } from './types'; import { SearchSessionRequestInfo } from '../../../../../../src/plugins/data/common'; @@ -19,9 +19,11 @@ export async function getSearchStatus( // TODO: Handle strategies other than the default one try { // @ts-expect-error start_time_in_millis: EpochMillis is string | number - const apiResponse: ApiResponse = await client.asyncSearch.status({ - id: asyncId, - }); + const apiResponse: TransportResult = await client.asyncSearch.status( + { + id: asyncId, + } + ); const response = apiResponse.body; if ((response.is_partial && !response.is_running) || response.completion_status >= 400) { return { diff --git a/x-pack/plugins/data_visualizer/common/types/indices.ts b/x-pack/plugins/data_visualizer/common/types/indices.ts index c80b89b4e84c7..dd4bea8602720 100644 --- a/x-pack/plugins/data_visualizer/common/types/indices.ts +++ b/x-pack/plugins/data_visualizer/common/types/indices.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; export interface IndicesOptions { allow_no_indices?: boolean; diff --git a/x-pack/plugins/data_visualizer/common/utils/datafeed_utils.ts b/x-pack/plugins/data_visualizer/common/utils/datafeed_utils.ts index bccd40ed43b0c..5a87d7b01db46 100644 --- a/x-pack/plugins/data_visualizer/common/utils/datafeed_utils.ts +++ b/x-pack/plugins/data_visualizer/common/utils/datafeed_utils.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; export type Datafeed = estypes.MlDatafeed; export type Aggregation = Record; diff --git a/x-pack/plugins/data_visualizer/common/utils/query_utils.ts b/x-pack/plugins/data_visualizer/common/utils/query_utils.ts index d2785072f419d..2aa4cd063d1b1 100644 --- a/x-pack/plugins/data_visualizer/common/utils/query_utils.ts +++ b/x-pack/plugins/data_visualizer/common/utils/query_utils.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; /* * Contains utility functions for building and processing queries. */ diff --git a/x-pack/plugins/data_visualizer/common/utils/runtime_field_utils.ts b/x-pack/plugins/data_visualizer/common/utils/runtime_field_utils.ts index fbe4ae5c6faf1..a088685f03f54 100644 --- a/x-pack/plugins/data_visualizer/common/utils/runtime_field_utils.ts +++ b/x-pack/plugins/data_visualizer/common/utils/runtime_field_utils.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { isPopulatedObject } from './object_utils'; import { RUNTIME_FIELD_TYPES } from '../../../../../src/plugins/data/common'; diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/full_time_range_selector/full_time_range_selector_service.ts b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/full_time_range_selector/full_time_range_selector_service.ts index 198079c6ec9de..f2d14de9812ca 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/full_time_range_selector/full_time_range_selector_service.ts +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/components/full_time_range_selector/full_time_range_selector_service.ts @@ -6,7 +6,7 @@ */ import moment from 'moment'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Query, TimefilterContract } from 'src/plugins/data/public'; import dateMath from '@elastic/datemath'; import { IndexPattern } from '../../../../../../../../src/plugins/data/public'; diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/data_loader/data_loader.ts b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/data_loader/data_loader.ts index c4db51dcd81bc..e0a2852a57b29 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/data_loader/data_loader.ts +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/data_loader/data_loader.ts @@ -7,7 +7,7 @@ // Maximum number of examples to obtain for text type fields. import { CoreSetup } from 'kibana/public'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { i18n } from '@kbn/i18n'; import { IndexPattern } from '../../../../../../../src/plugins/data/common'; import { NON_AGGREGATABLE_FIELD_TYPES, OMIT_FIELDS } from '../../../../common/constants'; diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/services/time_field_range.ts b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/services/time_field_range.ts index 87d4a3b7fb711..58a4bd4520829 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/services/time_field_range.ts +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/services/time_field_range.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { lazyLoadModules } from '../../../lazy_load_bundle'; import { GetTimeFieldRangeResponse } from '../../../../common/types/time_field_request'; import { Query } from '../../../../../../../src/plugins/data/common/query'; diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/services/visualizer_stats.ts b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/services/visualizer_stats.ts index 8db267a1dc837..3653936f3d12e 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/services/visualizer_stats.ts +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/services/visualizer_stats.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { lazyLoadModules } from '../../../lazy_load_bundle'; import type { DocumentCounts, FieldRequestConfig, FieldVisStats } from '../../../../common/types'; import { OverallStats } from '../types/overall_stats'; diff --git a/x-pack/plugins/data_visualizer/server/models/data_visualizer/check_fields_exist.ts b/x-pack/plugins/data_visualizer/server/models/data_visualizer/check_fields_exist.ts index f0cbffbfa70c3..24b4deeecdddd 100644 --- a/x-pack/plugins/data_visualizer/server/models/data_visualizer/check_fields_exist.ts +++ b/x-pack/plugins/data_visualizer/server/models/data_visualizer/check_fields_exist.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { get } from 'lodash'; import { IScopedClusterClient } from 'kibana/server'; import { AggCardinality, Aggs, FieldData } from '../../types'; diff --git a/x-pack/plugins/data_visualizer/server/models/data_visualizer/data_visualizer.ts b/x-pack/plugins/data_visualizer/server/models/data_visualizer/data_visualizer.ts index 003d5a7d86015..42e7f93cc8789 100644 --- a/x-pack/plugins/data_visualizer/server/models/data_visualizer/data_visualizer.ts +++ b/x-pack/plugins/data_visualizer/server/models/data_visualizer/data_visualizer.ts @@ -7,7 +7,7 @@ import { IScopedClusterClient } from 'kibana/server'; import { each, last } from 'lodash'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { JOB_FIELD_TYPES } from '../../../common'; import type { BatchStats, diff --git a/x-pack/plugins/data_visualizer/server/models/data_visualizer/get_field_examples.ts b/x-pack/plugins/data_visualizer/server/models/data_visualizer/get_field_examples.ts index 69476e254068f..78adfb9e81b95 100644 --- a/x-pack/plugins/data_visualizer/server/models/data_visualizer/get_field_examples.ts +++ b/x-pack/plugins/data_visualizer/server/models/data_visualizer/get_field_examples.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { get } from 'lodash'; import { IScopedClusterClient } from 'kibana/server'; import { buildBaseFilterCriteria } from '../../../common/utils/query_utils'; diff --git a/x-pack/plugins/data_visualizer/server/models/data_visualizer/get_fields_stats.ts b/x-pack/plugins/data_visualizer/server/models/data_visualizer/get_fields_stats.ts index 6968aa97ab938..da93719e9ed93 100644 --- a/x-pack/plugins/data_visualizer/server/models/data_visualizer/get_fields_stats.ts +++ b/x-pack/plugins/data_visualizer/server/models/data_visualizer/get_fields_stats.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { each, find, get } from 'lodash'; import { IScopedClusterClient } from 'kibana/server'; import { diff --git a/x-pack/plugins/data_visualizer/server/models/data_visualizer/get_histogram_for_fields.ts b/x-pack/plugins/data_visualizer/server/models/data_visualizer/get_histogram_for_fields.ts index 6621c793c0017..1cbf40a22b056 100644 --- a/x-pack/plugins/data_visualizer/server/models/data_visualizer/get_histogram_for_fields.ts +++ b/x-pack/plugins/data_visualizer/server/models/data_visualizer/get_histogram_for_fields.ts @@ -6,7 +6,7 @@ */ import { IScopedClusterClient } from 'kibana/server'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { get } from 'lodash'; import { ChartData, ChartRequestAgg, HistogramField, NumericColumnStatsMap } from '../../types'; import { KBN_FIELD_TYPES } from '../../../../../../src/plugins/data/common'; diff --git a/x-pack/plugins/data_visualizer/server/routes/routes.ts b/x-pack/plugins/data_visualizer/server/routes/routes.ts index 74afae2634636..1ec2eaa242c1c 100644 --- a/x-pack/plugins/data_visualizer/server/routes/routes.ts +++ b/x-pack/plugins/data_visualizer/server/routes/routes.ts @@ -6,7 +6,7 @@ */ import type { CoreSetup, IScopedClusterClient } from 'kibana/server'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { dataVisualizerFieldHistogramsSchema, dataVisualizerFieldStatsSchema, diff --git a/x-pack/plugins/event_log/server/es/cluster_client_adapter.test.ts b/x-pack/plugins/event_log/server/es/cluster_client_adapter.test.ts index f4140298928b6..314a6b9a31ef8 100644 --- a/x-pack/plugins/event_log/server/es/cluster_client_adapter.test.ts +++ b/x-pack/plugins/event_log/server/es/cluster_client_adapter.test.ts @@ -16,7 +16,8 @@ import { findOptionsSchema } from '../event_log_client'; import { delay } from '../lib/delay'; import { times } from 'lodash'; import { DeeplyMockedKeys } from '@kbn/utility-types/jest'; -import { estypes, RequestEvent } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; +import type { TransportResult } from '@elastic/elasticsearch'; type MockedLogger = ReturnType; @@ -399,9 +400,7 @@ describe('setIndexToHidden', () => { expect(clusterClient.indices.putSettings).toHaveBeenCalledWith({ index: 'foo-bar-000001', body: { - settings: { - 'index.hidden': true, - }, + 'index.hidden': true, }, }); }); @@ -1270,10 +1269,10 @@ type RetryableFunction = () => boolean; const RETRY_UNTIL_DEFAULT_COUNT = 20; const RETRY_UNTIL_DEFAULT_WAIT = 1000; // milliseconds -function asApiResponse(body: T): RequestEvent { +function asApiResponse(body: T): TransportResult { return { body, - } as RequestEvent; + } as TransportResult; } async function retryUntil( diff --git a/x-pack/plugins/event_log/server/es/cluster_client_adapter.ts b/x-pack/plugins/event_log/server/es/cluster_client_adapter.ts index 7eb3328dddb6b..7246e1ed972ec 100644 --- a/x-pack/plugins/event_log/server/es/cluster_client_adapter.ts +++ b/x-pack/plugins/event_log/server/es/cluster_client_adapter.ts @@ -11,7 +11,7 @@ import { reject, isUndefined, isNumber, pick } from 'lodash'; import type { PublicMethodsOf } from '@kbn/utility-types'; import { Logger, ElasticsearchClient } from 'src/core/server'; import util from 'util'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query'; import { IEvent, IValidatedEvent, SAVED_OBJECT_REL_PRIMARY } from '../types'; import { FindOptionsType } from '../event_log_client'; @@ -255,9 +255,7 @@ export class ClusterClientAdapter ({ version: '1.2.3' })); jest.mock('./init'); @@ -63,6 +63,7 @@ describe('createEsContext', () => { kibanaVersion: '1.2.3', elasticsearchClientPromise: Promise.resolve(elasticsearchClient), }); + elasticsearchClient.indices.existsTemplate.mockResolvedValue(asApiResponse(false)); elasticsearchClient.indices.existsIndexTemplate.mockResolvedValue(asApiResponse(false)); elasticsearchClient.indices.existsAlias.mockResolvedValue(asApiResponse(false)); @@ -113,8 +114,8 @@ describe('createEsContext', () => { }); }); -function asApiResponse(body: T): RequestEvent { +function asApiResponse(body: T): TransportResult { return { body, - } as RequestEvent; + } as TransportResult; } diff --git a/x-pack/plugins/event_log/server/es/init.ts b/x-pack/plugins/event_log/server/es/init.ts index f15b9f89887c5..7641404c484ce 100644 --- a/x-pack/plugins/event_log/server/es/init.ts +++ b/x-pack/plugins/event_log/server/es/init.ts @@ -5,8 +5,11 @@ * 2.0. */ -import { IndicesAlias, IndicesIndexStatePrefixedSettings } from '@elastic/elasticsearch/api/types'; -import { estypes } from '@elastic/elasticsearch'; +import { + IndicesAlias, + IndicesIndexStatePrefixedSettings, +} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { asyncForEach } from '@kbn/std'; import { getIlmPolicy, getIndexTemplate } from './documents'; import { EsContext } from './context'; diff --git a/x-pack/plugins/file_upload/common/types.ts b/x-pack/plugins/file_upload/common/types.ts index 8462f8983a67d..6e72b749bdb61 100644 --- a/x-pack/plugins/file_upload/common/types.ts +++ b/x-pack/plugins/file_upload/common/types.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ES_FIELD_TYPES } from 'src/plugins/data/common'; export interface InputOverrides { diff --git a/x-pack/plugins/file_upload/server/get_time_field_range.ts b/x-pack/plugins/file_upload/server/get_time_field_range.ts index 0e8358f1671d0..1c8e94d5fc301 100644 --- a/x-pack/plugins/file_upload/server/get_time_field_range.ts +++ b/x-pack/plugins/file_upload/server/get_time_field_range.ts @@ -5,7 +5,7 @@ * 2.0. */ import { IScopedClusterClient } from 'kibana/server'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { isPopulatedObject } from './utils/runtime_field_utils'; export async function getTimeFieldRange( diff --git a/x-pack/plugins/file_upload/server/utils/runtime_field_utils.ts b/x-pack/plugins/file_upload/server/utils/runtime_field_utils.ts index aba6effe175c0..09a473b611ac9 100644 --- a/x-pack/plugins/file_upload/server/utils/runtime_field_utils.ts +++ b/x-pack/plugins/file_upload/server/utils/runtime_field_utils.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { RUNTIME_FIELD_TYPES } from '../../../../../src/plugins/data/common'; type RuntimeType = typeof RUNTIME_FIELD_TYPES[number]; diff --git a/x-pack/plugins/fleet/common/types/models/epm.ts b/x-pack/plugins/fleet/common/types/models/epm.ts index 6f107ae44bfa7..078281fec9806 100644 --- a/x-pack/plugins/fleet/common/types/models/epm.ts +++ b/x-pack/plugins/fleet/common/types/models/epm.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; // Follow pattern from https://github.com/elastic/kibana/pull/52447 // TODO: Update when https://github.com/elastic/kibana/issues/53021 is closed import type { SavedObject, SavedObjectAttributes, SavedObjectReference } from 'src/core/public'; diff --git a/x-pack/plugins/fleet/server/errors/index.ts b/x-pack/plugins/fleet/server/errors/index.ts index 22f4b8cd6daab..6075b7e441fdf 100644 --- a/x-pack/plugins/fleet/server/errors/index.ts +++ b/x-pack/plugins/fleet/server/errors/index.ts @@ -6,6 +6,8 @@ */ /* eslint-disable max-classes-per-file */ +import type { ElasticsearchErrorDetails } from 'src/core/server'; + import { isESClientError } from './utils'; export { defaultIngestErrorHandler, ingestErrorToResponseOptions } from './handlers'; @@ -65,8 +67,8 @@ export class ArtifactsElasticsearchError extends IngestManagerError { constructor(public readonly meta: Error) { super( `${ - isESClientError(meta) && meta.meta.body?.error?.reason - ? meta.meta.body?.error?.reason + isESClientError(meta) && (meta.meta.body as ElasticsearchErrorDetails)?.error?.reason + ? (meta.meta.body as ElasticsearchErrorDetails)?.error?.reason : `Elasticsearch error while working with artifacts: ${meta.message}` }` ); diff --git a/x-pack/plugins/fleet/server/errors/utils.ts b/x-pack/plugins/fleet/server/errors/utils.ts index d58f82b94fcd7..23e92cdcd9f51 100644 --- a/x-pack/plugins/fleet/server/errors/utils.ts +++ b/x-pack/plugins/fleet/server/errors/utils.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { ResponseError } from '@elastic/elasticsearch/lib/errors'; +import { errors } from '@elastic/elasticsearch'; -export function isESClientError(error: unknown): error is ResponseError { - return error instanceof ResponseError; +export function isESClientError(error: unknown): error is errors.ResponseError { + return error instanceof errors.ResponseError; } export function isElasticsearchVersionConflictError(error: Error): boolean { diff --git a/x-pack/plugins/fleet/server/routes/app/index.ts b/x-pack/plugins/fleet/server/routes/app/index.ts index 43614f3a286b0..e46e57d3838b4 100644 --- a/x-pack/plugins/fleet/server/routes/app/index.ts +++ b/x-pack/plugins/fleet/server/routes/app/index.ts @@ -48,7 +48,10 @@ export const getCheckPermissionsHandler: RequestHandler = async (context, reques export const generateServiceTokenHandler: RequestHandler = async (context, request, response) => { const esClient = context.core.elasticsearch.client.asCurrentUser; try { - const { body: tokenResponse } = await esClient.transport.request({ + const { body: tokenResponse } = await esClient.transport.request<{ + created?: boolean; + token?: GenerateServiceTokenResponse; + }>({ method: 'POST', path: `_security/service/elastic/fleet-server/credential/token/token-${Date.now()}`, }); diff --git a/x-pack/plugins/fleet/server/routes/data_streams/handlers.ts b/x-pack/plugins/fleet/server/routes/data_streams/handlers.ts index 050b1a2441fed..232df94d7610b 100644 --- a/x-pack/plugins/fleet/server/routes/data_streams/handlers.ts +++ b/x-pack/plugins/fleet/server/routes/data_streams/handlers.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { keyBy, keys, merge } from 'lodash'; import type { RequestHandler } from 'src/core/server'; diff --git a/x-pack/plugins/fleet/server/services/agents/crud.ts b/x-pack/plugins/fleet/server/services/agents/crud.ts index 03647c52e05f0..b8d7c284309df 100644 --- a/x-pack/plugins/fleet/server/services/agents/crud.ts +++ b/x-pack/plugins/fleet/server/services/agents/crud.ts @@ -6,7 +6,7 @@ */ import Boom from '@hapi/boom'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { SavedObjectsClientContract, ElasticsearchClient } from 'src/core/server'; import type { KueryNode } from '@kbn/es-query'; @@ -126,10 +126,12 @@ export async function getAgentsByKuery( index: AGENTS_INDEX, from: (page - 1) * perPage, size: perPage, - sort: `${sortField}:${sortOrder}`, track_total_hits: true, ignore_unavailable: true, - body, + body: { + ...body, + sort: [{ [sortField]: { order: sortOrder } }], + }, }); let agents = res.body.hits.hits.map(searchHitToAgent); @@ -219,6 +221,7 @@ export function isAgentDocument( } export type ESAgentDocumentResult = estypes.MgetHit; + export async function getAgentDocuments( esClient: ElasticsearchClient, agentIds: string[] @@ -315,10 +318,9 @@ export async function bulkUpdateAgents( }); return { - items: res.body.items.map((item: estypes.BulkResponseItemContainer) => ({ + items: res.body.items.map((item) => ({ id: item.update!._id as string, success: !item.update!.error, - // @ts-expect-error ErrorCause is not assignable to Error error: item.update!.error as Error, })), }; diff --git a/x-pack/plugins/fleet/server/services/agents/helpers.ts b/x-pack/plugins/fleet/server/services/agents/helpers.ts index 195b2567c24ae..609d5ba6c83a0 100644 --- a/x-pack/plugins/fleet/server/services/agents/helpers.ts +++ b/x-pack/plugins/fleet/server/services/agents/helpers.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { SearchHit } from '../../../../../../src/core/types/elasticsearch'; import type { Agent, AgentSOAttributes, FleetServerAgent } from '../../types'; diff --git a/x-pack/plugins/fleet/server/services/agents/reassign.test.ts b/x-pack/plugins/fleet/server/services/agents/reassign.test.ts index a87432c639249..71935ffa5f90c 100644 --- a/x-pack/plugins/fleet/server/services/agents/reassign.test.ts +++ b/x-pack/plugins/fleet/server/services/agents/reassign.test.ts @@ -6,6 +6,7 @@ */ import { elasticsearchServiceMock, savedObjectsClientMock } from 'src/core/server/mocks'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { SavedObject } from 'kibana/server'; import type { AgentPolicy } from '../../types'; @@ -47,7 +48,10 @@ describe('reassignAgent (singular)', () => { expect(esClient.update).toBeCalledTimes(1); const calledWith = esClient.update.mock.calls[0]; expect(calledWith[0]?.id).toBe(agentInRegularDoc._id); - expect(calledWith[0]?.body?.doc).toHaveProperty('policy_id', regularAgentPolicySO.id); + expect((calledWith[0] as estypes.UpdateRequest)?.body?.doc).toHaveProperty( + 'policy_id', + regularAgentPolicySO.id + ); }); it('cannot reassign from regular agent policy to hosted', async () => { @@ -85,7 +89,7 @@ describe('reassignAgents (plural)', () => { // calls ES update with correct values const calledWith = esClient.bulk.mock.calls[0][0]; // only 1 are regular and bulk write two line per update - expect(calledWith.body?.length).toBe(2); + expect((calledWith as estypes.BulkRequest).body?.length).toBe(2); // @ts-expect-error expect(calledWith.body[0].update._id).toEqual(agentInRegularDoc._id); }); diff --git a/x-pack/plugins/fleet/server/services/agents/unenroll.test.ts b/x-pack/plugins/fleet/server/services/agents/unenroll.test.ts index 3621bc5025ab3..7f744ba6a59f4 100644 --- a/x-pack/plugins/fleet/server/services/agents/unenroll.test.ts +++ b/x-pack/plugins/fleet/server/services/agents/unenroll.test.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { elasticsearchServiceMock, savedObjectsClientMock } from 'src/core/server/mocks'; import type { SavedObject } from 'kibana/server'; @@ -43,7 +43,9 @@ describe('unenrollAgent (singular)', () => { expect(esClient.update).toBeCalledTimes(1); const calledWith = esClient.update.mock.calls[0]; expect(calledWith[0]?.id).toBe(agentInRegularDoc._id); - expect(calledWith[0]?.body).toHaveProperty('doc.unenrollment_started_at'); + expect((calledWith[0] as estypes.UpdateRequest)?.body).toHaveProperty( + 'doc.unenrollment_started_at' + ); }); it('cannot unenroll from hosted agent policy by default', async () => { @@ -71,7 +73,9 @@ describe('unenrollAgent (singular)', () => { expect(esClient.update).toBeCalledTimes(1); const calledWith = esClient.update.mock.calls[0]; expect(calledWith[0]?.id).toBe(agentInHostedDoc._id); - expect(calledWith[0]?.body).toHaveProperty('doc.unenrollment_started_at'); + expect((calledWith[0] as estypes.UpdateRequest)?.body).toHaveProperty( + 'doc.unenrollment_started_at' + ); }); it('can unenroll from hosted agent policy with force=true and revoke=true', async () => { @@ -81,7 +85,7 @@ describe('unenrollAgent (singular)', () => { expect(esClient.update).toBeCalledTimes(1); const calledWith = esClient.update.mock.calls[0]; expect(calledWith[0]?.id).toBe(agentInHostedDoc._id); - expect(calledWith[0]?.body).toHaveProperty('doc.unenrolled_at'); + expect((calledWith[0] as estypes.UpdateRequest)?.body).toHaveProperty('doc.unenrolled_at'); }); }); @@ -93,10 +97,12 @@ describe('unenrollAgents (plural)', () => { // calls ES update with correct values const calledWith = esClient.bulk.mock.calls[1][0]; - const ids = calledWith?.body + const ids = (calledWith as estypes.BulkRequest)?.body ?.filter((i: any) => i.update !== undefined) .map((i: any) => i.update._id); - const docs = calledWith?.body?.filter((i: any) => i.doc).map((i: any) => i.doc); + const docs = (calledWith as estypes.BulkRequest)?.body + ?.filter((i: any) => i.doc) + .map((i: any) => i.doc); expect(ids).toEqual(idsToUnenroll); for (const doc of docs!) { expect(doc).toHaveProperty('unenrollment_started_at'); @@ -111,10 +117,12 @@ describe('unenrollAgents (plural)', () => { // calls ES update with correct values const onlyRegular = [agentInRegularDoc._id, agentInRegularDoc2._id]; const calledWith = esClient.bulk.mock.calls[1][0]; - const ids = calledWith?.body + const ids = (calledWith as estypes.BulkRequest)?.body ?.filter((i: any) => i.update !== undefined) .map((i: any) => i.update._id); - const docs = calledWith?.body?.filter((i: any) => i.doc).map((i: any) => i.doc); + const docs = (calledWith as estypes.BulkRequest)?.body + ?.filter((i: any) => i.doc) + .map((i: any) => i.doc); expect(ids).toEqual(onlyRegular); for (const doc of docs!) { expect(doc).toHaveProperty('unenrollment_started_at'); @@ -149,10 +157,12 @@ describe('unenrollAgents (plural)', () => { // calls ES update with correct values const onlyRegular = [agentInRegularDoc._id, agentInRegularDoc2._id]; const calledWith = esClient.bulk.mock.calls[0][0]; - const ids = calledWith?.body + const ids = (calledWith as estypes.BulkRequest)?.body ?.filter((i: any) => i.update !== undefined) .map((i: any) => i.update._id); - const docs = calledWith?.body?.filter((i: any) => i.doc).map((i: any) => i.doc); + const docs = (calledWith as estypes.BulkRequest)?.body + ?.filter((i: any) => i.doc) + .map((i: any) => i.doc); expect(ids).toEqual(onlyRegular); for (const doc of docs!) { expect(doc).toHaveProperty('unenrolled_at'); @@ -166,10 +176,12 @@ describe('unenrollAgents (plural)', () => { // calls ES update with correct values const calledWith = esClient.bulk.mock.calls[1][0]; - const ids = calledWith?.body + const ids = (calledWith as estypes.BulkRequest)?.body ?.filter((i: any) => i.update !== undefined) .map((i: any) => i.update._id); - const docs = calledWith?.body?.filter((i: any) => i.doc).map((i: any) => i.doc); + const docs = (calledWith as estypes.BulkRequest)?.body + ?.filter((i: any) => i.doc) + .map((i: any) => i.doc); expect(ids).toEqual(idsToUnenroll); for (const doc of docs!) { expect(doc).toHaveProperty('unenrollment_started_at'); @@ -204,10 +216,12 @@ describe('unenrollAgents (plural)', () => { // calls ES update with correct values const calledWith = esClient.bulk.mock.calls[0][0]; - const ids = calledWith?.body + const ids = (calledWith as estypes.BulkRequest)?.body ?.filter((i: any) => i.update !== undefined) .map((i: any) => i.update._id); - const docs = calledWith?.body?.filter((i: any) => i.doc).map((i: any) => i.doc); + const docs = (calledWith as estypes.BulkRequest)?.body + ?.filter((i: any) => i.doc) + .map((i: any) => i.doc); expect(ids).toEqual(idsToUnenroll); for (const doc of docs!) { expect(doc).toHaveProperty('unenrolled_at'); diff --git a/x-pack/plugins/fleet/server/services/api_keys/enrollment_api_key.ts b/x-pack/plugins/fleet/server/services/api_keys/enrollment_api_key.ts index cc2357351f6df..166bd26e0d706 100644 --- a/x-pack/plugins/fleet/server/services/api_keys/enrollment_api_key.ts +++ b/x-pack/plugins/fleet/server/services/api_keys/enrollment_api_key.ts @@ -8,7 +8,7 @@ import uuid from 'uuid'; import Boom from '@hapi/boom'; import { i18n } from '@kbn/i18n'; -import { ResponseError } from '@elastic/elasticsearch/lib/errors'; +import { errors } from '@elastic/elasticsearch'; import type { SavedObjectsClientContract, ElasticsearchClient } from 'src/core/server'; import { toElasticsearchQuery, fromKueryExpression } from '@kbn/es-query'; @@ -42,10 +42,12 @@ export async function listEnrollmentApiKeys( index: ENROLLMENT_API_KEYS_INDEX, from: (page - 1) * perPage, size: perPage, - sort: 'created_at:desc', track_total_hits: true, ignore_unavailable: true, - body: query ? { query } : undefined, + body: { + sort: [{ created_at: { order: 'desc' } }], + ...(query ? { query } : {}), + }, }); // @ts-expect-error @elastic/elasticsearch _source is optional @@ -84,7 +86,7 @@ export async function getEnrollmentAPIKey( // @ts-expect-error esDocToEnrollmentApiKey doesn't accept optional _source return esDocToEnrollmentApiKey(res.body); } catch (e) { - if (e instanceof ResponseError && e.statusCode === 404) { + if (e instanceof errors.ResponseError && e.statusCode === 404) { throw Boom.notFound(`Enrollment api key ${id} not found`); } diff --git a/x-pack/plugins/fleet/server/services/artifacts/artifacts.test.ts b/x-pack/plugins/fleet/server/services/artifacts/artifacts.test.ts index b046b41d73722..a0e186aafb79a 100644 --- a/x-pack/plugins/fleet/server/services/artifacts/artifacts.test.ts +++ b/x-pack/plugins/fleet/server/services/artifacts/artifacts.test.ts @@ -7,9 +7,9 @@ import { elasticsearchServiceMock } from 'src/core/server/mocks'; -import { ResponseError } from '@elastic/elasticsearch/lib/errors'; +import { errors } from '@elastic/elasticsearch'; -import type { ApiResponse } from '@elastic/elasticsearch/lib/Transport'; +import type { TransportResult } from '@elastic/elasticsearch'; import { FLEET_SERVER_ARTIFACTS_INDEX } from '../../../common'; @@ -43,6 +43,7 @@ describe('When using the artifacts services', () => { describe('and calling `getArtifact()`', () => { it('should get artifact using id', async () => { + // @ts-expect-error not full interface esClientMock.get.mockImplementation(() => { return elasticsearchServiceMock.createSuccessTransportRequestPromise( generateArtifactEsGetSingleHitMock() @@ -64,7 +65,7 @@ describe('When using the artifacts services', () => { it('should throw an ArtifactElasticsearchError if one is encountered', async () => { esClientMock.get.mockImplementation(() => { return elasticsearchServiceMock.createErrorTransportRequestPromise( - new ResponseError(generateEsRequestErrorApiResponseMock()) + new errors.ResponseError(generateEsRequestErrorApiResponseMock()) ); }); @@ -103,9 +104,8 @@ describe('When using the artifacts services', () => { }); it('should ignore 409 errors from elasticsearch', async () => { - const error = new ResponseError({ statusCode: 409 } as ApiResponse); + const error = new errors.ResponseError({ statusCode: 409 } as TransportResult); // Unclear why `mockRejectedValue()` has the params value type set to `never` - // @ts-expect-error esClientMock.create.mockRejectedValue(error); await expect(() => createArtifact(esClientMock, newArtifact)).not.toThrow(); }); @@ -140,6 +140,7 @@ describe('When using the artifacts services', () => { describe('and calling `listArtifacts()`', () => { beforeEach(() => { + // @ts-expect-error not full interface esClientMock.search.mockImplementation(() => { return elasticsearchServiceMock.createSuccessTransportRequestPromise( generateArtifactEsSearchResultHitsMock() @@ -152,11 +153,13 @@ describe('When using the artifacts services', () => { expect(esClientMock.search).toHaveBeenCalledWith({ index: FLEET_SERVER_ARTIFACTS_INDEX, - sort: 'created:asc', ignore_unavailable: true, q: '', from: 0, size: 20, + body: { + sort: [{ created: { order: 'asc' } }], + }, }); expect(results).toEqual({ @@ -184,11 +187,13 @@ describe('When using the artifacts services', () => { expect(esClientMock.search).toHaveBeenCalledWith({ index: FLEET_SERVER_ARTIFACTS_INDEX, - sort: 'identifier:desc', q: 'packageName:endpoint', ignore_unavailable: true, from: 450, size: 50, + body: { + sort: [{ identifier: { order: 'desc' } }], + }, }); expect(listMeta).toEqual({ diff --git a/x-pack/plugins/fleet/server/services/artifacts/artifacts.ts b/x-pack/plugins/fleet/server/services/artifacts/artifacts.ts index 6ac23cb1f9ef8..3a6db6fd0d04f 100644 --- a/x-pack/plugins/fleet/server/services/artifacts/artifacts.ts +++ b/x-pack/plugins/fleet/server/services/artifacts/artifacts.ts @@ -103,11 +103,13 @@ export const listArtifacts = async ( try { const searchResult = await esClient.search({ index: FLEET_SERVER_ARTIFACTS_INDEX, - sort: `${sortField}:${sortOrder}`, q: kuery, from: (page - 1) * perPage, ignore_unavailable: true, size: perPage, + body: { + sort: [{ [sortField]: { order: sortOrder } }], + }, }); return { diff --git a/x-pack/plugins/fleet/server/services/artifacts/client.test.ts b/x-pack/plugins/fleet/server/services/artifacts/client.test.ts index 470f1d4ce0a84..ae875df26371c 100644 --- a/x-pack/plugins/fleet/server/services/artifacts/client.test.ts +++ b/x-pack/plugins/fleet/server/services/artifacts/client.test.ts @@ -28,6 +28,7 @@ describe('When using the Fleet Artifacts Client', () => { singleHit._source.package_name = 'not endpoint'; } + // @ts-expect-error not full interface esClientMock.get.mockImplementation(() => { return elasticsearchServiceMock.createSuccessTransportRequestPromise(singleHit); }); @@ -104,6 +105,7 @@ describe('When using the Fleet Artifacts Client', () => { describe('and calling `listArtifacts()`', () => { beforeEach(() => { + // @ts-expect-error not full interface esClientMock.search.mockImplementation(() => { return elasticsearchServiceMock.createSuccessTransportRequestPromise( generateArtifactEsSearchResultHitsMock() diff --git a/x-pack/plugins/fleet/server/services/artifacts/mocks.ts b/x-pack/plugins/fleet/server/services/artifacts/mocks.ts index 2799e1807123d..bc22bff0b29d0 100644 --- a/x-pack/plugins/fleet/server/services/artifacts/mocks.ts +++ b/x-pack/plugins/fleet/server/services/artifacts/mocks.ts @@ -6,8 +6,8 @@ */ import { URL } from 'url'; -import type { ApiResponse } from '@elastic/elasticsearch'; -import { ResponseError } from '@elastic/elasticsearch/lib/errors'; +import type { TransportResult } from '@elastic/elasticsearch'; +import { errors } from '@elastic/elasticsearch'; import { elasticsearchServiceMock } from '../../../../../../src/core/server/mocks'; import type { SearchHit, ESSearchResponse } from '../../../../../../src/core/types/elasticsearch'; @@ -69,7 +69,7 @@ export interface GenerateEsRequestErrorApiResponseMockProps { export const generateEsRequestErrorApiResponseMock = ( { statusCode = 500 }: GenerateEsRequestErrorApiResponseMockProps = { statusCode: 500 } -): ApiResponse => { +): TransportResult => { return generateEsApiResponseMock( { _index: '.fleet-artifacts_1', @@ -127,8 +127,8 @@ export const generateArtifactEsSearchResultHitsMock = (): ESSearchResponse< export const generateEsApiResponseMock = >( body: TBody, - otherProps: Partial> = {} -): ApiResponse => { + otherProps: Partial> = {} +): TransportResult => { return elasticsearchServiceMock.createApiResponse({ body, headers: { @@ -148,8 +148,6 @@ export const generateEsApiResponseMock = >( id: 7160, }, name: 'elasticsearch-js', - // There are some properties missing below which is not important for this mock - // @ts-ignore connection: { url: new URL('http://localhost:9200/'), id: 'http://localhost:9200/', @@ -158,6 +156,8 @@ export const generateEsApiResponseMock = >( resurrectTimeout: 0, _openRequests: 0, status: 'alive', + // There are some properties missing below which is not important for this mock + // @ts-expect-error roles: { master: true, data: true, @@ -182,7 +182,7 @@ export const setEsClientMethodResponseToError = ( ) => { esClientMock[method].mockImplementation(() => { return elasticsearchServiceMock.createErrorTransportRequestPromise( - new ResponseError(generateEsRequestErrorApiResponseMock(options)) + new errors.ResponseError(generateEsRequestErrorApiResponseMock(options)) ); }); }; diff --git a/x-pack/plugins/fleet/server/services/artifacts/utils.ts b/x-pack/plugins/fleet/server/services/artifacts/utils.ts index bce6b1a1e815b..e3b1be26165e8 100644 --- a/x-pack/plugins/fleet/server/services/artifacts/utils.ts +++ b/x-pack/plugins/fleet/server/services/artifacts/utils.ts @@ -8,5 +8,9 @@ import { isESClientError } from '../../errors'; export const isElasticsearchItemNotFoundError = (error: Error): boolean => { - return isESClientError(error) && error.meta.statusCode === 404 && error.meta.body.found === false; + return ( + isESClientError(error) && + error.meta.statusCode === 404 && + (error.meta.body as any).found === false + ); }; diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/install.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/install.ts index 5b85a25f14659..42e1bff6ab370 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ingest_pipeline/install.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { TransportRequestOptions } from '@elastic/elasticsearch/lib/Transport'; +import type { TransportRequestOptions } from '@elastic/elasticsearch'; import type { ElasticsearchClient, SavedObjectsClientContract } from 'src/core/server'; import { ElasticsearchAssetType } from '../../../../types'; diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/ml_model/install.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ml_model/install.ts index d6de59507fbf7..d97081f15aca3 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/ml_model/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/ml_model/install.ts @@ -6,7 +6,7 @@ */ import type { ElasticsearchClient, SavedObjectsClientContract } from 'kibana/server'; -import { ResponseError } from '@elastic/elasticsearch/lib/errors'; +import { errors } from '@elastic/elasticsearch'; import { saveInstalledEsRefs } from '../../packages/install'; import { getPathParts } from '../../archive'; @@ -71,12 +71,13 @@ async function handleMlModelInstall({ model_id: mlModel.installationName, defer_definition_decompression: true, timeout: '45s', + // @ts-expect-error expects an object not a string body: mlModel.content, }); } catch (err) { // swallow the error if the ml model already exists. const isAlreadyExistError = - err instanceof ResponseError && + err instanceof errors.ResponseError && err?.body?.error?.type === 'resource_already_exists_exception'; if (!isAlreadyExistError) { throw err; diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.test.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.test.ts index 552e486552a78..2e6365a9913e4 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.test.ts @@ -5,6 +5,7 @@ * 2.0. */ import { elasticsearchServiceMock } from 'src/core/server/mocks'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { createAppContextStartContractMock } from '../../../../mocks'; import { appContextService } from '../../../../services'; @@ -49,14 +50,13 @@ describe('EPM install', () => { packageName: pkg.name, }); - const sentTemplate = esClient.indices.putIndexTemplate.mock.calls[0][0]!.body as Record< - string, - any - >; + const sentTemplate = ( + esClient.indices.putIndexTemplate.mock.calls[0][0] as estypes.IndicesPutIndexTemplateRequest + ).body; expect(sentTemplate).toBeDefined(); - expect(sentTemplate.priority).toBe(templatePriorityDatasetIsPrefixUnset); - expect(sentTemplate.index_patterns).toEqual([templateIndexPatternDatasetIsPrefixUnset]); + expect(sentTemplate?.priority).toBe(templatePriorityDatasetIsPrefixUnset); + expect(sentTemplate?.index_patterns).toEqual([templateIndexPatternDatasetIsPrefixUnset]); }); it('tests installPackage to use correct priority and index_patterns for data stream with dataset_is_prefix set to false', async () => { @@ -90,14 +90,13 @@ describe('EPM install', () => { packageName: pkg.name, }); - const sentTemplate = esClient.indices.putIndexTemplate.mock.calls[0][0]!.body as Record< - string, - any - >; + const sentTemplate = ( + esClient.indices.putIndexTemplate.mock.calls[0][0] as estypes.IndicesPutIndexTemplateRequest + ).body; expect(sentTemplate).toBeDefined(); - expect(sentTemplate.priority).toBe(templatePriorityDatasetIsPrefixFalse); - expect(sentTemplate.index_patterns).toEqual([templateIndexPatternDatasetIsPrefixFalse]); + expect(sentTemplate?.priority).toBe(templatePriorityDatasetIsPrefixFalse); + expect(sentTemplate?.index_patterns).toEqual([templateIndexPatternDatasetIsPrefixFalse]); }); it('tests installPackage to use correct priority and index_patterns for data stream with dataset_is_prefix set to true', async () => { @@ -130,14 +129,14 @@ describe('EPM install', () => { packageVersion: pkg.version, packageName: pkg.name, }); - const sentTemplate = esClient.indices.putIndexTemplate.mock.calls[0][0]!.body as Record< - string, - any - >; + + const sentTemplate = ( + esClient.indices.putIndexTemplate.mock.calls[0][0] as estypes.IndicesPutIndexTemplateRequest + ).body; expect(sentTemplate).toBeDefined(); - expect(sentTemplate.priority).toBe(templatePriorityDatasetIsPrefixTrue); - expect(sentTemplate.index_patterns).toEqual([templateIndexPatternDatasetIsPrefixTrue]); + expect(sentTemplate?.priority).toBe(templatePriorityDatasetIsPrefixTrue); + expect(sentTemplate?.index_patterns).toEqual([templateIndexPatternDatasetIsPrefixTrue]); }); it('tests installPackage remove the aliases property if the property existed', async () => { @@ -181,18 +180,16 @@ describe('EPM install', () => { packageName: pkg.name, }); - const removeAliases = esClient.indices.putIndexTemplate.mock.calls[0][0]!.body as Record< - string, - any - >; - expect(removeAliases.template.aliases).not.toBeDefined(); + const removeAliases = ( + esClient.indices.putIndexTemplate.mock.calls[0][0] as estypes.IndicesPutIndexTemplateRequest + ).body; + expect(removeAliases?.template?.aliases).not.toBeDefined(); - const sentTemplate = esClient.indices.putIndexTemplate.mock.calls[1][0]!.body as Record< - string, - any - >; + const sentTemplate = ( + esClient.indices.putIndexTemplate.mock.calls[1][0] as estypes.IndicesPutIndexTemplateRequest + ).body; expect(sentTemplate).toBeDefined(); - expect(sentTemplate.priority).toBe(templatePriorityDatasetIsPrefixUnset); - expect(sentTemplate.index_patterns).toEqual([templateIndexPatternDatasetIsPrefixUnset]); + expect(sentTemplate?.priority).toBe(templatePriorityDatasetIsPrefixUnset); + expect(sentTemplate?.index_patterns).toEqual([templateIndexPatternDatasetIsPrefixUnset]); }); }); diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts index 9dae415838890..67b57dea6e310 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts @@ -192,7 +192,6 @@ function putComponentTemplate( const { name, body, create = false } = params; return { clusterPromise: esClient.cluster.putComponentTemplate( - // @ts-expect-error body is missing required key `settings`. TemplateMapEntry has settings *or* mappings { name, body, create }, { ignore: [404] } ), diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts index 44d633d5f6e53..16cb4a29bcc7e 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts @@ -505,7 +505,7 @@ const updateExistingDataStream = async ({ try { await esClient.indices.putSettings({ index: dataStreamName, - body: { settings: { default_pipeline: settings.index.default_pipeline } }, + body: { default_pipeline: settings.index.default_pipeline }, }); } catch (err) { throw new Error(`could not update index template settings for ${dataStreamName}`); diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/install.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/install.ts index 7d62c0ef41c8d..93181d4f26d02 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/install.ts @@ -6,7 +6,7 @@ */ import type { ElasticsearchClient, SavedObjectsClientContract } from 'kibana/server'; -import { ResponseError } from '@elastic/elasticsearch/lib/errors'; +import { errors } from '@elastic/elasticsearch'; import { saveInstalledEsRefs } from '../../packages/install'; import { getPathParts } from '../../archive'; @@ -129,7 +129,7 @@ async function handleTransformInstall({ } catch (err) { // swallow the error if the transform already exists. const isAlreadyExistError = - err instanceof ResponseError && + err instanceof errors.ResponseError && err?.body?.error?.type === 'resource_already_exists_exception'; if (!isAlreadyExistError) { throw err; diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/transform.test.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/transform.test.ts index 34dcd5427d655..5f6f64576ad64 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/transform.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/transform/transform.test.ts @@ -18,7 +18,7 @@ jest.mock('./common', () => { }; }); -import { ResponseError } from '@elastic/elasticsearch/lib/errors'; +import { errors } from '@elastic/elasticsearch'; import type { DeeplyMockedKeys } from '@kbn/utility-types/jest'; import type { ElasticsearchClient, SavedObject, SavedObjectsClientContract } from 'kibana/server'; @@ -518,7 +518,7 @@ describe('test transform install', () => { esClient.transport.request.mockImplementationOnce(() => elasticsearchClientMock.createErrorTransportRequestPromise( - new ResponseError( + new errors.ResponseError( elasticsearchClientMock.createApiResponse({ statusCode: 400, body: { error: { type: 'resource_already_exists_exception' } }, diff --git a/x-pack/plugins/index_lifecycle_management/server/plugin.ts b/x-pack/plugins/index_lifecycle_management/server/plugin.ts index f511f837b8074..08b1033371ad5 100644 --- a/x-pack/plugins/index_lifecycle_management/server/plugin.ts +++ b/x-pack/plugins/index_lifecycle_management/server/plugin.ts @@ -31,11 +31,10 @@ const indexLifecycleDataEnricher = async ( } = await client.asCurrentUser.ilm.explainLifecycle({ index: '*', }); - + // @ts-expect-error IndexLifecyclePolicy is not compatible with IlmExplainLifecycleResponse return indicesList.map((index: IndexWithoutIlm) => { return { ...index, - // @ts-expect-error @elastic/elasticsearch https://github.com/elastic/elasticsearch-specification/issues/531 ilm: { ...(ilmIndicesData[index.name] || {}) }, }; }); diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_create_route.ts b/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_create_route.ts index bc27a3b909c85..5ac37f4eeb215 100644 --- a/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_create_route.ts +++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_create_route.ts @@ -21,7 +21,7 @@ async function createPolicy( ignore: [404], }; - return client.ilm.putLifecycle({ policy: name, body }, options); + return client.ilm.putLifecycle({ name, body }, options); } /** diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_delete_route.ts b/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_delete_route.ts index 069adc139a86d..eed36962a78e5 100644 --- a/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_delete_route.ts +++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_delete_route.ts @@ -17,8 +17,7 @@ async function deletePolicies(client: ElasticsearchClient, policyName: string): ignore: [404], }; - // @ts-expect-error @elastic/elasticsearch DeleteSnapshotLifecycleRequest.policy_id is required - return client.ilm.deleteLifecycle({ policy: policyName }, options); + return client.ilm.deleteLifecycle({ name: policyName }, options); } const paramsSchema = schema.object({ diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_fetch_route.ts b/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_fetch_route.ts index 5c65ff9f6a14b..8cb96e4af0bf3 100644 --- a/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_fetch_route.ts +++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/policies/register_fetch_route.ts @@ -6,7 +6,7 @@ */ import { ElasticsearchClient } from 'kibana/server'; -import { ApiResponse } from '@elastic/elasticsearch'; +import type { TransportResult } from '@elastic/elasticsearch'; import { PolicyFromES, SerializedPolicy } from '../../../../common/types'; import { RouteDependencies } from '../../../types'; @@ -46,7 +46,7 @@ function formatPolicies(policiesMap: PoliciesMap): PolicyFromES[] { }, []); } -async function fetchPolicies(client: ElasticsearchClient): Promise> { +async function fetchPolicies(client: ElasticsearchClient): Promise> { const options = { // we allow 404 since they may have no policies ignore: [404], diff --git a/x-pack/plugins/index_lifecycle_management/server/routes/api/snapshot_repositories/register_fetch_route.ts b/x-pack/plugins/index_lifecycle_management/server/routes/api/snapshot_repositories/register_fetch_route.ts index f1fb987c41911..8787be8e936ba 100644 --- a/x-pack/plugins/index_lifecycle_management/server/routes/api/snapshot_repositories/register_fetch_route.ts +++ b/x-pack/plugins/index_lifecycle_management/server/routes/api/snapshot_repositories/register_fetch_route.ts @@ -29,7 +29,7 @@ export const registerFetchRoute = ({ router, license }: RouteDependencies) => { try { const esResult = await ctx.core.elasticsearch.client.asCurrentUser.snapshot.getRepository({ - repository: '*', + name: '*', }); const repos: ListSnapshotReposResponse = { repositories: Object.keys(esResult.body), diff --git a/x-pack/plugins/index_management/server/lib/fetch_indices.ts b/x-pack/plugins/index_management/server/lib/fetch_indices.ts index f78e666ddfc5f..1dd27dff98c16 100644 --- a/x-pack/plugins/index_management/server/lib/fetch_indices.ts +++ b/x-pack/plugins/index_management/server/lib/fetch_indices.ts @@ -54,7 +54,6 @@ async function fetchIndicesCall( aliases: aliases.length ? aliases : 'none', // @ts-expect-error @elastic/elasticsearch https://github.com/elastic/elasticsearch-specification/issues/532 hidden: index.settings.index.hidden === 'true', - // @ts-expect-error @elastic/elasticsearch https://github.com/elastic/elasticsearch-specification/issues/532 data_stream: index.data_stream!, }); } diff --git a/x-pack/plugins/index_management/server/routes/api/component_templates/register_update_route.ts b/x-pack/plugins/index_management/server/routes/api/component_templates/register_update_route.ts index 464d73790af2a..c2235b9eb85ab 100644 --- a/x-pack/plugins/index_management/server/routes/api/component_templates/register_update_route.ts +++ b/x-pack/plugins/index_management/server/routes/api/component_templates/register_update_route.ts @@ -6,7 +6,7 @@ */ import { schema } from '@kbn/config-schema'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { RouteDependencies } from '../../../types'; import { addBasePath } from '../index'; diff --git a/x-pack/plugins/index_management/server/routes/api/stats/register_stats_route.ts b/x-pack/plugins/index_management/server/routes/api/stats/register_stats_route.ts index 7458b98f5092f..3335913b81071 100644 --- a/x-pack/plugins/index_management/server/routes/api/stats/register_stats_route.ts +++ b/x-pack/plugins/index_management/server/routes/api/stats/register_stats_route.ts @@ -6,7 +6,7 @@ */ import { schema } from '@kbn/config-schema'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { RouteDependencies } from '../../../types'; import { addBasePath } from '../index'; diff --git a/x-pack/plugins/index_management/server/routes/api/templates/lib.ts b/x-pack/plugins/index_management/server/routes/api/templates/lib.ts index ec8916b0b8d07..413e73ff93d5f 100644 --- a/x-pack/plugins/index_management/server/routes/api/templates/lib.ts +++ b/x-pack/plugins/index_management/server/routes/api/templates/lib.ts @@ -51,7 +51,6 @@ export const saveTemplate = async ({ return await client.asCurrentUser.indices.putTemplate({ name: template.name, - // @ts-expect-error @elastic/elasticsearch https://github.com/elastic/elasticsearch-specification/issues/533 order, body: { index_patterns, diff --git a/x-pack/plugins/index_management/server/routes/api/templates/register_simulate_route.ts b/x-pack/plugins/index_management/server/routes/api/templates/register_simulate_route.ts index cd363cbd7d003..e45d86f3e2b27 100644 --- a/x-pack/plugins/index_management/server/routes/api/templates/register_simulate_route.ts +++ b/x-pack/plugins/index_management/server/routes/api/templates/register_simulate_route.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { schema, TypeOf } from '@kbn/config-schema'; import { RouteDependencies } from '../../../types'; @@ -31,7 +31,7 @@ export function registerSimulateRoute({ router, lib: { handleEsError } }: RouteD // Issue: https://github.com/elastic/elasticsearch/issues/59152 index_patterns: ['a_fake_index_pattern_that_wont_match_any_indices'], }, - }); + } as estypes.IndicesSimulateTemplateRequest); return response.ok({ body: templatePreview }); } catch (error) { diff --git a/x-pack/plugins/infra/common/log_sources/resolved_log_source_configuration.ts b/x-pack/plugins/infra/common/log_sources/resolved_log_source_configuration.ts index 567acf1fc4134..c6bc10901fcb8 100644 --- a/x-pack/plugins/infra/common/log_sources/resolved_log_source_configuration.ts +++ b/x-pack/plugins/infra/common/log_sources/resolved_log_source_configuration.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { DataView, DataViewsContract } from '../../../../../src/plugins/data_views/common'; import { ObjectEntries } from '../utility_types'; import { ResolveLogSourceConfigurationError } from './errors'; diff --git a/x-pack/plugins/infra/common/search_strategies/log_entries/log_entries.ts b/x-pack/plugins/infra/common/search_strategies/log_entries/log_entries.ts index cc6d3fbe585e0..4e115cda6a8e6 100644 --- a/x-pack/plugins/infra/common/search_strategies/log_entries/log_entries.ts +++ b/x-pack/plugins/infra/common/search_strategies/log_entries/log_entries.ts @@ -6,7 +6,7 @@ */ import * as rt from 'io-ts'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { logSourceColumnConfigurationRT } from '../../log_sources/log_source_configuration'; import { logEntryAfterCursorRT, diff --git a/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_chart.test.tsx b/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_chart.test.tsx index 5aafd9b613d99..ec97d01a1cd6f 100644 --- a/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_chart.test.tsx +++ b/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_chart.test.tsx @@ -54,6 +54,7 @@ describe('ExpressionChart', () => { metricAlias: 'metricbeat-*', inventoryDefaultView: 'host', metricsExplorerDefaultView: 'host', + // @ts-ignore fields: { timestamp: '@timestamp', container: 'container.id', diff --git a/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_chart.tsx b/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_chart.tsx index b176e3907228c..6a68c01e26017 100644 --- a/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_chart.tsx +++ b/x-pack/plugins/infra/public/alerting/metric_threshold/components/expression_chart.tsx @@ -7,10 +7,11 @@ import React, { useMemo, useCallback } from 'react'; import { Axis, Chart, niceTimeFormatter, Position, Settings } from '@elastic/charts'; -import { first, last } from 'lodash'; import { EuiText } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { DataViewBase } from '@kbn/es-query'; +import { first, last } from 'lodash'; + import { MetricsSourceConfiguration } from '../../../../common/metrics_sources'; import { Color } from '../../../../common/color_palette'; import { MetricsExplorerRow, MetricsExplorerAggregation } from '../../../../common/http_api'; diff --git a/x-pack/plugins/infra/public/containers/logs/log_analysis/api/validate_datasets.ts b/x-pack/plugins/infra/public/containers/logs/log_analysis/api/validate_datasets.ts index 9de6e574ecb5b..94bb3d8e66cbf 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_analysis/api/validate_datasets.ts +++ b/x-pack/plugins/infra/public/containers/logs/log_analysis/api/validate_datasets.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { HttpHandler } from 'src/core/public'; import { LOG_ANALYSIS_VALIDATE_DATASETS_PATH, diff --git a/x-pack/plugins/infra/public/containers/logs/log_analysis/api/validate_indices.ts b/x-pack/plugins/infra/public/containers/logs/log_analysis/api/validate_indices.ts index a211fecc807fa..8a9f960b54afa 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_analysis/api/validate_indices.ts +++ b/x-pack/plugins/infra/public/containers/logs/log_analysis/api/validate_indices.ts @@ -6,7 +6,7 @@ */ import type { HttpHandler } from 'src/core/public'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { LOG_ANALYSIS_VALIDATE_INDICES_PATH, diff --git a/x-pack/plugins/infra/public/containers/logs/log_analysis/log_analysis_module_types.ts b/x-pack/plugins/infra/public/containers/logs/log_analysis/log_analysis_module_types.ts index 4ae99b95cfff8..4ff8c0c3c08e0 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_analysis/log_analysis_module_types.ts +++ b/x-pack/plugins/infra/public/containers/logs/log_analysis/log_analysis_module_types.ts @@ -6,7 +6,7 @@ */ import type { HttpHandler } from 'src/core/public'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ValidateLogEntryDatasetsResponsePayload, ValidationIndicesResponsePayload, diff --git a/x-pack/plugins/infra/public/containers/logs/log_analysis/modules/log_entry_categories/module_descriptor.ts b/x-pack/plugins/infra/public/containers/logs/log_analysis/modules/log_entry_categories/module_descriptor.ts index 6823ed173a740..9ef41042302a1 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_analysis/modules/log_entry_categories/module_descriptor.ts +++ b/x-pack/plugins/infra/public/containers/logs/log_analysis/modules/log_entry_categories/module_descriptor.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { i18n } from '@kbn/i18n'; import type { HttpHandler } from 'src/core/public'; import { diff --git a/x-pack/plugins/infra/public/containers/logs/log_analysis/modules/log_entry_categories/use_log_entry_categories_module.tsx b/x-pack/plugins/infra/public/containers/logs/log_analysis/modules/log_entry_categories/use_log_entry_categories_module.tsx index 99d4ab4becee5..433a24cffd937 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_analysis/modules/log_entry_categories/use_log_entry_categories_module.tsx +++ b/x-pack/plugins/infra/public/containers/logs/log_analysis/modules/log_entry_categories/use_log_entry_categories_module.tsx @@ -6,7 +6,7 @@ */ import createContainer from 'constate'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { useMemo } from 'react'; import { useLogAnalysisModule } from '../../log_analysis_module'; import { useLogAnalysisModuleConfiguration } from '../../log_analysis_module_configuration'; diff --git a/x-pack/plugins/infra/public/containers/logs/log_analysis/modules/log_entry_rate/module_descriptor.ts b/x-pack/plugins/infra/public/containers/logs/log_analysis/modules/log_entry_rate/module_descriptor.ts index c4c939d0ebb9d..214faaf9a3012 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_analysis/modules/log_entry_rate/module_descriptor.ts +++ b/x-pack/plugins/infra/public/containers/logs/log_analysis/modules/log_entry_rate/module_descriptor.ts @@ -6,7 +6,7 @@ */ import { i18n } from '@kbn/i18n'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { HttpHandler } from 'src/core/public'; import { bucketSpan, diff --git a/x-pack/plugins/infra/public/containers/logs/log_analysis/modules/log_entry_rate/use_log_entry_rate_module.tsx b/x-pack/plugins/infra/public/containers/logs/log_analysis/modules/log_entry_rate/use_log_entry_rate_module.tsx index f3e8f7e777597..46587969ca2ab 100644 --- a/x-pack/plugins/infra/public/containers/logs/log_analysis/modules/log_entry_rate/use_log_entry_rate_module.tsx +++ b/x-pack/plugins/infra/public/containers/logs/log_analysis/modules/log_entry_rate/use_log_entry_rate_module.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import createContainer from 'constate'; import { useMemo } from 'react'; import { ModuleSourceConfiguration } from '../../log_analysis_module_types'; diff --git a/x-pack/plugins/infra/public/lib/lib.ts b/x-pack/plugins/infra/public/lib/lib.ts index 4541eb6518788..97a3f8eabbe4e 100644 --- a/x-pack/plugins/infra/public/lib/lib.ts +++ b/x-pack/plugins/infra/public/lib/lib.ts @@ -124,7 +124,7 @@ export enum InfraWaffleMapRuleOperator { } export interface InfraWaffleMapOptions { - fields?: MetricsSourceConfigurationProperties['fields'] | null; + fields?: Omit | null; formatter: InfraFormatterType; formatTemplate: string; metric: SnapshotMetricInput; diff --git a/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/hooks/use_metrics_explorer_data.ts b/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/hooks/use_metrics_explorer_data.ts index 6b7e98912fd49..c0d0b15217df3 100644 --- a/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/hooks/use_metrics_explorer_data.ts +++ b/x-pack/plugins/infra/public/pages/metrics/metrics_explorer/hooks/use_metrics_explorer_data.ts @@ -6,9 +6,10 @@ */ import DateMath from '@elastic/datemath'; -import { isEqual } from 'lodash'; import { useEffect, useState } from 'react'; import { DataViewBase } from '@kbn/es-query'; +import { isEqual } from 'lodash'; + import { MetricsSourceConfigurationProperties } from '../../../../../common/metrics_sources'; import { MetricsExplorerResponse, diff --git a/x-pack/plugins/infra/public/utils/logs_overview_fetchers.ts b/x-pack/plugins/infra/public/utils/logs_overview_fetchers.ts index c813bd3dae781..44f65b9e8071a 100644 --- a/x-pack/plugins/infra/public/utils/logs_overview_fetchers.ts +++ b/x-pack/plugins/infra/public/utils/logs_overview_fetchers.ts @@ -6,7 +6,7 @@ */ import { encode } from 'rison-node'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { FetchData, FetchDataParams, LogsFetchDataResponse } from '../../../observability/public'; import { DEFAULT_SOURCE_ID } from '../../common/constants'; import { callFetchLogSourceConfigurationAPI } from '../containers/logs/log_source/api/fetch_log_source_configuration'; diff --git a/x-pack/plugins/infra/server/lib/adapters/framework/adapter_types.ts b/x-pack/plugins/infra/server/lib/adapters/framework/adapter_types.ts index 4d4a0ff6320bd..00c52dae7ed3c 100644 --- a/x-pack/plugins/infra/server/lib/adapters/framework/adapter_types.ts +++ b/x-pack/plugins/infra/server/lib/adapters/framework/adapter_types.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Lifecycle } from '@hapi/hapi'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; import { JsonArray, JsonValue } from '@kbn/utility-types'; diff --git a/x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts b/x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts index b1ea0ce21b3c1..0c0284e328dd3 100644 --- a/x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts +++ b/x-pack/plugins/infra/server/lib/adapters/framework/kibana_framework_adapter.ts @@ -5,13 +5,8 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; -import { - IndicesExistsAlias, - IndicesGet, - MlGetBuckets, -} from '@elastic/elasticsearch/api/requestParams'; -import { TransportRequestParams } from '@elastic/elasticsearch/lib/Transport'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { TransportRequestParams } from '@elastic/elasticsearch'; import { ElasticsearchClient, SavedObjectsClientContract } from 'src/core/server'; import { CoreSetup, @@ -181,7 +176,7 @@ export class KibanaFramework { case 'indices.existsAlias': apiResult = elasticsearch.client.asCurrentUser.indices.existsAlias({ ...params, - } as IndicesExistsAlias); + } as estypes.IndicesExistsAliasRequest); break; case 'indices.getAlias': apiResult = elasticsearch.client.asCurrentUser.indices.getAlias({ @@ -191,7 +186,7 @@ export class KibanaFramework { case 'indices.get': apiResult = elasticsearch.client.asCurrentUser.indices.get({ ...params, - } as IndicesGet); + } as estypes.IndicesGetRequest); break; case 'transport.request': apiResult = elasticsearch.client.asCurrentUser.transport.request({ @@ -201,7 +196,7 @@ export class KibanaFramework { case 'ml.getBuckets': apiResult = elasticsearch.client.asCurrentUser.ml.getBuckets({ ...params, - } as MlGetBuckets); + } as estypes.MlGetBucketsRequest); break; } return apiResult ? (await apiResult).body : undefined; diff --git a/x-pack/plugins/infra/server/lib/adapters/log_entries/kibana_log_entries_adapter.ts b/x-pack/plugins/infra/server/lib/adapters/log_entries/kibana_log_entries_adapter.ts index 524658559eadf..75a86ae654d6c 100644 --- a/x-pack/plugins/infra/server/lib/adapters/log_entries/kibana_log_entries_adapter.ts +++ b/x-pack/plugins/infra/server/lib/adapters/log_entries/kibana_log_entries_adapter.ts @@ -10,8 +10,8 @@ import { fold, map } from 'fp-ts/lib/Either'; import { constant, identity } from 'fp-ts/lib/function'; import { pipe } from 'fp-ts/lib/pipeable'; import * as runtimeTypes from 'io-ts'; -import { compact } from 'lodash'; import { JsonArray } from '@kbn/utility-types'; +import { compact } from 'lodash'; import type { InfraPluginRequestHandlerContext } from '../../../types'; import { LogEntriesAdapter, @@ -46,7 +46,7 @@ export class InfraKibanaLogEntriesAdapter implements LogEntriesAdapter { const highlightClause = highlightQuery ? { highlight: { - boundary_scanner: 'word', + boundary_scanner: 'word' as const, fields: fields.reduce( (highlightFieldConfigs, fieldName) => ({ ...highlightFieldConfigs, diff --git a/x-pack/plugins/infra/server/lib/adapters/metrics/lib/check_valid_node.ts b/x-pack/plugins/infra/server/lib/adapters/metrics/lib/check_valid_node.ts index f2b7691646e48..a1bff361a8067 100644 --- a/x-pack/plugins/infra/server/lib/adapters/metrics/lib/check_valid_node.ts +++ b/x-pack/plugins/infra/server/lib/adapters/metrics/lib/check_valid_node.ts @@ -17,7 +17,7 @@ export const checkValidNode = async ( allow_no_indices: true, ignore_unavailable: true, index: indexPattern, - terminateAfter: 1, + terminate_after: 1, body: { size: 0, query: { diff --git a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts index 3dd702126735d..26f2ecbc10197 100644 --- a/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts +++ b/x-pack/plugins/infra/server/lib/alerting/inventory_metric_threshold/inventory_metric_threshold_executor.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { first, get, last } from 'lodash'; import { i18n } from '@kbn/i18n'; import { ALERT_REASON, ALERT_RULE_PARAMS } from '@kbn/rule-data-utils'; import moment from 'moment'; +import { first, get, last } from 'lodash'; import { getCustomMetricLabel } from '../../../../common/formatters/get_custom_metric_label'; import { toMetricOpt } from '../../../../common/snapshot_metric_i18n'; import { AlertStates } from './types'; diff --git a/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.test.ts b/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.test.ts index 1f0521070a1e5..e5d8bab948581 100644 --- a/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.test.ts +++ b/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.test.ts @@ -24,7 +24,7 @@ import { GroupedSearchQueryResponse, } from '../../../../common/alerting/logs/log_threshold/types'; import { alertsMock } from '../../../../../alerting/server/mocks'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; // Mocks // const numericField = { diff --git a/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts b/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts index f99f7a96158c3..6d2b074c45bb0 100644 --- a/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts +++ b/x-pack/plugins/infra/server/lib/alerting/log_threshold/log_threshold_executor.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { i18n } from '@kbn/i18n'; import { ALERT_EVALUATION_THRESHOLD, diff --git a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/evaluate_alert.ts b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/evaluate_alert.ts index 5bd7a4947b439..71c18d9f7cf04 100644 --- a/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/evaluate_alert.ts +++ b/x-pack/plugins/infra/server/lib/alerting/metric_threshold/lib/evaluate_alert.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { mapValues, first, last, isNaN, isNumber, isObject, has } from 'lodash'; import moment from 'moment'; import { ElasticsearchClient } from 'kibana/server'; +import { mapValues, first, last, isNaN, isNumber, isObject, has } from 'lodash'; import { isTooManyBucketsPreviewException, TOO_MANY_BUCKETS_PREVIEW_EXCEPTION, @@ -222,6 +222,7 @@ const getMetric: ( return groupedResults; } const { body: result } = await esClient.search({ + // @ts-expect-error buckets_path is not compatible body: searchBody, index, }); diff --git a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/log_entries_domain.ts b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/log_entries_domain.ts index 16209e5e4b684..e7b1624206515 100644 --- a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/log_entries_domain.ts +++ b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/log_entries_domain.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { JsonObject } from '@kbn/utility-types'; import type { InfraPluginRequestHandlerContext } from '../../../types'; diff --git a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/queries/log_entry_datasets.ts b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/queries/log_entry_datasets.ts index 9eae8daa3e74f..4386b6ccef9c1 100644 --- a/x-pack/plugins/infra/server/lib/domains/log_entries_domain/queries/log_entry_datasets.ts +++ b/x-pack/plugins/infra/server/lib/domains/log_entries_domain/queries/log_entry_datasets.ts @@ -6,7 +6,7 @@ */ import * as rt from 'io-ts'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { commonSearchSuccessResponseFieldsRT } from '../../../../utils/elasticsearch_runtime_types'; diff --git a/x-pack/plugins/infra/server/lib/log_analysis/log_entry_anomalies.ts b/x-pack/plugins/infra/server/lib/log_analysis/log_entry_anomalies.ts index 3210f01116f76..aca0483037912 100644 --- a/x-pack/plugins/infra/server/lib/log_analysis/log_entry_anomalies.ts +++ b/x-pack/plugins/infra/server/lib/log_analysis/log_entry_anomalies.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { InfraPluginRequestHandlerContext, InfraRequestHandlerContext } from '../../types'; import { TracingSpan, startTracingSpan } from '../../../common/performance_tracing'; import { fetchMlJob, getLogEntryDatasets } from './common'; diff --git a/x-pack/plugins/infra/server/lib/log_analysis/log_entry_categories_analysis.ts b/x-pack/plugins/infra/server/lib/log_analysis/log_entry_categories_analysis.ts index 7023f7007763c..d1d136c741876 100644 --- a/x-pack/plugins/infra/server/lib/log_analysis/log_entry_categories_analysis.ts +++ b/x-pack/plugins/infra/server/lib/log_analysis/log_entry_categories_analysis.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ElasticsearchClient } from 'src/core/server'; import { compareDatasetsByMaximumAnomalyScore, diff --git a/x-pack/plugins/infra/server/lib/log_analysis/queries/log_entry_category_examples.ts b/x-pack/plugins/infra/server/lib/log_analysis/queries/log_entry_category_examples.ts index 8b05d7c44e3f5..dd68de4e49d34 100644 --- a/x-pack/plugins/infra/server/lib/log_analysis/queries/log_entry_category_examples.ts +++ b/x-pack/plugins/infra/server/lib/log_analysis/queries/log_entry_category_examples.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import * as rt from 'io-ts'; import { commonSearchSuccessResponseFieldsRT } from '../../../utils/elasticsearch_runtime_types'; import { defaultRequestParameters } from './common'; diff --git a/x-pack/plugins/infra/server/lib/log_analysis/queries/log_entry_examples.ts b/x-pack/plugins/infra/server/lib/log_analysis/queries/log_entry_examples.ts index d903225facd57..d6099404daa80 100644 --- a/x-pack/plugins/infra/server/lib/log_analysis/queries/log_entry_examples.ts +++ b/x-pack/plugins/infra/server/lib/log_analysis/queries/log_entry_examples.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import * as rt from 'io-ts'; import { partitionField } from '../../../../common/log_analysis'; import { commonSearchSuccessResponseFieldsRT } from '../../../utils/elasticsearch_runtime_types'; diff --git a/x-pack/plugins/infra/server/routes/log_analysis/validation/datasets.ts b/x-pack/plugins/infra/server/routes/log_analysis/validation/datasets.ts index ef789c1b41349..4237ee2ae9abc 100644 --- a/x-pack/plugins/infra/server/routes/log_analysis/validation/datasets.ts +++ b/x-pack/plugins/infra/server/routes/log_analysis/validation/datasets.ts @@ -6,7 +6,7 @@ */ import Boom from '@hapi/boom'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { InfraBackendLibs } from '../../../lib/infra_types'; import { diff --git a/x-pack/plugins/infra/server/routes/log_sources/configuration.ts b/x-pack/plugins/infra/server/routes/log_sources/configuration.ts index f0d7b18d91a5d..9a92012c21fe4 100644 --- a/x-pack/plugins/infra/server/routes/log_sources/configuration.ts +++ b/x-pack/plugins/infra/server/routes/log_sources/configuration.ts @@ -85,11 +85,13 @@ export const initLogSourceConfigurationRoutes = ({ framework, sources }: InfraBa ? sources.updateSourceConfiguration( requestContext.core.savedObjects.client, sourceId, + // @ts-ignore patchedSourceConfigurationProperties ) : sources.createSourceConfiguration( requestContext.core.savedObjects.client, sourceId, + // @ts-ignore patchedSourceConfigurationProperties )); diff --git a/x-pack/plugins/infra/server/routes/metadata/lib/get_node_info.ts b/x-pack/plugins/infra/server/routes/metadata/lib/get_node_info.ts index 06035ed40adf1..94becdf6d2811 100644 --- a/x-pack/plugins/infra/server/routes/metadata/lib/get_node_info.ts +++ b/x-pack/plugins/infra/server/routes/metadata/lib/get_node_info.ts @@ -55,7 +55,7 @@ export const getNodeInfo = async ( const params = { allow_no_indices: true, ignore_unavailable: true, - terminateAfter: 1, + terminate_after: 1, index: sourceConfiguration.metricAlias, body: { size: 1, diff --git a/x-pack/plugins/infra/server/routes/metadata/lib/get_pod_node_name.ts b/x-pack/plugins/infra/server/routes/metadata/lib/get_pod_node_name.ts index 9bf809ba3b3f4..164d94d9f692f 100644 --- a/x-pack/plugins/infra/server/routes/metadata/lib/get_pod_node_name.ts +++ b/x-pack/plugins/infra/server/routes/metadata/lib/get_pod_node_name.ts @@ -24,7 +24,7 @@ export const getPodNodeName = async ( const params = { allow_no_indices: true, ignore_unavailable: true, - terminateAfter: 1, + terminate_after: 1, index: sourceConfiguration.metricAlias, body: { size: 1, diff --git a/x-pack/plugins/infra/server/routes/metrics_explorer/lib/get_dataset_for_field.ts b/x-pack/plugins/infra/server/routes/metrics_explorer/lib/get_dataset_for_field.ts index be25bbbf022ee..640d62c366726 100644 --- a/x-pack/plugins/infra/server/routes/metrics_explorer/lib/get_dataset_for_field.ts +++ b/x-pack/plugins/infra/server/routes/metrics_explorer/lib/get_dataset_for_field.ts @@ -24,7 +24,7 @@ export const getDatasetForField = async ( const params = { allow_no_indices: true, ignore_unavailable: true, - terminateAfter: 1, + terminate_after: 1, index: indexPattern, body: { query: { diff --git a/x-pack/plugins/infra/server/routes/metrics_sources/index.ts b/x-pack/plugins/infra/server/routes/metrics_sources/index.ts index 0123e4678697c..24ea04e3e14f9 100644 --- a/x-pack/plugins/infra/server/routes/metrics_sources/index.ts +++ b/x-pack/plugins/infra/server/routes/metrics_sources/index.ts @@ -88,11 +88,13 @@ export const initMetricsSourceConfigurationRoutes = (libs: InfraBackendLibs) => ? sources.updateSourceConfiguration( requestContext.core.savedObjects.client, sourceId, + // @ts-ignore patchedSourceConfigurationProperties ) : sources.createSourceConfiguration( requestContext.core.savedObjects.client, sourceId, + // @ts-ignore patchedSourceConfigurationProperties )); diff --git a/x-pack/plugins/infra/server/services/log_entries/log_entries_search_strategy.test.ts b/x-pack/plugins/infra/server/services/log_entries/log_entries_search_strategy.test.ts index 85a1b95cf70aa..b0d2eeb987861 100644 --- a/x-pack/plugins/infra/server/services/log_entries/log_entries_search_strategy.test.ts +++ b/x-pack/plugins/infra/server/services/log_entries/log_entries_search_strategy.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ResponseError } from '@elastic/elasticsearch/lib/errors'; +import { errors } from '@elastic/elasticsearch'; import { of, throwError } from 'rxjs'; import { elasticsearchServiceMock, @@ -230,7 +230,7 @@ describe('LogEntries search strategy', () => { mockDependencies ); - await expect(response.toPromise()).rejects.toThrowError(ResponseError); + await expect(response.toPromise()).rejects.toThrowError(errors.ResponseError); }); it('forwards cancellation to the underlying search strategy', async () => { @@ -307,7 +307,7 @@ const createEsSearchStrategyMock = (esSearchResponse: IEsSearchResponse) => ({ return of(esSearchResponse); } else { return throwError( - new ResponseError({ + new errors.ResponseError({ body: {}, headers: {}, meta: {} as any, diff --git a/x-pack/plugins/infra/server/services/log_entries/log_entries_search_strategy.ts b/x-pack/plugins/infra/server/services/log_entries/log_entries_search_strategy.ts index 651758d9cd976..b401b68d0e3d3 100644 --- a/x-pack/plugins/infra/server/services/log_entries/log_entries_search_strategy.ts +++ b/x-pack/plugins/infra/server/services/log_entries/log_entries_search_strategy.ts @@ -113,7 +113,6 @@ export const logEntriesSearchStrategyProvider = ({ messageFormattingRules, ]): IEsSearchRequest => { return { - // @ts-expect-error @elastic/elasticsearch declares indices_boost as Record params: createGetLogEntriesQuery( indices, params.startTimestamp, diff --git a/x-pack/plugins/infra/server/services/log_entries/log_entry_search_strategy.test.ts b/x-pack/plugins/infra/server/services/log_entries/log_entry_search_strategy.test.ts index ec3d4aa52a6b5..1f03878ba6feb 100644 --- a/x-pack/plugins/infra/server/services/log_entries/log_entry_search_strategy.test.ts +++ b/x-pack/plugins/infra/server/services/log_entries/log_entry_search_strategy.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ResponseError } from '@elastic/elasticsearch/lib/errors'; +import { errors } from '@elastic/elasticsearch'; import { of, throwError } from 'rxjs'; import { elasticsearchServiceMock, @@ -196,7 +196,7 @@ describe('LogEntry search strategy', () => { mockDependencies ); - await expect(response.toPromise()).rejects.toThrowError(ResponseError); + await expect(response.toPromise()).rejects.toThrowError(errors.ResponseError); }); it('forwards cancellation to the underlying search strategy', async () => { @@ -262,7 +262,7 @@ const createEsSearchStrategyMock = (esSearchResponse: IEsSearchResponse) => ({ return of(esSearchResponse); } else { return throwError( - new ResponseError({ + new errors.ResponseError({ body: {}, headers: {}, meta: {} as any, diff --git a/x-pack/plugins/infra/server/services/log_entries/log_entry_search_strategy.ts b/x-pack/plugins/infra/server/services/log_entries/log_entry_search_strategy.ts index 1f0f13eeb6ca9..565318578f990 100644 --- a/x-pack/plugins/infra/server/services/log_entries/log_entry_search_strategy.ts +++ b/x-pack/plugins/infra/server/services/log_entries/log_entry_search_strategy.ts @@ -84,7 +84,6 @@ export const logEntrySearchStrategyProvider = ({ tiebreakerField, runtimeMappings, }): IEsSearchRequest => ({ - // @ts-expect-error `Field` is not assignable to `SearchRequest.docvalue_fields` params: createGetLogEntryQuery( indices, params.logEntryId, diff --git a/x-pack/plugins/infra/server/services/log_entries/queries/log_entries.ts b/x-pack/plugins/infra/server/services/log_entries/queries/log_entries.ts index 9022195dce85d..6ca6d5ecd0191 100644 --- a/x-pack/plugins/infra/server/services/log_entries/queries/log_entries.ts +++ b/x-pack/plugins/infra/server/services/log_entries/queries/log_entries.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import * as rt from 'io-ts'; import { LogEntryAfterCursor, @@ -53,7 +53,6 @@ export const createGetLogEntriesQuery = ( }, }, fields, - // @ts-expect-error @elastic/elasticsearch doesn't declare "runtime_mappings" property runtime_mappings: runtimeMappings, _source: false, ...createSortClause(sortDirection, timestampField, tiebreakerField), @@ -87,7 +86,7 @@ const createHighlightClause = (highlightQuery: JsonObject | undefined, fields: s highlightQuery ? { highlight: { - boundary_scanner: 'word', + boundary_scanner: 'word' as const, fields: fields.reduce( (highlightFieldConfigs, fieldName) => ({ ...highlightFieldConfigs, diff --git a/x-pack/plugins/infra/server/services/log_entries/queries/log_entry.ts b/x-pack/plugins/infra/server/services/log_entries/queries/log_entry.ts index 8da2f1d685db3..856f8b1af9770 100644 --- a/x-pack/plugins/infra/server/services/log_entries/queries/log_entry.ts +++ b/x-pack/plugins/infra/server/services/log_entries/queries/log_entry.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import * as rt from 'io-ts'; import { jsonArrayRT } from '../../../../common/typed_json'; import { @@ -32,7 +32,6 @@ export const createGetLogEntryQuery = ( }, }, fields: ['*'], - // @ts-expect-error @elastic/elasticsearch doesn't declare "runtime_mappings" property runtime_mappings: runtimeMappings, sort: [{ [timestampField]: 'desc' }, { [tiebreakerField]: 'desc' }], _source: false, diff --git a/x-pack/plugins/infra/server/utils/get_all_composite_data.ts b/x-pack/plugins/infra/server/utils/get_all_composite_data.ts index 1ab290796e36d..b5b4b731472c4 100644 --- a/x-pack/plugins/infra/server/utils/get_all_composite_data.ts +++ b/x-pack/plugins/infra/server/utils/get_all_composite_data.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ApiResponse } from '@elastic/elasticsearch/lib/Transport'; +import { TransportResult } from '@elastic/elasticsearch'; import { InfraDatabaseSearchResponse } from '../lib/adapters/framework'; export const getAllCompositeData = async < @@ -15,7 +15,7 @@ export const getAllCompositeData = async < >( esClientSearch: ( options: Options - ) => Promise>>, + ) => Promise>>, options: Options, bucketSelector: (response: InfraDatabaseSearchResponse<{}, Aggregation>) => Bucket[], onAfterKey: (options: Options, response: InfraDatabaseSearchResponse<{}, Aggregation>) => Options, diff --git a/x-pack/plugins/ingest_pipelines/common/lib/pipeline_serialization.ts b/x-pack/plugins/ingest_pipelines/common/lib/pipeline_serialization.ts index d2669e7c0012b..248797c652c6a 100644 --- a/x-pack/plugins/ingest_pipelines/common/lib/pipeline_serialization.ts +++ b/x-pack/plugins/ingest_pipelines/common/lib/pipeline_serialization.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Pipeline, Processor } from '../types'; export function deserializePipelines(pipelinesByName: { diff --git a/x-pack/plugins/ingest_pipelines/server/routes/api/privileges.ts b/x-pack/plugins/ingest_pipelines/server/routes/api/privileges.ts index 5368b59b35a41..a2882fd7855d6 100644 --- a/x-pack/plugins/ingest_pipelines/server/routes/api/privileges.ts +++ b/x-pack/plugins/ingest_pipelines/server/routes/api/privileges.ts @@ -41,6 +41,7 @@ export const registerPrivilegesRoute = ({ router, config }: RouteDependencies) = const { body: { has_all_requested: hasAllPrivileges, cluster }, } = await clusterClient.asCurrentUser.security.hasPrivileges({ + // @ts-expect-error @elastic/elasticsearch SecurityClusterPrivilege doesn’t contain all the priviledges body: { cluster: APP_CLUSTER_REQUIRED_PRIVILEGES }, }); diff --git a/x-pack/plugins/ingest_pipelines/server/routes/api/simulate.ts b/x-pack/plugins/ingest_pipelines/server/routes/api/simulate.ts index c133b9237102a..c6d628294a734 100644 --- a/x-pack/plugins/ingest_pipelines/server/routes/api/simulate.ts +++ b/x-pack/plugins/ingest_pipelines/server/routes/api/simulate.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { schema } from '@kbn/config-schema'; import { API_BASE_PATH } from '../../../common/constants'; @@ -38,7 +38,7 @@ export const registerSimulateRoute = ({ verbose, body: { pipeline, - docs: documents as estypes.IngestSimulatePipelineDocument[], + docs: documents as estypes.IngestSimulateDocument[], }, }); diff --git a/x-pack/plugins/lens/server/routes/existing_fields.ts b/x-pack/plugins/lens/server/routes/existing_fields.ts index f35b0a7f23179..704b248faeadb 100644 --- a/x-pack/plugins/lens/server/routes/existing_fields.ts +++ b/x-pack/plugins/lens/server/routes/existing_fields.ts @@ -6,7 +6,8 @@ */ import Boom from '@hapi/boom'; -import { errors, estypes } from '@elastic/elasticsearch'; +import { errors } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { schema } from '@kbn/config-schema'; import { RequestHandlerContext, ElasticsearchClient } from 'src/core/server'; import { CoreSetup, Logger } from 'src/core/server'; diff --git a/x-pack/plugins/lens/server/routes/field_stats.ts b/x-pack/plugins/lens/server/routes/field_stats.ts index 88e8e600aa906..9e48c00b9d8cb 100644 --- a/x-pack/plugins/lens/server/routes/field_stats.ts +++ b/x-pack/plugins/lens/server/routes/field_stats.ts @@ -4,7 +4,8 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { errors, estypes } from '@elastic/elasticsearch'; +import { errors } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import DateMath from '@elastic/datemath'; import { schema } from '@kbn/config-schema'; import { CoreSetup } from 'src/core/server'; diff --git a/x-pack/plugins/license_management/server/lib/permissions.ts b/x-pack/plugins/license_management/server/lib/permissions.ts index 517854fad8e83..06395fb6302b6 100644 --- a/x-pack/plugins/license_management/server/lib/permissions.ts +++ b/x-pack/plugins/license_management/server/lib/permissions.ts @@ -20,14 +20,12 @@ export async function getPermissions({ isSecurityEnabled, client }: GetPermissio }; } - const options = { - body: { - cluster: ['manage'], // License management requires "manage" cluster privileges - }, - }; - try { - const { body: response } = await client.asCurrentUser.security.hasPrivileges(options); + const { body: response } = await client.asCurrentUser.security.hasPrivileges({ + body: { + cluster: ['manage'], // License management requires "manage" cluster privileges + }, + }); return { hasPermission: response.cluster.manage, }; diff --git a/x-pack/plugins/licensing/server/plugin.test.ts b/x-pack/plugins/licensing/server/plugin.test.ts index 1fe4bbf238e19..71a98098bb0f5 100644 --- a/x-pack/plugins/licensing/server/plugin.test.ts +++ b/x-pack/plugins/licensing/server/plugin.test.ts @@ -6,7 +6,7 @@ */ import { take, toArray } from 'rxjs/operators'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import moment from 'moment'; import { LicenseType } from '../common/types'; import { ElasticsearchError } from './types'; @@ -102,9 +102,6 @@ describe('licensing plugin', () => { await license$.pipe(take(1)).toPromise(); expect(esClient.asInternalUser.xpack.info).toHaveBeenCalledTimes(1); - expect(esClient.asInternalUser.xpack.info).toHaveBeenCalledWith({ - accept_enterprise: true, - }); }); it('observable receives updated licenses', async () => { diff --git a/x-pack/plugins/licensing/server/plugin.ts b/x-pack/plugins/licensing/server/plugin.ts index 00d2ae602fcae..83379fe48ac9e 100644 --- a/x-pack/plugins/licensing/server/plugin.ts +++ b/x-pack/plugins/licensing/server/plugin.ts @@ -10,7 +10,7 @@ import moment from 'moment'; import { createHash } from 'crypto'; import stringify from 'json-stable-stringify'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { MaybePromise } from '@kbn/utility-types'; import { isPromise } from '@kbn/std'; import { diff --git a/x-pack/plugins/lists/server/schemas/common/get_shard.mock.ts b/x-pack/plugins/lists/server/schemas/common/get_shard.mock.ts index 43511a748ba1a..e7a887d6ca354 100644 --- a/x-pack/plugins/lists/server/schemas/common/get_shard.mock.ts +++ b/x-pack/plugins/lists/server/schemas/common/get_shard.mock.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; export const getShardMock = (): estypes.ShardStatistics => ({ failed: 0, diff --git a/x-pack/plugins/lists/server/schemas/elastic_response/search_es_list_item_schema.mock.ts b/x-pack/plugins/lists/server/schemas/elastic_response/search_es_list_item_schema.mock.ts index 2f213ccfbad06..682c77cf5c83b 100644 --- a/x-pack/plugins/lists/server/schemas/elastic_response/search_es_list_item_schema.mock.ts +++ b/x-pack/plugins/lists/server/schemas/elastic_response/search_es_list_item_schema.mock.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { DATE_NOW, diff --git a/x-pack/plugins/lists/server/schemas/elastic_response/search_es_list_schema.mock.ts b/x-pack/plugins/lists/server/schemas/elastic_response/search_es_list_schema.mock.ts index 2cfbaf26f9d6a..5dde9cc14d4a1 100644 --- a/x-pack/plugins/lists/server/schemas/elastic_response/search_es_list_schema.mock.ts +++ b/x-pack/plugins/lists/server/schemas/elastic_response/search_es_list_schema.mock.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { DATE_NOW, diff --git a/x-pack/plugins/lists/server/services/items/find_list_item.mock.ts b/x-pack/plugins/lists/server/services/items/find_list_item.mock.ts index 1c1ce872a402d..99c2f18877032 100644 --- a/x-pack/plugins/lists/server/services/items/find_list_item.mock.ts +++ b/x-pack/plugins/lists/server/services/items/find_list_item.mock.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks'; diff --git a/x-pack/plugins/lists/server/services/items/write_list_items_to_stream.ts b/x-pack/plugins/lists/server/services/items/write_list_items_to_stream.ts index 1bf337dbd7532..565e8a3e196c5 100644 --- a/x-pack/plugins/lists/server/services/items/write_list_items_to_stream.ts +++ b/x-pack/plugins/lists/server/services/items/write_list_items_to_stream.ts @@ -7,7 +7,7 @@ import { PassThrough } from 'stream'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ElasticsearchClient } from 'kibana/server'; import { ErrorWithStatusCode } from '../../error_with_status_code'; diff --git a/x-pack/plugins/lists/server/services/utils/get_query_filter_from_type_value.ts b/x-pack/plugins/lists/server/services/utils/get_query_filter_from_type_value.ts index db667951381b0..8d0d2501475e6 100644 --- a/x-pack/plugins/lists/server/services/utils/get_query_filter_from_type_value.ts +++ b/x-pack/plugins/lists/server/services/utils/get_query_filter_from_type_value.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { isEmpty, isObject } from 'lodash/fp'; import type { Type } from '@kbn/securitysolution-io-ts-list-types'; diff --git a/x-pack/plugins/lists/server/services/utils/get_search_after_with_tie_breaker.ts b/x-pack/plugins/lists/server/services/utils/get_search_after_with_tie_breaker.ts index 7db46ce1a464c..37794228bd693 100644 --- a/x-pack/plugins/lists/server/services/utils/get_search_after_with_tie_breaker.ts +++ b/x-pack/plugins/lists/server/services/utils/get_search_after_with_tie_breaker.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { SortFieldOrUndefined } from '@kbn/securitysolution-io-ts-list-types'; export type TieBreaker = T & { diff --git a/x-pack/plugins/lists/server/services/utils/get_sort_with_tie_breaker.ts b/x-pack/plugins/lists/server/services/utils/get_sort_with_tie_breaker.ts index 8a513483f5b5e..e8fae957a5615 100644 --- a/x-pack/plugins/lists/server/services/utils/get_sort_with_tie_breaker.ts +++ b/x-pack/plugins/lists/server/services/utils/get_sort_with_tie_breaker.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { SortFieldOrUndefined, SortOrderOrUndefined } from '@kbn/securitysolution-io-ts-list-types'; export const getSortWithTieBreaker = ({ diff --git a/x-pack/plugins/lists/server/services/utils/transform_elastic_named_search_to_list_item.ts b/x-pack/plugins/lists/server/services/utils/transform_elastic_named_search_to_list_item.ts index b669b983fe46d..0a3632efe9195 100644 --- a/x-pack/plugins/lists/server/services/utils/transform_elastic_named_search_to_list_item.ts +++ b/x-pack/plugins/lists/server/services/utils/transform_elastic_named_search_to_list_item.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { SearchListItemArraySchema, Type } from '@kbn/securitysolution-io-ts-list-types'; import { SearchEsListItemSchema } from '../../schemas/elastic_response'; diff --git a/x-pack/plugins/lists/server/services/utils/transform_elastic_to_list.ts b/x-pack/plugins/lists/server/services/utils/transform_elastic_to_list.ts index 5b0949d7b79b7..3242742c1cfd6 100644 --- a/x-pack/plugins/lists/server/services/utils/transform_elastic_to_list.ts +++ b/x-pack/plugins/lists/server/services/utils/transform_elastic_to_list.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ListArraySchema } from '@kbn/securitysolution-io-ts-list-types'; import { encodeHitVersion } from '@kbn/securitysolution-es-utils'; diff --git a/x-pack/plugins/lists/server/services/utils/transform_elastic_to_list_item.ts b/x-pack/plugins/lists/server/services/utils/transform_elastic_to_list_item.ts index 65392f8c379d9..3edbab94a0cfd 100644 --- a/x-pack/plugins/lists/server/services/utils/transform_elastic_to_list_item.ts +++ b/x-pack/plugins/lists/server/services/utils/transform_elastic_to_list_item.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ListItemArraySchema, Type } from '@kbn/securitysolution-io-ts-list-types'; import { encodeHitVersion } from '@kbn/securitysolution-es-utils'; diff --git a/x-pack/plugins/logstash/server/models/cluster/cluster.test.ts b/x-pack/plugins/logstash/server/models/cluster/cluster.test.ts index 10c1d1ba24ae0..9fe03cd411b81 100755 --- a/x-pack/plugins/logstash/server/models/cluster/cluster.test.ts +++ b/x-pack/plugins/logstash/server/models/cluster/cluster.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Cluster } from './cluster'; describe('cluster', () => { diff --git a/x-pack/plugins/logstash/server/models/cluster/cluster.ts b/x-pack/plugins/logstash/server/models/cluster/cluster.ts index 2982284879c47..6c1712eb4797e 100755 --- a/x-pack/plugins/logstash/server/models/cluster/cluster.ts +++ b/x-pack/plugins/logstash/server/models/cluster/cluster.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; /** * This model deals with a cluster object from ES and converts it to Kibana downstream diff --git a/x-pack/plugins/logstash/server/routes/pipeline/save.ts b/x-pack/plugins/logstash/server/routes/pipeline/save.ts index 48a62f83c91ca..83f6ee9b00ba9 100644 --- a/x-pack/plugins/logstash/server/routes/pipeline/save.ts +++ b/x-pack/plugins/logstash/server/routes/pipeline/save.ts @@ -47,6 +47,7 @@ export function registerPipelineSaveRoute( await client.asCurrentUser.logstash.putPipeline({ id: pipeline.id, + // @ts-expect-error description is required body: pipeline.upstreamJSON, }); diff --git a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.tsx b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.tsx index d038c139a1667..777787d8213f3 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.tsx +++ b/x-pack/plugins/maps/public/classes/sources/es_geo_grid_source/es_geo_grid_source.tsx @@ -10,7 +10,7 @@ import React, { ReactElement } from 'react'; import { i18n } from '@kbn/i18n'; import rison from 'rison-node'; import { Feature } from 'geojson'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { makeESBbox } from '../../../../common/elasticsearch_util'; import { convertCompositeRespToGeoJson, convertRegularRespToGeoJson } from './convert_to_geojson'; import { UpdateSourceEditor } from './update_source_editor'; diff --git a/x-pack/plugins/maps/server/plugin.ts b/x-pack/plugins/maps/server/plugin.ts index 8768580089f31..5d84ee2ef26d2 100644 --- a/x-pack/plugins/maps/server/plugin.ts +++ b/x-pack/plugins/maps/server/plugin.ts @@ -73,7 +73,9 @@ export class MapsPlugin implements Plugin { defaultMessage: 'Map', }); - home.sampleData.addSavedObjectsToSampleDataset('ecommerce', getEcommerceSavedObjects()); + // commented out since it registers an SO already registered by home plugin + // https://github.com/elastic/kibana/blob/2ddaddc2e958f60c6685ab9f9840cdd86da9d398/src/plugins/home/server/services/sample_data/data_sets/ecommerce/saved_objects.ts#L151 + // home.sampleData.addSavedObjectsToSampleDataset('ecommerce', getEcommerceSavedObjects()); home.sampleData.addAppLinksToSampleDataset('ecommerce', [ { diff --git a/x-pack/plugins/ml/common/types/anomaly_detection_jobs/datafeed.ts b/x-pack/plugins/ml/common/types/anomaly_detection_jobs/datafeed.ts index e1a3f6044587b..ef38504c869fb 100644 --- a/x-pack/plugins/ml/common/types/anomaly_detection_jobs/datafeed.ts +++ b/x-pack/plugins/ml/common/types/anomaly_detection_jobs/datafeed.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; export type DatafeedId = string; diff --git a/x-pack/plugins/ml/common/types/anomaly_detection_jobs/datafeed_stats.ts b/x-pack/plugins/ml/common/types/anomaly_detection_jobs/datafeed_stats.ts index 4e23d97c0d145..3c7f8c51785d1 100644 --- a/x-pack/plugins/ml/common/types/anomaly_detection_jobs/datafeed_stats.ts +++ b/x-pack/plugins/ml/common/types/anomaly_detection_jobs/datafeed_stats.ts @@ -5,6 +5,6 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; export type DatafeedStats = estypes.MlDatafeedStats; diff --git a/x-pack/plugins/ml/common/types/anomaly_detection_jobs/job.ts b/x-pack/plugins/ml/common/types/anomaly_detection_jobs/job.ts index dcf18b98e00a0..0e32f4e7a065b 100644 --- a/x-pack/plugins/ml/common/types/anomaly_detection_jobs/job.ts +++ b/x-pack/plugins/ml/common/types/anomaly_detection_jobs/job.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; export type JobId = string; export type BucketSpan = string; diff --git a/x-pack/plugins/ml/common/types/anomaly_detection_jobs/job_stats.ts b/x-pack/plugins/ml/common/types/anomaly_detection_jobs/job_stats.ts index 5fc8b423a5ac2..995bd1e6a14fc 100644 --- a/x-pack/plugins/ml/common/types/anomaly_detection_jobs/job_stats.ts +++ b/x-pack/plugins/ml/common/types/anomaly_detection_jobs/job_stats.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; export type JobStats = estypes.MlJobStats; diff --git a/x-pack/plugins/ml/common/types/anomaly_detection_jobs/model_snapshot.ts b/x-pack/plugins/ml/common/types/anomaly_detection_jobs/model_snapshot.ts index 0bb2162994c37..806aca3eb43ad 100644 --- a/x-pack/plugins/ml/common/types/anomaly_detection_jobs/model_snapshot.ts +++ b/x-pack/plugins/ml/common/types/anomaly_detection_jobs/model_snapshot.ts @@ -5,6 +5,6 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; export type ModelSnapshot = estypes.MlModelSnapshot; diff --git a/x-pack/plugins/ml/common/types/data_frame_analytics.ts b/x-pack/plugins/ml/common/types/data_frame_analytics.ts index 1d2a75069dfe6..92c0c1d06ef93 100644 --- a/x-pack/plugins/ml/common/types/data_frame_analytics.ts +++ b/x-pack/plugins/ml/common/types/data_frame_analytics.ts @@ -6,7 +6,7 @@ */ import Boom from '@hapi/boom'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { RuntimeMappings } from './fields'; import { EsErrorBody } from '../util/errors'; diff --git a/x-pack/plugins/ml/common/types/es_client.ts b/x-pack/plugins/ml/common/types/es_client.ts index 466075284515e..2a6a1d4c1ffab 100644 --- a/x-pack/plugins/ml/common/types/es_client.ts +++ b/x-pack/plugins/ml/common/types/es_client.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { isPopulatedObject } from '../util/object_utils'; export function isMultiBucketAggregate( diff --git a/x-pack/plugins/ml/common/types/fields.ts b/x-pack/plugins/ml/common/types/fields.ts index 33a4a94e539b8..bf7876570f485 100644 --- a/x-pack/plugins/ml/common/types/fields.ts +++ b/x-pack/plugins/ml/common/types/fields.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ES_FIELD_TYPES } from '../../../../../src/plugins/data/common'; import { ML_JOB_AGGREGATION, diff --git a/x-pack/plugins/ml/common/types/results.ts b/x-pack/plugins/ml/common/types/results.ts index 74d3286438588..f840f9ad58c01 100644 --- a/x-pack/plugins/ml/common/types/results.ts +++ b/x-pack/plugins/ml/common/types/results.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { LineAnnotationDatum, RectAnnotationDatum } from '@elastic/charts'; export interface GetStoppedPartitionResult { diff --git a/x-pack/plugins/ml/common/util/job_utils.ts b/x-pack/plugins/ml/common/util/job_utils.ts index 6d069cd4383ea..e66d8de5bd15e 100644 --- a/x-pack/plugins/ml/common/util/job_utils.ts +++ b/x-pack/plugins/ml/common/util/job_utils.ts @@ -8,7 +8,7 @@ import { each, isEmpty, isEqual, pick } from 'lodash'; import semverGte from 'semver/functions/gte'; import moment, { Duration } from 'moment'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; // @ts-ignore import numeral from '@elastic/numeral'; import { i18n } from '@kbn/i18n'; diff --git a/x-pack/plugins/ml/common/util/runtime_field_utils.ts b/x-pack/plugins/ml/common/util/runtime_field_utils.ts index 1fcf8e2e72b15..edda547d363e4 100644 --- a/x-pack/plugins/ml/common/util/runtime_field_utils.ts +++ b/x-pack/plugins/ml/common/util/runtime_field_utils.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { isPopulatedObject } from './object_utils'; import { RUNTIME_FIELD_TYPES } from '../../../../../src/plugins/data/common'; import type { RuntimeMappings } from '../types/fields'; diff --git a/x-pack/plugins/ml/public/alerting/ml_anomaly_alert_trigger.tsx b/x-pack/plugins/ml/public/alerting/ml_anomaly_alert_trigger.tsx index 794f4b3b164e9..2be57ddf95431 100644 --- a/x-pack/plugins/ml/public/alerting/ml_anomaly_alert_trigger.tsx +++ b/x-pack/plugins/ml/public/alerting/ml_anomaly_alert_trigger.tsx @@ -88,7 +88,7 @@ const MlAnomalyAlertTrigger: FC = ({ const availableResultTypes = useMemo(() => { if (jobConfigs.length === 0) return Object.values(ANOMALY_RESULT_TYPE); - return (jobConfigs ?? []).some((v) => v.analysis_config.influencers.length > 0) + return (jobConfigs ?? []).some((v) => Boolean(v.analysis_config?.influencers?.length)) ? Object.values(ANOMALY_RESULT_TYPE) : [ANOMALY_RESULT_TYPE.BUCKET, ANOMALY_RESULT_TYPE.RECORD]; }, [jobConfigs]); diff --git a/x-pack/plugins/ml/public/application/components/data_grid/common.ts b/x-pack/plugins/ml/public/application/components/data_grid/common.ts index 6fc6f298e73d8..fc6a20e9d4cda 100644 --- a/x-pack/plugins/ml/public/application/components/data_grid/common.ts +++ b/x-pack/plugins/ml/public/application/components/data_grid/common.ts @@ -6,7 +6,7 @@ */ import moment from 'moment-timezone'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { useEffect, useMemo } from 'react'; import { diff --git a/x-pack/plugins/ml/public/application/components/data_grid/types.ts b/x-pack/plugins/ml/public/application/components/data_grid/types.ts index 47684ee307e99..01c135000fb0e 100644 --- a/x-pack/plugins/ml/public/application/components/data_grid/types.ts +++ b/x-pack/plugins/ml/public/application/components/data_grid/types.ts @@ -7,7 +7,7 @@ import { Dispatch, SetStateAction } from 'react'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { EuiDataGridCellValueElementProps, EuiDataGridPaginationProps, diff --git a/x-pack/plugins/ml/public/application/components/jobs_awaiting_node_warning/new_job_awaiting_node_shared/new_job_awaiting_node_shared.tsx b/x-pack/plugins/ml/public/application/components/jobs_awaiting_node_warning/new_job_awaiting_node_shared/new_job_awaiting_node_shared.tsx index 5850349ff5fd6..d4ce935cc085f 100644 --- a/x-pack/plugins/ml/public/application/components/jobs_awaiting_node_warning/new_job_awaiting_node_shared/new_job_awaiting_node_shared.tsx +++ b/x-pack/plugins/ml/public/application/components/jobs_awaiting_node_warning/new_job_awaiting_node_shared/new_job_awaiting_node_shared.tsx @@ -6,7 +6,7 @@ */ import React, { FC, useState, useEffect, useCallback, useMemo } from 'react'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { EuiCallOut, EuiSpacer, EuiLink } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; diff --git a/x-pack/plugins/ml/public/application/components/scatterplot_matrix/scatterplot_matrix.tsx b/x-pack/plugins/ml/public/application/components/scatterplot_matrix/scatterplot_matrix.tsx index d64a180bfa8b6..ecaf3515e1634 100644 --- a/x-pack/plugins/ml/public/application/components/scatterplot_matrix/scatterplot_matrix.tsx +++ b/x-pack/plugins/ml/public/application/components/scatterplot_matrix/scatterplot_matrix.tsx @@ -7,7 +7,7 @@ import React, { useMemo, useEffect, useState, FC } from 'react'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { EuiCallOut, diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/common/get_index_data.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/common/get_index_data.ts index 920f56b376747..eda63ec4285ea 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/common/get_index_data.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/common/get_index_data.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { extractErrorMessage } from '../../../../common/util/errors'; import { EsSorting, UseDataGridReturnType, getProcessedFields } from '../../components/data_grid'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/form_options_validation.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/form_options_validation.ts index 72853ec23fd36..1fe649ee9519a 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/form_options_validation.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/form_options_validation.ts @@ -6,7 +6,7 @@ */ import { i18n } from '@kbn/i18n'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ES_FIELD_TYPES } from '../../../../../../../../../../src/plugins/data/public'; import { EVENT_RATE_FIELD_ID } from '../../../../../../../common/types/fields'; import { ANALYSIS_CONFIG_TYPE } from '../../../../common/analytics'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/use_saved_search.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/use_saved_search.ts index 41973b5ec2d01..ad23c018afbbb 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/use_saved_search.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/use_saved_search.ts @@ -12,7 +12,7 @@ import { luceneStringToDsl, toElasticsearchQuery, } from '@kbn/es-query'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { useMlContext } from '../../../../../contexts/ml'; import { SEARCH_QUERY_LANGUAGE } from '../../../../../../../common/constants/search'; import { getQueryFromSavedSearchObject } from '../../../../../util/index_utils'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts index f3779e1968985..69f66832af3c7 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/hooks/use_index_data.ts @@ -7,7 +7,7 @@ import { useEffect, useMemo, useState } from 'react'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { EuiDataGridColumn } from '@elastic/eui'; import { CoreSetup } from 'src/core/public'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_query_bar/exploration_query_bar.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_query_bar/exploration_query_bar.tsx index 3639836c6be01..27eb06d7ecd41 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_query_bar/exploration_query_bar.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_exploration/components/exploration_query_bar/exploration_query_bar.tsx @@ -11,7 +11,7 @@ import { i18n } from '@kbn/i18n'; import { debounce } from 'lodash'; import { fromKueryExpression, luceneStringToDsl, toElasticsearchQuery } from '@kbn/es-query'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Dictionary } from '../../../../../../../common/types/common'; import { DataView } from '../../../../../../../../../../src/plugins/data_views/common'; import { Query, QueryStringInput } from '../../../../../../../../../../src/plugins/data/public'; diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/advanced_job_creator.ts b/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/advanced_job_creator.ts index 3d8c34e0e5967..fd1df5395ff84 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/advanced_job_creator.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/advanced_job_creator.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { SavedSearchSavedObject } from '../../../../../../common/types/kibana'; import { JobCreator } from './job_creator'; diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts b/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts index 607a4fcf9a73c..79bf2f64ca95d 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts +++ b/x-pack/plugins/ml/public/application/jobs/new_job/common/job_creator/job_creator.ts @@ -83,7 +83,7 @@ export class JobCreator { this._calendars = []; this._datafeed_config = createEmptyDatafeed(this._indexPatternTitle); this._detectors = this._job_config.analysis_config.detectors; - this._influencers = this._job_config.analysis_config.influencers; + this._influencers = this._job_config.analysis_config.influencers!; if (typeof indexPattern.timeFieldName === 'string') { this._job_config.data_description.time_field = indexPattern.timeFieldName; @@ -766,7 +766,7 @@ export class JobCreator { this._datafeed_config = datafeed; this._detectors = this._job_config.analysis_config.detectors; - this._influencers = this._job_config.analysis_config.influencers; + this._influencers = this._job_config.analysis_config.influencers!; if (this._job_config.groups === undefined) { this._job_config.groups = []; } diff --git a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx index f156233dfde85..f6317bcc41e54 100644 --- a/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx +++ b/x-pack/plugins/ml/public/application/jobs/new_job/pages/components/pick_fields_step/components/advanced_detector_modal/advanced_detector_modal.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import React, { FC, Fragment, useState, useContext, useEffect } from 'react'; import { EuiComboBox, diff --git a/x-pack/plugins/ml/public/application/services/anomaly_detector_service.ts b/x-pack/plugins/ml/public/application/services/anomaly_detector_service.ts index eacfd826868ac..1601a5d6cceea 100644 --- a/x-pack/plugins/ml/public/application/services/anomaly_detector_service.ts +++ b/x-pack/plugins/ml/public/application/services/anomaly_detector_service.ts @@ -50,7 +50,7 @@ export class AnomalyDetectorService { } const influencers = new Set(); for (const job of jobs) { - for (const influencer of job.analysis_config.influencers) { + for (const influencer of job.analysis_config.influencers || []) { influencers.add(influencer); } } diff --git a/x-pack/plugins/ml/public/application/services/job_service.d.ts b/x-pack/plugins/ml/public/application/services/job_service.d.ts index 667f23da34aa0..b6575c48b21f2 100644 --- a/x-pack/plugins/ml/public/application/services/job_service.d.ts +++ b/x-pack/plugins/ml/public/application/services/job_service.d.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { TimeRange } from 'src/plugins/data/common/query/timefilter/types'; import { CombinedJob, Datafeed, Job } from '../../../common/types/anomaly_detection_jobs'; diff --git a/x-pack/plugins/ml/public/application/services/ml_api_service/index.ts b/x-pack/plugins/ml/public/application/services/ml_api_service/index.ts index 29c2cd8a2408c..854d4b8014b09 100644 --- a/x-pack/plugins/ml/public/application/services/ml_api_service/index.ts +++ b/x-pack/plugins/ml/public/application/services/ml_api_service/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Observable } from 'rxjs'; import type { HttpStart } from 'kibana/public'; import { HttpService } from '../http_service'; diff --git a/x-pack/plugins/ml/public/embeddables/common/process_filters.ts b/x-pack/plugins/ml/public/embeddables/common/process_filters.ts index 4ce445eb4c488..1ff8259250019 100644 --- a/x-pack/plugins/ml/public/embeddables/common/process_filters.ts +++ b/x-pack/plugins/ml/public/embeddables/common/process_filters.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Filter, fromKueryExpression, diff --git a/x-pack/plugins/ml/server/lib/alerts/jobs_health_service.test.ts b/x-pack/plugins/ml/server/lib/alerts/jobs_health_service.test.ts index 2790ce423c1e7..e824e34a1779b 100644 --- a/x-pack/plugins/ml/server/lib/alerts/jobs_health_service.test.ts +++ b/x-pack/plugins/ml/server/lib/alerts/jobs_health_service.test.ts @@ -9,7 +9,7 @@ import { JobsHealthService, jobsHealthServiceProvider } from './jobs_health_serv import type { DatafeedsService } from '../../models/job_service/datafeeds'; import type { Logger } from 'kibana/server'; import { MlClient } from '../ml_client'; -import { MlJob, MlJobStats } from '@elastic/elasticsearch/api/types'; +import { MlJob, MlJobStats } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { AnnotationService } from '../../models/annotation_service/annotation'; import { JobsHealthExecutorOptions } from './register_jobs_monitoring_rule_type'; import { JobAuditMessagesService } from '../../models/job_audit_messages/job_audit_messages'; diff --git a/x-pack/plugins/ml/server/lib/alerts/jobs_health_service.ts b/x-pack/plugins/ml/server/lib/alerts/jobs_health_service.ts index 70a8e4a777b69..2fbda6a4b37f6 100644 --- a/x-pack/plugins/ml/server/lib/alerts/jobs_health_service.ts +++ b/x-pack/plugins/ml/server/lib/alerts/jobs_health_service.ts @@ -8,7 +8,7 @@ import { groupBy, keyBy, memoize } from 'lodash'; import { KibanaRequest, Logger, SavedObjectsClientContract } from 'kibana/server'; import { i18n } from '@kbn/i18n'; -import { MlJob } from '@elastic/elasticsearch/api/types'; +import { MlJob } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { MlClient } from '../ml_client'; import { JobSelection } from '../../routes/schemas/alerting_schema'; import { datafeedsProvider, DatafeedsService } from '../../models/job_service/datafeeds'; diff --git a/x-pack/plugins/ml/server/lib/alerts/register_jobs_monitoring_rule_type.ts b/x-pack/plugins/ml/server/lib/alerts/register_jobs_monitoring_rule_type.ts index dcf545fa4060b..5fd21d5372d23 100644 --- a/x-pack/plugins/ml/server/lib/alerts/register_jobs_monitoring_rule_type.ts +++ b/x-pack/plugins/ml/server/lib/alerts/register_jobs_monitoring_rule_type.ts @@ -7,7 +7,11 @@ import { i18n } from '@kbn/i18n'; import { KibanaRequest } from 'kibana/server'; -import { MlDatafeedState, MlJobState, MlJobStats } from '@elastic/elasticsearch/api/types'; +import { + MlDatafeedState, + MlJobState, + MlJobStats, +} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ML_ALERT_TYPES } from '../../../common/constants/alerts'; import { PLUGIN_ID } from '../../../common/constants/app'; import { MINIMUM_FULL_LICENSE } from '../../../common/license'; diff --git a/x-pack/plugins/ml/server/lib/ml_client/search.ts b/x-pack/plugins/ml/server/lib/ml_client/search.ts index 3062a70d9a975..bdcee216cf669 100644 --- a/x-pack/plugins/ml/server/lib/ml_client/search.ts +++ b/x-pack/plugins/ml/server/lib/ml_client/search.ts @@ -7,7 +7,8 @@ import Boom from '@hapi/boom'; import { IScopedClusterClient } from 'kibana/server'; -import { estypes, ApiResponse } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { TransportResult } from '@elastic/elasticsearch'; import { JobSavedObjectService } from '../../saved_objects'; import { ML_RESULTS_INDEX_PATTERN } from '../../../common/constants/index_patterns'; @@ -30,7 +31,7 @@ export function searchProvider( async function anomalySearch( searchParams: estypes.SearchRequest, jobIds: string[] - ): Promise>> { + ): Promise, unknown>> { await jobIdsCheck('anomaly-detector', jobIds); const { asInternalUser } = client; const resp = await asInternalUser.search({ diff --git a/x-pack/plugins/ml/server/lib/query_utils.ts b/x-pack/plugins/ml/server/lib/query_utils.ts index e801130643345..cfaa5abaf7f23 100644 --- a/x-pack/plugins/ml/server/lib/query_utils.ts +++ b/x-pack/plugins/ml/server/lib/query_utils.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; /* * Contains utility functions for building and processing queries. */ diff --git a/x-pack/plugins/ml/server/models/annotation_service/annotation.ts b/x-pack/plugins/ml/server/models/annotation_service/annotation.ts index 5807d181cc566..fac35d6255e03 100644 --- a/x-pack/plugins/ml/server/models/annotation_service/annotation.ts +++ b/x-pack/plugins/ml/server/models/annotation_service/annotation.ts @@ -9,7 +9,7 @@ import Boom from '@hapi/boom'; import { each, get } from 'lodash'; import { IScopedClusterClient } from 'kibana/server'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ANNOTATION_EVENT_USER, ANNOTATION_TYPE } from '../../../common/constants/annotations'; import { PARTITION_FIELDS } from '../../../common/constants/anomalies'; import { diff --git a/x-pack/plugins/ml/server/models/calculate_model_memory_limit/calculate_model_memory_limit.ts b/x-pack/plugins/ml/server/models/calculate_model_memory_limit/calculate_model_memory_limit.ts index 760faa8d530fc..4eb2c2421debf 100644 --- a/x-pack/plugins/ml/server/models/calculate_model_memory_limit/calculate_model_memory_limit.ts +++ b/x-pack/plugins/ml/server/models/calculate_model_memory_limit/calculate_model_memory_limit.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import numeral from '@elastic/numeral'; import { IScopedClusterClient } from 'kibana/server'; import { MLCATEGORY } from '../../../common/constants/field_types'; @@ -89,6 +89,7 @@ const cardinalityCheckProvider = (client: IScopedClusterClient) => { new Set() ); + // @ts-expect-error influencers is optional const normalizedInfluencers: estypes.Field[] = Array.isArray(influencers) ? influencers : [influencers]; diff --git a/x-pack/plugins/ml/server/models/calendar/calendar_manager.ts b/x-pack/plugins/ml/server/models/calendar/calendar_manager.ts index 791ba6d79ab5a..508abcffd0776 100644 --- a/x-pack/plugins/ml/server/models/calendar/calendar_manager.ts +++ b/x-pack/plugins/ml/server/models/calendar/calendar_manager.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { difference } from 'lodash'; import { EventManager } from './event_manager'; import type { MlClient } from '../../lib/ml_client'; diff --git a/x-pack/plugins/ml/server/models/calendar/event_manager.ts b/x-pack/plugins/ml/server/models/calendar/event_manager.ts index d30297eab5c15..46ad415167387 100644 --- a/x-pack/plugins/ml/server/models/calendar/event_manager.ts +++ b/x-pack/plugins/ml/server/models/calendar/event_manager.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { GLOBAL_CALENDAR } from '../../../common/constants/calendars'; import type { MlClient } from '../../lib/ml_client'; diff --git a/x-pack/plugins/ml/server/models/data_frame_analytics/validation.ts b/x-pack/plugins/ml/server/models/data_frame_analytics/validation.ts index b39debbe664d3..436ca86b5a603 100644 --- a/x-pack/plugins/ml/server/models/data_frame_analytics/validation.ts +++ b/x-pack/plugins/ml/server/models/data_frame_analytics/validation.ts @@ -6,7 +6,7 @@ */ import { i18n } from '@kbn/i18n'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { IScopedClusterClient } from 'kibana/server'; import { getAnalysisType } from '../../../common/util/analytics_utils'; import { ANALYSIS_CONFIG_TYPE } from '../../../common/constants/data_frame_analytics'; diff --git a/x-pack/plugins/ml/server/models/filter/filter_manager.ts b/x-pack/plugins/ml/server/models/filter/filter_manager.ts index a2b71ae572170..3a0d7a706e69c 100644 --- a/x-pack/plugins/ml/server/models/filter/filter_manager.ts +++ b/x-pack/plugins/ml/server/models/filter/filter_manager.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import Boom from '@hapi/boom'; import type { MlClient } from '../../lib/ml_client'; diff --git a/x-pack/plugins/ml/server/models/job_audit_messages/job_audit_messages.ts b/x-pack/plugins/ml/server/models/job_audit_messages/job_audit_messages.ts index 69f5c8b36f10c..313b60a35aa6d 100644 --- a/x-pack/plugins/ml/server/models/job_audit_messages/job_audit_messages.ts +++ b/x-pack/plugins/ml/server/models/job_audit_messages/job_audit_messages.ts @@ -7,8 +7,8 @@ import moment from 'moment'; import type { IScopedClusterClient } from 'kibana/server'; -import type { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; -import type { estypes } from '@elastic/elasticsearch'; +import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ML_NOTIFICATION_INDEX_PATTERN } from '../../../common/constants/index_patterns'; import { MESSAGE_LEVEL } from '../../../common/constants/message_levels'; import type { JobSavedObjectService } from '../../saved_objects'; diff --git a/x-pack/plugins/ml/server/models/job_service/datafeeds.ts b/x-pack/plugins/ml/server/models/job_service/datafeeds.ts index 8b3f7f4b0b0ee..a699402f9b47a 100644 --- a/x-pack/plugins/ml/server/models/job_service/datafeeds.ts +++ b/x-pack/plugins/ml/server/models/job_service/datafeeds.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { i18n } from '@kbn/i18n'; import { IScopedClusterClient } from 'kibana/server'; import { JOB_STATE, DATAFEED_STATE } from '../../../common/constants/states'; diff --git a/x-pack/plugins/ml/server/models/job_service/new_job/categorization/examples.ts b/x-pack/plugins/ml/server/models/job_service/new_job/categorization/examples.ts index 4f87e4698c032..a5510977d2ade 100644 --- a/x-pack/plugins/ml/server/models/job_service/new_job/categorization/examples.ts +++ b/x-pack/plugins/ml/server/models/job_service/new_job/categorization/examples.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { IScopedClusterClient } from 'kibana/server'; import { chunk } from 'lodash'; diff --git a/x-pack/plugins/ml/server/models/job_service/new_job/categorization/top_categories.ts b/x-pack/plugins/ml/server/models/job_service/new_job/categorization/top_categories.ts index 87715d9d85dbf..03477b896d7c7 100644 --- a/x-pack/plugins/ml/server/models/job_service/new_job/categorization/top_categories.ts +++ b/x-pack/plugins/ml/server/models/job_service/new_job/categorization/top_categories.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { CategoryId, Category } from '../../../../../common/types/categories'; import type { MlClient } from '../../../../lib/ml_client'; diff --git a/x-pack/plugins/ml/server/models/job_service/new_job_caps/field_service.ts b/x-pack/plugins/ml/server/models/job_service/new_job_caps/field_service.ts index a25b3183362b3..3682245b1b640 100644 --- a/x-pack/plugins/ml/server/models/job_service/new_job_caps/field_service.ts +++ b/x-pack/plugins/ml/server/models/job_service/new_job_caps/field_service.ts @@ -6,7 +6,7 @@ */ import { cloneDeep } from 'lodash'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { IScopedClusterClient } from 'kibana/server'; import type { Field, FieldId, NewJobCaps, RollupFields } from '../../../../common/types/fields'; import { ES_FIELD_TYPES } from '../../../../../../../src/plugins/data/common'; @@ -113,7 +113,7 @@ class FieldsService { this._mlClusterClient, this._dataViewsService ); - const rollupConfigs: estypes.RollupGetRollupCapabilitiesRollupCapabilitySummary[] | null = + const rollupConfigs: estypes.RollupGetRollupCapsRollupCapabilitySummary[] | null = await rollupService.getRollupJobs(); // if a rollup index has been specified, yet there are no @@ -137,7 +137,7 @@ class FieldsService { } function combineAllRollupFields( - rollupConfigs: estypes.RollupGetRollupCapabilitiesRollupCapabilitySummary[] + rollupConfigs: estypes.RollupGetRollupCapsRollupCapabilitySummary[] ): RollupFields { const rollupFields: RollupFields = {}; rollupConfigs.forEach((conf) => { diff --git a/x-pack/plugins/ml/server/models/job_service/new_job_caps/rollup.ts b/x-pack/plugins/ml/server/models/job_service/new_job_caps/rollup.ts index 87504a1bc0e10..f0f9a53879962 100644 --- a/x-pack/plugins/ml/server/models/job_service/new_job_caps/rollup.ts +++ b/x-pack/plugins/ml/server/models/job_service/new_job_caps/rollup.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { IScopedClusterClient } from 'kibana/server'; import type { DataViewsService, @@ -29,7 +29,7 @@ export async function rollupServiceProvider( let jobIndexPatterns: string[] = [indexPattern]; async function getRollupJobs(): Promise< - estypes.RollupGetRollupCapabilitiesRollupCapabilitySummary[] | null + estypes.RollupGetRollupCapsRollupCapabilitySummary[] | null > { if ( rollupIndexPatternObject !== null && diff --git a/x-pack/plugins/ml/server/models/job_validation/validate_influencers.ts b/x-pack/plugins/ml/server/models/job_validation/validate_influencers.ts index ad67cfb49ca6d..212beb1ebbd4a 100644 --- a/x-pack/plugins/ml/server/models/job_validation/validate_influencers.ts +++ b/x-pack/plugins/ml/server/models/job_validation/validate_influencers.ts @@ -38,7 +38,7 @@ export async function validateInfluencers(job: CombinedJob) { // detector using 'count' and no influencers and there shouldn't // be a warning about that. if ( - influencers.length === 0 && + influencers?.length === 0 && job.analysis_config.detectors.length === 1 && detectorFieldNames.length === 0 ) { @@ -46,6 +46,7 @@ export async function validateInfluencers(job: CombinedJob) { } if ( + // @ts-expect-error influencers is optional influencers.length <= INFLUENCER_LOW_THRESHOLD && detectorFieldNames.length >= DETECTOR_FIELD_NAMES_THRESHOLD ) { @@ -59,8 +60,10 @@ export async function validateInfluencers(job: CombinedJob) { } messages.push({ id, influencerSuggestion }); + // @ts-expect-error influencers is optional } else if (influencers.length <= INFLUENCER_LOW_THRESHOLD) { messages.push({ id: 'influencer_low' }); + // @ts-expect-error influencers is optional } else if (influencers.length >= INFLUENCER_HIGH_THRESHOLD) { messages.push({ id: 'influencer_high' }); } diff --git a/x-pack/plugins/ml/server/routes/anomaly_detectors.ts b/x-pack/plugins/ml/server/routes/anomaly_detectors.ts index 30aae3c0fb550..4e222e05c1b19 100644 --- a/x-pack/plugins/ml/server/routes/anomaly_detectors.ts +++ b/x-pack/plugins/ml/server/routes/anomaly_detectors.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { schema } from '@kbn/config-schema'; import { wrapError } from '../client/error_wrapper'; import { RouteInitialization } from '../types'; @@ -221,6 +221,7 @@ export function jobRoutes({ router, routeGuard }: RouteInitialization) { const { jobId } = request.params; const { body } = await mlClient.updateJob({ job_id: jobId, + // @ts-expect-error MlDetector is not compatible body: request.body, }); return response.ok({ diff --git a/x-pack/plugins/ml/server/routes/datafeeds.ts b/x-pack/plugins/ml/server/routes/datafeeds.ts index 9f908bf61a35d..c3414b2fbc55c 100644 --- a/x-pack/plugins/ml/server/routes/datafeeds.ts +++ b/x-pack/plugins/ml/server/routes/datafeeds.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { wrapError } from '../client/error_wrapper'; import { RouteInitialization } from '../types'; import { diff --git a/x-pack/plugins/ml/server/routes/job_service.ts b/x-pack/plugins/ml/server/routes/job_service.ts index 15b0b4449590c..96ca56baa38da 100644 --- a/x-pack/plugins/ml/server/routes/job_service.ts +++ b/x-pack/plugins/ml/server/routes/job_service.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { schema } from '@kbn/config-schema'; import { wrapError } from '../client/error_wrapper'; import type { RouteInitialization } from '../types'; diff --git a/x-pack/plugins/ml/server/shared_services/providers/system.ts b/x-pack/plugins/ml/server/shared_services/providers/system.ts index 85cd73ba010af..b198e5d8345f0 100644 --- a/x-pack/plugins/ml/server/shared_services/providers/system.ts +++ b/x-pack/plugins/ml/server/shared_services/providers/system.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { KibanaRequest, SavedObjectsClientContract } from 'kibana/server'; import { MlLicense } from '../../../common/license'; diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/lib/fetch_es_usage.ts b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/lib/fetch_es_usage.ts index 1fb2ba70f2ab1..884b4e6466e60 100644 --- a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/lib/fetch_es_usage.ts +++ b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/lib/fetch_es_usage.ts @@ -7,7 +7,7 @@ import { ElasticsearchClient } from 'src/core/server'; import { get } from 'lodash'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { StackProductUsage } from '../types'; interface ESIndicesBucket { diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/lib/fetch_license_type.ts b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/lib/fetch_license_type.ts index f42623ff851ce..0f0d75546d28d 100644 --- a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/lib/fetch_license_type.ts +++ b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/lib/fetch_license_type.ts @@ -7,7 +7,7 @@ import { get } from 'lodash'; import { ElasticsearchClient } from 'src/core/server'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { INDEX_PATTERN_ELASTICSEARCH } from '../../../../common/constants'; import { getCcsIndexPattern } from '../../../lib/alerts/get_ccs_index_pattern'; diff --git a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/lib/fetch_stack_product_usage.ts b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/lib/fetch_stack_product_usage.ts index 0d3aab8283688..bcb872912394c 100644 --- a/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/lib/fetch_stack_product_usage.ts +++ b/x-pack/plugins/monitoring/server/kibana_monitoring/collectors/lib/fetch_stack_product_usage.ts @@ -7,7 +7,7 @@ import { get } from 'lodash'; import { ElasticsearchClient } from 'src/core/server'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { MonitoringConfig } from '../../../config'; // @ts-ignore import { prefixIndexPattern } from '../../../../common/ccs_utils'; diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_available_ccs.test.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_available_ccs.test.ts index ca8270590da54..19d6168dbb5d0 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_available_ccs.test.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_available_ccs.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks'; import { elasticsearchServiceMock } from 'src/core/server/mocks'; diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_cluster_health.test.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_cluster_health.test.ts index 08ecaef33085b..2739e23245bde 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_cluster_health.test.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_cluster_health.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { elasticsearchClientMock } from '../../../../../../src/core/server/elasticsearch/client/mocks'; import { fetchClusterHealth } from './fetch_cluster_health'; diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_clusters.test.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_clusters.test.ts index 75991e892d419..c46ec424b2cd3 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_clusters.test.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_clusters.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks'; import { elasticsearchServiceMock } from 'src/core/server/mocks'; diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_cpu_usage_node_stats.test.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_cpu_usage_node_stats.test.ts index 8f0083f1f533f..a67a5e679cc33 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_cpu_usage_node_stats.test.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_cpu_usage_node_stats.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { elasticsearchClientMock } from '../../../../../../src/core/server/elasticsearch/client/mocks'; import { fetchCpuUsageNodeStats } from './fetch_cpu_usage_node_stats'; diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_elasticsearch_versions.test.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_elasticsearch_versions.test.ts index d105174853636..515fa3b2442d3 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_elasticsearch_versions.test.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_elasticsearch_versions.test.ts @@ -9,7 +9,7 @@ import { elasticsearchClientMock } from '../../../../../../src/core/server/elasticsearch/client/mocks'; import { elasticsearchServiceMock } from 'src/core/server/mocks'; import { fetchElasticsearchVersions } from './fetch_elasticsearch_versions'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; describe('fetchElasticsearchVersions', () => { const esClient = elasticsearchServiceMock.createScopedClusterClient().asCurrentUser; diff --git a/x-pack/plugins/monitoring/server/lib/alerts/fetch_licenses.test.ts b/x-pack/plugins/monitoring/server/lib/alerts/fetch_licenses.test.ts index 3c12c70bf1713..538e24a764276 100644 --- a/x-pack/plugins/monitoring/server/lib/alerts/fetch_licenses.test.ts +++ b/x-pack/plugins/monitoring/server/lib/alerts/fetch_licenses.test.ts @@ -8,7 +8,7 @@ import { fetchLicenses } from './fetch_licenses'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { elasticsearchClientMock } from '../../../../../../src/core/server/elasticsearch/client/mocks'; import { elasticsearchServiceMock } from 'src/core/server/mocks'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; describe('fetchLicenses', () => { const clusterName = 'MyCluster'; diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch_settings/cluster.test.ts b/x-pack/plugins/monitoring/server/lib/elasticsearch_settings/cluster.test.ts index 8b2ea8459e26c..985ad2357648a 100644 --- a/x-pack/plugins/monitoring/server/lib/elasticsearch_settings/cluster.test.ts +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch_settings/cluster.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ClusterGetSettingsResponse } from '@elastic/elasticsearch/api/types'; +import { ClusterGetSettingsResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { checkClusterSettings } from '.'; import { LegacyRequest } from '../../types'; diff --git a/x-pack/plugins/monitoring/server/lib/elasticsearch_settings/cluster.ts b/x-pack/plugins/monitoring/server/lib/elasticsearch_settings/cluster.ts index 4f46f65591d62..b474cca59519e 100644 --- a/x-pack/plugins/monitoring/server/lib/elasticsearch_settings/cluster.ts +++ b/x-pack/plugins/monitoring/server/lib/elasticsearch_settings/cluster.ts @@ -6,7 +6,7 @@ */ import { get } from 'lodash'; -import { ClusterGetSettingsResponse } from '@elastic/elasticsearch/api/types'; +import { ClusterGetSettingsResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { findReason } from './find_reason'; import { ClusterSettingsReasonResponse, LegacyRequest } from '../../types'; diff --git a/x-pack/plugins/monitoring/server/lib/errors/auth_errors.test.ts b/x-pack/plugins/monitoring/server/lib/errors/auth_errors.test.ts index e9f3eb8efc4d7..06883a47f2ca3 100644 --- a/x-pack/plugins/monitoring/server/lib/errors/auth_errors.test.ts +++ b/x-pack/plugins/monitoring/server/lib/errors/auth_errors.test.ts @@ -6,7 +6,7 @@ */ import { forbidden, unauthorized } from '@hapi/boom'; -import { ResponseError } from '@elastic/elasticsearch/lib/errors'; +import { errors } from '@elastic/elasticsearch'; import { isAuthError, handleAuthError } from './auth_errors'; describe('Error handling for 401/403 errors', () => { @@ -59,7 +59,7 @@ describe('Error handling for 401/403 errors', () => { describe('Elasticsearch errors', () => { it('handles Forbidden error defined by ElasticsearchJS', () => { - const err = new ResponseError({ + const err = new errors.ResponseError({ statusCode: 401, body: { error: { @@ -91,7 +91,7 @@ describe('Error handling for 401/403 errors', () => { }); it('handles Unauthorized error defined by ElasticsearchJS', () => { - const err = new ResponseError({ + const err = new errors.ResponseError({ statusCode: 403, body: { error: { diff --git a/x-pack/plugins/monitoring/server/lib/errors/esclient_errors.ts b/x-pack/plugins/monitoring/server/lib/errors/esclient_errors.ts index 5994c3048dae8..1b83b8e4e7eb6 100644 --- a/x-pack/plugins/monitoring/server/lib/errors/esclient_errors.ts +++ b/x-pack/plugins/monitoring/server/lib/errors/esclient_errors.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ElasticsearchClientError } from '@elastic/elasticsearch/lib/errors'; +import { errors } from '@elastic/elasticsearch'; import { boomify } from '@hapi/boom'; import { i18n } from '@kbn/i18n'; import { ErrorTypes } from '../../types'; @@ -38,12 +38,12 @@ const mapTypeMessage: { [key: string]: string } = { }; export function isESClientError(err: ErrorTypes) { - if (err instanceof ElasticsearchClientError === false) return false; + if (err instanceof errors.ElasticsearchClientError === false) return false; const knownTypes = Object.keys(mapTypeMessage); return knownTypes.includes(err.constructor.name); } -export function handleESClientError(err: ElasticsearchClientError) { +export function handleESClientError(err: errors.ElasticsearchClientError) { err.message = mapTypeMessage[err.constructor.name]; return boomify(err, { statusCode: 503 }); } diff --git a/x-pack/plugins/monitoring/server/lib/errors/handle_error.ts b/x-pack/plugins/monitoring/server/lib/errors/handle_error.ts index 3fe3b28034b2c..cc5fde228120e 100644 --- a/x-pack/plugins/monitoring/server/lib/errors/handle_error.ts +++ b/x-pack/plugins/monitoring/server/lib/errors/handle_error.ts @@ -6,7 +6,7 @@ */ import { boomify, isBoom } from '@hapi/boom'; -import { ResponseError } from '@elastic/elasticsearch/lib/errors'; +import { errors } from '@elastic/elasticsearch'; import { isCustomError, handleCustomError } from './custom_errors'; import { isAuthError, handleAuthError } from './auth_errors'; import { ErrorTypes, LegacyRequest } from '../../types'; @@ -15,7 +15,7 @@ import { handleESClientError, isESClientError } from './esclient_errors'; export const getStatusCode = (err: ErrorTypes) => { return isBoom(err) ? err.output.statusCode - : err instanceof ResponseError + : err instanceof errors.ResponseError ? err.statusCode : undefined; }; diff --git a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch_settings/check/internal_monitoring.ts b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch_settings/check/internal_monitoring.ts index 3cd2b8b73b315..eee6ba98e62c7 100644 --- a/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch_settings/check/internal_monitoring.ts +++ b/x-pack/plugins/monitoring/server/routes/api/v1/elasticsearch_settings/check/internal_monitoring.ts @@ -7,7 +7,7 @@ import { schema } from '@kbn/config-schema'; import { RequestHandlerContext } from 'kibana/server'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { INDEX_PATTERN_ELASTICSEARCH, INDEX_PATTERN_KIBANA, diff --git a/x-pack/plugins/monitoring/server/static_globals.ts b/x-pack/plugins/monitoring/server/static_globals.ts index fc4ece3231486..ac0cab7a68388 100644 --- a/x-pack/plugins/monitoring/server/static_globals.ts +++ b/x-pack/plugins/monitoring/server/static_globals.ts @@ -13,7 +13,7 @@ import { PluginInitializerContext, } from 'kibana/server'; import url from 'url'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { MonitoringConfig } from './config'; import { PluginsSetup } from './types'; import { mbSafeQuery } from './lib/mb_safe_query'; diff --git a/x-pack/plugins/monitoring/server/telemetry_collection/get_beats_stats.ts b/x-pack/plugins/monitoring/server/telemetry_collection/get_beats_stats.ts index 00dba8b727883..8da551a923f04 100644 --- a/x-pack/plugins/monitoring/server/telemetry_collection/get_beats_stats.ts +++ b/x-pack/plugins/monitoring/server/telemetry_collection/get_beats_stats.ts @@ -7,7 +7,7 @@ import { get } from 'lodash'; import { ElasticsearchClient } from 'kibana/server'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { createQuery } from './create_query'; import { INDEX_PATTERN_BEATS } from '../../common/constants'; diff --git a/x-pack/plugins/monitoring/server/telemetry_collection/get_cluster_uuids.ts b/x-pack/plugins/monitoring/server/telemetry_collection/get_cluster_uuids.ts index 7cf4ca2b94ce0..eda038ac19395 100644 --- a/x-pack/plugins/monitoring/server/telemetry_collection/get_cluster_uuids.ts +++ b/x-pack/plugins/monitoring/server/telemetry_collection/get_cluster_uuids.ts @@ -8,7 +8,7 @@ import { get } from 'lodash'; import moment from 'moment'; import { ElasticsearchClient } from 'kibana/server'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { createQuery } from './create_query'; import { INDEX_PATTERN_ELASTICSEARCH, diff --git a/x-pack/plugins/monitoring/server/telemetry_collection/get_es_stats.ts b/x-pack/plugins/monitoring/server/telemetry_collection/get_es_stats.ts index 92aa48cbe90ef..8155c0080e44e 100644 --- a/x-pack/plugins/monitoring/server/telemetry_collection/get_es_stats.ts +++ b/x-pack/plugins/monitoring/server/telemetry_collection/get_es_stats.ts @@ -6,7 +6,7 @@ */ import { ElasticsearchClient } from 'kibana/server'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { INDEX_PATTERN_ELASTICSEARCH } from '../../common/constants'; /** diff --git a/x-pack/plugins/monitoring/server/telemetry_collection/get_high_level_stats.ts b/x-pack/plugins/monitoring/server/telemetry_collection/get_high_level_stats.ts index 5f14ebb815bab..79c38c4d15a87 100644 --- a/x-pack/plugins/monitoring/server/telemetry_collection/get_high_level_stats.ts +++ b/x-pack/plugins/monitoring/server/telemetry_collection/get_high_level_stats.ts @@ -7,7 +7,7 @@ import { get } from 'lodash'; import { ElasticsearchClient } from 'kibana/server'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { createQuery } from './create_query'; import { INDEX_PATTERN_KIBANA, diff --git a/x-pack/plugins/monitoring/server/telemetry_collection/get_kibana_stats.test.ts b/x-pack/plugins/monitoring/server/telemetry_collection/get_kibana_stats.test.ts index cd037fa062ed8..5474880986238 100644 --- a/x-pack/plugins/monitoring/server/telemetry_collection/get_kibana_stats.test.ts +++ b/x-pack/plugins/monitoring/server/telemetry_collection/get_kibana_stats.test.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { getUsageStats, combineStats, diff --git a/x-pack/plugins/monitoring/server/telemetry_collection/get_kibana_stats.ts b/x-pack/plugins/monitoring/server/telemetry_collection/get_kibana_stats.ts index 8313bcc9f5464..df8354716a0c8 100644 --- a/x-pack/plugins/monitoring/server/telemetry_collection/get_kibana_stats.ts +++ b/x-pack/plugins/monitoring/server/telemetry_collection/get_kibana_stats.ts @@ -7,7 +7,7 @@ import moment from 'moment'; import { isEmpty } from 'lodash'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ElasticsearchClient } from 'kibana/server'; import { KIBANA_SYSTEM_ID, TELEMETRY_COLLECTION_INTERVAL } from '../../common/constants'; import { diff --git a/x-pack/plugins/monitoring/server/telemetry_collection/get_licenses.ts b/x-pack/plugins/monitoring/server/telemetry_collection/get_licenses.ts index 514b04bf1a0e7..d70bfdfd70ad6 100644 --- a/x-pack/plugins/monitoring/server/telemetry_collection/get_licenses.ts +++ b/x-pack/plugins/monitoring/server/telemetry_collection/get_licenses.ts @@ -6,7 +6,7 @@ */ import { ElasticsearchClient } from 'kibana/server'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ESLicense } from '../../../telemetry_collection_xpack/server'; import { INDEX_PATTERN_ELASTICSEARCH } from '../../common/constants'; diff --git a/x-pack/plugins/monitoring/server/telemetry_collection/get_logstash_stats.ts b/x-pack/plugins/monitoring/server/telemetry_collection/get_logstash_stats.ts index 306c9b6201557..736c61130bc67 100644 --- a/x-pack/plugins/monitoring/server/telemetry_collection/get_logstash_stats.ts +++ b/x-pack/plugins/monitoring/server/telemetry_collection/get_logstash_stats.ts @@ -6,7 +6,7 @@ */ import { ElasticsearchClient } from 'kibana/server'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { createQuery } from './create_query'; import { mapToList } from './get_high_level_stats'; import { incrementByKey } from './get_high_level_stats'; diff --git a/x-pack/plugins/monitoring/server/types.ts b/x-pack/plugins/monitoring/server/types.ts index 416d1ac7c3d86..14071aafaea12 100644 --- a/x-pack/plugins/monitoring/server/types.ts +++ b/x-pack/plugins/monitoring/server/types.ts @@ -14,7 +14,7 @@ import type { ElasticsearchClient, } from 'kibana/server'; import type Boom from '@hapi/boom'; -import { ElasticsearchClientError, ResponseError } from '@elastic/elasticsearch/lib/errors'; +import { errors } from '@elastic/elasticsearch'; import { UsageCollectionSetup } from 'src/plugins/usage_collection/server'; import { LicenseFeature, ILicense } from '../../licensing/server'; import type { @@ -180,7 +180,7 @@ export interface ClusterSettingsReasonResponse { }; } -export type ErrorTypes = Error | Boom.Boom | ResponseError | ElasticsearchClientError; +export type ErrorTypes = Error | Boom.Boom | errors.ResponseError | errors.ElasticsearchClientError; export type Pipeline = { id: string; diff --git a/x-pack/plugins/observability/common/utils/unwrap_es_response.ts b/x-pack/plugins/observability/common/utils/unwrap_es_response.ts index 81f8be4e0f696..d2c97eb0ba25a 100644 --- a/x-pack/plugins/observability/common/utils/unwrap_es_response.ts +++ b/x-pack/plugins/observability/common/utils/unwrap_es_response.ts @@ -4,20 +4,20 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { ElasticsearchClientError, ResponseError } from '@elastic/elasticsearch/lib/errors'; +import { errors } from '@elastic/elasticsearch'; import type { UnwrapPromise } from '@kbn/utility-types'; import { inspect } from 'util'; export class WrappedElasticsearchClientError extends Error { - originalError: ElasticsearchClientError; - constructor(originalError: ElasticsearchClientError) { + originalError: errors.ElasticsearchClientError; + constructor(originalError: errors.ElasticsearchClientError) { super(originalError.message); const stack = this.stack; this.originalError = originalError; - if (originalError instanceof ResponseError) { + if (originalError instanceof errors.ResponseError) { // make sure ES response body is visible when logged to the console // @ts-expect-error this.stack = { diff --git a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/use_filter_values.ts b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/use_filter_values.ts index e84f79f88298c..d27e3ec98287e 100644 --- a/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/use_filter_values.ts +++ b/x-pack/plugins/observability/public/components/shared/exploratory_view/series_editor/use_filter_values.ts @@ -5,7 +5,7 @@ * 2.0. */ import { ExistsFilter, isExistsFilter } from '@kbn/es-query'; -import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { useValuesList } from '../../../../hooks/use_values_list'; import { FilterProps } from './columns/filter_expanded'; import { useAppIndexPatternContext } from '../hooks/use_app_index_pattern'; @@ -25,7 +25,7 @@ export function useFilterValues( queryFilters.push(qFilter.query); } if (isExistsFilter(qFilter)) { - queryFilters.push({ exists: qFilter.query.exists } as QueryDslQueryContainer); + queryFilters.push({ exists: qFilter.query.exists } as estypes.QueryDslQueryContainer); } }); diff --git a/x-pack/plugins/observability/public/hooks/use_es_search.ts b/x-pack/plugins/observability/public/hooks/use_es_search.ts index bf96cf2c1f2c5..94126d6c1540e 100644 --- a/x-pack/plugins/observability/public/hooks/use_es_search.ts +++ b/x-pack/plugins/observability/public/hooks/use_es_search.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { DataPublicPluginStart } from '../../../../../src/plugins/data/public'; import { ESSearchResponse } from '../../../../../src/core/types/elasticsearch'; import { useKibana } from '../../../../../src/plugins/kibana_react/public'; diff --git a/x-pack/plugins/observability/server/routes/register_routes.ts b/x-pack/plugins/observability/server/routes/register_routes.ts index 660c38edb8e9d..66d8940b615b3 100644 --- a/x-pack/plugins/observability/server/routes/register_routes.ts +++ b/x-pack/plugins/observability/server/routes/register_routes.ts @@ -12,7 +12,7 @@ import { } from '@kbn/server-route-repository'; import { CoreSetup, CoreStart, Logger, RouteRegistrar } from 'kibana/server'; import Boom from '@hapi/boom'; -import { RequestAbortedError } from '@elastic/elasticsearch/lib/errors'; +import { errors } from '@elastic/elasticsearch'; import { RuleDataPluginService } from '../../../rule_registry/server'; import { ObservabilityRequestHandlerContext } from '../types'; import { AbstractObservabilityServerRouteRepository } from './types'; @@ -79,7 +79,7 @@ export function registerRoutes({ opts.statusCode = error.output.statusCode; } - if (error instanceof RequestAbortedError) { + if (error instanceof errors.RequestAbortedError) { opts.statusCode = 499; opts.body.message = 'Client closed request'; } diff --git a/x-pack/plugins/observability/server/utils/create_or_update_index.ts b/x-pack/plugins/observability/server/utils/create_or_update_index.ts index 7451314ad248c..9cd4cf9c9334f 100644 --- a/x-pack/plugins/observability/server/utils/create_or_update_index.ts +++ b/x-pack/plugins/observability/server/utils/create_or_update_index.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import pRetry from 'p-retry'; import { Logger, ElasticsearchClient } from 'src/core/server'; diff --git a/x-pack/plugins/observability/server/utils/queries.ts b/x-pack/plugins/observability/server/utils/queries.ts index 2e05aa6cb3758..953c0021636d4 100644 --- a/x-pack/plugins/observability/server/utils/queries.ts +++ b/x-pack/plugins/observability/server/utils/queries.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query'; export function rangeQuery( diff --git a/x-pack/plugins/osquery/common/search_strategy/osquery/actions/index.ts b/x-pack/plugins/osquery/common/search_strategy/osquery/actions/index.ts index b24e4f28d89f1..22edbf25cc412 100644 --- a/x-pack/plugins/osquery/common/search_strategy/osquery/actions/index.ts +++ b/x-pack/plugins/osquery/common/search_strategy/osquery/actions/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { IEsSearchResponse } from '../../../../../../../src/plugins/data/common'; import { Inspect, Maybe, PageInfoPaginated } from '../../common'; diff --git a/x-pack/plugins/osquery/common/search_strategy/osquery/index.ts b/x-pack/plugins/osquery/common/search_strategy/osquery/index.ts index fb3bd92abb4c9..d0d67c8546b61 100644 --- a/x-pack/plugins/osquery/common/search_strategy/osquery/index.ts +++ b/x-pack/plugins/osquery/common/search_strategy/osquery/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { IEsSearchRequest } from '../../../../../../src/plugins/data/common'; import { ESQuery } from '../../typed_json'; import { diff --git a/x-pack/plugins/osquery/common/search_strategy/osquery/results/index.ts b/x-pack/plugins/osquery/common/search_strategy/osquery/results/index.ts index ca85f4342c9c1..f08d9f88e705d 100644 --- a/x-pack/plugins/osquery/common/search_strategy/osquery/results/index.ts +++ b/x-pack/plugins/osquery/common/search_strategy/osquery/results/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { IEsSearchResponse } from '../../../../../../../src/plugins/data/common'; import { Inspect, Maybe, PageInfoPaginated, SortField } from '../../common'; diff --git a/x-pack/plugins/osquery/public/agents/helpers.ts b/x-pack/plugins/osquery/public/agents/helpers.ts index 1b9ac9cedcee2..1b0ae182070de 100644 --- a/x-pack/plugins/osquery/public/agents/helpers.ts +++ b/x-pack/plugins/osquery/public/agents/helpers.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { euiPaletteColorBlindBehindText } from '@elastic/eui'; import { PaginationInputPaginated, diff --git a/x-pack/plugins/osquery/public/agents/types.ts b/x-pack/plugins/osquery/public/agents/types.ts index bfe59c91d007d..9a4d4c7ff18cc 100644 --- a/x-pack/plugins/osquery/public/agents/types.ts +++ b/x-pack/plugins/osquery/public/agents/types.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { EuiComboBoxOptionOption } from '@elastic/eui'; import { Agent } from '../../common/shared_imports'; diff --git a/x-pack/plugins/osquery/server/search_strategy/osquery/factory/actions/all/query.all_actions.dsl.ts b/x-pack/plugins/osquery/server/search_strategy/osquery/factory/actions/all/query.all_actions.dsl.ts index 8dc8fad02a7c1..5162475529792 100644 --- a/x-pack/plugins/osquery/server/search_strategy/osquery/factory/actions/all/query.all_actions.dsl.ts +++ b/x-pack/plugins/osquery/server/search_strategy/osquery/factory/actions/all/query.all_actions.dsl.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ISearchRequestParams } from '../../../../../../../../../src/plugins/data/common'; import { AgentsRequestOptions } from '../../../../../../common/search_strategy'; diff --git a/x-pack/plugins/osquery/server/usage/fetchers.ts b/x-pack/plugins/osquery/server/usage/fetchers.ts index 3ac7d56acac4d..cbf72f9144b4b 100644 --- a/x-pack/plugins/osquery/server/usage/fetchers.ts +++ b/x-pack/plugins/osquery/server/usage/fetchers.ts @@ -10,7 +10,7 @@ import { AggregationsTopHitsAggregate, AggregationsValueAggregate, SearchResponse, -} from '@elastic/elasticsearch/api/types'; +} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { PackagePolicyServiceInterface } from '../../../fleet/server'; import { getRouteMetric } from '../routes/usage'; import { ElasticsearchClient, SavedObjectsClientContract } from '../../../../../src/core/server'; diff --git a/x-pack/plugins/remote_clusters/server/routes/api/update_route.test.ts b/x-pack/plugins/remote_clusters/server/routes/api/update_route.test.ts index 129326dea95ec..856b8062e320e 100644 --- a/x-pack/plugins/remote_clusters/server/routes/api/update_route.test.ts +++ b/x-pack/plugins/remote_clusters/server/routes/api/update_route.test.ts @@ -164,6 +164,7 @@ describe('UPDATE remote clusters', () => { test('updates v1 proxy cluster', async () => { remoteInfoMockFn.mockResolvedValueOnce( + // @ts-expect-error not full interface createApiResponse({ body: { test: { diff --git a/x-pack/plugins/reporting/server/deprecations/reporting_role.ts b/x-pack/plugins/reporting/server/deprecations/reporting_role.ts index a2a7e9c78726d..e4575f9875315 100644 --- a/x-pack/plugins/reporting/server/deprecations/reporting_role.ts +++ b/x-pack/plugins/reporting/server/deprecations/reporting_role.ts @@ -8,7 +8,7 @@ import { SecurityGetRoleMappingResponse, SecurityGetUserResponse, -} from '@elastic/elasticsearch/api/types'; +} from '@elastic/elasticsearch/lib/api/types'; import { i18n } from '@kbn/i18n'; import type { DeprecationsDetails, diff --git a/x-pack/plugins/reporting/server/export_types/csv/execute_job.test.ts b/x-pack/plugins/reporting/server/export_types/csv/execute_job.test.ts index 57f030df66e0e..6af186fa6baf6 100644 --- a/x-pack/plugins/reporting/server/export_types/csv/execute_job.test.ts +++ b/x-pack/plugins/reporting/server/export_types/csv/execute_job.test.ts @@ -190,7 +190,7 @@ describe('CSV Execute Job', function () { ); expect(mockEsClient.scroll).toHaveBeenCalledWith( - expect.objectContaining({ body: { scroll_id: scrollId } }) + expect.objectContaining({ scroll_id: scrollId }) ); }); @@ -279,7 +279,7 @@ describe('CSV Execute Job', function () { ); expect(mockEsClient.clearScroll).toHaveBeenCalledWith( - expect.objectContaining({ body: { scroll_id: lastScrollId } }) + expect.objectContaining({ scroll_id: lastScrollId }) ); }); @@ -315,7 +315,7 @@ describe('CSV Execute Job', function () { ); expect(mockEsClient.clearScroll).toHaveBeenCalledWith( - expect.objectContaining({ body: { scroll_id: lastScrollId } }) + expect.objectContaining({ scroll_id: lastScrollId }) ); }); }); @@ -788,9 +788,7 @@ describe('CSV Execute Job', function () { await delay(100); expect(mockEsClient.clearScroll).toHaveBeenCalledWith( - expect.objectContaining({ - body: { scroll_id: scrollId }, - }) + expect.objectContaining({ scroll_id: scrollId }) ); }); }); @@ -1184,7 +1182,7 @@ describe('CSV Execute Job', function () { await runTask('job123', jobParams, cancellationToken, stream); expect(mockEsClient.scroll).toHaveBeenCalledWith( - expect.objectContaining({ body: { scroll: scrollDuration, scroll_id: 'scrollId' } }) + expect.objectContaining({ scroll: scrollDuration, scroll_id: 'scrollId' }) ); }); }); diff --git a/x-pack/plugins/reporting/server/export_types/csv/generate_csv/hit_iterator.ts b/x-pack/plugins/reporting/server/export_types/csv/generate_csv/hit_iterator.ts index 9014e4f85b3b2..f2da8564bebbc 100644 --- a/x-pack/plugins/reporting/server/export_types/csv/generate_csv/hit_iterator.ts +++ b/x-pack/plugins/reporting/server/export_types/csv/generate_csv/hit_iterator.ts @@ -4,18 +4,15 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - -import { UnwrapPromise } from '@kbn/utility-types'; +import type { TransportResult } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { i18n } from '@kbn/i18n'; import { ElasticsearchClient } from 'src/core/server'; import { CancellationToken } from '../../../../common'; import { LevelLogger } from '../../../lib'; import { ScrollConfig } from '../../../types'; -type SearchResponse = UnwrapPromise>; -type SearchRequest = Required>[0]; - -function parseResponse(response: SearchResponse) { +function parseResponse(response: TransportResult) { if (!response?.body._scroll_id) { throw new Error( i18n.translate('xpack.reporting.exportTypes.csv.hitIterator.expectedScrollIdErrorMessage', { @@ -44,11 +41,14 @@ export function createHitIterator(logger: LevelLogger) { return async function* hitIterator( scrollSettings: ScrollConfig, elasticsearchClient: ElasticsearchClient, - searchRequest: SearchRequest, + searchRequest: estypes.SearchRequest, cancellationToken: CancellationToken ) { logger.debug('executing search request'); - async function search(index: SearchRequest['index'], body: SearchRequest['body']) { + async function search( + index: estypes.SearchRequest['index'], + body: estypes.SearchRequest['body'] + ) { return parseResponse( await elasticsearchClient.search({ index, @@ -64,10 +64,8 @@ export function createHitIterator(logger: LevelLogger) { logger.debug('executing scroll request'); return parseResponse( await elasticsearchClient.scroll({ - body: { - scroll_id: scrollId, - scroll: scrollSettings.duration, - }, + scroll_id: scrollId, + scroll: scrollSettings.duration, }) ); } @@ -76,7 +74,7 @@ export function createHitIterator(logger: LevelLogger) { logger.debug('executing clearScroll request'); try { await elasticsearchClient.clearScroll({ - body: { scroll_id: scrollId }, + scroll_id: scrollId, }); } catch (err) { // Do not throw the error, as the job can still be completed successfully diff --git a/x-pack/plugins/reporting/server/export_types/csv_searchsource/generate_csv/generate_csv.test.ts b/x-pack/plugins/reporting/server/export_types/csv_searchsource/generate_csv/generate_csv.test.ts index 1902c4ed0272e..4d883eb9aefb9 100644 --- a/x-pack/plugins/reporting/server/export_types/csv_searchsource/generate_csv/generate_csv.test.ts +++ b/x-pack/plugins/reporting/server/export_types/csv_searchsource/generate_csv/generate_csv.test.ts @@ -345,12 +345,13 @@ it('uses the scrollId to page all the data', async () => { // `scroll` and `clearScroll` must be called with scroll ID in the post body! expect(mockEsClient.asCurrentUser.scroll).toHaveBeenCalledTimes(9); expect(mockEsClient.asCurrentUser.scroll).toHaveBeenCalledWith({ - body: { scroll: '30s', scroll_id: 'awesome-scroll-hero' }, + scroll: '30s', + scroll_id: 'awesome-scroll-hero', }); expect(mockEsClient.asCurrentUser.clearScroll).toHaveBeenCalledTimes(1); expect(mockEsClient.asCurrentUser.clearScroll).toHaveBeenCalledWith({ - body: { scroll_id: ['awesome-scroll-hero'] }, + scroll_id: ['awesome-scroll-hero'], }); }); diff --git a/x-pack/plugins/reporting/server/export_types/csv_searchsource/generate_csv/generate_csv.ts b/x-pack/plugins/reporting/server/export_types/csv_searchsource/generate_csv/generate_csv.ts index 77ad4fba1ab60..76172da3e99cf 100644 --- a/x-pack/plugins/reporting/server/export_types/csv_searchsource/generate_csv/generate_csv.ts +++ b/x-pack/plugins/reporting/server/export_types/csv_searchsource/generate_csv/generate_csv.ts @@ -7,7 +7,7 @@ import { Writable } from 'stream'; import { i18n } from '@kbn/i18n'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { IScopedClusterClient, IUiSettingsClient } from 'src/core/server'; import { IScopedSearchClient } from 'src/plugins/data/server'; import { Datatable } from 'src/plugins/expressions/server'; @@ -109,10 +109,8 @@ export class CsvGenerator { this.logger.debug(`executing scroll request`); const results = ( await this.clients.es.asCurrentUser.scroll({ - body: { - scroll: scrollSettings.duration, - scroll_id: scrollId, - }, + scroll: scrollSettings.duration, + scroll_id: scrollId, }) ).body; return results; @@ -403,7 +401,7 @@ export class CsvGenerator { if (scrollId) { this.logger.debug(`executing clearScroll request`); try { - await this.clients.es.asCurrentUser.clearScroll({ body: { scroll_id: [scrollId] } }); + await this.clients.es.asCurrentUser.clearScroll({ scroll_id: [scrollId] }); } catch (err) { this.logger.error(err); } diff --git a/x-pack/plugins/reporting/server/lib/content_stream.ts b/x-pack/plugins/reporting/server/lib/content_stream.ts index 3c0fdaa91f32e..9719ac57b119c 100644 --- a/x-pack/plugins/reporting/server/lib/content_stream.ts +++ b/x-pack/plugins/reporting/server/lib/content_stream.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Duplex } from 'stream'; import { defaults, get } from 'lodash'; import Puid from 'puid'; @@ -22,7 +22,7 @@ import { LevelLogger } from './level_logger'; const REQUEST_SPAN_SIZE_IN_BYTES = 1024; type Callback = (error?: Error) => void; -type SearchRequest = Required>[0]; +type SearchRequest = estypes.SearchRequest; interface ContentStreamDocument { id: string; diff --git a/x-pack/plugins/reporting/server/lib/deprecations/check_ilm_migration_status.ts b/x-pack/plugins/reporting/server/lib/deprecations/check_ilm_migration_status.ts index dc20f92f38c94..629a44ecbcc9e 100644 --- a/x-pack/plugins/reporting/server/lib/deprecations/check_ilm_migration_status.ts +++ b/x-pack/plugins/reporting/server/lib/deprecations/check_ilm_migration_status.ts @@ -7,7 +7,7 @@ import type { IndicesIndexStatePrefixedSettings, IndicesIndexSettings, -} from '@elastic/elasticsearch/api/types'; +} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ILM_POLICY_NAME } from '../../../common/constants'; import { IlmPolicyMigrationStatus } from '../../../common/types'; import { IlmPolicyManager } from '../../lib/store/ilm_policy_manager'; diff --git a/x-pack/plugins/reporting/server/lib/deprecations/index.ts b/x-pack/plugins/reporting/server/lib/deprecations/index.ts index 2d55c3b4c22d8..5d8a95695a129 100644 --- a/x-pack/plugins/reporting/server/lib/deprecations/index.ts +++ b/x-pack/plugins/reporting/server/lib/deprecations/index.ts @@ -58,7 +58,7 @@ function deprecationError(title: string, error: Error): DeprecationsDetails[] { ]; } -function getErrorStatusCode(error: any): number { +function getErrorStatusCode(error: any): number | undefined { if (error instanceof errors.ResponseError) { return error.statusCode; } diff --git a/x-pack/plugins/reporting/server/lib/store/ilm_policy_manager/constants.ts b/x-pack/plugins/reporting/server/lib/store/ilm_policy_manager/constants.ts index bea2ba21c0846..cbbf21094d61f 100644 --- a/x-pack/plugins/reporting/server/lib/store/ilm_policy_manager/constants.ts +++ b/x-pack/plugins/reporting/server/lib/store/ilm_policy_manager/constants.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { IlmPutLifecycleRequest } from '@elastic/elasticsearch/api/types'; +import type { IlmPutLifecycleRequest } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; export const reportingIlmPolicy: IlmPutLifecycleRequest['body'] = { policy: { diff --git a/x-pack/plugins/reporting/server/lib/store/ilm_policy_manager/ilm_policy_manager.ts b/x-pack/plugins/reporting/server/lib/store/ilm_policy_manager/ilm_policy_manager.ts index ca0a74cae8726..e0569883fbbe2 100644 --- a/x-pack/plugins/reporting/server/lib/store/ilm_policy_manager/ilm_policy_manager.ts +++ b/x-pack/plugins/reporting/server/lib/store/ilm_policy_manager/ilm_policy_manager.ts @@ -24,7 +24,7 @@ export class IlmPolicyManager { public async doesIlmPolicyExist(): Promise { try { - await this.client.ilm.getLifecycle({ policy: ILM_POLICY_NAME }); + await this.client.ilm.getLifecycle({ name: ILM_POLICY_NAME }); return true; } catch (e) { if (e.statusCode === 404) { @@ -39,7 +39,7 @@ export class IlmPolicyManager { */ public async createIlmPolicy(): Promise { await this.client.ilm.putLifecycle({ - policy: ILM_POLICY_NAME, + name: ILM_POLICY_NAME, body: reportingIlmPolicy, }); } diff --git a/x-pack/plugins/reporting/server/lib/store/store.test.ts b/x-pack/plugins/reporting/server/lib/store/store.test.ts index 8c6cb4dcdd7d6..a28197d261ba2 100644 --- a/x-pack/plugins/reporting/server/lib/store/store.test.ts +++ b/x-pack/plugins/reporting/server/lib/store/store.test.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { DeeplyMockedKeys } from '@kbn/utility-types/jest'; import { ElasticsearchClient } from 'src/core/server'; import { elasticsearchServiceMock } from 'src/core/server/mocks'; @@ -262,7 +262,8 @@ describe('ReportingStore', () => { await store.setReportClaimed(report, { testDoc: 'test' } as any); const [[updateCall]] = mockEsClient.update.mock.calls; - const response = updateCall.body?.doc as Report; + + const response = (updateCall as estypes.UpdateRequest).body?.doc as Report; expect(response.migration_version).toBe(`7.14.0`); expect(response.status).toBe(`processing`); expect(updateCall.if_seq_no).toBe(42); @@ -293,7 +294,7 @@ describe('ReportingStore', () => { await store.setReportFailed(report, { errors: 'yes' } as any); const [[updateCall]] = mockEsClient.update.mock.calls; - const response = updateCall.body?.doc as Report; + const response = (updateCall as estypes.UpdateRequest).body?.doc as Report; expect(response.migration_version).toBe(`7.14.0`); expect(response.status).toBe(`failed`); expect(updateCall.if_seq_no).toBe(43); @@ -324,7 +325,7 @@ describe('ReportingStore', () => { await store.setReportCompleted(report, { certainly_completed: 'yes' } as any); const [[updateCall]] = mockEsClient.update.mock.calls; - const response = updateCall.body?.doc as Report; + const response = (updateCall as estypes.UpdateRequest).body?.doc as Report; expect(response.migration_version).toBe(`7.14.0`); expect(response.status).toBe(`completed`); expect(updateCall.if_seq_no).toBe(44); @@ -360,7 +361,7 @@ describe('ReportingStore', () => { } as any); const [[updateCall]] = mockEsClient.update.mock.calls; - const response = updateCall.body?.doc as Report; + const response = (updateCall as estypes.UpdateRequest).body?.doc as Report; expect(response.migration_version).toBe(`7.14.0`); expect(response.status).toBe(`completed_with_warnings`); @@ -401,7 +402,7 @@ describe('ReportingStore', () => { await store.prepareReportForRetry(report); const [[updateCall]] = mockEsClient.update.mock.calls; - const response = updateCall.body?.doc as Report; + const response = (updateCall as estypes.UpdateRequest).body?.doc as Report; expect(response.migration_version).toBe(`7.14.0`); expect(response.status).toBe(`pending`); @@ -417,7 +418,7 @@ describe('ReportingStore', () => { const store = new ReportingStore(mockCore, mockLogger); await store.start(); - expect(mockEsClient.ilm.getLifecycle).toHaveBeenCalledWith({ policy: 'kibana-reporting' }); + expect(mockEsClient.ilm.getLifecycle).toHaveBeenCalledWith({ name: 'kibana-reporting' }); expect(mockEsClient.ilm.putLifecycle.mock.calls[0][0]).toMatchInlineSnapshot(` Object { "body": Object { @@ -429,7 +430,7 @@ describe('ReportingStore', () => { }, }, }, - "policy": "kibana-reporting", + "name": "kibana-reporting", } `); }); @@ -440,7 +441,7 @@ describe('ReportingStore', () => { const store = new ReportingStore(mockCore, mockLogger); await store.start(); - expect(mockEsClient.ilm.getLifecycle).toHaveBeenCalledWith({ policy: 'kibana-reporting' }); + expect(mockEsClient.ilm.getLifecycle).toHaveBeenCalledWith({ name: 'kibana-reporting' }); expect(mockEsClient.ilm.putLifecycle).not.toHaveBeenCalled(); }); }); diff --git a/x-pack/plugins/reporting/server/lib/store/store.ts b/x-pack/plugins/reporting/server/lib/store/store.ts index 01a6f7a3cd06d..43f57da8c21f7 100644 --- a/x-pack/plugins/reporting/server/lib/store/store.ts +++ b/x-pack/plugins/reporting/server/lib/store/store.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { IndexResponse, UpdateResponse } from '@elastic/elasticsearch/api/types'; +import { IndexResponse, UpdateResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ElasticsearchClient } from 'src/core/server'; import { LevelLogger, statuses } from '../'; import { ReportingCore } from '../../'; @@ -196,7 +196,7 @@ export class ReportingStore { await ilmPolicyManager.createIlmPolicy(); } catch (e) { this.logger.error('Error in start phase'); - this.logger.error(e.body.error); + this.logger.error(e.body?.error); throw e; } } diff --git a/x-pack/plugins/reporting/server/lib/tasks/execute_report.ts b/x-pack/plugins/reporting/server/lib/tasks/execute_report.ts index 84566eb9c250c..5f885ad127b43 100644 --- a/x-pack/plugins/reporting/server/lib/tasks/execute_report.ts +++ b/x-pack/plugins/reporting/server/lib/tasks/execute_report.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { UpdateResponse } from '@elastic/elasticsearch/api/types'; +import { UpdateResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import moment from 'moment'; import * as Rx from 'rxjs'; import { timeout } from 'rxjs/operators'; diff --git a/x-pack/plugins/reporting/server/routes/deprecations.ts b/x-pack/plugins/reporting/server/routes/deprecations.ts index 4a519b7c199f8..521be51d6ccee 100644 --- a/x-pack/plugins/reporting/server/routes/deprecations.ts +++ b/x-pack/plugins/reporting/server/routes/deprecations.ts @@ -5,7 +5,7 @@ * 2.0. */ import { errors } from '@elastic/elasticsearch'; -import { SecurityHasPrivilegesIndexPrivilegesCheck } from '@elastic/elasticsearch/api/types'; +import { SecurityHasPrivilegesIndexPrivilegesCheck } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { RequestHandler } from 'src/core/server'; import { API_MIGRATE_ILM_POLICY_URL, diff --git a/x-pack/plugins/reporting/server/routes/lib/jobs_query.ts b/x-pack/plugins/reporting/server/routes/lib/jobs_query.ts index 54efe0636536a..ce8b5cf14ac9b 100644 --- a/x-pack/plugins/reporting/server/routes/lib/jobs_query.ts +++ b/x-pack/plugins/reporting/server/routes/lib/jobs_query.ts @@ -5,9 +5,14 @@ * 2.0. */ -import { ApiResponse } from '@elastic/elasticsearch'; -import { DeleteResponse, SearchHit, SearchResponse } from '@elastic/elasticsearch/api/types'; -import { ResponseError } from '@elastic/elasticsearch/lib/errors'; +import type { TransportResult } from '@elastic/elasticsearch'; +import { + DeleteResponse, + SearchHit, + SearchResponse, + SearchRequest, +} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { errors } from '@elastic/elasticsearch'; import { i18n } from '@kbn/i18n'; import { UnwrapPromise } from '@kbn/utility-types'; import { ElasticsearchClient } from 'src/core/server'; @@ -19,8 +24,6 @@ import { statuses } from '../../lib/statuses'; import { Report } from '../../lib/store'; import { ReportingUser } from '../../types'; -type SearchRequest = Required>[0]; - const defaultSize = 10; const getUsername = (user: ReportingUser) => (user ? user.username : false); @@ -50,7 +53,7 @@ interface JobsQueryFactory { count(jobTypes: string[], user: ReportingUser): Promise; get(user: ReportingUser, id: string): Promise; getError(id: string): Promise; - delete(deleteIndex: string, id: string): Promise>; + delete(deleteIndex: string, id: string): Promise>; } export function jobsQueryFactory(reportingCore: ReportingCore): JobsQueryFactory { @@ -66,7 +69,7 @@ export function jobsQueryFactory(reportingCore: ReportingCore): JobsQueryFactory return await callback(client); } catch (error) { - if (error instanceof ResponseError && [401, 403, 404].includes(error.statusCode)) { + if (error instanceof errors.ResponseError && [401, 403, 404].includes(error.statusCode!)) { return; } @@ -97,7 +100,7 @@ export function jobsQueryFactory(reportingCore: ReportingCore): JobsQueryFactory const response = (await execQuery((elasticsearchClient) => elasticsearchClient.search({ body, index: getIndex() }) - )) as ApiResponse>; + )) as TransportResult>; return ( response?.body.hits?.hits.map((report: SearchHit) => { diff --git a/x-pack/plugins/reporting/server/usage/get_reporting_usage.ts b/x-pack/plugins/reporting/server/usage/get_reporting_usage.ts index b2c6aece924f2..73a4920b350e3 100644 --- a/x-pack/plugins/reporting/server/usage/get_reporting_usage.ts +++ b/x-pack/plugins/reporting/server/usage/get_reporting_usage.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ElasticsearchClient } from 'kibana/server'; import { get } from 'lodash'; import type { ReportingConfig } from '../'; diff --git a/x-pack/plugins/rule_registry/common/mapping_from_field_map.ts b/x-pack/plugins/rule_registry/common/mapping_from_field_map.ts index f929917bd8f75..4833631f09adb 100644 --- a/x-pack/plugins/rule_registry/common/mapping_from_field_map.ts +++ b/x-pack/plugins/rule_registry/common/mapping_from_field_map.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { set } from '@elastic/safer-lodash-set'; import { FieldMap } from './field_map/types'; diff --git a/x-pack/plugins/rule_registry/common/types.ts b/x-pack/plugins/rule_registry/common/types.ts index 7b2fde48057a6..8ffbebbc631a1 100644 --- a/x-pack/plugins/rule_registry/common/types.ts +++ b/x-pack/plugins/rule_registry/common/types.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import * as t from 'io-ts'; diff --git a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts index 16447e6b0f539..6a22e47000d0e 100644 --- a/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts +++ b/x-pack/plugins/rule_registry/server/alert_data_client/alerts_client.ts @@ -5,7 +5,7 @@ * 2.0. */ import Boom from '@hapi/boom'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { PublicMethodsOf } from '@kbn/utility-types'; import { Filter, buildEsQuery, EsQueryConfig } from '@kbn/es-query'; import { decodeVersion, encodeHitVersion } from '@kbn/securitysolution-es-utils'; @@ -23,7 +23,10 @@ import { // @ts-expect-error } from '@kbn/rule-data-utils/target_node/alerts_as_data_rbac'; -import { InlineScript, QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; +import { + InlineScript, + QueryDslQueryContainer, +} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { AlertTypeParams, AlertingAuthorizationFilterType } from '../../../alerting/server'; import { ReadOperations, diff --git a/x-pack/plugins/rule_registry/server/rule_data_client/rule_data_client.ts b/x-pack/plugins/rule_registry/server/rule_data_client/rule_data_client.ts index 2755021e235a8..ba92e9aac3d27 100644 --- a/x-pack/plugins/rule_registry/server/rule_data_client/rule_data_client.ts +++ b/x-pack/plugins/rule_registry/server/rule_data_client/rule_data_client.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { BulkRequest } from '@elastic/elasticsearch/api/types'; -import { ResponseError } from '@elastic/elasticsearch/lib/errors'; +import { errors } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Either, isLeft } from 'fp-ts/lib/Either'; import { ElasticsearchClient } from 'kibana/server'; @@ -168,7 +168,7 @@ export class RuleDataClient implements IRuleDataClient { const prepareForWritingResult = prepareForWriting(); return { - bulk: async (request: BulkRequest) => { + bulk: async (request: estypes.BulkRequest) => { return prepareForWritingResult .then((clusterClient) => { const requestWithDefaultParameters = { @@ -179,7 +179,7 @@ export class RuleDataClient implements IRuleDataClient { return clusterClient.bulk(requestWithDefaultParameters).then((response) => { if (response.body.errors) { - const error = new ResponseError(response); + const error = new errors.ResponseError(response); throw error; } return response; diff --git a/x-pack/plugins/rule_registry/server/rule_data_client/types.ts b/x-pack/plugins/rule_registry/server/rule_data_client/types.ts index 7c05945a98b10..5ddbd0035526d 100644 --- a/x-pack/plugins/rule_registry/server/rule_data_client/types.ts +++ b/x-pack/plugins/rule_registry/server/rule_data_client/types.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { ApiResponse } from '@elastic/elasticsearch'; -import { BulkRequest, BulkResponse } from '@elastic/elasticsearch/api/types'; +import type { TransportResult } from '@elastic/elasticsearch'; +import { BulkRequest, BulkResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ESSearchRequest, ESSearchResponse } from 'src/core/types/elasticsearch'; import { FieldDescriptor } from 'src/plugins/data/server'; @@ -35,5 +35,5 @@ export interface IRuleDataReader { } export interface IRuleDataWriter { - bulk(request: BulkRequest): Promise | undefined>; + bulk(request: BulkRequest): Promise | undefined>; } diff --git a/x-pack/plugins/rule_registry/server/rule_data_plugin_service/index_options.ts b/x-pack/plugins/rule_registry/server/rule_data_plugin_service/index_options.ts index e85331fb02a63..ba0961c7926a1 100644 --- a/x-pack/plugins/rule_registry/server/rule_data_plugin_service/index_options.ts +++ b/x-pack/plugins/rule_registry/server/rule_data_plugin_service/index_options.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ValidFeatureId } from '@kbn/rule-data-utils'; /** diff --git a/x-pack/plugins/rule_registry/server/rule_data_plugin_service/resource_installer.ts b/x-pack/plugins/rule_registry/server/rule_data_plugin_service/resource_installer.ts index 160261642ff25..041dfdeed42e0 100644 --- a/x-pack/plugins/rule_registry/server/rule_data_plugin_service/resource_installer.ts +++ b/x-pack/plugins/rule_registry/server/rule_data_plugin_service/resource_installer.ts @@ -6,7 +6,7 @@ */ import { get, isEmpty } from 'lodash'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ElasticsearchClient, Logger } from 'kibana/server'; @@ -85,7 +85,7 @@ export class ResourceInstaller { // We can install them in parallel await Promise.all([ this.createOrUpdateLifecyclePolicy({ - policy: getResourceName(DEFAULT_ILM_POLICY_ID), + name: getResourceName(DEFAULT_ILM_POLICY_ID), body: defaultLifecyclePolicy, }), @@ -116,7 +116,7 @@ export class ResourceInstaller { if (ilmPolicy != null) { await this.createOrUpdateLifecyclePolicy({ - policy: indexInfo.getIlmPolicyName(), + name: indexInfo.getIlmPolicyName(), body: { policy: ilmPolicy }, }); } @@ -385,7 +385,7 @@ export class ResourceInstaller { const { logger, getClusterClient } = this.options; const clusterClient = await getClusterClient(); - logger.debug(`Installing lifecycle policy ${policy.policy}`); + logger.debug(`Installing lifecycle policy ${policy.name}`); return clusterClient.ilm.putLifecycle(policy); } diff --git a/x-pack/plugins/rule_registry/server/utils/persistence_types.ts b/x-pack/plugins/rule_registry/server/utils/persistence_types.ts index 5da05d9956d7f..326a8bef49abd 100644 --- a/x-pack/plugins/rule_registry/server/utils/persistence_types.ts +++ b/x-pack/plugins/rule_registry/server/utils/persistence_types.ts @@ -5,8 +5,8 @@ * 2.0. */ -import { ApiResponse } from '@elastic/elasticsearch'; -import { BulkResponse } from '@elastic/elasticsearch/api/types'; +import type { TransportResult } from '@elastic/elasticsearch'; +import { BulkResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Logger } from '@kbn/logging'; import { AlertExecutorOptions, @@ -25,7 +25,7 @@ export type PersistenceAlertService = ( fields: Record; }>, refresh: boolean | 'wait_for' -) => Promise | undefined>; +) => Promise | undefined>; export interface PersistenceServices { alertWithPersistence: PersistenceAlertService; diff --git a/x-pack/plugins/security/server/authentication/api_keys/api_keys.ts b/x-pack/plugins/security/server/authentication/api_keys/api_keys.ts index 1707ca710aaf8..65a7972084cb8 100644 --- a/x-pack/plugins/security/server/authentication/api_keys/api_keys.ts +++ b/x-pack/plugins/security/server/authentication/api_keys/api_keys.ts @@ -113,11 +113,11 @@ export interface InvalidateAPIKeyResult { * Details about these errors. This field is not present in the response when error_count is 0. */ error_details?: Array<{ - type: string; - reason: string; + type?: string; + reason?: string; caused_by?: { - type: string; - reason: string; + type?: string; + reason?: string; }; }>; } diff --git a/x-pack/plugins/security/server/authorization/check_privileges.ts b/x-pack/plugins/security/server/authorization/check_privileges.ts index 36c364f1ff7da..81cf3ebc29f43 100644 --- a/x-pack/plugins/security/server/authorization/check_privileges.ts +++ b/x-pack/plugins/security/server/authorization/check_privileges.ts @@ -5,6 +5,7 @@ * 2.0. */ +import type * as estypes from '@elastic/elasticsearch/lib/api/types'; import { pick, transform, uniq } from 'lodash'; import type { IClusterClient, KibanaRequest } from 'src/core/server'; @@ -60,11 +61,11 @@ export function checkPrivilegesWithRequestFactory( const clusterClient = await getClusterClient(); const { body } = await clusterClient.asScoped(request).asCurrentUser.security.hasPrivileges({ body: { - cluster: privileges.elasticsearch?.cluster, + cluster: privileges.elasticsearch?.cluster as estypes.SecurityClusterPrivilege[], index: Object.entries(privileges.elasticsearch?.index ?? {}).map( ([name, indexPrivileges]) => ({ names: [name], - privileges: indexPrivileges, + privileges: indexPrivileges as estypes.SecurityIndexPrivilege[], }) ), application: [ diff --git a/x-pack/plugins/security/server/deprecations/kibana_user_role.test.ts b/x-pack/plugins/security/server/deprecations/kibana_user_role.test.ts index da728b12fca91..d971769160df5 100644 --- a/x-pack/plugins/security/server/deprecations/kibana_user_role.test.ts +++ b/x-pack/plugins/security/server/deprecations/kibana_user_role.test.ts @@ -6,7 +6,7 @@ */ import { errors } from '@elastic/elasticsearch'; -import type { SecurityRoleMapping, SecurityUser } from '@elastic/elasticsearch/api/types'; +import type { SecurityRoleMapping, SecurityUser } from '@elastic/elasticsearch/lib/api/types'; import type { PackageInfo, RegisterDeprecationsConfig } from 'src/core/server'; import { diff --git a/x-pack/plugins/security/server/deprecations/kibana_user_role.ts b/x-pack/plugins/security/server/deprecations/kibana_user_role.ts index d659ea273f05f..ba32446611a62 100644 --- a/x-pack/plugins/security/server/deprecations/kibana_user_role.ts +++ b/x-pack/plugins/security/server/deprecations/kibana_user_role.ts @@ -8,7 +8,7 @@ import type { SecurityGetRoleMappingResponse, SecurityGetUserResponse, -} from '@elastic/elasticsearch/api/types'; +} from '@elastic/elasticsearch/lib/api/types'; import { i18n } from '@kbn/i18n'; import type { diff --git a/x-pack/plugins/security/server/errors.ts b/x-pack/plugins/security/server/errors.ts index 25d2aa44f3dc8..2f2573b171ae2 100644 --- a/x-pack/plugins/security/server/errors.ts +++ b/x-pack/plugins/security/server/errors.ts @@ -33,7 +33,7 @@ export function wrapIntoCustomErrorResponse(error: any) { */ export function getErrorStatusCode(error: any): number { if (error instanceof errors.ResponseError) { - return error.statusCode; + return error.statusCode!; } return Boom.isBoom(error) ? error.output.statusCode : error.statusCode || error.status; diff --git a/x-pack/plugins/security/server/mocks.ts b/x-pack/plugins/security/server/mocks.ts index 7cae0d29bf943..491d6cdafa44d 100644 --- a/x-pack/plugins/security/server/mocks.ts +++ b/x-pack/plugins/security/server/mocks.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { ApiResponse } from '@elastic/elasticsearch'; +import type { TransportResult } from '@elastic/elasticsearch'; import { licenseMock } from '../common/licensing/index.mock'; import type { MockAuthenticatedUserProps } from '../common/model/authenticated_user.mock'; @@ -53,11 +53,13 @@ function createStartMock() { } function createApiResponseMock( - apiResponse: Pick, 'body'> & - Partial, 'body'>> -): ApiResponse { + apiResponse: Pick, 'body'> & + Partial, 'body'>> +): TransportResult { return { + // @ts-expect-error null is not supported statusCode: null, + // @ts-expect-error null is not supported headers: null, warnings: null, meta: {} as any, diff --git a/x-pack/plugins/security/server/routes/deprecations/kibana_user_role.test.ts b/x-pack/plugins/security/server/routes/deprecations/kibana_user_role.test.ts index b2ae2543bd652..3c9a775d7a054 100644 --- a/x-pack/plugins/security/server/routes/deprecations/kibana_user_role.test.ts +++ b/x-pack/plugins/security/server/routes/deprecations/kibana_user_role.test.ts @@ -6,7 +6,7 @@ */ import { errors } from '@elastic/elasticsearch'; -import type { SecurityRoleMapping, SecurityUser } from '@elastic/elasticsearch/api/types'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { DeeplyMockedKeys } from '@kbn/utility-types/jest'; import type { RequestHandler, RouteConfig } from 'src/core/server'; @@ -18,11 +18,11 @@ import type { SecurityRequestHandlerContext, SecurityRouter } from '../../types' import { routeDefinitionParamsMock } from '../index.mock'; import { defineKibanaUserRoleDeprecationRoutes } from './kibana_user_role'; -function createMockUser(user: Partial = {}) { +function createMockUser(user: Partial = {}) { return { enabled: true, username: 'userA', roles: ['roleA'], metadata: {}, ...user }; } -function createMockRoleMapping(mapping: Partial = {}) { +function createMockRoleMapping(mapping: Partial = {}) { return { enabled: true, roles: ['roleA'], rules: {}, metadata: {}, ...mapping }; } diff --git a/x-pack/plugins/security/server/routes/deprecations/kibana_user_role.ts b/x-pack/plugins/security/server/routes/deprecations/kibana_user_role.ts index 21bb9db7329b6..5d5e2a12f86a6 100644 --- a/x-pack/plugins/security/server/routes/deprecations/kibana_user_role.ts +++ b/x-pack/plugins/security/server/routes/deprecations/kibana_user_role.ts @@ -5,10 +5,7 @@ * 2.0. */ -import type { - SecurityGetRoleMappingResponse, - SecurityGetUserResponse, -} from '@elastic/elasticsearch/api/types'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { RouteDefinitionParams } from '..'; import { KIBANA_ADMIN_ROLE_NAME, KIBANA_USER_ROLE_NAME } from '../../deprecations'; @@ -29,7 +26,7 @@ export function defineKibanaUserRoleDeprecationRoutes({ router, logger }: RouteD validate: false, }, createLicensedRouteHandler(async (context, request, response) => { - let users: SecurityGetUserResponse; + let users: estypes.SecurityGetUserResponse; try { users = (await context.core.elasticsearch.client.asCurrentUser.security.getUser()).body; } catch (err) { @@ -92,7 +89,7 @@ export function defineKibanaUserRoleDeprecationRoutes({ router, logger }: RouteD validate: false, }, createLicensedRouteHandler(async (context, request, response) => { - let roleMappings: SecurityGetRoleMappingResponse; + let roleMappings: estypes.SecurityGetRoleMappingResponse; try { roleMappings = ( await context.core.elasticsearch.client.asCurrentUser.security.getRoleMapping() diff --git a/x-pack/plugins/security/server/routes/indices/get_fields.ts b/x-pack/plugins/security/server/routes/indices/get_fields.ts index ebfb2b9b3fb95..d6c7778d9ccbf 100644 --- a/x-pack/plugins/security/server/routes/indices/get_fields.ts +++ b/x-pack/plugins/security/server/routes/indices/get_fields.ts @@ -39,11 +39,7 @@ export function defineGetFieldsRoutes({ router }: RouteDefinitionParams) { const mappingValues = Object.values( // `FieldMapping` type from `TypeFieldMappings` --> `GetFieldMappingResponse` is not correct and // doesn't have any properties. - ( - indexMapping.mappings[fieldName] as { - mapping: Record; - } - ).mapping + indexMapping.mappings[fieldName]?.mapping as Record ); const hasMapping = mappingValues.length > 0; diff --git a/x-pack/plugins/security_solution/common/endpoint/data_generators/fleet_agent_generator.ts b/x-pack/plugins/security_solution/common/endpoint/data_generators/fleet_agent_generator.ts index 61f71e2ee253b..8f69df325fe42 100644 --- a/x-pack/plugins/security_solution/common/endpoint/data_generators/fleet_agent_generator.ts +++ b/x-pack/plugins/security_solution/common/endpoint/data_generators/fleet_agent_generator.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { DeepPartial } from 'utility-types'; import { merge } from 'lodash'; import { BaseDataGenerator } from './base_data_generator'; diff --git a/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_endpoint_actions.ts b/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_endpoint_actions.ts index e4379271315dd..3c8d23e375159 100644 --- a/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_endpoint_actions.ts +++ b/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_endpoint_actions.ts @@ -6,7 +6,7 @@ */ import { Client } from '@elastic/elasticsearch'; -import { DeleteByQueryResponse } from '@elastic/elasticsearch/api/types'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { HostMetadata, LogsEndpointAction, LogsEndpointActionResponse } from '../types'; import { EndpointActionGenerator } from '../data_generators/endpoint_action_generator'; import { wrapErrorAndRejectPromise } from './utils'; @@ -144,8 +144,8 @@ export const indexEndpointActionsForHost = async ( }; export interface DeleteIndexedEndpointActionsResponse { - endpointActionRequests: DeleteByQueryResponse | undefined; - endpointActionResponses: DeleteByQueryResponse | undefined; + endpointActionRequests: estypes.DeleteByQueryResponse | undefined; + endpointActionResponses: estypes.DeleteByQueryResponse | undefined; } export const deleteIndexedEndpointActions = async ( @@ -158,55 +158,51 @@ export const deleteIndexedEndpointActions = async ( }; if (indexedData.endpointActions.length) { - response.endpointActionRequests = ( - await esClient - .deleteByQuery({ - index: `${indexedData.endpointActionsIndex}-*`, - wait_for_completion: true, - body: { - query: { - bool: { - filter: [ - { - terms: { - action_id: indexedData.endpointActions.map( - (action) => action.EndpointActions.action_id - ), - }, + response.endpointActionRequests = await esClient + .deleteByQuery({ + index: `${indexedData.endpointActionsIndex}-*`, + wait_for_completion: true, + body: { + query: { + bool: { + filter: [ + { + terms: { + action_id: indexedData.endpointActions.map( + (action) => action.EndpointActions.action_id + ), }, - ], - }, + }, + ], }, }, - }) - .catch(wrapErrorAndRejectPromise) - ).body; + }, + }) + .catch(wrapErrorAndRejectPromise); } if (indexedData.endpointActionResponses) { - response.endpointActionResponses = ( - await esClient - .deleteByQuery({ - index: `${indexedData.endpointActionResponsesIndex}-*`, - wait_for_completion: true, - body: { - query: { - bool: { - filter: [ - { - terms: { - action_id: indexedData.endpointActionResponses.map( - (action) => action.EndpointActions.action_id - ), - }, + response.endpointActionResponses = await esClient + .deleteByQuery({ + index: `${indexedData.endpointActionResponsesIndex}-*`, + wait_for_completion: true, + body: { + query: { + bool: { + filter: [ + { + terms: { + action_id: indexedData.endpointActionResponses.map( + (action) => action.EndpointActions.action_id + ), }, - ], - }, + }, + ], }, }, - }) - .catch(wrapErrorAndRejectPromise) - ).body; + }, + }) + .catch(wrapErrorAndRejectPromise); } return response; diff --git a/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_endpoint_hosts.ts b/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_endpoint_hosts.ts index fdb8416de2ed8..de564019db6d0 100644 --- a/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_endpoint_hosts.ts +++ b/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_endpoint_hosts.ts @@ -10,7 +10,7 @@ import { cloneDeep, merge } from 'lodash'; import { AxiosResponse } from 'axios'; // eslint-disable-next-line import/no-extraneous-dependencies import { KbnClient } from '@kbn/test'; -import { DeleteByQueryResponse } from '@elastic/elasticsearch/api/types'; +import { DeleteByQueryResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Agent, CreatePackagePolicyResponse, GetPackagesResponse } from '../../../../fleet/common'; import { EndpointDocGenerator } from '../generate_data'; import { HostMetadata, HostPolicyResponse } from '../types'; @@ -290,15 +290,13 @@ export const deleteIndexedEndpointHosts = async ( }, }; - response.hosts = ( - await esClient - .deleteByQuery({ - index: indexedData.metadataIndex, - wait_for_completion: true, - body, - }) - .catch(wrapErrorAndRejectPromise) - ).body; + response.hosts = await esClient + .deleteByQuery({ + index: indexedData.metadataIndex, + wait_for_completion: true, + body, + }) + .catch(wrapErrorAndRejectPromise); // Delete from the transform destination index await esClient @@ -311,29 +309,27 @@ export const deleteIndexedEndpointHosts = async ( } if (indexedData.policyResponses.length) { - response.policyResponses = ( - await esClient - .deleteByQuery({ - index: indexedData.policyResponseIndex, - wait_for_completion: true, - body: { - query: { - bool: { - filter: [ - { - terms: { - 'agent.id': indexedData.policyResponses.map( - (policyResponse) => policyResponse.agent.id - ), - }, + response.policyResponses = await esClient + .deleteByQuery({ + index: indexedData.policyResponseIndex, + wait_for_completion: true, + body: { + query: { + bool: { + filter: [ + { + terms: { + 'agent.id': indexedData.policyResponses.map( + (policyResponse) => policyResponse.agent.id + ), }, - ], - }, + }, + ], }, }, - }) - .catch(wrapErrorAndRejectPromise) - ).body; + }, + }) + .catch(wrapErrorAndRejectPromise); } merge(response, await deleteIndexedFleetAgents(esClient, indexedData)); diff --git a/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_fleet_actions.ts b/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_fleet_actions.ts index 5cc564ee3d41d..34f57c0604fac 100644 --- a/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_fleet_actions.ts +++ b/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_fleet_actions.ts @@ -6,7 +6,7 @@ */ import { Client } from '@elastic/elasticsearch'; -import { DeleteByQueryResponse } from '@elastic/elasticsearch/api/types'; +import { DeleteByQueryResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { EndpointAction, EndpointActionResponse, HostMetadata } from '../types'; import { AGENT_ACTIONS_INDEX, AGENT_ACTIONS_RESULTS_INDEX } from '../../../../fleet/common'; import { FleetActionGenerator } from '../data_generators/fleet_action_generator'; @@ -175,47 +175,43 @@ export const deleteIndexedFleetActions = async ( }; if (indexedData.actions.length) { - response.actions = ( - await esClient - .deleteByQuery({ - index: `${indexedData.actionsIndex}-*`, - wait_for_completion: true, - body: { - query: { - bool: { - filter: [ - { terms: { action_id: indexedData.actions.map((action) => action.action_id) } }, - ], - }, + response.actions = await esClient + .deleteByQuery({ + index: `${indexedData.actionsIndex}-*`, + wait_for_completion: true, + body: { + query: { + bool: { + filter: [ + { terms: { action_id: indexedData.actions.map((action) => action.action_id) } }, + ], }, }, - }) - .catch(wrapErrorAndRejectPromise) - ).body; + }, + }) + .catch(wrapErrorAndRejectPromise); } if (indexedData.actionResponses) { - response.responses = ( - await esClient - .deleteByQuery({ - index: `${indexedData.responsesIndex}-*`, - wait_for_completion: true, - body: { - query: { - bool: { - filter: [ - { - terms: { - action_id: indexedData.actionResponses.map((action) => action.action_id), - }, + response.responses = await esClient + .deleteByQuery({ + index: `${indexedData.responsesIndex}-*`, + wait_for_completion: true, + body: { + query: { + bool: { + filter: [ + { + terms: { + action_id: indexedData.actionResponses.map((action) => action.action_id), }, - ], - }, + }, + ], }, }, - }) - .catch(wrapErrorAndRejectPromise) - ).body; + }, + }) + .catch(wrapErrorAndRejectPromise); } return response; diff --git a/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_fleet_agent.ts b/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_fleet_agent.ts index 67a261d088f86..263b6bc175688 100644 --- a/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_fleet_agent.ts +++ b/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_fleet_agent.ts @@ -7,7 +7,7 @@ import { Client } from '@elastic/elasticsearch'; import { AxiosResponse } from 'axios'; -import { DeleteByQueryResponse } from '@elastic/elasticsearch/api/types'; +import { DeleteByQueryResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; // eslint-disable-next-line import/no-extraneous-dependencies import { KbnClient } from '@kbn/test'; import { HostMetadata } from '../types'; @@ -81,7 +81,7 @@ export const indexFleetAgentForHost = async ( return { fleetAgentsIndex: agentDoc._index, agents: [ - await fetchFleetAgent(kbnClient, createdFleetAgent.body._id).catch(wrapErrorAndRejectPromise), + await fetchFleetAgent(kbnClient, createdFleetAgent._id).catch(wrapErrorAndRejectPromise), ], }; }; @@ -110,29 +110,27 @@ export const deleteIndexedFleetAgents = async ( }; if (indexedData.agents.length) { - response.agents = ( - await esClient - .deleteByQuery({ - index: `${indexedData.fleetAgentsIndex}-*`, - wait_for_completion: true, - body: { - query: { - bool: { - filter: [ - { - terms: { - 'local_metadata.elastic.agent.id': indexedData.agents.map( - (agent) => agent.local_metadata.elastic.agent.id - ), - }, + response.agents = await esClient + .deleteByQuery({ + index: `${indexedData.fleetAgentsIndex}-*`, + wait_for_completion: true, + body: { + query: { + bool: { + filter: [ + { + terms: { + 'local_metadata.elastic.agent.id': indexedData.agents.map( + (agent) => agent.local_metadata.elastic.agent.id + ), }, - ], - }, + }, + ], }, }, - }) - .catch(wrapErrorAndRejectPromise) - ).body; + }, + }) + .catch(wrapErrorAndRejectPromise); } return response; diff --git a/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_fleet_server.ts b/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_fleet_server.ts index 7ef827b8ea1f1..ed3e1812b8a63 100644 --- a/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_fleet_server.ts +++ b/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_fleet_server.ts @@ -17,13 +17,13 @@ import { wrapErrorAndRejectPromise } from './utils'; * @param version */ export const enableFleetServerIfNecessary = async (esClient: Client, version: string = '8.0.0') => { - const res = await esClient.search<{}, {}>({ + const res = await esClient.search({ index: FLEET_SERVER_SERVERS_INDEX, ignore_unavailable: true, rest_total_hits_as_int: true, }); - if (res.body.hits.total > 0) { + if (res.hits.total > 0) { return; } diff --git a/x-pack/plugins/security_solution/common/search_strategy/eql/validation/helpers.mock.ts b/x-pack/plugins/security_solution/common/search_strategy/eql/validation/helpers.mock.ts index b3a2c9c9a3f62..0c620fbdd348d 100644 --- a/x-pack/plugins/security_solution/common/search_strategy/eql/validation/helpers.mock.ts +++ b/x-pack/plugins/security_solution/common/search_strategy/eql/validation/helpers.mock.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { ApiResponse } from '@elastic/elasticsearch'; +import type { TransportResult } from '@elastic/elasticsearch'; import { ErrorResponse } from './helpers'; -export const getValidEqlResponse = (): ApiResponse['body'] => ({ +export const getValidEqlResponse = (): TransportResult['body'] => ({ is_partial: false, is_running: false, took: 162, @@ -56,7 +56,7 @@ export const getEqlResponseWithValidationErrors = (): ErrorResponse => ({ }, }); -export const getEqlResponseWithNonValidationError = (): ApiResponse['body'] => ({ +export const getEqlResponseWithNonValidationError = (): TransportResult['body'] => ({ error: { root_cause: [ { diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/details/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/details/index.ts index e8578b4c07063..315f6eeb69f34 100644 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/details/index.ts +++ b/x-pack/plugins/security_solution/common/search_strategy/security_solution/hosts/details/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { IEsSearchResponse } from '../../../../../../../../src/plugins/data/common'; import { Inspect, Maybe, TimerangeInput } from '../../../common'; diff --git a/x-pack/plugins/security_solution/common/search_strategy/security_solution/index.ts b/x-pack/plugins/security_solution/common/search_strategy/security_solution/index.ts index 9a176662fe86b..91a2956e25286 100644 --- a/x-pack/plugins/security_solution/common/search_strategy/security_solution/index.ts +++ b/x-pack/plugins/security_solution/common/search_strategy/security_solution/index.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { IEsSearchRequest } from '../../../../../../src/plugins/data/common'; import { ESQuery } from '../../typed_json'; import { diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/use_add_exception.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/use_add_exception.test.tsx index 662a3ee770547..82c3fb4c40248 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/use_add_exception.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/use_add_exception.test.tsx @@ -6,7 +6,7 @@ */ import { act, renderHook, RenderHookResult } from '@testing-library/react-hooks'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { coreMock } from '../../../../../../../src/core/public/mocks'; import { KibanaServices } from '../../../common/lib/kibana'; diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/use_add_exception.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/use_add_exception.tsx index 18fce44646909..7cb8b643aa0e8 100644 --- a/x-pack/plugins/security_solution/public/common/components/exceptions/use_add_exception.tsx +++ b/x-pack/plugins/security_solution/public/common/components/exceptions/use_add_exception.tsx @@ -6,7 +6,7 @@ */ import { useEffect, useRef, useState, useCallback } from 'react'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ExceptionListItemSchema, CreateExceptionListItemSchema, diff --git a/x-pack/plugins/security_solution/public/common/hooks/eql/eql_search_response.mock.ts b/x-pack/plugins/security_solution/public/common/hooks/eql/eql_search_response.mock.ts index 513bfc654027d..107a691b6dbeb 100644 --- a/x-pack/plugins/security_solution/public/common/hooks/eql/eql_search_response.mock.ts +++ b/x-pack/plugins/security_solution/public/common/hooks/eql/eql_search_response.mock.ts @@ -8,7 +8,7 @@ import { EqlSearchStrategyResponse } from '../../../../../../../src/plugins/data/common'; import { Source } from './types'; import { EqlSearchResponse } from '../../../../common/detection_engine/types'; -import { Connection } from '@elastic/elasticsearch'; +import type { Connection } from '@elastic/elasticsearch'; export const getMockEqlResponse = (): EqlSearchStrategyResponse> => ({ id: 'some-id', diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/api.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/api.ts index 324372edf8623..44f3e22c82ae8 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/api.ts +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/api.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { getCasesFromAlertsUrl } from '../../../../../../cases/common'; import { HostIsolationResponse, HostInfo } from '../../../../../common/endpoint/types'; import { diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_fetch_ecs_alerts_data.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_fetch_ecs_alerts_data.ts index 749addcc94930..64b5d6ea9431a 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_fetch_ecs_alerts_data.ts +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/alerts/use_fetch_ecs_alerts_data.ts @@ -5,7 +5,7 @@ * 2.0. */ import { useEffect, useState } from 'react'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { isEmpty } from 'lodash'; import { diff --git a/x-pack/plugins/security_solution/public/hosts/components/authentications_table/mock.ts b/x-pack/plugins/security_solution/public/hosts/components/authentications_table/mock.ts index f2b004f856cc4..caf441b34ca90 100644 --- a/x-pack/plugins/security_solution/public/hosts/components/authentications_table/mock.ts +++ b/x-pack/plugins/security_solution/public/hosts/components/authentications_table/mock.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { HostAuthenticationsStrategyResponse } from '../../../../common/search_strategy/security_solution/hosts/authentications'; export const mockData: { Authentications: HostAuthenticationsStrategyResponse } = { diff --git a/x-pack/plugins/security_solution/public/timelines/containers/index.tsx b/x-pack/plugins/security_solution/public/timelines/containers/index.tsx index 368a5a02d7167..4ccb90b0ee5ae 100644 --- a/x-pack/plugins/security_solution/public/timelines/containers/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/containers/index.tsx @@ -245,6 +245,7 @@ export const useTimelineEvents = ({ activeTimeline.setEqlRequest(request as TimelineEqlRequestOptions); activeTimeline.setEqlResponse(newTimelineResponse); } else { + // @ts-expect-error EqlSearchRequest.query is not compatible with QueryDslQueryContainer activeTimeline.setRequest(request); activeTimeline.setResponse(newTimelineResponse); } diff --git a/x-pack/plugins/security_solution/scripts/endpoint/resolver_generator_script.ts b/x-pack/plugins/security_solution/scripts/endpoint/resolver_generator_script.ts index 3c267117964ce..da0810bead47e 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/resolver_generator_script.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/resolver_generator_script.ts @@ -8,8 +8,8 @@ /* eslint-disable no-console */ import yargs from 'yargs'; import fs from 'fs'; -import { Client, ClientOptions } from '@elastic/elasticsearch'; -import { ResponseError } from '@elastic/elasticsearch/lib/errors'; +import { Client, errors } from '@elastic/elasticsearch'; +import type { ClientOptions } from '@elastic/elasticsearch/lib/client'; import { ToolingLog, CA_CERT_PATH } from '@kbn/dev-utils'; import { KbnClient } from '@kbn/test'; import { indexHostsAndAlerts } from '../../common/endpoint/index_data'; @@ -19,7 +19,7 @@ main(); async function deleteIndices(indices: string[], client: Client) { const handleErr = (err: unknown) => { - if (err instanceof ResponseError && err.statusCode !== 404) { + if (err instanceof errors.ResponseError && err.statusCode !== 404) { console.log(JSON.stringify(err, null, 2)); // eslint-disable-next-line no-process-exit process.exit(1); @@ -196,7 +196,7 @@ async function main() { url, certificateAuthorities: [ca], }); - clientOptions = { node, ssl: { ca: [ca] } }; + clientOptions = { node, tls: { ca: [ca] } }; } else { kbnClient = new KbnClient({ log: new ToolingLog({ diff --git a/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/migrate_artifacts_to_fleet.test.ts b/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/migrate_artifacts_to_fleet.test.ts index d6599f2686670..277ccf030f808 100644 --- a/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/migrate_artifacts_to_fleet.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/migrate_artifacts_to_fleet.test.ts @@ -21,7 +21,7 @@ import { createEndpointArtifactClientMock } from '../../services/artifacts/mocks import { InternalArtifactCompleteSchema } from '../../schemas'; import { generateArtifactEsGetSingleHitMock } from '../../../../../fleet/server/services/artifacts/mocks'; import { NewArtifact } from '../../../../../fleet/server/services'; -import { CreateRequest } from '@elastic/elasticsearch/api/types'; +import { CreateRequest } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; describe('When migrating artifacts to fleet', () => { let soClient: jest.Mocked; diff --git a/x-pack/plugins/security_solution/server/endpoint/lib/metadata/check_metadata_transforms_task.test.ts b/x-pack/plugins/security_solution/server/endpoint/lib/metadata/check_metadata_transforms_task.test.ts index 0510743fdf05b..91bb5c775b74e 100644 --- a/x-pack/plugins/security_solution/server/endpoint/lib/metadata/check_metadata_transforms_task.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/lib/metadata/check_metadata_transforms_task.test.ts @@ -4,8 +4,8 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { ApiResponse } from '@elastic/elasticsearch'; -import { TransformGetTransformStatsResponse } from '@elastic/elasticsearch/api/types'; +import type { TransportResult } from '@elastic/elasticsearch'; +import { TransformGetTransformStatsResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { CheckMetadataTransformsTask, TYPE, @@ -102,7 +102,7 @@ describe('check metadata transforms task', () => { }, ], }, - } as unknown as ApiResponse); + } as unknown as TransportResult); it('should stop task if transform stats response fails', async () => { esClient.transform.getTransformStats.mockRejectedValue({}); @@ -237,7 +237,7 @@ describe('check metadata transforms task', () => { }, ], }, - } as unknown as ApiResponse; + } as unknown as TransportResult; esClient.transform.getTransformStats.mockResolvedValue(transformStatsResponseMock); taskResponse = (await runTask({ ...MOCK_TASK_INSTANCE, diff --git a/x-pack/plugins/security_solution/server/endpoint/lib/metadata/check_metadata_transforms_task.ts b/x-pack/plugins/security_solution/server/endpoint/lib/metadata/check_metadata_transforms_task.ts index d55e3966f997b..ba3974839af77 100644 --- a/x-pack/plugins/security_solution/server/endpoint/lib/metadata/check_metadata_transforms_task.ts +++ b/x-pack/plugins/security_solution/server/endpoint/lib/metadata/check_metadata_transforms_task.ts @@ -4,11 +4,11 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { ApiResponse } from '@elastic/elasticsearch'; +import type { TransportResult } from '@elastic/elasticsearch'; import { TransformGetTransformStatsResponse, TransformGetTransformStatsTransformStats, -} from '@elastic/elasticsearch/api/types'; +} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { CoreSetup, ElasticsearchClient, Logger } from 'src/core/server'; import { ConcreteTaskInstance, @@ -104,7 +104,7 @@ export class CheckMetadataTransformsTask { const [{ elasticsearch }] = await core.getStartServices(); const esClient = elasticsearch.client.asInternalUser; - let transformStatsResponse: ApiResponse; + let transformStatsResponse: TransportResult; try { transformStatsResponse = await esClient?.transform.getTransformStats({ transform_id: METADATA_TRANSFORMS_PATTERN, diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/actions/mocks.ts b/x-pack/plugins/security_solution/server/endpoint/routes/actions/mocks.ts index b50d80a9bae71..1c9d781af38e7 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/actions/mocks.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/actions/mocks.ts @@ -9,7 +9,7 @@ /* eslint-disable max-classes-per-file */ /* eslint-disable @typescript-eslint/no-useless-constructor */ -import { ApiResponse } from '@elastic/elasticsearch'; +import type { TransportResult } from '@elastic/elasticsearch'; import moment from 'moment'; import uuid from 'uuid'; import { @@ -50,7 +50,7 @@ export const mockAuditLogSearchResult = (results?: Results[]) => { return response; }; -export const mockSearchResult = (results: any = []): ApiResponse => { +export const mockSearchResult = (results: any = []): TransportResult => { return { body: { hits: { diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/handlers.ts b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/handlers.ts index e98cdc4f11404..4ef3291e1b8f2 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/handlers.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/handlers.ts @@ -6,8 +6,8 @@ */ import Boom from '@hapi/boom'; -import { ApiResponse } from '@elastic/elasticsearch'; -import { SearchResponse, SearchTotalHits } from '@elastic/elasticsearch/api/types'; +import type { TransportResult } from '@elastic/elasticsearch'; +import { SearchResponse, SearchTotalHits } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { TypeOf } from '@kbn/config-schema'; import { @@ -463,7 +463,7 @@ async function queryUnitedIndex( endpointPolicyIds ); - let unitedMetadataQueryResponse: ApiResponse>; + let unitedMetadataQueryResponse: TransportResult, unknown>; try { unitedMetadataQueryResponse = await context.core.elasticsearch.client.asCurrentUser.search( diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/query_builders.ts b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/query_builders.ts index 7b09013496c6d..8f10bc79bc0ff 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/query_builders.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/query_builders.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query'; import { metadataCurrentIndexPattern, diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/query_strategies.ts b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/query_strategies.ts index ae9d0780de337..3770a6c36fb01 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/query_strategies.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/query_strategies.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { SearchResponse } from '@elastic/elasticsearch/api/types'; +import { SearchResponse } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { HostMetadata } from '../../../../../common/endpoint/types'; import { HostListQueryResult, HostQueryResult } from '../../../types'; diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/test_support.ts b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/test_support.ts index 0207d59137eb3..2ffcc06915e73 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/test_support.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/support/test_support.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { METADATA_UNITED_INDEX } from '../../../../../common/endpoint/constants'; import { HostMetadata, UnitedAgentMetadata } from '../../../../../common/endpoint/types'; diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/policy/handlers.test.ts b/x-pack/plugins/security_solution/server/endpoint/routes/policy/handlers.test.ts index f25171c6734c8..0570eeb708d4e 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/policy/handlers.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/policy/handlers.test.ts @@ -23,7 +23,7 @@ import { loggingSystemMock, savedObjectsClientMock, } from '../../../../../../../src/core/server/mocks'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { GetHostPolicyResponse, HostPolicyResponse } from '../../../../common/endpoint/types'; import { EndpointDocGenerator } from '../../../../common/endpoint/generate_data'; import { parseExperimentalConfigValue } from '../../../../common/experimental_features'; diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/tree/queries/descendants.ts b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/tree/queries/descendants.ts index ba9ac98cbffe4..989d695de4d62 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/resolver/tree/queries/descendants.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/resolver/tree/queries/descendants.ts @@ -5,7 +5,8 @@ * 2.0. */ -import type { ApiResponse, estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { TransportResult } from '@elastic/elasticsearch'; import { IScopedClusterClient } from 'src/core/server'; import { JsonObject, JsonValue } from '@kbn/utility-types'; import { FieldsObject, ResolverSchema } from '../../../../../../common/endpoint/types'; @@ -197,7 +198,7 @@ export class DescendantsQuery { return []; } - let response: ApiResponse>; + let response: TransportResult>; if (this.schema.ancestry) { response = await client.asCurrentUser.search({ body: this.queryWithAncestryArray(validNodes, this.schema.ancestry, limit), diff --git a/x-pack/plugins/security_solution/server/endpoint/services/actions.ts b/x-pack/plugins/security_solution/server/endpoint/services/actions.ts index b25b599517300..87455e6c578bc 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/actions.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/actions.ts @@ -6,8 +6,8 @@ */ import { ElasticsearchClient, Logger } from 'kibana/server'; -import { SearchHit, SearchResponse } from '@elastic/elasticsearch/api/types'; -import { ApiResponse } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { TransportResult } from '@elastic/elasticsearch'; import { AGENT_ACTIONS_INDEX, AGENT_ACTIONS_RESULTS_INDEX } from '../../../../fleet/common'; import { ENDPOINT_ACTION_RESPONSES_INDEX } from '../../../common/endpoint/constants'; import { SecuritySolutionRequestHandlerContext } from '../../types'; @@ -89,8 +89,8 @@ const getActivityLog = async ({ endDate: string; logger: Logger; }): Promise => { - let actionsResult: ApiResponse, unknown>; - let responsesResult: ApiResponse, unknown>; + let actionsResult: TransportResult, unknown>; + let responsesResult: TransportResult, unknown>; try { // fetch actions with matching agent_id @@ -126,14 +126,14 @@ const getActivityLog = async ({ // label record as `action`, `fleetAction` const responses = categorizeResponseResults({ results: responsesResult?.body?.hits?.hits as Array< - SearchHit + estypes.SearchHit >, }); // label record as `response`, `fleetResponse` const actions = categorizeActionResults({ results: actionsResult?.body?.hits?.hits as Array< - SearchHit + estypes.SearchHit >, }); diff --git a/x-pack/plugins/security_solution/server/endpoint/services/metadata/metadata.ts b/x-pack/plugins/security_solution/server/endpoint/services/metadata/metadata.ts index 6bf062c02732e..f82ce73491e57 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/metadata/metadata.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/metadata/metadata.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { HostMetadata } from '../../../../common/endpoint/types'; import { SecuritySolutionRequestHandlerContext } from '../../../types'; import { getESQueryHostMetadataByIDs } from '../../routes/metadata/query_builders'; diff --git a/x-pack/plugins/security_solution/server/endpoint/utils/audit_log_helpers.ts b/x-pack/plugins/security_solution/server/endpoint/utils/audit_log_helpers.ts index f75b265bf24d7..c50a460a377c7 100644 --- a/x-pack/plugins/security_solution/server/endpoint/utils/audit_log_helpers.ts +++ b/x-pack/plugins/security_solution/server/endpoint/utils/audit_log_helpers.ts @@ -7,8 +7,8 @@ import { Logger } from 'kibana/server'; import { SearchRequest } from 'src/plugins/data/public'; -import { SearchHit, SearchResponse } from '@elastic/elasticsearch/api/types'; -import { ApiResponse } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { TransportResult } from '@elastic/elasticsearch'; import { AGENT_ACTIONS_INDEX, AGENT_ACTIONS_RESULTS_INDEX } from '../../../../fleet/common'; import { ENDPOINT_ACTIONS_INDEX, @@ -84,7 +84,7 @@ export const getUniqueLogData = (activityLogEntries: ActivityLogEntry[]): Activi export const categorizeResponseResults = ({ results, }: { - results: Array>; + results: Array>; }): Array => { return results?.length ? results?.map((e) => { @@ -108,7 +108,7 @@ export const categorizeResponseResults = ({ export const categorizeActionResults = ({ results, }: { - results: Array>; + results: Array>; }): Array => { return results?.length ? results?.map((e) => { @@ -153,7 +153,7 @@ export const getActionRequestsResult = async ({ from: number; }): Promise<{ actionIds: string[]; - actionRequests: ApiResponse, unknown>; + actionRequests: TransportResult, unknown>; }> => { const dateFilters = getDateFilters({ startDate, endDate }); const baseActionFilters = [ @@ -189,7 +189,7 @@ export const getActionRequestsResult = async ({ }, }; - let actionRequests: ApiResponse, unknown>; + let actionRequests: TransportResult, unknown>; try { const esClient = context.core.elasticsearch.client.asCurrentUser; actionRequests = await esClient.search(actionsSearchQuery, queryOptions); @@ -220,7 +220,7 @@ export const getActionResponsesResult = async ({ actionIds: string[]; startDate: string; endDate: string; -}): Promise, unknown>> => { +}): Promise, unknown>> => { const dateFilters = getDateFilters({ startDate, endDate }); const baseResponsesFilter = [ { term: { agent_id: elasticAgentId } }, @@ -246,7 +246,7 @@ export const getActionResponsesResult = async ({ }, }; - let actionResponses: ApiResponse, unknown>; + let actionResponses: TransportResult, unknown>; try { const esClient = context.core.elasticsearch.client.asCurrentUser; actionResponses = await esClient.search(responsesSearchQuery, queryOptions); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/migrations/migration_cleanup.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/migrations/migration_cleanup.ts index 00446a204ca89..e8b9b000a47d3 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/migrations/migration_cleanup.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/migrations/migration_cleanup.ts @@ -20,7 +20,7 @@ const getPolicyExists = async ({ }): Promise => { try { await esClient.ilm.getLifecycle({ - policy, + name: policy, }); return true; } catch (err) { @@ -56,7 +56,7 @@ export const ensureMigrationCleanupPolicy = async ({ const policyExists = await getPolicyExists({ esClient, policy }); if (!policyExists) { await esClient.ilm.putLifecycle({ - policy, + name: policy, body: migrationCleanupPolicy, }); } @@ -86,10 +86,8 @@ export const applyMigrationCleanupPolicy = async ({ await esClient.indices.putSettings({ index, body: { - settings: { - lifecycle: { - name: getMigrationCleanupPolicyName(alias), - }, + lifecycle: { + name: getMigrationCleanupPolicyName(alias), }, }, }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/utils.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/utils.test.ts index 2da7a0398bd3f..36e0b6a6c02ab 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/utils.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/notifications/utils.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { SearchHit } from '@elastic/elasticsearch/api/types'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { loggingSystemMock } from 'src/core/server/mocks'; import { SignalSource } from '../signals/types'; import { deconflictSignalsAndResults, getNotificationResultsLink } from './utils'; @@ -41,7 +41,7 @@ describe('utils', () => { }); test('given an empty signal and a single query result it returns the query result in the array', () => { - const querySignals: Array> = [ + const querySignals: Array> = [ { _id: 'id-123', _index: 'index-123', @@ -56,7 +56,7 @@ describe('utils', () => { }); test('given a single signal and an empty query result it returns the query result in the array', () => { - const signals: Array> = [ + const signals: Array> = [ { _id: 'id-123', _index: 'index-123', @@ -71,7 +71,7 @@ describe('utils', () => { }); test('given a signal and a different query result it returns both combined together', () => { - const querySignals: Array> = [ + const querySignals: Array> = [ { _id: 'id-123', _index: 'index-123', @@ -80,7 +80,7 @@ describe('utils', () => { }, }, ]; - const signals: Array> = [ + const signals: Array> = [ { _id: 'id-789', _index: 'index-456', @@ -96,7 +96,7 @@ describe('utils', () => { }); test('given a duplicate in querySignals it returns both combined together without the duplicate', () => { - const querySignals: Array> = [ + const querySignals: Array> = [ { _id: 'id-123', _index: 'index-123', // This should only show up once and not be duplicated twice @@ -112,7 +112,7 @@ describe('utils', () => { }, }, ]; - const signals: Array> = [ + const signals: Array> = [ { _id: 'id-123', // This should only show up once and not be duplicated twice _index: 'index-123', @@ -154,7 +154,7 @@ describe('utils', () => { }); test('given a duplicate in signals it returns both combined together without the duplicate', () => { - const signals: Array> = [ + const signals: Array> = [ { _id: 'id-123', _index: 'index-123', // This should only show up once and not be duplicated twice @@ -170,7 +170,7 @@ describe('utils', () => { }, }, ]; - const querySignals: Array> = [ + const querySignals: Array> = [ { _id: 'id-123', // This should only show up once and not be duplicated twice _index: 'index-123', @@ -206,7 +206,7 @@ describe('utils', () => { }); test('does not give a duplicate in signals if they are only different by their index', () => { - const signals: Array> = [ + const signals: Array> = [ { _id: 'id-123', _index: 'index-123-a', // This is only different by index @@ -222,7 +222,7 @@ describe('utils', () => { }, }, ]; - const querySignals: Array> = [ + const querySignals: Array> = [ { _id: 'id-123', // This is only different by index _index: 'index-123-b', @@ -245,7 +245,7 @@ describe('utils', () => { }); test('it logs a debug statement when it sees a duplicate and returns nothing if both are identical', () => { - const querySignals: Array> = [ + const querySignals: Array> = [ { _id: 'id-123', _index: 'index-123', @@ -254,7 +254,7 @@ describe('utils', () => { }, }, ]; - const signals: Array> = [ + const signals: Array> = [ { _id: 'id-123', _index: 'index-123', @@ -278,7 +278,7 @@ describe('utils', () => { }); test('it logs an error statement if it sees a signal missing an "_id" for an uncommon reason and returns both documents', () => { - const querySignals: Array> = [ + const querySignals: Array> = [ { _id: 'id-123', _index: 'index-123', @@ -305,7 +305,7 @@ describe('utils', () => { }); test('it logs an error statement if it sees a signal missing a "_index" for an uncommon reason and returns both documents', () => { - const querySignals: Array> = [ + const querySignals: Array> = [ { _id: 'id-123', _index: 'index-123', @@ -332,14 +332,14 @@ describe('utils', () => { }); test('it logs an error statement if it sees a querySignals missing an "_id" for an uncommon reason and returns both documents', () => { - const querySignals: Array> = [ + const querySignals: Array> = [ { _index: 'index-123', _source: { test: '123', }, }, - ] as unknown[] as Array>; + ] as unknown[] as Array>; const signals: unknown[] = [ { _id: 'id-123', @@ -359,14 +359,14 @@ describe('utils', () => { }); test('it logs an error statement if it sees a querySignals missing a "_index" for an uncommon reason and returns both documents', () => { - const querySignals: Array> = [ + const querySignals: Array> = [ { _id: 'id-123', _source: { test: '123', }, }, - ] as unknown[] as Array>; + ] as unknown[] as Array>; const signals: unknown[] = [ { _id: 'id-123', diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_responses.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_responses.ts index 1520b4da82d8d..d91d9b29c5b59 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_responses.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/request_responses.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { SavedObjectsFindResponse, SavedObjectsFindResult } from 'src/core/server'; import { ActionResult } from '../../../../../../actions/server'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/create_index_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/create_index_route.ts index b011fd3fcd247..fffc982bb8ae1 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/create_index_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/create_index_route.ts @@ -6,7 +6,7 @@ */ import { get } from 'lodash'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ElasticsearchClient } from 'src/core/server'; import { transformError, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/types.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/types.ts index 545f00ddeacd8..89c01f65b4156 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/types.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/types.ts @@ -7,7 +7,7 @@ import { Moment } from 'moment'; -import { SearchHit } from '@elastic/elasticsearch/api/types'; +import { SearchHit } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Logger } from '@kbn/logging'; import { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_events_query.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_events_query.ts index 065707252c601..c09a60ba165fd 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_events_query.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_events_query.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { isEmpty } from 'lodash'; import { TimestampOverrideOrUndefined } from '../../../../common/detection_engine/schemas/common/schemas'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/bulk_create_ml_signals.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/bulk_create_ml_signals.ts index 00acd55234ad2..2453e92dc3c0a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/bulk_create_ml_signals.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/bulk_create_ml_signals.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { flow, omit } from 'lodash/fp'; import set from 'set-value'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/eql.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/eql.ts index 5317c508b203e..8bd428263a703 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/eql.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/eql.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ApiResponse } from '@elastic/elasticsearch'; +import type { TransportResult } from '@elastic/elasticsearch'; import { performance } from 'perf_hooks'; import type { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; import { Logger } from 'src/core/server'; @@ -120,7 +120,7 @@ export const eqlExecutor = async ({ // TODO: fix this later const { body: response } = (await services.scopedClusterClient.asCurrentUser.transport.request( request - )) as ApiResponse; + )) as TransportResult; const eqlSignalSearchEnd = performance.now(); const eqlSearchDuration = makeFloatString(eqlSignalSearchEnd - eqlSignalSearchStart); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/threshold.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/threshold.ts index 1550caba9434a..2bb5d6880c634 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/threshold.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/executors/threshold.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { SearchHit } from '@elastic/elasticsearch/api/types'; +import { SearchHit } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; import { Logger } from 'src/core/server'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/filter_events.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/filter_events.ts index da664f65c2d50..d267153a4813a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/filter_events.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/filter_events.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { FilterEventsOptions } from './types'; /** diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/filter_events_against_list.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/filter_events_against_list.ts index fffe971753f87..49a8ab0781eb0 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/filter_events_against_list.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/filter_events_against_list.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { entriesList, ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; import { hasLargeValueList } from '@kbn/securitysolution-list-utils'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/types.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/types.ts index 160506b965bf0..5feb8e8b92c5b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/types.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/filters/types.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Logger } from 'src/core/server'; import type { Type, ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.test.ts index 92b66873396ee..62a7e87425d6b 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.test.ts @@ -30,7 +30,7 @@ import { getCompleteRuleMock, getQueryRuleParams } from '../schemas/rule_schemas import { bulkCreateFactory } from './bulk_create_factory'; import { wrapHitsFactory } from './wrap_hits_factory'; import { mockBuildRuleMessage } from './__mocks__/build_rule_message.mock'; -import { ResponseError } from '@elastic/elasticsearch/lib/errors'; +import { errors as esErrors } from '@elastic/elasticsearch'; import { BuildReasonMessage } from './reason_formatters'; import { QueryRuleParams } from '../schemas/rule_schemas'; @@ -755,7 +755,7 @@ describe('searchAfterAndBulkCreate', () => { ); mockService.scopedClusterClient.asCurrentUser.bulk.mockReturnValue( elasticsearchClientMock.createErrorTransportRequestPromise( - new ResponseError( + new esErrors.ResponseError( elasticsearchClientMock.createApiResponse({ statusCode: 400, body: { error: { type: 'bulk_error_type' } }, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.ts index 09b64fc2b654c..de8657f73fa55 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/search_after_bulk_create.ts @@ -6,7 +6,7 @@ */ import { identity } from 'lodash'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { singleSearchAfter } from './single_search_after'; import { filterEventsAgainstList } from './filters/filter_events_against_list'; import { sendAlertTelemetryEvents } from './send_telemetry_events'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.test.ts index c55b3e2a297a3..d3d5a7601c31e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/signal_rule_alert_type.test.ts @@ -6,7 +6,7 @@ */ import moment from 'moment'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { loggingSystemMock } from 'src/core/server/mocks'; import { getAlertMock } from '../routes/__mocks__/request_responses'; import { signalRulesAlertType } from './signal_rule_alert_type'; @@ -24,13 +24,13 @@ import { listMock } from '../../../../../lists/server/mocks'; import { getListClientMock } from '../../../../../lists/server/services/lists/list_client.mock'; import { getExceptionListClientMock } from '../../../../../lists/server/services/exception_lists/exception_list_client.mock'; import { getExceptionListItemSchemaMock } from '../../../../../lists/common/schemas/response/exception_list_item_schema.mock'; -import { ApiResponse } from '@elastic/elasticsearch/lib/Transport'; +import type { TransportResult } from '@elastic/elasticsearch'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks'; import { queryExecutor } from './executors/query'; import { mlExecutor } from './executors/ml'; import { getMlRuleParams, getQueryRuleParams } from '../schemas/rule_schemas.mock'; -import { ResponseError } from '@elastic/elasticsearch/lib/errors'; +import { errors } from '@elastic/elasticsearch'; import { allowedExperimentalValues } from '../../../../common/experimental_features'; import { scheduleNotificationActions } from '../notifications/schedule_notification_actions'; import { ruleExecutionLogClientMock } from '../rule_execution_log/__mocks__/rule_execution_log_client'; @@ -160,7 +160,7 @@ describe('signal_rule_alert_type', () => { (mlExecutor as jest.Mock).mockClear(); (mlExecutor as jest.Mock).mockResolvedValue(executorReturnValue); (parseScheduleDates as jest.Mock).mockReturnValue(moment(100)); - const value: Partial> = { + const value: Partial> = { statusCode: 200, body: { indices: ['index1', 'index2', 'index3', 'index4'], @@ -177,7 +177,7 @@ describe('signal_rule_alert_type', () => { }, }; alertServices.scopedClusterClient.asCurrentUser.fieldCaps.mockResolvedValue( - value as ApiResponse + value as TransportResult ); const ruleAlert = getAlertMock(false, getQueryRuleParams()); alertServices.savedObjectsClient.get.mockResolvedValue({ @@ -494,7 +494,7 @@ describe('signal_rule_alert_type', () => { it('and log failure with the default message', async () => { (queryExecutor as jest.Mock).mockReturnValue( elasticsearchClientMock.createErrorTransportRequestPromise( - new ResponseError( + new errors.ResponseError( elasticsearchClientMock.createApiResponse({ statusCode: 400, body: { error: { type: 'some_error_type' } }, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/single_search_after.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/single_search_after.test.ts index a67016491aaef..d00925af74316 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/single_search_after.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/single_search_after.test.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { sampleDocSearchResultsNoSortId, mockLogger, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/single_search_after.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/single_search_after.ts index 2b1d27fc2fcd0..2596068848ef0 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/single_search_after.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/single_search_after.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { performance } from 'perf_hooks'; import { AlertInstanceContext, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/build_threat_mapping_filter.mock.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/build_threat_mapping_filter.mock.ts index f49e3dec93600..592ab137ee289 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/build_threat_mapping_filter.mock.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/build_threat_mapping_filter.mock.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ThreatMapping } from '@kbn/securitysolution-io-ts-alerting-types'; import { Filter } from 'src/plugins/data/common'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/get_threat_list.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/get_threat_list.ts index 2e10f467b9fc8..94d6be3ea24dd 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/get_threat_list.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/get_threat_list.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { getQueryFilter } from '../../../../../common/detection_engine/get_query_filter'; import { GetSortWithTieBreakerOptions, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/types.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/types.ts index 07baa353dddb7..be17682ea4d08 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/types.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/types.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ThreatQuery, ThreatMapping, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/build_signal_history.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/build_signal_history.ts index 81b12d2d4f229..e5c21edbc9350 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/build_signal_history.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/build_signal_history.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { SearchHit } from '@elastic/elasticsearch/api/types'; +import { SearchHit } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ALERT_ORIGINAL_TIME, ALERT_RULE_THRESHOLD_FIELD, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/types.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/types.ts index c831fb7f00cff..9783cb222e84a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/types.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/types.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { BoolQuery } from '@kbn/es-query'; import moment from 'moment'; import type { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts index 840b897997ddc..48def86203e95 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts @@ -7,7 +7,7 @@ import moment from 'moment'; import sinon from 'sinon'; -import { ApiResponse, Context } from '@elastic/elasticsearch/lib/Transport'; +import { TransportResult } from '@elastic/elasticsearch'; import { alertsMock, AlertServicesMock } from '../../../../../alerting/server/mocks'; import { listMock } from '../../../../../lists/server/mocks'; @@ -638,7 +638,7 @@ describe('utils', () => { test('returns true when missing timestamp override field', async () => { const timestampField = 'event.ingested'; // eslint-disable-next-line @typescript-eslint/no-explicit-any - const timestampFieldCapsResponse: Partial, Context>> = { + const timestampFieldCapsResponse: Partial, unknown>> = { body: { indices: ['myfakeindex-1', 'myfakeindex-2', 'myfakeindex-3', 'myfakeindex-4'], fields: { @@ -663,8 +663,10 @@ describe('utils', () => { const res = await hasTimestampFields({ timestampField, ruleName: 'myfakerulename', - // eslint-disable-next-line @typescript-eslint/no-explicit-any - timestampFieldCapsResponse: timestampFieldCapsResponse as ApiResponse>, + timestampFieldCapsResponse: timestampFieldCapsResponse as TransportResult< + // eslint-disable-next-line @typescript-eslint/no-explicit-any + Record + >, inputIndices: ['myfa*'], ruleStatusClient, ruleId: 'ruleId', @@ -681,7 +683,7 @@ describe('utils', () => { test('returns true when missing timestamp field', async () => { const timestampField = '@timestamp'; // eslint-disable-next-line @typescript-eslint/no-explicit-any - const timestampFieldCapsResponse: Partial, Context>> = { + const timestampFieldCapsResponse: Partial, unknown>> = { body: { indices: ['myfakeindex-1', 'myfakeindex-2', 'myfakeindex-3', 'myfakeindex-4'], fields: { @@ -706,8 +708,10 @@ describe('utils', () => { const res = await hasTimestampFields({ timestampField, ruleName: 'myfakerulename', - // eslint-disable-next-line @typescript-eslint/no-explicit-any - timestampFieldCapsResponse: timestampFieldCapsResponse as ApiResponse>, + timestampFieldCapsResponse: timestampFieldCapsResponse as TransportResult< + // eslint-disable-next-line @typescript-eslint/no-explicit-any + Record + >, inputIndices: ['myfa*'], ruleStatusClient, ruleId: 'ruleId', @@ -725,7 +729,7 @@ describe('utils', () => { test('returns true when missing logs-endpoint.alerts-* index and rule name is Endpoint Security', async () => { const timestampField = '@timestamp'; // eslint-disable-next-line @typescript-eslint/no-explicit-any - const timestampFieldCapsResponse: Partial, Context>> = { + const timestampFieldCapsResponse: Partial, unknown>> = { body: { indices: [], fields: {}, @@ -735,8 +739,10 @@ describe('utils', () => { const res = await hasTimestampFields({ timestampField, ruleName: 'Endpoint Security', - // eslint-disable-next-line @typescript-eslint/no-explicit-any - timestampFieldCapsResponse: timestampFieldCapsResponse as ApiResponse>, + timestampFieldCapsResponse: timestampFieldCapsResponse as TransportResult< + // eslint-disable-next-line @typescript-eslint/no-explicit-any + Record + >, inputIndices: ['logs-endpoint.alerts-*'], ruleStatusClient, ruleId: 'ruleId', @@ -754,7 +760,7 @@ describe('utils', () => { test('returns true when missing logs-endpoint.alerts-* index and rule name is NOT Endpoint Security', async () => { const timestampField = '@timestamp'; // eslint-disable-next-line @typescript-eslint/no-explicit-any - const timestampFieldCapsResponse: Partial, Context>> = { + const timestampFieldCapsResponse: Partial, unknown>> = { body: { indices: [], fields: {}, @@ -764,8 +770,10 @@ describe('utils', () => { const res = await hasTimestampFields({ timestampField, ruleName: 'NOT Endpoint Security', - // eslint-disable-next-line @typescript-eslint/no-explicit-any - timestampFieldCapsResponse: timestampFieldCapsResponse as ApiResponse>, + timestampFieldCapsResponse: timestampFieldCapsResponse as TransportResult< + // eslint-disable-next-line @typescript-eslint/no-explicit-any + Record + >, inputIndices: ['logs-endpoint.alerts-*'], ruleStatusClient, ruleId: 'ruleId', diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts index c7145ec27701b..2ac9c0c18305c 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts @@ -10,8 +10,8 @@ import moment from 'moment'; import uuidv5 from 'uuid/v5'; import dateMath from '@elastic/datemath'; -import type { estypes } from '@elastic/elasticsearch'; -import { ApiResponse, Context } from '@elastic/elasticsearch/lib/Transport'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { TransportResult } from '@elastic/elasticsearch'; import { ALERT_INSTANCE_ID, ALERT_RULE_UUID } from '@kbn/rule-data-utils'; import type { ListArray, ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; import { MAX_EXCEPTION_LIST_SIZE } from '@kbn/securitysolution-list-constants'; @@ -143,9 +143,9 @@ export const hasTimestampFields = async (args: { timestampField: string; ruleName: string; // any is derived from here - // node_modules/@elastic/elasticsearch/api/kibana.d.ts + // node_modules/@elastic/elasticsearch/lib/api/kibana.d.ts // eslint-disable-next-line @typescript-eslint/no-explicit-any - timestampFieldCapsResponse: ApiResponse, Context>; + timestampFieldCapsResponse: TransportResult, unknown>; inputIndices: string[]; ruleStatusClient: IRuleExecutionLogClient; ruleId: string; diff --git a/x-pack/plugins/security_solution/server/lib/machine_learning/index.ts b/x-pack/plugins/security_solution/server/lib/machine_learning/index.ts index 86e1c6dee6180..f8d767a371d9a 100644 --- a/x-pack/plugins/security_solution/server/lib/machine_learning/index.ts +++ b/x-pack/plugins/security_solution/server/lib/machine_learning/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; import { buildExceptionFilter } from '@kbn/securitysolution-list-utils'; diff --git a/x-pack/plugins/security_solution/server/lib/telemetry/receiver.ts b/x-pack/plugins/security_solution/server/lib/telemetry/receiver.ts index 5246b649ebaa1..f8e393fc3994f 100644 --- a/x-pack/plugins/security_solution/server/lib/telemetry/receiver.ts +++ b/x-pack/plugins/security_solution/server/lib/telemetry/receiver.ts @@ -11,7 +11,7 @@ import { ElasticsearchClient, SavedObjectsClientContract, } from 'src/core/server'; -import { SearchRequest } from '@elastic/elasticsearch/api/types'; +import { SearchRequest } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { getTrustedAppsList } from '../../endpoint/routes/trusted_apps/service'; import { AgentService, AgentPolicyServiceInterface } from '../../../../fleet/server'; import { ExceptionListClient } from '../../../../lists/server'; diff --git a/x-pack/plugins/security_solution/server/plugin.ts b/x-pack/plugins/security_solution/server/plugin.ts index e9f2e305b6556..7e485513ff1f8 100644 --- a/x-pack/plugins/security_solution/server/plugin.ts +++ b/x-pack/plugins/security_solution/server/plugin.ts @@ -7,7 +7,7 @@ import { Observable } from 'rxjs'; import LRU from 'lru-cache'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Logger, SavedObjectsClient } from '../../../../src/core/server'; import { UsageCounter } from '../../../../src/plugins/usage_collection/server'; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/cti/event_enrichment/helpers.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/cti/event_enrichment/helpers.ts index 22dba31701e17..4d39a7e12f679 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/cti/event_enrichment/helpers.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/cti/event_enrichment/helpers.ts @@ -6,7 +6,7 @@ */ import { get, isEmpty } from 'lodash'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ENRICHMENT_TYPES, diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/authentications/dsl/query.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/authentications/dsl/query.dsl.ts index 1057ace837b43..c88104745ba06 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/authentications/dsl/query.dsl.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/authentications/dsl/query.dsl.ts @@ -6,7 +6,7 @@ */ import { isEmpty } from 'lodash/fp'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { HostAuthenticationsRequestOptions } from '../../../../../../../common/search_strategy/security_solution/hosts/authentications'; import { sourceFieldsMap, hostFieldsMap } from '../../../../../../../common/ecs/ecs_fields'; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/authentications/dsl/query_entities.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/authentications/dsl/query_entities.dsl.ts index a17bb2ecf9c8f..ab726b41ae01b 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/authentications/dsl/query_entities.dsl.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/authentications/dsl/query_entities.dsl.ts @@ -6,7 +6,7 @@ */ import { isEmpty } from 'lodash/fp'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { HostAuthenticationsRequestOptions } from '../../../../../../../common/search_strategy/security_solution/hosts/authentications'; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/uncommon_processes/dsl/query.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/uncommon_processes/dsl/query.dsl.ts index c5a78354ed866..e87e344e22eca 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/uncommon_processes/dsl/query.dsl.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/uncommon_processes/dsl/query.dsl.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { createQueryFilterClauses } from '../../../../../../utils/build_query'; import { reduceFields } from '../../../../../../utils/build_query/reduce_fields'; import { diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/http/index.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/http/index.ts index 6a36e113b62a7..259b45f436124 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/http/index.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/network/http/index.ts @@ -24,7 +24,6 @@ import { getHttpEdges } from './helpers'; import { buildHttpQuery } from './query.http_network.dsl'; export const networkHttp: SecuritySolutionFactory = { - // @ts-expect-error dns_name_query_count is not conpatible with @elastic/elasticsearch buildDsl: (options: NetworkHttpRequestOptions) => { if (options.pagination && options.pagination.querySize >= DEFAULT_MAX_TABLE_QUERY_SIZE) { throw new Error(`No query size above ${DEFAULT_MAX_TABLE_QUERY_SIZE}`); diff --git a/x-pack/plugins/snapshot_restore/server/routes/api/app.ts b/x-pack/plugins/snapshot_restore/server/routes/api/app.ts index 217bce9721f63..5e6c937088848 100644 --- a/x-pack/plugins/snapshot_restore/server/routes/api/app.ts +++ b/x-pack/plugins/snapshot_restore/server/routes/api/app.ts @@ -53,6 +53,7 @@ export function registerAppRoutes({ body: { has_all_requested: hasAllPrivileges, cluster }, } = await clusterClient.asCurrentUser.security.hasPrivileges({ body: { + // @ts-expect-error @elastic/elasticsearch doesn't declare all possible values in SecurityClusterPrivilege cluster: [...APP_REQUIRED_CLUSTER_PRIVILEGES, ...APP_SLM_CLUSTER_PRIVILEGES], }, }); @@ -73,6 +74,7 @@ export function registerAppRoutes({ } const indexHasAllPrivileges = APP_RESTORE_INDEX_PRIVILEGES.every((privilege) => + // @ts-expect-error SecurityClusterPrivilege doesn’t list all the possible privileges. privileges.includes(privilege) ); diff --git a/x-pack/plugins/snapshot_restore/server/routes/api/policy.ts b/x-pack/plugins/snapshot_restore/server/routes/api/policy.ts index a93540c1ba90d..0458d78263270 100644 --- a/x-pack/plugins/snapshot_restore/server/routes/api/policy.ts +++ b/x-pack/plugins/snapshot_restore/server/routes/api/policy.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { schema, TypeOf } from '@kbn/config-schema'; import { SlmPolicyEs, PolicyIndicesResponse } from '../../../common/types'; @@ -38,7 +38,7 @@ export function registerPolicyRoutes({ body: { policies: Object.entries(policiesByName).map(([name, policy]) => { // TODO: Figure out why our {@link SlmPolicyEs} is not compatible with: - // import type { SnapshotLifecyclePolicyMetadata } from '@elastic/elasticsearch/api/types'; + // import type { SnapshotLifecyclePolicyMetadata } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; return deserializePolicy(name, policy as SlmPolicyEs, managedPolicies); }), }, diff --git a/x-pack/plugins/snapshot_restore/server/routes/api/repositories.ts b/x-pack/plugins/snapshot_restore/server/routes/api/repositories.ts index 6048ec3b52656..c220d92280822 100644 --- a/x-pack/plugins/snapshot_restore/server/routes/api/repositories.ts +++ b/x-pack/plugins/snapshot_restore/server/routes/api/repositories.ts @@ -9,7 +9,7 @@ import { TypeOf } from '@kbn/config-schema'; import type { SnapshotGetRepositoryResponse, SnapshotRepositorySettings, -} from '@elastic/elasticsearch/api/types'; +} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { DEFAULT_REPOSITORY_TYPES, REPOSITORY_PLUGINS_MAP } from '../../../common/constants'; import { Repository, RepositoryType } from '../../../common/types'; @@ -48,7 +48,7 @@ export function registerRepositoriesRoutes({ try { const { body: repositoriesByName } = await clusterClient.asCurrentUser.snapshot.getRepository({ - repository: '_all', + name: '_all', }); repositoryNames = Object.keys(repositoriesByName); repositories = repositoryNames.map((name) => { @@ -107,7 +107,7 @@ export function registerRepositoriesRoutes({ try { ({ body: repositoryByName } = await clusterClient.asCurrentUser.snapshot.getRepository({ - repository: name, + name, })); } catch (e) { return handleEsError({ error: e, response: res }); @@ -196,9 +196,7 @@ export function registerRepositoriesRoutes({ try { const { body: verificationResults } = await clusterClient.asCurrentUser.snapshot - .verifyRepository({ - repository: name, - }) + .verifyRepository({ name }) .catch((e) => ({ body: { valid: false, @@ -234,9 +232,7 @@ export function registerRepositoriesRoutes({ try { const { body: cleanupResults } = await clusterClient.asCurrentUser.snapshot - .cleanupRepository({ - repository: name, - }) + .cleanupRepository({ name }) .catch((e) => ({ body: { cleaned: false, @@ -270,9 +266,7 @@ export function registerRepositoriesRoutes({ // Check that repository with the same name doesn't already exist try { const { body: repositoryByName } = await clusterClient.asCurrentUser.snapshot.getRepository( - { - repository: name, - } + { name } ); if (repositoryByName[name]) { return res.conflict({ body: 'There is already a repository with that name.' }); @@ -284,7 +278,7 @@ export function registerRepositoriesRoutes({ // Otherwise create new repository try { const response = await clusterClient.asCurrentUser.snapshot.createRepository({ - repository: name, + name, body: { type, // TODO: Bring {@link RepositorySettings} in line with {@link SnapshotRepositorySettings} @@ -314,11 +308,11 @@ export function registerRepositoriesRoutes({ try { // Check that repository with the given name exists // If it doesn't exist, 404 will be thrown by ES and will be returned - await clusterClient.asCurrentUser.snapshot.getRepository({ repository: name }); + await clusterClient.asCurrentUser.snapshot.getRepository({ name }); // Otherwise update repository const response = await clusterClient.asCurrentUser.snapshot.createRepository({ - repository: name, + name, body: { type, settings: serializeRepositorySettings(settings) as SnapshotRepositorySettings, @@ -352,7 +346,7 @@ export function registerRepositoriesRoutes({ await Promise.all( repositoryNames.map((repoName) => { return clusterClient.asCurrentUser.snapshot - .deleteRepository({ repository: repoName }) + .deleteRepository({ name: repoName }) .then(() => response.itemsDeleted.push(repoName)) .catch((e) => response.errors.push({ diff --git a/x-pack/plugins/snapshot_restore/server/routes/api/restore.ts b/x-pack/plugins/snapshot_restore/server/routes/api/restore.ts index eb77c5e2d833f..f62256090eaaa 100644 --- a/x-pack/plugins/snapshot_restore/server/routes/api/restore.ts +++ b/x-pack/plugins/snapshot_restore/server/routes/api/restore.ts @@ -6,7 +6,7 @@ */ import { schema, TypeOf } from '@kbn/config-schema'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { SnapshotRestore, SnapshotRestoreShardEs } from '../../../common/types'; import { serializeRestoreSettings } from '../../../common/lib'; diff --git a/x-pack/plugins/snapshot_restore/server/routes/api/snapshots.ts b/x-pack/plugins/snapshot_restore/server/routes/api/snapshots.ts index 4de0c3011fed5..7ff68f7958bfc 100644 --- a/x-pack/plugins/snapshot_restore/server/routes/api/snapshots.ts +++ b/x-pack/plugins/snapshot_restore/server/routes/api/snapshots.ts @@ -76,7 +76,7 @@ export function registerSnapshotsRoutes({ try { const { body: repositoriesByName } = await clusterClient.asCurrentUser.snapshot.getRepository({ - repository: '_all', + name: '_all', }); repositories = Object.keys(repositoriesByName); @@ -157,7 +157,6 @@ export function registerSnapshotsRoutes({ repositories, // @ts-expect-error @elastic/elasticsearch https://github.com/elastic/elasticsearch-specification/issues/845 errors: fetchedSnapshots?.failures, - // @ts-expect-error @elastic/elasticsearch "total" is a new field in the response total: fetchedSnapshots?.total, }, }); diff --git a/x-pack/plugins/stack_alerts/common/build_sorted_events_query.ts b/x-pack/plugins/stack_alerts/common/build_sorted_events_query.ts index 83421056229cf..c3b59dbd1c557 100644 --- a/x-pack/plugins/stack_alerts/common/build_sorted_events_query.ts +++ b/x-pack/plugins/stack_alerts/common/build_sorted_events_query.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { ESSearchRequest } from '../../../../src/core/types/elasticsearch'; interface BuildSortedEventsQueryOpts { diff --git a/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression.tsx b/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression.tsx index 5111f427cd0d8..4cba80a9a541a 100644 --- a/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression.tsx +++ b/x-pack/plugins/stack_alerts/public/alert_types/es_query/expression.tsx @@ -23,7 +23,7 @@ import { EuiLink, } from '@elastic/eui'; import { DocLinksStart, HttpSetup } from 'kibana/public'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { XJson } from '../../../../../../src/plugins/es_ui_shared/public'; import { useKibana } from '../../../../../../src/plugins/kibana_react/public'; diff --git a/x-pack/plugins/stack_alerts/server/alert_types/es_query/action_context.ts b/x-pack/plugins/stack_alerts/server/alert_types/es_query/action_context.ts index 84a4569d9b860..f4886e3c055a2 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/es_query/action_context.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/es_query/action_context.ts @@ -6,7 +6,7 @@ */ import { i18n } from '@kbn/i18n'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { AlertExecutorOptions, AlertInstanceContext } from '../../../../alerting/server'; import { EsQueryAlertParams } from './alert_type_params'; diff --git a/x-pack/plugins/stack_alerts/server/alert_types/es_query/alert_type.ts b/x-pack/plugins/stack_alerts/server/alert_types/es_query/alert_type.ts index 26efdc0c056a5..42f3508f1a2c9 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/es_query/alert_type.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/es_query/alert_type.ts @@ -6,7 +6,7 @@ */ import { i18n } from '@kbn/i18n'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Logger } from 'src/core/server'; import { AlertType, AlertExecutorOptions } from '../../types'; import { ActionContext, EsQueryAlertActionContext, addMessages } from './action_context'; diff --git a/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/es_query_builder.ts b/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/es_query_builder.ts index 9a95517986bee..7efce1153c915 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/es_query_builder.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/es_query_builder.ts @@ -7,7 +7,8 @@ import { ElasticsearchClient } from 'kibana/server'; import { Logger } from 'src/core/server'; -import type { ApiResponse, estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { TransportResult } from '@elastic/elasticsearch'; import { fromKueryExpression, toElasticsearchQuery, @@ -49,7 +50,7 @@ export async function getShapesFilters( const shapesIdsNamesMap: Record = {}; // Get all shapes in index // eslint-disable-next-line @typescript-eslint/no-explicit-any - const { body: boundaryData }: ApiResponse> = await esClient.search({ + const { body: boundaryData }: TransportResult> = await esClient.search({ index: boundaryIndexTitle, body: { size: MAX_SHAPES_QUERY_SIZE, diff --git a/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/geo_containment.ts b/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/geo_containment.ts index f227ae4fc23cc..ecd08d3dc432f 100644 --- a/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/geo_containment.ts +++ b/x-pack/plugins/stack_alerts/server/alert_types/geo_containment/geo_containment.ts @@ -7,7 +7,7 @@ import _ from 'lodash'; import { Logger } from 'src/core/server'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { executeEsQueryFactory, getShapesFilters, OTHER_CATEGORY } from './es_query_builder'; import { AlertServices } from '../../../../alerting/server'; import { diff --git a/x-pack/plugins/task_manager/server/monitoring/workload_statistics.test.ts b/x-pack/plugins/task_manager/server/monitoring/workload_statistics.test.ts index 9628e2807627a..9a63ece0dda46 100644 --- a/x-pack/plugins/task_manager/server/monitoring/workload_statistics.test.ts +++ b/x-pack/plugins/task_manager/server/monitoring/workload_statistics.test.ts @@ -21,7 +21,7 @@ import { times } from 'lodash'; import { taskStoreMock } from '../task_store.mock'; import { of, Subject } from 'rxjs'; import { sleep } from '../test_utils'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; type ResponseWithAggs = Omit, 'aggregations'> & { aggregations: WorkloadAggregationResponse; diff --git a/x-pack/plugins/task_manager/server/monitoring/workload_statistics.ts b/x-pack/plugins/task_manager/server/monitoring/workload_statistics.ts index 9ac528cfd1ced..1ea3e5c6242e2 100644 --- a/x-pack/plugins/task_manager/server/monitoring/workload_statistics.ts +++ b/x-pack/plugins/task_manager/server/monitoring/workload_statistics.ts @@ -10,7 +10,7 @@ import { mergeMap, map, filter, switchMap, catchError } from 'rxjs/operators'; import { Logger } from 'src/core/server'; import { JsonObject } from '@kbn/utility-types'; import { keyBy, mapValues } from 'lodash'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { AggregatedStatProvider } from './runtime_statistics_aggregator'; import { parseIntervalAsSecond, asInterval, parseIntervalAsMillisecond } from '../lib/intervals'; import { AggregationResultOf } from '../../../../../src/core/types/elasticsearch'; diff --git a/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.ts b/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.ts index 3183f364001d9..47f4722562973 100644 --- a/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.ts +++ b/x-pack/plugins/task_manager/server/queries/mark_available_tasks_as_claimed.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ScriptBasedSortClause, ScriptClause, diff --git a/x-pack/plugins/task_manager/server/queries/query_clauses.ts b/x-pack/plugins/task_manager/server/queries/query_clauses.ts index 5f7cc8ed2bdb3..6fc5677594f3d 100644 --- a/x-pack/plugins/task_manager/server/queries/query_clauses.ts +++ b/x-pack/plugins/task_manager/server/queries/query_clauses.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; export interface MustCondition { bool: Pick; diff --git a/x-pack/plugins/task_manager/server/saved_objects/index.ts b/x-pack/plugins/task_manager/server/saved_objects/index.ts index bb8b247af87b8..c85d7f31ec41e 100644 --- a/x-pack/plugins/task_manager/server/saved_objects/index.ts +++ b/x-pack/plugins/task_manager/server/saved_objects/index.ts @@ -6,7 +6,7 @@ */ import type { SavedObjectsServiceSetup, SavedObjectsTypeMappingDefinition } from 'kibana/server'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import mappings from './mappings.json'; import { getMigrations } from './migrations'; import { TaskManagerConfig } from '../config.js'; diff --git a/x-pack/plugins/task_manager/server/task_store.test.ts b/x-pack/plugins/task_manager/server/task_store.test.ts index f3b4014c9c919..4a5637d75b65f 100644 --- a/x-pack/plugins/task_manager/server/task_store.test.ts +++ b/x-pack/plugins/task_manager/server/task_store.test.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import _ from 'lodash'; import { first } from 'rxjs/operators'; diff --git a/x-pack/plugins/task_manager/server/task_store.ts b/x-pack/plugins/task_manager/server/task_store.ts index bcd4b3b1885f9..4f13f95497a42 100644 --- a/x-pack/plugins/task_manager/server/task_store.ts +++ b/x-pack/plugins/task_manager/server/task_store.ts @@ -11,7 +11,7 @@ import { Subject } from 'rxjs'; import { omit, defaults } from 'lodash'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { SavedObject, diff --git a/x-pack/plugins/telemetry_collection_xpack/server/telemetry_collection/get_license.ts b/x-pack/plugins/telemetry_collection_xpack/server/telemetry_collection/get_license.ts index ad7d5439f8765..ff16d272b17b2 100644 --- a/x-pack/plugins/telemetry_collection_xpack/server/telemetry_collection/get_license.ts +++ b/x-pack/plugins/telemetry_collection_xpack/server/telemetry_collection/get_license.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ElasticsearchClient } from 'src/core/server'; export type ESLicense = estypes.LicenseGetLicenseInformation; diff --git a/x-pack/plugins/telemetry_collection_xpack/server/telemetry_collection/get_stats_with_xpack.test.ts b/x-pack/plugins/telemetry_collection_xpack/server/telemetry_collection/get_stats_with_xpack.test.ts index 75b9c736de901..2d1fea23c5ef3 100644 --- a/x-pack/plugins/telemetry_collection_xpack/server/telemetry_collection/get_stats_with_xpack.test.ts +++ b/x-pack/plugins/telemetry_collection_xpack/server/telemetry_collection/get_stats_with_xpack.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { coreMock, elasticsearchServiceMock } from '../../../../../src/core/server/mocks'; import { getStatsWithXpack } from './get_stats_with_xpack'; import { SavedObjectsClient } from '../../../../../src/core/server'; diff --git a/x-pack/plugins/timelines/common/search_strategy/common/index.ts b/x-pack/plugins/timelines/common/search_strategy/common/index.ts index 62c2187e267fa..976b0bfc373d1 100644 --- a/x-pack/plugins/timelines/common/search_strategy/common/index.ts +++ b/x-pack/plugins/timelines/common/search_strategy/common/index.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; export type Maybe = T | null; diff --git a/x-pack/plugins/timelines/common/search_strategy/eql/validation/helpers.mock.ts b/x-pack/plugins/timelines/common/search_strategy/eql/validation/helpers.mock.ts index b3a2c9c9a3f62..0c620fbdd348d 100644 --- a/x-pack/plugins/timelines/common/search_strategy/eql/validation/helpers.mock.ts +++ b/x-pack/plugins/timelines/common/search_strategy/eql/validation/helpers.mock.ts @@ -5,10 +5,10 @@ * 2.0. */ -import { ApiResponse } from '@elastic/elasticsearch'; +import type { TransportResult } from '@elastic/elasticsearch'; import { ErrorResponse } from './helpers'; -export const getValidEqlResponse = (): ApiResponse['body'] => ({ +export const getValidEqlResponse = (): TransportResult['body'] => ({ is_partial: false, is_running: false, took: 162, @@ -56,7 +56,7 @@ export const getEqlResponseWithValidationErrors = (): ErrorResponse => ({ }, }); -export const getEqlResponseWithNonValidationError = (): ApiResponse['body'] => ({ +export const getEqlResponseWithNonValidationError = (): TransportResult['body'] => ({ error: { root_cause: [ { diff --git a/x-pack/plugins/timelines/public/container/use_update_alerts.ts b/x-pack/plugins/timelines/public/container/use_update_alerts.ts index 1b9e6218eecca..37a1fe1671fbd 100644 --- a/x-pack/plugins/timelines/public/container/use_update_alerts.ts +++ b/x-pack/plugins/timelines/public/container/use_update_alerts.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { CoreStart } from '../../../../../src/core/public'; import { useKibana } from '../../../../../src/plugins/kibana_react/public'; diff --git a/x-pack/plugins/transform/common/api_schemas/type_guards.ts b/x-pack/plugins/transform/common/api_schemas/type_guards.ts index 1f27f1798c8e7..9fcf01f80cf66 100644 --- a/x-pack/plugins/transform/common/api_schemas/type_guards.ts +++ b/x-pack/plugins/transform/common/api_schemas/type_guards.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { EsIndex } from '../types/es_index'; import { isPopulatedObject } from '../shared_imports'; diff --git a/x-pack/plugins/transform/public/app/common/request.ts b/x-pack/plugins/transform/public/app/common/request.ts index a7a3a91f9429b..8f8341260bd7e 100644 --- a/x-pack/plugins/transform/public/app/common/request.ts +++ b/x-pack/plugins/transform/public/app/common/request.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { HttpFetchError } from '../../../../../../src/core/public'; import type { IndexPattern } from '../../../../../../src/plugins/data/public'; diff --git a/x-pack/plugins/transform/public/app/hooks/__mocks__/use_api.ts b/x-pack/plugins/transform/public/app/hooks/__mocks__/use_api.ts index 3d5e1783f8c62..979a98ececabb 100644 --- a/x-pack/plugins/transform/public/app/hooks/__mocks__/use_api.ts +++ b/x-pack/plugins/transform/public/app/hooks/__mocks__/use_api.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { HttpFetchError } from 'kibana/public'; diff --git a/x-pack/plugins/transform/public/app/hooks/use_api.ts b/x-pack/plugins/transform/public/app/hooks/use_api.ts index 1abe2ed09444e..21e37ca16c4de 100644 --- a/x-pack/plugins/transform/public/app/hooks/use_api.ts +++ b/x-pack/plugins/transform/public/app/hooks/use_api.ts @@ -7,7 +7,7 @@ import { useMemo } from 'react'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { HttpFetchError } from 'kibana/public'; diff --git a/x-pack/plugins/transform/public/app/hooks/use_index_data.ts b/x-pack/plugins/transform/public/app/hooks/use_index_data.ts index 55a304207a1c7..3b26f0cffb28e 100644 --- a/x-pack/plugins/transform/public/app/hooks/use_index_data.ts +++ b/x-pack/plugins/transform/public/app/hooks/use_index_data.ts @@ -7,7 +7,7 @@ import { useEffect, useMemo, useState } from 'react'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import type { EuiDataGridColumn } from '@elastic/eui'; import { diff --git a/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx b/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx index da7100a31167a..2456c61b6c2ed 100644 --- a/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx +++ b/x-pack/plugins/transform/public/app/sections/create_transform/components/step_define/common/filter_agg/components/filter_term_form.tsx @@ -6,7 +6,7 @@ */ import React, { useCallback, useContext, useEffect, useState } from 'react'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { EuiComboBox, EuiComboBoxOptionOption, EuiFormRow } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { debounce } from 'lodash'; diff --git a/x-pack/plugins/transform/server/lib/alerting/transform_health_rule_type/transform_health_service.ts b/x-pack/plugins/transform/server/lib/alerting/transform_health_rule_type/transform_health_service.ts index eb51c04e0bca7..020f5739cd67b 100644 --- a/x-pack/plugins/transform/server/lib/alerting/transform_health_rule_type/transform_health_service.ts +++ b/x-pack/plugins/transform/server/lib/alerting/transform_health_rule_type/transform_health_service.ts @@ -7,7 +7,7 @@ import { ElasticsearchClient } from 'kibana/server'; import { i18n } from '@kbn/i18n'; -import type { Transform as EsTransform } from '@elastic/elasticsearch/api/types'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { keyBy } from 'lodash'; import { TransformHealthRuleParams } from './schema'; import { @@ -29,8 +29,7 @@ interface TestResult { context: TransformHealthAlertContext; } -// @ts-ignore FIXME update types in the elasticsearch client -type Transform = EsTransform & { id: string; description?: string; sync: object }; +type Transform = estypes.Transform & { id: string; description?: string; sync: object }; type TransformWithAlertingRules = Transform & { alerting_rules: TransformHealthAlertRule[] }; diff --git a/x-pack/plugins/transform/server/routes/api/privileges.ts b/x-pack/plugins/transform/server/routes/api/privileges.ts index f1900079ec9c4..6029260e13914 100644 --- a/x-pack/plugins/transform/server/routes/api/privileges.ts +++ b/x-pack/plugins/transform/server/routes/api/privileges.ts @@ -33,6 +33,7 @@ export function registerPrivilegesRoute({ router, license }: RouteDependencies) body: { has_all_requested: hasAllPrivileges, cluster }, } = await ctx.core.elasticsearch.client.asCurrentUser.security.hasPrivileges({ body: { + // @ts-expect-error SecurityClusterPrivilege doesn’t contain all the priviledges cluster: APP_CLUSTER_PRIVILEGES, }, }); diff --git a/x-pack/plugins/transform/server/routes/api/transforms.ts b/x-pack/plugins/transform/server/routes/api/transforms.ts index a41c65e1be606..e19ac2c39c129 100644 --- a/x-pack/plugins/transform/server/routes/api/transforms.ts +++ b/x-pack/plugins/transform/server/routes/api/transforms.ts @@ -6,7 +6,7 @@ */ import { schema } from '@kbn/config-schema'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { ElasticsearchClient, @@ -16,10 +16,6 @@ import { SavedObjectsClientContract, } from 'kibana/server'; -import { - TransformGetTransform, - TransformGetTransformStats, -} from '@elastic/elasticsearch/api/requestParams'; import { TRANSFORM_STATE } from '../../../common/constants'; import { transformIdParamSchema, @@ -85,28 +81,32 @@ export function registerTransformsRoutes(routeDependencies: RouteDependencies) { */ router.get( { path: addBasePath('transforms'), validate: false }, - license.guardApiRoute(async (ctx, req, res) => { - try { - const { body } = await ctx.core.elasticsearch.client.asCurrentUser.transform.getTransform({ - size: 1000, - ...req.params, - }); - - if (ctx.alerting) { - const transformHealthService = transformHealthServiceProvider( - ctx.core.elasticsearch.client.asCurrentUser, - ctx.alerting.getRulesClient() + license.guardApiRoute( + async (ctx, req, res) => { + try { + const { body } = await ctx.core.elasticsearch.client.asCurrentUser.transform.getTransform( + { + size: 1000, + ...req.params, + } ); - // @ts-ignore - await transformHealthService.populateTransformsWithAssignedRules(body.transforms); - } + if (ctx.alerting) { + const transformHealthService = transformHealthServiceProvider( + ctx.core.elasticsearch.client.asCurrentUser, + ctx.alerting.getRulesClient() + ); - return res.ok({ body }); - } catch (e) { - return res.customError(wrapError(wrapEsError(e))); + // @ts-ignore + await transformHealthService.populateTransformsWithAssignedRules(body.transforms); + } + + return res.ok({ body }); + } catch (e) { + return res.customError(wrapError(wrapEsError(e))); + } } - }) + ) ); /** @@ -145,7 +145,7 @@ export function registerTransformsRoutes(routeDependencies: RouteDependencies) { */ router.get( { path: addBasePath('transforms/_stats'), validate: false }, - license.guardApiRoute( + license.guardApiRoute( async (ctx, req, res) => { try { const { body } = @@ -555,7 +555,6 @@ const previewTransformHandler: RequestHandler< try { const reqBody = req.body; const { body } = await ctx.core.elasticsearch.client.asCurrentUser.transform.previewTransform({ - // @ts-expect-error max_page_search_size is required in TransformPivot body: reqBody, }); if (isLatestTransform(reqBody)) { diff --git a/x-pack/plugins/transform/server/routes/api/transforms_nodes.ts b/x-pack/plugins/transform/server/routes/api/transforms_nodes.ts index 29a3c50b2eea9..5a260b63d5501 100644 --- a/x-pack/plugins/transform/server/routes/api/transforms_nodes.ts +++ b/x-pack/plugins/transform/server/routes/api/transforms_nodes.ts @@ -54,6 +54,7 @@ export function registerTransformNodesRoutes({ router, license }: RouteDependenc body: { has_all_requested: hasAllPrivileges }, } = await ctx.core.elasticsearch.client.asCurrentUser.security.hasPrivileges({ body: { + // @ts-expect-error SecurityClusterPrivilege doesn’t contain all the priviledges cluster: NODES_INFO_PRIVILEGES, }, }); diff --git a/x-pack/plugins/triggers_actions_ui/server/data/lib/time_series_query.test.ts b/x-pack/plugins/triggers_actions_ui/server/data/lib/time_series_query.test.ts index 46fd82f4bd70e..5afe37df536a6 100644 --- a/x-pack/plugins/triggers_actions_ui/server/data/lib/time_series_query.test.ts +++ b/x-pack/plugins/triggers_actions_ui/server/data/lib/time_series_query.test.ts @@ -7,7 +7,7 @@ // test error conditions of calling timeSeriesQuery - postive results tested in FT -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { loggingSystemMock } from '../../../../../../src/core/server/mocks'; import { Logger } from '../../../../../../src/core/server'; import { TimeSeriesQuery, timeSeriesQuery, getResultFromEs } from './time_series_query'; diff --git a/x-pack/plugins/triggers_actions_ui/server/data/lib/time_series_query.ts b/x-pack/plugins/triggers_actions_ui/server/data/lib/time_series_query.ts index a90d903d71db5..0be981661f565 100644 --- a/x-pack/plugins/triggers_actions_ui/server/data/lib/time_series_query.ts +++ b/x-pack/plugins/triggers_actions_ui/server/data/lib/time_series_query.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Logger, ElasticsearchClient } from 'kibana/server'; import { getEsErrorMessage } from '../../../../alerting/server'; import { DEFAULT_GROUPS } from '../index'; diff --git a/x-pack/plugins/upgrade_assistant/common/types.ts b/x-pack/plugins/upgrade_assistant/common/types.ts index a390dd26a0747..a296e158481fa 100644 --- a/x-pack/plugins/upgrade_assistant/common/types.ts +++ b/x-pack/plugins/upgrade_assistant/common/types.ts @@ -5,10 +5,7 @@ * 2.0. */ -import { - MigrationDeprecationInfoDeprecation, - MigrationDeprecationInfoResponse, -} from '@elastic/elasticsearch/api/types'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { SavedObject, SavedObjectAttributes } from 'src/core/public'; export enum ReindexStep { @@ -210,8 +207,8 @@ export interface IndexSettingAction { deprecatedSettings: string[]; } export interface EnrichedDeprecationInfo - extends Omit { - type: keyof MigrationDeprecationInfoResponse; + extends Omit { + type: keyof estypes.MigrationDeprecationsResponse; isCritical: boolean; index?: string; correctiveAction?: ReindexAction | MlAction | IndexSettingAction; diff --git a/x-pack/plugins/upgrade_assistant/server/lib/es_deprecations_status.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_deprecations_status.test.ts index e1a348f8ed8ee..99c101e04e36b 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/es_deprecations_status.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/es_deprecations_status.test.ts @@ -6,19 +6,19 @@ */ import _ from 'lodash'; -import { RequestEvent } from '@elastic/elasticsearch/lib/Transport'; +import { TransportResult } from '@elastic/elasticsearch'; import { elasticsearchServiceMock } from 'src/core/server/mocks'; -import { MigrationDeprecationInfoResponse } from '@elastic/elasticsearch/api/types'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { getESUpgradeStatus } from './es_deprecations_status'; import fakeDeprecations from './__fixtures__/fake_deprecations.json'; const fakeIndexNames = Object.keys(fakeDeprecations.index_settings); -const asApiResponse = (body: T): RequestEvent => +const asApiResponse = (body: T): TransportResult => ({ body, - } as RequestEvent); + } as TransportResult); describe('getESUpgradeStatus', () => { const resolvedIndices = { @@ -32,7 +32,7 @@ describe('getESUpgradeStatus', () => { }; // @ts-expect-error mock data is too loosely typed - const deprecationsResponse: MigrationDeprecationInfoResponse = _.cloneDeep(fakeDeprecations); + const deprecationsResponse: estypes.MigrationDeprecationsResponse = _.cloneDeep(fakeDeprecations); const esClient = elasticsearchServiceMock.createScopedClusterClient(); diff --git a/x-pack/plugins/upgrade_assistant/server/lib/es_deprecations_status.ts b/x-pack/plugins/upgrade_assistant/server/lib/es_deprecations_status.ts index cd719cc0f32b5..aa08ecef78d32 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/es_deprecations_status.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/es_deprecations_status.ts @@ -5,10 +5,7 @@ * 2.0. */ -import { - MigrationDeprecationInfoDeprecation, - MigrationDeprecationInfoResponse, -} from '@elastic/elasticsearch/api/types'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { IScopedClusterClient } from 'src/core/server'; import { indexSettingDeprecations } from '../../common/constants'; import { EnrichedDeprecationInfo, ESUpgradeStatus } from '../../common/types'; @@ -28,8 +25,8 @@ export async function getESUpgradeStatus( combinedDeprecations = combinedDeprecations.concat(indices); } else { const deprecationsByType = deprecations[ - deprecationType as keyof MigrationDeprecationInfoResponse - ] as MigrationDeprecationInfoDeprecation[]; + deprecationType as keyof estypes.MigrationDeprecationsResponse + ] as estypes.MigrationDeprecationsDeprecation[]; const enrichedDeprecationInfo = deprecationsByType.map( ({ @@ -46,7 +43,7 @@ export async function getESUpgradeStatus( details, message, url, - type: deprecationType as keyof MigrationDeprecationInfoResponse, + type: deprecationType as keyof estypes.MigrationDeprecationsResponse, isCritical: level === 'critical', resolveDuringUpgrade, correctiveAction: getCorrectiveAction(message, metadata), @@ -72,7 +69,7 @@ export async function getESUpgradeStatus( // Reformats the index deprecations to an array of deprecation warnings extended with an index field. const getCombinedIndexInfos = async ( - deprecations: MigrationDeprecationInfoResponse, + deprecations: estypes.MigrationDeprecationsResponse, dataClient: IScopedClusterClient ) => { const indices = Object.keys(deprecations.index_settings).reduce( diff --git a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/index_settings.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/index_settings.ts index 0fb531b286854..b65984af5deb3 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/index_settings.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/index_settings.ts @@ -99,7 +99,7 @@ export const getDeprecatedSettingWarning = ( ): ReindexWarning | undefined => { const { settings } = flatSettings; - const deprecatedSettingsInUse = Object.keys(settings).filter((setting) => { + const deprecatedSettingsInUse = Object.keys(settings || {}).filter((setting) => { return deprecatedSettings.indexOf(setting) > -1; }); diff --git a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.test.ts index ce1e8e11eb2d1..7595e1da7b573 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_actions.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { RequestEvent } from '@elastic/elasticsearch/lib/Transport'; +import { TransportResult } from '@elastic/elasticsearch'; import { SavedObjectsErrorHelpers } from 'src/core/server'; import { elasticsearchServiceMock } from 'src/core/server/mocks'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths @@ -257,10 +257,10 @@ describe('ReindexActions', () => { }); describe('getFlatSettings', () => { - const asApiResponse = (body: T): RequestEvent => + const asApiResponse = (body: T): TransportResult => ({ body, - } as RequestEvent); + } as TransportResult); it('returns flat settings', async () => { clusterClient.asCurrentUser.indices.get.mockResolvedValueOnce( diff --git a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts index 6017691a9328d..bd31196dbb78b 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.test.ts @@ -7,7 +7,7 @@ jest.mock('../es_indices_state_check', () => ({ esIndicesStateCheck: jest.fn() })); import { BehaviorSubject } from 'rxjs'; -import { RequestEvent } from '@elastic/elasticsearch/lib/Transport'; +import { TransportResult } from '@elastic/elasticsearch'; import { Logger } from 'src/core/server'; import { elasticsearchServiceMock, loggingSystemMock } from 'src/core/server/mocks'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths @@ -35,10 +35,10 @@ import { reindexServiceFactory, } from './reindex_service'; -const asApiResponse = (body: T): RequestEvent => +const asApiResponse = (body: T): TransportResult => ({ body, - } as RequestEvent); + } as TransportResult); const { currentMajor, prevMajor } = getMockVersionInfo(); @@ -793,7 +793,7 @@ describe('reindexService', () => { expect(updatedOp.attributes.lastCompletedStep).toEqual(ReindexStep.readonly); expect(clusterClient.asCurrentUser.indices.putSettings).toHaveBeenCalledWith({ index: 'myIndex', - body: { settings: { blocks: { write: true } } }, + body: { blocks: { write: true } }, }); }); @@ -885,7 +885,7 @@ describe('reindexService', () => { // Original index should have been set back to allow reads. expect(clusterClient.asCurrentUser.indices.putSettings).toHaveBeenCalledWith({ index: 'myIndex', - body: { settings: { blocks: { write: false } } }, + body: { blocks: { write: false } }, }); }); }); diff --git a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.ts index 1bf45e3a4a038..77b5495bd4563 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/reindex_service.ts @@ -226,7 +226,7 @@ export const reindexServiceFactory = ( if (reindexOp.attributes.lastCompletedStep >= ReindexStep.readonly) { await esClient.indices.putSettings({ index: reindexOp.attributes.indexName, - body: { settings: { blocks: { write: false } } }, + body: { blocks: { write: false } }, }); } @@ -290,7 +290,7 @@ export const reindexServiceFactory = ( const { indexName } = reindexOp.attributes; const { body: putReadonly } = await esClient.indices.putSettings({ index: indexName, - body: { settings: { blocks: { write: true } } }, + body: { blocks: { write: true } }, }); if (!putReadonly.acknowledged) { diff --git a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/types.ts b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/types.ts index ddff137772ae8..8d600849987db 100644 --- a/x-pack/plugins/upgrade_assistant/server/lib/reindexing/types.ts +++ b/x-pack/plugins/upgrade_assistant/server/lib/reindexing/types.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; interface Mapping { type?: string; @@ -20,7 +20,7 @@ interface MetaProperties { } export interface FlatSettings { - settings: estypes.IndicesIndexState['settings']; + settings?: estypes.IndicesIndexState['settings']; mappings?: { properties?: MappingProperties; _meta?: MetaProperties; diff --git a/x-pack/plugins/upgrade_assistant/server/routes/ml_snapshots.ts b/x-pack/plugins/upgrade_assistant/server/routes/ml_snapshots.ts index f23de49d97dc8..65e707339d67c 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/ml_snapshots.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/ml_snapshots.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ResponseError } from '@elastic/elasticsearch/lib/errors'; +import { errors } from '@elastic/elasticsearch'; import { schema } from '@kbn/config-schema'; import { IScopedClusterClient, SavedObjectsClientContract } from 'kibana/server'; import { API_BASE_PATH } from '../../common/constants'; @@ -56,7 +56,7 @@ const verifySnapshotUpgrade = async ( snapshot: { snapshotId: string; jobId: string } ): Promise<{ isSuccessful: boolean; - error?: ResponseError; + error?: errors.ResponseError; }> => { const { snapshotId, jobId } = snapshot; @@ -257,7 +257,7 @@ export function registerMlSnapshotRoutes({ router }: RouteDependencies) { } return response.customError({ - statusCode: upgradeSnapshotError ? upgradeSnapshotError.statusCode : 500, + statusCode: upgradeSnapshotError ? upgradeSnapshotError.statusCode! : 500, body: { message: upgradeSnapshotError?.body?.error?.reason || @@ -286,7 +286,7 @@ export function registerMlSnapshotRoutes({ router }: RouteDependencies) { } return response.customError({ - statusCode: upgradeSnapshotError ? upgradeSnapshotError.statusCode : 500, + statusCode: upgradeSnapshotError ? upgradeSnapshotError.statusCode! : 500, body: { message: upgradeSnapshotError?.body?.error?.reason || diff --git a/x-pack/plugins/upgrade_assistant/server/routes/update_index_settings.ts b/x-pack/plugins/upgrade_assistant/server/routes/update_index_settings.ts index b90ff4281644b..751e685002a99 100644 --- a/x-pack/plugins/upgrade_assistant/server/routes/update_index_settings.ts +++ b/x-pack/plugins/upgrade_assistant/server/routes/update_index_settings.ts @@ -44,9 +44,7 @@ export function registerUpdateSettingsRoute({ router }: RouteDependencies) { const { body: settingsResponse } = await client.asCurrentUser.indices.putSettings({ index: indexName, - body: { - settings: settingsToDelete, - }, + body: settingsToDelete, }); return response.ok({ diff --git a/x-pack/plugins/uptime/common/requests/get_certs_request_body.ts b/x-pack/plugins/uptime/common/requests/get_certs_request_body.ts index 5a729c7e3b96d..ca72717ff4113 100644 --- a/x-pack/plugins/uptime/common/requests/get_certs_request_body.ts +++ b/x-pack/plugins/uptime/common/requests/get_certs_request_body.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { CertResult, GetCertsParams, Ping } from '../runtime_types'; import { createEsQuery } from '../utils/es_search'; diff --git a/x-pack/plugins/uptime/common/utils/es_search.ts b/x-pack/plugins/uptime/common/utils/es_search.ts index ba72d09a4e8ef..6a41b83d19ee0 100644 --- a/x-pack/plugins/uptime/common/utils/es_search.ts +++ b/x-pack/plugins/uptime/common/utils/es_search.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; export function createEsQuery(params: T): T { return params; diff --git a/x-pack/plugins/uptime/public/components/overview/monitor_list/use_monitor_histogram.ts b/x-pack/plugins/uptime/public/components/overview/monitor_list/use_monitor_histogram.ts index a3985fe5ccca5..8f500f54cf4ba 100644 --- a/x-pack/plugins/uptime/public/components/overview/monitor_list/use_monitor_histogram.ts +++ b/x-pack/plugins/uptime/public/components/overview/monitor_list/use_monitor_histogram.ts @@ -7,7 +7,7 @@ import { useContext } from 'react'; import { useSelector } from 'react-redux'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Histogram, HistogramPoint, diff --git a/x-pack/plugins/uptime/server/lib/lib.ts b/x-pack/plugins/uptime/server/lib/lib.ts index eb2ad9ce21b9e..894bf743499f9 100644 --- a/x-pack/plugins/uptime/server/lib/lib.ts +++ b/x-pack/plugins/uptime/server/lib/lib.ts @@ -12,7 +12,7 @@ import { ISavedObjectsRepository, } from 'kibana/server'; import chalk from 'chalk'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { UMBackendFrameworkAdapter } from './adapters'; import { UMLicenseCheck } from './domains'; import { UptimeRequests } from './requests'; diff --git a/x-pack/plugins/uptime/server/lib/requests/get_index_status.ts b/x-pack/plugins/uptime/server/lib/requests/get_index_status.ts index dcd61d5331aa4..f9215b5af31e4 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_index_status.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_index_status.ts @@ -19,7 +19,7 @@ export const getIndexStatus: UMElasticsearchQueryFn<{}, StatesIndexStatus> = asy count, }, }, - } = await uptimeEsClient.count({ terminateAfter: 1 }); + } = await uptimeEsClient.count({ terminate_after: 1 }); return { indices, indexExists: total > 0, diff --git a/x-pack/plugins/uptime/server/lib/requests/get_journey_details.ts b/x-pack/plugins/uptime/server/lib/requests/get_journey_details.ts index b389699e2074a..24e33b9248da6 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_journey_details.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_journey_details.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { UMElasticsearchQueryFn } from '../adapters/framework'; import { JourneyStep, diff --git a/x-pack/plugins/uptime/server/lib/requests/get_journey_failed_steps.ts b/x-pack/plugins/uptime/server/lib/requests/get_journey_failed_steps.ts index 52a7b67000fec..c53f1b589ef7a 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_journey_failed_steps.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_journey_failed_steps.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { asMutableArray } from '../../../common/utils/as_mutable_array'; import { UMElasticsearchQueryFn } from '../adapters/framework'; import { JourneyStep } from '../../../common/runtime_types/ping/synthetics'; diff --git a/x-pack/plugins/uptime/server/lib/requests/get_journey_screenshot.ts b/x-pack/plugins/uptime/server/lib/requests/get_journey_screenshot.ts index 3d95d35aa90d0..be9f21d4cea02 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_journey_screenshot.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_journey_screenshot.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { UMElasticsearchQueryFn } from '../adapters'; import { RefResult, FullScreenshot } from '../../../common/runtime_types/ping/synthetics'; diff --git a/x-pack/plugins/uptime/server/lib/requests/get_journey_steps.ts b/x-pack/plugins/uptime/server/lib/requests/get_journey_steps.ts index f843859575e31..3e48ae7cccfbc 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_journey_steps.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_journey_steps.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { asMutableArray } from '../../../common/utils/as_mutable_array'; import { UMElasticsearchQueryFn } from '../adapters/framework'; import { JourneyStep } from '../../../common/runtime_types/ping/synthetics'; diff --git a/x-pack/plugins/uptime/server/lib/requests/get_last_successful_step.ts b/x-pack/plugins/uptime/server/lib/requests/get_last_successful_step.ts index 6d0f72052e586..e096cdaa65b86 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_last_successful_step.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_last_successful_step.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { UMElasticsearchQueryFn } from '../adapters/framework'; import { JourneyStep } from '../../../common/runtime_types/ping'; diff --git a/x-pack/plugins/uptime/server/lib/requests/get_latest_monitor.ts b/x-pack/plugins/uptime/server/lib/requests/get_latest_monitor.ts index 36968fa97fda4..f6f1d7ff938be 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_latest_monitor.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_latest_monitor.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { UMElasticsearchQueryFn } from '../adapters'; import { Ping } from '../../../common/runtime_types'; diff --git a/x-pack/plugins/uptime/server/lib/requests/get_monitor_availability.ts b/x-pack/plugins/uptime/server/lib/requests/get_monitor_availability.ts index bf6c176a233c4..4d51a4857ecaa 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_monitor_availability.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_monitor_availability.ts @@ -148,9 +148,7 @@ export const getMonitorAvailability: UMElasticsearchQueryFn< }; const { body: result } = await uptimeEsClient.search({ body: esParams }); - afterKey = result?.aggregations?.monitors?.after_key as AfterKey; - queryResults.push(formatBuckets(result?.aggregations?.monitors?.buckets || [])); } while (afterKey !== undefined); diff --git a/x-pack/plugins/uptime/server/lib/requests/get_monitor_duration.ts b/x-pack/plugins/uptime/server/lib/requests/get_monitor_duration.ts index be134a311af66..35e02da34148e 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_monitor_duration.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_monitor_duration.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { UMElasticsearchQueryFn } from '../adapters'; import { LocationDurationLine, MonitorDurationResult } from '../../../common/types'; import { QUERY, UNNAMED_LOCATION } from '../../../common/constants'; diff --git a/x-pack/plugins/uptime/server/lib/requests/get_monitor_status.ts b/x-pack/plugins/uptime/server/lib/requests/get_monitor_status.ts index 5227b8ca7dcc2..ab21a12aa735e 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_monitor_status.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_monitor_status.ts @@ -6,7 +6,7 @@ */ import { JsonObject } from '@kbn/utility-types'; -import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { asMutableArray } from '../../../common/utils/as_mutable_array'; import { UMElasticsearchQueryFn } from '../adapters'; import { Ping } from '../../../common/runtime_types/ping'; diff --git a/x-pack/plugins/uptime/server/lib/requests/get_network_events.ts b/x-pack/plugins/uptime/server/lib/requests/get_network_events.ts index 20e5c3a2a1185..1b6f02f90d34c 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_network_events.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_network_events.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { UMElasticsearchQueryFn } from '../adapters/framework'; import { NetworkEvent } from '../../../common/runtime_types'; diff --git a/x-pack/plugins/uptime/server/lib/requests/get_pings.ts b/x-pack/plugins/uptime/server/lib/requests/get_pings.ts index 86c96c5f589bc..c084c6e6afe82 100644 --- a/x-pack/plugins/uptime/server/lib/requests/get_pings.ts +++ b/x-pack/plugins/uptime/server/lib/requests/get_pings.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { QueryDslQueryContainer } from '@elastic/elasticsearch/api/types'; +import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { UMElasticsearchQueryFn } from '../adapters/framework'; import { GetPingsParams, diff --git a/x-pack/plugins/uptime/server/lib/requests/helper.ts b/x-pack/plugins/uptime/server/lib/requests/helper.ts index 03cc3e1ea3713..b12b979d786e6 100644 --- a/x-pack/plugins/uptime/server/lib/requests/helper.ts +++ b/x-pack/plugins/uptime/server/lib/requests/helper.ts @@ -5,7 +5,10 @@ * 2.0. */ -import { AggregationsAggregate, SearchResponse } from '@elastic/elasticsearch/api/types'; +import { + AggregationsAggregate, + SearchResponse, +} from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { ElasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks'; import { diff --git a/x-pack/plugins/watcher/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.test.js b/x-pack/plugins/watcher/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.test.js index a561aabbf4107..28f3eaabb283d 100644 --- a/x-pack/plugins/watcher/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.test.js +++ b/x-pack/plugins/watcher/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.test.js @@ -76,10 +76,12 @@ describe('fetch_all_from_scroll', () => { expect(mockScopedClusterClient.asCurrentUser.scroll).toHaveBeenCalledTimes(2); expect(mockScopedClusterClient.asCurrentUser.scroll).toHaveBeenNthCalledWith(1, { - body: { scroll: '30s', scroll_id: 'originalScrollId' }, + scroll: '30s', + scroll_id: 'originalScrollId', }); expect(mockScopedClusterClient.asCurrentUser.scroll).toHaveBeenNthCalledWith(2, { - body: { scroll: '30s', scroll_id: 'newScrollId' }, + scroll: '30s', + scroll_id: 'newScrollId', }); }); }); diff --git a/x-pack/plugins/watcher/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.ts b/x-pack/plugins/watcher/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.ts index 621fdf0d15861..7f6bc5d0af22a 100644 --- a/x-pack/plugins/watcher/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.ts +++ b/x-pack/plugins/watcher/server/lib/fetch_all_from_scroll/fetch_all_from_scroll.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { IScopedClusterClient } from 'kibana/server'; import { get } from 'lodash'; import { ES_SCROLL_SETTINGS } from '../../../common/constants'; @@ -23,10 +23,8 @@ export function fetchAllFromScroll( return dataClient.asCurrentUser .scroll({ - body: { - scroll: ES_SCROLL_SETTINGS.KEEPALIVE, - scroll_id: scrollId!, - }, + scroll: ES_SCROLL_SETTINGS.KEEPALIVE, + scroll_id: scrollId!, }) .then(({ body: innerResponse }) => { return fetchAllFromScroll(innerResponse, dataClient, hits); diff --git a/x-pack/plugins/watcher/server/routes/api/indices/register_get_route.ts b/x-pack/plugins/watcher/server/routes/api/indices/register_get_route.ts index f69ee60f9cd73..247c90bd40b4d 100644 --- a/x-pack/plugins/watcher/server/routes/api/indices/register_get_route.ts +++ b/x-pack/plugins/watcher/server/routes/api/indices/register_get_route.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { schema } from '@kbn/config-schema'; import { IScopedClusterClient } from 'kibana/server'; import { reduce, size } from 'lodash'; diff --git a/x-pack/plugins/watcher/server/routes/api/watches/register_delete_route.ts b/x-pack/plugins/watcher/server/routes/api/watches/register_delete_route.ts index b7c09361774ab..adefe8a29be97 100644 --- a/x-pack/plugins/watcher/server/routes/api/watches/register_delete_route.ts +++ b/x-pack/plugins/watcher/server/routes/api/watches/register_delete_route.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { schema } from '@kbn/config-schema'; import { IScopedClusterClient } from 'kibana/server'; import { RouteDependencies } from '../../../types'; diff --git a/x-pack/test/accessibility/apps/helpers.ts b/x-pack/test/accessibility/apps/helpers.ts index 18e3a51a2d268..790a3a089624d 100644 --- a/x-pack/test/accessibility/apps/helpers.ts +++ b/x-pack/test/accessibility/apps/helpers.ts @@ -4,35 +4,38 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import type { Client } from '@elastic/elasticsearch'; import { asyncForEach } from '@kbn/std'; // This function clears all pipelines to ensure that there in an empty state before starting each test. -export async function deleteAllPipelines(client: any, logger: any) { +export async function deleteAllPipelines(client: Client, logger: any) { const pipelines = await client.ingest.getPipeline(); - const pipeLineIds = Object.keys(pipelines.body); + const pipeLineIds = Object.keys(pipelines); await logger.debug(pipelines); if (pipeLineIds.length > 0) { - await asyncForEach(pipeLineIds, async (newId: any) => { + await asyncForEach(pipeLineIds, async (newId) => { await client.ingest.deletePipeline({ id: newId }); }); } } -export async function putSamplePipeline(client: any) { - return await client.ingest.putPipeline({ - id: 'testPipeline', - body: { - description: 'describe pipeline', - version: 123, - processors: [ - { - set: { - field: 'foo', - value: 'bar', +export async function putSamplePipeline(client: Client) { + return await client.ingest.putPipeline( + { + id: 'testPipeline', + body: { + description: 'describe pipeline', + version: 123, + processors: [ + { + set: { + field: 'foo', + value: 'bar', + }, }, - }, - ], + ], + }, }, - }); + { meta: true } + ); } diff --git a/x-pack/test/accessibility/apps/index_lifecycle_management.ts b/x-pack/test/accessibility/apps/index_lifecycle_management.ts index 65faa77fc497b..35f4a8e1adea5 100644 --- a/x-pack/test/accessibility/apps/index_lifecycle_management.ts +++ b/x-pack/test/accessibility/apps/index_lifecycle_management.ts @@ -62,7 +62,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { // https://github.com/elastic/kibana/issues/114542 describe.skip('Index Lifecycle Management', async () => { before(async () => { - await esClient.ilm.putLifecycle({ policy: POLICY_NAME, body: POLICY_ALL_PHASES }); + await esClient.ilm.putLifecycle({ name: POLICY_NAME, body: POLICY_ALL_PHASES }); await esClient.indices.putIndexTemplate({ name: indexTemplateName, body: { @@ -79,8 +79,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); after(async () => { - // @ts-expect-error @elastic/elasticsearch DeleteSnapshotLifecycleRequest.policy_id is required - await esClient.ilm.deleteLifecycle({ policy: POLICY_NAME }); + await esClient.ilm.deleteLifecycle({ name: POLICY_NAME }); await esClient.indices.deleteIndexTemplate({ name: indexTemplateName }); }); diff --git a/x-pack/test/accessibility/apps/ingest_node_pipelines.ts b/x-pack/test/accessibility/apps/ingest_node_pipelines.ts index dab9c86bf018e..9e92446fe4b5e 100644 --- a/x-pack/test/accessibility/apps/ingest_node_pipelines.ts +++ b/x-pack/test/accessibility/apps/ingest_node_pipelines.ts @@ -4,13 +4,13 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import type { Client } from '@elastic/elasticsearch'; import { deleteAllPipelines, putSamplePipeline } from './helpers'; export default function ({ getService, getPageObjects }: any) { const { common } = getPageObjects(['common']); const retry = getService('retry'); const testSubjects = getService('testSubjects'); - const esClient = getService('es'); + const esClient: Client = getService('es'); const log = getService('log'); const a11y = getService('a11y'); /* this is the wrapping service around axe */ diff --git a/x-pack/test/alerting_api_integration/common/lib/es_test_index_tool.ts b/x-pack/test/alerting_api_integration/common/lib/es_test_index_tool.ts index 47fae2a249efe..c880ce945042f 100644 --- a/x-pack/test/alerting_api_integration/common/lib/es_test_index_tool.ts +++ b/x-pack/test/alerting_api_integration/common/lib/es_test_index_tool.ts @@ -4,64 +4,67 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import type { Client } from '@elastic/elasticsearch'; export const ES_TEST_INDEX_NAME = '.kibana-alerting-test-data'; export class ESTestIndexTool { constructor( - private readonly es: any, + private readonly es: Client, private readonly retry: any, private readonly index: string = ES_TEST_INDEX_NAME ) {} async setup() { - return await this.es.indices.create({ - index: this.index, - body: { - mappings: { - properties: { - source: { - type: 'keyword', - }, - reference: { - type: 'keyword', - }, - params: { - enabled: false, - type: 'object', - }, - config: { - enabled: false, - type: 'object', - }, - state: { - enabled: false, - type: 'object', - }, - date: { - type: 'date', - format: 'strict_date_time', - }, - date_epoch_millis: { - type: 'date', - format: 'epoch_millis', - }, - testedValue: { - type: 'long', - }, - group: { - type: 'keyword', + return await this.es.indices.create( + { + index: this.index, + body: { + mappings: { + properties: { + source: { + type: 'keyword', + }, + reference: { + type: 'keyword', + }, + params: { + enabled: false, + type: 'object', + }, + config: { + enabled: false, + type: 'object', + }, + state: { + enabled: false, + type: 'object', + }, + date: { + type: 'date', + format: 'strict_date_time', + }, + date_epoch_millis: { + type: 'date', + format: 'epoch_millis', + }, + testedValue: { + type: 'long', + }, + group: { + type: 'keyword', + }, }, }, }, }, - }); + { meta: true } + ); } async destroy() { - const indexExists = (await this.es.indices.exists({ index: this.index })).body; + const indexExists = await this.es.indices.exists({ index: this.index }); if (indexExists) { - return await this.es.indices.delete({ index: this.index }); + return await this.es.indices.delete({ index: this.index }, { meta: true }); } } @@ -97,13 +100,15 @@ export class ESTestIndexTool { size: 1000, body, }; - return await this.es.search(params); + return await this.es.search(params, { meta: true }); } async waitForDocs(source: string, reference: string, numDocs: number = 1) { return await this.retry.try(async () => { const searchResult = await this.search(source, reference); + // @ts-expect-error doesn't handle total: number if (searchResult.body.hits.total.value < numDocs) { + // @ts-expect-error doesn't handle total: number throw new Error(`Expected ${numDocs} but received ${searchResult.body.hits.total.value}.`); } return searchResult.body.hits.hits; diff --git a/x-pack/test/alerting_api_integration/common/lib/task_manager_utils.ts b/x-pack/test/alerting_api_integration/common/lib/task_manager_utils.ts index 57af1b1bcb035..11e0b047ffd85 100644 --- a/x-pack/test/alerting_api_integration/common/lib/task_manager_utils.ts +++ b/x-pack/test/alerting_api_integration/common/lib/task_manager_utils.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import type { Client } from '@elastic/elasticsearch'; import { SerializedConcreteTaskInstance } from '../../../../plugins/task_manager/server/task'; export interface TaskManagerDoc { @@ -12,10 +12,10 @@ export interface TaskManagerDoc { task: SerializedConcreteTaskInstance; } export class TaskManagerUtils { - private readonly es: any; + private readonly es: Client; private readonly retry: any; - constructor(es: any, retry: any) { + constructor(es: Client, retry: any) { this.es = es; this.retry = retry; } @@ -36,7 +36,7 @@ export class TaskManagerUtils { { range: { 'task.scheduledAt': { - gte: taskRunAtFilter, + gte: taskRunAtFilter.getTime().toString(), }, }, }, @@ -45,8 +45,10 @@ export class TaskManagerUtils { }, }, }); - if (searchResult.body.hits.total.value) { - throw new Error(`Expected 0 tasks but received ${searchResult.body.hits.total.value}`); + // @ts-expect-error + if (searchResult.hits.total.value) { + // @ts-expect-error + throw new Error(`Expected 0 tasks but received ${searchResult.hits.total.value}`); } }); } @@ -67,7 +69,7 @@ export class TaskManagerUtils { { range: { 'task.scheduledAt': { - gte: taskRunAtFilter, + gte: taskRunAtFilter.getTime().toString(), }, }, }, @@ -83,10 +85,10 @@ export class TaskManagerUtils { }, }, }); - if (searchResult.body.hits.total.value) { - throw new Error( - `Expected 0 non-idle tasks but received ${searchResult.body.hits.total.value}` - ); + // @ts-expect-error + if (searchResult.hits.total.value) { + // @ts-expect-error + throw new Error(`Expected 0 non-idle tasks but received ${searchResult.hits.total.value}`); } }); } @@ -107,7 +109,7 @@ export class TaskManagerUtils { { range: { updated_at: { - gte: createdAtFilter, + gte: createdAtFilter.getTime().toString(), }, }, }, @@ -116,9 +118,11 @@ export class TaskManagerUtils { }, }, }); - if (searchResult.body.hits.total.value) { + // @ts-expect-error + if (searchResult.hits.total.value) { throw new Error( - `Expected 0 action_task_params objects but received ${searchResult.body.hits.total.value}` + // @ts-expect-error + `Expected 0 action_task_params objects but received ${searchResult.hits.total.value}` ); } }); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index.ts index 3db58cb2adc3d..fc40d036f925a 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import type { Client } from '@elastic/elasticsearch'; import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../../common/ftr_provider_context'; @@ -13,7 +13,7 @@ const ES_TEST_INDEX_NAME = 'functional-test-actions-index'; // eslint-disable-next-line import/no-default-export export default function indexTest({ getService }: FtrProviderContext) { - const es = getService('es'); + const es: Client = getService('es'); const supertest = getService('supertest'); const esDeleteAllIndices = getService('esDeleteAllIndices'); @@ -189,7 +189,7 @@ export default function indexTest({ getService }: FtrProviderContext) { .expect(200); expect(result.status).to.eql('ok'); - const items = await getTestIndexItems(es); + const items: any[] = await getTestIndexItems(es); expect(items.length).to.eql(2); let passed1 = false; let passed2 = false; @@ -268,10 +268,10 @@ export default function indexTest({ getService }: FtrProviderContext) { }); } -async function getTestIndexItems(es: any) { +async function getTestIndexItems(es: Client) { const result = await es.search({ index: ES_TEST_INDEX_NAME, }); - return result.body.hits.hits; + return result.hits.hits; } diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index_preconfigured.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index_preconfigured.ts index 92a5d7d840276..caa7d57688037 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index_preconfigured.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/es_index_preconfigured.ts @@ -5,8 +5,8 @@ * 2.0. */ +import type { Client } from '@elastic/elasticsearch'; import expect from '@kbn/expect'; - import { FtrProviderContext } from '../../../../common/ftr_provider_context'; // from: x-pack/test/alerting_api_integration/common/config.ts @@ -15,7 +15,7 @@ const ES_TEST_INDEX_NAME = 'functional-test-actions-index-preconfigured'; // eslint-disable-next-line import/no-default-export export default function indexTest({ getService }: FtrProviderContext) { - const es = getService('es'); + const es: Client = getService('es'); const esDeleteAllIndices = getService('esDeleteAllIndices'); const supertest = getService('supertest'); @@ -38,7 +38,7 @@ export default function indexTest({ getService }: FtrProviderContext) { expect(items.length).to.eql(1); // check document sans timestamp - const document = items[0]._source; + const document: any = items[0]._source; const timestamp = document.timestamp; delete document.timestamp; expect(document).to.eql({ testing: [4, 5, 6] }); @@ -52,10 +52,10 @@ export default function indexTest({ getService }: FtrProviderContext) { }); } -async function getTestIndexItems(es: any) { +async function getTestIndexItems(es: Client) { const result = await es.search({ index: ES_TEST_INDEX_NAME, }); - return result.body.hits.hits; + return result.hits.hits; } diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/execute.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/execute.ts index 9091b96ff335a..913baa2517fbb 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/execute.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/execute.ts @@ -97,6 +97,7 @@ export default function ({ getService }: FtrProviderContext) { 'action:test.index-record', reference ); + // @ts-expect-error doesnt handle total: number expect(searchResult.body.hits.total.value).to.eql(1); const indexedRecord = searchResult.body.hits.hits[0]; expect(indexedRecord._source).to.eql({ @@ -250,6 +251,7 @@ export default function ({ getService }: FtrProviderContext) { 'action:test.index-record', reference ); + // @ts-expect-error doesnt handle total: number expect(searchResult.body.hits.total.value).to.eql(1); const indexedRecord = searchResult.body.hits.hits[0]; expect(indexedRecord._source).to.eql({ diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts index 3131649e7c742..0de487a064a17 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/alerts.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import { omit } from 'lodash'; -import type { ApiResponse, estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { UserAtSpaceScenarios, Superuser } from '../../scenarios'; import { FtrProviderContext } from '../../../common/ftr_provider_context'; import { @@ -134,9 +134,10 @@ export default function alertTests({ getService }: FtrProviderContext) { 'alert:test.always-firing', reference ); + // @ts-expect-error doesnt handle total: number expect(alertSearchResult.body.hits.total.value).to.eql(1); const alertSearchResultWithoutDates = omit( - alertSearchResult.body.hits.hits[0]._source, + alertSearchResult.body.hits.hits[0]._source as object, ['alertInfo.createdAt', 'alertInfo.updatedAt'] ); expect(alertSearchResultWithoutDates).to.eql({ @@ -177,9 +178,12 @@ export default function alertTests({ getService }: FtrProviderContext) { ruleTypeName: 'Test: Always Firing', }, }); + // @ts-expect-error _source: unknown expect(alertSearchResult.body.hits.hits[0]._source.alertInfo.createdAt).to.match( /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/ ); + + // @ts-expect-error _source: unknown expect(alertSearchResult.body.hits.hits[0]._source.alertInfo.updatedAt).to.match( /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/ ); @@ -189,6 +193,7 @@ export default function alertTests({ getService }: FtrProviderContext) { 'action:test.index-record', reference ); + // @ts-expect-error doesnt handle total: number expect(actionSearchResult.body.hits.total.value).to.eql(1); expect(actionSearchResult.body.hits.hits[0]._source).to.eql({ config: { @@ -281,9 +286,10 @@ instanceStateValue: true 'alert:test.always-firing', reference ); + // @ts-expect-error doesnt handle total: number expect(alertSearchResult.body.hits.total.value).to.eql(1); const alertSearchResultWithoutDates = omit( - alertSearchResult.body.hits.hits[0]._source, + alertSearchResult.body.hits.hits[0]._source as object, ['alertInfo.createdAt', 'alertInfo.updatedAt'] ); expect(alertSearchResultWithoutDates).to.eql({ @@ -325,9 +331,11 @@ instanceStateValue: true }, }); + // @ts-expect-error _source: unknown expect(alertSearchResult.body.hits.hits[0]._source.alertInfo.createdAt).to.match( /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/ ); + // @ts-expect-error _source: unknown expect(alertSearchResult.body.hits.hits[0]._source.alertInfo.updatedAt).to.match( /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/ ); @@ -336,6 +344,7 @@ instanceStateValue: true 'action:test.index-record', reference ); + // @ts-expect-error doesnt handle total: number expect(actionSearchResult.body.hits.total.value).to.eql(1); expect(actionSearchResult.body.hits.hits[0]._source).to.eql({ config: { @@ -416,8 +425,10 @@ instanceStateValue: true reference2 ); + // @ts-expect-error doesnt handle total: number expect(alertSearchResult.body.hits.total.value).to.be.greaterThan(0); const alertSearchResultInfoWithoutDates = omit( + // @ts-expect-error _source: unknown alertSearchResult.body.hits.hits[0]._source.alertInfo, ['createdAt', 'updatedAt'] ); @@ -451,9 +462,11 @@ instanceStateValue: true ruleTypeName: 'Test: Always Firing', }); + // @ts-expect-error _source: unknown expect(alertSearchResult.body.hits.hits[0]._source.alertInfo.createdAt).to.match( /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/ ); + // @ts-expect-error _source: unknown expect(alertSearchResult.body.hits.hits[0]._source.alertInfo.updatedAt).to.match( /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/ ); @@ -534,9 +547,9 @@ instanceStateValue: true const scheduledActionTask: estypes.SearchHit< TaskRunning > = await retry.try(async () => { - const searchResult: ApiResponse< - estypes.SearchResponse> - > = await es.search({ + const searchResult = await es.search< + TaskRunning + >({ index: '.kibana_task_manager', body: { query: { @@ -569,8 +582,8 @@ instanceStateValue: true }, }, }); - expect((searchResult.body.hits.total as estypes.SearchTotalHits).value).to.eql(1); - return searchResult.body.hits.hits[0]; + expect((searchResult.hits.total as estypes.SearchTotalHits).value).to.eql(1); + return searchResult.hits.hits[0]; }); // Ensure the next runAt is set to the retryDate by custom logic @@ -852,6 +865,7 @@ instanceStateValue: true 'action:test.index-record', reference ); + // @ts-expect-error doesnt handle total: number expect(searchResult.body.hits.total.value).to.eql(1); break; default: @@ -931,8 +945,10 @@ instanceStateValue: true 'action:test.index-record', reference ); + // @ts-expect-error doesnt handle total: number expect(searchResult.body.hits.total.value).to.eql(2); const messages: string[] = searchResult.body.hits.hits.map( + // @ts-expect-error _search: unknown (hit: { _source: { params: { message: string } } }) => hit._source.params.message ); expect(messages.sort()).to.eql(['from:default', 'from:other']); @@ -1005,8 +1021,10 @@ instanceStateValue: true 'action:test.index-record', reference ); + // @ts-expect-error doesnt handle total: number expect(searchResult.body.hits.total.value).to.eql(2); const messages: string[] = searchResult.body.hits.hits.map( + // @ts-expect-error _source: unknown (hit: { _source: { params: { message: string } } }) => hit._source.params.message ); expect(messages.sort()).to.eql(['from:default:next', 'from:default:prev']); @@ -1068,6 +1086,7 @@ instanceStateValue: true 'action:test.index-record', reference ); + // @ts-expect-error doesnt handle total: number expect(searchResult.body.hits.total.value).to.eql(2); break; default: @@ -1126,6 +1145,7 @@ instanceStateValue: true 'action:test.index-record', reference ); + // @ts-expect-error doesnt handle total: number expect(executedActionsResult.body.hits.total.value).to.eql(0); break; default: @@ -1184,6 +1204,7 @@ instanceStateValue: true 'action:test.index-record', reference ); + // @ts-expect-error doesnt handle total: number expect(executedActionsResult.body.hits.total.value).to.eql(0); break; default: @@ -1243,6 +1264,7 @@ instanceStateValue: true 'action:test.index-record', reference ); + // @ts-expect-error doesnt handle total: number expect(searchResult.body.hits.total.value).to.eql(1); break; default: diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/create.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/create.ts index 1e85cb3011979..eaa73facb3734 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/create.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/create.ts @@ -6,7 +6,6 @@ */ import expect from '@kbn/expect'; -import type { ApiResponse, estypes } from '@elastic/elasticsearch'; import { UserAtSpaceScenarios } from '../../scenarios'; import { checkAAD, @@ -31,11 +30,11 @@ export default function createAlertTests({ getService }: FtrProviderContext) { after(() => objectRemover.removeAll()); async function getScheduledTask(id: string): Promise { - const scheduledTask: ApiResponse> = await es.get({ + const scheduledTask = await es.get({ id: `task:${id}`, index: '.kibana_task_manager', }); - return scheduledTask.body._source!; + return scheduledTask._source!; } for (const scenario of UserAtSpaceScenarios) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/enable.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/enable.ts index d836f615e5349..1589a63cb7108 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/enable.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/enable.ts @@ -6,7 +6,6 @@ */ import expect from '@kbn/expect'; -import type { ApiResponse, estypes } from '@elastic/elasticsearch'; import { UserAtSpaceScenarios } from '../../scenarios'; import { FtrProviderContext } from '../../../common/ftr_provider_context'; import { @@ -33,11 +32,11 @@ export default function createEnableAlertTests({ getService }: FtrProviderContex after(() => objectRemover.removeAll()); async function getScheduledTask(id: string): Promise { - const scheduledTask: ApiResponse> = await es.get({ + const scheduledTask = await es.get({ id: `task:${id}`, index: '.kibana_task_manager', }); - return scheduledTask.body._source!; + return scheduledTask._source!; } for (const scenario of UserAtSpaceScenarios) { diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/rbac_legacy.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/rbac_legacy.ts index 17e34973041c0..4aa8447823dca 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/rbac_legacy.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/rbac_legacy.ts @@ -226,13 +226,19 @@ export default function alertTests({ getService }: FtrProviderContext) { async function ensureAlertIsRunning() { // ensure the alert still runs and that it can schedule actions - const numberOfAlertExecutions = ( - await esTestIndexTool.search('alert:test.always-firing', reference) - ).body.hits.total.value; + const alwaysFiringResponse = await esTestIndexTool.search( + 'alert:test.always-firing', + reference + ); + // @ts-expect-error doesnt handle total: number + const numberOfAlertExecutions = alwaysFiringResponse.body.hits.total.value; - const numberOfActionExecutions = ( - await esTestIndexTool.search('action:test.index-record', reference) - ).body.hits.total.value; + const indexRecordResponse = await esTestIndexTool.search( + 'action:test.index-record', + reference + ); + // @ts-expect-error doesnt handle total: number + const numberOfActionExecutions = indexRecordResponse.body.hits.total.value; // wait for alert to execute and for its action to be scheduled and run await retry.try(async () => { @@ -246,9 +252,11 @@ export default function alertTests({ getService }: FtrProviderContext) { reference ); + // @ts-expect-error doesnt handle total: number expect(alertSearchResult.body.hits.total.value).to.be.greaterThan( numberOfAlertExecutions ); + // @ts-expect-error doesnt handle total: number expect(actionSearchResult.body.hits.total.value).to.be.greaterThan( numberOfActionExecutions ); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/action_task_params/migrations.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/action_task_params/migrations.ts index 0c0b62b6cb529..27b523fa24298 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/action_task_params/migrations.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/action_task_params/migrations.ts @@ -26,10 +26,13 @@ export default function createGetTests({ getService }: FtrProviderContext) { it('7.16.0 migrates action_task_params to use references array', async () => { // Inspect migration of non-preconfigured connector ID - const response = await es.get>({ - index: '.kibana', - id: 'action_task_params:b9af6280-0052-11ec-917b-f7aa317691ed', - }); + const response = await es.get>( + { + index: '.kibana', + id: 'action_task_params:b9af6280-0052-11ec-917b-f7aa317691ed', + }, + { meta: true } + ); expect(response.statusCode).to.eql(200); const { actionId, relatedSavedObjects, references } = getActionIdAndRelatedSavedObjects( response.body._source @@ -49,10 +52,13 @@ export default function createGetTests({ getService }: FtrProviderContext) { }); // Inspect migration of preconfigured connector ID - const preconfiguredConnectorResponse = await es.get>({ - index: '.kibana', - id: 'action_task_params:0205a520-0054-11ec-917b-f7aa317691ed', - }); + const preconfiguredConnectorResponse = await es.get>( + { + index: '.kibana', + id: 'action_task_params:0205a520-0054-11ec-917b-f7aa317691ed', + }, + { meta: true } + ); expect(preconfiguredConnectorResponse.statusCode).to.eql(200); const { diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/builtin_action_types/es_index.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/builtin_action_types/es_index.ts index 3f4cef25ff65e..3bc8cec9bf163 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/builtin_action_types/es_index.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/builtin_action_types/es_index.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import type { Client } from '@elastic/elasticsearch'; import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../../common/ftr_provider_context'; @@ -13,7 +13,7 @@ const ES_TEST_INDEX_NAME = 'functional-test-actions-index'; // eslint-disable-next-line import/no-default-export export default function indexTest({ getService }: FtrProviderContext) { - const es = getService('es'); + const es: Client = getService('es'); const supertest = getService('supertest'); const esDeleteAllIndices = getService('esDeleteAllIndices'); @@ -144,10 +144,10 @@ export default function indexTest({ getService }: FtrProviderContext) { }); } -async function getTestIndexItems(es: any) { +async function getTestIndexItems(es: Client) { const result = await es.search({ index: ES_TEST_INDEX_NAME, }); - return result.body.hits.hits; + return result.hits.hits; } diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/builtin_action_types/preconfigured_alert_history_connector.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/builtin_action_types/preconfigured_alert_history_connector.ts index fe0f5d3ecbade..dea873073f61f 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/builtin_action_types/preconfigured_alert_history_connector.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/builtin_action_types/preconfigured_alert_history_connector.ts @@ -6,7 +6,6 @@ */ import expect from '@kbn/expect'; -import type { ApiResponse, estypes } from '@elastic/elasticsearch'; import { FtrProviderContext } from '../../../../common/ftr_provider_context'; import { getTestAlertData, ObjectRemover } from '../../../../common/lib'; import { AlertHistoryDefaultIndexName } from '../../../../../../plugins/actions/common'; @@ -66,10 +65,10 @@ export default function preconfiguredAlertHistoryConnectorTests({ await waitForStatus(response.body.id, new Set(['active'])); await retry.try(async () => { - const result: ApiResponse> = await es.search({ + const result = await es.search({ index: AlertHistoryDefaultIndexName, }); - const indexedItems = result.body.hits.hits; + const indexedItems = result.hits.hits; expect(indexedItems.length).to.eql(1); const indexedDoc = indexedItems[0]._source; @@ -104,10 +103,10 @@ export default function preconfiguredAlertHistoryConnectorTests({ await waitForStatus(response.body.id, new Set(['active'])); await retry.try(async () => { - const result: ApiResponse> = await es.search({ + const result = await es.search({ index: ALERT_HISTORY_OVERRIDE_INDEX, }); - const indexedItems = result.body.hits.hits; + const indexedItems = result.hits.hits; expect(indexedItems.length).to.eql(1); const indexedDoc = indexedItems[0]._source; diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/enqueue.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/enqueue.ts index 93f6a73b7ce21..084c105aa723a 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/enqueue.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/enqueue.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Spaces } from '../../scenarios'; import { ESTestIndexTool, @@ -123,7 +123,7 @@ export default function ({ getService }: FtrProviderContext) { }, }, }); - expect((searchResult.body.hits.total as estypes.SearchTotalHits).value).to.eql(0); + expect((searchResult.hits.total as estypes.SearchTotalHits).value).to.eql(0); }); }); @@ -174,7 +174,7 @@ export default function ({ getService }: FtrProviderContext) { }, }, }); - const total = (runningSearchResult.body.hits.total as estypes.SearchTotalHits).value; + const total = (runningSearchResult.hits.total as estypes.SearchTotalHits).value; expect(total).to.eql(1); }); @@ -195,7 +195,7 @@ export default function ({ getService }: FtrProviderContext) { }, }, }); - const total = (runningSearchResult.body.hits.total as estypes.SearchTotalHits).value; + const total = (runningSearchResult.hits.total as estypes.SearchTotalHits).value; expect(total).to.eql(0); }); }); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/execute.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/execute.ts index 10da2d852e806..389a4beeb8737 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/execute.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/execute.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import type { Client } from '@elastic/elasticsearch'; import expect from '@kbn/expect'; import { Spaces } from '../../scenarios'; import { @@ -22,7 +22,7 @@ const NANOS_IN_MILLIS = 1000 * 1000; // eslint-disable-next-line import/no-default-export export default function ({ getService }: FtrProviderContext) { const supertest = getService('supertest'); - const es = getService('es'); + const es: Client = getService('es'); const retry = getService('retry'); const esTestIndexTool = new ESTestIndexTool(es, retry); @@ -76,6 +76,7 @@ export default function ({ getService }: FtrProviderContext) { expect(response.status).to.eql(200); expect(response.body).to.be.an('object'); const searchResult = await esTestIndexTool.search('action:test.index-record', reference); + // @ts-expect-error doesn't handle total: number expect(searchResult.body.hits.total.value).to.eql(1); const indexedRecord = searchResult.body.hits.hits[0]; expect(indexedRecord._source).to.eql({ @@ -211,15 +212,19 @@ export default function ({ getService }: FtrProviderContext) { expect(response.status).to.eql(200); const searchResult = await esTestIndexTool.search('action:test.authorization', reference); + // @ts-expect-error doesn't handle total: number expect(searchResult.body.hits.total.value).to.eql(1); const indexedRecord = searchResult.body.hits.hits[0]; + // @ts-expect-error _source is not typed expect(indexedRecord._source.state).to.eql({ callClusterSuccess: true, callScopedClusterSuccess: true, savedObjectsClientSuccess: false, savedObjectsClientError: { + // @ts-expect-error _source is not typed ...indexedRecord._source.state.savedObjectsClientError, output: { + // @ts-expect-error _source is not typed ...indexedRecord._source.state.savedObjectsClientError.output, statusCode: 404, }, diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/alerts_base.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/alerts_base.ts index 999135993d069..ea818a6e64b0d 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/alerts_base.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/alerts_base.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import { omit } from 'lodash'; -import type { ApiResponse, estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Response as SupertestResponse } from 'supertest'; import { RecoveredActionGroup } from '../../../../../plugins/alerting/common'; import { Space } from '../../../common/types'; @@ -298,6 +298,7 @@ instanceStateValue: true await taskManagerUtils.waitForActionTaskParamsToBeCleanedUp(testStart); const actionTestRecord = await esTestIndexTool.search('action:test.index-record', reference); + // @ts-expect-error doesnt handle total: number expect(actionTestRecord.body.hits.total.value).to.eql(0); objectRemover.add(space.id, alertId, 'rule', 'alerting'); }); @@ -379,9 +380,9 @@ instanceStateValue: true const scheduledActionTask: estypes.SearchHit< TaskRunning > = await retry.try(async () => { - const searchResult: ApiResponse< - estypes.SearchResponse> - > = await es.search({ + const searchResult = await es.search< + TaskRunning + >({ index: '.kibana_task_manager', body: { query: { @@ -414,8 +415,8 @@ instanceStateValue: true }, }, }); - expect((searchResult.body.hits.total as estypes.SearchTotalHits).value).to.eql(1); - return searchResult.body.hits.hits[0]; + expect((searchResult.hits.total as estypes.SearchTotalHits).value).to.eql(1); + return searchResult.hits.hits[0]; }); expect(scheduledActionTask._source!.task.runAt).to.eql(retryDate.toISOString()); }); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/es_query/create_test_data.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/es_query/create_test_data.ts index f3c707c58af1c..73a81904d0cc0 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/es_query/create_test_data.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/es_query/create_test_data.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import type { Client } from '@elastic/elasticsearch'; import { times } from 'lodash'; import { v4 as uuid } from 'uuid'; import { ESTestIndexTool, ES_TEST_INDEX_NAME } from '../../../../../common/lib'; @@ -16,7 +16,7 @@ export const DOCUMENT_SOURCE = 'queryDataEndpointTests'; export const DOCUMENT_REFERENCE = '-na-'; export async function createEsDocuments( - es: any, + es: Client, esTestIndexTool: ESTestIndexTool, endDate: string = END_DATE, intervals: number = 1, @@ -39,7 +39,7 @@ export async function createEsDocuments( await esTestIndexTool.waitForDocs(DOCUMENT_SOURCE, DOCUMENT_REFERENCE, totalDocuments); } -async function createEsDocument(es: any, epochMillis: number, testedValue: number) { +async function createEsDocument(es: Client, epochMillis: number, testedValue: number) { const document = { source: DOCUMENT_SOURCE, reference: DOCUMENT_REFERENCE, @@ -54,7 +54,7 @@ async function createEsDocument(es: any, epochMillis: number, testedValue: numbe body: document, }); - if (response.body.result !== 'created') { + if (response.result !== 'created') { throw new Error(`document not created: ${JSON.stringify(response)}`); } } diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/create_test_data.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/create_test_data.ts index b9faadcd3d4b7..ba063044d9233 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/create_test_data.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/builtin_alert_types/index_threshold/create_test_data.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import type { Client } from '@elastic/elasticsearch'; import { times } from 'lodash'; import { v4 as uuid } from 'uuid'; import { ESTestIndexTool, ES_TEST_INDEX_NAME } from '../../../../../common/lib'; @@ -24,7 +24,7 @@ export const DOCUMENT_REFERENCE = '-na-'; // 2^0 as the value of the last documents, the values increasing for older // documents. export async function createEsDocuments( - es: any, + es: Client, esTestIndexTool: ESTestIndexTool, endDate: string = END_DATE, intervals: number = 1, @@ -49,7 +49,12 @@ export async function createEsDocuments( await esTestIndexTool.waitForDocs(DOCUMENT_SOURCE, DOCUMENT_REFERENCE, totalDocuments); } -async function createEsDocument(es: any, epochMillis: number, testedValue: number, group: string) { +async function createEsDocument( + es: Client, + epochMillis: number, + testedValue: number, + group: string +) { const document = { source: DOCUMENT_SOURCE, reference: DOCUMENT_REFERENCE, @@ -66,7 +71,7 @@ async function createEsDocument(es: any, epochMillis: number, testedValue: numbe }); // console.log(`writing document to ${ES_TEST_INDEX_NAME}:`, JSON.stringify(document, null, 4)); - if (response.body.result !== 'created') { + if (response.result !== 'created') { throw new Error(`document not created: ${JSON.stringify(response)}`); } } diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/create.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/create.ts index f45ad28e2cdc5..dce5de4188220 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/create.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/create.ts @@ -6,7 +6,6 @@ */ import expect from '@kbn/expect'; -import type { ApiResponse, estypes } from '@elastic/elasticsearch'; import { SavedObject } from 'kibana/server'; import { Spaces } from '../../scenarios'; import { @@ -31,11 +30,11 @@ export default function createAlertTests({ getService }: FtrProviderContext) { after(() => objectRemover.removeAll()); async function getScheduledTask(id: string): Promise { - const scheduledTask: ApiResponse> = await es.get({ + const scheduledTask = await es.get({ id: `task:${id}`, index: '.kibana_task_manager', }); - return scheduledTask.body._source!; + return scheduledTask._source!; } it('should handle create alert request appropriately', async () => { @@ -191,10 +190,13 @@ export default function createAlertTests({ getService }: FtrProviderContext) { execution_status: response.body.execution_status, }); - const esResponse = await es.get>({ - index: '.kibana', - id: `alert:${response.body.id}`, - }); + const esResponse = await es.get>( + { + index: '.kibana', + id: `alert:${response.body.id}`, + }, + { meta: true } + ); expect(esResponse.statusCode).to.eql(200); const rawActions = (esResponse.body._source as any)?.alert.actions ?? []; expect(rawActions).to.eql([ diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/enable.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/enable.ts index 881931252ed5f..611c2498dd9d3 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/enable.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/enable.ts @@ -6,7 +6,6 @@ */ import expect from '@kbn/expect'; -import type { ApiResponse, estypes } from '@elastic/elasticsearch'; import { Spaces } from '../../scenarios'; import { FtrProviderContext } from '../../../common/ftr_provider_context'; import { @@ -30,11 +29,11 @@ export default function createEnableAlertTests({ getService }: FtrProviderContex after(() => objectRemover.removeAll()); async function getScheduledTask(id: string): Promise { - const scheduledTask: ApiResponse> = await es.get({ + const scheduledTask = await es.get({ id: `task:${id}`, index: '.kibana_task_manager', }); - return scheduledTask.body._source!; + return scheduledTask._source!; } it('should handle enable alert request appropriately', async () => { diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/ephemeral.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/ephemeral.ts index 99801cf838836..a3b8c75f79e62 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/ephemeral.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/ephemeral.ts @@ -117,6 +117,7 @@ export default function createNotifyWhenTests({ getService }: FtrProviderContext ); const searchResult = await esTestIndexTool.search('action:test.index-record'); + // @ts-expect-error doesnt handle total: number expect(searchResult.body.hits.total.value).equal( nonEphemeralTasks + DEFAULT_MAX_EPHEMERAL_ACTIONS_PER_ALERT ); diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/migrations.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/migrations.ts index e3a062a08ffb9..250f78c6b2800 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/migrations.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/migrations.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import type { ApiResponse, estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { getUrlPrefix } from '../../../common/lib'; import { FtrProviderContext } from '../../../common/ftr_provider_context'; import type { RawAlert, RawAlertAction } from '../../../../../plugins/alerting/server/types'; @@ -181,10 +181,13 @@ export default function createGetTests({ getService }: FtrProviderContext) { it('7.15.0 migrates security_solution alerts with exceptionLists to be saved object references', async () => { // NOTE: We hae to use elastic search directly against the ".kibana" index because alerts do not expose the references which we want to test exists - const response = await es.get<{ references: [{}] }>({ - index: '.kibana', - id: 'alert:38482620-ef1b-11eb-ad71-7de7959be71c', - }); + const response = await es.get<{ references: [{}] }>( + { + index: '.kibana', + id: 'alert:38482620-ef1b-11eb-ad71-7de7959be71c', + }, + { meta: true } + ); expect(response.statusCode).to.eql(200); expect(response.body._source?.references).to.eql([ { @@ -201,16 +204,19 @@ export default function createGetTests({ getService }: FtrProviderContext) { }); it('7.16.0 migrates existing alerts to contain legacyId field', async () => { - const searchResult: ApiResponse> = await es.search({ - index: '.kibana', - body: { - query: { - term: { - _id: 'alert:74f3e6d7-b7bb-477d-ac28-92ee22728e6e', + const searchResult = await es.search( + { + index: '.kibana', + body: { + query: { + term: { + _id: 'alert:74f3e6d7-b7bb-477d-ac28-92ee22728e6e', + }, }, }, }, - }); + { meta: true } + ); expect(searchResult.statusCode).to.equal(200); expect((searchResult.body.hits.total as estypes.SearchTotalHits).value).to.equal(1); const hit = searchResult.body.hits.hits[0]; @@ -220,16 +226,19 @@ export default function createGetTests({ getService }: FtrProviderContext) { }); it('7.16.0 migrates existing rules so predefined connectors are not stored in references', async () => { - const searchResult: ApiResponse> = await es.search({ - index: '.kibana', - body: { - query: { - term: { - _id: 'alert:9c003b00-00ee-11ec-b067-2524946ba327', + const searchResult = await es.search( + { + index: '.kibana', + body: { + query: { + term: { + _id: 'alert:9c003b00-00ee-11ec-b067-2524946ba327', + }, }, }, }, - }); + { meta: true } + ); expect(searchResult.statusCode).to.equal(200); expect((searchResult.body.hits.total as estypes.SearchTotalHits).value).to.equal(1); const hit = searchResult.body.hits.hits[0]; @@ -260,10 +269,13 @@ export default function createGetTests({ getService }: FtrProviderContext) { it('7.16.0 migrates security_solution (Legacy) siem.notifications with "ruleAlertId" to be saved object references', async () => { // NOTE: We hae to use elastic search directly against the ".kibana" index because alerts do not expose the references which we want to test exists - const response = await es.get<{ references: [{}] }>({ - index: '.kibana', - id: 'alert:d7a8c6a1-9394-48df-a634-d5457c35d747', - }); + const response = await es.get<{ references: [{}] }>( + { + index: '.kibana', + id: 'alert:d7a8c6a1-9394-48df-a634-d5457c35d747', + }, + { meta: true } + ); expect(response.statusCode).to.eql(200); expect(response.body._source?.references).to.eql([ { diff --git a/x-pack/test/api_integration/apis/es/post_privileges.ts b/x-pack/test/api_integration/apis/es/post_privileges.ts index 37399fe31a2ca..76cc21a861d8c 100644 --- a/x-pack/test/api_integration/apis/es/post_privileges.ts +++ b/x-pack/test/api_integration/apis/es/post_privileges.ts @@ -32,7 +32,7 @@ export default function ({ getService }: FtrProviderContext) { }, }); - expect(response.body).to.eql({ + expect(response).to.eql({ foo: { all: { created: true }, read: { created: true }, @@ -62,7 +62,7 @@ export default function ({ getService }: FtrProviderContext) { }, }); - expect(updateResponse.body).to.eql({ + expect(updateResponse).to.eql({ foo: { other: { created: true }, read: { created: false }, @@ -70,7 +70,7 @@ export default function ({ getService }: FtrProviderContext) { }); const retrievedPrivilege = await es.security.getPrivileges({ application }); - expect(retrievedPrivilege.body).to.eql({ + expect(retrievedPrivilege).to.eql({ foo: { // "all" is maintained even though the subsequent update did not specify this privilege all: { diff --git a/x-pack/test/api_integration/apis/lens/telemetry.ts b/x-pack/test/api_integration/apis/lens/telemetry.ts index 9f691115232ae..1c0c67a5203d6 100644 --- a/x-pack/test/api_integration/apis/lens/telemetry.ts +++ b/x-pack/test/api_integration/apis/lens/telemetry.ts @@ -7,6 +7,7 @@ import moment from 'moment'; import expect from '@kbn/expect'; +import { convertToKibanaClient } from '@kbn/test'; import { FtrProviderContext } from '../../ftr_provider_context'; @@ -27,9 +28,7 @@ export default ({ getService }: FtrProviderContext) => { index: '.kibana', }); - const { - body: { count }, - } = await es.count({ + const { count } = await es.count({ index: '.kibana', q: 'type:lens-ui-telemetry', }); @@ -106,8 +105,8 @@ export default ({ getService }: FtrProviderContext) => { }, refresh: 'wait_for', }); - - const result = await getDailyEvents('.kibana', () => Promise.resolve(es)); + const kibanaClient = convertToKibanaClient(es); + const result = await getDailyEvents('.kibana', () => Promise.resolve(kibanaClient)); expect(result).to.eql({ byDate: {}, @@ -149,8 +148,8 @@ export default ({ getService }: FtrProviderContext) => { getEvent('revert', date1, 'suggestion'), ], }); - - const result = await getDailyEvents('.kibana', () => Promise.resolve(es)); + const kibanaClient = convertToKibanaClient(es); + const result = await getDailyEvents('.kibana', () => Promise.resolve(kibanaClient)); expect(result).to.eql({ byDate: { @@ -176,8 +175,8 @@ export default ({ getService }: FtrProviderContext) => { const esArchiver = getService('esArchiver'); await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/lens/basic'); - - const results = await getVisualizationCounts(() => Promise.resolve(es), '.kibana'); + const kibanaClient = convertToKibanaClient(es); + const results = await getVisualizationCounts(() => Promise.resolve(kibanaClient), '.kibana'); expect(results).to.have.keys([ 'saved_overall', diff --git a/x-pack/test/api_integration/apis/logstash/cluster/load.ts b/x-pack/test/api_integration/apis/logstash/cluster/load.ts index 1997b65c5a871..951acd3bb3aae 100644 --- a/x-pack/test/api_integration/apis/logstash/cluster/load.ts +++ b/x-pack/test/api_integration/apis/logstash/cluster/load.ts @@ -16,7 +16,7 @@ export default function ({ getService }: FtrProviderContext) { it('should return the ES cluster info', async () => { const { body } = await supertest.get('/api/logstash/cluster').expect(200); - const { body: responseFromES } = await es.info(); + const responseFromES = await es.info(); expect(body.cluster.uuid).to.eql(responseFromES.cluster_uuid); }); }); diff --git a/x-pack/test/api_integration/apis/management/index_lifecycle_management/lib/elasticsearch.js b/x-pack/test/api_integration/apis/management/index_lifecycle_management/lib/elasticsearch.js index 9e09ae57e167e..8c5481a6e2c85 100644 --- a/x-pack/test/api_integration/apis/management/index_lifecycle_management/lib/elasticsearch.js +++ b/x-pack/test/api_integration/apis/management/index_lifecycle_management/lib/elasticsearch.js @@ -22,7 +22,7 @@ export const initElasticsearchHelpers = (getService) => { let dataStreamsCreated = []; // Indices - const getIndex = (index) => es.indices.get({ index }).then(({ body }) => body); + const getIndex = (index) => es.indices.get({ index }); const createIndex = (index = getRandomString()) => { indicesCreated.push(index); @@ -37,34 +37,34 @@ export const initElasticsearchHelpers = (getService) => { // Data streams const createDataStream = (dataStream = getRandomString(), document) => { dataStreamsCreated.push(dataStream); - return es.index({ index: dataStream, body: document }); + return es.index({ index: dataStream, body: document }, { meta: true }); }; const deleteDataStream = (dataStream) => { dataStreamsCreated = dataStreamsCreated.filter((i) => i !== dataStream); - return es.indices.deleteDataStream({ name: dataStream }); + return es.indices.deleteDataStream({ name: dataStream }, { meta: true }); }; const deleteAllDataStreams = () => Promise.all(dataStreamsCreated.map(deleteDataStream)).then(() => (dataStreamsCreated = [])); // Index templates - const getIndexTemplates = () => es.indices.getTemplate(); + const getIndexTemplates = () => es.indices.getTemplate(undefined, { meta: true }); // Create index template if it does not already exist const createIndexTemplate = (name, template) => { templatesCreated.push(name); - return es.indices.putTemplate({ name, body: template }, { create: true }); + return es.indices.putTemplate({ name, body: template }, { create: true, meta: true }); }; const createComposableIndexTemplate = (name, template) => { composableTemplatesCreated.push(name); - return es.indices.putIndexTemplate({ name, body: template }, { create: true }); + return es.indices.putIndexTemplate({ name, body: template }, { create: true, meta: true }); }; const deleteIndexTemplate = (name) => { templatesCreated = templatesCreated.filter((i) => i !== name); - return es.indices.deleteTemplate({ name }).catch((err) => { + return es.indices.deleteTemplate({ name }, { meta: true }).catch((err) => { // Silently fail templates not found if (err.statusCode !== 404) { throw err; @@ -74,7 +74,7 @@ export const initElasticsearchHelpers = (getService) => { const deleteComposableIndexTemplate = (name) => { composableTemplatesCreated = composableTemplatesCreated.filter((i) => i !== name); - return es.indices.deleteIndexTemplate({ name }).catch((err) => { + return es.indices.deleteIndexTemplate({ name }, { meta: true }).catch((err) => { // Silently fail if templates not found if (err.statusCode !== 404) { throw err; @@ -98,7 +98,7 @@ export const initElasticsearchHelpers = (getService) => { deleteAllDataStreams(), ]); - const getNodesStats = () => es.nodes.stats().then(({ body }) => body); + const getNodesStats = () => es.nodes.stats(); return { getIndex, diff --git a/x-pack/test/api_integration/apis/management/index_management/lib/elasticsearch.js b/x-pack/test/api_integration/apis/management/index_management/lib/elasticsearch.js index 22824227f1275..9c67f493a7ca3 100644 --- a/x-pack/test/api_integration/apis/management/index_management/lib/elasticsearch.js +++ b/x-pack/test/api_integration/apis/management/index_management/lib/elasticsearch.js @@ -29,24 +29,24 @@ export const initElasticsearchHelpers = (getService) => { indicesCreated = []; }; - const catIndex = (index, h) => es.cat.indices({ index, format: 'json', h }); + const catIndex = (index, h) => es.cat.indices({ index, format: 'json', h }, { meta: true }); - const indexStats = (index, metric) => es.indices.stats({ index, metric }); + const indexStats = (index, metric) => es.indices.stats({ index, metric }, { meta: true }); const cleanUp = () => deleteAllIndices(); - const catTemplate = (name) => es.cat.templates({ name, format: 'json' }); + const catTemplate = (name) => es.cat.templates({ name, format: 'json' }, { meta: true }); const createComponentTemplate = (componentTemplate, shouldCacheTemplate) => { if (shouldCacheTemplate) { componentTemplatesCreated.push(componentTemplate.name); } - return es.cluster.putComponentTemplate(componentTemplate); + return es.cluster.putComponentTemplate(componentTemplate, { meta: true }); }; const deleteComponentTemplate = (componentTemplateName) => { - return es.cluster.deleteComponentTemplate({ name: componentTemplateName }); + return es.cluster.deleteComponentTemplate({ name: componentTemplateName }, { meta: true }); }; const cleanUpComponentTemplates = () => diff --git a/x-pack/test/api_integration/apis/management/ingest_pipelines/lib/elasticsearch.ts b/x-pack/test/api_integration/apis/management/ingest_pipelines/lib/elasticsearch.ts index 5a4459fced624..c2a42356f5f51 100644 --- a/x-pack/test/api_integration/apis/management/ingest_pipelines/lib/elasticsearch.ts +++ b/x-pack/test/api_integration/apis/management/ingest_pipelines/lib/elasticsearch.ts @@ -37,11 +37,10 @@ export const registerEsHelpers = (getService: FtrProviderContext['getService']) pipelinesCreated.push(pipeline.id); } - return es.ingest.putPipeline(pipeline).then(({ body }) => body); + return es.ingest.putPipeline(pipeline); }; - const deletePipeline = (pipelineId: string) => - es.ingest.deletePipeline({ id: pipelineId }).then(({ body }) => body); + const deletePipeline = (pipelineId: string) => es.ingest.deletePipeline({ id: pipelineId }); const cleanupPipelines = () => Promise.all(pipelinesCreated.map(deletePipeline)) @@ -54,11 +53,11 @@ export const registerEsHelpers = (getService: FtrProviderContext['getService']) }); const createIndex = (index: { index: string; id: string; body: object }) => { - return es.index(index).then(({ body }) => body); + return es.index(index); }; const deleteIndex = (indexName: string) => { - return es.indices.delete({ index: indexName }).then(({ body }) => body); + return es.indices.delete({ index: indexName }); }; return { diff --git a/x-pack/test/api_integration/apis/management/snapshot_restore/lib/elasticsearch.ts b/x-pack/test/api_integration/apis/management/snapshot_restore/lib/elasticsearch.ts index a59c90fe29132..b5b0bc053f3de 100644 --- a/x-pack/test/api_integration/apis/management/snapshot_restore/lib/elasticsearch.ts +++ b/x-pack/test/api_integration/apis/management/snapshot_restore/lib/elasticsearch.ts @@ -39,18 +39,16 @@ export const registerEsHelpers = (getService: FtrProviderContext['getService']) const es = getService('es'); const createRepository = (repoName: string, repoPath?: string) => { - return es.snapshot - .createRepository({ - repository: repoName, - body: { - type: 'fs', - settings: { - location: repoPath ?? '/tmp/repo', - }, + return es.snapshot.createRepository({ + name: repoName, + body: { + type: 'fs', + settings: { + location: repoPath ?? '/tmp/repo', }, - verify: false, - }) - .then(({ body }) => body); + }, + verify: false, + }); }; const createPolicy = (policy: SlmPolicy, cachePolicy?: boolean) => { @@ -58,27 +56,22 @@ export const registerEsHelpers = (getService: FtrProviderContext['getService']) policiesCreated.push(policy.policyName); } - return es.slm - .putLifecycle({ - policy_id: policy.policyName, - // TODO: bring {@link SlmPolicy} in line with {@link PutSnapshotLifecycleRequest['body']} - // @ts-expect-error - body: policy, - }) - .then(({ body }) => body); + return es.slm.putLifecycle({ + policy_id: policy.policyName, + // TODO: bring {@link SlmPolicy} in line with {@link PutSnapshotLifecycleRequest['body']} + // @ts-expect-error + body: policy, + }); }; const getPolicy = (policyName: string) => { - return es.slm - .getLifecycle({ - policy_id: policyName, - human: true, - }) - .then(({ body }) => body); + return es.slm.getLifecycle({ + policy_id: policyName, + human: true, + }); }; - const deletePolicy = (policyName: string) => - es.slm.deleteLifecycle({ policy_id: policyName }).then(({ body }) => body); + const deletePolicy = (policyName: string) => es.slm.deleteLifecycle({ policy_id: policyName }); const cleanupPolicies = () => Promise.all(policiesCreated.map(deletePolicy)) @@ -91,13 +84,11 @@ export const registerEsHelpers = (getService: FtrProviderContext['getService']) }); const executePolicy = (policyName: string) => { - return es.slm.executeLifecycle({ policy_id: policyName }).then(({ body }) => body); + return es.slm.executeLifecycle({ policy_id: policyName }); }; const createSnapshot = (snapshotName: string, repositoryName: string) => { - return es.snapshot - .create({ snapshot: snapshotName, repository: repositoryName }) - .then(({ body }) => body); + return es.snapshot.create({ snapshot: snapshotName, repository: repositoryName }); }; const deleteSnapshots = (repositoryName: string) => { diff --git a/x-pack/test/api_integration/apis/metrics_ui/metric_threshold_alert.ts b/x-pack/test/api_integration/apis/metrics_ui/metric_threshold_alert.ts index 880d73a236c3b..bf5e9532edf25 100644 --- a/x-pack/test/api_integration/apis/metrics_ui/metric_threshold_alert.ts +++ b/x-pack/test/api_integration/apis/metrics_ui/metric_threshold_alert.ts @@ -6,6 +6,7 @@ */ import expect from '@kbn/expect'; +import { convertToKibanaClient } from '@kbn/test'; import { InfraSource } from '../../../../plugins/infra/common/source_configuration/source_configuration'; import { FtrProviderContext } from '../../ftr_provider_context'; import { @@ -103,7 +104,8 @@ export default function ({ getService }: FtrProviderContext) { metricAlias: 'filebeat-*', }; const timeFrame = { end: DATES.ten_thousand_plus.max }; - const results = await evaluateAlert(esClient, params, config, [], timeFrame); + const kbnClient = convertToKibanaClient(esClient); + const results = await evaluateAlert(kbnClient, params, config, [], timeFrame); expect(results).to.eql([ { '*': { @@ -144,7 +146,8 @@ export default function ({ getService }: FtrProviderContext) { metricAlias: 'filebeat-*', }; const timeFrame = { end: DATES.ten_thousand_plus.max }; - const results = await evaluateAlert(esClient, params, config, [], timeFrame); + const kbnClient = convertToKibanaClient(esClient); + const results = await evaluateAlert(kbnClient, params, config, [], timeFrame); expect(results).to.eql([ { web: { @@ -185,7 +188,8 @@ export default function ({ getService }: FtrProviderContext) { ], }; const timeFrame = { end: gauge.max }; - const results = await evaluateAlert(esClient, params, configuration, [], timeFrame); + const kbnClient = convertToKibanaClient(esClient); + const results = await evaluateAlert(kbnClient, params, configuration, [], timeFrame); expect(results).to.eql([ { '*': { @@ -208,7 +212,8 @@ export default function ({ getService }: FtrProviderContext) { it('should alert on the last value when the end date is the same as the last event', async () => { const params = { ...baseParams }; const timeFrame = { end: gauge.max }; - const results = await evaluateAlert(esClient, params, configuration, [], timeFrame); + const kbnClient = convertToKibanaClient(esClient); + const results = await evaluateAlert(kbnClient, params, configuration, [], timeFrame); expect(results).to.eql([ { '*': { @@ -245,7 +250,8 @@ export default function ({ getService }: FtrProviderContext) { ], }; const timeFrame = { end: gauge.max }; - const results = await evaluateAlert(esClient, params, configuration, [], timeFrame); + const kbnClient = convertToKibanaClient(esClient); + const results = await evaluateAlert(kbnClient, params, configuration, [], timeFrame); expect(results).to.eql([ { dev: { @@ -285,7 +291,8 @@ export default function ({ getService }: FtrProviderContext) { groupBy: ['env'], }; const timeFrame = { end: gauge.max }; - const results = await evaluateAlert(esClient, params, configuration, [], timeFrame); + const kbnClient = convertToKibanaClient(esClient); + const results = await evaluateAlert(kbnClient, params, configuration, [], timeFrame); expect(results).to.eql([ { dev: { @@ -326,8 +333,9 @@ export default function ({ getService }: FtrProviderContext) { groupBy: ['env'], }; const timeFrame = { end: gauge.midpoint }; + const kbnClient = convertToKibanaClient(esClient); const results = await evaluateAlert( - esClient, + kbnClient, params, configuration, ['dev', 'prod'], @@ -388,7 +396,8 @@ export default function ({ getService }: FtrProviderContext) { ], }; const timeFrame = { end: rate.max }; - const results = await evaluateAlert(esClient, params, configuration, [], timeFrame); + const kbnClient = convertToKibanaClient(esClient); + const results = await evaluateAlert(kbnClient, params, configuration, [], timeFrame); expect(results).to.eql([ { '*': { @@ -428,7 +437,8 @@ export default function ({ getService }: FtrProviderContext) { ], }; const timeFrame = { end: rate.max }; - const results = await evaluateAlert(esClient, params, configuration, [], timeFrame); + const kbnClient = convertToKibanaClient(esClient); + const results = await evaluateAlert(kbnClient, params, configuration, [], timeFrame); expect(results).to.eql([ { dev: { diff --git a/x-pack/test/api_integration/apis/metrics_ui/metrics_alerting.ts b/x-pack/test/api_integration/apis/metrics_ui/metrics_alerting.ts index 90b815d4d0530..f2c9d48ad4652 100644 --- a/x-pack/test/api_integration/apis/metrics_ui/metrics_alerting.ts +++ b/x-pack/test/api_integration/apis/metrics_ui/metrics_alerting.ts @@ -42,8 +42,9 @@ export default function ({ getService }: FtrProviderContext) { '@timestamp', timeframe ); - const { body: result } = await client.search({ + const result = await client.search({ index, + // @ts-expect-error @elastic/elasticsearch AggregationsBucketsPath is not valid body: searchBody, }); @@ -65,8 +66,9 @@ export default function ({ getService }: FtrProviderContext) { undefined, '{"bool":{"should":[{"match_phrase":{"agent.hostname":"foo"}}],"minimum_should_match":1}}' ); - const { body: result } = await client.search({ + const result = await client.search({ index, + // @ts-expect-error @elastic/elasticsearch AggregationsBucketsPath is not valid body: searchBody, }); @@ -87,8 +89,9 @@ export default function ({ getService }: FtrProviderContext) { timeframe, 'agent.id' ); - const { body: result } = await client.search({ + const result = await client.search({ index, + // @ts-expect-error @elastic/elasticsearch AggregationsBucketsPath is not valid body: searchBody, }); @@ -108,8 +111,9 @@ export default function ({ getService }: FtrProviderContext) { 'agent.id', '{"bool":{"should":[{"match_phrase":{"agent.hostname":"foo"}}],"minimum_should_match":1}}' ); - const { body: result } = await client.search({ + const result = await client.search({ index, + // @ts-expect-error @elastic/elasticsearch AggregationsBucketsPath is not valid body: searchBody, }); diff --git a/x-pack/test/api_integration/apis/ml/calendars/helpers.ts b/x-pack/test/api_integration/apis/ml/calendars/helpers.ts index 4667eb25437b1..3d60285bb5d23 100644 --- a/x-pack/test/api_integration/apis/ml/calendars/helpers.ts +++ b/x-pack/test/api_integration/apis/ml/calendars/helpers.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Calendar } from '../../../../../plugins/ml/server/models/calendar'; type ScheduledEvent = estypes.MlCalendarEvent; diff --git a/x-pack/test/api_integration/apis/ml/job_audit_messages/index.ts b/x-pack/test/api_integration/apis/ml/job_audit_messages/index.ts index a87855cef964e..d66728613a1cd 100644 --- a/x-pack/test/api_integration/apis/ml/job_audit_messages/index.ts +++ b/x-pack/test/api_integration/apis/ml/job_audit_messages/index.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { MlJob } from '@elastic/elasticsearch/api/types'; +import { MlJob } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ loadTestFile }: FtrProviderContext) { diff --git a/x-pack/test/api_integration/apis/ml/job_validation/datafeed_preview_validation.ts b/x-pack/test/api_integration/apis/ml/job_validation/datafeed_preview_validation.ts index c16050e08c886..b449fb903958f 100644 --- a/x-pack/test/api_integration/apis/ml/job_validation/datafeed_preview_validation.ts +++ b/x-pack/test/api_integration/apis/ml/job_validation/datafeed_preview_validation.ts @@ -12,7 +12,7 @@ */ import expect from '@kbn/expect'; -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { FtrProviderContext } from '../../../ftr_provider_context'; import { USER } from '../../../../functional/services/ml/security_common'; import { COMMON_REQUEST_HEADERS } from '../../../../functional/services/ml/common_api'; diff --git a/x-pack/test/api_integration/apis/monitoring/common/mappings_exist.js b/x-pack/test/api_integration/apis/monitoring/common/mappings_exist.js index f193e0dbe091a..a34473501c2e2 100644 --- a/x-pack/test/api_integration/apis/monitoring/common/mappings_exist.js +++ b/x-pack/test/api_integration/apis/monitoring/common/mappings_exist.js @@ -49,7 +49,7 @@ export default function ({ getService }) { let mappings; before('load mappings', async () => { - const { body: template } = await es.indices.getTemplate({ name: indexTemplate }); + const template = await es.indices.getTemplate({ name: indexTemplate }); mappings = get(template, [indexTemplate, 'mappings', 'properties']); }); diff --git a/x-pack/test/api_integration/apis/security/index_fields.ts b/x-pack/test/api_integration/apis/security/index_fields.ts index c21f65eb488ba..621a183182348 100644 --- a/x-pack/test/api_integration/apis/security/index_fields.ts +++ b/x-pack/test/api_integration/apis/security/index_fields.ts @@ -43,7 +43,7 @@ export default function ({ getService }: FtrProviderContext) { it('should not include runtime fields', async () => { // First, make sure the mapping actually includes a runtime field - const { body: mapping } = await es.indices.getMapping({ + const mapping = await es.indices.getMapping({ index: 'flstest', }); diff --git a/x-pack/test/api_integration/apis/security/roles.ts b/x-pack/test/api_integration/apis/security/roles.ts index 440bb4ca32f18..b07a5ca859a5c 100644 --- a/x-pack/test/api_integration/apis/security/roles.ts +++ b/x-pack/test/api_integration/apis/security/roles.ts @@ -58,7 +58,7 @@ export default function ({ getService }: FtrProviderContext) { }) .expect(204); - const { body: role } = await es.security.getRole({ name: 'role_with_privileges' }); + const role = await es.security.getRole({ name: 'role_with_privileges' }); expect(role).to.eql({ role_with_privileges: { cluster: ['manage'], @@ -186,7 +186,7 @@ export default function ({ getService }: FtrProviderContext) { }) .expect(204); - const { body: role } = await es.security.getRole({ name: 'role_to_update' }); + const role = await es.security.getRole({ name: 'role_to_update' }); expect(role).to.eql({ role_to_update: { cluster: ['manage'], @@ -263,7 +263,7 @@ export default function ({ getService }: FtrProviderContext) { }) .expect(basic ? 403 : 204); - const { body: role } = await es.security.getRole({ name: 'role_to_update_with_dls_fls' }); + const role = await es.security.getRole({ name: 'role_to_update_with_dls_fls' }); expect(role.role_to_update_with_dls_fls.cluster).to.eql(basic ? ['monitor'] : ['manage']); expect(role.role_to_update_with_dls_fls.run_as).to.eql( @@ -380,27 +380,24 @@ export default function ({ getService }: FtrProviderContext) { .set('kbn-xsrf', 'xxx') .expect(204); - const { body: emptyRole } = await es.security.getRole( - { name: 'empty_role' }, - { ignore: [404] } - ); + const emptyRole = await es.security.getRole({ name: 'empty_role' }, { ignore: [404] }); expect(emptyRole).to.eql({}); - const { body: roleWithPrivileges } = await es.security.getRole( + const roleWithPrivileges = await es.security.getRole( { name: 'role_with_privileges' }, { ignore: [404] } ); expect(roleWithPrivileges).to.eql({}); - const { body: roleWithPrivilegesDlsFls } = await es.security.getRole( + const roleWithPrivilegesDlsFls = await es.security.getRole( { name: 'role_with_privileges_dls_fls' }, { ignore: [404] } ); expect(roleWithPrivilegesDlsFls).to.eql({}); - const { body: roleToUpdate } = await es.security.getRole( + const roleToUpdate = await es.security.getRole( { name: 'role_to_update' }, { ignore: [404] } ); expect(roleToUpdate).to.eql({}); - const { body: roleToUpdateWithDlsFls } = await es.security.getRole( + const roleToUpdateWithDlsFls = await es.security.getRole( { name: 'role_to_update_with_dls_fls' }, { ignore: [404] } ); diff --git a/x-pack/test/api_integration/apis/security/users.ts b/x-pack/test/api_integration/apis/security/users.ts index 60554d2cf7c04..20f591205be39 100644 --- a/x-pack/test/api_integration/apis/security/users.ts +++ b/x-pack/test/api_integration/apis/security/users.ts @@ -31,7 +31,7 @@ export default function ({ getService }: FtrProviderContext) { .set('kbn-xsrf', 'xxx') .expect(204); - const { body } = await es.security.getUser({ username: mockUserName }); + const body = await es.security.getUser({ username: mockUserName }); expect(body[mockUserName].enabled).to.be(false); }); @@ -41,7 +41,7 @@ export default function ({ getService }: FtrProviderContext) { .set('kbn-xsrf', 'xxx') .expect(204); - const { body } = await es.security.getUser({ username: mockUserName }); + const body = await es.security.getUser({ username: mockUserName }); expect(body[mockUserName].enabled).to.be(true); }); }); diff --git a/x-pack/test/api_integration/apis/security_solution/utils.ts b/x-pack/test/api_integration/apis/security_solution/utils.ts index 79d5ef499deb2..4bc152ebcf5db 100644 --- a/x-pack/test/api_integration/apis/security_solution/utils.ts +++ b/x-pack/test/api_integration/apis/security_solution/utils.ts @@ -5,34 +5,38 @@ * 2.0. */ -import { ApiResponse, estypes } from '@elastic/elasticsearch'; -import { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { TransportResult } from '@elastic/elasticsearch'; +import type { Client } from '@elastic/elasticsearch'; import { JsonObject, JsonArray } from '@kbn/utility-types'; export async function getSavedObjectFromES( - es: KibanaClient, + es: Client, savedObjectType: string, query?: object -): Promise, unknown>> { - return await es.search({ - index: '.kibana', - body: { - query: { - bool: { - filter: [ - { ...query }, - { - term: { - type: { - value: savedObjectType, +): Promise, unknown>> { + return await es.search( + { + index: '.kibana', + body: { + query: { + bool: { + filter: [ + { ...query }, + { + term: { + type: { + value: savedObjectType, + }, }, }, - }, - ], + ], + }, }, }, }, - }); + { meta: true } + ); } export const getFilterValue = (hostName: string, from: string, to: string): JsonObject => ({ diff --git a/x-pack/test/api_integration/apis/telemetry/telemetry_optin_notice_seen.ts b/x-pack/test/api_integration/apis/telemetry/telemetry_optin_notice_seen.ts index 9e9211c4b5893..2a4725739e73f 100644 --- a/x-pack/test/api_integration/apis/telemetry/telemetry_optin_notice_seen.ts +++ b/x-pack/test/api_integration/apis/telemetry/telemetry_optin_notice_seen.ts @@ -24,9 +24,7 @@ export default function optInTest({ getService }: FtrProviderContext) { await supertest.put('/api/telemetry/v2/userHasSeenNotice').set('kbn-xsrf', 'xxx').expect(200); - const { - body: { _source }, - } = await client.get<{ telemetry: { userHasSeenNotice: boolean } }>({ + const { _source } = await client.get<{ telemetry: { userHasSeenNotice: boolean } }>({ index: '.kibana', id: 'telemetry:telemetry', }); diff --git a/x-pack/test/api_integration/apis/upgrade_assistant/upgrade_assistant.ts b/x-pack/test/api_integration/apis/upgrade_assistant/upgrade_assistant.ts index c0a6760d4cf53..3ed7856e8d1fe 100644 --- a/x-pack/test/api_integration/apis/upgrade_assistant/upgrade_assistant.ts +++ b/x-pack/test/api_integration/apis/upgrade_assistant/upgrade_assistant.ts @@ -89,7 +89,7 @@ export default function ({ getService }: FtrProviderContext) { // Refetch the index and verify settings were updated correctly try { - const { body: indexSettingsResponse } = await es.indices.getSettings({ + const indexSettingsResponse = await es.indices.getSettings({ index: indexName, }); diff --git a/x-pack/test/api_integration/apis/uptime/rest/helper/make_checks.ts b/x-pack/test/api_integration/apis/uptime/rest/helper/make_checks.ts index 51338d2bb6e03..b9e913524cb1f 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/helper/make_checks.ts +++ b/x-pack/test/api_integration/apis/uptime/rest/helper/make_checks.ts @@ -7,12 +7,12 @@ import uuid from 'uuid'; import { merge, flattenDeep } from 'lodash'; -import { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import type { Client } from '@elastic/elasticsearch'; import { makePing } from './make_ping'; import { TlsProps } from './make_tls'; interface CheckProps { - es: KibanaClient; + es: Client; monitorId?: string; numIps?: number; fields?: { [key: string]: any }; @@ -77,7 +77,7 @@ export const makeCheck = async ({ }; export const makeChecks = async ( - es: KibanaClient, + es: Client, monitorId: string, numChecks: number = 1, numIps: number = 1, @@ -122,7 +122,7 @@ export const makeChecks = async ( }; export const makeChecksWithStatus = async ( - es: KibanaClient, + es: Client, monitorId: string, numChecks: number, numIps: number, diff --git a/x-pack/test/api_integration/apis/uptime/rest/helper/make_ping.ts b/x-pack/test/api_integration/apis/uptime/rest/helper/make_ping.ts index 8532b3079f3c2..29421345393a8 100644 --- a/x-pack/test/api_integration/apis/uptime/rest/helper/make_ping.ts +++ b/x-pack/test/api_integration/apis/uptime/rest/helper/make_ping.ts @@ -7,14 +7,14 @@ import uuid from 'uuid'; import { merge } from 'lodash'; -import { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import type { Client } from '@elastic/elasticsearch'; import { makeTls, TlsProps } from './make_tls'; const DEFAULT_INDEX_NAME = 'heartbeat-8-generated-test'; const DATA_STREAM_INDEX_NAME = 'synthetics-http-default'; export const makePing = async ( - es: KibanaClient, + es: Client, monitorId: string, fields: { [key: string]: any }, mogrify: (doc: any) => any, diff --git a/x-pack/test/apm_api_integration/common/synthtrace_es_client.ts b/x-pack/test/apm_api_integration/common/synthtrace_es_client.ts index 68f5c2b08b518..6a42ae16f0b26 100644 --- a/x-pack/test/apm_api_integration/common/synthtrace_es_client.ts +++ b/x-pack/test/apm_api_integration/common/synthtrace_es_client.ts @@ -50,7 +50,7 @@ export async function synthtraceEsClient(context: InheritedFtrProviderContext) { ) ).then((results) => { const errors = results - .flatMap((result) => result.body.items) + .flatMap((result) => result.items) .filter((item) => !!item.index?.error) .map((item) => item.index?.error); diff --git a/x-pack/test/apm_api_integration/tests/alerts/rule_registry.ts b/x-pack/test/apm_api_integration/tests/alerts/rule_registry.ts index 7f107f127594d..06abeb02404c8 100644 --- a/x-pack/test/apm_api_integration/tests/alerts/rule_registry.ts +++ b/x-pack/test/apm_api_integration/tests/alerts/rule_registry.ts @@ -370,12 +370,9 @@ export default function ApiTest({ getService }: FtrProviderContext) { }, }); - expect(afterViolatingDataResponse.body.hits.hits.length).to.be(1); + expect(afterViolatingDataResponse.hits.hits.length).to.be(1); - const alertEvent = afterViolatingDataResponse.body.hits.hits[0].fields as Record< - string, - any - >; + const alertEvent = afterViolatingDataResponse.hits.hits[0].fields as Record; const exclude = ['@timestamp', ALERT_START, ALERT_UUID, ALERT_RULE_UUID, VERSION]; @@ -482,9 +479,9 @@ export default function ApiTest({ getService }: FtrProviderContext) { }, }); - expect(afterRecoveryResponse.body.hits.hits.length).to.be(1); + expect(afterRecoveryResponse.hits.hits.length).to.be(1); - const recoveredAlertEvent = afterRecoveryResponse.body.hits.hits[0].fields as Record< + const recoveredAlertEvent = afterRecoveryResponse.hits.hits[0].fields as Record< string, any >; diff --git a/x-pack/test/apm_api_integration/tests/metadata/event_metadata.ts b/x-pack/test/apm_api_integration/tests/metadata/event_metadata.ts index fb98cc9a6abd0..40af7b132eb8f 100644 --- a/x-pack/test/apm_api_integration/tests/metadata/event_metadata.ts +++ b/x-pack/test/apm_api_integration/tests/metadata/event_metadata.ts @@ -32,7 +32,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { }, }); - return response.body.hits.hits[0]._source![processorEvent].id; + return response.hits.hits[0]._source![processorEvent].id; } registry.when('Event metadata', { config: 'basic', archives: ['apm_8.0.0'] }, () => { diff --git a/x-pack/test/apm_api_integration/tests/service_overview/dependencies/es_utils.ts b/x-pack/test/apm_api_integration/tests/service_overview/dependencies/es_utils.ts index b1663ea714056..e0913ba09e448 100644 --- a/x-pack/test/apm_api_integration/tests/service_overview/dependencies/es_utils.ts +++ b/x-pack/test/apm_api_integration/tests/service_overview/dependencies/es_utils.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { MappingTypeMapping } from '@elastic/elasticsearch/api/types'; +import { MappingTypeMapping } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import uuid from 'uuid'; export function createServiceDependencyDocs({ diff --git a/x-pack/test/apm_api_integration/tests/service_overview/dependencies/index.ts b/x-pack/test/apm_api_integration/tests/service_overview/dependencies/index.ts index 1e8acccbb192a..1549e403c1377 100644 --- a/x-pack/test/apm_api_integration/tests/service_overview/dependencies/index.ts +++ b/x-pack/test/apm_api_integration/tests/service_overview/dependencies/index.ts @@ -75,7 +75,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { after(async () => { const allIndices = Object.values(indices).join(','); - const indexExists = (await es.indices.exists({ index: allIndices })).body; + const indexExists = await es.indices.exists({ index: allIndices }); if (indexExists) { await es.indices.delete({ index: allIndices, diff --git a/x-pack/test/apm_api_integration/tests/services/annotations.ts b/x-pack/test/apm_api_integration/tests/services/annotations.ts index 32ade1036e629..25737ce8cce9a 100644 --- a/x-pack/test/apm_api_integration/tests/services/annotations.ts +++ b/x-pack/test/apm_api_integration/tests/services/annotations.ts @@ -70,7 +70,7 @@ export default function annotationApiTests({ getService }: FtrProviderContext) { registry.when('Annotations with a trial license', { config: 'trial', archives: [] }, () => { describe('when creating an annotation', () => { afterEach(async () => { - const indexExists = (await es.indices.exists({ index: DEFAULT_INDEX_NAME })).body; + const indexExists = await es.indices.exists({ index: DEFAULT_INDEX_NAME }); if (indexExists) { await es.indices.delete({ index: DEFAULT_INDEX_NAME, @@ -259,11 +259,9 @@ export default function annotationApiTests({ getService }: FtrProviderContext) { index: transactionIndexName, }); - const annotationIndexExists = ( - await es.indices.exists({ - index: DEFAULT_INDEX_NAME, - }) - ).body; + const annotationIndexExists = await es.indices.exists({ + index: DEFAULT_INDEX_NAME, + }); if (annotationIndexExists) { await es.indices.delete({ diff --git a/x-pack/test/apm_api_integration/tests/services/derived_annotations.ts b/x-pack/test/apm_api_integration/tests/services/derived_annotations.ts index f401d69b1b002..c9ee61557deb6 100644 --- a/x-pack/test/apm_api_integration/tests/services/derived_annotations.ts +++ b/x-pack/test/apm_api_integration/tests/services/derived_annotations.ts @@ -32,7 +32,7 @@ export default function annotationApiTests({ getService }: FtrProviderContext) { let response: APIReturnType<'GET /api/apm/services/{serviceName}/annotation/search'>; before(async () => { - const { body: indexExists } = await es.indices.exists({ index: indexName }); + const indexExists = await es.indices.exists({ index: indexName }); if (indexExists) { await es.indices.delete({ index: indexName, diff --git a/x-pack/test/case_api_integration/common/lib/utils.ts b/x-pack/test/case_api_integration/common/lib/utils.ts index 9d48aed32d55c..212b59f0e51f7 100644 --- a/x-pack/test/case_api_integration/common/lib/utils.ts +++ b/x-pack/test/case_api_integration/common/lib/utils.ts @@ -10,8 +10,9 @@ import getPort from 'get-port'; import http from 'http'; import expect from '@kbn/expect'; -import type { ApiResponse, estypes } from '@elastic/elasticsearch'; -import type { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { TransportResult } from '@elastic/elasticsearch'; +import type { Client } from '@elastic/elasticsearch'; import type SuperTest from 'supertest'; import { ObjectRemover as ActionsRemover } from '../../../alerting_api_integration/common/lib'; @@ -78,27 +79,30 @@ export const getSignalsWithES = async ({ indices, ids, }: { - es: KibanaClient; + es: Client; indices: string | string[]; ids: string | string[]; }): Promise>>> => { - const signals: ApiResponse> = await es.search({ - index: indices, - body: { - size: 10000, - query: { - bool: { - filter: [ - { - ids: { - values: toArray(ids), + const signals: TransportResult, unknown> = await es.search( + { + index: indices, + body: { + size: 10000, + query: { + bool: { + filter: [ + { + ids: { + values: toArray(ids), + }, }, - }, - ], + ], + }, }, }, }, - }); + { meta: true } + ); return signals.body.hits.hits.reduce((acc, hit) => { let indexMap = acc.get(hit._index); @@ -470,7 +474,7 @@ export const removeServerGeneratedPropertiesFromComments = ( }); }; -export const deleteAllCaseItems = async (es: KibanaClient) => { +export const deleteAllCaseItems = async (es: Client) => { await Promise.all([ deleteCasesByESQuery(es), deleteSubCases(es), @@ -481,7 +485,7 @@ export const deleteAllCaseItems = async (es: KibanaClient) => { ]); }; -export const deleteCasesUserActions = async (es: KibanaClient): Promise => { +export const deleteCasesUserActions = async (es: Client): Promise => { await es.deleteByQuery({ index: '.kibana', q: 'type:cases-user-actions', @@ -492,7 +496,7 @@ export const deleteCasesUserActions = async (es: KibanaClient): Promise => }); }; -export const deleteCasesByESQuery = async (es: KibanaClient): Promise => { +export const deleteCasesByESQuery = async (es: Client): Promise => { await es.deleteByQuery({ index: '.kibana', q: 'type:cases', @@ -507,7 +511,7 @@ export const deleteCasesByESQuery = async (es: KibanaClient): Promise => { * Deletes all sub cases in the .kibana index. This uses ES to perform the delete and does * not go through the case API. */ -export const deleteSubCases = async (es: KibanaClient): Promise => { +export const deleteSubCases = async (es: Client): Promise => { await es.deleteByQuery({ index: '.kibana', q: 'type:cases-sub-case', @@ -518,7 +522,7 @@ export const deleteSubCases = async (es: KibanaClient): Promise => { }); }; -export const deleteComments = async (es: KibanaClient): Promise => { +export const deleteComments = async (es: Client): Promise => { await es.deleteByQuery({ index: '.kibana', q: 'type:cases-comments', @@ -529,7 +533,7 @@ export const deleteComments = async (es: KibanaClient): Promise => { }); }; -export const deleteConfiguration = async (es: KibanaClient): Promise => { +export const deleteConfiguration = async (es: Client): Promise => { await es.deleteByQuery({ index: '.kibana', q: 'type:cases-configure', @@ -540,7 +544,7 @@ export const deleteConfiguration = async (es: KibanaClient): Promise => { }); }; -export const deleteMappings = async (es: KibanaClient): Promise => { +export const deleteMappings = async (es: Client): Promise => { await es.deleteByQuery({ index: '.kibana', q: 'type:cases-connector-mappings', @@ -595,9 +599,12 @@ interface ConnectorMappingsSavedObject { /** * Returns connector mappings saved objects from Elasticsearch directly. */ -export const getConnectorMappingsFromES = async ({ es }: { es: KibanaClient }) => { - const mappings: ApiResponse> = - await es.search({ +export const getConnectorMappingsFromES = async ({ es }: { es: Client }) => { + const mappings: TransportResult< + estypes.SearchResponse, + unknown + > = await es.search( + { index: '.kibana', body: { query: { @@ -608,7 +615,9 @@ export const getConnectorMappingsFromES = async ({ es }: { es: KibanaClient }) = }, }, }, - }); + }, + { meta: true } + ); return mappings; }; @@ -620,26 +629,35 @@ interface ConfigureSavedObject { /** * Returns configure saved objects from Elasticsearch directly. */ -export const getConfigureSavedObjectsFromES = async ({ es }: { es: KibanaClient }) => { - const configure: ApiResponse> = await es.search({ - index: '.kibana', - body: { - query: { - term: { - type: { - value: 'cases-configure', +export const getConfigureSavedObjectsFromES = async ({ es }: { es: Client }) => { + const configure: TransportResult< + estypes.SearchResponse, + unknown + > = await es.search( + { + index: '.kibana', + body: { + query: { + term: { + type: { + value: 'cases-configure', + }, }, }, }, }, - }); + { meta: true } + ); return configure; }; -export const getCaseSavedObjectsFromES = async ({ es }: { es: KibanaClient }) => { - const configure: ApiResponse> = - await es.search({ +export const getCaseSavedObjectsFromES = async ({ es }: { es: Client }) => { + const configure: TransportResult< + estypes.SearchResponse<{ cases: ESCaseAttributes }>, + unknown + > = await es.search( + { index: '.kibana', body: { query: { @@ -650,7 +668,9 @@ export const getCaseSavedObjectsFromES = async ({ es }: { es: KibanaClient }) => }, }, }, - }); + }, + { meta: true } + ); return configure; }; diff --git a/x-pack/test/case_api_integration/security_and_spaces/tests/common/cases/find_cases.ts b/x-pack/test/case_api_integration/security_and_spaces/tests/common/cases/find_cases.ts index b7838dd9299bc..d0d4cea91146d 100644 --- a/x-pack/test/case_api_integration/security_and_spaces/tests/common/cases/find_cases.ts +++ b/x-pack/test/case_api_integration/security_and_spaces/tests/common/cases/find_cases.ts @@ -6,7 +6,6 @@ */ import expect from '@kbn/expect'; -import type { ApiResponse, estypes } from '@elastic/elasticsearch'; import { FtrProviderContext } from '../../../../common/ftr_provider_context'; import { @@ -423,7 +422,7 @@ export default ({ getService }: FtrProviderContext): void => { * around 30 seconds which seemed too slow */ const getAllCasesSortedByCreatedAtAsc = async () => { - const cases: ApiResponse> = await es.search({ + const cases = await es.search({ index: '.kibana', body: { size: 10000, @@ -433,7 +432,7 @@ export default ({ getService }: FtrProviderContext): void => { }, }, }); - return cases.body.hits.hits.map((hit) => hit._source); + return cases.hits.hits.map((hit) => hit._source); }; it('returns the correct total when perPage is less than the total', async () => { diff --git a/x-pack/test/case_api_integration/security_and_spaces/tests/common/sub_cases/find_sub_cases.ts b/x-pack/test/case_api_integration/security_and_spaces/tests/common/sub_cases/find_sub_cases.ts index d54523bec0c4d..91a6ebc098b8e 100644 --- a/x-pack/test/case_api_integration/security_and_spaces/tests/common/sub_cases/find_sub_cases.ts +++ b/x-pack/test/case_api_integration/security_and_spaces/tests/common/sub_cases/find_sub_cases.ts @@ -6,7 +6,6 @@ */ import expect from '@kbn/expect'; -import type { ApiResponse, estypes } from '@elastic/elasticsearch'; import { FtrProviderContext } from '../../../../common/ftr_provider_context'; import { findSubCasesResp, postCollectionReq } from '../../../../common/lib/mock'; @@ -313,7 +312,7 @@ export default ({ getService }: FtrProviderContext): void => { }; const getAllCasesSortedByCreatedAtAsc = async () => { - const cases: ApiResponse> = await es.search({ + const cases = await es.search({ index: '.kibana', body: { size: 10000, @@ -323,7 +322,7 @@ export default ({ getService }: FtrProviderContext): void => { }, }, }); - return cases.body.hits.hits.map((hit) => hit._source); + return cases.hits.hits.map((hit) => hit._source); }; it('returns the correct total when perPage is less than the total', async () => { diff --git a/x-pack/test/detection_engine_api_integration/basic/tests/open_close_signals.ts b/x-pack/test/detection_engine_api_integration/basic/tests/open_close_signals.ts index 071be0e7add92..e46391e5cc2dd 100644 --- a/x-pack/test/detection_engine_api_integration/basic/tests/open_close_signals.ts +++ b/x-pack/test/detection_engine_api_integration/basic/tests/open_close_signals.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Signal } from '../../../../plugins/security_solution/server/lib/detection_engine/signals/types'; import { DETECTION_ENGINE_SIGNALS_STATUS_URL, diff --git a/x-pack/test/detection_engine_api_integration/basic/tests/update_rac_alerts.ts b/x-pack/test/detection_engine_api_integration/basic/tests/update_rac_alerts.ts index 2b339159d5900..cdad74720b9e2 100644 --- a/x-pack/test/detection_engine_api_integration/basic/tests/update_rac_alerts.ts +++ b/x-pack/test/detection_engine_api_integration/basic/tests/update_rac_alerts.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Signal } from '../../../../plugins/security_solution/server/lib/detection_engine/signals/types'; import { DETECTION_ENGINE_QUERY_SIGNALS_URL } from '../../../../plugins/security_solution/common/constants'; import { RAC_ALERTS_BULK_UPDATE_URL } from '../../../../plugins/timelines/common/constants'; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/alerts/alerts_compatibility.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/alerts/alerts_compatibility.ts index 8d12f9192e13b..ee4dadd1ffcb5 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/alerts/alerts_compatibility.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/alerts/alerts_compatibility.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import expect from '@kbn/expect'; import { diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_signals_migrations.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_signals_migrations.ts index 8d18b98e40c59..d0c610319ba88 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_signals_migrations.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_signals_migrations.ts @@ -97,7 +97,7 @@ export default ({ getService }: FtrProviderContext): void => { const [{ migration_index: newIndex }] = createResponses; await waitForIndexToPopulate(es, newIndex); - const { body: migrationResults } = await es.search<{ signal: Signal }>({ index: newIndex }); + const migrationResults = await es.search<{ signal: Signal }>({ index: newIndex }); expect(migrationResults.hits.hits).length(1); const migratedSignal = migrationResults.hits.hits[0]._source?.signal; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/delete_signals_migrations.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/delete_signals_migrations.ts index 5f373ceedcf7d..73bd8abf0a304 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/delete_signals_migrations.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/delete_signals_migrations.ts @@ -95,7 +95,10 @@ export default ({ getService }: FtrProviderContext): void => { .send({ migration_ids: [createdMigration.migration_id] }) .expect(200); - const { body } = await es.indices.getSettings({ index: createdMigration.index }); + const { body } = await es.indices.getSettings( + { index: createdMigration.index }, + { meta: true } + ); // @ts-expect-error @elastic/elasticsearch supports flatten 'index.*' keys only const indexSettings = body[createdMigration.index].settings.index; expect(indexSettings.lifecycle.name).to.eql( diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/migrations.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/migrations.ts index cfae7532ba496..d4eaf0d3dbf80 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/migrations.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/migrations.ts @@ -31,10 +31,15 @@ export default ({ getService }: FtrProviderContext): void => { actions: [{ id: string; actionRef: string }]; }; references: [{}]; - }>({ - index: '.kibana', - id: 'siem-detection-engine-rule-actions:fce024a0-0452-11ec-9b15-d13d79d162f3', - }); + }>( + { + index: '.kibana', + id: 'siem-detection-engine-rule-actions:fce024a0-0452-11ec-9b15-d13d79d162f3', + }, + { + meta: true, + } + ); expect(response.statusCode).to.eql(200); // references exist and are expected values @@ -73,10 +78,15 @@ export default ({ getService }: FtrProviderContext): void => { ruleThrottle: string; alertThrottle: string; }; - }>({ - index: '.kibana', - id: 'siem-detection-engine-rule-actions:fce024a0-0452-11ec-9b15-d13d79d162f3', - }); + }>( + { + index: '.kibana', + id: 'siem-detection-engine-rule-actions:fce024a0-0452-11ec-9b15-d13d79d162f3', + }, + { + meta: true, + } + ); expect(response.statusCode).to.eql(200); // "alertThrottle" and "ruleThrottle" should still exist @@ -94,10 +104,13 @@ export default ({ getService }: FtrProviderContext): void => { alertId: string; }; references: [{}]; - }>({ - index: '.kibana', - id: 'siem-detection-engine-rule-status:d62d2980-27c4-11ec-92b0-f7b47106bb35', - }); + }>( + { + index: '.kibana', + id: 'siem-detection-engine-rule-status:d62d2980-27c4-11ec-92b0-f7b47106bb35', + }, + { meta: true } + ); expect(response.statusCode).to.eql(200); // references exist and are expected values @@ -118,10 +131,13 @@ export default ({ getService }: FtrProviderContext): void => { it('migrates legacy siem-detection-engine-rule-status and retains other attributes as the same attributes as before', async () => { const response = await es.get<{ 'siem-detection-engine-rule-status': IRuleStatusSOAttributes; - }>({ - index: '.kibana', - id: 'siem-detection-engine-rule-status:d62d2980-27c4-11ec-92b0-f7b47106bb35', - }); + }>( + { + index: '.kibana', + id: 'siem-detection-engine-rule-status:d62d2980-27c4-11ec-92b0-f7b47106bb35', + }, + { meta: true } + ); expect(response.statusCode).to.eql(200); expect(response.body._source?.['siem-detection-engine-rule-status']).to.eql({ diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/open_close_signals.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/open_close_signals.ts index 7b6192ddc07e9..6654852988613 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/open_close_signals.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/open_close_signals.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { Signal } from '../../../../plugins/security_solution/server/lib/detection_engine/signals/types'; import { diff --git a/x-pack/test/detection_engine_api_integration/utils.ts b/x-pack/test/detection_engine_api_integration/utils.ts index edb2db3e9a261..9fd1086e5b6f1 100644 --- a/x-pack/test/detection_engine_api_integration/utils.ts +++ b/x-pack/test/detection_engine_api_integration/utils.ts @@ -6,10 +6,9 @@ */ import { KbnClient } from '@kbn/test'; -import type { ApiResponse } from '@elastic/elasticsearch'; -import { Context } from '@elastic/elasticsearch/lib/Transport'; -import type { estypes } from '@elastic/elasticsearch'; -import type { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import type { TransportResult } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { Client } from '@elastic/elasticsearch'; import type SuperTest from 'supertest'; import type { ListArray, @@ -443,24 +442,27 @@ export const deleteAllAlerts = async ( ); }; -export const downgradeImmutableRule = async (es: KibanaClient, ruleId: string): Promise => { +export const downgradeImmutableRule = async (es: Client, ruleId: string): Promise => { return countDownES(async () => { - return es.updateByQuery({ - index: '.kibana', - refresh: true, - wait_for_completion: true, - body: { - script: { - lang: 'painless', - source: 'ctx._source.alert.params.version--', - }, - query: { - term: { - 'alert.tags': `${INTERNAL_RULE_ID_KEY}:${ruleId}`, + return es.updateByQuery( + { + index: '.kibana', + refresh: true, + wait_for_completion: true, + body: { + script: { + lang: 'painless', + source: 'ctx._source.alert.params.version--', + }, + query: { + term: { + 'alert.tags': `${INTERNAL_RULE_ID_KEY}:${ruleId}`, + }, }, }, }, - }); + { meta: true } + ); }, 'downgradeImmutableRule'); }; @@ -468,7 +470,7 @@ export const downgradeImmutableRule = async (es: KibanaClient, ruleId: string): * Remove all timelines from the .kibana index * @param es The ElasticSearch handle */ -export const deleteAllTimelines = async (es: KibanaClient): Promise => { +export const deleteAllTimelines = async (es: Client): Promise => { await es.deleteByQuery({ index: '.kibana', q: 'type:siem-ui-timeline', @@ -483,15 +485,18 @@ export const deleteAllTimelines = async (es: KibanaClient): Promise => { * This will retry 20 times before giving up and hopefully still not interfere with other tests * @param es The ElasticSearch handle */ -export const deleteAllRulesStatuses = async (es: KibanaClient): Promise => { +export const deleteAllRulesStatuses = async (es: Client): Promise => { return countDownES(async () => { - return es.deleteByQuery({ - index: '.kibana', - q: 'type:siem-detection-engine-rule-status', - wait_for_completion: true, - refresh: true, - body: {}, - }); + return es.deleteByQuery( + { + index: '.kibana', + q: 'type:siem-detection-engine-rule-status', + wait_for_completion: true, + refresh: true, + body: {}, + }, + { meta: true } + ); }, 'deleteAllRulesStatuses'); }; @@ -809,7 +814,7 @@ export const waitFor = async ( * @param timeoutWait Time to wait before trying again (has default) */ export const countDownES = async ( - esFunction: () => Promise, Context>>, + esFunction: () => Promise, unknown>>, esFunctionName: string, retryCount: number = 20, timeoutWait = 250 @@ -836,7 +841,7 @@ export const countDownES = async ( * Useful for tests where we want to ensure that a rule does NOT create alerts, e.g. testing exceptions. * @param es The ElasticSearch handle */ -export const refreshIndex = async (es: KibanaClient, index?: string) => { +export const refreshIndex = async (es: Client, index?: string) => { await es.indices.refresh({ index, }); @@ -1468,10 +1473,10 @@ export const getIndexNameFromLoad = (loadResponse: Record): str * @param esClient elasticsearch {@link Client} * @param index name of the index to query */ -export const waitForIndexToPopulate = async (es: KibanaClient, index: string): Promise => { +export const waitForIndexToPopulate = async (es: Client, index: string): Promise => { await waitFor(async () => { - const response = await es.count<{ count: number }>({ index }); - return response.body.count > 0; + const response = await es.count({ index }); + return response.count > 0; }, `waitForIndexToPopulate: ${index}`); }; @@ -1542,7 +1547,7 @@ export const finalizeSignalsMigration = async ({ export const getOpenSignals = async ( supertest: SuperTest.SuperTest, - es: KibanaClient, + es: Client, rule: FullResponseSchema ) => { await waitForRuleSuccessOrStatus(supertest, rule.id); diff --git a/x-pack/test/encrypted_saved_objects_api_integration/tests/encrypted_saved_objects_api.ts b/x-pack/test/encrypted_saved_objects_api_integration/tests/encrypted_saved_objects_api.ts index 311228424afe3..79880e1f21cb0 100644 --- a/x-pack/test/encrypted_saved_objects_api_integration/tests/encrypted_saved_objects_api.ts +++ b/x-pack/test/encrypted_saved_objects_api_integration/tests/encrypted_saved_objects_api.ts @@ -28,9 +28,7 @@ export default function ({ getService }: FtrProviderContext) { generateRawID: (id: string, type: string) => string ) { async function getRawSavedObjectAttributes({ id, type }: SavedObject) { - const { - body: { _source }, - } = await es.get>({ + const { _source } = await es.get>({ id: generateRawID(id, type), index: '.kibana', }); diff --git a/x-pack/test/examples/search_examples/search_session_example.ts b/x-pack/test/examples/search_examples/search_session_example.ts index 4834fbddea899..ab96a7767baff 100644 --- a/x-pack/test/examples/search_examples/search_session_example.ts +++ b/x-pack/test/examples/search_examples/search_session_example.ts @@ -19,7 +19,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { const appId = 'searchExamples'; before(async function () { - const { body } = await es.info(); + const body = await es.info(); if (!body.version.number.includes('SNAPSHOT')) { log.debug('Skipping because this build does not have the required shard_delay agg'); this.skip(); diff --git a/x-pack/test/fleet_api_integration/apis/agent_policy/agent_policy_with_agents_setup.ts b/x-pack/test/fleet_api_integration/apis/agent_policy/agent_policy_with_agents_setup.ts index a4f67cd58d935..87bb8b7d1c913 100644 --- a/x-pack/test/fleet_api_integration/apis/agent_policy/agent_policy_with_agents_setup.ts +++ b/x-pack/test/fleet_api_integration/apis/agent_policy/agent_policy_with_agents_setup.ts @@ -50,7 +50,7 @@ export default function (providerContext: FtrProviderContext) { }); // @ts-expect-error TotalHit - return res.body.hits.total.value !== 0; + return res.hits.total.value !== 0; } // Test all the side effect that should occurs when we create|update an agent policy diff --git a/x-pack/test/fleet_api_integration/apis/agents/services.ts b/x-pack/test/fleet_api_integration/apis/agents/services.ts index 0e28ad647bbc4..f9f779271934e 100644 --- a/x-pack/test/fleet_api_integration/apis/agents/services.ts +++ b/x-pack/test/fleet_api_integration/apis/agents/services.ts @@ -6,7 +6,7 @@ */ import supertest from 'supertest'; -import { Client } from '@elastic/elasticsearch'; +import { Client, HttpConnection } from '@elastic/elasticsearch'; import { format as formatUrl } from 'url'; import { FtrProviderContext } from '../../../api_integration/ftr_provider_context'; @@ -29,6 +29,7 @@ export function getEsClientForAPIKey({ getService }: FtrProviderContext, esApiKe apiKey: esApiKey, }, requestTimeout: config.get('timeouts.esRequestTimeout'), + Connection: HttpConnection, }); } @@ -36,10 +37,8 @@ export function setupFleetAndAgents(providerContext: FtrProviderContext) { before(async () => { // Use elastic/fleet-server service account to execute setup to verify privilege configuration const es = providerContext.getService('es'); - const { - body: { token }, - // @ts-expect-error SecurityCreateServiceTokenRequest should not require `name` - } = await es.security.createServiceToken({ + // @ts-expect-error SecurityCreateServiceTokenRequest should not require `name` + const { token } = await es.security.createServiceToken({ namespace: 'elastic', service: 'fleet-server', }); diff --git a/x-pack/test/fleet_api_integration/apis/agents/unenroll.ts b/x-pack/test/fleet_api_integration/apis/agents/unenroll.ts index 05ada4cc6a388..14dd5871a0317 100644 --- a/x-pack/test/fleet_api_integration/apis/agents/unenroll.ts +++ b/x-pack/test/fleet_api_integration/apis/agents/unenroll.ts @@ -30,21 +30,19 @@ export default function (providerContext: FtrProviderContext) { await esArchiver.unload('x-pack/test/functional/es_archives/fleet/empty_fleet_server'); await esArchiver.load('x-pack/test/functional/es_archives/fleet/agents'); await getService('supertest').post(`/api/fleet/setup`).set('kbn-xsrf', 'xxx').send(); - const { body: accessAPIKeyBody } = await esClient.security.createApiKey({ + const accessAPIKeyBody = await esClient.security.createApiKey({ body: { name: `test access api key: ${uuid.v4()}`, }, }); accessAPIKeyId = accessAPIKeyBody.id; - const { body: outputAPIKeyBody } = await esClient.security.createApiKey({ + const outputAPIKeyBody = await esClient.security.createApiKey({ body: { name: `test output api key: ${uuid.v4()}`, }, }); outputAPIKeyId = outputAPIKeyBody.id; - const { - body: { _source: agentDoc }, - } = await esClient.get({ + const { _source: agentDoc } = await esClient.get({ index: '.fleet-agents', id: 'agent1', }); @@ -104,15 +102,11 @@ export default function (providerContext: FtrProviderContext) { }) .expect(200); - const { - body: { api_keys: accessAPIKeys }, - } = await esClient.security.getApiKey({ id: accessAPIKeyId }); + const { api_keys: accessAPIKeys } = await esClient.security.getApiKey({ id: accessAPIKeyId }); expect(accessAPIKeys).length(1); expect(accessAPIKeys[0].invalidated).eql(true); - const { - body: { api_keys: outputAPIKeys }, - } = await esClient.security.getApiKey({ id: outputAPIKeyId }); + const { api_keys: outputAPIKeys } = await esClient.security.getApiKey({ id: outputAPIKeyId }); expect(outputAPIKeys).length(1); expect(outputAPIKeys[0].invalidated).eql(true); }); diff --git a/x-pack/test/fleet_api_integration/apis/data_streams/list.ts b/x-pack/test/fleet_api_integration/apis/data_streams/list.ts index 7755acc2468b1..365eb716592d1 100644 --- a/x-pack/test/fleet_api_integration/apis/data_streams/list.ts +++ b/x-pack/test/fleet_api_integration/apis/data_streams/list.ts @@ -146,21 +146,24 @@ export default function (providerContext: FtrProviderContext) { // Wait until backing indices are created await retry.tryForTime(10000, async () => { - const { body } = await es.transport.request({ - method: 'GET', - path: `/${logsTemplateName}-default,${metricsTemplateName}-default/_search`, - body: { - size: 0, - aggs: { - index: { - terms: { - field: '_index', - size: 100000, + const { body } = await es.transport.request( + { + method: 'GET', + path: `/${logsTemplateName}-default,${metricsTemplateName}-default/_search`, + body: { + size: 0, + aggs: { + index: { + terms: { + field: '_index', + size: 100000, + }, }, }, }, }, - }); + { meta: true } + ); expect(body.aggregations.index.buckets.length).to.eql(4); }); diff --git a/x-pack/test/fleet_api_integration/apis/enrollment_api_keys/crud.ts b/x-pack/test/fleet_api_integration/apis/enrollment_api_keys/crud.ts index 429bc3b80a54f..d1d9ce70dcd25 100644 --- a/x-pack/test/fleet_api_integration/apis/enrollment_api_keys/crud.ts +++ b/x-pack/test/fleet_api_integration/apis/enrollment_api_keys/crud.ts @@ -73,9 +73,7 @@ export default function (providerContext: FtrProviderContext) { .set('kbn-xsrf', 'xxx') .expect(200); - const { - body: { api_keys: apiKeys }, - } = await es.security.getApiKey({ id: esApiKeyId }); + const { api_keys: apiKeys } = await es.security.getApiKey({ id: esApiKeyId }); expect(apiKeys).length(1); expect(apiKeys[0].invalidated).eql(true); @@ -173,7 +171,7 @@ export default function (providerContext: FtrProviderContext) { }) .expect(200); - const { body: apiKeyRes } = await es.security.getApiKey({ + const apiKeyRes = await es.security.getApiKey({ id: apiResponse.item.api_key_id, }); @@ -197,17 +195,20 @@ export default function (providerContext: FtrProviderContext) { const { body: privileges } = await getEsClientForAPIKey( providerContext, apiResponse.item.api_key - ).security.hasPrivileges({ - body: { - cluster: ['all', 'monitor', 'manage_api_key'], - index: [ - { - names: ['log-*', 'metrics-*', 'events-*', '*'], - privileges: ['write', 'create_index'], - }, - ], + ).security.hasPrivileges( + { + body: { + cluster: ['all', 'monitor', 'manage_api_key'], + index: [ + { + names: ['log-*', 'metrics-*', 'events-*', '*'], + privileges: ['write', 'create_index'], + }, + ], + }, }, - }); + { meta: true } + ); expect(privileges.cluster).to.eql({ all: false, monitor: false, diff --git a/x-pack/test/fleet_api_integration/apis/epm/data_stream.ts b/x-pack/test/fleet_api_integration/apis/epm/data_stream.ts index e258d1c4a2d07..9cdc21943a312 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/data_stream.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/data_stream.ts @@ -43,32 +43,38 @@ export default function (providerContext: FtrProviderContext) { await installPackage(pkgKey); await Promise.all( namespaces.map(async (namespace) => { - const createLogsRequest = es.transport.request({ - method: 'POST', - path: `/${logsTemplateName}-${namespace}/_doc`, - body: { - '@timestamp': '2015-01-01', - logs_test_name: 'test', - data_stream: { - dataset: `${pkgName}.test_logs`, - namespace, - type: 'logs', + const createLogsRequest = es.transport.request( + { + method: 'POST', + path: `/${logsTemplateName}-${namespace}/_doc`, + body: { + '@timestamp': '2015-01-01', + logs_test_name: 'test', + data_stream: { + dataset: `${pkgName}.test_logs`, + namespace, + type: 'logs', + }, }, }, - }); - const createMetricsRequest = es.transport.request({ - method: 'POST', - path: `/${metricsTemplateName}-${namespace}/_doc`, - body: { - '@timestamp': '2015-01-01', - logs_test_name: 'test', - data_stream: { - dataset: `${pkgName}.test_metrics`, - namespace, - type: 'metrics', + { meta: true } + ); + const createMetricsRequest = es.transport.request( + { + method: 'POST', + path: `/${metricsTemplateName}-${namespace}/_doc`, + body: { + '@timestamp': '2015-01-01', + logs_test_name: 'test', + data_stream: { + dataset: `${pkgName}.test_metrics`, + namespace, + type: 'metrics', + }, }, }, - }); + { meta: true } + ); return Promise.all([createLogsRequest, createMetricsRequest]); }) ); @@ -77,14 +83,20 @@ export default function (providerContext: FtrProviderContext) { afterEach(async () => { await Promise.all( namespaces.map(async (namespace) => { - const deleteLogsRequest = es.transport.request({ - method: 'DELETE', - path: `/_data_stream/${logsTemplateName}-${namespace}`, - }); - const deleteMetricsRequest = es.transport.request({ - method: 'DELETE', - path: `/_data_stream/${metricsTemplateName}-${namespace}`, - }); + const deleteLogsRequest = es.transport.request( + { + method: 'DELETE', + path: `/_data_stream/${logsTemplateName}-${namespace}`, + }, + { meta: true } + ); + const deleteMetricsRequest = es.transport.request( + { + method: 'DELETE', + path: `/_data_stream/${metricsTemplateName}-${namespace}`, + }, + { meta: true } + ); return Promise.all([deleteLogsRequest, deleteMetricsRequest]); }) ); @@ -94,14 +106,20 @@ export default function (providerContext: FtrProviderContext) { it('should list the logs and metrics datastream', async function () { await asyncForEach(namespaces, async (namespace) => { - const resLogsDatastream = await es.transport.request({ - method: 'GET', - path: `/_data_stream/${logsTemplateName}-${namespace}`, - }); - const resMetricsDatastream = await es.transport.request({ - method: 'GET', - path: `/_data_stream/${metricsTemplateName}-${namespace}`, - }); + const resLogsDatastream = await es.transport.request( + { + method: 'GET', + path: `/_data_stream/${logsTemplateName}-${namespace}`, + }, + { meta: true } + ); + const resMetricsDatastream = await es.transport.request( + { + method: 'GET', + path: `/_data_stream/${metricsTemplateName}-${namespace}`, + }, + { meta: true } + ); expect(resLogsDatastream.body.data_streams.length).equal(1); expect(resLogsDatastream.body.data_streams[0].indices.length).equal(1); expect(resMetricsDatastream.body.data_streams.length).equal(1); @@ -112,14 +130,20 @@ export default function (providerContext: FtrProviderContext) { it('after update, it should have rolled over logs datastream because mappings are not compatible and not metrics', async function () { await installPackage(pkgUpdateKey); await asyncForEach(namespaces, async (namespace) => { - const resLogsDatastream = await es.transport.request({ - method: 'GET', - path: `/_data_stream/${logsTemplateName}-${namespace}`, - }); - const resMetricsDatastream = await es.transport.request({ - method: 'GET', - path: `/_data_stream/${metricsTemplateName}-${namespace}`, - }); + const resLogsDatastream = await es.transport.request( + { + method: 'GET', + path: `/_data_stream/${logsTemplateName}-${namespace}`, + }, + { meta: true } + ); + const resMetricsDatastream = await es.transport.request( + { + method: 'GET', + path: `/_data_stream/${metricsTemplateName}-${namespace}`, + }, + { meta: true } + ); expect(resLogsDatastream.body.data_streams[0].indices.length).equal(2); expect(resMetricsDatastream.body.data_streams[0].indices.length).equal(1); }); @@ -127,14 +151,20 @@ export default function (providerContext: FtrProviderContext) { it('should be able to upgrade a package after a rollover', async function () { await asyncForEach(namespaces, async (namespace) => { - await es.transport.request({ - method: 'POST', - path: `/${logsTemplateName}-${namespace}/_rollover`, - }); - const resLogsDatastream = await es.transport.request({ - method: 'GET', - path: `/_data_stream/${logsTemplateName}-${namespace}`, - }); + await es.transport.request( + { + method: 'POST', + path: `/${logsTemplateName}-${namespace}/_rollover`, + }, + { meta: true } + ); + const resLogsDatastream = await es.transport.request( + { + method: 'GET', + path: `/_data_stream/${logsTemplateName}-${namespace}`, + }, + { meta: true } + ); expect(resLogsDatastream.body.data_streams[0].indices.length).equal(2); }); await installPackage(pkgUpdateKey); diff --git a/x-pack/test/fleet_api_integration/apis/epm/final_pipeline.ts b/x-pack/test/fleet_api_integration/apis/epm/final_pipeline.ts index 8c6603a3e38b0..85ebf346aa202 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/final_pipeline.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/final_pipeline.ts @@ -75,7 +75,7 @@ export default function (providerContext: FtrProviderContext) { index: TEST_INDEX, }); - for (const hit of res.body.hits.hits) { + for (const hit of res.hits.hits) { await es.delete({ id: hit._id, index: hit._index, @@ -100,16 +100,16 @@ export default function (providerContext: FtrProviderContext) { }); await supertest.post(`/api/fleet/setup`).set('kbn-xsrf', 'xxxx'); const pipelineRes = await es.ingest.getPipeline({ id: FINAL_PIPELINE_ID }); - expect(pipelineRes.body).to.have.property(FINAL_PIPELINE_ID); - expect(pipelineRes.body[FINAL_PIPELINE_ID].version).to.be(1); + expect(pipelineRes).to.have.property(FINAL_PIPELINE_ID); + expect(pipelineRes[FINAL_PIPELINE_ID].version).to.be(1); }); it('should correctly setup the final pipeline and apply to fleet managed index template', async () => { const pipelineRes = await es.ingest.getPipeline({ id: FINAL_PIPELINE_ID }); - expect(pipelineRes.body).to.have.property(FINAL_PIPELINE_ID); + expect(pipelineRes).to.have.property(FINAL_PIPELINE_ID); const res = await es.indices.getIndexTemplate({ name: 'logs-log.log' }); - expect(res.body.index_templates.length).to.be(FINAL_PIPELINE_VERSION); - expect(res.body.index_templates[0]?.index_template?.composed_of).to.contain( + expect(res.index_templates.length).to.be(FINAL_PIPELINE_VERSION); + expect(res.index_templates[0]?.index_template?.composed_of).to.contain( '.fleet_component_template-1' ); }); @@ -123,9 +123,9 @@ export default function (providerContext: FtrProviderContext) { }, }); - const { body: doc } = await es.get({ - id: res.body._id, - index: res.body._index, + const doc = await es.get({ + id: res._id, + index: res._index, }); // @ts-expect-error const ingestTimestamp = doc._source.event.ingested; @@ -146,9 +146,9 @@ export default function (providerContext: FtrProviderContext) { }, }); - const { body: doc } = await es.get({ - id: res.body._id, - index: res.body._index, + const doc = await es.get({ + id: res._id, + index: res._index, }); // @ts-expect-error const event = doc._source.event; @@ -197,7 +197,7 @@ export default function (providerContext: FtrProviderContext) { for (const scenario of scenarios) { it(`Should write the correct event.agent_id_status for ${scenario.name}`, async () => { // Create an API key - const { body: apiKeyRes } = await es.security.createApiKey({ + const apiKeyRes = await es.security.createApiKey({ body: { name: `test api key`, ...(scenario.apiKey || {}), @@ -213,7 +213,7 @@ export default function (providerContext: FtrProviderContext) { Buffer.from(`${apiKeyRes.id}:${apiKeyRes.api_key}`).toString('base64') ); - const { body: doc } = await es.get({ + const doc = await es.get({ id: res.body._id as string, index: res.body._index as string, }); diff --git a/x-pack/test/fleet_api_integration/apis/epm/ilm.ts b/x-pack/test/fleet_api_integration/apis/epm/ilm.ts index 28a8bb11e6e1e..26d93598dd35a 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/ilm.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/ilm.ts @@ -28,11 +28,14 @@ export default function ({ getService }: FtrProviderContext) { }, }; - const data = await es.transport.request({ - method: 'PUT', - path: '/_ilm/policy/' + policyName, - body: policy, - }); + const data = await es.transport.request( + { + method: 'PUT', + path: '/_ilm/policy/' + policyName, + body: policy, + }, + { meta: true } + ); expect(data.body.acknowledged).to.eql(true); expect(data.statusCode).to.eql(200); diff --git a/x-pack/test/fleet_api_integration/apis/epm/install_endpoint.ts b/x-pack/test/fleet_api_integration/apis/epm/install_endpoint.ts index ba9264e1d1999..e3e0fda58e230 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/install_endpoint.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/install_endpoint.ts @@ -49,18 +49,24 @@ export default function (providerContext: FtrProviderContext) { describe('install', () => { transforms.forEach((transform) => { it(`should have installed the [${transform.id}] transform`, async function () { - const res = await es.transport.request({ - method: 'GET', - path: `/_transform/${transform.id}-${pkgVersion}`, - }); + const res = await es.transport.request( + { + method: 'GET', + path: `/_transform/${transform.id}-${pkgVersion}`, + }, + { meta: true } + ); expect(res.statusCode).equal(200); }); it(`should have created the destination index for the [${transform.id}] transform`, async function () { // the index is defined in the transform file - const res = await es.transport.request({ - method: 'GET', - path: `/${transform.dest}`, - }); + const res = await es.transport.request( + { + method: 'GET', + path: `/${transform.dest}`, + }, + { meta: true } + ); expect(res.statusCode).equal(200); }); }); @@ -82,9 +88,7 @@ export default function (providerContext: FtrProviderContext) { method: 'GET', path: `/_transform/${transform.id}`, }, - { - ignore: [404], - } + { meta: true, ignore: [404] } ); expect(res.statusCode).equal(404); }); @@ -97,6 +101,7 @@ export default function (providerContext: FtrProviderContext) { path: `/${transform.dest}`, }, { + meta: true, ignore: [404], } ); diff --git a/x-pack/test/fleet_api_integration/apis/epm/install_overrides.ts b/x-pack/test/fleet_api_integration/apis/epm/install_overrides.ts index 02820f85e8ee5..9e8bab3854b54 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/install_overrides.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/install_overrides.ts @@ -40,10 +40,13 @@ export default function (providerContext: FtrProviderContext) { const templateName = body.response[0].id; - const { body: indexTemplateResponse } = await es.transport.request({ - method: 'GET', - path: `/_index_template/${templateName}`, - }); + const { body: indexTemplateResponse } = await es.transport.request( + { + method: 'GET', + path: `/_index_template/${templateName}`, + }, + { meta: true } + ); // the index template composed_of has the correct component templates in the correct order const indexTemplate = indexTemplateResponse.index_templates[0].index_template; @@ -54,28 +57,37 @@ export default function (providerContext: FtrProviderContext) { '.fleet_component_template-1', ]); - ({ body } = await es.transport.request({ - method: 'GET', - path: `/_component_template/${templateName}@mappings`, - })); + ({ body } = await es.transport.request( + { + method: 'GET', + path: `/_component_template/${templateName}@mappings`, + }, + { meta: true } + )); // The mappings override provided in the package is set in the mappings component template expect(body.component_templates[0].component_template.template.mappings.dynamic).to.be(false); - ({ body } = await es.transport.request({ - method: 'GET', - path: `/_component_template/${templateName}@settings`, - })); + ({ body } = await es.transport.request( + { + method: 'GET', + path: `/_component_template/${templateName}@settings`, + }, + { meta: true } + )); // The settings override provided in the package is set in the settings component template expect( body.component_templates[0].component_template.template.settings.index.lifecycle.name ).to.be('reference'); - ({ body } = await es.transport.request({ - method: 'GET', - path: `/_component_template/${templateName}@custom`, - })); + ({ body } = await es.transport.request( + { + method: 'GET', + path: `/_component_template/${templateName}@custom`, + }, + { meta: true } + )); // The user_settings component template is an empty/stub template at first const storedTemplate = body.component_templates[0].component_template.template.settings; @@ -99,19 +111,22 @@ export default function (providerContext: FtrProviderContext) { })); // simulate the result - ({ body } = await es.transport.request({ - method: 'POST', - path: `/_index_template/_simulate/${templateName}`, - // body: indexTemplate, // I *think* this should work, but it doesn't - body: { - index_patterns: [`${templateName}-*`], - composed_of: [ - `${templateName}@mappings`, - `${templateName}@settings`, - `${templateName}@custom`, - ], + ({ body } = await es.transport.request( + { + method: 'POST', + path: `/_index_template/_simulate/${templateName}`, + // body: indexTemplate, // I *think* this should work, but it doesn't + body: { + index_patterns: [`${templateName}-*`], + composed_of: [ + `${templateName}@mappings`, + `${templateName}@settings`, + `${templateName}@custom`, + ], + }, }, - })); + { meta: true } + )); expect(body).to.eql({ template: { diff --git a/x-pack/test/fleet_api_integration/apis/epm/install_remove_assets.ts b/x-pack/test/fleet_api_integration/apis/epm/install_remove_assets.ts index 3fac1ce0aa59e..699b60a14b911 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/install_remove_assets.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/install_remove_assets.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import type { Client } from '@elastic/elasticsearch'; import expect from '@kbn/expect'; import { sortBy } from 'lodash'; import { AssetReference } from '../../../../plugins/fleet/common'; @@ -18,7 +18,7 @@ export default function (providerContext: FtrProviderContext) { const supertest = getService('supertest'); const dockerServers = getService('dockerServers'); const server = dockerServers.get('registry'); - const es = getService('es'); + const es: Client = getService('es'); const pkgName = 'all_assets'; const pkgVersion = '0.1.0'; const pkgKey = `${pkgName}-${pkgVersion}`; @@ -74,6 +74,7 @@ export default function (providerContext: FtrProviderContext) { }, { ignore: [404], + meta: true, } ); expect(resLogsTemplate.statusCode).equal(404); @@ -85,6 +86,7 @@ export default function (providerContext: FtrProviderContext) { }, { ignore: [404], + meta: true, } ); expect(resMetricsTemplate.statusCode).equal(404); @@ -97,6 +99,7 @@ export default function (providerContext: FtrProviderContext) { }, { ignore: [404], + meta: true, } ); expect(resMappings.statusCode).equal(404); @@ -108,6 +111,7 @@ export default function (providerContext: FtrProviderContext) { }, { ignore: [404], + meta: true, } ); expect(resSettings.statusCode).equal(404); @@ -119,6 +123,7 @@ export default function (providerContext: FtrProviderContext) { }, { ignore: [404], + meta: true, } ); expect(resUserSettings.statusCode).equal(404); @@ -131,6 +136,7 @@ export default function (providerContext: FtrProviderContext) { }, { ignore: [404], + meta: true, } ); expect(res.statusCode).equal(404); @@ -141,6 +147,7 @@ export default function (providerContext: FtrProviderContext) { }, { ignore: [404], + meta: true, } ); expect(resPipeline1.statusCode).equal(404); @@ -151,6 +158,7 @@ export default function (providerContext: FtrProviderContext) { }, { ignore: [404], + meta: true, } ); expect(resPipeline2.statusCode).equal(404); @@ -163,6 +171,7 @@ export default function (providerContext: FtrProviderContext) { }, { ignore: [404], + meta: true, } ); expect(res.statusCode).equal(404); @@ -175,6 +184,7 @@ export default function (providerContext: FtrProviderContext) { }, { ignore: [404], + meta: true, } ); expect(res.statusCode).equal(404); @@ -188,6 +198,7 @@ export default function (providerContext: FtrProviderContext) { }, { ignore: [404], + meta: true, } ); expect(res.statusCode).equal(404); @@ -335,68 +346,98 @@ const expectAssetsInstalled = ({ metricsTemplateName: string; pkgVersion: string; pkgName: string; - es: any; + es: Client; kibanaServer: any; }) => { it('should have installed the ILM policy', async function () { - const resPolicy = await es.transport.request({ - method: 'GET', - path: `/_ilm/policy/all_assets`, - }); + const resPolicy = await es.transport.request( + { + method: 'GET', + path: `/_ilm/policy/all_assets`, + }, + { meta: true } + ); expect(resPolicy.statusCode).equal(200); }); it('should have installed the index templates', async function () { - const resLogsTemplate = await es.transport.request({ - method: 'GET', - path: `/_index_template/${logsTemplateName}`, - }); + const resLogsTemplate = await es.transport.request( + { + method: 'GET', + path: `/_index_template/${logsTemplateName}`, + }, + { meta: true } + ); expect(resLogsTemplate.statusCode).equal(200); - const resMetricsTemplate = await es.transport.request({ - method: 'GET', - path: `/_index_template/${metricsTemplateName}`, - }); + const resMetricsTemplate = await es.transport.request( + { + method: 'GET', + path: `/_index_template/${metricsTemplateName}`, + }, + { meta: true } + ); expect(resMetricsTemplate.statusCode).equal(200); }); it('should have installed the pipelines', async function () { - const res = await es.transport.request({ - method: 'GET', - path: `/_ingest/pipeline/${logsTemplateName}-${pkgVersion}`, - }); + const res = await es.transport.request( + { + method: 'GET', + path: `/_ingest/pipeline/${logsTemplateName}-${pkgVersion}`, + }, + { meta: true } + ); expect(res.statusCode).equal(200); - const resPipeline1 = await es.transport.request({ - method: 'GET', - path: `/_ingest/pipeline/${logsTemplateName}-${pkgVersion}-pipeline1`, - }); + const resPipeline1 = await es.transport.request( + { + method: 'GET', + path: `/_ingest/pipeline/${logsTemplateName}-${pkgVersion}-pipeline1`, + }, + { meta: true } + ); expect(resPipeline1.statusCode).equal(200); - const resPipeline2 = await es.transport.request({ - method: 'GET', - path: `/_ingest/pipeline/${logsTemplateName}-${pkgVersion}-pipeline2`, - }); + const resPipeline2 = await es.transport.request( + { + method: 'GET', + path: `/_ingest/pipeline/${logsTemplateName}-${pkgVersion}-pipeline2`, + }, + { meta: true } + ); expect(resPipeline2.statusCode).equal(200); }); it('should have installed the ml model', async function () { - const res = await es.transport.request({ - method: 'GET', - path: `_ml/trained_models/default`, - }); + const res = await es.transport.request( + { + method: 'GET', + path: `_ml/trained_models/default`, + }, + { meta: true } + ); expect(res.statusCode).equal(200); }); it('should have installed the component templates', async function () { - const resMappings = await es.transport.request({ - method: 'GET', - path: `/_component_template/${logsTemplateName}@mappings`, - }); + const resMappings = await es.transport.request( + { + method: 'GET', + path: `/_component_template/${logsTemplateName}@mappings`, + }, + { meta: true } + ); expect(resMappings.statusCode).equal(200); - const resSettings = await es.transport.request({ - method: 'GET', - path: `/_component_template/${logsTemplateName}@settings`, - }); + const resSettings = await es.transport.request( + { + method: 'GET', + path: `/_component_template/${logsTemplateName}@settings`, + }, + { meta: true } + ); expect(resSettings.statusCode).equal(200); - const resUserSettings = await es.transport.request({ - method: 'GET', - path: `/_component_template/${logsTemplateName}@custom`, - }); + const resUserSettings = await es.transport.request( + { + method: 'GET', + path: `/_component_template/${logsTemplateName}@custom`, + }, + { meta: true } + ); expect(resUserSettings.statusCode).equal(200); }); it('should have installed the kibana assets', async function () { diff --git a/x-pack/test/fleet_api_integration/apis/epm/setup.ts b/x-pack/test/fleet_api_integration/apis/epm/setup.ts index 051636ad11f5a..ce967160f33e1 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/setup.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/setup.ts @@ -52,7 +52,7 @@ export default function (providerContext: FtrProviderContext) { it('allows elastic/fleet-server user to call required APIs', async () => { const { - body: { token }, + token, // @ts-expect-error SecurityCreateServiceTokenRequest should not require `name` } = await es.security.createServiceToken({ namespace: 'elastic', diff --git a/x-pack/test/fleet_api_integration/apis/epm/template.ts b/x-pack/test/fleet_api_integration/apis/epm/template.ts index 517d2c77d430d..6f29eb794e7d0 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/template.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/template.ts @@ -55,19 +55,25 @@ export default function ({ getService }: FtrProviderContext) { // This test is not an API integration test with Kibana // We want to test here if the template is valid and for this we need a running ES instance. // If the ES instance takes the template, we assume it is a valid template. - const { body: response1 } = await es.transport.request({ - method: 'PUT', - path: `/_index_template/${templateName}`, - body: template, - }); + const { body: response1 } = await es.transport.request( + { + method: 'PUT', + path: `/_index_template/${templateName}`, + body: template, + }, + { meta: true } + ); // Checks if template loading worked as expected expect(response1).to.eql({ acknowledged: true }); - const { body: response2 } = await es.transport.request({ - method: 'GET', - path: `/_index_template/${templateName}`, - }); + const { body: response2 } = await es.transport.request( + { + method: 'GET', + path: `/_index_template/${templateName}`, + }, + { meta: true } + ); // Checks if the content of the template that was loaded is as expected // We already know based on the above test that the template was valid diff --git a/x-pack/test/fleet_api_integration/apis/epm/update_assets.ts b/x-pack/test/fleet_api_integration/apis/epm/update_assets.ts index b5e24b6dc6358..4ae42ce179219 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/update_assets.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/update_assets.ts @@ -46,10 +46,12 @@ export default function (providerContext: FtrProviderContext) { await uninstallPackage(pkgUpdateKey); }); it('should have updated the ILM policy', async function () { - const resPolicy = await es.transport.request({ - method: 'GET', - path: `/_ilm/policy/all_assets`, - }); + const resPolicy = await es.ilm.getLifecycle( + { + name: 'all_assets', + }, + { meta: true } + ); expect(resPolicy.body.all_assets.policy).eql({ phases: { hot: { @@ -65,10 +67,13 @@ export default function (providerContext: FtrProviderContext) { }); }); it('should have updated the index templates', async function () { - const resLogsTemplate = await es.transport.request({ - method: 'GET', - path: `/_index_template/${logsTemplateName}`, - }); + const resLogsTemplate = await es.transport.request( + { + method: 'GET', + path: `/_index_template/${logsTemplateName}`, + }, + { meta: true } + ); expect(resLogsTemplate.statusCode).equal(200); expect( resLogsTemplate.body.index_templates[0].index_template.template.mappings.properties @@ -97,10 +102,13 @@ export default function (providerContext: FtrProviderContext) { }, }, }); - const resMetricsTemplate = await es.transport.request({ - method: 'GET', - path: `/_index_template/${metricsTemplateName}`, - }); + const resMetricsTemplate = await es.transport.request( + { + method: 'GET', + path: `/_index_template/${metricsTemplateName}`, + }, + { meta: true } + ); expect(resMetricsTemplate.statusCode).equal(200); expect( resMetricsTemplate.body.index_templates[0].index_template.template.mappings.properties @@ -128,10 +136,13 @@ export default function (providerContext: FtrProviderContext) { }); }); it('should have installed the new index template', async function () { - const resLogsTemplate = await es.transport.request({ - method: 'GET', - path: `/_index_template/${logsTemplateName2}`, - }); + const resLogsTemplate = await es.transport.request( + { + method: 'GET', + path: `/_index_template/${logsTemplateName2}`, + }, + { meta: true } + ); expect(resLogsTemplate.statusCode).equal(200); expect( resLogsTemplate.body.index_templates[0].index_template.template.mappings.properties @@ -159,62 +170,72 @@ export default function (providerContext: FtrProviderContext) { }); }); it('should have installed the new versionized pipelines', async function () { - const res = await es.transport.request({ - method: 'GET', - path: `/_ingest/pipeline/${logsTemplateName}-${pkgUpdateVersion}`, - }); + const res = await es.ingest.getPipeline( + { + id: `${logsTemplateName}-${pkgUpdateVersion}`, + }, + { meta: true } + ); expect(res.statusCode).equal(200); - const resPipeline1 = await es.transport.request({ - method: 'GET', - path: `/_ingest/pipeline/${logsTemplateName}-${pkgUpdateVersion}-pipeline1`, - }); + const resPipeline1 = await es.ingest.getPipeline( + { + id: `${logsTemplateName}-${pkgUpdateVersion}-pipeline1`, + }, + { meta: true } + ); expect(resPipeline1.statusCode).equal(200); }); it('should have removed the old versionized pipelines', async function () { - const res = await es.transport.request( + const res = await es.ingest.getPipeline( { - method: 'GET', - path: `/_ingest/pipeline/${logsTemplateName}-${pkgVersion}`, + id: `${logsTemplateName}-${pkgVersion}`, }, { ignore: [404], + meta: true, } ); expect(res.statusCode).equal(404); - const resPipeline1 = await es.transport.request( + const resPipeline1 = await es.ingest.getPipeline( { - method: 'GET', - path: `/_ingest/pipeline/${logsTemplateName}-${pkgVersion}-pipeline1`, + id: `${logsTemplateName}-${pkgVersion}-pipeline1`, }, { ignore: [404], + meta: true, } ); expect(resPipeline1.statusCode).equal(404); - const resPipeline2 = await es.transport.request( + const resPipeline2 = await es.ingest.getPipeline( { - method: 'GET', - path: `/_ingest/pipeline/${logsTemplateName}-${pkgVersion}-pipeline2`, + id: `${logsTemplateName}-${pkgVersion}-pipeline2`, }, { ignore: [404], + meta: true, } ); expect(resPipeline2.statusCode).equal(404); }); it('should have updated the component templates', async function () { - const resMappings = await es.transport.request({ - method: 'GET', - path: `/_component_template/${logsTemplateName}@mappings`, - }); + const resMappings = await es.transport.request( + { + method: 'GET', + path: `/_component_template/${logsTemplateName}@mappings`, + }, + { meta: true } + ); expect(resMappings.statusCode).equal(200); expect(resMappings.body.component_templates[0].component_template.template.mappings).eql({ dynamic: true, }); - const resSettings = await es.transport.request({ - method: 'GET', - path: `/_component_template/${logsTemplateName}@settings`, - }); + const resSettings = await es.transport.request( + { + method: 'GET', + path: `/_component_template/${logsTemplateName}@settings`, + }, + { meta: true } + ); expect(resSettings.statusCode).equal(200); expect(resSettings.body.component_templates[0].component_template.template.settings).eql({ index: { @@ -230,10 +251,13 @@ export default function (providerContext: FtrProviderContext) { }, }, }); - const resUserSettings = await es.transport.request({ - method: 'GET', - path: `/_component_template/${logsTemplateName}@custom`, - }); + const resUserSettings = await es.transport.request( + { + method: 'GET', + path: `/_component_template/${logsTemplateName}@custom`, + }, + { meta: true } + ); expect(resUserSettings.statusCode).equal(200); expect(resUserSettings.body).eql({ component_templates: [ diff --git a/x-pack/test/fleet_api_integration/apis/service_tokens.ts b/x-pack/test/fleet_api_integration/apis/service_tokens.ts index 0399778b2e13c..4d5487841782c 100644 --- a/x-pack/test/fleet_api_integration/apis/service_tokens.ts +++ b/x-pack/test/fleet_api_integration/apis/service_tokens.ts @@ -33,10 +33,13 @@ export default function (providerContext: FtrProviderContext) { expect(apiResponse).have.property('name'); expect(apiResponse).have.property('value'); - const { body: tokensResponse } = await esClient.transport.request({ - method: 'GET', - path: `_security/service/elastic/fleet-server/credential`, - }); + const { body: tokensResponse } = await esClient.transport.request( + { + method: 'GET', + path: `_security/service/elastic/fleet-server/credential`, + }, + { meta: true } + ); expect(tokensResponse.tokens).have.property(apiResponse.name); }); diff --git a/x-pack/test/fleet_api_integration/apis/settings/update.ts b/x-pack/test/fleet_api_integration/apis/settings/update.ts index 1db0fc7e39441..566eeb156d243 100644 --- a/x-pack/test/fleet_api_integration/apis/settings/update.ts +++ b/x-pack/test/fleet_api_integration/apis/settings/update.ts @@ -130,7 +130,7 @@ export default function (providerContext: FtrProviderContext) { }, }); - expect(res.body.hits.hits.length).equal(beforeRes.body.hits.hits.length + 1); + expect(res.hits.hits.length).equal(beforeRes.hits.hits.length + 1); }); }); } diff --git a/x-pack/test/functional/apps/index_lifecycle_management/home_page.ts b/x-pack/test/functional/apps/index_lifecycle_management/home_page.ts index e2540d80280c2..f7510c3c30318 100644 --- a/x-pack/test/functional/apps/index_lifecycle_management/home_page.ts +++ b/x-pack/test/functional/apps/index_lifecycle_management/home_page.ts @@ -22,8 +22,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await pageObjects.common.navigateToApp('indexLifecycleManagement'); }); after(async () => { - // @ts-expect-error @elastic/elasticsearch DeleteSnapshotLifecycleRequest.policy_id is required - await esClient.ilm.deleteLifecycle({ policy: policyName }); + await esClient.ilm.deleteLifecycle({ name: policyName }); }); it('Loads the app', async () => { diff --git a/x-pack/test/functional/apps/rollup_job/hybrid_index_pattern.js b/x-pack/test/functional/apps/rollup_job/hybrid_index_pattern.js index 4fe957dac7b6d..336a575454e72 100644 --- a/x-pack/test/functional/apps/rollup_job/hybrid_index_pattern.js +++ b/x-pack/test/functional/apps/rollup_job/hybrid_index_pattern.js @@ -57,7 +57,7 @@ export default function ({ getService, getPageObjects }) { 'waiting for 3 records to be loaded into elasticsearch.', 10000, async () => { - const { body: response } = await es.indices.get({ + const response = await es.indices.get({ index: `${rollupSourceIndexPrefix}*`, allow_no_indices: false, }); diff --git a/x-pack/test/functional/apps/snapshot_restore/home_page.ts b/x-pack/test/functional/apps/snapshot_restore/home_page.ts index b72656a96980f..b2893ace7b20a 100644 --- a/x-pack/test/functional/apps/snapshot_restore/home_page.ts +++ b/x-pack/test/functional/apps/snapshot_restore/home_page.ts @@ -31,7 +31,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { describe('Repositories Tab', async () => { before(async () => { await es.snapshot.createRepository({ - repository: 'my-repository', + name: 'my-repository', body: { type: 'fs', settings: { @@ -55,7 +55,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }); after(async () => { await es.snapshot.deleteRepository({ - repository: 'my-repository', + name: 'my-repository', }); }); }); diff --git a/x-pack/test/functional/apps/watcher/index.js b/x-pack/test/functional/apps/watcher/index.js index 49fcdf65fcdcd..db5f52d2121e8 100644 --- a/x-pack/test/functional/apps/watcher/index.js +++ b/x-pack/test/functional/apps/watcher/index.js @@ -9,7 +9,6 @@ export default function ({ loadTestFile }) { describe('watcher app', function () { this.tags(['ciGroup1', 'includeFirefox']); - //loadTestFile(require.resolve('./management')); loadTestFile(require.resolve('./watcher_test')); }); } diff --git a/x-pack/test/functional/services/ml/api.ts b/x-pack/test/functional/services/ml/api.ts index 6ffd95f213c41..a9a44f58a84df 100644 --- a/x-pack/test/functional/services/ml/api.ts +++ b/x-pack/test/functional/services/ml/api.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import expect from '@kbn/expect'; import { ProvidedType } from '@kbn/test'; import fs from 'fs'; @@ -39,7 +39,7 @@ export function MachineLearningAPIProvider({ getService }: FtrProviderContext) { return { async hasJobResults(jobId: string): Promise { - const { body } = await es.search({ + const body = await es.search({ index: '.ml-anomalies-*', body: { size: 1, @@ -79,7 +79,7 @@ export function MachineLearningAPIProvider({ getService }: FtrProviderContext) { }, async hasDetectorResults(jobId: string, detectorIndex: number): Promise { - const { body } = await es.search({ + const body = await es.search({ index: '.ml-anomalies-*', body: { size: 1, @@ -131,12 +131,12 @@ export function MachineLearningAPIProvider({ getService }: FtrProviderContext) { mappings?: Record | estypes.MappingTypeMapping ) { log.debug(`Creating indices: '${indices}'...`); - if ((await es.indices.exists({ index: indices, allow_no_indices: false })).body === true) { + if ((await es.indices.exists({ index: indices, allow_no_indices: false })) === true) { log.debug(`Indices '${indices}' already exist. Nothing to create.`); return; } - const { body } = await es.indices.create({ + const body = await es.indices.create({ index: indices, ...(mappings ? { body: { mappings } } : {}), }); @@ -150,12 +150,12 @@ export function MachineLearningAPIProvider({ getService }: FtrProviderContext) { async deleteIndices(indices: string) { log.debug(`Deleting indices: '${indices}'...`); - if ((await es.indices.exists({ index: indices, allow_no_indices: false })).body === false) { + if ((await es.indices.exists({ index: indices, allow_no_indices: false })) === false) { log.debug(`Indices '${indices}' don't exist. Nothing to delete.`); return; } - const { body } = await es.indices.delete({ + const body = await es.indices.delete({ index: indices, }); expect(body) @@ -321,7 +321,7 @@ export function MachineLearningAPIProvider({ getService }: FtrProviderContext) { async assertIndicesExist(indices: string) { await retry.tryForTime(30 * 1000, async () => { - if ((await es.indices.exists({ index: indices, allow_no_indices: false })).body === true) { + if ((await es.indices.exists({ index: indices, allow_no_indices: false })) === true) { return true; } else { throw new Error(`indices '${indices}' should exist`); @@ -331,7 +331,7 @@ export function MachineLearningAPIProvider({ getService }: FtrProviderContext) { async assertIndicesNotToExist(indices: string) { await retry.tryForTime(30 * 1000, async () => { - if ((await es.indices.exists({ index: indices, allow_no_indices: false })).body === false) { + if ((await es.indices.exists({ index: indices, allow_no_indices: false })) === false) { return true; } else { throw new Error(`indices '${indices}' should not exist`); @@ -341,7 +341,7 @@ export function MachineLearningAPIProvider({ getService }: FtrProviderContext) { async assertIndicesNotEmpty(indices: string) { await retry.tryForTime(30 * 1000, async () => { - const { body } = await es.search({ + const body = await es.search({ index: indices, body: { size: 1, @@ -848,7 +848,7 @@ export function MachineLearningAPIProvider({ getService }: FtrProviderContext) { async getAnnotations(jobId: string) { log.debug(`Fetching annotations for job '${jobId}'...`); - const { body } = await es.search({ + const body = await es.search({ index: ML_ANNOTATIONS_INDEX_ALIAS_READ, body: { query: { @@ -867,7 +867,7 @@ export function MachineLearningAPIProvider({ getService }: FtrProviderContext) { async getAnnotationById(annotationId: string): Promise { log.debug(`Fetching annotation '${annotationId}'...`); - const { body } = await es.search({ + const body = await es.search({ index: ML_ANNOTATIONS_INDEX_ALIAS_READ, body: { size: 1, @@ -896,7 +896,7 @@ export function MachineLearningAPIProvider({ getService }: FtrProviderContext) { body: annotationRequestBody, refresh: 'wait_for', } as const; - const { body } = await es.index(params); + const body = await es.index(params); await this.waitForAnnotationToExist(body._id); log.debug(`> Annotation ${body._id} indexed.`); return body; diff --git a/x-pack/test/functional/services/transform/api.ts b/x-pack/test/functional/services/transform/api.ts index 73dff415832f6..e30146e5bdd69 100644 --- a/x-pack/test/functional/services/transform/api.ts +++ b/x-pack/test/functional/services/transform/api.ts @@ -32,12 +32,12 @@ export function TransformAPIProvider({ getService }: FtrProviderContext) { return { async createIndices(indices: string) { log.debug(`Creating indices: '${indices}'...`); - if ((await es.indices.exists({ index: indices, allow_no_indices: false })).body === true) { + if ((await es.indices.exists({ index: indices, allow_no_indices: false })) === true) { log.debug(`Indices '${indices}' already exist. Nothing to create.`); return; } - const createResponse = (await es.indices.create({ index: indices })).body; + const createResponse = await es.indices.create({ index: indices }); expect(createResponse) .to.have.property('acknowledged') .eql(true, 'Response for create request indices should be acknowledged.'); @@ -47,16 +47,14 @@ export function TransformAPIProvider({ getService }: FtrProviderContext) { async deleteIndices(indices: string, skipWaitForIndicesNotToExist?: boolean) { log.debug(`Deleting indices: '${indices}'...`); - if ((await es.indices.exists({ index: indices, allow_no_indices: false })).body === false) { + if ((await es.indices.exists({ index: indices, allow_no_indices: false })) === false) { log.debug(`Indices '${indices}' don't exist. Nothing to delete.`); return; } - const deleteResponse = ( - await es.indices.delete({ - index: indices, - }) - ).body; + const deleteResponse = await es.indices.delete({ + index: indices, + }); expect(deleteResponse) .to.have.property('acknowledged') .eql(true, 'Response for delete request should be acknowledged'); @@ -72,7 +70,7 @@ export function TransformAPIProvider({ getService }: FtrProviderContext) { async waitForIndicesToExist(indices: string, errorMsg?: string) { await retry.tryForTime(30 * 1000, async () => { - if ((await es.indices.exists({ index: indices, allow_no_indices: false })).body === true) { + if ((await es.indices.exists({ index: indices, allow_no_indices: false })) === true) { return true; } else { throw new Error(errorMsg || `indices '${indices}' should exist`); @@ -82,7 +80,7 @@ export function TransformAPIProvider({ getService }: FtrProviderContext) { async waitForIndicesNotToExist(indices: string, errorMsg?: string) { await retry.tryForTime(30 * 1000, async () => { - if ((await es.indices.exists({ index: indices, allow_no_indices: false })).body === false) { + if ((await es.indices.exists({ index: indices, allow_no_indices: false })) === false) { return true; } else { throw new Error(errorMsg || `indices '${indices}' should not exist`); diff --git a/x-pack/test/functional_with_es_ssl/apps/ml/alert_flyout.ts b/x-pack/test/functional_with_es_ssl/apps/ml/alert_flyout.ts index b97562fe07bfc..cfcfbb021b52a 100644 --- a/x-pack/test/functional_with_es_ssl/apps/ml/alert_flyout.ts +++ b/x-pack/test/functional_with_es_ssl/apps/ml/alert_flyout.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { FtrProviderContext } from '../../ftr_provider_context'; import { DATAFEED_STATE } from '../../../../plugins/ml/common/constants/states'; diff --git a/x-pack/test/observability_api_integration/trial/tests/annotations.ts b/x-pack/test/observability_api_integration/trial/tests/annotations.ts index 48b16b712bf3a..be4e98f9937d0 100644 --- a/x-pack/test/observability_api_integration/trial/tests/annotations.ts +++ b/x-pack/test/observability_api_integration/trial/tests/annotations.ts @@ -36,7 +36,7 @@ export default function annotationApiTests({ getService }: FtrProviderContext) { describe('Observability annotations', () => { describe('when creating an annotation', () => { afterEach(async () => { - const indexExists = (await es.indices.exists({ index: DEFAULT_INDEX_NAME })).body; + const indexExists = await es.indices.exists({ index: DEFAULT_INDEX_NAME }); if (indexExists) { await es.indices.delete({ index: DEFAULT_INDEX_NAME, @@ -153,10 +153,10 @@ export default function annotationApiTests({ getService }: FtrProviderContext) { }); // @ts-expect-error doesn't handle number - expect(search.body.hits.total.value).to.be(1); + expect(search.hits.total.value).to.be(1); - expect(search.body.hits.hits[0]._source).to.eql(response.body._source); - expect(search.body.hits.hits[0]._id).to.eql(response.body._id); + expect(search.hits.hits[0]._source).to.eql(response.body._source); + expect(search.hits.hits[0]._id).to.eql(response.body._id); }); it('returns the annotation', async () => { @@ -242,9 +242,9 @@ export default function annotationApiTests({ getService }: FtrProviderContext) { }); // @ts-expect-error doesn't handler number - expect(initialSearch.body.hits.total.value).to.be(2); + expect(initialSearch.hits.total.value).to.be(2); - const [id1, id2] = initialSearch.body.hits.hits.map((hit) => hit._id); + const [id1, id2] = initialSearch.hits.hits.map((hit) => hit._id); expect( ( @@ -261,9 +261,9 @@ export default function annotationApiTests({ getService }: FtrProviderContext) { }); // @ts-expect-error doesn't handler number - expect(searchAfterFirstDelete.body.hits.total.value).to.be(1); + expect(searchAfterFirstDelete.hits.total.value).to.be(1); - expect(searchAfterFirstDelete.body.hits.hits[0]._id).to.be(id2); + expect(searchAfterFirstDelete.hits.hits[0]._id).to.be(id2); expect( ( @@ -280,7 +280,7 @@ export default function annotationApiTests({ getService }: FtrProviderContext) { }); // @ts-expect-error doesn't handle number - expect(searchAfterSecondDelete.body.hits.total.value).to.be(0); + expect(searchAfterSecondDelete.hits.total.value).to.be(0); }); }); }); diff --git a/x-pack/test/performance/tests/reporting_dashboard.ts b/x-pack/test/performance/tests/reporting_dashboard.ts index f363f8449df96..9d285b1cf7f44 100644 --- a/x-pack/test/performance/tests/reporting_dashboard.ts +++ b/x-pack/test/performance/tests/reporting_dashboard.ts @@ -16,7 +16,8 @@ export default function ({ getService, getPageObject }: FtrProviderContext) { const dashboard = getPageObject('dashboard'); const reporting = getPageObject('reporting'); - describe('reporting dashbaord', () => { + // TODO: unskip when https://github.com/elastic/kibana/issues/116109 is fixed + describe.skip('reporting dashbaord', () => { before(async () => { await kibanaServer.importExport.load( 'x-pack/test/performance/kbn_archives/reporting_dashboard' diff --git a/x-pack/test/plugin_api_integration/test_suites/event_log/service_api_integration.ts b/x-pack/test/plugin_api_integration/test_suites/event_log/service_api_integration.ts index fe734a764d2f3..267df365427a0 100644 --- a/x-pack/test/plugin_api_integration/test_suites/event_log/service_api_integration.ts +++ b/x-pack/test/plugin_api_integration/test_suites/event_log/service_api_integration.ts @@ -33,7 +33,7 @@ export default function ({ getService }: FtrProviderContext) { .find((val: string) => val === '--xpack.eventLog.indexEntries=true'); const result = await isIndexingEntries(); const exists = await es.indices.exists({ index: '.kibana-event-log-*' }); - expect(exists.body).to.be.eql(true); + expect(exists).to.be.eql(true); expect(configValue).to.be.eql( `--xpack.eventLog.indexEntries=${result.body.isIndexingEntries}` ); diff --git a/x-pack/test/plugin_api_integration/test_suites/task_manager/migrations.ts b/x-pack/test/plugin_api_integration/test_suites/task_manager/migrations.ts index caf62a1d364c0..329aee7e74b98 100644 --- a/x-pack/test/plugin_api_integration/test_suites/task_manager/migrations.ts +++ b/x-pack/test/plugin_api_integration/test_suites/task_manager/migrations.ts @@ -6,7 +6,8 @@ */ import expect from '@kbn/expect'; -import type { ApiResponse, estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import type { TransportResult } from '@elastic/elasticsearch'; import { TaskInstanceWithDeprecatedFields } from '../../../../plugins/task_manager/server/task'; import { FtrProviderContext } from '../../../common/ftr_provider_context'; import { SavedObjectsUtils } from '../../../../../src/core/server/saved_objects'; @@ -28,10 +29,15 @@ export default function createGetTests({ getService }: FtrProviderContext) { it('8.0.0 migrates actions tasks with legacy id to saved object ids', async () => { // NOTE: We hae to use elastic search directly against the ".kibana" index because alerts do not expose the references which we want to test exists - const response = await es.get<{ task: TaskInstanceWithDeprecatedFields }>({ - index: '.kibana_task_manager', - id: 'task:be7e1250-3322-11eb-94c1-db6995e84f6a', - }); + const response = await es.get<{ task: TaskInstanceWithDeprecatedFields }>( + { + index: '.kibana_task_manager', + id: 'task:be7e1250-3322-11eb-94c1-db6995e84f6a', + }, + { + meta: true, + } + ); expect(response.statusCode).to.eql(200); expect(response.body._source?.task.params).to.eql( `{"spaceId":"user1","alertId":"${SavedObjectsUtils.getConvertedObjectId( @@ -43,18 +49,22 @@ export default function createGetTests({ getService }: FtrProviderContext) { }); it('8.0.0 migrates actions tasks from legacy id to saved object ids', async () => { - const searchResult: ApiResponse< - estypes.SearchResponse<{ task: TaskInstanceWithDeprecatedFields }> - > = await es.search({ - index: '.kibana_task_manager', - body: { - query: { - term: { - _id: 'task:be7e1250-3322-11eb-94c1-db6995e8389f', + const searchResult: TransportResult< + estypes.SearchResponse<{ task: TaskInstanceWithDeprecatedFields }>, + unknown + > = await es.search( + { + index: '.kibana_task_manager', + body: { + query: { + term: { + _id: 'task:be7e1250-3322-11eb-94c1-db6995e8389f', + }, }, }, }, - }); + { meta: true } + ); expect(searchResult.statusCode).to.equal(200); expect((searchResult.body.hits.total as estypes.SearchTotalHits).value).to.equal(1); const hit = searchResult.body.hits.hits[0]; diff --git a/x-pack/test/plugin_api_integration/test_suites/task_manager/task_management.ts b/x-pack/test/plugin_api_integration/test_suites/task_manager/task_management.ts index eb2b4cb1f6f49..cc7b3ceb542d6 100644 --- a/x-pack/test/plugin_api_integration/test_suites/task_manager/task_management.ts +++ b/x-pack/test/plugin_api_integration/test_suites/task_manager/task_management.ts @@ -7,7 +7,7 @@ import { random, times } from 'lodash'; import expect from '@kbn/expect'; -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { FtrProviderContext } from '../../ftr_provider_context'; import TaskManagerMapping from '../../../../plugins/task_manager/server/saved_objects/mappings.json'; import { @@ -64,7 +64,7 @@ export default function ({ getService }: FtrProviderContext) { beforeEach(async () => { const exists = await es.indices.exists({ index: testHistoryIndex }); - if (exists.body) { + if (exists) { await es.deleteByQuery({ index: testHistoryIndex, refresh: true, @@ -151,7 +151,7 @@ export default function ({ getService }: FtrProviderContext) { }, }) .then((result) => - (result.body as unknown as SearchResults).hits.hits.filter((task) => + (result as unknown as SearchResults).hits.hits.filter((task) => taskId ? task._source?.taskId === taskId : true ) ); diff --git a/x-pack/test/reporting_api_integration/reporting_and_security/ilm_migration_apis.ts b/x-pack/test/reporting_api_integration/reporting_and_security/ilm_migration_apis.ts index fd49e2b237217..d1dc091992dd6 100644 --- a/x-pack/test/reporting_api_integration/reporting_and_security/ilm_migration_apis.ts +++ b/x-pack/test/reporting_api_integration/reporting_and_security/ilm_migration_apis.ts @@ -50,8 +50,7 @@ export default function ({ getService }: FtrProviderContext) { it('detects when reporting indices should be migrated due to missing ILM policy', async () => { await reportingAPI.makeAllReportingIndicesUnmanaged(); - // TODO: Remove "any" when no longer through type issue "policy_id" missing - await es.ilm.deleteLifecycle({ policy: ILM_POLICY_NAME } as any); + await es.ilm.deleteLifecycle({ name: ILM_POLICY_NAME }); await supertest .post(`/api/reporting/generate/csv`) @@ -99,17 +98,15 @@ export default function ({ getService }: FtrProviderContext) { // customize the lifecycle policy await es.ilm.putLifecycle({ - policy: ILM_POLICY_NAME, + name: ILM_POLICY_NAME, body: customLifecycle, }); await reportingAPI.migrateReportingIndices(); const { - body: { - [ILM_POLICY_NAME]: { policy }, - }, - } = await es.ilm.getLifecycle({ policy: ILM_POLICY_NAME }); + [ILM_POLICY_NAME]: { policy }, + } = await es.ilm.getLifecycle({ name: ILM_POLICY_NAME }); expect(policy).to.eql(customLifecycle.policy); }); diff --git a/x-pack/test/saved_object_api_integration/common/lib/create_users_and_roles.ts b/x-pack/test/saved_object_api_integration/common/lib/create_users_and_roles.ts index 2ba5ce3f7d5b1..e0fed03efb94d 100644 --- a/x-pack/test/saved_object_api_integration/common/lib/create_users_and_roles.ts +++ b/x-pack/test/saved_object_api_integration/common/lib/create_users_and_roles.ts @@ -6,10 +6,10 @@ */ import type { SuperTest } from 'supertest'; -import type { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import type { Client } from '@elastic/elasticsearch'; import { AUTHENTICATION } from './authentication'; -export const createUsersAndRoles = async (es: KibanaClient, supertest: SuperTest) => { +export const createUsersAndRoles = async (es: Client, supertest: SuperTest) => { await supertest .put('/api/security/role/kibana_legacy_user') .send({ diff --git a/x-pack/test/saved_object_api_integration/common/lib/saved_object_test_utils.ts b/x-pack/test/saved_object_api_integration/common/lib/saved_object_test_utils.ts index ce2079ab8234a..a4c69ec5a2ab1 100644 --- a/x-pack/test/saved_object_api_integration/common/lib/saved_object_test_utils.ts +++ b/x-pack/test/saved_object_api_integration/common/lib/saved_object_test_utils.ts @@ -6,7 +6,7 @@ */ import expect from '@kbn/expect'; -import type { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import type { Client } from '@elastic/elasticsearch'; import { SavedObjectsErrorHelpers } from '../../../../../src/core/server'; import { SPACES, ALL_SPACES_ID } from './spaces'; import { AUTHENTICATION } from './authentication'; @@ -182,11 +182,11 @@ export const expectResponses = { * Additional assertions that we use in `import` and `resolve_import_errors` to ensure that * newly-created (or overwritten) objects don't have unexpected properties */ - successCreated: async (es: KibanaClient, spaceId: string, type: string, id: string) => { + successCreated: async (es: Client, spaceId: string, type: string, id: string) => { const isNamespaceUndefined = spaceId === SPACES.DEFAULT.spaceId || isNamespaceAgnostic(type) || isMultiNamespace(type); const expectedSpacePrefix = isNamespaceUndefined ? '' : `${spaceId}:`; - const { body: savedObject } = await es.get>({ + const savedObject = await es.get>({ id: `${expectedSpacePrefix}${type}:${id}`, index: '.kibana', }); diff --git a/x-pack/test/saved_object_api_integration/common/suites/import.ts b/x-pack/test/saved_object_api_integration/common/suites/import.ts index 69b3b9925c651..04e0f3c41ed87 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/import.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/import.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import { SuperTest } from 'supertest'; -import type { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import type { Client } from '@elastic/elasticsearch'; import { SAVED_OBJECT_TEST_CASES as CASES } from '../lib/saved_object_test_cases'; import { SPACES } from '../lib/spaces'; import { expectResponses, getUrlPrefix, getTestTitle } from '../lib/saved_object_test_utils'; @@ -72,11 +72,7 @@ const getConflictDest = (id: string) => ({ updatedAt: '2017-09-21T18:59:16.270Z', }); -export function importTestSuiteFactory( - es: KibanaClient, - esArchiver: any, - supertest: SuperTest -) { +export function importTestSuiteFactory(es: Client, esArchiver: any, supertest: SuperTest) { const expectSavedObjectForbidden = expectResponses.forbiddenTypes('bulk_create'); const expectResponseBody = ( diff --git a/x-pack/test/saved_object_api_integration/common/suites/resolve_import_errors.ts b/x-pack/test/saved_object_api_integration/common/suites/resolve_import_errors.ts index dd1f04529db7b..6de4e6dfbdcfa 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/resolve_import_errors.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/resolve_import_errors.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import { SuperTest } from 'supertest'; -import type { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import type { Client } from '@elastic/elasticsearch'; import { SAVED_OBJECT_TEST_CASES as CASES } from '../lib/saved_object_test_cases'; import { SPACES } from '../lib/spaces'; import { expectResponses, getUrlPrefix, getTestTitle } from '../lib/saved_object_test_utils'; @@ -92,7 +92,7 @@ const createRequest = ( }); export function resolveImportErrorsTestSuiteFactory( - es: KibanaClient, + es: Client, esArchiver: any, supertest: SuperTest ) { diff --git a/x-pack/test/saved_objects_field_count/runner.ts b/x-pack/test/saved_objects_field_count/runner.ts index e590a0667296f..22c6fd5d4612f 100644 --- a/x-pack/test/saved_objects_field_count/runner.ts +++ b/x-pack/test/saved_objects_field_count/runner.ts @@ -37,9 +37,7 @@ export async function testRunner({ getService }: FtrProviderContext) { log.debug('Saved Objects field count metrics starting'); - const { - body: { fields }, - } = await es.fieldCaps({ + const { fields } = await es.fieldCaps({ index: '.kibana', fields: '*', }); diff --git a/x-pack/test/search_sessions_integration/tests/apps/dashboard/async_search/async_search.ts b/x-pack/test/search_sessions_integration/tests/apps/dashboard/async_search/async_search.ts index 3428071684900..eca329bd47439 100644 --- a/x-pack/test/search_sessions_integration/tests/apps/dashboard/async_search/async_search.ts +++ b/x-pack/test/search_sessions_integration/tests/apps/dashboard/async_search/async_search.ts @@ -25,7 +25,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { describe('dashboard with async search', () => { before(async function () { - const { body } = await es.info(); + const body = await es.info(); if (!body.version.number.includes('SNAPSHOT')) { log.debug('Skipping because this build does not have the required shard_delay agg'); this.skip(); diff --git a/x-pack/test/search_sessions_integration/tests/apps/dashboard/async_search/save_search_session.ts b/x-pack/test/search_sessions_integration/tests/apps/dashboard/async_search/save_search_session.ts index bab93ad0483d3..0fe3cb428880b 100644 --- a/x-pack/test/search_sessions_integration/tests/apps/dashboard/async_search/save_search_session.ts +++ b/x-pack/test/search_sessions_integration/tests/apps/dashboard/async_search/save_search_session.ts @@ -26,7 +26,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { describe('save a search sessions', () => { before(async function () { - const { body } = await es.info(); + const body = await es.info(); if (!body.version.number.includes('SNAPSHOT')) { log.debug('Skipping because this build does not have the required shard_delay agg'); this.skip(); diff --git a/x-pack/test/search_sessions_integration/tests/apps/dashboard/async_search/search_sessions_tour.ts b/x-pack/test/search_sessions_integration/tests/apps/dashboard/async_search/search_sessions_tour.ts index e12bd377288ba..86b7f41abf4eb 100644 --- a/x-pack/test/search_sessions_integration/tests/apps/dashboard/async_search/search_sessions_tour.ts +++ b/x-pack/test/search_sessions_integration/tests/apps/dashboard/async_search/search_sessions_tour.ts @@ -17,7 +17,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { describe('search sessions tour', () => { before(async function () { - const { body } = await es.info(); + const body = await es.info(); if (!body.version.number.includes('SNAPSHOT')) { log.debug('Skipping because this build does not have the required shard_delay agg'); this.skip(); diff --git a/x-pack/test/security_api_integration/tests/http_bearer/header.ts b/x-pack/test/security_api_integration/tests/http_bearer/header.ts index f7ebef4f16d09..7de7d83e154e2 100644 --- a/x-pack/test/security_api_integration/tests/http_bearer/header.ts +++ b/x-pack/test/security_api_integration/tests/http_bearer/header.ts @@ -14,9 +14,7 @@ export default function ({ getService }: FtrProviderContext) { const es = getService('es'); async function createToken() { - const { - body: { access_token: accessToken, authentication }, - } = await es.security.getToken({ + const { access_token: accessToken, authentication } = await es.security.getToken({ body: { grant_type: 'password', ...adminTestUser, diff --git a/x-pack/test/security_api_integration/tests/kerberos/kerberos_login.ts b/x-pack/test/security_api_integration/tests/kerberos/kerberos_login.ts index 5b21d63c8d888..ed1a1f3c16fcc 100644 --- a/x-pack/test/security_api_integration/tests/kerberos/kerberos_login.ts +++ b/x-pack/test/security_api_integration/tests/kerberos/kerberos_login.ts @@ -399,7 +399,7 @@ export default function ({ getService }: FtrProviderContext) { body: { query: { match: { doc_type: 'token' } } }, refresh: true, }); - expect(esResponse.body).to.have.property('deleted').greaterThan(0); + expect(esResponse).to.have.property('deleted').greaterThan(0); }); it('AJAX call should initiate SPNEGO and clear existing cookie', async function () { diff --git a/x-pack/test/security_api_integration/tests/oidc/authorization_code_flow/oidc_auth.ts b/x-pack/test/security_api_integration/tests/oidc/authorization_code_flow/oidc_auth.ts index 330133049f549..a7a8702894482 100644 --- a/x-pack/test/security_api_integration/tests/oidc/authorization_code_flow/oidc_auth.ts +++ b/x-pack/test/security_api_integration/tests/oidc/authorization_code_flow/oidc_auth.ts @@ -581,7 +581,7 @@ export default function ({ getService }: FtrProviderContext) { body: { query: { match: { doc_type: 'token' } } }, refresh: true, }); - expect(esResponse.body).to.have.property('deleted').greaterThan(0); + expect(esResponse).to.have.property('deleted').greaterThan(0); const handshakeResponse = await supertest .get( diff --git a/x-pack/test/security_api_integration/tests/saml/saml_login.ts b/x-pack/test/security_api_integration/tests/saml/saml_login.ts index d78a7b1040455..97fdcb77f4d66 100644 --- a/x-pack/test/security_api_integration/tests/saml/saml_login.ts +++ b/x-pack/test/security_api_integration/tests/saml/saml_login.ts @@ -568,7 +568,7 @@ export default function ({ getService }: FtrProviderContext) { body: { query: { match: { doc_type: 'token' } } }, refresh: true, }); - expect(esResponse.body).to.have.property('deleted').greaterThan(0); + expect(esResponse).to.have.property('deleted').greaterThan(0); }); it('should redirect user to a page that would capture URL fragment', async () => { @@ -650,7 +650,7 @@ export default function ({ getService }: FtrProviderContext) { body: { query: { match: { doc_type: 'token' } } }, refresh: true, }); - expect(esResponse.body).to.have.property('deleted').greaterThan(0); + expect(esResponse).to.have.property('deleted').greaterThan(0); }, ], ]; diff --git a/x-pack/test/security_api_integration/tests/session_idle/cleanup.ts b/x-pack/test/security_api_integration/tests/session_idle/cleanup.ts index 86b1cff3568f3..beb7bdfbdfccc 100644 --- a/x-pack/test/security_api_integration/tests/session_idle/cleanup.ts +++ b/x-pack/test/security_api_integration/tests/session_idle/cleanup.ts @@ -45,7 +45,7 @@ export default function ({ getService }: FtrProviderContext) { async function getNumberOfSessionDocuments() { return ( // @ts-expect-error doesn't handle total as number - (await es.search({ index: '.kibana_security_session*' })).body.hits.total.value as number + (await es.search({ index: '.kibana_security_session*' })).hits.total.value as number ); } diff --git a/x-pack/test/security_api_integration/tests/session_lifespan/cleanup.ts b/x-pack/test/security_api_integration/tests/session_lifespan/cleanup.ts index 69bbe9ea00341..6b5308f623805 100644 --- a/x-pack/test/security_api_integration/tests/session_lifespan/cleanup.ts +++ b/x-pack/test/security_api_integration/tests/session_lifespan/cleanup.ts @@ -40,7 +40,7 @@ export default function ({ getService }: FtrProviderContext) { async function getNumberOfSessionDocuments() { return ( // @ts-expect-error doesn't handle total as number - (await es.search({ index: '.kibana_security_session*' })).body.hits.total.value as number + (await es.search({ index: '.kibana_security_session*' })).hits.total.value as number ); } diff --git a/x-pack/test/security_api_integration/tests/token/header.ts b/x-pack/test/security_api_integration/tests/token/header.ts index 63e24e94565a0..74707aee68931 100644 --- a/x-pack/test/security_api_integration/tests/token/header.ts +++ b/x-pack/test/security_api_integration/tests/token/header.ts @@ -12,9 +12,7 @@ export default function ({ getService }: FtrProviderContext) { const es = getService('es'); async function createToken() { - const { - body: { access_token: accessToken }, - } = await es.security.getToken({ + const { access_token: accessToken } = await es.security.getToken({ body: { grant_type: 'password', username: 'elastic', diff --git a/x-pack/test/security_api_integration/tests/token/session.ts b/x-pack/test/security_api_integration/tests/token/session.ts index b8319ec8f7af1..b668108b9ee8b 100644 --- a/x-pack/test/security_api_integration/tests/token/session.ts +++ b/x-pack/test/security_api_integration/tests/token/session.ts @@ -146,7 +146,7 @@ export default function ({ getService }: FtrProviderContext) { body: { query: { match: { doc_type: 'token' } } }, refresh: true, }); - expect(esResponse.body).to.have.property('deleted').greaterThan(0); + expect(esResponse).to.have.property('deleted').greaterThan(0); const response = await supertest .get('/abc/xyz/') diff --git a/x-pack/test/security_solution_endpoint/services/endpoint.ts b/x-pack/test/security_solution_endpoint/services/endpoint.ts index 5bcc5c415a0db..af6519cff83e0 100644 --- a/x-pack/test/security_solution_endpoint/services/endpoint.ts +++ b/x-pack/test/security_solution_endpoint/services/endpoint.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ResponseError } from '@elastic/elasticsearch/lib/errors'; +import { errors } from '@elastic/elasticsearch'; import { Client } from '@elastic/elasticsearch'; import { FtrService } from '../../functional/ftr_provider_context'; import { @@ -177,10 +177,10 @@ export class EndpointTestResources extends FtrService { rest_total_hits_as_int: true, }); - return searchResponse.body.hits.total === size; + return searchResponse.hits.total === size; } catch (error) { // We ignore 404's (index might not exist) - if (error instanceof ResponseError && error.statusCode === 404) { + if (error instanceof errors.ResponseError && error.statusCode === 404) { return false; } diff --git a/x-pack/test/security_solution_endpoint_api_int/apis/package.ts b/x-pack/test/security_solution_endpoint_api_int/apis/package.ts index fdacc07426871..db993d8c47205 100644 --- a/x-pack/test/security_solution_endpoint_api_int/apis/package.ts +++ b/x-pack/test/security_solution_endpoint_api_int/apis/package.ts @@ -48,22 +48,25 @@ export default function ({ getService }: FtrProviderContext) { const generator = new EndpointDocGenerator('data'); const searchForID = async (id: string) => { - return es.search({ - index: eventsIndexPattern, - body: { - query: { - bool: { - filter: [ - { - ids: { - values: [id], + return es.search( + { + index: eventsIndexPattern, + body: { + query: { + bool: { + filter: [ + { + ids: { + values: [id], + }, }, - }, - ], + ], + }, }, }, }, - }); + { meta: true } + ); }; // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/114885 diff --git a/x-pack/test/security_solution_endpoint_api_int/services/resolver.ts b/x-pack/test/security_solution_endpoint_api_int/services/resolver.ts index 156043bd3c918..586de1f1276ee 100644 --- a/x-pack/test/security_solution_endpoint_api_int/services/resolver.ts +++ b/x-pack/test/security_solution_endpoint_api_int/services/resolver.ts @@ -64,7 +64,7 @@ export function ResolverGeneratorProvider({ getService }: FtrProviderContext) { const bulkResp = await client.bulk({ body, refresh: true }); const eventsInfo = events.map((event: Event, i: number) => { - return { event, _id: bulkResp.body.items[i].create?._id }; + return { event, _id: bulkResp.items[i].create?._id }; }); // @ts-expect-error @elastic/elasticsearch expected BulkResponseItemBase._id: string diff --git a/x-pack/test/spaces_api_integration/common/lib/create_users_and_roles.ts b/x-pack/test/spaces_api_integration/common/lib/create_users_and_roles.ts index ecc680c32f303..15ee9785aa690 100644 --- a/x-pack/test/spaces_api_integration/common/lib/create_users_and_roles.ts +++ b/x-pack/test/spaces_api_integration/common/lib/create_users_and_roles.ts @@ -6,10 +6,10 @@ */ import { SuperTest } from 'supertest'; -import type { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import type { Client } from '@elastic/elasticsearch'; import { AUTHENTICATION } from './authentication'; -export const createUsersAndRoles = async (es: KibanaClient, supertest: SuperTest) => { +export const createUsersAndRoles = async (es: Client, supertest: SuperTest) => { await supertest .put('/api/security/role/kibana_legacy_user') .send({ diff --git a/x-pack/test/spaces_api_integration/common/lib/space_test_utils.ts b/x-pack/test/spaces_api_integration/common/lib/space_test_utils.ts index c047a741e35da..a4ce22c6c010c 100644 --- a/x-pack/test/spaces_api_integration/common/lib/space_test_utils.ts +++ b/x-pack/test/spaces_api_integration/common/lib/space_test_utils.ts @@ -5,7 +5,7 @@ * 2.0. */ -import type { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import type { Client } from '@elastic/elasticsearch'; import { DEFAULT_SPACE_ID } from '../../../../plugins/spaces/common/constants'; export function getUrlPrefix(spaceId?: string) { @@ -37,7 +37,7 @@ export function getTestScenariosForSpace(spaceId: string) { return [explicitScenario]; } -export function getAggregatedSpaceData(es: KibanaClient, objectTypes: string[]) { +export function getAggregatedSpaceData(es: Client, objectTypes: string[]) { return es.search({ index: '.kibana', body: { diff --git a/x-pack/test/spaces_api_integration/common/suites/copy_to_space.ts b/x-pack/test/spaces_api_integration/common/suites/copy_to_space.ts index 644200a0636ec..91e35b2b0d8d4 100644 --- a/x-pack/test/spaces_api_integration/common/suites/copy_to_space.ts +++ b/x-pack/test/spaces_api_integration/common/suites/copy_to_space.ts @@ -4,11 +4,11 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import type { estypes } from '@elastic/elasticsearch'; +import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import expect from '@kbn/expect'; import { SuperTest } from 'supertest'; import { EsArchiver } from '@kbn/es-archiver'; -import type { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import type { Client } from '@elastic/elasticsearch'; import { DEFAULT_SPACE_ID } from '../../../../plugins/spaces/common/constants'; import { CopyResponse } from '../../../../plugins/spaces/server/lib/copy_to_spaces'; import { getAggregatedSpaceData, getUrlPrefix } from '../lib/space_test_utils'; @@ -76,12 +76,12 @@ const getDestinationWithConflicts = (originSpaceId?: string) => !originSpaceId || originSpaceId === DEFAULT_SPACE_ID ? 'space_1' : DEFAULT_SPACE_ID; export function copyToSpaceTestSuiteFactory( - es: KibanaClient, + es: Client, esArchiver: EsArchiver, supertest: SuperTest ) { const collectSpaceContents = async () => { - const { body: response } = await getAggregatedSpaceData(es, [ + const response = await getAggregatedSpaceData(es, [ 'visualization', 'dashboard', 'index-pattern', diff --git a/x-pack/test/spaces_api_integration/common/suites/delete.ts b/x-pack/test/spaces_api_integration/common/suites/delete.ts index f6fe05682e2da..e0f222af707c5 100644 --- a/x-pack/test/spaces_api_integration/common/suites/delete.ts +++ b/x-pack/test/spaces_api_integration/common/suites/delete.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import { SuperTest } from 'supertest'; -import type { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import type { Client } from '@elastic/elasticsearch'; import { getAggregatedSpaceData, getTestScenariosForSpace } from '../lib/space_test_utils'; import { MULTI_NAMESPACE_SAVED_OBJECT_TEST_CASES as CASES } from '../lib/saved_object_test_cases'; import { DescribeFn, TestDefinitionAuthentication } from '../lib/types'; @@ -29,11 +29,7 @@ interface DeleteTestDefinition { tests: DeleteTests; } -export function deleteTestSuiteFactory( - es: KibanaClient, - esArchiver: any, - supertest: SuperTest -) { +export function deleteTestSuiteFactory(es: Client, esArchiver: any, supertest: SuperTest) { const createExpectResult = (expectedResult: any) => (resp: { [key: string]: any }) => { expect(resp.body).to.eql(expectedResult); }; @@ -43,7 +39,7 @@ export function deleteTestSuiteFactory( // Query ES to ensure that we deleted everything we expected, and nothing we didn't // Grouping first by namespace, then by saved object type - const { body: response } = await getAggregatedSpaceData(es, [ + const response = await getAggregatedSpaceData(es, [ 'visualization', 'dashboard', 'space', @@ -108,7 +104,7 @@ export function deleteTestSuiteFactory( // There were 15 multi-namespace objects. // Since Space 2 was deleted, any multi-namespace objects that existed in that space // are updated to remove it, and of those, any that don't exist in any space are deleted. - const { body: multiNamespaceResponse } = await es.search>({ + const multiNamespaceResponse = await es.search>({ index: '.kibana', size: 20, body: { query: { terms: { type: ['sharedtype'] } } }, diff --git a/x-pack/test/spaces_api_integration/common/suites/disable_legacy_url_aliases.ts b/x-pack/test/spaces_api_integration/common/suites/disable_legacy_url_aliases.ts index 2d4b8b237e3c7..3374bfe647d10 100644 --- a/x-pack/test/spaces_api_integration/common/suites/disable_legacy_url_aliases.ts +++ b/x-pack/test/spaces_api_integration/common/suites/disable_legacy_url_aliases.ts @@ -7,7 +7,7 @@ import expect from '@kbn/expect'; import { SuperTest } from 'supertest'; -import type { KibanaClient } from '@elastic/elasticsearch/api/kibana'; +import type { Client } from '@elastic/elasticsearch'; import { LegacyUrlAlias } from 'src/core/server/saved_objects/object_types'; import { SPACES } from '../lib/spaces'; import { getUrlPrefix } from '../../../saved_object_api_integration/common/lib/saved_object_test_utils'; @@ -44,7 +44,7 @@ const getTestTitle = ({ targetSpace, targetType, sourceId }: DisableLegacyUrlAli }; export function disableLegacyUrlAliasesTestSuiteFactory( - es: KibanaClient, + es: Client, esArchiver: any, supertest: SuperTest ) { @@ -63,7 +63,7 @@ export function disableLegacyUrlAliasesTestSuiteFactory( index: '.kibana', id: `${LEGACY_URL_ALIAS_TYPE}:${targetSpace}:${targetType}:${sourceId}`, }); - const doc = esResponse.body._source!; + const doc = esResponse._source!; expect(doc).not.to.be(undefined); expect(doc[LEGACY_URL_ALIAS_TYPE].disabled).to.be(statusCode === 204 ? true : undefined); }; diff --git a/x-pack/test/stack_functional_integration/apps/reporting/util.js b/x-pack/test/stack_functional_integration/apps/reporting/util.js index 8f5356dd741ed..d3dc7967d1f54 100644 --- a/x-pack/test/stack_functional_integration/apps/reporting/util.js +++ b/x-pack/test/stack_functional_integration/apps/reporting/util.js @@ -11,7 +11,7 @@ export const pretty = (x) => JSON.stringify(x, null, 2); export const buildUrl = ({ protocol, auth, hostname, port }) => new URL(`${protocol}://${auth}@${hostname}:${port}`); export const putWatcher = async (watch, id, body, client, log) => { - const putWatchResponse = await client.watcher.putWatch({ ...watch, body }); + const putWatchResponse = await client.watcher.putWatch({ ...watch, body }, { meta: true }); log.debug(`# putWatchResponse \n${pretty(putWatchResponse)}`); expect(putWatchResponse.body._id).to.eql(id); expect(putWatchResponse.statusCode).to.eql('201'); @@ -26,7 +26,7 @@ export const getWatcher = async (watch, id, client, log, common, tryForTime) => await watcherHistory(id, client, log); - const getWatchResponse = await client.watcher.getWatch(watch); + const getWatchResponse = await client.watcher.getWatch(watch, { meta: true }); log.debug(`\n getWatchResponse: ${JSON.stringify(getWatchResponse)}`); expect(getWatchResponse.body._id).to.eql(id); expect(getWatchResponse.body._version).to.be.above(1); @@ -44,14 +44,14 @@ export const getWatcher = async (watch, id, client, log, common, tryForTime) => ); }; export const deleteWatcher = async (watch, id, client, log) => { - const deleteResponse = await client.watcher.deleteWatch(watch); + const deleteResponse = await client.watcher.deleteWatch(watch, { meta: true }); log.debug('\nDelete Response=' + pretty(deleteResponse) + '\n'); expect(deleteResponse.body._id).to.eql(id); expect(deleteResponse.body.found).to.eql(true); expect(deleteResponse.statusCode).to.eql('200'); }; async function watcherHistory(watchId, client, log) { - const { body } = await client.search({ + const body = await client.search({ index: '.watcher-history*', body: { query: { diff --git a/x-pack/test/upgrade_assistant_integration/upgrade_assistant/reindexing.js b/x-pack/test/upgrade_assistant_integration/upgrade_assistant/reindexing.js index 2fe7254def272..d52f407e8483f 100644 --- a/x-pack/test/upgrade_assistant_integration/upgrade_assistant/reindexing.js +++ b/x-pack/test/upgrade_assistant_integration/upgrade_assistant/reindexing.js @@ -66,7 +66,7 @@ export default function ({ getService }) { expect(lastState.status).to.equal(ReindexStatus.completed); const { newIndexName } = lastState; - const { body: indexSummary } = await es.indices.get({ index: 'dummydata' }); + const indexSummary = await es.indices.get({ index: 'dummydata' }); // The new index was created expect(indexSummary[newIndexName]).to.be.an('object'); @@ -75,7 +75,7 @@ export default function ({ getService }) { // Verify mappings exist on new index expect(indexSummary[newIndexName].mappings.properties).to.be.an('object'); // The number of documents in the new index matches what we expect - expect((await es.count({ index: lastState.newIndexName })).body.count).to.be(3); + expect((await es.count({ index: lastState.newIndexName })).count).to.be(3); // Cleanup newly created index await es.indices.delete({ @@ -98,9 +98,9 @@ export default function ({ getService }) { ], }, }); - expect((await es.count({ index: 'myAlias' })).body.count).to.be(3); - expect((await es.count({ index: 'wildcardAlias' })).body.count).to.be(3); - expect((await es.count({ index: 'myHttpsAlias' })).body.count).to.be(2); + expect((await es.count({ index: 'myAlias' })).count).to.be(3); + expect((await es.count({ index: 'wildcardAlias' })).count).to.be(3); + expect((await es.count({ index: 'myHttpsAlias' })).count).to.be(2); // Reindex await supertest @@ -110,10 +110,10 @@ export default function ({ getService }) { const lastState = await waitForReindexToComplete('dummydata'); // The regular aliases should still return 3 docs - expect((await es.count({ index: 'myAlias' })).body.count).to.be(3); - expect((await es.count({ index: 'wildcardAlias' })).body.count).to.be(3); + expect((await es.count({ index: 'myAlias' })).count).to.be(3); + expect((await es.count({ index: 'wildcardAlias' })).count).to.be(3); // The filtered alias should still return 2 docs - expect((await es.count({ index: 'myHttpsAlias' })).body.count).to.be(2); + expect((await es.count({ index: 'myHttpsAlias' })).count).to.be(2); // Cleanup newly created index await es.indices.delete({ @@ -207,7 +207,7 @@ export default function ({ getService }) { await assertQueueState(undefined, 0); // Check that the closed index is still closed after reindexing - const { body: resolvedIndices } = await es.indices.resolveIndex({ + const resolvedIndices = await es.indices.resolveIndex({ name: nameOfIndexThatShouldBeClosed, }); diff --git a/yarn.lock b/yarn.lock index 04e303975b9c7..43db04f70de45 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2379,15 +2379,13 @@ dependencies: "@elastic/ecs-helpers" "^1.1.0" -"@elastic/elasticsearch@npm:@elastic/elasticsearch-canary@^8.0.0-canary.21": - version "8.0.0-canary.21" - resolved "https://registry.yarnpkg.com/@elastic/elasticsearch-canary/-/elasticsearch-canary-8.0.0-canary.21.tgz#6572a547071a17cf511a42fd93738780266a9f89" - integrity sha512-J/qRGYkTj+YeEJh5xci9eLlVPrfwSEURK/P+ZZ6ZKymFLz7VQvK1vvha2YJJBjpM3ERnLNDL0y/HTEjYkR3VtQ== +"@elastic/elasticsearch@npm:@elastic/elasticsearch-canary@^8.0.0-canary.35": + version "8.0.0-canary.35" + resolved "https://registry.yarnpkg.com/@elastic/elasticsearch-canary/-/elasticsearch-canary-8.0.0-canary.35.tgz#a6023cb83c063cb0a82eac5d0ef1b025d4025c74" + integrity sha512-mrMnIDrhZECjIy8sdARsuaRip9xm4xOmi+WtDWpIhmvRNZ3lpw5d9BmEr7+AnduG4HsccCGWY05HrA+iUtRV8w== dependencies: - debug "^4.3.1" - hpagent "^0.1.1" - ms "^2.1.3" - secure-json-parse "^2.4.0" + "@elastic/transport" "^0.0.15" + tslib "^2.3.0" "@elastic/ems-client@7.16.0": version "7.16.0" @@ -2573,6 +2571,18 @@ ts-node "^10.2.1" typescript "^4.3.5" +"@elastic/transport@^0.0.15": + version "0.0.15" + resolved "https://registry.yarnpkg.com/@elastic/transport/-/transport-0.0.15.tgz#4f09806035d4959c1e2ab5e395f80927cb0ad821" + integrity sha512-V3ROTwKEWLT8X+rntJbZ4wV8sdt7HHSj81yi2Wv0DojQlvYo91Cit8YvdEwZcZHF4z8muIoWJv4G9gyD0MkfHQ== + dependencies: + debug "^4.3.2" + hpagent "^0.1.2" + ms "^2.1.3" + secure-json-parse "^2.4.0" + tslib "^2.3.0" + undici "^4.7.0" + "@emotion/babel-plugin-jsx-pragmatic@^0.1.5": version "0.1.5" resolved "https://registry.yarnpkg.com/@emotion/babel-plugin-jsx-pragmatic/-/babel-plugin-jsx-pragmatic-0.1.5.tgz#27debfe9c27c4d83574d509787ae553bf8a34d7e" @@ -16313,10 +16323,10 @@ hpack.js@^2.1.6: readable-stream "^2.0.1" wbuf "^1.1.0" -hpagent@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/hpagent/-/hpagent-0.1.1.tgz#66f67f16e5c7a8b59a068e40c2658c2c749ad5e2" - integrity sha512-IxJWQiY0vmEjetHdoE9HZjD4Cx+mYTr25tR7JCxXaiI3QxW0YqYyM11KyZbHufoa/piWhMb2+D3FGpMgmA2cFQ== +hpagent@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/hpagent/-/hpagent-0.1.2.tgz#cab39c66d4df2d4377dbd212295d878deb9bdaa9" + integrity sha512-ePqFXHtSQWAFXYmj+JtOTHr84iNrII4/QRlAAPPE+zqnKy4xJo7Ie1Y4kC7AdB+LxLxSTTzBMASsEcy0q8YyvQ== hsl-regex@^1.0.0: version "1.0.0" @@ -28242,6 +28252,11 @@ tslib@^2.0.0, tslib@^2.0.1, tslib@^2.2.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.2.0.tgz#fb2c475977e35e241311ede2693cee1ec6698f5c" integrity sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w== +tslib@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" + integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== + tslib@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a" @@ -28530,6 +28545,11 @@ undertaker@^1.2.1: object.reduce "^1.0.0" undertaker-registry "^1.0.0" +undici@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/undici/-/undici-4.7.0.tgz#3bda286d67bf45d0ab1b94ca6c84e546dcb3b0d4" + integrity sha512-O1q+/EIs4g0HnVMH8colei3qODGiYBLpavWYv3kI+JazBBsBIndnZfUqZ2MEfPJ12H9d56yVdwZG1/nV/xcoSQ== + unfetch@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/unfetch/-/unfetch-4.1.0.tgz#6ec2dd0de887e58a4dee83a050ded80ffc4137db" From 57c2555f271a77a8e0b49b8b050a83ec03d626f5 Mon Sep 17 00:00:00 2001 From: Nathan L Smith Date: Tue, 26 Oct 2021 07:25:01 -0500 Subject: [PATCH 26/58] Jest and Storybook fixes (#116132) * Fix all broken stories * In stories that were broken, add an associated Jest test so they if they break in the future we'll know * Fix all console.error messages that were being printed during Jest test runs * Add test setup which makes it so `console.error` throws an error so tests will fail if error console messages are printed --- x-pack/plugins/apm/jest.config.js | 5 +- x-pack/plugins/apm/jest_setup.js | 14 + .../error_count_alert_trigger.stories.tsx | 12 +- .../error_count_alert_trigger.test.tsx | 8 +- .../error_group_overview/List/List.test.tsx | 55 - .../List/__snapshots__/List.test.tsx.snap | 1335 ----------------- .../__fixtures__/props.json | 0 .../error_group_list.stories.tsx | 100 ++ .../error_group_list.test.tsx | 19 + .../{List => error_group_list}/index.tsx | 0 .../app/error_group_overview/index.tsx | 2 +- .../service_list/service_list.stories.tsx | 81 + .../service_list/service_list.test.tsx | 93 +- .../distribution/index.test.tsx | 53 +- .../templates/settings_template.stories.tsx | 75 + .../templates/settings_template.test.tsx | 68 +- .../shared/backend_link.stories.tsx | 6 + .../components/shared/backend_link.test.tsx | 19 + .../latency_chart/latency_chart.stories.tsx | 97 +- .../latency_chart/latency_chart.test.tsx | 21 + .../shared/service_link.stories.tsx | 6 + .../components/shared/service_link.test.tsx | 19 + .../suggestions_select.test.tsx | 8 +- 23 files changed, 496 insertions(+), 1600 deletions(-) create mode 100644 x-pack/plugins/apm/jest_setup.js delete mode 100644 x-pack/plugins/apm/public/components/app/error_group_overview/List/List.test.tsx delete mode 100644 x-pack/plugins/apm/public/components/app/error_group_overview/List/__snapshots__/List.test.tsx.snap rename x-pack/plugins/apm/public/components/app/error_group_overview/{List => error_group_list}/__fixtures__/props.json (100%) create mode 100644 x-pack/plugins/apm/public/components/app/error_group_overview/error_group_list/error_group_list.stories.tsx create mode 100644 x-pack/plugins/apm/public/components/app/error_group_overview/error_group_list/error_group_list.test.tsx rename x-pack/plugins/apm/public/components/app/error_group_overview/{List => error_group_list}/index.tsx (100%) create mode 100644 x-pack/plugins/apm/public/components/app/service_inventory/service_list/service_list.stories.tsx create mode 100644 x-pack/plugins/apm/public/components/routing/templates/settings_template.stories.tsx create mode 100644 x-pack/plugins/apm/public/components/shared/backend_link.test.tsx create mode 100644 x-pack/plugins/apm/public/components/shared/charts/latency_chart/latency_chart.test.tsx create mode 100644 x-pack/plugins/apm/public/components/shared/service_link.test.tsx diff --git a/x-pack/plugins/apm/jest.config.js b/x-pack/plugins/apm/jest.config.js index 4fd2e72776943..66b4b164a794c 100644 --- a/x-pack/plugins/apm/jest.config.js +++ b/x-pack/plugins/apm/jest.config.js @@ -11,7 +11,10 @@ module.exports = { preset: '@kbn/test', rootDir: path.resolve(__dirname, '../../..'), roots: ['/x-pack/plugins/apm'], - setupFiles: ['/x-pack/plugins/apm/.storybook/jest_setup.js'], + setupFiles: [ + '/x-pack/plugins/apm/jest_setup.js', + '/x-pack/plugins/apm/.storybook/jest_setup.js', + ], coverageDirectory: '/target/kibana-coverage/jest/x-pack/plugins/apm', coverageReporters: ['text', 'html'], collectCoverageFrom: [ diff --git a/x-pack/plugins/apm/jest_setup.js b/x-pack/plugins/apm/jest_setup.js new file mode 100644 index 0000000000000..df8ba56cdc1c3 --- /dev/null +++ b/x-pack/plugins/apm/jest_setup.js @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +/* global jest */ + +// When a `console.error` is encountered, throw the error to make the test fail. +// This effectively treats logged errors during the test run as failures. +jest.spyOn(console, 'error').mockImplementation((message) => { + throw new Error(message); +}); diff --git a/x-pack/plugins/apm/public/components/alerting/error_count_alert_trigger/error_count_alert_trigger.stories.tsx b/x-pack/plugins/apm/public/components/alerting/error_count_alert_trigger/error_count_alert_trigger.stories.tsx index d28d3076b21c0..38ef94f9c1526 100644 --- a/x-pack/plugins/apm/public/components/alerting/error_count_alert_trigger/error_count_alert_trigger.stories.tsx +++ b/x-pack/plugins/apm/public/components/alerting/error_count_alert_trigger/error_count_alert_trigger.stories.tsx @@ -11,11 +11,17 @@ import { AlertParams, ErrorCountAlertTrigger } from '.'; import { CoreStart } from '../../../../../../../src/core/public'; import { createKibanaReactContext } from '../../../../../../../src/plugins/kibana_react/public'; import { ENVIRONMENT_ALL } from '../../../../common/environment_filter_values'; +import { createCallApmApi } from '../../../services/rest/createCallApmApi'; + import { AlertMetadata } from '../helper'; -const KibanaReactContext = createKibanaReactContext({ +const coreMock = { + http: { get: async () => ({}) }, notifications: { toasts: { add: () => {} } }, -} as unknown as Partial); + uiSettings: { get: () => {} }, +} as unknown as CoreStart; + +const KibanaReactContext = createKibanaReactContext(coreMock); interface Args { alertParams: AlertParams; @@ -27,6 +33,8 @@ const stories: Meta<{}> = { component: ErrorCountAlertTrigger, decorators: [ (StoryComponent) => { + createCallApmApi(coreMock); + return (
diff --git a/x-pack/plugins/apm/public/components/alerting/error_count_alert_trigger/error_count_alert_trigger.test.tsx b/x-pack/plugins/apm/public/components/alerting/error_count_alert_trigger/error_count_alert_trigger.test.tsx index 26c62b10e6220..edf3b5b675cc4 100644 --- a/x-pack/plugins/apm/public/components/alerting/error_count_alert_trigger/error_count_alert_trigger.test.tsx +++ b/x-pack/plugins/apm/public/components/alerting/error_count_alert_trigger/error_count_alert_trigger.test.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { render } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; import React from 'react'; import * as stories from './error_count_alert_trigger.stories'; import { composeStories } from '@storybook/testing-react'; @@ -13,7 +13,9 @@ import { composeStories } from '@storybook/testing-react'; const { CreatingInApmFromService } = composeStories(stories); describe('ErrorCountAlertTrigger', () => { - it('renders', () => { - expect(() => render()).not.toThrowError(); + it('renders', async () => { + render(); + + expect(await screen.findByText('Service')).toBeInTheDocument(); }); }); diff --git a/x-pack/plugins/apm/public/components/app/error_group_overview/List/List.test.tsx b/x-pack/plugins/apm/public/components/app/error_group_overview/List/List.test.tsx deleted file mode 100644 index 12fa1c955ccc8..0000000000000 --- a/x-pack/plugins/apm/public/components/app/error_group_overview/List/List.test.tsx +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { mount } from 'enzyme'; -import React from 'react'; -import { MockApmPluginContextWrapper } from '../../../../context/apm_plugin/mock_apm_plugin_context'; -import { MockUrlParamsContextProvider } from '../../../../context/url_params_context/mock_url_params_context_provider'; -import { mockMoment, toJson } from '../../../../utils/testHelpers'; -import { ErrorGroupList } from './index'; -import props from './__fixtures__/props.json'; -import { MemoryRouter } from 'react-router-dom'; -import { EuiThemeProvider } from '../../../../../../../../src/plugins/kibana_react/common'; - -describe('ErrorGroupOverview -> List', () => { - beforeAll(() => { - mockMoment(); - }); - - it('should render empty state', () => { - const storeState = {}; - const wrapper = mount( - - - - - , - storeState - ); - - expect(toJson(wrapper)).toMatchSnapshot(); - }); - - it('should render with data', () => { - const wrapper = mount( - - - - - - - - - - ); - - expect(toJson(wrapper)).toMatchSnapshot(); - }); -}); diff --git a/x-pack/plugins/apm/public/components/app/error_group_overview/List/__snapshots__/List.test.tsx.snap b/x-pack/plugins/apm/public/components/app/error_group_overview/List/__snapshots__/List.test.tsx.snap deleted file mode 100644 index ee68630daa469..0000000000000 --- a/x-pack/plugins/apm/public/components/app/error_group_overview/List/__snapshots__/List.test.tsx.snap +++ /dev/null @@ -1,1335 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`ErrorGroupOverview -> List should render empty state 1`] = ` -
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - -
-
- - - Group ID - - - - - - - - - - Type - - - - - - Error message and culprit - - - - - - - - - - -
-
- - No errors found - -
-
-
-
-`; - -exports[`ErrorGroupOverview -> List should render with data 1`] = ` -.c0 { - font-family: 'Roboto Mono','Consolas','Menlo','Courier',monospace; -} - -.c2 { - max-width: 100%; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.c1 { - max-width: 100%; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.c3 { - font-family: 'Roboto Mono','Consolas','Menlo','Courier',monospace; - font-size: 18px; - max-width: 100%; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -} - -.c4 { - font-family: 'Roboto Mono','Consolas','Menlo','Courier',monospace; -} - -
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - Group ID - - - - - - - - - - Type - - - - - - Error message and culprit - - - - - - - - - - -
-
- Group ID - - - - -
- -
-
- Type -
- -
-
- Error message and culprit -
-
-
- - - About to blow up! - - -
- -
- elasticapm.contrib.django.client.capture -
-
-
-
-
-
-
-
- Occurrences -
-
- 75 -
-
-
- Latest occurrence -
-
- - 1337 minutes ago (mocking 1515578797) - -
-
-
- Group ID - - - - -
- -
-
- Type -
- -
-
- Error message and culprit -
-
-
- - - AssertionError: - - -
- -
- opbeans.views.oopsie -
-
-
-
-
-
-
-
- Occurrences -
-
- 75 -
-
-
- Latest occurrence -
-
- - 1337 minutes ago (mocking 1515578797) - -
-
-
- Group ID - - - - -
- -
-
- Type -
- -
-
- Error message and culprit -
-
-
- - - AssertionError: Bad luck! - - -
- -
- opbeans.tasks.update_stats -
-
-
-
-
-
-
-
- Occurrences -
-
- 24 -
-
-
- Latest occurrence -
-
- - 1337 minutes ago (mocking 1515578796) - -
-
-
- Group ID - - - - -
- -
-
- Type -
- -
-
- Error message and culprit -
-
-
- - - Customer with ID 8517 not found - - -
- -
- opbeans.views.customer -
-
-
-
-
-
-
-
- Occurrences -
-
- 15 -
-
-
- Latest occurrence -
-
- - 1337 minutes ago (mocking 1515578773) - -
-
-
-
-
-
-
-
- -
-
-
-
-`; diff --git a/x-pack/plugins/apm/public/components/app/error_group_overview/List/__fixtures__/props.json b/x-pack/plugins/apm/public/components/app/error_group_overview/error_group_list/__fixtures__/props.json similarity index 100% rename from x-pack/plugins/apm/public/components/app/error_group_overview/List/__fixtures__/props.json rename to x-pack/plugins/apm/public/components/app/error_group_overview/error_group_list/__fixtures__/props.json diff --git a/x-pack/plugins/apm/public/components/app/error_group_overview/error_group_list/error_group_list.stories.tsx b/x-pack/plugins/apm/public/components/app/error_group_overview/error_group_list/error_group_list.stories.tsx new file mode 100644 index 0000000000000..e61e43c8bb7ea --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/error_group_overview/error_group_list/error_group_list.stories.tsx @@ -0,0 +1,100 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { Meta, Story } from '@storybook/react'; +import React, { ComponentProps } from 'react'; +import { MemoryRouter } from 'react-router-dom'; +import { MockApmPluginContextWrapper } from '../../../../context/apm_plugin/mock_apm_plugin_context'; +import { MockUrlParamsContextProvider } from '../../../../context/url_params_context/mock_url_params_context_provider'; + +import { ErrorGroupList } from '.'; + +type Args = ComponentProps; + +const stories: Meta = { + title: 'app/ErrorGroupOverview/ErrorGroupList', + component: ErrorGroupList, + decorators: [ + (StoryComponent) => { + return ( + + + + + + + + ); + }, + ], +}; +export default stories; + +export const Example: Story = (args) => { + return ; +}; +Example.args = { + items: [ + { + message: 'net/http: abort Handler', + occurrenceCount: 14, + culprit: 'Main.func2', + groupId: '83a653297ec29afed264d7b60d5cda7b', + latestOccurrenceAt: '2021-10-21T16:18:41.434Z', + handled: false, + type: 'errorString', + }, + { + message: 'POST /api/orders (500)', + occurrenceCount: 5, + culprit: 'logrusMiddleware', + groupId: '7a640436a9be648fd708703d1ac84650', + latestOccurrenceAt: '2021-10-21T16:18:40.162Z', + handled: false, + type: 'OpError', + }, + { + message: + 'write tcp 10.36.2.24:3000->10.36.1.14:34232: write: connection reset by peer', + occurrenceCount: 4, + culprit: 'apiHandlers.getProductCustomers', + groupId: '95ca0e312c109aa11e298bcf07f1445b', + latestOccurrenceAt: '2021-10-21T16:18:42.650Z', + handled: false, + type: 'OpError', + }, + { + message: + 'write tcp 10.36.0.21:3000->10.36.1.252:57070: write: connection reset by peer', + occurrenceCount: 3, + culprit: 'apiHandlers.getCustomers', + groupId: '4053d7e33d2b716c819bd96d9d6121a2', + latestOccurrenceAt: '2021-10-21T16:07:44.078Z', + handled: false, + type: 'OpError', + }, + { + message: + 'write tcp 10.36.0.21:3000->10.36.0.88:33926: write: broken pipe', + occurrenceCount: 2, + culprit: 'apiHandlers.getOrders', + groupId: '94f4ca8ec8c02e5318cf03f46ae4c1f3', + latestOccurrenceAt: '2021-10-21T16:13:45.742Z', + handled: false, + type: 'OpError', + }, + ], + serviceName: 'test service', +}; + +export const EmptyState: Story = (args) => { + return ; +}; +EmptyState.args = { + items: [], + serviceName: 'test service', +}; diff --git a/x-pack/plugins/apm/public/components/app/error_group_overview/error_group_list/error_group_list.test.tsx b/x-pack/plugins/apm/public/components/app/error_group_overview/error_group_list/error_group_list.test.tsx new file mode 100644 index 0000000000000..278825c25c68c --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/error_group_overview/error_group_list/error_group_list.test.tsx @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { composeStories } from '@storybook/testing-react'; +import { render } from '@testing-library/react'; +import React from 'react'; +import * as stories from './error_group_list.stories'; + +const { Example } = composeStories(stories); + +describe('ErrorGroupList', () => { + it('renders', () => { + expect(() => render()).not.toThrowError(); + }); +}); diff --git a/x-pack/plugins/apm/public/components/app/error_group_overview/List/index.tsx b/x-pack/plugins/apm/public/components/app/error_group_overview/error_group_list/index.tsx similarity index 100% rename from x-pack/plugins/apm/public/components/app/error_group_overview/List/index.tsx rename to x-pack/plugins/apm/public/components/app/error_group_overview/error_group_list/index.tsx diff --git a/x-pack/plugins/apm/public/components/app/error_group_overview/index.tsx b/x-pack/plugins/apm/public/components/app/error_group_overview/index.tsx index 9020021d3d6f8..5e9095def6e55 100644 --- a/x-pack/plugins/apm/public/components/app/error_group_overview/index.tsx +++ b/x-pack/plugins/apm/public/components/app/error_group_overview/index.tsx @@ -23,7 +23,7 @@ import { useFetcher } from '../../../hooks/use_fetcher'; import { useTimeRange } from '../../../hooks/use_time_range'; import { FailedTransactionRateChart } from '../../shared/charts/failed_transaction_rate_chart'; import { ErrorDistribution } from '../error_group_details/Distribution'; -import { ErrorGroupList } from './List'; +import { ErrorGroupList } from './error_group_list'; export function ErrorGroupOverview() { const { serviceName } = useApmServiceContext(); diff --git a/x-pack/plugins/apm/public/components/app/service_inventory/service_list/service_list.stories.tsx b/x-pack/plugins/apm/public/components/app/service_inventory/service_list/service_list.stories.tsx new file mode 100644 index 0000000000000..628ef4617417c --- /dev/null +++ b/x-pack/plugins/apm/public/components/app/service_inventory/service_list/service_list.stories.tsx @@ -0,0 +1,81 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { Meta, Story } from '@storybook/react'; +import React, { ComponentProps } from 'react'; +import { MemoryRouter } from 'react-router-dom'; +import { CoreStart } from '../../../../../../../../src/core/public'; +import { createKibanaReactContext } from '../../../../../../../../src/plugins/kibana_react/public'; +import { ServiceHealthStatus } from '../../../../../common/service_health_status'; +import type { ApmPluginContextValue } from '../../../../context/apm_plugin/apm_plugin_context'; +import { MockApmPluginContextWrapper } from '../../../../context/apm_plugin/mock_apm_plugin_context'; +import { ServiceList } from './'; +import { items } from './__fixtures__/service_api_mock_data'; + +type Args = ComponentProps; + +const coreMock = { + http: { + get: async () => { + return { fallBackToTransactions: false }; + }, + }, + notifications: { toasts: { add: () => {} } }, + uiSettings: { get: () => ({}) }, +} as unknown as CoreStart; + +const KibanaReactContext = createKibanaReactContext(coreMock); + +const stories: Meta = { + title: 'app/ServiceInventory/ServiceList', + component: ServiceList, + decorators: [ + (StoryComponent) => { + return ( + + + + + + + + ); + }, + ], +}; +export default stories; + +export const Example: Story = (args) => { + return ; +}; +Example.args = { + isLoading: false, + items, +}; + +export const EmptyState: Story = (args) => { + return ; +}; +EmptyState.args = { + isLoading: false, + items: [], +}; + +export const WithHealthWarnings: Story = (args) => { + return ; +}; +WithHealthWarnings.args = { + isLoading: false, + items: items.map((item) => ({ + ...item, + healthStatus: ServiceHealthStatus.warning, + })), +}; diff --git a/x-pack/plugins/apm/public/components/app/service_inventory/service_list/service_list.test.tsx b/x-pack/plugins/apm/public/components/app/service_inventory/service_list/service_list.test.tsx index 69ec1e6b1eb93..5068d13d589c8 100644 --- a/x-pack/plugins/apm/public/components/app/service_inventory/service_list/service_list.test.tsx +++ b/x-pack/plugins/apm/public/components/app/service_inventory/service_list/service_list.test.tsx @@ -5,58 +5,27 @@ * 2.0. */ -import React, { ReactNode } from 'react'; -import { MemoryRouter } from 'react-router-dom'; -import { Breakpoints } from '../../../../hooks/use_breakpoints'; -import { ServiceHealthStatus } from '../../../../../common/service_health_status'; -import { MockApmPluginContextWrapper } from '../../../../context/apm_plugin/mock_apm_plugin_context'; -import { mockMoment, renderWithTheme } from '../../../../utils/testHelpers'; -import { getServiceColumns, ServiceList } from './'; -import { items } from './__fixtures__/service_api_mock_data'; +import { composeStories } from '@storybook/testing-react'; +import { render, screen } from '@testing-library/react'; +import React from 'react'; import { ENVIRONMENT_ALL } from '../../../../../common/environment_filter_values'; -import { - getCallApmApiSpy, - getCreateCallApmApiSpy, -} from '../../../../services/rest/callApmApiSpy'; +import { Breakpoints } from '../../../../hooks/use_breakpoints'; +import { getServiceColumns } from './'; +import * as stories from './service_list.stories'; -function Wrapper({ children }: { children?: ReactNode }) { - return ( - - {children} - - ); -} +const { Example, EmptyState, WithHealthWarnings } = composeStories(stories); describe('ServiceList', () => { - beforeAll(() => { - mockMoment(); + it('renders empty state', async () => { + render(); - const callApmApiSpy = getCallApmApiSpy().mockImplementation( - ({ endpoint }) => { - if (endpoint === 'GET /internal/apm/fallback_to_transactions') { - return Promise.resolve({ fallbackToTransactions: false }); - } - return Promise.reject(`Response for ${endpoint} is not defined`); - } - ); - - getCreateCallApmApiSpy().mockImplementation(() => callApmApiSpy as any); + expect(await screen.findByRole('table')).toBeInTheDocument(); }); - it('renders empty state', () => { - expect(() => - renderWithTheme(, { - wrapper: Wrapper, - }) - ).not.toThrowError(); - }); + it('renders with data', async () => { + render(); - it('renders with data', () => { - expect(() => - renderWithTheme(, { - wrapper: Wrapper, - }) - ).not.toThrowError(); + expect(await screen.findByRole('table')).toBeInTheDocument(); }); describe('responsive columns', () => { @@ -212,44 +181,20 @@ describe('ServiceList', () => { }); describe('without ML data', () => { - it('does not render the health column', () => { - const { queryByText } = renderWithTheme( - , - { - wrapper: Wrapper, - } - ); - const healthHeading = queryByText('Health'); - - expect(healthHeading).toBeNull(); - }); - it('sorts by throughput', async () => { - const { findByTitle } = renderWithTheme( - , - { - wrapper: Wrapper, - } - ); + render(); - expect(await findByTitle('Throughput')).toBeInTheDocument(); + expect(await screen.findByTitle('Throughput')).toBeInTheDocument(); }); }); describe('with ML data', () => { it('renders the health column', async () => { - const { findByTitle } = renderWithTheme( - ({ - ...item, - healthStatus: ServiceHealthStatus.warning, - }))} - />, - { wrapper: Wrapper } - ); + render(); - expect(await findByTitle('Health')).toBeInTheDocument(); + expect( + await screen.findByRole('button', { name: /Health/ }) + ).toBeInTheDocument(); }); }); }); diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/distribution/index.test.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/distribution/index.test.tsx index 0e9639de4aa74..acee2a964d1eb 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/distribution/index.test.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/distribution/index.test.tsx @@ -5,6 +5,7 @@ * 2.0. */ +import { __IntlProvider as IntlProvider } from '@kbn/i18n/react'; import { render, screen, waitFor } from '@testing-library/react'; import { createMemoryHistory } from 'history'; import React, { ReactNode } from 'react'; @@ -49,25 +50,27 @@ function Wrapper({ children }: { children?: ReactNode }) { }) as unknown as ApmPluginContextValue; return ( - - - - + + + - {children} - - - - + + {children} + + + + + ); } @@ -93,13 +96,13 @@ describe('transaction_details/distribution', () => { })); render( - - - + , + + { wrapper: Wrapper } ); await waitFor(() => { diff --git a/x-pack/plugins/apm/public/components/routing/templates/settings_template.stories.tsx b/x-pack/plugins/apm/public/components/routing/templates/settings_template.stories.tsx new file mode 100644 index 0000000000000..4fc35bf242a40 --- /dev/null +++ b/x-pack/plugins/apm/public/components/routing/templates/settings_template.stories.tsx @@ -0,0 +1,75 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { Meta, Story } from '@storybook/react'; +import type { CoreStart, DocLinksStart } from 'kibana/public'; +import React, { ComponentProps } from 'react'; +import { MemoryRouter } from 'react-router-dom'; +import { createKibanaReactContext } from '../../../../../../../src/plugins/kibana_react/public'; +import type { ApmPluginContextValue } from '../../../context/apm_plugin/apm_plugin_context'; +import { MockApmPluginContextWrapper } from '../../../context/apm_plugin/mock_apm_plugin_context'; +import { SettingsTemplate } from './settings_template'; + +type Args = ComponentProps; + +const coreMock = { + notifications: { toasts: { add: () => {} } }, + usageCollection: { reportUiCounter: () => {} }, + observability: { + navigation: { + PageTemplate: () => { + return <>hello world; + }, + }, + }, + http: { + basePath: { + prepend: (path: string) => `/basepath${path}`, + get: () => `/basepath`, + }, + get: async () => ({}), + }, + docLinks: { + DOC_LINK_VERSION: '0', + ELASTIC_WEBSITE_URL: 'https://www.elastic.co/', + links: { + apm: {}, + observability: { guide: '' }, + }, + } as unknown as DocLinksStart, +} as unknown as Partial; + +const KibanaReactContext = createKibanaReactContext(coreMock); + +const stories: Meta = { + title: 'routing/templates/SettingsTemplate', + component: SettingsTemplate, + decorators: [ + (StoryComponent) => { + return ( + + + + + + + + ); + }, + ], +}; +export default stories; + +export const Example: Story = (args) => { + return ; +}; +Example.args = { + children: <>test, + selectedTab: 'agent-configurations', +}; diff --git a/x-pack/plugins/apm/public/components/routing/templates/settings_template.test.tsx b/x-pack/plugins/apm/public/components/routing/templates/settings_template.test.tsx index d52c758909ff1..90dbbdf2bc546 100644 --- a/x-pack/plugins/apm/public/components/routing/templates/settings_template.test.tsx +++ b/x-pack/plugins/apm/public/components/routing/templates/settings_template.test.tsx @@ -5,69 +5,17 @@ * 2.0. */ -import { render } from '@testing-library/react'; -import { MockApmPluginContextWrapper } from '../../../context/apm_plugin/mock_apm_plugin_context'; -import React, { ReactNode } from 'react'; -import { SettingsTemplate } from './settings_template'; -import { createMemoryHistory } from 'history'; -import { MemoryRouter, RouteComponentProps } from 'react-router-dom'; -import { CoreStart, DocLinksStart, HttpStart } from 'kibana/public'; -import { createKibanaReactContext } from 'src/plugins/kibana_react/public'; -import { createCallApmApi } from '../../../services/rest/createCallApmApi'; +import { composeStories } from '@storybook/testing-react'; +import { render, screen } from '@testing-library/react'; +import React from 'react'; +import * as stories from './settings_template.stories'; -const { location } = createMemoryHistory(); - -const KibanaReactContext = createKibanaReactContext({ - notifications: { toasts: { add: () => {} } }, - usageCollection: { reportUiCounter: () => {} }, - observability: { - navigation: { - PageTemplate: () => { - return <>hello world; - }, - }, - }, - http: { - basePath: { - prepend: (path: string) => `/basepath${path}`, - get: () => `/basepath`, - }, - } as HttpStart, - docLinks: { - DOC_LINK_VERSION: '0', - ELASTIC_WEBSITE_URL: 'https://www.elastic.co/', - links: { - apm: {}, - observability: { guide: '' }, - }, - } as unknown as DocLinksStart, -} as unknown as Partial); - -function Wrapper({ children }: { children?: ReactNode }) { - return ( - - - {children} - - - ); -} +const { Example } = composeStories(stories); describe('Settings', () => { - beforeEach(() => { - createCallApmApi({} as CoreStart); - }); it('renders', async () => { - const routerProps = { - location, - } as unknown as RouteComponentProps<{}>; - expect(() => - render( - -
hello world
-
, - { wrapper: Wrapper } - ) - ).not.toThrowError(); + render(); + + expect(await screen.findByText('hello world')).toBeInTheDocument(); }); }); diff --git a/x-pack/plugins/apm/public/components/shared/backend_link.stories.tsx b/x-pack/plugins/apm/public/components/shared/backend_link.stories.tsx index 31bc2f2302798..500aa983b8b1d 100644 --- a/x-pack/plugins/apm/public/components/shared/backend_link.stories.tsx +++ b/x-pack/plugins/apm/public/components/shared/backend_link.stories.tsx @@ -31,6 +31,12 @@ export const Example: Story = (args) => { }; Example.args = { backendName: 'postgres', + query: { + environment: 'ENVIRONMENT_ALL', + kuery: '', + rangeFrom: 'now-15m', + rangeTo: 'now', + }, type: 'db', subtype: 'postgresql', }; diff --git a/x-pack/plugins/apm/public/components/shared/backend_link.test.tsx b/x-pack/plugins/apm/public/components/shared/backend_link.test.tsx new file mode 100644 index 0000000000000..683fec3a41725 --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/backend_link.test.tsx @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { composeStories } from '@storybook/testing-react'; +import { render } from '@testing-library/react'; +import React from 'react'; +import * as stories from './backend_link.stories'; + +const { Example } = composeStories(stories); + +describe('BackendLink', () => { + it('renders', () => { + expect(() => render()).not.toThrowError(); + }); +}); diff --git a/x-pack/plugins/apm/public/components/shared/charts/latency_chart/latency_chart.stories.tsx b/x-pack/plugins/apm/public/components/shared/charts/latency_chart/latency_chart.stories.tsx index ad51e66f1959c..e1921aca8d9ef 100644 --- a/x-pack/plugins/apm/public/components/shared/charts/latency_chart/latency_chart.stories.tsx +++ b/x-pack/plugins/apm/public/components/shared/charts/latency_chart/latency_chart.stories.tsx @@ -20,18 +20,18 @@ import { ALERT_RULE_UUID, ALERT_RULE_NAME, ALERT_RULE_CATEGORY, + ALERT_RULE_CONSUMER, ALERT_RULE_PRODUCER, + SPACE_IDS, } from '@kbn/rule-data-utils'; -import { StoryContext } from '@storybook/react'; -import React, { ComponentType } from 'react'; -import { MemoryRouter, Route } from 'react-router-dom'; +import { Meta, Story } from '@storybook/react'; +import React from 'react'; +import { MemoryRouter } from 'react-router-dom'; import { KibanaContextProvider } from '../../../../../../../../src/plugins/kibana_react/public'; import { ENVIRONMENT_ALL } from '../../../../../common/environment_filter_values'; import { LatencyAggregationType } from '../../../../../common/latency_aggregation_types'; -import { - ApmPluginContext, - ApmPluginContextValue, -} from '../../../../context/apm_plugin/apm_plugin_context'; +import type { ApmPluginContextValue } from '../../../../context/apm_plugin/apm_plugin_context'; +import { MockApmPluginContextWrapper } from '../../../../context/apm_plugin/mock_apm_plugin_context'; import { APMServiceContext } from '../../../../context/apm_service/apm_service_context'; import { ChartPointerEventContextProvider } from '../../../../context/chart_pointer_event/chart_pointer_event_context'; import { MockUrlParamsContextProvider } from '../../../../context/url_params_context/mock_url_params_context_provider'; @@ -46,7 +46,7 @@ interface Args { latencyChartResponse: APIReturnType<'GET /internal/apm/services/{serviceName}/transactions/charts/latency'>; } -export default { +const stories: Meta = { title: 'shared/charts/LatencyChart', component: LatencyChart, argTypes: { @@ -57,7 +57,7 @@ export default { }, }, decorators: [ - (Story: ComponentType, { args }: StoryContext) => { + (StoryComponent, { args }) => { const { alertsResponse, latencyChartResponse } = args as Args; const serviceName = 'testService'; @@ -88,44 +88,46 @@ export default { const transactionType = `${Math.random()}`; // So we don't memoize return ( - - - - + + + - - - - - - - - - - - + + + + + + + + ); }, ], }; -export function Example(_args: Args) { +export default stories; + +export const Example: Story = () => { return ( ); -} +}; Example.args = { alertsResponse: { alerts: [ @@ -139,6 +141,7 @@ Example.args = { tags: ['apm', 'service.name:frontend-rum'], 'transaction.type': ['page-load'], [ALERT_RULE_PRODUCER]: ['apm'], + [ALERT_RULE_CONSUMER]: ['apm'], [ALERT_UUID]: ['af2ae371-df79-4fca-b0eb-a2dbd9478180'], [ALERT_RULE_UUID]: ['82e0ee40-c2f4-11eb-9a42-a9da66a1722f'], 'event.action': ['active'], @@ -149,9 +152,11 @@ Example.args = { [ALERT_START]: ['2021-06-02T04:00:00.000Z'], 'event.kind': ['state'], [ALERT_RULE_CATEGORY]: ['Latency threshold'], + [SPACE_IDS]: [], }, { [ALERT_RULE_TYPE_ID]: ['apm.transaction_duration'], + [ALERT_EVALUATION_VALUE]: [2001708.19], 'service.name': ['frontend-rum'], [ALERT_RULE_NAME]: ['Latency threshold | frontend-rum'], @@ -160,6 +165,7 @@ Example.args = { tags: ['apm', 'service.name:frontend-rum'], 'transaction.type': ['page-load'], [ALERT_RULE_PRODUCER]: ['apm'], + [ALERT_RULE_CONSUMER]: ['apm'], [ALERT_SEVERITY]: ['warning'], [ALERT_UUID]: ['af2ae371-df79-4fca-b0eb-a2dbd9478181'], [ALERT_RULE_UUID]: ['82e0ee40-c2f4-11eb-9a42-a9da66a1722f'], @@ -171,9 +177,11 @@ Example.args = { [ALERT_START]: ['2021-06-02T10:45:00.000Z'], 'event.kind': ['state'], [ALERT_RULE_CATEGORY]: ['Latency threshold'], + [SPACE_IDS]: [], }, { [ALERT_RULE_TYPE_ID]: ['apm.transaction_duration'], + [ALERT_EVALUATION_VALUE]: [2001708.19], 'service.name': ['frontend-rum'], [ALERT_RULE_NAME]: ['Latency threshold | frontend-rum'], @@ -182,6 +190,7 @@ Example.args = { tags: ['apm', 'service.name:frontend-rum'], 'transaction.type': ['page-load'], [ALERT_RULE_PRODUCER]: ['apm'], + [ALERT_RULE_CONSUMER]: ['apm'], [ALERT_SEVERITY]: ['critical'], [ALERT_UUID]: ['af2ae371-df79-4fca-b0eb-a2dbd9478182'], [ALERT_RULE_UUID]: ['82e0ee40-c2f4-11eb-9a42-a9da66a1722f'], @@ -193,6 +202,7 @@ Example.args = { [ALERT_START]: ['2021-06-02T16:50:00.000Z'], 'event.kind': ['state'], [ALERT_RULE_CATEGORY]: ['Latency threshold'], + [SPACE_IDS]: [], }, ], }, @@ -801,19 +811,24 @@ Example.args = { }, ], }, - previousPeriod: { latencyTimeseries: [] }, + previousPeriod: { latencyTimeseries: [], overallAvgDuration: null }, }, }; -export function NoData(_args: Args) { +export const NoData: Story = () => { return ( ); -} +}; NoData.args = { alertsResponse: { alerts: [] }, latencyChartResponse: { - currentPeriod: { latencyTimeseries: [] }, - previousPeriod: { latencyTimeseries: [] }, + anomalyTimeseries: { + jobId: 'apm-production-00aa-high_mean_transaction_duration', + anomalyScore: [], + anomalyBoundaries: [], + }, + currentPeriod: { latencyTimeseries: [], overallAvgDuration: null }, + previousPeriod: { latencyTimeseries: [], overallAvgDuration: null }, }, }; diff --git a/x-pack/plugins/apm/public/components/shared/charts/latency_chart/latency_chart.test.tsx b/x-pack/plugins/apm/public/components/shared/charts/latency_chart/latency_chart.test.tsx new file mode 100644 index 0000000000000..f5f7c87ed22de --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/charts/latency_chart/latency_chart.test.tsx @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { composeStories } from '@storybook/testing-react'; +import { render, waitFor } from '@testing-library/react'; +import React from 'react'; +import * as stories from './latency_chart.stories'; + +const { Example } = composeStories(stories); + +describe('LatencyChart', () => { + it('renders', async () => { + await waitFor(() => { + expect(() => render()).not.toThrowError(); + }); + }); +}); diff --git a/x-pack/plugins/apm/public/components/shared/service_link.stories.tsx b/x-pack/plugins/apm/public/components/shared/service_link.stories.tsx index f25838a3552f4..c50c1911afe79 100644 --- a/x-pack/plugins/apm/public/components/shared/service_link.stories.tsx +++ b/x-pack/plugins/apm/public/components/shared/service_link.stories.tsx @@ -31,5 +31,11 @@ export const Example: Story = (args) => { }; Example.args = { agentName: 'java', + query: { + environment: 'ENVIRONMENT_ALL', + kuery: '', + rangeFrom: 'now-15m', + rangeTo: 'now', + }, serviceName: 'opbeans-java', }; diff --git a/x-pack/plugins/apm/public/components/shared/service_link.test.tsx b/x-pack/plugins/apm/public/components/shared/service_link.test.tsx new file mode 100644 index 0000000000000..63311b306e6bb --- /dev/null +++ b/x-pack/plugins/apm/public/components/shared/service_link.test.tsx @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { composeStories } from '@storybook/testing-react'; +import { render } from '@testing-library/react'; +import React from 'react'; +import * as stories from './service_link.stories'; + +const { Example } = composeStories(stories); + +describe('ServiceLink', () => { + it('renders', () => { + expect(() => render()).not.toThrowError(); + }); +}); diff --git a/x-pack/plugins/apm/public/components/shared/suggestions_select/suggestions_select.test.tsx b/x-pack/plugins/apm/public/components/shared/suggestions_select/suggestions_select.test.tsx index b1fce1c439f32..629a3f3df47f7 100644 --- a/x-pack/plugins/apm/public/components/shared/suggestions_select/suggestions_select.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/suggestions_select/suggestions_select.test.tsx @@ -6,14 +6,16 @@ */ import { composeStories } from '@storybook/testing-react'; -import { render } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; import React from 'react'; import * as stories from './suggestions_select.stories'; const { Example } = composeStories(stories); describe('SuggestionsSelect', () => { - it('renders', () => { - expect(() => render()).not.toThrowError(); + it('renders', async () => { + render(); + + expect(await screen.findByRole('combobox')).toBeInTheDocument(); }); }); From f5463ceaeb8553c130f331cdb9c60bf06685dbc1 Mon Sep 17 00:00:00 2001 From: Gloria Hornero Date: Tue, 26 Oct 2021 14:26:49 +0200 Subject: [PATCH 27/58] fixes alignment issue (#115948) --- .../rules/all/exceptions/exceptions_overflow_display.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/exceptions/exceptions_overflow_display.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/exceptions/exceptions_overflow_display.tsx index d22d338d6f50a..d3219cc86d0e7 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/exceptions/exceptions_overflow_display.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/exceptions/exceptions_overflow_display.tsx @@ -27,7 +27,10 @@ interface OverflowListComponentProps { } const ExceptionOverflowWrapper = styled(EuiBadgeGroup)` - width: 100%; + .euiBadgeGroup__item { + display: block; + width: 100%; + } `; const ExceptionOverflowPopoverWrapper = styled(EuiBadgeGroup)` @@ -87,7 +90,6 @@ const ExceptionOverflowDisplayComponent = ({ Date: Tue, 26 Oct 2021 14:02:43 +0100 Subject: [PATCH 28/58] [ML] Fix errors from annotations searches when event mapping is incorrect (#116101) * [ML] Fix errors from annotations searches when event mapping is incorrect * [ML] Delete tests on annotation errors due to incorrect mappings * [ML] Jest test fix and remove unused servuce method * [ML] type fix * [ML] Edits following review --- x-pack/plugins/ml/common/types/annotations.ts | 21 +---- .../annotations_table/annotations_table.js | 56 +++++------- .../public/application/explorer/explorer.js | 7 +- .../application/explorer/explorer_utils.js | 18 +--- .../reducers/explorer_reducer/state.ts | 2 - .../services/ml_api_service/annotations.ts | 8 +- .../timeseries_chart_with_tooltip.tsx | 7 -- .../timeseriesexplorer/timeseriesexplorer.js | 3 - .../get_focus_data.ts | 13 +-- .../__mocks__/get_annotations_request.json | 1 + .../models/annotation_service/annotation.ts | 38 ++------ .../apps/ml/anomaly_detection/annotations.ts | 51 ----------- .../functional/services/ml/test_resources.ts | 86 ------------------- 13 files changed, 37 insertions(+), 274 deletions(-) diff --git a/x-pack/plugins/ml/common/types/annotations.ts b/x-pack/plugins/ml/common/types/annotations.ts index 6234444322a5b..dbc146c1175d8 100644 --- a/x-pack/plugins/ml/common/types/annotations.ts +++ b/x-pack/plugins/ml/common/types/annotations.ts @@ -118,26 +118,8 @@ export function isAnnotations(arg: any): arg is Annotations { return arg.every((d: Annotation) => isAnnotation(d)); } -export interface FieldToBucket { - field: string; - missing?: string | number; -} - -export interface FieldToBucketResult { - key: string; - doc_count: number; -} - -export interface TermAggregationResult { - doc_count_error_upper_bound: number; - sum_other_doc_count: number; - buckets: FieldToBucketResult[]; -} - -export type EsAggregationResult = Record; - export interface GetAnnotationsResponse { - aggregations?: EsAggregationResult; + totalCount: number; annotations: Record; error?: string; success: boolean; @@ -145,6 +127,5 @@ export interface GetAnnotationsResponse { export interface AnnotationsTable { annotationsData: Annotations; - aggregations: EsAggregationResult; error?: string; } diff --git a/x-pack/plugins/ml/public/application/components/annotations/annotations_table/annotations_table.js b/x-pack/plugins/ml/public/application/components/annotations/annotations_table/annotations_table.js index 26fddcc6394b0..98dc5f4204c32 100644 --- a/x-pack/plugins/ml/public/application/components/annotations/annotations_table/annotations_table.js +++ b/x-pack/plugins/ml/public/application/components/annotations/annotations_table/annotations_table.js @@ -81,7 +81,6 @@ class AnnotationsTableUI extends Component { super(props); this.state = { annotations: [], - aggregations: null, isLoading: false, queryText: `event:(${ANNOTATION_EVENT_USER} or ${ANNOTATION_EVENT_DELAYED_DATA})`, searchError: undefined, @@ -115,18 +114,11 @@ class AnnotationsTableUI extends Component { earliestMs: null, latestMs: null, maxAnnotations: ANNOTATIONS_TABLE_DEFAULT_QUERY_SIZE, - fields: [ - { - field: 'event', - missing: ANNOTATION_EVENT_USER, - }, - ], }) .toPromise() .then((resp) => { this.setState((prevState, props) => ({ annotations: resp.annotations[props.jobs[0].job_id] || [], - aggregations: resp.aggregations, errorMessage: undefined, isLoading: false, jobId: props.jobs[0].job_id, @@ -570,41 +562,35 @@ class AnnotationsTableUI extends Component { onMouseLeave: () => this.onMouseLeaveRow(), }; }; - let filterOptions = []; - const aggregations = this.props.aggregations ?? this.state.aggregations; - if (aggregations) { - const buckets = aggregations.event.buckets; - let foundUser = false; - let foundDelayedData = false; - - buckets.forEach((bucket) => { - if (bucket.key === ANNOTATION_EVENT_USER) { - foundUser = true; - } - if (bucket.key === ANNOTATION_EVENT_DELAYED_DATA) { - foundDelayedData = true; - } - }); - const adjustedBuckets = []; - if (!foundUser) { - adjustedBuckets.push({ key: ANNOTATION_EVENT_USER, doc_count: 0 }); - } - if (!foundDelayedData) { - adjustedBuckets.push({ key: ANNOTATION_EVENT_DELAYED_DATA, doc_count: 0 }); + + // Build the options to show in the Event type filter. + // Do not try and run a search using a terms agg on the event field + // because in 7.9 this field was incorrectly mapped as a text rather than keyword. + + // Always display options for user and delayed data types. + const countsByEvent = { + [ANNOTATION_EVENT_USER]: 0, + [ANNOTATION_EVENT_DELAYED_DATA]: 0, + }; + annotations.forEach((annotation) => { + // Default to user type for annotations created in early releases which didn't have an event field + const event = annotation.event ?? ANNOTATION_EVENT_USER; + if (countsByEvent[event] === undefined) { + countsByEvent[event] = 0; } + countsByEvent[event]++; + }); - filterOptions = [...adjustedBuckets, ...buckets]; - } const filters = [ { type: 'field_value_selection', field: 'event', name: 'Event', multiSelect: 'or', - options: filterOptions.map((field) => ({ - value: field.key, - name: field.key, - view: `${field.key} (${field.doc_count})`, + options: Object.entries(countsByEvent).map(([key, docCount]) => ({ + value: key, + name: key, + view: `${key} (${docCount})`, })), 'data-test-subj': 'mlAnnotationTableEventFilter', }, diff --git a/x-pack/plugins/ml/public/application/explorer/explorer.js b/x-pack/plugins/ml/public/application/explorer/explorer.js index daecf7585b3ea..7d08c0fc1756e 100644 --- a/x-pack/plugins/ml/public/application/explorer/explorer.js +++ b/x-pack/plugins/ml/public/application/explorer/explorer.js @@ -255,13 +255,9 @@ export class ExplorerUI extends React.Component { tableData, swimLaneSeverity, } = this.props.explorerState; - const { annotationsData, aggregations, error: annotationsError } = annotations; + const { annotationsData, totalCount: allAnnotationsCnt, error: annotationsError } = annotations; const annotationsCnt = Array.isArray(annotationsData) ? annotationsData.length : 0; - const allAnnotationsCnt = Array.isArray(aggregations?.event?.buckets) - ? aggregations.event.buckets.reduce((acc, v) => acc + v.doc_count, 0) - : annotationsCnt; - const badge = allAnnotationsCnt > annotationsCnt ? ( @@ -449,7 +445,6 @@ export class ExplorerUI extends React.Component { diff --git a/x-pack/plugins/ml/public/application/explorer/explorer_utils.js b/x-pack/plugins/ml/public/application/explorer/explorer_utils.js index ecf347e6b142f..af2b9b07a43fb 100644 --- a/x-pack/plugins/ml/public/application/explorer/explorer_utils.js +++ b/x-pack/plugins/ml/public/application/explorer/explorer_utils.js @@ -35,7 +35,6 @@ import { SWIMLANE_TYPE, VIEW_BY_JOB_LABEL, } from './explorer_constants'; -import { ANNOTATION_EVENT_USER } from '../../../common/constants/annotations'; // create new job objects based on standard job config objects // new job objects just contain job id, bucket span in seconds and a selected flag. @@ -437,10 +436,7 @@ export function loadOverallAnnotations(selectedJobs, interval, bounds) { } export function loadAnnotationsTableData(selectedCells, selectedJobs, interval, bounds) { - const jobIds = - selectedCells !== undefined && selectedCells.viewByFieldName === VIEW_BY_JOB_LABEL - ? selectedCells.lanes - : selectedJobs.map((d) => d.id); + const jobIds = getSelectionJobIds(selectedCells, selectedJobs); const timeRange = getSelectionTimeRange(selectedCells, interval, bounds); return new Promise((resolve) => { @@ -450,12 +446,6 @@ export function loadAnnotationsTableData(selectedCells, selectedJobs, interval, earliestMs: timeRange.earliestMs, latestMs: timeRange.latestMs, maxAnnotations: ANNOTATIONS_TABLE_DEFAULT_QUERY_SIZE, - fields: [ - { - field: 'event', - missing: ANNOTATION_EVENT_USER, - }, - ], }) .toPromise() .then((resp) => { @@ -463,7 +453,7 @@ export function loadAnnotationsTableData(selectedCells, selectedJobs, interval, const errorMessage = extractErrorMessage(resp.error); return resolve({ annotationsData: [], - aggregations: {}, + totalCount: 0, error: errorMessage !== '' ? errorMessage : undefined, }); } @@ -485,14 +475,14 @@ export function loadAnnotationsTableData(selectedCells, selectedJobs, interval, d.key = (i + 1).toString(); return d; }), - aggregations: resp.aggregations, + totalCount: resp.totalCount, }); }) .catch((resp) => { const errorMessage = extractErrorMessage(resp); return resolve({ annotationsData: [], - aggregations: {}, + totalCount: 0, error: errorMessage !== '' ? errorMessage : undefined, }); }); diff --git a/x-pack/plugins/ml/public/application/explorer/reducers/explorer_reducer/state.ts b/x-pack/plugins/ml/public/application/explorer/reducers/explorer_reducer/state.ts index 202a4389ef524..cfc9f076fbb3a 100644 --- a/x-pack/plugins/ml/public/application/explorer/reducers/explorer_reducer/state.ts +++ b/x-pack/plugins/ml/public/application/explorer/reducers/explorer_reducer/state.ts @@ -71,12 +71,10 @@ export function getExplorerDefaultState(): ExplorerState { overallAnnotations: { error: undefined, annotationsData: [], - aggregations: {}, }, annotations: { error: undefined, annotationsData: [], - aggregations: {}, }, anomalyChartsDataLoading: true, chartsData: getDefaultChartsData(), diff --git a/x-pack/plugins/ml/public/application/services/ml_api_service/annotations.ts b/x-pack/plugins/ml/public/application/services/ml_api_service/annotations.ts index f3f9e935a92c7..006b70934c71e 100644 --- a/x-pack/plugins/ml/public/application/services/ml_api_service/annotations.ts +++ b/x-pack/plugins/ml/public/application/services/ml_api_service/annotations.ts @@ -5,11 +5,7 @@ * 2.0. */ -import { - Annotation, - FieldToBucket, - GetAnnotationsResponse, -} from '../../../../common/types/annotations'; +import { Annotation, GetAnnotationsResponse } from '../../../../common/types/annotations'; import { http, http$ } from '../http_service'; import { basePath } from './index'; @@ -19,7 +15,6 @@ export const annotations = { earliestMs: number; latestMs: number; maxAnnotations: number; - fields?: FieldToBucket[]; detectorIndex?: number; entities?: any[]; }) { @@ -36,7 +31,6 @@ export const annotations = { earliestMs: number | null; latestMs: number | null; maxAnnotations: number; - fields?: FieldToBucket[]; detectorIndex?: number; entities?: any[]; }) { diff --git a/x-pack/plugins/ml/public/application/timeseriesexplorer/components/timeseries_chart/timeseries_chart_with_tooltip.tsx b/x-pack/plugins/ml/public/application/timeseriesexplorer/components/timeseries_chart/timeseries_chart_with_tooltip.tsx index 85530de2ea718..174ab8a682b5b 100644 --- a/x-pack/plugins/ml/public/application/timeseriesexplorer/components/timeseries_chart/timeseries_chart_with_tooltip.tsx +++ b/x-pack/plugins/ml/public/application/timeseriesexplorer/components/timeseries_chart/timeseries_chart_with_tooltip.tsx @@ -15,7 +15,6 @@ import { extractErrorMessage } from '../../../../../common/util/errors'; import { Annotation } from '../../../../../common/types/annotations'; import { useMlKibana, useNotifications } from '../../../contexts/kibana'; import { getBoundsRoundedToInterval } from '../../../util/time_buckets'; -import { ANNOTATION_EVENT_USER } from '../../../../../common/constants/annotations'; import { getControlsForDetector } from '../../get_controls_for_detector'; import { MlAnnotationUpdatesContext } from '../../../contexts/ml/ml_annotation_updates_context'; @@ -88,12 +87,6 @@ export const TimeSeriesChartWithTooltips: FC = earliestMs: searchBounds.min.valueOf(), latestMs: searchBounds.max.valueOf(), maxAnnotations: ANNOTATIONS_TABLE_DEFAULT_QUERY_SIZE, - fields: [ - { - field: 'event', - missing: ANNOTATION_EVENT_USER, - }, - ], detectorIndex, entities: nonBlankEntities, }); diff --git a/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js b/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js index 454bb0b489837..9b8770350909e 100644 --- a/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js +++ b/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer.js @@ -104,7 +104,6 @@ function getTimeseriesexplorerDefaultState() { entitiesLoading: false, entityValues: {}, focusAnnotationData: [], - focusAggregations: {}, focusAggregationInterval: {}, focusChartData: undefined, focusForecastData: undefined, @@ -935,7 +934,6 @@ export class TimeSeriesExplorer extends React.Component { focusAggregationInterval, focusAnnotationError, focusAnnotationData, - focusAggregations, focusChartData, focusForecastData, fullRefresh, @@ -1257,7 +1255,6 @@ export class TimeSeriesExplorer extends React.Component { detectors={detectors} jobIds={[this.props.selectedJobId]} annotations={focusAnnotationData} - aggregations={focusAggregations} isSingleMetricViewerLinkVisible={false} isNumberBadgeVisible={true} /> diff --git a/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer_utils/get_focus_data.ts b/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer_utils/get_focus_data.ts index cb1974afd5ed8..d4548a43f3f2b 100644 --- a/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer_utils/get_focus_data.ts +++ b/x-pack/plugins/ml/public/application/timeseriesexplorer/timeseriesexplorer_utils/get_focus_data.ts @@ -26,7 +26,6 @@ import { import { mlForecastService } from '../../services/forecast_service'; import { mlFunctionToESAggregation } from '../../../../common/util/job_utils'; import { GetAnnotationsResponse } from '../../../../common/types/annotations'; -import { ANNOTATION_EVENT_USER } from '../../../../common/constants/annotations'; import { aggregationTypeTransform } from '../../../../common/util/anomaly_utils'; export interface Interval { @@ -42,7 +41,6 @@ export interface FocusData { focusAnnotationError?: string; focusAnnotationData?: any[]; focusForecastData?: any; - focusAggregations?: any; } export function getFocusData( @@ -98,12 +96,6 @@ export function getFocusData( earliestMs: searchBounds.min.valueOf(), latestMs: searchBounds.max.valueOf(), maxAnnotations: ANNOTATIONS_TABLE_DEFAULT_QUERY_SIZE, - fields: [ - { - field: 'event', - missing: ANNOTATION_EVENT_USER, - }, - ], detectorIndex, entities: nonBlankEntities, }) @@ -111,7 +103,7 @@ export function getFocusData( catchError((resp) => of({ annotations: {}, - aggregations: {}, + totalCount: 0, error: extractErrorMessage(resp), success: false, } as GetAnnotationsResponse) @@ -168,7 +160,6 @@ export function getFocusData( if (annotations.error !== undefined) { refreshFocusData.focusAnnotationError = annotations.error; refreshFocusData.focusAnnotationData = []; - refreshFocusData.focusAggregations = {}; } else { refreshFocusData.focusAnnotationData = (annotations.annotations[selectedJob.job_id] ?? []) .sort((a, b) => { @@ -178,8 +169,6 @@ export function getFocusData( d.key = (i + 1).toString(); return d; }); - - refreshFocusData.focusAggregations = annotations.aggregations; } } diff --git a/x-pack/plugins/ml/server/models/annotation_service/__mocks__/get_annotations_request.json b/x-pack/plugins/ml/server/models/annotation_service/__mocks__/get_annotations_request.json index b91eb94c7fd7b..c65185a6172eb 100644 --- a/x-pack/plugins/ml/server/models/annotation_service/__mocks__/get_annotations_request.json +++ b/x-pack/plugins/ml/server/models/annotation_service/__mocks__/get_annotations_request.json @@ -1,6 +1,7 @@ { "index": ".ml-annotations-read", "size": 500, + "track_total_hits": true, "body": { "query": { "bool": { diff --git a/x-pack/plugins/ml/server/models/annotation_service/annotation.ts b/x-pack/plugins/ml/server/models/annotation_service/annotation.ts index fac35d6255e03..12b2954f63710 100644 --- a/x-pack/plugins/ml/server/models/annotation_service/annotation.ts +++ b/x-pack/plugins/ml/server/models/annotation_service/annotation.ts @@ -24,7 +24,6 @@ import { isAnnotations, getAnnotationFieldName, getAnnotationFieldValue, - EsAggregationResult, } from '../../../common/types/annotations'; import { JobId } from '../../../common/types/anomaly_detection_jobs'; @@ -35,36 +34,27 @@ interface EsResult { _id: string; } -export interface FieldToBucket { - field: string; - missing?: string | number; -} - export interface IndexAnnotationArgs { jobIds: string[]; earliestMs: number | null; latestMs: number | null; maxAnnotations: number; - fields?: FieldToBucket[]; detectorIndex?: number; entities?: any[]; event?: Annotation['event']; } -export interface AggTerm { - terms: FieldToBucket; -} - export interface GetParams { index: string; size: number; body: object; + track_total_hits: boolean; } export interface GetResponse { success: true; annotations: Record; - aggregations: EsAggregationResult; + totalCount: number; } export interface IndexParams { @@ -118,7 +108,6 @@ export function annotationProvider({ asInternalUser }: IScopedClusterClient) { earliestMs, latestMs, maxAnnotations, - fields, detectorIndex, entities, event, @@ -126,7 +115,7 @@ export function annotationProvider({ asInternalUser }: IScopedClusterClient) { const obj: GetResponse = { success: true, annotations: {}, - aggregations: {}, + totalCount: 0, }; const boolCriteria: object[] = []; @@ -215,18 +204,6 @@ export function annotationProvider({ asInternalUser }: IScopedClusterClient) { }); } - // Find unique buckets (e.g. events) from the queried annotations to show in dropdowns - const aggs: Record = {}; - if (fields) { - fields.forEach((fieldToBucket) => { - aggs[fieldToBucket.field] = { - terms: { - ...fieldToBucket, - }, - }; - }); - } - // Build should clause to further query for annotations in SMV // we want to show either the exact match with detector index and by/over/partition fields // OR annotations without any partition fields defined @@ -276,6 +253,7 @@ export function annotationProvider({ asInternalUser }: IScopedClusterClient) { const params: GetParams = { index: ML_ANNOTATIONS_INDEX_ALIAS_READ, size: maxAnnotations, + track_total_hits: true, body: { query: { bool: { @@ -295,7 +273,6 @@ export function annotationProvider({ asInternalUser }: IScopedClusterClient) { ...(shouldClauses ? { should: shouldClauses, minimum_should_match: 1 } : {}), }, }, - ...(fields ? { aggs } : {}), }, }; @@ -308,6 +285,9 @@ export function annotationProvider({ asInternalUser }: IScopedClusterClient) { throw new Error(`Annotations couldn't be retrieved from Elasticsearch.`); } + // @ts-expect-error incorrect search response type + obj.totalCount = body.hits.total.value; + // @ts-expect-error TODO fix search response types const docs: Annotations = get(body, ['hits', 'hits'], []).map((d: EsResult) => { // get the original source document and the document id, we need it @@ -321,10 +301,6 @@ export function annotationProvider({ asInternalUser }: IScopedClusterClient) { } as Annotation; }); - const aggregations = get(body, ['aggregations'], {}) as EsAggregationResult; - if (fields) { - obj.aggregations = aggregations; - } if (isAnnotations(docs) === false) { // No need to translate, this will not be exposed in the UI. throw new Error(`Annotations didn't pass integrity check.`); diff --git a/x-pack/test/functional/apps/ml/anomaly_detection/annotations.ts b/x-pack/test/functional/apps/ml/anomaly_detection/annotations.ts index 446f8a0549fc8..f0d0b898aefc1 100644 --- a/x-pack/test/functional/apps/ml/anomaly_detection/annotations.ts +++ b/x-pack/test/functional/apps/ml/anomaly_detection/annotations.ts @@ -262,56 +262,5 @@ export default function ({ getService }: FtrProviderContext) { await ml.jobAnnotations.assertAnnotationsRowMissing(annotationId); }); }); - - // FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/115849 - describe.skip('with errors', function () { - before(async () => { - // Points the read/write aliases of annotations to an index with wrong mappings - // so we can simulate errors when requesting annotations. - await ml.testResources.setupBrokenAnnotationsIndexState(jobId); - }); - - it('displays error on broken annotation index and recovers after fix', async () => { - await ml.testExecution.logTestStep('loads from job list row link'); - await ml.navigation.navigateToMl(); - await ml.navigation.navigateToJobManagement(); - - await ml.jobTable.waitForJobsToLoad(); - await ml.jobTable.filterWithSearchString(jobId, 1); - - await ml.jobTable.clickOpenJobInSingleMetricViewerButton(jobId); - await ml.commonUI.waitForMlLoadingIndicatorToDisappear(); - - await ml.testExecution.logTestStep( - 'should display the annotations section showing an error' - ); - await ml.singleMetricViewer.assertAnnotationsExists('error'); - - await ml.testExecution.logTestStep('should navigate to anomaly explorer'); - await ml.navigation.navigateToAnomalyExplorerViaSingleMetricViewer(); - - await ml.testExecution.logTestStep( - 'should display the annotations section showing an error' - ); - await ml.anomalyExplorer.assertAnnotationsPanelExists('error'); - - await ml.testExecution.logTestStep( - 'should display the annotations section without an error' - ); - // restores the aliases to point to the original working annotations index - // so we can run tests against successfully loaded annotations sections. - await ml.testResources.restoreAnnotationsIndexState(); - await ml.anomalyExplorer.refreshPage(); - await ml.anomalyExplorer.assertAnnotationsPanelExists('loaded'); - - await ml.testExecution.logTestStep('should navigate to single metric viewer'); - await ml.navigation.navigateToSingleMetricViewerViaAnomalyExplorer(); - - await ml.testExecution.logTestStep( - 'should display the annotations section without an error' - ); - await ml.singleMetricViewer.assertAnnotationsExists('loaded'); - }); - }); }); } diff --git a/x-pack/test/functional/services/ml/test_resources.ts b/x-pack/test/functional/services/ml/test_resources.ts index f1b2ef97e4e0d..65a892d124edb 100644 --- a/x-pack/test/functional/services/ml/test_resources.ts +++ b/x-pack/test/functional/services/ml/test_resources.ts @@ -24,7 +24,6 @@ export enum SavedObjectType { export type MlTestResourcesi = ProvidedType; export function MachineLearningTestResourcesProvider({ getService }: FtrProviderContext) { - const es = getService('es'); const kibanaServer = getService('kibanaServer'); const log = getService('log'); const supertest = getService('supertest'); @@ -188,91 +187,6 @@ export function MachineLearningTestResourcesProvider({ getService }: FtrProvider } }, - async setupBrokenAnnotationsIndexState(jobId: string) { - // Creates a temporary annotations index with unsupported mappings. - await es.indices.create({ - index: '.ml-annotations-6-wrong-mapping', - body: { - settings: { - number_of_shards: 1, - }, - mappings: { - properties: { - field1: { type: 'text' }, - }, - }, - }, - }); - - // Ingests an annotation that will cause dynamic mapping to pick up the wrong field type. - es.create({ - id: 'annotation_with_wrong_mapping', - index: '.ml-annotations-6-wrong-mapping', - body: { - annotation: 'Annotation with wrong mapping', - create_time: 1597393915910, - create_username: '_xpack', - timestamp: 1549756800000, - end_timestamp: 1549756800000, - job_id: jobId, - modified_time: 1597393915910, - modified_username: '_xpack', - type: 'annotation', - event: 'user', - detector_index: 0, - }, - }); - - // Points the read/write aliases for annotations to the broken annotations index - // so we can run tests against a state where annotation endpoints return errors. - await es.indices.updateAliases({ - body: { - actions: [ - { - add: { - index: '.ml-annotations-6-wrong-mapping', - alias: '.ml-annotations-read', - is_hidden: true, - }, - }, - { remove: { index: '.ml-annotations-6', alias: '.ml-annotations-read' } }, - { - add: { - index: '.ml-annotations-6-wrong-mapping', - alias: '.ml-annotations-write', - is_hidden: true, - }, - }, - { remove: { index: '.ml-annotations-6', alias: '.ml-annotations-write' } }, - ], - }, - }); - }, - - async restoreAnnotationsIndexState() { - // restore the original working state of pointing read/write aliases - // to the right annotations index. - await es.indices.updateAliases({ - body: { - actions: [ - { add: { index: '.ml-annotations-6', alias: '.ml-annotations-read', is_hidden: true } }, - { remove: { index: '.ml-annotations-6-wrong-mapping', alias: '.ml-annotations-read' } }, - { - add: { index: '.ml-annotations-6', alias: '.ml-annotations-write', is_hidden: true }, - }, - { - remove: { index: '.ml-annotations-6-wrong-mapping', alias: '.ml-annotations-write' }, - }, - ], - }, - }); - - // deletes the temporary annotations index with wrong mappings - await es.indices.delete({ - index: '.ml-annotations-6-wrong-mapping', - }); - }, - async updateSavedSearchRequestBody(body: object, indexPatternTitle: string): Promise { const indexPatternId = await this.getIndexPatternId(indexPatternTitle); if (indexPatternId === undefined) { From 063e30b6a858e697a01d932ef6a0f3839ef8099e Mon Sep 17 00:00:00 2001 From: Justin Kambic Date: Tue, 26 Oct 2021 09:59:01 -0400 Subject: [PATCH 29/58] [Uptime] Add tests for new waterfall components (#115856) * Add `aria-label`s for icon and icon buttons. * Fix typo. * Create test wrapper to help with testing context-reliant components. * Create tests for `WaterfallMarkerIcon` component. * Create tests for `WaterfallMarkerTrend` component. * Simplify test wrapper. Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../components/waterfall_marker_icon.test.tsx | 58 ++++++++ .../components/waterfall_marker_icon.tsx | 14 +- .../waterfall_marker_test_helper.tsx | 59 ++++++++ .../waterfall_marker_trend.test.tsx | 132 ++++++++++++++++++ .../components/waterfall_marker_trend.tsx | 8 +- 5 files changed, 266 insertions(+), 5 deletions(-) create mode 100644 x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_marker_icon.test.tsx create mode 100644 x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_marker_test_helper.tsx create mode 100644 x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_marker_trend.test.tsx diff --git a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_marker_icon.test.tsx b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_marker_icon.test.tsx new file mode 100644 index 0000000000000..7934d9878b435 --- /dev/null +++ b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_marker_icon.test.tsx @@ -0,0 +1,58 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { fireEvent, waitFor } from '@testing-library/dom'; +import { render } from '../../../../../lib/helper/rtl_helpers'; +import { WaterfallMarkerIcon } from './waterfall_marker_icon'; +import { TestWrapper } from './waterfall_marker_test_helper'; + +describe('', () => { + it('renders a dot icon when `field` is an empty string', () => { + const { getByLabelText } = render(); + expect(getByLabelText('An icon indicating that this marker has no field associated with it')); + }); + + it('renders an embeddable when opened', async () => { + const { getByLabelText, getByText } = render( + + + + ); + + const expandButton = getByLabelText( + 'Use this icon button to show metrics for this annotation marker.' + ); + + fireEvent.click(expandButton); + + await waitFor(() => { + getByText('Test Field'); + }); + }); +}); diff --git a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_marker_icon.tsx b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_marker_icon.tsx index 10c9189eca2bf..4bef5fb041520 100644 --- a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_marker_icon.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_marker_icon.tsx @@ -6,6 +6,7 @@ */ import React, { useState } from 'react'; +import { i18n } from '@kbn/i18n'; import { EuiButtonIcon, EuiIcon, EuiPopover } from '@elastic/eui'; import { WaterfallMarkerTrend } from './waterfall_marker_trend'; @@ -13,7 +14,15 @@ export function WaterfallMarkerIcon({ field, label }: { field: string; label: st const [isOpen, setIsOpen] = useState(false); if (!field) { - return ; + return ( + + ); } return ( @@ -25,6 +34,9 @@ export function WaterfallMarkerIcon({ field, label }: { field: string; label: st zIndex={100} button={ ( +
+

{title}

+
{appendTitle}
+
{reportType}
+
{JSON.stringify(attributes)}
+
+); + +export const TestWrapper = ({ + basePath, + activeStep, + children, +}: { + basePath: string; + activeStep?: JourneyStep; + children: JSX.Element; +}) => ( + ), + }, + }} + > + + {children} + + +); diff --git a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_marker_trend.test.tsx b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_marker_trend.test.tsx new file mode 100644 index 0000000000000..f77457aa6df7b --- /dev/null +++ b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_marker_trend.test.tsx @@ -0,0 +1,132 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { render } from '../../../../../lib/helper/rtl_helpers'; +import { WaterfallMarkerTrend } from './waterfall_marker_trend'; +import moment from 'moment'; +import { JourneyStep } from '../../../../../../common/runtime_types'; +import { TestWrapper } from './waterfall_marker_test_helper'; + +describe('', () => { + const mockDiff = jest.fn(); + + jest.spyOn(moment.prototype, 'diff').mockImplementation(mockDiff); + + let activeStep: JourneyStep | undefined; + beforeEach(() => { + activeStep = { + '@timestamp': '123', + _id: 'id', + synthetics: { + type: 'step/end', + step: { + index: 0, + name: 'test-name', + }, + }, + monitor: { + id: 'mon-id', + check_group: 'group', + timespan: { + gte: '1988-10-09T12:00:00.000Z', + lt: '1988-10-10T12:00:00.000Z', + }, + }, + }; + mockDiff.mockReturnValue(0); + }); + + const BASE_PATH = 'xyz'; + + it('supplies props', () => { + const { getByLabelText, getByText, getByRole } = render( + + + , + { + core: { + http: { + // @ts-expect-error incomplete implementation for testing purposes + basePath: { + get: () => BASE_PATH, + }, + }, + }, + } + ); + const heading = getByRole('heading'); + expect(heading.innerHTML).toEqual('test title'); + expect(getByLabelText('append title').innerHTML.indexOf(BASE_PATH)).not.toBe(-1); + expect(getByText('kpi-over-time')); + expect(getByLabelText('attributes').innerHTML.indexOf('0s')).not.toBe(-1); + expect(getByLabelText('attributes').innerHTML.indexOf('0h')).toBe(-1); + expect(getByLabelText('attributes').innerHTML.indexOf('0m')).toBe(-1); + expect(getByLabelText('attributes').innerHTML.indexOf('0d')).toBe(-1); + }); + + it('handles days', () => { + mockDiff.mockReturnValue(10); + const { getByLabelText } = render( + + + + ); + + const attributesText = getByLabelText('attributes').innerHTML; + + expect(attributesText.indexOf('480s')).toBe(-1); + expect(attributesText.indexOf('480h')).toBe(-1); + expect(attributesText.indexOf('480m')).toBe(-1); + expect(attributesText.indexOf('480d')).not.toBe(-1); + }); + + it('handles hours', () => { + mockDiff.mockReturnValueOnce(0); + mockDiff.mockReturnValue(10); + const { getByLabelText } = render( + + + + ); + + const attributesText = getByLabelText('attributes').innerHTML; + + expect(attributesText.indexOf('480s')).toBe(-1); + expect(attributesText.indexOf('480h')).not.toBe(-1); + expect(attributesText.indexOf('480m')).toBe(-1); + expect(attributesText.indexOf('480d')).toBe(-1); + }); + + it('handles minutes', () => { + mockDiff.mockReturnValueOnce(0); + mockDiff.mockReturnValueOnce(0); + mockDiff.mockReturnValue(10); + const { getByLabelText } = render( + + + + ); + + const attributesText = getByLabelText('attributes').innerHTML; + + expect(attributesText.indexOf('480s')).toBe(-1); + expect(attributesText.indexOf('480h')).toBe(-1); + expect(attributesText.indexOf('480m')).not.toBe(-1); + expect(attributesText.indexOf('480d')).toBe(-1); + }); + + it('returns null for missing active step', () => { + activeStep = undefined; + const { container } = render( + + + + ); + expect(container.innerHTML).toBe(''); + }); +}); diff --git a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_marker_trend.tsx b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_marker_trend.tsx index 6ff7835633914..1639e8a0d872c 100644 --- a/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_marker_trend.tsx +++ b/x-pack/plugins/uptime/public/components/monitor/synthetics/waterfall/components/waterfall_marker_trend.tsx @@ -9,8 +9,8 @@ import React from 'react'; import { EuiButton } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import moment from 'moment'; +import { useKibana } from '../../../../../../../../../src/plugins/kibana_react/public'; import { useUptimeStartPlugins } from '../../../../../contexts/uptime_startup_plugins_context'; -import { useUptimeSettingsContext } from '../../../../../contexts/uptime_settings_context'; import { AllSeries, createExploratoryViewUrl } from '../../../../../../../observability/public'; import { euiStyled } from '../../../../../../../../../src/plugins/kibana_react/common'; import { useWaterfallContext } from '../context/waterfall_chart'; @@ -40,9 +40,9 @@ const getLast48Intervals = (activeStep: JourneyStep) => { export function WaterfallMarkerTrend({ title, field }: { title: string; field: string }) { const { observability } = useUptimeStartPlugins(); - const EmbeddableExpVIew = observability!.ExploratoryViewEmbeddable; + const EmbeddableExpView = observability!.ExploratoryViewEmbeddable; - const { basePath } = useUptimeSettingsContext(); + const basePath = useKibana().services.http?.basePath?.get(); const { activeStep } = useWaterfallContext(); @@ -75,7 +75,7 @@ export function WaterfallMarkerTrend({ title, field }: { title: string; field: s return ( - From 7bd1452ec9468ff36f40cfa88ef81bb1591fb2af Mon Sep 17 00:00:00 2001 From: Josh Dover <1813008+joshdover@users.noreply.github.com> Date: Tue, 26 Oct 2021 16:29:03 +0200 Subject: [PATCH 30/58] [Fleet] Add data-test-subj to featured integration cards (#116277) --- .../sections/epm/screens/home/available_packages.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/home/available_packages.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/home/available_packages.tsx index 4f13a874532f1..f1d0717584e2e 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/home/available_packages.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/home/available_packages.tsx @@ -231,6 +231,7 @@ export const AvailablePackages: React.FC = memo(() => { } href={addBasePath('/app/integrations/detail/endpoint/')} title={i18n.translate('xpack.fleet.featuredSecurityTitle', { @@ -246,6 +247,7 @@ export const AvailablePackages: React.FC = memo(() => { { } href={addBasePath('/app/enterprise_search/app_search')} title={i18n.translate('xpack.fleet.featuredSearchTitle', { From ff8e0f54e4821427ae621c448ae7817b5da3eb76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20S=C3=A1nchez?= Date: Tue, 26 Oct 2021 16:30:33 +0200 Subject: [PATCH 31/58] [Security Solutions][Endpoint] Hide headers when there is no data on exceptions list (#115526) * hide headers when there is no data or loading for trusted apps, event filters and host isolation exceptions list pages * Fix ts error * Fix integration test * Create a wrapper to set a margin-top in order to center content. Also fix a bug when switching between exceptions pages main menu wasn't updated. * Remove unused import * Update trusted apps text and changed testId for host isolation add button * Use flex instead margin to vertically center content * Remove wrong prop to fix ts types Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../components/administration_list_page.tsx | 25 +++++--- .../management_empty_state_wraper.tsx | 24 ++++++++ .../view/components/empty/index.tsx | 61 ++++++++++--------- .../view/event_filters_list_page.tsx | 1 + .../view/components/empty.tsx | 55 +++++++++-------- .../host_isolation_exceptions_list.test.tsx | 5 +- .../view/host_isolation_exceptions_list.tsx | 7 +-- .../view/components/empty_state.tsx | 61 ++++++++++--------- .../trusted_apps/view/trusted_apps_page.tsx | 3 +- .../apps/endpoint/trusted_apps_list.ts | 13 ++-- 10 files changed, 153 insertions(+), 102 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/management/components/management_empty_state_wraper.tsx diff --git a/x-pack/plugins/security_solution/public/management/components/administration_list_page.tsx b/x-pack/plugins/security_solution/public/management/components/administration_list_page.tsx index 37b1646319f3f..05912e764af2c 100644 --- a/x-pack/plugins/security_solution/public/management/components/administration_list_page.tsx +++ b/x-pack/plugins/security_solution/public/management/components/administration_list_page.tsx @@ -26,6 +26,7 @@ interface AdministrationListPageProps { actions?: React.ReactNode; restrictWidth?: boolean | number; hasBottomBorder?: boolean; + hideHeader?: boolean; headerBackComponent?: React.ReactNode; } @@ -37,6 +38,7 @@ export const AdministrationListPage: FC { @@ -63,15 +65,20 @@ export const AdministrationListPage: FC - - + {!hideHeader && ( + <> + + + + )} + { + return ( + + {children} + + ); +}); + +ManagementEmptyStateWraper.displayName = 'ManagementEmptyStateWraper'; diff --git a/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/empty/index.tsx b/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/empty/index.tsx index e27adc851dab7..36a7f32ce32dd 100644 --- a/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/empty/index.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/empty/index.tsx @@ -9,6 +9,7 @@ import React, { memo } from 'react'; import styled, { css } from 'styled-components'; import { EuiButton, EuiEmptyPrompt } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; +import { ManagementEmptyStateWraper } from '../../../../../components/management_empty_state_wraper'; const EmptyPrompt = styled(EuiEmptyPrompt)` ${() => css` @@ -22,37 +23,39 @@ export const EventFiltersListEmptyState = memo<{ isAddDisabled?: boolean; }>(({ onAdd, isAddDisabled = false }) => { return ( - + + + + + } + body={ - - } - body={ - - } - actions={ - - - - } - /> + } + actions={ + + + + } + /> + ); }); diff --git a/x-pack/plugins/security_solution/public/management/pages/event_filters/view/event_filters_list_page.tsx b/x-pack/plugins/security_solution/public/management/pages/event_filters/view/event_filters_list_page.tsx index db4e5dbb531b2..cebd70d2b69a3 100644 --- a/x-pack/plugins/security_solution/public/management/pages/event_filters/view/event_filters_list_page.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/event_filters/view/event_filters_list_page.tsx @@ -248,6 +248,7 @@ export const EventFiltersListPage = memo(() => { ) } + hideHeader={!doesDataExist} > {showFlyout && ( css` @@ -18,32 +19,38 @@ const EmptyPrompt = styled(EuiEmptyPrompt)` export const HostIsolationExceptionsEmptyState = memo<{ onAdd: () => void }>(({ onAdd }) => { return ( - + + + + + } + body={ - - } - body={ - - } - actions={ - - - - } - /> + } + actions={ + + + + } + /> + ); }); diff --git a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/host_isolation_exceptions_list.test.tsx b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/host_isolation_exceptions_list.test.tsx index 625da11a3644e..bf71cde6b6c76 100644 --- a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/host_isolation_exceptions_list.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/host_isolation_exceptions_list.test.tsx @@ -130,10 +130,11 @@ describe('When on the host isolation exceptions page', () => { beforeEach(() => { isPlatinumPlusMock.mockReturnValue(true); }); - it('should show the create flyout when the add button is pressed', () => { + it('should show the create flyout when the add button is pressed', async () => { render(); + await dataReceived(); act(() => { - userEvent.click(renderResult.getByTestId('hostIsolationExceptionsListAddButton')); + userEvent.click(renderResult.getByTestId('hostIsolationExceptionsEmptyStateAddButton')); }); expect(renderResult.getByTestId('hostIsolationExceptionsCreateEditFlyout')).toBeTruthy(); }); diff --git a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/host_isolation_exceptions_list.tsx b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/host_isolation_exceptions_list.tsx index 096575bab360c..d9b667947517e 100644 --- a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/host_isolation_exceptions_list.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/host_isolation_exceptions_list.tsx @@ -8,7 +8,7 @@ import { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types'; import { i18n } from '@kbn/i18n'; import React, { Dispatch, useCallback, useEffect } from 'react'; -import { EuiButton, EuiSpacer } from '@elastic/eui'; +import { EuiButton } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; import { useDispatch } from 'react-redux'; import { useHistory } from 'react-router-dom'; @@ -148,12 +148,13 @@ export const HostIsolationExceptionsList = () => { [] ) } + hideHeader={isLoading || listItems.length === 0} > {showFlyout && } {itemToDelete ? : null} - {listItems.length ? ( + {!isLoading && listItems.length ? ( { /> ) : null} - - items={listItems} ItemComponent={ArtifactEntryCard} diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/empty_state.tsx b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/empty_state.tsx index d4b02b6ac467a..d64d2fd7f634b 100644 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/empty_state.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/empty_state.tsx @@ -8,6 +8,7 @@ import React, { memo } from 'react'; import { EuiButton, EuiEmptyPrompt } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n/react'; +import { ManagementEmptyStateWraper } from '../../../../components/management_empty_state_wraper'; export const EmptyState = memo<{ onAdd: () => void; @@ -15,37 +16,39 @@ export const EmptyState = memo<{ isAddDisabled?: boolean; }>(({ onAdd, isAddDisabled = false }) => { return ( - + + + + + } + body={ - - } - body={ - - } - actions={ - - - - } - /> + } + actions={ + + + + } + /> + ); }); diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/trusted_apps_page.tsx b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/trusted_apps_page.tsx index 70698aec509ba..dcdf86e395619 100644 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/trusted_apps_page.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/trusted_apps_page.tsx @@ -171,7 +171,8 @@ export const TrustedAppsPage = memo(() => { } headerBackComponent={backButton} subtitle={ABOUT_TRUSTED_APPS} - actions={canDisplayContent() ? addButton : <>} + actions={addButton} + hideHeader={!canDisplayContent()} > diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/trusted_apps_list.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/trusted_apps_list.ts index 52fb9b8fc8599..9476d20ccb4b0 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/trusted_apps_list.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/trusted_apps_list.ts @@ -29,10 +29,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await endpointTestResources.unloadEndpointData(indexedData); }); - it('should show page title', async () => { - expect(await testSubjects.getVisibleText('header-page-title')).to.equal( - 'Trusted applications' - ); + it('should not show page title if there is no trusted app', async () => { + await testSubjects.missingOrFail('header-page-title'); }); it('should be able to add a new trusted app and remove it', async () => { @@ -56,6 +54,11 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { ); await pageObjects.common.closeToast(); + // Title is shown after adding an item + expect(await testSubjects.getVisibleText('header-page-title')).to.equal( + 'Trusted applications' + ); + // Remove it await pageObjects.trustedApps.clickCardActionMenu(); await testSubjects.click('deleteTrustedAppAction'); @@ -63,6 +66,8 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await testSubjects.waitForDeleted('trustedAppDeletionConfirm'); // We only expect one trusted app to have been visible await testSubjects.missingOrFail('trustedAppCard'); + // Header has gone because there is no trusted app + await testSubjects.missingOrFail('header-page-title'); }); }); }; From d59d0c92cad2331dfda39e69f8807ccd964c2dd9 Mon Sep 17 00:00:00 2001 From: Pete Hampton Date: Tue, 26 Oct 2021 15:35:10 +0100 Subject: [PATCH 32/58] [Telemetry] Collect trusted application policy scope. (#116281) --- x-pack/plugins/security_solution/server/lib/telemetry/filters.ts | 1 + x-pack/plugins/security_solution/server/lib/telemetry/helpers.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/x-pack/plugins/security_solution/server/lib/telemetry/filters.ts b/x-pack/plugins/security_solution/server/lib/telemetry/filters.ts index ee162fb76f95b..e0955c9508f87 100644 --- a/x-pack/plugins/security_solution/server/lib/telemetry/filters.ts +++ b/x-pack/plugins/security_solution/server/lib/telemetry/filters.ts @@ -140,6 +140,7 @@ export const exceptionListEventFields: AllowlistFields = { name: true, os_types: true, rule_version: true, + scope: true, }; /** diff --git a/x-pack/plugins/security_solution/server/lib/telemetry/helpers.ts b/x-pack/plugins/security_solution/server/lib/telemetry/helpers.ts index e72b0ba7d16fe..86d41f5040cc6 100644 --- a/x-pack/plugins/security_solution/server/lib/telemetry/helpers.ts +++ b/x-pack/plugins/security_solution/server/lib/telemetry/helpers.ts @@ -108,6 +108,7 @@ export const trustedApplicationToTelemetryEntry = (trustedApplication: TrustedAp updated_at: trustedApplication.updated_at, entries: trustedApplication.entries, os_types: [trustedApplication.os], + scope: trustedApplication.effectScope, } as ExceptionListItem; }; From 1581512816f6e74bd0763c2ebcb544b1ff18a683 Mon Sep 17 00:00:00 2001 From: Shivindera Singh Date: Tue, 26 Oct 2021 16:45:45 +0200 Subject: [PATCH 33/58] [AppServices] Disallow creating runtime and scripted fields with * in the name (#110081) (#116119) --- .../common/data_views/data_view.test.ts | 18 +++++++++++++++- .../data_views/common/data_views/data_view.ts | 11 +++++++++- .../components/field_editor/form_schema.ts | 13 +++++++++++- .../__snapshots__/field_editor.test.tsx.snap | 4 ++-- .../field_editor/field_editor.test.tsx | 21 +++++++++++++++++++ .../components/field_editor/field_editor.tsx | 17 ++++++++++----- .../kibana_utils/common/errors/errors.ts | 11 ++++++++++ .../runtime_field_editor.test.tsx | 2 +- x-pack/test/functional/apps/lens/formula.ts | 10 ++++----- 9 files changed, 91 insertions(+), 16 deletions(-) diff --git a/src/plugins/data_views/common/data_views/data_view.test.ts b/src/plugins/data_views/common/data_views/data_view.test.ts index 990b8fa4d5f35..ad66beb1daa6a 100644 --- a/src/plugins/data_views/common/data_views/data_view.test.ts +++ b/src/plugins/data_views/common/data_views/data_view.test.ts @@ -10,7 +10,7 @@ import { map, last } from 'lodash'; import { IndexPattern } from './data_view'; -import { DuplicateField } from '../../../kibana_utils/common'; +import { CharacterNotAllowedInField, DuplicateField } from '../../../kibana_utils/common'; import { IndexPatternField } from '../fields'; @@ -207,6 +207,14 @@ describe('IndexPattern', () => { expect(e).toBeInstanceOf(DuplicateField); } }); + + test('should not allow scripted field with * in name', async () => { + try { + await indexPattern.addScriptedField('test*123', "'new script'", 'string'); + } catch (e) { + expect(e).toBeInstanceOf(CharacterNotAllowedInField); + } + }); }); describe('setFieldFormat and deleteFieldFormaat', () => { @@ -267,6 +275,14 @@ describe('IndexPattern', () => { }); expect(indexPattern.toSpec()!.fields!.new_field).toBeUndefined(); }); + + test('should not allow runtime field with * in name', async () => { + try { + await indexPattern.addRuntimeField('test*123', runtime); + } catch (e) { + expect(e).toBeInstanceOf(CharacterNotAllowedInField); + } + }); }); describe('getFormatterForField', () => { diff --git a/src/plugins/data_views/common/data_views/data_view.ts b/src/plugins/data_views/common/data_views/data_view.ts index 9a597d5ae4471..8d3fcbf7d0ced 100644 --- a/src/plugins/data_views/common/data_views/data_view.ts +++ b/src/plugins/data_views/common/data_views/data_view.ts @@ -13,7 +13,7 @@ import { castEsToKbnFieldTypeName, ES_FIELD_TYPES, KBN_FIELD_TYPES } from '@kbn/ import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; import { FieldAttrs, FieldAttrSet, DataViewAttributes } from '..'; import type { RuntimeField } from '../types'; -import { DuplicateField } from '../../../kibana_utils/common'; +import { CharacterNotAllowedInField, DuplicateField } from '../../../kibana_utils/common'; import { IIndexPattern, IFieldType } from '../../common'; import { DataViewField, IIndexPatternFieldList, fieldList } from '../fields'; @@ -237,6 +237,10 @@ export class DataView implements IIndexPattern { const scriptedFields = this.getScriptedFields(); const names = _.map(scriptedFields, 'name'); + if (name.includes('*')) { + throw new CharacterNotAllowedInField('*', name); + } + if (_.includes(names, name)) { throw new DuplicateField(name); } @@ -358,6 +362,11 @@ export class DataView implements IIndexPattern { */ addRuntimeField(name: string, runtimeField: RuntimeField) { const existingField = this.getFieldByName(name); + + if (name.includes('*')) { + throw new CharacterNotAllowedInField('*', name); + } + if (existingField) { existingField.runtimeField = runtimeField; } else { diff --git a/src/plugins/index_pattern_field_editor/public/components/field_editor/form_schema.ts b/src/plugins/index_pattern_field_editor/public/components/field_editor/form_schema.ts index a722f277b8e23..979a1fdb1adc1 100644 --- a/src/plugins/index_pattern_field_editor/public/components/field_editor/form_schema.ts +++ b/src/plugins/index_pattern_field_editor/public/components/field_editor/form_schema.ts @@ -11,7 +11,7 @@ import { fieldValidators } from '../../shared_imports'; import { RUNTIME_FIELD_OPTIONS } from './constants'; -const { emptyField, numberGreaterThanField } = fieldValidators; +const { containsCharsField, emptyField, numberGreaterThanField } = fieldValidators; export const schema = { name: { @@ -29,6 +29,17 @@ export const schema = { ) ), }, + { + validator: containsCharsField({ + message: i18n.translate( + 'indexPatternFieldEditor.editor.form.validations.starCharacterNotAllowedValidationErrorMessage', + { + defaultMessage: 'The field cannot have * in the name.', + } + ), + chars: '*', + }), + }, ], }, type: { diff --git a/src/plugins/index_pattern_management/public/components/field_editor/__snapshots__/field_editor.test.tsx.snap b/src/plugins/index_pattern_management/public/components/field_editor/__snapshots__/field_editor.test.tsx.snap index 87aa20c4617c1..460c6c99786bf 100644 --- a/src/plugins/index_pattern_management/public/components/field_editor/__snapshots__/field_editor.test.tsx.snap +++ b/src/plugins/index_pattern_management/public/components/field_editor/__snapshots__/field_editor.test.tsx.snap @@ -546,7 +546,7 @@ exports[`FieldEditor should show conflict field warning 1`] = ` onClose={[Function]} /> { component.update(); expect(component).toMatchSnapshot(); }); + + it('should not allow field to have * in the name', async () => { + const testField = { + ...field, + name: 'test-field', + }; + const component = createComponentWithContext( + FieldEditor, + { + indexPattern, + spec: testField as unknown as IndexPatternField, + services, + }, + mockContext + ); + + await new Promise((resolve) => process.nextTick(resolve)); + (component.instance() as FieldEditor).onFieldChange('name', 'test*123'); + component.update(); + expect(component.html().includes('The field cannot have * in the name.')).toBe(true); + }); }); diff --git a/src/plugins/index_pattern_management/public/components/field_editor/field_editor.tsx b/src/plugins/index_pattern_management/public/components/field_editor/field_editor.tsx index 234da4f3bbe05..1c66f37dad141 100644 --- a/src/plugins/index_pattern_management/public/components/field_editor/field_editor.tsx +++ b/src/plugins/index_pattern_management/public/components/field_editor/field_editor.tsx @@ -267,7 +267,8 @@ export class FieldEditor extends PureComponent { const defaultValue: RuntimeField = { name: 'myRuntimeField', type: 'boolean', - script: { source: 'emit("hello"' }, + script: { source: 'emit("hello")' }, }; testBed = setup({ diff --git a/x-pack/test/functional/apps/lens/formula.ts b/x-pack/test/functional/apps/lens/formula.ts index 29caf422b7acd..2078836e2af8a 100644 --- a/x-pack/test/functional/apps/lens/formula.ts +++ b/x-pack/test/functional/apps/lens/formula.ts @@ -98,7 +98,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.lens.goToTimeRange(); await PageObjects.lens.switchToVisualization('lnsDatatable'); await PageObjects.lens.clickAddField(); - await fieldEditor.setName(`*' "'`); + await fieldEditor.setName(`ab' "'`); await fieldEditor.enableValue(); await fieldEditor.typeScript("emit('abc')"); await fieldEditor.save(); @@ -106,21 +106,21 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { await PageObjects.lens.configureDimension({ dimension: 'lnsDatatable_metrics > lns-empty-dimension', operation: 'unique_count', - field: `*`, + field: `ab`, keepOpen: true, }); await PageObjects.lens.switchToFormula(); - await PageObjects.lens.expectFormulaText(`unique_count('*\\' "\\'')`); + await PageObjects.lens.expectFormulaText(`unique_count('ab\\' "\\'')`); await PageObjects.lens.typeFormula('unique_count('); const input = await find.activeElement(); - await input.type('*'); + await input.type('ab'); await input.pressKeys(browser.keys.ENTER); await PageObjects.common.sleep(100); - await PageObjects.lens.expectFormulaText(`unique_count('*\\' "\\'')`); + await PageObjects.lens.expectFormulaText(`unique_count('ab\\' "\\'')`); }); it('should persist a broken formula on close', async () => { From 4b9c3da31f2f453c91ceecad2e5a59ce12719320 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yulia=20=C4=8Cech?= <6585477+yuliacech@users.noreply.github.com> Date: Tue, 26 Oct 2021 16:47:12 +0200 Subject: [PATCH 34/58] [ILM] Removed freeze action from Cold phase (#116160) * [ILM] Removed the freeze action from ILM, added a clean up to the serializer, deleted freeze from the Console autocomplete * [ILM] Removed i18n strings for freeze action Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../json/overrides/ilm.put_lifecycle.json | 10 ++-- .../index_lifecycle_management/README.md | 1 - .../features/searchable_snapshots.helpers.ts | 2 - .../features/searchable_snapshots.test.ts | 4 +- .../policy_serialization.test.ts | 2 - .../helpers/actions/freeze_actions.ts | 18 ------- .../helpers/actions/index.ts | 1 - .../helpers/actions/phases.ts | 2 - .../common/types/policies.ts | 1 - .../public/application/constants/ui_metric.ts | 1 - .../phases/cold_phase/cold_phase.tsx | 4 -- .../phases/shared_fields/freeze_field.tsx | 47 ------------------- .../components/phases/shared_fields/index.ts | 2 - .../searchable_snapshot_field.tsx | 2 +- .../form/configuration_context.tsx | 2 +- .../sections/edit_policy/form/deserializer.ts | 2 - .../form/deserializer_and_serializer.test.ts | 45 ++++++++++-------- .../sections/edit_policy/form/schema.ts | 12 ----- .../edit_policy/form/serializer/serializer.ts | 6 +-- .../application/sections/edit_policy/types.ts | 2 - .../application/services/ui_metric.test.ts | 17 ------- .../public/application/services/ui_metric.ts | 5 -- .../translations/translations/ja-JP.json | 4 -- .../translations/translations/zh-CN.json | 4 -- 24 files changed, 35 insertions(+), 161 deletions(-) delete mode 100644 x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/actions/freeze_actions.ts delete mode 100644 x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/freeze_field.tsx diff --git a/src/plugins/console/server/lib/spec_definitions/json/overrides/ilm.put_lifecycle.json b/src/plugins/console/server/lib/spec_definitions/json/overrides/ilm.put_lifecycle.json index 64014adc86e19..7648ab48621d5 100644 --- a/src/plugins/console/server/lib/spec_definitions/json/overrides/ilm.put_lifecycle.json +++ b/src/plugins/console/server/lib/spec_definitions/json/overrides/ilm.put_lifecycle.json @@ -31,7 +31,7 @@ "forcemerge": { "max_num_segments": 1 } - } + } }, "min_age": "1d", "actions": { @@ -69,7 +69,6 @@ "set_priority": { "priority": 0 }, - "freeze": {}, "allocate": { "number_of_replicas": 1, "include": { @@ -85,14 +84,13 @@ "_ip": "" } } - } + } }, "min_age": "1d", "actions": { "set_priority": { "priority": 0 }, - "freeze": {}, "unfollow": {}, "allocate": { "number_of_replicas": 1, @@ -123,7 +121,7 @@ "max_docs": 1000, "max_size": "5gb" } - } + } }, "min_age": "1d", "actions": { @@ -154,4 +152,4 @@ } } } -} \ No newline at end of file +} diff --git a/x-pack/plugins/index_lifecycle_management/README.md b/x-pack/plugins/index_lifecycle_management/README.md index 28b2a4637da89..35c2aa063ec23 100644 --- a/x-pack/plugins/index_lifecycle_management/README.md +++ b/x-pack/plugins/index_lifecycle_management/README.md @@ -34,7 +34,6 @@ PUT /_ilm/policy/full "cold" : { "min_age" : "30s", "actions" : { - "freeze": {} } }, "delete" : { diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/features/searchable_snapshots.helpers.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/features/searchable_snapshots.helpers.ts index cdb5dc16d1964..23b64c3dade19 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/features/searchable_snapshots.helpers.ts +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/features/searchable_snapshots.helpers.ts @@ -7,7 +7,6 @@ import { createForceMergeActions, - createFreezeActions, createMinAgeActions, createReadonlyActions, createRolloverActions, @@ -47,7 +46,6 @@ export const setupSearchableSnapshotsTestBed = async (args?: { cold: { ...createMinAgeActions(testBed, 'cold'), ...createSearchableSnapshotActions(testBed, 'cold'), - ...createFreezeActions(testBed, 'cold'), ...createReadonlyActions(testBed, 'cold'), }, frozen: { diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/features/searchable_snapshots.test.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/features/searchable_snapshots.test.ts index f6b8276938daf..a620f6e1268be 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/features/searchable_snapshots.test.ts +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/features/searchable_snapshots.test.ts @@ -33,7 +33,7 @@ describe(' searchable snapshots', () => { component.update(); }); - test('enabling searchable snapshot should hide force merge, freeze, readonly and shrink in subsequent phases', async () => { + test('enabling searchable snapshot should hide force merge, readonly and shrink in subsequent phases', async () => { const { actions } = testBed; await actions.togglePhase('warm'); @@ -43,7 +43,6 @@ describe(' searchable snapshots', () => { expect(actions.warm.shrinkExists()).toBeTruthy(); expect(actions.warm.readonlyExists()).toBeTruthy(); expect(actions.cold.searchableSnapshotsExists()).toBeTruthy(); - expect(actions.cold.freezeExists()).toBeTruthy(); expect(actions.cold.readonlyExists()).toBeTruthy(); await actions.hot.setSearchableSnapshot('my-repo'); @@ -53,7 +52,6 @@ describe(' searchable snapshots', () => { expect(actions.warm.readonlyExists()).toBeFalsy(); // searchable snapshot in cold is still visible expect(actions.cold.searchableSnapshotsExists()).toBeTruthy(); - expect(actions.cold.freezeExists()).toBeFalsy(); expect(actions.cold.readonlyExists()).toBeFalsy(); }); diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/serialization/policy_serialization.test.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/serialization/policy_serialization.test.ts index 7a4d1f7efca63..be196a377edb4 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/serialization/policy_serialization.test.ts +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/edit_policy/serialization/policy_serialization.test.ts @@ -408,7 +408,6 @@ describe(' serialization', () => { await actions.cold.setDataAllocation('node_attrs'); await actions.cold.setSelectedNodeAttribute('test:123'); await actions.cold.setReplicas('123'); - await actions.cold.setFreeze(); await actions.cold.toggleReadonly(); await actions.cold.setIndexPriority('123'); @@ -428,7 +427,6 @@ describe(' serialization', () => { "test": "123", }, }, - "freeze": Object {}, "readonly": Object {}, "set_priority": Object { "priority": 123, diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/actions/freeze_actions.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/actions/freeze_actions.ts deleted file mode 100644 index ad3d9d3bfbcb8..0000000000000 --- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/actions/freeze_actions.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { TestBed } from '@kbn/test/jest'; -import { Phase } from '../../../../common/types'; -import { createFormToggleAction } from './form_toggle_action'; - -export const createFreezeActions = (testBed: TestBed, phase: Phase) => { - const { exists } = testBed; - return { - setFreeze: createFormToggleAction(testBed, `${phase}-freezeSwitch`), - freezeExists: (): boolean => exists(`${phase}-freezeSwitch`), - }; -}; diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/actions/index.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/actions/index.ts index 528e818e8a7da..f2579031dbad9 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/actions/index.ts +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/actions/index.ts @@ -21,7 +21,6 @@ export { createForceMergeActions } from './forcemerge_actions'; export { createReadonlyActions } from './readonly_actions'; export { createIndexPriorityActions } from './index_priority_actions'; export { createShrinkActions } from './shrink_actions'; -export { createFreezeActions } from './freeze_actions'; export { createHotPhaseActions, createWarmPhaseActions, diff --git a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/actions/phases.ts b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/actions/phases.ts index 18cc0f01ca06c..7f07480cc248d 100644 --- a/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/actions/phases.ts +++ b/x-pack/plugins/index_lifecycle_management/__jest__/client_integration/helpers/actions/phases.ts @@ -15,7 +15,6 @@ import { createMinAgeActions, createNodeAllocationActions, createReplicasAction, - createFreezeActions, createSnapshotPolicyActions, } from './'; @@ -49,7 +48,6 @@ export const createColdPhaseActions = (testBed: TestBed) => { ...createMinAgeActions(testBed, 'cold'), ...createReplicasAction(testBed, 'cold'), ...createReadonlyActions(testBed, 'cold'), - ...createFreezeActions(testBed, 'cold'), ...createIndexPriorityActions(testBed, 'cold'), ...createNodeAllocationActions(testBed, 'cold'), ...createSearchableSnapshotActions(testBed, 'cold'), diff --git a/x-pack/plugins/index_lifecycle_management/common/types/policies.ts b/x-pack/plugins/index_lifecycle_management/common/types/policies.ts index b9922a0d59459..085179f14913d 100644 --- a/x-pack/plugins/index_lifecycle_management/common/types/policies.ts +++ b/x-pack/plugins/index_lifecycle_management/common/types/policies.ts @@ -134,7 +134,6 @@ export interface SerializedColdPhase extends SerializedPhase { export interface SerializedFrozenPhase extends SerializedPhase { actions: { - freeze?: {}; allocate?: AllocateAction; set_priority?: { priority: number | null; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/constants/ui_metric.ts b/x-pack/plugins/index_lifecycle_management/public/application/constants/ui_metric.ts index aed3aa455b651..e1a316eda594f 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/constants/ui_metric.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/constants/ui_metric.ts @@ -17,6 +17,5 @@ export const UIM_POLICY_DETACH_INDEX: string = 'policy_detach_index'; export const UIM_CONFIG_COLD_PHASE: string = 'config_cold_phase'; export const UIM_CONFIG_WARM_PHASE: string = 'config_warm_phase'; export const UIM_CONFIG_SET_PRIORITY: string = 'config_set_priority'; -export const UIM_CONFIG_FREEZE_INDEX: string = 'config_freeze_index'; export const UIM_INDEX_RETRY_STEP: string = 'index_retry_step'; export const UIM_EDIT_CLICK: string = 'edit_click'; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/cold_phase.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/cold_phase.tsx index 648aebf8118de..58f8544174044 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/cold_phase.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/cold_phase/cold_phase.tsx @@ -14,7 +14,6 @@ import { SearchableSnapshotField, IndexPriorityField, ReplicasField, - FreezeField, ReadonlyField, } from '../shared_fields'; @@ -36,9 +35,6 @@ export const ColdPhase: FunctionComponent = () => { }> - {/* Freeze section */} - {!isUsingSearchableSnapshotInHotPhase && } - {/* Readonly section */} {!isUsingSearchableSnapshotInHotPhase && } diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/freeze_field.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/freeze_field.tsx deleted file mode 100644 index 8db1829f03764..0000000000000 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/freeze_field.tsx +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import React, { FunctionComponent } from 'react'; -import { FormattedMessage } from '@kbn/i18n/react'; -import { EuiTextColor } from '@elastic/eui'; - -import { LearnMoreLink, ToggleFieldWithDescribedFormRow } from '../../'; - -interface Props { - phase: 'cold' | 'frozen'; -} - -export const FreezeField: FunctionComponent = ({ phase }) => { - return ( - - - - } - description={ - - {' '} - - - } - fullWidth - titleSize="xs" - switchProps={{ - 'data-test-subj': `${phase}-freezeSwitch`, - path: `_meta.${phase}.freezeEnabled`, - }} - > -
- - ); -}; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/index.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/index.ts index 91faf5c66df81..220f0bd8e941a 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/index.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/index.ts @@ -22,5 +22,3 @@ export { ReadonlyField } from './readonly_field'; export { ReplicasField } from './replicas_field'; export { IndexPriorityField } from './index_priority_field'; - -export { FreezeField } from './freeze_field'; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/searchable_snapshot_field/searchable_snapshot_field.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/searchable_snapshot_field/searchable_snapshot_field.tsx index 44459debc8f4d..0ce98351c9672 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/searchable_snapshot_field/searchable_snapshot_field.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/components/phases/shared_fields/searchable_snapshot_field/searchable_snapshot_field.tsx @@ -257,7 +257,7 @@ export const SearchableSnapshotField: FunctionComponent = ({ 'xpack.indexLifecycleMgmt.editPolicy.searchableSnapshotCalloutBody', { defaultMessage: - 'Force merge, shrink, read only, and freeze actions are not allowed when converting data to a fully-mounted index in this phase.', + 'Force merge, shrink and read only actions are not allowed when converting data to a fully-mounted index in this phase.', } )} data-test-subj="searchableSnapshotFieldsDisabledCallout" diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/configuration_context.tsx b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/configuration_context.tsx index 97952a3a212c7..5d506d6235f3f 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/configuration_context.tsx +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/configuration_context.tsx @@ -19,7 +19,7 @@ export interface Configuration { */ isUsingRollover: boolean; /** - * If this value is true, phases after hot cannot set shrink, forcemerge, freeze, or + * If this value is true, phases after hot cannot set shrink, forcemerge or * searchable_snapshot actions. * * See https://github.com/elastic/elasticsearch/blob/master/docs/reference/ilm/actions/ilm-searchable-snapshot.asciidoc. diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/deserializer.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/deserializer.ts index 1ce5b8aa7a717..73c15c864b2af 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/deserializer.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/deserializer.ts @@ -53,14 +53,12 @@ export const createDeserializer = cold: { enabled: Boolean(cold), dataTierAllocationType: determineDataTierAllocationType(cold?.actions), - freezeEnabled: Boolean(cold?.actions?.freeze), readonlyEnabled: Boolean(cold?.actions?.readonly), minAgeToMilliSeconds: -1, }, frozen: { enabled: Boolean(frozen), dataTierAllocationType: determineDataTierAllocationType(frozen?.actions), - freezeEnabled: Boolean(frozen?.actions?.freeze), minAgeToMilliSeconds: -1, }, delete: { diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/deserializer_and_serializer.test.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/deserializer_and_serializer.test.ts index 4391f398a6c5a..bd3cd3e08a5a9 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/deserializer_and_serializer.test.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/deserializer_and_serializer.test.ts @@ -85,7 +85,6 @@ const originalPolicy: SerializedPolicy = { include: { test: 'my_value' }, exclude: { test: 'my_value' }, }, - freeze: {}, readonly: {}, set_priority: { priority: 12, @@ -139,20 +138,34 @@ describe('deserializer and serializer', () => { serializer = createSerializer(cloneDeep(policy)); }); - it('preserves any unknown policy settings', () => { - const thisTestPolicy = cloneDeep(originalPolicy); - // We populate all levels of the policy with entries our UI does not know about - populateWithUnknownEntries(thisTestPolicy); - serializer = createSerializer(thisTestPolicy); + describe('unknown policy settings', function () { + it('preserves any unknown properties', () => { + const thisTestPolicy = cloneDeep(originalPolicy); + // We populate all levels of the policy with entries our UI does not know about + populateWithUnknownEntries(thisTestPolicy); + serializer = createSerializer(thisTestPolicy); - const copyOfThisTestPolicy = cloneDeep(thisTestPolicy); + const copyOfThisTestPolicy = cloneDeep(thisTestPolicy); - const _formInternal = deserializer(thisTestPolicy); - expect(serializer(_formInternal)).toEqual(thisTestPolicy); + const _formInternal = deserializer(thisTestPolicy); + expect(serializer(_formInternal)).toEqual(thisTestPolicy); - // Assert that the policy we passed in is unaltered after deserialization and serialization - expect(thisTestPolicy).not.toBe(copyOfThisTestPolicy); - expect(thisTestPolicy).toEqual(copyOfThisTestPolicy); + // Assert that the policy we passed in is unaltered after deserialization and serialization + expect(thisTestPolicy).not.toBe(copyOfThisTestPolicy); + expect(thisTestPolicy).toEqual(copyOfThisTestPolicy); + }); + + it('except freeze action in the cold phase', () => { + const policyWithoutFreeze = cloneDeep(originalPolicy); + + const policyWithFreeze = cloneDeep(policyWithoutFreeze); + // add a freeze action to the cold phase + policyWithFreeze.phases.cold!.actions!.freeze = {}; + serializer = createSerializer(policyWithFreeze); + + const _formInternal = deserializer(policyWithFreeze); + expect(serializer(_formInternal)).toEqual(policyWithoutFreeze); + }); }); it('removes all phases if they were disabled in the form', () => { @@ -240,14 +253,6 @@ describe('deserializer and serializer', () => { expect(result.phases.cold!.actions.set_priority).toBeUndefined(); }); - it('removes freeze setting in the cold phase if it is disabled in the form', () => { - formInternal._meta.cold.freezeEnabled = false; - - const result = serializer(formInternal); - - expect(result.phases.cold!.actions.freeze).toBeUndefined(); - }); - it('removes node attribute allocation when it is not selected in the form', () => { // Change from 'node_attrs' to 'node_roles' formInternal._meta.cold.dataTierAllocationType = 'node_roles'; diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/schema.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/schema.ts index 24112cf4725d2..2870b41d71783 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/schema.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/schema.ts @@ -248,12 +248,6 @@ export const getSchema = (isCloudEnabled: boolean): FormSchema => ({ { defaultMessage: 'Activate cold phase' } ), }, - freezeEnabled: { - defaultValue: false, - label: i18n.translate('xpack.indexLifecycleMgmt.coldPhase.freezeIndexLabel', { - defaultMessage: 'Freeze index', - }), - }, readonlyEnabled: { defaultValue: false, label: i18nTexts.editPolicy.readonlyEnabledFieldLabel, @@ -284,12 +278,6 @@ export const getSchema = (isCloudEnabled: boolean): FormSchema => ({ { defaultMessage: 'Activate frozen phase' } ), }, - freezeEnabled: { - defaultValue: false, - label: i18n.translate('xpack.indexLifecycleMgmt.frozePhase.freezeIndexLabel', { - defaultMessage: 'Freeze index', - }), - }, minAgeUnit: { defaultValue: 'd', }, diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/serializer/serializer.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/serializer/serializer.ts index 652f045922d4d..1bc97107b07a9 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/serializer/serializer.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/form/serializer/serializer.ts @@ -237,10 +237,10 @@ export const createSerializer = /** * COLD PHASE FREEZE + * The freeze action has been removed in 8.0. + * Clean up any policies that still have this action configured */ - if (_meta.cold.freezeEnabled) { - coldPhase.actions.freeze = coldPhase.actions.freeze ?? {}; - } else { + if (coldPhase.actions.freeze) { delete coldPhase.actions.freeze; } diff --git a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/types.ts b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/types.ts index 6c4d311d6177c..8e83f123a8fa2 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/types.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/sections/edit_policy/types.ts @@ -66,13 +66,11 @@ interface WarmPhaseMetaFields interface ColdPhaseMetaFields extends DataAllocationMetaFields, MinAgeField { enabled: boolean; - freezeEnabled: boolean; readonlyEnabled: boolean; } interface FrozenPhaseMetaFields extends DataAllocationMetaFields, MinAgeField { enabled: boolean; - freezeEnabled: boolean; } interface DeletePhaseMetaFields extends MinAgeField { diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.test.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.test.ts index 513fd122a0848..891109fd22027 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.test.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.test.ts @@ -9,7 +9,6 @@ import { UIM_CONFIG_COLD_PHASE, UIM_CONFIG_WARM_PHASE, UIM_CONFIG_SET_PRIORITY, - UIM_CONFIG_FREEZE_INDEX, defaultIndexPriority, } from '../constants/'; @@ -60,20 +59,4 @@ describe('getUiMetricsForPhases', () => { }) ).toEqual([UIM_CONFIG_WARM_PHASE, UIM_CONFIG_SET_PRIORITY]); }); - - test('gets freeze index', () => { - expect( - getUiMetricsForPhases({ - cold: { - min_age: '0ms', - actions: { - freeze: {}, - set_priority: { - priority: parseInt(defaultIndexPriority.cold, 10), - }, - }, - }, - }) - ).toEqual([UIM_CONFIG_COLD_PHASE, UIM_CONFIG_FREEZE_INDEX]); - }); }); diff --git a/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.ts b/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.ts index 0e68b389ef3da..fa9a8d44e9774 100644 --- a/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.ts +++ b/x-pack/plugins/index_lifecycle_management/public/application/services/ui_metric.ts @@ -17,7 +17,6 @@ import { UiCounterMetricType } from '@kbn/analytics'; import { UIM_APP_NAME, UIM_CONFIG_COLD_PHASE, - UIM_CONFIG_FREEZE_INDEX, UIM_CONFIG_SET_PRIORITY, UIM_CONFIG_WARM_PHASE, defaultIndexPriority, @@ -68,10 +67,6 @@ export function getUiMetricsForPhases(phases: Phases): string[] { ); }, }, - { - metric: UIM_CONFIG_FREEZE_INDEX, - isTracked: () => phases.cold && phases.cold.actions.freeze, - }, ]; return phaseUiMetrics.reduce((tracked: string[], { metric, isTracked }) => { diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index b3e77a39ef6b0..02d04b6b54881 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -12433,7 +12433,6 @@ "xpack.indexLifecycleMgmt.coldPhase.dataTier.noTiersAvailableTitle": "コールドティアに割り当てられているノードがありません", "xpack.indexLifecycleMgmt.coldPhase.dataTier.willUseFallbackTierDescription": "使用可能なコールドノードがない場合は、データが{tier}ティアに格納されます。", "xpack.indexLifecycleMgmt.coldPhase.dataTier.willUseFallbackTierTitle": "コールドティアに割り当てられているノードがありません", - "xpack.indexLifecycleMgmt.coldPhase.freezeIndexLabel": "インデックスを凍結", "xpack.indexLifecycleMgmt.common.dataTier.title": "データ割り当て", "xpack.indexLifecycleMgmt.confirmDelete.cancelButton": "キャンセル", "xpack.indexLifecycleMgmt.confirmDelete.deleteButton": "削除", @@ -12512,8 +12511,6 @@ "xpack.indexLifecycleMgmt.editPolicy.forceMerge.enableText": "強制結合", "xpack.indexLifecycleMgmt.editPolicy.forcemerge.numberOfSegmentsRequiredError": "セグメント数の評価が必要です。", "xpack.indexLifecycleMgmt.editPolicy.formErrorsMessage": "このページのエラーを修正してください。", - "xpack.indexLifecycleMgmt.editPolicy.freezeIndexExplanationText": "インデックスを読み取り専用にし、メモリー消費量を最小化します。", - "xpack.indexLifecycleMgmt.editPolicy.freezeText": "凍結", "xpack.indexLifecycleMgmt.editPolicy.frozenPhase.activateFrozenPhaseSwitchLabel": "フローズンフェーズをアクティブ化", "xpack.indexLifecycleMgmt.editPolicy.frozenPhase.frozenPhaseDescription": "長期間保持する場合はデータをフローズンティアに移動します。フローズンティアはデータを格納し、検索することもできる最も費用対効果が高い方法です。", "xpack.indexLifecycleMgmt.editPolicy.frozenPhase.frozenPhaseTitle": "フローズンフェーズ", @@ -12611,7 +12608,6 @@ "xpack.indexLifecycleMgmt.forcemerge.bestCompressionLabel": "格納されたフィールドを圧縮", "xpack.indexLifecycleMgmt.forcemerge.enableLabel": "データを強制結合", "xpack.indexLifecycleMgmt.forceMerge.numberOfSegmentsLabel": "セグメントの数", - "xpack.indexLifecycleMgmt.frozePhase.freezeIndexLabel": "インデックスを凍結", "xpack.indexLifecycleMgmt.hotPhase.enableRolloverLabel": "ロールオーバーを有効にする", "xpack.indexLifecycleMgmt.hotPhase.isUsingDefaultRollover": "推奨のデフォルト値を使用", "xpack.indexLifecycleMgmt.hotPhase.maximumAgeLabel": "最高年齢", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index dc43b75b5d1e3..ad7e3ea25c375 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -12596,7 +12596,6 @@ "xpack.indexLifecycleMgmt.coldPhase.dataTier.noTiersAvailableTitle": "没有分配到冷层的节点", "xpack.indexLifecycleMgmt.coldPhase.dataTier.willUseFallbackTierDescription": "如果没有可用的冷节点,数据将存储在{tier}层。", "xpack.indexLifecycleMgmt.coldPhase.dataTier.willUseFallbackTierTitle": "没有分配到冷层的节点", - "xpack.indexLifecycleMgmt.coldPhase.freezeIndexLabel": "冻结索引", "xpack.indexLifecycleMgmt.common.dataTier.title": "数据分配", "xpack.indexLifecycleMgmt.confirmDelete.cancelButton": "取消", "xpack.indexLifecycleMgmt.confirmDelete.deleteButton": "删除", @@ -12676,8 +12675,6 @@ "xpack.indexLifecycleMgmt.editPolicy.forceMerge.enableText": "强制合并", "xpack.indexLifecycleMgmt.editPolicy.forcemerge.numberOfSegmentsRequiredError": "必须指定分段数的值。", "xpack.indexLifecycleMgmt.editPolicy.formErrorsMessage": "请修复此页面上的错误。", - "xpack.indexLifecycleMgmt.editPolicy.freezeIndexExplanationText": "使索引只读,并最大限度减小其内存占用。", - "xpack.indexLifecycleMgmt.editPolicy.freezeText": "冻结", "xpack.indexLifecycleMgmt.editPolicy.frozenPhase.activateFrozenPhaseSwitchLabel": "激活冻结阶段", "xpack.indexLifecycleMgmt.editPolicy.frozenPhase.frozenPhaseDescription": "将数据移到冻层以长期保留。冻层提供最有成本效益的方法存储数据,并且仍能够搜索数据。", "xpack.indexLifecycleMgmt.editPolicy.frozenPhase.frozenPhaseTitle": "冻结阶段", @@ -12777,7 +12774,6 @@ "xpack.indexLifecycleMgmt.forcemerge.bestCompressionLabel": "压缩已存储字段", "xpack.indexLifecycleMgmt.forcemerge.enableLabel": "强制合并数据", "xpack.indexLifecycleMgmt.forceMerge.numberOfSegmentsLabel": "分段数目", - "xpack.indexLifecycleMgmt.frozePhase.freezeIndexLabel": "冻结索引", "xpack.indexLifecycleMgmt.hotPhase.enableRolloverLabel": "启用滚动更新", "xpack.indexLifecycleMgmt.hotPhase.isUsingDefaultRollover": "使用建议的默认值", "xpack.indexLifecycleMgmt.hotPhase.maximumAgeLabel": "最大存在时间", From 38026a8bd3e4aa5d432bed66df44a18b6ab7b099 Mon Sep 17 00:00:00 2001 From: Dan Panzarella Date: Tue, 26 Oct 2021 10:48:26 -0400 Subject: [PATCH 35/58] [Security Solution] Updating fleet action response data naming (#116214) --- .../common/endpoint/data_loaders/index_fleet_actions.ts | 9 +++++---- .../security_solution/common/endpoint/types/actions.ts | 9 ++++++++- .../server/endpoint/services/actions.ts | 2 +- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_fleet_actions.ts b/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_fleet_actions.ts index 34f57c0604fac..47448be2e0a92 100644 --- a/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_fleet_actions.ts +++ b/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_fleet_actions.ts @@ -66,10 +66,11 @@ export const indexFleetActionsForHost = async ( const actionResponse = fleetActionGenerator.generateResponse({ action_id: action.action_id, agent_id: agentId, - action_data: { - ...action.data, - // add ack to 4/5th of fleet response - ack: fleetActionGenerator.randomFloat() < 0.8 ? true : undefined, + action_response: { + endpoint: { + // add ack to 4/5th of fleet response + ack: fleetActionGenerator.randomFloat() < 0.8 ? true : undefined, + }, }, }); diff --git a/x-pack/plugins/security_solution/common/endpoint/types/actions.ts b/x-pack/plugins/security_solution/common/endpoint/types/actions.ts index d7ad417fc7d3f..2ac4c9e772ded 100644 --- a/x-pack/plugins/security_solution/common/endpoint/types/actions.ts +++ b/x-pack/plugins/security_solution/common/endpoint/types/actions.ts @@ -64,7 +64,12 @@ export interface LogsEndpointActionResponse { export interface EndpointActionData { command: ISOLATION_ACTIONS; comment?: string; - ack?: boolean; +} + +export interface FleetActionResponseData { + endpoint?: { + ack?: boolean; + }; } export interface EndpointAction { @@ -93,6 +98,8 @@ export interface EndpointActionResponse { completed_at: string; error?: string; action_data: EndpointActionData; + /* Response data from the Endpoint process -- only present in 7.16+ */ + action_response?: FleetActionResponseData; } export interface EndpointActivityLogAction { diff --git a/x-pack/plugins/security_solution/server/endpoint/services/actions.ts b/x-pack/plugins/security_solution/server/endpoint/services/actions.ts index 87455e6c578bc..6b44b7b3ce87a 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/actions.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/actions.ts @@ -148,7 +148,7 @@ const getActivityLog = async ({ }; const hasAckInResponse = (response: EndpointActionResponse): boolean => { - return typeof response.action_data.ack !== 'undefined'; + return response.action_response?.endpoint?.ack ?? false; }; // return TRUE if for given action_id/agent_id From d91bd98e973fe688aa96729e5e7799ab9f494f21 Mon Sep 17 00:00:00 2001 From: Melissa Alvarez Date: Tue, 26 Oct 2021 10:49:45 -0400 Subject: [PATCH 36/58] retain query language on step edit (#116227) --- .../configuration_step/configuration_step_form.tsx | 9 +++++++-- .../hooks/use_create_analytics_form/state.ts | 2 ++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx index 9b29d9108a1a1..df42c5b8eb1ca 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_creation/components/configuration_step/configuration_step_form.tsx @@ -127,6 +127,7 @@ export const ConfigurationStepForm: FC = ({ dependentVariable, includes, jobConfigQuery, + jobConfigQueryLanguage, jobConfigQueryString, jobType, modelMemoryLimit, @@ -150,14 +151,18 @@ export const ConfigurationStepForm: FC = ({ const [query, setQuery] = useState({ query: jobConfigQueryString ?? '', - language: SEARCH_QUERY_LANGUAGE.KUERY, + language: jobConfigQueryLanguage ?? SEARCH_QUERY_LANGUAGE.KUERY, }); const toastNotifications = getToastNotifications(); const setJobConfigQuery: ExplorationQueryBarProps['setSearchQuery'] = (update) => { if (update.query) { - setFormState({ jobConfigQuery: update.query, jobConfigQueryString: update.queryString }); + setFormState({ + jobConfigQuery: update.query, + jobConfigQueryLanguage: update.language, + jobConfigQueryString: update.queryString, + }); } setQuery({ query: update.queryString, language: update.language }); }; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts index e7a263520af31..0b2cb8fcfc716 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/hooks/use_create_analytics_form/state.ts @@ -79,6 +79,7 @@ export interface State { jobType: AnalyticsJobType; jobConfigQuery: any; jobConfigQueryString: string | undefined; + jobConfigQueryLanguage: string | undefined; lambda: number | undefined; lossFunction: string | undefined; lossFunctionParameter: number | undefined; @@ -162,6 +163,7 @@ export const getInitialState = (): State => ({ jobType: undefined, jobConfigQuery: defaultSearchQuery, jobConfigQueryString: undefined, + jobConfigQueryLanguage: undefined, lambda: undefined, lossFunction: undefined, lossFunctionParameter: undefined, From 3920918d3adfb3944725ce9e42915efab3330143 Mon Sep 17 00:00:00 2001 From: Ignacio Rivas Date: Tue, 26 Oct 2021 16:02:17 +0100 Subject: [PATCH 37/58] [Index Management] Remove freeze index action and api (#116110) * Remove freeze index action and api * Remove unused translations * Add test for unfreeze action * Fix tests * Fix tests --- .../helpers/test_subjects.ts | 1 + .../home/indices_tab.test.ts | 30 ++++++- .../__snapshots__/index_table.test.js.snap | 2 - .../common/constants/index.ts | 2 - .../common/constants/ui_metric.ts | 2 - .../index_actions_context_menu.container.js | 4 - .../index_actions_context_menu.js | 83 +------------------ .../public/application/services/api.ts | 12 --- .../public/application/services/index.ts | 1 - .../store/actions/freeze_indices.js | 33 -------- .../public/application/store/actions/index.js | 1 - .../api/indices/register_freeze_route.ts | 34 -------- .../api/indices/register_indices_routes.ts | 2 - .../translations/translations/ja-JP.json | 5 -- .../translations/translations/zh-CN.json | 8 -- .../index_management/indices.helpers.js | 3 - .../management/index_management/indices.js | 28 +------ 17 files changed, 33 insertions(+), 218 deletions(-) delete mode 100644 x-pack/plugins/index_management/public/application/store/actions/freeze_indices.js delete mode 100644 x-pack/plugins/index_management/server/routes/api/indices/register_freeze_route.ts diff --git a/x-pack/plugins/index_management/__jest__/client_integration/helpers/test_subjects.ts b/x-pack/plugins/index_management/__jest__/client_integration/helpers/test_subjects.ts index 8ee05bfa5d322..96775484e0733 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/helpers/test_subjects.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/helpers/test_subjects.ts @@ -59,4 +59,5 @@ export type TestSubjects = | 'templatesTab' | 'templateTable' | 'title' + | 'unfreezeIndexMenuButton' | 'viewButton'; diff --git a/x-pack/plugins/index_management/__jest__/client_integration/home/indices_tab.test.ts b/x-pack/plugins/index_management/__jest__/client_integration/home/indices_tab.test.ts index 5f5580d263285..79fe885820fae 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/home/indices_tab.test.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/home/indices_tab.test.ts @@ -159,9 +159,15 @@ describe('', () => { describe('index actions', () => { const indexName = 'testIndex'; + const indexMock = createNonDataStreamIndex(indexName); beforeEach(async () => { - httpRequestsMockHelpers.setLoadIndicesResponse([createNonDataStreamIndex(indexName)]); + httpRequestsMockHelpers.setLoadIndicesResponse([ + { + ...indexMock, + isFrozen: true, + }, + ]); httpRequestsMockHelpers.setReloadIndicesResponse({ indexNames: [indexName] }); testBed = await setup(); @@ -183,5 +189,27 @@ describe('', () => { // a reload server call also. expect(server.requests[requestsCount - 1].url).toBe(`${API_BASE_PATH}/indices/reload`); }); + + test('should be able to unfreeze a frozen index', async () => { + const { actions, exists } = testBed; + + httpRequestsMockHelpers.setReloadIndicesResponse([{ ...indexMock, isFrozen: false }]); + + // Open context menu + await actions.clickManageContextMenuButton(); + // Check that the unfreeze action exists for the current index and unfreeze it + expect(exists('unfreezeIndexMenuButton')).toBe(true); + await actions.clickContextMenuOption('unfreezeIndexMenuButton'); + + const requestsCount = server.requests.length; + expect(server.requests[requestsCount - 2].url).toBe(`${API_BASE_PATH}/indices/unfreeze`); + // After the index is unfrozen, we imediately do a reload. So we need to expect to see + // a reload server call also. + expect(server.requests[requestsCount - 1].url).toBe(`${API_BASE_PATH}/indices/reload`); + // Open context menu once again, since clicking an action will close it. + await actions.clickManageContextMenuButton(); + // The unfreeze action should not be present anymore + expect(exists('unfreezeIndexMenuButton')).toBe(false); + }); }); }); diff --git a/x-pack/plugins/index_management/__jest__/components/__snapshots__/index_table.test.js.snap b/x-pack/plugins/index_management/__jest__/components/__snapshots__/index_table.test.js.snap index f4f886dd7211c..68fb65ed352d1 100644 --- a/x-pack/plugins/index_management/__jest__/components/__snapshots__/index_table.test.js.snap +++ b/x-pack/plugins/index_management/__jest__/components/__snapshots__/index_table.test.js.snap @@ -108,7 +108,6 @@ Array [ "Refresh indices", "Clear indices cache", "Flush indices", - "Freeze indices", "Delete indices", ] `; @@ -134,7 +133,6 @@ Array [ "Refresh index", "Clear index cache", "Flush index", - "Freeze index", "Delete index", ] `; diff --git a/x-pack/plugins/index_management/common/constants/index.ts b/x-pack/plugins/index_management/common/constants/index.ts index 373044aef9d45..6641e6ef67c7d 100644 --- a/x-pack/plugins/index_management/common/constants/index.ts +++ b/x-pack/plugins/index_management/common/constants/index.ts @@ -24,8 +24,6 @@ export { UIM_INDEX_FLUSH_MANY, UIM_INDEX_FORCE_MERGE, UIM_INDEX_FORCE_MERGE_MANY, - UIM_INDEX_FREEZE, - UIM_INDEX_FREEZE_MANY, UIM_INDEX_OPEN, UIM_INDEX_OPEN_MANY, UIM_INDEX_REFRESH, diff --git a/x-pack/plugins/index_management/common/constants/ui_metric.ts b/x-pack/plugins/index_management/common/constants/ui_metric.ts index b6e29cd7e3024..18cd983834bd5 100644 --- a/x-pack/plugins/index_management/common/constants/ui_metric.ts +++ b/x-pack/plugins/index_management/common/constants/ui_metric.ts @@ -19,8 +19,6 @@ export const UIM_INDEX_FLUSH = 'index_flush'; export const UIM_INDEX_FLUSH_MANY = 'index_flush_many'; export const UIM_INDEX_FORCE_MERGE = 'index_force_merge'; export const UIM_INDEX_FORCE_MERGE_MANY = 'index_force_merge_many'; -export const UIM_INDEX_FREEZE = 'index_freeze'; -export const UIM_INDEX_FREEZE_MANY = 'index_freeze_many'; export const UIM_INDEX_OPEN = 'index_open'; export const UIM_INDEX_OPEN_MANY = 'index_open_many'; export const UIM_INDEX_REFRESH = 'index_refresh'; diff --git a/x-pack/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.container.js b/x-pack/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.container.js index 4470d7ba152cc..9e650f7fe2da5 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.container.js +++ b/x-pack/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.container.js @@ -20,7 +20,6 @@ import { openDetailPanel, performExtensionAction, reloadIndices, - freezeIndices, unfreezeIndices, } from '../../../../store/actions'; @@ -68,9 +67,6 @@ const mapDispatchToProps = (dispatch, { indexNames }) => { refreshIndices: () => { dispatch(refreshIndices({ indexNames })); }, - freezeIndices: () => { - dispatch(freezeIndices({ indexNames })); - }, unfreezeIndices: () => { dispatch(unfreezeIndices({ indexNames })); }, diff --git a/x-pack/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.js b/x-pack/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.js index c5bd62feff826..cc78f8c99a4c6 100644 --- a/x-pack/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.js +++ b/x-pack/plugins/index_management/public/application/sections/home/index_list/index_actions_context_menu/index_actions_context_menu.js @@ -70,7 +70,6 @@ export class IndexActionsContextMenu extends Component { return indexStatusByName[indexName] === INDEX_OPEN; }); const allFrozen = every(indices, (index) => index.isFrozen); - const allUnfrozen = every(indices, (index) => !index.isFrozen); const selectedIndexCount = indexNames.length; const items = []; if (!detailPanel && selectedIndexCount === 1) { @@ -178,6 +177,7 @@ export class IndexActionsContextMenu extends Component { }); if (allFrozen) { items.push({ + 'data-test-subj': 'unfreezeIndexMenuButton', name: i18n.translate('xpack.idxMgmt.indexActionsMenu.unfreezeIndexLabel', { defaultMessage: 'Unfreeze {selectedIndexCount, plural, one {index} other {indices} }', values: { selectedIndexCount }, @@ -186,17 +186,6 @@ export class IndexActionsContextMenu extends Component { this.closePopoverAndExecute(unfreezeIndices); }, }); - } else if (allUnfrozen) { - items.push({ - name: i18n.translate('xpack.idxMgmt.indexActionsMenu.freezeIndexLabel', { - defaultMessage: 'Freeze {selectedIndexCount, plural, one {index} other {indices} }', - values: { selectedIndexCount }, - }), - onClick: () => { - this.closePopover(); - this.setState({ renderConfirmModal: this.renderConfirmFreezeModal }); - }, - }); } } else { items.push({ @@ -619,76 +608,6 @@ export class IndexActionsContextMenu extends Component { ); }; - renderConfirmFreezeModal = () => { - const { freezeIndices, indexNames } = this.props; - - return ( - this.closePopoverAndExecute(freezeIndices)} - cancelButtonText={i18n.translate( - 'xpack.idxMgmt.indexActionsMenu.freezeEntity.confirmModal.cancelButtonText', - { - defaultMessage: 'Cancel', - } - )} - confirmButtonText={i18n.translate( - 'xpack.idxMgmt.indexActionsMenu.freezeEntity.confirmModal.confirmButtonText', - { - defaultMessage: 'Freeze {count, plural, one {index} other {indices}}', - values: { - count: indexNames.length, - }, - } - )} - > -

- -

- -
    - {indexNames.map((indexName) => ( -
  • {indexName}
  • - ))} -
- - -

- -

-
-
- ); - }; - render() { return ( diff --git a/x-pack/plugins/index_management/public/application/services/api.ts b/x-pack/plugins/index_management/public/application/services/api.ts index a7109854d676f..5929df2f2821d 100644 --- a/x-pack/plugins/index_management/public/application/services/api.ts +++ b/x-pack/plugins/index_management/public/application/services/api.ts @@ -19,8 +19,6 @@ import { UIM_INDEX_FLUSH_MANY, UIM_INDEX_FORCE_MERGE, UIM_INDEX_FORCE_MERGE_MANY, - UIM_INDEX_FREEZE, - UIM_INDEX_FREEZE_MANY, UIM_INDEX_OPEN, UIM_INDEX_OPEN_MANY, UIM_INDEX_REFRESH, @@ -177,16 +175,6 @@ export async function clearCacheIndices(indices: string[]) { uiMetricService.trackMetric(METRIC_TYPE.COUNT, eventName); return response; } -export async function freezeIndices(indices: string[]) { - const body = JSON.stringify({ - indices, - }); - const response = await httpService.httpClient.post(`${API_BASE_PATH}/indices/freeze`, { body }); - // Only track successful requests. - const eventName = indices.length > 1 ? UIM_INDEX_FREEZE_MANY : UIM_INDEX_FREEZE; - uiMetricService.trackMetric(METRIC_TYPE.COUNT, eventName); - return response; -} export async function unfreezeIndices(indices: string[]) { const body = JSON.stringify({ indices, diff --git a/x-pack/plugins/index_management/public/application/services/index.ts b/x-pack/plugins/index_management/public/application/services/index.ts index 53bb9fa9ebb5e..536024ed5c758 100644 --- a/x-pack/plugins/index_management/public/application/services/index.ts +++ b/x-pack/plugins/index_management/public/application/services/index.ts @@ -15,7 +15,6 @@ export { flushIndices, forcemergeIndices, clearCacheIndices, - freezeIndices, unfreezeIndices, loadIndexSettings, updateIndexSettings, diff --git a/x-pack/plugins/index_management/public/application/store/actions/freeze_indices.js b/x-pack/plugins/index_management/public/application/store/actions/freeze_indices.js deleted file mode 100644 index 002b0c5f00c9d..0000000000000 --- a/x-pack/plugins/index_management/public/application/store/actions/freeze_indices.js +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { createAction } from 'redux-actions'; -import { i18n } from '@kbn/i18n'; -import { freezeIndices as request } from '../../services'; -import { clearRowStatus, reloadIndices } from '../actions'; -import { notificationService } from '../../services/notification'; - -export const freezeIndicesStart = createAction('INDEX_MANAGEMENT_FREEZE_INDICES_START'); - -export const freezeIndices = - ({ indexNames }) => - async (dispatch) => { - dispatch(freezeIndicesStart({ indexNames })); - try { - await request(indexNames); - } catch (error) { - notificationService.showDangerToast(error.message); - return dispatch(clearRowStatus({ indexNames })); - } - dispatch(reloadIndices(indexNames)); - notificationService.showSuccessToast( - i18n.translate('xpack.idxMgmt.freezeIndicesAction.successfullyFrozeIndicesMessage', { - defaultMessage: 'Successfully froze: [{indexNames}]', - values: { indexNames: indexNames.join(', ') }, - }) - ); - }; diff --git a/x-pack/plugins/index_management/public/application/store/actions/index.js b/x-pack/plugins/index_management/public/application/store/actions/index.js index bb970efe1b58f..853798ab94bff 100644 --- a/x-pack/plugins/index_management/public/application/store/actions/index.js +++ b/x-pack/plugins/index_management/public/application/store/actions/index.js @@ -15,7 +15,6 @@ export * from './load_indices'; export * from './load_index_data'; export * from './open_indices'; export * from './refresh_indices'; -export * from './freeze_indices'; export * from './unfreeze_indices'; export * from './reload_indices'; export * from './table_state'; diff --git a/x-pack/plugins/index_management/server/routes/api/indices/register_freeze_route.ts b/x-pack/plugins/index_management/server/routes/api/indices/register_freeze_route.ts deleted file mode 100644 index fcab1d6338b6f..0000000000000 --- a/x-pack/plugins/index_management/server/routes/api/indices/register_freeze_route.ts +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { schema } from '@kbn/config-schema'; - -import { RouteDependencies } from '../../../types'; -import { addBasePath } from '../index'; - -const bodySchema = schema.object({ - indices: schema.arrayOf(schema.string()), -}); - -export function registerFreezeRoute({ router, lib: { handleEsError } }: RouteDependencies) { - router.post( - { path: addBasePath('/indices/freeze'), validate: { body: bodySchema } }, - async (context, request, response) => { - const { client } = context.core.elasticsearch; - const { indices = [] } = request.body as typeof bodySchema.type; - - try { - await client.asCurrentUser.indices.freeze({ - index: indices.join(','), - }); - return response.ok(); - } catch (error) { - return handleEsError({ error, response }); - } - } - ); -} diff --git a/x-pack/plugins/index_management/server/routes/api/indices/register_indices_routes.ts b/x-pack/plugins/index_management/server/routes/api/indices/register_indices_routes.ts index ae1577f7722fe..c3e3eeb35118c 100644 --- a/x-pack/plugins/index_management/server/routes/api/indices/register_indices_routes.ts +++ b/x-pack/plugins/index_management/server/routes/api/indices/register_indices_routes.ts @@ -16,7 +16,6 @@ import { registerOpenRoute } from './register_open_route'; import { registerRefreshRoute } from './register_refresh_route'; import { registerReloadRoute } from './register_reload_route'; import { registerDeleteRoute } from './register_delete_route'; -import { registerFreezeRoute } from './register_freeze_route'; import { registerUnfreezeRoute } from './register_unfreeze_route'; export function registerIndicesRoutes(dependencies: RouteDependencies) { @@ -29,6 +28,5 @@ export function registerIndicesRoutes(dependencies: RouteDependencies) { registerRefreshRoute(dependencies); registerReloadRoute(dependencies); registerDeleteRoute(dependencies); - registerFreezeRoute(dependencies); registerUnfreezeRoute(dependencies); } diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 02d04b6b54881..157deffe6ff7b 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -11640,7 +11640,6 @@ "xpack.idxMgmt.formWizard.stepSettings.settingsDescription": "インデックスの動作を定義します。", "xpack.idxMgmt.formWizard.stepSettings.settingsEditorHelpText": "JSONフォーマットを使用:{code}", "xpack.idxMgmt.formWizard.stepSettings.stepTitle": "インデックス設定(任意)", - "xpack.idxMgmt.freezeIndicesAction.successfullyFrozeIndicesMessage": "[{indexNames}] が凍結されました", "xpack.idxMgmt.frozenBadgeLabel": "凍結", "xpack.idxMgmt.home.appTitle": "インデックス管理", "xpack.idxMgmt.home.componentTemplates.checkingPrivilegesDescription": "権限を確認中…", @@ -11690,10 +11689,6 @@ "xpack.idxMgmt.indexActionsMenu.forceMerge.forceMergeWarningDescription": " まだ書き込み中のインデックスや、将来もう一度書き込む予定がある強制・マージしないでください。自動バックグラウンドマージプロセスを活用して、スムーズなインデックス実行に必要なマージを実行できます。強制・マージインデックスに書き込む場合、パフォーマンスが大幅に低下する可能性があります。", "xpack.idxMgmt.indexActionsMenu.forceMerge.maximumNumberOfSegmentsFormRowLabel": "シャードごとの最大セグメント数", "xpack.idxMgmt.indexActionsMenu.forceMerge.proceedWithCautionCallOutTitle": "十分ご注意ください!", - "xpack.idxMgmt.indexActionsMenu.freezeEntity.confirmModal.cancelButtonText": "キャンセル", - "xpack.idxMgmt.indexActionsMenu.freezeEntity.freezeDescription": "{count, plural, one {このインデックス} other {これらのインデックス} }を凍結しようとしています。", - "xpack.idxMgmt.indexActionsMenu.freezeEntity.freezeEntityWarningDescription": " 凍結されたインデックスはクラスターにほとんどオーバーヘッドがなく、書き込みオペレーションがブロックされます。凍結されたインデックスは検索できますが、クエリが遅くなります。", - "xpack.idxMgmt.indexActionsMenu.freezeEntity.proceedWithCautionCallOutTitle": "十分ご注意ください", "xpack.idxMgmt.indexActionsMenu.segmentsNumberErrorMessage": "セグメント数は 0 より大きい値である必要があります。", "xpack.idxMgmt.indexStatusLabels.clearingCacheStatusLabel": "キャッシュを消去中...", "xpack.idxMgmt.indexStatusLabels.closedStatusLabel": "クローズ済み", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index ad7e3ea25c375..df595545cd4f4 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -11772,7 +11772,6 @@ "xpack.idxMgmt.formWizard.stepSettings.settingsDescription": "定义索引的行为。", "xpack.idxMgmt.formWizard.stepSettings.settingsEditorHelpText": "使用 JSON 格式:{code}", "xpack.idxMgmt.formWizard.stepSettings.stepTitle": "索引设置(可选)", - "xpack.idxMgmt.freezeIndicesAction.successfullyFrozeIndicesMessage": "成功冻结:[{indexNames}]", "xpack.idxMgmt.frozenBadgeLabel": "已冻结", "xpack.idxMgmt.home.appTitle": "索引管理", "xpack.idxMgmt.home.componentTemplates.checkingPrivilegesDescription": "正在检查权限……", @@ -11835,13 +11834,6 @@ "xpack.idxMgmt.indexActionsMenu.forceMerge.maximumNumberOfSegmentsFormRowLabel": "每分片最大段数", "xpack.idxMgmt.indexActionsMenu.forceMerge.proceedWithCautionCallOutTitle": "谨慎操作!", "xpack.idxMgmt.indexActionsMenu.forceMergeIndexLabel": "强制合并{selectedIndexCount, plural, other {索引} }", - "xpack.idxMgmt.indexActionsMenu.freezeEntity.confirmModal.cancelButtonText": "取消", - "xpack.idxMgmt.indexActionsMenu.freezeEntity.confirmModal.confirmButtonText": "隐藏{count, plural, other {索引}}", - "xpack.idxMgmt.indexActionsMenu.freezeEntity.confirmModal.modalTitle": "确认冻结{count, plural, other {索引}}", - "xpack.idxMgmt.indexActionsMenu.freezeEntity.freezeDescription": "您将要冻结{count, plural, other {以下索引}}:", - "xpack.idxMgmt.indexActionsMenu.freezeEntity.freezeEntityWarningDescription": " 冻结的索引在集群上有很少的开销,已被阻止进行写操作。您可以搜索冻结的索引,但查询应会较慢。", - "xpack.idxMgmt.indexActionsMenu.freezeEntity.proceedWithCautionCallOutTitle": "谨慎操作", - "xpack.idxMgmt.indexActionsMenu.freezeIndexLabel": "冻结{selectedIndexCount, plural, other {索引} }", "xpack.idxMgmt.indexActionsMenu.manageButtonAriaLabel": "{selectedIndexCount, plural, other {索引} }选项", "xpack.idxMgmt.indexActionsMenu.manageButtonLabel": "管理{selectedIndexCount, plural, one {索引} other { {selectedIndexCount} 个索引}}", "xpack.idxMgmt.indexActionsMenu.openIndexLabel": "打开{selectedIndexCount, plural, other {索引} }", diff --git a/x-pack/test/api_integration/apis/management/index_management/indices.helpers.js b/x-pack/test/api_integration/apis/management/index_management/indices.helpers.js index 3ca06421aee28..368272858ea2c 100644 --- a/x-pack/test/api_integration/apis/management/index_management/indices.helpers.js +++ b/x-pack/test/api_integration/apis/management/index_management/indices.helpers.js @@ -29,8 +29,6 @@ export const registerHelpers = ({ supertest }) => { const forceMerge = (index, args) => executeActionOnIndices(index, 'forcemerge', args); - const freeze = (index) => executeActionOnIndices(index, 'freeze'); - const unfreeze = (index) => executeActionOnIndices(index, 'unfreeze'); const clearCache = (index) => executeActionOnIndices(index, 'clear_cache'); @@ -47,7 +45,6 @@ export const registerHelpers = ({ supertest }) => { flushIndex, refreshIndex, forceMerge, - freeze, unfreeze, list, reload, diff --git a/x-pack/test/api_integration/apis/management/index_management/indices.js b/x-pack/test/api_integration/apis/management/index_management/indices.js index 589887329fcd1..7cb6950207f9b 100644 --- a/x-pack/test/api_integration/apis/management/index_management/indices.js +++ b/x-pack/test/api_integration/apis/management/index_management/indices.js @@ -27,7 +27,6 @@ export default function ({ getService }) { flushIndex, refreshIndex, forceMerge, - freeze, unfreeze, list, reload, @@ -164,35 +163,12 @@ export default function ({ getService }) { }); }); - describe('freeze', () => { - it('should freeze an index', async () => { - const index = await createIndex(); - // "sth" correspond to search throttling. Frozen indices are normal indices - // with search throttling turned on. - const { - body: [cat1], - } = await catIndex(index, 'sth'); - expect(cat1.sth).to.be('false'); - - await freeze(index).expect(200); - - const { - body: [cat2], - } = await catIndex(index, 'sth'); - expect(cat2.sth).to.be('true'); - }); - }); - describe('unfreeze', () => { it('should unfreeze an index', async () => { const index = await createIndex(); - await freeze(index).expect(200); - const { - body: [cat1], - } = await catIndex(index, 'sth'); - expect(cat1.sth).to.be('true'); - + // Even if the index is already unfrozen, calling the unfreeze api + // will have no effect on it and will return a 200. await unfreeze(index).expect(200); const { body: [cat2], From 84a3536fe4b10434f6e0cc9f7b1bb50a3ad2e3ab Mon Sep 17 00:00:00 2001 From: Su Tran Date: Tue, 26 Oct 2021 22:08:03 +0700 Subject: [PATCH 38/58] Fix Add filter button doesnt close popup after openning (#111917) Co-authored-by: Su Tran --- src/plugins/data/public/ui/filter_bar/filter_bar.tsx | 4 +++- test/accessibility/apps/filter_panel.ts | 1 + test/functional/page_objects/discover_page.ts | 4 ++++ test/functional/services/filter_bar.ts | 1 + 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/plugins/data/public/ui/filter_bar/filter_bar.tsx b/src/plugins/data/public/ui/filter_bar/filter_bar.tsx index 09fd818f23703..8abf6a41d8762 100644 --- a/src/plugins/data/public/ui/filter_bar/filter_bar.tsx +++ b/src/plugins/data/public/ui/filter_bar/filter_bar.tsx @@ -55,6 +55,8 @@ function FilterBarUI(props: Props) { } } + const onAddFilterClick = () => setIsAddFilterPopoverOpen(!isAddFilterPopoverOpen); + function renderItems() { return props.filters.map((filter, i) => ( @@ -81,7 +83,7 @@ function FilterBarUI(props: Props) { const button = ( setIsAddFilterPopoverOpen(true)} + onClick={onAddFilterClick} data-test-subj="addFilter" className="globalFilterBar__addButton" > diff --git a/test/accessibility/apps/filter_panel.ts b/test/accessibility/apps/filter_panel.ts index 78e776ce3a482..deb1e9512cd81 100644 --- a/test/accessibility/apps/filter_panel.ts +++ b/test/accessibility/apps/filter_panel.ts @@ -24,6 +24,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { it('a11y test on add filter panel', async () => { await PageObjects.discover.openAddFilterPanel(); await a11y.testAppSnapshot(); + await PageObjects.discover.closeAddFilterPanel(); await filterBar.addFilter('OriginCityName', 'is', 'Rome'); }); diff --git a/test/functional/page_objects/discover_page.ts b/test/functional/page_objects/discover_page.ts index a45c1a23ed3a5..fa7aee4e3c54c 100644 --- a/test/functional/page_objects/discover_page.ts +++ b/test/functional/page_objects/discover_page.ts @@ -83,6 +83,10 @@ export class DiscoverPageObject extends FtrService { await this.testSubjects.click('addFilter'); } + public async closeAddFilterPanel() { + await this.testSubjects.click('addFilter'); + } + public async waitUntilSearchingHasFinished() { await this.testSubjects.missingOrFail('loadingSpinner', { timeout: this.defaultFindTimeout * 10, diff --git a/test/functional/services/filter_bar.ts b/test/functional/services/filter_bar.ts index 1d0b85eed3a9c..5d189506c314d 100644 --- a/test/functional/services/filter_bar.ts +++ b/test/functional/services/filter_bar.ts @@ -199,5 +199,6 @@ export class FilterBarService extends FtrService { public async selectIndexPattern(indexPatternTitle: string): Promise { await this.testSubjects.click('addFilter'); await this.comboBox.set('filterIndexPatternsSelect', indexPatternTitle); + await this.testSubjects.click('addFilter'); } } From 06fbfd91f6e8df20a123e3e24db003c15c364cbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Marcondes?= <55978943+cauemarcondes@users.noreply.github.com> Date: Tue, 26 Oct 2021 11:10:17 -0400 Subject: [PATCH 39/58] [APM] Fix Service maps api test (#116218) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../__snapshots__/service_maps.snap | 2755 ----------------- .../tests/service_maps/service_maps.ts | 50 +- 2 files changed, 23 insertions(+), 2782 deletions(-) delete mode 100644 x-pack/test/apm_api_integration/tests/service_maps/__snapshots__/service_maps.snap diff --git a/x-pack/test/apm_api_integration/tests/service_maps/__snapshots__/service_maps.snap b/x-pack/test/apm_api_integration/tests/service_maps/__snapshots__/service_maps.snap deleted file mode 100644 index 9e32f311e8d11..0000000000000 --- a/x-pack/test/apm_api_integration/tests/service_maps/__snapshots__/service_maps.snap +++ /dev/null @@ -1,2755 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`APM API tests trial apm_8.0.0 Service Map with data /internal/apm/service-map returns the correct data 3`] = ` -Array [ - Object { - "data": Object { - "agent.name": "rum-js", - "id": "opbeans-rum", - "service.environment": "testing", - "service.name": "opbeans-rum", - "serviceAnomalyStats": Object { - "actualValue": 1020870.96774194, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-rum", - "transactionType": "page-load", - }, - }, - }, - Object { - "data": Object { - "agent.name": "ruby", - "id": "opbeans-ruby", - "service.environment": "production", - "service.name": "opbeans-ruby", - "serviceAnomalyStats": Object { - "actualValue": 62009.3356643357, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-ruby", - "transactionType": "request", - }, - }, - }, - Object { - "data": Object { - "id": ">postgresql", - "label": "postgresql", - "span.destination.service.resource": "postgresql", - "span.subtype": "postgresql", - "span.type": "db", - }, - }, - Object { - "data": Object { - "agent.name": "python", - "id": "opbeans-python", - "service.environment": "production", - "service.name": "opbeans-python", - "serviceAnomalyStats": Object { - "actualValue": 38862.7831325301, - "anomalyScore": 0.0725701910161626, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-python", - "transactionType": "request", - }, - }, - }, - Object { - "data": Object { - "id": ">elasticsearch", - "label": "elasticsearch", - "span.destination.service.resource": "elasticsearch", - "span.subtype": "elasticsearch", - "span.type": "db", - }, - }, - Object { - "data": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "testing", - "service.name": "opbeans-node", - "serviceAnomalyStats": Object { - "actualValue": 24819.2962962963, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-node", - "transactionType": "request", - }, - }, - }, - Object { - "data": Object { - "agent.name": "dotnet", - "id": "opbeans-dotnet", - "service.environment": "production", - "service.name": "opbeans-dotnet", - "serviceAnomalyStats": Object { - "actualValue": 868025.86875, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-dotnet", - "transactionType": "request", - }, - }, - }, - Object { - "data": Object { - "id": ">sqlite", - "label": "sqlite", - "span.destination.service.resource": "sqlite", - "span.subtype": "sqlite", - "span.type": "db", - }, - }, - Object { - "data": Object { - "agent.name": "java", - "id": "opbeans-java", - "service.environment": "production", - "service.name": "opbeans-java", - "serviceAnomalyStats": Object { - "actualValue": 175568.855769231, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-java", - "transactionType": "request", - }, - }, - }, - Object { - "data": Object { - "agent.name": "go", - "id": "opbeans-go", - "service.environment": "testing", - "service.name": "opbeans-go", - "serviceAnomalyStats": Object { - "actualValue": 102786.319148936, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-go", - "transactionType": "request", - }, - }, - }, - Object { - "data": Object { - "id": ">redis", - "label": "redis", - "span.destination.service.resource": "redis", - "span.subtype": "redis", - "span.type": "cache", - }, - }, - Object { - "data": Object { - "agent.name": "go", - "id": "auditbeat", - "service.environment": null, - "service.name": "auditbeat", - }, - }, - Object { - "data": Object { - "id": "opbeans-dotnet~>sqlite", - "source": "opbeans-dotnet", - "sourceData": Object { - "agent.name": "dotnet", - "id": "opbeans-dotnet", - "service.environment": "production", - "service.name": "opbeans-dotnet", - "serviceAnomalyStats": Object { - "actualValue": 868025.86875, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-dotnet", - "transactionType": "request", - }, - }, - "target": ">sqlite", - "targetData": Object { - "id": ">sqlite", - "label": "sqlite", - "span.destination.service.resource": "sqlite", - "span.subtype": "sqlite", - "span.type": "db", - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-go~>postgresql", - "source": "opbeans-go", - "sourceData": Object { - "agent.name": "go", - "id": "opbeans-go", - "service.environment": "testing", - "service.name": "opbeans-go", - "serviceAnomalyStats": Object { - "actualValue": 102786.319148936, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-go", - "transactionType": "request", - }, - }, - "target": ">postgresql", - "targetData": Object { - "id": ">postgresql", - "label": "postgresql", - "span.destination.service.resource": "postgresql", - "span.subtype": "postgresql", - "span.type": "db", - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-go~opbeans-dotnet", - "source": "opbeans-go", - "sourceData": Object { - "agent.name": "go", - "id": "opbeans-go", - "service.environment": "testing", - "service.name": "opbeans-go", - "serviceAnomalyStats": Object { - "actualValue": 102786.319148936, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-go", - "transactionType": "request", - }, - }, - "target": "opbeans-dotnet", - "targetData": Object { - "agent.name": "dotnet", - "id": "opbeans-dotnet", - "service.environment": "production", - "service.name": "opbeans-dotnet", - "serviceAnomalyStats": Object { - "actualValue": 868025.86875, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-dotnet", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "bidirectional": true, - "id": "opbeans-go~opbeans-java", - "source": "opbeans-go", - "sourceData": Object { - "agent.name": "go", - "id": "opbeans-go", - "service.environment": "testing", - "service.name": "opbeans-go", - "serviceAnomalyStats": Object { - "actualValue": 102786.319148936, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-go", - "transactionType": "request", - }, - }, - "target": "opbeans-java", - "targetData": Object { - "agent.name": "java", - "id": "opbeans-java", - "service.environment": "production", - "service.name": "opbeans-java", - "serviceAnomalyStats": Object { - "actualValue": 175568.855769231, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-java", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "bidirectional": true, - "id": "opbeans-go~opbeans-node", - "source": "opbeans-go", - "sourceData": Object { - "agent.name": "go", - "id": "opbeans-go", - "service.environment": "testing", - "service.name": "opbeans-go", - "serviceAnomalyStats": Object { - "actualValue": 102786.319148936, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-go", - "transactionType": "request", - }, - }, - "target": "opbeans-node", - "targetData": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "testing", - "service.name": "opbeans-node", - "serviceAnomalyStats": Object { - "actualValue": 24819.2962962963, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-node", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "bidirectional": true, - "id": "opbeans-go~opbeans-python", - "source": "opbeans-go", - "sourceData": Object { - "agent.name": "go", - "id": "opbeans-go", - "service.environment": "testing", - "service.name": "opbeans-go", - "serviceAnomalyStats": Object { - "actualValue": 102786.319148936, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-go", - "transactionType": "request", - }, - }, - "target": "opbeans-python", - "targetData": Object { - "agent.name": "python", - "id": "opbeans-python", - "service.environment": "production", - "service.name": "opbeans-python", - "serviceAnomalyStats": Object { - "actualValue": 38862.7831325301, - "anomalyScore": 0.0725701910161626, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-python", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "bidirectional": true, - "id": "opbeans-go~opbeans-ruby", - "source": "opbeans-go", - "sourceData": Object { - "agent.name": "go", - "id": "opbeans-go", - "service.environment": "testing", - "service.name": "opbeans-go", - "serviceAnomalyStats": Object { - "actualValue": 102786.319148936, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-go", - "transactionType": "request", - }, - }, - "target": "opbeans-ruby", - "targetData": Object { - "agent.name": "ruby", - "id": "opbeans-ruby", - "service.environment": "production", - "service.name": "opbeans-ruby", - "serviceAnomalyStats": Object { - "actualValue": 62009.3356643357, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-ruby", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-java~>postgresql", - "source": "opbeans-java", - "sourceData": Object { - "agent.name": "java", - "id": "opbeans-java", - "service.environment": "production", - "service.name": "opbeans-java", - "serviceAnomalyStats": Object { - "actualValue": 175568.855769231, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-java", - "transactionType": "request", - }, - }, - "target": ">postgresql", - "targetData": Object { - "id": ">postgresql", - "label": "postgresql", - "span.destination.service.resource": "postgresql", - "span.subtype": "postgresql", - "span.type": "db", - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-java~opbeans-dotnet", - "source": "opbeans-java", - "sourceData": Object { - "agent.name": "java", - "id": "opbeans-java", - "service.environment": "production", - "service.name": "opbeans-java", - "serviceAnomalyStats": Object { - "actualValue": 175568.855769231, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-java", - "transactionType": "request", - }, - }, - "target": "opbeans-dotnet", - "targetData": Object { - "agent.name": "dotnet", - "id": "opbeans-dotnet", - "service.environment": "production", - "service.name": "opbeans-dotnet", - "serviceAnomalyStats": Object { - "actualValue": 868025.86875, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-dotnet", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-java~opbeans-go", - "isInverseEdge": true, - "source": "opbeans-java", - "sourceData": Object { - "agent.name": "java", - "id": "opbeans-java", - "service.environment": "production", - "service.name": "opbeans-java", - "serviceAnomalyStats": Object { - "actualValue": 175568.855769231, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-java", - "transactionType": "request", - }, - }, - "target": "opbeans-go", - "targetData": Object { - "agent.name": "go", - "id": "opbeans-go", - "service.environment": "testing", - "service.name": "opbeans-go", - "serviceAnomalyStats": Object { - "actualValue": 102786.319148936, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-go", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "bidirectional": true, - "id": "opbeans-java~opbeans-node", - "source": "opbeans-java", - "sourceData": Object { - "agent.name": "java", - "id": "opbeans-java", - "service.environment": "production", - "service.name": "opbeans-java", - "serviceAnomalyStats": Object { - "actualValue": 175568.855769231, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-java", - "transactionType": "request", - }, - }, - "target": "opbeans-node", - "targetData": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "testing", - "service.name": "opbeans-node", - "serviceAnomalyStats": Object { - "actualValue": 24819.2962962963, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-node", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "bidirectional": true, - "id": "opbeans-java~opbeans-ruby", - "source": "opbeans-java", - "sourceData": Object { - "agent.name": "java", - "id": "opbeans-java", - "service.environment": "production", - "service.name": "opbeans-java", - "serviceAnomalyStats": Object { - "actualValue": 175568.855769231, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-java", - "transactionType": "request", - }, - }, - "target": "opbeans-ruby", - "targetData": Object { - "agent.name": "ruby", - "id": "opbeans-ruby", - "service.environment": "production", - "service.name": "opbeans-ruby", - "serviceAnomalyStats": Object { - "actualValue": 62009.3356643357, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-ruby", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-node~>postgresql", - "source": "opbeans-node", - "sourceData": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "testing", - "service.name": "opbeans-node", - "serviceAnomalyStats": Object { - "actualValue": 24819.2962962963, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-node", - "transactionType": "request", - }, - }, - "target": ">postgresql", - "targetData": Object { - "id": ">postgresql", - "label": "postgresql", - "span.destination.service.resource": "postgresql", - "span.subtype": "postgresql", - "span.type": "db", - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-node~>redis", - "source": "opbeans-node", - "sourceData": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "testing", - "service.name": "opbeans-node", - "serviceAnomalyStats": Object { - "actualValue": 24819.2962962963, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-node", - "transactionType": "request", - }, - }, - "target": ">redis", - "targetData": Object { - "id": ">redis", - "label": "redis", - "span.destination.service.resource": "redis", - "span.subtype": "redis", - "span.type": "cache", - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-node~opbeans-go", - "isInverseEdge": true, - "source": "opbeans-node", - "sourceData": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "testing", - "service.name": "opbeans-node", - "serviceAnomalyStats": Object { - "actualValue": 24819.2962962963, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-node", - "transactionType": "request", - }, - }, - "target": "opbeans-go", - "targetData": Object { - "agent.name": "go", - "id": "opbeans-go", - "service.environment": "testing", - "service.name": "opbeans-go", - "serviceAnomalyStats": Object { - "actualValue": 102786.319148936, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-go", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-node~opbeans-java", - "isInverseEdge": true, - "source": "opbeans-node", - "sourceData": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "testing", - "service.name": "opbeans-node", - "serviceAnomalyStats": Object { - "actualValue": 24819.2962962963, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-node", - "transactionType": "request", - }, - }, - "target": "opbeans-java", - "targetData": Object { - "agent.name": "java", - "id": "opbeans-java", - "service.environment": "production", - "service.name": "opbeans-java", - "serviceAnomalyStats": Object { - "actualValue": 175568.855769231, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-java", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "bidirectional": true, - "id": "opbeans-node~opbeans-python", - "source": "opbeans-node", - "sourceData": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "testing", - "service.name": "opbeans-node", - "serviceAnomalyStats": Object { - "actualValue": 24819.2962962963, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-node", - "transactionType": "request", - }, - }, - "target": "opbeans-python", - "targetData": Object { - "agent.name": "python", - "id": "opbeans-python", - "service.environment": "production", - "service.name": "opbeans-python", - "serviceAnomalyStats": Object { - "actualValue": 38862.7831325301, - "anomalyScore": 0.0725701910161626, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-python", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "bidirectional": true, - "id": "opbeans-node~opbeans-ruby", - "source": "opbeans-node", - "sourceData": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "testing", - "service.name": "opbeans-node", - "serviceAnomalyStats": Object { - "actualValue": 24819.2962962963, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-node", - "transactionType": "request", - }, - }, - "target": "opbeans-ruby", - "targetData": Object { - "agent.name": "ruby", - "id": "opbeans-ruby", - "service.environment": "production", - "service.name": "opbeans-ruby", - "serviceAnomalyStats": Object { - "actualValue": 62009.3356643357, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-ruby", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-python~>elasticsearch", - "source": "opbeans-python", - "sourceData": Object { - "agent.name": "python", - "id": "opbeans-python", - "service.environment": "production", - "service.name": "opbeans-python", - "serviceAnomalyStats": Object { - "actualValue": 38862.7831325301, - "anomalyScore": 0.0725701910161626, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-python", - "transactionType": "request", - }, - }, - "target": ">elasticsearch", - "targetData": Object { - "id": ">elasticsearch", - "label": "elasticsearch", - "span.destination.service.resource": "elasticsearch", - "span.subtype": "elasticsearch", - "span.type": "db", - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-python~>postgresql", - "source": "opbeans-python", - "sourceData": Object { - "agent.name": "python", - "id": "opbeans-python", - "service.environment": "production", - "service.name": "opbeans-python", - "serviceAnomalyStats": Object { - "actualValue": 38862.7831325301, - "anomalyScore": 0.0725701910161626, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-python", - "transactionType": "request", - }, - }, - "target": ">postgresql", - "targetData": Object { - "id": ">postgresql", - "label": "postgresql", - "span.destination.service.resource": "postgresql", - "span.subtype": "postgresql", - "span.type": "db", - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-python~>redis", - "source": "opbeans-python", - "sourceData": Object { - "agent.name": "python", - "id": "opbeans-python", - "service.environment": "production", - "service.name": "opbeans-python", - "serviceAnomalyStats": Object { - "actualValue": 38862.7831325301, - "anomalyScore": 0.0725701910161626, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-python", - "transactionType": "request", - }, - }, - "target": ">redis", - "targetData": Object { - "id": ">redis", - "label": "redis", - "span.destination.service.resource": "redis", - "span.subtype": "redis", - "span.type": "cache", - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-python~opbeans-go", - "isInverseEdge": true, - "source": "opbeans-python", - "sourceData": Object { - "agent.name": "python", - "id": "opbeans-python", - "service.environment": "production", - "service.name": "opbeans-python", - "serviceAnomalyStats": Object { - "actualValue": 38862.7831325301, - "anomalyScore": 0.0725701910161626, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-python", - "transactionType": "request", - }, - }, - "target": "opbeans-go", - "targetData": Object { - "agent.name": "go", - "id": "opbeans-go", - "service.environment": "testing", - "service.name": "opbeans-go", - "serviceAnomalyStats": Object { - "actualValue": 102786.319148936, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-go", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-python~opbeans-java", - "source": "opbeans-python", - "sourceData": Object { - "agent.name": "python", - "id": "opbeans-python", - "service.environment": "production", - "service.name": "opbeans-python", - "serviceAnomalyStats": Object { - "actualValue": 38862.7831325301, - "anomalyScore": 0.0725701910161626, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-python", - "transactionType": "request", - }, - }, - "target": "opbeans-java", - "targetData": Object { - "agent.name": "java", - "id": "opbeans-java", - "service.environment": "production", - "service.name": "opbeans-java", - "serviceAnomalyStats": Object { - "actualValue": 175568.855769231, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-java", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-python~opbeans-node", - "isInverseEdge": true, - "source": "opbeans-python", - "sourceData": Object { - "agent.name": "python", - "id": "opbeans-python", - "service.environment": "production", - "service.name": "opbeans-python", - "serviceAnomalyStats": Object { - "actualValue": 38862.7831325301, - "anomalyScore": 0.0725701910161626, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-python", - "transactionType": "request", - }, - }, - "target": "opbeans-node", - "targetData": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "testing", - "service.name": "opbeans-node", - "serviceAnomalyStats": Object { - "actualValue": 24819.2962962963, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-node", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "bidirectional": true, - "id": "opbeans-python~opbeans-ruby", - "source": "opbeans-python", - "sourceData": Object { - "agent.name": "python", - "id": "opbeans-python", - "service.environment": "production", - "service.name": "opbeans-python", - "serviceAnomalyStats": Object { - "actualValue": 38862.7831325301, - "anomalyScore": 0.0725701910161626, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-python", - "transactionType": "request", - }, - }, - "target": "opbeans-ruby", - "targetData": Object { - "agent.name": "ruby", - "id": "opbeans-ruby", - "service.environment": "production", - "service.name": "opbeans-ruby", - "serviceAnomalyStats": Object { - "actualValue": 62009.3356643357, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-ruby", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-ruby~>postgresql", - "source": "opbeans-ruby", - "sourceData": Object { - "agent.name": "ruby", - "id": "opbeans-ruby", - "service.environment": "production", - "service.name": "opbeans-ruby", - "serviceAnomalyStats": Object { - "actualValue": 62009.3356643357, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-ruby", - "transactionType": "request", - }, - }, - "target": ">postgresql", - "targetData": Object { - "id": ">postgresql", - "label": "postgresql", - "span.destination.service.resource": "postgresql", - "span.subtype": "postgresql", - "span.type": "db", - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-ruby~opbeans-dotnet", - "source": "opbeans-ruby", - "sourceData": Object { - "agent.name": "ruby", - "id": "opbeans-ruby", - "service.environment": "production", - "service.name": "opbeans-ruby", - "serviceAnomalyStats": Object { - "actualValue": 62009.3356643357, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-ruby", - "transactionType": "request", - }, - }, - "target": "opbeans-dotnet", - "targetData": Object { - "agent.name": "dotnet", - "id": "opbeans-dotnet", - "service.environment": "production", - "service.name": "opbeans-dotnet", - "serviceAnomalyStats": Object { - "actualValue": 868025.86875, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-dotnet", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-ruby~opbeans-go", - "isInverseEdge": true, - "source": "opbeans-ruby", - "sourceData": Object { - "agent.name": "ruby", - "id": "opbeans-ruby", - "service.environment": "production", - "service.name": "opbeans-ruby", - "serviceAnomalyStats": Object { - "actualValue": 62009.3356643357, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-ruby", - "transactionType": "request", - }, - }, - "target": "opbeans-go", - "targetData": Object { - "agent.name": "go", - "id": "opbeans-go", - "service.environment": "testing", - "service.name": "opbeans-go", - "serviceAnomalyStats": Object { - "actualValue": 102786.319148936, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-go", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-ruby~opbeans-java", - "isInverseEdge": true, - "source": "opbeans-ruby", - "sourceData": Object { - "agent.name": "ruby", - "id": "opbeans-ruby", - "service.environment": "production", - "service.name": "opbeans-ruby", - "serviceAnomalyStats": Object { - "actualValue": 62009.3356643357, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-ruby", - "transactionType": "request", - }, - }, - "target": "opbeans-java", - "targetData": Object { - "agent.name": "java", - "id": "opbeans-java", - "service.environment": "production", - "service.name": "opbeans-java", - "serviceAnomalyStats": Object { - "actualValue": 175568.855769231, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-java", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-ruby~opbeans-node", - "isInverseEdge": true, - "source": "opbeans-ruby", - "sourceData": Object { - "agent.name": "ruby", - "id": "opbeans-ruby", - "service.environment": "production", - "service.name": "opbeans-ruby", - "serviceAnomalyStats": Object { - "actualValue": 62009.3356643357, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-ruby", - "transactionType": "request", - }, - }, - "target": "opbeans-node", - "targetData": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "testing", - "service.name": "opbeans-node", - "serviceAnomalyStats": Object { - "actualValue": 24819.2962962963, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-node", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-ruby~opbeans-python", - "isInverseEdge": true, - "source": "opbeans-ruby", - "sourceData": Object { - "agent.name": "ruby", - "id": "opbeans-ruby", - "service.environment": "production", - "service.name": "opbeans-ruby", - "serviceAnomalyStats": Object { - "actualValue": 62009.3356643357, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-ruby", - "transactionType": "request", - }, - }, - "target": "opbeans-python", - "targetData": Object { - "agent.name": "python", - "id": "opbeans-python", - "service.environment": "production", - "service.name": "opbeans-python", - "serviceAnomalyStats": Object { - "actualValue": 38862.7831325301, - "anomalyScore": 0.0725701910161626, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-python", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-rum~opbeans-dotnet", - "source": "opbeans-rum", - "sourceData": Object { - "agent.name": "rum-js", - "id": "opbeans-rum", - "service.environment": "testing", - "service.name": "opbeans-rum", - "serviceAnomalyStats": Object { - "actualValue": 1020870.96774194, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-rum", - "transactionType": "page-load", - }, - }, - "target": "opbeans-dotnet", - "targetData": Object { - "agent.name": "dotnet", - "id": "opbeans-dotnet", - "service.environment": "production", - "service.name": "opbeans-dotnet", - "serviceAnomalyStats": Object { - "actualValue": 868025.86875, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-dotnet", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-rum~opbeans-go", - "source": "opbeans-rum", - "sourceData": Object { - "agent.name": "rum-js", - "id": "opbeans-rum", - "service.environment": "testing", - "service.name": "opbeans-rum", - "serviceAnomalyStats": Object { - "actualValue": 1020870.96774194, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-rum", - "transactionType": "page-load", - }, - }, - "target": "opbeans-go", - "targetData": Object { - "agent.name": "go", - "id": "opbeans-go", - "service.environment": "testing", - "service.name": "opbeans-go", - "serviceAnomalyStats": Object { - "actualValue": 102786.319148936, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-go", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-rum~opbeans-java", - "source": "opbeans-rum", - "sourceData": Object { - "agent.name": "rum-js", - "id": "opbeans-rum", - "service.environment": "testing", - "service.name": "opbeans-rum", - "serviceAnomalyStats": Object { - "actualValue": 1020870.96774194, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-rum", - "transactionType": "page-load", - }, - }, - "target": "opbeans-java", - "targetData": Object { - "agent.name": "java", - "id": "opbeans-java", - "service.environment": "production", - "service.name": "opbeans-java", - "serviceAnomalyStats": Object { - "actualValue": 175568.855769231, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-java", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-rum~opbeans-node", - "source": "opbeans-rum", - "sourceData": Object { - "agent.name": "rum-js", - "id": "opbeans-rum", - "service.environment": "testing", - "service.name": "opbeans-rum", - "serviceAnomalyStats": Object { - "actualValue": 1020870.96774194, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-rum", - "transactionType": "page-load", - }, - }, - "target": "opbeans-node", - "targetData": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "testing", - "service.name": "opbeans-node", - "serviceAnomalyStats": Object { - "actualValue": 24819.2962962963, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-node", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-rum~opbeans-ruby", - "source": "opbeans-rum", - "sourceData": Object { - "agent.name": "rum-js", - "id": "opbeans-rum", - "service.environment": "testing", - "service.name": "opbeans-rum", - "serviceAnomalyStats": Object { - "actualValue": 1020870.96774194, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-rum", - "transactionType": "page-load", - }, - }, - "target": "opbeans-ruby", - "targetData": Object { - "agent.name": "ruby", - "id": "opbeans-ruby", - "service.environment": "production", - "service.name": "opbeans-ruby", - "serviceAnomalyStats": Object { - "actualValue": 62009.3356643357, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-ruby", - "transactionType": "request", - }, - }, - }, - }, -] -`; - -exports[`APM API tests trial apm_8.0.0 Service Map with data /internal/apm/service-map with ML data with the default apm user returns the correct anomaly stats 3`] = ` -Object { - "elements": Array [ - Object { - "data": Object { - "agent.name": "rum-js", - "id": "opbeans-rum", - "service.environment": "testing", - "service.name": "opbeans-rum", - "serviceAnomalyStats": Object { - "actualValue": 1020870.96774194, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-rum", - "transactionType": "page-load", - }, - }, - }, - Object { - "data": Object { - "agent.name": "ruby", - "id": "opbeans-ruby", - "service.environment": "production", - "service.name": "opbeans-ruby", - "serviceAnomalyStats": Object { - "actualValue": 62009.3356643357, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-ruby", - "transactionType": "request", - }, - }, - }, - Object { - "data": Object { - "id": ">postgresql", - "label": "postgresql", - "span.destination.service.resource": "postgresql", - "span.subtype": "postgresql", - "span.type": "db", - }, - }, - Object { - "data": Object { - "agent.name": "python", - "id": "opbeans-python", - "service.environment": "production", - "service.name": "opbeans-python", - "serviceAnomalyStats": Object { - "actualValue": 38862.7831325301, - "anomalyScore": 0.0725701910161626, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-python", - "transactionType": "request", - }, - }, - }, - Object { - "data": Object { - "id": ">elasticsearch", - "label": "elasticsearch", - "span.destination.service.resource": "elasticsearch", - "span.subtype": "elasticsearch", - "span.type": "db", - }, - }, - Object { - "data": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "testing", - "service.name": "opbeans-node", - "serviceAnomalyStats": Object { - "actualValue": 24819.2962962963, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-node", - "transactionType": "request", - }, - }, - }, - Object { - "data": Object { - "agent.name": "dotnet", - "id": "opbeans-dotnet", - "service.environment": "production", - "service.name": "opbeans-dotnet", - "serviceAnomalyStats": Object { - "actualValue": 868025.86875, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-dotnet", - "transactionType": "request", - }, - }, - }, - Object { - "data": Object { - "id": ">sqlite", - "label": "sqlite", - "span.destination.service.resource": "sqlite", - "span.subtype": "sqlite", - "span.type": "db", - }, - }, - Object { - "data": Object { - "agent.name": "java", - "id": "opbeans-java", - "service.environment": "production", - "service.name": "opbeans-java", - "serviceAnomalyStats": Object { - "actualValue": 175568.855769231, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-java", - "transactionType": "request", - }, - }, - }, - Object { - "data": Object { - "agent.name": "go", - "id": "opbeans-go", - "service.environment": "testing", - "service.name": "opbeans-go", - "serviceAnomalyStats": Object { - "actualValue": 102786.319148936, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-go", - "transactionType": "request", - }, - }, - }, - Object { - "data": Object { - "id": ">redis", - "label": "redis", - "span.destination.service.resource": "redis", - "span.subtype": "redis", - "span.type": "cache", - }, - }, - Object { - "data": Object { - "agent.name": "go", - "id": "auditbeat", - "service.environment": null, - "service.name": "auditbeat", - }, - }, - Object { - "data": Object { - "id": "opbeans-dotnet~>sqlite", - "source": "opbeans-dotnet", - "sourceData": Object { - "agent.name": "dotnet", - "id": "opbeans-dotnet", - "service.environment": "production", - "service.name": "opbeans-dotnet", - "serviceAnomalyStats": Object { - "actualValue": 868025.86875, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-dotnet", - "transactionType": "request", - }, - }, - "target": ">sqlite", - "targetData": Object { - "id": ">sqlite", - "label": "sqlite", - "span.destination.service.resource": "sqlite", - "span.subtype": "sqlite", - "span.type": "db", - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-go~>postgresql", - "source": "opbeans-go", - "sourceData": Object { - "agent.name": "go", - "id": "opbeans-go", - "service.environment": "testing", - "service.name": "opbeans-go", - "serviceAnomalyStats": Object { - "actualValue": 102786.319148936, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-go", - "transactionType": "request", - }, - }, - "target": ">postgresql", - "targetData": Object { - "id": ">postgresql", - "label": "postgresql", - "span.destination.service.resource": "postgresql", - "span.subtype": "postgresql", - "span.type": "db", - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-go~opbeans-dotnet", - "source": "opbeans-go", - "sourceData": Object { - "agent.name": "go", - "id": "opbeans-go", - "service.environment": "testing", - "service.name": "opbeans-go", - "serviceAnomalyStats": Object { - "actualValue": 102786.319148936, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-go", - "transactionType": "request", - }, - }, - "target": "opbeans-dotnet", - "targetData": Object { - "agent.name": "dotnet", - "id": "opbeans-dotnet", - "service.environment": "production", - "service.name": "opbeans-dotnet", - "serviceAnomalyStats": Object { - "actualValue": 868025.86875, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-dotnet", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "bidirectional": true, - "id": "opbeans-go~opbeans-java", - "source": "opbeans-go", - "sourceData": Object { - "agent.name": "go", - "id": "opbeans-go", - "service.environment": "testing", - "service.name": "opbeans-go", - "serviceAnomalyStats": Object { - "actualValue": 102786.319148936, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-go", - "transactionType": "request", - }, - }, - "target": "opbeans-java", - "targetData": Object { - "agent.name": "java", - "id": "opbeans-java", - "service.environment": "production", - "service.name": "opbeans-java", - "serviceAnomalyStats": Object { - "actualValue": 175568.855769231, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-java", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "bidirectional": true, - "id": "opbeans-go~opbeans-node", - "source": "opbeans-go", - "sourceData": Object { - "agent.name": "go", - "id": "opbeans-go", - "service.environment": "testing", - "service.name": "opbeans-go", - "serviceAnomalyStats": Object { - "actualValue": 102786.319148936, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-go", - "transactionType": "request", - }, - }, - "target": "opbeans-node", - "targetData": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "testing", - "service.name": "opbeans-node", - "serviceAnomalyStats": Object { - "actualValue": 24819.2962962963, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-node", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "bidirectional": true, - "id": "opbeans-go~opbeans-python", - "source": "opbeans-go", - "sourceData": Object { - "agent.name": "go", - "id": "opbeans-go", - "service.environment": "testing", - "service.name": "opbeans-go", - "serviceAnomalyStats": Object { - "actualValue": 102786.319148936, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-go", - "transactionType": "request", - }, - }, - "target": "opbeans-python", - "targetData": Object { - "agent.name": "python", - "id": "opbeans-python", - "service.environment": "production", - "service.name": "opbeans-python", - "serviceAnomalyStats": Object { - "actualValue": 38862.7831325301, - "anomalyScore": 0.0725701910161626, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-python", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "bidirectional": true, - "id": "opbeans-go~opbeans-ruby", - "source": "opbeans-go", - "sourceData": Object { - "agent.name": "go", - "id": "opbeans-go", - "service.environment": "testing", - "service.name": "opbeans-go", - "serviceAnomalyStats": Object { - "actualValue": 102786.319148936, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-go", - "transactionType": "request", - }, - }, - "target": "opbeans-ruby", - "targetData": Object { - "agent.name": "ruby", - "id": "opbeans-ruby", - "service.environment": "production", - "service.name": "opbeans-ruby", - "serviceAnomalyStats": Object { - "actualValue": 62009.3356643357, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-ruby", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-java~>postgresql", - "source": "opbeans-java", - "sourceData": Object { - "agent.name": "java", - "id": "opbeans-java", - "service.environment": "production", - "service.name": "opbeans-java", - "serviceAnomalyStats": Object { - "actualValue": 175568.855769231, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-java", - "transactionType": "request", - }, - }, - "target": ">postgresql", - "targetData": Object { - "id": ">postgresql", - "label": "postgresql", - "span.destination.service.resource": "postgresql", - "span.subtype": "postgresql", - "span.type": "db", - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-java~opbeans-dotnet", - "source": "opbeans-java", - "sourceData": Object { - "agent.name": "java", - "id": "opbeans-java", - "service.environment": "production", - "service.name": "opbeans-java", - "serviceAnomalyStats": Object { - "actualValue": 175568.855769231, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-java", - "transactionType": "request", - }, - }, - "target": "opbeans-dotnet", - "targetData": Object { - "agent.name": "dotnet", - "id": "opbeans-dotnet", - "service.environment": "production", - "service.name": "opbeans-dotnet", - "serviceAnomalyStats": Object { - "actualValue": 868025.86875, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-dotnet", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-java~opbeans-go", - "isInverseEdge": true, - "source": "opbeans-java", - "sourceData": Object { - "agent.name": "java", - "id": "opbeans-java", - "service.environment": "production", - "service.name": "opbeans-java", - "serviceAnomalyStats": Object { - "actualValue": 175568.855769231, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-java", - "transactionType": "request", - }, - }, - "target": "opbeans-go", - "targetData": Object { - "agent.name": "go", - "id": "opbeans-go", - "service.environment": "testing", - "service.name": "opbeans-go", - "serviceAnomalyStats": Object { - "actualValue": 102786.319148936, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-go", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "bidirectional": true, - "id": "opbeans-java~opbeans-node", - "source": "opbeans-java", - "sourceData": Object { - "agent.name": "java", - "id": "opbeans-java", - "service.environment": "production", - "service.name": "opbeans-java", - "serviceAnomalyStats": Object { - "actualValue": 175568.855769231, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-java", - "transactionType": "request", - }, - }, - "target": "opbeans-node", - "targetData": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "testing", - "service.name": "opbeans-node", - "serviceAnomalyStats": Object { - "actualValue": 24819.2962962963, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-node", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "bidirectional": true, - "id": "opbeans-java~opbeans-ruby", - "source": "opbeans-java", - "sourceData": Object { - "agent.name": "java", - "id": "opbeans-java", - "service.environment": "production", - "service.name": "opbeans-java", - "serviceAnomalyStats": Object { - "actualValue": 175568.855769231, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-java", - "transactionType": "request", - }, - }, - "target": "opbeans-ruby", - "targetData": Object { - "agent.name": "ruby", - "id": "opbeans-ruby", - "service.environment": "production", - "service.name": "opbeans-ruby", - "serviceAnomalyStats": Object { - "actualValue": 62009.3356643357, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-ruby", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-node~>postgresql", - "source": "opbeans-node", - "sourceData": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "testing", - "service.name": "opbeans-node", - "serviceAnomalyStats": Object { - "actualValue": 24819.2962962963, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-node", - "transactionType": "request", - }, - }, - "target": ">postgresql", - "targetData": Object { - "id": ">postgresql", - "label": "postgresql", - "span.destination.service.resource": "postgresql", - "span.subtype": "postgresql", - "span.type": "db", - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-node~>redis", - "source": "opbeans-node", - "sourceData": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "testing", - "service.name": "opbeans-node", - "serviceAnomalyStats": Object { - "actualValue": 24819.2962962963, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-node", - "transactionType": "request", - }, - }, - "target": ">redis", - "targetData": Object { - "id": ">redis", - "label": "redis", - "span.destination.service.resource": "redis", - "span.subtype": "redis", - "span.type": "cache", - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-node~opbeans-go", - "isInverseEdge": true, - "source": "opbeans-node", - "sourceData": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "testing", - "service.name": "opbeans-node", - "serviceAnomalyStats": Object { - "actualValue": 24819.2962962963, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-node", - "transactionType": "request", - }, - }, - "target": "opbeans-go", - "targetData": Object { - "agent.name": "go", - "id": "opbeans-go", - "service.environment": "testing", - "service.name": "opbeans-go", - "serviceAnomalyStats": Object { - "actualValue": 102786.319148936, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-go", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-node~opbeans-java", - "isInverseEdge": true, - "source": "opbeans-node", - "sourceData": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "testing", - "service.name": "opbeans-node", - "serviceAnomalyStats": Object { - "actualValue": 24819.2962962963, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-node", - "transactionType": "request", - }, - }, - "target": "opbeans-java", - "targetData": Object { - "agent.name": "java", - "id": "opbeans-java", - "service.environment": "production", - "service.name": "opbeans-java", - "serviceAnomalyStats": Object { - "actualValue": 175568.855769231, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-java", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "bidirectional": true, - "id": "opbeans-node~opbeans-python", - "source": "opbeans-node", - "sourceData": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "testing", - "service.name": "opbeans-node", - "serviceAnomalyStats": Object { - "actualValue": 24819.2962962963, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-node", - "transactionType": "request", - }, - }, - "target": "opbeans-python", - "targetData": Object { - "agent.name": "python", - "id": "opbeans-python", - "service.environment": "production", - "service.name": "opbeans-python", - "serviceAnomalyStats": Object { - "actualValue": 38862.7831325301, - "anomalyScore": 0.0725701910161626, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-python", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "bidirectional": true, - "id": "opbeans-node~opbeans-ruby", - "source": "opbeans-node", - "sourceData": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "testing", - "service.name": "opbeans-node", - "serviceAnomalyStats": Object { - "actualValue": 24819.2962962963, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-node", - "transactionType": "request", - }, - }, - "target": "opbeans-ruby", - "targetData": Object { - "agent.name": "ruby", - "id": "opbeans-ruby", - "service.environment": "production", - "service.name": "opbeans-ruby", - "serviceAnomalyStats": Object { - "actualValue": 62009.3356643357, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-ruby", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-python~>elasticsearch", - "source": "opbeans-python", - "sourceData": Object { - "agent.name": "python", - "id": "opbeans-python", - "service.environment": "production", - "service.name": "opbeans-python", - "serviceAnomalyStats": Object { - "actualValue": 38862.7831325301, - "anomalyScore": 0.0725701910161626, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-python", - "transactionType": "request", - }, - }, - "target": ">elasticsearch", - "targetData": Object { - "id": ">elasticsearch", - "label": "elasticsearch", - "span.destination.service.resource": "elasticsearch", - "span.subtype": "elasticsearch", - "span.type": "db", - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-python~>postgresql", - "source": "opbeans-python", - "sourceData": Object { - "agent.name": "python", - "id": "opbeans-python", - "service.environment": "production", - "service.name": "opbeans-python", - "serviceAnomalyStats": Object { - "actualValue": 38862.7831325301, - "anomalyScore": 0.0725701910161626, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-python", - "transactionType": "request", - }, - }, - "target": ">postgresql", - "targetData": Object { - "id": ">postgresql", - "label": "postgresql", - "span.destination.service.resource": "postgresql", - "span.subtype": "postgresql", - "span.type": "db", - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-python~>redis", - "source": "opbeans-python", - "sourceData": Object { - "agent.name": "python", - "id": "opbeans-python", - "service.environment": "production", - "service.name": "opbeans-python", - "serviceAnomalyStats": Object { - "actualValue": 38862.7831325301, - "anomalyScore": 0.0725701910161626, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-python", - "transactionType": "request", - }, - }, - "target": ">redis", - "targetData": Object { - "id": ">redis", - "label": "redis", - "span.destination.service.resource": "redis", - "span.subtype": "redis", - "span.type": "cache", - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-python~opbeans-go", - "isInverseEdge": true, - "source": "opbeans-python", - "sourceData": Object { - "agent.name": "python", - "id": "opbeans-python", - "service.environment": "production", - "service.name": "opbeans-python", - "serviceAnomalyStats": Object { - "actualValue": 38862.7831325301, - "anomalyScore": 0.0725701910161626, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-python", - "transactionType": "request", - }, - }, - "target": "opbeans-go", - "targetData": Object { - "agent.name": "go", - "id": "opbeans-go", - "service.environment": "testing", - "service.name": "opbeans-go", - "serviceAnomalyStats": Object { - "actualValue": 102786.319148936, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-go", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-python~opbeans-java", - "source": "opbeans-python", - "sourceData": Object { - "agent.name": "python", - "id": "opbeans-python", - "service.environment": "production", - "service.name": "opbeans-python", - "serviceAnomalyStats": Object { - "actualValue": 38862.7831325301, - "anomalyScore": 0.0725701910161626, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-python", - "transactionType": "request", - }, - }, - "target": "opbeans-java", - "targetData": Object { - "agent.name": "java", - "id": "opbeans-java", - "service.environment": "production", - "service.name": "opbeans-java", - "serviceAnomalyStats": Object { - "actualValue": 175568.855769231, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-java", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-python~opbeans-node", - "isInverseEdge": true, - "source": "opbeans-python", - "sourceData": Object { - "agent.name": "python", - "id": "opbeans-python", - "service.environment": "production", - "service.name": "opbeans-python", - "serviceAnomalyStats": Object { - "actualValue": 38862.7831325301, - "anomalyScore": 0.0725701910161626, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-python", - "transactionType": "request", - }, - }, - "target": "opbeans-node", - "targetData": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "testing", - "service.name": "opbeans-node", - "serviceAnomalyStats": Object { - "actualValue": 24819.2962962963, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-node", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "bidirectional": true, - "id": "opbeans-python~opbeans-ruby", - "source": "opbeans-python", - "sourceData": Object { - "agent.name": "python", - "id": "opbeans-python", - "service.environment": "production", - "service.name": "opbeans-python", - "serviceAnomalyStats": Object { - "actualValue": 38862.7831325301, - "anomalyScore": 0.0725701910161626, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-python", - "transactionType": "request", - }, - }, - "target": "opbeans-ruby", - "targetData": Object { - "agent.name": "ruby", - "id": "opbeans-ruby", - "service.environment": "production", - "service.name": "opbeans-ruby", - "serviceAnomalyStats": Object { - "actualValue": 62009.3356643357, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-ruby", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-ruby~>postgresql", - "source": "opbeans-ruby", - "sourceData": Object { - "agent.name": "ruby", - "id": "opbeans-ruby", - "service.environment": "production", - "service.name": "opbeans-ruby", - "serviceAnomalyStats": Object { - "actualValue": 62009.3356643357, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-ruby", - "transactionType": "request", - }, - }, - "target": ">postgresql", - "targetData": Object { - "id": ">postgresql", - "label": "postgresql", - "span.destination.service.resource": "postgresql", - "span.subtype": "postgresql", - "span.type": "db", - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-ruby~opbeans-dotnet", - "source": "opbeans-ruby", - "sourceData": Object { - "agent.name": "ruby", - "id": "opbeans-ruby", - "service.environment": "production", - "service.name": "opbeans-ruby", - "serviceAnomalyStats": Object { - "actualValue": 62009.3356643357, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-ruby", - "transactionType": "request", - }, - }, - "target": "opbeans-dotnet", - "targetData": Object { - "agent.name": "dotnet", - "id": "opbeans-dotnet", - "service.environment": "production", - "service.name": "opbeans-dotnet", - "serviceAnomalyStats": Object { - "actualValue": 868025.86875, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-dotnet", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-ruby~opbeans-go", - "isInverseEdge": true, - "source": "opbeans-ruby", - "sourceData": Object { - "agent.name": "ruby", - "id": "opbeans-ruby", - "service.environment": "production", - "service.name": "opbeans-ruby", - "serviceAnomalyStats": Object { - "actualValue": 62009.3356643357, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-ruby", - "transactionType": "request", - }, - }, - "target": "opbeans-go", - "targetData": Object { - "agent.name": "go", - "id": "opbeans-go", - "service.environment": "testing", - "service.name": "opbeans-go", - "serviceAnomalyStats": Object { - "actualValue": 102786.319148936, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-go", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-ruby~opbeans-java", - "isInverseEdge": true, - "source": "opbeans-ruby", - "sourceData": Object { - "agent.name": "ruby", - "id": "opbeans-ruby", - "service.environment": "production", - "service.name": "opbeans-ruby", - "serviceAnomalyStats": Object { - "actualValue": 62009.3356643357, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-ruby", - "transactionType": "request", - }, - }, - "target": "opbeans-java", - "targetData": Object { - "agent.name": "java", - "id": "opbeans-java", - "service.environment": "production", - "service.name": "opbeans-java", - "serviceAnomalyStats": Object { - "actualValue": 175568.855769231, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-java", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-ruby~opbeans-node", - "isInverseEdge": true, - "source": "opbeans-ruby", - "sourceData": Object { - "agent.name": "ruby", - "id": "opbeans-ruby", - "service.environment": "production", - "service.name": "opbeans-ruby", - "serviceAnomalyStats": Object { - "actualValue": 62009.3356643357, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-ruby", - "transactionType": "request", - }, - }, - "target": "opbeans-node", - "targetData": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "testing", - "service.name": "opbeans-node", - "serviceAnomalyStats": Object { - "actualValue": 24819.2962962963, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-node", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-ruby~opbeans-python", - "isInverseEdge": true, - "source": "opbeans-ruby", - "sourceData": Object { - "agent.name": "ruby", - "id": "opbeans-ruby", - "service.environment": "production", - "service.name": "opbeans-ruby", - "serviceAnomalyStats": Object { - "actualValue": 62009.3356643357, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-ruby", - "transactionType": "request", - }, - }, - "target": "opbeans-python", - "targetData": Object { - "agent.name": "python", - "id": "opbeans-python", - "service.environment": "production", - "service.name": "opbeans-python", - "serviceAnomalyStats": Object { - "actualValue": 38862.7831325301, - "anomalyScore": 0.0725701910161626, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-python", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-rum~opbeans-dotnet", - "source": "opbeans-rum", - "sourceData": Object { - "agent.name": "rum-js", - "id": "opbeans-rum", - "service.environment": "testing", - "service.name": "opbeans-rum", - "serviceAnomalyStats": Object { - "actualValue": 1020870.96774194, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-rum", - "transactionType": "page-load", - }, - }, - "target": "opbeans-dotnet", - "targetData": Object { - "agent.name": "dotnet", - "id": "opbeans-dotnet", - "service.environment": "production", - "service.name": "opbeans-dotnet", - "serviceAnomalyStats": Object { - "actualValue": 868025.86875, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-dotnet", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-rum~opbeans-go", - "source": "opbeans-rum", - "sourceData": Object { - "agent.name": "rum-js", - "id": "opbeans-rum", - "service.environment": "testing", - "service.name": "opbeans-rum", - "serviceAnomalyStats": Object { - "actualValue": 1020870.96774194, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-rum", - "transactionType": "page-load", - }, - }, - "target": "opbeans-go", - "targetData": Object { - "agent.name": "go", - "id": "opbeans-go", - "service.environment": "testing", - "service.name": "opbeans-go", - "serviceAnomalyStats": Object { - "actualValue": 102786.319148936, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-go", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-rum~opbeans-java", - "source": "opbeans-rum", - "sourceData": Object { - "agent.name": "rum-js", - "id": "opbeans-rum", - "service.environment": "testing", - "service.name": "opbeans-rum", - "serviceAnomalyStats": Object { - "actualValue": 1020870.96774194, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-rum", - "transactionType": "page-load", - }, - }, - "target": "opbeans-java", - "targetData": Object { - "agent.name": "java", - "id": "opbeans-java", - "service.environment": "production", - "service.name": "opbeans-java", - "serviceAnomalyStats": Object { - "actualValue": 175568.855769231, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-java", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-rum~opbeans-node", - "source": "opbeans-rum", - "sourceData": Object { - "agent.name": "rum-js", - "id": "opbeans-rum", - "service.environment": "testing", - "service.name": "opbeans-rum", - "serviceAnomalyStats": Object { - "actualValue": 1020870.96774194, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-rum", - "transactionType": "page-load", - }, - }, - "target": "opbeans-node", - "targetData": Object { - "agent.name": "nodejs", - "id": "opbeans-node", - "service.environment": "testing", - "service.name": "opbeans-node", - "serviceAnomalyStats": Object { - "actualValue": 24819.2962962963, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-node", - "transactionType": "request", - }, - }, - }, - }, - Object { - "data": Object { - "id": "opbeans-rum~opbeans-ruby", - "source": "opbeans-rum", - "sourceData": Object { - "agent.name": "rum-js", - "id": "opbeans-rum", - "service.environment": "testing", - "service.name": "opbeans-rum", - "serviceAnomalyStats": Object { - "actualValue": 1020870.96774194, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-rum", - "transactionType": "page-load", - }, - }, - "target": "opbeans-ruby", - "targetData": Object { - "agent.name": "ruby", - "id": "opbeans-ruby", - "service.environment": "production", - "service.name": "opbeans-ruby", - "serviceAnomalyStats": Object { - "actualValue": 62009.3356643357, - "anomalyScore": 0, - "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-ruby", - "transactionType": "request", - }, - }, - }, - }, - ], -} -`; diff --git a/x-pack/test/apm_api_integration/tests/service_maps/service_maps.ts b/x-pack/test/apm_api_integration/tests/service_maps/service_maps.ts index ab1be97e0fd8a..167b6e1ff6dea 100644 --- a/x-pack/test/apm_api_integration/tests/service_maps/service_maps.ts +++ b/x-pack/test/apm_api_integration/tests/service_maps/service_maps.ts @@ -8,7 +8,7 @@ import querystring from 'querystring'; import url from 'url'; import expect from '@kbn/expect'; -import { isEmpty, uniq } from 'lodash'; +import { isEmpty, orderBy, uniq } from 'lodash'; import archives_metadata from '../../common/fixtures/es_archiver/archives_metadata'; import { PromiseReturnType } from '../../../../plugins/observability/typings/common'; import { FtrProviderContext } from '../../common/ftr_provider_context'; @@ -151,8 +151,6 @@ export default function serviceMapsApiTests({ getService }: FtrProviderContext) ">sqlite", ] `); - - expectSnapshot(elements).toMatch(); }); describe('with ML data', () => { @@ -186,60 +184,58 @@ export default function serviceMapsApiTests({ getService }: FtrProviderContext) expect(dataWithAnomalies).not.to.be.empty(); expectSnapshot(dataWithAnomalies.length).toMatchInline(`7`); - expectSnapshot(dataWithAnomalies.slice(0, 3)).toMatchInline(` + expectSnapshot(orderBy(dataWithAnomalies, 'data.id').slice(0, 3)).toMatchInline(` Array [ Object { "data": Object { - "agent.name": "rum-js", - "id": "opbeans-rum", - "service.environment": "testing", - "service.name": "opbeans-rum", + "agent.name": "dotnet", + "id": "opbeans-dotnet", + "service.environment": "production", + "service.name": "opbeans-dotnet", "serviceAnomalyStats": Object { - "actualValue": 1020870.96774194, + "actualValue": 868025.86875, "anomalyScore": 0, "healthStatus": "healthy", - "jobId": "apm-testing-41e5-high_mean_transaction_duration", - "serviceName": "opbeans-rum", - "transactionType": "page-load", + "jobId": "apm-production-6117-high_mean_transaction_duration", + "serviceName": "opbeans-dotnet", + "transactionType": "request", }, }, }, Object { "data": Object { - "agent.name": "ruby", - "id": "opbeans-ruby", - "service.environment": "production", - "service.name": "opbeans-ruby", + "agent.name": "go", + "id": "opbeans-go", + "service.environment": "testing", + "service.name": "opbeans-go", "serviceAnomalyStats": Object { - "actualValue": 62009.3356643357, + "actualValue": 102786.319148936, "anomalyScore": 0, "healthStatus": "healthy", - "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-ruby", + "jobId": "apm-testing-41e5-high_mean_transaction_duration", + "serviceName": "opbeans-go", "transactionType": "request", }, }, }, Object { "data": Object { - "agent.name": "python", - "id": "opbeans-python", + "agent.name": "java", + "id": "opbeans-java", "service.environment": "production", - "service.name": "opbeans-python", + "service.name": "opbeans-java", "serviceAnomalyStats": Object { - "actualValue": 38862.7831325301, - "anomalyScore": 0.0725701910161626, + "actualValue": 175568.855769231, + "anomalyScore": 0, "healthStatus": "healthy", "jobId": "apm-production-6117-high_mean_transaction_duration", - "serviceName": "opbeans-python", + "serviceName": "opbeans-java", "transactionType": "request", }, }, }, ] `); - - expectSnapshot(response.body).toMatch(); }); }); From 0dff7d0223cb789e4a34940ced036b18045beb1f Mon Sep 17 00:00:00 2001 From: Gil Raphaelli Date: Tue, 26 Oct 2021 11:16:04 -0400 Subject: [PATCH 40/58] APM project automation (#116306) --- .github/workflows/add-to-apm-project.yml | 28 ++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 .github/workflows/add-to-apm-project.yml diff --git a/.github/workflows/add-to-apm-project.yml b/.github/workflows/add-to-apm-project.yml new file mode 100644 index 0000000000000..a47425ce8eda5 --- /dev/null +++ b/.github/workflows/add-to-apm-project.yml @@ -0,0 +1,28 @@ +name: Add to APM Project +on: + issues: + types: + - labeled +jobs: + add_to_project: + runs-on: ubuntu-latest + steps: + - uses: octokit/graphql-action@v2.x + id: add_to_project + if: | + github.event.label.name == 'Team:apm' + with: + headers: '{"GraphQL-Features": "projects_next_graphql"}' + query: | + mutation add_to_project($projectid:String!,$contentid:String!) { + addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) { + projectNextItem { + id + } + } + } + projectid: ${{ env.PROJECT_ID }} + contentid: ${{ github.event.issue.node_id }} + env: + PROJECT_ID: "PN_kwDOAGc3Zs0VSg" + GITHUB_TOKEN: ${{ secrets.KIBANAMACHINE_TOKEN }} From 3d47a0348950d48f6174a96d82bae3ce25f58cee Mon Sep 17 00:00:00 2001 From: Mark Hopkin Date: Tue, 26 Oct 2021 16:19:18 +0100 Subject: [PATCH 41/58] change save integration button text (#116267) --- .../sections/agent_policy/create_package_policy_page/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.tsx index b30d51bb46aaa..875180e5795c2 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/index.tsx @@ -553,7 +553,7 @@ export const CreatePackagePolicyPage: React.FunctionComponent = () => { > From dc77c89e842f84f4db843a4d93a0f86fcd8dd7ee Mon Sep 17 00:00:00 2001 From: Giorgos Bamparopoulos Date: Tue, 26 Oct 2021 16:35:08 +0100 Subject: [PATCH 42/58] Update dependencies overview route to use backendName as a query param (#115226) * Update dependencies overview route to use backendName as a query param * Remove backendName from context * Move backendMetadataFetch call to the place that is used and remove ApmBackendContext * Update API routes and tests * Add redirect from the old route --- .../backend_detail_dependencies_table.tsx | 18 +-- .../backend_error_rate_chart.tsx | 13 +- .../backend_latency_chart.tsx | 13 +- .../backend_throughput_chart.tsx | 13 +- .../app/backend_detail_overview/index.tsx | 120 +++++++++--------- .../index.tsx | 2 +- .../service_map/Popover/backend_contents.tsx | 15 +-- .../index.tsx | 2 +- .../span_flyout/sticky_span_properties.tsx | 6 +- .../public/components/routing/home/index.tsx | 12 +- ...edirect_to_backend_overview_route_view.tsx | 22 ++++ .../templates/backend_detail_template.tsx | 33 ++++- .../shared/backend_link.stories.tsx | 4 +- .../public/components/shared/backend_link.tsx | 9 +- .../apm_backend/apm_backend_context.tsx | 74 ----------- .../apm_backend/use_apm_backend_context.tsx | 20 --- x-pack/plugins/apm/server/routes/backends.ts | 83 +++++++----- .../plugins/apm/server/routes/service_map.ts | 14 +- .../tests/service_maps/service_maps.ts | 10 +- .../tests/throughput/dependencies_apis.ts | 8 +- 20 files changed, 223 insertions(+), 268 deletions(-) create mode 100644 x-pack/plugins/apm/public/components/routing/home/redirect_to_backend_overview_route_view.tsx delete mode 100644 x-pack/plugins/apm/public/context/apm_backend/apm_backend_context.tsx delete mode 100644 x-pack/plugins/apm/public/context/apm_backend/use_apm_backend_context.tsx diff --git a/x-pack/plugins/apm/public/components/app/backend_detail_overview/backend_detail_dependencies_table.tsx b/x-pack/plugins/apm/public/components/app/backend_detail_overview/backend_detail_dependencies_table.tsx index 57efea4ffdcac..72273bf8c9e19 100644 --- a/x-pack/plugins/apm/public/components/app/backend_detail_overview/backend_detail_dependencies_table.tsx +++ b/x-pack/plugins/apm/public/components/app/backend_detail_overview/backend_detail_dependencies_table.tsx @@ -13,7 +13,6 @@ import { useUrlParams } from '../../../context/url_params_context/use_url_params import { useFetcher } from '../../../hooks/use_fetcher'; import { getTimeRangeComparison } from '../../shared/time_comparison/get_time_range_comparison'; import { DependenciesTable } from '../../shared/dependencies_table'; -import { useApmBackendContext } from '../../../context/apm_backend/use_apm_backend_context'; import { ServiceLink } from '../../shared/service_link'; import { useTimeRange } from '../../../hooks/use_time_range'; @@ -23,8 +22,8 @@ export function BackendDetailDependenciesTable() { } = useUrlParams(); const { - query: { rangeFrom, rangeTo, kuery, environment }, - } = useApmParams('/backends/{backendName}/overview'); + query: { backendName, rangeFrom, rangeTo, kuery, environment }, + } = useApmParams('/backends/overview'); const { start, end } = useTimeRange({ rangeFrom, rangeTo }); @@ -35,8 +34,6 @@ export function BackendDetailDependenciesTable() { comparisonType, }); - const { backendName } = useApmBackendContext(); - const { data, status } = useFetcher( (callApmApi) => { if (!start || !end) { @@ -44,12 +41,17 @@ export function BackendDetailDependenciesTable() { } return callApmApi({ - endpoint: 'GET /internal/apm/backends/{backendName}/upstream_services', + endpoint: 'GET /internal/apm/backends/upstream_services', params: { - path: { + query: { backendName, + start, + end, + environment, + numBuckets: 20, + offset, + kuery, }, - query: { start, end, environment, numBuckets: 20, offset, kuery }, }, }); }, diff --git a/x-pack/plugins/apm/public/components/app/backend_detail_overview/backend_error_rate_chart.tsx b/x-pack/plugins/apm/public/components/app/backend_detail_overview/backend_error_rate_chart.tsx index cf14145dba82a..3b19e8b6dd920 100644 --- a/x-pack/plugins/apm/public/components/app/backend_detail_overview/backend_error_rate_chart.tsx +++ b/x-pack/plugins/apm/public/components/app/backend_detail_overview/backend_error_rate_chart.tsx @@ -7,7 +7,6 @@ import React, { useMemo } from 'react'; import { i18n } from '@kbn/i18n'; import { asPercent } from '../../../../common/utils/formatters'; -import { useApmBackendContext } from '../../../context/apm_backend/use_apm_backend_context'; import { useComparison } from '../../../hooks/use_comparison'; import { useFetcher } from '../../../hooks/use_fetcher'; import { useTimeRange } from '../../../hooks/use_time_range'; @@ -25,13 +24,11 @@ export function BackendFailedTransactionRateChart({ }: { height: number; }) { - const { backendName } = useApmBackendContext(); - const theme = useTheme(); const { - query: { kuery, environment, rangeFrom, rangeTo }, - } = useApmParams('/backends/{backendName}/overview'); + query: { backendName, kuery, environment, rangeFrom, rangeTo }, + } = useApmParams('/backends/overview'); const { start, end } = useTimeRange({ rangeFrom, rangeTo }); @@ -44,12 +41,10 @@ export function BackendFailedTransactionRateChart({ } return callApmApi({ - endpoint: 'GET /internal/apm/backends/{backendName}/charts/error_rate', + endpoint: 'GET /internal/apm/backends/charts/error_rate', params: { - path: { - backendName, - }, query: { + backendName, start, end, offset, diff --git a/x-pack/plugins/apm/public/components/app/backend_detail_overview/backend_latency_chart.tsx b/x-pack/plugins/apm/public/components/app/backend_detail_overview/backend_latency_chart.tsx index 3f5a56d55d823..2e750141257a5 100644 --- a/x-pack/plugins/apm/public/components/app/backend_detail_overview/backend_latency_chart.tsx +++ b/x-pack/plugins/apm/public/components/app/backend_detail_overview/backend_latency_chart.tsx @@ -7,7 +7,6 @@ import React, { useMemo } from 'react'; import { i18n } from '@kbn/i18n'; import { getDurationFormatter } from '../../../../common/utils/formatters'; -import { useApmBackendContext } from '../../../context/apm_backend/use_apm_backend_context'; import { useComparison } from '../../../hooks/use_comparison'; import { useFetcher } from '../../../hooks/use_fetcher'; import { useTimeRange } from '../../../hooks/use_time_range'; @@ -21,13 +20,11 @@ import { import { useApmParams } from '../../../hooks/use_apm_params'; export function BackendLatencyChart({ height }: { height: number }) { - const { backendName } = useApmBackendContext(); - const theme = useTheme(); const { - query: { rangeFrom, rangeTo, kuery, environment }, - } = useApmParams('/backends/{backendName}/overview'); + query: { backendName, rangeFrom, rangeTo, kuery, environment }, + } = useApmParams('/backends/overview'); const { start, end } = useTimeRange({ rangeFrom, rangeTo }); @@ -40,12 +37,10 @@ export function BackendLatencyChart({ height }: { height: number }) { } return callApmApi({ - endpoint: 'GET /internal/apm/backends/{backendName}/charts/latency', + endpoint: 'GET /internal/apm/backends/charts/latency', params: { - path: { - backendName, - }, query: { + backendName, start, end, offset, diff --git a/x-pack/plugins/apm/public/components/app/backend_detail_overview/backend_throughput_chart.tsx b/x-pack/plugins/apm/public/components/app/backend_detail_overview/backend_throughput_chart.tsx index f5d9cb7a7a55e..6f201f468a9e3 100644 --- a/x-pack/plugins/apm/public/components/app/backend_detail_overview/backend_throughput_chart.tsx +++ b/x-pack/plugins/apm/public/components/app/backend_detail_overview/backend_throughput_chart.tsx @@ -7,7 +7,6 @@ import React, { useMemo } from 'react'; import { i18n } from '@kbn/i18n'; import { asTransactionRate } from '../../../../common/utils/formatters'; -import { useApmBackendContext } from '../../../context/apm_backend/use_apm_backend_context'; import { useComparison } from '../../../hooks/use_comparison'; import { useFetcher } from '../../../hooks/use_fetcher'; import { useTimeRange } from '../../../hooks/use_time_range'; @@ -17,13 +16,11 @@ import { useTheme } from '../../../hooks/use_theme'; import { useApmParams } from '../../../hooks/use_apm_params'; export function BackendThroughputChart({ height }: { height: number }) { - const { backendName } = useApmBackendContext(); - const theme = useTheme(); const { - query: { rangeFrom, rangeTo, kuery, environment }, - } = useApmParams('/backends/{backendName}/overview'); + query: { backendName, rangeFrom, rangeTo, kuery, environment }, + } = useApmParams('/backends/overview'); const { start, end } = useTimeRange({ rangeFrom, rangeTo }); @@ -36,12 +33,10 @@ export function BackendThroughputChart({ height }: { height: number }) { } return callApmApi({ - endpoint: 'GET /internal/apm/backends/{backendName}/charts/throughput', + endpoint: 'GET /internal/apm/backends/charts/throughput', params: { - path: { - backendName, - }, query: { + backendName, start, end, offset, diff --git a/x-pack/plugins/apm/public/components/app/backend_detail_overview/index.tsx b/x-pack/plugins/apm/public/components/app/backend_detail_overview/index.tsx index 3b4deac794df0..6823b571e9597 100644 --- a/x-pack/plugins/apm/public/components/app/backend_detail_overview/index.tsx +++ b/x-pack/plugins/apm/public/components/app/backend_detail_overview/index.tsx @@ -11,7 +11,6 @@ import React from 'react'; import { EuiSpacer } from '@elastic/eui'; import { EuiTitle } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; -import { ApmBackendContextProvider } from '../../../context/apm_backend/apm_backend_context'; import { useBreadcrumb } from '../../../context/breadcrumbs/use_breadcrumb'; import { ChartPointerEventContextProvider } from '../../../context/chart_pointer_event/chart_pointer_event_context'; import { useApmParams } from '../../../hooks/use_apm_params'; @@ -31,8 +30,8 @@ import { useBreakpoints } from '../../../hooks/use_breakpoints'; export function BackendDetailOverview() { const { - path: { backendName }, query: { + backendName, rangeFrom, rangeTo, refreshInterval, @@ -40,7 +39,7 @@ export function BackendDetailOverview() { environment, kuery, }, - } = useApmParams('/backends/{backendName}/overview'); + } = useApmParams('/backends/overview'); const apmRouter = useApmRouter(); @@ -60,9 +59,9 @@ export function BackendDetailOverview() { }, { title: backendName, - href: apmRouter.link('/backends/{backendName}/overview', { - path: { backendName }, + href: apmRouter.link('/backends/overview', { query: { + backendName, rangeFrom, rangeTo, refreshInterval, @@ -82,62 +81,59 @@ export function BackendDetailOverview() { const largeScreenOrSmaller = useBreakpoints().isLarge; return ( - - - - - - - - -

- {i18n.translate( - 'xpack.apm.backendDetailLatencyChartTitle', - { defaultMessage: 'Latency' } - )} -

-
- -
-
- - - -

- {i18n.translate( - 'xpack.apm.backendDetailThroughputChartTitle', - { defaultMessage: 'Throughput' } - )} -

-
- -
-
- - - -

- {i18n.translate( - 'xpack.apm.backendDetailFailedTransactionRateChartTitle', - { defaultMessage: 'Failed transaction rate' } - )} -

-
- -
-
-
-
- - -
-
+ + + + + + + +

+ {i18n.translate('xpack.apm.backendDetailLatencyChartTitle', { + defaultMessage: 'Latency', + })} +

+
+ +
+
+ + + +

+ {i18n.translate( + 'xpack.apm.backendDetailThroughputChartTitle', + { defaultMessage: 'Throughput' } + )} +

+
+ +
+
+ + + +

+ {i18n.translate( + 'xpack.apm.backendDetailFailedTransactionRateChartTitle', + { defaultMessage: 'Failed transaction rate' } + )} +

+
+ +
+
+
+
+ + +
); } diff --git a/x-pack/plugins/apm/public/components/app/backend_inventory/backend_inventory_dependencies_table/index.tsx b/x-pack/plugins/apm/public/components/app/backend_inventory/backend_inventory_dependencies_table/index.tsx index c214c4348bbe7..b84e8830aae5f 100644 --- a/x-pack/plugins/apm/public/components/app/backend_inventory/backend_inventory_dependencies_table/index.tsx +++ b/x-pack/plugins/apm/public/components/app/backend_inventory/backend_inventory_dependencies_table/index.tsx @@ -64,10 +64,10 @@ export function BackendInventoryDependenciesTable() { } const link = ( { if (backendName) { return callApmApi({ - endpoint: 'GET /internal/apm/service-map/backend/{backendName}', + endpoint: 'GET /internal/apm/service-map/backend', params: { - path: { backendName }, query: { + backendName, environment, start, end, @@ -57,12 +57,11 @@ export function BackendContents({ ); const isLoading = status === FETCH_STATUS.LOADING; - const detailsUrl = apmRouter.link('/backends/{backendName}/overview', { - path: { backendName }, - query: query as TypeOf< - ApmRoutes, - '/backends/{backendName}/overview' - >['query'], + const detailsUrl = apmRouter.link('/backends/overview', { + query: { + ...query, + backendName, + } as TypeOf['query'], }); const trackEvent = useUiTracker(); diff --git a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_dependencies_table/index.tsx b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_dependencies_table/index.tsx index eea15c0e915f0..208d1a30a46d1 100644 --- a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_dependencies_table/index.tsx +++ b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_dependencies_table/index.tsx @@ -76,10 +76,10 @@ export function ServiceOverviewDependenciesTable({ const itemLink = location.type === NodeType.backend ? ( { diff --git a/x-pack/plugins/apm/public/components/routing/home/index.tsx b/x-pack/plugins/apm/public/components/routing/home/index.tsx index 7372a40a59bbe..025fa8ddcc8a0 100644 --- a/x-pack/plugins/apm/public/components/routing/home/index.tsx +++ b/x-pack/plugins/apm/public/components/routing/home/index.tsx @@ -20,6 +20,7 @@ import { ServiceInventory } from '../../app/service_inventory'; import { ServiceMapHome } from '../../app/service_map'; import { TraceOverview } from '../../app/trace_overview'; import { ApmMainTemplate } from '../templates/apm_main_template'; +import { RedirectToBackendOverviewRouteView } from './redirect_to_backend_overview_route_view'; function page({ path, @@ -109,13 +110,22 @@ export const home = { children: [ { path: '/backends/{backendName}/overview', - element: , + element: , params: t.type({ path: t.type({ backendName: t.string, }), }), }, + { + path: '/backends/overview', + element: , + params: t.type({ + query: t.type({ + backendName: t.string, + }), + }), + }, page({ path: '/backends', title: DependenciesInventoryTitle, diff --git a/x-pack/plugins/apm/public/components/routing/home/redirect_to_backend_overview_route_view.tsx b/x-pack/plugins/apm/public/components/routing/home/redirect_to_backend_overview_route_view.tsx new file mode 100644 index 0000000000000..ef6d04828c19d --- /dev/null +++ b/x-pack/plugins/apm/public/components/routing/home/redirect_to_backend_overview_route_view.tsx @@ -0,0 +1,22 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import qs from 'query-string'; +import React from 'react'; +import { Redirect } from 'react-router-dom'; +import { useApmParams } from '../../../hooks/use_apm_params'; + +export function RedirectToBackendOverviewRouteView() { + const { + path: { backendName }, + query, + } = useApmParams('/backends/{backendName}/overview'); + + const search = qs.stringify({ ...query, backendName }); + + return ; +} diff --git a/x-pack/plugins/apm/public/components/routing/templates/backend_detail_template.tsx b/x-pack/plugins/apm/public/components/routing/templates/backend_detail_template.tsx index 27eb16a0221b7..f87e9a46df584 100644 --- a/x-pack/plugins/apm/public/components/routing/templates/backend_detail_template.tsx +++ b/x-pack/plugins/apm/public/components/routing/templates/backend_detail_template.tsx @@ -7,9 +7,11 @@ import { EuiFlexGroup, EuiFlexItem, EuiTitle } from '@elastic/eui'; import React from 'react'; -import { useApmBackendContext } from '../../../context/apm_backend/use_apm_backend_context'; import { ApmMainTemplate } from './apm_main_template'; import { SpanIcon } from '../../shared/span_icon'; +import { useApmParams } from '../../../hooks/use_apm_params'; +import { useTimeRange } from '../../../hooks/use_time_range'; +import { useFetcher } from '../../../hooks/use_fetcher'; interface Props { title: string; @@ -18,11 +20,32 @@ interface Props { export function BackendDetailTemplate({ title, children }: Props) { const { - backendName, - metadata: { data }, - } = useApmBackendContext(); + query: { backendName, rangeFrom, rangeTo }, + } = useApmParams('/backends/overview'); - const metadata = data?.metadata; + const { start, end } = useTimeRange({ rangeFrom, rangeTo }); + + const backendMetadataFetch = useFetcher( + (callApmApi) => { + if (!start || !end) { + return; + } + + return callApmApi({ + endpoint: 'GET /internal/apm/backends/metadata', + params: { + query: { + backendName, + start, + end, + }, + }, + }); + }, + [backendName, start, end] + ); + + const { data: { metadata } = {} } = backendMetadataFetch; return ( = (args) => { return ; }; Example.args = { - backendName: 'postgres', query: { + backendName: 'postgres', environment: 'ENVIRONMENT_ALL', kuery: '', rangeFrom: 'now-15m', rangeTo: 'now', }, - type: 'db', - subtype: 'postgresql', }; diff --git a/x-pack/plugins/apm/public/components/shared/backend_link.tsx b/x-pack/plugins/apm/public/components/shared/backend_link.tsx index 342c668d2efdb..92cad37273b02 100644 --- a/x-pack/plugins/apm/public/components/shared/backend_link.tsx +++ b/x-pack/plugins/apm/public/components/shared/backend_link.tsx @@ -17,15 +17,13 @@ import { SpanIcon } from './span_icon'; const StyledLink = euiStyled(EuiLink)`${truncate('100%')};`; interface BackendLinkProps { - backendName: string; - query: TypeOf['query']; + query: TypeOf['query']; subtype?: string; type?: string; onClick?: React.ComponentProps['onClick']; } export function BackendLink({ - backendName, query, subtype, type, @@ -35,8 +33,7 @@ export function BackendLink({ return ( - {backendName} + {query.backendName} ); diff --git a/x-pack/plugins/apm/public/context/apm_backend/apm_backend_context.tsx b/x-pack/plugins/apm/public/context/apm_backend/apm_backend_context.tsx deleted file mode 100644 index 6093f05c2cb02..0000000000000 --- a/x-pack/plugins/apm/public/context/apm_backend/apm_backend_context.tsx +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { createContext, useMemo } from 'react'; -import { FETCH_STATUS, useFetcher } from '../../hooks/use_fetcher'; -import { useApmParams } from '../../hooks/use_apm_params'; -import { APIReturnType } from '../../services/rest/createCallApmApi'; -import { useTimeRange } from '../../hooks/use_time_range'; - -export const ApmBackendContext = createContext< - | { - backendName: string; - metadata: { - data?: APIReturnType<'GET /internal/apm/backends/{backendName}/metadata'>; - status?: FETCH_STATUS; - }; - } - | undefined ->(undefined); - -export function ApmBackendContextProvider({ - children, -}: { - children: React.ReactNode; -}) { - const { - path: { backendName }, - query: { rangeFrom, rangeTo }, - } = useApmParams('/backends/{backendName}/overview'); - - const { start, end } = useTimeRange({ rangeFrom, rangeTo }); - - const backendMetadataFetch = useFetcher( - (callApmApi) => { - if (!start || !end) { - return; - } - - return callApmApi({ - endpoint: 'GET /internal/apm/backends/{backendName}/metadata', - params: { - path: { - backendName, - }, - query: { - start, - end, - }, - }, - }); - }, - [backendName, start, end] - ); - - const value = useMemo(() => { - return { - backendName, - metadata: { - data: backendMetadataFetch.data, - status: backendMetadataFetch.status, - }, - }; - }, [backendName, backendMetadataFetch.data, backendMetadataFetch.status]); - - return ( - - {children} - - ); -} diff --git a/x-pack/plugins/apm/public/context/apm_backend/use_apm_backend_context.tsx b/x-pack/plugins/apm/public/context/apm_backend/use_apm_backend_context.tsx deleted file mode 100644 index 5a48014c75662..0000000000000 --- a/x-pack/plugins/apm/public/context/apm_backend/use_apm_backend_context.tsx +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import { useContext } from 'react'; -import { ApmBackendContext } from './apm_backend_context'; - -export function useApmBackendContext() { - const context = useContext(ApmBackendContext); - - if (!context) { - throw new Error( - 'ApmBackendContext has no set value, did you forget rendering ApmBackendContextProvider?' - ); - } - - return context; -} diff --git a/x-pack/plugins/apm/server/routes/backends.ts b/x-pack/plugins/apm/server/routes/backends.ts index feb4ca8bb978c..03466c7443665 100644 --- a/x-pack/plugins/apm/server/routes/backends.ts +++ b/x-pack/plugins/apm/server/routes/backends.ts @@ -65,13 +65,14 @@ const topBackendsRoute = createApmServerRoute({ }); const upstreamServicesForBackendRoute = createApmServerRoute({ - endpoint: 'GET /internal/apm/backends/{backendName}/upstream_services', + endpoint: 'GET /internal/apm/backends/upstream_services', params: t.intersection([ t.type({ - path: t.type({ - backendName: t.string, - }), - query: t.intersection([rangeRt, t.type({ numBuckets: toNumberRt })]), + query: t.intersection([ + t.type({ backendName: t.string }), + rangeRt, + t.type({ numBuckets: toNumberRt }), + ]), }), t.partial({ query: t.intersection([environmentRt, offsetRt, kueryRt]), @@ -83,8 +84,15 @@ const upstreamServicesForBackendRoute = createApmServerRoute({ handler: async (resources) => { const setup = await setupRequest(resources); const { - path: { backendName }, - query: { environment, offset, numBuckets, kuery, start, end }, + query: { + backendName, + environment, + offset, + numBuckets, + kuery, + start, + end, + }, } = resources.params; const opts = { @@ -121,12 +129,9 @@ const upstreamServicesForBackendRoute = createApmServerRoute({ }); const backendMetadataRoute = createApmServerRoute({ - endpoint: 'GET /internal/apm/backends/{backendName}/metadata', + endpoint: 'GET /internal/apm/backends/metadata', params: t.type({ - path: t.type({ - backendName: t.string, - }), - query: rangeRt, + query: t.intersection([t.type({ backendName: t.string }), rangeRt]), }), options: { tags: ['access:apm'], @@ -134,9 +139,8 @@ const backendMetadataRoute = createApmServerRoute({ handler: async (resources) => { const setup = await setupRequest(resources); const { params } = resources; - const { backendName } = params.path; - const { start, end } = params.query; + const { backendName, start, end } = params.query; const metadata = await getMetadataForBackend({ backendName, @@ -150,12 +154,15 @@ const backendMetadataRoute = createApmServerRoute({ }); const backendLatencyChartsRoute = createApmServerRoute({ - endpoint: 'GET /internal/apm/backends/{backendName}/charts/latency', + endpoint: 'GET /internal/apm/backends/charts/latency', params: t.type({ - path: t.type({ - backendName: t.string, - }), - query: t.intersection([rangeRt, kueryRt, environmentRt, offsetRt]), + query: t.intersection([ + t.type({ backendName: t.string }), + rangeRt, + kueryRt, + environmentRt, + offsetRt, + ]), }), options: { tags: ['access:apm'], @@ -163,8 +170,8 @@ const backendLatencyChartsRoute = createApmServerRoute({ handler: async (resources) => { const setup = await setupRequest(resources); const { params } = resources; - const { backendName } = params.path; - const { kuery, environment, offset, start, end } = params.query; + const { backendName, kuery, environment, offset, start, end } = + params.query; const [currentTimeseries, comparisonTimeseries] = await Promise.all([ getLatencyChartsForBackend({ @@ -193,12 +200,15 @@ const backendLatencyChartsRoute = createApmServerRoute({ }); const backendThroughputChartsRoute = createApmServerRoute({ - endpoint: 'GET /internal/apm/backends/{backendName}/charts/throughput', + endpoint: 'GET /internal/apm/backends/charts/throughput', params: t.type({ - path: t.type({ - backendName: t.string, - }), - query: t.intersection([rangeRt, kueryRt, environmentRt, offsetRt]), + query: t.intersection([ + t.type({ backendName: t.string }), + rangeRt, + kueryRt, + environmentRt, + offsetRt, + ]), }), options: { tags: ['access:apm'], @@ -206,8 +216,8 @@ const backendThroughputChartsRoute = createApmServerRoute({ handler: async (resources) => { const setup = await setupRequest(resources); const { params } = resources; - const { backendName } = params.path; - const { kuery, environment, offset, start, end } = params.query; + const { backendName, kuery, environment, offset, start, end } = + params.query; const [currentTimeseries, comparisonTimeseries] = await Promise.all([ getThroughputChartsForBackend({ @@ -236,12 +246,15 @@ const backendThroughputChartsRoute = createApmServerRoute({ }); const backendFailedTransactionRateChartsRoute = createApmServerRoute({ - endpoint: 'GET /internal/apm/backends/{backendName}/charts/error_rate', + endpoint: 'GET /internal/apm/backends/charts/error_rate', params: t.type({ - path: t.type({ - backendName: t.string, - }), - query: t.intersection([rangeRt, kueryRt, environmentRt, offsetRt]), + query: t.intersection([ + t.type({ backendName: t.string }), + rangeRt, + kueryRt, + environmentRt, + offsetRt, + ]), }), options: { tags: ['access:apm'], @@ -249,8 +262,8 @@ const backendFailedTransactionRateChartsRoute = createApmServerRoute({ handler: async (resources) => { const setup = await setupRequest(resources); const { params } = resources; - const { backendName } = params.path; - const { kuery, environment, offset, start, end } = params.query; + const { backendName, kuery, environment, offset, start, end } = + params.query; const [currentTimeseries, comparisonTimeseries] = await Promise.all([ getErrorRateChartsForBackend({ diff --git a/x-pack/plugins/apm/server/routes/service_map.ts b/x-pack/plugins/apm/server/routes/service_map.ts index 038f909d7b334..3711ee20d814b 100644 --- a/x-pack/plugins/apm/server/routes/service_map.ts +++ b/x-pack/plugins/apm/server/routes/service_map.ts @@ -114,12 +114,13 @@ const serviceMapServiceNodeRoute = createApmServerRoute({ }); const serviceMapBackendNodeRoute = createApmServerRoute({ - endpoint: 'GET /internal/apm/service-map/backend/{backendName}', + endpoint: 'GET /internal/apm/service-map/backend', params: t.type({ - path: t.type({ - backendName: t.string, - }), - query: t.intersection([environmentRt, rangeRt]), + query: t.intersection([ + t.type({ backendName: t.string }), + environmentRt, + rangeRt, + ]), }), options: { tags: ['access:apm'] }, handler: async (resources) => { @@ -134,8 +135,7 @@ const serviceMapBackendNodeRoute = createApmServerRoute({ const setup = await setupRequest(resources); const { - path: { backendName }, - query: { environment, start, end }, + query: { backendName, environment, start, end }, } = params; return getServiceMapBackendNodeInfo({ diff --git a/x-pack/test/apm_api_integration/tests/service_maps/service_maps.ts b/x-pack/test/apm_api_integration/tests/service_maps/service_maps.ts index 167b6e1ff6dea..2da57c0a25779 100644 --- a/x-pack/test/apm_api_integration/tests/service_maps/service_maps.ts +++ b/x-pack/test/apm_api_integration/tests/service_maps/service_maps.ts @@ -76,14 +76,15 @@ export default function serviceMapsApiTests({ getService }: FtrProviderContext) }); }); - describe('/internal/apm/service-map/backend/{backendName}', () => { + describe('/internal/apm/service-map/backend', () => { it('returns an object with nulls', async () => { const q = querystring.stringify({ + backendName: 'postgres', start: metadata.start, end: metadata.end, environment: 'ENVIRONMENT_ALL', }); - const response = await supertest.get(`/internal/apm/service-map/backend/postgres?${q}`); + const response = await supertest.get(`/internal/apm/service-map/backend?${q}`); expect(response.status).to.be(200); @@ -305,14 +306,15 @@ export default function serviceMapsApiTests({ getService }: FtrProviderContext) }); }); - describe('/internal/apm/service-map/backend/{backendName}', () => { + describe('/internal/apm/service-map/backend', () => { it('returns an object with data', async () => { const q = querystring.stringify({ + backendName: 'postgresql', start: metadata.start, end: metadata.end, environment: 'ENVIRONMENT_ALL', }); - const response = await supertest.get(`/internal/apm/service-map/backend/postgresql?${q}`); + const response = await supertest.get(`/internal/apm/service-map/backend?${q}`); expect(response.status).to.be(200); diff --git a/x-pack/test/apm_api_integration/tests/throughput/dependencies_apis.ts b/x-pack/test/apm_api_integration/tests/throughput/dependencies_apis.ts index 22b4486181e62..1aa3ebb7b985b 100644 --- a/x-pack/test/apm_api_integration/tests/throughput/dependencies_apis.ts +++ b/x-pack/test/apm_api_integration/tests/throughput/dependencies_apis.ts @@ -39,21 +39,21 @@ export default function ApiTest({ getService }: FtrProviderContext) { }, }), apmApiClient.readUser({ - endpoint: `GET /internal/apm/backends/{backendName}/charts/throughput`, + endpoint: `GET /internal/apm/backends/charts/throughput`, params: { - path: { backendName: overrides?.backendName || 'elasticsearch' }, query: { ...commonQuery, + backendName: overrides?.backendName || 'elasticsearch', kuery: '', }, }, }), apmApiClient.readUser({ - endpoint: `GET /internal/apm/backends/{backendName}/upstream_services`, + endpoint: `GET /internal/apm/backends/upstream_services`, params: { - path: { backendName: overrides?.backendName || 'elasticsearch' }, query: { ...commonQuery, + backendName: overrides?.backendName || 'elasticsearch', numBuckets: 20, offset: '1d', kuery: '', From 6f779c6d1785ef54c49189409e2e5255b804d4b0 Mon Sep 17 00:00:00 2001 From: Gil Raphaelli Date: Tue, 26 Oct 2021 11:35:26 -0400 Subject: [PATCH 43/58] use separate token for APM (#116315) --- .github/workflows/add-to-apm-project.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/add-to-apm-project.yml b/.github/workflows/add-to-apm-project.yml index a47425ce8eda5..26ff71fbdca8c 100644 --- a/.github/workflows/add-to-apm-project.yml +++ b/.github/workflows/add-to-apm-project.yml @@ -25,4 +25,4 @@ jobs: contentid: ${{ github.event.issue.node_id }} env: PROJECT_ID: "PN_kwDOAGc3Zs0VSg" - GITHUB_TOKEN: ${{ secrets.KIBANAMACHINE_TOKEN }} + GITHUB_TOKEN: ${{ secrets.APM_TECH_KIBANA_USER_TOKEN }} From b17e01dd9a8e77aa45438d89bad60ca2bd4b12b6 Mon Sep 17 00:00:00 2001 From: Giorgos Bamparopoulos Date: Tue, 26 Oct 2021 16:42:32 +0100 Subject: [PATCH 44/58] [APM] Set level for all registered deprecations (#116272) --- x-pack/plugins/apm/server/index.ts | 37 +++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/apm/server/index.ts b/x-pack/plugins/apm/server/index.ts index 1ed54be0271dd..6bf3b2cb493f1 100644 --- a/x-pack/plugins/apm/server/index.ts +++ b/x-pack/plugins/apm/server/index.ts @@ -62,23 +62,38 @@ export const config: PluginConfigDescriptor = { deprecations: ({ renameFromRoot, deprecateFromRoot, unusedFromRoot }) => [ renameFromRoot( 'apm_oss.transactionIndices', - 'xpack.apm.indices.transaction' + 'xpack.apm.indices.transaction', + { level: 'warning' } ), - renameFromRoot('apm_oss.spanIndices', 'xpack.apm.indices.span'), - renameFromRoot('apm_oss.errorIndices', 'xpack.apm.indices.error'), - renameFromRoot('apm_oss.metricsIndices', 'xpack.apm.indices.metric'), - renameFromRoot('apm_oss.sourcemapIndices', 'xpack.apm.indices.sourcemap'), - renameFromRoot('apm_oss.onboardingIndices', 'xpack.apm.indices.onboarding'), - deprecateFromRoot('apm_oss.enabled', '8.0.0'), - unusedFromRoot('apm_oss.fleetMode'), - unusedFromRoot('apm_oss.indexPattern'), + renameFromRoot('apm_oss.spanIndices', 'xpack.apm.indices.span', { + level: 'warning', + }), + renameFromRoot('apm_oss.errorIndices', 'xpack.apm.indices.error', { + level: 'warning', + }), + renameFromRoot('apm_oss.metricsIndices', 'xpack.apm.indices.metric', { + level: 'warning', + }), + renameFromRoot('apm_oss.sourcemapIndices', 'xpack.apm.indices.sourcemap', { + level: 'warning', + }), + renameFromRoot( + 'apm_oss.onboardingIndices', + 'xpack.apm.indices.onboarding', + { level: 'warning' } + ), + deprecateFromRoot('apm_oss.enabled', '8.0.0', { level: 'warning' }), + unusedFromRoot('apm_oss.fleetMode', { level: 'warning' }), + unusedFromRoot('apm_oss.indexPattern', { level: 'warning' }), renameFromRoot( 'xpack.apm.maxServiceEnvironments', - `uiSettings.overrides[${maxSuggestions}]` + `uiSettings.overrides[${maxSuggestions}]`, + { level: 'warning' } ), renameFromRoot( 'xpack.apm.maxServiceSelections', - `uiSettings.overrides[${maxSuggestions}]` + `uiSettings.overrides[${maxSuggestions}]`, + { level: 'warning' } ), ], exposeToBrowser: { From 9911883ba4af3a109700a74f6096192c6ed6336e Mon Sep 17 00:00:00 2001 From: Andrew Goldstein Date: Tue, 26 Oct 2021 09:46:01 -0600 Subject: [PATCH 45/58] [Security Solution] Prevents the `Status` badge from stretching in the Alert Details flyout (#116237) ## [Security Solution] Prevents the `Status` badge from stretching in the Alert Details flyout This PR fixes to prevent the `Status` badge from stretching in the Alert Details flyout. ### Screenshots **Before:** ![before](https://user-images.githubusercontent.com/4459398/138806049-895317b6-2990-43f6-b978-dab1711494a5.png) After Chrome `95.0.4638.54`: ![after-chrome](https://user-images.githubusercontent.com/4459398/138806164-ce802982-5c5a-4a30-a906-1583e2ba9939.png) After Firefox `93.0`: ![after-firefox](https://user-images.githubusercontent.com/4459398/138806249-152a6b33-f1b9-4a5b-8607-8da29689d599.png) After Safari `15.0`: ![after-safari](https://user-images.githubusercontent.com/4459398/138806320-45202b3a-1f84-4a4f-8fd0-107523597a22.png) ### Details The fix overrides the default value of `EuiFlexGroup`'s `alignItems` prop, which has a default value of `stretch`, per the image below: ![EuiFlexGroup_alignItems](https://user-images.githubusercontent.com/4459398/138805941-96e06533-8df7-447c-bb74-9278a06d39db.png) --- .../alert_summary_view.test.tsx.snap | 32 +++++++++---------- .../table/field_value_cell.test.tsx | 6 ++++ .../event_details/table/field_value_cell.tsx | 1 + 3 files changed, 23 insertions(+), 16 deletions(-) diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/__snapshots__/alert_summary_view.test.tsx.snap b/x-pack/plugins/security_solution/public/common/components/event_details/__snapshots__/alert_summary_view.test.tsx.snap index 772badd80ce53..d97208a500714 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/__snapshots__/alert_summary_view.test.tsx.snap +++ b/x-pack/plugins/security_solution/public/common/components/event_details/__snapshots__/alert_summary_view.test.tsx.snap @@ -136,7 +136,7 @@ exports[`AlertSummaryView Behavior event code renders additional summary rows 1` class="euiTableCellContent flyoutOverviewDescription euiTableCellContent--overflowingContent" >
{ ); }); + test('it aligns items at the start of the group to prevent content from stretching (by default)', () => { + expect(screen.getByTestId(`event-field-${hostIpData.field}`)).toHaveClass( + 'euiFlexGroup--alignItemsFlexStart' + ); + }); + test('it renders link buttons for each of the host ip addresses', () => { expect(screen.getAllByRole('button').length).toBe(hostIpValues.length); }); diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/table/field_value_cell.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/table/field_value_cell.tsx index dc6c84b8138fe..0685582b33882 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/table/field_value_cell.tsx +++ b/x-pack/plugins/security_solution/public/common/components/event_details/table/field_value_cell.tsx @@ -37,6 +37,7 @@ export const FieldValueCell = React.memo( }: FieldValueCellProps) => { return ( Date: Tue, 26 Oct 2021 12:15:41 -0400 Subject: [PATCH 46/58] Prevent legacy url conflicts (#116007) --- docs/api/saved-objects/bulk_create.asciidoc | 19 +- docs/api/saved-objects/bulk_get.asciidoc | 3 +- docs/api/saved-objects/bulk_resolve.asciidoc | 3 +- docs/api/saved-objects/create.asciidoc | 11 + docs/api/saved-objects/update.asciidoc | 13 + ...ct_multi_namespace_references.test.mock.ts | 9 + ...collect_multi_namespace_references.test.ts | 159 ++---- .../lib/collect_multi_namespace_references.ts | 123 +---- .../lib/find_legacy_url_aliases.test.ts | 140 +++++ .../service/lib/find_legacy_url_aliases.ts | 81 +++ .../service/lib/internal_utils.test.ts | 18 + .../service/lib/internal_utils.ts | 25 +- .../service/lib/point_in_time_finder.ts | 7 + .../preflight_check_for_create.test.mock.ts | 30 ++ .../lib/preflight_check_for_create.test.ts | 246 +++++++++ .../service/lib/preflight_check_for_create.ts | 285 ++++++++++ .../service/lib/repository.test.js | 498 ++++++++++++------ .../service/lib/repository.test.mock.ts | 9 + .../saved_objects/service/lib/repository.ts | 322 ++++++----- .../saved_objects/spaces/data.json | 37 ++ .../common/suites/bulk_create.ts | 16 +- .../common/suites/create.ts | 2 + .../common/suites/update.ts | 21 +- .../security_and_spaces/apis/bulk_create.ts | 13 + .../security_and_spaces/apis/create.ts | 13 + .../security_and_spaces/apis/update.ts | 4 +- .../spaces_only/apis/bulk_create.ts | 12 + .../spaces_only/apis/create.ts | 3 + .../spaces_only/apis/update.ts | 4 +- 29 files changed, 1588 insertions(+), 538 deletions(-) create mode 100644 src/core/server/saved_objects/service/lib/find_legacy_url_aliases.test.ts create mode 100644 src/core/server/saved_objects/service/lib/find_legacy_url_aliases.ts create mode 100644 src/core/server/saved_objects/service/lib/preflight_check_for_create.test.mock.ts create mode 100644 src/core/server/saved_objects/service/lib/preflight_check_for_create.test.ts create mode 100644 src/core/server/saved_objects/service/lib/preflight_check_for_create.ts diff --git a/docs/api/saved-objects/bulk_create.asciidoc b/docs/api/saved-objects/bulk_create.asciidoc index a935907ef3f11..471e297316578 100644 --- a/docs/api/saved-objects/bulk_create.asciidoc +++ b/docs/api/saved-objects/bulk_create.asciidoc @@ -66,7 +66,8 @@ Saved objects that are unable to persist are replaced with an error object. ==== Response code `200`:: - Indicates a successful call. + Indicates a successful call. Note, this HTTP response code indicates that the bulk operation succeeded. Errors pertaining to individual + objects will be returned in the response body. See the example below for details. [[saved-objects-api-bulk-create-example]] ==== Example @@ -122,3 +123,19 @@ The API returns the following: -------------------------------------------------- There is already a saved object with the `my-dashboard` ID, so only the index pattern is created. + +[[saved-objects-api-bulk-create-conflict-errors]] +==== Conflict errors + +Starting in {kib} 8.0, saved objects can exist in multiple spaces. As a result, you may encounter different types of conflict errors when +attempting to create an object: + +* *Regular conflict*: This is a 409 error without any metadata. It means an object of that type/ID already exists. This can be + overridden by using the `overwrite: true` option. +* *Unresolvable conflict*: This is a 409 error with `isNotOverwritable: true` in its metadata. It means an object of that type/ID already + exists in a different space, and it cannot be overridden with the given parameters. To successfully overwrite this object, you must do so + in at least one space where it exists. You can specify that using the `space_id` path parameter _or_ the `initialNamespaces` parameter. +* *Alias conflict*: This is a 409 error with a `spacesWithConflictingAliases` string array in its metadata. It means a conflicting + <> for this type/ID exists in the space(s) where you attempted to create this object. A conflicting + legacy URL alias is one that points to a different type/ID. To successfully create this object, you need to first use the + <> API to disable the problematic legacy URL alias(es). diff --git a/docs/api/saved-objects/bulk_get.asciidoc b/docs/api/saved-objects/bulk_get.asciidoc index 1bcdf7ba33cf4..65cd93fe212f8 100644 --- a/docs/api/saved-objects/bulk_get.asciidoc +++ b/docs/api/saved-objects/bulk_get.asciidoc @@ -53,7 +53,8 @@ Saved objects that are unable to persist are replaced with an error object. ==== Response code `200`:: - Indicates a successful call. + Indicates a successful call. Note, this HTTP response code indicates that the bulk operation succeeded. Errors pertaining to individual + objects will be returned in the response body. See the example below for details. [[saved-objects-api-bulk-get-body-example]] ==== Example diff --git a/docs/api/saved-objects/bulk_resolve.asciidoc b/docs/api/saved-objects/bulk_resolve.asciidoc index 98077ff11aa8c..e8b947638abeb 100644 --- a/docs/api/saved-objects/bulk_resolve.asciidoc +++ b/docs/api/saved-objects/bulk_resolve.asciidoc @@ -46,7 +46,8 @@ that "exactMatch" is the default outcome, and the outcome only changes if an ali ==== Response code `200`:: - Indicates a successful call. + Indicates a successful call. Note, this HTTP response code indicates that the bulk operation succeeded. Errors pertaining to individual + objects will be returned in the response body. See the example below for details. [[saved-objects-api-bulk-resolve-body-example]] ==== Example diff --git a/docs/api/saved-objects/create.asciidoc b/docs/api/saved-objects/create.asciidoc index 437bdb497da26..d250b0602adb7 100644 --- a/docs/api/saved-objects/create.asciidoc +++ b/docs/api/saved-objects/create.asciidoc @@ -64,6 +64,9 @@ used to specify a single space, and the "All spaces" identifier (`'*'`) is not a `200`:: Indicates a successful call. +`409`:: + Indicates a <>. + [[saved-objects-api-create-example]] ==== Example @@ -93,3 +96,11 @@ The API returns the following: -------------------------------------------------- <1> When `my-pattern` is unspecified in the path, a unique ID is automatically generated. + +[[saved-objects-api-create-conflict-errors]] +==== Conflict errors + +Starting in {kib} 8.0, saved objects can exist in multiple spaces. As a result, you may encounter different types of conflict errors when +attempting to create an object. If you encounter a 409 error that cannot be overridden by using the `overwrite: true` option, you are likely +hitting a different type of conflict error. The Create API response is limited and does not include additional metadata. You can get more +details about this error by using the <> instead. diff --git a/docs/api/saved-objects/update.asciidoc b/docs/api/saved-objects/update.asciidoc index 2bd95df1adf30..fccc6112948a1 100644 --- a/docs/api/saved-objects/update.asciidoc +++ b/docs/api/saved-objects/update.asciidoc @@ -45,6 +45,12 @@ WARNING: When you update, attributes are not validated, which allows you to pass `200`:: Indicates a successful call. +`404`:: + Indicates the object was not found. + +`409`:: + Indicates a <>. + [[saved-objects-api-update-example]] ==== Example @@ -74,3 +80,10 @@ The API returns the following: } } -------------------------------------------------- + +[[saved-objects-api-update-conflict-errors]] +==== Conflict errors + +Starting in {kib} 8.0, saved objects can exist in multiple spaces. As a result, you may encounter a 409 *alias conflict* error when using +the `upsert` option. The Update API response is limited and does not include additional metadata. You can get more details about this error +by using the <> instead. diff --git a/src/core/server/saved_objects/service/lib/collect_multi_namespace_references.test.mock.ts b/src/core/server/saved_objects/service/lib/collect_multi_namespace_references.test.mock.ts index cbd1ac4a8eb8f..382212cfbbd11 100644 --- a/src/core/server/saved_objects/service/lib/collect_multi_namespace_references.test.mock.ts +++ b/src/core/server/saved_objects/service/lib/collect_multi_namespace_references.test.mock.ts @@ -6,8 +6,17 @@ * Side Public License, v 1. */ +import type { findLegacyUrlAliases } from './find_legacy_url_aliases'; import type * as InternalUtils from './internal_utils'; +export const mockFindLegacyUrlAliases = jest.fn() as jest.MockedFunction< + typeof findLegacyUrlAliases +>; + +jest.mock('./find_legacy_url_aliases', () => { + return { findLegacyUrlAliases: mockFindLegacyUrlAliases }; +}); + export const mockRawDocExistsInNamespace = jest.fn() as jest.MockedFunction< typeof InternalUtils['rawDocExistsInNamespace'] >; diff --git a/src/core/server/saved_objects/service/lib/collect_multi_namespace_references.test.ts b/src/core/server/saved_objects/service/lib/collect_multi_namespace_references.test.ts index 45794e25d00a6..bb13a03adb53b 100644 --- a/src/core/server/saved_objects/service/lib/collect_multi_namespace_references.test.ts +++ b/src/core/server/saved_objects/service/lib/collect_multi_namespace_references.test.ts @@ -6,25 +6,25 @@ * Side Public License, v 1. */ -import { mockRawDocExistsInNamespace } from './collect_multi_namespace_references.test.mock'; +import { + mockFindLegacyUrlAliases, + mockRawDocExistsInNamespace, +} from './collect_multi_namespace_references.test.mock'; import type { DeeplyMockedKeys } from '@kbn/utility-types/jest'; -import type { ElasticsearchClient } from 'src/core/server/elasticsearch'; -import { elasticsearchClientMock } from 'src/core/server/elasticsearch/client/mocks'; -import { LegacyUrlAlias, LEGACY_URL_ALIAS_TYPE } from '../../object_types'; +import type { ElasticsearchClient } from '../../../elasticsearch'; +import { elasticsearchClientMock } from '../../../elasticsearch/client/mocks'; import { typeRegistryMock } from '../../saved_objects_type_registry.mock'; import { SavedObjectsSerializer } from '../../serialization'; -import type { +import { + ALIAS_SEARCH_PER_PAGE, CollectMultiNamespaceReferencesParams, SavedObjectsCollectMultiNamespaceReferencesObject, SavedObjectsCollectMultiNamespaceReferencesOptions, } from './collect_multi_namespace_references'; import { collectMultiNamespaceReferences } from './collect_multi_namespace_references'; -import { savedObjectsPointInTimeFinderMock } from './point_in_time_finder.mock'; -import { savedObjectsRepositoryMock } from './repository.mock'; -import { PointInTimeFinder } from './point_in_time_finder'; -import { ISavedObjectsRepository } from './repository'; +import type { CreatePointInTimeFinderFn } from './point_in_time_finder'; const SPACES = ['default', 'another-space']; const VERSION_PROPS = { _seq_no: 1, _primary_term: 1 }; @@ -35,17 +35,14 @@ const NON_MULTI_NAMESPACE_OBJ_TYPE = 'type-c'; const MULTI_NAMESPACE_HIDDEN_OBJ_TYPE = 'type-d'; beforeEach(() => { + mockFindLegacyUrlAliases.mockReset(); + mockFindLegacyUrlAliases.mockResolvedValue(new Map()); // return an empty map by default mockRawDocExistsInNamespace.mockReset(); mockRawDocExistsInNamespace.mockReturnValue(true); // return true by default }); describe('collectMultiNamespaceReferences', () => { let client: DeeplyMockedKeys; - let savedObjectsMock: jest.Mocked; - let createPointInTimeFinder: jest.MockedFunction< - CollectMultiNamespaceReferencesParams['createPointInTimeFinder'] - >; - let pointInTimeFinder: DeeplyMockedKeys; /** Sets up the type registry, saved objects client, etc. and return the full parameters object to be passed to `collectMultiNamespaceReferences` */ function setup( @@ -67,20 +64,6 @@ describe('collectMultiNamespaceReferences', () => { client = elasticsearchClientMock.createElasticsearchClient(); const serializer = new SavedObjectsSerializer(registry); - savedObjectsMock = savedObjectsRepositoryMock.create(); - savedObjectsMock.find.mockResolvedValue({ - pit_id: 'foo', - saved_objects: [], - // the rest of these fields don't matter but are included for type safety - total: 0, - page: 1, - per_page: 100, - }); - createPointInTimeFinder = jest.fn(); - createPointInTimeFinder.mockImplementation((params) => { - pointInTimeFinder = savedObjectsPointInTimeFinderMock.create({ savedObjectsMock })(params); - return pointInTimeFinder; - }); return { registry, allowedTypes: [ @@ -91,7 +74,7 @@ describe('collectMultiNamespaceReferences', () => { client, serializer, getIndexForType: (type: string) => `index-for-${type}`, - createPointInTimeFinder, + createPointInTimeFinder: jest.fn() as CreatePointInTimeFinderFn, objects, options, }; @@ -130,23 +113,6 @@ describe('collectMultiNamespaceReferences', () => { ); } - function mockFindResults(...results: LegacyUrlAlias[]) { - savedObjectsMock.find.mockResolvedValueOnce({ - pit_id: 'foo', - saved_objects: results.map((attributes) => ({ - id: 'doesnt-matter', - type: LEGACY_URL_ALIAS_TYPE, - attributes, - references: [], - score: 0, // doesn't matter - })), - // the rest of these fields don't matter but are included for type safety - total: 0, - page: 1, - per_page: 100, - }); - } - /** Asserts that mget is called for the given objects */ function expectMgetArgs( n: number, @@ -320,45 +286,30 @@ describe('collectMultiNamespaceReferences', () => { }); describe('legacy URL aliases', () => { - it('uses the PointInTimeFinder to search for legacy URL aliases', async () => { + it('uses findLegacyUrlAliases to search for legacy URL aliases', async () => { const obj1 = { type: MULTI_NAMESPACE_OBJ_TYPE_1, id: 'id-1' }; const obj2 = { type: MULTI_NAMESPACE_OBJ_TYPE_1, id: 'id-2' }; const obj3 = { type: MULTI_NAMESPACE_OBJ_TYPE_1, id: 'id-3' }; const params = setup([obj1, obj2], {}); mockMgetResults({ found: true, references: [obj3] }, { found: true, references: [] }); // results for obj1 and obj2 mockMgetResults({ found: true, references: [] }); // results for obj3 - mockFindResults( - // mock search results for four aliases for obj1, and none for obj2 or obj3 - ...[1, 2, 3, 4].map((i) => ({ - sourceId: obj1.id, - targetId: 'doesnt-matter', - targetType: obj1.type, - targetNamespace: `space-${i}`, - })) + mockFindLegacyUrlAliases.mockResolvedValue( + new Map([ + [`${obj1.type}:${obj1.id}`, new Set(['space-1', 'space-2', 'space-3', 'space-4'])], + // the result map does not contain keys for obj2 or obj3 because we did not find any aliases for those objects + ]) ); const result = await collectMultiNamespaceReferences(params); expect(client.mget).toHaveBeenCalledTimes(2); expectMgetArgs(1, obj1, obj2); expectMgetArgs(2, obj3); // obj3 is retrieved in a second cluster call - expect(createPointInTimeFinder).toHaveBeenCalledTimes(1); - const kueryFilterArgs = createPointInTimeFinder.mock.calls[0][0].filter.arguments; - expect(kueryFilterArgs).toHaveLength(2); - const typeAndIdFilters = kueryFilterArgs[1].arguments; - expect(typeAndIdFilters).toHaveLength(3); - [obj1, obj2, obj3].forEach(({ type, id }, i) => { - const typeAndIdFilter = typeAndIdFilters[i].arguments; - expect(typeAndIdFilter).toEqual([ - expect.objectContaining({ - arguments: expect.arrayContaining([{ type: 'literal', value: type }]), - }), - expect.objectContaining({ - arguments: expect.arrayContaining([{ type: 'literal', value: id }]), - }), - ]); - }); - expect(pointInTimeFinder.find).toHaveBeenCalledTimes(1); - expect(pointInTimeFinder.close).toHaveBeenCalledTimes(2); + expect(mockFindLegacyUrlAliases).toHaveBeenCalledTimes(1); + expect(mockFindLegacyUrlAliases).toHaveBeenCalledWith( + expect.anything(), + [obj1, obj2, obj3], + ALIAS_SEARCH_PER_PAGE + ); expect(result.objects).toEqual([ { ...obj1, @@ -371,74 +322,32 @@ describe('collectMultiNamespaceReferences', () => { ]); }); - it('does not create a PointInTimeFinder if no objects are passed in', async () => { - const params = setup([]); - - await collectMultiNamespaceReferences(params); - expect(params.createPointInTimeFinder).not.toHaveBeenCalled(); - }); - - it('does not search for objects that have an empty spaces array (the object does not exist, or we are not sure)', async () => { + it('omits objects that have an empty spaces array (the object does not exist, or we are not sure)', async () => { const obj1 = { type: MULTI_NAMESPACE_OBJ_TYPE_1, id: 'id-1' }; const obj2 = { type: MULTI_NAMESPACE_OBJ_TYPE_1, id: 'id-2' }; const params = setup([obj1, obj2]); mockMgetResults({ found: true }, { found: false }); // results for obj1 and obj2 await collectMultiNamespaceReferences(params); - expect(createPointInTimeFinder).toHaveBeenCalledTimes(1); - - const kueryFilterArgs = createPointInTimeFinder.mock.calls[0][0].filter.arguments; - expect(kueryFilterArgs).toHaveLength(2); - const typeAndIdFilters = kueryFilterArgs[1].arguments; - expect(typeAndIdFilters).toHaveLength(1); - const typeAndIdFilter = typeAndIdFilters[0].arguments; - expect(typeAndIdFilter).toEqual([ - expect.objectContaining({ - arguments: expect.arrayContaining([{ type: 'literal', value: obj1.type }]), - }), - expect.objectContaining({ - arguments: expect.arrayContaining([{ type: 'literal', value: obj1.id }]), - }), - ]); - expect(pointInTimeFinder.find).toHaveBeenCalledTimes(1); - expect(pointInTimeFinder.close).toHaveBeenCalledTimes(2); - }); - - it('does not search at all if all objects that have an empty spaces array (the object does not exist, or we are not sure)', async () => { - const obj1 = { type: MULTI_NAMESPACE_OBJ_TYPE_1, id: 'id-1' }; - const params = setup([obj1]); - mockMgetResults({ found: false }); // results for obj1 - - await collectMultiNamespaceReferences(params); - expect(params.createPointInTimeFinder).not.toHaveBeenCalled(); - }); - - it('handles PointInTimeFinder.find errors', async () => { - const obj1 = { type: MULTI_NAMESPACE_OBJ_TYPE_1, id: 'id-1' }; - const params = setup([obj1]); - mockMgetResults({ found: true }); // results for obj1 - savedObjectsMock.find.mockRejectedValue(new Error('Oh no!')); - - await expect(() => collectMultiNamespaceReferences(params)).rejects.toThrow( - 'Failed to retrieve legacy URL aliases: Oh no!' + expect(mockFindLegacyUrlAliases).toHaveBeenCalledTimes(1); + expect(mockFindLegacyUrlAliases).toHaveBeenCalledWith( + expect.anything(), + [obj1], + ALIAS_SEARCH_PER_PAGE ); - expect(createPointInTimeFinder).toHaveBeenCalledTimes(1); - expect(pointInTimeFinder.find).toHaveBeenCalledTimes(1); - expect(pointInTimeFinder.close).toHaveBeenCalledTimes(2); // we still close the point-in-time, even though the search failed }); - it('handles PointInTimeFinder.close errors', async () => { + it('handles findLegacyUrlAliases errors', async () => { const obj1 = { type: MULTI_NAMESPACE_OBJ_TYPE_1, id: 'id-1' }; const params = setup([obj1]); mockMgetResults({ found: true }); // results for obj1 - savedObjectsMock.closePointInTime.mockRejectedValue(new Error('Oh no!')); + mockFindLegacyUrlAliases.mockRejectedValue( + new Error('Failed to retrieve legacy URL aliases: Oh no!') + ); await expect(() => collectMultiNamespaceReferences(params)).rejects.toThrow( 'Failed to retrieve legacy URL aliases: Oh no!' ); - expect(createPointInTimeFinder).toHaveBeenCalledTimes(1); - expect(pointInTimeFinder.find).toHaveBeenCalledTimes(1); - expect(pointInTimeFinder.close).toHaveBeenCalledTimes(2); }); }); }); diff --git a/src/core/server/saved_objects/service/lib/collect_multi_namespace_references.ts b/src/core/server/saved_objects/service/lib/collect_multi_namespace_references.ts index 278964c934ba0..87bb5017aab95 100644 --- a/src/core/server/saved_objects/service/lib/collect_multi_namespace_references.ts +++ b/src/core/server/saved_objects/service/lib/collect_multi_namespace_references.ts @@ -6,17 +6,18 @@ * Side Public License, v 1. */ -import * as esKuery from '@kbn/es-query'; -import { LegacyUrlAlias, LEGACY_URL_ALIAS_TYPE } from '../../object_types'; import type { ISavedObjectTypeRegistry } from '../../saved_objects_type_registry'; import type { SavedObjectsSerializer } from '../../serialization'; import type { SavedObject, SavedObjectsBaseOptions } from '../../types'; +import { findLegacyUrlAliases } from './find_legacy_url_aliases'; import { getRootFields } from './included_fields'; -import { getSavedObjectFromSource, rawDocExistsInNamespace } from './internal_utils'; -import type { - ISavedObjectsPointInTimeFinder, - SavedObjectsCreatePointInTimeFinderOptions, -} from './point_in_time_finder'; +import { + getObjectKey, + getSavedObjectFromSource, + parseObjectKey, + rawDocExistsInNamespace, +} from './internal_utils'; +import type { CreatePointInTimeFinderFn } from './point_in_time_finder'; import type { RepositoryEsClient } from './repository_es_client'; /** @@ -28,8 +29,10 @@ const MAX_REFERENCE_GRAPH_DEPTH = 20; * How many aliases to search for per page. This is smaller than the PointInTimeFinder's default of 1000. We specify 100 for the page count * because this is a relatively unimportant operation, and we want to avoid blocking the Elasticsearch thread pool for longer than * necessary. + * + * @internal */ -const ALIAS_SEARCH_PER_PAGE = 100; +export const ALIAS_SEARCH_PER_PAGE = 100; /** * An object to collect references for. It must be a multi-namespace type (in other words, the object type must be registered with the @@ -106,9 +109,7 @@ export interface CollectMultiNamespaceReferencesParams { client: RepositoryEsClient; serializer: SavedObjectsSerializer; getIndexForType: (type: string) => string; - createPointInTimeFinder: ( - findOptions: SavedObjectsCreatePointInTimeFinderOptions - ) => ISavedObjectsPointInTimeFinder; + createPointInTimeFinder: CreatePointInTimeFinderFn; objects: SavedObjectsCollectMultiNamespaceReferencesObject[]; options?: SavedObjectsCollectMultiNamespaceReferencesOptions; } @@ -116,6 +117,8 @@ export interface CollectMultiNamespaceReferencesParams { /** * Gets all references and transitive references of the given objects. Ignores any object and/or reference that is not a multi-namespace * type. + * + * @internal */ export async function collectMultiNamespaceReferences( params: CollectMultiNamespaceReferencesParams @@ -130,18 +133,25 @@ export async function collectMultiNamespaceReferences( inboundReferencesMap.entries() ).map(([referenceKey, referenceVal]) => { const inboundReferences = Array.from(referenceVal.entries()).map(([objectKey, name]) => { - const { type, id } = parseKey(objectKey); + const { type, id } = parseObjectKey(objectKey); return { type, id, name }; }); - const { type, id } = parseKey(referenceKey); + const { type, id } = parseObjectKey(referenceKey); const object = objectMap.get(referenceKey); const spaces = object?.namespaces ?? []; return { type, id, spaces, inboundReferences, ...(object === null && { isMissing: true }) }; }); - const aliasesMap = await checkLegacyUrlAliases(createPointInTimeFinder, objectsWithContext); + const objectsToFindAliasesFor = objectsWithContext + .filter(({ spaces }) => spaces.length !== 0) + .map(({ type, id }) => ({ type, id })); + const aliasesMap = await findLegacyUrlAliases( + createPointInTimeFinder, + objectsToFindAliasesFor, + ALIAS_SEARCH_PER_PAGE + ); const results = objectsWithContext.map((obj) => { - const key = getKey(obj); + const key = getObjectKey(obj); const val = aliasesMap.get(key); const spacesWithMatchingAliases = val && Array.from(val); return { ...obj, spacesWithMatchingAliases }; @@ -167,7 +177,7 @@ async function getObjectsAndReferences({ const { namespace, purpose } = options; const inboundReferencesMap = objects.reduce( // Add the input objects to the references map so they are returned with the results, even if they have no inbound references - (acc, cur) => acc.set(getKey(cur), new Map()), + (acc, cur) => acc.set(getObjectKey(cur), new Map()), new Map>() ); const objectMap = new Map(); @@ -201,7 +211,7 @@ async function getObjectsAndReferences({ for (let i = 0; i < bulkGetObjects.length; i++) { // For every element in bulkGetObjects, there should be a matching element in bulkGetResponse.body.docs const { type, id } = bulkGetObjects[i]; - const objectKey = getKey({ type, id }); + const objectKey = getObjectKey({ type, id }); const doc = bulkGetResponse.body.docs[i]; // @ts-expect-error MultiGetHit._source is optional if (!doc.found || !rawDocExistsInNamespace(registry, doc, namespace)) { @@ -215,7 +225,7 @@ async function getObjectsAndReferences({ if (!validObjectTypesFilter(reference)) { continue; } - const referenceKey = getKey(reference); + const referenceKey = getObjectKey(reference); const referenceVal = inboundReferencesMap.get(referenceKey) ?? new Map(); if (!referenceVal.has(objectKey)) { inboundReferencesMap.set(referenceKey, referenceVal.set(objectKey, reference.name)); @@ -225,84 +235,9 @@ async function getObjectsAndReferences({ } } } - bulkGetObjects = Array.from(newObjectsToGet).map((key) => parseKey(key)); + bulkGetObjects = Array.from(newObjectsToGet).map((key) => parseObjectKey(key)); count++; } return { objectMap, inboundReferencesMap }; } - -/** - * Fetches all legacy URL aliases that match the given objects, returning a map of the matching aliases and what space(s) they exist in. - */ -async function checkLegacyUrlAliases( - createPointInTimeFinder: ( - findOptions: SavedObjectsCreatePointInTimeFinderOptions - ) => ISavedObjectsPointInTimeFinder, - objects: SavedObjectReferenceWithContext[] -) { - const filteredObjects = objects.filter(({ spaces }) => spaces.length !== 0); - if (!filteredObjects.length) { - return new Map>(); - } - const filter = createAliasKueryFilter(filteredObjects); - const finder = createPointInTimeFinder({ - type: LEGACY_URL_ALIAS_TYPE, - perPage: ALIAS_SEARCH_PER_PAGE, - filter, - }); - const aliasesMap = new Map>(); - let error: Error | undefined; - try { - for await (const { saved_objects: savedObjects } of finder.find()) { - for (const alias of savedObjects) { - const { sourceId, targetType, targetNamespace } = alias.attributes; - const key = getKey({ type: targetType, id: sourceId }); - const val = aliasesMap.get(key) ?? new Set(); - val.add(targetNamespace); - aliasesMap.set(key, val); - } - } - } catch (e) { - error = e; - } - - try { - await finder.close(); - } catch (e) { - if (!error) { - error = e; - } - } - - if (error) { - throw new Error(`Failed to retrieve legacy URL aliases: ${error.message}`); - } - return aliasesMap; -} - -function createAliasKueryFilter(objects: SavedObjectReferenceWithContext[]) { - const { buildNode } = esKuery.nodeTypes.function; - const kueryNodes = objects.reduce((acc, { type, id }) => { - const match1 = buildNode('is', `${LEGACY_URL_ALIAS_TYPE}.attributes.targetType`, type); - const match2 = buildNode('is', `${LEGACY_URL_ALIAS_TYPE}.attributes.sourceId`, id); - acc.push(buildNode('and', [match1, match2])); - return acc; - }, []); - return buildNode('and', [ - buildNode('not', buildNode('is', `${LEGACY_URL_ALIAS_TYPE}.attributes.disabled`, true)), // ignore aliases that have been disabled - buildNode('or', kueryNodes), - ]); -} - -/** Takes an object with a `type` and `id` field and returns a key string */ -function getKey({ type, id }: { type: string; id: string }) { - return `${type}:${id}`; -} - -/** Parses a 'type:id' key string and returns an object with a `type` field and an `id` field */ -function parseKey(key: string) { - const type = key.slice(0, key.indexOf(':')); - const id = key.slice(type.length + 1); - return { type, id }; -} diff --git a/src/core/server/saved_objects/service/lib/find_legacy_url_aliases.test.ts b/src/core/server/saved_objects/service/lib/find_legacy_url_aliases.test.ts new file mode 100644 index 0000000000000..134ea26d53b7d --- /dev/null +++ b/src/core/server/saved_objects/service/lib/find_legacy_url_aliases.test.ts @@ -0,0 +1,140 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { DeeplyMockedKeys } from '@kbn/utility-types/jest'; + +import { LegacyUrlAlias, LEGACY_URL_ALIAS_TYPE } from '../../object_types'; +import { findLegacyUrlAliases } from './find_legacy_url_aliases'; +import type { CreatePointInTimeFinderFn, PointInTimeFinder } from './point_in_time_finder'; +import { savedObjectsPointInTimeFinderMock } from './point_in_time_finder.mock'; +import type { ISavedObjectsRepository } from './repository'; +import { savedObjectsRepositoryMock } from './repository.mock'; + +describe('findLegacyUrlAliases', () => { + let savedObjectsMock: jest.Mocked; + let pointInTimeFinder: DeeplyMockedKeys; + let createPointInTimeFinder: jest.MockedFunction; + + beforeEach(() => { + savedObjectsMock = savedObjectsRepositoryMock.create(); + savedObjectsMock.find.mockResolvedValue({ + pit_id: 'foo', + saved_objects: [], + // the rest of these fields don't matter but are included for type safety + total: 0, + page: 1, + per_page: 100, + }); + pointInTimeFinder = savedObjectsPointInTimeFinderMock.create({ savedObjectsMock })(); // PIT finder mock uses the actual implementation, but it doesn't need to be created with real params because the SOR is mocked too + createPointInTimeFinder = jest.fn().mockReturnValue(pointInTimeFinder); + }); + + function mockFindResults(...results: LegacyUrlAlias[]) { + savedObjectsMock.find.mockResolvedValueOnce({ + pit_id: 'foo', + saved_objects: results.map((attributes) => ({ + id: 'doesnt-matter', + type: LEGACY_URL_ALIAS_TYPE, + attributes, + references: [], + score: 0, // doesn't matter + })), + // the rest of these fields don't matter but are included for type safety + total: 0, + page: 1, + per_page: 100, + }); + } + + const obj1 = { type: 'obj-type', id: 'id-1' }; + const obj2 = { type: 'obj-type', id: 'id-2' }; + const obj3 = { type: 'obj-type', id: 'id-3' }; + + it('uses the PointInTimeFinder to search for legacy URL aliases', async () => { + mockFindResults( + // mock search results for four aliases for obj1, and none for obj2 or obj3 + ...[1, 2, 3, 4].map((i) => ({ + sourceId: obj1.id, + targetId: 'doesnt-matter', + targetType: obj1.type, + targetNamespace: `space-${i}`, + })) + ); + + const objects = [obj1, obj2, obj3]; + const result = await findLegacyUrlAliases(createPointInTimeFinder, objects); + expect(createPointInTimeFinder).toHaveBeenCalledTimes(1); + expect(createPointInTimeFinder).toHaveBeenCalledWith({ + type: LEGACY_URL_ALIAS_TYPE, + filter: expect.any(Object), // assertions are below + }); + const kueryFilterArgs = createPointInTimeFinder.mock.calls[0][0].filter.arguments; + expect(kueryFilterArgs).toHaveLength(2); + const typeAndIdFilters = kueryFilterArgs[1].arguments; + expect(typeAndIdFilters).toHaveLength(3); + [obj1, obj2, obj3].forEach(({ type, id }, i) => { + const typeAndIdFilter = typeAndIdFilters[i].arguments; + expect(typeAndIdFilter).toEqual([ + expect.objectContaining({ + arguments: expect.arrayContaining([{ type: 'literal', value: type }]), + }), + expect.objectContaining({ + arguments: expect.arrayContaining([{ type: 'literal', value: id }]), + }), + ]); + }); + expect(pointInTimeFinder.find).toHaveBeenCalledTimes(1); + expect(pointInTimeFinder.close).toHaveBeenCalledTimes(2); + expect(result).toEqual( + new Map([ + [`${obj1.type}:${obj1.id}`, new Set(['space-1', 'space-2', 'space-3', 'space-4'])], + // the result map does not contain keys for obj2 or obj3 because we did not find any aliases for those objects + ]) + ); + }); + + it('allows perPage to be set', async () => { + const objects = [obj1, obj2, obj3]; + await findLegacyUrlAliases(createPointInTimeFinder, objects, 999); + expect(createPointInTimeFinder).toHaveBeenCalledTimes(1); + expect(createPointInTimeFinder).toHaveBeenCalledWith({ + type: LEGACY_URL_ALIAS_TYPE, + perPage: 999, + filter: expect.any(Object), + }); + }); + + it('does not create a PointInTimeFinder if no objects are passed in', async () => { + await findLegacyUrlAliases(createPointInTimeFinder, []); + expect(createPointInTimeFinder).not.toHaveBeenCalled(); + }); + + it('handles PointInTimeFinder.find errors', async () => { + savedObjectsMock.find.mockRejectedValue(new Error('Oh no!')); + + const objects = [obj1, obj2, obj3]; + await expect(() => findLegacyUrlAliases(createPointInTimeFinder, objects)).rejects.toThrow( + 'Failed to retrieve legacy URL aliases: Oh no!' + ); + expect(createPointInTimeFinder).toHaveBeenCalledTimes(1); + expect(pointInTimeFinder.find).toHaveBeenCalledTimes(1); + expect(pointInTimeFinder.close).toHaveBeenCalledTimes(2); // we still close the point-in-time, even though the search failed + }); + + it('handles PointInTimeFinder.close errors', async () => { + pointInTimeFinder.close.mockRejectedValue(new Error('Oh no!')); + + const objects = [obj1, obj2, obj3]; + await expect(() => findLegacyUrlAliases(createPointInTimeFinder, objects)).rejects.toThrow( + 'Failed to retrieve legacy URL aliases: Oh no!' + ); + expect(createPointInTimeFinder).toHaveBeenCalledTimes(1); + expect(pointInTimeFinder.find).toHaveBeenCalledTimes(1); + expect(pointInTimeFinder.close).toHaveBeenCalledTimes(2); + }); +}); diff --git a/src/core/server/saved_objects/service/lib/find_legacy_url_aliases.ts b/src/core/server/saved_objects/service/lib/find_legacy_url_aliases.ts new file mode 100644 index 0000000000000..aac022fc32098 --- /dev/null +++ b/src/core/server/saved_objects/service/lib/find_legacy_url_aliases.ts @@ -0,0 +1,81 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import * as esKuery from '@kbn/es-query'; +import { LegacyUrlAlias, LEGACY_URL_ALIAS_TYPE } from '../../object_types'; +import { getObjectKey } from './internal_utils'; +import type { CreatePointInTimeFinderFn } from './point_in_time_finder'; + +interface FindLegacyUrlAliasesObject { + type: string; + id: string; +} + +/** + * Fetches all legacy URL aliases that match the given objects, returning a map of the matching aliases and what space(s) they exist in. + * + * @internal + */ +export async function findLegacyUrlAliases( + createPointInTimeFinder: CreatePointInTimeFinderFn, + objects: FindLegacyUrlAliasesObject[], + perPage?: number +) { + if (!objects.length) { + return new Map>(); + } + + const filter = createAliasKueryFilter(objects); + const finder = createPointInTimeFinder({ + type: LEGACY_URL_ALIAS_TYPE, + perPage, + filter, + }); + const aliasesMap = new Map>(); + let error: Error | undefined; + try { + for await (const { saved_objects: savedObjects } of finder.find()) { + for (const alias of savedObjects) { + const { sourceId, targetType, targetNamespace } = alias.attributes; + const key = getObjectKey({ type: targetType, id: sourceId }); + const val = aliasesMap.get(key) ?? new Set(); + val.add(targetNamespace); + aliasesMap.set(key, val); + } + } + } catch (e) { + error = e; + } + + try { + await finder.close(); + } catch (e) { + if (!error) { + error = e; + } + } + + if (error) { + throw new Error(`Failed to retrieve legacy URL aliases: ${error.message}`); + } + return aliasesMap; +} + +function createAliasKueryFilter(objects: Array<{ type: string; id: string }>) { + const { buildNode } = esKuery.nodeTypes.function; + const kueryNodes = objects.reduce((acc, { type, id }) => { + const match1 = buildNode('is', `${LEGACY_URL_ALIAS_TYPE}.attributes.targetType`, type); + const match2 = buildNode('is', `${LEGACY_URL_ALIAS_TYPE}.attributes.sourceId`, id); + acc.push(buildNode('and', [match1, match2])); + return acc; + }, []); + return buildNode('and', [ + buildNode('not', buildNode('is', `${LEGACY_URL_ALIAS_TYPE}.attributes.disabled`, true)), // ignore aliases that have been disabled + buildNode('or', kueryNodes), + ]); +} diff --git a/src/core/server/saved_objects/service/lib/internal_utils.test.ts b/src/core/server/saved_objects/service/lib/internal_utils.test.ts index 1a94e22d61f86..710303ab33359 100644 --- a/src/core/server/saved_objects/service/lib/internal_utils.test.ts +++ b/src/core/server/saved_objects/service/lib/internal_utils.test.ts @@ -12,8 +12,10 @@ import { encodeHitVersion } from '../../version'; import { getBulkOperationError, getCurrentTime, + getObjectKey, getSavedObjectFromSource, normalizeNamespace, + parseObjectKey, rawDocExistsInNamespace, rawDocExistsInNamespaces, } from './internal_utils'; @@ -359,3 +361,19 @@ describe('#getCurrentTime', () => { expect(getCurrentTime()).toEqual('2021-09-10T21:00:00.000Z'); }); }); + +describe('#getObjectKey', () => { + it('returns the expected key string', () => { + expect(getObjectKey({ type: 'foo', id: 'bar' })).toEqual('foo:bar'); + }); +}); + +describe('#parseObjectKey', () => { + it('returns the expected object', () => { + expect(parseObjectKey('foo:bar')).toEqual({ type: 'foo', id: 'bar' }); + }); + + it('throws error when input is malformed', () => { + expect(() => parseObjectKey('foobar')).toThrowError('Malformed object key'); + }); +}); diff --git a/src/core/server/saved_objects/service/lib/internal_utils.ts b/src/core/server/saved_objects/service/lib/internal_utils.ts index b480000f1b3da..abedcf53c781f 100644 --- a/src/core/server/saved_objects/service/lib/internal_utils.ts +++ b/src/core/server/saved_objects/service/lib/internal_utils.ts @@ -15,7 +15,7 @@ import { SavedObjectsErrorHelpers } from './errors'; import { ALL_NAMESPACES_STRING, SavedObjectsUtils } from './utils'; /** - * Discriminated union (TypeScript approximation of an algebraic data type); this design pattern used for internal repository operations. + * Discriminated union (TypeScript approximation of an algebraic data type); this design pattern is used for internal repository operations. * @internal */ export type Either = Left | Right; @@ -242,3 +242,26 @@ export function normalizeNamespace(namespace?: string) { export function getCurrentTime() { return new Date(Date.now()).toISOString(); } + +/** + * Takes an object with a `type` and `id` field and returns a key string. + * + * @internal + */ +export function getObjectKey({ type, id }: { type: string; id: string }) { + return `${type}:${id}`; +} + +/** + * Parses a 'type:id' key string and returns an object with a `type` field and an `id` field. + * + * @internal + */ +export function parseObjectKey(key: string) { + const type = key.slice(0, key.indexOf(':')); + const id = key.slice(type.length + 1); + if (!type || !id) { + throw new Error('Malformed object key (should be "type:id")'); + } + return { type, id }; +} diff --git a/src/core/server/saved_objects/service/lib/point_in_time_finder.ts b/src/core/server/saved_objects/service/lib/point_in_time_finder.ts index e7f3e9c378e90..5c630d1416cc3 100644 --- a/src/core/server/saved_objects/service/lib/point_in_time_finder.ts +++ b/src/core/server/saved_objects/service/lib/point_in_time_finder.ts @@ -38,6 +38,13 @@ export interface PointInTimeFinderDependencies logger: Logger; } +/** + * @internal + */ +export type CreatePointInTimeFinderFn = ( + findOptions: SavedObjectsCreatePointInTimeFinderOptions +) => ISavedObjectsPointInTimeFinder; + /** @public */ export interface ISavedObjectsPointInTimeFinder { /** diff --git a/src/core/server/saved_objects/service/lib/preflight_check_for_create.test.mock.ts b/src/core/server/saved_objects/service/lib/preflight_check_for_create.test.mock.ts new file mode 100644 index 0000000000000..e774a178abd49 --- /dev/null +++ b/src/core/server/saved_objects/service/lib/preflight_check_for_create.test.mock.ts @@ -0,0 +1,30 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import type { findLegacyUrlAliases } from './find_legacy_url_aliases'; +import type * as InternalUtils from './internal_utils'; + +export const mockFindLegacyUrlAliases = jest.fn() as jest.MockedFunction< + typeof findLegacyUrlAliases +>; + +jest.mock('./find_legacy_url_aliases', () => { + return { findLegacyUrlAliases: mockFindLegacyUrlAliases }; +}); + +export const mockRawDocExistsInNamespaces = jest.fn() as jest.MockedFunction< + typeof InternalUtils['rawDocExistsInNamespaces'] +>; + +jest.mock('./internal_utils', () => { + const actual = jest.requireActual('./internal_utils'); + return { + ...actual, + rawDocExistsInNamespaces: mockRawDocExistsInNamespaces, + }; +}); diff --git a/src/core/server/saved_objects/service/lib/preflight_check_for_create.test.ts b/src/core/server/saved_objects/service/lib/preflight_check_for_create.test.ts new file mode 100644 index 0000000000000..8d7cfd25ac885 --- /dev/null +++ b/src/core/server/saved_objects/service/lib/preflight_check_for_create.test.ts @@ -0,0 +1,246 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { + mockFindLegacyUrlAliases, + mockRawDocExistsInNamespaces, +} from './preflight_check_for_create.test.mock'; + +import type { DeeplyMockedKeys } from '@kbn/utility-types/jest'; + +import type { ElasticsearchClient } from '../../../elasticsearch'; +import { elasticsearchClientMock } from '../../../elasticsearch/client/mocks'; +import { LEGACY_URL_ALIAS_TYPE } from '../../object_types'; +import { typeRegistryMock } from '../../saved_objects_type_registry.mock'; +import { SavedObjectsSerializer } from '../../serialization'; +import type { CreatePointInTimeFinderFn } from './point_in_time_finder'; +import { + ALIAS_SEARCH_PER_PAGE, + PreflightCheckForCreateObject, + PreflightCheckForCreateParams, +} from './preflight_check_for_create'; +import { preflightCheckForCreate } from './preflight_check_for_create'; + +beforeEach(() => { + mockFindLegacyUrlAliases.mockReset(); + mockFindLegacyUrlAliases.mockResolvedValue(new Map()); // return an empty map by default + mockRawDocExistsInNamespaces.mockReset(); + mockRawDocExistsInNamespaces.mockReturnValue(true); // return true by default +}); + +describe('preflightCheckForCreate', () => { + let client: DeeplyMockedKeys; + + function setup(...objects: PreflightCheckForCreateObject[]): PreflightCheckForCreateParams { + const registry = typeRegistryMock.create(); + client = elasticsearchClientMock.createElasticsearchClient(); + const serializer = new SavedObjectsSerializer(registry); + return { + registry, + client, + serializer, + getIndexForType: (type: string) => `index-for-${type}`, + createPointInTimeFinder: jest.fn() as CreatePointInTimeFinderFn, + objects, + }; + } + + /** Mocks the saved objects client so it returns the expected results */ + function mockMgetResults( + ...results: Array<{ + found: boolean; + disabled?: boolean; // only used for alias results + }> + ) { + // instead of just mocking the response, we need to mock the implementation so we can correctly set the _id in the response docs + client.mget.mockImplementation((params, _options) => { + return elasticsearchClientMock.createSuccessTransportRequestPromise({ + docs: results.map(({ found, disabled }, i) => { + return found + ? { + // @ts-expect-error + _id: params!.body!.docs![i]._id as string, // needed for mockRawDocExistsInNamespaces mock implementation and existingDocument assertions + _index: 'doesnt-matter', + _source: { + ...(disabled !== undefined && { [LEGACY_URL_ALIAS_TYPE]: { disabled } }), + }, + found: true, + } + : { + _id: 'doesnt-matter', + _index: 'doesnt-matter', + found: false, + }; + }), + }); + }); + } + + /** Asserts that mget is called for the given raw object IDs */ + function expectMgetArgs(...rawObjectIds: string[]) { + const docs = rawObjectIds.map((_id) => expect.objectContaining({ _id })); + expect(client.mget).toHaveBeenCalledWith({ body: { docs } }, expect.anything()); + } + + /** Asserts that findLegacyUrlAliases is called for the given objects */ + function expectFindArgs(...objects: Array<{ type: string; id: string }>) { + expect(mockFindLegacyUrlAliases).toHaveBeenCalledWith( + expect.anything(), + objects.map(({ type, id }) => ({ type, id })), + ALIAS_SEARCH_PER_PAGE + ); + } + + it(`doesn't call mget if no object args are passed in`, async () => { + const params = setup(); + + await preflightCheckForCreate(params); + expectFindArgs(); // it *does* call findLegacyUrlAliases, but it's intentional beause that module handles an empty object array gracefully + expect(client.mget).not.toHaveBeenCalled(); + }); + + it(`uses find instead of mget when exceeding the alias threshold`, async () => { + const fourSpaces = ['a', 'b', 'c', 'd']; + const obj1 = { type: 'obj-type', id: 'id-1', overwrite: false, namespaces: ['a'] }; // mget aliases + const obj2 = { type: 'obj-type', id: 'id-2', overwrite: false, namespaces: ['*'] }; // find aliases because it exists in all spaces + const obj3 = { type: 'obj-type', id: 'id-3', overwrite: false, namespaces: ['a', 'b', 'c'] }; // mget aliases + const obj4 = { type: 'obj-type', id: 'id-4', overwrite: false, namespaces: fourSpaces }; // find aliases because it exists in 4 spaces (the threshold is 3) + const params = setup(obj1, obj2, obj3, obj4); + mockMgetResults(...new Array(8).fill({ found: false })); + await preflightCheckForCreate(params); + + expectFindArgs(obj2, obj4); + expectMgetArgs( + `${obj1.type}:${obj1.id}`, + `${LEGACY_URL_ALIAS_TYPE}:a:${obj1.type}:${obj1.id}`, + `${obj2.type}:${obj2.id}`, + // we already searched for aliases for obj2 above, so we don't do it again during mget + `${obj3.type}:${obj3.id}`, + `${LEGACY_URL_ALIAS_TYPE}:a:${obj3.type}:${obj3.id}`, + `${LEGACY_URL_ALIAS_TYPE}:b:${obj3.type}:${obj3.id}`, + `${LEGACY_URL_ALIAS_TYPE}:c:${obj3.type}:${obj3.id}`, + `${obj4.type}:${obj4.id}` + // we already searched for aliases for obj4 above, so we don't do it again during mget + ); + }); + + it(`returns mix of success and error results`, async () => { + const fourSpaces = ['a', 'b', 'c', 'd']; + const obj1 = { type: 'obj-type', id: 'id-1', overwrite: false, namespaces: ['*'] }; // success: find aliases, object not found + const obj2 = { type: 'obj-type', id: 'id-2', overwrite: true, namespaces: fourSpaces }; // success: find aliases, object found + const obj3 = { type: 'obj-type', id: 'id-3', overwrite: false, namespaces: ['a'] }; // success: mget aliases, object not found + const obj4 = { type: 'obj-type', id: 'id-4', overwrite: true, namespaces: ['a'] }; // success: mget aliases, object found + const obj5 = { type: 'obj-type', id: 'id-5', overwrite: true, namespaces: ['*'] }; // error: find aliases, alias conflict (1) + const obj6 = { type: 'obj-type', id: 'id-6', overwrite: true, namespaces: fourSpaces }; // error: find aliases, alias conflict (2) + const obj7 = { type: 'obj-type', id: 'id-7', overwrite: true, namespaces: ['a'] }; // error: mget aliases, alias conflict + const obj8 = { type: 'obj-type', id: 'id-8', overwrite: true, namespaces: fourSpaces }; // error: find aliases, unresolvable conflict + const obj9 = { type: 'obj-type', id: 'id-9', overwrite: true, namespaces: ['a'] }; // error: mget aliases, unresolvable conflict + const obj10 = { type: 'obj-type', id: 'id-10', overwrite: false, namespaces: fourSpaces }; // error: find aliases, regular conflict + const obj11 = { type: 'obj-type', id: 'id-11', overwrite: false, namespaces: ['a'] }; // error: mget aliases, regular conflict + + const params = setup(obj1, obj2, obj3, obj4, obj5, obj6, obj7, obj8, obj9, obj10, obj11); + mockFindLegacyUrlAliases.mockResolvedValue( + new Map([ + // did not find aliases for obj1 + [`${obj2.type}:${obj2.id}`, new Set(['e'])], // found an alias for obj2, but it is not in the requested spaces, no problem + [`${obj5.type}:${obj5.id}`, new Set(['e'])], // found an alias for obj5, and obj5 should be created in all spaces -> this causes an alias conflict + [`${obj6.type}:${obj6.id}`, new Set(['b'])], // found an alias for obj6, and obj6 should be created in the same space -> this causes an alias conflict + // did not find aliases for obj8 or obj10 + ]) + ); + mockMgetResults( + { found: false }, // did not find obj1 + { found: true }, // found obj2, but it has overwrite enabled, no problem + { found: false }, // did not find obj3 + { found: false }, // did not find obj3 alias in "a" + { found: true }, // found obj4 + { found: true, disabled: true }, // found obj4 alias in "a", but it is disabled, no problem + // we do not mget obj5 or obj6 because they had alias conflicts from the earlier find operation + { found: true }, // found obj7, but it has overwrite enabled, no problem + { found: true, disabled: false }, // found obj7 alias in "a" -> this causes an alias conflict + { found: true }, // found obj8 + // we do not mget aliases for obj8 because we used find for those + { found: true }, // found obj9 + { found: false }, // did not find obj9 alias in "a" + { found: true }, // found obj10 -> this causes a regular conflict + // we do not mget aliases for obj10 because we used find for those + { found: true }, // found obj11 -> this causes a regular conflict + { found: false } // did not find obj11 alias in "a" + ); + mockRawDocExistsInNamespaces.mockImplementation((_registry, { _id }, _namespaces) => { + return _id !== `${obj8.type}:${obj8.id}` && _id !== `${obj9.type}:${obj9.id}`; // only obj8 and obj9 exist outside of the given spaces + }); + const result = await preflightCheckForCreate(params); + + expectFindArgs(obj1, obj2, obj5, obj6, obj8, obj10); + expectMgetArgs( + `${obj1.type}:${obj1.id}`, + // we already searched for aliases for obj1 above, so we don't do it again during mget + `${obj2.type}:${obj2.id}`, + // we already searched for aliases for obj2 above, so we don't do it again during mget + `${obj3.type}:${obj3.id}`, + `${LEGACY_URL_ALIAS_TYPE}:a:${obj3.type}:${obj3.id}`, + `${obj4.type}:${obj4.id}`, + `${LEGACY_URL_ALIAS_TYPE}:a:${obj4.type}:${obj4.id}`, + // we do not mget obj5 or obj6 because they had alias conflicts from the earlier find operation + `${obj7.type}:${obj7.id}`, + `${LEGACY_URL_ALIAS_TYPE}:a:${obj7.type}:${obj7.id}`, + `${obj8.type}:${obj8.id}`, + // we already searched for aliases for obj8 above, so we don't do it again during mget + `${obj9.type}:${obj9.id}`, + `${LEGACY_URL_ALIAS_TYPE}:a:${obj9.type}:${obj9.id}`, + `${obj10.type}:${obj10.id}`, + // we already searched for aliases for obj10 above, so we don't do it again during mget + `${obj11.type}:${obj11.id}`, + `${LEGACY_URL_ALIAS_TYPE}:a:${obj9.type}:${obj11.id}` + ); + expect(result).toEqual([ + // Success results: obj2 and obj4 include the existingDocument field because those objects were found + { type: obj1.type, id: obj1.id }, + { + type: obj2.type, + id: obj2.id, + existingDocument: expect.objectContaining({ _id: `${obj2.type}:${obj2.id}` }), + }, + { type: obj3.type, id: obj3.id }, + { + type: obj4.type, + id: obj4.id, + existingDocument: expect.objectContaining({ _id: `${obj4.type}:${obj4.id}` }), + }, + // Error results + { + type: obj5.type, + id: obj5.id, + error: { type: 'aliasConflict', metadata: { spacesWithConflictingAliases: ['e'] } }, + }, + { + type: obj6.type, + id: obj6.id, + error: { type: 'aliasConflict', metadata: { spacesWithConflictingAliases: ['b'] } }, + }, + { + type: obj7.type, + id: obj7.id, + error: { type: 'aliasConflict', metadata: { spacesWithConflictingAliases: ['a'] } }, + }, + { + type: obj8.type, + id: obj8.id, + error: { type: 'unresolvableConflict', metadata: { isNotOverwritable: true } }, + }, + { + type: obj9.type, + id: obj9.id, + error: { type: 'unresolvableConflict', metadata: { isNotOverwritable: true } }, + }, + { type: obj10.type, id: obj10.id, error: { type: 'conflict' } }, + { type: obj11.type, id: obj11.id, error: { type: 'conflict' } }, + ]); + }); +}); diff --git a/src/core/server/saved_objects/service/lib/preflight_check_for_create.ts b/src/core/server/saved_objects/service/lib/preflight_check_for_create.ts new file mode 100644 index 0000000000000..6788cd8aa3abf --- /dev/null +++ b/src/core/server/saved_objects/service/lib/preflight_check_for_create.ts @@ -0,0 +1,285 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { LegacyUrlAlias, LEGACY_URL_ALIAS_TYPE } from '../../object_types'; +import type { ISavedObjectTypeRegistry } from '../../saved_objects_type_registry'; +import type { + SavedObjectsRawDoc, + SavedObjectsRawDocSource, + SavedObjectsSerializer, +} from '../../serialization'; +import { findLegacyUrlAliases } from './find_legacy_url_aliases'; +import { Either, rawDocExistsInNamespaces } from './internal_utils'; +import { getObjectKey, isLeft, isRight } from './internal_utils'; +import type { CreatePointInTimeFinderFn } from './point_in_time_finder'; +import type { RepositoryEsClient } from './repository_es_client'; +import { ALL_NAMESPACES_STRING } from './utils'; + +/** + * If the object will be created in this many spaces (or "*" all current and future spaces), we use find to fetch all aliases. + * If the object does not exceed this threshold, we use mget to fetch aliases instead. + * This threshold is a bit arbitrary, but it is intended to optimize so we don't make expensive PIT/find operations unless it is necessary. + */ +const FIND_ALIASES_THRESHOLD = 3; + +/** + * How many aliases to search for per page. This is 1000 because consumers are relatively important operations and we could potentially be + * paging through many thousands of results. + * + * @internal + */ +export const ALIAS_SEARCH_PER_PAGE = 1000; + +export interface PreflightCheckForCreateObject { + /** The type of the object. */ + type: string; + /** The ID of the object. */ + id: string; + /** The namespaces that the consumer intends to create this object in. */ + namespaces: string[]; + /** Whether or not the object should be overwritten if it would encounter a regular conflict. */ + overwrite?: boolean; +} + +export interface PreflightCheckForCreateParams { + registry: ISavedObjectTypeRegistry; + client: RepositoryEsClient; + serializer: SavedObjectsSerializer; + getIndexForType: (type: string) => string; + createPointInTimeFinder: CreatePointInTimeFinderFn; + objects: PreflightCheckForCreateObject[]; +} + +export interface PreflightCheckForCreateResult { + /** The type of the object. */ + type: string; + /** The ID of the object. */ + id: string; + /** Only included if we did not encounter an error _and_ the object was found. */ + existingDocument?: SavedObjectsRawDoc; + /** Only included if we encountered an error. */ + error?: { + type: 'aliasConflict' | 'unresolvableConflict' | 'conflict'; + metadata?: { + spacesWithConflictingAliases?: string[]; + isNotOverwritable?: boolean; + }; + }; +} + +interface ParsedObject { + type: string; + id: string; + overwrite: boolean; + spaces: Set; +} + +/** + * Conducts pre-flight checks before object creation. Consumers should only check eligible objects (multi-namespace types). + * For each object that the consumer intends to create, we check for three potential error cases in all applicable spaces: + * + * 1. 'aliasConflict' - there is already an alias that points to a different object. + * 2. 'unresolvableConflict' - this object already exists in a different space and it cannot be overwritten with the given parameters. + * 3. 'conflict' - this object already exists (and the given options include `overwrite=false`). + * + * Objects can be created in 1-N spaces, and for each object+space combination we need to check if a legacy URL alias exists. This function + * attempts to optimize by defining an "alias threshold"; if we need to check for more aliases than that threshold, instead of attempting to + * bulk-get each one, we find (search for) them. This is intended to strike an acceptable balance of performance, and is necessary when + * creating objects in "*" (all current and future spaces) because we don't want to attempt to enumerate all spaces here. + * + * @param objects The objects that the consumer intends to create. + * + * @internal + */ +export async function preflightCheckForCreate(params: PreflightCheckForCreateParams) { + const { registry, client, serializer, getIndexForType, createPointInTimeFinder, objects } = + params; + + // Step 1: for each object, check if it is over the potential alias threshold; if so, attempt to search for aliases that may be affected. + // The result is a discriminated union: the left side is 'aliasConflict' errors, and the right side is objects/aliases to bulk-get. + const aliasConflictsOrObjectsToGet = await optionallyFindAliases( + createPointInTimeFinder, + objects + ); + + // Step 2: bulk-get all objects and aliases. + const objectsAndAliasesToBulkGet = aliasConflictsOrObjectsToGet + .filter(isRight) + .map(({ value }) => value); + const { bulkGetResponse, aliasSpaces } = await bulkGetObjectsAndAliases( + client, + serializer, + getIndexForType, + objectsAndAliasesToBulkGet + ); + + // Step 3: process all of the find and bulk-get results, and return appropriate results to the consumer. + let getResponseIndex = 0; + let aliasSpacesIndex = 0; + const results: PreflightCheckForCreateResult[] = []; + for (const either of aliasConflictsOrObjectsToGet) { + if (isLeft(either)) { + const { type, id, spacesWithConflictingAliases } = either.value; + const error = { + type: 'aliasConflict' as const, + metadata: { spacesWithConflictingAliases }, + }; + results.push({ type, id, error }); + } else { + const { type, id, spaces, overwrite, checkAliases } = either.value; + const objectDoc = bulkGetResponse?.body.docs[getResponseIndex++]!; + + if (checkAliases) { + const spacesWithConflictingAliases: string[] = []; + for (let i = 0; i < spaces.size; i++) { + const aliasDoc = bulkGetResponse?.body.docs[getResponseIndex++]; + const index = aliasSpacesIndex++; // increment whether the alias was found or not + if (aliasDoc?.found) { + const legacyUrlAlias: LegacyUrlAlias | undefined = + aliasDoc._source![LEGACY_URL_ALIAS_TYPE]; // if the 'disabled' field is not present, the source will be empty + if (!legacyUrlAlias?.disabled) { + // the alias was found, so the space we checked in has a conflicting alias + // in case the space in the alias's raw ID does not match the space in its sourceSpace field, prefer the former + spacesWithConflictingAliases.push(aliasSpaces[index]); + } + } + } + if (spacesWithConflictingAliases.length) { + const error = { + type: 'aliasConflict' as const, + metadata: { spacesWithConflictingAliases }, + }; + results.push({ type, id, error }); + continue; + } + } + + let existingDocument: PreflightCheckForCreateResult['existingDocument']; + if (objectDoc.found) { + // @ts-expect-error MultiGetHit._source is optional + if (!rawDocExistsInNamespaces(registry, objectDoc, [...spaces])) { + const error = { + type: 'unresolvableConflict' as const, + metadata: { isNotOverwritable: true }, + }; + results.push({ type, id, error }); + continue; + } else if (!overwrite) { + const error = { type: 'conflict' as const }; + results.push({ type, id, error }); + continue; + } + existingDocument = objectDoc as SavedObjectsRawDoc; + } + results.push({ type, id, existingDocument }); + } + } + return results; +} + +async function optionallyFindAliases( + createPointInTimeFinder: CreatePointInTimeFinderFn, + objects: PreflightCheckForCreateObject[] +) { + // Make a discriminated union based on the spaces the objects should be created in (Left=mget aliases, Right=find aliases) + const objectsToGetOrObjectsToFind = objects.map>((object) => { + const { type, id, namespaces, overwrite = false } = object; + const spaces = new Set(namespaces); + const tag = + spaces.size > FIND_ALIASES_THRESHOLD || spaces.has(ALL_NAMESPACES_STRING) ? 'Right' : 'Left'; + return { tag, value: { type, id, overwrite, spaces } }; + }); + + const objectsToFind = objectsToGetOrObjectsToFind + .filter(isRight) + .map(({ value: { type, id } }) => ({ type, id })); + const aliasMap = await findLegacyUrlAliases( + createPointInTimeFinder, + objectsToFind, + ALIAS_SEARCH_PER_PAGE + ); + + // Make another discriminated union based on the find results (Left=error, Right=mget objects/aliases) + const result = objectsToGetOrObjectsToFind.map< + Either< + ParsedObject & { spacesWithConflictingAliases: string[] }, + ParsedObject & { checkAliases: boolean } + > + >((either) => { + let checkAliases = true; + if (isRight(either)) { + const { type, id, spaces } = either.value; + const key = getObjectKey({ type, id }); + const spacesWithMatchingAliases = aliasMap.get(key); + if (spacesWithMatchingAliases) { + let spacesWithConflictingAliases: string[] = []; + if (spaces.has(ALL_NAMESPACES_STRING)) { + spacesWithConflictingAliases = [...spacesWithMatchingAliases]; + } else { + spacesWithConflictingAliases = intersection(spaces, spacesWithMatchingAliases); + } + if (spacesWithConflictingAliases.length) { + // we found one or more conflicting aliases, this is an error result + return { tag: 'Left', value: { ...either.value, spacesWithConflictingAliases } }; + } + } + // we checked for aliases but did not detect any conflicts; make sure we don't check for aliases again during mget + checkAliases = false; + } + return { tag: 'Right', value: { ...either.value, checkAliases } }; + }); + + return result; +} + +async function bulkGetObjectsAndAliases( + client: RepositoryEsClient, + serializer: SavedObjectsSerializer, + getIndexForType: (type: string) => string, + objectsAndAliasesToBulkGet: Array +) { + const docsToBulkGet: Array<{ _id: string; _index: string; _source: string[] }> = []; + const aliasSpaces: string[] = []; + for (const { type, id, spaces, checkAliases } of objectsAndAliasesToBulkGet) { + docsToBulkGet.push({ + _id: serializer.generateRawId(undefined, type, id), // namespace is intentionally undefined because multi-namespace objects don't have a namespace in their raw ID + _index: getIndexForType(type), + _source: ['type', 'namespaces'], + }); + if (checkAliases) { + for (const space of spaces) { + const rawAliasId = serializer.generateRawLegacyUrlAliasId(space, type, id); + docsToBulkGet.push({ + _id: rawAliasId, + _index: getIndexForType(LEGACY_URL_ALIAS_TYPE), + _source: [`${LEGACY_URL_ALIAS_TYPE}.disabled`], + }); + aliasSpaces.push(space); + } + } + } + + const bulkGetResponse = docsToBulkGet.length + ? await client.mget( + { body: { docs: docsToBulkGet } }, + { ignore: [404] } + ) + : undefined; + + return { bulkGetResponse, aliasSpaces }; +} + +function intersection(a: Set, b: Set) { + const result: T[] = []; + for (const x of a) { + if (b.has(x)) { + result.push(x); + } + } + return result; +} diff --git a/src/core/server/saved_objects/service/lib/repository.test.js b/src/core/server/saved_objects/service/lib/repository.test.js index 32b13ba160d5e..51ec81503956a 100644 --- a/src/core/server/saved_objects/service/lib/repository.test.js +++ b/src/core/server/saved_objects/service/lib/repository.test.js @@ -13,6 +13,7 @@ import { mockInternalBulkResolve, mockUpdateObjectsSpaces, mockGetCurrentTime, + mockPreflightCheckForCreate, } from './repository.test.mock'; import { SavedObjectsRepository } from './repository'; @@ -314,6 +315,13 @@ describe('SavedObjectsRepository', () => { }); describe('#bulkCreate', () => { + beforeEach(() => { + mockPreflightCheckForCreate.mockReset(); + mockPreflightCheckForCreate.mockImplementation(({ objects }) => { + return objects.map(({ type, id }) => ({ type, id })); // respond with no errors by default + }); + }); + const obj1 = { type: 'config', id: '6.0.0-alpha1', @@ -350,21 +358,11 @@ describe('SavedObjectsRepository', () => { }; const bulkCreateSuccess = async (objects, options) => { - const multiNamespaceObjects = objects.filter( - ({ type, id }) => registry.isMultiNamespace(type) && id - ); - if (multiNamespaceObjects?.length) { - const response = getMockMgetResponse(multiNamespaceObjects, options?.namespace); - client.mget.mockResolvedValue( - elasticsearchClientMock.createSuccessTransportRequestPromise(response) - ); - } const response = getMockBulkCreateResponse(objects, options?.namespace); client.bulk.mockResolvedValue( elasticsearchClientMock.createSuccessTransportRequestPromise(response) ); const result = await savedObjectsRepository.bulkCreate(objects, options); - expect(client.mget).toHaveBeenCalledTimes(multiNamespaceObjects?.length ? 1 : 0); return result; }; @@ -418,15 +416,23 @@ describe('SavedObjectsRepository', () => { expect(client.bulk).toHaveBeenCalledTimes(1); }); - it(`should use the ES mget action before bulk action for any types that are multi-namespace, when id is defined`, async () => { + it(`should use the preflightCheckForCreate action before bulk action for any types that are multi-namespace, when id is defined`, async () => { const objects = [obj1, { ...obj2, type: MULTI_NAMESPACE_ISOLATED_TYPE }]; await bulkCreateSuccess(objects); expect(client.bulk).toHaveBeenCalledTimes(1); - expect(client.mget).toHaveBeenCalledTimes(1); - const docs = [ - expect.objectContaining({ _id: `${MULTI_NAMESPACE_ISOLATED_TYPE}:${obj2.id}` }), - ]; - expect(client.mget.mock.calls[0][0].body).toEqual({ docs }); + expect(mockPreflightCheckForCreate).toHaveBeenCalledTimes(1); + expect(mockPreflightCheckForCreate).toHaveBeenCalledWith( + expect.objectContaining({ + objects: [ + { + type: MULTI_NAMESPACE_ISOLATED_TYPE, + id: obj2.id, + overwrite: false, + namespaces: ['default'], + }, + ], + }) + ); }); it(`should use the ES create method if ID is undefined and overwrite=true`, async () => { @@ -518,16 +524,25 @@ describe('SavedObjectsRepository', () => { it(`adds namespaces to request body for any types that are multi-namespace`, async () => { const test = async (namespace) => { const objects = [obj1, obj2].map((x) => ({ ...x, type: MULTI_NAMESPACE_ISOLATED_TYPE })); - const namespaces = [namespace ?? 'default']; + const [o1, o2] = objects; + mockPreflightCheckForCreate.mockResolvedValueOnce([ + { type: o1.type, id: o1.id }, // first object does not have an existing document to overwrite + { + type: o2.type, + id: o2.id, + existingDocument: { _source: { namespaces: ['*'] } }, // second object does have an existing document to overwrite + }, + ]); await bulkCreateSuccess(objects, { namespace, overwrite: true }); - const expected = expect.objectContaining({ namespaces }); - const body = [expect.any(Object), expected, expect.any(Object), expected]; + const expected1 = expect.objectContaining({ namespaces: [namespace ?? 'default'] }); + const expected2 = expect.objectContaining({ namespaces: ['*'] }); + const body = [expect.any(Object), expected1, expect.any(Object), expected2]; expect(client.bulk).toHaveBeenCalledWith( expect.objectContaining({ body }), expect.anything() ); client.bulk.mockClear(); - client.mget.mockClear(); + mockPreflightCheckForCreate.mockReset(); }; await test(undefined); await test(namespace); @@ -542,25 +557,46 @@ describe('SavedObjectsRepository', () => { { ...obj1, type: MULTI_NAMESPACE_ISOLATED_TYPE, initialNamespaces: [ns2] }, { ...obj1, type: MULTI_NAMESPACE_TYPE, initialNamespaces: [ns2, ns3] }, ]; + const [o1, o2, o3] = objects; + mockPreflightCheckForCreate.mockResolvedValueOnce([ + // first object does not get passed in to preflightCheckForCreate at all + { type: o2.type, id: o2.id }, // second object does not have an existing document to overwrite + { + type: o3.type, + id: o3.id, + existingDocument: { + _source: { namespaces: [namespace ?? 'default', 'something-else'] }, // third object does have an existing document to overwrite + }, + }, + ]); await bulkCreateSuccess(objects, { namespace, overwrite: true }); const body = [ - { index: expect.objectContaining({ _id: `${ns2}:dashboard:${obj1.id}` }) }, + { index: expect.objectContaining({ _id: `${ns2}:dashboard:${o1.id}` }) }, expect.objectContaining({ namespace: ns2 }), { index: expect.objectContaining({ - _id: `${MULTI_NAMESPACE_ISOLATED_TYPE}:${obj1.id}`, + _id: `${MULTI_NAMESPACE_ISOLATED_TYPE}:${o2.id}`, }), }, expect.objectContaining({ namespaces: [ns2] }), - { index: expect.objectContaining({ _id: `${MULTI_NAMESPACE_TYPE}:${obj1.id}` }) }, + { index: expect.objectContaining({ _id: `${MULTI_NAMESPACE_TYPE}:${o3.id}` }) }, expect.objectContaining({ namespaces: [ns2, ns3] }), ]; + expect(mockPreflightCheckForCreate).toHaveBeenCalledWith( + expect.objectContaining({ + objects: [ + // assert that the initialNamespaces fields were passed into preflightCheckForCreate instead of the current namespace + { type: o2.type, id: o2.id, overwrite: true, namespaces: o2.initialNamespaces }, + { type: o3.type, id: o3.id, overwrite: true, namespaces: o3.initialNamespaces }, + ], + }) + ); expect(client.bulk).toHaveBeenCalledWith( expect.objectContaining({ body }), expect.anything() ); client.bulk.mockClear(); - client.mget.mockClear(); + mockPreflightCheckForCreate.mockReset(); }; await test(undefined); await test(namespace); @@ -579,7 +615,6 @@ describe('SavedObjectsRepository', () => { expect.anything() ); client.bulk.mockClear(); - client.mget.mockClear(); }; await test(undefined); await test(namespace); @@ -748,94 +783,60 @@ describe('SavedObjectsRepository', () => { await bulkCreateError(obj, undefined, expectErrorInvalidType(obj)); }); - it(`returns error when there is a conflict with an existing multi-namespace saved object (get)`, async () => { - const obj = { ...obj3, type: MULTI_NAMESPACE_ISOLATED_TYPE }; - const response1 = { - status: 200, - docs: [ - { - found: true, - _source: { - type: obj.type, - namespaces: ['bar-namespace'], - }, - }, - ], - }; - client.mget.mockResolvedValueOnce( - elasticsearchClientMock.createSuccessTransportRequestPromise(response1) - ); - const response2 = getMockBulkCreateResponse([obj1, obj2]); + it(`returns error when there is a conflict from preflightCheckForCreate`, async () => { + const objects = [ + // only the second, third, and fourth objects are passed to preflightCheckForCreate and result in errors + obj1, + { ...obj1, type: MULTI_NAMESPACE_TYPE }, + { ...obj2, type: MULTI_NAMESPACE_TYPE }, + { ...obj3, type: MULTI_NAMESPACE_TYPE }, + obj2, + ]; + const [o1, o2, o3, o4, o5] = objects; + mockPreflightCheckForCreate.mockResolvedValueOnce([ + // first and last objects do not get passed in to preflightCheckForCreate at all + { type: o2.type, id: o2.id, error: { type: 'conflict' } }, + { + type: o3.type, + id: o3.id, + error: { type: 'unresolvableConflict', metadata: { isNotOverwritable: true } }, + }, + { + type: o4.type, + id: o4.id, + error: { type: 'aliasConflict', metadata: { spacesWithConflictingAliases: ['foo'] } }, + }, + ]); + const bulkResponse = getMockBulkCreateResponse([o1, o5]); client.bulk.mockResolvedValueOnce( - elasticsearchClientMock.createSuccessTransportRequestPromise(response2) + elasticsearchClientMock.createSuccessTransportRequestPromise(bulkResponse) ); const options = { overwrite: true }; - const result = await savedObjectsRepository.bulkCreate([obj1, obj, obj2], options); - expect(client.bulk).toHaveBeenCalled(); - expect(client.mget).toHaveBeenCalled(); - - const body1 = { docs: [expect.objectContaining({ _id: `${obj.type}:${obj.id}` })] }; - expect(client.mget).toHaveBeenCalledWith( - expect.objectContaining({ body: body1 }), - expect.anything() - ); - const body2 = [...expectObjArgs(obj1), ...expectObjArgs(obj2)]; - expect(client.bulk).toHaveBeenCalledWith( - expect.objectContaining({ body: body2 }), - expect.anything() - ); - const expectedError = expectErrorConflict(obj, { metadata: { isNotOverwritable: true } }); - expect(result).toEqual({ - saved_objects: [expectSuccess(obj1), expectedError, expectSuccess(obj2)], - }); - }); - - it(`returns error when there is an unresolvable conflict with an existing multi-namespace saved object when using initialNamespaces (get)`, async () => { - const obj = { - ...obj3, - type: MULTI_NAMESPACE_TYPE, - initialNamespaces: ['foo-namespace', 'default'], - }; - const response1 = { - status: 200, - docs: [ - { - found: true, - _source: { - type: obj.type, - namespaces: ['bar-namespace'], - }, - }, - ], - }; - client.mget.mockResolvedValueOnce( - elasticsearchClientMock.createSuccessTransportRequestPromise(response1) - ); - const response2 = getMockBulkCreateResponse([obj1, obj2]); - client.bulk.mockResolvedValueOnce( - elasticsearchClientMock.createSuccessTransportRequestPromise(response2) + const result = await savedObjectsRepository.bulkCreate(objects, options); + expect(mockPreflightCheckForCreate).toHaveBeenCalled(); + expect(mockPreflightCheckForCreate).toHaveBeenCalledWith( + expect.objectContaining({ + objects: [ + { type: o2.type, id: o2.id, overwrite: true, namespaces: ['default'] }, + { type: o3.type, id: o3.id, overwrite: true, namespaces: ['default'] }, + { type: o4.type, id: o4.id, overwrite: true, namespaces: ['default'] }, + ], + }) ); - - const options = { overwrite: true }; - const result = await savedObjectsRepository.bulkCreate([obj1, obj, obj2], options); - expect(client.bulk).toHaveBeenCalled(); - expect(client.mget).toHaveBeenCalled(); - - const body1 = { docs: [expect.objectContaining({ _id: `${obj.type}:${obj.id}` })] }; - expect(client.mget).toHaveBeenCalledWith( - expect.objectContaining({ body: body1 }), - expect.anything() - ); - const body2 = [...expectObjArgs(obj1), ...expectObjArgs(obj2)]; expect(client.bulk).toHaveBeenCalledWith( - expect.objectContaining({ body: body2 }), + expect.objectContaining({ body: [...expectObjArgs(o1), ...expectObjArgs(o5)] }), expect.anything() ); - const expectedError = expectErrorConflict(obj, { metadata: { isNotOverwritable: true } }); expect(result).toEqual({ - saved_objects: [expectSuccess(obj1), expectedError, expectSuccess(obj2)], + saved_objects: [ + expectSuccess(o1), + expectErrorConflict(o2), + expectErrorConflict(o3, { metadata: { isNotOverwritable: true } }), + expectErrorConflict(o4, { metadata: { spacesWithConflictingAliases: ['foo'] } }), + expectSuccess(o5), + ], }); }); @@ -1879,6 +1880,10 @@ describe('SavedObjectsRepository', () => { describe('#create', () => { beforeEach(() => { + mockPreflightCheckForCreate.mockReset(); + mockPreflightCheckForCreate.mockImplementation(({ objects }) => { + return objects.map(({ type, id }) => ({ type, id })); // respond with no errors by default + }); client.create.mockImplementation((params) => elasticsearchClientMock.createSuccessTransportRequestPromise({ _id: params.id, @@ -1902,27 +1907,26 @@ describe('SavedObjectsRepository', () => { const createSuccess = async (type, attributes, options) => { const result = await savedObjectsRepository.create(type, attributes, options); - expect(client.get).toHaveBeenCalledTimes( - registry.isMultiNamespace(type) && options.overwrite ? 1 : 0 - ); return result; }; describe('client calls', () => { - it(`should use the ES index action if overwrite=true`, async () => { + it(`should use the ES index action if ID is not defined and overwrite=true`, async () => { await createSuccess(type, attributes, { overwrite: true }); + expect(mockPreflightCheckForCreate).not.toHaveBeenCalled(); expect(client.index).toHaveBeenCalled(); }); - it(`should use the ES create action if overwrite=false`, async () => { + it(`should use the ES create action if ID is not defined and overwrite=false`, async () => { await createSuccess(type, attributes); + expect(mockPreflightCheckForCreate).not.toHaveBeenCalled(); expect(client.create).toHaveBeenCalled(); }); it(`should use the ES index with version if ID and version are defined and overwrite=true`, async () => { await createSuccess(type, attributes, { id, overwrite: true, version: mockVersion }); + expect(mockPreflightCheckForCreate).not.toHaveBeenCalled(); expect(client.index).toHaveBeenCalled(); - expect(client.index.mock.calls[0][0]).toMatchObject({ if_seq_no: mockVersionProps._seq_no, if_primary_term: mockVersionProps._primary_term, @@ -1931,12 +1935,33 @@ describe('SavedObjectsRepository', () => { it(`should use the ES create action if ID is defined and overwrite=false`, async () => { await createSuccess(type, attributes, { id }); + expect(mockPreflightCheckForCreate).not.toHaveBeenCalled(); expect(client.create).toHaveBeenCalled(); }); - it(`should use the ES get action then index action if type is multi-namespace, ID is defined, and overwrite=true`, async () => { + it(`should use the preflightCheckForCreate action then create action if type is multi-namespace, ID is defined, and overwrite=false`, async () => { + await createSuccess(MULTI_NAMESPACE_TYPE, attributes, { id }); + expect(mockPreflightCheckForCreate).toHaveBeenCalled(); + expect(mockPreflightCheckForCreate).toHaveBeenCalledWith( + expect.objectContaining({ + objects: [ + { type: MULTI_NAMESPACE_TYPE, id, overwrite: false, namespaces: ['default'] }, + ], + }) + ); + expect(client.create).toHaveBeenCalled(); + }); + + it(`should use the preflightCheckForCreate action then index action if type is multi-namespace, ID is defined, and overwrite=true`, async () => { await createSuccess(MULTI_NAMESPACE_ISOLATED_TYPE, attributes, { id, overwrite: true }); - expect(client.get).toHaveBeenCalled(); + expect(mockPreflightCheckForCreate).toHaveBeenCalled(); + expect(mockPreflightCheckForCreate).toHaveBeenCalledWith( + expect.objectContaining({ + objects: [ + { type: MULTI_NAMESPACE_ISOLATED_TYPE, id, overwrite: true, namespaces: ['default'] }, + ], + }) + ); expect(client.index).toHaveBeenCalled(); }); @@ -2056,36 +2081,103 @@ describe('SavedObjectsRepository', () => { }); it(`doesn't prepend namespace to the id and adds namespaces to body when using multi-namespace type`, async () => { - await createSuccess(MULTI_NAMESPACE_ISOLATED_TYPE, attributes, { id, namespace }); + // first object does not have an existing document to overwrite + await createSuccess(MULTI_NAMESPACE_TYPE, attributes, { id, namespace }); + mockPreflightCheckForCreate.mockResolvedValueOnce([ + { + type: MULTI_NAMESPACE_TYPE, + id, + existingDocument: { _source: { namespaces: ['*'] } }, // second object does have an existing document to overwrite + }, + ]); + await createSuccess(MULTI_NAMESPACE_ISOLATED_TYPE, attributes, { + id, + namespace, + overwrite: true, + }); + + expect(mockPreflightCheckForCreate).toHaveBeenCalledTimes(2); + expect(mockPreflightCheckForCreate).toHaveBeenNthCalledWith( + 1, + expect.objectContaining({ + objects: [ + { type: MULTI_NAMESPACE_TYPE, id, overwrite: false, namespaces: [namespace] }, + ], + }) + ); + expect(mockPreflightCheckForCreate).toHaveBeenNthCalledWith( + 2, + expect.objectContaining({ + objects: [ + { type: MULTI_NAMESPACE_ISOLATED_TYPE, id, overwrite: true, namespaces: [namespace] }, + ], + }) + ); + + expect(client.create).toHaveBeenCalledTimes(1); expect(client.create).toHaveBeenCalledWith( expect.objectContaining({ - id: `${MULTI_NAMESPACE_ISOLATED_TYPE}:${id}`, + id: `${MULTI_NAMESPACE_TYPE}:${id}`, body: expect.objectContaining({ namespaces: [namespace] }), }), expect.anything() ); + expect(client.index).toHaveBeenCalledTimes(1); + expect(client.index).toHaveBeenCalledWith( + expect.objectContaining({ + id: `${MULTI_NAMESPACE_ISOLATED_TYPE}:${id}`, + body: expect.objectContaining({ namespaces: ['*'] }), + }), + expect.anything() + ); }); it(`adds initialNamespaces instead of namespace`, async () => { const ns2 = 'bar-namespace'; const ns3 = 'baz-namespace'; + // first object does not get passed in to preflightCheckForCreate at all await savedObjectsRepository.create('dashboard', attributes, { id, namespace, initialNamespaces: [ns2], }); - await savedObjectsRepository.create(MULTI_NAMESPACE_ISOLATED_TYPE, attributes, { + // second object does not have an existing document to overwrite + await savedObjectsRepository.create(MULTI_NAMESPACE_TYPE, attributes, { id, namespace, - initialNamespaces: [ns2], + initialNamespaces: [ns2, ns3], }); - await savedObjectsRepository.create(MULTI_NAMESPACE_TYPE, attributes, { + mockPreflightCheckForCreate.mockResolvedValueOnce([ + { + type: MULTI_NAMESPACE_ISOLATED_TYPE, + id, + existingDocument: { _source: { namespaces: ['something-else'] } }, // third object does have an existing document to overwrite + }, + ]); + await savedObjectsRepository.create(MULTI_NAMESPACE_ISOLATED_TYPE, attributes, { id, namespace, - initialNamespaces: [ns2, ns3], + initialNamespaces: [ns2], + overwrite: true, }); - expect(client.create).toHaveBeenCalledTimes(3); + expect(mockPreflightCheckForCreate).toHaveBeenCalledTimes(2); + expect(mockPreflightCheckForCreate).toHaveBeenNthCalledWith( + 1, + expect.objectContaining({ + objects: [{ type: MULTI_NAMESPACE_TYPE, id, overwrite: false, namespaces: [ns2, ns3] }], + }) + ); + expect(mockPreflightCheckForCreate).toHaveBeenNthCalledWith( + 2, + expect.objectContaining({ + objects: [ + { type: MULTI_NAMESPACE_ISOLATED_TYPE, id, overwrite: true, namespaces: [ns2] }, + ], + }) + ); + + expect(client.create).toHaveBeenCalledTimes(2); expect(client.create).toHaveBeenNthCalledWith( 1, expect.objectContaining({ @@ -2097,16 +2189,16 @@ describe('SavedObjectsRepository', () => { expect(client.create).toHaveBeenNthCalledWith( 2, expect.objectContaining({ - id: `${MULTI_NAMESPACE_ISOLATED_TYPE}:${id}`, - body: expect.objectContaining({ namespaces: [ns2] }), + id: `${MULTI_NAMESPACE_TYPE}:${id}`, + body: expect.objectContaining({ namespaces: [ns2, ns3] }), }), expect.anything() ); - expect(client.create).toHaveBeenNthCalledWith( - 3, + expect(client.index).toHaveBeenCalledTimes(1); + expect(client.index).toHaveBeenCalledWith( expect.objectContaining({ - id: `${MULTI_NAMESPACE_TYPE}:${id}`, - body: expect.objectContaining({ namespaces: [ns2, ns3] }), + id: `${MULTI_NAMESPACE_ISOLATED_TYPE}:${id}`, + body: expect.objectContaining({ namespaces: [ns2] }), }), expect.anything() ); @@ -2200,14 +2292,10 @@ describe('SavedObjectsRepository', () => { expect(client.create).not.toHaveBeenCalled(); }); - it(`throws when there is a conflict with an existing multi-namespace saved object (get)`, async () => { - const response = getMockGetResponse( - { type: MULTI_NAMESPACE_ISOLATED_TYPE, id }, - 'bar-namespace' - ); - client.get.mockResolvedValueOnce( - elasticsearchClientMock.createSuccessTransportRequestPromise(response) - ); + it(`throws when there is a conflict from preflightCheckForCreate`, async () => { + mockPreflightCheckForCreate.mockResolvedValueOnce([ + { type: MULTI_NAMESPACE_ISOLATED_TYPE, id, error: { type: 'unresolvableConflict' } }, // error type and metadata dont matter + ]); await expect( savedObjectsRepository.create(MULTI_NAMESPACE_ISOLATED_TYPE, attributes, { id, @@ -2215,23 +2303,7 @@ describe('SavedObjectsRepository', () => { namespace, }) ).rejects.toThrowError(createConflictError(MULTI_NAMESPACE_ISOLATED_TYPE, id)); - expect(client.get).toHaveBeenCalled(); - }); - - it(`throws when there is an unresolvable conflict with an existing multi-namespace saved object when using initialNamespaces (get)`, async () => { - const response = getMockGetResponse({ type: MULTI_NAMESPACE_ISOLATED_TYPE, id }, namespace); - client.get.mockResolvedValueOnce( - elasticsearchClientMock.createSuccessTransportRequestPromise(response) - ); - await expect( - savedObjectsRepository.create(MULTI_NAMESPACE_TYPE, attributes, { - id, - overwrite: true, - initialNamespaces: ['bar-ns', 'dolly-ns'], - namespace, - }) - ).rejects.toThrowError(createConflictError(MULTI_NAMESPACE_TYPE, id)); - expect(client.get).toHaveBeenCalled(); + expect(mockPreflightCheckForCreate).toHaveBeenCalled(); }); it.todo(`throws when automatic index creation fails`); @@ -3513,10 +3585,12 @@ describe('SavedObjectsRepository', () => { const namespace = 'foo-namespace'; const originId = 'some-origin-id'; - const incrementCounterSuccess = async (type, id, fields, options) => { + const incrementCounterSuccess = async (type, id, fields, options, internalOptions = {}) => { + const { mockGetResponseValue } = internalOptions; const isMultiNamespace = registry.isMultiNamespace(type); if (isMultiNamespace) { - const response = getMockGetResponse({ type, id }, options?.namespace); + const response = + mockGetResponseValue ?? getMockGetResponse({ type, id }, options?.namespace); client.get.mockResolvedValueOnce( elasticsearchClientMock.createSuccessTransportRequestPromise(response) ); @@ -3548,9 +3622,18 @@ describe('SavedObjectsRepository', () => { return result; }; + beforeEach(() => { + mockPreflightCheckForCreate.mockReset(); + mockPreflightCheckForCreate.mockImplementation(({ objects }) => { + return objects.map(({ type, id }) => ({ type, id })); // respond with no errors by default + }); + }); + describe('client calls', () => { it(`should use the ES update action if type is not multi-namespace`, async () => { await incrementCounterSuccess(type, id, counterFields, { namespace }); + expect(client.get).not.toHaveBeenCalled(); + expect(mockPreflightCheckForCreate).not.toHaveBeenCalled(); expect(client.update).toHaveBeenCalledTimes(1); }); @@ -3559,6 +3642,20 @@ describe('SavedObjectsRepository', () => { namespace, }); expect(client.get).toHaveBeenCalledTimes(1); + expect(mockPreflightCheckForCreate).not.toHaveBeenCalled(); + expect(client.update).toHaveBeenCalledTimes(1); + }); + + it(`should check for alias conflicts if a new multi-namespace object would be created`, async () => { + await incrementCounterSuccess( + MULTI_NAMESPACE_ISOLATED_TYPE, + id, + counterFields, + { namespace }, + { mockGetResponseValue: { found: false } } + ); + expect(client.get).toHaveBeenCalledTimes(1); + expect(mockPreflightCheckForCreate).toHaveBeenCalledTimes(1); expect(client.update).toHaveBeenCalledTimes(1); }); @@ -3727,6 +3824,43 @@ describe('SavedObjectsRepository', () => { ) ).rejects.toThrowError(createConflictError(MULTI_NAMESPACE_ISOLATED_TYPE, id)); expect(client.get).toHaveBeenCalledTimes(1); + expect(mockPreflightCheckForCreate).not.toHaveBeenCalled(); + expect(client.update).not.toHaveBeenCalled(); + }); + + it(`throws when there is an alias conflict from preflightCheckForCreate`, async () => { + client.get.mockResolvedValueOnce( + elasticsearchClientMock.createSuccessTransportRequestPromise({ found: false }) + ); + mockPreflightCheckForCreate.mockResolvedValue([{ error: { type: 'aliasConflict' } }]); + await expect( + savedObjectsRepository.incrementCounter( + MULTI_NAMESPACE_ISOLATED_TYPE, + id, + counterFields, + { namespace } + ) + ).rejects.toThrowError(createConflictError(MULTI_NAMESPACE_ISOLATED_TYPE, id)); + expect(client.get).toHaveBeenCalledTimes(1); + expect(mockPreflightCheckForCreate).toHaveBeenCalledTimes(1); + expect(client.update).not.toHaveBeenCalled(); + }); + + it(`does not throw when there is a different error from preflightCheckForCreate`, async () => { + client.get.mockResolvedValueOnce( + elasticsearchClientMock.createSuccessTransportRequestPromise({ found: false }) + ); + mockPreflightCheckForCreate.mockResolvedValue([{ error: { type: 'something-else' } }]); + await incrementCounterSuccess( + MULTI_NAMESPACE_ISOLATED_TYPE, + id, + counterFields, + { namespace }, + { mockGetResponseValue: { found: false } } + ); + expect(client.get).toHaveBeenCalledTimes(1); + expect(mockPreflightCheckForCreate).toHaveBeenCalledTimes(1); + expect(client.update).toHaveBeenCalledTimes(1); }); }); @@ -3872,9 +4006,11 @@ describe('SavedObjectsRepository', () => { ); }; - const updateSuccess = async (type, id, attributes, options, includeOriginId) => { + const updateSuccess = async (type, id, attributes, options, internalOptions = {}) => { + const { mockGetResponseValue, includeOriginId } = internalOptions; if (registry.isMultiNamespace(type)) { - const mockGetResponse = getMockGetResponse({ type, id }, options?.namespace); + const mockGetResponse = + mockGetResponseValue ?? getMockGetResponse({ type, id }, options?.namespace); client.get.mockResolvedValueOnce( elasticsearchClientMock.createSuccessTransportRequestPromise( { ...mockGetResponse }, @@ -3888,15 +4024,38 @@ describe('SavedObjectsRepository', () => { return result; }; + beforeEach(() => { + mockPreflightCheckForCreate.mockReset(); + mockPreflightCheckForCreate.mockImplementation(({ objects }) => { + return objects.map(({ type, id }) => ({ type, id })); // respond with no errors by default + }); + }); + describe('client calls', () => { + it(`should use the ES update action when type is not multi-namespace`, async () => { + await updateSuccess(type, id, attributes); + expect(client.get).not.toHaveBeenCalled(); + expect(mockPreflightCheckForCreate).not.toHaveBeenCalled(); + expect(client.update).toHaveBeenCalledTimes(1); + }); + it(`should use the ES get action then update action when type is multi-namespace`, async () => { await updateSuccess(MULTI_NAMESPACE_ISOLATED_TYPE, id, attributes); expect(client.get).toHaveBeenCalledTimes(1); + expect(mockPreflightCheckForCreate).not.toHaveBeenCalled(); expect(client.update).toHaveBeenCalledTimes(1); }); - it(`should use the ES update action when type is not multi-namespace`, async () => { - await updateSuccess(type, id, attributes); + it(`should check for alias conflicts if a new multi-namespace object would be created`, async () => { + await updateSuccess( + MULTI_NAMESPACE_ISOLATED_TYPE, + id, + attributes, + { upsert: true }, + { mockGetResponseValue: { found: false } } + ); + expect(client.get).toHaveBeenCalledTimes(1); + expect(mockPreflightCheckForCreate).toHaveBeenCalledTimes(1); expect(client.update).toHaveBeenCalledTimes(1); }); @@ -4147,6 +4306,33 @@ describe('SavedObjectsRepository', () => { expect(client.get).toHaveBeenCalledTimes(1); }); + it(`throws when there is an alias conflict from preflightCheckForCreate`, async () => { + client.get.mockResolvedValueOnce( + elasticsearchClientMock.createSuccessTransportRequestPromise({ found: false }) + ); + mockPreflightCheckForCreate.mockResolvedValue([{ error: { type: 'aliasConflict' } }]); + await expect( + savedObjectsRepository.update(MULTI_NAMESPACE_ISOLATED_TYPE, id, {}, { upsert: true }) + ).rejects.toThrowError(createConflictError(MULTI_NAMESPACE_ISOLATED_TYPE, id)); + expect(client.get).toHaveBeenCalledTimes(1); + expect(mockPreflightCheckForCreate).toHaveBeenCalledTimes(1); + expect(client.update).not.toHaveBeenCalled(); + }); + + it(`does not throw when there is a different error from preflightCheckForCreate`, async () => { + mockPreflightCheckForCreate.mockResolvedValue([{ error: { type: 'something-else' } }]); + await updateSuccess( + MULTI_NAMESPACE_ISOLATED_TYPE, + id, + attributes, + { upsert: true }, + { mockGetResponseValue: { found: false } } + ); + expect(client.get).toHaveBeenCalledTimes(1); + expect(mockPreflightCheckForCreate).toHaveBeenCalledTimes(1); + expect(client.update).toHaveBeenCalledTimes(1); + }); + it(`throws when ES is unable to find the document during update`, async () => { const notFoundError = new EsErrors.ResponseError( elasticsearchClientMock.createApiResponse({ @@ -4194,7 +4380,7 @@ describe('SavedObjectsRepository', () => { }); it(`includes originId property if present in cluster call response`, async () => { - const result = await updateSuccess(type, id, attributes, {}, true); + const result = await updateSuccess(type, id, attributes, {}, { includeOriginId: true }); expect(result).toMatchObject({ originId }); }); }); diff --git a/src/core/server/saved_objects/service/lib/repository.test.mock.ts b/src/core/server/saved_objects/service/lib/repository.test.mock.ts index d9a611226f8b5..88eb13e3ca46b 100644 --- a/src/core/server/saved_objects/service/lib/repository.test.mock.ts +++ b/src/core/server/saved_objects/service/lib/repository.test.mock.ts @@ -9,6 +9,7 @@ import type { collectMultiNamespaceReferences } from './collect_multi_namespace_references'; import type { internalBulkResolve } from './internal_bulk_resolve'; import type * as InternalUtils from './internal_utils'; +import type { preflightCheckForCreate } from './preflight_check_for_create'; import type { updateObjectsSpaces } from './update_objects_spaces'; export const mockCollectMultiNamespaceReferences = jest.fn() as jest.MockedFunction< @@ -41,6 +42,14 @@ jest.mock('./internal_utils', () => { }; }); +export const mockPreflightCheckForCreate = jest.fn() as jest.MockedFunction< + typeof preflightCheckForCreate +>; + +jest.mock('./preflight_check_for_create', () => ({ + preflightCheckForCreate: mockPreflightCheckForCreate, +})); + export const mockUpdateObjectsSpaces = jest.fn() as jest.MockedFunction; jest.mock('./update_objects_spaces', () => ({ diff --git a/src/core/server/saved_objects/service/lib/repository.ts b/src/core/server/saved_objects/service/lib/repository.ts index 9f69396fac838..383801e790c76 100644 --- a/src/core/server/saved_objects/service/lib/repository.ts +++ b/src/core/server/saved_objects/service/lib/repository.ts @@ -96,6 +96,10 @@ import { SavedObjectsUpdateObjectsSpacesOptions, } from './update_objects_spaces'; import { getIndexForType } from './get_index_for_type'; +import { + preflightCheckForCreate, + PreflightCheckForCreateObject, +} from './preflight_check_for_create'; // BEWARE: The SavedObjectClient depends on the implementation details of the SavedObjectsRepository // so any breaking changes to this repository are considered breaking changes to the SavedObjectsClient. @@ -324,19 +328,23 @@ export class SavedObjectsRepository { ? normalizeNamespace(initialNamespaces[0]) : namespace; } else if (this._registry.isMultiNamespace(type)) { - if (id && overwrite) { + if (options.id) { // we will overwrite a multi-namespace saved object if it exists; if that happens, ensure we preserve its included namespaces // note: this check throws an error if the object is found but does not exist in this namespace - const preflightResult = await this.preflightCheckNamespaces({ - type, - id, - namespace, - initialNamespaces, + const namespaceString = SavedObjectsUtils.namespaceIdToString(namespace); + const [{ error, existingDocument }] = await preflightCheckForCreate({ + registry: this._registry, + client: this.client, + serializer: this._serializer, + getIndexForType: this.getIndexForType.bind(this), + createPointInTimeFinder: this.createPointInTimeFinder.bind(this), + objects: [{ type, id, overwrite, namespaces: initialNamespaces ?? [namespaceString] }], }); - if (preflightResult.checkResult === 'found_outside_namespace') { + if (error) { throw SavedObjectsErrorHelpers.createConflictError(type, id); } - savedObjectNamespaces = preflightResult.savedObjectNamespaces; + savedObjectNamespaces = + initialNamespaces || getSavedObjectNamespaces(namespace, existingDocument); } else { savedObjectNamespaces = initialNamespaces || getSavedObjectNamespaces(namespace); } @@ -393,160 +401,149 @@ export class SavedObjectsRepository { const namespace = normalizeNamespace(options.namespace); const time = getCurrentTime(); - let bulkGetRequestIndexCounter = 0; - const expectedResults: Array, Record>> = objects.map( - (object) => { - const { type, id, initialNamespaces } = object; - let error: DecoratedError | undefined; - if (!this._allowedTypes.includes(type)) { - error = SavedObjectsErrorHelpers.createUnsupportedTypeError(type); - } else { - try { - this.validateInitialNamespaces(type, initialNamespaces); - } catch (e) { - error = e; - } - } - - if (error) { - return { - tag: 'Left', - value: { id, type, error: errorContent(error) }, - }; + let preflightCheckIndexCounter = 0; + const expectedResults = objects.map< + Either< + { type: string; id?: string; error: Payload }, + { + method: 'index' | 'create'; + object: SavedObjectsBulkCreateObject & { id: string }; + preflightCheckIndex?: number; } - - const method = id && overwrite ? 'index' : 'create'; - const requiresNamespacesCheck = id && this._registry.isMultiNamespace(type); - - if (id == null) { - object.id = SavedObjectsUtils.generateId(); + > + >((object) => { + const { type, id, initialNamespaces } = object; + let error: DecoratedError | undefined; + if (!this._allowedTypes.includes(type)) { + error = SavedObjectsErrorHelpers.createUnsupportedTypeError(type); + } else { + try { + this.validateInitialNamespaces(type, initialNamespaces); + } catch (e) { + error = e; } + } + if (error) { return { - tag: 'Right', - value: { - method, - object, - ...(requiresNamespacesCheck && { esRequestIndex: bulkGetRequestIndexCounter++ }), - }, + tag: 'Left', + value: { id, type, error: errorContent(error) }, }; } - ); - const bulkGetDocs = expectedResults + const method = id && overwrite ? 'index' : 'create'; + const requiresNamespacesCheck = id && this._registry.isMultiNamespace(type); + + return { + tag: 'Right', + value: { + method, + object: { ...object, id: object.id || SavedObjectsUtils.generateId() }, + ...(requiresNamespacesCheck && { preflightCheckIndex: preflightCheckIndexCounter++ }), + }, + }; + }); + + const namespaceString = SavedObjectsUtils.namespaceIdToString(namespace); + const preflightCheckObjects = expectedResults .filter(isRight) - .filter(({ value }) => value.esRequestIndex !== undefined) - .map( - ({ - value: { - object: { type, id }, - }, - }) => ({ - _id: this._serializer.generateRawId(namespace, type, id), - _index: this.getIndexForType(type), - _source: ['type', 'namespaces'], - }) - ); - const bulkGetResponse = bulkGetDocs.length - ? await this.client.mget( - { - body: { - docs: bulkGetDocs, - }, - }, - { ignore: [404] } - ) - : undefined; + .filter(({ value }) => value.preflightCheckIndex !== undefined) + .map(({ value }) => { + const { type, id, initialNamespaces } = value.object; + const namespaces = initialNamespaces ?? [namespaceString]; + return { type, id, overwrite, namespaces }; + }); + const preflightCheckResponse = await preflightCheckForCreate({ + registry: this._registry, + client: this.client, + serializer: this._serializer, + getIndexForType: this.getIndexForType.bind(this), + createPointInTimeFinder: this.createPointInTimeFinder.bind(this), + objects: preflightCheckObjects, + }); let bulkRequestIndexCounter = 0; const bulkCreateParams: object[] = []; - const expectedBulkResults: Array, Record>> = - expectedResults.map((expectedBulkGetResult) => { - if (isLeft(expectedBulkGetResult)) { - return expectedBulkGetResult; - } + const expectedBulkResults = expectedResults.map< + Either< + { type: string; id?: string; error: Payload }, + { esRequestIndex: number; requestedId: string; rawMigratedDoc: SavedObjectsRawDoc } + > + >((expectedBulkGetResult) => { + if (isLeft(expectedBulkGetResult)) { + return expectedBulkGetResult; + } - let savedObjectNamespace: string | undefined; - let savedObjectNamespaces: string[] | undefined; - let versionProperties; - const { - esRequestIndex, - object: { initialNamespaces, version, ...object }, - method, - } = expectedBulkGetResult.value; - if (esRequestIndex !== undefined) { - const indexFound = bulkGetResponse?.statusCode !== 404; - const actualResult = indexFound ? bulkGetResponse?.body.docs[esRequestIndex] : undefined; - const docFound = indexFound && actualResult?.found === true; - if ( - docFound && - !this.rawDocExistsInNamespaces( - // @ts-expect-error MultiGetHit._source is optional - actualResult!, - initialNamespaces ?? [SavedObjectsUtils.namespaceIdToString(namespace)] - ) - ) { - const { id, type } = object; - return { - tag: 'Left', - value: { - id, - type, - error: { - ...errorContent(SavedObjectsErrorHelpers.createConflictError(type, id)), - metadata: { isNotOverwritable: true }, - }, + let savedObjectNamespace: string | undefined; + let savedObjectNamespaces: string[] | undefined; + let versionProperties; + const { + preflightCheckIndex, + object: { initialNamespaces, version, ...object }, + method, + } = expectedBulkGetResult.value; + if (preflightCheckIndex !== undefined) { + const preflightResult = preflightCheckResponse[preflightCheckIndex]; + const { type, id, existingDocument, error } = preflightResult; + if (error) { + const { metadata } = error; + return { + tag: 'Left', + value: { + id, + type, + error: { + ...errorContent(SavedObjectsErrorHelpers.createConflictError(type, id)), + ...(metadata && { metadata }), }, - }; - } - savedObjectNamespaces = - initialNamespaces || - // @ts-expect-error MultiGetHit._source is optional - getSavedObjectNamespaces(namespace, docFound ? actualResult : undefined); - // @ts-expect-error MultiGetHit._source is optional - versionProperties = getExpectedVersionProperties(version, actualResult); - } else { - if (this._registry.isSingleNamespace(object.type)) { - savedObjectNamespace = initialNamespaces - ? normalizeNamespace(initialNamespaces[0]) - : namespace; - } else if (this._registry.isMultiNamespace(object.type)) { - savedObjectNamespaces = initialNamespaces || getSavedObjectNamespaces(namespace); - } - versionProperties = getExpectedVersionProperties(version); + }, + }; + } + savedObjectNamespaces = + initialNamespaces || getSavedObjectNamespaces(namespace, existingDocument); + versionProperties = getExpectedVersionProperties(version, existingDocument); + } else { + if (this._registry.isSingleNamespace(object.type)) { + savedObjectNamespace = initialNamespaces + ? normalizeNamespace(initialNamespaces[0]) + : namespace; + } else if (this._registry.isMultiNamespace(object.type)) { + savedObjectNamespaces = initialNamespaces || getSavedObjectNamespaces(namespace); } + versionProperties = getExpectedVersionProperties(version); + } - const expectedResult = { - esRequestIndex: bulkRequestIndexCounter++, - requestedId: object.id, - rawMigratedDoc: this._serializer.savedObjectToRaw( - this._migrator.migrateDocument({ - id: object.id, - type: object.type, - attributes: object.attributes, - migrationVersion: object.migrationVersion, - ...(savedObjectNamespace && { namespace: savedObjectNamespace }), - ...(savedObjectNamespaces && { namespaces: savedObjectNamespaces }), - updated_at: time, - references: object.references || [], - originId: object.originId, - }) as SavedObjectSanitizedDoc - ), - }; + const expectedResult = { + esRequestIndex: bulkRequestIndexCounter++, + requestedId: object.id, + rawMigratedDoc: this._serializer.savedObjectToRaw( + this._migrator.migrateDocument({ + id: object.id, + type: object.type, + attributes: object.attributes, + migrationVersion: object.migrationVersion, + ...(savedObjectNamespace && { namespace: savedObjectNamespace }), + ...(savedObjectNamespaces && { namespaces: savedObjectNamespaces }), + updated_at: time, + references: object.references || [], + originId: object.originId, + }) as SavedObjectSanitizedDoc + ), + }; - bulkCreateParams.push( - { - [method]: { - _id: expectedResult.rawMigratedDoc._id, - _index: this.getIndexForType(object.type), - ...(overwrite && versionProperties), - }, + bulkCreateParams.push( + { + [method]: { + _id: expectedResult.rawMigratedDoc._id, + _index: this.getIndexForType(object.type), + ...(overwrite && versionProperties), }, - expectedResult.rawMigratedDoc._source - ); + }, + expectedResult.rawMigratedDoc._source + ); - return { tag: 'Right', value: expectedResult }; - }); + return { tag: 'Right', value: expectedResult }; + }); const bulkResponse = bulkCreateParams.length ? await this.client.bulk({ @@ -1228,6 +1225,12 @@ export class SavedObjectsRepository { ) { throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); } + if (upsert && preflightResult.checkResult === 'not_found') { + // If an upsert would result in the creation of a new object, we need to check for alias conflicts too. + // This takes an extra round trip to Elasticsearch, but this won't happen often. + // TODO: improve performance by combining these into a single preflight check + await this.preflightCheckForUpsertAliasConflict(type, id, namespace); + } } const time = getCurrentTime(); @@ -1764,6 +1767,14 @@ export class SavedObjectsRepository { if (preflightResult.checkResult === 'found_outside_namespace') { throw SavedObjectsErrorHelpers.createConflictError(type, id); } + + if (preflightResult.checkResult === 'not_found') { + // If an upsert would result in the creation of a new object, we need to check for alias conflicts too. + // This takes an extra round trip to Elasticsearch, but this won't happen often. + // TODO: improve performance by combining these into a single preflight check + await this.preflightCheckForUpsertAliasConflict(type, id, namespace); + } + savedObjectNamespaces = preflightResult.savedObjectNamespaces; } @@ -2095,6 +2106,29 @@ export class SavedObjectsRepository { }; } + /** + * Pre-flight check to ensure that an upsert which would create a new object does not result in an alias conflict. + */ + private async preflightCheckForUpsertAliasConflict( + type: string, + id: string, + namespace: string | undefined + ) { + const namespaceString = SavedObjectsUtils.namespaceIdToString(namespace); + const [{ error }] = await preflightCheckForCreate({ + registry: this._registry, + client: this.client, + serializer: this._serializer, + getIndexForType: this.getIndexForType.bind(this), + createPointInTimeFinder: this.createPointInTimeFinder.bind(this), + objects: [{ type, id, namespaces: [namespaceString] }], + }); + if (error?.type === 'aliasConflict') { + throw SavedObjectsErrorHelpers.createConflictError(type, id); + } + // any other error from this check does not matter + } + /** The `initialNamespaces` field (create, bulkCreate) is used to create an object in an initial set of spaces. */ private validateInitialNamespaces(type: string, initialNamespaces: string[] | undefined) { if (!initialNamespaces) { diff --git a/x-pack/test/saved_object_api_integration/common/fixtures/es_archiver/saved_objects/spaces/data.json b/x-pack/test/saved_object_api_integration/common/fixtures/es_archiver/saved_objects/spaces/data.json index 56785f913262a..84c31dc2b7db6 100644 --- a/x-pack/test/saved_object_api_integration/common/fixtures/es_archiver/saved_objects/spaces/data.json +++ b/x-pack/test/saved_object_api_integration/common/fixtures/es_archiver/saved_objects/spaces/data.json @@ -573,6 +573,43 @@ } } +{ + "type": "doc", + "value": { + "index": ".kibana", + "id": "legacy-url-alias:space_x:resolvetype:alias-match", + "source": { + "type": "legacy-url-alias", + "updated_at": "2017-09-21T18:51:23.794Z", + "legacy-url-alias": { + "sourceId": "alias-match", + "targetNamespace": "space_x", + "targetType": "resolvetype", + "targetId": "doesnt-matter" + } + } + } +} + +{ + "type": "doc", + "value": { + "index": ".kibana", + "id": "legacy-url-alias:space_y:resolvetype:alias-match", + "source": { + "type": "legacy-url-alias", + "updated_at": "2017-09-21T18:51:23.794Z", + "legacy-url-alias": { + "sourceId": "alias-match", + "targetNamespace": "space_y", + "targetType": "resolvetype", + "targetId": "doesnt-matter", + "disabled": true + } + } + } +} + { "type": "doc", "value": { diff --git a/x-pack/test/saved_object_api_integration/common/suites/bulk_create.ts b/x-pack/test/saved_object_api_integration/common/suites/bulk_create.ts index 1c4fc9bfa372f..45a96f8ebd8b4 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/bulk_create.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/bulk_create.ts @@ -65,6 +65,7 @@ const INITIAL_NS_MULTI_NAMESPACE_OBJ_ALL_SPACES = Object.freeze({ expectedNamespaces: [ALL_SPACES_ID], // expected namespaces of resulting object initialNamespaces: [ALL_SPACES_ID], // args passed to the bulkCreate method }); +const ALIAS_CONFLICT_OBJ = Object.freeze({ type: 'resolvetype', id: 'alias-match' }); // this fixture was created to test the resolve API, but we are reusing to test the alias conflict error const NEW_NAMESPACE_AGNOSTIC_OBJ = Object.freeze({ type: 'globaltype', id: 'new-globaltype-id' }); export const TEST_CASES: Record = Object.freeze({ ...CASES, @@ -74,6 +75,7 @@ export const TEST_CASES: Record = Object.freeze({ INITIAL_NS_MULTI_NAMESPACE_ISOLATED_OBJ_OTHER_SPACE, INITIAL_NS_MULTI_NAMESPACE_OBJ_EACH_SPACE, INITIAL_NS_MULTI_NAMESPACE_OBJ_ALL_SPACES, + ALIAS_CONFLICT_OBJ, NEW_NAMESPACE_AGNOSTIC_OBJ, }); @@ -103,12 +105,20 @@ export function bulkCreateTestSuiteFactory(esArchiver: any, supertest: SuperTest for (let i = 0; i < savedObjects.length; i++) { const object = savedObjects[i]; const testCase = testCaseArray[i]; - if (testCase.failure === 409 && testCase.fail409Param === 'unresolvableConflict') { + if (testCase.failure === 409) { const { type, id } = testCase; - const error = SavedObjectsErrorHelpers.createConflictError(type, id); - const payload = { ...error.output.payload, metadata: { isNotOverwritable: true } }; expect(object.type).to.eql(type); expect(object.id).to.eql(id); + let metadata; + if (testCase.fail409Param === 'unresolvableConflict') { + metadata = { isNotOverwritable: true }; + } else if (testCase.fail409Param === 'aliasConflictSpace1') { + metadata = { spacesWithConflictingAliases: ['space_1'] }; + } else if (testCase.fail409Param === 'aliasConflictAllSpaces') { + metadata = { spacesWithConflictingAliases: ['space_1', 'space_x'] }; + } + const error = SavedObjectsErrorHelpers.createConflictError(type, id); + const payload = { ...error.output.payload, ...(metadata && { metadata }) }; expect(object.error).to.eql(payload); continue; } diff --git a/x-pack/test/saved_object_api_integration/common/suites/create.ts b/x-pack/test/saved_object_api_integration/common/suites/create.ts index 29562167afbce..dfad5e638a708 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/create.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/create.ts @@ -65,6 +65,7 @@ const INITIAL_NS_MULTI_NAMESPACE_OBJ_ALL_SPACES = Object.freeze({ expectedNamespaces: [ALL_SPACES_ID], // expected namespaces of resulting object initialNamespaces: [ALL_SPACES_ID], // args passed to the bulkCreate method }); +const ALIAS_CONFLICT_OBJ = Object.freeze({ type: 'resolvetype', id: 'alias-match' }); // this fixture was created to test the resolve API, but we are reusing to test the alias conflict error const NEW_NAMESPACE_AGNOSTIC_OBJ = Object.freeze({ type: 'globaltype', id: 'new-globaltype-id' }); export const TEST_CASES: Record = Object.freeze({ ...CASES, @@ -74,6 +75,7 @@ export const TEST_CASES: Record = Object.freeze({ INITIAL_NS_MULTI_NAMESPACE_ISOLATED_OBJ_OTHER_SPACE, INITIAL_NS_MULTI_NAMESPACE_OBJ_EACH_SPACE, INITIAL_NS_MULTI_NAMESPACE_OBJ_ALL_SPACES, + ALIAS_CONFLICT_OBJ, NEW_NAMESPACE_AGNOSTIC_OBJ, }); diff --git a/x-pack/test/saved_object_api_integration/common/suites/update.ts b/x-pack/test/saved_object_api_integration/common/suites/update.ts index 4a69c75806537..1fc2cef6e051a 100644 --- a/x-pack/test/saved_object_api_integration/common/suites/update.ts +++ b/x-pack/test/saved_object_api_integration/common/suites/update.ts @@ -9,31 +9,31 @@ import expect from '@kbn/expect'; import { SuperTest } from 'supertest'; import { SAVED_OBJECT_TEST_CASES as CASES } from '../lib/saved_object_test_cases'; import { SPACES } from '../lib/spaces'; -import { - createRequest, - expectResponses, - getUrlPrefix, - getTestTitle, -} from '../lib/saved_object_test_utils'; +import { expectResponses, getUrlPrefix, getTestTitle } from '../lib/saved_object_test_utils'; import { ExpectResponseBody, TestCase, TestDefinition, TestSuite } from '../lib/types'; export interface UpdateTestDefinition extends TestDefinition { - request: { type: string; id: string }; + request: { type: string; id: string; upsert?: boolean }; } export type UpdateTestSuite = TestSuite; export interface UpdateTestCase extends TestCase { - failure?: 403 | 404; + failure?: 403 | 404 | 409; + upsert?: boolean; } const NEW_ATTRIBUTE_KEY = 'title'; // all type mappings include this attribute, for simplicity's sake const NEW_ATTRIBUTE_VAL = `Updated attribute value ${Date.now()}`; +const ALIAS_CONFLICT_OBJ = Object.freeze({ type: 'resolvetype', id: 'alias-match' }); // this fixture was created to test the resolve API, but we are reusing to test the alias conflict error const DOES_NOT_EXIST = Object.freeze({ type: 'dashboard', id: 'does-not-exist' }); export const TEST_CASES: Record = Object.freeze({ ...CASES, + ALIAS_CONFLICT_OBJ, DOES_NOT_EXIST, }); +const createRequest = ({ type, id, upsert }: UpdateTestCase) => ({ type, id, upsert }); + export function updateTestSuiteFactory(esArchiver: any, supertest: SuperTest) { const expectSavedObjectForbidden = expectResponses.forbiddenTypes('update'); const expectResponseBody = @@ -89,8 +89,9 @@ export function updateTestSuiteFactory(esArchiver: any, supertest: SuperTest { - const { type, id } = test.request; - const requestBody = { attributes: { [NEW_ATTRIBUTE_KEY]: NEW_ATTRIBUTE_VAL } }; + const { type, id, upsert } = test.request; + const attributes = { [NEW_ATTRIBUTE_KEY]: NEW_ATTRIBUTE_VAL }; + const requestBody = { attributes, ...(upsert && { upsert: attributes }) }; await supertest .put(`${getUrlPrefix(spaceId)}/api/saved_objects/${type}/${id}`) .auth(user?.username, user?.password) diff --git a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/bulk_create.ts b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/bulk_create.ts index 550d4d529d2a4..ce10b5e609324 100644 --- a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/bulk_create.ts +++ b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/bulk_create.ts @@ -74,8 +74,21 @@ const createTestCases = (overwrite: boolean, spaceId: string) => { { ...CASES.NEW_SINGLE_NAMESPACE_OBJ, expectedNamespaces }, { ...CASES.NEW_MULTI_NAMESPACE_OBJ, expectedNamespaces }, CASES.NEW_NAMESPACE_AGNOSTIC_OBJ, + // We test the alias conflict preflight check error case twice; once by checking the alias with "find" and once by using "bulk-get". + { + ...CASES.ALIAS_CONFLICT_OBJ, + ...(spaceId === SPACE_1_ID ? { ...fail409(), fail409Param: 'aliasConflictSpace1' } : {}), // first try fails if this is space_1 because an alias exists in space_1 + expectedNamespaces, + }, ]; const crossNamespace = [ + { + ...CASES.ALIAS_CONFLICT_OBJ, + initialNamespaces: ['*'], + ...fail409(), + fail409Param: 'aliasConflictAllSpaces', // second try fails because an alias exists in space_x and space_1 (but not space_y because that alias is disabled) + // note that if an object was successfully created with this type/ID in the first try, that won't change this outcome, because an alias conflict supersedes all other types of conflicts + }, { ...CASES.INITIAL_NS_SINGLE_NAMESPACE_OBJ_OTHER_SPACE, initialNamespaces: ['x', 'y'], diff --git a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/create.ts b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/create.ts index 8215c991a9287..88cfa496f0130 100644 --- a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/create.ts +++ b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/create.ts @@ -61,8 +61,21 @@ const createTestCases = (overwrite: boolean, spaceId: string) => { { ...CASES.NEW_SINGLE_NAMESPACE_OBJ, expectedNamespaces }, { ...CASES.NEW_MULTI_NAMESPACE_OBJ, expectedNamespaces }, CASES.NEW_NAMESPACE_AGNOSTIC_OBJ, + // We test the alias conflict preflight check error case twice; once by checking the alias with "find" and once by using "bulk-get". + { + ...CASES.ALIAS_CONFLICT_OBJ, + ...(spaceId === SPACE_1_ID ? { ...fail409(), fail409Param: 'aliasConflictSpace1' } : {}), // first try fails if this is space_1 because an alias exists in space_1 + expectedNamespaces, + }, ]; const crossNamespace = [ + { + ...CASES.ALIAS_CONFLICT_OBJ, + initialNamespaces: ['*'], + ...fail409(), + fail409Param: 'aliasConflictAllSpaces', // second try fails because an alias exists in space_x and space_1 (but not space_y because that alias is disabled) + // note that if an object was successfully created with this type/ID in the first try, that won't change this outcome, because an alias conflict supersedes all other types of conflicts + }, { ...CASES.INITIAL_NS_SINGLE_NAMESPACE_OBJ_OTHER_SPACE, initialNamespaces: ['x', 'y'], diff --git a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/update.ts b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/update.ts index 44296597d52ea..89aec5152205e 100644 --- a/x-pack/test/saved_object_api_integration/security_and_spaces/apis/update.ts +++ b/x-pack/test/saved_object_api_integration/security_and_spaces/apis/update.ts @@ -20,7 +20,7 @@ const { SPACE_1: { spaceId: SPACE_1_ID }, SPACE_2: { spaceId: SPACE_2_ID }, } = SPACES; -const { fail404 } = testCaseFailures; +const { fail404, fail409 } = testCaseFailures; const createTestCases = (spaceId: string) => { // for each permitted (non-403) outcome, if failure !== undefined then we expect @@ -42,6 +42,8 @@ const createTestCases = (spaceId: string) => { }, { ...CASES.MULTI_NAMESPACE_ISOLATED_ONLY_SPACE_1, ...fail404(spaceId !== SPACE_1_ID) }, CASES.NAMESPACE_AGNOSTIC, + { ...CASES.ALIAS_CONFLICT_OBJ, upsert: false, ...fail404() }, + { ...CASES.ALIAS_CONFLICT_OBJ, upsert: true, ...fail409(spaceId === SPACE_1_ID) }, { ...CASES.DOES_NOT_EXIST, ...fail404() }, ]; const hiddenType = [{ ...CASES.HIDDEN, ...fail404() }]; diff --git a/x-pack/test/saved_object_api_integration/spaces_only/apis/bulk_create.ts b/x-pack/test/saved_object_api_integration/spaces_only/apis/bulk_create.ts index c448d73ce7bf8..c2fcbbf570830 100644 --- a/x-pack/test/saved_object_api_integration/spaces_only/apis/bulk_create.ts +++ b/x-pack/test/saved_object_api_integration/spaces_only/apis/bulk_create.ts @@ -84,6 +84,18 @@ const createTestCases = (overwrite: boolean, spaceId: string) => { CASES.INITIAL_NS_MULTI_NAMESPACE_ISOLATED_OBJ_OTHER_SPACE, // second try creates it in a single other space, which is valid CASES.INITIAL_NS_MULTI_NAMESPACE_OBJ_EACH_SPACE, CASES.INITIAL_NS_MULTI_NAMESPACE_OBJ_ALL_SPACES, + // We test the alias conflict preflight check error case twice; once by checking the alias with "find" and once by using "bulk-get". + { + ...CASES.ALIAS_CONFLICT_OBJ, + initialNamespaces: ['*'], + ...fail409(), + fail409Param: 'aliasConflictAllSpaces', // first try fails because an alias exists in space_x and space_1 (but not space_y because that alias is disabled) + }, + { + ...CASES.ALIAS_CONFLICT_OBJ, + ...(spaceId === SPACE_1_ID ? { ...fail409(), fail409Param: 'aliasConflictSpace1' } : {}), // second try fails if this is space_1 because an alias exists in space_1 + expectedNamespaces, + }, ]; }; diff --git a/x-pack/test/saved_object_api_integration/spaces_only/apis/create.ts b/x-pack/test/saved_object_api_integration/spaces_only/apis/create.ts index 7c8726896c18a..a46baeb261c8a 100644 --- a/x-pack/test/saved_object_api_integration/spaces_only/apis/create.ts +++ b/x-pack/test/saved_object_api_integration/spaces_only/apis/create.ts @@ -71,6 +71,9 @@ const createTestCases = (overwrite: boolean, spaceId: string) => { CASES.INITIAL_NS_MULTI_NAMESPACE_ISOLATED_OBJ_OTHER_SPACE, // second try creates it in a single other space, which is valid CASES.INITIAL_NS_MULTI_NAMESPACE_OBJ_EACH_SPACE, CASES.INITIAL_NS_MULTI_NAMESPACE_OBJ_ALL_SPACES, + // We test the alias conflict preflight check error case twice; once by checking the alias with "find" and once by using "bulk-get". + { ...CASES.ALIAS_CONFLICT_OBJ, initialNamespaces: ['*'], ...fail409() }, // first try fails because an alias exists in space_x and space_1 (but not space_y because that alias is disabled) + { ...CASES.ALIAS_CONFLICT_OBJ, ...fail409(spaceId === SPACE_1_ID), expectedNamespaces }, // second try fails if this is space_1 because an alias exists in space_1 ]; }; diff --git a/x-pack/test/saved_object_api_integration/spaces_only/apis/update.ts b/x-pack/test/saved_object_api_integration/spaces_only/apis/update.ts index bf5d635a11d8a..02a89ef8aae99 100644 --- a/x-pack/test/saved_object_api_integration/spaces_only/apis/update.ts +++ b/x-pack/test/saved_object_api_integration/spaces_only/apis/update.ts @@ -15,7 +15,7 @@ const { SPACE_1: { spaceId: SPACE_1_ID }, SPACE_2: { spaceId: SPACE_2_ID }, } = SPACES; -const { fail404 } = testCaseFailures; +const { fail404, fail409 } = testCaseFailures; const createTestCases = (spaceId: string) => [ // for each outcome, if failure !== undefined then we expect to receive @@ -37,6 +37,8 @@ const createTestCases = (spaceId: string) => [ { ...CASES.MULTI_NAMESPACE_ISOLATED_ONLY_SPACE_1, ...fail404(spaceId !== SPACE_1_ID) }, CASES.NAMESPACE_AGNOSTIC, { ...CASES.HIDDEN, ...fail404() }, + { ...CASES.ALIAS_CONFLICT_OBJ, upsert: false, ...fail404() }, + { ...CASES.ALIAS_CONFLICT_OBJ, upsert: true, ...fail409(spaceId === SPACE_1_ID) }, { ...CASES.DOES_NOT_EXIST, ...fail404() }, ]; From 4a988dc5e3875f214564ab03c7f2eb2725cee87e Mon Sep 17 00:00:00 2001 From: Thomas Neirynck Date: Tue, 26 Oct 2021 12:16:29 -0400 Subject: [PATCH 47/58] [Maps] Remove proxyElasticMapsServiceInMaps (#116184) Removes the map.proxyElasticMapsServiceInMaps yml setting. --- docs/setup/settings.asciidoc | 5 - .../resources/base/bin/kibana-docker | 2 - src/plugins/maps_ems/config.ts | 8 +- src/plugins/maps_ems/server/index.ts | 1 - x-pack/plugins/maps/common/constants.ts | 18 - .../plugins/maps/common/ems_settings.test.ts | 1 - x-pack/plugins/maps/common/ems_settings.ts | 5 - x-pack/plugins/maps/public/util.test.js | 16 - x-pack/plugins/maps/public/util.ts | 36 +- x-pack/plugins/maps/server/index.ts | 34 -- x-pack/plugins/maps/server/routes.js | 491 +----------------- .../translations/translations/ja-JP.json | 3 - .../translations/translations/zh-CN.json | 3 - .../test/api_integration/apis/maps/index.js | 1 - .../api_integration/apis/maps/proxy_api.js | 29 -- x-pack/test/api_integration/config.ts | 1 - 16 files changed, 6 insertions(+), 648 deletions(-) delete mode 100644 x-pack/test/api_integration/apis/maps/proxy_api.js diff --git a/docs/setup/settings.asciidoc b/docs/setup/settings.asciidoc index 6ff5556c331a2..9ccfeb6894713 100644 --- a/docs/setup/settings.asciidoc +++ b/docs/setup/settings.asciidoc @@ -350,11 +350,6 @@ When `includeElasticMapsService` is turned off, only tile layer configured by << | `map.emsUrl:` | Specifies the URL of a self hosted <> -| `map.proxyElasticMapsServiceInMaps:` - | deprecated:[7.14.0,"In 8.0 and later, this setting will no longer be supported."] - Set to `true` to proxy all <> Elastic Maps Service -requests through the {kib} server. *Default: `false`* - | [[tilemap-settings]] `map.tilemap.options.attribution:` {ess-icon} | The map attribution string. *Default: `"© [Elastic Maps Service](https://www.elastic.co/elastic-maps-service)"`* diff --git a/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker b/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker index ad66e1a16e04c..42cf433046e3f 100755 --- a/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker +++ b/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker @@ -85,8 +85,6 @@ kibana_vars=( logging.root.appenders logging.root.level map.includeElasticMapsService - map.proxyElasticMapsServiceInMaps - map.regionmap map.tilemap.options.attribution map.tilemap.options.maxZoom map.tilemap.options.minZoom diff --git a/src/plugins/maps_ems/config.ts b/src/plugins/maps_ems/config.ts index 710cb52f32a09..d64156a0395b1 100644 --- a/src/plugins/maps_ems/config.ts +++ b/src/plugins/maps_ems/config.ts @@ -39,13 +39,7 @@ export const tilemapConfigSchema = schema.object({ export const emsConfigSchema = schema.object({ tilemap: tilemapConfigSchema, includeElasticMapsService: schema.boolean({ defaultValue: true }), - proxyElasticMapsServiceInMaps: schema.boolean({ defaultValue: false }), - emsUrl: schema.conditional( - schema.siblingRef('proxyElasticMapsServiceInMaps'), - true, - schema.never(), - schema.string({ defaultValue: '' }) - ), + emsUrl: schema.string({ defaultValue: '' }), emsFileApiUrl: schema.string({ defaultValue: DEFAULT_EMS_FILE_API_URL }), emsTileApiUrl: schema.string({ defaultValue: DEFAULT_EMS_TILE_API_URL }), emsLandingPageUrl: schema.string({ defaultValue: DEFAULT_EMS_LANDING_PAGE_URL }), diff --git a/src/plugins/maps_ems/server/index.ts b/src/plugins/maps_ems/server/index.ts index 7422dbcfcdec9..1fdafd465da12 100644 --- a/src/plugins/maps_ems/server/index.ts +++ b/src/plugins/maps_ems/server/index.ts @@ -18,7 +18,6 @@ export const config: PluginConfigDescriptor = { exposeToBrowser: { tilemap: true, includeElasticMapsService: true, - proxyElasticMapsServiceInMaps: true, emsUrl: true, emsFileApiUrl: true, emsTileApiUrl: true, diff --git a/x-pack/plugins/maps/common/constants.ts b/x-pack/plugins/maps/common/constants.ts index 42c5b70514000..86d1a38b4939f 100644 --- a/x-pack/plugins/maps/common/constants.ts +++ b/x-pack/plugins/maps/common/constants.ts @@ -9,22 +9,6 @@ import { i18n } from '@kbn/i18n'; import { FeatureCollection } from 'geojson'; export const EMS_APP_NAME = 'kibana'; - -export const EMS_FILES_CATALOGUE_PATH = 'ems/files'; -export const EMS_FILES_API_PATH = 'ems/files'; -export const EMS_FILES_DEFAULT_JSON_PATH = 'file'; -export const EMS_GLYPHS_PATH = 'fonts'; -export const EMS_SPRITES_PATH = 'sprites'; - -export const EMS_TILES_CATALOGUE_PATH = 'ems/tiles'; -export const EMS_TILES_API_PATH = 'ems/tiles'; -export const EMS_TILES_RASTER_STYLE_PATH = 'raster/style'; -export const EMS_TILES_RASTER_TILE_PATH = 'raster/tile'; - -export const EMS_TILES_VECTOR_STYLE_PATH = 'vector/style'; -export const EMS_TILES_VECTOR_SOURCE_PATH = 'vector/source'; -export const EMS_TILES_VECTOR_TILE_PATH = 'vector/tile'; - export const MAP_SAVED_OBJECT_TYPE = 'map'; export const APP_ID = 'maps'; export const APP_ICON = 'gisApp'; @@ -306,5 +290,3 @@ export const MAPS_NEW_VECTOR_LAYER_META_CREATED_BY = 'maps-new-vector-layer'; export const MAX_DRAWING_SIZE_BYTES = 10485760; // 10MB export const emsWorldLayerId = 'world_countries'; -export const emsRegionLayerId = 'administrative_regions_lvl2'; -export const emsUsaZipLayerId = 'usa_zip_codes'; diff --git a/x-pack/plugins/maps/common/ems_settings.test.ts b/x-pack/plugins/maps/common/ems_settings.test.ts index c299d535db193..82d7823250e4c 100644 --- a/x-pack/plugins/maps/common/ems_settings.test.ts +++ b/x-pack/plugins/maps/common/ems_settings.test.ts @@ -18,7 +18,6 @@ const IS_ENTERPRISE_PLUS = () => true; describe('EMSSettings', () => { const mockConfig: IEMSConfig = { includeElasticMapsService: true, - proxyElasticMapsServiceInMaps: false, emsUrl: '', emsFileApiUrl: DEFAULT_EMS_FILE_API_URL, emsTileApiUrl: DEFAULT_EMS_TILE_API_URL, diff --git a/x-pack/plugins/maps/common/ems_settings.ts b/x-pack/plugins/maps/common/ems_settings.ts index 166fc6fbdfc4c..f85351b2fdab2 100644 --- a/x-pack/plugins/maps/common/ems_settings.ts +++ b/x-pack/plugins/maps/common/ems_settings.ts @@ -15,7 +15,6 @@ import { export interface IEMSConfig { emsUrl?: string; includeElasticMapsService?: boolean; - proxyElasticMapsServiceInMaps?: boolean; emsFileApiUrl?: string; emsTileApiUrl?: string; emsLandingPageUrl?: string; @@ -63,10 +62,6 @@ export class EMSSettings { } } - isProxyElasticMapsServiceInMaps(): boolean { - return !!this._config.proxyElasticMapsServiceInMaps; - } - getEMSTileApiUrl(): string { if (this._config.emsTileApiUrl !== DEFAULT_EMS_TILE_API_URL || !this.isEMSUrlSet()) { return this._config.emsTileApiUrl!; diff --git a/x-pack/plugins/maps/public/util.test.js b/x-pack/plugins/maps/public/util.test.js index 47c3d77180077..c8c93a6a93aef 100644 --- a/x-pack/plugins/maps/public/util.test.js +++ b/x-pack/plugins/maps/public/util.test.js @@ -49,27 +49,11 @@ describe('getGlyphUrl', () => { }); }); - describe('EMS proxy enabled', () => { - beforeAll(() => { - require('./kibana_services').getEMSSettings = () => { - return { - ...MOCK_EMS_SETTINGS, - isProxyElasticMapsServiceInMaps: () => true, - }; - }; - }); - - test('should return proxied EMS fonts URL', async () => { - expect(getGlyphUrl()).toBe('http://localhost/api/maps/ems/tiles/fonts/{fontstack}/{range}'); - }); - }); - describe('EMS proxy disabled', () => { beforeAll(() => { require('./kibana_services').getEMSSettings = () => { return { ...MOCK_EMS_SETTINGS, - isProxyElasticMapsServiceInMaps: () => false, }; }; }); diff --git a/x-pack/plugins/maps/public/util.ts b/x-pack/plugins/maps/public/util.ts index f92a60ffedfdc..a6bc1412691ab 100644 --- a/x-pack/plugins/maps/public/util.ts +++ b/x-pack/plugins/maps/public/util.ts @@ -7,15 +7,7 @@ import { i18n } from '@kbn/i18n'; import { EMSClient, FileLayer, TMSService } from '@elastic/ems-client'; -import _ from 'lodash'; -import { - GIS_API_PATH, - EMS_FILES_CATALOGUE_PATH, - EMS_TILES_CATALOGUE_PATH, - EMS_GLYPHS_PATH, - EMS_APP_NAME, - FONTS_API_PATH, -} from '../common/constants'; +import { EMS_APP_NAME, FONTS_API_PATH } from '../common/constants'; import { getHttp, getTilemap, getKibanaVersion, getEMSSettings } from './kibana_services'; import { getLicenseId } from './licensed_features'; @@ -39,28 +31,14 @@ export async function getEmsTmsServices(): Promise { return getEMSClient().getTMSServices(); } -function relativeToAbsolute(url: string): string { - const a = document.createElement('a'); - a.setAttribute('href', url); - return a.href; -} - let emsClient: EMSClient | null = null; let latestLicenseId: string | undefined; export function getEMSClient(): EMSClient { if (!emsClient) { const emsSettings = getEMSSettings(); const proxyPath = ''; - const tileApiUrl = emsSettings!.isProxyElasticMapsServiceInMaps() - ? relativeToAbsolute( - getHttp().basePath.prepend(`/${GIS_API_PATH}/${EMS_TILES_CATALOGUE_PATH}`) - ) - : emsSettings!.getEMSTileApiUrl(); - const fileApiUrl = emsSettings!.isProxyElasticMapsServiceInMaps() - ? relativeToAbsolute( - getHttp().basePath.prepend(`/${GIS_API_PATH}/${EMS_FILES_CATALOGUE_PATH}`) - ) - : emsSettings!.getEMSFileApiUrl(); + const tileApiUrl = emsSettings!.getEMSTileApiUrl(); + const fileApiUrl = emsSettings!.getEMSFileApiUrl(); emsClient = new EMSClient({ language: i18n.getLocale(), @@ -89,13 +67,7 @@ export function getGlyphUrl(): string { return getHttp().basePath.prepend(`/${FONTS_API_PATH}/{fontstack}/{range}`); } - return emsSettings!.isProxyElasticMapsServiceInMaps() - ? relativeToAbsolute( - getHttp().basePath.prepend( - `/${GIS_API_PATH}/${EMS_TILES_CATALOGUE_PATH}/${EMS_GLYPHS_PATH}` - ) - ) + `/{fontstack}/{range}` - : emsSettings!.getEMSFontLibraryUrl(); + return emsSettings!.getEMSFontLibraryUrl(); } export function isRetina(): boolean { diff --git a/x-pack/plugins/maps/server/index.ts b/x-pack/plugins/maps/server/index.ts index e00951610bbed..55eaadcd28063 100644 --- a/x-pack/plugins/maps/server/index.ts +++ b/x-pack/plugins/maps/server/index.ts @@ -5,9 +5,6 @@ * 2.0. */ -import _ from 'lodash'; -import { i18n } from '@kbn/i18n'; -import { AddConfigDeprecation } from '@kbn/config'; import { PluginInitializerContext } from 'src/core/server'; import { PluginConfigDescriptor } from 'kibana/server'; import { MapsPlugin } from './plugin'; @@ -21,37 +18,6 @@ export const config: PluginConfigDescriptor = { preserveDrawingBuffer: true, }, schema: configSchema, - deprecations: () => [ - ( - completeConfig: Record, - rootPath: string, - addDeprecation: AddConfigDeprecation - ) => { - if (_.get(completeConfig, 'map.proxyElasticMapsServiceInMaps') === undefined) { - return completeConfig; - } - addDeprecation({ - configPath: 'map.proxyElasticMapsServiceInMaps', - documentationUrl: - 'https://www.elastic.co/guide/en/kibana/current/maps-connect-to-ems.html#elastic-maps-server', - message: i18n.translate('xpack.maps.deprecation.proxyEMS.message', { - defaultMessage: 'map.proxyElasticMapsServiceInMaps is deprecated and is no longer used', - }), - correctiveActions: { - manualSteps: [ - i18n.translate('xpack.maps.deprecation.proxyEMS.step1', { - defaultMessage: - 'Remove "map.proxyElasticMapsServiceInMaps" in the Kibana config file, CLI flag, or environment variable (in Docker only).', - }), - i18n.translate('xpack.maps.deprecation.proxyEMS.step2', { - defaultMessage: 'Host Elastic Maps Service locally.', - }), - ], - }, - }); - return completeConfig; - }, - ], }; export const plugin = (initializerContext: PluginInitializerContext) => diff --git a/x-pack/plugins/maps/server/routes.js b/x-pack/plugins/maps/server/routes.js index 7587ec54218e5..da3385de4db8e 100644 --- a/x-pack/plugins/maps/server/routes.js +++ b/x-pack/plugins/maps/server/routes.js @@ -5,27 +5,7 @@ * 2.0. */ -import { - EMS_APP_NAME, - EMS_FILES_API_PATH, - EMS_FILES_CATALOGUE_PATH, - EMS_FILES_DEFAULT_JSON_PATH, - EMS_TILES_API_PATH, - EMS_TILES_CATALOGUE_PATH, - EMS_GLYPHS_PATH, - EMS_TILES_RASTER_STYLE_PATH, - EMS_TILES_RASTER_TILE_PATH, - EMS_TILES_VECTOR_STYLE_PATH, - EMS_TILES_VECTOR_SOURCE_PATH, - EMS_TILES_VECTOR_TILE_PATH, - EMS_SPRITES_PATH, - INDEX_SETTINGS_API_PATH, - FONTS_API_PATH, - API_ROOT_PATH, -} from '../common/constants'; -import { EMSClient } from '@elastic/ems-client'; -import fetch from 'node-fetch'; -import { i18n } from '@kbn/i18n'; +import { INDEX_SETTINGS_API_PATH, FONTS_API_PATH } from '../common/constants'; import { getIndexPatternSettings } from './lib/get_index_pattern_settings'; import { schema } from '@kbn/config-schema'; import fs from 'fs'; @@ -33,449 +13,10 @@ import path from 'path'; import { initMVTRoutes } from './mvt/mvt_routes'; import { initIndexingRoutes } from './data_indexing/indexing_routes'; -const EMPTY_EMS_CLIENT = { - async getFileLayers() { - return []; - }, - async getTMSServices() { - return []; - }, - async getDefaultFileManifest() { - return null; - }, - async getDefaultTMSManifest() { - return null; - }, - addQueryParams() {}, -}; - export async function initRoutes(core, getLicenseId, emsSettings, kbnVersion, logger) { - let emsClient; - let lastLicenseId; const router = core.http.createRouter(); const [, { data: dataPlugin }] = await core.getStartServices(); - function getEMSClient() { - const currentLicenseId = getLicenseId(); - if (emsClient && emsSettings.isEMSEnabled() && lastLicenseId === currentLicenseId) { - return emsClient; - } - - lastLicenseId = currentLicenseId; - if (emsSettings.isIncludeElasticMapsService()) { - emsClient = new EMSClient({ - language: i18n.getLocale(), - appVersion: kbnVersion, - appName: EMS_APP_NAME, - fileApiUrl: emsSettings.getEMSFileApiUrl(), - tileApiUrl: emsSettings.getEMSTileApiUrl(), - landingPageUrl: emsSettings.getEMSLandingPageUrl(), - fetchFunction: fetch, - }); - emsClient.addQueryParams({ - license: currentLicenseId, - is_kibana_proxy: '1', // identifies this is proxied request from kibana - }); - return emsClient; - } else { - return EMPTY_EMS_CLIENT; - } - } - - router.get( - { - path: `${API_ROOT_PATH}/${EMS_FILES_API_PATH}/${EMS_FILES_DEFAULT_JSON_PATH}`, - validate: { - query: schema.object({ - id: schema.maybe(schema.string()), - elastic_tile_service_tos: schema.maybe(schema.string()), - my_app_name: schema.maybe(schema.string()), - my_app_version: schema.maybe(schema.string()), - license: schema.maybe(schema.string()), - }), - }, - }, - async (context, request, { ok, badRequest }) => { - if (!checkEMSProxyEnabled()) { - return badRequest('map.proxyElasticMapsServiceInMaps disabled'); - } - - if (!request.query.id) { - logger.warn('Must supply id parameters to retrieve EMS file'); - return null; - } - - const fileLayers = await getEMSClient().getFileLayers(); - const layer = fileLayers.find((layer) => layer.getId() === request.query.id); - if (!layer) { - return null; - } - - try { - const file = await fetch(layer.getDefaultFormatUrl()); - const fileJson = await file.json(); - return ok({ body: fileJson }); - } catch (e) { - logger.warn(`Cannot connect to EMS for file, error: ${e.message}`); - return badRequest(`Cannot connect to EMS`); - } - } - ); - - router.get( - { - path: `${API_ROOT_PATH}/${EMS_TILES_API_PATH}/${EMS_TILES_RASTER_TILE_PATH}`, - validate: false, - }, - async (context, request, response) => { - if (!checkEMSProxyEnabled()) { - return response.badRequest('map.proxyElasticMapsServiceInMaps disabled'); - } - - if ( - !request.query.id || - typeof parseInt(request.query.x, 10) !== 'number' || - typeof parseInt(request.query.y, 10) !== 'number' || - typeof parseInt(request.query.z, 10) !== 'number' - ) { - logger.warn('Must supply id/x/y/z parameters to retrieve EMS raster tile'); - return null; - } - - const tmsServices = await getEMSClient().getTMSServices(); - const tmsService = tmsServices.find((layer) => layer.getId() === request.query.id); - if (!tmsService) { - return null; - } - - const urlTemplate = await tmsService.getUrlTemplate(); - const url = urlTemplate - .replace('{x}', request.query.x) - .replace('{y}', request.query.y) - .replace('{z}', request.query.z); - - return await proxyResource({ url, contentType: 'image/png' }, response); - } - ); - - router.get( - { - path: `${API_ROOT_PATH}/${EMS_FILES_CATALOGUE_PATH}/{emsVersion}/manifest`, - validate: false, - }, - async (context, request, { ok, badRequest }) => { - if (!checkEMSProxyEnabled()) { - return badRequest('map.proxyElasticMapsServiceInMaps disabled'); - } - - const file = await getEMSClient().getDefaultFileManifest(); //need raw manifest - const fileLayers = await getEMSClient().getFileLayers(); - - const layers = file.layers.map((layerJson) => { - const newLayerJson = { ...layerJson }; - const id = encodeURIComponent(layerJson.layer_id); - - const fileLayer = fileLayers.find((fileLayer) => fileLayer.getId() === layerJson.layer_id); - const defaultFormat = layerJson.formats.find( - (format) => format.type === fileLayer.getDefaultFormatType() - ); - - const newUrl = `${EMS_FILES_DEFAULT_JSON_PATH}?id=${id}`; - - //Only proxy default-format. Others are unused in Maps-app - newLayerJson.formats = [ - { - ...defaultFormat, - url: newUrl, - }, - ]; - return newLayerJson; - }); - //rewrite - return ok({ - body: { - layers, - }, - }); - } - ); - - router.get( - { - path: `${API_ROOT_PATH}/${EMS_TILES_CATALOGUE_PATH}/{emsVersion}/manifest`, - validate: false, - }, - async (context, request, { ok, badRequest }) => { - if (!checkEMSProxyEnabled()) { - return badRequest('map.proxyElasticMapsServiceInMaps disabled'); - } - - const tilesManifest = await getEMSClient().getDefaultTMSManifest(); - const newServices = tilesManifest.services.map((service) => { - const newService = { - ...service, - }; - - newService.formats = []; - const rasterFormats = service.formats.filter((format) => format.format === 'raster'); - if (rasterFormats.length) { - const newUrl = `${EMS_TILES_RASTER_STYLE_PATH}?id=${service.id}`; - newService.formats.push({ - ...rasterFormats[0], - url: newUrl, - }); - } - const vectorFormats = service.formats.filter((format) => format.format === 'vector'); - if (vectorFormats.length) { - const newUrl = `${EMS_TILES_VECTOR_STYLE_PATH}?id=${service.id}`; - newService.formats.push({ - ...vectorFormats[0], - url: newUrl, - }); - } - return newService; - }); - - return ok({ - body: { - services: newServices, - }, - }); - } - ); - - router.get( - { - path: `${API_ROOT_PATH}/${EMS_TILES_API_PATH}/${EMS_TILES_RASTER_STYLE_PATH}`, - validate: { - query: schema.object({ - id: schema.maybe(schema.string()), - }), - }, - }, - async (context, request, { ok, badRequest }) => { - if (!checkEMSProxyEnabled()) { - return badRequest('map.proxyElasticMapsServiceInMaps disabled'); - } - - if (!request.query.id) { - logger.warn('Must supply id parameter to retrieve EMS raster style'); - return null; - } - - const tmsServices = await getEMSClient().getTMSServices(); - const tmsService = tmsServices.find((layer) => layer.getId() === request.query.id); - if (!tmsService) { - return null; - } - const style = await tmsService.getDefaultRasterStyle(); - - const newUrl = `${EMS_TILES_RASTER_TILE_PATH}?id=${request.query.id}&x={x}&y={y}&z={z}`; - return ok({ - body: { - ...style, - tiles: [newUrl], - }, - }); - } - ); - - router.get( - { - path: `${API_ROOT_PATH}/${EMS_TILES_API_PATH}/${EMS_TILES_VECTOR_STYLE_PATH}`, - validate: { - query: schema.object({ - id: schema.string(), - elastic_tile_service_tos: schema.maybe(schema.string()), - my_app_name: schema.maybe(schema.string()), - my_app_version: schema.maybe(schema.string()), - license: schema.maybe(schema.string()), - }), - }, - }, - async (context, request, { ok, badRequest }) => { - if (!checkEMSProxyEnabled()) { - return badRequest('map.proxyElasticMapsServiceInMaps disabled'); - } - - const tmsServices = await getEMSClient().getTMSServices(); - const tmsService = tmsServices.find((layer) => layer.getId() === request.query.id); - if (!tmsService) { - return null; - } - - const vectorStyle = await tmsService.getVectorStyleSheetRaw(); - const newSources = {}; - for (const sourceId in vectorStyle.sources) { - if (vectorStyle.sources.hasOwnProperty(sourceId)) { - newSources[sourceId] = { - type: 'vector', - url: `${EMS_TILES_VECTOR_SOURCE_PATH}?id=${request.query.id}&sourceId=${sourceId}`, - }; - } - } - - const spritePath = `${EMS_SPRITES_PATH}/${request.query.id}/sprite`; - - return ok({ - body: { - ...vectorStyle, - glyphs: `${EMS_GLYPHS_PATH}/{fontstack}/{range}`, - sprite: spritePath, - sources: newSources, - }, - }); - } - ); - - router.get( - { - path: `${API_ROOT_PATH}/${EMS_TILES_API_PATH}/${EMS_TILES_VECTOR_SOURCE_PATH}`, - validate: { - query: schema.object({ - id: schema.string(), - sourceId: schema.maybe(schema.string()), - elastic_tile_service_tos: schema.maybe(schema.string()), - my_app_name: schema.maybe(schema.string()), - my_app_version: schema.maybe(schema.string()), - license: schema.maybe(schema.string()), - }), - }, - }, - async (context, request, { ok, badRequest }) => { - if (!checkEMSProxyEnabled()) { - return badRequest('map.proxyElasticMapsServiceInMaps disabled'); - } - - const tmsServices = await getEMSClient().getTMSServices(); - const tmsService = tmsServices.find((layer) => layer.getId() === request.query.id); - if (!tmsService) { - return null; - } - - const vectorStyle = await tmsService.getVectorStyleSheet(); - const sourceManifest = vectorStyle.sources[request.query.sourceId]; - - const newUrl = `${EMS_TILES_VECTOR_TILE_PATH}?id=${request.query.id}&sourceId=${request.query.sourceId}&x={x}&y={y}&z={z}`; - return ok({ - body: { - ...sourceManifest, - tiles: [newUrl], - }, - }); - } - ); - - router.get( - { - path: `${API_ROOT_PATH}/${EMS_TILES_API_PATH}/${EMS_TILES_VECTOR_TILE_PATH}`, - validate: { - query: schema.object({ - id: schema.string(), - sourceId: schema.string(), - x: schema.number(), - y: schema.number(), - z: schema.number(), - elastic_tile_service_tos: schema.maybe(schema.string()), - my_app_name: schema.maybe(schema.string()), - my_app_version: schema.maybe(schema.string()), - license: schema.maybe(schema.string()), - }), - }, - }, - async (context, request, response) => { - if (!checkEMSProxyEnabled()) { - return response.badRequest('map.proxyElasticMapsServiceInMaps disabled'); - } - - const tmsServices = await getEMSClient().getTMSServices(); - const tmsService = tmsServices.find((layer) => layer.getId() === request.query.id); - if (!tmsService) { - return null; - } - - const urlTemplate = await tmsService.getUrlTemplateForVector(request.query.sourceId); - const url = urlTemplate - .replace('{x}', request.query.x) - .replace('{y}', request.query.y) - .replace('{z}', request.query.z); - - return await proxyResource({ url }, response); - } - ); - - router.get( - { - path: `${API_ROOT_PATH}/${EMS_TILES_API_PATH}/${EMS_GLYPHS_PATH}/{fontstack}/{range}`, - validate: { - params: schema.object({ - fontstack: schema.string(), - range: schema.string(), - }), - }, - }, - async (context, request, response) => { - if (!checkEMSProxyEnabled()) { - return response.badRequest('map.proxyElasticMapsServiceInMaps disabled'); - } - const url = emsSettings - .getEMSFontLibraryUrl() - .replace('{fontstack}', request.params.fontstack) - .replace('{range}', request.params.range); - - return await proxyResource({ url }, response); - } - ); - - router.get( - { - path: `${API_ROOT_PATH}/${EMS_TILES_API_PATH}/${EMS_SPRITES_PATH}/{id}/sprite{scaling?}.{extension}`, - validate: { - query: schema.object({ - elastic_tile_service_tos: schema.maybe(schema.string()), - my_app_name: schema.maybe(schema.string()), - my_app_version: schema.maybe(schema.string()), - license: schema.maybe(schema.string()), - }), - params: schema.object({ - id: schema.string(), - scaling: schema.maybe(schema.string()), - extension: schema.string(), - }), - }, - }, - async (context, request, response) => { - if (!checkEMSProxyEnabled()) { - return response.badRequest('map.proxyElasticMapsServiceInMaps disabled'); - } - - const tmsServices = await getEMSClient().getTMSServices(); - const tmsService = tmsServices.find((layer) => layer.getId() === request.params.id); - if (!tmsService) { - return null; - } - - let proxyPathUrl; - const isRetina = request.params.scaling === '@2x'; - if (request.params.extension === 'json') { - proxyPathUrl = await tmsService.getSpriteSheetJsonPath(isRetina); - } else if (request.params.extension === 'png') { - proxyPathUrl = await tmsService.getSpriteSheetPngPath(isRetina); - } else { - logger.warn(`Must have png or json extension for spritesheet`); - return null; - } - - return await proxyResource( - { - url: proxyPathUrl, - contentType: request.params.extension === 'png' ? 'image/png' : '', - }, - response - ); - } - ); - router.get( { path: `/${FONTS_API_PATH}/{fontstack}/{range}`, @@ -547,36 +88,6 @@ export async function initRoutes(core, getLicenseId, emsSettings, kbnVersion, lo } ); - function checkEMSProxyEnabled() { - const proxyEMSInMaps = emsSettings.isProxyElasticMapsServiceInMaps(); - if (!proxyEMSInMaps) { - logger.warn( - `Cannot load content from EMS when map.proxyElasticMapsServiceInMaps is turned off` - ); - } - return proxyEMSInMaps; - } - - async function proxyResource({ url, contentType }, response) { - try { - const resource = await fetch(url); - const arrayBuffer = await resource.arrayBuffer(); - const buffer = Buffer.from(arrayBuffer); - - return response.ok({ - body: buffer, - headers: { - 'content-disposition': 'inline', - 'content-length': buffer.length, - ...(contentType ? { 'Content-type': contentType } : {}), - }, - }); - } catch (e) { - logger.warn(`Cannot connect to EMS for resource, error: ${e.message}`); - return response.badRequest(`Cannot connect to EMS`); - } - } - initMVTRoutes({ router, logger }); initIndexingRoutes({ router, logger, dataPlugin }); } diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 157deffe6ff7b..0ca4d2ae81f13 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -14537,9 +14537,6 @@ "xpack.maps.common.esSpatialRelation.intersectsLabel": "intersects", "xpack.maps.common.esSpatialRelation.withinLabel": "within", "xpack.maps.deleteBtnTitle": "削除", - "xpack.maps.deprecation.proxyEMS.message": "map.proxyElasticMapsServiceInMapsは廃止予定であり、使用されません", - "xpack.maps.deprecation.proxyEMS.step1": "Kibana構成ファイル、CLIフラグ、または環境変数(Dockerのみ)で「map.proxyElasticMapsServiceInMaps」を削除します。", - "xpack.maps.deprecation.proxyEMS.step2": "Elastic Maps Serviceをローカルでホストします。", "xpack.maps.discover.visualizeFieldLabel": "Mapsで可視化", "xpack.maps.distanceFilterForm.filterLabelLabel": "ラベルでフィルタリング", "xpack.maps.drawFeatureControl.invalidGeometry": "無効なジオメトリが検出されました", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index df595545cd4f4..b7d5804f9e17a 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -14729,9 +14729,6 @@ "xpack.maps.common.esSpatialRelation.intersectsLabel": "intersects", "xpack.maps.common.esSpatialRelation.withinLabel": "之内", "xpack.maps.deleteBtnTitle": "删除", - "xpack.maps.deprecation.proxyEMS.message": "map.proxyElasticMapsServiceInMaps 已过时,将不再使用", - "xpack.maps.deprecation.proxyEMS.step1": "在 Kibana 配置文件、CLI 标志或环境变量中中移除“map.proxyElasticMapsServiceInMaps”(仅适用于 Docker)。", - "xpack.maps.deprecation.proxyEMS.step2": "本地托管 Elastic Maps Service。", "xpack.maps.discover.visualizeFieldLabel": "在 Maps 中可视化", "xpack.maps.distanceFilterForm.filterLabelLabel": "筛选标签", "xpack.maps.drawFeatureControl.invalidGeometry": "检测到无效的几何形状", diff --git a/x-pack/test/api_integration/apis/maps/index.js b/x-pack/test/api_integration/apis/maps/index.js index bd2505905c395..b18137af9b844 100644 --- a/x-pack/test/api_integration/apis/maps/index.js +++ b/x-pack/test/api_integration/apis/maps/index.js @@ -30,7 +30,6 @@ export default function ({ loadTestFile, getService }) { loadTestFile(require.resolve('./migrations')); loadTestFile(require.resolve('./get_tile')); loadTestFile(require.resolve('./get_grid_tile')); - loadTestFile(require.resolve('./proxy_api')); }); }); } diff --git a/x-pack/test/api_integration/apis/maps/proxy_api.js b/x-pack/test/api_integration/apis/maps/proxy_api.js deleted file mode 100644 index 282a116a33ce6..0000000000000 --- a/x-pack/test/api_integration/apis/maps/proxy_api.js +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import expect from '@kbn/expect'; - -export default function ({ getService }) { - const supertest = getService('supertest'); - - describe('EMS proxy', () => { - it('should correctly rewrite url and format', async () => { - const resp = await supertest - .get(`/api/maps/ems/files/v7.10/manifest`) - .set('kbn-xsrf', 'kibana') - .expect(200); - - expect(resp.body.layers.length).to.be.greaterThan(0); - - //Check world-layer - const worldLayer = resp.body.layers.find((layer) => layer.layer_id === 'world_countries'); - expect(worldLayer.formats.length).to.be.greaterThan(0); - expect(worldLayer.formats[0].type).to.be('topojson'); - expect(worldLayer.formats[0].url).to.be('file?id=world_countries'); - }); - }); -} diff --git a/x-pack/test/api_integration/config.ts b/x-pack/test/api_integration/config.ts index 678f7a0d3d929..fd9aa1e1f2355 100644 --- a/x-pack/test/api_integration/config.ts +++ b/x-pack/test/api_integration/config.ts @@ -25,7 +25,6 @@ export async function getApiIntegrationConfig({ readConfigFile }: FtrConfigProvi ...xPackFunctionalTestsConfig.get('kbnTestServer'), serverArgs: [ ...xPackFunctionalTestsConfig.get('kbnTestServer.serverArgs'), - '--map.proxyElasticMapsServiceInMaps=true', '--xpack.security.session.idleTimeout=3600000', // 1 hour '--telemetry.optIn=true', '--xpack.fleet.agents.pollingRequestTimeout=5000', // 5 seconds From c40d3db6b637fbb043520c8055d930ba12a51fcf Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Tue, 26 Oct 2021 10:44:14 -0600 Subject: [PATCH 48/58] [Maps] remove ecommerce map saved object from home plugin (#116295) --- .../data_sets/ecommerce/saved_objects.ts | 67 ++++++------------- x-pack/plugins/maps/server/plugin.ts | 16 ++++- 2 files changed, 32 insertions(+), 51 deletions(-) diff --git a/src/plugins/home/server/services/sample_data/data_sets/ecommerce/saved_objects.ts b/src/plugins/home/server/services/sample_data/data_sets/ecommerce/saved_objects.ts index 1f0ce6186bb8a..9559aa6b930a3 100644 --- a/src/plugins/home/server/services/sample_data/data_sets/ecommerce/saved_objects.ts +++ b/src/plugins/home/server/services/sample_data/data_sets/ecommerce/saved_objects.ts @@ -138,55 +138,26 @@ export const getSavedObjects = (): SavedObject[] => [ version: 'WzIzLDFd', }, { + id: '9c6f83f0-bb4d-11e8-9c84-77068524bcab', + type: 'visualization', + updated_at: '2018-10-01T15:13:03.270Z', + version: '1', + migrationVersion: {}, attributes: { + title: i18n.translate('home.sampleData.ecommerceSpec.salesCountMapTitle', { + defaultMessage: '[eCommerce] Sales Count Map', + }), + visState: + '{"title":"[eCommerce] Sales Count Map","type":"vega","aggs":[],"params":{"spec":"{\\n $schema: https://vega.github.io/schema/vega/v5.json\\n config: {\\n kibana: {type: \\"map\\", latitude: 25, longitude: -40, zoom: 3}\\n }\\n data: [\\n {\\n name: table\\n url: {\\n index: kibana_sample_data_ecommerce\\n %context%: true\\n %timefield%: order_date\\n body: {\\n size: 0\\n aggs: {\\n gridSplit: {\\n geotile_grid: {field: \\"geoip.location\\", precision: 4, size: 10000}\\n aggs: {\\n gridCentroid: {\\n geo_centroid: {\\n field: \\"geoip.location\\"\\n }\\n }\\n }\\n }\\n }\\n }\\n }\\n format: {property: \\"aggregations.gridSplit.buckets\\"}\\n transform: [\\n {\\n type: geopoint\\n projection: projection\\n fields: [\\n gridCentroid.location.lon\\n gridCentroid.location.lat\\n ]\\n }\\n ]\\n }\\n ]\\n scales: [\\n {\\n name: gridSize\\n type: linear\\n domain: {data: \\"table\\", field: \\"doc_count\\"}\\n range: [\\n 50\\n 1000\\n ]\\n }\\n ]\\n marks: [\\n {\\n name: gridMarker\\n type: symbol\\n from: {data: \\"table\\"}\\n encode: {\\n update: {\\n size: {scale: \\"gridSize\\", field: \\"doc_count\\"}\\n xc: {signal: \\"datum.x\\"}\\n yc: {signal: \\"datum.y\\"}\\n }\\n }\\n },\\n {\\n name: gridLabel\\n type: text\\n from: {data: \\"table\\"}\\n encode: {\\n enter: {\\n fill: {value: \\"firebrick\\"}\\n text: {signal: \\"datum.doc_count\\"}\\n }\\n update: {\\n x: {signal: \\"datum.x\\"}\\n y: {signal: \\"datum.y\\"}\\n dx: {value: -6}\\n dy: {value: 6}\\n fontSize: {value: 18}\\n fontWeight: {value: \\"bold\\"}\\n }\\n }\\n }\\n ]\\n}"}}', + uiStateJSON: '{}', description: '', - layerListJSON: - '[{"id":"0hmz5","alpha":1,"sourceDescriptor":{"type":"EMS_TMS","isAutoSelect":true},"visible":true,"style":{},"type":"VECTOR_TILE","minZoom":0,"maxZoom":24},{"id":"7ameq","label":null,"minZoom":0,"maxZoom":24,"alpha":1,"sourceDescriptor":{"type":"EMS_FILE","id":"world_countries","tooltipProperties":["name","iso2"]},"visible":true,"style":{"type":"VECTOR","properties":{"fillColor":{"type":"DYNAMIC","options":{"field":{"name":"__kbnjoin__count__741db9c6-8ebb-4ea9-9885-b6b4ac019d14","origin":"join"},"color":"Green to Red","fieldMetaOptions":{"isEnabled":false,"sigma":3}}},"lineColor":{"type":"STATIC","options":{"color":"#FFFFFF"}},"lineWidth":{"type":"STATIC","options":{"size":1}},"iconSize":{"type":"STATIC","options":{"size":10}},"symbolizeAs":{"options":{"value":"circle"}},"icon":{"type":"STATIC","options":{"value":"marker"}}}},"type":"VECTOR","joins":[{"leftField":"iso2","right":{"type":"ES_TERM_SOURCE","id":"741db9c6-8ebb-4ea9-9885-b6b4ac019d14","indexPatternTitle":"kibana_sample_data_ecommerce","term":"geoip.country_iso_code","indexPatternRefName":"layer_1_join_0_index_pattern","metrics":[{"type":"count","label":"sales count"}],"applyGlobalQuery":true}}]},{"id":"jmtgf","label":"United States","minZoom":0,"maxZoom":24,"alpha":1,"sourceDescriptor":{"type":"EMS_FILE","id":"usa_states","tooltipProperties":["name"]},"visible":true,"style":{"type":"VECTOR","properties":{"fillColor":{"type":"DYNAMIC","options":{"field":{"name":"__kbnjoin__count__30a0ec24-49b6-476a-b4ed-6c1636333695","origin":"join"},"color":"Blues","fieldMetaOptions":{"isEnabled":false,"sigma":3}}},"lineColor":{"type":"STATIC","options":{"color":"#FFFFFF"}},"lineWidth":{"type":"STATIC","options":{"size":1}},"iconSize":{"type":"STATIC","options":{"size":10}},"symbolizeAs":{"options":{"value":"circle"}},"icon":{"type":"STATIC","options":{"value":"marker"}}}},"type":"VECTOR","joins":[{"leftField":"name","right":{"type":"ES_TERM_SOURCE","id":"30a0ec24-49b6-476a-b4ed-6c1636333695","indexPatternTitle":"kibana_sample_data_ecommerce","term":"geoip.region_name","indexPatternRefName":"layer_2_join_0_index_pattern","metrics":[{"type":"count","label":"sales count"}],"applyGlobalQuery":true}}]},{"id":"ui5f8","label":"France","minZoom":0,"maxZoom":24,"alpha":1,"sourceDescriptor":{"type":"EMS_FILE","id":"france_departments","tooltipProperties":["label_en"]},"visible":true,"style":{"type":"VECTOR","properties":{"fillColor":{"type":"DYNAMIC","options":{"field":{"name":"__kbnjoin__count__e325c9da-73fa-4b3b-8b59-364b99370826","origin":"join"},"color":"Blues","fieldMetaOptions":{"isEnabled":false,"sigma":3}}},"lineColor":{"type":"STATIC","options":{"color":"#FFFFFF"}},"lineWidth":{"type":"STATIC","options":{"size":1}},"iconSize":{"type":"STATIC","options":{"size":10}},"symbolizeAs":{"options":{"value":"circle"}},"icon":{"type":"STATIC","options":{"value":"marker"}}}},"type":"VECTOR","joins":[{"leftField":"label_en","right":{"type":"ES_TERM_SOURCE","id":"e325c9da-73fa-4b3b-8b59-364b99370826","indexPatternTitle":"kibana_sample_data_ecommerce","term":"geoip.region_name","indexPatternRefName":"layer_3_join_0_index_pattern","metrics":[{"type":"count","label":"sales count"}],"applyGlobalQuery":true}}]},{"id":"y3fjb","label":"United Kingdom","minZoom":0,"maxZoom":24,"alpha":1,"sourceDescriptor":{"type":"EMS_FILE","id":"uk_subdivisions","tooltipProperties":["label_en"]},"visible":true,"style":{"type":"VECTOR","properties":{"fillColor":{"type":"DYNAMIC","options":{"field":{"name":"__kbnjoin__count__612d805d-8533-43a9-ac0e-cbf51fe63dcd","origin":"join"},"color":"Blues","fieldMetaOptions":{"isEnabled":false,"sigma":3}}},"lineColor":{"type":"STATIC","options":{"color":"#FFFFFF"}},"lineWidth":{"type":"STATIC","options":{"size":1}},"iconSize":{"type":"STATIC","options":{"size":10}},"symbolizeAs":{"options":{"value":"circle"}},"icon":{"type":"STATIC","options":{"value":"marker"}}}},"type":"VECTOR","joins":[{"leftField":"label_en","right":{"type":"ES_TERM_SOURCE","id":"612d805d-8533-43a9-ac0e-cbf51fe63dcd","indexPatternTitle":"kibana_sample_data_ecommerce","term":"geoip.region_name","indexPatternRefName":"layer_4_join_0_index_pattern","metrics":[{"type":"count","label":"sales count"}],"applyGlobalQuery":true}}]},{"id":"c54wk","label":"Sales","minZoom":9,"maxZoom":24,"alpha":1,"sourceDescriptor":{"id":"04c983b0-8cfa-4e6a-a64b-52c10b7008fe","type":"ES_SEARCH","geoField":"geoip.location","limit":2048,"filterByMapBounds":true,"tooltipProperties":["category","customer_gender","manufacturer","order_id","total_quantity","total_unique_products","taxful_total_price","order_date","geoip.region_name","geoip.country_iso_code"],"indexPatternRefName":"layer_5_source_index_pattern","applyGlobalQuery":true,"scalingType":"LIMIT"},"visible":true,"style":{"type":"VECTOR","properties":{"fillColor":{"type":"DYNAMIC","options":{"field":{"name":"taxful_total_price","origin":"source"},"color":"Greens","fieldMetaOptions":{"isEnabled":false,"sigma":3}}},"lineColor":{"type":"STATIC","options":{"color":"#FFFFFF"}},"lineWidth":{"type":"STATIC","options":{"size":1}},"iconSize":{"type":"STATIC","options":{"size":10}},"symbolizeAs":{"options":{"value":"circle"}},"icon":{"type":"STATIC","options":{"value":"marker"}}}},"type":"VECTOR"},{"id":"qvhh3","label":"Total Sales Revenue","minZoom":0,"maxZoom":9,"alpha":1,"sourceDescriptor":{"type":"ES_GEO_GRID","resolution":"COARSE","id":"aa7f87b8-9dc5-42be-b19e-1a2fa09b6cad","geoField":"geoip.location","requestType":"point","metrics":[{"type":"count","label":"sales count"},{"type":"sum","field":"taxful_total_price","label":"total sales price"}],"indexPatternRefName":"layer_6_source_index_pattern","applyGlobalQuery":true},"visible":true,"style":{"type":"VECTOR","properties":{"fillColor":{"type":"DYNAMIC","options":{"field":{"name":"doc_count","origin":"source"},"color":"Greens","fieldMetaOptions":{"isEnabled":false,"sigma":3}}},"lineColor":{"type":"STATIC","options":{"color":"#cccccc"}},"lineWidth":{"type":"STATIC","options":{"size":1}},"iconSize":{"type":"DYNAMIC","options":{"field":{"name":"sum_of_taxful_total_price","origin":"source"},"minSize":1,"maxSize":20,"fieldMetaOptions":{"isEnabled":false,"sigma":3}}},"labelText":{"type":"DYNAMIC","options":{"field":{"name":"sum_of_taxful_total_price","origin":"source"},"fieldMetaOptions":{"isEnabled":false,"sigma":3}}},"labelSize":{"type":"DYNAMIC","options":{"field":{"name":"sum_of_taxful_total_price","origin":"source"},"minSize":12,"maxSize":24,"fieldMetaOptions":{"isEnabled":false,"sigma":3}}},"labelBorderSize":{"options":{"size":"MEDIUM"}},"symbolizeAs":{"options":{"value":"circle"}},"icon":{"type":"STATIC","options":{"value":"marker"}}}},"type":"VECTOR"}]', - mapStateJSON: - '{"zoom":2.11,"center":{"lon":-15.07605,"lat":45.88578},"timeFilters":{"from":"now-7d","to":"now"},"refreshConfig":{"isPaused":true,"interval":0},"query":{"query":"","language":"kuery"},"settings":{"autoFitToDataBounds":false}}', - title: '[eCommerce] Orders by Country', - uiStateJSON: '{"isDarkMode":false}', - }, - coreMigrationVersion: '8.0.0', - id: '2c9c1f60-1909-11e9-919b-ffe5949a18d2', - migrationVersion: { - map: '7.14.0', - }, - references: [ - { - id: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', - name: 'layer_1_join_0_index_pattern', - type: 'index-pattern', - }, - { - id: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', - name: 'layer_2_join_0_index_pattern', - type: 'index-pattern', - }, - { - id: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', - name: 'layer_3_join_0_index_pattern', - type: 'index-pattern', - }, - { - id: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', - name: 'layer_4_join_0_index_pattern', - type: 'index-pattern', - }, - { - id: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', - name: 'layer_5_source_index_pattern', - type: 'index-pattern', - }, - { - id: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', - name: 'layer_6_source_index_pattern', - type: 'index-pattern', + version: 1, + kibanaSavedObjectMeta: { + searchSourceJSON: + '{"index":"ff959d40-b880-11e8-a6d9-e546fe2bba5f","query":{"query":"","language":"kuery"},"filter":[]}', }, - ], - type: 'map', - updated_at: '2021-08-05T12:23:57.577Z', - version: 'WzI5LDFd', + }, + references: [], }, { attributes: { @@ -1351,9 +1322,9 @@ export const getSavedObjects = (): SavedObject[] => [ type: 'search', }, { - id: '2c9c1f60-1909-11e9-919b-ffe5949a18d2', + id: '9c6f83f0-bb4d-11e8-9c84-77068524bcab', name: '11:panel_11', - type: 'map', + type: 'visualization', }, { id: 'c00d1f90-f5ea-11eb-a78e-83aac3c38a60', diff --git a/x-pack/plugins/maps/server/plugin.ts b/x-pack/plugins/maps/server/plugin.ts index 5d84ee2ef26d2..8145b2bd8bb28 100644 --- a/x-pack/plugins/maps/server/plugin.ts +++ b/x-pack/plugins/maps/server/plugin.ts @@ -73,9 +73,7 @@ export class MapsPlugin implements Plugin { defaultMessage: 'Map', }); - // commented out since it registers an SO already registered by home plugin - // https://github.com/elastic/kibana/blob/2ddaddc2e958f60c6685ab9f9840cdd86da9d398/src/plugins/home/server/services/sample_data/data_sets/ecommerce/saved_objects.ts#L151 - // home.sampleData.addSavedObjectsToSampleDataset('ecommerce', getEcommerceSavedObjects()); + home.sampleData.addSavedObjectsToSampleDataset('ecommerce', getEcommerceSavedObjects()); home.sampleData.addAppLinksToSampleDataset('ecommerce', [ { @@ -85,6 +83,18 @@ export class MapsPlugin implements Plugin { }, ]); + home.sampleData.replacePanelInSampleDatasetDashboard({ + sampleDataId: 'ecommerce', + dashboardId: '722b74f0-b882-11e8-a6d9-e546fe2bba5f', + oldEmbeddableId: '9c6f83f0-bb4d-11e8-9c84-77068524bcab', + embeddableId: '2c9c1f60-1909-11e9-919b-ffe5949a18d2', + // @ts-ignore + embeddableType: MAP_SAVED_OBJECT_TYPE, + embeddableConfig: { + isLayerTOCOpen: false, + }, + }); + home.sampleData.addSavedObjectsToSampleDataset('flights', getFlightsSavedObjects()); home.sampleData.addAppLinksToSampleDataset('flights', [ From aa17c1b509ee481e1c2a1434a25a1e9789ae4738 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Tue, 26 Oct 2021 10:45:14 -0600 Subject: [PATCH 49/58] =?UTF-8?q?[maps]=20re-enable=20x-pack/test/function?= =?UTF-8?q?al/apps/maps/documents=5Fsource/top=5Fhits=C2=B7js=20(#115392)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [maps] re-enable x-pack/test/functional/apps/maps/documents_source/top_hits·js * remove comment Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/test/functional/apps/maps/documents_source/top_hits.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/x-pack/test/functional/apps/maps/documents_source/top_hits.js b/x-pack/test/functional/apps/maps/documents_source/top_hits.js index b1998936316de..fa93d657aa3dd 100644 --- a/x-pack/test/functional/apps/maps/documents_source/top_hits.js +++ b/x-pack/test/functional/apps/maps/documents_source/top_hits.js @@ -15,8 +15,7 @@ export default function ({ getPageObjects, getService }) { const find = getService('find'); const security = getService('security'); - // Failing: See https://github.com/elastic/kibana/issues/115262 - describe.skip('geo top hits', () => { + describe('geo top hits', () => { describe('split on string field', () => { before(async () => { await security.testUser.setRoles(['global_maps_all', 'test_logstash_reader'], false); From 109e0e71c7c4f24e58b66968f8626ac2c0b50da5 Mon Sep 17 00:00:00 2001 From: Sergi Massaneda Date: Tue, 26 Oct 2021 18:50:48 +0200 Subject: [PATCH 50/58] [Security Solutions] Improve deep links generation by capabilities (#116274) * deep links structure changed * feature on child deep links not required --- .../public/app/deep_links/index.test.ts | 15 ++- .../public/app/deep_links/index.ts | 109 ++++++++++-------- 2 files changed, 72 insertions(+), 52 deletions(-) diff --git a/x-pack/plugins/security_solution/public/app/deep_links/index.test.ts b/x-pack/plugins/security_solution/public/app/deep_links/index.test.ts index 479ff4753dd75..cc493d53c029c 100644 --- a/x-pack/plugins/security_solution/public/app/deep_links/index.test.ts +++ b/x-pack/plugins/security_solution/public/app/deep_links/index.test.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { getDeepLinks, PREMIUM_DEEP_LINK_IDS } from '.'; +import { getDeepLinks } from '.'; import { AppDeepLink, Capabilities } from '../../../../../../src/core/public'; import { SecurityPageName } from '../types'; import { mockGlobalState } from '../../common/mock'; @@ -28,7 +28,7 @@ const basicLicense = 'basic'; const platinumLicense = 'platinum'; describe('deepLinks', () => { - it('should return a subset of links for basic license and the full set for platinum', () => { + it('should return a all basic license deep links in the premium deep links', () => { const basicLinks = getDeepLinks(mockGlobalState.app.enableExperimental, basicLicense); const platinumLinks = getDeepLinks(mockGlobalState.app.enableExperimental, platinumLicense); @@ -50,8 +50,17 @@ describe('deepLinks', () => { }); }; testAllBasicInPlatinum(basicLinks, platinumLinks); + }); + + it('should not return premium deep links in basic license deep links', () => { + const basicLinks = getDeepLinks(mockGlobalState.app.enableExperimental, basicLicense); + const platinumLinks = getDeepLinks(mockGlobalState.app.enableExperimental, platinumLicense); - PREMIUM_DEEP_LINK_IDS.forEach((premiumDeepLinkId) => { + [ + SecurityPageName.hostsAnomalies, + SecurityPageName.networkAnomalies, + SecurityPageName.caseConfigure, + ].forEach((premiumDeepLinkId) => { expect(findDeepLink(premiumDeepLinkId, platinumLinks)).toBeTruthy(); expect(findDeepLink(premiumDeepLinkId, basicLinks)).toBeFalsy(); }); diff --git a/x-pack/plugins/security_solution/public/app/deep_links/index.ts b/x-pack/plugins/security_solution/public/app/deep_links/index.ts index 8daec76f280b2..c8b058ef2913d 100644 --- a/x-pack/plugins/security_solution/public/app/deep_links/index.ts +++ b/x-pack/plugins/security_solution/public/app/deep_links/index.ts @@ -7,10 +7,10 @@ import { i18n } from '@kbn/i18n'; -import { isEmpty } from 'lodash'; +import { get } from 'lodash'; import { LicenseType } from '../../../../licensing/common/types'; import { SecurityPageName } from '../types'; -import { AppDeepLink, ApplicationStart, AppNavLinkStatus } from '../../../../../../src/core/public'; +import { AppDeepLink, AppNavLinkStatus, Capabilities } from '../../../../../../src/core/public'; import { OVERVIEW, DETECT, @@ -49,18 +49,28 @@ import { } from '../../../common/constants'; import { ExperimentalFeatures } from '../../../common/experimental_features'; -export const PREMIUM_DEEP_LINK_IDS: Set = new Set([ - SecurityPageName.hostsAnomalies, - SecurityPageName.networkAnomalies, - SecurityPageName.caseConfigure, -]); +const FEATURE = { + general: `${SERVER_APP_ID}.show`, + casesRead: `${CASES_FEATURE_ID}.read_cases`, + casesCrud: `${CASES_FEATURE_ID}.crud_cases`, +} as const; -export const securitySolutionsDeepLinks: AppDeepLink[] = [ +type Feature = typeof FEATURE[keyof typeof FEATURE]; + +type SecuritySolutionDeepLink = AppDeepLink & { + isPremium?: boolean; + features?: Feature[]; + experimentalKey?: keyof ExperimentalFeatures; + deepLinks?: SecuritySolutionDeepLink[]; +}; + +export const securitySolutionsDeepLinks: SecuritySolutionDeepLink[] = [ { id: SecurityPageName.overview, title: OVERVIEW, path: OVERVIEW_PATH, navLinkStatus: AppNavLinkStatus.visible, + features: [FEATURE.general], keywords: [ i18n.translate('xpack.securitySolution.search.overview', { defaultMessage: 'Overview', @@ -73,6 +83,7 @@ export const securitySolutionsDeepLinks: AppDeepLink[] = [ title: DETECT, path: ALERTS_PATH, navLinkStatus: AppNavLinkStatus.hidden, + features: [FEATURE.general], keywords: [ i18n.translate('xpack.securitySolution.search.detect', { defaultMessage: 'Detect', @@ -122,6 +133,7 @@ export const securitySolutionsDeepLinks: AppDeepLink[] = [ id: SecurityPageName.explore, title: EXPLORE, navLinkStatus: AppNavLinkStatus.hidden, + features: [FEATURE.general], keywords: [ i18n.translate('xpack.securitySolution.search.explore', { defaultMessage: 'Explore', @@ -174,6 +186,7 @@ export const securitySolutionsDeepLinks: AppDeepLink[] = [ defaultMessage: 'Anomalies', }), path: `${HOSTS_PATH}/anomalies`, + isPremium: true, }, ], }, @@ -223,6 +236,7 @@ export const securitySolutionsDeepLinks: AppDeepLink[] = [ defaultMessage: 'Anomalies', }), path: `${NETWORK_PATH}/anomalies`, + isPremium: true, }, ], }, @@ -233,6 +247,8 @@ export const securitySolutionsDeepLinks: AppDeepLink[] = [ title: UEBA, path: UEBA_PATH, navLinkStatus: AppNavLinkStatus.visible, + features: [FEATURE.general], + experimentalKey: 'uebaEnabled', keywords: [ i18n.translate('xpack.securitySolution.search.ueba', { defaultMessage: 'Users & Entities', @@ -244,6 +260,7 @@ export const securitySolutionsDeepLinks: AppDeepLink[] = [ id: SecurityPageName.investigate, title: INVESTIGATE, navLinkStatus: AppNavLinkStatus.hidden, + features: [FEATURE.general, FEATURE.casesRead], keywords: [ i18n.translate('xpack.securitySolution.search.investigate', { defaultMessage: 'Investigate', @@ -255,6 +272,7 @@ export const securitySolutionsDeepLinks: AppDeepLink[] = [ title: TIMELINES, path: TIMELINES_PATH, navLinkStatus: AppNavLinkStatus.visible, + features: [FEATURE.general], keywords: [ i18n.translate('xpack.securitySolution.search.timelines', { defaultMessage: 'Timelines', @@ -276,6 +294,7 @@ export const securitySolutionsDeepLinks: AppDeepLink[] = [ title: CASE, path: CASES_PATH, navLinkStatus: AppNavLinkStatus.visible, + features: [FEATURE.casesRead], keywords: [ i18n.translate('xpack.securitySolution.search.cases', { defaultMessage: 'Cases', @@ -289,6 +308,7 @@ export const securitySolutionsDeepLinks: AppDeepLink[] = [ defaultMessage: 'Create New Case', }), path: `${CASES_PATH}/create`, + features: [FEATURE.casesCrud], }, { id: SecurityPageName.caseConfigure, @@ -296,6 +316,8 @@ export const securitySolutionsDeepLinks: AppDeepLink[] = [ defaultMessage: 'Configure Cases', }), path: `${CASES_PATH}/configure`, + features: [FEATURE.casesCrud], + isPremium: true, }, ], }, @@ -306,6 +328,7 @@ export const securitySolutionsDeepLinks: AppDeepLink[] = [ title: MANAGE, path: ENDPOINTS_PATH, navLinkStatus: AppNavLinkStatus.hidden, + features: [FEATURE.general], keywords: [ i18n.translate('xpack.securitySolution.search.manage', { defaultMessage: 'Manage', @@ -348,56 +371,44 @@ export const securitySolutionsDeepLinks: AppDeepLink[] = [ export function getDeepLinks( enableExperimental: ExperimentalFeatures, licenseType?: LicenseType, - capabilities?: ApplicationStart['capabilities'] + capabilities?: Capabilities ): AppDeepLink[] { - const isPremium = isPremiumLicense(licenseType); + const hasPremium = isPremiumLicense(licenseType); - /** - * Recursive DFS function to filter deepLinks by permissions (licence and capabilities). - * Checks "end" deepLinks with no children first, the other parent deepLinks will be included if - * they still have children deepLinks after filtering - */ - const filterDeepLinks = (deepLinks: AppDeepLink[]): AppDeepLink[] => { - return deepLinks - .map((deepLink) => { - if ( - deepLink.id === SecurityPageName.case && - capabilities != null && - capabilities[CASES_FEATURE_ID]?.crud_cases === false - ) { - return { - ...deepLink, - deepLinks: [], - }; - } - if (deepLink.deepLinks) { - return { - ...deepLink, - deepLinks: filterDeepLinks(deepLink.deepLinks), - }; - } - return deepLink; - }) - .filter((deepLink) => { - if (!isPremium && PREMIUM_DEEP_LINK_IDS.has(deepLink.id)) { - return false; + const filterDeepLinks = (securityDeepLinks: SecuritySolutionDeepLink[]): AppDeepLink[] => + securityDeepLinks.reduce( + (deepLinks: AppDeepLink[], { isPremium, features, experimentalKey, ...deepLink }) => { + if (isPremium && !hasPremium) { + return deepLinks; } - if (deepLink.path && deepLink.path.startsWith(CASES_PATH)) { - return capabilities == null || capabilities[CASES_FEATURE_ID]?.read_cases === true; + if (experimentalKey && !enableExperimental[experimentalKey]) { + return deepLinks; } - if (deepLink.id === SecurityPageName.ueba) { - return enableExperimental.uebaEnabled; + if (capabilities != null && !hasFeaturesCapability(features, capabilities)) { + return deepLinks; } - if (!isEmpty(deepLink.deepLinks)) { - return true; + if (deepLink.deepLinks) { + deepLinks.push({ ...deepLink, deepLinks: filterDeepLinks(deepLink.deepLinks) }); + } else { + deepLinks.push(deepLink); } - return capabilities == null || capabilities[SERVER_APP_ID]?.show === true; - }); - }; - + return deepLinks; + }, + [] + ); return filterDeepLinks(securitySolutionsDeepLinks); } +function hasFeaturesCapability( + features: Feature[] | undefined, + capabilities: Capabilities +): boolean { + if (!features) { + return true; + } + return features.some((featureKey) => get(capabilities, featureKey, false)); +} + export function isPremiumLicense(licenseType?: LicenseType): boolean { return ( licenseType === 'gold' || From adace71ee52c121440324535ed74a00ccca5294a Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Tue, 26 Oct 2021 11:08:43 -0600 Subject: [PATCH 51/58] [maps] add support for mvt _key property (#116204) * [maps] add support for mvt _key property * return property value, not key name * eslint * eslint * fix jest test and update expect for second geo grid tile API test * tslint Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../maps/public/actions/tooltip_actions.ts | 5 ++--- .../tiled_vector_layer/tiled_vector_layer.tsx | 10 ++++++++++ .../layers/vector_layer/assign_feature_ids.ts | 13 ------------- .../public/classes/layers/vector_layer/index.ts | 1 - .../classes/layers/vector_layer/vector_layer.tsx | 9 +++++++-- .../tooltip_control/tooltip_control.test.tsx | 12 +++--------- .../mb_map/tooltip_control/tooltip_control.tsx | 6 +++--- .../api_integration/apis/maps/get_grid_tile.js | 15 +++++++++++---- 8 files changed, 36 insertions(+), 35 deletions(-) diff --git a/x-pack/plugins/maps/public/actions/tooltip_actions.ts b/x-pack/plugins/maps/public/actions/tooltip_actions.ts index 30213510c8be4..f1842ade4277e 100644 --- a/x-pack/plugins/maps/public/actions/tooltip_actions.ts +++ b/x-pack/plugins/maps/public/actions/tooltip_actions.ts @@ -14,7 +14,7 @@ import { FEATURE_VISIBLE_PROPERTY_NAME } from '../../common/constants'; import { TooltipFeature, TooltipState } from '../../common/descriptor_types'; import { MapStoreState } from '../reducers/store'; import { ILayer } from '../classes/layers/layer'; -import { IVectorLayer, getFeatureId, isVectorLayer } from '../classes/layers/vector_layer'; +import { IVectorLayer, isVectorLayer } from '../classes/layers/vector_layer'; export function closeOnClickTooltip(tooltipId: string) { return (dispatch: Dispatch, getState: () => MapStoreState) => { @@ -85,8 +85,7 @@ export function updateTooltipStateForLayer(layer: ILayer, layerFeatures: Feature ? layerFeature.properties![FEATURE_VISIBLE_PROPERTY_NAME] : true; return ( - isVisible && - getFeatureId(layerFeature, (layer as IVectorLayer).getSource()) === tooltipFeature.id + isVisible && (layer as IVectorLayer).getFeatureId(layerFeature) === tooltipFeature.id ); }); diff --git a/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/tiled_vector_layer.tsx b/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/tiled_vector_layer.tsx index ece57af7b54ce..79aeab76e4185 100644 --- a/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/tiled_vector_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/tiled_vector_layer/tiled_vector_layer.tsx @@ -70,6 +70,16 @@ export class TiledVectorLayer extends VectorLayer { this._source = source as ITiledSingleLayerVectorSource; } + getFeatureId(feature: Feature): string | number | undefined { + if (!this.getSource().isESSource()) { + return feature.id; + } + + return this.getSource().getType() === SOURCE_TYPES.ES_SEARCH + ? feature.properties?._id + : feature.properties?._key; + } + _getMetaFromTiles(): TileMetaFeature[] { return this._descriptor.__metaFromTiles || []; } diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/assign_feature_ids.ts b/x-pack/plugins/maps/public/classes/layers/vector_layer/assign_feature_ids.ts index 53ce15439e815..3611256d246fb 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/assign_feature_ids.ts +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/assign_feature_ids.ts @@ -7,11 +7,8 @@ import _ from 'lodash'; import { FeatureCollection, Feature } from 'geojson'; -import { SOURCE_TYPES } from '../../../../common/constants'; -import { IVectorSource } from '../../sources/vector_source'; export const GEOJSON_FEATURE_ID_PROPERTY_NAME = '__kbn__feature_id__'; -export const ES_MVT_FEATURE_ID_PROPERTY_NAME = '_id'; let idCounter = 0; @@ -60,13 +57,3 @@ export function assignFeatureIds(featureCollection: FeatureCollection): FeatureC features, }; } - -export function getFeatureId(feature: Feature, source: IVectorSource): string | number | undefined { - if (!source.isMvt()) { - return feature.properties?.[GEOJSON_FEATURE_ID_PROPERTY_NAME]; - } - - return source.getType() === SOURCE_TYPES.ES_SEARCH - ? feature.properties?.[ES_MVT_FEATURE_ID_PROPERTY_NAME] - : feature.id; -} diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/index.ts b/x-pack/plugins/maps/public/classes/layers/vector_layer/index.ts index 80d83996d8fd6..cb964f77613da 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/index.ts +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/index.ts @@ -13,4 +13,3 @@ export { VectorLayerArguments, NO_RESULTS_ICON_AND_TOOLTIPCONTENT, } from './vector_layer'; -export { getFeatureId } from './assign_feature_ids'; diff --git a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx index cd1b644e9cfba..675bacb10cde9 100644 --- a/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx +++ b/x-pack/plugins/maps/public/classes/layers/vector_layer/vector_layer.tsx @@ -76,7 +76,7 @@ import { addGeoJsonMbSource, getVectorSourceBounds, syncVectorSource } from './u import { JoinState, performInnerJoins } from './perform_inner_joins'; import { buildVectorRequestMeta } from '../build_vector_request_meta'; import { getJoinAggKey } from '../../../../common/get_agg_key'; -import { getFeatureId } from './assign_feature_ids'; +import { GEOJSON_FEATURE_ID_PROPERTY_NAME } from './assign_feature_ids'; export function isVectorLayer(layer: ILayer) { return (layer as IVectorLayer).canShowTooltip !== undefined; @@ -102,6 +102,7 @@ export interface IVectorLayer extends ILayer { getJoinsDisabledReason(): string | null; getValidJoins(): InnerJoin[]; getSource(): IVectorSource; + getFeatureId(feature: Feature): string | number | undefined; getFeatureById(id: string | number): Feature | null; getPropertiesForTooltip(properties: GeoJsonProperties): Promise; hasJoins(): boolean; @@ -1154,6 +1155,10 @@ export class VectorLayer extends AbstractLayer implements IVectorLayer { return this.getSource().hasTooltipProperties() || this.getJoins().length > 0; } + getFeatureId(feature: Feature): string | number | undefined { + return feature.properties?.[GEOJSON_FEATURE_ID_PROPERTY_NAME]; + } + getFeatureById(id: string | number) { const featureCollection = this._getSourceFeatureCollection(); if (!featureCollection) { @@ -1161,7 +1166,7 @@ export class VectorLayer extends AbstractLayer implements IVectorLayer { } const targetFeature = featureCollection.features.find((feature) => { - return getFeatureId(feature, this.getSource()) === id; + return this.getFeatureId(feature) === id; }); return targetFeature ? targetFeature : null; } diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/tooltip_control.test.tsx b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/tooltip_control.test.tsx index 04b1d2205644f..54e3f532fe913 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/tooltip_control.test.tsx +++ b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/tooltip_control.test.tsx @@ -14,6 +14,7 @@ jest.mock('./tooltip_popover', () => ({ import sinon from 'sinon'; import React from 'react'; import { mount, shallow } from 'enzyme'; +import { Feature } from 'geojson'; import type { Map as MbMap, MapMouseEvent, MapboxGeoJSONFeature } from '@kbn/mapbox-gl'; import { TooltipControl } from './tooltip_control'; import { IVectorLayer } from '../../../classes/layers/vector_layer'; @@ -39,15 +40,8 @@ const mockLayer = { getMbTooltipLayerIds: () => { return ['foo', 'bar']; }, - getSource: () => { - return { - isMvt: () => { - return false; - }, - isESSource: () => { - return false; - }, - }; + getFeatureId: (feature: Feature) => { + return feature.properties?.__kbn__feature_id__; }, getFeatureById: () => { return { diff --git a/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/tooltip_control.tsx b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/tooltip_control.tsx index c2b89e64a449b..dee05b54c45c6 100644 --- a/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/tooltip_control.tsx +++ b/x-pack/plugins/maps/public/connected_components/mb_map/tooltip_control/tooltip_control.tsx @@ -29,7 +29,7 @@ import { import { TooltipPopover } from './tooltip_popover'; import { FeatureGeometryFilterForm } from './features_tooltip'; import { ILayer } from '../../../classes/layers/layer'; -import { IVectorLayer, isVectorLayer, getFeatureId } from '../../../classes/layers/vector_layer'; +import { IVectorLayer, isVectorLayer } from '../../../classes/layers/vector_layer'; import { RenderToolTipContent } from '../../../classes/tooltips/tooltip_property'; function justifyAnchorLocation( @@ -204,7 +204,7 @@ export class TooltipControl extends Component { break; } - const featureId = getFeatureId(mbFeature, layer.getSource()); + const featureId = layer.getFeatureId(mbFeature); const layerId = layer.getId(); let match = false; for (let j = 0; j < uniqueFeatures.length; j++) { @@ -288,7 +288,7 @@ export class TooltipControl extends Component { const layer = this._getLayerByMbLayerId(targetMbFeature.layer.id); if (layer && this.props.openTooltips[0] && this.props.openTooltips[0].features.length) { const firstFeature = this.props.openTooltips[0].features[0]; - if (getFeatureId(targetMbFeature, layer.getSource()) === firstFeature.id) { + if (layer.getFeatureId(targetMbFeature) === firstFeature.id) { // ignore hover events when hover tooltip is all ready opened for feature return; } diff --git a/x-pack/test/api_integration/apis/maps/get_grid_tile.js b/x-pack/test/api_integration/apis/maps/get_grid_tile.js index 63063514555b3..d19c5f20ecd30 100644 --- a/x-pack/test/api_integration/apis/maps/get_grid_tile.js +++ b/x-pack/test/api_integration/apis/maps/get_grid_tile.js @@ -12,8 +12,7 @@ import expect from '@kbn/expect'; export default function ({ getService }) { const supertest = getService('supertest'); - // FLAKY: https://github.com/elastic/kibana/issues/116186 - describe.skip('getGridTile', () => { + describe('getGridTile', () => { it('should return vector tile containing cluster features', async () => { const resp = await supertest .get( @@ -36,7 +35,11 @@ export default function ({ getService }) { expect(clusterFeature.type).to.be(1); expect(clusterFeature.extent).to.be(4096); expect(clusterFeature.id).to.be(undefined); - expect(clusterFeature.properties).to.eql({ _count: 1, 'avg_of_bytes.value': 9252 }); + expect(clusterFeature.properties).to.eql({ + _count: 1, + _key: '10/258/404', + 'avg_of_bytes.value': 9252, + }); expect(clusterFeature.loadGeometry()).to.eql([[{ x: 87, y: 667 }]]); // Metadata feature @@ -92,7 +95,11 @@ export default function ({ getService }) { expect(gridFeature.type).to.be(3); expect(gridFeature.extent).to.be(4096); expect(gridFeature.id).to.be(undefined); - expect(gridFeature.properties).to.eql({ _count: 1, 'avg_of_bytes.value': 9252 }); + expect(gridFeature.properties).to.eql({ + _count: 1, + _key: '10/258/404', + 'avg_of_bytes.value': 9252, + }); expect(gridFeature.loadGeometry()).to.eql([ [ { x: 64, y: 672 }, From 40674b53be5cd21ba59447af14df6e6d13665276 Mon Sep 17 00:00:00 2001 From: Mikhail Shustov Date: Tue, 26 Oct 2021 19:28:46 +0200 Subject: [PATCH 52/58] Enable APM agent (#116283) * update APM agent to version with v8 client support * enable APM agent back --- package.json | 2 +- .../src/init_apm.test.ts | 3 +-- .../kbn-apm-config-loader/src/init_apm.ts | 3 --- .../performance/tests/reporting_dashboard.ts | 3 +-- yarn.lock | 26 +++++++++---------- 5 files changed, 16 insertions(+), 21 deletions(-) diff --git a/package.json b/package.json index 37590371bde73..264c0718a663e 100644 --- a/package.json +++ b/package.json @@ -217,7 +217,7 @@ "deep-freeze-strict": "^1.1.1", "deepmerge": "^4.2.2", "del": "^5.1.0", - "elastic-apm-node": "^3.21.1", + "elastic-apm-node": "^3.23.0", "execa": "^4.0.2", "exit-hook": "^2.2.0", "expiry-js": "0.1.7", diff --git a/packages/kbn-apm-config-loader/src/init_apm.test.ts b/packages/kbn-apm-config-loader/src/init_apm.test.ts index 6781b1b8b807e..95f0a15a448c8 100644 --- a/packages/kbn-apm-config-loader/src/init_apm.test.ts +++ b/packages/kbn-apm-config-loader/src/init_apm.test.ts @@ -11,8 +11,7 @@ import { mockLoadConfiguration } from './init_apm.test.mocks'; import { initApm } from './init_apm'; import apm from 'elastic-apm-node'; -// TODO: unskip when https://github.com/elastic/kibana/issues/116109 is fixed -describe.skip('initApm', () => { +describe('initApm', () => { let apmAddFilterSpy: jest.SpyInstance; let apmStartSpy: jest.SpyInstance; let getConfig: jest.Mock; diff --git a/packages/kbn-apm-config-loader/src/init_apm.ts b/packages/kbn-apm-config-loader/src/init_apm.ts index 33609c2493396..21c40c8b39419 100644 --- a/packages/kbn-apm-config-loader/src/init_apm.ts +++ b/packages/kbn-apm-config-loader/src/init_apm.ts @@ -14,9 +14,6 @@ export const initApm = ( isDistributable: boolean, serviceName: string ) => { - // TODO: re-enabled when https://github.com/elastic/kibana/issues/116109 is fixed - return; - const apmConfigLoader = loadConfiguration(argv, rootDir, isDistributable); const apmConfig = apmConfigLoader.getConfig(serviceName); diff --git a/x-pack/test/performance/tests/reporting_dashboard.ts b/x-pack/test/performance/tests/reporting_dashboard.ts index 9d285b1cf7f44..f363f8449df96 100644 --- a/x-pack/test/performance/tests/reporting_dashboard.ts +++ b/x-pack/test/performance/tests/reporting_dashboard.ts @@ -16,8 +16,7 @@ export default function ({ getService, getPageObject }: FtrProviderContext) { const dashboard = getPageObject('dashboard'); const reporting = getPageObject('reporting'); - // TODO: unskip when https://github.com/elastic/kibana/issues/116109 is fixed - describe.skip('reporting dashbaord', () => { + describe('reporting dashbaord', () => { before(async () => { await kibanaServer.importExport.load( 'x-pack/test/performance/kbn_archives/reporting_dashboard' diff --git a/yarn.lock b/yarn.lock index 43db04f70de45..1fbfcdc605885 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2302,10 +2302,6 @@ is-absolute "^1.0.0" is-negated-glob "^1.0.0" -"@elastic/apm-synthtrace@link:bazel-bin/packages/elastic-apm-synthtrace": - version "0.0.0" - uid "" - "@elastic/apm-rum-core@^5.12.1": version "5.12.1" resolved "https://registry.yarnpkg.com/@elastic/apm-rum-core/-/apm-rum-core-5.12.1.tgz#ad78787876c68b9ce718d1c42b8e7b12b12eaa69" @@ -2330,6 +2326,10 @@ dependencies: "@elastic/apm-rum-core" "^5.12.1" +"@elastic/apm-synthtrace@link:bazel-bin/packages/elastic-apm-synthtrace": + version "0.0.0" + uid "" + "@elastic/app-search-javascript@^7.13.1": version "7.13.1" resolved "https://registry.yarnpkg.com/@elastic/app-search-javascript/-/app-search-javascript-7.13.1.tgz#07d84daa27e856ad14f3f840683288eab06577f4" @@ -13165,10 +13165,10 @@ ejs@^3.1.2, ejs@^3.1.6: dependencies: jake "^10.6.1" -elastic-apm-http-client@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/elastic-apm-http-client/-/elastic-apm-http-client-10.0.0.tgz#495651716c13a744544c4dc983107a948418d213" - integrity sha512-D0Frzaqo2h6RxrbxkwfTZSu7tKkmmP3UGYLCp2Fq25cGT/3px4hBWvTc+nV7iDwj2rwdQl7CNkcathYNkyHRWQ== +elastic-apm-http-client@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/elastic-apm-http-client/-/elastic-apm-http-client-10.1.0.tgz#8fbfa3f026f40d82b22b77bf4ed539cc20623edb" + integrity sha512-G+UsOQS8+kTyjbZ9PBXgbN8RGgeTe3FfbVljiwuN+eIf0UwpSR8k5Oh+Z2BELTTVwTcit7NCH4+B4MPayYx1mw== dependencies: breadth-filter "^2.0.0" container-info "^1.0.1" @@ -13179,10 +13179,10 @@ elastic-apm-http-client@^10.0.0: readable-stream "^3.4.0" stream-chopper "^3.0.1" -elastic-apm-node@^3.21.1: - version "3.21.1" - resolved "https://registry.yarnpkg.com/elastic-apm-node/-/elastic-apm-node-3.21.1.tgz#5f79cfc6ba60469e4ec83d176b3d28ddee78b530" - integrity sha512-qnYWvWXQx00pS98IFYxkRQ9+T+R8oh0KdsbCU8t1ouSozZI6l5frlwC9CVpsqakPnAuvWP/qIYJEKF3CkYPv0w== +elastic-apm-node@^3.23.0: + version "3.23.0" + resolved "https://registry.yarnpkg.com/elastic-apm-node/-/elastic-apm-node-3.23.0.tgz#e842aa505d576003579803e45fe91f572db74a72" + integrity sha512-yzdO/MwAcjT+TbcBQBKWbDb4beDVmmrIaFCu9VA+z6Ow9GKlQv7QaD9/cQjuN8/KI6ASiJfQI8cPgqy1SgSUuA== dependencies: "@elastic/ecs-pino-format" "^1.2.0" after-all-results "^2.0.0" @@ -13191,7 +13191,7 @@ elastic-apm-node@^3.21.1: basic-auth "^2.0.1" cookie "^0.4.0" core-util-is "^1.0.2" - elastic-apm-http-client "^10.0.0" + elastic-apm-http-client "^10.1.0" end-of-stream "^1.4.4" error-callsites "^2.0.4" error-stack-parser "^2.0.6" From 5a9e170d4b89d95547fc8a46f54fefdbd1649a28 Mon Sep 17 00:00:00 2001 From: Larry Gregory Date: Tue, 26 Oct 2021 13:32:17 -0400 Subject: [PATCH 53/58] Remove the legacy audit logger (#116191) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../server/audit/audit_service.test.ts | 218 ++---------------- .../security/server/audit/audit_service.ts | 35 +-- x-pack/plugins/security/server/config.test.ts | 61 +++-- x-pack/plugins/security/server/config.ts | 64 +++-- .../security_usage_collector.test.ts | 30 +-- 5 files changed, 112 insertions(+), 296 deletions(-) diff --git a/x-pack/plugins/security/server/audit/audit_service.test.ts b/x-pack/plugins/security/server/audit/audit_service.test.ts index a1848068eac35..07fa761dc9d85 100644 --- a/x-pack/plugins/security/server/audit/audit_service.test.ts +++ b/x-pack/plugins/security/server/audit/audit_service.test.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { BehaviorSubject, Observable, of } from 'rxjs'; +import { Observable, of } from 'rxjs'; import { coreMock, @@ -14,10 +14,9 @@ import { loggingSystemMock, } from 'src/core/server/mocks'; -import type { SecurityLicenseFeatures } from '../../common/licensing'; import { licenseMock } from '../../common/licensing/index.mock'; import type { ConfigType } from '../config'; -import { ConfigSchema } from '../config'; +import { ConfigSchema, createConfig } from '../config'; import type { AuditEvent } from './audit_events'; import { AuditService, @@ -28,13 +27,15 @@ import { jest.useFakeTimers(); -const createConfig = (settings: Partial) => { - return ConfigSchema.validate({ audit: settings }).audit; -}; - const logger = loggingSystemMock.createLogger(); const license = licenseMock.create(); -const config = createConfig({ enabled: true }); + +const createAuditConfig = (settings: Partial) => { + return createConfig(ConfigSchema.validate({ audit: settings }), logger, { isTLSEnabled: false }) + .audit; +}; + +const config = createAuditConfig({ enabled: true }); const { logging } = coreMock.createSetup(); const http = httpServiceMock.createSetupContract(); const getCurrentUser = jest.fn().mockReturnValue({ username: 'jdoe', roles: ['admin'] }); @@ -132,6 +133,7 @@ describe('#setup', () => { license, config: { enabled: false, + appender: undefined, }, logging, http, @@ -198,6 +200,12 @@ describe('#asScoped', () => { license, config: { enabled: true, + appender: { + type: 'console', + layout: { + type: 'json', + }, + }, ignore_filters: [{ actions: ['ACTION'] }], }, logging, @@ -222,6 +230,12 @@ describe('#asScoped', () => { license, config: { enabled: true, + appender: { + type: 'console', + layout: { + type: 'json', + }, + }, ignore_filters: [{ actions: ['ACTION'] }], }, logging, @@ -306,22 +320,6 @@ describe('#createLoggingConfig', () => { expect(loggingConfig.loggers![0].level).toEqual('off'); }); - test('sets log level to `off` when appender is not defined', async () => { - const features$ = of({ - allowAuditLogging: true, - }); - - const loggingConfig = await features$ - .pipe( - createLoggingConfig({ - enabled: true, - }) - ) - .toPromise(); - - expect(loggingConfig.loggers![0].level).toEqual('off'); - }); - test('sets log level to `off` when license does not allow audit logging', async () => { const features$ = of({ allowAuditLogging: false, @@ -563,175 +561,3 @@ describe('#filterEvent', () => { ).toBeFalsy(); }); }); - -describe('#getLogger', () => { - test('calls the underlying logger with the provided message and requisite tags', () => { - const pluginId = 'foo'; - - const licenseWithFeatures = licenseMock.create(); - licenseWithFeatures.features$ = new BehaviorSubject({ - allowLegacyAuditLogging: true, - } as SecurityLicenseFeatures).asObservable(); - - const auditService = new AuditService(logger).setup({ - license: licenseWithFeatures, - config, - logging, - http, - getCurrentUser, - getSpaceId, - getSID, - recordAuditLoggingUsage, - }); - - const auditLogger = auditService.getLogger(pluginId); - - const eventType = 'bar'; - const message = 'this is my audit message'; - auditLogger.log(eventType, message); - - expect(logger.info).toHaveBeenCalledTimes(1); - expect(logger.info).toHaveBeenCalledWith(message, { - eventType, - tags: [pluginId, eventType], - }); - }); - - test('calls the underlying logger with the provided metadata', () => { - const pluginId = 'foo'; - - const licenseWithFeatures = licenseMock.create(); - licenseWithFeatures.features$ = new BehaviorSubject({ - allowLegacyAuditLogging: true, - } as SecurityLicenseFeatures).asObservable(); - - const auditService = new AuditService(logger).setup({ - license: licenseWithFeatures, - config, - logging, - http, - getCurrentUser, - getSpaceId, - getSID, - recordAuditLoggingUsage, - }); - - const auditLogger = auditService.getLogger(pluginId); - - const eventType = 'bar'; - const message = 'this is my audit message'; - const metadata = Object.freeze({ - property1: 'value1', - property2: false, - property3: 123, - }); - auditLogger.log(eventType, message, metadata); - - expect(logger.info).toHaveBeenCalledTimes(1); - expect(logger.info).toHaveBeenCalledWith(message, { - eventType, - tags: [pluginId, eventType], - property1: 'value1', - property2: false, - property3: 123, - }); - }); - - test('does not call the underlying logger if license does not support audit logging', () => { - const pluginId = 'foo'; - - const licenseWithFeatures = licenseMock.create(); - licenseWithFeatures.features$ = new BehaviorSubject({ - allowLegacyAuditLogging: false, - } as SecurityLicenseFeatures).asObservable(); - - const auditService = new AuditService(logger).setup({ - license: licenseWithFeatures, - config, - logging, - http, - getCurrentUser, - getSpaceId, - getSID, - recordAuditLoggingUsage, - }); - - const auditLogger = auditService.getLogger(pluginId); - - const eventType = 'bar'; - const message = 'this is my audit message'; - auditLogger.log(eventType, message); - - expect(logger.info).not.toHaveBeenCalled(); - }); - - test('does not call the underlying logger if security audit logging is not enabled', () => { - const pluginId = 'foo'; - - const licenseWithFeatures = licenseMock.create(); - licenseWithFeatures.features$ = new BehaviorSubject({ - allowLegacyAuditLogging: true, - } as SecurityLicenseFeatures).asObservable(); - - const auditService = new AuditService(logger).setup({ - license: licenseWithFeatures, - config: createConfig({ - enabled: false, - }), - logging, - http, - getCurrentUser, - getSpaceId, - getSID, - recordAuditLoggingUsage, - }); - - const auditLogger = auditService.getLogger(pluginId); - - const eventType = 'bar'; - const message = 'this is my audit message'; - auditLogger.log(eventType, message); - - expect(logger.info).not.toHaveBeenCalled(); - }); - - test('calls the underlying logger after license upgrade', () => { - const pluginId = 'foo'; - - const licenseWithFeatures = licenseMock.create(); - - const features$ = new BehaviorSubject({ - allowLegacyAuditLogging: false, - } as SecurityLicenseFeatures); - - licenseWithFeatures.features$ = features$.asObservable(); - - const auditService = new AuditService(logger).setup({ - license: licenseWithFeatures, - config, - logging, - http, - getCurrentUser, - getSpaceId, - getSID, - recordAuditLoggingUsage, - }); - - const auditLogger = auditService.getLogger(pluginId); - - const eventType = 'bar'; - const message = 'this is my audit message'; - auditLogger.log(eventType, message); - - expect(logger.info).not.toHaveBeenCalled(); - - // perform license upgrade - features$.next({ - allowLegacyAuditLogging: true, - } as SecurityLicenseFeatures); - - auditLogger.log(eventType, message); - - expect(logger.info).toHaveBeenCalledTimes(1); - }); -}); diff --git a/x-pack/plugins/security/server/audit/audit_service.ts b/x-pack/plugins/security/server/audit/audit_service.ts index a6205ff196537..1878138ea2592 100644 --- a/x-pack/plugins/security/server/audit/audit_service.ts +++ b/x-pack/plugins/security/server/audit/audit_service.ts @@ -5,7 +5,6 @@ * 2.0. */ -import type { Subscription } from 'rxjs'; import { distinctUntilKeyChanged, map } from 'rxjs/operators'; import type { @@ -58,18 +57,10 @@ interface AuditServiceSetupParams { } export class AuditService { - /** - * @deprecated - */ - private licenseFeaturesSubscription?: Subscription; - /** - * @deprecated - */ - private allowLegacyAuditLogging = false; private ecsLogger: Logger; private usageIntervalId?: NodeJS.Timeout; - constructor(private readonly logger: Logger) { + constructor(logger: Logger) { this.ecsLogger = logger.get('ecs'); } @@ -83,14 +74,6 @@ export class AuditService { getSpaceId, recordAuditLoggingUsage, }: AuditServiceSetupParams): AuditServiceSetup { - if (config.enabled && !config.appender) { - this.licenseFeaturesSubscription = license.features$.subscribe( - ({ allowLegacyAuditLogging }) => { - this.allowLegacyAuditLogging = allowLegacyAuditLogging; - } - ); - } - // Configure logging during setup and when license changes logging.configure( license.features$.pipe( @@ -181,17 +164,7 @@ export class AuditService { */ const getLogger = (id?: string): LegacyAuditLogger => { return { - log: (eventType: string, message: string, data?: Record) => { - if (!this.allowLegacyAuditLogging) { - return; - } - - this.logger.info(message, { - tags: id ? [id, eventType] : [eventType], - eventType, - ...data, - }); - }, + log: (eventType: string, message: string, data?: Record) => {}, }; }; @@ -206,10 +179,6 @@ export class AuditService { } stop() { - if (this.licenseFeaturesSubscription) { - this.licenseFeaturesSubscription.unsubscribe(); - this.licenseFeaturesSubscription = undefined; - } clearInterval(this.usageIntervalId!); } } diff --git a/x-pack/plugins/security/server/config.test.ts b/x-pack/plugins/security/server/config.test.ts index ababf435af3c9..feadbbab5a4ca 100644 --- a/x-pack/plugins/security/server/config.test.ts +++ b/x-pack/plugins/security/server/config.test.ts @@ -10,6 +10,10 @@ jest.mock('crypto', () => ({ constants: jest.requireActual('crypto').constants, })); +jest.mock('@kbn/utils', () => ({ + getDataPath: () => '/mock/kibana/data/path', +})); + import { loggingSystemMock } from 'src/core/server/mocks'; import { ConfigSchema, createConfig } from './config'; @@ -1703,6 +1707,50 @@ describe('createConfig()', () => { `); }); + it('creates a default audit appender when audit logging is enabled', () => { + expect( + createConfig( + ConfigSchema.validate({ + audit: { + enabled: true, + }, + }), + loggingSystemMock.create().get(), + { isTLSEnabled: true } + ).audit.appender + ).toMatchInlineSnapshot(` + Object { + "fileName": "/mock/kibana/data/path/audit.log", + "layout": Object { + "type": "json", + }, + "policy": Object { + "interval": "PT24H", + "type": "time-interval", + }, + "strategy": Object { + "max": 10, + "type": "numeric", + }, + "type": "rolling-file", + } + `); + }); + + it('does not create a default audit appender when audit logging is disabled', () => { + expect( + createConfig( + ConfigSchema.validate({ + audit: { + enabled: false, + }, + }), + loggingSystemMock.create().get(), + { isTLSEnabled: true } + ).audit.appender + ).toBeUndefined(); + }); + it('accepts an audit appender', () => { expect( ConfigSchema.validate({ @@ -1741,19 +1789,6 @@ describe('createConfig()', () => { ).toThrow('[audit.appender.1.layout]: expected at least one defined value but got [undefined]'); }); - it('rejects an ignore_filter when no appender is configured', () => { - expect(() => - ConfigSchema.validate({ - audit: { - enabled: true, - ignore_filters: [{ actions: ['some_action'] }], - }, - }) - ).toThrow( - '[audit]: xpack.security.audit.ignore_filters can only be used with the ECS audit logger. To enable the ECS audit logger, specify where you want to write the audit events using xpack.security.audit.appender.' - ); - }); - describe('#getExpirationTimeouts', () => { function createMockConfig(config: Record = {}) { return createConfig(ConfigSchema.validate(config), loggingSystemMock.createLogger(), { diff --git a/x-pack/plugins/security/server/config.ts b/x-pack/plugins/security/server/config.ts index a9e22448e1725..ba0d0d35d8ddd 100644 --- a/x-pack/plugins/security/server/config.ts +++ b/x-pack/plugins/security/server/config.ts @@ -7,11 +7,13 @@ import crypto from 'crypto'; import type { Duration } from 'moment'; +import path from 'path'; import type { Type, TypeOf } from '@kbn/config-schema'; import { schema } from '@kbn/config-schema'; import { i18n } from '@kbn/i18n'; -import type { Logger } from 'src/core/server'; +import { getDataPath } from '@kbn/utils'; +import type { AppenderConfigType, Logger } from 'src/core/server'; import { config as coreConfig } from '../../../../src/core/server'; import type { AuthenticationProvider } from '../common/model'; @@ -271,30 +273,21 @@ export const ConfigSchema = schema.object({ schemes: schema.arrayOf(schema.string(), { defaultValue: ['apikey', 'bearer'] }), }), }), - audit: schema.object( - { - enabled: schema.boolean({ defaultValue: false }), - appender: schema.maybe(coreConfig.logging.appenders), - ignore_filters: schema.maybe( - schema.arrayOf( - schema.object({ - actions: schema.maybe(schema.arrayOf(schema.string(), { minSize: 1 })), - categories: schema.maybe(schema.arrayOf(schema.string(), { minSize: 1 })), - types: schema.maybe(schema.arrayOf(schema.string(), { minSize: 1 })), - outcomes: schema.maybe(schema.arrayOf(schema.string(), { minSize: 1 })), - spaces: schema.maybe(schema.arrayOf(schema.string(), { minSize: 1 })), - }) - ) - ), - }, - { - validate: (auditConfig) => { - if (auditConfig.ignore_filters && !auditConfig.appender) { - return 'xpack.security.audit.ignore_filters can only be used with the ECS audit logger. To enable the ECS audit logger, specify where you want to write the audit events using xpack.security.audit.appender.'; - } - }, - } - ), + audit: schema.object({ + enabled: schema.boolean({ defaultValue: false }), + appender: schema.maybe(coreConfig.logging.appenders), + ignore_filters: schema.maybe( + schema.arrayOf( + schema.object({ + actions: schema.maybe(schema.arrayOf(schema.string(), { minSize: 1 })), + categories: schema.maybe(schema.arrayOf(schema.string(), { minSize: 1 })), + types: schema.maybe(schema.arrayOf(schema.string(), { minSize: 1 })), + outcomes: schema.maybe(schema.arrayOf(schema.string(), { minSize: 1 })), + spaces: schema.maybe(schema.arrayOf(schema.string(), { minSize: 1 })), + }) + ) + ), + }), }); export function createConfig( @@ -381,8 +374,29 @@ export function createConfig( sortedProviders.filter(({ type, name }) => providers[type]?.[name].showInSelector).length > 1; + const appender: AppenderConfigType | undefined = + config.audit.appender ?? + ({ + type: 'rolling-file', + fileName: path.join(getDataPath(), 'audit.log'), + layout: { + type: 'json', + }, + policy: { + type: 'time-interval', + interval: schema.duration().validate('24h'), + }, + strategy: { + type: 'numeric', + max: 10, + }, + } as AppenderConfigType); return { ...config, + audit: { + ...config.audit, + ...(config.audit.enabled && { appender }), + }, authc: { selector: { ...config.authc.selector, enabled: isLoginSelectorEnabled }, providers, diff --git a/x-pack/plugins/security/server/usage_collector/security_usage_collector.test.ts b/x-pack/plugins/security/server/usage_collector/security_usage_collector.test.ts index 3a53a2422770c..aeeeb9c888914 100644 --- a/x-pack/plugins/security/server/usage_collector/security_usage_collector.test.ts +++ b/x-pack/plugins/security/server/usage_collector/security_usage_collector.test.ts @@ -343,35 +343,7 @@ describe('Security UsageCollector', () => { }); describe('audit logging', () => { - it('reports when legacy audit logging is enabled (and ECS audit logging is not enabled)', async () => { - const config = createSecurityConfig( - ConfigSchema.validate({ - audit: { - enabled: true, - appender: undefined, - }, - }) - ); - const usageCollection = usageCollectionPluginMock.createSetupContract(); - const license = createSecurityLicense({ - isLicenseAvailable: true, - allowLegacyAuditLogging: true, - allowAuditLogging: true, - }); - registerSecurityUsageCollector({ usageCollection, config, license }); - - const usage = await usageCollection - .getCollectorByType('security') - ?.fetch(collectorFetchContext); - - expect(usage).toEqual({ - ...DEFAULT_USAGE, - auditLoggingEnabled: true, - auditLoggingType: 'legacy', - }); - }); - - it('reports when ECS audit logging is enabled (and legacy audit logging is not enabled)', async () => { + it('reports when ECS audit logging is enabled', async () => { const config = createSecurityConfig( ConfigSchema.validate({ audit: { From c200c44347f5c5f8bdcc6b2c22d676b624c58556 Mon Sep 17 00:00:00 2001 From: Brian Seeders Date: Tue, 26 Oct 2021 13:35:58 -0400 Subject: [PATCH 54/58] [buildkite] Add Docker CI Group to flaky test job (#116307) --- .buildkite/pipelines/flaky_tests/pipeline.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.buildkite/pipelines/flaky_tests/pipeline.js b/.buildkite/pipelines/flaky_tests/pipeline.js index 5f3633860dfe3..208924aefe80e 100644 --- a/.buildkite/pipelines/flaky_tests/pipeline.js +++ b/.buildkite/pipelines/flaky_tests/pipeline.js @@ -27,6 +27,8 @@ for (let i = 1; i <= XPACK_CI_GROUPS; i++) { inputs.push(stepInput(`xpack/cigroup/${i}`, `Default CI Group ${i}`)); } +inputs.push(stepInput(`xpack/cigroup/Docker`, 'Default CI Group Docker')); + const pipeline = { steps: [ { From 605e9e2d3d74af2edbc41e55fb796abdf67c62a7 Mon Sep 17 00:00:00 2001 From: Dima Arnautov Date: Tue, 26 Oct 2021 19:39:37 +0200 Subject: [PATCH 55/58] [ML] Nodes overview for the Model Management page (#115772) * [ML] trained models tab * [ML] wip nodes list * [ML] add types * [ML] add types * [ML] node expanded row * [ML] wip show memory usage * [ML] refactor, use model_memory_limit for dfa jobs * [ML] fix refresh button * [ML] add process memory overhead * [ML] trained models memory overview * [ML] add jvm size, remove node props from the response * [ML] fix tab name * [ML] custom colors for the bar chart * [ML] sub jvm size * [ML] updates for the model list * [ML] apply native process overhead * [ML]add adjusted_total_in_bytes * [ML] start and stop deployment * [ML] fix default sorting * [ML] fix types issues * [ML] fix const * [ML] remove unused i18n strings * [ML] fix lint * [ML] extra custom URLs test * [ML] update tests for model provider * [ML] add node routing state info * [ML] fix functional tests * [ML] update for es response * [ML] GetTrainedModelDeploymentStats * [ML] add deployment stats * [ML] add spacer * [ML] disable stop allocation for models with pipelines * [ML] fix type * [ML] add beta label * [ML] move beta label * [ML] rename model_size prop * [ML] update tooltip header * [ML] update text * [ML] remove ts ignore * [ML] update types * remove commented code * replace toast notification service * remove ts-ignore * remove empty panel * add comments, update test subjects * fix ts error * update comment * fix applying memory overhead * Revert "fix applying memory overhead" This reverts commit 0cf38fbead0d09658d9e992ed17ede9016b2ea8e. * fix type, remove ts-ignore * add todo comment --- x-pack/plugins/ml/common/constants/locator.ts | 3 +- x-pack/plugins/ml/common/types/locator.ts | 12 +- .../plugins/ml/common/types/trained_models.ts | 81 +++ x-pack/plugins/ml/public/application/app.tsx | 7 +- .../components/navigation_menu/main_tabs.tsx | 31 +- .../navigation_menu/navigation_menu.tsx | 1 + .../contexts/kibana/kibana_context.ts | 2 + .../contexts/kibana/use_field_formatter.ts | 17 + .../analytics_navigation_bar.tsx | 8 - .../pages/analytics_management/page.tsx | 2 - .../public/application/routing/breadcrumbs.ts | 8 + .../routes/data_frame_analytics/index.ts | 1 - .../application/routing/routes/index.ts | 1 + .../routing/routes/trained_models/index.ts | 9 + .../models_list.tsx | 8 +- .../routes/trained_models/nodes_list.tsx | 44 ++ .../services/ml_api_service/trained_models.ts | 40 +- .../application/trained_models/index.ts | 8 + .../models_management/delete_models_modal.tsx | 2 +- .../models_management/expanded_row.tsx | 111 ++-- .../models_management/index.ts | 1 + .../models_management/models_list.tsx | 193 +++++-- .../trained_models/navigation_bar.tsx | 69 +++ .../nodes_overview/expanded_row.tsx | 123 +++++ .../trained_models/nodes_overview/index.ts | 8 + .../nodes_overview/memory_preview_chart.tsx | 140 +++++ .../nodes_overview/nodes_list.tsx | 205 +++++++ .../application/trained_models/page.tsx | 77 +++ .../application/util/custom_url_utils.test.ts | 39 ++ .../locator/formatters/trained_models.ts | 16 + .../plugins/ml/public/locator/ml_locator.ts | 4 + x-pack/plugins/ml/public/plugin.ts | 7 + .../search_deep_links.ts | 2 +- .../ml/server/lib/ml_client/ml_client.ts | 21 + .../plugins/ml/server/lib/ml_client/types.ts | 13 + .../__mocks__/mock_deployment_response.json | 357 +++++++++++++ .../model_provider.test.ts | 503 ++++++++++++++++++ .../data_frame_analytics/models_provider.ts | 135 ++++- .../ml/server/models/memory_overview/index.ts | 8 + .../memory_overview_service.ts | 90 ++++ x-pack/plugins/ml/server/routes/apidoc.json | 6 +- .../ml/server/routes/trained_models.ts | 139 ++++- .../translations/translations/ja-JP.json | 2 - .../translations/translations/zh-CN.json | 2 - .../alerting/transform_rule_types/index.ts | 1 - .../apps/ml/data_frame_analytics/index.ts | 1 - x-pack/test/functional/apps/ml/index.ts | 1 + .../apps/ml/model_management/index.ts | 16 + .../model_list.ts} | 6 +- .../test/functional/services/ml/navigation.ts | 13 +- 50 files changed, 2459 insertions(+), 135 deletions(-) create mode 100644 x-pack/plugins/ml/public/application/contexts/kibana/use_field_formatter.ts create mode 100644 x-pack/plugins/ml/public/application/routing/routes/trained_models/index.ts rename x-pack/plugins/ml/public/application/routing/routes/{data_frame_analytics => trained_models}/models_list.tsx (80%) create mode 100644 x-pack/plugins/ml/public/application/routing/routes/trained_models/nodes_list.tsx create mode 100644 x-pack/plugins/ml/public/application/trained_models/index.ts rename x-pack/plugins/ml/public/application/{data_frame_analytics/pages/analytics_management/components => trained_models}/models_management/delete_models_modal.tsx (100%) rename x-pack/plugins/ml/public/application/{data_frame_analytics/pages/analytics_management/components => trained_models}/models_management/expanded_row.tsx (90%) rename x-pack/plugins/ml/public/application/{data_frame_analytics/pages/analytics_management/components => trained_models}/models_management/index.ts (94%) rename x-pack/plugins/ml/public/application/{data_frame_analytics/pages/analytics_management/components => trained_models}/models_management/models_list.tsx (76%) create mode 100644 x-pack/plugins/ml/public/application/trained_models/navigation_bar.tsx create mode 100644 x-pack/plugins/ml/public/application/trained_models/nodes_overview/expanded_row.tsx create mode 100644 x-pack/plugins/ml/public/application/trained_models/nodes_overview/index.ts create mode 100644 x-pack/plugins/ml/public/application/trained_models/nodes_overview/memory_preview_chart.tsx create mode 100644 x-pack/plugins/ml/public/application/trained_models/nodes_overview/nodes_list.tsx create mode 100644 x-pack/plugins/ml/public/application/trained_models/page.tsx create mode 100644 x-pack/plugins/ml/public/locator/formatters/trained_models.ts create mode 100644 x-pack/plugins/ml/server/models/data_frame_analytics/__mocks__/mock_deployment_response.json create mode 100644 x-pack/plugins/ml/server/models/data_frame_analytics/model_provider.test.ts create mode 100644 x-pack/plugins/ml/server/models/memory_overview/index.ts create mode 100644 x-pack/plugins/ml/server/models/memory_overview/memory_overview_service.ts create mode 100644 x-pack/test/functional/apps/ml/model_management/index.ts rename x-pack/test/functional/apps/ml/{data_frame_analytics/trained_models.ts => model_management/model_list.ts} (96%) diff --git a/x-pack/plugins/ml/common/constants/locator.ts b/x-pack/plugins/ml/common/constants/locator.ts index fe34557504a08..0441805a6771b 100644 --- a/x-pack/plugins/ml/common/constants/locator.ts +++ b/x-pack/plugins/ml/common/constants/locator.ts @@ -13,7 +13,8 @@ export const ML_PAGES = { SINGLE_METRIC_VIEWER: 'timeseriesexplorer', DATA_FRAME_ANALYTICS_JOBS_MANAGE: 'data_frame_analytics', DATA_FRAME_ANALYTICS_CREATE_JOB: 'data_frame_analytics/new_job', - DATA_FRAME_ANALYTICS_MODELS_MANAGE: 'data_frame_analytics/models', + TRAINED_MODELS_MANAGE: 'trained_models', + TRAINED_MODELS_NODES: 'trained_models/nodes', DATA_FRAME_ANALYTICS_EXPLORATION: 'data_frame_analytics/exploration', DATA_FRAME_ANALYTICS_MAP: 'data_frame_analytics/map', /** diff --git a/x-pack/plugins/ml/common/types/locator.ts b/x-pack/plugins/ml/common/types/locator.ts index 6c1ec2972854e..79db780b791fd 100644 --- a/x-pack/plugins/ml/common/types/locator.ts +++ b/x-pack/plugins/ml/common/types/locator.ts @@ -184,6 +184,10 @@ export interface DataFrameAnalyticsQueryState { globalState?: MlCommonGlobalState; } +export interface TrainedModelsQueryState { + modelId?: string; +} + export type DataFrameAnalyticsUrlState = MLPageState< | typeof ML_PAGES.DATA_FRAME_ANALYTICS_JOBS_MANAGE | typeof ML_PAGES.DATA_FRAME_ANALYTICS_MAP @@ -250,8 +254,14 @@ export type MlLocatorState = | DataFrameAnalyticsExplorationUrlState | CalendarEditUrlState | FilterEditUrlState - | MlGenericUrlState; + | MlGenericUrlState + | TrainedModelsUrlState; export type MlLocatorParams = MlLocatorState & SerializableRecord; export type MlLocator = LocatorPublic; + +export type TrainedModelsUrlState = MLPageState< + typeof ML_PAGES.TRAINED_MODELS_MANAGE, + TrainedModelsQueryState | undefined +>; diff --git a/x-pack/plugins/ml/common/types/trained_models.ts b/x-pack/plugins/ml/common/types/trained_models.ts index 3c4c3af748645..5ad1d85d9feb9 100644 --- a/x-pack/plugins/ml/common/types/trained_models.ts +++ b/x-pack/plugins/ml/common/types/trained_models.ts @@ -44,6 +44,7 @@ export interface TrainedModelStat { } >; }; + deployment_stats?: Omit; } type TreeNode = object; @@ -95,6 +96,7 @@ export interface TrainedModelConfigResponse { model_aliases?: string[]; } & Record; model_id: string; + model_type: 'tree_ensemble' | 'pytorch' | 'lang_ident'; tags: string[]; version: string; inference_config?: Record; @@ -117,3 +119,82 @@ export interface ModelPipelines { export interface InferenceConfigResponse { trained_model_configs: TrainedModelConfigResponse[]; } + +export interface TrainedModelDeploymentStatsResponse { + model_id: string; + model_size_bytes: number; + inference_threads: number; + model_threads: number; + state: string; + allocation_status: { target_allocation_count: number; state: string; allocation_count: number }; + nodes: Array<{ + node: Record< + string, + { + transport_address: string; + roles: string[]; + name: string; + attributes: { + 'ml.machine_memory': string; + 'xpack.installed': string; + 'ml.max_open_jobs': string; + 'ml.max_jvm_size': string; + }; + ephemeral_id: string; + } + >; + inference_count: number; + routing_state: { routing_state: string }; + average_inference_time_ms: number; + last_access: number; + }>; +} + +export interface NodeDeploymentStatsResponse { + id: string; + name: string; + transport_address: string; + attributes: Record; + roles: string[]; + allocated_models: Array<{ + inference_threads: number; + allocation_status: { + target_allocation_count: number; + state: string; + allocation_count: number; + }; + model_id: string; + state: string; + model_threads: number; + model_size_bytes: number; + }>; + memory_overview: { + machine_memory: { + /** Total machine memory in bytes */ + total: number; + jvm: number; + }; + /** Open anomaly detection jobs + hardcoded overhead */ + anomaly_detection: { + /** Total size in bytes */ + total: number; + }; + /** DFA jobs currently in training + hardcoded overhead */ + dfa_training: { + total: number; + }; + /** Allocated trained models */ + trained_models: { + total: number; + by_model: Array<{ + model_id: string; + model_size: number; + }>; + }; + }; +} + +export interface NodesOverviewResponse { + count: number; + nodes: NodeDeploymentStatsResponse[]; +} diff --git a/x-pack/plugins/ml/public/application/app.tsx b/x-pack/plugins/ml/public/application/app.tsx index 6259cecae78b5..1df0a7afe475b 100644 --- a/x-pack/plugins/ml/public/application/app.tsx +++ b/x-pack/plugins/ml/public/application/app.tsx @@ -27,7 +27,11 @@ import { MlRouter } from './routing'; import { mlApiServicesProvider } from './services/ml_api_service'; import { HttpService } from './services/http_service'; import { ML_APP_LOCATOR, ML_PAGES } from '../../common/constants/locator'; -export type MlDependencies = Omit & + +export type MlDependencies = Omit< + MlSetupDependencies, + 'share' | 'indexPatternManagement' | 'fieldFormats' +> & MlStartDependencies; interface AppProps { @@ -84,6 +88,7 @@ const App: FC = ({ coreStart, deps, appMountParams }) => { triggersActionsUi: deps.triggersActionsUi, dataVisualizer: deps.dataVisualizer, usageCollection: deps.usageCollection, + fieldFormats: deps.fieldFormats, ...coreStart, }; diff --git a/x-pack/plugins/ml/public/application/components/navigation_menu/main_tabs.tsx b/x-pack/plugins/ml/public/application/components/navigation_menu/main_tabs.tsx index 44f00477ab027..78fc10e77b2da 100644 --- a/x-pack/plugins/ml/public/application/components/navigation_menu/main_tabs.tsx +++ b/x-pack/plugins/ml/public/application/components/navigation_menu/main_tabs.tsx @@ -7,7 +7,7 @@ import React, { FC, useState, useEffect } from 'react'; -import { EuiPageHeader } from '@elastic/eui'; +import { EuiPageHeader, EuiBetaBadge } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { TabId } from './navigation_menu'; import { useMlKibana, useMlLocator, useNavigateToPath } from '../../contexts/kibana'; @@ -20,6 +20,7 @@ export interface Tab { id: TabId; name: any; disabled: boolean; + betaTag?: JSX.Element; } interface Props { @@ -50,6 +51,27 @@ function getTabs(disableLinks: boolean): Tab[] { }), disabled: disableLinks, }, + { + id: 'trained_models', + name: i18n.translate('xpack.ml.navMenu.trainedModelsTabLinkText', { + defaultMessage: 'Model Management', + }), + disabled: disableLinks, + betaTag: ( + + ), + }, { id: 'datavisualizer', name: i18n.translate('xpack.ml.navMenu.dataVisualizerTabLinkText', { @@ -93,6 +115,12 @@ const TAB_DATA: Record = { defaultMessage: 'Data Frame Analytics', }), }, + trained_models: { + testSubject: 'mlMainTab modelManagement', + name: i18n.translate('xpack.ml.trainedModelsTabLabel', { + defaultMessage: 'Trained Models', + }), + }, datavisualizer: { testSubject: 'mlMainTab dataVisualizer', name: i18n.translate('xpack.ml.dataVisualizerTabLabel', { @@ -173,6 +201,7 @@ export const MainTabs: FC = ({ tabId, disableLinks }) => { }, 'data-test-subj': testSubject + (id === selectedTabId ? ' selected' : ''), isSelected: id === selectedTabId, + append: tab.betaTag, }; })} /> diff --git a/x-pack/plugins/ml/public/application/components/navigation_menu/navigation_menu.tsx b/x-pack/plugins/ml/public/application/components/navigation_menu/navigation_menu.tsx index 986a88d789b36..2df9259226ce2 100644 --- a/x-pack/plugins/ml/public/application/components/navigation_menu/navigation_menu.tsx +++ b/x-pack/plugins/ml/public/application/components/navigation_menu/navigation_menu.tsx @@ -15,6 +15,7 @@ export type TabId = | 'access-denied' | 'anomaly_detection' | 'data_frame_analytics' + | 'trained_models' | 'datavisualizer' | 'overview' | 'settings'; diff --git a/x-pack/plugins/ml/public/application/contexts/kibana/kibana_context.ts b/x-pack/plugins/ml/public/application/contexts/kibana/kibana_context.ts index e69d75a24d423..10c00098d82d5 100644 --- a/x-pack/plugins/ml/public/application/contexts/kibana/kibana_context.ts +++ b/x-pack/plugins/ml/public/application/contexts/kibana/kibana_context.ts @@ -21,6 +21,7 @@ import type { EmbeddableStart } from '../../../../../../../src/plugins/embeddabl import type { MapsStartApi } from '../../../../../maps/public'; import type { DataVisualizerPluginStart } from '../../../../../data_visualizer/public'; import type { TriggersAndActionsUIPublicPluginStart } from '../../../../../triggers_actions_ui/public'; +import type { FieldFormatsRegistry } from '../../../../../../../src/plugins/field_formats/common'; interface StartPlugins { data: DataPublicPluginStart; @@ -32,6 +33,7 @@ interface StartPlugins { triggersActionsUi?: TriggersAndActionsUIPublicPluginStart; dataVisualizer?: DataVisualizerPluginStart; usageCollection?: UsageCollectionSetup; + fieldFormats: FieldFormatsRegistry; } export type StartServices = CoreStart & StartPlugins & { diff --git a/x-pack/plugins/ml/public/application/contexts/kibana/use_field_formatter.ts b/x-pack/plugins/ml/public/application/contexts/kibana/use_field_formatter.ts new file mode 100644 index 0000000000000..508ce66f40f47 --- /dev/null +++ b/x-pack/plugins/ml/public/application/contexts/kibana/use_field_formatter.ts @@ -0,0 +1,17 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { useMlKibana } from './kibana_context'; + +export function useFieldFormatter(fieldType: 'bytes') { + const { + services: { fieldFormats }, + } = useMlKibana(); + + const fieldFormatter = fieldFormats.deserialize({ id: fieldType }); + return fieldFormatter.convert.bind(fieldFormatter); +} diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_navigation_bar/analytics_navigation_bar.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_navigation_bar/analytics_navigation_bar.tsx index d26b5d5cfc16f..53fe22208ec94 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_navigation_bar/analytics_navigation_bar.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/analytics_navigation_bar/analytics_navigation_bar.tsx @@ -33,14 +33,6 @@ export const AnalyticsNavigationBar: FC<{ path: '/data_frame_analytics', testSubj: 'mlAnalyticsJobsTab', }, - { - id: 'models', - name: i18n.translate('xpack.ml.dataframe.modelsTabLabel', { - defaultMessage: 'Models', - }), - path: '/data_frame_analytics/models', - testSubj: 'mlTrainedModelsTab', - }, ]; if (jobId !== undefined || modelId !== undefined) { navTabs.push({ diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/page.tsx b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/page.tsx index dedbddcab4f52..1f0e0bf0aad8d 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/page.tsx +++ b/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/page.tsx @@ -31,7 +31,6 @@ import { NodeAvailableWarning } from '../../../components/node_available_warning import { SavedObjectsWarning } from '../../../components/saved_objects_warning'; import { UpgradeWarning } from '../../../components/upgrade'; import { AnalyticsNavigationBar } from './components/analytics_navigation_bar'; -import { ModelsList } from './components/models_management'; import { JobMap } from '../job_map'; import { usePageUrlState } from '../../../util/url_state'; import { ListingPageUrlState } from '../../../../../common/types/common'; @@ -125,7 +124,6 @@ export const Page: FC = () => { updatePageState={setDfaPageState} /> )} - {selectedTabId === 'models' && } diff --git a/x-pack/plugins/ml/public/application/routing/breadcrumbs.ts b/x-pack/plugins/ml/public/application/routing/breadcrumbs.ts index 29412979e1827..ad11c879b2918 100644 --- a/x-pack/plugins/ml/public/application/routing/breadcrumbs.ts +++ b/x-pack/plugins/ml/public/application/routing/breadcrumbs.ts @@ -41,6 +41,13 @@ export const DATA_FRAME_ANALYTICS_BREADCRUMB: ChromeBreadcrumb = Object.freeze({ href: '/data_frame_analytics', }); +export const TRAINED_MODELS: ChromeBreadcrumb = Object.freeze({ + text: i18n.translate('xpack.ml.trainedModelsLabel', { + defaultMessage: 'Trained Models', + }), + href: '/trained_models', +}); + export const DATA_VISUALIZER_BREADCRUMB: ChromeBreadcrumb = Object.freeze({ text: i18n.translate('xpack.ml.datavisualizerBreadcrumbLabel', { defaultMessage: 'Data Visualizer', @@ -74,6 +81,7 @@ const breadcrumbs = { SETTINGS_BREADCRUMB, ANOMALY_DETECTION_BREADCRUMB, DATA_FRAME_ANALYTICS_BREADCRUMB, + TRAINED_MODELS, DATA_VISUALIZER_BREADCRUMB, CREATE_JOB_BREADCRUMB, CALENDAR_MANAGEMENT_BREADCRUMB, diff --git a/x-pack/plugins/ml/public/application/routing/routes/data_frame_analytics/index.ts b/x-pack/plugins/ml/public/application/routing/routes/data_frame_analytics/index.ts index 16e9a2fe0c9ce..52b4ca3213f8c 100644 --- a/x-pack/plugins/ml/public/application/routing/routes/data_frame_analytics/index.ts +++ b/x-pack/plugins/ml/public/application/routing/routes/data_frame_analytics/index.ts @@ -8,5 +8,4 @@ export * from './analytics_jobs_list'; export * from './analytics_job_exploration'; export * from './analytics_job_creation'; -export * from './models_list'; export * from './analytics_map'; diff --git a/x-pack/plugins/ml/public/application/routing/routes/index.ts b/x-pack/plugins/ml/public/application/routing/routes/index.ts index a01d5405f3001..31a8d863e3086 100644 --- a/x-pack/plugins/ml/public/application/routing/routes/index.ts +++ b/x-pack/plugins/ml/public/application/routing/routes/index.ts @@ -14,3 +14,4 @@ export * from './data_frame_analytics'; export { timeSeriesExplorerRouteFactory } from './timeseriesexplorer'; export * from './explorer'; export * from './access_denied'; +export * from './trained_models'; diff --git a/x-pack/plugins/ml/public/application/routing/routes/trained_models/index.ts b/x-pack/plugins/ml/public/application/routing/routes/trained_models/index.ts new file mode 100644 index 0000000000000..53b9ffd0ee87e --- /dev/null +++ b/x-pack/plugins/ml/public/application/routing/routes/trained_models/index.ts @@ -0,0 +1,9 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './models_list'; +export * from './nodes_list'; diff --git a/x-pack/plugins/ml/public/application/routing/routes/data_frame_analytics/models_list.tsx b/x-pack/plugins/ml/public/application/routing/routes/trained_models/models_list.tsx similarity index 80% rename from x-pack/plugins/ml/public/application/routing/routes/data_frame_analytics/models_list.tsx rename to x-pack/plugins/ml/public/application/routing/routes/trained_models/models_list.tsx index a1aca430c9283..9367a58372484 100644 --- a/x-pack/plugins/ml/public/application/routing/routes/data_frame_analytics/models_list.tsx +++ b/x-pack/plugins/ml/public/application/routing/routes/trained_models/models_list.tsx @@ -13,20 +13,20 @@ import { NavigateToPath } from '../../../contexts/kibana'; import { MlRoute, PageLoader, PageProps } from '../../router'; import { useResolver } from '../../use_resolver'; import { basicResolvers } from '../../resolvers'; -import { Page } from '../../../data_frame_analytics/pages/analytics_management'; import { getBreadcrumbWithUrlForApp } from '../../breadcrumbs'; +import { Page } from '../../../trained_models'; export const modelsListRouteFactory = ( navigateToPath: NavigateToPath, basePath: string ): MlRoute => ({ - path: '/data_frame_analytics/models', + path: '/trained_models', render: (props, deps) => , breadcrumbs: [ getBreadcrumbWithUrlForApp('ML_BREADCRUMB', navigateToPath, basePath), - getBreadcrumbWithUrlForApp('DATA_FRAME_ANALYTICS_BREADCRUMB', navigateToPath, basePath), + getBreadcrumbWithUrlForApp('TRAINED_MODELS', navigateToPath, basePath), { - text: i18n.translate('xpack.ml.dataFrameAnalyticsBreadcrumbs.modelsListLabel', { + text: i18n.translate('xpack.ml.trainedModelsBreadcrumbs.modelsListLabel', { defaultMessage: 'Model Management', }), href: '', diff --git a/x-pack/plugins/ml/public/application/routing/routes/trained_models/nodes_list.tsx b/x-pack/plugins/ml/public/application/routing/routes/trained_models/nodes_list.tsx new file mode 100644 index 0000000000000..bd88527af1a8d --- /dev/null +++ b/x-pack/plugins/ml/public/application/routing/routes/trained_models/nodes_list.tsx @@ -0,0 +1,44 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FC } from 'react'; +import { i18n } from '@kbn/i18n'; + +import { NavigateToPath } from '../../../contexts/kibana'; + +import { MlRoute, PageLoader, PageProps } from '../../router'; +import { useResolver } from '../../use_resolver'; +import { basicResolvers } from '../../resolvers'; +import { getBreadcrumbWithUrlForApp } from '../../breadcrumbs'; +import { Page } from '../../../trained_models'; + +export const nodesListRouteFactory = ( + navigateToPath: NavigateToPath, + basePath: string +): MlRoute => ({ + path: '/trained_models/nodes', + render: (props, deps) => , + breadcrumbs: [ + getBreadcrumbWithUrlForApp('ML_BREADCRUMB', navigateToPath, basePath), + getBreadcrumbWithUrlForApp('TRAINED_MODELS', navigateToPath, basePath), + { + text: i18n.translate('xpack.ml.trainedModelsBreadcrumbs.nodesListLabel', { + defaultMessage: 'Nodes Overview', + }), + href: '', + }, + ], +}); + +const PageWrapper: FC = ({ location, deps }) => { + const { context } = useResolver(undefined, undefined, deps.config, basicResolvers(deps)); + return ( + + + + ); +}; diff --git a/x-pack/plugins/ml/public/application/services/ml_api_service/trained_models.ts b/x-pack/plugins/ml/public/application/services/ml_api_service/trained_models.ts index fe2b76c768cba..c483b0a23c2d0 100644 --- a/x-pack/plugins/ml/public/application/services/ml_api_service/trained_models.ts +++ b/x-pack/plugins/ml/public/application/services/ml_api_service/trained_models.ts @@ -14,6 +14,8 @@ import { TrainedModelConfigResponse, ModelPipelines, TrainedModelStat, + NodesOverviewResponse, + TrainedModelDeploymentStatsResponse, } from '../../../../common/types/trained_models'; export interface InferenceQueryParams { @@ -114,11 +116,47 @@ export function trainedModelsApiProvider(httpService: HttpService) { * @param modelId - Model ID */ deleteTrainedModel(modelId: string) { - return httpService.http({ + return httpService.http<{ acknowledge: boolean }>({ path: `${apiBasePath}/trained_models/${modelId}`, method: 'DELETE', }); }, + + getTrainedModelDeploymentStats(modelId?: string | string[]) { + let model = modelId ?? '*'; + if (Array.isArray(modelId)) { + model = modelId.join(','); + } + + return httpService.http<{ + count: number; + deployment_stats: TrainedModelDeploymentStatsResponse[]; + }>({ + path: `${apiBasePath}/trained_models/${model}/deployment/_stats`, + method: 'GET', + }); + }, + + getTrainedModelsNodesOverview() { + return httpService.http({ + path: `${apiBasePath}/trained_models/nodes_overview`, + method: 'GET', + }); + }, + + startModelAllocation(modelId: string) { + return httpService.http<{ acknowledge: boolean }>({ + path: `${apiBasePath}/trained_models/${modelId}/deployment/_start`, + method: 'POST', + }); + }, + + stopModelAllocation(modelId: string) { + return httpService.http<{ acknowledge: boolean }>({ + path: `${apiBasePath}/trained_models/${modelId}/deployment/_stop`, + method: 'POST', + }); + }, }; } diff --git a/x-pack/plugins/ml/public/application/trained_models/index.ts b/x-pack/plugins/ml/public/application/trained_models/index.ts new file mode 100644 index 0000000000000..99a826236c34f --- /dev/null +++ b/x-pack/plugins/ml/public/application/trained_models/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { Page } from './page'; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/models_management/delete_models_modal.tsx b/x-pack/plugins/ml/public/application/trained_models/models_management/delete_models_modal.tsx similarity index 100% rename from x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/models_management/delete_models_modal.tsx rename to x-pack/plugins/ml/public/application/trained_models/models_management/delete_models_modal.tsx index 0db4c5d30fbeb..09daafb885720 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/models_management/delete_models_modal.tsx +++ b/x-pack/plugins/ml/public/application/trained_models/models_management/delete_models_modal.tsx @@ -6,7 +6,6 @@ */ import React, { FC } from 'react'; -import { FormattedMessage } from '@kbn/i18n/react'; import { EuiModal, EuiModalHeader, @@ -17,6 +16,7 @@ import { EuiButton, EuiCallOut, } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; import { ModelItemFull } from './models_list'; interface DeleteModelsModalProps { diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/models_management/expanded_row.tsx b/x-pack/plugins/ml/public/application/trained_models/models_management/expanded_row.tsx similarity index 90% rename from x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/models_management/expanded_row.tsx rename to x-pack/plugins/ml/public/application/trained_models/models_management/expanded_row.tsx index 87a3f10992c06..4b342fe02b4d5 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/models_management/expanded_row.tsx +++ b/x-pack/plugins/ml/public/application/trained_models/models_management/expanded_row.tsx @@ -6,30 +6,30 @@ */ import React, { FC, Fragment } from 'react'; -import { FormattedMessage } from '@kbn/i18n/react'; import { + EuiBadge, + EuiButtonEmpty, + EuiCodeBlock, EuiDescriptionList, + EuiFlexGrid, + EuiFlexGroup, + EuiFlexItem, + EuiHorizontalRule, + EuiNotificationBadge, EuiPanel, EuiSpacer, EuiTabbedContent, - EuiTitle, - EuiNotificationBadge, - EuiFlexGrid, - EuiFlexItem, - EuiCodeBlock, EuiText, - EuiHorizontalRule, - EuiFlexGroup, EuiTextColor, - EuiButtonEmpty, - EuiBadge, + EuiTitle, } from '@elastic/eui'; import { EuiDescriptionListProps } from '@elastic/eui/src/components/description_list/description_list'; +import { FormattedMessage } from '@kbn/i18n/react'; import { ModelItemFull } from './models_list'; -import { useMlKibana } from '../../../../../contexts/kibana'; -import { timeFormatter } from '../../../../../../../common/util/date_utils'; -import { isDefined } from '../../../../../../../common/types/guards'; -import { isPopulatedObject } from '../../../../../../../common'; +import { useMlKibana } from '../../contexts/kibana'; +import { timeFormatter } from '../../../../common/util/date_utils'; +import { isDefined } from '../../../../common/types/guards'; +import { isPopulatedObject } from '../../../../common'; interface ExpandedRowProps { item: ModelItemFull; @@ -52,6 +52,38 @@ const formatterDictionary: Record JSX.Element | string | timestamp: timeFormatter, }; +export function formatToListItems( + items: Record | object +): EuiDescriptionListProps['listItems'] { + return Object.entries(items) + .filter(([, value]) => isDefined(value)) + .map(([title, value]) => { + if (title in formatterDictionary) { + return { + title, + description: formatterDictionary[title](value), + }; + } + return { + title, + description: + typeof value === 'object' ? ( + + {JSON.stringify(value, null, 2)} + + ) : ( + value.toString() + ), + }; + }); +} + export const ExpandedRow: FC = ({ item }) => { const { inference_config: inferenceConfig, @@ -83,36 +115,6 @@ export const ExpandedRow: FC = ({ item }) => { license_level, }; - function formatToListItems(items: Record): EuiDescriptionListProps['listItems'] { - return Object.entries(items) - .filter(([, value]) => isDefined(value)) - .map(([title, value]) => { - if (title in formatterDictionary) { - return { - title, - description: formatterDictionary[title](value), - }; - } - return { - title, - description: - typeof value === 'object' ? ( - - {JSON.stringify(value, null, 2)} - - ) : ( - value.toString() - ), - }; - }); - } - const { services: { share }, } = useMlKibana(); @@ -243,6 +245,27 @@ export const ExpandedRow: FC = ({ item }) => { content: ( <> + {stats.deployment_stats && ( + <> + + +
+ +
+
+ + +
+ + + )} {stats.inference_stats && ( diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/models_management/index.ts b/x-pack/plugins/ml/public/application/trained_models/models_management/index.ts similarity index 94% rename from x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/models_management/index.ts rename to x-pack/plugins/ml/public/application/trained_models/models_management/index.ts index 27c378aaed25b..b15e65e5150c9 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/models_management/index.ts +++ b/x-pack/plugins/ml/public/application/trained_models/models_management/index.ts @@ -12,4 +12,5 @@ export const ModelsTableToConfigMapping = { description: 'description', createdAt: 'create_time', type: 'type', + modelType: 'model_type', } as const; diff --git a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/models_management/models_list.tsx b/x-pack/plugins/ml/public/application/trained_models/models_management/models_list.tsx similarity index 76% rename from x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/models_management/models_list.tsx rename to x-pack/plugins/ml/public/application/trained_models/models_management/models_list.tsx index dab86534209f1..16b9aa760f535 100644 --- a/x-pack/plugins/ml/public/application/data_frame_analytics/pages/analytics_management/components/models_management/models_list.tsx +++ b/x-pack/plugins/ml/public/application/trained_models/models_management/models_list.tsx @@ -6,8 +6,7 @@ */ import React, { FC, useState, useCallback, useMemo } from 'react'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n/react'; +import { groupBy } from 'lodash'; import { EuiInMemoryTable, EuiFlexGroup, @@ -21,40 +20,37 @@ import { EuiSearchBarProps, } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n/react'; import { EuiBasicTableColumn } from '@elastic/eui/src/components/basic_table/basic_table'; import { EuiTableSelectionType } from '@elastic/eui/src/components/basic_table/table_types'; import { Action } from '@elastic/eui/src/components/basic_table/action_types'; -import { StatsBar, ModelsBarStats } from '../../../../../components/stats_bar'; -import { useTrainedModelsApiService } from '../../../../../services/ml_api_service/trained_models'; -import { ModelsTableToConfigMapping } from './index'; -import { DeleteModelsModal } from './delete_models_modal'; -import { - useMlKibana, - useMlLocator, - useNavigateToPath, - useNotifications, -} from '../../../../../contexts/kibana'; -import { ExpandedRow } from './expanded_row'; - -import { - TrainedModelConfigResponse, - ModelPipelines, - TrainedModelStat, -} from '../../../../../../../common/types/trained_models'; import { getAnalysisType, REFRESH_ANALYTICS_LIST_STATE, refreshAnalyticsList$, useRefreshAnalyticsList, -} from '../../../../common'; -import { ML_PAGES } from '../../../../../../../common/constants/locator'; -import { DataFrameAnalysisConfigType } from '../../../../../../../common/types/data_frame_analytics'; -import { timeFormatter } from '../../../../../../../common/util/date_utils'; -import { isPopulatedObject } from '../../../../../../../common'; -import { ListingPageUrlState } from '../../../../../../../common/types/common'; -import { usePageUrlState } from '../../../../../util/url_state'; -import { BUILT_IN_MODEL_TAG } from '../../../../../../../common/constants/data_frame_analytics'; -import { useTableSettings } from '../analytics_list/use_table_settings'; +} from '../../data_frame_analytics/common'; +import { ModelsTableToConfigMapping } from './index'; +import { ModelsBarStats, StatsBar } from '../../components/stats_bar'; +import { useMlKibana, useMlLocator, useNavigateToPath } from '../../contexts/kibana'; +import { useTrainedModelsApiService } from '../../services/ml_api_service/trained_models'; +import { + ModelPipelines, + TrainedModelConfigResponse, + TrainedModelStat, +} from '../../../../common/types/trained_models'; +import { BUILT_IN_MODEL_TAG } from '../../../../common/constants/data_frame_analytics'; +import { DataFrameAnalysisConfigType } from '../../../../common/types/data_frame_analytics'; +import { DeleteModelsModal } from './delete_models_modal'; +import { ML_PAGES } from '../../../../common/constants/locator'; +import { ListingPageUrlState } from '../../../../common/types/common'; +import { usePageUrlState } from '../../util/url_state'; +import { ExpandedRow } from './expanded_row'; +import { isPopulatedObject } from '../../../../common'; +import { timeFormatter } from '../../../../common/util/date_utils'; +import { useTableSettings } from '../../data_frame_analytics/pages/analytics_management/components/analytics_list/use_table_settings'; +import { useToastNotificationService } from '../../services/toast_notification_service'; type Stats = Omit; @@ -87,7 +83,7 @@ export const ModelsList: FC = () => { const urlLocator = useMlLocator()!; const [pageState, updatePageState] = usePageUrlState( - ML_PAGES.DATA_FRAME_ANALYTICS_MODELS_MANAGE, + ML_PAGES.TRAINED_MODELS_MANAGE, getDefaultModelsListState() ); @@ -96,7 +92,9 @@ export const ModelsList: FC = () => { const canDeleteDataFrameAnalytics = capabilities.ml.canDeleteDataFrameAnalytics as boolean; const trainedModelsApiService = useTrainedModelsApiService(); - const { toasts } = useNotifications(); + + const { displayErrorToast, displayDangerToast, displaySuccessToast } = + useToastNotificationService(); const [isLoading, setIsLoading] = useState(false); const [items, setItems] = useState([]); @@ -133,6 +131,7 @@ export const ModelsList: FC = () => { ...(typeof model.inference_config === 'object' ? { type: [ + model.model_type, ...Object.keys(model.inference_config), ...(isBuiltInModel(model) ? [BUILT_IN_MODEL_TYPE] : []), ], @@ -159,11 +158,12 @@ export const ModelsList: FC = () => { ); } } catch (error) { - toasts.addError(new Error(error.body?.message), { - title: i18n.translate('xpack.ml.trainedModels.modelsList.fetchFailedErrorMessage', { + displayErrorToast( + error, + i18n.translate('xpack.ml.trainedModels.modelsList.fetchFailedErrorMessage', { defaultMessage: 'Models fetch failed', - }), - }); + }) + ); } setIsLoading(false); refreshAnalyticsList$.next(REFRESH_ANALYTICS_LIST_STATE.IDLE); @@ -191,23 +191,39 @@ export const ModelsList: FC = () => { * Fetches models stats and update the original object */ const fetchModelsStats = useCallback(async (models: ModelItem[]) => { - const modelIdsToFetch = models.map((model) => model.model_id); + const { true: pytorchModels } = groupBy(models, (m) => m.model_type === 'pytorch'); try { - const { trained_model_stats: modelsStatsResponse } = - await trainedModelsApiService.getTrainedModelStats(modelIdsToFetch); + if (models) { + const { trained_model_stats: modelsStatsResponse } = + await trainedModelsApiService.getTrainedModelStats(models.map((m) => m.model_id)); - for (const { model_id: id, ...stats } of modelsStatsResponse) { - const model = models.find((m) => m.model_id === id); - model!.stats = stats; + for (const { model_id: id, ...stats } of modelsStatsResponse) { + const model = models.find((m) => m.model_id === id); + model!.stats = stats; + } } + + if (pytorchModels) { + const { deployment_stats: deploymentStatsResponse } = + await trainedModelsApiService.getTrainedModelDeploymentStats( + pytorchModels.map((m) => m.model_id) + ); + + for (const { model_id: id, ...stats } of deploymentStatsResponse) { + const model = models.find((m) => m.model_id === id); + model!.stats!.deployment_stats = stats; + } + } + return true; } catch (error) { - toasts.addError(new Error(error.body.message), { - title: i18n.translate('xpack.ml.trainedModels.modelsList.fetchModelStatsErrorMessage', { + displayErrorToast( + error, + i18n.translate('xpack.ml.trainedModels.modelsList.fetchModelStatsErrorMessage', { defaultMessage: 'Fetch model stats failed', - }), - }); + }) + ); } }, []); @@ -220,6 +236,7 @@ export const ModelsList: FC = () => { if (type) { acc.add(type); } + acc.add(item.model_type); return acc; }, new Set()); return [...result].map((v) => ({ @@ -233,7 +250,7 @@ export const ModelsList: FC = () => { if (await fetchModelsStats(models)) { setModelsToDelete(models as ModelItemFull[]); } else { - toasts.addDanger( + displayDangerToast( i18n.translate('xpack.ml.trainedModels.modelsList.unableToDeleteModelsErrorMessage', { defaultMessage: 'Unable to delete models', }) @@ -256,7 +273,7 @@ export const ModelsList: FC = () => { (model) => !modelsToDelete.some((toDelete) => toDelete.model_id === model.model_id) ) ); - toasts.addSuccess( + displaySuccessToast( i18n.translate('xpack.ml.trainedModels.modelsList.successfullyDeletedMessage', { defaultMessage: '{modelsCount, plural, one {Model {modelsToDeleteIds}} other {# models}} {modelsCount, plural, one {has} other {have}} been successfully deleted', @@ -267,14 +284,15 @@ export const ModelsList: FC = () => { }) ); } catch (error) { - toasts.addError(new Error(error?.body?.message), { - title: i18n.translate('xpack.ml.trainedModels.modelsList.fetchDeletionErrorMessage', { + displayErrorToast( + error, + i18n.translate('xpack.ml.trainedModels.modelsList.fetchDeletionErrorMessage', { defaultMessage: '{modelsCount, plural, one {Model} other {Models}} deletion failed', values: { modelsCount: modelsToDeleteIds.length, }, - }), - }); + }) + ); } } @@ -336,6 +354,77 @@ export const ModelsList: FC = () => { await navigateToPath(path, false); }, }, + { + name: i18n.translate('xpack.ml.inference.modelsList.startModelAllocationActionLabel', { + defaultMessage: 'Start allocation', + }), + description: i18n.translate('xpack.ml.inference.modelsList.startModelAllocationActionLabel', { + defaultMessage: 'Start allocation', + }), + icon: 'download', + type: 'icon', + isPrimary: true, + available: (item) => item.model_type === 'pytorch', + onClick: async (item) => { + try { + await trainedModelsApiService.startModelAllocation(item.model_id); + displaySuccessToast( + i18n.translate('xpack.ml.trainedModels.modelsList.startSuccess', { + defaultMessage: 'Deployment for "{modelId}" has been started successfully.', + values: { + modelId: item.model_id, + }, + }) + ); + } catch (e) { + displayErrorToast( + e, + i18n.translate('xpack.ml.trainedModels.modelsList.startFailed', { + defaultMessage: 'Failed to start "{modelId}"', + values: { + modelId: item.model_id, + }, + }) + ); + } + }, + }, + { + name: i18n.translate('xpack.ml.inference.modelsList.stopModelAllocationActionLabel', { + defaultMessage: 'Stop allocation', + }), + description: i18n.translate('xpack.ml.inference.modelsList.stopModelAllocationActionLabel', { + defaultMessage: 'Stop allocation', + }), + icon: 'stop', + type: 'icon', + isPrimary: true, + available: (item) => item.model_type === 'pytorch', + enabled: (item) => !isPopulatedObject(item.pipelines), + onClick: async (item) => { + try { + await trainedModelsApiService.stopModelAllocation(item.model_id); + displaySuccessToast( + i18n.translate('xpack.ml.trainedModels.modelsList.stopSuccess', { + defaultMessage: 'Deployment for "{modelId}" has been stopped successfully.', + values: { + modelId: item.model_id, + }, + }) + ); + } catch (e) { + displayErrorToast( + e, + i18n.translate('xpack.ml.trainedModels.modelsList.stopFailed', { + defaultMessage: 'Failed to stop "{modelId}"', + values: { + modelId: item.model_id, + }, + }) + ); + } + }, + }, { name: i18n.translate('xpack.ml.trainedModels.modelsList.deleteModelActionLabel', { defaultMessage: 'Delete model', @@ -399,7 +488,7 @@ export const ModelsList: FC = () => { defaultMessage: 'ID', }), sortable: true, - truncateText: true, + truncateText: false, 'data-test-subj': 'mlModelsTableColumnId', }, { @@ -409,7 +498,7 @@ export const ModelsList: FC = () => { defaultMessage: 'Description', }), sortable: false, - truncateText: true, + truncateText: false, 'data-test-subj': 'mlModelsTableColumnDescription', }, { diff --git a/x-pack/plugins/ml/public/application/trained_models/navigation_bar.tsx b/x-pack/plugins/ml/public/application/trained_models/navigation_bar.tsx new file mode 100644 index 0000000000000..da8605f075c2f --- /dev/null +++ b/x-pack/plugins/ml/public/application/trained_models/navigation_bar.tsx @@ -0,0 +1,69 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FC, useCallback, useMemo } from 'react'; +import { i18n } from '@kbn/i18n'; +import { EuiTab, EuiTabs } from '@elastic/eui'; +import { useNavigateToPath } from '../contexts/kibana'; + +interface Tab { + id: string; + name: string; + path: string; +} + +export const TrainedModelsNavigationBar: FC<{ + selectedTabId?: string; +}> = ({ selectedTabId }) => { + const navigateToPath = useNavigateToPath(); + + const tabs = useMemo(() => { + const navTabs = [ + { + id: 'trained_models', + name: i18n.translate('xpack.ml.trainedModels.modelsTabLabel', { + defaultMessage: 'Models', + }), + path: '/trained_models', + testSubj: 'mlTrainedModelsTab', + }, + { + id: 'nodes', + name: i18n.translate('xpack.ml.trainedModels.nodesTabLabel', { + defaultMessage: 'Nodes', + }), + path: '/trained_models/nodes', + testSubj: 'mlNodesOverviewTab', + }, + ]; + return navTabs; + }, []); + + const onTabClick = useCallback( + async (tab: Tab) => { + await navigateToPath(tab.path, true); + }, + [navigateToPath] + ); + + return ( + + {tabs.map((tab) => { + return ( + + {tab.name} + + ); + })} + + ); +}; diff --git a/x-pack/plugins/ml/public/application/trained_models/nodes_overview/expanded_row.tsx b/x-pack/plugins/ml/public/application/trained_models/nodes_overview/expanded_row.tsx new file mode 100644 index 0000000000000..560923e9ebdc9 --- /dev/null +++ b/x-pack/plugins/ml/public/application/trained_models/nodes_overview/expanded_row.tsx @@ -0,0 +1,123 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FC } from 'react'; +import { + EuiDescriptionList, + EuiFlexGrid, + EuiFlexGroup, + EuiFlexItem, + EuiHorizontalRule, + EuiPanel, + EuiSpacer, + EuiTextColor, + EuiTitle, +} from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { NodeItemWithStats } from './nodes_list'; +import { formatToListItems } from '../models_management/expanded_row'; + +interface ExpandedRowProps { + item: NodeItemWithStats; +} + +export const ExpandedRow: FC = ({ item }) => { + const { + allocated_models: allocatedModels, + attributes, + memory_overview: memoryOverview, + ...details + } = item; + + return ( + <> + + + + + + +
+ +
+
+ + +
+ + +
+ + + + +
+ +
+
+ + +
+ + + + + +
+ +
+
+ + + {allocatedModels.map(({ model_id: modelId, ...rest }) => { + return ( + <> + + + + +
{modelId}
+
+
+
+ + + +
+ + + + + ); + })} +
+
+
+ + ); +}; diff --git a/x-pack/plugins/ml/public/application/trained_models/nodes_overview/index.ts b/x-pack/plugins/ml/public/application/trained_models/nodes_overview/index.ts new file mode 100644 index 0000000000000..95b30e2409a45 --- /dev/null +++ b/x-pack/plugins/ml/public/application/trained_models/nodes_overview/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { NodesList } from './nodes_list'; diff --git a/x-pack/plugins/ml/public/application/trained_models/nodes_overview/memory_preview_chart.tsx b/x-pack/plugins/ml/public/application/trained_models/nodes_overview/memory_preview_chart.tsx new file mode 100644 index 0000000000000..ba790ba1c2576 --- /dev/null +++ b/x-pack/plugins/ml/public/application/trained_models/nodes_overview/memory_preview_chart.tsx @@ -0,0 +1,140 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { i18n } from '@kbn/i18n'; +import React, { FC, useMemo } from 'react'; +import { + Chart, + Settings, + BarSeries, + ScaleType, + Axis, + Position, + SeriesColorAccessor, +} from '@elastic/charts'; +import { euiPaletteGray } from '@elastic/eui'; +import { NodeDeploymentStatsResponse } from '../../../../common/types/trained_models'; +import { useFieldFormatter } from '../../contexts/kibana/use_field_formatter'; +import { useCurrentEuiTheme } from '../../components/color_range_legend'; + +interface MemoryPreviewChartProps { + memoryOverview: NodeDeploymentStatsResponse['memory_overview']; +} + +export const MemoryPreviewChart: FC = ({ memoryOverview }) => { + const bytesFormatter = useFieldFormatter('bytes'); + + const { euiTheme } = useCurrentEuiTheme(); + + const groups = useMemo( + () => ({ + jvm: { + name: i18n.translate('xpack.ml.trainedModels.nodesList.jvmHeapSIze', { + defaultMessage: 'JVM heap size', + }), + colour: euiTheme.euiColorVis1, + }, + trained_models: { + name: i18n.translate('xpack.ml.trainedModels.nodesList.modelsMemoryUsage', { + defaultMessage: 'Trained models', + }), + colour: euiTheme.euiColorVis2, + }, + anomaly_detection: { + name: i18n.translate('xpack.ml.trainedModels.nodesList.adMemoryUsage', { + defaultMessage: 'Anomaly detection jobs', + }), + colour: euiTheme.euiColorVis6, + }, + dfa_training: { + name: i18n.translate('xpack.ml.trainedModels.nodesList.dfaMemoryUsage', { + defaultMessage: 'Data frame analytics jobs', + }), + colour: euiTheme.euiColorVis4, + }, + available: { + name: i18n.translate('xpack.ml.trainedModels.nodesList.availableMemory', { + defaultMessage: 'Estimated available memory', + }), + colour: euiPaletteGray(5)[0], + }, + }), + [] + ); + + const chartData = [ + { + x: 0, + y: memoryOverview.machine_memory.jvm, + g: groups.jvm.name, + }, + { + x: 0, + y: memoryOverview.trained_models.total, + g: groups.trained_models.name, + }, + { + x: 0, + y: memoryOverview.anomaly_detection.total, + g: groups.anomaly_detection.name, + }, + { + x: 0, + y: memoryOverview.dfa_training.total, + g: groups.dfa_training.name, + }, + { + x: 0, + y: + memoryOverview.machine_memory.total - + memoryOverview.machine_memory.jvm - + memoryOverview.trained_models.total - + memoryOverview.dfa_training.total - + memoryOverview.anomaly_detection.total, + g: groups.available.name, + }, + ]; + + const barSeriesColorAccessor: SeriesColorAccessor = ({ specId, yAccessor, splitAccessors }) => { + const group = splitAccessors.get('g'); + + return Object.values(groups).find((v) => v.name === group)!.colour; + }; + + return ( + + + i18n.translate('xpack.ml.trainedModels.nodesList.memoryBreakdown', { + defaultMessage: 'Approximate memory breakdown based on the node info', + }), + }} + /> + + bytesFormatter(d)} + /> + + + + ); +}; diff --git a/x-pack/plugins/ml/public/application/trained_models/nodes_overview/nodes_list.tsx b/x-pack/plugins/ml/public/application/trained_models/nodes_overview/nodes_list.tsx new file mode 100644 index 0000000000000..e2ae3b4adffb9 --- /dev/null +++ b/x-pack/plugins/ml/public/application/trained_models/nodes_overview/nodes_list.tsx @@ -0,0 +1,205 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React, { FC, useCallback, useMemo, useState } from 'react'; +import { + EuiButtonIcon, + EuiFlexGroup, + EuiFlexItem, + EuiInMemoryTable, + EuiSearchBarProps, + EuiSpacer, +} from '@elastic/eui'; +import { EuiBasicTableColumn } from '@elastic/eui/src/components/basic_table/basic_table'; +import { i18n } from '@kbn/i18n'; +import { ModelsBarStats, StatsBar } from '../../components/stats_bar'; +import { NodeDeploymentStatsResponse } from '../../../../common/types/trained_models'; +import { usePageUrlState } from '../../util/url_state'; +import { ML_PAGES } from '../../../../common/constants/locator'; +import { useTrainedModelsApiService } from '../../services/ml_api_service/trained_models'; +import { useTableSettings } from '../../data_frame_analytics/pages/analytics_management/components/analytics_list/use_table_settings'; +import { ExpandedRow } from './expanded_row'; +import { + REFRESH_ANALYTICS_LIST_STATE, + refreshAnalyticsList$, + useRefreshAnalyticsList, +} from '../../data_frame_analytics/common'; +import { MemoryPreviewChart } from './memory_preview_chart'; +import { useFieldFormatter } from '../../contexts/kibana/use_field_formatter'; +import { ListingPageUrlState } from '../../../../common/types/common'; + +export type NodeItem = NodeDeploymentStatsResponse; + +export interface NodeItemWithStats extends NodeItem { + stats: any; +} + +export const getDefaultNodesListState = (): ListingPageUrlState => ({ + pageIndex: 0, + pageSize: 10, + sortField: 'name', + sortDirection: 'asc', +}); + +export const NodesList: FC = () => { + const trainedModelsApiService = useTrainedModelsApiService(); + const bytesFormatter = useFieldFormatter('bytes'); + const [items, setItems] = useState([]); + const [isLoading, setIsLoading] = useState(false); + const [itemIdToExpandedRowMap, setItemIdToExpandedRowMap] = useState>( + {} + ); + const [pageState, updatePageState] = usePageUrlState( + ML_PAGES.TRAINED_MODELS_NODES, + getDefaultNodesListState() + ); + + const searchQueryText = pageState.queryText ?? ''; + + const fetchNodesData = useCallback(async () => { + const nodesResponse = await trainedModelsApiService.getTrainedModelsNodesOverview(); + setItems(nodesResponse.nodes); + setIsLoading(false); + refreshAnalyticsList$.next(REFRESH_ANALYTICS_LIST_STATE.IDLE); + }, []); + + const toggleDetails = (item: NodeItem) => { + const itemIdToExpandedRowMapValues = { ...itemIdToExpandedRowMap }; + if (itemIdToExpandedRowMapValues[item.id]) { + delete itemIdToExpandedRowMapValues[item.id]; + } else { + itemIdToExpandedRowMapValues[item.id] = ; + } + setItemIdToExpandedRowMap(itemIdToExpandedRowMapValues); + }; + + const columns: Array> = [ + { + align: 'left', + width: '40px', + isExpander: true, + render: (item: NodeItem) => ( + + ), + 'data-test-subj': 'mlNodesTableRowDetailsToggle', + }, + { + field: 'name', + name: i18n.translate('xpack.ml.trainedModels.nodesList.nodeNameHeader', { + defaultMessage: 'Name', + }), + sortable: true, + truncateText: true, + 'data-test-subj': 'mlNodesTableColumnName', + }, + { + name: i18n.translate('xpack.ml.trainedModels.nodesList.nodeTotalMemoryHeader', { + defaultMessage: 'Total memory', + }), + width: '200px', + truncateText: true, + 'data-test-subj': 'mlNodesTableColumnTotalMemory', + render: (v: NodeItem) => { + return bytesFormatter(v.attributes['ml.machine_memory']); + }, + }, + { + name: i18n.translate('xpack.ml.trainedModels.nodesList.nodeMemoryUsageHeader', { + defaultMessage: 'Memory usage', + }), + truncateText: true, + 'data-test-subj': 'mlNodesTableColumnMemoryUsage', + render: (v: NodeItem) => { + return ; + }, + }, + ]; + + const nodesStats: ModelsBarStats = useMemo(() => { + return { + total: { + show: true, + value: items.length, + label: i18n.translate('xpack.ml.trainedModels.nodesList.totalAmountLabel', { + defaultMessage: 'Total machine learning nodes', + }), + }, + }; + }, [items]); + + const { onTableChange, pagination, sorting } = useTableSettings( + items, + pageState, + updatePageState + ); + + const search: EuiSearchBarProps = { + query: searchQueryText, + onChange: (searchChange) => { + if (searchChange.error !== null) { + return false; + } + updatePageState({ queryText: searchChange.queryText, pageIndex: 0 }); + return true; + }, + box: { + incremental: true, + }, + }; + + // Subscribe to the refresh observable to trigger reloading the model list. + useRefreshAnalyticsList({ + isLoading: setIsLoading, + onRefresh: fetchNodesData, + }); + + return ( + <> + + + {nodesStats && ( + + + + )} + + +
+ + allowNeutralSort={false} + columns={columns} + hasActions={true} + isExpandable={true} + itemIdToExpandedRowMap={itemIdToExpandedRowMap} + isSelectable={false} + items={items} + itemId={'id'} + loading={isLoading} + search={search} + rowProps={(item) => ({ + 'data-test-subj': `mlNodesTableRow row-${item.id}`, + })} + pagination={pagination} + onTableChange={onTableChange} + sorting={sorting} + data-test-subj={isLoading ? 'mlNodesTable loading' : 'mlNodesTable loaded'} + /> +
+ + ); +}; diff --git a/x-pack/plugins/ml/public/application/trained_models/page.tsx b/x-pack/plugins/ml/public/application/trained_models/page.tsx new file mode 100644 index 0000000000000..a6d99ca0fedc0 --- /dev/null +++ b/x-pack/plugins/ml/public/application/trained_models/page.tsx @@ -0,0 +1,77 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { FC, Fragment, useMemo } from 'react'; + +import { FormattedMessage } from '@kbn/i18n/react'; + +import { + EuiFlexGroup, + EuiFlexItem, + EuiPage, + EuiPageBody, + EuiPageContent, + EuiPageHeader, + EuiPageHeaderSection, + EuiTitle, +} from '@elastic/eui'; + +import { useLocation } from 'react-router-dom'; +import { NavigationMenu } from '../components/navigation_menu'; +import { ModelsList } from './models_management'; +import { TrainedModelsNavigationBar } from './navigation_bar'; +import { RefreshAnalyticsListButton } from '../data_frame_analytics/pages/analytics_management/components/refresh_analytics_list_button'; +import { DatePickerWrapper } from '../components/navigation_menu/date_picker_wrapper'; +import { useRefreshAnalyticsList } from '../data_frame_analytics/common'; +import { useRefreshInterval } from '../data_frame_analytics/pages/analytics_management/components/analytics_list/use_refresh_interval'; +import { NodesList } from './nodes_overview'; + +export const Page: FC = () => { + useRefreshInterval(() => {}); + + useRefreshAnalyticsList({ isLoading: () => {} }); + const location = useLocation(); + const selectedTabId = useMemo(() => location.pathname.split('/').pop(), [location]); + + return ( + + + + + + + +

+ +

+
+
+ + + + + + + + + + +
+ + + + {selectedTabId === 'trained_models' ? : null} + {selectedTabId === 'nodes' ? : null} + +
+
+
+ ); +}; diff --git a/x-pack/plugins/ml/public/application/util/custom_url_utils.test.ts b/x-pack/plugins/ml/public/application/util/custom_url_utils.test.ts index 3e2b78d3b0ebb..09f5f17dc64be 100644 --- a/x-pack/plugins/ml/public/application/util/custom_url_utils.test.ts +++ b/x-pack/plugins/ml/public/application/util/custom_url_utils.test.ts @@ -585,6 +585,45 @@ describe('ML - custom URL utils', () => { 'http://airlinecodes.info/airline-code-AAL' ); }); + + test('returns expected URL with preserving custom filter', () => { + const urlWithCustomFilter: UrlConfig = { + url_name: 'URL with a custom filter', + url_value: `discover#/?_g=(time:(from:'$earliest$',mode:absolute,to:'$latest$'))&_a=(filters:!(('$state':(store:appState),meta:(alias:!n,disabled:!f,key:subSystem.keyword,negate:!f,params:(query:JDBC),type:phrase),query:(match_phrase:(subSystem.keyword:JDBC)))),index:'eap_wls_server_12c*,*:eap_wls_server_12c*',query:(language:kuery,query:'wlscluster.keyword:"$wlscluster.keyword$"'))`, + }; + + const testRecords = { + job_id: 'farequote', + result_type: 'record', + probability: 6.533287347648861e-45, + record_score: 93.84475, + initial_record_score: 94.867922946384, + bucket_span: 300, + detector_index: 0, + is_interim: false, + timestamp: 1486656600000, + partition_field_name: 'wlscluster.keyword', + partition_field_value: 'AAL', + function: 'mean', + function_description: 'mean', + typical: [99.2329899996025], + actual: [274.7279901504516], + field_name: 'wlscluster.keyword', + influencers: [ + { + influencer_field_name: 'wlscluster.keyword', + influencer_field_values: ['AAL'], + }, + ], + 'wlscluster.keyword': ['AAL'], + earliest: '2019-02-01T16:00:00.000Z', + latest: '2019-02-01T18:59:59.999Z', + }; + + expect(getUrlForRecord(urlWithCustomFilter, testRecords)).toBe( + `discover#/?_g=(time:(from:'2019-02-01T16:00:00.000Z',mode:absolute,to:'2019-02-01T18:59:59.999Z'))&_a=(filters:!(('$state':(store:appState),meta:(alias:!n,disabled:!f,key:subSystem.keyword,negate:!f,params:(query:JDBC),type:phrase),query:(match_phrase:(subSystem.keyword:JDBC)))),index:'eap_wls_server_12c*,*:eap_wls_server_12c*',query:(language:kuery,query:'wlscluster.keyword:\"AAL\"'))` + ); + }); }); describe('isValidLabel', () => { diff --git a/x-pack/plugins/ml/public/locator/formatters/trained_models.ts b/x-pack/plugins/ml/public/locator/formatters/trained_models.ts new file mode 100644 index 0000000000000..d084c0675769f --- /dev/null +++ b/x-pack/plugins/ml/public/locator/formatters/trained_models.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { TrainedModelsUrlState } from '../../../common/types/locator'; +import { ML_PAGES } from '../../../common/constants/locator'; + +export function formatTrainedModelsManagementUrl( + appBasePath: string, + mlUrlGeneratorState: TrainedModelsUrlState['pageState'] +): string { + return `${appBasePath}/${ML_PAGES.TRAINED_MODELS_MANAGE}`; +} diff --git a/x-pack/plugins/ml/public/locator/ml_locator.ts b/x-pack/plugins/ml/public/locator/ml_locator.ts index 5e41864c96e29..f1bcd84e77d7d 100644 --- a/x-pack/plugins/ml/public/locator/ml_locator.ts +++ b/x-pack/plugins/ml/public/locator/ml_locator.ts @@ -26,6 +26,7 @@ import { formatEditCalendarUrl, formatEditFilterUrl, } from './formatters'; +import { formatTrainedModelsManagementUrl } from './formatters/trained_models'; export { MlLocatorParams, MlLocator }; @@ -66,6 +67,9 @@ export class MlLocatorDefinition implements LocatorDefinition { case ML_PAGES.DATA_FRAME_ANALYTICS_EXPLORATION: path = formatDataFrameAnalyticsExplorationUrl('', params.pageState); break; + case ML_PAGES.TRAINED_MODELS_MANAGE: + path = formatTrainedModelsManagementUrl('', params.pageState); + break; case ML_PAGES.ANOMALY_DETECTION_CREATE_JOB: case ML_PAGES.ANOMALY_DETECTION_CREATE_JOB_ADVANCED: case ML_PAGES.DATA_VISUALIZER: diff --git a/x-pack/plugins/ml/public/plugin.ts b/x-pack/plugins/ml/public/plugin.ts index 60767ecc4c43e..e5346b6618098 100644 --- a/x-pack/plugins/ml/public/plugin.ts +++ b/x-pack/plugins/ml/public/plugin.ts @@ -46,6 +46,10 @@ import type { DataVisualizerPluginStart } from '../../data_visualizer/public'; import type { PluginSetupContract as AlertingSetup } from '../../alerting/public'; import { registerManagementSection } from './application/management'; import type { UsageCollectionSetup } from '../../../../src/plugins/usage_collection/public'; +import type { + FieldFormatsSetup, + FieldFormatsStart, +} from '../../../../src/plugins/field_formats/public'; export interface MlStartDependencies { data: DataPublicPluginStart; @@ -57,6 +61,7 @@ export interface MlStartDependencies { maps?: MapsStartApi; triggersActionsUi?: TriggersAndActionsUIPublicPluginStart; dataVisualizer: DataVisualizerPluginStart; + fieldFormats: FieldFormatsStart; } export interface MlSetupDependencies { @@ -72,6 +77,7 @@ export interface MlSetupDependencies { triggersActionsUi?: TriggersAndActionsUIPublicPluginSetup; alerting?: AlertingSetup; usageCollection?: UsageCollectionSetup; + fieldFormats: FieldFormatsSetup; } export type MlCoreSetup = CoreSetup; @@ -116,6 +122,7 @@ export class MlPlugin implements Plugin { triggersActionsUi: pluginsStart.triggersActionsUi, dataVisualizer: pluginsStart.dataVisualizer, usageCollection: pluginsSetup.usageCollection, + fieldFormats: pluginsStart.fieldFormats, }, params ); diff --git a/x-pack/plugins/ml/public/register_helper/register_search_links/search_deep_links.ts b/x-pack/plugins/ml/public/register_helper/register_search_links/search_deep_links.ts index 693731562ee82..d88bce762e093 100644 --- a/x-pack/plugins/ml/public/register_helper/register_search_links/search_deep_links.ts +++ b/x-pack/plugins/ml/public/register_helper/register_search_links/search_deep_links.ts @@ -38,7 +38,7 @@ const DATA_FRAME_ANALYTICS_DEEP_LINK: AppDeepLink = { title: i18n.translate('xpack.ml.deepLink.trainedModels', { defaultMessage: 'Trained Models', }), - path: `/${ML_PAGES.DATA_FRAME_ANALYTICS_MODELS_MANAGE}`, + path: `/${ML_PAGES.TRAINED_MODELS_MANAGE}`, }, ], }; diff --git a/x-pack/plugins/ml/server/lib/ml_client/ml_client.ts b/x-pack/plugins/ml/server/lib/ml_client/ml_client.ts index 8fa8f71e82d81..b2146b3b9cdb9 100644 --- a/x-pack/plugins/ml/server/lib/ml_client/ml_client.ts +++ b/x-pack/plugins/ml/server/lib/ml_client/ml_client.ts @@ -380,6 +380,27 @@ export function getMlClient( async getTrainedModelsStats(...p: Parameters) { return mlClient.getTrainedModelsStats(...p); }, + // TODO update when the new elasticsearch-js client is available + async getTrainedModelsDeploymentStats(...p: Parameters) { + return client.asCurrentUser.transport.request({ + method: 'GET', + path: `/_ml/trained_models/${p[0]?.model_id ?? '*'}/deployment/_stats`, + }); + }, + // TODO update when the new elasticsearch-js client is available + async startTrainedModelDeployment(...p: Parameters) { + return client.asCurrentUser.transport.request({ + method: 'POST', + path: `/_ml/trained_models/${p[0].model_id}/deployment/_start`, + }); + }, + // TODO update when the new elasticsearch-js client is available + async stopTrainedModelDeployment(...p: Parameters) { + return client.asCurrentUser.transport.request({ + method: 'POST', + path: `/_ml/trained_models/${p[0].model_id}/deployment/_stop`, + }); + }, async info(...p: Parameters) { return mlClient.info(...p); }, diff --git a/x-pack/plugins/ml/server/lib/ml_client/types.ts b/x-pack/plugins/ml/server/lib/ml_client/types.ts index 7ff1acf4ac0ce..fdd491cfc8a6c 100644 --- a/x-pack/plugins/ml/server/lib/ml_client/types.ts +++ b/x-pack/plugins/ml/server/lib/ml_client/types.ts @@ -7,11 +7,24 @@ import { ElasticsearchClient } from 'kibana/server'; import { searchProvider } from './search'; +import { TrainedModelDeploymentStatsResponse } from '../../../common/types/trained_models'; type OrigMlClient = ElasticsearchClient['ml']; export interface MlClient extends OrigMlClient { anomalySearch: ReturnType['anomalySearch']; + // TODO remove when the new elasticsearch-js client is available + getTrainedModelsDeploymentStats: (options?: { model_id?: string }) => Promise<{ + body: { count: number; deployment_stats: TrainedModelDeploymentStatsResponse[] }; + }>; + // TODO remove when the new elasticsearch-js client is available + startTrainedModelDeployment: (options: { model_id: string }) => Promise<{ + body: { acknowledge: boolean }; + }>; + // TODO remove when the new elasticsearch-js client is available + stopTrainedModelDeployment: (options: { model_id: string }) => Promise<{ + body: { acknowledge: boolean }; + }>; } export type MlClientParams = diff --git a/x-pack/plugins/ml/server/models/data_frame_analytics/__mocks__/mock_deployment_response.json b/x-pack/plugins/ml/server/models/data_frame_analytics/__mocks__/mock_deployment_response.json new file mode 100644 index 0000000000000..0742c249b67b0 --- /dev/null +++ b/x-pack/plugins/ml/server/models/data_frame_analytics/__mocks__/mock_deployment_response.json @@ -0,0 +1,357 @@ +{ + "count" : 4, + "deployment_stats" : [ + { + "model_id" : "distilbert-base-uncased-finetuned-sst-2-english", + "model_size_bytes" : 267386880, + "inference_threads" : 1, + "model_threads" : 1, + "state" : "started", + "allocation_status" : { + "allocation_count" : 2, + "target_allocation_count" : 3, + "state" : "started" + }, + "nodes" : [ + { + "node" : { + "3qIoLFnbSi-DwVrYioUCdw" : { + "name" : "node3", + "ephemeral_id" : "WeA49KLuRPmJM_ulLx0ANg", + "transport_address" : "10.142.0.2:9353", + "attributes" : { + "ml.machine_memory" : "15599742976", + "xpack.installed" : "true", + "ml.max_jvm_size" : "1073741824" + }, + "roles" : [ + "data", + "ingest", + "master", + "ml", + "transform" + ] + } + }, + "routing_state" : { + "routing_state" : "started" + }, + "inference_count" : 0, + "average_inference_time_ms" : 0.0 + }, + { + "node" : { + "DpCy7SOBQla3pu0Dq-tnYw" : { + "name" : "node2", + "ephemeral_id" : "17qcsXsNTYqbJ6uwSvdl9g", + "transport_address" : "10.142.0.2:9352", + "attributes" : { + "ml.machine_memory" : "15599742976", + "xpack.installed" : "true", + "ml.max_jvm_size" : "1073741824" + }, + "roles" : [ + "data", + "master", + "ml", + "transform" + ] + } + }, + "routing_state" : { + "routing_state" : "failed", + "reason" : "The object cannot be set twice!" + } + }, + { + "node" : { + "pt7s6lKHQJaP4QHKtU-Q0Q" : { + "name" : "node1", + "ephemeral_id" : "nMJBE9WSRQSWotk0zDPi_Q", + "transport_address" : "10.142.0.2:9351", + "attributes" : { + "ml.machine_memory" : "15599742976", + "xpack.installed" : "true", + "ml.max_jvm_size" : "1073741824" + }, + "roles" : [ + "data", + "master", + "ml" + ] + } + }, + "routing_state" : { + "routing_state" : "started" + }, + "inference_count" : 0, + "average_inference_time_ms" : 0.0 + } + ] + }, + { + "model_id" : "elastic__distilbert-base-cased-finetuned-conll03-english", + "model_size_bytes" : 260947500, + "inference_threads" : 1, + "model_threads" : 1, + "state" : "started", + "allocation_status" : { + "allocation_count" : 2, + "target_allocation_count" : 3, + "state" : "started" + }, + "nodes" : [ + { + "node" : { + "3qIoLFnbSi-DwVrYioUCdw" : { + "name" : "node3", + "ephemeral_id" : "WeA49KLuRPmJM_ulLx0ANg", + "transport_address" : "10.142.0.2:9353", + "attributes" : { + "ml.machine_memory" : "15599742976", + "xpack.installed" : "true", + "ml.max_jvm_size" : "1073741824" + }, + "roles" : [ + "data", + "ingest", + "master", + "ml", + "transform" + ] + } + }, + "routing_state" : { + "routing_state" : "started" + }, + "inference_count" : 0, + "average_inference_time_ms" : 0.0 + }, + { + "node" : { + "DpCy7SOBQla3pu0Dq-tnYw" : { + "name" : "node2", + "ephemeral_id" : "17qcsXsNTYqbJ6uwSvdl9g", + "transport_address" : "10.142.0.2:9352", + "attributes" : { + "ml.machine_memory" : "15599742976", + "xpack.installed" : "true", + "ml.max_jvm_size" : "1073741824" + }, + "roles" : [ + "data", + "master", + "ml", + "transform" + ] + } + }, + "routing_state" : { + "routing_state" : "failed", + "reason" : "The object cannot be set twice!" + } + }, + { + "node" : { + "pt7s6lKHQJaP4QHKtU-Q0Q" : { + "name" : "node1", + "ephemeral_id" : "nMJBE9WSRQSWotk0zDPi_Q", + "transport_address" : "10.142.0.2:9351", + "attributes" : { + "ml.machine_memory" : "15599742976", + "xpack.installed" : "true", + "ml.max_jvm_size" : "1073741824" + }, + "roles" : [ + "data", + "master", + "ml" + ] + } + }, + "routing_state" : { + "routing_state" : "started" + }, + "inference_count" : 0, + "average_inference_time_ms" : 0.0 + } + ] + }, + { + "model_id" : "sentence-transformers__msmarco-minilm-l-12-v3", + "model_size_bytes" : 133378867, + "inference_threads" : 1, + "model_threads" : 1, + "state" : "started", + "allocation_status" : { + "allocation_count" : 2, + "target_allocation_count" : 3, + "state" : "started" + }, + "nodes" : [ + { + "node" : { + "3qIoLFnbSi-DwVrYioUCdw" : { + "name" : "node3", + "ephemeral_id" : "WeA49KLuRPmJM_ulLx0ANg", + "transport_address" : "10.142.0.2:9353", + "attributes" : { + "ml.machine_memory" : "15599742976", + "xpack.installed" : "true", + "ml.max_jvm_size" : "1073741824" + }, + "roles" : [ + "data", + "ingest", + "master", + "ml", + "transform" + ] + } + }, + "routing_state" : { + "routing_state" : "started" + }, + "inference_count" : 0, + "average_inference_time_ms" : 0.0 + }, + { + "node" : { + "DpCy7SOBQla3pu0Dq-tnYw" : { + "name" : "node2", + "ephemeral_id" : "17qcsXsNTYqbJ6uwSvdl9g", + "transport_address" : "10.142.0.2:9352", + "attributes" : { + "ml.machine_memory" : "15599742976", + "xpack.installed" : "true", + "ml.max_jvm_size" : "1073741824" + }, + "roles" : [ + "data", + "master", + "ml", + "transform" + ] + } + }, + "routing_state" : { + "routing_state" : "failed", + "reason" : "The object cannot be set twice!" + } + }, + { + "node" : { + "pt7s6lKHQJaP4QHKtU-Q0Q" : { + "name" : "node1", + "ephemeral_id" : "nMJBE9WSRQSWotk0zDPi_Q", + "transport_address" : "10.142.0.2:9351", + "attributes" : { + "ml.machine_memory" : "15599742976", + "xpack.installed" : "true", + "ml.max_jvm_size" : "1073741824" + }, + "roles" : [ + "data", + "master", + "ml" + ] + } + }, + "routing_state" : { + "routing_state" : "started" + }, + "inference_count" : 0, + "average_inference_time_ms" : 0.0 + } + ] + }, + { + "model_id" : "typeform__mobilebert-uncased-mnli", + "model_size_bytes" : 100139008, + "inference_threads" : 1, + "model_threads" : 1, + "state" : "started", + "allocation_status" : { + "allocation_count" : 2, + "target_allocation_count" : 3, + "state" : "started" + }, + "nodes" : [ + { + "node" : { + "3qIoLFnbSi-DwVrYioUCdw" : { + "name" : "node3", + "ephemeral_id" : "WeA49KLuRPmJM_ulLx0ANg", + "transport_address" : "10.142.0.2:9353", + "attributes" : { + "ml.machine_memory" : "15599742976", + "xpack.installed" : "true", + "ml.max_jvm_size" : "1073741824" + }, + "roles" : [ + "data", + "ingest", + "master", + "ml", + "transform" + ] + } + }, + "routing_state" : { + "routing_state" : "started" + }, + "inference_count" : 0, + "average_inference_time_ms" : 0.0 + }, + { + "node" : { + "DpCy7SOBQla3pu0Dq-tnYw" : { + "name" : "node2", + "ephemeral_id" : "17qcsXsNTYqbJ6uwSvdl9g", + "transport_address" : "10.142.0.2:9352", + "attributes" : { + "ml.machine_memory" : "15599742976", + "xpack.installed" : "true", + "ml.max_jvm_size" : "1073741824" + }, + "roles" : [ + "data", + "master", + "ml", + "transform" + ] + } + }, + "routing_state" : { + "routing_state" : "failed", + "reason" : "The object cannot be set twice!" + } + }, + { + "node" : { + "pt7s6lKHQJaP4QHKtU-Q0Q" : { + "name" : "node1", + "ephemeral_id" : "nMJBE9WSRQSWotk0zDPi_Q", + "transport_address" : "10.142.0.2:9351", + "attributes" : { + "ml.machine_memory" : "15599742976", + "xpack.installed" : "true", + "ml.max_jvm_size" : "1073741824" + }, + "roles" : [ + "data", + "master", + "ml" + ] + } + }, + "routing_state" : { + "routing_state" : "started" + }, + "inference_count" : 0, + "average_inference_time_ms" : 0.0 + } + ] + } + ] +} diff --git a/x-pack/plugins/ml/server/models/data_frame_analytics/model_provider.test.ts b/x-pack/plugins/ml/server/models/data_frame_analytics/model_provider.test.ts new file mode 100644 index 0000000000000..fed049a3c3baf --- /dev/null +++ b/x-pack/plugins/ml/server/models/data_frame_analytics/model_provider.test.ts @@ -0,0 +1,503 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { ModelService, modelsProvider } from './models_provider'; +import { IScopedClusterClient } from 'kibana/server'; +import { MlClient } from '../../lib/ml_client'; +import mockResponse from './__mocks__/mock_deployment_response.json'; +import { MemoryOverviewService } from '../memory_overview/memory_overview_service'; + +describe('Model service', () => { + const client = { + asCurrentUser: { + nodes: { + stats: jest.fn(() => { + return Promise.resolve({ + body: { + _nodes: { + total: 3, + successful: 3, + failed: 0, + }, + cluster_name: 'test_cluster', + nodes: { + '3qIoLFnbSi-DwVrYioUCdw': { + timestamp: 1635167166946, + name: 'node3', + transport_address: '10.10.10.2:9353', + host: '10.10.10.2', + ip: '10.10.10.2:9353', + roles: ['data', 'ingest', 'master', 'ml', 'transform'], + attributes: { + 'ml.machine_memory': '15599742976', + 'xpack.installed': 'true', + 'ml.max_jvm_size': '1073741824', + }, + os: { + mem: { + total_in_bytes: 15599742976, + adjusted_total_in_bytes: 15599742976, + free_in_bytes: 376324096, + used_in_bytes: 15223418880, + free_percent: 2, + used_percent: 98, + }, + }, + }, + 'DpCy7SOBQla3pu0Dq-tnYw': { + timestamp: 1635167166946, + name: 'node2', + transport_address: '10.10.10.2:9352', + host: '10.10.10.2', + ip: '10.10.10.2:9352', + roles: ['data', 'master', 'ml', 'transform'], + attributes: { + 'ml.machine_memory': '15599742976', + 'xpack.installed': 'true', + 'ml.max_jvm_size': '1073741824', + }, + os: { + timestamp: 1635167166959, + mem: { + total_in_bytes: 15599742976, + adjusted_total_in_bytes: 15599742976, + free_in_bytes: 376324096, + used_in_bytes: 15223418880, + free_percent: 2, + used_percent: 98, + }, + }, + }, + 'pt7s6lKHQJaP4QHKtU-Q0Q': { + timestamp: 1635167166945, + name: 'node1', + transport_address: '10.10.10.2:9351', + host: '10.10.10.2', + ip: '10.10.10.2:9351', + roles: ['data', 'master', 'ml'], + attributes: { + 'ml.machine_memory': '15599742976', + 'xpack.installed': 'true', + 'ml.max_jvm_size': '1073741824', + }, + os: { + timestamp: 1635167166959, + mem: { + total_in_bytes: 15599742976, + adjusted_total_in_bytes: 15599742976, + free_in_bytes: 376324096, + used_in_bytes: 15223418880, + free_percent: 2, + used_percent: 98, + }, + }, + }, + }, + }, + }); + }), + }, + }, + } as unknown as jest.Mocked; + const mlClient = { + getTrainedModelsDeploymentStats: jest.fn(() => { + return Promise.resolve({ body: mockResponse }); + }), + } as unknown as jest.Mocked; + const memoryOverviewService = { + getDFAMemoryOverview: jest.fn(() => { + return Promise.resolve([{ job_id: '', node_id: '', model_size: 32165465 }]); + }), + getAnomalyDetectionMemoryOverview: jest.fn(() => { + return Promise.resolve([{ job_id: '', node_id: '', model_size: 32165465 }]); + }), + } as unknown as jest.Mocked; + + let service: ModelService; + + beforeEach(() => { + service = modelsProvider(client, mlClient, memoryOverviewService); + }); + + afterEach(() => {}); + + it('extract nodes list correctly', async () => { + expect(await service.getNodesOverview()).toEqual({ + count: 3, + nodes: [ + { + name: 'node3', + allocated_models: [ + { + allocation_status: { + allocation_count: 2, + state: 'started', + target_allocation_count: 3, + }, + inference_threads: 1, + model_id: 'distilbert-base-uncased-finetuned-sst-2-english', + model_size_bytes: 267386880, + model_threads: 1, + state: 'started', + node: { + average_inference_time_ms: 0, + inference_count: 0, + routing_state: { + routing_state: 'started', + }, + }, + }, + { + allocation_status: { + allocation_count: 2, + state: 'started', + target_allocation_count: 3, + }, + inference_threads: 1, + model_id: 'elastic__distilbert-base-cased-finetuned-conll03-english', + model_size_bytes: 260947500, + model_threads: 1, + state: 'started', + node: { + average_inference_time_ms: 0, + inference_count: 0, + routing_state: { + routing_state: 'started', + }, + }, + }, + { + allocation_status: { + allocation_count: 2, + state: 'started', + target_allocation_count: 3, + }, + inference_threads: 1, + model_id: 'sentence-transformers__msmarco-minilm-l-12-v3', + model_size_bytes: 133378867, + model_threads: 1, + state: 'started', + node: { + average_inference_time_ms: 0, + inference_count: 0, + routing_state: { + routing_state: 'started', + }, + }, + }, + { + allocation_status: { + allocation_count: 2, + state: 'started', + target_allocation_count: 3, + }, + inference_threads: 1, + model_id: 'typeform__mobilebert-uncased-mnli', + model_size_bytes: 100139008, + model_threads: 1, + state: 'started', + node: { + average_inference_time_ms: 0, + inference_count: 0, + routing_state: { + routing_state: 'started', + }, + }, + }, + ], + attributes: { + 'ml.machine_memory': '15599742976', + 'ml.max_jvm_size': '1073741824', + 'xpack.installed': 'true', + }, + host: '10.10.10.2', + id: '3qIoLFnbSi-DwVrYioUCdw', + ip: '10.10.10.2:9353', + memory_overview: { + anomaly_detection: { + total: 0, + }, + dfa_training: { + total: 0, + }, + machine_memory: { + jvm: 1073741824, + total: 15599742976, + }, + trained_models: { + by_model: [ + { + model_id: 'distilbert-base-uncased-finetuned-sst-2-english', + model_size: 267386880, + }, + { + model_id: 'elastic__distilbert-base-cased-finetuned-conll03-english', + model_size: 260947500, + }, + { + model_id: 'sentence-transformers__msmarco-minilm-l-12-v3', + model_size: 133378867, + }, + { + model_id: 'typeform__mobilebert-uncased-mnli', + model_size: 100139008, + }, + ], + total: 793309535, + }, + }, + roles: ['data', 'ingest', 'master', 'ml', 'transform'], + transport_address: '10.10.10.2:9353', + }, + { + name: 'node2', + allocated_models: [ + { + allocation_status: { + allocation_count: 2, + state: 'started', + target_allocation_count: 3, + }, + inference_threads: 1, + model_id: 'distilbert-base-uncased-finetuned-sst-2-english', + model_size_bytes: 267386880, + model_threads: 1, + state: 'started', + node: { + routing_state: { + reason: 'The object cannot be set twice!', + routing_state: 'failed', + }, + }, + }, + { + allocation_status: { + allocation_count: 2, + state: 'started', + target_allocation_count: 3, + }, + inference_threads: 1, + model_id: 'elastic__distilbert-base-cased-finetuned-conll03-english', + model_size_bytes: 260947500, + model_threads: 1, + state: 'started', + node: { + routing_state: { + reason: 'The object cannot be set twice!', + routing_state: 'failed', + }, + }, + }, + { + allocation_status: { + allocation_count: 2, + state: 'started', + target_allocation_count: 3, + }, + inference_threads: 1, + model_id: 'sentence-transformers__msmarco-minilm-l-12-v3', + model_size_bytes: 133378867, + model_threads: 1, + state: 'started', + node: { + routing_state: { + reason: 'The object cannot be set twice!', + routing_state: 'failed', + }, + }, + }, + { + allocation_status: { + allocation_count: 2, + state: 'started', + target_allocation_count: 3, + }, + inference_threads: 1, + model_id: 'typeform__mobilebert-uncased-mnli', + model_size_bytes: 100139008, + model_threads: 1, + state: 'started', + node: { + routing_state: { + reason: 'The object cannot be set twice!', + routing_state: 'failed', + }, + }, + }, + ], + attributes: { + 'ml.machine_memory': '15599742976', + 'ml.max_jvm_size': '1073741824', + 'xpack.installed': 'true', + }, + host: '10.10.10.2', + id: 'DpCy7SOBQla3pu0Dq-tnYw', + ip: '10.10.10.2:9352', + memory_overview: { + anomaly_detection: { + total: 0, + }, + dfa_training: { + total: 0, + }, + machine_memory: { + jvm: 1073741824, + total: 15599742976, + }, + trained_models: { + by_model: [ + { + model_id: 'distilbert-base-uncased-finetuned-sst-2-english', + model_size: 267386880, + }, + { + model_id: 'elastic__distilbert-base-cased-finetuned-conll03-english', + model_size: 260947500, + }, + { + model_id: 'sentence-transformers__msmarco-minilm-l-12-v3', + model_size: 133378867, + }, + { + model_id: 'typeform__mobilebert-uncased-mnli', + model_size: 100139008, + }, + ], + total: 793309535, + }, + }, + roles: ['data', 'master', 'ml', 'transform'], + transport_address: '10.10.10.2:9352', + }, + { + allocated_models: [ + { + allocation_status: { + allocation_count: 2, + state: 'started', + target_allocation_count: 3, + }, + inference_threads: 1, + model_id: 'distilbert-base-uncased-finetuned-sst-2-english', + model_size_bytes: 267386880, + model_threads: 1, + state: 'started', + node: { + average_inference_time_ms: 0, + inference_count: 0, + routing_state: { + routing_state: 'started', + }, + }, + }, + { + allocation_status: { + allocation_count: 2, + state: 'started', + target_allocation_count: 3, + }, + inference_threads: 1, + model_id: 'elastic__distilbert-base-cased-finetuned-conll03-english', + model_size_bytes: 260947500, + model_threads: 1, + state: 'started', + node: { + average_inference_time_ms: 0, + inference_count: 0, + routing_state: { + routing_state: 'started', + }, + }, + }, + { + allocation_status: { + allocation_count: 2, + state: 'started', + target_allocation_count: 3, + }, + inference_threads: 1, + model_id: 'sentence-transformers__msmarco-minilm-l-12-v3', + model_size_bytes: 133378867, + model_threads: 1, + state: 'started', + node: { + average_inference_time_ms: 0, + inference_count: 0, + routing_state: { + routing_state: 'started', + }, + }, + }, + { + allocation_status: { + allocation_count: 2, + state: 'started', + target_allocation_count: 3, + }, + inference_threads: 1, + model_id: 'typeform__mobilebert-uncased-mnli', + model_size_bytes: 100139008, + model_threads: 1, + state: 'started', + node: { + average_inference_time_ms: 0, + inference_count: 0, + routing_state: { + routing_state: 'started', + }, + }, + }, + ], + attributes: { + 'ml.machine_memory': '15599742976', + 'ml.max_jvm_size': '1073741824', + 'xpack.installed': 'true', + }, + host: '10.10.10.2', + id: 'pt7s6lKHQJaP4QHKtU-Q0Q', + ip: '10.10.10.2:9351', + memory_overview: { + anomaly_detection: { + total: 0, + }, + dfa_training: { + total: 0, + }, + machine_memory: { + jvm: 1073741824, + total: 15599742976, + }, + trained_models: { + by_model: [ + { + model_id: 'distilbert-base-uncased-finetuned-sst-2-english', + model_size: 267386880, + }, + { + model_id: 'elastic__distilbert-base-cased-finetuned-conll03-english', + model_size: 260947500, + }, + { + model_id: 'sentence-transformers__msmarco-minilm-l-12-v3', + model_size: 133378867, + }, + { + model_id: 'typeform__mobilebert-uncased-mnli', + model_size: 100139008, + }, + ], + total: 793309535, + }, + }, + name: 'node1', + roles: ['data', 'master', 'ml'], + transport_address: '10.10.10.2:9351', + }, + ], + }); + }); +}); diff --git a/x-pack/plugins/ml/server/models/data_frame_analytics/models_provider.ts b/x-pack/plugins/ml/server/models/data_frame_analytics/models_provider.ts index 84f0fbaea0579..9ff57b13be5e1 100644 --- a/x-pack/plugins/ml/server/models/data_frame_analytics/models_provider.ts +++ b/x-pack/plugins/ml/server/models/data_frame_analytics/models_provider.ts @@ -5,10 +5,39 @@ * 2.0. */ -import { IScopedClusterClient } from 'kibana/server'; -import { PipelineDefinition } from '../../../common/types/trained_models'; +import type { IScopedClusterClient } from 'kibana/server'; +import { sumBy, pick } from 'lodash'; +import { NodesInfoNodeInfo } from '@elastic/elasticsearch/api/types'; +import type { + NodeDeploymentStatsResponse, + PipelineDefinition, + NodesOverviewResponse, +} from '../../../common/types/trained_models'; +import type { MlClient } from '../../lib/ml_client'; +import { + MemoryOverviewService, + NATIVE_EXECUTABLE_CODE_OVERHEAD, +} from '../memory_overview/memory_overview_service'; -export function modelsProvider(client: IScopedClusterClient) { +export type ModelService = ReturnType; + +const NODE_FIELDS = [ + 'attributes', + 'name', + 'roles', + 'ip', + 'host', + 'transport_address', + 'version', +] as const; + +export type RequiredNodeFields = Pick; + +export function modelsProvider( + client: IScopedClusterClient, + mlClient: MlClient, + memoryOverviewService?: MemoryOverviewService +) { return { /** * Retrieves the map of model ids and aliases with associated pipelines. @@ -39,5 +68,105 @@ export function modelsProvider(client: IScopedClusterClient) { return modelIdsMap; }, + + /** + * Provides the ML nodes overview with allocated models. + */ + async getNodesOverview(): Promise { + if (!memoryOverviewService) { + throw new Error('Memory overview service is not provided'); + } + + const { body: deploymentStats } = await mlClient.getTrainedModelsDeploymentStats(); + + const { + body: { nodes: clusterNodes }, + } = await client.asCurrentUser.nodes.stats(); + + const mlNodes = Object.entries(clusterNodes).filter(([id, node]) => + node.roles.includes('ml') + ); + + const adMemoryReport = await memoryOverviewService.getAnomalyDetectionMemoryOverview(); + const dfaMemoryReport = await memoryOverviewService.getDFAMemoryOverview(); + + const nodeDeploymentStatsResponses: NodeDeploymentStatsResponse[] = mlNodes.map( + ([nodeId, node]) => { + const nodeFields = pick(node, NODE_FIELDS) as RequiredNodeFields; + + const allocatedModels = deploymentStats.deployment_stats + .filter((v) => v.nodes.some((n) => Object.keys(n.node)[0] === nodeId)) + .map(({ nodes, ...rest }) => { + const { node: tempNode, ...nodeRest } = nodes.find( + (v) => Object.keys(v.node)[0] === nodeId + )!; + return { + ...rest, + node: nodeRest, + }; + }); + + const modelsMemoryUsage = allocatedModels.map((v) => { + return { + model_id: v.model_id, + model_size: v.model_size_bytes, + }; + }); + + const memoryRes = { + adTotalMemory: sumBy( + adMemoryReport.filter((ad) => ad.node_id === nodeId), + 'model_size' + ), + dfaTotalMemory: sumBy( + dfaMemoryReport.filter((dfa) => dfa.node_id === nodeId), + 'model_size' + ), + trainedModelsTotalMemory: sumBy(modelsMemoryUsage, 'model_size'), + }; + + for (const key of Object.keys(memoryRes)) { + if (memoryRes[key as keyof typeof memoryRes] > 0) { + /** + * The amount of memory needed to load the ML native code shared libraries. The assumption is that the first + * ML job to run on a given node will do this, and then subsequent ML jobs on the same node will reuse the + * same already-loaded code. + */ + memoryRes[key as keyof typeof memoryRes] += NATIVE_EXECUTABLE_CODE_OVERHEAD; + break; + } + } + + return { + id: nodeId, + ...nodeFields, + allocated_models: allocatedModels, + memory_overview: { + machine_memory: { + // TODO remove ts-ignore when elasticsearch client is updated + // @ts-ignore + total: Number(node.os?.mem.adjusted_total_in_bytes ?? node.os?.mem.total_in_bytes), + jvm: Number(node.attributes['ml.max_jvm_size']), + }, + anomaly_detection: { + total: memoryRes.adTotalMemory, + }, + dfa_training: { + total: memoryRes.dfaTotalMemory, + }, + trained_models: { + total: memoryRes.trainedModelsTotalMemory, + by_model: modelsMemoryUsage, + }, + }, + }; + } + ); + + return { + count: nodeDeploymentStatsResponses.length, + nodes: nodeDeploymentStatsResponses, + }; + }, }; } diff --git a/x-pack/plugins/ml/server/models/memory_overview/index.ts b/x-pack/plugins/ml/server/models/memory_overview/index.ts new file mode 100644 index 0000000000000..038b1cd8d4b80 --- /dev/null +++ b/x-pack/plugins/ml/server/models/memory_overview/index.ts @@ -0,0 +1,8 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export { memoryOverviewServiceProvider } from './memory_overview_service'; diff --git a/x-pack/plugins/ml/server/models/memory_overview/memory_overview_service.ts b/x-pack/plugins/ml/server/models/memory_overview/memory_overview_service.ts new file mode 100644 index 0000000000000..964e0ba595ecc --- /dev/null +++ b/x-pack/plugins/ml/server/models/memory_overview/memory_overview_service.ts @@ -0,0 +1,90 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import numeral from '@elastic/numeral'; +import { keyBy } from 'lodash'; +import { MlClient } from '../../lib/ml_client'; + +export type MemoryOverviewService = ReturnType; + +export interface MlJobMemoryOverview { + job_id: string; + node_id: string; + model_size: number; +} + +const MB = Math.pow(2, 20); + +const AD_PROCESS_MEMORY_OVERHEAD = 10 * MB; +const DFA_PROCESS_MEMORY_OVERHEAD = 5 * MB; +export const NATIVE_EXECUTABLE_CODE_OVERHEAD = 30 * MB; + +/** + * Provides a service for memory overview across ML. + * @param mlClient + */ +export function memoryOverviewServiceProvider(mlClient: MlClient) { + return { + /** + * Retrieves memory consumed my started DFA jobs. + */ + async getDFAMemoryOverview(): Promise { + const { + body: { data_frame_analytics: dfaStats }, + } = await mlClient.getDataFrameAnalyticsStats(); + + const dfaMemoryReport = dfaStats + .filter((dfa) => dfa.state === 'started') + .map((dfa) => { + return { + node_id: dfa.node?.id, + job_id: dfa.id, + }; + }) as MlJobMemoryOverview[]; + + if (dfaMemoryReport.length === 0) { + return []; + } + + const dfaMemoryKeyByJobId = keyBy(dfaMemoryReport, 'job_id'); + + const { + body: { data_frame_analytics: startedDfaJobs }, + } = await mlClient.getDataFrameAnalytics({ + id: dfaMemoryReport.map((v) => v.job_id).join(','), + }); + + startedDfaJobs.forEach((dfa) => { + dfaMemoryKeyByJobId[dfa.id].model_size = + numeral( + dfa.model_memory_limit?.toUpperCase() + // @ts-ignore + ).value() + DFA_PROCESS_MEMORY_OVERHEAD; + }); + + return dfaMemoryReport; + }, + /** + * Retrieves memory consumed by opened Anomaly Detection jobs. + */ + async getAnomalyDetectionMemoryOverview(): Promise { + const { + body: { jobs: jobsStats }, + } = await mlClient.getJobStats(); + + return jobsStats + .filter((v) => v.state === 'opened') + .map((jobStats) => { + return { + node_id: jobStats.node.id, + model_size: jobStats.model_size_stats.model_bytes + AD_PROCESS_MEMORY_OVERHEAD, + job_id: jobStats.job_id, + }; + }); + }, + }; +} diff --git a/x-pack/plugins/ml/server/routes/apidoc.json b/x-pack/plugins/ml/server/routes/apidoc.json index 226b69e06b48a..77e5443d0a257 100644 --- a/x-pack/plugins/ml/server/routes/apidoc.json +++ b/x-pack/plugins/ml/server/routes/apidoc.json @@ -123,7 +123,7 @@ "GetJobAuditMessages", "GetAllJobAuditMessages", "ClearJobAuditMessages", - + "JobValidation", "EstimateBucketSpan", "CalculateModelMemoryLimit", @@ -160,7 +160,11 @@ "TrainedModels", "GetTrainedModel", "GetTrainedModelStats", + "GetTrainedModelDeploymentStats", + "GetTrainedModelsNodesOverview", "GetTrainedModelPipelines", + "StartTrainedModelDeployment", + "StopTrainedModelDeployment", "DeleteTrainedModel", "Alerting", diff --git a/x-pack/plugins/ml/server/routes/trained_models.ts b/x-pack/plugins/ml/server/routes/trained_models.ts index 106010d0f7550..4c68139d65be4 100644 --- a/x-pack/plugins/ml/server/routes/trained_models.ts +++ b/x-pack/plugins/ml/server/routes/trained_models.ts @@ -14,6 +14,7 @@ import { } from './schemas/inference_schema'; import { modelsProvider } from '../models/data_frame_analytics'; import { TrainedModelConfigResponse } from '../../common/types/trained_models'; +import { memoryOverviewServiceProvider } from '../models/memory_overview'; export function trainedModelsRoutes({ router, routeGuard }: RouteInitialization) { /** @@ -44,6 +45,8 @@ export function trainedModelsRoutes({ router, routeGuard }: RouteInitialization) ...query, ...(modelId ? { model_id: modelId } : {}), }); + // model_type is missing + // @ts-ignore const result = body.trained_model_configs as TrainedModelConfigResponse[]; try { if (withPipelines) { @@ -57,7 +60,7 @@ export function trainedModelsRoutes({ router, routeGuard }: RouteInitialization) ) ); - const pipelinesResponse = await modelsProvider(client).getModelsPipelines( + const pipelinesResponse = await modelsProvider(client, mlClient).getModelsPipelines( modelIdsAndAliases ); for (const model of result) { @@ -136,10 +139,12 @@ export function trainedModelsRoutes({ router, routeGuard }: RouteInitialization) tags: ['access:ml:canGetDataFrameAnalytics'], }, }, - routeGuard.fullLicenseAPIGuard(async ({ client, request, response }) => { + routeGuard.fullLicenseAPIGuard(async ({ client, request, mlClient, response }) => { try { const { modelId } = request.params; - const result = await modelsProvider(client).getModelsPipelines(modelId.split(',')); + const result = await modelsProvider(client, mlClient).getModelsPipelines( + modelId.split(',') + ); return response.ok({ body: [...result].map(([id, pipelines]) => ({ model_id: id, pipelines })), }); @@ -180,4 +185,132 @@ export function trainedModelsRoutes({ router, routeGuard }: RouteInitialization) } }) ); + + /** + * @apiGroup TrainedModels + * + * @api {get} /api/ml/trained_models/nodes_overview Get node overview about the models allocation + * @apiName GetTrainedModelsNodesOverview + * @apiDescription Retrieves the list of ML nodes with memory breakdown and allocated models info + */ + router.get( + { + path: '/api/ml/trained_models/nodes_overview', + validate: {}, + options: { + tags: ['access:ml:canGetDataFrameAnalytics'], + }, + }, + routeGuard.fullLicenseAPIGuard(async ({ client, mlClient, request, response }) => { + try { + const memoryOverviewService = memoryOverviewServiceProvider(mlClient); + const result = await modelsProvider( + client, + mlClient, + memoryOverviewService + ).getNodesOverview(); + return response.ok({ + body: result, + }); + } catch (e) { + return response.customError(wrapError(e)); + } + }) + ); + + /** + * @apiGroup TrainedModels + * + * @api {post} /api/ml/trained_models/:modelId/deployment/_start Start trained model deployment + * @apiName StartTrainedModelDeployment + * @apiDescription Starts trained model deployment. + */ + router.post( + { + path: '/api/ml/trained_models/{modelId}/deployment/_start', + validate: { + params: modelIdSchema, + }, + options: { + tags: ['access:ml:canGetDataFrameAnalytics'], + }, + }, + routeGuard.fullLicenseAPIGuard(async ({ mlClient, request, response }) => { + try { + const { modelId } = request.params; + const { body } = await mlClient.startTrainedModelDeployment({ + model_id: modelId, + }); + return response.ok({ + body, + }); + } catch (e) { + return response.customError(wrapError(e)); + } + }) + ); + + /** + * @apiGroup TrainedModels + * + * @api {post} /api/ml/trained_models/:modelId/deployment/_stop Stop trained model deployment + * @apiName StopTrainedModelDeployment + * @apiDescription Stops trained model deployment. + */ + router.post( + { + path: '/api/ml/trained_models/{modelId}/deployment/_stop', + validate: { + params: modelIdSchema, + }, + options: { + tags: ['access:ml:canGetDataFrameAnalytics'], + }, + }, + routeGuard.fullLicenseAPIGuard(async ({ mlClient, request, response }) => { + try { + const { modelId } = request.params; + const { body } = await mlClient.stopTrainedModelDeployment({ + model_id: modelId, + }); + return response.ok({ + body, + }); + } catch (e) { + return response.customError(wrapError(e)); + } + }) + ); + + /** + * @apiGroup TrainedModels + * + * @api {get} /api/ml/trained_models/:modelId/deployment/_stats Get trained model deployment stats + * @apiName GetTrainedModelDeploymentStats + * @apiDescription Gets trained model deployment stats. + */ + router.get( + { + path: '/api/ml/trained_models/{modelId}/deployment/_stats', + validate: { + params: modelIdSchema, + }, + options: { + tags: ['access:ml:canGetDataFrameAnalytics'], + }, + }, + routeGuard.fullLicenseAPIGuard(async ({ mlClient, request, response }) => { + try { + const { modelId } = request.params; + const { body } = await mlClient.getTrainedModelsDeploymentStats({ + model_id: modelId, + }); + return response.ok({ + body, + }); + } catch (e) { + return response.customError(wrapError(e)); + } + }) + ); } diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 0ca4d2ae81f13..dd246772dcd14 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -15837,14 +15837,12 @@ "xpack.ml.dataframe.analyticsMap.modelIdTitle": "学習済みモデル ID {modelId} のマップ", "xpack.ml.dataframe.jobsTabLabel": "ジョブ", "xpack.ml.dataframe.mapTabLabel": "マップ", - "xpack.ml.dataframe.modelsTabLabel": "モデル", "xpack.ml.dataframe.stepDetailsForm.destinationIndexInvalidErrorLink": "インデックス名の制限に関する詳細。", "xpack.ml.dataFrameAnalyticsBreadcrumbs.analyticsMapLabel": "分析マップ", "xpack.ml.dataFrameAnalyticsBreadcrumbs.dataFrameExplorationLabel": "探索", "xpack.ml.dataFrameAnalyticsBreadcrumbs.dataFrameListLabel": "ジョブ管理", "xpack.ml.dataFrameAnalyticsBreadcrumbs.dataFrameManagementLabel": "データフレーム分析", "xpack.ml.dataFrameAnalyticsBreadcrumbs.indexLabel": "インデックス", - "xpack.ml.dataFrameAnalyticsBreadcrumbs.modelsListLabel": "モデル管理", "xpack.ml.dataFrameAnalyticsLabel": "データフレーム分析", "xpack.ml.dataFrameAnalyticsTabLabel": "データフレーム分析", "xpack.ml.dataGrid.CcsWarningCalloutBody": "インデックスパターンのデータの取得中に問題が発生しました。ソースプレビューとクラスター横断検索を組み合わせることは、バージョン7.10以上ではサポートされていません。変換を構成して作成することはできます。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index b7d5804f9e17a..ea98ec8c433bf 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -16039,7 +16039,6 @@ "xpack.ml.dataframe.analyticsMap.modelIdTitle": "已训练模型 ID {modelId} 的地图", "xpack.ml.dataframe.jobsTabLabel": "作业", "xpack.ml.dataframe.mapTabLabel": "地图", - "xpack.ml.dataframe.modelsTabLabel": "模型", "xpack.ml.dataframe.stepCreateForm.createDataFrameAnalyticsSuccessMessage": "数据帧分析 {jobId} 创建请求已确认。", "xpack.ml.dataframe.stepDetailsForm.destinationIndexInvalidErrorLink": "详细了解索引名称限制。", "xpack.ml.dataFrameAnalyticsBreadcrumbs.analyticsMapLabel": "分析地图", @@ -16047,7 +16046,6 @@ "xpack.ml.dataFrameAnalyticsBreadcrumbs.dataFrameListLabel": "作业管理", "xpack.ml.dataFrameAnalyticsBreadcrumbs.dataFrameManagementLabel": "数据帧分析", "xpack.ml.dataFrameAnalyticsBreadcrumbs.indexLabel": "索引", - "xpack.ml.dataFrameAnalyticsBreadcrumbs.modelsListLabel": "模型管理", "xpack.ml.dataFrameAnalyticsLabel": "数据帧分析", "xpack.ml.dataFrameAnalyticsTabLabel": "数据帧分析", "xpack.ml.dataGrid.CcsWarningCalloutBody": "检索索引模式的数据时有问题。源预览和跨集群搜索仅在 7.10 及以上版本上受支持。可能需要配置和创建转换。", diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/transform_rule_types/index.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/transform_rule_types/index.ts index 072e318da2df9..f743df169d417 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/transform_rule_types/index.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/transform_rule_types/index.ts @@ -10,7 +10,6 @@ import { FtrProviderContext } from '../../../../common/ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function alertingTests({ loadTestFile }: FtrProviderContext) { describe('transform alert rule types', function () { - this.tags('dima'); loadTestFile(require.resolve('./transform_health')); }); } diff --git a/x-pack/test/functional/apps/ml/data_frame_analytics/index.ts b/x-pack/test/functional/apps/ml/data_frame_analytics/index.ts index 4de95a5d82054..e7b5df70c99a0 100644 --- a/x-pack/test/functional/apps/ml/data_frame_analytics/index.ts +++ b/x-pack/test/functional/apps/ml/data_frame_analytics/index.ts @@ -16,6 +16,5 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./classification_creation')); loadTestFile(require.resolve('./cloning')); loadTestFile(require.resolve('./feature_importance')); - loadTestFile(require.resolve('./trained_models')); }); } diff --git a/x-pack/test/functional/apps/ml/index.ts b/x-pack/test/functional/apps/ml/index.ts index d4bf9a22367bf..ee14e3f414e36 100644 --- a/x-pack/test/functional/apps/ml/index.ts +++ b/x-pack/test/functional/apps/ml/index.ts @@ -50,6 +50,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./anomaly_detection')); loadTestFile(require.resolve('./data_visualizer')); loadTestFile(require.resolve('./data_frame_analytics')); + loadTestFile(require.resolve('./model_management')); }); describe('', function () { diff --git a/x-pack/test/functional/apps/ml/model_management/index.ts b/x-pack/test/functional/apps/ml/model_management/index.ts new file mode 100644 index 0000000000000..e958392d9ba74 --- /dev/null +++ b/x-pack/test/functional/apps/ml/model_management/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ loadTestFile }: FtrProviderContext) { + describe('model management', function () { + this.tags(['mlqa', 'skipFirefox']); + + loadTestFile(require.resolve('./model_list')); + }); +} diff --git a/x-pack/test/functional/apps/ml/data_frame_analytics/trained_models.ts b/x-pack/test/functional/apps/ml/model_management/model_list.ts similarity index 96% rename from x-pack/test/functional/apps/ml/data_frame_analytics/trained_models.ts rename to x-pack/test/functional/apps/ml/model_management/model_list.ts index b302e0bfb1140..955639dbe60a4 100644 --- a/x-pack/test/functional/apps/ml/data_frame_analytics/trained_models.ts +++ b/x-pack/test/functional/apps/ml/model_management/model_list.ts @@ -27,19 +27,19 @@ export default function ({ getService }: FtrProviderContext) { const builtInModelData = { modelId: 'lang_ident_model_1', description: 'Model used for identifying language from arbitrary input text.', - modelTypes: ['classification', 'built-in'], + modelTypes: ['classification', 'built-in', 'lang_ident'], }; const modelWithPipelineData = { modelId: 'dfa_classification_model_n_0', description: '', - modelTypes: ['classification'], + modelTypes: ['classification', 'tree_ensemble'], }; const modelWithoutPipelineData = { modelId: 'dfa_regression_model_n_0', description: '', - modelTypes: ['regression'], + modelTypes: ['regression', 'tree_ensemble'], }; it('renders trained models list', async () => { diff --git a/x-pack/test/functional/services/ml/navigation.ts b/x-pack/test/functional/services/ml/navigation.ts index ddd0950c610fd..0027405e4bf39 100644 --- a/x-pack/test/functional/services/ml/navigation.ts +++ b/x-pack/test/functional/services/ml/navigation.ts @@ -130,13 +130,24 @@ export function MachineLearningNavigationProvider({ await this.navigateToArea('~mlMainTab & ~dataFrameAnalytics', 'mlPageDataFrameAnalytics'); }, + async navigateToModelManagement() { + await this.navigateToArea('~mlMainTab & ~modelManagement', 'mlPageModelManagement'); + }, + async navigateToTrainedModels() { await this.navigateToMl(); - await this.navigateToDataFrameAnalytics(); + await this.navigateToModelManagement(); await testSubjects.click('mlTrainedModelsTab'); await testSubjects.existOrFail('mlModelsTableContainer'); }, + async navigateToModelManagementNodeList() { + await this.navigateToMl(); + await this.navigateToModelManagement(); + await testSubjects.click('mlNodesOverviewTab'); + await testSubjects.existOrFail('mlNodesTableContainer'); + }, + async navigateToDataVisualizer() { await this.navigateToArea('~mlMainTab & ~dataVisualizer', 'mlPageDataVisualizerSelector'); }, From 38a634d543b479f04da79d1b5f3c75188993b520 Mon Sep 17 00:00:00 2001 From: Nick Peihl Date: Tue, 26 Oct 2021 10:43:36 -0700 Subject: [PATCH 56/58] Use Elastic Maps Service v8.0 (#116217) --- package.json | 2 +- src/dev/license_checker/config.ts | 2 +- src/plugins/maps_ems/common/index.ts | 2 +- yarn.lock | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 264c0718a663e..3ecb64cf06dff 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "@elastic/charts": "38.0.1", "@elastic/datemath": "link:bazel-bin/packages/elastic-datemath", "@elastic/elasticsearch": "npm:@elastic/elasticsearch-canary@^8.0.0-canary.35", - "@elastic/ems-client": "7.16.0", + "@elastic/ems-client": "8.0.0", "@elastic/eui": "40.0.0", "@elastic/filesaver": "1.1.2", "@elastic/maki": "6.3.0", diff --git a/src/dev/license_checker/config.ts b/src/dev/license_checker/config.ts index 305eeb9a6a358..4c630ae1c10e1 100644 --- a/src/dev/license_checker/config.ts +++ b/src/dev/license_checker/config.ts @@ -74,7 +74,7 @@ export const DEV_ONLY_LICENSE_ALLOWED = ['MPL-2.0']; export const LICENSE_OVERRIDES = { 'jsts@1.6.2': ['Eclipse Distribution License - v 1.0'], // cf. https://github.com/bjornharrtell/jsts '@mapbox/jsonlint-lines-primitives@2.0.2': ['MIT'], // license in readme https://github.com/tmcw/jsonlint - '@elastic/ems-client@7.16.0': ['Elastic License 2.0'], + '@elastic/ems-client@8.0.0': ['Elastic License 2.0'], '@elastic/eui@40.0.0': ['SSPL-1.0 OR Elastic License 2.0'], 'language-subtag-registry@0.3.21': ['CC-BY-4.0'], // retired ODC‑By license https://github.com/mattcg/language-subtag-registry }; diff --git a/src/plugins/maps_ems/common/index.ts b/src/plugins/maps_ems/common/index.ts index 26fdb4fa795fe..acf27bb3a8a73 100644 --- a/src/plugins/maps_ems/common/index.ts +++ b/src/plugins/maps_ems/common/index.ts @@ -10,7 +10,7 @@ export const TMS_IN_YML_ID = 'TMS in config/kibana.yml'; export const DEFAULT_EMS_FILE_API_URL = 'https://vector.maps.elastic.co'; export const DEFAULT_EMS_TILE_API_URL = 'https://tiles.maps.elastic.co'; -export const DEFAULT_EMS_LANDING_PAGE_URL = 'https://maps.elastic.co/v7.16'; +export const DEFAULT_EMS_LANDING_PAGE_URL = 'https://maps.elastic.co/v8.0'; export const DEFAULT_EMS_FONT_LIBRARY_URL = 'https://tiles.maps.elastic.co/fonts/{fontstack}/{range}.pbf'; diff --git a/yarn.lock b/yarn.lock index 1fbfcdc605885..5825f6452c232 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2387,10 +2387,10 @@ "@elastic/transport" "^0.0.15" tslib "^2.3.0" -"@elastic/ems-client@7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@elastic/ems-client/-/ems-client-7.16.0.tgz#92db94126bac0b95fbf156fe609f68979e7af4b6" - integrity sha512-NgMB5vqj6I7lxVsysrz6eB1EW6gsZj7SWWs79WSiiKQeNuRg82tJhvbHQnWezjIS4UKOtoGxZsg475EHVZB46g== +"@elastic/ems-client@8.0.0": + version "8.0.0" + resolved "https://registry.yarnpkg.com/@elastic/ems-client/-/ems-client-8.0.0.tgz#94f682298f39f19d14a1eca927a22508029671e1" + integrity sha512-0nIEu+PHkWmTZUI27J/6BCPyY7bsmNTbDRn9EHPyciWq487G7TWoocoZog/mj1DoP2bo/ZxA8dpTKf6bJpy2Rg== dependencies: "@types/geojson" "^7946.0.7" "@types/lru-cache" "^5.1.0" From e185afefa2c579dc822a3a94bd80907611527c0a Mon Sep 17 00:00:00 2001 From: Xavier Mouligneau <189600+XavierM@users.noreply.github.com> Date: Tue, 26 Oct 2021 13:49:01 -0400 Subject: [PATCH 57/58] Register "minimal" feature privileges regardless of the current license level (#115992) * bring minimal-* privilege up * Fix api_integration for minimal_ * attempt to fix minimal_ UI * fix tests * Update x-pack/plugins/security/server/authorization/privileges/privileges.test.ts Co-authored-by: Larry Gregory * fix tests * fix es-lint Co-authored-by: Larry Gregory --- .../feature_table/feature_table.test.tsx | 8 ++-- .../privilege_form_calculator.ts | 8 ++-- .../privilege_summary_table.test.tsx | 8 ++-- .../management/roles/model/secured_feature.ts | 12 ++--- .../privileges/privileges.test.ts | 18 ++++++-- .../authorization/privileges/privileges.ts | 22 ++++----- .../apis/security/license_downgrade.ts | 2 +- .../apis/security/privileges.ts | 38 +++++++-------- .../apis/security/privileges_basic.ts | 46 +++++++++---------- 9 files changed, 84 insertions(+), 78 deletions(-) diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.test.tsx index 216409642289b..a7fab418f42cc 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.test.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/feature_table/feature_table.test.tsx @@ -678,7 +678,7 @@ describe('FeatureTable', () => { }); }); - it('renders with no privileges granted when minimal feature privileges are assigned, and sub-feature privileges are disallowed', () => { + it('renders with privileges granted when minimal feature privileges are assigned, and sub-feature privileges are disallowed', () => { const role = createRole([ { spaces: ['foo'], @@ -710,13 +710,13 @@ describe('FeatureTable', () => { subFeaturePrivileges: [], }, with_sub_features: { - primaryFeaturePrivilege: 'none', + primaryFeaturePrivilege: 'all', subFeaturePrivileges: [], }, }); }); - it('renders with no privileges granted when sub feature privileges are assigned, and sub-feature privileges are disallowed', () => { + it('renders with privileges granted when sub feature privileges are assigned, and sub-feature privileges are disallowed', () => { const role = createRole([ { spaces: ['foo'], @@ -748,7 +748,7 @@ describe('FeatureTable', () => { subFeaturePrivileges: [], }, with_sub_features: { - primaryFeaturePrivilege: 'none', + primaryFeaturePrivilege: 'read', subFeaturePrivileges: [], }, }); diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_form_calculator/privilege_form_calculator.ts b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_form_calculator/privilege_form_calculator.ts index f92d959a7208f..897ac36664f08 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_form_calculator/privilege_form_calculator.ts +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_form_calculator/privilege_form_calculator.ts @@ -278,13 +278,11 @@ export class PrivilegeFormCalculator { .getMinimalFeaturePrivileges() .find((mp) => mp.id === correspondingMinimalPrivilegeId)!; - // There are two cases where the minimal privileges aren't available: - // 1. The feature has no registered sub-features - // 2. Sub-feature privileges cannot be customized. When this is the case, the minimal privileges aren't registered with ES, + // There is only one case where the minimal privileges aren't available: + // 1. Sub-feature privileges cannot be customized. When this is the case, the minimal privileges aren't registered with ES, // so they end up represented in the UI as an empty privilege. Empty privileges cannot be granted other privileges, so if we // encounter a minimal privilege that isn't granted by it's correspending primary, then we know we've encountered this scenario. - const hasMinimalPrivileges = - feature.subFeatures.length > 0 && fp.grantsPrivilege(correspendingMinimalPrivilege); + const hasMinimalPrivileges = fp.grantsPrivilege(correspendingMinimalPrivilege); return ( selectedFeaturePrivileges.includes(fp.id) || (hasMinimalPrivileges && diff --git a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_summary/privilege_summary_table.test.tsx b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_summary/privilege_summary_table.test.tsx index 53a7084c7014e..93ed2d000bb0e 100644 --- a/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_summary/privilege_summary_table.test.tsx +++ b/x-pack/plugins/security/public/management/roles/edit_role/privileges/kibana/privilege_summary/privilege_summary_table.test.tsx @@ -426,7 +426,7 @@ describe('PrivilegeSummaryTable', () => { with_sub_features: { 'default, space-1': { hasCustomizedSubFeaturePrivileges: allowSubFeaturePrivileges, - primaryFeaturePrivilege: allowSubFeaturePrivileges ? 'Read' : 'None', + primaryFeaturePrivilege: 'Read', ...maybeExpectSubFeaturePrivileges(allowSubFeaturePrivileges, { 'Cool Sub Feature': [], }), @@ -693,7 +693,7 @@ describe('PrivilegeSummaryTable', () => { with_sub_features: { '*': { hasCustomizedSubFeaturePrivileges: allowSubFeaturePrivileges, - primaryFeaturePrivilege: allowSubFeaturePrivileges ? 'Read' : 'None', + primaryFeaturePrivilege: 'Read', ...maybeExpectSubFeaturePrivileges(allowSubFeaturePrivileges, { 'Cool Sub Feature': ['All'], }), @@ -787,7 +787,7 @@ describe('PrivilegeSummaryTable', () => { with_sub_features: { '*': { hasCustomizedSubFeaturePrivileges: allowSubFeaturePrivileges, - primaryFeaturePrivilege: allowSubFeaturePrivileges ? 'Read' : 'None', + primaryFeaturePrivilege: 'Read', ...maybeExpectSubFeaturePrivileges(allowSubFeaturePrivileges, { 'Cool Sub Feature': ['All'], }), @@ -859,7 +859,7 @@ describe('PrivilegeSummaryTable', () => { }, 'space-1, space-2': { hasCustomizedSubFeaturePrivileges: allowSubFeaturePrivileges, - primaryFeaturePrivilege: allowSubFeaturePrivileges ? 'All' : 'None', + primaryFeaturePrivilege: 'All', ...maybeExpectSubFeaturePrivileges(allowSubFeaturePrivileges, { 'Cool Sub Feature': ['Cool toggle 2'], }), diff --git a/x-pack/plugins/security/public/management/roles/model/secured_feature.ts b/x-pack/plugins/security/public/management/roles/model/secured_feature.ts index c5d879b9d2d54..d5fb7ef628657 100644 --- a/x-pack/plugins/security/public/management/roles/model/secured_feature.ts +++ b/x-pack/plugins/security/public/management/roles/model/secured_feature.ts @@ -29,14 +29,10 @@ export class SecuredFeature extends KibanaFeature { ([id, privilege]) => new PrimaryFeaturePrivilege(id, privilege, actionMapping[id]) ); - if (this.config.subFeatures?.length ?? 0 > 0) { - this.minimalPrimaryFeaturePrivileges = Object.entries(this.config.privileges || {}).map( - ([id, privilege]) => - new PrimaryFeaturePrivilege(`minimal_${id}`, privilege, actionMapping[`minimal_${id}`]) - ); - } else { - this.minimalPrimaryFeaturePrivileges = []; - } + this.minimalPrimaryFeaturePrivileges = Object.entries(this.config.privileges || {}).map( + ([id, privilege]) => + new PrimaryFeaturePrivilege(`minimal_${id}`, privilege, actionMapping[`minimal_${id}`]) + ); this.securedSubFeatures = this.config.subFeatures?.map((sf) => new SecuredSubFeature(sf, actionMapping)) ?? []; diff --git a/x-pack/plugins/security/server/authorization/privileges/privileges.test.ts b/x-pack/plugins/security/server/authorization/privileges/privileges.test.ts index 5264e74861be1..b15793527b7e5 100644 --- a/x-pack/plugins/security/server/authorization/privileges/privileges.test.ts +++ b/x-pack/plugins/security/server/authorization/privileges/privileges.test.ts @@ -60,6 +60,8 @@ describe('features', () => { expect(actual).toHaveProperty('features.foo-feature', { all: [actions.login, actions.version], read: [actions.login, actions.version], + minimal_all: [actions.login, actions.version], + minimal_read: [actions.login, actions.version], }); }); @@ -175,6 +177,8 @@ describe('features', () => { expect(actual).toHaveProperty('features.foo', { all: [...expectedAllPrivileges], read: [...expectedReadPrivileges], + minimal_all: [...expectedAllPrivileges], + minimal_read: [...expectedReadPrivileges], }); }); @@ -1627,7 +1631,7 @@ describe('subFeatures', () => { }); describe(`when license does not allow sub features`, () => { - test(`should augment the primary feature privileges, and should not create minimal or sub-feature privileges`, () => { + test(`should augment the primary feature privileges, and should not create sub-feature privileges`, () => { const features: KibanaFeature[] = [ new KibanaFeature({ id: 'foo', @@ -1705,7 +1709,11 @@ describe('subFeatures', () => { actions.ui.get('foo', 'sub-feature-ui'), ]); - expect(actual.features).not.toHaveProperty(`foo.minimal_all`); + expect(actual.features).toHaveProperty(`foo.minimal_all`, [ + actions.login, + actions.version, + actions.ui.get('foo', 'foo'), + ]); expect(actual.features).toHaveProperty(`foo.read`, [ actions.login, @@ -1730,7 +1738,11 @@ describe('subFeatures', () => { actions.ui.get('foo', 'sub-feature-ui'), ]); - expect(actual.features).not.toHaveProperty(`foo.minimal_read`); + expect(actual.features).toHaveProperty(`foo.minimal_read`, [ + actions.login, + actions.version, + actions.ui.get('foo', 'foo'), + ]); expect(actual).toHaveProperty('global.all', [ actions.login, diff --git a/x-pack/plugins/security/server/authorization/privileges/privileges.ts b/x-pack/plugins/security/server/authorization/privileges/privileges.ts index c38a5c9a44f57..0b2ab93c966c0 100644 --- a/x-pack/plugins/security/server/authorization/privileges/privileges.ts +++ b/x-pack/plugins/security/server/authorization/privileges/privileges.ts @@ -70,18 +70,18 @@ export function privilegesFactory( ]; } - if (allowSubFeaturePrivileges && feature.subFeatures?.length > 0) { - for (const featurePrivilege of featuresService.featurePrivilegeIterator(feature, { - augmentWithSubFeaturePrivileges: false, - licenseHasAtLeast, - })) { - featurePrivileges[feature.id][`minimal_${featurePrivilege.privilegeId}`] = [ - actions.login, - actions.version, - ...uniq(featurePrivilegeBuilder.getActions(featurePrivilege.privilege, feature)), - ]; - } + for (const featurePrivilege of featuresService.featurePrivilegeIterator(feature, { + augmentWithSubFeaturePrivileges: false, + licenseHasAtLeast, + })) { + featurePrivileges[feature.id][`minimal_${featurePrivilege.privilegeId}`] = [ + actions.login, + actions.version, + ...uniq(featurePrivilegeBuilder.getActions(featurePrivilege.privilege, feature)), + ]; + } + if (allowSubFeaturePrivileges && feature.subFeatures?.length > 0) { for (const subFeaturePrivilege of featuresService.subFeaturePrivilegeIterator( feature, licenseHasAtLeast diff --git a/x-pack/test/api_integration/apis/security/license_downgrade.ts b/x-pack/test/api_integration/apis/security/license_downgrade.ts index a56bb5908ca05..ad7fba3ac3d64 100644 --- a/x-pack/test/api_integration/apis/security/license_downgrade.ts +++ b/x-pack/test/api_integration/apis/security/license_downgrade.ts @@ -45,7 +45,7 @@ export default function ({ getService }: FtrProviderContext) { }); // Verify that privileges were re-registered. - const expectedBasicLicenseDiscoverPrivileges = ['all', 'read']; + const expectedBasicLicenseDiscoverPrivileges = ['all', 'read', 'minimal_all', 'minimal_read']; const basicPrivileges = await supertest .get('/api/security/privileges') .set('kbn-xsrf', 'xxx') diff --git a/x-pack/test/api_integration/apis/security/privileges.ts b/x-pack/test/api_integration/apis/security/privileges.ts index 4938334bb936b..95076fe01000a 100644 --- a/x-pack/test/api_integration/apis/security/privileges.ts +++ b/x-pack/test/api_integration/apis/security/privileges.ts @@ -24,21 +24,21 @@ export default function ({ getService }: FtrProviderContext) { global: ['all', 'read'], space: ['all', 'read'], features: { - graph: ['all', 'read'], - savedObjectsTagging: ['all', 'read'], - canvas: ['all', 'read'], - maps: ['all', 'read'], - observabilityCases: ['all', 'read'], - fleet: ['all', 'read'], - actions: ['all', 'read'], - stackAlerts: ['all', 'read'], - ml: ['all', 'read'], - siem: ['all', 'read'], - uptime: ['all', 'read'], - securitySolutionCases: ['all', 'read'], - infrastructure: ['all', 'read'], - logs: ['all', 'read'], - apm: ['all', 'read'], + graph: ['all', 'read', 'minimal_all', 'minimal_read'], + savedObjectsTagging: ['all', 'read', 'minimal_all', 'minimal_read'], + canvas: ['all', 'read', 'minimal_all', 'minimal_read'], + maps: ['all', 'read', 'minimal_all', 'minimal_read'], + observabilityCases: ['all', 'read', 'minimal_all', 'minimal_read'], + fleet: ['all', 'read', 'minimal_all', 'minimal_read'], + actions: ['all', 'read', 'minimal_all', 'minimal_read'], + stackAlerts: ['all', 'read', 'minimal_all', 'minimal_read'], + ml: ['all', 'read', 'minimal_all', 'minimal_read'], + siem: ['all', 'read', 'minimal_all', 'minimal_read'], + uptime: ['all', 'read', 'minimal_all', 'minimal_read'], + securitySolutionCases: ['all', 'read', 'minimal_all', 'minimal_read'], + infrastructure: ['all', 'read', 'minimal_all', 'minimal_read'], + logs: ['all', 'read', 'minimal_all', 'minimal_read'], + apm: ['all', 'read', 'minimal_all', 'minimal_read'], discover: [ 'all', 'read', @@ -56,10 +56,10 @@ export default function ({ getService }: FtrProviderContext) { 'url_create', 'store_search_session', ], - dev_tools: ['all', 'read'], - advancedSettings: ['all', 'read'], - indexPatterns: ['all', 'read'], - savedObjectsManagement: ['all', 'read'], + dev_tools: ['all', 'read', 'minimal_all', 'minimal_read'], + advancedSettings: ['all', 'read', 'minimal_all', 'minimal_read'], + indexPatterns: ['all', 'read', 'minimal_all', 'minimal_read'], + savedObjectsManagement: ['all', 'read', 'minimal_all', 'minimal_read'], osquery: [ 'all', 'read', diff --git a/x-pack/test/api_integration/apis/security/privileges_basic.ts b/x-pack/test/api_integration/apis/security/privileges_basic.ts index e6fe9d87af6f3..fc3d038c3965e 100644 --- a/x-pack/test/api_integration/apis/security/privileges_basic.ts +++ b/x-pack/test/api_integration/apis/security/privileges_basic.ts @@ -20,29 +20,29 @@ export default function ({ getService }: FtrProviderContext) { // Roles are associated with these privileges, and we shouldn't be removing them in a minor version. const expected = { features: { - discover: ['all', 'read'], - visualize: ['all', 'read'], - dashboard: ['all', 'read'], - dev_tools: ['all', 'read'], - advancedSettings: ['all', 'read'], - indexPatterns: ['all', 'read'], - savedObjectsManagement: ['all', 'read'], - savedObjectsTagging: ['all', 'read'], - graph: ['all', 'read'], - maps: ['all', 'read'], - observabilityCases: ['all', 'read'], - canvas: ['all', 'read'], - infrastructure: ['all', 'read'], - logs: ['all', 'read'], - uptime: ['all', 'read'], - apm: ['all', 'read'], - osquery: ['all', 'read'], - ml: ['all', 'read'], - siem: ['all', 'read'], - securitySolutionCases: ['all', 'read'], - fleet: ['all', 'read'], - stackAlerts: ['all', 'read'], - actions: ['all', 'read'], + discover: ['all', 'read', 'minimal_all', 'minimal_read'], + visualize: ['all', 'read', 'minimal_all', 'minimal_read'], + dashboard: ['all', 'read', 'minimal_all', 'minimal_read'], + dev_tools: ['all', 'read', 'minimal_all', 'minimal_read'], + advancedSettings: ['all', 'read', 'minimal_all', 'minimal_read'], + indexPatterns: ['all', 'read', 'minimal_all', 'minimal_read'], + savedObjectsManagement: ['all', 'read', 'minimal_all', 'minimal_read'], + savedObjectsTagging: ['all', 'read', 'minimal_all', 'minimal_read'], + graph: ['all', 'read', 'minimal_all', 'minimal_read'], + maps: ['all', 'read', 'minimal_all', 'minimal_read'], + observabilityCases: ['all', 'read', 'minimal_all', 'minimal_read'], + canvas: ['all', 'read', 'minimal_all', 'minimal_read'], + infrastructure: ['all', 'read', 'minimal_all', 'minimal_read'], + logs: ['all', 'read', 'minimal_all', 'minimal_read'], + uptime: ['all', 'read', 'minimal_all', 'minimal_read'], + apm: ['all', 'read', 'minimal_all', 'minimal_read'], + osquery: ['all', 'read', 'minimal_all', 'minimal_read'], + ml: ['all', 'read', 'minimal_all', 'minimal_read'], + siem: ['all', 'read', 'minimal_all', 'minimal_read'], + securitySolutionCases: ['all', 'read', 'minimal_all', 'minimal_read'], + fleet: ['all', 'read', 'minimal_all', 'minimal_read'], + stackAlerts: ['all', 'read', 'minimal_all', 'minimal_read'], + actions: ['all', 'read', 'minimal_all', 'minimal_read'], }, global: ['all', 'read'], space: ['all', 'read'], From 99d07acfcef99c01abb8849d004e9c7a5dc3310f Mon Sep 17 00:00:00 2001 From: Thom Heymann <190132+thomheymann@users.noreply.github.com> Date: Tue, 26 Oct 2021 19:03:00 +0100 Subject: [PATCH 58/58] Interactive setup functional tests (#115274) --- .github/CODEOWNERS | 1 + scripts/functional_tests.js | 8 ++ .../public/progress_indicator.tsx | 29 ++++-- .../server/kibana_config_writer.test.ts | 4 +- .../server/kibana_config_writer.ts | 6 +- ...l_configuration_flow_without_tls.config.ts | 1 - .../enrollment_token.config.ts | 57 ++++++++++++ .../manual_configuration.config.ts | 55 ++++++++++++ ...l_configuration_without_security.config.ts | 64 ++++++++++++++ ...manual_configuration_without_tls.config.ts | 52 +++++++++++ .../tests/enrollment_token.ts | 88 +++++++++++++++++++ .../tests/manual_configuration.ts | 67 ++++++++++++++ .../manual_configuration_without_security.ts | 53 +++++++++++ .../tests/manual_configuration_without_tls.ts | 61 +++++++++++++ 14 files changed, 534 insertions(+), 12 deletions(-) create mode 100644 test/interactive_setup_functional/enrollment_token.config.ts create mode 100644 test/interactive_setup_functional/manual_configuration.config.ts create mode 100644 test/interactive_setup_functional/manual_configuration_without_security.config.ts create mode 100644 test/interactive_setup_functional/manual_configuration_without_tls.config.ts create mode 100644 test/interactive_setup_functional/tests/enrollment_token.ts create mode 100644 test/interactive_setup_functional/tests/manual_configuration.ts create mode 100644 test/interactive_setup_functional/tests/manual_configuration_without_security.ts create mode 100644 test/interactive_setup_functional/tests/manual_configuration_without_tls.ts diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index a324b9f429b39..227041522ac78 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -289,6 +289,7 @@ /src/core/server/csp/ @elastic/kibana-security @elastic/kibana-core /src/plugins/interactive_setup/ @elastic/kibana-security /test/interactive_setup_api_integration/ @elastic/kibana-security +/test/interactive_setup_functional/ @elastic/kibana-security /x-pack/plugins/spaces/ @elastic/kibana-security /x-pack/plugins/encrypted_saved_objects/ @elastic/kibana-security /x-pack/plugins/security/ @elastic/kibana-security diff --git a/scripts/functional_tests.js b/scripts/functional_tests.js index 601ee3096e0b7..b286cf05a6d71 100644 --- a/scripts/functional_tests.js +++ b/scripts/functional_tests.js @@ -17,6 +17,14 @@ const alwaysImportedTests = [ require.resolve( '../test/interactive_setup_api_integration/manual_configuration_flow_without_tls.config.ts' ), + require.resolve('../test/interactive_setup_functional/enrollment_token.config.ts'), + require.resolve('../test/interactive_setup_functional/manual_configuration.config.ts'), + require.resolve( + '../test/interactive_setup_functional/manual_configuration_without_security.config.ts' + ), + require.resolve( + '../test/interactive_setup_functional/manual_configuration_without_tls.config.ts' + ), ]; // eslint-disable-next-line no-restricted-syntax const onlyNotInCoverageTests = [ diff --git a/src/plugins/interactive_setup/public/progress_indicator.tsx b/src/plugins/interactive_setup/public/progress_indicator.tsx index 44362554609c3..73f757246af53 100644 --- a/src/plugins/interactive_setup/public/progress_indicator.tsx +++ b/src/plugins/interactive_setup/public/progress_indicator.tsx @@ -16,31 +16,48 @@ import useTimeoutFn from 'react-use/lib/useTimeoutFn'; import { i18n } from '@kbn/i18n'; import type { IHttpFetchError } from 'kibana/public'; +import type { StatusResponse } from '../../../core/types/status'; import { useKibana } from './use_kibana'; export interface ProgressIndicatorProps { onSuccess?(): void; } +function isKibanaPastPreboot(response?: Response, body?: StatusResponse) { + if (!response?.headers.get('content-type')?.includes('application/json')) { + return false; + } + + return ( + // Status endpoint may require authentication after `preboot` stage. + response?.status === 401 || + // We're only interested in the availability of the critical core services. + (body?.status?.core?.elasticsearch?.level === 'available' && + body?.status?.core?.savedObjects?.level === 'available') + ); +} + export const ProgressIndicator: FunctionComponent = ({ onSuccess }) => { const { http } = useKibana(); const [status, checkStatus] = useAsyncFn(async () => { let isAvailable: boolean | undefined = false; let isPastPreboot: boolean | undefined = false; try { - const { response } = await http.get('/api/status', { asResponse: true }); + const { response, body } = await http.get('/api/status', { + asResponse: true, + }); isAvailable = response ? response.status < 500 : undefined; - isPastPreboot = response?.headers.get('content-type')?.includes('application/json'); + isPastPreboot = isKibanaPastPreboot(response, body); } catch (error) { - const { response } = error as IHttpFetchError; + const { response, body = {} } = error as IHttpFetchError; isAvailable = response ? response.status < 500 : undefined; - isPastPreboot = response?.headers.get('content-type')?.includes('application/json'); + isPastPreboot = isKibanaPastPreboot(response, body); } - return isAvailable === true && isPastPreboot === true + return isAvailable === true && isPastPreboot ? 'complete' : isAvailable === false ? 'unavailable' - : isAvailable === true && isPastPreboot === false + : isAvailable === true && !isPastPreboot ? 'preboot' : 'unknown'; }); diff --git a/src/plugins/interactive_setup/server/kibana_config_writer.test.ts b/src/plugins/interactive_setup/server/kibana_config_writer.test.ts index 0580a35d909ea..005e280fcc744 100644 --- a/src/plugins/interactive_setup/server/kibana_config_writer.test.ts +++ b/src/plugins/interactive_setup/server/kibana_config_writer.test.ts @@ -183,8 +183,8 @@ describe('KibanaConfigWriter', () => { # This section was automatically generated during setup. elasticsearch.hosts: [some-host] - elasticsearch.password: password elasticsearch.username: username + elasticsearch.password: password elasticsearch.ssl.certificateAuthorities: [/data/ca_1234.crt] ", @@ -212,8 +212,8 @@ describe('KibanaConfigWriter', () => { # This section was automatically generated during setup. elasticsearch.hosts: [some-host] - elasticsearch.password: password elasticsearch.username: username + elasticsearch.password: password ", ], diff --git a/src/plugins/interactive_setup/server/kibana_config_writer.ts b/src/plugins/interactive_setup/server/kibana_config_writer.ts index ea7f776aad82f..949bc25ddd253 100644 --- a/src/plugins/interactive_setup/server/kibana_config_writer.ts +++ b/src/plugins/interactive_setup/server/kibana_config_writer.ts @@ -62,11 +62,11 @@ export class KibanaConfigWriter { public async writeConfig(params: WriteConfigParameters) { const caPath = path.join(this.dataDirectoryPath, `ca_${Date.now()}.crt`); const config: Record = { 'elasticsearch.hosts': [params.host] }; - if ('serviceAccountToken' in params) { + if ('serviceAccountToken' in params && params.serviceAccountToken) { config['elasticsearch.serviceAccountToken'] = params.serviceAccountToken.value; - } else if ('username' in params) { - config['elasticsearch.password'] = params.password; + } else if ('username' in params && params.username) { config['elasticsearch.username'] = params.username; + config['elasticsearch.password'] = params.password; } if (params.caCert) { config['elasticsearch.ssl.certificateAuthorities'] = [caPath]; diff --git a/test/interactive_setup_api_integration/manual_configuration_flow_without_tls.config.ts b/test/interactive_setup_api_integration/manual_configuration_flow_without_tls.config.ts index 5317026a1d8dc..16d98c00768c0 100644 --- a/test/interactive_setup_api_integration/manual_configuration_flow_without_tls.config.ts +++ b/test/interactive_setup_api_integration/manual_configuration_flow_without_tls.config.ts @@ -46,7 +46,6 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { .filter((arg: string) => !arg.startsWith('--elasticsearch.')), `--plugin-path=${testEndpointsPlugin}`, `--config=${tempKibanaYamlFile}`, - '--interactiveSetup.enabled=true', ], runOptions: { ...xPackAPITestsConfig.get('kbnTestServer.runOptions'), diff --git a/test/interactive_setup_functional/enrollment_token.config.ts b/test/interactive_setup_functional/enrollment_token.config.ts new file mode 100644 index 0000000000000..9c9f270ed0fc1 --- /dev/null +++ b/test/interactive_setup_functional/enrollment_token.config.ts @@ -0,0 +1,57 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import fs from 'fs/promises'; +import { join, resolve } from 'path'; + +import type { FtrConfigProviderContext } from '@kbn/test'; +import { getDataPath } from '@kbn/utils'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const manualConfigurationConfig = await readConfigFile( + require.resolve('./manual_configuration.config.ts') + ); + + const tempKibanaYamlFile = join(getDataPath(), `interactive_setup_kibana_${Date.now()}.yml`); + await fs.writeFile(tempKibanaYamlFile, ''); + + const caPath = resolve( + __dirname, + '../interactive_setup_api_integration/fixtures/elasticsearch.p12' + ); + + return { + ...manualConfigurationConfig.getAll(), + + testFiles: [require.resolve('./tests/enrollment_token')], + + junit: { + reportName: 'Interactive Setup Functional Tests (Enrollment token)', + }, + + esTestCluster: { + ...manualConfigurationConfig.get('esTestCluster'), + serverArgs: [ + ...manualConfigurationConfig.get('esTestCluster.serverArgs'), + 'xpack.security.enrollment.enabled=true', + `xpack.security.http.ssl.keystore.path=${caPath}`, + 'xpack.security.http.ssl.keystore.password=storepass', + ], + }, + + kbnTestServer: { + ...manualConfigurationConfig.get('kbnTestServer'), + serverArgs: [ + ...manualConfigurationConfig + .get('kbnTestServer.serverArgs') + .filter((arg: string) => !arg.startsWith('--config')), + `--config=${tempKibanaYamlFile}`, + ], + }, + }; +} diff --git a/test/interactive_setup_functional/manual_configuration.config.ts b/test/interactive_setup_functional/manual_configuration.config.ts new file mode 100644 index 0000000000000..6199e918c3608 --- /dev/null +++ b/test/interactive_setup_functional/manual_configuration.config.ts @@ -0,0 +1,55 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import fs from 'fs/promises'; +import { join } from 'path'; + +import type { FtrConfigProviderContext } from '@kbn/test'; +import { getDataPath } from '@kbn/utils'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const withoutTlsConfig = await readConfigFile( + require.resolve('./manual_configuration_without_tls.config.ts') + ); + + const tempKibanaYamlFile = join(getDataPath(), `interactive_setup_kibana_${Date.now()}.yml`); + await fs.writeFile(tempKibanaYamlFile, ''); + + return { + ...withoutTlsConfig.getAll(), + + testFiles: [require.resolve('./tests/manual_configuration')], + + servers: { + ...withoutTlsConfig.get('servers'), + elasticsearch: { + ...withoutTlsConfig.get('servers.elasticsearch'), + protocol: 'https', + }, + }, + + junit: { + reportName: 'Interactive Setup Functional Tests (Manual configuration)', + }, + + esTestCluster: { + ...withoutTlsConfig.get('esTestCluster'), + ssl: true, + }, + + kbnTestServer: { + ...withoutTlsConfig.get('kbnTestServer'), + serverArgs: [ + ...withoutTlsConfig + .get('kbnTestServer.serverArgs') + .filter((arg: string) => !arg.startsWith('--config')), + `--config=${tempKibanaYamlFile}`, + ], + }, + }; +} diff --git a/test/interactive_setup_functional/manual_configuration_without_security.config.ts b/test/interactive_setup_functional/manual_configuration_without_security.config.ts new file mode 100644 index 0000000000000..953b33d4e2077 --- /dev/null +++ b/test/interactive_setup_functional/manual_configuration_without_security.config.ts @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import fs from 'fs/promises'; +import { join, resolve } from 'path'; + +import type { FtrConfigProviderContext } from '@kbn/test'; +import { getDataPath } from '@kbn/utils'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile(require.resolve('../functional/config')); + + const testEndpointsPlugin = resolve( + __dirname, + '../interactive_setup_api_integration/fixtures/test_endpoints' + ); + + const tempKibanaYamlFile = join(getDataPath(), `interactive_setup_kibana_${Date.now()}.yml`); + await fs.writeFile(tempKibanaYamlFile, ''); + + return { + ...functionalConfig.getAll(), + + testFiles: [require.resolve('./tests/manual_configuration_without_security')], + + junit: { + reportName: 'Interactive Setup Functional Tests (Manual configuration without Security)', + }, + + security: { disableTestUser: true }, + + esTestCluster: { + ...functionalConfig.get('esTestCluster'), + serverArgs: [ + ...functionalConfig + .get('esTestCluster.serverArgs') + .filter((arg: string) => !arg.startsWith('xpack.security.')), + 'xpack.security.enabled=false', + ], + }, + + kbnTestServer: { + ...functionalConfig.get('kbnTestServer'), + serverArgs: [ + ...functionalConfig + .get('kbnTestServer.serverArgs') + .filter((arg: string) => !arg.startsWith('--elasticsearch.')), + `--plugin-path=${testEndpointsPlugin}`, + `--config=${tempKibanaYamlFile}`, + ], + runOptions: { + ...functionalConfig.get('kbnTestServer.runOptions'), + wait: /Kibana has not been configured/, + }, + }, + + uiSettings: {}, // UI settings can't be set during `preboot` stage + }; +} diff --git a/test/interactive_setup_functional/manual_configuration_without_tls.config.ts b/test/interactive_setup_functional/manual_configuration_without_tls.config.ts new file mode 100644 index 0000000000000..306e1128d5f8f --- /dev/null +++ b/test/interactive_setup_functional/manual_configuration_without_tls.config.ts @@ -0,0 +1,52 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import fs from 'fs/promises'; +import { join } from 'path'; + +import type { FtrConfigProviderContext } from '@kbn/test'; +import { getDataPath } from '@kbn/utils'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const withoutSecurityConfig = await readConfigFile( + require.resolve('./manual_configuration_without_security.config') + ); + + const tempKibanaYamlFile = join(getDataPath(), `interactive_setup_kibana_${Date.now()}.yml`); + await fs.writeFile(tempKibanaYamlFile, ''); + + return { + ...withoutSecurityConfig.getAll(), + + testFiles: [require.resolve('./tests/manual_configuration_without_tls')], + + junit: { + reportName: 'Interactive Setup Functional Tests (Manual configuration without TLS)', + }, + + esTestCluster: { + ...withoutSecurityConfig.get('esTestCluster'), + serverArgs: [ + ...withoutSecurityConfig + .get('esTestCluster.serverArgs') + .filter((arg: string) => !arg.startsWith('xpack.security.')), + 'xpack.security.enabled=true', + ], + }, + + kbnTestServer: { + ...withoutSecurityConfig.get('kbnTestServer'), + serverArgs: [ + ...withoutSecurityConfig + .get('kbnTestServer.serverArgs') + .filter((arg: string) => !arg.startsWith('--config')), + `--config=${tempKibanaYamlFile}`, + ], + }, + }; +} diff --git a/test/interactive_setup_functional/tests/enrollment_token.ts b/test/interactive_setup_functional/tests/enrollment_token.ts new file mode 100644 index 0000000000000..56311c9458cef --- /dev/null +++ b/test/interactive_setup_functional/tests/enrollment_token.ts @@ -0,0 +1,88 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { kibanaPackageJson } from '@kbn/utils'; + +import type { FtrProviderContext } from '../../functional/ftr_provider_context'; +import { getElasticsearchCaCertificate } from '../../interactive_setup_api_integration/fixtures/tls_tools'; + +export default function ({ getService }: FtrProviderContext) { + const browser = getService('browser'); + const find = getService('find'); + const supertest = getService('supertest'); + const deployment = getService('deployment'); + const es = getService('es'); + const config = getService('config'); + const retry = getService('retry'); + const log = getService('log'); + + describe('Interactive Setup Functional Tests (Enrollment token)', function () { + this.tags(['skipCloud', 'ciGroup2']); + + const elasticsearchConfig = config.get('servers.elasticsearch'); + let verificationCode: string; + let caFingerprint: string; + before(async function () { + verificationCode = (await supertest.get('/test_endpoints/verification_code').expect(200)).body + .verificationCode; + log.info(`Verification code: ${verificationCode}`); + + caFingerprint = ( + await getElasticsearchCaCertificate(elasticsearchConfig.hostname, elasticsearchConfig.port) + ).fingerprint256 + .replace(/:/g, '') + .toLowerCase(); + log.info(`Elasticsearch ca fingerprint: ${caFingerprint}`); + }); + + let enrollmentAPIKey: string; + beforeEach(async function () { + const apiResponse = await es.security.createApiKey({ body: { name: 'enrollment_api_key' } }); + enrollmentAPIKey = `${apiResponse.id}:${apiResponse.api_key}`; + log.info(`API key for enrollment token: ${enrollmentAPIKey}`); + }); + + afterEach(async function () { + await es.security.invalidateApiKey({ body: { name: 'enrollment_api_key' } }); + }); + + it('should configure Kibana successfully', async function () { + this.timeout(150_000); + + const enrollmentToken = btoa( + JSON.stringify({ + ver: kibanaPackageJson.version, + adr: [`${elasticsearchConfig.hostname}:${elasticsearchConfig.port}`], + fgr: caFingerprint, + key: enrollmentAPIKey, + }) + ); + + await browser.get(`${deployment.getHostPort()}?code=${verificationCode}`); + const initialUrl = await browser.getCurrentUrl(); + log.info(`Opened interactive setup: ${initialUrl}`); + + const tokenField = await find.byName('token'); + await tokenField.clearValueWithKeyboard(); + await tokenField.type(enrollmentToken); + log.info(`Entered enrollment token: ${enrollmentToken}`); + + await find.clickByButtonText('Configure Elastic'); + log.info('Submitted form'); + + await retry.waitForWithTimeout('redirect to login page', 120_000, async () => { + log.debug(`Current URL: ${await browser.getCurrentUrl()}, initial URL: ${initialUrl}`); + return (await browser.getCurrentUrl()) !== initialUrl; + }); + }); + }); +} + +function btoa(str: string) { + return Buffer.from(str, 'binary').toString('base64'); +} diff --git a/test/interactive_setup_functional/tests/manual_configuration.ts b/test/interactive_setup_functional/tests/manual_configuration.ts new file mode 100644 index 0000000000000..3c7c5d9c08d76 --- /dev/null +++ b/test/interactive_setup_functional/tests/manual_configuration.ts @@ -0,0 +1,67 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { getUrl, kibanaServerTestUser } from '@kbn/test'; +import type { FtrProviderContext } from '../../functional/ftr_provider_context'; + +export default function ({ getService }: FtrProviderContext) { + const browser = getService('browser'); + const find = getService('find'); + const supertest = getService('supertest'); + const deployment = getService('deployment'); + const config = getService('config'); + const retry = getService('retry'); + const log = getService('log'); + + describe('Interactive Setup Functional Tests (Manual configuration)', function () { + this.tags(['skipCloud', 'ciGroup2']); + + let verificationCode: string; + before(async function () { + verificationCode = (await supertest.get('/test_endpoints/verification_code').expect(200)).body + .verificationCode; + }); + + it('should configure Kibana successfully', async function () { + this.timeout(150_000); + + await browser.get(`${deployment.getHostPort()}?code=${verificationCode}`); + const url = await browser.getCurrentUrl(); + + await find.clickByButtonText('Configure manually'); + + const elasticsearchHost = getUrl.baseUrl(config.get('servers.elasticsearch')); + const hostField = await find.byName('host'); + await hostField.clearValueWithKeyboard(); + await hostField.type(elasticsearchHost); + + await find.clickByButtonText('Check address'); + + const usernameField = await find.byName('username'); + await usernameField.clearValueWithKeyboard(); + await usernameField.type(kibanaServerTestUser.username); + + const passwordField = await find.byName('password'); + await passwordField.clearValueWithKeyboard(); + await passwordField.type(kibanaServerTestUser.password); + + const caCertField = await find.byCssSelector('input[type="checkbox"]'); + if (!(await caCertField.isSelected())) { + const id = await caCertField.getAttribute('id'); + await find.clickByCssSelector(`label[for="${id}"]`); + } + + await find.clickByButtonText('Configure Elastic'); + + await retry.waitForWithTimeout('redirect to login page', 120_000, async () => { + log.debug(`Current URL: ${await browser.getCurrentUrl()}, initial URL: ${url}`); + return (await browser.getCurrentUrl()) !== url; + }); + }); + }); +} diff --git a/test/interactive_setup_functional/tests/manual_configuration_without_security.ts b/test/interactive_setup_functional/tests/manual_configuration_without_security.ts new file mode 100644 index 0000000000000..2111dc3cce7e7 --- /dev/null +++ b/test/interactive_setup_functional/tests/manual_configuration_without_security.ts @@ -0,0 +1,53 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { getUrl } from '@kbn/test'; +import type { FtrProviderContext } from '../../functional/ftr_provider_context'; + +export default function ({ getService, getPageObject }: FtrProviderContext) { + const browser = getService('browser'); + const find = getService('find'); + const supertest = getService('supertest'); + const deployment = getService('deployment'); + const config = getService('config'); + const retry = getService('retry'); + const log = getService('log'); + + describe('Interactive Setup Functional Tests (Manual configuration without Security)', function () { + this.tags(['skipCloud', 'ciGroup2']); + + let verificationCode: string; + before(async function () { + verificationCode = (await supertest.get('/test_endpoints/verification_code').expect(200)).body + .verificationCode; + }); + + it('should configure Kibana successfully', async function () { + this.timeout(150_000); + + await browser.get(`${deployment.getHostPort()}?code=${verificationCode}`); + const url = await browser.getCurrentUrl(); + + await find.clickByButtonText('Configure manually'); + + const elasticsearchHost = getUrl.baseUrl(config.get('servers.elasticsearch')); + const hostField = await find.byName('host'); + await hostField.clearValueWithKeyboard(); + await hostField.type(elasticsearchHost); + + await find.clickByButtonText('Check address'); + + await find.clickByButtonText('Configure Elastic'); + + await retry.waitForWithTimeout('redirect to home page', 120_000, async () => { + log.debug(`Current URL: ${await browser.getCurrentUrl()}, initial URL: ${url}`); + return (await browser.getCurrentUrl()) !== url; + }); + }); + }); +} diff --git a/test/interactive_setup_functional/tests/manual_configuration_without_tls.ts b/test/interactive_setup_functional/tests/manual_configuration_without_tls.ts new file mode 100644 index 0000000000000..b8e391dc6f93f --- /dev/null +++ b/test/interactive_setup_functional/tests/manual_configuration_without_tls.ts @@ -0,0 +1,61 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { getUrl, kibanaServerTestUser } from '@kbn/test'; +import type { FtrProviderContext } from '../../functional/ftr_provider_context'; + +export default function ({ getService }: FtrProviderContext) { + const browser = getService('browser'); + const find = getService('find'); + const supertest = getService('supertest'); + const deployment = getService('deployment'); + const config = getService('config'); + const retry = getService('retry'); + const log = getService('log'); + + describe('Interactive Setup Functional Tests (Manual configuration without TLS)', function () { + this.tags(['skipCloud', 'ciGroup2']); + + let verificationCode: string; + before(async function () { + verificationCode = (await supertest.get('/test_endpoints/verification_code').expect(200)).body + .verificationCode; + }); + + it('should configure Kibana successfully', async function () { + this.timeout(150_000); + + await browser.get(`${deployment.getHostPort()}?code=${verificationCode}`); + const url = await browser.getCurrentUrl(); + + await find.clickByButtonText('Configure manually'); + + const elasticsearchHost = getUrl.baseUrl(config.get('servers.elasticsearch')); + const hostField = await find.byName('host'); + await hostField.clearValueWithKeyboard(); + await hostField.type(elasticsearchHost); + + await find.clickByButtonText('Check address'); + + const usernameField = await find.byName('username'); + await usernameField.clearValueWithKeyboard(); + await usernameField.type(kibanaServerTestUser.username); + + const passwordField = await find.byName('password'); + await passwordField.clearValueWithKeyboard(); + await passwordField.type(kibanaServerTestUser.password); + + await find.clickByButtonText('Configure Elastic'); + + await retry.waitForWithTimeout('redirect to login page', 120_000, async () => { + log.debug(`Current URL: ${await browser.getCurrentUrl()}, initial URL: ${url}`); + return (await browser.getCurrentUrl()) !== url; + }); + }); + }); +}